@dxos/plugin-explorer 0.9.1-main.c7dcc2e112 → 0.9.1-staging.ee54ba693a

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 (151) hide show
  1. package/dist/lib/neutral/ExplorerArticle-2WPXYTXV.mjs +101 -0
  2. package/dist/lib/neutral/ExplorerArticle-2WPXYTXV.mjs.map +7 -0
  3. package/dist/lib/neutral/ExplorerPlugin.mjs +1 -1
  4. package/dist/lib/neutral/NeighborhoodCompanion-WC6E3YE6.mjs +90 -0
  5. package/dist/lib/neutral/NeighborhoodCompanion-WC6E3YE6.mjs.map +7 -0
  6. package/dist/lib/neutral/app-graph-builder-L2TJ6GNR.mjs +37 -0
  7. package/dist/lib/neutral/app-graph-builder-L2TJ6GNR.mjs.map +7 -0
  8. package/dist/lib/neutral/capabilities/index.mjs +4 -2
  9. package/dist/lib/neutral/capabilities/index.mjs.map +3 -3
  10. package/dist/lib/neutral/{chunk-JXYIG54N.mjs → chunk-4F6AT7RA.mjs} +4 -2
  11. package/dist/lib/neutral/chunk-4F6AT7RA.mjs.map +7 -0
  12. package/dist/lib/neutral/{chunk-7XUDLV6E.mjs → chunk-EZ52JY7X.mjs} +34 -31
  13. package/dist/lib/neutral/chunk-EZ52JY7X.mjs.map +7 -0
  14. package/dist/lib/neutral/{chunk-YBCHBVCJ.mjs → chunk-TTFPTHAQ.mjs} +8 -8
  15. package/dist/lib/neutral/chunk-TTFPTHAQ.mjs.map +7 -0
  16. package/dist/lib/neutral/components/index.mjs +430 -506
  17. package/dist/lib/neutral/components/index.mjs.map +4 -4
  18. package/dist/lib/neutral/containers/index.mjs +4 -2
  19. package/dist/lib/neutral/containers/index.mjs.map +3 -3
  20. package/dist/lib/neutral/{create-object-F6TKVAGV.mjs → create-object-WKIN3OB6.mjs} +3 -4
  21. package/dist/lib/neutral/{create-object-F6TKVAGV.mjs.map → create-object-WKIN3OB6.mjs.map} +3 -3
  22. package/dist/lib/neutral/hooks/index.mjs +64 -1
  23. package/dist/lib/neutral/hooks/index.mjs.map +4 -4
  24. package/dist/lib/neutral/index.mjs +1 -1
  25. package/dist/lib/neutral/meta.json +1 -1
  26. package/dist/lib/neutral/react-surface-EWPG5PUQ.mjs +39 -0
  27. package/dist/lib/neutral/react-surface-EWPG5PUQ.mjs.map +7 -0
  28. package/dist/lib/neutral/testing/index.mjs +2 -2
  29. package/dist/lib/neutral/testing/index.mjs.map +2 -2
  30. package/dist/lib/neutral/translations.mjs +4 -1
  31. package/dist/lib/neutral/translations.mjs.map +2 -2
  32. package/dist/lib/neutral/types/index.mjs +1 -1
  33. package/dist/types/src/ExplorerPlugin.d.ts.map +1 -1
  34. package/dist/types/src/capabilities/app-graph-builder.d.ts +9 -0
  35. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  36. package/dist/types/src/capabilities/create-object.d.ts +1 -7
  37. package/dist/types/src/capabilities/create-object.d.ts.map +1 -1
  38. package/dist/types/src/capabilities/index.d.ts +1 -0
  39. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  40. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  41. package/dist/types/src/components/Lattice/Lattice.d.ts +1 -1
  42. package/dist/types/src/components/Lattice/Lattice.d.ts.map +1 -1
  43. package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts +1 -1
  44. package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts.map +1 -1
  45. package/dist/types/src/components/Tree/Tree.stories.d.ts +1 -1
  46. package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
  47. package/dist/types/src/components/Tree/index.d.ts +1 -3
  48. package/dist/types/src/components/Tree/index.d.ts.map +1 -1
  49. package/dist/types/src/components/Tree/types/tree.d.ts +10 -27
  50. package/dist/types/src/components/Tree/types/tree.d.ts.map +1 -1
  51. package/dist/types/src/components/Tree/types/types.d.ts +1 -10
  52. package/dist/types/src/components/Tree/types/types.d.ts.map +1 -1
  53. package/dist/types/src/components/Visualization/Visualization.d.ts +39 -0
  54. package/dist/types/src/components/Visualization/Visualization.d.ts.map +1 -0
  55. package/dist/types/src/components/Visualization/Visualization.stories.d.ts +13 -0
  56. package/dist/types/src/components/Visualization/Visualization.stories.d.ts.map +1 -0
  57. package/dist/types/src/components/Visualization/index.d.ts +3 -0
  58. package/dist/types/src/components/Visualization/index.d.ts.map +1 -0
  59. package/dist/types/src/components/Visualization/variants.d.ts +53 -0
  60. package/dist/types/src/components/Visualization/variants.d.ts.map +1 -0
  61. package/dist/types/src/components/index.d.ts +1 -0
  62. package/dist/types/src/components/index.d.ts.map +1 -1
  63. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts +1 -1
  64. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts.map +1 -1
  65. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts +2 -2
  66. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts.map +1 -1
  67. package/dist/types/src/containers/NeighborhoodCompanion/NeighborhoodCompanion.d.ts +14 -0
  68. package/dist/types/src/containers/NeighborhoodCompanion/NeighborhoodCompanion.d.ts.map +1 -0
  69. package/dist/types/src/containers/NeighborhoodCompanion/index.d.ts +2 -0
  70. package/dist/types/src/containers/NeighborhoodCompanion/index.d.ts.map +1 -0
  71. package/dist/types/src/containers/index.d.ts +1 -0
  72. package/dist/types/src/containers/index.d.ts.map +1 -1
  73. package/dist/types/src/hooks/index.d.ts +1 -0
  74. package/dist/types/src/hooks/index.d.ts.map +1 -1
  75. package/dist/types/src/hooks/useNeighborhoodModel.d.ts +14 -0
  76. package/dist/types/src/hooks/useNeighborhoodModel.d.ts.map +1 -0
  77. package/dist/types/src/meta.d.ts +4 -0
  78. package/dist/types/src/meta.d.ts.map +1 -1
  79. package/dist/types/src/testing/relations.d.ts +1 -2
  80. package/dist/types/src/testing/relations.d.ts.map +1 -1
  81. package/dist/types/src/translations.d.ts +6 -0
  82. package/dist/types/src/translations.d.ts.map +1 -1
  83. package/dist/types/src/types/Graph.d.ts +6 -8
  84. package/dist/types/src/types/Graph.d.ts.map +1 -1
  85. package/dist/types/tsconfig.tsbuildinfo +1 -1
  86. package/package.json +41 -37
  87. package/src/ExplorerPlugin.tsx +2 -1
  88. package/src/capabilities/app-graph-builder.ts +40 -0
  89. package/src/capabilities/create-object.ts +3 -2
  90. package/src/capabilities/index.ts +1 -0
  91. package/src/capabilities/react-surface.tsx +14 -4
  92. package/src/components/Lattice/Lattice.tsx +1 -2
  93. package/src/components/Tree/EdgeBundling.stories.tsx +5 -3
  94. package/src/components/Tree/Tree.stories.tsx +7 -2
  95. package/src/components/Tree/index.ts +3 -3
  96. package/src/components/Tree/types/tree.ts +6 -6
  97. package/src/components/Tree/types/types.ts +1 -11
  98. package/src/components/Visualization/Visualization.stories.tsx +104 -0
  99. package/src/components/Visualization/Visualization.tsx +209 -0
  100. package/src/components/Visualization/index.ts +6 -0
  101. package/src/components/Visualization/variants.ts +508 -0
  102. package/src/components/index.ts +1 -0
  103. package/src/containers/ExplorerArticle/ExplorerArticle.stories.tsx +3 -3
  104. package/src/containers/ExplorerArticle/ExplorerArticle.tsx +7 -8
  105. package/src/containers/NeighborhoodCompanion/NeighborhoodCompanion.tsx +102 -0
  106. package/src/containers/NeighborhoodCompanion/index.ts +5 -0
  107. package/src/containers/index.ts +1 -0
  108. package/src/hooks/index.ts +1 -0
  109. package/src/hooks/useNeighborhoodModel.ts +81 -0
  110. package/src/testing/relations.ts +1 -3
  111. package/src/translations.ts +3 -0
  112. package/src/types/Graph.ts +18 -20
  113. package/dist/lib/neutral/ExplorerArticle-MHEINWUL.mjs +0 -460
  114. package/dist/lib/neutral/ExplorerArticle-MHEINWUL.mjs.map +0 -7
  115. package/dist/lib/neutral/chunk-7XUDLV6E.mjs.map +0 -7
  116. package/dist/lib/neutral/chunk-IKHJV3Q4.mjs +0 -20
  117. package/dist/lib/neutral/chunk-IKHJV3Q4.mjs.map +0 -7
  118. package/dist/lib/neutral/chunk-JXYIG54N.mjs.map +0 -7
  119. package/dist/lib/neutral/chunk-YBCHBVCJ.mjs.map +0 -7
  120. package/dist/lib/neutral/react-surface-APBW2VQG.mjs +0 -26
  121. package/dist/lib/neutral/react-surface-APBW2VQG.mjs.map +0 -7
  122. package/dist/types/src/components/Tree/Tree.d.ts +0 -24
  123. package/dist/types/src/components/Tree/Tree.d.ts.map +0 -1
  124. package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts +0 -40
  125. package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts.map +0 -1
  126. package/dist/types/src/components/Tree/layout/RadialTree.d.ts +0 -37
  127. package/dist/types/src/components/Tree/layout/RadialTree.d.ts.map +0 -1
  128. package/dist/types/src/components/Tree/layout/TidyTree.d.ts +0 -26
  129. package/dist/types/src/components/Tree/layout/TidyTree.d.ts.map +0 -1
  130. package/dist/types/src/components/Tree/layout/hierarchy.d.ts +0 -17
  131. package/dist/types/src/components/Tree/layout/hierarchy.d.ts.map +0 -1
  132. package/dist/types/src/components/Tree/layout/index.d.ts +0 -6
  133. package/dist/types/src/components/Tree/layout/index.d.ts.map +0 -1
  134. package/dist/types/src/components/Tree/layout/slots.d.ts +0 -7
  135. package/dist/types/src/components/Tree/layout/slots.d.ts.map +0 -1
  136. package/dist/types/src/components/Tree/layout/useContainerSize.d.ts +0 -15
  137. package/dist/types/src/components/Tree/layout/useContainerSize.d.ts.map +0 -1
  138. package/dist/types/src/containers/ExplorerArticle/Visualization.d.ts +0 -18
  139. package/dist/types/src/containers/ExplorerArticle/Visualization.d.ts.map +0 -1
  140. package/dist/types/src/containers/ExplorerArticle/variants.d.ts +0 -9
  141. package/dist/types/src/containers/ExplorerArticle/variants.d.ts.map +0 -1
  142. package/src/components/Tree/Tree.tsx +0 -81
  143. package/src/components/Tree/layout/HierarchicalEdgeBundling.tsx +0 -335
  144. package/src/components/Tree/layout/RadialTree.tsx +0 -242
  145. package/src/components/Tree/layout/TidyTree.tsx +0 -246
  146. package/src/components/Tree/layout/hierarchy.ts +0 -32
  147. package/src/components/Tree/layout/index.ts +0 -9
  148. package/src/components/Tree/layout/slots.ts +0 -19
  149. package/src/components/Tree/layout/useContainerSize.ts +0 -43
  150. package/src/containers/ExplorerArticle/Visualization.tsx +0 -523
  151. package/src/containers/ExplorerArticle/variants.ts +0 -47
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-explorer",
3
- "version": "0.9.1-main.c7dcc2e112",
3
+ "version": "0.9.1-staging.ee54ba693a",
4
4
  "description": "Braneframe data visualization plugin",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -97,57 +97,61 @@
