@dxos/plugin-navtree 0.8.4-main.84f28bd → 0.8.4-main.a4bbb77

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 (129) hide show
  1. package/dist/lib/browser/{app-graph-builder-5J4LRWDX.mjs → app-graph-builder-BCXDEDN7.mjs} +9 -9
  2. package/dist/lib/browser/app-graph-builder-BCXDEDN7.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-TZA65AKW.mjs → chunk-6AZKY5WZ.mjs} +279 -237
  4. package/dist/lib/browser/chunk-6AZKY5WZ.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-WCARAZ7J.mjs → chunk-LPAREX6J.mjs} +4 -4
  6. package/dist/lib/browser/chunk-LPAREX6J.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-ZENLR72O.mjs +14 -0
  8. package/dist/lib/browser/chunk-ZENLR72O.mjs.map +7 -0
  9. package/dist/lib/browser/index.mjs +8 -11
  10. package/dist/lib/browser/index.mjs.map +3 -3
  11. package/dist/lib/browser/{intent-resolver-3XYN2CBU.mjs → intent-resolver-G6COWRWW.mjs} +6 -6
  12. package/dist/lib/browser/{intent-resolver-3XYN2CBU.mjs.map → intent-resolver-G6COWRWW.mjs.map} +3 -3
  13. package/dist/lib/browser/{keyboard-QRS6WOQH.mjs → keyboard-AHSAWKXA.mjs} +4 -4
  14. package/dist/lib/{node-esm/keyboard-MOZWHFUM.mjs.map → browser/keyboard-AHSAWKXA.mjs.map} +2 -2
  15. package/dist/lib/browser/meta.json +1 -1
  16. package/dist/lib/browser/{react-surface-N2HPMYCU.mjs → react-surface-FOCB4Y5R.mjs} +10 -10
  17. package/dist/lib/browser/react-surface-FOCB4Y5R.mjs.map +7 -0
  18. package/dist/lib/browser/{state-54DY3DOY.mjs → state-2Q623V7U.mjs} +7 -7
  19. package/dist/lib/browser/state-2Q623V7U.mjs.map +7 -0
  20. package/dist/types/src/NavTreePlugin.d.ts +1 -1
  21. package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
  22. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
  23. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  24. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  25. package/dist/types/src/capabilities/index.d.ts +6 -6
  26. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  27. package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
  28. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  29. package/dist/types/src/capabilities/keyboard.d.ts +1 -1
  30. package/dist/types/src/capabilities/keyboard.d.ts.map +1 -1
  31. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  32. package/dist/types/src/capabilities/state.d.ts +2 -2
  33. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  34. package/dist/types/src/components/CommandsDialog/CommandsTrigger.d.ts.map +1 -1
  35. package/dist/types/src/components/NavTree/NavTree.d.ts +2 -2
  36. package/dist/types/src/components/NavTree/NavTree.d.ts.map +1 -1
  37. package/dist/types/src/components/NavTree/NavTree.stories.d.ts +26 -3
  38. package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +1 -1
  39. package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
  40. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +32 -4
  41. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +1 -1
  42. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts +1 -1
  43. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +1 -1
  44. package/dist/types/src/components/Sidebar/L0Menu.d.ts +2 -0
  45. package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -1
  46. package/dist/types/src/components/Sidebar/L1Panel.d.ts +5 -6
  47. package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -1
  48. package/dist/types/src/components/Sidebar/L1Tabs.d.ts +12 -0
  49. package/dist/types/src/components/Sidebar/L1Tabs.d.ts.map +1 -0
  50. package/dist/types/src/components/Sidebar/index.d.ts +1 -0
  51. package/dist/types/src/components/Sidebar/index.d.ts.map +1 -1
  52. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.d.ts.map +1 -1
  53. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts +8 -5
  54. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts.map +1 -1
  55. package/dist/types/src/components/index.d.ts +1 -1
  56. package/dist/types/src/components/index.d.ts.map +1 -1
  57. package/dist/types/src/components/types.d.ts +2 -2
  58. package/dist/types/src/components/types.d.ts.map +1 -1
  59. package/dist/types/src/events.d.ts.map +1 -1
  60. package/dist/types/src/experimental/Tree.d.ts +4 -5
  61. package/dist/types/src/experimental/Tree.d.ts.map +1 -1
  62. package/dist/types/src/experimental/Tree.stories.d.ts +10 -4
  63. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
  64. package/dist/types/src/meta.d.ts +2 -3
  65. package/dist/types/src/meta.d.ts.map +1 -1
  66. package/dist/types/src/testing/app-graph-builder.d.ts.map +1 -1
  67. package/dist/types/src/translations.d.ts +1 -0
  68. package/dist/types/src/translations.d.ts.map +1 -1
  69. package/dist/types/src/util.d.ts +1 -2
  70. package/dist/types/src/util.d.ts.map +1 -1
  71. package/dist/types/tsconfig.tsbuildinfo +1 -1
  72. package/package.json +49 -49
  73. package/src/NavTreePlugin.tsx +75 -76
  74. package/src/capabilities/app-graph-builder.ts +5 -5
  75. package/src/capabilities/capabilities.ts +2 -2
  76. package/src/capabilities/intent-resolver.ts +1 -1
  77. package/src/capabilities/keyboard.ts +2 -2
  78. package/src/capabilities/react-surface.tsx +5 -5
  79. package/src/capabilities/state.ts +4 -3
  80. package/src/components/CommandsDialog/CommandsDialog.tsx +5 -5
  81. package/src/components/CommandsDialog/CommandsTrigger.tsx +5 -7
  82. package/src/components/NavTree/NavTree.stories.tsx +21 -18
  83. package/src/components/NavTree/NavTree.tsx +7 -3
  84. package/src/components/NavTreeContainer.tsx +43 -18
  85. package/src/components/NavTreeDocumentTitle.tsx +2 -2
  86. package/src/components/NavTreeItem/NavTreeItemAction.stories.tsx +4 -6
  87. package/src/components/NavTreeItem/NavTreeItemAction.tsx +9 -9
  88. package/src/components/NavTreeItem/NavTreeItemColumns.tsx +9 -9
  89. package/src/components/Sidebar/L0Menu.tsx +51 -50
  90. package/src/components/Sidebar/L1Panel.tsx +71 -93
  91. package/src/components/Sidebar/L1Tabs.tsx +58 -0
  92. package/src/components/Sidebar/index.ts +1 -0
  93. package/src/components/UserAccountAvatar/UserAccountAvatar.stories.tsx +9 -8
  94. package/src/components/UserAccountAvatar/UserAccountAvatar.tsx +20 -12
  95. package/src/components/index.ts +1 -1
  96. package/src/components/types.ts +3 -2
  97. package/src/events.ts +2 -2
  98. package/src/experimental/Tree.stories.tsx +37 -36
  99. package/src/experimental/Tree.tsx +16 -34
  100. package/src/meta.ts +5 -7
  101. package/src/testing/app-graph-builder.ts +1 -1
  102. package/src/translations.ts +1 -0
  103. package/src/util.ts +2 -20
  104. package/dist/lib/browser/app-graph-builder-5J4LRWDX.mjs.map +0 -7
  105. package/dist/lib/browser/chunk-ERDGQTH5.mjs +0 -16
  106. package/dist/lib/browser/chunk-ERDGQTH5.mjs.map +0 -7
  107. package/dist/lib/browser/chunk-TZA65AKW.mjs.map +0 -7
  108. package/dist/lib/browser/chunk-WCARAZ7J.mjs.map +0 -7
  109. package/dist/lib/browser/keyboard-QRS6WOQH.mjs.map +0 -7
  110. package/dist/lib/browser/react-surface-N2HPMYCU.mjs.map +0 -7
  111. package/dist/lib/browser/state-54DY3DOY.mjs.map +0 -7
  112. package/dist/lib/node-esm/app-graph-builder-GY7GCTGU.mjs +0 -46
  113. package/dist/lib/node-esm/app-graph-builder-GY7GCTGU.mjs.map +0 -7
  114. package/dist/lib/node-esm/chunk-CY7QWR4R.mjs +0 -1429
  115. package/dist/lib/node-esm/chunk-CY7QWR4R.mjs.map +0 -7
  116. package/dist/lib/node-esm/chunk-P2JGW3WR.mjs +0 -18
  117. package/dist/lib/node-esm/chunk-P2JGW3WR.mjs.map +0 -7
  118. package/dist/lib/node-esm/chunk-V3QXFDDP.mjs +0 -16
  119. package/dist/lib/node-esm/chunk-V3QXFDDP.mjs.map +0 -7
  120. package/dist/lib/node-esm/index.mjs +0 -150
  121. package/dist/lib/node-esm/index.mjs.map +0 -7
  122. package/dist/lib/node-esm/intent-resolver-R7UNPSZY.mjs +0 -48
  123. package/dist/lib/node-esm/intent-resolver-R7UNPSZY.mjs.map +0 -7
  124. package/dist/lib/node-esm/keyboard-MOZWHFUM.mjs +0 -52
  125. package/dist/lib/node-esm/meta.json +0 -1
  126. package/dist/lib/node-esm/react-surface-EW5FDMW4.mjs +0 -52
  127. package/dist/lib/node-esm/react-surface-EW5FDMW4.mjs.map +0 -7
  128. package/dist/lib/node-esm/state-Z3OTRC2I.mjs +0 -118
  129. package/dist/lib/node-esm/state-Z3OTRC2I.mjs.map +0 -7
