json-edit-react
Advanced tools
Comparing version 1.1.0 to 1.1.1
@@ -1,1081 +0,1 @@ | ||
'use strict'; | ||
var jsxRuntime = require('react/jsx-runtime'); | ||
var react = require('react'); | ||
var assign = require('object-property-assigner'); | ||
var extract = require('object-property-extractor'); | ||
var clone = require('just-clone'); | ||
var hi = require('react-icons/hi'); | ||
var bi = require('react-icons/bi'); | ||
var md = require('react-icons/md'); | ||
var fi = require('react-icons/fi'); | ||
var ti = require('react-icons/ti'); | ||
var fa = require('react-icons/fa'); | ||
/****************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
/* global Reflect, Promise, SuppressedError, Symbol */ | ||
function __rest(s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
} | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
} | ||
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { | ||
var e = new Error(message); | ||
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; | ||
}; | ||
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}} | ||
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"; | ||
n(css,{}); | ||
const defaultTheme$1 = { | ||
displayName: 'Default', | ||
fragments: { edit: 'rgb(42, 161, 152)' }, | ||
styles: { | ||
container: { | ||
backgroundColor: '#f6f6f6', | ||
fontFamily: 'monospace', | ||
}, | ||
property: '#292929', | ||
bracket: { color: 'rgb(0, 43, 54)', fontWeight: 'bold' }, | ||
itemCount: { color: 'rgba(0, 0, 0, 0.3)', fontStyle: 'italic' }, | ||
string: 'rgb(203, 75, 22)', | ||
number: 'rgb(38, 139, 210)', | ||
boolean: 'green', | ||
null: { color: 'rgb(220, 50, 47)', fontVariant: 'small-caps', fontWeight: 'bold' }, | ||
input: ['#292929', { fontSize: '90%' }], | ||
inputHighlight: '#b3d8ff', | ||
error: { fontSize: '0.8em', color: 'red', fontWeight: 'bold' }, | ||
iconCollection: 'rgb(0, 43, 54)', | ||
iconEdit: 'edit', | ||
iconDelete: 'rgb(203, 75, 22)', | ||
iconAdd: 'edit', | ||
iconCopy: 'rgb(38, 139, 210)', | ||
iconOk: 'green', | ||
iconCancel: 'rgb(203, 75, 22)', | ||
}, | ||
}; | ||
const themes = { | ||
default: defaultTheme$1, | ||
githubDark: { | ||
displayName: 'Github Dark', | ||
styles: { | ||
container: { | ||
backgroundColor: '#0d1117', | ||
color: 'white', | ||
}, | ||
property: '#E6EDF3', | ||
bracket: '#56d364', | ||
itemCount: '#8B949E', | ||
string: '#A5D6FF', | ||
number: '#D2A8FF', | ||
boolean: { color: '#FF7B72', fontSize: '90%', fontWeight: 'bold' }, | ||
null: 'green', | ||
iconCollection: '#D2A8FF', | ||
iconEdit: '#D2A8FF', | ||
iconDelete: 'rgb(203, 75, 22)', | ||
iconAdd: 'rgb(203, 75, 22)', | ||
iconCopy: '#A5D6FF', | ||
iconOk: '#56d364', | ||
iconCancel: 'rgb(203, 75, 22)', | ||
}, | ||
}, | ||
githubLight: { | ||
displayName: 'Github Light', | ||
styles: { | ||
container: 'white', | ||
property: '#1F2328', | ||
bracket: '#00802e', | ||
itemCount: '#8B949E', | ||
string: '#0A3069', | ||
number: '#953800', | ||
boolean: { color: '#CF222E', fontSize: '90%', fontWeight: 'bold' }, | ||
null: '#FF7B72', | ||
iconCollection: '#8250DF', | ||
iconEdit: '#8250DF', | ||
iconDelete: 'rgb(203, 75, 22)', | ||
iconAdd: '#8250DF', | ||
iconCopy: '#57606A', | ||
}, | ||
}, | ||
monoDark: { | ||
displayName: 'Black & White', | ||
fragments: { | ||
lightText: { color: 'white' }, | ||
midGrey: '#5c5c5c', | ||
}, | ||
styles: { | ||
container: ['lightText', { backgroundColor: 'black' }], | ||
property: 'lightText', | ||
bracket: 'midGrey', | ||
itemCount: '#4a4a4a', | ||
string: '#a8a8a8', | ||
number: '#666666', | ||
boolean: { color: '#848484', fontStyle: 'italic' }, | ||
null: '#333333', | ||
iconCollection: 'midGrey', | ||
iconEdit: 'midGrey', | ||
iconDelete: 'midGrey', | ||
iconAdd: 'midGrey', | ||
iconCopy: 'midGrey', | ||
iconOk: 'midGrey', | ||
iconCancel: 'midGrey', | ||
}, | ||
}, | ||
monoLight: { | ||
fragments: { midGrey: '#a3a3a3' }, | ||
displayName: 'White & Black', | ||
styles: { | ||
container: 'white', | ||
property: 'black', | ||
bracket: 'midGrey', | ||
itemCount: '#b5b5b5', | ||
string: '#575757', | ||
number: '#999999', | ||
boolean: { color: '#7b7b7b', fontStyle: 'italic' }, | ||
null: '#cccccc', | ||
iconCollection: 'midGrey', | ||
iconEdit: 'midGrey', | ||
iconDelete: 'midGrey', | ||
iconAdd: 'midGrey', | ||
iconCopy: 'midGrey', | ||
iconOk: 'midGrey', | ||
iconCancel: 'midGrey', | ||
}, | ||
}, | ||
candyWrapper: { | ||
displayName: 'Candy Wrapper', | ||
fragments: { | ||
minty: { backgroundColor: '#F1FAEE' }, | ||
pale: { color: '#A8DADC' }, | ||
mid: { color: '#457B9D' }, | ||
dark: { color: '#1D3557' }, | ||
pop: { color: '#E63946' }, | ||
darkBlue: { color: '#2B2D42' }, | ||
}, | ||
styles: { | ||
container: 'minty', | ||
property: 'pop', | ||
bracket: 'dark', | ||
itemCount: 'pale', | ||
string: 'mid', | ||
number: ['darkBlue', { fontSize: '85%' }], | ||
boolean: ['mid', { fontStyle: 'italic', fontWeight: 'bold', fontSize: '80%' }], | ||
null: ['#cccccc', { fontWeight: 'bold' }], | ||
iconCollection: '#1D3557', | ||
iconEdit: '#457B9D', | ||
iconDelete: '#E63946', | ||
iconAdd: '#2B2D42', | ||
iconCopy: '#1D3557', | ||
iconCancel: '#E63946', | ||
}, | ||
}, | ||
psychedelic: { | ||
displayName: 'Psychedelic', | ||
fragments: { | ||
minty: { | ||
backgroundColor: '#F1FAEE', | ||
}, | ||
pale: { | ||
color: '#A8DADC', | ||
}, | ||
mid: { | ||
color: '#457B9D', | ||
}, | ||
dark: { | ||
color: '#1D3557', | ||
}, | ||
pop: { | ||
color: '#E63946', | ||
}, | ||
fluroYellow: 'rgb(242, 228, 21)', | ||
fluroGreen: 'rgb(68, 255, 62)', | ||
hotPink: '#f7379a', | ||
}, | ||
styles: { | ||
container: { | ||
backgroundColor: 'unset', | ||
background: 'linear-gradient(90deg, hsla(333, 100%, 53%, 1) 0%, hsla(33, 94%, 57%, 1) 100%)', | ||
color: 'black', | ||
}, | ||
property: 'black', | ||
bracket: 'fluroYellow', | ||
itemCount: [ | ||
'pale', | ||
{ | ||
opacity: 0.7, | ||
}, | ||
], | ||
string: 'white', | ||
number: [ | ||
'#33d9ff', | ||
{ | ||
fontSize: '90%', | ||
fontWeight: 'bold', | ||
}, | ||
], | ||
boolean: [ | ||
'fluroGreen', | ||
{ | ||
fontWeight: 'bold', | ||
fontSize: '80%', | ||
}, | ||
], | ||
null: [ | ||
'black', | ||
{ | ||
fontWeight: 'bold', | ||
opacity: 0.3, | ||
backgroundColor: 'rgb(255, 255, 255, 0.5)', | ||
padding: '0 0.4em', | ||
borderRadius: '0.4em', | ||
}, | ||
], | ||
iconCollection: 'fluroYellow', | ||
iconEdit: ['black'], | ||
iconDelete: [ | ||
'white', | ||
{ | ||
opacity: 0.5, | ||
}, | ||
], | ||
iconAdd: [ | ||
'white', | ||
{ | ||
opacity: 0.5, | ||
}, | ||
], | ||
iconCopy: 'rgb(32, 84, 242)', | ||
iconOk: 'fluroGreen', | ||
iconCancel: 'hotPink', | ||
}, | ||
}, | ||
}; | ||
const emptyStyleObject = { | ||
container: {}, | ||
property: {}, | ||
bracket: {}, | ||
itemCount: {}, | ||
string: {}, | ||
number: {}, | ||
boolean: {}, | ||
null: {}, | ||
input: {}, | ||
inputHighlight: {}, | ||
error: {}, | ||
iconCollection: {}, | ||
iconEdit: {}, | ||
iconDelete: {}, | ||
iconAdd: {}, | ||
iconCopy: {}, | ||
iconOk: {}, | ||
iconCancel: {}, | ||
}; | ||
const defaultTheme = themes.default; | ||
const initialContext = { | ||
styles: emptyStyleObject, | ||
setTheme: (_) => { }, | ||
icons: {}, | ||
setIcons: () => { }, | ||
}; | ||
const ThemeProviderContext = react.createContext(initialContext); | ||
const ThemeProvider = ({ children }) => { | ||
const [styles, setStyles] = react.useState(emptyStyleObject); | ||
const [icons, setIcons] = react.useState({}); | ||
const setTheme = (theme) => setStyles(compileStyles(theme)); | ||
return (jsxRuntime.jsx(ThemeProviderContext.Provider, { value: { styles, setTheme, icons, setIcons }, children: children })); | ||
}; | ||
const useTheme = () => react.useContext(ThemeProviderContext); | ||
const compileStyles = (themeInput) => { | ||
if (typeof themeInput === 'string') | ||
return buildStyleObject(themes[themeInput]); | ||
if (Array.isArray(themeInput)) { | ||
const [name, overrides] = themeInput; | ||
return buildStyleObject(themes[name], isStyleObject(overrides) ? { styles: overrides } : overrides); | ||
} | ||
return buildStyleObject(defaultTheme, isStyleObject(themeInput) ? { styles: themeInput } : themeInput); | ||
}; | ||
const buildStyleObject = (baseTheme, overrides = { styles: emptyStyleObject }) => { | ||
var _a, _b, _c, _d; | ||
const [defaultStyles, baseStyles, overrideStyles] = [defaultTheme, baseTheme, overrides].map((theme) => { | ||
const { fragments, styles } = theme; | ||
const compiledStyles = {}; | ||
Object.entries(styles).forEach(([key, value]) => { | ||
const elements = Array.isArray(value) ? value : [value]; | ||
const cssStyles = elements.reduce((acc, curr) => { | ||
var _a; | ||
if (typeof curr === 'string') { | ||
const style = (_a = fragments === null || fragments === void 0 ? void 0 : fragments[curr]) !== null && _a !== void 0 ? _a : curr; | ||
switch (typeof style) { | ||
case 'string': | ||
return Object.assign(Object.assign({}, acc), { [defaultStyleProperties[key]]: style }); | ||
default: | ||
return Object.assign(Object.assign({}, acc), style); | ||
} | ||
} | ||
else | ||
return Object.assign(Object.assign({}, acc), curr); | ||
}, {}); | ||
compiledStyles[key] = cssStyles; | ||
}); | ||
return compiledStyles; | ||
}); | ||
const finalStyles = {}; | ||
Object.keys(defaultTheme.styles).forEach((key) => { | ||
finalStyles[key] = Object.assign(Object.assign(Object.assign({}, defaultStyles[key]), baseStyles[key]), overrideStyles[key]); | ||
}); | ||
if ((_a = finalStyles === null || finalStyles === void 0 ? void 0 : finalStyles.inputHighlight) === null || _a === void 0 ? void 0 : _a.backgroundColor) | ||
document.documentElement.style.setProperty('--jer-highlight-color', (_b = finalStyles === null || finalStyles === void 0 ? void 0 : finalStyles.inputHighlight) === null || _b === void 0 ? void 0 : _b.backgroundColor); | ||
if ((_c = finalStyles === null || finalStyles === void 0 ? void 0 : finalStyles.iconCopy) === null || _c === void 0 ? void 0 : _c.color) | ||
document.documentElement.style.setProperty('--jer-icon-copy-color', (_d = finalStyles === null || finalStyles === void 0 ? void 0 : finalStyles.iconCopy) === null || _d === void 0 ? void 0 : _d.color); | ||
return finalStyles; | ||
}; | ||
const isStyleObject = (overrideObject) => { | ||
return !('styles' in overrideObject); | ||
}; | ||
const defaultStyleProperties = { | ||
container: 'backgroundColor', | ||
property: 'color', | ||
bracket: 'color', | ||
itemCount: 'color', | ||
string: 'color', | ||
number: 'color', | ||
boolean: 'color', | ||
null: 'color', | ||
input: 'color', | ||
inputHighlight: 'backgroundColor', | ||
error: 'color', | ||
iconCollection: 'color', | ||
iconEdit: 'color', | ||
iconDelete: 'color', | ||
iconAdd: 'color', | ||
iconCopy: 'color', | ||
iconOk: 'color', | ||
iconCancel: 'color', | ||
}; | ||
const AutogrowTextArea = ({ className, name, value, setValue, handleKeyPress, }) => { | ||
const { styles } = useTheme(); | ||
const dummyValue = value.slice(-1) === '\n' ? value + '.' : value; | ||
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) => { | ||
if (value.length < 40) | ||
e.target.select(); | ||
}, 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 })] })); | ||
}; | ||
const INVALID_FUNCTION_STRING = '**INVALID_FUNCTION**'; | ||
const truncate = (string, length = 200) => string.length < length ? string : `${string.slice(0, length - 2).trim()}...`; | ||
const StringValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, stringTruncate, }) => { | ||
const { styles } = useTheme(); | ||
const handleKeyPress = (e) => { | ||
if (e.key === 'Enter' && !e.shiftKey) | ||
handleEdit(); | ||
else if (e.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
const breakString = (text) => text.split('\n').map((line, index, arr) => (jsxRuntime.jsxs("span", { children: [line, index < arr.length - 1 ? jsxRuntime.jsx("br", {}) : null] }, index))); | ||
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) => { | ||
if (e.getModifierState('Control') || e.getModifierState('Meta')) | ||
setIsEditing(true); | ||
}, className: "jer-value-string", style: styles.string, children: ["\"", breakString(truncate(value, stringTruncate)), "\""] })); | ||
}; | ||
const NumberValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, }) => { | ||
const { styles } = useTheme(); | ||
const handleKeyPress = (e) => { | ||
if (e.key === 'Enter') | ||
handleEdit(); | ||
else if (e.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
const validateNumber = (input) => { | ||
return input.replace(/[^0-9.-]/g, ''); | ||
}; | ||
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 })); | ||
}; | ||
const BooleanValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, }) => { | ||
const { styles } = useTheme(); | ||
react.useEffect(() => { | ||
if (isEditing) | ||
document.addEventListener('keydown', listenForSubmit); | ||
return () => document.removeEventListener('keydown', listenForSubmit); | ||
}, [isEditing]); | ||
const listenForSubmit = (event) => { | ||
if (event.key === 'Enter') { | ||
handleEdit(); | ||
} | ||
else if (event.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
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) })); | ||
}; | ||
const NullValue = ({ value, isEditing, setIsEditing, handleEdit, handleCancel, }) => { | ||
const { styles } = useTheme(); | ||
react.useEffect(() => { | ||
if (isEditing) | ||
document.addEventListener('keydown', listenForSubmit); | ||
return () => document.removeEventListener('keydown', listenForSubmit); | ||
}, [isEditing]); | ||
const listenForSubmit = (event) => { | ||
if (event.key === 'Enter') { | ||
handleEdit(); | ||
} | ||
else if (event.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
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) })); | ||
}; | ||
const ObjectValue = ({ value, translate, isEditing, handleEdit, handleCancel, }) => { | ||
react.useEffect(() => { | ||
if (isEditing) | ||
document.addEventListener('keydown', listenForSubmit); | ||
return () => document.removeEventListener('keydown', listenForSubmit); | ||
}, []); | ||
const listenForSubmit = (event) => { | ||
if (event.key === 'Enter') { | ||
handleEdit(); | ||
} | ||
else if (event.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
return (jsxRuntime.jsx("span", { className: "jer-value-object", children: `{${translate('DEFAULT_NEW_KEY')}: "${value}" }` })); | ||
}; | ||
const ArrayValue = ({ value, isEditing, handleEdit, handleCancel, }) => { | ||
react.useEffect(() => { | ||
if (isEditing) | ||
document.addEventListener('keydown', listenForSubmit); | ||
return () => document.removeEventListener('keydown', listenForSubmit); | ||
}, []); | ||
const listenForSubmit = (event) => { | ||
if (event.key === 'Enter') { | ||
handleEdit(); | ||
} | ||
else if (event.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
return jsxRuntime.jsx("span", { className: "jer-value-array", children: `[${value === null ? '' : value}]` }); | ||
}; | ||
const InvalidValue = ({ value }) => { | ||
let message = 'Error!'; | ||
switch (typeof value) { | ||
case 'string': | ||
if (value === INVALID_FUNCTION_STRING) | ||
message = 'Function'; | ||
break; | ||
case 'undefined': | ||
message = 'Undefined'; | ||
break; | ||
case 'symbol': | ||
message = 'Symbol'; | ||
break; | ||
} | ||
return jsxRuntime.jsx("span", { className: "jer-value-invalid", children: message }); | ||
}; | ||
const Icon = ({ name, rotate }) => { | ||
var _a, _b, _c, _d, _e, _f, _g; | ||
const { styles, icons } = useTheme(); | ||
const commonProps = { size: '1.4em', className: 'jer-icon' }; | ||
switch (name) { | ||
case 'add': | ||
return (_a = icons === null || icons === void 0 ? void 0 : icons.add) !== null && _a !== void 0 ? _a : jsxRuntime.jsx(bi.BiPlusCircle, Object.assign({}, commonProps, { style: styles.iconAdd })); | ||
case 'edit': | ||
return (_b = icons === null || icons === void 0 ? void 0 : icons.edit) !== null && _b !== void 0 ? _b : jsxRuntime.jsx(bi.BiEdit, Object.assign({}, commonProps, { style: styles.iconEdit })); | ||
case 'delete': | ||
return ((_c = icons === null || icons === void 0 ? void 0 : icons.delete) !== null && _c !== void 0 ? _c : jsxRuntime.jsx(md.MdDeleteForever, Object.assign({}, commonProps, { style: styles.iconDelete, size: "1.5em" }))); | ||
case 'copy': | ||
return (_d = icons === null || icons === void 0 ? void 0 : icons.copy) !== null && _d !== void 0 ? _d : jsxRuntime.jsx(hi.HiOutlineClipboardCopy, Object.assign({}, commonProps, { style: styles.iconCopy })); | ||
case 'ok': | ||
return ((_e = icons === null || icons === void 0 ? void 0 : icons.ok) !== null && _e !== void 0 ? _e : (jsxRuntime.jsx(fi.FiCheckCircle, Object.assign({}, commonProps, { style: Object.assign({ fontSize: '90%' }, styles.iconOk) })))); | ||
case 'cancel': | ||
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) })))); | ||
case 'chevron': | ||
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 }))); | ||
default: | ||
return jsxRuntime.jsx(jsxRuntime.Fragment, {}); | ||
} | ||
}; | ||
const EditButtons = ({ startEdit, handleDelete, handleAdd, enableClipboard, type, data, path, name, translate, }) => { | ||
const { styles } = useTheme(); | ||
const NEW_KEY_PROMPT = translate('KEY_NEW'); | ||
const [isAdding, setIsAdding] = react.useState(false); | ||
const [newKey, setNewKey] = react.useState(NEW_KEY_PROMPT); | ||
react.useEffect(() => { | ||
if (!isAdding) | ||
setNewKey(NEW_KEY_PROMPT); | ||
}, [isAdding]); | ||
const handleKeyPress = (e) => { | ||
if (e.key === 'Enter' && handleAdd) { | ||
setIsAdding(false); | ||
handleAdd(newKey); | ||
} | ||
else if (e.key === 'Escape') | ||
setIsAdding(false); | ||
}; | ||
const handleCopy = (e) => { | ||
let copyType = 'value'; | ||
let value; | ||
let stringValue = ''; | ||
if (enableClipboard) { | ||
switch (e.ctrlKey || e.metaKey) { | ||
case true: | ||
value = stringifyPath(path); | ||
stringValue = value; | ||
copyType = 'path'; | ||
break; | ||
default: | ||
value = data; | ||
stringValue = type ? JSON.stringify(data, null, 2) : String(value); | ||
} | ||
navigator.clipboard.writeText(stringValue); | ||
} | ||
if (typeof enableClipboard === 'function') | ||
enableClipboard({ value, stringValue, path, key: name, type: copyType }); | ||
}; | ||
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: () => { | ||
if (type === 'object') | ||
setIsAdding(true); | ||
else | ||
handleAdd(''); | ||
}, 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: () => { | ||
if (!!newKey) { | ||
setIsAdding(false); | ||
handleAdd(newKey); | ||
} | ||
}, onCancel: () => { | ||
setIsAdding(false); | ||
} })] }))] })); | ||
}; | ||
const InputButtons = ({ onOk, onCancel }) => { | ||
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" }) })] })); | ||
}; | ||
const stringifyPath = (path) => path.reduce((str, part) => { | ||
if (typeof part === 'number') | ||
return `${str}[${part}]`; | ||
else | ||
return str === '' ? part : `${str}.${part}`; | ||
}, ''); | ||
const ERROR_DISPLAY_TIME = 2500; | ||
const ValueDataTypes = ['string', 'number', 'boolean', 'null']; | ||
const CollectionDataTypes = ['object', 'array']; | ||
const DataTypes = [...ValueDataTypes, ...CollectionDataTypes]; | ||
const getCustomNode = (customNodeDefinitions = [], filterProps) => { | ||
const matchingDefinitions = customNodeDefinitions.filter(({ condition }) => condition(filterProps)); | ||
if (matchingDefinitions.length === 0) | ||
return {}; | ||
const { element, props, hideKey = false } = matchingDefinitions[0]; | ||
return { CustomNode: element, customNodeProps: props, hideKey }; | ||
}; | ||
const CustomNodeWrapper = ({ name, hideKey, children, indent, }) => { | ||
const { styles } = useTheme(); | ||
const indentStyle = indent ? { marginLeft: `${indent / 2}em` } : {}; | ||
return (jsxRuntime.jsx("div", { className: "jer-component jer-value-component", style: indentStyle, children: jsxRuntime.jsxs("div", { className: "jer-value-main-row", style: { | ||
flexWrap: name.length > 10 ? 'wrap' : 'nowrap', | ||
}, 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 })] }) })); | ||
}; | ||
const ValueNodeWrapper = (props) => { | ||
const { data, parentData, name, path, onEdit, onDelete, enableClipboard, restrictEditFilter, restrictDeleteFilter, restrictTypeSelection, showLabel, stringTruncate, indent, translate, customNodeDefinitions, } = props; | ||
const { styles } = useTheme(); | ||
const [isEditing, setIsEditing] = react.useState(false); | ||
const [isEditingKey, setIsEditingKey] = react.useState(false); | ||
const [value, setValue] = react.useState(typeof data === 'function' ? INVALID_FUNCTION_STRING : data); | ||
const [error, setError] = react.useState(null); | ||
const [dataType, setDataType] = react.useState(getDataType(data)); | ||
react.useEffect(() => { | ||
setValue(typeof data === 'function' ? INVALID_FUNCTION_STRING : data); | ||
setDataType(getDataType(data)); | ||
}, [data, error]); | ||
const handleChangeDataType = (type) => { | ||
const customNode = customNodeDefinitions.find((customNode) => customNode.name === type); | ||
if (customNode) { | ||
onEdit(customNode.defaultValue, path); | ||
} | ||
else { | ||
setValue(convertValue(value, type)); | ||
setDataType(type); | ||
} | ||
}; | ||
const logError = (errorString) => { | ||
setError(errorString); | ||
setTimeout(() => setError(null), ERROR_DISPLAY_TIME); | ||
console.log('Error', errorString); | ||
}; | ||
const handleEdit = () => { | ||
setIsEditing(false); | ||
let newValue; | ||
switch (dataType) { | ||
case 'object': | ||
newValue = { [translate('DEFAULT_NEW_KEY')]: value }; | ||
break; | ||
case 'array': | ||
newValue = value !== null ? value : []; | ||
break; | ||
case 'number': | ||
const n = Number(value); | ||
if (isNaN(n)) | ||
newValue = 0; | ||
else | ||
newValue = n; | ||
break; | ||
default: | ||
newValue = value; | ||
} | ||
onEdit(newValue, path).then((error) => { | ||
if (error) | ||
logError(error); | ||
}); | ||
}; | ||
const handleEditKey = (newKey) => { | ||
setIsEditingKey(false); | ||
if (!parentData) | ||
return; | ||
const parentPath = path.slice(0, -1); | ||
if (!newKey) | ||
return; | ||
const newData = Object.fromEntries(Object.entries(parentData).map(([key, val]) => (key === name ? [newKey, val] : [key, val]))); | ||
onEdit(newData, parentPath); | ||
}; | ||
const handleKeyPress = (e) => { | ||
if (e.key === 'Enter') | ||
handleEditKey(e.target.value); | ||
else if (e.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
const handleCancel = () => { | ||
setIsEditing(false); | ||
setIsEditingKey(false); | ||
setValue(data); | ||
setDataType(getDataType(data)); | ||
}; | ||
const handleDelete = () => { | ||
onDelete(value, path).then((error) => { | ||
if (error) | ||
logError(error); | ||
}); | ||
}; | ||
const filterProps = { key: name, path, level: path.length, value: data, size: null }; | ||
const canEdit = react.useMemo(() => !restrictEditFilter(filterProps), [filterProps]); | ||
const canDelete = react.useMemo(() => !restrictDeleteFilter(filterProps), [filterProps]); | ||
const isArray = typeof path.slice(-1)[0] === 'number'; | ||
const canEditKey = !isArray && canEdit && canDelete; | ||
const inputProps = { | ||
value, | ||
parentData, | ||
setValue, | ||
isEditing, | ||
setIsEditing: canEdit ? () => setIsEditing(true) : () => { }, | ||
handleEdit, | ||
handleCancel, | ||
path, | ||
stringTruncate, | ||
translate, | ||
}; | ||
const { CustomNode, customNodeProps, hideKey } = getCustomNode(customNodeDefinitions, { | ||
key: name, | ||
path, | ||
level: path.length, | ||
value: data, | ||
size: 0, | ||
}); | ||
const allDataTypes = [ | ||
...customNodeDefinitions | ||
.filter(({ showInTypesSelector = false }) => showInTypesSelector) | ||
.map(({ name }) => name), | ||
...DataTypes, | ||
]; | ||
const allowedDataTypes = react.useMemo(() => { | ||
if (typeof restrictTypeSelection === 'boolean') | ||
return restrictTypeSelection ? [] : allDataTypes; | ||
if (Array.isArray(restrictTypeSelection)) | ||
return restrictTypeSelection; | ||
const result = restrictTypeSelection(filterProps); | ||
if (typeof result === 'boolean') | ||
return result ? [] : allDataTypes; | ||
return result; | ||
}, [filterProps, restrictTypeSelection]); | ||
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: { | ||
flexWrap: name.length > 10 ? 'wrap' : 'nowrap', | ||
}, 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' && | ||
!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 }))] })] }) })); | ||
}; | ||
const getDataType = (value) => { | ||
if (typeof value === 'string') | ||
return 'string'; | ||
if (typeof value === 'number') | ||
return 'number'; | ||
if (typeof value === 'boolean') | ||
return 'boolean'; | ||
if (value === null) | ||
return 'null'; | ||
return 'invalid'; | ||
}; | ||
const getInputComponent = (dataType, inputProps) => { | ||
const value = inputProps.value; | ||
switch (dataType) { | ||
case 'string': | ||
return jsxRuntime.jsx(StringValue, Object.assign({}, inputProps, { value: value })); | ||
case 'number': | ||
return jsxRuntime.jsx(NumberValue, Object.assign({}, inputProps, { value: value })); | ||
case 'boolean': | ||
return jsxRuntime.jsx(BooleanValue, Object.assign({}, inputProps, { value: value })); | ||
case 'null': | ||
return jsxRuntime.jsx(NullValue, Object.assign({}, inputProps)); | ||
case 'object': | ||
return jsxRuntime.jsx(ObjectValue, Object.assign({}, inputProps, { value: value })); | ||
case 'array': | ||
return jsxRuntime.jsx(ArrayValue, Object.assign({}, inputProps)); | ||
default: | ||
return jsxRuntime.jsx(InvalidValue, Object.assign({}, inputProps)); | ||
} | ||
}; | ||
const convertValue = (value, type) => { | ||
switch (type) { | ||
case 'string': | ||
return String(value); | ||
case 'number': | ||
const n = Number(value); | ||
return isNaN(n) ? 0 : n; | ||
case 'boolean': | ||
return !!value; | ||
case 'null': | ||
return null; | ||
case 'object': | ||
return value; | ||
case 'array': | ||
return [value]; | ||
default: | ||
return String(value); | ||
} | ||
}; | ||
const isCollection = (value) => value !== null && typeof value == 'object'; | ||
const CollectionNode = (_a) => { | ||
var { data, path, name, parentData, showCollectionCount } = _a, props = __rest(_a, ["data", "path", "name", "parentData", "showCollectionCount"]); | ||
const { styles } = useTheme(); | ||
const { onEdit, onAdd, onDelete, restrictEditFilter, restrictDeleteFilter, restrictAddFilter, collapseFilter, enableClipboard, indent, keySort, showArrayIndices, defaultValue, translate, customNodeDefinitions, } = props; | ||
const [isEditing, setIsEditing] = react.useState(false); | ||
const [isEditingKey, setIsEditingKey] = react.useState(false); | ||
const [stringifiedValue, setStringifiedValue] = react.useState(JSON.stringify(data, null, 2)); | ||
const [error, setError] = react.useState(null); | ||
const collectionSize = Object.keys(data).length; | ||
const filterProps = { key: name, path, level: path.length, value: data, size: collectionSize }; | ||
const startCollapsed = collapseFilter(filterProps); | ||
const [collapsed, setCollapsed] = react.useState(startCollapsed); | ||
const hasBeenOpened = react.useRef(!startCollapsed); | ||
const [isAnimating, setIsAnimating] = react.useState(false); | ||
react.useEffect(() => { | ||
setStringifiedValue(JSON.stringify(data, null, 2)); | ||
}, [data]); | ||
react.useEffect(() => { | ||
setCollapsed(collapseFilter(filterProps)); | ||
}, [collapseFilter]); | ||
const collectionType = Array.isArray(data) ? 'array' : 'object'; | ||
const brackets = collectionType === 'array' ? { open: '[', close: ']' } : { open: '{', close: '}' }; | ||
const transitionTime = getComputedStyle(document.documentElement).getPropertyValue('--jer-expand-transition-time'); | ||
const handleKeyPress = (e) => { | ||
if (e.key === 'Enter' && (e.metaKey || e.shiftKey || e.ctrlKey)) | ||
handleEdit(); | ||
else if (e.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
const handleCollapse = () => { | ||
if (!isEditing) { | ||
setIsAnimating(true); | ||
hasBeenOpened.current = true; | ||
setCollapsed(!collapsed); | ||
setTimeout(() => setIsAnimating(false), 500); | ||
} | ||
}; | ||
const showError = (errorString) => { | ||
setError(errorString); | ||
setTimeout(() => setError(null), ERROR_DISPLAY_TIME); | ||
console.log('Error', errorString); | ||
}; | ||
const handleEdit = () => { | ||
try { | ||
const value = JSON.parse(stringifiedValue); | ||
setIsEditing(false); | ||
setError(null); | ||
onEdit(value, path).then((error) => { | ||
if (error) | ||
showError(error); | ||
}); | ||
} | ||
catch (_a) { | ||
setError(translate('ERROR_INVALID_JSON')); | ||
setTimeout(() => setError(null), ERROR_DISPLAY_TIME); | ||
console.log('Invalid JSON'); | ||
return; | ||
} | ||
}; | ||
const handleEditKey = (newKey) => { | ||
setIsEditingKey(false); | ||
if (!parentData) | ||
return; | ||
const parentPath = path.slice(0, -1); | ||
if (!newKey) | ||
return; | ||
const newData = Object.fromEntries(Object.entries(parentData).map(([key, val]) => (key === name ? [newKey, val] : [key, val]))); | ||
onEdit(newData, parentPath); | ||
}; | ||
const handleKeyPressKeyEdit = (e) => { | ||
if (e.key === 'Enter') | ||
handleEditKey(e.target.value); | ||
else if (e.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
const handleAdd = (key) => { | ||
setCollapsed(false); | ||
if (collectionType === 'array') { | ||
onAdd(defaultValue, [...path, data.length]).then((error) => { | ||
if (error) | ||
showError(error); | ||
}); | ||
} | ||
else if (key in data) { | ||
showError(translate('ERROR_KEY_EXISTS')); | ||
return; | ||
} | ||
else | ||
onAdd(defaultValue, [...path, key]).then((error) => { | ||
if (error) | ||
showError(error); | ||
}); | ||
}; | ||
const handleDelete = path.length > 0 | ||
? () => { | ||
onDelete(data, path).then((result) => { | ||
if (result) | ||
showError(result); | ||
}); | ||
} | ||
: undefined; | ||
const handleCancel = () => { | ||
setIsEditing(false); | ||
setError(null); | ||
setStringifiedValue(JSON.stringify(data, null, 2)); | ||
}; | ||
const canEdit = react.useMemo(() => !restrictEditFilter(filterProps), [filterProps]); | ||
const canDelete = react.useMemo(() => !restrictDeleteFilter(filterProps), [filterProps]); | ||
const canAdd = react.useMemo(() => !restrictAddFilter(filterProps), [filterProps]); | ||
const canEditKey = parentData !== null && canEdit && canAdd && canDelete; | ||
const isArray = typeof path.slice(-1)[0] === 'number'; | ||
const showLabel = showArrayIndices || !isArray; | ||
const showCount = showCollectionCount === 'when-closed' ? collapsed : showCollectionCount; | ||
const keyValueArray = Object.entries(data).map(([key, value]) => [ | ||
collectionType === 'array' ? Number(key) : key, | ||
value, | ||
]); | ||
if (keySort && collectionType === 'object') | ||
keyValueArray.sort(typeof keySort === 'function' ? (a, b) => keySort(a[0], b[0]) : undefined); | ||
const numOfLines = JSON.stringify(data, null, 2).split('\n').length; | ||
const { CustomNode, customNodeProps, hideKey } = getCustomNode(customNodeDefinitions, { | ||
key: name, | ||
path, | ||
level: path.length, | ||
value: data, | ||
size: Object.keys(data).length, | ||
}); | ||
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 | ||
? translate('ITEM_SINGLE', 1) | ||
: 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 | ||
? () => { | ||
setIsEditing(true); | ||
setCollapsed(false); | ||
} | ||
: 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: { | ||
maxHeight: collapsed ? 0 : !isEditing ? `${numOfLines * 3}em` : undefined, | ||
overflowY: collapsed || isAnimating ? 'hidden' : 'visible', | ||
transition: `max-height ${transitionTime}`, | ||
}, 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 | ||
? null | ||
: 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 })] })] })) })); | ||
}; | ||
const localisedStrings = { | ||
ITEM_SINGLE: '{{count}} item', | ||
ITEMS_MULTIPLE: '{{count}} items', | ||
KEY_NEW: 'Enter new key', | ||
ERROR_KEY_EXISTS: 'Key already exists', | ||
ERROR_INVALID_JSON: 'Invalid JSON', | ||
ERROR_UPDATE: 'Update unsuccessful', | ||
ERROR_DELETE: 'Delete unsuccessful', | ||
ERROR_ADD: 'Adding node unsuccessful', | ||
DEFAULT_STRING: 'New data!', | ||
DEFAULT_NEW_KEY: 'key', | ||
}; | ||
const translate = (translations, key, count) => { | ||
const string = key in translations ? translations[key] : localisedStrings[key]; | ||
return count === undefined ? string : string === null || string === void 0 ? void 0 : string.replace('{{count}}', String(count)); | ||
}; | ||
const getTranslateFunction = (translations) => (key, count) => translate(translations, key, count); | ||
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 = [], }) => { | ||
const [data, setData] = react.useState(srcData); | ||
const { styles, setTheme, setIcons } = useTheme(); | ||
const collapseFilter = react.useCallback(getFilterFunction(collapse), [collapse]); | ||
const translate = react.useCallback(getTranslateFunction(translations), [translations]); | ||
react.useEffect(() => { | ||
setData(srcData); | ||
}, [srcData]); | ||
react.useEffect(() => { | ||
if (theme) | ||
setTheme(theme); | ||
if (icons) | ||
setIcons(icons); | ||
}, [theme, icons]); | ||
const onEdit = (value, path) => __awaiter(void 0, void 0, void 0, function* () { | ||
const { currentData, newData, currentValue, newValue } = updateDataObject(data, path, value, 'update'); | ||
if (srcEdit) { | ||
const result = yield srcEdit({ | ||
currentData, | ||
newData, | ||
currentValue, | ||
newValue, | ||
name: path.slice(-1)[0], | ||
path, | ||
}); | ||
if (result === undefined) | ||
setData(newData); | ||
if (result === false) | ||
return translate('ERROR_UPDATE'); | ||
return result; | ||
} | ||
else | ||
setData(newData); | ||
}); | ||
const onDelete = (value, path) => __awaiter(void 0, void 0, void 0, function* () { | ||
const { currentData, newData, currentValue, newValue } = updateDataObject(data, path, value, 'delete'); | ||
if (srcDelete) { | ||
const result = yield srcDelete({ | ||
currentData, | ||
newData, | ||
currentValue, | ||
newValue, | ||
name: path.slice(-1)[0], | ||
path, | ||
}); | ||
if (result === undefined) | ||
setData(newData); | ||
if (result === false) | ||
return translate('ERROR_DELETE'); | ||
return result; | ||
} | ||
else | ||
setData(newData); | ||
}); | ||
const onAdd = (value, path) => __awaiter(void 0, void 0, void 0, function* () { | ||
const { currentData, newData, currentValue, newValue } = updateDataObject(data, path, value, 'add'); | ||
if (srcAdd) { | ||
const result = yield srcAdd({ | ||
currentData, | ||
newData, | ||
currentValue, | ||
newValue, | ||
name: path.slice(-1)[0], | ||
path, | ||
}); | ||
if (result === undefined) | ||
setData(newData); | ||
if (result === false) | ||
return translate('ERROR_ADD'); | ||
return result; | ||
} | ||
else | ||
setData(newData); | ||
}); | ||
const restrictEditFilter = getFilterFunction(restrictEdit); | ||
const restrictDeleteFilter = getFilterFunction(restrictDelete); | ||
const restrictAddFilter = getFilterFunction(restrictAdd); | ||
const otherProps = { | ||
name: rootName, | ||
onEdit, | ||
onDelete, | ||
onAdd, | ||
showCollectionCount, | ||
collapseFilter, | ||
restrictEditFilter, | ||
restrictDeleteFilter, | ||
restrictAddFilter, | ||
restrictTypeSelection, | ||
enableClipboard, | ||
keySort, | ||
showArrayIndices, | ||
indent, | ||
defaultValue, | ||
stringTruncate, | ||
translate, | ||
customNodeDefinitions, | ||
parentData: null, | ||
}; | ||
if (!styles) | ||
return null; | ||
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))) })); | ||
}; | ||
const JsonEditor = (props) => (jsxRuntime.jsx(ThemeProvider, { children: jsxRuntime.jsx(Editor, Object.assign({}, props)) })); | ||
const updateDataObject = (data, path, newValue, action) => { | ||
if (path.length === 0) { | ||
return { | ||
currentData: data, | ||
newData: newValue, | ||
currentValue: data, | ||
newValue: newValue, | ||
}; | ||
} | ||
const currentValue = action !== 'add' ? extract(data, path) : undefined; | ||
const newData = assign(clone(data), path, newValue, { remove: action === 'delete' }); | ||
return { | ||
currentData: data, | ||
newData, | ||
currentValue, | ||
newValue: action === 'update' ? newValue : undefined, | ||
}; | ||
}; | ||
const getFilterFunction = (propValue) => { | ||
if (typeof propValue === 'boolean') | ||
return () => propValue; | ||
if (typeof propValue === 'number') | ||
return ({ level }) => level >= propValue; | ||
return propValue; | ||
}; | ||
exports.JsonEditor = JsonEditor; | ||
exports.themes = themes; | ||
"use strict";var e=require("react/jsx-runtime"),n=require("react"),t=require("object-property-assigner"),r=require("object-property-extractor"),o=require("just-clone"),i=require("react-icons/hi"),a=require("react-icons/bi"),l=require("react-icons/md"),s=require("react-icons/fi"),c=require("react-icons/ti"),d=require("react-icons/fa");function u(e,n,t,r){return new(t||(t=Promise))((function(o,i){function a(e){try{s(r.next(e))}catch(e){i(e)}}function l(e){try{s(r.throw(e))}catch(e){i(e)}}function s(e){var n;e.done?o(e.value):(n=e.value,n instanceof t?n:new t((function(e){e(n)}))).then(a,l)}s((r=r.apply(e,n||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;var p=[],m=[];!function(e,n){if(e&&"undefined"!=typeof document){var t,r=!0===n.prepend?"prepend":"append",o=!0===n.singleTag,i="string"==typeof n.container?document.querySelector(n.container):document.getElementsByTagName("head")[0];if(o){var a=p.indexOf(i);-1===a&&(a=p.push(i)-1,m[a]={}),t=m[a]&&m[a][r]?m[a][r]:m[a][r]=l()}else t=l();65279===e.charCodeAt(0)&&(e=e.substring(1)),t.styleSheet?t.styleSheet.cssText+=e:t.appendChild(document.createTextNode(e))}function l(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),n.attributes)for(var t=Object.keys(n.attributes),o=0;o<t.length;o++)e.setAttribute(t[o],n.attributes[t[o]]);var a="prepend"===r?"afterbegin":"beforeend";return i.insertAdjacentElement(a,e),e}}(":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",{});const h={default:{displayName:"Default",fragments:{edit:"rgb(42, 161, 152)"},styles:{container:{backgroundColor:"#f6f6f6",fontFamily:"monospace"},property:"#292929",bracket:{color:"rgb(0, 43, 54)",fontWeight:"bold"},itemCount:{color:"rgba(0, 0, 0, 0.3)",fontStyle:"italic"},string:"rgb(203, 75, 22)",number:"rgb(38, 139, 210)",boolean:"green",null:{color:"rgb(220, 50, 47)",fontVariant:"small-caps",fontWeight:"bold"},input:["#292929",{fontSize:"90%"}],inputHighlight:"#b3d8ff",error:{fontSize:"0.8em",color:"red",fontWeight:"bold"},iconCollection:"rgb(0, 43, 54)",iconEdit:"edit",iconDelete:"rgb(203, 75, 22)",iconAdd:"edit",iconCopy:"rgb(38, 139, 210)",iconOk:"green",iconCancel:"rgb(203, 75, 22)"}},githubDark:{displayName:"Github Dark",styles:{container:{backgroundColor:"#0d1117",color:"white"},property:"#E6EDF3",bracket:"#56d364",itemCount:"#8B949E",string:"#A5D6FF",number:"#D2A8FF",boolean:{color:"#FF7B72",fontSize:"90%",fontWeight:"bold"},null:"green",iconCollection:"#D2A8FF",iconEdit:"#D2A8FF",iconDelete:"rgb(203, 75, 22)",iconAdd:"rgb(203, 75, 22)",iconCopy:"#A5D6FF",iconOk:"#56d364",iconCancel:"rgb(203, 75, 22)"}},githubLight:{displayName:"Github Light",styles:{container:"white",property:"#1F2328",bracket:"#00802e",itemCount:"#8B949E",string:"#0A3069",number:"#953800",boolean:{color:"#CF222E",fontSize:"90%",fontWeight:"bold"},null:"#FF7B72",iconCollection:"#8250DF",iconEdit:"#8250DF",iconDelete:"rgb(203, 75, 22)",iconAdd:"#8250DF",iconCopy:"#57606A"}},monoDark:{displayName:"Black & White",fragments:{lightText:{color:"white"},midGrey:"#5c5c5c"},styles:{container:["lightText",{backgroundColor:"black"}],property:"lightText",bracket:"midGrey",itemCount:"#4a4a4a",string:"#a8a8a8",number:"#666666",boolean:{color:"#848484",fontStyle:"italic"},null:"#333333",iconCollection:"midGrey",iconEdit:"midGrey",iconDelete:"midGrey",iconAdd:"midGrey",iconCopy:"midGrey",iconOk:"midGrey",iconCancel:"midGrey"}},monoLight:{fragments:{midGrey:"#a3a3a3"},displayName:"White & Black",styles:{container:"white",property:"black",bracket:"midGrey",itemCount:"#b5b5b5",string:"#575757",number:"#999999",boolean:{color:"#7b7b7b",fontStyle:"italic"},null:"#cccccc",iconCollection:"midGrey",iconEdit:"midGrey",iconDelete:"midGrey",iconAdd:"midGrey",iconCopy:"midGrey",iconOk:"midGrey",iconCancel:"midGrey"}},candyWrapper:{displayName:"Candy Wrapper",fragments:{minty:{backgroundColor:"#F1FAEE"},pale:{color:"#A8DADC"},mid:{color:"#457B9D"},dark:{color:"#1D3557"},pop:{color:"#E63946"},darkBlue:{color:"#2B2D42"}},styles:{container:"minty",property:"pop",bracket:"dark",itemCount:"pale",string:"mid",number:["darkBlue",{fontSize:"85%"}],boolean:["mid",{fontStyle:"italic",fontWeight:"bold",fontSize:"80%"}],null:["#cccccc",{fontWeight:"bold"}],iconCollection:"#1D3557",iconEdit:"#457B9D",iconDelete:"#E63946",iconAdd:"#2B2D42",iconCopy:"#1D3557",iconCancel:"#E63946"}},psychedelic:{displayName:"Psychedelic",fragments:{minty:{backgroundColor:"#F1FAEE"},pale:{color:"#A8DADC"},mid:{color:"#457B9D"},dark:{color:"#1D3557"},pop:{color:"#E63946"},fluroYellow:"rgb(242, 228, 21)",fluroGreen:"rgb(68, 255, 62)",hotPink:"#f7379a"},styles:{container:{backgroundColor:"unset",background:"linear-gradient(90deg, hsla(333, 100%, 53%, 1) 0%, hsla(33, 94%, 57%, 1) 100%)",color:"black"},property:"black",bracket:"fluroYellow",itemCount:["pale",{opacity:.7}],string:"white",number:["#33d9ff",{fontSize:"90%",fontWeight:"bold"}],boolean:["fluroGreen",{fontWeight:"bold",fontSize:"80%"}],null:["black",{fontWeight:"bold",opacity:.3,backgroundColor:"rgb(255, 255, 255, 0.5)",padding:"0 0.4em",borderRadius:"0.4em"}],iconCollection:"fluroYellow",iconEdit:["black"],iconDelete:["white",{opacity:.5}],iconAdd:["white",{opacity:.5}],iconCopy:"rgb(32, 84, 242)",iconOk:"fluroGreen",iconCancel:"hotPink"}}},y={container:{},property:{},bracket:{},itemCount:{},string:{},number:{},boolean:{},null:{},input:{},inputHighlight:{},error:{},iconCollection:{},iconEdit:{},iconDelete:{},iconAdd:{},iconCopy:{},iconOk:{},iconCancel:{}},j=h.default,b={styles:y,setTheme:e=>{},icons:{},setIcons:()=>{}},g=n.createContext(b),f=({children:t})=>{const[r,o]=n.useState(y),[i,a]=n.useState({});return e.jsx(g.Provider,{value:{styles:r,setTheme:e=>o(x(e)),icons:i,setIcons:a},children:t})},v=()=>n.useContext(g),x=e=>{if("string"==typeof e)return E(h[e]);if(Array.isArray(e)){const[n,t]=e;return E(h[n],k(t)?{styles:t}:t)}return E(j,k(e)?{styles:e}:e)},E=(e,n={styles:y})=>{var t,r,o,i;const[a,l,s]=[j,e,n].map((e=>{const{fragments:n,styles:t}=e,r={};return Object.entries(t).forEach((([e,t])=>{const o=(Array.isArray(t)?t:[t]).reduce(((t,r)=>{var o;if("string"==typeof r){const i=null!==(o=null==n?void 0:n[r])&&void 0!==o?o:r;return"string"==typeof i?Object.assign(Object.assign({},t),{[C[e]]:i}):Object.assign(Object.assign({},t),i)}return Object.assign(Object.assign({},t),r)}),{});r[e]=o})),r})),c={};return Object.keys(j.styles).forEach((e=>{c[e]=Object.assign(Object.assign(Object.assign({},a[e]),l[e]),s[e])})),(null===(t=null==c?void 0:c.inputHighlight)||void 0===t?void 0:t.backgroundColor)&&document.documentElement.style.setProperty("--jer-highlight-color",null===(r=null==c?void 0:c.inputHighlight)||void 0===r?void 0:r.backgroundColor),(null===(o=null==c?void 0:c.iconCopy)||void 0===o?void 0:o.color)&&document.documentElement.style.setProperty("--jer-icon-copy-color",null===(i=null==c?void 0:c.iconCopy)||void 0===i?void 0:i.color),c},k=e=>!("styles"in e),C={container:"backgroundColor",property:"color",bracket:"color",itemCount:"color",string:"color",number:"color",boolean:"color",null:"color",input:"color",inputHighlight:"backgroundColor",error:"color",iconCollection:"color",iconEdit:"color",iconDelete:"color",iconAdd:"color",iconCopy:"color",iconOk:"color",iconCancel:"color"},w=({className:n,name:t,value:r,setValue:o,handleKeyPress:i})=>{const{styles:a}=v(),l="\n"===r.slice(-1)?r+".":r;return e.jsxs("div",{style:{display:"grid"},children:[e.jsx("textarea",{style:Object.assign({height:"auto",gridArea:"1 / 1 / 2 / 2",overflowY:"auto"},a.input),rows:1,className:n,name:t,value:r,onChange:e=>o(e.target.value),autoFocus:!0,onFocus:e=>{r.length<40&&e.target.select()},onKeyDown:i}),e.jsx("span",{className:n,style:Object.assign({visibility:"hidden",height:"auto",gridArea:"1 / 1 / 2 / 2",color:"red",opacity:.9,whiteSpace:"pre-wrap",overflow:"clip",border:"1px solid transparent"},a.input),children:l})]})},D="**INVALID_FUNCTION**",N=(e,n=200)=>e.length<n?e:`${e.slice(0,n-2).trim()}...`,O=({value:n,setValue:t,isEditing:r,path:o,setIsEditing:i,handleEdit:a,handleCancel:l,stringTruncate:s})=>{const{styles:c}=v();return r?e.jsx(w,{className:"jer-input-text",name:o.join("."),value:n,setValue:t,isEditing:r,handleKeyPress:e=>{"Enter"!==e.key||e.shiftKey?"Escape"===e.key&&l():a()}}):e.jsxs("div",{onDoubleClick:()=>i(!0),onClick:e=>{(e.getModifierState("Control")||e.getModifierState("Meta"))&&i(!0)},className:"jer-value-string",style:c.string,children:['"',(d=N(n,s),d.split("\n").map(((n,t,r)=>e.jsxs("span",{children:[n,t<r.length-1?e.jsx("br",{}):null]},t)))),'"']});var d},S=({value:n,setValue:t,isEditing:r,path:o,setIsEditing:i,handleEdit:a,handleCancel:l})=>{const{styles:s}=v();return r?e.jsx("input",{className:"jer-input-number",type:"text",name:o.join("."),value:n,onChange:e=>t(e.target.value.replace(/[^0-9.-]/g,"")),autoFocus:!0,onFocus:e=>e.target.select(),onKeyDown:e=>{"Enter"===e.key?a():"Escape"===e.key&&l()},style:{width:String(n).length/1.5+2+"em"}}):e.jsx("span",{onDoubleClick:()=>i(!0),className:"jer-value-number",style:s.number,children:n})},A=({value:t,setValue:r,isEditing:o,path:i,setIsEditing:a,handleEdit:l,handleCancel:s})=>{const{styles:c}=v();n.useEffect((()=>(o&&document.addEventListener("keydown",d),()=>document.removeEventListener("keydown",d))),[o]);const d=e=>{"Enter"===e.key?l():"Escape"===e.key&&s()};return o?e.jsx("input",{className:"jer-input-boolean",type:"checkbox",name:i.join("."),checked:t,onChange:()=>r(!t)}):e.jsx("span",{onDoubleClick:()=>a(!0),className:"jer-value-boolean",style:c.boolean,children:String(t)})},F=({value:t,isEditing:r,setIsEditing:o,handleEdit:i,handleCancel:a})=>{const{styles:l}=v();n.useEffect((()=>(r&&document.addEventListener("keydown",s),()=>document.removeEventListener("keydown",s))),[r]);const s=e=>{"Enter"===e.key?i():"Escape"===e.key&&a()};return r?e.jsx("div",{className:"jer-input-null",children:"null"}):e.jsx("div",{onDoubleClick:()=>o(!0),className:"jer-value-null",style:l.null,children:String(t)})},T=({value:t,translate:r,isEditing:o,handleEdit:i,handleCancel:a})=>{n.useEffect((()=>(o&&document.addEventListener("keydown",l),()=>document.removeEventListener("keydown",l))),[]);const l=e=>{"Enter"===e.key?i():"Escape"===e.key&&a()};return e.jsx("span",{className:"jer-value-object",children:`{${r("DEFAULT_NEW_KEY")}: "${t}" }`})},V=({value:t,isEditing:r,handleEdit:o,handleCancel:i})=>{n.useEffect((()=>(r&&document.addEventListener("keydown",a),()=>document.removeEventListener("keydown",a))),[]);const a=e=>{"Enter"===e.key?o():"Escape"===e.key&&i()};return e.jsx("span",{className:"jer-value-array",children:`[${null===t?"":t}]`})},I=({value:n})=>{let t="Error!";switch(typeof n){case"string":n===D&&(t="Function");break;case"undefined":t="Undefined";break;case"symbol":t="Symbol"}return e.jsx("span",{className:"jer-value-invalid",children:t})},L=({name:n,rotate:t})=>{var r,o,u,p,m,h,y;const{styles:j,icons:b}=v(),g={size:"1.4em",className:"jer-icon"};switch(n){case"add":return null!==(r=null==b?void 0:b.add)&&void 0!==r?r:e.jsx(a.BiPlusCircle,Object.assign({},g,{style:j.iconAdd}));case"edit":return null!==(o=null==b?void 0:b.edit)&&void 0!==o?o:e.jsx(a.BiEdit,Object.assign({},g,{style:j.iconEdit}));case"delete":return null!==(u=null==b?void 0:b.delete)&&void 0!==u?u:e.jsx(l.MdDeleteForever,Object.assign({},g,{style:j.iconDelete,size:"1.5em"}));case"copy":return null!==(p=null==b?void 0:b.copy)&&void 0!==p?p:e.jsx(i.HiOutlineClipboardCopy,Object.assign({},g,{style:j.iconCopy}));case"ok":return null!==(m=null==b?void 0:b.ok)&&void 0!==m?m:e.jsx(s.FiCheckCircle,Object.assign({},g,{style:Object.assign({fontSize:"90%"},j.iconOk)}));case"cancel":return null!==(h=null==b?void 0:b.cancel)&&void 0!==h?h:e.jsx(c.TiCancel,Object.assign({},g,{style:Object.assign({fontSize:"130%"},j.iconCancel)}));case"chevron":return null!==(y=null==b?void 0:b.chevron)&&void 0!==y?y:e.jsx(d.FaChevronDown,{className:"jer-accordion-icon"+(t?" jer-rotate-90":""),style:j.iconCollection});default:return e.jsx(e.Fragment,{})}},R=({startEdit:t,handleDelete:r,handleAdd:o,enableClipboard:i,type:a,data:l,path:s,name:c,translate:d})=>{const{styles:u}=v(),p=d("KEY_NEW"),[m,h]=n.useState(!1),[y,j]=n.useState(p);n.useEffect((()=>{m||j(p)}),[m]);return e.jsxs("div",{className:"jer-edit-buttons",style:m?{opacity:1}:void 0,children:[i&&e.jsx("div",{onClick:e=>{let n,t="value",r="";if(i){if(!0===(e.ctrlKey||e.metaKey))n=_(s),r=n,t="path";else n=l,r=a?JSON.stringify(l,null,2):String(n);navigator.clipboard.writeText(r)}"function"==typeof i&&i({value:n,stringValue:r,path:s,key:c,type:t})},className:"jer-copy-pulse",children:e.jsx(L,{name:"copy"})}),t&&e.jsx("div",{onClick:t,children:e.jsx(L,{name:"edit"})}),r&&e.jsx("div",{onClick:r,children:e.jsx(L,{name:"delete"})}),o&&e.jsx("div",{onClick:()=>{"object"===a?h(!0):o("")},children:e.jsx(L,{name:"add"})}),m&&o&&"object"===a&&e.jsxs(e.Fragment,{children:[e.jsx("input",{className:"jer-input-new-key",type:"text",name:"new-object-key",value:y,onChange:e=>j(e.target.value),autoFocus:!0,onFocus:e=>e.target.select(),onKeyDown:e=>{"Enter"===e.key&&o?(h(!1),o(y)):"Escape"===e.key&&h(!1)},style:Object.assign({},u.input)}),e.jsx(K,{onOk:()=>{y&&(h(!1),o(y))},onCancel:()=>{h(!1)}})]})]})},K=({onOk:n,onCancel:t})=>e.jsxs("div",{className:"jer-confirm-buttons",children:[e.jsx("div",{onClick:n,children:e.jsx(L,{name:"ok"})}),e.jsx("div",{onClick:t,children:e.jsx(L,{name:"cancel"})})]}),_=e=>e.reduce(((e,n)=>"number"==typeof n?`${e}[${n}]`:""===e?n:`${e}.${n}`),""),W=2500,z=["string","number","boolean","null","object","array"],G=(e=[],n)=>{const t=e.filter((({condition:e})=>e(n)));if(0===t.length)return{};const{element:r,props:o,hideKey:i=!1}=t[0];return{CustomNode:r,customNodeProps:o,hideKey:i}},P=({name:n,hideKey:t,children:r,indent:o})=>{const{styles:i}=v(),a=o?{marginLeft:o/2+"em"}:{};return e.jsx("div",{className:"jer-component jer-value-component",style:a,children:e.jsxs("div",{className:"jer-value-main-row",style:{flexWrap:n.length>10?"wrap":"nowrap"},children:[!t&&e.jsxs("label",{htmlFor:n,className:"jer-object-key",style:Object.assign(Object.assign({},i.property),{minWidth:`${Math.min(String(n).length+1,5)}ch`,flexShrink:n.length>10?1:0}),children:[n,":"," "]}),e.jsx("div",{className:"jer-value-and-buttons",style:{paddingLeft:t?0:void 0},children:r})]})})},M=t=>{const{data:r,parentData:o,name:i,path:a,onEdit:l,onDelete:s,enableClipboard:c,restrictEditFilter:d,restrictDeleteFilter:u,restrictTypeSelection:p,showLabel:m,stringTruncate:h,indent:y,translate:j,customNodeDefinitions:b}=t,{styles:g}=v(),[f,x]=n.useState(!1),[E,k]=n.useState(!1),[C,w]=n.useState("function"==typeof r?D:r),[N,O]=n.useState(null),[S,A]=n.useState(B(r));n.useEffect((()=>{w("function"==typeof r?D:r),A(B(r))}),[r,N]);const F=e=>{O(e),setTimeout((()=>O(null)),W),console.log("Error",e)},T=()=>{let e;switch(x(!1),S){case"object":e={[j("DEFAULT_NEW_KEY")]:C};break;case"array":e=null!==C?C:[];break;case"number":const n=Number(C);e=isNaN(n)?0:n;break;default:e=C}l(e,a).then((e=>{e&&F(e)}))},V=()=>{x(!1),k(!1),w(r),A(B(r))},I={key:i,path:a,level:a.length,value:r,size:null},L=n.useMemo((()=>!d(I)),[I]),_=n.useMemo((()=>!u(I)),[I]),M=!("number"==typeof a.slice(-1)[0])&&L&&_,U={value:C,parentData:o,setValue:w,isEditing:f,setIsEditing:L?()=>x(!0):()=>{},handleEdit:T,handleCancel:V,path:a,stringTruncate:h,translate:j},{CustomNode:Y,customNodeProps:J,hideKey:H}=G(b,{key:i,path:a,level:a.length,value:r,size:0}),X=[...b.filter((({showInTypesSelector:e=!1})=>e)).map((({name:e})=>e)),...z],Q=n.useMemo((()=>{if("boolean"==typeof p)return p?[]:X;if(Array.isArray(p))return p;const e=p(I);return"boolean"==typeof e?e?[]:X:e}),[I,p]);return Y?e.jsx(P,{name:i,hideKey:H,indent:y,children:e.jsx(Y,Object.assign({customProps:J},t))}):e.jsx("div",{className:"jer-component jer-value-component",style:{marginLeft:y/2+"em"},children:e.jsxs("div",{className:"jer-value-main-row",style:{flexWrap:i.length>10?"wrap":"nowrap"},children:[m&&!E&&e.jsxs("label",{htmlFor:a.join("."),className:"jer-object-key",style:Object.assign(Object.assign({},g.property),{minWidth:`${Math.min(String(i).length+1,5)}ch`,flexShrink:i.length>10?1:0}),onDoubleClick:()=>M&&k(!0),children:[i,":"," "]}),m&&E&&e.jsx("input",{className:"jer-object-key",type:"text",name:a.join("."),defaultValue:i,autoFocus:!0,onFocus:e=>e.target.select(),onKeyDown:e=>{"Enter"===e.key?(e=>{if(k(!1),!o)return;const n=a.slice(0,-1);if(!e)return;const t=Object.fromEntries(Object.entries(o).map((([n,t])=>n===i?[e,t]:[n,t])));l(t,n)})(e.target.value):"Escape"===e.key&&V()},style:{width:String(i).length/1.5+.5+"em"}}),e.jsxs("div",{className:"jer-value-and-buttons",children:[e.jsx("div",{className:"jer-input-component",children:$(S,U)}),f?e.jsx(K,{onOk:T,onCancel:V}):"invalid"!==S&&!N&&e.jsx(R,{startEdit:L?()=>x(!0):void 0,handleDelete:_?()=>{s(C,a).then((e=>{e&&F(e)}))}:void 0,data:r,enableClipboard:c,name:i,path:a,translate:j}),f&&Q.length>0&&e.jsxs("div",{className:"jer-select",children:[e.jsx("select",{name:`${i}-type-select`,className:"jer-type-select",onChange:e=>(e=>{const n=b.find((n=>n.name===e));n?l(n.defaultValue,a):(w(q(C,e)),A(e))})(e.target.value),value:S,children:Q.map((n=>e.jsx("option",{value:n,children:n},n)))}),e.jsx("span",{className:"focus"})]}),!f&&N&&e.jsx("span",{className:"jer-error-slug",style:g.error,children:N})]})]})})},B=e=>"string"==typeof e?"string":"number"==typeof e?"number":"boolean"==typeof e?"boolean":null===e?"null":"invalid",$=(n,t)=>{const r=t.value;switch(n){case"string":return e.jsx(O,Object.assign({},t,{value:r}));case"number":return e.jsx(S,Object.assign({},t,{value:r}));case"boolean":return e.jsx(A,Object.assign({},t,{value:r}));case"null":return e.jsx(F,Object.assign({},t));case"object":return e.jsx(T,Object.assign({},t,{value:r}));case"array":return e.jsx(V,Object.assign({},t));default:return e.jsx(I,Object.assign({},t))}},q=(e,n)=>{switch(n){case"string":default:return String(e);case"number":const n=Number(e);return isNaN(n)?0:n;case"boolean":return!!e;case"null":return null;case"object":return e;case"array":return[e]}},U=e=>null!==e&&"object"==typeof e,Y=t=>{var{data:r,path:o,name:i,parentData:a,showCollectionCount:l}=t,s=function(e,n){var t={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&n.indexOf(r)<0&&(t[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(r=Object.getOwnPropertySymbols(e);o<r.length;o++)n.indexOf(r[o])<0&&Object.prototype.propertyIsEnumerable.call(e,r[o])&&(t[r[o]]=e[r[o]])}return t}(t,["data","path","name","parentData","showCollectionCount"]);const{styles:c}=v(),{onEdit:d,onAdd:u,onDelete:p,restrictEditFilter:m,restrictDeleteFilter:h,restrictAddFilter:y,collapseFilter:j,enableClipboard:b,indent:g,keySort:f,showArrayIndices:x,defaultValue:E,translate:k,customNodeDefinitions:C}=s,[D,N]=n.useState(!1),[O,S]=n.useState(!1),[A,F]=n.useState(JSON.stringify(r,null,2)),[T,V]=n.useState(null),I=Object.keys(r).length,_={key:i,path:o,level:o.length,value:r,size:I},z=j(_),[B,$]=n.useState(z),q=n.useRef(!z),[J,H]=n.useState(!1);n.useEffect((()=>{F(JSON.stringify(r,null,2))}),[r]),n.useEffect((()=>{$(j(_))}),[j]);const X=Array.isArray(r)?"array":"object",Q="array"===X?{open:"[",close:"]"}:{open:"{",close:"}"},Z=getComputedStyle(document.documentElement).getPropertyValue("--jer-expand-transition-time"),ee=e=>{V(e),setTimeout((()=>V(null)),W),console.log("Error",e)},ne=()=>{try{const e=JSON.parse(A);N(!1),V(null),d(e,o).then((e=>{e&&ee(e)}))}catch(e){return V(k("ERROR_INVALID_JSON")),setTimeout((()=>V(null)),W),void console.log("Invalid JSON")}},te=o.length>0?()=>{p(r,o).then((e=>{e&&ee(e)}))}:void 0,re=()=>{N(!1),S(!1),V(null),F(JSON.stringify(r,null,2))},oe=n.useMemo((()=>!m(_)),[_]),ie=n.useMemo((()=>!h(_)),[_]),ae=n.useMemo((()=>!y(_)),[_]),le=null!==a&&oe&&ae&&ie,se="number"==typeof o.slice(-1)[0],ce=x||!se,de="when-closed"===l?B:l,ue=Object.entries(r).map((([e,n])=>["array"===X?Number(e):e,n]));f&&"object"===X&&ue.sort("function"==typeof f?(e,n)=>f(e[0],n[0]):void 0);const pe=JSON.stringify(r,null,2).split("\n").length,{CustomNode:me,customNodeProps:he,hideKey:ye}=G(C,{key:i,path:o,level:o.length,value:r,size:Object.keys(r).length});return e.jsx("div",{className:"jer-component jer-collection-component",style:{marginLeft:(0===o.length?0:g/2)+"em"},children:me?e.jsx(P,{name:i,hideKey:ye,children:e.jsx(me,Object.assign({data:r,path:o,name:i,parentData:a,customProps:he},s))}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"jer-collection-header-row",children:[e.jsx("div",{onClick:()=>{D||(H(!0),q.current=!0,$(!B),setTimeout((()=>H(!1)),500))},children:e.jsx(L,{name:"chevron",rotate:B})}),e.jsxs("div",{className:"jer-collection-name",children:[!O&&e.jsx("span",{style:c.property,onDoubleClick:()=>le&&S(!0),children:ce&&""!==i&&void 0!==i?`${i}:`:null}),O&&e.jsx("input",{className:"jer-collection-name",type:"text",name:o.join("."),defaultValue:i,autoFocus:!0,onFocus:e=>e.target.select(),onKeyDown:e=>{"Enter"===e.key?(e=>{if(S(!1),!a)return;const n=o.slice(0,-1);if(!e)return;const t=Object.fromEntries(Object.entries(a).map((([n,t])=>n===i?[e,t]:[n,t])));d(t,n)})(e.target.value):"Escape"===e.key&&re()},style:{width:String(i).length/1.5+.5+"em"}}),!D&&e.jsx("span",{className:"jer-brackets",style:c.bracket,children:Q.open})]}),!D&&l&&e.jsx("div",{className:"jer-collection-item-count"+(de?" jer-visible":" jer-hidden"),style:c.itemCount,children:1===I?k("ITEM_SINGLE",1):k("ITEMS_MULTIPLE",I)}),e.jsx("div",{className:"jer-brackets"+(B?" jer-visible":" jer-hidden"),style:c.bracket,children:Q.close}),!D&&e.jsx(R,{startEdit:oe?()=>{N(!0),$(!1)}:void 0,handleAdd:ae?e=>{if($(!1),"array"===X)u(E,[...o,r.length]).then((e=>{e&&ee(e)}));else{if(e in r)return void ee(k("ERROR_KEY_EXISTS"));u(E,[...o,e]).then((e=>{e&&ee(e)}))}}:void 0,handleDelete:ie?te:void 0,enableClipboard:b,type:X,data:r,name:i,path:o,translate:k})]}),e.jsxs("div",{className:"jer-collection-inner",style:{maxHeight:B?0:D?void 0:3*pe+"em",overflowY:B||J?"hidden":"visible",transition:`max-height ${Z}`},children:[D?e.jsx("div",{className:"jer-collection-text-edit",children:e.jsxs("div",{children:[e.jsx(w,{className:"jer-collection-text-area",name:o.join("."),value:A,setValue:F,isEditing:D,handleKeyPress:e=>{"Enter"===e.key&&(e.metaKey||e.shiftKey||e.ctrlKey)?ne():"Escape"===e.key&&re()}}),e.jsx("div",{className:"jer-collection-input-button-row",children:e.jsx(K,{onOk:ne,onCancel:re,isCollection:!0})})]})}):e.jsx(e.Fragment,{children:q.current?ue.map((([n,t])=>e.jsx("div",{className:"jer-collection-element",children:U(t)?e.jsx(Y,Object.assign({data:t,parentData:r,path:[...o,n],name:n,showCollectionCount:l},s),n):e.jsx(M,Object.assign({data:t,parentData:r,path:[...o,n],name:n},s,{showLabel:"object"===X||x}),n)},n))):null}),e.jsx("div",{className:D?"jer-collection-error-row":"jer-collection-error-row-edit",children:T&&e.jsx("span",{className:"jer-error-slug",style:c.error,children:T})}),e.jsx("div",{className:"jer-brackets",style:c.bracket,children:Q.close})]})]})})},J={ITEM_SINGLE:"{{count}} item",ITEMS_MULTIPLE:"{{count}} items",KEY_NEW:"Enter new key",ERROR_KEY_EXISTS:"Key already exists",ERROR_INVALID_JSON:"Invalid JSON",ERROR_UPDATE:"Update unsuccessful",ERROR_DELETE:"Delete unsuccessful",ERROR_ADD:"Adding node unsuccessful",DEFAULT_STRING:"New data!",DEFAULT_NEW_KEY:"key"},H=e=>(n,t)=>((e,n,t)=>{const r=n in e?e[n]:J[n];return void 0===t?r:null==r?void 0:r.replace("{{count}}",String(t))})(e,n,t),X=({data:t,rootName:r="root",onUpdate:o,onEdit:i=o,onDelete:a=o,onAdd:l=o,enableClipboard:s=!0,theme:c="default",icons:d,indent:p=4,collapse:m=!1,showCollectionCount:h=!0,restrictEdit:y=!1,restrictDelete:j=!1,restrictAdd:b=!1,restrictTypeSelection:g=!1,keySort:f=!1,showArrayIndices:x=!0,defaultValue:E=null,minWidth:k=250,maxWidth:C="min(600px, 90vw)",stringTruncate:w=250,translations:D={},className:N,customNodeDefinitions:O=[]})=>{const{styles:S,setTheme:A,setIcons:F}=v(),T=n.useCallback(Z(m),[m]),V=n.useCallback(H(D),[D]);n.useEffect((()=>{c&&A(c),d&&F(d)}),[c,d]);const I={name:r,onEdit:(e,n)=>u(void 0,void 0,void 0,(function*(){const{currentData:r,newData:o,currentValue:a,newValue:l}=Q(t,n,e,"update");if(i){const e=yield i({currentData:r,newData:o,currentValue:a,newValue:l,name:n.slice(-1)[0],path:n});return!1===e?V("ERROR_UPDATE"):e}})),onDelete:(e,n)=>u(void 0,void 0,void 0,(function*(){const{currentData:r,newData:o,currentValue:i,newValue:l}=Q(t,n,e,"delete");if(a){const e=yield a({currentData:r,newData:o,currentValue:i,newValue:l,name:n.slice(-1)[0],path:n});return!1===e?V("ERROR_DELETE"):e}})),onAdd:(e,n)=>u(void 0,void 0,void 0,(function*(){const{currentData:r,newData:o,currentValue:i,newValue:a}=Q(t,n,e,"add");if(l){const e=yield l({currentData:r,newData:o,currentValue:i,newValue:a,name:n.slice(-1)[0],path:n});return!1===e?V("ERROR_ADD"):e}})),showCollectionCount:h,collapseFilter:T,restrictEditFilter:Z(y),restrictDeleteFilter:Z(j),restrictAddFilter:Z(b),restrictTypeSelection:g,enableClipboard:s,keySort:f,showArrayIndices:x,indent:p,defaultValue:E,stringTruncate:w,translate:V,customNodeDefinitions:O,parentData:null};return S?e.jsx("div",{className:"jer-editor-container "+N,style:Object.assign(Object.assign({},S.container),{minWidth:k,maxWidth:C}),children:U(t)?e.jsx(Y,Object.assign({data:t,path:[]},I)):e.jsx(M,Object.assign({data:t,path:[],showLabel:!0},I))}):null},Q=(e,n,i,a)=>{if(0===n.length)return{currentData:e,newData:i,currentValue:e,newValue:i};const l="add"!==a?r(e,n):void 0;return{currentData:e,newData:t(o(e),n,i,{remove:"delete"===a}),currentValue:l,newValue:"update"===a?i:void 0}},Z=e=>"boolean"==typeof e?()=>e:"number"==typeof e?({level:n})=>n>=e:e;exports.JsonEditor=n=>e.jsx(f,{children:e.jsx(X,Object.assign({},n))}),exports.themes=h; |
/// <reference types="react" /> | ||
import React$1 from 'react'; | ||
import React$1 from 'react' | ||
declare const themes: { | ||
default: DefaultTheme; | ||
} & Record<string, Theme>; | ||
declare const themeableElements: readonly ["container", "property", "bracket", "itemCount", "string", "number", "boolean", "null", "input", "inputHighlight", "error", "iconCollection", "iconEdit", "iconDelete", "iconAdd", "iconCopy", "iconOk", "iconCancel"]; | ||
type ThemeableElement = (typeof themeableElements)[number]; | ||
type ThemeValue = string | React.CSSProperties | Array<string | React.CSSProperties>; | ||
type ThemeStyles = Record<ThemeableElement, ThemeValue>; | ||
type Fragments = Record<string, React.CSSProperties | string>; | ||
default: DefaultTheme | ||
} & Record<string, Theme> | ||
declare const themeableElements: readonly [ | ||
'container', | ||
'property', | ||
'bracket', | ||
'itemCount', | ||
'string', | ||
'number', | ||
'boolean', | ||
'null', | ||
'input', | ||
'inputHighlight', | ||
'error', | ||
'iconCollection', | ||
'iconEdit', | ||
'iconDelete', | ||
'iconAdd', | ||
'iconCopy', | ||
'iconOk', | ||
'iconCancel' | ||
] | ||
type ThemeableElement = (typeof themeableElements)[number] | ||
type ThemeValue = string | React.CSSProperties | Array<string | React.CSSProperties> | ||
type ThemeStyles = Record<ThemeableElement, ThemeValue> | ||
type Fragments = Record<string, React.CSSProperties | string> | ||
interface Theme { | ||
displayName?: string; | ||
fragments?: Fragments; | ||
styles: Partial<ThemeStyles>; | ||
displayName?: string | ||
fragments?: Fragments | ||
styles: Partial<ThemeStyles> | ||
} | ||
interface DefaultTheme extends Theme { | ||
displayName: 'Default'; | ||
styles: ThemeStyles; | ||
displayName: 'Default' | ||
styles: ThemeStyles | ||
} | ||
type ThemeName = keyof typeof themes; | ||
type ThemeInput = ThemeName | Theme | Partial<ThemeStyles> | [ThemeName, Theme | Partial<ThemeStyles>]; | ||
type ThemeName = keyof typeof themes | ||
type ThemeInput = | ||
| ThemeName | ||
| Theme | ||
| Partial<ThemeStyles> | ||
| [ThemeName, Theme | Partial<ThemeStyles>] | ||
declare const localisedStrings: { | ||
ITEM_SINGLE: string; | ||
ITEMS_MULTIPLE: string; | ||
KEY_NEW: string; | ||
ERROR_KEY_EXISTS: string; | ||
ERROR_INVALID_JSON: string; | ||
ERROR_UPDATE: string; | ||
ERROR_DELETE: string; | ||
ERROR_ADD: string; | ||
DEFAULT_STRING: string; | ||
DEFAULT_NEW_KEY: string; | ||
}; | ||
type LocalisedStrings = typeof localisedStrings; | ||
type TranslateFunction = (key: keyof LocalisedStrings, count?: number) => string; | ||
ITEM_SINGLE: string | ||
ITEMS_MULTIPLE: string | ||
KEY_NEW: string | ||
ERROR_KEY_EXISTS: string | ||
ERROR_INVALID_JSON: string | ||
ERROR_UPDATE: string | ||
ERROR_DELETE: string | ||
ERROR_ADD: string | ||
DEFAULT_STRING: string | ||
DEFAULT_NEW_KEY: string | ||
} | ||
type LocalisedStrings = typeof localisedStrings | ||
type TranslateFunction = (key: keyof LocalisedStrings, count?: number) => string | ||
interface JsonEditorProps { | ||
data: object; | ||
rootName?: string; | ||
onUpdate?: UpdateFunction; | ||
onEdit?: UpdateFunction; | ||
onDelete?: UpdateFunction; | ||
onAdd?: UpdateFunction; | ||
enableClipboard?: boolean | CopyFunction; | ||
theme?: ThemeInput; | ||
icons?: IconReplacements; | ||
className?: string; | ||
indent?: number; | ||
collapse?: boolean | number | FilterFunction; | ||
showCollectionCount?: boolean | 'when-closed'; | ||
restrictEdit?: boolean | FilterFunction; | ||
restrictDelete?: boolean | FilterFunction; | ||
restrictAdd?: boolean | FilterFunction; | ||
restrictTypeSelection?: boolean | DataType[] | TypeFilterFunction; | ||
keySort?: boolean | CompareFunction; | ||
showArrayIndices?: boolean; | ||
defaultValue?: unknown; | ||
minWidth?: string | number; | ||
maxWidth?: string | number; | ||
stringTruncate?: number; | ||
translations?: Partial<LocalisedStrings>; | ||
customNodeDefinitions?: CustomNodeDefinition[]; | ||
data: object | ||
rootName?: string | ||
onUpdate?: UpdateFunction | ||
onEdit?: UpdateFunction | ||
onDelete?: UpdateFunction | ||
onAdd?: UpdateFunction | ||
enableClipboard?: boolean | CopyFunction | ||
theme?: ThemeInput | ||
icons?: IconReplacements | ||
className?: string | ||
indent?: number | ||
collapse?: boolean | number | FilterFunction | ||
showCollectionCount?: boolean | 'when-closed' | ||
restrictEdit?: boolean | FilterFunction | ||
restrictDelete?: boolean | FilterFunction | ||
restrictAdd?: boolean | FilterFunction | ||
restrictTypeSelection?: boolean | DataType[] | TypeFilterFunction | ||
keySort?: boolean | CompareFunction | ||
showArrayIndices?: boolean | ||
defaultValue?: unknown | ||
minWidth?: string | number | ||
maxWidth?: string | number | ||
stringTruncate?: number | ||
translations?: Partial<LocalisedStrings> | ||
customNodeDefinitions?: CustomNodeDefinition[] | ||
} | ||
declare const DataTypes: readonly ["string", "number", "boolean", "null", "object", "array"]; | ||
type DataType = (typeof DataTypes)[number] | 'invalid'; | ||
type CollectionKey = string | number; | ||
type CollectionData = object | unknown[]; | ||
type ErrorString = string; | ||
declare const DataTypes: readonly ['string', 'number', 'boolean', 'null', 'object', 'array'] | ||
type DataType = (typeof DataTypes)[number] | 'invalid' | ||
type CollectionKey = string | number | ||
type CollectionData = object | unknown[] | ||
type ErrorString = string | ||
interface IconReplacements { | ||
add?: JSX.Element; | ||
edit?: JSX.Element; | ||
delete?: JSX.Element; | ||
copy?: JSX.Element; | ||
ok?: JSX.Element; | ||
cancel?: JSX.Element; | ||
chevron?: JSX.Element; | ||
add?: JSX.Element | ||
edit?: JSX.Element | ||
delete?: JSX.Element | ||
copy?: JSX.Element | ||
ok?: JSX.Element | ||
cancel?: JSX.Element | ||
chevron?: JSX.Element | ||
} | ||
type UpdateFunction = (props: { | ||
newData: object; | ||
currentData: object; | ||
newValue: unknown; | ||
currentValue: unknown; | ||
name: CollectionKey; | ||
path: CollectionKey[]; | ||
}) => void | ErrorString | false; | ||
newData: object | ||
currentData: object | ||
newValue: unknown | ||
currentValue: unknown | ||
name: CollectionKey | ||
path: CollectionKey[] | ||
}) => void | ErrorString | false | ||
interface FilterProps { | ||
key: CollectionKey; | ||
path: CollectionKey[]; | ||
level: number; | ||
value: unknown; | ||
size: number | null; | ||
key: CollectionKey | ||
path: CollectionKey[] | ||
level: number | ||
value: unknown | ||
size: number | null | ||
} | ||
type FilterFunction = (input: FilterProps) => boolean; | ||
type TypeFilterFunction = (input: FilterProps) => boolean | DataType[]; | ||
type CopyType = 'path' | 'value'; | ||
type FilterFunction = (input: FilterProps) => boolean | ||
type TypeFilterFunction = (input: FilterProps) => boolean | DataType[] | ||
type CopyType = 'path' | 'value' | ||
type CopyFunction = (input: { | ||
key: CollectionKey; | ||
path: CollectionKey[]; | ||
value: unknown; | ||
stringValue: string; | ||
type: CopyType; | ||
}) => void; | ||
type CompareFunction = (a: string, b: string) => number; | ||
type OnChangeFunction = (value: unknown, path: (string | number)[]) => Promise<string | void>; | ||
key: CollectionKey | ||
path: CollectionKey[] | ||
value: unknown | ||
stringValue: string | ||
type: CopyType | ||
}) => void | ||
type CompareFunction = (a: string, b: string) => number | ||
type OnChangeFunction = (value: unknown, path: (string | number)[]) => Promise<string | void> | ||
interface BaseNodeProps { | ||
data: unknown; | ||
parentData: CollectionData | null; | ||
path: CollectionKey[]; | ||
name: CollectionKey; | ||
onEdit: OnChangeFunction; | ||
onDelete: OnChangeFunction; | ||
enableClipboard: boolean | CopyFunction; | ||
restrictEditFilter: FilterFunction; | ||
restrictDeleteFilter: FilterFunction; | ||
restrictAddFilter: FilterFunction; | ||
restrictTypeSelection: boolean | DataType[] | TypeFilterFunction; | ||
stringTruncate: number; | ||
indent: number; | ||
translate: TranslateFunction; | ||
customNodeDefinitions: CustomNodeDefinition[]; | ||
data: unknown | ||
parentData: CollectionData | null | ||
path: CollectionKey[] | ||
name: CollectionKey | ||
onEdit: OnChangeFunction | ||
onDelete: OnChangeFunction | ||
enableClipboard: boolean | CopyFunction | ||
restrictEditFilter: FilterFunction | ||
restrictDeleteFilter: FilterFunction | ||
restrictAddFilter: FilterFunction | ||
restrictTypeSelection: boolean | DataType[] | TypeFilterFunction | ||
stringTruncate: number | ||
indent: number | ||
translate: TranslateFunction | ||
customNodeDefinitions: CustomNodeDefinition[] | ||
} | ||
interface CustomNodeProps extends BaseNodeProps { | ||
customProps?: Record<string, unknown>; | ||
parentData: CollectionData | null; | ||
customProps?: Record<string, unknown> | ||
parentData: CollectionData | null | ||
} | ||
interface CustomNodeDefinition { | ||
condition: FilterFunction; | ||
element: React$1.FC<CustomNodeProps>; | ||
name: string; | ||
props?: Record<string, unknown>; | ||
hideKey?: boolean; | ||
defaultValue: unknown; | ||
showInTypesSelector?: boolean; | ||
condition: FilterFunction | ||
element: React$1.FC<CustomNodeProps> | ||
name: string | ||
props?: Record<string, unknown> | ||
hideKey?: boolean | ||
defaultValue: unknown | ||
showInTypesSelector?: boolean | ||
} | ||
declare const JsonEditor: React$1.FC<JsonEditorProps>; | ||
declare const JsonEditor: React$1.FC<JsonEditorProps> | ||
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 }; | ||
export { | ||
CompareFunction, | ||
CopyFunction, | ||
FilterFunction, | ||
IconReplacements, | ||
JsonEditor, | ||
JsonEditorProps, | ||
LocalisedStrings, | ||
Theme, | ||
ThemeInput, | ||
ThemeName, | ||
TranslateFunction, | ||
UpdateFunction, | ||
themes, | ||
} |
@@ -1,1078 +0,1 @@ | ||
import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; | ||
import { createContext, useState, useContext, useEffect, useMemo, useRef, useCallback } from 'react'; | ||
import assign from 'object-property-assigner'; | ||
import extract from 'object-property-extractor'; | ||
import clone from 'just-clone'; | ||
import { HiOutlineClipboardCopy } from 'react-icons/hi'; | ||
import { BiEdit, BiPlusCircle } from 'react-icons/bi'; | ||
import { MdDeleteForever } from 'react-icons/md'; | ||
import { FiCheckCircle } from 'react-icons/fi'; | ||
import { TiCancel } from 'react-icons/ti'; | ||
import { FaChevronDown } from 'react-icons/fa'; | ||
/****************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
/* global Reflect, Promise, SuppressedError, Symbol */ | ||
function __rest(s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
} | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
} | ||
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { | ||
var e = new Error(message); | ||
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; | ||
}; | ||
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}} | ||
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"; | ||
n(css,{}); | ||
const defaultTheme$1 = { | ||
displayName: 'Default', | ||
fragments: { edit: 'rgb(42, 161, 152)' }, | ||
styles: { | ||
container: { | ||
backgroundColor: '#f6f6f6', | ||
fontFamily: 'monospace', | ||
}, | ||
property: '#292929', | ||
bracket: { color: 'rgb(0, 43, 54)', fontWeight: 'bold' }, | ||
itemCount: { color: 'rgba(0, 0, 0, 0.3)', fontStyle: 'italic' }, | ||
string: 'rgb(203, 75, 22)', | ||
number: 'rgb(38, 139, 210)', | ||
boolean: 'green', | ||
null: { color: 'rgb(220, 50, 47)', fontVariant: 'small-caps', fontWeight: 'bold' }, | ||
input: ['#292929', { fontSize: '90%' }], | ||
inputHighlight: '#b3d8ff', | ||
error: { fontSize: '0.8em', color: 'red', fontWeight: 'bold' }, | ||
iconCollection: 'rgb(0, 43, 54)', | ||
iconEdit: 'edit', | ||
iconDelete: 'rgb(203, 75, 22)', | ||
iconAdd: 'edit', | ||
iconCopy: 'rgb(38, 139, 210)', | ||
iconOk: 'green', | ||
iconCancel: 'rgb(203, 75, 22)', | ||
}, | ||
}; | ||
const themes = { | ||
default: defaultTheme$1, | ||
githubDark: { | ||
displayName: 'Github Dark', | ||
styles: { | ||
container: { | ||
backgroundColor: '#0d1117', | ||
color: 'white', | ||
}, | ||
property: '#E6EDF3', | ||
bracket: '#56d364', | ||
itemCount: '#8B949E', | ||
string: '#A5D6FF', | ||
number: '#D2A8FF', | ||
boolean: { color: '#FF7B72', fontSize: '90%', fontWeight: 'bold' }, | ||
null: 'green', | ||
iconCollection: '#D2A8FF', | ||
iconEdit: '#D2A8FF', | ||
iconDelete: 'rgb(203, 75, 22)', | ||
iconAdd: 'rgb(203, 75, 22)', | ||
iconCopy: '#A5D6FF', | ||
iconOk: '#56d364', | ||
iconCancel: 'rgb(203, 75, 22)', | ||
}, | ||
}, | ||
githubLight: { | ||
displayName: 'Github Light', | ||
styles: { | ||
container: 'white', | ||
property: '#1F2328', | ||
bracket: '#00802e', | ||
itemCount: '#8B949E', | ||
string: '#0A3069', | ||
number: '#953800', | ||
boolean: { color: '#CF222E', fontSize: '90%', fontWeight: 'bold' }, | ||
null: '#FF7B72', | ||
iconCollection: '#8250DF', | ||
iconEdit: '#8250DF', | ||
iconDelete: 'rgb(203, 75, 22)', | ||
iconAdd: '#8250DF', | ||
iconCopy: '#57606A', | ||
}, | ||
}, | ||
monoDark: { | ||
displayName: 'Black & White', | ||
fragments: { | ||
lightText: { color: 'white' }, | ||
midGrey: '#5c5c5c', | ||
}, | ||
styles: { | ||
container: ['lightText', { backgroundColor: 'black' }], | ||
property: 'lightText', | ||
bracket: 'midGrey', | ||
itemCount: '#4a4a4a', | ||
string: '#a8a8a8', | ||
number: '#666666', | ||
boolean: { color: '#848484', fontStyle: 'italic' }, | ||
null: '#333333', | ||
iconCollection: 'midGrey', | ||
iconEdit: 'midGrey', | ||
iconDelete: 'midGrey', | ||
iconAdd: 'midGrey', | ||
iconCopy: 'midGrey', | ||
iconOk: 'midGrey', | ||
iconCancel: 'midGrey', | ||
}, | ||
}, | ||
monoLight: { | ||
fragments: { midGrey: '#a3a3a3' }, | ||
displayName: 'White & Black', | ||
styles: { | ||
container: 'white', | ||
property: 'black', | ||
bracket: 'midGrey', | ||
itemCount: '#b5b5b5', | ||
string: '#575757', | ||
number: '#999999', | ||
boolean: { color: '#7b7b7b', fontStyle: 'italic' }, | ||
null: '#cccccc', | ||
iconCollection: 'midGrey', | ||
iconEdit: 'midGrey', | ||
iconDelete: 'midGrey', | ||
iconAdd: 'midGrey', | ||
iconCopy: 'midGrey', | ||
iconOk: 'midGrey', | ||
iconCancel: 'midGrey', | ||
}, | ||
}, | ||
candyWrapper: { | ||
displayName: 'Candy Wrapper', | ||
fragments: { | ||
minty: { backgroundColor: '#F1FAEE' }, | ||
pale: { color: '#A8DADC' }, | ||
mid: { color: '#457B9D' }, | ||
dark: { color: '#1D3557' }, | ||
pop: { color: '#E63946' }, | ||
darkBlue: { color: '#2B2D42' }, | ||
}, | ||
styles: { | ||
container: 'minty', | ||
property: 'pop', | ||
bracket: 'dark', | ||
itemCount: 'pale', | ||
string: 'mid', | ||
number: ['darkBlue', { fontSize: '85%' }], | ||
boolean: ['mid', { fontStyle: 'italic', fontWeight: 'bold', fontSize: '80%' }], | ||
null: ['#cccccc', { fontWeight: 'bold' }], | ||
iconCollection: '#1D3557', | ||
iconEdit: '#457B9D', | ||
iconDelete: '#E63946', | ||
iconAdd: '#2B2D42', | ||
iconCopy: '#1D3557', | ||
iconCancel: '#E63946', | ||
}, | ||
}, | ||
psychedelic: { | ||
displayName: 'Psychedelic', | ||
fragments: { | ||
minty: { | ||
backgroundColor: '#F1FAEE', | ||
}, | ||
pale: { | ||
color: '#A8DADC', | ||
}, | ||
mid: { | ||
color: '#457B9D', | ||
}, | ||
dark: { | ||
color: '#1D3557', | ||
}, | ||
pop: { | ||
color: '#E63946', | ||
}, | ||
fluroYellow: 'rgb(242, 228, 21)', | ||
fluroGreen: 'rgb(68, 255, 62)', | ||
hotPink: '#f7379a', | ||
}, | ||
styles: { | ||
container: { | ||
backgroundColor: 'unset', | ||
background: 'linear-gradient(90deg, hsla(333, 100%, 53%, 1) 0%, hsla(33, 94%, 57%, 1) 100%)', | ||
color: 'black', | ||
}, | ||
property: 'black', | ||
bracket: 'fluroYellow', | ||
itemCount: [ | ||
'pale', | ||
{ | ||
opacity: 0.7, | ||
}, | ||
], | ||
string: 'white', | ||
number: [ | ||
'#33d9ff', | ||
{ | ||
fontSize: '90%', | ||
fontWeight: 'bold', | ||
}, | ||
], | ||
boolean: [ | ||
'fluroGreen', | ||
{ | ||
fontWeight: 'bold', | ||
fontSize: '80%', | ||
}, | ||
], | ||
null: [ | ||
'black', | ||
{ | ||
fontWeight: 'bold', | ||
opacity: 0.3, | ||
backgroundColor: 'rgb(255, 255, 255, 0.5)', | ||
padding: '0 0.4em', | ||
borderRadius: '0.4em', | ||
}, | ||
], | ||
iconCollection: 'fluroYellow', | ||
iconEdit: ['black'], | ||
iconDelete: [ | ||
'white', | ||
{ | ||
opacity: 0.5, | ||
}, | ||
], | ||
iconAdd: [ | ||
'white', | ||
{ | ||
opacity: 0.5, | ||
}, | ||
], | ||
iconCopy: 'rgb(32, 84, 242)', | ||
iconOk: 'fluroGreen', | ||
iconCancel: 'hotPink', | ||
}, | ||
}, | ||
}; | ||
const emptyStyleObject = { | ||
container: {}, | ||
property: {}, | ||
bracket: {}, | ||
itemCount: {}, | ||
string: {}, | ||
number: {}, | ||
boolean: {}, | ||
null: {}, | ||
input: {}, | ||
inputHighlight: {}, | ||
error: {}, | ||
iconCollection: {}, | ||
iconEdit: {}, | ||
iconDelete: {}, | ||
iconAdd: {}, | ||
iconCopy: {}, | ||
iconOk: {}, | ||
iconCancel: {}, | ||
}; | ||
const defaultTheme = themes.default; | ||
const initialContext = { | ||
styles: emptyStyleObject, | ||
setTheme: (_) => { }, | ||
icons: {}, | ||
setIcons: () => { }, | ||
}; | ||
const ThemeProviderContext = createContext(initialContext); | ||
const ThemeProvider = ({ children }) => { | ||
const [styles, setStyles] = useState(emptyStyleObject); | ||
const [icons, setIcons] = useState({}); | ||
const setTheme = (theme) => setStyles(compileStyles(theme)); | ||
return (jsx(ThemeProviderContext.Provider, { value: { styles, setTheme, icons, setIcons }, children: children })); | ||
}; | ||
const useTheme = () => useContext(ThemeProviderContext); | ||
const compileStyles = (themeInput) => { | ||
if (typeof themeInput === 'string') | ||
return buildStyleObject(themes[themeInput]); | ||
if (Array.isArray(themeInput)) { | ||
const [name, overrides] = themeInput; | ||
return buildStyleObject(themes[name], isStyleObject(overrides) ? { styles: overrides } : overrides); | ||
} | ||
return buildStyleObject(defaultTheme, isStyleObject(themeInput) ? { styles: themeInput } : themeInput); | ||
}; | ||
const buildStyleObject = (baseTheme, overrides = { styles: emptyStyleObject }) => { | ||
var _a, _b, _c, _d; | ||
const [defaultStyles, baseStyles, overrideStyles] = [defaultTheme, baseTheme, overrides].map((theme) => { | ||
const { fragments, styles } = theme; | ||
const compiledStyles = {}; | ||
Object.entries(styles).forEach(([key, value]) => { | ||
const elements = Array.isArray(value) ? value : [value]; | ||
const cssStyles = elements.reduce((acc, curr) => { | ||
var _a; | ||
if (typeof curr === 'string') { | ||
const style = (_a = fragments === null || fragments === void 0 ? void 0 : fragments[curr]) !== null && _a !== void 0 ? _a : curr; | ||
switch (typeof style) { | ||
case 'string': | ||
return Object.assign(Object.assign({}, acc), { [defaultStyleProperties[key]]: style }); | ||
default: | ||
return Object.assign(Object.assign({}, acc), style); | ||
} | ||
} | ||
else | ||
return Object.assign(Object.assign({}, acc), curr); | ||
}, {}); | ||
compiledStyles[key] = cssStyles; | ||
}); | ||
return compiledStyles; | ||
}); | ||
const finalStyles = {}; | ||
Object.keys(defaultTheme.styles).forEach((key) => { | ||
finalStyles[key] = Object.assign(Object.assign(Object.assign({}, defaultStyles[key]), baseStyles[key]), overrideStyles[key]); | ||
}); | ||
if ((_a = finalStyles === null || finalStyles === void 0 ? void 0 : finalStyles.inputHighlight) === null || _a === void 0 ? void 0 : _a.backgroundColor) | ||
document.documentElement.style.setProperty('--jer-highlight-color', (_b = finalStyles === null || finalStyles === void 0 ? void 0 : finalStyles.inputHighlight) === null || _b === void 0 ? void 0 : _b.backgroundColor); | ||
if ((_c = finalStyles === null || finalStyles === void 0 ? void 0 : finalStyles.iconCopy) === null || _c === void 0 ? void 0 : _c.color) | ||
document.documentElement.style.setProperty('--jer-icon-copy-color', (_d = finalStyles === null || finalStyles === void 0 ? void 0 : finalStyles.iconCopy) === null || _d === void 0 ? void 0 : _d.color); | ||
return finalStyles; | ||
}; | ||
const isStyleObject = (overrideObject) => { | ||
return !('styles' in overrideObject); | ||
}; | ||
const defaultStyleProperties = { | ||
container: 'backgroundColor', | ||
property: 'color', | ||
bracket: 'color', | ||
itemCount: 'color', | ||
string: 'color', | ||
number: 'color', | ||
boolean: 'color', | ||
null: 'color', | ||
input: 'color', | ||
inputHighlight: 'backgroundColor', | ||
error: 'color', | ||
iconCollection: 'color', | ||
iconEdit: 'color', | ||
iconDelete: 'color', | ||
iconAdd: 'color', | ||
iconCopy: 'color', | ||
iconOk: 'color', | ||
iconCancel: 'color', | ||
}; | ||
const AutogrowTextArea = ({ className, name, value, setValue, handleKeyPress, }) => { | ||
const { styles } = useTheme(); | ||
const dummyValue = value.slice(-1) === '\n' ? value + '.' : value; | ||
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) => { | ||
if (value.length < 40) | ||
e.target.select(); | ||
}, 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 })] })); | ||
}; | ||
const INVALID_FUNCTION_STRING = '**INVALID_FUNCTION**'; | ||
const truncate = (string, length = 200) => string.length < length ? string : `${string.slice(0, length - 2).trim()}...`; | ||
const StringValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, stringTruncate, }) => { | ||
const { styles } = useTheme(); | ||
const handleKeyPress = (e) => { | ||
if (e.key === 'Enter' && !e.shiftKey) | ||
handleEdit(); | ||
else if (e.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
const breakString = (text) => text.split('\n').map((line, index, arr) => (jsxs("span", { children: [line, index < arr.length - 1 ? jsx("br", {}) : null] }, index))); | ||
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) => { | ||
if (e.getModifierState('Control') || e.getModifierState('Meta')) | ||
setIsEditing(true); | ||
}, className: "jer-value-string", style: styles.string, children: ["\"", breakString(truncate(value, stringTruncate)), "\""] })); | ||
}; | ||
const NumberValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, }) => { | ||
const { styles } = useTheme(); | ||
const handleKeyPress = (e) => { | ||
if (e.key === 'Enter') | ||
handleEdit(); | ||
else if (e.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
const validateNumber = (input) => { | ||
return input.replace(/[^0-9.-]/g, ''); | ||
}; | ||
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 })); | ||
}; | ||
const BooleanValue = ({ value, setValue, isEditing, path, setIsEditing, handleEdit, handleCancel, }) => { | ||
const { styles } = useTheme(); | ||
useEffect(() => { | ||
if (isEditing) | ||
document.addEventListener('keydown', listenForSubmit); | ||
return () => document.removeEventListener('keydown', listenForSubmit); | ||
}, [isEditing]); | ||
const listenForSubmit = (event) => { | ||
if (event.key === 'Enter') { | ||
handleEdit(); | ||
} | ||
else if (event.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
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) })); | ||
}; | ||
const NullValue = ({ value, isEditing, setIsEditing, handleEdit, handleCancel, }) => { | ||
const { styles } = useTheme(); | ||
useEffect(() => { | ||
if (isEditing) | ||
document.addEventListener('keydown', listenForSubmit); | ||
return () => document.removeEventListener('keydown', listenForSubmit); | ||
}, [isEditing]); | ||
const listenForSubmit = (event) => { | ||
if (event.key === 'Enter') { | ||
handleEdit(); | ||
} | ||
else if (event.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
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) })); | ||
}; | ||
const ObjectValue = ({ value, translate, isEditing, handleEdit, handleCancel, }) => { | ||
useEffect(() => { | ||
if (isEditing) | ||
document.addEventListener('keydown', listenForSubmit); | ||
return () => document.removeEventListener('keydown', listenForSubmit); | ||
}, []); | ||
const listenForSubmit = (event) => { | ||
if (event.key === 'Enter') { | ||
handleEdit(); | ||
} | ||
else if (event.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
return (jsx("span", { className: "jer-value-object", children: `{${translate('DEFAULT_NEW_KEY')}: "${value}" }` })); | ||
}; | ||
const ArrayValue = ({ value, isEditing, handleEdit, handleCancel, }) => { | ||
useEffect(() => { | ||
if (isEditing) | ||
document.addEventListener('keydown', listenForSubmit); | ||
return () => document.removeEventListener('keydown', listenForSubmit); | ||
}, []); | ||
const listenForSubmit = (event) => { | ||
if (event.key === 'Enter') { | ||
handleEdit(); | ||
} | ||
else if (event.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
return jsx("span", { className: "jer-value-array", children: `[${value === null ? '' : value}]` }); | ||
}; | ||
const InvalidValue = ({ value }) => { | ||
let message = 'Error!'; | ||
switch (typeof value) { | ||
case 'string': | ||
if (value === INVALID_FUNCTION_STRING) | ||
message = 'Function'; | ||
break; | ||
case 'undefined': | ||
message = 'Undefined'; | ||
break; | ||
case 'symbol': | ||
message = 'Symbol'; | ||
break; | ||
} | ||
return jsx("span", { className: "jer-value-invalid", children: message }); | ||
}; | ||
const Icon = ({ name, rotate }) => { | ||
var _a, _b, _c, _d, _e, _f, _g; | ||
const { styles, icons } = useTheme(); | ||
const commonProps = { size: '1.4em', className: 'jer-icon' }; | ||
switch (name) { | ||
case 'add': | ||
return (_a = icons === null || icons === void 0 ? void 0 : icons.add) !== null && _a !== void 0 ? _a : jsx(BiPlusCircle, Object.assign({}, commonProps, { style: styles.iconAdd })); | ||
case 'edit': | ||
return (_b = icons === null || icons === void 0 ? void 0 : icons.edit) !== null && _b !== void 0 ? _b : jsx(BiEdit, Object.assign({}, commonProps, { style: styles.iconEdit })); | ||
case 'delete': | ||
return ((_c = icons === null || icons === void 0 ? void 0 : icons.delete) !== null && _c !== void 0 ? _c : jsx(MdDeleteForever, Object.assign({}, commonProps, { style: styles.iconDelete, size: "1.5em" }))); | ||
case 'copy': | ||
return (_d = icons === null || icons === void 0 ? void 0 : icons.copy) !== null && _d !== void 0 ? _d : jsx(HiOutlineClipboardCopy, Object.assign({}, commonProps, { style: styles.iconCopy })); | ||
case 'ok': | ||
return ((_e = icons === null || icons === void 0 ? void 0 : icons.ok) !== null && _e !== void 0 ? _e : (jsx(FiCheckCircle, Object.assign({}, commonProps, { style: Object.assign({ fontSize: '90%' }, styles.iconOk) })))); | ||
case 'cancel': | ||
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) })))); | ||
case 'chevron': | ||
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 }))); | ||
default: | ||
return jsx(Fragment, {}); | ||
} | ||
}; | ||
const EditButtons = ({ startEdit, handleDelete, handleAdd, enableClipboard, type, data, path, name, translate, }) => { | ||
const { styles } = useTheme(); | ||
const NEW_KEY_PROMPT = translate('KEY_NEW'); | ||
const [isAdding, setIsAdding] = useState(false); | ||
const [newKey, setNewKey] = useState(NEW_KEY_PROMPT); | ||
useEffect(() => { | ||
if (!isAdding) | ||
setNewKey(NEW_KEY_PROMPT); | ||
}, [isAdding]); | ||
const handleKeyPress = (e) => { | ||
if (e.key === 'Enter' && handleAdd) { | ||
setIsAdding(false); | ||
handleAdd(newKey); | ||
} | ||
else if (e.key === 'Escape') | ||
setIsAdding(false); | ||
}; | ||
const handleCopy = (e) => { | ||
let copyType = 'value'; | ||
let value; | ||
let stringValue = ''; | ||
if (enableClipboard) { | ||
switch (e.ctrlKey || e.metaKey) { | ||
case true: | ||
value = stringifyPath(path); | ||
stringValue = value; | ||
copyType = 'path'; | ||
break; | ||
default: | ||
value = data; | ||
stringValue = type ? JSON.stringify(data, null, 2) : String(value); | ||
} | ||
navigator.clipboard.writeText(stringValue); | ||
} | ||
if (typeof enableClipboard === 'function') | ||
enableClipboard({ value, stringValue, path, key: name, type: copyType }); | ||
}; | ||
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: () => { | ||
if (type === 'object') | ||
setIsAdding(true); | ||
else | ||
handleAdd(''); | ||
}, 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: () => { | ||
if (!!newKey) { | ||
setIsAdding(false); | ||
handleAdd(newKey); | ||
} | ||
}, onCancel: () => { | ||
setIsAdding(false); | ||
} })] }))] })); | ||
}; | ||
const InputButtons = ({ onOk, onCancel }) => { | ||
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" }) })] })); | ||
}; | ||
const stringifyPath = (path) => path.reduce((str, part) => { | ||
if (typeof part === 'number') | ||
return `${str}[${part}]`; | ||
else | ||
return str === '' ? part : `${str}.${part}`; | ||
}, ''); | ||
const ERROR_DISPLAY_TIME = 2500; | ||
const ValueDataTypes = ['string', 'number', 'boolean', 'null']; | ||
const CollectionDataTypes = ['object', 'array']; | ||
const DataTypes = [...ValueDataTypes, ...CollectionDataTypes]; | ||
const getCustomNode = (customNodeDefinitions = [], filterProps) => { | ||
const matchingDefinitions = customNodeDefinitions.filter(({ condition }) => condition(filterProps)); | ||
if (matchingDefinitions.length === 0) | ||
return {}; | ||
const { element, props, hideKey = false } = matchingDefinitions[0]; | ||
return { CustomNode: element, customNodeProps: props, hideKey }; | ||
}; | ||
const CustomNodeWrapper = ({ name, hideKey, children, indent, }) => { | ||
const { styles } = useTheme(); | ||
const indentStyle = indent ? { marginLeft: `${indent / 2}em` } : {}; | ||
return (jsx("div", { className: "jer-component jer-value-component", style: indentStyle, children: jsxs("div", { className: "jer-value-main-row", style: { | ||
flexWrap: name.length > 10 ? 'wrap' : 'nowrap', | ||
}, 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 })] }) })); | ||
}; | ||
const ValueNodeWrapper = (props) => { | ||
const { data, parentData, name, path, onEdit, onDelete, enableClipboard, restrictEditFilter, restrictDeleteFilter, restrictTypeSelection, showLabel, stringTruncate, indent, translate, customNodeDefinitions, } = props; | ||
const { styles } = useTheme(); | ||
const [isEditing, setIsEditing] = useState(false); | ||
const [isEditingKey, setIsEditingKey] = useState(false); | ||
const [value, setValue] = useState(typeof data === 'function' ? INVALID_FUNCTION_STRING : data); | ||
const [error, setError] = useState(null); | ||
const [dataType, setDataType] = useState(getDataType(data)); | ||
useEffect(() => { | ||
setValue(typeof data === 'function' ? INVALID_FUNCTION_STRING : data); | ||
setDataType(getDataType(data)); | ||
}, [data, error]); | ||
const handleChangeDataType = (type) => { | ||
const customNode = customNodeDefinitions.find((customNode) => customNode.name === type); | ||
if (customNode) { | ||
onEdit(customNode.defaultValue, path); | ||
} | ||
else { | ||
setValue(convertValue(value, type)); | ||
setDataType(type); | ||
} | ||
}; | ||
const logError = (errorString) => { | ||
setError(errorString); | ||
setTimeout(() => setError(null), ERROR_DISPLAY_TIME); | ||
console.log('Error', errorString); | ||
}; | ||
const handleEdit = () => { | ||
setIsEditing(false); | ||
let newValue; | ||
switch (dataType) { | ||
case 'object': | ||
newValue = { [translate('DEFAULT_NEW_KEY')]: value }; | ||
break; | ||
case 'array': | ||
newValue = value !== null ? value : []; | ||
break; | ||
case 'number': | ||
const n = Number(value); | ||
if (isNaN(n)) | ||
newValue = 0; | ||
else | ||
newValue = n; | ||
break; | ||
default: | ||
newValue = value; | ||
} | ||
onEdit(newValue, path).then((error) => { | ||
if (error) | ||
logError(error); | ||
}); | ||
}; | ||
const handleEditKey = (newKey) => { | ||
setIsEditingKey(false); | ||
if (!parentData) | ||
return; | ||
const parentPath = path.slice(0, -1); | ||
if (!newKey) | ||
return; | ||
const newData = Object.fromEntries(Object.entries(parentData).map(([key, val]) => (key === name ? [newKey, val] : [key, val]))); | ||
onEdit(newData, parentPath); | ||
}; | ||
const handleKeyPress = (e) => { | ||
if (e.key === 'Enter') | ||
handleEditKey(e.target.value); | ||
else if (e.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
const handleCancel = () => { | ||
setIsEditing(false); | ||
setIsEditingKey(false); | ||
setValue(data); | ||
setDataType(getDataType(data)); | ||
}; | ||
const handleDelete = () => { | ||
onDelete(value, path).then((error) => { | ||
if (error) | ||
logError(error); | ||
}); | ||
}; | ||
const filterProps = { key: name, path, level: path.length, value: data, size: null }; | ||
const canEdit = useMemo(() => !restrictEditFilter(filterProps), [filterProps]); | ||
const canDelete = useMemo(() => !restrictDeleteFilter(filterProps), [filterProps]); | ||
const isArray = typeof path.slice(-1)[0] === 'number'; | ||
const canEditKey = !isArray && canEdit && canDelete; | ||
const inputProps = { | ||
value, | ||
parentData, | ||
setValue, | ||
isEditing, | ||
setIsEditing: canEdit ? () => setIsEditing(true) : () => { }, | ||
handleEdit, | ||
handleCancel, | ||
path, | ||
stringTruncate, | ||
translate, | ||
}; | ||
const { CustomNode, customNodeProps, hideKey } = getCustomNode(customNodeDefinitions, { | ||
key: name, | ||
path, | ||
level: path.length, | ||
value: data, | ||
size: 0, | ||
}); | ||
const allDataTypes = [ | ||
...customNodeDefinitions | ||
.filter(({ showInTypesSelector = false }) => showInTypesSelector) | ||
.map(({ name }) => name), | ||
...DataTypes, | ||
]; | ||
const allowedDataTypes = useMemo(() => { | ||
if (typeof restrictTypeSelection === 'boolean') | ||
return restrictTypeSelection ? [] : allDataTypes; | ||
if (Array.isArray(restrictTypeSelection)) | ||
return restrictTypeSelection; | ||
const result = restrictTypeSelection(filterProps); | ||
if (typeof result === 'boolean') | ||
return result ? [] : allDataTypes; | ||
return result; | ||
}, [filterProps, restrictTypeSelection]); | ||
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: { | ||
flexWrap: name.length > 10 ? 'wrap' : 'nowrap', | ||
}, 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' && | ||
!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 }))] })] }) })); | ||
}; | ||
const getDataType = (value) => { | ||
if (typeof value === 'string') | ||
return 'string'; | ||
if (typeof value === 'number') | ||
return 'number'; | ||
if (typeof value === 'boolean') | ||
return 'boolean'; | ||
if (value === null) | ||
return 'null'; | ||
return 'invalid'; | ||
}; | ||
const getInputComponent = (dataType, inputProps) => { | ||
const value = inputProps.value; | ||
switch (dataType) { | ||
case 'string': | ||
return jsx(StringValue, Object.assign({}, inputProps, { value: value })); | ||
case 'number': | ||
return jsx(NumberValue, Object.assign({}, inputProps, { value: value })); | ||
case 'boolean': | ||
return jsx(BooleanValue, Object.assign({}, inputProps, { value: value })); | ||
case 'null': | ||
return jsx(NullValue, Object.assign({}, inputProps)); | ||
case 'object': | ||
return jsx(ObjectValue, Object.assign({}, inputProps, { value: value })); | ||
case 'array': | ||
return jsx(ArrayValue, Object.assign({}, inputProps)); | ||
default: | ||
return jsx(InvalidValue, Object.assign({}, inputProps)); | ||
} | ||
}; | ||
const convertValue = (value, type) => { | ||
switch (type) { | ||
case 'string': | ||
return String(value); | ||
case 'number': | ||
const n = Number(value); | ||
return isNaN(n) ? 0 : n; | ||
case 'boolean': | ||
return !!value; | ||
case 'null': | ||
return null; | ||
case 'object': | ||
return value; | ||
case 'array': | ||
return [value]; | ||
default: | ||
return String(value); | ||
} | ||
}; | ||
const isCollection = (value) => value !== null && typeof value == 'object'; | ||
const CollectionNode = (_a) => { | ||
var { data, path, name, parentData, showCollectionCount } = _a, props = __rest(_a, ["data", "path", "name", "parentData", "showCollectionCount"]); | ||
const { styles } = useTheme(); | ||
const { onEdit, onAdd, onDelete, restrictEditFilter, restrictDeleteFilter, restrictAddFilter, collapseFilter, enableClipboard, indent, keySort, showArrayIndices, defaultValue, translate, customNodeDefinitions, } = props; | ||
const [isEditing, setIsEditing] = useState(false); | ||
const [isEditingKey, setIsEditingKey] = useState(false); | ||
const [stringifiedValue, setStringifiedValue] = useState(JSON.stringify(data, null, 2)); | ||
const [error, setError] = useState(null); | ||
const collectionSize = Object.keys(data).length; | ||
const filterProps = { key: name, path, level: path.length, value: data, size: collectionSize }; | ||
const startCollapsed = collapseFilter(filterProps); | ||
const [collapsed, setCollapsed] = useState(startCollapsed); | ||
const hasBeenOpened = useRef(!startCollapsed); | ||
const [isAnimating, setIsAnimating] = useState(false); | ||
useEffect(() => { | ||
setStringifiedValue(JSON.stringify(data, null, 2)); | ||
}, [data]); | ||
useEffect(() => { | ||
setCollapsed(collapseFilter(filterProps)); | ||
}, [collapseFilter]); | ||
const collectionType = Array.isArray(data) ? 'array' : 'object'; | ||
const brackets = collectionType === 'array' ? { open: '[', close: ']' } : { open: '{', close: '}' }; | ||
const transitionTime = getComputedStyle(document.documentElement).getPropertyValue('--jer-expand-transition-time'); | ||
const handleKeyPress = (e) => { | ||
if (e.key === 'Enter' && (e.metaKey || e.shiftKey || e.ctrlKey)) | ||
handleEdit(); | ||
else if (e.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
const handleCollapse = () => { | ||
if (!isEditing) { | ||
setIsAnimating(true); | ||
hasBeenOpened.current = true; | ||
setCollapsed(!collapsed); | ||
setTimeout(() => setIsAnimating(false), 500); | ||
} | ||
}; | ||
const showError = (errorString) => { | ||
setError(errorString); | ||
setTimeout(() => setError(null), ERROR_DISPLAY_TIME); | ||
console.log('Error', errorString); | ||
}; | ||
const handleEdit = () => { | ||
try { | ||
const value = JSON.parse(stringifiedValue); | ||
setIsEditing(false); | ||
setError(null); | ||
onEdit(value, path).then((error) => { | ||
if (error) | ||
showError(error); | ||
}); | ||
} | ||
catch (_a) { | ||
setError(translate('ERROR_INVALID_JSON')); | ||
setTimeout(() => setError(null), ERROR_DISPLAY_TIME); | ||
console.log('Invalid JSON'); | ||
return; | ||
} | ||
}; | ||
const handleEditKey = (newKey) => { | ||
setIsEditingKey(false); | ||
if (!parentData) | ||
return; | ||
const parentPath = path.slice(0, -1); | ||
if (!newKey) | ||
return; | ||
const newData = Object.fromEntries(Object.entries(parentData).map(([key, val]) => (key === name ? [newKey, val] : [key, val]))); | ||
onEdit(newData, parentPath); | ||
}; | ||
const handleKeyPressKeyEdit = (e) => { | ||
if (e.key === 'Enter') | ||
handleEditKey(e.target.value); | ||
else if (e.key === 'Escape') | ||
handleCancel(); | ||
}; | ||
const handleAdd = (key) => { | ||
setCollapsed(false); | ||
if (collectionType === 'array') { | ||
onAdd(defaultValue, [...path, data.length]).then((error) => { | ||
if (error) | ||
showError(error); | ||
}); | ||
} | ||
else if (key in data) { | ||
showError(translate('ERROR_KEY_EXISTS')); | ||
return; | ||
} | ||
else | ||
onAdd(defaultValue, [...path, key]).then((error) => { | ||
if (error) | ||
showError(error); | ||
}); | ||
}; | ||
const handleDelete = path.length > 0 | ||
? () => { | ||
onDelete(data, path).then((result) => { | ||
if (result) | ||
showError(result); | ||
}); | ||
} | ||
: undefined; | ||
const handleCancel = () => { | ||
setIsEditing(false); | ||
setError(null); | ||
setStringifiedValue(JSON.stringify(data, null, 2)); | ||
}; | ||
const canEdit = useMemo(() => !restrictEditFilter(filterProps), [filterProps]); | ||
const canDelete = useMemo(() => !restrictDeleteFilter(filterProps), [filterProps]); | ||
const canAdd = useMemo(() => !restrictAddFilter(filterProps), [filterProps]); | ||
const canEditKey = parentData !== null && canEdit && canAdd && canDelete; | ||
const isArray = typeof path.slice(-1)[0] === 'number'; | ||
const showLabel = showArrayIndices || !isArray; | ||
const showCount = showCollectionCount === 'when-closed' ? collapsed : showCollectionCount; | ||
const keyValueArray = Object.entries(data).map(([key, value]) => [ | ||
collectionType === 'array' ? Number(key) : key, | ||
value, | ||
]); | ||
if (keySort && collectionType === 'object') | ||
keyValueArray.sort(typeof keySort === 'function' ? (a, b) => keySort(a[0], b[0]) : undefined); | ||
const numOfLines = JSON.stringify(data, null, 2).split('\n').length; | ||
const { CustomNode, customNodeProps, hideKey } = getCustomNode(customNodeDefinitions, { | ||
key: name, | ||
path, | ||
level: path.length, | ||
value: data, | ||
size: Object.keys(data).length, | ||
}); | ||
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 | ||
? translate('ITEM_SINGLE', 1) | ||
: 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 | ||
? () => { | ||
setIsEditing(true); | ||
setCollapsed(false); | ||
} | ||
: 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: { | ||
maxHeight: collapsed ? 0 : !isEditing ? `${numOfLines * 3}em` : undefined, | ||
overflowY: collapsed || isAnimating ? 'hidden' : 'visible', | ||
transition: `max-height ${transitionTime}`, | ||
}, 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 | ||
? null | ||
: 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 })] })] })) })); | ||
}; | ||
const localisedStrings = { | ||
ITEM_SINGLE: '{{count}} item', | ||
ITEMS_MULTIPLE: '{{count}} items', | ||
KEY_NEW: 'Enter new key', | ||
ERROR_KEY_EXISTS: 'Key already exists', | ||
ERROR_INVALID_JSON: 'Invalid JSON', | ||
ERROR_UPDATE: 'Update unsuccessful', | ||
ERROR_DELETE: 'Delete unsuccessful', | ||
ERROR_ADD: 'Adding node unsuccessful', | ||
DEFAULT_STRING: 'New data!', | ||
DEFAULT_NEW_KEY: 'key', | ||
}; | ||
const translate = (translations, key, count) => { | ||
const string = key in translations ? translations[key] : localisedStrings[key]; | ||
return count === undefined ? string : string === null || string === void 0 ? void 0 : string.replace('{{count}}', String(count)); | ||
}; | ||
const getTranslateFunction = (translations) => (key, count) => translate(translations, key, count); | ||
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 = [], }) => { | ||
const [data, setData] = useState(srcData); | ||
const { styles, setTheme, setIcons } = useTheme(); | ||
const collapseFilter = useCallback(getFilterFunction(collapse), [collapse]); | ||
const translate = useCallback(getTranslateFunction(translations), [translations]); | ||
useEffect(() => { | ||
setData(srcData); | ||
}, [srcData]); | ||
useEffect(() => { | ||
if (theme) | ||
setTheme(theme); | ||
if (icons) | ||
setIcons(icons); | ||
}, [theme, icons]); | ||
const onEdit = (value, path) => __awaiter(void 0, void 0, void 0, function* () { | ||
const { currentData, newData, currentValue, newValue } = updateDataObject(data, path, value, 'update'); | ||
if (srcEdit) { | ||
const result = yield srcEdit({ | ||
currentData, | ||
newData, | ||
currentValue, | ||
newValue, | ||
name: path.slice(-1)[0], | ||
path, | ||
}); | ||
if (result === undefined) | ||
setData(newData); | ||
if (result === false) | ||
return translate('ERROR_UPDATE'); | ||
return result; | ||
} | ||
else | ||
setData(newData); | ||
}); | ||
const onDelete = (value, path) => __awaiter(void 0, void 0, void 0, function* () { | ||
const { currentData, newData, currentValue, newValue } = updateDataObject(data, path, value, 'delete'); | ||
if (srcDelete) { | ||
const result = yield srcDelete({ | ||
currentData, | ||
newData, | ||
currentValue, | ||
newValue, | ||
name: path.slice(-1)[0], | ||
path, | ||
}); | ||
if (result === undefined) | ||
setData(newData); | ||
if (result === false) | ||
return translate('ERROR_DELETE'); | ||
return result; | ||
} | ||
else | ||
setData(newData); | ||
}); | ||
const onAdd = (value, path) => __awaiter(void 0, void 0, void 0, function* () { | ||
const { currentData, newData, currentValue, newValue } = updateDataObject(data, path, value, 'add'); | ||
if (srcAdd) { | ||
const result = yield srcAdd({ | ||
currentData, | ||
newData, | ||
currentValue, | ||
newValue, | ||
name: path.slice(-1)[0], | ||
path, | ||
}); | ||
if (result === undefined) | ||
setData(newData); | ||
if (result === false) | ||
return translate('ERROR_ADD'); | ||
return result; | ||
} | ||
else | ||
setData(newData); | ||
}); | ||
const restrictEditFilter = getFilterFunction(restrictEdit); | ||
const restrictDeleteFilter = getFilterFunction(restrictDelete); | ||
const restrictAddFilter = getFilterFunction(restrictAdd); | ||
const otherProps = { | ||
name: rootName, | ||
onEdit, | ||
onDelete, | ||
onAdd, | ||
showCollectionCount, | ||
collapseFilter, | ||
restrictEditFilter, | ||
restrictDeleteFilter, | ||
restrictAddFilter, | ||
restrictTypeSelection, | ||
enableClipboard, | ||
keySort, | ||
showArrayIndices, | ||
indent, | ||
defaultValue, | ||
stringTruncate, | ||
translate, | ||
customNodeDefinitions, | ||
parentData: null, | ||
}; | ||
if (!styles) | ||
return null; | ||
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))) })); | ||
}; | ||
const JsonEditor = (props) => (jsx(ThemeProvider, { children: jsx(Editor, Object.assign({}, props)) })); | ||
const updateDataObject = (data, path, newValue, action) => { | ||
if (path.length === 0) { | ||
return { | ||
currentData: data, | ||
newData: newValue, | ||
currentValue: data, | ||
newValue: newValue, | ||
}; | ||
} | ||
const currentValue = action !== 'add' ? extract(data, path) : undefined; | ||
const newData = assign(clone(data), path, newValue, { remove: action === 'delete' }); | ||
return { | ||
currentData: data, | ||
newData, | ||
currentValue, | ||
newValue: action === 'update' ? newValue : undefined, | ||
}; | ||
}; | ||
const getFilterFunction = (propValue) => { | ||
if (typeof propValue === 'boolean') | ||
return () => propValue; | ||
if (typeof propValue === 'number') | ||
return ({ level }) => level >= propValue; | ||
return propValue; | ||
}; | ||
export { JsonEditor, themes }; | ||
import{jsx as e,jsxs as n,Fragment as t}from"react/jsx-runtime";import{createContext as r,useState as o,useContext as i,useEffect as a,useMemo as l,useRef as c,useCallback as s}from"react";import d from"object-property-assigner";import u from"object-property-extractor";import p from"just-clone";import{HiOutlineClipboardCopy as m}from"react-icons/hi";import{BiEdit as h,BiPlusCircle as y}from"react-icons/bi";import{MdDeleteForever as b}from"react-icons/md";import{FiCheckCircle as g}from"react-icons/fi";import{TiCancel as f}from"react-icons/ti";import{FaChevronDown as j}from"react-icons/fa";function v(e,n,t,r){return new(t||(t=Promise))((function(o,i){function a(e){try{c(r.next(e))}catch(e){i(e)}}function l(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){var n;e.done?o(e.value):(n=e.value,n instanceof t?n:new t((function(e){e(n)}))).then(a,l)}c((r=r.apply(e,n||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;var E=[],k=[];!function(e,n){if(e&&"undefined"!=typeof document){var t,r=!0===n.prepend?"prepend":"append",o=!0===n.singleTag,i="string"==typeof n.container?document.querySelector(n.container):document.getElementsByTagName("head")[0];if(o){var a=E.indexOf(i);-1===a&&(a=E.push(i)-1,k[a]={}),t=k[a]&&k[a][r]?k[a][r]:k[a][r]=l()}else t=l();65279===e.charCodeAt(0)&&(e=e.substring(1)),t.styleSheet?t.styleSheet.cssText+=e:t.appendChild(document.createTextNode(e))}function l(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),n.attributes)for(var t=Object.keys(n.attributes),o=0;o<t.length;o++)e.setAttribute(t[o],n.attributes[t[o]]);var a="prepend"===r?"afterbegin":"beforeend";return i.insertAdjacentElement(a,e),e}}(":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",{});const w={default:{displayName:"Default",fragments:{edit:"rgb(42, 161, 152)"},styles:{container:{backgroundColor:"#f6f6f6",fontFamily:"monospace"},property:"#292929",bracket:{color:"rgb(0, 43, 54)",fontWeight:"bold"},itemCount:{color:"rgba(0, 0, 0, 0.3)",fontStyle:"italic"},string:"rgb(203, 75, 22)",number:"rgb(38, 139, 210)",boolean:"green",null:{color:"rgb(220, 50, 47)",fontVariant:"small-caps",fontWeight:"bold"},input:["#292929",{fontSize:"90%"}],inputHighlight:"#b3d8ff",error:{fontSize:"0.8em",color:"red",fontWeight:"bold"},iconCollection:"rgb(0, 43, 54)",iconEdit:"edit",iconDelete:"rgb(203, 75, 22)",iconAdd:"edit",iconCopy:"rgb(38, 139, 210)",iconOk:"green",iconCancel:"rgb(203, 75, 22)"}},githubDark:{displayName:"Github Dark",styles:{container:{backgroundColor:"#0d1117",color:"white"},property:"#E6EDF3",bracket:"#56d364",itemCount:"#8B949E",string:"#A5D6FF",number:"#D2A8FF",boolean:{color:"#FF7B72",fontSize:"90%",fontWeight:"bold"},null:"green",iconCollection:"#D2A8FF",iconEdit:"#D2A8FF",iconDelete:"rgb(203, 75, 22)",iconAdd:"rgb(203, 75, 22)",iconCopy:"#A5D6FF",iconOk:"#56d364",iconCancel:"rgb(203, 75, 22)"}},githubLight:{displayName:"Github Light",styles:{container:"white",property:"#1F2328",bracket:"#00802e",itemCount:"#8B949E",string:"#0A3069",number:"#953800",boolean:{color:"#CF222E",fontSize:"90%",fontWeight:"bold"},null:"#FF7B72",iconCollection:"#8250DF",iconEdit:"#8250DF",iconDelete:"rgb(203, 75, 22)",iconAdd:"#8250DF",iconCopy:"#57606A"}},monoDark:{displayName:"Black & White",fragments:{lightText:{color:"white"},midGrey:"#5c5c5c"},styles:{container:["lightText",{backgroundColor:"black"}],property:"lightText",bracket:"midGrey",itemCount:"#4a4a4a",string:"#a8a8a8",number:"#666666",boolean:{color:"#848484",fontStyle:"italic"},null:"#333333",iconCollection:"midGrey",iconEdit:"midGrey",iconDelete:"midGrey",iconAdd:"midGrey",iconCopy:"midGrey",iconOk:"midGrey",iconCancel:"midGrey"}},monoLight:{fragments:{midGrey:"#a3a3a3"},displayName:"White & Black",styles:{container:"white",property:"black",bracket:"midGrey",itemCount:"#b5b5b5",string:"#575757",number:"#999999",boolean:{color:"#7b7b7b",fontStyle:"italic"},null:"#cccccc",iconCollection:"midGrey",iconEdit:"midGrey",iconDelete:"midGrey",iconAdd:"midGrey",iconCopy:"midGrey",iconOk:"midGrey",iconCancel:"midGrey"}},candyWrapper:{displayName:"Candy Wrapper",fragments:{minty:{backgroundColor:"#F1FAEE"},pale:{color:"#A8DADC"},mid:{color:"#457B9D"},dark:{color:"#1D3557"},pop:{color:"#E63946"},darkBlue:{color:"#2B2D42"}},styles:{container:"minty",property:"pop",bracket:"dark",itemCount:"pale",string:"mid",number:["darkBlue",{fontSize:"85%"}],boolean:["mid",{fontStyle:"italic",fontWeight:"bold",fontSize:"80%"}],null:["#cccccc",{fontWeight:"bold"}],iconCollection:"#1D3557",iconEdit:"#457B9D",iconDelete:"#E63946",iconAdd:"#2B2D42",iconCopy:"#1D3557",iconCancel:"#E63946"}},psychedelic:{displayName:"Psychedelic",fragments:{minty:{backgroundColor:"#F1FAEE"},pale:{color:"#A8DADC"},mid:{color:"#457B9D"},dark:{color:"#1D3557"},pop:{color:"#E63946"},fluroYellow:"rgb(242, 228, 21)",fluroGreen:"rgb(68, 255, 62)",hotPink:"#f7379a"},styles:{container:{backgroundColor:"unset",background:"linear-gradient(90deg, hsla(333, 100%, 53%, 1) 0%, hsla(33, 94%, 57%, 1) 100%)",color:"black"},property:"black",bracket:"fluroYellow",itemCount:["pale",{opacity:.7}],string:"white",number:["#33d9ff",{fontSize:"90%",fontWeight:"bold"}],boolean:["fluroGreen",{fontWeight:"bold",fontSize:"80%"}],null:["black",{fontWeight:"bold",opacity:.3,backgroundColor:"rgb(255, 255, 255, 0.5)",padding:"0 0.4em",borderRadius:"0.4em"}],iconCollection:"fluroYellow",iconEdit:["black"],iconDelete:["white",{opacity:.5}],iconAdd:["white",{opacity:.5}],iconCopy:"rgb(32, 84, 242)",iconOk:"fluroGreen",iconCancel:"hotPink"}}},C={container:{},property:{},bracket:{},itemCount:{},string:{},number:{},boolean:{},null:{},input:{},inputHighlight:{},error:{},iconCollection:{},iconEdit:{},iconDelete:{},iconAdd:{},iconCopy:{},iconOk:{},iconCancel:{}},D=w.default,N=r({styles:C,setTheme:e=>{},icons:{},setIcons:()=>{}}),O=({children:n})=>{const[t,r]=o(C),[i,a]=o({});return e(N.Provider,{value:{styles:t,setTheme:e=>r(S(e)),icons:i,setIcons:a},children:n})},x=()=>i(N),S=e=>{if("string"==typeof e)return A(w[e]);if(Array.isArray(e)){const[n,t]=e;return A(w[n],F(t)?{styles:t}:t)}return A(D,F(e)?{styles:e}:e)},A=(e,n={styles:C})=>{var t,r,o,i;const[a,l,c]=[D,e,n].map((e=>{const{fragments:n,styles:t}=e,r={};return Object.entries(t).forEach((([e,t])=>{const o=(Array.isArray(t)?t:[t]).reduce(((t,r)=>{var o;if("string"==typeof r){const i=null!==(o=null==n?void 0:n[r])&&void 0!==o?o:r;return"string"==typeof i?Object.assign(Object.assign({},t),{[T[e]]:i}):Object.assign(Object.assign({},t),i)}return Object.assign(Object.assign({},t),r)}),{});r[e]=o})),r})),s={};return Object.keys(D.styles).forEach((e=>{s[e]=Object.assign(Object.assign(Object.assign({},a[e]),l[e]),c[e])})),(null===(t=null==s?void 0:s.inputHighlight)||void 0===t?void 0:t.backgroundColor)&&document.documentElement.style.setProperty("--jer-highlight-color",null===(r=null==s?void 0:s.inputHighlight)||void 0===r?void 0:r.backgroundColor),(null===(o=null==s?void 0:s.iconCopy)||void 0===o?void 0:o.color)&&document.documentElement.style.setProperty("--jer-icon-copy-color",null===(i=null==s?void 0:s.iconCopy)||void 0===i?void 0:i.color),s},F=e=>!("styles"in e),T={container:"backgroundColor",property:"color",bracket:"color",itemCount:"color",string:"color",number:"color",boolean:"color",null:"color",input:"color",inputHighlight:"backgroundColor",error:"color",iconCollection:"color",iconEdit:"color",iconDelete:"color",iconAdd:"color",iconCopy:"color",iconOk:"color",iconCancel:"color"},V=({className:t,name:r,value:o,setValue:i,handleKeyPress:a})=>{const{styles:l}=x(),c="\n"===o.slice(-1)?o+".":o;return n("div",{style:{display:"grid"},children:[e("textarea",{style:Object.assign({height:"auto",gridArea:"1 / 1 / 2 / 2",overflowY:"auto"},l.input),rows:1,className:t,name:r,value:o,onChange:e=>i(e.target.value),autoFocus:!0,onFocus:e=>{o.length<40&&e.target.select()},onKeyDown:a}),e("span",{className:t,style:Object.assign({visibility:"hidden",height:"auto",gridArea:"1 / 1 / 2 / 2",color:"red",opacity:.9,whiteSpace:"pre-wrap",overflow:"clip",border:"1px solid transparent"},l.input),children:c})]})},I="**INVALID_FUNCTION**",L=(e,n=200)=>e.length<n?e:`${e.slice(0,n-2).trim()}...`,R=({value:t,setValue:r,isEditing:o,path:i,setIsEditing:a,handleEdit:l,handleCancel:c,stringTruncate:s})=>{const{styles:d}=x();return o?e(V,{className:"jer-input-text",name:i.join("."),value:t,setValue:r,isEditing:o,handleKeyPress:e=>{"Enter"!==e.key||e.shiftKey?"Escape"===e.key&&c():l()}}):n("div",{onDoubleClick:()=>a(!0),onClick:e=>{(e.getModifierState("Control")||e.getModifierState("Meta"))&&a(!0)},className:"jer-value-string",style:d.string,children:['"',(u=L(t,s),u.split("\n").map(((t,r,o)=>n("span",{children:[t,r<o.length-1?e("br",{}):null]},r)))),'"']});var u},K=({value:n,setValue:t,isEditing:r,path:o,setIsEditing:i,handleEdit:a,handleCancel:l})=>{const{styles:c}=x();return r?e("input",{className:"jer-input-number",type:"text",name:o.join("."),value:n,onChange:e=>t(e.target.value.replace(/[^0-9.-]/g,"")),autoFocus:!0,onFocus:e=>e.target.select(),onKeyDown:e=>{"Enter"===e.key?a():"Escape"===e.key&&l()},style:{width:String(n).length/1.5+2+"em"}}):e("span",{onDoubleClick:()=>i(!0),className:"jer-value-number",style:c.number,children:n})},_=({value:n,setValue:t,isEditing:r,path:o,setIsEditing:i,handleEdit:l,handleCancel:c})=>{const{styles:s}=x();a((()=>(r&&document.addEventListener("keydown",d),()=>document.removeEventListener("keydown",d))),[r]);const d=e=>{"Enter"===e.key?l():"Escape"===e.key&&c()};return r?e("input",{className:"jer-input-boolean",type:"checkbox",name:o.join("."),checked:n,onChange:()=>t(!n)}):e("span",{onDoubleClick:()=>i(!0),className:"jer-value-boolean",style:s.boolean,children:String(n)})},W=({value:n,isEditing:t,setIsEditing:r,handleEdit:o,handleCancel:i})=>{const{styles:l}=x();a((()=>(t&&document.addEventListener("keydown",c),()=>document.removeEventListener("keydown",c))),[t]);const c=e=>{"Enter"===e.key?o():"Escape"===e.key&&i()};return e("div",t?{className:"jer-input-null",children:"null"}:{onDoubleClick:()=>r(!0),className:"jer-value-null",style:l.null,children:String(n)})},z=({value:n,translate:t,isEditing:r,handleEdit:o,handleCancel:i})=>{a((()=>(r&&document.addEventListener("keydown",l),()=>document.removeEventListener("keydown",l))),[]);const l=e=>{"Enter"===e.key?o():"Escape"===e.key&&i()};return e("span",{className:"jer-value-object",children:`{${t("DEFAULT_NEW_KEY")}: "${n}" }`})},G=({value:n,isEditing:t,handleEdit:r,handleCancel:o})=>{a((()=>(t&&document.addEventListener("keydown",i),()=>document.removeEventListener("keydown",i))),[]);const i=e=>{"Enter"===e.key?r():"Escape"===e.key&&o()};return e("span",{className:"jer-value-array",children:`[${null===n?"":n}]`})},P=({value:n})=>{let t="Error!";switch(typeof n){case"string":n===I&&(t="Function");break;case"undefined":t="Undefined";break;case"symbol":t="Symbol"}return e("span",{className:"jer-value-invalid",children:t})},B=({name:n,rotate:r})=>{var o,i,a,l,c,s,d;const{styles:u,icons:p}=x(),v={size:"1.4em",className:"jer-icon"};switch(n){case"add":return null!==(o=null==p?void 0:p.add)&&void 0!==o?o:e(y,Object.assign({},v,{style:u.iconAdd}));case"edit":return null!==(i=null==p?void 0:p.edit)&&void 0!==i?i:e(h,Object.assign({},v,{style:u.iconEdit}));case"delete":return null!==(a=null==p?void 0:p.delete)&&void 0!==a?a:e(b,Object.assign({},v,{style:u.iconDelete,size:"1.5em"}));case"copy":return null!==(l=null==p?void 0:p.copy)&&void 0!==l?l:e(m,Object.assign({},v,{style:u.iconCopy}));case"ok":return null!==(c=null==p?void 0:p.ok)&&void 0!==c?c:e(g,Object.assign({},v,{style:Object.assign({fontSize:"90%"},u.iconOk)}));case"cancel":return null!==(s=null==p?void 0:p.cancel)&&void 0!==s?s:e(f,Object.assign({},v,{style:Object.assign({fontSize:"130%"},u.iconCancel)}));case"chevron":return null!==(d=null==p?void 0:p.chevron)&&void 0!==d?d:e(j,{className:"jer-accordion-icon"+(r?" jer-rotate-90":""),style:u.iconCollection});default:return e(t,{})}},$=({startEdit:r,handleDelete:i,handleAdd:l,enableClipboard:c,type:s,data:d,path:u,name:p,translate:m})=>{const{styles:h}=x(),y=m("KEY_NEW"),[b,g]=o(!1),[f,j]=o(y);a((()=>{b||j(y)}),[b]);return n("div",{className:"jer-edit-buttons",style:b?{opacity:1}:void 0,children:[c&&e("div",{onClick:e=>{let n,t="value",r="";if(c){if(!0===(e.ctrlKey||e.metaKey))n=Y(u),r=n,t="path";else n=d,r=s?JSON.stringify(d,null,2):String(n);navigator.clipboard.writeText(r)}"function"==typeof c&&c({value:n,stringValue:r,path:u,key:p,type:t})},className:"jer-copy-pulse",children:e(B,{name:"copy"})}),r&&e("div",{onClick:r,children:e(B,{name:"edit"})}),i&&e("div",{onClick:i,children:e(B,{name:"delete"})}),l&&e("div",{onClick:()=>{"object"===s?g(!0):l("")},children:e(B,{name:"add"})}),b&&l&&"object"===s&&n(t,{children:[e("input",{className:"jer-input-new-key",type:"text",name:"new-object-key",value:f,onChange:e=>j(e.target.value),autoFocus:!0,onFocus:e=>e.target.select(),onKeyDown:e=>{"Enter"===e.key&&l?(g(!1),l(f)):"Escape"===e.key&&g(!1)},style:Object.assign({},h.input)}),e(U,{onOk:()=>{f&&(g(!1),l(f))},onCancel:()=>{g(!1)}})]})]})},U=({onOk:t,onCancel:r})=>n("div",{className:"jer-confirm-buttons",children:[e("div",{onClick:t,children:e(B,{name:"ok"})}),e("div",{onClick:r,children:e(B,{name:"cancel"})})]}),Y=e=>e.reduce(((e,n)=>"number"==typeof n?`${e}[${n}]`:""===e?n:`${e}.${n}`),""),M=2500,J=["string","number","boolean","null","object","array"],H=(e=[],n)=>{const t=e.filter((({condition:e})=>e(n)));if(0===t.length)return{};const{element:r,props:o,hideKey:i=!1}=t[0];return{CustomNode:r,customNodeProps:o,hideKey:i}},X=({name:t,hideKey:r,children:o,indent:i})=>{const{styles:a}=x();return e("div",{className:"jer-component jer-value-component",style:i?{marginLeft:i/2+"em"}:{},children:n("div",{className:"jer-value-main-row",style:{flexWrap:t.length>10?"wrap":"nowrap"},children:[!r&&n("label",{htmlFor:t,className:"jer-object-key",style:Object.assign(Object.assign({},a.property),{minWidth:`${Math.min(String(t).length+1,5)}ch`,flexShrink:t.length>10?1:0}),children:[t,":"," "]}),e("div",{className:"jer-value-and-buttons",style:{paddingLeft:r?0:void 0},children:o})]})})},q=t=>{const{data:r,parentData:i,name:c,path:s,onEdit:d,onDelete:u,enableClipboard:p,restrictEditFilter:m,restrictDeleteFilter:h,restrictTypeSelection:y,showLabel:b,stringTruncate:g,indent:f,translate:j,customNodeDefinitions:v}=t,{styles:E}=x(),[k,w]=o(!1),[C,D]=o(!1),[N,O]=o("function"==typeof r?I:r),[S,A]=o(null),[F,T]=o(Q(r));a((()=>{O("function"==typeof r?I:r),T(Q(r))}),[r,S]);const V=e=>{A(e),setTimeout((()=>A(null)),M),console.log("Error",e)},L=()=>{let e;switch(w(!1),F){case"object":e={[j("DEFAULT_NEW_KEY")]:N};break;case"array":e=null!==N?N:[];break;case"number":const n=Number(N);e=isNaN(n)?0:n;break;default:e=N}d(e,s).then((e=>{e&&V(e)}))},R=()=>{w(!1),D(!1),O(r),T(Q(r))},K={key:c,path:s,level:s.length,value:r,size:null},_=l((()=>!m(K)),[K]),W=l((()=>!h(K)),[K]),z=!("number"==typeof s.slice(-1)[0])&&_&&W,G={value:N,parentData:i,setValue:O,isEditing:k,setIsEditing:_?()=>w(!0):()=>{},handleEdit:L,handleCancel:R,path:s,stringTruncate:g,translate:j},{CustomNode:P,customNodeProps:B,hideKey:Y}=H(v,{key:c,path:s,level:s.length,value:r,size:0}),q=[...v.filter((({showInTypesSelector:e=!1})=>e)).map((({name:e})=>e)),...J],ne=l((()=>{if("boolean"==typeof y)return y?[]:q;if(Array.isArray(y))return y;const e=y(K);return"boolean"==typeof e?e?[]:q:e}),[K,y]);return P?e(X,{name:c,hideKey:Y,indent:f,children:e(P,Object.assign({customProps:B},t))}):e("div",{className:"jer-component jer-value-component",style:{marginLeft:f/2+"em"},children:n("div",{className:"jer-value-main-row",style:{flexWrap:c.length>10?"wrap":"nowrap"},children:[b&&!C&&n("label",{htmlFor:s.join("."),className:"jer-object-key",style:Object.assign(Object.assign({},E.property),{minWidth:`${Math.min(String(c).length+1,5)}ch`,flexShrink:c.length>10?1:0}),onDoubleClick:()=>z&&D(!0),children:[c,":"," "]}),b&&C&&e("input",{className:"jer-object-key",type:"text",name:s.join("."),defaultValue:c,autoFocus:!0,onFocus:e=>e.target.select(),onKeyDown:e=>{"Enter"===e.key?(e=>{if(D(!1),!i)return;const n=s.slice(0,-1);if(!e)return;const t=Object.fromEntries(Object.entries(i).map((([n,t])=>n===c?[e,t]:[n,t])));d(t,n)})(e.target.value):"Escape"===e.key&&R()},style:{width:String(c).length/1.5+.5+"em"}}),n("div",{className:"jer-value-and-buttons",children:[e("div",{className:"jer-input-component",children:Z(F,G)}),k?e(U,{onOk:L,onCancel:R}):"invalid"!==F&&!S&&e($,{startEdit:_?()=>w(!0):void 0,handleDelete:W?()=>{u(N,s).then((e=>{e&&V(e)}))}:void 0,data:r,enableClipboard:p,name:c,path:s,translate:j}),k&&ne.length>0&&n("div",{className:"jer-select",children:[e("select",{name:`${c}-type-select`,className:"jer-type-select",onChange:e=>(e=>{const n=v.find((n=>n.name===e));n?d(n.defaultValue,s):(O(ee(N,e)),T(e))})(e.target.value),value:F,children:ne.map((n=>e("option",{value:n,children:n},n)))}),e("span",{className:"focus"})]}),!k&&S&&e("span",{className:"jer-error-slug",style:E.error,children:S})]})]})})},Q=e=>"string"==typeof e?"string":"number"==typeof e?"number":"boolean"==typeof e?"boolean":null===e?"null":"invalid",Z=(n,t)=>{const r=t.value;switch(n){case"string":return e(R,Object.assign({},t,{value:r}));case"number":return e(K,Object.assign({},t,{value:r}));case"boolean":return e(_,Object.assign({},t,{value:r}));case"null":return e(W,Object.assign({},t));case"object":return e(z,Object.assign({},t,{value:r}));case"array":return e(G,Object.assign({},t));default:return e(P,Object.assign({},t))}},ee=(e,n)=>{switch(n){case"string":default:return String(e);case"number":const n=Number(e);return isNaN(n)?0:n;case"boolean":return!!e;case"null":return null;case"object":return e;case"array":return[e]}},ne=e=>null!==e&&"object"==typeof e,te=r=>{var{data:i,path:s,name:d,parentData:u,showCollectionCount:p}=r,m=function(e,n){var t={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&n.indexOf(r)<0&&(t[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(r=Object.getOwnPropertySymbols(e);o<r.length;o++)n.indexOf(r[o])<0&&Object.prototype.propertyIsEnumerable.call(e,r[o])&&(t[r[o]]=e[r[o]])}return t}(r,["data","path","name","parentData","showCollectionCount"]);const{styles:h}=x(),{onEdit:y,onAdd:b,onDelete:g,restrictEditFilter:f,restrictDeleteFilter:j,restrictAddFilter:v,collapseFilter:E,enableClipboard:k,indent:w,keySort:C,showArrayIndices:D,defaultValue:N,translate:O,customNodeDefinitions:S}=m,[A,F]=o(!1),[T,I]=o(!1),[L,R]=o(JSON.stringify(i,null,2)),[K,_]=o(null),W=Object.keys(i).length,z={key:d,path:s,level:s.length,value:i,size:W},G=E(z),[P,Y]=o(G),J=c(!G),[Q,Z]=o(!1);a((()=>{R(JSON.stringify(i,null,2))}),[i]),a((()=>{Y(E(z))}),[E]);const ee=Array.isArray(i)?"array":"object",re="array"===ee?{open:"[",close:"]"}:{open:"{",close:"}"},oe=getComputedStyle(document.documentElement).getPropertyValue("--jer-expand-transition-time"),ie=e=>{_(e),setTimeout((()=>_(null)),M),console.log("Error",e)},ae=()=>{try{const e=JSON.parse(L);F(!1),_(null),y(e,s).then((e=>{e&&ie(e)}))}catch(e){return _(O("ERROR_INVALID_JSON")),setTimeout((()=>_(null)),M),void console.log("Invalid JSON")}},le=s.length>0?()=>{g(i,s).then((e=>{e&&ie(e)}))}:void 0,ce=()=>{F(!1),I(!1),_(null),R(JSON.stringify(i,null,2))},se=l((()=>!f(z)),[z]),de=l((()=>!j(z)),[z]),ue=l((()=>!v(z)),[z]),pe=null!==u&&se&&ue&&de,me="number"==typeof s.slice(-1)[0],he=D||!me,ye="when-closed"===p?P:p,be=Object.entries(i).map((([e,n])=>["array"===ee?Number(e):e,n]));C&&"object"===ee&&be.sort("function"==typeof C?(e,n)=>C(e[0],n[0]):void 0);const ge=JSON.stringify(i,null,2).split("\n").length,{CustomNode:fe,customNodeProps:je,hideKey:ve}=H(S,{key:d,path:s,level:s.length,value:i,size:Object.keys(i).length});return e("div",{className:"jer-component jer-collection-component",style:{marginLeft:(0===s.length?0:w/2)+"em"},children:fe?e(X,{name:d,hideKey:ve,children:e(fe,Object.assign({data:i,path:s,name:d,parentData:u,customProps:je},m))}):n(t,{children:[n("div",{className:"jer-collection-header-row",children:[e("div",{onClick:()=>{A||(Z(!0),J.current=!0,Y(!P),setTimeout((()=>Z(!1)),500))},children:e(B,{name:"chevron",rotate:P})}),n("div",{className:"jer-collection-name",children:[!T&&e("span",{style:h.property,onDoubleClick:()=>pe&&I(!0),children:he&&""!==d&&void 0!==d?`${d}:`:null}),T&&e("input",{className:"jer-collection-name",type:"text",name:s.join("."),defaultValue:d,autoFocus:!0,onFocus:e=>e.target.select(),onKeyDown:e=>{"Enter"===e.key?(e=>{if(I(!1),!u)return;const n=s.slice(0,-1);if(!e)return;const t=Object.fromEntries(Object.entries(u).map((([n,t])=>n===d?[e,t]:[n,t])));y(t,n)})(e.target.value):"Escape"===e.key&&ce()},style:{width:String(d).length/1.5+.5+"em"}}),!A&&e("span",{className:"jer-brackets",style:h.bracket,children:re.open})]}),!A&&p&&e("div",{className:"jer-collection-item-count"+(ye?" jer-visible":" jer-hidden"),style:h.itemCount,children:1===W?O("ITEM_SINGLE",1):O("ITEMS_MULTIPLE",W)}),e("div",{className:"jer-brackets"+(P?" jer-visible":" jer-hidden"),style:h.bracket,children:re.close}),!A&&e($,{startEdit:se?()=>{F(!0),Y(!1)}:void 0,handleAdd:ue?e=>{if(Y(!1),"array"===ee)b(N,[...s,i.length]).then((e=>{e&&ie(e)}));else{if(e in i)return void ie(O("ERROR_KEY_EXISTS"));b(N,[...s,e]).then((e=>{e&&ie(e)}))}}:void 0,handleDelete:de?le:void 0,enableClipboard:k,type:ee,data:i,name:d,path:s,translate:O})]}),n("div",{className:"jer-collection-inner",style:{maxHeight:P?0:A?void 0:3*ge+"em",overflowY:P||Q?"hidden":"visible",transition:`max-height ${oe}`},children:[A?e("div",{className:"jer-collection-text-edit",children:n("div",{children:[e(V,{className:"jer-collection-text-area",name:s.join("."),value:L,setValue:R,isEditing:A,handleKeyPress:e=>{"Enter"===e.key&&(e.metaKey||e.shiftKey||e.ctrlKey)?ae():"Escape"===e.key&&ce()}}),e("div",{className:"jer-collection-input-button-row",children:e(U,{onOk:ae,onCancel:ce,isCollection:!0})})]})}):e(t,{children:J.current?be.map((([n,t])=>e("div",{className:"jer-collection-element",children:ne(t)?e(te,Object.assign({data:t,parentData:i,path:[...s,n],name:n,showCollectionCount:p},m),n):e(q,Object.assign({data:t,parentData:i,path:[...s,n],name:n},m,{showLabel:"object"===ee||D}),n)},n))):null}),e("div",{className:A?"jer-collection-error-row":"jer-collection-error-row-edit",children:K&&e("span",{className:"jer-error-slug",style:h.error,children:K})}),e("div",{className:"jer-brackets",style:h.bracket,children:re.close})]})]})})},re={ITEM_SINGLE:"{{count}} item",ITEMS_MULTIPLE:"{{count}} items",KEY_NEW:"Enter new key",ERROR_KEY_EXISTS:"Key already exists",ERROR_INVALID_JSON:"Invalid JSON",ERROR_UPDATE:"Update unsuccessful",ERROR_DELETE:"Delete unsuccessful",ERROR_ADD:"Adding node unsuccessful",DEFAULT_STRING:"New data!",DEFAULT_NEW_KEY:"key"},oe=e=>(n,t)=>((e,n,t)=>{const r=n in e?e[n]:re[n];return void 0===t?r:null==r?void 0:r.replace("{{count}}",String(t))})(e,n,t),ie=({data:n,rootName:t="root",onUpdate:r,onEdit:o=r,onDelete:i=r,onAdd:l=r,enableClipboard:c=!0,theme:d="default",icons:u,indent:p=4,collapse:m=!1,showCollectionCount:h=!0,restrictEdit:y=!1,restrictDelete:b=!1,restrictAdd:g=!1,restrictTypeSelection:f=!1,keySort:j=!1,showArrayIndices:E=!0,defaultValue:k=null,minWidth:w=250,maxWidth:C="min(600px, 90vw)",stringTruncate:D=250,translations:N={},className:O,customNodeDefinitions:S=[]})=>{const{styles:A,setTheme:F,setIcons:T}=x(),V=s(ce(m),[m]),I=s(oe(N),[N]);a((()=>{d&&F(d),u&&T(u)}),[d,u]);const L={name:t,onEdit:(e,t)=>v(void 0,void 0,void 0,(function*(){const{currentData:r,newData:i,currentValue:a,newValue:l}=le(n,t,e,"update");if(o){const e=yield o({currentData:r,newData:i,currentValue:a,newValue:l,name:t.slice(-1)[0],path:t});return!1===e?I("ERROR_UPDATE"):e}})),onDelete:(e,t)=>v(void 0,void 0,void 0,(function*(){const{currentData:r,newData:o,currentValue:a,newValue:l}=le(n,t,e,"delete");if(i){const e=yield i({currentData:r,newData:o,currentValue:a,newValue:l,name:t.slice(-1)[0],path:t});return!1===e?I("ERROR_DELETE"):e}})),onAdd:(e,t)=>v(void 0,void 0,void 0,(function*(){const{currentData:r,newData:o,currentValue:i,newValue:a}=le(n,t,e,"add");if(l){const e=yield l({currentData:r,newData:o,currentValue:i,newValue:a,name:t.slice(-1)[0],path:t});return!1===e?I("ERROR_ADD"):e}})),showCollectionCount:h,collapseFilter:V,restrictEditFilter:ce(y),restrictDeleteFilter:ce(b),restrictAddFilter:ce(g),restrictTypeSelection:f,enableClipboard:c,keySort:j,showArrayIndices:E,indent:p,defaultValue:k,stringTruncate:D,translate:I,customNodeDefinitions:S,parentData:null};return A?e("div",{className:"jer-editor-container "+O,style:Object.assign(Object.assign({},A.container),{minWidth:w,maxWidth:C}),children:ne(n)?e(te,Object.assign({data:n,path:[]},L)):e(q,Object.assign({data:n,path:[],showLabel:!0},L))}):null},ae=n=>e(O,{children:e(ie,Object.assign({},n))}),le=(e,n,t,r)=>{if(0===n.length)return{currentData:e,newData:t,currentValue:e,newValue:t};const o="add"!==r?u(e,n):void 0;return{currentData:e,newData:d(p(e),n,t,{remove:"delete"===r}),currentValue:o,newValue:"update"===r?t:void 0}},ce=e=>"boolean"==typeof e?()=>e:"number"==typeof e?({level:n})=>n>=e:e;export{ae as JsonEditor,w as themes}; |
{ | ||
"name": "json-edit-react", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"description": "React component for editing or viewing JSON/object data", | ||
@@ -19,3 +19,3 @@ "main": "build/index.cjs.js", | ||
"compile": "rimraf ./build && tsc", | ||
"release": "yarn build && yarn publish", | ||
"release": "yarn publish", | ||
"release-demo": "cd demo && yarn deploy" | ||
@@ -22,0 +22,0 @@ }, |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
133203
413
2
1