@dxos/plugin-navtree 0.8.2-main.f11618f → 0.8.2-staging.7ac8446
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-TLQLMZXU.mjs → chunk-4RQJXI4D.mjs} +1 -1
- package/dist/lib/browser/chunk-4RQJXI4D.mjs.map +7 -0
- package/dist/lib/browser/{chunk-FHOAKMRS.mjs → chunk-DN43QXSX.mjs} +47 -134
- package/dist/lib/browser/chunk-DN43QXSX.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +2 -3
- package/dist/lib/browser/index.mjs.map +2 -2
- package/dist/lib/browser/{intent-resolver-OBGGMBVJ.mjs → intent-resolver-BZMUS24C.mjs} +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-DWMOF2TM.mjs → react-surface-3HCM3SHJ.mjs} +3 -3
- package/dist/lib/browser/{state-EW62QYEN.mjs → state-M5UJ3MHL.mjs} +11 -17
- package/dist/lib/browser/state-M5UJ3MHL.mjs.map +7 -0
- package/dist/types/src/capabilities/capabilities.d.ts +4 -7
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +3 -34
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/state.d.ts +4 -7
- package/dist/types/src/capabilities/state.d.ts.map +1 -1
- package/dist/types/src/components/L1Panels.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeItemAction.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeItemColumns.d.ts +1 -1
- package/dist/types/src/components/NavTreeItemColumns.d.ts.map +1 -1
- package/dist/types/src/components/types.d.ts +0 -4
- package/dist/types/src/components/types.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/translations.d.ts +0 -1
- package/dist/types/src/translations.d.ts.map +1 -1
- package/package.json +31 -31
- package/src/capabilities/capabilities.ts +4 -5
- package/src/capabilities/state.ts +14 -20
- package/src/components/L1Panels.tsx +30 -115
- package/src/components/NavTree.stories.tsx +5 -5
- package/src/components/NavTreeContainer.tsx +2 -16
- package/src/components/NavTreeItemAction.tsx +4 -10
- package/src/components/NavTreeItemColumns.tsx +27 -29
- package/src/components/UserAccountAvatar.tsx +1 -1
- package/src/components/types.ts +0 -4
- package/src/stories/Graph.stories.tsx +4 -4
- package/src/testing/generator.ts +3 -3
- package/src/translations.ts +0 -1
- package/dist/lib/browser/chunk-FHOAKMRS.mjs.map +0 -7
- package/dist/lib/browser/chunk-TLQLMZXU.mjs.map +0 -7
- package/dist/lib/browser/state-EW62QYEN.mjs.map +0 -7
- /package/dist/lib/browser/{intent-resolver-OBGGMBVJ.mjs.map → intent-resolver-BZMUS24C.mjs.map} +0 -0
- /package/dist/lib/browser/{react-surface-DWMOF2TM.mjs.map → react-surface-3HCM3SHJ.mjs.map} +0 -0
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, {
|
|
5
|
+
import React, { useMemo } from 'react';
|
|
6
6
|
|
|
7
7
|
import { useLayout } from '@dxos/app-framework';
|
|
8
8
|
import { type Node } from '@dxos/app-graph';
|
|
9
|
-
import { Button,
|
|
9
|
+
import { Button, Icon, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
10
10
|
import { Tree } from '@dxos/react-ui-list';
|
|
11
11
|
import { Tabs } from '@dxos/react-ui-tabs';
|
|
12
12
|
import { hoverableControlItem, hoverableOpenControlItem, mx } from '@dxos/react-ui-theme';
|
|
13
|
-
import { byPosition } from '@dxos/util';
|
|
14
13
|
|
|
15
14
|
import { useNavTreeContext } from './NavTreeContext';
|
|
16
15
|
import { NavTreeItemColumns } from './NavTreeItemColumns';
|
|
@@ -18,78 +17,12 @@ import { useLoadDescendents } from '../hooks';
|
|
|
18
17
|
import { NAVTREE_PLUGIN } from '../meta';
|
|
19
18
|
import { l0ItemType } from '../util';
|
|
20
19
|
|
|
21
|
-
export type L1PanelProps = {
|
|
22
|
-
item: Node<any>;
|
|
23
|
-
path: string[];
|
|
24
|
-
currentItemId: string;
|
|
25
|
-
onBack?: () => void;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const headingBackButtonLabel =
|
|
29
|
-
'absolute inset-0 min-is-0 truncate flex items-center pis-6 transition-[transform,opacity] ease-in-out duration-200';
|
|
30
|
-
|
|
31
|
-
const HeadingBackButton = ({ title, onClick }: { title: string } & Pick<ButtonProps, 'onClick'>) => {
|
|
32
|
-
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
33
|
-
return (
|
|
34
|
-
<Button
|
|
35
|
-
variant='ghost'
|
|
36
|
-
classNames='pli-1 flex-1 relative group text-start justify-start bs-[--rail-action] font-normal'
|
|
37
|
-
onClick={onClick}
|
|
38
|
-
>
|
|
39
|
-
<Icon icon='ph--caret-left--bold' size={3} />
|
|
40
|
-
<span
|
|
41
|
-
className={mx(
|
|
42
|
-
headingBackButtonLabel,
|
|
43
|
-
'translate-y-2 opacity-0 group-hover:translate-y-0 group-hover:opacity-100 group-focus:translate-y-0 group-focus:opacity-100',
|
|
44
|
-
)}
|
|
45
|
-
>
|
|
46
|
-
{t('back label')}
|
|
47
|
-
</span>
|
|
48
|
-
<span
|
|
49
|
-
className={mx(
|
|
50
|
-
headingBackButtonLabel,
|
|
51
|
-
'translate-y-0 opacity-100 group-hover:-translate-y-2 group-hover:opacity-0 group-focus:-translate-y-2 group-focus:opacity-0',
|
|
52
|
-
)}
|
|
53
|
-
>
|
|
54
|
-
{title}
|
|
55
|
-
</span>
|
|
56
|
-
</Button>
|
|
57
|
-
);
|
|
58
|
-
};
|
|
20
|
+
export type L1PanelProps = { item: Node<any>; path: string[]; currentItemId: string; onBack?: () => void };
|
|
59
21
|
|
|
60
22
|
const L1Panel = ({ item, path, currentItemId, onBack }: L1PanelProps) => {
|
|
61
23
|
const layout = useLayout();
|
|
62
|
-
const
|
|
24
|
+
const navTreeContext = useNavTreeContext();
|
|
63
25
|
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
64
|
-
|
|
65
|
-
// TODO(wittjosiah): Support multiple alternate trees.
|
|
66
|
-
const alternateTree = navTreeContext.getItems(item, 'alternate-tree')[0];
|
|
67
|
-
const alternatePath = useMemo(() => [...path, item.id], [item.id, path]);
|
|
68
|
-
const handleOpen = useCallback(() => setAlternateTree?.(alternatePath, true), [alternatePath, setAlternateTree]);
|
|
69
|
-
const isAlternate = isAlternateTree?.(alternatePath, item) ?? false;
|
|
70
|
-
const alternateGetItems = useCallback(
|
|
71
|
-
(node?: Node, disposition?: string) => {
|
|
72
|
-
const items = navTreeContext.getItems(node, disposition);
|
|
73
|
-
if (node === alternateTree) {
|
|
74
|
-
// TODO(wittjosiah): Sorting is expensive, limit to necessary items for now.
|
|
75
|
-
return items.toSorted((a, b) => byPosition(a.properties, b.properties));
|
|
76
|
-
}
|
|
77
|
-
return items;
|
|
78
|
-
},
|
|
79
|
-
[navTreeContext, alternateTree],
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
const handleBack = useCallback(() => {
|
|
83
|
-
if (isAlternate) {
|
|
84
|
-
setAlternateTree?.(alternatePath, false);
|
|
85
|
-
} else {
|
|
86
|
-
onBack?.();
|
|
87
|
-
}
|
|
88
|
-
}, [isAlternate, onBack, alternatePath, setAlternateTree]);
|
|
89
|
-
|
|
90
|
-
const title = toLocalizedString(item.properties.label, t);
|
|
91
|
-
const backCapable = item.id.startsWith('!') || isAlternate;
|
|
92
|
-
|
|
93
26
|
return (
|
|
94
27
|
<Tabs.Tabpanel
|
|
95
28
|
key={item.id}
|
|
@@ -99,56 +32,38 @@ const L1Panel = ({ item, path, currentItemId, onBack }: L1PanelProps) => {
|
|
|
99
32
|
item.id === currentItemId && 'grid',
|
|
100
33
|
]}
|
|
101
34
|
tabIndex={-1}
|
|
102
|
-
aria-label={title}
|
|
103
35
|
{...(!layout.sidebarOpen && { inert: 'true' })}
|
|
104
36
|
>
|
|
105
37
|
{item.id === currentItemId && (
|
|
106
38
|
<>
|
|
107
|
-
<h2 className='flex items-center border-be border-separator app-drag
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
onClick={handleOpen}
|
|
124
|
-
/>
|
|
125
|
-
)}
|
|
126
|
-
<NavTreeItemColumns path={path} item={item} open density='coarse' />
|
|
39
|
+
<h2 className='flex items-center border-be border-separator app-drag'>
|
|
40
|
+
<Button
|
|
41
|
+
variant='ghost'
|
|
42
|
+
density='fine'
|
|
43
|
+
classNames={mx(
|
|
44
|
+
'is-6 pli-0 dx-focus-ring-inset',
|
|
45
|
+
!item.id.startsWith('!') && 'invisible',
|
|
46
|
+
hoverableControlItem,
|
|
47
|
+
hoverableOpenControlItem,
|
|
48
|
+
)}
|
|
49
|
+
onClick={onBack}
|
|
50
|
+
>
|
|
51
|
+
<Icon icon='ph--caret-left--regular' size={3} />
|
|
52
|
+
</Button>
|
|
53
|
+
<span className='flex-1 truncate cursor-default'>{toLocalizedString(item.properties.label, t)}</span>
|
|
54
|
+
<NavTreeItemColumns path={path} item={item} open />
|
|
127
55
|
</h2>
|
|
128
56
|
<div role='none' className='overflow-y-auto'>
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
/>
|
|
140
|
-
) : (
|
|
141
|
-
<Tree
|
|
142
|
-
{...navTreeContext}
|
|
143
|
-
id={item.id}
|
|
144
|
-
root={item}
|
|
145
|
-
path={path}
|
|
146
|
-
levelOffset={5}
|
|
147
|
-
draggable
|
|
148
|
-
gridTemplateColumns='[tree-row-start] 1fr min-content min-content min-content [tree-row-end]'
|
|
149
|
-
renderColumns={NavTreeItemColumns}
|
|
150
|
-
/>
|
|
151
|
-
)}
|
|
57
|
+
<Tree
|
|
58
|
+
{...navTreeContext}
|
|
59
|
+
id={item.id}
|
|
60
|
+
root={item}
|
|
61
|
+
path={path}
|
|
62
|
+
levelOffset={5}
|
|
63
|
+
draggable
|
|
64
|
+
gridTemplateColumns='[tree-row-start] 1fr min-content min-content min-content [tree-row-end]'
|
|
65
|
+
renderColumns={NavTreeItemColumns}
|
|
66
|
+
/>
|
|
152
67
|
</div>
|
|
153
68
|
</>
|
|
154
69
|
)}
|
|
@@ -10,7 +10,7 @@ import { type Meta } from '@storybook/react';
|
|
|
10
10
|
import React, { useEffect } from 'react';
|
|
11
11
|
|
|
12
12
|
import { isActionLike, type NodeArg } from '@dxos/app-graph';
|
|
13
|
-
import {
|
|
13
|
+
import { create, type ReactiveObject } from '@dxos/live-object';
|
|
14
14
|
import { faker } from '@dxos/random';
|
|
15
15
|
import { isTreeData, type TreeData } from '@dxos/react-ui-list';
|
|
16
16
|
import { Path } from '@dxos/react-ui-list';
|
|
@@ -21,8 +21,8 @@ import { createTree, updateState } from '../testing';
|
|
|
21
21
|
|
|
22
22
|
faker.seed(1234);
|
|
23
23
|
|
|
24
|
-
const tree =
|
|
25
|
-
const state = new Map<string,
|
|
24
|
+
const tree = create<NodeArg<any>>(createTree());
|
|
25
|
+
const state = new Map<string, ReactiveObject<{ open: boolean; current: boolean }>>();
|
|
26
26
|
|
|
27
27
|
const meta: Meta<typeof StorybookNavTree> = {
|
|
28
28
|
title: 'plugins/plugin-navtree/NavTree',
|
|
@@ -73,7 +73,7 @@ const meta: Meta<typeof StorybookNavTree> = {
|
|
|
73
73
|
}),
|
|
74
74
|
isOpen: (_path: string[]) => {
|
|
75
75
|
const path = Path.create(..._path);
|
|
76
|
-
const value = state.get(path) ??
|
|
76
|
+
const value = state.get(path) ?? create({ open: false, current: false });
|
|
77
77
|
if (!state.has(path)) {
|
|
78
78
|
state.set(path, value);
|
|
79
79
|
}
|
|
@@ -82,7 +82,7 @@ const meta: Meta<typeof StorybookNavTree> = {
|
|
|
82
82
|
},
|
|
83
83
|
isCurrent: (_path: string[]) => {
|
|
84
84
|
const path = Path.create(..._path);
|
|
85
|
-
const value = state.get(path) ??
|
|
85
|
+
const value = state.get(path) ?? create({ open: false, current: false });
|
|
86
86
|
if (!state.has(path)) {
|
|
87
87
|
state.set(path, value);
|
|
88
88
|
}
|
|
@@ -59,7 +59,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
59
59
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
60
60
|
const { graph } = useAppGraph();
|
|
61
61
|
const layout = useLayout();
|
|
62
|
-
const { isOpen, isCurrent,
|
|
62
|
+
const { isOpen, isCurrent, setItem } = useCapability(NavTreeCapabilities.State);
|
|
63
63
|
|
|
64
64
|
const getActions = useCallback((node: Node) => naturalGetActions(graph, node), [graph]);
|
|
65
65
|
|
|
@@ -68,10 +68,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
68
68
|
return graph.nodes(node ?? graph.root, {
|
|
69
69
|
filter: (node): node is Node => {
|
|
70
70
|
return untracked(() => {
|
|
71
|
-
if (
|
|
72
|
-
!disposition &&
|
|
73
|
-
(node.properties.disposition === 'hidden' || node.properties.disposition === 'alternate-tree')
|
|
74
|
-
) {
|
|
71
|
+
if (node.properties.disposition === 'hidden') {
|
|
75
72
|
return false;
|
|
76
73
|
} else if (!disposition) {
|
|
77
74
|
const action = isAction(node);
|
|
@@ -265,13 +262,6 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
265
262
|
});
|
|
266
263
|
}, [graph]);
|
|
267
264
|
|
|
268
|
-
const setAlternateTree = useCallback(
|
|
269
|
-
(path: string[], open: boolean) => {
|
|
270
|
-
setItem(path, 'alternateTree', open);
|
|
271
|
-
},
|
|
272
|
-
[setItem],
|
|
273
|
-
);
|
|
274
|
-
|
|
275
265
|
const navTreeContextValue = useMemo(
|
|
276
266
|
() => ({
|
|
277
267
|
tab,
|
|
@@ -289,8 +279,6 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
289
279
|
onOpenChange,
|
|
290
280
|
canDrop,
|
|
291
281
|
onSelect: handleSelect,
|
|
292
|
-
isAlternateTree,
|
|
293
|
-
setAlternateTree,
|
|
294
282
|
}),
|
|
295
283
|
[
|
|
296
284
|
tab,
|
|
@@ -308,8 +296,6 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
308
296
|
onOpenChange,
|
|
309
297
|
canDrop,
|
|
310
298
|
handleSelect,
|
|
311
|
-
isAlternateTree,
|
|
312
|
-
setAlternateTree,
|
|
313
299
|
],
|
|
314
300
|
);
|
|
315
301
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React, { type MutableRefObject, useRef } from 'react';
|
|
6
6
|
|
|
7
7
|
import { type Action, type Node } from '@dxos/app-graph';
|
|
8
|
-
import { useTranslation, toLocalizedString, IconButton
|
|
8
|
+
import { useTranslation, toLocalizedString, IconButton } from '@dxos/react-ui';
|
|
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
|
|
|
@@ -23,14 +23,10 @@ export type NavTreeItemActionMenuProps = ActionProperties & {
|
|
|
23
23
|
|
|
24
24
|
const fallbackIcon = 'ph--placeholder--regular';
|
|
25
25
|
|
|
26
|
-
const
|
|
26
|
+
const actionButtonProps = {
|
|
27
27
|
size: 4 as const,
|
|
28
28
|
density: 'fine' as const,
|
|
29
29
|
};
|
|
30
|
-
const coarseActionButtonProps = {
|
|
31
|
-
size: 5 as const,
|
|
32
|
-
density: 'coarse' as const,
|
|
33
|
-
};
|
|
34
30
|
|
|
35
31
|
export const NavTreeItemActionDropdownMenu = ({
|
|
36
32
|
label,
|
|
@@ -41,13 +37,12 @@ export const NavTreeItemActionDropdownMenu = ({
|
|
|
41
37
|
}: NavTreeItemActionMenuProps) => {
|
|
42
38
|
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
43
39
|
const suppressNextTooltip = useRef<boolean>(false);
|
|
44
|
-
const density = useDensityContext();
|
|
45
40
|
return (
|
|
46
41
|
<MenuProvider onAction={onAction}>
|
|
47
42
|
<DropdownMenu.Root items={menuActions as MenuItem[]} suppressNextTooltip={suppressNextTooltip}>
|
|
48
43
|
<DropdownMenu.Trigger asChild>
|
|
49
44
|
<IconButton
|
|
50
|
-
{...
|
|
45
|
+
{...actionButtonProps}
|
|
51
46
|
classNames={mx('shrink-0 pli-2 pointer-fine:pli-1', hoverableControlItem, hoverableOpenControlItem)}
|
|
52
47
|
variant='ghost'
|
|
53
48
|
icon={icon ?? fallbackIcon}
|
|
@@ -68,10 +63,9 @@ export const NavTreeItemMonolithicAction = ({
|
|
|
68
63
|
data: invoke,
|
|
69
64
|
baseLabel,
|
|
70
65
|
}: Action & { parent: Node; onAction?: (action: Action) => void; baseLabel: string }) => {
|
|
71
|
-
const density = useDensityContext();
|
|
72
66
|
return (
|
|
73
67
|
<IconButton
|
|
74
|
-
{...
|
|
68
|
+
{...actionButtonProps}
|
|
75
69
|
variant={variant}
|
|
76
70
|
classNames={mx(
|
|
77
71
|
'shrink-0',
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React, { Fragment, memo } from 'react';
|
|
6
6
|
|
|
7
7
|
import { isAction } from '@dxos/app-graph';
|
|
8
|
-
import {
|
|
8
|
+
import { Popover, toLocalizedString, Treegrid, useTranslation } from '@dxos/react-ui';
|
|
9
9
|
|
|
10
10
|
import { NAV_TREE_ITEM } from './NavTree';
|
|
11
11
|
import { useNavTreeContext } from './NavTreeContext';
|
|
@@ -14,7 +14,7 @@ import type { NavTreeItemColumnsProps } from './types';
|
|
|
14
14
|
import { useLoadDescendents } from '../hooks';
|
|
15
15
|
import { NAVTREE_PLUGIN } from '../meta';
|
|
16
16
|
|
|
17
|
-
export const NavTreeItemColumns = memo(({ path, item, open
|
|
17
|
+
export const NavTreeItemColumns = memo(({ path, item, open }: NavTreeItemColumnsProps) => {
|
|
18
18
|
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
19
19
|
const { getActions, renderItemEnd: ItemEnd, popoverAnchorId } = useNavTreeContext();
|
|
20
20
|
|
|
@@ -35,39 +35,37 @@ export const NavTreeItemColumns = memo(({ path, item, open, density = 'fine' }:
|
|
|
35
35
|
useLoadDescendents(primaryAction && !isAction(primaryAction) ? primaryAction : undefined);
|
|
36
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
|
+
<NavTreeItemAction
|
|
41
|
+
testId={primaryAction.properties?.testId}
|
|
42
|
+
label={toLocalizedString(primaryAction.properties?.label, t)}
|
|
43
|
+
icon={primaryAction.properties?.icon ?? 'ph--placeholder--regular'}
|
|
44
|
+
parent={item}
|
|
45
|
+
monolithic={isAction(primaryAction)}
|
|
46
|
+
menuActions={isAction(primaryAction) ? [primaryAction] : groupedActions[primaryAction.id]}
|
|
47
|
+
menuType={primaryAction.properties?.menuType}
|
|
48
|
+
caller={NAV_TREE_ITEM}
|
|
49
|
+
/>
|
|
50
|
+
) : (
|
|
51
|
+
<Treegrid.Cell />
|
|
52
|
+
)}
|
|
53
|
+
<ActionRoot>
|
|
54
|
+
{actions.length > 0 ? (
|
|
41
55
|
<NavTreeItemAction
|
|
42
|
-
testId={
|
|
43
|
-
label={
|
|
44
|
-
icon=
|
|
56
|
+
testId={`navtree.treeItem.actionsLevel${level}`}
|
|
57
|
+
label={t('tree item actions label')}
|
|
58
|
+
icon='ph--dots-three-vertical--regular'
|
|
45
59
|
parent={item}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
menuType={primaryAction.properties?.menuType}
|
|
60
|
+
menuActions={actions}
|
|
61
|
+
menuType='dropdown'
|
|
49
62
|
caller={NAV_TREE_ITEM}
|
|
50
63
|
/>
|
|
51
64
|
) : (
|
|
52
65
|
<Treegrid.Cell />
|
|
53
66
|
)}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
testId={`navtree.treeItem.actionsLevel${level}`}
|
|
58
|
-
label={t('tree item actions label')}
|
|
59
|
-
icon='ph--dots-three-vertical--regular'
|
|
60
|
-
parent={item}
|
|
61
|
-
menuActions={actions}
|
|
62
|
-
menuType='dropdown'
|
|
63
|
-
caller={NAV_TREE_ITEM}
|
|
64
|
-
/>
|
|
65
|
-
) : (
|
|
66
|
-
<Treegrid.Cell />
|
|
67
|
-
)}
|
|
68
|
-
</ActionRoot>
|
|
69
|
-
{ItemEnd && <ItemEnd node={item} open={open} />}
|
|
70
|
-
</div>
|
|
71
|
-
</DensityProvider>
|
|
67
|
+
</ActionRoot>
|
|
68
|
+
{ItemEnd && <ItemEnd node={item} open={open} />}
|
|
69
|
+
</div>
|
|
72
70
|
);
|
|
73
71
|
});
|
|
@@ -27,7 +27,7 @@ export const UserAccountAvatar = (props: UserAccountAvatarProps) => {
|
|
|
27
27
|
status={props.status ?? 'active'}
|
|
28
28
|
hue={props.hue || fallbackValue.hue}
|
|
29
29
|
fallback={props.emoji || fallbackValue.emoji}
|
|
30
|
-
data-testid='
|
|
30
|
+
data-testid='treeview.userAccount'
|
|
31
31
|
/>
|
|
32
32
|
</Avatar.Root>
|
|
33
33
|
</div>
|
package/src/components/types.ts
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import type { FC } from 'react';
|
|
6
6
|
|
|
7
7
|
import type { Node } from '@dxos/app-graph';
|
|
8
|
-
import type { Density } from '@dxos/react-ui';
|
|
9
8
|
import type { TreeProps } from '@dxos/react-ui-list';
|
|
10
9
|
import type { MaybePromise } from '@dxos/util';
|
|
11
10
|
|
|
@@ -16,7 +15,6 @@ export type NavTreeItemColumnsProps = {
|
|
|
16
15
|
path: string[];
|
|
17
16
|
item: Node;
|
|
18
17
|
open: boolean;
|
|
19
|
-
density?: Density;
|
|
20
18
|
};
|
|
21
19
|
|
|
22
20
|
export type NavTreeProps = Pick<TreeProps<NavTreeItemGraphNode>, 'id' | 'root'>;
|
|
@@ -34,6 +32,4 @@ export type NavTreeContextValue = Pick<
|
|
|
34
32
|
renderItemEnd?: FC<{ node: Node; open: boolean }>;
|
|
35
33
|
popoverAnchorId?: string;
|
|
36
34
|
topbar?: boolean;
|
|
37
|
-
isAlternateTree?: (path: string[], item: NavTreeItemGraphNode) => boolean;
|
|
38
|
-
setAlternateTree?: (path: string[], open: boolean) => void;
|
|
39
35
|
};
|
|
@@ -12,7 +12,7 @@ import React, { useEffect } from 'react';
|
|
|
12
12
|
|
|
13
13
|
import { Graph, ROOT_ID, type Node } from '@dxos/app-graph';
|
|
14
14
|
import { registerSignalsRuntime } from '@dxos/echo-signals/react';
|
|
15
|
-
import {
|
|
15
|
+
import { create, type ReactiveObject } from '@dxos/live-object';
|
|
16
16
|
import { faker } from '@dxos/random';
|
|
17
17
|
import { isTreeData, type PropsFromTreeItem } from '@dxos/react-ui-list';
|
|
18
18
|
import { Path } from '@dxos/react-ui-list';
|
|
@@ -49,7 +49,7 @@ const createGraph = () => {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
const graph = createGraph();
|
|
52
|
-
const state = new Map<string,
|
|
52
|
+
const state = new Map<string, ReactiveObject<{ open: boolean; current: boolean }>>();
|
|
53
53
|
|
|
54
54
|
export const Default = {};
|
|
55
55
|
|
|
@@ -98,7 +98,7 @@ const meta: Meta<typeof StorybookNavTree> = {
|
|
|
98
98
|
},
|
|
99
99
|
isOpen: (_path: string[]) => {
|
|
100
100
|
const path = Path.create(..._path);
|
|
101
|
-
const value = state.get(path) ??
|
|
101
|
+
const value = state.get(path) ?? create({ open: false, current: false });
|
|
102
102
|
if (!state.has(path)) {
|
|
103
103
|
state.set(path, value);
|
|
104
104
|
}
|
|
@@ -107,7 +107,7 @@ const meta: Meta<typeof StorybookNavTree> = {
|
|
|
107
107
|
},
|
|
108
108
|
isCurrent: (_path: string[]) => {
|
|
109
109
|
const path = Path.create(..._path);
|
|
110
|
-
const value = state.get(path) ??
|
|
110
|
+
const value = state.get(path) ?? create({ open: false, current: false });
|
|
111
111
|
if (!state.has(path)) {
|
|
112
112
|
state.set(path, value);
|
|
113
113
|
}
|
package/src/testing/generator.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { type NodeArg } from '@dxos/app-graph';
|
|
6
6
|
import { S, TypedObject } from '@dxos/echo-schema';
|
|
7
|
-
import {
|
|
7
|
+
import { create, type ReactiveObject } from '@dxos/live-object';
|
|
8
8
|
import { faker } from '@dxos/random';
|
|
9
9
|
import { range } from '@dxos/util';
|
|
10
10
|
|
|
@@ -19,7 +19,7 @@ type ObjectDataGenerator = {
|
|
|
19
19
|
createData: () => any;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
type ObjectFactory<T extends
|
|
22
|
+
type ObjectFactory<T extends ReactiveObject<any>> = {
|
|
23
23
|
schema?: S.Schema.AnyNoContext; // TODO(burdon): Support both typed and expando schema.
|
|
24
24
|
createObject: () => T;
|
|
25
25
|
};
|
|
@@ -30,7 +30,7 @@ const createFactory = ({ createSchema, createData }: ObjectDataGenerator) => {
|
|
|
30
30
|
const schema = createSchema?.();
|
|
31
31
|
return {
|
|
32
32
|
schema,
|
|
33
|
-
createObject: () => (schema ?
|
|
33
|
+
createObject: () => (schema ? create(schema, createData()) : create(createData())),
|
|
34
34
|
};
|
|
35
35
|
};
|
|
36
36
|
|