Skip to content

Commit b520218

Browse files
author
blucas.wu
committed
feat: support expand at particular depth
1 parent fdd6a65 commit b520218

File tree

8 files changed

+100
-79
lines changed

8 files changed

+100
-79
lines changed

README.md

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ Engligh | [中文](./README_ZH.md)
44

55
`<ReactJsonView />` is a React component for displaying JSON data.
66

7-
The component accepts source data of _string_ type, which means you need to ensure that the data passed in is valid JSON string and can be parsed without errors using the `JSON.parse()` method. Otherwise, the data will be converted to a _string_ type before being processed.
8-
97
## Install
108

119
```bash
@@ -30,17 +28,7 @@ import ReactDOM from 'react-dom';
3028
import ReactJsonView from '@huolala-tech/react-json-view';
3129
import '@huolala-tech/react-json-view/dist/style.css';
3230

33-
const data = JSON.stringify([
34-
1,
35-
true,
36-
"Hello world",
37-
["foo", "bar", "baz"],
38-
{
39-
name: "@huolala-tech/react-json-view",
40-
contributor: "wqcstrong",
41-
description: 'The component accepts source data of *string* type, which means you need to ensure that the data passed in is valid JSON string and can be parsed without errors using the `JSON.parse()` method.',
42-
},
43-
]);
31+
const data = [1,2,3,4]
4432

4533
const App = () => {
4634
return (
@@ -64,10 +52,6 @@ ReactDOM.render(
6452
)
6553
```
6654

67-
Now you should get that after above:
68-
69-
![Main](./screenshots/expand.jpg)
70-
7155
## Config
7256

7357
The default configuration usage:
@@ -82,13 +66,13 @@ The default configuration usage:
8266
/>
8367
```
8468

85-
| Name | Type | Default value | Description |
86-
| --------------- | ----------------- | ------------- | ------------------------------------------------ |
87-
| `source` | `string` | None | Origin json string. |
88-
| `rootLabel` | `React.ReactNode` | `""` | Root node's label. |
89-
| `defaultExpand` | `boolean` | `false` | Whether expand property panel. |
90-
| `keyCount` | `number / "all"` | `200` | `ReactJsonView` supports lazily loading more properties. The parameter indicates how many properties to show at a time, and you can pass `"all"` to show all properties. |
91-
| `maxTitleSize` | `number` | `100` | The max length of abbreviated title in collapse. |
69+
| Name | Type | Default value | Description |
70+
| --------------- | ------------------ | ------------- | ------------------------------------------------------------ |
71+
| `source` | `object` | None | Origin json data. |
72+
| `rootLabel` | `React.ReactNode` | `""` | Root node's label. |
73+
| `defaultExpand` | `boolean / number` | `false` | Whether expand property panel. Expand at a particular depth if you pass a integer value. |
74+
| `keyCount` | `number / "all"` | `200` | `ReactJsonView` supports lazily loading more properties. The parameter indicates how many properties to show at a time, and you can pass `"all"` to show all properties. |
75+
| `maxTitleSize` | `number` | `100` | The max length of abbreviated title in collapse. |
9276

9377
## License
9478

README_ZH.md

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
`<ReactJsonView />` 是一个用于展示 JSON 数据的 React 组件。
66

7-
该组件接受 `string` 类型的源数据,这意味着你需要确保传入的数据是有效的 JSON 字符串,并且可以使用 `JSON.parse()` 方法正确解析。否则,数据将在被处理之前转换为 `string` 类型。
8-
97
## 安装
108

119
```bash
@@ -30,17 +28,7 @@ import ReactDOM from 'react-dom';
3028
import ReactJsonView from '@huolala-tech/react-json-view';
3129
import '@huolala-tech/react-json-view/dist/style.css';
3230

