@dxos/plugin-explorer 0.8.4-main.7996785055 → 0.8.4-main.8baae0fced

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 (251) hide show
  1. package/LICENSE +102 -5
  2. package/dist/lib/neutral/ExplorerArticle-EAKRB55W.mjs +277 -0
  3. package/dist/lib/neutral/ExplorerArticle-EAKRB55W.mjs.map +7 -0
  4. package/dist/lib/neutral/ExplorerPlugin.mjs +10 -0
  5. package/dist/lib/neutral/capabilities/index.mjs +11 -0
  6. package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
  7. package/dist/lib/{browser/chunk-6KEHUEEZ.mjs → neutral/chunk-7SPMPHRS.mjs} +6 -5
  8. package/dist/lib/neutral/chunk-7SPMPHRS.mjs.map +7 -0
  9. package/dist/lib/{browser/chunk-LSUP47BZ.mjs → neutral/chunk-DXIWQFYO.mjs} +2 -4
  10. package/dist/lib/neutral/chunk-DXIWQFYO.mjs.map +7 -0
  11. package/dist/lib/neutral/chunk-EM2BV4PF.mjs +290 -0
  12. package/dist/lib/neutral/chunk-EM2BV4PF.mjs.map +7 -0
  13. package/dist/lib/neutral/chunk-GRJXLL4Z.mjs +25 -0
  14. package/dist/lib/neutral/chunk-GRJXLL4Z.mjs.map +7 -0
  15. package/dist/lib/neutral/chunk-V2OFO6PI.mjs +14 -0
  16. package/dist/lib/neutral/chunk-V2OFO6PI.mjs.map +7 -0
  17. package/dist/lib/{browser/chunk-56VV76WZ.mjs → neutral/components/index.mjs} +706 -356
  18. package/dist/lib/neutral/components/index.mjs.map +7 -0
  19. package/dist/lib/neutral/containers/index.mjs +9 -0
  20. package/dist/lib/neutral/containers/index.mjs.map +7 -0
  21. package/dist/lib/neutral/create-object-F6TKVAGV.mjs +39 -0
  22. package/dist/lib/neutral/create-object-F6TKVAGV.mjs.map +7 -0
  23. package/dist/lib/neutral/hooks/index.mjs +45 -0
  24. package/dist/lib/neutral/hooks/index.mjs.map +7 -0
  25. package/dist/lib/neutral/index.mjs +14 -0
  26. package/dist/lib/neutral/meta.json +1 -0
  27. package/dist/lib/{browser → neutral}/meta.mjs +1 -1
  28. package/dist/lib/neutral/plugin.mjs +12 -0
  29. package/dist/lib/neutral/plugin.mjs.map +7 -0
  30. package/dist/lib/neutral/react-surface-APBW2VQG.mjs +26 -0
  31. package/dist/lib/neutral/react-surface-APBW2VQG.mjs.map +7 -0
  32. package/dist/lib/neutral/testing/index.mjs +193 -0
  33. package/dist/lib/neutral/testing/index.mjs.map +7 -0
  34. package/dist/lib/neutral/translations.mjs +33 -0
  35. package/dist/lib/neutral/translations.mjs.map +7 -0
  36. package/dist/lib/{browser → neutral}/types/index.mjs +1 -1
  37. package/dist/types/data/cities.d.ts +4 -4
  38. package/dist/types/data/cities.d.ts.map +1 -1
  39. package/dist/types/data/countries-110m.d.ts +19 -22
  40. package/dist/types/data/countries-110m.d.ts.map +1 -1
  41. package/dist/types/src/ExplorerPlugin.d.ts +1 -0
  42. package/dist/types/src/ExplorerPlugin.d.ts.map +1 -1
  43. package/dist/types/src/ExplorerPlugin.test.d.ts +2 -0
  44. package/dist/types/src/ExplorerPlugin.test.d.ts.map +1 -0
  45. package/dist/types/src/capabilities/create-object.d.ts +11 -0
  46. package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
  47. package/dist/types/src/capabilities/index.d.ts +8 -1
  48. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  49. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  50. package/dist/types/src/components/Chart/Chart.d.ts +1 -1
  51. package/dist/types/src/components/Chart/Chart.d.ts.map +1 -1
  52. package/dist/types/src/components/Chart/Chart.stories.d.ts +4 -1
  53. package/dist/types/src/components/Chart/Chart.stories.d.ts.map +1 -1
  54. package/dist/types/src/components/Globe/Globe.d.ts +1 -1
  55. package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
  56. package/dist/types/src/components/Globe/Globe.stories.d.ts +5 -2
  57. package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
  58. package/dist/types/src/components/Graph/CanvasForceGraph.d.ts +13 -0
  59. package/dist/types/src/components/Graph/CanvasForceGraph.d.ts.map +1 -0
  60. package/dist/types/src/components/Graph/{D3ForceGraph.stories.d.ts → CanvasForceGraph.stories.d.ts} +3 -7
  61. package/dist/types/src/components/Graph/CanvasForceGraph.stories.d.ts.map +1 -0
  62. package/dist/types/src/components/Graph/ForceGraph.d.ts +12 -5
  63. package/dist/types/src/components/Graph/ForceGraph.d.ts.map +1 -1
  64. package/dist/types/src/components/Graph/ForceGraph.stories.d.ts +3 -1
  65. package/dist/types/src/components/Graph/ForceGraph.stories.d.ts.map +1 -1
  66. package/dist/types/src/components/Graph/{adapter.d.ts → graph-adapter.d.ts} +1 -1
  67. package/dist/types/src/components/Graph/graph-adapter.d.ts.map +1 -0
  68. package/dist/types/src/components/Graph/index.d.ts +1 -1
  69. package/dist/types/src/components/Graph/index.d.ts.map +1 -1
  70. package/dist/types/src/components/Lattice/Lattice.d.ts +20 -0
  71. package/dist/types/src/components/Lattice/Lattice.d.ts.map +1 -0
  72. package/dist/types/src/components/Lattice/Lattice.stories.d.ts +8 -0
  73. package/dist/types/src/components/Lattice/Lattice.stories.d.ts.map +1 -0
  74. package/dist/types/src/components/Lattice/index.d.ts +2 -0
  75. package/dist/types/src/components/Lattice/index.d.ts.map +1 -0
  76. package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts +21 -0
  77. package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts.map +1 -0
  78. package/dist/types/src/components/Tree/Tree.d.ts +20 -23
  79. package/dist/types/src/components/Tree/Tree.d.ts.map +1 -1
  80. package/dist/types/src/components/Tree/Tree.stories.d.ts +5 -12
  81. package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
  82. package/dist/types/src/components/Tree/index.d.ts +2 -0
  83. package/dist/types/src/components/Tree/index.d.ts.map +1 -1
  84. package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts +37 -2
  85. package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts.map +1 -1
  86. package/dist/types/src/components/Tree/layout/RadialTree.d.ts +35 -2
  87. package/dist/types/src/components/Tree/layout/RadialTree.d.ts.map +1 -1
  88. package/dist/types/src/components/Tree/layout/TidyTree.d.ts +24 -2
  89. package/dist/types/src/components/Tree/layout/TidyTree.d.ts.map +1 -1
  90. package/dist/types/src/components/Tree/layout/hierarchy.d.ts +17 -0
  91. package/dist/types/src/components/Tree/layout/hierarchy.d.ts.map +1 -0
  92. package/dist/types/src/components/Tree/layout/index.d.ts +5 -4
  93. package/dist/types/src/components/Tree/layout/index.d.ts.map +1 -1
  94. package/dist/types/src/components/Tree/layout/slots.d.ts +7 -0
  95. package/dist/types/src/components/Tree/layout/slots.d.ts.map +1 -0
  96. package/dist/types/src/components/Tree/layout/useContainerSize.d.ts +15 -0
  97. package/dist/types/src/components/Tree/layout/useContainerSize.d.ts.map +1 -0
  98. package/dist/types/src/components/Tree/types/tree.d.ts +6 -6
  99. package/dist/types/src/components/Tree/types/tree.d.ts.map +1 -1
  100. package/dist/types/src/components/Tree/types/types.d.ts +14 -4
  101. package/dist/types/src/components/Tree/types/types.d.ts.map +1 -1
  102. package/dist/types/src/components/index.d.ts +1 -0
  103. package/dist/types/src/components/index.d.ts.map +1 -1
  104. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts +9 -0
  105. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts.map +1 -0
  106. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts +29 -0
  107. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts.map +1 -0
  108. package/dist/types/src/containers/ExplorerArticle/experimental.stories.d.ts +7 -0
  109. package/dist/types/src/containers/ExplorerArticle/experimental.stories.d.ts.map +1 -0
  110. package/dist/types/src/containers/ExplorerArticle/index.d.ts +2 -0
  111. package/dist/types/src/containers/ExplorerArticle/index.d.ts.map +1 -0
  112. package/dist/types/src/containers/index.d.ts +1 -1
  113. package/dist/types/src/containers/index.d.ts.map +1 -1
  114. package/dist/types/src/hooks/useGraphModel.d.ts +2 -2
  115. package/dist/types/src/hooks/useGraphModel.d.ts.map +1 -1
  116. package/dist/types/src/index.d.ts +1 -3
  117. package/dist/types/src/index.d.ts.map +1 -1
  118. package/dist/types/src/plugin.d.ts +3 -0
  119. package/dist/types/src/plugin.d.ts.map +1 -0
  120. package/dist/types/src/{components/Tree/testing → testing}/generator.d.ts +1 -1
  121. package/dist/types/src/testing/generator.d.ts.map +1 -0
  122. package/dist/types/src/testing/index.d.ts +4 -0
  123. package/dist/types/src/testing/index.d.ts.map +1 -0
  124. package/dist/types/src/testing/relations.d.ts +47 -0
  125. package/dist/types/src/testing/relations.d.ts.map +1 -0
  126. package/dist/types/src/translations.d.ts +28 -28
  127. package/dist/types/src/translations.d.ts.map +1 -1
  128. package/dist/types/src/types/Graph.d.ts +3 -4
  129. package/dist/types/src/types/Graph.d.ts.map +1 -1
  130. package/dist/types/src/util/index.d.ts +3 -0
  131. package/dist/types/src/util/index.d.ts.map +1 -0
  132. package/dist/types/src/util/node-color.d.ts +13 -0
  133. package/dist/types/src/util/node-color.d.ts.map +1 -0
  134. package/dist/types/src/{components → util}/plot.d.ts +1 -1
  135. package/dist/types/src/util/plot.d.ts.map +1 -0
  136. package/dist/types/tsconfig.tsbuildinfo +1 -1
  137. package/package.json +102 -56
  138. package/src/ExplorerPlugin.test.ts +26 -0
  139. package/src/ExplorerPlugin.tsx +7 -35
  140. package/src/capabilities/create-object.ts +36 -0
  141. package/src/capabilities/index.ts +4 -1
  142. package/src/capabilities/react-surface.tsx +32 -0
  143. package/src/components/Chart/Chart.stories.tsx +14 -21
  144. package/src/components/Chart/Chart.tsx +1 -1
  145. package/src/components/Globe/Globe.stories.tsx +17 -20
  146. package/src/components/Globe/Globe.tsx +1 -1
  147. package/src/components/Graph/CanvasForceGraph.stories.tsx +83 -0
  148. package/src/components/Graph/CanvasForceGraph.tsx +124 -0
  149. package/src/components/Graph/ForceGraph.stories.tsx +78 -42
  150. package/src/components/Graph/ForceGraph.tsx +104 -85
  151. package/src/components/Graph/index.ts +1 -1
  152. package/src/components/Lattice/Lattice.stories.tsx +90 -0
  153. package/src/components/Lattice/Lattice.tsx +182 -0
  154. package/src/components/Lattice/index.ts +5 -0
  155. package/src/components/Tree/EdgeBundling.stories.tsx +144 -0
  156. package/src/components/Tree/Tree.stories.tsx +19 -40
  157. package/src/components/Tree/Tree.tsx +69 -100
  158. package/src/components/Tree/index.ts +2 -0
  159. package/src/components/Tree/layout/HierarchicalEdgeBundling.tsx +296 -0
  160. package/src/components/Tree/layout/RadialTree.tsx +242 -0
  161. package/src/components/Tree/layout/TidyTree.tsx +246 -0
  162. package/src/components/Tree/layout/hierarchy.ts +32 -0
  163. package/src/components/Tree/layout/index.ts +5 -5
  164. package/src/components/Tree/layout/slots.ts +19 -0
  165. package/src/components/Tree/layout/useContainerSize.ts +43 -0
  166. package/src/components/Tree/types/tree.test.ts +4 -5
  167. package/src/components/Tree/types/tree.ts +9 -9
  168. package/src/components/Tree/types/types.ts +38 -29
  169. package/src/components/index.ts +1 -0
  170. package/src/containers/ExplorerArticle/ExplorerArticle.stories.tsx +136 -0
  171. package/src/containers/ExplorerArticle/ExplorerArticle.tsx +465 -0
  172. package/src/containers/ExplorerArticle/experimental.stories.tsx +446 -0
  173. package/src/containers/ExplorerArticle/index.ts +5 -0
  174. package/src/containers/index.ts +1 -1
  175. package/src/hooks/useGraphModel.ts +10 -6
  176. package/src/index.ts +1 -4
  177. package/src/meta.ts +1 -1
  178. package/src/plugin.ts +9 -0
  179. package/src/{components/Tree/testing → testing}/generator.ts +2 -2
  180. package/src/testing/index.ts +9 -0
  181. package/src/testing/relations.ts +192 -0
  182. package/src/translations.ts +14 -14
  183. package/src/types/ExplorerAction.ts +1 -1
  184. package/src/types/Graph.ts +2 -3
  185. package/src/typings.d.ts +8 -0
  186. package/src/util/index.ts +6 -0
  187. package/src/util/node-color.ts +23 -0
  188. package/src/{components → util}/plot.ts +16 -4
  189. package/dist/lib/browser/ExplorerContainer-H5RGY6AD.mjs +0 -48
  190. package/dist/lib/browser/ExplorerContainer-H5RGY6AD.mjs.map +0 -7
  191. package/dist/lib/browser/chunk-56VV76WZ.mjs.map +0 -7
  192. package/dist/lib/browser/chunk-6KEHUEEZ.mjs.map +0 -7
  193. package/dist/lib/browser/chunk-LSUP47BZ.mjs.map +0 -7
  194. package/dist/lib/browser/index.mjs +0 -107
  195. package/dist/lib/browser/index.mjs.map +0 -7
  196. package/dist/lib/browser/meta.json +0 -1
  197. package/dist/lib/browser/react-surface-JYGFP5ZN.mjs +0 -38
  198. package/dist/lib/browser/react-surface-JYGFP5ZN.mjs.map +0 -7
  199. package/dist/lib/node-esm/ExplorerContainer-KFHE5KU3.mjs +0 -49
  200. package/dist/lib/node-esm/ExplorerContainer-KFHE5KU3.mjs.map +0 -7
  201. package/dist/lib/node-esm/chunk-35JCF4SD.mjs +0 -11292
  202. package/dist/lib/node-esm/chunk-35JCF4SD.mjs.map +0 -7
  203. package/dist/lib/node-esm/chunk-EN3JZNEY.mjs +0 -26
  204. package/dist/lib/node-esm/chunk-EN3JZNEY.mjs.map +0 -7
  205. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
  206. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
  207. package/dist/lib/node-esm/chunk-WSE2Z4OT.mjs +0 -72
  208. package/dist/lib/node-esm/chunk-WSE2Z4OT.mjs.map +0 -7
  209. package/dist/lib/node-esm/index.mjs +0 -108
  210. package/dist/lib/node-esm/index.mjs.map +0 -7
  211. package/dist/lib/node-esm/meta.json +0 -1
  212. package/dist/lib/node-esm/meta.mjs +0 -9
  213. package/dist/lib/node-esm/react-surface-HJEJL53N.mjs +0 -39
  214. package/dist/lib/node-esm/react-surface-HJEJL53N.mjs.map +0 -7
  215. package/dist/lib/node-esm/types/index.mjs +0 -11
  216. package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
  217. package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
  218. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
  219. package/dist/types/src/components/Graph/D3ForceGraph.d.ts +0 -19
  220. package/dist/types/src/components/Graph/D3ForceGraph.d.ts.map +0 -1
  221. package/dist/types/src/components/Graph/D3ForceGraph.stories.d.ts.map +0 -1
  222. package/dist/types/src/components/Graph/adapter.d.ts.map +0 -1
  223. package/dist/types/src/components/Graph/testing.d.ts +0 -14
  224. package/dist/types/src/components/Graph/testing.d.ts.map +0 -1
  225. package/dist/types/src/components/Tree/testing/generator.d.ts.map +0 -1
  226. package/dist/types/src/components/Tree/testing/index.d.ts +0 -2
  227. package/dist/types/src/components/Tree/testing/index.d.ts.map +0 -1
  228. package/dist/types/src/components/plot.d.ts.map +0 -1
  229. package/dist/types/src/containers/ExplorerContainer/ExplorerContainer.d.ts +0 -6
  230. package/dist/types/src/containers/ExplorerContainer/ExplorerContainer.d.ts.map +0 -1
  231. package/dist/types/src/containers/ExplorerContainer/index.d.ts +0 -3
  232. package/dist/types/src/containers/ExplorerContainer/index.d.ts.map +0 -1
  233. package/src/capabilities/react-surface/index.ts +0 -7
  234. package/src/capabilities/react-surface/react-surface.tsx +0 -31
  235. package/src/components/Graph/D3ForceGraph.stories.tsx +0 -83
  236. package/src/components/Graph/D3ForceGraph.tsx +0 -109
  237. package/src/components/Graph/testing.ts +0 -58
  238. package/src/components/Tree/layout/HierarchicalEdgeBundling.ts +0 -162
  239. package/src/components/Tree/layout/RadialTree.ts +0 -94
  240. package/src/components/Tree/layout/TidyTree.ts +0 -101
  241. package/src/components/Tree/testing/index.ts +0 -5
  242. package/src/containers/ExplorerContainer/ExplorerContainer.tsx +0 -53
  243. package/src/containers/ExplorerContainer/index.ts +0 -7
  244. /package/dist/lib/{browser/chunk-J5LGTIGS.mjs.map → neutral/ExplorerPlugin.mjs.map} +0 -0
  245. /package/dist/lib/{browser → neutral}/chunk-J5LGTIGS.mjs +0 -0
  246. /package/dist/lib/{browser/meta.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
  247. /package/dist/lib/{browser/types → neutral}/index.mjs.map +0 -0
  248. /package/dist/lib/{node-esm → neutral}/meta.mjs.map +0 -0
  249. /package/dist/lib/{node-esm → neutral}/types/index.mjs.map +0 -0
  250. /package/dist/types/src/capabilities/{react-surface/react-surface.d.ts → react-surface.d.ts} +0 -0
  251. /package/src/components/Graph/{adapter.ts → graph-adapter.ts} +0 -0
@@ -0,0 +1,192 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type Space } from '@dxos/client/echo';
6
+ import { Obj, Query, Relation } from '@dxos/echo';
7
+ import { type TypeSpec, type ValueGenerator, createObjectFactory } from '@dxos/schema/testing';
8
+ import { HasConnection, HasRelationship, Organization, Person, Pipeline } from '@dxos/types';
9
+ import { range } from '@dxos/util';
10
+
11
+ import { type BundleEdge } from '../components/Tree/layout';
12
+ import { type TreeNode } from '../components/Tree/types';
13
+
14
+ const SECTORS = ['Technology', 'Finance', 'Research', 'Media'];
15
+ const CONNECTION_KINDS = ['partner', 'investor', 'vendor', 'customer'];
16
+
17
+ const pick = <T>(arr: readonly T[], rng = Math.random): T => arr[Math.floor(rng() * arr.length)];
18
+
19
+ export type ConnectedOrgsResult = {
20
+ organizations: Obj.Any[];
21
+ people: Obj.Any[];
22
+ connections: Obj.Any[];
23
+ };
24
+
25
+ export type ConnectedOrgsOptions = {
26
+ organizationCount?: number;
27
+ personCount?: number;
28
+ connectionCount?: number;
29
+ };
30
+
31
+ /**
32
+ * Populate a space with Organizations, People, and HasConnection relations between organizations.
33
+ * Uses `createObjectFactory` to generate Org/Person properties from their `GeneratorAnnotation`s,
34
+ * then layers manual HasConnection relations on top — the connection schema is fixed
35
+ * (Org→Org) so it isn't a fit for the generator's reference inference.
36
+ */
37
+ export const generateConnectedOrgs = async (
38
+ space: Space,
39
+ generator: ValueGenerator,
40
+ { organizationCount = 12, personCount = 24, connectionCount = 18 }: ConnectedOrgsOptions = {},
41
+ ): Promise<ConnectedOrgsResult> => {
42
+ const specs: TypeSpec[] = [
43
+ { type: Organization.Organization, count: organizationCount },
44
+ // Person has a Ref to Organization — generator fills it from objects already in db.
45
+ { type: Person.Person, count: personCount },
46
+ ];
47
+
48
+ const factory = createObjectFactory(space.db, generator);
49
+ await factory(specs);
50
+
51
+ const organizations = await space.db.query(Query.type(Organization.Organization)).run();
52
+ const people = await space.db.query(Query.type(Person.Person)).run();
53
+
54
+ const connections: Obj.Any[] = [];
55
+ const seen = new Set<string>();
56
+ for (let i = 0; i < connectionCount && organizations.length >= 2; i++) {
57
+ const source = pick(organizations);
58
+ const target = pick(organizations);
59
+ if (source.id === target.id) {
60
+ continue;
61
+ }
62
+ const key = `${source.id}->${target.id}`;
63
+ if (seen.has(key)) {
64
+ continue;
65
+ }
66
+ seen.add(key);
67
+
68
+ const relation = Relation.make(HasConnection.HasConnection, {
69
+ [Relation.Source]: source as any,
70
+ [Relation.Target]: target as any,
71
+ kind: pick(CONNECTION_KINDS),
72
+ });
73
+ connections.push(space.db.add(relation as any));
74
+ }
75
+
76
+ await space.db.flush();
77
+ return { organizations, people, connections };
78
+ };
79
+
80
+ /**
81
+ * Build a TreeNode hierarchy: Root → Sector → Organization (leaf).
82
+ * Organizations are deterministically bucketed into `SECTORS` so the demo has visible groups.
83
+ */
84
+ export const buildOrgHierarchy = (organizations: Obj.Any[], sectors: readonly string[] = SECTORS): TreeNode => {
85
+ // Avoid modulo-by-zero / missing-bucket crashes when the caller passes an empty sectors list.
86
+ const activeSectors = sectors.length > 0 ? sectors : ['Uncategorized'];
87
+ const buckets = new Map<string, TreeNode[]>();
88
+ for (const sector of activeSectors) {
89
+ buckets.set(sector, []);
90
+ }
91
+ for (let i = 0; i < organizations.length; i++) {
92
+ const org = organizations[i] as any;
93
+ const sector = activeSectors[i % activeSectors.length];
94
+ buckets.get(sector)!.push({
95
+ id: org.id,
96
+ label: org.name ?? org.id.slice(0, 6),
97
+ });
98
+ }
99
+
100
+ return {
101
+ id: 'root',
102
+ label: 'Organizations',
103
+ children: activeSectors.map((sector) => ({
104
+ id: `sector:${sector}`,
105
+ label: sector,
106
+ children: buckets.get(sector) ?? [],
107
+ })),
108
+ };
109
+ };
110
+
111
+ export type GenerateOptions = {
112
+ spec?: TypeSpec[];
113
+ relations?: {
114
+ count: number;
115
+ kind: string;
116
+ };
117
+ };
118
+
119
+ const defaultGenerateTypes: TypeSpec[] = [
120
+ {
121
+ type: Organization.Organization,
122
+ count: 20,
123
+ },
124
+ {
125
+ type: Person.Person,
126
+ count: 20,
127
+ },
128
+ {
129
+ type: Pipeline.Pipeline,
130
+ count: 20,
131
+ },
132
+ ];
133
+
134
+ const defaultGenerateRelations: NonNullable<GenerateOptions['relations']> = {
135
+ kind: 'friend',
136
+ count: 10,
137
+ };
138
+
139
+ /**
140
+ * Populate a space with a mixed dataset (Orgs, Pipelines, People) plus
141
+ * `HasRelationship` edges between random pairs of People.
142
+ *
143
+ * Used by the force-directed and canvas-force graph stories that want a
144
+ * heterogeneous typed dataset without caring about the precise shape of relations.
145
+ */
146
+ export const generate = async (
147
+ space: Space,
148
+ generator: ValueGenerator,
149
+ { spec = defaultGenerateTypes, relations = defaultGenerateRelations }: GenerateOptions = {},
150
+ ) => {
151
+ const createObjects = createObjectFactory(space.db, generator);
152
+ await createObjects(spec);
153
+
154
+ const contacts: Obj.Any[] = await space.db.query(Query.type(Person.Person)).run();
155
+ if (contacts.length < 2 || relations.count <= 0) {
156
+ return;
157
+ }
158
+
159
+ for (const _ of range(relations.count)) {
160
+ const source = pick(contacts);
161
+ const target = pick(contacts);
162
+ if (source.id !== target.id) {
163
+ space.db.add(
164
+ Relation.make(HasRelationship.HasRelationship, {
165
+ [Relation.Source]: source as any,
166
+ [Relation.Target]: target as any,
167
+ kind: relations.kind,
168
+ }) as any,
169
+ );
170
+ }
171
+ }
172
+ };
173
+
174
+ /**
175
+ * Convert HasConnection relations into bundle edges between organization ids.
176
+ */
177
+ export const connectionsToEdges = (connections: Obj.Any[]): BundleEdge[] => {
178
+ return connections
179
+ .map((relation): BundleEdge | undefined => {
180
+ const source = Relation.getSource(relation as any) as any;
181
+ const target = Relation.getTarget(relation as any) as any;
182
+ if (!source?.id || !target?.id) {
183
+ return undefined;
184
+ }
185
+ return {
186
+ source: source.id,
187
+ target: target.id,
188
+ kind: (relation as any).kind,
189
+ };
190
+ })
191
+ .filter((e): e is BundleEdge => Boolean(e));
192
+ };
@@ -4,28 +4,28 @@
4
4
 
