Skip to content

Commit 1869f0d

Browse files
committed
feat: enhance render props for Quote/KeyName/Colon/Arrow/BracketsOpen/BracketsClose. #32
1 parent 5a3a449 commit 1869f0d

File tree

5 files changed

+86
-36
lines changed

5 files changed

+86
-36
lines changed

core/README.md

+29-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ export default function Demo() {
127127
}
128128
```
129129

130-
131130
Example of custom `vscode` theme styles:
132131

133132
```tsx mdx:preview
@@ -682,6 +681,35 @@ export default function Demo() {
682681

683682
This feature can be disabled with `highlightUpdates={false}`, and the default color can be changed with `--w-rjv-update-color`.
684683

684+
## Do not display array index
685+
686+
```tsx mdx:preview
687+
import React, { Fragment } from 'react';
688+
import JsonView from '@uiw/react-json-view';
689+
690+
export default function Demo() {
691+
const value = { data: ["123", 23] }
692+
return (
693+
<JsonView value={value} style={{ '--w-rjv-background-color': '#ffffff' }}>
694+
<JsonView.Colon render={(props, { parentValue, value, keyName }) => {
695+
if (Array.isArray(parentValue) && props.children == ":") {
696+
return <span />
697+
}
698+
return <span {...props} />
699+
}}/>
700+
<JsonView.KeyName
701+
render={({ ...props }, { type, parentValue, value, keyName }) => {
702+
if (Array.isArray(parentValue) && Number.isFinite( props.children)) {
703+
return <span />
704+
}
705+
return <span {...props} />
706+
}}
707+
/>
708+
</JsonView>
709+
)
710+
}
711+
```
712+
685713
## Modify Icon Style
686714

687715
Use built-in default icons.

core/src/comps/KeyValues.tsx

+5-6
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,15 @@ export const KayName = <T extends object>(props: KayNameProps<T>) => {
6666
const isNumber = typeof keyName === 'number';
6767
const highlightContainer = useRef<HTMLSpanElement>(null);
6868
useHighlight({ value, highlightUpdates, highlightContainer });
69+
const compProps = { keyName, value, keys, parentValue };
6970
return (
7071
<Fragment>
7172
<span ref={highlightContainer}>
72-
<Quote isNumber={isNumber} data-placement="left" />
73-
<KeyNameComp keyName={keyName!} value={value} keys={keys} parentValue={parentValue}>
74-
{keyName}
75-
</KeyNameComp>
76-
<Quote isNumber={isNumber} data-placement="right" />
73+
<Quote isNumber={isNumber} data-placement="left" {...compProps} />
74+
<KeyNameComp {...compProps}>{keyName}</KeyNameComp>
75+
<Quote isNumber={isNumber} data-placement="right" {...compProps} />
7776
</span>
78-
<Colon />
77+
<Colon {...compProps} />
7978
</Fragment>
8079
);
8180
};

core/src/comps/NestedOpen.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,16 @@ export const NestedOpen = <T extends object>(props: NestedOpenProps<T>) => {
4040
if (showArrow) {
4141
reset.onClick = click;
4242
}
43+
const compProps = { keyName, value, keys, parentValue };
4344
return (
4445
<span {...reset}>
45-
{showArrow && <Arrow style={arrowStyle} expandKey={expandKey} />}
46+
{showArrow && <Arrow style={arrowStyle} expandKey={expandKey} {...compProps} />}
4647
{(keyName || typeof keyName === 'number') && <KayName keyName={keyName} />}
4748
<SetComp value={initialValue} keyName={keyName!} />
4849
<MapComp value={initialValue} keyName={keyName!} />
49-
<BracketsOpen isBrackets={isArray || isMySet} />
50+
<BracketsOpen isBrackets={isArray || isMySet} {...compProps} />
5051
<EllipsisComp keyName={keyName!} value={value} isExpanded={isExpanded} />
51-
<BracketsClose isVisiable={isExpanded || !showArrow} isBrackets={isArray || isMySet} />
52+
<BracketsClose isVisiable={isExpanded || !showArrow} isBrackets={isArray || isMySet} {...compProps} />
5253
<CountInfoComp value={value} keyName={keyName!} />
5354
<CountInfoExtraComps value={value} keyName={keyName!} />
5455
<Copied keyName={keyName!} value={value} expandKey={expandKey} parentValue={parentValue} keys={keys} />

core/src/store/Symbols.tsx

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,17 @@ import {
1010
import { type TagType } from './Types';
1111
import { TriangleArrow } from '../arrow/TriangleArrow';
1212

13+
export interface SymbolsElementResult<T extends object, K = string | number> {
14+
value?: T;
15+
parentValue?: T;
16+
keyName?: K;
17+
/** Index of the parent `keyName` */
18+
keys?: K[];
19+
}
20+
1321
type SymbolsElementProps<T extends TagType = 'span'> = {
1422
as?: T;
15-
render?: (props: SymbolsElement<T>) => React.ReactNode;
23+
render?: (props: SymbolsElement<T>, result: SymbolsElementResult<object>) => React.ReactNode;
1624
'data-type'?: string;
1725
};
1826
export type SymbolsElement<T extends TagType = 'span'> = SymbolsElementProps<T> & ComponentPropsWithoutRef<T>;

core/src/symbol/index.tsx

+39-25
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
import { useSymbolsStore, type SymbolsElement } from '../store/Symbols';
1+
import { useSymbolsStore, type SymbolsElement, type SymbolsElementResult } from '../store/Symbols';
22
import { type TagType } from '../store/Types';
33
import { useExpandsStore } from '../store/Expands';
44

5-
export const Quote = (props: { isNumber?: boolean } & React.HTMLAttributes<HTMLElement>) => {
5+
export const Quote = <T extends object>(
6+
props: { isNumber?: boolean } & React.HTMLAttributes<HTMLElement> & SymbolsElementResult<T>,
7+
) => {
68
const { Quote: Comp = {} } = useSymbolsStore();
7-
const { isNumber, ...other } = props;
9+
const { isNumber, value, parentValue, keyName, keys, ...other } = props;
810
if (isNumber) return null;
911
const { as, render, ...reset } = Comp;
1012
const Elm = as || 'span';
1113
const elmProps = { ...other, ...reset };
12-
const child = render && typeof render === 'function' && render(elmProps);
14+
let result = { value, parentValue, keyName, keys: keys || (keyName ? [keyName] : []) };
15+
const child = render && typeof render === 'function' && render(elmProps, result);
1316
if (child) return child;
1417
return <Elm {...elmProps} />;
1518
};
@@ -22,59 +25,68 @@ export const ValueQuote = (props: React.HTMLAttributes<HTMLElement>) => {
2225
const { as, render, ...reset } = Comp;
2326
const Elm = as || 'span';
2427
const elmProps = { ...other, ...reset };
25-
const child = render && typeof render === 'function' && render(elmProps);
28+
const child = render && typeof render === 'function' && render(elmProps, {});
2629
if (child) return child;
2730
return <Elm {...elmProps} />;
2831
};
2932

3033
ValueQuote.displayName = 'JVR.ValueQuote';
3134

32-
export const Colon = () => {
35+
export const Colon = <T extends object>(props: SymbolsElementResult<T>) => {
36+
const { value, parentValue, keyName, keys } = props;
3337
const { Colon: Comp = {} } = useSymbolsStore();
3438
const { as, render, ...reset } = Comp;
3539
const Elm = as || 'span';
36-
const child = render && typeof render === 'function' && render(reset);
40+
const child =
41+
render &&
42+
typeof render === 'function' &&
43+
render(reset, {
44+
value,
45+
parentValue,
46+
keyName,
47+
keys: keys || (keyName ? [keyName] : []),
48+
});
3749
if (child) return child;
3850
return <Elm {...reset} />;
3951
};
4052

4153
Colon.displayName = 'JVR.Colon';
4254

43-
export const Arrow = <T extends TagType>(props: SymbolsElement<T> & { expandKey: string }) => {
55+
export const Arrow = <T extends TagType, K extends object>(
56+
props: SymbolsElement<T> & { expandKey: string } & SymbolsElementResult<K>,
57+
) => {
4458
const { Arrow: Comp = {} } = useSymbolsStore();
4559
const expands = useExpandsStore();
46-
const { expandKey } = props;
60+
const { expandKey, style: resetStyle, value, parentValue, keyName, keys } = props;
4761
const isExpanded = !!expands[expandKey];
4862
const { as, style, render, ...reset } = Comp;
4963
const Elm = as || 'span';
5064
const isRender = render && typeof render === 'function';
51-
const child = isRender && render({ ...reset, 'data-expanded': isExpanded, style: { ...style, ...props.style } });
65+
const elmProps = { ...reset, 'data-expanded': isExpanded, style: { ...style, ...resetStyle } };
66+
const result = { value, parentValue, keyName, keys: keys || (keyName ? [keyName] : []) };
67+
const child = isRender && render(elmProps, result);
5268
if (child) return child;
53-
return <Elm {...reset} style={{ ...style, ...props.style }} />;
69+
return <Elm {...reset} style={{ ...style, ...resetStyle }} />;
5470
};
5571

5672
Arrow.displayName = 'JVR.Arrow';
5773

58-
type EllipsisProps<T extends object> = {
59-
isExpanded?: boolean;
60-
keyName: string | number;
61-
value?: T;
62-
};
63-
64-
export const BracketsOpen = ({ isBrackets }: { isBrackets?: boolean }) => {
74+
export const BracketsOpen = <K extends object>(props: { isBrackets?: boolean } & SymbolsElementResult<K>) => {
75+
const { isBrackets, value, parentValue, keyName, keys } = props;
6576
const { BracketsLeft = {}, BraceLeft = {} } = useSymbolsStore();
77+
const result = { value, parentValue, keyName, keys: keys || (keyName ? [keyName] : []) };
6678
if (isBrackets) {
6779
const { as, render, ...reset } = BracketsLeft;
6880
const BracketsLeftComp = as || 'span';
69-
const child = render && typeof render === 'function' && render(reset);
81+
const child = render && typeof render === 'function' && render(reset, result);
7082
if (child) return child;
7183
return <BracketsLeftComp {...reset} />;
7284
}
73-
const { as: elm, render, ...props } = BraceLeft;
85+
const { as: elm, render, ...resetProps } = BraceLeft;
7486
const BraceLeftComp = elm || 'span';
75-
const child = render && typeof render === 'function' && render(props);
87+
const child = render && typeof render === 'function' && render(resetProps, result);
7688
if (child) return child;
77-
return <BraceLeftComp {...props} />;
89+
return <BraceLeftComp {...resetProps} />;
7890
};
7991

8092
BracketsOpen.displayName = 'JVR.BracketsOpen';
@@ -84,19 +96,21 @@ type BracketsCloseProps = {
8496
isVisiable?: boolean;
8597
};
8698

87-
export const BracketsClose = ({ isBrackets, isVisiable }: BracketsCloseProps) => {
99+
export const BracketsClose = <K extends object>(props: BracketsCloseProps & SymbolsElementResult<K>) => {
100+
const { isBrackets, isVisiable, value, parentValue, keyName, keys } = props;
101+
const result = { value, parentValue, keyName, keys: keys || (keyName ? [keyName] : []) };
88102
if (!isVisiable) return null;
89103
const { BracketsRight = {}, BraceRight = {} } = useSymbolsStore();
90104
if (isBrackets) {
91105
const { as, render, ...reset } = BracketsRight;
92106
const BracketsRightComp = as || 'span';
93-
const child = render && typeof render === 'function' && render(reset);
107+
const child = render && typeof render === 'function' && render(reset, result);
94108
if (child) return child;
95109
return <BracketsRightComp {...reset} />;
96110
}
97111
const { as: elm, render, ...reset } = BraceRight;
98112
const BraceRightComp = elm || 'span';
99-
const child = render && typeof render === 'function' && render(reset);
113+
const child = render && typeof render === 'function' && render(reset, result);
100114
if (child) return child;
101115
return <BraceRightComp {...reset} />;
102116
};

0 commit comments

Comments
 (0)