Skip to content

Commit

Permalink
feat: nesting ol and ul will result in disinct bullet style types
Browse files Browse the repository at this point in the history
The list renderer can now be extended with
getListStyleTypeFromNestLevel prop.

resolves #312
  • Loading branch information
jsamr committed Jun 4, 2021
1 parent 912ff7a commit ddd66bb
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 35 deletions.
32 changes: 31 additions & 1 deletion demo/snippets/lists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,37 @@ const html = `
<li>Sneaky</li>
<li>Beaky</li>
<li>Like</li>
</ol>`;
</ol>
<hr />
<p> The bullet style type will automatically adapt depending on the nest level of the list.
For example, nesting <em>ul</em> elements will result in:</p>
<ul>
<li>
Hello world
<ul>
<li>Sneaky
<ul>
<li>Beaky</li>
<li>Like</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr />
<p>And nesting <em>ol</em> elements:</p>
<ol>
<li>
Hello world
<ol>
<li>Sneaky</li>
<li>Beaky</li>
</ol>
</li>
</ol>
`;

const lists: SnippetDeclaration = {
name: 'Lists',
Expand Down
6 changes: 3 additions & 3 deletions demo/snippets/test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { SnippetDeclaration } from '../types';

// Change the HTML code here and see what happens.
const html = `
<p>
Open <code>demo/snippets/test.tsx</code> and edit me!
</p>
<ol style="">
<li>Hello world</li>
</ol>
`;

const test: SnippetDeclaration = {
Expand Down
2 changes: 1 addition & 1 deletion packages/render-html/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
]
},
"dependencies": {
"@native-html/transient-render-engine": "^3.6.1",
"@native-html/transient-render-engine": "^3.6.2",
"@types/ramda": "^0.27.32",
"ramda": "^0.27.1"
}
Expand Down
29 changes: 29 additions & 0 deletions packages/render-html/src/context/NestLevelProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* eslint-disable react-hooks/rules-of-hooks */
import React, { PropsWithChildren } from 'react';

const OlNestLevel = React.createContext<number>(0);
const UlNestLevel = React.createContext<number>(0);

export function useListNestLevel(listType: 'ol' | 'ul') {
return listType === 'ol'
? React.useContext(OlNestLevel)
: React.useContext(UlNestLevel);
}

export interface NestLevelProviderProps {
listType: 'ol' | 'ul';
level: number;
}

export default function NestLevelProvider({
listType,
level,
children
}: PropsWithChildren<NestLevelProviderProps>) {
if (listType === 'ol') {
return (
<OlNestLevel.Provider value={level}>{children}</OlNestLevel.Provider>
);
}
return <UlNestLevel.Provider value={level}>{children}</UlNestLevel.Provider>;
}
38 changes: 23 additions & 15 deletions packages/render-html/src/elements/HTMLListElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { DefaultTagRendererProps } from '../shared-types';
import type { TChildProps } from '../TChildrenRenderer';
import { useTChildrenRenderer } from '../context/TChildrenRendererContext';
import usePrefixRenderer, { SupportedListStyleType } from './usePrefixRenderer';
import NestLevelProvider, {
useListNestLevel
} from '../context/NestLevelProvider';

const styles = StyleSheet.create({
row: {
Expand All @@ -15,22 +18,26 @@ const styles = StyleSheet.create({
});

export interface HTMLListElementProps extends DefaultTagRendererProps<TBlock> {
defaultListType: SupportedListStyleType;
listType: 'ol' | 'ul';
getListStyleTypeFromNestLevel: (nestLevel: number) => SupportedListStyleType;
}

export default function HTMLListElement({
tnode,
TDefaultRenderer,
hasAnchorAncestor,
defaultListType,
listType,
style,
getListStyleTypeFromNestLevel,
...props
}: HTMLListElementProps) {
const nestLevel = useListNestLevel(listType);
// Map children to horizontal rows with prefixes
const TChildrenRenderer = useTChildrenRenderer();
const prefixRenderer = usePrefixRenderer({
listStyleType: tnode.styles.webTextFlow.listStyleType,
defaultListType
nestLevel,
getListStyleTypeFromNestLevel,
listStyleType: tnode.styles.webTextFlow.listStyleType
});
const fontSize = tnode.styles.nativeTextFlow.fontSize || 14;
const color = tnode.styles.nativeTextFlow.color as string;
Expand Down Expand Up @@ -58,7 +65,6 @@ export default function HTMLListElement({
<View style={prefixContainerStyle}>
<PrefixRenderer
index={index}
nestLevel={0}
color={color}
fontSize={fontSize}
lineHeight={lineHeight}
Expand All @@ -68,16 +74,18 @@ export default function HTMLListElement({
</View>
);
return (
<TDefaultRenderer
hasAnchorAncestor={hasAnchorAncestor}
tnode={tnode}
style={[style, { paddingLeft }]}
{...props}>
<TChildrenRenderer
tchildren={tnode.children}
<NestLevelProvider listType={listType} level={nestLevel + 1}>
<TDefaultRenderer
hasAnchorAncestor={hasAnchorAncestor}
renderChild={renderChild}
/>
</TDefaultRenderer>
tnode={tnode}
style={[style, { paddingLeft }]}
{...props}>
<TChildrenRenderer
tchildren={tnode.children}
hasAnchorAncestor={hasAnchorAncestor}
renderChild={renderChild}
/>
</TDefaultRenderer>
</NestLevelProvider>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import numOfCharsInPrefix from '../numOfCharsInPrefix';

describe('numOfCharsInPrefix', () => {
it('should handle length of 1', () => {
expect(numOfCharsInPrefix(1, 10)).toEqual(1);
});
});
2 changes: 1 addition & 1 deletion packages/render-html/src/elements/numOfCharsInPrefix.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export default function numOfCharsInPrefix(length: number, base: number) {
let digits: number = 0;
let digits: number = 1;
while (length > 1) {
length /= base;
digits++;
Expand Down
21 changes: 14 additions & 7 deletions packages/render-html/src/elements/usePrefixRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ interface ListPrefixRendererProps {
fontSize: number;
lineHeight: number;
index: number;
nestLevel: number;
/**
* The number of parents of the same tag
*/
// nestLevel: number;
}

const TextualPrefixRenderer = ({
Expand Down Expand Up @@ -195,15 +198,19 @@ export type SupportedListStyleType =

export interface HTMLListPrefixProps {
listStyleType?: string;
defaultListType: string;
nestLevel: number;
getListStyleTypeFromNestLevel: (nestLevel: number) => SupportedListStyleType;
}

export default function usePrefixRenderer({
listStyleType,
defaultListType
getListStyleTypeFromNestLevel,
nestLevel
}: HTMLListPrefixProps): PrefixSepcs {
return (
prefixRenderersMap[listStyleType as SupportedListStyleType] ||
defaultListType
);
const selectedListType = getListStyleTypeFromNestLevel(nestLevel);
console.info('selected style type', selectedListType);
return listStyleType
? prefixRenderersMap[listStyleType as SupportedListStyleType] ||
prefixRenderersMap[selectedListType]
: prefixRenderersMap[selectedListType];
}
17 changes: 16 additions & 1 deletion packages/render-html/src/renderers/OrderedListRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,28 @@ import HTMLListElement, {
} from '../elements/HTMLListElement';
import { DefaultBlockRenderer } from '../render/render-types';
import { DefaultTagRendererProps } from '../shared-types';
import { SupportedListStyleType } from '../elements/usePrefixRenderer';

function getListStyleTypeFromNestLevel(
nestLevel: number
): SupportedListStyleType {
switch (nestLevel % 3) {
case 0:
return 'decimal';
case 1:
return 'upper-alpha';
default:
return 'lower-alpha';
}
}

export function useOrderedListRendererProps(
props: DefaultTagRendererProps<TBlock>
): HTMLListElementProps {
return {
...props,
defaultListType: 'decimal'
listType: 'ol',
getListStyleTypeFromNestLevel
};
}

Expand Down
17 changes: 16 additions & 1 deletion packages/render-html/src/renderers/UnorderedListRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,28 @@ import HTMLListElement, {
import { DefaultBlockRenderer } from '../render/render-types';
import { DefaultTagRendererProps } from '../shared-types';
import { TBlock } from '@native-html/transient-render-engine';
import { SupportedListStyleType } from '../elements/usePrefixRenderer';

function getListStyleTypeFromNestLevel(
nestLevel: number
): SupportedListStyleType {
switch (nestLevel % 3) {
case 0:
return 'disc';
case 1:
return 'circle';
default:
return 'square';
}
}

export function useUnorderedListRendererProps(
props: DefaultTagRendererProps<TBlock>
): HTMLListElementProps {
return {
...props,
defaultListType: 'disc'
listType: 'ul',
getListStyleTypeFromNestLevel
};
}

Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2922,9 +2922,9 @@ __metadata:
languageName: node
linkType: hard

"@native-html/transient-render-engine@npm:^3.6.1":
version: 3.6.1
resolution: "@native-html/transient-render-engine@npm:3.6.1"
"@native-html/transient-render-engine@npm:^3.6.2":
version: 3.6.2
resolution: "@native-html/transient-render-engine@npm:3.6.2"
dependencies:
"@native-html/css-processor": 1.6.1
"@types/ramda": ^0.27.32
Expand All @@ -2933,7 +2933,7 @@ __metadata:
peerDependencies:
"@types/react-native": "*"
react-native: ^0.63.0
checksum: 7ac04fd89b15080689a02c6f183070e2ff4a405551cacb1721beba07e3d97d682a14e88dcdaf2121aac123ab3894134a8d42b2a1d19c308460faee22ef722d8f
checksum: f5512fa7623452488c5228cb6b04e7962a8b2128a99db2c0b27bf6dbdef75fc4a8caf76c79c02a2fa4fb30e7af1d1fea3269e33c08c98fec4a33c09717514a3c
languageName: node
linkType: hard

Expand Down Expand Up @@ -14287,7 +14287,7 @@ fsevents@^1.2.7:
"@babel/preset-react": ^7.12.7
"@babel/preset-typescript": ^7.12.1
"@babel/runtime": ^7.12.5
"@native-html/transient-render-engine": ^3.6.1
"@native-html/transient-render-engine": ^3.6.2
"@react-native-community/bob": ^0.16.2
"@release-it/conventional-changelog": ^2.0.0
"@types/jest": ^26.0.14
Expand Down

0 comments on commit ddd66bb

Please sign in to comment.