diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index fe82a169..c05c3878 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 JSONArrow from './JSONArrow'; -import getCollectionEntries from './getCollectionEntries'; -import JSONNode from './JSONNode'; import ItemRange from './ItemRange'; +import JSONArrow from './JSONArrow'; +import JSONNode from './JSONNode'; +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 99c10e2b..5c56a12b 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 && } + return ( +
+ {enableDefaultButton && ( + + )} - - - -
- ) + + + +
+ ); } -function ExpandButton({ expandableDefaultValue, expandIcon, shouldExpandNode, setEnableDefaultButton, setShouldExpandNode }: ExpandButtonProps) { - const onExpand = () => { - setShouldExpandNode('expand'); - setEnableDefaultButton(true); - } - - const isDefault = !shouldExpandNode ||shouldExpandNode === 'default' +function ExpandButton({ + expandableDefaultValue, + expandIcon, +}: ExpandButtonProps) { + const { shouldExpandNode, setShouldExpandNode, setEnableDefaultButton } = + useExpandableButtonContext(); - 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' + const onExpand = () => { + setShouldExpandNode('expand'); + setEnableDefaultButton(true); + }; - if (shouldExpandNode === 'expand' ||(isDefault && expandableDefaultValue === 'expand')) { - return ( -
- {collapseIcon || } -
- ); - } - - return <>; - } - - function DefaultButton({defaultIcon, setEnableDefaultButton, setShouldExpandNode }:DefaultButtonProps) { - const onDefaultCollapse = () => { - setShouldExpandNode('default'); - setEnableDefaultButton(false) - } - + const isDefault = !shouldExpandNode || shouldExpandNode === 'default'; + + if ( + shouldExpandNode === 'collapse' || + (isDefault && expandableDefaultValue === 'collapse') + ) { return ( -
- {defaultIcon || } +
+ {expandIcon || }
); - - return <>; } - export default ExpandableButtons \ No newline at end of file + return <>; +} + +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 ( +
+ {collapseIcon || } +
+ ); + } + + 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 00000000..b57ca79f --- /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 9ba8d18b..5e454db1 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 71943a35..6a67f376 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'; }