json-edit-react 0.9.6 → 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.
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var jsxRuntime = require('react/jsx-runtime');
6
4
  var react = require('react');
7
5
  var assign = require('object-property-assigner');
@@ -28,7 +26,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
28
26
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29
27
  PERFORMANCE OF THIS SOFTWARE.
30
28
  ***************************************************************************** */
31
- /* global Reflect, Promise */
29
+ /* global Reflect, Promise, SuppressedError, Symbol */
32
30
 
33
31
 
34
32
  function __rest(s, e) {
@@ -51,7 +49,12 @@ function __awaiter(thisArg, _arguments, P, generator) {
51
49
  function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
52
50
  step((generator = generator.apply(thisArg, _arguments || [])).next());
53
51
  });
54
- }
52
+ }
53
+
54
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
55
+ var e = new Error(message);
56
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
57
+ };
55
58
 
56
59
  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
60
 
@@ -314,7 +317,7 @@ const ThemeProvider = ({ children }) => {
314
317
  const [styles, setStyles] = react.useState(emptyStyleObject);
315
318
  const [icons, setIcons] = react.useState({});
316
319
  const setTheme = (theme) => setStyles(compileStyles(theme));
317
- return (jsxRuntime.jsx(ThemeProviderContext.Provider, Object.assign({ value: { styles, setTheme, icons, setIcons } }, { children: children })));
320
+ return (jsxRuntime.jsx(ThemeProviderContext.Provider, { value: { styles, setTheme, icons, setIcons }, children: children }));
318
321
  };
319
322
  const useTheme = () => react.useContext(ThemeProviderContext);
320
323
  const compileStyles = (themeInput) => {
@@ -388,10 +391,10 @@ const defaultStyleProperties = {
388
391
  const AutogrowTextArea = ({ className, name, value, setValue, handleKeyPress, }) => {
389
392
  const { styles } = useTheme();
390
393
  const dummyValue = value.slice(-1) === '\n' ? value + '.' : value;
391
- return (jsxRuntime.jsxs("div", Object.assign({ style: { display: 'grid' } }, { children: [jsxRuntime.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) => {
394
+ return (jsxRuntime.jsxs("div", { style: { display: 'grid' }, children: [jsxRuntime.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) => {
392
395
  if (value.length < 40)
393
396
  e.target.select();
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 }))] })));
397
+ }, onKeyDown: handleKeyPress }), jsxRuntime.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 })] }));
395
398
  };
396
399
 
397
400
  const INVALID_FUNCTION_STRING = '**INVALID_FUNCTION**';
@@ -405,10 +408,10 @@ const StringValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdi
405
408
  handleCancel();
406
409
  };
407
410
  const breakString = (text) => text.split('\n').map((line, index, arr) => (jsxRuntime.jsxs("span", { children: [line, index < arr.length - 1 ? jsxRuntime.jsx("br", {}) : null] }, index)));
408
- return isEditing ? (jsxRuntime.jsx(AutogrowTextArea, { className: "jer-input-text", name: path.join('.'), value: value, setValue: setValue, isEditing: isEditing, handleKeyPress: handleKeyPress })) : (jsxRuntime.jsxs("div", Object.assign({ onDoubleClick: () => setIsEditing(true), onClick: (e) => {
411
+ return isEditing ? (jsxRuntime.jsx(AutogrowTextArea, { className: "jer-input-text", name: path.join('.'), value: value, setValue: setValue, isEditing: isEditing, handleKeyPress: handleKeyPress })) : (jsxRuntime.jsxs("div", { onDoubleClick: () => setIsEditing(true), onClick: (e) => {
409
412
  if (e.getModifierState('Control') || e.getModifierState('Meta'))
410
413
  setIsEditing(true);
411
- }, className: "jer-value-string", style: styles.string }, { children: ["\"", breakString(truncate(value, stringTruncate)), "\""] })));
414
+ }, className: "jer-value-string", style: styles.string, children: ["\"", breakString(truncate(value, stringTruncate)), "\""] }));
412
415
  };
413
416
  const NumberValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, }) => {
414
417
  const { styles } = useTheme();
@@ -421,18 +424,70 @@ const NumberValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdi
421
424
  const validateNumber = (input) => {
422
425
  return input.replace(/[^0-9.-]/g, '');
423
426
  };
424
- return isEditing ? (jsxRuntime.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` } })) : (jsxRuntime.jsx("span", Object.assign({ onDoubleClick: () => setIsEditing(true), className: "jer-value-number", style: styles.number }, { children: value })));
427
+ return isEditing ? (jsxRuntime.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` } })) : (jsxRuntime.jsx("span", { onDoubleClick: () => setIsEditing(true), className: "jer-value-number", style: styles.number, children: value }));
425
428
  };
