@dxos/plugin-navtree 0.8.2-main.fbd8ed0 → 0.8.2-staging.7ac8446

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 (149) hide show
  1. package/dist/lib/browser/{app-graph-builder-P7AY3K72.mjs → app-graph-builder-26D3MUCA.mjs} +6 -7
  2. package/dist/lib/browser/app-graph-builder-26D3MUCA.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-TLQLMZXU.mjs → chunk-4RQJXI4D.mjs} +1 -1
  4. package/dist/lib/browser/chunk-4RQJXI4D.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-UM2C5XK3.mjs → chunk-DN43QXSX.mjs} +365 -444
  6. package/dist/lib/browser/chunk-DN43QXSX.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +10 -5
  8. package/dist/lib/browser/index.mjs.map +3 -3
  9. package/dist/lib/browser/{intent-resolver-PW7B76HO.mjs → intent-resolver-BZMUS24C.mjs} +7 -7
  10. package/dist/lib/browser/intent-resolver-BZMUS24C.mjs.map +7 -0
  11. package/dist/lib/browser/keyboard-IQXHKUWM.mjs +46 -0
  12. package/dist/lib/browser/keyboard-IQXHKUWM.mjs.map +7 -0
  13. package/dist/lib/browser/meta.json +1 -1
  14. package/dist/lib/browser/{react-surface-M3CAS7ZP.mjs → react-surface-3HCM3SHJ.mjs} +3 -3
  15. package/dist/lib/browser/{state-3UBYOTQT.mjs → state-M5UJ3MHL.mjs} +12 -18
  16. package/dist/lib/browser/state-M5UJ3MHL.mjs.map +7 -0
  17. package/dist/types/src/capabilities/app-graph-builder.d.ts +179 -2
  18. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  19. package/dist/types/src/capabilities/capabilities.d.ts +4 -7
  20. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  21. package/dist/types/src/capabilities/index.d.ts +183 -38
  22. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  23. package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
  24. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  25. package/dist/types/src/capabilities/keyboard.d.ts +2 -2
  26. package/dist/types/src/capabilities/keyboard.d.ts.map +1 -1
  27. package/dist/types/src/capabilities/state.d.ts +6 -9
  28. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  29. package/dist/types/src/components/CommandsDialog.d.ts.map +1 -0
  30. package/dist/types/src/components/CommandsTrigger.d.ts.map +1 -0
  31. package/dist/types/src/components/L0Menu.d.ts +10 -0
  32. package/dist/types/src/components/L0Menu.d.ts.map +1 -0
  33. package/dist/types/src/components/L1Panels.d.ts +14 -0
  34. package/dist/types/src/components/L1Panels.d.ts.map +1 -0
  35. package/dist/types/src/components/NavTree.d.ts +5 -0
  36. package/dist/types/src/components/NavTree.d.ts.map +1 -0
  37. package/dist/types/src/components/NavTree.stories.d.ts +7 -0
  38. package/dist/types/src/components/NavTree.stories.d.ts.map +1 -0
  39. package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
  40. package/dist/types/src/components/NavTreeContext.d.ts.map +1 -1
  41. package/dist/types/src/components/NavTreeDocumentTitle.d.ts.map +1 -1
  42. package/dist/types/src/components/{NavTreeItem/NavTreeItemAction.d.ts → NavTreeItemAction.d.ts} +3 -2
  43. package/dist/types/src/components/NavTreeItemAction.d.ts.map +1 -0
  44. package/dist/types/src/components/NavTreeItemAction.stories.d.ts +41 -0
  45. package/dist/types/src/components/NavTreeItemAction.stories.d.ts.map +1 -0
  46. package/dist/types/src/components/NavTreeItemColumns.d.ts +4 -0
  47. package/dist/types/src/components/NavTreeItemColumns.d.ts.map +1 -0
  48. package/dist/types/src/components/{UserAccountAvatar/UserAccountAvatar.d.ts → UserAccountAvatar.d.ts} +1 -1
  49. package/dist/types/src/components/UserAccountAvatar.d.ts.map +1 -0
  50. package/dist/types/src/components/{UserAccountAvatar/UserAccountAvatar.stories.d.ts → UserAccountAvatar.stories.d.ts} +2 -1
  51. package/dist/types/src/components/UserAccountAvatar.stories.d.ts.map +1 -0
  52. package/dist/types/src/components/index.d.ts +1 -0
  53. package/dist/types/src/components/index.d.ts.map +1 -1
  54. package/dist/types/src/components/types.d.ts +14 -20
  55. package/dist/types/src/components/types.d.ts.map +1 -1
  56. package/dist/types/src/experimental/Tree.d.ts.map +1 -1
  57. package/dist/types/src/hooks.d.ts.map +1 -1
  58. package/dist/types/src/stories/Graph.stories.d.ts +7 -0
  59. package/dist/types/src/stories/Graph.stories.d.ts.map +1 -0
  60. package/dist/types/src/stories/StorybookNavTree.d.ts +4 -0
  61. package/dist/types/src/stories/StorybookNavTree.d.ts.map +1 -0
  62. package/dist/types/src/testing/generator.d.ts +6 -7
  63. package/dist/types/src/testing/generator.d.ts.map +1 -1
  64. package/dist/types/src/testing/index.d.ts +0 -1
  65. package/dist/types/src/testing/index.d.ts.map +1 -1
  66. package/dist/types/src/testing/update-state.d.ts.map +1 -1
  67. package/dist/types/src/translations.d.ts +0 -1
  68. package/dist/types/src/translations.d.ts.map +1 -1
  69. package/dist/types/src/util.d.ts +10 -7
  70. package/dist/types/src/util.d.ts.map +1 -1
  71. package/dist/types/tsconfig.tsbuildinfo +1 -1
  72. package/package.json +31 -40
  73. package/src/NavTreePlugin.tsx +2 -2
  74. package/src/capabilities/app-graph-builder.ts +28 -38
  75. package/src/capabilities/capabilities.ts +4 -5
  76. package/src/capabilities/intent-resolver.ts +7 -8
  77. package/src/capabilities/keyboard.ts +32 -37
  78. package/src/capabilities/state.ts +17 -23
  79. package/src/components/{CommandsDialog/CommandsDialog.tsx → CommandsDialog.tsx} +7 -8
  80. package/src/components/{CommandsDialog/CommandsTrigger.tsx → CommandsTrigger.tsx} +1 -1
  81. package/src/components/{Sidebar/L0Menu.tsx → L0Menu.tsx} +131 -188
  82. package/src/components/L1Panels.tsx +115 -0
  83. package/src/components/NavTree.stories.tsx +107 -0
  84. package/src/components/NavTree.tsx +51 -0
  85. package/src/components/NavTreeContainer.tsx +74 -94
  86. package/src/components/NavTreeContext.tsx +1 -1
  87. package/src/components/{NavTreeItem/NavTreeItemAction.stories.tsx → NavTreeItemAction.stories.tsx} +6 -12
  88. package/src/components/{NavTreeItem/NavTreeItemAction.tsx → NavTreeItemAction.tsx} +18 -23
  89. package/src/components/NavTreeItemColumns.tsx +71 -0
  90. package/src/components/{UserAccountAvatar/UserAccountAvatar.stories.tsx → UserAccountAvatar.stories.tsx} +5 -5
  91. package/src/components/{UserAccountAvatar/UserAccountAvatar.tsx → UserAccountAvatar.tsx} +7 -7
  92. package/src/components/index.ts +1 -0
  93. package/src/components/types.ts +15 -20
  94. package/src/hooks.ts +11 -12
  95. package/src/stories/Graph.stories.tsx +130 -0
  96. package/src/stories/StorybookNavTree.tsx +63 -0
  97. package/src/testing/generator.ts +12 -15
  98. package/src/testing/index.ts +0 -1
  99. package/src/translations.ts +0 -1
  100. package/src/util.ts +32 -10
  101. package/dist/lib/browser/app-graph-builder-P7AY3K72.mjs.map +0 -7
  102. package/dist/lib/browser/chunk-TLQLMZXU.mjs.map +0 -7
  103. package/dist/lib/browser/chunk-UM2C5XK3.mjs.map +0 -7
  104. package/dist/lib/browser/intent-resolver-PW7B76HO.mjs.map +0 -7
  105. package/dist/lib/browser/keyboard-DDFATRUG.mjs +0 -51
  106. package/dist/lib/browser/keyboard-DDFATRUG.mjs.map +0 -7
  107. package/dist/lib/browser/state-3UBYOTQT.mjs.map +0 -7
  108. package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts.map +0 -1
  109. package/dist/types/src/components/CommandsDialog/CommandsTrigger.d.ts.map +0 -1
  110. package/dist/types/src/components/CommandsDialog/index.d.ts +0 -3
  111. package/dist/types/src/components/CommandsDialog/index.d.ts.map +0 -1
  112. package/dist/types/src/components/NavTree/NavTree.d.ts +0 -8
  113. package/dist/types/src/components/NavTree/NavTree.d.ts.map +0 -1
  114. package/dist/types/src/components/NavTree/NavTree.stories.d.ts +0 -8
  115. package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +0 -1
  116. package/dist/types/src/components/NavTree/index.d.ts +0 -2
  117. package/dist/types/src/components/NavTree/index.d.ts.map +0 -1
  118. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts.map +0 -1
  119. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +0 -8
  120. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +0 -1
  121. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts +0 -4
  122. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +0 -1
  123. package/dist/types/src/components/NavTreeItem/index.d.ts +0 -3
  124. package/dist/types/src/components/NavTreeItem/index.d.ts.map +0 -1
  125. package/dist/types/src/components/Sidebar/L0Menu.d.ts +0 -13
  126. package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +0 -1
  127. package/dist/types/src/components/Sidebar/L1Panel.d.ts +0 -15
  128. package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +0 -1
  129. package/dist/types/src/components/Sidebar/index.d.ts +0 -3
  130. package/dist/types/src/components/Sidebar/index.d.ts.map +0 -1
  131. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.d.ts.map +0 -1
  132. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts.map +0 -1
  133. package/dist/types/src/components/UserAccountAvatar/index.d.ts +0 -2
  134. package/dist/types/src/components/UserAccountAvatar/index.d.ts.map +0 -1
  135. package/dist/types/src/testing/app-graph-builder.d.ts +0 -3
  136. package/dist/types/src/testing/app-graph-builder.d.ts.map +0 -1
  137. package/src/components/CommandsDialog/index.ts +0 -6
  138. package/src/components/NavTree/NavTree.stories.tsx +0 -159
  139. package/src/components/NavTree/NavTree.tsx +0 -62
  140. package/src/components/NavTree/index.ts +0 -5
  141. package/src/components/NavTreeItem/NavTreeItemColumns.tsx +0 -73
  142. package/src/components/NavTreeItem/index.ts +0 -6
  143. package/src/components/Sidebar/L1Panel.tsx +0 -175
  144. package/src/components/Sidebar/index.ts +0 -6
  145. package/src/components/UserAccountAvatar/index.ts +0 -5
  146. package/src/testing/app-graph-builder.ts +0 -224
  147. /package/dist/lib/browser/{react-surface-M3CAS7ZP.mjs.map → react-surface-3HCM3SHJ.mjs.map} +0 -0
  148. /package/dist/types/src/components/{CommandsDialog/CommandsDialog.d.ts → CommandsDialog.d.ts} +0 -0
  149. /package/dist/types/src/components/{CommandsDialog/CommandsTrigger.d.ts → CommandsTrigger.d.ts} +0 -0