97
97
  "dependencies": {
98
98
  "@effect-atom/atom-react": "^0.5.0",
99
99
  "@observablehq/plot": "^0.6.11",
100
+ "@radix-ui/react-context": "1.1.1",
101
+ "@radix-ui/react-slot": "1.1.2",
100
102
  "d3": "^7.9.0",
101
- "effect": "3.21.3",
103
+ "effect": "3.21.4",
102
104
  "force-graph": "^1.49.4",
103
105
  "react-resize-detector": "^11.0.1",
104
106
  "topojson-client": "^3.1.0",
105
- "@dxos/app-toolkit": "0.9.1-main.c7dcc2e112",
106
- "@dxos/client": "0.9.1-main.c7dcc2e112",
107
- "@dxos/app-framework": "0.9.1-main.c7dcc2e112",
108
- "@dxos/compute": "0.9.1-main.c7dcc2e112",
109
- "@dxos/echo": "0.9.1-main.c7dcc2e112",
110
- "@dxos/echo-query": "0.9.1-main.c7dcc2e112",
111
- "@dxos/graph": "0.9.1-main.c7dcc2e112",
112
- "@dxos/invariant": "0.9.1-main.c7dcc2e112",
113
- "@dxos/keys": "0.9.1-main.c7dcc2e112",
114
- "@dxos/log": "0.9.1-main.c7dcc2e112",
115
- "@dxos/plugin-space": "0.9.1-main.c7dcc2e112",
116
- "@dxos/react-client": "0.9.1-main.c7dcc2e112",
117
- "@dxos/react-ui-graph": "0.9.1-main.c7dcc2e112",
118
- "@dxos/react-ui-components": "0.9.1-main.c7dcc2e112",
119
- "@dxos/react-ui-mosaic": "0.9.1-main.c7dcc2e112",
120
- "@dxos/types": "0.9.1-main.c7dcc2e112",
121
- "@dxos/react-ui-stack": "0.9.1-main.c7dcc2e112",
122
- "@dxos/schema": "0.9.1-main.c7dcc2e112",
123
- "@dxos/util": "0.9.1-main.c7dcc2e112",
124
- "@dxos/plugin-client": "0.9.1-main.c7dcc2e112"
107
+ "@dxos/app-toolkit": "0.9.1-staging.ee54ba693a",
108
+ "@dxos/app-framework": "0.9.1-staging.ee54ba693a",
109
+ "@dxos/client": "0.9.1-staging.ee54ba693a",
110
+ "@dxos/echo": "0.9.1-staging.ee54ba693a",
111
+ "@dxos/echo-query": "0.9.1-staging.ee54ba693a",
112
+ "@dxos/graph": "0.9.1-staging.ee54ba693a",
113
+ "@dxos/invariant": "0.9.1-staging.ee54ba693a",
114
+ "@dxos/log": "0.9.1-staging.ee54ba693a",
115
+ "@dxos/compute": "0.9.1-staging.ee54ba693a",
116
+ "@dxos/keys": "0.9.1-staging.ee54ba693a",
117
+ "@dxos/plugin-client": "0.9.1-staging.ee54ba693a",
118
+ "@dxos/plugin-graph": "0.9.1-staging.ee54ba693a",
119
+ "@dxos/react-client": "0.9.1-staging.ee54ba693a",
120
+ "@dxos/plugin-space": "0.9.1-staging.ee54ba693a",
121
+ "@dxos/react-ui-graph": "0.9.1-staging.ee54ba693a",
122
+ "@dxos/react-ui-attention": "0.9.1-staging.ee54ba693a",
123
+ "@dxos/react-ui-mosaic": "0.9.1-staging.ee54ba693a",
124
+ "@dxos/types": "0.9.1-staging.ee54ba693a",
125
+ "@dxos/ui-types": "0.9.1-staging.ee54ba693a",
126
+ "@dxos/schema": "0.9.1-staging.ee54ba693a",
127
+ "@dxos/util": "0.9.1-staging.ee54ba693a",
128
+ "@dxos/react-ui-components": "0.9.1-staging.ee54ba693a"
125
129
  },
