Skip to content

Commit c76a9ee

Browse files
committed
fix: fix shouldExpandNodeInitially display bug. #76
1 parent ad4dd2d commit c76a9ee

File tree

9 files changed

+91
-52
lines changed

9 files changed

+91
-52
lines changed

core/README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -911,10 +911,7 @@ export interface JsonViewProps<T extends object> extends React.DetailedHTMLProps
911911
/** When set to true, all nodes will be collapsed by default. Use an integer value to collapse at a particular depth. @default false */
912912
collapsed?: boolean | number;
913913
/** Determine whether the node should be expanded on the first render, or you can use collapsed to control the level of expansion (by default, the root is expanded). */
914-
shouldExpandNodeInitially?: (
915-
isExpanded: boolean,
916-
props: { value?: T; keys: (number | string)[]; level: number },
917-
) => boolean;
914+
shouldExpandNodeInitially?: ShouldExpandNodeInitially<T>;
918915
/** Whether to highlight updates. @default true */
919916
highlightUpdates?: boolean;
920917
/** Shorten long JSON strings, Set to `0` to disable this feature @default 30 */
@@ -926,6 +923,13 @@ export interface JsonViewProps<T extends object> extends React.DetailedHTMLProps
926923
/** Fires event when you copy */
927924
onCopied?: (text: string, value?: T) => void;
928925
}
926+
export type ShouldExpandNodeInitially<T extends object> = (isExpanded: boolean, props: {
927+
keyName?: string | number;
928+
value?: T;
929+
parentValue?: T;
930+
keys: (number | string)[];
931+
level: number;
932+
}) => boolean;
929933
```
930934

931935
```ts

core/src/Container.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,14 @@ export const Container = forwardRef(<T extends object>(props: ContainerProps<T>,
5454
parentValue={parentValue}
5555
keyName={keyName}
5656
/>
57-
<NestedClose expandKey={subkeyid} value={value} level={level} keys={keys} />
57+
<NestedClose
58+
expandKey={subkeyid}
59+
value={value}
60+
level={level}
61+
keys={keys}
62+
parentValue={parentValue}
63+
keyName={keyName}
64+
/>
5865
</div>
5966
);
6067
});

core/src/comps/KeyValues.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,21 @@ interface KeyValuesProps<T extends object> extends SectionElementResult<T> {
1818
}
1919

