@dxos/plugin-navtree 0.8.4-main.5ad4a44 → 0.8.4-main.66e292d

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 (57) hide show
  1. package/dist/lib/browser/{app-graph-builder-YAPMENYT.mjs → app-graph-builder-OHSCN3GX.mjs} +4 -4
  2. package/dist/lib/browser/app-graph-builder-OHSCN3GX.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-LPAREX6J.mjs → chunk-5VLWX4PK.mjs} +2 -2
  4. package/dist/lib/browser/chunk-E6MZBCU5.mjs +19 -0
  5. package/dist/lib/browser/chunk-E6MZBCU5.mjs.map +7 -0
  6. package/dist/lib/browser/{chunk-IMFXKPSB.mjs → chunk-UDAINHB6.mjs} +49 -43
  7. package/dist/lib/browser/chunk-UDAINHB6.mjs.map +7 -0
  8. package/dist/lib/browser/index.mjs +3 -3
  9. package/dist/lib/browser/{intent-resolver-TCQXGF6U.mjs → intent-resolver-YUVXVPHG.mjs} +3 -3
  10. package/dist/lib/browser/{keyboard-AHSAWKXA.mjs → keyboard-YJEK2HTH.mjs} +6 -8
  11. package/dist/lib/browser/{keyboard-AHSAWKXA.mjs.map → keyboard-YJEK2HTH.mjs.map} +2 -2
  12. package/dist/lib/browser/meta.json +1 -1
  13. package/dist/lib/browser/{react-surface-AH2TP73M.mjs → react-surface-V6LS3R4L.mjs} +4 -4
  14. package/dist/lib/browser/{state-2Q623V7U.mjs → state-BFD5KJCV.mjs} +3 -3
  15. package/dist/lib/browser/state-BFD5KJCV.mjs.map +7 -0
  16. package/dist/types/src/capabilities/index.d.ts +3 -3
  17. package/dist/types/src/capabilities/keyboard.d.ts.map +1 -1
  18. package/dist/types/src/capabilities/state.d.ts +1 -1
  19. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  20. package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts.map +1 -1
  21. package/dist/types/src/components/CommandsDialog/CommandsTrigger.d.ts.map +1 -1
  22. package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
  23. package/dist/types/src/components/types.d.ts +1 -1
  24. package/dist/types/src/components/types.d.ts.map +1 -1
  25. package/dist/types/src/experimental/Tree.stories.d.ts +0 -3
  26. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
  27. package/dist/types/src/meta.d.ts.map +1 -1
  28. package/dist/types/src/testing/generator.d.ts +1 -1
  29. package/dist/types/src/testing/generator.d.ts.map +1 -1
  30. package/dist/types/src/types.d.ts +1 -1
  31. package/dist/types/src/types.d.ts.map +1 -1
  32. package/dist/types/tsconfig.tsbuildinfo +1 -1
  33. package/package.json +39 -39
  34. package/src/capabilities/app-graph-builder.ts +2 -2
  35. package/src/capabilities/keyboard.ts +1 -3
  36. package/src/capabilities/state.ts +1 -2
  37. package/src/components/CommandsDialog/CommandsDialog.tsx +11 -3
  38. package/src/components/CommandsDialog/CommandsTrigger.tsx +2 -1
  39. package/src/components/NavTree/NavTree.stories.tsx +2 -2
  40. package/src/components/NavTreeContainer.tsx +74 -42
  41. package/src/components/Sidebar/L0Menu.tsx +4 -4
  42. package/src/components/Sidebar/L1Panel.tsx +0 -2
  43. package/src/components/types.ts +1 -1
  44. package/src/experimental/Tree.stories.tsx +4 -7
  45. package/src/experimental/Tree.tsx +2 -2
  46. package/src/meta.ts +5 -0
  47. package/src/testing/app-graph-builder.ts +10 -10
  48. package/src/testing/generator.ts +9 -7
  49. package/src/types.ts +1 -1
  50. package/dist/lib/browser/app-graph-builder-YAPMENYT.mjs.map +0 -7
  51. package/dist/lib/browser/chunk-IMFXKPSB.mjs.map +0 -7
  52. package/dist/lib/browser/chunk-ZENLR72O.mjs +0 -14
  53. package/dist/lib/browser/chunk-ZENLR72O.mjs.map +0 -7
  54. package/dist/lib/browser/state-2Q623V7U.mjs.map +0 -7
  55. /package/dist/lib/browser/{chunk-LPAREX6J.mjs.map → chunk-5VLWX4PK.mjs.map} +0 -0
  56. /package/dist/lib/browser/{intent-resolver-TCQXGF6U.mjs.map → intent-resolver-YUVXVPHG.mjs.map} +0 -0
  57. /package/dist/lib/browser/{react-surface-AH2TP73M.mjs.map → react-surface-V6LS3R4L.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.5ad4a44",
3
+ "version": "0.8.4-main.66e292d",
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",
@@ -31,58 +31,58 @@
31
31
  "@radix-ui/react-dismissable-layer": "1.1.5",
32
32
  "@radix-ui/react-use-controllable-state": "1.1.0",
33
33
  "date-fns": "^3.3.1",
34
- "@dxos/app-framework": "0.8.4-main.5ad4a44",
35
- "@dxos/async": "0.8.4-main.5ad4a44",
36
- "@dxos/debug": "0.8.4-main.5ad4a44",
37
- "@dxos/app-graph": "0.8.4-main.5ad4a44",
38
- "@dxos/invariant": "0.8.4-main.5ad4a44",
39
- "@dxos/echo": "0.8.4-main.5ad4a44",
40
- "@dxos/lit-ui": "0.8.4-main.5ad4a44",
41
- "@dxos/keyboard": "0.8.4-main.5ad4a44",
42
- "@dxos/local-storage": "0.8.4-main.5ad4a44",
43
- "@dxos/live-object": "0.8.4-main.5ad4a44",
44
- "@dxos/log": "0.8.4-main.5ad4a44",
45
- "@dxos/plugin-deck": "0.8.4-main.5ad4a44",
46
- "@dxos/plugin-graph": "0.8.4-main.5ad4a44",
47
- "@dxos/plugin-observability": "0.8.4-main.5ad4a44",
48
- "@dxos/protocols": "0.8.4-main.5ad4a44",
49
- "@dxos/react-client": "0.8.4-main.5ad4a44",
50
- "@dxos/react-ui-attention": "0.8.4-main.5ad4a44",
51
- "@dxos/react-ui-list": "0.8.4-main.5ad4a44",
52
- "@dxos/react-ui-menu": "0.8.4-main.5ad4a44",
53
- "@dxos/react-ui-searchlist": "0.8.4-main.5ad4a44",
54
- "@dxos/react-ui-stack": "0.8.4-main.5ad4a44",
55
- "@dxos/react-ui-tabs": "0.8.4-main.5ad4a44",
56
- "@dxos/util": "0.8.4-main.5ad4a44"
34
+ "@dxos/app-framework": "0.8.4-main.66e292d",
35
+ "@dxos/app-graph": "0.8.4-main.66e292d",
36
+ "@dxos/debug": "0.8.4-main.66e292d",
37
+ "@dxos/echo": "0.8.4-main.66e292d",
38
+ "@dxos/async": "0.8.4-main.66e292d",
39
+ "@dxos/invariant": "0.8.4-main.66e292d",
40
+ "@dxos/keyboard": "0.8.4-main.66e292d",
41
+ "@dxos/lit-ui": "0.8.4-main.66e292d",
42
+ "@dxos/local-storage": "0.8.4-main.66e292d",
43
+ "@dxos/live-object": "0.8.4-main.66e292d",
44
+ "@dxos/log": "0.8.4-main.66e292d",
45
+ "@dxos/plugin-graph": "0.8.4-main.66e292d",
46
+ "@dxos/plugin-deck": "0.8.4-main.66e292d",
47
+ "@dxos/plugin-observability": "0.8.4-main.66e292d",
48
+ "@dxos/react-client": "0.8.4-main.66e292d",
49
+ "@dxos/protocols": "0.8.4-main.66e292d",
50
+ "@dxos/react-ui-attention": "0.8.4-main.66e292d",
51
+ "@dxos/react-ui-list": "0.8.4-main.66e292d",
52
+ "@dxos/react-ui-menu": "0.8.4-main.66e292d",
53
+ "@dxos/react-ui-searchlist": "0.8.4-main.66e292d",
54
+ "@dxos/react-ui-stack": "0.8.4-main.66e292d",
55
+ "@dxos/react-ui-tabs": "0.8.4-main.66e292d",
56
+ "@dxos/util": "0.8.4-main.66e292d"
57
57
  },
