@dxos/plugin-explorer 0.8.4-main.ae835ea → 0.8.4-main.bc2380dfbc

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 (234) hide show
  1. package/LICENSE +102 -5
  2. package/dist/lib/neutral/ExplorerArticle-EW2MBCRK.mjs +141 -0
  3. package/dist/lib/neutral/ExplorerArticle-EW2MBCRK.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/neutral/chunk-7SPMPHRS.mjs +72 -0
  8. package/dist/lib/neutral/chunk-7SPMPHRS.mjs.map +7 -0
  9. package/dist/lib/neutral/chunk-GRJXLL4Z.mjs +25 -0
  10. package/dist/lib/neutral/chunk-GRJXLL4Z.mjs.map +7 -0
  11. package/dist/lib/{browser/chunk-UBHZGWZQ.mjs → neutral/chunk-HPIS2WXY.mjs} +2 -2
  12. package/dist/lib/neutral/chunk-HPIS2WXY.mjs.map +7 -0
  13. package/dist/lib/{browser/chunk-CRN65FY3.mjs → neutral/components/index.mjs} +817 -288
  14. package/dist/lib/{node-esm/chunk-RSZFBKZM.mjs.map → neutral/components/index.mjs.map} +4 -4
  15. package/dist/lib/neutral/containers/index.mjs +9 -0
  16. package/dist/lib/neutral/containers/index.mjs.map +7 -0
  17. package/dist/lib/neutral/create-object-F6TKVAGV.mjs +39 -0
  18. package/dist/lib/neutral/create-object-F6TKVAGV.mjs.map +7 -0
  19. package/dist/lib/neutral/hooks/index.mjs +45 -0
  20. package/dist/lib/neutral/hooks/index.mjs.map +7 -0
  21. package/dist/lib/neutral/index.mjs +14 -0
  22. package/dist/lib/neutral/meta.json +1 -0
  23. package/dist/lib/{browser → neutral}/meta.mjs +1 -1
  24. package/dist/lib/neutral/plugin.mjs +12 -0
  25. package/dist/lib/neutral/plugin.mjs.map +7 -0
  26. package/dist/lib/neutral/react-surface-APBW2VQG.mjs +26 -0
  27. package/dist/lib/neutral/react-surface-APBW2VQG.mjs.map +7 -0
  28. package/dist/lib/neutral/testing.mjs +8 -0
  29. package/dist/lib/neutral/translations.mjs +33 -0
  30. package/dist/lib/neutral/translations.mjs.map +7 -0
  31. package/dist/lib/{browser → neutral}/types/index.mjs +1 -2
  32. package/dist/types/data/cities.d.ts +4 -4
  33. package/dist/types/data/cities.d.ts.map +1 -1
  34. package/dist/types/data/countries-110m.d.ts +19 -22
  35. package/dist/types/data/countries-110m.d.ts.map +1 -1
  36. package/dist/types/src/ExplorerPlugin.d.ts +3 -1
  37. package/dist/types/src/ExplorerPlugin.d.ts.map +1 -1
  38. package/dist/types/src/ExplorerPlugin.test.d.ts +2 -0
  39. package/dist/types/src/ExplorerPlugin.test.d.ts.map +1 -0
  40. package/dist/types/src/capabilities/create-object.d.ts +11 -0
  41. package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
  42. package/dist/types/src/capabilities/index.d.ts +8 -2
  43. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  44. package/dist/types/src/capabilities/react-surface.d.ts +3 -2
  45. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  46. package/dist/types/src/components/Chart/Chart.d.ts.map +1 -1
  47. package/dist/types/src/components/Chart/Chart.stories.d.ts +4 -1
  48. package/dist/types/src/components/Chart/Chart.stories.d.ts.map +1 -1
  49. package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
  50. package/dist/types/src/components/Globe/Globe.stories.d.ts +5 -2
  51. package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
  52. package/dist/types/src/components/Graph/CanvasForceGraph.d.ts +13 -0
  53. package/dist/types/src/components/Graph/CanvasForceGraph.d.ts.map +1 -0
  54. package/dist/types/src/components/Graph/CanvasForceGraph.stories.d.ts +17 -0
  55. package/dist/types/src/components/Graph/CanvasForceGraph.stories.d.ts.map +1 -0
  56. package/dist/types/src/components/Graph/ForceGraph.d.ts +12 -5
  57. package/dist/types/src/components/Graph/ForceGraph.d.ts.map +1 -1
  58. package/dist/types/src/components/Graph/ForceGraph.stories.d.ts +4 -2
  59. package/dist/types/src/components/Graph/ForceGraph.stories.d.ts.map +1 -1
  60. package/dist/types/src/components/Graph/{adapter.d.ts → graph-adapter.d.ts} +2 -2
  61. package/dist/types/src/components/Graph/graph-adapter.d.ts.map +1 -0
  62. package/dist/types/src/components/Graph/index.d.ts +1 -1
  63. package/dist/types/src/components/Graph/index.d.ts.map +1 -1
  64. package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts +21 -0
  65. package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts.map +1 -0
  66. package/dist/types/src/components/Tree/Tree.d.ts +20 -23
  67. package/dist/types/src/components/Tree/Tree.d.ts.map +1 -1
  68. package/dist/types/src/components/Tree/Tree.stories.d.ts +5 -12
  69. package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
  70. package/dist/types/src/components/Tree/index.d.ts +3 -0
  71. package/dist/types/src/components/Tree/index.d.ts.map +1 -1
  72. package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts +35 -2
  73. package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts.map +1 -1
  74. package/dist/types/src/components/Tree/layout/RadialTree.d.ts +35 -2
  75. package/dist/types/src/components/Tree/layout/RadialTree.d.ts.map +1 -1
  76. package/dist/types/src/components/Tree/layout/TidyTree.d.ts +24 -2
  77. package/dist/types/src/components/Tree/layout/TidyTree.d.ts.map +1 -1
  78. package/dist/types/src/components/Tree/layout/hierarchy.d.ts +17 -0
  79. package/dist/types/src/components/Tree/layout/hierarchy.d.ts.map +1 -0
  80. package/dist/types/src/components/Tree/layout/index.d.ts +5 -4
  81. package/dist/types/src/components/Tree/layout/index.d.ts.map +1 -1
  82. package/dist/types/src/components/Tree/layout/slots.d.ts +7 -0
  83. package/dist/types/src/components/Tree/layout/slots.d.ts.map +1 -0
  84. package/dist/types/src/components/Tree/layout/useContainerSize.d.ts +15 -0
  85. package/dist/types/src/components/Tree/layout/useContainerSize.d.ts.map +1 -0
  86. package/dist/types/src/components/Tree/space-graph-adapter.d.ts +32 -0
  87. package/dist/types/src/components/Tree/space-graph-adapter.d.ts.map +1 -0
  88. package/dist/types/src/components/Tree/testing/generator.d.ts.map +1 -1
  89. package/dist/types/src/components/Tree/testing/index.d.ts +1 -0
  90. package/dist/types/src/components/Tree/testing/index.d.ts.map +1 -1
  91. package/dist/types/src/components/Tree/testing/relations.d.ts +47 -0
  92. package/dist/types/src/components/Tree/testing/relations.d.ts.map +1 -0
  93. package/dist/types/src/components/Tree/types/tree.d.ts +18 -16
  94. package/dist/types/src/components/Tree/types/tree.d.ts.map +1 -1
  95. package/dist/types/src/components/Tree/types/types.d.ts +14 -4
  96. package/dist/types/src/components/Tree/types/types.d.ts.map +1 -1
  97. package/dist/types/src/components/index.d.ts +0 -4
  98. package/dist/types/src/components/index.d.ts.map +1 -1
  99. package/dist/types/src/components/plot.d.ts.map +1 -1
  100. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts +8 -0
  101. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts.map +1 -0
  102. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts +24 -0
  103. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts.map +1 -0
  104. package/dist/types/src/containers/ExplorerArticle/index.d.ts +2 -0
  105. package/dist/types/src/containers/ExplorerArticle/index.d.ts.map +1 -0
  106. package/dist/types/src/containers/index.d.ts +3 -0
  107. package/dist/types/src/containers/index.d.ts.map +1 -0
  108. package/dist/types/src/hooks/useGraphModel.d.ts +2 -2
  109. package/dist/types/src/hooks/useGraphModel.d.ts.map +1 -1
  110. package/dist/types/src/index.d.ts +1 -3
  111. package/dist/types/src/index.d.ts.map +1 -1
  112. package/dist/types/src/meta.d.ts +2 -2
  113. package/dist/types/src/meta.d.ts.map +1 -1
  114. package/dist/types/src/plugin.d.ts +3 -0
  115. package/dist/types/src/plugin.d.ts.map +1 -0
  116. package/dist/types/src/testing.d.ts +2 -0
  117. package/dist/types/src/testing.d.ts.map +1 -0
  118. package/dist/types/src/translations.d.ts +31 -22
  119. package/dist/types/src/translations.d.ts.map +1 -1
  120. package/dist/types/src/types/ExplorerAction.d.ts +1 -18
  121. package/dist/types/src/types/ExplorerAction.d.ts.map +1 -1
  122. package/dist/types/src/types/Graph.d.ts +14 -25
  123. package/dist/types/src/types/Graph.d.ts.map +1 -1
  124. package/dist/types/tsconfig.tsbuildinfo +1 -1
  125. package/package.json +113 -61
  126. package/src/ExplorerPlugin.test.ts +26 -0
  127. package/src/ExplorerPlugin.tsx +15 -56
  128. package/src/capabilities/create-object.ts +36 -0
  129. package/src/capabilities/index.ts +3 -3
  130. package/src/capabilities/react-surface.tsx +24 -19
  131. package/src/components/Chart/Chart.stories.tsx +16 -23
  132. package/src/components/Globe/Globe.stories.tsx +19 -22
  133. package/src/components/Graph/CanvasForceGraph.stories.tsx +83 -0
  134. package/src/components/Graph/CanvasForceGraph.tsx +124 -0
  135. package/src/components/Graph/ForceGraph.stories.tsx +79 -41
  136. package/src/components/Graph/ForceGraph.tsx +104 -85
  137. package/src/components/Graph/{adapter.ts → graph-adapter.ts} +14 -8
  138. package/src/components/Graph/index.ts +1 -1
  139. package/src/components/Tree/EdgeBundling.stories.tsx +144 -0
  140. package/src/components/Tree/Tree.stories.tsx +20 -38
  141. package/src/components/Tree/Tree.tsx +69 -95
  142. package/src/components/Tree/index.ts +3 -0
  143. package/src/components/Tree/layout/HierarchicalEdgeBundling.tsx +277 -0
  144. package/src/components/Tree/layout/RadialTree.tsx +237 -0
  145. package/src/components/Tree/layout/TidyTree.tsx +246 -0
  146. package/src/components/Tree/layout/hierarchy.ts +32 -0
  147. package/src/components/Tree/layout/index.ts +5 -5
  148. package/src/components/Tree/layout/slots.ts +19 -0
  149. package/src/components/Tree/layout/useContainerSize.ts +43 -0
  150. package/src/components/Tree/space-graph-adapter.ts +96 -0
  151. package/src/components/Tree/testing/generator.ts +4 -2
  152. package/src/components/Tree/testing/index.ts +1 -0
  153. package/src/components/Tree/testing/relations.ts +182 -0
  154. package/src/components/Tree/types/tree.test.ts +7 -6
  155. package/src/components/Tree/types/tree.ts +41 -20
  156. package/src/components/Tree/types/types.ts +38 -29
  157. package/src/components/index.ts +0 -4
  158. package/src/containers/ExplorerArticle/ExplorerArticle.stories.tsx +119 -0
  159. package/src/containers/ExplorerArticle/ExplorerArticle.tsx +153 -0
  160. package/src/containers/ExplorerArticle/index.ts +5 -0
  161. package/src/containers/index.ts +7 -0
  162. package/src/hooks/useGraphModel.ts +25 -14
  163. package/src/index.ts +1 -4
  164. package/src/meta.ts +3 -3
  165. package/src/plugin.ts +9 -0
  166. package/src/testing.ts +7 -0
  167. package/src/translations.ts +16 -13
  168. package/src/types/ExplorerAction.ts +10 -19
  169. package/src/types/Graph.ts +25 -22
  170. package/src/typings.d.ts +8 -0
  171. package/dist/lib/browser/ExplorerContainer-L5RVUJRL.mjs +0 -50
  172. package/dist/lib/browser/ExplorerContainer-L5RVUJRL.mjs.map +0 -7
  173. package/dist/lib/browser/chunk-2MKBRIUT.mjs +0 -31
  174. package/dist/lib/browser/chunk-2MKBRIUT.mjs.map +0 -7
  175. package/dist/lib/browser/chunk-6BVXZQPP.mjs +0 -188
  176. package/dist/lib/browser/chunk-6BVXZQPP.mjs.map +0 -7
  177. package/dist/lib/browser/chunk-BGNRYZUN.mjs +0 -79
  178. package/dist/lib/browser/chunk-BGNRYZUN.mjs.map +0 -7
  179. package/dist/lib/browser/chunk-CRN65FY3.mjs.map +0 -7
  180. package/dist/lib/browser/chunk-UBHZGWZQ.mjs.map +0 -7
  181. package/dist/lib/browser/index.mjs +0 -119
  182. package/dist/lib/browser/index.mjs.map +0 -7
  183. package/dist/lib/browser/intent-resolver-FX5H52QN.mjs +0 -31
  184. package/dist/lib/browser/intent-resolver-FX5H52QN.mjs.map +0 -7
  185. package/dist/lib/browser/meta.json +0 -1
  186. package/dist/lib/browser/react-surface-VS3ZFL2Y.mjs +0 -35
  187. package/dist/lib/browser/react-surface-VS3ZFL2Y.mjs.map +0 -7
  188. package/dist/lib/node-esm/ExplorerContainer-BBLPHH7K.mjs +0 -51
  189. package/dist/lib/node-esm/ExplorerContainer-BBLPHH7K.mjs.map +0 -7
  190. package/dist/lib/node-esm/chunk-3ODK27PU.mjs +0 -33
  191. package/dist/lib/node-esm/chunk-3ODK27PU.mjs.map +0 -7
  192. package/dist/lib/node-esm/chunk-CRSVAZNA.mjs +0 -190
  193. package/dist/lib/node-esm/chunk-CRSVAZNA.mjs.map +0 -7
  194. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
  195. package/dist/lib/node-esm/chunk-RSZFBKZM.mjs +0 -11091
  196. package/dist/lib/node-esm/chunk-TQESRBUJ.mjs +0 -80
  197. package/dist/lib/node-esm/chunk-TQESRBUJ.mjs.map +0 -7
  198. package/dist/lib/node-esm/chunk-UXZM5VJB.mjs +0 -26
  199. package/dist/lib/node-esm/chunk-UXZM5VJB.mjs.map +0 -7
  200. package/dist/lib/node-esm/index.mjs +0 -120
  201. package/dist/lib/node-esm/index.mjs.map +0 -7
  202. package/dist/lib/node-esm/intent-resolver-RGBBXXYM.mjs +0 -32
  203. package/dist/lib/node-esm/intent-resolver-RGBBXXYM.mjs.map +0 -7
  204. package/dist/lib/node-esm/meta.json +0 -1
  205. package/dist/lib/node-esm/meta.mjs +0 -9
  206. package/dist/lib/node-esm/react-surface-SXPT2T37.mjs +0 -36
  207. package/dist/lib/node-esm/react-surface-SXPT2T37.mjs.map +0 -7
  208. package/dist/lib/node-esm/types/index.mjs +0 -12
  209. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  210. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  211. package/dist/types/src/components/ExplorerContainer.d.ts +0 -9
  212. package/dist/types/src/components/ExplorerContainer.d.ts.map +0 -1
  213. package/dist/types/src/components/Graph/D3ForceGraph.d.ts +0 -14
  214. package/dist/types/src/components/Graph/D3ForceGraph.d.ts.map +0 -1
  215. package/dist/types/src/components/Graph/D3ForceGraph.stories.d.ts +0 -15
  216. package/dist/types/src/components/Graph/D3ForceGraph.stories.d.ts.map +0 -1
  217. package/dist/types/src/components/Graph/adapter.d.ts.map +0 -1
  218. package/dist/types/src/components/Graph/testing.d.ts +0 -14
  219. package/dist/types/src/components/Graph/testing.d.ts.map +0 -1
  220. package/src/capabilities/intent-resolver.ts +0 -21
  221. package/src/components/ExplorerContainer.tsx +0 -54
  222. package/src/components/Graph/D3ForceGraph.stories.tsx +0 -77
  223. package/src/components/Graph/D3ForceGraph.tsx +0 -101
  224. package/src/components/Graph/testing.ts +0 -55
  225. package/src/components/Tree/layout/HierarchicalEdgeBundling.ts +0 -162
  226. package/src/components/Tree/layout/RadialTree.ts +0 -94
  227. package/src/components/Tree/layout/TidyTree.ts +0 -101
  228. /package/dist/lib/{browser/chunk-J5LGTIGS.mjs.map → neutral/ExplorerPlugin.mjs.map} +0 -0
  229. /package/dist/lib/{browser → neutral}/chunk-J5LGTIGS.mjs +0 -0
  230. /package/dist/lib/{browser/meta.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
  231. /package/dist/lib/{browser/types → neutral}/index.mjs.map +0 -0
  232. /package/dist/lib/{node-esm → neutral}/meta.mjs.map +0 -0
  233. /package/dist/lib/{node-esm/chunk-HSLMI22Q.mjs.map → neutral/testing.mjs.map} +0 -0
  234. /package/dist/lib/{node-esm → neutral}/types/index.mjs.map +0 -0
@@ -1,54 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import React, { useCallback, useMemo, useState } from 'react';
6
-
7
- import { type Filter } from '@dxos/echo';
8
- import { QueryBuilder } from '@dxos/echo-query';
9
- import { useGlobalSearch } from '@dxos/plugin-search';
10
- import { getSpace } from '@dxos/react-client/echo';
11
- import { Toolbar } from '@dxos/react-ui';
12
- import { QueryEditor, type QueryEditorProps } from '@dxos/react-ui-components';
13
- import { StackItem } from '@dxos/react-ui-stack';
14
- import { type DataType } from '@dxos/schema';
15
-
16
- import { useGraphModel } from '../hooks';
17
-
18
- import { D3ForceGraph } from './Graph';
19
-
20
- type ExplorerContainerProps = {
21
- role: string;
22
- view: DataType.View;
23
- };
24
-
25
- const ExplorerContainer = ({ role, view }: ExplorerContainerProps) => {
26
- const space = getSpace(view);
27
- const [filter, setFilter] = useState<Filter.Any>();
28
- const model = useGraphModel(space, filter);
29
- const { match } = useGlobalSearch();
30
-
31
- const builder = useMemo(() => new QueryBuilder(), []);
32
- const handleChange = useCallback<NonNullable<QueryEditorProps['onChange']>>((value) => {
33
- setFilter(builder.build(value).filter);
34
- }, []);
35
-
36
- const showToolbar = role === 'article';
37
-
38
- if (!space || !model) {
39
- return null;
40
- }
41
-
42
- return (
43
- <StackItem.Content toolbar={showToolbar}>
44
- {showToolbar && (
45
- <Toolbar.Root>
46
- <QueryEditor db={space.db} onChange={handleChange} />
47
- </Toolbar.Root>
48
- )}
49
- <D3ForceGraph model={model} match={match} />
50
- </StackItem.Content>
51
- );
52
- };
53
-
54
- export default ExplorerContainer;
@@ -1,77 +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 { faker } from '@dxos/random';
9
- import { useClient } from '@dxos/react-client';
10
- import { type Space } from '@dxos/react-client/echo';
11
- import { withClientProvider } from '@dxos/react-client/testing';
12
- import { useAsyncEffect } from '@dxos/react-ui';
13
- import { withTheme } from '@dxos/react-ui/testing';
14
- import { DataType } from '@dxos/schema';
15
- import { type ValueGenerator } from '@dxos/schema/testing';
16
- import { render } from '@dxos/storybook-utils';
17
-
18
- import { useGraphModel } from '../../hooks';
19
- import { Graph } from '../../types';
20
-
21
- import { D3ForceGraph } from './D3ForceGraph';
22
- import { generate } from './testing';
23
-
24
- const generator = faker as any as ValueGenerator;
25
-
26
- faker.seed(1);
27
-
28
- const DefaultStory = () => {
29
- const client = useClient();
30
- const [space, setSpace] = useState<Space>();
31
- const [view, setView] = useState<DataType.View>();
32
-
33
- useAsyncEffect(async () => {
34
- const space = client.spaces.default;
35
- void generate(space, generator);
36
- const { view } = await Graph.makeView({ client, space, name: 'Test', typename: Graph.Graph.typename });
37
- space.db.add(view);
38
- setSpace(space);
39
- setView(view);
40
- }, []);
41
-
42
- const model = useGraphModel(space);
43
- if (!model || !space || !view) {
44
- return null;
45
- }
46
-
47
- return <D3ForceGraph model={model} />;
48
- };
49
-
50
- const meta = {
51
- title: 'plugins/plugin-explorer/D3ForceGraph',
52
- component: D3ForceGraph,
53
- render: render(DefaultStory),
54
- decorators: [
55
- withTheme,
56
- withClientProvider({
57
- createSpace: true,
58
- types: [
59
- Graph.Graph,
60
- DataType.View,
61
- DataType.Organization,
62
- DataType.Project,
63
- DataType.Person,
64
- DataType.HasRelationship,
65
- ],
66
- }),
67
- ],
68
- parameters: {
69
- layout: 'fullscreen',
70
- },
71
- } satisfies Meta<typeof D3ForceGraph>;
72
-
73
- export default meta;
74
-
75
- type Story = StoryObj<typeof meta>;
76
-
77
- export const Default: Story = {};
@@ -1,101 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import React, { useCallback, useEffect, useMemo, useRef } from 'react';
6
-
7
- import { Obj } from '@dxos/echo';
8
- import { SelectionModel } from '@dxos/graph';
9
- import { type ThemedClassName } from '@dxos/react-ui';
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 { getHashStyles } from '@dxos/react-ui-theme';
19
- import { type SpaceGraphEdge, type SpaceGraphModel, type SpaceGraphNode } from '@dxos/schema';
20
-
21
- import '@dxos/react-ui-graph/styles/graph.css';
22
-
23
- export type D3ForceGraphProps = ThemedClassName<
24
- {
25
- model?: SpaceGraphModel;
26
- match?: RegExp;
27
- selection?: SelectionModel;
28
- grid?: boolean;
29
- } & Pick<GraphProps, 'drag'>
30
- >;
31
-
32
- export const D3ForceGraph = ({ classNames, model, selection: _selection, grid, ...props }: D3ForceGraphProps) => {
33
- const context = useRef<SVGContext>(null);
34
- const projector = useMemo<GraphForceProjector | undefined>(() => {
35
- if (context.current) {
36
- return new GraphForceProjector(context.current, {
37
- attributes: {
38
- linkForce: (edge) => {
39
- // TODO(burdon): Check type (currently assumes Employee property).
40
- // Edge shouldn't contribute to force if it's not active.
41
- return edge.data?.object?.active !== false;
42
- },
43
- },
44
- forces: {
45
- point: {
46
- strength: 0.01,
47
- },
48
- },
49
- });
50
- }
51
- }, [context.current]);
52
-
53
- const graph = useRef<GraphController>(null);
54
- const selection = useMemo(() => _selection ?? new SelectionModel(), [_selection]);
55
- useEffect(() => graph.current?.repaint(), [selection.selected.value]);
56
-
57
- const handleSelect = useCallback<NonNullable<GraphProps['onSelect']>>(
58
- (node) => {
59
- if (selection.contains(node.id)) {
60
- selection.remove(node.id);
61
- } else {
62
- selection.add(node.id);
63
- }
64
- },
65
- [selection],
66
- );
67
-
68
- return (
69
- <SVG.Root ref={context} classNames={classNames}>
70
- <SVG.Markers />
71
- {grid && <SVG.Grid axis />}
72
- <SVG.Zoom extent={[1 / 2, 2]}>
73
- <SVG.Graph<SpaceGraphNode, SpaceGraphEdge>
74
- {...props}
75
- ref={graph}
76
- model={model}
77
- projector={projector}
78
- labels={{
79
- text: (node) => {
80
- return node.data?.data.label ?? node.id;
81
- },
82
- }}
83
- attributes={{
84
- node: (node: GraphLayoutNode<SpaceGraphNode>) => {
85
- const obj = node.data?.data.object;
86
- return {
87
- data: {
88
- color: getHashStyles(obj && Obj.getTypename(obj))?.hue,
89
- },
90
- classes: {
91
- 'dx-selected': selection.contains(node.id),
92
- },
93
- };
94
- },
95
- }}
96
- onSelect={handleSelect}
97
- />
98
- </SVG.Zoom>
99
- </SVG.Root>
100
- );
101
- };
@@ -1,55 +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 { DataType } from '@dxos/schema';
8
- import { type TypeSpec, type ValueGenerator, createObjectFactory } from '@dxos/schema/testing';
9
- import { range } from '@dxos/util';
10
-
11
- const getObject = (objects: Obj.Any[]) => objects[Math.floor(Math.random() * objects.length)];
12
-
13
- const defaultTypes: TypeSpec[] = [
14
- { type: DataType.Organization, count: 5 },
15
- { type: DataType.Project, count: 5 },
16
- { type: DataType.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'] = { kind: 'friend', count: 10 };
28
-
29
- /**
30
- * @deprecated Use @dxos/schema.
31
- */
32
- export const generate = async (
33
- space: Space,
34
- generator: ValueGenerator,
35
- { spec = defaultTypes, relations = defaultRelations }: GenerateOptions = {},
36
- ) => {
37
- const createObjects = createObjectFactory(space.db, generator);
38
- await createObjects(spec);
39
-
40
- // Add relations between objects.
41
- const { objects: contacts } = await space.db.query(Query.type(DataType.Person)).run();
42
- for (const _ of range(relations.count)) {
43
- const source = getObject(contacts);
44
- const target = getObject(contacts);
45
- if (source.id !== target.id) {
46
- space.db.add(
47
- Relation.make(DataType.HasRelationship, {
48
- [Relation.Source]: source,
49
- [Relation.Target]: target,
50
- kind: relations.kind,
51
- }),
52
- );
53
- }
54
- }
55
- };
@@ -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;
File without changes