@dxos/plugin-explorer 0.8.0 → 0.8.1-main.ae460ac

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 (49) hide show
  1. package/dist/lib/browser/{ExplorerContainer-GJTCBEM4.mjs → ExplorerContainer-T5CTMBIS.mjs} +2 -2
  2. package/dist/lib/{node-esm/chunk-BRJI3QC2.mjs → browser/chunk-SU3K2HL7.mjs} +240 -3
  3. package/dist/lib/{node-esm/chunk-BRJI3QC2.mjs.map → browser/chunk-SU3K2HL7.mjs.map} +4 -4
  4. package/dist/lib/browser/chunk-V23FAKIX.mjs +205 -0
  5. package/dist/lib/browser/chunk-V23FAKIX.mjs.map +7 -0
  6. package/dist/lib/browser/index.mjs +7 -7
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/{react-surface-3X2V3VPN.mjs → react-surface-Q7OT6GXC.mjs} +3 -3
  9. package/dist/lib/node/{ExplorerContainer-RJT54IOS.cjs → ExplorerContainer-SO5XAXFS.cjs} +6 -6
  10. package/dist/lib/node/chunk-6GTOKVKH.cjs +236 -0
  11. package/dist/lib/node/chunk-6GTOKVKH.cjs.map +7 -0
  12. package/dist/lib/node/{chunk-VSACDC6F.cjs → chunk-CQYBCGC4.cjs} +234 -8
  13. package/dist/lib/node/chunk-CQYBCGC4.cjs.map +7 -0
  14. package/dist/lib/node/index.cjs +10 -10
  15. package/dist/lib/node/meta.json +1 -1
  16. package/dist/lib/node/{react-surface-36YIY7NA.cjs → react-surface-5G52HSJW.cjs} +7 -7
  17. package/dist/lib/node-esm/{ExplorerContainer-TM3VIXVK.mjs → ExplorerContainer-DTUTEZLK.mjs} +2 -2
  18. package/dist/lib/{browser/chunk-S3QNIEBS.mjs → node-esm/chunk-4IST6Y3Z.mjs} +242 -2
  19. package/dist/lib/{browser/chunk-S3QNIEBS.mjs.map → node-esm/chunk-4IST6Y3Z.mjs.map} +4 -4
  20. package/dist/lib/node-esm/chunk-Q2IQDIKJ.mjs +207 -0
  21. package/dist/lib/node-esm/chunk-Q2IQDIKJ.mjs.map +7 -0
  22. package/dist/lib/node-esm/index.mjs +7 -7
  23. package/dist/lib/node-esm/meta.json +1 -1
  24. package/dist/lib/node-esm/{react-surface-YDY7IBMY.mjs → react-surface-QSQVINGP.mjs} +3 -3
  25. package/dist/types/src/components/Graph/Graph.d.ts +0 -3
  26. package/dist/types/src/components/Graph/Graph.d.ts.map +1 -1
  27. package/dist/types/src/components/Graph/Graph.stories.d.ts +1 -1
  28. package/dist/types/src/components/Graph/Graph.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/Graph/graph-model.d.ts.map +1 -1
  30. package/dist/types/src/components/Tree/types.d.ts +1 -1
  31. package/dist/types/src/components/Tree/types.d.ts.map +1 -1
  32. package/package.json +24 -25
  33. package/src/components/Graph/Graph.stories.tsx +2 -2
  34. package/src/components/Graph/Graph.tsx +15 -142
  35. package/src/components/Graph/graph-model.ts +2 -0
  36. package/src/components/Tree/types.ts +2 -1
  37. package/dist/lib/browser/chunk-YQL7YE6N.mjs +0 -546
  38. package/dist/lib/browser/chunk-YQL7YE6N.mjs.map +0 -7
  39. package/dist/lib/node/chunk-VSACDC6F.cjs.map +0 -7
  40. package/dist/lib/node/chunk-YH4QYCZH.cjs +0 -567
  41. package/dist/lib/node/chunk-YH4QYCZH.cjs.map +0 -7
  42. package/dist/lib/node-esm/chunk-3KRWHGBM.mjs +0 -548
  43. package/dist/lib/node-esm/chunk-3KRWHGBM.mjs.map +0 -7
  44. /package/dist/lib/browser/{ExplorerContainer-GJTCBEM4.mjs.map → ExplorerContainer-T5CTMBIS.mjs.map} +0 -0
  45. /package/dist/lib/browser/{react-surface-3X2V3VPN.mjs.map → react-surface-Q7OT6GXC.mjs.map} +0 -0
  46. /package/dist/lib/node/{ExplorerContainer-RJT54IOS.cjs.map → ExplorerContainer-SO5XAXFS.cjs.map} +0 -0
  47. /package/dist/lib/node/{react-surface-36YIY7NA.cjs.map → react-surface-5G52HSJW.cjs.map} +0 -0
  48. /package/dist/lib/node-esm/{ExplorerContainer-TM3VIXVK.mjs.map → ExplorerContainer-DTUTEZLK.mjs.map} +0 -0
  49. /package/dist/lib/node-esm/{react-surface-YDY7IBMY.mjs.map → react-surface-QSQVINGP.mjs.map} +0 -0