126
130
  "devDependencies": {
127
131
  "@types/d3": "^7.4.3",
128
132
  "@types/d3-hierarchy": "^3.1.6",
129
133
  "@types/lodash.defaultsdeep": "^4.6.6",
130
- "@types/react": "~19.2.7",
134
+ "@types/react": "~19.2.17",
131
135
  "@types/react-dom": "~19.2.3",
132
136
  "@types/topojson-client": "^3.1.4",
133
137
  "@types/topojson-specification": "^1.0.5",
134
- "react": "~19.2.3",
135
- "react-dom": "~19.2.3",
138
+ "react": "~19.2.7",
139
+ "react-dom": "~19.2.7",
136
140
  "vite": "^8.0.16",
137
- "@dxos/echo-generator": "0.9.1-main.c7dcc2e112",
138
- "@dxos/plugin-preview": "0.9.1-main.c7dcc2e112",
139
- "@dxos/plugin-testing": "0.9.1-main.c7dcc2e112",
140
- "@dxos/react-ui": "0.9.1-main.c7dcc2e112",
141
- "@dxos/random": "0.9.1-main.c7dcc2e112",
142
- "@dxos/ui-theme": "0.9.1-main.c7dcc2e112",
143
- "@dxos/storybook-utils": "0.9.1-main.c7dcc2e112"
141
+ "@dxos/echo-generator": "0.9.1-staging.ee54ba693a",
142
+ "@dxos/plugin-preview": "0.9.1-staging.ee54ba693a",
143
+ "@dxos/plugin-testing": "0.9.1-staging.ee54ba693a",
144
+ "@dxos/storybook-utils": "0.9.1-staging.ee54ba693a",
145
+ "@dxos/ui-theme": "0.9.1-staging.ee54ba693a",
146
+ "@dxos/random": "0.9.1-staging.ee54ba693a",
147
+ "@dxos/react-ui": "0.9.1-staging.ee54ba693a"
144
148
  },
