json-edit-react 0.9.4 → 0.9.6
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 +8 -5
- package/build/index.cjs.js +51 -28
- package/build/index.d.ts +3 -2
- package/build/index.esm.js +52 -29
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Features include:
|
|
|
9
9
|
- edit individual values, or whole objects as JSON text
|
|
10
10
|
- fine-grained control over which elements can be edited, deleted, or added to
|
|
11
11
|
- customisable UI, through simple, pre-defined [themes](#themes), or specific CSS overrides
|
|
12
|
-
- self-contained —
|
|
12
|
+
- self-contained — rendered with plain HTML/CSS, so no dependance on external UI libraries
|
|
13
13
|
|
|
14
14
|
**[Explore the Demo](https://carlosnz.github.io/json-edit-react/)**
|
|
15
15
|
|
|
@@ -119,10 +119,12 @@ The function needn't return anything, but if it returns `false`, it will be cons
|
|
|
119
119
|
A similar callback is executed whenever an item is copied to the clipboard (if passed to the `enableClipboard` prop), but with a different input parameter:
|
|
120
120
|
|
|
121
121
|
```js
|
|
122
|
-
key
|
|
123
|
-
path
|
|
124
|
-
value
|
|
125
|
-
type
|
|
122
|
+
key // name of the property being copied
|
|
123
|
+
path // path to the property
|
|
124
|
+
value // the value copied to the clipboard
|
|
125
|
+
type // Either "path" or "value" depending on whether "Cmd/Ctrl" was pressed
|
|
126
|
+
stringValue // A nicely stringified version of `value`
|
|
127
|
+
// (i.e. what the clipboard actually receives)
|
|
126
128
|
```
|
|
127
129
|
|
|
128
130
|
Since there is very little user feedback when clicking "Copy", a good idea would be to present some kind of notification in this callback.
|
|
@@ -335,6 +337,7 @@ This component is heavily inspired by [react-json-view](https://github.com/mac-s
|
|
|
335
337
|
|
|
336
338
|
## Changelog
|
|
337
339
|
|
|
340
|
+
- **0.9.6**: Performance improvement by not processing child elements if not visible
|
|
338
341
|
- **0.9.4**:
|
|
339
342
|
- Layout improvements
|
|
340
343
|
- Better internal handling of functions in data
|
package/build/index.cjs.js
CHANGED
|
@@ -55,7 +55,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
55
55
|
|
|
56
56
|
var e=[],t=[];function n(n,r){if(n&&"undefined"!=typeof document){var a,s=!0===r.prepend?"prepend":"append",d=!0===r.singleTag,i="string"==typeof r.container?document.querySelector(r.container):document.getElementsByTagName("head")[0];if(d){var u=e.indexOf(i);-1===u&&(u=e.push(i)-1,t[u]={}),a=t[u]&&t[u][s]?t[u][s]:t[u][s]=c();}else a=c();65279===n.charCodeAt(0)&&(n=n.substring(1)),a.styleSheet?a.styleSheet.cssText+=n:a.appendChild(document.createTextNode(n));}function c(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),r.attributes)for(var t=Object.keys(r.attributes),n=0;n<t.length;n++)e.setAttribute(t[n],r.attributes[t[n]]);var a="prepend"===s?"afterbegin":"beforeend";return i.insertAdjacentElement(a,e),e}}
|
|
57
57
|
|
|
58
|
-
var css = ":root {\n --jer-select-border: #b6b6b6;\n --jer-select-focus: #777;\n --jer-select-arrow: #777;\n --jer-form-border: 1px solid #ededf0;\n --jer-form-border-focus: 1px solid #e2e2e2;\n --jer-expand-transition-time: 0.
|
|
58
|
+
var css = ":root {\n --jer-select-border: #b6b6b6;\n --jer-select-focus: #777;\n --jer-select-arrow: #777;\n --jer-form-border: 1px solid #ededf0;\n --jer-form-border-focus: 1px solid #e2e2e2;\n --jer-expand-transition-time: 0.5s;\n --jer-highlight-color: #b3d8ff;\n}\n\n.jer-visible {\n opacity: 1;\n transition: var(--jer-expand-transition-time);\n}\n\n.jer-hidden {\n opacity: 0;\n transition: var(--jer-expand-transition-time);\n}\n\n/* Select styled as per:\nhttps://moderncss.dev/custom-select-styles-with-pure-css/\n*/\n\n.jer-select select {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n background-color: transparent;\n border: none;\n padding: 0 1em 0 0;\n margin: 0;\n /* width: 100%; */\n font-family: inherit;\n font-size: inherit;\n color: black;\n cursor: inherit;\n line-height: inherit;\n z-index: 1;\n outline: none;\n}\nselect::-ms-expand {\n display: none;\n}\n\n.jer-select {\n display: grid;\n grid-template-areas: 'select';\n align-items: center;\n position: relative;\n min-width: 12ch;\n max-width: 15ch;\n border: 1px solid var(--jer-select-border);\n border-radius: 0.25em;\n padding: 0.25em 0.5em;\n font-size: 1em;\n cursor: pointer;\n line-height: 1.1;\n background-color: #fff;\n background-image: linear-gradient(to top, #f9f9f9, #fff 33%);\n}\n.jer-select select,\n.jer-select::after {\n grid-area: select;\n}\n.jer-select:not(.jer-select--multiple)::after {\n content: '';\n justify-self: end;\n width: 0.8em;\n height: 0.5em;\n background-color: var(--jer-select-arrow);\n -webkit-clip-path: polygon(100% 0%, 0 0%, 50% 100%);\n clip-path: polygon(100% 0%, 0 0%, 50% 100%);\n}\n\nselect:focus + .focus {\n position: absolute;\n top: -1px;\n left: -1px;\n right: -1px;\n bottom: -1px;\n border: 1px solid var(--jer-select-focus);\n border-radius: inherit;\n}\n\n.jer-editor-container {\n font-size: 1.1em;\n /* font-size: 20px; */\n padding: 1em;\n margin-top: 1em;\n margin-bottom: 1em;\n border-radius: 0.5em;\n}\n\n.jer-editor-container textarea {\n /* width: 90%; */\n color: var(--jer-input-color);\n border: var(--jer-form-border);\n border-radius: 0.3em;\n outline: none;\n}\n\n.jer-editor-container textarea:focus {\n border: var(--jer-form-border-focus);\n}\n\n.jer-editor-container input {\n border: var(--jer-form-border);\n border-radius: 0.3em;\n outline: none;\n}\n\n.jer-editor-container input:focus {\n border: var(--jer-form-border-focus);\n}\n\n/* Input highlighted text */\n.jer-editor-container ::selection {\n background-color: var(--jer-highlight-color);\n}\n\n.jer-editor-container select {\n /* color: red; */\n}\n\n.jer-component {\n}\n\n.jer-collection-header-row,\n.jer-value-main-row {\n display: flex;\n min-height: 1.7em;\n gap: 0.3em;\n align-items: center;\n}\n\n.jer-collection-header-row {\n display: flex;\n flex-wrap: wrap;\n}\n\n.jer-brackets {\n}\n\n.jer-collection-item-count {\n}\n\n.jer-collection-inner {\n position: relative;\n}\n\n.jer-collection-text-edit {\n display: flex;\n flex-direction: column;\n gap: 0.3em;\n align-items: flex-start;\n}\n\n.jer-collection-text-area {\n resize: both;\n padding-top: 0.2em;\n padding-left: 0.5em;\n padding-right: 0.5em;\n padding-bottom: 0;\n overflow: hidden;\n max-height: 40em;\n}\n\n.jer-collection-input-button-row {\n display: flex;\n justify-content: flex-end;\n font-size: 150%;\n}\n\n.jer-collection-element {\n}\n\n.jer-collection-error-row {\n position: absolute;\n bottom: 0;\n}\n\n.jer-collection-error-row-edit {\n}\n\n.jer-error-slug {\n margin-left: 1em;\n}\n\n.jer-value-component {\n position: relative;\n}\n\n.jer-value-main-row {\n display: flex;\n gap: 0;\n}\n\n.jer-value-and-buttons {\n display: flex;\n justify-content: flex-start;\n align-items: center;\n padding-left: 0.5em;\n}\n\n.jer-value-error-row {\n position: absolute;\n}\n\n.jer-value-string {\n line-height: 1.3em;\n}\n\n.jer-input-text {\n resize: none;\n margin: 0;\n height: 1.4em;\n padding-left: 0.5em;\n padding-right: 0.5em;\n padding-bottom: 0;\n min-width: 6em;\n overflow: hidden;\n max-height: 30em;\n}\n\n.jer-value-number {\n}\n\n.jer-value-boolean {\n}\n\n.jer-input-boolean {\n transform: scale(1.5);\n margin-left: 0.3em;\n margin-right: 0.3em;\n}\n\n.jer-value-null {\n}\n\n.jer-value-object {\n}\n\n.jer-object-key {\n word-break: break-word;\n line-height: 1.1em;\n}\n\n.jer-value-array {\n}\n\n.jer-value-invalid {\n opacity: 0.5;\n font-style: italic;\n}\n\n/* .jer-input-text, */\n.jer-input-number {\n height: 1.6em;\n}\n\n.jer-input-number {\n min-width: 3em;\n}\n\n.jer-input-component {\n}\n\n.jer-edit-buttons,\n.jer-confirm-buttons {\n display: flex;\n align-items: center;\n cursor: pointer;\n}\n\n.jer-input-buttons {\n gap: 0.4em;\n}\n\n.jer-edit-buttons {\n gap: 0.4em;\n margin-left: 0.5em;\n opacity: 0;\n}\n\n.jer-confirm-buttons {\n gap: 0.2em;\n margin-left: 0.4em;\n}\n\n.jer-edit-buttons:hover {\n opacity: 1;\n position: relative;\n}\n\n.jer-collection-header-row:hover > .jer-edit-buttons {\n opacity: 1;\n}\n\n.jer-value-main-row:hover > .jer-edit-buttons {\n opacity: 1;\n}\n\n.jer-value-and-buttons:hover > .jer-edit-buttons {\n opacity: 1;\n}\n\n.jer-input-buttons {\n}\n\n.jer-copy-pulse {\n position: relative;\n transition: transform var(--jer-expand-transition-time);\n}\n\n.jer-copy-pulse:hover {\n opacity: 0.85;\n transition: 0.3s;\n transform: scale(1.2);\n}\n\n.jer-copy-pulse:after {\n content: '';\n display: block;\n position: absolute;\n border-radius: 50%;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n opacity: 0;\n transition: all 0.5s;\n box-shadow: 0 0 15px 5px var(--jer-icon-copy-color);\n}\n\n.jer-copy-pulse:active:after {\n box-shadow: 0 0 0 0 var(--jer-icon-copy-color);\n position: absolute;\n border-radius: 4em;\n left: 0;\n top: 0;\n opacity: 1;\n transition: 0s;\n}\n\n.jer-copy-pulse:active {\n top: 0.07em;\n}\n\n.jer-rotate-90 {\n transform: rotate(-90deg);\n transition: transform var(--jer-expand-transition-time);\n}\n\n.jer-accordion-icon {\n /* font-size: '2em'; */\n transition: transform var(--jer-expand-transition-time);\n}\n\n.jer-icon:hover {\n opacity: 0.85;\n transition: 0.3s;\n transform: scale(1.2);\n}\n";
|
|
59
59
|
n(css,{});
|
|
60
60
|
|
|
61
61
|
const defaultTheme$1 = {
|
|
@@ -394,6 +394,7 @@ const AutogrowTextArea = ({ className, name, value, setValue, handleKeyPress, })
|
|
|
394
394
|
}, onKeyDown: handleKeyPress }), jsxRuntime.jsx("span", Object.assign({ className: className, style: Object.assign({ visibility: 'hidden', height: 'auto', gridArea: '1 / 1 / 2 / 2', color: 'red', opacity: 0.9, whiteSpace: 'pre-wrap', overflow: 'clip', border: '1px solid transparent' }, styles.input) }, { children: dummyValue }))] })));
|
|
395
395
|
};
|
|
396
396
|
|
|
397
|
+
const INVALID_FUNCTION_STRING = '**INVALID_FUNCTION**';
|
|
397
398
|
const truncate = (string, length = 200) => string.length < length ? string : `${string.slice(0, length - 2).trim()}...`;
|
|
398
399
|
const StringValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, stringTruncate, }) => {
|
|
399
400
|
const { styles } = useTheme();
|
|
@@ -430,14 +431,23 @@ const NullValue = ({ value, isEditing, setIsEditing }) => {
|
|
|
430
431
|
const { styles } = useTheme();
|
|
431
432
|
return isEditing ? (jsxRuntime.jsx("div", Object.assign({ className: "jer-input-null" }, { children: "null" }))) : (jsxRuntime.jsx("div", Object.assign({ onDoubleClick: () => setIsEditing(true), className: "jer-value-null", style: styles.null }, { children: String(value) })));
|
|
432
433
|
};
|
|
433
|
-
const ObjectValue = () => {
|
|
434
|
-
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
434
|
+
const ObjectValue = () => (jsxRuntime.jsx("span", Object.assign({ className: "jer-value-object" }, { children: '{ }' })));
|
|
435
|
+
const ArrayValue = ({ value }) => (jsxRuntime.jsx("span", Object.assign({ className: "jer-value-array" }, { children: `[${value === null ? '' : value}]` })));
|
|
436
|
+
const InvalidValue = ({ value }) => {
|
|
437
|
+
let message = 'Error!';
|
|
438
|
+
switch (typeof value) {
|
|
439
|
+
case 'string':
|
|
440
|
+
if (value === INVALID_FUNCTION_STRING)
|
|
441
|
+
message = 'Function';
|
|
442
|
+
break;
|
|
443
|
+
case 'undefined':
|
|
444
|
+
message = 'Undefined';
|
|
445
|
+
break;
|
|
446
|
+
case 'symbol':
|
|
447
|
+
message = 'Symbol';
|
|
448
|
+
break;
|
|
449
|
+
}
|
|
450
|
+
return jsxRuntime.jsx("span", Object.assign({ className: "jer-value-invalid" }, { children: message }));
|
|
441
451
|
};
|
|
442
452
|
|
|
443
453
|
const Icon = ({ name, rotate }) => {
|
|
@@ -458,7 +468,7 @@ const Icon = ({ name, rotate }) => {
|
|
|
458
468
|
case 'cancel':
|
|
459
469
|
return ((_f = icons === null || icons === void 0 ? void 0 : icons.cancel) !== null && _f !== void 0 ? _f : (jsxRuntime.jsx(ti.TiCancel, Object.assign({}, commonProps, { style: Object.assign({ fontSize: '130%' }, styles.iconCancel) }))));
|
|
460
470
|
case 'chevron':
|
|
461
|
-
return ((_g = icons === null || icons === void 0 ? void 0 : icons.chevron) !== null && _g !== void 0 ? _g : (jsxRuntime.jsx(fa.FaChevronDown, { className:
|
|
471
|
+
return ((_g = icons === null || icons === void 0 ? void 0 : icons.chevron) !== null && _g !== void 0 ? _g : (jsxRuntime.jsx(fa.FaChevronDown, { className: `jer-accordion-icon${rotate ? ' jer-rotate-90' : ''}`, style: styles.iconCollection })));
|
|
462
472
|
default:
|
|
463
473
|
return jsxRuntime.jsx(jsxRuntime.Fragment, {});
|
|
464
474
|
}
|
|
@@ -482,21 +492,24 @@ const EditButtons = ({ startEdit, handleDelete, handleAdd, enableClipboard, type
|
|
|
482
492
|
setIsAdding(false);
|
|
483
493
|
};
|
|
484
494
|
const handleCopy = (e) => {
|
|
485
|
-
let
|
|
486
|
-
let value
|
|
495
|
+
let copyType = 'value';
|
|
496
|
+
let value;
|
|
497
|
+
let stringValue = '';
|
|
487
498
|
if (enableClipboard) {
|
|
488
499
|
switch (e.ctrlKey || e.metaKey) {
|
|
489
500
|
case true:
|
|
490
501
|
value = stringifyPath(path);
|
|
491
|
-
|
|
502
|
+
stringValue = value;
|
|
503
|
+
copyType = 'path';
|
|
492
504
|
break;
|
|
493
505
|
default:
|
|
494
|
-
value =
|
|
506
|
+
value = data;
|
|
507
|
+
stringValue = type ? JSON.stringify(data, null, 2) : String(value);
|
|
495
508
|
}
|
|
496
|
-
navigator.clipboard.writeText(
|
|
509
|
+
navigator.clipboard.writeText(stringValue);
|
|
497
510
|
}
|
|
498
511
|
if (typeof enableClipboard === 'function')
|
|
499
|
-
enableClipboard({ value, path, key: name, type });
|
|
512
|
+
enableClipboard({ value, stringValue, path, key: name, type: copyType });
|
|
500
513
|
};
|
|
501
514
|
return (jsxRuntime.jsxs("div", Object.assign({ className: "jer-edit-buttons", style: isAdding ? { opacity: 1 } : undefined }, { children: [enableClipboard && (jsxRuntime.jsx("div", Object.assign({ onClick: handleCopy, className: "jer-copy-pulse" }, { children: jsxRuntime.jsx(Icon, { name: "copy" }) }))), startEdit && (jsxRuntime.jsx("div", Object.assign({ onClick: startEdit }, { children: jsxRuntime.jsx(Icon, { name: "edit" }) }))), handleDelete && (jsxRuntime.jsx("div", Object.assign({ onClick: handleDelete }, { children: jsxRuntime.jsx(Icon, { name: "delete" }) }))), handleAdd && (jsxRuntime.jsx("div", Object.assign({ onClick: () => {
|
|
502
515
|
if (type === 'object')
|
|
@@ -530,11 +543,11 @@ const DataTypes = [...ValueDataTypes, ...CollectionDataTypes];
|
|
|
530
543
|
const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard, restrictEditFilter, restrictDeleteFilter, showArrayIndices, stringTruncate, indent, translate, }) => {
|
|
531
544
|
const { styles } = useTheme();
|
|
532
545
|
const [isEditing, setIsEditing] = react.useState(false);
|
|
533
|
-
const [value, setValue] = react.useState(typeof data === 'function' ?
|
|
546
|
+
const [value, setValue] = react.useState(typeof data === 'function' ? INVALID_FUNCTION_STRING : data);
|
|
534
547
|
const [error, setError] = react.useState(null);
|
|
535
548
|
const [dataType, setDataType] = react.useState(getDataType(data));
|
|
536
549
|
react.useEffect(() => {
|
|
537
|
-
setValue(typeof data === 'function' ?
|
|
550
|
+
setValue(typeof data === 'function' ? INVALID_FUNCTION_STRING : data);
|
|
538
551
|
setDataType(getDataType(data));
|
|
539
552
|
}, [data, error]);
|
|
540
553
|
const handleChangeDataType = (type) => {
|
|
@@ -588,7 +601,7 @@ const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard,
|
|
|
588
601
|
value,
|
|
589
602
|
setValue,
|
|
590
603
|
isEditing,
|
|
591
|
-
setIsEditing,
|
|
604
|
+
setIsEditing: canEdit ? () => setIsEditing(true) : () => { },
|
|
592
605
|
handleEdit,
|
|
593
606
|
handleCancel,
|
|
594
607
|
path,
|
|
@@ -659,7 +672,10 @@ const CollectionNode = (_a) => {
|
|
|
659
672
|
const [error, setError] = react.useState(null);
|
|
660
673
|
const collectionSize = Object.keys(data).length;
|
|
661
674
|
const filterProps = { key: name, path, level: path.length, value: data, size: collectionSize };
|
|
662
|
-
const
|
|
675
|
+
const startCollapsed = collapseFilter(filterProps);
|
|
676
|
+
const [collapsed, setCollapsed] = react.useState(startCollapsed);
|
|
677
|
+
const hasBeenOpened = react.useRef(!startCollapsed);
|
|
678
|
+
const [isAnimating, setIsAnimating] = react.useState(false);
|
|
663
679
|
react.useEffect(() => {
|
|
664
680
|
setStringifiedValue(JSON.stringify(data, null, 2));
|
|
665
681
|
}, [data]);
|
|
@@ -675,6 +691,14 @@ const CollectionNode = (_a) => {
|
|
|
675
691
|
else if (e.key === 'Escape')
|
|
676
692
|
handleCancel();
|
|
677
693
|
};
|
|
694
|
+
const handleCollapse = () => {
|
|
695
|
+
if (!isEditing) {
|
|
696
|
+
setIsAnimating(true);
|
|
697
|
+
hasBeenOpened.current = true;
|
|
698
|
+
setCollapsed(!collapsed);
|
|
699
|
+
setTimeout(() => setIsAnimating(false), 500);
|
|
700
|
+
}
|
|
701
|
+
};
|
|
678
702
|
const showError = (errorString) => {
|
|
679
703
|
setError(errorString);
|
|
680
704
|
setTimeout(() => setError(null), ERROR_DISPLAY_TIME);
|
|
@@ -739,10 +763,7 @@ const CollectionNode = (_a) => {
|
|
|
739
763
|
if (keySort && collectionType === 'object')
|
|
740
764
|
keyValueArray.sort(typeof keySort === 'function' ? (a, b) => keySort(a[0], b[0]) : undefined);
|
|
741
765
|
const numOfLines = JSON.stringify(data, null, 2).split('\n').length;
|
|
742
|
-
return (jsxRuntime.jsxs("div", Object.assign({ className: "jer-component fb-collection-component", style: { marginLeft: `${path.length === 0 ? 0 : indent / 2}em` } }, { children: [jsxRuntime.jsxs("div", Object.assign({ className: "jer-collection-header-row" }, { children: [jsxRuntime.jsx("div", Object.assign({ onClick: ()
|
|
743
|
-
if (!isEditing)
|
|
744
|
-
setCollapsed(!collapsed);
|
|
745
|
-
} }, { children: jsxRuntime.jsx(Icon, { name: "chevron", rotate: collapsed }) })), jsxRuntime.jsxs("div", Object.assign({ className: "jer-collection-name" }, { children: [jsxRuntime.jsx("span", Object.assign({ style: styles.property }, { children: showLabel ? `${name}:` : null })), !isEditing && (jsxRuntime.jsx("span", Object.assign({ className: "jer-brackets", style: styles.bracket }, { children: brackets.open })))] })), !isEditing && (jsxRuntime.jsx("div", Object.assign({ className: "jer-collection-item-count", style: styles.itemCount }, { children: collectionSize === 1
|
|
766
|
+
return (jsxRuntime.jsxs("div", Object.assign({ className: "jer-component fb-collection-component", style: { marginLeft: `${path.length === 0 ? 0 : indent / 2}em` } }, { children: [jsxRuntime.jsxs("div", Object.assign({ className: "jer-collection-header-row" }, { children: [jsxRuntime.jsx("div", Object.assign({ onClick: handleCollapse }, { children: jsxRuntime.jsx(Icon, { name: "chevron", rotate: collapsed }) })), jsxRuntime.jsxs("div", Object.assign({ className: "jer-collection-name" }, { children: [jsxRuntime.jsx("span", Object.assign({ style: styles.property }, { children: showLabel ? `${name}:` : null })), !isEditing && (jsxRuntime.jsx("span", Object.assign({ className: "jer-brackets", style: styles.bracket }, { children: brackets.open })))] })), !isEditing && (jsxRuntime.jsx("div", Object.assign({ className: "jer-collection-item-count", style: styles.itemCount }, { children: collectionSize === 1
|
|
746
767
|
? translate('ITEM_SINGLE', 1)
|
|
747
768
|
: translate('ITEMS_MULTIPLE', collectionSize) }))), jsxRuntime.jsx("div", Object.assign({ className: `jer-brackets${collapsed ? ' jer-visible' : ' jer-hidden'}`, style: styles.bracket }, { children: brackets.close })), !isEditing && (jsxRuntime.jsx(EditButtons, { startEdit: canEdit
|
|
748
769
|
? () => {
|
|
@@ -750,10 +771,12 @@ const CollectionNode = (_a) => {
|
|
|
750
771
|
setCollapsed(false);
|
|
751
772
|
}
|
|
752
773
|
: undefined, handleAdd: canAdd ? handleAdd : undefined, handleDelete: canDelete ? handleDelete : undefined, enableClipboard: enableClipboard, type: collectionType, data: data, name: name, path: path, translate: translate }))] })), jsxRuntime.jsxs("div", Object.assign({ className: 'jer-collection-inner', style: {
|
|
753
|
-
maxHeight: collapsed ? 0 : !isEditing ? `${numOfLines *
|
|
754
|
-
overflowY: collapsed ? 'hidden' : 'visible',
|
|
774
|
+
maxHeight: collapsed ? 0 : !isEditing ? `${numOfLines * 3}em` : undefined,
|
|
775
|
+
overflowY: collapsed || isAnimating ? 'hidden' : 'visible',
|
|
755
776
|
transition: `max-height ${transitionTime}`,
|
|
756
|
-
} }, { children: [isEditing ? (jsxRuntime.jsx("div", Object.assign({ className: "jer-collection-text-edit" }, { children: jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(AutogrowTextArea, { className: "jer-collection-text-area", name: path.join('.'), value: stringifiedValue, setValue: setStringifiedValue, isEditing: isEditing, handleKeyPress: handleKeyPress }), jsxRuntime.jsx("div", Object.assign({ className: "jer-collection-input-button-row" }, { children: jsxRuntime.jsx(InputButtons, { onOk: handleEdit, onCancel: handleCancel, isCollection: true }) }))] }) }))) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children:
|
|
777
|
+
} }, { children: [isEditing ? (jsxRuntime.jsx("div", Object.assign({ className: "jer-collection-text-edit" }, { children: jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(AutogrowTextArea, { className: "jer-collection-text-area", name: path.join('.'), value: stringifiedValue, setValue: setStringifiedValue, isEditing: isEditing, handleKeyPress: handleKeyPress }), jsxRuntime.jsx("div", Object.assign({ className: "jer-collection-input-button-row" }, { children: jsxRuntime.jsx(InputButtons, { onOk: handleEdit, onCancel: handleCancel, isCollection: true }) }))] }) }))) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: !hasBeenOpened.current
|
|
778
|
+
? null
|
|
779
|
+
: keyValueArray.map(([key, value]) => (jsxRuntime.jsx("div", Object.assign({ className: "jer-collection-element" }, { children: isCollection(value) ? (jsxRuntime.jsx(CollectionNode, Object.assign({ data: value, path: [...path, key], name: key }, props), key)) : (jsxRuntime.jsx(ValueNodeWrapper, Object.assign({ data: value, path: [...path, key], name: key }, props, { showArrayIndices: collectionType === 'object' ? true : showArrayIndices }), key)) }), key))) })), jsxRuntime.jsx("div", Object.assign({ className: isEditing ? 'jer-collection-error-row' : 'jer-collection-error-row-edit' }, { children: error && (jsxRuntime.jsx("span", Object.assign({ className: "jer-error-slug", style: styles.error }, { children: error }))) })), jsxRuntime.jsx("div", Object.assign({ className: "jer-brackets", style: styles.bracket }, { children: brackets.close }))] }))] })));
|
|
757
780
|
};
|
|
758
781
|
|
|
759
782
|
const localisedStrings = {
|
|
@@ -772,7 +795,7 @@ const translate = (translations, key, count) => {
|
|
|
772
795
|
};
|
|
773
796
|
const getTranslateFunction = (translations) => (key, count) => translate(translations, key, count);
|
|
774
797
|
|
|
775
|
-
const Editor = ({ data: srcData, rootName = 'root', onUpdate, onEdit: srcEdit = onUpdate, onDelete: srcDelete = onUpdate, onAdd: srcAdd = onUpdate, enableClipboard = true, theme = 'default', icons, indent = 4, collapse = false, restrictEdit = false, restrictDelete = false, restrictAdd = false, keySort = false, showArrayIndices = true, defaultValue = null, minWidth = 250, maxWidth =
|
|
798
|
+
const Editor = ({ data: srcData, rootName = 'root', onUpdate, onEdit: srcEdit = onUpdate, onDelete: srcDelete = onUpdate, onAdd: srcAdd = onUpdate, enableClipboard = true, theme = 'default', icons, indent = 4, collapse = false, restrictEdit = false, restrictDelete = false, restrictAdd = false, keySort = false, showArrayIndices = true, defaultValue = null, minWidth = 250, maxWidth = 'min(600px, 90vw)', stringTruncate = 250, translations = {}, className, }) => {
|
|
776
799
|
const [data, setData] = react.useState(srcData);
|
|
777
800
|
const { styles, setTheme, setIcons } = useTheme();
|
|
778
801
|
const collapseFilter = react.useCallback(getFilterFunction(collapse), [collapse]);
|
package/build/index.d.ts
CHANGED
|
@@ -55,7 +55,7 @@ interface JsonEditorProps {
|
|
|
55
55
|
showArrayIndices?: boolean;
|
|
56
56
|
defaultValue?: unknown;
|
|
57
57
|
minWidth?: string | number;
|
|
58
|
-
maxWidth?: number;
|
|
58
|
+
maxWidth?: string | number;
|
|
59
59
|
stringTruncate?: number;
|
|
60
60
|
translations?: Partial<LocalisedStrings>;
|
|
61
61
|
}
|
|
@@ -89,7 +89,8 @@ type CopyType = 'path' | 'value';
|
|
|
89
89
|
type CopyFunction = (input: {
|
|
90
90
|
key: CollectionKey;
|
|
91
91
|
path: CollectionKey[];
|
|
92
|
-
value:
|
|
92
|
+
value: unknown;
|
|
93
|
+
stringValue: string;
|
|
93
94
|
type: CopyType;
|
|
94
95
|
}) => void;
|
|
95
96
|
type CompareFunction = (a: string, b: string) => number;
|
package/build/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext, useState, useContext, useEffect, useMemo, useCallback } from 'react';
|
|
2
|
+
import { createContext, useState, useContext, useEffect, useMemo, useRef, useCallback } from 'react';
|
|
3
3
|
import assign from 'object-property-assigner';
|
|
4
4
|
import extract from 'object-property-extractor';
|
|
5
5
|
import clone from 'just-clone';
|
|
@@ -51,7 +51,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
51
51
|
|
|
52
52
|
var e=[],t=[];function n(n,r){if(n&&"undefined"!=typeof document){var a,s=!0===r.prepend?"prepend":"append",d=!0===r.singleTag,i="string"==typeof r.container?document.querySelector(r.container):document.getElementsByTagName("head")[0];if(d){var u=e.indexOf(i);-1===u&&(u=e.push(i)-1,t[u]={}),a=t[u]&&t[u][s]?t[u][s]:t[u][s]=c();}else a=c();65279===n.charCodeAt(0)&&(n=n.substring(1)),a.styleSheet?a.styleSheet.cssText+=n:a.appendChild(document.createTextNode(n));}function c(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),r.attributes)for(var t=Object.keys(r.attributes),n=0;n<t.length;n++)e.setAttribute(t[n],r.attributes[t[n]]);var a="prepend"===s?"afterbegin":"beforeend";return i.insertAdjacentElement(a,e),e}}
|
|
53
53
|
|
|
54
|
-
var css = ":root {\n --jer-select-border: #b6b6b6;\n --jer-select-focus: #777;\n --jer-select-arrow: #777;\n --jer-form-border: 1px solid #ededf0;\n --jer-form-border-focus: 1px solid #e2e2e2;\n --jer-expand-transition-time: 0.
|
|
54
|
+
var css = ":root {\n --jer-select-border: #b6b6b6;\n --jer-select-focus: #777;\n --jer-select-arrow: #777;\n --jer-form-border: 1px solid #ededf0;\n --jer-form-border-focus: 1px solid #e2e2e2;\n --jer-expand-transition-time: 0.5s;\n --jer-highlight-color: #b3d8ff;\n}\n\n.jer-visible {\n opacity: 1;\n transition: var(--jer-expand-transition-time);\n}\n\n.jer-hidden {\n opacity: 0;\n transition: var(--jer-expand-transition-time);\n}\n\n/* Select styled as per:\nhttps://moderncss.dev/custom-select-styles-with-pure-css/\n*/\n\n.jer-select select {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n background-color: transparent;\n border: none;\n padding: 0 1em 0 0;\n margin: 0;\n /* width: 100%; */\n font-family: inherit;\n font-size: inherit;\n color: black;\n cursor: inherit;\n line-height: inherit;\n z-index: 1;\n outline: none;\n}\nselect::-ms-expand {\n display: none;\n}\n\n.jer-select {\n display: grid;\n grid-template-areas: 'select';\n align-items: center;\n position: relative;\n min-width: 12ch;\n max-width: 15ch;\n border: 1px solid var(--jer-select-border);\n border-radius: 0.25em;\n padding: 0.25em 0.5em;\n font-size: 1em;\n cursor: pointer;\n line-height: 1.1;\n background-color: #fff;\n background-image: linear-gradient(to top, #f9f9f9, #fff 33%);\n}\n.jer-select select,\n.jer-select::after {\n grid-area: select;\n}\n.jer-select:not(.jer-select--multiple)::after {\n content: '';\n justify-self: end;\n width: 0.8em;\n height: 0.5em;\n background-color: var(--jer-select-arrow);\n -webkit-clip-path: polygon(100% 0%, 0 0%, 50% 100%);\n clip-path: polygon(100% 0%, 0 0%, 50% 100%);\n}\n\nselect:focus + .focus {\n position: absolute;\n top: -1px;\n left: -1px;\n right: -1px;\n bottom: -1px;\n border: 1px solid var(--jer-select-focus);\n border-radius: inherit;\n}\n\n.jer-editor-container {\n font-size: 1.1em;\n /* font-size: 20px; */\n padding: 1em;\n margin-top: 1em;\n margin-bottom: 1em;\n border-radius: 0.5em;\n}\n\n.jer-editor-container textarea {\n /* width: 90%; */\n color: var(--jer-input-color);\n border: var(--jer-form-border);\n border-radius: 0.3em;\n outline: none;\n}\n\n.jer-editor-container textarea:focus {\n border: var(--jer-form-border-focus);\n}\n\n.jer-editor-container input {\n border: var(--jer-form-border);\n border-radius: 0.3em;\n outline: none;\n}\n\n.jer-editor-container input:focus {\n border: var(--jer-form-border-focus);\n}\n\n/* Input highlighted text */\n.jer-editor-container ::selection {\n background-color: var(--jer-highlight-color);\n}\n\n.jer-editor-container select {\n /* color: red; */\n}\n\n.jer-component {\n}\n\n.jer-collection-header-row,\n.jer-value-main-row {\n display: flex;\n min-height: 1.7em;\n gap: 0.3em;\n align-items: center;\n}\n\n.jer-collection-header-row {\n display: flex;\n flex-wrap: wrap;\n}\n\n.jer-brackets {\n}\n\n.jer-collection-item-count {\n}\n\n.jer-collection-inner {\n position: relative;\n}\n\n.jer-collection-text-edit {\n display: flex;\n flex-direction: column;\n gap: 0.3em;\n align-items: flex-start;\n}\n\n.jer-collection-text-area {\n resize: both;\n padding-top: 0.2em;\n padding-left: 0.5em;\n padding-right: 0.5em;\n padding-bottom: 0;\n overflow: hidden;\n max-height: 40em;\n}\n\n.jer-collection-input-button-row {\n display: flex;\n justify-content: flex-end;\n font-size: 150%;\n}\n\n.jer-collection-element {\n}\n\n.jer-collection-error-row {\n position: absolute;\n bottom: 0;\n}\n\n.jer-collection-error-row-edit {\n}\n\n.jer-error-slug {\n margin-left: 1em;\n}\n\n.jer-value-component {\n position: relative;\n}\n\n.jer-value-main-row {\n display: flex;\n gap: 0;\n}\n\n.jer-value-and-buttons {\n display: flex;\n justify-content: flex-start;\n align-items: center;\n padding-left: 0.5em;\n}\n\n.jer-value-error-row {\n position: absolute;\n}\n\n.jer-value-string {\n line-height: 1.3em;\n}\n\n.jer-input-text {\n resize: none;\n margin: 0;\n height: 1.4em;\n padding-left: 0.5em;\n padding-right: 0.5em;\n padding-bottom: 0;\n min-width: 6em;\n overflow: hidden;\n max-height: 30em;\n}\n\n.jer-value-number {\n}\n\n.jer-value-boolean {\n}\n\n.jer-input-boolean {\n transform: scale(1.5);\n margin-left: 0.3em;\n margin-right: 0.3em;\n}\n\n.jer-value-null {\n}\n\n.jer-value-object {\n}\n\n.jer-object-key {\n word-break: break-word;\n line-height: 1.1em;\n}\n\n.jer-value-array {\n}\n\n.jer-value-invalid {\n opacity: 0.5;\n font-style: italic;\n}\n\n/* .jer-input-text, */\n.jer-input-number {\n height: 1.6em;\n}\n\n.jer-input-number {\n min-width: 3em;\n}\n\n.jer-input-component {\n}\n\n.jer-edit-buttons,\n.jer-confirm-buttons {\n display: flex;\n align-items: center;\n cursor: pointer;\n}\n\n.jer-input-buttons {\n gap: 0.4em;\n}\n\n.jer-edit-buttons {\n gap: 0.4em;\n margin-left: 0.5em;\n opacity: 0;\n}\n\n.jer-confirm-buttons {\n gap: 0.2em;\n margin-left: 0.4em;\n}\n\n.jer-edit-buttons:hover {\n opacity: 1;\n position: relative;\n}\n\n.jer-collection-header-row:hover > .jer-edit-buttons {\n opacity: 1;\n}\n\n.jer-value-main-row:hover > .jer-edit-buttons {\n opacity: 1;\n}\n\n.jer-value-and-buttons:hover > .jer-edit-buttons {\n opacity: 1;\n}\n\n.jer-input-buttons {\n}\n\n.jer-copy-pulse {\n position: relative;\n transition: transform var(--jer-expand-transition-time);\n}\n\n.jer-copy-pulse:hover {\n opacity: 0.85;\n transition: 0.3s;\n transform: scale(1.2);\n}\n\n.jer-copy-pulse:after {\n content: '';\n display: block;\n position: absolute;\n border-radius: 50%;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n opacity: 0;\n transition: all 0.5s;\n box-shadow: 0 0 15px 5px var(--jer-icon-copy-color);\n}\n\n.jer-copy-pulse:active:after {\n box-shadow: 0 0 0 0 var(--jer-icon-copy-color);\n position: absolute;\n border-radius: 4em;\n left: 0;\n top: 0;\n opacity: 1;\n transition: 0s;\n}\n\n.jer-copy-pulse:active {\n top: 0.07em;\n}\n\n.jer-rotate-90 {\n transform: rotate(-90deg);\n transition: transform var(--jer-expand-transition-time);\n}\n\n.jer-accordion-icon {\n /* font-size: '2em'; */\n transition: transform var(--jer-expand-transition-time);\n}\n\n.jer-icon:hover {\n opacity: 0.85;\n transition: 0.3s;\n transform: scale(1.2);\n}\n";
|
|
55
55
|
n(css,{});
|
|
56
56
|
|
|
57
57
|
const defaultTheme$1 = {
|
|
@@ -390,6 +390,7 @@ const AutogrowTextArea = ({ className, name, value, setValue, handleKeyPress, })
|
|
|
390
390
|
}, onKeyDown: handleKeyPress }), jsx("span", Object.assign({ className: className, style: Object.assign({ visibility: 'hidden', height: 'auto', gridArea: '1 / 1 / 2 / 2', color: 'red', opacity: 0.9, whiteSpace: 'pre-wrap', overflow: 'clip', border: '1px solid transparent' }, styles.input) }, { children: dummyValue }))] })));
|
|
391
391
|
};
|
|
392
392
|
|
|
393
|
+
const INVALID_FUNCTION_STRING = '**INVALID_FUNCTION**';
|
|
393
394
|
const truncate = (string, length = 200) => string.length < length ? string : `${string.slice(0, length - 2).trim()}...`;
|
|
394
395
|
const StringValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, stringTruncate, }) => {
|
|
395
396
|
const { styles } = useTheme();
|
|
@@ -426,14 +427,23 @@ const NullValue = ({ value, isEditing, setIsEditing }) => {
|
|
|
426
427
|
const { styles } = useTheme();
|
|
427
428
|
return isEditing ? (jsx("div", Object.assign({ className: "jer-input-null" }, { children: "null" }))) : (jsx("div", Object.assign({ onDoubleClick: () => setIsEditing(true), className: "jer-value-null", style: styles.null }, { children: String(value) })));
|
|
428
429
|
};
|
|
429
|
-
const ObjectValue = () => {
|
|
430
|
-
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
430
|
+
const ObjectValue = () => (jsx("span", Object.assign({ className: "jer-value-object" }, { children: '{ }' })));
|
|
431
|
+
const ArrayValue = ({ value }) => (jsx("span", Object.assign({ className: "jer-value-array" }, { children: `[${value === null ? '' : value}]` })));
|
|
432
|
+
const InvalidValue = ({ value }) => {
|
|
433
|
+
let message = 'Error!';
|
|
434
|
+
switch (typeof value) {
|
|
435
|
+
case 'string':
|
|
436
|
+
if (value === INVALID_FUNCTION_STRING)
|
|
437
|
+
message = 'Function';
|
|
438
|
+
break;
|
|
439
|
+
case 'undefined':
|
|
440
|
+
message = 'Undefined';
|
|
441
|
+
break;
|
|
442
|
+
case 'symbol':
|
|
443
|
+
message = 'Symbol';
|
|
444
|
+
break;
|
|
445
|
+
}
|
|
446
|
+
return jsx("span", Object.assign({ className: "jer-value-invalid" }, { children: message }));
|
|
437
447
|
};
|
|
438
448
|
|
|
439
449
|
const Icon = ({ name, rotate }) => {
|
|
@@ -454,7 +464,7 @@ const Icon = ({ name, rotate }) => {
|
|
|
454
464
|
case 'cancel':
|
|
455
465
|
return ((_f = icons === null || icons === void 0 ? void 0 : icons.cancel) !== null && _f !== void 0 ? _f : (jsx(TiCancel, Object.assign({}, commonProps, { style: Object.assign({ fontSize: '130%' }, styles.iconCancel) }))));
|
|
456
466
|
case 'chevron':
|
|
457
|
-
return ((_g = icons === null || icons === void 0 ? void 0 : icons.chevron) !== null && _g !== void 0 ? _g : (jsx(FaChevronDown, { className:
|
|
467
|
+
return ((_g = icons === null || icons === void 0 ? void 0 : icons.chevron) !== null && _g !== void 0 ? _g : (jsx(FaChevronDown, { className: `jer-accordion-icon${rotate ? ' jer-rotate-90' : ''}`, style: styles.iconCollection })));
|
|
458
468
|
default:
|
|
459
469
|
return jsx(Fragment, {});
|
|
460
470
|
}
|
|
@@ -478,21 +488,24 @@ const EditButtons = ({ startEdit, handleDelete, handleAdd, enableClipboard, type
|
|
|
478
488
|
setIsAdding(false);
|
|
479
489
|
};
|
|
480
490
|
const handleCopy = (e) => {
|
|
481
|
-
let
|
|
482
|
-
let value
|
|
491
|
+
let copyType = 'value';
|
|
492
|
+
let value;
|
|
493
|
+
let stringValue = '';
|
|
483
494
|
if (enableClipboard) {
|
|
484
495
|
switch (e.ctrlKey || e.metaKey) {
|
|
485
496
|
case true:
|
|
486
497
|
value = stringifyPath(path);
|
|
487
|
-
|
|
498
|
+
stringValue = value;
|
|
499
|
+
copyType = 'path';
|
|
488
500
|
break;
|
|
489
501
|
default:
|
|
490
|
-
value =
|
|
502
|
+
value = data;
|
|
503
|
+
stringValue = type ? JSON.stringify(data, null, 2) : String(value);
|
|
491
504
|
}
|
|
492
|
-
navigator.clipboard.writeText(
|
|
505
|
+
navigator.clipboard.writeText(stringValue);
|
|
493
506
|
}
|
|
494
507
|
if (typeof enableClipboard === 'function')
|
|
495
|
-
enableClipboard({ value, path, key: name, type });
|
|
508
|
+
enableClipboard({ value, stringValue, path, key: name, type: copyType });
|
|
496
509
|
};
|
|
497
510
|
return (jsxs("div", Object.assign({ className: "jer-edit-buttons", style: isAdding ? { opacity: 1 } : undefined }, { children: [enableClipboard && (jsx("div", Object.assign({ onClick: handleCopy, className: "jer-copy-pulse" }, { children: jsx(Icon, { name: "copy" }) }))), startEdit && (jsx("div", Object.assign({ onClick: startEdit }, { children: jsx(Icon, { name: "edit" }) }))), handleDelete && (jsx("div", Object.assign({ onClick: handleDelete }, { children: jsx(Icon, { name: "delete" }) }))), handleAdd && (jsx("div", Object.assign({ onClick: () => {
|
|
498
511
|
if (type === 'object')
|
|
@@ -526,11 +539,11 @@ const DataTypes = [...ValueDataTypes, ...CollectionDataTypes];
|
|
|
526
539
|
const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard, restrictEditFilter, restrictDeleteFilter, showArrayIndices, stringTruncate, indent, translate, }) => {
|
|
527
540
|
const { styles } = useTheme();
|
|
528
541
|
const [isEditing, setIsEditing] = useState(false);
|
|
529
|
-
const [value, setValue] = useState(typeof data === 'function' ?
|
|
542
|
+
const [value, setValue] = useState(typeof data === 'function' ? INVALID_FUNCTION_STRING : data);
|
|
530
543
|
const [error, setError] = useState(null);
|
|
531
544
|
const [dataType, setDataType] = useState(getDataType(data));
|
|
532
545
|
useEffect(() => {
|
|
533
|
-
setValue(typeof data === 'function' ?
|
|
546
|
+
setValue(typeof data === 'function' ? INVALID_FUNCTION_STRING : data);
|
|
534
547
|
setDataType(getDataType(data));
|
|
535
548
|
}, [data, error]);
|
|
536
549
|
const handleChangeDataType = (type) => {
|
|
@@ -584,7 +597,7 @@ const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard,
|
|
|
584
597
|
value,
|
|
585
598
|
setValue,
|
|
586
599
|
isEditing,
|
|
587
|
-
setIsEditing,
|
|
600
|
+
setIsEditing: canEdit ? () => setIsEditing(true) : () => { },
|
|
588
601
|
handleEdit,
|
|
589
602
|
handleCancel,
|
|
590
603
|
path,
|
|
@@ -655,7 +668,10 @@ const CollectionNode = (_a) => {
|
|
|
655
668
|
const [error, setError] = useState(null);
|
|
656
669
|
const collectionSize = Object.keys(data).length;
|
|
657
670
|
const filterProps = { key: name, path, level: path.length, value: data, size: collectionSize };
|
|
658
|
-
const
|
|
671
|
+
const startCollapsed = collapseFilter(filterProps);
|
|
672
|
+
const [collapsed, setCollapsed] = useState(startCollapsed);
|
|
673
|
+
const hasBeenOpened = useRef(!startCollapsed);
|
|
674
|
+
const [isAnimating, setIsAnimating] = useState(false);
|
|
659
675
|
useEffect(() => {
|
|
660
676
|
setStringifiedValue(JSON.stringify(data, null, 2));
|
|
661
677
|
}, [data]);
|
|
@@ -671,6 +687,14 @@ const CollectionNode = (_a) => {
|
|
|
671
687
|
else if (e.key === 'Escape')
|
|
672
688
|
handleCancel();
|
|
673
689
|
};
|
|
690
|
+
const handleCollapse = () => {
|
|
691
|
+
if (!isEditing) {
|
|
692
|
+
setIsAnimating(true);
|
|
693
|
+
hasBeenOpened.current = true;
|
|
694
|
+
setCollapsed(!collapsed);
|
|
695
|
+
setTimeout(() => setIsAnimating(false), 500);
|
|
696
|
+
}
|
|
697
|
+
};
|
|
674
698
|
const showError = (errorString) => {
|
|
675
699
|
setError(errorString);
|
|
676
700
|
setTimeout(() => setError(null), ERROR_DISPLAY_TIME);
|
|
@@ -735,10 +759,7 @@ const CollectionNode = (_a) => {
|
|
|
735
759
|
if (keySort && collectionType === 'object')
|
|
736
760
|
keyValueArray.sort(typeof keySort === 'function' ? (a, b) => keySort(a[0], b[0]) : undefined);
|
|
737
761
|
const numOfLines = JSON.stringify(data, null, 2).split('\n').length;
|
|
738
|
-
return (jsxs("div", Object.assign({ className: "jer-component fb-collection-component", style: { marginLeft: `${path.length === 0 ? 0 : indent / 2}em` } }, { children: [jsxs("div", Object.assign({ className: "jer-collection-header-row" }, { children: [jsx("div", Object.assign({ onClick: ()
|
|
739
|
-
if (!isEditing)
|
|
740
|
-
setCollapsed(!collapsed);
|
|
741
|
-
} }, { children: jsx(Icon, { name: "chevron", rotate: collapsed }) })), jsxs("div", Object.assign({ className: "jer-collection-name" }, { children: [jsx("span", Object.assign({ style: styles.property }, { children: showLabel ? `${name}:` : null })), !isEditing && (jsx("span", Object.assign({ className: "jer-brackets", style: styles.bracket }, { children: brackets.open })))] })), !isEditing && (jsx("div", Object.assign({ className: "jer-collection-item-count", style: styles.itemCount }, { children: collectionSize === 1
|
|
762
|
+
return (jsxs("div", Object.assign({ className: "jer-component fb-collection-component", style: { marginLeft: `${path.length === 0 ? 0 : indent / 2}em` } }, { children: [jsxs("div", Object.assign({ className: "jer-collection-header-row" }, { children: [jsx("div", Object.assign({ onClick: handleCollapse }, { children: jsx(Icon, { name: "chevron", rotate: collapsed }) })), jsxs("div", Object.assign({ className: "jer-collection-name" }, { children: [jsx("span", Object.assign({ style: styles.property }, { children: showLabel ? `${name}:` : null })), !isEditing && (jsx("span", Object.assign({ className: "jer-brackets", style: styles.bracket }, { children: brackets.open })))] })), !isEditing && (jsx("div", Object.assign({ className: "jer-collection-item-count", style: styles.itemCount }, { children: collectionSize === 1
|
|
742
763
|
? translate('ITEM_SINGLE', 1)
|
|
743
764
|
: translate('ITEMS_MULTIPLE', collectionSize) }))), jsx("div", Object.assign({ className: `jer-brackets${collapsed ? ' jer-visible' : ' jer-hidden'}`, style: styles.bracket }, { children: brackets.close })), !isEditing && (jsx(EditButtons, { startEdit: canEdit
|
|
744
765
|
? () => {
|
|
@@ -746,10 +767,12 @@ const CollectionNode = (_a) => {
|
|
|
746
767
|
setCollapsed(false);
|
|
747
768
|
}
|
|
748
769
|
: undefined, handleAdd: canAdd ? handleAdd : undefined, handleDelete: canDelete ? handleDelete : undefined, enableClipboard: enableClipboard, type: collectionType, data: data, name: name, path: path, translate: translate }))] })), jsxs("div", Object.assign({ className: 'jer-collection-inner', style: {
|
|
749
|
-
maxHeight: collapsed ? 0 : !isEditing ? `${numOfLines *
|
|
750
|
-
overflowY: collapsed ? 'hidden' : 'visible',
|
|
770
|
+
maxHeight: collapsed ? 0 : !isEditing ? `${numOfLines * 3}em` : undefined,
|
|
771
|
+
overflowY: collapsed || isAnimating ? 'hidden' : 'visible',
|
|
751
772
|
transition: `max-height ${transitionTime}`,
|
|
752
|
-
} }, { children: [isEditing ? (jsx("div", Object.assign({ className: "jer-collection-text-edit" }, { children: jsxs("div", { children: [jsx(AutogrowTextArea, { className: "jer-collection-text-area", name: path.join('.'), value: stringifiedValue, setValue: setStringifiedValue, isEditing: isEditing, handleKeyPress: handleKeyPress }), jsx("div", Object.assign({ className: "jer-collection-input-button-row" }, { children: jsx(InputButtons, { onOk: handleEdit, onCancel: handleCancel, isCollection: true }) }))] }) }))) : (jsx(Fragment, { children:
|
|
773
|
+
} }, { children: [isEditing ? (jsx("div", Object.assign({ className: "jer-collection-text-edit" }, { children: jsxs("div", { children: [jsx(AutogrowTextArea, { className: "jer-collection-text-area", name: path.join('.'), value: stringifiedValue, setValue: setStringifiedValue, isEditing: isEditing, handleKeyPress: handleKeyPress }), jsx("div", Object.assign({ className: "jer-collection-input-button-row" }, { children: jsx(InputButtons, { onOk: handleEdit, onCancel: handleCancel, isCollection: true }) }))] }) }))) : (jsx(Fragment, { children: !hasBeenOpened.current
|
|
774
|
+
? null
|
|
775
|
+
: keyValueArray.map(([key, value]) => (jsx("div", Object.assign({ className: "jer-collection-element" }, { children: isCollection(value) ? (jsx(CollectionNode, Object.assign({ data: value, path: [...path, key], name: key }, props), key)) : (jsx(ValueNodeWrapper, Object.assign({ data: value, path: [...path, key], name: key }, props, { showArrayIndices: collectionType === 'object' ? true : showArrayIndices }), key)) }), key))) })), jsx("div", Object.assign({ className: isEditing ? 'jer-collection-error-row' : 'jer-collection-error-row-edit' }, { children: error && (jsx("span", Object.assign({ className: "jer-error-slug", style: styles.error }, { children: error }))) })), jsx("div", Object.assign({ className: "jer-brackets", style: styles.bracket }, { children: brackets.close }))] }))] })));
|
|
753
776
|
};
|
|
754
777
|
|
|
755
778
|
const localisedStrings = {
|
|
@@ -768,7 +791,7 @@ const translate = (translations, key, count) => {
|
|
|
768
791
|
};
|
|
769
792
|
const getTranslateFunction = (translations) => (key, count) => translate(translations, key, count);
|
|
770
793
|
|
|
771
|
-
const Editor = ({ data: srcData, rootName = 'root', onUpdate, onEdit: srcEdit = onUpdate, onDelete: srcDelete = onUpdate, onAdd: srcAdd = onUpdate, enableClipboard = true, theme = 'default', icons, indent = 4, collapse = false, restrictEdit = false, restrictDelete = false, restrictAdd = false, keySort = false, showArrayIndices = true, defaultValue = null, minWidth = 250, maxWidth =
|
|
794
|
+
const Editor = ({ data: srcData, rootName = 'root', onUpdate, onEdit: srcEdit = onUpdate, onDelete: srcDelete = onUpdate, onAdd: srcAdd = onUpdate, enableClipboard = true, theme = 'default', icons, indent = 4, collapse = false, restrictEdit = false, restrictDelete = false, restrictAdd = false, keySort = false, showArrayIndices = true, defaultValue = null, minWidth = 250, maxWidth = 'min(600px, 90vw)', stringTruncate = 250, translations = {}, className, }) => {
|
|
772
795
|
const [data, setData] = useState(srcData);
|
|
773
796
|
const { styles, setTheme, setIcons } = useTheme();
|
|
774
797
|
const collapseFilter = useCallback(getFilterFunction(collapse), [collapse]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-edit-react",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.6",
|
|
4
4
|
"description": "React component for editing or viewing JSON/object data",
|
|
5
5
|
"main": "build/index.cjs.js",
|
|
6
6
|
"module": "build/index.esm.js",
|
|
@@ -13,9 +13,11 @@
|
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"scripts": {
|
|
15
15
|
"setup": "yarn install && cd demo && yarn install",
|
|
16
|
-
"demo": "cd demo && yarn start",
|
|
16
|
+
"demo": "cd demo && node ./scripts/getVersion.js && yarn start",
|
|
17
17
|
"build": "rimraf ./build && rollup -c && rimraf ./build/dts",
|
|
18
|
-
"compile": "rimraf ./build && tsc"
|
|
18
|
+
"compile": "rimraf ./build && tsc",
|
|
19
|
+
"release": "yarn build && yarn publish",
|
|
20
|
+
"release-demo": "cd demo && yarn deploy"
|
|
19
21
|
},
|
|
20
22
|
"peerDependencies": {
|
|
21
23
|
"@types/react": "^18.2.6",
|