atom.io 0.33.11 → 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.
@@ -1,24 +1,31 @@
1
- import { IMPLICIT, become, createAtomFamily, createStandaloneAtom, findInStore } from "atom.io/internal";
1
+ import { useI, useO } from "../use-o-BrXc7Qro.js";
2
+ import { IMPLICIT, actUponStore, arbitrary, become, createAtomFamily, createStandaloneAtom, createTransaction, findInStore, getFromStore } from "atom.io/internal";
2
3
  import { JSON_DEFAULTS, fromEntries, isJson, stringifyJson, toEntries } from "atom.io/json";
3
- import { getState, redo, undo } from "atom.io";
4
+ import { redo, undo } from "atom.io";
4
5
  import { Component, Fragment, createContext, forwardRef, useContext, useId, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
5
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
- import { StoreContext, useI, useO } from "atom.io/react";
7
+ import { StoreContext, useI as useI$1, useO as useO$1 } from "atom.io/react";
7
8
  import { LayoutGroup, motion } from "motion/react";
8
- import { attachIntrospectionStates, discoverType, jsonRefinery, prettyJson, primitiveRefinery } from "atom.io/introspection";
9
+ import { attachIntrospectionStates, discoverType, isPlainObject, jsonRefinery, prettyJson, primitiveRefinery } from "atom.io/introspection";
9
10
  import { persistSync } from "atom.io/web";
10
11
 
11
12
  //#region src/react-devtools/Button.tsx
12
- const OpenClose = ({ isOpen, setIsOpen, disabled, testid }) => {
13
+ const OpenClose = ({ isOpen, setIsOpen, onShiftClick, disabled, testid }) => {
13
14
  return /* @__PURE__ */ jsx("button", {
14
15
  type: "button",
15
16
  "data-testid": testid,
16
17
  className: `carat ${isOpen ? `open` : `closed`}`,
17
- onClick: () => {
18
- setIsOpen((prev) => !prev);
18
+ onClick: (event) => {
19
+ if (onShiftClick && event.shiftKey) {
20
+ if (!onShiftClick(event)) return;
21
+ }
22
+ setIsOpen?.((prev) => !prev);
19
23
  },
20
24
  disabled,
21
- children: ""
25
+ children: /* @__PURE__ */ jsx("span", {
26
+ className: "json_editor_icon json_editor_carat",
27
+ children: "▶"
28
+ })
22
29
  });
23
30
  };
24
31
  const button = { OpenClose };
@@ -140,7 +147,11 @@ const DEFAULT_JSON_EDITOR_COMPONENTS = {
140
147
  }),
141
148
  DeleteIcon: () => /* @__PURE__ */ jsx("span", {
142
149
  className: "json_editor_icon json_editor_delete",
143
- children: "x"
150
+ children: "×"
151
+ }),
152
+ AddIcon: () => /* @__PURE__ */ jsx("span", {
153
+ className: "json_editor_icon json_editor_add",
154
+ children: "+"
144
155
  }),
145
156
  MissingPropertyWrapper: ({ children, testid }) => /* @__PURE__ */ jsx("span", {
146
157
  className: "json_editor_missing_property",
@@ -154,6 +165,92 @@ const DEFAULT_JSON_EDITOR_COMPONENTS = {
154
165
  })
155
166
  };
156
167
 
168
+ //#endregion
169
+ //#region src/react-devtools/store.ts
170
+ function attachDevtoolsStates(store) {
171
+ const introspectionStates = attachIntrospectionStates(store);
172
+ const devtoolsAreOpenState = createStandaloneAtom(store, {
173
+ key: `🔍 Devtools Are Open`,
174
+ default: true,
175
+ effects: typeof window === `undefined` ? [] : [persistSync(window.localStorage, JSON, `🔍 Devtools Are Open`)]
176
+ });
177
+ const devtoolsViewSelectionState = createStandaloneAtom(store, {
178
+ key: `🔍 Devtools View Selection`,
179
+ default: `atoms`,
180
+ effects: typeof window === `undefined` ? [] : [persistSync(window.localStorage, JSON, `🔍 Devtools View`)]
181
+ });
182
+ const devtoolsViewOptionsState = createStandaloneAtom(store, {
183
+ key: `🔍 Devtools View Options`,
184
+ default: [
185
+ `atoms`,
186
+ `selectors`,
187
+ `transactions`,
188
+ `timelines`
189
+ ],
190
+ effects: typeof window === `undefined` ? [] : [persistSync(window.localStorage, JSON, `🔍 Devtools View Options`)]
191
+ });
192
+ const viewIsOpenAtoms = createAtomFamily(store, {
193
+ key: `🔍 Devtools View Is Open`,
194
+ default: false,
195
+ effects: (key) => typeof window === `undefined` ? [] : [persistSync(window.localStorage, JSON, `view-is-open:${key.join()}`)]
196
+ });
197
+ const openCloseAllTX = createTransaction(store, {
198
+ key: `openCloseMultiView`,
199
+ do: ({ get, set }, path, current) => {
200
+ const currentView = get(devtoolsViewSelectionState);
201
+ let states;
202
+ switch (currentView) {
203
+ case `atoms`:
204
+ states = get(introspectionStates.atomIndex);
205
+ break;
206
+ case `selectors`:
207
+ states = get(introspectionStates.selectorIndex);
208
+ break;
209
+ case `transactions`:
210
+ case `timelines`: return;
211
+ }
212
+ switch (path.length) {
213
+ case 1:
214
+ for (const [key] of states) set(viewIsOpenAtoms, [key], !current);
215
+ break;
216
+ default: {
217
+ const item = states.get(path[0]);
218
+ let value;
219
+ let segments;
220
+ if (item) {
221
+ if (`familyMembers` in item) {
222
+ if (path.length === 2) {
223
+ for (const [subKey] of item.familyMembers) set(viewIsOpenAtoms, [path[0], subKey], !current);
224
+ return;
225
+ }
226
+ const token = item.familyMembers.get(path[1]);
227
+ value = get(token);
228
+ segments = path.slice(2, -1);
229
+ } else {
230
+ value = get(item);
231
+ segments = path.slice(1, -1);
232
+ }
233
+ for (const segment of segments) if (value && typeof value === `object`) value = value[segment];
234
+ const head = path.slice(0, -1);
235
+ if (Array.isArray(value)) for (let i = 0; i < value.length; i++) set(viewIsOpenAtoms, [...head, i], !current);
236
+ else if (isPlainObject(value)) for (const key of Object.keys(value)) set(viewIsOpenAtoms, [...head, key], !current);
237
+ }
238
+ }
239
+ }
240
+ }
241
+ });
242
+ return {
243
+ ...introspectionStates,
244
+ devtoolsAreOpenState,
245
+ devtoolsViewSelectionState,
246
+ devtoolsViewOptionsState,
247
+ viewIsOpenAtoms,
248
+ openCloseAllTX,
249
+ store
250
+ };
251
+ }
252
+ const DevtoolsContext = createContext(attachDevtoolsStates(IMPLICIT.STORE));
253
+
157
254
  //#endregion
158
255
  //#region src/react-devtools/elastic-input/ElasticInput.tsx
159
256
  const ElasticInput = forwardRef(function ElasticInputFC(props, ref) {
@@ -361,7 +458,8 @@ const NonJsonEditor = ({ data, testid }) => {
361
458
 
362
459
  //#endregion
363
460
  //#region src/react-devtools/json-editor/json-editor-internal.tsx
364
- const JsonEditor_INTERNAL = ({ data, set, name, rename, remove, recast, path = [], isReadonly = () => false, isHidden = () => false, className, style, Header: HeaderDisplay, Components, testid }) => {
461
+ const JsonEditor_INTERNAL = ({ data, set, name, rename, remove, recast, path = [], isReadonly = () => false, isHidden = () => false, className, style, Components, isOpen, setIsOpen, testid }) => {
462
+ const { openCloseAllTX, store } = useContext(DevtoolsContext);
365
463
  const dataIsJson = isJson(data);
366
464
  const refined = jsonRefinery.refine(data) ?? {
367
465
  type: `non-json`,
@@ -369,29 +467,46 @@ const JsonEditor_INTERNAL = ({ data, set, name, rename, remove, recast, path = [
369
467
  };
370
468
  const SubEditor = dataIsJson ? SubEditors[refined.type] : NonJsonEditor;
371
469
  const disabled = isReadonly(path);
470
+ const dataIsTree = refined.type === `array` || refined.type === `object`;
471
+ const dataIsExpandable = dataIsTree && isOpen !== void 0 && setIsOpen;
372
472
  return isHidden(path) ? null : /* @__PURE__ */ jsx(Components.ErrorBoundary, { children: /* @__PURE__ */ jsxs(Components.EditorWrapper, {
373
473
  className,
374
474
  style,
375
475
  testid,
376
- children: [
377
- remove ? /* @__PURE__ */ jsx(Components.Button, {
378
- disabled,
379
- onClick: () => {
380
- remove();
476
+ children: [/* @__PURE__ */ jsxs("header", { children: [/* @__PURE__ */ jsxs("main", { children: [
477
+ remove || dataIsExpandable ? /* @__PURE__ */ jsx(button.OpenClose, {
478
+ isOpen: isOpen ?? false,
479
+ testid: `${testid}-open-close`,
480
+ onShiftClick: () => {
481
+ actUponStore(store, openCloseAllTX, arbitrary())(path, isOpen);
482
+ return false;
381
483
  },
382
- testid: `${testid}-delete`,
383
- children: /* @__PURE__ */ jsx(Components.DeleteIcon, {})
484
+ setIsOpen,
485
+ disabled: !dataIsExpandable
384
486
  }) : null,
385
- HeaderDisplay && /* @__PURE__ */ jsx(HeaderDisplay, { data }),
386
487
  rename && /* @__PURE__ */ jsx(Components.KeyWrapper, { children: /* @__PURE__ */ jsx(ElasticInput, {
387
488
  value: name,
388
- onChange: disabled ? void 0 : (e) => {
489
+ onChange: (e) => {
389
490
  rename(e.target.value);
390
491
  },
391
492
  disabled,
392
493
  "data-testid": `${testid}-rename`
393
494
  }) }),
394
- /* @__PURE__ */ jsx(SubEditor, {
495
+ dataIsTree ? /* @__PURE__ */ jsxs(Fragment$1, { children: [isOpen !== void 0 && setIsOpen ? /* @__PURE__ */ jsx("span", {
496
+ className: "json_viewer",
497
+ children: JSON.stringify(data)
498
+ }) : null, recast ? /* @__PURE__ */ jsx("select", {
499
+ onChange: (e) => {
500
+ recast(e.target.value);
501
+ },
502
+ value: refined.type,
503
+ disabled,
504
+ "data-testid": `${testid}-recast`,
505
+ children: Object.keys(SubEditors).map((type) => /* @__PURE__ */ jsx("option", {
506
+ value: type,
507
+ children: type
508
+ }, type))
509
+ }) : null] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(SubEditor, {
395
510
  data: refined.data,
396
511
  set,
397
512
  remove,
@@ -401,8 +516,7 @@ const JsonEditor_INTERNAL = ({ data, set, name, rename, remove, recast, path = [
401
516
  isHidden,
402
517
  Components,
403
518
  testid
404
- }),
405
- recast && dataIsJson ? /* @__PURE__ */ jsx("select", {
519
+ }), recast && dataIsJson ? /* @__PURE__ */ jsx("select", {
406
520
  onChange: disabled ? void 0 : (e) => {
407
521
  recast(e.target.value);
408
522
  },
@@ -413,8 +527,25 @@ const JsonEditor_INTERNAL = ({ data, set, name, rename, remove, recast, path = [
413
527
  value: type,
414
528
  children: type
415
529
  }, type))
416
- }) : null
417
- ]
530
+ }) : null] })
531
+ ] }), remove ? /* @__PURE__ */ jsx(Components.Button, {
532
+ disabled,
533
+ onClick: () => {
534
+ remove();
535
+ },
536
+ testid: `${testid}-delete`,
537
+ children: /* @__PURE__ */ jsx(Components.DeleteIcon, {})
538
+ }) : null] }), dataIsTree && isOpen !== false ? /* @__PURE__ */ jsx(SubEditor, {
539
+ data: refined.data,
540
+ set,
541
+ remove,
542
+ rename,
543
+ path,
544
+ isReadonly,
545
+ isHidden,
546
+ Components,
547
+ testid
548
+ }) : null]
418
549
  }) });
419
550
  };
420
551
 
@@ -673,30 +804,52 @@ const makePropertySorter = (data, set, sortFn) => () => {
673
804
 
674
805
  //#endregion
675
806
  //#region src/react-devtools/json-editor/editors-by-type/array-editor.tsx
807
+ const ArrayElement = ({ path, isReadonly, isHidden, data, set, remove, recast, Components, testid, viewIsOpenAtom }) => {
808
+ const index = path[path.length - 1];
809
+ const viewIsOpen = useO$1(viewIsOpenAtom);
810
+ const setViewIsOpen = useI$1(viewIsOpenAtom);
811
+ return /* @__PURE__ */ jsx(JsonEditor_INTERNAL, {
812
+ path,
813
+ name: `${index}`,
814
+ isReadonly,
815
+ isHidden,
816
+ data,
817
+ set,
818
+ remove,
819
+ recast,
820
+ className: "json_editor_element",
821
+ Components,
822
+ isOpen: viewIsOpen,
823
+ setIsOpen: setViewIsOpen,
824
+ testid: `${testid}-element-${index}`
825
+ });
826
+ };
676
827
  const ArrayEditor = ({ path = [], isReadonly = () => false, isHidden = () => false, data, set, Components, testid }) => {
828
+ const { viewIsOpenAtoms, store } = useContext(DevtoolsContext);
677
829
  const disabled = isReadonly(path);
678
830
  const setElement = makeElementSetters(data, set);
679
831
  const removeElement = makePropertyRemovers(data, set);
680
832
  const recastElement = makePropertyRecasters(data, set);
681
- return /* @__PURE__ */ jsxs(Components.ArrayWrapper, { children: [/* @__PURE__ */ jsx("div", {
833
+ return /* @__PURE__ */ jsxs(Components.ArrayWrapper, { children: [/* @__PURE__ */ jsx("main", {
682
834
  className: `json_editor_elements${disabled ? ` readonly` : ``}`,
683
835
  children: data.map((element, index) => {
684
- const newPath = [...path, index];
685
- return /* @__PURE__ */ jsx(JsonEditor_INTERNAL, {
686
- path: newPath,
687
- name: `${index}`,
836
+ const elementPath = [...path, index];
837
+ const pathKey = elementPath.join(`,`);
838
+ const viewIsOpenAtom = findInStore(store, viewIsOpenAtoms, [...path, index]);
839
+ return /* @__PURE__ */ jsx(ArrayElement, {
840
+ path: elementPath,
688
841
  isReadonly,
689
842
  isHidden,
690
843
  data: element,
691
844
  set: setElement[index],
692
845
  remove: removeElement[index],
693
846
  recast: recastElement[index],
694
- className: "json_editor_element",
695
847
  Components,
696
- testid: `${testid}-element-${index}`
697
- }, newPath.join(``));
848
+ testid,
849
+ viewIsOpenAtom
850
+ }, pathKey);
698
851
  })
699
- }), disabled ? null : /* @__PURE__ */ jsx(Components.Button, {
852
+ }), !disabled ? /* @__PURE__ */ jsx("footer", { children: /* @__PURE__ */ jsx(Components.Button, {
700
853
  testid: `${testid}-add-element`,
701
854
  disabled,
702
855
  onClick: () => {
@@ -705,13 +858,35 @@ const ArrayEditor = ({ path = [], isReadonly = () => false, isHidden = () => fal
705
858
  return newData;
706
859
  });
707
860
  },
708
- children: "+"
709
- })] });
861
+ children: /* @__PURE__ */ jsx(Components.AddIcon, {})
862
+ }) }) : null] });
710
863
  };
711
864
 
712
865
  //#endregion
713
866
  //#region src/react-devtools/json-editor/editors-by-type/object-editor.tsx
867
+ const ObjectProperty = ({ path, isReadonly, isHidden, data, set, rename, remove, recast, Components, testid, viewIsOpenAtom }) => {
868
+ const key = path[path.length - 1];
869
+ const viewIsOpen = useO(viewIsOpenAtom);
870
+ const setViewIsOpen = useI(viewIsOpenAtom);
871
+ return /* @__PURE__ */ jsx(JsonEditor_INTERNAL, {
872
+ path,
873
+ name: `${key}`,
874
+ isReadonly,
875
+ isHidden,
876
+ data,
877
+ set,
878
+ rename,
879
+ remove,
880
+ recast,
881
+ className: "json_editor_property",
882
+ Components,
883
+ isOpen: viewIsOpen,
884
+ setIsOpen: setViewIsOpen,
885
+ testid: `${testid}-property-${key}`
886
+ });
887
+ };
714
888
  const ObjectEditor = ({ path = [], isReadonly = () => false, isHidden = () => false, data, set, Components, testid }) => {
889
+ const { viewIsOpenAtoms, store } = useContext(DevtoolsContext);
715
890
  const disabled = isReadonly(path);
716
891
  const stableKeyMap = useRef(Object.keys(data).reduce((acc, key) => {
717
892
  acc[key] = key;
@@ -727,11 +902,12 @@ const ObjectEditor = ({ path = [], isReadonly = () => false, isHidden = () => fa
727
902
  className: `json_editor_properties${disabled ? ` readonly` : ``}`,
728
903
  children: Object.keys(data).map((key) => {
729
904
  const originalKey = stableKeyMap.current[key];
730
- const newPath = [...path, key];
731
- const originalPath = [...path, originalKey];
732
- return /* @__PURE__ */ jsx(JsonEditor_INTERNAL, {
733
- path: newPath,
734
- name: key,
905
+ const propertyPath = [...path, key];
906
+ const originalPropertyPath = [...path, originalKey];
907
+ const stablePathKey = originalPropertyPath.join(`.`);
908
+ const viewIsOpenAtom = findInStore(store, viewIsOpenAtoms, [...path, key]);
909
+ return /* @__PURE__ */ jsx(ObjectProperty, {
910
+ path: propertyPath,
735
911
  isReadonly,
736
912
  isHidden,
737
913
  data: data[key],
@@ -739,18 +915,18 @@ const ObjectEditor = ({ path = [], isReadonly = () => false, isHidden = () => fa
739
915
  rename: renameProperty[key],
740
916
  remove: removeProperty[key],
741
917
  recast: recastProperty[key],
742
- className: "json_editor_property",
743
918
  Components,
744
- testid: `${testid}-property-${key}`
745
- }, originalPath.join(`.`));
919
+ testid,
920
+ viewIsOpenAtom
921
+ }, stablePathKey);
746
922
  })
747
- }), disabled ? null : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Components.Button, {
923
+ }), disabled ? null : /* @__PURE__ */ jsxs("footer", { children: [/* @__PURE__ */ jsx(Components.Button, {
748
924
  disabled,
749
925
  testid: `${testid}-add-property`,
750
926
  onClick: () => {
751
927
  makePropertyAdder(`new_property`, `string`)();
752
928
  },
753
- children: "+"
929
+ children: /* @__PURE__ */ jsx(Components.AddIcon, {})
754
930
  }), /* @__PURE__ */ jsx(Components.Button, {
755
931
  testid: `${testid}-sort-properties`,
756
932
  onClick: () => {
@@ -802,7 +978,7 @@ const SubEditors = {
802
978
  object: ObjectEditor,
803
979
  string: StringEditor
804
980
  };
805
- const JsonEditor = ({ data, set, name, rename, remove, isReadonly = () => false, isHidden = () => false, className, Header, style, Components: CustomComponents = {}, testid }) => {
981
+ const JsonEditor = ({ data, set, name, rename, remove, path = [], isReadonly = () => false, isHidden = () => false, className, Header, style, Components: CustomComponents = {}, testid }) => {
806
982
  const Components = {
807
983
  ...DEFAULT_JSON_EDITOR_COMPONENTS,
808
984
  ...CustomComponents
@@ -813,7 +989,7 @@ const JsonEditor = ({ data, set, name, rename, remove, isReadonly = () => false,
813
989
  name,
814
990
  rename,
815
991
  remove,
816
- path: [],
992
+ path,
817
993
  isReadonly,
818
994
  isHidden,
819
995
  className,
@@ -827,21 +1003,25 @@ const JsonEditor = ({ data, set, name, rename, remove, isReadonly = () => false,
827
1003
  //#endregion
828
1004
  //#region src/react-devtools/StateEditor.tsx
829
1005
  const StateEditor = ({ token }) => {
830
- const set = useI(token);
831
- const data = useO(token);
1006
+ const set = useI$1(token);
1007
+ const data = useO$1(token);
1008
+ const metaPath = token.family ? [token.family.key, token.family.subKey] : [token.key];
832
1009
  return /* @__PURE__ */ jsx(JsonEditor, {
833
1010
  testid: `${token.key}-state-editor`,
834
1011
  data,
835
- set
1012
+ set,
1013
+ path: metaPath
836
1014
  });
837
1015
  };
838
1016
  const ReadonlySelectorViewer = ({ token }) => {
839
- const data = useO(token);
1017
+ const data = useO$1(token);
1018
+ const metaPath = token.family ? [token.family.key, token.family.subKey] : [token.key];
840
1019
  return /* @__PURE__ */ jsx(JsonEditor, {
841
1020
  testid: `${token.key}-state-editor`,
842
1021
  data,
843
1022
  set: () => null,
844
- isReadonly: () => true
1023
+ isReadonly: () => true,
1024
+ path: metaPath
845
1025
  });
846
1026
  };
847
1027
  const StoreEditor = ({ token }) => {
@@ -855,102 +1035,76 @@ const StoreEditor = ({ token }) => {
855
1035
  }
856
1036
  };
857
1037
 
858
- //#endregion
859
- //#region src/react-devtools/store.ts
860
- function attachDevtoolsStates(store) {
861
- const introspectionStates = attachIntrospectionStates(store);
862
- const devtoolsAreOpenState = createStandaloneAtom(store, {
863
- key: `🔍 Devtools Are Open`,
864
- default: true,
865
- effects: typeof window === `undefined` ? [] : [persistSync(window.localStorage, JSON, `🔍 Devtools Are Open`)]
866
- });
867
- const devtoolsViewSelectionState = createStandaloneAtom(store, {
868
- key: `🔍 Devtools View Selection`,
869
- default: `atoms`,
870
- effects: typeof window === `undefined` ? [] : [persistSync(window.localStorage, JSON, `🔍 Devtools View`)]
871
- });
872
- const devtoolsViewOptionsState = createStandaloneAtom(store, {
873
- key: `🔍 Devtools View Options`,
874
- default: [
875
- `atoms`,
876
- `selectors`,
877
- `transactions`,
878
- `timelines`
879
- ],
880
- effects: typeof window === `undefined` ? [] : [persistSync(window.localStorage, JSON, `🔍 Devtools View Options`)]
881
- });
882
- const viewIsOpenAtoms = createAtomFamily(store, {
883
- key: `🔍 Devtools View Is Open`,
884
- default: false,
885
- effects: (key) => typeof window === `undefined` ? [] : [persistSync(window.localStorage, JSON, key + `:view-is-open`)]
886
- });
887
- return {
888
- ...introspectionStates,
889
- devtoolsAreOpenState,
890
- devtoolsViewSelectionState,
891
- devtoolsViewOptionsState,
892
- viewIsOpenAtoms,
893
- store
894
- };
895
- }
896
- const DevtoolsContext = createContext(attachDevtoolsStates(IMPLICIT.STORE));
897
-
898
1038
  //#endregion
899
1039
  //#region src/react-devtools/StateIndex.tsx
900
1040
  const StateIndexLeafNode = ({ node, isOpenState, typeState }) => {
901
- const setIsOpen = useI(isOpenState);
902
- const isOpen = useO(isOpenState);
903
- const state = useO(node);
904
- const stateTypeLoadable = useO(typeState);
1041
+ const { openCloseAllTX, store } = useContext(DevtoolsContext);
1042
+ const setIsOpen = useI$1(isOpenState);
1043
+ const isOpen = useO$1(isOpenState);
1044
+ const state = useO$1(node);
1045
+ const stateTypeLoadable = useO$1(typeState);
905
1046
  const stateType = stateTypeLoadable instanceof Promise ? `Promise` : stateTypeLoadable;
906
1047
  const isPrimitive = Boolean(primitiveRefinery.refine(state));
907
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("header", { children: [
908
- /* @__PURE__ */ jsx(button.OpenClose, {
909
- isOpen: isOpen && !isPrimitive,
910
- testid: `open-close-state-${node.key}`,
911
- setIsOpen,
912
- disabled: isPrimitive
913
- }),
914
- /* @__PURE__ */ jsxs("main", {
915
- onClick: () => {
916
- console.log(node, getState(node));
917
- },
918
- onKeyUp: () => {
919
- console.log(node, getState(node));
920
- },
921
- children: [/* @__PURE__ */ jsx("h2", { children: node.family?.subKey ?? node.key }), /* @__PURE__ */ jsxs("span", {
1048
+ const path = node.family ? [node.family.key, node.family.subKey] : [node.key];
1049
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("header", { children: [/* @__PURE__ */ jsxs("main", {
1050
+ onClick: () => {
1051
+ console.log(node, getFromStore(store, node));
1052
+ },
1053
+ onKeyUp: () => {
1054
+ console.log(node, getFromStore(store, node));
1055
+ },
1056
+ children: [
1057
+ /* @__PURE__ */ jsx(button.OpenClose, {
1058
+ isOpen: isOpen && !isPrimitive,
1059
+ testid: `open-close-state-${node.key}`,
1060
+ onShiftClick: () => {
1061
+ actUponStore(store, openCloseAllTX, arbitrary())(path, isOpen);
1062
+ return false;
1063
+ },
1064
+ setIsOpen,
1065
+ disabled: isPrimitive
1066
+ }),
1067
+ /* @__PURE__ */ jsx("h2", { children: node.family?.subKey ?? node.key }),
1068
+ /* @__PURE__ */ jsxs("span", {
922
1069
  className: "type detail",
923
1070
  children: [
924
1071
  "(",
925
1072
  stateType,
926
1073
  ")"
927
1074
  ]
928
- })]
929
- }),
930
- isPrimitive ? /* @__PURE__ */ jsx(StoreEditor, { token: node }) : /* @__PURE__ */ jsx("div", {
931
- className: "json_viewer",
932
- children: JSON.stringify(state)
933
- })
934
- ] }), isOpen && !isPrimitive ? /* @__PURE__ */ jsx("main", { children: /* @__PURE__ */ jsx(StoreEditor, { token: node }) }) : null] });
1075
+ })
1076
+ ]
1077
+ }), isPrimitive ? /* @__PURE__ */ jsx(StoreEditor, { token: node }) : /* @__PURE__ */ jsx("div", {
1078
+ className: "json_viewer",
1079
+ children: JSON.stringify(state)
1080
+ })] }), isOpen && !isPrimitive ? /* @__PURE__ */ jsx("main", { children: /* @__PURE__ */ jsx(StoreEditor, { token: node }) }) : null] });
935
1081
  };
936
1082
  const StateIndexTreeNode = ({ node, isOpenState }) => {
937
- const setIsOpen = useI(isOpenState);
938
- const isOpen = useO(isOpenState);
939
- const { typeSelectors, viewIsOpenAtoms, store } = useContext(DevtoolsContext);
1083
+ const setIsOpen = useI$1(isOpenState);
1084
+ const isOpen = useO$1(isOpenState);
1085
+ const { typeSelectors, viewIsOpenAtoms, openCloseAllTX, store } = useContext(DevtoolsContext);
940
1086
  for (const [key, childNode] of node.familyMembers) {
941
- findInStore(store, viewIsOpenAtoms, key);
1087
+ findInStore(store, viewIsOpenAtoms, [key]);
942
1088
  findInStore(store, typeSelectors, childNode.key);
943
1089
  }
944
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("header", { children: [/* @__PURE__ */ jsx(button.OpenClose, {
945
- isOpen,
946
- testid: `open-close-state-family-${node.key}`,
947
- setIsOpen
948
- }), /* @__PURE__ */ jsxs("main", { children: [/* @__PURE__ */ jsx("h2", { children: node.key }), /* @__PURE__ */ jsx("span", {
949
- className: "type detail",
950
- children: " (family)"
951
- })] })] }), isOpen ? [...node.familyMembers.entries()].map(([key, childNode]) => /* @__PURE__ */ jsx(StateIndexNode, {
1090
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("header", { children: /* @__PURE__ */ jsxs("main", { children: [
1091
+ /* @__PURE__ */ jsx(button.OpenClose, {
1092
+ isOpen,
1093
+ testid: `open-close-state-family-${node.key}`,
1094
+ onShiftClick: () => {
1095
+ actUponStore(store, openCloseAllTX, arbitrary())([node.key], isOpen);
1096
+ return false;
1097
+ },
1098
+ setIsOpen
1099
+ }),
1100
+ /* @__PURE__ */ jsx("h2", { children: node.key }),
1101
+ /* @__PURE__ */ jsx("span", {
1102
+ className: "type detail",
1103
+ children: " (family)"
1104
+ })
1105
+ ] }) }), isOpen ? [...node.familyMembers.entries()].map(([key, childNode]) => /* @__PURE__ */ jsx(StateIndexNode, {
952
1106
  node: childNode,
953
- isOpenState: findInStore(store, viewIsOpenAtoms, childNode.key),
1107
+ isOpenState: findInStore(store, viewIsOpenAtoms, [node.key, key]),
954
1108
  typeState: findInStore(store, typeSelectors, childNode.key)
955
1109
  }, key)) : null] });
956
1110
  };
@@ -969,16 +1123,15 @@ const StateIndexNode = ({ node, isOpenState, typeState }) => {
969
1123
  });
970
1124
  };
971
1125
  const StateIndex = ({ tokenIndex }) => {
972
- const tokenIds = useO(tokenIndex);
1126
+ const tokenIds = useO$1(tokenIndex);
973
1127
  const { typeSelectors, viewIsOpenAtoms, store } = useContext(DevtoolsContext);
974
- console.log(tokenIds);
975
1128
  return /* @__PURE__ */ jsx("article", {
976
1129
  className: "index state_index",
977
1130
  "data-testid": "state-index",
978
1131
  children: [...tokenIds.entries()].map(([key, node]) => {
979
1132
  return /* @__PURE__ */ jsx(StateIndexNode, {
980
1133
  node,
981
- isOpenState: findInStore(store, viewIsOpenAtoms, node.key),
1134
+ isOpenState: findInStore(store, viewIsOpenAtoms, [node.key]),
982
1135
  typeState: findInStore(store, typeSelectors, node.key)
983
1136
  }, key);
984
1137
  })
@@ -1132,9 +1285,9 @@ const YouAreHere = () => {
1132
1285
  });
1133
1286
  };
1134
1287
  const TimelineLog = ({ token, isOpenState, timelineState }) => {
1135
- const timeline = useO(timelineState);
1136
- const isOpen = useO(isOpenState);
1137
- const setIsOpen = useI(isOpenState);
1288
+ const timeline = useO$1(timelineState);
1289
+ const isOpen = useO$1(isOpenState);
1290
+ const setIsOpen = useI$1(isOpenState);
1138
1291
  return /* @__PURE__ */ jsxs("section", {
1139
1292
  className: "node timeline_log",
1140
1293
  "data-testid": `timeline-${token.key}`,
@@ -1182,14 +1335,14 @@ const TimelineLog = ({ token, isOpenState, timelineState }) => {
1182
1335
  };
1183
1336
  const TimelineIndex = () => {
1184
1337
  const { timelineIndex, timelineSelectors, viewIsOpenAtoms, store } = useContext(DevtoolsContext);
1185
- const tokenIds = useO(timelineIndex);
1338
+ const tokenIds = useO$1(timelineIndex);
1186
1339
  return /* @__PURE__ */ jsx("article", {
1187
1340
  className: "index timeline_index",
1188
1341
  "data-testid": "timeline-index",
1189
1342
  children: tokenIds.filter((token) => !token.key.startsWith(`👁‍🗨`)).map((token) => {
1190
1343
  return /* @__PURE__ */ jsx(TimelineLog, {
1191
1344
  token,
1192
- isOpenState: findInStore(store, viewIsOpenAtoms, token.key),
1345
+ isOpenState: findInStore(store, viewIsOpenAtoms, [token.key]),
1193
1346
  timelineState: findInStore(store, timelineSelectors, token.key)
1194
1347
  }, token.key);
1195
1348
  })
@@ -1199,9 +1352,9 @@ const TimelineIndex = () => {
1199
1352
  //#endregion
1200
1353
  //#region src/react-devtools/TransactionIndex.tsx
1201
1354
  const TransactionLog = ({ token, isOpenState, logState }) => {
1202
- const log = useO(logState);
1203
- const isOpen = useO(isOpenState);
1204
- const setIsOpen = useI(isOpenState);
1355
+ const log = useO$1(logState);
1356
+ const isOpen = useO$1(isOpenState);
1357
+ const setIsOpen = useI$1(isOpenState);
1205
1358
  return /* @__PURE__ */ jsxs("section", {
1206
1359
  className: "node transaction_log",
1207
1360
  "data-testid": `transaction-${token.key}`,
@@ -1224,14 +1377,14 @@ const TransactionLog = ({ token, isOpenState, logState }) => {
1224
1377
  };
1225
1378
  const TransactionIndex = () => {
1226
1379
  const { transactionIndex, transactionLogSelectors, viewIsOpenAtoms, store } = useContext(DevtoolsContext);
1227
- const tokenIds = useO(transactionIndex);
1380
+ const tokenIds = useO$1(transactionIndex);
1228
1381
  return /* @__PURE__ */ jsx("article", {
1229
1382
  className: "index transaction_index",
1230
1383
  "data-testid": "transaction-index",
1231
1384
  children: tokenIds.filter((token) => !token.key.startsWith(`🔍`)).map((token) => {
1232
1385
  return /* @__PURE__ */ jsx(TransactionLog, {
1233
1386
  token,
1234
- isOpenState: findInStore(store, viewIsOpenAtoms, token.key),
1387
+ isOpenState: findInStore(store, viewIsOpenAtoms, [token.key]),
1235
1388
  logState: findInStore(store, transactionLogSelectors, token.key)
1236
1389
  }, token.key);
1237
1390
  })
@@ -1250,11 +1403,11 @@ const AtomIODevtools = () => {
1250
1403
  const AtomIODevtoolsInternal = () => {
1251
1404
  const constraintsRef = useRef(null);
1252
1405
  const { atomIndex, selectorIndex, devtoolsAreOpenState, devtoolsViewSelectionState, devtoolsViewOptionsState } = useContext(DevtoolsContext);
1253
- const setDevtoolsAreOpen = useI(devtoolsAreOpenState);
1254
- const devtoolsAreOpen = useO(devtoolsAreOpenState);
1255
- const setDevtoolsView = useI(devtoolsViewSelectionState);
1256
- const devtoolsView = useO(devtoolsViewSelectionState);
1257
- const devtoolsViewOptions = useO(devtoolsViewOptionsState);
1406
+ const setDevtoolsAreOpen = useI$1(devtoolsAreOpenState);
1407
+ const devtoolsAreOpen = useO$1(devtoolsAreOpenState);
1408
+ const setDevtoolsView = useI$1(devtoolsViewSelectionState);
1409
+ const devtoolsView = useO$1(devtoolsViewSelectionState);
1410
+ const devtoolsViewOptions = useO$1(devtoolsViewOptionsState);
1258
1411
  const mouseHasMoved = useRef(false);
1259
1412
  return /* @__PURE__ */ jsxs("span", {
1260
1413
  style: {