@uiw/react-json-view 0.1.0 → 1.0.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 CHANGED
@@ -3,6 +3,7 @@ react-json-view
3
3
 
4
4
  [![CI](https://github.com/uiwjs/react-json-view/actions/workflows/ci.yml/badge.svg)](https://github.com/uiwjs/react-json-view/actions/workflows/ci.yml)
5
5
  [![npm version](https://img.shields.io/npm/v/@uiw/react-json-view.svg)](https://www.npmjs.com/package/@uiw/react-json-view)
6
+ [![react@^18](https://shields.io/badge/react-^18-green?style=flat&logo=react)](https://github.com/facebook/react/releases)
6
7
 
7
8
  A React component for displaying and editing javascript arrays and JSON objects.
8
9
 
@@ -106,9 +107,11 @@ const customTheme = {
106
107
  '--w-rjv-font-family': 'monospace',
107
108
  '--w-rjv-color': '#9cdcfe',
108
109
  '--w-rjv-background-color': '#1e1e1e',
109
- '--w-rjv-border-left': '1px solid #323232',
110
+ '--w-rjv-line-color': '#323232',
110
111
  '--w-rjv-arrow-color': 'var(--w-rjv-color)',
111
112
  '--w-rjv-info-color': '#656565',
113
+ '--w-rjv-copied-color': '#9cdcfe',
114
+ '--w-rjv-copied-success-color': '#28a745',
112
115
 
113
116
  '--w-rjv-curlybraces-color': '#d4d4d4',
114
117
  '--w-rjv-brackets-color': '#d4d4d4',
@@ -135,7 +138,7 @@ export default function Demo() {
135
138
 
136
139
  Online custom style example, please check in the [documentation website](https://uiwjs.github.io/react-json-view/)
137
140
 
138
- ```tsx mdx:preview
141
+ ```tsx mdx:preview:&title=Online Editing Theme
139
142
  import React, { useState, useRef } from 'react';
140
143
  import Colorful from '@uiw/react-color-colorful';
141
144
  import JsonView from '@uiw/react-json-view';
@@ -165,9 +168,11 @@ const object = {
165
168
  const customTheme = {
166
169
  '--w-rjv-color': '#9cdcfe',
167
170
  '--w-rjv-background-color': '#1e1e1e',
168
- '--w-rjv-border-left': '1px solid #323232',
169
- '--w-rjv-arrow-color': 'var(--w-rjv-color)',
171
+ '--w-rjv-line-color': '#323232',
172
+ '--w-rjv-arrow-color': '#9cdcfe',
170
173
  '--w-rjv-info-color': '#656565',
174
+ '--w-rjv-copied-color': '#0184a6',
175
+ '--w-rjv-copied-success-color': '#28a745',
171
176
 
172
177
  '--w-rjv-curlybraces-color': '#d4d4d4',
173
178
  '--w-rjv-brackets-color': '#d4d4d4',
@@ -188,9 +193,8 @@ export default function Demo() {
188
193
  const [hex, setHex] = useState("#1e1e1e");
189
194
  const [theme, setTheme] = useState(customTheme);
190
195
  const onChange = ({ hexa }) => {
191
- const value = cssvar === '--w-rjv-border-left' ? `1px solid ${hexa}` : hexa;
192
196
  setHex(hexa);
193
- setTheme({ ...theme, [cssvar]: value });
197
+ setTheme({ ...theme, [cssvar]: hexa });
194
198
  };
195
199
  return (
196
200
  <React.Fragment>
@@ -200,7 +204,10 @@ export default function Demo() {
200
204
  <Colorful color={hex} onChange={onChange} />
201
205
  <div style={{ display: 'flex', gap: '0.4rem', flexWrap: 'wrap' }}>
202
206
  {Object.keys(customTheme).map((varname, idx) => {
203
- const click = () => setCssvar(varname);
207
+ const click = () => {
208
+ setCssvar(varname);
209
+ setHex(customTheme[varname]);
210
+ };
204
211
  const active = cssvar === varname ? '#a8a8a8' : '';
205
212
  return <button key={idx} style={{ background: active }} onClick={click}>{varname}</button>
206
213
  })}
@@ -375,14 +382,17 @@ import { MetaProps, SemicolonProps, EllipsisProps, ValueViewProps } from '@uiw/r
375
382
  export interface JsonViewProps<T> extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
376
383
  /** This property contains your input JSON */
377
384
  value?: T;
378
- /** Set the indent-width for nested objects @default `15`*/
385
+ /** Set the indent-width for nested objects @default 15 */
379
386
  indentWidth?: number;
380
- /** When set to `true`, data type labels prefix values @default `true` */
387
+ /** When set to `true`, data type labels prefix values @default true */
381
388
  displayDataTypes?: boolean;
382
- /** When set to `true`, `objects` and `arrays` are labeled with size @default `true` */
389
+ /** When set to `true`, `objects` and `arrays` are labeled with size @default true */
383
390
  displayObjectSize?: boolean;
384
- /** Define the root node name. @default `undefined` */
391
+ /** Define the root node name. @default undefined */
385
392
  keyName?: string | number;
393
+ /** The user can copy objects and arrays to clipboard by clicking on the clipboard icon. @default true */
394
+ enableClipboard?: boolean;
395
+ /** Redefine interface elements to re-render. */
386
396
  components?: {
387
397
  braces?: MetaProps['render'];
388
398
  ellipsis?: EllipsisProps['render'];
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ export interface CopiedProps<T = object> extends React.SVGProps<SVGSVGElement> {
3
+ show?: boolean;
4
+ text?: T;
5
+ }
6
+ export declare function Copied<T>(props: CopiedProps<T>): import("react/jsx-runtime").JSX.Element | null;
package/cjs/copied.js ADDED
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.Copied = Copied;
8
+ var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
9
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
+ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
11
+ var _react = require("react");
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ var _excluded = ["children", "style", "text", "show"];
14
+ function Copied(props) {
15
+ var children = props.children,
16
+ style = props.style,
17
+ _props$text = props.text,
18
+ text = _props$text === void 0 ? '' : _props$text,
19
+ show = props.show,
20
+ reset = (0, _objectWithoutProperties2["default"])(props, _excluded);
21
+ if (!show) return null;
22
+ var _useState = (0, _react.useState)(false),
23
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
24
+ copied = _useState2[0],
25
+ setCopied = _useState2[1];
26
+ var click = function click(event) {
27
+ event.stopPropagation();
28
+ var copyText = JSON.stringify(text, function (key, value) {
29
+ if (typeof value === 'bigint') {
30
+ return value.toString();
31
+ }
32
+ return value;
33
+ }, 2);
34
+ if (text === Infinity) copyText = Infinity;
35
+ navigator.clipboard.writeText(copyText).then(function () {
36
+ setCopied(true);
37
+ var timer = setTimeout(function () {
38
+ setCopied(false);
39
+ clearTimeout(timer);
40
+ }, 3000);
41
+ })["catch"](function (error) {});
42
+ };
43
+ var defalutStyle = (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, style), {}, {
44
+ cursor: 'pointer',
45
+ marginLeft: 5
46
+ });
47
+ var svgProps = (0, _objectSpread2["default"])({
48
+ height: "1em",
49
+ width: "1em",
50
+ fill: "var(--w-rjv-copied-color, currentColor)",
51
+ onClick: click,
52
+ style: defalutStyle,
53
+ className: 'w-rjv-copied'
54
+ }, reset);
55
+ if (copied) {
56
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("svg", (0, _objectSpread2["default"])((0, _objectSpread2["default"])({
57
+ viewBox: "0 0 38 38"
58
+ }, svgProps), {}, {
59
+ fill: "var(--w-rjv-copied-success-color, #28a745)",
60
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
61
+ d: "M27.5,35 L2.5,35 L2.5,12.5 L27.5,12.5 L27.5,15.2249049 C29.1403264,13.8627542 29.9736597,13.1778155 30,13.1700887 C30,11.9705278 30,10.0804982 30,7.5 C30,6.1 28.9,5 27.5,5 L20,5 C20,2.2 17.8,0 15,0 C12.2,0 10,2.2 10,5 L2.5,5 C1.1,5 0,6.1 0,7.5 L0,35 C0,36.4 1.1,37.5 2.5,37.5 L27.5,37.5 C28.9,37.5 30,36.4 30,35 L30,30 L27.5,30 L27.5,35 Z M7.5,7.5 L10,7.5 C10,7.5 12.5,6.4 12.5,5 C12.5,3.6 13.6,2.5 15,2.5 C16.4,2.5 17.5,3.6 17.5,5 C17.5,6.4 18.8,7.5 20,7.5 L22.5,7.5 C22.5,7.5 25,8.6 25,10 L5,10 C5,8.5 6.1,7.5 7.5,7.5 Z M5,27.5 L10,27.5 L10,25 L5,25 L5,27.5 Z M31.5589286,15 L35.1589286,18.6 L21.0160714,33 L12.5303571,24.2571429 L16.1303571,20.6571429 L21.0160714,25.5428571 L31.5589286,15 Z M12.5,30 L12.5,32.5 L5,32.5 L5,30 L12.5,30 Z M17.5,15 L5,15 L5,17.5 L17.5,17.5 L17.5,15 Z M10,20 L5,20 L5,22.5 L10,22.5 L10,20 Z"
62
+ })
63
+ }));
64
+ }
65
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("svg", (0, _objectSpread2["default"])((0, _objectSpread2["default"])({
66
+ viewBox: "0 0 38 38"
67
+ }, svgProps), {}, {
68
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
69
+ d: "M27.5,35 L2.5,35 L2.5,12.5 L27.5,12.5 L27.5,20 L30,20 L30,7.5 C30,6.1 28.9,5 27.5,5 L20,5 C20,2.2 17.8,0 15,0 C12.2,0 10,2.2 10,5 L2.5,5 C1.1,5 0,6.1 0,7.5 L0,35 C0,36.4 1.1,37.5 2.5,37.5 L27.5,37.5 C28.9,37.5 30,36.4 30,35 L30,30 L27.5,30 L27.5,35 Z M7.5,7.5 L10,7.5 C10,7.5 12.5,6.4 12.5,5 C12.5,3.6 13.6,2.5 15,2.5 C16.4,2.5 17.5,3.6 17.5,5 C17.5,6.4 18.8,7.5 20,7.5 L22.5,7.5 C22.5,7.5 25,8.6 25,10 L5,10 C5,8.5 6.1,7.5 7.5,7.5 Z M5,27.5 L10,27.5 L10,25 L5,25 L5,27.5 Z M22.5,22.5 L22.5,17.5 L12.5,25 L22.5,32.5 L22.5,27.5 L35,27.5 L35,22.5 L22.5,22.5 Z M5,32.5 L12.5,32.5 L12.5,30 L5,30 L5,32.5 Z M17.5,15 L5,15 L5,17.5 L17.5,17.5 L17.5,15 Z M10,20 L5,20 L5,22.5 L10,22.5 L10,20 Z"
70
+ })
71
+ }));
72
+ }
package/cjs/index.d.ts CHANGED
@@ -6,14 +6,17 @@ export * from './value';
6
6
  export interface JsonViewProps<T> extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
7
7
  /** This property contains your input JSON */
8
8
  value?: T;
9
- /** Set the indent-width for nested objects @default `15`*/
9
+ /** Set the indent-width for nested objects @default 15 */
10
10
  indentWidth?: number;
11
- /** When set to `true`, data type labels prefix values @default `true` */
11
+ /** When set to `true`, data type labels prefix values @default true */
12
12
  displayDataTypes?: boolean;
13
- /** When set to `true`, `objects` and `arrays` are labeled with size @default `true` */
13
+ /** When set to `true`, `objects` and `arrays` are labeled with size @default true */
14
14
  displayObjectSize?: boolean;
15
- /** Define the root node name. @default `undefined` */
15
+ /** Define the root node name. @default undefined */
16
16
  keyName?: string | number;
17
+ /** The user can copy objects and arrays to clipboard by clicking on the clipboard icon. @default true */
18
+ enableClipboard?: boolean;
19
+ /** Redefine interface elements to re-render. */
17
20
  components?: {
18
21
  braces?: MetaProps['render'];
19
22
  ellipsis?: EllipsisProps['render'];
package/cjs/node.d.ts CHANGED
@@ -7,7 +7,6 @@ export interface MetaProps extends LabelProps {
7
7
  render?: (props: Pick<MetaProps, 'start' | 'isArray' | 'className' | 'children'>) => JSX.Element;
8
8
  }
9
9
  export declare function Meta(props: MetaProps): import("react/jsx-runtime").JSX.Element;
10
- export declare const Line: FC<PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>>;
11
10
  export interface EllipsisProps extends React.HTMLAttributes<HTMLSpanElement> {
12
11
  render?: (props: EllipsisProps) => JSX.Element;
13
12
  }
package/cjs/node.js CHANGED
@@ -4,22 +4,24 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.Line = exports.Ellipsis = exports.CountInfo = void 0;
7
+ exports.Ellipsis = exports.CountInfo = void 0;
8
8
  exports.Meta = Meta;
9
9
  exports.RooNode = RooNode;
10
10
  exports.Semicolon = void 0;
11
11
  var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
12
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
12
13
  var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
13
14
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
14
15
  var _react = require("react");
15
16
  var _value = require("./value");
16
17
  var _TriangleArrow = require("./arrow/TriangleArrow");
17
18
  var _store = require("./store");
19
+ var _copied = require("./copied");
18
20
  var _jsxRuntime = require("react/jsx-runtime");
19
21
  var _excluded = ["isArray", "start", "className", "render"],
20
22
  _excluded2 = ["style", "render"],
21
23
  _excluded3 = ["children", "render", "color", "value", "className", "show"],
22
- _excluded4 = ["value", "keyName", "displayDataTypes", "components", "displayObjectSize", "indentWidth", "keyid"];
24
+ _excluded4 = ["value", "keyName", "displayDataTypes", "components", "displayObjectSize", "enableClipboard", "indentWidth", "keyid"];
23
25
  function Meta(props) {
24
26
  var _props$isArray = props.isArray,
25
27
  isArray = _props$isArray === void 0 ? false : _props$isArray,
@@ -46,10 +48,6 @@ function Meta(props) {
46
48
  children: start ? mark.charAt(0) : mark.charAt(1)
47
49
  }));
48
50
  }
49
- var Line = function Line(props) {
50
- return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", (0, _objectSpread2["default"])({}, props));
51
- };
52
- exports.Line = Line;
53
51
  var Ellipsis = function Ellipsis(_ref) {
54
52
  var style = _ref.style,
55
53
  render = _ref.render,
@@ -122,6 +120,8 @@ function RooNode(props) {
122
120
  components = _props$components === void 0 ? {} : _props$components,
123
121
  _props$displayObjectS = props.displayObjectSize,
124
122
  displayObjectSize = _props$displayObjectS === void 0 ? true : _props$displayObjectS,
123
+ _props$enableClipboar = props.enableClipboard,
124
+ enableClipboard = _props$enableClipboar === void 0 ? true : _props$enableClipboar,
125
125
  _props$indentWidth = props.indentWidth,
126
126
  indentWidth = _props$indentWidth === void 0 ? 15 : _props$indentWidth,
127
127
  _props$keyid = props.keyid,
@@ -152,6 +152,9 @@ function RooNode(props) {
152
152
  };
153
153
  var valueViewProps = {
154
154
  displayDataTypes: displayDataTypes,
155
+ displayObjectSize: displayObjectSize,
156
+ enableClipboard: enableClipboard,
157
+ indentWidth: indentWidth,
155
158
  renderValue: components.value
156
159
  };
157
160
  var arrowView = components.arrow ? /*#__PURE__*/(0, _react.cloneElement)(components.arrow, {
@@ -160,8 +163,24 @@ function RooNode(props) {
160
163
  }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_TriangleArrow.TriangleArrow, {
161
164
  style: arrowStyle
162
165
  });
166
+ var _useState = (0, _react.useState)(false),
167
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
168
+ showTools = _useState2[0],
169
+ setShowTools = _useState2[1];
170
+ var tools = enableClipboard ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_copied.Copied, {
171
+ show: showTools,
172
+ text: value
173
+ }) : undefined;
174
+ var mouseEnter = function mouseEnter() {
175
+ return setShowTools(true);
176
+ };
177
+ var mouseLeave = function mouseLeave() {
178
+ return setShowTools(false);
179
+ };
163
180
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, reset), {}, {
164
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, {
181
+ onMouseEnter: mouseEnter,
182
+ onMouseLeave: mouseLeave,
183
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_value.Line, {
165
184
  style: {
166
185
  display: 'inline-flex',
167
186
  alignItems: 'center'
@@ -186,17 +205,25 @@ function RooNode(props) {
186
205
  render: components.braces
187
206
  }), displayObjectSize && /*#__PURE__*/(0, _jsxRuntime.jsxs)(CountInfo, {
188
207
  children: [nameKeys.length, " items"]
189
- })]
190
- }), expand && /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
208
+ }), tools]
209
+ }), expand && /*#__PURE__*/(0, _jsxRuntime.jsx)(_value.Line, {
191
210
  style: {
192
- borderLeft: 'var(--w-rjv-border-left, 1px solid #ebebeb)',
211
+ borderLeft: '1px solid var(--w-rjv-line-color, #ebebeb)',
193
212
  marginLeft: 6
194
213
  },
195
214
  children: nameKeys.length > 0 && nameKeys.map(function (key, idx) {
196
215
  var item = value[key];
197
- if (Array.isArray(item)) {
216
+ var renderKey = /*#__PURE__*/(0, _jsxRuntime.jsx)(Semicolon, {
217
+ value: item,
218
+ render: components.objectKey,
219
+ color: typeof key === 'number' ? _value.typeMap['number'].color : '',
220
+ show: typeof key === 'string',
221
+ children: key
222
+ });
223
+ var isEmpty = Array.isArray(item) && item.length === 0 || (0, _typeof2["default"])(item) === 'object' && item && !(item instanceof Date) && Object.keys(item).length === 0;
224
+ if (Array.isArray(item) && !isEmpty) {
198
225
  var label = isArray ? idx : key;
199
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
226
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_value.Line, {
200
227
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(RooNode, (0, _objectSpread2["default"])({
201
228
  value: item,
202
229
  keyid: keyid + subkeyid + label,
@@ -204,36 +231,8 @@ function RooNode(props) {
204
231
  }, subNodeProps))
205
232
  }, label + idx);
206
233
  }
207
- var renderKey = /*#__PURE__*/(0, _jsxRuntime.jsx)(Semicolon, {
208
- value: item,
209
- render: components.objectKey,
210
- color: typeof key === 'number' ? _value.typeMap['number'].color : '',
211
- show: typeof key === 'string',
212
- children: key
213
- });
214
- if ((0, _typeof2["default"])(item) === 'object' && item && !(item instanceof Date)) {
215
- if (Object.keys(item).length === 0) {
216
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, {
217
- style: {
218
- paddingLeft: indentWidth
219
- },
220
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_value.ValueView, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, valueViewProps), {}, {
221
- renderKey: renderKey,
222
- keyName: key,
223
- value: item
224
- })), /*#__PURE__*/(0, _jsxRuntime.jsx)(Meta, {
225
- render: components.braces,
226
- start: true,
227
- isArray: isArray
228
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Meta, {
229
- render: components.braces,
230
- isArray: isArray
231
- }), displayObjectSize && /*#__PURE__*/(0, _jsxRuntime.jsxs)(CountInfo, {
232
- children: [Object.keys(item).length, " items"]
233
- })]
234
- }, key + idx);
235
- }
236
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
234
+ if ((0, _typeof2["default"])(item) === 'object' && item && !(item instanceof Date) && !isEmpty) {
235
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_value.Line, {
237
236
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(RooNode, (0, _objectSpread2["default"])({
238
237
  keyid: keyid + subkeyid + key,
239
238
  value: item,
@@ -244,18 +243,14 @@ function RooNode(props) {
244
243
  if (typeof item === 'function') {
245
244
  return;
246
245
  }
247
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
248
- style: {
249
- paddingLeft: indentWidth
250
- },
251
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_value.ValueView, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, valueViewProps), {}, {
252
- renderKey: renderKey,
253
- keyName: key,
254
- value: item
255
- }))
256
- }, idx);
246
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_value.ValueView, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, valueViewProps), {}, {
247
+ renderBraces: components.braces,
248
+ renderKey: renderKey,
249
+ keyName: key,
250
+ value: item
251
+ }), idx);
257
252
  })
258
- }), expand && /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
253
+ }), expand && /*#__PURE__*/(0, _jsxRuntime.jsx)(_value.Line, {
259
254
  style: {
260
255
  paddingLeft: 2
261
256
  },
@@ -2,9 +2,11 @@ export declare const darkTheme: {
2
2
  '--w-rjv-font-family': string;
3
3
  '--w-rjv-color': string;
4
4
  '--w-rjv-background-color': string;
5
- '--w-rjv-border-left': string;
5
+ '--w-rjv-line-color': string;
6
6
  '--w-rjv-arrow-color': string;
7
7
  '--w-rjv-info-color': string;
8
+ '--w-rjv-copied-color': string;
9
+ '--w-rjv-copied-success-color': string;
8
10
  '--w-rjv-curlybraces-color': string;
9
11
  '--w-rjv-brackets-color': string;
10
12
  '--w-rjv-type-string-color': string;
package/cjs/theme/dark.js CHANGED
@@ -8,9 +8,11 @@ var darkTheme = {
8
8
  '--w-rjv-font-family': 'monospace',
9
9
  '--w-rjv-color': '#0184a6',
10
10
  '--w-rjv-background-color': '#202020',
11
- '--w-rjv-border-left': '1px solid #323232',
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-copied-color': '#0184a6',
15
+ '--w-rjv-copied-success-color': '#28a745',
14
16
  '--w-rjv-curlybraces-color': '#1896b6',
15
17
  '--w-rjv-brackets-color': '#1896b6',
16
18
  '--w-rjv-type-string-color': '#cb4b16',
@@ -2,9 +2,11 @@ export declare const lightTheme: {
2
2
  '--w-rjv-font-family': string;
3
3
  '--w-rjv-color': string;
4
4
  '--w-rjv-background-color': string;
5
- '--w-rjv-border-left': string;
5
+ '--w-rjv-line-color': string;
6
6
  '--w-rjv-arrow-color': string;
7
7
  '--w-rjv-info-color': string;
8
+ '--w-rjv-copied-color': string;
9
+ '--w-rjv-copied-success-color': string;
8
10
  '--w-rjv-curlybraces-color': string;
9
11
  '--w-rjv-brackets-color': string;
10
12
  '--w-rjv-type-string-color': string;
@@ -8,9 +8,11 @@ var lightTheme = {
8
8
  '--w-rjv-font-family': 'monospace',
9
9
  '--w-rjv-color': '#002b36',
10
10
  '--w-rjv-background-color': '#ffffff',
11
- '--w-rjv-border-left': '1px solid #ebebeb',
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-copied-color': '#002b36',
15
+ '--w-rjv-copied-success-color': '#28a745',
14
16
  '--w-rjv-curlybraces-color': '#236a7c',
15
17
  '--w-rjv-brackets-color': '#236a7c',
16
18
  '--w-rjv-type-string-color': '#cb4b16',
package/cjs/value.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import { FC, PropsWithChildren } from 'react';
2
+ import { MetaProps } from './node';
3
+ export declare const Line: FC<PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>>;
2
4
  export declare const typeMap: {
3
5
  string: {
4
6
  color: string;
@@ -40,14 +42,18 @@ export declare const typeMap: {
40
42
  export declare const Colon: FC<PropsWithChildren<React.HTMLAttributes<HTMLSpanElement>>>;
41
43
  export interface ValueViewProps<T> extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement> {
42
44
  keyName?: string;
43
- value: T;
45
+ value?: T;
44
46
  displayDataTypes: boolean;
47
+ displayObjectSize: boolean;
48
+ enableClipboard: boolean;
49
+ indentWidth: number;
45
50
  renderKey?: JSX.Element;
51
+ renderBraces?: MetaProps['render'];
46
52
  renderValue?: (props: React.HTMLAttributes<HTMLSpanElement> & {
47
53
  type: TypeProps['type'];
48
54
  }) => JSX.Element;
49
55
  }
50
- export declare function ValueView<T>(props: ValueViewProps<T>): import("react/jsx-runtime").JSX.Element;
56
+ export declare function ValueView<T = object>(props: ValueViewProps<T>): import("react/jsx-runtime").JSX.Element;
51
57
  export interface LabelProps extends React.HTMLAttributes<HTMLSpanElement> {
52
58
  color?: string;
53
59
  fontSize?: number;
package/cjs/value.js CHANGED
@@ -4,17 +4,24 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.Type = exports.Label = exports.Colon = void 0;
7
+ exports.Type = exports.Line = exports.Label = exports.Colon = void 0;
8
8
  exports.ValueView = ValueView;
9
9
  exports.typeMap = void 0;
10
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
11
  var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
11
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
12
12
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
13
+ var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
13
14
  var _react = require("react");
15
+ var _node = require("./node");
16
+ var _copied = require("./copied");
14
17
  var _jsxRuntime = require("react/jsx-runtime");
15
18
  var _excluded = ["children", "style"],
16
- _excluded2 = ["value", "keyName", "renderKey", "renderValue", "displayDataTypes"],
19
+ _excluded2 = ["value", "keyName", "indentWidth", "renderKey", "renderValue", "renderBraces", "enableClipboard", "displayObjectSize", "displayDataTypes"],
17
20
  _excluded3 = ["children", "color", "fontSize", "opacity", "paddingRight", "style"];
21
+ var Line = function Line(props) {
22
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", (0, _objectSpread2["default"])({}, props));
23
+ };
24
+ exports.Line = Line;
18
25
  var isFloat = function isFloat(n) {
19
26
  return Number(n) === n && n % 1 !== 0 || isNaN(n);
20
27
  };
@@ -76,8 +83,12 @@ function ValueView(props) {
76
83
  var _typeMap$type;
77
84
  var value = props.value,
78
85
  keyName = props.keyName,
86
+ indentWidth = props.indentWidth,
79
87
  renderKey = props.renderKey,
80
88
  renderValue = props.renderValue,
89
+ renderBraces = props.renderBraces,
90
+ enableClipboard = props.enableClipboard,
91
+ displayObjectSize = props.displayObjectSize,
81
92
  displayDataTypes = props.displayDataTypes,
82
93
  reset = (0, _objectWithoutProperties2["default"])(props, _excluded2);
83
94
  var type = (0, _typeof2["default"])(value);
@@ -123,6 +134,20 @@ function ValueView(props) {
123
134
  typeView = /*#__PURE__*/(0, _jsxRuntime.jsx)(_react.Fragment, {});
124
135
  }
125
136
  color = ((_typeMap$type = typeMap[type]) === null || _typeMap$type === void 0 ? void 0 : _typeMap$type.color) || '';
137
+ var _useState = (0, _react.useState)(false),
138
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
139
+ showTools = _useState2[0],
140
+ setShowTools = _useState2[1];
141
+ var tools = enableClipboard ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_copied.Copied, {
142
+ show: showTools,
143
+ text: value
144
+ }) : undefined;
145
+ var mouseEnter = function mouseEnter() {
146
+ return setShowTools(true);
147
+ };
148
+ var mouseLeave = function mouseLeave() {
149
+ return setShowTools(false);
150
+ };
126
151
  if (content && typeof content === 'string') {
127
152
  var valueView = renderValue ? renderValue({
128
153
  className: 'w-rjv-value',
@@ -137,13 +162,40 @@ function ValueView(props) {
137
162
  className: "w-rjv-value",
138
163
  children: content
139
164
  });
140
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Label, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, reset), {}, {
141
- children: [renderKey, /*#__PURE__*/(0, _jsxRuntime.jsx)(Colon, {}), typeView, valueView]
142
- }));
165
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
166
+ style: {
167
+ paddingLeft: indentWidth
168
+ },
169
+ onMouseEnter: mouseEnter,
170
+ onMouseLeave: mouseLeave,
171
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(Label, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, reset), {}, {
172
+ children: [renderKey, /*#__PURE__*/(0, _jsxRuntime.jsx)(Colon, {}), typeView, valueView, tools]
173
+ }))
174
+ });
143
175
  }
144
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Label, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, reset), {}, {
145
- children: [renderKey, /*#__PURE__*/(0, _jsxRuntime.jsx)(Colon, {}), typeView]
146
- }));
176
+ var length = Array.isArray(value) ? value.length : Object.keys(value).length;
177
+ var empty = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_react.Fragment, {
178
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_node.Meta, {
179
+ render: renderBraces,
180
+ start: true,
181
+ isArray: Array.isArray(value)
182
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_node.Meta, {
183
+ render: renderBraces,
184
+ isArray: Array.isArray(value)
185
+ }), displayObjectSize && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_node.CountInfo, {
186
+ children: [length, " items"]
187
+ })]
188
+ });
189
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(Line, {
190
+ style: {
191
+ paddingLeft: indentWidth
192
+ },
193
+ onMouseEnter: mouseEnter,
194
+ onMouseLeave: mouseLeave,
195
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(Label, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, reset), {}, {
196
+ children: [renderKey, /*#__PURE__*/(0, _jsxRuntime.jsx)(Colon, {}), typeView, empty, tools]
197
+ }))
198
+ });
147
199
  }