58
58
  "devDependencies": {
59
- "@effect-rx/rx-react": "0.42.4",
59
+ "@effect-atom/atom-react": "^0.3.4",
60
60
  "@effect/platform": "0.92.1",
61
61
  "@types/react": "~19.2.2",
62
- "@types/react-dom": "~19.2.1",
62
+ "@types/react-dom": "~19.2.2",
63
63
  "effect": "3.18.3",
64
64
  "react": "~19.2.0",
65
65
  "react-dom": "~19.2.0",
66
66
  "vite": "7.1.9",
67
- "@dxos/echo-signals": "0.8.4-main.5ad4a44",
68
- "@dxos/plugin-attention": "0.8.4-main.5ad4a44",
69
- "@dxos/plugin-client": "0.8.4-main.5ad4a44",
70
- "@dxos/plugin-space": "0.8.4-main.5ad4a44",
71
- "@dxos/plugin-theme": "0.8.4-main.5ad4a44",
72
- "@dxos/random": "0.8.4-main.5ad4a44",
73
- "@dxos/plugin-storybook-layout": "0.8.4-main.5ad4a44",
74
- "@dxos/react-ui": "0.8.4-main.5ad4a44",
75
- "@dxos/react-ui-theme": "0.8.4-main.5ad4a44",
76
- "@dxos/storybook-utils": "0.8.4-main.5ad4a44"
67
+ "@dxos/echo-signals": "0.8.4-main.66e292d",
68
+ "@dxos/plugin-attention": "0.8.4-main.66e292d",
69
+ "@dxos/plugin-client": "0.8.4-main.66e292d",
70
+ "@dxos/plugin-space": "0.8.4-main.66e292d",
71
+ "@dxos/plugin-storybook-layout": "0.8.4-main.66e292d",
72
+ "@dxos/plugin-theme": "0.8.4-main.66e292d",
73
+ "@dxos/react-ui": "0.8.4-main.66e292d",
74
+ "@dxos/react-ui-theme": "0.8.4-main.66e292d",
75
+ "@dxos/random": "0.8.4-main.66e292d",
76
+ "@dxos/storybook-utils": "0.8.4-main.66e292d"
77
77
  },
