@dxos/plugin-navtree 0.8.4-main.5ea62a8 → 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-6JDBQ25U.mjs → app-graph-builder-OHSCN3GX.mjs} +11 -10
- package/dist/lib/browser/app-graph-builder-OHSCN3GX.mjs.map +7 -0
- package/dist/lib/browser/{chunk-WCARAZ7J.mjs → chunk-5VLWX4PK.mjs} +4 -4
- package/dist/lib/browser/chunk-5VLWX4PK.mjs.map +7 -0
- package/dist/lib/browser/chunk-E6MZBCU5.mjs +19 -0
- package/dist/lib/browser/chunk-E6MZBCU5.mjs.map +7 -0
- package/dist/lib/browser/{chunk-ZKVY35IG.mjs → chunk-UDAINHB6.mjs} +153 -134
- package/dist/lib/browser/chunk-UDAINHB6.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +5 -7
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-N35ZIHFD.mjs → intent-resolver-YUVXVPHG.mjs} +6 -6
- package/dist/lib/browser/intent-resolver-YUVXVPHG.mjs.map +7 -0
- package/dist/lib/browser/{keyboard-HMTMA33N.mjs → keyboard-YJEK2HTH.mjs} +8 -10
- package/dist/lib/browser/{keyboard-HMTMA33N.mjs.map → keyboard-YJEK2HTH.mjs.map} +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-5PZ4XJT7.mjs → react-surface-V6LS3R4L.mjs} +10 -10
- package/dist/lib/browser/react-surface-V6LS3R4L.mjs.map +7 -0
- package/dist/lib/browser/{state-P5DGL7KS.mjs → state-BFD5KJCV.mjs} +7 -7
- package/dist/lib/browser/state-BFD5KJCV.mjs.map +7 -0
- package/dist/types/src/NavTreePlugin.d.ts +1 -1
- package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +12 -9
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- 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/NavTree/NavTree.d.ts.map +1 -1
- package/dist/types/src/components/NavTree/NavTree.stories.d.ts +1 -2
- 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/NavTreeItem/NavTreeItemAction.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +1 -2
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts +1 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/L0Menu.d.ts +2 -0
- package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -1
- package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.d.ts.map +1 -1
- package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts +1 -2
- package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.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/events.d.ts.map +1 -1
- package/dist/types/src/experimental/Tree.d.ts +1 -2
- package/dist/types/src/experimental/Tree.d.ts.map +1 -1
- package/dist/types/src/experimental/Tree.stories.d.ts +2 -3
- package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +2 -3
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/testing/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/testing/generator.d.ts +2 -2
- package/dist/types/src/testing/generator.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +4 -3
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +48 -48
- package/src/NavTreePlugin.tsx +70 -71
- package/src/capabilities/app-graph-builder.ts +8 -7
- package/src/capabilities/capabilities.ts +2 -2
- package/src/capabilities/intent-resolver.ts +1 -1
- package/src/capabilities/keyboard.ts +1 -3
- package/src/capabilities/react-surface.tsx +4 -4
- package/src/capabilities/state.ts +3 -4
- package/src/components/CommandsDialog/CommandsDialog.tsx +14 -6
- package/src/components/CommandsDialog/CommandsTrigger.tsx +4 -3
- package/src/components/NavTree/NavTree.stories.tsx +63 -49
- package/src/components/NavTree/NavTree.tsx +4 -0
- package/src/components/NavTreeContainer.tsx +84 -45
- package/src/components/NavTreeDocumentTitle.tsx +2 -2
- package/src/components/NavTreeItem/NavTreeItemAction.stories.tsx +2 -4
- package/src/components/NavTreeItem/NavTreeItemAction.tsx +5 -4
- package/src/components/NavTreeItem/NavTreeItemColumns.tsx +27 -21
- package/src/components/Sidebar/L0Menu.tsx +54 -53
- package/src/components/Sidebar/L1Panel.tsx +7 -10
- package/src/components/UserAccountAvatar/UserAccountAvatar.stories.tsx +3 -4
- package/src/components/UserAccountAvatar/UserAccountAvatar.tsx +20 -12
- package/src/components/types.ts +1 -1
- package/src/events.ts +2 -2
- package/src/experimental/Tree.stories.tsx +26 -30
- package/src/experimental/Tree.tsx +6 -23
- package/src/meta.ts +10 -7
- package/src/testing/app-graph-builder.ts +19 -18
- package/src/testing/generator.ts +10 -8
- package/src/types.ts +4 -3
- package/dist/lib/browser/app-graph-builder-6JDBQ25U.mjs.map +0 -7
- package/dist/lib/browser/chunk-ERDGQTH5.mjs +0 -16
- package/dist/lib/browser/chunk-ERDGQTH5.mjs.map +0 -7
- package/dist/lib/browser/chunk-WCARAZ7J.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZKVY35IG.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-N35ZIHFD.mjs.map +0 -7
- package/dist/lib/browser/react-surface-5PZ4XJT7.mjs.map +0 -7
- package/dist/lib/browser/state-P5DGL7KS.mjs.map +0 -7
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@dxos-theme';
|
|
6
|
-
|
|
7
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
|
-
import
|
|
9
|
-
import React from 'react';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
7
|
+
import React, { type KeyboardEvent, useCallback, useRef } from 'react';
|
|
8
|
+
import { expect, userEvent, within } from 'storybook/test';
|
|
10
9
|
|
|
11
10
|
import {
|
|
12
11
|
Capabilities,
|
|
@@ -16,22 +15,20 @@ import {
|
|
|
16
15
|
contributes,
|
|
17
16
|
createResolver,
|
|
18
17
|
defineCapability,
|
|
19
|
-
useCapability,
|
|
20
18
|
} from '@dxos/app-framework';
|
|
19
|
+
import { useCapability } from '@dxos/app-framework/react';
|
|
21
20
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
22
21
|
import { live } from '@dxos/live-object';
|
|
23
22
|
import { AttentionPlugin } from '@dxos/plugin-attention';
|
|
24
|
-
import { ClientPlugin } from '@dxos/plugin-client';
|
|
25
23
|
import { GraphPlugin } from '@dxos/plugin-graph';
|
|
26
|
-
import { SpacePlugin } from '@dxos/plugin-space';
|
|
27
24
|
import { StorybookLayoutPlugin } from '@dxos/plugin-storybook-layout';
|
|
28
25
|
import { ThemePlugin } from '@dxos/plugin-theme';
|
|
29
26
|
import { faker } from '@dxos/random';
|
|
30
27
|
import { IconButton, Input, Main, Toolbar } from '@dxos/react-ui';
|
|
28
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
31
29
|
import { useAttention, useAttentionAttributes } from '@dxos/react-ui-attention';
|
|
32
30
|
import { Stack, StackItem } from '@dxos/react-ui-stack';
|
|
33
31
|
import { defaultTx, mx } from '@dxos/react-ui-theme';
|
|
34
|
-
import { withLayout } from '@dxos/storybook-utils';
|
|
35
32
|
|
|
36
33
|
import { NavTreePlugin } from '../../NavTreePlugin';
|
|
37
34
|
import { storybookGraphBuilders } from '../../testing';
|
|
@@ -68,6 +65,15 @@ const StoryPlankHeading = ({ attendableId }: { attendableId: string }) => {
|
|
|
68
65
|
|
|
69
66
|
const StoryPlank = ({ attendableId }: { attendableId: string }) => {
|
|
70
67
|
const attentionAttrs = useAttentionAttributes(attendableId);
|
|
68
|
+
const rootElement = useRef<HTMLDivElement | null>(null);
|
|
69
|
+
|
|
70
|
+
// NOTE(thure): This is the same workaround as in Plank, but that component is out of scope for this story.
|
|
71
|
+
// TODO(thure): Tabster’s focus group should handle moving focus to Main, but something is blocking it.
|
|
72
|
+
const handleKeyDown = useCallback((event: KeyboardEvent) => {
|
|
73
|
+
if (event.target === event.currentTarget && event.key === 'Escape') {
|
|
74
|
+
rootElement.current?.closest('main')?.focus();
|
|
75
|
+
}
|
|
76
|
+
}, []);
|
|
71
77
|
|
|
72
78
|
return (
|
|
73
79
|
<StackItem.Root
|
|
@@ -75,10 +81,12 @@ const StoryPlank = ({ attendableId }: { attendableId: string }) => {
|
|
|
75
81
|
{...attentionAttrs}
|
|
76
82
|
classNames='bg-baseSurface border-ie border-separator'
|
|
77
83
|
size={30}
|
|
84
|
+
onKeyDown={handleKeyDown}
|
|
85
|
+
ref={rootElement}
|
|
78
86
|
>
|
|
79
87
|
<StoryPlankHeading attendableId={attendableId} />
|
|
80
88
|
<StackItem.Content toolbar>
|
|
81
|
-
<Toolbar.Root classNames='border-
|
|
89
|
+
<Toolbar.Root classNames='border-be border-subduedSeparator'>
|
|
82
90
|
<Toolbar.Button>Test</Toolbar.Button>
|
|
83
91
|
</Toolbar.Root>
|
|
84
92
|
|
|
@@ -121,15 +129,16 @@ const meta = {
|
|
|
121
129
|
component: NavTreeContainer,
|
|
122
130
|
render: DefaultStory,
|
|
123
131
|
decorators: [
|
|
132
|
+
withTheme,
|
|
124
133
|
withPluginManager({
|
|
125
134
|
plugins: [
|
|
126
135
|
ThemePlugin({ tx: defaultTx }),
|
|
127
|
-
StorybookLayoutPlugin({ initialState: { sidebarState: 'expanded' } }),
|
|
128
136
|
GraphPlugin(),
|
|
129
137
|
IntentPlugin(),
|
|
130
138
|
SettingsPlugin(),
|
|
131
139
|
AttentionPlugin(),
|
|
132
140
|
NavTreePlugin(),
|
|
141
|
+
StorybookLayoutPlugin({ initialState: { sidebarState: 'expanded' } }),
|
|
133
142
|
],
|
|
134
143
|
capabilities: (context) => [
|
|
135
144
|
contributes(StoryState, live({ tab: 'space-0' })),
|
|
@@ -147,9 +156,9 @@ const meta = {
|
|
|
147
156
|
]),
|
|
148
157
|
],
|
|
149
158
|
}),
|
|
150
|
-
withLayout({ fullscreen: true }),
|
|
151
159
|
],
|
|
152
160
|
parameters: {
|
|
161
|
+
layout: 'fullscreen',
|
|
153
162
|
translations,
|
|
154
163
|
},
|
|
155
164
|
} satisfies Meta<typeof NavTreeContainer>;
|
|
@@ -158,43 +167,48 @@ export default meta;
|
|
|
158
167
|
|
|
159
168
|
type Story = StoryObj<typeof NavTreeContainer>;
|
|
160
169
|
|
|
161
|
-
export const Default: Story = {
|
|
170
|
+
export const Default: Story = {
|
|
171
|
+
play: async ({ canvasElement }) => {
|
|
172
|
+
const canvas = within(canvasElement);
|
|
162
173
|
|
|
163
|
-
//
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
174
|
+
// Find the element with treegrid role and click on its parent
|
|
175
|
+
const treegridElement = await canvas.findByRole('treegrid');
|
|
176
|
+
const treegridParent = treegridElement.parentElement;
|
|
177
|
+
if (treegridParent) {
|
|
178
|
+
await userEvent.click(treegridParent);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Press Escape
|
|
182
|
+
await userEvent.keyboard('{Escape}');
|
|
183
|
+
|
|
184
|
+
// Confirm that focus is on an element with attribute data-main-landmark="0"
|
|
185
|
+
await expect(document.activeElement).toHaveAttribute('data-main-landmark', '0');
|
|
186
|
+
|
|
187
|
+
// Press Tab
|
|
188
|
+
await userEvent.keyboard('{Tab}');
|
|
189
|
+
|
|
190
|
+
// Confirm that focus is now on an element with data-main-landmark="1"
|
|
191
|
+
await expect(document.activeElement).toHaveAttribute('data-main-landmark', '1');
|
|
192
|
+
|
|
193
|
+
// Press Tab
|
|
194
|
+
await userEvent.keyboard('{Tab}');
|
|
195
|
+
|
|
196
|
+
// Confirm that focus is now on an element with data-main-landmark="0"
|
|
197
|
+
await expect(document.activeElement).toHaveAttribute('data-main-landmark', '0');
|
|
198
|
+
|
|
199
|
+
// Press Shift-Tab
|
|
200
|
+
await userEvent.keyboard('{Shift>}{Tab}{/Shift}');
|
|
201
|
+
|
|
202
|
+
// Press Enter
|
|
203
|
+
await userEvent.keyboard('{Enter}');
|
|
204
|
+
|
|
205
|
+
// Confirm that focus is now on an element with data-attendable-id="space-0:object-0"
|
|
206
|
+
await expect(document.activeElement).toHaveAttribute('data-attendable-id', 'space-0:object-0');
|
|
207
|
+
|
|
208
|
+
// Press Escape
|
|
209
|
+
await userEvent.keyboard('{Escape}');
|
|
210
|
+
|
|
211
|
+
// Confirm that focus is now on an element with data-main-landmark="1"
|
|
212
|
+
await expect(document.activeElement).toHaveAttribute('data-main-landmark', '1');
|
|
213
|
+
},
|
|
200
214
|
};
|
|
@@ -47,6 +47,10 @@ export const NavTree = ({ id, root, ...props }: NavTreeProps) => {
|
|
|
47
47
|
const path = useMemo(() => [id], [id]);
|
|
48
48
|
|
|
49
49
|
return (
|
|
50
|
+
// TODO(thure): `Tabs.Root` forces all items that should be able to receive focus to use `Tabs.Tab(Primitive)` since
|
|
51
|
+
// it uses RovingFocus and doesn’t support moving focus to an item that is not a tab. Assess whether this situation
|
|
52
|
+
// should change including whether it should motivate a change in the design/taxonomy, or if this means this should
|
|
53
|
+
// not use `react-ui-tabs` at all.
|
|
50
54
|
<Tabs.Root value={tab} orientation='vertical' verticalVariant='stateless' classNames='relative'>
|
|
51
55
|
<L0Menu
|
|
52
56
|
menuActions={topLevelActions}
|
|
@@ -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';
|
|
@@ -25,7 +18,7 @@ import { mx } from '@dxos/react-ui-theme';
|
|
|
25
18
|
import { arrayMove, byPosition } from '@dxos/util';
|
|
26
19
|
|
|
27
20
|
import { NavTreeCapabilities } from '../capabilities';
|
|
28
|
-
import {
|
|
21
|
+
import { meta } from '../meta';
|
|
29
22
|
import { type FlattenedActions, type NavTreeItemGraphNode } from '../types';
|
|
30
23
|
import { getChildren, getParent, resolveMigrationOperation } from '../util';
|
|
31
24
|
|
|
@@ -98,12 +91,12 @@ export type NavTreeContainerProps = {
|
|
|
98
91
|
} & Pick<NavTreeContextValue, 'tab'>;
|
|
99
92
|
|
|
100
93
|
export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeContainerProps) => {
|
|
101
|
-
const [isLg] = useMediaQuery('lg'
|
|
94
|
+
const [isLg] = useMediaQuery('lg');
|
|
102
95
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
103
96
|
const { graph } = useAppGraph();
|
|
104
97
|
const { isOpen, isCurrent, isAlternateTree, setItem } = useCapability(NavTreeCapabilities.State);
|
|
105
98
|
const layout = useLayout();
|
|
106
|
-
const { navigationSidebarState } = useSidebars(
|
|
99
|
+
const { navigationSidebarState } = useSidebars(meta.id);
|
|
107
100
|
|
|
108
101
|
const getProps = useCallback(
|
|
109
102
|
(node: Node, path: string[]): TreeItemDataProps => {
|
|
@@ -112,12 +105,13 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
112
105
|
children.length > 0 ? children.map(({ id }) => id) : node.properties.role === 'branch' ? [] : undefined;
|
|
113
106
|
return {
|
|
114
107
|
id: node.id,
|
|
115
|
-
label: node.properties.label ?? node.id,
|
|
116
108
|
parentOf,
|
|
117
|
-
icon: node.properties.icon,
|
|
118
109
|
disabled: node.properties.disabled,
|
|
119
|
-
|
|
110
|
+
label: node.properties.label ?? node.id,
|
|
111
|
+
className: mx(node.properties.className, node.properties.modified && 'italic'), // TODO(burdon): Italic?
|
|
120
112
|
headingClassName: node.properties.headingClassName,
|
|
113
|
+
icon: node.properties.icon,
|
|
114
|
+
iconHue: node.properties.iconHue,
|
|
121
115
|
testId: node.properties.testId,
|
|
122
116
|
};
|
|
123
117
|
},
|
|
@@ -162,23 +156,44 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
162
156
|
}),
|
|
163
157
|
);
|
|
164
158
|
|
|
165
|
-
await dispatch(
|
|
159
|
+
await dispatch(
|
|
160
|
+
createIntent(LayoutAction.SwitchWorkspace, {
|
|
161
|
+
part: 'workspace',
|
|
162
|
+
subject: node.id,
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
166
165
|
|
|
167
166
|
// Open the first item if the workspace is empty.
|
|
168
167
|
if (layout.active.length === 0) {
|
|
169
168
|
const [item] = getItems(graph, node).filter((node) => !isActionLike(node));
|
|
170
169
|
if (item && item.data) {
|
|
171
|
-
await dispatch(
|
|
170
|
+
await dispatch(
|
|
171
|
+
createIntent(LayoutAction.Open, {
|
|
172
|
+
part: 'main',
|
|
173
|
+
subject: [item.id],
|
|
174
|
+
}),
|
|
175
|
+
);
|
|
172
176
|
}
|
|
173
177
|
}
|
|
174
178
|
},
|
|
175
179
|
[dispatch, layout.active, tab, navigationSidebarState, isLg],
|
|
176
180
|
);
|
|
177
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
|
+
|
|
178
189
|
const canDrop = useCallback(({ source, target }: { source: TreeData; target: TreeData }) => {
|
|
179
190
|
return target.item.properties.canDrop?.(source) ?? false;
|
|
180
191
|
}, []);
|
|
181
192
|
|
|
193
|
+
const canSelect = useCallback(({ item }: { item: Node }) => {
|
|
194
|
+
return item.properties.selectable ?? true;
|
|
195
|
+
}, []);
|
|
196
|
+
|
|
182
197
|
const handleSelect = useCallback(
|
|
183
198
|
({ item: node, path, option }: { item: Node; path: string[]; option: boolean }) => {
|
|
184
199
|
if (!node.data) {
|
|
@@ -202,10 +217,19 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
202
217
|
);
|
|
203
218
|
} else if (option) {
|
|
204
219
|
void dispatch(
|
|
205
|
-
createIntent(LayoutAction.Close, {
|
|
220
|
+
createIntent(LayoutAction.Close, {
|
|
221
|
+
part: 'main',
|
|
222
|
+
subject: [node.id],
|
|
223
|
+
options: { state: false },
|
|
224
|
+
}),
|
|
206
225
|
);
|
|
207
226
|
} else {
|
|
208
|
-
void dispatch(
|
|
227
|
+
void dispatch(
|
|
228
|
+
createIntent(LayoutAction.ScrollIntoView, {
|
|
229
|
+
part: 'current',
|
|
230
|
+
subject: node.id,
|
|
231
|
+
}),
|
|
232
|
+
);
|
|
209
233
|
}
|
|
210
234
|
|
|
211
235
|
const defaultAction = graph.getActions(node.id).find((action) => action.properties?.disposition === 'default');
|
|
@@ -214,14 +238,25 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
214
238
|
}
|
|
215
239
|
|
|
216
240
|
if (!isLg) {
|
|
217
|
-
void dispatch(
|
|
241
|
+
void dispatch(
|
|
242
|
+
createIntent(LayoutAction.UpdateSidebar, {
|
|
243
|
+
part: 'sidebar',
|
|
244
|
+
options: { state: 'closed' },
|
|
245
|
+
}),
|
|
246
|
+
);
|
|
218
247
|
}
|
|
219
248
|
},
|
|
220
249
|
[graph, dispatch, isCurrent, isLg],
|
|
221
250
|
);
|
|
222
251
|
|
|
223
252
|
const handleBack = useCallback(
|
|
224
|
-
() =>
|
|
253
|
+
() =>
|
|
254
|
+
dispatch(
|
|
255
|
+
createIntent(LayoutAction.RevertWorkspace, {
|
|
256
|
+
part: 'workspace',
|
|
257
|
+
options: { revert: true },
|
|
258
|
+
}),
|
|
259
|
+
),
|
|
225
260
|
[dispatch],
|
|
226
261
|
);
|
|
227
262
|
|
|
@@ -293,41 +328,45 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
293
328
|
|
|
294
329
|
const navTreeContextValue = useMemo(
|
|
295
330
|
() => ({
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
loadDescendents,
|
|
300
|
-
renderItemEnd,
|
|
301
|
-
popoverAnchorId,
|
|
302
|
-
topbar,
|
|
331
|
+
blockInstruction,
|
|
332
|
+
canDrop,
|
|
333
|
+
canSelect,
|
|
303
334
|
getProps,
|
|
335
|
+
isAlternateTree,
|
|
304
336
|
isCurrent,
|
|
305
337
|
isOpen,
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
setAlternateTree,
|
|
309
|
-
onTabChange: handleTabChange,
|
|
338
|
+
loadDescendents,
|
|
339
|
+
onBack: handleBack,
|
|
310
340
|
onOpenChange: handleOpenChange,
|
|
311
341
|
onSelect: handleSelect,
|
|
312
|
-
|
|
313
|
-
}),
|
|
314
|
-
[
|
|
315
|
-
tab,
|
|
316
|
-
useActions,
|
|
317
|
-
loadDescendents,
|
|
318
|
-
renderItemEnd,
|
|
342
|
+
onTabChange: handleTabChange,
|
|
319
343
|
popoverAnchorId,
|
|
344
|
+
renderItemEnd,
|
|
345
|
+
setAlternateTree,
|
|
346
|
+
tab,
|
|
320
347
|
topbar,
|
|
348
|
+
useActions,
|
|
349
|
+
useItems,
|
|
350
|
+
}),
|
|
351
|
+
[
|
|
352
|
+
blockInstruction,
|
|
353
|
+
canDrop,
|
|
354
|
+
canSelect,
|
|
321
355
|
getProps,
|
|
356
|
+
handleBack,
|
|
357
|
+
handleOpenChange,
|
|
358
|
+
handleSelect,
|
|
359
|
+
handleTabChange,
|
|
360
|
+
isAlternateTree,
|
|
322
361
|
isCurrent,
|
|
323
362
|
isOpen,
|
|
324
|
-
|
|
325
|
-
|
|
363
|
+
loadDescendents,
|
|
364
|
+
popoverAnchorId,
|
|
365
|
+
renderItemEnd,
|
|
326
366
|
setAlternateTree,
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
handleBack,
|
|
367
|
+
tab,
|
|
368
|
+
topbar,
|
|
369
|
+
useActions,
|
|
331
370
|
],
|
|
332
371
|
);
|
|
333
372
|
|
|
@@ -6,10 +6,10 @@ import { useEffect } from 'react';
|
|
|
6
6
|
import { type Node } from '@dxos/app-graph';
|
|
7
7
|
import { toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { meta } from '../meta';
|
|
10
10
|
|
|
11
11
|
export const NavTreeDocumentTitle = ({ node }: { node?: Node }) => {
|
|
12
|
-
const { t } = useTranslation(
|
|
12
|
+
const { t } = useTranslation(meta.id);
|
|
13
13
|
useEffect(() => {
|
|
14
14
|
document.title = node ? toLocalizedString(node.properties.label, t) : t('current app name', { ns: 'appkit' });
|
|
15
15
|
}, [node?.properties?.label]);
|
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@dxos-theme';
|
|
6
|
-
|
|
7
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
6
|
|
|
9
7
|
import { type NodeArg } from '@dxos/app-graph';
|
|
10
8
|
import { faker } from '@dxos/random';
|
|
11
|
-
import {
|
|
9
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
12
10
|
|
|
13
11
|
import { NavTreeItemAction, type NavTreeItemActionMenuProps } from './NavTreeItemAction';
|
|
14
12
|
|
|
@@ -42,13 +40,13 @@ const menuActions = faker.helpers.multiple(
|
|
|
42
40
|
const meta = {
|
|
43
41
|
title: 'plugins/plugin-navtree/NavTreeItemAction',
|
|
44
42
|
component: NavTreeItemAction,
|
|
45
|
-
decorators: [withTheme, withLayout()],
|
|
46
43
|
args: {
|
|
47
44
|
icon: 'ph--list--regular',
|
|
48
45
|
parent,
|
|
49
46
|
menuActions,
|
|
50
47
|
label: 'Select action',
|
|
51
48
|
} satisfies Partial<NavTreeItemActionMenuProps>,
|
|
49
|
+
decorators: [withTheme],
|
|
52
50
|
parameters: {
|
|
53
51
|
layout: 'centered',
|
|
54
52
|
},
|
|
@@ -9,7 +9,7 @@ import { IconButton, toLocalizedString, useDensityContext, useTranslation } from
|
|
|
9
9
|
import { DropdownMenu, type MenuItem, MenuProvider } from '@dxos/react-ui-menu';
|
|
10
10
|
import { hoverableControlItem, hoverableOpenControlItem } from '@dxos/react-ui-theme';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { meta } from '../../meta';
|
|
13
13
|
import { type ActionProperties } from '../../types';
|
|
14
14
|
|
|
15
15
|
export type NavTreeItemActionMenuProps = ActionProperties & {
|
|
@@ -38,7 +38,7 @@ export const NavTreeItemActionDropdownMenu = ({
|
|
|
38
38
|
menuActions,
|
|
39
39
|
caller,
|
|
40
40
|
}: NavTreeItemActionMenuProps) => {
|
|
41
|
-
const { t } = useTranslation(
|
|
41
|
+
const { t } = useTranslation(meta.id);
|
|
42
42
|
const density = useDensityContext();
|
|
43
43
|
return (
|
|
44
44
|
<MenuProvider>
|
|
@@ -81,10 +81,11 @@ export const NavTreeItemMonolithicAction = ({
|
|
|
81
81
|
label={baseLabel}
|
|
82
82
|
disabled={disabled}
|
|
83
83
|
onClick={(event) => {
|
|
84
|
+
event.stopPropagation();
|
|
84
85
|
if (disabled) {
|
|
85
86
|
return;
|
|
86
87
|
}
|
|
87
|
-
|
|
88
|
+
|
|
88
89
|
void invoke?.(caller ? { parent, caller } : { parent });
|
|
89
90
|
}}
|
|
90
91
|
data-testid={testId}
|
|
@@ -93,7 +94,7 @@ export const NavTreeItemMonolithicAction = ({
|
|
|
93
94
|
};
|
|
94
95
|
|
|
95
96
|
export const NavTreeItemAction = ({ monolithic, menuActions, parent: node, ...props }: NavTreeItemActionMenuProps) => {
|
|
96
|
-
const { t } = useTranslation(
|
|
97
|
+
const { t } = useTranslation(meta.id);
|
|
97
98
|
|
|
98
99
|
const monolithicAction = menuActions?.length === 1 && menuActions[0];
|
|
99
100
|
const baseLabel = toLocalizedString(monolithicAction ? monolithicAction.properties!.label : props.label, t);
|
|
@@ -5,18 +5,18 @@
|
|
|
5
5
|
import React, { Fragment, memo } from 'react';
|
|
6
6
|
|
|
7
7
|
import { isAction } from '@dxos/app-graph';
|
|
8
|
-
import {
|
|
8
|
+
import { Popover, Treegrid, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
9
9
|
|
|
10
10
|
import { useLoadDescendents } from '../../hooks';
|
|
11
|
-
import {
|
|
11
|
+
import { meta } from '../../meta';
|
|
12
12
|
import { NAV_TREE_ITEM } from '../NavTree';
|
|
13
13
|
import { useNavTreeContext } from '../NavTreeContext';
|
|
14
14
|
import { type NavTreeItemColumnsProps } from '../types';
|
|
15
15
|
|
|
16
16
|
import { NavTreeItemAction } from './NavTreeItemAction';
|
|
17
17
|
|
|
18
|
-
export const NavTreeItemColumns = memo(({ path, item, open
|
|
19
|
-
const { t } = useTranslation(
|
|
18
|
+
export const NavTreeItemColumns = memo(({ path, item, open }: NavTreeItemColumnsProps) => {
|
|
19
|
+
const { t } = useTranslation(meta.id);
|
|
20
20
|
const { useActions, renderItemEnd: ItemEnd, popoverAnchorId } = useNavTreeContext();
|
|
21
21
|
|
|
22
22
|
const level = path.length - 2;
|
|
@@ -29,15 +29,15 @@ export const NavTreeItemColumns = memo(({ path, item, open, density = 'fine' }:
|
|
|
29
29
|
.flatMap((action) => (isAction(action) ? [action] : []))
|
|
30
30
|
.filter((a) => ['list-item', 'list-item-primary'].includes(a.properties?.disposition));
|
|
31
31
|
|
|
32
|
-
const ActionRoot = popoverAnchorId === `dxos.org/ui/${NAV_TREE_ITEM}/${item.id}` ? Popover.Anchor : Fragment;
|
|
33
|
-
|
|
34
32
|
useLoadDescendents(item);
|
|
35
33
|
useLoadDescendents(primaryAction && !isAction(primaryAction) ? primaryAction : undefined);
|
|
36
34
|
|
|
35
|
+
const ActionRoot = popoverAnchorId === `dxos.org/ui/${NAV_TREE_ITEM}/${item.id}` ? Popover.Anchor : Fragment;
|
|
36
|
+
|
|
37
37
|
return (
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
<div role='none' className='contents app-no-drag'>
|
|
39
|
+
{primaryAction?.properties?.disposition === 'list-item-primary' && !primaryAction?.properties?.disabled ? (
|
|
40
|
+
<Treegrid.Cell classNames='contents'>
|
|
41
41
|
<NavTreeItemAction
|
|
42
42
|
testId={primaryAction.properties?.testId}
|
|
43
43
|
label={toLocalizedString(primaryAction.properties?.label, t)}
|
|
@@ -48,11 +48,13 @@ export const NavTreeItemColumns = memo(({ path, item, open, density = 'fine' }:
|
|
|
48
48
|
menuType={primaryAction.properties?.menuType}
|
|
49
49
|
caller={NAV_TREE_ITEM}
|
|
50
50
|
/>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
</Treegrid.Cell>
|
|
52
|
+
) : (
|
|
53
|
+
<Treegrid.Cell role='none' />
|
|
54
|
+
)}
|
|
55
|
+
<ActionRoot>
|
|
56
|
+
{actions.length > 0 ? (
|
|
57
|
+
<Treegrid.Cell classNames='contents'>
|
|
56
58
|
<NavTreeItemAction
|
|
57
59
|
testId={`navtree.treeItem.actionsLevel${level}`}
|
|
58
60
|
label={t('tree item actions label')}
|
|
@@ -62,12 +64,16 @@ export const NavTreeItemColumns = memo(({ path, item, open, density = 'fine' }:
|
|
|
62
64
|
menuType='dropdown'
|
|
63
65
|
caller={NAV_TREE_ITEM}
|
|
64
66
|
/>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
</Treegrid.Cell>
|
|
68
|
+
) : (
|
|
69
|
+
<Treegrid.Cell role='none' />
|
|
70
|
+
)}
|
|
71
|
+
</ActionRoot>
|
|
72
|
+
{ItemEnd && (
|
|
73
|
+
<Treegrid.Cell classNames='contents'>
|
|
74
|
+
<ItemEnd node={item} open={open} />
|
|
75
|
+
</Treegrid.Cell>
|
|
76
|
+
)}
|
|
77
|
+
</div>
|
|
72
78
|
);
|
|
73
79
|
});
|