@kanzo-tech/graph 0.26.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +7 -4
  2. package/dist/core/client.d.ts.map +1 -1
  3. package/dist/core/client.js +16 -16
  4. package/dist/core/client.js.map +1 -1
  5. package/dist/core/error.d.ts +3 -3
  6. package/dist/core/error.d.ts.map +1 -1
  7. package/dist/core/error.js.map +1 -1
  8. package/dist/core/state.d.ts +8 -3
  9. package/dist/core/state.d.ts.map +1 -1
  10. package/dist/core/store.d.ts +1 -1
  11. package/dist/core/store.d.ts.map +1 -1
  12. package/dist/core/store.js +84 -76
  13. package/dist/core/store.js.map +1 -1
  14. package/dist/core/types.d.ts +5 -3
  15. package/dist/core/types.d.ts.map +1 -1
  16. package/dist/index.d.ts +5 -3
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +28 -24
  19. package/dist/index.js.map +1 -1
  20. package/dist/parts/graph-counts.d.ts +9 -11
  21. package/dist/parts/graph-counts.d.ts.map +1 -1
  22. package/dist/parts/graph-counts.js +28 -27
  23. package/dist/parts/graph-counts.js.map +1 -1
  24. package/dist/parts/graph-select.d.ts +27 -0
  25. package/dist/parts/graph-select.d.ts.map +1 -0
  26. package/dist/parts/graph-select.js +53 -0
  27. package/dist/parts/graph-select.js.map +1 -0
  28. package/dist/parts/graph-status.d.ts +13 -0
  29. package/dist/parts/graph-status.d.ts.map +1 -0
  30. package/dist/parts/graph-status.js +28 -0
  31. package/dist/parts/graph-status.js.map +1 -0
  32. package/dist/react/use-graph-prefs.d.ts +1 -1
  33. package/dist/react/use-graph-prefs.js.map +1 -1
  34. package/dist/render/camera.d.ts +12 -1
  35. package/dist/render/camera.d.ts.map +1 -1
  36. package/dist/render/camera.js +33 -21
  37. package/dist/render/camera.js.map +1 -1
  38. package/dist/render/renderer.d.ts.map +1 -1
  39. package/dist/render/renderer.js +85 -84
  40. package/dist/render/renderer.js.map +1 -1
  41. package/package.json +8 -8
@@ -1,158 +1,159 @@
1
- import { Graph as rn } from "@cosmos.gl/graph";
1
+ import { Graph as an } from "@cosmos.gl/graph";
2
2
  import { GraphError as L } from "../core/error.js";
