@dxos/plugin-navtree 0.8.2-main.5ca3450 → 0.8.2-main.600d381
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/{chunk-FBQKXPOR.mjs → chunk-ZULGSU3L.mjs} +239 -204
- package/dist/lib/browser/chunk-ZULGSU3L.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +2 -2
- package/dist/lib/browser/index.mjs.map +2 -2
- package/dist/lib/browser/{keyboard-IQXHKUWM.mjs → keyboard-2KXRP22I.mjs} +2 -2
- package/dist/lib/browser/{keyboard-IQXHKUWM.mjs.map → keyboard-2KXRP22I.mjs.map} +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-FQEYRV4Q.mjs → react-surface-BVZN7664.mjs} +2 -2
- package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts.map +1 -0
- package/dist/types/src/components/CommandsDialog/CommandsTrigger.d.ts.map +1 -0
- package/dist/types/src/components/CommandsDialog/index.d.ts +3 -0
- package/dist/types/src/components/CommandsDialog/index.d.ts.map +1 -0
- package/dist/types/src/components/NavTree/NavTree.d.ts +8 -0
- package/dist/types/src/components/NavTree/NavTree.d.ts.map +1 -0
- package/dist/types/src/components/NavTree/NavTree.stories.d.ts +8 -0
- package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +1 -0
- package/dist/types/src/components/NavTree/index.d.ts +2 -0
- package/dist/types/src/components/NavTree/index.d.ts.map +1 -0
- package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeContext.d.ts.map +1 -1
- package/dist/types/src/components/{NavTreeItemAction.d.ts → NavTreeItem/NavTreeItemAction.d.ts} +2 -3
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts.map +1 -0
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +8 -0
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +1 -0
- package/dist/types/src/components/{NavTreeItemColumns.d.ts → NavTreeItem/NavTreeItemColumns.d.ts} +1 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +1 -0
- package/dist/types/src/components/NavTreeItem/index.d.ts +3 -0
- package/dist/types/src/components/NavTreeItem/index.d.ts.map +1 -0
- package/dist/types/src/components/Sidebar/L0Menu.d.ts +13 -0
- package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -0
- package/dist/types/src/components/Sidebar/L1Panel.d.ts +15 -0
- package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -0
- package/dist/types/src/components/Sidebar/index.d.ts +3 -0
- package/dist/types/src/components/Sidebar/index.d.ts.map +1 -0
- package/dist/types/src/components/{UserAccountAvatar.d.ts → UserAccountAvatar/UserAccountAvatar.d.ts} +1 -1
- package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.d.ts.map +1 -0
- package/dist/types/src/components/{UserAccountAvatar.stories.d.ts → UserAccountAvatar/UserAccountAvatar.stories.d.ts} +1 -2
- package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts.map +1 -0
- package/dist/types/src/components/UserAccountAvatar/index.d.ts +2 -0
- package/dist/types/src/components/UserAccountAvatar/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +0 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/types.d.ts +14 -15
- package/dist/types/src/components/types.d.ts.map +1 -1
- package/dist/types/src/testing/app-graph-builder.d.ts +11 -0
- package/dist/types/src/testing/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/testing/generator.d.ts +1 -0
- package/dist/types/src/testing/generator.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +1 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -1
- package/dist/types/src/util.d.ts +1 -1
- package/package.json +32 -31
- package/src/capabilities/keyboard.ts +1 -1
- package/src/components/{CommandsDialog.tsx → CommandsDialog/CommandsDialog.tsx} +2 -2
- package/src/components/{CommandsTrigger.tsx → CommandsDialog/CommandsTrigger.tsx} +1 -1
- package/src/components/CommandsDialog/index.ts +6 -0
- package/src/components/NavTree/NavTree.stories.tsx +87 -0
- package/src/components/{NavTree.tsx → NavTree/NavTree.tsx} +24 -11
- package/src/components/NavTree/index.ts +5 -0
- package/src/components/NavTreeContainer.tsx +35 -16
- package/src/components/NavTreeContext.tsx +1 -1
- package/src/components/{NavTreeItemAction.stories.tsx → NavTreeItem/NavTreeItemAction.stories.tsx} +12 -6
- package/src/components/{NavTreeItemAction.tsx → NavTreeItem/NavTreeItemAction.tsx} +13 -14
- package/src/components/{NavTreeItemColumns.tsx → NavTreeItem/NavTreeItemColumns.tsx} +5 -5
- package/src/components/NavTreeItem/index.ts +6 -0
- package/src/components/{L0Menu.tsx → Sidebar/L0Menu.tsx} +182 -129
- package/src/components/{L1Panels.tsx → Sidebar/L1Panel.tsx} +29 -48
- package/src/components/Sidebar/index.ts +6 -0
- package/src/components/{UserAccountAvatar.stories.tsx → UserAccountAvatar/UserAccountAvatar.stories.tsx} +5 -5
- package/src/components/{UserAccountAvatar.tsx → UserAccountAvatar/UserAccountAvatar.tsx} +6 -6
- package/src/components/UserAccountAvatar/index.ts +5 -0
- package/src/components/index.ts +0 -1
- package/src/components/types.ts +13 -15
- package/src/testing/app-graph-builder.ts +158 -0
- package/src/testing/generator.ts +2 -1
- package/src/testing/index.ts +1 -0
- package/src/translations.ts +1 -1
- package/dist/lib/browser/chunk-FBQKXPOR.mjs.map +0 -7
- package/dist/types/src/components/CommandsDialog.d.ts.map +0 -1
- package/dist/types/src/components/CommandsTrigger.d.ts.map +0 -1
- package/dist/types/src/components/L0Menu.d.ts +0 -10
- package/dist/types/src/components/L0Menu.d.ts.map +0 -1
- package/dist/types/src/components/L1Panels.d.ts +0 -14
- package/dist/types/src/components/L1Panels.d.ts.map +0 -1
- package/dist/types/src/components/NavTree.d.ts +0 -5
- package/dist/types/src/components/NavTree.d.ts.map +0 -1
- package/dist/types/src/components/NavTree.stories.d.ts +0 -7
- package/dist/types/src/components/NavTree.stories.d.ts.map +0 -1
- package/dist/types/src/components/NavTreeItemAction.d.ts.map +0 -1
- package/dist/types/src/components/NavTreeItemAction.stories.d.ts +0 -41
- package/dist/types/src/components/NavTreeItemAction.stories.d.ts.map +0 -1
- package/dist/types/src/components/NavTreeItemColumns.d.ts.map +0 -1
- package/dist/types/src/components/UserAccountAvatar.d.ts.map +0 -1
- package/dist/types/src/components/UserAccountAvatar.stories.d.ts.map +0 -1
- package/dist/types/src/stories/Graph.stories.d.ts +0 -7
- package/dist/types/src/stories/Graph.stories.d.ts.map +0 -1
- package/dist/types/src/stories/StorybookNavTree.d.ts +0 -4
- package/dist/types/src/stories/StorybookNavTree.d.ts.map +0 -1
- package/src/components/NavTree.stories.tsx +0 -107
- package/src/stories/Graph.stories.tsx +0 -130
- package/src/stories/StorybookNavTree.tsx +0 -63
- /package/dist/lib/browser/{react-surface-FQEYRV4Q.mjs.map → react-surface-BVZN7664.mjs.map} +0 -0
- /package/dist/types/src/components/{CommandsDialog.d.ts → CommandsDialog/CommandsDialog.d.ts} +0 -0
- /package/dist/types/src/components/{CommandsTrigger.d.ts → CommandsDialog/CommandsTrigger.d.ts} +0 -0
package/dist/types/src/util.d.ts
CHANGED
|
@@ -9,5 +9,5 @@ export declare const getActions: (graph: Graph, node: Node) => FlattenedActions;
|
|
|
9
9
|
export declare const expandChildrenAndActions: (graph: Graph, node: Node) => Promise<[void, [void, void]]>;
|
|
10
10
|
export declare const expandChildren: (graph: Graph, node: Node) => Promise<void>;
|
|
11
11
|
export declare const expandActions: (graph: Graph, node: Node) => Promise<[void, void]>;
|
|
12
|
-
export declare const l0ItemType: (item: Node<any>) => "
|
|
12
|
+
export declare const l0ItemType: (item: Node<any>) => "collection" | "action" | "link" | "tab";
|
|
13
13
|
//# sourceMappingURL=util.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-navtree",
|
|
3
|
-
"version": "0.8.2-main.
|
|
3
|
+
"version": "0.8.2-main.600d381",
|
|
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",
|
|
@@ -30,29 +30,28 @@
|
|
|
30
30
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
|
31
31
|
"date-fns": "^3.3.1",
|
|
32
32
|
"effect": "^3.13.3",
|
|
33
|
-
"@dxos/app-
|
|
34
|
-
"@dxos/
|
|
35
|
-
"@dxos/
|
|
36
|
-
"@dxos/
|
|
37
|
-
"@dxos/
|
|
38
|
-
"@dxos/
|
|
39
|
-
"@dxos/
|
|
40
|
-
"@dxos/live-object": "0.8.2-main.
|
|
41
|
-
"@dxos/
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/plugin-
|
|
44
|
-
"@dxos/plugin-deck": "0.8.2-main.
|
|
45
|
-
"@dxos/plugin-
|
|
46
|
-
"@dxos/
|
|
47
|
-
"@dxos/
|
|
48
|
-
"@dxos/
|
|
49
|
-
"@dxos/react-ui-list": "0.8.2-main.
|
|
50
|
-
"@dxos/
|
|
51
|
-
"@dxos/react-ui-
|
|
52
|
-
"@dxos/react-ui-
|
|
53
|
-
"@dxos/
|
|
54
|
-
"@dxos/react-ui-
|
|
55
|
-
"@dxos/util": "0.8.2-main.5ca3450"
|
|
33
|
+
"@dxos/app-graph": "0.8.2-main.600d381",
|
|
34
|
+
"@dxos/async": "0.8.2-main.600d381",
|
|
35
|
+
"@dxos/echo-schema": "0.8.2-main.600d381",
|
|
36
|
+
"@dxos/keyboard": "0.8.2-main.600d381",
|
|
37
|
+
"@dxos/app-framework": "0.8.2-main.600d381",
|
|
38
|
+
"@dxos/debug": "0.8.2-main.600d381",
|
|
39
|
+
"@dxos/invariant": "0.8.2-main.600d381",
|
|
40
|
+
"@dxos/live-object": "0.8.2-main.600d381",
|
|
41
|
+
"@dxos/log": "0.8.2-main.600d381",
|
|
42
|
+
"@dxos/local-storage": "0.8.2-main.600d381",
|
|
43
|
+
"@dxos/plugin-client": "0.8.2-main.600d381",
|
|
44
|
+
"@dxos/plugin-deck": "0.8.2-main.600d381",
|
|
45
|
+
"@dxos/plugin-graph": "0.8.2-main.600d381",
|
|
46
|
+
"@dxos/react-client": "0.8.2-main.600d381",
|
|
47
|
+
"@dxos/protocols": "0.8.2-main.600d381",
|
|
48
|
+
"@dxos/plugin-observability": "0.8.2-main.600d381",
|
|
49
|
+
"@dxos/react-ui-list": "0.8.2-main.600d381",
|
|
50
|
+
"@dxos/react-ui-searchlist": "0.8.2-main.600d381",
|
|
51
|
+
"@dxos/react-ui-stack": "0.8.2-main.600d381",
|
|
52
|
+
"@dxos/react-ui-tabs": "0.8.2-main.600d381",
|
|
53
|
+
"@dxos/util": "0.8.2-main.600d381",
|
|
54
|
+
"@dxos/react-ui-menu": "0.8.2-main.600d381"
|
|
56
55
|
},
|
|
57
56
|
"devDependencies": {
|
|
58
57
|
"@phosphor-icons/react": "^2.1.5",
|
|
@@ -61,19 +60,21 @@
|
|
|
61
60
|
"react": "~18.2.0",
|
|
62
61
|
"react-dom": "~18.2.0",
|
|
63
62
|
"vite": "5.4.7",
|
|
64
|
-
"@dxos/
|
|
65
|
-
"@dxos/
|
|
66
|
-
"@dxos/random": "0.8.2-main.
|
|
67
|
-
"@dxos/
|
|
68
|
-
"@dxos/
|
|
63
|
+
"@dxos/echo-signals": "0.8.2-main.600d381",
|
|
64
|
+
"@dxos/plugin-storybook-layout": "0.8.2-main.600d381",
|
|
65
|
+
"@dxos/random": "0.8.2-main.600d381",
|
|
66
|
+
"@dxos/plugin-theme": "0.8.2-main.600d381",
|
|
67
|
+
"@dxos/react-ui": "0.8.2-main.600d381",
|
|
68
|
+
"@dxos/storybook-utils": "0.8.2-main.600d381",
|
|
69
|
+
"@dxos/react-ui-theme": "0.8.2-main.600d381"
|
|
69
70
|
},
|
|
70
71
|
"peerDependencies": {
|
|
71
72
|
"@phosphor-icons/react": "^2.1.5",
|
|
72
73
|
"effect": "^3.13.3",
|
|
73
74
|
"react": "~18.2.0",
|
|
74
75
|
"react-dom": "~18.2.0",
|
|
75
|
-
"@dxos/react-ui": "0.8.2-main.
|
|
76
|
-
"@dxos/react-ui-theme": "0.8.2-main.
|
|
76
|
+
"@dxos/react-ui": "0.8.2-main.600d381",
|
|
77
|
+
"@dxos/react-ui-theme": "0.8.2-main.600d381"
|
|
77
78
|
},
|
|
78
79
|
"publishConfig": {
|
|
79
80
|
"access": "public"
|
|
@@ -35,7 +35,7 @@ export default (context: PluginsContext) => {
|
|
|
35
35
|
Keyboard.singleton.getContext(path.slice(0, -1).join('/')).bind({
|
|
36
36
|
shortcut,
|
|
37
37
|
handler: () => {
|
|
38
|
-
void node.data({ node, caller: KEY_BINDING });
|
|
38
|
+
void node.data({ parent: node, caller: KEY_BINDING });
|
|
39
39
|
},
|
|
40
40
|
data: node.properties.label,
|
|
41
41
|
});
|
|
@@ -12,7 +12,7 @@ import { SearchList } from '@dxos/react-ui-searchlist';
|
|
|
12
12
|
import { descriptionText, mx } from '@dxos/react-ui-theme';
|
|
13
13
|
import { getHostPlatform } from '@dxos/util';
|
|
14
14
|
|
|
15
|
-
import { KEY_BINDING, NAVTREE_PLUGIN } from '
|
|
15
|
+
import { KEY_BINDING, NAVTREE_PLUGIN } from '../../meta';
|
|
16
16
|
|
|
17
17
|
// TODO(wittjosiah): This probably deserves its own plugin but for now it lives here w/ other navigation UI.
|
|
18
18
|
export const CommandsDialogContent = ({ selected: initial }: { selected?: string }) => {
|
|
@@ -85,7 +85,7 @@ export const CommandsDialogContent = ({ selected: initial }: { selected?: string
|
|
|
85
85
|
void dispatch(createIntent(LayoutAction.UpdateDialog, { part: 'dialog', options: { state: false } }));
|
|
86
86
|
setTimeout(() => {
|
|
87
87
|
const node = graph.nodes(group ?? action, { relation: 'inbound' })[0];
|
|
88
|
-
void (node && isAction(action) && action.data({ node, caller: KEY_BINDING }));
|
|
88
|
+
void (node && isAction(action) && action.data({ parent: node, caller: KEY_BINDING }));
|
|
89
89
|
});
|
|
90
90
|
}}
|
|
91
91
|
classNames='flex items-center gap-2'
|
|
@@ -9,7 +9,7 @@ import { createIntent, LayoutAction, useIntentDispatcher } from '@dxos/app-frame
|
|
|
9
9
|
import { Button, useTranslation } from '@dxos/react-ui';
|
|
10
10
|
import { getSize } from '@dxos/react-ui-theme';
|
|
11
11
|
|
|
12
|
-
import { COMMANDS_DIALOG, NAVTREE_PLUGIN } from '
|
|
12
|
+
import { COMMANDS_DIALOG, NAVTREE_PLUGIN } from '../../meta';
|
|
13
13
|
|
|
14
14
|
// TODO(thure): Refactor to be handled by a more appropriate plugin.
|
|
15
15
|
export const CommandsTrigger = () => {
|
|
@@ -0,0 +1,87 @@
|
|
|
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
|
+
contributes,
|
|
13
|
+
Capabilities,
|
|
14
|
+
IntentPlugin,
|
|
15
|
+
createResolver,
|
|
16
|
+
defineCapability,
|
|
17
|
+
LayoutAction,
|
|
18
|
+
SettingsPlugin,
|
|
19
|
+
useCapability,
|
|
20
|
+
} from '@dxos/app-framework';
|
|
21
|
+
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
22
|
+
import { live } from '@dxos/live-object';
|
|
23
|
+
import { GraphPlugin } from '@dxos/plugin-graph';
|
|
24
|
+
import { StorybookLayoutPlugin } from '@dxos/plugin-storybook-layout';
|
|
25
|
+
import { ThemePlugin } from '@dxos/plugin-theme';
|
|
26
|
+
import { faker } from '@dxos/random';
|
|
27
|
+
import { Main } from '@dxos/react-ui';
|
|
28
|
+
import { defaultTx } from '@dxos/react-ui-theme';
|
|
29
|
+
import { withLayout } from '@dxos/storybook-utils';
|
|
30
|
+
|
|
31
|
+
import { NavTreePlugin } from '../../NavTreePlugin';
|
|
32
|
+
import { storybookGraphBuilders } from '../../testing';
|
|
33
|
+
import { NavTreeContainer } from '../NavTreeContainer';
|
|
34
|
+
|
|
35
|
+
faker.seed(1234);
|
|
36
|
+
|
|
37
|
+
const StoryState = defineCapability<{ tab: string }>('story-state');
|
|
38
|
+
|
|
39
|
+
const DefaultStory = () => {
|
|
40
|
+
const state = useCapability(StoryState);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Main.NavigationSidebar label='Navigation' classNames='grid'>
|
|
44
|
+
<NavTreeContainer tab={state.tab} />
|
|
45
|
+
</Main.NavigationSidebar>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const meta: Meta<typeof NavTreeContainer> = {
|
|
50
|
+
title: 'plugins/plugin-navtree/NavTree',
|
|
51
|
+
component: NavTreeContainer,
|
|
52
|
+
render: DefaultStory,
|
|
53
|
+
decorators: [
|
|
54
|
+
withPluginManager({
|
|
55
|
+
plugins: [
|
|
56
|
+
ThemePlugin({ tx: defaultTx }),
|
|
57
|
+
StorybookLayoutPlugin({ initialState: { sidebarState: 'expanded' } }),
|
|
58
|
+
GraphPlugin(),
|
|
59
|
+
IntentPlugin(),
|
|
60
|
+
SettingsPlugin(),
|
|
61
|
+
NavTreePlugin(),
|
|
62
|
+
],
|
|
63
|
+
capabilities: (context) => [
|
|
64
|
+
contributes(StoryState, live({ tab: 'default' })),
|
|
65
|
+
contributes(Capabilities.IntentResolver, [
|
|
66
|
+
createResolver({
|
|
67
|
+
intent: LayoutAction.UpdateLayout,
|
|
68
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.SwitchWorkspace.fields.input> =>
|
|
69
|
+
Schema.is(LayoutAction.SwitchWorkspace.fields.input)(data),
|
|
70
|
+
resolve: ({ subject }) => {
|
|
71
|
+
const state = context.requestCapability(StoryState);
|
|
72
|
+
state.tab = subject;
|
|
73
|
+
},
|
|
74
|
+
}),
|
|
75
|
+
]),
|
|
76
|
+
contributes(Capabilities.AppGraphBuilder, storybookGraphBuilders),
|
|
77
|
+
],
|
|
78
|
+
}),
|
|
79
|
+
withLayout({ fullscreen: true }),
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export default meta;
|
|
84
|
+
|
|
85
|
+
type Story = StoryObj<typeof NavTreeContainer>;
|
|
86
|
+
|
|
87
|
+
export const Default: Story = {};
|
|
@@ -4,31 +4,43 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { useMemo } from 'react';
|
|
6
6
|
|
|
7
|
+
import { type TreeProps } from '@dxos/react-ui-list';
|
|
7
8
|
import { Tabs } from '@dxos/react-ui-tabs';
|
|
8
9
|
import { byPosition } from '@dxos/util';
|
|
9
10
|
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { useNavTreeContext } from '
|
|
13
|
-
import { type
|
|
14
|
-
import { useLoadDescendents } from '../hooks';
|
|
11
|
+
import { useLoadDescendents } from '../../hooks';
|
|
12
|
+
import { type NavTreeItemGraphNode } from '../../types';
|
|
13
|
+
import { useNavTreeContext } from '../NavTreeContext';
|
|
14
|
+
import { L0Menu, L1Panels, type L1PanelsProps } from '../Sidebar';
|
|
15
15
|
|
|
16
16
|
export const NAV_TREE_ITEM = 'NavTreeItem';
|
|
17
17
|
|
|
18
|
-
export
|
|
18
|
+
export type NavTreeProps = Pick<TreeProps<NavTreeItemGraphNode>, 'id' | 'root'> & Pick<L1PanelsProps, 'open'>;
|
|
19
|
+
|
|
20
|
+
export const NavTree = ({ id, root, ...props }: NavTreeProps) => {
|
|
19
21
|
const { tab, getItems, onBack } = useNavTreeContext();
|
|
20
|
-
const topLevelActions = getItems(root, '
|
|
22
|
+
const topLevelActions = getItems(root, 'menu').toSorted((a, b) => byPosition(a.properties, b.properties));
|
|
21
23
|
const topLevelCollections = getItems(root, 'collection');
|
|
22
24
|
const topLevelWorkspaces = getItems(root, 'workspace');
|
|
23
25
|
const topLevelNavigation = getItems(root, 'navigation');
|
|
24
26
|
const l0Items = useMemo(
|
|
25
|
-
() => [
|
|
26
|
-
|
|
27
|
+
() => [
|
|
28
|
+
// prettier-ignore
|
|
29
|
+
...topLevelCollections,
|
|
30
|
+
...topLevelWorkspaces,
|
|
31
|
+
...topLevelNavigation,
|
|
32
|
+
],
|
|
33
|
+
[topLevelCollections, topLevelWorkspaces, topLevelNavigation],
|
|
27
34
|
);
|
|
28
35
|
const pinnedItems = getItems(root, 'pin-end').toSorted((a, b) => byPosition(a.properties, b.properties));
|
|
29
36
|
const userAccountItem = getItems(root, 'user-account')[0];
|
|
30
37
|
const topLevelItems = useMemo(
|
|
31
|
-
() => [
|
|
38
|
+
() => [
|
|
39
|
+
// prettier-ignore
|
|
40
|
+
...l0Items,
|
|
41
|
+
...pinnedItems,
|
|
42
|
+
...(userAccountItem ? [userAccountItem] : []),
|
|
43
|
+
],
|
|
32
44
|
[l0Items, pinnedItems, userAccountItem],
|
|
33
45
|
);
|
|
34
46
|
|
|
@@ -39,13 +51,14 @@ export const NavTree = ({ id, root }: NavTreeProps) => {
|
|
|
39
51
|
// NOTE(thure): 74px (rather than rem) is intentional in order to match the size of macOS windowing controls
|
|
40
52
|
<Tabs.Root value={tab} orientation='vertical' verticalVariant='stateless' classNames='relative'>
|
|
41
53
|
<L0Menu
|
|
54
|
+
menuActions={topLevelActions}
|
|
42
55
|
topLevelItems={l0Items}
|
|
43
56
|
pinnedItems={pinnedItems}
|
|
44
57
|
userAccountItem={userAccountItem}
|
|
45
58
|
path={path}
|
|
46
59
|
parent={root}
|
|
47
60
|
/>
|
|
48
|
-
<L1Panels topLevelItems={topLevelItems} path={path} currentItemId={tab} onBack={onBack} />
|
|
61
|
+
<L1Panels topLevelItems={topLevelItems} path={path} currentItemId={tab} onBack={onBack} {...props} />
|
|
49
62
|
</Tabs.Root>
|
|
50
63
|
);
|
|
51
64
|
};
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import { isAction, isActionLike, type Node } from '@dxos/app-graph';
|
|
20
20
|
import { PLANK_COMPANION_TYPE } from '@dxos/plugin-deck/types';
|
|
21
21
|
import { isEchoObject, isSpace } from '@dxos/react-client/echo';
|
|
22
|
-
import { useMediaQuery } from '@dxos/react-ui';
|
|
22
|
+
import { useMediaQuery, useSidebars } from '@dxos/react-ui';
|
|
23
23
|
import { isTreeData, type TreeData, type PropsFromTreeItem } from '@dxos/react-ui-list';
|
|
24
24
|
import { mx } from '@dxos/react-ui-theme';
|
|
25
25
|
import { arrayMove } from '@dxos/util';
|
|
@@ -28,6 +28,7 @@ import { NAV_TREE_ITEM, NavTree } from './NavTree';
|
|
|
28
28
|
import { NavTreeContext } from './NavTreeContext';
|
|
29
29
|
import { type NavTreeContextValue } from './types';
|
|
30
30
|
import { NavTreeCapabilities } from '../capabilities';
|
|
31
|
+
import { NAVTREE_PLUGIN } from '../meta';
|
|
31
32
|
import { type NavTreeItemGraphNode } from '../types';
|
|
32
33
|
import {
|
|
33
34
|
expandActions,
|
|
@@ -58,8 +59,9 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
58
59
|
const [isLg] = useMediaQuery('lg', { ssr: false });
|
|
59
60
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
60
61
|
const { graph } = useAppGraph();
|
|
61
|
-
const layout = useLayout();
|
|
62
62
|
const { isOpen, isCurrent, isAlternateTree, setItem } = useCapability(NavTreeCapabilities.State);
|
|
63
|
+
const layout = useLayout();
|
|
64
|
+
const { navigationSidebarState } = useSidebars(NAVTREE_PLUGIN);
|
|
63
65
|
|
|
64
66
|
const getActions = useCallback((node: Node) => naturalGetActions(graph, node), [graph]);
|
|
65
67
|
|
|
@@ -120,7 +122,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
120
122
|
[graph],
|
|
121
123
|
);
|
|
122
124
|
|
|
123
|
-
const
|
|
125
|
+
const handleOpenChange = useCallback(
|
|
124
126
|
({ item: { id }, path, open }: { item: Node; path: string[]; open: boolean }) => {
|
|
125
127
|
// TODO(thure): This might become a localstorage leak; openItemIds that no longer exist should be removed from this map.
|
|
126
128
|
setItem(path, 'open', open);
|
|
@@ -133,9 +135,26 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
133
135
|
[graph],
|
|
134
136
|
);
|
|
135
137
|
|
|
136
|
-
const
|
|
138
|
+
const handleTabChange = useCallback(
|
|
137
139
|
async (node: NavTreeItemGraphNode) => {
|
|
140
|
+
await dispatch(
|
|
141
|
+
createIntent(LayoutAction.UpdateSidebar, {
|
|
142
|
+
part: 'sidebar',
|
|
143
|
+
options: {
|
|
144
|
+
state:
|
|
145
|
+
node.id === tab
|
|
146
|
+
? navigationSidebarState === 'expanded'
|
|
147
|
+
? isLg
|
|
148
|
+
? 'collapsed'
|
|
149
|
+
: 'closed'
|
|
150
|
+
: 'expanded'
|
|
151
|
+
: 'expanded',
|
|
152
|
+
},
|
|
153
|
+
}),
|
|
154
|
+
);
|
|
155
|
+
|
|
138
156
|
await dispatch(createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: node.id }));
|
|
157
|
+
|
|
139
158
|
// Open the first item if the workspace is empty.
|
|
140
159
|
if (layout.active.length === 0) {
|
|
141
160
|
const [item] = getItems(node).filter((node) => !isActionLike(node));
|
|
@@ -144,7 +163,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
144
163
|
}
|
|
145
164
|
}
|
|
146
165
|
},
|
|
147
|
-
[dispatch, layout],
|
|
166
|
+
[dispatch, layout.active, tab, navigationSidebarState, isLg],
|
|
148
167
|
);
|
|
149
168
|
|
|
150
169
|
const canDrop = useCallback((source: TreeData, target: TreeData) => {
|
|
@@ -168,7 +187,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
168
187
|
|
|
169
188
|
if (isAction(node)) {
|
|
170
189
|
const [parent] = graph.nodes(node, { relation: 'inbound' });
|
|
171
|
-
void (parent && node.data({
|
|
190
|
+
void (parent && node.data({ parent, caller: NAV_TREE_ITEM }));
|
|
172
191
|
return;
|
|
173
192
|
}
|
|
174
193
|
|
|
@@ -201,7 +220,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
201
220
|
[graph, dispatch, isCurrent, isLg],
|
|
202
221
|
);
|
|
203
222
|
|
|
204
|
-
const
|
|
223
|
+
const handleBack = useCallback(
|
|
205
224
|
() => dispatch(createIntent(LayoutAction.RevertWorkspace, { part: 'workspace', options: { revert: true } })),
|
|
206
225
|
[dispatch],
|
|
207
226
|
);
|
|
@@ -275,8 +294,6 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
275
294
|
const navTreeContextValue = useMemo(
|
|
276
295
|
() => ({
|
|
277
296
|
tab,
|
|
278
|
-
onTabChange,
|
|
279
|
-
onBack,
|
|
280
297
|
getActions,
|
|
281
298
|
loadDescendents,
|
|
282
299
|
renderItemEnd,
|
|
@@ -286,16 +303,16 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
286
303
|
getProps,
|
|
287
304
|
isCurrent,
|
|
288
305
|
isOpen,
|
|
289
|
-
onOpenChange,
|
|
290
306
|
canDrop,
|
|
291
|
-
onSelect: handleSelect,
|
|
292
307
|
isAlternateTree,
|
|
293
308
|
setAlternateTree,
|
|
309
|
+
onTabChange: handleTabChange,
|
|
310
|
+
onOpenChange: handleOpenChange,
|
|
311
|
+
onSelect: handleSelect,
|
|
312
|
+
onBack: handleBack,
|
|
294
313
|
}),
|
|
295
314
|
[
|
|
296
315
|
tab,
|
|
297
|
-
onTabChange,
|
|
298
|
-
onBack,
|
|
299
316
|
getActions,
|
|
300
317
|
loadDescendents,
|
|
301
318
|
renderItemEnd,
|
|
@@ -305,17 +322,19 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
305
322
|
getProps,
|
|
306
323
|
isCurrent,
|
|
307
324
|
isOpen,
|
|
308
|
-
onOpenChange,
|
|
309
325
|
canDrop,
|
|
310
|
-
handleSelect,
|
|
311
326
|
isAlternateTree,
|
|
312
327
|
setAlternateTree,
|
|
328
|
+
handleTabChange,
|
|
329
|
+
handleOpenChange,
|
|
330
|
+
handleSelect,
|
|
331
|
+
handleBack,
|
|
313
332
|
],
|
|
314
333
|
);
|
|
315
334
|
|
|
316
335
|
return (
|
|
317
336
|
<NavTreeContext.Provider value={navTreeContextValue}>
|
|
318
|
-
<NavTree
|
|
337
|
+
<NavTree id={graph.root.id} root={graph.root} open={layout.sidebarOpen} />
|
|
319
338
|
</NavTreeContext.Provider>
|
|
320
339
|
);
|
|
321
340
|
});
|
|
@@ -10,4 +10,4 @@ import { type NavTreeContextValue } from './types';
|
|
|
10
10
|
|
|
11
11
|
export const NavTreeContext = createContext<NavTreeContextValue | null>(null);
|
|
12
12
|
|
|
13
|
-
export const useNavTreeContext = () => useContext(NavTreeContext) ?? raise(new Error('NavTreeContext
|
|
13
|
+
export const useNavTreeContext = () => useContext(NavTreeContext) ?? raise(new Error('Missing NavTreeContext'));
|
package/src/components/{NavTreeItemAction.stories.tsx → NavTreeItem/NavTreeItemAction.stories.tsx}
RENAMED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
6
|
|
|
7
|
+
import { type Meta, type StoryObj } from '@storybook/react';
|
|
8
|
+
|
|
7
9
|
import { type NodeArg } from '@dxos/app-graph';
|
|
8
10
|
import { faker } from '@dxos/random';
|
|
9
11
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
@@ -37,19 +39,23 @@ const menuActions = faker.helpers.multiple(
|
|
|
37
39
|
{ count: 20 },
|
|
38
40
|
);
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
const meta: Meta<typeof NavTreeItemAction> = {
|
|
41
43
|
title: 'plugins/plugin-navtree/NavTreeItemAction',
|
|
42
44
|
component: NavTreeItemAction,
|
|
43
|
-
decorators: [withTheme, withLayout(
|
|
45
|
+
decorators: [withTheme, withLayout()],
|
|
44
46
|
args: {
|
|
45
47
|
icon: 'ph--list--regular',
|
|
46
48
|
parent,
|
|
47
49
|
menuActions,
|
|
48
50
|
label: 'Select action',
|
|
49
|
-
onAction: (action) => {
|
|
50
|
-
console.log(action);
|
|
51
|
-
},
|
|
52
51
|
} satisfies Partial<NavTreeItemActionMenuProps>,
|
|
52
|
+
parameters: {
|
|
53
|
+
layout: 'centered',
|
|
54
|
+
},
|
|
53
55
|
};
|
|
54
56
|
|
|
55
|
-
export
|
|
57
|
+
export default meta;
|
|
58
|
+
|
|
59
|
+
type Story = StoryObj<typeof meta>;
|
|
60
|
+
|
|
61
|
+
export const Default: Story = {};
|
|
@@ -9,8 +9,8 @@ import { useTranslation, toLocalizedString, IconButton, useDensityContext } from
|
|
|
9
9
|
import { DropdownMenu, MenuProvider, type MenuItem } from '@dxos/react-ui-menu';
|
|
10
10
|
import { hoverableControlItem, hoverableOpenControlItem, mx } from '@dxos/react-ui-theme';
|
|
11
11
|
|
|
12
|
-
import { NAVTREE_PLUGIN } from '
|
|
13
|
-
import { type ActionProperties } from '
|
|
12
|
+
import { NAVTREE_PLUGIN } from '../../meta';
|
|
13
|
+
import { type ActionProperties } from '../../types';
|
|
14
14
|
|
|
15
15
|
export type NavTreeItemActionMenuProps = ActionProperties & {
|
|
16
16
|
parent: Node;
|
|
@@ -18,7 +18,6 @@ export type NavTreeItemActionMenuProps = ActionProperties & {
|
|
|
18
18
|
monolithic?: boolean;
|
|
19
19
|
menuActions?: Action[];
|
|
20
20
|
suppressNextTooltip?: MutableRefObject<boolean>;
|
|
21
|
-
onAction?: (action: Action) => void;
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
const fallbackIcon = 'ph--placeholder--regular';
|
|
@@ -33,18 +32,24 @@ const coarseActionButtonProps = {
|
|
|
33
32
|
};
|
|
34
33
|
|
|
35
34
|
export const NavTreeItemActionDropdownMenu = ({
|
|
35
|
+
parent,
|
|
36
36
|
label,
|
|
37
37
|
icon,
|
|
38
38
|
testId,
|
|
39
39
|
menuActions,
|
|
40
|
-
|
|
40
|
+
caller,
|
|
41
41
|
}: NavTreeItemActionMenuProps) => {
|
|
42
42
|
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
43
43
|
const suppressNextTooltip = useRef<boolean>(false);
|
|
44
44
|
const density = useDensityContext();
|
|
45
45
|
return (
|
|
46
|
-
<MenuProvider
|
|
47
|
-
<DropdownMenu.Root
|
|
46
|
+
<MenuProvider>
|
|
47
|
+
<DropdownMenu.Root
|
|
48
|
+
group={parent}
|
|
49
|
+
items={menuActions as MenuItem[]}
|
|
50
|
+
caller={caller}
|
|
51
|
+
suppressNextTooltip={suppressNextTooltip}
|
|
52
|
+
>
|
|
48
53
|
<DropdownMenu.Trigger asChild>
|
|
49
54
|
<IconButton
|
|
50
55
|
{...(density === 'coarse' ? coarseActionButtonProps : fineActionButtonProps)}
|
|
@@ -88,7 +93,7 @@ export const NavTreeItemMonolithicAction = ({
|
|
|
88
93
|
return;
|
|
89
94
|
}
|
|
90
95
|
event.stopPropagation();
|
|
91
|
-
void invoke?.(caller ? {
|
|
96
|
+
void invoke?.(caller ? { parent, caller } : { parent });
|
|
92
97
|
}}
|
|
93
98
|
data-testid={testId}
|
|
94
99
|
/>
|
|
@@ -104,12 +109,6 @@ export const NavTreeItemAction = ({ monolithic, menuActions, parent: node, ...pr
|
|
|
104
109
|
return monolithic && menuActions?.length === 1 ? (
|
|
105
110
|
<NavTreeItemMonolithicAction baseLabel={baseLabel} parent={node} {...menuActions[0]} />
|
|
106
111
|
) : (
|
|
107
|
-
<NavTreeItemActionDropdownMenu
|
|
108
|
-
{...props}
|
|
109
|
-
label={baseLabel}
|
|
110
|
-
parent={node}
|
|
111
|
-
menuActions={menuActions}
|
|
112
|
-
onAction={(action) => action.data?.(props.caller ? { node, caller: props.caller } : { node })}
|
|
113
|
-
/>
|
|
112
|
+
<NavTreeItemActionDropdownMenu {...props} label={baseLabel} parent={node} menuActions={menuActions} />
|
|
114
113
|
);
|
|
115
114
|
};
|
|
@@ -7,12 +7,12 @@ import React, { Fragment, memo } from 'react';
|
|
|
7
7
|
import { isAction } from '@dxos/app-graph';
|
|
8
8
|
import { DensityProvider, Popover, toLocalizedString, Treegrid, useTranslation } from '@dxos/react-ui';
|
|
9
9
|
|
|
10
|
-
import { NAV_TREE_ITEM } from './NavTree';
|
|
11
|
-
import { useNavTreeContext } from './NavTreeContext';
|
|
12
10
|
import { NavTreeItemAction } from './NavTreeItemAction';
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
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
16
|
|
|
17
17
|
export const NavTreeItemColumns = memo(({ path, item, open, density = 'fine' }: NavTreeItemColumnsProps) => {
|
|
18
18
|
const { t } = useTranslation(NAVTREE_PLUGIN);
|