33-
const data = JSON.stringify([
34-
1,
35-
true,
36-
"Hello world",
37-
["foo", "bar", "baz"],
38-
{
39-
name: "@huolala-tech/react-json-view",
40-
contributor: "wqcstrong",
41-
description: 'The component accepts source data of *string* type, which means you need to ensure that the data passed in is valid JSON string and can be parsed without errors using the `JSON.parse()` method.',
42-
},
43-
]);
31+
const data = [1, 2, 3, 4];
4432

4533
const App = () => {
4634
return (
@@ -64,10 +52,6 @@ ReactDOM.render(
6452
)
6553
```
6654

67-
此时你应该可以看到如下界面:
68-
69-
![Main](/screenshots/expand.jpg)
70-
7155
## 配置
7256

7357
默认配置下的使用方式:
@@ -86,7 +70,7 @@ ReactDOM.render(
8670
| --------------- | ----------------- | ------------- | ---------------------- |
8771
| `source` | `string` | 无默认值 | JSON 数据。 |
8872
| `rootLabel` | `React.ReactNode` | `""` | 根节点的标题名称 |
89-
| `defaultExpand` | `boolean` | `false` | 是否展开面板 |
73+
| `defaultExpand` | `boolean / number` | `false` | 是否展开面板。传入整数时是指定展开的层级。 |
9074
| `keyCount` | `number / "all"` | `200` | `ReactJsonView` 支持延迟加载更多属性。 该参数表示一次显示多少个属性,您可以传递 `"all"` 以显示所有属性。 |
9175
| `maxTitleSize` | `number` | `100` | 折叠时缩写标题的最大长度。 |
9276

examples/App.tsx

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,61 @@
11
import ReactJsonView from '../dist/index';
22
import '../dist/style.css';
3-
import json from './assets/data.json?raw';
3+
import json from './assets/data.json';
44

5-
const data = JSON.stringify([
6-
1,
7-
true,
8-
'Hello world',
9-
['foo', 'bar', 'baz'],
5+
const data = [
106
{
11-
name: '@huolala-tech/react-json-view',
12-
contributor: 'wqcstrong',
13-
description:
14-
'The component accepts source data of string type, which means you need to ensure that the data passed in is valid JSON string and can be parsed without errors using the JSON.parse() method.',
7+
type: 'Primitive',
8+
data: 'Hello, @huolala-tech/react-json-view',
159
},
16-
]);
10+
{
11+
type: 'Normal',
12+
data: {
13+
name: '@huolala-tech/react-json-view',
14+
contributor: 'wqcstrong',
15+
description:
16+
'<ReactJsonView /> is a react component for display json tree, it accepts the valid json object as the source and show them',
17+
},
18+
},
19+
{
20+
type: 'Indicate expand depth (3)',
21+
data: {
22+
foo: {
23+
name: 'foo',
24+
child: {
25+
bar: {
26+
name: 'bar',
27+
child: {
28+
name: 'baz',
29+
},
30+
},
31+
},
32+
},
33+
},
34+
},
35+
{
36+
type: 'Self-Reference (window)',
37+
data: window,
38+
},
39+
{ type: 'Big Size', data: json },
40+
];
1741

1842
const App = () => {
1943
return (
2044
<div id="app">
21-
<ReactJsonView
22-
source={data || json}
23-
rootLabel="Response data"
24-
keyCount={200}
25-
defaultExpand={false}
26-
maxTitleSize={100}
27-
/>
45+
{data.map((item) => {
46+
return (
47+
<>
48+
<h2>{item.type}</h2>
49+
<ReactJsonView
50+
key={item.type}
51+
source={item.data}
52+
keyCount={200}
53+
defaultExpand={2}
54+
maxTitleSize={100}
55+
/>
56+
</>
57+
);
58+
})}
2859
</div>
2960
);
3061
};

src/ReactJsonView/components/ConfigContext.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { PropsWithChildren, createContext, useContext } from 'react';
22
import { Options } from '../../../types';
33

44
const ConfigContext = createContext<Options>({
5-
source: '',
5+
source: {},
66
defaultExpand: false,
77
rootLabel: '',
88
keyCount: 200,

src/ReactJsonView/components/JsonNode.tsx

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,42 @@
11
import { useState, useMemo, ReactNode } from 'react';
2-
import { clsx, isListOrMap, shortTitle } from '../../utils';
2+
import {
3+
clsx,
4+
isBoolean,
5+
isListOrMap,
6+
isNumber,
7+
shortTitle,
8+
} from '../../utils';
39
import { ArrowRight } from './SvgIcon';
410
import { useConfigInfo } from './ConfigContext';
511
import CopyContent from './CopyContent';
612
import LazyLoadMore from './LazyLoadMore';
713

814
const JsonNode = ({
9-
source = '',
15+
source = {},
16+
depth = 1,
1017
label = '',
1118
}: {
12-
source: string;
19+
source: object;
20+
depth?: number;
1321
label?: ReactNode;
1422
}) => {
1523
const { defaultExpand, maxTitleSize } = useConfigInfo();
16-
const [collapsed, setCollapsed] = useState(!defaultExpand);
24+
const [expanded, setExpanded] = useState(() => {
25+
if (isBoolean(defaultExpand)) {
26+
return defaultExpand;
27+
}
28+
if (isNumber(defaultExpand)) {
29+
return defaultExpand + 1 >= depth;
30+
}
31+
return false;
32+
});
1733

1834
let data: unknown;
1935
try {
20-
data = JSON.parse(source);
36+
data = JSON.parse(JSON.stringify(source));
2137
} catch (e) {
22-
data = `${source}`;
38+
label = 'Error';
39+
data = 'The source value must be a valid json object';
2340
}
2441

2542
const labelContent = useMemo(() => {
@@ -60,28 +77,26 @@ const JsonNode = ({
6077

6178
return (
6279
<div className="rjv-node">
63-
<div
64-
className="rjv-node__title"
65-
onClick={() => setCollapsed(!collapsed)}
66-
>
80+
<div className="rjv-node__title" onClick={() => setExpanded(!expanded)}>
6781
<ArrowRight
6882
width={10}
6983
height={10}
7084
className={clsx('rjv-node__spread-controller', {
71-
spread: !collapsed,
85+
spread: expanded,
7286
})}
7387
/>
7488
{labelContent}
75-
{(!label || collapsed) && <code>{title}</code>}
89+
{(!label || !expanded) && <code>{title}</code>}
7690
</div>
77-
{!collapsed && (
78-
<div className="rjv-node__property">
91+
{expanded && (
92+
<div className="rjv-node__property" data-depth={depth}>
7993
<LazyLoadMore
8094
list={Object.keys(data)}
8195
render={(key) => (
8296
<JsonNode
8397
label={key}
84-
source={JSON.stringify((data as any)[key])}
98+
source={(data as any)[key]}
99+
depth={depth + 1}
85100
/>
86101
)}
87102
/>

src/ReactJsonView/index.less

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
font-size: @fontSize;
55
font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier,
66
monospace;
7-
line-height: 1.3;
7+
line-height: 1.4;
88
&__title {
99
cursor: default;
1010
}

src/utils/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ export function toStringTag(data: unknown) {
109109
return Object.prototype.toString.call(data);
110110
}
111111

112+
export function isBoolean(data: unknown): data is boolean {
113+
return typeof data === 'boolean';
114+
}
115+
export function isNumber(data: unknown): data is number {
116+
return typeof data === 'number';
117+
}
118+
112119
export function isArray<T = unknown>(data: unknown): data is T[] {
113120
return Array.isArray(data);
114121
}

types/index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export interface Options {
44
/**
55
* origin json data.
66
*/
7-
source: string;
7+
source: object;
88
/**
99
* root label.
1010
* @default ""
@@ -14,7 +14,7 @@ export interface Options {
1414
* Whether expand property panel.
1515
* @default false
1616
*/
17-
defaultExpand?: boolean;
17+
defaultExpand?: boolean | number;
1818
/**
1919
* `ReactJsonView` support load more property lazily.
2020
* The option indicated how many properties to show once, you

0 commit comments

Comments
 (0)