145
149
  "peerDependencies": {
146
- "effect": "3.21.3",
147
- "react": "~19.2.3",
148
- "react-dom": "~19.2.3",
149
- "@dxos/react-ui": "0.9.1-main.c7dcc2e112",
150
- "@dxos/ui-theme": "0.9.1-main.c7dcc2e112"
150
+ "effect": "3.21.4",
151
+ "react": "~19.2.7",
152
+ "react-dom": "~19.2.7",
153
+ "@dxos/react-ui": "0.9.1-staging.ee54ba693a",
154
+ "@dxos/ui-theme": "0.9.1-staging.ee54ba693a"
151
155
  },
152
156
  "publishConfig": {
153
157
  "access": "public"
@@ -5,7 +5,7 @@
5
5
  import { Plugin } from '@dxos/app-framework';
6
6
  import { AppPlugin } from '@dxos/app-toolkit';
7
7
 
8
- import { CreateObject, ReactSurface } from '#capabilities';
8
+ import { AppGraphBuilder, CreateObject, ReactSurface } from '#capabilities';
9
9
  import { meta } from '#meta';
10
10
  import { translations } from '#translations';
11
11
  import { Graph } from '#types';
@@ -15,6 +15,7 @@ import pluginSpec from '../PLUGIN.mdl?raw';
15
15
 
16
16
  export const ExplorerPlugin = Plugin.define(meta).pipe(
17
17
  AppPlugin.addCreateObjectModule({ activate: CreateObject }),
18
+ AppPlugin.addAppGraphModule({ activate: AppGraphBuilder }),
18
19
  AppPlugin.addSchemaModule({ schema: [Graph.Graph] }),
19
20
  AppPlugin.addSurfaceModule({ activate: ReactSurface }),
20
21
  AppPlugin.addTranslationsModule({ translations }),
@@ -0,0 +1,40 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capability } from '@dxos/app-framework';
8
+ import { AppCapabilities, AppNode } from '@dxos/app-toolkit';
9
+ import { GraphBuilder, NodeMatcher } from '@dxos/plugin-graph';
10
+ import { linkedSegment } from '@dxos/react-ui-attention';
11
+ import { Position } from '@dxos/util';
12
+
13
+ import { meta } from '#meta';
14
+
15
+ /**
16
+ * Offers a "Neighborhood" companion on any ECHO object. The matched node is passed through as the
17
+ * companion's `companionTo` (the active node), which the surface renders as an ego-centric graph.
18
+ */
19
+ export default Capability.makeModule(
20
+ Effect.fnUntraced(function* () {
21
+ const extensions = yield* Effect.all([
22
+ GraphBuilder.createExtension({
23
+ id: 'neighborhoodCompanion',
24
+ match: NodeMatcher.whenEchoObjectMatches,
25
+ connector: () =>
26
+ Effect.succeed([
27
+ AppNode.makeCompanion({
28
+ id: linkedSegment('neighborhood'),
29
+ label: ['neighborhood-companion.label', { ns: meta.profile.key }],
30
+ icon: 'ph--share-network--regular',
31
+ data: 'neighborhood',
32
+ position: Position.last,
33
+ }),
34
+ ]),
35
+ }),
36
+ ]);
37
+
38
+ return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);
39
+ }),
40
+ );
@@ -21,13 +21,14 @@ export default Capability.makeModule(
21
21
  createObject: (props, options) =>
22
22
  Effect.gen(function* () {
23
23
  const object = yield* Effect.promise(async () => {
24
- const { view } = await ViewModel.makeFromDatabase({ db: options.db, typename: props.typename });
24
+ const view = props.typename
25
+ ? (await ViewModel.makeFromDatabase({ db: options.db, typename: props.typename })).view
26
+ : undefined;
25
27
  return Graph.make({ name: props.name, view });
26
28
  });
27
29
  return yield* Operation.invoke(SpaceOperation.AddObject, {
28
30
  object,
29
31
  target: options.target,
30
- hidden: true,
31
32
  targetNodeId: options.targetNodeId,
32
33
  });
33
34
  }),
@@ -4,5 +4,6 @@
4
4
 
5
5
  import { Capability } from '@dxos/app-framework';
6
6
 
7
+ export const AppGraphBuilder = Capability.lazy('AppGraphBuilder', () => import('./app-graph-builder'));
7
8
  export const CreateObject = Capability.lazy('CreateObject', () => import('./create-object'));
8
9
  export const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));