148
200
  var Label = function Label(_ref2) {
149
201
  var children = _ref2.children,
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ export interface CopiedProps<T = object> extends React.SVGProps<SVGSVGElement> {
3
+ show?: boolean;
4
+ text?: T;
5
+ }
6
+ export declare function Copied<T>(props: CopiedProps<T>): import("react/jsx-runtime").JSX.Element | null;
package/esm/copied.js ADDED
@@ -0,0 +1,61 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
3
+ var _excluded = ["children", "style", "text", "show"];
4
+ import { useState } from "react";
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ export function Copied(props) {
7
+ var {
8
+ style,
9
+ text = '',
10
+ show
11
+ } = props,
12
+ reset = _objectWithoutPropertiesLoose(props, _excluded);
13
+ if (!show) return null;
14
+ var [copied, setCopied] = useState(false);
15
+ var click = event => {
16
+ event.stopPropagation();
17
+ var copyText = JSON.stringify(text, (key, value) => {
18
+ if (typeof value === 'bigint') {
19
+ return value.toString();
20
+ }
21
+ return value;
22
+ }, 2);
23
+ if (text === Infinity) copyText = Infinity;
24
+ navigator.clipboard.writeText(copyText).then(() => {
25
+ setCopied(true);
26
+ var timer = setTimeout(() => {
27
+ setCopied(false);
28
+ clearTimeout(timer);
29
+ }, 3000);
30
+ }).catch(error => {});
31
+ };
32
+ var defalutStyle = _extends({}, style, {
33
+ cursor: 'pointer',
34
+ marginLeft: 5
35
+ });
36
+ var svgProps = _extends({
37
+ height: "1em",
38
+ width: "1em",
39
+ fill: "var(--w-rjv-copied-color, currentColor)",
40
+ onClick: click,
41
+ style: defalutStyle,
42
+ className: 'w-rjv-copied'
43
+ }, reset);
44
+ if (copied) {
45
+ return /*#__PURE__*/_jsx("svg", _extends({
46
+ viewBox: "0 0 38 38"
47
+ }, svgProps, {
48
+ fill: "var(--w-rjv-copied-success-color, #28a745)",
49
+ children: /*#__PURE__*/_jsx("path", {
50
+ d: "M27.5,35 L2.5,35 L2.5,12.5 L27.5,12.5 L27.5,15.2249049 C29.1403264,13.8627542 29.9736597,13.1778155 30,13.1700887 C30,11.9705278 30,10.0804982 30,7.5 C30,6.1 28.9,5 27.5,5 L20,5 C20,2.2 17.8,0 15,0 C12.2,0 10,2.2 10,5 L2.5,5 C1.1,5 0,6.1 0,7.5 L0,35 C0,36.4 1.1,37.5 2.5,37.5 L27.5,37.5 C28.9,37.5 30,36.4 30,35 L30,30 L27.5,30 L27.5,35 Z M7.5,7.5 L10,7.5 C10,7.5 12.5,6.4 12.5,5 C12.5,3.6 13.6,2.5 15,2.5 C16.4,2.5 17.5,3.6 17.5,5 C17.5,6.4 18.8,7.5 20,7.5 L22.5,7.5 C22.5,7.5 25,8.6 25,10 L5,10 C5,8.5 6.1,7.5 7.5,7.5 Z M5,27.5 L10,27.5 L10,25 L5,25 L5,27.5 Z M31.5589286,15 L35.1589286,18.6 L21.0160714,33 L12.5303571,24.2571429 L16.1303571,20.6571429 L21.0160714,25.5428571 L31.5589286,15 Z M12.5,30 L12.5,32.5 L5,32.5 L5,30 L12.5,30 Z M17.5,15 L5,15 L5,17.5 L17.5,17.5 L17.5,15 Z M10,20 L5,20 L5,22.5 L10,22.5 L10,20 Z"
51
+ })
52
+ }));
53
+ }
54
+ return /*#__PURE__*/_jsx("svg", _extends({
55
+ viewBox: "0 0 38 38"
56
+ }, svgProps, {
57
+ children: /*#__PURE__*/_jsx("path", {
58
+ d: "M27.5,35 L2.5,35 L2.5,12.5 L27.5,12.5 L27.5,20 L30,20 L30,7.5 C30,6.1 28.9,5 27.5,5 L20,5 C20,2.2 17.8,0 15,0 C12.2,0 10,2.2 10,5 L2.5,5 C1.1,5 0,6.1 0,7.5 L0,35 C0,36.4 1.1,37.5 2.5,37.5 L27.5,37.5 C28.9,37.5 30,36.4 30,35 L30,30 L27.5,30 L27.5,35 Z M7.5,7.5 L10,7.5 C10,7.5 12.5,6.4 12.5,5 C12.5,3.6 13.6,2.5 15,2.5 C16.4,2.5 17.5,3.6 17.5,5 C17.5,6.4 18.8,7.5 20,7.5 L22.5,7.5 C22.5,7.5 25,8.6 25,10 L5,10 C5,8.5 6.1,7.5 7.5,7.5 Z M5,27.5 L10,27.5 L10,25 L5,25 L5,27.5 Z M22.5,22.5 L22.5,17.5 L12.5,25 L22.5,32.5 L22.5,27.5 L35,27.5 L35,22.5 L22.5,22.5 Z M5,32.5 L12.5,32.5 L12.5,30 L5,30 L5,32.5 Z M17.5,15 L5,15 L5,17.5 L17.5,17.5 L17.5,15 Z M10,20 L5,20 L5,22.5 L10,22.5 L10,20 Z"
59
+ })
60
+ }));
61
+ }
package/esm/index.d.ts CHANGED
@@ -6,14 +6,17 @@ export * from './value';
6
6
  export interface JsonViewProps<T> extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
7
7
  /** This property contains your input JSON */
8
8
  value?: T;
9
- /** Set the indent-width for nested objects @default `15`*/
9
+ /** Set the indent-width for nested objects @default 15 */
10
10
  indentWidth?: number;
11
- /** When set to `true`, data type labels prefix values @default `true` */
11
+ /** When set to `true`, data type labels prefix values @default true */
12
12
  displayDataTypes?: boolean;
13
- /** When set to `true`, `objects` and `arrays` are labeled with size @default `true` */
13
+ /** When set to `true`, `objects` and `arrays` are labeled with size @default true */
14
14
  displayObjectSize?: boolean;
15
- /** Define the root node name. @default `undefined` */
15
+ /** Define the root node name. @default undefined */
16
16
  keyName?: string | number;
17
+ /** The user can copy objects and arrays to clipboard by clicking on the clipboard icon. @default true */
18
+ enableClipboard?: boolean;
19
+ /** Redefine interface elements to re-render. */
17
20
  components?: {
18
21
  braces?: MetaProps['render'];
19
22
  ellipsis?: EllipsisProps['render'];
package/esm/node.d.ts CHANGED
@@ -7,7 +7,6 @@ export interface MetaProps extends LabelProps {
7
7
  render?: (props: Pick<MetaProps, 'start' | 'isArray' | 'className' | 'children'>) => JSX.Element;
8
8
  }
9
9
  export declare function Meta(props: MetaProps): import("react/jsx-runtime").JSX.Element;
10
- export declare const Line: FC<PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>>;
11
10
  export interface EllipsisProps extends React.HTMLAttributes<HTMLSpanElement> {
12
11
  render?: (props: EllipsisProps) => JSX.Element;
13
12
  }
package/esm/node.js CHANGED
@@ -3,11 +3,12 @@ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutP
3
3
  var _excluded = ["isArray", "start", "className", "render"],
4
4
  _excluded2 = ["style", "render"],
5
5
  _excluded3 = ["children", "render", "color", "value", "className", "show"],
6
- _excluded4 = ["value", "keyName", "displayDataTypes", "components", "displayObjectSize", "indentWidth", "keyid"];
7
- import { Fragment, useId, cloneElement } from 'react';
8
- import { ValueView, Colon, Label, typeMap } from './value';
6
+ _excluded4 = ["value", "keyName", "displayDataTypes", "components", "displayObjectSize", "enableClipboard", "indentWidth", "keyid"];
7
+ import { Fragment, useId, cloneElement, useState } from 'react';
8
+ import { ValueView, Colon, Label, Line, typeMap } from './value';
9
9
  import { TriangleArrow } from './arrow/TriangleArrow';
10
10
  import { useExpandsStatus, store } from './store';
11
+ import { Copied } from './copied';
11
12
  import { jsx as _jsx } from "react/jsx-runtime";
12
13
  import { jsxs as _jsxs } from "react/jsx-runtime";
13
14
  export function Meta(props) {
@@ -36,7 +37,6 @@ export function Meta(props) {
36
37
  children: start ? mark.charAt(0) : mark.charAt(1)
37
38
  }));
38
39
  }
