From 5961ae4cba0778527a569530fc4529f62c4a362f Mon Sep 17 00:00:00 2001 From: lucataglia Date: Thu, 18 May 2023 15:33:28 +0200 Subject: [PATCH 01/24] add collapse/expand all feature for react-json-tree --- packages/react-json-tree/src/JSONNestedNode.tsx | 12 +++++++++++- packages/react-json-tree/src/index.tsx | 2 ++ packages/react-json-tree/src/types.ts | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index 0e5b5be52c..ab451d473c 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import JSONArrow from './JSONArrow'; import getCollectionEntries from './getCollectionEntries'; import JSONNode from './JSONNode'; @@ -110,6 +110,7 @@ export default function JSONNestedNode(props: Props) { nodeType, nodeTypeIndicator, shouldExpandNodeInitially, + shouldExpandNode, styling, } = props; @@ -117,7 +118,16 @@ export default function JSONNestedNode(props: Props) { // calculate individual node expansion if necessary isCircular ? false : shouldExpandNodeInitially(keyPath, data, level) ); + + useEffect(() => { + if(shouldExpandNode === undefined){ + return + } + + setExpanded(shouldExpandNode); + }, [shouldExpandNode]) + const handleClick = useCallback(() => { if (expandable) setExpanded(!expanded); }, [expandable, expanded]); diff --git a/packages/react-json-tree/src/index.tsx b/packages/react-json-tree/src/index.tsx index 26fab0fc4b..48d1ceaa8b 100644 --- a/packages/react-json-tree/src/index.tsx +++ b/packages/react-json-tree/src/index.tsx @@ -41,6 +41,7 @@ export function JSONTree({ labelRenderer = defaultLabelRenderer, valueRenderer = identity, shouldExpandNodeInitially = expandRootNode, + shouldExpandNode, hideRoot = false, getItemString = defaultItemString, postprocessValue = identity, @@ -64,6 +65,7 @@ export function JSONTree({ labelRenderer={labelRenderer} valueRenderer={valueRenderer} shouldExpandNodeInitially={shouldExpandNodeInitially} + shouldExpandNode={shouldExpandNode} hideRoot={hideRoot} getItemString={getItemString} postprocessValue={postprocessValue} diff --git a/packages/react-json-tree/src/types.ts b/packages/react-json-tree/src/types.ts index 6a67f376c9..2bb3981a9d 100644 --- a/packages/react-json-tree/src/types.ts +++ b/packages/react-json-tree/src/types.ts @@ -47,6 +47,7 @@ export interface CommonExternalProps { labelRenderer: LabelRenderer; valueRenderer: ValueRenderer; shouldExpandNodeInitially: ShouldExpandNodeInitially; + shouldExpandNode: boolean | undefined; hideRoot: boolean; getItemString: GetItemString; postprocessValue: PostprocessValue; From 2ce138849429504488e7579d8795dfd08da8903d Mon Sep 17 00:00:00 2001 From: lucataglia Date: Thu, 18 May 2023 15:45:51 +0200 Subject: [PATCH 02/24] add changeset --- .changeset/modern-masks-fetch.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/modern-masks-fetch.md diff --git a/.changeset/modern-masks-fetch.md b/.changeset/modern-masks-fetch.md new file mode 100644 index 0000000000..7b52ed8d01 --- /dev/null +++ b/.changeset/modern-masks-fetch.md @@ -0,0 +1,5 @@ +--- +'react-json-tree': minor +--- + +Add expand/collapse all feature From 583749467def3222259f4e25c0c9f98a607899ac Mon Sep 17 00:00:00 2001 From: lucataglia Date: Thu, 18 May 2023 15:50:14 +0200 Subject: [PATCH 03/24] run prettier --- packages/react-json-tree/src/JSONNestedNode.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index ab451d473c..265d0c4745 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -118,16 +118,15 @@ export default function JSONNestedNode(props: Props) { // calculate individual node expansion if necessary isCircular ? false : shouldExpandNodeInitially(keyPath, data, level) ); - useEffect(() => { - if(shouldExpandNode === undefined){ - return + if (shouldExpandNode === undefined) { + return; } setExpanded(shouldExpandNode); - }, [shouldExpandNode]) - + }, [shouldExpandNode]); + const handleClick = useCallback(() => { if (expandable) setExpanded(!expanded); }, [expandable, expanded]); From c98870d84835bb63794e28abd25db3e3c4c6d74d Mon Sep 17 00:00:00 2001 From: lucataglia Date: Thu, 18 May 2023 16:17:14 +0200 Subject: [PATCH 04/24] add traceResolution --- packages/react-json-tree/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/react-json-tree/tsconfig.json b/packages/react-json-tree/tsconfig.json index 0aade49afc..46522d101a 100644 --- a/packages/react-json-tree/tsconfig.json +++ b/packages/react-json-tree/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig.react.base.json", "compilerOptions": { - "outDir": "lib/types" + "outDir": "lib/types", + "traceResolution": true }, "include": ["src"] } From 205e271937491bab0810cb961c704f27d73e1b2b Mon Sep 17 00:00:00 2001 From: lucataglia Date: Thu, 18 May 2023 16:30:35 +0200 Subject: [PATCH 05/24] add traceResolution option to build:types command --- packages/react-json-tree/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-json-tree/package.json b/packages/react-json-tree/package.json index 5190e75517..8777751fdb 100644 --- a/packages/react-json-tree/package.json +++ b/packages/react-json-tree/package.json @@ -35,7 +35,7 @@ "build": "pnpm run build:cjs && pnpm run build:esm && pnpm run build:types && pnpm run build:umd", "build:cjs": "babel src --extensions \".ts,.tsx\" --out-dir lib/cjs", "build:esm": "babel src --config-file ./babel.config.esm.json --extensions \".ts,.tsx\" --out-dir lib/esm", - "build:types": "tsc --emitDeclarationOnly", + "build:types": "tsc --traceResolution --emitDeclarationOnly", "build:umd": "rollup -c", "clean": "rimraf lib", "test": "jest", From f0b8a64713d6a6c710e35531a956e91bb236ef49 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Thu, 18 May 2023 16:59:18 +0200 Subject: [PATCH 06/24] remove traceResolution config --- packages/react-json-tree/package.json | 2 +- packages/react-json-tree/tsconfig.json | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/react-json-tree/package.json b/packages/react-json-tree/package.json index 8777751fdb..5190e75517 100644 --- a/packages/react-json-tree/package.json +++ b/packages/react-json-tree/package.json @@ -35,7 +35,7 @@ "build": "pnpm run build:cjs && pnpm run build:esm && pnpm run build:types && pnpm run build:umd", "build:cjs": "babel src --extensions \".ts,.tsx\" --out-dir lib/cjs", "build:esm": "babel src --config-file ./babel.config.esm.json --extensions \".ts,.tsx\" --out-dir lib/esm", - "build:types": "tsc --traceResolution --emitDeclarationOnly", + "build:types": "tsc --emitDeclarationOnly", "build:umd": "rollup -c", "clean": "rimraf lib", "test": "jest", diff --git a/packages/react-json-tree/tsconfig.json b/packages/react-json-tree/tsconfig.json index 46522d101a..0aade49afc 100644 --- a/packages/react-json-tree/tsconfig.json +++ b/packages/react-json-tree/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "../../tsconfig.react.base.json", "compilerOptions": { - "outDir": "lib/types", - "traceResolution": true + "outDir": "lib/types" }, "include": ["src"] } From decde458b15072e51c4b9b808dd8f5eb07f51ab4 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Fri, 19 May 2023 17:45:35 +0200 Subject: [PATCH 07/24] Integrate expand/collapse buttons into the react-json-tree --- packages/react-json-tree/package.json | 3 + .../react-json-tree/src/JSONNestedNode.tsx | 13 ++- .../react-json-tree/src/expandableButtons.tsx | 106 ++++++++++++++++++ packages/react-json-tree/src/index.tsx | 25 ++++- packages/react-json-tree/src/types.ts | 2 +- packages/react-json-tree/test/index.spec.tsx | 2 +- 6 files changed, 141 insertions(+), 10 deletions(-) create mode 100644 packages/react-json-tree/src/expandableButtons.tsx diff --git a/packages/react-json-tree/package.json b/packages/react-json-tree/package.json index 5190e75517..8bee4142fc 100644 --- a/packages/react-json-tree/package.json +++ b/packages/react-json-tree/package.json @@ -46,6 +46,9 @@ }, "dependencies": { "@babel/runtime": "^7.21.0", + "@fortawesome/fontawesome-svg-core": "^6.4.0", + "@fortawesome/free-solid-svg-icons": "^6.4.0", + "@fortawesome/react-fontawesome": "^0.2.0", "@types/lodash": "^4.14.194", "react-base16-styling": "^0.9.1" }, diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index 265d0c4745..6a505adffa 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -119,13 +119,16 @@ export default function JSONNestedNode(props: Props) { isCircular ? false : shouldExpandNodeInitially(keyPath, data, level) ); + const defaultExpanded = shouldExpandNodeInitially(keyPath, data, level); + useEffect(() => { - if (shouldExpandNode === undefined) { - return; + switch(shouldExpandNode){ + case 'expand': setExpanded(true); break; + case'collapse': setExpanded(false); break; + case'default': setExpanded(defaultExpanded); break; + default: } - - setExpanded(shouldExpandNode); - }, [shouldExpandNode]); + }, [defaultExpanded, shouldExpandNode]); const handleClick = useCallback(() => { if (expandable) setExpanded(!expanded); diff --git a/packages/react-json-tree/src/expandableButtons.tsx b/packages/react-json-tree/src/expandableButtons.tsx new file mode 100644 index 0000000000..a4e4818deb --- /dev/null +++ b/packages/react-json-tree/src/expandableButtons.tsx @@ -0,0 +1,106 @@ +import React, { ReactNode } from 'react' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faArrowDown, faArrowRight, faUndo } from '@fortawesome/free-solid-svg-icons'; +import { Expandable } from '.'; + +interface Props { + expandable?: Expandable; + expandableDefaultValue?: 'expand' | 'collapse'; + shouldExpandNode?: 'expand' | 'collapse' | 'default'; + setShouldExpandNode: any; +} + +interface ExpandButtonProps { + expandableDefaultValue?: 'expand' | 'collapse'; + expandIcon?: ReactNode; + shouldExpandNode?: 'expand' | 'collapse' | 'default'; + setShouldExpandNode: any; +} + +interface CollapseButtonProps { + expandableDefaultValue?: 'expand' | 'collapse'; + collapseIcon?: ReactNode; + shouldExpandNode?: 'expand' | 'collapse' | 'default'; + setShouldExpandNode: any; +} + +interface DefaultButtonProps { + defaultIcon?: ReactNode; + setShouldExpandNode: any; +} + +function ExpandableButtons({ + expandable, + expandableDefaultValue, + setShouldExpandNode, + shouldExpandNode + }: Props){ + if(!expandable){ + return <> + } + + return ( +
+ + + + + +
+ ) +} + +function ExpandButton({ expandableDefaultValue, expandIcon, shouldExpandNode, setShouldExpandNode }: ExpandButtonProps) { + const onExpand = () => setShouldExpandNode('expand'); + + if (shouldExpandNode === 'collapse' || (shouldExpandNode === 'default' && expandableDefaultValue === 'collapse')) { + return ( +
+ {expandIcon || } +
+ ); + } + + return <>; + } + + function CollapseButton({ expandableDefaultValue, collapseIcon, shouldExpandNode, setShouldExpandNode }: CollapseButtonProps) { + const onCollapse = () => setShouldExpandNode('collapse'); + + if (shouldExpandNode === 'expand' ||(shouldExpandNode === 'default' && expandableDefaultValue === 'expand')) { + return ( +
+ {collapseIcon || } +
+ ); + } + + return <>; + } + + function DefaultButton({defaultIcon, setShouldExpandNode }:DefaultButtonProps) { + const onDefaultCollapse = () => setShouldExpandNode('default'); + + return ( +
+ {defaultIcon || } +
+ ); + + return <>; + } + + export default ExpandableButtons \ No newline at end of file diff --git a/packages/react-json-tree/src/index.tsx b/packages/react-json-tree/src/index.tsx index 48d1ceaa8b..f3df0b663f 100644 --- a/packages/react-json-tree/src/index.tsx +++ b/packages/react-json-tree/src/index.tsx @@ -3,11 +3,12 @@ // Dave Vedder http://www.eskimospy.com/ // port by Daniele Zannotti http://www.github.com/dzannotti -import React, { useMemo } from 'react'; +import React, { ReactNode, useMemo, useState } from 'react'; import JSONNode from './JSONNode'; import createStylingFromTheme from './createStylingFromTheme'; import { invertTheme } from 'react-base16-styling'; import type { StylingValue, Theme } from 'react-base16-styling'; +import ExpandableButtons from './expandableButtons' import type { CommonExternalProps, GetItemString, @@ -20,6 +21,14 @@ interface Props extends Partial { data: unknown; theme?: Theme; invertTheme?: boolean; + expandable?: Expandable; +} + +interface Expandable { + defaultValue?: 'expand' | 'collapse'; + expandIcon?: ReactNode; + collapseIcon?: ReactNode; + defaultIcon?: ReactNode; } const identity = (value: any) => value; @@ -41,7 +50,7 @@ export function JSONTree({ labelRenderer = defaultLabelRenderer, valueRenderer = identity, shouldExpandNodeInitially = expandRootNode, - shouldExpandNode, + expandable, hideRoot = false, getItemString = defaultItemString, postprocessValue = identity, @@ -49,6 +58,9 @@ export function JSONTree({ collectionLimit = 50, sortObjectKeys = false, }: Props) { + const expandableDefaultValue = expandable?.defaultValue || 'expand' + const [shouldExpandNode, setShouldExpandNode] = useState(expandableDefaultValue); + const styling = useMemo( () => createStylingFromTheme(shouldInvertTheme ? invertTheme(theme) : theme), @@ -72,6 +84,13 @@ export function JSONTree({ collectionLimit={collectionLimit} sortObjectKeys={sortObjectKeys} /> + + ); } @@ -89,4 +108,4 @@ export type { Styling, CommonExternalProps, } from './types'; -export type { StylingValue }; +export type { Expandable, StylingValue }; diff --git a/packages/react-json-tree/src/types.ts b/packages/react-json-tree/src/types.ts index 2bb3981a9d..048a4086fb 100644 --- a/packages/react-json-tree/src/types.ts +++ b/packages/react-json-tree/src/types.ts @@ -47,7 +47,6 @@ export interface CommonExternalProps { labelRenderer: LabelRenderer; valueRenderer: ValueRenderer; shouldExpandNodeInitially: ShouldExpandNodeInitially; - shouldExpandNode: boolean | undefined; hideRoot: boolean; getItemString: GetItemString; postprocessValue: PostprocessValue; @@ -61,4 +60,5 @@ export interface CommonInternalProps extends CommonExternalProps { circularCache?: CircularCache; level?: number; isCircular?: boolean; + shouldExpandNode?: 'expand' | 'collapse' | 'default'; } diff --git a/packages/react-json-tree/test/index.spec.tsx b/packages/react-json-tree/test/index.spec.tsx index 996612913e..7f409eda7b 100644 --- a/packages/react-json-tree/test/index.spec.tsx +++ b/packages/react-json-tree/test/index.spec.tsx @@ -17,6 +17,6 @@ describe('JSONTree', () => { const result = render(); expect(result.type).toBe('ul'); - expect(result.props.children.type.name).toBe(JSONNode.name); + expect(result.props.children[0].type.name).toBe(JSONNode.name); }); }); From b12babbcd91e25a0e579326d0b8f3ddcd8f3173f Mon Sep 17 00:00:00 2001 From: lucataglia Date: Fri, 19 May 2023 18:16:39 +0200 Subject: [PATCH 08/24] handle very first render --- packages/react-json-tree/src/expandableButtons.tsx | 14 +++++++++----- packages/react-json-tree/src/index.tsx | 4 +--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/react-json-tree/src/expandableButtons.tsx b/packages/react-json-tree/src/expandableButtons.tsx index a4e4818deb..ed9f985605 100644 --- a/packages/react-json-tree/src/expandableButtons.tsx +++ b/packages/react-json-tree/src/expandableButtons.tsx @@ -5,7 +5,6 @@ import { Expandable } from '.'; interface Props { expandable?: Expandable; - expandableDefaultValue?: 'expand' | 'collapse'; shouldExpandNode?: 'expand' | 'collapse' | 'default'; setShouldExpandNode: any; } @@ -31,7 +30,6 @@ interface DefaultButtonProps { function ExpandableButtons({ expandable, - expandableDefaultValue, setShouldExpandNode, shouldExpandNode }: Props){ @@ -39,13 +37,15 @@ function ExpandableButtons({ return <> } + const expandableDefaultValue = expandable?.defaultValue || 'expand' + return (
- + setShouldExpandNode('expand'); - if (shouldExpandNode === 'collapse' || (shouldExpandNode === 'default' && expandableDefaultValue === 'collapse')) { + const isDefault = !shouldExpandNode ||shouldExpandNode === 'default' + + if (shouldExpandNode === 'collapse' || (isDefault && expandableDefaultValue === 'collapse')) { return (
{expandIcon || } @@ -80,7 +82,9 @@ function ExpandButton({ expandableDefaultValue, expandIcon, shouldExpandNode, se function CollapseButton({ expandableDefaultValue, collapseIcon, shouldExpandNode, setShouldExpandNode }: CollapseButtonProps) { const onCollapse = () => setShouldExpandNode('collapse'); - if (shouldExpandNode === 'expand' ||(shouldExpandNode === 'default' && expandableDefaultValue === 'expand')) { + const isDefault = !shouldExpandNode ||shouldExpandNode === 'default' + + if (shouldExpandNode === 'expand' ||(isDefault && expandableDefaultValue === 'expand')) { return (
{collapseIcon || } diff --git a/packages/react-json-tree/src/index.tsx b/packages/react-json-tree/src/index.tsx index f3df0b663f..77458611fd 100644 --- a/packages/react-json-tree/src/index.tsx +++ b/packages/react-json-tree/src/index.tsx @@ -58,8 +58,7 @@ export function JSONTree({ collectionLimit = 50, sortObjectKeys = false, }: Props) { - const expandableDefaultValue = expandable?.defaultValue || 'expand' - const [shouldExpandNode, setShouldExpandNode] = useState(expandableDefaultValue); + const [shouldExpandNode, setShouldExpandNode] = useState(); const styling = useMemo( () => @@ -87,7 +86,6 @@ export function JSONTree({ From 1f6d0291eedb3749222f45e91fbea0d8c932b3e4 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Fri, 19 May 2023 18:47:21 +0200 Subject: [PATCH 09/24] handle default button visibility --- .../react-json-tree/src/JSONNestedNode.tsx | 8 +++-- .../react-json-tree/src/expandableButtons.tsx | 35 ++++++++++++++----- packages/react-json-tree/src/index.tsx | 4 +++ packages/react-json-tree/src/types.ts | 1 + 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index 6a505adffa..2f035e3831 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -112,6 +112,7 @@ export default function JSONNestedNode(props: Props) { shouldExpandNodeInitially, shouldExpandNode, styling, + setEnableDefaultButton, } = props; const [expanded, setExpanded] = useState( @@ -131,8 +132,11 @@ export default function JSONNestedNode(props: Props) { }, [defaultExpanded, shouldExpandNode]); const handleClick = useCallback(() => { - if (expandable) setExpanded(!expanded); - }, [expandable, expanded]); + if (expandable) { + setExpanded(!expanded); + setEnableDefaultButton(true); + } + }, [expandable, expanded, setEnableDefaultButton]); const renderedChildren = expanded || (hideRoot && level === 0) diff --git a/packages/react-json-tree/src/expandableButtons.tsx b/packages/react-json-tree/src/expandableButtons.tsx index ed9f985605..99c10e2b5d 100644 --- a/packages/react-json-tree/src/expandableButtons.tsx +++ b/packages/react-json-tree/src/expandableButtons.tsx @@ -5,6 +5,8 @@ import { Expandable } from '.'; interface Props { expandable?: Expandable; + enableDefaultButton: boolean; + setEnableDefaultButton: any; shouldExpandNode?: 'expand' | 'collapse' | 'default'; setShouldExpandNode: any; } @@ -14,6 +16,7 @@ interface ExpandButtonProps { expandIcon?: ReactNode; shouldExpandNode?: 'expand' | 'collapse' | 'default'; setShouldExpandNode: any; + setEnableDefaultButton: any; } interface CollapseButtonProps { @@ -21,15 +24,19 @@ interface CollapseButtonProps { collapseIcon?: ReactNode; shouldExpandNode?: 'expand' | 'collapse' | 'default'; setShouldExpandNode: any; + setEnableDefaultButton: any; } interface DefaultButtonProps { defaultIcon?: ReactNode; setShouldExpandNode: any; + setEnableDefaultButton: any; } function ExpandableButtons({ expandable, + enableDefaultButton, + setEnableDefaultButton, setShouldExpandNode, shouldExpandNode }: Props){ @@ -41,15 +48,17 @@ function ExpandableButtons({ return (
- + setEnableDefaultButton={setEnableDefaultButton} + />} @@ -57,14 +66,18 @@ function ExpandableButtons({ expandableDefaultValue={expandable?.defaultValue} collapseIcon={expandable?.collapseIcon} setShouldExpandNode={setShouldExpandNode} + setEnableDefaultButton={setEnableDefaultButton} shouldExpandNode={shouldExpandNode} />
) } -function ExpandButton({ expandableDefaultValue, expandIcon, shouldExpandNode, setShouldExpandNode }: ExpandButtonProps) { - const onExpand = () => setShouldExpandNode('expand'); +function ExpandButton({ expandableDefaultValue, expandIcon, shouldExpandNode, setEnableDefaultButton, setShouldExpandNode }: ExpandButtonProps) { + const onExpand = () => { + setShouldExpandNode('expand'); + setEnableDefaultButton(true); + } const isDefault = !shouldExpandNode ||shouldExpandNode === 'default' @@ -79,8 +92,11 @@ function ExpandButton({ expandableDefaultValue, expandIcon, shouldExpandNode, se return <>; } - function CollapseButton({ expandableDefaultValue, collapseIcon, shouldExpandNode, setShouldExpandNode }: CollapseButtonProps) { - const onCollapse = () => setShouldExpandNode('collapse'); + function CollapseButton({ expandableDefaultValue, collapseIcon, shouldExpandNode, setEnableDefaultButton, setShouldExpandNode }: CollapseButtonProps) { + const onCollapse = () => { + setShouldExpandNode('collapse'); + setEnableDefaultButton(true); + } const isDefault = !shouldExpandNode ||shouldExpandNode === 'default' @@ -95,8 +111,11 @@ function ExpandButton({ expandableDefaultValue, expandIcon, shouldExpandNode, se return <>; } - function DefaultButton({defaultIcon, setShouldExpandNode }:DefaultButtonProps) { - const onDefaultCollapse = () => setShouldExpandNode('default'); + function DefaultButton({defaultIcon, setEnableDefaultButton, setShouldExpandNode }:DefaultButtonProps) { + const onDefaultCollapse = () => { + setShouldExpandNode('default'); + setEnableDefaultButton(false) + } return (
diff --git a/packages/react-json-tree/src/index.tsx b/packages/react-json-tree/src/index.tsx index 77458611fd..9b5a6d68ed 100644 --- a/packages/react-json-tree/src/index.tsx +++ b/packages/react-json-tree/src/index.tsx @@ -58,6 +58,7 @@ export function JSONTree({ collectionLimit = 50, sortObjectKeys = false, }: Props) { + const [enableDefaultButton, setEnableDefaultButton] = useState(false); const [shouldExpandNode, setShouldExpandNode] = useState(); const styling = useMemo( @@ -77,6 +78,7 @@ export function JSONTree({ valueRenderer={valueRenderer} shouldExpandNodeInitially={shouldExpandNodeInitially} shouldExpandNode={shouldExpandNode} + setEnableDefaultButton={setEnableDefaultButton} hideRoot={hideRoot} getItemString={getItemString} postprocessValue={postprocessValue} @@ -86,6 +88,8 @@ export function JSONTree({ diff --git a/packages/react-json-tree/src/types.ts b/packages/react-json-tree/src/types.ts index 048a4086fb..27e4f8063b 100644 --- a/packages/react-json-tree/src/types.ts +++ b/packages/react-json-tree/src/types.ts @@ -53,6 +53,7 @@ export interface CommonExternalProps { isCustomNode: IsCustomNode; collectionLimit: number; sortObjectKeys: SortObjectKeys; + setEnableDefaultButton: any; } export interface CommonInternalProps extends CommonExternalProps { From e664cba9fbedf580882ca0fc35b1788f0b9f1d56 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Fri, 19 May 2023 18:56:26 +0200 Subject: [PATCH 10/24] bugfix on corner case --- packages/react-json-tree/src/JSONNestedNode.tsx | 6 ++++-- packages/react-json-tree/src/index.tsx | 1 + packages/react-json-tree/src/types.ts | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index 2f035e3831..fe82a169a2 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -111,8 +111,9 @@ export default function JSONNestedNode(props: Props) { nodeTypeIndicator, shouldExpandNodeInitially, shouldExpandNode, - styling, + setShouldExpandNode, setEnableDefaultButton, + styling, } = props; const [expanded, setExpanded] = useState( @@ -135,8 +136,9 @@ export default function JSONNestedNode(props: Props) { if (expandable) { setExpanded(!expanded); setEnableDefaultButton(true); + setShouldExpandNode(undefined) } - }, [expandable, expanded, setEnableDefaultButton]); + }, [expandable, expanded, setEnableDefaultButton, setShouldExpandNode]); const renderedChildren = expanded || (hideRoot && level === 0) diff --git a/packages/react-json-tree/src/index.tsx b/packages/react-json-tree/src/index.tsx index 9b5a6d68ed..9ba8d18b39 100644 --- a/packages/react-json-tree/src/index.tsx +++ b/packages/react-json-tree/src/index.tsx @@ -79,6 +79,7 @@ export function JSONTree({ shouldExpandNodeInitially={shouldExpandNodeInitially} shouldExpandNode={shouldExpandNode} setEnableDefaultButton={setEnableDefaultButton} + setShouldExpandNode={setShouldExpandNode} hideRoot={hideRoot} getItemString={getItemString} postprocessValue={postprocessValue} diff --git a/packages/react-json-tree/src/types.ts b/packages/react-json-tree/src/types.ts index 27e4f8063b..71943a35b2 100644 --- a/packages/react-json-tree/src/types.ts +++ b/packages/react-json-tree/src/types.ts @@ -54,6 +54,7 @@ export interface CommonExternalProps { collectionLimit: number; sortObjectKeys: SortObjectKeys; setEnableDefaultButton: any; + setShouldExpandNode: any; } export interface CommonInternalProps extends CommonExternalProps { From fc0611d750852ee1eee156295933cd0f45c88846 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Sat, 20 May 2023 22:41:59 +0200 Subject: [PATCH 11/24] add context --- .../react-json-tree/src/JSONNestedNode.tsx | 29 ++- .../react-json-tree/src/expandableButtons.tsx | 207 +++++++++--------- .../src/expandableButtonsContext.tsx | 50 +++++ packages/react-json-tree/src/index.tsx | 49 ++--- packages/react-json-tree/src/types.ts | 3 - 5 files changed, 195 insertions(+), 143 deletions(-) create mode 100644 packages/react-json-tree/src/expandableButtonsContext.tsx diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index fe82a169a2..c05c387841 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -1,8 +1,9 @@ import React, { useCallback, useEffect, useState } from 'react'; +import ItemRange from './ItemRange'; import JSONArrow from './JSONArrow'; -import getCollectionEntries from './getCollectionEntries'; import JSONNode from './JSONNode'; -import ItemRange from './ItemRange'; +import { useExpandableButtonContext } from './expandableButtonsContext'; +import getCollectionEntries from './getCollectionEntries'; import type { CircularCache, CommonInternalProps } from './types'; /** @@ -110,12 +111,12 @@ export default function JSONNestedNode(props: Props) { nodeType, nodeTypeIndicator, shouldExpandNodeInitially, - shouldExpandNode, - setShouldExpandNode, - setEnableDefaultButton, styling, } = props; + const { shouldExpandNode, setShouldExpandNode, setEnableDefaultButton } = + useExpandableButtonContext(); + const [expanded, setExpanded] = useState( // calculate individual node expansion if necessary isCircular ? false : shouldExpandNodeInitially(keyPath, data, level) @@ -124,11 +125,17 @@ export default function JSONNestedNode(props: Props) { const defaultExpanded = shouldExpandNodeInitially(keyPath, data, level); useEffect(() => { - switch(shouldExpandNode){ - case 'expand': setExpanded(true); break; - case'collapse': setExpanded(false); break; - case'default': setExpanded(defaultExpanded); break; - default: + switch (shouldExpandNode) { + case 'expand': + setExpanded(true); + break; + case 'collapse': + setExpanded(false); + break; + case 'default': + setExpanded(defaultExpanded); + break; + default: // Do nothing } }, [defaultExpanded, shouldExpandNode]); @@ -136,7 +143,7 @@ export default function JSONNestedNode(props: Props) { if (expandable) { setExpanded(!expanded); setEnableDefaultButton(true); - setShouldExpandNode(undefined) + setShouldExpandNode(undefined); } }, [expandable, expanded, setEnableDefaultButton, setShouldExpandNode]); diff --git a/packages/react-json-tree/src/expandableButtons.tsx b/packages/react-json-tree/src/expandableButtons.tsx index 99c10e2b5d..5c56a12b78 100644 --- a/packages/react-json-tree/src/expandableButtons.tsx +++ b/packages/react-json-tree/src/expandableButtons.tsx @@ -1,129 +1,138 @@ -import React, { ReactNode } from 'react' +import { + faArrowDown, + faArrowRight, + faUndo, +} from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faArrowDown, faArrowRight, faUndo } from '@fortawesome/free-solid-svg-icons'; +import React, { ReactNode } from 'react'; import { Expandable } from '.'; +import { useExpandableButtonContext } from './expandableButtonsContext'; -interface Props { - expandable?: Expandable; - enableDefaultButton: boolean; - setEnableDefaultButton: any; - shouldExpandNode?: 'expand' | 'collapse' | 'default'; - setShouldExpandNode: any; +interface ExpandableButtonsProps { + expandable: Expandable; } interface ExpandButtonProps { expandableDefaultValue?: 'expand' | 'collapse'; expandIcon?: ReactNode; - shouldExpandNode?: 'expand' | 'collapse' | 'default'; - setShouldExpandNode: any; - setEnableDefaultButton: any; } interface CollapseButtonProps { expandableDefaultValue?: 'expand' | 'collapse'; collapseIcon?: ReactNode; - shouldExpandNode?: 'expand' | 'collapse' | 'default'; - setShouldExpandNode: any; - setEnableDefaultButton: any; } interface DefaultButtonProps { defaultIcon?: ReactNode; - setShouldExpandNode: any; - setEnableDefaultButton: any; } -function ExpandableButtons({ - expandable, - enableDefaultButton, - setEnableDefaultButton, - setShouldExpandNode, - shouldExpandNode - }: Props){ - if(!expandable){ - return <> - } +function ExpandableButtons({ expandable }: ExpandableButtonsProps) { + const { enableDefaultButton } = useExpandableButtonContext(); - const expandableDefaultValue = expandable?.defaultValue || 'expand' + const expandableDefaultValue = expandable?.defaultValue || 'expand'; + return ( +
+ {enableDefaultButton && ( + + )} + + + + +
+ ); +} + +function ExpandButton({ + expandableDefaultValue, + expandIcon, +}: ExpandButtonProps) { + const { shouldExpandNode, setShouldExpandNode, setEnableDefaultButton } = + useExpandableButtonContext(); + + const onExpand = () => { + setShouldExpandNode('expand'); + setEnableDefaultButton(true); + }; + + const isDefault = !shouldExpandNode || shouldExpandNode === 'default'; + + if ( + shouldExpandNode === 'collapse' || + (isDefault && expandableDefaultValue === 'collapse') + ) { return ( -
- {enableDefaultButton && } - - - - +
+ {expandIcon || }
- ) + ); + } + + return <>; } -function ExpandButton({ expandableDefaultValue, expandIcon, shouldExpandNode, setEnableDefaultButton, setShouldExpandNode }: ExpandButtonProps) { - const onExpand = () => { - setShouldExpandNode('expand'); - setEnableDefaultButton(true); - } - - const isDefault = !shouldExpandNode ||shouldExpandNode === 'default' - - if (shouldExpandNode === 'collapse' || (isDefault && expandableDefaultValue === 'collapse')) { - return ( -
- {expandIcon || } -
- ); - } - - return <>; - } - - function CollapseButton({ expandableDefaultValue, collapseIcon, shouldExpandNode, setEnableDefaultButton, setShouldExpandNode }: CollapseButtonProps) { - const onCollapse = () => { - setShouldExpandNode('collapse'); - setEnableDefaultButton(true); - } - - const isDefault = !shouldExpandNode ||shouldExpandNode === 'default' - - if (shouldExpandNode === 'expand' ||(isDefault && expandableDefaultValue === 'expand')) { - return ( -
- {collapseIcon || } -
- ); - } - - return <>; - } - - function DefaultButton({defaultIcon, setEnableDefaultButton, setShouldExpandNode }:DefaultButtonProps) { - const onDefaultCollapse = () => { - setShouldExpandNode('default'); - setEnableDefaultButton(false) - } - +function CollapseButton({ + expandableDefaultValue, + collapseIcon, +}: CollapseButtonProps) { + const { shouldExpandNode, setShouldExpandNode, setEnableDefaultButton } = + useExpandableButtonContext(); + + const onCollapse = () => { + setShouldExpandNode('collapse'); + setEnableDefaultButton(true); + }; + + const isDefault = !shouldExpandNode || shouldExpandNode === 'default'; + + if ( + shouldExpandNode === 'expand' || + (isDefault && expandableDefaultValue === 'expand') + ) { return ( -
- {defaultIcon || } +
+ {collapseIcon || }
); - - return <>; } - export default ExpandableButtons \ No newline at end of file + return <>; +} + +function DefaultButton({ defaultIcon }: DefaultButtonProps) { + const { setShouldExpandNode, setEnableDefaultButton } = + useExpandableButtonContext(); + + const onDefaultCollapse = () => { + setShouldExpandNode('default'); + setEnableDefaultButton(false); + }; + + return ( +
+ {defaultIcon || } +
+ ); + + return <>; +} + +export default ExpandableButtons; diff --git a/packages/react-json-tree/src/expandableButtonsContext.tsx b/packages/react-json-tree/src/expandableButtonsContext.tsx new file mode 100644 index 0000000000..b57ca79fd3 --- /dev/null +++ b/packages/react-json-tree/src/expandableButtonsContext.tsx @@ -0,0 +1,50 @@ +import React, { + ReactNode, + createContext, + useContext, + useMemo, + useState, +} from 'react'; +import { Expandable } from '.'; +import ExpandableButtons from './expandableButtons'; + +interface Context { + enableDefaultButton: boolean; + setEnableDefaultButton: any; + shouldExpandNode?: 'expand' | 'collapse' | 'default'; + setShouldExpandNode: any; +} + +interface Props { + children: ReactNode; + expandable?: Expandable; +} + +const ExpandableButtonsContext = createContext({} as Context); + +function ExpandableButtonsContextProvider({ expandable, children }: Props) { + const [enableDefaultButton, setEnableDefaultButton] = useState(false); + const [shouldExpandNode, setShouldExpandNode] = useState(); + + const value = useMemo( + () => ({ + enableDefaultButton, + setEnableDefaultButton, + shouldExpandNode, + setShouldExpandNode, + }), + [enableDefaultButton, shouldExpandNode] + ); + + return ( + + {children} + {expandable && } + + ); +} + +export const useExpandableButtonContext = () => + useContext(ExpandableButtonsContext); + +export default ExpandableButtonsContextProvider; diff --git a/packages/react-json-tree/src/index.tsx b/packages/react-json-tree/src/index.tsx index 9ba8d18b39..5e454db17c 100644 --- a/packages/react-json-tree/src/index.tsx +++ b/packages/react-json-tree/src/index.tsx @@ -3,12 +3,13 @@ // Dave Vedder http://www.eskimospy.com/ // port by Daniele Zannotti http://www.github.com/dzannotti -import React, { ReactNode, useMemo, useState } from 'react'; +import React, { ReactNode, useMemo } from 'react'; import JSONNode from './JSONNode'; import createStylingFromTheme from './createStylingFromTheme'; import { invertTheme } from 'react-base16-styling'; import type { StylingValue, Theme } from 'react-base16-styling'; -import ExpandableButtons from './expandableButtons' +import ExpandableButtonsContext from './expandableButtonsContext'; + import type { CommonExternalProps, GetItemString, @@ -58,9 +59,6 @@ export function JSONTree({ collectionLimit = 50, sortObjectKeys = false, }: Props) { - const [enableDefaultButton, setEnableDefaultButton] = useState(false); - const [shouldExpandNode, setShouldExpandNode] = useState(); - const styling = useMemo( () => createStylingFromTheme(shouldInvertTheme ? invertTheme(theme) : theme), @@ -69,31 +67,22 @@ export function JSONTree({ return (
    - - - + + +
); } diff --git a/packages/react-json-tree/src/types.ts b/packages/react-json-tree/src/types.ts index 71943a35b2..6a67f376c9 100644 --- a/packages/react-json-tree/src/types.ts +++ b/packages/react-json-tree/src/types.ts @@ -53,8 +53,6 @@ export interface CommonExternalProps { isCustomNode: IsCustomNode; collectionLimit: number; sortObjectKeys: SortObjectKeys; - setEnableDefaultButton: any; - setShouldExpandNode: any; } export interface CommonInternalProps extends CommonExternalProps { @@ -62,5 +60,4 @@ export interface CommonInternalProps extends CommonExternalProps { circularCache?: CircularCache; level?: number; isCircular?: boolean; - shouldExpandNode?: 'expand' | 'collapse' | 'default'; } From 5a6dc0e89f9681360a4802d585eb0e23f48bb1f9 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Sat, 20 May 2023 23:12:02 +0200 Subject: [PATCH 12/24] fix handle of the default value --- packages/react-json-tree/src/expandableButtons.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-json-tree/src/expandableButtons.tsx b/packages/react-json-tree/src/expandableButtons.tsx index 5c56a12b78..cbf909bc89 100644 --- a/packages/react-json-tree/src/expandableButtons.tsx +++ b/packages/react-json-tree/src/expandableButtons.tsx @@ -77,7 +77,7 @@ function ExpandButton({ if ( shouldExpandNode === 'collapse' || - (isDefault && expandableDefaultValue === 'collapse') + (isDefault && expandableDefaultValue === 'expand') ) { return (
@@ -105,7 +105,7 @@ function CollapseButton({ if ( shouldExpandNode === 'expand' || - (isDefault && expandableDefaultValue === 'expand') + (isDefault && expandableDefaultValue === 'collapse') ) { return (
From 0680165debbf6c2657d8320919de2f63f789b800 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Sun, 21 May 2023 22:25:45 +0200 Subject: [PATCH 13/24] add position relative as style for tree --- packages/react-json-tree/src/createStylingFromTheme.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-json-tree/src/createStylingFromTheme.ts b/packages/react-json-tree/src/createStylingFromTheme.ts index 5c776c7e85..0500f238fa 100644 --- a/packages/react-json-tree/src/createStylingFromTheme.ts +++ b/packages/react-json-tree/src/createStylingFromTheme.ts @@ -46,6 +46,7 @@ const getDefaultThemeStyling = (theme: Base16Theme): StylingConfig => { return { tree: { + position: 'relative', border: 0, padding: 0, marginTop: '0.5em', From 4574eb0c6261c3f67659ced1ee3b70913234cff4 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Mon, 22 May 2023 12:29:08 +0200 Subject: [PATCH 14/24] implement solution using useRef --- .../react-json-tree/src/JSONNestedNode.tsx | 61 ++++++++++--------- .../src/createStylingFromTheme.ts | 13 ++++ .../react-json-tree/src/expandableButtons.tsx | 17 ++---- .../src/expandableButtonsContext.tsx | 6 +- packages/react-json-tree/src/index.tsx | 2 +- packages/react-json-tree/test/index.spec.tsx | 4 +- 6 files changed, 57 insertions(+), 46 deletions(-) diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index c05c387841..f4492484d5 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useRef, useState } from 'react'; import ItemRange from './ItemRange'; import JSONArrow from './JSONArrow'; import JSONNode from './JSONNode'; @@ -113,47 +113,52 @@ export default function JSONNestedNode(props: Props) { shouldExpandNodeInitially, styling, } = props; - - const { shouldExpandNode, setShouldExpandNode, setEnableDefaultButton } = + const { shouldExpandNode, setEnableDefaultButton, setShouldExpandNode } = useExpandableButtonContext(); - const [expanded, setExpanded] = useState( + const [defaultExpanded] = useState( // calculate individual node expansion if necessary - isCircular ? false : shouldExpandNodeInitially(keyPath, data, level) + isCircular + ? false + : (function getDefault(){ + switch (shouldExpandNode) { + case 'expand': return true; + case 'collapse': return false; + default: return shouldExpandNodeInitially(keyPath, data, level); + } + })() ); - const defaultExpanded = shouldExpandNodeInitially(keyPath, data, level); - - useEffect(() => { - switch (shouldExpandNode) { - case 'expand': - setExpanded(true); - break; - case 'collapse': - setExpanded(false); - break; - case 'default': - setExpanded(defaultExpanded); - break; - default: // Do nothing - } - }, [defaultExpanded, shouldExpandNode]); + const [, setTriggerReRender] = useState(defaultExpanded); + + /** + * Used the useRef to handle expanded because calling a setState in a recursive implementation + * could lead to a "Maximum update depth exceeded" error */ + const expandedRef = useRef(defaultExpanded) + + switch (shouldExpandNode) { + case 'expand': expandedRef.current = isCircular ? false : true; break; + case 'collapse': expandedRef.current = false; break; + case 'default': expandedRef.current = defaultExpanded; break; + default: //Do nothing; + } const handleClick = useCallback(() => { if (expandable) { - setExpanded(!expanded); + expandedRef.current = !expandedRef.current + setTriggerReRender((e) => !e) setEnableDefaultButton(true); - setShouldExpandNode(undefined); + setShouldExpandNode(undefined) } - }, [expandable, expanded, setEnableDefaultButton, setShouldExpandNode]); + }, [expandable, setEnableDefaultButton, setShouldExpandNode]); const renderedChildren = - expanded || (hideRoot && level === 0) + expandedRef.current || (hideRoot && level === 0) ? renderChildNodes({ ...props, circularCache, level: level + 1 }) : null; const itemType = ( - + {nodeTypeIndicator} ); @@ -164,7 +169,7 @@ export default function JSONNestedNode(props: Props) { createItemString(data, collectionLimit), keyPath ); - const stylingArgs = [keyPath, nodeType, expanded, expandable] as const; + const stylingArgs = [keyPath, nodeType, expandedRef.current, expandable] as const; return hideRoot ? (
  • @@ -178,7 +183,7 @@ export default function JSONNestedNode(props: Props) { )} diff --git a/packages/react-json-tree/src/createStylingFromTheme.ts b/packages/react-json-tree/src/createStylingFromTheme.ts index 0500f238fa..189f565113 100644 --- a/packages/react-json-tree/src/createStylingFromTheme.ts +++ b/packages/react-json-tree/src/createStylingFromTheme.ts @@ -58,6 +58,19 @@ const getDefaultThemeStyling = (theme: Base16Theme): StylingConfig => { WebkitUserSelect: 'none', backgroundColor: colors.BACKGROUND_COLOR, }, + + expandable: { + color: colors.TEXT_COLOR, + backgroundColor: colors.BACKGROUND_COLOR, + position: 'absolute', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + gap: '1rem', + top: '1rem', + right: '1rem', + cursor: 'pointer', + }, value: ({ style }, nodeType, keyPath) => ({ style: { diff --git a/packages/react-json-tree/src/expandableButtons.tsx b/packages/react-json-tree/src/expandableButtons.tsx index cbf909bc89..8aa66b258d 100644 --- a/packages/react-json-tree/src/expandableButtons.tsx +++ b/packages/react-json-tree/src/expandableButtons.tsx @@ -7,9 +7,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import React, { ReactNode } from 'react'; import { Expandable } from '.'; import { useExpandableButtonContext } from './expandableButtonsContext'; +import { StylingFunction } from 'react-base16-styling'; interface ExpandableButtonsProps { expandable: Expandable; + styling: StylingFunction; } interface ExpandButtonProps { @@ -26,24 +28,13 @@ interface DefaultButtonProps { defaultIcon?: ReactNode; } -function ExpandableButtons({ expandable }: ExpandableButtonsProps) { +function ExpandableButtons({ expandable, styling }: ExpandableButtonsProps) { const { enableDefaultButton } = useExpandableButtonContext(); const expandableDefaultValue = expandable?.defaultValue || 'expand'; return ( -
    +
    {enableDefaultButton && ( )} diff --git a/packages/react-json-tree/src/expandableButtonsContext.tsx b/packages/react-json-tree/src/expandableButtonsContext.tsx index b57ca79fd3..b1a2f82c07 100644 --- a/packages/react-json-tree/src/expandableButtonsContext.tsx +++ b/packages/react-json-tree/src/expandableButtonsContext.tsx @@ -7,6 +7,7 @@ import React, { } from 'react'; import { Expandable } from '.'; import ExpandableButtons from './expandableButtons'; +import { StylingFunction } from 'react-base16-styling'; interface Context { enableDefaultButton: boolean; @@ -18,11 +19,12 @@ interface Context { interface Props { children: ReactNode; expandable?: Expandable; + styling: StylingFunction; } const ExpandableButtonsContext = createContext({} as Context); -function ExpandableButtonsContextProvider({ expandable, children }: Props) { +function ExpandableButtonsContextProvider({ expandable, children, styling }: Props) { const [enableDefaultButton, setEnableDefaultButton] = useState(false); const [shouldExpandNode, setShouldExpandNode] = useState(); @@ -39,7 +41,7 @@ function ExpandableButtonsContextProvider({ expandable, children }: Props) { return ( {children} - {expandable && } + {expandable && } ); } diff --git a/packages/react-json-tree/src/index.tsx b/packages/react-json-tree/src/index.tsx index 5e454db17c..8ed3a09902 100644 --- a/packages/react-json-tree/src/index.tsx +++ b/packages/react-json-tree/src/index.tsx @@ -67,7 +67,7 @@ export function JSONTree({ return (
      - + { const result = render(); expect(result.type).toBe('ul'); - expect(result.props.children[0].type.name).toBe(JSONNode.name); + expect(result.props.children.type.name).toBe(ExpandableButtonsContextProvider.name); }); }); From a4aac76d5a8d9c26f2663e9627463f169c0c6c34 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Mon, 22 May 2023 12:47:55 +0200 Subject: [PATCH 15/24] run prettier --- .../react-json-tree/src/JSONNestedNode.tsx | 50 ++++++++++++------- .../src/createStylingFromTheme.ts | 2 +- .../src/expandableButtonsContext.tsx | 10 +++- packages/react-json-tree/test/index.spec.tsx | 4 +- 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index f4492484d5..38aa299cae 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -118,37 +118,46 @@ export default function JSONNestedNode(props: Props) { const [defaultExpanded] = useState( // calculate individual node expansion if necessary - isCircular - ? false - : (function getDefault(){ + isCircular + ? false + : (function getDefault() { switch (shouldExpandNode) { - case 'expand': return true; - case 'collapse': return false; - default: return shouldExpandNodeInitially(keyPath, data, level); - } - })() + case 'expand': + return true; + case 'collapse': + return false; + default: + return shouldExpandNodeInitially(keyPath, data, level); + } + })() ); const [, setTriggerReRender] = useState(defaultExpanded); /** * Used the useRef to handle expanded because calling a setState in a recursive implementation - * could lead to a "Maximum update depth exceeded" error */ - const expandedRef = useRef(defaultExpanded) - + * could lead to a "Maximum update depth exceeded" error */ + const expandedRef = useRef(defaultExpanded); + switch (shouldExpandNode) { - case 'expand': expandedRef.current = isCircular ? false : true; break; - case 'collapse': expandedRef.current = false; break; - case 'default': expandedRef.current = defaultExpanded; break; + case 'expand': + expandedRef.current = isCircular ? false : true; + break; + case 'collapse': + expandedRef.current = false; + break; + case 'default': + expandedRef.current = defaultExpanded; + break; default: //Do nothing; } const handleClick = useCallback(() => { if (expandable) { - expandedRef.current = !expandedRef.current - setTriggerReRender((e) => !e) + expandedRef.current = !expandedRef.current; + setTriggerReRender((e) => !e); setEnableDefaultButton(true); - setShouldExpandNode(undefined) + setShouldExpandNode(undefined); } }, [expandable, setEnableDefaultButton, setShouldExpandNode]); @@ -169,7 +178,12 @@ export default function JSONNestedNode(props: Props) { createItemString(data, collectionLimit), keyPath ); - const stylingArgs = [keyPath, nodeType, expandedRef.current, expandable] as const; + const stylingArgs = [ + keyPath, + nodeType, + expandedRef.current, + expandable, + ] as const; return hideRoot ? (
    • diff --git a/packages/react-json-tree/src/createStylingFromTheme.ts b/packages/react-json-tree/src/createStylingFromTheme.ts index 189f565113..f43b88cfe4 100644 --- a/packages/react-json-tree/src/createStylingFromTheme.ts +++ b/packages/react-json-tree/src/createStylingFromTheme.ts @@ -58,7 +58,7 @@ const getDefaultThemeStyling = (theme: Base16Theme): StylingConfig => { WebkitUserSelect: 'none', backgroundColor: colors.BACKGROUND_COLOR, }, - + expandable: { color: colors.TEXT_COLOR, backgroundColor: colors.BACKGROUND_COLOR, diff --git a/packages/react-json-tree/src/expandableButtonsContext.tsx b/packages/react-json-tree/src/expandableButtonsContext.tsx index b1a2f82c07..41e15f47bc 100644 --- a/packages/react-json-tree/src/expandableButtonsContext.tsx +++ b/packages/react-json-tree/src/expandableButtonsContext.tsx @@ -24,7 +24,11 @@ interface Props { const ExpandableButtonsContext = createContext({} as Context); -function ExpandableButtonsContextProvider({ expandable, children, styling }: Props) { +function ExpandableButtonsContextProvider({ + expandable, + children, + styling, +}: Props) { const [enableDefaultButton, setEnableDefaultButton] = useState(false); const [shouldExpandNode, setShouldExpandNode] = useState(); @@ -41,7 +45,9 @@ function ExpandableButtonsContextProvider({ expandable, children, styling }: Pro return ( {children} - {expandable && } + {expandable && ( + + )} ); } diff --git a/packages/react-json-tree/test/index.spec.tsx b/packages/react-json-tree/test/index.spec.tsx index 3db514ee8b..198975ac9e 100644 --- a/packages/react-json-tree/test/index.spec.tsx +++ b/packages/react-json-tree/test/index.spec.tsx @@ -17,6 +17,8 @@ describe('JSONTree', () => { const result = render(); expect(result.type).toBe('ul'); - expect(result.props.children.type.name).toBe(ExpandableButtonsContextProvider.name); + expect(result.props.children.type.name).toBe( + ExpandableButtonsContextProvider.name + ); }); }); From 032aeb6271410771488b9878fbe49f94e5ad3ee6 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Mon, 22 May 2023 13:11:27 +0200 Subject: [PATCH 16/24] rename variables and update README --- packages/react-json-tree/README.md | 15 ++++++++++++++ .../react-json-tree/src/JSONNestedNode.tsx | 10 +++++----- .../react-json-tree/src/expandableButtons.tsx | 20 +++++++++---------- .../src/expandableButtonsContext.tsx | 12 +++++------ 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/packages/react-json-tree/README.md b/packages/react-json-tree/README.md index 7a55b3e110..100a3c9844 100644 --- a/packages/react-json-tree/README.md +++ b/packages/react-json-tree/README.md @@ -137,6 +137,21 @@ Their full signatures are: - `labelRenderer: function(keyPath, nodeType, expanded, expandable)` - `valueRenderer: function(valueAsString, value, ...keyPath)` +#### Customize Expandable Buttons + +Passing the `expandable` props will activate in the top right corner of the JSONTree component the `expand all/collapse all` buttons. You can pass a JSON to customize the expand all/collapse all icons. The default icons are from [FontAwesome](https://fontawesome.com/). + +```jsx + +``` + #### More Options - `shouldExpandNodeInitially: function(keyPath, data, level)` - determines if node should be expanded when it first renders (root is expanded by default) diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index 38aa299cae..fe16593fc5 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -113,7 +113,7 @@ export default function JSONNestedNode(props: Props) { shouldExpandNodeInitially, styling, } = props; - const { shouldExpandNode, setEnableDefaultButton, setShouldExpandNode } = + const { expandAllState, setExpandAllState, setEnableDefaultButton } = useExpandableButtonContext(); const [defaultExpanded] = useState( @@ -121,7 +121,7 @@ export default function JSONNestedNode(props: Props) { isCircular ? false : (function getDefault() { - switch (shouldExpandNode) { + switch (expandAllState) { case 'expand': return true; case 'collapse': @@ -139,7 +139,7 @@ export default function JSONNestedNode(props: Props) { * could lead to a "Maximum update depth exceeded" error */ const expandedRef = useRef(defaultExpanded); - switch (shouldExpandNode) { + switch (expandAllState) { case 'expand': expandedRef.current = isCircular ? false : true; break; @@ -157,9 +157,9 @@ export default function JSONNestedNode(props: Props) { expandedRef.current = !expandedRef.current; setTriggerReRender((e) => !e); setEnableDefaultButton(true); - setShouldExpandNode(undefined); + setExpandAllState(undefined); } - }, [expandable, setEnableDefaultButton, setShouldExpandNode]); + }, [expandable, setEnableDefaultButton, setExpandAllState]); const renderedChildren = expandedRef.current || (hideRoot && level === 0) diff --git a/packages/react-json-tree/src/expandableButtons.tsx b/packages/react-json-tree/src/expandableButtons.tsx index 8aa66b258d..f6be23a0fe 100644 --- a/packages/react-json-tree/src/expandableButtons.tsx +++ b/packages/react-json-tree/src/expandableButtons.tsx @@ -56,18 +56,18 @@ function ExpandButton({ expandableDefaultValue, expandIcon, }: ExpandButtonProps) { - const { shouldExpandNode, setShouldExpandNode, setEnableDefaultButton } = + const { expandAllState, setExpandAllState, setEnableDefaultButton } = useExpandableButtonContext(); const onExpand = () => { - setShouldExpandNode('expand'); + setExpandAllState('expand'); setEnableDefaultButton(true); }; - const isDefault = !shouldExpandNode || shouldExpandNode === 'default'; + const isDefault = !expandAllState || expandAllState === 'default'; if ( - shouldExpandNode === 'collapse' || + expandAllState === 'collapse' || (isDefault && expandableDefaultValue === 'expand') ) { return ( @@ -84,18 +84,18 @@ function CollapseButton({ expandableDefaultValue, collapseIcon, }: CollapseButtonProps) { - const { shouldExpandNode, setShouldExpandNode, setEnableDefaultButton } = + const { expandAllState, setExpandAllState, setEnableDefaultButton } = useExpandableButtonContext(); const onCollapse = () => { - setShouldExpandNode('collapse'); + setExpandAllState('collapse'); setEnableDefaultButton(true); }; - const isDefault = !shouldExpandNode || shouldExpandNode === 'default'; + const isDefault = !expandAllState || expandAllState === 'default'; if ( - shouldExpandNode === 'expand' || + expandAllState === 'expand' || (isDefault && expandableDefaultValue === 'collapse') ) { return ( @@ -109,11 +109,11 @@ function CollapseButton({ } function DefaultButton({ defaultIcon }: DefaultButtonProps) { - const { setShouldExpandNode, setEnableDefaultButton } = + const { setExpandAllState, setEnableDefaultButton } = useExpandableButtonContext(); const onDefaultCollapse = () => { - setShouldExpandNode('default'); + setExpandAllState('default'); setEnableDefaultButton(false); }; diff --git a/packages/react-json-tree/src/expandableButtonsContext.tsx b/packages/react-json-tree/src/expandableButtonsContext.tsx index 41e15f47bc..38dc6017e8 100644 --- a/packages/react-json-tree/src/expandableButtonsContext.tsx +++ b/packages/react-json-tree/src/expandableButtonsContext.tsx @@ -12,8 +12,8 @@ import { StylingFunction } from 'react-base16-styling'; interface Context { enableDefaultButton: boolean; setEnableDefaultButton: any; - shouldExpandNode?: 'expand' | 'collapse' | 'default'; - setShouldExpandNode: any; + expandAllState?: 'expand' | 'collapse' | 'default'; + setExpandAllState: any; } interface Props { @@ -30,16 +30,16 @@ function ExpandableButtonsContextProvider({ styling, }: Props) { const [enableDefaultButton, setEnableDefaultButton] = useState(false); - const [shouldExpandNode, setShouldExpandNode] = useState(); + const [expandAllState, setExpandAllState] = useState(); const value = useMemo( () => ({ enableDefaultButton, setEnableDefaultButton, - shouldExpandNode, - setShouldExpandNode, + expandAllState, + setExpandAllState, }), - [enableDefaultButton, shouldExpandNode] + [enableDefaultButton, expandAllState] ); return ( From 6a125af9087d72d503674b6a2f176572799245b2 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Mon, 22 May 2023 14:36:06 +0200 Subject: [PATCH 17/24] refactor variables names and files names --- packages/react-json-tree/README.md | 6 ++-- .../react-json-tree/src/JSONNestedNode.tsx | 4 +-- ...eButtons.tsx => expandCollapseButtons.tsx} | 30 +++++++++---------- ...sContext.tsx => expandCollapseContext.tsx} | 29 ++++++++++-------- packages/react-json-tree/src/index.tsx | 17 ++++++----- packages/react-json-tree/test/index.spec.tsx | 6 ++-- 6 files changed, 48 insertions(+), 44 deletions(-) rename packages/react-json-tree/src/{expandableButtons.tsx => expandCollapseButtons.tsx} (75%) rename packages/react-json-tree/src/{expandableButtonsContext.tsx => expandCollapseContext.tsx} (55%) diff --git a/packages/react-json-tree/README.md b/packages/react-json-tree/README.md index 100a3c9844..7577d62f8b 100644 --- a/packages/react-json-tree/README.md +++ b/packages/react-json-tree/README.md @@ -137,13 +137,13 @@ Their full signatures are: - `labelRenderer: function(keyPath, nodeType, expanded, expandable)` - `valueRenderer: function(valueAsString, value, ...keyPath)` -#### Customize Expandable Buttons +#### Customize "Expand All/Collapse All" Buttons -Passing the `expandable` props will activate in the top right corner of the JSONTree component the `expand all/collapse all` buttons. You can pass a JSON to customize the expand all/collapse all icons. The default icons are from [FontAwesome](https://fontawesome.com/). +Passing the `expandCollapseAll` props will activate in the top right corner of the JSONTree component the `expand all/collapse all` buttons. You can pass a JSON to customize the expand all/collapse all icons. The default icons are from [FontAwesome](https://fontawesome.com/). ```jsx ( // calculate individual node expansion if necessary diff --git a/packages/react-json-tree/src/expandableButtons.tsx b/packages/react-json-tree/src/expandCollapseButtons.tsx similarity index 75% rename from packages/react-json-tree/src/expandableButtons.tsx rename to packages/react-json-tree/src/expandCollapseButtons.tsx index f6be23a0fe..8031856402 100644 --- a/packages/react-json-tree/src/expandableButtons.tsx +++ b/packages/react-json-tree/src/expandCollapseButtons.tsx @@ -5,12 +5,12 @@ import { } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import React, { ReactNode } from 'react'; -import { Expandable } from '.'; -import { useExpandableButtonContext } from './expandableButtonsContext'; +import { ExpandCollapseAll } from '.'; +import { useExpandCollapseAllContext } from './expandCollapseContext'; import { StylingFunction } from 'react-base16-styling'; -interface ExpandableButtonsProps { - expandable: Expandable; +interface Props { + expandCollapseAll: ExpandCollapseAll; styling: StylingFunction; } @@ -28,25 +28,25 @@ interface DefaultButtonProps { defaultIcon?: ReactNode; } -function ExpandableButtons({ expandable, styling }: ExpandableButtonsProps) { - const { enableDefaultButton } = useExpandableButtonContext(); +function ExpandCollapseButtons({ expandCollapseAll, styling }: Props) { + const { enableDefaultButton } = useExpandCollapseAllContext(); - const expandableDefaultValue = expandable?.defaultValue || 'expand'; + const expandableDefaultValue = expandCollapseAll?.defaultValue || 'expand'; return (
      {enableDefaultButton && ( - + )}
      ); @@ -57,7 +57,7 @@ function ExpandButton({ expandIcon, }: ExpandButtonProps) { const { expandAllState, setExpandAllState, setEnableDefaultButton } = - useExpandableButtonContext(); + useExpandCollapseAllContext(); const onExpand = () => { setExpandAllState('expand'); @@ -85,7 +85,7 @@ function CollapseButton({ collapseIcon, }: CollapseButtonProps) { const { expandAllState, setExpandAllState, setEnableDefaultButton } = - useExpandableButtonContext(); + useExpandCollapseAllContext(); const onCollapse = () => { setExpandAllState('collapse'); @@ -110,7 +110,7 @@ function CollapseButton({ function DefaultButton({ defaultIcon }: DefaultButtonProps) { const { setExpandAllState, setEnableDefaultButton } = - useExpandableButtonContext(); + useExpandCollapseAllContext(); const onDefaultCollapse = () => { setExpandAllState('default'); @@ -126,4 +126,4 @@ function DefaultButton({ defaultIcon }: DefaultButtonProps) { return <>; } -export default ExpandableButtons; +export default ExpandCollapseButtons; diff --git a/packages/react-json-tree/src/expandableButtonsContext.tsx b/packages/react-json-tree/src/expandCollapseContext.tsx similarity index 55% rename from packages/react-json-tree/src/expandableButtonsContext.tsx rename to packages/react-json-tree/src/expandCollapseContext.tsx index 38dc6017e8..d1258ef5d1 100644 --- a/packages/react-json-tree/src/expandableButtonsContext.tsx +++ b/packages/react-json-tree/src/expandCollapseContext.tsx @@ -5,8 +5,8 @@ import React, { useMemo, useState, } from 'react'; -import { Expandable } from '.'; -import ExpandableButtons from './expandableButtons'; +import { ExpandCollapseAll } from '.'; +import ExpandCollapseButtons from './expandCollapseButtons'; import { StylingFunction } from 'react-base16-styling'; interface Context { @@ -18,14 +18,14 @@ interface Context { interface Props { children: ReactNode; - expandable?: Expandable; + expandCollapseAll?: ExpandCollapseAll; styling: StylingFunction; } -const ExpandableButtonsContext = createContext({} as Context); +const ExpandCollapseAllContext = createContext({} as Context); -function ExpandableButtonsContextProvider({ - expandable, +function ExpandCollapseAllContextProvider({ + expandCollapseAll, children, styling, }: Props) { @@ -43,16 +43,19 @@ function ExpandableButtonsContextProvider({ ); return ( - + {children} - {expandable && ( - + {expandCollapseAll && ( + )} - + ); } -export const useExpandableButtonContext = () => - useContext(ExpandableButtonsContext); +export const useExpandCollapseAllContext = () => + useContext(ExpandCollapseAllContext); -export default ExpandableButtonsContextProvider; +export default ExpandCollapseAllContextProvider; diff --git a/packages/react-json-tree/src/index.tsx b/packages/react-json-tree/src/index.tsx index 8ed3a09902..0af44436bc 100644 --- a/packages/react-json-tree/src/index.tsx +++ b/packages/react-json-tree/src/index.tsx @@ -8,7 +8,7 @@ import JSONNode from './JSONNode'; import createStylingFromTheme from './createStylingFromTheme'; import { invertTheme } from 'react-base16-styling'; import type { StylingValue, Theme } from 'react-base16-styling'; -import ExpandableButtonsContext from './expandableButtonsContext'; +import ExpandCollapseAllButtonsContext from './expandCollapseContext'; import type { CommonExternalProps, @@ -22,10 +22,10 @@ interface Props extends Partial { data: unknown; theme?: Theme; invertTheme?: boolean; - expandable?: Expandable; + expandCollapseAll?: ExpandCollapseAll; } -interface Expandable { +interface ExpandCollapseAll { defaultValue?: 'expand' | 'collapse'; expandIcon?: ReactNode; collapseIcon?: ReactNode; @@ -51,7 +51,7 @@ export function JSONTree({ labelRenderer = defaultLabelRenderer, valueRenderer = identity, shouldExpandNodeInitially = expandRootNode, - expandable, + expandCollapseAll, hideRoot = false, getItemString = defaultItemString, postprocessValue = identity, @@ -67,7 +67,10 @@ export function JSONTree({ return (
        - + - +
      ); } @@ -100,4 +103,4 @@ export type { Styling, CommonExternalProps, } from './types'; -export type { Expandable, StylingValue }; +export type { ExpandCollapseAll, StylingValue }; diff --git a/packages/react-json-tree/test/index.spec.tsx b/packages/react-json-tree/test/index.spec.tsx index 198975ac9e..136b64a974 100644 --- a/packages/react-json-tree/test/index.spec.tsx +++ b/packages/react-json-tree/test/index.spec.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { createRenderer } from 'react-test-renderer/shallow'; import { JSONTree } from '../src/index'; -import ExpandableButtonsContextProvider from '../src/expandableButtonsContext'; +import ExpandCollapseAllContext from '../src/expandCollapseContext'; const BASIC_DATA = { a: 1, b: 'c' }; @@ -17,8 +17,6 @@ describe('JSONTree', () => { const result = render(); expect(result.type).toBe('ul'); - expect(result.props.children.type.name).toBe( - ExpandableButtonsContextProvider.name - ); + expect(result.props.children.type.name).toBe(ExpandCollapseAllContext.name); }); }); From 61e526d3f560eac3ae908fb3b5d76fb17b9a26d1 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Mon, 22 May 2023 14:53:03 +0200 Subject: [PATCH 18/24] rename style --- .../react-json-tree/examples/package.json | 2 +- packages/react-json-tree/examples/src/App.tsx | 73 +- .../examples/src/very-deep-json.ts | 3532 +++++++++++++++++ .../src/createStylingFromTheme.ts | 2 +- .../src/expandCollapseButtons.tsx | 2 +- 5 files changed, 3540 insertions(+), 71 deletions(-) create mode 100644 packages/react-json-tree/examples/src/very-deep-json.ts diff --git a/packages/react-json-tree/examples/package.json b/packages/react-json-tree/examples/package.json index af9b7394d1..883e2616b7 100644 --- a/packages/react-json-tree/examples/package.json +++ b/packages/react-json-tree/examples/package.json @@ -23,7 +23,7 @@ "react": "^18.2.0", "react-base16-styling": "^0.9.1", "react-dom": "^18.2.0", - "react-json-tree": "^0.18.0" + "react-json-tree": "link:.." }, "devDependencies": { "@babel/core": "^7.21.4", diff --git a/packages/react-json-tree/examples/src/App.tsx b/packages/react-json-tree/examples/src/App.tsx index a972ce5888..c3fd4885a6 100644 --- a/packages/react-json-tree/examples/src/App.tsx +++ b/packages/react-json-tree/examples/src/App.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { Map } from 'immutable'; import { JSONTree, StylingValue } from 'react-json-tree'; +import veryDeepJson from './very-deep-json'; const getLabelStyle: StylingValue = ({ style }, nodeType, expanded) => ({ style: { @@ -127,77 +128,13 @@ const theme = { const App = () => (
      - -
      -

      Dark Theme

      - -
      -

      Hidden Root

      - -
      -

      Base16 Greenscreen Theme

      - -

      Inverted Theme

      - -
      -

      Style Customization

      -
        -
      • - Label changes between uppercase/lowercase based on the expanded state. -
      • -
      • Array keys are styled based on their parity.
      • -
      • - The labels of objects, arrays, and iterables are customized as "// - type". -
      • -
      • See code for details.
      • -
      +

      Very deep JSON

      -
      -

      More Fine Grained Rendering

      -

      - Pass labelRenderer or valueRenderer. -

      -
      - (({raw})):} - valueRenderer={(raw) => ( - - - 😐 - {' '} - {raw as string}{' '} - - 😐 - - - )} - /> -
      -

      - Sort object keys with sortObjectKeys prop. -

      -
      - -
      -

      Collapsed root node

      -
      - false} + expandCollapseAll={{ defaultValue: 'expand' }} + shouldExpandNodeInitially={(_, __, level) => level < 3} />
      diff --git a/packages/react-json-tree/examples/src/very-deep-json.ts b/packages/react-json-tree/examples/src/very-deep-json.ts new file mode 100644 index 0000000000..1e164ae238 --- /dev/null +++ b/packages/react-json-tree/examples/src/very-deep-json.ts @@ -0,0 +1,3532 @@ +// https://onlinetools.com/random/generate-random-json +export default { + fields: [ + { default: null, name: 'addition', type: ['null', 'string'] }, + { default: null, name: 'brother', type: ['null', 'string'] }, + { default: null, name: 'company', type: ['null', 'string'] }, + { + default: null, + name: 'friend', + type: [ + 'null', + { + fields: [ + { default: null, name: 'barn', type: ['null', 'string'] }, + { default: null, name: 'brush', type: ['null', 'string'] }, + { default: null, name: 'does', type: ['null', 'string'] }, + { default: null, name: 'glad', type: ['null', 'string'] }, + { + default: null, + name: 'keep', + type: [ + 'null', + { + fields: [ + { default: null, name: 'bell', type: ['null', 'string'] }, + { default: null, name: 'case', type: ['null', 'string'] }, + { default: null, name: 'chest', type: ['null', 'string'] }, + { default: null, name: 'done', type: ['null', 'string'] }, + { default: null, name: 'dress', type: ['null', 'string'] }, + { + default: null, + name: 'further', + type: ['null', 'string'], + }, + { default: null, name: 'jungle', type: ['null', 'string'] }, + { default: null, name: 'kill', type: ['null', 'string'] }, + { default: null, name: 'map', type: ['null', 'string'] }, + { + default: null, + name: 'putting', + type: ['null', 'string'], + }, + { + default: null, + name: 'seven', + type: [ + 'null', + { + fields: [ + { + default: null, + name: 'brick', + type: ['null', 'string'], + }, + { + default: null, + name: 'chamber', + type: ['null', 'string'], + }, + { + default: null, + name: 'church', + type: ['null', 'string'], + }, + { + default: null, + name: 'evening', + type: ['null', 'string'], + }, + { + default: null, + name: 'jump', + type: ['null', 'string'], + }, + { + default: null, + name: 'lesson', + type: ['null', 'string'], + }, + { + default: null, + name: 'library', + type: ['null', 'string'], + }, + { + default: null, + name: 'out', + type: ['null', 'string'], + }, + { + default: null, + name: 'population', + type: ['null', 'string'], + }, + { + default: null, + name: 'problem', + type: ['null', 'string'], + }, + { + default: null, + name: 'proud', + type: ['null', 'string'], + }, + { + default: null, + name: 'ride', + type: ['null', 'string'], + }, + { + default: null, + name: 'same', + type: ['null', 'string'], + }, + { + default: null, + name: 'saved', + type: ['null', 'string'], + }, + { + default: null, + name: 'strike', + type: ['null', 'string'], + }, + { + default: null, + name: 'student', + type: [ + 'null', + { + fields: [ + { + default: null, + name: 'careful', + type: ['null', 'string'], + }, + { + default: null, + name: 'hungry', + type: ['null', 'string'], + }, + { + default: null, + name: 'large', + type: ['null', 'string'], + }, + { + default: null, + name: 'line', + type: [ + 'null', + { + fields: [ + { + default: null, + name: 'breeze', + type: ['null', 'string'], + }, + { + default: null, + name: 'brother', + type: ['null', 'string'], + }, + { + default: null, + name: 'carbon', + type: ['null', 'string'], + }, + { + default: null, + name: 'cook', + type: ['null', 'string'], + }, + { + default: null, + name: 'famous', + type: ['null', 'string'], + }, + { + default: null, + name: 'flag', + type: [ + 'null', + { + fields: [ + { + default: null, + name: 'automobile', + type: ['null', 'string'], + }, + { + default: null, + name: 'figure', + type: ['null', 'string'], + }, + { + default: null, + name: 'frighten', + type: ['null', 'string'], + }, + { + default: null, + name: 'gone', + type: ['null', 'string'], + }, + { + default: null, + name: 'hollow', + type: ['null', 'string'], + }, + { + default: null, + name: 'mostly', + type: ['null', 'string'], + }, + { + default: null, + name: 'plain', + type: ['null', 'string'], + }, + { + default: null, + name: 'strength', + type: ['null', 'string'], + }, + { + default: null, + name: 'than', + type: ['null', 'string'], + }, + { + default: null, + name: 'white', + type: [ + 'null', + { + fields: [ + { + default: null, + name: 'advice', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'bend', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'calm', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'darkness', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'disappear', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'egg', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'log', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'massage', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'mountain', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'needed', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'origin', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'refer', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'sale', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'spoken', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'strike', + type: [ + 'null', + { + fields: [ + { + default: + null, + name: 'feel', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'being', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'dark', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'dear', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'dollar', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'gasoline', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'golden', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'hit', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'bottom', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'breathing', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'buy', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'by', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'command', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'contrast', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'earlier', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'facing', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'finish', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'gain', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'just', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'land', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'planned', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'ruler', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'wealth', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'without', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'wonderful', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'catch', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'city', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'experience', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'announced', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'chemical', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'children', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'extra', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'angle', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'base', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'blanket', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'clock', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'cut', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'effort', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'lunch', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'accurate', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'ago', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'blow', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'clay', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'closer', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'darkness', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'how', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'laid', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'location', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'property', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'mark', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'property', + type: 'record', + }, + ], + }, + ], + name: 'location', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'new', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'please', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'slave', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'brother', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'coast', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'fewer', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'number', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'shelter', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'silver', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'symbol', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'apart', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'crowd', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'stick', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'bridge', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'chair', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'combination', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'curious', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'death', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'discover', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'grandmother', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'hour', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'island', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'live', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'needed', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'pound', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'select', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'son', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'steel', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'bill', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'dropped', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'he', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'means', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'consonant', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'cutting', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'except', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'forward', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'grew', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'layers', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'quick', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'sat', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'seldom', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'select', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'shake', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'arrange', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'bend', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'citizen', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'closely', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'door', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'fellow', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'hay', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'leather', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'leaving', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'actually', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'applied', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'at', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'choose', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'forest', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'hit', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'library', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'anything', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'century', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'fall', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'familiar', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'ring', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'familiar', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'happy', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'necessary', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'activity', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'additional', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'brush', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'cross', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'eight', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'final', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'gain', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'grow', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'involved', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'loose', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'myself', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'occur', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'possible', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'rate', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'scale', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'castle', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'condition', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'dead', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'enjoy', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'event', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'home', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'industry', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'baby', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'matter', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'parts', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'possibly', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'stand', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'bar', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'else', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'create', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'home', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'material', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'military', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'dig', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'four', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'has', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'herself', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'manufacturing', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'political', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'read', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'this', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'tonight', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'president', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'tonight', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'tool', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'underline', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'willing', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'activity', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'already', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'appearance', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'castle', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'equator', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'fallen', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'half', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'continent', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'balance', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'bone', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'chest', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'dead', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'describe', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'failed', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'man', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'manner', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'poem', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'principle', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'refer', + type: [ + 'null', + { + fields: + [ + { + default: + null, + name: 'adjective', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'adult', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'alone', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'bent', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'busy', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'couple', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'except', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'fresh', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'gave', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'quite', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'think', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'unusual', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'refer', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'research', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'shake', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'slipped', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'continent', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'first', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'importance', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'is', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'tie', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'half', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'hang', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'labor', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'no', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'position', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'solve', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'topic', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'tribe', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'willing', + type: 'record', + }, + ], + }, + ], + name: 'military', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'poem', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'trouble', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'wait', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'else', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'garden', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'hardly', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'individual', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'mighty', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'mission', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'type', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'stand', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'women', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'industry', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'leaving', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'loss', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'part', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'particular', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'poet', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'snow', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'sum', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'scale', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'thing', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'necessary', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'needed', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'no', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'range', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'refer', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'space', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'stream', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'tree', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'library', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'slide', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'slipped', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'struggle', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'universe', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'leaving', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'park', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'wealth', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'shake', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'till', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'trick', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'means', + type: 'record', + }, + ], + }, + ], + name: 'steel', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'team', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'stick', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'strong', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'treated', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'symbol', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'trade', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'slave', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'successful', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'war', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'lunch', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'planned', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'slightly', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'tent', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'angle', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'available', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'bee', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'bowl', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'chicken', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'flame', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'kept', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'liquid', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'me', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'middle', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'missing', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'plan', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'pond', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'related', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'rod', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'spin', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'swing', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'there', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'village', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'extra', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'got', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'influence', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'interior', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'it', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'knew', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'oldest', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'other', + type: [ + 'null', + { + fields: + [], + name: 'other', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'pull', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'quietly', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'rough', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'stepped', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'tongue', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'younger', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'experience', + type: 'record', + }, + ], + }, + ], + name: 'city', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'fair', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'gate', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'material', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'men', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'musical', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'paid', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'particularly', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'pig', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'rise', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'shall', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'slope', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'wonderful', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'zero', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'hit', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'leader', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'member', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'my', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'over', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'plain', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'real', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'same', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'shoe', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'soldier', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'wood', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'feel', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'figure', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'floor', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'flow', + type: [ + 'null', + { + fields: + [], + name: 'flow', + type: 'record', + }, + ], + }, + { + default: + null, + name: 'gone', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'hunter', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'kept', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'kids', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'shallow', + type: [ + 'null', + 'string', + ], + }, + { + default: + null, + name: 'valuable', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'strike', + type: 'record', + }, + ], + }, + { + default: null, + name: 'tell', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'unit', + type: [ + 'null', + 'string', + ], + }, + { + default: null, + name: 'wild', + type: [ + 'null', + 'string', + ], + }, + ], + name: 'white', + type: 'record', + }, + ], + }, + { + default: null, + name: 'wonder', + type: ['null', 'string'], + }, + ], + name: 'flag', + type: 'record', + }, + ], + }, + { + default: null, + name: 'frog', + type: ['null', 'string'], + }, + { + default: null, + name: 'lift', + type: ['null', 'string'], + }, + { + default: null, + name: 'married', + type: [ + 'null', + { + fields: [], + name: 'married', + type: 'record', + }, + ], + }, + { + default: null, + name: 'police', + type: ['null', 'string'], + }, + { + default: null, + name: 'printed', + type: ['null', 'string'], + }, + { + default: null, + name: 'reader', + type: ['null', 'string'], + }, + { + default: null, + name: 'science', + type: ['null', 'string'], + }, + { + default: null, + name: 'sing', + type: ['null', 'string'], + }, + { + default: null, + name: 'somewhere', + type: ['null', 'string'], + }, + { + default: null, + name: 'wolf', + type: ['null', 'string'], + }, + ], + name: 'line', + type: 'record', + }, + ], + }, + { + default: null, + name: 'manufacturing', + type: ['null', 'string'], + }, + { + default: null, + name: 'price', + type: ['null', 'string'], + }, + { + default: null, + name: 'smaller', + type: ['null', 'string'], + }, + { + default: null, + name: 'struggle', + type: ['null', 'string'], + }, + ], + name: 'student', + type: 'record', + }, + ], + }, + { + default: null, + name: 'tail', + type: ['null', 'string'], + }, + { + default: null, + name: 'went', + type: ['null', 'string'], + }, + { + default: null, + name: 'writing', + type: ['null', 'string'], + }, + ], + name: 'seven', + type: 'record', + }, + ], + }, + { default: null, name: 'star', type: ['null', 'string'] }, + { + default: null, + name: 'station', + type: ['null', 'string'], + }, + ], + name: 'keep', + type: 'record', + }, + ], + }, + { default: null, name: 'kept', type: ['null', 'string'] }, + { default: null, name: 'plenty', type: ['null', 'string'] }, + { default: null, name: 'pool', type: ['null', 'string'] }, + { default: null, name: 'road', type: ['null', 'string'] }, + { default: null, name: 'taken', type: ['null', 'string'] }, + ], + name: 'friend', + type: 'record', + }, + ], + }, + { default: null, name: 'stood', type: ['null', 'string'] }, + { default: null, name: 'they', type: ['null', 'string'] }, + { default: null, name: 'trade', type: ['null', 'string'] }, + ], + name: 'veryDeepJson', + type: 'record', +}; diff --git a/packages/react-json-tree/src/createStylingFromTheme.ts b/packages/react-json-tree/src/createStylingFromTheme.ts index f43b88cfe4..2be9fe2f59 100644 --- a/packages/react-json-tree/src/createStylingFromTheme.ts +++ b/packages/react-json-tree/src/createStylingFromTheme.ts @@ -59,7 +59,7 @@ const getDefaultThemeStyling = (theme: Base16Theme): StylingConfig => { backgroundColor: colors.BACKGROUND_COLOR, }, - expandable: { + expandCollapseAll: { color: colors.TEXT_COLOR, backgroundColor: colors.BACKGROUND_COLOR, position: 'absolute', diff --git a/packages/react-json-tree/src/expandCollapseButtons.tsx b/packages/react-json-tree/src/expandCollapseButtons.tsx index 8031856402..bcaab8f96a 100644 --- a/packages/react-json-tree/src/expandCollapseButtons.tsx +++ b/packages/react-json-tree/src/expandCollapseButtons.tsx @@ -34,7 +34,7 @@ function ExpandCollapseButtons({ expandCollapseAll, styling }: Props) { const expandableDefaultValue = expandCollapseAll?.defaultValue || 'expand'; return ( -
      +
      {enableDefaultButton && ( )} From 63b691a264a647389f16545d1676e4db25e7f9ad Mon Sep 17 00:00:00 2001 From: lucataglia Date: Mon, 22 May 2023 15:05:55 +0200 Subject: [PATCH 19/24] revert example --- packages/react-json-tree/examples/src/App.tsx | 73 +- .../examples/src/very-deep-json.ts | 3532 ----------------- 2 files changed, 68 insertions(+), 3537 deletions(-) delete mode 100644 packages/react-json-tree/examples/src/very-deep-json.ts diff --git a/packages/react-json-tree/examples/src/App.tsx b/packages/react-json-tree/examples/src/App.tsx index c3fd4885a6..a972ce5888 100644 --- a/packages/react-json-tree/examples/src/App.tsx +++ b/packages/react-json-tree/examples/src/App.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { Map } from 'immutable'; import { JSONTree, StylingValue } from 'react-json-tree'; -import veryDeepJson from './very-deep-json'; const getLabelStyle: StylingValue = ({ style }, nodeType, expanded) => ({ style: { @@ -128,13 +127,77 @@ const theme = { const App = () => (
      -

      Very deep JSON

      + +
      +

      Dark Theme

      + +
      +

      Hidden Root

      + +
      +

      Base16 Greenscreen Theme

      + +

      Inverted Theme

      + +
      +

      Style Customization

      +
        +
      • + Label changes between uppercase/lowercase based on the expanded state. +
      • +
      • Array keys are styled based on their parity.
      • +
      • + The labels of objects, arrays, and iterables are customized as "// + type". +
      • +
      • See code for details.
      • +
      +
      +

      More Fine Grained Rendering

      +

      + Pass labelRenderer or valueRenderer. +

      +
      + (({raw})):} + valueRenderer={(raw) => ( + + + 😐 + {' '} + {raw as string}{' '} + + 😐 + + + )} + /> +
      +

      + Sort object keys with sortObjectKeys prop. +

      +
      + +
      +

      Collapsed root node

      +
      + level < 3} + shouldExpandNodeInitially={() => false} />
      diff --git a/packages/react-json-tree/examples/src/very-deep-json.ts b/packages/react-json-tree/examples/src/very-deep-json.ts deleted file mode 100644 index 1e164ae238..0000000000 --- a/packages/react-json-tree/examples/src/very-deep-json.ts +++ /dev/null @@ -1,3532 +0,0 @@ -// https://onlinetools.com/random/generate-random-json -export default { - fields: [ - { default: null, name: 'addition', type: ['null', 'string'] }, - { default: null, name: 'brother', type: ['null', 'string'] }, - { default: null, name: 'company', type: ['null', 'string'] }, - { - default: null, - name: 'friend', - type: [ - 'null', - { - fields: [ - { default: null, name: 'barn', type: ['null', 'string'] }, - { default: null, name: 'brush', type: ['null', 'string'] }, - { default: null, name: 'does', type: ['null', 'string'] }, - { default: null, name: 'glad', type: ['null', 'string'] }, - { - default: null, - name: 'keep', - type: [ - 'null', - { - fields: [ - { default: null, name: 'bell', type: ['null', 'string'] }, - { default: null, name: 'case', type: ['null', 'string'] }, - { default: null, name: 'chest', type: ['null', 'string'] }, - { default: null, name: 'done', type: ['null', 'string'] }, - { default: null, name: 'dress', type: ['null', 'string'] }, - { - default: null, - name: 'further', - type: ['null', 'string'], - }, - { default: null, name: 'jungle', type: ['null', 'string'] }, - { default: null, name: 'kill', type: ['null', 'string'] }, - { default: null, name: 'map', type: ['null', 'string'] }, - { - default: null, - name: 'putting', - type: ['null', 'string'], - }, - { - default: null, - name: 'seven', - type: [ - 'null', - { - fields: [ - { - default: null, - name: 'brick', - type: ['null', 'string'], - }, - { - default: null, - name: 'chamber', - type: ['null', 'string'], - }, - { - default: null, - name: 'church', - type: ['null', 'string'], - }, - { - default: null, - name: 'evening', - type: ['null', 'string'], - }, - { - default: null, - name: 'jump', - type: ['null', 'string'], - }, - { - default: null, - name: 'lesson', - type: ['null', 'string'], - }, - { - default: null, - name: 'library', - type: ['null', 'string'], - }, - { - default: null, - name: 'out', - type: ['null', 'string'], - }, - { - default: null, - name: 'population', - type: ['null', 'string'], - }, - { - default: null, - name: 'problem', - type: ['null', 'string'], - }, - { - default: null, - name: 'proud', - type: ['null', 'string'], - }, - { - default: null, - name: 'ride', - type: ['null', 'string'], - }, - { - default: null, - name: 'same', - type: ['null', 'string'], - }, - { - default: null, - name: 'saved', - type: ['null', 'string'], - }, - { - default: null, - name: 'strike', - type: ['null', 'string'], - }, - { - default: null, - name: 'student', - type: [ - 'null', - { - fields: [ - { - default: null, - name: 'careful', - type: ['null', 'string'], - }, - { - default: null, - name: 'hungry', - type: ['null', 'string'], - }, - { - default: null, - name: 'large', - type: ['null', 'string'], - }, - { - default: null, - name: 'line', - type: [ - 'null', - { - fields: [ - { - default: null, - name: 'breeze', - type: ['null', 'string'], - }, - { - default: null, - name: 'brother', - type: ['null', 'string'], - }, - { - default: null, - name: 'carbon', - type: ['null', 'string'], - }, - { - default: null, - name: 'cook', - type: ['null', 'string'], - }, - { - default: null, - name: 'famous', - type: ['null', 'string'], - }, - { - default: null, - name: 'flag', - type: [ - 'null', - { - fields: [ - { - default: null, - name: 'automobile', - type: ['null', 'string'], - }, - { - default: null, - name: 'figure', - type: ['null', 'string'], - }, - { - default: null, - name: 'frighten', - type: ['null', 'string'], - }, - { - default: null, - name: 'gone', - type: ['null', 'string'], - }, - { - default: null, - name: 'hollow', - type: ['null', 'string'], - }, - { - default: null, - name: 'mostly', - type: ['null', 'string'], - }, - { - default: null, - name: 'plain', - type: ['null', 'string'], - }, - { - default: null, - name: 'strength', - type: ['null', 'string'], - }, - { - default: null, - name: 'than', - type: ['null', 'string'], - }, - { - default: null, - name: 'white', - type: [ - 'null', - { - fields: [ - { - default: null, - name: 'advice', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'bend', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'calm', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'darkness', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'disappear', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'egg', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'log', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'massage', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'mountain', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'needed', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'origin', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'refer', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'sale', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'spoken', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'strike', - type: [ - 'null', - { - fields: [ - { - default: - null, - name: 'feel', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'being', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'dark', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'dear', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'dollar', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'gasoline', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'golden', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'hit', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'bottom', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'breathing', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'buy', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'by', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'command', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'contrast', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'earlier', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'facing', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'finish', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'gain', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'just', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'land', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'planned', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'ruler', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'wealth', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'without', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'wonderful', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'catch', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'city', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'experience', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'announced', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'chemical', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'children', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'extra', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'angle', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'base', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'blanket', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'clock', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'cut', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'effort', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'lunch', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'accurate', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'ago', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'blow', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'clay', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'closer', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'darkness', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'how', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'laid', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'location', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'property', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'mark', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'property', - type: 'record', - }, - ], - }, - ], - name: 'location', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'new', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'please', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'slave', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'brother', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'coast', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'fewer', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'number', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'shelter', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'silver', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'symbol', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'apart', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'crowd', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'stick', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'bridge', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'chair', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'combination', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'curious', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'death', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'discover', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'grandmother', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'hour', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'island', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'live', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'needed', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'pound', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'select', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'son', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'steel', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'bill', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'dropped', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'he', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'means', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'consonant', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'cutting', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'except', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'forward', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'grew', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'layers', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'quick', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'sat', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'seldom', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'select', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'shake', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'arrange', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'bend', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'citizen', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'closely', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'door', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'fellow', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'hay', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'leather', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'leaving', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'actually', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'applied', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'at', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'choose', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'forest', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'hit', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'library', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'anything', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'century', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'fall', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'familiar', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'ring', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'familiar', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'happy', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'necessary', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'activity', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'additional', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'brush', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'cross', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'eight', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'final', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'gain', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'grow', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'involved', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'loose', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'myself', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'occur', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'possible', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'rate', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'scale', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'castle', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'condition', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'dead', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'enjoy', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'event', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'home', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'industry', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'baby', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'matter', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'parts', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'possibly', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'stand', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'bar', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'else', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'create', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'home', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'material', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'military', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'dig', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'four', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'has', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'herself', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'manufacturing', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'political', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'read', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'this', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'tonight', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'president', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'tonight', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'tool', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'underline', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'willing', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'activity', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'already', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'appearance', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'castle', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'equator', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'fallen', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'half', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'continent', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'balance', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'bone', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'chest', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'dead', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'describe', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'failed', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'man', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'manner', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'poem', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'principle', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'refer', - type: [ - 'null', - { - fields: - [ - { - default: - null, - name: 'adjective', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'adult', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'alone', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'bent', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'busy', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'couple', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'except', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'fresh', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'gave', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'quite', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'think', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'unusual', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'refer', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'research', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'shake', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'slipped', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'continent', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'first', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'importance', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'is', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'tie', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'half', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'hang', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'labor', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'no', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'position', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'solve', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'topic', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'tribe', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'willing', - type: 'record', - }, - ], - }, - ], - name: 'military', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'poem', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'trouble', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'wait', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'else', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'garden', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'hardly', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'individual', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'mighty', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'mission', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'type', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'stand', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'women', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'industry', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'leaving', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'loss', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'part', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'particular', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'poet', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'snow', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'sum', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'scale', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'thing', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'necessary', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'needed', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'no', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'range', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'refer', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'space', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'stream', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'tree', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'library', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'slide', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'slipped', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'struggle', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'universe', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'leaving', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'park', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'wealth', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'shake', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'till', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'trick', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'means', - type: 'record', - }, - ], - }, - ], - name: 'steel', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'team', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'stick', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'strong', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'treated', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'symbol', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'trade', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'slave', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'successful', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'war', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'lunch', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'planned', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'slightly', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'tent', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'angle', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'available', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'bee', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'bowl', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'chicken', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'flame', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'kept', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'liquid', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'me', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'middle', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'missing', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'plan', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'pond', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'related', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'rod', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'spin', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'swing', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'there', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'village', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'extra', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'got', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'influence', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'interior', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'it', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'knew', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'oldest', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'other', - type: [ - 'null', - { - fields: - [], - name: 'other', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'pull', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'quietly', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'rough', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'stepped', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'tongue', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'younger', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'experience', - type: 'record', - }, - ], - }, - ], - name: 'city', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'fair', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'gate', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'material', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'men', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'musical', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'paid', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'particularly', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'pig', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'rise', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'shall', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'slope', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'wonderful', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'zero', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'hit', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'leader', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'member', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'my', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'over', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'plain', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'real', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'same', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'shoe', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'soldier', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'wood', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'feel', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'figure', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'floor', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'flow', - type: [ - 'null', - { - fields: - [], - name: 'flow', - type: 'record', - }, - ], - }, - { - default: - null, - name: 'gone', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'hunter', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'kept', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'kids', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'shallow', - type: [ - 'null', - 'string', - ], - }, - { - default: - null, - name: 'valuable', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'strike', - type: 'record', - }, - ], - }, - { - default: null, - name: 'tell', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'unit', - type: [ - 'null', - 'string', - ], - }, - { - default: null, - name: 'wild', - type: [ - 'null', - 'string', - ], - }, - ], - name: 'white', - type: 'record', - }, - ], - }, - { - default: null, - name: 'wonder', - type: ['null', 'string'], - }, - ], - name: 'flag', - type: 'record', - }, - ], - }, - { - default: null, - name: 'frog', - type: ['null', 'string'], - }, - { - default: null, - name: 'lift', - type: ['null', 'string'], - }, - { - default: null, - name: 'married', - type: [ - 'null', - { - fields: [], - name: 'married', - type: 'record', - }, - ], - }, - { - default: null, - name: 'police', - type: ['null', 'string'], - }, - { - default: null, - name: 'printed', - type: ['null', 'string'], - }, - { - default: null, - name: 'reader', - type: ['null', 'string'], - }, - { - default: null, - name: 'science', - type: ['null', 'string'], - }, - { - default: null, - name: 'sing', - type: ['null', 'string'], - }, - { - default: null, - name: 'somewhere', - type: ['null', 'string'], - }, - { - default: null, - name: 'wolf', - type: ['null', 'string'], - }, - ], - name: 'line', - type: 'record', - }, - ], - }, - { - default: null, - name: 'manufacturing', - type: ['null', 'string'], - }, - { - default: null, - name: 'price', - type: ['null', 'string'], - }, - { - default: null, - name: 'smaller', - type: ['null', 'string'], - }, - { - default: null, - name: 'struggle', - type: ['null', 'string'], - }, - ], - name: 'student', - type: 'record', - }, - ], - }, - { - default: null, - name: 'tail', - type: ['null', 'string'], - }, - { - default: null, - name: 'went', - type: ['null', 'string'], - }, - { - default: null, - name: 'writing', - type: ['null', 'string'], - }, - ], - name: 'seven', - type: 'record', - }, - ], - }, - { default: null, name: 'star', type: ['null', 'string'] }, - { - default: null, - name: 'station', - type: ['null', 'string'], - }, - ], - name: 'keep', - type: 'record', - }, - ], - }, - { default: null, name: 'kept', type: ['null', 'string'] }, - { default: null, name: 'plenty', type: ['null', 'string'] }, - { default: null, name: 'pool', type: ['null', 'string'] }, - { default: null, name: 'road', type: ['null', 'string'] }, - { default: null, name: 'taken', type: ['null', 'string'] }, - ], - name: 'friend', - type: 'record', - }, - ], - }, - { default: null, name: 'stood', type: ['null', 'string'] }, - { default: null, name: 'they', type: ['null', 'string'] }, - { default: null, name: 'trade', type: ['null', 'string'] }, - ], - name: 'veryDeepJson', - type: 'record', -}; From becb83393f2a8f9cd2533b065590be028a098f3f Mon Sep 17 00:00:00 2001 From: lucataglia Date: Mon, 22 May 2023 17:24:35 +0200 Subject: [PATCH 20/24] add isExpanded as argument to getItemString method --- packages/react-json-tree/src/JSONNestedNode.tsx | 3 ++- packages/react-json-tree/src/types.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index c38dddd39f..2f03c282cf 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -176,7 +176,8 @@ export default function JSONNestedNode(props: Props) { data, itemType, createItemString(data, collectionLimit), - keyPath + keyPath, + expandedRef.current, ); const stylingArgs = [ keyPath, diff --git a/packages/react-json-tree/src/types.ts b/packages/react-json-tree/src/types.ts index 6a67f376c9..357979eca7 100644 --- a/packages/react-json-tree/src/types.ts +++ b/packages/react-json-tree/src/types.ts @@ -10,7 +10,8 @@ export type GetItemString = ( data: unknown, itemType: React.ReactNode, itemString: string, - keyPath: KeyPath + keyPath: KeyPath, + isExpanded: boolean, ) => React.ReactNode; export type LabelRenderer = ( From 8e07c1d1d373c2c1eb4cbb47410148e5a42da687 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Mon, 22 May 2023 19:11:39 +0200 Subject: [PATCH 21/24] hotfix --- packages/react-json-tree/src/JSONNestedNode.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index 2f03c282cf..2ff408a2cf 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -147,7 +147,7 @@ export default function JSONNestedNode(props: Props) { expandedRef.current = false; break; case 'default': - expandedRef.current = defaultExpanded; + expandedRef.current = shouldExpandNodeInitially(keyPath, data, level); break; default: //Do nothing; } From 25d7b5e8d4a900d027661093df838063ae790ebe Mon Sep 17 00:00:00 2001 From: Luca Tagliabue Date: Wed, 23 Aug 2023 11:24:02 +0200 Subject: [PATCH 22/24] feat: add copyToClipboard button --- packages/react-json-tree/examples/src/App.tsx | 2 +- .../src/expandCollapseButtons.tsx | 41 +++++++++++++++++-- .../src/expandCollapseContext.tsx | 7 +++- packages/react-json-tree/src/index.tsx | 3 ++ 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/packages/react-json-tree/examples/src/App.tsx b/packages/react-json-tree/examples/src/App.tsx index a972ce5888..67b7d1c3c5 100644 --- a/packages/react-json-tree/examples/src/App.tsx +++ b/packages/react-json-tree/examples/src/App.tsx @@ -190,7 +190,7 @@ const App = () => ( Sort object keys with sortObjectKeys prop.

      - +

      Collapsed root node

      diff --git a/packages/react-json-tree/src/expandCollapseButtons.tsx b/packages/react-json-tree/src/expandCollapseButtons.tsx index bcaab8f96a..0f140e2680 100644 --- a/packages/react-json-tree/src/expandCollapseButtons.tsx +++ b/packages/react-json-tree/src/expandCollapseButtons.tsx @@ -2,9 +2,11 @@ import { faArrowDown, faArrowRight, faUndo, + faCopy, + faCheck, } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import React, { ReactNode } from 'react'; +import React, { ReactNode, useState } from 'react'; import { ExpandCollapseAll } from '.'; import { useExpandCollapseAllContext } from './expandCollapseContext'; import { StylingFunction } from 'react-base16-styling'; @@ -12,6 +14,7 @@ import { StylingFunction } from 'react-base16-styling'; interface Props { expandCollapseAll: ExpandCollapseAll; styling: StylingFunction; + value: unknown; } interface ExpandButtonProps { @@ -24,11 +27,17 @@ interface CollapseButtonProps { collapseIcon?: ReactNode; } +interface CopyToClipboardButtonProps { + copyToClipboardIcon?: ReactNode; + copiedToClipboardIcon?: ReactNode; + value: unknown; +} + interface DefaultButtonProps { defaultIcon?: ReactNode; } -function ExpandCollapseButtons({ expandCollapseAll, styling }: Props) { +function ExpandCollapseButtons({ expandCollapseAll, styling, value }: Props) { const { enableDefaultButton } = useExpandCollapseAllContext(); const expandableDefaultValue = expandCollapseAll?.defaultValue || 'expand'; @@ -39,6 +48,12 @@ function ExpandCollapseButtons({ expandCollapseAll, styling }: Props) { )} + + ; } +function CopyToClipboardButton({copyToClipboardIcon, copiedToClipboardIcon, value}:CopyToClipboardButtonProps) { + const [isCopied, setIsCopied] = useState(false); + + const handleOnCopyToClipboard = async () => { + await navigator.clipboard.writeText(JSON.stringify(value, null, 2)); + setIsCopied(true) + } + + if(isCopied){ + return (
      + {copiedToClipboardIcon || } +
      ); + } + + return ( +
      + {copyToClipboardIcon || } +
      ) +} + function DefaultButton({ defaultIcon }: DefaultButtonProps) { const { setExpandAllState, setEnableDefaultButton } = useExpandCollapseAllContext(); @@ -122,8 +157,6 @@ function DefaultButton({ defaultIcon }: DefaultButtonProps) { {defaultIcon || }
      ); - - return <>; } export default ExpandCollapseButtons; diff --git a/packages/react-json-tree/src/expandCollapseContext.tsx b/packages/react-json-tree/src/expandCollapseContext.tsx index d1258ef5d1..0fbc8bf99f 100644 --- a/packages/react-json-tree/src/expandCollapseContext.tsx +++ b/packages/react-json-tree/src/expandCollapseContext.tsx @@ -20,6 +20,7 @@ interface Props { children: ReactNode; expandCollapseAll?: ExpandCollapseAll; styling: StylingFunction; + value: unknown; } const ExpandCollapseAllContext = createContext({} as Context); @@ -28,11 +29,12 @@ function ExpandCollapseAllContextProvider({ expandCollapseAll, children, styling, + value, }: Props) { const [enableDefaultButton, setEnableDefaultButton] = useState(false); const [expandAllState, setExpandAllState] = useState(); - const value = useMemo( + const contextValue = useMemo( () => ({ enableDefaultButton, setEnableDefaultButton, @@ -43,12 +45,13 @@ function ExpandCollapseAllContextProvider({ ); return ( - + {children} {expandCollapseAll && ( )} diff --git a/packages/react-json-tree/src/index.tsx b/packages/react-json-tree/src/index.tsx index 0af44436bc..eb0df18d70 100644 --- a/packages/react-json-tree/src/index.tsx +++ b/packages/react-json-tree/src/index.tsx @@ -29,6 +29,8 @@ interface ExpandCollapseAll { defaultValue?: 'expand' | 'collapse'; expandIcon?: ReactNode; collapseIcon?: ReactNode; + copyToClipboardIcon?: ReactNode; + copiedToClipboardIcon?: ReactNode; defaultIcon?: ReactNode; } @@ -70,6 +72,7 @@ export function JSONTree({ Date: Wed, 23 Aug 2023 11:38:39 +0200 Subject: [PATCH 23/24] feat: add timer to restore copyToClipboard button state --- packages/react-json-tree/src/expandCollapseButtons.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/react-json-tree/src/expandCollapseButtons.tsx b/packages/react-json-tree/src/expandCollapseButtons.tsx index 0f140e2680..eff07219b1 100644 --- a/packages/react-json-tree/src/expandCollapseButtons.tsx +++ b/packages/react-json-tree/src/expandCollapseButtons.tsx @@ -6,7 +6,7 @@ import { faCheck, } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import React, { ReactNode, useState } from 'react'; +import React, { ReactNode, useEffect, useState } from 'react'; import { ExpandCollapseAll } from '.'; import { useExpandCollapseAllContext } from './expandCollapseContext'; import { StylingFunction } from 'react-base16-styling'; @@ -131,6 +131,12 @@ function CopyToClipboardButton({copyToClipboardIcon, copiedToClipboardIcon, valu setIsCopied(true) } + useEffect(() => { + if(isCopied){ + setTimeout(() => setIsCopied(false), 6000) + } + }, [isCopied]) + if(isCopied){ return (
      {copiedToClipboardIcon || } From 2ccdf15bc92d3b1b81333a0f43946c02722cff49 Mon Sep 17 00:00:00 2001 From: lucataglia Date: Wed, 23 Aug 2023 11:42:39 +0200 Subject: [PATCH 24/24] refactor: run yarn format --- packages/react-json-tree/examples/src/App.tsx | 7 ++++- .../react-json-tree/src/JSONNestedNode.tsx | 2 +- .../src/expandCollapseButtons.tsx | 29 ++++++++++++------- packages/react-json-tree/src/types.ts | 2 +- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/packages/react-json-tree/examples/src/App.tsx b/packages/react-json-tree/examples/src/App.tsx index 67b7d1c3c5..8d8f6e9f40 100644 --- a/packages/react-json-tree/examples/src/App.tsx +++ b/packages/react-json-tree/examples/src/App.tsx @@ -190,7 +190,12 @@ const App = () => ( Sort object keys with sortObjectKeys prop.

      - +

      Collapsed root node

      diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index 2ff408a2cf..30f6c464d0 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -177,7 +177,7 @@ export default function JSONNestedNode(props: Props) { itemType, createItemString(data, collectionLimit), keyPath, - expandedRef.current, + expandedRef.current ); const stylingArgs = [ keyPath, diff --git a/packages/react-json-tree/src/expandCollapseButtons.tsx b/packages/react-json-tree/src/expandCollapseButtons.tsx index eff07219b1..e60b9c271f 100644 --- a/packages/react-json-tree/src/expandCollapseButtons.tsx +++ b/packages/react-json-tree/src/expandCollapseButtons.tsx @@ -123,30 +123,37 @@ function CollapseButton({ return <>; } -function CopyToClipboardButton({copyToClipboardIcon, copiedToClipboardIcon, value}:CopyToClipboardButtonProps) { +function CopyToClipboardButton({ + copyToClipboardIcon, + copiedToClipboardIcon, + value, +}: CopyToClipboardButtonProps) { const [isCopied, setIsCopied] = useState(false); const handleOnCopyToClipboard = async () => { await navigator.clipboard.writeText(JSON.stringify(value, null, 2)); - setIsCopied(true) - } + setIsCopied(true); + }; useEffect(() => { - if(isCopied){ - setTimeout(() => setIsCopied(false), 6000) + if (isCopied) { + setTimeout(() => setIsCopied(false), 6000); } - }, [isCopied]) + }, [isCopied]); - if(isCopied){ - return (
      - {copiedToClipboardIcon || } -
      ); + if (isCopied) { + return ( +
      + {copiedToClipboardIcon || } +
      + ); } return (
      {copyToClipboardIcon || } -
      ) +
      + ); } function DefaultButton({ defaultIcon }: DefaultButtonProps) { diff --git a/packages/react-json-tree/src/types.ts b/packages/react-json-tree/src/types.ts index 357979eca7..26894388e2 100644 --- a/packages/react-json-tree/src/types.ts +++ b/packages/react-json-tree/src/types.ts @@ -11,7 +11,7 @@ export type GetItemString = ( itemType: React.ReactNode, itemString: string, keyPath: KeyPath, - isExpanded: boolean, + isExpanded: boolean ) => React.ReactNode; export type LabelRenderer = (