From 02aa624f0af1d685cced5c8144c557f2d3cbff85 Mon Sep 17 00:00:00 2001 From: "Jules Sam. Randolph" Date: Wed, 26 May 2021 15:54:58 -0300 Subject: [PATCH] refactor: simplify types / suggest module augmentation for extensibility BREAKING CHANGE: A few TypeScript types names have been changed and some type parameters have been removed for simplicity. Use module augmentation if you need to specify `RenderersProps` or `PropsFromParent`. --- .../src/RenderHTMLConfigProvider.tsx | 12 +- packages/render-html/src/RenderHTMLDebug.tsx | 8 +- packages/render-html/src/TBlockRenderer.tsx | 3 +- packages/render-html/src/TPhrasingRenderer.ts | 3 +- packages/render-html/src/TTextRenderer.ts | 7 +- .../__tests__/component.render-html.test.tsx | 8 +- packages/render-html/src/__tests__/utils.tsx | 4 +- .../src/context/RenderersPropsProvider.tsx | 2 +- .../src/context/SharedPropsProvider.tsx | 4 +- .../render-html/src/elements/AElement.tsx | 4 +- .../render-html/src/elements/ListElement.tsx | 4 +- .../src/hooks/useAssembledCommonProps.ts | 14 +- .../src/hooks/useInternalRenderer.ts | 7 +- packages/render-html/src/internal-types.ts | 15 +- .../render-html/src/render/RenderRegistry.ts | 8 +- .../render-html/src/render/render-types.tsx | 22 +-- .../render-html/src/renderers/ARenderer.tsx | 6 +- .../render-html/src/renderers/IMGRenderer.tsx | 4 +- .../render-html/src/renderers/OLRenderer.tsx | 4 +- .../render-html/src/renderers/ULRenderer.tsx | 4 +- packages/render-html/src/shared-types.ts | 165 ++++++++++-------- 21 files changed, 169 insertions(+), 139 deletions(-) diff --git a/packages/render-html/src/RenderHTMLConfigProvider.tsx b/packages/render-html/src/RenderHTMLConfigProvider.tsx index 8c2f95fab..bfb321837 100644 --- a/packages/render-html/src/RenderHTMLConfigProvider.tsx +++ b/packages/render-html/src/RenderHTMLConfigProvider.tsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import RenderersPropsProvider from './context/RenderersPropsProvider'; import SharedPropsProvider from './context/SharedPropsProvider'; import TChildrenRenderersContext from './context/TChildrenRendererContext'; -import { RenderHTMLConfig, RenderersPropsBase } from './shared-types'; +import { RenderHTMLConfig } from './shared-types'; import TNodeChildrenRenderer from './TNodeChildrenRenderer'; import TChildrenRenderer from './TChildrenRenderer'; import sourceLoaderContext from './context/sourceLoaderContext'; @@ -34,9 +34,13 @@ export const renderHTMLConfigPropTypes: RenderHTMLConfigPropTypes = { renderers: PropTypes.object }; -export default function RenderHTMLConfigProvider< - P extends RenderersPropsBase = RenderersPropsBase ->(props: PropsWithChildren>): ReactElement { +/** + * A component to provide configuration for {@link RenderHTMLSource} + * descendants, to be used in conjunction with {@link TRenderEngineProvider}. + */ +export default function RenderHTMLConfigProvider( + props: PropsWithChildren +): ReactElement { const { remoteErrorView, remoteLoadingView, diff --git a/packages/render-html/src/RenderHTMLDebug.tsx b/packages/render-html/src/RenderHTMLDebug.tsx index 50936e65d..20ec9482a 100644 --- a/packages/render-html/src/RenderHTMLDebug.tsx +++ b/packages/render-html/src/RenderHTMLDebug.tsx @@ -1,10 +1,10 @@ import React, { Fragment, PropsWithChildren } from 'react'; import debugMessage from './debugMessages'; -import { RenderersPropsBase, RenderHTMLProps } from './shared-types'; +import { RenderHTMLProps } from './shared-types'; -const RenderHTMLDebug = function RenderHTMLDebug< - P extends RenderersPropsBase = RenderersPropsBase ->(props: PropsWithChildren>) { +const RenderHTMLDebug = function RenderHTMLDebug( + props: PropsWithChildren +) { if (__DEV__) { if (typeof props.contentWidth !== 'number') { console.warn(debugMessage.contentWidth); diff --git a/packages/render-html/src/TBlockRenderer.tsx b/packages/render-html/src/TBlockRenderer.tsx index a46c944e1..46c499614 100644 --- a/packages/render-html/src/TBlockRenderer.tsx +++ b/packages/render-html/src/TBlockRenderer.tsx @@ -2,7 +2,8 @@ import React from 'react'; import { View } from 'react-native'; import { TBlock } from '@native-html/transient-render-engine'; import { useTNodeChildrenRenderer } from './context/TChildrenRendererContext'; -import { TDefaultRenderer, TNodeSubRendererProps } from './shared-types'; +import { TDefaultRenderer } from './shared-types'; +import { TNodeSubRendererProps } from './internal-types'; import GenericPressable from './GenericPressable'; import useAssembledCommonProps from './hooks/useAssembledCommonProps'; diff --git a/packages/render-html/src/TPhrasingRenderer.ts b/packages/render-html/src/TPhrasingRenderer.ts index f0be1bead..847c14b4a 100644 --- a/packages/render-html/src/TPhrasingRenderer.ts +++ b/packages/render-html/src/TPhrasingRenderer.ts @@ -1,7 +1,8 @@ import React from 'react'; import { TPhrasing } from '@native-html/transient-render-engine'; import { useTNodeChildrenRenderer } from './context/TChildrenRendererContext'; -import { TDefaultRenderer, TNodeSubRendererProps } from './shared-types'; +import { TDefaultRenderer } from './shared-types'; +import { TNodeSubRendererProps } from './internal-types'; import useAssembledCommonProps from './hooks/useAssembledCommonProps'; import TDefaultTextualRenderer from './TDefaultTextualRenderer'; diff --git a/packages/render-html/src/TTextRenderer.ts b/packages/render-html/src/TTextRenderer.ts index 242541012..3c0348a2e 100644 --- a/packages/render-html/src/TTextRenderer.ts +++ b/packages/render-html/src/TTextRenderer.ts @@ -1,10 +1,7 @@ import React from 'react'; import { TText } from '@native-html/transient-render-engine'; -import { - TDefaultRenderer, - TDefaultRendererProps, - TNodeSubRendererProps -} from './shared-types'; +import { TDefaultRenderer, TDefaultRendererProps } from './shared-types'; +import { TNodeSubRendererProps } from './internal-types'; import { useInternalTextRenderer } from './context/RenderRegistryProvider'; import useAssembledCommonProps from './hooks/useAssembledCommonProps'; import TDefaultTextualRenderer from './TDefaultTextualRenderer'; diff --git a/packages/render-html/src/__tests__/component.render-html.test.tsx b/packages/render-html/src/__tests__/component.render-html.test.tsx index fd4231b42..e36838fc5 100644 --- a/packages/render-html/src/__tests__/component.render-html.test.tsx +++ b/packages/render-html/src/__tests__/component.render-html.test.tsx @@ -218,7 +218,9 @@ describe('RenderHTML', () => { const SpanRenderer: CustomTextualRenderer = ({ TDefaultRenderer, ...props - }) => ; + }) => ( + + ); const EmRenderer: CustomTextualRenderer = ({ TDefaultRenderer, ...props @@ -240,7 +242,9 @@ describe('RenderHTML', () => { const SpanRenderer: CustomTextualRenderer = ({ TDefaultRenderer, ...props - }) => ; + }) => ( + + ); const EmRenderer: CustomTextualRenderer = ({ TDefaultRenderer, ...props diff --git a/packages/render-html/src/__tests__/utils.tsx b/packages/render-html/src/__tests__/utils.tsx index d07dc7e10..d83225563 100644 --- a/packages/render-html/src/__tests__/utils.tsx +++ b/packages/render-html/src/__tests__/utils.tsx @@ -25,7 +25,7 @@ export function expectTranslatedInlineCSSRuleTo({ cssInlineRules: string; test: (v: any) => void; render: typeof renderTestingLib; - extraProps?: Partial>; + extraProps?: Partial; }) { const { getByText } = render( >; + extraProps?: Partial; }) { expectTranslatedInlineCSSRuleTo({ cssInlineRules, diff --git a/packages/render-html/src/context/RenderersPropsProvider.tsx b/packages/render-html/src/context/RenderersPropsProvider.tsx index 636b2ddaa..1e96e59a3 100644 --- a/packages/render-html/src/context/RenderersPropsProvider.tsx +++ b/packages/render-html/src/context/RenderersPropsProvider.tsx @@ -29,7 +29,7 @@ export function useRendererProps< * @internal */ export default function RenderersPropsProvider( - props: PropsWithChildren> + props: PropsWithChildren ) { const mergedRenderersProps = useMemo( () => mergeDeepRight(defaultRendererProps, props.renderersProps || {}), diff --git a/packages/render-html/src/context/SharedPropsProvider.tsx b/packages/render-html/src/context/SharedPropsProvider.tsx index 9084a844a..16f356c4b 100644 --- a/packages/render-html/src/context/SharedPropsProvider.tsx +++ b/packages/render-html/src/context/SharedPropsProvider.tsx @@ -1,7 +1,7 @@ import React, { PropsWithChildren, useCallback, useMemo } from 'react'; import defaultListStyleSpecs from '../elements/defaultListStyleSpecs'; import selectSharedProps from '../helpers/selectSharedProps'; -import { RenderHTMLSharedProps, TRendererBaseProps } from '../shared-types'; +import { RenderHTMLSharedProps, RendererBaseProps } from '../shared-types'; import defaultSharedProps from './defaultSharedProps'; const SharedPropsContext = React.createContext>( @@ -23,7 +23,7 @@ export function useSharedProps() { * @internal */ export function useDefaultContainerProps(): Pick< - TRendererBaseProps, + RendererBaseProps, 'viewProps' | 'textProps' > { const sharedProps = useSharedProps(); diff --git a/packages/render-html/src/elements/AElement.tsx b/packages/render-html/src/elements/AElement.tsx index baa5e128e..444787838 100644 --- a/packages/render-html/src/elements/AElement.tsx +++ b/packages/render-html/src/elements/AElement.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { TBlock, TPhrasing, TText } from '@native-html/transient-render-engine'; -import { DefaultTagRendererProps } from '../shared-types'; +import { InternalRendererProps } from '../shared-types'; export default function AElement({ TDefaultRenderer, ...props -}: DefaultTagRendererProps) { +}: InternalRendererProps) { return React.createElement(TDefaultRenderer, props); } diff --git a/packages/render-html/src/elements/ListElement.tsx b/packages/render-html/src/elements/ListElement.tsx index 1f14e01d5..e7e0de23e 100644 --- a/packages/render-html/src/elements/ListElement.tsx +++ b/packages/render-html/src/elements/ListElement.tsx @@ -9,7 +9,7 @@ import { } from '@jsamr/react-native-li'; import type { DefaultSupportedListStyleType, - DefaultTagRendererProps, + InternalRendererProps, ListElementConfig, ListStyleSpec, TChildProps, @@ -20,7 +20,7 @@ import { DEFAULT_TEXT_COLOR } from '../constants'; import pick from 'ramda/src/pick'; export interface ListElementProps - extends DefaultTagRendererProps, + extends InternalRendererProps, ListElementConfig { listType: T; listStyleSpecs: Record; diff --git a/packages/render-html/src/hooks/useAssembledCommonProps.ts b/packages/render-html/src/hooks/useAssembledCommonProps.ts index 2b228a6fd..37844cadb 100644 --- a/packages/render-html/src/hooks/useAssembledCommonProps.ts +++ b/packages/render-html/src/hooks/useAssembledCommonProps.ts @@ -1,11 +1,11 @@ import { TNode } from '@native-html/transient-render-engine'; import { - CustomTagRenderer, - CustomTagRendererProps, + CustomRenderer, + CustomRendererProps, TDefaultRenderer, - TDefaultRendererProps, - TNodeSubRendererProps + TDefaultRendererProps } from '../shared-types'; +import { TNodeSubRendererProps } from '../internal-types'; import mergeCollapsedMargins from '../helpers/mergeCollapsedMargins'; import { useRendererConfig } from '../context/RenderRegistryProvider'; import { useDefaultContainerProps } from '../context/SharedPropsProvider'; @@ -17,12 +17,12 @@ export default function useAssembledCommonProps( { tnode, key, propsFromParent, sharedProps }: TNodeSubRendererProps, TDefault: TDefaultRenderer ): { - assembledProps: CustomTagRendererProps & TDefaultRendererProps; - Renderer: CustomTagRenderer; + assembledProps: CustomRendererProps & TDefaultRendererProps; + Renderer: CustomRenderer; } { const { Default, Custom } = useRendererConfig(tnode); const containerProps = useDefaultContainerProps(); - const assembledProps: CustomTagRendererProps & TDefaultRendererProps = { + const assembledProps: CustomRendererProps & TDefaultRendererProps = { key, tnode, propsFromParent, diff --git a/packages/render-html/src/hooks/useInternalRenderer.ts b/packages/render-html/src/hooks/useInternalRenderer.ts index 724d64a4f..094431b9c 100644 --- a/packages/render-html/src/hooks/useInternalRenderer.ts +++ b/packages/render-html/src/hooks/useInternalRenderer.ts @@ -8,10 +8,7 @@ import { useAElementProps } from '../renderers/ARenderer'; import { useIMGElementProps } from '../renderers/IMGRenderer'; import { useOLElementProps } from '../renderers/OLRenderer'; import { useULElementProps } from '../renderers/ULRenderer'; -import { - DefaultTagRendererProps, - TDefaultRendererProps -} from '../shared-types'; +import { InternalRendererProps, TDefaultRendererProps } from '../shared-types'; const specialRenderersConfig = { img: { @@ -60,7 +57,7 @@ export interface InternalRendererConfig

{ */ export default function useInternalRenderer( tagName: T, - props: DefaultTagRendererProps + props: InternalRendererProps ): T extends InternalSpecialRenderedTag ? InternalRendererConfig> : InternalRendererConfig> { diff --git a/packages/render-html/src/internal-types.ts b/packages/render-html/src/internal-types.ts index b8262484d..cddefdfd4 100644 --- a/packages/render-html/src/internal-types.ts +++ b/packages/render-html/src/internal-types.ts @@ -1,5 +1,10 @@ +import { TNode } from '@native-html/transient-render-engine'; import { DOMDocument, DOMElement } from '@native-html/transient-render-engine'; -import { RenderHTMLProps } from './shared-types'; +import { + RenderHTMLProps, + TNodeRendererProps, + RenderHTMLSharedProps +} from './shared-types'; export type SourceLoaderProps = Pick< RenderHTMLProps, @@ -15,3 +20,11 @@ export type TTreeEvents = Pick< RenderHTMLProps, 'onTTreeChange' | 'onDocumentMetadataLoaded' >; + +export interface TNodeSubRendererProps + extends TNodeRendererProps { + /** + * Props shared across the whole render tree. + */ + sharedProps: Required; +} diff --git a/packages/render-html/src/render/RenderRegistry.ts b/packages/render-html/src/render/RenderRegistry.ts index d0e48983b..6e4585f0c 100644 --- a/packages/render-html/src/render/RenderRegistry.ts +++ b/packages/render-html/src/render/RenderRegistry.ts @@ -1,11 +1,11 @@ import { TNode } from '@native-html/transient-render-engine'; import { ComponentType } from 'react'; -import { CustomTagRendererProps } from '..'; +import { CustomRendererProps } from '..'; import lookupRecord from '../helpers/lookupRecord'; import BRRenderer from '../renderers/BRRenderer'; import WBRRenderer from '../renderers/WBRRenderer'; import { - CustomTagRenderer, + CustomRenderer, HTMLElementModelRecord, InternalRenderer } from '../shared-types'; @@ -22,7 +22,7 @@ const internalTextRenderers: Record = { export interface RendererConfig { Default: InternalRenderer | null; - Custom: CustomTagRenderer | null; + Custom: CustomRenderer | null; } export default class RenderRegistry { @@ -63,7 +63,7 @@ export default class RenderRegistry { private getCustomRendererForTNode( tnode: T - ): ComponentType> | null { + ): ComponentType> | null { if (tnode.tagName! in this.customRenderers) { const renderer = this.customRenderers[tnode.tagName!]; if (__DEV__) { diff --git a/packages/render-html/src/render/render-types.tsx b/packages/render-html/src/render/render-types.tsx index 34e25e334..8ef29f085 100644 --- a/packages/render-html/src/render/render-types.tsx +++ b/packages/render-html/src/render/render-types.tsx @@ -1,10 +1,6 @@ import { TBlock, TPhrasing, TText } from '@native-html/transient-render-engine'; import { ComponentType } from 'react'; -import { - CustomTagRenderer, - InternalRenderer, - PropsFromParent -} from '../shared-types'; +import { CustomRenderer, InternalRenderer } from '../shared-types'; /** * Special internal renderers for non-printable text (wbr, br). @@ -35,30 +31,22 @@ export type InternalTextualRenderer = InternalRenderer; /** * Block renderers can only render tnodes of type TBlock. */ -export type CustomBlockRenderer< - P extends PropsFromParent = PropsFromParent -> = CustomTagRenderer; +export type CustomBlockRenderer = CustomRenderer; /** * Textual renderers can render tnodes of type TText or TPhrasing. */ -export type CustomTextualRenderer< - P extends PropsFromParent = PropsFromParent -> = CustomTagRenderer; +export type CustomTextualRenderer = CustomRenderer; /** * Mixed renderers can can render tnodes of type TText, TPhrasing or TBlock. */ -export type CustomMixedRenderer< - P extends PropsFromParent = PropsFromParent -> = CustomTagRenderer; +export type CustomMixedRenderer = CustomRenderer; /** * A record of custom renderers. */ export type CustomTagRendererRecord = Record< string, - | CustomBlockRenderer - | CustomTextualRenderer - | CustomMixedRenderer + CustomBlockRenderer | CustomTextualRenderer | CustomMixedRenderer >; diff --git a/packages/render-html/src/renderers/ARenderer.tsx b/packages/render-html/src/renderers/ARenderer.tsx index f23e6771e..c37a45710 100644 --- a/packages/render-html/src/renderers/ARenderer.tsx +++ b/packages/render-html/src/renderers/ARenderer.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { InternalMixedRenderer } from '../render/render-types'; import { TNode, DocumentContext } from '@native-html/transient-render-engine'; -import { DefaultTagRendererProps, RenderersPropsBase } from '../shared-types'; +import { InternalRendererProps, RenderersPropsBase } from '../shared-types'; import { AccessibilityProps, GestureResponderEvent } from 'react-native'; import AElement from '../elements/AElement'; import useNormalizedUrl from '../hooks/useNormalizedUrl'; @@ -32,8 +32,8 @@ function useAnchorOnLinkPress( } export function useAElementProps( - props: DefaultTagRendererProps -): DefaultTagRendererProps { + props: InternalRendererProps +): InternalRendererProps { const { tnode } = props; const { onPress } = useRendererProps('a'); const syntheticAnchorOnLinkPress = useAnchorOnLinkPress(tnode, onPress); diff --git a/packages/render-html/src/renderers/IMGRenderer.tsx b/packages/render-html/src/renderers/IMGRenderer.tsx index 15fcd38c3..eef07866a 100644 --- a/packages/render-html/src/renderers/IMGRenderer.tsx +++ b/packages/render-html/src/renderers/IMGRenderer.tsx @@ -4,13 +4,13 @@ import IMGElement, { IMGElementProps } from '../elements/IMGElement'; import { InternalBlockRenderer } from '../render/render-types'; import { useComputeMaxWidthForTag } from '../context/SharedPropsProvider'; import { ImageStyle } from 'react-native'; -import { DefaultTagRendererProps } from '../shared-types'; +import { InternalRendererProps } from '../shared-types'; import useNormalizedUrl from '../hooks/useNormalizedUrl'; import { useRendererProps } from '../context/RenderersPropsProvider'; import useContentWidth from '../hooks/useContentWidth'; export function useIMGElementProps( - props: DefaultTagRendererProps + props: InternalRendererProps ): IMGElementProps & ClassAttributes { const { style, tnode, onPress, key } = props; const contentWidth = useContentWidth(); diff --git a/packages/render-html/src/renderers/OLRenderer.tsx b/packages/render-html/src/renderers/OLRenderer.tsx index 383bd893f..aecbda02a 100644 --- a/packages/render-html/src/renderers/OLRenderer.tsx +++ b/packages/render-html/src/renderers/OLRenderer.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { TBlock } from '@native-html/transient-render-engine'; import { InternalBlockRenderer } from '../render/render-types'; import { - DefaultTagRendererProps, + InternalRendererProps, DefaultSupportedListStyleType } from '../shared-types'; import OLElement, { OLElementProps } from '../elements/OLElement'; @@ -22,7 +22,7 @@ function getFallbackListStyleTypeFromNestLevel( } export function useOLElementProps( - props: DefaultTagRendererProps + props: InternalRendererProps ): OLElementProps { const listStyleSpecs = props.sharedProps.customListStyleSpecs; const config = useRendererProps('ol'); diff --git a/packages/render-html/src/renderers/ULRenderer.tsx b/packages/render-html/src/renderers/ULRenderer.tsx index a807aa0c2..95d3fb61e 100644 --- a/packages/render-html/src/renderers/ULRenderer.tsx +++ b/packages/render-html/src/renderers/ULRenderer.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { InternalBlockRenderer } from '../render/render-types'; import { - DefaultTagRendererProps, + InternalRendererProps, DefaultSupportedListStyleType } from '../shared-types'; import { TBlock } from '@native-html/transient-render-engine'; @@ -22,7 +22,7 @@ function getFallbackListStyleTypeFromNestLevel( } export function useULElementProps( - props: DefaultTagRendererProps + props: InternalRendererProps ): ULElementProps { const listStyleSpecs = props.sharedProps.customListStyleSpecs; const config = useRendererProps('ul'); diff --git a/packages/render-html/src/shared-types.ts b/packages/render-html/src/shared-types.ts index 4e3270ac7..cff4ca454 100644 --- a/packages/render-html/src/shared-types.ts +++ b/packages/render-html/src/shared-types.ts @@ -26,7 +26,9 @@ import type { TRenderEngineOptions, DOMNodeWithChildren, DOMElement, - DOMDocument + DOMDocument, + NativeTextStyles, + NativeBlockStyles } from '@native-html/transient-render-engine'; import type { CounterStyleRenderer } from '@jsamr/counter-style'; import type { ComponentType, ReactElement, ReactNode } from 'react'; @@ -162,17 +164,30 @@ export interface RenderersPropsBase extends Record { * * @public */ -export interface RenderHTMLPassedProps< - RendererProps extends RenderersPropsBase = RenderersPropsBase -> { +export interface RenderHTMLPassedProps { /** * Props to use in custom renderers with `useRendererProps`. * + * **Typescript users**: If you need to add fields to the {@link RenderersPropsBase} interface, + * you should use module augmentation: + * + * ```ts + * import { RenderersPropsBase } from 'react-native-render-html'; + * + * declare module 'react-native-render-html' { + * interface RenderersPropsBase { + * div?: { + * customProp: boolean; + * }; + * } + * } + * ``` + * * @remarks * - When you use the hook, you'll get this object deep-merged with default renderers props. * - Changes to this prop will cause a react tree update. Always memoize it. */ - renderersProps?: Partial; + renderersProps?: Partial; } /** @@ -574,10 +589,9 @@ export type HTMLSource = HTMLSourceInline | HTMLSourceDom | HTMLSourceUri; * * @public */ -export interface RenderHTMLConfig< - P extends RenderersPropsBase = RenderersPropsBase -> extends RenderHTMLSharedProps, - RenderHTMLPassedProps

{ +export interface RenderHTMLConfig + extends RenderHTMLSharedProps, + RenderHTMLPassedProps { /** * Your custom renderers. */ @@ -629,9 +643,8 @@ export interface RenderHTMLSourceProps { * * @public */ -export interface RenderHTMLProps< - P extends RenderersPropsBase = RenderersPropsBase -> extends RenderHTMLConfig

, +export interface RenderHTMLProps + extends RenderHTMLConfig, RenderHTMLSourceProps, TransientRenderEngineConfig {} @@ -649,10 +662,23 @@ export interface FallbackFontsDefinitions { /** * Props passed from parents to children. * + * **Typescript users**: If you need to customize this type, use module + * augmentation: + * + * ```ts + * import { RenderersPropsBase } from 'react-native-render-html'; + * + * declare module 'react-native-render-html' { + * interface PropsFromParent { + * customProp?: boolean; + * } + * } + * ``` + * * @remarks Anonymous nodes will pass those props from their parents to * children. */ -export interface PropsFromParent extends Record { +export interface PropsFromParent { collapsedMarginTop: number | null; } @@ -698,29 +724,33 @@ export interface TNodeChildrenRendererProps extends TChildrenBaseProps { tnode: TNode; } -export interface TNodeRendererProps< - T extends TNode, - P extends PropsFromParent = PropsFromParent -> { +/** + * Props for {@link TNodeRenderer} component. + * + * @typeParam T - The concrete type of {@link TNode}. + */ +export interface TNodeRendererProps { + /** + * The {@link TNode} to render. + */ tnode: T; + /** + * The key that must be passed to the root of the returned element. + */ key?: string | number; - propsFromParent: P; -} - -export interface TNodeSubRendererProps< - T extends TNode, - P extends PropsFromParent = PropsFromParent -> extends TNodeRendererProps { /** - * Props shared across the whole render tree. + * Props passed by direct parents. */ - sharedProps: Required; + propsFromParent: PropsFromParent; } -export interface TRendererBaseProps< - T extends TNode, - P extends PropsFromParent = PropsFromParent -> extends TNodeRendererProps { +/** + * Abstract interface for renderers. + * + * @typeParam T - The concrete type of {@link TNode}. + */ +export interface RendererBaseProps + extends TNodeRendererProps { /** * Any default renderer should be able to handle press. */ @@ -742,23 +772,20 @@ export interface TRendererBaseProps< /** * Props for {@link TDefaultRenderer}. * + * @typeParam T - The concrete type of {@link TNode}. * @public */ -export interface TDefaultRendererProps< - T extends TNode, - P extends PropsFromParent = PropsFromParent -> extends TRendererBaseProps { +export interface TDefaultRendererProps + extends RendererBaseProps { /** * When children is present, renderChildren will not be invoked. */ children?: ReactNode; /** - * The style for this renderer will depend on the type of tnode. + * The style for this renderer will depend on the type of {@link TNode}. * You can check if a node is textual with `props.type === 'text'`. */ - style: T extends TText - ? StyleProp - : T extends TPhrasing + style: T extends TText | TPhrasing ? StyleProp : StyleProp; /** @@ -769,22 +796,23 @@ export interface TDefaultRendererProps< } /** + * Props for {@link InternalRenderer} components. + * + * @typeParam T - The concrete type of {@link TNode}. * @public */ -export interface DefaultTagRendererProps< - T extends TNode, - P extends PropsFromParent = PropsFromParent -> extends TRendererBaseProps { +export interface InternalRendererProps + extends RendererBaseProps { /** - * Styles extracted with tnode.getNativeStyles + * Styles extracted with {@link TNode.getNativeStyles}. */ - style: ReturnType; + style: T extends TText | TPhrasing ? NativeTextStyles : NativeBlockStyles; /** * Props shared across the whole render tree. */ sharedProps: Required; /** - * Default renderer for this tnode. + * Default renderer for this {@link TNode}. */ TDefaultRenderer: TDefaultRenderer; } @@ -792,65 +820,62 @@ export interface DefaultTagRendererProps< /** * Props for custom renderers, such as provided in the `renderers` prop. * + * @typeParam T - The concrete type of {@link TNode}. * @public */ -export interface CustomTagRendererProps< - T extends TNode, - P extends PropsFromParent = PropsFromParent -> extends DefaultTagRendererProps { +export interface CustomRendererProps + extends InternalRendererProps { /** * Internal renderer for this _tagName_, not to be confused with - * {@link TDefaultRenderer}, which is the fallback renderer for any _tnode_. + * {@link TDefaultRenderer}, which is the fallback renderer for any {@link TNode}. * * @remarks For example, when rendering `img` tags, `TDefaultRenderer` and * `InternalRenderer` won't be equal. * - * When there is no default tag renderer for this tag, this prop will fallback - * to the `TDefaultRenderer`. + * When there is no internal renderer for this tag, this prop will fallback + * to `TDefaultRenderer`. */ InternalRenderer: InternalRenderer; } /** * Default renderer for any {@link TNode}. The renderer behavior will only - * change by the {@link TNodeType | type} of the {@link TNode}. + * change given the {@link TNodeType | type} of the {@link TNode}. * + * @typeParam T - The concrete type of {@link TNode}. * @public */ -export type TDefaultRenderer< - T extends TNode, - P extends PropsFromParent = PropsFromParent -> = React.ComponentType>; +export type TDefaultRenderer = React.ComponentType< + TDefaultRendererProps +>; /** - * An "internal renderer" is an internal custom renderer, adding custom + * An "internal renderer" is an internal custom renderer, adding specific * features to the fallback `TDefaultRenderer`. For example, `` tags will * be rendered via an internal renderer, while `

` will fallback to a * {@link TDefaultRenderer}. * * @public * - * @typeParam T - The concrete type of {@link TNode} for this renderer. - * @typeParam P - The type for props from parent. + * @typeParam T - The concrete type of {@link TNode}. */ -export type InternalRenderer< - T extends TNode, - P extends PropsFromParent = PropsFromParent -> = React.ComponentType>; +export type InternalRenderer = React.ComponentType< + InternalRendererProps +>; /** - * A custom renderer, such as provided in the `renderers` prop. + * A custom renderer, such as provided in the {@link RenderHTMLProps.renderers} prop. * + * @typeParam T - The concrete type of {@link TNode}. * @public */ -export type CustomTagRenderer< - T extends TNode, - P extends PropsFromParent = PropsFromParent -> = React.ComponentType>; +export type CustomRenderer = React.ComponentType< + CustomRendererProps +>; /** * An object containing meta-data extracted from resource URL and HTML - * <head> element. + * `` element. * * @public */