426
- const BooleanValue = ({ value, setValue, isEditing, path, setIsEditing, }) => {
429
+ const BooleanValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, }) => {
427
430
  const { styles } = useTheme();
428
- return isEditing ? (jsxRuntime.jsx("input", { className: "jer-input-boolean", type: "checkbox", name: path.join('.'), checked: value, onChange: () => setValue(!value) })) : (jsxRuntime.jsx("span", Object.assign({ onDoubleClick: () => setIsEditing(true), className: "jer-value-boolean", style: styles.boolean }, { children: String(value) })));
431
+ react.useEffect(() => {
432
+ if (isEditing)
433
+ document.addEventListener('keydown', listenForSubmit);
434
+ return () => document.removeEventListener('keydown', listenForSubmit);
435
+ }, [isEditing]);
436
+ const listenForSubmit = (event) => {
437
+ if (event.key === 'Enter') {
438
+ handleEdit();
439
+ }
440
+ else if (event.key === 'Escape')
441
+ handleCancel();
442
+ };
443
+ return isEditing ? (jsxRuntime.jsx("input", { className: "jer-input-boolean", type: "checkbox", name: path.join('.'), checked: value, onChange: () => setValue(!value) })) : (jsxRuntime.jsx("span", { onDoubleClick: () => setIsEditing(true), className: "jer-value-boolean", style: styles.boolean, children: String(value) }));
429
444
  };
430
- const NullValue = ({ value, isEditing, setIsEditing }) => {
445
+ const NullValue = ({ value, isEditing, setIsEditing, handleEdit, handleCancel, }) => {
431
446
  const { styles } = useTheme();
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) })));
447
+ react.useEffect(() => {
448
+ if (isEditing)
449
+ document.addEventListener('keydown', listenForSubmit);
450
+ return () => document.removeEventListener('keydown', listenForSubmit);
451
+ }, [isEditing]);
452
+ const listenForSubmit = (event) => {
453
+ if (event.key === 'Enter') {
454
+ handleEdit();
455
+ }
456
+ else if (event.key === 'Escape')
457
+ handleCancel();
458
+ };
459
+ return isEditing ? (jsxRuntime.jsx("div", { className: "jer-input-null", children: "null" })) : (jsxRuntime.jsx("div", { onDoubleClick: () => setIsEditing(true), className: "jer-value-null", style: styles.null, children: String(value) }));
460
+ };
461
+ const ObjectValue = ({ value, translate, isEditing, handleEdit, handleCancel, }) => {
462
+ react.useEffect(() => {
463
+ if (isEditing)
464
+ document.addEventListener('keydown', listenForSubmit);
465
+ return () => document.removeEventListener('keydown', listenForSubmit);
466
+ }, []);
467
+ const listenForSubmit = (event) => {
468
+ if (event.key === 'Enter') {
469
+ handleEdit();
470
+ }
471
+ else if (event.key === 'Escape')
472
+ handleCancel();
473
+ };
474
+ return (jsxRuntime.jsx("span", { className: "jer-value-object", children: `{${translate('DEFAULT_NEW_KEY')}: "${value}" }` }));
475
+ };
476
+ const ArrayValue = ({ value, isEditing, handleEdit, handleCancel, }) => {
477
+ react.useEffect(() => {
478
+ if (isEditing)
479
+ document.addEventListener('keydown', listenForSubmit);
480
+ return () => document.removeEventListener('keydown', listenForSubmit);
481
+ }, []);
482
+ const listenForSubmit = (event) => {
483
+ if (event.key === 'Enter') {
484
+ handleEdit();
485
+ }
486
+ else if (event.key === 'Escape')
487
+ handleCancel();
488
+ };
489
+ return jsxRuntime.jsx("span", { className: "jer-value-array", children: `[${value === null ? '' : value}]` });
433
490
  };
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
491
  const InvalidValue = ({ value }) => {
437
492
  let message = 'Error!';
438
493
  switch (typeof value) {
@@ -447,7 +502,7 @@ const InvalidValue = ({ value }) => {
447
502
  message = 'Symbol';
448
503
  break;
449
504
  }
450
- return jsxRuntime.jsx("span", Object.assign({ className: "jer-value-invalid" }, { children: message }));
505
+ return jsxRuntime.jsx("span", { className: "jer-value-invalid", children: message });
451
506
  };
452
507
 
453
508
  const Icon = ({ name, rotate }) => {
@@ -511,22 +566,22 @@ const EditButtons = ({ startEdit, handleDelete, handleAdd, enableClipboard, type
511
566
  if (typeof enableClipboard === 'function')
512
567
  enableClipboard({ value, stringValue, path, key: name, type: copyType });
513
568
  };
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: () => {
569
+ return (jsxRuntime.jsxs("div", { className: "jer-edit-buttons", style: isAdding ? { opacity: 1 } : undefined, children: [enableClipboard && (jsxRuntime.jsx("div", { onClick: handleCopy, className: "jer-copy-pulse", children: jsxRuntime.jsx(Icon, { name: "copy" }) })), startEdit && (jsxRuntime.jsx("div", { onClick: startEdit, children: jsxRuntime.jsx(Icon, { name: "edit" }) })), handleDelete && (jsxRuntime.jsx("div", { onClick: handleDelete, children: jsxRuntime.jsx(Icon, { name: "delete" }) })), handleAdd && (jsxRuntime.jsx("div", { onClick: () => {
515
570
  if (type === 'object')
516
571
  setIsAdding(true);
517
572
  else
518
573
  handleAdd('');
519
- } }, { children: jsxRuntime.jsx(Icon, { name: "add" }) }))), isAdding && handleAdd && type === 'object' && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.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) }), jsxRuntime.jsx(InputButtons, { onOk: () => {
574
+ }, children: jsxRuntime.jsx(Icon, { name: "add" }) })), isAdding && handleAdd && type === 'object' && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.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) }), jsxRuntime.jsx(InputButtons, { onOk: () => {
520
575
  if (!!newKey) {
521
576
  setIsAdding(false);
522
577
  handleAdd(newKey);
523
578
  }
524
579
  }, onCancel: () => {
525
580
  setIsAdding(false);
526
- } })] }))] })));
581
+ } })] }))] }));
527
582
  };
