diff --git a/packages/react-json-tree/package.json b/packages/react-json-tree/package.json
index 5190e755..8bee4142 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 265d0c47..6a505adf 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)
);
- useEffect(() => {
- if (shouldExpandNode === undefined) {
- return;
- }
+ const defaultExpanded = shouldExpandNodeInitially(keyPath, data, level);
- setExpanded(shouldExpandNode);
- }, [shouldExpandNode]);
+ useEffect(() => {
+ switch(shouldExpandNode){
+ case 'expand': setExpanded(true); break;
+ case'collapse': setExpanded(false); break;
+ case'default': setExpanded(defaultExpanded); break;
+ default:
+ }
+ }, [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 00000000..a4e4818d
--- /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 48d1ceaa..f3df0b66 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 2bb3981a..048a4086 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 99661291..7f409eda 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);
});
});