@@ -1,159 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import '@dxos-theme';
6
-
7
- import { type StoryObj, type Meta } from '@storybook/react';
8
- import { Schema } from 'effect';
9
- import React from 'react';
10
-
11
- import {
12
- Capabilities,
13
- IntentPlugin,
14
- LayoutAction,
15
- SettingsPlugin,
16
- contributes,
17
- createResolver,
18
- defineCapability,
19
- useCapability,
20
- } from '@dxos/app-framework';
21
- import { withPluginManager } from '@dxos/app-framework/testing';
22
- import { live } from '@dxos/live-object';
23
- import { AttentionPlugin } from '@dxos/plugin-attention';
24
- import { GraphPlugin } from '@dxos/plugin-graph';
25
- import { StorybookLayoutPlugin } from '@dxos/plugin-storybook-layout';
26
- import { ThemePlugin } from '@dxos/plugin-theme';
27
- import { faker } from '@dxos/random';
28
- import { IconButton, Input, Main, Toolbar } from '@dxos/react-ui';
29
- import { useAttendableAttributes, useAttention } from '@dxos/react-ui-attention';
30
- import { Stack, StackItem } from '@dxos/react-ui-stack';
31
- import { defaultTx, mx } from '@dxos/react-ui-theme';
32
- import { withLayout } from '@dxos/storybook-utils';
33
-
34
- import { NavTreePlugin } from '../../NavTreePlugin';
35
- import { storybookGraphBuilders } from '../../testing';
36
- import translations from '../../translations';
37
- import { NavTreeContainer } from '../NavTreeContainer';
38
-
39
- faker.seed(1234);
40
-
41
- const StoryState = defineCapability<{ tab: string }>('story-state');
42
-
43
- // TODO(burdon): Fix outline (e.g., button in sidebar nav is clipped when focused).
44
- // TODO(burdon): Consider similar containment of: Table, Sheet, Kanban Column, Form, etc.
45
-
46
- const container = 'flex flex-col grow gap-2 p-4 rounded-md';
47
-
48
- // TODO(burdon): Factor out PlankHeader.
49
- const StoryPlankHeading = ({ attendableId }: { attendableId: string }) => {
50
- const { hasAttention } = useAttention(attendableId);
51
- console.log('hasAttention', hasAttention);
52
- return (
53
- <div className='flex p-1 items-center border-b border-separator'>
54
- <IconButton
55
- density='coarse'
56
- icon='ph--atom--regular'
57
- label='Test'
58
- iconOnly
59
- variant={hasAttention ? 'primary' : 'ghost'}
60
- classNames='is-[--rail-action] bs-[--rail-action]'
61
- />
62
- <StackItem.ResizeHandle />
63
- </div>
64
- );
65
- };
66
-
67
- const StoryPlank = ({ attendableId }: { attendableId: string }) => {
68
- const attentionAttrs = useAttendableAttributes(attendableId);
69
-
70
- return (
71
- <StackItem.Root
72
- item={{ id: attendableId }}
73
- {...attentionAttrs}
74
- classNames='bg-baseSurface border-ie border-separator'
75
- size={30}
76
- >
77
- <StoryPlankHeading attendableId={attendableId} />
78
- <StackItem.Content toolbar>
79
- <Toolbar.Root classNames='border-b border-separator'>
80
- <Toolbar.Button>Test</Toolbar.Button>
81
- </Toolbar.Root>
82
-
83
- <div className={mx(container, 'm-2 bg-groupSurface')}>
84
- <Input.Root>
85
- <Input.Label>Level 1 (group)</Input.Label>
86
- </Input.Root>
87
- <div className={mx(container, 'bg-baseSurface')}>
88
- <Input.Root>
89
- <Input.Label>Level 2 (base)</Input.Label>
90
- <Input.TextArea placeholder='Enter text' />
91
- </Input.Root>
92
- </div>
93
- </div>
94
- </StackItem.Content>
95
- </StackItem.Root>
96
- );
97
- };
98
-
99
- const DefaultStory = () => {
100
- const state = useCapability(StoryState);
101
-
102
- return (
103
- <Main.Root complementarySidebarState='closed'>
104
- <Main.NavigationSidebar label='Navigation' classNames='grid'>
105
- <NavTreeContainer tab={state.tab} />
106
- </Main.NavigationSidebar>
107
- <Main.Content bounce handlesFocus>
108
- <Stack orientation='horizontal' size='contain'>
109
- <StoryPlank attendableId='space-0:object-0' />
110
- <StoryPlank attendableId='space-0:object-1' />
111
- </Stack>
112
- </Main.Content>
113
- </Main.Root>
114
- );
115
- };
116
-
117
- const meta: Meta<typeof NavTreeContainer> = {
118
- title: 'plugins/plugin-navtree/NavTree',
119
- component: NavTreeContainer,
120
- render: DefaultStory,
121
- decorators: [
122
- withPluginManager({
123
- plugins: [
124
- ThemePlugin({ tx: defaultTx }),
125
- StorybookLayoutPlugin({ initialState: { sidebarState: 'expanded' } }),
126
- GraphPlugin(),
127
- IntentPlugin(),
128
- SettingsPlugin(),
129
- AttentionPlugin(),
130
- NavTreePlugin(),
131
- ],
132
- capabilities: (context) => [
133
- contributes(StoryState, live({ tab: 'space-0' })),
134
- contributes(Capabilities.AppGraphBuilder, storybookGraphBuilders),
135
- contributes(Capabilities.IntentResolver, [
136
- createResolver({
137
- intent: LayoutAction.UpdateLayout,
138
- filter: (data): data is Schema.Schema.Type<typeof LayoutAction.SwitchWorkspace.fields.input> =>
139
- Schema.is(LayoutAction.SwitchWorkspace.fields.input)(data),
140
- resolve: ({ subject }) => {
141
- const state = context.getCapability(StoryState);
142
- state.tab = subject;
143
- },
144
- }),
145
- ]),
146
- ],
147
- }),
148
- withLayout({ fullscreen: true }),
149
- ],
150
- parameters: {
151
- translations,
152
- },
153
- };
154
-
155
- export default meta;
156
-
157
- type Story = StoryObj<typeof NavTreeContainer>;
158
-
159
- export const Default: Story = {};
@@ -1,62 +0,0 @@
1
- //
2
- // Copyright 2024 DXOS.org
3
- //
4
-
5
- import React, { useMemo } from 'react';
6
-
7
- import { type TreeProps } from '@dxos/react-ui-list';
8
- import { Tabs } from '@dxos/react-ui-tabs';
9
-
10
- import { useLoadDescendents } from '../../hooks';
11
- import { type NavTreeItemGraphNode } from '../../types';
12
- import { useNavTreeContext } from '../NavTreeContext';
13
- import { L0Menu, L1Panels, type L1PanelsProps } from '../Sidebar';
14
-
15
- export const NAV_TREE_ITEM = 'NavTreeItem';
16
-
17
- export type NavTreeProps = Pick<TreeProps<NavTreeItemGraphNode>, 'id' | 'root'> & Pick<L1PanelsProps, 'open'>;
18
-
19
- export const NavTree = ({ id, root, ...props }: NavTreeProps) => {
20
- const { tab, useItems, onBack } = useNavTreeContext();
21
- const topLevelActions = useItems(root, { disposition: 'menu', sort: true });
22
- const topLevelCollections = useItems(root, { disposition: 'collection' });
23
- const topLevelWorkspaces = useItems(root, { disposition: 'workspace' });
24
- const topLevelNavigation = useItems(root, { disposition: 'navigation' });
25
- const l0Items = useMemo(
26
- () => [
27
- // prettier-ignore
28
- ...topLevelCollections,
29
- ...topLevelWorkspaces,
30
- ...topLevelNavigation,
31
- ],
32
- [topLevelCollections, topLevelWorkspaces, topLevelNavigation],
33
- );
34
- const pinnedItems = useItems(root, { disposition: 'pin-end', sort: true });
35
- const userAccountItem = useItems(root, { disposition: 'user-account' })[0];
36
- const topLevelItems = useMemo(
37
- () => [
38
- // prettier-ignore
39
- ...l0Items,
40
- ...pinnedItems,
41
- ...(userAccountItem ? [userAccountItem] : []),
42
- ],
43
- [l0Items, pinnedItems, userAccountItem],
44
- );
45
-
46
- useLoadDescendents(root);
47
- const path = useMemo(() => [id], [id]);
48
-
49
- return (
50
- <Tabs.Root value={tab} orientation='vertical' verticalVariant='stateless' classNames='relative'>
51
- <L0Menu
52
- menuActions={topLevelActions}
53
- topLevelItems={l0Items}
54
- pinnedItems={pinnedItems}
55
- userAccountItem={userAccountItem}
56
- path={path}
57
- parent={root}
58
- />
59
- <L1Panels topLevelItems={topLevelItems} path={path} currentItemId={tab} onBack={onBack} {...props} />
60
- </Tabs.Root>
61
- );
62
- };
@@ -1,5 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- export * from './NavTree';
@@ -1,73 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import React, { Fragment, memo } from 'react';
6
-
7
- import { isAction } from '@dxos/app-graph';
8
- import { DensityProvider, Popover, toLocalizedString, Treegrid, useTranslation } from '@dxos/react-ui';
9
-
10
- import { NavTreeItemAction } from './NavTreeItemAction';
11
- import { useLoadDescendents } from '../../hooks';
12
- import { NAVTREE_PLUGIN } from '../../meta';
13
- import { NAV_TREE_ITEM } from '../NavTree';
14
- import { useNavTreeContext } from '../NavTreeContext';
15
- import type { NavTreeItemColumnsProps } from '../types';
16
-
17
- export const NavTreeItemColumns = memo(({ path, item, open, density = 'fine' }: NavTreeItemColumnsProps) => {
18
- const { t } = useTranslation(NAVTREE_PLUGIN);
19
- const { getActions, renderItemEnd: ItemEnd, popoverAnchorId } = useNavTreeContext();
20
-
21
- const level = path.length - 2;
22
-
23
- const { actions: _actions, groupedActions } = getActions(item);
24
- const [primaryAction, ...secondaryActions] = _actions.toSorted((a, b) =>
25
- a.properties?.disposition === 'list-item-primary' ? -1 : 1,
26
- );
27
-
28
- const actions = (primaryAction?.properties?.disposition === 'list-item-primary' ? secondaryActions : _actions)
29
- .flatMap((action) => (isAction(action) ? [action] : []))
30
- .filter((action) => !action.properties?.hidden);
31
-
32
- const ActionRoot = popoverAnchorId === `dxos.org/ui/${NAV_TREE_ITEM}/${item.id}` ? Popover.Anchor : Fragment;
33
-
34
- useLoadDescendents(item);
35
- useLoadDescendents(primaryAction && !isAction(primaryAction) ? primaryAction : undefined);
36
-
37
- return (
38
- <DensityProvider density={density}>
39
- <div role='none' className='contents app-no-drag'>
40
- {primaryAction?.properties?.disposition === 'list-item-primary' && !primaryAction?.properties?.disabled ? (
41
- <NavTreeItemAction
42
- testId={primaryAction.properties?.testId}
43
- label={toLocalizedString(primaryAction.properties?.label, t)}
44
- icon={primaryAction.properties?.icon ?? 'ph--placeholder--regular'}
45
- parent={item}
46
- monolithic={isAction(primaryAction)}
47
- menuActions={isAction(primaryAction) ? [primaryAction] : groupedActions[primaryAction.id]}
48
- menuType={primaryAction.properties?.menuType}
49
- caller={NAV_TREE_ITEM}
50
- />
51
- ) : (
52
- <Treegrid.Cell />
53
- )}
54
- <ActionRoot>
55
- {actions.length > 0 ? (
56
- <NavTreeItemAction
57
- testId={`navtree.treeItem.actionsLevel${level}`}
58
- label={t('tree item actions label')}
59
- icon='ph--dots-three-vertical--regular'
60
- parent={item}
61
- menuActions={actions}
62
- menuType='dropdown'
63
- caller={NAV_TREE_ITEM}
64
- />
65
- ) : (
66
- <Treegrid.Cell />
67
- )}
68
- </ActionRoot>
69
- {ItemEnd && <ItemEnd node={item} open={open} />}
70
- </div>
71
- </DensityProvider>
72
- );
73
- });
@@ -1,6 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- export * from './NavTreeItemAction';
6
- export * from './NavTreeItemColumns';
@@ -1,175 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import React, { useCallback, useMemo } from 'react';
6
-
7
- import { type Node } from '@dxos/app-graph';
8
- import { Button, type ButtonProps, Icon, IconButton, toLocalizedString, useTranslation } from '@dxos/react-ui';
9
- import { Tree } from '@dxos/react-ui-list';
10
- import { Tabs } from '@dxos/react-ui-tabs';
11
- import { hoverableControlItem, hoverableOpenControlItem, mx } from '@dxos/react-ui-theme';
12
-
13
- import { useLoadDescendents } from '../../hooks';
14
- import { NAVTREE_PLUGIN } from '../../meta';
15
- import { l0ItemType } from '../../util';
16
- import { useNavTreeContext } from '../NavTreeContext';
17
- import { NavTreeItemColumns } from '../NavTreeItem';
18
-
19
- const headingBackButtonLabel = 'inset-0 min-is-0 truncate flex items-center pis-2';
20
-
21
- const TitleButton = ({ title, onClick }: { title: string } & Pick<ButtonProps, 'onClick'>) => {
22
- return (
23
- <Button
24
- variant='ghost'
25
- classNames='pli-1 flex-1 group text-start justify-start bs-[--rail-action] font-normal'
26
- onClick={onClick}
27
- >
28
- <Icon icon='ph--caret-left--bold' size={3} />
29
- <span className={mx(headingBackButtonLabel)}>{title}</span>
30
- </Button>
31
- );
32
- };
33
-
34
- export type L1PanelProps = {
35
- open?: boolean;
36
- item: Node<any>;
37
- path: string[];
38
- currentItemId: string;
39
- onBack?: () => void;
40
- };
41
-
42
- const L1Panel = ({ open, item, path, currentItemId, onBack }: L1PanelProps) => {
43
- const { isAlternateTree, setAlternateTree, ...navTreeContext } = useNavTreeContext();
44
- const { t } = useTranslation(NAVTREE_PLUGIN);
45
-
46
- // TODO(wittjosiah): Support multiple alternate trees.
47
- const alternateTree = navTreeContext.useItems(item, { disposition: 'alternate-tree' })[0];
48
- const alternatePath = useMemo(() => [...path, item.id], [item.id, path]);
49
- const handleOpen = useCallback(() => setAlternateTree?.(alternatePath, true), [alternatePath, setAlternateTree]);
50
- const isAlternate = isAlternateTree?.(alternatePath, item) ?? false;
51
- const useAlternateItems = useCallback(
52
- (node?: Node, { disposition }: { disposition?: string } = {}) => {
53
- // TODO(wittjosiah): Sorting is expensive, limit to necessary items for now.
54
- return navTreeContext.useItems(node, { disposition, sort: node?.id === alternateTree.id });
55
- },
56
- [navTreeContext, alternateTree],
57
- );
58
-
59
- const handleBack = useCallback(() => {
60
- if (isAlternate) {
61
- setAlternateTree?.(alternatePath, false);
62
- } else {
63
- onBack?.();
64
- }
65
- }, [isAlternate, onBack, alternatePath, setAlternateTree]);
66
-
67
- const title = toLocalizedString(item.properties.label, t);
68
- const backCapable = item.id.startsWith('!') || isAlternate;
69
-
70
- return (
71
- <Tabs.Tabpanel
72
- key={item.id}
73
- value={item.id}
74
- classNames={[
75
- 'absolute inset-block-0 inline-end-0',
76
- 'is-[calc(100%-var(--l0-size))] lg:is-[--l1-size] grid-cols-1 grid-rows-[var(--rail-size)_1fr]',
77
- 'pbs-[env(safe-area-inset-top)]',
78
- item.id === currentItemId && 'grid',
79
- ]}
80
- tabIndex={-1}
81
- aria-label={title}
82
- {...(!open && { inert: 'true' })}
83
- >
84
- {item.id === currentItemId && (
85
- <>
86
- <h2 className='flex items-center border-be border-separator app-drag pli-1'>
87
- {backCapable ? (
88
- <TitleButton title={title} onClick={handleBack} />
89
- ) : (
90
- <span className='flex-1 truncate min-is-0 pis-6'>{title}</span>
91
- )}
92
- {alternateTree && !isAlternate && (
93
- <IconButton
94
- variant='ghost'
95
- classNames={mx('shrink-0', hoverableControlItem, hoverableOpenControlItem, 'pli-2 pointer-fine:pli-1')}
96
- iconOnly
97
- size={5}
98
- density='coarse'
99
- icon={alternateTree.properties.icon ?? 'ph--placeholder--regular'}
100
- label={toLocalizedString(alternateTree.properties.label ?? alternateTree.id, t)}
101
- data-testid='treeView.alternateTreeButton'
102
- onClick={handleOpen}
103
- />
104
- )}
105
- <NavTreeItemColumns path={path} item={item} open density='coarse' />
106
- </h2>
107
- <div role='none' className='overflow-y-auto'>
108
- {isAlternate ? (
109
- <Tree
110
- {...navTreeContext}
111
- useItems={useAlternateItems}
112
- id={alternateTree.id}
113
- root={alternateTree}
114
- path={alternatePath}
115
- levelOffset={5}
116
- gridTemplateColumns='[tree-row-start] 1fr min-content min-content min-content [tree-row-end]'
117
- renderColumns={NavTreeItemColumns}
118
- />
119
- ) : (
120
- <Tree
121
- {...navTreeContext}
122
- id={item.id}
123
- root={item}
124
- path={path}
125
- levelOffset={5}
126
- draggable
127
- gridTemplateColumns='[tree-row-start] 1fr min-content min-content min-content [tree-row-end]'
128
- renderColumns={NavTreeItemColumns}
129
- />
130
- )}
131
- </div>
132
- </>
133
- )}
134
- </Tabs.Tabpanel>
135
- );
136
- };
137
-
138
- const L1PanelCollection = ({ item, path, ...props }: L1PanelProps) => {
139
- const { useItems } = useNavTreeContext();
140
- useLoadDescendents(item);
141
- const collectionItems = useItems(item);
142
- const groupPath = useMemo(() => [...path, item.id], [item.id, path]);
143
- return (
144
- <>
145
- {collectionItems
146
- .filter((item) => l0ItemType(item) === 'tab')
147
- .map((item) => (
148
- <L1Panel key={item.id} item={item} path={groupPath} {...props} />
149
- ))}
150
- </>
151
- );
152
- };
153
-
154
- export type L1PanelsProps = Pick<L1PanelProps, 'open' | 'currentItemId' | 'onBack'> & {
155
- topLevelItems: Node<any>[];
156
- path: string[];
157
- };
158
-
159
- export const L1Panels = ({ topLevelItems, onBack, ...props }: L1PanelsProps) => {
160
- return (
161
- <>
162
- {topLevelItems.map((item) => {
163
- const type = l0ItemType(item);
164
- switch (type) {
165
- case 'collection':
166
- return <L1PanelCollection key={item.id} item={item} {...props} />;
167
- case 'tab':
168
- return <L1Panel key={item.id} item={item} {...props} onBack={onBack} />;
169
- default:
170
- return null;
171
- }
172
- })}
173
- </>
174
- );
175
- };
@@ -1,6 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- export * from './L0Menu';
6
- export * from './L1Panel';
@@ -1,5 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- export * from './UserAccountAvatar';