atom.io 0.33.12 → 0.33.13

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.
@@ -9,8 +9,16 @@ export const StateEditor: FC<{
9
9
  }> = ({ token }) => {
10
10
  const set = useI(token)
11
11
  const data = useO(token)
12
+ const metaPath = token.family
13
+ ? [token.family.key, token.family.subKey]
14
+ : [token.key]
12
15
  return (
13
- <JsonEditor testid={`${token.key}-state-editor`} data={data} set={set} />
16
+ <JsonEditor
17
+ testid={`${token.key}-state-editor`}
18
+ data={data}
19
+ set={set}
20
+ path={metaPath}
21
+ />
14
22
  )
15
23
  }
16
24
 
@@ -18,12 +26,16 @@ export const ReadonlySelectorViewer: FC<{
18
26
  token: ReadonlySelectorToken<unknown>
19
27
  }> = ({ token }) => {
20
28
  const data = useO(token)
29
+ const metaPath = token.family
30
+ ? [token.family.key, token.family.subKey]
31
+ : [token.key]
21
32
  return (
22
33
  <JsonEditor
23
34
  testid={`${token.key}-state-editor`}
24
35
  data={data}
25
36
  set={() => null}
26
37
  isReadonly={() => true}
38
+ path={metaPath}
27
39
  />
28
40
  )
29
41
  }
@@ -4,8 +4,12 @@ import type {
4
4
  ReadonlyPureSelectorToken,
5
5
  RegularAtomToken,
6
6
  } from "atom.io"
7
- import { getState } from "atom.io"
8
- import { findInStore } from "atom.io/internal"
7
+ import {
8
+ actUponStore,
9
+ arbitrary,
10
+ findInStore,
11
+ getFromStore,
12
+ } from "atom.io/internal"
9
13
  import type { FamilyNode, WritableTokenIndex } from "atom.io/introspection"
10
14
  import { primitiveRefinery } from "atom.io/introspection"
11
15
  import { useI, useO } from "atom.io/react"