@@ -3,34 +3,35 @@
3
3
  //
4
4
 
5
5
  import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
6
- import { extractInstruction, type Instruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
6
+ import { type Instruction, extractInstruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
7
7
  import { untracked } from '@preact/signals-core';
8
8
  import React, { memo, useCallback, useEffect, useMemo } from 'react';
9
9
 
10
10
  import {
11
- createIntent,
12
11
  LayoutAction,
13
12
  Surface,
13
+ createIntent,
14
14
  useAppGraph,
15
15
  useCapability,
16
16
  useIntentDispatcher,
17
17
  useLayout,
18
18
  } from '@dxos/app-framework';
19
- import { isAction, isActionLike, ROOT_ID, type Node, type ReadableGraph } from '@dxos/app-graph';
19
+ import { type Node, ROOT_ID, type ReadableGraph, isAction, isActionLike } from '@dxos/app-graph';
20
20
  import { PLANK_COMPANION_TYPE } from '@dxos/plugin-deck/types';
21
- import { useConnections } from '@dxos/plugin-graph';
21
+ import { useConnections, useActions as useGraphActions } from '@dxos/plugin-graph';
22
22
  import { useMediaQuery, useSidebars } from '@dxos/react-ui';
23
- import { isTreeData, type TreeItemDataProps, type TreeData } from '@dxos/react-ui-list';
23
+ import { type TreeData, type TreeItemDataProps, isTreeData } from '@dxos/react-ui-list';
24
24
  import { mx } from '@dxos/react-ui-theme';
25
25
  import { arrayMove, byPosition } from '@dxos/util';
26
26
 
27
+ import { NavTreeCapabilities } from '../capabilities';
28
+ import { meta } from '../meta';
29
+ import { type FlattenedActions, type NavTreeItemGraphNode } from '../types';
30
+ import { getChildren, getParent, resolveMigrationOperation } from '../util';
31
+
27
32
  import { NAV_TREE_ITEM, NavTree } from './NavTree';
28
33
  import { NavTreeContext } from './NavTreeContext';
29
34
  import { type NavTreeContextValue } from './types';
30
- import { NavTreeCapabilities } from '../capabilities';
31
- import { NAVTREE_PLUGIN } from '../meta';
32
- import { type NavTreeItemGraphNode } from '../types';
33
- import { getChildren, getParent, getActions as naturalGetActions, resolveMigrationOperation } from '../util';
34
35
 
35
36
  // TODO(thure): Is NavTree truly authoritative in this regard?
36
37
  export const NODE_TYPE = 'dxos/app-graph/node';
@@ -40,7 +41,9 @@ const renderItemEnd = ({ node, open }: { node: Node; open: boolean }) => (
40
41
  );
41
42
 
42
43
  const getChildrenFilter = (node: Node): node is Node =>
43
- untracked(() => !isActionLike(node) && node.type !== PLANK_COMPANION_TYPE);
44
+ untracked(
45
+ () => !isActionLike(node) && node.type !== PLANK_COMPANION_TYPE && node.properties.disposition !== 'hidden',
46
+ );
44
47
 
45
48
  const filterItems = (node: Node, disposition?: string) => {
46
49
  if (!disposition && (node.properties.disposition === 'hidden' || node.properties.disposition === 'alternate-tree')) {
@@ -59,10 +62,34 @@ const getItems = (graph: ReadableGraph, node?: Node, disposition?: string) => {
59
62
 
60
63
  const useItems = (node?: Node, options?: { disposition?: string; sort?: boolean }) => {
61
64
  const { graph } = useAppGraph();
62
- const connections = useConnections(graph, node?.id ?? ROOT_ID).filter((node) =>
63
- filterItems(node, options?.disposition),
65
+ const connections = useConnections(graph, node?.id ?? ROOT_ID);
66
+ const filtered = connections.filter((node) => filterItems(node, options?.disposition));
67
+ return options?.sort ? filtered.toSorted((a, b) => byPosition(a.properties, b.properties)) : filtered;
68
+ };
69
+
70
+ const useActions = (node: Node): FlattenedActions => {
71
+ const { graph } = useAppGraph();
72
+ const actions = useGraphActions(graph, node.id);
73
+
74
+ return useMemo(
75
+ () =>
76
+ actions.reduce(
77
+ (acc: FlattenedActions, arg) => {
78
+ if (arg.properties.disposition === 'item') {
79
+ return acc;
80
+ }
81
+
82
+ acc.actions.push(arg);
83
+ if (!isAction(arg)) {
84
+ const actionGroup = graph.getActions(arg.id);
85
+ acc.groupedActions[arg.id] = actionGroup;
86
+ }
87
+ return acc;
88
+ },
89
+ { actions: [], groupedActions: {} },
90
+ ),
91
+ [actions],
64
92
  );
65
- return options?.sort ? connections.toSorted((a, b) => byPosition(a.properties, b.properties)) : connections;
66
93
  };
67
94
 
68
95
  export type NavTreeContainerProps = {
@@ -76,9 +103,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
76
103
  const { graph } = useAppGraph();
77
104
  const { isOpen, isCurrent, isAlternateTree, setItem } = useCapability(NavTreeCapabilities.State);
78
105
  const layout = useLayout();
79
- const { navigationSidebarState } = useSidebars(NAVTREE_PLUGIN);
80
-
81
- const getActions = useCallback((node: Node) => naturalGetActions(graph, node), [graph]);
106
+ const { navigationSidebarState } = useSidebars(meta.id);
82
107
 
83
108
  const getProps = useCallback(
84
109
  (node: Node, path: string[]): TreeItemDataProps => {
@@ -270,7 +295,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
270
295
  () => ({
271
296
  useItems,
272
297
  tab,
273
- getActions,
298
+ useActions,
274
299
  loadDescendents,
275
300
  renderItemEnd,
276
301
  popoverAnchorId,
@@ -288,7 +313,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
288
313
  }),
289
314
  [
290
315
  tab,
291
- getActions,
316
+ useActions,
292
317
  loadDescendents,
293
318
  renderItemEnd,
294
319
  popoverAnchorId,
@@ -6,10 +6,10 @@ import { useEffect } from 'react';
6
6
  import { type Node } from '@dxos/app-graph';
7
7
  import { toLocalizedString, useTranslation } from '@dxos/react-ui';
8
8
 
9
- import { NAVTREE_PLUGIN } from '../meta';
9
+ import { meta } from '../meta';
10
10
 
11
11
  export const NavTreeDocumentTitle = ({ node }: { node?: Node }) => {
12
- const { t } = useTranslation(NAVTREE_PLUGIN);
12
+ const { t } = useTranslation(meta.id);
13
13
  useEffect(() => {
14
14
  document.title = node ? toLocalizedString(node.properties.label, t) : t('current app name', { ns: 'appkit' });
15
15
  }, [node?.properties?.label]);
@@ -2,13 +2,11 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
8
6
 
9
7
  import { type NodeArg } from '@dxos/app-graph';
10
8
  import { faker } from '@dxos/random';
11
- import { withLayout, withTheme } from '@dxos/storybook-utils';
9
+ import { withTheme } from '@dxos/react-ui/testing';
12
10
 
13
11
  import { NavTreeItemAction, type NavTreeItemActionMenuProps } from './NavTreeItemAction';
14
12
 
@@ -39,20 +37,20 @@ const menuActions = faker.helpers.multiple(
39
37
  { count: 20 },
40
38
  );
41
39
 
42
- const meta: Meta<typeof NavTreeItemAction> = {
40
+ const meta = {
43
41
  title: 'plugins/plugin-navtree/NavTreeItemAction',
44
42
  component: NavTreeItemAction,
45
- decorators: [withTheme, withLayout()],
46
43
  args: {
47
44
  icon: 'ph--list--regular',
48
45
  parent,
49
46
  menuActions,
50
47
  label: 'Select action',
51
48
  } satisfies Partial<NavTreeItemActionMenuProps>,
49
+ decorators: [withTheme],
52
50
  parameters: {
53
51
  layout: 'centered',
54
52
  },
55
- };
53
+ } satisfies Meta<typeof NavTreeItemAction>;
56
54
 
57
55
  export default meta;
58
56
 
@@ -5,11 +5,11 @@
5
5
  import React from 'react';
6
6
 
7
7
  import { type Action, type Node } from '@dxos/app-graph';
8
- import { useTranslation, toLocalizedString, IconButton, useDensityContext } from '@dxos/react-ui';
9
- import { DropdownMenu, MenuProvider, type MenuItem } from '@dxos/react-ui-menu';
10
- import { hoverableControlItem, hoverableOpenControlItem, mx } from '@dxos/react-ui-theme';
8
+ import { IconButton, toLocalizedString, useDensityContext, useTranslation } from '@dxos/react-ui';
9
+ import { DropdownMenu, type MenuItem, MenuProvider } from '@dxos/react-ui-menu';
10
+ import { hoverableControlItem, hoverableOpenControlItem } from '@dxos/react-ui-theme';
11
11
 
12
- import { NAVTREE_PLUGIN } from '../../meta';
12
+ import { meta } from '../../meta';
13
13
  import { type ActionProperties } from '../../types';
14
14
 
15
15
  export type NavTreeItemActionMenuProps = ActionProperties & {
@@ -38,7 +38,7 @@ export const NavTreeItemActionDropdownMenu = ({
38
38
  menuActions,
39
39
  caller,
40
40
  }: NavTreeItemActionMenuProps) => {
41
- const { t } = useTranslation(NAVTREE_PLUGIN);
41
+ const { t } = useTranslation(meta.id);
42
42
  const density = useDensityContext();
43
43
  return (
44
44
  <MenuProvider>
@@ -46,7 +46,7 @@ export const NavTreeItemActionDropdownMenu = ({
46
46
  <DropdownMenu.Trigger asChild>
47
47
  <IconButton
48
48
  {...(density === 'coarse' ? coarseActionButtonProps : fineActionButtonProps)}
49
- classNames={mx('shrink-0 pli-2 pointer-fine:pli-1', hoverableControlItem, hoverableOpenControlItem)}
49
+ classNames={['shrink-0 pli-2 pointer-fine:pli-1', hoverableControlItem, hoverableOpenControlItem]}
50
50
  variant='ghost'
51
51
  icon={icon ?? fallbackIcon}
52
52
  iconOnly
@@ -70,12 +70,12 @@ export const NavTreeItemMonolithicAction = ({
70
70
  <IconButton
71
71
  {...(density === 'coarse' ? coarseActionButtonProps : fineActionButtonProps)}
72
72
  variant={variant}
73
- classNames={mx(
73
+ classNames={[
74
74
  'shrink-0',
75
75
  hoverableControlItem,
76
76
  hoverableOpenControlItem,
77
77
  iconOnly ? 'pli-2 pointer-fine:pli-1' : 'p-2 pointer-fine:p-2 mie-1',
78
- )}
78
+ ]}
79
79
  icon={icon ?? fallbackIcon}
80
80
  iconOnly={iconOnly}
81
81
  label={baseLabel}
@@ -93,7 +93,7 @@ export const NavTreeItemMonolithicAction = ({
93
93
  };
94
94
 
95
95
  export const NavTreeItemAction = ({ monolithic, menuActions, parent: node, ...props }: NavTreeItemActionMenuProps) => {
96
- const { t } = useTranslation(NAVTREE_PLUGIN);
96
+ const { t } = useTranslation(meta.id);
97
97
 
98
98
  const monolithicAction = menuActions?.length === 1 && menuActions[0];
99
99
  const baseLabel = toLocalizedString(monolithicAction ? monolithicAction.properties!.label : props.label, t);
@@ -5,23 +5,23 @@
5
5
  import React, { Fragment, memo } from 'react';
6
6
 
7
7
  import { isAction } from '@dxos/app-graph';
8
- import { DensityProvider, Popover, toLocalizedString, Treegrid, useTranslation } from '@dxos/react-ui';
8
+ import { DensityProvider, Popover, Treegrid, toLocalizedString, useTranslation } from '@dxos/react-ui';
9
9
 
10
- import { NavTreeItemAction } from './NavTreeItemAction';
11
10
  import { useLoadDescendents } from '../../hooks';
12
- import { NAVTREE_PLUGIN } from '../../meta';
11
+ import { meta } from '../../meta';
13
12
  import { NAV_TREE_ITEM } from '../NavTree';
14
13
  import { useNavTreeContext } from '../NavTreeContext';
15
- import type { NavTreeItemColumnsProps } from '../types';
14
+ import { type NavTreeItemColumnsProps } from '../types';
15
+
16
+ import { NavTreeItemAction } from './NavTreeItemAction';
16
17
 
17
18
  export const NavTreeItemColumns = memo(({ path, item, open, density = 'fine' }: NavTreeItemColumnsProps) => {
18
- const { t } = useTranslation(NAVTREE_PLUGIN);
19
- const { getActions, renderItemEnd: ItemEnd, popoverAnchorId } = useNavTreeContext();
19
+ const { t } = useTranslation(meta.id);
20
+ const { useActions, renderItemEnd: ItemEnd, popoverAnchorId } = useNavTreeContext();
20
21
 
21
22
  const level = path.length - 2;
22
-
23
- const { actions: _actions, groupedActions } = getActions(item);
24
- const [primaryAction, ...secondaryActions] = _actions.toSorted((a, b) =>
23
+ const { actions: _actions, groupedActions } = useActions(item);
24
+ const [primaryAction, ...secondaryActions] = _actions.toSorted((a, _b) =>
25
25
  a.properties?.disposition === 'list-item-primary' ? -1 : 1,
26
26
  );
27
27
 
@@ -12,9 +12,9 @@ import {
12
12
  extractClosestEdge,
13
13
  } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
14
14
  import React, {
15
- forwardRef,
16
15
  type MouseEvent,
17
16
  type PropsWithChildren,
17
+ forwardRef,
18
18
  useCallback,
19
19
  useLayoutEffect,
20
20
  useMemo,
@@ -24,15 +24,25 @@ import React, {
24
24
 
25
25
  import { type Node } from '@dxos/app-graph';
26
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';
27
+ import { DxAvatar } from '@dxos/lit-ui/react';
28
+ import {
29
+ Icon,
30
+ ListItem,
31
+ ScrollArea,
32
+ type ThemedClassName,
33
+ Tooltip,
34
+ toLocalizedString,
35
+ useMediaQuery,
36
+ useTranslation,
37
+ } from '@dxos/react-ui';
38
+ import { DropdownMenu, type MenuItem, MenuProvider } from '@dxos/react-ui-menu';
29
39
  import type { StackItemRearrangeHandler } from '@dxos/react-ui-stack';
30
40
  import { Tabs } from '@dxos/react-ui-tabs';
31
41
  import { mx } from '@dxos/react-ui-theme';
32
- import { arrayMove, getFirstTwoRenderableChars } from '@dxos/util';
42
+ import { arrayMove } from '@dxos/util';
33
43
 
34
44
  import { useLoadDescendents } from '../../hooks';
35
- import { NAVTREE_PLUGIN } from '../../meta';
45
+ import { meta } from '../../meta';
36
46
  import { l0ItemType } from '../../util';
37
47
  import { useNavTreeContext } from '../NavTreeContext';
38
48
  import { UserAccountAvatar } from '../UserAccountAvatar';
@@ -103,7 +113,7 @@ const L0ItemRoot = forwardRef<HTMLElement, PropsWithChildren<L0ItemRootProps>>(
103
113
  const type = l0ItemType(item);
104
114
  const itemPath = useMemo(() => [...path, item.id], [item.id, path]);
105
115
 
106
- const { t } = useTranslation(NAVTREE_PLUGIN);
116
+ const { t } = useTranslation(meta.id);
107
117
  const localizedString = toLocalizedString(item.properties.label, t);
108
118
 
109
119
  const handleClick = useL0ItemClick({ item, parent, path: itemPath }, type);
@@ -112,46 +122,36 @@ const L0ItemRoot = forwardRef<HTMLElement, PropsWithChildren<L0ItemRootProps>>(
112
122
  ? { value: item.id, tabIndex: 0, onClick: handleClick, 'data-testid': testId, 'data-itemid': id }
113
123
  : type !== 'collection'
114
124
  ? { onClick: handleClick, 'data-testid': testId, 'data-itemid': id }
115
- : { onClick: handleClick };
116
-
117
- const Root = type === 'collection' ? 'h2' : type === 'tab' ? Tabs.TabPrimitive : 'button';
125
+ : { onClick: handleClick, role: 'button' };
118
126
 
119
127
  return (
120
128
  <Tooltip.Trigger asChild delayDuration={0} side='right' content={localizedString}>
121
- <Root
129
+ <Tabs.TabPrimitive
122
130
  {...(rootProps as any)}
123
131
  data-type={type}
124
132
  className={mx(l0ItemRoot, l0Breakpoints[item.properties.l0Breakpoint])}
125
133
  ref={forwardedRef}
126
134
  >
127
135
  {children}
128
- </Root>
136
+ </Tabs.TabPrimitive>
129
137
  </Tooltip.Trigger>
130
138
  );
131
139
  },
132
140
  );
133
141
 
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
- };
142
+ export const L0ItemActiveTabIndicator = ({ classNames }: ThemedClassName<{}>) => (
143
+ <div
144
+ role='none'
145
+ className={mx(
146
+ 'hidden group-aria-selected/l0item:block absolute inline-start-0 inset-block-2 is-1 bg-accentSurface rounded-ie',
147
+ classNames,
148
+ )}
149
+ />
150
+ );
151
151
 
152
152
  // TODO(burdon): Factor out pinned (non-draggable) items.
153
153
  const L0Item = ({ item, parent, path, pinned, onRearrange }: L0ItemProps) => {
154
- const { t } = useTranslation(NAVTREE_PLUGIN);
154
+ const { t } = useTranslation(meta.id);
155
155
  const itemElement = useRef<HTMLElement | null>(null);
156
156
  const [closestEdge, setEdge] = useState<Edge | null>(null);
157
157
  const localizedString = toLocalizedString(item.properties.label, t);
@@ -228,10 +228,7 @@ const L0Item = ({ item, parent, path, pinned, onRearrange }: L0ItemProps) => {
228
228
  >
229
229
  <ItemAvatar item={item} />
230
230
  </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
- />
231
+ <L0ItemActiveTabIndicator />
235
232
  <span id={`${item.id}__label`} className='sr-only'>
236
233
  {localizedString}
237
234
  </span>
@@ -241,15 +238,18 @@ const L0Item = ({ item, parent, path, pinned, onRearrange }: L0ItemProps) => {
241
238
  };
242
239
 
243
240
  const ItemAvatar = ({ item }: Pick<L0ItemProps, 'item'>) => {
241
+ const { t } = useTranslation(meta.id);
244
242
  const type = l0ItemType(item);
245
243
  if (item.properties.icon) {
246
244
  const hue = item.properties.hue ?? null;
247
245
  const hueFgStyle = hue && { style: { color: `var(--dx-${hue}SurfaceText)` } };
248
- return <Icon icon={item.properties.icon} size={5} {...hueFgStyle} />;
246
+ return <Icon icon={item.properties.icon} size={6} {...hueFgStyle} />;
249
247
  }
250
248
 
251
249
  if (type === 'tab' && item.properties.disposition !== 'pin-end') {
252
- return <L0Avatar item={item} />;
250
+ const hue = item.properties.hue ?? null;
251
+ const localizedString = toLocalizedString(item.properties.label, t);
252
+ return <DxAvatar hue={hue} hueVariant='surface' variant='square' size={12} fallback={localizedString} />;
253
253
  }
254
254
 
255
255
  return null;
@@ -317,7 +317,7 @@ export type L0MenuProps = {
317
317
  };
318
318
 
319
319
  export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountItem, parent, path }: L0MenuProps) => {
320
- const { t } = useTranslation(NAVTREE_PLUGIN);
320
+ const { t } = useTranslation(meta.id);
321
321
 
322
322
  return (
323
323
  <Tabs.Tablist
@@ -331,20 +331,22 @@ export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountIte
331
331
  <MenuProvider>
332
332
  <DropdownMenu.Root group={parent} items={menuActions}>
333
333
  <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
- <div
339
- role='none'
340
- className={mx(
341
- l0ItemContent,
342
- 'is-[--rail-action] bs-[--rail-action] group-hover/l0item:bg-hoverSurface',
343
- )}
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')}
344
338
  >
345
- <Icon icon='ph--list--regular' size={5} />
346
- </div>
347
- </DropdownMenu.Trigger>
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>
348
350
  </Tooltip.Trigger>
349
351
  </DropdownMenu.Root>
350
352
  </MenuProvider>
@@ -396,7 +398,6 @@ export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountIte
396
398
  </L0ItemRoot>
397
399
  </div>
398
400
  )}
399
-
400
401
  <div
401
402
  role='none'
402
403
  className='hidden [body[data-platform="darwin"]_&]:block absolute block-start-0 is-[calc(var(--l0-size)-1px)] bs-[calc(40px+0.25rem)]'