import { createContext, useCallback, useEffect, useState } from 'react' import JsonNode from './json-node' import type { Collapsed, CustomizeCollapseStringUI, CustomizeNode, DisplaySize, Editable } from '../types' import { stringifyForCopying } from '../utils' type OnEdit = (params: { newValue: any; oldValue: any; depth: number; src: any; indexOrName: string | number; parentType: 'object' | 'array' | null }) => void type OnDelete = (params: { value: any; indexOrName: string | number; depth: number; src: any; parentType: 'object' | 'array' | null }) => void type OnAdd = (params: { indexOrName: string | number; depth: number; src: any; parentType: 'object' | 'array' }) => void type OnChange = (params: { indexOrName: string | number depth: number src: any parentType: 'object' | 'array' | null type: 'add' | 'edit' | 'delete' }) => void export const defaultURLRegExp = /^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/ export const JsonViewContext = createContext({ src: undefined as any, collapseStringsAfterLength: 99, collapseStringMode: 'directly' as 'directly' | 'word' | 'address', customizeCollapseStringUI: undefined as CustomizeCollapseStringUI | undefined, collapseObjectsAfterLength: 20, collapsed: false as Collapsed, enableClipboard: true, editable: false as Editable, onEdit: undefined as OnEdit | undefined, onDelete: undefined as OnDelete | undefined, onAdd: undefined as OnAdd | undefined, onChange: undefined as OnChange | undefined, forceUpdate: () => {}, customizeNode: undefined as CustomizeNode | undefined, customizeCopy: (() => {}) as (node: any) => any, displaySize: undefined as DisplaySize, matchesURL: false, urlRegExp: defaultURLRegExp, ignoreLargeArray: false }) export interface JsonViewProps { src: any collapseStringsAfterLength?: number collapseStringMode?: 'directly' | 'word' | 'address' customizeCollapseStringUI?: CustomizeCollapseStringUI collapseObjectsAfterLength?: number collapsed?: Collapsed enableClipboard?: boolean editable?: Editable onEdit?: OnEdit onDelete?: OnDelete onAdd?: OnAdd onChange?: OnChange customizeNode?: CustomizeNode customizeCopy?: (node: any) => any dark?: boolean theme?: 'default' | 'a11y' | 'github' | 'vscode' | 'atom' | 'winter-is-coming' displaySize?: DisplaySize style?: React.CSSProperties className?: string matchesURL?: boolean urlRegExp?: RegExp ignoreLargeArray?: boolean } export default function JsonView({ src: _src, collapseStringsAfterLength = 99, collapseStringMode = 'directly', customizeCollapseStringUI, collapseObjectsAfterLength = 99, collapsed, enableClipboard = true, editable = false, onEdit, onDelete, onAdd, onChange, dark = false, theme = 'default', customizeNode, customizeCopy = stringifyForCopying, displaySize, style, className, matchesURL = false, urlRegExp = defaultURLRegExp, ignoreLargeArray = false }: JsonViewProps) { const [_, update] = useState(0) const forceUpdate = useCallback(() => update(state => ++state), []) const [src, setSrc] = useState(_src) useEffect(() => setSrc(_src), [_src]) return ( { setSrc(newValue) if (onEdit) onEdit({ newValue, oldValue, depth: 1, src, indexOrName: indexOrName, parentType: null }) if (onChange) onChange({ type: 'edit', depth: 1, src, indexOrName: indexOrName, parentType: null }) }} deleteHandle={() => { setSrc(undefined) if (onDelete) onDelete({ value: src, depth: 1, src, indexOrName: '', parentType: null }) if (onChange) onChange({ depth: 1, src, indexOrName: '', parentType: null, type: 'delete' }) }} /> ) }