@dxos/plugin-navtree 0.8.4-main.937b3ca → 0.8.4-main.9be5663bfe

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 (187) hide show
  1. package/dist/lib/browser/index.mjs +137 -72
  2. package/dist/lib/browser/index.mjs.map +4 -4
  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/capabilities/app-graph-builder.d.ts +6 -0
  6. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  7. package/dist/types/src/capabilities/index.d.ts +7 -5
  8. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  9. package/dist/types/src/capabilities/keyboard.d.ts +5 -0
  10. package/dist/types/src/capabilities/keyboard.d.ts.map +1 -0
  11. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  12. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  13. package/dist/types/src/capabilities/react-surface.d.ts +5 -0
  14. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  15. package/dist/types/src/capabilities/state.d.ts +6 -0
  16. package/dist/types/src/capabilities/state.d.ts.map +1 -0
  17. package/dist/types/src/components/NavTree/NavTree.d.ts +10 -32
  18. package/dist/types/src/components/NavTree/NavTree.d.ts.map +1 -1
  19. package/dist/types/src/components/NavTree/NavTree.stories.d.ts +10 -14
  20. package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +1 -1
  21. package/dist/types/src/components/{NavTreeContext.d.ts → NavTreeContext/NavTreeContext.d.ts} +1 -1
  22. package/dist/types/src/components/NavTreeContext/NavTreeContext.d.ts.map +1 -0
  23. package/dist/types/src/components/NavTreeContext/index.d.ts +2 -0
  24. package/dist/types/src/components/NavTreeContext/index.d.ts.map +1 -0
  25. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts +7 -3
  26. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts.map +1 -1
  27. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +1 -1
  28. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +1 -1
  30. package/dist/types/src/components/Sidebar/L0Menu.d.ts +4 -1
  31. package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -1
  32. package/dist/types/src/components/Sidebar/L1Panel.d.ts +3 -6
  33. package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -1
  34. package/dist/types/src/components/Sidebar/L1Tabs.d.ts +3 -2
  35. package/dist/types/src/components/Sidebar/L1Tabs.d.ts.map +1 -1
  36. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts.map +1 -1
  37. package/dist/types/src/components/index.d.ts +0 -3
  38. package/dist/types/src/components/index.d.ts.map +1 -1
  39. package/dist/types/src/components/types.d.ts +5 -13
  40. package/dist/types/src/components/types.d.ts.map +1 -1
  41. package/dist/types/src/{components/CommandsDialog/CommandsDialog.d.ts → containers/CommandsDialogContent/CommandsDialogContent.d.ts} +1 -1
  42. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.d.ts.map +1 -0
  43. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.stories.d.ts +29 -0
  44. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.stories.d.ts.map +1 -0
  45. package/dist/types/src/containers/CommandsDialogContent/index.d.ts +2 -0
  46. package/dist/types/src/containers/CommandsDialogContent/index.d.ts.map +1 -0
  47. package/dist/types/src/containers/CommandsTrigger/CommandsTrigger.d.ts.map +1 -0
  48. package/dist/types/src/containers/CommandsTrigger/index.d.ts +2 -0
  49. package/dist/types/src/containers/CommandsTrigger/index.d.ts.map +1 -0
  50. package/dist/types/src/containers/NavTreeContainer/NavTreeContainer.d.ts +9 -0
  51. package/dist/types/src/containers/NavTreeContainer/NavTreeContainer.d.ts.map +1 -0
  52. package/dist/types/src/containers/NavTreeContainer/index.d.ts +3 -0
  53. package/dist/types/src/containers/NavTreeContainer/index.d.ts.map +1 -0
  54. package/dist/types/src/containers/NavTreeDocumentTitle/NavTreeDocumentTitle.d.ts.map +1 -0
  55. package/dist/types/src/containers/NavTreeDocumentTitle/index.d.ts +2 -0
  56. package/dist/types/src/containers/NavTreeDocumentTitle/index.d.ts.map +1 -0
  57. package/dist/types/src/containers/index.d.ts +7 -0
  58. package/dist/types/src/containers/index.d.ts.map +1 -0
  59. package/dist/types/src/experimental/Tree.stories.d.ts +18 -4
  60. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
  61. package/dist/types/src/hooks/index.d.ts +5 -0
  62. package/dist/types/src/hooks/index.d.ts.map +1 -0
  63. package/dist/types/src/hooks/useActions.d.ts +5 -0
  64. package/dist/types/src/hooks/useActions.d.ts.map +1 -0
  65. package/dist/types/src/hooks/useLoadDescendents.d.ts +6 -0
  66. package/dist/types/src/hooks/useLoadDescendents.d.ts.map +1 -0
  67. package/dist/types/src/hooks/useNavTreeModel.d.ts +7 -0
  68. package/dist/types/src/hooks/useNavTreeModel.d.ts.map +1 -0
  69. package/dist/types/src/{hooks.d.ts → hooks/useNavTreeState.d.ts} +2 -14
  70. package/dist/types/src/hooks/useNavTreeState.d.ts.map +1 -0
  71. package/dist/types/src/meta.d.ts.map +1 -1
  72. package/dist/types/src/operations/expose.d.ts +5 -0
  73. package/dist/types/src/operations/expose.d.ts.map +1 -0
  74. package/dist/types/src/operations/index.d.ts +3 -0
  75. package/dist/types/src/operations/index.d.ts.map +1 -0
  76. package/dist/types/src/testing/app-graph-builder.d.ts.map +1 -1
  77. package/dist/types/src/testing/generator.d.ts +3 -3
  78. package/dist/types/src/testing/generator.d.ts.map +1 -1
  79. package/dist/types/src/translations.d.ts +9 -10
  80. package/dist/types/src/translations.d.ts.map +1 -1
  81. package/dist/types/src/types/events.d.ts.map +1 -1
  82. package/dist/types/src/util.d.ts +6 -2
  83. package/dist/types/src/util.d.ts.map +1 -1
  84. package/dist/types/tsconfig.tsbuildinfo +1 -1
  85. package/package.json +54 -43
  86. package/src/NavTreePlugin.tsx +26 -27
  87. package/src/capabilities/{app-graph-builder/app-graph-builder.ts → app-graph-builder.ts} +10 -9
  88. package/src/capabilities/index.ts +11 -5
  89. package/src/capabilities/{keyboard/keyboard.ts → keyboard.ts} +7 -6
  90. package/src/capabilities/operation-handler.ts +16 -0
  91. package/src/capabilities/{react-surface/react-surface.tsx → react-surface.tsx} +15 -15
  92. package/src/capabilities/{state/state.ts → state.ts} +43 -15
  93. package/src/components/NavTree/NavTree.stories.tsx +31 -28
  94. package/src/components/NavTree/NavTree.tsx +64 -22
  95. package/src/components/{NavTreeContext.tsx → NavTreeContext/NavTreeContext.tsx} +1 -1
  96. package/src/components/NavTreeContext/index.ts +5 -0
  97. package/src/components/NavTreeItem/NavTreeItemAction.stories.tsx +7 -9
  98. package/src/components/NavTreeItem/NavTreeItemAction.tsx +56 -39
  99. package/src/components/NavTreeItem/NavTreeItemColumns.tsx +43 -17
  100. package/src/components/Sidebar/L0Menu.tsx +104 -113
  101. package/src/components/Sidebar/L1Panel.tsx +253 -94
  102. package/src/components/Sidebar/L1Tabs.tsx +13 -4
  103. package/src/components/UserAccountAvatar/UserAccountAvatar.stories.tsx +2 -3
  104. package/src/components/UserAccountAvatar/UserAccountAvatar.tsx +1 -1
  105. package/src/components/index.ts +0 -3
  106. package/src/components/types.ts +12 -17
  107. package/src/containers/CommandsDialogContent/CommandsDialogContent.stories.tsx +45 -0
  108. package/src/{components/CommandsDialog/CommandsDialog.tsx → containers/CommandsDialogContent/CommandsDialogContent.tsx} +23 -21
  109. package/src/containers/CommandsDialogContent/index.ts +5 -0
  110. package/src/containers/CommandsTrigger/CommandsTrigger.tsx +28 -0
  111. package/src/containers/CommandsTrigger/index.ts +5 -0
  112. package/src/{components → containers/NavTreeContainer}/NavTreeContainer.tsx +85 -142
  113. package/src/containers/NavTreeContainer/index.ts +6 -0
  114. package/src/{components → containers/NavTreeDocumentTitle}/NavTreeDocumentTitle.tsx +2 -2
  115. package/src/containers/NavTreeDocumentTitle/index.ts +5 -0
  116. package/src/containers/index.ts +12 -0
  117. package/src/experimental/Tree.stories.tsx +81 -84
  118. package/src/experimental/Tree.tsx +3 -3
  119. package/src/hooks/index.ts +8 -0
  120. package/src/hooks/useActions.ts +34 -0
  121. package/src/hooks/useLoadDescendents.ts +23 -0
  122. package/src/hooks/useNavTreeModel.ts +118 -0
  123. package/src/{hooks.ts → hooks/useNavTreeState.ts} +3 -34
  124. package/src/meta.ts +2 -2
  125. package/src/operations/expose.ts +42 -0
  126. package/src/operations/index.ts +7 -0
  127. package/src/testing/app-graph-builder.ts +40 -36
  128. package/src/testing/generator.ts +25 -25
  129. package/src/translations.ts +9 -10
  130. package/src/types/capabilities.ts +2 -2
  131. package/src/types/events.ts +4 -3
  132. package/src/util.ts +19 -5
  133. package/dist/lib/browser/app-graph-builder-RSMA6I22.mjs +0 -43
  134. package/dist/lib/browser/app-graph-builder-RSMA6I22.mjs.map +0 -7
  135. package/dist/lib/browser/chunk-6YPQ625I.mjs +0 -1293
  136. package/dist/lib/browser/chunk-6YPQ625I.mjs.map +0 -7
  137. package/dist/lib/browser/chunk-AGQDZBPL.mjs +0 -23
  138. package/dist/lib/browser/chunk-AGQDZBPL.mjs.map +0 -7
  139. package/dist/lib/browser/chunk-YKTYPINZ.mjs +0 -19
  140. package/dist/lib/browser/chunk-YKTYPINZ.mjs.map +0 -7
  141. package/dist/lib/browser/keyboard-32EH3N4K.mjs +0 -52
  142. package/dist/lib/browser/keyboard-32EH3N4K.mjs.map +0 -7
  143. package/dist/lib/browser/operation-resolver-IB75DC5O.mjs +0 -52
  144. package/dist/lib/browser/operation-resolver-IB75DC5O.mjs.map +0 -7
  145. package/dist/lib/browser/react-surface-F6CVMS3Y.mjs +0 -58
  146. package/dist/lib/browser/react-surface-F6CVMS3Y.mjs.map +0 -7
  147. package/dist/lib/browser/state-EVYQOUI3.mjs +0 -120
  148. package/dist/lib/browser/state-EVYQOUI3.mjs.map +0 -7
  149. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts +0 -6
  150. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +0 -1
  151. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +0 -3
  152. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +0 -1
  153. package/dist/types/src/capabilities/keyboard/index.d.ts +0 -3
  154. package/dist/types/src/capabilities/keyboard/index.d.ts.map +0 -1
  155. package/dist/types/src/capabilities/keyboard/keyboard.d.ts +0 -5
  156. package/dist/types/src/capabilities/keyboard/keyboard.d.ts.map +0 -1
  157. package/dist/types/src/capabilities/operation-resolver/index.d.ts +0 -3
  158. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +0 -1
  159. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +0 -5
  160. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +0 -1
  161. package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
  162. package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
  163. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +0 -5
  164. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
  165. package/dist/types/src/capabilities/state/index.d.ts +0 -3
  166. package/dist/types/src/capabilities/state/index.d.ts.map +0 -1
  167. package/dist/types/src/capabilities/state/state.d.ts +0 -6
  168. package/dist/types/src/capabilities/state/state.d.ts.map +0 -1
  169. package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts.map +0 -1
  170. package/dist/types/src/components/CommandsDialog/CommandsTrigger.d.ts.map +0 -1
  171. package/dist/types/src/components/CommandsDialog/index.d.ts +0 -3
  172. package/dist/types/src/components/CommandsDialog/index.d.ts.map +0 -1
  173. package/dist/types/src/components/NavTreeContainer.d.ts +0 -16
  174. package/dist/types/src/components/NavTreeContainer.d.ts.map +0 -1
  175. package/dist/types/src/components/NavTreeContext.d.ts.map +0 -1
  176. package/dist/types/src/components/NavTreeDocumentTitle.d.ts.map +0 -1
  177. package/dist/types/src/hooks.d.ts.map +0 -1
  178. package/src/capabilities/app-graph-builder/index.ts +0 -7
  179. package/src/capabilities/keyboard/index.ts +0 -7
  180. package/src/capabilities/operation-resolver/index.ts +0 -7
  181. package/src/capabilities/operation-resolver/operation-resolver.ts +0 -41
  182. package/src/capabilities/react-surface/index.ts +0 -7
  183. package/src/capabilities/state/index.ts +0 -7
  184. package/src/components/CommandsDialog/CommandsTrigger.tsx +0 -26
  185. package/src/components/CommandsDialog/index.ts +0 -6
  186. /package/dist/types/src/{components/CommandsDialog → containers/CommandsTrigger}/CommandsTrigger.d.ts +0 -0
  187. /package/dist/types/src/{components → containers/NavTreeDocumentTitle}/NavTreeDocumentTitle.d.ts +0 -0
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export { CommandsDialogContent as default } from './CommandsDialogContent';
@@ -0,0 +1,28 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { useOperationInvoker } from '@dxos/app-framework/ui';
8
+ import { LayoutOperation } from '@dxos/app-toolkit';
9
+ import { Button, Icon, useTranslation } from '@dxos/react-ui';
10
+
11
+ import { COMMANDS_DIALOG, meta } from '#meta';
12
+
13
+ // TODO(thure): Refactor to be handled by a more appropriate plugin.
14
+ export const CommandsTrigger = () => {
15
+ const { invokePromise } = useOperationInvoker();
16
+ const { t } = useTranslation(meta.id);
17
+ return (
18
+ <Button
19
+ classNames='m-1 px-1 lg:px-2'
20
+ onClick={() =>
21
+ void invokePromise(LayoutOperation.UpdateDialog, { subject: COMMANDS_DIALOG, blockAlign: 'start' })
22
+ }
23
+ >
24
+ <span className='text-description font-normal grow text-start'>{t('command-list-input.placeholder')}</span>
25
+ <Icon icon='ph--magnifying-glass--regular' />
26
+ </Button>
27
+ );
28
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export { CommandsTrigger as default } from './CommandsTrigger';
@@ -2,167 +2,114 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
6
5
  import { type Instruction, extractInstruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
7
- import React, { forwardRef, memo, useCallback, useEffect, useMemo } from 'react';
6
+ import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
7
+ import React, { forwardRef, memo, useCallback, useEffect, useMemo, useRef } from 'react';
8
8
 
9
- import { Common } from '@dxos/app-framework';
10
- import { Surface, useAppGraph, useLayout, useOperationInvoker } from '@dxos/app-framework/react';
11
- import { PLANK_COMPANION_TYPE } from '@dxos/plugin-deck/types';
9
+ import { Surface, useOperationInvoker } from '@dxos/app-framework/ui';
10
+ import { LayoutOperation } from '@dxos/app-toolkit';
11
+ import { useAppGraph, useLayout } from '@dxos/app-toolkit/ui';
12
12
  import { Graph, Node, useActionRunner } from '@dxos/plugin-graph';
13
- import { useConnections, useActions as useGraphActions } from '@dxos/plugin-graph';
14
13
  import { useMediaQuery, useSidebars } from '@dxos/react-ui';
15
- import { type TreeData, type TreeItemDataProps, isTreeData } from '@dxos/react-ui-list';
16
- import { mx } from '@dxos/ui-theme';
17
- import { arrayMove, byPosition } from '@dxos/util';
14
+ import { type TreeData, isTreeData } from '@dxos/react-ui-list';
15
+ import { arrayMove } from '@dxos/util';
18
16
 
19
- import { useIsAlternateTree, useIsCurrent, useIsOpen, useNavTreeState } from '../hooks';
20
- import { meta } from '../meta';
21
- import { type FlattenedActions, type NavTreeItemGraphNode } from '../types';
22
- import { getChildren, getParent, resolveMigrationOperation } from '../util';
17
+ import { NAV_TREE_ITEM, NavTree, NavTreeContext } from '#components';
18
+ import { useNavTreeModel, useNavTreeState } from '#hooks';
19
+ import { meta } from '#meta';
20
+ import { type NavTreeItemGraphNode } from '#types';
23
21
 
24
- import { NAV_TREE_ITEM, NavTree } from './NavTree';
25
- import { NavTreeContext } from './NavTreeContext';
26
- import { type NavTreeContextValue } from './types';
22
+ import { filterItems, getParent, resolveMigrationOperation } from '../../util';
27
23
 
28
24
  // TODO(thure): Is NavTree truly authoritative in this regard?
29
25
  export const NODE_TYPE = 'dxos/app-graph/node';
30
26
 
31
- const renderItemEnd = ({ node, open }: { node: Node.Node; open: boolean }) => (
32
- <Surface role='navtree-item-end' data={{ id: node.id, subject: node.data, open }} limit={1} />
33
- );
34
-
35
- const getChildrenFilter = (node: Node.Node): node is Node.Node =>
36
- !Node.isActionLike(node) && node.type !== PLANK_COMPANION_TYPE && node.properties.disposition !== 'hidden';
37
-
38
- const filterItems = (node: Node.Node, disposition?: string) => {
39
- if (!disposition && (node.properties.disposition === 'hidden' || node.properties.disposition === 'alternate-tree')) {
40
- return false;
41
- } else if (!disposition) {
42
- const action = Node.isAction(node);
43
- return !action || node.properties.disposition === 'item';
44
- } else {
45
- return node.properties.disposition === disposition;
46
- }
27
+ // TODO(wittjosiah): Avoid using Surface within the navtree, prefer declarative data flow.
28
+ const NavTreeItemEnd = ({ node, open }: { node: Node.Node; open: boolean }) => {
29
+ const data = useMemo(() => ({ id: node.id, subject: node.data, open }), [node.id, node.data, open]);
30
+ return <Surface.Surface role='navtree-item-end' data={data} limit={1} />;
47
31
  };
48
32
 
49
33
  const getItems = (graph: Graph.ReadableGraph, node?: Node.Node, disposition?: string) => {
50
- return Graph.getConnections(graph, node?.id ?? Node.RootId, 'outbound').filter((node) =>
51
- filterItems(node, disposition),
52
- );
53
- };
54
-
55
- const useItems = (node?: Node.Node, options?: { disposition?: string; sort?: boolean }) => {
56
- const { graph } = useAppGraph();
57
- const connections = useConnections(graph, node?.id ?? Node.RootId);
58
- const filtered = connections.filter((node) => filterItems(node, options?.disposition));
59
- return options?.sort ? filtered.toSorted((a, b) => byPosition(a.properties, b.properties)) : filtered;
60
- };
61
-
62
- const useActions = (node: Node.Node): FlattenedActions => {
63
- const { graph } = useAppGraph();
64
- const actions = useGraphActions(graph, node.id);
65
-
66
- return useMemo(
67
- () =>
68
- actions.reduce(
69
- (acc: FlattenedActions, arg) => {
70
- if (arg.properties.disposition === 'item') {
71
- return acc;
72
- }
73
-
74
- acc.actions.push(arg);
75
- if (!Node.isAction(arg)) {
76
- const actionGroup = Graph.getActions(graph, arg.id);
77
- acc.groupedActions[arg.id] = actionGroup;
78
- }
79
- return acc;
80
- },
81
- { actions: [], groupedActions: {} },
82
- ),
83
- [actions],
84
- );
34
+ return Graph.getConnections(graph, node?.id ?? Node.RootId, 'child').filter((node) => filterItems(node, disposition));
85
35
  };
86
36
 
87
37
  export type NavTreeContainerProps = {
88
38
  popoverAnchorId?: string;
89
- topbar?: boolean;
90
- } & Pick<NavTreeContextValue, 'tab'>;
39
+ tab: string;
40
+ };
91
41
 
92
42
  export const NavTreeContainer$ = forwardRef<HTMLDivElement, NavTreeContainerProps>(
93
- ({ tab, popoverAnchorId, topbar }, forwardedRef) => {
43
+ ({ tab, popoverAnchorId }, forwardedRef) => {
94
44
  const [isLg] = useMediaQuery('lg');
95
- const { invokeSync, invokePromise } = useOperationInvoker();
45
+ const { invokePromise } = useOperationInvoker();
96
46
  const runAction = useActionRunner();
97
47
  const { graph } = useAppGraph();
98
48
  const { getItem, setItem } = useNavTreeState();
99
49
  const layout = useLayout();
50
+ const model = useNavTreeModel(Node.RootId);
100
51
  const { navigationSidebarState } = useSidebars(meta.id);
52
+ const latestRef = useRef({
53
+ tab,
54
+ activeItems: layout.active,
55
+ navigationSidebarState,
56
+ isLg,
57
+ });
101
58
 
102
- const getProps = useCallback(
103
- (node: Node.Node, path: string[]): TreeItemDataProps => {
104
- const children = getChildren(graph, node, path).filter(getChildrenFilter);
105
- const parentOf =
106
- children.length > 0 ? children.map(({ id }) => id) : node.properties.role === 'branch' ? [] : undefined;
107
- return {
108
- id: node.id,
109
- parentOf,
110
- disabled: node.properties.disabled,
111
- label: node.properties.label ?? node.id,
112
- className: mx(node.properties.className, node.properties.modified && 'italic'), // TODO(burdon): Italic?
113
- headingClassName: node.properties.headingClassName,
114
- icon: node.properties.icon,
115
- iconHue: node.properties.iconHue,
116
- testId: node.properties.testId,
117
- };
118
- },
119
- [graph],
120
- );
121
-
122
- const loadDescendents = useCallback(
123
- (node: Node.Node) => {
124
- Graph.expand(graph, node.id, 'outbound');
125
- // Load one level deeper, which resolves some juddering observed on open/close.
126
- Graph.getConnections(graph, node.id, 'outbound').forEach((child) => {
127
- Graph.expand(graph, child.id, 'outbound');
128
- });
129
- },
130
- [graph],
131
- );
59
+ useEffect(() => {
60
+ latestRef.current = {
61
+ tab,
62
+ activeItems: layout.active,
63
+ navigationSidebarState,
64
+ isLg,
65
+ };
66
+ }, [tab, layout.active, navigationSidebarState, isLg]);
132
67
 
133
68
  const handleOpenChange = useCallback(
134
69
  ({ item: { id }, path, open }: { item: Node.Node; path: string[]; open: boolean }) => {
135
70
  // TODO(thure): This might become a localstorage leak; openItemIds that no longer exist should be removed from this map.
136
71
  setItem(path, 'open', open);
137
- Graph.expand(graph, id, 'outbound');
72
+ Graph.expand(graph, id, 'child');
138
73
  },
139
- [graph],
74
+ [graph, setItem],
140
75
  );
141
76
 
142
77
  const handleTabChange = useCallback(
143
78
  (node: NavTreeItemGraphNode) => {
144
- invokeSync(Common.LayoutOperation.UpdateSidebar, {
79
+ Graph.expand(graph, node.id, 'child');
80
+
81
+ const {
82
+ tab: activeTab,
83
+ activeItems,
84
+ navigationSidebarState: currentSidebarState,
85
+ isLg: latestIsLg,
86
+ } = latestRef.current;
87
+ void invokePromise(LayoutOperation.UpdateSidebar, {
145
88
  state:
146
- node.id === tab
147
- ? navigationSidebarState === 'expanded'
148
- ? isLg
89
+ node.id === activeTab
90
+ ? currentSidebarState === 'expanded'
91
+ ? latestIsLg
149
92
  ? 'collapsed'
150
93
  : 'closed'
151
94
  : 'expanded'
152
95
  : 'expanded',
153
96
  });
154
97
 
155
- invokeSync(Common.LayoutOperation.SwitchWorkspace, { subject: node.id });
98
+ void invokePromise(LayoutOperation.SwitchWorkspace, { subject: node.id });
156
99
 
157
100
  // Open the first item if the workspace is empty.
158
- if (layout.active.length === 0) {
101
+ if (activeItems.length === 0) {
159
102
  const [item] = getItems(graph, node).filter((node) => !Node.isActionLike(node));
160
103
  if (item && item.data) {
161
- invokeSync(Common.LayoutOperation.Open, { subject: [item.id] });
104
+ if (layout.mode === 'multi') {
105
+ void invokePromise(LayoutOperation.Set, { subject: [item.id] });
106
+ } else {
107
+ void invokePromise(LayoutOperation.Open, { subject: [item.id] });
108
+ }
162
109
  }
163
110
  }
164
111
  },
165
- [invokeSync, layout.active, tab, navigationSidebarState, isLg],
112
+ [invokePromise, graph, layout.mode],
166
113
  );
167
114
 
168
115
  const blockInstruction = useCallback(
@@ -187,20 +134,24 @@ export const NavTreeContainer$ = forwardRef<HTMLDivElement, NavTreeContainerProp
187
134
  }
188
135
 
189
136
  if (Node.isAction(node)) {
190
- const [parent] = Graph.getConnections(graph, node.id, 'inbound');
137
+ const [parent] = Graph.getConnections(graph, node.id, Node.childRelation('inbound'));
191
138
  if (parent) {
192
- void runAction(node, { parent, caller: NAV_TREE_ITEM });
139
+ void runAction(node, { parent, path, caller: NAV_TREE_ITEM });
193
140
  }
194
141
  return;
195
142
  }
196
143
 
197
144
  const current = getItem(path).current;
198
145
  if (!current) {
199
- invokeSync(Common.LayoutOperation.Open, { subject: [node.id], key: node.properties.key });
146
+ if (layout.mode === 'multi') {
147
+ void invokePromise(LayoutOperation.Set, { subject: [node.id] });
148
+ } else {
149
+ void invokePromise(LayoutOperation.Open, { subject: [node.id], key: node.properties.key });
150
+ }
200
151
  } else if (option) {
201
- invokeSync(Common.LayoutOperation.Close, { subject: [node.id] });
152
+ void invokePromise(LayoutOperation.Close, { subject: [node.id] });
202
153
  } else {
203
- void invokePromise(Common.LayoutOperation.ScrollIntoView, { subject: node.id });
154
+ void invokePromise(LayoutOperation.ScrollIntoView, { subject: node.id });
204
155
  }
205
156
 
206
157
  const defaultAction = Graph.getActions(graph, node.id).find(
@@ -211,13 +162,13 @@ export const NavTreeContainer$ = forwardRef<HTMLDivElement, NavTreeContainerProp
211
162
  }
212
163
 
213
164
  if (!isLg) {
214
- invokeSync(Common.LayoutOperation.UpdateSidebar, { state: 'closed' });
165
+ void invokePromise(LayoutOperation.UpdateSidebar, { state: 'closed' });
215
166
  }
216
167
  },
217
- [graph, invokeSync, invokePromise, getItem, isLg, runAction],
168
+ [graph, invokePromise, getItem, runAction, isLg, layout.mode],
218
169
  );
219
170
 
220
- const handleBack = useCallback(() => invokeSync(Common.LayoutOperation.RevertWorkspace), [invokeSync]);
171
+ const handleBack = useCallback(() => void invokePromise(LayoutOperation.RevertWorkspace), [invokePromise]);
221
172
 
222
173
  // TODO(wittjosiah): Factor out hook.
223
174
  useEffect(() => {
@@ -235,8 +186,9 @@ export const NavTreeContainer$ = forwardRef<HTMLDivElement, NavTreeContainerProp
235
186
  const targetNode = target.data.item as NavTreeItemGraphNode;
236
187
  const sourcePath = source.data.path as string[];
237
188
  const targetPath = target.data.path as string[];
189
+ const sameParent = sourcePath.slice(0, -1).join() === targetPath.slice(0, -1).join();
238
190
  const operation =
239
- sourcePath.slice(0, -1).join() === targetPath.slice(0, -1).join() && instruction.type !== 'make-child'
191
+ sameParent && instruction.type !== 'make-child'
240
192
  ? 'rearrange'
241
193
  : resolveMigrationOperation(graph, sourceNode, targetPath, targetNode);
242
194
  const sourceParent = getParent(graph, sourceNode, sourcePath);
@@ -265,7 +217,7 @@ export const NavTreeContainer$ = forwardRef<HTMLDivElement, NavTreeContainerProp
265
217
  }
266
218
  case 'transfer': {
267
219
  const target = instruction.type === 'make-child' ? targetNode : targetParent;
268
- if (!target?.properties.onTransferStart || !sourceParent?.properties.onTransferEnd) {
220
+ if (!target?.properties.onTransferStart || target?.id === sourceParent?.id) {
269
221
  break;
270
222
  }
271
223
  void target?.properties.onTransferStart(sourceNode, migrationIndex);
@@ -285,50 +237,41 @@ export const NavTreeContainer$ = forwardRef<HTMLDivElement, NavTreeContainerProp
285
237
  [setItem],
286
238
  );
287
239
 
240
+ const onItemHover = useCallback(({ item }: { item: Node.Node }) => Graph.expand(graph, item.id, 'child'), [graph]);
241
+
288
242
  const navTreeContextValue = useMemo(
289
243
  () => ({
244
+ model,
245
+ popoverAnchorId,
246
+ renderItemEnd: NavTreeItemEnd,
290
247
  blockInstruction,
291
248
  canDrop,
292
249
  canSelect,
293
- getProps,
294
- useIsAlternateTree,
295
- useIsCurrent,
296
- useIsOpen,
297
- loadDescendents,
250
+ setAlternateTree,
298
251
  onBack: handleBack,
299
252
  onOpenChange: handleOpenChange,
300
253
  onSelect: handleSelect,
301
254
  onTabChange: handleTabChange,
302
- popoverAnchorId,
303
- renderItemEnd,
304
- setAlternateTree,
305
- tab,
306
- topbar,
307
- useActions,
308
- useItems,
255
+ onItemHover,
309
256
  }),
310
257
  [
258
+ model,
259
+ popoverAnchorId,
311
260
  blockInstruction,
312
261
  canDrop,
313
262
  canSelect,
314
- getProps,
263
+ setAlternateTree,
315
264
  handleBack,
316
265
  handleOpenChange,
317
266
  handleSelect,
318
267
  handleTabChange,
319
- loadDescendents,
320
- popoverAnchorId,
321
- renderItemEnd,
322
- setAlternateTree,
323
- tab,
324
- topbar,
325
- useActions,
268
+ onItemHover,
326
269
  ],
327
270
  );
328
271
 
329
272
  return (
330
273
  <NavTreeContext.Provider value={navTreeContextValue}>
331
- <NavTree id={Node.RootId} root={Graph.getRoot(graph)} open={layout.sidebarOpen} ref={forwardedRef} />
274
+ <NavTree id={Node.RootId} root={Graph.getRoot(graph)} tab={tab} open={layout.sidebarOpen} ref={forwardedRef} />
332
275
  </NavTreeContext.Provider>
333
276
  );
334
277
  },
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export { NavTreeContainer, NODE_TYPE } from './NavTreeContainer';
6
+ export { NavTreeContainer as default } from './NavTreeContainer';
@@ -7,12 +7,12 @@ import { type Node } from '@dxos/app-graph';
7
7
  import { toLocalizedString, useTranslation } from '@dxos/react-ui';
8
8
  import { osTranslations } from '@dxos/ui-theme';
9
9
 
10
- import { meta } from '../meta';
10
+ import { meta } from '#meta';
11
11
 
12
12
  export const NavTreeDocumentTitle = ({ node }: { node?: Node.Node }) => {
13
13
  const { t } = useTranslation(meta.id);
14
14
  useEffect(() => {
15
- document.title = node ? toLocalizedString(node.properties.label, t) : t('current app name', { ns: osTranslations });
15
+ document.title = node ? toLocalizedString(node.properties.label, t) : t('current-app.name', { ns: osTranslations });
16
16
  }, [node?.properties?.label]);
17
17
  return null;
18
18
  };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export { NavTreeDocumentTitle as default } from './NavTreeDocumentTitle';
@@ -0,0 +1,12 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { type ComponentType, lazy } from 'react';
6
+
7
+ export { NODE_TYPE } from './NavTreeContainer';
8
+
9
+ export const CommandsDialogContent: ComponentType<any> = lazy(() => import('./CommandsDialogContent'));
10
+ export const CommandsTrigger: ComponentType<any> = lazy(() => import('./CommandsTrigger'));
11
+ export const NavTreeContainer: ComponentType<any> = lazy(() => import('./NavTreeContainer'));
12
+ export const NavTreeDocumentTitle: ComponentType<any> = lazy(() => import('./NavTreeDocumentTitle'));