@dxos/plugin-navtree 0.8.4-main.67995b8 → 0.8.4-main.6fa680abb7

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 (239) hide show
  1. package/dist/lib/browser/CommandsDialogContent-2DKIOLJL.mjs +113 -0
  2. package/dist/lib/browser/CommandsDialogContent-2DKIOLJL.mjs.map +7 -0
  3. package/dist/lib/browser/CommandsTrigger-ABODVVMP.mjs +33 -0
  4. package/dist/lib/browser/CommandsTrigger-ABODVVMP.mjs.map +7 -0
  5. package/dist/lib/browser/NavTreeContainer-TLSYS4KK.mjs +12 -0
  6. package/dist/lib/browser/NavTreeContainer-TLSYS4KK.mjs.map +7 -0
  7. package/dist/lib/browser/NavTreeDocumentTitle-L6NLLWLD.mjs +26 -0
  8. package/dist/lib/browser/NavTreeDocumentTitle-L6NLLWLD.mjs.map +7 -0
  9. package/dist/lib/browser/app-graph-builder-Z43OTNI2.mjs +44 -0
  10. package/dist/lib/browser/app-graph-builder-Z43OTNI2.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-A4VDCIJC.mjs +19 -0
  12. package/dist/lib/browser/chunk-A4VDCIJC.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-AYF2TX65.mjs +14 -0
  14. package/dist/lib/browser/chunk-AYF2TX65.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-JT37R5HS.mjs +1468 -0
  16. package/dist/lib/browser/chunk-JT37R5HS.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-KF26WA4O.mjs +23 -0
  18. package/dist/lib/browser/chunk-KF26WA4O.mjs.map +7 -0
  19. package/dist/lib/browser/index.mjs +86 -95
  20. package/dist/lib/browser/index.mjs.map +4 -4
  21. package/dist/lib/browser/{keyboard-QRS6WOQH.mjs → keyboard-HYGFQO7T.mjs} +25 -19
  22. package/dist/lib/browser/keyboard-HYGFQO7T.mjs.map +7 -0
  23. package/dist/lib/browser/meta.json +1 -1
  24. package/dist/lib/browser/operation-resolver-VDWVUII5.mjs +49 -0
  25. package/dist/lib/browser/operation-resolver-VDWVUII5.mjs.map +7 -0
  26. package/dist/lib/browser/react-surface-D2RLMV4Z.mjs +59 -0
  27. package/dist/lib/browser/react-surface-D2RLMV4Z.mjs.map +7 -0
  28. package/dist/lib/browser/state-CWMNNF7K.mjs +131 -0
  29. package/dist/lib/browser/state-CWMNNF7K.mjs.map +7 -0
  30. package/dist/types/src/NavTreePlugin.d.ts +2 -1
  31. package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
  32. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts +6 -0
  33. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +1 -0
  34. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +3 -0
  35. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +1 -0
  36. package/dist/types/src/capabilities/index.d.ts +5 -105
  37. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  38. package/dist/types/src/capabilities/keyboard/index.d.ts +3 -0
  39. package/dist/types/src/capabilities/keyboard/index.d.ts.map +1 -0
  40. package/dist/types/src/capabilities/keyboard/keyboard.d.ts +5 -0
  41. package/dist/types/src/capabilities/keyboard/keyboard.d.ts.map +1 -0
  42. package/dist/types/src/capabilities/operation-resolver/index.d.ts +3 -0
  43. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +1 -0
  44. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +5 -0
  45. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +1 -0
  46. package/dist/types/src/capabilities/react-surface/index.d.ts +3 -0
  47. package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -0
  48. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +5 -0
  49. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -0
  50. package/dist/types/src/capabilities/state/index.d.ts +3 -0
  51. package/dist/types/src/capabilities/state/index.d.ts.map +1 -0
  52. package/dist/types/src/capabilities/state/state.d.ts +6 -0
  53. package/dist/types/src/capabilities/state/state.d.ts.map +1 -0
  54. package/dist/types/src/components/NavTree/NavTree.d.ts +11 -4
  55. package/dist/types/src/components/NavTree/NavTree.d.ts.map +1 -1
  56. package/dist/types/src/components/NavTree/NavTree.stories.d.ts +27 -5
  57. package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +1 -1
  58. package/dist/types/src/components/{NavTreeContext.d.ts → NavTreeContext/NavTreeContext.d.ts} +1 -1
  59. package/dist/types/src/components/NavTreeContext/NavTreeContext.d.ts.map +1 -0
  60. package/dist/types/src/components/NavTreeContext/index.d.ts +2 -0
  61. package/dist/types/src/components/NavTreeContext/index.d.ts.map +1 -0
  62. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts +10 -8
  63. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts.map +1 -1
  64. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +33 -4
  65. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +1 -1
  66. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts +1 -1
  67. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +1 -1
  68. package/dist/types/src/components/Sidebar/L0Menu.d.ts +10 -5
  69. package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -1
  70. package/dist/types/src/components/Sidebar/L1Panel.d.ts +4 -7
  71. package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -1
  72. package/dist/types/src/components/Sidebar/L1Tabs.d.ts +5 -4
  73. package/dist/types/src/components/Sidebar/L1Tabs.d.ts.map +1 -1
  74. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.d.ts.map +1 -1
  75. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts +8 -5
  76. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts.map +1 -1
  77. package/dist/types/src/components/index.d.ts +0 -3
  78. package/dist/types/src/components/index.d.ts.map +1 -1
  79. package/dist/types/src/components/types.d.ts +8 -16
  80. package/dist/types/src/components/types.d.ts.map +1 -1
  81. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.d.ts +6 -0
  82. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.d.ts.map +1 -0
  83. package/dist/types/src/containers/CommandsDialogContent/index.d.ts +3 -0
  84. package/dist/types/src/containers/CommandsDialogContent/index.d.ts.map +1 -0
  85. package/dist/types/src/containers/CommandsTrigger/CommandsTrigger.d.ts.map +1 -0
  86. package/dist/types/src/containers/CommandsTrigger/index.d.ts +3 -0
  87. package/dist/types/src/containers/CommandsTrigger/index.d.ts.map +1 -0
  88. package/dist/types/src/containers/NavTreeContainer/NavTreeContainer.d.ts +9 -0
  89. package/dist/types/src/containers/NavTreeContainer/NavTreeContainer.d.ts.map +1 -0
  90. package/dist/types/src/containers/NavTreeContainer/index.d.ts +3 -0
  91. package/dist/types/src/containers/NavTreeContainer/index.d.ts.map +1 -0
  92. package/dist/types/src/{components → containers/NavTreeDocumentTitle}/NavTreeDocumentTitle.d.ts +1 -1
  93. package/dist/types/src/containers/NavTreeDocumentTitle/NavTreeDocumentTitle.d.ts.map +1 -0
  94. package/dist/types/src/containers/NavTreeDocumentTitle/index.d.ts +3 -0
  95. package/dist/types/src/containers/NavTreeDocumentTitle/index.d.ts.map +1 -0
  96. package/dist/types/src/containers/index.d.ts +7 -0
  97. package/dist/types/src/containers/index.d.ts.map +1 -0
  98. package/dist/types/src/experimental/Tree.d.ts +1 -2
  99. package/dist/types/src/experimental/Tree.d.ts.map +1 -1
  100. package/dist/types/src/experimental/Tree.stories.d.ts +23 -6
  101. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
  102. package/dist/types/src/hooks/index.d.ts +5 -0
  103. package/dist/types/src/hooks/index.d.ts.map +1 -0
  104. package/dist/types/src/hooks/useActions.d.ts +5 -0
  105. package/dist/types/src/hooks/useActions.d.ts.map +1 -0
  106. package/dist/types/src/hooks/useLoadDescendents.d.ts +6 -0
  107. package/dist/types/src/hooks/useLoadDescendents.d.ts.map +1 -0
  108. package/dist/types/src/hooks/useNavTreeModel.d.ts +7 -0
  109. package/dist/types/src/hooks/useNavTreeModel.d.ts.map +1 -0
  110. package/dist/types/src/hooks/useNavTreeState.d.ts +22 -0
  111. package/dist/types/src/hooks/useNavTreeState.d.ts.map +1 -0
  112. package/dist/types/src/index.d.ts +1 -2
  113. package/dist/types/src/index.d.ts.map +1 -1
  114. package/dist/types/src/meta.d.ts +3 -4
  115. package/dist/types/src/meta.d.ts.map +1 -1
  116. package/dist/types/src/testing/app-graph-builder.d.ts +2 -3
  117. package/dist/types/src/testing/app-graph-builder.d.ts.map +1 -1
  118. package/dist/types/src/testing/generator.d.ts +5 -6
  119. package/dist/types/src/testing/generator.d.ts.map +1 -1
  120. package/dist/types/src/testing/update-state.d.ts +2 -2
  121. package/dist/types/src/testing/update-state.d.ts.map +1 -1
  122. package/dist/types/src/types/capabilities.d.ts +16 -0
  123. package/dist/types/src/types/capabilities.d.ts.map +1 -0
  124. package/dist/types/src/types/events.d.ts +5 -0
  125. package/dist/types/src/types/events.d.ts.map +1 -0
  126. package/dist/types/src/types/index.d.ts +4 -0
  127. package/dist/types/src/types/index.d.ts.map +1 -0
  128. package/dist/types/src/{types.d.ts → types/schema.d.ts} +10 -9
  129. package/dist/types/src/types/schema.d.ts.map +1 -0
  130. package/dist/types/src/util.d.ts +12 -9
  131. package/dist/types/src/util.d.ts.map +1 -1
  132. package/dist/types/tsconfig.tsbuildinfo +1 -1
  133. package/package.json +57 -55
  134. package/src/NavTreePlugin.tsx +64 -84
  135. package/src/capabilities/app-graph-builder/app-graph-builder.ts +42 -0
  136. package/src/capabilities/app-graph-builder/index.ts +7 -0
  137. package/src/capabilities/index.ts +5 -9
  138. package/src/capabilities/keyboard/index.ts +7 -0
  139. package/src/capabilities/keyboard/keyboard.ts +66 -0
  140. package/src/capabilities/operation-resolver/index.ts +7 -0
  141. package/src/capabilities/operation-resolver/operation-resolver.ts +45 -0
  142. package/src/capabilities/react-surface/index.ts +7 -0
  143. package/src/capabilities/react-surface/react-surface.tsx +53 -0
  144. package/src/capabilities/state/index.ts +7 -0
  145. package/src/capabilities/state/state.ts +149 -0
  146. package/src/components/NavTree/NavTree.stories.tsx +105 -98
  147. package/src/components/NavTree/NavTree.tsx +67 -32
  148. package/src/components/{NavTreeContext.tsx → NavTreeContext/NavTreeContext.tsx} +1 -1
  149. package/src/components/NavTreeContext/index.ts +5 -0
  150. package/src/components/NavTreeItem/NavTreeItemAction.stories.tsx +21 -13
  151. package/src/components/NavTreeItem/NavTreeItemAction.tsx +61 -37
  152. package/src/components/NavTreeItem/NavTreeItemColumns.tsx +68 -35
  153. package/src/components/Sidebar/L0Menu.tsx +170 -179
  154. package/src/components/Sidebar/L1Panel.tsx +252 -101
  155. package/src/components/Sidebar/L1Tabs.tsx +19 -33
  156. package/src/components/UserAccountAvatar/UserAccountAvatar.stories.tsx +9 -9
  157. package/src/components/UserAccountAvatar/UserAccountAvatar.tsx +20 -12
  158. package/src/components/index.ts +1 -3
  159. package/src/components/types.ts +15 -19
  160. package/src/containers/CommandsDialogContent/CommandsDialogContent.tsx +135 -0
  161. package/src/containers/CommandsDialogContent/index.ts +7 -0
  162. package/src/containers/CommandsTrigger/CommandsTrigger.tsx +26 -0
  163. package/src/containers/CommandsTrigger/index.ts +7 -0
  164. package/src/containers/NavTreeContainer/NavTreeContainer.tsx +271 -0
  165. package/src/containers/NavTreeContainer/index.ts +6 -0
  166. package/src/{components → containers/NavTreeDocumentTitle}/NavTreeDocumentTitle.tsx +5 -4
  167. package/src/containers/NavTreeDocumentTitle/index.ts +7 -0
  168. package/src/containers/index.ts +12 -0
  169. package/src/experimental/Tree.stories.tsx +78 -83
  170. package/src/experimental/Tree.tsx +6 -23
  171. package/src/hooks/index.ts +8 -0
  172. package/src/hooks/useActions.ts +34 -0
  173. package/src/hooks/useLoadDescendents.ts +23 -0
  174. package/src/hooks/useNavTreeModel.ts +118 -0
  175. package/src/hooks/useNavTreeState.ts +42 -0
  176. package/src/index.ts +1 -2
  177. package/src/meta.ts +11 -8
  178. package/src/testing/app-graph-builder.ts +159 -234
  179. package/src/testing/generator.ts +20 -18
  180. package/src/testing/update-state.ts +6 -6
  181. package/src/types/capabilities.ts +21 -0
  182. package/src/types/events.ts +12 -0
  183. package/src/types/index.ts +7 -0
  184. package/src/{types.ts → types/schema.ts} +9 -8
  185. package/src/util.ts +26 -33
  186. package/dist/lib/browser/app-graph-builder-5J4LRWDX.mjs +0 -45
  187. package/dist/lib/browser/app-graph-builder-5J4LRWDX.mjs.map +0 -7
  188. package/dist/lib/browser/chunk-ERDGQTH5.mjs +0 -16
  189. package/dist/lib/browser/chunk-ERDGQTH5.mjs.map +0 -7
  190. package/dist/lib/browser/chunk-WCARAZ7J.mjs +0 -15
  191. package/dist/lib/browser/chunk-WCARAZ7J.mjs.map +0 -7
  192. package/dist/lib/browser/chunk-WEMCSQI7.mjs +0 -1469
  193. package/dist/lib/browser/chunk-WEMCSQI7.mjs.map +0 -7
  194. package/dist/lib/browser/intent-resolver-3XYN2CBU.mjs +0 -47
  195. package/dist/lib/browser/intent-resolver-3XYN2CBU.mjs.map +0 -7
  196. package/dist/lib/browser/keyboard-QRS6WOQH.mjs.map +0 -7
  197. package/dist/lib/browser/react-surface-JSJ5SQX5.mjs +0 -51
  198. package/dist/lib/browser/react-surface-JSJ5SQX5.mjs.map +0 -7
  199. package/dist/lib/browser/state-54DY3DOY.mjs +0 -117
  200. package/dist/lib/browser/state-54DY3DOY.mjs.map +0 -7
  201. package/dist/types/src/capabilities/app-graph-builder.d.ts +0 -4
  202. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +0 -1
  203. package/dist/types/src/capabilities/capabilities.d.ts +0 -21
  204. package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
  205. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  206. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  207. package/dist/types/src/capabilities/keyboard.d.ts +0 -4
  208. package/dist/types/src/capabilities/keyboard.d.ts.map +0 -1
  209. package/dist/types/src/capabilities/react-surface.d.ts +0 -4
  210. package/dist/types/src/capabilities/react-surface.d.ts.map +0 -1
  211. package/dist/types/src/capabilities/state.d.ts +0 -20
  212. package/dist/types/src/capabilities/state.d.ts.map +0 -1
  213. package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts +0 -5
  214. package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts.map +0 -1
  215. package/dist/types/src/components/CommandsDialog/CommandsTrigger.d.ts.map +0 -1
  216. package/dist/types/src/components/CommandsDialog/index.d.ts +0 -3
  217. package/dist/types/src/components/CommandsDialog/index.d.ts.map +0 -1
  218. package/dist/types/src/components/NavTreeContainer.d.ts +0 -9
  219. package/dist/types/src/components/NavTreeContainer.d.ts.map +0 -1
  220. package/dist/types/src/components/NavTreeContext.d.ts.map +0 -1
  221. package/dist/types/src/components/NavTreeDocumentTitle.d.ts.map +0 -1
  222. package/dist/types/src/events.d.ts +0 -4
  223. package/dist/types/src/events.d.ts.map +0 -1
  224. package/dist/types/src/hooks.d.ts +0 -3
  225. package/dist/types/src/hooks.d.ts.map +0 -1
  226. package/dist/types/src/types.d.ts.map +0 -1
  227. package/src/capabilities/app-graph-builder.ts +0 -52
  228. package/src/capabilities/capabilities.ts +0 -20
  229. package/src/capabilities/intent-resolver.ts +0 -37
  230. package/src/capabilities/keyboard.ts +0 -59
  231. package/src/capabilities/react-surface.tsx +0 -45
  232. package/src/capabilities/state.ts +0 -104
  233. package/src/components/CommandsDialog/CommandsDialog.tsx +0 -118
  234. package/src/components/CommandsDialog/CommandsTrigger.tsx +0 -35
  235. package/src/components/CommandsDialog/index.ts +0 -6
  236. package/src/components/NavTreeContainer.tsx +0 -313
  237. package/src/events.ts +0 -11
  238. package/src/hooks.ts +0 -21
  239. /package/dist/types/src/{components/CommandsDialog → containers/CommandsTrigger}/CommandsTrigger.d.ts +0 -0