528
583
  const InputButtons = ({ onOk, onCancel }) => {
529
- return (jsxRuntime.jsxs("div", Object.assign({ className: "jer-confirm-buttons" }, { children: [jsxRuntime.jsx("div", Object.assign({ onClick: onOk }, { children: jsxRuntime.jsx(Icon, { name: "ok" }) })), jsxRuntime.jsx("div", Object.assign({ onClick: onCancel }, { children: jsxRuntime.jsx(Icon, { name: "cancel" }) }))] })));
584
+ return (jsxRuntime.jsxs("div", { className: "jer-confirm-buttons", children: [jsxRuntime.jsx("div", { onClick: onOk, children: jsxRuntime.jsx(Icon, { name: "ok" }) }), jsxRuntime.jsx("div", { onClick: onCancel, children: jsxRuntime.jsx(Icon, { name: "cancel" }) })] }));
530
585
  };
531
586
  const stringifyPath = (path) => path.reduce((str, part) => {
532
587
  if (typeof part === 'number')
@@ -540,9 +595,27 @@ const ValueDataTypes = ['string', 'number', 'boolean', 'null'];
540
595
  const CollectionDataTypes = ['object', 'array'];
541
596
  const DataTypes = [...ValueDataTypes, ...CollectionDataTypes];
542
597
 
543
- const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard, restrictEditFilter, restrictDeleteFilter, showArrayIndices, stringTruncate, indent, translate, }) => {
598
+ const getCustomNode = (customNodeDefinitions = [], filterProps) => {
599
+ const matchingDefinitions = customNodeDefinitions.filter(({ condition }) => condition(filterProps));
600
+ if (matchingDefinitions.length === 0)
601
+ return {};
602
+ const { element, props, hideKey = false } = matchingDefinitions[0];
603
+ return { CustomNode: element, customNodeProps: props, hideKey };
604
+ };
605
+
606
+ const CustomNodeWrapper = ({ name, hideKey, children, indent, }) => {
607
+ const { styles } = useTheme();
608
+ const indentStyle = indent ? { marginLeft: `${indent / 2}em` } : {};
609
+ return (jsxRuntime.jsx("div", { className: "jer-component jer-value-component", style: indentStyle, children: jsxRuntime.jsxs("div", { className: "jer-value-main-row", style: {
610
+ flexWrap: name.length > 10 ? 'wrap' : 'nowrap',
611
+ }, children: [!hideKey && (jsxRuntime.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, ":", ' '] })), jsxRuntime.jsx("div", { className: "jer-value-and-buttons", style: { paddingLeft: hideKey ? 0 : undefined }, children: children })] }) }));
612
+ };
613
+
614
+ const ValueNodeWrapper = (props) => {
615
+ const { data, parentData, name, path, onEdit, onDelete, enableClipboard, restrictEditFilter, restrictDeleteFilter, restrictTypeSelection, showLabel, stringTruncate, indent, translate, customNodeDefinitions, } = props;
544
616
  const { styles } = useTheme();
545
617
  const [isEditing, setIsEditing] = react.useState(false);
618
+ const [isEditingKey, setIsEditingKey] = react.useState(false);
546
619
  const [value, setValue] = react.useState(typeof data === 'function' ? INVALID_FUNCTION_STRING : data);
547
620
  const [error, setError] = react.useState(null);
548
621
  const [dataType, setDataType] = react.useState(getDataType(data));
@@ -551,8 +624,14 @@ const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard,
551
624
  setDataType(getDataType(data));
552
625
  }, [data, error]);