78
78
  "peerDependencies": {
79
- "@effect-rx/rx-react": "^0.34.1",
79
+ "@effect-atom/atom-react": "^0.3.4",
80
80
  "@effect/platform": "^0.80.12",
81
81
  "effect": "^3.13.3",
82
82
  "react": "^19.0.0",
83
83
  "react-dom": "^19.0.0",
84
- "@dxos/react-ui": "0.8.4-main.5ad4a44",
85
- "@dxos/react-ui-theme": "0.8.4-main.5ad4a44"
84
+ "@dxos/react-ui": "0.8.4-main.66e292d",
85
+ "@dxos/react-ui-theme": "0.8.4-main.66e292d"
86
86
  },
87
87
  "publishConfig": {
88
88
  "access": "public"
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Rx } from '@effect-rx/rx-react';
5
+ import { Atom } from '@effect-atom/atom-react';
6
6
  import * as Function from 'effect/Function';
7
7
  import * as Option from 'effect/Option';
8
8
 
@@ -17,7 +17,7 @@ export default (context: PluginContext) =>
17
17
  createExtension({
18
18
  id: meta.id,
19
19
  actions: (node) =>
20
- Rx.make((get) =>
20
+ Atom.make((get) =>
21
21
  Function.pipe(
22
22
  get(node),
23
23
  Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
@@ -34,9 +34,7 @@ export default (context: PluginContext) => {
34
34
  if (shortcut && isAction(node)) {
35
35
  Keyboard.singleton.getContext(path.slice(0, -1).join('/')).bind({
36
36
  shortcut,
37
- handler: () => {
38
- void node.data({ parent: node, caller: KEY_BINDING });
39
- },
37
+ handler: () => node.data({ parent: node, caller: KEY_BINDING }),
40
38
  data: node.properties.label,
41
39
  });
42
40
  }
@@ -5,8 +5,7 @@
5
5
  import { effect, untracked } from '@preact/signals-core';
6
6
 
7
7
  import { Capabilities, type PluginContext, contributes } from '@dxos/app-framework';
8
- import { type Live } from '@dxos/echo';
9
- import { live } from '@dxos/live-object';
8
+ import { type Live, live } from '@dxos/live-object';
10
9
  import { Path } from '@dxos/react-ui-list';
11
10
 
12
11
  import { meta } from '../meta';
@@ -4,7 +4,8 @@
4
4
 
5
5
  import React, { useMemo, useState } from 'react';
6
6
 
7
- import { LayoutAction, createIntent, useAppGraph, useIntentDispatcher } from '@dxos/app-framework';
7
+ import { LayoutAction, createIntent } from '@dxos/app-framework';
8
+ import { useAppGraph, useIntentDispatcher } from '@dxos/app-framework/react';
8
9
  import { type ActionLike, isAction, isActionGroup } from '@dxos/app-graph';
9
10
  import { Keyboard, keySymbols } from '@dxos/keyboard';
10
11
  import { useActions } from '@dxos/plugin-graph';
@@ -89,7 +90,12 @@ export const CommandsDialogContent = ({ selected: initial }: { selected?: string
89
90
  return;
90
91
  }
91
92
 
92
- void dispatch(createIntent(LayoutAction.UpdateDialog, { part: 'dialog', options: { state: false } }));
93
+ void dispatch(
94
+ createIntent(LayoutAction.UpdateDialog, {
95
+ part: 'dialog',
96
+ options: { state: false },
97
+ }),
98
+ );
93
99
  setTimeout(() => {
94
100
  const node = graph.getConnections(group?.id ?? action.id, 'inbound')[0];
95
101
  void (node && isAction(action) && action.data({ parent: node, caller: KEY_BINDING }));
@@ -97,7 +103,9 @@ export const CommandsDialogContent = ({ selected: initial }: { selected?: string
97
103
  }}
98
104
  classNames='flex items-center gap-2'
99
105
  disabled={action.properties.disabled}
100
- {...(action.properties?.testId && { 'data-testid': action.properties.testId })}
106
+ {...(action.properties?.testId && {
107
+ 'data-testid': action.properties.testId,
108
+ })}
101
109
  >
102
110
  <Icon icon={action.properties.icon} size={4} />
103
111
  <span className='grow truncate'>{label}</span>
@@ -4,7 +4,8 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { LayoutAction, createIntent, useIntentDispatcher } from '@dxos/app-framework';
7
+ import { LayoutAction, createIntent } from '@dxos/app-framework';
8
+ import { useIntentDispatcher } from '@dxos/app-framework/react';
8
9
  import { Button, Icon, useTranslation } from '@dxos/react-ui';
9
10
 
10
11
  import { COMMANDS_DIALOG, meta } from '../../meta';
@@ -15,8 +15,8 @@ import {
15
15
  contributes,
16
16
  createResolver,
17
17
  defineCapability,
18
- useCapability,
19
18
  } from '@dxos/app-framework';
19
+ import { useCapability } from '@dxos/app-framework/react';
20
20
  import { withPluginManager } from '@dxos/app-framework/testing';
21
21
  import { live } from '@dxos/live-object';
22
22
  import { AttentionPlugin } from '@dxos/plugin-attention';
@@ -86,7 +86,7 @@ const StoryPlank = ({ attendableId }: { attendableId: string }) => {
86
86
  >
87
87
  <StoryPlankHeading attendableId={attendableId} />
88
88
  <StackItem.Content toolbar>
89
- <Toolbar.Root classNames='border-b border-subduedSeparator'>
89
+ <Toolbar.Root classNames='border-be border-subduedSeparator'>
90
90
  <Toolbar.Button>Test</Toolbar.Button>
91
91
  </Toolbar.Root>
92
92
 
@@ -7,15 +7,8 @@ import { type Instruction, extractInstruction } from '@atlaskit/pragmatic-drag-a
7
7
  import { untracked } from '@preact/signals-core';
8
8
  import React, { memo, useCallback, useEffect, useMemo } from 'react';
9
9
 
10
- import {
11
- LayoutAction,
12
- Surface,
13
- createIntent,
14
- useAppGraph,
15
- useCapability,
16
- useIntentDispatcher,
17
- useLayout,
18
- } from '@dxos/app-framework';
10
+ import { LayoutAction, createIntent } from '@dxos/app-framework';
11
+ import { Surface, useAppGraph, useCapability, useIntentDispatcher, useLayout } from '@dxos/app-framework/react';
19
12
  import { type Node, ROOT_ID, type ReadableGraph, isAction, isActionLike } from '@dxos/app-graph';
20
13
  import { PLANK_COMPANION_TYPE } from '@dxos/plugin-deck/types';
21
14
  import { useConnections, useActions as useGraphActions } from '@dxos/plugin-graph';
@@ -118,7 +111,7 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
118
111
  className: mx(node.properties.className, node.properties.modified && 'italic'), // TODO(burdon): Italic?
119
112
  headingClassName: node.properties.headingClassName,
120
113
  icon: node.properties.icon,
121
- iconClassName: node.properties.iconClassName,
114
+ iconHue: node.properties.iconHue,
122
115
  testId: node.properties.testId,
123
116
  };
124
117
  },
@@ -163,19 +156,36 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
163
156
  }),
164
157
  );
165
158
 
166
- await dispatch(createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: node.id }));
159
+ await dispatch(
160
+ createIntent(LayoutAction.SwitchWorkspace, {
161
+ part: 'workspace',
162
+ subject: node.id,
163
+ }),
164
+ );
167
165
 
168
166
  // Open the first item if the workspace is empty.
169
167
  if (layout.active.length === 0) {
170
168
  const [item] = getItems(graph, node).filter((node) => !isActionLike(node));
171
169
  if (item && item.data) {
172
- await dispatch(createIntent(LayoutAction.Open, { part: 'main', subject: [item.id] }));
170
+ await dispatch(
171
+ createIntent(LayoutAction.Open, {
172
+ part: 'main',
173
+ subject: [item.id],
174
+ }),
175
+ );
173
176
  }
174
177
  }
175
178
  },
176
179
  [dispatch, layout.active, tab, navigationSidebarState, isLg],
177
180
  );
178
181
 
182
+ const blockInstruction = useCallback(
183
+ ({ instruction, source, target }: { instruction: Instruction; source: TreeData; target: TreeData }) => {
184
+ return target.item.properties.blockInstruction?.(source, instruction) ?? false;
185
+ },
186
+ [],
187
+ );
188
+
179
189
  const canDrop = useCallback(({ source, target }: { source: TreeData; target: TreeData }) => {
180
190
  return target.item.properties.canDrop?.(source) ?? false;
181
191
  }, []);
@@ -207,10 +217,19 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
207
217
  );