@@ -11,10 +11,12 @@ import {
11
11
  attachClosestEdge,
12
12
  extractClosestEdge,
13
13
  } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
14
+ import { useAtomValue } from '@effect-atom/atom-react';
14
15
  import React, {
15
- forwardRef,
16
16
  type MouseEvent,
17
17
  type PropsWithChildren,
18
+ forwardRef,
19
+ memo,
18
20
  useCallback,
19
21
  useLayoutEffect,
20
22
  useMemo,
@@ -23,16 +25,26 @@ import React, {
23
25
  } from 'react';
24
26
 
25
27
  import { type Node } from '@dxos/app-graph';
26
- import { invariant } from '@dxos/invariant';
27
- import { Icon, ListItem, ScrollArea, Tooltip, toLocalizedString, useMediaQuery, useTranslation } from '@dxos/react-ui';
28
- import { MenuProvider, DropdownMenu, type MenuItem } from '@dxos/react-ui-menu';
28
+ import { DxAvatar } from '@dxos/lit-ui/react';
29
+ import { useActionRunner } from '@dxos/plugin-graph';
30
+ import {
31
+ Icon,
32
+ ListItem,
33
+ ScrollArea,
34
+ type ThemedClassName,
35
+ Tooltip,
36
+ toLocalizedString,
37
+ useMediaQuery,
38
+ useTranslation,
39
+ } from '@dxos/react-ui';
40
+ import { Menu, type MenuItem } from '@dxos/react-ui-menu';
29
41
  import type { StackItemRearrangeHandler } from '@dxos/react-ui-stack';
30
42
  import { Tabs } from '@dxos/react-ui-tabs';
31
- import { mx } from '@dxos/react-ui-theme';
32
- import { arrayMove, getFirstTwoRenderableChars } from '@dxos/util';
43
+ import { mx } from '@dxos/ui-theme';
44
+ import { arrayMove } from '@dxos/util';
33
45
 
34
- import { useLoadDescendents } from '../../hooks';
35
- import { NAVTREE_PLUGIN } from '../../meta';
46
+ import { useNavTreeState } from '../../hooks';
47
+ import { meta } from '../../meta';
36
48
  import { l0ItemType } from '../../util';
37
49
  import { useNavTreeContext } from '../NavTreeContext';
38
50
  import { UserAccountAvatar } from '../UserAccountAvatar';
@@ -47,43 +59,43 @@ type L0ItemData = {
47
59
  };
48
60
 
49
61
  type L0ItemRootProps = {
50
- item: Node<any>;
51
- parent?: Node<any>;
62
+ item: Node.Node;
63
+ parent?: Node.Node;
52
64
  path: string[];
65
+ onMouseEnter?: () => void;
53
66
  };
54
67
 
55
68
  type L0ItemProps = L0ItemRootProps & {
56
- item: Node<any>;
57
- parent?: Node<any>;
69
+ item: Node.Node;
70
+ parent?: Node.Node;
58
71
  path: string[];
59
72
  pinned?: boolean;
60
73
  onRearrange?: StackItemRearrangeHandler<L0ItemData>;
74
+ onItemHover?: (params: { item: Node.Node }) => void;
61
75
  };
62
76
 
63
77
  const useL0ItemClick = ({ item, parent, path }: L0ItemProps, type: string) => {
64
- const { tab, isCurrent, onSelect, onTabChange } = useNavTreeContext();
65
- const [isLg] = useMediaQuery('lg', { ssr: false });
78
+ const { onSelect, onTabChange } = useNavTreeContext();
79
+ const { getItem } = useNavTreeState();
80
+ const [isLg] = useMediaQuery('lg');
81
+ const runAction = useActionRunner();
66
82
 
67
83
  return useCallback(
68
84
  (event: MouseEvent) => {
69
85
  switch (type) {
70
86
  case 'action': {
71
- const {
72
- data: invoke,
73
- properties: { caller },
74
- } = item;
75
-
76
- return invoke?.(caller ? { node: parent, caller } : { node: parent });
87
+ const { properties: { caller } = {} } = item;
88
+ return void runAction(item as Node.Action, caller ? { parent, path, caller } : { parent, path });
77
89
  }
78
90
 
79
91
  case 'tab':
80
92
  return onTabChange?.(item);
81
93
 
82
94
  case 'link':
83
- return onSelect?.({ item, path, current: !isCurrent(path, item), option: event.altKey });
95
+ return onSelect?.({ item, path, current: !getItem(path).current, option: event.altKey });
84
96
  }
85
97
  },
86
- [item, parent, type, tab, isCurrent, onSelect, onTabChange, isLg],
98
+ [item, parent, type, getItem, onSelect, onTabChange, isLg, runAction],
87
99
  );
88
100
  };
89
101
 
@@ -92,66 +104,57 @@ const l0Breakpoints: Record<string, string> = {
92
104
  };
93
105
 
94
106
  const l0ItemRoot =
95
- 'group/l0item flex w-full justify-center items-center relative data[type!="collection"]:cursor-pointer app-no-drag dx-focus-ring-group';
107
+ 'group/l0item flex w-full justify-center items-center relative data[type!="collection"]:cursor-pointer dx-app-no-drag dx-focus-ring-group';
96
108
 
97
109
  const l0ItemContent = 'flex justify-center items-center dx-focus-ring-group-indicator transition-colors rounded-sm';
98
110
 
99
- const L0ItemRoot = forwardRef<HTMLElement, PropsWithChildren<L0ItemRootProps>>(
100
- ({ item, parent, path, children }, forwardedRef) => {
101
- const { getProps } = useNavTreeContext();
102
- const { id, testId } = getProps?.(item, path) ?? {};
103
- const type = l0ItemType(item);
104
- const itemPath = useMemo(() => [...path, item.id], [item.id, path]);
105
-
106
- const { t } = useTranslation(NAVTREE_PLUGIN);
107
- const localizedString = toLocalizedString(item.properties.label, t);
108
-
109
- const handleClick = useL0ItemClick({ item, parent, path: itemPath }, type);
110
- const rootProps =
111
- type === 'tab'
112
- ? { value: item.id, tabIndex: 0, onClick: handleClick, 'data-testid': testId, 'data-itemid': id }
113
- : type !== 'collection'
114
- ? { onClick: handleClick, 'data-testid': testId, 'data-itemid': id }
115
- : { onClick: handleClick };
116
-
117
- const Root = type === 'collection' ? 'h2' : type === 'tab' ? Tabs.TabPrimitive : 'button';
118
-
119
- return (
120
- <Tooltip.Trigger asChild delayDuration={0} side='right' content={localizedString}>
121
- <Root
122
- {...(rootProps as any)}
123
- data-type={type}
124
- className={mx(l0ItemRoot, l0Breakpoints[item.properties.l0Breakpoint])}
125
- ref={forwardedRef}
126
- >
127
- {children}
128
- </Root>
129
- </Tooltip.Trigger>
130
- );
131
- },
111
+ const L0ItemRoot = memo(
112
+ forwardRef<HTMLElement, PropsWithChildren<L0ItemRootProps>>(
113
+ ({ item, parent, path, onMouseEnter, children }, forwardedRef) => {
114
+ const { model } = useNavTreeContext();
115
+ const itemPath = useMemo(() => [...path, item.id], [item.id, path]);
116
+ const { id, testId } = useAtomValue(model.itemProps(itemPath));
117
+ const type = l0ItemType(item);
118
+
119
+ const { t } = useTranslation(meta.id);
120
+ const localizedString = toLocalizedString(item.properties.label, t);
121
+
122
+ const handleClick = useL0ItemClick({ item, parent, path: itemPath }, type);
123
+ const rootProps =
124
+ type === 'tab'
125
+ ? { value: item.id, tabIndex: 0, onClick: handleClick, 'data-testid': testId, 'data-object-id': id }
126
+ : { onClick: handleClick, 'data-testid': testId, 'data-object-id': id };
127
+
128
+ return (
129
+ <Tooltip.Trigger asChild delayDuration={0} side='right' content={localizedString}>
130
+ <Tabs.TabPrimitive
131
+ {...(rootProps as any)}
132
+ data-type={type}
133
+ className={mx(l0ItemRoot, l0Breakpoints[item.properties.l0Breakpoint])}
134
+ ref={forwardedRef}
135
+ onMouseEnter={onMouseEnter}
136
+ >
137
+ {children}
138
+ </Tabs.TabPrimitive>
139
+ </Tooltip.Trigger>
140
+ );
141
+ },
142
+ ),
132
143
  );
133
144
 
134
- const L0Avatar = ({ item }: Pick<L0ItemProps, 'item'>) => {
135
- const { t } = useTranslation(NAVTREE_PLUGIN);
136
- const type = l0ItemType(item);
137
- const hue = item.properties.hue ?? null;
138
- const hueFgStyle = hue && { style: { color: `var(--dx-${hue}SurfaceText)` } };
139
- const localizedString = toLocalizedString(item.properties.label, t);
140
- const avatarValue = useMemo(
141
- () => (type === 'tab' ? getFirstTwoRenderableChars(localizedString).join('').toUpperCase() : []),
142
- [type, item.properties.label, t],
143
- );
144
-
145
- return (
146
- <span role='img' className='place-self-center text-xl font-light' {...hueFgStyle}>
147
- {avatarValue}
148
- </span>
149
- );
150
- };
145
+ export const L0ItemActiveTabIndicator = ({ classNames }: ThemedClassName<{}>) => (
146
+ <div
147
+ role='none'
148
+ className={mx(
149
+ 'hidden group-aria-selected/l0item:block absolute start-0 inset-y-2 w-1 bg-accent-surface rounded-ie',
150
+ classNames,
151
+ )}
152
+ />
153
+ );
151
154
 
152
155
  // TODO(burdon): Factor out pinned (non-draggable) items.
153
- const L0Item = ({ item, parent, path, pinned, onRearrange }: L0ItemProps) => {
154
- const { t } = useTranslation(NAVTREE_PLUGIN);
156
+ const L0Item = memo(({ item, parent, path, pinned, onRearrange, onItemHover }: L0ItemProps) => {
157
+ const { t } = useTranslation(meta.id);
155
158
  const itemElement = useRef<HTMLElement | null>(null);
156
159
  const [closestEdge, setEdge] = useState<Edge | null>(null);
157
160
  const localizedString = toLocalizedString(item.properties.label, t);
@@ -213,178 +216,175 @@ const L0Item = ({ item, parent, path, pinned, onRearrange }: L0ItemProps) => {
213
216
  );
214
217
  }, [item, onRearrange]);
215
218
 
219
+ const handleMouseEnter = useCallback(() => onItemHover?.({ item }), [item, onItemHover]);
220
+
216
221
  return (
217
- <L0ItemRoot ref={itemElement} item={item} parent={parent} path={path}>
222
+ <L0ItemRoot ref={itemElement} item={item} parent={parent} path={path} onMouseEnter={handleMouseEnter}>
218
223
  <div
219
224
  role='none'
220
225
  data-frame={true}
221
- {...(hue && { style: { background: `var(--dx-${hue}Surface)` } })}
226
+ {...(hue && { style: { background: `var(--color-${hue}-surface)` } })}
222
227
  className={mx(
223
228
  l0ItemContent,
224
229
  pinned
225
- ? 'p-2 group-hover/l0item:bg-activeSurface'
226
- : 'is-[--l0-avatar-size] bs-[--l0-avatar-size] bg-activeSurface',
230
+ ? 'p-2 group-hover/l0item:bg-active-surface'
231
+ : 'w-(--dx-l0-avatar-size) h-(--dx-l0-avatar-size) bg-active-surface',
227
232
  )}
228
233
  >
229
234
  <ItemAvatar item={item} />
230
235
  </div>
231
- <div
232
- role='none'
233
- className='hidden group-aria-selected/l0item:block absolute inline-start-0 inset-block-2 is-1 bg-accentSurface rounded-ie'
234
- />
236
+ <L0ItemActiveTabIndicator />
235
237
  <span id={`${item.id}__label`} className='sr-only'>
236
238
  {localizedString}
237
239
  </span>
238
240
  {closestEdge && <ListItem.DropIndicator edge={closestEdge} />}
239
241
  </L0ItemRoot>
240
242
  );
241
- };
243
+ });
242
244
 
