@jmbarzee/force-graph 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4895 @@
1
+ var gi = Object.defineProperty;
2
+ var pi = (e, t, n) => t in e ? gi(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
+ var Ze = (e, t, n) => pi(e, typeof t != "symbol" ? t + "" : t, n);
4
+ import { jsx as h, jsxs as C, Fragment as yn } from "react/jsx-runtime";
5
+ import g from "react";
6
+ const _n = g.createContext(null);
7
+ function Bt() {
8
+ const e = g.useContext(_n);
9
+ if (e === null)
10
+ throw new Error(
11
+ "useTaxonomy() was called with no TaxonomyContext.Provider above it. The graph engine resolves styles, filter keys, spring categories and physics through the taxonomy, so there is no meaningful default — wrap the tree in <TaxonomyContext.Provider value={…}>."
12
+ );
13
+ return e;
14
+ }
15
+ function mi(e, t) {
16
+ const n = e.emptyMeans === "none", s = e.id === t.axis, o = e.labelFor ?? (s ? t.labelFor : (a) => a), i = e.abbreviationFor ?? (s ? t.abbreviationFor : (a) => o(a).slice(0, 2)), r = e.keepCamera ?? !n, c = e.iconFor ?? (s ? t.iconFor : () => "");
17
+ return {
18
+ id: e.id,
19
+ label: e.label ?? e.id,
20
+ emptyMeans: e.emptyMeans,
21
+ absentMeans: e.absentMeans ?? (n ? "hidden" : "visible"),
22
+ widens: e.widens ?? (n ? "always" : "whenActive"),
23
+ keepCamera: r,
24
+ labelFor: o,
25
+ abbreviationFor: i,
26
+ tooltipFor: e.tooltipFor,
27
+ iconFor: c,
28
+ chipsFor: e.chipsFor ?? ((a) => a.map((l) => {
29
+ var d;
30
+ return {
31
+ id: l,
32
+ label: o(l),
33
+ icon: c(l) || void 0,
34
+ tint: s ? l : void 0,
35
+ tooltip: (d = e.tooltipFor) == null ? void 0 : d.call(e, l),
36
+ values: [l]
37
+ };
38
+ })),
39
+ initialSelection: e.initialSelection ?? ((a) => n ? a : []),
40
+ presentation: e.presentation ?? "chip"
41
+ };
42
+ }
43
+ function vi(e) {
44
+ const t = /* @__PURE__ */ new Map(), n = [], s = /* @__PURE__ */ new Set();
45
+ for (const i of e.buckets) {
46
+ s.has(i.id) && n.push(`bucket id ${JSON.stringify(i.id)} is declared twice`), s.add(i.id), i.values.length === 0 && n.push(`bucket ${JSON.stringify(i.id)} has no values`);
47
+ for (const r of i.values) {
48
+ const c = t.get(r);
49
+ c !== void 0 && c !== i.id ? n.push(`${JSON.stringify(r)} is in both ${c} and ${i.id}`) : t.set(r, i.id);
50
+ }
51
+ }
52
+ if (n.length > 0)
53
+ throw new Error(
54
+ `axis mapping ${JSON.stringify(e.id)} is incoherent: ` + n.join("; ") + ". A value in two buckets has no defined answer for which one tunes it."
55
+ );
56
+ const o = /* @__PURE__ */ new Map();
57
+ for (const i of e.buckets)
58
+ for (const r of i.values) o.set(r, i);
59
+ return {
60
+ id: e.id,
61
+ label: e.label,
62
+ axis: e.axis,
63
+ buckets: e.buckets,
64
+ bucketFor: (i) => i === void 0 ? void 0 : o.get(i)
65
+ };
66
+ }
67
+ function Vn(e, t) {
68
+ const n = /* @__PURE__ */ new Map();
69
+ return vi({
70
+ id: `${e.id}:identity`,
71
+ label: e.label,
72
+ axis: e.id,
73
+ buckets: t.map((s) => {
74
+ const o = e.abbreviationFor(s), i = (n.get(o) ?? 0) + 1;
75
+ return n.set(o, i), {
76
+ id: s,
77
+ label: e.labelFor(s),
78
+ abbreviation: i === 1 ? o : `${o}${i}`,
79
+ values: [s]
80
+ };
81
+ })
82
+ });
83
+ }
84
+ function Fs(e) {
85
+ return e.buckets.every((t) => t.values.length === 1 && t.values[0] === t.id);
86
+ }
87
+ function sn(e, t) {
88
+ const n = /* @__PURE__ */ new Set();
89
+ for (const s of e) {
90
+ const o = s.values[t];
91
+ o !== void 0 && n.add(o);
92
+ }
93
+ return [...n];
94
+ }
95
+ function _o(e, t) {
96
+ const n = new Map(t.map((i) => [i, /* @__PURE__ */ new Map()])), s = new Map(t.map((i) => [i, /* @__PURE__ */ new Map()]));
97
+ let o = 0;
98
+ for (const i of e) {
99
+ const r = i.copyKey ?? i.id ?? `\0${o++}`;
100
+ for (const c of t) {
101
+ const a = i.values[c];
102
+ if (a === void 0) continue;
103
+ const l = n.get(c);
104
+ let d = l.get(a);
105
+ if (d || (d = /* @__PURE__ */ new Set(), l.set(a, d)), d.has(r)) continue;
106
+ d.add(r);
107
+ const u = s.get(c);
108
+ u.set(a, (u.get(a) ?? 0) + 1);
109
+ }
110
+ }
111
+ return s;
112
+ }
113
+ function Rn(e, t) {
114
+ return Object.prototype.hasOwnProperty.call(e, t);
115
+ }
116
+ function yi(e) {
117
+ return { alpha: e.emptyMeans === "none" ? 0.5 : 0.3, seedRevealed: !e.keepCamera, refit: !e.keepCamera, resume: !0 };
118
+ }
119
+ function bi(e) {
120
+ let t = 0, n = !1, s = !1, o = !1;
121
+ for (const i of e) {
122
+ const r = yi(i);
123
+ t = Math.max(t, r.alpha), n = n || r.seedRevealed, s = s || r.refit, o = o || r.resume;
124
+ }
125
+ return { alpha: t, seedRevealed: n, refit: s, resume: o, changed: e.map((i) => i.id) };
126
+ }
127
+ function Mt(e, t, n, s) {
128
+ const [o, i] = g.useState(n), r = e !== void 0;
129
+ Bo(s, r);
130
+ const c = g.useRef(t);
131
+ c.current = t;
132
+ const a = g.useCallback((l) => {
133
+ var d;
134
+ r || i(l), (d = c.current) == null || d.call(c, l);
135
+ }, [r]);
136
+ return [r ? e : o, a];
137
+ }
138
+ function Bo(e, t) {
139
+ const n = g.useRef(t), s = g.useRef(!1);
140
+ g.useEffect(() => {
141
+ n.current !== t && !s.current && (s.current = !0, console.warn(`[force-graph] \`${e}\` changed from ${n.current ? "controlled to uncontrolled" : "uncontrolled to controlled"}: pass a value on every render (null for none), or on none.`)), n.current = t;
142
+ }, [t, e]);
143
+ }
144
+ function Ft(e, t) {
145
+ const n = g.useRef(e);
146
+ return n.current !== e && !t(n.current, e) && (n.current = e), n.current;
147
+ }
148
+ function Te(e) {
149
+ const t = g.useRef(e);
150
+ return t.current = e, t;
151
+ }
152
+ const Es = typeof window > "u" ? g.useEffect : g.useLayoutEffect, Ln = ["system", "light", "dark"];
153
+ function Fl(e) {
154
+ return Ln.includes(e) ? e : "system";
155
+ }
156
+ const uo = "[data-theme]";
157
+ function xi(e) {
158
+ if (!e) return;
159
+ const t = e.getAttribute("data-theme");
160
+ return t === "dark" || t === "light" ? t : void 0;
161
+ }
162
+ function fo(e) {
163
+ var n, s, o;
164
+ if (typeof window > "u") return "light";
165
+ let t = ((n = e == null ? void 0 : e.parentElement) == null ? void 0 : n.closest(uo)) ?? null;
166
+ for (; t; ) {
167
+ const i = xi(t);
168
+ if (i) return i;
169
+ t = ((s = t.parentElement) == null ? void 0 : s.closest(uo)) ?? null;
170
+ }
171
+ return (o = window.matchMedia) != null && o.call(window, "(prefers-color-scheme: dark)").matches ? "dark" : "light";
172
+ }
173
+ function wi(e, t = !0) {
174
+ const [n, s] = g.useState(() => t ? fo(e.current) : "light");
175
+ return Es(() => {
176
+ var c, a;
177
+ if (!t) return;
178
+ const o = () => s(fo(e.current));
179
+ if (o(), typeof MutationObserver > "u") return;
180
+ const i = new MutationObserver(o);
181
+ i.observe(document.documentElement, { attributes: !0, attributeFilter: ["data-theme"], subtree: !0 });
182
+ const r = (c = window.matchMedia) == null ? void 0 : c.call(window, "(prefers-color-scheme: dark)");
183
+ return (a = r == null ? void 0 : r.addEventListener) == null || a.call(r, "change", o), () => {
184
+ var l;
185
+ i.disconnect(), (l = r == null ? void 0 : r.removeEventListener) == null || l.call(r, "change", o);
186
+ };
187
+ }, [e, t]), n;
188
+ }
189
+ function Ho(e, t, n) {
190
+ const s = wi(e, n === void 0);
191
+ return t === "system" ? n ?? s : t;
192
+ }
193
+ function Tn(e) {
194
+ return e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^A-Za-z0-9]+/g, "-").replace(/^-|-$/g, "").toLowerCase();
195
+ }
196
+ function zo(e, t) {
197
+ const n = {};
198
+ for (const s of e.styleValues) {
199
+ const o = e.styleOf(s).color[t];
200
+ n[e.colorVar(s)] = o.fill, n[`${e.colorVar(s)}-border`] = o.border;
201
+ }
202
+ return n;
203
+ }
204
+ const Mi = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i, Si = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i, ki = /^rgba?\(\s*(\d{1,3})\s*[, ]\s*(\d{1,3})\s*[, ]\s*(\d{1,3})\s*(?:[,/]\s*[\d.]+%?\s*)?\)$/i, Ni = /^hsla?\(\s*(-?[\d.]+)(?:deg)?\s*[, ]\s*([\d.]+)%\s*[, ]\s*([\d.]+)%\s*(?:[,/]\s*[\d.]+%?\s*)?\)$/i;
205
+ function Ei(e, t, n) {
206
+ const s = Math.min(100, Math.max(0, t)) / 100, o = Math.min(100, Math.max(0, n)) / 100, i = (e % 360 + 360) % 360, r = (1 - Math.abs(2 * o - 1)) * s, c = r * (1 - Math.abs(i / 60 % 2 - 1)), a = o - r / 2, [l, d, u] = i < 60 ? [r, c, 0] : i < 120 ? [c, r, 0] : i < 180 ? [0, r, c] : i < 240 ? [0, c, r] : i < 300 ? [c, 0, r] : [r, 0, c];
207
+ return [Math.round((l + a) * 255), Math.round((d + a) * 255), Math.round((u + a) * 255)];
208
+ }
209
+ function Vo(e) {
210
+ const t = e.trim();
211
+ let n = Si.exec(t);
212
+ if (n) return [parseInt(n[1], 16), parseInt(n[2], 16), parseInt(n[3], 16)];
213
+ if (n = Mi.exec(t), n) return [parseInt(n[1] + n[1], 16), parseInt(n[2] + n[2], 16), parseInt(n[3] + n[3], 16)];
214
+ if (n = ki.exec(t), n) return [Number(n[1]), Number(n[2]), Number(n[3])];
215
+ if (n = Ni.exec(t), n) return Ei(Number(n[1]), Number(n[2]), Number(n[3]));
216
+ }
217
+ const Ii = (e) => Vo(e) !== void 0, $i = [148, 163, 184], ho = /* @__PURE__ */ new Set();
218
+ function fs(e, t) {
219
+ let n = Vo(e);
220
+ return n || (ho.has(e) || (ho.add(e), console.error(`[scheme] ${JSON.stringify(e)} is not a colour the canvas can read; drawing it neutral`)), n = $i), `rgba(${n[0]}, ${n[1]}, ${n[2]}, ${t})`;
221
+ }
222
+ function Ll(e, t = '[data-theme="dark"]') {
223
+ const n = [], s = [];
224
+ for (const i of e.styleValues) {
225
+ const { light: r, dark: c } = e.styleOf(i).color, a = e.colorVar(i);
226
+ n.push(` ${a}: ${r.fill};`), n.push(` ${a}-border: ${r.border};`), c.fill !== r.fill && s.push(` ${a}: ${c.fill};`), c.border !== r.border && s.push(` ${a}-border: ${c.border};`);
227
+ }
228
+ const o = [`:root {
229
+ ${n.join(`
230
+ `)}
231
+ }`];
232
+ return s.length > 0 && o.push(`${t} {
233
+ ${s.join(`
234
+ `)}
235
+ }`), o.join(`
236
+ `);
237
+ }
238
+ function je(e) {
239
+ if (typeof e != "object" || e === null || Array.isArray(e)) return !1;
240
+ const t = Object.getPrototypeOf(e);
241
+ return t === Object.prototype || t === null;
242
+ }
243
+ function yt(e) {
244
+ return typeof e == "number" && Number.isFinite(e);
245
+ }
246
+ const Ci = /* @__PURE__ */ new Set();
247
+ function ze(e, t) {
248
+ return e.get(t) ?? Ci;
249
+ }
250
+ function Gn(e, t) {
251
+ if (e === t) return !0;
252
+ if (e.size !== t.size) return !1;
253
+ for (const n of e) if (!t.has(n)) return !1;
254
+ return !0;
255
+ }
256
+ function on(e, t, n) {
257
+ if (Gn(ze(e, t), n)) return e;
258
+ const s = new Map(e);
259
+ return s.set(t, n), s;
260
+ }
261
+ function bn(e, t) {
262
+ if (e === t) return !0;
263
+ const n = /* @__PURE__ */ new Set([...e.keys(), ...t.keys()]);
264
+ for (const s of n)
265
+ if (!Gn(ze(e, s), ze(t, s))) return !1;
266
+ return !0;
267
+ }
268
+ function Go(e, t) {
269
+ if (e === t) return !0;
270
+ if (e.size !== t.size) return !1;
271
+ for (const [n, s] of e) if (t.get(n) !== s) return !1;
272
+ return !0;
273
+ }
274
+ function Xo(e, t) {
275
+ return e === t || e.length === t.length && e.every((n, s) => n === t[s]);
276
+ }
277
+ function Ai(e, t, n) {
278
+ const s = new Map(e);
279
+ return s.set(t, n), s;
280
+ }
281
+ function Ls(e, t) {
282
+ return e.get(t) ?? !1;
283
+ }
284
+ function Ps(e, t) {
285
+ const n = /* @__PURE__ */ new Map();
286
+ for (const s of e.filterAxes) {
287
+ const o = sn(t.nodes, s.id), i = new Set(s.initialSelection(o)), r = new Set(o);
288
+ for (const c of s.chipsFor(o)) {
289
+ const a = c.values.filter((d) => r.has(d)), l = a.filter((d) => i.has(d));
290
+ if (!(!c.values.some((d) => i.has(d)) || l.length === a.length)) {
291
+ for (const d of a) i.add(d);
292
+ Ri(e, s.id, c.id, a.filter((d) => !l.includes(d)));
293
+ }
294
+ }
295
+ n.set(s.id, i);
296
+ }
297
+ return n;
298
+ }
299
+ function Yo(e, t, n, s = /* @__PURE__ */ new Set()) {
300
+ const o = Ps(t, n);
301
+ let i = e;
302
+ for (const r of t.filterAxes)
303
+ s.has(r.id) || (i = on(i, r.id, ze(o, r.id)));
304
+ return i;
305
+ }
306
+ function Oi(e, t) {
307
+ const n = [];
308
+ for (const s of /* @__PURE__ */ new Set([...e.keys(), ...t.keys()]))
309
+ Gn(ze(e, s), ze(t, s)) || n.push(s);
310
+ return n;
311
+ }
312
+ const go = /* @__PURE__ */ new WeakMap();
313
+ function Ri(e, t, n, s) {
314
+ let o = go.get(e);
315
+ o || (o = /* @__PURE__ */ new Set(), go.set(e, o));
316
+ const i = `${t}\0${n}`;
317
+ o.has(i) || (o.add(i), console.warn(`[filter] the initial selection on axis ${JSON.stringify(t)} splits the chip ${JSON.stringify(n)}; the whole chip is selected (${s.map((r) => JSON.stringify(r)).join(", ")} added). Choose a selection the chips can show.`));
318
+ }
319
+ function Pl(e) {
320
+ return Object.fromEntries([...e].map(([t, n]) => [t, [...n]]));
321
+ }
322
+ function Dl(e) {
323
+ if (!je(e)) return;
324
+ const t = /* @__PURE__ */ new Map();
325
+ for (const [n, s] of Object.entries(e)) {
326
+ if (!Array.isArray(s) || !s.every((o) => typeof o == "string")) return;
327
+ t.set(n, new Set(s));
328
+ }
329
+ return t;
330
+ }
331
+ function _l(e) {
332
+ return Object.fromEntries([...e]);
333
+ }
334
+ function Bl(e) {
335
+ if (!je(e)) return;
336
+ const t = /* @__PURE__ */ new Map();
337
+ for (const [n, s] of Object.entries(e)) {
338
+ if (typeof s != "boolean") return;
339
+ t.set(n, s);
340
+ }
341
+ return t;
342
+ }
343
+ function Hl(e, t) {
344
+ for (const [n, s] of Object.entries(t.values))
345
+ if (s !== void 0 && e.values[n] !== s) return !1;
346
+ return !0;
347
+ }
348
+ function Ti(e) {
349
+ return typeof e == "object" && e !== null;
350
+ }
351
+ function zl({ filter: e, taxonomy: t, axes: n, node: s, valueOn: o }) {
352
+ const i = o ?? ((r, c) => {
353
+ var a;
354
+ return Ti(r) ? (a = r.values) == null ? void 0 : a[c] : void 0;
355
+ });
356
+ for (const r of n) {
357
+ const c = t.axisFor(r);
358
+ if (c && !Xn(e, [c], (a) => i(s, a))) return !1;
359
+ }
360
+ return !0;
361
+ }
362
+ function Xn(e, t, n) {
363
+ for (const s of t) {
364
+ const o = ze(e, s.id);
365
+ if (o.size === 0) {
366
+ if (s.emptyMeans === "none") return !1;
367
+ continue;
368
+ }
369
+ const i = n(s.id);
370
+ if (i === void 0) {
371
+ if (s.absentMeans === "hidden") return !1;
372
+ continue;
373
+ }
374
+ if (!o.has(i)) return !1;
375
+ }
376
+ return !0;
377
+ }
378
+ function Fi({ nodes: e, filter: t, taxonomy: n, axes: s, visibleIds: o, matches: i, valueOn: r }) {
379
+ const c = r ?? ((v, M) => {
380
+ var S;
381
+ return (S = v.values) == null ? void 0 : S[M];
382
+ }), a = s.flatMap((v) => {
383
+ const M = n.axisFor(v);
384
+ return M ? [M] : [];
385
+ }), l = /* @__PURE__ */ new Set();
386
+ let d = 0;
387
+ const u = /* @__PURE__ */ new Map();
388
+ for (const v of e) {
389
+ if (!i(v)) continue;
390
+ if (o.has(v.id)) {
391
+ l.add(v.id);
392
+ continue;
393
+ }
394
+ d++;
395
+ const M = a.find(($) => !Xn(t, [$], (D) => c(v, D))), S = M ? c(v, M.id) : void 0;
396
+ if (!M || S === void 0) continue;
397
+ const p = u.get(M.id) ?? /* @__PURE__ */ new Map();
398
+ p.set(S, (p.get(S) ?? 0) + 1), u.set(M.id, p);
399
+ }
400
+ return { visible: l, hiddenCount: d, hiddenByAxis: u };
401
+ }
402
+ const po = /* @__PURE__ */ new Map();
403
+ function Jo(e) {
404
+ const t = Ft(e, bn), n = g.useRef(t), [s, o] = g.useState(po);
405
+ return g.useEffect(() => {
406
+ const i = n.current;
407
+ if (bn(i, t)) return;
408
+ const r = /* @__PURE__ */ new Map();
409
+ for (const [a, l] of t) {
410
+ const d = ze(i, a);
411
+ for (const u of l) {
412
+ if (d.has(u)) continue;
413
+ const v = r.get(a) ?? /* @__PURE__ */ new Set();
414
+ v.add(u), r.set(a, v);
415
+ }
416
+ }
417
+ if (n.current = t, o(r), r.size === 0) return;
418
+ const c = setTimeout(() => o(po), 450);
419
+ return () => clearTimeout(c);
420
+ }, [t]), s;
421
+ }
422
+ function Vl(e, t, n) {
423
+ const s = ze(e, t), o = new Set(s);
424
+ return o.has(n) ? o.delete(n) : o.add(n), on(e, t, o);
425
+ }
426
+ function Li(e, t, n) {
427
+ const s = ze(e, t), o = n.some((r) => s.has(r)), i = new Set(s);
428
+ if (o) for (const r of n) i.delete(r);
429
+ else for (const r of n) i.add(r);
430
+ return on(e, t, i);
431
+ }
432
+ function Pi({ locked: e, onClick: t, flashing: n, label: s }) {
433
+ const o = e ? `${s} filter locked — held as it is; click to unlock` : `${s} filter unlocked — click to lock and hold it as it is`, i = [
434
+ "gv-lock-toggle",
435
+ e ? "locked" : "",
436
+ n ? "flashing" : ""
437
+ ].filter(Boolean).join(" ");
438
+ return /* @__PURE__ */ h(
439
+ "button",
440
+ {
441
+ className: i,
442
+ onClick: t,
443
+ title: o,
444
+ "aria-label": o,
445
+ "aria-pressed": e,
446
+ children: e ? /* @__PURE__ */ h(Di, {}) : /* @__PURE__ */ h(_i, {})
447
+ }
448
+ );
449
+ }
450
+ function Di() {
451
+ return /* @__PURE__ */ C("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
452
+ /* @__PURE__ */ h("rect", { x: "3", y: "7", width: "10", height: "7", rx: "1.5" }),
453
+ /* @__PURE__ */ h("path", { d: "M5.5 7V5a2.5 2.5 0 0 1 5 0v2" })
454
+ ] });
455
+ }
456
+ function _i() {
457
+ return /* @__PURE__ */ C("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
458
+ /* @__PURE__ */ h("rect", { x: "3", y: "7", width: "10", height: "7", rx: "1.5" }),
459
+ /* @__PURE__ */ h("path", { d: "M5.5 7V5a2.5 2.5 0 0 1 4.9-.6" })
460
+ ] });
461
+ }
462
+ function Bi({ size: e = 16 }) {
463
+ return /* @__PURE__ */ C(
464
+ "svg",
465
+ {
466
+ width: e,
467
+ height: e,
468
+ viewBox: "0 0 24 24",
469
+ fill: "none",
470
+ stroke: "currentColor",
471
+ strokeWidth: "2.5",
472
+ strokeLinecap: "round",
473
+ strokeLinejoin: "round",
474
+ style: { display: "block" },
475
+ children: [
476
+ /* @__PURE__ */ h("circle", { cx: "11", cy: "11", r: "7" }),
477
+ /* @__PURE__ */ h("line", { x1: "16.65", y1: "16.65", x2: "21", y2: "21" })
478
+ ]
479
+ }
480
+ );
481
+ }
482
+ function Hi(e, t, n, s) {
483
+ return n.styleValues.includes(t) || s.has(e) || (s.add(e), console.error(`[filter] chip ${JSON.stringify(e)} borrows the colour of ${JSON.stringify(t)}, which the taxonomy does not declare`)), t;
484
+ }
485
+ const hs = /* @__PURE__ */ new Set(), zi = {
486
+ chip: { sectionClass: "gv-chip-section", rowClass: "gv-chip-row", chipClass: "gv-chip", modifierPrefix: "gv-chip", activeClass: "active", iconClass: "gv-chip-icon", labelClass: "gv-chip-label" },
487
+ tag: { sectionClass: "gv-tag-section", rowClass: "gv-tag-row", chipClass: "gv-tag", modifierPrefix: "", activeClass: "selected", iconClass: "gv-tag-icon", labelClass: "gv-tag-label" }
488
+ };
489
+ function Vi({
490
+ taxonomy: e,
491
+ chrome: t,
492
+ theme: n = "system",
493
+ systemTheme: s,
494
+ counts: o,
495
+ values: i,
496
+ graph: r,
497
+ filter: c,
498
+ onFilterChange: a,
499
+ locks: l,
500
+ onLocksChange: d,
501
+ overriddenLocks: u = hs,
502
+ recentlyChanged: v,
503
+ search: M,
504
+ onSearchChange: S,
505
+ searchInputRef: p,
506
+ searchTitle: $ = "Search (/)",
507
+ searchPlaceholder: D = "Search…",
508
+ searchExtra: x,
509
+ hiddenMatches: V,
510
+ findings: F,
511
+ refreshFlash: L,
512
+ axes: y,
513
+ onAxesChange: I
514
+ }) {
515
+ const E = g.useContext(_n), O = e ?? E;
516
+ if (!O) throw new Error("FilterBar has no taxonomy: pass `taxonomy`, or mount it inside <TaxonomyContext.Provider value={…}>.");
517
+ const X = g.useRef(/* @__PURE__ */ new Set()), N = Ft(c, bn), [k, w] = Mt(l, d, () => /* @__PURE__ */ new Map(), "locks"), R = Ft(k, Go), z = (t == null ? void 0 : t.locks) ?? (l !== void 0 && d !== void 0), pe = (t == null ? void 0 : t.search) ?? !0, [ke, St] = g.useState(hs);
518
+ g.useEffect(() => {
519
+ if (St(u), u.size === 0) return;
520
+ const Y = setTimeout(() => St(hs), 600);
521
+ return () => clearTimeout(Y);
522
+ }, [u]);
523
+ const [Ne, ct] = g.useState(!1);
524
+ g.useEffect(() => {
525
+ if (!L) return;
526
+ ct(!0);
527
+ const Y = setTimeout(() => ct(!1), 600);
528
+ return () => clearTimeout(Y);
529
+ }, [L]);
530
+ const [at, lt] = Mt(y, I, () => O.filterAxes.map((Y) => Y.id), "axes"), Ie = Ft(at, Xo), dt = y === void 0 || I !== void 0, [De, ht] = Mt(M, S, () => ({ query: "", active: !1 }), "search"), { query: b, active: T } = De, U = g.useRef(null), se = p ?? U, G = g.useRef(null), oe = Ho(G, n, s), B = g.useMemo(() => zo(O, oe), [O, oe]), [f, q] = g.useState(!1), te = (Y) => {
531
+ var re;
532
+ return ((re = O.axisFor(Y)) == null ? void 0 : re.label) ?? Y;
533
+ }, le = Jo(N), Ee = v ?? le, Me = g.useMemo(
534
+ () => i ?? new Map([.../* @__PURE__ */ new Set([...O.filterAxes.map((Y) => Y.id), ...Ie])].map((Y) => [Y, r ? sn(r.nodes, Y) : []])),
535
+ [i, r, Ie, O]
536
+ ), A = g.useMemo(
537
+ () => o ?? (r ? _o(r.nodes, Ie) : void 0),
538
+ [o, r, Ie]
539
+ ), Oe = (Y, re) => ({
540
+ values: [...Me.get(Y) ?? []],
541
+ counts: A == null ? void 0 : A.get(Y),
542
+ hidden: V == null ? void 0 : V.get(Y),
543
+ ...zi[(re == null ? void 0 : re.presentation) ?? "chip"]
544
+ }), xe = O.filterAxes.map((Y) => Y.id).filter((Y) => {
545
+ var re;
546
+ return !Ie.includes(Y) && (((re = Me.get(Y)) == null ? void 0 : re.length) ?? 0) > 0;
547
+ });
548
+ g.useEffect(() => {
549
+ xe.length < 2 && q(!1);
550
+ }, [xe.length]);
551
+ const xt = () => {
552
+ T ? ht({ query: "", active: !1 }) : (ht({ query: b, active: !0 }), setTimeout(() => {
553
+ var Y;
554
+ return (Y = se.current) == null ? void 0 : Y.focus();
555
+ }, 50));
556
+ };
557
+ return /* @__PURE__ */ C("div", { className: `gv-canvas-header${Ne ? " refresh-flash" : ""}`, ref: G, "data-theme": oe, style: B, children: [
558
+ Ie.map((Y) => {
559
+ const re = O.axisFor(Y), Qe = (re == null ? void 0 : re.label) ?? Y, Z = Oe(Y, re), _e = new Set(Z.values), Be = re ? re.chipsFor(Z.values).filter((ye) => ye.values.some((Ue) => _e.has(Ue))) : [], rn = Be.length === 0, kt = ze(N, Y), et = Ls(R, Y), Ve = kt.size === 0 && (re == null ? void 0 : re.emptyMeans) === "all";
560
+ return /* @__PURE__ */ C(g.Fragment, { children: [
561
+ /* @__PURE__ */ C("div", { className: `${Z.sectionClass}${et ? " section-locked" : ""}`, children: [
562
+ /* @__PURE__ */ C("div", { className: Z.rowClass, children: [
563
+ /* @__PURE__ */ h("span", { className: "gv-header-axis-label", children: Qe }),
564
+ rn && /* @__PURE__ */ h("span", { className: "gv-header-axis-empty", title: re ? `${Qe} has no values in this view` : `${Qe} is not an axis the taxonomy declares`, children: re ? `no ${Qe.toLowerCase()} values` : "not declared" }),
565
+ Be.map((ye) => {
566
+ const Ue = ye.values.some((H) => kt.has(H)), gt = ye.values.some((H) => {
567
+ var ne;
568
+ return (ne = Ee.get(Y)) == null ? void 0 : ne.has(H);
569
+ }), tt = ye.values.reduce((H, ne) => {
570
+ var J;
571
+ return H + (((J = Z.hidden) == null ? void 0 : J.get(ne)) ?? 0);
572
+ }, 0), _ = Z.counts === void 0 ? void 0 : ye.values.reduce((H, ne) => H + (Z.counts.get(ne) ?? 0), 0), K = [
573
+ Z.chipClass,
574
+ Ve ? "all-included" : Ue ? Z.activeClass : "",
575
+ Z.modifierPrefix ? `${Z.modifierPrefix}-${ye.id}` : "",
576
+ gt ? "recently-changed" : ""
577
+ ].filter(Boolean).join(" ");
578
+ return /* @__PURE__ */ C(
579
+ "button",
580
+ {
581
+ className: K,
582
+ style: ye.tint ? { "--gv-chip-tint": `var(${O.colorVar(Hi(ye.id, ye.tint, O, X.current))})` } : void 0,
583
+ onClick: () => a(Li(N, Y, ye.values), [Y]),
584
+ title: ye.tooltip ?? (Ue ? `Hide ${ye.label.toLowerCase()}` : `Show ${ye.label.toLowerCase()}`),
585
+ children: [
586
+ ye.icon && /* @__PURE__ */ h("span", { className: Z.iconClass, children: ye.icon }),
587
+ /* @__PURE__ */ h("span", { className: Z.labelClass, children: ye.label }),
588
+ _ !== void 0 && /* @__PURE__ */ h("span", { className: "gv-header-chip-count", children: _ }),
589
+ tt > 0 && /* @__PURE__ */ h("span", { className: "gv-header-hidden-badge", title: `${tt} match${tt !== 1 ? "es" : ""} hidden by this filter`, children: tt })
590
+ ]
591
+ },
592
+ ye.id
593
+ );
594
+ })
595
+ ] }),
596
+ z && re && /* @__PURE__ */ h(
597
+ Pi,
598
+ {
599
+ locked: et,
600
+ onClick: () => w(Ai(R, Y, !et)),
601
+ flashing: ke.has(Y),
602
+ label: Qe
603
+ }
604
+ ),
605
+ dt && /* @__PURE__ */ h(
606
+ "button",
607
+ {
608
+ className: "gv-header-remove",
609
+ onClick: () => {
610
+ a(on(
611
+ N,
612
+ Y,
613
+ (re == null ? void 0 : re.emptyMeans) !== "none" ? /* @__PURE__ */ new Set() : new Set(Be.flatMap((ye) => [...ye.values]))
614
+ ), [Y]), lt(Ie.filter((ye) => ye !== Y));
615
+ },
616
+ title: `Remove the ${Qe} filter`,
617
+ children: "×"
618
+ }
619
+ )
620
+ ] }),
621
+ /* @__PURE__ */ h("div", { className: "gv-header-divider" })
622
+ ] }, Y);
623
+ }),
624
+ dt && xe.length > 0 && /* @__PURE__ */ C("div", { className: "gv-header-add", children: [
625
+ /* @__PURE__ */ h(
626
+ "button",
627
+ {
628
+ className: "gv-header-add-button",
629
+ onClick: () => xe.length === 1 ? lt([...Ie, xe[0]]) : q((Y) => !Y),
630
+ title: xe.length === 1 ? `Add the ${te(xe[0])} filter` : "Add a filter",
631
+ "aria-haspopup": xe.length > 1 ? "menu" : void 0,
632
+ "aria-expanded": xe.length > 1 ? f : void 0,
633
+ children: "+"
634
+ }
635
+ ),
636
+ f && xe.length > 1 && /* @__PURE__ */ h("div", { className: "gv-header-add-menu", role: "menu", onKeyDown: (Y) => {
637
+ Y.key === "Escape" && q(!1);
638
+ }, children: xe.map((Y) => /* @__PURE__ */ h("button", { role: "menuitem", className: "gv-header-add-menu-item", onClick: () => {
639
+ lt([...Ie, Y]), q(!1);
640
+ }, children: te(Y) }, Y)) })
641
+ ] }),
642
+ /* @__PURE__ */ h("div", { className: "gv-header-divider" }),
643
+ pe && /* @__PURE__ */ h("div", { className: "gv-header-controls-section", children: /* @__PURE__ */ C("div", { className: `gv-header-search ${T ? "active" : ""}`, children: [
644
+ /* @__PURE__ */ h("button", { className: "gv-header-search-toggle", onClick: xt, title: $, children: /* @__PURE__ */ h(Bi, { size: 14 }) }),
645
+ T && /* @__PURE__ */ h(
646
+ "input",
647
+ {
648
+ ref: se,
649
+ className: "gv-header-search-input",
650
+ type: "text",
651
+ placeholder: D,
652
+ value: b,
653
+ onChange: (Y) => ht({ query: Y.target.value, active: !0 }),
654
+ onKeyDown: (Y) => {
655
+ Y.key === "Escape" && xt();
656
+ }
657
+ }
658
+ ),
659
+ x
660
+ ] }) }),
661
+ F
662
+ ] });
663
+ }
664
+ const Vt = (e) => e.copyKey ?? e.id;
665
+ function Gi(e) {
666
+ const t = /* @__PURE__ */ new Map();
667
+ for (const n of e.nodes) {
668
+ const s = Vt(n), o = t.get(s);
669
+ o ? o.add(n.id) : t.set(s, /* @__PURE__ */ new Set([n.id]));
670
+ }
671
+ return t;
672
+ }
673
+ function Gl(e, t) {
674
+ var s;
675
+ const n = (s = e.payload) == null ? void 0 : s[t];
676
+ return typeof n == "string" ? n : void 0;
677
+ }
678
+ function Xl(e, t) {
679
+ var s;
680
+ const n = (s = e.payload) == null ? void 0 : s[t];
681
+ return typeof n == "number" ? n : void 0;
682
+ }
683
+ function xn(e) {
684
+ return e.relation === "containment" ? "containment" : "dependency";
685
+ }
686
+ function it(e) {
687
+ return e.relation === "containment";
688
+ }
689
+ function Pt(e) {
690
+ const t = /* @__PURE__ */ new Map();
691
+ for (const n of e) t.has(n.id) || t.set(n.id, n);
692
+ return t;
693
+ }
694
+ function Xi(e) {
695
+ var i;
696
+ const t = Pt(e.nodes), n = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set();
697
+ for (const r of e.edges)
698
+ s.add(r.id), r.relation === "containment" && r.targetId === ((i = t.get(r.sourceId)) == null ? void 0 : i.parentId) && n.add(r.sourceId);
699
+ const o = [];
700
+ for (const r of e.nodes) {
701
+ if (r.parentId === void 0 || !t.has(r.parentId) || n.has(r.id)) continue;
702
+ let c = `in:${r.id}`;
703
+ for (let a = 2; s.has(c); a++) c = `in:${r.id}#${a}`;
704
+ s.add(c), o.push({ id: c, sourceId: r.id, targetId: r.parentId, relation: "containment" });
705
+ }
706
+ return o.length === 0 ? e : { nodes: e.nodes, edges: [...e.edges, ...o] };
707
+ }
708
+ function jo(e) {
709
+ const t = Pt(e.nodes);
710
+ return { nodes: e.nodes, edges: e.edges, getNode: (n) => t.get(n) };
711
+ }
712
+ const mo = (e, t) => {
713
+ if (e === t) return !0;
714
+ if (e === void 0 || t === void 0) return !1;
715
+ const n = Object.keys(e);
716
+ if (n.length !== Object.keys(t).length) return !1;
717
+ for (const s of n) if (e[s] !== t[s]) return !1;
718
+ return !0;
719
+ }, Yi = (e, t) => e === t || e !== void 0 && t !== void 0 && e.length === t.length && e.every((n, s) => n === t[s]);
720
+ function Ji(e, t) {
721
+ if (e === t) return !0;
722
+ if (e.nodes.length !== t.nodes.length || e.edges.length !== t.edges.length) return !1;
723
+ for (let n = 0; n < e.nodes.length; n++) {
724
+ const s = e.nodes[n], o = t.nodes[n];
725
+ if (s !== o && (s.id !== o.id || s.name !== o.name || s.parentId !== o.parentId || s.copyKey !== o.copyKey || s.ring !== o.ring || s.payload !== o.payload || !mo(s.values, o.values) || !Yi(s.badges, o.badges)))
726
+ return !1;
727
+ }
728
+ for (let n = 0; n < e.edges.length; n++) {
729
+ const s = e.edges[n], o = t.edges[n];
730
+ if (s !== o && (s.id !== o.id || s.sourceId !== o.sourceId || s.targetId !== o.targetId || s.relation !== o.relation || s.payload !== o.payload || !mo(s.values, o.values)))
731
+ return !1;
732
+ }
733
+ return !0;
734
+ }
735
+ function qo({ destination: e, source: t, locks: n, transition: s, taxonomy: o, axes: i, graph: r }) {
736
+ const c = i.flatMap((a) => {
737
+ const l = o.axisFor(a);
738
+ return l ? [l] : [];
739
+ });
740
+ switch (s.kind) {
741
+ case "manual":
742
+ return ji(e, t, n, c);
743
+ case "focus":
744
+ return qi(e, n, s.target, c, r);
745
+ }
746
+ }
747
+ function ji(e, t, n, s) {
748
+ let o = e;
749
+ for (const i of s)
750
+ Ls(n, i.id) || (o = on(o, i.id, ze(t, i.id)));
751
+ return { filter: o, overriddenLocks: /* @__PURE__ */ new Set() };
752
+ }
753
+ function qi(e, t, n, s, o) {
754
+ let i = e;
755
+ const r = /* @__PURE__ */ new Set();
756
+ for (const c of s) {
757
+ const a = n.values[c.id];
758
+ if (a === void 0) continue;
759
+ const l = ze(e, c.id);
760
+ l.has(a) || c.widens === "whenActive" && l.size === 0 || (i = on(i, c.id, /* @__PURE__ */ new Set([...l, ...Ui(c, a, o)])), Ls(t, c.id) && r.add(c.id));
761
+ }
762
+ return {
763
+ filter: bn(i, e) ? e : i,
764
+ overriddenLocks: r
765
+ };
766
+ }
767
+ function Ui(e, t, n) {
768
+ if (!n) return [t];
769
+ const s = sn(n.nodes, e.id), o = e.chipsFor(s).find((c) => c.values.includes(t));
770
+ if (!o) return [t];
771
+ const i = new Set(s), r = o.values.filter((c) => i.has(c));
772
+ return r.includes(t) ? r : [t, ...r];
773
+ }
774
+ function Ki(e) {
775
+ const t = e.label ?? e.id;
776
+ return { id: e.id, label: t, tooltip: e.tooltip ?? t, normalize: e.normalize, compute: (n) => e.compute(n) };
777
+ }
778
+ function Zt(e) {
779
+ return "scalar" in e;
780
+ }
781
+ function Uo(e) {
782
+ const t = /* @__PURE__ */ new Map();
783
+ for (const o of e.edges) {
784
+ if (it(o)) continue;
785
+ const i = t.get(o.sourceId);
786
+ i ? i.push(o.targetId) : t.set(o.sourceId, [o.targetId]);
787
+ }
788
+ const n = /* @__PURE__ */ new Map();
789
+ for (const o of e.nodes) {
790
+ const i = /* @__PURE__ */ new Set([o.id]);
791
+ let r = 0, c = [o.id];
792
+ for (; c.length > 0; ) {
793
+ const a = [];
794
+ for (const l of c) {
795
+ const d = t.get(l);
796
+ if (d)
797
+ for (const u of d)
798
+ i.has(u) || (i.add(u), a.push(u));
799
+ }
800
+ a.length > 0 && r++, c = a;
801
+ }
802
+ n.set(o.id, r);
803
+ }
804
+ const s = new Map(n);
805
+ for (const o of e.nodes) {
806
+ const i = n.get(o.id) ?? 0;
807
+ if (i <= 0) continue;
808
+ let r = o.parentId === void 0 ? void 0 : e.getNode(o.parentId), c = i;
809
+ const a = /* @__PURE__ */ new Set();
810
+ for (; r && !a.has(r.id) && (a.add(r.id), c += 1, !((s.get(r.id) ?? 0) >= c)); )
811
+ s.set(r.id, c), r = r.parentId === void 0 ? void 0 : e.getNode(r.parentId);
812
+ }
813
+ return Yn(s);
814
+ }
815
+ function Wi(e) {
816
+ const t = /* @__PURE__ */ new Map();
817
+ for (const n of e.nodes) t.set(n.id, 0);
818
+ for (const n of e.edges)
819
+ it(n) || (e.getNode(n.sourceId) && t.set(n.sourceId, (t.get(n.sourceId) ?? 0) + 1), e.getNode(n.targetId) && t.set(n.targetId, (t.get(n.targetId) ?? 0) + 1));
820
+ return Yn(t);
821
+ }
822
+ function Zi(e) {
823
+ const t = /* @__PURE__ */ new Map();
824
+ for (const n of e.nodes) {
825
+ let s = 0, o = n.parentId === void 0 ? void 0 : e.getNode(n.parentId);
826
+ const i = /* @__PURE__ */ new Set();
827
+ for (; o && !i.has(o.id); )
828
+ i.add(o.id), s++, o = o.parentId === void 0 ? void 0 : e.getNode(o.parentId);
829
+ t.set(n.id, s);
830
+ }
831
+ return Yn(t);
832
+ }
833
+ function Yn(e) {
834
+ let t = 0;
835
+ for (const s of e.values()) s > t && (t = s);
836
+ const n = /* @__PURE__ */ new Map();
837
+ for (const [s, o] of e) n.set(s, t === 0 ? 0 : o / t);
838
+ return n;
839
+ }
840
+ function Qi(e) {
841
+ let t = 1 / 0, n = -1 / 0;
842
+ for (const o of e.values())
843
+ o < t && (t = o), o > n && (n = o);
844
+ const s = /* @__PURE__ */ new Map();
845
+ for (const [o, i] of e) s.set(o, n > t ? (i - t) / (n - t) : 0);
846
+ return s;
847
+ }
848
+ const ec = {
849
+ id: "reach",
850
+ label: "Reach",
851
+ tooltip: "Downstream reach: how many dependency levels deep a node’s subtree runs, propagated up containment; leaves at 0",
852
+ compute: Uo,
853
+ normalize: "none"
854
+ }, tc = {
855
+ id: "degree",
856
+ label: "Degree",
857
+ tooltip: "Dependency edges in and out, as a fraction of the busiest node’s",
858
+ compute: Wi,
859
+ normalize: "none"
860
+ }, nc = {
861
+ id: "depth",
862
+ label: "Depth",
863
+ tooltip: "Containment depth: 0 at the top of the hierarchy, 1 at the deepest node",
864
+ compute: Zi,
865
+ normalize: "none"
866
+ }, sc = [ec, tc, nc], wn = { color: { light: "#94A3B8", dark: "#64748B" }, alpha: 0.7, dash: [], width: 1.2 }, Ko = { color: { light: "#94A3B8", dark: "#64748B" }, alpha: 0.35, dash: [3, 4], width: 1 };
867
+ function Mn(e) {
868
+ return typeof e == "string" ? [e] : e;
869
+ }
870
+ function hn(e) {
871
+ const t = Mn(e.targetValue);
872
+ return Mn(e.sourceValue).flatMap((n) => t.map((s) => [n, s]));
873
+ }
874
+ const Jt = { top: -300, bottom: 400, x: { min: 0, max: 380 } }, oc = 12, Wo = { strength: 0.5, distance: 120 };
875
+ function rc(e, t) {
876
+ if (t <= 1) return { min: Jt.top, max: Jt.bottom };
877
+ const n = (Jt.bottom - Jt.top) / (t - 1), s = Jt.top + n * e, o = n * 0.6;
878
+ return { min: Math.round(s - o), max: Math.round(s + o) };
879
+ }
880
+ function vo(e, t, n) {
881
+ var o, i, r, c, a, l, d, u;
882
+ const s = ((o = e.size) == null ? void 0 : o.r) ?? oc;
883
+ return {
884
+ ...e,
885
+ abbreviation: e.abbreviation ?? e.label.slice(0, 2),
886
+ icon: e.icon ?? "",
887
+ size: { r: s, iconSize: ((i = e.size) == null ? void 0 : i.iconSize) ?? Math.max(9, Math.round(s * 0.9)) },
888
+ physics: {
889
+ charge: ((r = e.physics) == null ? void 0 : r.charge) ?? -40 * s,
890
+ coreRadius: ((c = e.physics) == null ? void 0 : c.coreRadius) ?? 4 * s,
891
+ band: {
892
+ x: ((l = (a = e.physics) == null ? void 0 : a.band) == null ? void 0 : l.x) ?? { ...Jt.x },
893
+ y: ((u = (d = e.physics) == null ? void 0 : d.band) == null ? void 0 : u.y) ?? rc(t, n)
894
+ }
895
+ },
896
+ whenHidden: e.whenHidden ?? "ascend",
897
+ summaryKind: e.summaryKind ?? "degree"
898
+ };
899
+ }
900
+ function ic(e) {
901
+ var s;
902
+ const t = e.relation === "containment" ? Ko : wn, n = e.label ?? e.id;
903
+ return {
904
+ ...e,
905
+ label: n,
906
+ sourceValue: Mn(e.sourceValue)[0],
907
+ targetValue: Mn(e.targetValue)[0],
908
+ pairs: hn(e),
909
+ physics: e.physics ?? { ...Wo },
910
+ style: { ...t, ...e.style, color: { ...t.color, ...(s = e.style) == null ? void 0 : s.color } },
911
+ tooltip: e.tooltip ?? n
912
+ };
913
+ }
914
+ const Zo = 2, Gt = {
915
+ charge: 0,
916
+ coreRadius: Zo,
917
+ /** On either axis: a point band at the axis's centre. */
918
+ band: { min: 0, max: 0 }
919
+ }, ft = (e) => "scalar" in e;
920
+ function Dt(e, t) {
921
+ var n;
922
+ return (n = e.mapping.bucketFor(t.values[e.mapping.axis])) == null ? void 0 : n.id;
923
+ }
924
+ function yo(e, t) {
925
+ let n = 0, s = 0;
926
+ for (const i of t) {
927
+ const r = e.styleOf(i).physics;
928
+ n += r.charge, s += r.coreRadius;
929
+ }
930
+ const o = Math.max(t.length, 1);
931
+ return { charge: n / o, coreRadius: s / o };
932
+ }
933
+ function Is(e, t, n) {
934
+ let s = 1 / 0, o = -1 / 0;
935
+ for (const i of t) {
936
+ const r = e.styleOf(i).physics.band[n];
937
+ s = Math.min(s, r.min), o = Math.max(o, r.max);
938
+ }
939
+ return t.length === 0 ? { ...Gt.band } : { min: s, max: o };
940
+ }
941
+ function cc(e, t) {
942
+ const n = Is(e, e.styleValues, t), s = (n.max - n.min) / 2;
943
+ return t === "y" ? { zero: s, one: -s } : { zero: -s, one: s };
944
+ }
945
+ function bo(e, t, n) {
946
+ const s = /* @__PURE__ */ new Map();
947
+ for (const o of e.buckets)
948
+ s.set(o.id, t.get(o.id) ?? n(o.values));
949
+ return { mapping: e, byBucket: s };
950
+ }
951
+ function $s(e, t) {
952
+ const n = t.styleAxis(), s = (r) => r.axis === n ? (c) => yo(t, c) : () => yo(t, t.styleValues), o = (r, c) => r.axis === n ? (a) => Is(t, a, c) : () => Is(t, t.styleValues, c), i = (r, c) => {
953
+ if (!Zt(r)) return bo(r.mapping, r.overrides, o(r.mapping, c));
954
+ const a = t.scalars.find((l) => l.id === r.scalar);
955
+ if (!a) throw new Error(`layout axis names scalar ${JSON.stringify(r.scalar)}, which the taxonomy does not declare`);
956
+ return { scalar: a, span: r.span ?? cc(t, c) };
957
+ };
958
+ return {
959
+ push: bo(e.pair.mapping, e.pair.push, s(e.pair.mapping)),
960
+ bandX: i(e.bandX, "x"),
961
+ bandY: i(e.bandY, "y"),
962
+ spring: _s(e.pair, t)
963
+ };
964
+ }
965
+ function Qo(e, t) {
966
+ var s;
967
+ const n = Dt(e, t);
968
+ return (n === void 0 || (s = e.byBucket.get(n)) == null ? void 0 : s.charge) ?? Gt.charge;
969
+ }
970
+ function er(e, t) {
971
+ var s;
972
+ const n = Dt(e, t);
973
+ return Math.max(
974
+ (n === void 0 || (s = e.byBucket.get(n)) == null ? void 0 : s.coreRadius) ?? Gt.coreRadius,
975
+ Zo
976
+ );
977
+ }
978
+ function gn(e, t) {
979
+ return e.byBucket.get(t) ?? { charge: Gt.charge, coreRadius: Gt.coreRadius };
980
+ }
981
+ function gs(e, t) {
982
+ return e.byBucket.get(t) ?? { ...Gt.band };
983
+ }
984
+ function Ds(e, t) {
985
+ return (t === void 0 ? void 0 : e.byBucket.get(t)) ?? Gt.band;
986
+ }
987
+ function Kt(e, t) {
988
+ const n = /* @__PURE__ */ new Set();
989
+ for (const s of e) {
990
+ const o = Dt(t, s);
991
+ o !== void 0 && n.add(o);
992
+ }
993
+ return [...n];
994
+ }
995
+ const tr = (e) => (e.min + e.max) / 2;
996
+ function ac(e, t) {
997
+ return Kt(e, t).map((n) => tr(Ds(t, n)));
998
+ }
999
+ function lc(e, t) {
1000
+ const n = ac(e, t).sort((o, i) => o - i), s = n.length;
1001
+ return s === 0 ? 0 : s % 2 ? n[(s - 1) / 2] : (n[s / 2 - 1] + n[s / 2]) / 2;
1002
+ }
1003
+ function dc(e, t) {
1004
+ const n = Kt(e, t), s = n.map((r) => tr(Ds(t, r))), o = s.length ? Math.min(...s) : 0, i = (s.length ? Math.max(...s) : 0) - o || 1;
1005
+ return new Map(n.map((r, c) => [r, Bn + (s[c] - o) / i * (or - Bn)]));
1006
+ }
1007
+ const xo = { lo: 0, hi: 0 };
1008
+ function uc(e, t) {
1009
+ const n = e.compute(t);
1010
+ for (const [o, i] of n)
1011
+ if (!Number.isFinite(i)) throw new Error(`scalar ${JSON.stringify(e.id)} answered ${String(i)} for node ${JSON.stringify(o)}; a scalar answers a finite number`);
1012
+ const s = e.normalize === "none" ? n : e.normalize === "range" ? Qi(n) : Yn(n);
1013
+ for (const [o, i] of s)
1014
+ if (!(Number.isFinite(i) && i >= 0 && i <= 1))
1015
+ throw new Error(`scalar ${JSON.stringify(e.id)} answered ${String(i)} for node ${JSON.stringify(o)}; a scalar answers in [0, 1]`);
1016
+ return s;
1017
+ }
1018
+ function Cs(e, t) {
1019
+ const n = [...e.nodes], s = (u) => ft(u) ? 0 : lc(n, u), o = (u) => ft(u) ? uc(u.scalar, e) : void 0, i = s(t.bandX), r = s(t.bandY), c = o(t.bandX), a = o(t.bandY), l = ft(t.bandY) ? /* @__PURE__ */ new Map() : dc(n, t.bandY), d = (u, v, M, S) => {
1020
+ if (ft(u)) {
1021
+ const D = M == null ? void 0 : M.get(S.id);
1022
+ if (D === void 0) return xo;
1023
+ const x = u.span.zero + D * (u.span.one - u.span.zero);
1024
+ return { lo: x, hi: x };
1025
+ }
1026
+ const p = Dt(u, S), $ = p === void 0 ? void 0 : u.byBucket.get(p);
1027
+ return $ === void 0 ? xo : { lo: $.min - v, hi: $.max - v };
1028
+ };
1029
+ return {
1030
+ centerX: i,
1031
+ centerY: r,
1032
+ rings: l,
1033
+ rest: (u, v) => u === "x" ? d(t.bandX, i, c, v) : d(t.bandY, r, a, v),
1034
+ ringOf: (u) => {
1035
+ if (ft(t.bandY)) {
1036
+ if ((a == null ? void 0 : a.get(u.id)) === void 0) return 0;
1037
+ const M = d(t.bandY, r, a, u), { zero: S, one: p } = t.bandY.span, $ = Math.min(S, p), D = Math.abs(p - S) || 1;
1038
+ return Bn + (M.lo - $) / D * (or - Bn);
1039
+ }
1040
+ const v = Dt(t.bandY, u);
1041
+ return (v === void 0 ? void 0 : l.get(v)) ?? 0;
1042
+ }
1043
+ };
1044
+ }
1045
+ function nr(e) {
1046
+ return e.radial ? e.gravityY > 0 : e.gravityX > 0 || e.gravityY > 0;
1047
+ }
1048
+ function fc(e) {
1049
+ return e.topologicalEnabled && e.gravityTopological > 0;
1050
+ }
1051
+ function hc(e, t, n, s, o) {
1052
+ const i = [...e], r = nr(t), c = /* @__PURE__ */ new Map(), a = (d, u) => {
1053
+ for (const v of u) for (const M of v.buckets) if (!c.has(M)) {
1054
+ const S = o(d, M);
1055
+ S !== void 0 && c.set(M, S);
1056
+ }
1057
+ return u;
1058
+ };
1059
+ if (!r) return { acting: r, x: [], y: [], rings: [], colors: c };
1060
+ if (t.radial) {
1061
+ if (ft(n.bandY)) return { acting: r, x: [], y: [], rings: [], colors: c };
1062
+ const d = /* @__PURE__ */ new Map();
1063
+ for (const [u, v] of s.rings) {
1064
+ const M = d.get(v);
1065
+ if (M ? M.push(u) : d.set(v, [u]), !c.has(u)) {
1066
+ const S = o(n.bandY, u);
1067
+ S !== void 0 && c.set(u, S);
1068
+ }
1069
+ }
1070
+ return { acting: r, x: [], y: [], rings: [...d].map(([u, v]) => ({ radius: u, buckets: v })), colors: c };
1071
+ }
1072
+ const l = (d, u) => ft(d) ? [{ lo: Math.min(d.span.zero, d.span.one), hi: Math.max(d.span.zero, d.span.one), buckets: [], gradient: d.span }] : a(d, gc(i, d, u));
1073
+ return {
1074
+ acting: r,
1075
+ x: t.gravityX > 0 ? l(n.bandX, s.centerX) : [],
1076
+ y: t.gravityY > 0 ? l(n.bandY, s.centerY) : [],
1077
+ rings: [],
1078
+ colors: c
1079
+ };
1080
+ }
1081
+ function gc(e, t, n) {
1082
+ const s = /* @__PURE__ */ new Map();
1083
+ for (const o of Kt(e, t)) {
1084
+ const i = Ds(t, o), r = `${i.min}:${i.max}`, c = s.get(r);
1085
+ c ? c.buckets.push(o) : s.set(r, { lo: i.min - n, hi: i.max - n, buckets: [o] });
1086
+ }
1087
+ return [...s.values()];
1088
+ }
1089
+ const sr = { strength: 0, distance: 0 };
1090
+ function pc(e, t, n) {
1091
+ return JSON.stringify(t <= n ? [e, t, n] : [e, n, t]);
1092
+ }
1093
+ function mc(e) {
1094
+ try {
1095
+ const t = JSON.parse(e);
1096
+ if (Array.isArray(t) && t.length === 3 && (t[0] === "containment" || t[0] === "dependency") && typeof t[1] == "string" && typeof t[2] == "string") return [t[0], t[1], t[2]];
1097
+ } catch {
1098
+ }
1099
+ }
1100
+ function _s(e, t) {
1101
+ const { mapping: n, spring: s } = e;
1102
+ if (n.axis === t.styleAxis() && Fs(n)) {
1103
+ const r = new Map(t.edgeTypes.map((c) => [c.id, c]));
1104
+ return {
1105
+ mapping: n,
1106
+ // An edge no declared type of its relation claims has no category here:
1107
+ // it pulls nothing and draws in its relation's stroke, and the
1108
+ // diagnostics have named it.
1109
+ classify: (c, a, l) => {
1110
+ const d = t.edgeTypeOf(c, a, l), u = d === void 0 ? void 0 : r.get(d);
1111
+ return u !== void 0 && u.relation === xn(c) ? d : void 0;
1112
+ },
1113
+ physicsFor: (c) => {
1114
+ var a;
1115
+ return s.get(c) ?? ((a = r.get(c)) == null ? void 0 : a.physics) ?? sr;
1116
+ },
1117
+ describe: (c) => r.get(c)
1118
+ };
1119
+ }
1120
+ const o = Wo, i = new Map(n.buckets.map((r) => [r.id, r]));
1121
+ return {
1122
+ mapping: n,
1123
+ classify: (r, c, a) => c === void 0 || a === void 0 ? void 0 : pc(xn(r), c, a),
1124
+ physicsFor: (r) => s.get(r) ?? o,
1125
+ describe: (r) => {
1126
+ const c = mc(r);
1127
+ if (!c) return;
1128
+ const [a, l, d] = c, u = i.get(l), v = i.get(d);
1129
+ if (!(!u || !v))
1130
+ return {
1131
+ id: r,
1132
+ label: `${u.abbreviation}↔${v.abbreviation}`,
1133
+ sourceValue: l,
1134
+ targetValue: d,
1135
+ relation: a,
1136
+ physics: o,
1137
+ tooltip: `${u.label} ↔ ${v.label} ${a}`
1138
+ };
1139
+ }
1140
+ };
1141
+ }
1142
+ function Bs(e, t, n, s) {
1143
+ const o = e.classify(t, Dt(e, n), Dt(e, s)), i = o === void 0 ? sr : e.physicsFor(o);
1144
+ return { strength: i.strength, distance: i.distance, key: o };
1145
+ }
1146
+ function Hs(e, t, n) {
1147
+ const s = /* @__PURE__ */ new Set();
1148
+ for (const o of t) {
1149
+ const i = n(o.sourceId), r = n(o.targetId);
1150
+ if (!i || !r) continue;
1151
+ const c = Bs(e, o, i, r).key;
1152
+ c !== void 0 && s.add(c);
1153
+ }
1154
+ return s;
1155
+ }
1156
+ function vc(e, t, n, s, o) {
1157
+ const i = t.coreRadiusMultiplier, r = t.pushMultiplier, c = t.chargeExponent, a = e.length, l = new Float64Array(a), d = new Float64Array(a);
1158
+ for (let u = 0; u < a; u++)
1159
+ l[u] = Qo(n.push, e[u]), d[u] = i * er(n.push, e[u]);
1160
+ for (let u = 0; u < a; u++)
1161
+ for (let v = u + 1; v < a; v++) {
1162
+ const M = e[u], S = e[v];
1163
+ let p = S.x - M.x, $ = S.y - M.y, D = p * p + $ * $;
1164
+ if (D < 0.01) {
1165
+ const O = o() * Math.PI * 2;
1166
+ p = Math.cos(O), $ = Math.sin(O), D = 1;
1167
+ }
1168
+ const x = Math.sqrt(D), V = (d[u] + d[v]) / 2, F = V * V, L = (l[u] + l[v]) / 2, y = -(s * r * L / Math.pow(D + F, c)), I = y * (p / x), E = y * ($ / x);
1169
+ M.pinned || (M.vx -= I, M.vy -= E), S.pinned || (S.vx += I, S.vy += E);
1170
+ }
1171
+ }
1172
+ function yc(e, t, n, s, o, i) {
1173
+ const r = /* @__PURE__ */ new Map();
1174
+ for (const d of e)
1175
+ r.set(d.sourceId, (r.get(d.sourceId) ?? 0) + 1), r.set(d.targetId, (r.get(d.targetId) ?? 0) + 1);
1176
+ const c = n.pullMultiplier, a = n.linkExponent, l = n.distanceMultiplier;
1177
+ for (const d of e) {
1178
+ const u = t.get(d.sourceId), v = t.get(d.targetId);
1179
+ if (!u || !v) continue;
1180
+ let M = v.x - u.x, S = v.y - u.y, p = Math.sqrt(M * M + S * S);
1181
+ if (p < 0.1) {
1182
+ const N = i() * Math.PI * 2;
1183
+ M = Math.cos(N), S = Math.sin(N), p = 1;
1184
+ }
1185
+ const $ = s(d), D = $.distance * l, x = p - D, V = Math.abs(x), F = x >= 0 ? 1 : -1, L = o * c * $.strength * F * Math.pow(V, a) / p, y = L * M, I = L * S, E = r.get(d.sourceId) ?? 1, O = r.get(d.targetId) ?? 1, X = E / (E + O);
1186
+ u.pinned || (u.vx += y * (1 - X), u.vy += I * (1 - X)), v.pinned || (v.vx -= y * X, v.vy -= I * X);
1187
+ }
1188
+ }
1189
+ const Bn = 60, or = 540;
1190
+ function bc(e, t, n, s, o) {
1191
+ if (t.radial) {
1192
+ xc(e, t, n, s, o);
1193
+ return;
1194
+ }
1195
+ t.gravityX > 0 && wo(e, "x", n, t.gravityX, t.gravityBandExp, s), t.gravityY > 0 && wo(e, "y", n, t.gravityY, t.gravityBandExp, s);
1196
+ }
1197
+ function wo(e, t, n, s, o, i) {
1198
+ const r = t === "x" ? "vx" : "vy";
1199
+ for (const c of e) {
1200
+ if (c.pinned) continue;
1201
+ const { lo: a, hi: l } = n.rest(t, c), d = c[t];
1202
+ let u = null;
1203
+ d < a ? u = a : d > l && (u = l), u !== null && (c[r] -= rr(d - u, o, i * s));
1204
+ }
1205
+ }
1206
+ function rr(e, t, n) {
1207
+ return Math.sign(e) * Math.min(Math.pow(Math.abs(e), t) * n, Math.abs(e));
1208
+ }
1209
+ function xc(e, t, n, s, o) {
1210
+ const i = t.gravityY;
1211
+ for (const r of e) {
1212
+ if (r.pinned) continue;
1213
+ const c = n.ringOf(r), a = Math.hypot(r.x, r.y);
1214
+ if (a < 1e-6) {
1215
+ c > 0 && (r.vx += o() - 0.5, r.vy += o() - 0.5);
1216
+ continue;
1217
+ }
1218
+ const l = rr(a - c, t.gravityBandExp, s * i);
1219
+ r.vx -= r.x / a * l, r.vy -= r.y / a * l;
1220
+ }
1221
+ }
1222
+ const wc = -350;
1223
+ function Mc(e, t, n, s) {
1224
+ const o = t.gravityTopological;
1225
+ if (o <= 0 || !s) return;
1226
+ const i = t.gravityTopologicalExp, r = t.radial;
1227
+ for (const c of e) {
1228
+ if (c.pinned) continue;
1229
+ const a = s.get(c.id) ?? 0;
1230
+ if (a <= 0) continue;
1231
+ const l = Math.pow(a, i);
1232
+ r ? (c.vx -= c.x * n * o * l, c.vy -= c.y * n * o * l) : c.vy -= (c.y - wc) * n * o * l;
1233
+ }
1234
+ }
1235
+ function Sc(e, t, n) {
1236
+ const s = t.gravityCenter;
1237
+ if (!(s <= 0))
1238
+ for (const o of e)
1239
+ o.pinned || (o.vx -= o.x * n * s, o.vy -= o.y * n * s);
1240
+ }
1241
+ function kc(e, t, n, s) {
1242
+ return {
1243
+ push: new Set(Kt(e, n.push)),
1244
+ bandX: ft(n.bandX) ? /* @__PURE__ */ new Set() : new Set(Kt(e, n.bandX)),
1245
+ bandY: ft(n.bandY) ? /* @__PURE__ */ new Set() : new Set(Kt(e, n.bandY)),
1246
+ springs: Hs(n.spring, t, s)
1247
+ };
1248
+ }
1249
+ function Nc(e, t, n) {
1250
+ const s = new Map(e.overrides);
1251
+ return s.set(t, n), { ...e, overrides: s };
1252
+ }
1253
+ function ps(e) {
1254
+ if (Zt(e)) throw new Error(`expected a mapped axis, got scalar ${JSON.stringify(e.scalar)}`);
1255
+ return e;
1256
+ }
1257
+ function Sn(e) {
1258
+ return { mapping: e, push: /* @__PURE__ */ new Map(), spring: /* @__PURE__ */ new Map() };
1259
+ }
1260
+ function Ec(e, t, n) {
1261
+ const s = new Map(e.push);
1262
+ return s.set(t, n), { ...e, push: s };
1263
+ }
1264
+ function Ic(e, t, n) {
1265
+ const s = new Map(e.spring);
1266
+ return s.set(t, n), { ...e, spring: s };
1267
+ }
1268
+ function Qt(e) {
1269
+ return Vn({
1270
+ id: e.styleAxis(),
1271
+ label: e.styleLabel(),
1272
+ labelFor: (t) => e.styleOf(t).label,
1273
+ abbreviationFor: (t) => e.abbreviationFor(t)
1274
+ }, e.styleValues);
1275
+ }
1276
+ function Hn(e) {
1277
+ return { mapping: Qt(e), overrides: /* @__PURE__ */ new Map() };
1278
+ }
1279
+ const $c = 0.35, Lt = 24;
1280
+ function zs(e) {
1281
+ return e.pushTokens <= Lt && e.pullTokens <= Lt;
1282
+ }
1283
+ function Cc(e, t) {
1284
+ const n = [Qt(e)];
1285
+ for (const i of Ac(e, t)) {
1286
+ const r = sn(t.nodes, i);
1287
+ r.length > 0 && n.push(Vn(Vs(e, i), r));
1288
+ }
1289
+ const s = Pt(t.nodes), o = (i) => s.get(i);
1290
+ return n.map((i) => ({
1291
+ mapping: i,
1292
+ pushTokens: i.buckets.length,
1293
+ pullTokens: Hs(_s(Sn(i), e), t.edges, o).size
1294
+ }));
1295
+ }
1296
+ function Ac(e, t) {
1297
+ const n = e.styleAxis(), s = [], o = /* @__PURE__ */ new Set([n]);
1298
+ for (const i of e.filterAxes)
1299
+ o.has(i.id) || (o.add(i.id), s.push(i.id));
1300
+ for (const i of t.nodes)
1301
+ for (const r of Object.keys(i.values))
1302
+ o.has(r) || (o.add(r), s.push(r));
1303
+ return s;
1304
+ }
1305
+ function Vs(e, t) {
1306
+ return e.axisFor(t) ?? {
1307
+ id: t,
1308
+ label: t,
1309
+ labelFor: (n) => n,
1310
+ abbreviationFor: (n) => n.slice(0, 2)
1311
+ };
1312
+ }
1313
+ function Oc(e, t) {
1314
+ return [
1315
+ ...e.map((n) => ({ kind: "mapping", option: n })),
1316
+ ...t.scalars.map((n) => ({ kind: "scalar", scalar: n }))
1317
+ ];
1318
+ }
1319
+ function Yt(e) {
1320
+ return "kind" in e ? e.kind === "scalar" ? `scalar:${e.scalar.id}` : `mapping:${e.option.mapping.axis}` : Zt(e) ? `scalar:${e.scalar}` : `mapping:${e.mapping.axis}`;
1321
+ }
1322
+ function Rc(e, t) {
1323
+ const n = (s) => s.buckets.map((o) => `${o.id}=${[...o.values].sort().join(",")}`).sort().join(";");
1324
+ return e.axis === t.axis && n(e) === n(t);
1325
+ }
1326
+ function Tc(e, t, n) {
1327
+ const s = (p) => Zt(p) && !t.scalars.some(($) => $.id === p.scalar) ? Hn(t) : p;
1328
+ if (n.nodes.length === 0) {
1329
+ const p = s(e.bandX), $ = s(e.bandY);
1330
+ return p === e.bandX && $ === e.bandY ? e : { ...e, bandX: p, bandY: $ };
1331
+ }
1332
+ const o = t.styleAxis(), i = Pt(n.nodes), r = (p) => i.get(p), c = (p) => {
1333
+ if (p.axis === o) return Qt(t);
1334
+ const $ = sn(n.nodes, p.axis);
1335
+ return $.length === 0 ? void 0 : Vn(Vs(t, p.axis), $);
1336
+ }, a = (p, $, D) => {
1337
+ const x = c(p.mapping);
1338
+ return x === void 0 || x.axis !== o && !D(x) ? (Fc(p.mapping.axis, x === void 0 ? "no node carries it any more" : `it has ${x.buckets.length} buckets, past the ceiling of ${Lt}`), $(Qt(t))) : Rc(x, p.mapping) ? p : { ...p, mapping: x };
1339
+ }, l = (p) => p.buckets.length <= Lt, d = (p) => zs({
1340
+ pushTokens: p.buckets.length,
1341
+ pullTokens: Hs(_s(Sn(p), t), n.edges, r).size
1342
+ }), u = (p) => Zt(p) ? t.scalars.some(($) => $.id === p.scalar) ? p : Hn(t) : a(p, ($) => ({ mapping: $, overrides: /* @__PURE__ */ new Map() }), l), v = a(e.pair, Sn, d), M = u(e.bandX), S = u(e.bandY);
1343
+ return v === e.pair && M === e.bandX && S === e.bandY ? e : { ...e, pair: v, bandX: M, bandY: S };
1344
+ }
1345
+ const Mo = /* @__PURE__ */ new Set();
1346
+ function Fc(e, t) {
1347
+ const n = `${e}\0${t}`;
1348
+ Mo.has(n) || (Mo.add(n), console.warn(`[graph] the ${JSON.stringify(e)} axis cannot be tuned on: ${t}; the forces returned to the style axis with nothing overridden.`));
1349
+ }
1350
+ function ir(e) {
1351
+ return {
1352
+ // Both default to the axis the taxonomy resolves style on, so the layout
1353
+ // keys on the same thing it is coloured by.
1354
+ pair: Sn(Qt(e)),
1355
+ bandX: Hn(e),
1356
+ bandY: Hn(e),
1357
+ // Gravity. The Y bands carry the vertical structure of the layout — strong
1358
+ // (gravityY = 0.145) and overlapping at the edges so adjacent tiers can
1359
+ // soften their boundary instead of forming a hard stripe. The X bands bound
1360
+ // the horizontal spread, gently (gravityX = 0.05): wide fan-outs may spread.
1361
+ gravityX: 0.05,
1362
+ gravityY: 0.145,
1363
+ gravityBandExp: 1,
1364
+ radial: !1,
1365
+ // Off by default — the experiment lives behind a slider. When non-zero,
1366
+ // every node with a positive downstream score gets an additional pull
1367
+ // toward the focal point, layered additively on top of the bands.
1368
+ gravityTopological: 0,
1369
+ gravityTopologicalExp: 3,
1370
+ gravityCenter: 0.05,
1371
+ topologicalEnabled: !1,
1372
+ // Dynamics. alphaMin is well below the d3 default (0.001) so the
1373
+ // simulation continues into its slow-cooling tail — layouts read as
1374
+ // "settled" rather than freezing while springs are still measurably
1375
+ // active. friction and cooling are stock.
1376
+ alphaDecay: 5e-3,
1377
+ alphaMin: 1e-4,
1378
+ velocityDecay: 0.4,
1379
+ pushMultiplier: 0.4,
1380
+ pullMultiplier: 0.6,
1381
+ distanceMultiplier: 0.1,
1382
+ coreRadiusMultiplier: 1,
1383
+ chargeExponent: 0.7,
1384
+ // acts on (dist² + softening); = old 1.4 with the /2 folded in
1385
+ linkExponent: 1
1386
+ };
1387
+ }
1388
+ const ms = 50, Ot = 1e6, Lc = 200;
1389
+ function cr(e, t) {
1390
+ return e.filter((n) => t.has(n.sourceId) && t.has(n.targetId));
1391
+ }
1392
+ class Pc {
1393
+ // `taxonomy` is REQUIRED, deliberately: a default here would let one
1394
+ // construction site resolve through a taxonomy every component ignores,
1395
+ // a split no gate can see because both halves are individually correct.
1396
+ constructor(t, n, s, o, i) {
1397
+ Ze(this, "nodes");
1398
+ Ze(this, "edges");
1399
+ Ze(this, "params");
1400
+ Ze(this, "alpha");
1401
+ // Per-burst cooling rate set by `reheat()` so the settle window stays fixed
1402
+ // (~REHEAT_TICKS) no matter the kick size. Null means "cool at the normal
1403
+ // alphaDecay" — used during steady-state and live tuning via `nudge()`.
1404
+ Ze(this, "reheatDecay", null);
1405
+ Ze(this, "nodeMap");
1406
+ // Source of randomness for the degenerate-frame breakers and the position
1407
+ // jitter. Defaults to the platform generator, so app behaviour is unchanged.
1408
+ Ze(this, "rng");
1409
+ // The taxonomy the link force resolves spring categories through. Held rather
1410
+ // than imported so the engine is not bound to one set of edge categories.
1411
+ Ze(this, "taxonomy");
1412
+ // The per-bucket tables, resolved once from (params, taxonomy) and read by the
1413
+ // kernels per pair / per node. Recomputed only when either input changes —
1414
+ // never per tick, and never inside a loop.
1415
+ Ze(this, "resolved");
1416
+ // The frame the band forces act in — median centres and ring radii over the
1417
+ // WHOLE node set — shared by seeding, the kernels and (through the view) the
1418
+ // overlay, so they agree by construction. Recomputed with the tables.
1419
+ Ze(this, "frame");
1420
+ // Each edge's spring category, classified once per (edges, resolved) rather
1421
+ // than per tick: an edge's category depends on the edge, its endpoints'
1422
+ // buckets and the pair mapping, none of which change between ticks. Built on
1423
+ // first use and dropped whenever the tables are re-resolved.
1424
+ Ze(this, "springByEdge", null);
1425
+ // Loud on a miss: every edge the simulation owns is classified above, so an
1426
+ // absent entry means the cache and the edge list have come apart.
1427
+ Ze(this, "edgeCategory", (t) => {
1428
+ const s = (this.springByEdge ?? (this.springByEdge = this.classifyEdges())).get(t.id);
1429
+ if (s === void 0) throw new Error(`edge ${JSON.stringify(t.id)} has no spring classification; the cache and the edge list have come apart`);
1430
+ return s;
1431
+ });
1432
+ this.params = { ...ir(o), ...n }, this.alpha = 1, this.rng = s, this.taxonomy = o, this.resolved = $s(this.params, o), this.nodes = [], this.nodeMap = /* @__PURE__ */ new Map();
1433
+ const r = t.nodes;
1434
+ this.frame = Cs(jo(t), this.resolved);
1435
+ for (const c of r) {
1436
+ const a = i == null ? void 0 : i.get(c.id), [l, d] = a ? [a.x, a.y] : this.seedPosition(c, s), u = { ...c, x: l, y: d, vx: 0, vy: 0, pinned: !1 };
1437
+ this.nodes.push(u), this.nodeMap.set(u.id, u);
1438
+ }
1439
+ for (const c of this.nodes) {
1440
+ if (!c.parentId || i != null && i.has(c.id)) continue;
1441
+ const a = this.nodeMap.get(c.parentId);
1442
+ if (a)
1443
+ if (this.params.radial) {
1444
+ const l = Math.hypot(c.x, c.y), d = Math.atan2(a.y, a.x) + (s() - 0.5) * 0.3;
1445
+ c.x = l * Math.cos(d), c.y = l * Math.sin(d);
1446
+ } else {
1447
+ const l = this.axisBand(c, "x");
1448
+ c.x = Math.min(Math.max(a.x + (s() - 0.5) * 20, l.lo), l.hi);
1449
+ }
1450
+ }
1451
+ this.edges = t.edges;
1452
+ }
1453
+ getNode(t) {
1454
+ return this.nodeMap.get(t);
1455
+ }
1456
+ // A node's rest interval on one axis in the frame — a re-centred band, a
1457
+ // scalar's point, or the centre itself for a node with no value there.
1458
+ axisBand(t, n) {
1459
+ return this.frame.rest(n, t);
1460
+ }
1461
+ seedPosition(t, n) {
1462
+ if (this.params.radial) {
1463
+ const c = this.frame.ringOf(t), a = n() * Math.PI * 2;
1464
+ return [c * Math.cos(a), c * Math.sin(a)];
1465
+ }
1466
+ const s = this.axisBand(t, "x"), o = this.axisBand(t, "y"), i = Math.max(40, (s.hi - s.lo) * 0.7), r = Math.max(20, (o.hi - o.lo) / 2);
1467
+ return [
1468
+ (s.lo + s.hi) / 2 + (n() - 0.5) * i,
1469
+ (o.lo + o.hi) / 2 + (o.hi - o.lo) * $c + (n() - 0.5) * r
1470
+ ];
1471
+ }
1472
+ tick(t, n) {
1473
+ if (this.alpha < this.params.alphaMin) return;
1474
+ const s = t ? this.nodes.filter((d) => t.has(d.id)) : this.nodes, o = t ? cr(this.edges, t) : this.edges;
1475
+ vc(s, this.params, this.resolved, this.alpha, this.rng), yc(o, this.nodeMap, this.params, this.edgeCategory, this.alpha, this.rng);
1476
+ const i = nr(this.params), r = fc(this.params);
1477
+ i && bc(s, this.params, this.frame, this.alpha, this.rng), r && Mc(s, this.params, this.alpha, n), !i && !r && Sc(s, this.params, this.alpha);
1478
+ const c = this.params.velocityDecay, a = ms * ms;
1479
+ for (const d of s) {
1480
+ if (d.pinned) continue;
1481
+ d.vx *= c, d.vy *= c, Number.isFinite(d.vx) || (d.vx = 0), Number.isFinite(d.vy) || (d.vy = 0);
1482
+ const u = d.vx * d.vx + d.vy * d.vy;
1483
+ if (u > a) {
1484
+ const v = ms / Math.sqrt(u);
1485
+ d.vx *= v, d.vy *= v;
1486
+ }
1487
+ d.x += d.vx, d.y += d.vy, Number.isFinite(d.x) || (d.x = 0), Number.isFinite(d.y) || (d.y = 0), d.x < -Ot ? d.x = -Ot : d.x > Ot && (d.x = Ot), d.y < -Ot ? d.y = -Ot : d.y > Ot && (d.y = Ot);
1488
+ }
1489
+ const l = this.reheatDecay ?? this.params.alphaDecay;
1490
+ this.alpha = Math.max(this.alpha - l, 0), this.alpha <= this.params.alphaMin && (this.reheatDecay = null);
1491
+ }
1492
+ // Strong, bounded-duration kick. A bigger `alpha` rearranges the layout
1493
+ // further but settles in the same ~REHEAT_TICKS window (decay scales with the
1494
+ // kick) rather than lingering proportionally longer.
1495
+ reheat(t = 0.5) {
1496
+ this.alpha = t, this.reheatDecay = t / Lc;
1497
+ }
1498
+ // Raise alpha to at least `target` without ever cooling a hotter sim.
1499
+ // This is the physics primitive behind the control panel's "keep the
1500
+ // layout warm while tuning" hook: a parameter edit re-energises the
1501
+ // simulation just enough to show its effect, but a still-hot sim is
1502
+ // left alone so dragging a slider during settling doesn't dampen it.
1503
+ nudge(t = 0.3) {
1504
+ this.alpha < t && (this.alpha = t), this.reheatDecay = null;
1505
+ }
1506
+ isStable() {
1507
+ return this.alpha < this.params.alphaMin;
1508
+ }
1509
+ pinNode(t, n, s) {
1510
+ const o = this.nodeMap.get(t);
1511
+ o && (o.pinned = !0, o.x = n, o.y = s, o.vx = 0, o.vy = 0);
1512
+ }
1513
+ unpinNode(t) {
1514
+ const n = this.nodeMap.get(t);
1515
+ n && (n.pinned = !1);
1516
+ }
1517
+ setParams(t) {
1518
+ Object.assign(this.params, t), this.resolved = $s(this.params, this.taxonomy), this.frame = Cs(this, this.resolved), this.springByEdge = null;
1519
+ }
1520
+ classifyEdges() {
1521
+ const t = /* @__PURE__ */ new Map();
1522
+ for (const n of this.edges) {
1523
+ const s = this.nodeMap.get(n.sourceId), o = this.nodeMap.get(n.targetId);
1524
+ s && o && t.set(n.id, Bs(this.resolved.spring, n, s, o));
1525
+ }
1526
+ return t;
1527
+ }
1528
+ // Seed a node at a given position (used when new nodes appear during a
1529
+ // level-toggle transition): the point, snapped into the frame the forces act
1530
+ // in — both rest bands in cartesian, the bucket's ring in radial — so the
1531
+ // structure is honoured immediately.
1532
+ seedAt(t, n, s) {
1533
+ const o = this.nodeMap.get(t);
1534
+ if (!o) return;
1535
+ let i, r;
1536
+ if (this.params.radial) {
1537
+ const c = this.frame.ringOf(o), a = Math.atan2(s, n);
1538
+ i = c * Math.cos(a), r = c * Math.sin(a);
1539
+ } else {
1540
+ const c = this.axisBand(o, "x"), a = this.axisBand(o, "y");
1541
+ i = Math.min(Math.max(n, c.lo), c.hi), r = Math.min(Math.max(s, a.lo), a.hi);
1542
+ }
1543
+ o.x = i + (this.rng() - 0.5) * 10, o.y = r + (this.rng() - 0.5) * 10, o.vx = 0, o.vy = 0;
1544
+ }
1545
+ }
1546
+ const Dc = {
1547
+ baseMul: 0.6,
1548
+ minZoomMul: 0.4,
1549
+ maxZoomMul: 1.65
1550
+ };
1551
+ function vs(e, t) {
1552
+ return t.baseMul * Math.max(t.minZoomMul, Math.min(t.maxZoomMul, e));
1553
+ }
1554
+ function zn(e, t) {
1555
+ return { forces: e, nodeScale: t };
1556
+ }
1557
+ function ar(e) {
1558
+ return zn(ir(e), Dc);
1559
+ }
1560
+ const lr = [
1561
+ "pushMultiplier",
1562
+ "coreRadiusMultiplier",
1563
+ "chargeExponent",
1564
+ "pullMultiplier",
1565
+ "distanceMultiplier",
1566
+ "linkExponent",
1567
+ "gravityX",
1568
+ "gravityY",
1569
+ "gravityBandExp",
1570
+ "gravityTopological",
1571
+ "gravityTopologicalExp",
1572
+ "gravityCenter",
1573
+ "alphaDecay",
1574
+ "alphaMin",
1575
+ "velocityDecay"
1576
+ ], dr = ["radial", "topologicalEnabled"], _c = ["baseMul", "minZoomMul", "maxZoomMul"];
1577
+ function ur(e) {
1578
+ const t = (s) => Zt(s) ? { scalar: s.scalar, ...s.span ? { span: { ...s.span } } : {} } : { axis: s.mapping.axis, ...s.overrides.size > 0 ? { overrides: Object.fromEntries(s.overrides) } : {} }, n = {
1579
+ pair: {
1580
+ axis: e.pair.mapping.axis,
1581
+ ...e.pair.push.size > 0 ? { push: Object.fromEntries(e.pair.push) } : {},
1582
+ ...e.pair.spring.size > 0 ? { spring: Object.fromEntries(e.pair.spring) } : {}
1583
+ },
1584
+ bandX: t(e.bandX),
1585
+ bandY: t(e.bandY)
1586
+ };
1587
+ for (const s of lr) n[s] = e[s];
1588
+ for (const s of dr) n[s] = e[s];
1589
+ return n;
1590
+ }
1591
+ function Bc(e, t, n) {
1592
+ if (!je(e)) return;
1593
+ const s = { ...t };
1594
+ for (const o of lr) {
1595
+ const i = e[o];
1596
+ if (i !== void 0) {
1597
+ if (!yt(i)) return;
1598
+ s[o] = i;
1599
+ }
1600
+ }
1601
+ for (const o of dr) {
1602
+ const i = e[o];
1603
+ if (i !== void 0) {
1604
+ if (typeof i != "boolean") return;
1605
+ s[o] = i;
1606
+ }
1607
+ }
1608
+ if (e.pair !== void 0) {
1609
+ const o = zc(e.pair, n);
1610
+ if (!o) return;
1611
+ s.pair = o;
1612
+ }
1613
+ for (const o of ["bandX", "bandY"]) {
1614
+ if (e[o] === void 0) continue;
1615
+ const i = Vc(e[o], n);
1616
+ if (!i) return;
1617
+ s[o] = i;
1618
+ }
1619
+ return s;
1620
+ }
1621
+ function Hc(e, t) {
1622
+ if (!je(e)) return;
1623
+ const n = { ...t };
1624
+ for (const s of _c) {
1625
+ const o = e[s];
1626
+ if (o !== void 0) {
1627
+ if (!yt(o)) return;
1628
+ n[s] = o;
1629
+ }
1630
+ }
1631
+ return n;
1632
+ }
1633
+ function fr(e, t) {
1634
+ return t === e.styleAxis() ? Qt(e) : Vn(Vs(e, t), []);
1635
+ }
1636
+ function zc(e, t) {
1637
+ if (!je(e) || typeof e.axis != "string") return;
1638
+ const n = /* @__PURE__ */ new Map();
1639
+ if (e.push !== void 0) {
1640
+ if (!je(e.push)) return;
1641
+ for (const [o, i] of Object.entries(e.push)) {
1642
+ if (!je(i) || !yt(i.charge) || !yt(i.coreRadius)) return;
1643
+ n.set(o, { charge: i.charge, coreRadius: i.coreRadius });
1644
+ }
1645
+ }
1646
+ const s = /* @__PURE__ */ new Map();
1647
+ if (e.spring !== void 0) {
1648
+ if (!je(e.spring)) return;
1649
+ for (const [o, i] of Object.entries(e.spring)) {
1650
+ if (!je(i) || !yt(i.strength) || !yt(i.distance)) return;
1651
+ s.set(o, { strength: i.strength, distance: i.distance });
1652
+ }
1653
+ }
1654
+ return { mapping: fr(t, e.axis), push: n, spring: s };
1655
+ }
1656
+ function Vc(e, t) {
1657
+ if (!je(e)) return;
1658
+ if (typeof e.scalar == "string")
1659
+ return e.span === void 0 ? { scalar: e.scalar } : !je(e.span) || !yt(e.span.zero) || !yt(e.span.one) ? void 0 : { scalar: e.scalar, span: { zero: e.span.zero, one: e.span.one } };
1660
+ if (typeof e.axis != "string") return;
1661
+ const n = /* @__PURE__ */ new Map();
1662
+ if (e.overrides !== void 0) {
1663
+ if (!je(e.overrides)) return;
1664
+ for (const [s, o] of Object.entries(e.overrides)) {
1665
+ if (!je(o) || !yt(o.min) || !yt(o.max)) return;
1666
+ n.set(s, { min: o.min, max: o.max });
1667
+ }
1668
+ }
1669
+ return { mapping: fr(t, e.axis), overrides: n };
1670
+ }
1671
+ function Gc(e, t) {
1672
+ if (e === t) return !0;
1673
+ const n = (s) => {
1674
+ const o = s;
1675
+ return JSON.stringify([ur(o.forces), o.nodeScale]);
1676
+ };
1677
+ return n(e) === n(t);
1678
+ }
1679
+ const Xc = { x: 0, y: 0, scale: 1 }, Yc = 0.1, Jc = 40;
1680
+ function Ye(e, t, n) {
1681
+ return [t * e.scale + e.x, n * e.scale + e.y];
1682
+ }
1683
+ function ys(e, t, n) {
1684
+ return [(t - e.x) / e.scale, (n - e.y) / e.scale];
1685
+ }
1686
+ function As(e, t, n, s) {
1687
+ const o = Math.max(Yc, Math.min(Jc, e.scale * s)), i = (t - e.x) / e.scale, r = (n - e.y) / e.scale;
1688
+ return {
1689
+ scale: o,
1690
+ x: t - i * o,
1691
+ y: n - r * o
1692
+ };
1693
+ }
1694
+ function jc(e, t, n) {
1695
+ if (!(t != null && t.width) || !t.height || !n.width || !n.height) return e;
1696
+ const s = n.width - t.width, o = n.height - t.height;
1697
+ return s || o ? { ...e, x: e.x + s / 2, y: e.y + o / 2 } : e;
1698
+ }
1699
+ function hr(e, t, n, s = 60) {
1700
+ if (e.length === 0) return { x: t / 2, y: n / 2, scale: 1 };
1701
+ let o = 1 / 0, i = -1 / 0, r = 1 / 0, c = -1 / 0;
1702
+ for (const p of e)
1703
+ p.x < o && (o = p.x), p.x > i && (i = p.x), p.y < r && (r = p.y), p.y > c && (c = p.y);
1704
+ const a = i - o || 1, l = c - r || 1, d = t - s * 2, u = n - s * 2, v = Math.min(d / a, u / l, 2), M = (o + i) / 2, S = (r + c) / 2;
1705
+ return {
1706
+ scale: v,
1707
+ x: t / 2 - M * v,
1708
+ y: n / 2 - S * v
1709
+ };
1710
+ }
1711
+ function qc(e, t, n) {
1712
+ const s = (o) => {
1713
+ o.preventDefault();
1714
+ const i = e.getBoundingClientRect();
1715
+ n(As(t(), o.clientX - i.left, o.clientY - i.top, o.deltaY < 0 ? 1.15 : 0.85));
1716
+ };
1717
+ return e.addEventListener("wheel", s, { passive: !1 }), () => e.removeEventListener("wheel", s);
1718
+ }
1719
+ const Uc = "#4A90D9", Kc = "#FFFFFF", Wc = 0.2, Zc = 0.5, Qc = 16, ea = 0.42, ta = 0.16, na = 9, sa = 0.6;
1720
+ function So(e) {
1721
+ return 1 + Math.max(0, e - 1) * sa;
1722
+ }
1723
+ const oa = [6, 4], ra = 6, ia = 0.55, Gs = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', ca = 11, aa = 0.78, la = 15, da = 12;
1724
+ function ua(e) {
1725
+ return e.length > la ? e.slice(0, da) + "…" : e;
1726
+ }
1727
+ function fa(e) {
1728
+ return `600 ${e.toFixed(1)}px ${Gs}`;
1729
+ }
1730
+ const gr = 9, ha = 4, pr = 2, ga = 3, mr = 4, pa = "#7C3AED", ma = "#FFFFFF";
1731
+ function va(e) {
1732
+ return `600 ${e.toFixed(1)}px ${Gs}`;
1733
+ }
1734
+ function ya(e, t, n, s, o, i) {
1735
+ const r = Math.min(i, s / 2, o / 2);
1736
+ e.beginPath(), e.moveTo(t + r, n), e.arcTo(t + s, n, t + s, n + o, r), e.arcTo(t + s, n + o, t, n + o, r), e.arcTo(t, n + o, t, n, r), e.arcTo(t, n, t + s, n, r), e.closePath();
1737
+ }
1738
+ function ba(e, t) {
1739
+ if (!e.badges || e.badges.length === 0) return 0;
1740
+ const n = gr * t + pr * 2 * t;
1741
+ return mr * t + n;
1742
+ }
1743
+ function zt(e, t, n) {
1744
+ const s = e ?? (typeof document < "u" ? document.documentElement : null);
1745
+ return s && getComputedStyle(s).getPropertyValue(t).trim() || n;
1746
+ }
1747
+ const Fn = 8, Pe = 100, bs = 0.25, xs = 0.1;
1748
+ function ko(e, t, n, s, o, i) {
1749
+ if (!t) return [n, s, o, i];
1750
+ const r = e.sourceId < e.targetId, c = r ? o - n : n - o, a = r ? i - s : s - i, l = Math.hypot(c, a) || 1, d = -a / l * t, u = c / l * t;
1751
+ return [n + d, s + u, o + d, i + u];
1752
+ }
1753
+ function xa({
1754
+ nodes: e,
1755
+ edges: t,
1756
+ viewport: n,
1757
+ onViewportChange: s,
1758
+ onNodeDragStart: o,
1759
+ onNodeDragMove: i,
1760
+ onNodeDragEnd: r,
1761
+ onDoubleClickNode: c,
1762
+ onFitView: a,
1763
+ onHoverNode: l,
1764
+ onSelectNode: d,
1765
+ highlightedNodes: u,
1766
+ highlightedEdges: v,
1767
+ hoveredNodeId: M,
1768
+ selectedNodeId: S,
1769
+ focusedNodeId: p,
1770
+ searchMatchIds: $,
1771
+ running: D,
1772
+ forceParams: x,
1773
+ resolved: V,
1774
+ overlay: F,
1775
+ theme: L,
1776
+ edgeStrokes: y,
1777
+ edgeOffsets: I,
1778
+ activeSection: E,
1779
+ activePushBucket: O,
1780
+ activeGravityBucket: X,
1781
+ activePullEdge: N,
1782
+ nodeScale: k,
1783
+ groupGlows: w,
1784
+ markedEdges: R
1785
+ }) {
1786
+ const z = g.useRef(null), pe = g.useRef(null), [ke, St] = g.useState({ w: 0, h: 0 }), Ne = g.useRef(null), ct = g.useMemo(() => {
1787
+ const B = /* @__PURE__ */ new Map();
1788
+ for (const f of e) B.set(f.id, f);
1789
+ return B;
1790
+ }, [e]), at = g.useMemo(() => {
1791
+ const B = /* @__PURE__ */ new Map();
1792
+ for (const q of e) B.set(Vt(q), (B.get(Vt(q)) ?? 0) + 1);
1793
+ const f = /* @__PURE__ */ new Set();
1794
+ for (const q of e)
1795
+ (B.get(Vt(q)) ?? 0) > 1 && f.add(q.id);
1796
+ return f;
1797
+ }, [e]), lt = g.useMemo(() => {
1798
+ const B = M ?? S;
1799
+ if (!B) return null;
1800
+ const f = ct.get(B);
1801
+ return !f || !at.has(B) ? null : Vt(f);
1802
+ }, [M, S, ct, at]), Ie = Bt(), dt = g.useRef({
1803
+ taxonomy: Ie,
1804
+ nodes: e,
1805
+ edges: t,
1806
+ nodeMap: ct,
1807
+ viewport: n,
1808
+ groupGlows: w,
1809
+ markedEdges: R,
1810
+ highlightedNodes: u,
1811
+ highlightedEdges: v,
1812
+ hoveredNodeId: M,
1813
+ selectedNodeId: S,
1814
+ focusedNodeId: p,
1815
+ searchMatchIds: $,
1816
+ forceParams: x,
1817
+ resolved: V,
1818
+ overlay: F,
1819
+ theme: L,
1820
+ edgeStrokes: y,
1821
+ edgeOffsets: I,
1822
+ activeSection: E,
1823
+ activePushBucket: O,
1824
+ activeGravityBucket: X,
1825
+ activePullEdge: N,
1826
+ nodeScale: k,
1827
+ running: D,
1828
+ dupNodeIds: at,
1829
+ activeDupDefKey: lt
1830
+ });
1831
+ dt.current = {
1832
+ taxonomy: Ie,
1833
+ nodes: e,
1834
+ edges: t,
1835
+ nodeMap: ct,
1836
+ viewport: n,
1837
+ groupGlows: w,
1838
+ markedEdges: R,
1839
+ highlightedNodes: u,
1840
+ highlightedEdges: v,
1841
+ hoveredNodeId: M,
1842
+ selectedNodeId: S,
1843
+ focusedNodeId: p,
1844
+ searchMatchIds: $,
1845
+ forceParams: x,
1846
+ resolved: V,
1847
+ overlay: F,
1848
+ theme: L,
1849
+ edgeStrokes: y,
1850
+ edgeOffsets: I,
1851
+ activeSection: E,
1852
+ activePushBucket: O,
1853
+ activeGravityBucket: X,
1854
+ activePullEdge: N,
1855
+ nodeScale: k,
1856
+ running: D,
1857
+ dupNodeIds: at,
1858
+ activeDupDefKey: lt
1859
+ }, g.useEffect(() => {
1860
+ const B = pe.current;
1861
+ if (!B) return;
1862
+ const f = new ResizeObserver((q) => {
1863
+ const { width: te, height: le } = q[0].contentRect;
1864
+ St({ w: Math.floor(te), h: Math.floor(le) });
1865
+ });
1866
+ return f.observe(B), () => f.disconnect();
1867
+ }, []);
1868
+ const De = g.useCallback((B, f) => {
1869
+ const [q, te] = ys(n, B, f), le = vs(n.scale, k);
1870
+ for (let Ee = e.length - 1; Ee >= 0; Ee--) {
1871
+ const Me = e[Ee], Oe = (Ie.nodeStyleOf(Me).size.r * le + ba(Me, le)) / n.scale + 4;
1872
+ if ((q - Me.x) ** 2 + (te - Me.y) ** 2 <= Oe * Oe) return Me;
1873
+ }
1874
+ return null;
1875
+ }, [e, n, k, Ie]), ht = Te(n), b = Te(s);
1876
+ g.useEffect(() => {
1877
+ const B = z.current;
1878
+ if (B)
1879
+ return qc(B, () => ht.current, (f) => b.current(f));
1880
+ }, []);
1881
+ const T = g.useCallback((B) => {
1882
+ var Ee;
1883
+ const f = B.currentTarget.getBoundingClientRect(), q = B.clientX - f.left, te = B.clientY - f.top, le = De(q, te);
1884
+ if (le) {
1885
+ Ne.current = { type: "node", sx: q, sy: te, moved: !1 };
1886
+ const [Me, A] = ys(n, q, te);
1887
+ o(le.id, Me, A);
1888
+ } else
1889
+ Ne.current = { type: "pan", startVp: { ...n }, sx: q, sy: te, moved: !1 };
1890
+ (Ee = z.current) == null || Ee.setPointerCapture(B.pointerId);
1891
+ }, [n, De, o]), U = g.useCallback((B) => {
1892
+ const f = B.currentTarget.getBoundingClientRect(), q = B.clientX - f.left, te = B.clientY - f.top;
1893
+ if (!Ne.current) {
1894
+ const le = De(q, te);
1895
+ l((le == null ? void 0 : le.id) ?? null);
1896
+ return;
1897
+ }
1898
+ if (Ne.current.moved = !0, Ne.current.type === "pan" && Ne.current.startVp) {
1899
+ const le = q - Ne.current.sx, Ee = te - Ne.current.sy;
1900
+ s({
1901
+ ...Ne.current.startVp,
1902
+ x: Ne.current.startVp.x + le,
1903
+ y: Ne.current.startVp.y + Ee
1904
+ });
1905
+ } else if (Ne.current.type === "node") {
1906
+ const [le, Ee] = ys(n, q, te);
1907
+ i(le, Ee);
1908
+ }
1909
+ }, [n, De, s, i, l]), se = g.useCallback((B) => {
1910
+ var q;
1911
+ const f = Ne.current;
1912
+ if ((f == null ? void 0 : f.type) === "node") {
1913
+ if (r(), !f.moved) {
1914
+ const te = B.currentTarget.getBoundingClientRect(), le = B.clientX - te.left, Ee = B.clientY - te.top, Me = De(le, Ee);
1915
+ Me && d(Me.id);
1916
+ }
1917
+ } else (f == null ? void 0 : f.type) === "pan" && !f.moved && d(null);
1918
+ Ne.current = null, (q = z.current) == null || q.releasePointerCapture(B.pointerId);
1919
+ }, [r, d, De]), G = g.useCallback((B) => {
1920
+ const f = B.currentTarget.getBoundingClientRect(), q = B.clientX - f.left, te = B.clientY - f.top, le = De(q, te);
1921
+ le ? c(le.id) : a();
1922
+ }, [De, a, c]), oe = g.useRef(!0);
1923
+ return g.useEffect(() => {
1924
+ oe.current = !0;
1925
+ }), g.useEffect(() => {
1926
+ const B = z.current;
1927
+ if (!B || ke.w === 0) return;
1928
+ const f = B.getContext("2d");
1929
+ if (!f) return;
1930
+ const q = window.devicePixelRatio || 1;
1931
+ B.width = ke.w * q, B.height = ke.h * q;
1932
+ let te = 0, le = !0;
1933
+ const Ee = () => {
1934
+ var gt, tt;
1935
+ const A = dt.current, { w: Oe, h: xe } = ke, xt = A.highlightedNodes !== null && A.highlightedNodes.size > 0, Y = A.groupGlows.length > 0 ? Zc : Wc, re = zt(B, "--gv-color-graph-label", "#0f172a"), Qe = re.startsWith("#") && re.length === 7 ? re + "33" : "rgba(100,116,139,0.2)", Z = A.viewport, _e = vs(Z.scale, A.nodeScale);
1936
+ if (f.setTransform(q, 0, 0, q, 0, 0), f.clearRect(0, 0, Oe, xe), A.groupGlows.length > 0) {
1937
+ const _ = /* @__PURE__ */ new Map();
1938
+ for (const K of A.groupGlows)
1939
+ for (const H of K.nodeIds) _.set(H, { color: K.color, strength: K.strength });
1940
+ f.save(), f.lineCap = "round";
1941
+ for (const K of A.edges) {
1942
+ const H = _.get(K.sourceId), ne = _.get(K.targetId);
1943
+ if (!H || !ne || H.color !== ne.color) continue;
1944
+ const J = A.nodeMap.get(K.sourceId), Q = A.nodeMap.get(K.targetId);
1945
+ if (!J || !Q) continue;
1946
+ const [ie, ee] = Ye(Z, J.x, J.y), [W, ce] = Ye(Z, Q.x, Q.y);
1947
+ Math.max(ie, W) < -Pe || Math.min(ie, W) > Oe + Pe || Math.max(ee, ce) < -Pe || Math.min(ee, ce) > xe + Pe || (f.globalAlpha = Math.min(0.5, ta * H.strength), f.strokeStyle = H.color, f.lineWidth = na * So(H.strength), f.beginPath(), f.moveTo(ie, ee), f.lineTo(W, ce), f.stroke());
1948
+ }
1949
+ f.globalAlpha = 1;
1950
+ for (const [K, H] of _) {
1951
+ const ne = A.nodeMap.get(K);
1952
+ if (!ne) continue;
1953
+ const [J, Q] = Ye(Z, ne.x, ne.y), ie = A.taxonomy.nodeStyleOf(ne).size.r * _e + Qc * So(H.strength);
1954
+ if (J + ie < 0 || J - ie > Oe || Q + ie < 0 || Q - ie > xe) continue;
1955
+ const ee = Math.min(0.92, ea * H.strength), W = f.createRadialGradient(J, Q, 0, J, Q, ie);
1956
+ W.addColorStop(0, fs(H.color, ee)), W.addColorStop(0.6, fs(H.color, ee * 0.5)), W.addColorStop(1, fs(H.color, 0)), f.fillStyle = W, f.beginPath(), f.arc(J, Q, ie, 0, Math.PI * 2), f.fill();
1957
+ }
1958
+ f.restore(), f.globalAlpha = 1;
1959
+ }
1960
+ for (const _ of A.edges) {
1961
+ const K = A.nodeMap.get(_.sourceId), H = A.nodeMap.get(_.targetId);
1962
+ if (!K || !H) continue;
1963
+ const [ne, J] = Ye(Z, K.x, K.y), [Q, ie] = Ye(Z, H.x, H.y), [ee, W, ce, $e] = ko(_, A.edgeOffsets.get(_.id) ?? 0, ne, J, Q, ie);
1964
+ if (Math.max(ee, ce) < -Pe || Math.min(ee, ce) > Oe + Pe || Math.max(W, $e) < -Pe || Math.min(W, $e) > xe + Pe) continue;
1965
+ const Re = ((gt = A.highlightedEdges) == null ? void 0 : gt.has(_.id)) ?? !1, de = A.edgeStrokes.get(_) ?? wn, he = de.alpha, ge = A.searchMatchIds !== null && (!A.searchMatchIds.has(_.sourceId) || !A.searchMatchIds.has(_.targetId)), ue = xt ? !Re : ge, we = xt && Re ? 1 : ue ? Y : he;
1966
+ if (A.markedEdges.has(_.id) && (f.globalAlpha = ue ? Y : ia, f.beginPath(), f.setLineDash(oa), f.strokeStyle = re, f.lineWidth = ra, f.moveTo(ee, W), f.lineTo(ce, $e), f.stroke()), f.globalAlpha = we, f.beginPath(), f.setLineDash([...de.dash]), f.strokeStyle = de.color[A.theme], f.lineWidth = de.width, f.moveTo(ee, W), f.lineTo(ce, $e), f.stroke(), f.setLineDash([]), !it(_)) {
1967
+ const be = Math.atan2($e - W, ce - ee), Fe = A.taxonomy.nodeStyleOf(H).size.r * vs(Z.scale, A.nodeScale) + 2, He = ce - Math.cos(be) * Fe, ae = $e - Math.sin(be) * Fe;
1968
+ f.beginPath(), f.moveTo(He, ae), f.lineTo(
1969
+ He - Fn * Math.cos(be - Math.PI / 6),
1970
+ ae - Fn * Math.sin(be - Math.PI / 6)
1971
+ ), f.lineTo(
1972
+ He - Fn * Math.cos(be + Math.PI / 6),
1973
+ ae - Fn * Math.sin(be + Math.PI / 6)
1974
+ ), f.closePath(), f.fillStyle = de.color[A.theme], f.fill();
1975
+ }
1976
+ f.globalAlpha = 1;
1977
+ }
1978
+ const Be = A.activeSection === "push", rn = A.activeSection === "pull", kt = A.activeSection === "gravity", et = [0.2, 0.5, 1.5];
1979
+ if (Be) {
1980
+ const _ = A.forceParams.chargeExponent, K = A.forceParams.pushMultiplier, H = A.forceParams.coreRadiusMultiplier, ne = A.activePushBucket;
1981
+ for (const J of A.nodes) {
1982
+ const [Q, ie] = Ye(Z, J.x, J.y), ee = 2e3;
1983
+ if (Q + ee < 0 || Q - ee > Oe || ie + ee < 0 || ie - ee > xe) continue;
1984
+ const W = ne === null || Dt(A.resolved.push, J) === ne, ce = W ? 0.28 : 0.05, $e = W ? 0.06 : 0.015, Re = A.taxonomy.nodeStyleOf(J).color[A.theme].fill;
1985
+ f.strokeStyle = Re;
1986
+ const de = Math.abs(Qo(A.resolved.push, J)) * K;
1987
+ if (de <= 0) continue;
1988
+ const he = H * er(A.resolved.push, J), ge = he * he, ue = [];
1989
+ for (let we = 0; we < et.length; we++) {
1990
+ const be = et[we], fe = de / be, Fe = Math.pow(fe, 1 / Math.max(_, 0.01)) - ge;
1991
+ if (Fe <= 0) continue;
1992
+ const ae = Math.sqrt(Fe) * Z.scale;
1993
+ ae < 2 || ae > 2e3 || ue.push(ae);
1994
+ }
1995
+ if (ue.length !== 0) {
1996
+ f.strokeStyle = Re;
1997
+ for (let we = 0; we < ue.length; we++) {
1998
+ const be = ue[we], fe = ue.length - 1 - we;
1999
+ f.beginPath(), f.arc(Q, ie, be, 0, Math.PI * 2), f.globalAlpha = ce + fe * $e, f.lineWidth = W ? 1.5 : 1, f.stroke();
2000
+ }
2001
+ }
2002
+ }
2003
+ f.globalAlpha = 1;
2004
+ }
2005
+ const Ve = A.activePullEdge;
2006
+ if (rn || Ve) {
2007
+ const _ = A.forceParams.distanceMultiplier, K = zt(B, "--gv-tension-stretch", "#d97706"), H = zt(B, "--gv-tension-compress", "#7CB9E8"), ne = zt(B, "--gv-tension-rest", "#7EC8B8");
2008
+ for (const J of A.edges) {
2009
+ const Q = A.nodeMap.get(J.sourceId), ie = A.nodeMap.get(J.targetId);
2010
+ if (!Q || !ie) continue;
2011
+ const ee = Bs(A.resolved.spring, J, Q, ie);
2012
+ if (Ve && ee.key !== Ve) continue;
2013
+ const [W, ce] = Ye(Z, Q.x, Q.y), [$e, Re] = Ye(Z, ie.x, ie.y), [de, he, ge, ue] = ko(J, A.edgeOffsets.get(J.id) ?? 0, W, ce, $e, Re);
2014
+ if (Math.max(de, ge) < -Pe || Math.min(de, ge) > Oe + Pe || Math.max(he, ue) < -Pe || Math.min(he, ue) > xe + Pe) continue;
2015
+ const we = ee.distance * _, be = ie.x - Q.x, fe = ie.y - Q.y, He = Math.sqrt(be * be + fe * fe) / Math.max(we, 0.1);
2016
+ let ae;
2017
+ if (He > 1.15 ? ae = K : He < 0.85 ? ae = H : ae = ne, Ve) {
2018
+ const Ge = A.edgeStrokes.get(J) ?? wn;
2019
+ f.beginPath(), f.moveTo(de, he), f.lineTo(ge, ue), f.strokeStyle = ae, f.globalAlpha = 0.9, f.lineWidth = Ge.width + 5, f.setLineDash([]), f.stroke(), f.beginPath(), f.moveTo(de, he), f.lineTo(ge, ue), f.strokeStyle = Ge.color[A.theme], f.globalAlpha = 1, f.lineWidth = Ge.width, f.setLineDash([...Ge.dash]), f.stroke(), f.setLineDash([]);
2020
+ continue;
2021
+ }
2022
+ f.beginPath(), f.moveTo(de, he), f.lineTo(ge, ue), f.strokeStyle = ae, f.globalAlpha = 0.5, f.lineWidth = 3, f.setLineDash([]), f.stroke();
2023
+ const Ce = Math.atan2(fe, be), Ke = -Math.sin(Ce), Xt = Math.cos(Ce), We = 5, pt = we * Z.scale;
2024
+ if (pt > 10 && pt < Math.sqrt((ge - de) ** 2 + (ue - he) ** 2) * 2) {
2025
+ const Ge = de + Math.cos(Ce) * pt, kn = he + Math.sin(Ce) * pt;
2026
+ f.beginPath(), f.moveTo(Ge - Ke * We, kn - Xt * We), f.lineTo(Ge + Ke * We, kn + Xt * We), f.strokeStyle = ne, f.globalAlpha = 0.7, f.lineWidth = 1.5, f.stroke();
2027
+ const Xe = ge - Math.cos(Ce) * pt, Nn = ue - Math.sin(Ce) * pt;
2028
+ f.beginPath(), f.moveTo(Xe - Ke * We, Nn - Xt * We), f.lineTo(Xe + Ke * We, Nn + Xt * We), f.stroke();
2029
+ }
2030
+ }
2031
+ f.globalAlpha = 1, f.setLineDash([]);
2032
+ }
2033
+ if (kt && A.overlay.acting) {
2034
+ const _ = A.activeGravityBucket, K = (J) => (J !== void 0 ? A.overlay.colors.get(J) : void 0) ?? zt(B, "--gv-color-text-muted", "#94A3B8"), H = (J) => _ !== null && _.axis === J && (J === "y" && A.overlay.rings.length > 0 ? A.overlay.rings.some((Q) => Q.buckets.includes(_.bucket)) : (J === "x" ? A.overlay.x : A.overlay.y).some((Q) => Q.buckets.includes(_.bucket)));
2035
+ if (A.overlay.rings.length > 0) {
2036
+ const [J, Q] = Ye(Z, 0, 0), ie = H("y");
2037
+ for (const ee of A.overlay.rings) {
2038
+ const W = ie && _ !== null && ee.buckets.includes(_.bucket), ce = ie && !W;
2039
+ f.strokeStyle = K(ee.buckets[0]), f.globalAlpha = W ? 0.6 : ce ? 0.1 : 0.28, f.lineWidth = W ? 1.5 : 1, f.setLineDash([]), f.beginPath(), f.arc(J, Q, ee.radius * Z.scale, 0, Math.PI * 2), f.stroke();
2040
+ }
2041
+ }
2042
+ const ne = (J) => {
2043
+ const Q = J === "x" ? A.overlay.x : A.overlay.y, ie = H(J), ee = (W) => J === "y" ? Ye(Z, 0, W)[1] : Ye(Z, W, 0)[0];
2044
+ for (const { lo: W, hi: ce, buckets: $e, gradient: Re } of Q) {
2045
+ const de = ee(W), he = ee(ce);
2046
+ if (he < 0 || de > (J === "y" ? xe : Oe)) continue;
2047
+ const ge = ie && _ !== null && $e.includes(_.bucket), ue = ie && !ge, we = K($e[0]);
2048
+ if (Re) {
2049
+ const be = ee(Re.zero), fe = ee(Re.one), Fe = J === "y" ? f.createLinearGradient(0, be, 0, fe) : f.createLinearGradient(be, 0, fe, 0);
2050
+ Fe.addColorStop(0, zt(B, "--gv-color-text-muted", "#94A3B8")), Fe.addColorStop(1, zt(B, "--gv-color-text", "#1E293B")), f.fillStyle = Fe, f.globalAlpha = 0.12;
2051
+ } else
2052
+ f.fillStyle = we, f.globalAlpha = ge ? 0.2 : ue ? 0.04 : 0.1;
2053
+ J === "y" ? f.fillRect(0, de, Oe, he - de) : f.fillRect(de, 0, he - de, xe), f.strokeStyle = we, f.globalAlpha = ge ? 0.55 : ue ? 0.08 : 0.22, f.lineWidth = ge ? 1.5 : 1, f.setLineDash([]), f.beginPath(), J === "y" ? (f.moveTo(0, de), f.lineTo(Oe, de), f.moveTo(0, he), f.lineTo(Oe, he)) : (f.moveTo(de, 0), f.lineTo(de, xe), f.moveTo(he, 0), f.lineTo(he, xe)), f.stroke();
2054
+ }
2055
+ };
2056
+ ne("y"), ne("x"), f.globalAlpha = 1;
2057
+ }
2058
+ f.textAlign = "center", f.textBaseline = "middle";
2059
+ const ye = [], Ue = A.nodes.map((_) => {
2060
+ const [K, H] = Ye(Z, _.x, _.y);
2061
+ return { x: K, y: H, r: A.taxonomy.nodeStyleOf(_).size.r * _e };
2062
+ });
2063
+ for (const _ of A.nodes) {
2064
+ const [K, H] = Ye(Z, _.x, _.y), ne = A.taxonomy.nodeStyleOf(_), J = ne.size.r * _e, Q = J;
2065
+ if (K + Q < -Pe || K - Q > Oe + Pe || H + Q < -Pe || H - Q > xe + Pe) continue;
2066
+ const ie = ((tt = A.highlightedNodes) == null ? void 0 : tt.has(_.id)) ?? !1, ee = A.searchMatchIds !== null && !A.searchMatchIds.has(_.id), W = xt && !ie || ee;
2067
+ f.globalAlpha = W ? Y : 1;
2068
+ const { fill: ce, border: $e } = ne.color[A.theme], Re = ne.icon;
2069
+ f.beginPath(), f.arc(K, H, J, 0, Math.PI * 2), f.fillStyle = ce, f.fill(), f.lineWidth = Math.max(1, Math.min(2, Z.scale * 1.25)), f.strokeStyle = $e, f.stroke(), Z.scale >= bs && Re && (f.save(), f.font = `${ne.size.iconSize * _e}px ${Gs}`, f.fillStyle = "#FFFFFF", f.globalAlpha = (W ? Y : 1) * 0.92, f.fillText(Re, K, H + 0.5), f.restore()), _.ring === "dashed" && Z.scale >= xs && (f.save(), f.setLineDash([3, 3]), f.strokeStyle = ce, f.lineWidth = 1.5, f.beginPath(), f.arc(K, H, J + 4, 0, Math.PI * 2), f.stroke(), f.restore());
2070
+ const de = A.activeDupDefKey !== null && Vt(_) === A.activeDupDefKey && Z.scale >= xs;
2071
+ if (de && (f.save(), f.strokeStyle = ce, f.lineWidth = 2, f.setLineDash([]), f.globalAlpha = 0.55, f.beginPath(), f.arc(K, H, J + 5, 0, Math.PI * 2), f.stroke(), f.restore()), _.id === A.selectedNodeId) {
2072
+ const ge = de ? J + 10 : J + 5;
2073
+ f.save(), f.strokeStyle = Kc, f.lineWidth = 2.5, f.setLineDash([]), f.beginPath(), f.arc(K, H, ge, 0, Math.PI * 2), f.stroke(), f.restore();
2074
+ }
2075
+ if (_.id === A.focusedNodeId && Z.scale >= xs && (f.save(), f.strokeStyle = Uc, f.lineWidth = 2, f.setLineDash([2, 2]), f.beginPath(), f.arc(K, H, J + 9, 0, Math.PI * 2), f.stroke(), f.restore()), f.globalAlpha = 1, _.badges && _.badges.length > 0 && Z.scale >= bs) {
2076
+ const ge = gr * _e, ue = ge + pr * 2 * _e, we = ha * _e, be = ga * _e;
2077
+ f.save(), f.font = va(ge), f.textAlign = "center", f.textBaseline = "middle";
2078
+ const fe = _.badges.map((Ce) => {
2079
+ const Ke = Ce;
2080
+ return { text: Ke, w: f.measureText(Ke).width + we * 2 };
2081
+ }), Fe = fe.reduce((Ce, Ke) => Ce + Ke.w, 0) + be * (fe.length - 1), He = H - J - mr * _e - ue;
2082
+ let ae = K - Fe / 2;
2083
+ f.globalAlpha = W ? Y : 1;
2084
+ for (const Ce of fe)
2085
+ ya(f, ae, He, Ce.w, ue, ue / 2), f.fillStyle = pa, f.fill(), f.fillStyle = ma, f.fillText(Ce.text, ae + Ce.w / 2, He + ue / 2 + 0.5), ae += Ce.w + be;
2086
+ f.restore(), f.globalAlpha = 1;
2087
+ }
2088
+ const he = _.id === A.hoveredNodeId || _.id === A.selectedNodeId;
2089
+ if (Z.scale >= bs || he) {
2090
+ const ge = ca * (he ? Math.max(_e, 1) : _e), ue = H + J + 4 + ge * 0.7;
2091
+ f.font = fa(ge);
2092
+ const we = ua(_.name), be = f.measureText(we).width, fe = { x: K - be / 2 - 2, y: ue - ge / 2 - 1, w: be + 4, h: ge + 2 }, Fe = ye.some((ae) => fe.x < ae.x + ae.w && fe.x + fe.w > ae.x && fe.y < ae.y + ae.h && fe.y + fe.h > ae.y), He = !Fe && Ue.some((ae) => {
2093
+ const Ce = Math.max(fe.x, Math.min(ae.x, fe.x + fe.w)), Ke = Math.max(fe.y, Math.min(ae.y, fe.y + fe.h));
2094
+ return (ae.x - Ce) ** 2 + (ae.y - Ke) ** 2 < ae.r * ae.r;
2095
+ });
2096
+ (he || !Fe && !He) && (ye.push(fe), f.globalAlpha = W ? 1 : aa, f.fillStyle = W ? Qe : re, f.fillText(we, K, ue), f.globalAlpha = 1);
2097
+ }
2098
+ }
2099
+ }, Me = () => {
2100
+ if (!le) return;
2101
+ (dt.current.running || oe.current) && (oe.current = !1, Ee()), te = requestAnimationFrame(Me);
2102
+ };
2103
+ return te = requestAnimationFrame(Me), () => {
2104
+ le = !1, cancelAnimationFrame(te);
2105
+ };
2106
+ }, [ke]), /* @__PURE__ */ h("div", { ref: pe, className: "gv-graph-canvas-container", children: /* @__PURE__ */ h(
2107
+ "canvas",
2108
+ {
2109
+ ref: z,
2110
+ style: { width: ke.w, height: ke.h },
2111
+ onPointerDown: T,
2112
+ onPointerMove: U,
2113
+ onPointerUp: se,
2114
+ onDoubleClick: G
2115
+ }
2116
+ ) });
2117
+ }
2118
+ class No extends g.Component {
2119
+ constructor(t) {
2120
+ super(t), this.state = { error: null };
2121
+ }
2122
+ static getDerivedStateFromError(t) {
2123
+ return { error: t };
2124
+ }
2125
+ componentDidCatch(t, n) {
2126
+ console.error(`${this.props.what ?? "graph canvas"} render/draw error:`, t, n.componentStack);
2127
+ }
2128
+ render() {
2129
+ return this.state.error ? /* @__PURE__ */ C("div", { className: "gv-graph-canvas-error", role: "alert", children: [
2130
+ /* @__PURE__ */ C("p", { children: [
2131
+ "The ",
2132
+ this.props.what ?? "graph canvas",
2133
+ " failed to render."
2134
+ ] }),
2135
+ /* @__PURE__ */ h("p", { className: "gv-graph-canvas-error-detail", children: this.state.error.message })
2136
+ ] }) : this.props.children;
2137
+ }
2138
+ }
2139
+ const wa = "var(--gv-color-text-muted)";
2140
+ function en(e, t, n) {
2141
+ return t.axis === e.styleAxis() && Fs(t) ? `var(${e.colorVar(n)})` : wa;
2142
+ }
2143
+ function Xs({
2144
+ yLabel: e,
2145
+ ySlider: t,
2146
+ bottom: n,
2147
+ children: s
2148
+ }) {
2149
+ return /* @__PURE__ */ C("div", { className: "gv-ctl-plot", children: [
2150
+ e !== void 0 && /* @__PURE__ */ h("div", { className: "gv-ctl-plot-ylabel", children: e }),
2151
+ t !== void 0 && /* @__PURE__ */ h("div", { className: "gv-ctl-plot-yslider", children: t }),
2152
+ /* @__PURE__ */ h("div", { className: "gv-ctl-plot-main", children: s }),
2153
+ n !== void 0 && /* @__PURE__ */ h("div", { className: "gv-ctl-plot-bottom", children: n })
2154
+ ] });
2155
+ }
2156
+ const vr = g.createContext({ popped: null, setPopped: () => {
2157
+ } });
2158
+ function Ma({ children: e }) {
2159
+ const [t, n] = g.useState(null), s = g.useMemo(() => ({ popped: t, setPopped: n }), [t]);
2160
+ return /* @__PURE__ */ h(vr.Provider, { value: s, children: e });
2161
+ }
2162
+ function yr() {
2163
+ return g.useContext(vr);
2164
+ }
2165
+ function rt({ id: e, children: t }) {
2166
+ const { popped: n, setPopped: s } = yr();
2167
+ return /* @__PURE__ */ h(
2168
+ "span",
2169
+ {
2170
+ className: `gv-ctl-formula-value${n === e ? " active" : ""}`,
2171
+ onMouseEnter: () => s(e),
2172
+ onMouseLeave: () => s(null),
2173
+ children: t
2174
+ }
2175
+ );
2176
+ }
2177
+ function _t({
2178
+ value: e,
2179
+ min: t,
2180
+ max: n,
2181
+ step: s,
2182
+ onChange: o,
2183
+ orientation: i = "horizontal",
2184
+ title: r,
2185
+ ariaLabel: c,
2186
+ className: a,
2187
+ popId: l
2188
+ }) {
2189
+ const { popped: d } = yr(), v = `gv-ctl-slider gv-ctl-slider-${i === "vertical" ? "v" : "h"}` + (l !== void 0 && d === l ? " gv-ctl-slider-popped" : "") + (a ? " " + a : "");
2190
+ return /* @__PURE__ */ h(
2191
+ "input",
2192
+ {
2193
+ type: "range",
2194
+ className: v,
2195
+ min: t,
2196
+ max: n,
2197
+ step: s,
2198
+ value: e,
2199
+ onChange: (M) => o(Number(M.target.value)),
2200
+ title: r,
2201
+ "aria-label": c,
2202
+ "data-pop-id": l
2203
+ }
2204
+ );
2205
+ }
2206
+ const Os = (e, t, n) => Math.max(t, Math.min(n, e)), Eo = (e, t) => Math.round(e / t) * t, jt = 300, Rt = 200, qt = 12, Io = jt - 2 * qt, $o = Rt - 2 * qt, Je = 7;
2207
+ function br({
2208
+ tokens: e,
2209
+ xAxis: t,
2210
+ yAxis: n,
2211
+ onDrag: s,
2212
+ hoveredId: o,
2213
+ onHover: i,
2214
+ xSlider: r,
2215
+ ySlider: c,
2216
+ ariaLabel: a
2217
+ }) {
2218
+ const l = g.useRef(null), d = g.useRef(null), u = (y) => qt + (y - t.min) / (t.max - t.min) * Io, v = (y) => Rt - qt - (y - n.min) / (n.max - n.min) * $o, M = (y) => t.min + (y - qt) / Io * (t.max - t.min), S = (y) => n.min + (Rt - qt - y) / $o * (n.max - n.min), p = (y) => {
2219
+ const I = l.current;
2220
+ if (!I) return { x: 0, y: 0 };
2221
+ const E = I.createSVGPoint();
2222
+ E.x = y.clientX, E.y = y.clientY;
2223
+ const O = I.getScreenCTM();
2224
+ if (!O) return { x: 0, y: 0 };
2225
+ const X = E.matrixTransform(O.inverse());
2226
+ return { x: X.x, y: X.y };
2227
+ }, $ = (y, I) => {
2228
+ y.preventDefault(), y.currentTarget.setPointerCapture(y.pointerId), d.current = I;
2229
+ }, D = (y) => {
2230
+ const I = d.current;
2231
+ if (!I) return;
2232
+ const { x: E, y: O } = p(y), X = Os(Eo(M(E), t.step), t.min, t.max), N = Os(Eo(S(O), n.step), n.min, n.max);
2233
+ s(I, X, N);
2234
+ }, x = (y) => {
2235
+ var I, E;
2236
+ d.current = null, (E = (I = y.currentTarget).releasePointerCapture) == null || E.call(I, y.pointerId);
2237
+ }, V = [0, jt / 2, jt], F = [0, Rt / 2, Rt], L = Sa(e.map((y) => ({ cx: u(y.x), cy: v(y.y) })));
2238
+ return /* @__PURE__ */ h(
2239
+ Xs,
2240
+ {
2241
+ yLabel: n.label,
2242
+ ySlider: /* @__PURE__ */ h(
2243
+ _t,
2244
+ {
2245
+ orientation: "vertical",
2246
+ min: c.min,
2247
+ max: c.max,
2248
+ step: c.step,
2249
+ value: c.value,
2250
+ onChange: c.onChange,
2251
+ title: c.title,
2252
+ ariaLabel: c.ariaLabel,
2253
+ popId: c.popId
2254
+ }
2255
+ ),
2256
+ bottom: /* @__PURE__ */ C(yn, { children: [
2257
+ /* @__PURE__ */ h(
2258
+ _t,
2259
+ {
2260
+ min: r.min,
2261
+ max: r.max,
2262
+ step: r.step,
2263
+ value: r.value,
2264
+ onChange: r.onChange,
2265
+ title: r.title,
2266
+ ariaLabel: r.ariaLabel,
2267
+ popId: r.popId
2268
+ }
2269
+ ),
2270
+ /* @__PURE__ */ h("div", { className: "gv-ctl-plot-xlabel", children: t.label })
2271
+ ] }),
2272
+ children: /* @__PURE__ */ C(
2273
+ "svg",
2274
+ {
2275
+ ref: l,
2276
+ className: "gv-spring-map-svg",
2277
+ viewBox: `0 0 ${jt} ${Rt}`,
2278
+ role: "group",
2279
+ "aria-label": a,
2280
+ children: [
2281
+ /* @__PURE__ */ h("rect", { x: 0, y: 0, width: jt, height: Rt, className: "gv-spring-plot-bg" }),
2282
+ V.map((y) => /* @__PURE__ */ h("line", { x1: y, y1: 0, x2: y, y2: Rt, className: "gv-spring-grid" }, `gx${y}`)),
2283
+ F.map((y) => /* @__PURE__ */ h("line", { x1: 0, y1: y, x2: jt, y2: y, className: "gv-spring-grid" }, `gy${y}`)),
2284
+ e.map((y, I) => {
2285
+ const { cx: E, cy: O } = L[I], X = o !== null && o !== y.id, N = o === y.id;
2286
+ return /* @__PURE__ */ C(
2287
+ "g",
2288
+ {
2289
+ transform: `translate(${E} ${O})`,
2290
+ className: `gv-spring-token${X ? " dim" : ""}${N ? " active" : ""}`,
2291
+ onPointerDown: (k) => $(k, y.id),
2292
+ onPointerMove: D,
2293
+ onPointerUp: x,
2294
+ onPointerEnter: () => i(y.id),
2295
+ onPointerLeave: () => {
2296
+ d.current || i(null);
2297
+ },
2298
+ children: [
2299
+ y.tooltip && /* @__PURE__ */ h("title", { children: y.tooltip }),
2300
+ y.colorB === void 0 ? /* @__PURE__ */ h("circle", { r: Je, fill: y.colorA }) : /* @__PURE__ */ C(yn, { children: [
2301
+ /* @__PURE__ */ h("path", { d: `M0,${-Je} A${Je},${Je} 0 0 0 0,${Je} Z`, fill: y.colorA }),
2302
+ /* @__PURE__ */ h("path", { d: `M0,${-Je} A${Je},${Je} 0 0 1 0,${Je} Z`, fill: y.colorB })
2303
+ ] }),
2304
+ /* @__PURE__ */ h(
2305
+ "circle",
2306
+ {
2307
+ r: Je,
2308
+ fill: "none",
2309
+ className: "gv-spring-token-outline",
2310
+ strokeDasharray: y.outline === "dashed" ? "2 2" : void 0
2311
+ }
2312
+ ),
2313
+ /* @__PURE__ */ h("text", { y: Je + 11, textAnchor: "middle", className: "gv-spring-token-label", children: y.label })
2314
+ ]
2315
+ },
2316
+ y.id
2317
+ );
2318
+ })
2319
+ ]
2320
+ }
2321
+ )
2322
+ }
2323
+ );
2324
+ }
2325
+ function Sa(e) {
2326
+ const t = [];
2327
+ e.forEach((s, o) => {
2328
+ const i = t.find((r) => Math.hypot(r.cx - s.cx, r.cy - s.cy) < Je);
2329
+ i ? i.members.push(o) : t.push({ cx: s.cx, cy: s.cy, members: [o] });
2330
+ });
2331
+ const n = e.map((s) => ({ cx: s.cx, cy: s.cy }));
2332
+ for (const s of t) {
2333
+ if (s.members.length === 1) continue;
2334
+ const o = Math.max(Je * 1.6, s.members.length * Je / Math.PI);
2335
+ s.members.forEach((i, r) => {
2336
+ const c = -Math.PI / 2 + 2 * Math.PI * r / s.members.length;
2337
+ n[i] = { cx: s.cx + o * Math.cos(c), cy: s.cy + o * Math.sin(c) };
2338
+ });
2339
+ }
2340
+ return n;
2341
+ }
2342
+ const Tt = 300, ot = 130, tn = 56;
2343
+ function ka(e) {
2344
+ var s;
2345
+ const t = e.trim().split(/\s+/), n = (s = t[t.length - 1]) == null ? void 0 : s.split(",");
2346
+ return !n || n.length < 2 ? null : { x: Number(n[0]), y: Number(n[1]) };
2347
+ }
2348
+ function Na(e, t) {
2349
+ if (!(e > 0)) return 1;
2350
+ const n = e / t, s = Math.pow(10, Math.floor(Math.log10(n))), o = n / s;
2351
+ return (o < 1.5 ? 1 : o < 3 ? 2 : o < 7 ? 5 : 10) * s;
2352
+ }
2353
+ function Ys({
2354
+ curves: e,
2355
+ baselineY: t,
2356
+ hoveredId: n,
2357
+ onHover: s,
2358
+ xLabel: o,
2359
+ yLabel: i,
2360
+ exp: r,
2361
+ ariaLabel: c,
2362
+ xMax: a
2363
+ }) {
2364
+ const l = [];
2365
+ if (a !== void 0 && a > 0) {
2366
+ const d = Na(a, 6);
2367
+ for (let u = d; u < a * 0.999; u += d) l.push(u / a * Tt);
2368
+ }
2369
+ return /* @__PURE__ */ C("div", { className: "gv-spring-curves", children: [
2370
+ /* @__PURE__ */ h("div", { className: "gv-spring-axis-label gv-spring-curves-axis-y", children: i }),
2371
+ /* @__PURE__ */ C(
2372
+ "svg",
2373
+ {
2374
+ className: "gv-spring-curves-svg",
2375
+ viewBox: `0 0 ${Tt} ${ot}`,
2376
+ role: "img",
2377
+ "aria-label": c,
2378
+ children: [
2379
+ /* @__PURE__ */ h("rect", { x: 0, y: 0, width: Tt, height: ot, className: "gv-spring-curve-frame" }),
2380
+ l.map((d, u) => /* @__PURE__ */ h("line", { x1: d.toFixed(1), y1: 0, x2: d.toFixed(1), y2: ot, className: "gv-ctl-grid-line" }, `g${u}`)),
2381
+ t !== void 0 && /* @__PURE__ */ h("line", { x1: 0, y1: t, x2: Tt, y2: t, className: "gv-spring-curve-baseline" }),
2382
+ e.filter((d) => d.id === n && d.markerX !== void 0).map((d) => /* @__PURE__ */ h("line", { x1: d.markerX, y1: 0, x2: d.markerX, y2: ot, className: "gv-spring-curve-restmark" }, `m${d.id}`)),
2383
+ e.map((d) => {
2384
+ const u = n !== null && n !== d.id, v = n === d.id;
2385
+ return /* @__PURE__ */ C("g", { className: `gv-spring-curve${u ? " dim" : ""}${v ? " active" : ""}`, children: [
2386
+ /* @__PURE__ */ h(
2387
+ "polyline",
2388
+ {
2389
+ points: d.points,
2390
+ className: "gv-spring-curve-hit",
2391
+ onPointerEnter: () => s(d.id),
2392
+ onPointerLeave: () => s(null)
2393
+ }
2394
+ ),
2395
+ /* @__PURE__ */ h(
2396
+ "polyline",
2397
+ {
2398
+ points: d.points,
2399
+ className: "gv-spring-curve-line",
2400
+ style: { stroke: d.color }
2401
+ }
2402
+ ),
2403
+ d.label && (() => {
2404
+ const M = ka(d.points);
2405
+ return M ? /* @__PURE__ */ h(
2406
+ "text",
2407
+ {
2408
+ x: Math.min(M.x + 4, Tt - 2),
2409
+ y: Os(M.y, 9, ot - 2),
2410
+ className: "gv-spring-curve-label",
2411
+ style: { fill: d.color },
2412
+ textAnchor: "end",
2413
+ children: d.label
2414
+ }
2415
+ ) : null;
2416
+ })()
2417
+ ] }, d.id);
2418
+ })
2419
+ ]
2420
+ }
2421
+ ),
2422
+ /* @__PURE__ */ h("div", { className: "gv-spring-axis-label gv-spring-curves-axis-x", children: o }),
2423
+ /* @__PURE__ */ C("div", { className: "gv-spring-curves-exp", title: r.title, children: [
2424
+ /* @__PURE__ */ h("span", { className: "gv-spring-exp-label", children: r.label ?? "exp" }),
2425
+ /* @__PURE__ */ h(
2426
+ _t,
2427
+ {
2428
+ min: r.min,
2429
+ max: r.max,
2430
+ step: r.step,
2431
+ value: r.value,
2432
+ onChange: r.onChange,
2433
+ popId: r.popId
2434
+ }
2435
+ )
2436
+ ] })
2437
+ ] });
2438
+ }
2439
+ const Ea = 0, Ia = 1e3, $a = 10, Ca = 0, Aa = 100, Oa = 1, Ra = (e, t, n) => Math.max(t, Math.min(n, e));
2440
+ function Ta({ params: e, resolved: t, present: n, onParamChange: s, hoveredBucket: o, onHoverBucket: i }) {
2441
+ const r = Bt(), { push: c } = t, l = c.mapping.buckets.filter((u) => n.has(u.id)).map((u) => ({
2442
+ id: u.id,
2443
+ x: gn(c, u.id).coreRadius,
2444
+ y: Math.abs(gn(c, u.id).charge),
2445
+ colorA: en(r, c.mapping, u.id),
2446
+ outline: "solid",
2447
+ label: u.abbreviation,
2448
+ tooltip: `${u.label} repulsion charge & core radius`
2449
+ }));
2450
+ return /* @__PURE__ */ h(
2451
+ br,
2452
+ {
2453
+ tokens: l,
2454
+ xAxis: { min: Ca, max: Aa, step: Oa, label: "core radius" },
2455
+ yAxis: { min: Ea, max: Ia, step: $a, label: "charge" },
2456
+ onDrag: (u, v, M) => {
2457
+ const S = u;
2458
+ s({
2459
+ // One override per bucket, carrying both numbers the token encodes;
2460
+ // charge is stored negative (repulsion).
2461
+ pair: Ec(e.pair, S, { charge: -M, coreRadius: v })
2462
+ });
2463
+ },
2464
+ hoveredId: o,
2465
+ onHover: i,
2466
+ ariaLabel: "Charge map: core radius versus charge magnitude",
2467
+ xSlider: {
2468
+ value: e.coreRadiusMultiplier,
2469
+ min: 0.1,
2470
+ max: 3,
2471
+ step: 0.05,
2472
+ onChange: (u) => s({ coreRadiusMultiplier: u }),
2473
+ title: "Scale every type’s core radius",
2474
+ ariaLabel: "Scale all core radius",
2475
+ popId: "coreRadiusMultiplier"
2476
+ },
2477
+ ySlider: {
2478
+ value: e.pushMultiplier,
2479
+ min: 0,
2480
+ max: 3,
2481
+ step: 0.1,
2482
+ onChange: (u) => s({ pushMultiplier: u }),
2483
+ title: "Scale every type’s charge",
2484
+ ariaLabel: "Scale all charge",
2485
+ popId: "pushMultiplier"
2486
+ }
2487
+ }
2488
+ );
2489
+ }
2490
+ function Fa({ params: e, resolved: t, present: n, onParamChange: s, hoveredBucket: o, onHoverBucket: i }) {
2491
+ const r = Bt(), { push: c } = t, a = c.mapping.buckets.filter((S) => n.has(S.id)), l = e.pushMultiplier, d = e.coreRadiusMultiplier, u = e.chargeExponent, { curves: v, dMax: M } = g.useMemo(() => {
2492
+ const S = a.map((E) => d * gn(c, E.id).coreRadius), p = Math.max(0, ...S), $ = Math.max(150, p * 4);
2493
+ let D = 0;
2494
+ const x = a.map(({ id: E }) => {
2495
+ const O = Math.abs(gn(c, E).charge) * l, X = d * gn(c, E).coreRadius, N = X * X, k = [];
2496
+ for (let w = 0; w <= tn; w++) {
2497
+ const R = w / tn * $, z = O / Math.pow(R * R + N, Math.max(u, 0.01));
2498
+ z > D && (D = z), k.push({ d: R, v: z });
2499
+ }
2500
+ return { type: E, rEff: X, pts: k };
2501
+ }), V = D > 0 ? D : 1, F = ot * 0.95, L = (E) => E / $ * Tt, y = (E) => Ra(ot - E / V * F, 0, ot);
2502
+ return { curves: x.map(({ type: E, rEff: O, pts: X }) => ({
2503
+ id: E,
2504
+ color: en(r, c.mapping, E),
2505
+ markerX: L(O),
2506
+ points: X.map((N) => `${L(N.d).toFixed(1)},${y(N.v).toFixed(1)}`).join(" ")
2507
+ })), dMax: $ };
2508
+ }, [e, l, c, d, u, r, n]);
2509
+ return /* @__PURE__ */ h(
2510
+ Ys,
2511
+ {
2512
+ curves: v,
2513
+ xMax: M,
2514
+ hoveredId: o,
2515
+ onHover: i,
2516
+ xLabel: "distance",
2517
+ yLabel: "force",
2518
+ ariaLabel: "Charge falloff curves",
2519
+ exp: {
2520
+ value: u,
2521
+ min: 0.5,
2522
+ max: 1,
2523
+ step: 0.05,
2524
+ onChange: (S) => s({ chargeExponent: S }),
2525
+ title: "Power of (d² + r²) in the charge falloff. 1 = inverse-square; higher = sharper drop-off.",
2526
+ popId: "chargeExponent"
2527
+ }
2528
+ }
2529
+ );
2530
+ }
2531
+ const La = 0, Pa = 2, Da = 0.05, _a = 0, Ba = 1e3, Ha = 10, za = (e, t, n) => Math.max(t, Math.min(n, e));
2532
+ function xr(e, t) {
2533
+ const n = [];
2534
+ for (const s of t) {
2535
+ const o = e.describe(s);
2536
+ o && n.push(o);
2537
+ }
2538
+ return n;
2539
+ }
2540
+ function Va({ params: e, resolved: t, present: n, onParamChange: s, hoveredEdge: o, onHoverEdge: i }) {
2541
+ const r = Bt(), { spring: c } = t, l = xr(c, n).map((u) => {
2542
+ const v = c.physicsFor(u.id);
2543
+ return {
2544
+ id: u.id,
2545
+ x: v.distance,
2546
+ y: v.strength,
2547
+ colorA: en(r, c.mapping, u.sourceValue),
2548
+ colorB: en(r, c.mapping, u.targetValue),
2549
+ outline: u.relation === "containment" ? "dashed" : "solid",
2550
+ label: u.label,
2551
+ tooltip: u.tooltip
2552
+ };
2553
+ });
2554
+ return /* @__PURE__ */ h(
2555
+ br,
2556
+ {
2557
+ tokens: l,
2558
+ xAxis: { min: _a, max: Ba, step: Ha, label: "length" },
2559
+ yAxis: { min: La, max: Pa, step: Da, label: "stiffness" },
2560
+ onDrag: (u, v, M) => {
2561
+ s({ pair: Ic(e.pair, u, { strength: M, distance: v }) });
2562
+ },
2563
+ hoveredId: o,
2564
+ onHover: i,
2565
+ ariaLabel: "Spring map: rest length versus stiffness",
2566
+ xSlider: {
2567
+ value: e.distanceMultiplier,
2568
+ min: 0.05,
2569
+ max: 3,
2570
+ step: 0.05,
2571
+ onChange: (u) => s({ distanceMultiplier: u }),
2572
+ title: "Scale every spring’s rest length",
2573
+ ariaLabel: "Scale all length",
2574
+ popId: "distanceMultiplier"
2575
+ },
2576
+ ySlider: {
2577
+ value: e.pullMultiplier,
2578
+ min: 0,
2579
+ max: 3,
2580
+ step: 0.1,
2581
+ onChange: (u) => s({ pullMultiplier: u }),
2582
+ title: "Scale every spring’s stiffness",
2583
+ ariaLabel: "Scale all stiffness",
2584
+ popId: "pullMultiplier"
2585
+ }
2586
+ }
2587
+ );
2588
+ }
2589
+ const ws = ot * 0.78;
2590
+ function Ga(e, t, n, s) {
2591
+ const o = e - n;
2592
+ return t * Math.sign(o) * Math.pow(Math.abs(o), s);
2593
+ }
2594
+ function Xa({ params: e, resolved: t, present: n, onParamChange: s, hoveredEdge: o, onHoverEdge: i }) {
2595
+ const r = Bt(), { spring: c } = t, a = g.useMemo(() => xr(c, n), [c, n]), l = e.pullMultiplier, d = e.distanceMultiplier, u = e.linkExponent, { curves: v, dMax: M } = g.useMemo(() => {
2596
+ const S = a.map((I) => c.physicsFor(I.id).distance * d), p = Math.max(60, Math.max(...S) * 2.2);
2597
+ let $ = 0;
2598
+ const D = a.map((I) => {
2599
+ const E = c.physicsFor(I.id), O = E.strength * l, X = E.distance * d, N = [];
2600
+ for (let k = 0; k <= tn; k++) {
2601
+ const w = k / tn * p, R = Ga(w, O, X, u);
2602
+ Math.abs(R) > $ && ($ = Math.abs(R)), N.push({ d: w, v: R });
2603
+ }
2604
+ return { edge: I, restEff: X, pts: N };
2605
+ }), x = $ > 0 ? $ : 1, V = ws, F = (I) => I / p * Tt, L = (I) => za(ws - I / x * V, 0, ot);
2606
+ return { curves: D.map(({ edge: I, restEff: E, pts: O }) => ({
2607
+ id: I.id,
2608
+ color: en(r, c.mapping, I.sourceValue),
2609
+ markerX: F(E),
2610
+ points: O.map((X) => `${F(X.d).toFixed(1)},${L(X.v).toFixed(1)}`).join(" ")
2611
+ })), dMax: p };
2612
+ }, [c, a, l, d, u, r]);
2613
+ return /* @__PURE__ */ h(
2614
+ Ys,
2615
+ {
2616
+ curves: v,
2617
+ xMax: M,
2618
+ baselineY: ws,
2619
+ hoveredId: o,
2620
+ onHover: i,
2621
+ xLabel: "distance",
2622
+ yLabel: "force",
2623
+ ariaLabel: "Spring force response curves",
2624
+ exp: {
2625
+ value: u,
2626
+ min: 0.5,
2627
+ max: 3,
2628
+ step: 0.1,
2629
+ onChange: (S) => s({ linkExponent: S }),
2630
+ title: "Power of displacement in the spring force. 1 = linear (Hooke); higher = softer near rest, stiffer far out.",
2631
+ popId: "linkExponent"
2632
+ }
2633
+ }
2634
+ );
2635
+ }
2636
+ function Js({ children: e }) {
2637
+ return e === "" || e === null || e === void 0 ? null : typeof e == "string" ? /* @__PURE__ */ h("pre", { className: "gv-graph-control-equation-formula", children: e }) : /* @__PURE__ */ h("div", { className: "gv-graph-control-equation-formula", children: e });
2638
+ }
2639
+ function pn({ subtitle: e, equation: t, onHover: n, children: s }) {
2640
+ return /* @__PURE__ */ C(
2641
+ "div",
2642
+ {
2643
+ className: "gv-graph-control-equation-section",
2644
+ onMouseEnter: () => n(!0),
2645
+ onMouseLeave: () => n(!1),
2646
+ children: [
2647
+ e && /* @__PURE__ */ h("div", { className: "gv-graph-control-equation-header", children: /* @__PURE__ */ C("span", { className: "gv-graph-control-equation-subtitle", children: [
2648
+ "(",
2649
+ e,
2650
+ ")"
2651
+ ] }) }),
2652
+ /* @__PURE__ */ h(Js, { children: t }),
2653
+ /* @__PURE__ */ h("div", { className: "gv-graph-control-equation-body", children: s })
2654
+ ]
2655
+ }
2656
+ );
2657
+ }
2658
+ function wr({ label: e, children: t }) {
2659
+ return /* @__PURE__ */ h("div", { className: "gv-force-subtabs", role: "tablist", "aria-label": e, children: t });
2660
+ }
2661
+ function mn({ label: e, active: t, onSelect: n, leading: s }) {
2662
+ return /* @__PURE__ */ C(
2663
+ "div",
2664
+ {
2665
+ role: "tab",
2666
+ "aria-selected": t,
2667
+ tabIndex: 0,
2668
+ className: `gv-force-subtab${t ? " active" : ""}`,
2669
+ onClick: n,
2670
+ onKeyDown: (o) => {
2671
+ (o.key === "Enter" || o.key === " ") && (o.preventDefault(), n());
2672
+ },
2673
+ children: [
2674
+ s,
2675
+ /* @__PURE__ */ h("span", { className: "gv-force-subtab-label", children: e })
2676
+ ]
2677
+ }
2678
+ );
2679
+ }
2680
+ function Mr({ children: e }) {
2681
+ return /* @__PURE__ */ h("div", { className: "gv-force-bodies", children: e });
2682
+ }
2683
+ function vn({ active: e, children: t }) {
2684
+ return /* @__PURE__ */ h("div", { className: `gv-force-body${e ? " active" : ""}`, "aria-hidden": !e, children: t });
2685
+ }
2686
+ const Ya = /* @__PURE__ */ C("span", { className: "gv-eq-line", children: [
2687
+ "F =",
2688
+ /* @__PURE__ */ C("span", { className: "gv-eq-frac", children: [
2689
+ /* @__PURE__ */ h("span", { className: "gv-eq-num", children: /* @__PURE__ */ h(rt, { id: "pushMultiplier", children: "charge" }) }),
2690
+ /* @__PURE__ */ C("span", { className: "gv-eq-den", children: [
2691
+ "(d² + ",
2692
+ /* @__PURE__ */ h(rt, { id: "coreRadiusMultiplier", children: "r" }),
2693
+ "²)",
2694
+ /* @__PURE__ */ h("sup", { children: /* @__PURE__ */ h(rt, { id: "chargeExponent", children: "exp" }) })
2695
+ ] })
2696
+ ] })
2697
+ ] }), Ja = /* @__PURE__ */ C("span", { className: "gv-eq-line", children: [
2698
+ "F = ",
2699
+ /* @__PURE__ */ h(rt, { id: "pullMultiplier", children: "stiffness" }),
2700
+ " ×",
2701
+ /* @__PURE__ */ C("span", { className: "gv-eq-frac", children: [
2702
+ /* @__PURE__ */ C("span", { className: "gv-eq-num", children: [
2703
+ "(d − ",
2704
+ /* @__PURE__ */ h(rt, { id: "distanceMultiplier", children: "length" }),
2705
+ ")",
2706
+ /* @__PURE__ */ h("sup", { children: /* @__PURE__ */ h(rt, { id: "linkExponent", children: "exp" }) })
2707
+ ] }),
2708
+ /* @__PURE__ */ h("span", { className: "gv-eq-den", children: "d" })
2709
+ ] })
2710
+ ] });
2711
+ function ja(e) {
2712
+ return zs(e) ? `${e.mapping.label} (${e.pushTokens} · ${e.pullTokens})` : `${e.mapping.label} — ${Math.max(e.pushTokens, e.pullTokens)} tokens (max ${Lt})`;
2713
+ }
2714
+ function qa({
2715
+ params: e,
2716
+ resolved: t,
2717
+ axes: n,
2718
+ present: s,
2719
+ onParamChange: o,
2720
+ onAxisChange: i,
2721
+ onActiveSection: r,
2722
+ hoveredPushBucket: c,
2723
+ onHoverPushBucket: a,
2724
+ hoveredEdge: l,
2725
+ onHoverEdge: d
2726
+ }) {
2727
+ const [u, v] = g.useState("push"), M = e.pair.mapping.axis;
2728
+ return /* @__PURE__ */ C("div", { className: "gv-pushpull-controls", children: [
2729
+ /* @__PURE__ */ C("div", { className: "gv-axis-row", children: [
2730
+ /* @__PURE__ */ h("label", { className: "gv-axis-label", htmlFor: "pushpull-axis", children: "axis" }),
2731
+ /* @__PURE__ */ h(
2732
+ "select",
2733
+ {
2734
+ id: "pushpull-axis",
2735
+ className: "gv-axis-select",
2736
+ value: M,
2737
+ title: "The axis push and pull key on. Tokens are the visible set's: a push token per bucket some visible node falls in, a pull token per spring category some sprung edge falls in; the counts measure the whole graph",
2738
+ onChange: (S) => {
2739
+ const p = n.find(($) => $.mapping.axis === S.target.value);
2740
+ p && i(p.mapping);
2741
+ },
2742
+ children: n.map((S) => /* @__PURE__ */ h("option", { value: S.mapping.axis, disabled: !zs(S), children: ja(S) }, S.mapping.axis))
2743
+ }
2744
+ )
2745
+ ] }),
2746
+ /* @__PURE__ */ C(wr, { label: "Pair force", children: [
2747
+ /* @__PURE__ */ h(mn, { label: "Push", active: u === "push", onSelect: () => v("push") }),
2748
+ /* @__PURE__ */ h(mn, { label: "Pull", active: u === "pull", onSelect: () => v("pull") })
2749
+ ] }),
2750
+ /* @__PURE__ */ C(Mr, { children: [
2751
+ /* @__PURE__ */ h(vn, { active: u === "push", children: /* @__PURE__ */ C(pn, { subtitle: "", equation: Ya, onHover: (S) => r(S ? "push" : null), children: [
2752
+ /* @__PURE__ */ h(
2753
+ Ta,
2754
+ {
2755
+ params: e,
2756
+ resolved: t,
2757
+ present: s.push,
2758
+ onParamChange: o,
2759
+ hoveredBucket: c,
2760
+ onHoverBucket: a
2761
+ }
2762
+ ),
2763
+ /* @__PURE__ */ h(
2764
+ Fa,
2765
+ {
2766
+ params: e,
2767
+ resolved: t,
2768
+ present: s.push,
2769
+ onParamChange: o,
2770
+ hoveredBucket: c,
2771
+ onHoverBucket: a
2772
+ }
2773
+ )
2774
+ ] }) }),
2775
+ /* @__PURE__ */ h(vn, { active: u === "pull", children: /* @__PURE__ */ C(pn, { subtitle: "", equation: Ja, onHover: (S) => r(S ? "pull" : null), children: [
2776
+ /* @__PURE__ */ h(
2777
+ Va,
2778
+ {
2779
+ params: e,
2780
+ resolved: t,
2781
+ present: s.springs,
2782
+ onParamChange: o,
2783
+ hoveredEdge: l,
2784
+ onHoverEdge: d
2785
+ }
2786
+ ),
2787
+ /* @__PURE__ */ h(
2788
+ Xa,
2789
+ {
2790
+ params: e,
2791
+ resolved: t,
2792
+ present: s.springs,
2793
+ onParamChange: o,
2794
+ hoveredEdge: l,
2795
+ onHoverEdge: d
2796
+ }
2797
+ )
2798
+ ] }) })
2799
+ ] })
2800
+ ] });
2801
+ }
2802
+ const Ua = (e) => e === "x" ? "bandX" : "bandY", Sr = (e) => e === "x" ? "gravityX" : "gravityY", Ms = (e, t) => e === "x" ? { bandX: t } : { bandY: t }, Co = (e, t) => e === "x" ? { gravityX: t } : { gravityY: t }, js = 300, qs = 210, Jn = { top: 16, right: 8, bottom: 2, left: 8 }, ut = Jn.left, Wt = js - Jn.right, qe = Jn.top, bt = qs - Jn.bottom, nn = -600, jn = 600, Pn = 10, Rs = 5, Ut = (e, t) => {
2803
+ const n = (t - nn) / (jn - nn);
2804
+ return e === "y" ? qe + n * (bt - qe) : bt - n * (bt - qe);
2805
+ }, kr = (e, t) => {
2806
+ const n = e === "y" ? (t - qe) / (bt - qe) : (bt - t) / (bt - qe);
2807
+ return nn + n * (jn - nn);
2808
+ }, Nr = (e, t, n) => Math.max(t, Math.min(n, e)), Er = (e, t) => Math.round(e / t) * t;
2809
+ function Ao({ axis: e, params: t, resolved: n, axes: s, present: o, onParamChange: i, onRelayout: r, hovered: c, onHover: a }) {
2810
+ const l = Bt(), d = Ua(e), u = t[d], v = e === "x" ? n.bandX : n.bandY, M = t[Sr(e)], S = e.toUpperCase(), p = e === "x" && t.radial, $ = Yt(u), D = (x) => {
2811
+ if (x === $) return;
2812
+ const V = s.find((F) => Yt(F) === x);
2813
+ V && r(Ms(e, V.kind === "scalar" ? { scalar: V.scalar.id } : { mapping: V.option.mapping, overrides: /* @__PURE__ */ new Map() }));
2814
+ };
2815
+ return /* @__PURE__ */ C("div", { className: `gv-gravity-section-tools${M > 0 && !p ? "" : " inactive"}`, children: [
2816
+ /* @__PURE__ */ h(Js, { children: ft(v) ? /* @__PURE__ */ C(yn, { children: [
2817
+ "F = ",
2818
+ /* @__PURE__ */ h(rt, { id: `bandStrength${S}`, children: "strength" }),
2819
+ " × d",
2820
+ /* @__PURE__ */ h("sup", { children: /* @__PURE__ */ h(rt, { id: "bandExp", children: "exp" }) }),
2821
+ ", d = |p − p",
2822
+ /* @__PURE__ */ h("sub", { children: "0" }),
2823
+ " − s·(p",
2824
+ /* @__PURE__ */ h("sub", { children: "1" }),
2825
+ " − p",
2826
+ /* @__PURE__ */ h("sub", { children: "0" }),
2827
+ ")|"
2828
+ ] }) : /* @__PURE__ */ C(yn, { children: [
2829
+ "F = ",
2830
+ /* @__PURE__ */ h(rt, { id: `bandStrength${S}`, children: "strength" }),
2831
+ " × d",
2832
+ /* @__PURE__ */ h("sup", { children: /* @__PURE__ */ h(rt, { id: "bandExp", children: "exp" }) })
2833
+ ] }) }),
2834
+ /* @__PURE__ */ C("div", { className: "gv-axis-row", children: [
2835
+ /* @__PURE__ */ h("label", { className: "gv-axis-label", htmlFor: `gravity-axis-${e}`, children: "axis" }),
2836
+ /* @__PURE__ */ h(
2837
+ "select",
2838
+ {
2839
+ id: `gravity-axis-${e}`,
2840
+ className: "gv-axis-select",
2841
+ value: $,
2842
+ title: `What the ${S} axis keys on: one column per bucket of a mapping, or a computed scalar as a gradient`,
2843
+ onChange: (x) => D(x.target.value),
2844
+ children: s.map((x) => x.kind === "scalar" ? /* @__PURE__ */ C("option", { value: Yt(x), title: x.scalar.tooltip, children: [
2845
+ x.scalar.label,
2846
+ " — computed"
2847
+ ] }, Yt(x)) : /* @__PURE__ */ h("option", { value: Yt(x), disabled: x.option.pushTokens > Lt, children: x.option.pushTokens > Lt ? `${x.option.mapping.label} — ${x.option.pushTokens} columns (max ${Lt})` : `${x.option.mapping.label} (${x.option.pushTokens})` }, Yt(x)))
2848
+ }
2849
+ ),
2850
+ p && /* @__PURE__ */ h("span", { className: "gv-axis-note", children: "ignored in radial" })
2851
+ ] }),
2852
+ ft(v) ? /* @__PURE__ */ h(
2853
+ Ka,
2854
+ {
2855
+ axis: e,
2856
+ radial: t.radial,
2857
+ label: v.scalar.label,
2858
+ tooltip: v.scalar.tooltip,
2859
+ span: v.span,
2860
+ strength: M,
2861
+ onStrength: (x) => i(Co(e, x)),
2862
+ onSpan: (x) => i(Ms(e, { scalar: v.scalar.id, span: x }))
2863
+ }
2864
+ ) : /* @__PURE__ */ h(
2865
+ Wa,
2866
+ {
2867
+ axis: e,
2868
+ radial: t.radial,
2869
+ tuning: ps(u),
2870
+ table: v,
2871
+ present: o,
2872
+ strength: M,
2873
+ onStrength: (x) => i(Co(e, x)),
2874
+ onBand: (x, V) => i(Ms(e, Nc(ps(u), x, V))),
2875
+ hovered: c,
2876
+ onHover: a,
2877
+ color: (x) => en(l, ps(u).mapping, x)
2878
+ }
2879
+ ),
2880
+ /* @__PURE__ */ h(Za, { axis: e, params: t, onParamChange: i })
2881
+ ] });
2882
+ }
2883
+ function Ka({ axis: e, radial: t, label: n, tooltip: s, span: o, strength: i, onStrength: r, onSpan: c }) {
2884
+ const a = g.useRef(null), l = g.useRef(null), d = e.toUpperCase(), u = (ut + Wt) / 2, v = (F) => {
2885
+ const L = a.current;
2886
+ if (!L) return 0;
2887
+ const y = L.createSVGPoint();
2888
+ y.x = F.clientX, y.y = F.clientY;
2889
+ const I = L.getScreenCTM();
2890
+ return I ? y.matrixTransform(I.inverse()).y : 0;
2891
+ }, M = (F, L) => {
2892
+ F.preventDefault(), F.currentTarget.setPointerCapture(F.pointerId), l.current = L;
2893
+ }, S = (F) => {
2894
+ const L = l.current;
2895
+ L && c({ ...o, [L]: Nr(Er(kr(e, v(F)), Pn), nn, jn) });
2896
+ }, p = (F) => {
2897
+ var L, y;
2898
+ l.current = null, (y = (L = F.currentTarget).releasePointerCapture) == null || y.call(L, F.pointerId);
2899
+ }, $ = Ut(e, o.zero), D = Ut(e, o.one), x = g.useId(), V = (F, L) => /* @__PURE__ */ C("g", { children: [
2900
+ /* @__PURE__ */ h("text", { x: ut + 10, y: L + 4, textAnchor: "middle", className: "gv-gravity-band-label", children: F === "zero" ? "0" : "1" }),
2901
+ /* @__PURE__ */ h(
2902
+ "circle",
2903
+ {
2904
+ cx: u,
2905
+ cy: L,
2906
+ r: Rs,
2907
+ className: "gv-gravity-band-dot gv-gravity-scalar-dot",
2908
+ onPointerDown: (y) => M(y, F),
2909
+ onPointerMove: S,
2910
+ onPointerUp: p,
2911
+ children: /* @__PURE__ */ h("title", { children: `where a score of ${F === "zero" ? 0 : 1} rests on ${d}: ${o[F]}` })
2912
+ }
2913
+ )
2914
+ ] }, F);
2915
+ return /* @__PURE__ */ h(
2916
+ Xs,
2917
+ {
2918
+ yLabel: `${d} strength`,
2919
+ ySlider: /* @__PURE__ */ h(
2920
+ _t,
2921
+ {
2922
+ orientation: "vertical",
2923
+ min: 0,
2924
+ max: 0.25,
2925
+ step: 5e-3,
2926
+ value: i,
2927
+ onChange: r,
2928
+ title: `${d} pull strength (scale all); 0 switches the axis off`,
2929
+ ariaLabel: `${d} strength`,
2930
+ popId: `bandStrength${d}`
2931
+ }
2932
+ ),
2933
+ bottom: /* @__PURE__ */ h("div", { className: "gv-ctl-plot-xlabel", children: t && e === "y" ? "ring: the span’s low end innermost" : `${d} position: ${n}, 0 → 1` }),
2934
+ children: /* @__PURE__ */ C(
2935
+ "svg",
2936
+ {
2937
+ ref: a,
2938
+ className: "gv-gravity-band-svg",
2939
+ viewBox: `0 0 ${js} ${qs}`,
2940
+ role: "group",
2941
+ "aria-label": `${d} axis: ${n}, a computed scalar; drag the 0 and 1 ends`,
2942
+ children: [
2943
+ /* @__PURE__ */ h("defs", { children: /* @__PURE__ */ C("linearGradient", { id: x, x1: "0", y1: $, x2: "0", y2: D, gradientUnits: "userSpaceOnUse", children: [
2944
+ /* @__PURE__ */ h("stop", { offset: "0", stopColor: "var(--gv-color-text-muted)", stopOpacity: "0.15" }),
2945
+ /* @__PURE__ */ h("stop", { offset: "1", stopColor: "var(--gv-color-text)", stopOpacity: "0.55" })
2946
+ ] }) }),
2947
+ /* @__PURE__ */ h("rect", { x: ut, y: qe, width: Wt - ut, height: bt - qe, className: "gv-gravity-band-bg" }),
2948
+ /* @__PURE__ */ h("title", { children: s }),
2949
+ /* @__PURE__ */ h("rect", { x: ut + 24, y: Math.min($, D), width: Wt - ut - 48, height: Math.abs(D - $), fill: `url(#${x})`, className: "gv-gravity-scalar-gradient" }),
2950
+ /* @__PURE__ */ h("text", { x: u, y: qe - 6, textAnchor: "middle", className: "gv-gravity-band-label", children: n }),
2951
+ /* @__PURE__ */ h("line", { x1: u, y1: qe, x2: u, y2: bt, className: "gv-gravity-band-track" }),
2952
+ V("zero", $),
2953
+ V("one", D)
2954
+ ]
2955
+ }
2956
+ )
2957
+ }
2958
+ );
2959
+ }
2960
+ function Wa({ axis: e, radial: t, tuning: n, table: s, present: o, strength: i, onStrength: r, onBand: c, hovered: a, onHover: l, color: d }) {
2961
+ const u = g.useRef(null), v = g.useRef(null), M = n.mapping.buckets.filter((y) => o.has(y.id)), S = (y) => ut + (y + 0.5) / Math.max(1, M.length) * (Wt - ut), p = e.toUpperCase(), $ = (y) => {
2962
+ const I = u.current;
2963
+ if (!I) return 0;
2964
+ const E = I.createSVGPoint();
2965
+ E.x = y.clientX, E.y = y.clientY;
2966
+ const O = I.getScreenCTM();
2967
+ return O ? E.matrixTransform(O.inverse()).y : 0;
2968
+ }, D = (y, I, E) => {
2969
+ y.preventDefault(), y.currentTarget.setPointerCapture(y.pointerId), v.current = { bucket: I, edge: E };
2970
+ }, x = (y) => {
2971
+ const I = v.current;
2972
+ if (!I) return;
2973
+ const E = gs(s, I.bucket), O = Nr(Er(kr(e, $(y)), Pn), nn, jn);
2974
+ c(I.bucket, I.edge === "min" ? { min: Math.min(O, E.max - Pn), max: E.max } : { min: E.min, max: Math.max(O, E.min + Pn) });
2975
+ }, V = (y) => {
2976
+ var I, E;
2977
+ v.current = null, (E = (I = y.currentTarget).releasePointerCapture) == null || E.call(I, y.pointerId);
2978
+ }, F = (y) => a !== null && a.axis === e && a.bucket === y, L = a !== null && a.axis === e;
2979
+ return /* @__PURE__ */ h(
2980
+ Xs,
2981
+ {
2982
+ yLabel: `${p} strength`,
2983
+ ySlider: /* @__PURE__ */ h(
2984
+ _t,
2985
+ {
2986
+ orientation: "vertical",
2987
+ min: 0,
2988
+ max: 0.25,
2989
+ step: 5e-3,
2990
+ value: i,
2991
+ onChange: r,
2992
+ title: `${p} band-pull strength (scale all); 0 switches the axis off`,
2993
+ ariaLabel: `${p} band strength`,
2994
+ popId: `bandStrength${p}`
2995
+ }
2996
+ ),
2997
+ bottom: (
2998
+ // In radial, Y reads each bucket's band CENTRE as its ring (width is
2999
+ // ignored, equal centres share a ring); the label says so in the same
3000
+ // slot, so the body does not change height when the mode flips.
3001
+ /* @__PURE__ */ h("div", { className: "gv-ctl-plot-xlabel", children: t && e === "y" ? "ring: the band centre, innermost first" : `${p} position` })
3002
+ ),
3003
+ children: /* @__PURE__ */ C(
3004
+ "svg",
3005
+ {
3006
+ ref: u,
3007
+ className: "gv-gravity-band-svg",
3008
+ viewBox: `0 0 ${js} ${qs}`,
3009
+ role: "group",
3010
+ "aria-label": `${p} axis: one column per bucket, its rest band as two handles`,
3011
+ children: [
3012
+ /* @__PURE__ */ h("rect", { x: ut, y: qe, width: Wt - ut, height: bt - qe, className: "gv-gravity-band-bg" }),
3013
+ /* @__PURE__ */ h("g", { className: "gv-gravity-band-stripes", children: M.map((y, I) => {
3014
+ const E = gs(s, y.id), O = Ut(e, E.min), X = Ut(e, E.max), N = (Wt - ut) / M.length / 2;
3015
+ return /* @__PURE__ */ h(
3016
+ "rect",
3017
+ {
3018
+ x: S(I) - N,
3019
+ y: O,
3020
+ width: N * 2,
3021
+ height: Math.max(0, X - O),
3022
+ fill: d(y.id),
3023
+ className: `gv-gravity-band-stripe${L && !F(y.id) ? " dim" : ""}${F(y.id) ? " active" : ""}`
3024
+ },
3025
+ y.id
3026
+ );
3027
+ }) }),
3028
+ M.map((y, I) => {
3029
+ const E = S(I), O = gs(s, y.id), X = Ut(e, O.min), N = Ut(e, O.max), k = d(y.id);
3030
+ return /* @__PURE__ */ C(
3031
+ "g",
3032
+ {
3033
+ className: `gv-gravity-band-col${L && !F(y.id) ? " dim" : ""}${F(y.id) ? " active" : ""}`,
3034
+ onPointerEnter: () => l({ axis: e, bucket: y.id }),
3035
+ onPointerLeave: () => {
3036
+ v.current || l(null);
3037
+ },
3038
+ children: [
3039
+ /* @__PURE__ */ h("title", { children: y.label }),
3040
+ /* @__PURE__ */ h("text", { x: E, y: qe - 6, textAnchor: "middle", className: "gv-gravity-band-label", style: { fill: k }, children: y.abbreviation }),
3041
+ /* @__PURE__ */ h("line", { x1: E, y1: qe, x2: E, y2: bt, className: "gv-gravity-band-track" }),
3042
+ /* @__PURE__ */ h("line", { x1: E, y1: X, x2: E, y2: N, stroke: k, className: "gv-gravity-band-stem" }),
3043
+ /* @__PURE__ */ h(
3044
+ "circle",
3045
+ {
3046
+ cx: E,
3047
+ cy: X,
3048
+ r: Rs,
3049
+ fill: k,
3050
+ className: "gv-gravity-band-dot",
3051
+ onPointerDown: (w) => D(w, y.id, "min"),
3052
+ onPointerMove: x,
3053
+ onPointerUp: V
3054
+ }
3055
+ ),
3056
+ /* @__PURE__ */ h(
3057
+ "circle",
3058
+ {
3059
+ cx: E,
3060
+ cy: N,
3061
+ r: Rs,
3062
+ fill: k,
3063
+ className: "gv-gravity-band-dot",
3064
+ onPointerDown: (w) => D(w, y.id, "max"),
3065
+ onPointerMove: x,
3066
+ onPointerUp: V
3067
+ }
3068
+ )
3069
+ ]
3070
+ },
3071
+ y.id
3072
+ );
3073
+ })
3074
+ ]
3075
+ }
3076
+ )
3077
+ }
3078
+ );
3079
+ }
3080
+ const Oo = 4;
3081
+ function Za({ axis: e, params: t, onParamChange: n }) {
3082
+ const s = t.gravityBandExp, o = t[Sr(e)], i = Math.max(t.gravityX, t.gravityY, 1e-6), r = Array.from({ length: tn + 1 }, (a, l) => {
3083
+ const d = l / tn, u = o / i * Math.pow(d, s), v = d * Tt, M = ot - Oo - u * (ot - 2 * Oo);
3084
+ return `${v.toFixed(1)},${M.toFixed(1)}`;
3085
+ }).join(" "), c = [{ id: e, points: r, color: "var(--gv-color-text)", label: e.toUpperCase() }];
3086
+ return /* @__PURE__ */ h(
3087
+ Ys,
3088
+ {
3089
+ curves: c,
3090
+ xMax: 1,
3091
+ hoveredId: null,
3092
+ onHover: () => {
3093
+ },
3094
+ xLabel: "distance",
3095
+ yLabel: "force",
3096
+ ariaLabel: `${e.toUpperCase()} band force-response curve`,
3097
+ exp: {
3098
+ value: s,
3099
+ min: 0.5,
3100
+ max: 3,
3101
+ step: 0.1,
3102
+ onChange: (a) => n({ gravityBandExp: a }),
3103
+ title: "Band falloff exponent, shared by both axes. 1 = linear (Hooke); higher = softer just outside the band, stiffer far out.",
3104
+ popId: "bandExp"
3105
+ }
3106
+ }
3107
+ );
3108
+ }
3109
+ function Qa({ params: e, resolved: t, axes: n, onParamChange: s, onRelayout: o, hovered: i, onHover: r, present: c }) {
3110
+ const [a, l] = g.useState("y");
3111
+ return /* @__PURE__ */ C("div", { className: "gv-gravity-controls", children: [
3112
+ /* @__PURE__ */ C(wr, { label: "Gravity", children: [
3113
+ /* @__PURE__ */ h(mn, { label: "X Axis", active: a === "x", onSelect: () => l("x") }),
3114
+ /* @__PURE__ */ h(
3115
+ mn,
3116
+ {
3117
+ label: "Y Axis",
3118
+ active: a === "y",
3119
+ onSelect: () => l("y"),
3120
+ leading: /* @__PURE__ */ h(Ro, { label: "Radial layout: Y as distance from the centre", enabled: e.radial, onToggle: (d) => o({ radial: d }) })
3121
+ }
3122
+ ),
3123
+ /* @__PURE__ */ h(
3124
+ mn,
3125
+ {
3126
+ label: "Topological",
3127
+ active: a === "topological",
3128
+ onSelect: () => l("topological"),
3129
+ leading: /* @__PURE__ */ h(Ro, { label: "Topological gravity enabled", enabled: e.topologicalEnabled, onToggle: (d) => o({ topologicalEnabled: d }) })
3130
+ }
3131
+ )
3132
+ ] }),
3133
+ /* @__PURE__ */ C(Mr, { children: [
3134
+ /* @__PURE__ */ h(vn, { active: a === "x", children: /* @__PURE__ */ h(
3135
+ Ao,
3136
+ {
3137
+ axis: "x",
3138
+ params: e,
3139
+ resolved: t,
3140
+ axes: n,
3141
+ present: c.bandX,
3142
+ onParamChange: s,
3143
+ onRelayout: o,
3144
+ hovered: i,
3145
+ onHover: r
3146
+ }
3147
+ ) }),
3148
+ /* @__PURE__ */ h(vn, { active: a === "y", children: /* @__PURE__ */ h(
3149
+ Ao,
3150
+ {
3151
+ axis: "y",
3152
+ params: e,
3153
+ resolved: t,
3154
+ axes: n,
3155
+ present: c.bandY,
3156
+ onParamChange: s,
3157
+ onRelayout: o,
3158
+ hovered: i,
3159
+ onHover: r
3160
+ }
3161
+ ) }),
3162
+ /* @__PURE__ */ h(vn, { active: a === "topological", children: /* @__PURE__ */ C("div", { className: `gv-gravity-section-tools gv-gravity-topo${e.topologicalEnabled ? "" : " inactive"}`, children: [
3163
+ /* @__PURE__ */ h(Js, { children: /* @__PURE__ */ C(yn, { children: [
3164
+ "F = ",
3165
+ /* @__PURE__ */ h(rt, { id: "topoStrength", children: "strength" }),
3166
+ " × depth",
3167
+ /* @__PURE__ */ h("sup", { children: /* @__PURE__ */ h(rt, { id: "topoExp", children: "exp" }) }),
3168
+ " × d"
3169
+ ] }) }),
3170
+ /* @__PURE__ */ h(tl, { exp: e.gravityTopologicalExp }),
3171
+ /* @__PURE__ */ C("div", { className: "gv-gravity-slider-row", children: [
3172
+ /* @__PURE__ */ h("label", { className: "gv-graph-control-slider-label", children: "strength" }),
3173
+ /* @__PURE__ */ h(
3174
+ _t,
3175
+ {
3176
+ min: 0,
3177
+ max: 2,
3178
+ step: 0.02,
3179
+ value: e.gravityTopological,
3180
+ onChange: (d) => s({ gravityTopological: d }),
3181
+ popId: "topoStrength"
3182
+ }
3183
+ )
3184
+ ] }),
3185
+ /* @__PURE__ */ C("div", { className: "gv-gravity-slider-row", children: [
3186
+ /* @__PURE__ */ h("label", { className: "gv-graph-control-slider-label", children: "exp" }),
3187
+ /* @__PURE__ */ h(
3188
+ _t,
3189
+ {
3190
+ min: 1,
3191
+ max: 6,
3192
+ step: 0.1,
3193
+ value: e.gravityTopologicalExp,
3194
+ onChange: (d) => s({ gravityTopologicalExp: d }),
3195
+ popId: "topoExp"
3196
+ }
3197
+ )
3198
+ ] })
3199
+ ] }) })
3200
+ ] })
3201
+ ] });
3202
+ }
3203
+ function Ro({ label: e, enabled: t, onToggle: n }) {
3204
+ return /* @__PURE__ */ C("label", { className: `gv-switch${t ? " on" : ""}`, onClick: (s) => s.stopPropagation(), title: e, children: [
3205
+ /* @__PURE__ */ h("input", { type: "checkbox", checked: t, onChange: (s) => n(s.target.checked), "aria-label": e }),
3206
+ /* @__PURE__ */ h("span", { className: "gv-switch-track", children: /* @__PURE__ */ h("span", { className: "gv-switch-knob" }) })
3207
+ ] });
3208
+ }
3209
+ const To = 220, Ss = 96, ks = 8, el = 16;
3210
+ function tl({ exp: e }) {
3211
+ const t = el, n = To - ks, s = ks, o = Ss - ks - 12, i = (s + o) / 2, r = 48, c = Array.from({ length: r + 1 }, (a, l) => {
3212
+ const d = l / r, u = Math.pow(d, e);
3213
+ return `${(t + d * (n - t)).toFixed(1)},${(o - u * (o - s)).toFixed(1)}`;
3214
+ }).join(" ");
3215
+ return /* @__PURE__ */ C("svg", { className: "gv-gravity-topo-curve", viewBox: `0 0 ${To} ${Ss}`, role: "img", "aria-label": "Depth-to-pull contrast curve", children: [
3216
+ /* @__PURE__ */ h("rect", { x: t, y: s, width: n - t, height: o - s, className: "gv-spring-curve-frame" }),
3217
+ /* @__PURE__ */ h("polyline", { points: c, className: "gv-gravity-topo-curve-line" }),
3218
+ /* @__PURE__ */ h("text", { x: (t + n) / 2, y: Ss - 1, textAnchor: "middle", className: "gv-gravity-topo-curve-axis", children: "depth" }),
3219
+ /* @__PURE__ */ h("text", { x: 5, y: i, textAnchor: "middle", className: "gv-gravity-topo-curve-axis", transform: `rotate(-90 5 ${i})`, children: "pull" })
3220
+ ] });
3221
+ }
3222
+ const nl = [
3223
+ { id: "forces", label: "Push/Pull" },
3224
+ { id: "gravity", label: "Gravity" },
3225
+ { id: "misc", label: "Misc" }
3226
+ ], sl = [
3227
+ {
3228
+ key: "velocityDecay",
3229
+ label: "friction",
3230
+ min: 0.05,
3231
+ max: 0.95,
3232
+ step: 0.05,
3233
+ tooltip: "Damping factor per tick. Higher = more friction"
3234
+ },
3235
+ {
3236
+ key: "alphaDecay",
3237
+ label: "cooling",
3238
+ min: 5e-4,
3239
+ max: 0.02,
3240
+ step: 5e-4,
3241
+ tooltip: "Energy lost per tick. Higher = settles faster"
3242
+ },
3243
+ {
3244
+ key: "alphaMin",
3245
+ label: "threshold",
3246
+ min: 0,
3247
+ max: 5e-3,
3248
+ step: 1e-4,
3249
+ tooltip: "Energy level below which simulation pauses"
3250
+ }
3251
+ ], ol = [
3252
+ {
3253
+ key: "baseMul",
3254
+ label: "size",
3255
+ min: 0.3,
3256
+ max: 2,
3257
+ step: 0.05,
3258
+ tooltip: "Overall node + label size. 1 = default."
3259
+ },
3260
+ {
3261
+ key: "maxZoomMul",
3262
+ label: "grow cap",
3263
+ min: 0.5,
3264
+ max: 3,
3265
+ step: 0.05,
3266
+ tooltip: "Zoom past which nodes stop growing. Lower = nodes start shrinking sooner as you zoom out."
3267
+ },
3268
+ {
3269
+ key: "minZoomMul",
3270
+ label: "shrink floor",
3271
+ min: 0.1,
3272
+ max: 1,
3273
+ step: 0.05,
3274
+ tooltip: "Smallest nodes may get when zoomed all the way out."
3275
+ }
3276
+ ];
3277
+ function rl({
3278
+ params: e,
3279
+ resolved: t,
3280
+ onParamChange: n,
3281
+ onAdjust: s,
3282
+ onRelayout: o,
3283
+ axes: i,
3284
+ layoutAxes: r,
3285
+ present: c,
3286
+ onAxisChange: a,
3287
+ onActiveSection: l,
3288
+ onActivePushBucket: d,
3289
+ onActiveGravityBucket: u,
3290
+ onActivePullEdge: v,
3291
+ nodeScale: M,
3292
+ onNodeScaleChange: S
3293
+ }) {
3294
+ const [p, $] = g.useState(!1), [D, x] = g.useState("forces"), [V, F] = g.useState(null), L = g.useCallback((w) => {
3295
+ F(w), v(w);
3296
+ }, [v]), [y, I] = g.useState(null), E = g.useCallback((w) => {
3297
+ I(w), d(w);
3298
+ }, [d]), [O, X] = g.useState(null), N = g.useCallback((w) => {
3299
+ X(w), u(w);
3300
+ }, [u]), k = g.useCallback((w) => {
3301
+ n(w), s();
3302
+ }, [n, s]);
3303
+ return /* @__PURE__ */ C("div", { className: `gv-graph-control-panel ${p ? "open" : ""}`, children: [
3304
+ /* @__PURE__ */ h(
3305
+ "button",
3306
+ {
3307
+ className: "gv-graph-control-panel-toggle",
3308
+ onClick: () => $(!p),
3309
+ title: "Toggle control panel",
3310
+ children: p ? "▼ Controls" : "▶ Controls"
3311
+ }
3312
+ ),
3313
+ p && /* @__PURE__ */ h(Ma, { children: /* @__PURE__ */ C("div", { className: "gv-graph-control-panel-body", children: [
3314
+ /* @__PURE__ */ h("div", { className: "gv-graph-control-tabs", role: "tablist", children: nl.map((w) => /* @__PURE__ */ h(
3315
+ "button",
3316
+ {
3317
+ role: "tab",
3318
+ "aria-selected": D === w.id,
3319
+ className: `gv-graph-control-tab${D === w.id ? " active" : ""}`,
3320
+ onClick: () => x(w.id),
3321
+ children: w.label
3322
+ },
3323
+ w.id
3324
+ )) }),
3325
+ /* @__PURE__ */ C("div", { className: "gv-graph-control-sections", children: [
3326
+ /* @__PURE__ */ h(Ns, { active: D === "forces", children: /* @__PURE__ */ h(
3327
+ qa,
3328
+ {
3329
+ params: e,
3330
+ resolved: t,
3331
+ axes: i,
3332
+ present: c,
3333
+ onParamChange: k,
3334
+ onAxisChange: a,
3335
+ onActiveSection: l,
3336
+ hoveredPushBucket: y,
3337
+ onHoverPushBucket: E,
3338
+ hoveredEdge: V,
3339
+ onHoverEdge: L
3340
+ }
3341
+ ) }),
3342
+ /* @__PURE__ */ h(Ns, { active: D === "gravity", children: /* @__PURE__ */ h(
3343
+ pn,
3344
+ {
3345
+ subtitle: "",
3346
+ equation: "",
3347
+ onHover: (w) => {
3348
+ l(w ? "gravity" : null), w || u(null);
3349
+ },
3350
+ children: /* @__PURE__ */ h(
3351
+ Qa,
3352
+ {
3353
+ params: e,
3354
+ resolved: t,
3355
+ axes: r,
3356
+ present: c,
3357
+ onParamChange: k,
3358
+ onRelayout: o,
3359
+ hovered: O,
3360
+ onHover: N
3361
+ }
3362
+ )
3363
+ }
3364
+ ) }),
3365
+ /* @__PURE__ */ C(Ns, { active: D === "misc", children: [
3366
+ /* @__PURE__ */ C("div", { className: "gv-graph-control-subsection", children: [
3367
+ /* @__PURE__ */ h("div", { className: "gv-graph-control-subsection-title", children: "Dynamics" }),
3368
+ /* @__PURE__ */ h(pn, { subtitle: "", equation: `v ×= friction
3369
+ α −= cooling, stop at threshold`, onHover: (w) => l(w ? "dynamics" : null), children: sl.map((w) => /* @__PURE__ */ h(Fo, { def: w, value: e[w.key], onChange: (R) => k({ [w.key]: R }) }, w.key)) })
3370
+ ] }),
3371
+ /* @__PURE__ */ C("div", { className: "gv-graph-control-subsection", children: [
3372
+ /* @__PURE__ */ h("div", { className: "gv-graph-control-subsection-title", children: "Node scaling" }),
3373
+ /* @__PURE__ */ h(pn, { subtitle: "", equation: "size = base × clamp(zoom, floor, cap)", onHover: () => {
3374
+ }, children: ol.map((w) => /* @__PURE__ */ h(Fo, { def: w, value: M[w.key], onChange: (R) => S({ [w.key]: R }) }, w.key)) })
3375
+ ] })
3376
+ ] })
3377
+ ] })
3378
+ ] }) })
3379
+ ] });
3380
+ }
3381
+ function Ns({ active: e, children: t }) {
3382
+ return /* @__PURE__ */ h("div", { className: `gv-graph-control-section-slot${e ? " active" : ""}`, "aria-hidden": !e, children: t });
3383
+ }
3384
+ function Fo({ def: e, value: t, onChange: n, nodeType: s }) {
3385
+ const o = Bt(), i = e.step < 1 ? String(t) : String(Math.round(t)), r = s ? { className: "gv-graph-control-slider gv-graph-control-typed-row", style: { "--gv-type-color": `var(${o.colorVar(s)})` } } : { className: "gv-graph-control-slider", style: void 0 };
3386
+ return /* @__PURE__ */ C("div", { className: r.className, style: r.style, title: e.tooltip, children: [
3387
+ /* @__PURE__ */ h("label", { className: "gv-graph-control-slider-label", children: e.label }),
3388
+ /* @__PURE__ */ h(_t, { min: e.min, max: e.max, step: e.step, value: t, onChange: n }),
3389
+ /* @__PURE__ */ h("span", { className: "gv-graph-control-slider-value", children: i })
3390
+ ] });
3391
+ }
3392
+ const il = {
3393
+ dark: [
3394
+ "#2DD4BF",
3395
+ // teal
3396
+ "#F59E0B",
3397
+ // amber
3398
+ "#A78BFA",
3399
+ // violet
3400
+ "#F472B6",
3401
+ // rose
3402
+ "#34D399",
3403
+ // green
3404
+ "#60A5FA",
3405
+ // blue
3406
+ "#FB923C",
3407
+ // orange
3408
+ "#A3E635",
3409
+ // lime
3410
+ "#22D3EE",
3411
+ // cyan
3412
+ "#E879F9"
3413
+ // fuchsia
3414
+ ],
3415
+ light: [
3416
+ "#0F766E",
3417
+ // teal
3418
+ "#B45309",
3419
+ // amber
3420
+ "#6D28D9",
3421
+ // violet
3422
+ "#BE185D",
3423
+ // rose
3424
+ "#047857",
3425
+ // green
3426
+ "#1D4ED8",
3427
+ // blue
3428
+ "#C2410C",
3429
+ // orange
3430
+ "#4D7C0F",
3431
+ // lime
3432
+ "#0E7490",
3433
+ // cyan
3434
+ "#A21CAF"
3435
+ // fuchsia
3436
+ ]
3437
+ }, cl = 2.2, al = 2.2;
3438
+ function ll(e, t, n = "dark", s = null) {
3439
+ const o = il[n], i = [];
3440
+ return e.forEach((r, c) => {
3441
+ const a = /* @__PURE__ */ new Set();
3442
+ for (const l of r.nodeIds) t.has(l) && a.add(l);
3443
+ a.size !== 0 && i.push({ id: r.id, strength: r.emphasized || r.id === s ? cl : 1, nodeIds: a, color: r.color ?? o[c % o.length] });
3444
+ }), i;
3445
+ }
3446
+ function dl(e, t) {
3447
+ const n = t.filter((i) => !!i);
3448
+ if (n.length === 0) return e;
3449
+ let s = !1;
3450
+ const o = e.map((i) => n.some((r) => i.nodeIds.has(r)) ? (s = !0, { ...i, strength: Math.max(i.strength, al) }) : i);
3451
+ return s ? o : e;
3452
+ }
3453
+ function ul() {
3454
+ const [e, t] = g.useState(Xc), n = g.useRef(null), s = g.useRef(!1), o = g.useRef(null), i = g.useRef(null), r = g.useCallback(() => {
3455
+ const a = n.current;
3456
+ if (!a) return null;
3457
+ const { width: l, height: d } = a.getBoundingClientRect();
3458
+ return i.current = { width: l, height: d }, { width: l, height: d };
3459
+ }, []);
3460
+ g.useEffect(() => {
3461
+ const a = n.current;
3462
+ if (!a || typeof ResizeObserver > "u") return;
3463
+ const l = new ResizeObserver(() => {
3464
+ const d = i.current, u = r();
3465
+ u && t((v) => jc(v, d, u));
3466
+ });
3467
+ return l.observe(a), () => l.disconnect();
3468
+ }, [r]);
3469
+ const c = g.useCallback((a, l) => {
3470
+ const d = r();
3471
+ d && t(hr(a, d.width, d.height, l));
3472
+ }, [r]);
3473
+ return { viewport: e, setViewport: t, containerRef: n, initialFitDone: s, pendingCenterRef: o, measure: r, fit: c };
3474
+ }
3475
+ function fl(e, t, n, s) {
3476
+ const o = /* @__PURE__ */ new Set([e]), i = [e];
3477
+ for (; i.length > 0; ) {
3478
+ const r = i.shift();
3479
+ for (const c of t) {
3480
+ if (it(c)) continue;
3481
+ let a;
3482
+ s === "downstream" && c.sourceId === r ? a = c.targetId : s === "upstream" && c.targetId === r && (a = c.sourceId), a && n.has(a) && !o.has(a) && (o.add(a), i.push(a));
3483
+ }
3484
+ }
3485
+ return o;
3486
+ }
3487
+ function hl(e, t) {
3488
+ const n = /* @__PURE__ */ new Set();
3489
+ for (const s of t)
3490
+ it(s) || e.has(s.sourceId) && e.has(s.targetId) && n.add(s.id);
3491
+ return n;
3492
+ }
3493
+ function gl(e, t, n, s) {
3494
+ const o = fl(t.id, [...s.visibleEdges], new Set(s.visibleIds), n), i = e.highlight(t, { nodes: o }, s, n), r = new Set(i.nodes), c = i.edges ? new Set(i.edges) : hl(r, [...s.visibleEdges]);
3495
+ return { nodes: r, edges: c };
3496
+ }
3497
+ function pl(e, t, n, s, o, i, r, c) {
3498
+ const [a, l] = g.useState(null), [d, u] = g.useState(-1), [v, M] = g.useState(!1), [S, p] = g.useState(null), [$, D] = g.useState(null), [x, V] = g.useState(null), [F, L] = g.useState(null);
3499
+ g.useEffect(() => {
3500
+ l(null), u(-1);
3501
+ }, [o]), g.useEffect(() => {
3502
+ const O = (N) => {
3503
+ N.key === "Shift" && M(!0);
3504
+ }, X = (N) => {
3505
+ N.key === "Shift" && M(!1);
3506
+ };
3507
+ return window.addEventListener("keydown", O), window.addEventListener("keyup", X), () => {
3508
+ window.removeEventListener("keydown", O), window.removeEventListener("keyup", X);
3509
+ };
3510
+ }, []);
3511
+ const y = d >= 0 && d < e.length ? e[d].id : null, { highlightedNodes: I, highlightedEdges: E } = g.useMemo(() => {
3512
+ const O = a ?? r;
3513
+ if (!O || !n.has(O))
3514
+ return { highlightedNodes: null, highlightedEdges: null };
3515
+ const X = v ? "upstream" : "downstream", N = s(O);
3516
+ if (!N) return { highlightedNodes: null, highlightedEdges: null };
3517
+ const k = (z) => c.get(z), { nodes: w, edges: R } = gl(i, k(O) ?? N, X, {
3518
+ visibleNodes: e.map((z) => k(z.id) ?? z),
3519
+ visibleEdges: t,
3520
+ visibleIds: n,
3521
+ getNode: (z) => k(z) ?? s(z)
3522
+ });
3523
+ return { highlightedNodes: w, highlightedEdges: R };
3524
+ }, [a, r, v, t, n, e, s, i, c]);
3525
+ return {
3526
+ hoveredNodeId: a,
3527
+ setHoveredNodeId: l,
3528
+ focusedIndex: d,
3529
+ setFocusedIndex: u,
3530
+ shiftHeld: v,
3531
+ focusedNodeId: y,
3532
+ highlightedNodes: I,
3533
+ highlightedEdges: E,
3534
+ activeSection: S,
3535
+ setActiveSection: p,
3536
+ activePushBucket: $,
3537
+ setActivePushBucket: D,
3538
+ activeGravityBucket: x,
3539
+ setActiveGravityBucket: V,
3540
+ activePullEdge: F,
3541
+ setActivePullEdge: L
3542
+ };
3543
+ }
3544
+ const ml = Math.random;
3545
+ function vl(e, t, n, s, o, i) {
3546
+ const r = g.useRef(null), c = g.useRef(null), a = g.useRef(!1), l = g.useRef([]), d = g.useRef(!1), u = g.useRef(null), v = g.useRef(null), [M, S] = g.useState(!0), p = g.useMemo(() => Tc(o, t, e), [o, t, e]);
3547
+ g.useEffect(() => {
3548
+ p !== o && i((N) => N === o ? p : N);
3549
+ }, [p, o]);
3550
+ const [$, D] = g.useState(0), x = g.useRef(s);
3551
+ x.current = s, g.useEffect(() => {
3552
+ var w;
3553
+ const N = r.current;
3554
+ if (N && c.current && c.current !== e && !a.current && Ji(c.current, e) && (a.current = !0, console.warn("[graph] the graph's identity changed but nothing in it did; the view rebuilt its simulation for nothing. Keep one graph object until its nodes or edges change.")), c.current = e, u.current !== null && u.current !== t && !d.current) {
3555
+ const R = typeof performance < "u" ? performance.now() : 0, z = l.current.filter((pe) => R - pe < 2e3);
3556
+ z.push(R), l.current = z, z.length >= 3 && (d.current = !0, console.warn("[graph] the taxonomy's identity changed three times in two seconds; the view rebuilds its simulation for each. Build the taxonomy once, outside render."));
3557
+ }
3558
+ u.current = t;
3559
+ const k = new Map(n ?? []);
3560
+ if (N) for (const R of N.nodes) k.set(R.id, { x: R.x, y: R.y });
3561
+ r.current = new Pc(e, p, ml, t, k.size > 0 ? k : void 0), (w = x.current) == null || w.call(x, N !== null), S(!0), D((R) => R + 1);
3562
+ }, [e, t]), g.useEffect(() => {
3563
+ const N = r.current;
3564
+ N && N.params !== p && N.setParams(p);
3565
+ }, [p]);
3566
+ const V = g.useCallback((N) => {
3567
+ var k;
3568
+ return (k = r.current) == null ? void 0 : k.getNode(N);
3569
+ }, []), F = g.useCallback((N) => {
3570
+ i((k) => ({ ...k, ...N }));
3571
+ }, [i]), L = g.useCallback(() => {
3572
+ var N;
3573
+ (N = r.current) == null || N.nudge(0.3), S(!0);
3574
+ }, []), y = g.useCallback((N) => {
3575
+ var k;
3576
+ i((w) => ({ ...w, ...N })), (k = r.current) == null || k.reheat(0.6), S(!0);
3577
+ }, [i]), I = g.useCallback((N, k, w) => {
3578
+ var R, z;
3579
+ v.current = N, (R = r.current) == null || R.pinNode(N, k, w), (z = r.current) == null || z.reheat(0.3), S(!0);
3580
+ }, []), E = g.useCallback((N, k) => {
3581
+ var w;
3582
+ v.current && ((w = r.current) == null || w.pinNode(v.current, N, k));
3583
+ }, []), O = g.useCallback(() => {
3584
+ var N;
3585
+ v.current && ((N = r.current) == null || N.unpinNode(v.current), v.current = null);
3586
+ }, []), X = g.useCallback(() => {
3587
+ var N;
3588
+ M ? S(!1) : ((N = r.current) == null || N.reheat(0.5), S(!0));
3589
+ }, [M]);
3590
+ return {
3591
+ simRef: r,
3592
+ simVersion: $,
3593
+ running: M,
3594
+ setRunning: S,
3595
+ forceParams: p,
3596
+ getNode: V,
3597
+ onParamChange: F,
3598
+ onForceAdjust: L,
3599
+ onRelayout: y,
3600
+ onNodeDragStart: I,
3601
+ onNodeDragMove: E,
3602
+ onNodeDragEnd: O,
3603
+ onToggleRunning: X
3604
+ };
3605
+ }
3606
+ const yl = {
3607
+ visibleNodes: [],
3608
+ visibleEdges: [],
3609
+ visibleIds: /* @__PURE__ */ new Set(),
3610
+ edgeTypes: /* @__PURE__ */ new Map(),
3611
+ origins: /* @__PURE__ */ new Map(),
3612
+ nodeSummaries: /* @__PURE__ */ new Map(),
3613
+ downstreamScores: /* @__PURE__ */ new Map()
3614
+ };
3615
+ function Ir(e, t, n) {
3616
+ const s = n(e);
3617
+ if (!s) return null;
3618
+ let o = s.parentId;
3619
+ for (; o; ) {
3620
+ if (t.has(o)) return o;
3621
+ const i = n(o);
3622
+ o = i == null ? void 0 : i.parentId;
3623
+ }
3624
+ return null;
3625
+ }
3626
+ function Ts(e, t, n, s, o, i, r, c = /* @__PURE__ */ new Set()) {
3627
+ if (t) return [e];
3628
+ if (c.has(e)) return [];
3629
+ c.add(e);
3630
+ const a = i(e);
3631
+ if (a && r.nodeStyleOf(a).whenHidden === "splice") {
3632
+ const d = [];
3633
+ for (const u of s.edges) {
3634
+ if (it(u)) continue;
3635
+ const v = n === "tgt" ? u.sourceId === e ? u.targetId : null : u.targetId === e ? u.sourceId : null;
3636
+ if (v)
3637
+ for (const M of Ts(v, o.has(v), n, s, o, i, r, c))
3638
+ d.push(M);
3639
+ }
3640
+ if (d.length > 0) return d;
3641
+ }
3642
+ const l = Ir(e, o, i);
3643
+ return l ? [l] : [];
3644
+ }
3645
+ function bl(e, t, n, s) {
3646
+ const { summaryKind: o } = s.nodeStyleOf(e);
3647
+ if (o === "none") return "";
3648
+ if (o === "children") {
3649
+ const a = /* @__PURE__ */ new Map();
3650
+ for (const l of t) {
3651
+ if (!it(l) || l.targetId !== e.id) continue;
3652
+ const d = n.get(l.sourceId);
3653
+ if (!d) continue;
3654
+ const u = s.styleValueOf(d);
3655
+ u !== void 0 && a.set(u, (a.get(u) ?? 0) + 1);
3656
+ }
3657
+ return s.styleValues.filter((l) => a.has(l)).map((l) => `${a.get(l)} ${s.abbreviationFor(l)}`).join(" · ");
3658
+ }
3659
+ let i = 0, r = 0;
3660
+ for (const a of t)
3661
+ it(a) || (a.sourceId === e.id && i++, a.targetId === e.id && r++);
3662
+ const c = [];
3663
+ return i > 0 && c.push(`→${i}`), r > 0 && c.push(`←${r}`), c.join(" ");
3664
+ }
3665
+ function Dn(e, t, n, s = n.filterAxes) {
3666
+ return Xn(t, s, (o) => n.valueOn(e, o));
3667
+ }
3668
+ function xl(e, t) {
3669
+ var o;
3670
+ const n = new Map(t.edgeTypes.map((i) => [i.id, i])), s = /* @__PURE__ */ new Map();
3671
+ for (const i of e.edges) {
3672
+ const r = e.getNode(i.sourceId), c = e.getNode(i.targetId);
3673
+ let a;
3674
+ try {
3675
+ a = t.edgeTypeOf(i, r && t.styleValueOf(r), c && t.styleValueOf(c));
3676
+ } catch {
3677
+ a = void 0;
3678
+ }
3679
+ s.set(i.id, a !== void 0 && ((o = n.get(a)) == null ? void 0 : o.relation) === xn(i) ? a : void 0);
3680
+ }
3681
+ return s;
3682
+ }
3683
+ function wl(e, t, n, s = n.filterAxes) {
3684
+ const o = /* @__PURE__ */ new Set(), i = [];
3685
+ for (const x of e.nodes)
3686
+ Dn(x, t, n, s) && (o.add(x.id), i.push(x));
3687
+ const r = xl(e, n), c = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), l = (x) => e.getNode(x), d = [], u = /* @__PURE__ */ new Set(), v = [];
3688
+ for (const x of e.edges) {
3689
+ const V = o.has(x.sourceId), F = o.has(x.targetId);
3690
+ if (it(x)) {
3691
+ if (!V) continue;
3692
+ if (F)
3693
+ d.push(x), c.set(x.id, r.get(x.id)), a.set(x.id, x.id);
3694
+ else {
3695
+ const L = Ir(x.targetId, o, l);
3696
+ if (L) {
3697
+ const y = `grad:${x.id}`;
3698
+ d.push({ ...x, targetId: L, id: y }), c.set(y, r.get(x.id)), a.set(y, x.id);
3699
+ }
3700
+ }
3701
+ } else V && F ? (d.push(x), c.set(x.id, r.get(x.id)), a.set(x.id, x.id), u.add(`${x.sourceId}→${x.targetId}`)) : v.push(x);
3702
+ }
3703
+ const M = /* @__PURE__ */ new Map();
3704
+ for (const x of v) {
3705
+ const V = Ts(x.sourceId, o.has(x.sourceId), "src", e, o, l, n), F = Ts(x.targetId, o.has(x.targetId), "tgt", e, o, l, n);
3706
+ for (const L of V)
3707
+ for (const y of F) {
3708
+ if (L === y) continue;
3709
+ const I = `${L}→${y}`;
3710
+ if (u.has(I)) continue;
3711
+ const E = M.get(I);
3712
+ E && n.collapse(E.origin, x) === E.origin || M.set(I, { origin: x, edge: { ...x, sourceId: L, targetId: y, id: `grad:${I}` } });
3713
+ }
3714
+ }
3715
+ const S = [...d];
3716
+ for (const { origin: x, edge: V } of M.values())
3717
+ S.push(V), c.set(V.id, r.get(x.id)), a.set(V.id, x.id);
3718
+ const p = /* @__PURE__ */ new Map();
3719
+ for (const x of i) p.set(x.id, x);
3720
+ const $ = /* @__PURE__ */ new Map();
3721
+ for (const x of i) {
3722
+ const V = bl(x, S, p, n);
3723
+ V && $.set(x.id, V);
3724
+ }
3725
+ const D = Uo({ nodes: i, edges: S, getNode: (x) => p.get(x) });
3726
+ return { visibleNodes: i, visibleEdges: S, visibleIds: o, edgeTypes: c, origins: a, nodeSummaries: $, downstreamScores: D };
3727
+ }
3728
+ function Ml(e, t, n, s, o) {
3729
+ return g.useMemo(() => {
3730
+ const i = e.current;
3731
+ return i ? wl(i, n, o, s) : yl;
3732
+ }, [n, s, t, o]);
3733
+ }
3734
+ function Sl({
3735
+ simRef: e,
3736
+ running: t,
3737
+ setRunning: n,
3738
+ visibleIds: s,
3739
+ visibleNodes: o,
3740
+ downstreamScores: i,
3741
+ filter: r,
3742
+ axes: c,
3743
+ hoveredNodeId: a,
3744
+ selectedNodeId: l,
3745
+ measure: d,
3746
+ initialFitDone: u,
3747
+ pendingCenterRef: v,
3748
+ setViewport: M,
3749
+ setSelectedNodeId: S,
3750
+ taxonomy: p
3751
+ }) {
3752
+ const [$, D] = g.useState(0), x = g.useRef({ frames: 0, lastStamp: 0 });
3753
+ g.useEffect(() => {
3754
+ if (!t) return;
3755
+ let L = 0;
3756
+ x.current = { frames: 0, lastStamp: 0 };
3757
+ const y = () => {
3758
+ const I = e.current;
3759
+ if (!I) return;
3760
+ if (I.tick(s, i), !u.current && I.alpha < 0.3) {
3761
+ const N = d();
3762
+ N && N.width > 0 && N.height > 0 && (M(hr(o, N.width, N.height)), u.current = !0);
3763
+ }
3764
+ if (u.current && v.current) {
3765
+ const N = I.getNode(v.current.nodeId);
3766
+ if (N) {
3767
+ const k = d();
3768
+ if (k) {
3769
+ const { width: w, height: R } = k;
3770
+ M((z) => ({
3771
+ scale: Math.max(z.scale, 1.2),
3772
+ x: w / 2 - N.x * Math.max(z.scale, 1.2),
3773
+ y: R / 2 - N.y * Math.max(z.scale, 1.2)
3774
+ })), S(N.id);
3775
+ }
3776
+ }
3777
+ v.current = null;
3778
+ }
3779
+ const E = performance.now(), O = x.current;
3780
+ O.frames++, O.lastStamp === 0 && (O.lastStamp = E);
3781
+ const X = E - O.lastStamp;
3782
+ if (X >= 500) {
3783
+ const N = Math.round(O.frames * 1e3 / X);
3784
+ D((k) => k === N ? k : N), O.frames = 0, O.lastStamp = E;
3785
+ }
3786
+ if (I.isStable()) {
3787
+ n(!1);
3788
+ return;
3789
+ }
3790
+ L = requestAnimationFrame(y);
3791
+ };
3792
+ return L = requestAnimationFrame(y), () => {
3793
+ L && cancelAnimationFrame(L);
3794
+ };
3795
+ }, [t, s, o, l]);
3796
+ const [, V] = g.useState(0);
3797
+ g.useEffect(() => {
3798
+ if (!t || !a) return;
3799
+ const L = window.setInterval(() => V((y) => y + 1), 100);
3800
+ return () => window.clearInterval(L);
3801
+ }, [t, a]);
3802
+ const F = g.useRef(r);
3803
+ return g.useEffect(() => {
3804
+ const L = F.current;
3805
+ if (L === r) return;
3806
+ const y = e.current;
3807
+ if (!y) {
3808
+ F.current = r;
3809
+ return;
3810
+ }
3811
+ const { alpha: I, seedRevealed: E, refit: O, resume: X } = bi(
3812
+ c.filter(
3813
+ (N) => !Gn(ze(L, N.id), ze(r, N.id))
3814
+ )
3815
+ );
3816
+ if (I > 0) {
3817
+ if (E)
3818
+ for (const N of y.nodes) {
3819
+ if (!Dn(N, r, p, c) || Dn(N, L, p, c)) continue;
3820
+ let k = N.parentId;
3821
+ for (; k; ) {
3822
+ const w = y.getNode(k);
3823
+ if (!w) break;
3824
+ if (Dn(w, r, p, c)) {
3825
+ y.seedAt(N.id, w.x, w.y);
3826
+ break;
3827
+ }
3828
+ k = w.parentId;
3829
+ }
3830
+ }
3831
+ y.reheat(I), X && n(!0), O && (u.current = !1);
3832
+ }
3833
+ F.current = r;
3834
+ }, [r]), { fps: $ };
3835
+ }
3836
+ function Lo(e, t) {
3837
+ return e === t || e !== null && t !== null && e.id === t.id && e.key === t.key;
3838
+ }
3839
+ const kl = /* @__PURE__ */ new Set(["containment", "dependency"]);
3840
+ function Nl(e, t) {
3841
+ const n = [], s = new Map(t.edgeTypes.map((l) => [l.id, l])), o = new Set(t.styleValues), i = Pt(e.nodes), r = /* @__PURE__ */ new Set();
3842
+ for (const l of e.nodes) {
3843
+ if (r.has(l.id)) {
3844
+ n.push({ severity: "error", code: "node-id-duplicate", nodeId: l.id, message: `node id ${JSON.stringify(l.id)} is used more than once; the view draws the first` });
3845
+ continue;
3846
+ }
3847
+ r.add(l.id), l.parentId !== void 0 && !i.has(l.parentId) && n.push({ severity: "error", code: "parent-missing", nodeId: l.id, message: `node ${JSON.stringify(l.id)} names parent ${JSON.stringify(l.parentId)}, which is not in the graph` });
3848
+ const d = t.styleValueOf(l);
3849
+ d !== void 0 && !o.has(d) && n.push({ severity: "warning", code: "node-value-undeclared", nodeId: l.id, message: `node ${JSON.stringify(l.id)} sits at ${JSON.stringify(d)} on the style axis, which the taxonomy does not declare; it draws in the fallback style` });
3850
+ }
3851
+ const c = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Map();
3852
+ for (const l of e.edges) {
3853
+ if (c.has(l.id)) {
3854
+ n.push({ severity: "error", code: "edge-id-duplicate", edgeId: l.id, message: `edge id ${JSON.stringify(l.id)} is used more than once` });
3855
+ continue;
3856
+ }
3857
+ c.add(l.id);
3858
+ const d = i.get(l.sourceId), u = i.get(l.targetId);
3859
+ if (!d || !u) {
3860
+ const p = [!d && l.sourceId, !u && l.targetId].filter(($) => typeof $ == "string");
3861
+ n.push({ severity: "error", code: "edge-endpoint-missing", edgeId: l.id, message: `edge ${JSON.stringify(l.id)} names ${p.map(($) => JSON.stringify($)).join(" and ")}, not in the graph` });
3862
+ continue;
3863
+ }
3864
+ if (l.relation !== void 0 && !kl.has(l.relation)) {
3865
+ n.push({ severity: "error", code: "edge-relation-unknown", edgeId: l.id, message: `edge ${JSON.stringify(l.id)} has relation ${JSON.stringify(l.relation)}; the engine knows "containment" and "dependency"` });
3866
+ continue;
3867
+ }
3868
+ const v = xn(l);
3869
+ if (v === "containment") {
3870
+ const p = a.get(l.sourceId) ?? /* @__PURE__ */ new Set();
3871
+ p.add(l.targetId), a.set(l.sourceId, p);
3872
+ }
3873
+ let M;
3874
+ try {
3875
+ M = t.edgeTypeOf(l, t.styleValueOf(d), t.styleValueOf(u));
3876
+ } catch (p) {
3877
+ n.push({ severity: "error", code: "edge-type-rule-threw", edgeId: l.id, message: `the taxonomy's classifyEdge rule threw on edge ${JSON.stringify(l.id)}: ${p instanceof Error ? p.message : String(p)}` });
3878
+ continue;
3879
+ }
3880
+ const S = M === void 0 ? void 0 : s.get(M);
3881
+ if (!S) {
3882
+ const p = M === void 0 ? "no declared type fits its endpoints and values" : `classifyEdge answered ${JSON.stringify(M)}, which edgeTypes does not declare`;
3883
+ n.push({ severity: "warning", code: "edge-type-unclassified", edgeId: l.id, message: `edge ${JSON.stringify(l.id)} has no type: ${p}; it draws in its relation's default stroke and pulls nothing while push and pull key on the style axis` });
3884
+ continue;
3885
+ }
3886
+ S.relation !== v && n.push({ severity: "error", code: "edge-type-relation-mismatch", edgeId: l.id, message: `edge ${JSON.stringify(l.id)} is a ${v} edge but resolves to type ${JSON.stringify(M)}, declared as ${S.relation}` });
3887
+ }
3888
+ for (const l of i.values()) {
3889
+ const d = a.get(l.id);
3890
+ l.parentId !== void 0 && d !== void 0 && !d.has(l.parentId) && n.push({ severity: "warning", code: "containment-parent-mismatch", nodeId: l.id, message: `node ${JSON.stringify(l.id)} has containment edges to ${[...d].map((u) => JSON.stringify(u)).join(" and ")} but its parentId is ${JSON.stringify(l.parentId)}` });
3891
+ }
3892
+ return n;
3893
+ }
3894
+ function El(e, t) {
3895
+ const n = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Set();
3896
+ for (const l of t)
3897
+ l.severity === "error" && (l.edgeId !== void 0 && n.add(l.edgeId), l.code === "parent-missing" && l.nodeId !== void 0 && s.add(l.nodeId), l.code === "node-id-duplicate" && l.nodeId !== void 0 && o.add(l.nodeId));
3898
+ if (n.size === 0 && s.size === 0 && o.size === 0) return e;
3899
+ const i = /* @__PURE__ */ new Set(), r = [];
3900
+ for (const l of e.nodes)
3901
+ o.has(l.id) && i.has(l.id) || (i.add(l.id), r.push(s.has(l.id) ? { ...l, parentId: void 0 } : l));
3902
+ const c = /* @__PURE__ */ new Set(), a = [];
3903
+ for (const l of e.edges)
3904
+ n.has(l.id) && c.has(l.id) || n.has(l.id) && !t.some((d) => d.edgeId === l.id && d.code === "edge-id-duplicate") || (c.add(l.id), a.push(l));
3905
+ return { nodes: r, edges: a };
3906
+ }
3907
+ function Il(e, t, n) {
3908
+ const s = new Set(t.edges), o = Pt(e.nodes), i = [];
3909
+ for (const a of e.edges) {
3910
+ if (s.has(a) || xn(a) !== "containment") continue;
3911
+ const l = o.get(a.sourceId), d = o.get(a.targetId);
3912
+ let u;
3913
+ try {
3914
+ u = n.edgeTypeOf(a, l && n.styleValueOf(l), d && n.styleValueOf(d));
3915
+ } catch {
3916
+ u = void 0;
3917
+ }
3918
+ const v = u === void 0 ? void 0 : n.edgeTypes.find((M) => M.id === u);
3919
+ (v === void 0 || v.relation !== "containment") && i.push(a.id);
3920
+ }
3921
+ if (i.length === 0) return [];
3922
+ const r = i.slice(0, 3).map((a) => JSON.stringify(a)).join(", "), c = i.length === 1;
3923
+ return [{
3924
+ severity: "warning",
3925
+ code: "containment-untyped",
3926
+ edgeId: i[0],
3927
+ message: `${i.length} derived containment edge${c ? "" : "s"} (${r}${i.length > 3 ? ", …" : ""}) ${c ? "has" : "have"} no type: no declared containment type runs between the child's value and the parent's; ${c ? "it draws" : "they draw"} in the containment stroke and pull${c ? "s" : ""} nothing while push and pull key on the style axis`
3928
+ }];
3929
+ }
3930
+ const Po = /* @__PURE__ */ new Set(), Yl = g.forwardRef(function({
3931
+ graph: t,
3932
+ taxonomy: n,
3933
+ keyboard: s = "pane",
3934
+ defaultPositions: o,
3935
+ counts: i,
3936
+ findings: r,
3937
+ groups: c,
3938
+ groupsControl: a,
3939
+ markedEdges: l,
3940
+ nodeAction: d,
3941
+ chrome: u,
3942
+ searchTitle: v = "Search nodes (/)",
3943
+ searchPlaceholder: M = "Search nodes...",
3944
+ selectedId: S,
3945
+ defaultSelectedId: p = null,
3946
+ focus: $,
3947
+ onFocusResult: D,
3948
+ className: x,
3949
+ style: V,
3950
+ filter: F,
3951
+ onFilterChange: L,
3952
+ defaultFilter: y,
3953
+ locks: I,
3954
+ onLocksChange: E,
3955
+ defaultLocks: O,
3956
+ overriddenLocks: X,
3957
+ axes: N,
3958
+ onAxesChange: k,
3959
+ defaultAxes: w,
3960
+ search: R,
3961
+ onSearchChange: z,
3962
+ defaultSearch: pe,
3963
+ theme: ke,
3964
+ onThemeChange: St,
3965
+ defaultTheme: Ne,
3966
+ systemTheme: ct,
3967
+ layout: at,
3968
+ onLayoutChange: lt,
3969
+ defaultLayout: Ie,
3970
+ onSelectionChange: dt,
3971
+ onNodeActivate: De,
3972
+ onHover: ht,
3973
+ onThemeResolved: b,
3974
+ onDiagnostics: T
3975
+ }, U) {
3976
+ const se = g.useContext(_n), G = n ?? se;
3977
+ if (!G)
3978
+ throw new Error("GraphView has no taxonomy: pass `taxonomy`, or mount it inside <TaxonomyContext.Provider value={…}>.");
3979
+ const oe = g.useMemo(() => Pt(t.nodes), [t]), [B, f] = Mt(F, void 0, () => y ?? Ps(G, t), "filter"), q = Ft(B, bn), te = Te(q), le = Te(L), Ee = F === void 0 || L !== void 0, Me = g.useCallback((m, P) => {
3980
+ var j;
3981
+ te.current = m, f(m), (j = le.current) == null || j.call(le, m, P);
3982
+ }, [te, f, le]), A = g.useRef(/* @__PURE__ */ new Set()), Oe = g.useCallback((m, P) => {
3983
+ for (const j of P) A.current.add(j);
3984
+ Me(m, P);
3985
+ }, [Me]), xe = g.useRef(y !== void 0), xt = g.useRef(t);
3986
+ g.useEffect(() => {
3987
+ if (xt.current === t || (xt.current = t, F !== void 0 || xe.current)) return;
3988
+ const m = Yo(q, G, t, A.current);
3989
+ m !== q && Me(m, []);
3990
+ }, [t]);
3991
+ const [Y, re] = Mt(I, E, () => O ?? /* @__PURE__ */ new Map(), "locks"), Qe = Ft(Y, Go), [Z, _e] = Mt(N, k, () => w ?? G.filterAxes.map((m) => m.id), "axes"), Be = Ft(Z, Xo), rn = N === void 0 || k !== void 0, [kt, et] = Mt(R, z, () => pe ?? { query: "", active: !1 }, "search"), [Ve, ye] = Mt(ke, St, () => Ne ?? "system", "theme"), Ue = kt.query, gt = kt.active, tt = g.useMemo(
3992
+ () => Be.flatMap((m) => {
3993
+ const P = G.axisFor(m);
3994
+ return P ? [P] : [];
3995
+ }),
3996
+ [Be, G]
3997
+ ), _ = {
3998
+ search: (u == null ? void 0 : u.search) ?? !0,
3999
+ locks: (u == null ? void 0 : u.locks) ?? (I !== void 0 && E !== void 0),
4000
+ transport: (u == null ? void 0 : u.transport) ?? !0,
4001
+ diagnostics: (u == null ? void 0 : u.diagnostics) ?? !0,
4002
+ shortcuts: (u == null ? void 0 : u.shortcuts) ?? !0,
4003
+ directionLine: (u == null ? void 0 : u.directionLine) ?? !0,
4004
+ activateZoom: (u == null ? void 0 : u.activateZoom) ?? !0,
4005
+ controls: (u == null ? void 0 : u.controls) ?? !0,
4006
+ themeToggle: (u == null ? void 0 : u.themeToggle) ?? !0
4007
+ }, { diagnostics: K, graph: H } = g.useMemo(() => {
4008
+ const m = Nl(t, G), P = Xi(El(t, m));
4009
+ return { diagnostics: [...m, ...Il(P, t, G)], graph: P };
4010
+ }, [t, G]), ne = g.useMemo(() => Pt(H.nodes), [H]), J = g.useMemo(() => _o(H.nodes, Be), [H, Be]), Q = i ?? J, ie = g.useMemo(() => Gi(H), [H]), { viewport: ee, setViewport: W, containerRef: ce, initialFitDone: $e, pendingCenterRef: Re, measure: de, fit: he } = ul(), ge = g.useRef(null), [ue, we] = g.useState(!1), be = g.useRef(null), [fe, Fe] = g.useState(0);
4011
+ Es(() => {
4012
+ const m = be.current;
4013
+ if (!m || typeof ResizeObserver > "u") return;
4014
+ const P = () => Fe(m.getBoundingClientRect().height);
4015
+ P();
4016
+ const j = new ResizeObserver(P);
4017
+ return j.observe(m), () => j.disconnect();
4018
+ }, []);
4019
+ const He = g.useRef(!1);
4020
+ Es(() => {
4021
+ const m = ce.current;
4022
+ if (!m || typeof ResizeObserver > "u") return;
4023
+ const P = () => {
4024
+ if (He.current || m.offsetParent === null) return;
4025
+ const { width: me, height: ve } = m.getBoundingClientRect();
4026
+ me > 0 && ve === 0 && (He.current = !0, console.warn("[force-graph] the pane measured 0 px tall: give its parent a height — the pane fills a flex column, or a block with a height."));
4027
+ };
4028
+ P();
4029
+ const j = new ResizeObserver(P);
4030
+ return j.observe(m), () => j.disconnect();
4031
+ }, []);
4032
+ const ae = Jo(q), Ce = g.useMemo(
4033
+ () => new Map(G.filterAxes.map((m) => [m.id, sn(H.nodes, m.id)])),
4034
+ [H, G]
4035
+ ), Ke = g.useCallback((m) => {
4036
+ m || ($e.current = !1);
4037
+ }, [$e]), [Xt, We] = Mt(at, lt, () => Ie ?? ar(G), "layout"), pt = Ft(Xt, Gc), Ge = Te(pt), kn = g.useCallback((m) => {
4038
+ const P = Ge.current, j = m(P.forces);
4039
+ if (j === P.forces) return;
4040
+ const me = zn(j, P.nodeScale);
4041
+ Ge.current = me, We(me);
4042
+ }, [Ge, We]), {
4043
+ simRef: Xe,
4044
+ simVersion: Nn,
4045
+ running: Nt,
4046
+ setRunning: cn,
4047
+ forceParams: Et,
4048
+ getNode: qn,
4049
+ onParamChange: Cr,
4050
+ onForceAdjust: Ar,
4051
+ onRelayout: Un,
4052
+ onNodeDragStart: Or,
4053
+ onNodeDragMove: Rr,
4054
+ onNodeDragEnd: Tr,
4055
+ onToggleRunning: Kn
4056
+ } = vl(H, G, o, Ke, pt.forces, kn), It = g.useMemo(() => $s(Et, G), [Et, G]), Wn = g.useMemo(() => Cc(G, H), [G, H]), Fr = g.useMemo(() => Oc(Wn, G), [Wn, G]), Us = g.useMemo(() => Cs(jo(H), It), [H, It]), nt = Ho(ce, Ve, ct), Lr = g.useMemo(() => zo(G, nt), [G, nt]), Pr = g.useMemo(() => hc(
4057
+ H.nodes,
4058
+ Et,
4059
+ It,
4060
+ Us,
4061
+ (m, P) => m.mapping.axis === G.styleAxis() && Fs(m.mapping) ? G.styleOf(P).color[nt].fill : void 0
4062
+ ), [H, Et, It, Us, G, nt]), Dr = g.useCallback((m) => {
4063
+ m.axis !== Et.pair.mapping.axis && Un({ pair: Sn(m) });
4064
+ }, [Et.pair.mapping.axis, Un]), Ks = pt.nodeScale, _r = g.useCallback((m) => {
4065
+ const P = Ge.current, j = zn(P.forces, { ...P.nodeScale, ...m });
4066
+ Ge.current = j, We(j);
4067
+ }, [Ge, We]), [Zn, Qn] = g.useState(Po);
4068
+ g.useEffect(() => {
4069
+ if (Zn.size === 0) return;
4070
+ const m = setTimeout(() => Qn(Po), 600);
4071
+ return () => clearTimeout(m);
4072
+ }, [Zn]), g.useEffect(() => {
4073
+ X && X.size > 0 && Qn((m) => /* @__PURE__ */ new Set([...m, ...X]));
4074
+ }, [X]);
4075
+ const { visibleNodes: st, visibleEdges: mt, visibleIds: wt, edgeTypes: Ws, origins: Zs, nodeSummaries: Br, downstreamScores: Hr } = Ml(Xe, Nn, q, tt, G), zr = g.useMemo(() => {
4076
+ const m = /* @__PURE__ */ new Set();
4077
+ if (l)
4078
+ for (const P of mt) l.has(Zs.get(P.id)) && m.add(P.id);
4079
+ return m;
4080
+ }, [l, mt, Zs]), Vr = g.useMemo(() => {
4081
+ const m = /* @__PURE__ */ new Map();
4082
+ for (const P of mt) {
4083
+ const j = Ws.get(P.id);
4084
+ m.set(P, j !== void 0 ? G.edgeStrokeFor(j) : it(P) ? Ko : wn);
4085
+ }
4086
+ return m;
4087
+ }, [mt, Ws, G]), Gr = g.useMemo(() => {
4088
+ const m = /* @__PURE__ */ new Map();
4089
+ for (const j of mt) {
4090
+ if (it(j)) continue;
4091
+ const me = j.sourceId < j.targetId ? `${j.sourceId}|${j.targetId}` : `${j.targetId}|${j.sourceId}`, ve = m.get(me);
4092
+ ve ? ve.push(j.id) : m.set(me, [j.id]);
4093
+ }
4094
+ const P = /* @__PURE__ */ new Map();
4095
+ for (const j of m.values())
4096
+ j.length < 2 || j.forEach((me, ve) => P.set(me, (ve - (j.length - 1) / 2) * 7));
4097
+ return P;
4098
+ }, [mt]), Qs = g.useMemo(() => cr(H.edges, wt), [H, wt]), Xr = g.useMemo(
4099
+ () => kc(st, Qs, It, qn),
4100
+ [st, Qs, It, G, qn]
4101
+ ), an = S !== void 0;
4102
+ Bo("selectedId", an);
4103
+ const [es, eo] = g.useState(p), $t = an ? S : es, to = Te($t), Ht = Te(dt), ts = Te(oe), Ct = g.useCallback((m) => {
4104
+ var P;
4105
+ m !== null && !ts.current.has(m) || (an || eo(m), m !== to.current && ((P = Ht.current) == null || P.call(Ht, m === null ? null : ts.current.get(m) ?? null)));
4106
+ }, [an, ts, to, Ht]);
4107
+ g.useEffect(() => {
4108
+ var m;
4109
+ an || es === null || oe.has(es) || (eo(null), (m = Ht.current) == null || m.call(Ht, null));
4110
+ }, [oe]);
4111
+ const {
4112
+ hoveredNodeId: At,
4113
+ setHoveredNodeId: ns,
4114
+ setFocusedIndex: no,
4115
+ shiftHeld: Yr,
4116
+ focusedNodeId: En,
4117
+ highlightedNodes: Jr,
4118
+ highlightedEdges: jr,
4119
+ activeSection: qr,
4120
+ setActiveSection: Ur,
4121
+ activePushBucket: Kr,
4122
+ setActivePushBucket: Wr,
4123
+ activeGravityBucket: Zr,
4124
+ setActiveGravityBucket: Qr,
4125
+ activePullEdge: ei,
4126
+ setActivePullEdge: ti
4127
+ } = pl(st, mt, wt, qn, H, G, $t, oe), [so, ni] = g.useState(null), si = g.useMemo(() => ({ emphasize: ni }), []), ss = g.useMemo(() => ll(c ?? [], wt, nt, so), [c, wt, nt, so]), oi = g.useMemo(
4128
+ () => dl(ss, [At, $t]),
4129
+ [ss, At, $t]
4130
+ ), { visibleMatchIds: In, hiddenMatchCount: $n, hiddenMatches: ri } = g.useMemo(() => {
4131
+ const m = /* @__PURE__ */ new Map();
4132
+ if (!Ue) return { visibleMatchIds: null, hiddenMatchCount: 0, hiddenMatches: m };
4133
+ const P = Ue.toLowerCase(), j = Xe.current;
4134
+ if (!j) return { visibleMatchIds: /* @__PURE__ */ new Set(), hiddenMatchCount: 0, hiddenMatches: m };
4135
+ const me = Fi({ nodes: j.nodes, filter: q, taxonomy: G, axes: Be, visibleIds: wt, matches: (ve) => G.searchText(oe.get(ve.id) ?? ve).toLowerCase().includes(P) });
4136
+ return { visibleMatchIds: me.visible, hiddenMatchCount: me.hiddenCount, hiddenMatches: me.hiddenByAxis };
4137
+ }, [Ue, wt, q, Be, G, oe]), { fps: ii } = Sl({
4138
+ simRef: Xe,
4139
+ running: Nt,
4140
+ setRunning: cn,
4141
+ visibleIds: wt,
4142
+ visibleNodes: st,
4143
+ downstreamScores: Hr,
4144
+ filter: q,
4145
+ axes: tt,
4146
+ hoveredNodeId: At,
4147
+ selectedNodeId: $t,
4148
+ measure: de,
4149
+ initialFitDone: $e,
4150
+ pendingCenterRef: Re,
4151
+ setViewport: W,
4152
+ setSelectedNodeId: Ct,
4153
+ taxonomy: G
4154
+ }), os = Te(ht), rs = Te(De), is = Te(b), cs = Te(T), oo = g.useRef(!1);
4155
+ g.useEffect(() => {
4156
+ var m;
4157
+ oo.current && ((m = os.current) == null || m.call(os, At === null ? null : oe.get(At) ?? null));
4158
+ }, [At]), g.useEffect(() => {
4159
+ oo.current = !0;
4160
+ }, []), g.useEffect(() => {
4161
+ var m;
4162
+ (m = is.current) == null || m.call(is, nt);
4163
+ }, [nt]), g.useEffect(() => {
4164
+ var m;
4165
+ (m = cs.current) == null || m.call(cs, K);
4166
+ }, [K]);
4167
+ const ci = g.useCallback((m) => {
4168
+ var Ae;
4169
+ const P = Xe.current;
4170
+ if (!P || !P.getNode(m)) return;
4171
+ const me = oe.get(m);
4172
+ me && ((Ae = rs.current) == null || Ae.call(rs, me));
4173
+ const ve = /* @__PURE__ */ new Set([m]);
4174
+ for (const Le of P.edges)
4175
+ Le.sourceId === m && ve.add(Le.targetId), Le.targetId === m && ve.add(Le.sourceId);
4176
+ if (!_.activateZoom) return;
4177
+ const Se = P.nodes.filter((Le) => ve.has(Le.id));
4178
+ he(Se, 80);
4179
+ }, [he, oe, _.activateZoom]), Cn = g.useCallback(() => {
4180
+ he(st);
4181
+ }, [he, st]), ai = () => {
4182
+ gt ? et({ query: "", active: !1 }) : (et({ query: Ue, active: !0 }), setTimeout(() => {
4183
+ var m;
4184
+ return (m = ge.current) == null ? void 0 : m.focus();
4185
+ }, 50));
4186
+ }, ln = g.useRef(null), as = g.useCallback(() => {
4187
+ ln.current !== null && (clearTimeout(ln.current), ln.current = null);
4188
+ }, []), ro = g.useCallback((m) => {
4189
+ as(), m !== null ? ns(m) : ln.current = window.setTimeout(() => {
4190
+ ns(null), ln.current = null;
4191
+ }, 150);
4192
+ }, [as, ns]), li = (m) => {
4193
+ Ct(m);
4194
+ const P = Xe.current, j = P == null ? void 0 : P.getNode(m), me = j && de();
4195
+ if (!j || !me) return;
4196
+ const { width: ve, height: Se } = me;
4197
+ W({
4198
+ scale: ee.scale,
4199
+ x: ve / 2 - j.x * ee.scale,
4200
+ y: Se / 2 - j.y * ee.scale
4201
+ });
4202
+ }, io = Te(st), ls = g.useCallback((m) => {
4203
+ var Ae;
4204
+ const P = ne.get(m);
4205
+ if (!P) return !1;
4206
+ const j = te.current, me = qo({ destination: j, source: j, locks: Qe, transition: { kind: "focus", target: { values: P.values } }, taxonomy: G, axes: Be, graph: H }), ve = Ee ? me.filter : j;
4207
+ return ve !== j && (Me(ve, []), me.overriddenLocks.size > 0 && Qn(me.overriddenLocks)), Xn(ve, tt, (Le) => G.valueOn(P, Le)) ? (Re.current = { nodeId: m }, Nt || ((Ae = Xe.current) == null || Ae.reheat(0.1), cn(!0)), !0) : !1;
4208
+ }, [ne, H, te, Ee, Me, Qe, Be, tt, Nt, cn, Xe, Re, G]), An = g.useRef(null), On = g.useRef(null), ds = Te(D);
4209
+ g.useEffect(() => {
4210
+ if (!$) {
4211
+ An.current = null, On.current = null;
4212
+ return;
4213
+ }
4214
+ Lo(An.current, $) || (An.current = $, On.current = $);
4215
+ }, [$]);
4216
+ const [dn, co] = g.useState(null);
4217
+ g.useEffect(() => {
4218
+ const m = On.current;
4219
+ !m || !ne.has(m.id) || (On.current = null, co(m));
4220
+ }, [$, ne]), g.useEffect(() => {
4221
+ var m;
4222
+ dn && (co(null), Lo(An.current, dn) && ((m = ds.current) == null || m.call(ds, dn, ls(dn.id))));
4223
+ }, [dn]), g.useImperativeHandle(U, () => ({
4224
+ focusNode: ls,
4225
+ select: Ct,
4226
+ fit: () => he(io.current),
4227
+ getPositions: () => {
4228
+ var m;
4229
+ return new Map((((m = Xe.current) == null ? void 0 : m.nodes) ?? []).map((P) => [P.id, { x: P.x, y: P.y }]));
4230
+ },
4231
+ setPositions: (m) => {
4232
+ const P = Xe.current;
4233
+ if (P) {
4234
+ for (const [j, me] of m) {
4235
+ const ve = P.getNode(j);
4236
+ !ve || ve.pinned || (ve.x = me.x, ve.y = me.y, ve.vx = 0, ve.vy = 0);
4237
+ }
4238
+ P.reheat(0.1), cn(!0);
4239
+ }
4240
+ }
4241
+ }), [ls, he, cn, Ct, Xe, io]);
4242
+ const un = g.useCallback((m) => {
4243
+ var me, ve;
4244
+ if (m.metaKey || m.ctrlKey || m.altKey) return;
4245
+ const P = m.target instanceof Element ? m.target : null;
4246
+ if (!(P instanceof HTMLInputElement || P instanceof HTMLTextAreaElement || P !== null && P !== ce.current && P.closest('button, select, a, [contenteditable], [role="tab"]') !== null && m.key !== "Escape"))
4247
+ switch (m.key) {
4248
+ case "Tab": {
4249
+ if (P !== ce.current) return;
4250
+ m.preventDefault();
4251
+ const Se = st.length;
4252
+ if (Se === 0) return;
4253
+ m.shiftKey ? no((Ae) => Ae > 0 ? Ae - 1 : Se - 1) : no((Ae) => Ae < Se - 1 ? Ae + 1 : 0);
4254
+ break;
4255
+ }
4256
+ case "Enter": {
4257
+ m.preventDefault(), En && Ct(En);
4258
+ break;
4259
+ }
4260
+ case "Escape": {
4261
+ if (ue) {
4262
+ m.preventDefault(), we(!1);
4263
+ break;
4264
+ }
4265
+ if (gt) {
4266
+ m.preventDefault(), ai();
4267
+ break;
4268
+ }
4269
+ if ($t) {
4270
+ m.preventDefault(), Ct(null);
4271
+ break;
4272
+ }
4273
+ s === "pane" && ((me = ce.current) == null || me.blur());
4274
+ break;
4275
+ }
4276
+ case "ArrowLeft":
4277
+ case "ArrowRight":
4278
+ case "ArrowUp":
4279
+ case "ArrowDown": {
4280
+ m.preventDefault();
4281
+ const Se = 30, Ae = m.key === "ArrowLeft" ? Se : m.key === "ArrowRight" ? -Se : 0, Le = m.key === "ArrowUp" ? Se : m.key === "ArrowDown" ? -Se : 0;
4282
+ W((us) => ({ ...us, x: us.x + Ae, y: us.y + Le }));
4283
+ break;
4284
+ }
4285
+ case "+":
4286
+ case "=": {
4287
+ m.preventDefault(), W((Se) => {
4288
+ var Ae, Le;
4289
+ return As(Se, (((Ae = ce.current) == null ? void 0 : Ae.clientWidth) ?? 400) / 2, (((Le = ce.current) == null ? void 0 : Le.clientHeight) ?? 400) / 2, 1.15);
4290
+ });
4291
+ break;
4292
+ }
4293
+ case "-":
4294
+ case "_": {
4295
+ m.preventDefault(), W((Se) => {
4296
+ var Ae, Le;
4297
+ return As(Se, (((Ae = ce.current) == null ? void 0 : Ae.clientWidth) ?? 400) / 2, (((Le = ce.current) == null ? void 0 : Le.clientHeight) ?? 400) / 2, 0.85);
4298
+ });
4299
+ break;
4300
+ }
4301
+ case "f":
4302
+ case "F": {
4303
+ m.preventDefault(), Cn();
4304
+ break;
4305
+ }
4306
+ case "/": {
4307
+ if (!_.search) break;
4308
+ m.preventDefault(), gt ? (ve = ge.current) == null || ve.focus() : (et({ query: Ue, active: !0 }), setTimeout(() => {
4309
+ var Se;
4310
+ return (Se = ge.current) == null ? void 0 : Se.focus();
4311
+ }, 50));
4312
+ break;
4313
+ }
4314
+ case " ": {
4315
+ m.preventDefault(), Kn();
4316
+ break;
4317
+ }
4318
+ case "?": {
4319
+ if (!_.shortcuts) break;
4320
+ m.preventDefault(), we((Se) => !Se);
4321
+ break;
4322
+ }
4323
+ }
4324
+ }, [s, st, En, $t, Ct, gt, Ue, et, ue, _.search, _.shortcuts, Cn, Kn]);
4325
+ g.useEffect(() => {
4326
+ if (s === "global")
4327
+ return window.addEventListener("keydown", un), () => window.removeEventListener("keydown", un);
4328
+ }, [s, un]);
4329
+ const di = g.useCallback((m) => un(m.nativeEvent), [un]), ui = g.useCallback((m) => {
4330
+ const P = oe.get(m.id) ?? m, j = typeof d == "function" ? d(P) : d ?? null;
4331
+ return j && { label: j.label, onSelect: () => j.onSelect(P) };
4332
+ }, [d, oe]), fi = g.useCallback((m) => oe.get(m), [oe]), ao = st.length, lo = mt.length, hi = $n > 0 ? /* @__PURE__ */ C("span", { className: "gv-header-search-badge", title: `${$n} match${$n !== 1 ? "es" : ""} hidden by filters`, children: [
4333
+ "+",
4334
+ $n
4335
+ ] }) : null;
4336
+ return /* @__PURE__ */ h(_n.Provider, { value: G, children: /* @__PURE__ */ h(No, { what: "graph view", children: /* @__PURE__ */ C(
4337
+ "div",
4338
+ {
4339
+ className: `gv-graph-view${x ? ` ${x}` : ""}`,
4340
+ ref: ce,
4341
+ "data-theme": nt,
4342
+ tabIndex: s === "pane" ? 0 : void 0,
4343
+ onKeyDown: s === "pane" ? di : void 0,
4344
+ style: { ...Lr, ...fe ? { "--gv-toolbar-height": `${fe}px` } : {}, ...V },
4345
+ children: [
4346
+ /* @__PURE__ */ C("div", { className: "gv-graph-canvas-area", children: [
4347
+ /* @__PURE__ */ h(No, { children: /* @__PURE__ */ h(
4348
+ xa,
4349
+ {
4350
+ nodes: st,
4351
+ edges: mt,
4352
+ viewport: ee,
4353
+ onViewportChange: W,
4354
+ onNodeDragStart: Or,
4355
+ onNodeDragMove: Rr,
4356
+ onNodeDragEnd: Tr,
4357
+ onDoubleClickNode: ci,
4358
+ onFitView: Cn,
4359
+ onHoverNode: ro,
4360
+ onSelectNode: Ct,
4361
+ highlightedNodes: Jr,
4362
+ highlightedEdges: jr,
4363
+ hoveredNodeId: At,
4364
+ selectedNodeId: $t,
4365
+ focusedNodeId: En,
4366
+ searchMatchIds: In,
4367
+ running: Nt,
4368
+ forceParams: Et,
4369
+ resolved: It,
4370
+ overlay: Pr,
4371
+ theme: nt,
4372
+ edgeStrokes: Vr,
4373
+ edgeOffsets: Gr,
4374
+ activeSection: qr,
4375
+ activePushBucket: Kr,
4376
+ activeGravityBucket: Zr,
4377
+ activePullEdge: ei,
4378
+ nodeScale: Ks,
4379
+ groupGlows: oi,
4380
+ markedEdges: zr
4381
+ }
4382
+ ) }),
4383
+ /* @__PURE__ */ h(
4384
+ Cl,
4385
+ {
4386
+ hoveredNodeId: At,
4387
+ simRef: Xe,
4388
+ visibleEdges: mt,
4389
+ visibleIds: wt,
4390
+ viewport: ee,
4391
+ shiftHeld: Yr,
4392
+ directionLine: _.directionLine,
4393
+ copies: ie,
4394
+ nodeSummaries: Br,
4395
+ nodeAction: ui,
4396
+ hostNodeOf: fi,
4397
+ onMouseEnter: as,
4398
+ onMouseLeave: () => ro(null)
4399
+ }
4400
+ )
4401
+ ] }),
4402
+ /* @__PURE__ */ C("div", { className: "gv-graph-overlay", ref: be, children: [
4403
+ /* @__PURE__ */ h("div", { className: "gv-graph-toolbar", children: /* @__PURE__ */ h(
4404
+ Vi,
4405
+ {
4406
+ chrome: { search: _.search, locks: _.locks },
4407
+ theme: nt,
4408
+ counts: Q,
4409
+ values: Ce,
4410
+ filter: q,
4411
+ onFilterChange: Oe,
4412
+ locks: Qe,
4413
+ onLocksChange: re,
4414
+ axes: Be,
4415
+ onAxesChange: rn ? _e : void 0,
4416
+ overriddenLocks: Zn,
4417
+ recentlyChanged: ae,
4418
+ search: kt,
4419
+ onSearchChange: et,
4420
+ searchInputRef: ge,
4421
+ searchTitle: v,
4422
+ searchPlaceholder: M,
4423
+ searchExtra: hi,
4424
+ hiddenMatches: ri,
4425
+ findings: r
4426
+ }
4427
+ ) }),
4428
+ _.diagnostics && K.length > 0 && /* @__PURE__ */ h($l, { diagnostics: K }),
4429
+ In && In.size > 0 && gt && /* @__PURE__ */ h("div", { className: "gv-graph-search-results", children: st.filter((m) => In.has(m.id)).map((m) => /* @__PURE__ */ C(
4430
+ "button",
4431
+ {
4432
+ className: "gv-graph-search-result",
4433
+ onClick: () => li(m.id),
4434
+ children: [
4435
+ /* @__PURE__ */ h("span", { className: "gv-graph-search-result-type", children: G.nodeStyleOf(m).label }),
4436
+ /* @__PURE__ */ h("span", { className: "gv-graph-search-result-name", children: m.name })
4437
+ ]
4438
+ },
4439
+ m.id
4440
+ )) })
4441
+ ] }),
4442
+ _.transport && /* @__PURE__ */ h("div", { className: `gv-graph-bottom-left${ue ? " shifted" : ""}`, children: /* @__PURE__ */ C("span", { className: "gv-graph-count", children: [
4443
+ ao,
4444
+ " node",
4445
+ ao !== 1 ? "s" : "",
4446
+ ", ",
4447
+ lo,
4448
+ " edge",
4449
+ lo !== 1 ? "s" : ""
4450
+ ] }) }),
4451
+ _.transport && /* @__PURE__ */ C("div", { className: "gv-graph-bottom-center", children: [
4452
+ /* @__PURE__ */ h("button", { className: "gv-graph-toolbar-btn", onClick: Cn, title: "Fit to view (F)", children: "Fit" }),
4453
+ _.themeToggle && /* @__PURE__ */ h(
4454
+ "button",
4455
+ {
4456
+ className: `gv-graph-toolbar-btn${Ve === "system" ? "" : " active"}`,
4457
+ onClick: () => ye(Ln[(Ln.indexOf(Ve) + 1) % Ln.length]),
4458
+ title: `Colour scheme: ${Ve}${Ve === "system" ? ` (${nt})` : ""} — click to change`,
4459
+ "aria-label": "Colour scheme",
4460
+ children: Ve === "system" ? "Auto" : Ve === "light" ? "Light" : "Dark"
4461
+ }
4462
+ ),
4463
+ /* @__PURE__ */ h(
4464
+ "button",
4465
+ {
4466
+ className: `gv-graph-toolbar-btn ${Nt ? "active" : ""}`,
4467
+ onClick: Kn,
4468
+ title: Nt ? "Pause simulation (Space)" : "Resume simulation (Space)",
4469
+ children: Nt ? "Pause" : "Play"
4470
+ }
4471
+ ),
4472
+ /* @__PURE__ */ C("span", { className: `gv-graph-count-fps${Nt ? "" : " hidden"}`, title: "Simulation frames per second", children: [
4473
+ ii,
4474
+ " fps"
4475
+ ] })
4476
+ ] }),
4477
+ _.controls && /* @__PURE__ */ h(
4478
+ rl,
4479
+ {
4480
+ params: Et,
4481
+ resolved: It,
4482
+ onParamChange: Cr,
4483
+ onAdjust: Ar,
4484
+ onRelayout: Un,
4485
+ axes: Wn,
4486
+ layoutAxes: Fr,
4487
+ present: Xr,
4488
+ onAxisChange: Dr,
4489
+ onActiveSection: Ur,
4490
+ onActivePushBucket: Wr,
4491
+ onActiveGravityBucket: Qr,
4492
+ onActivePullEdge: ti,
4493
+ nodeScale: Ks,
4494
+ onNodeScaleChange: _r
4495
+ }
4496
+ ),
4497
+ a == null ? void 0 : a(ss, si),
4498
+ _.shortcuts && ue && /* @__PURE__ */ C("div", { className: "gv-graph-shortcuts-panel", children: [
4499
+ /* @__PURE__ */ C("div", { className: "gv-graph-shortcuts-title", children: [
4500
+ "Keyboard Shortcuts",
4501
+ /* @__PURE__ */ h("button", { className: "gv-graph-shortcuts-close", onClick: () => we(!1), children: "×" })
4502
+ ] }),
4503
+ /* @__PURE__ */ C("div", { className: "gv-graph-shortcuts-list", children: [
4504
+ /* @__PURE__ */ h(vt, { keys: "Tab / Shift+Tab", desc: "Cycle focus" }),
4505
+ /* @__PURE__ */ h(vt, { keys: "Enter", desc: "Select focused node" }),
4506
+ /* @__PURE__ */ h(vt, { keys: "Escape", desc: "Deselect / close" }),
4507
+ /* @__PURE__ */ h(vt, { keys: "Arrow keys", desc: "Pan viewport" }),
4508
+ /* @__PURE__ */ h(vt, { keys: "+ / -", desc: "Zoom in / out" }),
4509
+ /* @__PURE__ */ h(vt, { keys: "F", desc: "Fit to view" }),
4510
+ _.search && /* @__PURE__ */ h(vt, { keys: "/", desc: "Open search" }),
4511
+ /* @__PURE__ */ h(vt, { keys: "Space", desc: "Toggle simulation" }),
4512
+ /* @__PURE__ */ h(vt, { keys: "Shift + hover", desc: "Upstream deps" }),
4513
+ /* @__PURE__ */ h(vt, { keys: "?", desc: "This panel" })
4514
+ ] })
4515
+ ] })
4516
+ ]
4517
+ }
4518
+ ) }) });
4519
+ });
4520
+ function $l({ diagnostics: e }) {
4521
+ const t = e.filter((o) => o.severity === "error").length, n = e.length - t, s = [];
4522
+ return t > 0 && s.push(`${t} graph error${t === 1 ? "" : "s"}`), n > 0 && s.push(`${n} graph warning${n === 1 ? "" : "s"}`), /* @__PURE__ */ C("details", { className: `gv-graph-diagnostics${t > 0 ? " has-errors" : ""}`, role: t > 0 ? "alert" : void 0, children: [
4523
+ /* @__PURE__ */ C("summary", { children: [
4524
+ s.join(", "),
4525
+ t > 0 ? " — what is named is not drawn" : ""
4526
+ ] }),
4527
+ /* @__PURE__ */ h("ul", { children: e.map((o, i) => /* @__PURE__ */ C("li", { className: `gv-graph-diagnostic ${o.severity}`, children: [
4528
+ /* @__PURE__ */ h("code", { children: o.code }),
4529
+ o.message
4530
+ ] }, i)) })
4531
+ ] });
4532
+ }
4533
+ function Cl({ hoveredNodeId: e, simRef: t, visibleEdges: n, visibleIds: s, viewport: o, shiftHeld: i, directionLine: r, copies: c, nodeSummaries: a, nodeAction: l, hostNodeOf: d, onMouseEnter: u, onMouseLeave: v }) {
4534
+ const M = Bt();
4535
+ if (!e) return null;
4536
+ const S = t.current;
4537
+ if (!S) return null;
4538
+ const p = S.getNode(e);
4539
+ if (!p) return null;
4540
+ const $ = p.parentId === void 0 ? void 0 : d(p.parentId) ?? S.getNode(p.parentId), D = M.contextLine(d(p.id) ?? p, $), x = D == null ? [] : Array.isArray(D) ? [...D] : [D], V = l(p), F = M.nodeStyleOf(p).icon, L = M.nodeStyleOf(p).summaryKind, y = L === "children" && a.get(e) || void 0, I = p.badges && p.badges.length > 0 ? p.badges.join(" ") : void 0;
4541
+ let E = 0, O = 0;
4542
+ for (const pe of n)
4543
+ it(pe) || (pe.sourceId === e && E++, pe.targetId === e && O++);
4544
+ const X = c.get(Vt(p)), N = X ? Array.from(X).filter((pe) => s.has(pe)) : [p.id], k = N.length, w = k > 1 ? N.indexOf(p.id) + 1 : 0, [R, z] = Ye(o, p.x, p.y);
4545
+ return /* @__PURE__ */ C(
4546
+ "div",
4547
+ {
4548
+ className: "gv-graph-hover-tooltip",
4549
+ style: { left: R, top: z },
4550
+ onMouseEnter: u,
4551
+ onMouseLeave: v,
4552
+ children: [
4553
+ /* @__PURE__ */ C("div", { className: "gv-tooltip-identity", children: [
4554
+ F && /* @__PURE__ */ h("span", { className: "gv-tooltip-type-icon", children: F }),
4555
+ /* @__PURE__ */ h("span", { className: "gv-tooltip-name", children: p.name })
4556
+ ] }),
4557
+ x.map((pe, ke) => /* @__PURE__ */ h("div", { className: "gv-tooltip-parent", children: pe }, ke)),
4558
+ y && /* @__PURE__ */ h("div", { className: "gv-tooltip-summary", children: y }),
4559
+ I && /* @__PURE__ */ h("div", { className: "gv-tooltip-summary", children: I }),
4560
+ k > 1 && /* @__PURE__ */ C("div", { className: "gv-tooltip-duplicates", title: "The same entity appears in more than one place. Hovering any copy marks all copies.", children: [
4561
+ "copy ",
4562
+ w,
4563
+ " of ",
4564
+ k
4565
+ ] }),
4566
+ L !== "none" && (E > 0 || O > 0) && /* @__PURE__ */ C("div", { className: "gv-tooltip-connections", children: [
4567
+ E > 0 && /* @__PURE__ */ C("span", { className: "gv-tooltip-conn-out", children: [
4568
+ "→",
4569
+ E
4570
+ ] }),
4571
+ O > 0 && /* @__PURE__ */ C("span", { className: "gv-tooltip-conn-in", children: [
4572
+ "←",
4573
+ O
4574
+ ] })
4575
+ ] }),
4576
+ r && /* @__PURE__ */ h("div", { className: "gv-tooltip-direction", children: i ? "dependents" : "dependencies" }),
4577
+ V && /* @__PURE__ */ h(
4578
+ "button",
4579
+ {
4580
+ className: "gv-tooltip-cross-view",
4581
+ onClick: () => V.onSelect(p),
4582
+ title: V.label,
4583
+ children: V.label
4584
+ }
4585
+ )
4586
+ ]
4587
+ }
4588
+ );
4589
+ }
4590
+ function vt({ keys: e, desc: t }) {
4591
+ return /* @__PURE__ */ C("div", { className: "gv-graph-shortcut-row", children: [
4592
+ /* @__PURE__ */ h("kbd", { className: "gv-graph-shortcut-key", children: e }),
4593
+ /* @__PURE__ */ h("span", { className: "gv-graph-shortcut-desc", children: t })
4594
+ ] });
4595
+ }
4596
+ function Jl({ items: e, active: t, enabled: n, onToggle: s, onEmphasize: o, title: i, className: r }) {
4597
+ const c = g.useMemo(() => new Map(t.map((l) => [l.id, l.color])), [t]), a = g.useRef(o);
4598
+ return a.current = o, g.useEffect(() => () => {
4599
+ var l;
4600
+ return (l = a.current) == null ? void 0 : l.call(a, null);
4601
+ }, []), /* @__PURE__ */ C("div", { className: `gv-group-legend${r ? ` ${r}` : ""}`, onMouseLeave: o ? () => o(null) : void 0, children: [
4602
+ i && /* @__PURE__ */ h("div", { className: "gv-group-legend-title", children: i }),
4603
+ e.map((l) => {
4604
+ const d = n === void 0 || n.has(l.id), u = c.get(l.id);
4605
+ return /* @__PURE__ */ C(s ? "label" : "div", { className: `gv-group-legend-row${d ? "" : " off"}`, onMouseEnter: o ? () => o(l.id) : void 0, children: [
4606
+ s && /* @__PURE__ */ h("input", { type: "checkbox", checked: d, onChange: () => s(l.id) }),
4607
+ /* @__PURE__ */ h("span", { className: "gv-group-legend-swatch", style: { background: u ?? "transparent" } }),
4608
+ /* @__PURE__ */ h("span", { className: "gv-group-legend-label", children: l.label }),
4609
+ d && u === void 0 && /* @__PURE__ */ h("span", { className: "gv-group-legend-note", children: "not shown" })
4610
+ ] }, l.id);
4611
+ })
4612
+ ] });
4613
+ }
4614
+ const $r = /* @__PURE__ */ new Set();
4615
+ function Do(e, t, n, s, o, i) {
4616
+ const r = e[n], c = qo({
4617
+ destination: r.filter,
4618
+ source: e[s].filter,
4619
+ locks: r.locks,
4620
+ transition: o,
4621
+ taxonomy: t,
4622
+ axes: r.axes,
4623
+ graph: i
4624
+ }), a = c.overriddenLocks.size > 0 ? c.overriddenLocks : $r, l = a === r.overriddenLocks || a.size === 0 && r.overriddenLocks.size === 0;
4625
+ return c.filter === r.filter && l ? { state: e, result: c } : { state: { ...e, [n]: { ...r, filter: c.filter, overriddenLocks: a } }, result: c };
4626
+ }
4627
+ function fn(e, t) {
4628
+ const n = /* @__PURE__ */ Object.create(null);
4629
+ for (const s of e) n[s] = t(s);
4630
+ return n;
4631
+ }
4632
+ function jl({ taxonomy: e, views: t, initial: n, graph: s, start: o, initialSearch: i }) {
4633
+ const r = g.useRef(fn(t, () => /* @__PURE__ */ new Set())), [c, a] = g.useState(() => fn(t, (k) => {
4634
+ const w = n == null ? void 0 : n(k), R = Ps(e, s ?? { nodes: [] });
4635
+ if ((w == null ? void 0 : w.filter) !== void 0) for (const z of Oi(R, w.filter)) r.current[k].add(z);
4636
+ return {
4637
+ filter: (w == null ? void 0 : w.filter) ?? R,
4638
+ locks: (w == null ? void 0 : w.locks) ?? /* @__PURE__ */ new Map(),
4639
+ axes: (w == null ? void 0 : w.axes) ?? e.filterAxes.map((z) => z.id),
4640
+ overriddenLocks: $r
4641
+ };
4642
+ })), [l, d] = g.useState(() => o ?? t[0]), [u, v] = g.useState(() => i ?? { query: "", active: !1 }), [M, S] = g.useState(() => fn(t, () => null)), p = g.useRef(0), $ = Te(c), D = Te(l), x = Te(e), V = Te(s), F = t.join("\0"), L = g.useMemo(() => fn(t, (k) => ({
4643
+ onFilterChange: (w, R = []) => {
4644
+ for (const z of R) r.current[k].add(z);
4645
+ a((z) => z[k].filter === w ? z : { ...z, [k]: { ...z[k], filter: w } });
4646
+ },
4647
+ onLocksChange: (w) => a((R) => R[k].locks === w ? R : { ...R, [k]: { ...R[k], locks: w } }),
4648
+ onAxesChange: (w) => a((R) => R[k].axes === w ? R : { ...R, [k]: { ...R[k], axes: w } }),
4649
+ onSearchChange: v,
4650
+ // The request is spent once the pane reports it, so a pane that mounts
4651
+ // again later does not act on it twice.
4652
+ onFocusResult: (w) => S((R) => R[k] === w ? { ...R, [k]: null } : R)
4653
+ })), [F]), y = g.useMemo(() => fn(t, (k) => ({ ...c[k], ...L[k], search: u, focus: M[k] })), [c, L, u, M]), I = g.useRef(s);
4654
+ g.useEffect(() => {
4655
+ I.current === s || s === void 0 || (I.current = s, a((k) => {
4656
+ let w = !1;
4657
+ const R = { ...k };
4658
+ for (const z of Object.keys(k)) {
4659
+ const pe = Yo(k[z].filter, x.current, s, r.current[z]);
4660
+ pe !== k[z].filter && (w = !0, R[z] = { ...k[z], filter: pe });
4661
+ }
4662
+ return w ? R : k;
4663
+ }));
4664
+ }, [s]);
4665
+ const E = g.useCallback((k, w = { kind: "manual" }) => {
4666
+ const R = D.current, { state: z, result: pe } = Do($.current, x.current, k, R, w, V.current);
4667
+ return $.current = z, a((ke) => Do(ke, x.current, k, R, w, V.current).state), D.current = k, d(k), pe;
4668
+ }, [$, D, x, V]), O = g.useCallback((k, w) => {
4669
+ const R = E(k, { kind: "focus", target: { values: w.values } });
4670
+ return S((z) => ({ ...z, [k]: { id: w.id, key: ++p.current } })), R;
4671
+ }, [E]), X = g.useCallback((k, w) => {
4672
+ a((R) => {
4673
+ const z = w(R[k].filter);
4674
+ return z === R[k].filter ? R : { ...R, [k]: { ...R[k], filter: z } };
4675
+ });
4676
+ }, []), N = g.useCallback((k) => {
4677
+ a((w) => {
4678
+ let R = !1;
4679
+ const z = { ...w };
4680
+ for (const pe of Object.keys(w)) {
4681
+ const ke = k(w[pe].filter, pe);
4682
+ ke !== w[pe].filter && (R = !0, z[pe] = { ...w[pe], filter: ke });
4683
+ }
4684
+ return R ? z : w;
4685
+ });
4686
+ }, []);
4687
+ return g.useMemo(() => ({
4688
+ of: (k) => {
4689
+ const w = c[k] === void 0 ? void 0 : y[k];
4690
+ if (w === void 0) throw new Error(`useLinkedViews: no view ${JSON.stringify(k)}; the views (read once, at mount) are ${Object.keys(c).map((R) => JSON.stringify(R)).join(", ")}`);
4691
+ return w;
4692
+ },
4693
+ active: l,
4694
+ switchTo: E,
4695
+ focus: O,
4696
+ updateFilter: X,
4697
+ updateFilters: N,
4698
+ search: u,
4699
+ state: c
4700
+ }), [y, l, E, O, X, N, u, c]);
4701
+ }
4702
+ function ql() {
4703
+ const [e, t] = g.useState(null), n = g.useRef(0), s = g.useCallback((o) => t(o === null ? null : { id: o, key: ++n.current }), []);
4704
+ return [e, s];
4705
+ }
4706
+ const Al = {
4707
+ label: "Unknown",
4708
+ icon: "?",
4709
+ color: { light: { fill: "#CBD5E1", border: "#94A3B8" }, dark: { fill: "#64748B", border: "#94A3B8" } },
4710
+ size: { r: 10 },
4711
+ summaryKind: "none"
4712
+ };
4713
+ function Ul(e) {
4714
+ var at, lt, Ie, dt, De, ht;
4715
+ const t = [], n = e.styles.map((b) => b.id), s = /* @__PURE__ */ new Set();
4716
+ for (const b of n)
4717
+ s.has(b) && t.push(`style value ${JSON.stringify(b)} is declared twice`), s.add(b);
4718
+ const o = /* @__PURE__ */ new Map();
4719
+ for (const b of n) o.set(Tn(b), (o.get(Tn(b)) ?? 0) + 1);
4720
+ const i = /* @__PURE__ */ new Map();
4721
+ n.forEach((b, T) => {
4722
+ const U = Tn(b);
4723
+ i.set(b, U !== "" && o.get(U) === 1 ? U : `v${T + 1}`);
4724
+ });
4725
+ const r = (b, T) => {
4726
+ Ii(T) || t.push(`${b} is ${JSON.stringify(T)}, not a hex, rgb() or hsl() colour`);
4727
+ }, c = (b, T) => {
4728
+ T && !(T.min <= T.max) && t.push(`${b} runs from ${T.min} to ${T.max}; a band's min must not exceed its max`);
4729
+ }, a = (b, T) => {
4730
+ var U, se, G, oe;
4731
+ for (const B of ["light", "dark"])
4732
+ r(`${b}.color.${B}.fill`, T.color[B].fill), r(`${b}.color.${B}.border`, T.color[B].border);
4733
+ T.whenHidden !== void 0 && T.whenHidden !== "ascend" && T.whenHidden !== "splice" && t.push(`${b}.whenHidden is ${JSON.stringify(T.whenHidden)}, not 'ascend' or 'splice'`), T.summaryKind !== void 0 && T.summaryKind !== "children" && T.summaryKind !== "degree" && T.summaryKind !== "none" && t.push(`${b}.summaryKind is ${JSON.stringify(T.summaryKind)}, not 'children', 'degree' or 'none'`), c(`${b}.physics.band.x`, (se = (U = T.physics) == null ? void 0 : U.band) == null ? void 0 : se.x), c(`${b}.physics.band.y`, (oe = (G = T.physics) == null ? void 0 : G.band) == null ? void 0 : oe.y);
4734
+ };
4735
+ for (const b of e.styles) a(`styles.${b.id}`, b);
4736
+ const l = e.fallbackStyle ?? Al;
4737
+ a("fallbackStyle", l);
4738
+ const d = /* @__PURE__ */ new Set(), u = (b, T, U) => JSON.stringify(T <= U ? [b, T, U] : [b, U, T]), v = /* @__PURE__ */ new Map(), M = e.edgeTypes ?? [];
4739
+ for (const b of M) {
4740
+ d.has(b.id) && t.push(`edge type ${JSON.stringify(b.id)} is declared twice`), d.add(b.id), ((lt = (at = b.style) == null ? void 0 : at.color) == null ? void 0 : lt.light) !== void 0 && r(`edgeTypes.${b.id}.style.color.light`, b.style.color.light), ((dt = (Ie = b.style) == null ? void 0 : Ie.color) == null ? void 0 : dt.dark) !== void 0 && r(`edgeTypes.${b.id}.style.color.dark`, b.style.color.dark);
4741
+ for (const T of ["sourceValue", "targetValue"]) {
4742
+ const U = Mn(b[T]);
4743
+ U.length === 0 && t.push(`edgeTypes.${b.id}.${T} names no value; name at least one`), U.forEach((se, G) => {
4744
+ s.has(se) || t.push(`edgeTypes.${b.id}.${T}${U.length > 1 ? `[${G}]` : ""} is ${JSON.stringify(se)}, which styles does not declare`);
4745
+ });
4746
+ }
4747
+ if (b.relation !== "containment" && b.relation !== "dependency" && t.push(`edgeTypes.${b.id}.relation is ${JSON.stringify(b.relation)}, not 'containment' or 'dependency'`), b.match !== void 0) {
4748
+ Object.keys(b.match).length === 0 && t.push(`edgeTypes.${b.id}.match is empty; leave it out`);
4749
+ for (const [T, U] of Object.entries(b.match))
4750
+ typeof U != "string" && t.push(`edgeTypes.${b.id}.match.${T} is ${JSON.stringify(U)}, not a value`);
4751
+ }
4752
+ for (const [T, U] of hn(b)) {
4753
+ const se = u(b.relation, T, U), G = v.get(se) ?? [];
4754
+ G.includes(b) || G.push(b), v.set(se, G);
4755
+ }
4756
+ }
4757
+ const S = (b, T) => {
4758
+ if (b.match === void 0 || T.match === void 0) return b.match === T.match;
4759
+ const U = Object.keys(b.match);
4760
+ return U.length === Object.keys(T.match).length && U.every((se) => b.match[se] === T.match[se]);
4761
+ };
4762
+ if (!e.classifyEdge) {
4763
+ const b = (U, se) => hn(U).some(([G, oe]) => hn(se).some(([B, f]) => G === B && oe === f)), T = /* @__PURE__ */ new Set();
4764
+ for (const [U, se] of v)
4765
+ for (let G = 0; G < se.length; G++)
4766
+ for (let oe = G + 1; oe < se.length; oe++) {
4767
+ const B = se[G], f = se[oe], q = `${B.id}\0${f.id}`;
4768
+ T.has(q) || !b(B, f) || !S(B, f) || (T.add(q), t.push(`edge types ${JSON.stringify(B.id)} and ${JSON.stringify(f.id)} run between the same values with the same relation (${JSON.parse(U)[0]}) and nothing tells them apart; give one a match on an edge axis, declare them in opposite orientations, or give classifyEdge`));
4769
+ }
4770
+ }
4771
+ const p = e.filterAxes ?? [{ id: e.styleAxis, label: e.styleLabel ?? e.styleAxis, emptyMeans: "none" }], $ = /* @__PURE__ */ new Set();
4772
+ for (const b of p)
4773
+ $.has(b.id) && t.push(`filter axis ${JSON.stringify(b.id)} is declared twice`), $.add(b.id), b.emptyMeans !== "all" && b.emptyMeans !== "none" && t.push(`filterAxes.${b.id}.emptyMeans is ${JSON.stringify(b.emptyMeans)}, not 'all' or 'none'`);
4774
+ const D = [...sc, ...e.scalars ?? []].map(Ki), x = /* @__PURE__ */ new Set();
4775
+ for (const b of D)
4776
+ x.has(b.id) && t.push(`scalar ${JSON.stringify(b.id)} is declared twice (the built-ins are reach, degree and depth)`), x.add(b.id);
4777
+ if (t.length > 0) throw new Error(`taxonomy is incoherent: ${t.join("; ")}`);
4778
+ const V = e.styles.length, F = /* @__PURE__ */ Object.create(null);
4779
+ e.styles.forEach((b, T) => {
4780
+ F[b.id] = vo(b, T, V);
4781
+ });
4782
+ const L = vo({ id: "", ...l }, 0, 1);
4783
+ V > 0 && ((ht = (De = l.physics) == null ? void 0 : De.band) == null ? void 0 : ht.y) === void 0 && (L.physics.band.y = { min: F[n[0]].physics.band.y.min, max: F[n[V - 1]].physics.band.y.max });
4784
+ const y = M.map(ic), I = new Map(y.map((b) => [b.id, b.style])), E = /* @__PURE__ */ new Set(), O = (b) => {
4785
+ const T = I.get(b);
4786
+ return T || (E.has(b) || (E.add(b), console.warn(`[graph] edge type ${JSON.stringify(b)} has no stroke: the taxonomy does not declare it; drawing it neutral`)), wn);
4787
+ }, X = (b, T) => {
4788
+ var U;
4789
+ for (const se of Object.keys(T)) if (((U = b.values) == null ? void 0 : U[se]) !== T[se]) return !1;
4790
+ return !0;
4791
+ }, N = (b, T, U) => {
4792
+ var q;
4793
+ if (T === void 0 || U === void 0) return;
4794
+ const se = v.get(u(b.relation === "containment" ? "containment" : "dependency", T, U));
4795
+ if (se === void 0) return;
4796
+ const G = se.filter((te) => te.match === void 0 || X(b, te.match)), oe = G.filter((te) => te.match !== void 0), B = oe.length > 0 ? oe : G;
4797
+ return (q = B.filter((te) => hn(te).some(([le, Ee]) => le === T && Ee === U))[0] ?? B[0]) == null ? void 0 : q.id;
4798
+ }, k = (b, T, U) => {
4799
+ var G;
4800
+ const se = N(b, T, U);
4801
+ return ((G = e.classifyEdge) == null ? void 0 : G.call(e, b, T, U, se)) ?? se;
4802
+ }, w = /* @__PURE__ */ new Set(), R = (b) => {
4803
+ const T = b !== void 0 && Rn(F, b) ? F[b] : void 0;
4804
+ if (T !== void 0) return T;
4805
+ const U = b ?? "<absent>";
4806
+ return w.has(U) || (w.add(U), console.warn(
4807
+ `[graph] no style declared for value ${JSON.stringify(U)}; using the fallback. The graph will render, but this node is drawn with placeholder styling.`
4808
+ )), L;
4809
+ }, { styleAxis: z } = e, pe = (b) => b.values[z], ke = (b) => Rn(F, b) ? F[b].abbreviation : b.slice(0, 2), St = {
4810
+ axis: z,
4811
+ labelFor: (b) => Rn(F, b) ? F[b].label : b,
4812
+ abbreviationFor: ke,
4813
+ iconFor: (b) => Rn(F, b) ? F[b].icon : ""
4814
+ }, Ne = p.map((b) => mi(b, St)), ct = new Map(Ne.map((b) => [b.id, b]));
4815
+ return {
4816
+ styleAxis: () => z,
4817
+ styleLabel: () => e.styleLabel ?? z,
4818
+ filterAxes: Ne,
4819
+ axisFor: (b) => ct.get(b),
4820
+ valueOn: (b, T) => b.values[T],
4821
+ abbreviationFor: ke,
4822
+ styleValues: n,
4823
+ edgeTypes: y,
4824
+ scalars: D,
4825
+ edgeStrokeFor: O,
4826
+ colorVar: (b) => `--gv-node-${i.get(b) ?? (Tn(b) || "undeclared")}`,
4827
+ styleOf: R,
4828
+ styleValueOf: pe,
4829
+ // Hot path: one property read, one record lookup, one branch. No allocation
4830
+ // — this runs per node per frame in the draw loop.
4831
+ nodeStyleOf: (b) => R(pe(b)),
4832
+ edgeTypeOf: k,
4833
+ collapse: e.collapse ?? ((b) => b),
4834
+ contextLine: e.contextLine ?? ((b, T) => T == null ? void 0 : T.name),
4835
+ searchText: e.searchText ?? ((b) => b.name),
4836
+ highlight: e.highlight ?? ((b, T) => T)
4837
+ };
4838
+ }
4839
+ function Kl(e) {
4840
+ const { forces: t, nodeScale: n } = e;
4841
+ return { forces: ur(t), nodeScale: { ...n } };
4842
+ }
4843
+ function Wl(e, t) {
4844
+ if (!je(e)) return;
4845
+ const n = ar(t), s = e.forces === void 0 ? n.forces : Bc(e.forces, n.forces, t);
4846
+ if (!s) return;
4847
+ const o = e.nodeScale === void 0 ? n.nodeScale : Hc(e.nodeScale, n.nodeScale);
4848
+ if (o)
4849
+ return zn(s, o);
4850
+ }
4851
+ export {
4852
+ Jt as BAND_FRAME,
4853
+ Ko as CONTAINMENT_STROKE,
4854
+ Vi as FilterBar,
4855
+ Yl as GraphView,
4856
+ Jl as GroupLegend,
4857
+ wn as NEUTRAL_STROKE,
4858
+ _n as TaxonomyContext,
4859
+ Gi as copyGroups,
4860
+ _o as countsOn,
4861
+ Ul as createTaxonomy,
4862
+ Dl as filterFromJSON,
4863
+ bn as filterStatesEqual,
4864
+ Pl as filterToJSON,
4865
+ Fi as hiddenMatchesOf,
4866
+ Ps as initialFilter,
4867
+ it as isContainment,
4868
+ Wl as layoutFromJSON,
4869
+ Kl as layoutToJSON,
4870
+ Ls as lockedFor,
4871
+ Bl as locksFromJSON,
4872
+ _l as locksToJSON,
4873
+ Hl as matchesFocus,
4874
+ Pt as nodesById,
4875
+ zl as passesSelection,
4876
+ Xl as payloadNumber,
4877
+ Gl as payloadString,
4878
+ qo as reconcileFilter,
4879
+ Yo as reseedFilter,
4880
+ Ll as schemeStylesheet,
4881
+ zo as schemeVars,
4882
+ ze as selectionFor,
4883
+ Fl as themeChoiceOf,
4884
+ Li as toggleGroup,
4885
+ Vl as toggleValue,
4886
+ ql as useFocusRequest,
4887
+ wi as useHostTheme,
4888
+ jl as useLinkedViews,
4889
+ Bt as useTaxonomy,
4890
+ Nl as validateGraph,
4891
+ sn as valuesOn,
4892
+ Ai as withLock,
4893
+ on as withSelection
4894
+ };
4895
+ //# sourceMappingURL=index.js.map