@@ -9,13 +9,12 @@ import { Capabilities, Capability } from '@dxos/app-framework';
9
9
  import { Surface } from '@dxos/app-framework/ui';
10
10
  import { AppSurface } from '@dxos/app-toolkit/ui';
11
11
 
12
- import { ExplorerArticle } from '#containers';
12
+ import { ExplorerArticle, NeighborhoodCompanion } from '#containers';
13
13
  import { Graph } from '#types';
14
14
 
15
15
  export default Capability.makeModule(() =>
16
16
  Effect.succeed(
17
- Capability.contributes(
18
- Capabilities.ReactSurface,
17
+ Capability.contributes(Capabilities.ReactSurface, [
19
18
  Surface.create({
20
19
  id: 'article',
21
20
  // TODO(wittjosiah): Split into multiple surfaces if this filter proves too strict for non-article roles.
@@ -27,6 +26,17 @@ export default Capability.makeModule(() =>
27
26
  return <ExplorerArticle role={role} subject={data.subject} attendableId={data.attendableId} />;
28
27
  },
29
28
  }),
30
- ),
29
+ // Neighborhood companion offered on any ECHO object; `companionTo` is the active node.
30
+ Surface.create({
31
+ id: 'neighborhood',
32
+ filter: AppSurface.allOf(
33
+ AppSurface.literal(AppSurface.Article, 'neighborhood'),
34
+ AppSurface.companion(AppSurface.Article),
35
+ ),
36
+ component: ({ data, role }) => {
37
+ return <NeighborhoodCompanion role={role} subject={data.companionTo} />;
38
+ },
39
+ }),
40
+ ]),
31
41
  ),
32
42
  );
