@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/render/renderer.js
CHANGED
|
@@ -1,43 +1,41 @@
|
|
|
1
|
-
import { Graph as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const t = A();
|
|
30
|
-
t && i.setViewport(t.view);
|
|
1
|
+
import { Graph as j } from "@cosmos.gl/graph";
|
|
2
|
+
import { resolveLook as B } from "./graph-looks.js";
|
|
3
|
+
import { forces as x, appearance as H, paint as $ } from "./graph-model.js";
|
|
4
|
+
import { resolveSim as M } from "./graph-sim.js";
|
|
5
|
+
import { hasWebGL as J, releaseContext as K } from "./webgl.js";
|
|
6
|
+
const C = 420, z = 0.18, S = 0.35, V = 20, _ = (s) => [s.x, s.y, s.x + s.w, s.y + s.h];
|
|
7
|
+
function Q(s, i) {
|
|
8
|
+
if (!i) return s.positions;
|
|
9
|
+
const e = s.positions.slice();
|
|
10
|
+
for (let l = 0; l < s.size; l++)
|
|
11
|
+
i[l] || (e[l * 2] = e[l * 2 + 1] = Number.NaN);
|
|
12
|
+
return e;
|
|
13
|
+
}
|
|
14
|
+
function on(s, i, e = {}) {
|
|
15
|
+
const l = (n) => i.getOptions().onFailure(n);
|
|
16
|
+
if (!J())
|
|
17
|
+
return l("This canvas renders on the GPU, and this browser offers no WebGL context."), null;
|
|
18
|
+
let h = M(i.getOptions().sim), f = i.getOptions().simulate ?? !1, k = null, y = null, D = -1;
|
|
19
|
+
const F = (n) => {
|
|
20
|
+
const t = Math.round(n * V);
|
|
21
|
+
t !== D && (D = t, i.reportProgress(t / V));
|
|
22
|
+
};
|
|
23
|
+
let P = B(i.getOptions().look), I = i.getOptions().look;
|
|
24
|
+
const r = { positions: !0, paint: !0, state: !0, pinned: !0 };
|
|
25
|
+
let g = 0, L = !1, T = null, b = null, u = i.getSnapshot(), p = i.getOptions();
|
|
26
|
+
const E = () => {
|
|
27
|
+
var n;
|
|
28
|
+
return ((n = i.getSnapshot().geometry) == null ? void 0 : n.size) ?? 0;
|
|
31
29
|
};
|
|
32
|
-
let
|
|
30
|
+
let o;
|
|
33
31
|
try {
|
|
34
|
-
|
|
35
|
-
// No `spaceSize` here: the box is the corpus's extent, set when the
|
|
36
|
-
// `rescalePositions: false` because the corpus's coordinates are the camera's
|
|
37
|
-
// between them means the cull and the viewport describe different places.
|
|
32
|
+
o = new j(s, {
|
|
33
|
+
// No `spaceSize` here: the box is the corpus's extent, set when the graph has loaded.
|
|
34
|
+
// `rescalePositions: false` because the corpus's coordinates are the camera's.
|
|
38
35
|
rescalePositions: !1,
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
transitionDuration: 0,
|
|
37
|
+
enableSimulation: f,
|
|
38
|
+
...x(h),
|
|
41
39
|
// Frames to convergence: alpha reaches its floor after exactly this many rendered frames.
|
|
42
40
|
simulationDecay: 400,
|
|
43
41
|
randomSeed: "kanzo-discovery",
|
|
@@ -47,189 +45,135 @@ function xt(u, i, l = {}) {
|
|
|
47
45
|
attribution: "",
|
|
48
46
|
onSimulationStart: () => i.report("running"),
|
|
49
47
|
onSimulationEnd: () => {
|
|
50
|
-
var
|
|
51
|
-
i.report("settled"),
|
|
48
|
+
var n;
|
|
49
|
+
i.report("settled"), F(1), (n = e.onFrame) == null || n.call(e);
|
|
52
50
|
},
|
|
53
51
|
onSimulationPause: () => i.report("paused"),
|
|
54
52
|
onSimulationUnpause: () => i.report("running"),
|
|
55
|
-
onSimulationTick: () => {
|
|
56
|
-
var
|
|
57
|
-
|
|
53
|
+
onSimulationTick: (n, t, a) => {
|
|
54
|
+
var c, d;
|
|
55
|
+
F(o.progress), t !== void 0 && a && ((c = e.onHover) == null || c.call(e, a)), (d = e.onFrame) == null || d.call(e);
|
|
58
56
|
},
|
|
59
57
|
onZoom: () => {
|
|
60
|
-
var
|
|
61
|
-
|
|
58
|
+
var n;
|
|
59
|
+
return (n = e.onFrame) == null ? void 0 : n.call(e);
|
|
62
60
|
},
|
|
63
|
-
onPointMouseOver: (t) => {
|
|
64
|
-
|
|
61
|
+
onPointMouseOver: (n, t) => {
|
|
62
|
+
var a;
|
|
63
|
+
k = n, (a = e.onHover) == null || a.call(e, t), i.hover(n);
|
|
65
64
|
},
|
|
66
65
|
onPointMouseOut: () => {
|
|
67
|
-
|
|
66
|
+
var n;
|
|
67
|
+
k = null, (n = e.onHover) == null || n.call(e, null), i.hover(null);
|
|
68
68
|
},
|
|
69
69
|
onDragStart: () => {
|
|
70
|
-
|
|
70
|
+
y = k;
|
|
71
71
|
},
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
onDrag: (n) => {
|
|
73
|
+
var t, a;
|
|
74
|
+
(t = e.onHover) == null || t.call(e, o.screenToSpacePosition([n.x, n.y])), (a = e.onFrame) == null || a.call(e);
|
|
75
75
|
},
|
|
76
|
-
|
|
77
|
-
const n =
|
|
78
|
-
n !==
|
|
76
|
+
onDragEnd: () => {
|
|
77
|
+
const n = y;
|
|
78
|
+
y = null, n !== null && i.pin([...i.getSnapshot().pinned, n]);
|
|
79
79
|
},
|
|
80
|
-
|
|
80
|
+
onPointClick: (n) => R(n),
|
|
81
|
+
onBackgroundClick: () => A()
|
|
81
82
|
});
|
|
82
|
-
} catch (
|
|
83
|
-
return
|
|
83
|
+
} catch (n) {
|
|
84
|
+
return l(`The renderer failed to start. (${String(n)})`), null;
|
|
84
85
|
}
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
const w = () => {
|
|
87
|
+
g || (g = requestAnimationFrame(() => {
|
|
88
|
+
g = 0, q();
|
|
88
89
|
}));
|
|
89
90
|
};
|
|
90
|
-
function
|
|
91
|
-
var
|
|
92
|
-
const n = i.getSnapshot(),
|
|
93
|
-
let
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
typeIndex: n.typeIndex,
|
|
99
|
-
binding: n.binding,
|
|
100
|
-
modeColumn: n.modeColumn,
|
|
101
|
-
domain: n.domain,
|
|
102
|
-
visible: n.visible,
|
|
103
|
-
cached: n.cached,
|
|
104
|
-
perPixel: ((p = A()) == null ? void 0 : p.perPixel) ?? 0
|
|
105
|
-
});
|
|
106
|
-
if (s && (m = s, t.setPointPositions(s.positions, !0), t.setLinks(s.links), a.paint = !0, a.state = !0, r = !0, (g = l.onComposed) == null || g.call(l, s), S !== null && s.resident.indexOf(S) !== void 0)) {
|
|
107
|
-
const tt = S;
|
|
108
|
-
S = null, queueMicrotask(() => q(tt));
|
|
109
|
-
}
|
|
110
|
-
const v = s && { marks: s.marks, represented: s.represented, domain: s.domain, tally: s.tally };
|
|
111
|
-
i.reportDrawn(n.visible, v);
|
|
91
|
+
function q() {
|
|
92
|
+
var N;
|
|
93
|
+
const n = i.getSnapshot(), { geometry: t, encoding: a } = n, c = i.getOptions();
|
|
94
|
+
let d = !1;
|
|
95
|
+
if (r.positions && t && (r.positions = !1, U(t), o.setPointPositions(Q(t, n.mask), !0), t.links !== b && (b = t.links, o.setLinks(b), r.paint = r.state = r.pinned = !0), d = !0), r.paint && t && a) {
|
|
96
|
+
r.paint = !1;
|
|
97
|
+
const m = $(t, a, P, s, c);
|
|
98
|
+
o.setPointColors(m.colors), o.setPointSizes(m.sizes), o.setPointShapes(m.shapes), o.setLinkColors(m.linkColors), o.setConfigPartial(H(P, s)), d = !0;
|
|
112
99
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
if (a.state && m) {
|
|
119
|
-
a.state = !1;
|
|
120
|
-
const s = m.resident;
|
|
121
|
-
t.setConfigPartial({
|
|
122
|
-
highlightedPointIndices: n.selection ? s.indicesOf(n.selection.vertices) : void 0,
|
|
123
|
-
focusedPointIndex: n.focus === null ? void 0 : s.indexOf(n.focus)
|
|
124
|
-
});
|
|
125
|
-
const v = s.indicesOf(n.pinned);
|
|
126
|
-
t.setPinnedPoints(v.length > 0 ? v : null), r = !0;
|
|
127
|
-
}
|
|
128
|
-
r && t.render(), (f = l.onFrame) == null || f.call(l);
|
|
100
|
+
r.state && t && (r.state = !1, o.setConfigPartial({
|
|
101
|
+
highlightedPointIndices: n.selection ? n.selection.vertices.filter((m) => m < t.size) : void 0,
|
|
102
|
+
focusedPointIndex: n.focus === null || n.focus >= t.size ? void 0 : n.focus
|
|
103
|
+
})), r.pinned && t && (r.pinned = !1, o.setPinnedPoints(n.pinned.length > 0 ? [...n.pinned] : null)), d && o.render(), t && a && !r.paint && i.reportDrawn(n), (N = e.onFrame) == null || N.call(e);
|
|
129
104
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}, J = i.subscribe(() => {
|
|
137
|
-
const t = i.getSnapshot(), n = i.getOptions();
|
|
138
|
-
G(t), (t.visible !== d.visible || t.binding !== d.binding || t.domain !== d.domain) && (a.compose = !0), n.look !== E && (E = n.look, O = U(n.look), a.paint = !0), (n.fill !== P.fill || n.symbol !== P.symbol || n.stroke !== P.stroke) && (a.paint = !0), (t.selection !== d.selection || t.focus !== d.focus || t.pinned !== d.pinned) && (a.state = !0), (n.sim !== P.sim || n.simulate !== P.simulate) && K(n.sim, n.simulate), d = t, P = n, (a.compose || a.paint || a.state) && T();
|
|
105
|
+
function U(n) {
|
|
106
|
+
n === T || !n.extent || (T = n, o.setConfigPartial({ spaceSize: Math.max(n.extent.w, n.extent.h) }), o.fitViewByPointPositions(_(n.extent), 0, z));
|
|
107
|
+
}
|
|
108
|
+
const W = i.subscribe(() => {
|
|
109
|
+
const n = i.getSnapshot(), t = i.getOptions();
|
|
110
|
+
(n.geometry !== u.geometry || n.mask !== u.mask) && (r.positions = !0), n.encoding !== u.encoding && (r.paint = !0), t.look !== I && (I = t.look, P = B(t.look), r.paint = !0), (t.fill !== p.fill || t.symbol !== p.symbol || t.stroke !== p.stroke) && (r.paint = !0), (n.selection !== u.selection || n.focus !== u.focus) && (r.state = !0), n.pinned !== u.pinned && (r.pinned = !0), t.sim !== p.sim && Z(t.sim), (t.simulate ?? !1) !== (p.simulate ?? !1) && (t.simulate ? O(S) : o.pause()), u = n, p = t, (r.positions || r.paint || r.state || r.pinned) && w();
|
|
139
111
|
});
|
|
140
|
-
function
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
p.setConfigPartial({ enableSimulation: n, ...Z(o) }), n && r && p.start(L);
|
|
144
|
-
});
|
|
112
|
+
function Z(n) {
|
|
113
|
+
const t = M(n), a = Object.keys(t).some((c) => t[c] !== h[c]);
|
|
114
|
+
h = t, f && (o.setConfigPartial(x(t)), a && i.getSnapshot().motion !== "paused" && o.start(S));
|
|
145
115
|
}
|
|
146
|
-
function
|
|
147
|
-
|
|
148
|
-
i.select([t, ...r], "node", "Node"), i.focus(t);
|
|
116
|
+
function O(n) {
|
|
117
|
+
f || (f = !0, o.setConfigPartial({ enableSimulation: !0, ...x(h) })), o.start(n);
|
|
149
118
|
}
|
|
150
|
-
function
|
|
151
|
-
|
|
119
|
+
function R(n) {
|
|
120
|
+
const t = o.getNeighboringPointIndices(n) ?? [];
|
|
121
|
+
i.select([n, ...t], "node", "Node"), i.focus(n);
|
|
152
122
|
}
|
|
153
|
-
function
|
|
154
|
-
|
|
155
|
-
const n = h().indexOf(t);
|
|
156
|
-
if (n !== void 0) {
|
|
157
|
-
V(t, n), c(e, (s) => s.zoomToPointByIndex(n, 500, 5, !0));
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
const o = i.getSnapshot().matrix, r = o ? et(o, it(t)) : null, p = r && ((f = (g = o == null ? void 0 : o.tileMatrices[r.z]) == null ? void 0 : g.tiles[r.tile]) == null ? void 0 : f.bbox);
|
|
161
|
-
p && (S = t, c(e, (s) => s.fitViewByPointPositions(C(p), b, k)));
|
|
123
|
+
function A() {
|
|
124
|
+
i.select(null), i.focus(null);
|
|
162
125
|
}
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
return i.report(i.getOptions().simulate && e.isSimulationRunning ? "running" : "settled"), G(d), T(), {
|
|
173
|
-
graph: e,
|
|
174
|
-
resident: h,
|
|
175
|
-
composition: () => m,
|
|
126
|
+
o.setConfigPartial(H(P, s)), o.render();
|
|
127
|
+
const G = (n) => {
|
|
128
|
+
n.preventDefault(), l("The graph's WebGL context was lost. A browser keeps a limited number of them and drops the oldest; reload the page to get one back.");
|
|
129
|
+
};
|
|
130
|
+
return o.ready.then(() => {
|
|
131
|
+
var n;
|
|
132
|
+
L || (n = s.querySelector("canvas")) == null || n.addEventListener("webglcontextlost", G);
|
|
133
|
+
}), i.report(f && o.isSimulationRunning ? "running" : "settled"), w(), {
|
|
134
|
+
graph: o,
|
|
176
135
|
repaint() {
|
|
177
|
-
|
|
136
|
+
r.paint = !0, w();
|
|
178
137
|
},
|
|
179
|
-
hit(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return Array.from(n);
|
|
138
|
+
hit(n) {
|
|
139
|
+
const t = "rect" in n ? o.findPointsInRect(n.rect) : o.findPointsInPolygon(n.polygon);
|
|
140
|
+
return Array.from(t);
|
|
183
141
|
},
|
|
184
|
-
zoomBy(
|
|
185
|
-
|
|
142
|
+
zoomBy(n) {
|
|
143
|
+
o.setZoomLevel(o.getZoomLevel() * n, 220);
|
|
186
144
|
},
|
|
187
145
|
fit() {
|
|
188
|
-
var
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
e,
|
|
192
|
-
(o) => t ? o.fitViewByPointPositions(C(t), b, k) : o.fitView(b, k)
|
|
193
|
-
);
|
|
146
|
+
var t;
|
|
147
|
+
const n = (t = i.getSnapshot().geometry) == null ? void 0 : t.extent;
|
|
148
|
+
n ? o.fitViewByPointPositions(_(n), C, z) : o.fitView(C, z);
|
|
194
149
|
},
|
|
195
|
-
pause: () =>
|
|
150
|
+
pause: () => o.pause(),
|
|
196
151
|
resume() {
|
|
197
|
-
|
|
198
|
-
c(e, (n) => t ? n.start(L) : n.unpause());
|
|
152
|
+
i.getSnapshot().motion === "settled" || !f ? O(S) : o.unpause();
|
|
199
153
|
},
|
|
200
154
|
restart() {
|
|
201
|
-
i.pin([]),
|
|
155
|
+
i.pin([]), O(1);
|
|
202
156
|
},
|
|
203
157
|
unpin() {
|
|
204
|
-
i.getSnapshot().pinned.length !== 0 && (i.pin([]),
|
|
158
|
+
i.getSnapshot().pinned.length !== 0 && (i.pin([]), i.getSnapshot().motion === "running" && o.start(S));
|
|
205
159
|
},
|
|
206
|
-
reveal
|
|
207
|
-
|
|
208
|
-
c(e, (r) => r.fitViewByPointPositions(C(t), n, o));
|
|
160
|
+
reveal(n) {
|
|
161
|
+
n >= E() || (R(n), o.zoomToPointByIndex(n, 500, 5, !0));
|
|
209
162
|
},
|
|
210
163
|
frameSelection() {
|
|
211
|
-
var
|
|
212
|
-
const
|
|
213
|
-
|
|
164
|
+
var t;
|
|
165
|
+
const n = (((t = i.getSnapshot().selection) == null ? void 0 : t.vertices) ?? []).filter((a) => a < E());
|
|
166
|
+
n.length > 0 && o.fitViewByPointIndices(n, C, 0.25);
|
|
214
167
|
},
|
|
215
|
-
clear:
|
|
168
|
+
clear: A,
|
|
216
169
|
destroy() {
|
|
217
|
-
|
|
218
|
-
const
|
|
219
|
-
|
|
170
|
+
W(), g && cancelAnimationFrame(g), L = !0;
|
|
171
|
+
const n = s.querySelector("canvas");
|
|
172
|
+
n == null || n.removeEventListener("webglcontextlost", G), o.destroy(), K(n);
|
|
220
173
|
}
|
|
221
174
|
};
|
|
222
175
|
}
|
|
223
|
-
const lt = {
|
|
224
|
-
size: 0,
|
|
225
|
-
indexOf: () => {
|
|
226
|
-
},
|
|
227
|
-
at: () => {
|
|
228
|
-
},
|
|
229
|
-
indicesOf: () => [],
|
|
230
|
-
verticesAt: () => []
|
|
231
|
-
};
|
|
232
176
|
export {
|
|
233
|
-
|
|
177
|
+
on as createRenderer
|
|
234
178
|
};
|
|
235
179
|
//# sourceMappingURL=renderer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.js","sources":["../../src/render/renderer.ts"],"sourcesContent":["import { Graph } from \"@cosmos.gl/graph\";\nimport type { Box } from \"@fossil-lang/corpus\";\nimport type { Resident, VertexId } from \"../core/resident\";\nimport { denseOf } from \"../core/resident\";\nimport type { GraphSnapshot, GraphStore } from \"../core/store\";\nimport { tileOfDense, type Viewport } from \"../core/tile-matrix\";\nimport type { GraphCommands } from \"../core/types\";\nimport { createComposer, type Composition } from \"./compose\";\nimport { resolveLook, type Look } from \"./graph-looks\";\nimport { appearance, forces, paint } from \"./graph-model\";\nimport { resolveSim, type Sim } from \"./graph-sim\";\nimport { isReady, whenReady } from \"./when-ready\";\nimport { hasWebGL, releaseContext } from \"./webgl\";\n\nexport interface RendererEvents {\n /** After every frame and every camera move — where the overlays repaint. */\n onFrame?: () => void;\n /** A new composition was uploaded. */\n onComposed?: (composition: Composition) => void;\n}\n\nexport interface Renderer extends GraphCommands {\n readonly graph: Graph;\n resident(): Resident;\n composition(): Composition | null;\n /** The theme moved under the canvas: colours are resolved again, nothing else. */\n repaint(): void;\n /** The drawn points inside a screen rectangle or polygon, once the device is ready. */\n hit(shape: { rect: [[number, number], [number, number]] } | { polygon: [number, number][] }): number[];\n destroy(): void;\n}\n\nconst FIT_DURATION = 420;\nconst FIT_PADDING = 0.18;\nconst REHEAT = 0.35;\n/** Twentieths: a settle costs twenty reports rather than one per frame. */\nconst PROGRESS_STEPS = 20;\n\nconst corners = (box: Box) => [box.x, box.y, box.x + box.w, box.y + box.h];\n\n/**\n * **cosmos.gl's lifetime, and the frame that renders once.** Built once per element; it subscribes to\n * the store and discharges what changed in one `requestAnimationFrame`:\n *\n * - a change of visible tiles recomposes, and dirties positions, links and the per-point arrays;\n * - a look or a theme change dirties colours, sizes and shapes and nothing else;\n * - a selection, a focus or a pin sets two config fields and uploads nothing;\n * - a snapshot that changed none of those schedules nothing.\n *\n * Every callback reads the store's latest options, so a host's inline `onFailure` never rebuilds it.\n */\nexport function createRenderer(host: HTMLDivElement, store: GraphStore, events: RendererEvents = {}): Renderer | null {\n const fail = (message: string) => store.getOptions().onFailure(message);\n if (!hasWebGL()) {\n fail(\"This canvas renders on the GPU, and this browser offers no WebGL context.\");\n return null;\n }\n\n let sim: Sim = resolveSim(store.getOptions().sim);\n let hovering: number | null = null;\n let dragging: number | null = null;\n let reported = -1;\n const progress = (value: number) => {\n const bucket = Math.round(value * PROGRESS_STEPS);\n if (bucket === reported) return;\n reported = bucket;\n store.reportProgress(bucket / PROGRESS_STEPS);\n };\n\n const compose = createComposer();\n let composition: Composition | null = null;\n let look: Look = resolveLook(store.getOptions().look);\n let lookPatch = store.getOptions().look;\n const dirty = { compose: true, paint: true, state: true };\n let frame = 0;\n let framed: GraphSnapshot[\"matrix\"] = null;\n let pendingReveal: VertexId | null = null;\n let last = store.getSnapshot();\n let lastOptions = store.getOptions();\n\n const resident = () => composition?.resident ?? EMPTY;\n\n const viewport = (): { view: Viewport; perPixel: number } | null => {\n const { height, width } = host.getBoundingClientRect();\n if (!isReady(graph) || width === 0 || height === 0) return null;\n const [ax, ay] = graph.screenToSpacePosition([0, 0]);\n const [bx, by] = graph.screenToSpacePosition([width, height]);\n const view = { xMin: Math.min(ax, bx), yMin: Math.min(ay, by), xMax: Math.max(ax, bx), yMax: Math.max(ay, by) };\n return { view, perPixel: (view.xMax - view.xMin) / width };\n };\n const observe = () => {\n const camera = viewport();\n if (camera) store.setViewport(camera.view);\n };\n\n let graph: Graph;\n try {\n graph = new Graph(host, {\n // No `spaceSize` here: the box is the corpus's extent, set when the matrix arrives.\n // `rescalePositions: false` because the corpus's coordinates are the camera's — a rescale\n // between them means the cull and the viewport describe different places.\n rescalePositions: false,\n enableSimulation: store.getOptions().simulate ?? false,\n ...forces(sim),\n // Frames to convergence: alpha reaches its floor after exactly this many rendered frames.\n simulationDecay: 400,\n randomSeed: \"kanzo-discovery\",\n pixelRatio: window.devicePixelRatio || 1,\n enableDrag: true,\n hoveredPointCursor: \"pointer\",\n attribution: \"\",\n onSimulationStart: () => store.report(\"running\"),\n onSimulationEnd: () => {\n store.report(\"settled\");\n progress(1);\n events.onFrame?.();\n },\n onSimulationPause: () => store.report(\"paused\"),\n onSimulationUnpause: () => store.report(\"running\"),\n onSimulationTick: () => {\n progress(graph.progress);\n events.onFrame?.();\n },\n onZoom: () => {\n observe();\n events.onFrame?.();\n },\n onPointMouseOver: (index) => {\n hovering = index;\n store.hover(resident().at(index) ?? null);\n },\n onPointMouseOut: () => {\n hovering = null;\n store.hover(null);\n },\n onDragStart: () => {\n dragging = hovering;\n },\n onDragEnd: () => {\n const vertex = dragging === null ? undefined : resident().at(dragging);\n dragging = null;\n if (vertex !== undefined) store.pin([...store.getSnapshot().pinned, vertex]);\n },\n onPointClick: (index) => {\n const vertex = resident().at(index);\n if (vertex !== undefined) focusOn(vertex, index);\n },\n onBackgroundClick: () => clear(),\n });\n } catch (error) {\n fail(`The renderer failed to start. (${String(error)})`);\n return null;\n }\n\n const schedule = () => {\n if (frame) return;\n frame = requestAnimationFrame(() => {\n frame = 0;\n whenReady(graph, draw);\n });\n };\n\n function draw(ready: Graph): void {\n const snapshot = store.getSnapshot();\n const options = store.getOptions();\n let changed = false;\n if (dirty.compose && snapshot.matrix) {\n dirty.compose = false;\n const next = compose({\n matrix: snapshot.matrix,\n typeIndex: snapshot.typeIndex,\n binding: snapshot.binding,\n modeColumn: snapshot.modeColumn,\n domain: snapshot.domain,\n visible: snapshot.visible,\n cached: snapshot.cached,\n perPixel: viewport()?.perPixel ?? 0,\n });\n if (next) {\n composition = next;\n ready.setPointPositions(next.positions, true);\n ready.setLinks(next.links);\n dirty.paint = true;\n dirty.state = true;\n changed = true;\n events.onComposed?.(next);\n if (pendingReveal !== null && next.resident.indexOf(pendingReveal) !== undefined) {\n const vertex = pendingReveal;\n pendingReveal = null;\n queueMicrotask(() => reveal(vertex));\n }\n }\n const drawn = next && { marks: next.marks, represented: next.represented, domain: next.domain, tally: next.tally };\n store.reportDrawn(snapshot.visible, drawn);\n }\n if (dirty.paint && composition) {\n dirty.paint = false;\n const buffers = paint(composition, look, host, options);\n ready.setPointColors(buffers.colors);\n ready.setPointSizes(buffers.sizes);\n ready.setPointShapes(buffers.shapes);\n ready.setLinkColors(buffers.linkColors);\n ready.setLinkWidths(buffers.linkWidths);\n ready.setConfigPartial(appearance(look, host));\n changed = true;\n }\n if (dirty.state && composition) {\n dirty.state = false;\n const drawn = composition.resident;\n ready.setConfigPartial({\n highlightedPointIndices: snapshot.selection ? drawn.indicesOf(snapshot.selection.vertices) : undefined,\n focusedPointIndex: snapshot.focus === null ? undefined : drawn.indexOf(snapshot.focus),\n });\n const pinned = drawn.indicesOf(snapshot.pinned);\n ready.setPinnedPoints(pinned.length > 0 ? pinned : null);\n changed = true;\n }\n if (changed) ready.render();\n events.onFrame?.();\n }\n\n const frameExtent = (snapshot: GraphSnapshot) => {\n const extent = snapshot.matrix?.extent;\n if (!extent || snapshot.matrix === framed) return;\n framed = snapshot.matrix;\n whenReady(graph, (ready) => {\n ready.setConfigPartial({ spaceSize: Math.max(extent.w, extent.h) });\n ready.fitViewByPointPositions(corners(extent), 0, FIT_PADDING);\n observe();\n });\n };\n\n const unsubscribe = store.subscribe(() => {\n const snapshot = store.getSnapshot();\n const options = store.getOptions();\n frameExtent(snapshot);\n if (snapshot.visible !== last.visible || snapshot.binding !== last.binding || snapshot.domain !== last.domain) {\n dirty.compose = true;\n }\n if (options.look !== lookPatch) {\n lookPatch = options.look;\n look = resolveLook(options.look);\n dirty.paint = true;\n }\n if (options.fill !== lastOptions.fill || options.symbol !== lastOptions.symbol || options.stroke !== lastOptions.stroke) {\n dirty.paint = true;\n }\n if (snapshot.selection !== last.selection || snapshot.focus !== last.focus || snapshot.pinned !== last.pinned) {\n dirty.state = true;\n }\n if (options.sim !== lastOptions.sim || options.simulate !== lastOptions.simulate) applyForces(options.sim, options.simulate);\n last = snapshot;\n lastOptions = options;\n if (dirty.compose || dirty.paint || dirty.state) schedule();\n });\n\n function applyForces(patch: Partial<Sim> | undefined, simulate = false): void {\n const next = resolveSim(patch);\n const moved = Object.keys(next).some((key) => next[key as keyof Sim] !== sim[key as keyof Sim]);\n sim = next;\n whenReady(graph, (ready) => {\n ready.setConfigPartial({ enableSimulation: simulate, ...forces(next) });\n if (simulate && moved) ready.start(REHEAT);\n });\n }\n\n function focusOn(vertex: VertexId, index: number): void {\n const drawn = resident();\n const around = isReady(graph) ? drawn.verticesAt(graph.getNeighboringPointIndices(index)) : [];\n store.select([vertex, ...around], \"node\", \"Node\");\n store.focus(vertex);\n }\n\n function clear(): void {\n store.select(null);\n store.focus(null);\n }\n\n /** Centre and select one vertex; one that is not drawn is framed by its tile first, then revealed. */\n function reveal(vertex: VertexId): void {\n const index = resident().indexOf(vertex);\n if (index !== undefined) {\n focusOn(vertex, index);\n whenReady(graph, (ready) => ready.zoomToPointByIndex(index, 500, 5, true));\n return;\n }\n const matrix = store.getSnapshot().matrix;\n const address = matrix ? tileOfDense(matrix, denseOf(vertex)) : null;\n const box = address && matrix?.tileMatrices[address.z]?.tiles[address.tile]?.bbox;\n if (!box) return;\n pendingReveal = vertex;\n whenReady(graph, (ready) => ready.fitViewByPointPositions(corners(box), FIT_DURATION, FIT_PADDING));\n }\n\n // Primed first, so every `whenReady` below runs with `isReady` already answering true.\n isReady(graph);\n const painted = whenReady(graph, (ready) => {\n ready.setConfigPartial(appearance(look, host));\n ready.render();\n });\n const onLost = (event: Event) => {\n event.preventDefault();\n fail(\"The graph's WebGL context was lost. A browser keeps a limited number of them and drops the oldest; reload the page to get one back.\");\n };\n // Inside `whenReady`: cosmos.gl makes its canvas with the device, which is asynchronous.\n const listening = whenReady(graph, () => {\n host.querySelector(\"canvas\")?.addEventListener(\"webglcontextlost\", onLost);\n });\n store.report(store.getOptions().simulate && graph.isSimulationRunning ? \"running\" : \"settled\");\n frameExtent(last);\n schedule();\n\n return {\n graph,\n resident,\n composition: () => composition,\n repaint() {\n dirty.paint = true;\n schedule();\n },\n hit(shape) {\n if (!isReady(graph)) return [];\n const found = \"rect\" in shape ? graph.findPointsInRect(shape.rect) : graph.findPointsInPolygon(shape.polygon);\n return Array.from(found);\n },\n zoomBy(factor) {\n whenReady(graph, (ready) => ready.setZoomLevel(ready.getZoomLevel() * factor, 220));\n },\n fit() {\n const extent = store.getSnapshot().matrix?.extent;\n whenReady(graph, (ready) =>\n extent ? ready.fitViewByPointPositions(corners(extent), FIT_DURATION, FIT_PADDING) : ready.fitView(FIT_DURATION, FIT_PADDING),\n );\n },\n pause: () => whenReady(graph, (ready) => ready.pause()),\n resume() {\n const settled = store.getSnapshot().motion === \"settled\";\n whenReady(graph, (ready) => (settled ? ready.start(REHEAT) : ready.unpause()));\n },\n restart() {\n store.pin([]);\n whenReady(graph, (ready) => ready.start(1));\n },\n unpin() {\n if (store.getSnapshot().pinned.length === 0) return;\n store.pin([]);\n whenReady(graph, (ready) => ready.start(REHEAT));\n },\n reveal,\n frameBox(box, { duration = FIT_DURATION, padding = FIT_PADDING } = {}) {\n whenReady(graph, (ready) => ready.fitViewByPointPositions(corners(box), duration, padding));\n },\n frameSelection() {\n const indices = resident().indicesOf(store.getSnapshot().selection?.vertices ?? []);\n if (indices.length > 0) whenReady(graph, (ready) => ready.fitViewByPointIndices(indices, FIT_DURATION, 0.25));\n },\n clear,\n destroy() {\n unsubscribe();\n if (frame) cancelAnimationFrame(frame);\n painted();\n listening();\n // Read here rather than remembered from construction: the element exists only with the device.\n const canvas = host.querySelector(\"canvas\");\n canvas?.removeEventListener(\"webglcontextlost\", onLost);\n graph.destroy();\n releaseContext(canvas);\n },\n };\n}\n\nconst EMPTY: Resident = {\n size: 0,\n indexOf: () => undefined,\n at: () => undefined,\n indicesOf: () => [],\n verticesAt: () => [],\n};\n"],"names":["FIT_DURATION","FIT_PADDING","REHEAT","PROGRESS_STEPS","corners","box","createRenderer","host","store","events","fail","message","hasWebGL","sim","resolveSim","hovering","dragging","reported","progress","value","bucket","compose","createComposer","composition","look","resolveLook","lookPatch","dirty","frame","framed","pendingReveal","last","lastOptions","resident","EMPTY","viewport","height","width","isReady","graph","ax","ay","bx","by","view","observe","camera","Graph","forces","_a","index","vertex","focusOn","clear","error","schedule","whenReady","draw","ready","snapshot","options","changed","next","_b","reveal","drawn","buffers","paint","appearance","pinned","_c","frameExtent","extent","unsubscribe","applyForces","patch","simulate","moved","key","around","matrix","address","tileOfDense","denseOf","painted","onLost","event","listening","shape","found","factor","settled","duration","padding","indices","canvas","releaseContext"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"renderer.js","sources":["../../src/render/renderer.ts"],"sourcesContent":["import { Graph } from \"@cosmos.gl/graph\";\nimport type { Geometry } from \"../core/load\";\nimport type { GraphStore } from \"../core/store\";\nimport type { GraphCommands, VertexId } from \"../core/types\";\nimport { resolveLook, type Look } from \"./graph-looks\";\nimport { appearance, forces, paint } from \"./graph-model\";\nimport { resolveSim, type Sim } from \"./graph-sim\";\nimport { hasWebGL, releaseContext } from \"./webgl\";\n\nexport interface RendererEvents {\n /** After every frame and every camera move — where the overlays repaint. */\n onFrame?: () => void;\n /** Where the hovered point is in space, as cosmos.gl reports it: no GPU readback per hover. */\n onHover?: (position: [number, number] | null) => void;\n}\n\nexport interface Renderer extends GraphCommands {\n readonly graph: Graph;\n /** The theme moved under the canvas: colours are resolved again, nothing else. */\n repaint(): void;\n /** The drawn points inside a screen rectangle or polygon, once the device is ready. */\n hit(shape: { rect: [[number, number], [number, number]] } | { polygon: [number, number][] }): number[];\n destroy(): void;\n}\n\nconst FIT_DURATION = 420;\nconst FIT_PADDING = 0.18;\nconst REHEAT = 0.35;\n/** Twentieths: a settle costs twenty reports rather than one per frame. */\nconst PROGRESS_STEPS = 20;\n\ntype Extent = NonNullable<Geometry[\"extent\"]>;\nconst corners = (box: Extent) => [box.x, box.y, box.x + box.w, box.y + box.h];\n\n/** The loaded positions, with `NaN` where the page's filter hides a vertex — cosmos.gl draws no such point. */\nfunction shown(geometry: Geometry, mask: Uint8Array | null): Float32Array {\n if (!mask) return geometry.positions;\n const positions = geometry.positions.slice();\n for (let id = 0; id < geometry.size; id++) {\n if (!mask[id]) positions[id * 2] = positions[id * 2 + 1] = Number.NaN;\n }\n return positions;\n}\n\n/**\n * **cosmos.gl's lifetime, and the frame that renders once.** Built once per element; it subscribes to\n * the store and discharges what changed in one `requestAnimationFrame`:\n *\n * - a new graph uploads positions and links, once per corpus; a filter uploads positions alone;\n * - a binding, a look or a theme change uploads colours, sizes and shapes and nothing else;\n * - a selection, a focus or a pin sets config and uploads nothing, and never calls `render()`:\n * `render()` walks every point and link in JS, and `setConfigPartial` asks for its own frame;\n * - the camera reaches nothing: cosmos.gl moves it, and the overlays follow.\n *\n * A vertex's id is its index here, so nothing is resolved between the store and the buffers.\n * `transitionDuration` is 0: the default animates every upload for 800 ms and keeps the loop awake.\n * The live layout is off unless `simulate` or the toolbar asks, and runs from the current positions.\n * Every callback reads the store's latest options, so a host's inline `onFailure` never rebuilds it.\n */\nexport function createRenderer(host: HTMLDivElement, store: GraphStore, events: RendererEvents = {}): Renderer | null {\n const fail = (message: string) => store.getOptions().onFailure(message);\n if (!hasWebGL()) {\n fail(\"This canvas renders on the GPU, and this browser offers no WebGL context.\");\n return null;\n }\n\n let sim: Sim = resolveSim(store.getOptions().sim);\n let live = store.getOptions().simulate ?? false;\n let hovering: number | null = null;\n let dragging: number | null = null;\n let reported = -1;\n const progress = (value: number) => {\n const bucket = Math.round(value * PROGRESS_STEPS);\n if (bucket === reported) return;\n reported = bucket;\n store.reportProgress(bucket / PROGRESS_STEPS);\n };\n\n let look: Look = resolveLook(store.getOptions().look);\n let lookPatch = store.getOptions().look;\n const dirty = { positions: true, paint: true, state: true, pinned: true };\n let frame = 0;\n let destroyed = false;\n let framed: Geometry | null = null;\n let links: Float32Array | null = null;\n let last = store.getSnapshot();\n let lastOptions = store.getOptions();\n\n const size = () => store.getSnapshot().geometry?.size ?? 0;\n\n let graph: Graph;\n try {\n graph = new Graph(host, {\n // No `spaceSize` here: the box is the corpus's extent, set when the graph has loaded.\n // `rescalePositions: false` because the corpus's coordinates are the camera's.\n rescalePositions: false,\n transitionDuration: 0,\n enableSimulation: live,\n ...forces(sim),\n // Frames to convergence: alpha reaches its floor after exactly this many rendered frames.\n simulationDecay: 400,\n randomSeed: \"kanzo-discovery\",\n pixelRatio: window.devicePixelRatio || 1,\n enableDrag: true,\n hoveredPointCursor: \"pointer\",\n attribution: \"\",\n onSimulationStart: () => store.report(\"running\"),\n onSimulationEnd: () => {\n store.report(\"settled\");\n progress(1);\n events.onFrame?.();\n },\n onSimulationPause: () => store.report(\"paused\"),\n onSimulationUnpause: () => store.report(\"running\"),\n onSimulationTick: (_alpha, index, position) => {\n progress(graph.progress);\n if (index !== undefined && position) events.onHover?.(position);\n events.onFrame?.();\n },\n onZoom: () => events.onFrame?.(),\n onPointMouseOver: (index, position) => {\n hovering = index;\n events.onHover?.(position);\n store.hover(index);\n },\n onPointMouseOut: () => {\n hovering = null;\n events.onHover?.(null);\n store.hover(null);\n },\n onDragStart: () => {\n dragging = hovering;\n },\n onDrag: (event) => {\n events.onHover?.(graph.screenToSpacePosition([event.x, event.y]));\n events.onFrame?.();\n },\n onDragEnd: () => {\n const vertex = dragging;\n dragging = null;\n if (vertex !== null) store.pin([...store.getSnapshot().pinned, vertex]);\n },\n onPointClick: (index) => focusOn(index),\n onBackgroundClick: () => clear(),\n });\n } catch (error) {\n fail(`The renderer failed to start. (${String(error)})`);\n return null;\n }\n\n const schedule = () => {\n if (frame) return;\n frame = requestAnimationFrame(() => {\n frame = 0;\n draw();\n });\n };\n\n function draw(): void {\n const snapshot = store.getSnapshot();\n const { geometry, encoding } = snapshot;\n const options = store.getOptions();\n let changed = false;\n if (dirty.positions && geometry) {\n dirty.positions = false;\n frameExtent(geometry);\n graph.setPointPositions(shown(geometry, snapshot.mask), true);\n if (geometry.links !== links) {\n links = geometry.links;\n graph.setLinks(links);\n dirty.paint = dirty.state = dirty.pinned = true;\n }\n changed = true;\n }\n if (dirty.paint && geometry && encoding) {\n dirty.paint = false;\n const buffers = paint(geometry, encoding, look, host, options);\n graph.setPointColors(buffers.colors);\n graph.setPointSizes(buffers.sizes);\n graph.setPointShapes(buffers.shapes);\n graph.setLinkColors(buffers.linkColors);\n graph.setConfigPartial(appearance(look, host));\n changed = true;\n }\n if (dirty.state && geometry) {\n dirty.state = false;\n graph.setConfigPartial({\n highlightedPointIndices: snapshot.selection ? snapshot.selection.vertices.filter((id) => id < geometry.size) : undefined,\n focusedPointIndex: snapshot.focus === null || snapshot.focus >= geometry.size ? undefined : snapshot.focus,\n });\n }\n if (dirty.pinned && geometry) {\n dirty.pinned = false;\n graph.setPinnedPoints(snapshot.pinned.length > 0 ? [...snapshot.pinned] : null);\n }\n if (changed) graph.render();\n if (geometry && encoding && !dirty.paint) store.reportDrawn(snapshot);\n events.onFrame?.();\n }\n\n function frameExtent(geometry: Geometry): void {\n if (geometry === framed || !geometry.extent) return;\n framed = geometry;\n graph.setConfigPartial({ spaceSize: Math.max(geometry.extent.w, geometry.extent.h) });\n graph.fitViewByPointPositions(corners(geometry.extent), 0, FIT_PADDING);\n }\n\n const unsubscribe = store.subscribe(() => {\n const snapshot = store.getSnapshot();\n const options = store.getOptions();\n if (snapshot.geometry !== last.geometry || snapshot.mask !== last.mask) dirty.positions = true;\n if (snapshot.encoding !== last.encoding) dirty.paint = true;\n if (options.look !== lookPatch) {\n lookPatch = options.look;\n look = resolveLook(options.look);\n dirty.paint = true;\n }\n if (options.fill !== lastOptions.fill || options.symbol !== lastOptions.symbol || options.stroke !== lastOptions.stroke) {\n dirty.paint = true;\n }\n if (snapshot.selection !== last.selection || snapshot.focus !== last.focus) dirty.state = true;\n if (snapshot.pinned !== last.pinned) dirty.pinned = true;\n if (options.sim !== lastOptions.sim) applyForces(options.sim);\n if ((options.simulate ?? false) !== (lastOptions.simulate ?? false)) {\n if (options.simulate) run(REHEAT);\n else graph.pause();\n }\n last = snapshot;\n lastOptions = options;\n if (dirty.positions || dirty.paint || dirty.state || dirty.pinned) schedule();\n });\n\n function applyForces(patch: Partial<Sim> | undefined): void {\n const next = resolveSim(patch);\n const moved = Object.keys(next).some((key) => next[key as keyof Sim] !== sim[key as keyof Sim]);\n sim = next;\n if (!live) return;\n graph.setConfigPartial(forces(next));\n if (moved && store.getSnapshot().motion !== \"paused\") graph.start(REHEAT);\n }\n\n /** A layout runs from where the points are: enabling cosmos.gl's simulation keeps its positions. */\n function run(alpha: number): void {\n if (!live) {\n live = true;\n graph.setConfigPartial({ enableSimulation: true, ...forces(sim) });\n }\n graph.start(alpha);\n }\n\n function focusOn(vertex: VertexId): void {\n const around = graph.getNeighboringPointIndices(vertex) ?? [];\n store.select([vertex, ...around], \"node\", \"Node\");\n store.focus(vertex);\n }\n\n function clear(): void {\n store.select(null);\n store.focus(null);\n }\n\n // cosmos.gl 3.4 queues every setter and command until its device exists (`ensureDevice`), and its\n // two synchronous hit tests answer `[]` until then; only the canvas element has to wait for `ready`.\n graph.setConfigPartial(appearance(look, host));\n graph.render();\n const onLost = (event: Event) => {\n event.preventDefault();\n fail(\"The graph's WebGL context was lost. A browser keeps a limited number of them and drops the oldest; reload the page to get one back.\");\n };\n void graph.ready.then(() => {\n if (!destroyed) host.querySelector(\"canvas\")?.addEventListener(\"webglcontextlost\", onLost);\n });\n store.report(live && graph.isSimulationRunning ? \"running\" : \"settled\");\n schedule();\n\n return {\n graph,\n repaint() {\n dirty.paint = true;\n schedule();\n },\n hit(shape) {\n const found = \"rect\" in shape ? graph.findPointsInRect(shape.rect) : graph.findPointsInPolygon(shape.polygon);\n return Array.from(found);\n },\n zoomBy(factor) {\n graph.setZoomLevel(graph.getZoomLevel() * factor, 220);\n },\n fit() {\n const extent = store.getSnapshot().geometry?.extent;\n if (extent) graph.fitViewByPointPositions(corners(extent), FIT_DURATION, FIT_PADDING);\n else graph.fitView(FIT_DURATION, FIT_PADDING);\n },\n pause: () => graph.pause(),\n resume() {\n const settled = store.getSnapshot().motion === \"settled\";\n if (settled || !live) run(REHEAT);\n else graph.unpause();\n },\n restart() {\n store.pin([]);\n run(1);\n },\n unpin() {\n if (store.getSnapshot().pinned.length === 0) return;\n store.pin([]);\n if (store.getSnapshot().motion === \"running\") graph.start(REHEAT);\n },\n reveal(vertex) {\n if (vertex >= size()) return;\n focusOn(vertex);\n graph.zoomToPointByIndex(vertex, 500, 5, true);\n },\n frameSelection() {\n const vertices = (store.getSnapshot().selection?.vertices ?? []).filter((id) => id < size());\n if (vertices.length > 0) graph.fitViewByPointIndices(vertices, FIT_DURATION, 0.25);\n },\n clear,\n destroy() {\n unsubscribe();\n if (frame) cancelAnimationFrame(frame);\n destroyed = true;\n // Read here rather than remembered from construction: the element exists only with the device.\n const canvas = host.querySelector(\"canvas\");\n canvas?.removeEventListener(\"webglcontextlost\", onLost);\n graph.destroy();\n releaseContext(canvas);\n },\n };\n}\n"],"names":["FIT_DURATION","FIT_PADDING","REHEAT","PROGRESS_STEPS","corners","box","shown","geometry","mask","positions","id","createRenderer","host","store","events","fail","message","hasWebGL","sim","resolveSim","live","hovering","dragging","reported","progress","value","bucket","look","resolveLook","lookPatch","dirty","frame","destroyed","framed","links","last","lastOptions","size","_a","graph","Graph","forces","_alpha","index","position","_b","event","vertex","focusOn","clear","error","schedule","draw","snapshot","encoding","options","changed","frameExtent","buffers","paint","appearance","unsubscribe","applyForces","run","patch","next","moved","key","alpha","around","onLost","shape","found","factor","extent","vertices","canvas","releaseContext"],"mappings":"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"}
|
package/dist/section.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"section.d.ts","sourceRoot":"","sources":["../src/section.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,KAAK,WAAW,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACpE,KAAK,gBAAgB,GACjB,CAAC,WAAW,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,SAAS;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,GACxF,CAAC,WAAW,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,GAClC,CAAC,WAAW,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE9E,UAAU,eAAe;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACpE,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;CACpD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"section.d.ts","sourceRoot":"","sources":["../src/section.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,KAAK,WAAW,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACpE,KAAK,gBAAgB,GACjB,CAAC,WAAW,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,SAAS;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,GACxF,CAAC,WAAW,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,GAClC,CAAC,WAAW,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE9E,UAAU,eAAe;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACpE,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;CACpD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,aAAa,EAAE,eAsI3B,CAAC"}
|
package/dist/section.js
CHANGED
|
@@ -53,7 +53,7 @@ const e = {
|
|
|
53
53
|
kind: "toggle",
|
|
54
54
|
label: "Show links",
|
|
55
55
|
default: "true",
|
|
56
|
-
doc: "Draw the edge layer at all. Past a few hundred thousand links it is fog that costs a draw call a frame
|
|
56
|
+
doc: "Draw the edge layer at all. Past a few hundred thousand links it is fog that costs a draw call a frame."
|
|
57
57
|
},
|
|
58
58
|
grid: {
|
|
59
59
|
kind: "toggle",
|
|
@@ -72,12 +72,8 @@ const e = {
|
|
|
72
72
|
*
|
|
73
73
|
* The bounds are cosmos.gl's useful range rather than its legal one, and a stored value outside
|
|
74
74
|
* them is declined: a slider that used to run to 5 and now stops at 3 must not paint 5 because
|
|
75
|
-
* storage remembers it.
|
|
76
|
-
*
|
|
77
|
-
* **`adaptive(nodes)` still exists and still knows better.** What a corpus of this size wants is
|
|
78
|
-
* computed, not chosen, and these defaults are tuned for a few hundred nodes. A host with a
|
|
79
|
-
* large corpus should start its users at `adaptive`'s answer through the tenant policy — which
|
|
80
|
-
* is the mechanism's own way of saying "start somewhere else" — rather than by writing values
|
|
75
|
+
* storage remembers it. These defaults are tuned for a few hundred nodes; a host with a large
|
|
76
|
+
* corpus starts its users elsewhere through the tenant policy, rather than by writing values
|
|
81
77
|
* into storage nobody can then reset.
|
|
82
78
|
*/
|
|
83
79
|
gravity: {
|
package/dist/section.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"section.js","sources":["../src/section.ts"],"sourcesContent":["/**\n * The manifest shape, re-declared structurally rather than imported from `@kanzo-tech/theme`.\n *\n * Third instance of the same call in this repository, and the same reasoning each time: the type is\n * a *shape*, the value is data, and importing it would add a dependency to carry no code. Here it\n * also keeps the arrow pointing one way — a section contributes to the core, and the core does not\n * know it exists, so neither package should have to name the other to make that true.\n *\n * `packages/theme/src/sections.ts` is the definition this conforms to. Two structural declarations\n * can drift; what stops it is that a mismatch is a `tsc` error the moment a host passes this to\n * `validateSection`, which `docs/` does.\n */\ntype PrefCommon_ = { default: string; doc: string; label?: string };\ntype SectionPrefDecl_ =\n | (PrefCommon_ & { kind: \"choice\"; options: readonly { value: string; label: string }[] })\n | (PrefCommon_ & { kind: \"toggle\" })\n | (PrefCommon_ & { kind: \"range\"; min: number; max: number; step: number });\n\ninterface SectionManifest {\n namespace: string;\n version: number;\n tokens?: Readonly<Record<string, { default: string; doc: string }>>;\n prefs?: Readonly<Record<string, SectionPrefDecl_>>;\n}\n\n/**\n * The graph's contribution to a host's preferences — its tokens and its choices.\n *\n * **It was `LOOK_SECTION`, and the name was half of it.** The look is five of the sixteen\n * preferences below; the rest are the edge layer, the dot grid and the six force coefficients, which\n * lived in a `Display` interface and a `Sim` interface with their own defaults and their own\n * hand-rolled sliders. One section, one storage shape, one resolution, one renderer.\n *\n * Reached by subpath — `@kanzo-tech/graph/section` — and never imported by\n * `@kanzo-tech/theme`. That direction is the whole design: contributing is *using* a namespace, not\n * registering a type in the core, so a consumer who never installs this package pays nothing and\n * `packages/ui` gains no reference to the graph.\n *\n * ## Four colour tokens are gone, and the rule that removed them is the same one\n *\n * A name is worth having when a theme would plausibly give it a value **different from the token it\n * comes out of**. If it can only ever repeat one, it is not a name, it is a use. Applied here:\n *\n * · `vignette` defaulted to `--background`, and the rim fades *toward the page* — any other value\n * breaks it. It could never differ, so the canvas reads `--background` directly.\n * · `marquee-edge` and `point-ring-focus` both defaulted to `--primary`. A selection outline IS the\n * brand; two names for \"the brand, solid\" is the duplication, not the flexibility.\n * · `marquee` was `(brand, alpha 5)` — a *dilution*, which is a derivation and not a name. It is\n * `color-mix` where it is drawn.\n *\n * What that costs is the capacity for a tenant to redirect them, and measured against the rule\n * nobody wants it: redirecting `vignette` is breaking it. It is the same rule that removed seventeen\n * level-names from the core's vocabulary, applied to a section rather than to the core — which is\n * the half that had not been done.\n *\n * `grid` survives, and it is the only one that is arguable: a dot grid is decorative and drawn at a\n * different weight from a border, so a theme might plausibly want it fainter. If no theme ever does,\n * it goes too.\n *\n * **A default is a CSS value now, not an object.** It was `{kind, ramp, step}` in three shapes, two\n * of which named a reference tier that no longer exists; `var(--border)` says the same thing with\n * nothing between it and the browser, and the type it mirrored no longer has to be declared\n * structurally in two packages at once.\n */\nexport const GRAPH_SECTION: SectionManifest = {\n namespace: \"graph\",\n version: 1,\n tokens: {\n grid: {\n default: \"var(--border)\",\n doc: \"The dot grid behind the canvas. Decorative, and WCAG 1.4.11 exempts a non-interactive separator by name.\",\n },\n \"point-ring-hover\": {\n default: \"var(--primary)\",\n doc: \"The ring drawn around a hovered point.\",\n },\n },\n prefs: {\n marks: {\n kind: \"choice\",\n label: \"Marks\",\n default: \"dense\",\n doc: \"How much ink a point spends. The legible mark is the one to pair the shape channel with — its radius floor is what keeps shape from corrupting the size ramp beside it.\",\n options: [\n { value: \"dense\", label: \"Dense\" },\n { value: \"legible\", label: \"Legible\" },\n ],\n },\n \"additive-links\": {\n kind: \"toggle\",\n label: \"Additive links\",\n default: \"false\",\n doc: \"Links add where they overlap instead of compositing over one another. Additive light is what makes a dense graph read as flow — and what made 4,280 links at 0.45 swallow 1,543 points on the archive.\",\n },\n \"bowed-links\": {\n kind: \"toggle\",\n label: \"Bowed links\",\n default: \"true\",\n doc: \"Links bow off the straight line by a hint, which is enough to tell two parallel edges apart. Every link curves the same way, so more than a hint reads as a pinwheel.\",\n },\n labels: {\n kind: \"range\",\n label: \"Labels\",\n default: \"26\",\n doc: \"How many of the highest-degree nodes carry a standing label. Zero draws none.\",\n min: 0,\n max: 60,\n step: 2,\n },\n vignette: {\n kind: \"toggle\",\n label: \"Vignette\",\n default: \"false\",\n doc: \"A darkened rim. Mood rather than a reading aid, which is why it is a preference and not a display control.\",\n },\n links: {\n kind: \"toggle\",\n label: \"Show links\",\n default: \"true\",\n doc: \"Draw the edge layer at all. Past a few hundred thousand links it is fog that costs a draw call a frame, and `adaptive` says where that is.\",\n },\n grid: {\n kind: \"toggle\",\n label: \"Dot grid\",\n default: \"true\",\n doc: \"The dot grid behind the graph. It pans and subdivides with the camera, which is what makes a pan read as motion rather than as a redraw.\",\n },\n\n /**\n * The force coefficients, which are preferences and were a second vocabulary.\n *\n * **They are not appearance, and this manifest holds them anyway.** A section's `tokens` are the\n * colours a document may move; its `prefs` are *what the person on the screen decides*, and a\n * reader tuning a layout until it settles is deciding something. They lived in a TS interface\n * with a `DEFAULT_SIM` beside it and six hand-rolled sliders in one showcase's dock — the fourth\n * declaration style in a census of four, for a quarter of the knobs.\n *\n * The bounds are cosmos.gl's useful range rather than its legal one, and a stored value outside\n * them is declined: a slider that used to run to 5 and now stops at 3 must not paint 5 because\n * storage remembers it.\n *\n * **`adaptive(nodes)` still exists and still knows better.** What a corpus of this size wants is\n * computed, not chosen, and these defaults are tuned for a few hundred nodes. A host with a\n * large corpus should start its users at `adaptive`'s answer through the tenant policy — which\n * is the mechanism's own way of saying \"start somewhere else\" — rather than by writing values\n * into storage nobody can then reset.\n */\n gravity: {\n kind: \"range\",\n label: \"Gravity\",\n default: \"0.14\",\n doc: \"Pull toward the centre. It is what stops a disconnected component drifting off the canvas.\",\n min: 0,\n max: 0.5,\n step: 0.01,\n },\n repulsion: {\n kind: \"range\",\n label: \"Repulsion\",\n default: \"1.1\",\n doc: \"How hard every point pushes every other. Bigger graphs need less of it, or they never settle.\",\n min: 0,\n max: 2,\n step: 0.05,\n },\n \"link-spring\": {\n kind: \"range\",\n label: \"Link spring\",\n default: \"0.6\",\n doc: \"How hard a link pulls its two ends together.\",\n min: 0,\n max: 2,\n step: 0.05,\n },\n \"link-distance\": {\n kind: \"range\",\n label: \"Link distance\",\n default: \"18\",\n doc: \"The length a link is happy at, in simulation units.\",\n min: 2,\n max: 60,\n step: 1,\n },\n friction: {\n kind: \"range\",\n label: \"Friction\",\n default: \"0.86\",\n doc: \"How fast motion decays. Under about 0.7 the layout twitches; near 1 it never stops.\",\n min: 0.5,\n max: 0.99,\n step: 0.01,\n },\n cluster: {\n kind: \"range\",\n label: \"Cluster pull\",\n default: \"0.1\",\n doc: \"Pull toward the node's group position on the cluster ring. Zero lets the links decide alone.\",\n min: 0,\n max: 1,\n step: 0.05,\n },\n },\n};\n"],"names":["GRAPH_SECTION"],"mappings":"AAgEO,MAAMA,IAAiC;AAAA,EAC5C,WAAW;AAAA,EACX,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA,IAEP,oBAAoB;AAAA,MAClB,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA,EACP;AAAA,EAEF,OAAO;AAAA,IACL,OAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,SAAS;AAAA,QACP,EAAE,OAAO,SAAS,OAAO,QAAA;AAAA,QACzB,EAAE,OAAO,WAAW,OAAO,UAAA;AAAA,MAAU;AAAA,IACvC;AAAA,IAEF,kBAAkB;AAAA,MAChB,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA,IAEP,eAAe;AAAA,MACb,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA,IAEP,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,IAER,UAAU;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA,IAEP,OAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA,IAEP,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAsBP,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,IAER,WAAW;AAAA,MACT,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,IAER,eAAe;AAAA,MACb,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,IAER,iBAAiB;AAAA,MACf,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,IAER,UAAU;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,IAER,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,EACR;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"section.js","sources":["../src/section.ts"],"sourcesContent":["/**\n * The manifest shape, re-declared structurally rather than imported from `@kanzo-tech/theme`.\n *\n * Third instance of the same call in this repository, and the same reasoning each time: the type is\n * a *shape*, the value is data, and importing it would add a dependency to carry no code. Here it\n * also keeps the arrow pointing one way — a section contributes to the core, and the core does not\n * know it exists, so neither package should have to name the other to make that true.\n *\n * `packages/theme/src/sections.ts` is the definition this conforms to. Two structural declarations\n * can drift; what stops it is that a mismatch is a `tsc` error the moment a host passes this to\n * `validateSection`, which `docs/` does.\n */\ntype PrefCommon_ = { default: string; doc: string; label?: string };\ntype SectionPrefDecl_ =\n | (PrefCommon_ & { kind: \"choice\"; options: readonly { value: string; label: string }[] })\n | (PrefCommon_ & { kind: \"toggle\" })\n | (PrefCommon_ & { kind: \"range\"; min: number; max: number; step: number });\n\ninterface SectionManifest {\n namespace: string;\n version: number;\n tokens?: Readonly<Record<string, { default: string; doc: string }>>;\n prefs?: Readonly<Record<string, SectionPrefDecl_>>;\n}\n\n/**\n * The graph's contribution to a host's preferences — its tokens and its choices.\n *\n * **It was `LOOK_SECTION`, and the name was half of it.** The look is five of the sixteen\n * preferences below; the rest are the edge layer, the dot grid and the six force coefficients, which\n * lived in a `Display` interface and a `Sim` interface with their own defaults and their own\n * hand-rolled sliders. One section, one storage shape, one resolution, one renderer.\n *\n * Reached by subpath — `@kanzo-tech/graph/section` — and never imported by\n * `@kanzo-tech/theme`. That direction is the whole design: contributing is *using* a namespace, not\n * registering a type in the core, so a consumer who never installs this package pays nothing and\n * `packages/ui` gains no reference to the graph.\n *\n * ## Four colour tokens are gone, and the rule that removed them is the same one\n *\n * A name is worth having when a theme would plausibly give it a value **different from the token it\n * comes out of**. If it can only ever repeat one, it is not a name, it is a use. Applied here:\n *\n * · `vignette` defaulted to `--background`, and the rim fades *toward the page* — any other value\n * breaks it. It could never differ, so the canvas reads `--background` directly.\n * · `marquee-edge` and `point-ring-focus` both defaulted to `--primary`. A selection outline IS the\n * brand; two names for \"the brand, solid\" is the duplication, not the flexibility.\n * · `marquee` was `(brand, alpha 5)` — a *dilution*, which is a derivation and not a name. It is\n * `color-mix` where it is drawn.\n *\n * What that costs is the capacity for a tenant to redirect them, and measured against the rule\n * nobody wants it: redirecting `vignette` is breaking it. It is the same rule that removed seventeen\n * level-names from the core's vocabulary, applied to a section rather than to the core — which is\n * the half that had not been done.\n *\n * `grid` survives, and it is the only one that is arguable: a dot grid is decorative and drawn at a\n * different weight from a border, so a theme might plausibly want it fainter. If no theme ever does,\n * it goes too.\n *\n * **A default is a CSS value now, not an object.** It was `{kind, ramp, step}` in three shapes, two\n * of which named a reference tier that no longer exists; `var(--border)` says the same thing with\n * nothing between it and the browser, and the type it mirrored no longer has to be declared\n * structurally in two packages at once.\n */\nexport const GRAPH_SECTION: SectionManifest = {\n namespace: \"graph\",\n version: 1,\n tokens: {\n grid: {\n default: \"var(--border)\",\n doc: \"The dot grid behind the canvas. Decorative, and WCAG 1.4.11 exempts a non-interactive separator by name.\",\n },\n \"point-ring-hover\": {\n default: \"var(--primary)\",\n doc: \"The ring drawn around a hovered point.\",\n },\n },\n prefs: {\n marks: {\n kind: \"choice\",\n label: \"Marks\",\n default: \"dense\",\n doc: \"How much ink a point spends. The legible mark is the one to pair the shape channel with — its radius floor is what keeps shape from corrupting the size ramp beside it.\",\n options: [\n { value: \"dense\", label: \"Dense\" },\n { value: \"legible\", label: \"Legible\" },\n ],\n },\n \"additive-links\": {\n kind: \"toggle\",\n label: \"Additive links\",\n default: \"false\",\n doc: \"Links add where they overlap instead of compositing over one another. Additive light is what makes a dense graph read as flow — and what made 4,280 links at 0.45 swallow 1,543 points on the archive.\",\n },\n \"bowed-links\": {\n kind: \"toggle\",\n label: \"Bowed links\",\n default: \"true\",\n doc: \"Links bow off the straight line by a hint, which is enough to tell two parallel edges apart. Every link curves the same way, so more than a hint reads as a pinwheel.\",\n },\n labels: {\n kind: \"range\",\n label: \"Labels\",\n default: \"26\",\n doc: \"How many of the highest-degree nodes carry a standing label. Zero draws none.\",\n min: 0,\n max: 60,\n step: 2,\n },\n vignette: {\n kind: \"toggle\",\n label: \"Vignette\",\n default: \"false\",\n doc: \"A darkened rim. Mood rather than a reading aid, which is why it is a preference and not a display control.\",\n },\n links: {\n kind: \"toggle\",\n label: \"Show links\",\n default: \"true\",\n doc: \"Draw the edge layer at all. Past a few hundred thousand links it is fog that costs a draw call a frame.\",\n },\n grid: {\n kind: \"toggle\",\n label: \"Dot grid\",\n default: \"true\",\n doc: \"The dot grid behind the graph. It pans and subdivides with the camera, which is what makes a pan read as motion rather than as a redraw.\",\n },\n\n /**\n * The force coefficients, which are preferences and were a second vocabulary.\n *\n * **They are not appearance, and this manifest holds them anyway.** A section's `tokens` are the\n * colours a document may move; its `prefs` are *what the person on the screen decides*, and a\n * reader tuning a layout until it settles is deciding something. They lived in a TS interface\n * with a `DEFAULT_SIM` beside it and six hand-rolled sliders in one showcase's dock — the fourth\n * declaration style in a census of four, for a quarter of the knobs.\n *\n * The bounds are cosmos.gl's useful range rather than its legal one, and a stored value outside\n * them is declined: a slider that used to run to 5 and now stops at 3 must not paint 5 because\n * storage remembers it. These defaults are tuned for a few hundred nodes; a host with a large\n * corpus starts its users elsewhere through the tenant policy, rather than by writing values\n * into storage nobody can then reset.\n */\n gravity: {\n kind: \"range\",\n label: \"Gravity\",\n default: \"0.14\",\n doc: \"Pull toward the centre. It is what stops a disconnected component drifting off the canvas.\",\n min: 0,\n max: 0.5,\n step: 0.01,\n },\n repulsion: {\n kind: \"range\",\n label: \"Repulsion\",\n default: \"1.1\",\n doc: \"How hard every point pushes every other. Bigger graphs need less of it, or they never settle.\",\n min: 0,\n max: 2,\n step: 0.05,\n },\n \"link-spring\": {\n kind: \"range\",\n label: \"Link spring\",\n default: \"0.6\",\n doc: \"How hard a link pulls its two ends together.\",\n min: 0,\n max: 2,\n step: 0.05,\n },\n \"link-distance\": {\n kind: \"range\",\n label: \"Link distance\",\n default: \"18\",\n doc: \"The length a link is happy at, in simulation units.\",\n min: 2,\n max: 60,\n step: 1,\n },\n friction: {\n kind: \"range\",\n label: \"Friction\",\n default: \"0.86\",\n doc: \"How fast motion decays. Under about 0.7 the layout twitches; near 1 it never stops.\",\n min: 0.5,\n max: 0.99,\n step: 0.01,\n },\n cluster: {\n kind: \"range\",\n label: \"Cluster pull\",\n default: \"0.1\",\n doc: \"Pull toward the node's group position on the cluster ring. Zero lets the links decide alone.\",\n min: 0,\n max: 1,\n step: 0.05,\n },\n },\n};\n"],"names":["GRAPH_SECTION"],"mappings":"AAgEO,MAAMA,IAAiC;AAAA,EAC5C,WAAW;AAAA,EACX,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA,IAEP,oBAAoB;AAAA,MAClB,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA,EACP;AAAA,EAEF,OAAO;AAAA,IACL,OAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,SAAS;AAAA,QACP,EAAE,OAAO,SAAS,OAAO,QAAA;AAAA,QACzB,EAAE,OAAO,WAAW,OAAO,UAAA;AAAA,MAAU;AAAA,IACvC;AAAA,IAEF,kBAAkB;AAAA,MAChB,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA,IAEP,eAAe;AAAA,MACb,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA,IAEP,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,IAER,UAAU;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA,IAEP,OAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA,IAEP,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAkBP,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,IAER,WAAW;AAAA,MACT,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,IAER,eAAe;AAAA,MACb,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,IAER,iBAAiB;AAAA,MACf,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,IAER,UAAU;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,IAER,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,EACR;AAEJ;"}
|