@dxos/plugin-navtree 0.8.4-main.ae835ea → 0.8.4-main.bc674ce

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/dist/lib/browser/app-graph-builder-RSMA6I22.mjs +43 -0
  2. package/dist/lib/browser/app-graph-builder-RSMA6I22.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-6YPQ625I.mjs +1293 -0
  4. package/dist/lib/browser/chunk-6YPQ625I.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-AGQDZBPL.mjs +23 -0
  6. package/dist/lib/browser/chunk-AGQDZBPL.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-E6MZBCU5.mjs → chunk-YKTYPINZ.mjs} +1 -1
  8. package/dist/lib/browser/chunk-YKTYPINZ.mjs.map +7 -0
  9. package/dist/lib/browser/index.mjs +82 -91
  10. package/dist/lib/browser/index.mjs.map +4 -4
  11. package/dist/lib/browser/{keyboard-YYTYJW4M.mjs → keyboard-32EH3N4K.mjs} +20 -19
  12. package/dist/lib/browser/keyboard-32EH3N4K.mjs.map +7 -0
  13. package/dist/lib/browser/meta.json +1 -1
  14. package/dist/lib/browser/operation-resolver-IB75DC5O.mjs +52 -0
  15. package/dist/lib/browser/operation-resolver-IB75DC5O.mjs.map +7 -0
  16. package/dist/lib/browser/react-surface-F6CVMS3Y.mjs +58 -0
  17. package/dist/lib/browser/react-surface-F6CVMS3Y.mjs.map +7 -0
  18. package/dist/lib/browser/state-EVYQOUI3.mjs +120 -0
  19. package/dist/lib/browser/state-EVYQOUI3.mjs.map +7 -0
  20. package/dist/types/src/NavTreePlugin.d.ts +2 -1
  21. package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
  22. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts +6 -0
  23. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +1 -0
  24. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +3 -0
  25. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +1 -0
  26. package/dist/types/src/capabilities/index.d.ts +5 -108
  27. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  28. package/dist/types/src/capabilities/keyboard/index.d.ts +3 -0
  29. package/dist/types/src/capabilities/keyboard/index.d.ts.map +1 -0
  30. package/dist/types/src/capabilities/keyboard/keyboard.d.ts +5 -0
  31. package/dist/types/src/capabilities/keyboard/keyboard.d.ts.map +1 -0
  32. package/dist/types/src/capabilities/operation-resolver/index.d.ts +3 -0
  33. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +1 -0
  34. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +5 -0
  35. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +1 -0
  36. package/dist/types/src/capabilities/react-surface/index.d.ts +3 -0
  37. package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -0
  38. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +5 -0
  39. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -0
  40. package/dist/types/src/capabilities/state/index.d.ts +3 -0
  41. package/dist/types/src/capabilities/state/index.d.ts.map +1 -0
  42. package/dist/types/src/capabilities/state/state.d.ts +6 -0
  43. package/dist/types/src/capabilities/state/state.d.ts.map +1 -0
  44. package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts +3 -2
  45. package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts.map +1 -1
  46. package/dist/types/src/components/CommandsDialog/CommandsTrigger.d.ts.map +1 -1
  47. package/dist/types/src/components/NavTree/NavTree.d.ts +30 -1
  48. package/dist/types/src/components/NavTree/NavTree.d.ts.map +1 -1
  49. package/dist/types/src/components/NavTree/NavTree.stories.d.ts +4 -1
  50. package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +1 -1
  51. package/dist/types/src/components/NavTreeContainer.d.ts +8 -1
  52. package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
  53. package/dist/types/src/components/NavTreeDocumentTitle.d.ts +1 -1
  54. package/dist/types/src/components/NavTreeDocumentTitle.d.ts.map +1 -1
  55. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts +6 -6
  56. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts.map +1 -1
  57. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +2 -1
  58. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +1 -1
  59. package/dist/types/src/components/Sidebar/L0Menu.d.ts +4 -4
  60. package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -1
  61. package/dist/types/src/components/Sidebar/L1Panel.d.ts +1 -1
  62. package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -1
  63. package/dist/types/src/components/Sidebar/L1Tabs.d.ts +2 -2
  64. package/dist/types/src/components/Sidebar/L1Tabs.d.ts.map +1 -1
  65. package/dist/types/src/components/index.d.ts.map +1 -1
  66. package/dist/types/src/components/types.d.ts +7 -7
  67. package/dist/types/src/components/types.d.ts.map +1 -1
  68. package/dist/types/src/hooks.d.ts +32 -1
  69. package/dist/types/src/hooks.d.ts.map +1 -1
  70. package/dist/types/src/index.d.ts +1 -2
  71. package/dist/types/src/index.d.ts.map +1 -1
  72. package/dist/types/src/meta.d.ts +2 -2
  73. package/dist/types/src/meta.d.ts.map +1 -1
  74. package/dist/types/src/testing/app-graph-builder.d.ts +2 -3
  75. package/dist/types/src/testing/app-graph-builder.d.ts.map +1 -1
  76. package/dist/types/src/testing/generator.d.ts +5 -6
  77. package/dist/types/src/testing/generator.d.ts.map +1 -1
  78. package/dist/types/src/testing/update-state.d.ts +2 -2
  79. package/dist/types/src/testing/update-state.d.ts.map +1 -1
  80. package/dist/types/src/types/capabilities.d.ts +16 -0
  81. package/dist/types/src/types/capabilities.d.ts.map +1 -0
  82. package/dist/types/src/types/events.d.ts +5 -0
  83. package/dist/types/src/types/events.d.ts.map +1 -0
  84. package/dist/types/src/types/index.d.ts +4 -0
  85. package/dist/types/src/types/index.d.ts.map +1 -0
  86. package/dist/types/src/{types.d.ts → types/schema.d.ts} +6 -6
  87. package/dist/types/src/types/schema.d.ts.map +1 -0
  88. package/dist/types/src/util.d.ts +7 -7
  89. package/dist/types/src/util.d.ts.map +1 -1
  90. package/dist/types/tsconfig.tsbuildinfo +1 -1
  91. package/package.json +53 -52
  92. package/src/NavTreePlugin.tsx +53 -70
  93. package/src/capabilities/app-graph-builder/app-graph-builder.ts +41 -0
  94. package/src/capabilities/app-graph-builder/index.ts +7 -0
  95. package/src/capabilities/index.ts +5 -9
  96. package/src/capabilities/keyboard/index.ts +7 -0
  97. package/src/capabilities/keyboard/keyboard.ts +65 -0
  98. package/src/capabilities/operation-resolver/index.ts +7 -0
  99. package/src/capabilities/operation-resolver/operation-resolver.ts +41 -0
  100. package/src/capabilities/react-surface/index.ts +7 -0
  101. package/src/capabilities/react-surface/react-surface.tsx +54 -0
  102. package/src/capabilities/state/index.ts +7 -0
  103. package/src/capabilities/state/state.ts +121 -0
  104. package/src/components/CommandsDialog/CommandsDialog.tsx +108 -97
  105. package/src/components/CommandsDialog/CommandsTrigger.tsx +4 -13
  106. package/src/components/NavTree/NavTree.stories.tsx +33 -42
  107. package/src/components/NavTree/NavTree.tsx +5 -15
  108. package/src/components/NavTreeContainer.tsx +253 -262
  109. package/src/components/NavTreeDocumentTitle.tsx +3 -2
  110. package/src/components/NavTreeItem/NavTreeItemAction.stories.tsx +17 -7
  111. package/src/components/NavTreeItem/NavTreeItemAction.tsx +18 -12
  112. package/src/components/NavTreeItem/NavTreeItemColumns.tsx +5 -5
  113. package/src/components/Sidebar/L0Menu.tsx +67 -93
  114. package/src/components/Sidebar/L1Panel.tsx +9 -9
  115. package/src/components/Sidebar/L1Tabs.tsx +6 -31
  116. package/src/components/index.ts +1 -0
  117. package/src/components/types.ts +7 -7
  118. package/src/experimental/Tree.stories.tsx +4 -4
  119. package/src/experimental/Tree.tsx +3 -3
  120. package/src/hooks.ts +54 -2
  121. package/src/index.ts +1 -2
  122. package/src/meta.ts +2 -2
  123. package/src/testing/app-graph-builder.ts +159 -235
  124. package/src/testing/generator.ts +19 -17
  125. package/src/testing/update-state.ts +6 -6
  126. package/src/types/capabilities.ts +21 -0
  127. package/src/types/events.ts +11 -0
  128. package/src/types/index.ts +7 -0
  129. package/src/{types.ts → types/schema.ts} +5 -5
  130. package/src/util.ts +13 -16
  131. package/dist/lib/browser/app-graph-builder-D7NLWZLU.mjs +0 -46
  132. package/dist/lib/browser/app-graph-builder-D7NLWZLU.mjs.map +0 -7
  133. package/dist/lib/browser/chunk-5VLWX4PK.mjs +0 -15
  134. package/dist/lib/browser/chunk-5VLWX4PK.mjs.map +0 -7
  135. package/dist/lib/browser/chunk-BNGPXJB7.mjs +0 -1482
  136. package/dist/lib/browser/chunk-BNGPXJB7.mjs.map +0 -7
  137. package/dist/lib/browser/chunk-E6MZBCU5.mjs.map +0 -7
  138. package/dist/lib/browser/intent-resolver-YUVXVPHG.mjs +0 -47
  139. package/dist/lib/browser/intent-resolver-YUVXVPHG.mjs.map +0 -7
  140. package/dist/lib/browser/keyboard-YYTYJW4M.mjs.map +0 -7
  141. package/dist/lib/browser/react-surface-7OUBD57A.mjs +0 -51
  142. package/dist/lib/browser/react-surface-7OUBD57A.mjs.map +0 -7
  143. package/dist/lib/browser/state-EUSVT6BI.mjs +0 -117
  144. package/dist/lib/browser/state-EUSVT6BI.mjs.map +0 -7
  145. package/dist/types/src/capabilities/app-graph-builder.d.ts +0 -4
  146. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +0 -1
  147. package/dist/types/src/capabilities/capabilities.d.ts +0 -21
  148. package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
  149. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  150. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  151. package/dist/types/src/capabilities/keyboard.d.ts +0 -4
  152. package/dist/types/src/capabilities/keyboard.d.ts.map +0 -1
  153. package/dist/types/src/capabilities/react-surface.d.ts +0 -4
  154. package/dist/types/src/capabilities/react-surface.d.ts.map +0 -1
  155. package/dist/types/src/capabilities/state.d.ts +0 -20
  156. package/dist/types/src/capabilities/state.d.ts.map +0 -1
  157. package/dist/types/src/events.d.ts +0 -4
  158. package/dist/types/src/events.d.ts.map +0 -1
  159. package/dist/types/src/types.d.ts.map +0 -1
  160. package/src/capabilities/app-graph-builder.ts +0 -53
  161. package/src/capabilities/capabilities.ts +0 -20
  162. package/src/capabilities/intent-resolver.ts +0 -37
  163. package/src/capabilities/keyboard.ts +0 -59
  164. package/src/capabilities/react-surface.tsx +0 -45
  165. package/src/capabilities/state.ts +0 -105
  166. 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 { useEffect } from 'react';
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 './capabilities';
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 PluginMeta } from '@dxos/app-framework';
5
+ import { type Plugin } from '@dxos/app-framework';
6
6
  import { trim } from '@dxos/util';
