json-edit-react 0.9.4 → 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 +96 -31
- package/build/index.cjs.js +246 -67
- package/build/index.d.ts +47 -6
- package/build/index.esm.js +248 -66
- package/package.json +15 -13
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';
|
|
@@ -24,7 +24,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
24
24
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
25
25
|
PERFORMANCE OF THIS SOFTWARE.
|
|
26
26
|
***************************************************************************** */
|
|
27
|
-
/* global Reflect, Promise */
|
|
27
|
+
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
function __rest(s, e) {
|
|
@@ -47,11 +47,16 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
47
47
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
48
48
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
49
49
|
});
|
|
50
|
-
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
53
|
+
var e = new Error(message);
|
|
54
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
55
|
+
};
|
|
51
56
|
|
|
52
57
|
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
58
|
|
|
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.
|
|
59
|
+
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
60
|
n(css,{});
|
|
56
61
|
|
|
57
62
|
const defaultTheme$1 = {
|
|
@@ -310,7 +315,7 @@ const ThemeProvider = ({ children }) => {
|
|
|
310
315
|
const [styles, setStyles] = useState(emptyStyleObject);
|
|
311
316
|
const [icons, setIcons] = useState({});
|
|
312
317
|
const setTheme = (theme) => setStyles(compileStyles(theme));
|
|
313
|
-
return (jsx(ThemeProviderContext.Provider,
|
|
318
|
+
return (jsx(ThemeProviderContext.Provider, { value: { styles, setTheme, icons, setIcons }, children: children }));
|
|
314
319
|
};
|
|
315
320
|
const useTheme = () => useContext(ThemeProviderContext);
|
|
316
321
|
const compileStyles = (themeInput) => {
|
|
@@ -384,12 +389,13 @@ const defaultStyleProperties = {
|
|
|
384
389
|
const AutogrowTextArea = ({ className, name, value, setValue, handleKeyPress, }) => {
|
|
385
390
|
const { styles } = useTheme();
|
|
386
391
|
const dummyValue = value.slice(-1) === '\n' ? value + '.' : value;
|
|
387
|
-
return (jsxs("div",
|
|
392
|
+
return (jsxs("div", { style: { display: 'grid' }, children: [jsx("textarea", { style: Object.assign({ height: 'auto', gridArea: '1 / 1 / 2 / 2', overflowY: 'auto' }, styles.input), rows: 1, className: className, name: name, value: value, onChange: (e) => setValue(e.target.value), autoFocus: true, onFocus: (e) => {
|
|
388
393
|
if (value.length < 40)
|
|
389
394
|
e.target.select();
|
|
390
|
-
}, onKeyDown: handleKeyPress }), jsx("span",
|
|
395
|
+
}, onKeyDown: handleKeyPress }), jsx("span", { 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
396
|
};
|
|
392
397
|
|
|
398
|
+
const INVALID_FUNCTION_STRING = '**INVALID_FUNCTION**';
|
|
393
399
|
const truncate = (string, length = 200) => string.length < length ? string : `${string.slice(0, length - 2).trim()}...`;
|
|
394
400
|
const StringValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, stringTruncate, }) => {
|
|
395
401
|
const { styles } = useTheme();
|
|
@@ -400,10 +406,10 @@ const StringValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdi
|
|
|
400
406
|
handleCancel();
|
|
401
407
|
};
|
|
402
408
|
const breakString = (text) => text.split('\n').map((line, index, arr) => (jsxs("span", { children: [line, index < arr.length - 1 ? jsx("br", {}) : null] }, index)));
|
|
403
|
-
return isEditing ? (jsx(AutogrowTextArea, { className: "jer-input-text", name: path.join('.'), value: value, setValue: setValue, isEditing: isEditing, handleKeyPress: handleKeyPress })) : (jsxs("div",
|
|
409
|
+
return isEditing ? (jsx(AutogrowTextArea, { className: "jer-input-text", name: path.join('.'), value: value, setValue: setValue, isEditing: isEditing, handleKeyPress: handleKeyPress })) : (jsxs("div", { onDoubleClick: () => setIsEditing(true), onClick: (e) => {
|
|
404
410
|
if (e.getModifierState('Control') || e.getModifierState('Meta'))
|
|
405
411
|
setIsEditing(true);
|
|
406
|
-
}, className: "jer-value-string", style: styles.string
|
|
412
|
+
}, className: "jer-value-string", style: styles.string, children: ["\"", breakString(truncate(value, stringTruncate)), "\""] }));
|
|
407
413
|
};
|
|
408
414
|
const NumberValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, }) => {
|
|
409
415
|
const { styles } = useTheme();
|
|
@@ -416,24 +422,85 @@ const NumberValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdi
|
|
|
416
422
|
const validateNumber = (input) => {
|
|
417
423
|
return input.replace(/[^0-9.-]/g, '');
|
|
418
424
|
};
|
|
419
|
-
return isEditing ? (jsx("input", { className: "jer-input-number", type: "text", name: path.join('.'), value: value, onChange: (e) => setValue(validateNumber(e.target.value)), autoFocus: true, onFocus: (e) => e.target.select(), onKeyDown: handleKeyPress, style: { width: `${String(value).length / 1.5 + 2}em` } })) : (jsx("span",
|
|
425
|
+
return isEditing ? (jsx("input", { className: "jer-input-number", type: "text", name: path.join('.'), value: value, onChange: (e) => setValue(validateNumber(e.target.value)), autoFocus: true, onFocus: (e) => e.target.select(), onKeyDown: handleKeyPress, style: { width: `${String(value).length / 1.5 + 2}em` } })) : (jsx("span", { onDoubleClick: () => setIsEditing(true), className: "jer-value-number", style: styles.number, children: value }));
|
|
420
426
|
};
|
|
421
|
-
const BooleanValue = ({ value, setValue, isEditing, path, setIsEditing, }) => {
|
|
427
|
+
const BooleanValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, }) => {
|
|
422
428
|
const { styles } = useTheme();
|
|
423
|
-
|
|
429
|
+
useEffect(() => {
|
|
430
|
+
if (isEditing)
|
|
431
|
+
document.addEventListener('keydown', listenForSubmit);
|
|
432
|
+
return () => document.removeEventListener('keydown', listenForSubmit);
|
|
433
|
+
}, [isEditing]);
|
|
434
|
+
const listenForSubmit = (event) => {
|
|
435
|
+
if (event.key === 'Enter') {
|
|
436
|
+
handleEdit();
|
|
437
|
+
}
|
|
438
|
+
else if (event.key === 'Escape')
|
|
439
|
+
handleCancel();
|
|
440
|
+
};
|
|
441
|
+
return isEditing ? (jsx("input", { className: "jer-input-boolean", type: "checkbox", name: path.join('.'), checked: value, onChange: () => setValue(!value) })) : (jsx("span", { onDoubleClick: () => setIsEditing(true), className: "jer-value-boolean", style: styles.boolean, children: String(value) }));
|
|
424
442
|
};
|
|
425
|
-
const NullValue = ({ value, isEditing, setIsEditing }) => {
|
|
443
|
+
const NullValue = ({ value, isEditing, setIsEditing, handleEdit, handleCancel, }) => {
|
|
426
444
|
const { styles } = useTheme();
|
|
427
|
-
|
|
445
|
+
useEffect(() => {
|
|
446
|
+
if (isEditing)
|
|
447
|
+
document.addEventListener('keydown', listenForSubmit);
|
|
448
|
+
return () => document.removeEventListener('keydown', listenForSubmit);
|
|
449
|
+
}, [isEditing]);
|
|
450
|
+
const listenForSubmit = (event) => {
|
|
451
|
+
if (event.key === 'Enter') {
|
|
452
|
+
handleEdit();
|
|
453
|
+
}
|
|
454
|
+
else if (event.key === 'Escape')
|
|
455
|
+
handleCancel();
|
|
456
|
+
};
|
|
457
|
+
return isEditing ? (jsx("div", { className: "jer-input-null", children: "null" })) : (jsx("div", { onDoubleClick: () => setIsEditing(true), className: "jer-value-null", style: styles.null, children: String(value) }));
|
|
428
458
|
};
|
|
429
|
-
const ObjectValue = () => {
|
|
430
|
-
|
|
459
|
+
const ObjectValue = ({ value, translate, isEditing, handleEdit, handleCancel, }) => {
|
|
460
|
+
useEffect(() => {
|
|
461
|
+
if (isEditing)
|
|
462
|
+
document.addEventListener('keydown', listenForSubmit);
|
|
463
|
+
return () => document.removeEventListener('keydown', listenForSubmit);
|
|
464
|
+
}, []);
|
|
465
|
+
const listenForSubmit = (event) => {
|
|
466
|
+
if (event.key === 'Enter') {
|
|
467
|
+
handleEdit();
|
|
468
|
+
}
|
|
469
|
+
else if (event.key === 'Escape')
|
|
470
|
+
handleCancel();
|
|
471
|
+
};
|
|
472
|
+
return (jsx("span", { className: "jer-value-object", children: `{${translate('DEFAULT_NEW_KEY')}: "${value}" }` }));
|
|
431
473
|
};
|
|
432
|
-
const ArrayValue = ({ value }) => {
|
|
433
|
-
|
|
474
|
+
const ArrayValue = ({ value, isEditing, handleEdit, handleCancel, }) => {
|
|
475
|
+
useEffect(() => {
|
|
476
|
+
if (isEditing)
|
|
477
|
+
document.addEventListener('keydown', listenForSubmit);
|
|
478
|
+
return () => document.removeEventListener('keydown', listenForSubmit);
|
|
479
|
+
}, []);
|
|
480
|
+
const listenForSubmit = (event) => {
|
|
481
|
+
if (event.key === 'Enter') {
|
|
482
|
+
handleEdit();
|
|
483
|
+
}
|
|
484
|
+
else if (event.key === 'Escape')
|
|
485
|
+
handleCancel();
|
|
486
|
+
};
|
|
487
|
+
return jsx("span", { className: "jer-value-array", children: `[${value === null ? '' : value}]` });
|
|
434
488
|
};
|
|
435
|
-
const InvalidValue = () => {
|
|
436
|
-
|
|
489
|
+
const InvalidValue = ({ value }) => {
|
|
490
|
+
let message = 'Error!';
|
|
491
|
+
switch (typeof value) {
|
|
492
|
+
case 'string':
|
|
493
|
+
if (value === INVALID_FUNCTION_STRING)
|
|
494
|
+
message = 'Function';
|
|
495
|
+
break;
|
|
496
|
+
case 'undefined':
|
|
497
|
+
message = 'Undefined';
|
|
498
|
+
break;
|
|
499
|
+
case 'symbol':
|
|
500
|
+
message = 'Symbol';
|
|
501
|
+
break;
|
|
502
|
+
}
|
|
503
|
+
return jsx("span", { className: "jer-value-invalid", children: message });
|
|
437
504
|
};
|
|
438
505
|
|
|
439
506
|
const Icon = ({ name, rotate }) => {
|
|
@@ -454,7 +521,7 @@ const Icon = ({ name, rotate }) => {
|
|
|
454
521
|
case 'cancel':
|
|
455
522
|
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
523
|
case 'chevron':
|
|
457
|
-
return ((_g = icons === null || icons === void 0 ? void 0 : icons.chevron) !== null && _g !== void 0 ? _g : (jsx(FaChevronDown, { className:
|
|
524
|
+
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
525
|
default:
|
|
459
526
|
return jsx(Fragment, {});
|
|
460
527
|
}
|
|
@@ -478,38 +545,41 @@ const EditButtons = ({ startEdit, handleDelete, handleAdd, enableClipboard, type
|
|
|
478
545
|
setIsAdding(false);
|
|
479
546
|
};
|
|
480
547
|
const handleCopy = (e) => {
|
|
481
|
-
let
|
|
482
|
-
let value
|
|
548
|
+
let copyType = 'value';
|
|
549
|
+
let value;
|
|
550
|
+
let stringValue = '';
|
|
483
551
|
if (enableClipboard) {
|
|
484
552
|
switch (e.ctrlKey || e.metaKey) {
|
|
485
553
|
case true:
|
|
486
554
|
value = stringifyPath(path);
|
|
487
|
-
|
|
555
|
+
stringValue = value;
|
|
556
|
+
copyType = 'path';
|
|
488
557
|
break;
|
|
489
558
|
default:
|
|
490
|
-
value =
|
|
559
|
+
value = data;
|
|
560
|
+
stringValue = type ? JSON.stringify(data, null, 2) : String(value);
|
|
491
561
|
}
|
|
492
|
-
navigator.clipboard.writeText(
|
|
562
|
+
navigator.clipboard.writeText(stringValue);
|
|
493
563
|
}
|
|
494
564
|
if (typeof enableClipboard === 'function')
|
|
495
|
-
enableClipboard({ value, path, key: name, type });
|
|
565
|
+
enableClipboard({ value, stringValue, path, key: name, type: copyType });
|
|
496
566
|
};
|
|
497
|
-
return (jsxs("div",
|
|
567
|
+
return (jsxs("div", { className: "jer-edit-buttons", style: isAdding ? { opacity: 1 } : undefined, children: [enableClipboard && (jsx("div", { onClick: handleCopy, className: "jer-copy-pulse", children: jsx(Icon, { name: "copy" }) })), startEdit && (jsx("div", { onClick: startEdit, children: jsx(Icon, { name: "edit" }) })), handleDelete && (jsx("div", { onClick: handleDelete, children: jsx(Icon, { name: "delete" }) })), handleAdd && (jsx("div", { onClick: () => {
|
|
498
568
|
if (type === 'object')
|
|
499
569
|
setIsAdding(true);
|
|
500
570
|
else
|
|
501
571
|
handleAdd('');
|
|
502
|
-
}
|
|
572
|
+
}, children: jsx(Icon, { name: "add" }) })), isAdding && handleAdd && type === 'object' && (jsxs(Fragment, { children: [jsx("input", { className: "jer-input-new-key", type: "text", name: "new-object-key", value: newKey, onChange: (e) => setNewKey(e.target.value), autoFocus: true, onFocus: (e) => e.target.select(), onKeyDown: handleKeyPress, style: Object.assign({}, styles.input) }), jsx(InputButtons, { onOk: () => {
|
|
503
573
|
if (!!newKey) {
|
|
504
574
|
setIsAdding(false);
|
|
505
575
|
handleAdd(newKey);
|
|
506
576
|
}
|
|
507
577
|
}, onCancel: () => {
|
|
508
578
|
setIsAdding(false);
|
|
509
|
-
} })] }))] }))
|
|
579
|
+
} })] }))] }));
|
|
510
580
|
};
|
|
511
581
|
const InputButtons = ({ onOk, onCancel }) => {
|
|
512
|
-
return (jsxs("div",
|
|
582
|
+
return (jsxs("div", { className: "jer-confirm-buttons", children: [jsx("div", { onClick: onOk, children: jsx(Icon, { name: "ok" }) }), jsx("div", { onClick: onCancel, children: jsx(Icon, { name: "cancel" }) })] }));
|
|
513
583
|
};
|
|
514
584
|
const stringifyPath = (path) => path.reduce((str, part) => {
|
|
515
585
|
if (typeof part === 'number')
|
|
@@ -523,19 +593,43 @@ const ValueDataTypes = ['string', 'number', 'boolean', 'null'];
|
|
|
523
593
|
const CollectionDataTypes = ['object', 'array'];
|
|
524
594
|
const DataTypes = [...ValueDataTypes, ...CollectionDataTypes];
|
|
525
595
|
|
|
526
|
-
const
|
|
596
|
+
const getCustomNode = (customNodeDefinitions = [], filterProps) => {
|
|
597
|
+
const matchingDefinitions = customNodeDefinitions.filter(({ condition }) => condition(filterProps));
|
|
598
|
+
if (matchingDefinitions.length === 0)
|
|
599
|
+
return {};
|
|
600
|
+
const { element, props, hideKey = false } = matchingDefinitions[0];
|
|
601
|
+
return { CustomNode: element, customNodeProps: props, hideKey };
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
const CustomNodeWrapper = ({ name, hideKey, children, indent, }) => {
|
|
605
|
+
const { styles } = useTheme();
|
|
606
|
+
const indentStyle = indent ? { marginLeft: `${indent / 2}em` } : {};
|
|
607
|
+
return (jsx("div", { className: "jer-component jer-value-component", style: indentStyle, children: jsxs("div", { className: "jer-value-main-row", style: {
|
|
608
|
+
flexWrap: name.length > 10 ? 'wrap' : 'nowrap',
|
|
609
|
+
}, children: [!hideKey && (jsxs("label", { htmlFor: name, className: "jer-object-key", style: Object.assign(Object.assign({}, styles.property), { minWidth: `${Math.min(String(name).length + 1, 5)}ch`, flexShrink: name.length > 10 ? 1 : 0 }), children: [name, ":", ' '] })), jsx("div", { className: "jer-value-and-buttons", style: { paddingLeft: hideKey ? 0 : undefined }, children: children })] }) }));
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
const ValueNodeWrapper = (props) => {
|
|
613
|
+
const { data, parentData, name, path, onEdit, onDelete, enableClipboard, restrictEditFilter, restrictDeleteFilter, restrictTypeSelection, showLabel, stringTruncate, indent, translate, customNodeDefinitions, } = props;
|
|
527
614
|
const { styles } = useTheme();
|
|
528
615
|
const [isEditing, setIsEditing] = useState(false);
|
|
529
|
-
const [
|
|
616
|
+
const [isEditingKey, setIsEditingKey] = useState(false);
|
|
617
|
+
const [value, setValue] = useState(typeof data === 'function' ? INVALID_FUNCTION_STRING : data);
|
|
530
618
|
const [error, setError] = useState(null);
|
|
531
619
|
const [dataType, setDataType] = useState(getDataType(data));
|
|
532
620
|
useEffect(() => {
|
|
533
|
-
setValue(typeof data === 'function' ?
|
|
621
|
+
setValue(typeof data === 'function' ? INVALID_FUNCTION_STRING : data);
|
|
534
622
|
setDataType(getDataType(data));
|
|
535
623
|
}, [data, error]);
|
|
536
624
|
const handleChangeDataType = (type) => {
|
|
537
|
-
|
|
538
|
-
|
|
625
|
+
const customNode = customNodeDefinitions.find((customNode) => customNode.name === type);
|
|
626
|
+
if (customNode) {
|
|
627
|
+
onEdit(customNode.defaultValue, path);
|
|
628
|
+
}
|
|
629
|
+
else {
|
|
630
|
+
setValue(convertValue(value, type));
|
|
631
|
+
setDataType(type);
|
|
632
|
+
}
|
|
539
633
|
};
|
|
540
634
|
const logError = (errorString) => {
|
|
541
635
|
setError(errorString);
|
|
@@ -547,10 +641,10 @@ const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard,
|
|
|
547
641
|
let newValue;
|
|
548
642
|
switch (dataType) {
|
|
549
643
|
case 'object':
|
|
550
|
-
newValue = {};
|
|
644
|
+
newValue = { [translate('DEFAULT_NEW_KEY')]: value };
|
|
551
645
|
break;
|
|
552
646
|
case 'array':
|
|
553
|
-
newValue = value !== null ?
|
|
647
|
+
newValue = value !== null ? value : [];
|
|
554
648
|
break;
|
|
555
649
|
case 'number':
|
|
556
650
|
const n = Number(value);
|
|
@@ -567,9 +661,27 @@ const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard,
|
|
|
567
661
|
logError(error);
|
|
568
662
|
});
|
|
569
663
|
};
|
|
664
|
+
const handleEditKey = (newKey) => {
|
|
665
|
+
setIsEditingKey(false);
|
|
666
|
+
if (!parentData)
|
|
667
|
+
return;
|
|
668
|
+
const parentPath = path.slice(0, -1);
|
|
669
|
+
if (!newKey)
|
|
670
|
+
return;
|
|
671
|
+
const newData = Object.fromEntries(Object.entries(parentData).map(([key, val]) => (key === name ? [newKey, val] : [key, val])));
|
|
672
|
+
onEdit(newData, parentPath);
|
|
673
|
+
};
|
|
674
|
+
const handleKeyPress = (e) => {
|
|
675
|
+
if (e.key === 'Enter')
|
|
676
|
+
handleEditKey(e.target.value);
|
|
677
|
+
else if (e.key === 'Escape')
|
|
678
|
+
handleCancel();
|
|
679
|
+
};
|
|
570
680
|
const handleCancel = () => {
|
|
571
681
|
setIsEditing(false);
|
|
682
|
+
setIsEditingKey(false);
|
|
572
683
|
setValue(data);
|
|
684
|
+
setDataType(getDataType(data));
|
|
573
685
|
};
|
|
574
686
|
const handleDelete = () => {
|
|
575
687
|
onDelete(value, path).then((error) => {
|
|
@@ -580,20 +692,47 @@ const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard,
|
|
|
580
692
|
const filterProps = { key: name, path, level: path.length, value: data, size: null };
|
|
581
693
|
const canEdit = useMemo(() => !restrictEditFilter(filterProps), [filterProps]);
|
|
582
694
|
const canDelete = useMemo(() => !restrictDeleteFilter(filterProps), [filterProps]);
|
|
695
|
+
const isArray = typeof path.slice(-1)[0] === 'number';
|
|
696
|
+
const canEditKey = !isArray && canEdit && canDelete;
|
|
583
697
|
const inputProps = {
|
|
584
698
|
value,
|
|
699
|
+
parentData,
|
|
585
700
|
setValue,
|
|
586
701
|
isEditing,
|
|
587
|
-
setIsEditing,
|
|
702
|
+
setIsEditing: canEdit ? () => setIsEditing(true) : () => { },
|
|
588
703
|
handleEdit,
|
|
589
704
|
handleCancel,
|
|
590
705
|
path,
|
|
591
706
|
stringTruncate,
|
|
707
|
+
translate,
|
|
592
708
|
};
|
|
593
|
-
|
|
709
|
+
const { CustomNode, customNodeProps, hideKey } = getCustomNode(customNodeDefinitions, {
|
|
710
|
+
key: name,
|
|
711
|
+
path,
|
|
712
|
+
level: path.length,
|
|
713
|
+
value: data,
|
|
714
|
+
size: 0,
|
|
715
|
+
});
|
|
716
|
+
const allDataTypes = [
|
|
717
|
+
...customNodeDefinitions
|
|
718
|
+
.filter(({ showInTypesSelector = false }) => showInTypesSelector)
|
|
719
|
+
.map(({ name }) => name),
|
|
720
|
+
...DataTypes,
|
|
721
|
+
];
|
|
722
|
+
const allowedDataTypes = useMemo(() => {
|
|
723
|
+
if (typeof restrictTypeSelection === 'boolean')
|
|
724
|
+
return restrictTypeSelection ? [] : allDataTypes;
|
|
725
|
+
if (Array.isArray(restrictTypeSelection))
|
|
726
|
+
return restrictTypeSelection;
|
|
727
|
+
const result = restrictTypeSelection(filterProps);
|
|
728
|
+
if (typeof result === 'boolean')
|
|
729
|
+
return result ? [] : allDataTypes;
|
|
730
|
+
return result;
|
|
731
|
+
}, [filterProps, restrictTypeSelection]);
|
|
732
|
+
return CustomNode ? (jsx(CustomNodeWrapper, { name: name, hideKey: hideKey, indent: indent, children: jsx(CustomNode, Object.assign({ customProps: customNodeProps }, props)) })) : (jsx("div", { className: "jer-component jer-value-component", style: { marginLeft: `${indent / 2}em` }, children: jsxs("div", { className: "jer-value-main-row", style: {
|
|
594
733
|
flexWrap: name.length > 10 ? 'wrap' : 'nowrap',
|
|
595
|
-
}
|
|
596
|
-
!error && (jsx(EditButtons, { startEdit: canEdit ? () => setIsEditing(true) : undefined, handleDelete: canDelete ? handleDelete : undefined, data: data, enableClipboard: enableClipboard, name: name, path: path, translate: translate }))), isEditing && (jsxs("div",
|
|
734
|
+
}, children: [showLabel && !isEditingKey && (jsxs("label", { htmlFor: path.join('.'), className: "jer-object-key", style: Object.assign(Object.assign({}, styles.property), { minWidth: `${Math.min(String(name).length + 1, 5)}ch`, flexShrink: name.length > 10 ? 1 : 0 }), onDoubleClick: () => canEditKey && setIsEditingKey(true), children: [name, ":", ' '] })), showLabel && isEditingKey && (jsx("input", { className: "jer-object-key", type: "text", name: path.join('.'), defaultValue: name, autoFocus: true, onFocus: (e) => e.target.select(), onKeyDown: handleKeyPress, style: { width: `${String(name).length / 1.5 + 0.5}em` } })), jsxs("div", { className: "jer-value-and-buttons", children: [jsx("div", { className: "jer-input-component", children: getInputComponent(dataType, inputProps) }), isEditing ? (jsx(InputButtons, { onOk: handleEdit, onCancel: handleCancel })) : (dataType !== 'invalid' &&
|
|
735
|
+
!error && (jsx(EditButtons, { startEdit: canEdit ? () => setIsEditing(true) : undefined, handleDelete: canDelete ? handleDelete : undefined, data: data, enableClipboard: enableClipboard, name: name, path: path, translate: translate }))), isEditing && allowedDataTypes.length > 0 && (jsxs("div", { className: "jer-select", children: [jsx("select", { name: `${name}-type-select`, className: "jer-type-select", onChange: (e) => handleChangeDataType(e.target.value), value: dataType, children: allowedDataTypes.map((type) => (jsx("option", { value: type, children: type }, type))) }), jsx("span", { className: "focus" })] })), !isEditing && error && (jsx("span", { className: "jer-error-slug", style: styles.error, children: error }))] })] }) }));
|
|
597
736
|
};
|
|
598
737
|
const getDataType = (value) => {
|
|
599
738
|
if (typeof value === 'string')
|
|
@@ -618,7 +757,7 @@ const getInputComponent = (dataType, inputProps) => {
|
|
|
618
757
|
case 'null':
|
|
619
758
|
return jsx(NullValue, Object.assign({}, inputProps));
|
|
620
759
|
case 'object':
|
|
621
|
-
return jsx(ObjectValue, Object.assign({}, inputProps));
|
|
760
|
+
return jsx(ObjectValue, Object.assign({}, inputProps, { value: value }));
|
|
622
761
|
case 'array':
|
|
623
762
|
return jsx(ArrayValue, Object.assign({}, inputProps));
|
|
624
763
|
default:
|
|
@@ -637,7 +776,7 @@ const convertValue = (value, type) => {
|
|
|
637
776
|
case 'null':
|
|
638
777
|
return null;
|
|
639
778
|
case 'object':
|
|
640
|
-
return
|
|
779
|
+
return value;
|
|
641
780
|
case 'array':
|
|
642
781
|
return [value];
|
|
643
782
|
default:
|
|
@@ -647,15 +786,19 @@ const convertValue = (value, type) => {
|
|
|
647
786
|
|
|
648
787
|
const isCollection = (value) => value !== null && typeof value == 'object';
|
|
649
788
|
const CollectionNode = (_a) => {
|
|
650
|
-
var { data, path, name } = _a, props = __rest(_a, ["data", "path", "name"]);
|
|
789
|
+
var { data, path, name, parentData, showCollectionCount } = _a, props = __rest(_a, ["data", "path", "name", "parentData", "showCollectionCount"]);
|
|
651
790
|
const { styles } = useTheme();
|
|
652
|
-
const { onEdit, onAdd, onDelete, restrictEditFilter, restrictDeleteFilter, restrictAddFilter, collapseFilter, enableClipboard, indent, keySort, showArrayIndices, defaultValue, translate, } = props;
|
|
791
|
+
const { onEdit, onAdd, onDelete, restrictEditFilter, restrictDeleteFilter, restrictAddFilter, collapseFilter, enableClipboard, indent, keySort, showArrayIndices, defaultValue, translate, customNodeDefinitions, } = props;
|
|
653
792
|
const [isEditing, setIsEditing] = useState(false);
|
|
793
|
+
const [isEditingKey, setIsEditingKey] = useState(false);
|
|
654
794
|
const [stringifiedValue, setStringifiedValue] = useState(JSON.stringify(data, null, 2));
|
|
655
795
|
const [error, setError] = useState(null);
|
|
656
796
|
const collectionSize = Object.keys(data).length;
|
|
657
797
|
const filterProps = { key: name, path, level: path.length, value: data, size: collectionSize };
|
|
658
|
-
const
|
|
798
|
+
const startCollapsed = collapseFilter(filterProps);
|
|
799
|
+
const [collapsed, setCollapsed] = useState(startCollapsed);
|
|
800
|
+
const hasBeenOpened = useRef(!startCollapsed);
|
|
801
|
+
const [isAnimating, setIsAnimating] = useState(false);
|
|
659
802
|
useEffect(() => {
|
|
660
803
|
setStringifiedValue(JSON.stringify(data, null, 2));
|
|
661
804
|
}, [data]);
|
|
@@ -671,6 +814,14 @@ const CollectionNode = (_a) => {
|
|
|
671
814
|
else if (e.key === 'Escape')
|
|
672
815
|
handleCancel();
|
|
673
816
|
};
|
|
817
|
+
const handleCollapse = () => {
|
|
818
|
+
if (!isEditing) {
|
|
819
|
+
setIsAnimating(true);
|
|
820
|
+
hasBeenOpened.current = true;
|
|
821
|
+
setCollapsed(!collapsed);
|
|
822
|
+
setTimeout(() => setIsAnimating(false), 500);
|
|
823
|
+
}
|
|
824
|
+
};
|
|
674
825
|
const showError = (errorString) => {
|
|
675
826
|
setError(errorString);
|
|
676
827
|
setTimeout(() => setError(null), ERROR_DISPLAY_TIME);
|
|
@@ -693,6 +844,22 @@ const CollectionNode = (_a) => {
|
|
|
693
844
|
return;
|
|
694
845
|
}
|
|
695
846
|
};
|
|
847
|
+
const handleEditKey = (newKey) => {
|
|
848
|
+
setIsEditingKey(false);
|
|
849
|
+
if (!parentData)
|
|
850
|
+
return;
|
|
851
|
+
const parentPath = path.slice(0, -1);
|
|
852
|
+
if (!newKey)
|
|
853
|
+
return;
|
|
854
|
+
const newData = Object.fromEntries(Object.entries(parentData).map(([key, val]) => (key === name ? [newKey, val] : [key, val])));
|
|
855
|
+
onEdit(newData, parentPath);
|
|
856
|
+
};
|
|
857
|
+
const handleKeyPressKeyEdit = (e) => {
|
|
858
|
+
if (e.key === 'Enter')
|
|
859
|
+
handleEditKey(e.target.value);
|
|
860
|
+
else if (e.key === 'Escape')
|
|
861
|
+
handleCancel();
|
|
862
|
+
};
|
|
696
863
|
const handleAdd = (key) => {
|
|
697
864
|
setCollapsed(false);
|
|
698
865
|
if (collectionType === 'array') {
|
|
@@ -727,7 +894,10 @@ const CollectionNode = (_a) => {
|
|
|
727
894
|
const canEdit = useMemo(() => !restrictEditFilter(filterProps), [filterProps]);
|
|
728
895
|
const canDelete = useMemo(() => !restrictDeleteFilter(filterProps), [filterProps]);
|
|
729
896
|
const canAdd = useMemo(() => !restrictAddFilter(filterProps), [filterProps]);
|
|
730
|
-
const
|
|
897
|
+
const canEditKey = parentData !== null && canEdit && canAdd && canDelete;
|
|
898
|
+
const isArray = typeof path.slice(-1)[0] === 'number';
|
|
899
|
+
const showLabel = showArrayIndices || !isArray;
|
|
900
|
+
const showCount = showCollectionCount === 'when-closed' ? collapsed : showCollectionCount;
|
|
731
901
|
const keyValueArray = Object.entries(data).map(([key, value]) => [
|
|
732
902
|
collectionType === 'array' ? Number(key) : key,
|
|
733
903
|
value,
|
|
@@ -735,21 +905,27 @@ const CollectionNode = (_a) => {
|
|
|
735
905
|
if (keySort && collectionType === 'object')
|
|
736
906
|
keyValueArray.sort(typeof keySort === 'function' ? (a, b) => keySort(a[0], b[0]) : undefined);
|
|
737
907
|
const numOfLines = JSON.stringify(data, null, 2).split('\n').length;
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
908
|
+
const { CustomNode, customNodeProps, hideKey } = getCustomNode(customNodeDefinitions, {
|
|
909
|
+
key: name,
|
|
910
|
+
path,
|
|
911
|
+
level: path.length,
|
|
912
|
+
value: data,
|
|
913
|
+
size: Object.keys(data).length,
|
|
914
|
+
});
|
|
915
|
+
return (jsx("div", { className: "jer-component fb-collection-component", style: { marginLeft: `${path.length === 0 ? 0 : indent / 2}em` }, children: CustomNode ? (jsx(CustomNodeWrapper, { name: name, hideKey: hideKey, children: jsx(CustomNode, Object.assign({ data: data, path: path, name: name, parentData: parentData, customProps: customNodeProps }, props)) })) : (jsxs(Fragment, { children: [jsxs("div", { className: "jer-collection-header-row", children: [jsx("div", { onClick: handleCollapse, children: jsx(Icon, { name: "chevron", rotate: collapsed }) }), jsxs("div", { className: "jer-collection-name", children: [!isEditingKey && (jsx("span", { style: styles.property, onDoubleClick: () => canEditKey && setIsEditingKey(true), children: showLabel && name !== '' && name !== undefined ? `${name}:` : null })), isEditingKey && (jsx("input", { className: "jer-collection-name", type: "text", name: path.join('.'), defaultValue: name, autoFocus: true, onFocus: (e) => e.target.select(), onKeyDown: handleKeyPressKeyEdit, style: { width: `${String(name).length / 1.5 + 0.5}em` } })), !isEditing && (jsx("span", { className: "jer-brackets", style: styles.bracket, children: brackets.open }))] }), !isEditing && showCollectionCount && (jsx("div", { className: `jer-collection-item-count${showCount ? ' jer-visible' : ' jer-hidden'}`, style: styles.itemCount, children: collectionSize === 1
|
|
916
|
+
? translate('ITEM_SINGLE', 1)
|
|
917
|
+
: translate('ITEMS_MULTIPLE', collectionSize) })), jsx("div", { className: `jer-brackets${collapsed ? ' jer-visible' : ' jer-hidden'}`, style: styles.bracket, children: brackets.close }), !isEditing && (jsx(EditButtons, { startEdit: canEdit
|
|
918
|
+
? () => {
|
|
919
|
+
setIsEditing(true);
|
|
920
|
+
setCollapsed(false);
|
|
921
|
+
}
|
|
922
|
+
: undefined, handleAdd: canAdd ? handleAdd : undefined, handleDelete: canDelete ? handleDelete : undefined, enableClipboard: enableClipboard, type: collectionType, data: data, name: name, path: path, translate: translate }))] }), jsxs("div", { className: 'jer-collection-inner', style: {
|
|
923
|
+
maxHeight: collapsed ? 0 : !isEditing ? `${numOfLines * 3}em` : undefined,
|
|
924
|
+
overflowY: collapsed || isAnimating ? 'hidden' : 'visible',
|
|
925
|
+
transition: `max-height ${transitionTime}`,
|
|
926
|
+
}, children: [isEditing ? (jsx("div", { 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", { className: "jer-collection-input-button-row", children: jsx(InputButtons, { onOk: handleEdit, onCancel: handleCancel, isCollection: true }) })] }) })) : (jsx(Fragment, { children: !hasBeenOpened.current
|
|
927
|
+
? null
|
|
928
|
+
: keyValueArray.map(([key, value]) => (jsx("div", { className: "jer-collection-element", children: isCollection(value) ? (jsx(CollectionNode, Object.assign({ data: value, parentData: data, path: [...path, key], name: key, showCollectionCount: showCollectionCount }, props), key)) : (jsx(ValueNodeWrapper, Object.assign({ data: value, parentData: data, path: [...path, key], name: key }, props, { showLabel: collectionType === 'object' ? true : showArrayIndices }), key)) }, key))) })), jsx("div", { className: isEditing ? 'jer-collection-error-row' : 'jer-collection-error-row-edit', children: error && (jsx("span", { className: "jer-error-slug", style: styles.error, children: error })) }), jsx("div", { className: "jer-brackets", style: styles.bracket, children: brackets.close })] })] })) }));
|
|
753
929
|
};
|
|
754
930
|
|
|
755
931
|
const localisedStrings = {
|
|
@@ -761,6 +937,8 @@ const localisedStrings = {
|
|
|
761
937
|
ERROR_UPDATE: 'Update unsuccessful',
|
|
762
938
|
ERROR_DELETE: 'Delete unsuccessful',
|
|
763
939
|
ERROR_ADD: 'Adding node unsuccessful',
|
|
940
|
+
DEFAULT_STRING: 'New data!',
|
|
941
|
+
DEFAULT_NEW_KEY: 'key',
|
|
764
942
|
};
|
|
765
943
|
const translate = (translations, key, count) => {
|
|
766
944
|
const string = key in translations ? translations[key] : localisedStrings[key];
|
|
@@ -768,7 +946,7 @@ const translate = (translations, key, count) => {
|
|
|
768
946
|
};
|
|
769
947
|
const getTranslateFunction = (translations) => (key, count) => translate(translations, key, count);
|
|
770
948
|
|
|
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 =
|
|
949
|
+
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, showCollectionCount = true, restrictEdit = false, restrictDelete = false, restrictAdd = false, restrictTypeSelection = false, keySort = false, showArrayIndices = true, defaultValue = null, minWidth = 250, maxWidth = 'min(600px, 90vw)', stringTruncate = 250, translations = {}, className, customNodeDefinitions = [], }) => {
|
|
772
950
|
const [data, setData] = useState(srcData);
|
|
773
951
|
const { styles, setTheme, setIcons } = useTheme();
|
|
774
952
|
const collapseFilter = useCallback(getFilterFunction(collapse), [collapse]);
|
|
@@ -850,10 +1028,12 @@ const Editor = ({ data: srcData, rootName = 'root', onUpdate, onEdit: srcEdit =
|
|
|
850
1028
|
onEdit,
|
|
851
1029
|
onDelete,
|
|
852
1030
|
onAdd,
|
|
1031
|
+
showCollectionCount,
|
|
853
1032
|
collapseFilter,
|
|
854
1033
|
restrictEditFilter,
|
|
855
1034
|
restrictDeleteFilter,
|
|
856
1035
|
restrictAddFilter,
|
|
1036
|
+
restrictTypeSelection,
|
|
857
1037
|
enableClipboard,
|
|
858
1038
|
keySort,
|
|
859
1039
|
showArrayIndices,
|
|
@@ -861,10 +1041,12 @@ const Editor = ({ data: srcData, rootName = 'root', onUpdate, onEdit: srcEdit =
|
|
|
861
1041
|
defaultValue,
|
|
862
1042
|
stringTruncate,
|
|
863
1043
|
translate,
|
|
1044
|
+
customNodeDefinitions,
|
|
1045
|
+
parentData: null,
|
|
864
1046
|
};
|
|
865
1047
|
if (!styles)
|
|
866
1048
|
return null;
|
|
867
|
-
return (jsx("div",
|
|
1049
|
+
return (jsx("div", { className: 'jer-editor-container ' + className, style: Object.assign(Object.assign({}, styles.container), { minWidth, maxWidth }), children: isCollection(data) ? (jsx(CollectionNode, Object.assign({ data: data, path: [] }, otherProps))) : (jsx(ValueNodeWrapper, Object.assign({ data: data, path: [], showLabel: true }, otherProps))) }));
|
|
868
1050
|
};
|
|
869
1051
|
const JsonEditor = (props) => (jsx(ThemeProvider, { children: jsx(Editor, Object.assign({}, props)) }));
|
|
870
1052
|
const updateDataObject = (data, path, newValue, action) => {
|
|
@@ -893,4 +1075,4 @@ const getFilterFunction = (propValue) => {
|
|
|
893
1075
|
return propValue;
|
|
894
1076
|
};
|
|
895
1077
|
|
|
896
|
-
export { JsonEditor,
|
|
1078
|
+
export { JsonEditor, themes };
|