208
218
  } else if (option) {
209
219
  void dispatch(
210
- createIntent(LayoutAction.Close, { part: 'main', subject: [node.id], options: { state: false } }),
220
+ createIntent(LayoutAction.Close, {
221
+ part: 'main',
222
+ subject: [node.id],
223
+ options: { state: false },
224
+ }),
211
225
  );
212
226
  } else {
213
- void dispatch(createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: node.id }));
227
+ void dispatch(
228
+ createIntent(LayoutAction.ScrollIntoView, {
229
+ part: 'current',
230
+ subject: node.id,
231
+ }),
232
+ );
214
233
  }
215
234
 
216
235
  const defaultAction = graph.getActions(node.id).find((action) => action.properties?.disposition === 'default');
@@ -219,14 +238,25 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
219
238
  }
220
239
 
221
240
  if (!isLg) {
222
- void dispatch(createIntent(LayoutAction.UpdateSidebar, { part: 'sidebar', options: { state: 'closed' } }));
241
+ void dispatch(
242
+ createIntent(LayoutAction.UpdateSidebar, {
243
+ part: 'sidebar',
244
+ options: { state: 'closed' },
245
+ }),
246
+ );
223
247
  }
224
248
  },
225
249
  [graph, dispatch, isCurrent, isLg],
