react18-json-view
Version:
JSON viewer for react18
1 lines • 120 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../../node_modules/.pnpm/toggle-selection@1.0.6/node_modules/toggle-selection/index.js","../../node_modules/.pnpm/copy-to-clipboard@3.3.3/node_modules/copy-to-clipboard/index.js","../../src/utils.ts","../../src/svgs/angle-down.svg","../../src/svgs/copy.svg","../../src/svgs/copied.svg","../../src/components/copy-button.tsx","../../src/components/name-value.tsx","../../src/svgs/trash.svg","../../src/svgs/add-square.svg","../../src/svgs/done.svg","../../src/svgs/cancel.svg","../../src/components/large-array-node.tsx","../../src/components/large-array.tsx","../../src/components/object-node.tsx","../../src/components/long-string.tsx","../../src/svgs/edit.svg","../../src/svgs/link.svg","../../src/components/json-node.tsx","../../src/components/json-view.tsx"],"sourcesContent":["\nmodule.exports = function () {\n var selection = document.getSelection();\n if (!selection.rangeCount) {\n return function () {};\n }\n var active = document.activeElement;\n\n var ranges = [];\n for (var i = 0; i < selection.rangeCount; i++) {\n ranges.push(selection.getRangeAt(i));\n }\n\n switch (active.tagName.toUpperCase()) { // .toUpperCase handles XHTML\n case 'INPUT':\n case 'TEXTAREA':\n active.blur();\n break;\n\n default:\n active = null;\n break;\n }\n\n selection.removeAllRanges();\n return function () {\n selection.type === 'Caret' &&\n selection.removeAllRanges();\n\n if (!selection.rangeCount) {\n ranges.forEach(function(range) {\n selection.addRange(range);\n });\n }\n\n active &&\n active.focus();\n };\n};\n","\"use strict\";\n\nvar deselectCurrent = require(\"toggle-selection\");\n\nvar clipboardToIE11Formatting = {\n \"text/plain\": \"Text\",\n \"text/html\": \"Url\",\n \"default\": \"Text\"\n}\n\nvar defaultMessage = \"Copy to clipboard: #{key}, Enter\";\n\nfunction format(message) {\n var copyKey = (/mac os x/i.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\") + \"+C\";\n return message.replace(/#{\\s*key\\s*}/g, copyKey);\n}\n\nfunction copy(text, options) {\n var debug,\n message,\n reselectPrevious,\n range,\n selection,\n mark,\n success = false;\n if (!options) {\n options = {};\n }\n debug = options.debug || false;\n try {\n reselectPrevious = deselectCurrent();\n\n range = document.createRange();\n selection = document.getSelection();\n\n mark = document.createElement(\"span\");\n mark.textContent = text;\n // avoid screen readers from reading out loud the text\n mark.ariaHidden = \"true\"\n // reset user styles for span element\n mark.style.all = \"unset\";\n // prevents scrolling to the end of the page\n mark.style.position = \"fixed\";\n mark.style.top = 0;\n mark.style.clip = \"rect(0, 0, 0, 0)\";\n // used to preserve spaces and line breaks\n mark.style.whiteSpace = \"pre\";\n // do not inherit user-select (it may be `none`)\n mark.style.webkitUserSelect = \"text\";\n mark.style.MozUserSelect = \"text\";\n mark.style.msUserSelect = \"text\";\n mark.style.userSelect = \"text\";\n mark.addEventListener(\"copy\", function(e) {\n e.stopPropagation();\n if (options.format) {\n e.preventDefault();\n if (typeof e.clipboardData === \"undefined\") { // IE 11\n debug && console.warn(\"unable to use e.clipboardData\");\n debug && console.warn(\"trying IE specific stuff\");\n window.clipboardData.clearData();\n var format = clipboardToIE11Formatting[options.format] || clipboardToIE11Formatting[\"default\"]\n window.clipboardData.setData(format, text);\n } else { // all other browsers\n e.clipboardData.clearData();\n e.clipboardData.setData(options.format, text);\n }\n }\n if (options.onCopy) {\n e.preventDefault();\n options.onCopy(e.clipboardData);\n }\n });\n\n document.body.appendChild(mark);\n\n range.selectNodeContents(mark);\n selection.addRange(range);\n\n var successful = document.execCommand(\"copy\");\n if (!successful) {\n throw new Error(\"copy command was unsuccessful\");\n }\n success = true;\n } catch (err) {\n debug && console.error(\"unable to copy using execCommand: \", err);\n debug && console.warn(\"trying IE specific stuff\");\n try {\n window.clipboardData.setData(options.format || \"text\", text);\n options.onCopy && options.onCopy(window.clipboardData);\n success = true;\n } catch (err) {\n debug && console.error(\"unable to copy using clipboardData: \", err);\n debug && console.error(\"falling back to prompt\");\n message = format(\"message\" in options ? options.message : defaultMessage);\n window.prompt(message, text);\n }\n } finally {\n if (selection) {\n if (typeof selection.removeRange == \"function\") {\n selection.removeRange(range);\n } else {\n selection.removeAllRanges();\n }\n }\n\n if (mark) {\n document.body.removeChild(mark);\n }\n reselectPrevious();\n }\n\n return success;\n}\n\nmodule.exports = copy;\n","import type { Collapsed, CustomizeOptions, DisplaySize, Editable } from './types'\r\nimport copy from 'copy-to-clipboard'\r\n\r\nexport function isObject(node: any): node is Record<string, any> {\r\n\treturn Object.prototype.toString.call(node) === '[object Object]'\r\n}\r\n\r\nexport function objectSize(node: Record<string, any> | Array<any>) {\r\n\treturn Array.isArray(node) ? node.length : isObject(node) ? Object.keys(node).length : 0\r\n}\r\n\r\nexport function stringifyForCopying(node: any, space?: string | number | undefined) {\r\n\t// return single string nodes without quotes\r\n\tif (typeof node === 'string') {\r\n\t\treturn node\r\n\t}\r\n\r\n\ttry {\r\n\t\treturn JSON.stringify(\r\n\t\t\tnode,\r\n\t\t\t(key, value) => {\r\n\t\t\t\tswitch (typeof value) {\r\n\t\t\t\t\tcase 'bigint':\r\n\t\t\t\t\t\treturn String(value) + 'n'\r\n\t\t\t\t\tcase 'number':\r\n\t\t\t\t\tcase 'boolean':\r\n\t\t\t\t\tcase 'object':\r\n\t\t\t\t\tcase 'string':\r\n\t\t\t\t\t\treturn value\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\treturn String(value)\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tspace\r\n\t\t)\r\n\t} catch (error: any) {\r\n\t\treturn `${error.name}: ${error.message}` || 'JSON.stringify failed'\r\n\t}\r\n}\r\n\r\nexport async function writeClipboard(value: string) {\r\n\ttry {\r\n\t\tawait navigator.clipboard.writeText(value)\r\n\t} catch (err) {\r\n\t\tcopy(value)\r\n\t}\r\n}\r\n\r\nexport function isCollapsed(\r\n\tnode: Record<string, any> | Array<any>,\r\n\tdepth: number,\r\n\tindexOrName: number | string | undefined,\r\n\tcollapsed: Collapsed,\r\n\tcollapseObjectsAfterLength: number,\r\n\tcustomOptions?: CustomizeOptions\r\n): boolean {\r\n\tif (customOptions && customOptions.collapsed !== undefined) return !!customOptions.collapsed\r\n\tif (typeof collapsed === 'boolean') return collapsed\r\n\tif (typeof collapsed === 'number' && depth > collapsed) return true\r\n\r\n\tconst size = objectSize(node)\r\n\r\n\tif (typeof collapsed === 'function') {\r\n\t\tconst result = safeCall(collapsed, [{ node, depth, indexOrName, size }])\r\n\t\tif (typeof result === 'boolean') return result\r\n\t}\r\n\r\n\tif (Array.isArray(node) && size > collapseObjectsAfterLength) return true\r\n\tif (isObject(node) && size > collapseObjectsAfterLength) return true\r\n\treturn false\r\n}\r\nexport function isCollapsed_largeArray(\r\n\tnode: Record<string, any> | Array<any>,\r\n\tdepth: number,\r\n\tindexOrName: number | string | undefined,\r\n\tcollapsed: Collapsed,\r\n\tcollapseObjectsAfterLength: number,\r\n\tcustomOptions?: CustomizeOptions\r\n): boolean {\r\n\tif (customOptions && customOptions.collapsed !== undefined) return !!customOptions.collapsed\r\n\tif (typeof collapsed === 'boolean') return collapsed\r\n\tif (typeof collapsed === 'number' && depth > collapsed) return true\r\n\r\n\tconst size = Math.ceil(node.length / 100)\r\n\r\n\tif (typeof collapsed === 'function') {\r\n\t\tconst result = safeCall(collapsed, [{ node, depth, indexOrName, size }])\r\n\t\tif (typeof result === 'boolean') return result\r\n\t}\r\n\r\n\tif (Array.isArray(node) && size > collapseObjectsAfterLength) return true\r\n\tif (isObject(node) && size > collapseObjectsAfterLength) return true\r\n\treturn false\r\n}\r\n\r\nexport function ifDisplay(displaySize: DisplaySize, depth: number, fold: boolean) {\r\n\tif (typeof displaySize === 'boolean') return displaySize\r\n\tif (typeof displaySize === 'number' && depth > displaySize) return true\r\n\tif (displaySize === 'collapsed' && fold) return true\r\n\tif (displaySize === 'expanded' && !fold) return true\r\n\r\n\treturn false\r\n}\r\n\r\nexport function safeCall<T extends (...args: any[]) => any>(func: T, params: Parameters<T>) {\r\n\ttry {\r\n\t\treturn func(...params)\r\n\t} catch (event) {\r\n\t\treportError(event)\r\n\t}\r\n}\r\n\r\nexport function editableAdd(editable: Editable) {\r\n\tif (editable === true) return true\r\n\tif (isObject(editable) && (editable as { add: boolean }).add === true) return true\r\n}\r\nexport function editableEdit(editable: Editable) {\r\n\tif (editable === true) return true\r\n\tif (isObject(editable) && (editable as { edit: boolean }).edit === true) return true\r\n}\r\nexport function editableDelete(editable: Editable) {\r\n\tif (editable === true) return true\r\n\tif (isObject(editable) && (editable as { delete: boolean }).delete === true) return true\r\n}\r\n\r\nfunction isClassComponent(component: any) {\r\n\treturn typeof component === 'function' && !!component.prototype?.isReactComponent\r\n}\r\nexport function isReactComponent(component: any): component is (new () => React.Component<any, any>) | React.FC<any> {\r\n\treturn typeof component === 'function'\r\n}\r\n\r\nexport function customAdd(customOptions?: CustomizeOptions) {\r\n\treturn !customOptions || customOptions.add === undefined || !!customOptions.add\r\n}\r\nexport function customEdit(customOptions?: CustomizeOptions) {\r\n\treturn !customOptions || customOptions.edit === undefined || !!customOptions.edit\r\n}\r\nexport function customDelete(customOptions?: CustomizeOptions) {\r\n\treturn !customOptions || customOptions.delete === undefined || !!customOptions.delete\r\n}\r\nexport function customCopy(customOptions?: CustomizeOptions) {\r\n\treturn !customOptions || customOptions.enableClipboard === undefined || !!customOptions.enableClipboard\r\n}\r\nexport function customMatchesURL(customOptions?: CustomizeOptions) {\r\n\treturn !customOptions || customOptions.matchesURL === undefined || !!customOptions.matchesURL\r\n}\r\n\r\nexport function resolveEvalFailedNewValue(type: string, value: string) {\r\n\tif (type === 'string') {\r\n\t\treturn value.trim().replace(/^\\\"([\\s\\S]+?)\\\"$/, '$1')\r\n\t}\r\n\treturn value\r\n}\r\n","export default \"data:image/svg+xml,%3Csvg%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20%20%20%20d%3D%22M12.4733%205.80615C12.4114%205.74366%2012.3376%205.69406%2012.2564%205.66022C12.1751%205.62637%2012.088%205.60895%2012%205.60895C11.912%205.60895%2011.8249%205.62637%2011.7436%205.66022C11.6624%205.69406%2011.5886%205.74366%2011.5267%205.80615L8.47333%208.85948C8.41136%208.92197%208.33762%208.97156%208.25639%209.00541C8.17515%209.03925%208.08801%209.05668%208%209.05668C7.91199%209.05668%207.82486%209.03925%207.74362%209.00541C7.66238%208.97156%207.58864%208.92197%207.52667%208.85948L4.47333%205.80615C4.41136%205.74366%204.33762%205.69406%204.25639%205.66022C4.17515%205.62637%204.08801%205.60895%204%205.60895C3.91199%205.60895%203.82486%205.62637%203.74362%205.66022C3.66238%205.69406%203.58864%205.74366%203.52667%205.80615C3.4025%205.93105%203.33281%206.10002%203.33281%206.27615C3.33281%206.45227%203.4025%206.62124%203.52667%206.74615L6.58667%209.80615C6.96167%2010.1807%207.47%2010.3911%208%2010.3911C8.53%2010.3911%209.03833%2010.1807%209.41333%209.80615L12.4733%206.74615C12.5975%206.62124%2012.6672%206.45227%2012.6672%206.27615C12.6672%206.10002%2012.5975%205.93105%2012.4733%205.80615Z%22%20%20%20%20fill%3D%22currentColor%22%20%2F%3E%3C%2Fsvg%3E\"","export default \"data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20%20%20%20d%3D%22M17.5417%202.5H12.7917C10.609%202.5%208.83333%204.27571%208.83333%206.45833V11.2083C8.83333%2013.391%2010.609%2015.1667%2012.7917%2015.1667H17.5417C19.7243%2015.1667%2021.5%2013.391%2021.5%2011.2083V6.45833C21.5%204.27571%2019.7243%202.5%2017.5417%202.5ZM19.9167%2011.2083C19.9167%2012.5178%2018.8511%2013.5833%2017.5417%2013.5833H12.7917C11.4823%2013.5833%2010.4167%2012.5178%2010.4167%2011.2083V6.45833C10.4167%205.14892%2011.4823%204.08333%2012.7917%204.08333H17.5417C18.8511%204.08333%2019.9167%205.14892%2019.9167%206.45833V11.2083ZM15.1667%2017.5417C15.1667%2019.7243%2013.391%2021.5%2011.2083%2021.5H6.45833C4.27571%2021.5%202.5%2019.7243%202.5%2017.5417V12.7917C2.5%2010.609%204.27571%208.83333%206.45833%208.83333C6.89613%208.83333%207.25%209.188%207.25%209.625C7.25%2010.062%206.89613%2010.4167%206.45833%2010.4167C5.14892%2010.4167%204.08333%2011.4823%204.08333%2012.7917V17.5417C4.08333%2018.8511%205.14892%2019.9167%206.45833%2019.9167H11.2083C12.5178%2019.9167%2013.5833%2018.8511%2013.5833%2017.5417C13.5833%2017.1047%2013.9372%2016.75%2014.375%2016.75C14.8128%2016.75%2015.1667%2017.1047%2015.1667%2017.5417Z%22%20%20%20%20fill%3D%22currentColor%22%20%2F%3E%3C%2Fsvg%3E\"","export default \"data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20%20%20%20d%3D%22M17.25%203H6.75C5.7558%203.00119%204.80267%203.39666%204.09966%204.09966C3.39666%204.80267%203.00119%205.7558%203%206.75L3%2017.25C3.00119%2018.2442%203.39666%2019.1973%204.09966%2019.9003C4.80267%2020.6033%205.7558%2020.9988%206.75%2021H17.25C18.2442%2020.9988%2019.1973%2020.6033%2019.9003%2019.9003C20.6033%2019.1973%2020.9988%2018.2442%2021%2017.25V6.75C20.9988%205.7558%2020.6033%204.80267%2019.9003%204.09966C19.1973%203.39666%2018.2442%203.00119%2017.25%203ZM19.5%2017.25C19.5%2017.8467%2019.2629%2018.419%2018.841%2018.841C18.419%2019.2629%2017.8467%2019.5%2017.25%2019.5H6.75C6.15326%2019.5%205.58097%2019.2629%205.15901%2018.841C4.73705%2018.419%204.5%2017.8467%204.5%2017.25V6.75C4.5%206.15326%204.73705%205.58097%205.15901%205.15901C5.58097%204.73705%206.15326%204.5%206.75%204.5H17.25C17.8467%204.5%2018.419%204.73705%2018.841%205.15901C19.2629%205.58097%2019.5%206.15326%2019.5%206.75V17.25Z%22%20%20%20%20fill%3D%22currentColor%22%20%2F%3E%20%20%3Cpath%20%20%20%20d%3D%22M10.3116%2014.4507L7.83053%2011.9047C7.71181%2011.7829%207.55082%2011.7145%207.38295%2011.7145C7.21507%2011.7145%207.05408%2011.7829%206.93536%2011.9047C6.81667%2012.0266%206.75%2012.1918%206.75%2012.364C6.75%2012.5363%206.81667%2012.7015%206.93536%2012.8233L9.4164%2015.3693C9.53398%2015.49%209.67358%2015.5857%209.82723%2015.651C9.98089%2015.7164%2010.1456%2015.75%2010.3119%2015.75C10.4782%2015.75%2010.6429%2015.7164%2010.7965%2015.651C10.9502%2015.5857%2011.0898%2015.49%2011.2074%2015.3693L17.0646%209.3588C17.1833%209.23697%2017.25%209.07176%2017.25%208.8995C17.25%208.72724%2017.1833%208.56203%2017.0646%208.44021C16.9459%208.31842%2016.7849%208.25%2016.6171%208.25C16.4492%208.25%2016.2882%208.31842%2016.1695%208.44021L10.3116%2014.4507Z%22%20%20%20%20fill%3D%22%2314C786%22%20%2F%3E%3C%2Fsvg%3E\"","import { useContext, useState } from 'react'\r\nimport { ReactComponent as CopySVG } from '../svgs/copy.svg'\r\nimport { ReactComponent as CopiedSVG } from '../svgs/copied.svg'\r\nimport { JsonViewContext } from './json-view'\r\nimport { writeClipboard } from 'src/utils'\r\nimport { NodeMeta } from 'src/types'\r\n\r\ninterface Props {\r\n\tnode: any\r\n\tnodeMeta: NodeMeta\r\n}\r\n\r\nexport default function CopyButton({ node, nodeMeta }: Props) {\r\n\tconst { customizeCopy, CopyComponent, CopiedComponent } = useContext(JsonViewContext)\r\n\r\n\tconst [copied, setCopied] = useState(false)\r\n\r\n\tconst copyHandler = (event: React.MouseEvent) => {\r\n\t\tevent.stopPropagation()\r\n\r\n\t\tconst value = customizeCopy(node, nodeMeta)\r\n\r\n\t\tif (typeof value === 'string' && value) {\r\n\t\t\twriteClipboard(value)\r\n\t\t}\r\n\r\n\t\tsetCopied(true)\r\n\t\tsetTimeout(() => setCopied(false), 3000)\r\n\t}\r\n\r\n\treturn copied ? (\r\n\t\ttypeof CopiedComponent === 'function' ? (\r\n\t\t\t<CopiedComponent className='json-view--copy' style={{ display: 'inline-block' }} />\r\n\t\t) : (\r\n\t\t\t<CopiedSVG className='json-view--copy' style={{ display: 'inline-block' }} />\r\n\t\t)\r\n\t) : typeof CopyComponent === 'function' ? (\r\n\t\t<CopyComponent onClick={copyHandler} className='json-view--copy' />\r\n\t) : (\r\n\t\t<CopySVG onClick={copyHandler} className='json-view--copy' />\r\n\t)\r\n}\r\n","import { useContext } from 'react'\r\nimport { JsonViewContext } from './json-view'\r\n\r\nimport JsonNode from './json-node'\r\n\r\ninterface Props {\r\n\tindexOrName: number | string\r\n\tvalue: any\r\n\tdepth: number\r\n\tparent?: Record<string, any> | Array<any>\r\n\tparentPath: string[]\r\n\tdeleteHandle: (indexOrName: string | number, parentPath: string[]) => void\r\n\teditHandle: (indexOrName: string | number, newValue: any, oldValue: any, parentPath: string[]) => void\r\n}\r\n\r\nexport default function NameValue({ indexOrName, value, depth, deleteHandle, editHandle, parent, parentPath }: Props) {\r\n\tconst { displayArrayIndex } = useContext(JsonViewContext)\r\n\tconst isArray = Array.isArray(parent)\r\n\r\n\treturn (\r\n\t\t<div className='json-view--pair'>\r\n\t\t\t{!isArray || (isArray && displayArrayIndex) ? (\r\n\t\t\t\t<>\r\n\t\t\t\t\t<span className={typeof indexOrName === 'number' ? 'json-view--index' : 'json-view--property'}>{indexOrName}</span>:{' '}\r\n\t\t\t\t</>\r\n\t\t\t) : (\r\n\t\t\t\t<></>\r\n\t\t\t)}\r\n\t\t\t<JsonNode\r\n\t\t\t\tnode={value}\r\n\t\t\t\tdepth={depth + 1}\r\n\t\t\t\tdeleteHandle={(indexOrName, parentPath) => deleteHandle(indexOrName, parentPath)}\r\n\t\t\t\teditHandle={(indexOrName, newValue, oldValue, parentPath) => editHandle(indexOrName, newValue, oldValue, parentPath)}\r\n\t\t\t\tparent={parent}\r\n\t\t\t\tindexOrName={indexOrName}\r\n\t\t\t\tparentPath={parentPath}\r\n\t\t\t/>\r\n\t\t</div>\r\n\t)\r\n}\r\n","export default \"data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20%20%20%20d%3D%22M18.75%206H16.425C16.2509%205.15356%2015.7904%204.39301%2015.1209%203.84654C14.4515%203.30007%2013.6142%203.00109%2012.75%203L11.25%203C10.3858%203.00109%209.54849%203.30007%208.87906%203.84654C8.20963%204.39301%207.74907%205.15356%207.575%206H5.25C5.05109%206%204.86032%206.07902%204.71967%206.21967C4.57902%206.36032%204.5%206.55109%204.5%206.75C4.5%206.94891%204.57902%207.13968%204.71967%207.28033C4.86032%207.42098%205.05109%207.5%205.25%207.5H6V17.25C6.00119%2018.2442%206.39666%2019.1973%207.09966%2019.9003C7.80267%2020.6033%208.7558%2020.9988%209.75%2021H14.25C15.2442%2020.9988%2016.1973%2020.6033%2016.9003%2019.9003C17.6033%2019.1973%2017.9988%2018.2442%2018%2017.25V7.5H18.75C18.9489%207.5%2019.1397%207.42098%2019.2803%207.28033C19.421%207.13968%2019.5%206.94891%2019.5%206.75C19.5%206.55109%2019.421%206.36032%2019.2803%206.21967C19.1397%206.07902%2018.9489%206%2018.75%206ZM11.25%204.5H12.75C13.2152%204.50057%2013.6688%204.64503%2014.0487%204.91358C14.4286%205.18213%2014.7161%205.56162%2014.8717%206H9.12825C9.28394%205.56162%209.57143%205.18213%209.95129%204.91358C10.3312%204.64503%2010.7848%204.50057%2011.25%204.5ZM16.5%2017.25C16.5%2017.8467%2016.2629%2018.419%2015.841%2018.841C15.419%2019.2629%2014.8467%2019.5%2014.25%2019.5H9.75C9.15326%2019.5%208.58097%2019.2629%208.15901%2018.841C7.73705%2018.419%207.5%2017.8467%207.5%2017.25V7.5H16.5V17.25Z%22%20%20%20%20fill%3D%22currentColor%22%20%2F%3E%20%20%3Cpath%20%20%20%20d%3D%22M10.5%2016.5C10.6989%2016.5%2010.8897%2016.421%2011.0303%2016.2803C11.171%2016.1397%2011.25%2015.9489%2011.25%2015.75V11.25C11.25%2011.0511%2011.171%2010.8603%2011.0303%2010.7197C10.8897%2010.579%2010.6989%2010.5%2010.5%2010.5C10.3011%2010.5%2010.1103%2010.579%209.96967%2010.7197C9.82902%2010.8603%209.75%2011.0511%209.75%2011.25V15.75C9.75%2015.9489%209.82902%2016.1397%209.96967%2016.2803C10.1103%2016.421%2010.3011%2016.5%2010.5%2016.5Z%22%20%20%20%20fill%3D%22%23DA0000%22%20%2F%3E%20%20%3Cpath%20%20%20%20d%3D%22M13.5%2016.5C13.6989%2016.5%2013.8897%2016.421%2014.0303%2016.2803C14.171%2016.1397%2014.25%2015.9489%2014.25%2015.75V11.25C14.25%2011.0511%2014.171%2010.8603%2014.0303%2010.7197C13.8897%2010.579%2013.6989%2010.5%2013.5%2010.5C13.3011%2010.5%2013.1103%2010.579%2012.9697%2010.7197C12.829%2010.8603%2012.75%2011.0511%2012.75%2011.25V15.75C12.75%2015.9489%2012.829%2016.1397%2012.9697%2016.2803C13.1103%2016.421%2013.3011%2016.5%2013.5%2016.5Z%22%20%20%20%20fill%3D%22%23DA0000%22%20%2F%3E%3C%2Fsvg%3E\"","export default \"data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20%20%20%20d%3D%22M21%206.75V17.25C21%2019.3177%2019.3177%2021%2017.25%2021H6.75C4.68225%2021%203%2019.3177%203%2017.25V6.75C3%204.68225%204.68225%203%206.75%203H17.25C19.3177%203%2021%204.68225%2021%206.75ZM19.5%206.75C19.5%205.5095%2018.4905%204.5%2017.25%204.5H6.75C5.5095%204.5%204.5%205.5095%204.5%206.75V17.25C4.5%2018.4905%205.5095%2019.5%206.75%2019.5H17.25C18.4905%2019.5%2019.5%2018.4905%2019.5%2017.25V6.75Z%22%20%20%20%20fill%3D%22currentColor%22%20%2F%3E%20%20%3Cpath%20%20%20%20d%3D%22M15%2012.75C15.414%2012.75%2015.75%2012.4148%2015.75%2012C15.75%2011.5852%2015.414%2011.25%2015%2011.25H12.75V9C12.75%208.58525%2012.414%208.25%2012%208.25C11.586%208.25%2011.25%208.58525%2011.25%209V11.25H9C8.586%2011.25%208.25%2011.5852%208.25%2012C8.25%2012.4148%208.586%2012.75%209%2012.75H11.25V15C11.25%2015.4148%2011.586%2015.75%2012%2015.75C12.414%2015.75%2012.75%2015.4148%2012.75%2015V12.75H15Z%22%20%20%20%20fill%3D%22%2314C786%22%20%2F%3E%3C%2Fsvg%3E\"","export default \"data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20%20%20%20d%3D%22M12%203C10.22%203%208.47991%203.52784%206.99987%204.51677C5.51983%205.50571%204.36628%206.91131%203.68509%208.55585C3.0039%2010.2004%202.82567%2012.01%203.17294%2013.7558C3.5202%2015.5016%204.37737%2017.1053%205.63604%2018.364C6.89472%2019.6226%208.49836%2020.4798%2010.2442%2020.8271C11.99%2021.1743%2013.7996%2020.9961%2015.4442%2020.3149C17.0887%2019.6337%2018.4943%2018.4802%2019.4832%2017.0001C20.4722%2015.5201%2021%2013.78%2021%2012C20.9974%209.61384%2020.0484%207.32616%2018.3611%205.63889C16.6738%203.95162%2014.3862%203.00258%2012%203ZM12%2019.5C10.5166%2019.5%209.0666%2019.0601%207.83323%2018.236C6.59986%2017.4119%205.63856%2016.2406%205.07091%2014.8701C4.50325%2013.4997%204.35473%2011.9917%204.64411%2010.5368C4.9335%209.08196%205.64781%207.74559%206.6967%206.6967C7.7456%205.64781%209.08197%204.9335%2010.5368%204.64411C11.9917%204.35472%2013.4997%204.50325%2014.8701%205.0709C16.2406%205.63856%2017.4119%206.59985%2018.236%207.83322C19.0601%209.06659%2019.5%2010.5166%2019.5%2012C19.4978%2013.9885%2018.7069%2015.8948%2017.3009%2017.3009C15.8948%2018.7069%2013.9885%2019.4978%2012%2019.5Z%22%20%20%20%20fill%3D%22currentColor%22%20%2F%3E%20%20%3Cpath%20%20%20%20d%3D%22M10.8493%2013.9605L8.86443%2011.9238C8.76945%2011.8264%208.64065%2011.7716%208.50636%2011.7716C8.37206%2011.7716%208.24326%2011.8264%208.14829%2011.9238C8.05334%2012.0212%208%2012.1534%208%2012.2912C8%2012.429%208.05334%2012.5612%208.14829%2012.6587L10.1331%2014.6954C10.2272%2014.792%2010.3389%2014.8686%2010.4618%2014.9208C10.5847%2014.9731%2010.7165%2015%2010.8495%2015C10.9826%2015%2011.1143%2014.9731%2011.2372%2014.9208C11.3602%2014.8686%2011.4718%2014.792%2011.5659%2014.6954L16.2517%209.88704C16.3467%209.78958%2016.4%209.65741%2016.4%209.5196C16.4%209.38179%2016.3467%209.24962%2016.2517%209.15216C16.1567%209.05473%2016.0279%209%2015.8936%209C15.7593%209%2015.6306%209.05473%2015.5356%209.15216L10.8493%2013.9605Z%22%20%20%20%20fill%3D%22%2314C786%22%20%2F%3E%3C%2Fsvg%3E\"","export default \"data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20%20%20%20d%3D%22M15%209C14.8593%208.8594%2014.6686%208.78041%2014.4697%208.78041C14.2708%208.78041%2014.0801%208.8594%2013.9395%209L12%2010.9395L10.0605%209C9.91901%208.86338%209.72956%208.78779%209.53291%208.7895C9.33626%208.7912%209.14815%208.87008%209.0091%209.00914C8.87004%209.14819%208.79117%209.3363%208.78946%209.53295C8.78775%209.7296%208.86334%209.91905%208.99996%2010.0605L10.9395%2012L8.99996%2013.9395C8.86334%2014.081%208.78775%2014.2704%208.78946%2014.4671C8.79117%2014.6637%208.87004%2014.8518%209.0091%2014.9909C9.14815%2015.1299%209.33626%2015.2088%209.53291%2015.2105C9.72956%2015.2122%209.91901%2015.1366%2010.0605%2015L12%2013.0605L13.9395%2015C14.0809%2015.1366%2014.2704%2015.2122%2014.467%2015.2105C14.6637%2015.2088%2014.8518%2015.1299%2014.9908%2014.9909C15.1299%2014.8518%2015.2088%2014.6637%2015.2105%2014.4671C15.2122%2014.2704%2015.1366%2014.081%2015%2013.9395L13.0605%2012L15%2010.0605C15.1406%209.91985%2015.2196%209.72912%2015.2196%209.53025C15.2196%209.33138%2015.1406%209.14065%2015%209Z%22%20%20%20%20fill%3D%22%23DA0000%22%20%2F%3E%20%20%3Cpath%20%20%20%20d%3D%22M12%203C10.22%203%208.47991%203.52784%206.99987%204.51677C5.51983%205.50571%204.36628%206.91131%203.68509%208.55585C3.0039%2010.2004%202.82567%2012.01%203.17294%2013.7558C3.5202%2015.5016%204.37737%2017.1053%205.63604%2018.364C6.89472%2019.6226%208.49836%2020.4798%2010.2442%2020.8271C11.99%2021.1743%2013.7996%2020.9961%2015.4442%2020.3149C17.0887%2019.6337%2018.4943%2018.4802%2019.4832%2017.0001C20.4722%2015.5201%2021%2013.78%2021%2012C20.9974%209.61384%2020.0484%207.32616%2018.3611%205.63889C16.6738%203.95162%2014.3862%203.00258%2012%203ZM12%2019.5C10.5166%2019.5%209.0666%2019.0601%207.83323%2018.236C6.59986%2017.4119%205.63856%2016.2406%205.07091%2014.8701C4.50325%2013.4997%204.35473%2011.9917%204.64411%2010.5368C4.9335%209.08197%205.64781%207.74559%206.6967%206.6967C7.7456%205.64781%209.08197%204.9335%2010.5368%204.64411C11.9917%204.35472%2013.4997%204.50325%2014.8701%205.0709C16.2406%205.63856%2017.4119%206.59985%2018.236%207.83322C19.0601%209.06659%2019.5%2010.5166%2019.5%2012C19.4978%2013.9885%2018.7069%2015.8948%2017.3009%2017.3009C15.8948%2018.7069%2013.9885%2019.4978%2012%2019.5Z%22%20%20%20%20fill%3D%22currentColor%22%20%2F%3E%3C%2Fsvg%3E\"","import { useCallback, useContext, useState } from 'react'\r\nimport { JsonViewContext } from './json-view'\r\nimport { customCopy, objectSize, ifDisplay } from '../utils'\r\nimport { ReactComponent as AngleDownSVG } from '../svgs/angle-down.svg'\r\nimport CopyButton from './copy-button'\r\nimport NameValue from './name-value'\r\nimport type { CustomizeOptions } from '../types'\r\n\r\ninterface Props {\r\n\toriginNode: Array<any>\r\n\tnode: Array<any>\r\n\tdepth: number\r\n\tindex: number\r\n\tdeleteHandle?: (_: string | number, currentPath: string[]) => void\r\n\tcustomOptions?: CustomizeOptions\r\n\tstartIndex: number\r\n\tparent?: Record<string, any> | Array<any>\r\n\tparentPath: string[]\r\n}\r\n\r\nexport default function LargeArrayNode({ originNode, node, depth, index, deleteHandle: _deleteSelf, customOptions, startIndex, parent, parentPath }: Props) {\r\n\tconst { enableClipboard, src, onEdit, onChange, forceUpdate, displaySize, CustomOperation } = useContext(JsonViewContext)\r\n\r\n\tconst currentPath = [...parentPath, String(index)]\r\n\r\n\tconst [fold, setFold] = useState(true)\r\n\r\n\t// Edit property\r\n\tconst editHandle = useCallback(\r\n\t\t(indexOrName: number | string, newValue: any, oldValue: any) => {\r\n\t\t\toriginNode[indexOrName as number] = newValue\r\n\t\t\tif (onEdit)\r\n\t\t\t\tonEdit({\r\n\t\t\t\t\tnewValue,\r\n\t\t\t\t\toldValue,\r\n\t\t\t\t\tdepth,\r\n\t\t\t\t\tsrc,\r\n\t\t\t\t\tindexOrName,\r\n\t\t\t\t\tparentType: 'array',\r\n\t\t\t\t\tparentPath\r\n\t\t\t\t})\r\n\t\t\tif (onChange) onChange({ type: 'edit', depth, src, indexOrName, parentType: 'array', parentPath })\r\n\t\t\tforceUpdate()\r\n\t\t},\r\n\t\t[node, onEdit, onChange, forceUpdate]\r\n\t)\r\n\r\n\t// Delete property\r\n\tconst deleteHandle = (index: number | string) => {\r\n\t\toriginNode.splice(index as number, 1)\r\n\t\tif (_deleteSelf) _deleteSelf(index, parentPath)\r\n\t\tforceUpdate()\r\n\t}\r\n\r\n\tconst Icons = (\r\n\t\t<>\r\n\t\t\t{!fold && (\r\n\t\t\t\t<span onClick={() => setFold(true)} className='jv-size-chevron'>\r\n\t\t\t\t\t{ifDisplay(displaySize, depth, fold) && <span className='jv-size'>{objectSize(node)} Items</span>}\r\n\r\n\t\t\t\t\t<AngleDownSVG className='jv-chevron' />\r\n\t\t\t\t</span>\r\n\t\t\t)}\r\n\r\n\t\t\t{!fold && enableClipboard && customCopy(customOptions) && (\r\n\t\t\t\t<CopyButton node={node} nodeMeta={{ depth, indexOrName: index, parent, parentPath, currentPath }} />\r\n\t\t\t)}\r\n\t\t\t{typeof CustomOperation === 'function' ? <CustomOperation node={node} /> : null}\r\n\t\t</>\r\n\t)\r\n\r\n\treturn (\r\n\t\t<div>\r\n\t\t\t<span>{'['}</span>\r\n\r\n\t\t\t{Icons}\r\n\r\n\t\t\t{!fold ? (\r\n\t\t\t\t<div className='jv-indent'>\r\n\t\t\t\t\t{node.map((n, i) => (\r\n\t\t\t\t\t\t<NameValue\r\n\t\t\t\t\t\t\tkey={String(index) + String(i)}\r\n\t\t\t\t\t\t\tindexOrName={i + startIndex}\r\n\t\t\t\t\t\t\tvalue={n}\r\n\t\t\t\t\t\t\tdepth={depth}\r\n\t\t\t\t\t\t\tparent={node}\r\n\t\t\t\t\t\t\tdeleteHandle={deleteHandle}\r\n\t\t\t\t\t\t\teditHandle={editHandle}\r\n\t\t\t\t\t\t\tparentPath={parentPath}\r\n\t\t\t\t\t\t/>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</div>\r\n\t\t\t) : (\r\n\t\t\t\t<button onClick={() => setFold(false)} className='jv-button'>\r\n\t\t\t\t\t{startIndex} ... {startIndex + node.length - 1}\r\n\t\t\t\t</button>\r\n\t\t\t)}\r\n\r\n\t\t\t<span>{']'}</span>\r\n\t\t</div>\r\n\t)\r\n}\r\n","import { useContext, useEffect, useState } from 'react'\r\nimport { JsonViewContext } from './json-view'\r\nimport { isCollapsed_largeArray, ifDisplay, editableAdd, editableDelete, customAdd, customCopy, customDelete } from '../utils'\r\nimport { ReactComponent as AngleDownSVG } from '../svgs/angle-down.svg'\r\nimport CopyButton from './copy-button'\r\nimport { ReactComponent as DeleteSVG } from '../svgs/trash.svg'\r\nimport { ReactComponent as AddSVG } from '../svgs/add-square.svg'\r\nimport { ReactComponent as DoneSVG } from '../svgs/done.svg'\r\nimport { ReactComponent as CancelSVG } from '../svgs/cancel.svg'\r\nimport type { CustomizeOptions } from '../types'\r\nimport LargeArrayNode from './large-array-node'\r\n\r\ninterface Props {\r\n\tnode: Array<any>\r\n\tdepth: number\r\n\tindexOrName?: number | string\r\n\tdeleteHandle?: (_: string | number, currentPath: string[]) => void\r\n\tcustomOptions?: CustomizeOptions\r\n\tparent?: Record<string, any> | Array<any>\r\n\tparentPath: string[]\r\n}\r\n\r\nexport default function LargeArray({ node, depth, deleteHandle: _deleteSelf, indexOrName, customOptions, parent, parentPath }: Props) {\r\n\tconst currentPath = typeof indexOrName !== 'undefined' ? [...parentPath, String(indexOrName)] : parentPath\r\n\r\n\tconst nestCollapsedArray: any[] = []\r\n\tfor (let i = 0; i < node.length; i += 100) {\r\n\t\tnestCollapsedArray.push(node.slice(i, i + 100))\r\n\t}\r\n\r\n\tconst { collapsed, enableClipboard, collapseObjectsAfterLength, editable, onDelete, src, onAdd, CustomOperation, onChange, forceUpdate, displaySize } =\r\n\t\tuseContext(JsonViewContext)\r\n\r\n\tconst [fold, setFold] = useState(isCollapsed_largeArray(node, depth, indexOrName, collapsed, collapseObjectsAfterLength, customOptions))\r\n\tuseEffect(() => {\r\n\t\tsetFold(isCollapsed_largeArray(node, depth, indexOrName, collapsed, collapseObjectsAfterLength, customOptions))\r\n\t}, [collapsed, collapseObjectsAfterLength])\r\n\r\n\t// Delete self\r\n\tconst [deleting, setDeleting] = useState(false)\r\n\tconst deleteSelf = () => {\r\n\t\tsetDeleting(false)\r\n\t\tif (_deleteSelf) _deleteSelf(indexOrName!, parentPath)\r\n\t\tif (onDelete) onDelete({ value: node, depth, src, indexOrName: indexOrName!, parentType: 'array', parentPath })\r\n\t\tif (onChange)\r\n\t\t\tonChange({\r\n\t\t\t\ttype: 'delete',\r\n\t\t\t\tdepth,\r\n\t\t\t\tsrc,\r\n\t\t\t\tindexOrName: indexOrName!,\r\n\t\t\t\tparentType: 'array',\r\n\t\t\t\tparentPath\r\n\t\t\t})\r\n\t}\r\n\r\n\t// Add\r\n\tconst [adding, setAdding] = useState(false)\r\n\tconst add = () => {\r\n\t\tconst arr = node as unknown as any[]\r\n\t\tarr.push(null)\r\n\t\tif (onAdd) onAdd({ indexOrName: arr.length - 1, depth, src, parentType: 'array', parentPath })\r\n\t\tif (onChange) onChange({ type: 'add', indexOrName: arr.length - 1, depth, src, parentType: 'array', parentPath })\r\n\t\tforceUpdate()\r\n\t}\r\n\r\n\tconst isEditing = deleting || adding\r\n\tconst cancel = () => {\r\n\t\tsetDeleting(false)\r\n\t\tsetAdding(false)\r\n\t}\r\n\r\n\tconst Icons = (\r\n\t\t<>\r\n\t\t\t{!fold && !isEditing && (\r\n\t\t\t\t<span onClick={() => setFold(true)} className='jv-size-chevron'>\r\n\t\t\t\t\t{ifDisplay(displaySize, depth, fold) && <span className='jv-size'>{node.length} Items</span>}\r\n\r\n\t\t\t\t\t<AngleDownSVG className='jv-chevron' />\r\n\t\t\t\t</span>\r\n\t\t\t)}\r\n\r\n\t\t\t{isEditing && <DoneSVG className='json-view--edit' style={{ display: 'inline-block' }} onClick={adding ? add : deleteSelf} />}\r\n\t\t\t{isEditing && <CancelSVG className='json-view--edit' style={{ display: 'inline-block' }} onClick={cancel} />}\r\n\r\n\t\t\t{!fold && !isEditing && enableClipboard && customCopy(customOptions) && (\r\n\t\t\t\t<CopyButton node={node} nodeMeta={{ depth, indexOrName, parent, parentPath, currentPath }} />\r\n\t\t\t)}\r\n\t\t\t{!fold && !isEditing && editableAdd(editable) && customAdd(customOptions) && (\r\n\t\t\t\t<AddSVG\r\n\t\t\t\t\tclassName='json-view--edit'\r\n\t\t\t\t\tonClick={() => {\r\n\t\t\t\t\t\tadd()\r\n\t\t\t\t\t}}\r\n\t\t\t\t/>\r\n\t\t\t)}\r\n\t\t\t{!fold && !isEditing && editableDelete(editable) && customDelete(customOptions) && _deleteSelf && (\r\n\t\t\t\t<DeleteSVG className='json-view--edit' onClick={() => setDeleting(true)} />\r\n\t\t\t)}\r\n\t\t\t{typeof CustomOperation === 'function' ? <CustomOperation node={node} /> : null}\r\n\t\t</>\r\n\t)\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t<span>{'['}</span>\r\n\r\n\t\t\t{Icons}\r\n\r\n\t\t\t{!fold ? (\r\n\t\t\t\t<div className='jv-indent'>\r\n\t\t\t\t\t{nestCollapsedArray.map((item, index) => (\r\n\t\t\t\t\t\t<LargeArrayNode\r\n\t\t\t\t\t\t\tkey={String(indexOrName) + String(index)}\r\n\t\t\t\t\t\t\toriginNode={node}\r\n\t\t\t\t\t\t\tnode={item}\r\n\t\t\t\t\t\t\tdepth={depth}\r\n\t\t\t\t\t\t\tindex={index}\r\n\t\t\t\t\t\t\tstartIndex={index * 100}\r\n\t\t\t\t\t\t\tdeleteHandle={_deleteSelf}\r\n\t\t\t\t\t\t\tcustomOptions={customOptions}\r\n\t\t\t\t\t\t\tparentPath={parentPath}\r\n\t\t\t\t\t\t/>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</div>\r\n\t\t\t) : (\r\n\t\t\t\t<button onClick={() => setFold(false)} className='jv-button'>\r\n\t\t\t\t\t...\r\n\t\t\t\t</button>\r\n\t\t\t)}\r\n\r\n\t\t\t<span>{']'}</span>\r\n\r\n\t\t\t{fold && ifDisplay(displaySize, depth, fold) && (\r\n\t\t\t\t<span onClick={() => setFold(false)} className='jv-size'>\r\n\t\t\t\t\t{node.length} Items\r\n\t\t\t\t</span>\r\n\t\t\t)}\r\n\t\t</>\r\n\t)\r\n}\r\n","import { useCallback, useContext, useEffect, useRef, useState } from 'react'\r\nimport { JsonViewContext } from './json-view'\r\nimport { isObject, customAdd, customCopy, customDelete, editableAdd, editableDelete, isCollapsed, objectSize, ifDisplay } from '../utils'\r\nimport { ReactComponent as AngleDownSVG } from '../svgs/angle-down.svg'\r\nimport CopyButton from './copy-button'\r\nimport NameValue from './name-value'\r\nimport { ReactComponent as DeleteSVG } from '../svgs/trash.svg'\r\nimport { ReactComponent as AddSVG } from '../svgs/add-square.svg'\r\nimport { ReactComponent as DoneSVG } from '../svgs/done.svg'\r\nimport { ReactComponent as CancelSVG } from '../svgs/cancel.svg'\r\nimport type { CustomizeOptions } from '../types'\r\nimport LargeArray from './large-array'\r\n\r\ninterface Props {\r\n\tnode: Record<string, any> | Array<any>\r\n\tdepth: number\r\n\tindexOrName?: number | string\r\n\tdeleteHandle?: (_: string | number, currentPath: string[]) => void\r\n\tcustomOptions?: CustomizeOptions\r\n\tparent?: Record<string, any> | Array<any>\r\n\tparentPath: string[]\r\n}\r\n\r\nexport default function ObjectNode({ node, depth, indexOrName, deleteHandle: _deleteSelf, customOptions, parent, parentPath }: Props) {\r\n\tconst {\r\n\t\tcollapsed,\r\n\t\tonCollapse,\r\n\t\tenableClipboard,\r\n\t\tignoreLargeArray,\r\n\t\tcollapseObjectsAfterLength,\r\n\t\teditable,\r\n\t\tonDelete,\r\n\t\tsrc,\r\n\t\tonAdd,\r\n\t\tonEdit,\r\n\t\tonChange,\r\n\t\tforceUpdate,\r\n\t\tdisplaySize,\r\n\t\tCustomOperation\r\n\t} = useContext(JsonViewContext)\r\n\r\n\tconst currentPath = typeof indexOrName !== 'undefined' ? [...parentPath, String(indexOrName)] : parentPath\r\n\r\n\tif (!ignoreLargeArray && Array.isArray(node) && node.length > 100) {\r\n\t\treturn <LargeArray node={node} depth={depth} indexOrName={indexOrName} deleteHandle={_deleteSelf} customOptions={customOptions} parentPath={currentPath} />\r\n\t}\r\n\r\n\tconst isPlainObject = isObject(node)\r\n\r\n\tconst [fold, _setFold] = useState(isCollapsed(node, depth, indexOrName, collapsed, collapseObjectsAfterLength, customOptions))\r\n\r\n\tconst setFold = (value: boolean) => {\r\n\t\tonCollapse?.({ isCollapsing: !value, node, depth, indexOrName })\r\n\t\t_setFold(value)\r\n\t}\r\n\r\n\tuseEffect(() => {\r\n\t\tsetFold(isCollapsed(node, depth, indexOrName, collapsed, collapseObjectsAfterLength, customOptions))\r\n\t}, [collapsed, collapseObjectsAfterLength])\r\n\r\n\t// Edit property\r\n\tconst editHandle = useCallback(\r\n\t\t(indexOrName: number | string, newValue: any, oldValue: any) => {\r\n\t\t\tif (Array.isArray(node)) {\r\n\t\t\t\tnode[+indexOrName] = newValue\r\n\t\t\t} else if (node) {\r\n\t\t\t\tnode[indexOrName] = newValue\r\n\t\t\t}\r\n\t\t\tif (onEdit)\r\n\t\t\t\tonEdit({\r\n\t\t\t\t\tnewValue,\r\n\t\t\t\t\toldValue,\r\n\t\t\t\t\tdepth,\r\n\t\t\t\t\tsrc,\r\n\t\t\t\t\tindexOrName: indexOrName,\r\n\t\t\t\t\tparentType: isPlainObject ? 'object' : 'array',\r\n\t\t\t\t\tparentPath: currentPath\r\n\t\t\t\t})\r\n\t\t\tif (onChange) onChange({ type: 'edit', depth, src, indexOrName: indexOrName, parentType: isPlainObject ? 'object' : 'array', parentPath: currentPath })\r\n\t\t\tforceUpdate()\r\n\t\t},\r\n\t\t[node, onEdit, onChange, forceUpdate]\r\n\t)\r\n\r\n\t// Delete property\r\n\tconst deleteHandle = (indexOrName: number | string) => {\r\n\t\tif (Array.isArray(node)) {\r\n\t\t\tnode.splice(+indexOrName, 1)\r\n\t\t} else if (node) {\r\n\t\t\tdelete node[indexOrName]\r\n\t\t}\r\n\t\tforceUpdate()\r\n\t}\r\n\r\n\t// Delete self\r\n\tconst [deleting, setDeleting] = useState(false)\r\n\tconst deleteSelf = () => {\r\n\t\tsetDeleting(false)\r\n\t\tif (_deleteSelf) _deleteSelf(indexOrName!, currentPath)\r\n\t\tif (onDelete) onDelete({ value: node, depth, src, indexOrName: indexOrName!, parentType: isPlainObject ? 'object' : 'array', parentPath: currentPath })\r\n\t\tif (onChange)\r\n\t\t\tonChange({\r\n\t\t\t\ttype: 'delete',\r\n\t\t\t\tdepth,\r\n\t\t\t\tsrc,\r\n\t\t\t\tindexOrName: indexOrName!,\r\n\t\t\t\tparentType: isPlainObject ? 'object' : 'array',\r\n\t\t\t\tparentPath: currentPath\r\n\t\t\t})\r\n\t}\r\n\r\n\t// Add\r\n\tconst [adding, setAdding] = useState(false)\r\n\tconst inputRef = useRef<HTMLInputElement>(null)\r\n\tconst add = () => {\r\n\t\tif (isPlainObject) {\r\n\t\t\tconst inputName = inputRef.current?.value\r\n\r\n\t\t\tif (inputName) {\r\n\t\t\t\t;(node as Record<string, any>)[inputName] = null\r\n\r\n\t\t\t\tif (inputRef.current) inputRef.current.value = ''\r\n\t\t\t\tsetAdding(false)\r\n\r\n\t\t\t\tif (onAdd) onAdd({ indexOrName: inputName, depth, src, parentType: 'object', parentPath: currentPath })\r\n\t\t\t\tif (onChange) onChange({ type: 'add', indexOrName: inputName, depth, src, parentType: 'object', parentPath: currentPath })\r\n\t\t\t}\r\n\t\t} else if (Array.isArray(node)) {\r\n\t\t\tconst arr = node as unknown as any[]\r\n\t\t\tarr.push(null)\r\n\t\t\tif (onAdd) onAdd({ indexOrName: arr.length - 1, depth, src, parentType: 'array', parentPath: currentPath })\r\n\t\t\tif (onChange) onChange({ type: 'add', indexOrName: arr.length - 1, depth, src, parentType: 'array', parentPath: currentPath })\r\n\t\t}\r\n\t\tforceUpdate()\r\n\t}\r\n\tconst handleAddKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\r\n\t\tif (event.key === 'Enter') {\r\n\t\t\tevent.preventDefault()\r\n\t\t\tadd()\r\n\t\t} else if (event.key === 'Escape') {\r\n\t\t\tcancel()\r\n\t\t}\r\n\t}\r\n\r\n\tconst isEditing = deleting || adding\r\n\tconst cancel = () => {\r\n\t\tsetDeleting(false)\r\n\t\tsetAdding(false)\r\n\t}\r\n\r\n\tconst Icons = (\r\n\t\t<>\r\n\t\t\t{!fold && !isEditing && (\r\n\t\t\t\t<span onClick={() => setFold(true)} className='jv-size-chevron'>\r\n\t\t\t\t\t{ifDisplay(displaySize, depth, fold) && <span className='jv-size'>{objectSize(node)} Items</span>}\r\n\r\n\t\t\t\t\t<AngleDownSVG className='jv-chevron' />\r\n\t\t\t\t</span>\r\n\t\t\t)}\r\n\r\n\t\t\t{adding && isPlainObject && <input className='json-view--input' placeholder='property' ref={inputRef} onKeyDown={handleAddKeyDown} />}\r\n\r\n\t\t\t{isEditing && <DoneSVG className='json-view--edit' style={{ display: 'inline-block' }} onClick={adding ? add : deleteSelf} />}\r\n\t\t\t{isEditing && <CancelSVG className='json-view--edit' style={{ display: 'inline-block' }} onClick={cancel} />}\r\n\r\n\t\t\t{!fold && !isEditing && enableClipboard && customCopy(customOptions) && (\r\n\t\t\t\t<CopyButton node={node} nodeMeta={{ depth, indexOrName, parent, parentPath, currentPath }} />\r\n\t\t\t)}\r\n\t\t\t{!fold && !isEditing && editableAdd(editable) && customAdd(customOptions) && (\r\n\t\t\t\t<AddSVG\r\n\t\t\t\t\tclassName='json-view--edit'\r\n\t\t\t\t\tonClick={() => {\r\n\t\t\t\t\t\tif (isPlainObject) {\r\n\t\t\t\t\t\t\tsetAdding(true)\r\n\t\t\t\t\t\t\tsetTimeout(() => inputRef.current?.focus())\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tadd()\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}}\r\n\t\t\t\t/>\r\n\t\t\t)}\r\n\t\t\t{!fold && !isEditing && editableDelete(editable) && customDelete(customOptions) && _deleteSelf && (\r\n\t\t\t\t<DeleteSVG className='json-view--edit' onClick={() => setDeleting(true)} />\r\n\t\t\t)}\r\n\t\t\t{typeof CustomOperation === 'function' ? <CustomOperation node={node} /> : null}\r\n\t\t</>\r\n\t)\r\n\r\n\tif (Array.isArray(node)) {\r\n\t\treturn (\r\n\t\t\t<>\r\n\t\t\t\t<span>{'['}</span>\r\n\r\n\t\t\t\t{Icons}\r\n\r\n\t\t\t\t{!fold ? (\r\n\t\t\t\t\t<div className='jv-indent'>\r\n\t\t\t\t\t\t{node.map((n, i) => (\r\n\t\t\t\t\t\t\t<NameValue\r\n\t\t\t\t\t\t\t\tkey={String(indexOrName) + String(i)}\r\n\t\t\t\t\t\t\t\tindexOrName={i}\r\n\t\t\t\t\t\t\t\tvalue={n}\r\n\t\t\t\t\t\t\t\tdepth={depth}\r\n\t\t\t\t\t\t\t\tparent={node}\r\n\t\t\t\t\t\t\t\tdeleteHandle={deleteHandle}\r\n\t\t\t\t\t\t\t\teditHandle={editHandle}\r\n\t\t\t\t\t\t\t\tparentPath={currentPath}\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t))}\r\n\t\t\t\t\t</div>\r\n\t\t\t\t) : (\r\n\t\t\t\t\t<button onClick={() => setFold(false)} className='jv-button'>\r\n\t\t\t\t\t\t...\r\n\t\t\t\t\t</button>\r\n\t\t\t\t)}\r\n\r\n\t\t\t\t<span>{']'}</span>\r\n\r\n\t\t\t\t{fold && ifDisplay(displaySize, depth, fold) && (\r\n\t\t\t\t\t<span onClick={() => setFold(false)} className='jv-size'>\r\n\t\t\t\t\t\t{objectSize(node)} Items\r\n\t\t\t\t\t</span>\r\n\t\t\t\t)}\r\n\t\t\t</>\r\n\t\t)\r\n\t} else if (isPlainObject) {\r\n\t\treturn (\r\n\t\t\t<>\r\n\t\t\t\t<span>{'{'}</span>\r\n\r\n\t\t\t\t{Icons}\r\n\r\n\t\t\t\t{!fold ? (\r\n\t\t\t\t\t<div className='jv-indent'>\r\n\t\t\t\t\t\t{Object.entries(node).map(([name, value]) => (\r\n\t\t\t\t\t\t\t<NameValue\r\n\t\t\t\t\t\t\t\tkey={String(indexOrName) + String(name)}\r\n\t\t\t\t\t\t\t\tindexOrName={name}\r\n\t\t\t\t\t\t\t\tvalue={value}\r\n\t\t\t\t\t\t\t\tdepth={depth}\r\n\t\t\t\t\t\t\t\tparent={node}\r\n\t\t\t\t\t\t\t\tdeleteHandle={deleteHandle}\r\n\t\t\t\t\t\t\t\teditHandle={editHandle}\r\n\t\t\t\t\t\t\t\tparentPath={currentPath}\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t))}\r\n\t\t\t\t\t</div>\r\n\t\t\t\t) : (\r\n\t\t\t\t\t<button onClick={() => setFold(false)} className='jv-button'>\r\n\t\t\t\t\t\t...\r\n\t\t\t\t\t</button>\r\n\t\t\t\t)}\r\n\r\n\t\t\t\t<span>{'}'}</span>\r\n\r\n\t\t\t\t{fold && ifDisplay(displaySize, depth, fold) && (\r\n\t\t\t\t\t<span onClick={() => setFold(false)} className='jv-size'>\r\n\t\t\t\t\t\t{objectSize(node)} Items\r\n\t\t\t\t\t</span>\r\n\t\t\t\t)}\r\n\t\t\t</>\r\n\t\t)\r\n\t} else {\r\n\t\treturn <span>{String(node)}</span>\r\n\t}\r\n}\r\n","import React, { useContext, useRef, useState } from 'react'\r\nimport { JsonViewContext } from './json-view'\r\n\r\ninterface Props {\r\n\tstr: string\r\n\tclassName: string\r\n\tctrlClick: ((event: React.MouseEvent) => void) | undefined\r\n}\r\n\r\nconst LongString = React.forwardRef<HTMLSpanElement, Props>(({ str, className, ctrlClick }, ref) => {\r\n\tlet { collapseStringMode, collapseStringsAfterLength, customizeCollapseStringUI } = useContext(JsonViewContext)\r\n\tconst [truncated, setTruncated] = useState(true)\r\n\tconst strRef = useRef<HTMLSpanElement>(null)\r\n\r\n\tcollapseStringsAfterLength = collapseStringsAfterLength > 0 ? collapseStringsAfterLength : 0\r\n\r\n\tconst str_show = str.replace(/\\s+/g, ' ')\r\n\tconst collapseStringUI =\r\n\t\ttypeof customizeCollapseStringUI === 'function'\r\n\t\t\t? customizeCollapseStringUI(str_show, truncated)\r\n\t\t\t: typeof customizeCollapseStringUI === 'string'\r\n\t\t\t? customizeCollapseStringUI\r\n\t\t\t: '...'\r\n\r\n\tconst clickToTruncateOrEdit = (event: React.MouseEvent) => {\r\n\t\tif ((event.ctrlKey || event.metaKey) && ctrlClick) {\r\n\t\t\tctrlClick(event)\r\n\t\t} else {\r\n\t\t\tconst selection = window.getSelection()\r\n\r\n\t\t\tif (selection && selection.anchorOffset !== selection.focusOffset && selection.anchorNode?.parentElement === strRef.current) return\r\n\r\n\t\t\tsetTruncated(!truncated)\r\n\t\t}\r\n\t}\r\n\r\n\tif (str.length <= collapseStringsAfterLength)\r\n\t\treturn (\r\n\t\t\t<span ref={strRef} className={className} onClick={ctrlClick}>\r\n\t\t\t\t\"{str}\"\r\n\t\t\t</span>\r\n\t\t)\r\n\r\n\tif (collapseStringMode === 'address')\r\n\t\treturn str.length <= 10 ? (\r\n\t\t\t<span ref={strRef} className={className} onClick={ctrlClick}>\r\n\t\t\t\t\"{str}\"\r\n\t\t\t</span>\r\n\t\t) : (\r\n\t\t\t<span ref={strRef} onClick={clickToTruncateOrEdit} className={className + ' cursor-pointer'}>\r\n\t\t\t\t\"{truncated ? [str_show.slice(0, 6), collapseStringUI, str_show.slice(-4)] : str}\"\r\n\t\t\t</span>\r\n\t\t)\r\n\r\n\tif (collapseStringMode === 'directly') {\r\n\t\treturn (\r\n\t\t\t<span ref={strRef} onClick={clickToTruncateOrEdit} className={className + ' cursor-pointer'}>\r\n\t\t\t\t\"{truncated ? [str_show.slice(0, collapseStringsAfterLength), collapseStringUI] : str}\"\r\n\t\t\t</span>\r\n\t\t)\r\n\t}\r\n\r\n\tif (collapseStringMode === 'word') {\r\n\t\tlet index_ahead = collapseStringsAfterLength\r\n\t\tlet index_behind = collapseStringsAfterLength + 1\r\n\t\tlet str_collapsed = str_show\r\n\t\tlet count = 1\r\n\r\n\t\twhile (true) {\r\n\t\t\tif (/\\W/.test(str[index_ahead])) {\r\n\t\t\t\tstr_collapsed = str.slice(0, index_ahead)\r\n\t\t\t\tbreak\r\n\t\t\t}\r\n\t\t\tif (/\\W/.test(str[index_behind])) {\r\n\t\t\t\tstr_collapsed = str.slice(0, index_behind)\r\n\t\t\t\tbreak\r\n\t\t\t}\r\n\t\t\tif (count === 6) {\r\n\t\t\t\tstr_collapsed = str.slice(0, collapseStringsAfterLength)\r\n\t\t\t\tbreak\r\n\t\t\t}\r\n\r\n\t\t\tcount++\r\n\t\t\tindex_ahead--\r\n\t\t\tindex_behind++\r\n\t\t}\r\n\r\n\t\treturn (\r\n\t\t\t<span ref={strRef} onClick={clickToTruncateOrEdit} className={className + ' cursor-pointer'}>\r\n\t\t\t\t\"{truncated ? [str_collapsed, collapseStringUI] : str}\"\r\n\t\t\t</span>\r\n\t\t)\r\n\t}\r\n\r\n\treturn (\r\n\t\t<span ref={strRef} className={className}>\r\n\t\t\t\"{str}\"\r\n\t\t</span>\r\n\t)\r\n})\r\n\r\nexport default LongString\r\n","export default \"data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20%20%20%20d%3D%22M17.25%203H6.75C4.68225%203%203%204.68225%203%206.75V17.25C3%2019.3177%204.68225%2021%206.75%2021H17.25C19.3177%2021%2021%2019.3177%2021%2017.25V6.75C21%204.68225%2019.3177%203%2017.25%203ZM19.5%2017.25C19.5%2018.4905%2018.4905%2019.5%2017.25%2019.5H6.75C5.5095%2019.5%204.5%2018.4905%204.5%2017.25V6.75C4.5%205.5095%205.5095%204.5%206.75%204.5H17.25C18.4905%204.5%2019.5%205.5095%2019.5%206.75V17.25ZM13.4092%207.78425L8.379%2012.8145C7.81275%2013.3808%207.5%2014.1345%207.5%2014.9355V16.125C7.5%2016.5397%207.836%2016.875%208.25%2016.875H9.4395C10.2405%2016.875%2010.9942%2016.563%2011.5605%2015.996L16.5908%2010.9658C17.4683%2010.0883%2017.4683%208.66175%2016.5908%207.78425C15.7403%206.9345%2014.259%206.9345%2013.4092%207.78425ZM10.5%2014.9355C10.2203%2015.2145%209.834%2015.375%209.4395%2015.375H9V14.9355C9%2014.535%209.156%2014.1585%209.4395%2013.875L12.627%2010.6875L13.6875%2011.748L10.5%2014.9355ZM15.5303%209.90525L14.748%2010.6875L