@dxos/plugin-navtree 0.8.4-main.21d9917 → 0.8.4-main.2244d791bb
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.
- package/dist/lib/browser/{app-graph-builder-RSMA6I22.mjs → app-graph-builder-XGA4GPGL.mjs} +5 -4
- package/dist/lib/browser/app-graph-builder-XGA4GPGL.mjs.map +7 -0
- package/dist/lib/browser/{chunk-6YPQ625I.mjs → chunk-63YLDLLE.mjs} +178 -98
- package/dist/lib/browser/chunk-63YLDLLE.mjs.map +7 -0
- package/dist/lib/browser/{chunk-AGQDZBPL.mjs → chunk-X2HDG62A.mjs} +3 -3
- package/dist/lib/browser/{chunk-AGQDZBPL.mjs.map → chunk-X2HDG62A.mjs.map} +3 -3
- package/dist/lib/browser/index.mjs +31 -30
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{keyboard-32EH3N4K.mjs → keyboard-46XQHY2O.mjs} +6 -5
- package/dist/lib/browser/keyboard-46XQHY2O.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{operation-resolver-IB75DC5O.mjs → operation-resolver-NNNDII45.mjs} +8 -7
- package/dist/lib/browser/operation-resolver-NNNDII45.mjs.map +7 -0
- package/dist/lib/browser/{react-surface-F6CVMS3Y.mjs → react-surface-APSEG23H.mjs} +10 -9
- package/dist/lib/browser/react-surface-APSEG23H.mjs.map +7 -0
- package/dist/lib/browser/{state-EVYQOUI3.mjs → state-M5YUCIQU.mjs} +6 -5
- package/dist/lib/browser/state-M5YUCIQU.mjs.map +7 -0
- package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/keyboard/keyboard.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-resolver/index.d.ts +1 -1
- package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +2 -2
- package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface/index.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts +2 -2
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/state/state.d.ts.map +1 -1
- package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts.map +1 -1
- package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/L1Panel.d.ts +1 -1
- package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -1
- package/dist/types/src/experimental/Tree.stories.d.ts +18 -4
- package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
- package/dist/types/src/types/events.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +42 -41
- package/src/NavTreePlugin.tsx +21 -23
- package/src/capabilities/app-graph-builder/app-graph-builder.ts +4 -3
- package/src/capabilities/keyboard/keyboard.ts +5 -4
- package/src/capabilities/operation-resolver/operation-resolver.ts +5 -4
- package/src/capabilities/react-surface/react-surface.tsx +7 -6
- package/src/capabilities/state/state.ts +4 -3
- package/src/components/CommandsDialog/CommandsDialog.tsx +43 -44
- package/src/components/CommandsDialog/CommandsTrigger.tsx +3 -3
- package/src/components/NavTree/NavTree.stories.tsx +9 -8
- package/src/components/NavTreeContainer.tsx +12 -11
- package/src/components/NavTreeItem/NavTreeItemAction.stories.tsx +1 -1
- package/src/components/Sidebar/L0Menu.tsx +2 -5
- package/src/components/Sidebar/L1Panel.tsx +146 -67
- package/src/components/UserAccountAvatar/UserAccountAvatar.stories.tsx +1 -1
- package/src/experimental/Tree.stories.tsx +43 -49
- package/src/hooks.ts +1 -1
- package/src/types/events.ts +3 -2
- package/dist/lib/browser/app-graph-builder-RSMA6I22.mjs.map +0 -7
- package/dist/lib/browser/chunk-6YPQ625I.mjs.map +0 -7
- package/dist/lib/browser/keyboard-32EH3N4K.mjs.map +0 -7
- package/dist/lib/browser/operation-resolver-IB75DC5O.mjs.map +0 -7
- package/dist/lib/browser/react-surface-F6CVMS3Y.mjs.map +0 -7
- package/dist/lib/browser/state-EVYQOUI3.mjs.map +0 -7
|
@@ -2,18 +2,22 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
5
6
|
import React, { useCallback, useMemo } from 'react';
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
8
|
+
import { Node } from '@dxos/app-graph';
|
|
9
|
+
import { useActionRunner } from '@dxos/plugin-graph';
|
|
10
|
+
import { DensityProvider, IconButton, ScrollArea, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
9
11
|
import { Tree } from '@dxos/react-ui-list';
|
|
12
|
+
import { DropdownMenu, type MenuItem, MenuProvider } from '@dxos/react-ui-menu';
|
|
10
13
|
import { Tabs } from '@dxos/react-ui-tabs';
|
|
11
14
|
import { hoverableControlItem, hoverableOpenControlItem } from '@dxos/ui-theme';
|
|
12
15
|
|
|
13
|
-
import { useIsAlternateTree } from '../../hooks';
|
|
16
|
+
import { useIsAlternateTree, useLoadDescendents } from '../../hooks';
|
|
14
17
|
import { meta } from '../../meta';
|
|
18
|
+
import { NAV_TREE_ITEM } from '../NavTree';
|
|
15
19
|
import { useNavTreeContext } from '../NavTreeContext';
|
|
16
|
-
import { NavTreeItemColumns } from '../NavTreeItem';
|
|
20
|
+
import { NavTreeItemAction, NavTreeItemColumns } from '../NavTreeItem';
|
|
17
21
|
|
|
18
22
|
export type L1PanelProps = {
|
|
19
23
|
open?: boolean;
|
|
@@ -61,31 +65,33 @@ export const L1Panel = ({ open, path, item, currentItemId, onBack }: L1PanelProp
|
|
|
61
65
|
{item.id === currentItemId && (
|
|
62
66
|
<DensityProvider density='fine'>
|
|
63
67
|
<L1PanelHeader path={path} item={item} currentItemId={currentItemId} onBack={onBack} />
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
68
|
+
<ScrollArea.Root thin orientation='vertical'>
|
|
69
|
+
<ScrollArea.Viewport>
|
|
70
|
+
{isAlternate ? (
|
|
71
|
+
<Tree
|
|
72
|
+
{...navTreeContext}
|
|
73
|
+
id={alternateTree.id}
|
|
74
|
+
root={alternateTree}
|
|
75
|
+
path={alternatePath}
|
|
76
|
+
levelOffset={5}
|
|
77
|
+
gridTemplateColumns='[tree-row-start] 1fr min-content min-content min-content [tree-row-end]'
|
|
78
|
+
renderColumns={NavTreeItemColumns}
|
|
79
|
+
useItems={useAlternateItems}
|
|
80
|
+
/>
|
|
81
|
+
) : (
|
|
82
|
+
<Tree
|
|
83
|
+
{...navTreeContext}
|
|
84
|
+
id={item.id}
|
|
85
|
+
root={item}
|
|
86
|
+
path={path}
|
|
87
|
+
levelOffset={5}
|
|
88
|
+
gridTemplateColumns='[tree-row-start] 1fr min-content min-content min-content [tree-row-end]'
|
|
89
|
+
renderColumns={NavTreeItemColumns}
|
|
90
|
+
draggable
|
|
91
|
+
/>
|
|
92
|
+
)}
|
|
93
|
+
</ScrollArea.Viewport>
|
|
94
|
+
</ScrollArea.Root>
|
|
89
95
|
</DensityProvider>
|
|
90
96
|
)}
|
|
91
97
|
</Tabs.Tabpanel>
|
|
@@ -97,55 +103,128 @@ export const L1Panel = ({ open, path, item, currentItemId, onBack }: L1PanelProp
|
|
|
97
103
|
*/
|
|
98
104
|
const L1PanelHeader = ({ item, path, onBack }: L1PanelProps) => {
|
|
99
105
|
const { t } = useTranslation(meta.id);
|
|
100
|
-
const {
|
|
106
|
+
const { renderItemEnd: ItemEnd } = useNavTreeContext();
|
|
101
107
|
const title = toLocalizedString(item.properties.label, t);
|
|
102
108
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const alternatePath = useMemo(() => [...path, item.id], [item.id, path]);
|
|
106
|
-
const isAlternate = useIsAlternateTree(alternatePath, item);
|
|
107
|
-
const backCapable = item.id.startsWith('!') || isAlternate;
|
|
109
|
+
const { primaryAction, groupedActions, menuActions, onAction } = useL1MenuActions({ item, path });
|
|
110
|
+
useLoadDescendents(item);
|
|
108
111
|
|
|
109
|
-
const handleOpen = useCallback(() => {
|
|
110
|
-
setAlternateTree?.(alternatePath, true);
|
|
111
|
-
}, [alternatePath, setAlternateTree]);
|
|
112
|
-
|
|
113
|
-
const handleBack = useCallback(() => {
|
|
114
|
-
if (isAlternate) {
|
|
115
|
-
setAlternateTree?.(alternatePath, false);
|
|
116
|
-
} else {
|
|
117
|
-
onBack?.();
|
|
118
|
-
}
|
|
119
|
-
}, [isAlternate, alternatePath, setAlternateTree, onBack]);
|
|
120
|
-
|
|
121
|
-
// TODO(burdon): Reuse same grid as tree?
|
|
122
112
|
return (
|
|
123
113
|
<div className='flex is-full items-center border-be border-subduedSeparator app-drag density-coarse'>
|
|
124
114
|
<div className='is-6' />
|
|
125
115
|
<h2 className='flex-1 truncate min-is-0'>{title}</h2>
|
|
126
|
-
{(
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
116
|
+
{/* TODO(wittjosiah): Reconcile with NavTreeItemColumns. */}
|
|
117
|
+
<div role='none' className='contents app-no-drag'>
|
|
118
|
+
{primaryAction?.properties?.disposition === 'list-item-primary' && !primaryAction?.properties?.disabled && (
|
|
119
|
+
<NavTreeItemAction
|
|
120
|
+
testId={primaryAction.properties?.testId}
|
|
121
|
+
label={toLocalizedString(primaryAction.properties?.label, t)}
|
|
122
|
+
icon={primaryAction.properties?.icon ?? 'ph--placeholder--regular'}
|
|
123
|
+
parent={item}
|
|
124
|
+
monolithic={Node.isAction(primaryAction)}
|
|
125
|
+
menuActions={Node.isAction(primaryAction) ? [primaryAction] : groupedActions[primaryAction?.id ?? '']}
|
|
126
|
+
menuType={primaryAction.properties?.menuType}
|
|
127
|
+
caller={NAV_TREE_ITEM}
|
|
128
|
+
/>
|
|
129
|
+
)}
|
|
130
|
+
{menuActions.length === 1 && (
|
|
138
131
|
<IconButton
|
|
139
|
-
|
|
132
|
+
size={5}
|
|
133
|
+
density='coarse'
|
|
134
|
+
classNames={['shrink-0 pli-2 pointer-fine:pli-1', hoverableControlItem, hoverableOpenControlItem]}
|
|
140
135
|
variant='ghost'
|
|
141
|
-
icon={
|
|
136
|
+
icon={menuActions[0].properties?.icon ?? 'ph--placeholder--regular'}
|
|
142
137
|
iconOnly
|
|
143
|
-
label={toLocalizedString(
|
|
144
|
-
|
|
145
|
-
onClick={
|
|
138
|
+
label={toLocalizedString(menuActions[0].properties?.label, t)}
|
|
139
|
+
data-testid={menuActions[0].properties?.testId}
|
|
140
|
+
onClick={() => onAction(menuActions[0] as Node.Action)}
|
|
146
141
|
/>
|
|
147
|
-
)
|
|
148
|
-
|
|
142
|
+
)}
|
|
143
|
+
{menuActions.length > 1 && (
|
|
144
|
+
<MenuProvider onAction={onAction}>
|
|
145
|
+
<DropdownMenu.Root group={item} items={menuActions as MenuItem[]} caller={NAV_TREE_ITEM}>
|
|
146
|
+
<DropdownMenu.Trigger asChild>
|
|
147
|
+
<IconButton
|
|
148
|
+
size={5}
|
|
149
|
+
density='coarse'
|
|
150
|
+
classNames={['shrink-0 pli-2 pointer-fine:pli-1', hoverableControlItem, hoverableOpenControlItem]}
|
|
151
|
+
variant='ghost'
|
|
152
|
+
icon='ph--dots-three-vertical--regular'
|
|
153
|
+
iconOnly
|
|
154
|
+
label={t('tree item actions label')}
|
|
155
|
+
data-testid='navtree.treeItem.actionsLevel0'
|
|
156
|
+
/>
|
|
157
|
+
</DropdownMenu.Trigger>
|
|
158
|
+
</DropdownMenu.Root>
|
|
159
|
+
</MenuProvider>
|
|
160
|
+
)}
|
|
161
|
+
{ItemEnd && <ItemEnd node={item} open />}
|
|
162
|
+
</div>
|
|
149
163
|
</div>
|
|
150
164
|
);
|
|
151
165
|
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Builds the menu actions for the L1 panel header, combining graph actions with a synthetic settings/back action.
|
|
169
|
+
*/
|
|
170
|
+
const useL1MenuActions = ({ item, path }: Pick<L1PanelProps, 'item' | 'path'>) => {
|
|
171
|
+
const { t } = useTranslation(meta.id);
|
|
172
|
+
const { setAlternateTree, useActions, ...navTreeContext } = useNavTreeContext();
|
|
173
|
+
const runAction = useActionRunner();
|
|
174
|
+
|
|
175
|
+
// TODO(wittjosiah): Support multiple alternate trees.
|
|
176
|
+
const alternateTree = navTreeContext.useItems(item, { disposition: 'alternate-tree' })[0];
|
|
177
|
+
const alternatePath = useMemo(() => [...path, item.id], [item.id, path]);
|
|
178
|
+
const isAlternate = useIsAlternateTree(alternatePath, item);
|
|
179
|
+
|
|
180
|
+
// Graph actions.
|
|
181
|
+
const { actions: _actions, groupedActions } = useActions(item);
|
|
182
|
+
const [primaryAction, ...secondaryActions] = _actions.toSorted((a, _b) =>
|
|
183
|
+
a.properties?.disposition === 'list-item-primary' ? -1 : 1,
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
const graphMenuActions = (
|
|
187
|
+
primaryAction?.properties?.disposition === 'list-item-primary' ? secondaryActions : _actions
|
|
188
|
+
)
|
|
189
|
+
.flatMap((action) => (Node.isAction(action) ? [action] : []))
|
|
190
|
+
.filter((a) => ['list-item', 'list-item-primary'].includes(a.properties?.disposition));
|
|
191
|
+
|
|
192
|
+
// Synthetic settings/back action.
|
|
193
|
+
const settingsActionId = `${item.id}~settings`;
|
|
194
|
+
const settingsAction = useMemo((): Node.Action | undefined => {
|
|
195
|
+
if (!alternateTree) {
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
id: settingsActionId,
|
|
200
|
+
type: Node.ActionType,
|
|
201
|
+
data: () => Effect.void,
|
|
202
|
+
properties: {
|
|
203
|
+
label: isAlternate ? ['button back', { ns: meta.id }] : (alternateTree.properties.label ?? alternateTree.id),
|
|
204
|
+
icon: isAlternate
|
|
205
|
+
? 'ph--arrow-u-down-left--regular'
|
|
206
|
+
: (alternateTree.properties.icon ?? 'ph--placeholder--regular'),
|
|
207
|
+
disposition: 'list-item',
|
|
208
|
+
testId: isAlternate ? 'navtree.backToSpace' : 'navtree.spaceSettings',
|
|
209
|
+
},
|
|
210
|
+
} as Node.Action;
|
|
211
|
+
}, [alternateTree, isAlternate, settingsActionId, t]);
|
|
212
|
+
|
|
213
|
+
const menuActions = useMemo(
|
|
214
|
+
() => [...graphMenuActions, ...(settingsAction ? [settingsAction] : [])],
|
|
215
|
+
[graphMenuActions, settingsAction],
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
const onAction = useCallback(
|
|
219
|
+
(action: Node.Action, params?: Node.InvokeProps) => {
|
|
220
|
+
if (action.id === settingsActionId) {
|
|
221
|
+
setAlternateTree?.(alternatePath, !isAlternate);
|
|
222
|
+
} else {
|
|
223
|
+
void runAction(action, params);
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
[settingsActionId, setAlternateTree, alternatePath, isAlternate, runAction],
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
return { primaryAction, groupedActions, menuActions, onAction };
|
|
230
|
+
};
|
|
@@ -11,7 +11,7 @@ import { UserAccountAvatar } from './UserAccountAvatar';
|
|
|
11
11
|
const meta = {
|
|
12
12
|
title: 'plugins/plugin-navtree/UserAccountAvatar',
|
|
13
13
|
|
|
14
|
-
decorators: [withTheme],
|
|
14
|
+
decorators: [withTheme()],
|
|
15
15
|
component: UserAccountAvatar,
|
|
16
16
|
} satisfies Meta<typeof UserAccountAvatar>;
|
|
17
17
|
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type Meta } from '@storybook/react-vite';
|
|
6
|
-
import React, {
|
|
6
|
+
import React, { useEffect, useState } from 'react';
|
|
7
7
|
|
|
8
8
|
import { faker } from '@dxos/random';
|
|
9
|
-
import { Icon, IconButton } from '@dxos/react-ui';
|
|
9
|
+
import { Icon, IconButton, Layout, ScrollArea } from '@dxos/react-ui';
|
|
10
10
|
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
11
11
|
import { mx } from '@dxos/ui-theme';
|
|
12
12
|
|
|
@@ -14,28 +14,6 @@ import { type ItemMap, Tree, type TreeNodeData, type TreeProps, visitNodes, visi
|
|
|
14
14
|
|
|
15
15
|
faker.seed(1234);
|
|
16
16
|
|
|
17
|
-
/**
|
|
18
|
-
* Space:
|
|
19
|
-
* - Space panels are separated from each other to give them more weight than folders.
|
|
20
|
-
* - Private space isn't different (just first, different icon).
|
|
21
|
-
* - Edit titles in place.
|
|
22
|
-
*
|
|
23
|
-
* Navigation:
|
|
24
|
-
* - up/down across spaces/folder peers
|
|
25
|
-
* - right to enter space/folder children
|
|
26
|
-
* - left to parent
|
|
27
|
-
*/
|
|
28
|
-
const Container = ({ children, sidebar }: PropsWithChildren<{ sidebar: JSX.Element }>) => {
|
|
29
|
-
return (
|
|
30
|
-
<div className='flex'>
|
|
31
|
-
{/* TODO(burdon): Custom thin scrollbar. */}
|
|
32
|
-
{/* TODO(burdon): Horizontal scrolling within navtree? */}
|
|
33
|
-
<div className='flex flex-col overflow-y-auto is-[300px] bg-neutral-100 dark:bg-neutral-950'>{sidebar}</div>
|
|
34
|
-
<div className='flex flex-col grow overflow-hidden'>{children}</div>
|
|
35
|
-
</div>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
17
|
// TODO(burdon): Generate.
|
|
40
18
|
const data: TreeNodeData[] = [
|
|
41
19
|
{
|
|
@@ -134,7 +112,7 @@ const Sidebar = ({ mutate }: { mutate?: boolean }) => {
|
|
|
134
112
|
}
|
|
135
113
|
}, []);
|
|
136
114
|
|
|
137
|
-
const handleCreateItem: TreeProps['onMenuAction'] = (id
|
|
115
|
+
const handleCreateItem: TreeProps['onMenuAction'] = (id) => {
|
|
138
116
|
setItems((items) => {
|
|
139
117
|
let parent: TreeNodeData | undefined;
|
|
140
118
|
visitNodes(root, (node) => {
|
|
@@ -167,27 +145,29 @@ const Sidebar = ({ mutate }: { mutate?: boolean }) => {
|
|
|
167
145
|
};
|
|
168
146
|
|
|
169
147
|
return (
|
|
170
|
-
<
|
|
171
|
-
<
|
|
172
|
-
<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
148
|
+
<Layout.Main>
|
|
149
|
+
<ScrollArea.Root orientation='vertical' thin>
|
|
150
|
+
<ScrollArea.Viewport>
|
|
151
|
+
<Tree
|
|
152
|
+
className='p-0.5 gap-1'
|
|
153
|
+
node={root}
|
|
154
|
+
open={openItems}
|
|
155
|
+
selected={selectedItems}
|
|
156
|
+
active={activeItems}
|
|
157
|
+
onChangeOpen={(id, open) => setOpenItems((items) => ({ ...items, [id]: open }))}
|
|
158
|
+
onChangeSelected={(id, open) => setSelectedItems((items) => ({ ...items, [id]: open }))}
|
|
159
|
+
onMenuAction={handleCreateItem}
|
|
160
|
+
getSlots={(node, open, depth) => {
|
|
161
|
+
if (depth === 1) {
|
|
162
|
+
return {
|
|
163
|
+
root: 'rounded bg-white dark:bg-neutral-850',
|
|
164
|
+
header: mx('rounded-t bg-neutral-50 dark:bg-neutral-900', !open && 'rounded-b'),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}}
|
|
168
|
+
/>
|
|
169
|
+
</ScrollArea.Viewport>
|
|
170
|
+
</ScrollArea.Root>
|
|
191
171
|
|
|
192
172
|
<div className='flex items-center my-2 pli-2 gap-2'>
|
|
193
173
|
<IconButton icon='ph--plus-circle--regular' iconOnly label='Create space' onClick={handleCreateSpace} />
|
|
@@ -196,20 +176,34 @@ const Sidebar = ({ mutate }: { mutate?: boolean }) => {
|
|
|
196
176
|
</span>
|
|
197
177
|
<Icon icon='ph--list--regular' />
|
|
198
178
|
</div>
|
|
199
|
-
</
|
|
179
|
+
</Layout.Main>
|
|
200
180
|
);
|
|
201
181
|
};
|
|
202
182
|
|
|
203
183
|
const meta = {
|
|
204
184
|
title: 'plugins/plugin-navtree/experimental/Tree',
|
|
205
185
|
component: Tree,
|
|
206
|
-
decorators: [withTheme, withLayout({ layout: 'column' })],
|
|
186
|
+
decorators: [withTheme(), withLayout({ layout: 'column', classNames: 'is-[20rem]' })],
|
|
187
|
+
parameters: {
|
|
188
|
+
layout: 'fullscreen',
|
|
189
|
+
},
|
|
207
190
|
} satisfies Meta<typeof Tree>;
|
|
208
191
|
|
|
209
192
|
export default meta;
|
|
210
193
|
|
|
194
|
+
/**
|
|
195
|
+
* Space:
|
|
196
|
+
* - Space panels are separated from each other to give them more weight than folders.
|
|
197
|
+
* - Private space isn't different (just first, different icon).
|
|
198
|
+
* - Edit titles in place.
|
|
199
|
+
*
|
|
200
|
+
* Navigation:
|
|
201
|
+
* - up/down across spaces/folder peers
|
|
202
|
+
* - right to enter space/folder children
|
|
203
|
+
* - left to parent
|
|
204
|
+
*/
|
|
211
205
|
export const Default = () => {
|
|
212
|
-
return <
|
|
206
|
+
return <Sidebar mutate />;
|
|
213
207
|
};
|
|
214
208
|
|
|
215
209
|
export const Visitor = () => {
|
package/src/hooks.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { type Atom, useAtomValue } from '@effect-atom/atom-react';
|
|
6
6
|
import { useEffect, useMemo } from 'react';
|
|
7
7
|
|
|
8
|
-
import { useCapability } from '@dxos/app-framework/
|
|
8
|
+
import { useCapability } from '@dxos/app-framework/ui';
|
|
9
9
|
import { type Node } from '@dxos/app-graph';
|
|
10
10
|
|
|
11
11
|
import { useNavTreeContext } from './components';
|
package/src/types/events.ts
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { type ActivationEvent
|
|
5
|
+
import { type ActivationEvent } from '@dxos/app-framework';
|
|
6
|
+
import { AppActivationEvents } from '@dxos/app-toolkit';
|
|
6
7
|
|
|
7
8
|
import { meta } from '../meta';
|
|
8
9
|
|
|
9
10
|
export namespace NavTreeEvents {
|
|
10
|
-
export const StateReady: ActivationEvent.ActivationEvent =
|
|
11
|
+
export const StateReady: ActivationEvent.ActivationEvent = AppActivationEvents.createStateEvent(meta.id);
|
|
11
12
|
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/capabilities/app-graph-builder/app-graph-builder.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Capability, Common } from '@dxos/app-framework';\nimport { Operation } from '@dxos/operation';\nimport { GraphBuilder, NodeMatcher } from '@dxos/plugin-graph';\n\nimport { COMMANDS_DIALOG, meta } from '../../meta';\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n const extensions = yield* GraphBuilder.createExtension({\n id: meta.id,\n match: NodeMatcher.whenRoot,\n actions: () =>\n Effect.succeed([\n {\n id: COMMANDS_DIALOG,\n data: () =>\n Operation.invoke(Common.LayoutOperation.UpdateDialog, {\n subject: COMMANDS_DIALOG,\n blockAlign: 'start',\n }),\n properties: {\n label: ['open commands label', { ns: meta.id }],\n icon: 'ph--magnifying-glass--regular',\n keyBinding: {\n macos: 'meta+k',\n windows: 'ctrl+k',\n },\n },\n },\n ]),\n });\n\n return Capability.contributes(Common.Capability.AppGraphBuilder, extensions);\n }),\n);\n"],
|
|
5
|
-
"mappings": ";;;;;;AAIA,YAAYA,YAAY;AAExB,SAASC,YAAYC,cAAc;AACnC,SAASC,iBAAiB;AAC1B,SAASC,cAAcC,mBAAmB;AAI1C,IAAA,4BAAeC,WAAWC,WACjBC,kBAAW,aAAA;AAChB,QAAMC,aAAa,OAAOC,aAAaC,gBAAgB;IACrDC,IAAIC,KAAKD;IACTE,OAAOC,YAAYC;IACnBC,SAAS,MACAC,eAAQ;MACb;QACEN,IAAIO;QACJC,MAAM,MACJC,UAAUC,OAAOC,OAAOC,gBAAgBC,cAAc;UACpDC,SAASP;UACTQ,YAAY;QACd,CAAA;QACFC,YAAY;UACVC,OAAO;YAAC;YAAuB;cAAEC,IAAIjB,KAAKD;YAAG;;UAC7CmB,MAAM;UACNC,YAAY;YACVC,OAAO;YACPC,SAAS;UACX;QACF;MACF;KACD;EACL,CAAA;AAEA,SAAO5B,WAAW6B,YAAYZ,OAAOjB,WAAW8B,iBAAiB3B,UAAAA;AACnE,CAAA,CAAA;",
|
|
6
|
-
"names": ["Effect", "Capability", "Common", "Operation", "GraphBuilder", "NodeMatcher", "Capability", "makeModule", "fnUntraced", "extensions", "GraphBuilder", "createExtension", "id", "meta", "match", "NodeMatcher", "whenRoot", "actions", "succeed", "COMMANDS_DIALOG", "data", "Operation", "invoke", "Common", "LayoutOperation", "UpdateDialog", "subject", "blockAlign", "properties", "label", "ns", "icon", "keyBinding", "macos", "windows", "contributes", "AppGraphBuilder"]
|
|
7
|
-
}
|