@dxos/plugin-navtree 0.8.4-main.4a85c3132b → 0.8.4-main.51f1e5ca51

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 (169) hide show
  1. package/dist/lib/browser/index.mjs +115 -74
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/browser/translations.mjs +21 -0
  5. package/dist/lib/browser/translations.mjs.map +7 -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.map +1 -0
  10. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  11. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  12. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  13. package/dist/types/src/capabilities/{state/state.d.ts → state.d.ts} +1 -1
  14. package/dist/types/src/capabilities/state.d.ts.map +1 -0
  15. package/dist/types/src/components/NavTree/NavTree.d.ts.map +1 -1
  16. package/dist/types/src/components/NavTree/NavTree.stories.d.ts +9 -11
  17. package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +1 -1
  18. package/dist/types/src/components/{NavTreeContext.d.ts → NavTreeContext/NavTreeContext.d.ts} +1 -1
  19. package/dist/types/src/components/NavTreeContext/NavTreeContext.d.ts.map +1 -0
  20. package/dist/types/src/components/NavTreeContext/index.d.ts +2 -0
  21. package/dist/types/src/components/NavTreeContext/index.d.ts.map +1 -0
  22. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts +7 -3
  23. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts.map +1 -1
  24. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +1 -1
  25. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +1 -1
  26. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +1 -1
  27. package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -1
  28. package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -1
  29. package/dist/types/src/components/Sidebar/L1Tabs.d.ts.map +1 -1
  30. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.d.ts.map +1 -1
  31. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts.map +1 -1
  32. package/dist/types/src/components/types.d.ts +1 -2
  33. package/dist/types/src/components/types.d.ts.map +1 -1
  34. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.d.ts.map +1 -1
  35. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.stories.d.ts +28 -0
  36. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.stories.d.ts.map +1 -0
  37. package/dist/types/src/containers/CommandsDialogContent/index.d.ts +1 -2
  38. package/dist/types/src/containers/CommandsDialogContent/index.d.ts.map +1 -1
  39. package/dist/types/src/containers/CommandsTrigger/CommandsTrigger.d.ts.map +1 -1
  40. package/dist/types/src/containers/CommandsTrigger/index.d.ts +1 -2
  41. package/dist/types/src/containers/CommandsTrigger/index.d.ts.map +1 -1
  42. package/dist/types/src/containers/NavTreeContainer/NavTreeContainer.d.ts.map +1 -1
  43. package/dist/types/src/containers/NavTreeContainer/index.d.ts +2 -2
  44. package/dist/types/src/containers/NavTreeContainer/index.d.ts.map +1 -1
  45. package/dist/types/src/containers/NavTreeDocumentTitle/NavTreeDocumentTitle.d.ts.map +1 -1
  46. package/dist/types/src/containers/NavTreeDocumentTitle/index.d.ts +1 -2
  47. package/dist/types/src/containers/NavTreeDocumentTitle/index.d.ts.map +1 -1
  48. package/dist/types/src/containers/index.d.ts +1 -1
  49. package/dist/types/src/containers/index.d.ts.map +1 -1
  50. package/dist/types/src/experimental/Tree.d.ts +2 -2
  51. package/dist/types/src/experimental/Tree.d.ts.map +1 -1
  52. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
  53. package/dist/types/src/hooks/useActions.d.ts +2 -4
  54. package/dist/types/src/hooks/useActions.d.ts.map +1 -1
  55. package/dist/types/src/hooks/useLoadDescendents.d.ts.map +1 -1
  56. package/dist/types/src/hooks/useNavTreeModel.d.ts +1 -1
  57. package/dist/types/src/hooks/useNavTreeModel.d.ts.map +1 -1
  58. package/dist/types/src/hooks/useNavTreeState.d.ts +2 -6
  59. package/dist/types/src/hooks/useNavTreeState.d.ts.map +1 -1
  60. package/dist/types/src/meta.d.ts.map +1 -1
  61. package/dist/types/src/operations/expose.d.ts +5 -0
  62. package/dist/types/src/operations/expose.d.ts.map +1 -0
  63. package/dist/types/src/operations/index.d.ts +3 -0
  64. package/dist/types/src/operations/index.d.ts.map +1 -0
  65. package/dist/types/src/testing/app-graph-builder.d.ts.map +1 -1
  66. package/dist/types/src/testing/generator.d.ts.map +1 -1
  67. package/dist/types/src/testing/update-state.d.ts.map +1 -1
  68. package/dist/types/src/translations.d.ts +8 -11
  69. package/dist/types/src/translations.d.ts.map +1 -1
  70. package/dist/types/src/types/capabilities.d.ts +1 -2
  71. package/dist/types/src/types/capabilities.d.ts.map +1 -1
  72. package/dist/types/src/types/events.d.ts.map +1 -1
  73. package/dist/types/src/util.d.ts +2 -2
  74. package/dist/types/src/util.d.ts.map +1 -1
  75. package/dist/types/tsconfig.tsbuildinfo +1 -1
  76. package/package.json +57 -43
  77. package/src/NavTreePlugin.tsx +7 -7
  78. package/src/capabilities/{app-graph-builder/app-graph-builder.ts → app-graph-builder.ts} +7 -7
  79. package/src/capabilities/index.ts +11 -5
  80. package/src/capabilities/{keyboard/keyboard.ts → keyboard.ts} +2 -2
  81. package/src/capabilities/operation-handler.ts +16 -0
  82. package/src/capabilities/{react-surface/react-surface.tsx → react-surface.tsx} +8 -8
  83. package/src/capabilities/{state/state.ts → state.ts} +5 -5
  84. package/src/components/NavTree/NavTree.stories.tsx +17 -16
  85. package/src/components/NavTree/NavTree.tsx +3 -2
  86. package/src/components/{NavTreeContext.tsx → NavTreeContext/NavTreeContext.tsx} +1 -1
  87. package/src/components/NavTreeContext/index.ts +5 -0
  88. package/src/components/NavTreeItem/NavTreeItemAction.stories.tsx +6 -8
  89. package/src/components/NavTreeItem/NavTreeItemAction.tsx +62 -45
  90. package/src/components/NavTreeItem/NavTreeItemColumns.tsx +7 -5
  91. package/src/components/Sidebar/L0Menu.tsx +49 -74
  92. package/src/components/Sidebar/L1Panel.tsx +97 -134
  93. package/src/components/Sidebar/L1Tabs.tsx +0 -1
  94. package/src/components/types.ts +1 -2
  95. package/src/containers/CommandsDialogContent/CommandsDialogContent.stories.tsx +46 -0
  96. package/src/containers/CommandsDialogContent/CommandsDialogContent.tsx +52 -58
  97. package/src/containers/CommandsDialogContent/index.ts +1 -3
  98. package/src/containers/CommandsTrigger/CommandsTrigger.tsx +7 -5
  99. package/src/containers/CommandsTrigger/index.ts +1 -3
  100. package/src/containers/NavTreeContainer/NavTreeContainer.tsx +28 -27
  101. package/src/containers/NavTreeContainer/index.ts +2 -3
  102. package/src/containers/NavTreeDocumentTitle/NavTreeDocumentTitle.tsx +2 -2
  103. package/src/containers/NavTreeDocumentTitle/index.ts +1 -3
  104. package/src/containers/index.ts +1 -1
  105. package/src/experimental/Tree.stories.tsx +27 -27
  106. package/src/hooks/useActions.ts +18 -22
  107. package/src/hooks/useNavTreeModel.ts +10 -4
  108. package/src/hooks/useNavTreeState.ts +2 -9
  109. package/src/meta.ts +2 -2
  110. package/src/operations/expose.ts +42 -0
  111. package/src/operations/index.ts +7 -0
  112. package/src/testing/app-graph-builder.ts +40 -36
  113. package/src/testing/generator.ts +22 -22
  114. package/src/translations.ts +8 -10
  115. package/src/types/capabilities.ts +4 -4
  116. package/src/types/events.ts +1 -1
  117. package/src/util.ts +2 -2
  118. package/dist/lib/browser/CommandsDialogContent-A27AKTHH.mjs +0 -111
  119. package/dist/lib/browser/CommandsDialogContent-A27AKTHH.mjs.map +0 -7
  120. package/dist/lib/browser/CommandsTrigger-HBZYQCGV.mjs +0 -33
  121. package/dist/lib/browser/CommandsTrigger-HBZYQCGV.mjs.map +0 -7
  122. package/dist/lib/browser/NavTreeContainer-B5K4FUJS.mjs +0 -12
  123. package/dist/lib/browser/NavTreeContainer-B5K4FUJS.mjs.map +0 -7
  124. package/dist/lib/browser/NavTreeDocumentTitle-GEE3URWH.mjs +0 -26
  125. package/dist/lib/browser/NavTreeDocumentTitle-GEE3URWH.mjs.map +0 -7
  126. package/dist/lib/browser/app-graph-builder-XGA4GPGL.mjs +0 -44
  127. package/dist/lib/browser/app-graph-builder-XGA4GPGL.mjs.map +0 -7
  128. package/dist/lib/browser/chunk-DQCYMXEU.mjs +0 -1426
  129. package/dist/lib/browser/chunk-DQCYMXEU.mjs.map +0 -7
  130. package/dist/lib/browser/chunk-H3OJ4WLF.mjs +0 -14
  131. package/dist/lib/browser/chunk-H3OJ4WLF.mjs.map +0 -7
  132. package/dist/lib/browser/chunk-X2HDG62A.mjs +0 -23
  133. package/dist/lib/browser/chunk-X2HDG62A.mjs.map +0 -7
  134. package/dist/lib/browser/chunk-YKTYPINZ.mjs +0 -19
  135. package/dist/lib/browser/chunk-YKTYPINZ.mjs.map +0 -7
  136. package/dist/lib/browser/keyboard-OJZC54PK.mjs +0 -54
  137. package/dist/lib/browser/keyboard-OJZC54PK.mjs.map +0 -7
  138. package/dist/lib/browser/operation-resolver-BNAMYOHF.mjs +0 -53
  139. package/dist/lib/browser/operation-resolver-BNAMYOHF.mjs.map +0 -7
  140. package/dist/lib/browser/react-surface-AYHOAJ4I.mjs +0 -59
  141. package/dist/lib/browser/react-surface-AYHOAJ4I.mjs.map +0 -7
  142. package/dist/lib/browser/state-AC3EETN7.mjs +0 -131
  143. package/dist/lib/browser/state-AC3EETN7.mjs.map +0 -7
  144. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +0 -1
  145. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +0 -3
  146. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +0 -1
  147. package/dist/types/src/capabilities/keyboard/index.d.ts +0 -3
  148. package/dist/types/src/capabilities/keyboard/index.d.ts.map +0 -1
  149. package/dist/types/src/capabilities/keyboard/keyboard.d.ts.map +0 -1
  150. package/dist/types/src/capabilities/operation-resolver/index.d.ts +0 -3
  151. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +0 -1
  152. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +0 -5
  153. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +0 -1
  154. package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
  155. package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
  156. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
  157. package/dist/types/src/capabilities/state/index.d.ts +0 -3
  158. package/dist/types/src/capabilities/state/index.d.ts.map +0 -1
  159. package/dist/types/src/capabilities/state/state.d.ts.map +0 -1
  160. package/dist/types/src/components/NavTreeContext.d.ts.map +0 -1
  161. package/src/capabilities/app-graph-builder/index.ts +0 -7
  162. package/src/capabilities/keyboard/index.ts +0 -7
  163. package/src/capabilities/operation-resolver/index.ts +0 -7
  164. package/src/capabilities/operation-resolver/operation-resolver.ts +0 -44
  165. package/src/capabilities/react-surface/index.ts +0 -7
  166. package/src/capabilities/state/index.ts +0 -7
  167. /package/dist/types/src/capabilities/{app-graph-builder/app-graph-builder.d.ts → app-graph-builder.d.ts} +0 -0
  168. /package/dist/types/src/capabilities/{keyboard/keyboard.d.ts → keyboard.d.ts} +0 -0
  169. /package/dist/types/src/capabilities/{react-surface/react-surface.d.ts → react-surface.d.ts} +0 -0
