@fusion.dev/helix-graph 0.214.0 → 0.215.1
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/README.md +12 -5
- package/dist/overlay/overlay.d.ts +4 -2
- package/dist/overlay/overlay.js +2 -2
- package/dist/sigma/edge-program.d.ts +14 -77
- package/dist/sigma/edge-program.js +36 -306
- package/dist/sigma/index.d.ts +2 -1
- package/dist/sigma/index.js +1 -1
- package/dist/sigma/node-program.d.ts +19 -49
- package/dist/sigma/node-program.js +65 -155
- package/dist/sigma/sigma-driver.d.ts +28 -8
- package/dist/sigma/sigma-driver.js +142 -135
- package/dist/sigma/sigma-options.d.ts +72 -0
- package/dist/sigma/sigma-options.js +36 -0
- package/package.json +11 -7
|
@@ -1,81 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { rgbOf } from '../connect-graph/looks.js';
|
|
2
2
|
import { pixelsOf } from '../connect-graph/sizes.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
'defaultDrawNodeLabel',
|
|
9
|
-
'defaultEdgeType',
|
|
10
|
-
'edgeProgramClasses',
|
|
11
|
-
'edgeReducer',
|
|
12
|
-
'enableCameraPanning',
|
|
13
|
-
'enableCameraZooming',
|
|
14
|
-
'labelColor',
|
|
15
|
-
'labelFont',
|
|
16
|
-
'labelGridCellSize',
|
|
17
|
-
'labelRenderedSizeThreshold',
|
|
18
|
-
'labelSize',
|
|
19
|
-
'minEdgeThickness',
|
|
20
|
-
'nodeProgramClasses',
|
|
21
|
-
'nodeReducer',
|
|
22
|
-
];
|
|
3
|
+
import { ease, gesturesHeld, groupsOver, namesOver, signalsOver, } from '../overlay/overlay.js';
|
|
4
|
+
import { SPREAD } from './edge-program.js';
|
|
5
|
+
import { DIAMOND, EMPHASES, MATERIALS, SHAPES } from './node-program.js';
|
|
6
|
+
import { reducersOf } from './sigma-options.js';
|
|
7
|
+
const SETTINGS = ['enableCameraPanning', 'enableCameraZooming'];
|
|
23
8
|
const STEP = 250;
|
|
24
9
|
const ZOOM = 1.5;
|
|
25
10
|
const SAMPLE = 250;
|
|
26
11
|
const STILL = 0.004;
|
|
27
12
|
const HELD = 2;
|
|
28
13
|
const IDLE = 2000;
|
|
29
|
-
const hoverOf = (looks, rightToLeft) => (context, data, settings) => {
|
|
30
|
-
if (!data.label) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
const size = settings.labelSize;
|
|
34
|
-
context.font = `${settings.labelWeight} ${size}px ${settings.labelFont}`;
|
|
35
|
-
const width = context.measureText(data.label).width;
|
|
36
|
-
const x = rightToLeft() ? data.x - data.size - 2 - width : data.x + data.size + 2;
|
|
37
|
-
const height = size + 8;
|
|
38
|
-
context.save();
|
|
39
|
-
context.shadowBlur = 8;
|
|
40
|
-
context.shadowColor = 'rgba(0, 0, 0, 0.25)';
|
|
41
|
-
context.fillStyle = looks.overlay;
|
|
42
|
-
context.beginPath();
|
|
43
|
-
context.roundRect(x - 4, data.y - height / 2, width + 8, height, 4);
|
|
44
|
-
context.fill();
|
|
45
|
-
context.restore();
|
|
46
|
-
context.fillStyle = looks.ink;
|
|
47
|
-
context.textAlign = 'left';
|
|
48
|
-
context.fillText(data.label, x, data.y + size / 3);
|
|
49
|
-
};
|
|
50
14
|
const GROW = 300;
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
const strong = data.strong === true;
|
|
56
|
-
const size = strong ? settings.labelSize : settings.labelSize - 1;
|
|
57
|
-
context.font = `${strong ? 600 : 500} ${size}px ${settings.labelFont}`;
|
|
58
|
-
const width = context.measureText(data.label).width;
|
|
59
|
-
const y = data.y + size / 3;
|
|
60
|
-
const boxAt = (from) => ({
|
|
61
|
-
bottom: y + 4,
|
|
62
|
-
left: from - 2,
|
|
63
|
-
right: from + width + 2,
|
|
64
|
-
top: y - size,
|
|
65
|
-
});
|
|
66
|
-
const x = start({ radius: data.size, x: data.x }, width, boxAt);
|
|
67
|
-
const box = boxAt(x);
|
|
68
|
-
if (!claim(box, data.forceLabel === true)) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
context.lineJoin = 'round';
|
|
72
|
-
context.lineWidth = 3;
|
|
73
|
-
context.strokeStyle = looks.ground;
|
|
74
|
-
context.textAlign = 'left';
|
|
75
|
-
context.strokeText(data.label, x, y);
|
|
76
|
-
context.fillStyle = strong ? looks.ink : looks.quiet;
|
|
77
|
-
context.fillText(data.label, x, y);
|
|
15
|
+
const faded = (color, opacity) => {
|
|
16
|
+
const [red, green, blue] = rgbOf(color);
|
|
17
|
+
return `rgba(${red}, ${green}, ${blue}, ${opacity})`;
|
|
78
18
|
};
|
|
19
|
+
const devicePixels = () => typeof devicePixelRatio === 'number' && devicePixelRatio > 0 ? devicePixelRatio : 1;
|
|
20
|
+
const cellOf = (labels) => (labels === 'all' ? 8 : 130);
|
|
79
21
|
const HUB = 6.5;
|
|
80
22
|
const positionsOf = (graph) => {
|
|
81
23
|
const positions = new Map();
|
|
@@ -84,16 +26,47 @@ const positionsOf = (graph) => {
|
|
|
84
26
|
});
|
|
85
27
|
return positions;
|
|
86
28
|
};
|
|
29
|
+
export const namedOf = (graph, looks, labels, hovered, onScreen) => {
|
|
30
|
+
const asked = [];
|
|
31
|
+
graph.forEachNode((id, attributes) => {
|
|
32
|
+
const look = looks.node(id);
|
|
33
|
+
const size = Number(attributes.size);
|
|
34
|
+
const must = look.label === 'always' || id === hovered || look.keyed === true;
|
|
35
|
+
const named = must ||
|
|
36
|
+
(look.label === 'room' &&
|
|
37
|
+
(look.raised || labels === 'all' || (labels === 'hubs' && size >= HUB)));
|
|
38
|
+
const name = attributes.label;
|
|
39
|
+
if (!named || typeof name !== 'string' || name === '') {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const at = onScreen(id);
|
|
43
|
+
if (at) {
|
|
44
|
+
asked.push({ id, must, name, size, strong: must || look.raised, x: at.x, y: at.y });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
asked.sort((one, other) => Number(other.must) - Number(one.must) || other.size - one.size);
|
|
48
|
+
const cell = cellOf(labels);
|
|
49
|
+
const cells = new Set();
|
|
50
|
+
return asked.flatMap(({ id, must, name, strong, x, y }) => {
|
|
51
|
+
const at = `${Math.floor(x / cell)}:${Math.floor(y / cell)}`;
|
|
52
|
+
if (!must) {
|
|
53
|
+
if (cells.has(at)) {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
cells.add(at);
|
|
57
|
+
}
|
|
58
|
+
return [{ id, must, name, strong }];
|
|
59
|
+
});
|
|
60
|
+
};
|
|
87
61
|
export const sigmaDriver = (sigma, options = {}) => {
|
|
62
|
+
const reducers = reducersOf(sigma);
|
|
63
|
+
if (!reducers) {
|
|
64
|
+
throw new TypeError('sigmaDriver: make the renderer with sigmaOptions(), as new Sigma(graph, box, sigmaOptions()). Sigma 4 takes its programs only when it is made.');
|
|
65
|
+
}
|
|
88
66
|
const graph = sigma.getGraph();
|
|
89
67
|
const container = sigma.getContainer();
|
|
90
68
|
const camera = sigma.getCamera();
|
|
91
69
|
const before = new Map(SETTINGS.map((name) => [name, sigma.getSetting(name)]));
|
|
92
|
-
const programs = before.get('nodeProgramClasses');
|
|
93
|
-
sigma.setSetting('nodeProgramClasses', { ...programs, helix: HelixNodeProgram });
|
|
94
|
-
const edgePrograms = before.get('edgeProgramClasses');
|
|
95
|
-
sigma.setSetting('edgeProgramClasses', { ...edgePrograms, helix: HelixEdgeProgram });
|
|
96
|
-
sigma.setSetting('defaultEdgeType', 'helix');
|
|
97
70
|
const sized = typeof ResizeObserver === 'function'
|
|
98
71
|
? new ResizeObserver(() => {
|
|
99
72
|
sigma.resize(true);
|
|
@@ -122,32 +95,36 @@ export const sigmaDriver = (sigma, options = {}) => {
|
|
|
122
95
|
sigma.on('enterNode', enter);
|
|
123
96
|
sigma.on('leaveNode', leave);
|
|
124
97
|
const naming = options.labels ?? 'hover';
|
|
125
|
-
let taken = [];
|
|
126
|
-
const claim = (box, must) => {
|
|
127
|
-
const free = clearOf(box, taken);
|
|
128
|
-
if (free || must) {
|
|
129
|
-
taken.push(box);
|
|
130
|
-
}
|
|
131
|
-
return free || must;
|
|
132
|
-
};
|
|
133
|
-
let rightToLeft = false;
|
|
134
|
-
const clear = () => {
|
|
135
|
-
taken = chromeOver(container);
|
|
136
|
-
rightToLeft = isRtl(container);
|
|
137
|
-
};
|
|
138
|
-
sigma.on('beforeRender', clear);
|
|
139
98
|
const held = gesturesHeld(container);
|
|
140
99
|
const onScreen = (id) => {
|
|
141
100
|
const data = sigma.getNodeDisplayData(id);
|
|
142
|
-
if (!data || data.hidden) {
|
|
101
|
+
if (!data || data.visibility === 'hidden') {
|
|
143
102
|
return undefined;
|
|
144
103
|
}
|
|
145
104
|
const at = sigma.framedGraphToViewport(data);
|
|
146
105
|
return { radius: sigma.scaleSize(data.size), x: at.x, y: at.y };
|
|
147
106
|
};
|
|
148
107
|
const signals = signalsOver(container, onScreen);
|
|
149
|
-
const
|
|
150
|
-
|
|
108
|
+
const names = namesOver(container, onScreen);
|
|
109
|
+
let looks;
|
|
110
|
+
const drawNames = () => {
|
|
111
|
+
if (looks) {
|
|
112
|
+
names.draw(looks, namedOf(graph, looks, naming, hovered, onScreen));
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const groups = groupsOver(container, onScreen, () => names.boxes());
|
|
116
|
+
const redraw = () => {
|
|
117
|
+
drawNames();
|
|
118
|
+
groups.draw();
|
|
119
|
+
};
|
|
120
|
+
sigma.on('afterRender', redraw);
|
|
121
|
+
const ringed = new Set();
|
|
122
|
+
const rezoomed = () => {
|
|
123
|
+
if (ringed.size > 0) {
|
|
124
|
+
sigma.refresh({ partialGraph: { nodes: [...ringed].filter((id) => graph.hasNode(id)) } });
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
camera.on('updated', rezoomed);
|
|
151
128
|
let gliding = 0;
|
|
152
129
|
const glide = (sizes, moves) => {
|
|
153
130
|
cancelAnimationFrame(gliding);
|
|
@@ -242,58 +219,84 @@ export const sigmaDriver = (sigma, options = {}) => {
|
|
|
242
219
|
groups.set(next);
|
|
243
220
|
}
|
|
244
221
|
},
|
|
245
|
-
look: (
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
sigma.setSetting('defaultDrawNodeLabel', labelOf(looks, claim, (at, width, box) => nameStart(at, width, box, taken, container.clientWidth, rightToLeft)));
|
|
255
|
-
sigma.setSetting('defaultDrawNodeHover', hoverOf(looks, () => rightToLeft));
|
|
256
|
-
sigma.setSetting('nodeReducer', (node, data) => {
|
|
257
|
-
const look = looks.node(node);
|
|
222
|
+
look: (next) => {
|
|
223
|
+
looks = next;
|
|
224
|
+
signals.look(next);
|
|
225
|
+
groups.look(next);
|
|
226
|
+
reducers.node = (node, attributes) => {
|
|
227
|
+
const look = next.node(node);
|
|
228
|
+
const density = devicePixels();
|
|
229
|
+
const shape = look.shape ?? options.shape ?? 'circle';
|
|
230
|
+
const material = look.material ?? options.material ?? 'flat';
|
|
258
231
|
const grown = look.selected ? 1.5 : look.raised ? 1.25 : 1;
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
232
|
+
const size = Number(attributes.size) * grown;
|
|
233
|
+
const radius = sigma.scaleSize(size) * density;
|
|
234
|
+
const glow = look.glow > 0
|
|
235
|
+
? {
|
|
236
|
+
backdropBorderColor: faded(look.color, 0.8 * look.glow),
|
|
237
|
+
backdropBorderWidth: Math.max(radius * 0.14, 1.5 * density),
|
|
238
|
+
backdropColor: next.ground,
|
|
239
|
+
backdropPadding: radius * 0.32 + Math.max(radius * 0.07, 0.75 * density),
|
|
240
|
+
backdropShadowBlur: radius * 2,
|
|
241
|
+
backdropShadowColor: faded(look.color, 0.6 * look.glow),
|
|
242
|
+
backdropVisibility: 'visible',
|
|
243
|
+
}
|
|
244
|
+
: material === 'mark'
|
|
245
|
+
? {
|
|
246
|
+
backdropBorderWidth: 0,
|
|
247
|
+
backdropColor: faded(look.color, 0.22),
|
|
248
|
+
backdropPadding: radius * 0.4,
|
|
249
|
+
backdropShadowBlur: radius * 0.9,
|
|
250
|
+
backdropShadowColor: faded(look.color, 0.3),
|
|
251
|
+
backdropVisibility: 'visible',
|
|
252
|
+
}
|
|
253
|
+
: { backdropVisibility: 'hidden' };
|
|
254
|
+
const keyed = look.keyed === true
|
|
255
|
+
? {
|
|
256
|
+
backdropBorderColor: next.ink,
|
|
257
|
+
backdropBorderWidth: 2 * density,
|
|
258
|
+
backdropColor: next.ground,
|
|
259
|
+
backdropPadding: Math.max(radius * 0.32, 3 * density),
|
|
260
|
+
backdropVisibility: 'visible',
|
|
261
|
+
}
|
|
262
|
+
: {};
|
|
263
|
+
if (glow.backdropVisibility === 'visible' || look.keyed === true) {
|
|
264
|
+
ringed.add(node);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
ringed.delete(node);
|
|
268
|
+
}
|
|
264
269
|
return {
|
|
265
|
-
...
|
|
270
|
+
...glow,
|
|
271
|
+
...keyed,
|
|
272
|
+
backdropArea: 'node',
|
|
266
273
|
color: look.color,
|
|
267
|
-
emphasisCode:
|
|
268
|
-
|
|
274
|
+
emphasisCode: shape === 'ring'
|
|
275
|
+
? EMPHASES.outlined
|
|
276
|
+
: EMPHASES[look.emphasis ?? options.emphasis ?? 'solid'],
|
|
269
277
|
glow: look.glow,
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
shapeCode: SHAPES[look.shape ?? options.shape ?? 'circle'],
|
|
275
|
-
size: typeof data.size === 'number' ? data.size * grown : data.size,
|
|
276
|
-
strong: look.selected || look.raised,
|
|
277
|
-
type: 'helix',
|
|
278
|
+
materialCode: MATERIALS[material],
|
|
279
|
+
shape: SHAPES[shape],
|
|
280
|
+
size: shape === 'diamond' ? size * DIAMOND : size,
|
|
281
|
+
visibility: look.hidden ? 'hidden' : 'visible',
|
|
278
282
|
zIndex: look.selected ? 2 : look.raised ? 1 : 0,
|
|
279
283
|
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const look =
|
|
283
|
-
const near = hovered ??
|
|
284
|
-
const lit = near !== undefined && (
|
|
284
|
+
};
|
|
285
|
+
reducers.edge = (_edge, attributes) => {
|
|
286
|
+
const look = next.link(String(attributes.from), String(attributes.to));
|
|
287
|
+
const near = hovered ?? next.keyed;
|
|
288
|
+
const lit = near !== undefined && (attributes.from === near || attributes.to === near);
|
|
285
289
|
const strong = look.raised || lit;
|
|
286
290
|
return {
|
|
287
|
-
|
|
288
|
-
|
|
291
|
+
color: lit ? next.node(near).color : look.color,
|
|
292
|
+
depth: strong ? 'topEdges' : 'edges',
|
|
289
293
|
glow: strong ? 1 : 0,
|
|
290
|
-
|
|
291
|
-
size: strong ?
|
|
292
|
-
|
|
293
|
-
type: 'helix',
|
|
294
|
+
head: strong && next.node(String(attributes.to)).glow === 0 ? 'arrow' : 'none',
|
|
295
|
+
size: strong ? 2.6 * SPREAD : 1.6,
|
|
296
|
+
visibility: look.hidden ? 'hidden' : 'visible',
|
|
294
297
|
zIndex: strong ? 1 : 0,
|
|
295
298
|
};
|
|
296
|
-
}
|
|
299
|
+
};
|
|
297
300
|
sigma.refresh();
|
|
298
301
|
},
|
|
299
302
|
onPress: (press) => {
|
|
@@ -320,19 +323,23 @@ export const sigmaDriver = (sigma, options = {}) => {
|
|
|
320
323
|
signals.signal(from, to, colors, animate);
|
|
321
324
|
},
|
|
322
325
|
stop: () => {
|
|
323
|
-
sigma.off('afterRender',
|
|
324
|
-
|
|
326
|
+
sigma.off('afterRender', redraw);
|
|
327
|
+
camera.off('updated', rezoomed);
|
|
328
|
+
names.stop();
|
|
325
329
|
groups.stop();
|
|
326
330
|
signals.stop();
|
|
327
331
|
sigma.off('enterNode', enter);
|
|
328
332
|
sigma.off('leaveNode', leave);
|
|
329
333
|
cancelAnimationFrame(gliding);
|
|
330
334
|
container.style.cursor = cursor;
|
|
335
|
+
reducers.edge = undefined;
|
|
336
|
+
reducers.node = undefined;
|
|
331
337
|
for (const [name, value] of before) {
|
|
332
|
-
sigma.setSetting(name, value);
|
|
338
|
+
sigma.setSetting(name, value !== false);
|
|
333
339
|
}
|
|
334
340
|
sized?.disconnect();
|
|
335
341
|
held.stop();
|
|
342
|
+
sigma.refresh();
|
|
336
343
|
},
|
|
337
344
|
update: (changes, animate) => {
|
|
338
345
|
for (const id of changes.removeNodes) {
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** What a reducer adds to a note's or a link's display data, by its key and its attributes. */
|
|
2
|
+
export type Reduce = (key: string, attributes: Record<string, unknown>) => Record<string, unknown>;
|
|
3
|
+
/** The reducers a driver puts in place, which the renderer's own call through to. */
|
|
4
|
+
export interface Reducers {
|
|
5
|
+
edge?: Reduce | undefined;
|
|
6
|
+
node?: Reduce | undefined;
|
|
7
|
+
}
|
|
8
|
+
/** The reducers of a renderer made with `sigmaOptions()`, or nothing for one made without. */
|
|
9
|
+
export declare const reducersOf: (sigma: {
|
|
10
|
+
getPrimitives(): {
|
|
11
|
+
nodes?: object | undefined;
|
|
12
|
+
};
|
|
13
|
+
}) => Reducers | undefined;
|
|
14
|
+
/** What `sigmaOptions` takes. */
|
|
15
|
+
export interface SigmaOptionsOverrides {
|
|
16
|
+
/** Sigma's settings, over the ones Helix sets. */
|
|
17
|
+
settings?: Record<string, unknown> | undefined;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The options to make a Sigma renderer with for `sigmaDriver`: Helix's
|
|
21
|
+
* programs for the notes and the links, and the reducers the driver draws
|
|
22
|
+
* them through.
|
|
23
|
+
*
|
|
24
|
+
* ```js
|
|
25
|
+
* const sigma = new Sigma(new Graph(), box, sigmaOptions())
|
|
26
|
+
* connectGraph(frame, sigmaDriver(sigma, { layout }))
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* **Sigma draws no names**: the driver names notes over the drawing, as it
|
|
30
|
+
* names groups, so a name keeps clear of the frame's controls and of the
|
|
31
|
+
* names beside it. `settings` are Sigma's own, over the ones set here.
|
|
32
|
+
*/
|
|
33
|
+
export declare const sigmaOptions: (overrides?: SigmaOptionsOverrides) => {
|
|
34
|
+
readonly edgeReducer: (edge: string, _data: unknown, attributes: Record<string, unknown>) => Record<string, unknown>;
|
|
35
|
+
readonly nodeReducer: (node: string, _data: unknown, attributes: Record<string, unknown>) => Record<string, unknown>;
|
|
36
|
+
readonly primitives: {
|
|
37
|
+
readonly edges: import("sigma/primitives").EdgePrimitives;
|
|
38
|
+
readonly nodes: import("sigma/primitives").NodePrimitives;
|
|
39
|
+
};
|
|
40
|
+
readonly settings: {
|
|
41
|
+
readonly enableCameraMouseRotation: false;
|
|
42
|
+
readonly itemSizesReference: 'screen';
|
|
43
|
+
readonly minEdgeThickness: 1.6;
|
|
44
|
+
readonly renderEdgeLabels: false;
|
|
45
|
+
readonly renderLabels: false;
|
|
46
|
+
};
|
|
47
|
+
readonly styles: {
|
|
48
|
+
readonly edges: {
|
|
49
|
+
readonly depth: 'edges';
|
|
50
|
+
readonly path: 'straight';
|
|
51
|
+
readonly size: {
|
|
52
|
+
readonly attribute: 'size';
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
readonly nodes: {
|
|
56
|
+
readonly depth: 'nodes';
|
|
57
|
+
readonly label: {
|
|
58
|
+
readonly attribute: 'label';
|
|
59
|
+
};
|
|
60
|
+
readonly labelVisibility: 'hidden';
|
|
61
|
+
readonly size: {
|
|
62
|
+
readonly attribute: 'size';
|
|
63
|
+
};
|
|
64
|
+
readonly x: {
|
|
65
|
+
readonly attribute: 'x';
|
|
66
|
+
};
|
|
67
|
+
readonly y: {
|
|
68
|
+
readonly attribute: 'y';
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { edgePrimitives } from './edge-program.js';
|
|
2
|
+
import { nodePrimitives } from './node-program.js';
|
|
3
|
+
const made = new WeakMap();
|
|
4
|
+
export const reducersOf = (sigma) => {
|
|
5
|
+
const nodes = sigma.getPrimitives().nodes;
|
|
6
|
+
return nodes ? made.get(nodes) : undefined;
|
|
7
|
+
};
|
|
8
|
+
export const sigmaOptions = (overrides = {}) => {
|
|
9
|
+
const nodes = nodePrimitives();
|
|
10
|
+
const reducers = {};
|
|
11
|
+
made.set(nodes, reducers);
|
|
12
|
+
return {
|
|
13
|
+
edgeReducer: (edge, _data, attributes) => reducers.edge?.(edge, attributes) ?? {},
|
|
14
|
+
nodeReducer: (node, _data, attributes) => reducers.node?.(node, attributes) ?? {},
|
|
15
|
+
primitives: { edges: edgePrimitives(), nodes },
|
|
16
|
+
settings: {
|
|
17
|
+
enableCameraMouseRotation: false,
|
|
18
|
+
itemSizesReference: 'screen',
|
|
19
|
+
minEdgeThickness: 1.6,
|
|
20
|
+
renderEdgeLabels: false,
|
|
21
|
+
renderLabels: false,
|
|
22
|
+
...overrides.settings,
|
|
23
|
+
},
|
|
24
|
+
styles: {
|
|
25
|
+
edges: { depth: 'edges', path: 'straight', size: { attribute: 'size' } },
|
|
26
|
+
nodes: {
|
|
27
|
+
depth: 'nodes',
|
|
28
|
+
label: { attribute: 'label' },
|
|
29
|
+
labelVisibility: 'hidden',
|
|
30
|
+
size: { attribute: 'size' },
|
|
31
|
+
x: { attribute: 'x' },
|
|
32
|
+
y: { attribute: 'y' },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusion.dev/helix-graph",
|
|
3
3
|
"description": "Connects the Helix Graph frame to a graph renderer: Sigma.js, cosmos.gl, three.js, or a driver of your own.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.215.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ross Sheppard <ross.sheppard@fusion.dev>",
|
|
7
7
|
"repository": {
|
|
@@ -60,12 +60,16 @@
|
|
|
60
60
|
},
|
|
61
61
|
"bugs": "https://github.com/project-fusion/fusion/issues",
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@fusion.dev/helix-core": "0.
|
|
63
|
+
"@fusion.dev/helix-core": "0.215.1"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@cosmos.gl/graph": "^3.
|
|
67
|
-
"@fusion.dev/helix-headless": "0.
|
|
68
|
-
"@fusion.dev/helix-testing": "0.
|
|
66
|
+
"@cosmos.gl/graph": "^3.5.1",
|
|
67
|
+
"@fusion.dev/helix-headless": "0.215.1",
|
|
68
|
+
"@fusion.dev/helix-testing": "0.215.1",
|
|
69
|
+
"@luma.gl/core": "~9.3.6",
|
|
70
|
+
"@luma.gl/engine": "~9.3.6",
|
|
71
|
+
"@luma.gl/shadertools": "~9.3.6",
|
|
72
|
+
"@luma.gl/webgl": "~9.3.6",
|
|
69
73
|
"@types/bun": "^1.4.2",
|
|
70
74
|
"@types/three": "^0.186.0",
|
|
71
75
|
"d3-force-3d": "^3.0.6",
|
|
@@ -73,7 +77,7 @@
|
|
|
73
77
|
"graphology-layout-forceatlas2": "^0.10.1",
|
|
74
78
|
"graphology-types": "^0.24.8",
|
|
75
79
|
"meshoptimizer": "^1.3.0",
|
|
76
|
-
"sigma": "^
|
|
80
|
+
"sigma": "^4.0.0",
|
|
77
81
|
"three": "^0.186.1"
|
|
78
82
|
},
|
|
79
83
|
"homepage": "https://fusion.dev",
|
|
@@ -90,7 +94,7 @@
|
|
|
90
94
|
"peerDependencies": {
|
|
91
95
|
"@cosmos.gl/graph": "^3.4.0",
|
|
92
96
|
"d3-force-3d": "^3.0.0",
|
|
93
|
-
"sigma": "^
|
|
97
|
+
"sigma": "^4.0.0",
|
|
94
98
|
"three": ">=0.160.0 <0.200.0"
|
|
95
99
|
},
|
|
96
100
|
"peerDependenciesMeta": {
|