@dxos/plugin-navtree 0.8.4-main.3f58842 → 0.8.4-main.67995b8
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-SICQTLXC.mjs → chunk-WEMCSQI7.mjs} +140 -113
- package/dist/lib/browser/chunk-WEMCSQI7.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +3 -2
- package/dist/lib/browser/index.mjs.map +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-WURHCBQQ.mjs → react-surface-JSJ5SQX5.mjs} +2 -2
- package/dist/types/src/components/NavTree/NavTree.d.ts +2 -2
- package/dist/types/src/components/NavTree/NavTree.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts +1 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/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/translations.d.ts +1 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +38 -37
- package/src/components/NavTree/NavTree.tsx +3 -3
- package/src/components/NavTreeItem/NavTreeItemColumns.tsx +2 -3
- package/src/components/Sidebar/L1Panel.tsx +72 -92
- package/src/components/Sidebar/L1Tabs.tsx +57 -0
- package/src/components/Sidebar/index.ts +1 -0
- package/src/translations.ts +1 -0
- package/dist/lib/browser/chunk-SICQTLXC.mjs.map +0 -7
- /package/dist/lib/browser/{react-surface-WURHCBQQ.mjs.map → react-surface-JSJ5SQX5.mjs.map} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-navtree",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.67995b8",
|
|
4
4
|
"description": "DXOS Surface plugin for a tree view visualization of the graph.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
13
|
"types": "./dist/types/src/index.d.ts",
|
|
14
|
-
"browser": "./dist/lib/browser/index.mjs"
|
|
14
|
+
"browser": "./dist/lib/browser/index.mjs",
|
|
15
|
+
"source": "./src/index.ts"
|
|
15
16
|
}
|
|
16
17
|
},
|
|
17
18
|
"types": "dist/types/src/index.d.ts",
|
|
@@ -31,29 +32,29 @@
|
|
|
31
32
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
|
32
33
|
"date-fns": "^3.3.1",
|
|
33
34
|
"effect": "3.17.0",
|
|
34
|
-
"@dxos/app-
|
|
35
|
-
"@dxos/app-
|
|
36
|
-
"@dxos/async": "0.8.4-main.
|
|
37
|
-
"@dxos/debug": "0.8.4-main.
|
|
38
|
-
"@dxos/echo": "0.8.4-main.
|
|
39
|
-
"@dxos/
|
|
40
|
-
"@dxos/
|
|
41
|
-
"@dxos/
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/
|
|
44
|
-
"@dxos/log": "0.8.4-main.
|
|
45
|
-
"@dxos/plugin-deck": "0.8.4-main.
|
|
46
|
-
"@dxos/plugin-graph": "0.8.4-main.
|
|
47
|
-
"@dxos/plugin-observability": "0.8.4-main.
|
|
48
|
-
"@dxos/protocols": "0.8.4-main.
|
|
49
|
-
"@dxos/react-
|
|
50
|
-
"@dxos/react-ui-
|
|
51
|
-
"@dxos/react-
|
|
52
|
-
"@dxos/react-ui-menu": "0.8.4-main.
|
|
53
|
-
"@dxos/react-ui-searchlist": "0.8.4-main.
|
|
54
|
-
"@dxos/react-ui-stack": "0.8.4-main.
|
|
55
|
-
"@dxos/
|
|
56
|
-
"@dxos/
|
|
35
|
+
"@dxos/app-framework": "0.8.4-main.67995b8",
|
|
36
|
+
"@dxos/app-graph": "0.8.4-main.67995b8",
|
|
37
|
+
"@dxos/async": "0.8.4-main.67995b8",
|
|
38
|
+
"@dxos/debug": "0.8.4-main.67995b8",
|
|
39
|
+
"@dxos/echo": "0.8.4-main.67995b8",
|
|
40
|
+
"@dxos/echo-schema": "0.8.4-main.67995b8",
|
|
41
|
+
"@dxos/invariant": "0.8.4-main.67995b8",
|
|
42
|
+
"@dxos/live-object": "0.8.4-main.67995b8",
|
|
43
|
+
"@dxos/local-storage": "0.8.4-main.67995b8",
|
|
44
|
+
"@dxos/keyboard": "0.8.4-main.67995b8",
|
|
45
|
+
"@dxos/log": "0.8.4-main.67995b8",
|
|
46
|
+
"@dxos/plugin-deck": "0.8.4-main.67995b8",
|
|
47
|
+
"@dxos/plugin-graph": "0.8.4-main.67995b8",
|
|
48
|
+
"@dxos/plugin-observability": "0.8.4-main.67995b8",
|
|
49
|
+
"@dxos/protocols": "0.8.4-main.67995b8",
|
|
50
|
+
"@dxos/react-ui-attention": "0.8.4-main.67995b8",
|
|
51
|
+
"@dxos/react-ui-list": "0.8.4-main.67995b8",
|
|
52
|
+
"@dxos/react-client": "0.8.4-main.67995b8",
|
|
53
|
+
"@dxos/react-ui-menu": "0.8.4-main.67995b8",
|
|
54
|
+
"@dxos/react-ui-searchlist": "0.8.4-main.67995b8",
|
|
55
|
+
"@dxos/react-ui-stack": "0.8.4-main.67995b8",
|
|
56
|
+
"@dxos/react-ui-tabs": "0.8.4-main.67995b8",
|
|
57
|
+
"@dxos/util": "0.8.4-main.67995b8"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
60
|
"@effect-rx/rx-react": "0.38.0",
|
|
@@ -63,16 +64,16 @@
|
|
|
63
64
|
"react": "~18.2.0",
|
|
64
65
|
"react-dom": "~18.2.0",
|
|
65
66
|
"vite": "5.4.7",
|
|
66
|
-
"@dxos/echo-signals": "0.8.4-main.
|
|
67
|
-
"@dxos/plugin-
|
|
68
|
-
"@dxos/plugin-
|
|
69
|
-
"@dxos/plugin-space": "0.8.4-main.
|
|
70
|
-
"@dxos/plugin-storybook-layout": "0.8.4-main.
|
|
71
|
-
"@dxos/
|
|
72
|
-
"@dxos/
|
|
73
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
74
|
-
"@dxos/
|
|
75
|
-
"@dxos/
|
|
67
|
+
"@dxos/echo-signals": "0.8.4-main.67995b8",
|
|
68
|
+
"@dxos/plugin-client": "0.8.4-main.67995b8",
|
|
69
|
+
"@dxos/plugin-attention": "0.8.4-main.67995b8",
|
|
70
|
+
"@dxos/plugin-space": "0.8.4-main.67995b8",
|
|
71
|
+
"@dxos/plugin-storybook-layout": "0.8.4-main.67995b8",
|
|
72
|
+
"@dxos/random": "0.8.4-main.67995b8",
|
|
73
|
+
"@dxos/react-ui": "0.8.4-main.67995b8",
|
|
74
|
+
"@dxos/react-ui-theme": "0.8.4-main.67995b8",
|
|
75
|
+
"@dxos/storybook-utils": "0.8.4-main.67995b8",
|
|
76
|
+
"@dxos/plugin-theme": "0.8.4-main.67995b8"
|
|
76
77
|
},
|
|
77
78
|
"peerDependencies": {
|
|
78
79
|
"@effect-rx/rx-react": "^0.34.1",
|
|
@@ -80,8 +81,8 @@
|
|
|
80
81
|
"effect": "^3.13.3",
|
|
81
82
|
"react": "~18.2.0",
|
|
82
83
|
"react-dom": "~18.2.0",
|
|
83
|
-
"@dxos/react-ui
|
|
84
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
84
|
+
"@dxos/react-ui": "0.8.4-main.67995b8",
|
|
85
|
+
"@dxos/react-ui-theme": "0.8.4-main.67995b8"
|
|
85
86
|
},
|
|
86
87
|
"publishConfig": {
|
|
87
88
|
"access": "public"
|
|
@@ -10,11 +10,11 @@ import { Tabs } from '@dxos/react-ui-tabs';
|
|
|
10
10
|
import { useLoadDescendents } from '../../hooks';
|
|
11
11
|
import { type NavTreeItemGraphNode } from '../../types';
|
|
12
12
|
import { useNavTreeContext } from '../NavTreeContext';
|
|
13
|
-
import { L0Menu,
|
|
13
|
+
import { L0Menu, L1Tabs, type L1TabsProps } from '../Sidebar';
|
|
14
14
|
|
|
15
15
|
export const NAV_TREE_ITEM = 'NavTreeItem';
|
|
16
16
|
|
|
17
|
-
export type NavTreeProps = Pick<TreeProps<NavTreeItemGraphNode>, 'id' | 'root'> & Pick<
|
|
17
|
+
export type NavTreeProps = Pick<TreeProps<NavTreeItemGraphNode>, 'id' | 'root'> & Pick<L1TabsProps, 'open'>;
|
|
18
18
|
|
|
19
19
|
export const NavTree = ({ id, root, ...props }: NavTreeProps) => {
|
|
20
20
|
const { tab, useItems, onBack } = useNavTreeContext();
|
|
@@ -56,7 +56,7 @@ export const NavTree = ({ id, root, ...props }: NavTreeProps) => {
|
|
|
56
56
|
path={path}
|
|
57
57
|
parent={root}
|
|
58
58
|
/>
|
|
59
|
-
<
|
|
59
|
+
<L1Tabs topLevelItems={topLevelItems} path={path} currentItemId={tab} onBack={onBack} {...props} />
|
|
60
60
|
</Tabs.Root>
|
|
61
61
|
);
|
|
62
62
|
};
|
|
@@ -12,16 +12,15 @@ import { useLoadDescendents } from '../../hooks';
|
|
|
12
12
|
import { NAVTREE_PLUGIN } from '../../meta';
|
|
13
13
|
import { NAV_TREE_ITEM } from '../NavTree';
|
|
14
14
|
import { useNavTreeContext } from '../NavTreeContext';
|
|
15
|
-
import type
|
|
15
|
+
import { type NavTreeItemColumnsProps } from '../types';
|
|
16
16
|
|
|
17
17
|
export const NavTreeItemColumns = memo(({ path, item, open, density = 'fine' }: NavTreeItemColumnsProps) => {
|
|
18
18
|
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
19
19
|
const { getActions, renderItemEnd: ItemEnd, popoverAnchorId } = useNavTreeContext();
|
|
20
20
|
|
|
21
21
|
const level = path.length - 2;
|
|
22
|
-
|
|
23
22
|
const { actions: _actions, groupedActions } = getActions(item);
|
|
24
|
-
const [primaryAction, ...secondaryActions] = _actions.toSorted((a,
|
|
23
|
+
const [primaryAction, ...secondaryActions] = _actions.toSorted((a, _b) =>
|
|
25
24
|
a.properties?.disposition === 'list-item-primary' ? -1 : 1,
|
|
26
25
|
);
|
|
27
26
|
|
|
@@ -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 { 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/react-ui-theme';
|
|
12
12
|
|
|
13
|
-
import {
|
|
14
|
-
import { NAVTREE_PLUGIN } from '../../meta';
|
|
15
|
-
import { l0ItemType } from '../../util';
|
|
13
|
+
import { meta } from '../../meta';
|
|
16
14
|
import { useNavTreeContext } from '../NavTreeContext';
|
|
17
15
|
import { NavTreeItemColumns } from '../NavTreeItem';
|
|
18
16
|
|
|
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
17
|
export type L1PanelProps = {
|
|
35
18
|
open?: boolean;
|
|
36
|
-
item: Node<any>;
|
|
37
19
|
path: string[];
|
|
20
|
+
item: Node<any>;
|
|
38
21
|
currentItemId: string;
|
|
39
22
|
onBack?: () => void;
|
|
40
23
|
};
|
|
41
24
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Space or settings panel.
|
|
27
|
+
*/
|
|
28
|
+
export const L1Panel = ({ open, path, item, currentItemId, onBack }: L1PanelProps) => {
|
|
29
|
+
const { t } = useTranslation(meta.id);
|
|
30
|
+
const { isAlternateTree, ...navTreeContext } = useNavTreeContext();
|
|
31
|
+
// NOTE(burdon): I'm very uneasy about this pattern of declaring hooks as context props.
|
|
32
|
+
const { useItems } = navTreeContext;
|
|
33
|
+
const title = toLocalizedString(item.properties.label, t);
|
|
45
34
|
|
|
46
35
|
// TODO(wittjosiah): Support multiple alternate trees.
|
|
47
|
-
const alternateTree =
|
|
36
|
+
const alternateTree = useItems(item, { disposition: 'alternate-tree' })[0];
|
|
48
37
|
const alternatePath = useMemo(() => [...path, item.id], [item.id, path]);
|
|
49
|
-
const handleOpen = useCallback(() => setAlternateTree?.(alternatePath, true), [alternatePath, setAlternateTree]);
|
|
50
38
|
const isAlternate = isAlternateTree?.(alternatePath, item) ?? false;
|
|
51
39
|
const useAlternateItems = useCallback(
|
|
52
40
|
(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}
|
|
@@ -83,26 +60,7 @@ const L1Panel = ({ open, item, path, currentItemId, onBack }: L1PanelProps) => {
|
|
|
83
60
|
>
|
|
84
61
|
{item.id === currentItemId && (
|
|
85
62
|
<>
|
|
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>
|
|
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
|
|
@@ -134,41 +92,63 @@ const L1Panel = ({ open, item, path, currentItemId, onBack }: L1PanelProps) => {
|
|
|
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 { isAlternateTree, 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 = isAlternateTree?.(alternatePath, item) ?? false;
|
|
107
|
+
const backCapable = item.id.startsWith('!') || isAlternate;
|
|
108
|
+
|
|
109
|
+
const handleOpen = useCallback(() => {
|
|
110
|
+
setAlternateTree?.(alternatePath, true);
|
|
111
|
+
}, [alternatePath, setAlternateTree]);
|
|
112
|
+
|
|
113
|
+
const handleBack = useCallback(() => {
|
|
114
|
+
if (isAlternate) {
|
|
115
|
+
setAlternateTree?.(alternatePath, false);
|
|
116
|
+
} else {
|
|
117
|
+
onBack?.();
|
|
118
|
+
}
|
|
119
|
+
}, [isAlternate, alternatePath, setAlternateTree, onBack]);
|
|
157
120
|
|
|
158
|
-
|
|
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
|
+
<div>
|
|
127
|
+
{(backCapable && (
|
|
128
|
+
<IconButton
|
|
129
|
+
variant='ghost'
|
|
130
|
+
icon='ph--arrow-u-down-left--regular'
|
|
131
|
+
iconOnly
|
|
132
|
+
size={5}
|
|
133
|
+
label={t('button back')}
|
|
134
|
+
classNames={[hoverableControlItem, hoverableOpenControlItem, 'pointer-fine:pli-1']}
|
|
135
|
+
onClick={handleBack}
|
|
136
|
+
/>
|
|
137
|
+
)) ||
|
|
138
|
+
(alternateTree && !isAlternate && (
|
|
139
|
+
<IconButton
|
|
140
|
+
data-testid='treeView.alternateTreeButton'
|
|
141
|
+
variant='ghost'
|
|
142
|
+
icon={alternateTree.properties.icon ?? 'ph--placeholder--regular'}
|
|
143
|
+
iconOnly
|
|
144
|
+
size={5}
|
|
145
|
+
label={toLocalizedString(alternateTree.properties.label ?? alternateTree.id, t)}
|
|
146
|
+
classNames={[hoverableControlItem, hoverableOpenControlItem, 'pointer-fine:pli-1']}
|
|
147
|
+
onClick={handleOpen}
|
|
148
|
+
/>
|
|
149
|
+
)) || <div />}
|
|
150
|
+
</div>
|
|
151
|
+
<NavTreeItemColumns open path={path} item={item} density='coarse' />
|
|
152
|
+
</div>
|
|
173
153
|
);
|
|
174
154
|
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useMemo } from 'react';
|
|
6
|
+
|
|
7
|
+
import { type Node } from '@dxos/app-graph';
|
|
8
|
+
|
|
9
|
+
import { useLoadDescendents } from '../../hooks';
|
|
10
|
+
import { l0ItemType } from '../../util';
|
|
11
|
+
import { useNavTreeContext } from '../NavTreeContext';
|
|
12
|
+
import { L1Panel, type L1PanelProps } from './L1Panel';
|
|
13
|
+
|
|
14
|
+
export type L1TabsProps = Pick<L1PanelProps, 'open' | 'currentItemId' | 'onBack'> & {
|
|
15
|
+
path: string[];
|
|
16
|
+
topLevelItems: Node<any>[];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Each space is an L1 tab.
|
|
21
|
+
*/
|
|
22
|
+
export const L1Tabs = ({ topLevelItems, onBack, ...props }: L1TabsProps) => {
|
|
23
|
+
return (
|
|
24
|
+
<>
|
|
25
|
+
{topLevelItems.map((item) => {
|
|
26
|
+
const type = l0ItemType(item);
|
|
27
|
+
switch (type) {
|
|
28
|
+
case 'tab':
|
|
29
|
+
return <L1Panel key={item.id} item={item} {...props} onBack={onBack} />;
|
|
30
|
+
case 'collection':
|
|
31
|
+
return <L1PanelCollection key={item.id} item={item} {...props} />;
|
|
32
|
+
default:
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
})}
|
|
36
|
+
</>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
*/
|
|
43
|
+
const L1PanelCollection = ({ item, path, ...props }: L1PanelProps) => {
|
|
44
|
+
const { useItems } = useNavTreeContext();
|
|
45
|
+
useLoadDescendents(item);
|
|
46
|
+
const collectionItems = useItems(item);
|
|
47
|
+
const groupPath = useMemo(() => [...path, item.id], [item.id, path]);
|
|
48
|
+
return (
|
|
49
|
+
<>
|
|
50
|
+
{collectionItems
|
|
51
|
+
.filter((item) => l0ItemType(item) === 'tab')
|
|
52
|
+
.map((item) => (
|
|
53
|
+
<L1Panel key={item.id} item={item} path={groupPath} {...props} />
|
|
54
|
+
))}
|
|
55
|
+
</>
|
|
56
|
+
);
|
|
57
|
+
};
|