Skip to content

Commit 04c4db0

Browse files
committed
feat: add collapsed props.
1 parent 2134a5a commit 04c4db0

File tree

4 files changed

+85
-48
lines changed

4 files changed

+85
-48
lines changed

core/src/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ export interface JsonViewProps<T extends object>
2222
enableClipboard?: boolean;
2323
/** Display for quotes in object-key @default " */
2424
quotes?: "'" | '"' | '';
25+
/** When set to true, all nodes will be collapsed by default. Use an integer value to collapse at a particular depth. @default false */
26+
collapsed?: boolean | number;
2527
/** Callback function for when a treeNode is expanded or collapsed */
2628
onExpand?: (props: { expand: boolean; value: T; keyid: string; keyName?: string | number; }) => void;
2729
/** Redefine interface elements to re-render. */

core/src/node.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export const CountInfo: FC<PropsWithChildren<LabelProps>> = ({ children }) => (
8181
export interface RooNodeProps<T extends object> extends JsonViewProps<T> {
8282
keyName?: string | number;
8383
keyid?: string;
84+
level?: number;
8485
}
8586
export function RooNode<T extends object>(props: RooNodeProps<T>) {
8687
const {
@@ -91,6 +92,8 @@ export function RooNode<T extends object>(props: RooNodeProps<T>) {
9192
displayObjectSize = true,
9293
enableClipboard = true,
9394
indentWidth = 15,
95+
collapsed,
96+
level = 1,
9497
keyid = 'root',
9598
quotes = '"',
9699
onExpand,
@@ -100,7 +103,7 @@ export function RooNode<T extends object>(props: RooNodeProps<T>) {
100103
const nameKeys = (isArray ? Object.keys(value).map(m => Number(m)) : Object.keys(value)) as (keyof typeof value)[];
101104
const subkeyid = useId();
102105
const expands = useExpandsStatus();
103-
const expand = expands[keyid] ?? true;
106+
const expand = expands[keyid] ?? (typeof collapsed === 'boolean' ? collapsed : (typeof collapsed === 'number' ? level <= collapsed : true));
104107
const arrowStyle = { transform: `rotate(${expand ? '0' : '-90'}deg)`, transition: 'all 0.3s' };
105108
const handle = () => {
106109
onExpand && typeof onExpand === 'function' && onExpand({ expand: !expand, keyid, keyName, value: value as T })
@@ -113,7 +116,9 @@ export function RooNode<T extends object>(props: RooNodeProps<T>) {
113116
displayObjectSize,
114117
enableClipboard,
115118
onExpand,
119+
collapsed,
116120
quotes,
121+
level: level + 1,
117122
style: { paddingLeft: indentWidth },
118123
};
119124
const valueViewProps = {
@@ -131,10 +136,13 @@ export function RooNode<T extends object>(props: RooNodeProps<T>) {
131136
);
132137
const [showTools, setShowTools] = useState(false);
133138
const tools = enableClipboard ? <Copied show={showTools} text={value as T} render={components.copied} /> : undefined;
134-
const mouseEnter = () => setShowTools(true);
135-
const mouseLeave = () => setShowTools(false);
139+
const eventProps: React.HTMLAttributes<HTMLDivElement> = {};
140+
if (enableClipboard) {
141+
eventProps.onMouseEnter = () => setShowTools(true);
142+
eventProps.onMouseLeave = () => setShowTools(false);
143+
}
136144
return (
137-
<div {...reset} onMouseEnter={mouseEnter} onMouseLeave={mouseLeave}>
145+
<div {...reset} {...eventProps}>
138146
<Line style={{ display: 'inline-flex', alignItems: 'center' }} onClick={handle}>
139147
{arrowView}
140148
{(typeof keyName === 'string' || typeof keyName === 'number') && (

core/src/value.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,11 @@ export function ValueView<T = object>(props: ValueViewProps<T>) {
112112

113113
const [showTools, setShowTools] = useState(false);
114114
const tools = enableClipboard ? <Copied show={showTools} text={value} /> : undefined;
115-
const mouseEnter = () => setShowTools(true);
116-
const mouseLeave = () => setShowTools(false);
115+
const eventProps: React.HTMLAttributes<HTMLDivElement> = {};
116+
if (enableClipboard) {
117+
eventProps.onMouseEnter = () => setShowTools(true);
118+
eventProps.onMouseLeave = () => setShowTools(false);
119+
}
117120

118121
if (content && typeof content === 'string') {
119122
const valueView = renderValue ? (
@@ -129,7 +132,7 @@ export function ValueView<T = object>(props: ValueViewProps<T>) {
129132
</Label>
130133
);
131134
return (
132-
<Line style={{ paddingLeft: indentWidth }} onMouseEnter={mouseEnter} onMouseLeave={mouseLeave}>
135+
<Line style={{ paddingLeft: indentWidth }} {...eventProps}>
133136
<Label {...reset}>
134137
{renderKey}
135138
<Colon />
@@ -149,7 +152,7 @@ export function ValueView<T = object>(props: ValueViewProps<T>) {
149152
</Fragment>
150153
)
151154
return (
152-
<Line style={{ paddingLeft: indentWidth }} onMouseEnter={mouseEnter} onMouseLeave={mouseLeave}>
155+
<Line style={{ paddingLeft: indentWidth }} {...eventProps}>
153156
<Label {...reset}>
154157
{renderKey}
155158
<Colon />

www/src/Example.tsx

Lines changed: 64 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,19 @@ const Label = styled.label`
5252
}
5353
`;
5454

55+
const Options = styled.div`
56+
display: grid;
57+
grid-template-columns: 50% 60%;
58+
`;
59+
5560
export function Example() {
5661
const [indentWidth, setIndentWidth] = useState(15);
5762
const [theme, setTheme] = useState<React.CSSProperties>(lightTheme as React.CSSProperties);
5863
const [displayDataTypes, setDisplayDataTypes] = useState(true);
5964
const [displayObjectSize, setDisplayObjectSize] = useState(true);
6065
const [clipboard, setClipboard] = useState(true);
6166
const [quotes, setQuotes] = useState<JsonViewProps<object>['quotes']>("\"");
67+
const [collapsed, setCollapsed] = useState<JsonViewProps<object>['collapsed']>(true);
6268
return (
6369
<Fragment>
6470
<JsonView
@@ -69,47 +75,65 @@ export function Example() {
6975
quotes={quotes}
7076
enableClipboard={clipboard}
7177
style={theme}
78+
collapsed={collapsed}
7279
/>
73-
<Label>
74-
<span>Theme:</span>
75-
<select
76-
onChange={(evn) => setTheme(themesData[evn.target.value as keyof typeof themesData] as React.CSSProperties)}
77-
>
78-
<option value="light">light</option>
79-
<option value="dark">dark</option>
80-
</select>
81-
</Label>
82-
<Label>
83-
<span>Quotes:</span>
84-
<select
85-
value={quotes?.toString()}
86-
onChange={(evn) => setQuotes(evn.target.value as JsonViewProps<object>['quotes'])}
87-
>
88-
<option value="">enable quotes</option>
89-
<option value={`"`}>" double quotes</option>
90-
<option value={`'`}>' single quotes</option>
91-
</select>
92-
</Label>
93-
<Label>
94-
<span>Indent:</span>
95-
<input type="number" value={indentWidth} onChange={(evn) => setIndentWidth(Number(evn.target.value))} />
96-
</Label>
97-
<Label>
98-
<span>Enable Clipboard:</span>
99-
<input type="checkbox" checked={clipboard} onChange={(evn) => setClipboard(evn.target.checked)} />
100-
</Label>
101-
<Label>
102-
<span>Display Data Types:</span>
103-
<input type="checkbox" checked={displayDataTypes} onChange={(evn) => setDisplayDataTypes(evn.target.checked)} />
104-
</Label>
105-
<Label>
106-
<span>Display Object Size:</span>
107-
<input
108-
type="checkbox"
109-
checked={displayObjectSize}
110-
onChange={(evn) => setDisplayObjectSize(evn.target.checked)}
111-
/>
112-
</Label>
80+
<Options>
81+
<Label>
82+
<span>Theme:</span>
83+
<select
84+
onChange={(evn) => setTheme(themesData[evn.target.value as keyof typeof themesData] as React.CSSProperties)}
85+
>
86+
<option value="light">light</option>
87+
<option value="dark">dark</option>
88+
</select>
89+
</Label>
90+
<Label>
91+
<span>Collapsed:</span>
92+
<select
93+
value={collapsed?.toString()}
94+
onChange={({ target: { value }}) => {
95+
const val = value === 'false' ? false : value === 'true' ? true : Number(value);
96+
setCollapsed(val);
97+
}}
98+
>
99+
<option value="false">false</option>
100+
<option value="true">true</option>
101+
<option value="1">1</option>
102+
<option value="2">2</option>
103+
</select>
104+
</Label>
105+
<Label>
106+
<span>Quotes:</span>
107+
<select
108+
value={quotes?.toString()}
109+
onChange={(evn) => setQuotes(evn.target.value as JsonViewProps<object>['quotes'])}
110+
>
111+
<option value="">enable quotes</option>
112+
<option value={`"`}>" double quotes</option>
113+
<option value={`'`}>' single quotes</option>
114+
</select>
115+
</Label>
116+
<Label>
117+
<span>Indent:</span>
118+
<input type="number" value={indentWidth} onChange={(evn) => setIndentWidth(Number(evn.target.value))} />
119+
</Label>
120+
<Label>
121+
<span>Enable Clipboard:</span>
122+
<input type="checkbox" checked={clipboard} onChange={(evn) => setClipboard(evn.target.checked)} />
123+
</Label>
124+
<Label>
125+
<span>Display Data Types:</span>
126+
<input type="checkbox" checked={displayDataTypes} onChange={(evn) => setDisplayDataTypes(evn.target.checked)} />
127+
</Label>
128+
<Label>
129+
<span>Display Object Size:</span>
130+
<input
131+
type="checkbox"
132+
checked={displayObjectSize}
133+
onChange={(evn) => setDisplayObjectSize(evn.target.checked)}
134+
/>
135+
</Label>
136+
</Options>
113137
</Fragment>
114138
);
115139
}

0 commit comments

Comments
 (0)