226
250
  );
227
251
 
228
252
  const handleBack = useCallback(
229
- () => dispatch(createIntent(LayoutAction.RevertWorkspace, { part: 'workspace', options: { revert: true } })),
253
+ () =>
254
+ dispatch(
255
+ createIntent(LayoutAction.RevertWorkspace, {
256
+ part: 'workspace',
257
+ options: { revert: true },
258
+ }),
259
+ ),
230
260
  [dispatch],
231
261
  );
232
262
 
@@ -298,43 +328,45 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
298
328
 
299
329
  const navTreeContextValue = useMemo(
300
330
  () => ({
301
- useItems,
302
- tab,
303
- useActions,
304
- loadDescendents,
305
- renderItemEnd,
306
- popoverAnchorId,
307
- topbar,
308
- getProps,
309
- isCurrent,
310
- isOpen,
331
+ blockInstruction,
311
332
  canDrop,
312
333
  canSelect,
334
+ getProps,
313
335
  isAlternateTree,
314
- setAlternateTree,
315
- onTabChange: handleTabChange,
336
+ isCurrent,
337
+ isOpen,
338
+ loadDescendents,
339
+ onBack: handleBack,
316
340
  onOpenChange: handleOpenChange,
317
341
  onSelect: handleSelect,
318
- onBack: handleBack,
319
- }),
320
- [
321
- tab,
322
- useActions,
323
- loadDescendents,
324
- renderItemEnd,
342
+ onTabChange: handleTabChange,
325
343
  popoverAnchorId,
344
+ renderItemEnd,
345
+ setAlternateTree,
346
+ tab,
326
347
  topbar,
327
- getProps,
328
- isCurrent,
329
- isOpen,
348
+ useActions,
349
+ useItems,
350
+ }),
351
+ [
352
+ blockInstruction,
330
353
  canDrop,
331
354
  canSelect,
332
- isAlternateTree,
333
- setAlternateTree,
334
- handleTabChange,
355
+ getProps,
356
+ handleBack,
335
357
  handleOpenChange,
336
358
  handleSelect,
337
- handleBack,
359
+ handleTabChange,
360
+ isAlternateTree,
361
+ isCurrent,
362
+ isOpen,
363
+ loadDescendents,
364
+ popoverAnchorId,
365
+ renderItemEnd,
366
+ setAlternateTree,
367
+ tab,
368
+ topbar,
369
+ useActions,
338
370
  ],