@@ -2,23 +2,16 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import React from 'react';
5
+ import React, { useCallback } from 'react';
6
6
 
7
7
  import { type Node } from '@dxos/app-graph';
8
8
  import { useActionRunner } from '@dxos/plugin-graph';
9
9
  import { IconButton, toLocalizedString, useDensityContext, useTranslation } from '@dxos/react-ui';
10
10
  import { Menu, type MenuItem } from '@dxos/react-ui-menu';
11
- import { hoverableControlItem, hoverableOpenControlItem } from '@dxos/ui-theme';
11
+ import { composable, composableProps, hoverableControlItem, hoverableOpenControlItem } from '@dxos/ui-theme';
12
12
 
13
- import { meta } from '../../meta';
14
- import { type ActionProperties } from '../../types';
15
-
16
- export type NavTreeItemActionMenuProps = ActionProperties & {
17
- parent: Node.Node;
18
- caller?: string;
19
- monolithic?: boolean;
20
- menuActions?: Node.Action[];
21
- };
13
+ import { meta } from '#meta';
14
+ import { type ActionProperties } from '#types';
22
15
 
23
16
  const fallbackIcon = 'ph--placeholder--regular';
24
17
 
@@ -26,46 +19,64 @@ const fineActionButtonProps = {
26
19
  size: 4 as const,
27
20
  density: 'fine' as const,
28
21
  };
