Skip to content

Commit a2b3cce

Browse files
authored
Merge pull request #65 from ThianHooi/feat/return-parent-paths-on-edit
feat: return parent paths on edit
2 parents 1e5636d + 4f3409a commit a2b3cce

8 files changed

Lines changed: 151 additions & 99 deletions

File tree

‎src/components/json-node.tsx‎

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ import type { CustomizeNode, CustomizeOptions } from '../types'
2626
interface Props {
2727
node: any
2828
depth: number
29-
deleteHandle?: (indexOrName: string | number) => void
30-
editHandle?: (indexOrName: string | number, newValue: any, oldValue: any) => void
29+
deleteHandle?: (indexOrName: string | number, parentPath: string[]) => void
30+
editHandle?: (indexOrName: string | number, newValue: any, oldValue: any, parentPath: string[]) => void
3131
indexOrName?: number | string
3232
parent?: Record<string, any> | Array<any>
33+
parentPath: string[]
3334
}
3435

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

@@ -54,6 +55,7 @@ export default function JsonNode({ node, depth, deleteHandle: _deleteHandle, ind
5455
depth={depth}
5556
indexOrName={indexOrName}
5657
deleteHandle={_deleteHandle}
58+
parentPath={parentPath}
5759
customOptions={typeof customReturn === 'object' ? (customReturn as CustomizeOptions) : undefined}
5860
/>
5961
)
@@ -78,36 +80,38 @@ export default function JsonNode({ node, depth, deleteHandle: _deleteHandle, ind
7880
try {
7981
const parsedValue = JSON.parse(newValue)
8082

81-
if (editHandle) editHandle(indexOrName!, parsedValue, node)
83+
if (editHandle) editHandle(indexOrName!, parsedValue, node, parentPath)
8284
} catch (e) {
8385
const trimmedStringValue = resolveEvalFailedNewValue(type, newValue)
84-
if (editHandle) editHandle(indexOrName!, trimmedStringValue, node)
86+
if (editHandle) editHandle(indexOrName!, trimmedStringValue, node, parentPath)
8587
}
8688

8789
setEditing(false)
88-
}, [editHandle])
90+
}, [editHandle, indexOrName, node, parentPath, type])
8991
const cancel = () => {
9092
setEditing(false)
9193
setDeleting(false)
9294
}
9395
const deleteHandle = () => {
9496
setDeleting(false)
95-
if (_deleteHandle) _deleteHandle(indexOrName!)
97+
if (_deleteHandle) _deleteHandle(indexOrName!, parentPath)
9698
if (onDelete)
9799
onDelete({
98100
value: node,
99101
depth,
100102
src,
101103
indexOrName: indexOrName!,
102-
parentType: Array.isArray(parent) ? 'array' : 'object'
104+
parentType: Array.isArray(parent) ? 'array' : 'object',
105+
parentPath
103106
})
104107
if (onChange)
105108
onChange({
106109
depth,
107110
src,
108111
indexOrName: indexOrName!,
109112
parentType: Array.isArray(parent) ? 'array' : 'object',
110-
type: 'delete'
113+
type: 'delete',
114+
parentPath
111115
})
112116
}
113117

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

