@dxos/plugin-navtree 0.7.1 → 0.7.2-staging.6d26b2a

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.
Files changed (34) hide show
  1. package/dist/lib/browser/index.mjs +190 -187
  2. package/dist/lib/browser/index.mjs.map +3 -3
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
  5. package/dist/types/src/components/NavTree.d.ts +7 -5
  6. package/dist/types/src/components/NavTree.d.ts.map +1 -1
  7. package/dist/types/src/components/NavTree.stories.d.ts.map +1 -1
  8. package/dist/types/src/components/NavTreeContainer.d.ts +2 -6
  9. package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
  10. package/dist/types/src/components/NavTreeItemAction.stories.d.ts +1 -0
  11. package/dist/types/src/components/NavTreeItemAction.stories.d.ts.map +1 -1
  12. package/dist/types/src/stories/Graph.stories.d.ts +2 -1
  13. package/dist/types/src/stories/Graph.stories.d.ts.map +1 -1
  14. package/dist/types/src/testing/index.d.ts +1 -1
  15. package/dist/types/src/testing/index.d.ts.map +1 -1
  16. package/dist/types/src/testing/update-state.d.ts +10 -0
  17. package/dist/types/src/testing/update-state.d.ts.map +1 -0
  18. package/dist/types/src/types.d.ts +12 -3
  19. package/dist/types/src/types.d.ts.map +1 -1
  20. package/dist/types/src/util.d.ts +1 -20
  21. package/dist/types/src/util.d.ts.map +1 -1
  22. package/package.json +28 -28
  23. package/src/NavTreePlugin.tsx +103 -90
  24. package/src/components/NavTree.stories.tsx +73 -69
  25. package/src/components/NavTree.tsx +30 -20
  26. package/src/components/NavTreeContainer.tsx +71 -47
  27. package/src/stories/Graph.stories.tsx +68 -96
  28. package/src/testing/index.ts +1 -1
  29. package/src/testing/update-state.ts +70 -0
  30. package/src/types.ts +18 -3
  31. package/src/util.ts +2 -94
  32. package/dist/types/src/testing/visitor.d.ts +0 -18
  33. package/dist/types/src/testing/visitor.d.ts.map +0 -1
  34. package/src/testing/visitor.ts +0 -152
@@ -5,14 +5,13 @@ import {
5
5
  } from "./chunk-PSVCPL4T.mjs";
6
6
 
7
7
  // packages/plugins/plugin-navtree/src/NavTreePlugin.tsx
8
+ import { effect } from "@preact/signals-core";
8
9
  import React10 from "react";
9
- import { resolvePlugin, parseIntentPlugin, LayoutAction as LayoutAction3, parseGraphPlugin, NavigationAction as NavigationAction2, parseNavigationPlugin as parseNavigationPlugin2 } from "@dxos/app-framework";
10
+ import { resolvePlugin, parseIntentPlugin, LayoutAction as LayoutAction3, parseGraphPlugin, NavigationAction as NavigationAction2, parseNavigationPlugin as parseNavigationPlugin2, parseLayoutPlugin } from "@dxos/app-framework";
10
11
  import { createExtension, isAction as isAction5, isGraphNode } from "@dxos/app-graph";
11
- import { invariant } from "@dxos/invariant";
12
+ import { create } from "@dxos/echo-schema";
12
13
  import { Keyboard as Keyboard2 } from "@dxos/keyboard";
13
- import { LocalStorageStore } from "@dxos/local-storage";
14
- import { Path as Path2 } from "@dxos/react-ui-mosaic";
15
- import { mx as mx5 } from "@dxos/react-ui-theme";
14
+ import { Path } from "@dxos/react-ui-mosaic";
16
15
  import { getHostPlatform as getHostPlatform3 } from "@dxos/util";
17
16
 
18
17
  // packages/plugins/plugin-navtree/src/components/CommandsDialog.tsx
@@ -395,10 +394,12 @@ var NavTreeItemAction = ({ monolithic, menuActions, parent: node, ...props }) =>
395
394
 
396
395
  // packages/plugins/plugin-navtree/src/components/NavTree.tsx
397
396
  var NAV_TREE_ITEM = "NavTreeItem";