22
+
29
23
  const coarseActionButtonProps = {
30
24
  size: 5 as const,
31
25
  density: 'coarse' as const,
32
26
  };
33
27
 
34
- export const NavTreeItemActionDropdownMenu = ({
35
- parent,
36
- label,
37
- icon,
38
- testId,
39
- menuActions,
40
- caller,
41
- }: NavTreeItemActionMenuProps) => {
42
- const { t } = useTranslation(meta.id);
43
- const density = useDensityContext();
44
- const runAction = useActionRunner();
45
-
46
- return (
47
- <Menu.Root caller={caller} onAction={runAction}>
48
- <Menu.Trigger asChild>
49
- <IconButton
50
- {...(density === 'coarse' ? coarseActionButtonProps : fineActionButtonProps)}
51
- classNames={['shrink-0 px-2 pointer-fine:px-1', hoverableControlItem, hoverableOpenControlItem]}
52
- variant='ghost'
53
- icon={icon ?? fallbackIcon}
54
- iconOnly
55
- label={toLocalizedString(label, t)}
56
- data-testid={testId}
57
- />
58
- </Menu.Trigger>
59
- <Menu.Content group={parent} items={menuActions as MenuItem[]} />
60
- </Menu.Root>
61
- );
28
+ export type NavTreeItemActionMenuProps = ActionProperties & {
29
+ parent: Node.Node;
30
+ path?: string[];
31
+ caller?: string;
32
+ monolithic?: boolean;
33
+ menuActions?: Node.Action[];
62
34
  };
63
35
 
36
+ export const NavTreeItemActionDropdownMenu = composable<HTMLButtonElement, NavTreeItemActionMenuProps>(
37
+ ({ parent, path, label, icon, testId, menuActions, caller, ...props }, forwardedRef) => {
38
+ const { t } = useTranslation(meta.id);
39
+ const density = useDensityContext();
40
+ const runAction = useActionRunner();
41
+ const handleAction = useCallback(
42
+ (action: Node.Action, params: Node.InvokeProps = {}) => runAction(action, { ...params, path }),
43
+ [runAction, path],
44
+ );
45
+
46
+ return (
47
+ <Menu.Root caller={caller} onAction={handleAction}>
48
+ <Menu.Trigger asChild>
49
+ <IconButton
50
+ {...(density === 'coarse' ? coarseActionButtonProps : fineActionButtonProps)}
51
+ {...composableProps(props)}
52
+ classNames={['shrink-0 px-2 pointer-fine:px-1', hoverableControlItem, hoverableOpenControlItem]}
53
+ variant='ghost'
54
+ icon={icon ?? fallbackIcon}
55
+ iconOnly
56
+ label={toLocalizedString(label, t)}
57
+ data-testid={testId}
58
+ ref={forwardedRef}
59
+ />
60
+ </Menu.Trigger>
61
+ <Menu.Content group={parent} items={menuActions as MenuItem[]} />
62
+ </Menu.Root>
63
+ );
64
+ },
65
+ );
66
+
67
+ NavTreeItemActionDropdownMenu.displayName = 'NavTreeItemActionDropdownMenu';
68
+
64
69
  export const NavTreeItemMonolithicAction = (
65
- props: Node.Action & { parent: Node.Node; onAction?: (action: Node.Action) => void; baseLabel: string },
70
+ props: Node.Action & {
71
+ parent: Node.Node;
72
+ path?: string[];
73
+ onAction?: (action: Node.Action) => void;
74
+ baseLabel: string;
75
+ },
66
76
  ) => {
67
77
  const {
68
78
  parent,
79
+ path,
69
80
  properties: { disabled, caller, testId, icon, variant = 'ghost', iconOnly = true } = { label: 'never' },
70
81
  baseLabel,
71
82
  } = props;
@@ -91,22 +102,28 @@ export const NavTreeItemMonolithicAction = (
91
102
  return;
92
103
  }
93
104
 
94
- void runAction(props, caller ? { parent, caller } : { parent });
105
+ void runAction(props, caller ? { parent, caller, path } : { parent, path });
95
106
  }}