5
5
  import { Type } from '@dxos/echo';
6
6
  import { type Resource } from '@dxos/react-ui';
7
- import { translations as componentsTranslations } from '@dxos/react-ui-components';
7
+ import { translations as componentsTranslations } from '@dxos/react-ui-components/translations';
8
8
 
9
- import { meta } from './meta';
10
- import { Graph } from './types';
9
+ import { meta } from '#meta';
10
+ import { Graph } from '#types';
11
11
 
12
12
  export const translations = [
13
13
  {
14
14
  'en-US': {
15
15
  [Type.getTypename(Graph.Graph)]: {
16
- 'typename label': 'Explorer',
17
- 'typename label_zero': 'Explorers',
18
- 'typename label_one': 'Explorer',
19
- 'typename label_other': 'Explorers',
20
- 'object name placeholder': 'New explorer',
21
- 'add object label': 'Add explorer',
22
- 'rename object label': 'Rename explorer',
23
- 'delete object label': 'Delete explorer',
24
- 'object deleted label': 'Explorer deleted',
16
+ 'typename.label': 'Explorer',
17
+ 'typename.label_zero': 'Explorers',
18
+ 'typename.label_one': 'Explorer',
19
+ 'typename.label_other': 'Explorers',
20
+ 'object-name.placeholder': 'New explorer',
21
+ 'add-object.label': 'Add explorer',
22
+ 'rename-object.label': 'Rename explorer',
23
+ 'delete-object.label': 'Delete explorer',
24
+ 'object-deleted.label': 'Explorer deleted',
25
25
  },
26
26
  [meta.id]: {
27
- 'plugin name': 'Explorer',
28
- 'object title label': 'Title',
27
+ 'plugin.name': 'Explorer',
28
+ 'object-title.label': 'Title',
29
29
  },
30
30
  },
31
31
  },
@@ -4,7 +4,7 @@
4
4
 
5
5
  import * as Schema from 'effect/Schema';
6
6
 
7
- import { TypeInputOptionsAnnotation } from '@dxos/plugin-space/types';
7
+ import { TypeInputOptionsAnnotation } from '@dxos/plugin-space';
8
8
 
9
9
  export const GraphProps = Schema.Struct({
10
10
  name: Schema.optional(Schema.String),
@@ -4,8 +4,7 @@
4
4
 
5
5
  import * as Schema from 'effect/Schema';
6
6
 
7
- import { Annotation, Filter, Obj, Query, QueryAST, Ref, Type } from '@dxos/echo';
8
- import { View } from '@dxos/echo';
7
+ import { Annotation, Filter, Obj, Query, QueryAST, Ref, Type, View } from '@dxos/echo';
9
8
  import { FormInputAnnotation, LabelAnnotation } from '@dxos/echo/internal';
10
9
  import { ViewAnnotation } from '@dxos/schema';
11
10
 
@@ -24,7 +23,7 @@ const GraphSchema = Schema.Struct({
24
23
  version: '0.1.0',
25
24
  }),
26
25
  LabelAnnotation.set(['name']),
27
- ViewAnnotation.set(true),
26
+ ViewAnnotation.set(['view']),
28
27
  Annotation.IconAnnotation.set({
29
28
  icon: 'ph--graph--regular',
30
29
  hue: 'green',
@@ -0,0 +1,8 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ declare module '*.css' {
6
+ const content: undefined;
7
+ export default content;
8
+ }
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export * from './node-color';
6
+ export * from './plot';
@@ -0,0 +1,23 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { Obj } from '@dxos/echo';
6
+ import { getHashHue } from '@dxos/ui-theme';
7
+
8
+ /**
9
+ * Returns the SVG `fill` value for a node, derived from its typename via the
10
+ * same hue-hash used by the force-directed renderer. Resolves to a Tailwind
11
+ * color token CSS variable so the value reads consistently across themes.
12
+ *
13
+ * Used by every variant of `ExplorerArticle` so nodes are colored consistently
14
+ * regardless of which layout is rendering them.
15
+ */
16
+ export const getNodeFillForTypename = (typename: string | undefined): string => {
17
+ return `var(--color-${getHashHue(typename)}-400)`;
18
+ };
19
+
20
+ /** Convenience: derive the fill from an ECHO object's typename. */
21
+ export const getNodeFillForObject = (object: Obj.Unknown | undefined): string => {
22
+ return getNodeFillForTypename(object && Obj.getTypename(object));
23
+ };
@@ -4,12 +4,24 @@
4
4
 
5
5
  import type { ChannelValueSpec } from '@observablehq/plot';
6
6
 
7
- export type Point = { x: number; y: number };
8
- export type GeoLocation = { lat: number; lng: number };
9
-
10
7
  export type Accessor<T> = (object: any) => T;
11
8
 
9
+ export type Point = {
10
+ x: number;
11
+ y: number;
12
+ };
13
+
14
+ export type GeoLocation = {
15
+ lat: number;
16
+ lng: number;
17
+ };
18
+
12
19
  export const createAdapter = <T extends Record<string, any>>(
13
20
  prop: string,
14
21
  accessor: Accessor<T> | undefined,
15
- ): ChannelValueSpec => (accessor ? { transform: (values) => values.map((value) => accessor(value)[prop]) } : prop);
22
+ ): ChannelValueSpec =>
23
+ accessor
24
+ ? {
25
+ transform: (values) => values.map((value) => accessor(value)[prop]),
26
+ }
27
+ : prop;
@@ -1,48 +0,0 @@
1
- import {
2
- D3ForceGraph,
3
- useGraphModel
4
- } from "./chunk-56VV76WZ.mjs";
5
- import "./chunk-J5LGTIGS.mjs";
6
-
7
- // src/containers/ExplorerContainer/ExplorerContainer.tsx
8
- import React, { useCallback, useMemo, useState } from "react";
9
- import { QueryBuilder } from "@dxos/echo-query";
10
- import { useGlobalSearch } from "@dxos/plugin-search";
11
- import { getSpace, useObject } from "@dxos/react-client/echo";
12
- import { Panel, Toolbar } from "@dxos/react-ui";
13
- import { QueryEditor } from "@dxos/react-ui-components";
14
- var ExplorerContainer = ({ role, subject: view }) => {
15
- useObject(view);
16
- const space = view && getSpace(view);
17
- const [filter, setFilter] = useState();
18
- const model = useGraphModel(space, filter);
19
- const { match } = useGlobalSearch();
20
- const builder = useMemo(() => new QueryBuilder(), []);
21
- const handleChange = useCallback((value) => {
22
- setFilter(builder.build(value).filter);
23
- }, []);
24
- const showToolbar = role === "article";
25
- if (!space || !model) {
26
- return null;
27
- }
28
- return /* @__PURE__ */ React.createElement(Panel.Root, {
29
- role
30
- }, showToolbar && /* @__PURE__ */ React.createElement(Panel.Toolbar, {
31
- asChild: true
32
- }, /* @__PURE__ */ React.createElement(Toolbar.Root, null, /* @__PURE__ */ React.createElement(QueryEditor, {
33
- db: space.db,
34
- onChange: handleChange
35
- }))), /* @__PURE__ */ React.createElement(Panel.Content, {
36
- asChild: true
37
- }, /* @__PURE__ */ React.createElement(D3ForceGraph, {
38
- model,
39
- match
40
- })));
41
- };
42
-
43
- // src/containers/ExplorerContainer/index.ts
44
- var ExplorerContainer_default = ExplorerContainer;
45
- export {
46
- ExplorerContainer_default as default
47
- };
48
- //# sourceMappingURL=ExplorerContainer-H5RGY6AD.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/containers/ExplorerContainer/ExplorerContainer.tsx", "../../../src/containers/ExplorerContainer/index.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { type SurfaceComponentProps } from '@dxos/app-toolkit/ui';\nimport { type Filter } from '@dxos/echo';\nimport { type View } from '@dxos/echo';\nimport { QueryBuilder } from '@dxos/echo-query';\nimport { useGlobalSearch } from '@dxos/plugin-search';\nimport { getSpace, useObject } from '@dxos/react-client/echo';\nimport { Panel, Toolbar } from '@dxos/react-ui';\nimport { QueryEditor, type QueryEditorProps } from '@dxos/react-ui-components';\n\nimport { D3ForceGraph } from '../../components';\nimport { useGraphModel } from '../../hooks';\n\nexport type ExplorerContainerProps = SurfaceComponentProps<View.View>;\n\nexport const ExplorerContainer = ({ role, subject: view }: ExplorerContainerProps) => {\n useObject(view);\n const space = view && getSpace(view);\n const [filter, setFilter] = useState<Filter.Any>();\n const model = useGraphModel(space, filter);\n const { match } = useGlobalSearch();\n\n const builder = useMemo(() => new QueryBuilder(), []);\n const handleChange = useCallback<NonNullable<QueryEditorProps['onChange']>>((value) => {\n setFilter(builder.build(value).filter);\n }, []);\n\n const showToolbar = role === 'article';\n\n if (!space || !model) {\n return null;\n }\n\n return (\n <Panel.Root role={role}>\n {showToolbar && (\n <Panel.Toolbar asChild>\n <Toolbar.Root>\n <QueryEditor db={space.db} onChange={handleChange} />\n </Toolbar.Root>\n </Panel.Toolbar>\n )}\n <Panel.Content asChild>\n <D3ForceGraph model={model} match={match} />\n </Panel.Content>\n </Panel.Root>\n );\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { ExplorerContainer } from './ExplorerContainer';\n\nexport default ExplorerContainer;\n"],
5
- "mappings": ";;;;;;;AAIA,OAAOA,SAASC,aAAaC,SAASC,gBAAgB;AAKtD,SAASC,oBAAoB;AAC7B,SAASC,uBAAuB;AAChC,SAASC,UAAUC,iBAAiB;AACpC,SAASC,OAAOC,eAAe;AAC/B,SAASC,mBAA0C;AAO5C,IAAMC,oBAAoB,CAAC,EAAEC,MAAMC,SAASC,KAAI,MAA0B;AAC/EC,YAAUD,IAAAA;AACV,QAAME,QAAQF,QAAQG,SAASH,IAAAA;AAC/B,QAAM,CAACI,QAAQC,SAAAA,IAAaC,SAAAA;AAC5B,QAAMC,QAAQC,cAAcN,OAAOE,MAAAA;AACnC,QAAM,EAAEK,MAAK,IAAKC,gBAAAA;AAElB,QAAMC,UAAUC,QAAQ,MAAM,IAAIC,aAAAA,GAAgB,CAAA,CAAE;AACpD,QAAMC,eAAeC,YAAuD,CAACC,UAAAA;AAC3EX,cAAUM,QAAQM,MAAMD,KAAAA,EAAOZ,MAAM;EACvC,GAAG,CAAA,CAAE;AAEL,QAAMc,cAAcpB,SAAS;AAE7B,MAAI,CAACI,SAAS,CAACK,OAAO;AACpB,WAAO;EACT;AAEA,SACE,sBAAA,cAACY,MAAMC,MAAI;IAACtB;KACToB,eACC,sBAAA,cAACC,MAAME,SAAO;IAACC,SAAAA;KACb,sBAAA,cAACD,QAAQD,MAAI,MACX,sBAAA,cAACG,aAAAA;IAAYC,IAAItB,MAAMsB;IAAIC,UAAUX;QAI3C,sBAAA,cAACK,MAAMO,SAAO;IAACJ,SAAAA;KACb,sBAAA,cAACK,cAAAA;IAAapB;IAAcE;;AAIpC;;;AC9CA,IAAA,4BAAemB;",
6
- "names": ["React", "useCallback", "useMemo", "useState", "QueryBuilder", "useGlobalSearch", "getSpace", "useObject", "Panel", "Toolbar", "QueryEditor", "ExplorerContainer", "role", "subject", "view", "useObject", "space", "getSpace", "filter", "setFilter", "useState", "model", "useGraphModel", "match", "useGlobalSearch", "builder", "useMemo", "QueryBuilder", "handleChange", "useCallback", "value", "build", "showToolbar", "Panel", "Root", "Toolbar", "asChild", "QueryEditor", "db", "onChange", "Content", "D3ForceGraph", "ExplorerContainer"]
7
- }