@dxos/plugin-navtree 0.8.2-main.fbd8ed0 → 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/{app-graph-builder-P7AY3K72.mjs → app-graph-builder-26D3MUCA.mjs} +6 -7
- package/dist/lib/browser/app-graph-builder-26D3MUCA.mjs.map +7 -0
- 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-UM2C5XK3.mjs → chunk-DN43QXSX.mjs} +365 -444
- package/dist/lib/browser/chunk-DN43QXSX.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +10 -5
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-PW7B76HO.mjs → intent-resolver-BZMUS24C.mjs} +7 -7
- package/dist/lib/browser/intent-resolver-BZMUS24C.mjs.map +7 -0
- package/dist/lib/browser/keyboard-IQXHKUWM.mjs +46 -0
- package/dist/lib/browser/keyboard-IQXHKUWM.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-M3CAS7ZP.mjs → react-surface-3HCM3SHJ.mjs} +3 -3
- package/dist/lib/browser/{state-3UBYOTQT.mjs → state-M5UJ3MHL.mjs} +12 -18
- package/dist/lib/browser/state-M5UJ3MHL.mjs.map +7 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts +179 -2
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- 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 +183 -38
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/keyboard.d.ts +2 -2
- package/dist/types/src/capabilities/keyboard.d.ts.map +1 -1
- package/dist/types/src/capabilities/state.d.ts +6 -9
- package/dist/types/src/capabilities/state.d.ts.map +1 -1
- package/dist/types/src/components/CommandsDialog.d.ts.map +1 -0
- package/dist/types/src/components/CommandsTrigger.d.ts.map +1 -0
- package/dist/types/src/components/L0Menu.d.ts +10 -0
- package/dist/types/src/components/L0Menu.d.ts.map +1 -0
- package/dist/types/src/components/L1Panels.d.ts +14 -0
- package/dist/types/src/components/L1Panels.d.ts.map +1 -0
- package/dist/types/src/components/NavTree.d.ts +5 -0
- package/dist/types/src/components/NavTree.d.ts.map +1 -0
- package/dist/types/src/components/NavTree.stories.d.ts +7 -0
- package/dist/types/src/components/NavTree.stories.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/NavTreeDocumentTitle.d.ts.map +1 -1
- package/dist/types/src/components/{NavTreeItem/NavTreeItemAction.d.ts → NavTreeItemAction.d.ts} +3 -2
- package/dist/types/src/components/NavTreeItemAction.d.ts.map +1 -0
- package/dist/types/src/components/NavTreeItemAction.stories.d.ts +41 -0
- package/dist/types/src/components/NavTreeItemAction.stories.d.ts.map +1 -0
- package/dist/types/src/components/NavTreeItemColumns.d.ts +4 -0
- package/dist/types/src/components/NavTreeItemColumns.d.ts.map +1 -0
- package/dist/types/src/components/{UserAccountAvatar/UserAccountAvatar.d.ts → UserAccountAvatar.d.ts} +1 -1
- package/dist/types/src/components/UserAccountAvatar.d.ts.map +1 -0
- package/dist/types/src/components/{UserAccountAvatar/UserAccountAvatar.stories.d.ts → UserAccountAvatar.stories.d.ts} +2 -1
- package/dist/types/src/components/UserAccountAvatar.stories.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/types.d.ts +14 -20
- package/dist/types/src/components/types.d.ts.map +1 -1
- package/dist/types/src/experimental/Tree.d.ts.map +1 -1
- package/dist/types/src/hooks.d.ts.map +1 -1
- package/dist/types/src/stories/Graph.stories.d.ts +7 -0
- package/dist/types/src/stories/Graph.stories.d.ts.map +1 -0
- package/dist/types/src/stories/StorybookNavTree.d.ts +4 -0
- package/dist/types/src/stories/StorybookNavTree.d.ts.map +1 -0
- package/dist/types/src/testing/generator.d.ts +6 -7
- package/dist/types/src/testing/generator.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +0 -1
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/update-state.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/dist/types/src/util.d.ts +10 -7
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +31 -40
- package/src/NavTreePlugin.tsx +2 -2
- package/src/capabilities/app-graph-builder.ts +28 -38
- package/src/capabilities/capabilities.ts +4 -5
- package/src/capabilities/intent-resolver.ts +7 -8
- package/src/capabilities/keyboard.ts +32 -37
- package/src/capabilities/state.ts +17 -23
- package/src/components/{CommandsDialog/CommandsDialog.tsx → CommandsDialog.tsx} +7 -8
- package/src/components/{CommandsDialog/CommandsTrigger.tsx → CommandsTrigger.tsx} +1 -1
- package/src/components/{Sidebar/L0Menu.tsx → L0Menu.tsx} +131 -188
- package/src/components/L1Panels.tsx +115 -0
- package/src/components/NavTree.stories.tsx +107 -0
- package/src/components/NavTree.tsx +51 -0
- package/src/components/NavTreeContainer.tsx +74 -94
- package/src/components/NavTreeContext.tsx +1 -1
- package/src/components/{NavTreeItem/NavTreeItemAction.stories.tsx → NavTreeItemAction.stories.tsx} +6 -12
- package/src/components/{NavTreeItem/NavTreeItemAction.tsx → NavTreeItemAction.tsx} +18 -23
- package/src/components/NavTreeItemColumns.tsx +71 -0
- package/src/components/{UserAccountAvatar/UserAccountAvatar.stories.tsx → UserAccountAvatar.stories.tsx} +5 -5
- package/src/components/{UserAccountAvatar/UserAccountAvatar.tsx → UserAccountAvatar.tsx} +7 -7
- package/src/components/index.ts +1 -0
- package/src/components/types.ts +15 -20
- package/src/hooks.ts +11 -12
- package/src/stories/Graph.stories.tsx +130 -0
- package/src/stories/StorybookNavTree.tsx +63 -0
- package/src/testing/generator.ts +12 -15
- package/src/testing/index.ts +0 -1
- package/src/translations.ts +0 -1
- package/src/util.ts +32 -10
- package/dist/lib/browser/app-graph-builder-P7AY3K72.mjs.map +0 -7
- package/dist/lib/browser/chunk-TLQLMZXU.mjs.map +0 -7
- package/dist/lib/browser/chunk-UM2C5XK3.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-PW7B76HO.mjs.map +0 -7
- package/dist/lib/browser/keyboard-DDFATRUG.mjs +0 -51
- package/dist/lib/browser/keyboard-DDFATRUG.mjs.map +0 -7
- package/dist/lib/browser/state-3UBYOTQT.mjs.map +0 -7
- package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts.map +0 -1
- package/dist/types/src/components/CommandsDialog/CommandsTrigger.d.ts.map +0 -1
- package/dist/types/src/components/CommandsDialog/index.d.ts +0 -3
- package/dist/types/src/components/CommandsDialog/index.d.ts.map +0 -1
- package/dist/types/src/components/NavTree/NavTree.d.ts +0 -8
- package/dist/types/src/components/NavTree/NavTree.d.ts.map +0 -1
- package/dist/types/src/components/NavTree/NavTree.stories.d.ts +0 -8
- package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +0 -1
- package/dist/types/src/components/NavTree/index.d.ts +0 -2
- package/dist/types/src/components/NavTree/index.d.ts.map +0 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts.map +0 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +0 -8
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +0 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts +0 -4
- package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +0 -1
- package/dist/types/src/components/NavTreeItem/index.d.ts +0 -3
- package/dist/types/src/components/NavTreeItem/index.d.ts.map +0 -1
- package/dist/types/src/components/Sidebar/L0Menu.d.ts +0 -13
- package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +0 -1
- package/dist/types/src/components/Sidebar/L1Panel.d.ts +0 -15
- package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +0 -1
- package/dist/types/src/components/Sidebar/index.d.ts +0 -3
- package/dist/types/src/components/Sidebar/index.d.ts.map +0 -1
- package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.d.ts.map +0 -1
- package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts.map +0 -1
- package/dist/types/src/components/UserAccountAvatar/index.d.ts +0 -2
- package/dist/types/src/components/UserAccountAvatar/index.d.ts.map +0 -1
- package/dist/types/src/testing/app-graph-builder.d.ts +0 -3
- package/dist/types/src/testing/app-graph-builder.d.ts.map +0 -1
- package/src/components/CommandsDialog/index.ts +0 -6
- package/src/components/NavTree/NavTree.stories.tsx +0 -159
- package/src/components/NavTree/NavTree.tsx +0 -62
- package/src/components/NavTree/index.ts +0 -5
- package/src/components/NavTreeItem/NavTreeItemColumns.tsx +0 -73
- package/src/components/NavTreeItem/index.ts +0 -6
- package/src/components/Sidebar/L1Panel.tsx +0 -175
- package/src/components/Sidebar/index.ts +0 -6
- package/src/components/UserAccountAvatar/index.ts +0 -5
- package/src/testing/app-graph-builder.ts +0 -224
- /package/dist/lib/browser/{react-surface-M3CAS7ZP.mjs.map → react-surface-3HCM3SHJ.mjs.map} +0 -0
- /package/dist/types/src/components/{CommandsDialog/CommandsDialog.d.ts → CommandsDialog.d.ts} +0 -0
- /package/dist/types/src/components/{CommandsDialog/CommandsTrigger.d.ts → CommandsTrigger.d.ts} +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useMemo } from 'react';
|
|
6
|
+
|
|
7
|
+
import { Tabs } from '@dxos/react-ui-tabs';
|
|
8
|
+
import { byPosition } from '@dxos/util';
|
|
9
|
+
|
|
10
|
+
import { L0Menu } from './L0Menu';
|
|
11
|
+
import { L1Panels } from './L1Panels';
|
|
12
|
+
import { useNavTreeContext } from './NavTreeContext';
|
|
13
|
+
import { type NavTreeProps } from './types';
|
|
14
|
+
import { useLoadDescendents } from '../hooks';
|
|
15
|
+
|
|
16
|
+
export const NAV_TREE_ITEM = 'NavTreeItem';
|
|
17
|
+
|
|
18
|
+
export const NavTree = ({ id, root }: NavTreeProps) => {
|
|
19
|
+
const { tab, getItems, onBack } = useNavTreeContext();
|
|
20
|
+
const topLevelActions = getItems(root, 'item').toSorted((a, b) => byPosition(a.properties, b.properties));
|
|
21
|
+
const topLevelCollections = getItems(root, 'collection');
|
|
22
|
+
const topLevelWorkspaces = getItems(root, 'workspace');
|
|
23
|
+
const topLevelNavigation = getItems(root, 'navigation');
|
|
24
|
+
const l0Items = useMemo(
|
|
25
|
+
() => [...topLevelActions, ...topLevelCollections, ...topLevelWorkspaces, ...topLevelNavigation],
|
|
26
|
+
[topLevelActions, topLevelCollections, topLevelWorkspaces, topLevelNavigation],
|
|
27
|
+
);
|
|
28
|
+
const pinnedItems = getItems(root, 'pin-end').toSorted((a, b) => byPosition(a.properties, b.properties));
|
|
29
|
+
const userAccountItem = getItems(root, 'user-account')[0];
|
|
30
|
+
const topLevelItems = useMemo(
|
|
31
|
+
() => [...l0Items, ...pinnedItems, userAccountItem],
|
|
32
|
+
[l0Items, pinnedItems, userAccountItem],
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
useLoadDescendents(root);
|
|
36
|
+
const path = useMemo(() => [id], [id]);
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
// NOTE(thure): 74px (rather than rem) is intentional in order to match the size of macOS windowing controls
|
|
40
|
+
<Tabs.Root value={tab} orientation='vertical' verticalVariant='stateless' classNames='relative'>
|
|
41
|
+
<L0Menu
|
|
42
|
+
topLevelItems={l0Items}
|
|
43
|
+
pinnedItems={pinnedItems}
|
|
44
|
+
userAccountItem={userAccountItem}
|
|
45
|
+
path={path}
|
|
46
|
+
parent={root}
|
|
47
|
+
/>
|
|
48
|
+
<L1Panels topLevelItems={topLevelItems} path={path} currentItemId={tab} onBack={onBack} />
|
|
49
|
+
</Tabs.Root>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
@@ -16,22 +16,28 @@ import {
|
|
|
16
16
|
useIntentDispatcher,
|
|
17
17
|
useLayout,
|
|
18
18
|
} from '@dxos/app-framework';
|
|
19
|
-
import { isAction, isActionLike, type
|
|
19
|
+
import { isAction, isActionLike, type Node } from '@dxos/app-graph';
|
|
20
20
|
import { PLANK_COMPANION_TYPE } from '@dxos/plugin-deck/types';
|
|
21
|
-
import { useConnections } from '@dxos/plugin-graph';
|
|
22
21
|
import { isEchoObject, isSpace } from '@dxos/react-client/echo';
|
|
23
|
-
import { useMediaQuery
|
|
22
|
+
import { useMediaQuery } from '@dxos/react-ui';
|
|
24
23
|
import { isTreeData, type TreeData, type PropsFromTreeItem } from '@dxos/react-ui-list';
|
|
25
24
|
import { mx } from '@dxos/react-ui-theme';
|
|
26
|
-
import { arrayMove
|
|
25
|
+
import { arrayMove } from '@dxos/util';
|
|
27
26
|
|
|
28
27
|
import { NAV_TREE_ITEM, NavTree } from './NavTree';
|
|
29
28
|
import { NavTreeContext } from './NavTreeContext';
|
|
30
29
|
import { type NavTreeContextValue } from './types';
|
|
31
30
|
import { NavTreeCapabilities } from '../capabilities';
|
|
32
|
-
import { NAVTREE_PLUGIN } from '../meta';
|
|
33
31
|
import { type NavTreeItemGraphNode } from '../types';
|
|
34
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
expandActions,
|
|
34
|
+
expandChildren,
|
|
35
|
+
getActions as naturalGetActions,
|
|
36
|
+
getChildren,
|
|
37
|
+
getParent,
|
|
38
|
+
resolveMigrationOperation,
|
|
39
|
+
expandChildrenAndActions,
|
|
40
|
+
} from '../util';
|
|
35
41
|
|
|
36
42
|
// TODO(thure): Is NavTree truly authoritative in this regard?
|
|
37
43
|
export const NODE_TYPE = 'dxos/app-graph/node';
|
|
@@ -43,29 +49,6 @@ const renderItemEnd = ({ node, open }: { node: Node; open: boolean }) => (
|
|
|
43
49
|
const getChildrenFilter = (node: Node): node is Node =>
|
|
44
50
|
untracked(() => !isActionLike(node) && node.type !== PLANK_COMPANION_TYPE);
|
|
45
51
|
|
|
46
|
-
const filterItems = (node: Node, disposition?: string) => {
|
|
47
|
-
if (!disposition && (node.properties.disposition === 'hidden' || node.properties.disposition === 'alternate-tree')) {
|
|
48
|
-
return false;
|
|
49
|
-
} else if (!disposition) {
|
|
50
|
-
const action = isAction(node);
|
|
51
|
-
return !action || node.properties.disposition === 'item';
|
|
52
|
-
} else {
|
|
53
|
-
return node.properties.disposition === disposition;
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const getItems = (graph: ReadableGraph, node?: Node, disposition?: string) => {
|
|
58
|
-
return graph.getConnections(node?.id ?? ROOT_ID, 'outbound').filter((node) => filterItems(node, disposition));
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const useItems = (node?: Node, options?: { disposition?: string; sort?: boolean }) => {
|
|
62
|
-
const { graph } = useAppGraph();
|
|
63
|
-
const connections = useConnections(graph, node?.id ?? ROOT_ID).filter((node) =>
|
|
64
|
-
filterItems(node, options?.disposition),
|
|
65
|
-
);
|
|
66
|
-
return options?.sort ? connections.toSorted((a, b) => byPosition(a.properties, b.properties)) : connections;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
52
|
export type NavTreeContainerProps = {
|
|
70
53
|
popoverAnchorId?: string;
|
|
71
54
|
topbar?: boolean;
|
|
@@ -75,15 +58,34 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
75
58
|
const [isLg] = useMediaQuery('lg', { ssr: false });
|
|
76
59
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
77
60
|
const { graph } = useAppGraph();
|
|
78
|
-
const { isOpen, isCurrent, isAlternateTree, setItem } = useCapability(NavTreeCapabilities.State);
|
|
79
61
|
const layout = useLayout();
|
|
80
|
-
const {
|
|
62
|
+
const { isOpen, isCurrent, setItem } = useCapability(NavTreeCapabilities.State);
|
|
81
63
|
|
|
82
64
|
const getActions = useCallback((node: Node) => naturalGetActions(graph, node), [graph]);
|
|
83
65
|
|
|
66
|
+
const getItems = useCallback(
|
|
67
|
+
(node?: Node, disposition?: string) => {
|
|
68
|
+
return graph.nodes(node ?? graph.root, {
|
|
69
|
+
filter: (node): node is Node => {
|
|
70
|
+
return untracked(() => {
|
|
71
|
+
if (node.properties.disposition === 'hidden') {
|
|
72
|
+
return false;
|
|
73
|
+
} else if (!disposition) {
|
|
74
|
+
const action = isAction(node);
|
|
75
|
+
return !action || node.properties.disposition === 'item';
|
|
76
|
+
} else {
|
|
77
|
+
return node.properties.disposition === disposition;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
[graph],
|
|
84
|
+
);
|
|
85
|
+
|
|
84
86
|
const getProps = useCallback(
|
|
85
87
|
(node: Node, path: string[]): PropsFromTreeItem => {
|
|
86
|
-
const children = getChildren(graph, node, path)
|
|
88
|
+
const children = getChildren(graph, node, getChildrenFilter, path);
|
|
87
89
|
const parentOf =
|
|
88
90
|
children.length > 0 ? children.map(({ id }) => id) : node.properties.role === 'branch' ? [] : undefined;
|
|
89
91
|
return {
|
|
@@ -100,63 +102,51 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
100
102
|
[graph],
|
|
101
103
|
);
|
|
102
104
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
const loadDescendents = useCallback(
|
|
106
|
+
(node: Node) => {
|
|
107
|
+
void expandActions(graph, node);
|
|
108
|
+
if (!isActionLike(node)) {
|
|
109
|
+
void expandChildren(graph, node).then(() =>
|
|
110
|
+
// Load one level deeper, which resolves some juddering observed on open/close.
|
|
111
|
+
Promise.all(
|
|
112
|
+
getChildren(graph, node).flatMap((child) => [expandActions(graph, child), expandChildren(graph, child)]),
|
|
113
|
+
),
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
[graph],
|
|
118
|
+
);
|
|
114
119
|
|
|
115
|
-
const
|
|
120
|
+
const onOpenChange = useCallback(
|
|
116
121
|
({ item: { id }, path, open }: { item: Node; path: string[]; open: boolean }) => {
|
|
117
122
|
// TODO(thure): This might become a localstorage leak; openItemIds that no longer exist should be removed from this map.
|
|
118
123
|
setItem(path, 'open', open);
|
|
119
|
-
|
|
120
|
-
|
|
124
|
+
|
|
125
|
+
if (graph) {
|
|
126
|
+
const node = graph.findNode(id);
|
|
127
|
+
return node && expandChildrenAndActions(graph, node as NavTreeItemGraphNode);
|
|
128
|
+
}
|
|
121
129
|
},
|
|
122
130
|
[graph],
|
|
123
131
|
);
|
|
124
132
|
|
|
125
|
-
const
|
|
133
|
+
const onTabChange = useCallback(
|
|
126
134
|
async (node: NavTreeItemGraphNode) => {
|
|
127
|
-
await dispatch(
|
|
128
|
-
createIntent(LayoutAction.UpdateSidebar, {
|
|
129
|
-
part: 'sidebar',
|
|
130
|
-
options: {
|
|
131
|
-
state:
|
|
132
|
-
node.id === tab
|
|
133
|
-
? navigationSidebarState === 'expanded'
|
|
134
|
-
? isLg
|
|
135
|
-
? 'collapsed'
|
|
136
|
-
: 'closed'
|
|
137
|
-
: 'expanded'
|
|
138
|
-
: 'expanded',
|
|
139
|
-
},
|
|
140
|
-
}),
|
|
141
|
-
);
|
|
142
|
-
|
|
143
135
|
await dispatch(createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: node.id }));
|
|
144
|
-
|
|
145
136
|
// Open the first item if the workspace is empty.
|
|
146
137
|
if (layout.active.length === 0) {
|
|
147
|
-
const [item] = getItems(
|
|
138
|
+
const [item] = getItems(node).filter((node) => !isActionLike(node));
|
|
148
139
|
if (item && item.data) {
|
|
149
140
|
await dispatch(createIntent(LayoutAction.Open, { part: 'main', subject: [item.id] }));
|
|
150
141
|
}
|
|
151
142
|
}
|
|
152
143
|
},
|
|
153
|
-
[dispatch, layout
|
|
144
|
+
[dispatch, layout],
|
|
154
145
|
);
|
|
155
146
|
|
|
156
147
|
const canDrop = useCallback((source: TreeData, target: TreeData) => {
|
|
157
148
|
const sourceNode = source.item as Node;
|
|
158
149
|
const targetNode = target.item as Node;
|
|
159
|
-
// TODO(wittjosiah): This shouldn't depend directly on client, there should be a graph-level abstraction.
|
|
160
150
|
if (isSpace(targetNode.data)) {
|
|
161
151
|
// TODO(wittjosiah): Find a way to only allow space as source for rearranging.
|
|
162
152
|
return isEchoObject(sourceNode.data) || isSpace(sourceNode.data);
|
|
@@ -174,8 +164,8 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
174
164
|
}
|
|
175
165
|
|
|
176
166
|
if (isAction(node)) {
|
|
177
|
-
const [parent] = graph.
|
|
178
|
-
void (parent && node.data({ parent, caller: NAV_TREE_ITEM }));
|
|
167
|
+
const [parent] = graph.nodes(node, { relation: 'inbound' });
|
|
168
|
+
void (parent && node.data({ node: parent, caller: NAV_TREE_ITEM }));
|
|
179
169
|
return;
|
|
180
170
|
}
|
|
181
171
|
|
|
@@ -196,7 +186,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
196
186
|
void dispatch(createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: node.id }));
|
|
197
187
|
}
|
|
198
188
|
|
|
199
|
-
const defaultAction = graph.
|
|
189
|
+
const defaultAction = graph.actions(node).find((action) => action.properties?.disposition === 'default');
|
|
200
190
|
if (isAction(defaultAction)) {
|
|
201
191
|
void (defaultAction.data as () => void)();
|
|
202
192
|
}
|
|
@@ -208,7 +198,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
208
198
|
[graph, dispatch, isCurrent, isLg],
|
|
209
199
|
);
|
|
210
200
|
|
|
211
|
-
const
|
|
201
|
+
const onBack = useCallback(
|
|
212
202
|
() => dispatch(createIntent(LayoutAction.RevertWorkspace, { part: 'workspace', options: { revert: true } })),
|
|
213
203
|
[dispatch],
|
|
214
204
|
);
|
|
@@ -235,8 +225,8 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
235
225
|
: resolveMigrationOperation(graph, sourceNode, targetPath, targetNode);
|
|
236
226
|
const sourceParent = getParent(graph, sourceNode, sourcePath);
|
|
237
227
|
const targetParent = getParent(graph, targetNode, targetPath);
|
|
238
|
-
const sourceItems = getItems(
|
|
239
|
-
const targetItems = getItems(
|
|
228
|
+
const sourceItems = getItems(sourceParent);
|
|
229
|
+
const targetItems = getItems(targetParent);
|
|
240
230
|
const sourceIndex = sourceItems.findIndex(({ id }) => id === sourceNode.id);
|
|
241
231
|
const targetIndex = targetItems.findIndex(({ id }) => id === targetNode.id);
|
|
242
232
|
const migrationIndex =
|
|
@@ -272,56 +262,46 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
272
262
|
});
|
|
273
263
|
}, [graph]);
|
|
274
264
|
|
|
275
|
-
const setAlternateTree = useCallback(
|
|
276
|
-
(path: string[], open: boolean) => {
|
|
277
|
-
setItem(path, 'alternateTree', open);
|
|
278
|
-
},
|
|
279
|
-
[setItem],
|
|
280
|
-
);
|
|
281
|
-
|
|
282
265
|
const navTreeContextValue = useMemo(
|
|
283
266
|
() => ({
|
|
284
|
-
useItems,
|
|
285
267
|
tab,
|
|
268
|
+
onTabChange,
|
|
269
|
+
onBack,
|
|
286
270
|
getActions,
|
|
287
|
-
|
|
271
|
+
loadDescendents,
|
|
288
272
|
renderItemEnd,
|
|
289
273
|
popoverAnchorId,
|
|
290
274
|
topbar,
|
|
275
|
+
getItems,
|
|
291
276
|
getProps,
|
|
292
277
|
isCurrent,
|
|
293
278
|
isOpen,
|
|
279
|
+
onOpenChange,
|
|
294
280
|
canDrop,
|
|
295
|
-
isAlternateTree,
|
|
296
|
-
setAlternateTree,
|
|
297
|
-
onTabChange: handleTabChange,
|
|
298
|
-
onOpenChange: handleOpenChange,
|
|
299
281
|
onSelect: handleSelect,
|
|
300
|
-
onBack: handleBack,
|
|
301
282
|
}),
|
|
302
283
|
[
|
|
303
284
|
tab,
|
|
285
|
+
onTabChange,
|
|
286
|
+
onBack,
|
|
304
287
|
getActions,
|
|
305
|
-
|
|
288
|
+
loadDescendents,
|
|
306
289
|
renderItemEnd,
|
|
307
290
|
popoverAnchorId,
|
|
308
291
|
topbar,
|
|
292
|
+
getItems,
|
|
309
293
|
getProps,
|
|
310
294
|
isCurrent,
|
|
311
295
|
isOpen,
|
|
296
|
+
onOpenChange,
|
|
312
297
|
canDrop,
|
|
313
|
-
isAlternateTree,
|
|
314
|
-
setAlternateTree,
|
|
315
|
-
handleTabChange,
|
|
316
|
-
handleOpenChange,
|
|
317
298
|
handleSelect,
|
|
318
|
-
handleBack,
|
|
319
299
|
],
|
|
320
300
|
);
|
|
321
301
|
|
|
322
302
|
return (
|
|
323
303
|
<NavTreeContext.Provider value={navTreeContextValue}>
|
|
324
|
-
<NavTree
|
|
304
|
+
<NavTree root={graph.root} id={graph.root.id} />
|
|
325
305
|
</NavTreeContext.Provider>
|
|
326
306
|
);
|
|
327
307
|
});
|
|
@@ -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('
|
|
13
|
+
export const useNavTreeContext = () => useContext(NavTreeContext) ?? raise(new Error('NavTreeContext not found'));
|
package/src/components/{NavTreeItem/NavTreeItemAction.stories.tsx → NavTreeItemAction.stories.tsx}
RENAMED
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
6
|
|
|
7
|
-
import { type Meta, type StoryObj } from '@storybook/react';
|
|
8
|
-
|
|
9
7
|
import { type NodeArg } from '@dxos/app-graph';
|
|
10
8
|
import { faker } from '@dxos/random';
|
|
11
9
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
@@ -39,23 +37,19 @@ const menuActions = faker.helpers.multiple(
|
|
|
39
37
|
{ count: 20 },
|
|
40
38
|
);
|
|
41
39
|
|
|
42
|
-
|
|
40
|
+
export default {
|
|
43
41
|
title: 'plugins/plugin-navtree/NavTreeItemAction',
|
|
44
42
|
component: NavTreeItemAction,
|
|
45
|
-
decorators: [withTheme, withLayout()],
|
|
43
|
+
decorators: [withTheme, withLayout({ fullscreen: true, tooltips: true })],
|
|
46
44
|
args: {
|
|
47
45
|
icon: 'ph--list--regular',
|
|
48
46
|
parent,
|
|
49
47
|
menuActions,
|
|
50
48
|
label: 'Select action',
|
|
49
|
+
onAction: (action) => {
|
|
50
|
+
console.log(action);
|
|
51
|
+
},
|
|
51
52
|
} satisfies Partial<NavTreeItemActionMenuProps>,
|
|
52
|
-
parameters: {
|
|
53
|
-
layout: 'centered',
|
|
54
|
-
},
|
|
55
53
|
};
|
|
56
54
|
|
|
57
|
-
export
|
|
58
|
-
|
|
59
|
-
type Story = StoryObj<typeof meta>;
|
|
60
|
-
|
|
61
|
-
export const Default: Story = {};
|
|
55
|
+
export const Default = {};
|
|
@@ -5,12 +5,12 @@
|
|
|
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
|
|
|
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,41 +18,31 @@ export type NavTreeItemActionMenuProps = ActionProperties & {
|
|
|
18
18
|
monolithic?: boolean;
|
|
19
19
|
menuActions?: Action[];
|
|
20
20
|
suppressNextTooltip?: MutableRefObject<boolean>;
|
|
21
|
+
onAction?: (action: Action) => void;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
const fallbackIcon = 'ph--placeholder--regular';
|
|
24
25
|
|
|
25
|
-
const
|
|
26
|
+
const actionButtonProps = {
|
|
26
27
|
size: 4 as const,
|
|
27
28
|
density: 'fine' as const,
|
|
28
29
|
};
|
|
29
|
-
const coarseActionButtonProps = {
|
|
30
|
-
size: 5 as const,
|
|
31
|
-
density: 'coarse' as const,
|
|
32
|
-
};
|
|
33
30
|
|
|
34
31
|
export const NavTreeItemActionDropdownMenu = ({
|
|
35
|
-
parent,
|
|
36
32
|
label,
|
|
37
33
|
icon,
|
|
38
34
|
testId,
|
|
39
35
|
menuActions,
|
|
40
|
-
|
|
36
|
+
onAction,
|
|
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
|
-
<MenuProvider>
|
|
47
|
-
<DropdownMenu.Root
|
|
48
|
-
group={parent}
|
|
49
|
-
items={menuActions as MenuItem[]}
|
|
50
|
-
caller={caller}
|
|
51
|
-
suppressNextTooltip={suppressNextTooltip}
|
|
52
|
-
>
|
|
41
|
+
<MenuProvider onAction={onAction}>
|
|
42
|
+
<DropdownMenu.Root items={menuActions as MenuItem[]} suppressNextTooltip={suppressNextTooltip}>
|
|
53
43
|
<DropdownMenu.Trigger asChild>
|
|
54
44
|
<IconButton
|
|
55
|
-
{...
|
|
45
|
+
{...actionButtonProps}
|
|
56
46
|
classNames={mx('shrink-0 pli-2 pointer-fine:pli-1', hoverableControlItem, hoverableOpenControlItem)}
|
|
57
47
|
variant='ghost'
|
|
58
48
|
icon={icon ?? fallbackIcon}
|
|
@@ -73,10 +63,9 @@ export const NavTreeItemMonolithicAction = ({
|
|
|
73
63
|
data: invoke,
|
|
74
64
|
baseLabel,
|
|
75
65
|
}: Action & { parent: Node; onAction?: (action: Action) => void; baseLabel: string }) => {
|
|
76
|
-
const density = useDensityContext();
|
|
77
66
|
return (
|
|
78
67
|
<IconButton
|
|
79
|
-
{...
|
|
68
|
+
{...actionButtonProps}
|
|
80
69
|
variant={variant}
|
|
81
70
|
classNames={mx(
|
|
82
71
|
'shrink-0',
|
|
@@ -93,7 +82,7 @@ export const NavTreeItemMonolithicAction = ({
|
|
|
93
82
|
return;
|
|
94
83
|
}
|
|
95
84
|
event.stopPropagation();
|
|
96
|
-
void invoke?.(caller ? { parent, caller } : { parent });
|
|
85
|
+
void invoke?.(caller ? { node: parent, caller } : { node: parent });
|
|
97
86
|
}}
|
|
98
87
|
data-testid={testId}
|
|
99
88
|
/>
|
|
@@ -109,6 +98,12 @@ export const NavTreeItemAction = ({ monolithic, menuActions, parent: node, ...pr
|
|
|
109
98
|
return monolithic && menuActions?.length === 1 ? (
|
|
110
99
|
<NavTreeItemMonolithicAction baseLabel={baseLabel} parent={node} {...menuActions[0]} />
|
|
111
100
|
) : (
|
|
112
|
-
<NavTreeItemActionDropdownMenu
|
|
101
|
+
<NavTreeItemActionDropdownMenu
|
|
102
|
+
{...props}
|
|
103
|
+
label={baseLabel}
|
|
104
|
+
parent={node}
|
|
105
|
+
menuActions={menuActions}
|
|
106
|
+
onAction={(action) => action.data?.(props.caller ? { node, caller: props.caller } : { node })}
|
|
107
|
+
/>
|
|
113
108
|
);
|
|
114
109
|
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { Fragment, memo } from 'react';
|
|
6
|
+
|
|
7
|
+
import { isAction } from '@dxos/app-graph';
|
|
8
|
+
import { Popover, toLocalizedString, Treegrid, useTranslation } from '@dxos/react-ui';
|
|
9
|
+
|
|
10
|
+
import { NAV_TREE_ITEM } from './NavTree';
|
|
11
|
+
import { useNavTreeContext } from './NavTreeContext';
|
|
12
|
+
import { NavTreeItemAction } from './NavTreeItemAction';
|
|
13
|
+
import type { NavTreeItemColumnsProps } from './types';
|
|
14
|
+
import { useLoadDescendents } from '../hooks';
|
|
15
|
+
import { NAVTREE_PLUGIN } from '../meta';
|
|
16
|
+
|
|
17
|
+
export const NavTreeItemColumns = memo(({ path, item, open }: NavTreeItemColumnsProps) => {
|
|
18
|
+
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
19
|
+
const { getActions, renderItemEnd: ItemEnd, popoverAnchorId } = useNavTreeContext();
|
|
20
|
+
|
|
21
|
+
const level = path.length - 2;
|
|
22
|
+
|
|
23
|
+
const { actions: _actions, groupedActions } = getActions(item);
|
|
24
|
+
const [primaryAction, ...secondaryActions] = _actions.toSorted((a, b) =>
|
|
25
|
+
a.properties?.disposition === 'list-item-primary' ? -1 : 1,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const actions = (primaryAction?.properties?.disposition === 'list-item-primary' ? secondaryActions : _actions)
|
|
29
|
+
.flatMap((action) => (isAction(action) ? [action] : []))
|
|
30
|
+
.filter((action) => !action.properties?.hidden);
|
|
31
|
+
|
|
32
|
+
const ActionRoot = popoverAnchorId === `dxos.org/ui/${NAV_TREE_ITEM}/${item.id}` ? Popover.Anchor : Fragment;
|
|
33
|
+
|
|
34
|
+
useLoadDescendents(item);
|
|
35
|
+
useLoadDescendents(primaryAction && !isAction(primaryAction) ? primaryAction : undefined);
|
|
36
|
+
|
|
37
|
+
return (
|
|
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 ? (
|
|
55
|
+
<NavTreeItemAction
|
|
56
|
+
testId={`navtree.treeItem.actionsLevel${level}`}
|
|
57
|
+
label={t('tree item actions label')}
|
|
58
|
+
icon='ph--dots-three-vertical--regular'
|
|
59
|
+
parent={item}
|
|
60
|
+
menuActions={actions}
|
|
61
|
+
menuType='dropdown'
|
|
62
|
+
caller={NAV_TREE_ITEM}
|
|
63
|
+
/>
|
|
64
|
+
) : (
|
|
65
|
+
<Treegrid.Cell />
|
|
66
|
+
)}
|
|
67
|
+
</ActionRoot>
|
|
68
|
+
{ItemEnd && <ItemEnd node={item} open={open} />}
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
});
|
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
6
|
|
|
7
7
|
import { type Meta } from '@storybook/react';
|
|
8
|
-
|
|
9
|
-
import { withTheme } from '@dxos/storybook-utils';
|
|
8
|
+
import React from 'react';
|
|
10
9
|
|
|
11
10
|
import { UserAccountAvatar } from './UserAccountAvatar';
|
|
12
11
|
|
|
12
|
+
export const Default = (props: any) => {
|
|
13
|
+
return <UserAccountAvatar {...props} />;
|
|
14
|
+
};
|
|
15
|
+
|
|
13
16
|
const meta: Meta<typeof UserAccountAvatar> = {
|
|
14
17
|
title: 'plugins/plugin-navtree/UserAccountAvatar',
|
|
15
18
|
component: UserAccountAvatar,
|
|
16
|
-
decorators: [withTheme],
|
|
17
19
|
};
|
|
18
20
|
|
|
19
21
|
export default meta;
|
|
20
|
-
|
|
21
|
-
export const Default = {};
|
|
@@ -15,19 +15,19 @@ export type UserAccountAvatarProps = {
|
|
|
15
15
|
status?: AvatarStatus;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
export const UserAccountAvatar = (
|
|
19
|
-
const fallbackValue = hexToFallback(userId ?? '0');
|
|
18
|
+
export const UserAccountAvatar = (props: UserAccountAvatarProps) => {
|
|
19
|
+
const fallbackValue = hexToFallback(props.userId ?? '0');
|
|
20
20
|
|
|
21
21
|
return (
|
|
22
22
|
<div className='grid place-items-center' data-joyride='welcome/account'>
|
|
23
23
|
<Avatar.Root>
|
|
24
24
|
<Avatar.Content
|
|
25
25
|
variant='circle'
|
|
26
|
-
size={size ?? 12}
|
|
27
|
-
status={status ?? 'active'}
|
|
28
|
-
hue={hue || fallbackValue.hue}
|
|
29
|
-
fallback={emoji || fallbackValue.emoji}
|
|
30
|
-
data-testid='
|
|
26
|
+
size={props.size ?? 12}
|
|
27
|
+
status={props.status ?? 'active'}
|
|
28
|
+
hue={props.hue || fallbackValue.hue}
|
|
29
|
+
fallback={props.emoji || fallbackValue.emoji}
|
|
30
|
+
data-testid='treeview.userAccount'
|
|
31
31
|
/>
|
|
32
32
|
</Avatar.Root>
|
|
33
33
|
</div>
|
package/src/components/index.ts
CHANGED
package/src/components/types.ts
CHANGED
|
@@ -5,36 +5,31 @@
|
|
|
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
|
|
|
12
|
-
import { type L1PanelProps } from './
|
|
11
|
+
import { type L1PanelProps } from './L1Panels';
|
|
13
12
|
import type { FlattenedActions, NavTreeItemGraphNode } from '../types';
|
|
14
13
|
|
|
14
|
+
export type NavTreeItemColumnsProps = {
|
|
15
|
+
path: string[];
|
|
16
|
+
item: Node;
|
|
17
|
+
open: boolean;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type NavTreeProps = Pick<TreeProps<NavTreeItemGraphNode>, 'id' | 'root'>;
|
|
21
|
+
|
|
15
22
|
export type NavTreeContextValue = Pick<
|
|
16
23
|
TreeProps<NavTreeItemGraphNode>,
|
|
17
|
-
'getProps' | 'isCurrent' | 'isOpen' | '
|
|
24
|
+
'getProps' | 'isCurrent' | 'isOpen' | 'onOpenChange' | 'canDrop' | 'onSelect'
|
|
18
25
|
> &
|
|
19
26
|
Pick<L1PanelProps, 'onBack'> & {
|
|
20
27
|
tab: string;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
renderItemEnd?: FC<{ node: Node; open: boolean }>;
|
|
24
|
-
useItems: (
|
|
25
|
-
node?: NavTreeItemGraphNode,
|
|
26
|
-
options?: { disposition?: string; sort?: boolean },
|
|
27
|
-
) => NavTreeItemGraphNode[];
|
|
28
|
+
onTabChange?: (node: NavTreeItemGraphNode) => void;
|
|
29
|
+
getItems: (node?: NavTreeItemGraphNode, disposition?: string) => NavTreeItemGraphNode[];
|
|
28
30
|
getActions: (node: Node) => FlattenedActions;
|
|
29
31
|
loadDescendents?: (node: Node) => MaybePromise<void>;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
renderItemEnd?: FC<{ node: Node; open: boolean }>;
|
|
33
|
+
popoverAnchorId?: string;
|
|
34
|
+
topbar?: boolean;
|
|
33
35
|
};
|
|
34
|
-
|
|
35
|
-
export type NavTreeItemColumnsProps = {
|
|
36
|
-
path: string[];
|
|
37
|
-
item: Node;
|
|
38
|
-
open: boolean;
|
|
39
|
-
density?: Density;
|
|
40
|
-
};
|