@@ -6,11 +6,10 @@ import { select } from 'd3';
6
6
  import React, { useEffect, useMemo, useRef } from 'react';
7
7
 
8
8
  import { Obj } from '@dxos/echo';
9
+ import { type TreeNode, useContainerSize } from '@dxos/react-ui-graph';
9
10
  import { type SpaceGraphNode } from '@dxos/schema';
10
11
 
11
12
  import { getNodeFillForObject } from '../../util/node-color';
12
- import { useContainerSize } from '../Tree/layout/useContainerSize';
13
- import { type TreeNode } from '../Tree/types';
14
13
 
15
14
  const TRANSITION_MS = 350;
16
15
 
@@ -7,18 +7,18 @@ import * as Effect from 'effect/Effect';
7
7
  import React, { useEffect, useMemo, useState } from 'react';
8
8
 
9
9
  import { withPluginManager } from '@dxos/app-framework/testing';
10
- import { Query } from '@dxos/echo';
10
+ import { type Obj, Query } from '@dxos/echo';
11
11
  import { ClientPlugin, initializeIdentity } from '@dxos/plugin-client/testing';
12
12
  import { corePlugins } from '@dxos/plugin-testing';
13
13
  import { random } from '@dxos/random';
14
14
  import { useSpaces } from '@dxos/react-client/echo';
15
+ import { Tree, type TreeComponentProps, type TreeNode } from '@dxos/react-ui-graph';
15
16
  import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
16
17
  import { type ValueGenerator } from '@dxos/schema/testing';