243
245
  const ItemAvatar = ({ item }: Pick<L0ItemProps, 'item'>) => {
246
+ const { t } = useTranslation(meta.id);
244
247
  const type = l0ItemType(item);
245
248
  if (item.properties.icon) {
246
249
  const hue = item.properties.hue ?? null;
247
- const hueFgStyle = hue && { style: { color: `var(--dx-${hue}SurfaceText)` } };
248
- return <Icon icon={item.properties.icon} size={5} {...hueFgStyle} />;
250
+ const hueFgStyle = hue && { style: { color: `var(--color-${hue}-surface-text)` } };
251
+ return <Icon icon={item.properties.icon} size={6} {...hueFgStyle} />;
249
252
  }
250
253
 
251
254
  if (type === 'tab' && item.properties.disposition !== 'pin-end') {
252
- return <L0Avatar item={item} />;
255
+ const hue = item.properties.hue ?? null;
256
+ const localizedString = toLocalizedString(item.properties.label, t);
257
+ return <DxAvatar hue={hue} hueVariant='surface' variant='square' size={12} fallback={localizedString} />;
253
258
  }
254
259
 
255
260
  return null;
256
261
  };
257
262
 
258
263
  //
259
- // L0Collection
264
+ // L0Menu
260
265
  //
261
266
 
