@dxos/plugin-navtree 0.8.4-main.7ace549 → 0.8.4-main.937b3ca
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-E6MZBCU5.mjs → chunk-YKTYPINZ.mjs} +1 -1
- package/dist/lib/browser/chunk-YKTYPINZ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +82 -91
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/{keyboard-YJEK2HTH.mjs → keyboard-32EH3N4K.mjs} +17 -14
- 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 -108
- 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 +30 -1
- package/dist/types/src/components/NavTree/NavTree.d.ts.map +1 -1
- package/dist/types/src/components/NavTree/NavTree.stories.d.ts +4 -1
- 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 +2 -1
- package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/L0Menu.d.ts +4 -4
- package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/L1Panel.d.ts +1 -1
- package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/L1Tabs.d.ts +2 -2
- package/dist/types/src/components/Sidebar/L1Tabs.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/types.d.ts +7 -7
- package/dist/types/src/components/types.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 +2 -2
- 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/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} +6 -6
- package/dist/types/src/types/schema.d.ts.map +1 -0
- package/dist/types/src/util.d.ts +7 -7
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +53 -52
- package/src/NavTreePlugin.tsx +53 -70
- 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 +107 -104
- package/src/components/CommandsDialog/CommandsTrigger.tsx +4 -14
- package/src/components/NavTree/NavTree.stories.tsx +32 -41
- package/src/components/NavTree/NavTree.tsx +5 -15
- package/src/components/NavTreeContainer.tsx +251 -292
- package/src/components/NavTreeDocumentTitle.tsx +3 -2
- package/src/components/NavTreeItem/NavTreeItemAction.stories.tsx +17 -7
- package/src/components/NavTreeItem/NavTreeItemAction.tsx +18 -12
- package/src/components/NavTreeItem/NavTreeItemColumns.tsx +5 -5
- package/src/components/Sidebar/L0Menu.tsx +65 -91
- package/src/components/Sidebar/L1Panel.tsx +9 -7
- package/src/components/Sidebar/L1Tabs.tsx +6 -31
- package/src/components/index.ts +1 -0
- package/src/components/types.ts +7 -7
- package/src/experimental/Tree.stories.tsx +2 -2
- package/src/experimental/Tree.tsx +1 -1
- package/src/hooks.ts +54 -2
- package/src/index.ts +1 -2
- package/src/meta.ts +2 -2
- package/src/testing/app-graph-builder.ts +158 -234
- package/src/testing/generator.ts +12 -12
- package/src/testing/update-state.ts +6 -6
- 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} +5 -5
- package/src/util.ts +13 -16
- package/dist/lib/browser/app-graph-builder-OHSCN3GX.mjs +0 -46
- package/dist/lib/browser/app-graph-builder-OHSCN3GX.mjs.map +0 -7
- package/dist/lib/browser/chunk-5VLWX4PK.mjs +0 -15
- package/dist/lib/browser/chunk-5VLWX4PK.mjs.map +0 -7
- package/dist/lib/browser/chunk-E6MZBCU5.mjs.map +0 -7
- package/dist/lib/browser/chunk-UDAINHB6.mjs +0 -1488
- package/dist/lib/browser/chunk-UDAINHB6.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-YUVXVPHG.mjs +0 -47
- package/dist/lib/browser/intent-resolver-YUVXVPHG.mjs.map +0 -7
- package/dist/lib/browser/keyboard-YJEK2HTH.mjs.map +0 -7
- package/dist/lib/browser/react-surface-V6LS3R4L.mjs +0 -51
- package/dist/lib/browser/react-surface-V6LS3R4L.mjs.map +0 -7
- package/dist/lib/browser/state-BFD5KJCV.mjs +0 -117
- package/dist/lib/browser/state-BFD5KJCV.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 -53
- package/src/capabilities/capabilities.ts +0 -20
- package/src/capabilities/intent-resolver.ts +0 -37
- package/src/capabilities/keyboard.ts +0 -57
- package/src/capabilities/react-surface.tsx +0 -45
- package/src/capabilities/state.ts +0 -104
- package/src/events.ts +0 -11
package/src/hooks.ts
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { type Atom, useAtomValue } from '@effect-atom/atom-react';
|
|
6
|
+
import { useEffect, useMemo } from 'react';
|
|
6
7
|
|
|
8
|
+
import { useCapability } from '@dxos/app-framework/react';
|
|
7
9
|
import { type Node } from '@dxos/app-graph';
|
|
8
10
|
|
|
9
11
|
import { useNavTreeContext } from './components';
|
|
12
|
+
import { NavTreeCapabilities } from './types';
|
|
10
13
|
|
|
11
|
-
export const useLoadDescendents = (root?: Node) => {
|
|
14
|
+
export const useLoadDescendents = (root?: Node.Node) => {
|
|
12
15
|
const { loadDescendents } = useNavTreeContext();
|
|
13
16
|
useEffect(() => {
|
|
14
17
|
const frame = requestAnimationFrame(() => {
|
|
@@ -19,3 +22,52 @@ export const useLoadDescendents = (root?: Node) => {
|
|
|
19
22
|
return () => cancelAnimationFrame(frame);
|
|
20
23
|
}, [root]);
|
|
21
24
|
};
|
|
25
|
+
|
|
26
|
+
export type UseNavTreeStateResult = {
|
|
27
|
+
getItem: (path: string[]) => NavTreeCapabilities.NavTreeItemState;
|
|
28
|
+
getItemAtom: (path: string[]) => Atom.Atom<NavTreeCapabilities.NavTreeItemState>;
|
|
29
|
+
setItem: (path: string[], key: 'open' | 'current' | 'alternateTree', next: boolean) => void;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Hook that provides access to navtree state functions.
|
|
34
|
+
* For reactive subscriptions, use `useNavTreeItemState` or `useAtomValue(getItemAtom(path))`.
|
|
35
|
+
*/
|
|
36
|
+
export const useNavTreeState = (): UseNavTreeStateResult => {
|
|
37
|
+
return useCapability(NavTreeCapabilities.State);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Hook that subscribes to a single navtree item's state.
|
|
42
|
+
* Use this for fine-grained reactivity.
|
|
43
|
+
*/
|
|
44
|
+
export const useNavTreeItemState = (path: string[]): NavTreeCapabilities.NavTreeItemState => {
|
|
45
|
+
const { getItemAtom } = useCapability(NavTreeCapabilities.State);
|
|
46
|
+
// Memoize the path to avoid creating new atoms on every render.
|
|
47
|
+
const pathKey = useMemo(() => path.join('~'), [path]);
|
|
48
|
+
const atom = useMemo(() => getItemAtom(path), [getItemAtom, pathKey]);
|
|
49
|
+
return useAtomValue(atom);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Hook that subscribes to the open state for a tree item.
|
|
54
|
+
* Designed to be passed to Tree component as useIsOpen prop.
|
|
55
|
+
*/
|
|
56
|
+
export const useIsOpen = (path: string[], _item?: any): boolean => {
|
|
57
|
+
return useNavTreeItemState(path).open;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Hook that subscribes to the current state for a tree item.
|
|
62
|
+
* Designed to be passed to Tree component as useIsCurrent prop.
|
|
63
|
+
*/
|
|
64
|
+
export const useIsCurrent = (path: string[], _item?: any): boolean => {
|
|
65
|
+
return useNavTreeItemState(path).current;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Hook that subscribes to the alternateTree state for a tree item.
|
|
70
|
+
*/
|
|
71
|
+
export const useIsAlternateTree = (path: string[], _item?: any): boolean => {
|
|
72
|
+
return useNavTreeItemState(path).alternateTree ?? false;
|
|
73
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
export { NavTreeCapabilities } from './
|
|
6
|
-
export { NavTreeEvents } from './events';
|
|
5
|
+
export { NavTreeCapabilities, NavTreeEvents } from './types';
|
|
7
6
|
export * from './NavTreePlugin';
|
|
8
7
|
export * from './meta';
|
|
9
8
|
export * from './util';
|
package/src/meta.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { type
|
|
5
|
+
import { type Plugin } from '@dxos/app-framework';
|
|
6
6
|
import { trim } from '@dxos/util';
|
|
7
7
|
|
|
8
|
-
export const meta:
|
|
8
|
+
export const meta: Plugin.Meta = {
|
|
9
9
|
id: 'dxos.org/plugin/navtree',
|
|
10
10
|
name: 'Navtree',
|
|
11
11
|
description: trim`
|
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Atom } from '@effect-atom/atom-react';
|
|
6
|
-
import * as
|
|
7
|
-
import * as Option from 'effect/Option';
|
|
6
|
+
import * as Effect from 'effect/Effect';
|
|
8
7
|
|
|
9
|
-
import { type
|
|
8
|
+
import { type BuilderExtensions } from '@dxos/app-graph';
|
|
10
9
|
import { log } from '@dxos/log';
|
|
11
|
-
import {
|
|
10
|
+
import { GraphBuilder, NodeMatcher } from '@dxos/plugin-graph';
|
|
12
11
|
import { faker } from '@dxos/random';
|
|
13
12
|
|
|
14
|
-
export const storybookGraphBuilders = (
|
|
13
|
+
export const storybookGraphBuilders = (): BuilderExtensions => {
|
|
15
14
|
const propertiesCache = new Map<string, Record<string, unknown>>();
|
|
16
15
|
const getProperties = (id: string, defaults: Record<string, unknown>) => {
|
|
17
16
|
const cached = propertiesCache.get(id);
|
|
@@ -23,249 +22,174 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
|
|
|
23
22
|
return defaults;
|
|
24
23
|
};
|
|
25
24
|
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
disposition: 'menu',
|
|
46
|
-
},
|
|
47
|
-
})),
|
|
48
|
-
];
|
|
49
|
-
}),
|
|
50
|
-
Option.getOrElse(() => []),
|
|
25
|
+
return Effect.runSync(
|
|
26
|
+
Effect.all([
|
|
27
|
+
// Create app menu actions.
|
|
28
|
+
GraphBuilder.createExtension({
|
|
29
|
+
id: 'app-menu',
|
|
30
|
+
match: NodeMatcher.whenRoot,
|
|
31
|
+
actions: () =>
|
|
32
|
+
Effect.succeed(
|
|
33
|
+
Array.from({ length: 5 }, (_, i) => ({
|
|
34
|
+
id: `app-menu/action-${i}`,
|
|
35
|
+
data: Effect.fnUntraced(function* () {
|
|
36
|
+
log.info('action', { id: 'app-menu', index: i });
|
|
37
|
+
}),
|
|
38
|
+
properties: {
|
|
39
|
+
label: `Action ${i}`,
|
|
40
|
+
icon: faker.properties.icon(),
|
|
41
|
+
disposition: 'menu',
|
|
42
|
+
},
|
|
43
|
+
})),
|
|
51
44
|
),
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
45
|
+
}),
|
|
46
|
+
// Create user account node.
|
|
47
|
+
GraphBuilder.createExtension({
|
|
48
|
+
id: 'user-account',
|
|
49
|
+
match: NodeMatcher.whenRoot,
|
|
50
|
+
connector: () =>
|
|
51
|
+
Effect.succeed([
|
|
52
|
+
{
|
|
53
|
+
id: 'user-account',
|
|
54
|
+
type: 'user-account',
|
|
55
|
+
properties: {
|
|
56
|
+
label: 'User profile',
|
|
57
|
+
icon: 'ph--user--regular',
|
|
58
|
+
disposition: 'user-account',
|
|
59
|
+
userId: '1234567890ABCDEF',
|
|
60
|
+
hue: faker.properties.hue(),
|
|
61
|
+
emoji: faker.properties.emoji(),
|
|
62
|
+
status: 'active',
|
|
63
|
+
},
|
|
64
|
+
nodes: [
|
|
64
65
|
{
|
|
65
|
-
id: '
|
|
66
|
-
type: '
|
|
66
|
+
id: 'profile',
|
|
67
|
+
type: 'profile',
|
|
67
68
|
properties: {
|
|
68
|
-
label: '
|
|
69
|
+
label: 'Profile',
|
|
69
70
|
icon: 'ph--user--regular',
|
|
70
|
-
disposition: 'user-account',
|
|
71
|
-
userId: '1234567890ABCDEF',
|
|
72
|
-
hue: faker.properties.hue(),
|
|
73
|
-
emoji: faker.properties.emoji(),
|
|
74
|
-
status: 'active',
|
|
75
71
|
},
|
|
76
|
-
nodes: [
|
|
77
|
-
{
|
|
78
|
-
id: 'profile',
|
|
79
|
-
type: 'profile',
|
|
80
|
-
properties: {
|
|
81
|
-
label: 'Profile',
|
|
82
|
-
icon: 'ph--user--regular',
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
id: 'devices',
|
|
87
|
-
type: 'devices',
|
|
88
|
-
properties: {
|
|
89
|
-
label: 'Devices',
|
|
90
|
-
icon: 'ph--devices--regular',
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
id: 'security',
|
|
95
|
-
type: 'security',
|
|
96
|
-
properties: {
|
|
97
|
-
label: 'Security',
|
|
98
|
-
icon: 'ph--key--regular',
|
|
99
|
-
},
|
|
100
|
-
},
|
|
101
|
-
],
|
|
102
72
|
},
|
|
103
|
-
];
|
|
104
|
-
}),
|
|
105
|
-
Option.getOrElse(() => []),
|
|
106
|
-
),
|
|
107
|
-
),
|
|
108
|
-
}),
|
|
109
|
-
// TODO(wittjosiah): This group node probably is unnecessary now with the flat L0 structure.
|
|
110
|
-
// Create spaces group node.
|
|
111
|
-
createExtension({
|
|
112
|
-
id: 'spaces-root',
|
|
113
|
-
position: 'hoist',
|
|
114
|
-
connector: (node) =>
|
|
115
|
-
Atom.make((get) =>
|
|
116
|
-
Function.pipe(
|
|
117
|
-
get(node),
|
|
118
|
-
Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
|
|
119
|
-
Option.map(() => {
|
|
120
|
-
return [
|
|
121
73
|
{
|
|
122
|
-
id: '
|
|
123
|
-
type: '
|
|
74
|
+
id: 'devices',
|
|
75
|
+
type: 'devices',
|
|
124
76
|
properties: {
|
|
125
|
-
label: '
|
|
126
|
-
icon: 'ph--
|
|
127
|
-
role: 'branch',
|
|
128
|
-
disposition: 'collection',
|
|
77
|
+
label: 'Devices',
|
|
78
|
+
icon: 'ph--devices--regular',
|
|
129
79
|
},
|
|
130
80
|
},
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
81
|
+
{
|
|
82
|
+
id: 'security',
|
|
83
|
+
type: 'security',
|
|
84
|
+
properties: {
|
|
85
|
+
label: 'Security',
|
|
86
|
+
icon: 'ph--key--regular',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
]),
|
|
92
|
+
}),
|
|
93
|
+
// Create space (workspace) nodes directly under root.
|
|
94
|
+
GraphBuilder.createExtension({
|
|
95
|
+
id: 'spaces',
|
|
96
|
+
match: NodeMatcher.whenRoot,
|
|
97
|
+
connector: (_, get) =>
|
|
98
|
+
Effect.sync(() => {
|
|
99
|
+
const count = Atom.make((get) => {
|
|
100
|
+
let value = 3;
|
|
101
|
+
const interval = setInterval(() => {
|
|
102
|
+
if (value >= 10) {
|
|
103
|
+
clearInterval(interval);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
148
106
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
107
|
+
value++;
|
|
108
|
+
get.setSelf(value);
|
|
109
|
+
}, 5000);
|
|
110
|
+
get.addFinalizer(() => clearInterval(interval));
|
|
111
|
+
return value;
|
|
112
|
+
});
|
|
155
113
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
get(node),
|
|
185
|
-
Option.flatMap((node) => (node.type === 'space' ? Option.some(node) : Option.none())),
|
|
186
|
-
Option.map((node) => {
|
|
187
|
-
return [
|
|
188
|
-
...Array.from({ length: 5 }, (_, i) => ({
|
|
189
|
-
id: `${node.id}/action-${i}`,
|
|
190
|
-
data: () => {
|
|
191
|
-
log.info('action', { id: node.id, index: i });
|
|
192
|
-
},
|
|
193
|
-
properties: getProperties(`${node.id}/action-${i}`, {
|
|
194
|
-
label: `Action ${i}`,
|
|
195
|
-
icon: faker.properties.icon(),
|
|
196
|
-
}),
|
|
197
|
-
})),
|
|
198
|
-
];
|
|
199
|
-
}),
|
|
200
|
-
Option.getOrElse(() => []),
|
|
114
|
+
return Array.from({ length: get(count) }, (_, i) => ({
|
|
115
|
+
id: `space-${i}`,
|
|
116
|
+
type: 'space',
|
|
117
|
+
properties: getProperties(`space-${i}`, {
|
|
118
|
+
label: `Space ${i}`,
|
|
119
|
+
icon: faker.properties.icon(),
|
|
120
|
+
hue: faker.properties.hue(),
|
|
121
|
+
disposition: 'workspace',
|
|
122
|
+
}),
|
|
123
|
+
}));
|
|
124
|
+
}),
|
|
125
|
+
}),
|
|
126
|
+
// Create space actions.
|
|
127
|
+
GraphBuilder.createExtension({
|
|
128
|
+
id: 'space-actions',
|
|
129
|
+
match: NodeMatcher.whenNodeType('space'),
|
|
130
|
+
actions: () =>
|
|
131
|
+
Effect.succeed(
|
|
132
|
+
Array.from({ length: 5 }, (_, i) => ({
|
|
133
|
+
id: `space-actions/action-${i}`,
|
|
134
|
+
data: Effect.fnUntraced(function* () {
|
|
135
|
+
log.info('action', { id: 'space-actions', index: i });
|
|
136
|
+
}),
|
|
137
|
+
properties: getProperties(`space-actions/action-${i}`, {
|
|
138
|
+
label: `Action ${i}`,
|
|
139
|
+
icon: faker.properties.icon(),
|
|
140
|
+
}),
|
|
141
|
+
})),
|
|
201
142
|
),
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
143
|
+
}),
|
|
144
|
+
// Create object nodes.
|
|
145
|
+
GraphBuilder.createExtension({
|
|
146
|
+
id: 'objects',
|
|
147
|
+
match: NodeMatcher.whenNodeType('space'),
|
|
148
|
+
connector: (_, get) =>
|
|
149
|
+
Effect.sync(() => {
|
|
150
|
+
const count = Atom.make((get) => {
|
|
151
|
+
let value = 3;
|
|
152
|
+
const interval = setInterval(() => {
|
|
153
|
+
if (value >= 20) {
|
|
154
|
+
clearInterval(interval);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
215
157
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
158
|
+
value++;
|
|
159
|
+
get.setSelf(value);
|
|
160
|
+
}, 5000);
|
|
161
|
+
get.addFinalizer(() => clearInterval(interval));
|
|
162
|
+
return value;
|
|
163
|
+
});
|
|
222
164
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
Function.pipe(
|
|
250
|
-
get(node),
|
|
251
|
-
Option.flatMap((node) => (node.type === 'object' ? Option.some(node) : Option.none())),
|
|
252
|
-
Option.map((node) => {
|
|
253
|
-
return [
|
|
254
|
-
...Array.from({ length: 5 }, (_, i) => ({
|
|
255
|
-
id: `${node.id}/action-${i}`,
|
|
256
|
-
data: () => {
|
|
257
|
-
log.info('action', { id: node.id, index: i });
|
|
258
|
-
},
|
|
259
|
-
properties: getProperties(`${node.id}/action-${i}`, {
|
|
260
|
-
label: `Action ${i}`,
|
|
261
|
-
icon: faker.properties.icon(),
|
|
262
|
-
}),
|
|
263
|
-
})),
|
|
264
|
-
];
|
|
265
|
-
}),
|
|
266
|
-
Option.getOrElse(() => []),
|
|
165
|
+
return Array.from({ length: get(count) }, (_, i) => ({
|
|
166
|
+
id: `object-${i}`,
|
|
167
|
+
type: 'object',
|
|
168
|
+
properties: getProperties(`object-${i}`, {
|
|
169
|
+
label: `Object ${i}`,
|
|
170
|
+
icon: faker.properties.icon(),
|
|
171
|
+
}),
|
|
172
|
+
}));
|
|
173
|
+
}),
|
|
174
|
+
}),
|
|
175
|
+
// Create object actions.
|
|
176
|
+
GraphBuilder.createExtension({
|
|
177
|
+
id: 'object-actions',
|
|
178
|
+
match: NodeMatcher.whenNodeType('object'),
|
|
179
|
+
actions: () =>
|
|
180
|
+
Effect.succeed(
|
|
181
|
+
Array.from({ length: 5 }, (_, i) => ({
|
|
182
|
+
id: `object-actions/action-${i}`,
|
|
183
|
+
data: Effect.fnUntraced(function* () {
|
|
184
|
+
log.info('action', { id: 'object-actions', index: i });
|
|
185
|
+
}),
|
|
186
|
+
properties: getProperties(`object-actions/action-${i}`, {
|
|
187
|
+
label: `Action ${i}`,
|
|
188
|
+
icon: faker.properties.icon(),
|
|
189
|
+
}),
|
|
190
|
+
})),
|
|
267
191
|
),
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
192
|
+
}),
|
|
193
|
+
]),
|
|
194
|
+
);
|
|
271
195
|
};
|
package/src/testing/generator.ts
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
|
|
7
|
-
import { type
|
|
7
|
+
import { type Node } from '@dxos/app-graph';
|
|
8
8
|
import { Obj, Type } from '@dxos/echo';
|
|
9
|
-
import {
|
|
9
|
+
import { TestSchema } from '@dxos/echo/testing';
|
|
10
10
|
import { faker } from '@dxos/random';
|
|
11
11
|
import { range } from '@dxos/util';
|
|
12
12
|
|
|
@@ -17,12 +17,12 @@ import { range } from '@dxos/util';
|
|
|
17
17
|
export type TestItem = { id: string; type: string } & Record<string, any>;
|
|
18
18
|
|
|
19
19
|
type ObjectDataGenerator = {
|
|
20
|
-
createSchema?: () =>
|
|
20
|
+
createSchema?: () => Type.Obj.Any;
|
|
21
21
|
createData: () => any;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
type ObjectFactory<T
|
|
25
|
-
schema?:
|
|
24
|
+
type ObjectFactory<T> = {
|
|
25
|
+
schema?: Type.Obj.Any; // TODO(burdon): Support both typed and expando schema.
|
|
26
26
|
createObject: () => T;
|
|
27
27
|
};
|
|
28
28
|
|
|
@@ -32,7 +32,7 @@ const createFactory = ({ createSchema, createData }: ObjectDataGenerator) => {
|
|
|
32
32
|
const schema = createSchema?.();
|
|
33
33
|
return {
|
|
34
34
|
schema,
|
|
35
|
-
createObject: () => (schema ? Obj.make(schema, createData()) : Obj.make(
|
|
35
|
+
createObject: () => (schema ? Obj.make(schema, createData()) : Obj.make(TestSchema.Expando, createData())),
|
|
36
36
|
};
|
|
37
37
|
};
|
|
38
38
|
|
|
@@ -64,7 +64,7 @@ export const defaultGenerators: { [type: string]: ObjectDataGenerator } = {
|
|
|
64
64
|
status: Schema.String,
|
|
65
65
|
priority: Schema.Number,
|
|
66
66
|
}).pipe(
|
|
67
|
-
Type.
|
|
67
|
+
Type.object({
|
|
68
68
|
typename: 'example.com/type/Project',
|
|
69
69
|
version: '0.1.0',
|
|
70
70
|
}),
|
|
@@ -94,7 +94,7 @@ export class TestObjectGenerator {
|
|
|
94
94
|
}, {});
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
get schema():
|
|
97
|
+
get schema(): Type.Obj.Any[] {
|
|
98
98
|
return Object.values(this.factories).map((f) => f.schema!);
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -142,7 +142,7 @@ export const createTree = () => {
|
|
|
142
142
|
properties: {
|
|
143
143
|
label: l0.title,
|
|
144
144
|
icon: 'ph--horse--regular',
|
|
145
|
-
disposition: '
|
|
145
|
+
disposition: 'workspace',
|
|
146
146
|
},
|
|
147
147
|
nodes: [
|
|
148
148
|
...[...Array(4)].map(() => {
|
|
@@ -175,7 +175,7 @@ export const createTree = () => {
|
|
|
175
175
|
},
|
|
176
176
|
},
|
|
177
177
|
],
|
|
178
|
-
} satisfies NodeArg<any>;
|
|
178
|
+
} satisfies Node.NodeArg<any>;
|
|
179
179
|
}),
|
|
180
180
|
{
|
|
181
181
|
id: `${faker.string.uuid()}__a1`,
|
|
@@ -196,9 +196,9 @@ export const createTree = () => {
|
|
|
196
196
|
},
|
|
197
197
|
},
|
|
198
198
|
],
|
|
199
|
-
} satisfies NodeArg<any>;
|
|
199
|
+
} satisfies Node.NodeArg<any>;
|
|
200
200
|
}),
|
|
201
|
-
} satisfies NodeArg<any>;
|
|
201
|
+
} satisfies Node.NodeArg<any>;
|
|
202
202
|
|
|
203
203
|
return initialContent;
|
|
204
204
|
};
|
|
@@ -4,22 +4,22 @@
|
|
|
4
4
|
|
|
5
5
|
import { type Instruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
|
|
6
6
|
|
|
7
|
-
import { type
|
|
7
|
+
import { type Node } from '@dxos/app-graph';
|
|
8
8
|
import { log } from '@dxos/log';
|
|
9
9
|
import { type TreeData } from '@dxos/react-ui-list';
|
|
10
10
|
|
|
11
|
-
const removeItem = (tree: NodeArg<any>, source: TreeData) => {
|
|
11
|
+
const removeItem = (tree: Node.NodeArg<any>, source: TreeData) => {
|
|
12
12
|
const parent = getNode(tree, source.path.slice(1, -1));
|
|
13
|
-
const index = parent.nodes!.findIndex((
|
|
13
|
+
const index = parent.nodes!.findIndex((node: Node.NodeArg<any>) => node.id === source.id);
|
|
14
14
|
const item = parent.nodes![index];
|
|
15
15
|
parent.nodes!.splice(index, 1);
|
|
16
16
|
return item;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
const getNode = (tree: NodeArg<any>, path: string[]) => {
|
|
19
|
+
const getNode = (tree: Node.NodeArg<any>, path: string[]) => {
|
|
20
20
|
let node = tree;
|
|
21
21
|
for (const part of path) {
|
|
22
|
-
node = node.nodes!.find((
|
|
22
|
+
node = node.nodes!.find((n: Node.NodeArg<any>) => n.id === part)!;
|
|
23
23
|
}
|
|
24
24
|
return node;
|
|
25
25
|
};
|
|
@@ -31,7 +31,7 @@ export const updateState = ({
|
|
|
31
31
|
source,
|
|
32
32
|
target,
|
|
33
33
|
}: {
|
|
34
|
-
state: NodeArg<any>;
|
|
34
|
+
state: Node.NodeArg<any>;
|
|
35
35
|
instruction: Instruction;
|
|
36
36
|
source: TreeData;
|
|
37
37
|
target: TreeData;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Atom } from '@effect-atom/atom-react';
|
|
6
|
+
|
|
7
|
+
import { Capability } from '@dxos/app-framework';
|
|
8
|
+
|
|
9
|
+
import { meta } from '../meta';
|
|
10
|
+
|
|
11
|
+
export namespace NavTreeCapabilities {
|
|
12
|
+
export type NavTreeItemState = { open: boolean; current: boolean; alternateTree?: boolean };
|
|
13
|
+
|
|
14
|
+
export type NavTreeStateStore = {
|
|
15
|
+
getItem: (path: string[]) => NavTreeItemState;
|
|
16
|
+
getItemAtom: (path: string[]) => Atom.Atom<NavTreeItemState>;
|
|
17
|
+
setItem: (path: string[], key: 'open' | 'current' | 'alternateTree', next: boolean) => void;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const State = Capability.make<NavTreeStateStore>(`${meta.id}/capability/state`);
|
|
21
|
+
}
|