3
- import { resolveLook as K } from "./graph-looks.js";
4
- import { forces as z, appearance as Y, paint as an } from "./graph-model.js";
5
- import { resolveSim as J } from "./graph-sim.js";
6
- import { createCamera as ln, FIT_DURATION as sn } from "./camera.js";
7
- import { simulating as F, highlighted as un, decayFor as cn, LINKS_WHILE_RUNNING as fn } from "./motion.js";
8
- import { placementOf as pn, cornersOf as dn, placed as mn } from "./placement.js";
9
- import { webglBox as gn, releaseContext as hn } from "./webgl.js";
10
- const T = 0.35, Sn = 1200, Q = 20, X = 1e4;
11
- function On(u, e, i = {}) {
3
+ import { resolveLook as Y } from "./graph-looks.js";
4
+ import { forces as z, appearance as J, paint as ln } from "./graph-model.js";
5
+ import { resolveSim as Q } from "./graph-sim.js";
6
+ import { createCamera as sn, FIT_DURATION as un } from "./camera.js";
7
+ import { simulating as F, highlighted as cn, decayFor as fn, LINKS_WHILE_RUNNING as pn } from "./motion.js";
8
+ import { placementOf as dn, cornersOf as mn, placed as gn } from "./placement.js";
9
+ import { webglBox as hn, releaseContext as Sn } from "./webgl.js";
10
+ const T = 0.35, Pn = 1200, X = 20, $ = 1e4;
11
+ function xn(f, i, e = {}) {
12
12
  let C = !1;
13
- const k = (n) => {
14
- C || e.unrenderable(n);
15
- }, N = gn();
13
+ const h = (n) => {
14
+ C || i.unrenderable(n);
15
+ }, N = hn();
16
16
  if (N === null)
17
- return k(new L("graph/no-webgl", "This browser offers no WebGL context to draw with.")), null;
18
- let b = J(e.getOptions().sim), c = !1, E = !1, O = null, x = null, w = 0, A = -1;
17
+ return h(new L("graph/no-webgl", "This browser offers no WebGL context to draw with.")), null;
18
+ let b = Q(i.getOptions().sim), p = !1, E = !1, O = null, x = null, w = 0, A = -1;
19
19
  const _ = (n) => {
20
- const o = Math.round(n * Q);
21
- o !== A && (A = o, e.reportProgress(o / Q));
20
+ const o = Math.round(n * X);
21
+ o !== A && (A = o, i.reportProgress(o / X));
22
22
  };
23
- let h = K(e.getOptions().look), B = e.getOptions().look;
23
+ let S = Y(i.getOptions().look), B = i.getOptions().look;
24
24
  const a = { positions: !0, paint: !0, state: !0, pinned: !0 };
25
- let S = 0, p = null, l = e.getSnapshot(), d = e.getOptions();
25
+ let P = 0, d = null, s = i.getSnapshot(), m = i.getOptions();
26
26
  const G = () => {
27
27
  var n;
28
- return ((n = e.getSnapshot().geometry) == null ? void 0 : n.size) ?? 0;
28
+ return ((n = i.getSnapshot().geometry) == null ? void 0 : n.size) ?? 0;
29
29
  };
30
30
  let t;
31
31
  try {
32
- t = new rn(u, {
32
+ t = new an(f, {
33
33
  // No `spaceSize` here: it is the geometry's, set when the graph has loaded.
34
34
  // `rescalePositions: false` because the placement below is ours.
35
35
  rescalePositions: !1,
36
36
  fitViewOnInit: !1,
37
37
  transitionDuration: 0,
38
- enableSimulation: c,
38
+ enableSimulation: p,
39
39
  ...z(b),
40
40
  randomSeed: "kanzo-discovery",
41
41
  pixelRatio: window.devicePixelRatio || 1,
42
42
  enableDrag: !0,
43
43
  hoveredPointCursor: "pointer",
44
44
  attribution: "",
45
- onSimulationStart: () => e.report("running"),
45
+ onSimulationStart: () => i.report("running"),
46
46
  onSimulationEnd: () => {
47
47
  var n;
48
- I("settled"), _(1), f.settle(), (n = i.onFrame) == null || n.call(i);
48
+ I("settled"), _(1), u.settle(), (n = e.onFrame) == null || n.call(e);
49
49
  },
50
50
  onSimulationPause: () => I("paused"),
51
51
  onSimulationUnpause: () => I("running"),
52
52
  onSimulationTick: (n, o, r) => {
53
- var s, g;
54
- _(t.progress), f.tick(), o !== void 0 && r && ((s = i.onHover) == null || s.call(i, r)), (g = i.onFrame) == null || g.call(i);
53
+ var c, l;
54
+ _(t.progress), u.tick(), o !== void 0 && r && ((c = e.onHover) == null || c.call(e, r)), (l = e.onFrame) == null || l.call(e);
55
55
  },
56
- onZoomStart: (n, o) => $(o),
56
+ onZoomStart: (n, o) => v(o),
57
57
  onZoom: () => {
58
58
  var n;
59
- return (n = i.onFrame) == null ? void 0 : n.call(i);
59
+ return (n = e.onFrame) == null ? void 0 : n.call(e);
60
60
  },
61
61
  onPointMouseOver: (n, o) => {
62
62
  var r;
63
- O = n, (r = i.onHover) == null || r.call(i, o), e.hover(n);
63
+ O = n, (r = e.onHover) == null || r.call(e, o), i.hover(n);
64
64
  },
65
65
  onPointMouseOut: () => {
66
66
  var n;
67
- O = null, (n = i.onHover) == null || n.call(i, null), e.hover(null);
67
+ O = null, (n = e.onHover) == null || n.call(e, null), i.hover(null);
68
68
  },
69
69
  onDragStart: () => {
70
70
  x = O;
71
71
  },
72
72
  onDrag: (n) => {
73
73
  var o, r;
74
- (o = i.onHover) == null || o.call(i, t.screenToSpacePosition([n.x, n.y])), (r = i.onFrame) == null || r.call(i);
74
+ (o = e.onHover) == null || o.call(e, t.screenToSpacePosition([n.x, n.y])), (r = e.onFrame) == null || r.call(e);
75
75
  },
76
76
  // d3-force's drag-to-fix, and only while a layout can move the point back: cosmos.gl moves a
77
77
  // dragged point with the simulation off too, and a pin nothing pulls against means nothing.
78
78
  onDragEnd: () => {
79
79
  const n = x;
80
80
  x = null;
81
- const { motion: o, pinned: r } = e.getSnapshot();
82
- n !== null && o !== "settled" && !r.includes(n) && e.pin([...r, n]);
81
+ const { motion: o, pinned: r } = i.getSnapshot();
82
+ n !== null && o !== "settled" && !r.includes(n) && i.pin([...r, n]);
83
83
  },
84
84
  onPointClick: (n) => Z(n),
85
85
  onBackgroundClick: () => q()
86
86
  });
87
87
  } catch (n) {
88
- return k(new L("graph/no-webgl", "The renderer failed to start.", {}, { cause: n })), null;
88
+ return h(new L("graph/no-webgl", "The renderer failed to start.", {}, { cause: n })), null;
89
89
  }
90
- const { camera: f, taken: $ } = ln(t, u), D = () => {
91
- S || (S = requestAnimationFrame(() => {
92
- S = 0, v();
90
+ const { camera: u, taken: v } = sn(t, f, h), D = () => {
91
+ P || (P = requestAnimationFrame(() => {
92
+ P = 0, nn();
93
93
  }));
94
94
  };
95
- function v() {
96
- var V, j;
97
- const n = e.getSnapshot(), { geometry: o, encoding: r } = n, s = e.getOptions();
98
- let g = !1;
99
- if (a.positions && o && r && (a.positions = !1, t.setPointPositions(nn(o), !0), o.links !== p && (p = o.links, t.setLinks(p), a.paint = a.state = a.pinned = !0), g = !0, on(o, F(s, o))), a.paint && o && r) {
95
+ function nn() {
96
+ var j, K;
97
+ const n = i.getSnapshot(), { geometry: o, encoding: r } = n, c = i.getOptions(), l = a.positions && r ? o : null;
98
+ l && (a.positions = !1, t.setPointPositions(on(l), !0), l.links !== d && (d = l.links, t.setLinks(d), a.paint = a.state = a.pinned = !0));
99
+ const V = a.paint && o && r;
100
+ if (V) {
100
101
  a.paint = !1;
101
- const y = an(o, r, h, u, s);
102
- t.setPointColors(y.colors), t.setPointSizes(y.sizes), t.setPointShapes(y.shapes), t.setLinkColors(y.linkColors), t.setPointClusters(r.clusters ?? []), t.setConfigPartial({ ...Y(h, u), renderLinks: H() }), g = !0;
102
+ const y = ln(o, r, S, f, c);
103
+ t.setPointColors(y.colors), t.setPointSizes(y.sizes), t.setPointShapes(y.shapes), t.setLinkColors(y.linkColors), t.setPointClusters(r.clusters ?? []), t.setConfigPartial({ ...J(S, f), renderLinks: H() });
103
104
  }
104
105
  a.state && o && (a.state = !1, t.setConfigPartial({
105
- ...un(o, n.mask, ((V = n.selection) == null ? void 0 : V.vertices) ?? null),
106
+ ...cn(o, n.mask, ((j = n.selection) == null ? void 0 : j.vertices) ?? null),
106
107
  focusedPointIndex: n.focus === null || n.focus >= o.size ? void 0 : n.focus
107
- })), a.pinned && o && (a.pinned = !1, t.setPinnedPoints(n.pinned.length > 0 ? [...n.pinned] : null)), g && t.render(), o && r && !a.paint && e.reportDrawn(n), (j = i.onFrame) == null || j.call(i);
108
+ })), a.pinned && o && (a.pinned = !1, t.setPinnedPoints(n.pinned.length > 0 ? [...n.pinned] : null)), (V || l) && t.render(), l && tn(l, F(c, l)), o && r && !a.paint && i.reportDrawn(n), (K = e.onFrame) == null || K.call(e);
108
109
  }
109
- function nn(n) {
110
- const o = n.bound && n.extent ? pn(n.extent, N) : null;
111
- return t.setConfigPartial({ spaceSize: (o == null ? void 0 : o.side) ?? n.space, simulationDecay: cn(n.size) }), !o || !n.extent ? n.positions : (f.frame(dn(n.extent, o)), mn(n.positions, o));
110
+ function on(n) {
111
+ const o = n.bound && n.extent ? dn(n.extent, N) : null;
112
+ return t.setConfigPartial({ spaceSize: (o == null ? void 0 : o.side) ?? n.space, simulationDecay: fn(n.size) }), !o || !n.extent ? n.positions : (u.frame(mn(n.extent, o)), gn(n.positions, o));
112
113
  }
113
- function on(n, o) {
114
- if (o) return P(1);
115
- c && t.pause(), n.bound || f.fit();
114
+ function tn(n, o) {
115
+ if (u.drawn(), o) return k(1);
116
+ p && t.pause(), n.bound || u.fit();
116
117
  }
117
- const H = () => h.link.render && !(E && ((p == null ? void 0 : p.length) ?? 0) / 2 > fn), U = () => t.setConfigPartial({ renderLinks: H() });
118
+ const H = () => S.link.render && !(E && ((d == null ? void 0 : d.length) ?? 0) / 2 > pn), U = () => t.setConfigPartial({ renderLinks: H() });
118
119
  function I(n) {
119
- E = n === "running", U(), e.report(n);
120
+ E = n === "running", U(), i.report(n);
120
121
  }
121
- function tn(n) {
122
- const o = J(n), r = Object.keys(o).some((s) => o[s] !== b[s]);
123
- b = o, c && (t.setConfigPartial(z(o)), r && e.getSnapshot().motion !== "paused" && t.start(T));
122
+ function en(n) {
123
+ const o = Q(n), r = Object.keys(o).some((c) => o[c] !== b[c]);
124
+ b = o, p && (t.setConfigPartial(z(o)), r && i.getSnapshot().motion !== "paused" && t.start(T));
124
125
  }
125
- function P(n) {
126
- c || (c = !0, t.setConfigPartial({ enableSimulation: !0, ...z(b) })), f.run(), E = !0, t.start(n), U();
126
+ function k(n) {
127
+ p || (p = !0, t.setConfigPartial({ enableSimulation: !0, ...z(b) })), u.run(), E = !0, t.start(n), U();
127
128
  }
128
- function m() {
129
+ function g() {
129
130
  clearTimeout(w), w = 0;
130
131
  }
131
132
  function Z(n) {
132
133
  const o = t.getNeighboringPointIndices(n) ?? [];
133
- e.select([n, ...o], "node", "Node"), e.focus(n);
134
+ i.select([n, ...o], "node", "Node"), i.focus(n);
134
135
  }
135
136
  function q() {
136
- e.select(null), e.focus(null);
137
+ i.select(null), i.focus(null);
137
138
  }
138
- t.setConfigPartial(Y(h, u)), t.render();
139
+ t.setConfigPartial(J(S, f)), t.render();
139
140
  const M = (n) => {
140
- n.preventDefault(), k(new L("graph/context-lost", "The browser took back the WebGL context; reload to get one."));
141
- }, W = (n, o) => k(new L("graph/no-webgl", "No GPU device came up to draw with.", n, { cause: o })), R = setTimeout(() => W({ after: X }), X);
141
+ n.preventDefault(), h(new L("graph/context-lost", "The browser took back the WebGL context; reload to get one."));
142
+ }, W = (n, o) => h(new L("graph/no-webgl", "No GPU device came up to draw with.", n, { cause: o })), R = setTimeout(() => W({ after: $ }), $);
142
143
  t.ready.then(
143
144
  () => {
144
145
  var n;
145
- clearTimeout(R), C || (n = u.querySelector("canvas")) == null || n.addEventListener("webglcontextlost", M);
146
+ clearTimeout(R), C || (n = f.querySelector("canvas")) == null || n.addEventListener("webglcontextlost", M), u.ready();
146
147
  },
147
148
  (n) => {
148
149
  clearTimeout(R), W({}, n);
149
150
  }
150
- ), e.report(c && t.isSimulationRunning ? "running" : "settled"), D();
151
- const en = e.subscribe(() => {
152
- const n = e.getSnapshot(), o = e.getOptions();
153
- n.geometry !== l.geometry && (a.positions = !0), n.encoding !== l.encoding && (a.paint = !0), o.look !== B && (B = o.look, h = K(o.look), a.paint = !0), (o.fill !== d.fill || o.symbol !== d.symbol || o.stroke !== d.stroke) && (a.paint = !0), (n.selection !== l.selection || n.focus !== l.focus || n.mask !== l.mask) && (a.state = !0), n.pinned !== l.pinned && (a.pinned = !0), o.sim !== d.sim && tn(o.sim);
151
+ ), i.report(p && t.isSimulationRunning ? "running" : "settled"), D();
152
+ const rn = i.subscribe(() => {
153
+ const n = i.getSnapshot(), o = i.getOptions();
154
+ n.geometry !== s.geometry && (a.positions = !0), n.encoding !== s.encoding && (a.paint = !0), o.look !== B && (B = o.look, S = Y(o.look), a.paint = !0), (o.fill !== m.fill || o.symbol !== m.symbol || o.stroke !== m.stroke) && (a.paint = !0), (n.selection !== s.selection || n.focus !== s.focus || n.mask !== s.mask) && (a.state = !0), n.pinned !== s.pinned && (a.pinned = !0), o.sim !== m.sim && en(o.sim);
154
155
  const r = F(o, n.geometry);
155
- n.geometry === l.geometry && r !== F(d, l.geometry) && (m(), r ? P(T) : t.pause()), l = n, d = o, (a.positions || a.paint || a.state || a.pinned) && D();
156
+ n.geometry === s.geometry && r !== F(m, s.geometry) && (g(), r ? k(T) : t.pause()), s = n, m = o, (a.positions || a.paint || a.state || a.pinned) && D();
156
157
  });
157
158
  return {
158
159
  graph: t,
@@ -166,15 +167,15 @@ function On(u, e, i = {}) {
166
167
  zoomBy(n) {
167
168
  t.setZoomLevel(t.getZoomLevel() * n, 220);
168
169
  },
169
- fit: () => f.fit(),
170
+ fit: () => u.fit(),
170
171
  pause() {
171
- m(), t.pause();
172
+ g(), t.pause();
172
173
  },
173
174
  resume() {
174
- m(), e.getSnapshot().motion === "settled" || !c ? P(T) : t.unpause();
175
+ g(), i.getSnapshot().motion === "settled" || !p ? k(T) : t.unpause();
175
176
  },
176
177
  restart() {
177
- m(), e.pin([]), P(1);
178
+ g(), i.pin([]), k(1);
178
179
  },
179
180
  /**
180
181
  * d3's release: unfix, then reheat, so the released points visibly flow back. A running layout
@@ -182,28 +183,28 @@ function On(u, e, i = {}) {
182
183
  * bounded burst and is paused again, because the reader paused it.
183
184
  */
184
185
  unpin() {
185
- const { motion: n, pinned: o } = e.getSnapshot();
186
- o.length !== 0 && (m(), e.pin([]), P(T), n === "paused" && (w = window.setTimeout(() => {
186
+ const { motion: n, pinned: o } = i.getSnapshot();
187
+ o.length !== 0 && (g(), i.pin([]), k(T), n === "paused" && (w = window.setTimeout(() => {
187
188
  w = 0, t.pause();
188
- }, Sn)));
189
+ }, Pn)));
189
190
  },
190
191
  reveal(n) {
191
192
  n >= G() || (Z(n), t.zoomToPointByIndex(n, 500, 5, !0));
192
193
  },
193
194
  frameSelection() {
194
195
  var o;
195
- const n = (((o = e.getSnapshot().selection) == null ? void 0 : o.vertices) ?? []).filter((r) => r < G());
196
- n.length > 0 && t.fitViewByPointIndices(n, sn, 0.25);
196
+ const n = (((o = i.getSnapshot().selection) == null ? void 0 : o.vertices) ?? []).filter((r) => r < G());
197
+ n.length > 0 && t.fitViewByPointIndices(n, un, 0.25);
197
198
  },
198
199
  clear: q,
199
200
  destroy() {
200
- en(), m(), S && cancelAnimationFrame(S), clearTimeout(R), f.destroy(), C = !0;
201
- const n = u.querySelector("canvas");
202
- n == null || n.removeEventListener("webglcontextlost", M), t.destroy(), hn(n);
201
+ rn(), g(), P && cancelAnimationFrame(P), clearTimeout(R), u.destroy(), C = !0;
202
+ const n = f.querySelector("canvas");
203
+ n == null || n.removeEventListener("webglcontextlost", M), t.destroy(), Sn(n);
203
204
  }
204
205
  };
205
206
  }
206
207
  export {
207
- On as createRenderer
208
+ xn as createRenderer
208
209
  };
209
210
  //# sourceMappingURL=renderer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.js","sources":["../../src/render/renderer.ts"],"sourcesContent":["import { Graph } from \"@cosmos.gl/graph\";\nimport { GraphError } from \"../core/error\";\nimport type { Geometry } from \"../core/load\";\nimport type { GraphStore } from \"../core/store\";\nimport type { GraphCommands, Motion, VertexId } from \"../core/types\";\nimport { resolveLook, type Look } from \"./graph-looks\";\nimport { appearance, forces, paint } from \"./graph-model\";\nimport { resolveSim, type Sim } from \"./graph-sim\";\nimport { createCamera, FIT_DURATION } from \"./camera\";\nimport { decayFor, highlighted, LINKS_WHILE_RUNNING, simulating } from \"./motion\";\nimport { cornersOf, placed, placementOf } from \"./placement\";\nimport { releaseContext, webglBox } from \"./webgl\";\n\nexport interface RendererEvents {\n /** After every frame and every camera move — where the overlays repaint. */\n onFrame?: () => void;\n /** Where the hovered point is in space, as cosmos.gl reports it: no GPU readback per hover. */\n onHover?: (position: [number, number] | null) => void;\n}\n\nexport interface Renderer extends GraphCommands {\n readonly graph: Graph;\n /** The theme moved under the canvas: colours are resolved again, nothing else. */\n repaint(): void;\n /** The drawn points inside a screen rectangle or polygon, once the device is ready. */\n hit(shape: { rect: [[number, number], [number, number]] } | { polygon: [number, number][] }): number[];\n destroy(): void;\n}\n\nconst REHEAT = 0.35;\n/** How long a release wakes a paused layout before pausing it again. */\nconst RELEASE_BURST = 1200;\n/** Twentieths: a settle costs twenty reports rather than one per frame. */\nconst PROGRESS_STEPS = 20;\n\n/**\n * The slowest honest answer for a GPU device: one comes up in milliseconds when it can be made at\n * all, so ten seconds is a device that will not come, not one that is slow.\n */\nconst READY_DEADLINE = 10_000;\n\n/**\n * **cosmos.gl's lifetime, and the frame that renders once.** Built once per element; it subscribes to\n * the store and discharges what changed in one `requestAnimationFrame`:\n *\n * - a new graph uploads positions and links, once per corpus and per position binding;\n * - a binding, a look or a theme change uploads colours, sizes, shapes and clusters and nothing else;\n * - a filter, a selection, a focus or a pin sets config and uploads nothing, and never calls\n * `render()`: a vertex the page's filter does not keep is greyed out, Cosmograph's way, so the\n * points never move because a chart was brushed;\n * - the camera reaches nothing: cosmos.gl moves it, and the overlays follow.\n *\n * A vertex's id is its index here, so nothing is resolved between the store and the buffers.\n * `transitionDuration` is 0: the default animates every upload for 800 ms and keeps the loop awake.\n * The layout runs on its own when `x` and `y` are unbound, and from the current positions.\n * Every callback reads the store's latest options, so a host's inline `onFailure` never rebuilds it.\n * A failure to draw at all marks the store `failed` through `unrenderable`, never `onFailure` alone.\n */\nexport function createRenderer(host: HTMLDivElement, store: GraphStore, events: RendererEvents = {}): Renderer | null {\n let destroyed = false;\n const fail = (error: unknown) => {\n if (!destroyed) store.unrenderable(error);\n };\n const box = webglBox();\n if (box === null) {\n fail(new GraphError(\"graph/no-webgl\", \"This browser offers no WebGL context to draw with.\"));\n return null;\n }\n\n let sim: Sim = resolveSim(store.getOptions().sim);\n let live = false;\n /** Whether a layout is moving the points — ours, since cosmos.gl's flag waits for its device. */\n let moving = false;\n let hovering: number | null = null;\n let dragging: number | null = null;\n let burst = 0;\n let reported = -1;\n const progress = (value: number) => {\n const bucket = Math.round(value * PROGRESS_STEPS);\n if (bucket === reported) return;\n reported = bucket;\n store.reportProgress(bucket / PROGRESS_STEPS);\n };\n\n let look: Look = resolveLook(store.getOptions().look);\n let lookPatch = store.getOptions().look;\n const dirty = { positions: true, paint: true, state: true, pinned: true };\n let frame = 0;\n let links: Float32Array | null = null;\n let last = store.getSnapshot();\n let lastOptions = store.getOptions();\n\n const size = () => store.getSnapshot().geometry?.size ?? 0;\n\n let graph: Graph;\n try {\n graph = new Graph(host, {\n // No `spaceSize` here: it is the geometry's, set when the graph has loaded.\n // `rescalePositions: false` because the placement below is ours.\n rescalePositions: false,\n fitViewOnInit: false,\n transitionDuration: 0,\n enableSimulation: live,\n ...forces(sim),\n randomSeed: \"kanzo-discovery\",\n pixelRatio: window.devicePixelRatio || 1,\n enableDrag: true,\n hoveredPointCursor: \"pointer\",\n attribution: \"\",\n onSimulationStart: () => store.report(\"running\"),\n onSimulationEnd: () => {\n moved(\"settled\");\n progress(1);\n camera.settle();\n events.onFrame?.();\n },\n onSimulationPause: () => moved(\"paused\"),\n onSimulationUnpause: () => moved(\"running\"),\n onSimulationTick: (_alpha, index, position) => {\n progress(graph.progress);\n camera.tick();\n if (index !== undefined && position) events.onHover?.(position);\n events.onFrame?.();\n },\n onZoomStart: (_event, userDriven) => taken(userDriven),\n onZoom: () => events.onFrame?.(),\n onPointMouseOver: (index, position) => {\n hovering = index;\n events.onHover?.(position);\n store.hover(index);\n },\n onPointMouseOut: () => {\n hovering = null;\n events.onHover?.(null);\n store.hover(null);\n },\n onDragStart: () => {\n dragging = hovering;\n },\n onDrag: (event) => {\n events.onHover?.(graph.screenToSpacePosition([event.x, event.y]));\n events.onFrame?.();\n },\n // d3-force's drag-to-fix, and only while a layout can move the point back: cosmos.gl moves a\n // dragged point with the simulation off too, and a pin nothing pulls against means nothing.\n onDragEnd: () => {\n const vertex = dragging;\n dragging = null;\n const { motion, pinned } = store.getSnapshot();\n if (vertex !== null && motion !== \"settled\" && !pinned.includes(vertex)) store.pin([...pinned, vertex]);\n },\n onPointClick: (index) => focusOn(index),\n onBackgroundClick: () => clear(),\n });\n } catch (error) {\n fail(new GraphError(\"graph/no-webgl\", \"The renderer failed to start.\", {}, { cause: error }));\n return null;\n }\n const { camera, taken } = createCamera(graph, host);\n\n const schedule = () => {\n if (frame) return;\n frame = requestAnimationFrame(() => {\n frame = 0;\n draw();\n });\n };\n\n function draw(): void {\n const snapshot = store.getSnapshot();\n const { geometry, encoding } = snapshot;\n const options = store.getOptions();\n let changed = false;\n // Positions wait for the first colours, so a graph's first frame is the drawn one, not a grey one.\n if (dirty.positions && geometry && encoding) {\n dirty.positions = false;\n graph.setPointPositions(position(geometry), true);\n if (geometry.links !== links) {\n links = geometry.links;\n graph.setLinks(links);\n dirty.paint = dirty.state = dirty.pinned = true;\n }\n changed = true;\n layout(geometry, simulating(options, geometry));\n }\n if (dirty.paint && geometry && encoding) {\n dirty.paint = false;\n const buffers = paint(geometry, encoding, look, host, options);\n graph.setPointColors(buffers.colors);\n graph.setPointSizes(buffers.sizes);\n graph.setPointShapes(buffers.shapes);\n graph.setLinkColors(buffers.linkColors);\n graph.setPointClusters(encoding.clusters ?? []);\n graph.setConfigPartial({ ...appearance(look, host), renderLinks: linksShown() });\n changed = true;\n }\n if (dirty.state && geometry) {\n dirty.state = false;\n graph.setConfigPartial({\n ...highlighted(geometry, snapshot.mask, snapshot.selection?.vertices ?? null),\n focusedPointIndex: snapshot.focus === null || snapshot.focus >= geometry.size ? undefined : snapshot.focus,\n });\n }\n if (dirty.pinned && geometry) {\n dirty.pinned = false;\n graph.setPinnedPoints(snapshot.pinned.length > 0 ? [...snapshot.pinned] : null);\n }\n if (changed) graph.render();\n if (geometry && encoding && !dirty.paint) store.reportDrawn(snapshot);\n events.onFrame?.();\n }\n\n /** The positions cosmos.gl gets: bound, the data's extent centred in the device's box; unbound, the seeded start. */\n function position(geometry: Geometry): Float32Array {\n const placement = geometry.bound && geometry.extent ? placementOf(geometry.extent, box as number) : null;\n graph.setConfigPartial({ spaceSize: placement?.side ?? geometry.space, simulationDecay: decayFor(geometry.size) });\n if (!placement || !geometry.extent) return geometry.positions;\n camera.frame(cornersOf(geometry.extent, placement));\n return placed(geometry.positions, placement);\n }\n\n /** A new geometry lays itself out when its positions are a start, and stands still when they are data. */\n function layout(geometry: Geometry, running: boolean): void {\n if (running) return run(1);\n if (live) graph.pause();\n if (!geometry.bound) camera.fit();\n }\n\n /** Whether links are drawn now: the look's choice, unless a large layout is running. */\n const linksShown = (): boolean => look.link.render && !(moving && (links?.length ?? 0) / 2 > LINKS_WHILE_RUNNING);\n const showLinks = () => graph.setConfigPartial({ renderLinks: linksShown() });\n function moved(motion: Motion): void {\n moving = motion === \"running\";\n showLinks();\n store.report(motion);\n }\n\n function applyForces(patch: Partial<Sim> | undefined): void {\n const next = resolveSim(patch);\n const moved = Object.keys(next).some((key) => next[key as keyof Sim] !== sim[key as keyof Sim]);\n sim = next;\n if (!live) return;\n graph.setConfigPartial(forces(next));\n if (moved && store.getSnapshot().motion !== \"paused\") graph.start(REHEAT);\n }\n\n /** A layout runs from where the points are: enabling cosmos.gl's simulation keeps its positions. */\n function run(alpha: number): void {\n if (!live) {\n live = true;\n graph.setConfigPartial({ enableSimulation: true, ...forces(sim) });\n }\n camera.run();\n moving = true;\n graph.start(alpha);\n showLinks();\n }\n\n function endBurst(): void {\n clearTimeout(burst);\n burst = 0;\n }\n\n function focusOn(vertex: VertexId): void {\n const around = graph.getNeighboringPointIndices(vertex) ?? [];\n store.select([vertex, ...around], \"node\", \"Node\");\n store.focus(vertex);\n }\n\n function clear(): void {\n store.select(null);\n store.focus(null);\n }\n\n // cosmos.gl 3.4 queues every setter and command until its device exists (`ensureDevice`), and its\n // two synchronous hit tests answer `[]` until then; only the canvas element has to wait for `ready`.\n graph.setConfigPartial(appearance(look, host));\n graph.render();\n const onLost = (event: Event) => {\n event.preventDefault();\n fail(new GraphError(\"graph/context-lost\", \"The browser took back the WebGL context; reload to get one.\"));\n };\n const noDevice = (data: GraphError[\"data\"], cause?: unknown) =>\n fail(new GraphError(\"graph/no-webgl\", \"No GPU device came up to draw with.\", data, { cause }));\n // `ready` never settles when cosmos.gl cannot make a device, so the deadline is what ends the wait.\n const deadline = setTimeout(() => noDevice({ after: READY_DEADLINE }), READY_DEADLINE);\n void graph.ready.then(\n () => {\n clearTimeout(deadline);\n if (!destroyed) host.querySelector(\"canvas\")?.addEventListener(\"webglcontextlost\", onLost);\n },\n (error: unknown) => {\n clearTimeout(deadline);\n noDevice({}, error);\n },\n );\n store.report(live && graph.isSimulationRunning ? \"running\" : \"settled\");\n schedule();\n\n const unsubscribe = store.subscribe(() => {\n const snapshot = store.getSnapshot();\n const options = store.getOptions();\n if (snapshot.geometry !== last.geometry) dirty.positions = true;\n if (snapshot.encoding !== last.encoding) dirty.paint = true;\n if (options.look !== lookPatch) {\n lookPatch = options.look;\n look = resolveLook(options.look);\n dirty.paint = true;\n }\n if (options.fill !== lastOptions.fill || options.symbol !== lastOptions.symbol || options.stroke !== lastOptions.stroke) {\n dirty.paint = true;\n }\n if (snapshot.selection !== last.selection || snapshot.focus !== last.focus || snapshot.mask !== last.mask) dirty.state = true;\n if (snapshot.pinned !== last.pinned) dirty.pinned = true;\n if (options.sim !== lastOptions.sim) applyForces(options.sim);\n const wants = simulating(options, snapshot.geometry);\n if (snapshot.geometry === last.geometry && wants !== simulating(lastOptions, last.geometry)) {\n endBurst();\n if (wants) run(REHEAT);\n else graph.pause();\n }\n last = snapshot;\n lastOptions = options;\n if (dirty.positions || dirty.paint || dirty.state || dirty.pinned) schedule();\n });\n\n return {\n graph,\n repaint() {\n dirty.paint = true;\n schedule();\n },\n hit(shape) {\n const found = \"rect\" in shape ? graph.findPointsInRect(shape.rect) : graph.findPointsInPolygon(shape.polygon);\n return Array.from(found);\n },\n zoomBy(factor) {\n graph.setZoomLevel(graph.getZoomLevel() * factor, 220);\n },\n fit: () => camera.fit(),\n pause() {\n endBurst();\n graph.pause();\n },\n resume() {\n endBurst();\n const settled = store.getSnapshot().motion === \"settled\";\n if (settled || !live) run(REHEAT);\n else graph.unpause();\n },\n restart() {\n endBurst();\n store.pin([]);\n run(1);\n },\n /**\n * d3's release: unfix, then reheat, so the released points visibly flow back. A running layout\n * takes the heat and goes on; a settled one cools to settled on its own; a paused one gets a\n * bounded burst and is paused again, because the reader paused it.\n */\n unpin() {\n const { motion, pinned } = store.getSnapshot();\n if (pinned.length === 0) return;\n endBurst();\n store.pin([]);\n run(REHEAT);\n if (motion === \"paused\") {\n burst = window.setTimeout(() => {\n burst = 0;\n graph.pause();\n }, RELEASE_BURST);\n }\n },\n reveal(vertex) {\n if (vertex >= size()) return;\n focusOn(vertex);\n graph.zoomToPointByIndex(vertex, 500, 5, true);\n },\n frameSelection() {\n const vertices = (store.getSnapshot().selection?.vertices ?? []).filter((id) => id < size());\n if (vertices.length > 0) graph.fitViewByPointIndices(vertices, FIT_DURATION, 0.25);\n },\n clear,\n destroy() {\n unsubscribe();\n endBurst();\n if (frame) cancelAnimationFrame(frame);\n clearTimeout(deadline);\n camera.destroy();\n destroyed = true;\n // Read here rather than remembered from construction: the element exists only with the device.\n const canvas = host.querySelector(\"canvas\");\n canvas?.removeEventListener(\"webglcontextlost\", onLost);\n graph.destroy();\n releaseContext(canvas);\n },\n };\n}\n"],"names":["REHEAT","RELEASE_BURST","PROGRESS_STEPS","READY_DEADLINE","createRenderer","host","store","events","destroyed","fail","error","box","webglBox","GraphError","sim","resolveSim","live","moving","hovering","dragging","burst","reported","progress","value","bucket","look","resolveLook","lookPatch","dirty","frame","links","last","lastOptions","size","_a","graph","Graph","forces","moved","camera","_alpha","index","position","_b","_event","userDriven","taken","event","vertex","motion","pinned","focusOn","clear","createCamera","schedule","draw","snapshot","geometry","encoding","options","changed","layout","simulating","buffers","paint","appearance","linksShown","highlighted","placement","placementOf","decayFor","cornersOf","placed","running","run","LINKS_WHILE_RUNNING","showLinks","applyForces","patch","next","key","alpha","endBurst","around","onLost","noDevice","data","cause","deadline","unsubscribe","wants","shape","found","factor","vertices","id","FIT_DURATION","canvas","releaseContext"],"mappings":";;;;;;;;;AA6BA,MAAMA,IAAS,MAETC,KAAgB,MAEhBC,IAAiB,IAMjBC,IAAiB;AAmBhB,SAASC,GAAeC,GAAsBC,GAAmBC,IAAyB,CAAA,GAAqB;AACpH,MAAIC,IAAY;AAChB,QAAMC,IAAO,CAACC,MAAmB;AAC/B,IAAKF,KAAWF,EAAM,aAAaI,CAAK;AAAA,EAC1C,GACMC,IAAMC,GAAA;AACZ,MAAID,MAAQ;AACV,WAAAF,EAAK,IAAII,EAAW,kBAAkB,oDAAoD,CAAC,GACpF;AAGT,MAAIC,IAAWC,EAAWT,EAAM,WAAA,EAAa,GAAG,GAC5CU,IAAO,IAEPC,IAAS,IACTC,IAA0B,MAC1BC,IAA0B,MAC1BC,IAAQ,GACRC,IAAW;AACf,QAAMC,IAAW,CAACC,MAAkB;AAClC,UAAMC,IAAS,KAAK,MAAMD,IAAQrB,CAAc;AAChD,IAAIsB,MAAWH,MACfA,IAAWG,GACXlB,EAAM,eAAekB,IAAStB,CAAc;AAAA,EAC9C;AAEA,MAAIuB,IAAaC,EAAYpB,EAAM,WAAA,EAAa,IAAI,GAChDqB,IAAYrB,EAAM,WAAA,EAAa;AACnC,QAAMsB,IAAQ,EAAE,WAAW,IAAM,OAAO,IAAM,OAAO,IAAM,QAAQ,GAAA;AACnE,MAAIC,IAAQ,GACRC,IAA6B,MAC7BC,IAAOzB,EAAM,YAAA,GACb0B,IAAc1B,EAAM,WAAA;AAExB,QAAM2B,IAAO,MAAA;;AAAM,aAAAC,IAAA5B,EAAM,YAAA,EAAc,aAApB,gBAAA4B,EAA8B,SAAQ;AAAA;AAEzD,MAAIC;AACJ,MAAI;AACF,IAAAA,IAAQ,IAAIC,GAAM/B,GAAM;AAAA;AAAA;AAAA,MAGtB,kBAAkB;AAAA,MAClB,eAAe;AAAA,MACf,oBAAoB;AAAA,MACpB,kBAAkBW;AAAA,MAClB,GAAGqB,EAAOvB,CAAG;AAAA,MACb,YAAY;AAAA,MACZ,YAAY,OAAO,oBAAoB;AAAA,MACvC,YAAY;AAAA,MACZ,oBAAoB;AAAA,MACpB,aAAa;AAAA,MACb,mBAAmB,MAAMR,EAAM,OAAO,SAAS;AAAA,MAC/C,iBAAiB,MAAM;;AACrB,QAAAgC,EAAM,SAAS,GACfhB,EAAS,CAAC,GACViB,EAAO,OAAA,IACPL,IAAA3B,EAAO,YAAP,QAAA2B,EAAA,KAAA3B;AAAA,MACF;AAAA,MACA,mBAAmB,MAAM+B,EAAM,QAAQ;AAAA,MACvC,qBAAqB,MAAMA,EAAM,SAAS;AAAA,MAC1C,kBAAkB,CAACE,GAAQC,GAAOC,MAAa;;AAC7C,QAAApB,EAASa,EAAM,QAAQ,GACvBI,EAAO,KAAA,GACHE,MAAU,UAAaC,OAAUR,IAAA3B,EAAO,YAAP,QAAA2B,EAAA,KAAA3B,GAAiBmC,MACtDC,IAAApC,EAAO,YAAP,QAAAoC,EAAA,KAAApC;AAAA,MACF;AAAA,MACA,aAAa,CAACqC,GAAQC,MAAeC,EAAMD,CAAU;AAAA,MACrD,QAAQ,MAAA;;AAAM,gBAAAX,IAAA3B,EAAO,YAAP,gBAAA2B,EAAA,KAAA3B;AAAA;AAAA,MACd,kBAAkB,CAACkC,GAAOC,MAAa;;AACrC,QAAAxB,IAAWuB,IACXP,IAAA3B,EAAO,YAAP,QAAA2B,EAAA,KAAA3B,GAAiBmC,IACjBpC,EAAM,MAAMmC,CAAK;AAAA,MACnB;AAAA,MACA,iBAAiB,MAAM;;AACrB,QAAAvB,IAAW,OACXgB,IAAA3B,EAAO,YAAP,QAAA2B,EAAA,KAAA3B,GAAiB,OACjBD,EAAM,MAAM,IAAI;AAAA,MAClB;AAAA,MACA,aAAa,MAAM;AACjB,QAAAa,IAAWD;AAAA,MACb;AAAA,MACA,QAAQ,CAAC6B,MAAU;;AACjB,SAAAb,IAAA3B,EAAO,YAAP,QAAA2B,EAAA,KAAA3B,GAAiB4B,EAAM,sBAAsB,CAACY,EAAM,GAAGA,EAAM,CAAC,CAAC,KAC/DJ,IAAApC,EAAO,YAAP,QAAAoC,EAAA,KAAApC;AAAA,MACF;AAAA;AAAA;AAAA,MAGA,WAAW,MAAM;AACf,cAAMyC,IAAS7B;AACf,QAAAA,IAAW;AACX,cAAM,EAAE,QAAA8B,GAAQ,QAAAC,MAAW5C,EAAM,YAAA;AACjC,QAAI0C,MAAW,QAAQC,MAAW,aAAa,CAACC,EAAO,SAASF,CAAM,OAAS,IAAI,CAAC,GAAGE,GAAQF,CAAM,CAAC;AAAA,MACxG;AAAA,MACA,cAAc,CAACP,MAAUU,EAAQV,CAAK;AAAA,MACtC,mBAAmB,MAAMW,EAAA;AAAA,IAAM,CAChC;AAAA,EACH,SAAS1C,GAAO;AACd,WAAAD,EAAK,IAAII,EAAW,kBAAkB,iCAAiC,CAAA,GAAI,EAAE,OAAOH,EAAA,CAAO,CAAC,GACrF;AAAA,EACT;AACA,QAAM,EAAE,QAAA6B,GAAQ,OAAAO,EAAA,IAAUO,GAAalB,GAAO9B,CAAI,GAE5CiD,IAAW,MAAM;AACrB,IAAIzB,MACJA,IAAQ,sBAAsB,MAAM;AAClC,MAAAA,IAAQ,GACR0B,EAAA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,WAASA,IAAa;;AACpB,UAAMC,IAAWlD,EAAM,YAAA,GACjB,EAAE,UAAAmD,GAAU,UAAAC,EAAA,IAAaF,GACzBG,IAAUrD,EAAM,WAAA;AACtB,QAAIsD,IAAU;AAad,QAXIhC,EAAM,aAAa6B,KAAYC,MACjC9B,EAAM,YAAY,IAClBO,EAAM,kBAAkBO,GAASe,CAAQ,GAAG,EAAI,GAC5CA,EAAS,UAAU3B,MACrBA,IAAQ2B,EAAS,OACjBtB,EAAM,SAASL,CAAK,GACpBF,EAAM,QAAQA,EAAM,QAAQA,EAAM,SAAS,KAE7CgC,IAAU,IACVC,GAAOJ,GAAUK,EAAWH,GAASF,CAAQ,CAAC,IAE5C7B,EAAM,SAAS6B,KAAYC,GAAU;AACvC,MAAA9B,EAAM,QAAQ;AACd,YAAMmC,IAAUC,GAAMP,GAAUC,GAAUjC,GAAMpB,GAAMsD,CAAO;AAC7D,MAAAxB,EAAM,eAAe4B,EAAQ,MAAM,GACnC5B,EAAM,cAAc4B,EAAQ,KAAK,GACjC5B,EAAM,eAAe4B,EAAQ,MAAM,GACnC5B,EAAM,cAAc4B,EAAQ,UAAU,GACtC5B,EAAM,iBAAiBuB,EAAS,YAAY,CAAA,CAAE,GAC9CvB,EAAM,iBAAiB,EAAE,GAAG8B,EAAWxC,GAAMpB,CAAI,GAAG,aAAa6D,EAAA,GAAc,GAC/EN,IAAU;AAAA,IACZ;AACA,IAAIhC,EAAM,SAAS6B,MACjB7B,EAAM,QAAQ,IACdO,EAAM,iBAAiB;AAAA,MACrB,GAAGgC,GAAYV,GAAUD,EAAS,QAAMtB,IAAAsB,EAAS,cAAT,gBAAAtB,EAAoB,aAAY,IAAI;AAAA,MAC5E,mBAAmBsB,EAAS,UAAU,QAAQA,EAAS,SAASC,EAAS,OAAO,SAAYD,EAAS;AAAA,IAAA,CACtG,IAEC5B,EAAM,UAAU6B,MAClB7B,EAAM,SAAS,IACfO,EAAM,gBAAgBqB,EAAS,OAAO,SAAS,IAAI,CAAC,GAAGA,EAAS,MAAM,IAAI,IAAI,IAE5EI,OAAe,OAAA,GACfH,KAAYC,KAAY,CAAC9B,EAAM,SAAOtB,EAAM,YAAYkD,CAAQ,IACpEb,IAAApC,EAAO,YAAP,QAAAoC,EAAA,KAAApC;AAAA,EACF;AAGA,WAASmC,GAASe,GAAkC;AAClD,UAAMW,IAAYX,EAAS,SAASA,EAAS,SAASY,GAAYZ,EAAS,QAAQ9C,CAAa,IAAI;AAEpG,WADAwB,EAAM,iBAAiB,EAAE,YAAWiC,KAAA,gBAAAA,EAAW,SAAQX,EAAS,OAAO,iBAAiBa,GAASb,EAAS,IAAI,EAAA,CAAG,GAC7G,CAACW,KAAa,CAACX,EAAS,SAAeA,EAAS,aACpDlB,EAAO,MAAMgC,GAAUd,EAAS,QAAQW,CAAS,CAAC,GAC3CI,GAAOf,EAAS,WAAWW,CAAS;AAAA,EAC7C;AAGA,WAASP,GAAOJ,GAAoBgB,GAAwB;AAC1D,QAAIA,EAAS,QAAOC,EAAI,CAAC;AACzB,IAAI1D,OAAY,MAAA,GACXyC,EAAS,SAAOlB,EAAO,IAAA;AAAA,EAC9B;AAGA,QAAM2B,IAAa,MAAezC,EAAK,KAAK,UAAU,EAAER,OAAWa,KAAA,gBAAAA,EAAO,WAAU,KAAK,IAAI6C,KACvFC,IAAY,MAAMzC,EAAM,iBAAiB,EAAE,aAAa+B,EAAA,GAAc;AAC5E,WAAS5B,EAAMW,GAAsB;AACnC,IAAAhC,IAASgC,MAAW,WACpB2B,EAAA,GACAtE,EAAM,OAAO2C,CAAM;AAAA,EACrB;AAEA,WAAS4B,GAAYC,GAAuC;AAC1D,UAAMC,IAAOhE,EAAW+D,CAAK,GACvBxC,IAAQ,OAAO,KAAKyC,CAAI,EAAE,KAAK,CAACC,MAAQD,EAAKC,CAAgB,MAAMlE,EAAIkE,CAAgB,CAAC;AAE9F,IADAlE,IAAMiE,GACD/D,MACLmB,EAAM,iBAAiBE,EAAO0C,CAAI,CAAC,GAC/BzC,KAAShC,EAAM,YAAA,EAAc,WAAW,YAAU6B,EAAM,MAAMnC,CAAM;AAAA,EAC1E;AAGA,WAAS0E,EAAIO,GAAqB;AAChC,IAAKjE,MACHA,IAAO,IACPmB,EAAM,iBAAiB,EAAE,kBAAkB,IAAM,GAAGE,EAAOvB,CAAG,GAAG,IAEnEyB,EAAO,IAAA,GACPtB,IAAS,IACTkB,EAAM,MAAM8C,CAAK,GACjBL,EAAA;AAAA,EACF;AAEA,WAASM,IAAiB;AACxB,iBAAa9D,CAAK,GAClBA,IAAQ;AAAA,EACV;AAEA,WAAS+B,EAAQH,GAAwB;AACvC,UAAMmC,IAAShD,EAAM,2BAA2Ba,CAAM,KAAK,CAAA;AAC3D,IAAA1C,EAAM,OAAO,CAAC0C,GAAQ,GAAGmC,CAAM,GAAG,QAAQ,MAAM,GAChD7E,EAAM,MAAM0C,CAAM;AAAA,EACpB;AAEA,WAASI,IAAc;AACrB,IAAA9C,EAAM,OAAO,IAAI,GACjBA,EAAM,MAAM,IAAI;AAAA,EAClB;AAIA,EAAA6B,EAAM,iBAAiB8B,EAAWxC,GAAMpB,CAAI,CAAC,GAC7C8B,EAAM,OAAA;AACN,QAAMiD,IAAS,CAACrC,MAAiB;AAC/B,IAAAA,EAAM,eAAA,GACNtC,EAAK,IAAII,EAAW,sBAAsB,6DAA6D,CAAC;AAAA,EAC1G,GACMwE,IAAW,CAACC,GAA0BC,MAC1C9E,EAAK,IAAII,EAAW,kBAAkB,uCAAuCyE,GAAM,EAAE,OAAAC,EAAA,CAAO,CAAC,GAEzFC,IAAW,WAAW,MAAMH,EAAS,EAAE,OAAOlF,EAAA,CAAgB,GAAGA,CAAc;AACrF,EAAKgC,EAAM,MAAM;AAAA,IACf,MAAM;;AACJ,mBAAaqD,CAAQ,GAChBhF,MAAW0B,IAAA7B,EAAK,cAAc,QAAQ,MAA3B,QAAA6B,EAA8B,iBAAiB,oBAAoBkD;AAAA,IACrF;AAAA,IACA,CAAC1E,MAAmB;AAClB,mBAAa8E,CAAQ,GACrBH,EAAS,CAAA,GAAI3E,CAAK;AAAA,IACpB;AAAA,EAAA,GAEFJ,EAAM,OAAOU,KAAQmB,EAAM,sBAAsB,YAAY,SAAS,GACtEmB,EAAA;AAEA,QAAMmC,KAAcnF,EAAM,UAAU,MAAM;AACxC,UAAMkD,IAAWlD,EAAM,YAAA,GACjBqD,IAAUrD,EAAM,WAAA;AACtB,IAAIkD,EAAS,aAAazB,EAAK,eAAgB,YAAY,KACvDyB,EAAS,aAAazB,EAAK,eAAgB,QAAQ,KACnD4B,EAAQ,SAAShC,MACnBA,IAAYgC,EAAQ,MACpBlC,IAAOC,EAAYiC,EAAQ,IAAI,GAC/B/B,EAAM,QAAQ,MAEZ+B,EAAQ,SAAS3B,EAAY,QAAQ2B,EAAQ,WAAW3B,EAAY,UAAU2B,EAAQ,WAAW3B,EAAY,YAC/GJ,EAAM,QAAQ,MAEZ4B,EAAS,cAAczB,EAAK,aAAayB,EAAS,UAAUzB,EAAK,SAASyB,EAAS,SAASzB,EAAK,YAAY,QAAQ,KACrHyB,EAAS,WAAWzB,EAAK,aAAc,SAAS,KAChD4B,EAAQ,QAAQ3B,EAAY,OAAK6C,GAAYlB,EAAQ,GAAG;AAC5D,UAAM+B,IAAQ5B,EAAWH,GAASH,EAAS,QAAQ;AACnD,IAAIA,EAAS,aAAazB,EAAK,YAAY2D,MAAU5B,EAAW9B,GAAaD,EAAK,QAAQ,MACxFmD,EAAA,GACIQ,MAAW1F,CAAM,MACV,MAAA,IAEb+B,IAAOyB,GACPxB,IAAc2B,IACV/B,EAAM,aAAaA,EAAM,SAASA,EAAM,SAASA,EAAM,WAAQ0B,EAAA;AAAA,EACrE,CAAC;AAED,SAAO;AAAA,IACL,OAAAnB;AAAA,IACA,UAAU;AACR,MAAAP,EAAM,QAAQ,IACd0B,EAAA;AAAA,IACF;AAAA,IACA,IAAIqC,GAAO;AACT,YAAMC,IAAQ,UAAUD,IAAQxD,EAAM,iBAAiBwD,EAAM,IAAI,IAAIxD,EAAM,oBAAoBwD,EAAM,OAAO;AAC5G,aAAO,MAAM,KAAKC,CAAK;AAAA,IACzB;AAAA,IACA,OAAOC,GAAQ;AACb,MAAA1D,EAAM,aAAaA,EAAM,aAAA,IAAiB0D,GAAQ,GAAG;AAAA,IACvD;AAAA,IACA,KAAK,MAAMtD,EAAO,IAAA;AAAA,IAClB,QAAQ;AACN,MAAA2C,EAAA,GACA/C,EAAM,MAAA;AAAA,IACR;AAAA,IACA,SAAS;AACP,MAAA+C,EAAA,GACgB5E,EAAM,YAAA,EAAc,WAAW,aAChC,CAACU,IAAM0D,EAAI1E,CAAM,MACrB,QAAA;AAAA,IACb;AAAA,IACA,UAAU;AACR,MAAAkF,EAAA,GACA5E,EAAM,IAAI,EAAE,GACZoE,EAAI,CAAC;AAAA,IACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,QAAQ;AACN,YAAM,EAAE,QAAAzB,GAAQ,QAAAC,MAAW5C,EAAM,YAAA;AACjC,MAAI4C,EAAO,WAAW,MACtBgC,EAAA,GACA5E,EAAM,IAAI,EAAE,GACZoE,EAAI1E,CAAM,GACNiD,MAAW,aACb7B,IAAQ,OAAO,WAAW,MAAM;AAC9B,QAAAA,IAAQ,GACRe,EAAM,MAAA;AAAA,MACR,GAAGlC,EAAa;AAAA,IAEpB;AAAA,IACA,OAAO+C,GAAQ;AACb,MAAIA,KAAUf,QACdkB,EAAQH,CAAM,GACdb,EAAM,mBAAmBa,GAAQ,KAAK,GAAG,EAAI;AAAA,IAC/C;AAAA,IACA,iBAAiB;;AACf,YAAM8C,OAAY5D,IAAA5B,EAAM,YAAA,EAAc,cAApB,gBAAA4B,EAA+B,aAAY,CAAA,GAAI,OAAO,CAAC6D,MAAOA,IAAK9D,GAAM;AAC3F,MAAI6D,EAAS,SAAS,OAAS,sBAAsBA,GAAUE,IAAc,IAAI;AAAA,IACnF;AAAA,IACA,OAAA5C;AAAA,IACA,UAAU;AACR,MAAAqC,GAAA,GACAP,EAAA,GACIrD,0BAA4BA,CAAK,GACrC,aAAa2D,CAAQ,GACrBjD,EAAO,QAAA,GACP/B,IAAY;AAEZ,YAAMyF,IAAS5F,EAAK,cAAc,QAAQ;AAC1C,MAAA4F,KAAA,QAAAA,EAAQ,oBAAoB,oBAAoBb,IAChDjD,EAAM,QAAA,GACN+D,GAAeD,CAAM;AAAA,IACvB;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"renderer.js","sources":["../../src/render/renderer.ts"],"sourcesContent":["import { Graph } from \"@cosmos.gl/graph\";\nimport { GraphError } from \"../core/error\";\nimport type { Geometry } from \"../core/load\";\nimport type { GraphStore } from \"../core/store\";\nimport type { GraphCommands, Motion, VertexId } from \"../core/types\";\nimport { resolveLook, type Look } from \"./graph-looks\";\nimport { appearance, forces, paint } from \"./graph-model\";\nimport { resolveSim, type Sim } from \"./graph-sim\";\nimport { createCamera, FIT_DURATION } from \"./camera\";\nimport { decayFor, highlighted, LINKS_WHILE_RUNNING, simulating } from \"./motion\";\nimport { cornersOf, placed, placementOf } from \"./placement\";\nimport { releaseContext, webglBox } from \"./webgl\";\n\nexport interface RendererEvents {\n /** After every frame and every camera move — where the overlays repaint. */\n onFrame?: () => void;\n /** Where the hovered point is in space, as cosmos.gl reports it: no GPU readback per hover. */\n onHover?: (position: [number, number] | null) => void;\n}\n\nexport interface Renderer extends GraphCommands {\n readonly graph: Graph;\n /** The theme moved under the canvas: colours are resolved again, nothing else. */\n repaint(): void;\n /** The drawn points inside a screen rectangle or polygon, once the device is ready. */\n hit(shape: { rect: [[number, number], [number, number]] } | { polygon: [number, number][] }): number[];\n destroy(): void;\n}\n\nconst REHEAT = 0.35;\n/** How long a release wakes a paused layout before pausing it again. */\nconst RELEASE_BURST = 1200;\n/** Twentieths: a settle costs twenty reports rather than one per frame. */\nconst PROGRESS_STEPS = 20;\n\n/**\n * The slowest honest answer for a GPU device: one comes up in milliseconds when it can be made at\n * all, so ten seconds is a device that will not come, not one that is slow.\n */\nconst READY_DEADLINE = 10_000;\n\n/**\n * **cosmos.gl's lifetime, and the frame that renders once.** Built once per element; it subscribes to\n * the store and discharges what changed in one `requestAnimationFrame`:\n *\n * - a new graph uploads positions and links, once per corpus and per position binding;\n * - a binding, a look or a theme change uploads colours, sizes, shapes and clusters and nothing else;\n * - a filter, a selection, a focus or a pin sets config and uploads nothing, and never calls\n * `render()`: a vertex the page's filter does not keep is greyed out, Cosmograph's way, so the\n * points never move because a chart was brushed;\n * - the camera reaches nothing: cosmos.gl moves it, and the overlays follow.\n *\n * A vertex's id is its index here, so nothing is resolved between the store and the buffers.\n * `transitionDuration` is 0: the default animates every upload for 800 ms and keeps the loop awake.\n * The layout runs on its own when `x` and `y` are unbound, and from the current positions.\n * Every callback reads the store's latest options, so a host's inline `onFailure` never rebuilds it.\n * A failure to draw at all marks the store `failed` through `unrenderable`, never `onFailure` alone.\n */\nexport function createRenderer(host: HTMLDivElement, store: GraphStore, events: RendererEvents = {}): Renderer | null {\n let destroyed = false;\n const fail = (error: unknown) => {\n if (!destroyed) store.unrenderable(error);\n };\n const box = webglBox();\n if (box === null) {\n fail(new GraphError(\"graph/no-webgl\", \"This browser offers no WebGL context to draw with.\"));\n return null;\n }\n\n let sim: Sim = resolveSim(store.getOptions().sim);\n let live = false;\n /** Whether a layout is moving the points — ours, since cosmos.gl's flag waits for its device. */\n let moving = false;\n let hovering: number | null = null;\n let dragging: number | null = null;\n let burst = 0;\n let reported = -1;\n const progress = (value: number) => {\n const bucket = Math.round(value * PROGRESS_STEPS);\n if (bucket === reported) return;\n reported = bucket;\n store.reportProgress(bucket / PROGRESS_STEPS);\n };\n\n let look: Look = resolveLook(store.getOptions().look);\n let lookPatch = store.getOptions().look;\n const dirty = { positions: true, paint: true, state: true, pinned: true };\n let frame = 0;\n let links: Float32Array | null = null;\n let last = store.getSnapshot();\n let lastOptions = store.getOptions();\n\n const size = () => store.getSnapshot().geometry?.size ?? 0;\n\n let graph: Graph;\n try {\n graph = new Graph(host, {\n // No `spaceSize` here: it is the geometry's, set when the graph has loaded.\n // `rescalePositions: false` because the placement below is ours.\n rescalePositions: false,\n fitViewOnInit: false,\n transitionDuration: 0,\n enableSimulation: live,\n ...forces(sim),\n randomSeed: \"kanzo-discovery\",\n pixelRatio: window.devicePixelRatio || 1,\n enableDrag: true,\n hoveredPointCursor: \"pointer\",\n attribution: \"\",\n onSimulationStart: () => store.report(\"running\"),\n onSimulationEnd: () => {\n moved(\"settled\");\n progress(1);\n camera.settle();\n events.onFrame?.();\n },\n onSimulationPause: () => moved(\"paused\"),\n onSimulationUnpause: () => moved(\"running\"),\n onSimulationTick: (_alpha, index, position) => {\n progress(graph.progress);\n camera.tick();\n if (index !== undefined && position) events.onHover?.(position);\n events.onFrame?.();\n },\n onZoomStart: (_event, userDriven) => taken(userDriven),\n onZoom: () => events.onFrame?.(),\n onPointMouseOver: (index, position) => {\n hovering = index;\n events.onHover?.(position);\n store.hover(index);\n },\n onPointMouseOut: () => {\n hovering = null;\n events.onHover?.(null);\n store.hover(null);\n },\n onDragStart: () => {\n dragging = hovering;\n },\n onDrag: (event) => {\n events.onHover?.(graph.screenToSpacePosition([event.x, event.y]));\n events.onFrame?.();\n },\n // d3-force's drag-to-fix, and only while a layout can move the point back: cosmos.gl moves a\n // dragged point with the simulation off too, and a pin nothing pulls against means nothing.\n onDragEnd: () => {\n const vertex = dragging;\n dragging = null;\n const { motion, pinned } = store.getSnapshot();\n if (vertex !== null && motion !== \"settled\" && !pinned.includes(vertex)) store.pin([...pinned, vertex]);\n },\n onPointClick: (index) => focusOn(index),\n onBackgroundClick: () => clear(),\n });\n } catch (error) {\n fail(new GraphError(\"graph/no-webgl\", \"The renderer failed to start.\", {}, { cause: error }));\n return null;\n }\n const { camera, taken } = createCamera(graph, host, fail);\n\n const schedule = () => {\n if (frame) return;\n frame = requestAnimationFrame(() => {\n frame = 0;\n draw();\n });\n };\n\n function draw(): void {\n const snapshot = store.getSnapshot();\n const { geometry, encoding } = snapshot;\n const options = store.getOptions();\n // Positions wait for the first colours, so a graph's first frame is the drawn one, not a grey one.\n const placing = dirty.positions && encoding ? geometry : null;\n if (placing) {\n dirty.positions = false;\n graph.setPointPositions(position(placing), true);\n if (placing.links !== links) {\n links = placing.links;\n graph.setLinks(links);\n dirty.paint = dirty.state = dirty.pinned = true;\n }\n }\n const painting = dirty.paint && geometry && encoding;\n if (painting) {\n dirty.paint = false;\n const buffers = paint(geometry, encoding, look, host, options);\n graph.setPointColors(buffers.colors);\n graph.setPointSizes(buffers.sizes);\n graph.setPointShapes(buffers.shapes);\n graph.setLinkColors(buffers.linkColors);\n graph.setPointClusters(encoding.clusters ?? []);\n graph.setConfigPartial({ ...appearance(look, host), renderLinks: linksShown() });\n }\n if (dirty.state && geometry) {\n dirty.state = false;\n graph.setConfigPartial({\n ...highlighted(geometry, snapshot.mask, snapshot.selection?.vertices ?? null),\n focusedPointIndex: snapshot.focus === null || snapshot.focus >= geometry.size ? undefined : snapshot.focus,\n });\n }\n if (dirty.pinned && geometry) {\n dirty.pinned = false;\n graph.setPinnedPoints(snapshot.pinned.length > 0 ? [...snapshot.pinned] : null);\n }\n if (painting || placing) graph.render();\n if (placing) layout(placing, simulating(options, placing)); // after render(): cosmos.gl 3.4 turning its simulation on drops unrendered uploads\n if (geometry && encoding && !dirty.paint) store.reportDrawn(snapshot);\n events.onFrame?.();\n }\n\n /** The positions cosmos.gl gets: bound, the data's extent centred in the device's box; unbound, the seeded start. */\n function position(geometry: Geometry): Float32Array {\n const placement = geometry.bound && geometry.extent ? placementOf(geometry.extent, box as number) : null;\n graph.setConfigPartial({ spaceSize: placement?.side ?? geometry.space, simulationDecay: decayFor(geometry.size) });\n if (!placement || !geometry.extent) return geometry.positions;\n camera.frame(cornersOf(geometry.extent, placement));\n return placed(geometry.positions, placement);\n }\n\n /** A new geometry lays itself out when its positions are a start, and stands still when they are data. */\n function layout(geometry: Geometry, running: boolean): void {\n camera.drawn();\n if (running) return run(1);\n if (live) graph.pause();\n if (!geometry.bound) camera.fit();\n }\n\n /** Whether links are drawn now: the look's choice, unless a large layout is running. */\n const linksShown = (): boolean => look.link.render && !(moving && (links?.length ?? 0) / 2 > LINKS_WHILE_RUNNING);\n const showLinks = () => graph.setConfigPartial({ renderLinks: linksShown() });\n function moved(motion: Motion): void {\n moving = motion === \"running\";\n showLinks();\n store.report(motion);\n }\n\n function applyForces(patch: Partial<Sim> | undefined): void {\n const next = resolveSim(patch);\n const moved = Object.keys(next).some((key) => next[key as keyof Sim] !== sim[key as keyof Sim]);\n sim = next;\n if (!live) return;\n graph.setConfigPartial(forces(next));\n if (moved && store.getSnapshot().motion !== \"paused\") graph.start(REHEAT);\n }\n\n /** A layout runs from where the points are: enabling cosmos.gl's simulation keeps its positions. */\n function run(alpha: number): void {\n if (!live) {\n live = true;\n graph.setConfigPartial({ enableSimulation: true, ...forces(sim) });\n }\n camera.run();\n moving = true;\n graph.start(alpha);\n showLinks();\n }\n\n function endBurst(): void {\n clearTimeout(burst);\n burst = 0;\n }\n\n function focusOn(vertex: VertexId): void {\n const around = graph.getNeighboringPointIndices(vertex) ?? [];\n store.select([vertex, ...around], \"node\", \"Node\");\n store.focus(vertex);\n }\n\n function clear(): void {\n store.select(null);\n store.focus(null);\n }\n\n // cosmos.gl 3.4 queues every setter and command until its device exists (`ensureDevice`), and its\n // two synchronous hit tests answer `[]` until then; only the canvas element has to wait for `ready`.\n graph.setConfigPartial(appearance(look, host));\n graph.render();\n const onLost = (event: Event) => {\n event.preventDefault();\n fail(new GraphError(\"graph/context-lost\", \"The browser took back the WebGL context; reload to get one.\"));\n };\n const noDevice = (data: GraphError[\"data\"], cause?: unknown) =>\n fail(new GraphError(\"graph/no-webgl\", \"No GPU device came up to draw with.\", data, { cause }));\n // `ready` never settles when cosmos.gl cannot make a device, so the deadline is what ends the wait.\n const deadline = setTimeout(() => noDevice({ after: READY_DEADLINE }), READY_DEADLINE);\n void graph.ready.then(\n () => {\n clearTimeout(deadline);\n if (!destroyed) host.querySelector(\"canvas\")?.addEventListener(\"webglcontextlost\", onLost);\n camera.ready();\n },\n (error: unknown) => {\n clearTimeout(deadline);\n noDevice({}, error);\n },\n );\n store.report(live && graph.isSimulationRunning ? \"running\" : \"settled\");\n schedule();\n\n const unsubscribe = store.subscribe(() => {\n const snapshot = store.getSnapshot();\n const options = store.getOptions();\n if (snapshot.geometry !== last.geometry) dirty.positions = true;\n if (snapshot.encoding !== last.encoding) dirty.paint = true;\n if (options.look !== lookPatch) {\n lookPatch = options.look;\n look = resolveLook(options.look);\n dirty.paint = true;\n }\n if (options.fill !== lastOptions.fill || options.symbol !== lastOptions.symbol || options.stroke !== lastOptions.stroke) {\n dirty.paint = true;\n }\n if (snapshot.selection !== last.selection || snapshot.focus !== last.focus || snapshot.mask !== last.mask) dirty.state = true;\n if (snapshot.pinned !== last.pinned) dirty.pinned = true;\n if (options.sim !== lastOptions.sim) applyForces(options.sim);\n const wants = simulating(options, snapshot.geometry);\n if (snapshot.geometry === last.geometry && wants !== simulating(lastOptions, last.geometry)) {\n endBurst();\n if (wants) run(REHEAT);\n else graph.pause();\n }\n last = snapshot;\n lastOptions = options;\n if (dirty.positions || dirty.paint || dirty.state || dirty.pinned) schedule();\n });\n\n return {\n graph,\n repaint() {\n dirty.paint = true;\n schedule();\n },\n hit(shape) {\n const found = \"rect\" in shape ? graph.findPointsInRect(shape.rect) : graph.findPointsInPolygon(shape.polygon);\n return Array.from(found);\n },\n zoomBy(factor) {\n graph.setZoomLevel(graph.getZoomLevel() * factor, 220);\n },\n fit: () => camera.fit(),\n pause() {\n endBurst();\n graph.pause();\n },\n resume() {\n endBurst();\n const settled = store.getSnapshot().motion === \"settled\";\n if (settled || !live) run(REHEAT);\n else graph.unpause();\n },\n restart() {\n endBurst();\n store.pin([]);\n run(1);\n },\n /**\n * d3's release: unfix, then reheat, so the released points visibly flow back. A running layout\n * takes the heat and goes on; a settled one cools to settled on its own; a paused one gets a\n * bounded burst and is paused again, because the reader paused it.\n */\n unpin() {\n const { motion, pinned } = store.getSnapshot();\n if (pinned.length === 0) return;\n endBurst();\n store.pin([]);\n run(REHEAT);\n if (motion === \"paused\") {\n burst = window.setTimeout(() => {\n burst = 0;\n graph.pause();\n }, RELEASE_BURST);\n }\n },\n reveal(vertex) {\n if (vertex >= size()) return;\n focusOn(vertex);\n graph.zoomToPointByIndex(vertex, 500, 5, true);\n },\n frameSelection() {\n const vertices = (store.getSnapshot().selection?.vertices ?? []).filter((id) => id < size());\n if (vertices.length > 0) graph.fitViewByPointIndices(vertices, FIT_DURATION, 0.25);\n },\n clear,\n destroy() {\n unsubscribe();\n endBurst();\n if (frame) cancelAnimationFrame(frame);\n clearTimeout(deadline);\n camera.destroy();\n destroyed = true;\n // Read here rather than remembered from construction: the element exists only with the device.\n const canvas = host.querySelector(\"canvas\");\n canvas?.removeEventListener(\"webglcontextlost\", onLost);\n graph.destroy();\n releaseContext(canvas);\n },\n };\n}\n"],"names":["REHEAT","RELEASE_BURST","PROGRESS_STEPS","READY_DEADLINE","createRenderer","host","store","events","destroyed","fail","error","box","webglBox","GraphError","sim","resolveSim","live","moving","hovering","dragging","burst","reported","progress","value","bucket","look","resolveLook","lookPatch","dirty","frame","links","last","lastOptions","size","_a","graph","Graph","forces","moved","camera","_alpha","index","position","_b","_event","userDriven","taken","event","vertex","motion","pinned","focusOn","clear","createCamera","schedule","draw","snapshot","geometry","encoding","options","placing","painting","buffers","paint","appearance","linksShown","highlighted","layout","simulating","placement","placementOf","decayFor","cornersOf","placed","running","run","LINKS_WHILE_RUNNING","showLinks","applyForces","patch","next","key","alpha","endBurst","around","onLost","noDevice","data","cause","deadline","unsubscribe","wants","shape","found","factor","vertices","id","FIT_DURATION","canvas","releaseContext"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanzo-tech/graph",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "description": "Kanzo graph view — a fossil corpus attached to the page's DuckDB, read through the page's Mosaic coordinator as one more client, laid out and drawn with cosmos.gl on the GPU. Sibling of @kanzo-tech/ui, not part of it: the admission rules exclude graphs from the generic vocabulary by name.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,8 +28,8 @@
28
28
  "@cosmos.gl/graph": "^3.4.0",
29
29
  "lucide-react": ">=1",
30
30
  "react": "^19.0.0",
31
- "@kanzo-tech/mosaic": "0.26.0",
32
- "@kanzo-tech/ui": "0.26.0"
31
+ "@kanzo-tech/mosaic": "0.28.0",
32
+ "@kanzo-tech/ui": "0.28.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@cosmos.gl/graph": "^3.4.0",
@@ -39,21 +39,21 @@
39
39
  "@testing-library/user-event": "^14.6.1",
40
40
  "@types/react": "^19.0.0",
41
41
  "@types/react-dom": "^19.0.0",
42
- "@uwdata/mosaic-core": "^0.29.2",
43
- "@uwdata/mosaic-sql": "^0.29.0",
42
+ "@uwdata/mosaic-core": "^0.32.0",
43
+ "@uwdata/mosaic-sql": "^0.32.0",
44
44
  "jsdom": "^25.0.0",
45
45
  "lucide-react": "^1.23.0",
46
46
  "react": "^19.0.0",
47
47
  "react-dom": "^19.0.0",
48
48
  "rollup-plugin-preserve-directives": "^0.4.0",
49
- "@kanzo-tech/mosaic": "0.26.0"
49
+ "@kanzo-tech/mosaic": "0.28.0"
50
50
  },
51
- "//size-limit": "Budgets our code only: `ignore` mirrors the peers the build externalises in vite.config.ts, cosmos.gl included (about 190 kB gzipped on its own, and the consumer pays it once whatever this package does). First measured 2026-09-30 at 19.07 kB, before the lag work of `perf/phase1-lag`; 19.13 kB before the whole-corpus store deleted the tileset, 15.29 kB after it, and the budget follows it down so real growth trips the gate. Raised to 18 kB on 2026-10-01 as a decision: 17.71 kB after GraphCounts, GraphSearch and GraphLooks moved in from the workspace showcase (their code left the host, it did not appear from nowhere) and the drag-to-fix release. Raised to 18.5 kB on 2026-10-02 as a decision (Ángel): 18.01 kB once the layout's square placement and the camera that follows a running layout landed.",
51
+ "//size-limit": "Budgets our code only: `ignore` mirrors the peers the build externalises in vite.config.ts, cosmos.gl included (about 190 kB gzipped on its own, and the consumer pays it once whatever this package does). First measured 2026-09-30 at 19.07 kB, before the lag work of `perf/phase1-lag`; 19.13 kB before the whole-corpus store deleted the tileset, 15.29 kB after it, and the budget follows it down so real growth trips the gate. Raised to 18 kB on 2026-10-01 as a decision: 17.71 kB after GraphCounts, GraphSearch and GraphLooks moved in from the workspace showcase (their code left the host, it did not appear from nowhere) and the drag-to-fix release. Raised to 18.5 kB on 2026-10-02 as a decision (Ángel): 18.01 kB once the layout's square placement and the camera that follows a running layout landed. Raised to 19 kB on 2026-10-03 as a decision (Ángel): 18.58 kB once GraphSelect moved in from the hosts (which drop their copies) and the camera stopped reading positions cosmos.gl had not uploaded.",
52
52
  "size-limit": [
53
53
  {
54
54
  "name": "root barrel (JS)",
55
55
  "path": "dist/index.js",
56
- "limit": "18.5 kB",
56
+ "limit": "19 kB",
57
57
  "ignore": [
58
58
  "react",
59
59
  "react-dom",