17
18
  import { HasConnection, Organization, Person } from '@dxos/types';
18
19
 
19
20
  import { buildOrgHierarchy, connectionsToEdges, generateConnectedOrgs } from '../../testing';
20
- import { Tree, type TreeComponentProps } from './Tree';
21
- import { type TreeNode } from './types';
21
+ import { getNodeFillForObject } from '../../util';
22
22
 
23
23
  const generator = random as any as ValueGenerator;
24
24
 
@@ -61,6 +61,8 @@ const DefaultStory = ({ variant = 'edge', tension }: { variant?: TreeComponentPr
61
61
  node: 'fill-neutral-700 dark:fill-neutral-300',
62
62
  path: 'stroke-orange-400/40 dark:stroke-orange-500/40',
63
63
  text: 'fill-neutral-700 dark:fill-neutral-200 text-xs',
64
+ // Boundary cast: the generic node `data` is an ECHO object here (carried opaquely by the renderer).
65
+ nodeFill: (data: unknown) => getNodeFillForObject(data as Obj.Unknown | undefined),
64
66
  }),
65
67
  [],
66
68
  );
@@ -5,11 +5,13 @@
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React, { useMemo } from 'react';
7
7
 
8
+ import { type Obj } from '@dxos/echo';
8
9
  import { random } from '@dxos/random';
10
+ import { Tree, type TreeComponentProps } from '@dxos/react-ui-graph';
9
11
  import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
10
12
 
11
13
  import { createTree } from '../../testing';
12
- import { Tree, type TreeComponentProps } from './Tree';
14
+ import { getNodeFillForObject } from '../../util';
13
15
  import { treeTypeToTreeNode } from './types';
14
16
 
15
17
  random.seed(1);
@@ -22,7 +24,10 @@ const DefaultStory = ({ variant }: StoryArgs) => {
22
24
  return <Loading />;
23
25
  }
24
26
 
25
- return <Tree data={data} variant={variant} />;
27
+ // Inject the ECHO-aware leaf fill (radial/edge variants) now that the renderer is domain-agnostic.
28
+ // Boundary cast: the generic node `data` is an ECHO object here (the renderer carries it opaquely).
29
+ const slots = { nodeFill: (data: unknown) => getNodeFillForObject(data as Obj.Unknown | undefined) };
30
+ return <Tree data={data} variant={variant} slots={slots} />;
26
31
  };
27
32
 