553
626
  const handleChangeDataType = (type) => {
554
- setValue(convertValue(value, type));
555
- setDataType(type);
627
+ const customNode = customNodeDefinitions.find((customNode) => customNode.name === type);
628
+ if (customNode) {
629
+ onEdit(customNode.defaultValue, path);
630
+ }
631
+ else {
632
+ setValue(convertValue(value, type));
633
+ setDataType(type);
634
+ }
556
635
  };
557
636
  const logError = (errorString) => {
558
637
  setError(errorString);
@@ -564,10 +643,10 @@ const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard,
564
643
  let newValue;
565
644
  switch (dataType) {
566
645
  case 'object':
567
- newValue = {};
646
+ newValue = { [translate('DEFAULT_NEW_KEY')]: value };
568
647
  break;
569
648
  case 'array':
570
- newValue = value !== null ? [value] : [];
649
+ newValue = value !== null ? value : [];
571
650
  break;
572
651
  case 'number':
573
652
  const n = Number(value);
@@ -584,9 +663,27 @@ const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard,
584
663
  logError(error);
585
664
  });
586
665
  };
666
+ const handleEditKey = (newKey) => {
667
+ setIsEditingKey(false);
668
+ if (!parentData)
669
+ return;
670
+ const parentPath = path.slice(0, -1);
671
+ if (!newKey)
672
+ return;
673
+ const newData = Object.fromEntries(Object.entries(parentData).map(([key, val]) => (key === name ? [newKey, val] : [key, val])));
674
+ onEdit(newData, parentPath);
675
+ };
676
+ const handleKeyPress = (e) => {
677
+ if (e.key === 'Enter')
678
+ handleEditKey(e.target.value);
679
+ else if (e.key === 'Escape')
680
+ handleCancel();
681
+ };
587
682
  const handleCancel = () => {
588
683
  setIsEditing(false);
684
+ setIsEditingKey(false);
589
685
  setValue(data);
686
+ setDataType(getDataType(data));
590
687
  };