39
- export var Line = props => /*#__PURE__*/_jsx("div", _extends({}, props));
40
40
  export var Ellipsis = _ref => {
41
41
  var {
42
42
  style,
@@ -108,6 +108,7 @@ export function RooNode(props) {
108
108
  displayDataTypes = true,
109
109
  components = {},
110
110
  displayObjectSize = true,
111
+ enableClipboard = true,
111
112
  indentWidth = 15,
112
113
  keyid = 'root'
113
114
  } = props,
@@ -135,6 +136,9 @@ export function RooNode(props) {
135
136
  };
136
137
  var valueViewProps = {
137
138
  displayDataTypes,
139
+ displayObjectSize,
140
+ enableClipboard,
141
+ indentWidth,
138
142
  renderValue: components.value
139
143
  };
140
144
  var arrowView = components.arrow ? /*#__PURE__*/cloneElement(components.arrow, {
@@ -143,7 +147,16 @@ export function RooNode(props) {
143
147
  }) : /*#__PURE__*/_jsx(TriangleArrow, {
144
148
  style: arrowStyle
145
149
  });
150
+ var [showTools, setShowTools] = useState(false);
151
+ var tools = enableClipboard ? /*#__PURE__*/_jsx(Copied, {
152
+ show: showTools,
153
+ text: value
154
+ }) : undefined;
155
+ var mouseEnter = () => setShowTools(true);
156
+ var mouseLeave = () => setShowTools(false);
146
157
  return /*#__PURE__*/_jsxs("div", _extends({}, reset, {
158
+ onMouseEnter: mouseEnter,
159
+ onMouseLeave: mouseLeave,
147
160
  children: [/*#__PURE__*/_jsxs(Line, {
148
161
  style: {
149
162
  display: 'inline-flex',
@@ -169,15 +182,23 @@ export function RooNode(props) {
169
182
  render: components.braces
170
183
  }), displayObjectSize && /*#__PURE__*/_jsxs(CountInfo, {
171
184
  children: [nameKeys.length, " items"]
172
- })]
185
+ }), tools]
173
186
  }), expand && /*#__PURE__*/_jsx(Line, {
174
187
  style: {
175
- borderLeft: 'var(--w-rjv-border-left, 1px solid #ebebeb)',
188
+ borderLeft: '1px solid var(--w-rjv-line-color, #ebebeb)',
176
189
  marginLeft: 6
177
190
  },
178
191
  children: nameKeys.length > 0 && nameKeys.map((key, idx) => {
179
192
  var item = value[key];
180
- if (Array.isArray(item)) {
193
+ var renderKey = /*#__PURE__*/_jsx(Semicolon, {
194
+ value: item,
195
+ render: components.objectKey,
196
+ color: typeof key === 'number' ? typeMap['number'].color : '',
197
+ show: typeof key === 'string',
198
+ children: key
199
+ });
200
+ var isEmpty = Array.isArray(item) && item.length === 0 || typeof item === 'object' && item && !(item instanceof Date) && Object.keys(item).length === 0;
201
+ if (Array.isArray(item) && !isEmpty) {
181
202
  var label = isArray ? idx : key;
182
203
  return /*#__PURE__*/_jsx(Line, {
183
204
  children: /*#__PURE__*/_jsx(RooNode, _extends({
@@ -187,35 +208,7 @@ export function RooNode(props) {
187
208
  }, subNodeProps))
188
209
  }, label + idx);
189
210
  }
190
- var renderKey = /*#__PURE__*/_jsx(Semicolon, {
191
- value: item,
192
- render: components.objectKey,
193
- color: typeof key === 'number' ? typeMap['number'].color : '',
194
- show: typeof key === 'string',
195
- children: key
196
- });
197
- if (typeof item === 'object' && item && !(item instanceof Date)) {
198
- if (Object.keys(item).length === 0) {
199
- return /*#__PURE__*/_jsxs(Line, {
200
- style: {
201
- paddingLeft: indentWidth
202
- },
203
- children: [/*#__PURE__*/_jsx(ValueView, _extends({}, valueViewProps, {
204
- renderKey: renderKey,
205
- keyName: key,
206
- value: item
207
- })), /*#__PURE__*/_jsx(Meta, {
208
- render: components.braces,
209
- start: true,
210
- isArray: isArray
211
- }), /*#__PURE__*/_jsx(Meta, {
212
- render: components.braces,
213
- isArray: isArray
214
- }), displayObjectSize && /*#__PURE__*/_jsxs(CountInfo, {
215
- children: [Object.keys(item).length, " items"]
216
- })]
217
- }, key + idx);
218
- }
211
+ if (typeof item === 'object' && item && !(item instanceof Date) && !isEmpty) {
219
212
  return /*#__PURE__*/_jsx(Line, {
220
213
  children: /*#__PURE__*/_jsx(RooNode, _extends({
221
214
  keyid: keyid + subkeyid + key,
@@ -227,16 +220,12 @@ export function RooNode(props) {
227
220
  if (typeof item === 'function') {
228
221
  return;
229
222
  }
230
- return /*#__PURE__*/_jsx(Line, {
231
- style: {
232
- paddingLeft: indentWidth
233
- },
234
- children: /*#__PURE__*/_jsx(ValueView, _extends({}, valueViewProps, {
235
- renderKey: renderKey,
236
- keyName: key,
237
- value: item
238
- }))
239
- }, idx);
223
+ return /*#__PURE__*/_jsx(ValueView, _extends({}, valueViewProps, {
224
+ renderBraces: components.braces,
225
+ renderKey: renderKey,
226
+ keyName: key,
227
+ value: item
228
+ }), idx);
240
229
  })
241
230
  }), expand && /*#__PURE__*/_jsx(Line, {
242
231
  style: {
@@ -2,9 +2,11 @@ export declare const darkTheme: {
2
2
  '--w-rjv-font-family': string;
3
3
  '--w-rjv-color': string;
4
4
  '--w-rjv-background-color': string;
5
- '--w-rjv-border-left': string;
5
+ '--w-rjv-line-color': string;
6
6
  '--w-rjv-arrow-color': string;
7
7
  '--w-rjv-info-color': string;
8
+ '--w-rjv-copied-color': string;
9
+ '--w-rjv-copied-success-color': string;
8
10
  '--w-rjv-curlybraces-color': string;
9
11
  '--w-rjv-brackets-color': string;
10
12
  '--w-rjv-type-string-color': string;
package/esm/theme/dark.js CHANGED
@@ -2,9 +2,11 @@ export var darkTheme = {
2
2
  '--w-rjv-font-family': 'monospace',
3
3
  '--w-rjv-color': '#0184a6',
4
4
  '--w-rjv-background-color': '#202020',
5
- '--w-rjv-border-left': '1px solid #323232',
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-copied-color': '#0184a6',
9
+ '--w-rjv-copied-success-color': '#28a745',
8
10
  '--w-rjv-curlybraces-color': '#1896b6',
9
11
  '--w-rjv-brackets-color': '#1896b6',
10
12
  '--w-rjv-type-string-color': '#cb4b16',
@@ -2,9 +2,11 @@ export declare const lightTheme: {
2
2
  '--w-rjv-font-family': string;
3
3
  '--w-rjv-color': string;
4
4
  '--w-rjv-background-color': string;
5
- '--w-rjv-border-left': string;
5
+ '--w-rjv-line-color': string;
6
6
  '--w-rjv-arrow-color': string;
7
7
  '--w-rjv-info-color': string;
8
+ '--w-rjv-copied-color': string;
9
+ '--w-rjv-copied-success-color': string;
8
10
  '--w-rjv-curlybraces-color': string;
9
11
  '--w-rjv-brackets-color': string;
10
12
  '--w-rjv-type-string-color': string;
@@ -2,9 +2,11 @@ export var lightTheme = {
2
2
  '--w-rjv-font-family': 'monospace',
3
3
  '--w-rjv-color': '#002b36',
4
4
  '--w-rjv-background-color': '#ffffff',
5
- '--w-rjv-border-left': '1px solid #ebebeb',
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-copied-color': '#002b36',
9
+ '--w-rjv-copied-success-color': '#28a745',
8
10
  '--w-rjv-curlybraces-color': '#236a7c',
9
11
  '--w-rjv-brackets-color': '#236a7c',
10
12
  '--w-rjv-type-string-color': '#cb4b16',
package/esm/value.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import { FC, PropsWithChildren } from 'react';
2
+ import { MetaProps } from './node';
3
+ export declare const Line: FC<PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>>;
2
4
  export declare const typeMap: {
3
5
  string: {
4
6
  color: string;
@@ -40,14 +42,18 @@ export declare const typeMap: {
40
42
  export declare const Colon: FC<PropsWithChildren<React.HTMLAttributes<HTMLSpanElement>>>;
41
43
  export interface ValueViewProps<T> extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement> {
42
44
  keyName?: string;
43
- value: T;
45
+ value?: T;
44
46
  displayDataTypes: boolean;
47
+ displayObjectSize: boolean;
48
+ enableClipboard: boolean;
49
+ indentWidth: number;
45
50
  renderKey?: JSX.Element;
51
+ renderBraces?: MetaProps['render'];
46
52
  renderValue?: (props: React.HTMLAttributes<HTMLSpanElement> & {
47
53
  type: TypeProps['type'];
48
54
  }) => JSX.Element;
49
55
  }
50
- export declare function ValueView<T>(props: ValueViewProps<T>): import("react/jsx-runtime").JSX.Element;
56
+ export declare function ValueView<T = object>(props: ValueViewProps<T>): import("react/jsx-runtime").JSX.Element;
51
57
  export interface LabelProps extends React.HTMLAttributes<HTMLSpanElement> {
52
58
  color?: string;
53
59
  fontSize?: number;
package/esm/value.js CHANGED
@@ -1,11 +1,14 @@
1
- import _extends from "@babel/runtime/helpers/extends";
2
1
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
2
+ import _extends from "@babel/runtime/helpers/extends";
3
3
  var _excluded = ["children", "style"],
4
- _excluded2 = ["value", "keyName", "renderKey", "renderValue", "displayDataTypes"],
4
+ _excluded2 = ["value", "keyName", "indentWidth", "renderKey", "renderValue", "renderBraces", "enableClipboard", "displayObjectSize", "displayDataTypes"],
5
5
  _excluded3 = ["children", "color", "fontSize", "opacity", "paddingRight", "style"];
6
- import { Fragment } from 'react';
6
+ import { Fragment, useState } from 'react';
7
+ import { Meta, CountInfo } from './node';
8
+ import { Copied } from './copied';
7
9
  import { jsx as _jsx } from "react/jsx-runtime";
8
10
  import { jsxs as _jsxs } from "react/jsx-runtime";
11
+ export var Line = props => /*#__PURE__*/_jsx("div", _extends({}, props));
9
12
  var isFloat = n => Number(n) === n && n % 1 !== 0 || isNaN(n);
10
13
  export var typeMap = {
11
14
  string: {
@@ -64,8 +67,12 @@ export function ValueView(props) {
64
67
  var _typeMap$type;
65
68
  var {
66
69
  value,
70
+ indentWidth,
67
71
  renderKey,
68
72
  renderValue,
73
+ renderBraces,
74
+ enableClipboard,
75
+ displayObjectSize,
69
76
  displayDataTypes
70
77
  } = props,
71
78
  reset = _objectWithoutPropertiesLoose(props, _excluded2);
@@ -112,6 +119,13 @@ export function ValueView(props) {
112
119
  typeView = /*#__PURE__*/_jsx(Fragment, {});
113
120
  }
114
121
  color = ((_typeMap$type = typeMap[type]) == null ? void 0 : _typeMap$type.color) || '';
122
+ var [showTools, setShowTools] = useState(false);
123
+ var tools = enableClipboard ? /*#__PURE__*/_jsx(Copied, {
124
+ show: showTools,
125
+ text: value
126
+ }) : undefined;
127
+ var mouseEnter = () => setShowTools(true);
128
+ var mouseLeave = () => setShowTools(false);
115
129
  if (content && typeof content === 'string') {
116
130
  var valueView = renderValue ? renderValue({
117
131
  className: 'w-rjv-value',
@@ -126,13 +140,40 @@ export function ValueView(props) {
126
140
  className: "w-rjv-value",
127
141
  children: content
128
142
  });
129
- return /*#__PURE__*/_jsxs(Label, _extends({}, reset, {
130
- children: [renderKey, /*#__PURE__*/_jsx(Colon, {}), typeView, valueView]
131
- }));
143
+ return /*#__PURE__*/_jsx(Line, {
144
+ style: {
145
+ paddingLeft: indentWidth
146
+ },
147
+ onMouseEnter: mouseEnter,
148
+ onMouseLeave: mouseLeave,
149
+ children: /*#__PURE__*/_jsxs(Label, _extends({}, reset, {
150
+ children: [renderKey, /*#__PURE__*/_jsx(Colon, {}), typeView, valueView, tools]
151
+ }))
152
+ });
132
153
  }
133
- return /*#__PURE__*/_jsxs(Label, _extends({}, reset, {
134
- children: [renderKey, /*#__PURE__*/_jsx(Colon, {}), typeView]
135
- }));
154
+ var length = Array.isArray(value) ? value.length : Object.keys(value).length;
155
+ var empty = /*#__PURE__*/_jsxs(Fragment, {
156
+ children: [/*#__PURE__*/_jsx(Meta, {
157
+ render: renderBraces,
158
+ start: true,
159
+ isArray: Array.isArray(value)
160
+ }), /*#__PURE__*/_jsx(Meta, {
161
+ render: renderBraces,
162
+ isArray: Array.isArray(value)
163
+ }), displayObjectSize && /*#__PURE__*/_jsxs(CountInfo, {
164
+ children: [length, " items"]
165
+ })]
166
+ });
167
+ return /*#__PURE__*/_jsx(Line, {
168
+ style: {
169
+ paddingLeft: indentWidth
170
+ },
171
+ onMouseEnter: mouseEnter,
172
+ onMouseLeave: mouseLeave,
173
+ children: /*#__PURE__*/_jsxs(Label, _extends({}, reset, {
174
+ children: [renderKey, /*#__PURE__*/_jsx(Colon, {}), typeView, empty, tools]
175
+ }))
176
+ });
136
177
  }
137
178
  export var Label = _ref2 => {
138
179
  var {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uiw/react-json-view",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "description": "JSON viewer for react.",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",