7
7
 
8
- export const meta: PluginMeta = {
8
+ export const meta: Plugin.Meta = {
9
9
  id: 'dxos.org/plugin/navtree',
10
10
  name: 'Navtree',
11
11
  description: trim`
@@ -2,16 +2,15 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Rx } from '@effect-rx/rx-react';
6
- import * as Function from 'effect/Function';
7
- import * as Option from 'effect/Option';
5
+ import { Atom } from '@effect-atom/atom-react';
6
+ import * as Effect from 'effect/Effect';
8
7
 
9
- import { type PluginContext } from '@dxos/app-framework';
8
+ import { type BuilderExtensions } from '@dxos/app-graph';
10
9
  import { log } from '@dxos/log';
11
- import { type BuilderExtensions, ROOT_ID, createExtension } from '@dxos/plugin-graph';
10
+ import { GraphBuilder, NodeMatcher } from '@dxos/plugin-graph';
12
11
  import { faker } from '@dxos/random';
13
12
 
14
- export const storybookGraphBuilders = (context: PluginContext): BuilderExtensions => {
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
- // Create app menu actions.
28
- createExtension({
29
- id: 'app-menu',
30
- actions: (node) =>
31
- Rx.make((get) =>
32
- Function.pipe(
33
- get(node),
34
- Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
35
- Option.map((node) => {
36
- return [
37
- ...Array.from({ length: 5 }, (_, i) => ({
38
- id: `${node.id}/action-${i}`,
39
- data: () => {
40
- log.info('action', { id: node.id, index: i });
41
- },
42
- properties: {
43
- label: `Action ${i}`,
44
- icon: faker.properties.icon(),
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
- // Create user account node.
55
- createExtension({
56
- id: 'user-account',
57
- connector: (node) =>
58
- Rx.make((get) =>
59
- Function.pipe(
60
- get(node),
61
- Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
62
- Option.map(() => {
63
- return [
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: 'user-account',
66
- type: 'user-account',
66
+ id: 'profile',
67
+ type: 'profile',
67
68
  properties: {
68
- label: 'User Account',
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
- Rx.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: 'spaces-root',
123
- type: 'spaces-root',
74
+ id: 'devices',
75
+ type: 'devices',
124
76
  properties: {
125
- label: 'Spaces',
126
- icon: 'ph--planet--regular',
127
- role: 'branch',
128
- disposition: 'collection',
77
+ label: 'Devices',
78
+ icon: 'ph--devices--regular',
129
79
  },
130
80
  },
131
- ];
132
- }),
133
- Option.getOrElse(() => []),
134
- ),
135
- ),
136
- }),
137
- // Create space nodes.
138
- createExtension({
139
- id: 'spaces',
140
- connector: (node) => {
141
- const count = Rx.make((get) => {
142
- let value = 3;
143
- const interval = setInterval(() => {
144
- if (value >= 10) {
145
- clearInterval(interval);
146
- return;
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
- value++;
150
- get.setSelf(value);
151
- }, 5000);
152
- get.addFinalizer(() => clearInterval(interval));
153
- return value;
154
- });
107
+ value++;
108
+ get.setSelf(value);
109
+ }, 5000);
110
+ get.addFinalizer(() => clearInterval(interval));
111
+ return value;
112
+ });
155
113
 
156
- return Rx.make((get) =>
157
- Function.pipe(
158
- get(node),
159
- Option.flatMap((node) => (node.id === 'spaces-root' ? Option.some(node) : Option.none())),
160
- Option.map(() => {
161
- return [
162
- ...Array.from({ length: get(count) }, (_, i) => ({
163
- id: `space-${i}`,
164
- type: 'space',
165
- properties: getProperties(`space-${i}`, {
166
- label: `Space ${i}`,
167
- icon: faker.properties.icon(),
168
- hue: faker.properties.hue(),
169
- }),
170
- })),
171
- ];
172
- }),
173
- Option.getOrElse(() => []),
174
- ),
175
- );
176
- },
177
- }),
178
- // Create space actions.
179
- createExtension({
180
- id: 'space-actions',
181
- actions: (node) =>
182
- Rx.make((get) =>
183
- Function.pipe(
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
- // Create object nodes.
205
- createExtension({
206
- id: 'objects',
207
- connector: (node) => {
208
- const count = Rx.make((get) => {
209
- let value = 3;
210
- const interval = setInterval(() => {
211
- if (value >= 20) {
212
- clearInterval(interval);
213
- return;
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
- value++;
217
- get.setSelf(value);
218
- }, 5000);
219
- get.addFinalizer(() => clearInterval(interval));
220
- return value;
221
- });
158
+ value++;
159
+ get.setSelf(value);
160
+ }, 5000);
161
+ get.addFinalizer(() => clearInterval(interval));
162
+ return value;
163
+ });
222
164
 
223
- return Rx.make((get) =>
224
- Function.pipe(
225
- get(node),
226
- Option.flatMap((node) => (node.type === 'space' ? Option.some(node) : Option.none())),
227
- Option.map((node) => {
228
- return [
229
- ...Array.from({ length: get(count) }, (_, i) => ({
230
- id: `${node.id}/object-${i}`,
231
- type: 'object',
232
- properties: getProperties(`${node.id}/object-${i}`, {
233
- label: `Object ${i}`,
234
- icon: faker.properties.icon(),
235
- }),
236
- })),
237
- ];
238
- }),
239
- Option.getOrElse(() => []),
240
- ),
241
- );
242
- },
243
- }),
244
- // Create object actions.
245
- createExtension({
246
- id: 'object-actions',
247
- actions: (node) =>
248
- Rx.make((get) =>
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
  };
@@ -4,9 +4,9 @@
4
4
 
5
5
  import * as Schema from 'effect/Schema';
6
6
 
7
- import { type NodeArg } from '@dxos/app-graph';
8
- import { type Live, Obj, Type } from '@dxos/echo';
9
- import { TypedObject } from '@dxos/echo/internal';
7
+ import { type Node } from '@dxos/app-graph';
8
+ import { Obj, Type } from '@dxos/echo';
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?: () => Schema.Schema.AnyNoContext;
20
+ createSchema?: () => Type.Obj.Any;
21
21
  createData: () => any;
22
22
  };
23
23
 
24
- type ObjectFactory<T extends Live<any>> = {
25
- schema?: Schema.Schema.AnyNoContext; // TODO(burdon): Support both typed and expando 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(Type.Expando, createData())),
35
+ createObject: () => (schema ? Obj.make(schema, createData()) : Obj.make(TestSchema.Expando, createData())),
36
36
  };
37
37
  };
38
38
 
@@ -58,15 +58,17 @@ export const defaultGenerators: { [type: string]: ObjectDataGenerator } = {
58
58
 
59
59
  project: {
60
60
  createSchema: () =>
61
- class ProjectType extends TypedObject({
62
- typename: 'example.com/type/Project',
63
- version: '0.1.0',
64
- })({
61
+ Schema.Struct({
65
62
  title: Schema.String,
66
63
  repo: Schema.String,
67
64
  status: Schema.String,
68
65
  priority: Schema.Number,
69
- }) {},
66
+ }).pipe(
67
+ Type.object({
68
+ typename: 'example.com/type/Project',
69
+ version: '0.1.0',
70
+ }),
71
+ ),
70
72
 
71
73
  createData: () => ({
72
74
  title: faker.commerce.productName(),
@@ -92,7 +94,7 @@ export class TestObjectGenerator {
92
94
  }, {});
93
95
  }
94
96
 
95
- get schema(): Schema.Schema.AnyNoContext[] {
97
+ get schema(): Type.Obj.Any[] {
96
98
  return Object.values(this.factories).map((f) => f.schema!);
97
99
  }
98
100
 
@@ -140,7 +142,7 @@ export const createTree = () => {
140
142
  properties: {
141
143
  label: l0.title,
142
144
  icon: 'ph--horse--regular',
143
- disposition: 'collection',
145
+ disposition: 'workspace',
144
146
  },
145
147
  nodes: [
146
148
  ...[...Array(4)].map(() => {
@@ -173,7 +175,7 @@ export const createTree = () => {
173
175
  },
174
176
  },
175
177
  ],
176
- } satisfies NodeArg<any>;
178
+ } satisfies Node.NodeArg<any>;
177
179
  }),
178
180
  {
179
181
  id: `${faker.string.uuid()}__a1`,
@@ -194,9 +196,9 @@ export const createTree = () => {
194
196
  },
195
197
  },
196
198
  ],
197
- } satisfies NodeArg<any>;
199
+ } satisfies Node.NodeArg<any>;
198
200
  }),
199
- } satisfies NodeArg<any>;
201
+ } satisfies Node.NodeArg<any>;
200
202
 
201
203
  return initialContent;
202
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 NodeArg } from '@dxos/app-graph';
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(({ id }) => id === source.id);
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(({ id }) => id === part)!;
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;