add context

This commit is contained in:
lucataglia 2023-05-20 22:41:59 +02:00
parent e664cba9fb
commit fc0611d750
5 changed files with 195 additions and 143 deletions

View File

@ -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<boolean>(
// 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]);

View File

@ -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 (
<div style={{position: 'absolute', display: 'flex', justifyContent:'center', alignItems: 'center', gap:'1rem', top: '1rem', right: '1rem', cursor: 'pointer'}}>
{enableDefaultButton && <DefaultButton
defaultIcon={expandable?.defaultIcon}
setShouldExpandNode={setShouldExpandNode}
setEnableDefaultButton={setEnableDefaultButton}
/>}
return (
<div
style={{
position: 'absolute',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: '1rem',
top: '1rem',
right: '1rem',
cursor: 'pointer',
}}
>
{enableDefaultButton && (
<DefaultButton defaultIcon={expandable?.defaultIcon} />
)}
<ExpandButton
expandableDefaultValue={expandableDefaultValue}
expandIcon={expandable?.expandIcon}
setShouldExpandNode={setShouldExpandNode}
setEnableDefaultButton={setEnableDefaultButton}
shouldExpandNode={shouldExpandNode}
/>
<ExpandButton
expandableDefaultValue={expandableDefaultValue}
expandIcon={expandable?.expandIcon}
/>
<CollapseButton
expandableDefaultValue={expandable?.defaultValue}
collapseIcon={expandable?.collapseIcon}
setShouldExpandNode={setShouldExpandNode}
setEnableDefaultButton={setEnableDefaultButton}
shouldExpandNode={shouldExpandNode}
/>
</div>
)
<CollapseButton
expandableDefaultValue={expandable?.defaultValue}
collapseIcon={expandable?.collapseIcon}
/>
</div>
);
}
function ExpandButton({ expandableDefaultValue, expandIcon, shouldExpandNode, setEnableDefaultButton, setShouldExpandNode }: ExpandButtonProps) {
const onExpand = () => {
setShouldExpandNode('expand');
setEnableDefaultButton(true);
}
function ExpandButton({
expandableDefaultValue,
expandIcon,
}: ExpandButtonProps) {
const { shouldExpandNode, setShouldExpandNode, setEnableDefaultButton } =
useExpandableButtonContext();
const isDefault = !shouldExpandNode ||shouldExpandNode === 'default'
const onExpand = () => {
setShouldExpandNode('expand');
setEnableDefaultButton(true);
};
if (shouldExpandNode === 'collapse' || (isDefault && expandableDefaultValue === 'collapse')) {
return (
<div role="presentation" onClick={onExpand}>
{expandIcon || <FontAwesomeIcon icon={faArrowRight} />}
</div>
);
}
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 (
<div role="presentation" onClick={onCollapse}>
{collapseIcon || <FontAwesomeIcon icon={faArrowDown} />}
</div>
);
}
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 (
<div role="presentation" onClick={onDefaultCollapse}>
{defaultIcon || <FontAwesomeIcon icon={faUndo} />}
<div role="presentation" onClick={onExpand}>
{expandIcon || <FontAwesomeIcon icon={faArrowRight} />}
</div>
);
return <></>;
}
export default ExpandableButtons
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 (
<div role="presentation" onClick={onCollapse}>
{collapseIcon || <FontAwesomeIcon icon={faArrowDown} />}
</div>
);
}
return <></>;
}
function DefaultButton({ defaultIcon }: DefaultButtonProps) {
const { setShouldExpandNode, setEnableDefaultButton } =
useExpandableButtonContext();
const onDefaultCollapse = () => {
setShouldExpandNode('default');
setEnableDefaultButton(false);
};
return (
<div role="presentation" onClick={onDefaultCollapse}>
{defaultIcon || <FontAwesomeIcon icon={faUndo} />}
</div>
);
return <></>;
}
export default ExpandableButtons;

View File

@ -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<Context>({} 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 (
<ExpandableButtonsContext.Provider value={value}>
{children}
{expandable && <ExpandableButtons expandable={expandable} />}
</ExpandableButtonsContext.Provider>
);
}
export const useExpandableButtonContext = () =>
useContext(ExpandableButtonsContext);
export default ExpandableButtonsContextProvider;

View File

@ -3,12 +3,13 @@
// Dave Vedder <veddermatic@gmail.com> http://www.eskimospy.com/
// port by Daniele Zannotti http://www.github.com/dzannotti <dzannotti@me.com>
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 (
<ul {...styling('tree')}>
<JSONNode
keyPath={hideRoot ? [] : keyPath}
value={postprocessValue(value)}
isCustomNode={isCustomNode}
styling={styling}
labelRenderer={labelRenderer}
valueRenderer={valueRenderer}
shouldExpandNodeInitially={shouldExpandNodeInitially}
shouldExpandNode={shouldExpandNode}
setEnableDefaultButton={setEnableDefaultButton}
setShouldExpandNode={setShouldExpandNode}
hideRoot={hideRoot}
getItemString={getItemString}
postprocessValue={postprocessValue}
collectionLimit={collectionLimit}
sortObjectKeys={sortObjectKeys}
/>
<ExpandableButtons
expandable={expandable}
enableDefaultButton={enableDefaultButton}
setEnableDefaultButton={setEnableDefaultButton}
shouldExpandNode={shouldExpandNode}
setShouldExpandNode={setShouldExpandNode}
/>
<ExpandableButtonsContext expandable={expandable}>
<JSONNode
keyPath={hideRoot ? [] : keyPath}
value={postprocessValue(value)}
isCustomNode={isCustomNode}
styling={styling}
labelRenderer={labelRenderer}
valueRenderer={valueRenderer}
shouldExpandNodeInitially={shouldExpandNodeInitially}
hideRoot={hideRoot}
getItemString={getItemString}
postprocessValue={postprocessValue}
collectionLimit={collectionLimit}
sortObjectKeys={sortObjectKeys}
/>
</ExpandableButtonsContext>
</ul>
);
}

View File

@ -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';
}