atom.io 0.33.10 → 0.33.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/index.js +2 -43
- package/dist/react/index.js.map +1 -1
- package/dist/react-devtools/index.css +173 -42
- package/dist/react-devtools/index.css.map +1 -1
- package/dist/react-devtools/index.d.ts +4 -1
- package/dist/react-devtools/index.d.ts.map +1 -1
- package/dist/react-devtools/index.js +381 -271
- package/dist/react-devtools/index.js.map +1 -1
- package/dist/use-o-BrXc7Qro.js +47 -0
- package/dist/use-o-BrXc7Qro.js.map +1 -0
- package/package.json +1 -1
- package/src/react-devtools/Button.tsx +1 -1
- package/src/react-devtools/devtools.css +173 -42
- package/src/react-devtools/json-editor/default-components.tsx +4 -1
- package/src/react-devtools/json-editor/editors-by-type/array-editor.tsx +105 -20
- package/src/react-devtools/json-editor/editors-by-type/object-editor.tsx +121 -46
- package/src/react-devtools/json-editor/editors-by-type/primitive-editors.tsx +5 -0
- package/src/react-devtools/json-editor/editors-by-type/utilities/object-properties.ts +30 -8
- package/src/react-devtools/json-editor/index.ts +0 -25
- package/src/react-devtools/json-editor/json-editor-internal.tsx +99 -54
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
main[data-css="atom_io_devtools"] {
|
|
2
2
|
--fg-color: #ccc;
|
|
3
3
|
--fg-light: #aaa;
|
|
4
|
+
--fg-soft: #777;
|
|
4
5
|
--fg-faint: #555;
|
|
6
|
+
--fg-hint: #333;
|
|
7
|
+
--fg-max: #fff;
|
|
5
8
|
--bg-color: #111;
|
|
6
9
|
--bg-accent: #00f;
|
|
10
|
+
--bg-max: #000;
|
|
7
11
|
--bg-tint1: #222;
|
|
12
|
+
--bg-tint2: #333;
|
|
8
13
|
--fg-border: 1px solid var(--fg-color);
|
|
14
|
+
--fg-border-soft: 1px solid var(--fg-soft);
|
|
15
|
+
--fg-border-hint: 1px solid var(--fg-hint);
|
|
9
16
|
@media (prefers-color-scheme: light) {
|
|
10
17
|
--fg-color: #444;
|
|
11
18
|
--fg-light: #777;
|
|
19
|
+
--fg-soft: #888;
|
|
12
20
|
--fg-faint: #999;
|
|
21
|
+
--fg-hint: #ccc;
|
|
22
|
+
--fg-max: #000;
|
|
13
23
|
--bg-color: #ddd;
|
|
14
24
|
--bg-accent: #0ff;
|
|
25
|
+
--bg-max: #fff;
|
|
15
26
|
--bg-tint1: #e3e3e3;
|
|
27
|
+
--bg-tint2: #f3f3f3;
|
|
16
28
|
}
|
|
17
29
|
& {
|
|
18
30
|
pointer-events: all;
|
|
@@ -42,14 +54,20 @@ main[data-css="atom_io_devtools"] {
|
|
|
42
54
|
display: flex;
|
|
43
55
|
justify-content: space-between;
|
|
44
56
|
h1 {
|
|
45
|
-
margin:
|
|
57
|
+
margin: 2px 4px;
|
|
46
58
|
font-size: 24px;
|
|
47
59
|
font-family: charter, serif;
|
|
48
60
|
}
|
|
49
61
|
nav {
|
|
62
|
+
position: relative;
|
|
50
63
|
display: flex;
|
|
51
64
|
flex-flow: row nowrap;
|
|
65
|
+
margin-top: 4px;
|
|
66
|
+
overflow-x: scroll;
|
|
67
|
+
overflow-y: visible;
|
|
68
|
+
height: 24px;
|
|
52
69
|
button {
|
|
70
|
+
height: 24px;
|
|
53
71
|
cursor: pointer;
|
|
54
72
|
background: none;
|
|
55
73
|
border: none;
|
|
@@ -58,10 +76,9 @@ main[data-css="atom_io_devtools"] {
|
|
|
58
76
|
z-index: 1000;
|
|
59
77
|
&:disabled {
|
|
60
78
|
cursor: default;
|
|
61
|
-
background-color: var(--
|
|
62
|
-
color: var(--
|
|
79
|
+
background-color: var(--fg-color);
|
|
80
|
+
color: var(--bg-color);
|
|
63
81
|
border: var(--fg-border);
|
|
64
|
-
border-bottom: none;
|
|
65
82
|
}
|
|
66
83
|
}
|
|
67
84
|
}
|
|
@@ -69,6 +86,10 @@ main[data-css="atom_io_devtools"] {
|
|
|
69
86
|
> main {
|
|
70
87
|
background: var(--bg-tint1);
|
|
71
88
|
}
|
|
89
|
+
> main::before {
|
|
90
|
+
background-color: black;
|
|
91
|
+
height: 10px;
|
|
92
|
+
}
|
|
72
93
|
main {
|
|
73
94
|
overflow-y: scroll;
|
|
74
95
|
flex-grow: 1;
|
|
@@ -86,7 +107,7 @@ main[data-css="atom_io_devtools"] {
|
|
|
86
107
|
}
|
|
87
108
|
.node > .node {
|
|
88
109
|
margin: 0px 2px 2px 18px;
|
|
89
|
-
border-left: var(--fg-border);
|
|
110
|
+
border-left: var(--fg-border-soft);
|
|
90
111
|
&:last-of-type {
|
|
91
112
|
margin-bottom: 6px;
|
|
92
113
|
}
|
|
@@ -100,32 +121,21 @@ main[data-css="atom_io_devtools"] {
|
|
|
100
121
|
&.transaction_update {
|
|
101
122
|
padding: 0;
|
|
102
123
|
}
|
|
103
|
-
header {
|
|
124
|
+
> header {
|
|
104
125
|
display: flex;
|
|
105
126
|
flex-flow: row;
|
|
106
127
|
position: sticky;
|
|
107
128
|
z-index: 999;
|
|
108
129
|
top: 0;
|
|
109
130
|
height: 22px;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
background: none;
|
|
113
|
-
border: none;
|
|
114
|
-
width: 20px;
|
|
115
|
-
color: var(--fg-light);
|
|
116
|
-
&.open {
|
|
117
|
-
transform: rotate(90deg);
|
|
118
|
-
}
|
|
119
|
-
&:disabled {
|
|
120
|
-
cursor: default;
|
|
121
|
-
color: var(--fg-faint);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
131
|
+
background: var(--bg-tint2);
|
|
132
|
+
border-bottom: var(--fg-border-soft);
|
|
124
133
|
> main {
|
|
125
134
|
display: flex;
|
|
126
135
|
flex-flow: row;
|
|
127
136
|
cursor: help;
|
|
128
137
|
align-items: center;
|
|
138
|
+
flex-shrink: 0;
|
|
129
139
|
* {
|
|
130
140
|
height: 100%;
|
|
131
141
|
display: flex;
|
|
@@ -146,25 +156,34 @@ main[data-css="atom_io_devtools"] {
|
|
|
146
156
|
}
|
|
147
157
|
> .json_viewer {
|
|
148
158
|
color: var(--fg-light);
|
|
159
|
+
font-size: 14px;
|
|
160
|
+
flex-shrink: 1;
|
|
161
|
+
overflow-x: scroll;
|
|
149
162
|
}
|
|
150
163
|
> .json_editor,
|
|
151
164
|
> .json_viewer {
|
|
152
165
|
display: flex;
|
|
166
|
+
flex-shrink: 1;
|
|
167
|
+
z-index: -1;
|
|
168
|
+
overflow-x: scroll;
|
|
153
169
|
align-items: center;
|
|
154
|
-
border-left:
|
|
155
|
-
|
|
156
|
-
|
|
170
|
+
border-left: var(--fg-border-soft);
|
|
171
|
+
white-space: pre;
|
|
172
|
+
background: var(--bg-tint2);
|
|
173
|
+
&:focus-within {
|
|
174
|
+
background-color: var(--bg-max);
|
|
175
|
+
outline: 2px solid var(--fg-max);
|
|
176
|
+
* {
|
|
177
|
+
color: var(--fg-max);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
&.nu * {
|
|
157
181
|
display: flex;
|
|
158
182
|
height: 100%;
|
|
159
183
|
}
|
|
160
184
|
> span {
|
|
161
185
|
padding: 0px 5px;
|
|
162
|
-
border-left: var(--fg-color);
|
|
163
186
|
z-index: 0;
|
|
164
|
-
&:focus-within {
|
|
165
|
-
outline: 4px solid var(--fg-color);
|
|
166
|
-
background: var(--bg-accent);
|
|
167
|
-
}
|
|
168
187
|
}
|
|
169
188
|
input {
|
|
170
189
|
outline: none;
|
|
@@ -281,6 +300,41 @@ main[data-css="atom_io_devtools"] {
|
|
|
281
300
|
}
|
|
282
301
|
|
|
283
302
|
.json_editor {
|
|
303
|
+
display: flex;
|
|
304
|
+
flex-flow: column;
|
|
305
|
+
align-items: flex-start;
|
|
306
|
+
> header {
|
|
307
|
+
display: flex;
|
|
308
|
+
flex-flow: row;
|
|
309
|
+
width: 100%;
|
|
310
|
+
position: relative;
|
|
311
|
+
align-items: baseline;
|
|
312
|
+
overflow: hidden;
|
|
313
|
+
white-space: nowrap;
|
|
314
|
+
> .json_viewer {
|
|
315
|
+
flex-shrink: 1;
|
|
316
|
+
overflow-x: scroll;
|
|
317
|
+
height: 21px;
|
|
318
|
+
font-size: 14px;
|
|
319
|
+
display: flex;
|
|
320
|
+
align-items: center;
|
|
321
|
+
margin-left: 6px;
|
|
322
|
+
color: var(--fg-light);
|
|
323
|
+
}
|
|
324
|
+
> button {
|
|
325
|
+
padding: 0;
|
|
326
|
+
&.carat {
|
|
327
|
+
line-height: 0.5em;
|
|
328
|
+
font-size: 14px;
|
|
329
|
+
align-self: flex-start;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
> .json_editor_array,
|
|
334
|
+
> .json_editor_object {
|
|
335
|
+
width: 100%;
|
|
336
|
+
flex-grow: 1;
|
|
337
|
+
}
|
|
284
338
|
input {
|
|
285
339
|
font-family: theia, monospace;
|
|
286
340
|
background: none;
|
|
@@ -288,12 +342,36 @@ main[data-css="atom_io_devtools"] {
|
|
|
288
342
|
border: none;
|
|
289
343
|
}
|
|
290
344
|
}
|
|
345
|
+
input,
|
|
346
|
+
button,
|
|
347
|
+
select {
|
|
348
|
+
&:focus-within {
|
|
349
|
+
outline: 2px solid var(--fg-max);
|
|
350
|
+
background: var(--bg-max);
|
|
351
|
+
color: var(--fg-max);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
button:disabled {
|
|
355
|
+
cursor: default;
|
|
356
|
+
> span.json_editor_icon {
|
|
357
|
+
color: var(--fg-hint);
|
|
358
|
+
}
|
|
359
|
+
&:hover {
|
|
360
|
+
background: none;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
input::selection {
|
|
364
|
+
background: var(--bg-accent);
|
|
365
|
+
}
|
|
366
|
+
|
|
291
367
|
button {
|
|
292
368
|
background: none;
|
|
293
369
|
color: #777;
|
|
294
370
|
border: none;
|
|
295
371
|
font-family: theia, monospace;
|
|
296
372
|
font-size: 14px;
|
|
373
|
+
height: 21px;
|
|
374
|
+
min-width: 21px;
|
|
297
375
|
margin: none;
|
|
298
376
|
padding: 4px;
|
|
299
377
|
padding-bottom: 6px;
|
|
@@ -323,25 +401,78 @@ main[data-css="atom_io_devtools"] {
|
|
|
323
401
|
background-color: #f055;
|
|
324
402
|
}
|
|
325
403
|
.json_editor_key {
|
|
326
|
-
padding-right:
|
|
404
|
+
padding-right: 0px;
|
|
405
|
+
&::after {
|
|
406
|
+
content: ":";
|
|
407
|
+
}
|
|
327
408
|
input {
|
|
328
|
-
color:
|
|
329
|
-
@media (prefers-color-scheme: light) {
|
|
330
|
-
color: #777;
|
|
331
|
-
}
|
|
409
|
+
color: var(--fg-color);
|
|
332
410
|
}
|
|
333
411
|
}
|
|
334
|
-
.json_editor_object
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
.json_editor_properties
|
|
341
|
-
|
|
342
|
-
|
|
412
|
+
.json_editor_object,
|
|
413
|
+
.json_editor_array {
|
|
414
|
+
border-left: var(--fg-border-soft);
|
|
415
|
+
padding-left: 10px;
|
|
416
|
+
margin-left: 10px;
|
|
417
|
+
width: calc(100% - 21px);
|
|
418
|
+
.json_editor_properties,
|
|
419
|
+
.json_editor_elements {
|
|
420
|
+
.json_editor_property,
|
|
421
|
+
.json_editor_element {
|
|
422
|
+
display: flex;
|
|
423
|
+
border-bottom: var(--fg-border-soft);
|
|
343
424
|
margin-bottom: 2px;
|
|
425
|
+
min-height: 23px;
|
|
426
|
+
> header {
|
|
427
|
+
width: 100%;
|
|
428
|
+
|
|
429
|
+
> span {
|
|
430
|
+
input {
|
|
431
|
+
min-width: 10px;
|
|
432
|
+
}
|
|
433
|
+
> * {
|
|
434
|
+
border: var(--fg-border-hint);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
344
438
|
}
|
|
439
|
+
&.readonly {
|
|
440
|
+
.json_editor_property,
|
|
441
|
+
.json_editor_element {
|
|
442
|
+
&:last-of-type {
|
|
443
|
+
border-bottom: none;
|
|
444
|
+
}
|
|
445
|
+
> span > * {
|
|
446
|
+
border: 1px solid transparent;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.json_editor_icon {
|
|
455
|
+
color: var(--fg-soft);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
button.carat {
|
|
459
|
+
border: none;
|
|
460
|
+
cursor: pointer;
|
|
461
|
+
background: none;
|
|
462
|
+
&:focus-within {
|
|
463
|
+
outline: none;
|
|
464
|
+
background: none;
|
|
465
|
+
}
|
|
466
|
+
> .json_editor_icon {
|
|
467
|
+
line-height: 4px;
|
|
468
|
+
}
|
|
469
|
+
&.open {
|
|
470
|
+
transform: rotate(90deg);
|
|
471
|
+
}
|
|
472
|
+
&:disabled {
|
|
473
|
+
> .json_editor_icon {
|
|
474
|
+
cursor: default;
|
|
475
|
+
color: var(--fg-hint);
|
|
345
476
|
}
|
|
346
477
|
}
|
|
347
478
|
}
|
|
@@ -18,6 +18,7 @@ export type JsonEditorComponents = {
|
|
|
18
18
|
disabled?: boolean
|
|
19
19
|
}>
|
|
20
20
|
DeleteIcon: FC
|
|
21
|
+
AddIcon: FC
|
|
21
22
|
|
|
22
23
|
EditorWrapper: WC<{
|
|
23
24
|
style?: CSSProperties | undefined
|
|
@@ -86,8 +87,10 @@ export const DEFAULT_JSON_EDITOR_COMPONENTS: JsonEditorComponents = {
|
|
|
86
87
|
<span className="json_editor_null" data-testid={testid} />
|
|
87
88
|
),
|
|
88
89
|
DeleteIcon: () => (
|
|
89
|
-
<span className="json_editor_icon json_editor_delete"
|
|
90
|
+
<span className="json_editor_icon json_editor_delete">×</span>
|
|
90
91
|
),
|
|
92
|
+
// big plus
|
|
93
|
+
AddIcon: () => <span className="json_editor_icon json_editor_add">+</span>,
|
|
91
94
|
MissingPropertyWrapper: ({ children, testid }) => (
|
|
92
95
|
<span className="json_editor_missing_property" data-testid={testid}>
|
|
93
96
|
{children}
|
|
@@ -1,9 +1,66 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
1
|
+
import type { RegularAtomToken } from "atom.io"
|
|
2
|
+
import { findInStore } from "atom.io/internal"
|
|
3
|
+
import type { Json, JsonTypes } from "atom.io/json"
|
|
4
|
+
import { JSON_DEFAULTS } from "atom.io/json"
|
|
5
|
+
import { useI, useO } from "atom.io/react"
|
|
6
|
+
import { DevtoolsContext } from "atom.io/react-devtools/store"
|
|
7
|
+
import { type ReactElement, useContext } from "react"
|
|
3
8
|
|
|
9
|
+
import type { JsonEditorComponents, SetterOrUpdater } from ".."
|
|
4
10
|
import type { JsonEditorProps_INTERNAL } from "../json-editor-internal"
|
|
5
11
|
import { JsonEditor_INTERNAL } from "../json-editor-internal"
|
|
6
12
|
import { makeElementSetters } from "./utilities/array-elements"
|
|
13
|
+
import {
|
|
14
|
+
makePropertyRecasters,
|
|
15
|
+
makePropertyRemovers,
|
|
16
|
+
} from "./utilities/object-properties"
|
|
17
|
+
|
|
18
|
+
type ArrayElementProps = {
|
|
19
|
+
path: ReadonlyArray<number | string>
|
|
20
|
+
isReadonly: (path: ReadonlyArray<number | string>) => boolean
|
|
21
|
+
isHidden: (path: ReadonlyArray<number | string>) => boolean
|
|
22
|
+
data: unknown
|
|
23
|
+
set: SetterOrUpdater<Json.Tree.Array>
|
|
24
|
+
remove: (() => void) | undefined
|
|
25
|
+
recast: (newType: keyof JsonTypes) => void
|
|
26
|
+
Components: JsonEditorComponents
|
|
27
|
+
testid?: string | undefined
|
|
28
|
+
viewIsOpenAtom: RegularAtomToken<boolean, string>
|
|
29
|
+
}
|
|
30
|
+
const ArrayElement = ({
|
|
31
|
+
path,
|
|
32
|
+
isReadonly,
|
|
33
|
+
isHidden,
|
|
34
|
+
data,
|
|
35
|
+
set,
|
|
36
|
+
remove,
|
|
37
|
+
recast,
|
|
38
|
+
Components,
|
|
39
|
+
testid,
|
|
40
|
+
viewIsOpenAtom,
|
|
41
|
+
}: ArrayElementProps): ReactElement => {
|
|
42
|
+
const index = path[path.length - 1]
|
|
43
|
+
const viewIsOpen = useO(viewIsOpenAtom)
|
|
44
|
+
const setViewIsOpen = useI(viewIsOpenAtom)
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<JsonEditor_INTERNAL
|
|
48
|
+
path={path}
|
|
49
|
+
name={`${index}`}
|
|
50
|
+
isReadonly={isReadonly}
|
|
51
|
+
isHidden={isHidden}
|
|
52
|
+
data={data}
|
|
53
|
+
set={set}
|
|
54
|
+
remove={remove}
|
|
55
|
+
recast={recast}
|
|
56
|
+
className="json_editor_element"
|
|
57
|
+
Components={Components}
|
|
58
|
+
isOpen={viewIsOpen}
|
|
59
|
+
setIsOpen={setViewIsOpen}
|
|
60
|
+
testid={`${testid}-element-${index}`}
|
|
61
|
+
/>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
7
64
|
|
|
8
65
|
export const ArrayEditor = ({
|
|
9
66
|
path = [],
|
|
@@ -14,25 +71,53 @@ export const ArrayEditor = ({
|
|
|
14
71
|
Components,
|
|
15
72
|
testid,
|
|
16
73
|
}: JsonEditorProps_INTERNAL<Json.Tree.Array>): ReactElement => {
|
|
74
|
+
const { viewIsOpenAtoms, store } = useContext(DevtoolsContext)
|
|
75
|
+
const disabled = isReadonly(path)
|
|
76
|
+
|
|
17
77
|
const setElement = makeElementSetters(data, set)
|
|
78
|
+
const removeElement = makePropertyRemovers(data, set)
|
|
79
|
+
const recastElement = makePropertyRecasters(data, set)
|
|
80
|
+
|
|
18
81
|
return (
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
82
|
+
<Components.ArrayWrapper>
|
|
83
|
+
<div className={`json_editor_elements${disabled ? ` readonly` : ``}`}>
|
|
84
|
+
{data.map((element, index) => {
|
|
85
|
+
const elementPath = [...path, index]
|
|
86
|
+
const pathKey = elementPath.join(`,`)
|
|
87
|
+
const viewIsOpenAtom = findInStore(
|
|
88
|
+
store,
|
|
89
|
+
viewIsOpenAtoms,
|
|
90
|
+
`${testid}__${pathKey}`,
|
|
91
|
+
)
|
|
92
|
+
return (
|
|
93
|
+
<ArrayElement
|
|
94
|
+
key={pathKey}
|
|
95
|
+
path={elementPath}
|
|
96
|
+
isReadonly={isReadonly}
|
|
97
|
+
isHidden={isHidden}
|
|
98
|
+
data={element}
|
|
99
|
+
set={setElement[index]}
|
|
100
|
+
remove={removeElement[index]}
|
|
101
|
+
recast={recastElement[index]}
|
|
102
|
+
Components={Components}
|
|
103
|
+
testid={testid}
|
|
104
|
+
viewIsOpenAtom={viewIsOpenAtom}
|
|
105
|
+
/>
|
|
106
|
+
)
|
|
107
|
+
})}
|
|
108
|
+
</div>
|
|
109
|
+
<Components.Button
|
|
110
|
+
testid={`${testid}-add-element`}
|
|
111
|
+
disabled={disabled}
|
|
112
|
+
onClick={() => {
|
|
113
|
+
set((current) => {
|
|
114
|
+
const newData = [...current, JSON_DEFAULTS.string]
|
|
115
|
+
return newData
|
|
116
|
+
})
|
|
117
|
+
}}
|
|
118
|
+
>
|
|
119
|
+
<Components.AddIcon />
|
|
120
|
+
</Components.Button>
|
|
121
|
+
</Components.ArrayWrapper>
|
|
37
122
|
)
|
|
38
123
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RegularAtomToken } from "atom.io"
|
|
2
|
+
import { findInStore } from "atom.io/internal"
|
|
3
|
+
import type { Json, JsonTypes } from "atom.io/json"
|
|
4
|
+
import { useI } from "atom.io/react/use-i"
|
|
5
|
+
import { useO } from "atom.io/react/use-o"
|
|
6
|
+
import { DevtoolsContext } from "atom.io/react-devtools/store"
|
|
2
7
|
import type { FC, ReactElement } from "react"
|
|
3
|
-
import { useRef } from "react"
|
|
8
|
+
import { useContext, useRef } from "react"
|
|
4
9
|
|
|
5
10
|
import { ElasticInput } from "../../elastic-input"
|
|
11
|
+
import type { SetterOrUpdater } from ".."
|
|
6
12
|
import type { JsonEditorComponents } from "../default-components"
|
|
7
13
|
import type { JsonEditorProps_INTERNAL } from "../json-editor-internal"
|
|
8
14
|
import { JsonEditor_INTERNAL } from "../json-editor-internal"
|
|
@@ -43,6 +49,56 @@ export const PropertyAdder: FC<PropertyAdderProps> = ({
|
|
|
43
49
|
</Components.MissingPropertyWrapper>
|
|
44
50
|
)
|
|
45
51
|
|
|
52
|
+
type ObjectPropertyProps = {
|
|
53
|
+
path: ReadonlyArray<number | string>
|
|
54
|
+
isReadonly: (path: ReadonlyArray<number | string>) => boolean
|
|
55
|
+
isHidden: (path: ReadonlyArray<number | string>) => boolean
|
|
56
|
+
data: unknown
|
|
57
|
+
set: SetterOrUpdater<Json.Tree.Object>
|
|
58
|
+
rename: (newKey: string) => void
|
|
59
|
+
remove: (() => void) | undefined
|
|
60
|
+
recast: (newType: keyof JsonTypes) => void
|
|
61
|
+
Components: JsonEditorComponents
|
|
62
|
+
testid?: string | undefined
|
|
63
|
+
viewIsOpenAtom: RegularAtomToken<boolean, string>
|
|
64
|
+
}
|
|
65
|
+
const ObjectProperty = ({
|
|
66
|
+
path,
|
|
67
|
+
isReadonly,
|
|
68
|
+
isHidden,
|
|
69
|
+
data,
|
|
70
|
+
set,
|
|
71
|
+
rename,
|
|
72
|
+
remove,
|
|
73
|
+
recast,
|
|
74
|
+
Components,
|
|
75
|
+
testid,
|
|
76
|
+
viewIsOpenAtom,
|
|
77
|
+
}: ObjectPropertyProps): ReactElement => {
|
|
78
|
+
const key = path[path.length - 1]
|
|
79
|
+
const viewIsOpen = useO(viewIsOpenAtom)
|
|
80
|
+
const setViewIsOpen = useI(viewIsOpenAtom)
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<JsonEditor_INTERNAL
|
|
84
|
+
path={path}
|
|
85
|
+
name={`${key}`}
|
|
86
|
+
isReadonly={isReadonly}
|
|
87
|
+
isHidden={isHidden}
|
|
88
|
+
data={data}
|
|
89
|
+
set={set}
|
|
90
|
+
rename={rename}
|
|
91
|
+
remove={remove}
|
|
92
|
+
recast={recast}
|
|
93
|
+
className="json_editor_property"
|
|
94
|
+
Components={Components}
|
|
95
|
+
isOpen={viewIsOpen}
|
|
96
|
+
setIsOpen={setViewIsOpen}
|
|
97
|
+
testid={`${testid}-property-${key}`}
|
|
98
|
+
/>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
46
102
|
export const ObjectEditor = <T extends Json.Tree.Object>({
|
|
47
103
|
path = [],
|
|
48
104
|
isReadonly = () => false,
|
|
@@ -52,6 +108,8 @@ export const ObjectEditor = <T extends Json.Tree.Object>({
|
|
|
52
108
|
Components,
|
|
53
109
|
testid,
|
|
54
110
|
}: JsonEditorProps_INTERNAL<T>): ReactElement => {
|
|
111
|
+
const { viewIsOpenAtoms, store } = useContext(DevtoolsContext)
|
|
112
|
+
|
|
55
113
|
const disabled = isReadonly(path)
|
|
56
114
|
|
|
57
115
|
const stableKeyMap = useRef<Record<keyof T, keyof T>>(
|
|
@@ -72,57 +130,74 @@ export const ObjectEditor = <T extends Json.Tree.Object>({
|
|
|
72
130
|
const makePropertyAdder = makePropertyCreationInterface(data, set)
|
|
73
131
|
|
|
74
132
|
return (
|
|
75
|
-
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
{Object.keys(data).map((key) => {
|
|
88
|
-
const originalKey = stableKeyMap.current[key]
|
|
89
|
-
const newPath = [...path, key]
|
|
90
|
-
const originalPath = [...path, originalKey]
|
|
133
|
+
<Components.ObjectWrapper>
|
|
134
|
+
<div className={`json_editor_properties${disabled ? ` readonly` : ``}`}>
|
|
135
|
+
{Object.keys(data).map((key) => {
|
|
136
|
+
const originalKey = stableKeyMap.current[key]
|
|
137
|
+
const propertyPath = [...path, key]
|
|
138
|
+
const originalPropertyPath = [...path, originalKey]
|
|
139
|
+
const stablePathKey = originalPropertyPath.join(`.`)
|
|
140
|
+
const viewIsOpenAtom = findInStore(
|
|
141
|
+
store,
|
|
142
|
+
viewIsOpenAtoms,
|
|
143
|
+
`${testid}__${stablePathKey}`,
|
|
144
|
+
)
|
|
91
145
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
146
|
+
return (
|
|
147
|
+
// <JsonEditor_INTERNAL
|
|
148
|
+
// key={originalPath.join(`.`)}
|
|
149
|
+
// path={newPath}
|
|
150
|
+
// name={key}
|
|
151
|
+
// isReadonly={isReadonly}
|
|
152
|
+
// isHidden={isHidden}
|
|
153
|
+
// data={data[key as keyof T]}
|
|
154
|
+
// set={setProperty[key as keyof T]}
|
|
155
|
+
// rename={renameProperty[key as keyof T]}
|
|
156
|
+
// remove={removeProperty[key as keyof T]}
|
|
157
|
+
// recast={recastProperty[key as keyof T]}
|
|
158
|
+
// className="json_editor_property"
|
|
159
|
+
// Components={Components}
|
|
160
|
+
// testid={`${testid}-property-${key}`}
|
|
161
|
+
// />
|
|
162
|
+
<ObjectProperty
|
|
163
|
+
key={stablePathKey}
|
|
164
|
+
path={propertyPath}
|
|
165
|
+
isReadonly={isReadonly}
|
|
166
|
+
isHidden={isHidden}
|
|
167
|
+
data={data[key]}
|
|
168
|
+
set={setProperty[key]}
|
|
169
|
+
rename={renameProperty[key]}
|
|
170
|
+
remove={removeProperty[key]}
|
|
171
|
+
recast={recastProperty[key]}
|
|
172
|
+
Components={Components}
|
|
173
|
+
testid={testid}
|
|
174
|
+
viewIsOpenAtom={viewIsOpenAtom}
|
|
175
|
+
/>
|
|
176
|
+
)
|
|
177
|
+
})}
|
|
178
|
+
</div>
|
|
179
|
+
{disabled ? null : (
|
|
180
|
+
<>
|
|
116
181
|
<Components.Button
|
|
182
|
+
disabled={disabled}
|
|
117
183
|
testid={`${testid}-add-property`}
|
|
118
184
|
onClick={() => {
|
|
119
185
|
makePropertyAdder(`new_property`, `string`)()
|
|
120
186
|
}}
|
|
121
187
|
>
|
|
122
|
-
|
|
188
|
+
<Components.AddIcon />
|
|
189
|
+
</Components.Button>
|
|
190
|
+
<Components.Button
|
|
191
|
+
testid={`${testid}-sort-properties`}
|
|
192
|
+
onClick={() => {
|
|
193
|
+
sortProperties()
|
|
194
|
+
}}
|
|
195
|
+
disabled={disabled}
|
|
196
|
+
>
|
|
197
|
+
Sort
|
|
123
198
|
</Components.Button>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
199
|
+
</>
|
|
200
|
+
)}
|
|
201
|
+
</Components.ObjectWrapper>
|
|
127
202
|
)
|
|
128
203
|
}
|