@@ -47,8 +47,6 @@ const Story = () => {
47
47
  return <Graph space={space} />;
48
48
  };
49
49
 
50
- export const Default = {};
51
-
52
50
  const meta: Meta = {
53
51
  title: 'plugins/plugin-explorer/Graph',
54
52
  component: Graph,
@@ -60,3 +58,5 @@ const meta: Meta = {
60
58
  };
61
59
 
62
60
  export default meta;
61
+
62
+ export const Default = {};
@@ -4,100 +4,36 @@
4
4
 
5
5
  import { forceLink, forceManyBody } from 'd3';
6
6
  import ForceGraph from 'force-graph';
7
- import React, { type FC, useEffect, useMemo, useRef, useState } from 'react';
7
+ import React, { type FC, useEffect, useRef } from 'react';
8
8
  import { useResizeDetector } from 'react-resize-detector';
9
9
 
10
- import { getTypename, type ReactiveEchoObject, type Space } from '@dxos/client/echo';
11
- import { createSvgContext, defaultGridStyles, Grid, SVG, SVGRoot, Zoom } from '@dxos/gem-core';
12
- import {
13
- defaultStyles,
14
- Graph as GraphComponent,
15
- GraphForceProjector,
16
- type GraphLayoutNode,
17
- Markers,
18
- } from '@dxos/gem-spore';
10
+ import { type Space } from '@dxos/client/echo';
19
11
  import { filterObjectsSync, type SearchResult } from '@dxos/plugin-search';
20
- import { useAsyncState, useThemeContext } from '@dxos/react-ui';
21
- import { mx } from '@dxos/react-ui-theme';
22
- import '@dxos/gem-spore/styles';
12
+ import { useAsyncState } from '@dxos/react-ui';
23
13
 
24
- import { type EchoGraphNode, SpaceGraphModel } from './graph-model';
25
- import { Tree } from '../Tree';
26
-
27
- type Slots = {
28
- root?: { className?: string };
29
- grid?: { className?: string };
30
- };
31
-
32
- const slots: Slots = {};
33
-
34
- const colors = [
35
- '[&>circle]:!fill-black-300 [&>circle]:!stroke-black-600',
36
- '[&>circle]:!fill-slate-300 [&>circle]:!stroke-slate-600',
37
- '[&>circle]:!fill-green-300 [&>circle]:!stroke-green-600',
38
- '[&>circle]:!fill-sky-300 [&>circle]:!stroke-sky-600',
39
- '[&>circle]:!fill-cyan-300 [&>circle]:!stroke-cyan-600',
40
- '[&>circle]:!fill-rose-300 [&>circle]:!stroke-rose-600',
41
- '[&>circle]:!fill-purple-300 [&>circle]:!stroke-purple-600',
42
- '[&>circle]:!fill-orange-300 [&>circle]:!stroke-orange-600',
43
- '[&>circle]:!fill-teal-300 [&>circle]:!stroke-teal-600',
44
- '[&>circle]:!fill-indigo-300 [&>circle]:!stroke-indigo-600',
45
- ];
14
+ import { SpaceGraphModel } from './graph-model';
46
15
 
47
16
  export type GraphProps = {
48
17
  space: Space;
49
18
  match?: RegExp;
50
- grid?: boolean;
51
- svg?: boolean;
52
19
  };
53
20
 
54
- export const Graph: FC<GraphProps> = ({ space, match, grid, svg }) => {
55
- const { themeMode } = useThemeContext();
56
- const [selected, setSelected] = useState<string>();
21
+ export const Graph: FC<GraphProps> = ({ space, match }) => {
22
+ const { ref, width, height } = useResizeDetector({ refreshRate: 200 });
23
+ const rootRef = useRef<HTMLDivElement>(null);
24
+ const forceGraph = useRef<ForceGraph>();
57
25
 
58
26
  const [model] = useAsyncState(
59
27
  async () => (space ? new SpaceGraphModel({ schema: true }).open(space) : undefined),
60
28
  [space],
61
29
  );
62
30
 
63
- const context = createSvgContext();
64
- const projector = useMemo(
65
- () =>
66
- new GraphForceProjector<EchoGraphNode>(context, {
67
- forces: {
68
- manyBody: {
69
- strength: -100,
70
- },
71
- link: {
72
- distance: 100,
73
- },
74
- radial: {
75
- radius: 150,
76
- strength: 0.05,
77
- },
78
- },
79
- attributes: {
80
- radius: (node: GraphLayoutNode<EchoGraphNode>) => (node.data?.type === 'schema' ? 12 : 8),
81
- },
82
- }),
83
- [],
84
- );
85
-
86
31
  const filteredRef = useRef<SearchResult[]>();
87
32
  filteredRef.current = filterObjectsSync(model?.objects ?? [], match);
88
- useEffect(() => {
89
- void projector.start();
90
- }, [match]);
91
-
92
- const [colorMap] = useState(new Map<string, string>());
93
-
94
- // https://github.com/vasturiano/force-graph
95
- const { ref, width, height } = useResizeDetector();
96
- const rootRef = useRef<HTMLDivElement>(null);
97
- const forceGraph = useRef<ForceGraph>();
98
33
 
99
34
  useEffect(() => {
100
35
  if (rootRef.current) {
36
+ // https://github.com/vasturiano/force-graph
101
37
  forceGraph.current = new ForceGraph(rootRef.current)
102
38
  .nodeRelSize(6)
103
39
  .nodeLabel((node: any) => {
@@ -117,7 +53,6 @@ export const Graph: FC<GraphProps> = ({ space, match, grid, svg }) => {
117
53
  };
118
54
  }, []);
119
55
 
120
- // Update.
121
56
  useEffect(() => {
122
57
  if (forceGraph.current && width && height && model) {
123
58
  forceGraph.current
@@ -125,7 +60,7 @@ export const Graph: FC<GraphProps> = ({ space, match, grid, svg }) => {
125
60
  .width(width)
126
61
  .height(height)
127
62
  .onEngineStop(() => {
128
- forceGraph.current?.zoomToFit(400, 40);
63
+ handleZoomToFit();
129
64
  })
130
65
 
131
66
  // https://github.com/vasturiano/force-graph?tab=readme-ov-file#force-engine-d3-force-configuration
@@ -134,11 +69,10 @@ export const Graph: FC<GraphProps> = ({ space, match, grid, svg }) => {
134
69
  .d3Force('charge', forceManyBody().strength(-30))
135
70
  // .d3AlphaDecay(0.0228)
136
71
  // .d3VelocityDecay(0.4)
137
- .warmupTicks(100)
138
- // .cooldownTime(1000)
139
72
 
140
- //
141
73
  .graphData(model.graph)
74
+ .warmupTicks(100)
75
+ .cooldownTime(1000)
142
76
  .resumeAnimation();
143
77
  }
144
78
  }, [model, width, height]);
@@ -147,70 +81,9 @@ export const Graph: FC<GraphProps> = ({ space, match, grid, svg }) => {
147
81
  forceGraph.current?.zoomToFit(400, 40);
148
82
  };
149
83
 
150
- if (!svg) {
151
- return (
152
- <div ref={ref} className='relative grow' onClick={handleZoomToFit}>
153
- <div ref={rootRef} className='absolute inset-0' />
154
- </div>
155
- );
156
- }
157
-
158
- if (selected) {
159
- return <Tree space={space} selected={selected} variant='tidy' onNodeClick={() => setSelected(undefined)} />;
160
- }
161
-
162
84
  return (
163
- <SVGRoot context={context}>
164
- <SVG className={mx(defaultStyles, slots?.root?.className)}>
165
- <Markers arrowSize={6} />
166
- {grid && <Grid className={slots?.grid?.className ?? defaultGridStyles(themeMode)} />}
167
- <Zoom extent={[1 / 2, 4]}>
168
- <GraphComponent
169
- model={model}
170
- projector={projector}
171
- drag
172
- arrows
173
- onSelect={(node) => setSelected(node?.data?.id)}
174
- labels={{
175
- text: (node: GraphLayoutNode<ReactiveEchoObject<any>>) => {
176
- if (filteredRef.current?.length && !filteredRef.current.some((object) => object.id === node.data?.id)) {
177
- return undefined;
178
- }
179
-
180
- // TODO(burdon): Use schema.
181
- return node.data?.label ?? node.data?.title ?? node.data?.name ?? node.data?.id.slice(0, 8);
182
- },
183
- }}
184
- attributes={{
185
- node: (node: GraphLayoutNode<ReactiveEchoObject<any>>) => {
186
- let className: string | undefined;
187
- if (node.data) {
188
- const { object } = node.data;
189
- if (object) {
190
- const typename = getTypename(object);
191
- if (typename) {
192
- className = colorMap.get(typename);
193
- if (!className) {
194
- className = colors[colorMap.size % colors.length];
195
- colorMap.set(typename, className);
196
- }
197
- }
198
- }
199
- }
200
-
201
- const selected = filteredRef.current?.some((object) => object.id === node.data?.id);
202
- const blur = !selected && !!filteredRef.current?.length;
203
- return {
204
- class: mx(className, blur && 'opacity-70'),
205
- };
206
- },
207
- link: () => ({
208
- class: '[&>path]:!stroke-neutral-300 dark:[&>path]:!stroke-neutral-700',
209
- }),
210
- }}
211
- />
212
- </Zoom>
213
- </SVG>
214
- </SVGRoot>
85
+ <div ref={ref} className='relative grow' onClick={handleZoomToFit}>
86
+ <div ref={rootRef} className='absolute inset-0' />
87
+ </div>
215
88
  );
216
89
  };
@@ -21,6 +21,8 @@ export type SpaceGraphModelOptions = {
21
21
  schema?: boolean;
22
22
  };
23
23
 
24
+ // TODO(burdon): Convert to common/graph.
25
+
24
26
  type SchemaGraphNode = {
25
27
  id: string;
26
28
  type: 'schema';
@@ -2,7 +2,8 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import type { GraphModel } from '@dxos/gem-spore';
5
+ // TODO(burdon): Convert to common/graph.
6
+ import { type GraphModel } from '@dxos/gem-spore';
6
7
 
7
8
  export type TreeNode = {
8
9
  id: string;