@fusion.dev/helix-graph 0.128.0 → 0.128.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/dist/overlay/overlay.d.ts +18 -0
- package/dist/overlay/overlay.js +43 -11
- package/dist/sigma/sigma-driver.js +12 -13
- package/package.json +4 -4
|
@@ -38,6 +38,24 @@ export declare const signalsOver: (container: HTMLElement, onScreen: OnScreen) =
|
|
|
38
38
|
} | undefined, animate: boolean) => void;
|
|
39
39
|
stop: () => void;
|
|
40
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* Where the frame's own controls lie over the drawing, in the drawing's
|
|
43
|
+
* pixels: its zoom buttons, and its list where it opens over the drawing.
|
|
44
|
+
* Names keep clear of them, since a name under a button can be read by
|
|
45
|
+
* nobody. Read from the frame the drawing is in, where there is one.
|
|
46
|
+
*/
|
|
47
|
+
export declare const chromeOver: (container: HTMLElement) => Box[];
|
|
48
|
+
/** Whether a box overlaps none of `others`. */
|
|
49
|
+
export declare const clearOf: (box: Box, others: readonly Box[]) => boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Where a note's name starts, along the line: after the note, or before it
|
|
52
|
+
* where after it would run under the frame's controls or off the drawing.
|
|
53
|
+
* `box` gives the name's box for a start.
|
|
54
|
+
*/
|
|
55
|
+
export declare const nameStart: (at: {
|
|
56
|
+
radius: number;
|
|
57
|
+
x: number;
|
|
58
|
+
}, width: number, box: (start: number) => Box, avoid: readonly Box[], room: number) => number;
|
|
41
59
|
/** A note to name over the drawing: its name, and whether it is the one the reader is on. */
|
|
42
60
|
export interface Named {
|
|
43
61
|
id: string;
|
package/dist/overlay/overlay.js
CHANGED
|
@@ -266,6 +266,40 @@ export const signalsOver = (container, onScreen) => {
|
|
|
266
266
|
},
|
|
267
267
|
};
|
|
268
268
|
};
|
|
269
|
+
export const chromeOver = (container) => {
|
|
270
|
+
const frame = container.closest('helix-graph, helix-headless-graph');
|
|
271
|
+
const parts = frame?.shadowRoot?.querySelectorAll('[part="controls"], [part="panel"]') ?? [];
|
|
272
|
+
const origin = container.getBoundingClientRect();
|
|
273
|
+
const boxes = [];
|
|
274
|
+
for (const part of parts) {
|
|
275
|
+
const at = part.getBoundingClientRect();
|
|
276
|
+
if (at.width > 0 && at.height > 0) {
|
|
277
|
+
boxes.push({
|
|
278
|
+
bottom: at.bottom - origin.top,
|
|
279
|
+
left: at.left - origin.left,
|
|
280
|
+
right: at.right - origin.left,
|
|
281
|
+
top: at.top - origin.top,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return boxes;
|
|
286
|
+
};
|
|
287
|
+
export const clearOf = (box, others) => others.every((other) => box.right < other.left ||
|
|
288
|
+
box.left > other.right ||
|
|
289
|
+
box.bottom < other.top ||
|
|
290
|
+
box.top > other.bottom);
|
|
291
|
+
export const nameStart = (at, width, box, avoid, room) => {
|
|
292
|
+
const after = at.x + at.radius + 4;
|
|
293
|
+
const fits = (start) => {
|
|
294
|
+
const placed = box(start);
|
|
295
|
+
return placed.left >= 0 && placed.right <= room && clearOf(placed, avoid);
|
|
296
|
+
};
|
|
297
|
+
if (fits(after)) {
|
|
298
|
+
return after;
|
|
299
|
+
}
|
|
300
|
+
const before = at.x - at.radius - 4 - width;
|
|
301
|
+
return fits(before) ? before : after;
|
|
302
|
+
};
|
|
269
303
|
export const namesOver = (container, onScreen) => {
|
|
270
304
|
const canvas = layer(container, 'names');
|
|
271
305
|
let taken = [];
|
|
@@ -276,26 +310,24 @@ export const namesOver = (container, onScreen) => {
|
|
|
276
310
|
if (!context || !looks) {
|
|
277
311
|
return;
|
|
278
312
|
}
|
|
279
|
-
taken =
|
|
313
|
+
taken = chromeOver(container);
|
|
280
314
|
for (const { id, name, strong } of named) {
|
|
281
315
|
const at = onScreen(id);
|
|
282
316
|
if (!at || looks.node(id).hidden) {
|
|
283
317
|
continue;
|
|
284
318
|
}
|
|
285
319
|
context.font = `${strong ? 600 : 500} ${strong ? 13 : 12}px ${looks.font}`;
|
|
286
|
-
const
|
|
320
|
+
const width = context.measureText(name).width;
|
|
287
321
|
const y = at.y + 4;
|
|
288
|
-
const
|
|
322
|
+
const boxAt = (start) => ({
|
|
289
323
|
bottom: y + 4,
|
|
290
|
-
left:
|
|
291
|
-
right:
|
|
324
|
+
left: start - 2,
|
|
325
|
+
right: start + width + 2,
|
|
292
326
|
top: y - 13,
|
|
293
|
-
};
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
box.top > other.bottom);
|
|
298
|
-
if (!free && !strong) {
|
|
327
|
+
});
|
|
328
|
+
const x = nameStart(at, width, boxAt, taken, container.clientWidth);
|
|
329
|
+
const box = boxAt(x);
|
|
330
|
+
if (!clearOf(box, taken) && !strong) {
|
|
299
331
|
continue;
|
|
300
332
|
}
|
|
301
333
|
taken.push(box);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ease, gesturesHeld, groupsOver, signalsOver } from '../overlay/overlay.js';
|
|
1
|
+
import { chromeOver, clearOf, ease, gesturesHeld, groupsOver, nameStart, signalsOver, } from '../overlay/overlay.js';
|
|
2
2
|
import { EMPHASES, HelixNodeProgram, MATERIALS, SHAPES } from './node-program.js';
|
|
3
3
|
const SETTINGS = [
|
|
4
4
|
'defaultDrawNodeHover',
|
|
@@ -43,21 +43,23 @@ const hoverOf = (looks) => (context, data, settings) => {
|
|
|
43
43
|
context.fillText(data.label, x, data.y + size / 3);
|
|
44
44
|
};
|
|
45
45
|
const GROW = 300;
|
|
46
|
-
const labelOf = (looks, claim) => (context, data, settings) => {
|
|
46
|
+
const labelOf = (looks, claim, start) => (context, data, settings) => {
|
|
47
47
|
if (!data.label) {
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
50
|
const strong = data.strong === true;
|
|
51
51
|
const size = strong ? settings.labelSize : settings.labelSize - 1;
|
|
52
52
|
context.font = `${strong ? 600 : 500} ${size}px ${settings.labelFont}`;
|
|
53
|
-
const
|
|
53
|
+
const width = context.measureText(data.label).width;
|
|
54
54
|
const y = data.y + size / 3;
|
|
55
|
-
const
|
|
55
|
+
const boxAt = (from) => ({
|
|
56
56
|
bottom: y + 4,
|
|
57
|
-
left:
|
|
58
|
-
right:
|
|
57
|
+
left: from - 2,
|
|
58
|
+
right: from + width + 2,
|
|
59
59
|
top: y - size,
|
|
60
|
-
};
|
|
60
|
+
});
|
|
61
|
+
const x = start({ radius: data.size, x: data.x }, width, boxAt);
|
|
62
|
+
const box = boxAt(x);
|
|
61
63
|
if (!claim(box, data.forceLabel === true)) {
|
|
62
64
|
return;
|
|
63
65
|
}
|
|
@@ -113,17 +115,14 @@ export const sigmaDriver = (sigma, options = {}) => {
|
|
|
113
115
|
const naming = options.labels ?? 'hover';
|
|
114
116
|
let taken = [];
|
|
115
117
|
const claim = (box, must) => {
|
|
116
|
-
const free =
|
|
117
|
-
box.left > other.right ||
|
|
118
|
-
box.bottom < other.top ||
|
|
119
|
-
box.top > other.bottom);
|
|
118
|
+
const free = clearOf(box, taken);
|
|
120
119
|
if (free || must) {
|
|
121
120
|
taken.push(box);
|
|
122
121
|
}
|
|
123
122
|
return free || must;
|
|
124
123
|
};
|
|
125
124
|
const clear = () => {
|
|
126
|
-
taken =
|
|
125
|
+
taken = chromeOver(container);
|
|
127
126
|
};
|
|
128
127
|
sigma.on('beforeRender', clear);
|
|
129
128
|
const held = gesturesHeld(container);
|
|
@@ -240,7 +239,7 @@ export const sigmaDriver = (sigma, options = {}) => {
|
|
|
240
239
|
sigma.setSetting('labelFont', looks.font);
|
|
241
240
|
sigma.setSetting('labelRenderedSizeThreshold', 0);
|
|
242
241
|
sigma.setSetting('labelGridCellSize', 130);
|
|
243
|
-
sigma.setSetting('defaultDrawNodeLabel', labelOf(looks, claim));
|
|
242
|
+
sigma.setSetting('defaultDrawNodeLabel', labelOf(looks, claim, (at, width, box) => nameStart(at, width, box, taken, container.clientWidth)));
|
|
244
243
|
sigma.setSetting('defaultDrawNodeHover', hoverOf(looks));
|
|
245
244
|
sigma.setSetting('nodeReducer', (node, data) => {
|
|
246
245
|
const look = looks.node(node);
|
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.128.
|
|
4
|
+
"version": "0.128.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ross Sheppard <ross.sheppard@fusion.dev>",
|
|
7
7
|
"repository": {
|
|
@@ -51,12 +51,12 @@
|
|
|
51
51
|
},
|
|
52
52
|
"bugs": "https://github.com/project-fusion/fusion/issues",
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@fusion.dev/helix-core": "0.128.
|
|
54
|
+
"@fusion.dev/helix-core": "0.128.1"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@cosmos.gl/graph": "^3.4.2",
|
|
58
|
-
"@fusion.dev/helix-headless": "0.128.
|
|
59
|
-
"@fusion.dev/helix-testing": "0.128.
|
|
58
|
+
"@fusion.dev/helix-headless": "0.128.1",
|
|
59
|
+
"@fusion.dev/helix-testing": "0.128.1",
|
|
60
60
|
"@types/bun": "^1.3.0",
|
|
61
61
|
"@types/three": "^0.186.0",
|
|
62
62
|
"d3-force-3d": "^3.0.6",
|