262
- const L0Collection = ({ item, path }: L0ItemProps) => {
263
- const navTreeContext = useNavTreeContext();
264
- useLoadDescendents(item);
265
- const collectionItems = navTreeContext.useItems(item);
266
- const groupPath = useMemo(() => [...path, item.id], [item.id, path]);
267
- const { id, testId } = navTreeContext.getProps?.(item, path) ?? {};
267
+ export type L0MenuProps = {
268
+ menuActions: MenuItem[];
269
+ topLevelItems: Node.Node[];
270
+ pinnedItems: Node.Node[];
271
+ userAccountItem?: Node.Node;
272
+ parent?: Node.Node;
273
+ path: string[];
274
+ onItemHover?: (params: { item: Node.Node }) => void;
275
+ };
276
+
277
+ export const L0Menu = ({
278
+ menuActions,
279
+ topLevelItems,
280
+ pinnedItems,
281
+ userAccountItem,
282
+ parent,
283
+ path,
284
+ onItemHover,
285
+ }: L0MenuProps) => {
286
+ const { t } = useTranslation(meta.id);
287
+ const runAction = useActionRunner();
288
+ const handleAction = useCallback(
289
+ (action: Node.Action, params: Node.InvokeProps) => {
290
+ void runAction(action, params);
291
+ },
292
+ [runAction],
293
+ );
268
294
 
269
295
  const handleRearrange = useCallback<StackItemRearrangeHandler<L0ItemData>>(
270
296
  (source, target, closestEdge) => {
271
- invariant(item.properties.onRearrangeChildren);
272
- const sourceIndex = collectionItems.findIndex((i) => i.id === source.id);
273
- const targetIndex = collectionItems.findIndex((i) => i.id === target.id);
297
+ const sourceItem = topLevelItems.find((i) => i.id === source.id);
298
+ if (!sourceItem?.properties.onRearrange) {
299
+ return;
300
+ }
301
+
302
+ const sourceIndex = topLevelItems.findIndex((i) => i.id === source.id);
303
+ const targetIndex = topLevelItems.findIndex((i) => i.id === target.id);
274
304
  const insertIndex =
275
305
  source.id === target.id
276
306
  ? sourceIndex
277
307
  : targetIndex +
278
308
  (sourceIndex < targetIndex ? (closestEdge === 'top' ? -1 : 0) : closestEdge === 'bottom' ? 1 : 0);
279
- const nextOrder = arrayMove([...collectionItems], sourceIndex, insertIndex);
280
- return item.properties.onRearrangeChildren(nextOrder);
309
+ const nextOrder = arrayMove([...topLevelItems], sourceIndex, insertIndex);
310
+ return sourceItem.properties.onRearrange(nextOrder.map((item) => item.data));
281
311
  },
282
- [collectionItems, item.properties.onRearrangeChildren],
312
+ [topLevelItems],
283
313
  );
284
314
 
285
- return (
286
- <div
287
- role='group'
288
- className='contents group/l0c'
289
- aria-labelledby={`${item.id}__label`}
290
- data-itemid={id}
291
- data-testid={testId}
292
- >
293
- {collectionItems.map((collectionItem) => (
294
- <L0Item
295
- key={collectionItem.id}
296
- item={collectionItem}
297
- parent={item}
298
- path={groupPath}
299
- {...(item.properties.onRearrangeChildren && { onRearrange: handleRearrange })}
300
- />
301
- ))}
302
- </div>
303
- );
304
- };
305
-
306
- //
307
- // L0Menu
308
- //
309
-
310
- export type L0MenuProps = {
311
- menuActions: MenuItem[];
312
- topLevelItems: Node<any>[];
313
- pinnedItems: Node<any>[];
314
- userAccountItem?: Node<any>;
315
- parent?: Node<any>;
316
- path: string[];
317
- };
318
-
319
- export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountItem, parent, path }: L0MenuProps) => {
320
- const { t } = useTranslation(NAVTREE_PLUGIN);
315
+ // Check if any items have onRearrange to enable drag-and-drop.
316
+ const hasRearrangeableItems = topLevelItems.some((item) => item.properties.onRearrange);
321
317
 
322
318
  return (
323
319
  <Tabs.Tablist
324
320
  classNames={[
325
- 'group/l0 absolute z-[1] inset-block-0 inline-start-0 rounded-is',
326
- 'grid grid-cols-[var(--l0-size)] grid-rows-[var(--rail-size)_1fr_min-content_var(--l0-size)] contain-layout',
327
- '!is-[--l0-size] bg-baseSurface border-ie border-subduedSeparator app-drag pbe-[env(safe-area-inset-bottom)]',
321
+ 'group/l0 absolute z-[1] inset-y-0 start-0 rounded-is',
322
+ 'grid grid-cols-[var(--dx-l0-size)] grid-rows-[var(--dx-rail-size)_1fr_min-content_var(--dx-l0-size)] dx-contain-layout',
323
+ '!w-(--dx-l0-size) bg-toolbar-surface border-e border-subdued-separator dx-app-drag pb-[env(safe-area-inset-bottom)]',
328
324
  ]}
329
325
  >
330
326
  {/* TODO(wittjosiah): Use L0Item trigger. */}
331
- <MenuProvider>
332
- <DropdownMenu.Root group={parent} items={menuActions}>
327
+ <Menu.Root onAction={handleAction}>
328
+ <Menu.Trigger
329
+ asChild
330
+ data-testid='spacePlugin.addSpace'
331
+ className={mx(
332
+ l0ItemRoot,
333
+ 'grid place-items-center dx-focus-ring-group',
334
+ '[body[data-platform="macos"]_&]:mt-[30px]',
335
+ )}
336
+ >
333
337
  <Tooltip.Trigger content={t('app menu label')} side='right' asChild>
334
- <DropdownMenu.Trigger
335
- data-testid='spacePlugin.addSpace'
336
- className={mx(l0ItemRoot, 'grid place-items-center')}
337
- >
338
+ <Tabs.TabPrimitive value='options' asChild role='button'>
338
339
  <div
339
340
  role='none'
340
341
  className={mx(
341
342
  l0ItemContent,
342
- 'is-[--rail-action] bs-[--rail-action] group-hover/l0item:bg-hoverSurface',
343
+ 'h-(--dx-rail-action) w-(--dx-rail-action) group-hover/l0item:bg-hover-surface',
343
344
  )}
344
345
  >
345
346
  <Icon icon='ph--list--regular' size={5} />
346
347
  </div>
347
- </DropdownMenu.Trigger>
348
+ </Tabs.TabPrimitive>
348
349
  </Tooltip.Trigger>
349
- </DropdownMenu.Root>
350
- </MenuProvider>
350
+ </Menu.Trigger>
351
+ <Menu.Content group={parent} items={menuActions} />
352
+ </Menu.Root>
351
353
 
352
354
  {/* Space list. */}
353
- <ScrollArea.Root>
355
+ <ScrollArea.Root thin orientation='vertical'>
354
356
  <ScrollArea.Viewport>
355
357
  <div
356
358
  role='none'
357
359
  className={mx([
358
- 'flex flex-col gap-1 pbs-1',
359
- '[body[data-platform="darwin"]_&]:pbs-[calc(30px+0.25rem)]',
360
- '[body[data-platform="ios"]_&]:pbs-[max(env(safe-area-inset-top),0.25rem)]',
360
+ 'flex flex-col gap-1 pt-1',
361
+ '[body[data-platform="macos"]_&]:py-[30px]',
362
+ '[body[data-platform="ios"]_&]:py-[max(env(safe-area-inset-top),0.25rem)]',
361
363
  ])}
362
364
  >
363
- {topLevelItems.map((item) => {
364
- if (l0ItemType(item) === 'collection') {
365
- return <L0Collection key={item.id} item={item} parent={parent} path={path} />;
366
- } else {
367
- return <L0Item key={item.id} item={item} parent={parent} path={path} />;
368
- }
369
- })}
365
+ {topLevelItems.map((item) => (
366
+ <L0Item
367
+ key={item.id}
368
+ item={item}
369
+ parent={parent}
370
+ path={path}
371
+ onItemHover={onItemHover}
372
+ {...(hasRearrangeableItems && { onRearrange: handleRearrange })}
373
+ />
374
+ ))}
370
375
  </div>
371
- <ScrollArea.Scrollbar orientation='vertical'>
372
- <ScrollArea.Thumb />
373
- </ScrollArea.Scrollbar>
374
376
  </ScrollArea.Viewport>
375
377
  </ScrollArea.Root>
376
378
 
377
379
  {/* Actions. */}
378
- <div role='none' className='grid grid-cols-1 auto-rows-[--rail-action] pbs-2'>
379
- {pinnedItems
380
- .filter((item) => l0ItemType(item) !== 'collection')
381
- .map((item) => (
382
- <L0Item key={item.id} item={item} parent={parent} path={path} pinned />
383
- ))}
380
+ <div role='none' className='grid grid-cols-1 auto-rows-(--dx-rail-action) pt-2'>
381
+ {pinnedItems.map((item) => (
382
+ <L0Item key={item.id} item={item} parent={parent} path={path} pinned />
383
+ ))}
384
384
  </div>
385
385
 
386
386
  {userAccountItem && (
387
- <div role='none' className='grid app-no-drag'>
387
+ <div role='none' className='grid dx-app-no-drag'>
388
388
  <L0ItemRoot key={userAccountItem.id} item={userAccountItem} parent={parent} path={path}>
389
389
  <UserAccountAvatar
390
390
  userId={userAccountItem.properties.userId}
@@ -396,15 +396,6 @@ export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountIte
396
396
  </L0ItemRoot>
397
397
  </div>
398
398
  )}
399
-
400
- <div
401
- role='none'
402
- className='hidden [body[data-platform="darwin"]_&]:block absolute block-start-0 is-[calc(var(--l0-size)-1px)] bs-[calc(40px+0.25rem)]'
403
- style={{
404
- background:
405
- 'linear-gradient(to bottom, var(--dx-sidebarSurface) 0%, var(--dx-sidebarSurface) 70%, transparent 100%)',
406
- }}
407
- />
408
399
  </Tabs.Tablist>
409
400
  );
410
401
  };