@dxos/plugin-navtree 0.8.4-main.ead640a → 0.8.4-main.effb148878

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