@kanzo-tech/graph 0.13.1 → 0.15.0
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 -15
- package/dist/core/categories.d.ts +18 -6
- package/dist/core/categories.d.ts.map +1 -1
- package/dist/core/categories.js +41 -10
- package/dist/core/categories.js.map +1 -1
- package/dist/core/channels.d.ts +10 -5
- package/dist/core/channels.d.ts.map +1 -1
- package/dist/core/channels.js +11 -13
- package/dist/core/channels.js.map +1 -1
- package/dist/core/detail.d.ts +14 -8
- package/dist/core/detail.d.ts.map +1 -1
- package/dist/core/detail.js +33 -15
- package/dist/core/detail.js.map +1 -1
- package/dist/core/filter.d.ts +3 -1
- package/dist/core/filter.d.ts.map +1 -1
- package/dist/core/filter.js +54 -50
- package/dist/core/filter.js.map +1 -1
- package/dist/core/load.d.ts +58 -0
- package/dist/core/load.d.ts.map +1 -0
- package/dist/core/load.js +115 -0
- package/dist/core/load.js.map +1 -0
- package/dist/core/state.d.ts +31 -56
- package/dist/core/state.d.ts.map +1 -1
- package/dist/core/store.d.ts +1 -3
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +162 -172
- package/dist/core/store.js.map +1 -1
- package/dist/core/types.d.ts +21 -17
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +5 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -25
- package/dist/index.js.map +1 -1
- package/dist/parts/gesture.d.ts +1 -10
- package/dist/parts/gesture.d.ts.map +1 -1
- package/dist/parts/gesture.js +26 -28
- package/dist/parts/gesture.js.map +1 -1
- package/dist/parts/graph-canvas.d.ts.map +1 -1
- package/dist/parts/graph-canvas.js +128 -106
- package/dist/parts/graph-canvas.js.map +1 -1
- package/dist/parts/graph-inspector.d.ts +4 -4
- package/dist/parts/graph-inspector.d.ts.map +1 -1
- package/dist/parts/graph-inspector.js +55 -57
- package/dist/parts/graph-inspector.js.map +1 -1
- package/dist/parts/graph-legend.d.ts +4 -4
- package/dist/parts/graph-legend.d.ts.map +1 -1
- package/dist/parts/graph-legend.js +21 -21
- package/dist/parts/graph-legend.js.map +1 -1
- package/dist/parts/graph-toolbar.d.ts +1 -1
- package/dist/parts/graph-toolbar.d.ts.map +1 -1
- package/dist/parts/graph-toolbar.js +40 -40
- package/dist/parts/graph-toolbar.js.map +1 -1
- package/dist/parts/overlays.d.ts +6 -5
- package/dist/parts/overlays.d.ts.map +1 -1
- package/dist/parts/overlays.js +70 -68
- package/dist/parts/overlays.js.map +1 -1
- package/dist/react/use-graph-state.d.ts +4 -2
- package/dist/react/use-graph-state.d.ts.map +1 -1
- package/dist/react/use-graph-state.js +10 -6
- package/dist/react/use-graph-state.js.map +1 -1
- package/dist/react/use-graph.d.ts +1 -4
- package/dist/react/use-graph.d.ts.map +1 -1
- package/dist/react/use-graph.js +38 -49
- package/dist/react/use-graph.js.map +1 -1
- package/dist/render/graph-looks.d.ts.map +1 -1
- package/dist/render/graph-looks.js.map +1 -1
- package/dist/render/graph-model.d.ts +6 -8
- package/dist/render/graph-model.d.ts.map +1 -1
- package/dist/render/graph-model.js +51 -57
- package/dist/render/graph-model.js.map +1 -1
- package/dist/render/graph-sim.d.ts +2 -3
- package/dist/render/graph-sim.d.ts.map +1 -1
- package/dist/render/graph-sim.js.map +1 -1
- package/dist/render/renderer.d.ts +10 -10
- package/dist/render/renderer.d.ts.map +1 -1
- package/dist/render/renderer.js +121 -177
- package/dist/render/renderer.js.map +1 -1
- package/dist/section.d.ts.map +1 -1
- package/dist/section.js +3 -7
- package/dist/section.js.map +1 -1
- package/package.json +29 -10
- package/dist/core/refine.d.ts +0 -14
- package/dist/core/refine.d.ts.map +0 -1
- package/dist/core/refine.js +0 -20
- package/dist/core/refine.js.map +0 -1
- package/dist/core/resident.d.ts +0 -79
- package/dist/core/resident.d.ts.map +0 -1
- package/dist/core/resident.js +0 -44
- package/dist/core/resident.js.map +0 -1
- package/dist/core/scheduler.d.ts +0 -42
- package/dist/core/scheduler.d.ts.map +0 -1
- package/dist/core/scheduler.js +0 -77
- package/dist/core/scheduler.js.map +0 -1
- package/dist/core/tile-matrix.d.ts +0 -37
- package/dist/core/tile-matrix.d.ts.map +0 -1
- package/dist/core/tile-matrix.js +0 -49
- package/dist/core/tile-matrix.js.map +0 -1
- package/dist/core/tile.d.ts +0 -54
- package/dist/core/tile.d.ts.map +0 -1
- package/dist/core/tile.js +0 -76
- package/dist/core/tile.js.map +0 -1
- package/dist/core/tileset.d.ts +0 -59
- package/dist/core/tileset.d.ts.map +0 -1
- package/dist/core/tileset.js +0 -177
- package/dist/core/tileset.js.map +0 -1
- package/dist/render/adaptive.d.ts +0 -27
- package/dist/render/adaptive.d.ts.map +0 -1
- package/dist/render/adaptive.js +0 -25
- package/dist/render/adaptive.js.map +0 -1
- package/dist/render/compose.d.ts +0 -51
- package/dist/render/compose.d.ts.map +0 -1
- package/dist/render/compose.js +0 -107
- package/dist/render/compose.js.map +0 -1
- package/dist/render/encode.d.ts +0 -42
- package/dist/render/encode.d.ts.map +0 -1
- package/dist/render/encode.js +0 -68
- package/dist/render/encode.js.map +0 -1
- package/dist/render/when-ready.d.ts +0 -35
- package/dist/render/when-ready.d.ts.map +0 -1
- package/dist/render/when-ready.js +0 -17
- package/dist/render/when-ready.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,35 +1,29 @@
|
|
|
1
1
|
import { GraphRoot as e, GraphRootProvider as p, useGraphContext as t } from "./react/graph-root.js";
|
|
2
|
-
import { useGraph as
|
|
2
|
+
import { useGraph as m } from "./react/use-graph.js";
|
|
3
3
|
import { useGraphState as x } from "./react/use-graph-state.js";
|
|
4
4
|
import { useGraphPrefs as G } from "./react/use-graph-prefs.js";
|
|
5
|
-
import { GraphCanvas as
|
|
6
|
-
import { GraphLegend as
|
|
7
|
-
import { GraphToolbar as
|
|
8
|
-
import { GraphInspector as
|
|
9
|
-
import { ShapeGlyph as
|
|
10
|
-
import { lookFrom as
|
|
11
|
-
import { simFrom as
|
|
12
|
-
import {
|
|
13
|
-
import { scaleOf as g } from "./render/graph-model.js";
|
|
14
|
-
import { denseOf as L, typeOf as T, vertexId as j } from "./core/resident.js";
|
|
5
|
+
import { GraphCanvas as l } from "./parts/graph-canvas.js";
|
|
6
|
+
import { GraphLegend as u } from "./parts/graph-legend.js";
|
|
7
|
+
import { GraphToolbar as d } from "./parts/graph-toolbar.js";
|
|
8
|
+
import { GraphInspector as v } from "./parts/graph-inspector.js";
|
|
9
|
+
import { ShapeGlyph as F } from "./parts/shape-glyph.js";
|
|
10
|
+
import { lookFrom as R } from "./render/graph-looks.js";
|
|
11
|
+
import { simFrom as b } from "./render/graph-sim.js";
|
|
12
|
+
import { scaleOf as k } from "./render/graph-model.js";
|
|
15
13
|
export {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
l as GraphCanvas,
|
|
15
|
+
v as GraphInspector,
|
|
16
|
+
u as GraphLegend,
|
|
19
17
|
e as GraphRoot,
|
|
20
18
|
p as GraphRootProvider,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
P as simFrom,
|
|
28
|
-
T as typeOf,
|
|
29
|
-
f as useGraph,
|
|
19
|
+
d as GraphToolbar,
|
|
20
|
+
F as ShapeGlyph,
|
|
21
|
+
R as lookFrom,
|
|
22
|
+
k as scaleOf,
|
|
23
|
+
b as simFrom,
|
|
24
|
+
m as useGraph,
|
|
30
25
|
t as useGraphContext,
|
|
31
26
|
G as useGraphPrefs,
|
|
32
|
-
x as useGraphState
|
|
33
|
-
j as vertexId
|
|
27
|
+
x as useGraphState
|
|
34
28
|
};
|
|
35
29
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
|
package/dist/parts/gesture.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { Graph } from '@cosmos.gl/graph';
|
|
3
|
-
import {
|
|
4
|
-
import { Selection, SelectionSource, Tool } from '../core/types';
|
|
3
|
+
import { Selection, SelectionSource, Tool, VertexId } from '../core/types';
|
|
5
4
|
/**
|
|
6
5
|
* Drawing a selection on the canvas: the marquee, the lasso, and the keys that modify them.
|
|
7
6
|
*
|
|
@@ -41,14 +40,6 @@ export interface GraphSelectionGesture {
|
|
|
41
40
|
}
|
|
42
41
|
export interface GraphSelectionOptions {
|
|
43
42
|
getGraph: () => Graph | null;
|
|
44
|
-
/**
|
|
45
|
-
* Who is drawn right now — the only thing that can turn a hit-test index into an identity.
|
|
46
|
-
*
|
|
47
|
-
* A gesture selects positions on screen, and a position is a buffer index, which the next
|
|
48
|
-
* residency reuses for a different vertex. So the gesture resolves to identities here and now,
|
|
49
|
-
* while the answer that produced them is still the one on screen.
|
|
50
|
-
*/
|
|
51
|
-
getResident: () => Resident;
|
|
52
43
|
/** The live selection, for the modifiers to add to or subtract from. */
|
|
53
44
|
getSelection: () => Selection | null;
|
|
54
45
|
commit: (vertices: Set<VertexId> | null, source: SelectionSource, label: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gesture.d.ts","sourceRoot":"","sources":["../../src/parts/gesture.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"gesture.d.ts","sourceRoot":"","sources":["../../src/parts/gesture.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEhF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAErC,wFAAwF;AACxF,MAAM,MAAM,IAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,KAAK,EAAE,CAAA;CAAE,CAAC;AAS/F,4FAA4F;AAC5F,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC,aAAa,CAIjE;AAED,MAAM,WAAW,qBAAqB;IACpC,0DAA0D;IAC1D,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,oFAAoF;IACpF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,mFAAmF;IACnF,MAAM,EAAE,IAAI,CAAC;IACb,QAAQ,EAAE;QACR,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;QACnD,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;QACnD,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;QACjD,eAAe,EAAE,MAAM,IAAI,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,KAAK,GAAG,IAAI,CAAC;IAC7B,wEAAwE;IACxE,YAAY,EAAE,MAAM,SAAS,GAAG,IAAI,CAAC;IACrC,MAAM,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzF,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAC/B;AAOD,wBAAgB,UAAU,CAAC,OAAO,EAAE,qBAAqB,GAAG,qBAAqB,CAyIhF"}
|
package/dist/parts/gesture.js
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useState as m, useRef as
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
function N(l) {
|
|
2
|
+
import { useState as m, useRef as A, useCallback as g, useEffect as R } from "react";
|
|
3
|
+
const x = 3, I = 4, K = 60;
|
|
4
|
+
function z(l) {
|
|
6
5
|
if (!l) return { display: "none" };
|
|
7
6
|
const [i = 0, a = 0] = l.tool === "rect" ? l.to : l.path[l.path.length - 1] ?? [];
|
|
8
7
|
return { left: i + 14, top: a + 14 };
|
|
9
8
|
}
|
|
10
|
-
const
|
|
9
|
+
const _ = {
|
|
11
10
|
rect: { source: "marquee", label: "Marquee" },
|
|
12
11
|
lasso: { source: "lasso", label: "Lasso" }
|
|
13
12
|
};
|
|
14
|
-
function
|
|
15
|
-
const { commit: i, getGraph: a,
|
|
13
|
+
function D(l) {
|
|
14
|
+
const { commit: i, getGraph: a, getSelection: k, setTool: y, tool: h } = l, [s, c] = m(null), [v, f] = m(null), [L, p] = m(!1), b = A(0), w = g(
|
|
16
15
|
(t) => {
|
|
17
16
|
const e = a();
|
|
18
17
|
if (!e) return [];
|
|
19
|
-
if (!K(e)) return [];
|
|
20
18
|
if (t.tool === "rect") {
|
|
21
19
|
const [[o, n], [r, u]] = [t.from, t.to];
|
|
22
20
|
return Math.abs(r - o) < x || Math.abs(u - n) < x ? [] : Array.from(
|
|
@@ -29,19 +27,19 @@ function U(l) {
|
|
|
29
27
|
return t.path.length < 3 ? [] : Array.from(e.findPointsInPolygon(t.path));
|
|
30
28
|
},
|
|
31
29
|
[a]
|
|
32
|
-
), E =
|
|
30
|
+
), E = g(
|
|
33
31
|
(t) => {
|
|
34
32
|
const e = performance.now();
|
|
35
|
-
e - b.current <
|
|
33
|
+
e - b.current < K || (b.current = e, f(w(t).length));
|
|
36
34
|
},
|
|
37
|
-
[
|
|
35
|
+
[w]
|
|
38
36
|
);
|
|
39
|
-
|
|
37
|
+
R(() => {
|
|
40
38
|
const t = (n) => {
|
|
41
|
-
n.key === "Shift" &&
|
|
39
|
+
n.key === "Shift" && p(!0), n.key === "Escape" && (c((r) => (r || (h ? y(null) : i(null, "node", "")), null)), f(null));
|
|
42
40
|
}, e = (n) => {
|
|
43
|
-
n.key === "Shift" &&
|
|
44
|
-
}, o = () =>
|
|
41
|
+
n.key === "Shift" && p(!1);
|
|
42
|
+
}, o = () => p(!1);
|
|
45
43
|
return window.addEventListener("keydown", t), window.addEventListener("keyup", e), window.addEventListener("blur", o), () => {
|
|
46
44
|
window.removeEventListener("keydown", t), window.removeEventListener("keyup", e), window.removeEventListener("blur", o);
|
|
47
45
|
};
|
|
@@ -50,28 +48,28 @@ function U(l) {
|
|
|
50
48
|
const e = t.currentTarget.getBoundingClientRect();
|
|
51
49
|
return [t.clientX - e.left, t.clientY - e.top];
|
|
52
50
|
}, T = (t, e) => {
|
|
53
|
-
var
|
|
51
|
+
var S;
|
|
54
52
|
if (c(null), f(null), !t) return;
|
|
55
|
-
const o = new Set(
|
|
53
|
+
const o = new Set(w(t));
|
|
56
54
|
if (o.size === 0 && !e.altKey) return;
|
|
57
|
-
const { label: n, source: r } =
|
|
55
|
+
const { label: n, source: r } = _[t.tool], u = ((S = k()) == null ? void 0 : S.vertices) ?? [];
|
|
58
56
|
if (e.altKey) {
|
|
59
|
-
const
|
|
60
|
-
for (const
|
|
61
|
-
i(
|
|
57
|
+
const d = new Set(u);
|
|
58
|
+
for (const C of o) d.delete(C);
|
|
59
|
+
i(d.size > 0 ? d : null, r, n);
|
|
62
60
|
} else e.metaKey || e.ctrlKey ? i(/* @__PURE__ */ new Set([...u, ...o]), r, n) : i(o, r, n);
|
|
63
|
-
},
|
|
61
|
+
}, P = h ?? (L ? "rect" : null);
|
|
64
62
|
return {
|
|
65
63
|
drag: s,
|
|
66
|
-
preview:
|
|
67
|
-
active:
|
|
64
|
+
preview: v,
|
|
65
|
+
active: P,
|
|
68
66
|
handlers: {
|
|
69
67
|
onPointerDown: (t) => {
|
|
70
68
|
if (t.button !== 0) return;
|
|
71
69
|
t.currentTarget.setPointerCapture(t.pointerId);
|
|
72
70
|
const e = M(t);
|
|
73
71
|
c(
|
|
74
|
-
|
|
72
|
+
P === "rect" ? { tool: "rect", from: e, to: e } : { tool: "lasso", path: [e] }
|
|
75
73
|
);
|
|
76
74
|
},
|
|
77
75
|
onPointerMove: (t) => {
|
|
@@ -83,7 +81,7 @@ function U(l) {
|
|
|
83
81
|
return;
|
|
84
82
|
}
|
|
85
83
|
const o = s.path[s.path.length - 1];
|
|
86
|
-
if (Math.hypot(e[0] - o[0], e[1] - o[1]) <
|
|
84
|
+
if (Math.hypot(e[0] - o[0], e[1] - o[1]) < I) return;
|
|
87
85
|
const n = { tool: "lasso", path: [...s.path, e] };
|
|
88
86
|
c(n), E(n);
|
|
89
87
|
},
|
|
@@ -95,7 +93,7 @@ function U(l) {
|
|
|
95
93
|
};
|
|
96
94
|
}
|
|
97
95
|
export {
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
z as cursorChip,
|
|
97
|
+
D as useGesture
|
|
100
98
|
};
|
|
101
99
|
//# sourceMappingURL=gesture.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gesture.js","sources":["../../src/parts/gesture.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type React from \"react\";\nimport type { Graph } from \"@cosmos.gl/graph\";\nimport type {
|
|
1
|
+
{"version":3,"file":"gesture.js","sources":["../../src/parts/gesture.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type React from \"react\";\nimport type { Graph } from \"@cosmos.gl/graph\";\nimport type { Selection, SelectionSource, Tool, VertexId } from \"../core/types\";\n\n/**\n * Drawing a selection on the canvas: the marquee, the lasso, and the keys that modify them.\n *\n * The whole gesture lives here — what is being drawn, how many nodes it currently holds, and what\n * happens when the pointer comes up. The component gets handlers to spread onto an overlay and the\n * state to draw it with; it does not need to know that Shift borrows the marquee or that a hit test\n * costs a GPU readback.\n *\n * Modifiers are read at *release*, not at press, because that is when the reader has decided:\n * `Alt` removes what was drawn from the selection, `⌘`/`Ctrl` adds it, and neither replaces.\n */\nexport type Point = [number, number];\n\n/** A selection gesture in flight. The two tools differ only in what they accumulate. */\nexport type Drag = { tool: \"rect\"; from: Point; to: Point } | { tool: \"lasso\"; path: Point[] };\n\n/** Below this the hit test would be answering about a click, not a box. */\nconst MIN_RECT = 3;\n/** A raw pointer stream makes a polygon of near-duplicate vertices; the hit test walks every one. */\nconst PATH_STEP = 4;\n/** Slower than the hand, faster than the eye — and one GPU readback per gesture frame is plenty. */\nconst MEASURE_MS = 60;\n\n/** The running count rides just off the cursor, at the edge the gesture is growing from. */\nexport function cursorChip(drag: Drag | null): React.CSSProperties {\n if (!drag) return { display: \"none\" };\n const [x = 0, y = 0] = drag.tool === \"rect\" ? drag.to : (drag.path[drag.path.length - 1] ?? []);\n return { left: x + 14, top: y + 14 };\n}\n\nexport interface GraphSelectionGesture {\n /** The gesture being drawn, for the overlay to render. */\n drag: Drag | null;\n /** How many nodes it holds right now, so the number lands before the mouse does. */\n preview: number | null;\n /** The tool actually in force: the chosen one, or the marquee Shift is lending. */\n active: Tool;\n handlers: {\n onPointerDown: (event: React.PointerEvent) => void;\n onPointerMove: (event: React.PointerEvent) => void;\n onPointerUp: (event: React.PointerEvent) => void;\n onPointerCancel: () => void;\n };\n}\n\nexport interface GraphSelectionOptions {\n getGraph: () => Graph | null;\n /** The live selection, for the modifiers to add to or subtract from. */\n getSelection: () => Selection | null;\n commit: (vertices: Set<VertexId> | null, source: SelectionSource, label: string) => void;\n tool: Tool;\n setTool: (tool: Tool) => void;\n}\n\nconst NAME: Record<\"rect\" | \"lasso\", { source: SelectionSource; label: string }> = {\n rect: { source: \"marquee\", label: \"Marquee\" },\n lasso: { source: \"lasso\", label: \"Lasso\" },\n};\n\nexport function useGesture(options: GraphSelectionOptions): GraphSelectionGesture {\n const { commit, getGraph, getSelection, setTool, tool } = options;\n const [drag, setDrag] = useState<Drag | null>(null);\n const [preview, setPreview] = useState<number | null>(null);\n const [shift, setShift] = useState(false);\n const measured = useRef(0);\n\n const hitTest = useCallback(\n (shape: Drag): number[] => {\n const graph = getGraph();\n if (!graph) return [];\n // Before its device cosmos.gl answers `[]` here: a gesture over a graph that has not drawn\n // selects nothing, which is what it looks like.\n if (shape.tool === \"rect\") {\n const [[ax, ay], [bx, by]] = [shape.from, shape.to];\n if (Math.abs(bx - ax) < MIN_RECT || Math.abs(by - ay) < MIN_RECT) return [];\n return Array.from(\n graph.findPointsInRect([\n [Math.min(ax, bx), Math.min(ay, by)],\n [Math.max(ax, bx), Math.max(ay, by)],\n ]),\n );\n }\n if (shape.path.length < 3) return [];\n return Array.from(graph.findPointsInPolygon(shape.path));\n },\n [getGraph],\n );\n\n // Both hit tests are a GPU pass followed by a synchronous `readPixels`, so running one per\n // pointer event would stall the frame the gesture is being drawn into.\n const measure = useCallback(\n (shape: Drag) => {\n const now = performance.now();\n if (now - measured.current < MEASURE_MS) return;\n measured.current = now;\n setPreview(hitTest(shape).length);\n },\n [hitTest],\n );\n\n // Escape is the way out of everything, in layers: it abandons a drag in progress, then drops the\n // tool, then clears what is held. And a window that loses focus never delivers the Shift keyup,\n // which would leave the canvas unable to pan.\n useEffect(() => {\n const down = (event: KeyboardEvent) => {\n if (event.key === \"Shift\") setShift(true);\n if (event.key !== \"Escape\") return;\n setDrag((current) => {\n if (current) return null;\n if (tool) setTool(null);\n else commit(null, \"node\", \"\");\n return null;\n });\n setPreview(null);\n };\n const up = (event: KeyboardEvent) => {\n if (event.key === \"Shift\") setShift(false);\n };\n const blur = () => setShift(false);\n window.addEventListener(\"keydown\", down);\n window.addEventListener(\"keyup\", up);\n window.addEventListener(\"blur\", blur);\n return () => {\n window.removeEventListener(\"keydown\", down);\n window.removeEventListener(\"keyup\", up);\n window.removeEventListener(\"blur\", blur);\n };\n }, [commit, setTool, tool]);\n\n /** Screen coordinates inside the canvas — the space every cosmos.gl hit test speaks. */\n const at = (event: React.PointerEvent): Point => {\n const box = event.currentTarget.getBoundingClientRect();\n return [event.clientX - box.left, event.clientY - box.top];\n };\n\n const finish = (shape: Drag | null, event: React.PointerEvent) => {\n setDrag(null);\n setPreview(null);\n if (!shape) return;\n // The hit test answers in buffer indices, and a drawn vertex's index is its id.\n const vertices = new Set<VertexId>(hitTest(shape));\n // A gesture that caught nothing and asked for nothing is a misfire, not a request to clear —\n // clearing is what the corner's own button and Escape are for.\n if (vertices.size === 0 && !event.altKey) return;\n const { label, source } = NAME[shape.tool];\n const held = getSelection()?.vertices ?? [];\n if (event.altKey) {\n const next = new Set(held);\n for (const vertex of vertices) next.delete(vertex);\n commit(next.size > 0 ? next : null, source, label);\n } else if (event.metaKey || event.ctrlKey) {\n commit(new Set([...held, ...vertices]), source, label);\n } else {\n commit(vertices, source, label);\n }\n };\n\n const active: Tool = tool ?? (shift ? \"rect\" : null);\n\n return {\n drag,\n preview,\n active,\n handlers: {\n onPointerDown: (event) => {\n if (event.button !== 0) return;\n event.currentTarget.setPointerCapture(event.pointerId);\n const start = at(event);\n setDrag(\n active === \"rect\"\n ? { tool: \"rect\", from: start, to: start }\n : { tool: \"lasso\", path: [start] },\n );\n },\n onPointerMove: (event) => {\n if (!drag) return;\n const next = at(event);\n if (drag.tool === \"rect\") {\n const shape: Drag = { ...drag, to: next };\n setDrag(shape);\n measure(shape);\n return;\n }\n const last = drag.path[drag.path.length - 1] as Point;\n if (Math.hypot(next[0] - last[0], next[1] - last[1]) < PATH_STEP) return;\n const shape: Drag = { tool: \"lasso\", path: [...drag.path, next] };\n setDrag(shape);\n measure(shape);\n },\n onPointerUp: (event) => finish(drag, event),\n onPointerCancel: () => {\n setDrag(null);\n setPreview(null);\n },\n },\n };\n}\n"],"names":[],"mappings":";;AAwBA;AAOO;AACL;AACA;AACA;AACF;AA0BA;AAAmF;AAC/C;AAEpC;AAEO;AACL;AAMgB;AAEZ;AACA;AAGA;AACE;AACA;AACa;AACY;AACc;AACA;AACpC;AAAA;AAGL;AACuD;AACzD;AACS;AAKK;AAEZ;AACA;AAEgC;AAClC;AACQ;AAMV;AACE;AAEE;AAOe;AAGf;AAAyC;AAG3C;AAIE;AAEuC;AACzC;AAIF;AACE;AACA;AAAyD;;AAMzD;AAEA;AAGA;AACA;AAEA;AACE;AACA;AACA;AAAiD;AAInB;AAMlC;AAAO;AACL;AACA;AACA;AACU;AAEN;AACA;AACA;AACA;AAAA;AAGmC;AAAE;AAEvC;AAEE;AACA;AACA;AACE;AACA;AAEA;AAAA;AAEF;AACA;AACA;AACA;AACa;AACf;AAC0C;AAExC;AACe;AACjB;AAAA;AAGN;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-canvas.d.ts","sourceRoot":"","sources":["../../src/parts/graph-canvas.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAqD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"graph-canvas.d.ts","sourceRoot":"","sources":["../../src/parts/graph-canvas.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAqD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAe1F,MAAM,WAAW,gBAAiB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACnE,oFAAoF;IACpF,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAkDD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,gBAAgB,+BAgJnF"}
|
|
@@ -1,174 +1,196 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsxs as
|
|
3
|
-
import { useThemeTick as
|
|
4
|
-
import { useMemo as
|
|
5
|
-
import { nameOf as
|
|
6
|
-
import {
|
|
7
|
-
import { useGraphContext as
|
|
8
|
-
import { internalsOf as
|
|
9
|
-
import { useGraphState as
|
|
10
|
-
import { resolveLook as
|
|
11
|
-
import { scaleOf as
|
|
12
|
-
import { useGesture as
|
|
13
|
-
import { useOverlays as
|
|
14
|
-
import { ShapeGlyph as
|
|
15
|
-
const
|
|
16
|
-
function
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
2
|
+
import { jsxs as b, jsx as a } from "react/jsx-runtime";
|
|
3
|
+
import { useThemeTick as Y, categoricalCapacity as Z, Show as g, cn as ee } from "@kanzo-tech/ui";
|
|
4
|
+
import { useMemo as x, useCallback as $, useRef as te, useEffect as y, useState as oe } from "react";
|
|
5
|
+
import { nameOf as ne } from "../core/categories.js";
|
|
6
|
+
import { readTitles as re } from "../core/detail.js";
|
|
7
|
+
import { useGraphContext as F } from "../react/graph-root.js";
|
|
8
|
+
import { internalsOf as ae } from "../react/use-graph.js";
|
|
9
|
+
import { useGraphState as m, useGraphSnapshot as S } from "../react/use-graph-state.js";
|
|
10
|
+
import { resolveLook as se } from "../render/graph-looks.js";
|
|
11
|
+
import { scaleOf as le } from "../render/graph-model.js";
|
|
12
|
+
import { useGesture as ie, cursorChip as ce } from "./gesture.js";
|
|
13
|
+
import { useOverlays as pe } from "./overlays.js";
|
|
14
|
+
import { ShapeGlyph as de } from "./shape-glyph.js";
|
|
15
|
+
const E = "color-mix(in oklab, var(--primary) 17%, transparent)";
|
|
16
|
+
function me(u, d, i, p, s) {
|
|
17
|
+
const c = d.sizes, n = [];
|
|
18
|
+
if (c && p > 0)
|
|
19
|
+
for (let t = 0; t < u.size; t++) {
|
|
20
|
+
const r = c[t];
|
|
21
|
+
if (i && !i[t] || Number.isNaN(r) || n.length === p && r <= c[n[p - 1]]) continue;
|
|
22
|
+
let o = n.length;
|
|
23
|
+
for (; o > 0 && c[n[o - 1]] < r; ) o--;
|
|
24
|
+
n.splice(o, 0, t), n.length > p && n.pop();
|
|
25
|
+
}
|
|
26
|
+
return s === null || n.includes(s) ? n : [s, ...n];
|
|
27
|
+
}
|
|
28
|
+
function D(u) {
|
|
29
|
+
const d = F(), i = m((r) => r.corpus), p = m((r) => r.options.title), s = S((r) => r.geometry), [c, n] = oe(() => /* @__PURE__ */ new Map()), t = u.join(",");
|
|
30
|
+
return y(() => {
|
|
31
|
+
if (!i || !s || t === "") return;
|
|
32
|
+
const r = new AbortController();
|
|
33
|
+
return re(i, s, t.split(",").map(Number), p, r.signal).then(
|
|
34
|
+
(o) => !r.signal.aborted && n(o),
|
|
35
|
+
(o) => !r.signal.aborted && d.getState().options.onFailure(o instanceof Error ? o.message : String(o))
|
|
36
|
+
), () => r.abort();
|
|
37
|
+
}, [d, i, s, t, p]), c;
|
|
26
38
|
}
|
|
27
|
-
const
|
|
39
|
+
const ue = {
|
|
28
40
|
opening: "Opening the corpus…",
|
|
29
|
-
|
|
41
|
+
loading: "Loading the graph…"
|
|
30
42
|
};
|
|
31
|
-
function
|
|
32
|
-
const
|
|
33
|
-
var
|
|
34
|
-
return ((
|
|
35
|
-
}),
|
|
43
|
+
function Me({ children: u, className: d, slot: i, ...p }) {
|
|
44
|
+
const s = F(), { attach: c, renderer: n } = ae(s), t = m((e) => e.focus), r = m((e) => e.tool), o = m((e) => e.options), k = m((e) => {
|
|
45
|
+
var h;
|
|
46
|
+
return ((h = e.drawn) == null ? void 0 : h.domain) ?? e.domain;
|
|
47
|
+
}), w = m((e) => e.drawn === null ? ue[e.status] : void 0), f = x(() => se(o.look), [o.look]), R = $(() => {
|
|
36
48
|
var e;
|
|
37
|
-
return ((e =
|
|
38
|
-
}, [
|
|
39
|
-
|
|
40
|
-
const e =
|
|
49
|
+
return ((e = n()) == null ? void 0 : e.graph) ?? null;
|
|
50
|
+
}, [n]), q = pe({ getGraph: R }), { cardRef: B, gridRef: J, hostRef: T, hoverAt: _, labelRef: K, schedule: v, setHovered: P, setLabelOrder: j, track: A } = q, I = te(null), G = S((e) => e.geometry), N = S((e) => e.encoding), W = S((e) => e.mask);
|
|
51
|
+
y(() => {
|
|
52
|
+
const e = I.current;
|
|
41
53
|
if (e)
|
|
42
|
-
return
|
|
43
|
-
}, [
|
|
44
|
-
const
|
|
45
|
-
|
|
54
|
+
return c(e, { onFrame: v, onHover: _ });
|
|
55
|
+
}, [c, _, v]);
|
|
56
|
+
const Q = Y();
|
|
57
|
+
y(() => {
|
|
46
58
|
var e;
|
|
47
|
-
(e =
|
|
48
|
-
}, [
|
|
49
|
-
const
|
|
50
|
-
() =>
|
|
51
|
-
[
|
|
59
|
+
(e = n()) == null || e.repaint();
|
|
60
|
+
}, [n, Q]);
|
|
61
|
+
const C = x(
|
|
62
|
+
() => G && N ? me(G, N, W, f.labels, t) : [],
|
|
63
|
+
[G, N, W, t, f.labels]
|
|
64
|
+
), M = D(C), z = x(
|
|
65
|
+
() => C.flatMap((e) => M.get(e) ? [{ vertex: e, text: M.get(e) }] : []),
|
|
66
|
+
[C, M]
|
|
52
67
|
);
|
|
53
|
-
|
|
54
|
-
z
|
|
55
|
-
}, [
|
|
56
|
-
const
|
|
57
|
-
getGraph:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
var H;
|
|
65
|
-
if (s === null || !d) return null;
|
|
66
|
-
const e = d.resident.indexOf(s);
|
|
67
|
-
if (e === void 0) return null;
|
|
68
|
-
const a = d.categories[e] ?? 0, C = o.fill !== void 0 || o.symbol !== void 0;
|
|
69
|
-
return {
|
|
70
|
-
rank: a,
|
|
71
|
-
title: ((H = d.titles) == null ? void 0 : H[e]) || `#${ee(s)}`,
|
|
72
|
-
category: C && a < N.length ? Z(N[a], o.categories) : null
|
|
73
|
-
};
|
|
74
|
-
}, [d, N, s, o]);
|
|
75
|
-
return /* @__PURE__ */ g(
|
|
68
|
+
y(() => {
|
|
69
|
+
j(z.map((e) => e.vertex)), A(), v();
|
|
70
|
+
}, [z, v, j, A, f.grid]);
|
|
71
|
+
const H = ie({
|
|
72
|
+
getGraph: R,
|
|
73
|
+
getSelection: $(() => s.getState().selection, [s]),
|
|
74
|
+
commit: (e, h, X) => s.select(e ? [...e] : null, h, X),
|
|
75
|
+
setTool: s.setTool,
|
|
76
|
+
tool: r
|
|
77
|
+
}), { active: U, drag: l, preview: O } = H, L = T.current ? Z(T.current) : void 0, V = x(() => le(o, L), [o, L]);
|
|
78
|
+
return /* @__PURE__ */ b(
|
|
76
79
|
"div",
|
|
77
80
|
{
|
|
78
|
-
...
|
|
79
|
-
className:
|
|
80
|
-
"data-slot":
|
|
81
|
-
ref:
|
|
81
|
+
...p,
|
|
82
|
+
className: ee("relative isolate size-full overflow-hidden bg-background", d),
|
|
83
|
+
"data-slot": i ?? "graph-canvas",
|
|
84
|
+
ref: T,
|
|
82
85
|
children: [
|
|
83
|
-
/* @__PURE__ */
|
|
84
|
-
/* @__PURE__ */
|
|
86
|
+
/* @__PURE__ */ a("div", { className: "size-full", "data-slot": "graph-canvas-surface", ref: I }),
|
|
87
|
+
/* @__PURE__ */ a(g, { when: f.grid, children: /* @__PURE__ */ a(
|
|
85
88
|
"div",
|
|
86
89
|
{
|
|
87
90
|
className: "pointer-events-none absolute inset-0",
|
|
88
|
-
ref:
|
|
91
|
+
ref: J,
|
|
89
92
|
style: { backgroundImage: "radial-gradient(var(--border) 1px, transparent 1px)" }
|
|
90
93
|
}
|
|
91
94
|
) }),
|
|
92
|
-
/* @__PURE__ */
|
|
95
|
+
/* @__PURE__ */ a(g, { when: f.vignette, children: /* @__PURE__ */ a(
|
|
93
96
|
"div",
|
|
94
97
|
{
|
|
95
98
|
className: "pointer-events-none absolute inset-0",
|
|
96
99
|
style: { background: "radial-gradient(ellipse 75% 65% at 50% 45%, transparent 30%, var(--background) 100%)" }
|
|
97
100
|
}
|
|
98
101
|
) }),
|
|
99
|
-
/* @__PURE__ */
|
|
100
|
-
|
|
102
|
+
/* @__PURE__ */ b("div", { className: "pointer-events-none absolute inset-0 overflow-hidden", children: [
|
|
103
|
+
z.map((e) => /* @__PURE__ */ a(
|
|
101
104
|
"span",
|
|
102
105
|
{
|
|
103
106
|
className: "absolute top-0 left-0 whitespace-nowrap font-medium text-[10px] text-foreground leading-none opacity-0 transition-opacity [text-shadow:0_0_3px_var(--background),0_0_6px_var(--background)]",
|
|
104
|
-
ref:
|
|
107
|
+
ref: K(e.vertex),
|
|
105
108
|
children: e.text
|
|
106
109
|
},
|
|
107
110
|
String(e.vertex)
|
|
108
111
|
)),
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
/* @__PURE__ */ a(
|
|
113
|
+
he,
|
|
111
114
|
{
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
]
|
|
115
|
+
cardRef: B,
|
|
116
|
+
domain: k,
|
|
117
|
+
encoding: N,
|
|
118
|
+
options: o,
|
|
119
|
+
scale: V,
|
|
120
|
+
schedule: v,
|
|
121
|
+
setHovered: P
|
|
120
122
|
}
|
|
121
123
|
)
|
|
122
124
|
] }),
|
|
123
|
-
/* @__PURE__ */
|
|
124
|
-
|
|
125
|
+
/* @__PURE__ */ a(g, { when: U !== null, children: /* @__PURE__ */ b("div", { className: "absolute inset-0 cursor-crosshair", "data-slot": "graph-canvas-gesture", ...H.handlers, children: [
|
|
126
|
+
l && /* @__PURE__ */ a("svg", { className: "pointer-events-none size-full", children: l.tool === "rect" ? /* @__PURE__ */ a(
|
|
125
127
|
"rect",
|
|
126
128
|
{
|
|
127
129
|
className: "stroke-primary",
|
|
128
|
-
height: Math.abs(
|
|
130
|
+
height: Math.abs(l.to[1] - l.from[1]),
|
|
129
131
|
strokeDasharray: "4 3",
|
|
130
132
|
strokeWidth: 1,
|
|
131
|
-
style: { fill:
|
|
132
|
-
width: Math.abs(
|
|
133
|
-
x: Math.min(
|
|
134
|
-
y: Math.min(
|
|
133
|
+
style: { fill: E },
|
|
134
|
+
width: Math.abs(l.to[0] - l.from[0]),
|
|
135
|
+
x: Math.min(l.from[0], l.to[0]),
|
|
136
|
+
y: Math.min(l.from[1], l.to[1])
|
|
135
137
|
}
|
|
136
|
-
) :
|
|
138
|
+
) : l.path.length > 1 && /* @__PURE__ */ a(
|
|
137
139
|
"polygon",
|
|
138
140
|
{
|
|
139
141
|
className: "stroke-primary",
|
|
140
|
-
points:
|
|
142
|
+
points: l.path.map(([e, h]) => `${e},${h}`).join(" "),
|
|
141
143
|
strokeWidth: 1,
|
|
142
|
-
style: { fill:
|
|
144
|
+
style: { fill: E }
|
|
143
145
|
}
|
|
144
146
|
) }),
|
|
145
|
-
/* @__PURE__ */
|
|
147
|
+
/* @__PURE__ */ a(g, { when: O !== null, children: /* @__PURE__ */ b(
|
|
146
148
|
"span",
|
|
147
149
|
{
|
|
148
150
|
className: "pointer-events-none absolute rounded-sm bg-primary px-1.5 py-0.5 font-medium text-[10px] text-primary-foreground tabular-nums",
|
|
149
|
-
style:
|
|
151
|
+
style: ce(l),
|
|
150
152
|
children: [
|
|
151
|
-
|
|
153
|
+
O,
|
|
152
154
|
" node",
|
|
153
|
-
|
|
155
|
+
O === 1 ? "" : "s"
|
|
154
156
|
]
|
|
155
157
|
}
|
|
156
158
|
) })
|
|
157
159
|
] }) }),
|
|
158
|
-
/* @__PURE__ */
|
|
160
|
+
/* @__PURE__ */ a(g, { when: w !== void 0, children: /* @__PURE__ */ a(
|
|
159
161
|
"p",
|
|
160
162
|
{
|
|
161
163
|
className: "pointer-events-none absolute inset-0 grid place-items-center text-muted-foreground text-xs",
|
|
162
164
|
"data-slot": "graph-canvas-waiting",
|
|
163
|
-
children:
|
|
165
|
+
children: w
|
|
164
166
|
}
|
|
165
167
|
) }),
|
|
166
|
-
|
|
168
|
+
u
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
function he({ cardRef: u, domain: d, encoding: i, options: p, scale: s, schedule: c, setHovered: n }) {
|
|
174
|
+
const t = m((w) => w.hovered), r = D(x(() => t === null ? [] : [t], [t]));
|
|
175
|
+
if (y(() => {
|
|
176
|
+
n(t), c();
|
|
177
|
+
}, [t, c, n, r]), t === null || !i || t >= i.ranks.length) return null;
|
|
178
|
+
const o = i.ranks[t] ?? 0, k = o < d.length ? ne(d[o], p.categories) : null;
|
|
179
|
+
return /* @__PURE__ */ b(
|
|
180
|
+
"div",
|
|
181
|
+
{
|
|
182
|
+
className: "absolute top-0 left-0 flex w-max max-w-60 items-center gap-2 rounded-lg border bg-popover px-2.5 py-2 opacity-0 shadow-lg",
|
|
183
|
+
"data-slot": "graph-canvas-card",
|
|
184
|
+
ref: u,
|
|
185
|
+
children: [
|
|
186
|
+
/* @__PURE__ */ a(de, { className: "size-2.5 shrink-0", color: s.color(o), shape: s.shape(o) }),
|
|
187
|
+
/* @__PURE__ */ a("span", { className: "truncate font-medium text-popover-foreground text-sm leading-none", children: r.get(t) || `#${t}` }),
|
|
188
|
+
/* @__PURE__ */ a(g, { when: k !== null, children: /* @__PURE__ */ a("span", { className: "text-muted-foreground text-xs", children: k }) })
|
|
167
189
|
]
|
|
168
190
|
}
|
|
169
191
|
);
|
|
170
192
|
}
|
|
171
193
|
export {
|
|
172
|
-
|
|
194
|
+
Me as GraphCanvas
|
|
173
195
|
};
|
|
174
196
|
//# sourceMappingURL=graph-canvas.js.map
|