171175
let className = 'json-view--string'
172-
176+
173177
switch (type) {
174178
case 'number':
175179
case 'bigint':
@@ -182,7 +186,7 @@ export default function JsonNode({ node, depth, deleteHandle: _deleteHandle, ind
182186
className = 'json-view--null'
183187
break
184188
}
185-
189+
186190
if (typeof (customReturn as CustomizeOptions)?.className === 'string') className += ' ' + (customReturn as CustomizeOptions).className
187191

188192
if (deleting) className += ' json-view--deleting'

‎src/components/json-view.tsx‎

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,31 @@ import JsonNode from './json-node'
33
import type { Collapsed, CustomizeCollapseStringUI, CustomizeNode, DisplaySize, Editable } from '../types'
44
import { stringifyForCopying } from '../utils'
55

6-
type OnEdit = (params: { newValue: any; oldValue: any; depth: number; src: any; indexOrName: string | number; parentType: 'object' | 'array' | null }) => void
7-
type OnDelete = (params: { value: any; indexOrName: string | number; depth: number; src: any; parentType: 'object' | 'array' | null }) => void
8-
type OnAdd = (params: { indexOrName: string | number; depth: number; src: any; parentType: 'object' | 'array' }) => void
6+
type OnEdit = (params: {
7+
newValue: any
8+
oldValue: any
9+
depth: number
10+
src: any
11+
indexOrName: string | number
12+
parentType: 'object' | 'array' | null
13+
parentPath: string[]
14+
}) => void
15+
type OnDelete = (params: {
16+
value: any
17+
indexOrName: string | number
18+
depth: number
19+
src: any
20+
parentType: 'object' | 'array' | null
21+
parentPath: string[]
22+
}) => void
23+
type OnAdd = (params: { indexOrName: string | number; depth: number; src: any; parentType: 'object' | 'array'; parentPath: string[] }) => void
924
type OnChange = (params: {
1025
indexOrName: string | number
1126
depth: number
1227
src: any
1328
parentType: 'object' | 'array' | null
1429
type: 'add' | 'edit' | 'delete'
30+
parentPath: string[]
1531
}) => void
1632
type OnCollapse = (params: { isCollapsing: boolean; node: Record<string, any> | Array<any>; indexOrName: string | number | undefined; depth: number }) => void
1733

@@ -57,21 +73,18 @@ export const JsonViewContext = createContext({
5773
| React.Component<{ className: string; style: React.CSSProperties }>
5874
| undefined,
5975
EditComponent: undefined as
60-
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string }>
61-
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string }>
62-
| undefined,
76+
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string }>
77+
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string }>
78+
| undefined,
6379
CancelComponent: undefined as
64-
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
65-
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
66-
| undefined,
80+
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
81+
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
82+
| undefined,
6783
DoneComponent: undefined as
68-
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
69-
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
70-
| undefined,
71-
CustomOperation: undefined as
72-
| React.FC<{ node: any }>
73-
| React.Component<{ node: any }>
74-
| undefined,
84+
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
85+
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
86+
| undefined,
87+
CustomOperation: undefined as React.FC<{ node: any }> | React.Component<{ node: any }> | undefined
7588
})
7689

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

118131
EditComponent?:
119-
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string }>
120-
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string }>
132+
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string }>
133+
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string }>
121134

122135
CancelComponent?:
123-
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
124-
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
136+
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
137+
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
125138

126139
DoneComponent?:
127-
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
128-
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
140+
| React.FC<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
141+
| React.Component<{ onClick: (event: React.MouseEvent) => void; className: string; style: React.CSSProperties }>
129142

130-
CustomOperation?:
131-
| React.FC<{ node: any }>
132-
| React.Component<{ node: any }>
143+
CustomOperation?: React.FC<{ node: any }> | React.Component<{ node: any }>
133144
}
134145