591
688
  const handleDelete = () => {
592
689
  onDelete(value, path).then((error) => {
@@ -597,8 +694,11 @@ const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard,
597
694
  const filterProps = { key: name, path, level: path.length, value: data, size: null };
598
695
  const canEdit = react.useMemo(() => !restrictEditFilter(filterProps), [filterProps]);
599
696
  const canDelete = react.useMemo(() => !restrictDeleteFilter(filterProps), [filterProps]);
697
+ const isArray = typeof path.slice(-1)[0] === 'number';
698
+ const canEditKey = !isArray && canEdit && canDelete;
600
699
  const inputProps = {
601
700
  value,
701
+ parentData,
602
702
  setValue,
603
703
  isEditing,
604
704
  setIsEditing: canEdit ? () => setIsEditing(true) : () => { },
@@ -606,11 +706,35 @@ const ValueNodeWrapper = ({ data, name, path, onEdit, onDelete, enableClipboard,
606
706
  handleCancel,
607
707
  path,
608
708
  stringTruncate,
709
+ translate,
609
710
  };
610
- return (jsxRuntime.jsx("div", Object.assign({ className: "jer-component jer-value-component", style: { marginLeft: `${indent / 2}em` } }, { children: jsxRuntime.jsxs("div", Object.assign({ className: "jer-value-main-row", style: {
711
+ const { CustomNode, customNodeProps, hideKey } = getCustomNode(customNodeDefinitions, {
712
+ key: name,
713
+ path,
714
+ level: path.length,
715
+ value: data,
716
+ size: 0,
717
+ });
718
+ const allDataTypes = [
719
+ ...customNodeDefinitions
720
+ .filter(({ showInTypesSelector = false }) => showInTypesSelector)
721
+ .map(({ name }) => name),
722
+ ...DataTypes,
723
+ ];
724
+ const allowedDataTypes = react.useMemo(() => {
725
+ if (typeof restrictTypeSelection === 'boolean')
726
+ return restrictTypeSelection ? [] : allDataTypes;
727
+ if (Array.isArray(restrictTypeSelection))
728
+ return restrictTypeSelection;
729
+ const result = restrictTypeSelection(filterProps);
730
+ if (typeof result === 'boolean')
731
+ return result ? [] : allDataTypes;
732
+ return result;
733
+ }, [filterProps, restrictTypeSelection]);
734
+ return CustomNode ? (jsxRuntime.jsx(CustomNodeWrapper, { name: name, hideKey: hideKey, indent: indent, children: jsxRuntime.jsx(CustomNode, Object.assign({ customProps: customNodeProps }, props)) })) : (jsxRuntime.jsx("div", { className: "jer-component jer-value-component", style: { marginLeft: `${indent / 2}em` }, children: jsxRuntime.jsxs("div", { className: "jer-value-main-row", style: {
611
735
  flexWrap: name.length > 10 ? 'wrap' : 'nowrap',
612
- } }, { children: [showArrayIndices && (jsxRuntime.jsxs("label", Object.assign({ 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 }) }, { children: [name, ":", ' '] }))), jsxRuntime.jsxs("div", Object.assign({ className: "jer-value-and-buttons" }, { children: [jsxRuntime.jsx("div", Object.assign({ className: "jer-input-component" }, { children: getInputComponent(dataType, inputProps) })), isEditing ? (jsxRuntime.jsx(InputButtons, { onOk: handleEdit, onCancel: handleCancel })) : (dataType !== 'invalid' &&
613
- !error && (jsxRuntime.jsx(EditButtons, { startEdit: canEdit ? () => setIsEditing(true) : undefined, handleDelete: canDelete ? handleDelete : undefined, data: data, enableClipboard: enableClipboard, name: name, path: path, translate: translate }))), isEditing && (jsxRuntime.jsxs("div", Object.assign({ className: "jer-select" }, { children: [jsxRuntime.jsx("select", Object.assign({ name: `${name}-type-select`, className: "jer-type-select", onChange: (e) => handleChangeDataType(e.target.value), value: dataType }, { children: DataTypes.map((type) => (jsxRuntime.jsx("option", Object.assign({ value: type }, { children: type }), type))) })), jsxRuntime.jsx("span", { className: "focus" })] }))), !isEditing && error && (jsxRuntime.jsx("span", Object.assign({ className: "jer-error-slug", style: styles.error }, { children: error })))] }))] })) })));
736
+ }, children: [showLabel && !isEditingKey && (jsxRuntime.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 && (jsxRuntime.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` } })), jsxRuntime.jsxs("div", { className: "jer-value-and-buttons", children: [jsxRuntime.jsx("div", { className: "jer-input-component", children: getInputComponent(dataType, inputProps) }), isEditing ? (jsxRuntime.jsx(InputButtons, { onOk: handleEdit, onCancel: handleCancel })) : (dataType !== 'invalid' &&
737
+ !error && (jsxRuntime.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 && (jsxRuntime.jsxs("div", { className: "jer-select", children: [jsxRuntime.jsx("select", { name: `${name}-type-select`, className: "jer-type-select", onChange: (e) => handleChangeDataType(e.target.value), value: dataType, children: allowedDataTypes.map((type) => (jsxRuntime.jsx("option", { value: type, children: type }, type))) }), jsxRuntime.jsx("span", { className: "focus" })] })), !isEditing && error && (jsxRuntime.jsx("span", { className: "jer-error-slug", style: styles.error, children: error }))] })] }) }));
614
738
  };
615
739
  const getDataType = (value) => {
616
740
  if (typeof value === 'string')
@@ -635,7 +759,7 @@ const getInputComponent = (dataType, inputProps) => {
635
759
  case 'null':
636
760
  return jsxRuntime.jsx(NullValue, Object.assign({}, inputProps));
637
761
  case 'object':
638
- return jsxRuntime.jsx(ObjectValue, Object.assign({}, inputProps));
762
+ return jsxRuntime.jsx(ObjectValue, Object.assign({}, inputProps, { value: value }));
639
763
  case 'array':
640
764
  return jsxRuntime.jsx(ArrayValue, Object.assign({}, inputProps));
641
765
  default:
@@ -654,7 +778,7 @@ const convertValue = (value, type) => {
654
778
  case 'null':
655
779
  return null;
656
780
  case 'object':
657
- return {};
781
+ return value;
658
782
  case 'array':
659
783
  return [value];
660
784
  default:
@@ -664,10 +788,11 @@ const convertValue = (value, type) => {
664
788
 
665
789
  const isCollection = (value) => value !== null && typeof value == 'object';
666
790
  const CollectionNode = (_a) => {
667
- var { data, path, name } = _a, props = __rest(_a, ["data", "path", "name"]);
791
+ var { data, path, name, parentData, showCollectionCount } = _a, props = __rest(_a, ["data", "path", "name", "parentData", "showCollectionCount"]);
668
792
  const { styles } = useTheme();
669
- const { onEdit, onAdd, onDelete, restrictEditFilter, restrictDeleteFilter, restrictAddFilter, collapseFilter, enableClipboard, indent, keySort, showArrayIndices, defaultValue, translate, } = props;
793
+ const { onEdit, onAdd, onDelete, restrictEditFilter, restrictDeleteFilter, restrictAddFilter, collapseFilter, enableClipboard, indent, keySort, showArrayIndices, defaultValue, translate, customNodeDefinitions, } = props;
670
794
  const [isEditing, setIsEditing] = react.useState(false);
795
+ const [isEditingKey, setIsEditingKey] = react.useState(false);
671
796
  const [stringifiedValue, setStringifiedValue] = react.useState(JSON.stringify(data, null, 2));
672
797
  const [error, setError] = react.useState(null);
673
798
  const collectionSize = Object.keys(data).length;
@@ -721,6 +846,22 @@ const CollectionNode = (_a) => {
721
846
  return;
722
847
  }
723
848
  };
849
+ const handleEditKey = (newKey) => {
850
+ setIsEditingKey(false);
851
+ if (!parentData)
852
+ return;
853
+ const parentPath = path.slice(0, -1);
854
+ if (!newKey)
855
+ return;
856
+ const newData = Object.fromEntries(Object.entries(parentData).map(([key, val]) => (key === name ? [newKey, val] : [key, val])));
857
+ onEdit(newData, parentPath);
858
+ };
859
+ const handleKeyPressKeyEdit = (e) => {
860
+ if (e.key === 'Enter')
861
+ handleEditKey(e.target.value);
862
+ else if (e.key === 'Escape')
863
+ handleCancel();
864
+ };
724
865
  const handleAdd = (key) => {
725
866
  setCollapsed(false);
726
867
  if (collectionType === 'array') {
@@ -755,7 +896,10 @@ const CollectionNode = (_a) => {
755
896
  const canEdit = react.useMemo(() => !restrictEditFilter(filterProps), [filterProps]);
756
897
  const canDelete = react.useMemo(() => !restrictDeleteFilter(filterProps), [filterProps]);
757
898
  const canAdd = react.useMemo(() => !restrictAddFilter(filterProps), [filterProps]);
758
- const showLabel = showArrayIndices || !(typeof path.slice(-1)[0] === 'number');
899
+ const canEditKey = parentData !== null && canEdit && canAdd && canDelete;
900
+ const isArray = typeof path.slice(-1)[0] === 'number';
901
+ const showLabel = showArrayIndices || !isArray;
902
+ const showCount = showCollectionCount === 'when-closed' ? collapsed : showCollectionCount;
759
903
  const keyValueArray = Object.entries(data).map(([key, value]) => [
760
904
  collectionType === 'array' ? Number(key) : key,
761
905
  value,
@@ -763,20 +907,27 @@ const CollectionNode = (_a) => {
763
907
  if (keySort && collectionType === 'object')
764
908
  keyValueArray.sort(typeof keySort === 'function' ? (a, b) => keySort(a[0], b[0]) : undefined);
765
909
  const numOfLines = JSON.stringify(data, null, 2).split('\n').length;
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
767
- ? translate('ITEM_SINGLE', 1)
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
769
- ? () => {
770
- setIsEditing(true);
771
- setCollapsed(false);
772
- }
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: {
774
- maxHeight: collapsed ? 0 : !isEditing ? `${numOfLines * 3}em` : undefined,
775
- overflowY: collapsed || isAnimating ? 'hidden' : 'visible',
776
- transition: `max-height ${transitionTime}`,
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 }))] }))] })));
910
+ const { CustomNode, customNodeProps, hideKey } = getCustomNode(customNodeDefinitions, {
911
+ key: name,
912
+ path,
913
+ level: path.length,
914
+ value: data,
915
+ size: Object.keys(data).length,
916
+ });
917
+ return (jsxRuntime.jsx("div", { className: "jer-component fb-collection-component", style: { marginLeft: `${path.length === 0 ? 0 : indent / 2}em` }, children: CustomNode ? (jsxRuntime.jsx(CustomNodeWrapper, { name: name, hideKey: hideKey, children: jsxRuntime.jsx(CustomNode, Object.assign({ data: data, path: path, name: name, parentData: parentData, customProps: customNodeProps }, props)) })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "jer-collection-header-row", children: [jsxRuntime.jsx("div", { onClick: handleCollapse, children: jsxRuntime.jsx(Icon, { name: "chevron", rotate: collapsed }) }), jsxRuntime.jsxs("div", { className: "jer-collection-name", children: [!isEditingKey && (jsxRuntime.jsx("span", { style: styles.property, onDoubleClick: () => canEditKey && setIsEditingKey(true), children: showLabel && name !== '' && name !== undefined ? `${name}:` : null })), isEditingKey && (jsxRuntime.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 && (jsxRuntime.jsx("span", { className: "jer-brackets", style: styles.bracket, children: brackets.open }))] }), !isEditing && showCollectionCount && (jsxRuntime.jsx("div", { className: `jer-collection-item-count${showCount ? ' jer-visible' : ' jer-hidden'}`, style: styles.itemCount, children: collectionSize === 1
918
+ ? translate('ITEM_SINGLE', 1)
919
+ : translate('ITEMS_MULTIPLE', collectionSize) })), jsxRuntime.jsx("div", { className: `jer-brackets${collapsed ? ' jer-visible' : ' jer-hidden'}`, style: styles.bracket, children: brackets.close }), !isEditing && (jsxRuntime.jsx(EditButtons, { startEdit: canEdit
920
+ ? () => {
921
+ setIsEditing(true);
922
+ setCollapsed(false);
923
+ }
924
+ : undefined, handleAdd: canAdd ? handleAdd : undefined, handleDelete: canDelete ? handleDelete : undefined, enableClipboard: enableClipboard, type: collectionType, data: data, name: name, path: path, translate: translate }))] }), jsxRuntime.jsxs("div", { className: 'jer-collection-inner', style: {
925
+ maxHeight: collapsed ? 0 : !isEditing ? `${numOfLines * 3}em` : undefined,
926
+ overflowY: collapsed || isAnimating ? 'hidden' : 'visible',
927
+ transition: `max-height ${transitionTime}`,
928
+ }, children: [isEditing ? (jsxRuntime.jsx("div", { 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", { className: "jer-collection-input-button-row", children: jsxRuntime.jsx(InputButtons, { onOk: handleEdit, onCancel: handleCancel, isCollection: true }) })] }) })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: !hasBeenOpened.current
929
+ ? null
930
+ : keyValueArray.map(([key, value]) => (jsxRuntime.jsx("div", { className: "jer-collection-element", children: isCollection(value) ? (jsxRuntime.jsx(CollectionNode, Object.assign({ data: value, parentData: data, path: [...path, key], name: key, showCollectionCount: showCollectionCount }, props), key)) : (jsxRuntime.jsx(ValueNodeWrapper, Object.assign({ data: value, parentData: data, path: [...path, key], name: key }, props, { showLabel: collectionType === 'object' ? true : showArrayIndices }), key)) }, key))) })), jsxRuntime.jsx("div", { className: isEditing ? 'jer-collection-error-row' : 'jer-collection-error-row-edit', children: error && (jsxRuntime.jsx("span", { className: "jer-error-slug", style: styles.error, children: error })) }), jsxRuntime.jsx("div", { className: "jer-brackets", style: styles.bracket, children: brackets.close })] })] })) }));
780
931
  };
781
932
 
782
933
  const localisedStrings = {
@@ -788,6 +939,8 @@ const localisedStrings = {
788
939
  ERROR_UPDATE: 'Update unsuccessful',
789
940
  ERROR_DELETE: 'Delete unsuccessful',
790
941
  ERROR_ADD: 'Adding node unsuccessful',
942
+ DEFAULT_STRING: 'New data!',
943
+ DEFAULT_NEW_KEY: 'key',
791
944
  };
792
945
  const translate = (translations, key, count) => {
793
946
  const string = key in translations ? translations[key] : localisedStrings[key];
@@ -795,7 +948,7 @@ const translate = (translations, key, count) => {
795
948
  };
796
949
  const getTranslateFunction = (translations) => (key, count) => translate(translations, key, count);
797
950
 
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, }) => {
951
+ 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 = [], }) => {
799
952
  const [data, setData] = react.useState(srcData);
800
953
  const { styles, setTheme, setIcons } = useTheme();
801
954
  const collapseFilter = react.useCallback(getFilterFunction(collapse), [collapse]);
@@ -877,10 +1030,12 @@ const Editor = ({ data: srcData, rootName = 'root', onUpdate, onEdit: srcEdit =
877
1030
  onEdit,
878
1031
  onDelete,
879
1032
  onAdd,
1033
+ showCollectionCount,
880
1034
  collapseFilter,
881
1035
  restrictEditFilter,
882
1036
  restrictDeleteFilter,
883
1037
  restrictAddFilter,
1038
+ restrictTypeSelection,
884
1039
  enableClipboard,
885
1040
  keySort,
886
1041
  showArrayIndices,
@@ -888,10 +1043,12 @@ const Editor = ({ data: srcData, rootName = 'root', onUpdate, onEdit: srcEdit =
888
1043
  defaultValue,
889
1044
  stringTruncate,
890
1045
  translate,
1046
+ customNodeDefinitions,
1047
+ parentData: null,
891
1048
  };
892
1049
  if (!styles)
893
1050
  return null;
894
- return (jsxRuntime.jsx("div", Object.assign({ className: 'jer-editor-container ' + className, style: Object.assign(Object.assign({}, styles.container), { minWidth, maxWidth }) }, { children: isCollection(data) && jsxRuntime.jsx(CollectionNode, Object.assign({ data: data, path: [] }, otherProps)) })));
1051
+ return (jsxRuntime.jsx("div", { className: 'jer-editor-container ' + className, style: Object.assign(Object.assign({}, styles.container), { minWidth, maxWidth }), children: isCollection(data) ? (jsxRuntime.jsx(CollectionNode, Object.assign({ data: data, path: [] }, otherProps))) : (jsxRuntime.jsx(ValueNodeWrapper, Object.assign({ data: data, path: [], showLabel: true }, otherProps))) }));
895
1052
  };
896
1053
  const JsonEditor = (props) => (jsxRuntime.jsx(ThemeProvider, { children: jsxRuntime.jsx(Editor, Object.assign({}, props)) }));
897
1054
  const updateDataObject = (data, path, newValue, action) => {
@@ -921,5 +1078,4 @@ const getFilterFunction = (propValue) => {
921
1078
  };
922
1079
 
923
1080
  exports.JsonEditor = JsonEditor;
924
- exports.default = JsonEditor;
925
1081
  exports.themes = themes;
package/build/index.d.ts CHANGED
@@ -30,6 +30,8 @@ declare const localisedStrings: {
30
30
  ERROR_UPDATE: string;
31
31
  ERROR_DELETE: string;
32
32
  ERROR_ADD: string;
33
+ DEFAULT_STRING: string;
34
+ DEFAULT_NEW_KEY: string;
33
35
  };
34
36
  type LocalisedStrings = typeof localisedStrings;
35
37
  type TranslateFunction = (key: keyof LocalisedStrings, count?: number) => string;
@@ -47,10 +49,11 @@ interface JsonEditorProps {
47
49
  className?: string;
48
50
  indent?: number;
49
51
  collapse?: boolean | number | FilterFunction;
52
+ showCollectionCount?: boolean | 'when-closed';
50
53
  restrictEdit?: boolean | FilterFunction;
51
54
  restrictDelete?: boolean | FilterFunction;
52
55
  restrictAdd?: boolean | FilterFunction;
53
- restrictKeyEdit?: boolean | FilterFunction;
56
+ restrictTypeSelection?: boolean | DataType[] | TypeFilterFunction;
54
57
  keySort?: boolean | CompareFunction;
55
58
  showArrayIndices?: boolean;
56
59
  defaultValue?: unknown;
@@ -58,8 +61,12 @@ interface JsonEditorProps {
58
61
  maxWidth?: string | number;
59
62
  stringTruncate?: number;
60
63
  translations?: Partial<LocalisedStrings>;
64
+ customNodeDefinitions?: CustomNodeDefinition[];
61
65
  }
66
+ declare const DataTypes: readonly ["string", "number", "boolean", "null", "object", "array"];
67
+ type DataType = (typeof DataTypes)[number] | 'invalid';
62
68
  type CollectionKey = string | number;
69
+ type CollectionData = object | unknown[];
63
70
  type ErrorString = string;
64
71
  interface IconReplacements {
65
72
  add?: JSX.Element;
@@ -78,13 +85,15 @@ type UpdateFunction = (props: {
78
85
  name: CollectionKey;
79
86
  path: CollectionKey[];
80
87
  }) => void | ErrorString | false;
81
- type FilterFunction = (input: {
88
+ interface FilterProps {
82
89
  key: CollectionKey;
83
90
  path: CollectionKey[];
84
91
  level: number;
85
92
  value: unknown;
86
93
  size: number | null;
87
- }) => boolean;
94
+ }
95
+ type FilterFunction = (input: FilterProps) => boolean;
96
+ type TypeFilterFunction = (input: FilterProps) => boolean | DataType[];
88
97
  type CopyType = 'path' | 'value';
89
98
  type CopyFunction = (input: {
90
99
  key: CollectionKey;
@@ -94,7 +103,38 @@ type CopyFunction = (input: {
94
103
  type: CopyType;
95
104
  }) => void;
96
105
  type CompareFunction = (a: string, b: string) => number;
106
+ type OnChangeFunction = (value: unknown, path: (string | number)[]) => Promise<string | void>;
107
+ interface BaseNodeProps {
108
+ data: unknown;
109
+ parentData: CollectionData | null;
110
+ path: CollectionKey[];
111
+ name: CollectionKey;
112
+ onEdit: OnChangeFunction;
113
+ onDelete: OnChangeFunction;
114
+ enableClipboard: boolean | CopyFunction;
115
+ restrictEditFilter: FilterFunction;
116
+ restrictDeleteFilter: FilterFunction;
117
+ restrictAddFilter: FilterFunction;
118
+ restrictTypeSelection: boolean | DataType[] | TypeFilterFunction;
119
+ stringTruncate: number;
120
+ indent: number;
121
+ translate: TranslateFunction;
122
+ customNodeDefinitions: CustomNodeDefinition[];
123
+ }
124
+ interface CustomNodeProps extends BaseNodeProps {
125
+ customProps?: Record<string, unknown>;
126
+ parentData: CollectionData | null;
127
+ }
128
+ interface CustomNodeDefinition {
129
+ condition: FilterFunction;
130
+ element: React$1.FC<CustomNodeProps>;
131
+ name: string;
132
+ props?: Record<string, unknown>;
133
+ hideKey?: boolean;
134
+ defaultValue: unknown;
135
+ showInTypesSelector?: boolean;
136
+ }
97
137
 
98
138
  declare const JsonEditor: React$1.FC<JsonEditorProps>;
99
139
 
100
- export { CompareFunction, CopyFunction, FilterFunction, IconReplacements, JsonEditor, JsonEditorProps, LocalisedStrings, Theme, ThemeInput, ThemeName, TranslateFunction, UpdateFunction, JsonEditor as default, themes };
140
+ export { type CompareFunction, type CopyFunction, type FilterFunction, type IconReplacements, JsonEditor, type JsonEditorProps, type LocalisedStrings, type Theme, type ThemeInput, type ThemeName, type TranslateFunction, type UpdateFunction, themes };