339
371
  );
340
372
 
@@ -102,7 +102,7 @@ const l0Breakpoints: Record<string, string> = {
102
102
  };
103
103
 
104
104
  const l0ItemRoot =
105
- 'group/l0item flex w-full justify-center items-center relative data[type!="collection"]:cursor-pointer app-no-drag dx-focus-ring-group';
105
+ 'group/l0item flex is-full justify-center items-center relative data[type!="collection"]:cursor-pointer app-no-drag dx-focus-ring-group';
106
106
 
107
107
  const l0ItemContent = 'flex justify-center items-center dx-focus-ring-group-indicator transition-colors rounded-sm';
108
108
 
@@ -119,9 +119,9 @@ const L0ItemRoot = forwardRef<HTMLElement, PropsWithChildren<L0ItemRootProps>>(
119
119
  const handleClick = useL0ItemClick({ item, parent, path: itemPath }, type);
120
120
  const rootProps =
121
121
  type === 'tab'
122
- ? { value: item.id, tabIndex: 0, onClick: handleClick, 'data-testid': testId, 'data-itemid': id }
122
+ ? { value: item.id, tabIndex: 0, onClick: handleClick, 'data-testid': testId, 'data-object-id': id }
123
123
  : type !== 'collection'
124
- ? { onClick: handleClick, 'data-testid': testId, 'data-itemid': id }
124
+ ? { onClick: handleClick, 'data-testid': testId, 'data-object-id': id }
125
125
  : { onClick: handleClick, role: 'button' };
126
126
 
127
127
  return (
@@ -287,7 +287,7 @@ const L0Collection = ({ item, path }: L0ItemProps) => {
287
287
  role='group'
288
288
  className='contents group/l0c'
289
289
  aria-labelledby={`${item.id}__label`}
290
- data-itemid={id}
290
+ data-object-id={id}
291
291
  data-testid={testId}
292
292
  >
293
293
  {collectionItems.map((collectionItem) => (
@@ -127,7 +127,6 @@ const L1PanelHeader = ({ item, path, onBack }: L1PanelProps) => {
127
127
  variant='ghost'
128
128
  icon='ph--arrow-u-down-left--regular'
129
129
  iconOnly
130
- size={5}
131
130
  label={t('button back')}
132
131
  classNames={[hoverableControlItem, hoverableOpenControlItem, 'pointer-fine:pli-1']}
133
132
  onClick={handleBack}
@@ -139,7 +138,6 @@ const L1PanelHeader = ({ item, path, onBack }: L1PanelProps) => {
139
138
  variant='ghost'
140
139
  icon={alternateTree.properties.icon ?? 'ph--placeholder--regular'}
141
140
  iconOnly
142
- size={5}
143
141
  label={toLocalizedString(alternateTree.properties.label ?? alternateTree.id, t)}
144
142
  classNames={[hoverableControlItem, hoverableOpenControlItem, 'pointer-fine:pli-1']}
145
143
  onClick={handleOpen}
@@ -15,7 +15,7 @@ import type { L1PanelProps } from './Sidebar';
15
15
 
16
16
  export type NavTreeContextValue = Pick<
17
17
  TreeProps<NavTreeItemGraphNode, { disposition?: string; sort?: boolean }>,
18
- 'useItems' | 'getProps' | 'isCurrent' | 'isOpen' | 'canDrop' | 'onOpenChange' | 'onSelect'
18
+ 'useItems' | 'getProps' | 'isCurrent' | 'isOpen' | 'blockInstruction' | 'canDrop' | 'onOpenChange' | 'onSelect'
19
19
  > &
20
20
  Pick<L1PanelProps, 'onBack'> & {
21
21
  tab: string;
@@ -7,7 +7,7 @@ import React, { type JSX, type PropsWithChildren, useEffect, useState } from 're
7
7
 
8
8
  import { faker } from '@dxos/random';
9
9
  import { Icon, IconButton } from '@dxos/react-ui';
10
- import { withTheme } from '@dxos/react-ui/testing';
10
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
11
11
  import { mx } from '@dxos/react-ui-theme';
12
12
 
13
13
  import { type ItemMap, Tree, type TreeNodeData, type TreeProps, visitNodes, visitor } from './Tree';
@@ -30,7 +30,7 @@ const Container = ({ children, sidebar }: PropsWithChildren<{ sidebar: JSX.Eleme
30
30
  <div className='flex'>
31
31
  {/* TODO(burdon): Custom thin scrollbar. */}
32
32
  {/* TODO(burdon): Horizontal scrolling within navtree? */}
33
- <div className='flex flex-col overflow-y-auto w-[300px] bg-neutral-100 dark:bg-neutral-950'>{sidebar}</div>
33
+ <div className='flex flex-col overflow-y-auto is-[300px] bg-neutral-100 dark:bg-neutral-950'>{sidebar}</div>
34
34
  <div className='flex flex-col grow overflow-hidden'>{children}</div>
35
35
  </div>
36
36
  );
@@ -189,7 +189,7 @@ const Sidebar = ({ mutate }: { mutate?: boolean }) => {
189
189
  />
190
190
  </div>
191
191
 
192
- <div className='flex items-center my-2 px-2 gap-2'>
192
+ <div className='flex items-center my-2 pli-2 gap-2'>
193
193
  <IconButton icon='ph--plus-circle--regular' iconOnly label='Create space' onClick={handleCreateSpace} />
194
194
  <span className='grow text-sm' onClick={handleCreateSpace}>
195
195
  New space
@@ -203,10 +203,7 @@ const Sidebar = ({ mutate }: { mutate?: boolean }) => {
203
203
  const meta = {
204
204
  title: 'plugins/plugin-navtree/experimental/Tree',
205
205
  component: Tree,
206
- decorators: [withTheme],
207
- parameters: {
208
- layout: 'column',
209
- },
206
+ decorators: [withTheme, withLayout({ container: 'column' })],
210
207
  } satisfies Meta<typeof Tree>;
211
208
 
212
209
  export default meta;
@@ -19,7 +19,7 @@ export const IconButton = ({
19
19
  } & Pick<HTMLAttributes<HTMLDivElement>, 'onClick'>) => {
20
20
  // TODO(burdon): Density aware.
21
21
  return (
22
- <div className={mx('flex w-6 h-6 items-center justify-center select-none', classNames)} onClick={onClick}>
22
+ <div className={mx('flex is-6 bs-6 items-center justify-center select-none', classNames)} onClick={onClick}>
23
23
  <Icon icon={iconName} classNames='cursor-pointer' size={size} />
24
24
  </div>
25
25
  );
@@ -193,7 +193,7 @@ export const TreeNodeRow = (props: TreeNodeProps & { className?: string }) => {
193
193
  <Grid
194
194
  style={{ paddingLeft: `${(depth - 1) * 24}px` }}
195
195
  className={mx(
196
- 'group w-full items-center cursor-pointer bg-hoverSurface',
196
+ 'group is-full items-center cursor-pointer bg-hoverSurface',
197
197
  // TODO(burdon): Use data-active.
198
198
  selected?.[id] && 'bg-activeSurface',
199
199
  className,
package/src/meta.ts CHANGED
@@ -3,10 +3,15 @@
3
3
  //
4
4
 
5
5
  import { type PluginMeta } from '@dxos/app-framework';
6
+ import { trim } from '@dxos/util';
6
7
 
7
8
  export const meta: PluginMeta = {
8
9
  id: 'dxos.org/plugin/navtree',
9
10
  name: 'Navtree',
11
+ description: trim`
12
+ Hierarchical navigation tree for browsing spaces, folders, and objects.
13
+ Provides sidebar navigation with collapsible sections and quick access to workspace content.
14
+ `,
10
15
  };
11
16
 
12
17
  // TODO(wittjosiah): Factor out.
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Rx } from '@effect-rx/rx-react';
5
+ import { Atom } from '@effect-atom/atom-react';
6
6
  import * as Function from 'effect/Function';
7
7
  import * as Option from 'effect/Option';
8
8
 
@@ -28,7 +28,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
28
28
  createExtension({
29
29
  id: 'app-menu',
30
30
  actions: (node) =>
31
- Rx.make((get) =>
31
+ Atom.make((get) =>
32
32
  Function.pipe(
33
33
  get(node),
34
34
  Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
@@ -55,7 +55,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
55
55
  createExtension({
56
56
  id: 'user-account',
57
57
  connector: (node) =>
58
- Rx.make((get) =>
58
+ Atom.make((get) =>
59
59
  Function.pipe(
60
60
  get(node),
61
61
  Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
@@ -112,7 +112,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
112
112
  id: 'spaces-root',
113
113
  position: 'hoist',
114
114
  connector: (node) =>
115
- Rx.make((get) =>
115
+ Atom.make((get) =>
116
116
  Function.pipe(
117
117
  get(node),
118
118
  Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
@@ -138,7 +138,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
138
138
  createExtension({
139
139
  id: 'spaces',
140
140
  connector: (node) => {
141
- const count = Rx.make((get) => {
141
+ const count = Atom.make((get) => {
142
142
  let value = 3;
143
143
  const interval = setInterval(() => {
144
144
  if (value >= 10) {
@@ -153,7 +153,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
153
153
  return value;
154
154
  });
155
155
 
156
- return Rx.make((get) =>
156
+ return Atom.make((get) =>
157
157
  Function.pipe(
158
158
  get(node),
159
159
  Option.flatMap((node) => (node.id === 'spaces-root' ? Option.some(node) : Option.none())),
@@ -179,7 +179,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
179
179
  createExtension({
180
180
  id: 'space-actions',
181
181
  actions: (node) =>
182
- Rx.make((get) =>
182
+ Atom.make((get) =>
183
183
  Function.pipe(
184
184
  get(node),
185
185
  Option.flatMap((node) => (node.type === 'space' ? Option.some(node) : Option.none())),
@@ -205,7 +205,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
205
205
  createExtension({
206
206
  id: 'objects',
207
207
  connector: (node) => {
208
- const count = Rx.make((get) => {
208
+ const count = Atom.make((get) => {
209
209
  let value = 3;
210
210
  const interval = setInterval(() => {
211
211
  if (value >= 20) {
@@ -220,7 +220,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
220
220
  return value;
221
221
  });
222
222
 
223
- return Rx.make((get) =>
223
+ return Atom.make((get) =>
224
224
  Function.pipe(
225
225
  get(node),
226
226
  Option.flatMap((node) => (node.type === 'space' ? Option.some(node) : Option.none())),
@@ -245,7 +245,7 @@ export const storybookGraphBuilders = (context: PluginContext): BuilderExtension
245
245
  createExtension({
246
246
  id: 'object-actions',
247
247
  actions: (node) =>
248
- Rx.make((get) =>
248
+ Atom.make((get) =>
249
249
  Function.pipe(
250
250
  get(node),
251
251
  Option.flatMap((node) => (node.type === 'object' ? Option.some(node) : Option.none())),
@@ -5,8 +5,8 @@
5
5
  import * as Schema from 'effect/Schema';
6
6
 
7
7
  import { type NodeArg } from '@dxos/app-graph';
8
- import { type Live, Obj, Type } from '@dxos/echo';
9
- import { TypedObject } from '@dxos/echo/internal';
8
+ import { Obj, Type } from '@dxos/echo';
9
+ import { type Live } from '@dxos/live-object';
10
10
  import { faker } from '@dxos/random';
11
11
  import { range } from '@dxos/util';
12
12
 
@@ -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.Obj({
68
+ typename: 'example.com/type/Project',
69
+ version: '0.1.0',
70
+ }),
71
+ ),
70
72
 
71
73
  createData: () => ({
72
74
  title: faker.commerce.productName(),