28
33
  const meta: Meta<StoryArgs> = {
@@ -2,6 +2,6 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- export * from './Tree';
6
- export * from './layout';
7
- export { type TreeNode, treeTypeToTreeNode } from './types';
5
+ // The Tree renderer + layouts moved to @dxos/react-ui-graph; this keeps the ECHO `TreeType` schema
6
+ // and the `treeTypeToTreeNode` converter that adapt plugin-explorer data to the renderer.
7
+ export * from './types';
@@ -19,12 +19,12 @@ export const TreeNodeType = Schema.Struct({
19
19
 
20
20
  export type TreeNodeType = Schema.Schema.Type<typeof TreeNodeType>;
21
21
 
22
- export const TreeType = Schema.Struct({
23
- root: Key.EntityId,
24
- nodes: Schema.mutable(Schema.Record({ key: Key.EntityId, value: TreeNodeType })),
25
- }).pipe(Type.makeObject(DXN.make('org.dxos.type.tree', '0.1.0')));
26
-
27
- export type TreeType = Type.InstanceType<typeof TreeType>;
22
+ export class TreeType extends Type.makeObject<TreeType>(DXN.make('org.dxos.type.tree', '0.1.0'))(
23
+ Schema.Struct({
24
+ root: Key.EntityId,
25
+ nodes: Schema.mutable(Schema.Record({ key: Key.EntityId, value: TreeNodeType })),
26
+ }),
27
+ ) {}
28
28
 
29
29
  /**
30
30
  * Wrapper object for tree.
@@ -3,20 +3,10 @@
3
3
  //
4
4
 
5
5
  import { type Key } from '@dxos/echo';
6
+ import { type TreeNode } from '@dxos/react-ui-graph';
6
7
 
7
8
  import { type TreeType } from './tree';
8
9
 
9
- /**
10
- * In-memory tree shape used by the d3 layouts.
11
- * `data` carries through to layout callbacks (e.g. hover/inspect) — typically an ECHO object on leaves.
12
- */
13
- export type TreeNode<TData = unknown> = {
14
- id: string;
15
- label?: string;
16
- data?: TData;
17
- children?: TreeNode<TData>[];
18
- };
19
-
20
10
  /**
21
11
  * Convert an ECHO `TreeType` (id-keyed node map) into a nested `TreeNode` hierarchy.
22
12
  * Returns `undefined` if the root id is missing — the tree is then incomplete and shouldn't render.
@@ -0,0 +1,104 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { Registry } from '@effect-atom/atom-react';
6
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
7
+ import React, { useMemo } from 'react';
8
+
9
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
10
+ import { type SpaceGraphEdge, SpaceGraphModel, type SpaceGraphNode } from '@dxos/schema';
11
+ import '@dxos/react-ui-graph/styles/graph.css';
12
+
13
+ import { type VisualizationVariantId } from './variants';
14
+ import { Visualization } from './Visualization';
15
+
16
+ // Synthetic neighbourhood: inbound sources → focus (left), focus → near → far (right, outgoing).
17
+ const NODES: SpaceGraphNode[] = [
18
+ { id: 'focus', type: 'object', data: { label: 'Focus' } },
19
+ ...Array.from(
20
+ { length: 3 },
21
+ (_, index): SpaceGraphNode => ({
22
+ id: `src-${index}`,
23
+ type: 'object',
24
+ data: { label: `Source ${index}` },
25
+ }),
26
+ ),
27
+ ...Array.from(
28
+ { length: 5 },
29
+ (_, index): SpaceGraphNode => ({
30
+ id: `near-${index}`,
31
+ type: 'object',
32
+ data: { label: `Near ${index}` },
33
+ }),
34
+ ),
35
+ ...Array.from(
36
+ { length: 8 },
37
+ (_, index): SpaceGraphNode => ({
38
+ id: `far-${index}`,
39
+ type: 'object',
40
+ data: { label: `Far ${index}` },
41
+ }),
42
+ ),
43
+ ];
44
+
45
+ const EDGES: SpaceGraphEdge[] = [
46
+ // Inbound: sources point at the focus (left side, terminal).
47
+ ...Array.from(
48
+ { length: 3 },
49
+ (_, index): SpaceGraphEdge => ({
50
+ id: `e-src-focus-${index}`,
51
+ type: 'ref',
52
+ source: `src-${index}`,
53
+ target: 'focus',
54
+ data: { force: true },
55
+ }),
56
+ ),
57
+ // Outgoing: focus → near → far (right side, explored).
58
+ ...Array.from(
59
+ { length: 5 },
60
+ (_, index): SpaceGraphEdge => ({
61
+ id: `e-focus-near-${index}`,
62
+ type: 'ref',
63
+ source: 'focus',
64
+ target: `near-${index}`,
65
+ data: { force: true },
66
+ }),
67
+ ),
68
+ ...Array.from(
69
+ { length: 8 },
70
+ (_, index): SpaceGraphEdge => ({
71
+ id: `e-near-far-${index}`,
72
+ type: 'ref',
73
+ source: `near-${index % 5}`,
74
+ target: `far-${index}`,
75
+ data: { force: true },
76
+ }),
77
+ ),
78
+ ];
79
+
80
+ type StoryArgs = { variant: VisualizationVariantId; focus?: string };
81
+
82
+ const DefaultStory = ({ variant, focus }: StoryArgs) => {
83
+ const model = useMemo(() => new SpaceGraphModel(Registry.make(), { nodes: NODES, edges: EDGES }), []);
84
+ return (
85
+ <Visualization.Root classNames='bg-base-surface' model={model} variant={variant} focus={focus}>
86
+ <Visualization.Graph debug={false} />
87
+ </Visualization.Root>
88
+ );
89
+ };
90
+
91
+ const meta: Meta<StoryArgs> = {
92
+ title: 'plugins/plugin-explorer/components/Visualization',
93
+ render: DefaultStory,
94
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
95
+ parameters: { layout: 'fullscreen' },
96
+ };
97
+
98
+ export default meta;
99
+
100
+ type Story = StoryObj<typeof meta>;
101
+
102
+ export const Force: Story = { args: { variant: 'force' } };
103
+
104
+ export const Neighborhood: Story = { args: { variant: 'neighborhood', focus: 'focus' } };