135146
export default function JsonView({
@@ -174,7 +185,7 @@ export default function JsonView({
174185
EditComponent,
175186
CancelComponent,
176187
DoneComponent,
177-
CustomOperation,
188+
CustomOperation
178189
}: JsonViewProps) {
179190
const [_, update] = useState(0)
180191
const forceUpdate = useCallback(() => update(state => ++state), [])
@@ -219,15 +230,15 @@ export default function JsonView({
219230
EditComponent,
220231
CancelComponent,
221232
DoneComponent,
222-
CustomOperation,
233+
CustomOperation
223234
}}>
224235
<code
225236
className={'json-view' + (dark ? ' dark' : '') + (theme && theme !== 'default' ? ' json-view_' + theme : '') + (className ? ' ' + className : '')}
226237
style={style}>
227238
<JsonNode
228239
node={src}
229240
depth={1}
230-
editHandle={(indexOrName: number | string, newValue: any, oldValue: any) => {
241+
editHandle={(indexOrName: number | string, newValue: any, oldValue: any, parentPath: string[]) => {
231242
setSrc(newValue)
232243
if (onEdit)
233244
onEdit({
@@ -236,29 +247,33 @@ export default function JsonView({
236247
depth: 1,
237248
src,
238249
indexOrName: indexOrName,
239-
parentType: null
250+
parentType: null,
251+
parentPath: parentPath
240252
})
241-
if (onChange) onChange({ type: 'edit', depth: 1, src, indexOrName: indexOrName, parentType: null })
253+
if (onChange) onChange({ type: 'edit', depth: 1, src, indexOrName: indexOrName, parentType: null, parentPath: parentPath })
242254
}}
243-
deleteHandle={() => {
255+
deleteHandle={(indexOrName: number | string, parentPath: string[]) => {
244256
setSrc(undefined)
245257
if (onDelete)
246258
onDelete({
247259
value: src,
248260
depth: 1,
249261
src,
250-
indexOrName: '',
251-
parentType: null
262+
indexOrName: indexOrName,
263+
parentType: null,
264+
parentPath: parentPath
252265
})
253266
if (onChange)
254267
onChange({
255268
depth: 1,
256269
src,
257-
indexOrName: '',
270+
indexOrName: indexOrName,
258271
parentType: null,
259-
type: 'delete'
272+
type: 'delete',
273+
parentPath: parentPath
260274
})
261275
}}
276+
parentPath={[]}
262277
/>
263278
</code>
264279
</JsonViewContext.Provider>

‎src/components/large-array-node.tsx‎

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ interface Props {
1111
node: Array<any>
1212
depth: number
1313
index: number
14-
deleteHandle?: (_: string | number) => void
14+
deleteHandle?: (_: string | number, currentPath: string[]) => void
1515
customOptions?: CustomizeOptions
1616
startIndex: number
17+
parentPath: string[]
1718
}
1819

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

2223
const [fold, setFold] = useState(true)
@@ -32,9 +33,10 @@ export default function LargeArrayNode({ originNode, node, depth, index, deleteH
3233
depth,
3334
src,
3435
indexOrName,
35-
parentType: 'array'
36+
parentType: 'array',
37+
parentPath
3638
})
37-
if (onChange) onChange({ type: 'edit', depth, src, indexOrName, parentType: 'array' })
39+
if (onChange) onChange({ type: 'edit', depth, src, indexOrName, parentType: 'array', parentPath })
3840
forceUpdate()
3941
},
4042
[node, onEdit, onChange, forceUpdate]
@@ -43,6 +45,7 @@ export default function LargeArrayNode({ originNode, node, depth, index, deleteH
4345
// Delete property
4446
const deleteHandle = (index: number | string) => {
4547
originNode.splice(index as number, 1)
48+
if (_deleteSelf) _deleteSelf(index, parentPath)
4649
forceUpdate()
4750
}
4851

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

5962
{!fold && enableClipboard && customCopy(customOptions) && <CopyButton node={node} />}
60-
{ typeof CustomOperation === 'function' ? <CustomOperation node={node} /> : null }
63+
{typeof CustomOperation === 'function' ? <CustomOperation node={node} /> : null}
6164
</>
6265
)
6366

@@ -78,6 +81,7 @@ export default function LargeArrayNode({ originNode, node, depth, index, deleteH
7881
parent={node}
7982
deleteHandle={deleteHandle}
8083
editHandle={editHandle}
84+
parentPath={parentPath}
8185
/>
8286
))}
8387
</div>
@@ -88,12 +92,6 @@ export default function LargeArrayNode({ originNode, node, depth, index, deleteH
8892
)}
8993

9094
<span>{']'}</span>
91-
92-
{/* {fold && ifDisplay(displaySize, depth, fold) && (
93-
<span onClick={() => setFold(false)} className='jv-size'>
94-
{objectSize(node)} Items
95-
</span>
96-
)} */}
9795
</div>
9896
)
9997
}

0 commit comments

Comments
 (0)