@@ -22,6 +26,8 @@ export const StateIndexLeafNode: FC<{
22
26
  isOpenState: RegularAtomToken<boolean>
23
27
  typeState: ReadonlyPureSelectorToken<Loadable<string>>
24
28
  }> = ({ node, isOpenState, typeState }) => {
29
+ const { openCloseAllTX, store } = useContext(DevtoolsContext)
30
+
25
31
  const setIsOpen = useI(isOpenState)
26
32
  const isOpen = useO(isOpenState)
27
33
 
@@ -32,23 +38,29 @@ export const StateIndexLeafNode: FC<{
32
38
 
33
39
  const isPrimitive = Boolean(primitiveRefinery.refine(state))
34
40
 
41
+ const path = node.family ? [node.family.key, node.family.subKey] : [node.key]
42
+
35
43
  return (
36
44
  <>
37
45
  <header>
38
- <button.OpenClose
39
- isOpen={isOpen && !isPrimitive}
40
- testid={`open-close-state-${node.key}`}
41
- setIsOpen={setIsOpen}
42
- disabled={isPrimitive}
43
- />
44
46
  <main
45
47
  onClick={() => {
46
- console.log(node, getState(node))
48
+ console.log(node, getFromStore(store, node))
47
49
  }}
48
50
  onKeyUp={() => {
49
- console.log(node, getState(node))
51
+ console.log(node, getFromStore(store, node))
50
52
  }}
51
53
  >
54
+ <button.OpenClose
55
+ isOpen={isOpen && !isPrimitive}
56
+ testid={`open-close-state-${node.key}`}
57
+ onShiftClick={() => {
58
+ actUponStore(store, openCloseAllTX, arbitrary())(path, isOpen)
59
+ return false
60
+ }}
61
+ setIsOpen={setIsOpen}
62
+ disabled={isPrimitive}
63
+ />
52
64
  <h2>{node.family?.subKey ?? node.key}</h2>
53
65
  <span className="type detail">({stateType})</span>
54
66
  </main>
@@ -73,21 +85,30 @@ export const StateIndexTreeNode: FC<{
73
85
  const setIsOpen = useI(isOpenState)
74
86
  const isOpen = useO(isOpenState)
75
87
 
76
- const { typeSelectors, viewIsOpenAtoms, store } = useContext(DevtoolsContext)
88
+ const { typeSelectors, viewIsOpenAtoms, openCloseAllTX, store } =
89
+ useContext(DevtoolsContext)
77
90
 
78
91
  for (const [key, childNode] of node.familyMembers) {
79
- findInStore(store, viewIsOpenAtoms, key)
92
+ findInStore(store, viewIsOpenAtoms, [key])
80
93
  findInStore(store, typeSelectors, childNode.key)
81
94
  }
82
95
  return (
83
96
  <>
84
97
  <header>
85
- <button.OpenClose
86
- isOpen={isOpen}
87
- testid={`open-close-state-family-${node.key}`}
88
- setIsOpen={setIsOpen}
89
- />
90
98
  <main>
99
+ <button.OpenClose
100
+ isOpen={isOpen}
101
+ testid={`open-close-state-family-${node.key}`}
102
+ onShiftClick={() => {
103
+ actUponStore(
104
+ store,
105
+ openCloseAllTX,
106
+ arbitrary(),
107
+ )([node.key], isOpen)
108
+ return false
109
+ }}
110
+ setIsOpen={setIsOpen}
111
+ />
91
112
  <h2>{node.key}</h2>
92
113
  <span className="type detail"> (family)</span>
93
114
  </main>
@@ -97,7 +118,7 @@ export const StateIndexTreeNode: FC<{
97
118
  <StateIndexNode
98
119
  key={key}
99
120
  node={childNode}
100
- isOpenState={findInStore(store, viewIsOpenAtoms, childNode.key)}
121
+ isOpenState={findInStore(store, viewIsOpenAtoms, [node.key, key])}
101
122
  typeState={findInStore(store, typeSelectors, childNode.key)}
102
123
  />
103
124
  ))
@@ -135,7 +156,6 @@ export const StateIndex: FC<{
135
156
 
136
157
  const { typeSelectors, viewIsOpenAtoms, store } = useContext(DevtoolsContext)
137
158
 
138
- console.log(tokenIds)
139
159
  return (
140
160
  <article className="index state_index" data-testid="state-index">
141
161
  {[...tokenIds.entries()].map(([key, node]) => {
@@ -143,7 +163,7 @@ export const StateIndex: FC<{
143
163
  <StateIndexNode
144
164
  key={key}
145
165
  node={node}
146
- isOpenState={findInStore(store, viewIsOpenAtoms, node.key)}
166
+ isOpenState={findInStore(store, viewIsOpenAtoms, [node.key])}
147
167
  typeState={findInStore(store, typeSelectors, node.key)}
148
168
  />
149
169
  )
@@ -102,7 +102,7 @@ export const TimelineIndex: FC = () => {
102
102
  <TimelineLog
103
103
  key={token.key}
104
104
  token={token}
105
- isOpenState={findInStore(store, viewIsOpenAtoms, token.key)}
105
+ isOpenState={findInStore(store, viewIsOpenAtoms, [token.key])}
106
106
  timelineState={findInStore(store, timelineSelectors, token.key)}
107
107
  />
108
108
  )
@@ -66,7 +66,7 @@ export const TransactionIndex: FC = () => {
66
66
  <TransactionLog
67
67
  key={token.key}
68
68
  token={token}
69
- isOpenState={findInStore(store, viewIsOpenAtoms, token.key)}
69
+ isOpenState={findInStore(store, viewIsOpenAtoms, [token.key])}
70
70
  logState={findInStore(store, transactionLogSelectors, token.key)}
71
71
  />
72
72
  )
@@ -1,9 +1,9 @@
1
1
  main[data-css="atom_io_devtools"] {
2
2
  --fg-color: #ccc;
3
3
  --fg-light: #aaa;
4
- --fg-soft: #777;
5
- --fg-faint: #555;
6
- --fg-hint: #333;
4
+ --fg-soft: #888;
5
+ --fg-faint: #777;
6
+ --fg-hint: #4a4a4a;
7
7
  --fg-max: #fff;
8
8
  --bg-color: #111;
9
9
  --bg-accent: #00f;
@@ -26,6 +26,9 @@ main[data-css="atom_io_devtools"] {
26
26
  --bg-tint1: #e3e3e3;
27
27
  --bg-tint2: #f3f3f3;
28
28
  }
29
+ * {
30
+ box-sizing: border-box;
31
+ }
29
32
  & {
30
33
  pointer-events: all;
31
34
  box-sizing: border-box;
@@ -44,7 +47,7 @@ main[data-css="atom_io_devtools"] {
44
47
  overflow-y: scroll;
45
48
  }
46
49
  * {
47
- font-size: 16px;
50
+ font-size: 14px;
48
51
  font-family: theia, monospace;
49
52
  line-height: 1em;
50
53
  color: var(--fg-color);
@@ -90,13 +93,15 @@ main[data-css="atom_io_devtools"] {
90
93
  background-color: black;
91
94
  height: 10px;
92
95
  }
93
- main {
96
+ > main {
94
97
  overflow-y: scroll;
95
98
  flex-grow: 1;
96
99
  display: flex;
97
100
  flex-flow: column;
98
101
  gap: 0;
99
102
  article.index {
103
+ margin-bottom: 24px;
104
+ border-bottom: var(--fg-border);
100
105
  .node .node {
101
106
  border-right: var(--fg-border);
102
107
  padding-right: 0;
@@ -106,30 +111,26 @@ main[data-css="atom_io_devtools"] {
106
111
  }
107
112
  }
108
113
  .node > .node {
109
- margin: 0px 2px 2px 18px;
114
+ margin: 0px 0px 0px 9px;
110
115
  border-left: var(--fg-border-soft);
111
- &:last-of-type {
112
- margin-bottom: 6px;
113
- }
114
116
  }
115
117
  .node {
116
118
  border-top: var(--fg-border);
117
119
  overflow: visible;
118
- &:last-of-type {
119
- border-bottom: var(--fg-border);
120
- }
120
+
121
121
  &.transaction_update {
122
122
  padding: 0;
123
123
  }
124
124
  > header {
125
125
  display: flex;
126
126
  flex-flow: row;
127
+ justify-content: space-between;
127
128
  position: sticky;
128
129
  z-index: 999;
129
130
  top: 0;
130
131
  height: 22px;
131
132
  background: var(--bg-tint2);
132
- border-bottom: var(--fg-border-soft);
133
+ border-bottom: none;
133
134
  > main {
134
135
  display: flex;
135
136
  flex-flow: row;
@@ -154,20 +155,23 @@ main[data-css="atom_io_devtools"] {
154
155
  }
155
156
  }
156
157
  }
158
+ > .json_editor {
159
+ border-left: var(--fg-border-soft);
160
+ padding: 3px 0px;
161
+ }
157
162
  > .json_viewer {
158
163
  color: var(--fg-light);
159
164
  font-size: 14px;
160
165
  flex-shrink: 1;
161
- overflow-x: scroll;
162
166
  }
163
167
  > .json_editor,
164
168
  > .json_viewer {
169
+ margin-left: 3px;
165
170
  display: flex;
166
171
  flex-shrink: 1;
167
172
  z-index: -1;
168
173
  overflow-x: scroll;
169
174
  align-items: center;
170
- border-left: var(--fg-border-soft);
171
175
  white-space: pre;
172
176
  background: var(--bg-tint2);
173
177
  &:focus-within {
@@ -187,6 +191,7 @@ main[data-css="atom_io_devtools"] {
187
191
  }
188
192
  input {
189
193
  outline: none;
194
+ min-width: 10px;
190
195
  }
191
196
  }
192
197
  }
@@ -285,7 +290,7 @@ main[data-css="atom_io_devtools"] {
285
290
  }
286
291
  }
287
292
  }
288
- footer {
293
+ > footer {
289
294
  display: flex;
290
295
  justify-content: flex-end;
291
296
  button {
@@ -304,29 +309,39 @@ main[data-css="atom_io_devtools"] {
304
309
  flex-flow: column;
305
310
  align-items: flex-start;
306
311
  > header {
312
+ width: 100%;
307
313
  display: flex;
308
314
  flex-flow: row;
309
- width: 100%;
310
- position: relative;
311
- align-items: baseline;
315
+ align-items: center;
312
316
  overflow: hidden;
313
317
  white-space: nowrap;
314
- > .json_viewer {
315
- flex-shrink: 1;
316
- overflow-x: scroll;
318
+ justify-content: space-between;
319
+ &:has(> main > button.carat) {
317
320
  height: 21px;
318
- font-size: 14px;
321
+ }
322
+ > main {
319
323
  display: flex;
324
+ flex-flow: row;
320
325
  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;
326
+ flex-shrink: 1;
327
+ overflow-x: hidden;
328
+ align-self: center;
329
+ > .json_viewer {
330
+ flex-shrink: 1;
331
+ overflow-x: scroll;
332
+ height: 21px;
328
333
  font-size: 14px;
329
- align-self: flex-start;
334
+ display: flex;
335
+ align-items: center;
336
+ margin-left: 0px;
337
+ color: var(--fg-soft);
338
+ }
339
+ > button {
340
+ padding: 0;
341
+ &.carat {
342
+ line-height: 0.5em;
343
+ font-size: 14px;
344
+ }
330
345
  }
331
346
  }
332
347
  }
@@ -343,7 +358,6 @@ main[data-css="atom_io_devtools"] {
343
358
  }
344
359
  }
345
360
  input,
346
- button,
347
361
  select {
348
362
  &:focus-within {
349
363
  outline: 2px solid var(--fg-max);
@@ -351,6 +365,7 @@ main[data-css="atom_io_devtools"] {
351
365
  color: var(--fg-max);
352
366
  }
353
367
  }
368
+
354
369
  button:disabled {
355
370
  cursor: default;
356
371
  > span.json_editor_icon {
@@ -376,9 +391,20 @@ main[data-css="atom_io_devtools"] {
376
391
  padding: 4px;
377
392
  padding-bottom: 6px;
378
393
  cursor: pointer;
379
- &:hover {
380
- color: #333;
381
- background-color: #aaa;
394
+ &:hover,
395
+ &:focus-within {
396
+ background-color: var(--fg-faint);
397
+ &,
398
+ > * {
399
+ color: var(--bg-color);
400
+ }
401
+ }
402
+ &:active {
403
+ background: var(--fg-color);
404
+ &,
405
+ > * {
406
+ color: var(--bg-color);
407
+ }
382
408
  }
383
409
  }
384
410
  select {
@@ -404,6 +430,7 @@ main[data-css="atom_io_devtools"] {
404
430
  padding-right: 0px;
405
431
  &::after {
406
432
  content: ":";
433
+ color: var(--fg-soft);
407
434
  }
408
435
  input {
409
436
  color: var(--fg-color);
@@ -412,26 +439,35 @@ main[data-css="atom_io_devtools"] {
412
439
  .json_editor_object,
413
440
  .json_editor_array {
414
441
  border-left: var(--fg-border-soft);
415
- padding-left: 10px;
416
- margin-left: 10px;
417
- width: calc(100% - 21px);
442
+ margin-left: 9px;
443
+ width: calc(100% - 9px);
444
+ > footer {
445
+ display: flex;
446
+ flex-flow: row;
447
+ justify-content: flex-start;
448
+ justify-items: flex-start;
449
+ height: 21px;
450
+ align-items: baseline;
451
+ position: relative;
452
+ }
418
453
  .json_editor_properties,
419
454
  .json_editor_elements {
455
+ border-top: var(--fg-border-soft);
420
456
  .json_editor_property,
421
457
  .json_editor_element {
422
458
  display: flex;
423
459
  border-bottom: var(--fg-border-soft);
424
- margin-bottom: 2px;
425
- min-height: 23px;
460
+ margin-bottom: 0;
461
+ min-height: 21px;
426
462
  > header {
427
- width: 100%;
428
-
429
- > span {
430
- input {
431
- min-width: 10px;
432
- }
433
- > * {
434
- border: var(--fg-border-hint);
463
+ > main {
464
+ > span {
465
+ input {
466
+ min-width: 10px;
467
+ }
468
+ > * {
469
+ border: var(--fg-border-hint);
470
+ }
435
471
  }
436
472
  }
437
473
  }
@@ -442,7 +478,7 @@ main[data-css="atom_io_devtools"] {
442
478
  &:last-of-type {
443
479
  border-bottom: none;
444
480
  }
445
- > span > * {
481
+ span > * {
446
482
  border: 1px solid transparent;
447
483
  }
448
484
  }
@@ -459,10 +495,6 @@ main[data-css="atom_io_devtools"] {
459
495
  border: none;
460
496
  cursor: pointer;
461
497
  background: none;
462
- &:focus-within {
463
- outline: none;
464
- background: none;
465
- }
466
498
  > .json_editor_icon {
467
499
  line-height: 4px;
468
500
  }
@@ -48,6 +48,7 @@ export const JsonEditor = <T,>({
48
48
  name,
49
49
  rename,
50
50
  remove,
51
+ path = [],
51
52
  isReadonly = () => false,
52
53
  isHidden = () => false,
53
54
  className,
@@ -68,7 +69,7 @@ export const JsonEditor = <T,>({
68
69
  name={name}
69
70
  rename={rename}
70
71
  remove={remove}
71
- path={[]}
72
+ path={path}
72
73
  isReadonly={isReadonly}
73
74
  isHidden={isHidden}
74
75
  className={className}
@@ -25,7 +25,7 @@ type ArrayElementProps = {
25
25
  recast: (newType: keyof JsonTypes) => void
26
26
  Components: JsonEditorComponents
27
27
  testid?: string | undefined
28
- viewIsOpenAtom: RegularAtomToken<boolean, string>
28
+ viewIsOpenAtom: RegularAtomToken<boolean, readonly (number | string)[]>
29
29
  }
30
30
  const ArrayElement = ({
31
31
  path,
@@ -80,15 +80,14 @@ export const ArrayEditor = ({
80
80
 
81
81
  return (
82
82
  <Components.ArrayWrapper>
83
- <div className={`json_editor_elements${disabled ? ` readonly` : ``}`}>
83
+ <main className={`json_editor_elements${disabled ? ` readonly` : ``}`}>
84
84
  {data.map((element, index) => {
85
85
  const elementPath = [...path, index]
86
86
  const pathKey = elementPath.join(`,`)
87
- const viewIsOpenAtom = findInStore(
88
- store,
89
- viewIsOpenAtoms,
90
- `${testid}__${pathKey}`,
91
- )
87
+ const viewIsOpenAtom = findInStore(store, viewIsOpenAtoms, [
88
+ ...path,
89
+ index,
90
+ ])
92
91
  return (
93
92
  <ArrayElement
94
93
  key={pathKey}
@@ -105,19 +104,23 @@ export const ArrayEditor = ({
105
104
  />
106
105
  )
107
106
  })}
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>
107
+ </main>
108
+ {!disabled ? (
109
+ <footer>
110
+ <Components.Button
111
+ testid={`${testid}-add-element`}
112
+ disabled={disabled}
113
+ onClick={() => {
114
+ set((current) => {
115
+ const newData = [...current, JSON_DEFAULTS.string]
116
+ return newData
117
+ })
118
+ }}
119
+ >
120
+ <Components.AddIcon />
121
+ </Components.Button>
122
+ </footer>
123
+ ) : null}
121
124
  </Components.ArrayWrapper>
122
125
  )
123
126
  }
@@ -60,7 +60,7 @@ type ObjectPropertyProps = {
60
60
  recast: (newType: keyof JsonTypes) => void
61
61
  Components: JsonEditorComponents
62
62
  testid?: string | undefined
63
- viewIsOpenAtom: RegularAtomToken<boolean, string>
63
+ viewIsOpenAtom: RegularAtomToken<boolean, readonly (number | string)[]>
64
64
  }
65
65
  const ObjectProperty = ({
66
66
  path,
@@ -137,28 +137,12 @@ export const ObjectEditor = <T extends Json.Tree.Object>({
137
137
  const propertyPath = [...path, key]
138
138
  const originalPropertyPath = [...path, originalKey]
139
139
  const stablePathKey = originalPropertyPath.join(`.`)
140
- const viewIsOpenAtom = findInStore(
141
- store,
142
- viewIsOpenAtoms,
143
- `${testid}__${stablePathKey}`,
144
- )
140
+ const viewIsOpenAtom = findInStore(store, viewIsOpenAtoms, [
141
+ ...path,
142
+ key,
143
+ ])
145
144
 
146
145
  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
146
  <ObjectProperty
163
147
  key={stablePathKey}
164
148
  path={propertyPath}
@@ -177,7 +161,7 @@ export const ObjectEditor = <T extends Json.Tree.Object>({
177
161
  })}
178
162
  </div>
179
163
  {disabled ? null : (
180
- <>
164
+ <footer>
181
165
  <Components.Button
182
166
  disabled={disabled}
183
167
  testid={`${testid}-add-property`}
@@ -196,7 +180,7 @@ export const ObjectEditor = <T extends Json.Tree.Object>({
196
180
  >
197
181
  Sort
198
182
  </Components.Button>
199
- </>
183
+ </footer>
200
184
  )}
201
185
  </Components.ObjectWrapper>
202
186
  )