Skip to content

Commit

Permalink
feat: new prop customListStyleSpecs to support additional `list-sty…
Browse files Browse the repository at this point in the history
…le-type`
  • Loading branch information
jsamr committed Jun 4, 2021
1 parent bf71c66 commit 84ec025
Show file tree
Hide file tree
Showing 16 changed files with 160 additions and 97 deletions.
3 changes: 2 additions & 1 deletion packages/render-html/src/RenderHTMLFragment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export const renderHtmlFragmentPropTypes: RenderHTMLFragmentPropTypes = {
defaultWebViewProps: PropTypes.object,
setMarkersForTNode: PropTypes.func,
onDocumentMetadataLoaded: PropTypes.func,
pressableHightlightColor: PropTypes.string
pressableHightlightColor: PropTypes.string,
customListStyleSpecs: PropTypes.object
};

export const renderHTMLFragmentDefaultProps: {
Expand Down
9 changes: 8 additions & 1 deletion packages/render-html/src/context/SharedPropsProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { PropsWithChildren, useCallback, useMemo } from 'react';
import { TextProps, ViewProps } from 'react-native';
import defaultListStyleSpecs from '../elements/defaultListStyleSpecs';
import selectSharedProps from '../helpers/selectSharedProps';
import { RenderHTMLSharedProps, TRendererBaseProps } from '../shared-types';
import defaultSharedProps from './defaultSharedProps';
Expand Down Expand Up @@ -72,7 +73,13 @@ export default function SharedPropsProvider(
props: PropsWithChildren<RenderHTMLSharedProps>
) {
const memoizedSharedProps = useMemo(
() => selectSharedProps(props),
() => ({
...selectSharedProps(props),
customListStyleSpecs: {
...defaultListStyleSpecs,
...props.customListStyleSpecs
}
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
Object.values(selectSharedProps(props))
);
Expand Down
3 changes: 2 additions & 1 deletion packages/render-html/src/context/defaultSharedProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const defaultSharedProps: Required<RenderHTMLSharedProps> = {
},
defaultWebViewProps: {},
setMarkersForTNode: () => null,
pressableHightlightColor: DEFAULT_PRESSABLE_RIPPLE_COLOR
pressableHightlightColor: DEFAULT_PRESSABLE_RIPPLE_COLOR,
customListStyleSpecs: {}
};

export default defaultSharedProps;
38 changes: 26 additions & 12 deletions packages/render-html/src/elements/ListElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,23 @@ import {
useMarkedList,
MarkerBoxProps
} from '@jsamr/react-native-li';
import { DefaultTagRendererProps, TChildProps } from '../shared-types';
import type {
DefaultSupportedListStyleType,
DefaultTagRendererProps,
ListStyleSpec,
TChildProps,
UnitaryListStyleSpec
} from '../shared-types';
import { useTChildrenRenderer } from '../context/TChildrenRendererContext';
import { DEFAULT_TEXT_COLOR } from '../constants';
import pick from 'ramda/src/pick';
import defaultListStyleSpecs, { UnitaryListStyleSpec } from './defaultListStyleSpecs';
import { DefaultSupportedListStyleType } from './list-types';

export interface ListElementProps<T extends 'ol' | 'ul'>
extends DefaultTagRendererProps<TBlock> {
listType: T;
getListStyleTypeFromNestLevel: (nestLevel: number) => DefaultSupportedListStyleType;
getListStyleTypeFromNestLevel: (
nestLevel: number
) => DefaultSupportedListStyleType;
getStyleFromNestLevel?: (nestLevel: number) => ViewStyle | null;
/**
* If `true`:
Expand All @@ -28,6 +34,7 @@ export interface ListElementProps<T extends 'ol' | 'ul'>
* be switched.
*/
enableExperimentalRtl?: boolean;
listStyleSpecs: Record<string, ListStyleSpec>;
}

function getStartIndex(tnode: TNode) {
Expand Down Expand Up @@ -98,6 +105,7 @@ export default function ListElement({
getStyleFromNestLevel,
markers,
enableExperimentalRtl = false,
listStyleSpecs,
...props
}: ListElementProps<any>) {
const nestLevel =
Expand All @@ -112,16 +120,22 @@ export default function ListElement({
const listStyleType =
(tnode.styles.webTextFlow.listStyleType as DefaultSupportedListStyleType) ||
selectedListType;
if (__DEV__ && !(listStyleType in defaultListStyleSpecs)) {
console.warn(
`list-style-type "${listStyleType}" is not handled by react-native-render-html.` +
'You can register a custom list marker renderer with the appropriate prop.'
);
if (__DEV__ && !(listStyleType in listStyleSpecs)) {
if (listStyleType.match(/^("|')/)) {
console.warn(
"This library doesn't support strings for list-style-type CSS properties."
);
} else {
console.warn(
`list-style-type "${listStyleType}" is not handled by react-native-render-html. ` +
'You can easily provide support for this style via "customListStyleSpecs" prop.'
);
}
}
const spec =
listStyleType in defaultListStyleSpecs
? defaultListStyleSpecs[listStyleType]
: defaultListStyleSpecs[selectedListType];
listStyleType in listStyleSpecs
? listStyleSpecs[listStyleType]
: listStyleSpecs[selectedListType];
const counterRenderer = spec.counterStyleRenderer;
const startIndex = getStartIndex(tnode);
const markerTextStyle = extractMarkerTextStyle(tnode);
Expand Down
48 changes: 10 additions & 38 deletions packages/render-html/src/elements/defaultListStyleSpecs.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import CounterStyle, { CounterStyleRenderer } from '@jsamr/counter-style';
import { ComponentType } from 'react';
import CounterStyle from '@jsamr/counter-style';
import decimal from '@jsamr/counter-style/presets/decimal';
import decimalLeadingZero from '@jsamr/counter-style/presets/decimalLeadingZero';
import lowerRoman from '@jsamr/counter-style/presets/lowerRoman';
Expand All @@ -12,45 +11,13 @@ import DisclosureOpenSymbolRenderer from './symbolic/DisclosureOpenSymbolRendere
import CircleSymbolRenderer from './symbolic/CircleSymbolRenderer';
import DiscSymbolRenderer from './symbolic/DiscSymbolRenderer';
import SquareSymbolRenderer from './symbolic/SquareSymbolRenderer';
import {
ListCounterRendererProps,
DefaultSupportedListStyleType
} from './list-types';
import type {
DefaultSupportedListStyleType,
ListStyleSpec
} from '../shared-types';

const unitaryRenderer = CounterStyle.cyclic('*').withSuffix(' ');

/**
* Specs for a list item marker renderer backed by a `CounterStyleRenderer`
* from `@jsamr/counter-style`.
*
* @public
*/
export interface TextualListStyleSpec {
type: 'textual';
counterStyleRenderer: CounterStyleRenderer;
}

/**
* Specs for a list item marker renderer with only one representation. The
* "Component" should render this representation, minus prefix and suffix. The
* rendered component should have a maximum width of `0.6 * fontSize`, and a height of
* `lineHeight`.
*
* @public
*/
export interface UnitaryListStyleSpec {
counterStyleRenderer: CounterStyleRenderer;
type: 'unitary';
Component: ComponentType<ListCounterRendererProps>;
}

/**
* An object to specify how to render list markers.
*
* @public
*/
export type ListStyleSpec = TextualListStyleSpec | UnitaryListStyleSpec;

const lowerAlphaSpec = {
type: 'textual',
counterStyleRenderer: lowerAlpha
Expand All @@ -61,6 +28,11 @@ const upperAlphaSpec = {
counterStyleRenderer: upperAlpha
} as const;

/**
* Default list style specs supported by this library.
*
* @public
*/
const defaultListStyleSpecs: Record<
DefaultSupportedListStyleType,
ListStyleSpec
Expand Down
28 changes: 0 additions & 28 deletions packages/render-html/src/elements/list-types.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { View } from 'react-native';
import { ListCounterRendererProps } from '../list-types';
import { ListCounterRendererProps } from '../../shared-types';
import useSymbolicMarkerRendererProps from './useSymbolicMarkerRendererStyles';

export default function CircleSymbolRenderer(props: ListCounterRendererProps) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { View } from 'react-native';
import { ListCounterRendererProps } from '../list-types';
import { ListCounterRendererProps } from '../../shared-types';
import useSymbolicMarkerRendererProps from './useSymbolicMarkerRendererStyles';

export default function DiscSymbolRenderer(props: ListCounterRendererProps) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { View } from 'react-native';
import { ListCounterRendererProps } from '../list-types';
import { ListCounterRendererProps } from '../../shared-types';
import useSymbolicMarkerRendererProps from './useSymbolicMarkerRendererStyles';

export default function DisclosureClosedSymbolRenderer(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { View } from 'react-native';
import { ListCounterRendererProps } from '../list-types';
import { ListCounterRendererProps } from '../../shared-types';
import useSymbolicMarkerRendererProps from './useSymbolicMarkerRendererStyles';

export default function DisclosureOpenSymbolRenderer(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { View } from 'react-native';
import { ListCounterRendererProps } from '../list-types';
import { ListCounterRendererProps } from '../../shared-types';
import useSymbolicMarkerRendererProps from './useSymbolicMarkerRendererStyles';

export default function SquareSymbolRenderer(props: ListCounterRendererProps) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ListCounterRendererProps } from '../list-types';
import { ListCounterRendererProps } from '../../shared-types';

export default function useSymbolicMarkerRendererProps(
props: ListCounterRendererProps,
Expand Down
1 change: 1 addition & 0 deletions packages/render-html/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export { useRendererProps } from './context/RenderersPropsProvider';
export { useDocumentMetadata } from './context/DocumentMetadataProvider';
export { default as domNodeToHTMLString } from './helpers/domNodeToHTMLString';
export type { DomNodeToHtmlReporter } from './helpers/domNodeToHTMLString';

// IMG
export { default as useIMGElementState } from './elements/useIMGElementState';
export { default as useIMGElementStateWithCache } from './elements/useIMGElementStateWithCache';
Expand Down
8 changes: 6 additions & 2 deletions packages/render-html/src/renderers/OLRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import {
TBlock
} from '@native-html/transient-render-engine';
import { DefaultBlockRenderer } from '../render/render-types';
import { DefaultTagRendererProps } from '../shared-types';
import {
DefaultTagRendererProps,
DefaultSupportedListStyleType
} from '../shared-types';
import OLElement, { OLElementProps } from '../elements/OLElement';
import { DefaultSupportedListStyleType } from '../elements/list-types';

function getListStyleTypeFromNestLevel(
nestLevel: number
Expand All @@ -28,8 +30,10 @@ function getStyleFromNestLevel(nestLevel: number) {
export function useOLElementProps(
props: DefaultTagRendererProps<TBlock>
): OLElementProps {
const listStyleSpecs = props.sharedProps.customListStyleSpecs;
return {
...props,
listStyleSpecs,
getListStyleTypeFromNestLevel,
getStyleFromNestLevel
};
Expand Down
8 changes: 6 additions & 2 deletions packages/render-html/src/renderers/ULRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React from 'react';
import { defaultHTMLElementModels } from '@native-html/transient-render-engine';
import { DefaultBlockRenderer } from '../render/render-types';
import { DefaultTagRendererProps } from '../shared-types';
import {
DefaultTagRendererProps,
DefaultSupportedListStyleType
} from '../shared-types';
import { TBlock } from '@native-html/transient-render-engine';
import ULElement, { ULElementProps } from '../elements/ULElement';
import { DefaultSupportedListStyleType } from '../elements/list-types';

function getListStyleTypeFromNestLevel(
nestLevel: number
Expand All @@ -26,8 +28,10 @@ function getStyleFromNestLevel(nestLevel: number) {
export function useULElementProps(
props: DefaultTagRendererProps<TBlock>
): ULElementProps {
const listStyleSpecs = props.sharedProps.customListStyleSpecs;
return {
...props,
listStyleSpecs,
getListStyleTypeFromNestLevel,
getStyleFromNestLevel
};
Expand Down
Loading

0 comments on commit 84ec025

Please sign in to comment.