@uiw/react-json-view 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -3
- package/cjs/copied.d.ts +1 -1
- package/cjs/copied.js +4 -2
- package/cjs/index.d.ts +6 -1
- package/cjs/node.d.ts +0 -7
- package/cjs/node.js +44 -43
- package/cjs/semicolon.d.ts +12 -0
- package/cjs/semicolon.js +94 -0
- package/cjs/theme/dark.d.ts +1 -0
- package/cjs/theme/dark.js +1 -0
- package/cjs/theme/light.d.ts +1 -0
- package/cjs/theme/light.js +1 -0
- package/cjs/value.d.ts +2 -2
- package/cjs/value.js +5 -2
- package/esm/copied.d.ts +1 -1
- package/esm/copied.js +4 -2
- package/esm/index.d.ts +6 -1
- package/esm/node.d.ts +0 -7
- package/esm/node.js +30 -38
- package/esm/semicolon.d.ts +12 -0
- package/esm/semicolon.js +85 -0
- package/esm/theme/dark.d.ts +1 -0
- package/esm/theme/dark.js +1 -0
- package/esm/theme/light.d.ts +1 -0
- package/esm/theme/light.js +1 -0
- package/esm/value.d.ts +2 -2
- package/esm/value.js +6 -3
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@ react-json-view
|
|
|
4
4
|
[](https://github.com/uiwjs/react-json-view/actions/workflows/ci.yml)
|
|
5
5
|
[](https://www.npmjs.com/package/@uiw/react-json-view)
|
|
6
6
|
[](https://github.com/facebook/react/releases)
|
|
7
|
+
[](https://uiwjs.github.io/react-json-view/lcov-report/)
|
|
7
8
|
|
|
8
9
|
A React component for displaying and editing javascript arrays and JSON objects.
|
|
9
10
|
|
|
@@ -22,7 +23,8 @@ A React component for displaying and editing javascript arrays and JSON objects.
|
|
|
22
23
|
📚 Use Typescript to write, better code hints.
|
|
23
24
|
🎨 Support theme customization & [`online editing`](https://uiwjs.github.io/react-json-view/#online-editing-theme) theme
|
|
24
25
|
🌒 Support dark/light mode
|
|
25
|
-
📦 Zero dependencies
|
|
26
|
+
📦 Zero dependencies
|
|
27
|
+
♻️ Whether to highlight updates.
|
|
26
28
|
|
|
27
29
|
## Quick Start
|
|
28
30
|
|
|
@@ -111,6 +113,7 @@ const customTheme = {
|
|
|
111
113
|
'--w-rjv-line-color': '#323232',
|
|
112
114
|
'--w-rjv-arrow-color': 'var(--w-rjv-color)',
|
|
113
115
|
'--w-rjv-info-color': '#656565',
|
|
116
|
+
'--w-rjv-update-color': '#ebcb8b',
|
|
114
117
|
'--w-rjv-copied-color': '#9cdcfe',
|
|
115
118
|
'--w-rjv-copied-success-color': '#28a745',
|
|
116
119
|
|
|
@@ -140,7 +143,7 @@ export default function Demo() {
|
|
|
140
143
|
Online custom style example, please check in the [documentation website](https://uiwjs.github.io/react-json-view/)
|
|
141
144
|
|
|
142
145
|
```tsx mdx:preview:&title=Online Editing Theme
|
|
143
|
-
import React, { useState, useRef } from 'react';
|
|
146
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
144
147
|
import Colorful from '@uiw/react-color-colorful';
|
|
145
148
|
import JsonView from '@uiw/react-json-view';
|
|
146
149
|
|
|
@@ -172,6 +175,7 @@ const customTheme = {
|
|
|
172
175
|
'--w-rjv-line-color': '#323232',
|
|
173
176
|
'--w-rjv-arrow-color': '#9cdcfe',
|
|
174
177
|
'--w-rjv-info-color': '#656565',
|
|
178
|
+
'--w-rjv-update-color': '#ebcb8b',
|
|
175
179
|
'--w-rjv-copied-color': '#0184a6',
|
|
176
180
|
'--w-rjv-copied-success-color': '#28a745',
|
|
177
181
|
|
|
@@ -197,10 +201,23 @@ export default function Demo() {
|
|
|
197
201
|
setHex(hexa);
|
|
198
202
|
setTheme({ ...theme, [cssvar]: hexa });
|
|
199
203
|
};
|
|
204
|
+
|
|
205
|
+
const [src, setSrc] = useState({ ...object })
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
const loop = () => {
|
|
208
|
+
setSrc(src => ({
|
|
209
|
+
...src,
|
|
210
|
+
timer: src.timer + 1
|
|
211
|
+
}))
|
|
212
|
+
}
|
|
213
|
+
const id = setInterval(loop, 1000)
|
|
214
|
+
return () => clearInterval(id)
|
|
215
|
+
}, []);
|
|
216
|
+
|
|
200
217
|
return (
|
|
201
218
|
<React.Fragment>
|
|
202
219
|
<div style={{ display: 'flex', gap: '1rem' }}>
|
|
203
|
-
<JsonView value={
|
|
220
|
+
<JsonView value={src} keyName="root" style={{ flex: 1, ...theme }} />
|
|
204
221
|
<div>
|
|
205
222
|
<Colorful color={hex} onChange={onChange} />
|
|
206
223
|
<div style={{ display: 'flex', gap: '0.4rem', flexWrap: 'wrap' }}>
|
|
@@ -305,6 +322,50 @@ export default function Demo() {
|
|
|
305
322
|
}
|
|
306
323
|
```
|
|
307
324
|
|
|
325
|
+
## Highlight Updates
|
|
326
|
+
|
|
327
|
+
```tsx mdx:preview
|
|
328
|
+
import React, { useState, useEffect } from 'react';
|
|
329
|
+
import JsonView from '@uiw/react-json-view';
|
|
330
|
+
import { TriangleArrow } from '@uiw/react-json-view/triangle-arrow';
|
|
331
|
+
import { TriangleSolidArrow } from '@uiw/react-json-view/triangle-solid-arrow';
|
|
332
|
+
|
|
333
|
+
const object = {
|
|
334
|
+
string: 'Lorem ipsum dolor sit amet',
|
|
335
|
+
integer: 42,
|
|
336
|
+
timer: 0,
|
|
337
|
+
object: { 'first-child': true, 'second-child': false, 'last-child': null },
|
|
338
|
+
}
|
|
339
|
+
export default function Demo() {
|
|
340
|
+
const [src, setSrc] = useState({ ...object })
|
|
341
|
+
useEffect(() => {
|
|
342
|
+
const loop = () => {
|
|
343
|
+
setSrc(src => ({
|
|
344
|
+
...src,
|
|
345
|
+
timer: src.timer + 1
|
|
346
|
+
}))
|
|
347
|
+
}
|
|
348
|
+
const id = setInterval(loop, 1000)
|
|
349
|
+
return () => clearInterval(id)
|
|
350
|
+
}, []);
|
|
351
|
+
|
|
352
|
+
return (
|
|
353
|
+
<JsonView
|
|
354
|
+
value={src}
|
|
355
|
+
keyName="root"
|
|
356
|
+
style={{
|
|
357
|
+
'--w-rjv-background-color': '#ffffff',
|
|
358
|
+
'--w-rjv-border-left': '1px dashed #ebebeb',
|
|
359
|
+
// ✅ Change default update background color ✅
|
|
360
|
+
'--w-rjv-update-color': '#ff6ffd',
|
|
361
|
+
}}
|
|
362
|
+
/>
|
|
363
|
+
)
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
This feature can be disabled with `highlightUpdates={false}`, and the default color can be changed with `--w-rjv-update-color`.
|
|
368
|
+
|
|
308
369
|
## Modify Icon Style
|
|
309
370
|
|
|
310
371
|
Use built-in default icons.
|
|
@@ -424,6 +485,10 @@ export interface JsonViewProps<T> extends React.DetailedHTMLProps<React.HTMLAttr
|
|
|
424
485
|
keyName?: string | number;
|
|
425
486
|
/** The user can copy objects and arrays to clipboard by clicking on the clipboard icon. @default true */
|
|
426
487
|
enableClipboard?: boolean;
|
|
488
|
+
/** Whether to highlight updates. @default true */
|
|
489
|
+
highlightUpdates?: boolean;
|
|
490
|
+
/** Whether sort keys through `String.prototype.localeCompare()` @default false */
|
|
491
|
+
objectSortKeys?: boolean | ((a: string, b: string) => number);
|
|
427
492
|
/** Display for quotes in object-key @default " */
|
|
428
493
|
quotes?: "'" | '"' | '';
|
|
429
494
|
/** When set to true, all nodes will be collapsed by default. Use an integer value to collapse at a particular depth. @default false */
|
|
@@ -435,6 +500,8 @@ export interface JsonViewProps<T> extends React.DetailedHTMLProps<React.HTMLAttr
|
|
|
435
500
|
keyid: string;
|
|
436
501
|
keyName?: string | number;
|
|
437
502
|
}) => void;
|
|
503
|
+
/** Fires event when you copy */
|
|
504
|
+
onCopied?: CopiedProps<T>['onCopied'];
|
|
438
505
|
/** Redefine interface elements to re-render. */
|
|
439
506
|
components?: {
|
|
440
507
|
braces?: MetaProps['render'];
|
|
@@ -442,6 +509,7 @@ export interface JsonViewProps<T> extends React.DetailedHTMLProps<React.HTMLAttr
|
|
|
442
509
|
arrow?: JSX.Element;
|
|
443
510
|
objectKey?: SemicolonProps['render'];
|
|
444
511
|
value?: ValueViewProps<T>['renderValue'];
|
|
512
|
+
copied?: CopiedProps<T>['render'];
|
|
445
513
|
};
|
|
446
514
|
}
|
|
447
515
|
declare const JsonView: React.ForwardRefExoticComponent<Omit<JsonViewProps<object>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
package/cjs/copied.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export interface CopiedProps<T = object> extends React.SVGProps<SVGSVGElement> {
|
|
3
3
|
show?: boolean;
|
|
4
4
|
text?: T;
|
|
5
|
-
onCopied?: (text: string, obj: T) => void;
|
|
5
|
+
onCopied?: (text: string, obj: T | '') => void;
|
|
6
6
|
render?: (props: Omit<CopiedProps<T>, 'render'>) => JSX.Element;
|
|
7
7
|
}
|
|
8
8
|
export declare function Copied<T>(props: CopiedProps<T>): JSX.Element | null;
|
package/cjs/copied.js
CHANGED
|
@@ -10,12 +10,13 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
|
|
|
10
10
|
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
|
|
11
11
|
var _react = require("react");
|
|
12
12
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
13
|
-
var _excluded = ["children", "style", "text", "render", "show"];
|
|
13
|
+
var _excluded = ["children", "style", "text", "onCopied", "render", "show"];
|
|
14
14
|
function Copied(props) {
|
|
15
15
|
var children = props.children,
|
|
16
16
|
style = props.style,
|
|
17
17
|
_props$text = props.text,
|
|
18
18
|
text = _props$text === void 0 ? '' : _props$text,
|
|
19
|
+
onCopied = props.onCopied,
|
|
19
20
|
render = props.render,
|
|
20
21
|
show = props.show,
|
|
21
22
|
reset = (0, _objectWithoutProperties2["default"])(props, _excluded);
|
|
@@ -26,7 +27,7 @@ function Copied(props) {
|
|
|
26
27
|
setCopied = _useState2[1];
|
|
27
28
|
var click = function click(event) {
|
|
28
29
|
event.stopPropagation();
|
|
29
|
-
var copyText = JSON.stringify(text, function (key, value) {
|
|
30
|
+
var copyText = JSON.stringify(text || '', function (key, value) {
|
|
30
31
|
if (typeof value === 'bigint') {
|
|
31
32
|
return value.toString();
|
|
32
33
|
}
|
|
@@ -34,6 +35,7 @@ function Copied(props) {
|
|
|
34
35
|
}, 2);
|
|
35
36
|
if (text === Infinity) copyText = Infinity;
|
|
36
37
|
navigator.clipboard.writeText(copyText).then(function () {
|
|
38
|
+
onCopied && onCopied(copyText, text);
|
|
37
39
|
setCopied(true);
|
|
38
40
|
var timer = setTimeout(function () {
|
|
39
41
|
setCopied(false);
|
package/cjs/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { MetaProps,
|
|
2
|
+
import { MetaProps, EllipsisProps } from './node';
|
|
3
|
+
import { SemicolonProps } from './semicolon';
|
|
3
4
|
import { ValueViewProps } from './value';
|
|
4
5
|
import { CopiedProps } from './copied';
|
|
5
6
|
export * from './node';
|
|
@@ -17,6 +18,10 @@ export interface JsonViewProps<T extends object> extends React.DetailedHTMLProps
|
|
|
17
18
|
keyName?: string | number;
|
|
18
19
|
/** The user can copy objects and arrays to clipboard by clicking on the clipboard icon. @default true */
|
|
19
20
|
enableClipboard?: boolean;
|
|
21
|
+
/** Whether to highlight updates. @default true */
|
|
22
|
+
highlightUpdates?: boolean;
|
|
23
|
+
/** Whether sort keys through `String.prototype.localeCompare()` @default false */
|
|
24
|
+
objectSortKeys?: boolean | ((a: string, b: string) => number);
|
|
20
25
|
/** Display for quotes in object-key @default " */
|
|
21
26
|
quotes?: "'" | '"' | '';
|
|
22
27
|
/** When set to true, all nodes will be collapsed by default. Use an integer value to collapse at a particular depth. @default false */
|
package/cjs/node.d.ts
CHANGED
|
@@ -11,13 +11,6 @@ export interface EllipsisProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
|
11
11
|
render?: (props: EllipsisProps) => JSX.Element;
|
|
12
12
|
}
|
|
13
13
|
export declare const Ellipsis: FC<PropsWithChildren<EllipsisProps>>;
|
|
14
|
-
export interface SemicolonProps extends LabelProps {
|
|
15
|
-
show?: boolean;
|
|
16
|
-
quotes?: JsonViewProps<object>['quotes'];
|
|
17
|
-
value?: object;
|
|
18
|
-
render?: (props: Omit<SemicolonProps, 'show'> & {}) => JSX.Element;
|
|
19
|
-
}
|
|
20
|
-
export declare const Semicolon: FC<PropsWithChildren<SemicolonProps>>;
|
|
21
14
|
export declare const CountInfo: FC<PropsWithChildren<LabelProps>>;
|
|
22
15
|
export interface RooNodeProps<T extends object> extends JsonViewProps<T> {
|
|
23
16
|
keyName?: string | number;
|
package/cjs/node.js
CHANGED
|
@@ -7,7 +7,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.Ellipsis = exports.CountInfo = void 0;
|
|
8
8
|
exports.Meta = Meta;
|
|
9
9
|
exports.RooNode = RooNode;
|
|
10
|
-
exports.Semicolon = void 0;
|
|
11
10
|
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
12
11
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
13
12
|
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
|
|
@@ -17,11 +16,11 @@ var _value = require("./value");
|
|
|
17
16
|
var _TriangleArrow = require("./arrow/TriangleArrow");
|
|
18
17
|
var _store = require("./store");
|
|
19
18
|
var _copied = require("./copied");
|
|
19
|
+
var _semicolon = require("./semicolon");
|
|
20
20
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
21
21
|
var _excluded = ["isArray", "start", "className", "render"],
|
|
22
22
|
_excluded2 = ["style", "render"],
|
|
23
|
-
_excluded3 = ["
|
|
24
|
-
_excluded4 = ["value", "keyName", "displayDataTypes", "components", "displayObjectSize", "enableClipboard", "indentWidth", "collapsed", "level", "keyid", "quotes", "onCopied", "onExpand"];
|
|
23
|
+
_excluded3 = ["value", "keyName", "className", "displayDataTypes", "components", "displayObjectSize", "enableClipboard", "highlightUpdates", "objectSortKeys", "indentWidth", "collapsed", "level", "keyid", "quotes", "onCopied", "onExpand"];
|
|
25
24
|
function Meta(props) {
|
|
26
25
|
var _props$isArray = props.isArray,
|
|
27
26
|
isArray = _props$isArray === void 0 ? false : _props$isArray,
|
|
@@ -69,36 +68,8 @@ var Ellipsis = function Ellipsis(_ref) {
|
|
|
69
68
|
}));
|
|
70
69
|
};
|
|
71
70
|
exports.Ellipsis = Ellipsis;
|
|
72
|
-
var
|
|
73
|
-
var children = _ref2.children
|
|
74
|
-
render = _ref2.render,
|
|
75
|
-
color = _ref2.color,
|
|
76
|
-
value = _ref2.value,
|
|
77
|
-
_ref2$className = _ref2.className,
|
|
78
|
-
className = _ref2$className === void 0 ? 'w-rjv-object-key' : _ref2$className,
|
|
79
|
-
show = _ref2.show,
|
|
80
|
-
quotes = _ref2.quotes,
|
|
81
|
-
props = (0, _objectWithoutProperties2["default"])(_ref2, _excluded3);
|
|
82
|
-
var content = show ? "".concat(quotes).concat(children).concat(quotes) : children;
|
|
83
|
-
if (render) return render((0, _objectSpread2["default"])((0, _objectSpread2["default"])({
|
|
84
|
-
className: className
|
|
85
|
-
}, props), {}, {
|
|
86
|
-
value: value,
|
|
87
|
-
style: {
|
|
88
|
-
color: color
|
|
89
|
-
},
|
|
90
|
-
children: content
|
|
91
|
-
}));
|
|
92
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_value.Label, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({
|
|
93
|
-
className: className,
|
|
94
|
-
color: color
|
|
95
|
-
}, props), {}, {
|
|
96
|
-
children: content
|
|
97
|
-
}));
|
|
98
|
-
};
|
|
99
|
-
exports.Semicolon = Semicolon;
|
|
100
|
-
var CountInfo = function CountInfo(_ref3) {
|
|
101
|
-
var children = _ref3.children;
|
|
71
|
+
var CountInfo = function CountInfo(_ref2) {
|
|
72
|
+
var children = _ref2.children;
|
|
102
73
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_value.Label, {
|
|
103
74
|
style: {
|
|
104
75
|
paddingLeft: 4,
|
|
@@ -115,6 +86,7 @@ function RooNode(props) {
|
|
|
115
86
|
var _props$value = props.value,
|
|
116
87
|
value = _props$value === void 0 ? {} : _props$value,
|
|
117
88
|
keyName = props.keyName,
|
|
89
|
+
className = props.className,
|
|
118
90
|
_props$displayDataTyp = props.displayDataTypes,
|
|
119
91
|
displayDataTypes = _props$displayDataTyp === void 0 ? true : _props$displayDataTyp,
|
|
120
92
|
_props$components = props.components,
|
|
@@ -123,6 +95,10 @@ function RooNode(props) {
|
|
|
123
95
|
displayObjectSize = _props$displayObjectS === void 0 ? true : _props$displayObjectS,
|
|
124
96
|
_props$enableClipboar = props.enableClipboard,
|
|
125
97
|
enableClipboard = _props$enableClipboar === void 0 ? true : _props$enableClipboar,
|
|
98
|
+
_props$highlightUpdat = props.highlightUpdates,
|
|
99
|
+
highlightUpdates = _props$highlightUpdat === void 0 ? true : _props$highlightUpdat,
|
|
100
|
+
_props$objectSortKeys = props.objectSortKeys,
|
|
101
|
+
objectSortKeys = _props$objectSortKeys === void 0 ? false : _props$objectSortKeys,
|
|
126
102
|
_props$indentWidth = props.indentWidth,
|
|
127
103
|
indentWidth = _props$indentWidth === void 0 ? 15 : _props$indentWidth,
|
|
128
104
|
collapsed = props.collapsed,
|
|
@@ -134,11 +110,8 @@ function RooNode(props) {
|
|
|
134
110
|
quotes = _props$quotes === void 0 ? '"' : _props$quotes,
|
|
135
111
|
onCopied = props.onCopied,
|
|
136
112
|
onExpand = props.onExpand,
|
|
137
|
-
reset = (0, _objectWithoutProperties2["default"])(props,
|
|
113
|
+
reset = (0, _objectWithoutProperties2["default"])(props, _excluded3);
|
|
138
114
|
var isArray = Array.isArray(value);
|
|
139
|
-
var nameKeys = isArray ? Object.keys(value).map(function (m) {
|
|
140
|
-
return Number(m);
|
|
141
|
-
}) : Object.keys(value);
|
|
142
115
|
var subkeyid = (0, _react.useId)();
|
|
143
116
|
var expands = (0, _store.useExpandsStatus)();
|
|
144
117
|
var expand = (_expands$keyid = expands[keyid]) !== null && _expands$keyid !== void 0 ? _expands$keyid : typeof collapsed === 'boolean' ? collapsed : typeof collapsed === 'number' ? level <= collapsed : true;
|
|
@@ -161,6 +134,7 @@ function RooNode(props) {
|
|
|
161
134
|
displayDataTypes: displayDataTypes,
|
|
162
135
|
displayObjectSize: displayObjectSize,
|
|
163
136
|
enableClipboard: enableClipboard,
|
|
137
|
+
highlightUpdates: highlightUpdates,
|
|
164
138
|
onCopied: onCopied,
|
|
165
139
|
onExpand: onExpand,
|
|
166
140
|
collapsed: collapsed,
|
|
@@ -205,8 +179,31 @@ function RooNode(props) {
|
|
|
205
179
|
return setShowTools(false);
|
|
206
180
|
};
|
|
207
181
|
}
|
|
182
|
+
var nameKeys = isArray ? Object.keys(value).map(function (m) {
|
|
183
|
+
return Number(m);
|
|
184
|
+
}) : Object.keys(value);
|
|
185
|
+
|
|
186
|
+
// object
|
|
187
|
+
var entries = isArray ? Object.entries(value).map(function (m) {
|
|
188
|
+
return [Number(m[0]), m[1]];
|
|
189
|
+
}) : Object.entries(value);
|
|
190
|
+
if (objectSortKeys) {
|
|
191
|
+
entries = objectSortKeys === true ? entries.sort(function (_ref3, _ref4) {
|
|
192
|
+
var _ref5 = (0, _slicedToArray2["default"])(_ref3, 1),
|
|
193
|
+
a = _ref5[0];
|
|
194
|
+
var _ref6 = (0, _slicedToArray2["default"])(_ref4, 1),
|
|
195
|
+
b = _ref6[0];
|
|
196
|
+
return typeof a === 'string' && typeof b === 'string' ? a.localeCompare(b) : 0;
|
|
197
|
+
}) : entries.sort(function (_ref7, _ref8) {
|
|
198
|
+
var _ref9 = (0, _slicedToArray2["default"])(_ref7, 1),
|
|
199
|
+
a = _ref9[0];
|
|
200
|
+
var _ref10 = (0, _slicedToArray2["default"])(_ref8, 1),
|
|
201
|
+
b = _ref10[0];
|
|
202
|
+
return typeof a === 'string' && typeof b === 'string' ? objectSortKeys(a, b) : 0;
|
|
203
|
+
});
|
|
204
|
+
}
|
|
208
205
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", (0, _objectSpread2["default"])((0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, reset), {}, {
|
|
209
|
-
className: "w-rjv-inner"
|
|
206
|
+
className: "".concat(className, " w-rjv-inner")
|
|
210
207
|
}, eventProps), {}, {
|
|
211
208
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_value.Line, {
|
|
212
209
|
style: {
|
|
@@ -215,7 +212,7 @@ function RooNode(props) {
|
|
|
215
212
|
},
|
|
216
213
|
onClick: handle,
|
|
217
214
|
children: [arrowView, (typeof keyName === 'string' || typeof keyName === 'number') && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_react.Fragment, {
|
|
218
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Semicolon, {
|
|
215
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_semicolon.Semicolon, {
|
|
219
216
|
value: value,
|
|
220
217
|
quotes: quotes,
|
|
221
218
|
render: components.objectKey,
|
|
@@ -241,11 +238,15 @@ function RooNode(props) {
|
|
|
241
238
|
borderLeft: 'var(--w-rjv-border-left-width, 1px) solid var(--w-rjv-line-color, #ebebeb)',
|
|
242
239
|
marginLeft: 6
|
|
243
240
|
},
|
|
244
|
-
children:
|
|
245
|
-
var
|
|
246
|
-
|
|
241
|
+
children: entries.length > 0 && entries.map(function (_ref11, idx) {
|
|
242
|
+
var _ref12 = (0, _slicedToArray2["default"])(_ref11, 2),
|
|
243
|
+
key = _ref12[0],
|
|
244
|
+
itemVal = _ref12[1];
|
|
245
|
+
var item = itemVal;
|
|
246
|
+
var renderKey = /*#__PURE__*/(0, _jsxRuntime.jsx)(_semicolon.Semicolon, {
|
|
247
247
|
value: item,
|
|
248
248
|
quotes: quotes,
|
|
249
|
+
highlightUpdates: highlightUpdates,
|
|
249
250
|
render: components.objectKey,
|
|
250
251
|
color: typeof key === 'number' ? _value.typeMap['number'].color : '',
|
|
251
252
|
show: typeof key === 'string',
|
|
@@ -271,7 +272,7 @@ function RooNode(props) {
|
|
|
271
272
|
value: item,
|
|
272
273
|
keyName: key
|
|
273
274
|
}, subNodeProps))
|
|
274
|
-
}, key + idx);
|
|
275
|
+
}, key + '' + idx);
|
|
275
276
|
}
|
|
276
277
|
if (typeof item === 'function') {
|
|
277
278
|
return;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FC, PropsWithChildren } from 'react';
|
|
2
|
+
import { LabelProps } from './value';
|
|
3
|
+
import { JsonViewProps } from './';
|
|
4
|
+
export declare function usePrevious<T>(value: T): T | undefined;
|
|
5
|
+
export interface SemicolonProps extends LabelProps {
|
|
6
|
+
show?: boolean;
|
|
7
|
+
highlightUpdates?: boolean;
|
|
8
|
+
quotes?: JsonViewProps<object>['quotes'];
|
|
9
|
+
value?: object;
|
|
10
|
+
render?: (props: Omit<SemicolonProps, 'show'> & {}) => JSX.Element;
|
|
11
|
+
}
|
|
12
|
+
export declare const Semicolon: FC<PropsWithChildren<SemicolonProps>>;
|
package/cjs/semicolon.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.Semicolon = void 0;
|
|
8
|
+
exports.usePrevious = usePrevious;
|
|
9
|
+
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
|
|
10
|
+
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
11
|
+
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
|
|
12
|
+
var _react = require("react");
|
|
13
|
+
var _value = require("./value");
|
|
14
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
15
|
+
var _excluded = ["children", "render", "color", "value", "className", "show", "highlightUpdates", "quotes", "style"];
|
|
16
|
+
function usePrevious(value) {
|
|
17
|
+
var ref = (0, _react.useRef)();
|
|
18
|
+
(0, _react.useEffect)(function () {
|
|
19
|
+
ref.current = value;
|
|
20
|
+
});
|
|
21
|
+
return ref.current;
|
|
22
|
+
}
|
|
23
|
+
var Semicolon = function Semicolon(_ref) {
|
|
24
|
+
var children = _ref.children,
|
|
25
|
+
render = _ref.render,
|
|
26
|
+
color = _ref.color,
|
|
27
|
+
value = _ref.value,
|
|
28
|
+
_ref$className = _ref.className,
|
|
29
|
+
className = _ref$className === void 0 ? 'w-rjv-object-key' : _ref$className,
|
|
30
|
+
show = _ref.show,
|
|
31
|
+
highlightUpdates = _ref.highlightUpdates,
|
|
32
|
+
quotes = _ref.quotes,
|
|
33
|
+
style = _ref.style,
|
|
34
|
+
props = (0, _objectWithoutProperties2["default"])(_ref, _excluded);
|
|
35
|
+
var prevValue = usePrevious(value);
|
|
36
|
+
var highlightContainer = (0, _react.useRef)(null);
|
|
37
|
+
var isHighlight = (0, _react.useMemo)(function () {
|
|
38
|
+
if (!highlightUpdates || prevValue === undefined) return false;
|
|
39
|
+
// highlight if value type changed
|
|
40
|
+
if ((0, _typeof2["default"])(value) !== (0, _typeof2["default"])(prevValue)) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
if (typeof value === 'number') {
|
|
44
|
+
// notice: NaN !== NaN
|
|
45
|
+
if (isNaN(value) && isNaN(prevValue)) return false;
|
|
46
|
+
return value !== prevValue;
|
|
47
|
+
}
|
|
48
|
+
// highlight if isArray changed
|
|
49
|
+
if (Array.isArray(value) !== Array.isArray(prevValue)) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
// not highlight object/function
|
|
53
|
+
// deep compare they will be slow
|
|
54
|
+
if ((0, _typeof2["default"])(value) === 'object' || typeof value === 'function') {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// highlight if not equal
|
|
59
|
+
if (value !== prevValue) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}, [highlightUpdates, value]);
|
|
64
|
+
(0, _react.useEffect)(function () {
|
|
65
|
+
if (highlightContainer.current && isHighlight && 'animate' in highlightContainer.current) {
|
|
66
|
+
highlightContainer.current.animate([{
|
|
67
|
+
backgroundColor: 'var(--w-rjv-update-color, #ebcb8b)'
|
|
68
|
+
}, {
|
|
69
|
+
backgroundColor: ''
|
|
70
|
+
}], {
|
|
71
|
+
duration: 1000,
|
|
72
|
+
easing: 'ease-in'
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}, [isHighlight, value]);
|
|
76
|
+
var content = show ? "".concat(quotes).concat(children).concat(quotes) : children;
|
|
77
|
+
if (render) return render((0, _objectSpread2["default"])((0, _objectSpread2["default"])({
|
|
78
|
+
className: className
|
|
79
|
+
}, props), {}, {
|
|
80
|
+
value: value,
|
|
81
|
+
style: (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, style), {}, {
|
|
82
|
+
color: color
|
|
83
|
+
}),
|
|
84
|
+
children: content
|
|
85
|
+
}));
|
|
86
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_value.Label, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({
|
|
87
|
+
className: className,
|
|
88
|
+
color: color
|
|
89
|
+
}, props), {}, {
|
|
90
|
+
ref: highlightContainer,
|
|
91
|
+
children: content
|
|
92
|
+
}));
|
|
93
|
+
};
|
|
94
|
+
exports.Semicolon = Semicolon;
|
package/cjs/theme/dark.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export declare const darkTheme: {
|
|
|
5
5
|
'--w-rjv-line-color': string;
|
|
6
6
|
'--w-rjv-arrow-color': string;
|
|
7
7
|
'--w-rjv-info-color': string;
|
|
8
|
+
'--w-rjv-update-color': string;
|
|
8
9
|
'--w-rjv-copied-color': string;
|
|
9
10
|
'--w-rjv-copied-success-color': string;
|
|
10
11
|
'--w-rjv-curlybraces-color': string;
|
package/cjs/theme/dark.js
CHANGED
|
@@ -11,6 +11,7 @@ var darkTheme = {
|
|
|
11
11
|
'--w-rjv-line-color': '#323232',
|
|
12
12
|
'--w-rjv-arrow-color': 'var(--w-rjv-color)',
|
|
13
13
|
'--w-rjv-info-color': '#656565',
|
|
14
|
+
'--w-rjv-update-color': '#ebcb8b',
|
|
14
15
|
'--w-rjv-copied-color': '#0184a6',
|
|
15
16
|
'--w-rjv-copied-success-color': '#28a745',
|
|
16
17
|
'--w-rjv-curlybraces-color': '#1896b6',
|
package/cjs/theme/light.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export declare const lightTheme: {
|
|
|
5
5
|
'--w-rjv-line-color': string;
|
|
6
6
|
'--w-rjv-arrow-color': string;
|
|
7
7
|
'--w-rjv-info-color': string;
|
|
8
|
+
'--w-rjv-update-color': string;
|
|
8
9
|
'--w-rjv-copied-color': string;
|
|
9
10
|
'--w-rjv-copied-success-color': string;
|
|
10
11
|
'--w-rjv-curlybraces-color': string;
|
package/cjs/theme/light.js
CHANGED
|
@@ -11,6 +11,7 @@ var lightTheme = {
|
|
|
11
11
|
'--w-rjv-line-color': '#ebebeb',
|
|
12
12
|
'--w-rjv-arrow-color': 'var(--w-rjv-color)',
|
|
13
13
|
'--w-rjv-info-color': '#0000004d',
|
|
14
|
+
'--w-rjv-update-color': '#ebcb8b',
|
|
14
15
|
'--w-rjv-copied-color': '#002b36',
|
|
15
16
|
'--w-rjv-copied-success-color': '#28a745',
|
|
16
17
|
'--w-rjv-curlybraces-color': '#236a7c',
|
package/cjs/value.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export declare const typeMap: {
|
|
|
41
41
|
};
|
|
42
42
|
export declare const Colon: FC<PropsWithChildren<React.HTMLAttributes<HTMLSpanElement>>>;
|
|
43
43
|
export interface ValueViewProps<T> extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement> {
|
|
44
|
-
keyName?: string;
|
|
44
|
+
keyName?: string | number;
|
|
45
45
|
value?: T;
|
|
46
46
|
displayDataTypes: boolean;
|
|
47
47
|
displayObjectSize: boolean;
|
|
@@ -60,7 +60,7 @@ export interface LabelProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
|
60
60
|
opacity?: number;
|
|
61
61
|
paddingRight?: number;
|
|
62
62
|
}
|
|
63
|
-
export declare const Label:
|
|
63
|
+
export declare const Label: import("react").ForwardRefExoticComponent<LabelProps & import("react").RefAttributes<HTMLSpanElement>>;
|
|
64
64
|
export interface TypeProps extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement> {
|
|
65
65
|
type: keyof typeof typeMap;
|
|
66
66
|
}
|
package/cjs/value.js
CHANGED
|
@@ -174,6 +174,7 @@ function ValueView(props) {
|
|
|
174
174
|
});
|
|
175
175
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, eventProps), {}, {
|
|
176
176
|
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(Label, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, reset), {}, {
|
|
177
|
+
ref: null,
|
|
177
178
|
children: [renderKey, /*#__PURE__*/(0, _jsxRuntime.jsx)(Colon, {}), typeView, valueView, tools]
|
|
178
179
|
}))
|
|
179
180
|
}));
|
|
@@ -193,11 +194,12 @@ function ValueView(props) {
|
|
|
193
194
|
});
|
|
194
195
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, eventProps), {}, {
|
|
195
196
|
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(Label, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, reset), {}, {
|
|
197
|
+
ref: null,
|
|
196
198
|
children: [renderKey, /*#__PURE__*/(0, _jsxRuntime.jsx)(Colon, {}), typeView, empty, tools]
|
|
197
199
|
}))
|
|
198
200
|
}));
|
|
199
201
|
}
|
|
200
|
-
var Label = function
|
|
202
|
+
var Label = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
|
|
201
203
|
var children = _ref2.children,
|
|
202
204
|
color = _ref2.color,
|
|
203
205
|
fontSize = _ref2.fontSize,
|
|
@@ -213,9 +215,10 @@ var Label = function Label(_ref2) {
|
|
|
213
215
|
paddingRight: paddingRight
|
|
214
216
|
}, style)
|
|
215
217
|
}, reset), {}, {
|
|
218
|
+
ref: ref,
|
|
216
219
|
children: children
|
|
217
220
|
}));
|
|
218
|
-
};
|
|
221
|
+
});
|
|
219
222
|
exports.Label = Label;
|
|
220
223
|
var Type = function Type(props) {
|
|
221
224
|
var _typeMap$type2, _typeMap$type3;
|
package/esm/copied.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export interface CopiedProps<T = object> extends React.SVGProps<SVGSVGElement> {
|
|
3
3
|
show?: boolean;
|
|
4
4
|
text?: T;
|
|
5
|
-
onCopied?: (text: string, obj: T) => void;
|
|
5
|
+
onCopied?: (text: string, obj: T | '') => void;
|
|
6
6
|
render?: (props: Omit<CopiedProps<T>, 'render'>) => JSX.Element;
|
|
7
7
|
}
|
|
8
8
|
export declare function Copied<T>(props: CopiedProps<T>): JSX.Element | null;
|
package/esm/copied.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
|
|
3
|
-
var _excluded = ["children", "style", "text", "render", "show"];
|
|
3
|
+
var _excluded = ["children", "style", "text", "onCopied", "render", "show"];
|
|
4
4
|
import { useState } from 'react';
|
|
5
5
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
6
|
export function Copied(props) {
|
|
7
7
|
var {
|
|
8
8
|
style,
|
|
9
9
|
text = '',
|
|
10
|
+
onCopied,
|
|
10
11
|
render,
|
|
11
12
|
show
|
|
12
13
|
} = props,
|
|
@@ -15,7 +16,7 @@ export function Copied(props) {
|
|
|
15
16
|
var [copied, setCopied] = useState(false);
|
|
16
17
|
var click = event => {
|
|
17
18
|
event.stopPropagation();
|
|
18
|
-
var copyText = JSON.stringify(text, (key, value) => {
|
|
19
|
+
var copyText = JSON.stringify(text || '', (key, value) => {
|
|
19
20
|
if (typeof value === 'bigint') {
|
|
20
21
|
return value.toString();
|
|
21
22
|
}
|
|
@@ -23,6 +24,7 @@ export function Copied(props) {
|
|
|
23
24
|
}, 2);
|
|
24
25
|
if (text === Infinity) copyText = Infinity;
|
|
25
26
|
navigator.clipboard.writeText(copyText).then(() => {
|
|
27
|
+
onCopied && onCopied(copyText, text);
|
|
26
28
|
setCopied(true);
|
|
27
29
|
var timer = setTimeout(() => {
|
|
28
30
|
setCopied(false);
|
package/esm/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { MetaProps,
|
|
2
|
+
import { MetaProps, EllipsisProps } from './node';
|
|
3
|
+
import { SemicolonProps } from './semicolon';
|
|
3
4
|
import { ValueViewProps } from './value';
|
|
4
5
|
import { CopiedProps } from './copied';
|
|
5
6
|
export * from './node';
|
|
@@ -17,6 +18,10 @@ export interface JsonViewProps<T extends object> extends React.DetailedHTMLProps
|
|
|
17
18
|
keyName?: string | number;
|
|
18
19
|
/** The user can copy objects and arrays to clipboard by clicking on the clipboard icon. @default true */
|
|
19
20
|
enableClipboard?: boolean;
|
|
21
|
+
/** Whether to highlight updates. @default true */
|
|
22
|
+
highlightUpdates?: boolean;
|
|
23
|
+
/** Whether sort keys through `String.prototype.localeCompare()` @default false */
|
|
24
|
+
objectSortKeys?: boolean | ((a: string, b: string) => number);
|
|
20
25
|
/** Display for quotes in object-key @default " */
|
|
21
26
|
quotes?: "'" | '"' | '';
|
|
22
27
|
/** When set to true, all nodes will be collapsed by default. Use an integer value to collapse at a particular depth. @default false */
|
package/esm/node.d.ts
CHANGED
|
@@ -11,13 +11,6 @@ export interface EllipsisProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
|
11
11
|
render?: (props: EllipsisProps) => JSX.Element;
|
|
12
12
|
}
|
|
13
13
|
export declare const Ellipsis: FC<PropsWithChildren<EllipsisProps>>;
|
|
14
|
-
export interface SemicolonProps extends LabelProps {
|
|
15
|
-
show?: boolean;
|
|
16
|
-
quotes?: JsonViewProps<object>['quotes'];
|
|
17
|
-
value?: object;
|
|
18
|
-
render?: (props: Omit<SemicolonProps, 'show'> & {}) => JSX.Element;
|
|
19
|
-
}
|
|
20
|
-
export declare const Semicolon: FC<PropsWithChildren<SemicolonProps>>;
|
|
21
14
|
export declare const CountInfo: FC<PropsWithChildren<LabelProps>>;
|
|
22
15
|
export interface RooNodeProps<T extends object> extends JsonViewProps<T> {
|
|
23
16
|
keyName?: string | number;
|
package/esm/node.js
CHANGED
|
@@ -2,13 +2,13 @@ import _extends from "@babel/runtime/helpers/extends";
|
|
|
2
2
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
|
|
3
3
|
var _excluded = ["isArray", "start", "className", "render"],
|
|
4
4
|
_excluded2 = ["style", "render"],
|
|
5
|
-
_excluded3 = ["
|
|
6
|
-
_excluded4 = ["value", "keyName", "displayDataTypes", "components", "displayObjectSize", "enableClipboard", "indentWidth", "collapsed", "level", "keyid", "quotes", "onCopied", "onExpand"];
|
|
5
|
+
_excluded3 = ["value", "keyName", "className", "displayDataTypes", "components", "displayObjectSize", "enableClipboard", "highlightUpdates", "objectSortKeys", "indentWidth", "collapsed", "level", "keyid", "quotes", "onCopied", "onExpand"];
|
|
7
6
|
import { Fragment, useId, cloneElement, useState } from 'react';
|
|
8
7
|
import { ValueView, Colon, Label, Line, typeMap } from './value';
|
|
9
8
|
import { TriangleArrow } from './arrow/TriangleArrow';
|
|
10
9
|
import { useExpandsStatus, store } from './store';
|
|
11
10
|
import { Copied } from './copied';
|
|
11
|
+
import { Semicolon } from './semicolon';
|
|
12
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
13
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
14
|
export function Meta(props) {
|
|
@@ -59,38 +59,10 @@ export var Ellipsis = _ref => {
|
|
|
59
59
|
children: "..."
|
|
60
60
|
}));
|
|
61
61
|
};
|
|
62
|
-
export var
|
|
63
|
-
var {
|
|
64
|
-
children,
|
|
65
|
-
render,
|
|
66
|
-
color,
|
|
67
|
-
value,
|
|
68
|
-
className = 'w-rjv-object-key',
|
|
69
|
-
show,
|
|
70
|
-
quotes
|
|
71
|
-
} = _ref2,
|
|
72
|
-
props = _objectWithoutPropertiesLoose(_ref2, _excluded3);
|
|
73
|
-
var content = show ? "" + quotes + children + quotes : children;
|
|
74
|
-
if (render) return render(_extends({
|
|
75
|
-
className
|
|
76
|
-
}, props, {
|
|
77
|
-
value,
|
|
78
|
-
style: {
|
|
79
|
-
color
|
|
80
|
-
},
|
|
81
|
-
children: content
|
|
82
|
-
}));
|
|
83
|
-
return /*#__PURE__*/_jsx(Label, _extends({
|
|
84
|
-
className: className,
|
|
85
|
-
color: color
|
|
86
|
-
}, props, {
|
|
87
|
-
children: content
|
|
88
|
-
}));
|
|
89
|
-
};
|
|
90
|
-
export var CountInfo = _ref3 => {
|
|
62
|
+
export var CountInfo = _ref2 => {
|
|
91
63
|
var {
|
|
92
64
|
children
|
|
93
|
-
} =
|
|
65
|
+
} = _ref2;
|
|
94
66
|
return /*#__PURE__*/_jsx(Label, {
|
|
95
67
|
style: {
|
|
96
68
|
paddingLeft: 4,
|
|
@@ -106,10 +78,13 @@ export function RooNode(props) {
|
|
|
106
78
|
var {
|
|
107
79
|
value = {},
|
|
108
80
|
keyName,
|
|
81
|
+
className,
|
|
109
82
|
displayDataTypes = true,
|
|
110
83
|
components = {},
|
|
111
84
|
displayObjectSize = true,
|
|
112
85
|
enableClipboard = true,
|
|
86
|
+
highlightUpdates = true,
|
|
87
|
+
objectSortKeys = false,
|
|
113
88
|
indentWidth = 15,
|
|
114
89
|
collapsed,
|
|
115
90
|
level = 1,
|
|
@@ -118,9 +93,8 @@ export function RooNode(props) {
|
|
|
118
93
|
onCopied,
|
|
119
94
|
onExpand
|
|
120
95
|
} = props,
|
|
121
|
-
reset = _objectWithoutPropertiesLoose(props,
|
|
96
|
+
reset = _objectWithoutPropertiesLoose(props, _excluded3);
|
|
122
97
|
var isArray = Array.isArray(value);
|
|
123
|
-
var nameKeys = isArray ? Object.keys(value).map(m => Number(m)) : Object.keys(value);
|
|
124
98
|
var subkeyid = useId();
|
|
125
99
|
var expands = useExpandsStatus();
|
|
126
100
|
var expand = (_expands$keyid = expands[keyid]) != null ? _expands$keyid : typeof collapsed === 'boolean' ? collapsed : typeof collapsed === 'number' ? level <= collapsed : true;
|
|
@@ -143,6 +117,7 @@ export function RooNode(props) {
|
|
|
143
117
|
displayDataTypes,
|
|
144
118
|
displayObjectSize,
|
|
145
119
|
enableClipboard,
|
|
120
|
+
highlightUpdates,
|
|
146
121
|
onCopied,
|
|
147
122
|
onExpand,
|
|
148
123
|
collapsed,
|
|
@@ -180,8 +155,23 @@ export function RooNode(props) {
|
|
|
180
155
|
eventProps.onMouseEnter = () => setShowTools(true);
|
|
181
156
|
eventProps.onMouseLeave = () => setShowTools(false);
|
|
182
157
|
}
|
|
158
|
+
var nameKeys = isArray ? Object.keys(value).map(m => Number(m)) : Object.keys(value);
|
|
159
|
+
|
|
160
|
+
// object
|
|
161
|
+
var entries = isArray ? Object.entries(value).map(m => [Number(m[0]), m[1]]) : Object.entries(value);
|
|
162
|
+
if (objectSortKeys) {
|
|
163
|
+
entries = objectSortKeys === true ? entries.sort((_ref3, _ref4) => {
|
|
164
|
+
var [a] = _ref3;
|
|
165
|
+
var [b] = _ref4;
|
|
166
|
+
return typeof a === 'string' && typeof b === 'string' ? a.localeCompare(b) : 0;
|
|
167
|
+
}) : entries.sort((_ref5, _ref6) => {
|
|
168
|
+
var [a] = _ref5;
|
|
169
|
+
var [b] = _ref6;
|
|
170
|
+
return typeof a === 'string' && typeof b === 'string' ? objectSortKeys(a, b) : 0;
|
|
171
|
+
});
|
|
172
|
+
}
|
|
183
173
|
return /*#__PURE__*/_jsxs("div", _extends({}, reset, {
|
|
184
|
-
className: "w-rjv-inner"
|
|
174
|
+
className: className + " w-rjv-inner"
|
|
185
175
|
}, eventProps, {
|
|
186
176
|
children: [/*#__PURE__*/_jsxs(Line, {
|
|
187
177
|
style: {
|
|
@@ -216,11 +206,13 @@ export function RooNode(props) {
|
|
|
216
206
|
borderLeft: 'var(--w-rjv-border-left-width, 1px) solid var(--w-rjv-line-color, #ebebeb)',
|
|
217
207
|
marginLeft: 6
|
|
218
208
|
},
|
|
219
|
-
children:
|
|
220
|
-
var
|
|
209
|
+
children: entries.length > 0 && entries.map((_ref7, idx) => {
|
|
210
|
+
var [key, itemVal] = _ref7;
|
|
211
|
+
var item = itemVal;
|
|
221
212
|
var renderKey = /*#__PURE__*/_jsx(Semicolon, {
|
|
222
213
|
value: item,
|
|
223
214
|
quotes: quotes,
|
|
215
|
+
highlightUpdates: highlightUpdates,
|
|
224
216
|
render: components.objectKey,
|
|
225
217
|
color: typeof key === 'number' ? typeMap['number'].color : '',
|
|
226
218
|
show: typeof key === 'string',
|
|
@@ -246,7 +238,7 @@ export function RooNode(props) {
|
|
|
246
238
|
value: item,
|
|
247
239
|
keyName: key
|
|
248
240
|
}, subNodeProps))
|
|
249
|
-
}, key + idx);
|
|
241
|
+
}, key + '' + idx);
|
|
250
242
|
}
|
|
251
243
|
if (typeof item === 'function') {
|
|
252
244
|
return;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FC, PropsWithChildren } from 'react';
|
|
2
|
+
import { LabelProps } from './value';
|
|
3
|
+
import { JsonViewProps } from './';
|
|
4
|
+
export declare function usePrevious<T>(value: T): T | undefined;
|
|
5
|
+
export interface SemicolonProps extends LabelProps {
|
|
6
|
+
show?: boolean;
|
|
7
|
+
highlightUpdates?: boolean;
|
|
8
|
+
quotes?: JsonViewProps<object>['quotes'];
|
|
9
|
+
value?: object;
|
|
10
|
+
render?: (props: Omit<SemicolonProps, 'show'> & {}) => JSX.Element;
|
|
11
|
+
}
|
|
12
|
+
export declare const Semicolon: FC<PropsWithChildren<SemicolonProps>>;
|
package/esm/semicolon.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
|
|
3
|
+
var _excluded = ["children", "render", "color", "value", "className", "show", "highlightUpdates", "quotes", "style"];
|
|
4
|
+
import { useMemo, useRef, useEffect } from 'react';
|
|
5
|
+
import { Label } from './value';
|
|
6
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
+
export function usePrevious(value) {
|
|
8
|
+
var ref = useRef();
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
ref.current = value;
|
|
11
|
+
});
|
|
12
|
+
return ref.current;
|
|
13
|
+
}
|
|
14
|
+
export var Semicolon = _ref => {
|
|
15
|
+
var {
|
|
16
|
+
children,
|
|
17
|
+
render,
|
|
18
|
+
color,
|
|
19
|
+
value,
|
|
20
|
+
className = 'w-rjv-object-key',
|
|
21
|
+
show,
|
|
22
|
+
highlightUpdates,
|
|
23
|
+
quotes,
|
|
24
|
+
style
|
|
25
|
+
} = _ref,
|
|
26
|
+
props = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
27
|
+
var prevValue = usePrevious(value);
|
|
28
|
+
var highlightContainer = useRef(null);
|
|
29
|
+
var isHighlight = useMemo(() => {
|
|
30
|
+
if (!highlightUpdates || prevValue === undefined) return false;
|
|
31
|
+
// highlight if value type changed
|
|
32
|
+
if (typeof value !== typeof prevValue) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
if (typeof value === 'number') {
|
|
36
|
+
// notice: NaN !== NaN
|
|
37
|
+
if (isNaN(value) && isNaN(prevValue)) return false;
|
|
38
|
+
return value !== prevValue;
|
|
39
|
+
}
|
|
40
|
+
// highlight if isArray changed
|
|
41
|
+
if (Array.isArray(value) !== Array.isArray(prevValue)) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
// not highlight object/function
|
|
45
|
+
// deep compare they will be slow
|
|
46
|
+
if (typeof value === 'object' || typeof value === 'function') {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// highlight if not equal
|
|
51
|
+
if (value !== prevValue) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}, [highlightUpdates, value]);
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (highlightContainer.current && isHighlight && 'animate' in highlightContainer.current) {
|
|
58
|
+
highlightContainer.current.animate([{
|
|
59
|
+
backgroundColor: 'var(--w-rjv-update-color, #ebcb8b)'
|
|
60
|
+
}, {
|
|
61
|
+
backgroundColor: ''
|
|
62
|
+
}], {
|
|
63
|
+
duration: 1000,
|
|
64
|
+
easing: 'ease-in'
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}, [isHighlight, value]);
|
|
68
|
+
var content = show ? "" + quotes + children + quotes : children;
|
|
69
|
+
if (render) return render(_extends({
|
|
70
|
+
className
|
|
71
|
+
}, props, {
|
|
72
|
+
value,
|
|
73
|
+
style: _extends({}, style, {
|
|
74
|
+
color
|
|
75
|
+
}),
|
|
76
|
+
children: content
|
|
77
|
+
}));
|
|
78
|
+
return /*#__PURE__*/_jsx(Label, _extends({
|
|
79
|
+
className: className,
|
|
80
|
+
color: color
|
|
81
|
+
}, props, {
|
|
82
|
+
ref: highlightContainer,
|
|
83
|
+
children: content
|
|
84
|
+
}));
|
|
85
|
+
};
|
package/esm/theme/dark.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export declare const darkTheme: {
|
|
|
5
5
|
'--w-rjv-line-color': string;
|
|
6
6
|
'--w-rjv-arrow-color': string;
|
|
7
7
|
'--w-rjv-info-color': string;
|
|
8
|
+
'--w-rjv-update-color': string;
|
|
8
9
|
'--w-rjv-copied-color': string;
|
|
9
10
|
'--w-rjv-copied-success-color': string;
|
|
10
11
|
'--w-rjv-curlybraces-color': string;
|
package/esm/theme/dark.js
CHANGED
|
@@ -5,6 +5,7 @@ export var darkTheme = {
|
|
|
5
5
|
'--w-rjv-line-color': '#323232',
|
|
6
6
|
'--w-rjv-arrow-color': 'var(--w-rjv-color)',
|
|
7
7
|
'--w-rjv-info-color': '#656565',
|
|
8
|
+
'--w-rjv-update-color': '#ebcb8b',
|
|
8
9
|
'--w-rjv-copied-color': '#0184a6',
|
|
9
10
|
'--w-rjv-copied-success-color': '#28a745',
|
|
10
11
|
'--w-rjv-curlybraces-color': '#1896b6',
|
package/esm/theme/light.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export declare const lightTheme: {
|
|
|
5
5
|
'--w-rjv-line-color': string;
|
|
6
6
|
'--w-rjv-arrow-color': string;
|
|
7
7
|
'--w-rjv-info-color': string;
|
|
8
|
+
'--w-rjv-update-color': string;
|
|
8
9
|
'--w-rjv-copied-color': string;
|
|
9
10
|
'--w-rjv-copied-success-color': string;
|
|
10
11
|
'--w-rjv-curlybraces-color': string;
|
package/esm/theme/light.js
CHANGED
|
@@ -5,6 +5,7 @@ export var lightTheme = {
|
|
|
5
5
|
'--w-rjv-line-color': '#ebebeb',
|
|
6
6
|
'--w-rjv-arrow-color': 'var(--w-rjv-color)',
|
|
7
7
|
'--w-rjv-info-color': '#0000004d',
|
|
8
|
+
'--w-rjv-update-color': '#ebcb8b',
|
|
8
9
|
'--w-rjv-copied-color': '#002b36',
|
|
9
10
|
'--w-rjv-copied-success-color': '#28a745',
|
|
10
11
|
'--w-rjv-curlybraces-color': '#236a7c',
|
package/esm/value.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export declare const typeMap: {
|
|
|
41
41
|
};
|
|
42
42
|
export declare const Colon: FC<PropsWithChildren<React.HTMLAttributes<HTMLSpanElement>>>;
|
|
43
43
|
export interface ValueViewProps<T> extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement> {
|
|
44
|
-
keyName?: string;
|
|
44
|
+
keyName?: string | number;
|
|
45
45
|
value?: T;
|
|
46
46
|
displayDataTypes: boolean;
|
|
47
47
|
displayObjectSize: boolean;
|
|
@@ -60,7 +60,7 @@ export interface LabelProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
|
60
60
|
opacity?: number;
|
|
61
61
|
paddingRight?: number;
|
|
62
62
|
}
|
|
63
|
-
export declare const Label:
|
|
63
|
+
export declare const Label: import("react").ForwardRefExoticComponent<LabelProps & import("react").RefAttributes<HTMLSpanElement>>;
|
|
64
64
|
export interface TypeProps extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement> {
|
|
65
65
|
type: keyof typeof typeMap;
|
|
66
66
|
}
|
package/esm/value.js
CHANGED
|
@@ -3,7 +3,7 @@ import _extends from "@babel/runtime/helpers/extends";
|
|
|
3
3
|
var _excluded = ["children", "style"],
|
|
4
4
|
_excluded2 = ["value", "keyName", "indentWidth", "renderKey", "renderValue", "renderBraces", "enableClipboard", "displayObjectSize", "displayDataTypes"],
|
|
5
5
|
_excluded3 = ["children", "color", "fontSize", "opacity", "paddingRight", "style"];
|
|
6
|
-
import { Fragment, useState } from 'react';
|
|
6
|
+
import { Fragment, forwardRef, useState } from 'react';
|
|
7
7
|
import { Meta, CountInfo } from './node';
|
|
8
8
|
import { Copied } from './copied';
|
|
9
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -152,6 +152,7 @@ export function ValueView(props) {
|
|
|
152
152
|
});
|
|
153
153
|
return /*#__PURE__*/_jsx(Line, _extends({}, eventProps, {
|
|
154
154
|
children: /*#__PURE__*/_jsxs(Label, _extends({}, reset, {
|
|
155
|
+
ref: null,
|
|
155
156
|
children: [renderKey, /*#__PURE__*/_jsx(Colon, {}), typeView, valueView, tools]
|
|
156
157
|
}))
|
|
157
158
|
}));
|
|
@@ -171,11 +172,12 @@ export function ValueView(props) {
|
|
|
171
172
|
});
|
|
172
173
|
return /*#__PURE__*/_jsx(Line, _extends({}, eventProps, {
|
|
173
174
|
children: /*#__PURE__*/_jsxs(Label, _extends({}, reset, {
|
|
175
|
+
ref: null,
|
|
174
176
|
children: [renderKey, /*#__PURE__*/_jsx(Colon, {}), typeView, empty, tools]
|
|
175
177
|
}))
|
|
176
178
|
}));
|
|
177
179
|
}
|
|
178
|
-
export var Label = _ref2 => {
|
|
180
|
+
export var Label = /*#__PURE__*/forwardRef((_ref2, ref) => {
|
|
179
181
|
var {
|
|
180
182
|
children,
|
|
181
183
|
color,
|
|
@@ -193,9 +195,10 @@ export var Label = _ref2 => {
|
|
|
193
195
|
paddingRight
|
|
194
196
|
}, style)
|
|
195
197
|
}, reset, {
|
|
198
|
+
ref: ref,
|
|
196
199
|
children: children
|
|
197
200
|
}));
|
|
198
|
-
};
|
|
201
|
+
});
|
|
199
202
|
export var Type = props => {
|
|
200
203
|
var _typeMap$type2, _typeMap$type3;
|
|
201
204
|
var {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uiw/react-json-view",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "JSON viewer for react.",
|
|
5
5
|
"main": "cjs/index.js",
|
|
6
6
|
"module": "esm/index.js",
|
|
@@ -74,7 +74,10 @@
|
|
|
74
74
|
"treeview"
|
|
75
75
|
],
|
|
76
76
|
"devDependencies": {
|
|
77
|
+
"@testing-library/react": "^14.0.0",
|
|
78
|
+
"@types/react-test-renderer": "^18.0.0",
|
|
77
79
|
"react": "^18.2.0",
|
|
78
|
-
"react-dom": "^18.2.0"
|
|
80
|
+
"react-dom": "^18.2.0",
|
|
81
|
+
"react-test-renderer": "^18.2.0"
|
|
79
82
|
}
|
|
80
83
|
}
|