398
- var NavTree = ({ loadDescendents, renderPresence: renderPresence2, popoverAnchorId, ...props }) => {
399
- const renderColumns = useCallback(({ item, menuOpen, setMenuOpen }) => {
397
+ var NavTree = ({ getActions: getActions2, loadDescendents, renderPresence: renderPresence2, popoverAnchorId, ...props }) => {
398
+ const renderColumns = useCallback(({ item, path, menuOpen, setMenuOpen }) => {
400
399
  return /* @__PURE__ */ React4.createElement(NavTreeColumns, {
401
- item,
400
+ path,
401
+ node: item,
402
+ getActions: getActions2,
402
403
  menuOpen,
403
404
  setMenuOpen,
404
405
  loadDescendents,
@@ -417,17 +418,18 @@ var NavTree = ({ loadDescendents, renderPresence: renderPresence2, popoverAnchor
417
418
  renderColumns
418
419
  });
419
420
  };
420
- var NavTreeColumns = ({ item, menuOpen, setMenuOpen, loadDescendents, renderPresence: Presence, popoverAnchorId }) => {
421
+ var NavTreeColumns = ({ path, node, getActions: getActions2, menuOpen, setMenuOpen, loadDescendents, renderPresence: Presence, popoverAnchorId }) => {
421
422
  const { t } = useTranslation4(NAVTREE_PLUGIN);
422
- const level = item.path.length - 2;
423
- const [primaryAction, ...secondaryActions] = item.actions.toSorted((a, b) => a.properties?.disposition === "toolbar" ? -1 : 1);
424
- const actions = (primaryAction?.properties?.disposition === "toolbar" ? secondaryActions : item.actions).flatMap((action) => isAction2(action) ? [
423
+ const level = path.length - 2;
424
+ const { actions: _actions, groupedActions } = getActions2(node);
425
+ const [primaryAction, ...secondaryActions] = _actions.toSorted((a, b) => a.properties?.disposition === "toolbar" ? -1 : 1);
426
+ const actions = (primaryAction?.properties?.disposition === "toolbar" ? secondaryActions : _actions).flatMap((action) => isAction2(action) ? [
425
427
  action
426
428
  ] : []).filter((action) => !action.properties?.hidden);
427
- const ActionRoot = popoverAnchorId === `dxos.org/ui/${NAV_TREE_ITEM}/${item.id}` ? Popover2.Anchor : Fragment2;
429
+ const ActionRoot = popoverAnchorId === `dxos.org/ui/${NAV_TREE_ITEM}/${node.id}` ? Popover2.Anchor : Fragment2;
428
430
  useEffect(() => {
429
431
  const frame = requestAnimationFrame(() => {
430
- void loadDescendents?.(item.node);
432
+ void loadDescendents?.(node);
431
433
  if (primaryAction && !isAction2(primaryAction)) {
432
434
  void loadDescendents?.(primaryAction);
433
435
  }
@@ -440,38 +442,40 @@ var NavTreeColumns = ({ item, menuOpen, setMenuOpen, loadDescendents, renderPres
440
442
  testId: primaryAction.properties?.testId,
441
443
  label: toLocalizedString4(primaryAction.properties?.label, t),
442
444
  icon: primaryAction.properties?.icon ?? "ph--placeholder--regular",
443
- parent: item.node,
445
+ parent: node,
444
446
  monolithic: isAction2(primaryAction),
445
447
  menuActions: isAction2(primaryAction) ? [
446
448
  primaryAction
447
- ] : item.groupedActions[primaryAction.id],
449
+ ] : groupedActions[primaryAction.id],
448
450
  menuType: primaryAction.properties?.menuType,
449
451
  caller: NAV_TREE_ITEM
450
452
  }) : /* @__PURE__ */ React4.createElement(Treegrid.Cell, null), /* @__PURE__ */ React4.createElement(ActionRoot, null, actions.length > 0 ? /* @__PURE__ */ React4.createElement(NavTreeItemAction, {
451
453
  testId: `navtree.treeItem.actionsLevel${level}`,
452
454
  label: t("tree item actions label"),
453
455
  icon: "ph--dots-three-vertical--regular",
454
- parent: item.node,
456
+ parent: node,
455
457
  menuActions: actions,
456
458
  menuType: "dropdown",
457
459
  caller: NAV_TREE_ITEM,
458
460
  menuOpen,
459
461
  onChangeMenuOpen: setMenuOpen
460
462
  }) : /* @__PURE__ */ React4.createElement(Treegrid.Cell, null)), Presence && /* @__PURE__ */ React4.createElement(Presence, {
461
- item
463
+ node
462
464
  }));
463
465
  };
464
466
 
465
467
  // packages/plugins/plugin-navtree/src/components/NavTreeContainer.tsx
466
468
  import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
467
469
  import { extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item";
468
- import React6, { useCallback as useCallback2, useEffect as useEffect2 } from "react";
470
+ import { untracked } from "@preact/signals-core";
471
+ import React6, { memo, useCallback as useCallback2, useEffect as useEffect2 } from "react";
469
472
  import { NavigationAction, Surface, useIntentDispatcher as useIntentDispatcher3 } from "@dxos/app-framework";
470
473
  import { isAction as isAction4, isActionLike } from "@dxos/app-graph";
471
474
  import { useGraph as useGraph2 } from "@dxos/plugin-graph";
472
475
  import { isEchoObject, isSpace } from "@dxos/react-client/echo";
473
476
  import { ElevationProvider, useMediaQuery, useSidebars as useSidebars2 } from "@dxos/react-ui";
474
- import { isItem } from "@dxos/react-ui-list";
477
+ import { isTreeData } from "@dxos/react-ui-list";
478
+ import { mx as mx4 } from "@dxos/react-ui-theme";
475
479
  import { arrayMove } from "@dxos/util";
476
480
 
477
481
  // packages/plugins/plugin-navtree/src/components/NavTreeFooter.tsx
@@ -584,7 +588,6 @@ var NavTreeFooter = (props) => {
584
588
 
585
589
  // packages/plugins/plugin-navtree/src/util.ts
586
590
  import { ACTION_TYPE, ACTION_GROUP_TYPE, isAction as isAction3 } from "@dxos/app-graph";
587
- import { Path } from "@dxos/react-ui-mosaic";
588
591
  import { nonNullable } from "@dxos/util";
589
592
  var getParent = (graph, node, path) => {
590
593
  const parentId = path[path.length - 2];
@@ -627,14 +630,6 @@ var sortActions = (actions) => actions.sort((a, b) => {
627
630
  }
628
631
  return 1;
629
632
  });
630
- var getTreeItemNode = (treeItems, path) => {
631
- if (!path) {
632
- return void 0;
633
- }
634
- return treeItems.find((treeItem) => {
635
- return treeItem.path && !treeItem.path.find((id, index) => path[index] !== id);
636
- });
637
- };
638
633
  var getChildren = (graph, node, filter, path = []) => {
639
634
  return graph.nodes(node, {
640
635
  relation: "outbound",
@@ -678,64 +673,55 @@ var expandActions = (graph, node) => {
678
673
  graph.expand(node, "outbound", ACTION_GROUP_TYPE)
679
674
  ]);
680
675
  };
681
- function* navTreeItemVisitor({ graph, node, open, getItem, path = [], filter }) {
682
- const stack = [
683
- getItem(node, path, filter)
684
- ];
685
- while (stack.length > 0) {
686
- const nextItem = stack.pop();
687
- if (nextItem.path.length > 1) {
688
- yield nextItem;
689
- }
690
- const { node: node2, path: path2 } = nextItem;
691
- const children = getChildren(graph, node2, filter, path2);
692
- const actions = graph.actions(node2);
693
- if (path2.length === 1 || open.includes(Path.create(...path2))) {
694
- for (let i = actions.length - 1; i >= 0; i--) {
695
- if (actions[i].properties.disposition === "item") {
696
- stack.push(getItem(actions[i], path2, filter));
697
- }
698
- }
699
- for (let i = children.length - 1; i >= 0; i--) {
700
- const child = children[i];
701
- stack.push(getItem(child, path2, filter));
702
- }
703
- }
704
- }
705
- }
706
- var treeItemsFromRootNode = (graph, rootNode, open, getItem, path, filter) => {
707
- return Array.from(navTreeItemVisitor({
708
- graph,
709
- node: rootNode,
710
- open,
711
- getItem,
712
- path,
713
- filter
714
- }));
715
- };
716
- var expandOpenGraphNodes = (graph, open) => {
717
- return Promise.all(open.map((id) => {
718
- const node = graph.findNode(Path.last(id));
719
- return node && expandChildrenAndActions(graph, node);
720
- }).filter(nonNullable));
721
- };
722
676
 
723
677
  // packages/plugins/plugin-navtree/src/components/NavTreeContainer.tsx
724
678
  var NODE_TYPE = "dxos/app-graph/node";
725
- var renderPresence = ({ item }) => /* @__PURE__ */ React6.createElement(Surface, {
679
+ var renderPresence = ({ node }) => /* @__PURE__ */ React6.createElement(Surface, {
726
680
  role: "presence--glyph",
727
681
  data: {
728
- object: item.node.data,
729
- id: item.node.id
682
+ object: node.data,
683
+ id: node.id
730
684
  }
731
685
  });
732
- var NavTreeContainer = ({ items, current, open, popoverAnchorId, ...props }) => {
686
+ var NavTreeContainer = /* @__PURE__ */ memo(({ popoverAnchorId, ...props }) => {
733
687
  const { closeNavigationSidebar } = useSidebars2(NAVTREE_PLUGIN);
734
688
  const [isLg] = useMediaQuery("lg", {
735
689
  ssr: false
736
690
  });
737
691
  const dispatch = useIntentDispatcher3();
738
692
  const { graph } = useGraph2();
693
+ const getActions2 = useCallback2((node) => getActions(graph, node), [
694
+ graph
695
+ ]);
696
+ const getItems = useCallback2((node) => {
697
+ return graph.nodes(node ?? graph.root, {
698
+ filter: (node2) => {
699
+ return untracked(() => {
700
+ const action = isActionLike(node2);
701
+ const disposition = node2.properties.disposition;
702
+ return !action || action && disposition === "item";
703
+ });
704
+ }
705
+ });
706
+ }, [
707
+ graph
708
+ ]);
709
+ const getProps = useCallback2((node, path) => {
710
+ const children = getChildren(graph, node, void 0, path);
711
+ const parentOf = children.length > 0 ? children.map(({ id }) => id) : node.properties.role === "branch" ? [] : void 0;
712
+ return {
713
+ id: node.id,
714
+ label: node.properties.label ?? node.id,
715
+ parentOf,
716
+ icon: node.properties.icon,
717
+ disabled: node.properties.disabled,
718
+ className: mx4(node.properties.modified && "italic", node.properties.className),
719
+ headingClassName: node.properties.headingClassName,
720
+ testId: node.properties.testId
721
+ };
722
+ }, [
723
+ graph
724
+ ]);
739
725
  const loadDescendents = useCallback2((node) => {
740
726
  void expandActions(graph, node);
741
727
  if (!isActionLike(node)) {
@@ -751,21 +737,24 @@ var NavTreeContainer = ({ items, current, open, popoverAnchorId, ...props }) =>
751
737
  graph
752
738
  ]);
753
739
  const canDrop = useCallback2((source, target) => {
754
- if (isSpace(target.node.data)) {
755
- return isEchoObject(source.node.data) || isSpace(source.node.data);
756
- } else if (isEchoObject(target.node.data)) {
757
- return isEchoObject(source.node.data);
740
+ const sourceNode = source.item;
741
+ const targetNode = target.item;
742
+ if (isSpace(targetNode.data)) {
743
+ return isEchoObject(sourceNode.data) || isSpace(sourceNode.data);
744
+ } else if (isEchoObject(targetNode.data)) {
745
+ return isEchoObject(sourceNode.data);
758
746
  } else {
759
747
  return false;
760
748
  }
761
749
  }, []);
762
- const handleSelect = useCallback2(({ node, actions, path }) => {
750
+ const handleSelect = useCallback2(({ item: node }) => {
763
751
  if (!node.data) {
764
752
  return;
765
753
  }
766
754
  if (isAction4(node)) {
767
- const [parentId] = path.slice(1);
768
- const parent = items.find(({ id }) => id === parentId)?.node;
755
+ const [parent] = graph.nodes(node, {
756
+ relation: "inbound"
757
+ });
769
758
  void (parent && node.data({
770
759
  node: parent,
771
760
  caller: NAV_TREE_ITEM
@@ -782,7 +771,7 @@ var NavTreeContainer = ({ items, current, open, popoverAnchorId, ...props }) =>
782
771
  }
783
772
  }
784
773
  });
785
- const defaultAction = actions?.find((action) => action.properties?.disposition === "default");
774
+ const defaultAction = graph.actions(node).find((action) => action.properties?.disposition === "default");
786
775
  if (isAction4(defaultAction)) {
787
776
  void defaultAction.data();
788
777
  }
@@ -790,14 +779,14 @@ var NavTreeContainer = ({ items, current, open, popoverAnchorId, ...props }) =>
790
779
  closeNavigationSidebar();
791
780
  }
792
781
  }, [
793
- items,
782
+ graph,
794
783
  dispatch,
795
784
  isLg,
796
785
  closeNavigationSidebar
797
786
  ]);
798
787
  useEffect2(() => {
799
788
  return monitorForElements({
800
- canMonitor: ({ source }) => isItem(source.data),
789
+ canMonitor: ({ source }) => isTreeData(source.data),
801
790
  onDrop: ({ location, source }) => {
802
791
  if (!location.current.dropTargets.length) {
803
792
  return;
@@ -805,21 +794,23 @@ var NavTreeContainer = ({ items, current, open, popoverAnchorId, ...props }) =>
805
794
  const target = location.current.dropTargets[0];
806
795
  const instruction = extractInstruction(target.data);
807
796
  if (instruction !== null && instruction.type !== "instruction-blocked") {
808
- const sourceNode = source.data.node;
809
- const targetNode = target.data.node;
797
+ const sourceNode = source.data.item;
798
+ const targetNode = target.data.item;
810
799
  const sourcePath = source.data.path;
811
800
  const targetPath = target.data.path;
812
- const nextItems = instruction.type.startsWith("reorder") ? items.filter((item) => item.path.slice(0, -1).join() === targetPath.slice(0, -1).join()) : items.filter((item) => item.path.slice(0, -1).join() === targetPath.join());
813
801
  const operation = sourcePath.slice(0, -1).join() === targetPath.slice(0, -1).join() && instruction.type !== "make-child" ? "rearrange" : resolveMigrationOperation(graph, sourceNode, targetPath, targetNode);
814
802
  const sourceParent = getParent(graph, sourceNode, sourcePath);
815
803
  const targetParent = getParent(graph, targetNode, targetPath);
816
- const sourceIndex = nextItems.findIndex(({ id }) => id === sourceNode.id);
817
- const targetIndex = nextItems.findIndex(({ id }) => id === targetNode.id);
818
- const migrationIndex = instruction.type === "make-child" ? nextItems.length > 0 ? nextItems.length - 1 : 0 : instruction.type === "reorder-below" ? targetIndex + 1 : targetIndex;
804
+ const sourceItems = getItems(sourceParent);
805
+ const targetItems = getItems(targetParent);
806
+ const sourceIndex = sourceItems.findIndex(({ id }) => id === sourceNode.id);
807
+ const targetIndex = targetItems.findIndex(({ id }) => id === targetNode.id);
808
+ const migrationIndex = instruction.type === "make-child" ? void 0 : instruction.type === "reorder-below" ? targetIndex + 1 : targetIndex;
819
809
  switch (operation) {
820
810
  case "rearrange": {
811
+ const nextItems = sourceItems.map(({ data }) => data);
821
812
  arrayMove(nextItems, sourceIndex, targetIndex);
822
- void sourceParent?.properties.onRearrangeChildren?.(nextItems.map((item) => item.node.data));
813
+ void sourceParent?.properties.onRearrangeChildren?.(nextItems);
823
814
  break;
824
815
  }
825
816
  case "copy": {
@@ -841,7 +832,7 @@ var NavTreeContainer = ({ items, current, open, popoverAnchorId, ...props }) =>
841
832
  }
842
833
  });
843
834
  }, [
844
- items
835
+ graph
845
836
  ]);
846
837
  return /* @__PURE__ */ React6.createElement(ElevationProvider, {
847
838
  elevation: "chrome"
@@ -858,9 +849,10 @@ var NavTreeContainer = ({ items, current, open, popoverAnchorId, ...props }) =>
858
849
  role: "none",
859
850
  className: "border-be border-separator !overflow-y-auto"
860
851
  }, /* @__PURE__ */ React6.createElement(NavTree, {
861
- items,
862
- open,
863
- current,
852
+ id: graph.root.id,
853
+ getActions: getActions2,
854
+ getItems,
855
+ getProps,
864
856
  loadDescendents,
865
857
  renderPresence,
866
858
  popoverAnchorId,
@@ -868,7 +860,7 @@ var NavTreeContainer = ({ items, current, open, popoverAnchorId, ...props }) =>
868
860
  onSelect: handleSelect,
869
861
  ...props
870
862
  })), /* @__PURE__ */ React6.createElement(NavTreeFooter, null)));
871
- };
863
+ });
872
864
 
873
865
  // packages/plugins/plugin-navtree/src/components/NavTreeDocumentTitle.tsx
874
866
  import { useEffect as useEffect3 } from "react";
@@ -896,7 +888,7 @@ import { useIdentity } from "@dxos/react-client/halo";
896
888
  import React7 from "react";
897
889
  import { ConnectionState, useNetworkStatus } from "@dxos/react-client/mesh";
898
890
  import { Avatar } from "@dxos/react-ui";
899
- import { focusRing, mx as mx4 } from "@dxos/react-ui-theme";
891
+ import { focusRing, mx as mx5 } from "@dxos/react-ui-theme";
900
892
  import { hexToFallback } from "@dxos/util";
901
893
  var INTERNAL = "https://avatars.githubusercontent.com/u/57182821";
902
894
  var HaloButton = (props) => {
@@ -904,7 +896,7 @@ var HaloButton = (props) => {
904
896
  const fallbackValue = hexToFallback(identityKey ?? "0");
905
897
  const { swarm: connectionState } = useNetworkStatus();
906
898
  return /* @__PURE__ */ React7.createElement("button", {
907
- className: mx4(focusRing, "rounded grid place-items-center"),
899
+ className: mx5(focusRing, "rounded grid place-items-center"),
908
900
  onClick
909
901
  }, /* @__PURE__ */ React7.createElement(Avatar.Root, {
910
902
  size,
@@ -989,93 +981,86 @@ var translations_default = [
989
981
  ];
990
982
 
991
983
  // packages/plugins/plugin-navtree/src/NavTreePlugin.tsx
992
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/plugin-navtree/src/NavTreePlugin.tsx";
984
+ var KEY = `${NAVTREE_PLUGIN}/state`;
985
+ var getInitialState = () => {
986
+ const stringified = localStorage.getItem(KEY);
987
+ if (!stringified) {
988
+ return;
989
+ }
990
+ try {
991
+ const cached = JSON.parse(stringified);
992
+ return cached.map(([key, value]) => [
993
+ key,
994
+ create(value)
995
+ ]);
996
+ } catch {
997
+ }
998
+ };
993
999
  var NavTreePlugin = () => {
994
1000
  let graphPlugin;
995
1001
  let graph;
996
- const itemCache = /* @__PURE__ */ new Map();
997
- const state = new LocalStorageStore("dxos.org/settings/navtree", {
998
- root: void 0,
999
- get flatTree() {
1000
- if (!this.root || !graph) {
1001
- return [];
1002
- }
1003
- return treeItemsFromRootNode(graph, this.root, this.open, getItem);
1004
- },
1005
- // TODO(thure): Do this dynamically.
1006
- open: [
1002
+ let unsubscribe;
1003
+ const state = new Map(getInitialState() ?? [
1004
+ // TODO(thure): Initialize these dynamically.
1005
+ [
1007
1006
  "root",
1007
+ create({
1008
+ open: true,
1009
+ current: false
1010
+ })
1011
+ ],
1012
+ [
1008
1013
  "root~dxos.org/plugin/space-spaces",
1009
- "root~dxos.org/plugin/files"
1014
+ create({
1015
+ open: true,
1016
+ current: false
1017
+ })
1018
+ ],
1019
+ [
1020
+ "root~dxos.org/plugin/files",
1021
+ create({
1022
+ open: true,
1023
+ current: false
1024
+ })
1010
1025
  ]
1011
- });
1012
- const getItem = (node, parent, filter) => {
1013
- invariant(graph, void 0, {
1014
- F: __dxlog_file,
1015
- L: 82,
1016
- S: void 0,
1017
- A: [
1018
- "graph",
1019
- ""
1020
- ]
1026
+ ]);
1027
+ const getItem = (_path) => {
1028
+ const path = Path.create(..._path);
1029
+ const value = state.get(path) ?? create({
1030
+ open: false,
1031
+ current: false
1021
1032
  });
1022
- const path = [
1023
- ...parent,
1024
- node.id
1025
- ];
1026
- const { actions, groupedActions } = getActions(graph, node);
1027
- const children = getChildren(graph, node, filter, path);
1028
- const parentOf = children.length > 0 ? children.map(({ id }) => id) : node.properties.role === "branch" ? [] : void 0;
1029
- const item = {
1030
- id: node.id,
1031
- label: node.properties.label ?? node.id,
1032
- icon: node.properties.icon,
1033
- disabled: node.properties.disabled,
1034
- testId: node.properties.testId,
1035
- className: mx5(node.properties.modified && "italic", node.properties.className),
1036
- headingClassName: node.properties.headingClassName,
1037
- path,
1038
- parentOf,
1039
- node,
1040
- actions,
1041
- groupedActions
1042
- };
1043
- const cachedItem = itemCache.get(node.id);
1044
- if (cachedItem && JSON.stringify(item) === JSON.stringify(cachedItem)) {
1045
- return cachedItem;
1046
- } else {
1047
- itemCache.set(node.id, item);
1048
- return item;
1033
+ if (!state.has(path)) {
1034
+ state.set(path, value);
1049
1035
  }
1036
+ return value;
1050
1037
  };
1051
- const handleOpenChange = (item, open) => {
1052
- const path = Path2.create(...item.path);
1053
- if (open) {
1054
- state.values.open.push(path);
1055
- } else {
1056
- const index = state.values.open.indexOf(path);
1057
- if (index > -1) {
1058
- state.values.open.splice(index, 1);
1059
- }
1060
- }
1038
+ const setItem = (path, key, next) => {
1039
+ const value = getItem(path);
1040
+ value[key] = next;
1041
+ localStorage.setItem(KEY, JSON.stringify(Array.from(state.entries())));
1042
+ };
1043
+ const isOpen = (path) => getItem(path).open;
1044
+ const isCurrent = (path) => getItem(path).current;
1045
+ const handleOpenChange = ({ item: { id }, path, open }) => {
1046
+ setItem(path, "open", open);
1061
1047
  if (graph) {
1062
- void expandOpenGraphNodes(graph, state.values.open);
1048
+ const node = graph.findNode(id);
1049
+ return node && expandChildrenAndActions(graph, node);
1063
1050
  }
1064
1051
  };
1065
1052
  return {
1066
1053
  meta: meta_default,
1067
1054
  ready: async (plugins) => {
1068
- state.prop({
1069
- key: "open",
1070
- type: LocalStorageStore.json()
1071
- });
1055
+ const layout = resolvePlugin(plugins, parseLayoutPlugin)?.provides.layout;
1056
+ const location = resolvePlugin(plugins, parseNavigationPlugin2)?.provides.location;
1072
1057
  graphPlugin = resolvePlugin(plugins, parseGraphPlugin);
1073
1058
  graph = graphPlugin?.provides.graph;
1074
- if (!graph) {
1059
+ if (!graph || !location || !layout) {
1075
1060
  return;
1076
1061
  }
1062
+ const soloPart = location?.active.solo?.[0];
1077
1063
  const dispatch = resolvePlugin(plugins, parseIntentPlugin)?.provides.intent.dispatch;
1078
- const soloPart = resolvePlugin(plugins, parseNavigationPlugin2)?.provides.location.active.solo?.[0];
1079
1064
  if (dispatch && soloPart) {
1080
1065
  void dispatch({
1081
1066
  plugin: NAVTREE_PLUGIN,
@@ -1085,8 +1070,30 @@ var NavTreePlugin = () => {
1085
1070
  }
1086
1071
  });
1087
1072
  }
1088
- state.values.root = graph.root;
1089
- void expandOpenGraphNodes(graph, state.values.open);
1073
+ let previous = [];
1074
+ unsubscribe = effect(() => {
1075
+ const part = layout.layoutMode === "solo" ? "solo" : "main";
1076
+ const current = location.active[part]?.map(({ id }) => id) ?? [];
1077
+ const removed = previous.filter((id) => !current.includes(id));
1078
+ previous = current;
1079
+ setTimeout(() => {
1080
+ removed.forEach((id) => {
1081
+ const keys = Array.from(state.keys()).filter((key) => Path.last(key) === id);
1082
+ keys.forEach((key) => {
1083
+ setItem(Path.parts(key), "current", false);
1084
+ });
1085
+ });
1086
+ current.forEach((id) => {
1087
+ const keys = Array.from(/* @__PURE__ */ new Set([
1088
+ ...state.keys(),
1089
+ id
1090
+ ])).filter((key) => Path.last(key) === id);
1091
+ keys.forEach((key) => {
1092
+ setItem(Path.parts(key), "current", true);
1093
+ });
1094
+ });
1095
+ });
1096
+ });
1090
1097
  graph.subscribeTraverse({
1091
1098
  visitor: (node, path) => {
1092
1099
  let shortcut;
@@ -1115,22 +1122,23 @@ var NavTreePlugin = () => {
1115
1122
  Keyboard2.singleton.setCurrentContext(graphPlugin?.provides.graph.root.id);
1116
1123
  },
1117
1124
  unload: async () => {
1125
+ unsubscribe?.();
1118
1126
  Keyboard2.singleton.destroy();
1119
1127
  },
1120
1128
  provides: {
1121
1129
  metadata: {
1122
1130
  records: {
1123
1131
  [NODE_TYPE]: {
1124
- parse: (item, type) => {
1132
+ parse: ({ item }, type) => {
1125
1133
  switch (type) {
1126
1134
  case "node":
1127
- return item.node;
1135
+ return item;
1128
1136
  case "object":
1129
- return item.node.data;
1137
+ return item.data;
1130
1138
  case "view-object":
1131
1139
  return {
1132
1140
  id: `${item.id}-view`,
1133
- object: item.node.data
1141
+ object: item.data
1134
1142
  };
1135
1143
  }
1136
1144
  }
@@ -1150,9 +1158,8 @@ var NavTreePlugin = () => {
1150
1158
  switch (role) {
1151
1159
  case "navigation":
1152
1160
  return /* @__PURE__ */ React10.createElement(NavTreeContainer, {
1153
- items: state.values.flatTree,
1154
- current: data.activeIds,
1155
- open: state.values.open,
1161
+ isOpen,
1162
+ isCurrent,
1156
1163
  onOpenChange: handleOpenChange,
1157
1164
  popoverAnchorId: data.popoverAnchorId
1158
1165
  });
@@ -1162,7 +1169,7 @@ var NavTreePlugin = () => {
1162
1169
  });
1163
1170
  }
1164
1171
  case "navbar-start": {
1165
- if (state.values.root && data.activeNode) {
1172
+ if (data.activeNode) {
1166
1173
  return {
1167
1174
  node: /* @__PURE__ */ React10.createElement(NavBarStart, {
1168
1175
  activeNode: data.activeNode,
@@ -1192,16 +1199,15 @@ var NavTreePlugin = () => {
1192
1199
  const path = await graph.waitForPath({
1193
1200
  target: intent.data.id
1194
1201
  });
1195
- const additionalOpenItems = [
1202
+ [
1196
1203
  ...Array(path.length)
1197
- ].reduce((acc, _, index) => {
1198
- const itemId = Path2.create(...path.slice(0, index));
1199
- if (itemId.length > 0 && !state.values.open.includes(itemId)) {
1200
- acc.push(itemId);
1204
+ ].forEach((_, index) => {
1205
+ const subpath = path.slice(0, index);
1206
+ const value = getItem(subpath);
1207
+ if (!value.open) {
1208
+ setItem(subpath, "open", true);
1201
1209
  }
1202
- return acc;
1203
- }, []);
1204
- state.values.open.push(...additionalOpenItems);
1210
+ });
1205
1211
  }
1206
1212
  break;
1207
1213
  }
@@ -1260,14 +1266,11 @@ export {
1260
1266
  expandActions,
1261
1267
  expandChildren,
1262
1268
  expandChildrenAndActions,
1263
- expandOpenGraphNodes,
1264
1269
  getActions,
1265
1270
  getChildren,
1266
1271
  getParent,
1267
1272
  getPersistenceParent,
1268
- getTreeItemNode,
1269
1273
  resolveMigrationOperation,
1270
- sortActions,
1271
- treeItemsFromRootNode
1274
+ sortActions
1272
1275
  };
1273
1276
  //# sourceMappingURL=index.mjs.map