@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
@@ -1,83 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import { type Meta, type StoryObj } from '@storybook/react-vite';
6
- import React, { useState } from 'react';
7
-
8
- import { Type } from '@dxos/echo';
9
- import { View } from '@dxos/echo';
10
- import { faker } from '@dxos/random';
11
- import { useClient } from '@dxos/react-client';
12
- import { type Space } from '@dxos/react-client/echo';
13
- import { withClientProvider } from '@dxos/react-client/testing';
14
- import { useAsyncEffect } from '@dxos/react-ui';
15
- import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
16
- import { ViewModel } from '@dxos/schema';
17
- import { type ValueGenerator } from '@dxos/schema/testing';
18
- import { withRegistry } from '@dxos/storybook-utils';
19
- import { HasRelationship, Organization, Person, Pipeline } from '@dxos/types';
20
-
21
- import { useGraphModel } from '../../hooks';
22
- import { Graph } from '../../types';
23
-
24
- import { D3ForceGraph } from './D3ForceGraph';
25
- import { generate } from './testing';
26
-
27
- const generator = faker as any as ValueGenerator;
28
-
29
- faker.seed(1);
30
-
31
- const DefaultStory = () => {
32
- const client = useClient();
33
- const [space, setSpace] = useState<Space>();
34
- const [graph, setGraph] = useState<Graph.Graph>();
35
-
36
- useAsyncEffect(async () => {
37
- const space = client.spaces.get()[0];
38
- void generate(space, generator);
39
- const { view } = await ViewModel.makeFromDatabase({ db: space.db, typename: Type.getTypename(Graph.Graph) });
40
- const graph = Graph.make({ name: 'Test', view });
41
- space.db.add(graph);
42
- setSpace(space);
43
- setGraph(graph);
44
- }, [client]);
45
-
46
- const model = useGraphModel(space);
47
- if (!model || !space || !graph) {
48
- return <Loading data={{ model: !!model, space: !!space, graph: !!graph }} />;
49
- }
50
-
51
- return <D3ForceGraph model={model} />;
52
- };
53
-
54
- const meta = {
55
- title: 'plugins/plugin-explorer/components/D3ForceGraph',
56
- component: D3ForceGraph,
57
- render: DefaultStory,
58
- decorators: [
59
- withRegistry,
60
- withTheme(),
61
- withLayout(),
62
- withClientProvider({
63
- createSpace: true,
64
- types: [
65
- Graph.Graph,
66
- View.View,
67
- Organization.Organization,
68
- Pipeline.Pipeline,
69
- Person.Person,
70
- HasRelationship.HasRelationship,
71
- ],
72
- }),
73
- ],
74
- parameters: {
75
- layout: 'fullscreen',
76
- },
77
- } satisfies Meta<typeof D3ForceGraph>;
78
-
79
- export default meta;
80
-
81
- type Story = StoryObj<typeof meta>;
82
-
83
- export const Default: Story = {};
@@ -1,109 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import { Atom, useAtomValue } from '@effect-atom/atom-react';
6
- import React, { type ComponentPropsWithoutRef, useCallback, useEffect, useMemo, useRef } from 'react';
7
-
8
- import { Obj } from '@dxos/echo';
9
- import { SelectionModel } from '@dxos/graph';
10
- import {
11
- type GraphController,
12
- GraphForceProjector,
13
- type GraphLayoutNode,
14
- type GraphProps,
15
- SVG,
16
- type SVGContext,
17
- } from '@dxos/react-ui-graph';
18
- import { type SpaceGraphEdge, type SpaceGraphModel, type SpaceGraphNode } from '@dxos/schema';
19
- import { composable, composableProps, getHashStyles } from '@dxos/ui-theme';
20
-
21
- import '@dxos/react-ui-graph/styles/graph.css';
22
-
23
- export type D3ForceGraphProps = {
24
- model?: SpaceGraphModel;
25
- match?: RegExp;
26
- selection?: SelectionModel;
27
- grid?: boolean;
28
- } & Pick<GraphProps, 'drag'> &
29
- ComponentPropsWithoutRef<'div'>;
30
-
31
- const EMPTY_ATOM = Atom.make<{ nodes: SpaceGraphNode[]; edges: SpaceGraphEdge[] }>({ nodes: [], edges: [] });
32
-
33
- export const D3ForceGraph = composable<HTMLDivElement, D3ForceGraphProps>(
34
- ({ model, selection: _selection, grid, drag, ...props }, forwardedRef) => {
35
- // TODO(wittjosiah): This should go into Graph.tsx but for some reason doesn't work.
36
- useAtomValue(model?.graphAtom ?? EMPTY_ATOM);
37
-
38
- const svgRef = useRef<SVGContext>(null);
39
- const projector = useMemo<GraphForceProjector | undefined>(() => {
40
- if (svgRef.current) {
41
- return new GraphForceProjector(svgRef.current, {
42
- attributes: {
43
- linkForce: (edge) => {
44
- // TODO(burdon): Check type (currently assumes Employee property).
45
- // Edge shouldn't contribute to force if it's not active.
46
- return edge.data?.object?.active !== false;
47
- },
48
- },
49
- forces: {
50
- point: {
51
- strength: 0.01,
52
- },
53
- },
54
- });
55
- }
56
- }, []);
57
-
58
- const graph = useRef<GraphController>(null);
59
- const selection = useMemo(() => _selection ?? new SelectionModel(), [_selection]);
60
- useEffect(() => selection.subscribe(() => graph.current?.repaint()), [selection]);
61
-
62
- const handleSelect = useCallback<NonNullable<GraphProps['onSelect']>>(
63
- (node) => {
64
- if (selection.contains(node.id)) {
65
- selection.remove(node.id);
66
- } else {
67
- selection.add(node.id);
68
- }
69
- },
70
- [selection],
71
- );
72
-
73
- return (
74
- <div {...composableProps(props, { role: 'none', classNames: 'dx-container' })} ref={forwardedRef}>
75
- <SVG.Root ref={svgRef}>
76
- <SVG.Markers />
77
- {grid && <SVG.Grid axis />}
78
- <SVG.Zoom extent={[1 / 2, 2]}>
79
- <SVG.Graph<SpaceGraphNode, SpaceGraphEdge>
80
- drag={drag}
81
- ref={graph}
82
- model={model}
83
- projector={projector}
84
- labels={{
85
- text: (node) => {
86
- return node.data?.data.label ?? node.id;
87
- },
88
- }}
89
- attributes={{
90
- node: (node: GraphLayoutNode<SpaceGraphNode>) => {
91
- const obj = node.data?.data.object;
92
- return {
93
- data: {
94
- color: getHashStyles(obj && Obj.getTypename(obj))?.hue,
95
- },
96
- classes: {
97
- 'dx-selected': selection.contains(node.id),
98
- },
99
- };
100
- },
101
- }}
102
- onSelect={handleSelect}
103
- />
104
- </SVG.Zoom>
105
- </SVG.Root>
106
- </div>
107
- );
108
- },
109
- );
@@ -1,58 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import { type Space } from '@dxos/client/echo';
6
- import { type Obj, Query, Relation } from '@dxos/echo';
7
- import { type TypeSpec, type ValueGenerator, createObjectFactory } from '@dxos/schema/testing';
8
- import { HasRelationship, Organization, Person, Pipeline } from '@dxos/types';
9
- import { range } from '@dxos/util';
10
-
11
- const getObject = (objects: Obj.Unknown[]) => objects[Math.floor(Math.random() * objects.length)];
12
-
13
- const defaultTypes: TypeSpec[] = [
14
- { type: Organization.Organization, count: 5 },
15
- { type: Pipeline.Pipeline, count: 5 },
16
- { type: Person.Person, count: 10 },
17
- ];
18
-
19
- export type GenerateOptions = {
20
- spec?: TypeSpec[];
21
- relations?: {
22
- count: number;
23
- kind: string;
24
- };
25
- };
26
-
27
- const defaultRelations: GenerateOptions['relations'] = {
28
- kind: 'friend',
29
- count: 10,
30
- };
31
-
32
- /**
33
- * @deprecated Use @dxos/schema.
34
- */
35
- export const generate = async (
36
- space: Space,
37
- generator: ValueGenerator,
38
- { spec = defaultTypes, relations = defaultRelations }: GenerateOptions = {},
39
- ) => {
40
- const createObjects = createObjectFactory(space.db, generator);
41
- await createObjects(spec);
42
-
43
- // Add relations between objects.
44
- const contacts = await space.db.query(Query.type(Person.Person)).run();
45
- for (const _ of range(relations.count)) {
46
- const source = getObject(contacts);
47
- const target = getObject(contacts);
48
- if (source.id !== target.id) {
49
- space.db.add(
50
- Relation.make(HasRelationship.HasRelationship, {
51
- [Relation.Source]: source,
52
- [Relation.Target]: target,
53
- kind: relations.kind,
54
- }),
55
- );
56
- }
57
- }
58
- };
@@ -1,162 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- // Copyright 2022 Observable, Inc.
4
- //
5
-
6
- import { cluster, curveBundle, hierarchy, lineRadial, select } from 'd3';
7
- import { type HierarchyNode } from 'd3-hierarchy';
8
-
9
- import { type TreeOptions } from '../Tree';
10
- import { type TreeNode } from '../types';
11
-
12
- // Create hierarchical ID.
13
- // eslint-disable-next-line unused-imports/no-unused-vars
14
- const getId = (node: HierarchyNode<TreeNode>): string =>
15
- `${node.parent ? getId(node.parent) + '/' : ''}${node.data.id.slice(0, 4)}`;
16
-
17
- // https://github.com/d3/d3-hierarchy
18
- // https://observablehq.com/@d3/hierarchical-edge-bundling?intent=fork
19
- const HierarchicalEdgeBundling = (s: SVGSVGElement, data: TreeNode, options: TreeOptions) => {
20
- const svg = select(s);
21
- svg.selectAll('*').remove();
22
-
23
- const { radius = 600, padding = 100, slots } = options;
24
-
25
- // https://d3js.org/d3-hierarchy/hierarchy
26
- const root = hierarchy(flatten(data));
27
- // .sort((a, b) => ascending(a.height, b.height) || ascending(getName(a.data), getName(b.data)));
28
-
29
- const tree = cluster<TreeNode>().size([2 * Math.PI, radius - padding]);
30
- const layout = tree(addLinks(root));
31
-
32
- // eslint-disable-next-line unused-imports/no-unused-vars
33
- const node = svg
34
- .append('g')
35
- .selectAll()
36
- .data(layout.leaves())
37
- .join('g')
38
- .attr('transform', (d) => `rotate(${d.x * (180 / Math.PI) - 90}) translate(${d.y},0)`)
39
- .append('text')
40
- .attr('class', slots?.text ?? '')
41
- .attr('dy', '0.31em') // TODO(burdon): Based on font size.
42
- .attr('x', (d) => (d.x < Math.PI ? 6 : -6))
43
- .attr('text-anchor', (d) => (d.x < Math.PI ? 'start' : 'end'))
44
- .attr('transform', (d) => (d.x >= Math.PI ? 'rotate(180)' : null))
45
- // .text((d: any) => d.data.id)
46
- // .each(function (d: any) {
47
- // d.text = this;
48
- // })
49
- // .on('mouseover', overed)
50
- // .on('mouseout', outed)
51
- .call(
52
- (text) => text.text((d: any) => d.data.id.slice(0, 8)),
53
- // .text((d: any) => `${getId(d)} [${[(d as any).outgoing?.length ?? 0]}]`),
54
- );
55
-
56
- // https://d3js.org/d3-shape/radial-line
57
- const line = lineRadial()
58
- .curve(curveBundle.beta(0.85))
59
- .radius((d: any) => d.y)
60
- .angle((d: any) => d.x);
61
-
62
- // eslint-disable-next-line unused-imports/no-unused-vars
63
- const links = svg
64
- .append('g')
65
- .selectAll()
66
- .data(layout.leaves().flatMap((leaf: any) => leaf.outgoing))
67
- .join('path')
68
- .style('mix-blend-mode', 'multiply')
69
- .attr('class', slots?.path ?? '')
70
- .attr('d', ([i, o]) => {
71
- return line(i.path(o));
72
- })
73
- .each(function (d) {
74
- d.path = this;
75
- });
76
-
77
- // function overed(event: any, d: X) {
78
- // link.style('mix-blend-mode', null);
79
- // select(this).attr('font-weight', 'bold');
80
- // selectAll(d.incoming.map((d) => d.path))
81
- // .attr('stroke', color.in)
82
- // .raise();
83
- // selectAll((d as any).incoming.map(([d]) => d.text))
84
- // .attr('fill', color.in)
85
- // .attr('font-weight', 'bold');
86
- // selectAll(d.outgoing.map((d) => d.path))
87
- // .attr('stroke', color.out)
88
- // .raise();
89
- // selectAll(d.outgoing.map(([, d]) => d.text))
90
- // .attr('fill', color.out)
91
- // .attr('font-weight', 'bold');
92
- // }
93
-
94
- // function outed(event: any, d: HierarchyNode<Datum>) {
95
- // // @ts-ignore
96
- // select(this).attr('font-weight', null);
97
- // selectAll(d.incoming.map((d) => d.path)).attr('stroke', null);
98
- // selectAll(d.incoming.map(([d]) => d.text))
99
- // .attr('fill', null)
100
- // .attr('font-weight', null);
101
- // selectAll(d.outgoing.map((d) => d.path)).attr('stroke', null);
102
- // selectAll(d.outgoing.map(([, d]) => d.text))
103
- // .attr('fill', null)
104
- // .attr('font-weight', null);
105
- // }
106
- };
107
-
108
- // Monkey-patch with incoming/outgoing nodes.
109
- const addLinks = (root: HierarchyNode<TreeNode>) => {
110
- // Map of nodes indexed by ID.
111
- const nodes = new Map(root.descendants().map((d) => [d.data.id, d]));
112
- const parents = root.descendants().reduce((map, d) => {
113
- if (d.children?.length) {
114
- map.set(d.data.id, d);
115
- }
116
- return map;
117
- }, new Map<string, HierarchyNode<TreeNode>>());
118
-
119
- for (const d of root.leaves()) {
120
- // (d as any).incoming = [];
121
- const parent = parents.get(d.data.id);
122
- if (parent) {
123
- // Skip the first node which is a placeholder created by flatten().
124
- (d as any).outgoing =
125
- parent.data.children?.slice(1).map((child) => {
126
- return [d, nodes.get(child.id)!];
127
- }) ?? [];
128
- } else {
129
- (d as any).outgoing = [];
130
- }
131
- }
132
-
133
- // for (const d of root.leaves()) {
134
- // for (const [_, o] of (d as any).outgoing) {
135
- // o.incoming.push(o);
136
- // }
137
- // }
138
-
139
- return root;
140
- };
141
-
142
- /**
143
- * We are using a hierarchy in order to group nodes by parent, but we want the parent
144
- * nodes to be positioned at the first level along with all descendents.
145
- * So we add a placeholder for all parents at the head of each group.
146
- * @param node
147
- */
148
- const flatten = (node: TreeNode) => {
149
- const clone: TreeNode = {
150
- id: node.id,
151
- };
152
-
153
- // TODO(burdon): NOTE: Should exclude schema (since requires a tree).
154
- if (node.children?.length) {
155
- const children = node.children.map((child) => flatten(child));
156
- clone.children = [{ id: node.id }, ...children];
157
- }
158
-
159
- return clone;
160
- };
161
-
162
- export default HierarchicalEdgeBundling;
@@ -1,94 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- // Copyright 2022 Observable, Inc.
4
- //
5
-
6
- import { hierarchy, linkRadial, select, tree } from 'd3';
7
-
8
- import { type TreeOptions } from '../Tree';
9
-
10
- // Released under the ISC license.
11
- // https://observablehq.com/@d3/radial-tree
12
- // https://observablehq.com/@d3/tree
13
- const RadialTree = (s: SVGSVGElement, data: any, options: TreeOptions) => {
14
- const svg = select(s);
15
- svg.selectAll('*').remove();
16
-
17
- const {
18
- label, // given a node d, returns the display name
19
- radius = 400,
20
- r = 4, // radius of nodes
21
- slots,
22
- } = options;
23
-
24
- const arc = 2 * Math.PI;
25
-
26
- const root = hierarchy(data);
27
-
28
- // Sort the nodes.
29
- // if (sort) {
30
- // root.sort(sort);
31
- // }
32
-
33
- // Compute labels and titles.
34
- const descendants = root.descendants();
35
- const getLabel = label === null ? null : descendants.map((d) => label(d.data));
36
-
37
- // Compute the layout.
38
- const layout = tree()
39
- .size([arc, radius])
40
- .separation((a: any, b: any) => (a.parent === b.parent ? 1 : 2) / a.depth);
41
- layout(root);
42
-
43
- // Links.
44
- svg
45
- .append('g')
46
- .selectAll('path')
47
- .data(root.links())
48
- .join('path')
49
- .attr('class', slots?.path ?? '')
50
- .attr(
51
- 'd',
52
- linkRadial()
53
- .angle((d: any) => d.x + Math.PI / 2)
54
- .radius((d: any) => d.y) as any,
55
- );
56
-
57
- // Nodes.
58
- const node = svg
59
- .append('g')
60
- .selectAll('a')
61
- .data(root.descendants())
62
- .join('a')
63
- // .attr('xlink:href', link == null ? null : (d) => link(d.data, d))
64
- // .attr('target', link == null ? null : linkTarget)
65
- .attr('transform', (d: any) => `rotate(${(d.x * 180) / Math.PI}) translate(${d.y},0)`);
66
-
67
- node
68
- .append('circle')
69
- .attr('class', slots?.node ?? '')
70
- .attr('r', r);
71
-
72
- // if (title != null) {
73
- // node.append('title').text((d) => title(d.data, d));
74
- // }
75
-
76
- // Text.
77
- if (getLabel) {
78
- node
79
- .append('text')
80
- .attr('transform', (d: any) => `rotate(${d.x >= Math.PI ? 180 : 0})`)
81
- .attr('dy', '0.32em')
82
- // eslint-disable-next-line no-mixed-operators
83
- .attr('x', (d: any) => (d.x < Math.PI === !d.children ? 6 : -6))
84
- // eslint-disable-next-line no-mixed-operators
85
- .attr('text-anchor', (d: any) => (d.x < Math.PI === !d.children ? 'start' : 'end'))
86
- // .attr('paint-order', 'stroke')
87
- .attr('class', slots?.text ?? '')
88
- .text((d, i) => getLabel[i]);
89
- }
90
-
91
- return svg.node();
92
- };
93
-
94
- export default RadialTree;
@@ -1,101 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- // Copyright 2021 Observable, Inc.
4
- //
5
-
6
- import { curveBumpX, hierarchy, link, select, tree } from 'd3';
7
-
8
- import { type TreeOptions } from '../Tree';
9
-
10
- // Released under the ISC license.
11
- // https://observablehq.com/@d3/tree
12
- const TidyTree = (s: SVGSVGElement, data: any, options: TreeOptions) => {
13
- const svg = select(s);
14
- svg.selectAll('*').remove();
15
-
16
- const { label, width, height, r = 4, padding = 4, margin = 60, slots } = options;
17
-
18
- const root = hierarchy(data);
19
-
20
- // Compute labels and titles.
21
- const descendants = root.descendants();
22
- const getLabel = label == null ? null : descendants.map((d) => label(d.data));
23
-
24
- // Compute the layout.
25
- const dx = 16;
26
- const dy = width / (root.height + padding);
27
- const layout = tree().nodeSize([dx, dy]);
28
- layout(root);
29
-
30
- // Center the tree.
31
- let x0 = Infinity;
32
- let x1 = -x0;
33
- let y0 = Infinity;
34
- let y1 = -y0;
35
- root.each((d: any) => {
36
- if (d.x > x1) {
37
- x1 = d.x;
38
- }
39
- if (d.x < x0) {
40
- x0 = d.x;
41
- }
42
- if (d.y > y1) {
43
- y1 = d.y;
44
- }
45
- if (d.y < y0) {
46
- y0 = d.y;
47
- }
48
- });
49
-
50
- // TODO(burdon): Option to expand.
51
- // NOTE: x and y are flipped.
52
- const sx = Math.min(2, Math.max(1, (height - margin * 2) / (x1 - x0)));
53
- const oy = -(width - (y1 - y0)) / 2;
54
-
55
- // Links.
56
- svg
57
- .append('g')
58
- .selectAll('path')
59
- .data(root.links())
60
- .join('path')
61
- .attr('class', slots?.path ?? '')
62
- .attr(
63
- 'd',
64
- link(curveBumpX)
65
- .x((d: any) => d.y + oy)
66
- .y((d: any) => d.x * sx) as any,
67
- );
68
-
69
- // Nodes.
70
- const node = svg
71
- .append('g')
72
- .selectAll('a')
73
- .data(root.descendants())
74
- .join('a')
75
- // .attr('xlink:href', link == null ? null : (d) => link(d.data, d))
76
- // .attr('target', link == null ? null : linkTarget)
77
- .attr('transform', (d: any) => `translate(${d.y + oy},${d.x * sx})`);
78
-
79
- node
80
- .append('circle')
81
- .attr('class', slots?.node ?? '')
82
- .attr('r', r);
83
-
84
- // if (title != null) {
85
- // node.append('title').text((d) => title(d.data, d));
86
- // }
87
-
88
- if (getLabel) {
89
- node
90
- .append('text')
91
-
92
- .attr('dy', '0.32em')
93
- .attr('x', (d) => (d.children ? -6 : 6))
94
- .attr('text-anchor', (d) => (d.children ? 'end' : 'start'))
95
- // .attr('paint-order', 'stroke')
96
- .attr('class', slots?.text ?? '')
97
- .text((d, i) => getLabel[i]);
98
- }
99
- };
100
-
101
- export default TidyTree;
@@ -1,5 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- export * from './generator';
@@ -1,53 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import React, { useCallback, useMemo, useState } from 'react';
6
-
7
- import { type SurfaceComponentProps } from '@dxos/app-toolkit/ui';
8
- import { type Filter } from '@dxos/echo';
9
- import { type View } from '@dxos/echo';
10
- import { QueryBuilder } from '@dxos/echo-query';
11
- import { useGlobalSearch } from '@dxos/plugin-search';
12
- import { getSpace, useObject } from '@dxos/react-client/echo';
13
- import { Panel, Toolbar } from '@dxos/react-ui';
14
- import { QueryEditor, type QueryEditorProps } from '@dxos/react-ui-components';
15
-
16
- import { D3ForceGraph } from '../../components';
17
- import { useGraphModel } from '../../hooks';
18
-
19
- export type ExplorerContainerProps = SurfaceComponentProps<View.View>;
20
-
21
- export const ExplorerContainer = ({ role, subject: view }: ExplorerContainerProps) => {
22
- useObject(view);
23
- const space = view && getSpace(view);
24
- const [filter, setFilter] = useState<Filter.Any>();
25
- const model = useGraphModel(space, filter);
26
- const { match } = useGlobalSearch();
27
-
28
- const builder = useMemo(() => new QueryBuilder(), []);
29
- const handleChange = useCallback<NonNullable<QueryEditorProps['onChange']>>((value) => {
30
- setFilter(builder.build(value).filter);
31
- }, []);
32
-
33
- const showToolbar = role === 'article';
34
-
35
- if (!space || !model) {
36
- return null;
37
- }
38
-
39
- return (
40
- <Panel.Root role={role}>
41
- {showToolbar && (
42
- <Panel.Toolbar asChild>
43
- <Toolbar.Root>
44
- <QueryEditor db={space.db} onChange={handleChange} />
45
- </Toolbar.Root>
46
- </Panel.Toolbar>
47
- )}
48
- <Panel.Content asChild>
49
- <D3ForceGraph model={model} match={match} />
50
- </Panel.Content>
51
- </Panel.Root>
52
- );
53
- };
@@ -1,7 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import { ExplorerContainer } from './ExplorerContainer';
6
-
7
- export default ExplorerContainer;
File without changes