Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: return parent paths on edit #65

Merged
merged 1 commit into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 16 additions & 12 deletions src/components/json-node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ import type { CustomizeNode, CustomizeOptions } from '../types'
interface Props {
node: any
depth: number
deleteHandle?: (indexOrName: string | number) => void
editHandle?: (indexOrName: string | number, newValue: any, oldValue: any) => void
deleteHandle?: (indexOrName: string | number, parentPath: string[]) => void
editHandle?: (indexOrName: string | number, newValue: any, oldValue: any, parentPath: string[]) => void
indexOrName?: number | string
parent?: Record<string, any> | Array<any>
parentPath: string[]
}

export default function JsonNode({ node, depth, deleteHandle: _deleteHandle, indexOrName, parent, editHandle }: Props) {
export default function JsonNode({ node, depth, deleteHandle: _deleteHandle, indexOrName, parent, editHandle, parentPath }: Props) {
// prettier-ignore
const { collapseStringsAfterLength, enableClipboard, editable, src, onDelete, onChange, customizeNode, matchesURL, urlRegExp, EditComponent, DoneComponent, CancelComponent, CustomOperation } = useContext(JsonViewContext)

Expand All @@ -54,6 +55,7 @@ export default function JsonNode({ node, depth, deleteHandle: _deleteHandle, ind
depth={depth}
indexOrName={indexOrName}
deleteHandle={_deleteHandle}
parentPath={parentPath}
customOptions={typeof customReturn === 'object' ? (customReturn as CustomizeOptions) : undefined}
/>
)
Expand All @@ -78,36 +80,38 @@ export default function JsonNode({ node, depth, deleteHandle: _deleteHandle, ind
try {
const parsedValue = JSON.parse(newValue)

if (editHandle) editHandle(indexOrName!, parsedValue, node)
if (editHandle) editHandle(indexOrName!, parsedValue, node, parentPath)
} catch (e) {
const trimmedStringValue = resolveEvalFailedNewValue(type, newValue)
if (editHandle) editHandle(indexOrName!, trimmedStringValue, node)
if (editHandle) editHandle(indexOrName!, trimmedStringValue, node, parentPath)
}

setEditing(false)
}, [editHandle])
}, [editHandle, indexOrName, node, parentPath, type])
const cancel = () => {
setEditing(false)
setDeleting(false)
}
const deleteHandle = () => {
setDeleting(false)
if (_deleteHandle) _deleteHandle(indexOrName!)
if (_deleteHandle) _deleteHandle(indexOrName!, parentPath)
if (onDelete)
onDelete({
value: node,
depth,
src,
indexOrName: indexOrName!,
parentType: Array.isArray(parent) ? 'array' : 'object'
parentType: Array.isArray(parent) ? 'array' : 'object',
parentPath
})
if (onChange)
onChange({
depth,
src,
indexOrName: indexOrName!,
parentType: Array.isArray(parent) ? 'array' : 'object',
type: 'delete'
type: 'delete',
parentPath
})
}

Expand Down Expand Up @@ -164,12 +168,12 @@ export default function JsonNode({ node, depth, deleteHandle: _deleteHandle, ind
{!isEditing && editableDelete(editable) && customDelete(customReturn as CustomizeOptions | undefined) && _deleteHandle && (
<DeleteSVG className='json-view--edit' onClick={() => setDeleting(true)} />
)}
{ typeof CustomOperation === 'function' ? <CustomOperation node={node} /> : null }
{typeof CustomOperation === 'function' ? <CustomOperation node={node} /> : null}
</>
)

let className = 'json-view--string'

switch (type) {
case 'number':
case 'bigint':
Expand All @@ -182,7 +186,7 @@ export default function JsonNode({ node, depth, deleteHandle: _deleteHandle, ind
className = 'json-view--null'
break
}

if (typeof (customReturn as CustomizeOptions)?.className === 'string') className += ' ' + (customReturn as CustomizeOptions).className

if (deleting) className += ' json-view--deleting'
Expand Down
85 changes: 50 additions & 35 deletions src/components/json-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,31 @@ 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 OnEdit = (params: {
newValue: any
oldValue: any
depth: number
src: any
indexOrName: string | number
parentType: 'object' | 'array' | null
parentPath: string[]
}) => void
type OnDelete = (params: {
value: any
indexOrName: string | number
depth: number
src: any
parentType: 'object' | 'array' | null
parentPath: string[]
}) => void
type OnAdd = (params: { indexOrName: string | number; depth: number; src: any; parentType: 'object' | 'array'; parentPath: string[] }) => void
type OnChange = (params: {
indexOrName: string | number
depth: number
src: any
parentType: 'object' | 'array' | null
type: 'add' | 'edit' | 'delete'
parentPath: string[]
}) => void
type OnCollapse = (params: { isCollapsing: boolean; node: Record<string, any> | Array<any>; indexOrName: string | number | undefined; depth: number }) => void

Expand Down Expand Up @@ -57,21 +73,18 @@ export const JsonViewContext = createContext({
| React.Component<{ className: string; style: React.CSSProperties }>
| undefined,
EditComponent: undefined as
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string }>
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string }>
| undefined,
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string }>
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string }>
| undefined,
CancelComponent: undefined as
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| undefined,
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| undefined,
DoneComponent: undefined as
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| undefined,
CustomOperation: undefined as
| React.FC<{ node: any }>
| React.Component<{ node: any }>
| undefined,
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| undefined,
CustomOperation: undefined as React.FC<{ node: any }> | React.Component<{ node: any }> | undefined
})

