@dxos/plugin-navtree 0.8.4-main.b97322e → 0.8.4-main.bc674ce
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 +43 -0
- package/dist/lib/browser/app-graph-builder-RSMA6I22.mjs.map +7 -0
- package/dist/lib/browser/chunk-6YPQ625I.mjs +1293 -0
- package/dist/lib/browser/chunk-6YPQ625I.mjs.map +7 -0
- package/dist/lib/browser/chunk-AGQDZBPL.mjs +23 -0
- package/dist/lib/browser/chunk-AGQDZBPL.mjs.map +7 -0
- package/dist/lib/browser/chunk-YKTYPINZ.mjs +19 -0
- package/dist/lib/browser/chunk-YKTYPINZ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +84 -96
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/{keyboard-QRS6WOQH.mjs → keyboard-32EH3N4K.mjs} +20 -19
- package/dist/lib/browser/keyboard-32EH3N4K.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/operation-resolver-IB75DC5O.mjs +52 -0
- package/dist/lib/browser/operation-resolver-IB75DC5O.mjs.map +7 -0
- package/dist/lib/browser/react-surface-F6CVMS3Y.mjs +58 -0
- package/dist/lib/browser/react-surface-F6CVMS3Y.mjs.map +7 -0
- package/dist/lib/browser/state-EVYQOUI3.mjs +120 -0
- package/dist/lib/browser/state-EVYQOUI3.mjs.map +7 -0
- package/dist/types/src/NavTreePlugin.d.ts +2 -1
- package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts +6 -0
- package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/capabilities/app-graph-builder/index.d.ts +3 -0
- package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +5 -105
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/keyboard/index.d.ts +3 -0
- package/dist/types/src/capabilities/keyboard/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/keyboard/keyboard.d.ts +5 -0
- package/dist/types/src/capabilities/keyboard/keyboard.d.ts.map +1 -0
- package/dist/types/src/capabilities/operation-resolver/index.d.ts +3 -0
- package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +5 -0
- package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface/index.d.ts +3 -0
- package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts +5 -0
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/state/index.d.ts +3 -0
- package/dist/types/src/capabilities/state/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/state/state.d.ts +6 -0
- package/dist/types/src/capabilities/state/state.d.ts.map +1 -0
- package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts +3 -2
- 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 +32 -3
- package/dist/types/src/components/NavTree/NavTree.d.ts.map +1 -1
- package/dist/types/src/components/NavTree/NavTree.stories.d.ts +29 -4
- package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeContainer.d.ts +8 -1
- package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeDocumentTitle.d.ts +1 -1
- package/dist/types/src/components/NavTreeDocumentTitle.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts +6 -6
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +33 -4
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts +2 -2
- package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/L0Menu.d.ts +6 -4
- package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/L1Panel.d.ts +5 -6
- package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/L1Tabs.d.ts +12 -0
- package/dist/types/src/components/Sidebar/L1Tabs.d.ts.map +1 -0
- package/dist/types/src/components/Sidebar/index.d.ts +1 -0
- package/dist/types/src/components/Sidebar/index.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 +8 -5
- package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/types.d.ts +8 -8
- package/dist/types/src/components/types.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 +7 -4
- package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
- package/dist/types/src/hooks.d.ts +32 -1
- package/dist/types/src/hooks.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +3 -4
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/testing/app-graph-builder.d.ts +2 -3
- package/dist/types/src/testing/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/testing/generator.d.ts +5 -6
- package/dist/types/src/testing/generator.d.ts.map +1 -1
- package/dist/types/src/testing/update-state.d.ts +2 -2
- package/dist/types/src/testing/update-state.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/capabilities.d.ts +16 -0
- package/dist/types/src/types/capabilities.d.ts.map +1 -0
- package/dist/types/src/types/events.d.ts +5 -0
- package/dist/types/src/types/events.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +4 -0
- package/dist/types/src/types/index.d.ts.map +1 -0
- package/dist/types/src/{types.d.ts → types/schema.d.ts} +10 -9
- package/dist/types/src/types/schema.d.ts.map +1 -0
- package/dist/types/src/util.d.ts +8 -9
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +55 -53
- package/src/NavTreePlugin.tsx +65 -83
- package/src/capabilities/app-graph-builder/app-graph-builder.ts +41 -0
- package/src/capabilities/app-graph-builder/index.ts +7 -0
- package/src/capabilities/index.ts +5 -9
- package/src/capabilities/keyboard/index.ts +7 -0
- package/src/capabilities/keyboard/keyboard.ts +65 -0
- package/src/capabilities/operation-resolver/index.ts +7 -0
- package/src/capabilities/operation-resolver/operation-resolver.ts +41 -0
- package/src/capabilities/react-surface/index.ts +7 -0
- package/src/capabilities/react-surface/react-surface.tsx +54 -0
- package/src/capabilities/state/index.ts +7 -0
- package/src/capabilities/state/state.ts +121 -0
- package/src/components/CommandsDialog/CommandsDialog.tsx +109 -98
- package/src/components/CommandsDialog/CommandsTrigger.tsx +6 -15
- package/src/components/NavTree/NavTree.stories.tsx +98 -93
- package/src/components/NavTree/NavTree.tsx +12 -18
- package/src/components/NavTreeContainer.tsx +280 -256
- package/src/components/NavTreeDocumentTitle.tsx +5 -4
- package/src/components/NavTreeItem/NavTreeItemAction.stories.tsx +20 -12
- package/src/components/NavTreeItem/NavTreeItemAction.tsx +25 -18
- package/src/components/NavTreeItem/NavTreeItemColumns.tsx +38 -32
- package/src/components/Sidebar/L0Menu.tsx +114 -139
- package/src/components/Sidebar/L1Panel.tsx +76 -99
- package/src/components/Sidebar/L1Tabs.tsx +33 -0
- package/src/components/Sidebar/index.ts +1 -0
- package/src/components/UserAccountAvatar/UserAccountAvatar.stories.tsx +9 -8
- package/src/components/UserAccountAvatar/UserAccountAvatar.tsx +20 -12
- package/src/components/index.ts +1 -0
- package/src/components/types.ts +9 -8
- package/src/experimental/Tree.stories.tsx +28 -30
- package/src/experimental/Tree.tsx +7 -24
- package/src/hooks.ts +54 -2
- package/src/index.ts +1 -2
- package/src/meta.ts +11 -8
- package/src/testing/app-graph-builder.ts +159 -234
- package/src/testing/generator.ts +20 -18
- package/src/testing/update-state.ts +6 -6
- package/src/translations.ts +1 -0
- package/src/types/capabilities.ts +21 -0
- package/src/types/events.ts +11 -0
- package/src/types/index.ts +7 -0
- package/src/{types.ts → types/schema.ts} +9 -8
- package/src/util.ts +14 -35
- package/dist/lib/browser/app-graph-builder-5J4LRWDX.mjs +0 -45
- package/dist/lib/browser/app-graph-builder-5J4LRWDX.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-SICQTLXC.mjs +0 -1442
- package/dist/lib/browser/chunk-SICQTLXC.mjs.map +0 -7
- package/dist/lib/browser/chunk-WCARAZ7J.mjs +0 -15
- package/dist/lib/browser/chunk-WCARAZ7J.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-3XYN2CBU.mjs +0 -47
- package/dist/lib/browser/intent-resolver-3XYN2CBU.mjs.map +0 -7
- package/dist/lib/browser/keyboard-QRS6WOQH.mjs.map +0 -7
- package/dist/lib/browser/react-surface-WURHCBQQ.mjs +0 -51
- package/dist/lib/browser/react-surface-WURHCBQQ.mjs.map +0 -7
- package/dist/lib/browser/state-54DY3DOY.mjs +0 -117
- package/dist/lib/browser/state-54DY3DOY.mjs.map +0 -7
- package/dist/types/src/capabilities/app-graph-builder.d.ts +0 -4
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +0 -1
- package/dist/types/src/capabilities/capabilities.d.ts +0 -21
- package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
- package/dist/types/src/capabilities/keyboard.d.ts +0 -4
- package/dist/types/src/capabilities/keyboard.d.ts.map +0 -1
- package/dist/types/src/capabilities/react-surface.d.ts +0 -4
- package/dist/types/src/capabilities/react-surface.d.ts.map +0 -1
- package/dist/types/src/capabilities/state.d.ts +0 -20
- package/dist/types/src/capabilities/state.d.ts.map +0 -1
- package/dist/types/src/events.d.ts +0 -4
- package/dist/types/src/events.d.ts.map +0 -1
- package/dist/types/src/types.d.ts.map +0 -1
- package/src/capabilities/app-graph-builder.ts +0 -52
- package/src/capabilities/capabilities.ts +0 -20
- package/src/capabilities/intent-resolver.ts +0 -37
- package/src/capabilities/keyboard.ts +0 -59
- package/src/capabilities/react-surface.tsx +0 -45
- package/src/capabilities/state.ts +0 -104
- package/src/events.ts +0 -11
|
@@ -12,9 +12,9 @@ import {
|
|
|
12
12
|
extractClosestEdge,
|
|
13
13
|
} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
14
14
|
import React, {
|
|
15
|
-
forwardRef,
|
|
16
15
|
type MouseEvent,
|
|
17
16
|
type PropsWithChildren,
|
|
17
|
+
forwardRef,
|
|
18
18
|
useCallback,
|
|
19
19
|
useLayoutEffect,
|
|
20
20
|
useMemo,
|
|
@@ -23,16 +23,26 @@ import React, {
|
|
|
23
23
|
} from 'react';
|
|
24
24
|
|
|
25
25
|
import { type Node } from '@dxos/app-graph';
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
26
|
+
import { DxAvatar } from '@dxos/lit-ui/react';
|
|
27
|
+
import { useActionRunner } from '@dxos/plugin-graph';
|
|
28
|
+
import {
|
|
29
|
+
Icon,
|
|
30
|
+
ListItem,
|
|
31
|
+
ScrollArea,
|
|
32
|
+
type ThemedClassName,
|
|
33
|
+
Tooltip,
|
|
34
|
+
toLocalizedString,
|
|
35
|
+
useMediaQuery,
|
|
36
|
+
useTranslation,
|
|
37
|
+
} from '@dxos/react-ui';
|
|
38
|
+
import { DropdownMenu, type MenuItem, MenuProvider } from '@dxos/react-ui-menu';
|
|
29
39
|
import type { StackItemRearrangeHandler } from '@dxos/react-ui-stack';
|
|
30
40
|
import { Tabs } from '@dxos/react-ui-tabs';
|
|
31
|
-
import { mx } from '@dxos/
|
|
32
|
-
import { arrayMove
|
|
41
|
+
import { mx } from '@dxos/ui-theme';
|
|
42
|
+
import { arrayMove } from '@dxos/util';
|
|
33
43
|
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
44
|
+
import { useNavTreeState } from '../../hooks';
|
|
45
|
+
import { meta } from '../../meta';
|
|
36
46
|
import { l0ItemType } from '../../util';
|
|
37
47
|
import { useNavTreeContext } from '../NavTreeContext';
|
|
38
48
|
import { UserAccountAvatar } from '../UserAccountAvatar';
|
|
@@ -47,43 +57,41 @@ type L0ItemData = {
|
|
|
47
57
|
};
|
|
48
58
|
|
|
49
59
|
type L0ItemRootProps = {
|
|
50
|
-
item: Node
|
|
51
|
-
parent?: Node
|
|
60
|
+
item: Node.Node;
|
|
61
|
+
parent?: Node.Node;
|
|
52
62
|
path: string[];
|
|
53
63
|
};
|
|
54
64
|
|
|
55
65
|
type L0ItemProps = L0ItemRootProps & {
|
|
56
|
-
item: Node
|
|
57
|
-
parent?: Node
|
|
66
|
+
item: Node.Node;
|
|
67
|
+
parent?: Node.Node;
|
|
58
68
|
path: string[];
|
|
59
69
|
pinned?: boolean;
|
|
60
70
|
onRearrange?: StackItemRearrangeHandler<L0ItemData>;
|
|
61
71
|
};
|
|
62
72
|
|
|
63
73
|
const useL0ItemClick = ({ item, parent, path }: L0ItemProps, type: string) => {
|
|
64
|
-
const { tab,
|
|
65
|
-
const
|
|
74
|
+
const { tab, onSelect, onTabChange } = useNavTreeContext();
|
|
75
|
+
const { getItem } = useNavTreeState();
|
|
76
|
+
const [isLg] = useMediaQuery('lg');
|
|
77
|
+
const runAction = useActionRunner();
|
|
66
78
|
|
|
67
79
|
return useCallback(
|
|
68
80
|
(event: MouseEvent) => {
|
|
69
81
|
switch (type) {
|
|
70
82
|
case 'action': {
|
|
71
|
-
const {
|
|
72
|
-
|
|
73
|
-
properties: { caller },
|
|
74
|
-
} = item;
|
|
75
|
-
|
|
76
|
-
return invoke?.(caller ? { node: parent, caller } : { node: parent });
|
|
83
|
+
const { properties: { caller } = {} } = item;
|
|
84
|
+
return void runAction(item as Node.Action, caller ? { parent, caller } : { parent });
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
case 'tab':
|
|
80
88
|
return onTabChange?.(item);
|
|
81
89
|
|
|
82
90
|
case 'link':
|
|
83
|
-
return onSelect?.({ item, path, current: !
|
|
91
|
+
return onSelect?.({ item, path, current: !getItem(path).current, option: event.altKey });
|
|
84
92
|
}
|
|
85
93
|
},
|
|
86
|
-
[item, parent, type, tab,
|
|
94
|
+
[item, parent, type, tab, getItem, onSelect, onTabChange, isLg, runAction],
|
|
87
95
|
);
|
|
88
96
|
};
|
|
89
97
|
|
|
@@ -92,7 +100,7 @@ const l0Breakpoints: Record<string, string> = {
|
|
|
92
100
|
};
|
|
93
101
|
|
|
94
102
|
const l0ItemRoot =
|
|
95
|
-
'group/l0item flex
|
|
103
|
+
'group/l0item flex is-full justify-center items-center relative data[type!="collection"]:cursor-pointer app-no-drag dx-focus-ring-group';
|
|
96
104
|
|
|
97
105
|
const l0ItemContent = 'flex justify-center items-center dx-focus-ring-group-indicator transition-colors rounded-sm';
|
|
98
106
|
|
|
@@ -103,55 +111,43 @@ const L0ItemRoot = forwardRef<HTMLElement, PropsWithChildren<L0ItemRootProps>>(
|
|
|
103
111
|
const type = l0ItemType(item);
|
|
104
112
|
const itemPath = useMemo(() => [...path, item.id], [item.id, path]);
|
|
105
113
|
|
|
106
|
-
const { t } = useTranslation(
|
|
114
|
+
const { t } = useTranslation(meta.id);
|
|
107
115
|
const localizedString = toLocalizedString(item.properties.label, t);
|
|
108
116
|
|
|
109
117
|
const handleClick = useL0ItemClick({ item, parent, path: itemPath }, type);
|
|
110
118
|
const rootProps =
|
|
111
119
|
type === 'tab'
|
|
112
|
-
? { value: item.id, tabIndex: 0, onClick: handleClick, 'data-testid': testId, 'data-
|
|
113
|
-
:
|
|
114
|
-
? { onClick: handleClick, 'data-testid': testId, 'data-itemid': id }
|
|
115
|
-
: { onClick: handleClick };
|
|
116
|
-
|
|
117
|
-
const Root = type === 'collection' ? 'h2' : type === 'tab' ? Tabs.TabPrimitive : 'button';
|
|
120
|
+
? { value: item.id, tabIndex: 0, onClick: handleClick, 'data-testid': testId, 'data-object-id': id }
|
|
121
|
+
: { onClick: handleClick, 'data-testid': testId, 'data-object-id': id };
|
|
118
122
|
|
|
119
123
|
return (
|
|
120
124
|
<Tooltip.Trigger asChild delayDuration={0} side='right' content={localizedString}>
|
|
121
|
-
<
|
|
125
|
+
<Tabs.TabPrimitive
|
|
122
126
|
{...(rootProps as any)}
|
|
123
127
|
data-type={type}
|
|
124
128
|
className={mx(l0ItemRoot, l0Breakpoints[item.properties.l0Breakpoint])}
|
|
125
129
|
ref={forwardedRef}
|
|
126
130
|
>
|
|
127
131
|
{children}
|
|
128
|
-
</
|
|
132
|
+
</Tabs.TabPrimitive>
|
|
129
133
|
</Tooltip.Trigger>
|
|
130
134
|
);
|
|
131
135
|
},
|
|
132
136
|
);
|
|
133
137
|
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
return (
|
|
146
|
-
<span role='img' className='place-self-center text-xl font-light' {...hueFgStyle}>
|
|
147
|
-
{avatarValue}
|
|
148
|
-
</span>
|
|
149
|
-
);
|
|
150
|
-
};
|
|
138
|
+
export const L0ItemActiveTabIndicator = ({ classNames }: ThemedClassName<{}>) => (
|
|
139
|
+
<div
|
|
140
|
+
role='none'
|
|
141
|
+
className={mx(
|
|
142
|
+
'hidden group-aria-selected/l0item:block absolute inline-start-0 inset-block-2 is-1 bg-accentSurface rounded-ie',
|
|
143
|
+
classNames,
|
|
144
|
+
)}
|
|
145
|
+
/>
|
|
146
|
+
);
|
|
151
147
|
|
|
152
148
|
// TODO(burdon): Factor out pinned (non-draggable) items.
|
|
153
149
|
const L0Item = ({ item, parent, path, pinned, onRearrange }: L0ItemProps) => {
|
|
154
|
-
const { t } = useTranslation(
|
|
150
|
+
const { t } = useTranslation(meta.id);
|
|
155
151
|
const itemElement = useRef<HTMLElement | null>(null);
|
|
156
152
|
const [closestEdge, setEdge] = useState<Edge | null>(null);
|
|
157
153
|
const localizedString = toLocalizedString(item.properties.label, t);
|
|
@@ -228,10 +224,7 @@ const L0Item = ({ item, parent, path, pinned, onRearrange }: L0ItemProps) => {
|
|
|
228
224
|
>
|
|
229
225
|
<ItemAvatar item={item} />
|
|
230
226
|
</div>
|
|
231
|
-
<
|
|
232
|
-
role='none'
|
|
233
|
-
className='hidden group-aria-selected/l0item:block absolute inline-start-0 inset-block-2 is-1 bg-accentSurface rounded-ie'
|
|
234
|
-
/>
|
|
227
|
+
<L0ItemActiveTabIndicator />
|
|
235
228
|
<span id={`${item.id}__label`} className='sr-only'>
|
|
236
229
|
{localizedString}
|
|
237
230
|
</span>
|
|
@@ -241,83 +234,68 @@ const L0Item = ({ item, parent, path, pinned, onRearrange }: L0ItemProps) => {
|
|
|
241
234
|
};
|
|
242
235
|
|
|
243
236
|
const ItemAvatar = ({ item }: Pick<L0ItemProps, 'item'>) => {
|
|
237
|
+
const { t } = useTranslation(meta.id);
|
|
244
238
|
const type = l0ItemType(item);
|
|
245
239
|
if (item.properties.icon) {
|
|
246
240
|
const hue = item.properties.hue ?? null;
|
|
247
241
|
const hueFgStyle = hue && { style: { color: `var(--dx-${hue}SurfaceText)` } };
|
|
248
|
-
return <Icon icon={item.properties.icon} size={
|
|
242
|
+
return <Icon icon={item.properties.icon} size={6} {...hueFgStyle} />;
|
|
249
243
|
}
|
|
250
244
|
|
|
251
245
|
if (type === 'tab' && item.properties.disposition !== 'pin-end') {
|
|
252
|
-
|
|
246
|
+
const hue = item.properties.hue ?? null;
|
|
247
|
+
const localizedString = toLocalizedString(item.properties.label, t);
|
|
248
|
+
return <DxAvatar hue={hue} hueVariant='surface' variant='square' size={12} fallback={localizedString} />;
|
|
253
249
|
}
|
|
254
250
|
|
|
255
251
|
return null;
|
|
256
252
|
};
|
|
257
253
|
|
|
258
254
|
//
|
|
259
|
-
//
|
|
255
|
+
// L0Menu
|
|
260
256
|
//
|
|
261
257
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
258
|
+
export type L0MenuProps = {
|
|
259
|
+
menuActions: MenuItem[];
|
|
260
|
+
topLevelItems: Node.Node[];
|
|
261
|
+
pinnedItems: Node.Node[];
|
|
262
|
+
userAccountItem?: Node.Node;
|
|
263
|
+
parent?: Node.Node;
|
|
264
|
+
path: string[];
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountItem, parent, path }: L0MenuProps) => {
|
|
268
|
+
const { t } = useTranslation(meta.id);
|
|
269
|
+
const runAction = useActionRunner();
|
|
270
|
+
const handleAction = useCallback(
|
|
271
|
+
(action: Node.Action, params: Node.InvokeProps) => {
|
|
272
|
+
void runAction(action, params);
|
|
273
|
+
},
|
|
274
|
+
[runAction],
|
|
275
|
+
);
|
|
268
276
|
|
|
269
277
|
const handleRearrange = useCallback<StackItemRearrangeHandler<L0ItemData>>(
|
|
270
278
|
(source, target, closestEdge) => {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
279
|
+
const sourceItem = topLevelItems.find((i) => i.id === source.id);
|
|
280
|
+
if (!sourceItem?.properties.onRearrange) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const sourceIndex = topLevelItems.findIndex((i) => i.id === source.id);
|
|
285
|
+
const targetIndex = topLevelItems.findIndex((i) => i.id === target.id);
|
|
274
286
|
const insertIndex =
|
|
275
287
|
source.id === target.id
|
|
276
288
|
? sourceIndex
|
|
277
289
|
: targetIndex +
|
|
278
290
|
(sourceIndex < targetIndex ? (closestEdge === 'top' ? -1 : 0) : closestEdge === 'bottom' ? 1 : 0);
|
|
279
|
-
const nextOrder = arrayMove([...
|
|
280
|
-
return
|
|
291
|
+
const nextOrder = arrayMove([...topLevelItems], sourceIndex, insertIndex);
|
|
292
|
+
return sourceItem.properties.onRearrange(nextOrder.map((item) => item.data));
|
|
281
293
|
},
|
|
282
|
-
[
|
|
294
|
+
[topLevelItems],
|
|
283
295
|
);
|
|
284
296
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
role='group'
|
|
288
|
-
className='contents group/l0c'
|
|
289
|
-
aria-labelledby={`${item.id}__label`}
|
|
290
|
-
data-itemid={id}
|
|
291
|
-
data-testid={testId}
|
|
292
|
-
>
|
|
293
|
-
{collectionItems.map((collectionItem) => (
|
|
294
|
-
<L0Item
|
|
295
|
-
key={collectionItem.id}
|
|
296
|
-
item={collectionItem}
|
|
297
|
-
parent={item}
|
|
298
|
-
path={groupPath}
|
|
299
|
-
{...(item.properties.onRearrangeChildren && { onRearrange: handleRearrange })}
|
|
300
|
-
/>
|
|
301
|
-
))}
|
|
302
|
-
</div>
|
|
303
|
-
);
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
//
|
|
307
|
-
// L0Menu
|
|
308
|
-
//
|
|
309
|
-
|
|
310
|
-
export type L0MenuProps = {
|
|
311
|
-
menuActions: MenuItem[];
|
|
312
|
-
topLevelItems: Node<any>[];
|
|
313
|
-
pinnedItems: Node<any>[];
|
|
314
|
-
userAccountItem?: Node<any>;
|
|
315
|
-
parent?: Node<any>;
|
|
316
|
-
path: string[];
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountItem, parent, path }: L0MenuProps) => {
|
|
320
|
-
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
297
|
+
// Check if any items have onRearrange to enable drag-and-drop.
|
|
298
|
+
const hasRearrangeableItems = topLevelItems.some((item) => item.properties.onRearrange);
|
|
321
299
|
|
|
322
300
|
return (
|
|
323
301
|
<Tabs.Tablist
|
|
@@ -328,23 +306,29 @@ export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountIte
|
|
|
328
306
|
]}
|
|
329
307
|
>
|
|
330
308
|
{/* TODO(wittjosiah): Use L0Item trigger. */}
|
|
331
|
-
<MenuProvider>
|
|
309
|
+
<MenuProvider onAction={handleAction}>
|
|
332
310
|
<DropdownMenu.Root group={parent} items={menuActions}>
|
|
333
311
|
<Tooltip.Trigger content={t('app menu label')} side='right' asChild>
|
|
334
|
-
<
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
>
|
|
338
|
-
<div
|
|
339
|
-
role='none'
|
|
312
|
+
<Tabs.TabPrimitive value='options' asChild role='button'>
|
|
313
|
+
<DropdownMenu.Trigger
|
|
314
|
+
data-testid='spacePlugin.addSpace'
|
|
340
315
|
className={mx(
|
|
341
|
-
|
|
342
|
-
'
|
|
316
|
+
l0ItemRoot,
|
|
317
|
+
'grid place-items-center dx-focus-ring-group',
|
|
318
|
+
'[body[data-platform="macos"]_&]:mt-[30px]',
|
|
343
319
|
)}
|
|
344
320
|
>
|
|
345
|
-
<
|
|
346
|
-
|
|
347
|
-
|
|
321
|
+
<div
|
|
322
|
+
role='none'
|
|
323
|
+
className={mx(
|
|
324
|
+
l0ItemContent,
|
|
325
|
+
'is-[--rail-action] bs-[--rail-action] group-hover/l0item:bg-hoverSurface',
|
|
326
|
+
)}
|
|
327
|
+
>
|
|
328
|
+
<Icon icon='ph--list--regular' size={5} />
|
|
329
|
+
</div>
|
|
330
|
+
</DropdownMenu.Trigger>
|
|
331
|
+
</Tabs.TabPrimitive>
|
|
348
332
|
</Tooltip.Trigger>
|
|
349
333
|
</DropdownMenu.Root>
|
|
350
334
|
</MenuProvider>
|
|
@@ -356,17 +340,19 @@ export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountIte
|
|
|
356
340
|
role='none'
|
|
357
341
|
className={mx([
|
|
358
342
|
'flex flex-col gap-1 pbs-1',
|
|
359
|
-
'[body[data-platform="
|
|
343
|
+
'[body[data-platform="macos"]_&]:pbs-[30px]',
|
|
360
344
|
'[body[data-platform="ios"]_&]:pbs-[max(env(safe-area-inset-top),0.25rem)]',
|
|
361
345
|
])}
|
|
362
346
|
>
|
|
363
|
-
{topLevelItems.map((item) =>
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
347
|
+
{topLevelItems.map((item) => (
|
|
348
|
+
<L0Item
|
|
349
|
+
key={item.id}
|
|
350
|
+
item={item}
|
|
351
|
+
parent={parent}
|
|
352
|
+
path={path}
|
|
353
|
+
{...(hasRearrangeableItems && { onRearrange: handleRearrange })}
|
|
354
|
+
/>
|
|
355
|
+
))}
|
|
370
356
|
</div>
|
|
371
357
|
<ScrollArea.Scrollbar orientation='vertical'>
|
|
372
358
|
<ScrollArea.Thumb />
|
|
@@ -376,11 +362,9 @@ export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountIte
|
|
|
376
362
|
|
|
377
363
|
{/* Actions. */}
|
|
378
364
|
<div role='none' className='grid grid-cols-1 auto-rows-[--rail-action] pbs-2'>
|
|
379
|
-
{pinnedItems
|
|
380
|
-
.
|
|
381
|
-
|
|
382
|
-
<L0Item key={item.id} item={item} parent={parent} path={path} pinned />
|
|
383
|
-
))}
|
|
365
|
+
{pinnedItems.map((item) => (
|
|
366
|
+
<L0Item key={item.id} item={item} parent={parent} path={path} pinned />
|
|
367
|
+
))}
|
|
384
368
|
</div>
|
|
385
369
|
|
|
386
370
|
{userAccountItem && (
|
|
@@ -396,15 +380,6 @@ export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountIte
|
|
|
396
380
|
</L0ItemRoot>
|
|
397
381
|
</div>
|
|
398
382
|
)}
|
|
399
|
-
|
|
400
|
-
<div
|
|
401
|
-
role='none'
|
|
402
|
-
className='hidden [body[data-platform="darwin"]_&]:block absolute block-start-0 is-[calc(var(--l0-size)-1px)] bs-[calc(40px+0.25rem)]'
|
|
403
|
-
style={{
|
|
404
|
-
background:
|
|
405
|
-
'linear-gradient(to bottom, var(--dx-sidebarSurface) 0%, var(--dx-sidebarSurface) 70%, transparent 100%)',
|
|
406
|
-
}}
|
|
407
|
-
/>
|
|
408
383
|
</Tabs.Tablist>
|
|
409
384
|
);
|
|
410
385
|
};
|
|
@@ -5,68 +5,45 @@
|
|
|
5
5
|
import React, { useCallback, useMemo } from 'react';
|
|
6
6
|
|
|
7
7
|
import { type Node } from '@dxos/app-graph';
|
|
8
|
-
import {
|
|
8
|
+
import { DensityProvider, IconButton, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
9
9
|
import { Tree } from '@dxos/react-ui-list';
|
|
10
10
|
import { Tabs } from '@dxos/react-ui-tabs';
|
|
11
|
-
import { hoverableControlItem, hoverableOpenControlItem
|
|
11
|
+
import { hoverableControlItem, hoverableOpenControlItem } from '@dxos/ui-theme';
|
|
12
12
|
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { l0ItemType } from '../../util';
|
|
13
|
+
import { useIsAlternateTree } from '../../hooks';
|
|
14
|
+
import { meta } from '../../meta';
|
|
16
15
|
import { useNavTreeContext } from '../NavTreeContext';
|
|
17
16
|
import { NavTreeItemColumns } from '../NavTreeItem';
|
|
18
17
|
|
|
19
|
-
const headingBackButtonLabel = 'inset-0 min-is-0 truncate flex items-center pis-2';
|
|
20
|
-
|
|
21
|
-
const TitleButton = ({ title, onClick }: { title: string } & Pick<ButtonProps, 'onClick'>) => {
|
|
22
|
-
return (
|
|
23
|
-
<Button
|
|
24
|
-
variant='ghost'
|
|
25
|
-
classNames='pli-1 flex-1 group text-start justify-start bs-[--rail-action] font-normal'
|
|
26
|
-
onClick={onClick}
|
|
27
|
-
>
|
|
28
|
-
<Icon icon='ph--caret-left--bold' size={3} />
|
|
29
|
-
<span className={mx(headingBackButtonLabel)}>{title}</span>
|
|
30
|
-
</Button>
|
|
31
|
-
);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
18
|
export type L1PanelProps = {
|
|
35
19
|
open?: boolean;
|
|
36
|
-
item: Node<any>;
|
|
37
20
|
path: string[];
|
|
21
|
+
item: Node.Node;
|
|
38
22
|
currentItemId: string;
|
|
39
23
|
onBack?: () => void;
|
|
40
24
|
};
|
|
41
25
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Space or settings panel.
|
|
28
|
+
*/
|
|
29
|
+
export const L1Panel = ({ open, path, item, currentItemId, onBack }: L1PanelProps) => {
|
|
30
|
+
const { t } = useTranslation(meta.id);
|
|
31
|
+
const navTreeContext = useNavTreeContext();
|
|
32
|
+
const title = toLocalizedString(item.properties.label, t);
|
|
45
33
|
|
|
46
34
|
// TODO(wittjosiah): Support multiple alternate trees.
|
|
47
|
-
const
|
|
35
|
+
const { useItems } = navTreeContext;
|
|
36
|
+
const alternateTree = useItems(item, { disposition: 'alternate-tree' })[0];
|
|
48
37
|
const alternatePath = useMemo(() => [...path, item.id], [item.id, path]);
|
|
49
|
-
const
|
|
50
|
-
const isAlternate = isAlternateTree?.(alternatePath, item) ?? false;
|
|
38
|
+
const isAlternate = useIsAlternateTree(alternatePath, item);
|
|
51
39
|
const useAlternateItems = useCallback(
|
|
52
|
-
(node?: Node, { disposition }: { disposition?: string } = {}) => {
|
|
40
|
+
(node?: Node.Node, { disposition }: { disposition?: string } = {}) => {
|
|
53
41
|
// TODO(wittjosiah): Sorting is expensive, limit to necessary items for now.
|
|
54
|
-
return
|
|
42
|
+
return useItems(node, { disposition, sort: node?.id === alternateTree.id });
|
|
55
43
|
},
|
|
56
|
-
[
|
|
44
|
+
[alternateTree, useItems],
|
|
57
45
|
);
|
|
58
46
|
|
|
59
|
-
const handleBack = useCallback(() => {
|
|
60
|
-
if (isAlternate) {
|
|
61
|
-
setAlternateTree?.(alternatePath, false);
|
|
62
|
-
} else {
|
|
63
|
-
onBack?.();
|
|
64
|
-
}
|
|
65
|
-
}, [isAlternate, onBack, alternatePath, setAlternateTree]);
|
|
66
|
-
|
|
67
|
-
const title = toLocalizedString(item.properties.label, t);
|
|
68
|
-
const backCapable = item.id.startsWith('!') || isAlternate;
|
|
69
|
-
|
|
70
47
|
return (
|
|
71
48
|
<Tabs.Tabpanel
|
|
72
49
|
key={item.id}
|
|
@@ -79,41 +56,22 @@ const L1Panel = ({ open, item, path, currentItemId, onBack }: L1PanelProps) => {
|
|
|
79
56
|
]}
|
|
80
57
|
tabIndex={-1}
|
|
81
58
|
aria-label={title}
|
|
82
|
-
{...(!open && { inert:
|
|
59
|
+
{...(!open && { inert: true })}
|
|
83
60
|
>
|
|
84
61
|
{item.id === currentItemId && (
|
|
85
|
-
|
|
86
|
-
<
|
|
87
|
-
{backCapable ? (
|
|
88
|
-
<TitleButton title={title} onClick={handleBack} />
|
|
89
|
-
) : (
|
|
90
|
-
<span className='flex-1 truncate min-is-0 pis-6'>{title}</span>
|
|
91
|
-
)}
|
|
92
|
-
{alternateTree && !isAlternate && (
|
|
93
|
-
<IconButton
|
|
94
|
-
variant='ghost'
|
|
95
|
-
classNames={['shrink-0', hoverableControlItem, hoverableOpenControlItem, 'pli-2 pointer-fine:pli-1']}
|
|
96
|
-
iconOnly
|
|
97
|
-
size={5}
|
|
98
|
-
icon={alternateTree.properties.icon ?? 'ph--placeholder--regular'}
|
|
99
|
-
label={toLocalizedString(alternateTree.properties.label ?? alternateTree.id, t)}
|
|
100
|
-
data-testid='treeView.alternateTreeButton'
|
|
101
|
-
onClick={handleOpen}
|
|
102
|
-
/>
|
|
103
|
-
)}
|
|
104
|
-
<NavTreeItemColumns path={path} item={item} open density='coarse' />
|
|
105
|
-
</h2>
|
|
62
|
+
<DensityProvider density='fine'>
|
|
63
|
+
<L1PanelHeader path={path} item={item} currentItemId={currentItemId} onBack={onBack} />
|
|
106
64
|
<div role='none' className='overflow-y-auto'>
|
|
107
65
|
{isAlternate ? (
|
|
108
66
|
<Tree
|
|
109
67
|
{...navTreeContext}
|
|
110
|
-
useItems={useAlternateItems}
|
|
111
68
|
id={alternateTree.id}
|
|
112
69
|
root={alternateTree}
|
|
113
70
|
path={alternatePath}
|
|
114
71
|
levelOffset={5}
|
|
115
72
|
gridTemplateColumns='[tree-row-start] 1fr min-content min-content min-content [tree-row-end]'
|
|
116
73
|
renderColumns={NavTreeItemColumns}
|
|
74
|
+
useItems={useAlternateItems}
|
|
117
75
|
/>
|
|
118
76
|
) : (
|
|
119
77
|
<Tree
|
|
@@ -122,53 +80,72 @@ const L1Panel = ({ open, item, path, currentItemId, onBack }: L1PanelProps) => {
|
|
|
122
80
|
root={item}
|
|
123
81
|
path={path}
|
|
124
82
|
levelOffset={5}
|
|
125
|
-
draggable
|
|
126
83
|
gridTemplateColumns='[tree-row-start] 1fr min-content min-content min-content [tree-row-end]'
|
|
127
84
|
renderColumns={NavTreeItemColumns}
|
|
85
|
+
draggable
|
|
128
86
|
/>
|
|
129
87
|
)}
|
|
130
88
|
</div>
|
|
131
|
-
|
|
89
|
+
</DensityProvider>
|
|
132
90
|
)}
|
|
133
91
|
</Tabs.Tabpanel>
|
|
134
92
|
);
|
|
135
93
|
};
|
|
136
94
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
{collectionItems
|
|
145
|
-
.filter((item) => l0ItemType(item) === 'tab')
|
|
146
|
-
.map((item) => (
|
|
147
|
-
<L1Panel key={item.id} item={item} path={groupPath} {...props} />
|
|
148
|
-
))}
|
|
149
|
-
</>
|
|
150
|
-
);
|
|
151
|
-
};
|
|
95
|
+
/**
|
|
96
|
+
* Header row.
|
|
97
|
+
*/
|
|
98
|
+
const L1PanelHeader = ({ item, path, onBack }: L1PanelProps) => {
|
|
99
|
+
const { t } = useTranslation(meta.id);
|
|
100
|
+
const { setAlternateTree, ...navTreeContext } = useNavTreeContext();
|
|
101
|
+
const title = toLocalizedString(item.properties.label, t);
|
|
152
102
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
path
|
|
156
|
-
|
|
103
|
+
// TODO(wittjosiah): Support multiple alternate trees.
|
|
104
|
+
const alternateTree = navTreeContext.useItems(item, { disposition: 'alternate-tree' })[0];
|
|
105
|
+
const alternatePath = useMemo(() => [...path, item.id], [item.id, path]);
|
|
106
|
+
const isAlternate = useIsAlternateTree(alternatePath, item);
|
|
107
|
+
const backCapable = item.id.startsWith('!') || isAlternate;
|
|
108
|
+
|
|
109
|
+
const handleOpen = useCallback(() => {
|
|
110
|
+
setAlternateTree?.(alternatePath, true);
|
|
111
|
+
}, [alternatePath, setAlternateTree]);
|
|
157
112
|
|
|
158
|
-
|
|
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?
|
|
159
122
|
return (
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
123
|
+
<div className='flex is-full items-center border-be border-subduedSeparator app-drag density-coarse'>
|
|
124
|
+
<div className='is-6' />
|
|
125
|
+
<h2 className='flex-1 truncate min-is-0'>{title}</h2>
|
|
126
|
+
{(backCapable && (
|
|
127
|
+
<IconButton
|
|
128
|
+
data-testid='treeView.primaryTreeButton'
|
|
129
|
+
variant='ghost'
|
|
130
|
+
icon='ph--arrow-u-down-left--regular'
|
|
131
|
+
iconOnly
|
|
132
|
+
label={t('button back')}
|
|
133
|
+
classNames={[hoverableControlItem, hoverableOpenControlItem, 'pointer-fine:pli-1']}
|
|
134
|
+
onClick={handleBack}
|
|
135
|
+
/>
|
|
136
|
+
)) ||
|
|
137
|
+
(alternateTree && !isAlternate && (
|
|
138
|
+
<IconButton
|
|
139
|
+
data-testid='treeView.alternateTreeButton'
|
|
140
|
+
variant='ghost'
|
|
141
|
+
icon={alternateTree.properties.icon ?? 'ph--placeholder--regular'}
|
|
142
|
+
iconOnly
|
|
143
|
+
label={toLocalizedString(alternateTree.properties.label ?? alternateTree.id, t)}
|
|
144
|
+
classNames={[hoverableControlItem, hoverableOpenControlItem, 'pointer-fine:pli-1']}
|
|
145
|
+
onClick={handleOpen}
|
|
146
|
+
/>
|
|
147
|
+
))}
|
|
148
|
+
<NavTreeItemColumns open path={path} item={item} density='coarse' />
|
|
149
|
+
</div>
|
|
173
150
|
);
|
|
174
151
|
};
|