@dxos/plugin-navtree 0.8.4-main.5ad4a44 → 0.8.4-main.66e292d
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-YAPMENYT.mjs → app-graph-builder-OHSCN3GX.mjs} +4 -4
- package/dist/lib/browser/app-graph-builder-OHSCN3GX.mjs.map +7 -0
- package/dist/lib/browser/{chunk-LPAREX6J.mjs → chunk-5VLWX4PK.mjs} +2 -2
- package/dist/lib/browser/chunk-E6MZBCU5.mjs +19 -0
- package/dist/lib/browser/chunk-E6MZBCU5.mjs.map +7 -0
- package/dist/lib/browser/{chunk-IMFXKPSB.mjs → chunk-UDAINHB6.mjs} +49 -43
- package/dist/lib/browser/chunk-UDAINHB6.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +3 -3
- package/dist/lib/browser/{intent-resolver-TCQXGF6U.mjs → intent-resolver-YUVXVPHG.mjs} +3 -3
- package/dist/lib/browser/{keyboard-AHSAWKXA.mjs → keyboard-YJEK2HTH.mjs} +6 -8
- package/dist/lib/browser/{keyboard-AHSAWKXA.mjs.map → keyboard-YJEK2HTH.mjs.map} +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-AH2TP73M.mjs → react-surface-V6LS3R4L.mjs} +4 -4
- package/dist/lib/browser/{state-2Q623V7U.mjs → state-BFD5KJCV.mjs} +3 -3
- package/dist/lib/browser/state-BFD5KJCV.mjs.map +7 -0
- package/dist/types/src/capabilities/index.d.ts +3 -3
- package/dist/types/src/capabilities/keyboard.d.ts.map +1 -1
- package/dist/types/src/capabilities/state.d.ts +1 -1
- package/dist/types/src/capabilities/state.d.ts.map +1 -1
- package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts.map +1 -1
- package/dist/types/src/components/CommandsDialog/CommandsTrigger.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
- package/dist/types/src/components/types.d.ts +1 -1
- package/dist/types/src/components/types.d.ts.map +1 -1
- package/dist/types/src/experimental/Tree.stories.d.ts +0 -3
- package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/testing/generator.d.ts +1 -1
- package/dist/types/src/testing/generator.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +1 -1
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +39 -39
- package/src/capabilities/app-graph-builder.ts +2 -2
- package/src/capabilities/keyboard.ts +1 -3
- package/src/capabilities/state.ts +1 -2
- package/src/components/CommandsDialog/CommandsDialog.tsx +11 -3
- package/src/components/CommandsDialog/CommandsTrigger.tsx +2 -1
- package/src/components/NavTree/NavTree.stories.tsx +2 -2
- package/src/components/NavTreeContainer.tsx +74 -42
- package/src/components/Sidebar/L0Menu.tsx +4 -4
- package/src/components/Sidebar/L1Panel.tsx +0 -2
- package/src/components/types.ts +1 -1
- package/src/experimental/Tree.stories.tsx +4 -7
- package/src/experimental/Tree.tsx +2 -2
- package/src/meta.ts +5 -0
- package/src/testing/app-graph-builder.ts +10 -10
- package/src/testing/generator.ts +9 -7
- package/src/types.ts +1 -1
- package/dist/lib/browser/app-graph-builder-YAPMENYT.mjs.map +0 -7
- package/dist/lib/browser/chunk-IMFXKPSB.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZENLR72O.mjs +0 -14
- package/dist/lib/browser/chunk-ZENLR72O.mjs.map +0 -7
- package/dist/lib/browser/state-2Q623V7U.mjs.map +0 -7
- /package/dist/lib/browser/{chunk-LPAREX6J.mjs.map → chunk-5VLWX4PK.mjs.map} +0 -0
- /package/dist/lib/browser/{intent-resolver-TCQXGF6U.mjs.map → intent-resolver-YUVXVPHG.mjs.map} +0 -0
- /package/dist/lib/browser/{react-surface-AH2TP73M.mjs.map → react-surface-V6LS3R4L.mjs.map} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-navtree",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.66e292d",
|
|
4
4
|
"description": "DXOS Surface plugin for a tree view visualization of the graph.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -31,58 +31,58 @@
|
|
|
31
31
|
"@radix-ui/react-dismissable-layer": "1.1.5",
|
|
32
32
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
|
33
33
|
"date-fns": "^3.3.1",
|
|
34
|
-
"@dxos/app-framework": "0.8.4-main.
|
|
35
|
-
"@dxos/
|
|
36
|
-
"@dxos/debug": "0.8.4-main.
|
|
37
|
-
"@dxos/
|
|
38
|
-
"@dxos/
|
|
39
|
-
"@dxos/
|
|
40
|
-
"@dxos/
|
|
41
|
-
"@dxos/
|
|
42
|
-
"@dxos/local-storage": "0.8.4-main.
|
|
43
|
-
"@dxos/live-object": "0.8.4-main.
|
|
44
|
-
"@dxos/log": "0.8.4-main.
|
|
45
|
-
"@dxos/plugin-
|
|
46
|
-
"@dxos/plugin-
|
|
47
|
-
"@dxos/plugin-observability": "0.8.4-main.
|
|
48
|
-
"@dxos/
|
|
49
|
-
"@dxos/
|
|
50
|
-
"@dxos/react-ui-attention": "0.8.4-main.
|
|
51
|
-
"@dxos/react-ui-list": "0.8.4-main.
|
|
52
|
-
"@dxos/react-ui-menu": "0.8.4-main.
|
|
53
|
-
"@dxos/react-ui-searchlist": "0.8.4-main.
|
|
54
|
-
"@dxos/react-ui-stack": "0.8.4-main.
|
|
55
|
-
"@dxos/react-ui-tabs": "0.8.4-main.
|
|
56
|
-
"@dxos/util": "0.8.4-main.
|
|
34
|
+
"@dxos/app-framework": "0.8.4-main.66e292d",
|
|
35
|
+
"@dxos/app-graph": "0.8.4-main.66e292d",
|
|
36
|
+
"@dxos/debug": "0.8.4-main.66e292d",
|
|
37
|
+
"@dxos/echo": "0.8.4-main.66e292d",
|
|
38
|
+
"@dxos/async": "0.8.4-main.66e292d",
|
|
39
|
+
"@dxos/invariant": "0.8.4-main.66e292d",
|
|
40
|
+
"@dxos/keyboard": "0.8.4-main.66e292d",
|
|
41
|
+
"@dxos/lit-ui": "0.8.4-main.66e292d",
|
|
42
|
+
"@dxos/local-storage": "0.8.4-main.66e292d",
|
|
43
|
+
"@dxos/live-object": "0.8.4-main.66e292d",
|
|
44
|
+
"@dxos/log": "0.8.4-main.66e292d",
|
|
45
|
+
"@dxos/plugin-graph": "0.8.4-main.66e292d",
|
|
46
|
+
"@dxos/plugin-deck": "0.8.4-main.66e292d",
|
|
47
|
+
"@dxos/plugin-observability": "0.8.4-main.66e292d",
|
|
48
|
+
"@dxos/react-client": "0.8.4-main.66e292d",
|
|
49
|
+
"@dxos/protocols": "0.8.4-main.66e292d",
|
|
50
|
+
"@dxos/react-ui-attention": "0.8.4-main.66e292d",
|
|
51
|
+
"@dxos/react-ui-list": "0.8.4-main.66e292d",
|
|
52
|
+
"@dxos/react-ui-menu": "0.8.4-main.66e292d",
|
|
53
|
+
"@dxos/react-ui-searchlist": "0.8.4-main.66e292d",
|
|
54
|
+
"@dxos/react-ui-stack": "0.8.4-main.66e292d",
|
|
55
|
+
"@dxos/react-ui-tabs": "0.8.4-main.66e292d",
|
|
56
|
+
"@dxos/util": "0.8.4-main.66e292d"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@effect-
|
|
59
|
+
"@effect-atom/atom-react": "^0.3.4",
|
|
60
60
|
"@effect/platform": "0.92.1",
|
|
61
61
|
"@types/react": "~19.2.2",
|
|
62
|
-
"@types/react-dom": "~19.2.
|
|
62
|
+
"@types/react-dom": "~19.2.2",
|
|
63
63
|
"effect": "3.18.3",
|
|
64
64
|
"react": "~19.2.0",
|
|
65
65
|
"react-dom": "~19.2.0",
|
|
66
66
|
"vite": "7.1.9",
|
|
67
|
-
"@dxos/echo-signals": "0.8.4-main.
|
|
68
|
-
"@dxos/plugin-attention": "0.8.4-main.
|
|
69
|
-
"@dxos/plugin-client": "0.8.4-main.
|
|
70
|
-
"@dxos/plugin-space": "0.8.4-main.
|
|
71
|
-
"@dxos/plugin-
|
|
72
|
-
"@dxos/
|
|
73
|
-
"@dxos/
|
|
74
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
75
|
-
"@dxos/
|
|
76
|
-
"@dxos/storybook-utils": "0.8.4-main.
|
|
67
|
+
"@dxos/echo-signals": "0.8.4-main.66e292d",
|
|
68
|
+
"@dxos/plugin-attention": "0.8.4-main.66e292d",
|
|
69
|
+
"@dxos/plugin-client": "0.8.4-main.66e292d",
|
|
70
|
+
"@dxos/plugin-space": "0.8.4-main.66e292d",
|
|
71
|
+
"@dxos/plugin-storybook-layout": "0.8.4-main.66e292d",
|
|
72
|
+
"@dxos/plugin-theme": "0.8.4-main.66e292d",
|
|
73
|
+
"@dxos/react-ui": "0.8.4-main.66e292d",
|
|
74
|
+
"@dxos/react-ui-theme": "0.8.4-main.66e292d",
|
|
75
|
+
"@dxos/random": "0.8.4-main.66e292d",
|
|
76
|
+
"@dxos/storybook-utils": "0.8.4-main.66e292d"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
|
-
"@effect-
|
|
79
|
+
"@effect-atom/atom-react": "^0.3.4",
|
|
80
80
|
"@effect/platform": "^0.80.12",
|
|
81
81
|
"effect": "^3.13.3",
|
|
82
82
|
"react": "^19.0.0",
|
|
83
83
|
"react-dom": "^19.0.0",
|
|
84
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
85
|
-
"@dxos/react-ui-theme": "0.8.4-main.
|
|
84
|
+
"@dxos/react-ui": "0.8.4-main.66e292d",
|
|
85
|
+
"@dxos/react-ui-theme": "0.8.4-main.66e292d"
|
|
86
86
|
},
|
|
87
87
|
"publishConfig": {
|
|
88
88
|
"access": "public"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Atom } from '@effect-atom/atom-react';
|
|
6
6
|
import * as Function from 'effect/Function';
|
|
7
7
|
import * as Option from 'effect/Option';
|
|
8
8
|
|
|
@@ -17,7 +17,7 @@ export default (context: PluginContext) =>
|
|
|
17
17
|
createExtension({
|
|
18
18
|
id: meta.id,
|
|
19
19
|
actions: (node) =>
|
|
20
|
-
|
|
20
|
+
Atom.make((get) =>
|
|
21
21
|
Function.pipe(
|
|
22
22
|
get(node),
|
|
23
23
|
Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
|
|
@@ -34,9 +34,7 @@ export default (context: PluginContext) => {
|
|
|
34
34
|
if (shortcut && isAction(node)) {
|
|
35
35
|
Keyboard.singleton.getContext(path.slice(0, -1).join('/')).bind({
|
|
36
36
|
shortcut,
|
|
37
|
-
handler: () => {
|
|
38
|
-
void node.data({ parent: node, caller: KEY_BINDING });
|
|
39
|
-
},
|
|
37
|
+
handler: () => node.data({ parent: node, caller: KEY_BINDING }),
|
|
40
38
|
data: node.properties.label,
|
|
41
39
|
});
|
|
42
40
|
}
|
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
import { effect, untracked } from '@preact/signals-core';
|
|
6
6
|
|
|
7
7
|
import { Capabilities, type PluginContext, contributes } from '@dxos/app-framework';
|
|
8
|
-
import { type Live } from '@dxos/
|
|
9
|
-
import { live } from '@dxos/live-object';
|
|
8
|
+
import { type Live, live } from '@dxos/live-object';
|
|
10
9
|
import { Path } from '@dxos/react-ui-list';
|
|
11
10
|
|
|
12
11
|
import { meta } from '../meta';
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { useMemo, useState } from 'react';
|
|
6
6
|
|
|
7
|
-
import { LayoutAction, createIntent
|
|
7
|
+
import { LayoutAction, createIntent } from '@dxos/app-framework';
|
|
8
|
+
import { useAppGraph, useIntentDispatcher } from '@dxos/app-framework/react';
|
|
8
9
|
import { type ActionLike, isAction, isActionGroup } from '@dxos/app-graph';
|
|
9
10
|
import { Keyboard, keySymbols } from '@dxos/keyboard';
|
|
10
11
|
import { useActions } from '@dxos/plugin-graph';
|
|
@@ -89,7 +90,12 @@ export const CommandsDialogContent = ({ selected: initial }: { selected?: string
|
|
|
89
90
|
return;
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
void dispatch(
|
|
93
|
+
void dispatch(
|
|
94
|
+
createIntent(LayoutAction.UpdateDialog, {
|
|
95
|
+
part: 'dialog',
|
|
96
|
+
options: { state: false },
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
93
99
|
setTimeout(() => {
|
|
94
100
|
const node = graph.getConnections(group?.id ?? action.id, 'inbound')[0];
|
|
95
101
|
void (node && isAction(action) && action.data({ parent: node, caller: KEY_BINDING }));
|
|
@@ -97,7 +103,9 @@ export const CommandsDialogContent = ({ selected: initial }: { selected?: string
|
|
|
97
103
|
}}
|
|
98
104
|
classNames='flex items-center gap-2'
|
|
99
105
|
disabled={action.properties.disabled}
|
|
100
|
-
{...(action.properties?.testId && {
|
|
106
|
+
{...(action.properties?.testId && {
|
|
107
|
+
'data-testid': action.properties.testId,
|
|
108
|
+
})}
|
|
101
109
|
>
|
|
102
110
|
<Icon icon={action.properties.icon} size={4} />
|
|
103
111
|
<span className='grow truncate'>{label}</span>
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
|
-
import { LayoutAction, createIntent
|
|
7
|
+
import { LayoutAction, createIntent } from '@dxos/app-framework';
|
|
8
|
+
import { useIntentDispatcher } from '@dxos/app-framework/react';
|
|
8
9
|
import { Button, Icon, useTranslation } from '@dxos/react-ui';
|
|
9
10
|
|
|
10
11
|
import { COMMANDS_DIALOG, meta } from '../../meta';
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
contributes,
|
|
16
16
|
createResolver,
|
|
17
17
|
defineCapability,
|
|
18
|
-
useCapability,
|
|
19
18
|
} from '@dxos/app-framework';
|
|
19
|
+
import { useCapability } from '@dxos/app-framework/react';
|
|
20
20
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
21
21
|
import { live } from '@dxos/live-object';
|
|
22
22
|
import { AttentionPlugin } from '@dxos/plugin-attention';
|
|
@@ -86,7 +86,7 @@ const StoryPlank = ({ attendableId }: { attendableId: string }) => {
|
|
|
86
86
|
>
|
|
87
87
|
<StoryPlankHeading attendableId={attendableId} />
|
|
88
88
|
<StackItem.Content toolbar>
|
|
89
|
-
<Toolbar.Root classNames='border-
|
|
89
|
+
<Toolbar.Root classNames='border-be border-subduedSeparator'>
|
|
90
90
|
<Toolbar.Button>Test</Toolbar.Button>
|
|
91
91
|
</Toolbar.Root>
|
|
92
92
|
|
|
@@ -7,15 +7,8 @@ import { type Instruction, extractInstruction } from '@atlaskit/pragmatic-drag-a
|
|
|
7
7
|
import { untracked } from '@preact/signals-core';
|
|
8
8
|
import React, { memo, useCallback, useEffect, useMemo } from 'react';
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
Surface,
|
|
13
|
-
createIntent,
|
|
14
|
-
useAppGraph,
|
|
15
|
-
useCapability,
|
|
16
|
-
useIntentDispatcher,
|
|
17
|
-
useLayout,
|
|
18
|
-
} from '@dxos/app-framework';
|
|
10
|
+
import { LayoutAction, createIntent } from '@dxos/app-framework';
|
|
11
|
+
import { Surface, useAppGraph, useCapability, useIntentDispatcher, useLayout } from '@dxos/app-framework/react';
|
|
19
12
|
import { type Node, ROOT_ID, type ReadableGraph, isAction, isActionLike } from '@dxos/app-graph';
|
|
20
13
|
import { PLANK_COMPANION_TYPE } from '@dxos/plugin-deck/types';
|
|
21
14
|
import { useConnections, useActions as useGraphActions } from '@dxos/plugin-graph';
|
|
@@ -118,7 +111,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
118
111
|
className: mx(node.properties.className, node.properties.modified && 'italic'), // TODO(burdon): Italic?
|
|
119
112
|
headingClassName: node.properties.headingClassName,
|
|
120
113
|
icon: node.properties.icon,
|
|
121
|
-
|
|
114
|
+
iconHue: node.properties.iconHue,
|
|
122
115
|
testId: node.properties.testId,
|
|
123
116
|
};
|
|
124
117
|
},
|
|
@@ -163,19 +156,36 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
163
156
|
}),
|
|
164
157
|
);
|
|
165
158
|
|
|
166
|
-
await dispatch(
|
|
159
|
+
await dispatch(
|
|
160
|
+
createIntent(LayoutAction.SwitchWorkspace, {
|
|
161
|
+
part: 'workspace',
|
|
162
|
+
subject: node.id,
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
167
165
|
|
|
168
166
|
// Open the first item if the workspace is empty.
|
|
169
167
|
if (layout.active.length === 0) {
|
|
170
168
|
const [item] = getItems(graph, node).filter((node) => !isActionLike(node));
|
|
171
169
|
if (item && item.data) {
|
|
172
|
-
await dispatch(
|
|
170
|
+
await dispatch(
|
|
171
|
+
createIntent(LayoutAction.Open, {
|
|
172
|
+
part: 'main',
|
|
173
|
+
subject: [item.id],
|
|
174
|
+
}),
|
|
175
|
+
);
|
|
173
176
|
}
|
|
174
177
|
}
|
|
175
178
|
},
|
|
176
179
|
[dispatch, layout.active, tab, navigationSidebarState, isLg],
|
|
177
180
|
);
|
|
178
181
|
|
|
182
|
+
const blockInstruction = useCallback(
|
|
183
|
+
({ instruction, source, target }: { instruction: Instruction; source: TreeData; target: TreeData }) => {
|
|
184
|
+
return target.item.properties.blockInstruction?.(source, instruction) ?? false;
|
|
185
|
+
},
|
|
186
|
+
[],
|
|
187
|
+
);
|
|
188
|
+
|
|
179
189
|
const canDrop = useCallback(({ source, target }: { source: TreeData; target: TreeData }) => {
|
|
180
190
|
return target.item.properties.canDrop?.(source) ?? false;
|
|
181
191
|
}, []);
|
|
@@ -207,10 +217,19 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
207
217
|
);
|
|
208
218
|
} else if (option) {
|
|
209
219
|
void dispatch(
|
|
210
|
-
createIntent(LayoutAction.Close, {
|
|
220
|
+
createIntent(LayoutAction.Close, {
|
|
221
|
+
part: 'main',
|
|
222
|
+
subject: [node.id],
|
|
223
|
+
options: { state: false },
|
|
224
|
+
}),
|
|
211
225
|
);
|
|
212
226
|
} else {
|
|
213
|
-
void dispatch(
|
|
227
|
+
void dispatch(
|
|
228
|
+
createIntent(LayoutAction.ScrollIntoView, {
|
|
229
|
+
part: 'current',
|
|
230
|
+
subject: node.id,
|
|
231
|
+
}),
|
|
232
|
+
);
|
|
214
233
|
}
|
|
215
234
|
|
|
216
235
|
const defaultAction = graph.getActions(node.id).find((action) => action.properties?.disposition === 'default');
|
|
@@ -219,14 +238,25 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
219
238
|
}
|
|
220
239
|
|
|
221
240
|
if (!isLg) {
|
|
222
|
-
void dispatch(
|
|
241
|
+
void dispatch(
|
|
242
|
+
createIntent(LayoutAction.UpdateSidebar, {
|
|
243
|
+
part: 'sidebar',
|
|
244
|
+
options: { state: 'closed' },
|
|
245
|
+
}),
|
|
246
|
+
);
|
|
223
247
|
}
|
|
224
248
|
},
|
|
225
249
|
[graph, dispatch, isCurrent, isLg],
|
|
226
250
|
);
|
|
227
251
|
|
|
228
252
|
const handleBack = useCallback(
|
|
229
|
-
() =>
|
|
253
|
+
() =>
|
|
254
|
+
dispatch(
|
|
255
|
+
createIntent(LayoutAction.RevertWorkspace, {
|
|
256
|
+
part: 'workspace',
|
|
257
|
+
options: { revert: true },
|
|
258
|
+
}),
|
|
259
|
+
),
|
|
230
260
|
[dispatch],
|
|
231
261
|
);
|
|
232
262
|
|
|
@@ -298,43 +328,45 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
298
328
|
|
|
299
329
|
const navTreeContextValue = useMemo(
|
|
300
330
|
() => ({
|
|
301
|
-
|
|
302
|
-
tab,
|
|
303
|
-
useActions,
|
|
304
|
-
loadDescendents,
|
|
305
|
-
renderItemEnd,
|
|
306
|
-
popoverAnchorId,
|
|
307
|
-
topbar,
|
|
308
|
-
getProps,
|
|
309
|
-
isCurrent,
|
|
310
|
-
isOpen,
|
|
331
|
+
blockInstruction,
|
|
311
332
|
canDrop,
|
|
312
333
|
canSelect,
|
|
334
|
+
getProps,
|
|
313
335
|
isAlternateTree,
|
|
314
|
-
|
|
315
|
-
|
|
336
|
+
isCurrent,
|
|
337
|
+
isOpen,
|
|
338
|
+
loadDescendents,
|
|
339
|
+
onBack: handleBack,
|
|
316
340
|
onOpenChange: handleOpenChange,
|
|
317
341
|
onSelect: handleSelect,
|
|
318
|
-
|
|
319
|
-
}),
|
|
320
|
-
[
|
|
321
|
-
tab,
|
|
322
|
-
useActions,
|
|
323
|
-
loadDescendents,
|
|
324
|
-
renderItemEnd,
|
|
342
|
+
onTabChange: handleTabChange,
|
|
325
343
|
popoverAnchorId,
|
|
344
|
+
renderItemEnd,
|
|
345
|
+
setAlternateTree,
|
|
346
|
+
tab,
|
|
326
347
|
topbar,
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
348
|
+
useActions,
|
|
349
|
+
useItems,
|
|
350
|
+
}),
|
|
351
|
+
[
|
|
352
|
+
blockInstruction,
|
|
330
353
|
canDrop,
|
|
331
354
|
canSelect,
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
handleTabChange,
|
|
355
|
+
getProps,
|
|
356
|
+
handleBack,
|
|
335
357
|
handleOpenChange,
|
|
336
358
|
handleSelect,
|
|
337
|
-
|
|
359
|
+
handleTabChange,
|
|
360
|
+
isAlternateTree,
|
|
361
|
+
isCurrent,
|
|
362
|
+
isOpen,
|
|
363
|
+
loadDescendents,
|
|
364
|
+
popoverAnchorId,
|
|
365
|
+
renderItemEnd,
|
|
366
|
+
setAlternateTree,
|
|
367
|
+
tab,
|
|
368
|
+
topbar,
|
|
369
|
+
useActions,
|
|
338
370
|
],
|
|
339
371
|
);
|
|
340
372
|
|
|
@@ -102,7 +102,7 @@ const l0Breakpoints: Record<string, string> = {
|
|
|
102
102
|
};
|
|
103
103
|
|
|
104
104
|
const l0ItemRoot =
|
|
105
|
-
'group/l0item flex
|
|
105
|
+
'group/l0item flex is-full justify-center items-center relative data[type!="collection"]:cursor-pointer app-no-drag dx-focus-ring-group';
|
|
106
106
|
|
|
107
107
|
const l0ItemContent = 'flex justify-center items-center dx-focus-ring-group-indicator transition-colors rounded-sm';
|
|
108
108
|
|
|
@@ -119,9 +119,9 @@ const L0ItemRoot = forwardRef<HTMLElement, PropsWithChildren<L0ItemRootProps>>(
|
|
|
119
119
|
const handleClick = useL0ItemClick({ item, parent, path: itemPath }, type);
|
|
120
120
|
const rootProps =
|
|
121
121
|
type === 'tab'
|
|
122
|
-
? { value: item.id, tabIndex: 0, onClick: handleClick, 'data-testid': testId, 'data-
|
|
122
|
+
? { value: item.id, tabIndex: 0, onClick: handleClick, 'data-testid': testId, 'data-object-id': id }
|
|
123
123
|
: type !== 'collection'
|
|
124
|
-
? { onClick: handleClick, 'data-testid': testId, 'data-
|
|
124
|
+
? { onClick: handleClick, 'data-testid': testId, 'data-object-id': id }
|
|
125
125
|
: { onClick: handleClick, role: 'button' };
|
|
126
126
|
|
|
127
127
|
return (
|
|
@@ -287,7 +287,7 @@ const L0Collection = ({ item, path }: L0ItemProps) => {
|
|
|
287
287
|
role='group'
|
|
288
288
|
className='contents group/l0c'
|
|
289
289
|
aria-labelledby={`${item.id}__label`}
|
|
290
|
-
data-
|
|
290
|
+
data-object-id={id}
|
|
291
291
|
data-testid={testId}
|
|
292
292
|
>
|
|
293
293
|
{collectionItems.map((collectionItem) => (
|
|
@@ -127,7 +127,6 @@ const L1PanelHeader = ({ item, path, onBack }: L1PanelProps) => {
|
|
|
127
127
|
variant='ghost'
|
|
128
128
|
icon='ph--arrow-u-down-left--regular'
|
|
129
129
|
iconOnly
|
|
130
|
-
size={5}
|
|
131
130
|
label={t('button back')}
|
|
132
131
|
classNames={[hoverableControlItem, hoverableOpenControlItem, 'pointer-fine:pli-1']}
|
|
133
132
|
onClick={handleBack}
|
|
@@ -139,7 +138,6 @@ const L1PanelHeader = ({ item, path, onBack }: L1PanelProps) => {
|
|
|
139
138
|
variant='ghost'
|
|
140
139
|
icon={alternateTree.properties.icon ?? 'ph--placeholder--regular'}
|
|
141
140
|
iconOnly
|
|
142
|
-
size={5}
|
|
143
141
|
label={toLocalizedString(alternateTree.properties.label ?? alternateTree.id, t)}
|
|
144
142
|
classNames={[hoverableControlItem, hoverableOpenControlItem, 'pointer-fine:pli-1']}
|
|
145
143
|
onClick={handleOpen}
|
package/src/components/types.ts
CHANGED
|
@@ -15,7 +15,7 @@ import type { L1PanelProps } from './Sidebar';
|
|
|
15
15
|
|
|
16
16
|
export type NavTreeContextValue = Pick<
|
|
17
17
|
TreeProps<NavTreeItemGraphNode, { disposition?: string; sort?: boolean }>,
|
|
18
|
-
'useItems' | 'getProps' | 'isCurrent' | 'isOpen' | 'canDrop' | 'onOpenChange' | 'onSelect'
|
|
18
|
+
'useItems' | 'getProps' | 'isCurrent' | 'isOpen' | 'blockInstruction' | 'canDrop' | 'onOpenChange' | 'onSelect'
|
|
19
19
|
> &
|
|
20
20
|
Pick<L1PanelProps, 'onBack'> & {
|
|
21
21
|
tab: string;
|
|
@@ -7,7 +7,7 @@ import React, { type JSX, type PropsWithChildren, useEffect, useState } from 're
|
|
|
7
7
|
|
|
8
8
|
import { faker } from '@dxos/random';
|
|
9
9
|
import { Icon, IconButton } from '@dxos/react-ui';
|
|
10
|
-
import { withTheme } from '@dxos/react-ui/testing';
|
|
10
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
11
11
|
import { mx } from '@dxos/react-ui-theme';
|
|
12
12
|
|
|
13
13
|
import { type ItemMap, Tree, type TreeNodeData, type TreeProps, visitNodes, visitor } from './Tree';
|
|
@@ -30,7 +30,7 @@ const Container = ({ children, sidebar }: PropsWithChildren<{ sidebar: JSX.Eleme
|
|
|
30
30
|
<div className='flex'>
|
|
31
31
|
{/* TODO(burdon): Custom thin scrollbar. */}
|
|
32
32
|
{/* TODO(burdon): Horizontal scrolling within navtree? */}
|
|
33
|
-
<div className='flex flex-col overflow-y-auto
|
|
33
|
+
<div className='flex flex-col overflow-y-auto is-[300px] bg-neutral-100 dark:bg-neutral-950'>{sidebar}</div>
|
|
34
34
|
<div className='flex flex-col grow overflow-hidden'>{children}</div>
|
|
35
35
|
</div>
|
|
36
36
|
);
|
|
@@ -189,7 +189,7 @@ const Sidebar = ({ mutate }: { mutate?: boolean }) => {
|
|
|
189
189
|
/>
|
|
190
190
|
</div>
|
|
191
191
|
|
|
192
|
-
<div className='flex items-center my-2
|
|
192
|
+
<div className='flex items-center my-2 pli-2 gap-2'>
|
|
193
193
|
<IconButton icon='ph--plus-circle--regular' iconOnly label='Create space' onClick={handleCreateSpace} />
|
|
194
194
|
<span className='grow text-sm' onClick={handleCreateSpace}>
|
|
195
195
|
New space
|
|
@@ -203,10 +203,7 @@ const Sidebar = ({ mutate }: { mutate?: boolean }) => {
|
|
|
203
203
|
const meta = {
|
|
204
204
|
title: 'plugins/plugin-navtree/experimental/Tree',
|
|
205
205
|
component: Tree,
|
|
206
|
-
decorators: [withTheme],
|
|
207
|
-
parameters: {
|
|
208
|
-
layout: 'column',
|
|
209
|
-
},
|
|
206
|
+
decorators: [withTheme, withLayout({ container: 'column' })],
|
|
210
207
|
} satisfies Meta<typeof Tree>;
|
|
211
208
|
|
|
212
209
|
export default meta;
|
|
@@ -19,7 +19,7 @@ export const IconButton = ({
|
|
|
19
19
|
} & Pick<HTMLAttributes<HTMLDivElement>, 'onClick'>) => {
|
|
20
20
|
// TODO(burdon): Density aware.
|
|
21
21
|
return (
|
|
22
|
-
<div className={mx('flex
|
|
22
|
+
<div className={mx('flex is-6 bs-6 items-center justify-center select-none', classNames)} onClick={onClick}>
|
|
23
23
|
<Icon icon={iconName} classNames='cursor-pointer' size={size} />
|
|
24
24
|
</div>
|
|
25
25
|
);
|
|
@@ -193,7 +193,7 @@ export const TreeNodeRow = (props: TreeNodeProps & { className?: string }) => {
|
|
|
193
193
|
<Grid
|
|
194
194
|
style={{ paddingLeft: `${(depth - 1) * 24}px` }}
|
|
195
195
|
className={mx(
|
|
196
|
-
'group
|
|
196
|
+
'group is-full items-center cursor-pointer bg-hoverSurface',
|
|
197
197
|
// TODO(burdon): Use data-active.
|
|
198
198
|
selected?.[id] && 'bg-activeSurface',
|
|
199
199
|
className,
|
package/src/meta.ts
CHANGED
|
@@ -3,10 +3,15 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type PluginMeta } from '@dxos/app-framework';
|
|
6
|
+
import { trim } from '@dxos/util';
|
|
6
7
|
|
|
7
8
|
export const meta: PluginMeta = {
|
|
8
9
|
id: 'dxos.org/plugin/navtree',
|
|
9
10
|
name: 'Navtree',
|
|
11
|
+
description: trim`
|
|
12
|
+
Hierarchical navigation tree for browsing spaces, folders, and objects.
|
|
13
|
+
Provides sidebar navigation with collapsible sections and quick access to workspace content.
|
|
14
|
+
`,
|
|
10
15
|
};
|
|
11
16
|
|
|
12
17
|
// TODO(wittjosiah): Factor out.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Atom } from '@effect-atom/atom-react';
|
|
6
6
|
import * as Function from 'effect/Function';
|
|
7
7
|
import * as Option from 'effect/Option';
|
|
8
8
|
|
|
@@ -28,7 +28,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
|
|
|
28
28
|
createExtension({
|
|
29
29
|
id: 'app-menu',
|
|
30
30
|
actions: (node) =>
|
|
31
|
-
|
|
31
|
+
Atom.make((get) =>
|
|
32
32
|
Function.pipe(
|
|
33
33
|
get(node),
|
|
34
34
|
Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
|
|
@@ -55,7 +55,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
|
|
|
55
55
|
createExtension({
|
|
56
56
|
id: 'user-account',
|
|
57
57
|
connector: (node) =>
|
|
58
|
-
|
|
58
|
+
Atom.make((get) =>
|
|
59
59
|
Function.pipe(
|
|
60
60
|
get(node),
|
|
61
61
|
Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
|
|
@@ -112,7 +112,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
|
|
|
112
112
|
id: 'spaces-root',
|
|
113
113
|
position: 'hoist',
|
|
114
114
|
connector: (node) =>
|
|
115
|
-
|
|
115
|
+
Atom.make((get) =>
|
|
116
116
|
Function.pipe(
|
|
117
117
|
get(node),
|
|
118
118
|
Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
|
|
@@ -138,7 +138,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
|
|
|
138
138
|
createExtension({
|
|
139
139
|
id: 'spaces',
|
|
140
140
|
connector: (node) => {
|
|
141
|
-
const count =
|
|
141
|
+
const count = Atom.make((get) => {
|
|
142
142
|
let value = 3;
|
|
143
143
|
const interval = setInterval(() => {
|
|
144
144
|
if (value >= 10) {
|
|
@@ -153,7 +153,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
|
|
|
153
153
|
return value;
|
|
154
154
|
});
|
|
155
155
|
|
|
156
|
-
return
|
|
156
|
+
return Atom.make((get) =>
|
|
157
157
|
Function.pipe(
|
|
158
158
|
get(node),
|
|
159
159
|
Option.flatMap((node) => (node.id === 'spaces-root' ? Option.some(node) : Option.none())),
|
|
@@ -179,7 +179,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
|
|
|
179
179
|
createExtension({
|
|
180
180
|
id: 'space-actions',
|
|
181
181
|
actions: (node) =>
|
|
182
|
-
|
|
182
|
+
Atom.make((get) =>
|
|
183
183
|
Function.pipe(
|
|
184
184
|
get(node),
|
|
185
185
|
Option.flatMap((node) => (node.type === 'space' ? Option.some(node) : Option.none())),
|
|
@@ -205,7 +205,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
|
|
|
205
205
|
createExtension({
|
|
206
206
|
id: 'objects',
|
|
207
207
|
connector: (node) => {
|
|
208
|
-
const count =
|
|
208
|
+
const count = Atom.make((get) => {
|
|
209
209
|
let value = 3;
|
|
210
210
|
const interval = setInterval(() => {
|
|
211
211
|
if (value >= 20) {
|
|
@@ -220,7 +220,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
|
|
|
220
220
|
return value;
|
|
221
221
|
});
|
|
222
222
|
|
|
223
|
-
return
|
|
223
|
+
return Atom.make((get) =>
|
|
224
224
|
Function.pipe(
|
|
225
225
|
get(node),
|
|
226
226
|
Option.flatMap((node) => (node.type === 'space' ? Option.some(node) : Option.none())),
|
|
@@ -245,7 +245,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
|
|
|
245
245
|
createExtension({
|
|
246
246
|
id: 'object-actions',
|
|
247
247
|
actions: (node) =>
|
|
248
|
-
|
|
248
|
+
Atom.make((get) =>
|
|
249
249
|
Function.pipe(
|
|
250
250
|
get(node),
|
|
251
251
|
Option.flatMap((node) => (node.type === 'object' ? Option.some(node) : Option.none())),
|
package/src/testing/generator.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
|
|
7
7
|
import { type NodeArg } from '@dxos/app-graph';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { Obj, Type } from '@dxos/echo';
|
|
9
|
+
import { type Live } from '@dxos/live-object';
|
|
10
10
|
import { faker } from '@dxos/random';
|
|
11
11
|
import { range } from '@dxos/util';
|
|
12
12
|
|
|
@@ -58,15 +58,17 @@ export const defaultGenerators: { [type: string]: ObjectDataGenerator } = {
|
|
|
58
58
|
|
|
59
59
|
project: {
|
|
60
60
|
createSchema: () =>
|
|
61
|
-
|
|
62
|
-
typename: 'example.com/type/Project',
|
|
63
|
-
version: '0.1.0',
|
|
64
|
-
})({
|
|
61
|
+
Schema.Struct({
|
|
65
62
|
title: Schema.String,
|
|
66
63
|
repo: Schema.String,
|
|
67
64
|
status: Schema.String,
|
|
68
65
|
priority: Schema.Number,
|
|
69
|
-
})
|
|
66
|
+
}).pipe(
|
|
67
|
+
Type.Obj({
|
|
68
|
+
typename: 'example.com/type/Project',
|
|
69
|
+
version: '0.1.0',
|
|
70
|
+
}),
|
|
71
|
+
),
|
|
70
72
|
|
|
71
73
|
createData: () => ({
|
|
72
74
|
title: faker.commerce.productName(),
|