96
107
  data-testid={testId}
97
108
  />
98
109
  );
99
110
  };
100
111
 
101
- export const NavTreeItemAction = ({ monolithic, menuActions, parent: node, ...props }: NavTreeItemActionMenuProps) => {
112
+ export const NavTreeItemAction = ({
113
+ monolithic,
114
+ menuActions,
115
+ menuType,
116
+ parent,
117
+ path,
118
+ ...props
119
+ }: NavTreeItemActionMenuProps) => {
102
120
  const { t } = useTranslation(meta.id);
103
121
 
104
122
  const monolithicAction = menuActions?.length === 1 && menuActions[0];
105
123
  const baseLabel = toLocalizedString(monolithicAction ? monolithicAction.properties!.label : props.label, t);
106
-
107
124
  return monolithic && menuActions?.length === 1 ? (
108
- <NavTreeItemMonolithicAction baseLabel={baseLabel} parent={node} {...menuActions[0]} />
125
+ <NavTreeItemMonolithicAction baseLabel={baseLabel} parent={parent} path={path} {...menuActions[0]} />
109
126
  ) : (
110
- <NavTreeItemActionDropdownMenu {...props} label={baseLabel} parent={node} menuActions={menuActions} />
127
+ <NavTreeItemActionDropdownMenu {...props} label={baseLabel} parent={parent} path={path} menuActions={menuActions} />
111
128
  );
112
129
  };
@@ -7,12 +7,12 @@ import React, { Fragment, memo, useMemo } from 'react';
7
7
  import { Node } from '@dxos/app-graph';
8
8
  import { Popover, Treegrid, toLocalizedString, useTranslation } from '@dxos/react-ui';
9
9
 
10
- import { useActions } from '../../hooks';
11
- import { meta } from '../../meta';
10
+ import { useActions } from '#hooks';
11
+ import { meta } from '#meta';
12
+
12
13
  import { NAV_TREE_ITEM } from '../NavTree';
13
14
  import { useNavTreeContext } from '../NavTreeContext';
14
15
  import { type NavTreeItemColumnsProps } from '../types';
15
-
16
16
  import { NavTreeItemAction } from './NavTreeItemAction';
17
17
 
18
18
  export const NavTreeItemColumns = memo(({ path, item, open }: NavTreeItemColumnsProps) => {
@@ -56,7 +56,7 @@ export const NavTreeItemColumns = memo(({ path, item, open }: NavTreeItemColumns
56
56
  [primaryAction, groupedActions],
57
57
  );
58
58
 
59
- const ActionRoot = popoverAnchorId === `dxos.org/ui/${NAV_TREE_ITEM}/${item.id}` ? Popover.Anchor : Fragment;
59
+ const ActionRoot = popoverAnchorId === `${NAV_TREE_ITEM}:${item.id}` ? Popover.Anchor : Fragment;
60
60
 
61
61
  return (
62
62
  <div role='none' className='contents dx-app-no-drag'>
@@ -67,6 +67,7 @@ export const NavTreeItemColumns = memo(({ path, item, open }: NavTreeItemColumns
67
67
  label={toLocalizedString(primaryAction.properties?.label, t)}
68
68
  icon={primaryAction.properties?.icon ?? 'ph--placeholder--regular'}
69
69
  parent={item}
70
+ path={path}
70
71
  monolithic={Node.isAction(primaryAction)}
71
72
  menuActions={primaryMenuActions}
72
73
  menuType={primaryAction.properties?.menuType}
@@ -81,9 +82,10 @@ export const NavTreeItemColumns = memo(({ path, item, open }: NavTreeItemColumns
81
82
  <Treegrid.Cell classNames='contents'>
82
83
  <NavTreeItemAction
83
84
  testId={`navtree.treeItem.actionsLevel${level}`}
84
- label={t('tree item actions label')}
85
+ label={t('tree-item-actions.label')}
85
86
  icon='ph--dots-three-vertical--regular'
86
87
  parent={item}
88
+ path={path}
87
89
  menuActions={actions}
88
90
  menuType='dropdown'
89
91
  caller={NAV_TREE_ITEM}
@@ -2,15 +2,15 @@
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
14
  import { useAtomValue } from '@effect-atom/atom-react';
15
15
  import React, {
16
16
  type MouseEvent,
@@ -29,6 +29,7 @@ import { DxAvatar } from '@dxos/lit-ui/react';
29
29
  import { useActionRunner } from '@dxos/plugin-graph';
30
30
  import {
31
31
  Icon,
32
+ IconButton,
32
33
  ListItem,
33
34
  ScrollArea,
34
35
  type ThemedClassName,
@@ -43,8 +44,9 @@ import { Tabs } from '@dxos/react-ui-tabs';
43
44
  import { mx } from '@dxos/ui-theme';
44
45
  import { arrayMove } from '@dxos/util';
45
46
 
46
- import { useNavTreeState } from '../../hooks';
47
- import { meta } from '../../meta';
47
+ import { useNavTreeState } from '#hooks';
48
+ import { meta } from '#meta';
49
+
48
50
  import { l0ItemType } from '../../util';
49
51
  import { useNavTreeContext } from '../NavTreeContext';
50
52
  import { UserAccountAvatar } from '../UserAccountAvatar';
@@ -85,12 +87,10 @@ const useL0ItemClick = ({ item, parent, path }: L0ItemProps, type: string) => {
85
87
  switch (type) {
86
88
  case 'action': {
87
89
  const { properties: { caller } = {} } = item;
88
- return void runAction(item as Node.Action, caller ? { parent, caller } : { parent });
90
+ return void runAction(item as Node.Action, caller ? { parent, path, caller } : { parent, path });
89
91
  }
90
-
91
92
  case 'tab':
92
93
  return onTabChange?.(item);
93
-
94
94
  case 'link':
95
95
  return onSelect?.({ item, path, current: !getItem(path).current, option: event.altKey });
96
96
  }
@@ -103,36 +103,34 @@ const l0Breakpoints: Record<string, string> = {
103
103
  lg: 'hidden lg:grid',
104
104
  };
105
105
 
106
- const l0ItemRoot =
107
- 'group/l0item flex w-full justify-center items-center relative data[type!="collection"]:cursor-pointer dx-app-no-drag dx-focus-ring-group';
108
-
109
- const l0ItemContent = 'flex justify-center items-center dx-focus-ring-group-indicator transition-colors rounded-sm';
110
-
111
106
  const L0ItemRoot = memo(
112
- forwardRef<HTMLElement, PropsWithChildren<L0ItemRootProps>>(
107
+ forwardRef<HTMLButtonElement, PropsWithChildren<L0ItemRootProps>>(
113
108
  ({ item, parent, path, onMouseEnter, children }, forwardedRef) => {
109
+ const { t } = useTranslation(meta.id);
114
110
  const { model } = useNavTreeContext();
115
111
  const itemPath = useMemo(() => [...path, item.id], [item.id, path]);
116
112
  const { id, testId } = useAtomValue(model.itemProps(itemPath));
117
- const type = l0ItemType(item);
118
-
119
- const { t } = useTranslation(meta.id);
120
113
  const localizedString = toLocalizedString(item.properties.label, t);
121
114
 
115
+ const type = l0ItemType(item);
122
116
  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
117
 
128
118
  return (
129
119
  <Tooltip.Trigger asChild delayDuration={0} side='right' content={localizedString}>
130
120
  <Tabs.TabPrimitive
131
- {...(rootProps as any)}
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}
132
127
  data-type={type}
133
- className={mx(l0ItemRoot, l0Breakpoints[item.properties.l0Breakpoint])}
134
- ref={forwardedRef}
128
+ data-testid={testId}
129
+ data-object-id={id}
130
+ value={item.id}
131
+ onClick={handleClick}
135
132
  onMouseEnter={onMouseEnter}
133
+ ref={forwardedRef}
136
134
  >
137
135
  {children}
138
136
  </Tabs.TabPrimitive>
@@ -146,7 +144,7 @@ export const L0ItemActiveTabIndicator = ({ classNames }: ThemedClassName<{}>) =>
146
144
  <div
147
145
  role='none'
148
146
  className={mx(
149
- 'hidden group-aria-selected/l0item:block absolute start-0 inset-y-2 w-1 bg-accent-surface rounded-ie',
147
+ 'hidden group-aria-selected/l0item:block absolute start-0 h-6 w-1.5 bg-accent-surface rounded-sm',
150
148
  classNames,
151
149
  )}
152
150
  />
@@ -155,13 +153,12 @@ export const L0ItemActiveTabIndicator = ({ classNames }: ThemedClassName<{}>) =>
155
153
  // TODO(burdon): Factor out pinned (non-draggable) items.
156
154
  const L0Item = memo(({ item, parent, path, pinned, onRearrange, onItemHover }: L0ItemProps) => {
157
155
  const { t } = useTranslation(meta.id);
158
- const itemElement = useRef<HTMLElement | null>(null);
156
+ const itemElement = useRef<HTMLButtonElement | null>(null);
159
157
  const [closestEdge, setEdge] = useState<Edge | null>(null);
160
158
  const localizedString = toLocalizedString(item.properties.label, t);
161
159
  const hue = item.properties.hue ?? null;
162
160
 
163
161
  useLayoutEffect(() => {
164
- // NOTE(thure): This is copied from StackItem, perhaps this should be DRYed out.
165
162
  if (!itemElement.current || !onRearrange) {
166
163
  return;
167
164
  }
@@ -225,7 +222,7 @@ const L0Item = memo(({ item, parent, path, pinned, onRearrange, onItemHover }: L
225
222
  data-frame={true}
226
223
  {...(hue && { style: { background: `var(--color-${hue}-surface)` } })}
227
224
  className={mx(
228
- l0ItemContent,
225
+ 'flex justify-center items-center dx-focus-ring-group-indicator transition-colors rounded-sm',
229
226
  pinned
230
227
  ? 'p-2 group-hover/l0item:bg-active-surface'
231
228
  : 'w-(--dx-l0-avatar-size) h-(--dx-l0-avatar-size) bg-active-surface',
@@ -244,13 +241,15 @@ const L0Item = memo(({ item, parent, path, pinned, onRearrange, onItemHover }: L
244
241
 
245
242
  const ItemAvatar = ({ item }: Pick<L0ItemProps, 'item'>) => {
246
243
  const { t } = useTranslation(meta.id);
247
- const type = l0ItemType(item);
244
+
245
+ // Actions.
248
246
  if (item.properties.icon) {
249
247
  const hue = item.properties.hue ?? null;
250
248
  const hueFgStyle = hue && { style: { color: `var(--color-${hue}-surface-text)` } };
251
249
  return <Icon icon={item.properties.icon} size={6} {...hueFgStyle} />;
252
250
  }
253
251
 
252
+ const type = l0ItemType(item);
254
253
  if (type === 'tab' && item.properties.disposition !== 'pin-end') {
255
254
  const hue = item.properties.hue ?? null;
256
255
  const localizedString = toLocalizedString(item.properties.label, t);
@@ -317,62 +316,38 @@ export const L0Menu = ({
317
316
 
318
317
  return (
319
318
  <Tabs.Tablist
319
+ data-tauri-drag-region
320
320
  classNames={[
321
321
  'group/l0 absolute z-[1] inset-y-0 start-0 rounded-is',
322
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)]',
323
+ 'w-(--dx-l0-size) bg-toolbar-surface dx-app-drag pb-[env(safe-area-inset-bottom)]',
324
+ '[body[data-platform="macos"]_&]:pt-[30px]',
325
+ '[body[data-platform="ios"]_&]:pt-[max(env(safe-area-inset-top),0.25rem)]',
324
326
  ]}
325
327
  >
326
328
  {/* TODO(wittjosiah): Use L0Item trigger. */}
327
329
  <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
- >
337
- <Tooltip.Trigger content={t('app menu label')} side='right' asChild>
338
- <Tabs.TabPrimitive value='options' asChild role='button'>
339
- <div
340
- role='none'
341
- className={mx(
342
- l0ItemContent,
343
- 'h-(--dx-rail-action) w-(--dx-rail-action) group-hover/l0item:bg-hover-surface',
344
- )}
345
- >
346
- <Icon icon='ph--list--regular' size={5} />
347
- </div>
348
- </Tabs.TabPrimitive>
349
- </Tooltip.Trigger>
330
+ <Menu.Trigger asChild data-testid='spacePlugin.addSpace'>
331
+ <div role='none' className='grid place-items-center'>
332
+ <IconButton variant='ghost' icon='ph--list--regular' iconOnly label={t('app-menu.label')} />
333
+ </div>
350
334
  </Menu.Trigger>
351
335
  <Menu.Content group={parent} items={menuActions} />
352
336
  </Menu.Root>
353
337
 
354
338
  {/* Space list. */}
355
- <ScrollArea.Root thin orientation='vertical'>
356
- <ScrollArea.Viewport>
357
- <div
358
- role='none'
359
- className={mx([
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)]',
363
- ])}
364
- >
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
- ))}
375
- </div>
339
+ <ScrollArea.Root centered thin orientation='vertical'>
340
+ <ScrollArea.Viewport classNames='flex flex-col gap-2 py-1'>
341
+ {topLevelItems.map((item) => (
342
+ <L0Item
343
+ key={item.id}
344
+ item={item}
345
+ parent={parent}
346
+ path={path}
347
+ onItemHover={onItemHover}
348
+ {...(hasRearrangeableItems && { onRearrange: handleRearrange })}
349
+ />
350
+ ))}
376
351
  </ScrollArea.Viewport>
377
352
  </ScrollArea.Root>
378
353