@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.
- package/dist/lib/browser/{ExplorerContainer-GJTCBEM4.mjs → ExplorerContainer-T5CTMBIS.mjs} +2 -2
- package/dist/lib/{node-esm/chunk-BRJI3QC2.mjs → browser/chunk-SU3K2HL7.mjs} +240 -3
- package/dist/lib/{node-esm/chunk-BRJI3QC2.mjs.map → browser/chunk-SU3K2HL7.mjs.map} +4 -4
- package/dist/lib/browser/chunk-V23FAKIX.mjs +205 -0
- package/dist/lib/browser/chunk-V23FAKIX.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +7 -7
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-3X2V3VPN.mjs → react-surface-Q7OT6GXC.mjs} +3 -3
- package/dist/lib/node/{ExplorerContainer-RJT54IOS.cjs → ExplorerContainer-SO5XAXFS.cjs} +6 -6
- package/dist/lib/node/chunk-6GTOKVKH.cjs +236 -0
- package/dist/lib/node/chunk-6GTOKVKH.cjs.map +7 -0
- package/dist/lib/node/{chunk-VSACDC6F.cjs → chunk-CQYBCGC4.cjs} +234 -8
- package/dist/lib/node/chunk-CQYBCGC4.cjs.map +7 -0
- package/dist/lib/node/index.cjs +10 -10
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/{react-surface-36YIY7NA.cjs → react-surface-5G52HSJW.cjs} +7 -7
- package/dist/lib/node-esm/{ExplorerContainer-TM3VIXVK.mjs → ExplorerContainer-DTUTEZLK.mjs} +2 -2
- package/dist/lib/{browser/chunk-S3QNIEBS.mjs → node-esm/chunk-4IST6Y3Z.mjs} +242 -2
- package/dist/lib/{browser/chunk-S3QNIEBS.mjs.map → node-esm/chunk-4IST6Y3Z.mjs.map} +4 -4
- package/dist/lib/node-esm/chunk-Q2IQDIKJ.mjs +207 -0
- package/dist/lib/node-esm/chunk-Q2IQDIKJ.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +7 -7
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-YDY7IBMY.mjs → react-surface-QSQVINGP.mjs} +3 -3
- package/dist/types/src/components/Graph/Graph.d.ts +0 -3
- package/dist/types/src/components/Graph/Graph.d.ts.map +1 -1
- package/dist/types/src/components/Graph/Graph.stories.d.ts +1 -1
- package/dist/types/src/components/Graph/Graph.stories.d.ts.map +1 -1
- package/dist/types/src/components/Graph/graph-model.d.ts.map +1 -1
- package/dist/types/src/components/Tree/types.d.ts +1 -1
- package/dist/types/src/components/Tree/types.d.ts.map +1 -1
- package/package.json +24 -25
- package/src/components/Graph/Graph.stories.tsx +2 -2
- package/src/components/Graph/Graph.tsx +15 -142
- package/src/components/Graph/graph-model.ts +2 -0
- package/src/components/Tree/types.ts +2 -1
- package/dist/lib/browser/chunk-YQL7YE6N.mjs +0 -546
- package/dist/lib/browser/chunk-YQL7YE6N.mjs.map +0 -7
- package/dist/lib/node/chunk-VSACDC6F.cjs.map +0 -7
- package/dist/lib/node/chunk-YH4QYCZH.cjs +0 -567
- package/dist/lib/node/chunk-YH4QYCZH.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-3KRWHGBM.mjs +0 -548
- package/dist/lib/node-esm/chunk-3KRWHGBM.mjs.map +0 -7
- /package/dist/lib/browser/{ExplorerContainer-GJTCBEM4.mjs.map → ExplorerContainer-T5CTMBIS.mjs.map} +0 -0
- /package/dist/lib/browser/{react-surface-3X2V3VPN.mjs.map → react-surface-Q7OT6GXC.mjs.map} +0 -0
- /package/dist/lib/node/{ExplorerContainer-RJT54IOS.cjs.map → ExplorerContainer-SO5XAXFS.cjs.map} +0 -0
- /package/dist/lib/node/{react-surface-36YIY7NA.cjs.map → react-surface-5G52HSJW.cjs.map} +0 -0
- /package/dist/lib/node-esm/{ExplorerContainer-TM3VIXVK.mjs.map → ExplorerContainer-DTUTEZLK.mjs.map} +0 -0
- /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,
|
|
7
|
+
import React, { type FC, useEffect, useRef } from 'react';
|
|
8
8
|
import { useResizeDetector } from 'react-resize-detector';
|
|
9
9
|
|
|
10
|
-
import {
|
|
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
|
|
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 {
|
|
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
|
|
55
|
-
const {
|
|
56
|
-
const
|
|
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
|
-
|
|
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
|
-
<
|
|
164
|
-
<
|
|
165
|
-
|
|
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
|
};
|