2020
export const KeyValues = <T extends object>(props: KeyValuesProps<T>) => {
21-
const { value, expandKey = '', level, keys = [] } = props;
21+
const { keyName, value, expandKey = '', level, keys = [], parentValue } = props;
2222
const expands = useExpandsStore();
2323
const { objectSortKeys, indentWidth, collapsed, shouldExpandNodeInitially } = useStore();
24-
const isMyArray = Array.isArray(value);
2524
const defaultExpanded =
2625
typeof collapsed === 'boolean' ? collapsed : typeof collapsed === 'number' ? level > collapsed : false;
2726
const isExpanded = expands[expandKey] ?? defaultExpanded;
28-
if (
29-
expands[expandKey] === undefined &&
30-
shouldExpandNodeInitially &&
31-
shouldExpandNodeInitially(isExpanded, { value, keys, level })
32-
) {
27+
const shouldExpand =
28+
shouldExpandNodeInitially && shouldExpandNodeInitially(isExpanded, { value, keys, level, keyName, parentValue });
29+
if (expands[expandKey] === undefined && !!shouldExpand) {
3330
return null;
3431
}
3532
if (isExpanded) {
3633
return null;
3734
}
35+
const isMyArray = Array.isArray(value);
3836
// object
3937
let entries: [key: string | number, value: T][] = isMyArray
4038
? Object.entries(value).map((m) => [Number(m[0]), m[1]])

core/src/comps/NestedClose.tsx

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,38 @@
11
import { useStore } from '../store';
22
import { useExpandsStore } from '../store/Expands';
33
import { BracketsClose } from '../symbol/';
4+
import { type SectionElementResult } from '../store/Section';
45

5-
interface NestedCloseProps<T extends object> {
6-
value?: T;
6+
interface NestedCloseProps<T extends object> extends SectionElementResult<T> {
77
expandKey: string;
88
level: number;
9-
keys?: (string | number)[];
109
}
1110

1211
export const NestedClose = <T extends object>(props: NestedCloseProps<T>) => {
13-
const { value, expandKey, level, keys = [] } = props;
12+
const { keyName, value, expandKey, parentValue, level, keys = [] } = props;
1413
const expands = useExpandsStore();
15-
const isArray = Array.isArray(value);
1614
const { collapsed, shouldExpandNodeInitially } = useStore();
17-
const isMySet = value instanceof Set;
1815
const defaultExpanded =
1916
typeof collapsed === 'boolean' ? collapsed : typeof collapsed === 'number' ? level > collapsed : false;
2017
const isExpanded = expands[expandKey] ?? defaultExpanded;
21-
const len = Object.keys(value!).length;
22-
const shouldExpand = shouldExpandNodeInitially && shouldExpandNodeInitially(!isExpanded, { value, keys, level });
23-
if (expands[expandKey] === undefined && shouldExpandNodeInitially && !shouldExpand) {
18+
const shouldExpand =
19+
shouldExpandNodeInitially && shouldExpandNodeInitially(isExpanded, { value, keys, level, keyName, parentValue });
20+
if (expands[expandKey] === undefined && !!shouldExpand) {
2421
return null;
2522
}
23+
const len = Object.keys(value!).length;
2624
if (isExpanded || len === 0) {
2725
return null;
2826
}
2927
const style: React.CSSProperties = {
3028
paddingLeft: 4,
3129
};
30+
const compProps = { keyName, value, keys, parentValue };
31+
const isArray = Array.isArray(value);
32+
const isMySet = value instanceof Set;
3233
return (
3334
<div style={style}>
34-
<BracketsClose isBrackets={isArray || isMySet} isVisiable={true} />
35+
<BracketsClose isBrackets={isArray || isMySet} {...compProps} isVisiable={true} />
3536
</div>
3637
);
3738
};

core/src/comps/NestedOpen.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,13 @@ export const NestedOpen = <T extends object>(props: NestedOpenProps<T>) => {
2020
const expands = useExpandsStore();
2121
const dispatchExpands = useExpandsDispatch();
2222
const { onExpand, collapsed, shouldExpandNodeInitially } = useStore();
23-
const isArray = Array.isArray(value);
24-
const isMySet = value instanceof Set;
2523
const defaultExpanded =
2624
typeof collapsed === 'boolean' ? collapsed : typeof collapsed === 'number' ? level > collapsed : false;
27-
const isObject = typeof value === 'object';
2825
let isExpanded = expands[expandKey] ?? defaultExpanded;
29-
const shouldExpand = shouldExpandNodeInitially && shouldExpandNodeInitially(!isExpanded, { value, keys, level });
30-
if (expands[expandKey] === undefined && shouldExpandNodeInitially && !shouldExpand) {
31-
isExpanded = !shouldExpand;
26+
const shouldExpand =
27+
shouldExpandNodeInitially && shouldExpandNodeInitially(isExpanded, { value, keys, level, keyName, parentValue });
28+
if (expands[expandKey] === undefined && shouldExpandNodeInitially) {
29+
isExpanded = !!shouldExpand;
3230
}
3331
const click = () => {
3432
const opt = { expand: !isExpanded, value, keyid: expandKey, keyName };
@@ -39,6 +37,9 @@ export const NestedOpen = <T extends object>(props: NestedOpenProps<T>) => {
3937
const style: React.CSSProperties = { display: 'inline-flex', alignItems: 'center' };
4038
const arrowStyle = { transform: `rotate(${!isExpanded ? '0' : '-90'}deg)`, transition: 'all 0.3s' };
4139
const len = Object.keys(value!).length;
40+
const isObject = typeof value === 'object';
41+
const isArray = Array.isArray(value);
42+
const isMySet = value instanceof Set;
4243
const showArrow = len !== 0 && (isArray || isMySet || isObject);
4344
const reset: React.HTMLAttributes<HTMLDivElement> = { style };
4445
if (showArrow) {

core/src/index.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ export * from './store/Symbols';
3939
export * from './store/Types';
4040
export * from './symbol/';
4141

42+
export type ShouldExpandNodeInitially<T extends object> = (
43+
isExpanded: boolean,
44+
props: { keyName?: string | number; value?: T; parentValue?: T; keys: (number | string)[]; level: number },
45+
) => boolean;
46+
4247
export interface JsonViewProps<T extends object>
4348
extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
4449
/** This property contains your input JSON */
@@ -58,10 +63,7 @@ export interface JsonViewProps<T extends object>
5863
/** When set to true, all nodes will be collapsed by default. Use an integer value to collapse at a particular depth. @default false */
5964
collapsed?: boolean | number;
6065
/** Determine whether the node should be expanded on the first render, or you can use collapsed to control the level of expansion (by default, the root is expanded). */
61-
shouldExpandNodeInitially?: (
62-
isExpanded: boolean,
63-
props: { value?: T; keys: (number | string)[]; level: number },
64-
) => boolean;
66+
shouldExpandNodeInitially?: ShouldExpandNodeInitially<T>;
6567
/** Whether to highlight updates. @default true */
6668
highlightUpdates?: boolean;
6769
/** Shorten long JSON strings, Set to `0` to disable this feature @default 30 */

core/src/store.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React, { PropsWithChildren, createContext, useContext, useEffect, useReducer } from 'react';
2-
import { JsonViewProps } from './';
1+
import React, { type PropsWithChildren, createContext, useContext, useEffect, useReducer } from 'react';
2+
import { type JsonViewProps } from './';
33
import { useShowTools, ShowTools } from './store/ShowTools';
44
import { useExpands, Expands } from './store/Expands';
55
import { useTypes, Types, type InitialTypesState, type TagType } from './store/Types';

core/src/symbol/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,12 @@ export const BracketsOpen = <K extends object>(props: { isBrackets?: boolean } &
9191

9292
BracketsOpen.displayName = 'JVR.BracketsOpen';
9393

94-
type BracketsCloseProps = {
94+
type BracketsProps = {
9595
isBrackets?: boolean;
9696
isVisiable?: boolean;
9797
};
9898

99-
export const BracketsClose = <K extends object>(props: BracketsCloseProps & SymbolsElementResult<K>) => {
99+
export const BracketsClose = <K extends object>(props: BracketsProps & SymbolsElementResult<K>) => {
100100
const { isBrackets, isVisiable, value, parentValue, keyName, keys } = props;
101101
const result = { value, parentValue, keyName, keys: keys || (keyName ? [keyName] : []) };
102102
if (!isVisiable) return null;

example/src/demo.tsx

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,49 @@
1-
import JsonView from '@uiw/react-json-view';
1+
import JsonView, { ShouldExpandNodeInitially } from '@uiw/react-json-view';
22

3+
const avatar = 'https://i.imgur.com/MK3eW3As.jpg';
4+
const tpl = {
5+
avatar,
6+
string: 'Lorem ipsum dolor sit amet',
7+
integer: 42,
8+
string_number: '1234',
9+
};
10+
const longArray = new Array(10).fill(tpl);
311
const example = {
4-
nestedArray: [],
5-
object: {},
6-
data: {
7-
value: 1,
12+
longArray,
13+
array2: new Array(2).fill(tpl),
14+
// nestedArray: [],
15+
// object: {},
16+
// data: {
17+
// value: 1,
18+
// },
19+
level1: {
20+
level2: {
21+
level3: {
22+
level4: {
23+
level5: {
24+
message: 'This is deeply nested and will be collapsed',
25+
value: 42,
26+
},
27+
},
28+
},
29+
},
830
},
931
};
1032

33+
const shouldExpandNodeInitially: ShouldExpandNodeInitially<object> = (isExpanded, props) => {
34+
const { value, level, keyName, parentValue, keys } = props;
35+
console.log('~~~~:', keyName, level, parentValue, keys);
36+
const isArray = Array.isArray(value);
37+
const isObject = typeof value === 'object' && !isArray;
38+
if (isArray) {
39+
return isExpanded || value.length > 5;
40+
}
41+
if (isObject && level > 3) {
42+
return isExpanded || true; // Expand if it's an object and level is greater than 3
43+
}
44+
return isExpanded;
45+
};
46+
1147
export default function App() {
12-
return (
13-
<JsonView value={example}>
14-
<JsonView.KeyName
15-
as="span"
16-
render={({ style, onClick, ...props }, { keyName, keys }) => {
17-
console.log('~~:', keyName, keys); // keys undefined
18-
return <span {...props} style={{ ...style, backgroundColor: 'red' }} />;
19-
}}
20-
/>
21-
</JsonView>
22-
);
48+
return <JsonView value={example} displayObjectSize={false} shouldExpandNodeInitially={shouldExpandNodeInitially} />;
2349
}

0 commit comments

Comments
 (0)