export interface JsonViewProps {
Expand Down Expand Up @@ -116,20 +129,18 @@ export interface JsonViewProps {
CopiedComponent?: React.FC<{ className: string; style: React.CSSProperties }> | React.Component<{ className: string; style: React.CSSProperties }>

EditComponent?:
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string }>
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string }>
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string }>
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string }>

CancelComponent?:
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>

DoneComponent?:
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>

CustomOperation?:
| React.FC<{ node: any }>
| React.Component<{ node: any }>
CustomOperation?: React.FC<{ node: any }> | React.Component<{ node: any }>
}

export default function JsonView({
Expand Down Expand Up @@ -174,7 +185,7 @@ export default function JsonView({
EditComponent,
CancelComponent,
DoneComponent,
CustomOperation,
CustomOperation
}: JsonViewProps) {
const [_, update] = useState(0)
const forceUpdate = useCallback(() => update(state => ++state), [])
Expand Down Expand Up @@ -219,15 +230,15 @@ export default function JsonView({
EditComponent,
CancelComponent,
DoneComponent,
CustomOperation,
CustomOperation
}}>
<code
className={'json-view' + (dark ? ' dark' : '') + (theme && theme !== 'default' ? ' json-view_' + theme : '') + (className ? ' ' + className : '')}
style={style}>
<JsonNode
node={src}
depth={1}
editHandle={(indexOrName: number | string, newValue: any, oldValue: any) => {
editHandle={(indexOrName: number | string, newValue: any, oldValue: any, parentPath: string[]) => {
setSrc(newValue)
if (onEdit)
onEdit({
Expand All @@ -236,29 +247,33 @@ export default function JsonView({
depth: 1,
src,
indexOrName: indexOrName,
parentType: null
parentType: null,
parentPath: parentPath
})
if (onChange) onChange({ type: 'edit', depth: 1, src, indexOrName: indexOrName, parentType: null })
if (onChange) onChange({ type: 'edit', depth: 1, src, indexOrName: indexOrName, parentType: null, parentPath: parentPath })
}}
deleteHandle={() => {
deleteHandle={(indexOrName: number | string, parentPath: string[]) => {
setSrc(undefined)
if (onDelete)
onDelete({
value: src,
depth: 1,
src,
indexOrName: '',
parentType: null
indexOrName: indexOrName,
parentType: null,
parentPath: parentPath
})
if (onChange)
onChange({
depth: 1,
src,
indexOrName: '',
indexOrName: indexOrName,
parentType: null,
type: 'delete'
type: 'delete',
parentPath: parentPath
})
}}
parentPath={[]}
/>
</code>
</JsonViewContext.Provider>
Expand Down
20 changes: 9 additions & 11 deletions src/components/large-array-node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ interface Props {
node: Array<any>
depth: number
index: number
deleteHandle?: (_: string | number) => void
deleteHandle?: (_: string | number, currentPath: string[]) => void
customOptions?: CustomizeOptions
startIndex: number
parentPath: string[]
}

export default function LargeArrayNode({ originNode, node, depth, index, deleteHandle: _deleteSelf, customOptions, startIndex }: Props) {
export default function LargeArrayNode({ originNode, node, depth, index, deleteHandle: _deleteSelf, customOptions, startIndex, parentPath }: Props) {
const { enableClipboard, src, onEdit, onChange, forceUpdate, displaySize, CustomOperation } = useContext(JsonViewContext)

const [fold, setFold] = useState(true)
Expand All @@ -32,9 +33,10 @@ export default function LargeArrayNode({ originNode, node, depth, index, deleteH
depth,
src,
indexOrName,
parentType: 'array'
parentType: 'array',
parentPath
})
if (onChange) onChange({ type: 'edit', depth, src, indexOrName, parentType: 'array' })
if (onChange) onChange({ type: 'edit', depth, src, indexOrName, parentType: 'array', parentPath })
forceUpdate()
},
[node, onEdit, onChange, forceUpdate]
Expand All @@ -43,6 +45,7 @@ export default function LargeArrayNode({ originNode, node, depth, index, deleteH
// Delete property
const deleteHandle = (index: number | string) => {
originNode.splice(index as number, 1)
if (_deleteSelf) _deleteSelf(index, parentPath)
forceUpdate()
}

Expand All @@ -57,7 +60,7 @@ export default function LargeArrayNode({ originNode, node, depth, index, deleteH
)}

{!fold && enableClipboard && customCopy(customOptions) && <CopyButton node={node} />}
{ typeof CustomOperation === 'function' ? <CustomOperation node={node} /> : null }
{typeof CustomOperation === 'function' ? <CustomOperation node={node} /> : null}
</>
)

Expand All @@ -78,6 +81,7 @@ export default function LargeArrayNode({ originNode, node, depth, index, deleteH
parent={node}
deleteHandle={deleteHandle}
editHandle={editHandle}
parentPath={parentPath}
/>
))}
</div>
Expand All @@ -88,12 +92,6 @@ export default function LargeArrayNode({ originNode, node, depth, index, deleteH
)}

<span>{']'}</span>

{/* {fold && ifDisplay(displaySize, depth, fold) && (
<span onClick={() => setFold(false)} className='jv-size'>
{objectSize(node)} Items
</span>
)} */}
</div>
)
}
Loading