@kanzo-tech/graph 0.9.0 → 0.11.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 (204) hide show
  1. package/README.md +60 -95
  2. package/dist/core/categories.d.ts +12 -0
  3. package/dist/core/categories.d.ts.map +1 -0
  4. package/dist/core/categories.js +14 -0
  5. package/dist/core/categories.js.map +1 -0
  6. package/dist/core/channels.d.ts +34 -0
  7. package/dist/core/channels.d.ts.map +1 -0
  8. package/dist/core/channels.js +19 -0
  9. package/dist/core/channels.js.map +1 -0
  10. package/dist/core/detail.d.ts +18 -0
  11. package/dist/core/detail.d.ts.map +1 -0
  12. package/dist/core/detail.js +20 -0
  13. package/dist/core/detail.js.map +1 -0
  14. package/dist/core/filter.d.ts +34 -0
  15. package/dist/core/filter.d.ts.map +1 -0
  16. package/dist/core/filter.js +99 -0
  17. package/dist/core/filter.js.map +1 -0
  18. package/dist/core/refine.d.ts +14 -0
  19. package/dist/core/refine.d.ts.map +1 -0
  20. package/dist/core/refine.js +20 -0
  21. package/dist/core/refine.js.map +1 -0
  22. package/dist/{resident.d.ts → core/resident.d.ts} +8 -8
  23. package/dist/core/resident.d.ts.map +1 -0
  24. package/dist/core/resident.js +44 -0
  25. package/dist/core/resident.js.map +1 -0
  26. package/dist/core/scheduler.d.ts +42 -0
  27. package/dist/core/scheduler.d.ts.map +1 -0
  28. package/dist/core/scheduler.js +77 -0
  29. package/dist/core/scheduler.js.map +1 -0
  30. package/dist/core/state.d.ts +132 -0
  31. package/dist/core/state.d.ts.map +1 -0
  32. package/dist/core/store.d.ts +6 -0
  33. package/dist/core/store.d.ts.map +1 -0
  34. package/dist/core/store.js +235 -0
  35. package/dist/core/store.js.map +1 -0
  36. package/dist/core/tile-matrix.d.ts +37 -0
  37. package/dist/core/tile-matrix.d.ts.map +1 -0
  38. package/dist/core/tile-matrix.js +49 -0
  39. package/dist/core/tile-matrix.js.map +1 -0
  40. package/dist/core/tile.d.ts +54 -0
  41. package/dist/core/tile.d.ts.map +1 -0
  42. package/dist/core/tile.js +76 -0
  43. package/dist/core/tile.js.map +1 -0
  44. package/dist/core/tileset.d.ts +59 -0
  45. package/dist/core/tileset.d.ts.map +1 -0
  46. package/dist/core/tileset.js +177 -0
  47. package/dist/core/tileset.js.map +1 -0
  48. package/dist/{types.d.ts → core/types.d.ts} +9 -0
  49. package/dist/core/types.d.ts.map +1 -0
  50. package/dist/index.d.ts +37 -70
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +32 -34
  53. package/dist/index.js.map +1 -1
  54. package/dist/{use-graph-selection.d.ts → parts/gesture.d.ts} +4 -4
  55. package/dist/parts/gesture.d.ts.map +1 -0
  56. package/dist/{use-graph-selection.js → parts/gesture.js} +17 -17
  57. package/dist/parts/gesture.js.map +1 -0
  58. package/dist/parts/graph-canvas.d.ts +17 -0
  59. package/dist/parts/graph-canvas.d.ts.map +1 -0
  60. package/dist/parts/graph-canvas.js +174 -0
  61. package/dist/parts/graph-canvas.js.map +1 -0
  62. package/dist/parts/graph-inspector.d.ts +18 -0
  63. package/dist/parts/graph-inspector.d.ts.map +1 -0
  64. package/dist/parts/graph-inspector.js +84 -0
  65. package/dist/parts/graph-inspector.js.map +1 -0
  66. package/dist/parts/graph-legend.d.ts +12 -0
  67. package/dist/parts/graph-legend.d.ts.map +1 -0
  68. package/dist/parts/graph-legend.js +61 -0
  69. package/dist/parts/graph-legend.js.map +1 -0
  70. package/dist/parts/graph-toolbar.d.ts +15 -0
  71. package/dist/parts/graph-toolbar.d.ts.map +1 -0
  72. package/dist/parts/graph-toolbar.js +94 -0
  73. package/dist/parts/graph-toolbar.js.map +1 -0
  74. package/dist/parts/overlays.d.ts +33 -0
  75. package/dist/parts/overlays.d.ts.map +1 -0
  76. package/dist/{use-graph-overlays.js → parts/overlays.js} +8 -8
  77. package/dist/parts/overlays.js.map +1 -0
  78. package/dist/{shape-glyph.d.ts → parts/shape-glyph.d.ts} +1 -1
  79. package/dist/parts/shape-glyph.d.ts.map +1 -0
  80. package/dist/{shape-glyph.js → parts/shape-glyph.js} +1 -1
  81. package/dist/parts/shape-glyph.js.map +1 -0
  82. package/dist/react/graph-root.d.ts +15 -0
  83. package/dist/react/graph-root.d.ts.map +1 -0
  84. package/dist/react/graph-root.js +23 -0
  85. package/dist/react/graph-root.js.map +1 -0
  86. package/dist/{use-graph-prefs.d.ts → react/use-graph-prefs.d.ts} +2 -2
  87. package/dist/react/use-graph-prefs.d.ts.map +1 -0
  88. package/dist/{use-graph-prefs.js → react/use-graph-prefs.js} +3 -3
  89. package/dist/react/use-graph-prefs.js.map +1 -0
  90. package/dist/react/use-graph-state.d.ts +11 -0
  91. package/dist/react/use-graph-state.d.ts.map +1 -0
  92. package/dist/react/use-graph-state.js +16 -0
  93. package/dist/react/use-graph-state.js.map +1 -0
  94. package/dist/react/use-graph.d.ts +38 -0
  95. package/dist/react/use-graph.d.ts.map +1 -0
  96. package/dist/react/use-graph.js +87 -0
  97. package/dist/react/use-graph.js.map +1 -0
  98. package/dist/{adaptive.d.ts → render/adaptive.d.ts} +1 -1
  99. package/dist/render/adaptive.d.ts.map +1 -0
  100. package/dist/render/adaptive.js.map +1 -0
  101. package/dist/render/compose.d.ts +51 -0
  102. package/dist/render/compose.d.ts.map +1 -0
  103. package/dist/render/compose.js +107 -0
  104. package/dist/render/compose.js.map +1 -0
  105. package/dist/render/css-color.d.ts.map +1 -0
  106. package/dist/render/css-color.js.map +1 -0
  107. package/dist/render/encode.d.ts +42 -0
  108. package/dist/render/encode.d.ts.map +1 -0
  109. package/dist/render/encode.js +68 -0
  110. package/dist/render/encode.js.map +1 -0
  111. package/dist/render/graph-looks.d.ts.map +1 -0
  112. package/dist/render/graph-looks.js.map +1 -0
  113. package/dist/render/graph-model.d.ts +44 -0
  114. package/dist/render/graph-model.d.ts.map +1 -0
  115. package/dist/render/graph-model.js +80 -0
  116. package/dist/render/graph-model.js.map +1 -0
  117. package/dist/{graph-sim.d.ts → render/graph-sim.d.ts} +2 -2
  118. package/dist/render/graph-sim.d.ts.map +1 -0
  119. package/dist/render/graph-sim.js.map +1 -0
  120. package/dist/{obligations.d.ts → render/obligations.d.ts} +1 -1
  121. package/dist/render/obligations.d.ts.map +1 -0
  122. package/dist/render/renderer.d.ts +38 -0
  123. package/dist/render/renderer.d.ts.map +1 -0
  124. package/dist/render/renderer.js +235 -0
  125. package/dist/render/renderer.js.map +1 -0
  126. package/dist/render/webgl.d.ts +14 -0
  127. package/dist/render/webgl.d.ts.map +1 -0
  128. package/dist/render/webgl.js +19 -0
  129. package/dist/render/webgl.js.map +1 -0
  130. package/dist/render/when-ready.d.ts.map +1 -0
  131. package/dist/render/when-ready.js.map +1 -0
  132. package/package.json +11 -21
  133. package/dist/adaptive.d.ts.map +0 -1
  134. package/dist/adaptive.js.map +0 -1
  135. package/dist/bounded.d.ts +0 -364
  136. package/dist/bounded.d.ts.map +0 -1
  137. package/dist/bounded.js +0 -18
  138. package/dist/bounded.js.map +0 -1
  139. package/dist/cluster-ring.d.ts +0 -25
  140. package/dist/cluster-ring.d.ts.map +0 -1
  141. package/dist/cluster-ring.js +0 -16
  142. package/dist/cluster-ring.js.map +0 -1
  143. package/dist/css-color.d.ts.map +0 -1
  144. package/dist/css-color.js.map +0 -1
  145. package/dist/duck-source.d.ts +0 -198
  146. package/dist/duck-source.d.ts.map +0 -1
  147. package/dist/duck-source.js +0 -320
  148. package/dist/duck-source.js.map +0 -1
  149. package/dist/graph-canvas.d.ts +0 -50
  150. package/dist/graph-canvas.d.ts.map +0 -1
  151. package/dist/graph-canvas.js +0 -35
  152. package/dist/graph-canvas.js.map +0 -1
  153. package/dist/graph-looks.d.ts.map +0 -1
  154. package/dist/graph-looks.js.map +0 -1
  155. package/dist/graph-model.d.ts +0 -130
  156. package/dist/graph-model.d.ts.map +0 -1
  157. package/dist/graph-model.js +0 -104
  158. package/dist/graph-model.js.map +0 -1
  159. package/dist/graph-sim.d.ts.map +0 -1
  160. package/dist/graph-sim.js.map +0 -1
  161. package/dist/obligations.d.ts.map +0 -1
  162. package/dist/resident.d.ts.map +0 -1
  163. package/dist/resident.js +0 -44
  164. package/dist/resident.js.map +0 -1
  165. package/dist/shape-glyph.d.ts.map +0 -1
  166. package/dist/shape-glyph.js.map +0 -1
  167. package/dist/slice-client.d.ts +0 -78
  168. package/dist/slice-client.d.ts.map +0 -1
  169. package/dist/slice-client.js +0 -98
  170. package/dist/slice-client.js.map +0 -1
  171. package/dist/types.d.ts.map +0 -1
  172. package/dist/use-graph-look.d.ts +0 -28
  173. package/dist/use-graph-look.d.ts.map +0 -1
  174. package/dist/use-graph-look.js +0 -28
  175. package/dist/use-graph-look.js.map +0 -1
  176. package/dist/use-graph-overlays.d.ts +0 -44
  177. package/dist/use-graph-overlays.d.ts.map +0 -1
  178. package/dist/use-graph-overlays.js.map +0 -1
  179. package/dist/use-graph-prefs.d.ts.map +0 -1
  180. package/dist/use-graph-prefs.js.map +0 -1
  181. package/dist/use-graph-selection.d.ts.map +0 -1
  182. package/dist/use-graph-selection.js.map +0 -1
  183. package/dist/use-graph.d.ts +0 -203
  184. package/dist/use-graph.d.ts.map +0 -1
  185. package/dist/use-graph.js +0 -102
  186. package/dist/use-graph.js.map +0 -1
  187. package/dist/use-query-loop.d.ts +0 -88
  188. package/dist/use-query-loop.d.ts.map +0 -1
  189. package/dist/use-query-loop.js +0 -148
  190. package/dist/use-query-loop.js.map +0 -1
  191. package/dist/use-renderer.d.ts +0 -86
  192. package/dist/use-renderer.d.ts.map +0 -1
  193. package/dist/use-renderer.js +0 -188
  194. package/dist/use-renderer.js.map +0 -1
  195. package/dist/when-ready.d.ts.map +0 -1
  196. package/dist/when-ready.js.map +0 -1
  197. /package/dist/{adaptive.js → render/adaptive.js} +0 -0
  198. /package/dist/{css-color.d.ts → render/css-color.d.ts} +0 -0
  199. /package/dist/{css-color.js → render/css-color.js} +0 -0
  200. /package/dist/{graph-looks.d.ts → render/graph-looks.d.ts} +0 -0
  201. /package/dist/{graph-looks.js → render/graph-looks.js} +0 -0
  202. /package/dist/{graph-sim.js → render/graph-sim.js} +0 -0
  203. /package/dist/{when-ready.d.ts → render/when-ready.d.ts} +0 -0
  204. /package/dist/{when-ready.js → render/when-ready.js} +0 -0
@@ -1,86 +0,0 @@
1
- import { RefObject } from 'react';
2
- import { Graph } from '@cosmos.gl/graph';
3
- import { Sim } from './graph-sim';
4
- import { Motion } from './types';
5
- export interface RendererOptions {
6
- /** The element cosmos.gl mounts its canvas into. */
7
- hostRef: RefObject<HTMLDivElement | null>;
8
- /**
9
- * Where to put the instance.
10
- *
11
- * Given rather than returned, because the overlays, the gesture and the query loop all need a way
12
- * to reach the graph and this hook needs their callbacks — returning it would make the
13
- * declarations circular.
14
- */
15
- graphRef: RefObject<Graph | null>;
16
- /**
17
- * Whether to run a live layout, and it **defaults to off**.
18
- *
19
- * ADR-0001's premise: positions are authority. A bounded source hands back coordinates that the
20
- * next spatial query is expressed in, so a force that moves them moves the picture out from under
21
- * its own index — the camera drifts away from the corpus within a frame. Off is therefore the
22
- * correct default and not a conservative one.
23
- *
24
- * On is for the other host: arrays in hand, no precomputed layout, few enough points that a live
25
- * simulation is the cheapest way to get one. That host has no spatial index to disagree with.
26
- */
27
- simulate?: boolean;
28
- /**
29
- * Cluster assignment per drawn point, when a live layout should group them.
30
- *
31
- * Only meaningful under `simulate` — it is a force, not a colour. `undefined` at a position means
32
- * *no group*, which is not group zero: a vertex shared by every group belongs to none, and left
33
- * unclustered it drifts between the ones it joins.
34
- */
35
- clusters?: (number | undefined)[];
36
- /** Defaults to `DEFAULT_SIM`, which is the same table the exported constant carries. */
37
- sim?: Sim;
38
- /** Where to report what the layout is doing. Optional: a host with no motion badge wants none. */
39
- report?: (motion: Motion) => void;
40
- /**
41
- * How far through settling the layout is, `0`–`1`.
42
- *
43
- * cosmos.gl computes it every tick as `√(min(1, ALPHA_MIN / alpha))` and exposes it as
44
- * `graph.progress`, so a determinate badge costs nothing to compute — only to deliver. Quantised
45
- * before it is reported, because this is React state read through context and a write per
46
- * animation frame would re-render every consumer 60 times a second to move a number by half a
47
- * percent.
48
- */
49
- reportProgress?: (value: number) => void;
50
- onFailure: (message: string) => void;
51
- /**
52
- * Callbacks handed to cosmos.gl once, at construction — **all optional, and so is the block**.
53
- *
54
- * They were required, and a graph that only wants to be *looked at* had to write seven no-ops to
55
- * say so. A picture with no interaction is a legitimate picture, and the seven that report a
56
- * gesture nobody handles have exactly one sensible default. `onFailure` is the one that stays
57
- * required, deliberately: it is the only callback whose silence is a defect rather than a
58
- * choice — unhandled, a browser with no WebGL context shows an empty box and says nothing.
59
- */
60
- events?: {
61
- onPointerOver?: (index: number) => void;
62
- onPointerOut?: () => void;
63
- onPointClick?: (graph: Graph, index: number) => void;
64
- onBackgroundClick?: () => void;
65
- /**
66
- * A node has been let go of, by index.
67
- *
68
- * cosmos.gl does not say which one. Its drag subject is `{x, y}`, and `store.draggingPointIndex`
69
- * is cleared *before* `onDragEnd` is called — so the index is remembered from the hover that
70
- * made the drag possible in the first place: the drag behaviour's subject only answers while
71
- * `store.hoveredPoint` is set, and hover detection is skipped for the whole gesture.
72
- */
73
- onDragEnd?: (index: number) => void;
74
- onTick?: () => void;
75
- /** The camera moved. The query loop is wired here — this is how a bounded graph is asked again. */
76
- onZoom?: () => void;
77
- };
78
- }
79
- export declare function useRenderer(options: RendererOptions): void;
80
- /**
81
- * The energy a wake puts back into a converged layout — enough to reorganise around a changed force,
82
- * not so much that the picture you were reading is thrown away. A full `start(1)` is what Re-run is
83
- * for.
84
- */
85
- export declare const REHEAT = 0.35;
86
- //# sourceMappingURL=use-renderer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-renderer.d.ts","sourceRoot":"","sources":["../src/use-renderer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvE,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAGzC,OAAO,EAAe,KAAK,GAAG,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAmEtC,MAAM,WAAW,eAAe;IAC9B,oDAAoD;IACpD,OAAO,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC1C;;;;;;OAMG;IACH,QAAQ,EAAE,SAAS,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAClC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;IAClC,wFAAwF;IACxF,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,kGAAkG;IAClG,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE;QACP,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QACxC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;QAC1B,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QACrD,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;QAC/B;;;;;;;WAOG;QACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QACpC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;QACpB,mGAAmG;QACnG,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;KACrB,CAAC;CACH;AAYD,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAoR1D;AAeD;;;;GAIG;AACH,eAAO,MAAM,MAAM,OAAO,CAAC"}
@@ -1,188 +0,0 @@
1
- "use client";
2
- import { useRef as d, useCallback as A, useEffect as w } from "react";
3
- import { Graph as I } from "@cosmos.gl/graph";
4
- import { clusterRing as M } from "./cluster-ring.js";
5
- import { forces as L } from "./graph-model.js";
6
- import { DEFAULT_SIM as V } from "./graph-sim.js";
7
- import { whenReady as m } from "./when-ready.js";
8
- function B() {
9
- if (typeof document > "u") return !1;
10
- try {
11
- const r = document.createElement("canvas");
12
- return r.getContext("webgl2") !== null || r.getContext("webgl") !== null;
13
- } catch {
14
- return !1;
15
- }
16
- }
17
- function U(r) {
18
- var g;
19
- const n = (r == null ? void 0 : r.getContext("webgl2")) ?? (r == null ? void 0 : r.getContext("webgl"));
20
- n && !n.isContextLost() && ((g = n.getExtension("WEBGL_lose_context")) == null || g.loseContext());
21
- }
22
- const O = () => {
23
- }, W = Object.freeze({});
24
- function X(r) {
25
- const {
26
- clusters: n,
27
- events: g = W,
28
- graphRef: u,
29
- hostRef: C,
30
- onFailure: T,
31
- report: b = O,
32
- reportProgress: x = O,
33
- sim: p = V,
34
- simulate: a = !1
35
- } = r, S = d(p), s = d(g);
36
- s.current = g;
37
- const c = d({ onFailure: T, report: b, reportProgress: x });
38
- c.current = { onFailure: T, report: b, reportProgress: x };
39
- const P = d(!1), R = d(-1), k = A((i) => {
40
- const o = Math.round(i * v);
41
- o !== R.current && (R.current = o, c.current.reportProgress(o / v));
42
- }, []);
43
- w(() => {
44
- const i = C.current;
45
- if (!i) return;
46
- if (P.current = !1, !B()) {
47
- c.current.onFailure("This canvas renders on the GPU, and this browser offers no WebGL context.");
48
- return;
49
- }
50
- const o = () => {
51
- if (P.current) return;
52
- P.current = !0;
53
- const e = u.current;
54
- e && m(e, (t) => t.fitView(q, Y));
55
- };
56
- let E = null, h = null, f;
57
- try {
58
- f = new I(i, {
59
- /**
60
- * **No `spaceSize` here, and that is the point.**
61
- *
62
- * The coordinate box belongs to whatever wrote the positions, not to the thing drawing
63
- * them. We used to declare it — one exported `SPACE = 4096`, copied by hand into both bench
64
- * generators — and a corpus fossil writes ignored it completely: a million vertices span
65
- * about x ∈ [−345, 645396], 157× the box the renderer was announcing. Nothing announced the
66
- * disagreement, because `spaceSize` enters every render path as a translation and the camera
67
- * is fitted from the extent anyway; the box was simply a false statement.
68
- *
69
- * So the box arrives with the first `extent()` — `useQueryLoop` sets it where it already
70
- * awaits one — and until then cosmos.gl's own default stands. A default of ours would be a
71
- * second way to answer a question one side already owns.
72
- */
73
- enableSimulation: a,
74
- ...L(S.current),
75
- /**
76
- * Frames to convergence — not milliseconds.
77
- *
78
- * `store.alphaDecay` is `α ⇒ 1 − 0.001^(1/α)` with `alphaTarget` 0, and one tick is one
79
- * rendered frame (`runSimulationStep` is called from `renderFrame`), so alpha decays as
80
- * `0.001^(n/α)` and reaches the `1e-3` floor after exactly `simulationDecay` frames — 400 ≈
81
- * 6.7 s at 60 fps, against cosmos.gl's default of 5,000 ≈ 83 s.
82
- */
83
- simulationDecay: 400,
84
- /**
85
- * Same seed, same picture. cosmos.gl's own randomness is not otherwise deterministic: the
86
- * per-link distance variation and the ±1e-5 jitter the force programs sow read
87
- * `store.random`, which is unseeded unless this is set. Init-only; `setConfig` cannot change
88
- * it.
89
- */
90
- randomSeed: "kanzo-discovery",
91
- /**
92
- * The device's, not cosmos.gl's literal `2`.
93
- *
94
- * It sizes the drawing buffer (`canvas.width = width * pixelRatio`) and divides the hardware
95
- * point-size limit into `maxPointSize`. Left at the default, a 1× display supersamples 4× for
96
- * nothing and a 3× display draws a canvas softer than the page it sits in.
97
- */
98
- pixelRatio: window.devicePixelRatio || 1,
99
- enableDrag: !0,
100
- fitViewOnInit: !0,
101
- fitViewDelay: 900,
102
- fitViewPadding: 0.18,
103
- hoveredPointCursor: "pointer",
104
- attribution: "",
105
- onSimulationStart: () => c.current.report("running"),
106
- onSimulationEnd: () => {
107
- var e, t;
108
- c.current.report("settled"), k(1), o(), (t = (e = s.current).onTick) == null || t.call(e);
109
- },
110
- onSimulationPause: () => c.current.report("paused"),
111
- onSimulationUnpause: () => c.current.report("running"),
112
- onSimulationTick: () => {
113
- var t, l;
114
- const e = u.current;
115
- e && k(e.progress), (l = (t = s.current).onTick) == null || l.call(t);
116
- },
117
- onZoom: () => {
118
- var e, t;
119
- return (t = (e = s.current).onZoom) == null ? void 0 : t.call(e);
120
- },
121
- onPointMouseOver: (e) => {
122
- var t, l;
123
- E = e, (l = (t = s.current).onPointerOver) == null || l.call(t, e);
124
- },
125
- onPointMouseOut: () => {
126
- var e, t;
127
- E = null, (t = (e = s.current).onPointerOut) == null || t.call(e);
128
- },
129
- onDragStart: () => {
130
- h = E;
131
- },
132
- onDragEnd: () => {
133
- var e, t;
134
- h !== null && ((t = (e = s.current).onDragEnd) == null || t.call(e, h)), h = null;
135
- },
136
- onPointClick: (e) => {
137
- var l, F;
138
- const t = u.current;
139
- t && ((F = (l = s.current).onPointClick) == null || F.call(l, t, e));
140
- },
141
- onBackgroundClick: () => {
142
- var e, t;
143
- return (t = (e = s.current).onBackgroundClick) == null ? void 0 : t.call(e);
144
- }
145
- });
146
- } catch (e) {
147
- c.current.onFailure(`The renderer failed to start. (${String(e)})`);
148
- return;
149
- }
150
- u.current = f;
151
- const y = m(f, (e) => e.render()), D = (e) => {
152
- e.preventDefault(), c.current.onFailure(
153
- "The graph's WebGL context was lost. A browser keeps a limited number of them and drops the oldest; reload the page to get one back."
154
- );
155
- }, G = m(f, () => {
156
- var e;
157
- (e = i.querySelector("canvas")) == null || e.addEventListener("webglcontextlost", D);
158
- });
159
- c.current.report(a && f.isSimulationRunning ? "running" : "settled");
160
- const _ = setTimeout(o, Z);
161
- return () => {
162
- clearTimeout(_), y(), G();
163
- const e = i.querySelector("canvas");
164
- e == null || e.removeEventListener("webglcontextlost", D), f.destroy(), U(e), u.current = null;
165
- };
166
- }, [u, C, k, a]), w(() => {
167
- const i = u.current;
168
- if (!(!i || !a || !n))
169
- return m(i, (o) => {
170
- o.setPointClusters(n), o.setClusterPositions(M(n, o.config.spaceSize)), o.render();
171
- });
172
- }, [n, u, a]), w(() => {
173
- const i = u.current;
174
- if (!(!i || !a || z(S.current, p)))
175
- return S.current = p, m(i, (o) => {
176
- o.setConfigPartial(L(p)), o.start(N);
177
- });
178
- }, [u, p, a]);
179
- }
180
- function z(r, n) {
181
- return r === n || r.gravity === n.gravity && r.repulsion === n.repulsion && r.linkSpring === n.linkSpring && r.linkDistance === n.linkDistance && r.friction === n.friction && r.cluster === n.cluster;
182
- }
183
- const N = 0.35, q = 450, Y = 0.18, Z = 6e3, v = 20;
184
- export {
185
- N as REHEAT,
186
- X as useRenderer
187
- };
188
- //# sourceMappingURL=use-renderer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-renderer.js","sources":["../src/use-renderer.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useRef, type RefObject } from \"react\";\nimport { Graph } from \"@cosmos.gl/graph\";\nimport { clusterRing } from \"./cluster-ring\";\nimport { forces } from \"./graph-model\";\nimport { DEFAULT_SIM, type Sim } from \"./graph-sim\";\nimport type { Motion } from \"./types\";\nimport { whenReady } from \"./when-ready\";\n\n/**\n * The renderer's whole life: built once, told what the forces are, destroyed on the way out.\n *\n * **It no longer knows anything about the data**, and that is the change ADR-0001 forced rather than\n * a tidy-up. Construction used to depend on a `Loaded`, which was harmless when the data arrived\n * once; under a bounded path a slice arrives on every camera move, and a construction effect keyed\n * on it would tear down and rebuild a WebGL context per pan. Geometry is pushed in by\n * `useQueryLoop`; the instance outlives every slice it draws.\n *\n * Everything about the picture — colours, sizes, shapes, the look, the camera, and since 3.0 even\n * whether a simulation runs at all — is a `setConfigPartial` somewhere else. **Three fields are\n * genuinely init-only**, and they are the three `preserveInitOnlyFields` restores after every config\n * write: `initialZoomLevel`, `randomSeed` and `attribution`.\n *\n * The callbacks are handed over exactly once, which is why every one of them reads the present\n * through a ref rather than a closure.\n */\n\n/**\n * Whether this browser can run the renderer at all.\n *\n * Asked rather than inferred, because the failure is silent in both directions. cosmos.gl draws its\n * own English message into the host element rather than throwing, so the `try/catch` around the\n * constructor was catching a case that cannot reach it. Worse under 3.x: device creation is\n * asynchronous and `graph.ready` has **no failure path** — when the device cannot be made it does\n * not reject, it simply never settles, so a caller awaiting it waits forever with nothing on screen.\n *\n * So the probe stays, and it answers the common case before any of that can happen. The catch stays\n * for real construction faults.\n */\nfunction hasWebGL(): boolean {\n if (typeof document === \"undefined\") return false;\n try {\n const probe = document.createElement(\"canvas\");\n return probe.getContext(\"webgl2\") !== null || probe.getContext(\"webgl\") !== null;\n } catch {\n return false;\n }\n}\n\n/**\n * **Give the WebGL context back, because cosmos.gl does not.**\n *\n * `destroy()` frees its own buffers and textures and leaves the context itself attached to the\n * canvas — `WEBGL_lose_context` and `loseContext` appear **zero times** in `@cosmos.gl/graph@3.4.0`.\n * A context released only by garbage collection is a context held for an unbounded time, and a\n * browser has a hard budget for them: Chrome keeps sixteen per renderer process and **evicts the\n * oldest** when a seventeenth is asked for. Eviction is not an error anywhere — the canvas simply\n * stops painting, `getPointPositions()` reads back empty, and `getZoomLevel()` answers zero.\n *\n * That is not a large-application problem. `/docs/graph` mounts four graphs, React's StrictMode runs\n * every effect setup → cleanup → setup, so eight contexts are created and four are orphaned on a\n * single page load — and three of the four canvases measured `isContextLost === true` while the\n * newest one drew. `/view/showcases/graph-bench` has one graph and has always looked fine, which is\n * how this survived: the bug is invisible until a page holds more than one.\n *\n * The extension is absent on some drivers and the context may already be lost, and neither is worth\n * reporting: this is a release, and a release that cannot happen has nothing to say.\n */\nfunction releaseContext(canvas: HTMLCanvasElement | null): void {\n const gl = canvas?.getContext(\"webgl2\") ?? canvas?.getContext(\"webgl\");\n if (gl && !gl.isContextLost()) gl.getExtension(\"WEBGL_lose_context\")?.loseContext();\n}\n\nexport interface RendererOptions {\n /** The element cosmos.gl mounts its canvas into. */\n hostRef: RefObject<HTMLDivElement | null>;\n /**\n * Where to put the instance.\n *\n * Given rather than returned, because the overlays, the gesture and the query loop all need a way\n * to reach the graph and this hook needs their callbacks — returning it would make the\n * declarations circular.\n */\n graphRef: RefObject<Graph | null>;\n /**\n * Whether to run a live layout, and it **defaults to off**.\n *\n * ADR-0001's premise: positions are authority. A bounded source hands back coordinates that the\n * next spatial query is expressed in, so a force that moves them moves the picture out from under\n * its own index — the camera drifts away from the corpus within a frame. Off is therefore the\n * correct default and not a conservative one.\n *\n * On is for the other host: arrays in hand, no precomputed layout, few enough points that a live\n * simulation is the cheapest way to get one. That host has no spatial index to disagree with.\n */\n simulate?: boolean;\n /**\n * Cluster assignment per drawn point, when a live layout should group them.\n *\n * Only meaningful under `simulate` — it is a force, not a colour. `undefined` at a position means\n * *no group*, which is not group zero: a vertex shared by every group belongs to none, and left\n * unclustered it drifts between the ones it joins.\n */\n clusters?: (number | undefined)[];\n /** Defaults to `DEFAULT_SIM`, which is the same table the exported constant carries. */\n sim?: Sim;\n /** Where to report what the layout is doing. Optional: a host with no motion badge wants none. */\n report?: (motion: Motion) => void;\n /**\n * How far through settling the layout is, `0`–`1`.\n *\n * cosmos.gl computes it every tick as `√(min(1, ALPHA_MIN / alpha))` and exposes it as\n * `graph.progress`, so a determinate badge costs nothing to compute — only to deliver. Quantised\n * before it is reported, because this is React state read through context and a write per\n * animation frame would re-render every consumer 60 times a second to move a number by half a\n * percent.\n */\n reportProgress?: (value: number) => void;\n onFailure: (message: string) => void;\n /**\n * Callbacks handed to cosmos.gl once, at construction — **all optional, and so is the block**.\n *\n * They were required, and a graph that only wants to be *looked at* had to write seven no-ops to\n * say so. A picture with no interaction is a legitimate picture, and the seven that report a\n * gesture nobody handles have exactly one sensible default. `onFailure` is the one that stays\n * required, deliberately: it is the only callback whose silence is a defect rather than a\n * choice — unhandled, a browser with no WebGL context shows an empty box and says nothing.\n */\n events?: {\n onPointerOver?: (index: number) => void;\n onPointerOut?: () => void;\n onPointClick?: (graph: Graph, index: number) => void;\n onBackgroundClick?: () => void;\n /**\n * A node has been let go of, by index.\n *\n * cosmos.gl does not say which one. Its drag subject is `{x, y}`, and `store.draggingPointIndex`\n * is cleared *before* `onDragEnd` is called — so the index is remembered from the hover that\n * made the drag possible in the first place: the drag behaviour's subject only answers while\n * `store.hoveredPoint` is set, and hover detection is skipped for the whole gesture.\n */\n onDragEnd?: (index: number) => void;\n onTick?: () => void;\n /** The camera moved. The query loop is wired here — this is how a bounded graph is asked again. */\n onZoom?: () => void;\n };\n}\n\n/**\n * The defaults for everything a picture-only host does not care about.\n *\n * Frozen module constants rather than object literals in the destructure: a fresh `{}` per render\n * would be a new identity for `live.current` and for `applied`, which is the class of bug the ref\n * indirection below exists to avoid in the first place.\n */\nconst noop = () => {};\nconst EMPTY_EVENTS: NonNullable<RendererOptions[\"events\"]> = Object.freeze({});\n\nexport function useRenderer(options: RendererOptions): void {\n const {\n clusters,\n events = EMPTY_EVENTS,\n graphRef,\n hostRef,\n onFailure,\n report = noop,\n reportProgress = noop,\n sim = DEFAULT_SIM,\n simulate = false,\n } = options;\n\n /**\n * The coefficients the graph is currently running with.\n *\n * The constructor takes them and the effect below re-applies them when they move — so this is not\n * a \"first render\" flag, it is the answer to *what does the simulation already have?*, which is\n * the question both places are asking.\n */\n const applied = useRef(sim);\n const live = useRef(events);\n live.current = events;\n\n /**\n * **The caller's callbacks, held rather than depended on.**\n *\n * `onFailure`, `report` and `reportProgress` used to sit in the construction effect's dependency\n * list, which made the renderer's lifetime a function of a caller's *render*. `onFailure` is\n * required by this package and every consumer writes it inline — `onFailure={(e) => setFailure(e)}`\n * is the obvious spelling — so every render was a new identity, and every new identity destroyed\n * the graph and built another.\n *\n * Measured on `/docs/graph`: **142 `destroy()` calls in five seconds** with nobody touching the\n * page, `setPointPositions` called **zero** times, and `getGraph()` answering a different instance\n * each time it was asked. Nothing painted, because no instance lived long enough to be given\n * geometry — and at roughly twenty-eight rebuilds a second it also burned the browser's\n * sixteen-context budget continuously, which is why the *other three* graphs on the page were\n * blank too. One example with an inline callback starved the page.\n *\n * A ref rather than `useCallback` at the call site: a rule that every consumer must memoise a\n * required callback is a rule nobody remembers, and its failure is silent.\n */\n const callbacks = useRef({ onFailure, report, reportProgress });\n callbacks.current = { onFailure, report, reportProgress };\n\n /**\n * Whether the camera has been put where the layout is.\n *\n * `fitViewOnInit` frames the graph at `fitViewDelay`, a second in, while a simulation is still\n * contracting — so by the time it converges the picture has shrunk to a blob in the middle of an\n * empty canvas. The early fit is still worth having, because a second of *something* beats a\n * second of nothing; it just is not the last word. This one is: once, and never again — re-framing\n * on later settles would yank the camera out from under whoever nudged a slider, and under a\n * bounded path it would fight the reader's own panning.\n */\n const framed = useRef(false);\n\n /** The last bucket handed on, so a tick that has not moved the badge costs nothing. */\n const reported = useRef(-1);\n const progress = useCallback((value: number) => {\n const bucket = Math.round(value * PROGRESS_STEPS);\n if (bucket === reported.current) return;\n reported.current = bucket;\n callbacks.current.reportProgress(bucket / PROGRESS_STEPS);\n }, []);\n\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n framed.current = false;\n if (!hasWebGL()) {\n callbacks.current.onFailure(\"This canvas renders on the GPU, and this browser offers no WebGL context.\");\n return;\n }\n\n /** Put the camera where the layout ended up — once, whoever gets here first. */\n const frameOnce = () => {\n if (framed.current) return;\n framed.current = true;\n const graph = graphRef.current;\n if (graph) whenReady(graph, (ready) => ready.fitView(FIT_DURATION, FIT_PADDING));\n };\n\n // Which node the pointer is on, and which one the current gesture picked up. Locals rather than\n // refs: they are read and written only by callbacks this closure owns, and they die with the\n // instance those callbacks belong to.\n let hovering: number | null = null;\n let dragging: number | null = null;\n\n let graph: Graph;\n try {\n graph = new Graph(host, {\n /**\n * **No `spaceSize` here, and that is the point.**\n *\n * The coordinate box belongs to whatever wrote the positions, not to the thing drawing\n * them. We used to declare it — one exported `SPACE = 4096`, copied by hand into both bench\n * generators — and a corpus fossil writes ignored it completely: a million vertices span\n * about x ∈ [−345, 645396], 157× the box the renderer was announcing. Nothing announced the\n * disagreement, because `spaceSize` enters every render path as a translation and the camera\n * is fitted from the extent anyway; the box was simply a false statement.\n *\n * So the box arrives with the first `extent()` — `useQueryLoop` sets it where it already\n * awaits one — and until then cosmos.gl's own default stands. A default of ours would be a\n * second way to answer a question one side already owns.\n */\n enableSimulation: simulate,\n ...forces(applied.current),\n /**\n * Frames to convergence — not milliseconds.\n *\n * `store.alphaDecay` is `α ⇒ 1 − 0.001^(1/α)` with `alphaTarget` 0, and one tick is one\n * rendered frame (`runSimulationStep` is called from `renderFrame`), so alpha decays as\n * `0.001^(n/α)` and reaches the `1e-3` floor after exactly `simulationDecay` frames — 400 ≈\n * 6.7 s at 60 fps, against cosmos.gl's default of 5,000 ≈ 83 s.\n */\n simulationDecay: 400,\n /**\n * Same seed, same picture. cosmos.gl's own randomness is not otherwise deterministic: the\n * per-link distance variation and the ±1e-5 jitter the force programs sow read\n * `store.random`, which is unseeded unless this is set. Init-only; `setConfig` cannot change\n * it.\n */\n randomSeed: \"kanzo-discovery\",\n /**\n * The device's, not cosmos.gl's literal `2`.\n *\n * It sizes the drawing buffer (`canvas.width = width * pixelRatio`) and divides the hardware\n * point-size limit into `maxPointSize`. Left at the default, a 1× display supersamples 4× for\n * nothing and a 3× display draws a canvas softer than the page it sits in.\n */\n pixelRatio: window.devicePixelRatio || 1,\n enableDrag: true,\n fitViewOnInit: true,\n fitViewDelay: 900,\n fitViewPadding: 0.18,\n hoveredPointCursor: \"pointer\",\n attribution: \"\",\n onSimulationStart: () => callbacks.current.report(\"running\"),\n onSimulationEnd: () => {\n callbacks.current.report(\"settled\");\n progress(1);\n frameOnce();\n live.current.onTick?.();\n },\n onSimulationPause: () => callbacks.current.report(\"paused\"),\n onSimulationUnpause: () => callbacks.current.report(\"running\"),\n onSimulationTick: () => {\n const instance = graphRef.current;\n if (instance) progress(instance.progress);\n live.current.onTick?.();\n },\n onZoom: () => live.current.onZoom?.(),\n onPointMouseOver: (index) => {\n hovering = index;\n live.current.onPointerOver?.(index);\n },\n onPointMouseOut: () => {\n hovering = null;\n live.current.onPointerOut?.();\n },\n onDragStart: () => {\n dragging = hovering;\n },\n onDragEnd: () => {\n if (dragging !== null) live.current.onDragEnd?.(dragging);\n dragging = null;\n },\n onPointClick: (index) => {\n const instance = graphRef.current;\n if (instance) live.current.onPointClick?.(instance, index);\n },\n onBackgroundClick: () => live.current.onBackgroundClick?.(),\n });\n } catch (error) {\n callbacks.current.onFailure(`The renderer failed to start. (${String(error)})`);\n return;\n }\n graphRef.current = graph;\n const painted = whenReady(graph, (ready) => ready.render());\n /**\n * **A lost context is silent, permanent, and indistinguishable from a graph with no data.**\n *\n * Losing one is not an exception: the canvas stops painting, `getPointPositions()` reads back\n * empty and `getZoomLevel()` answers zero, while every setter keeps accepting arrays. Measured\n * on `/docs/graph`, where three of four canvases sat at `isContextLost === true` with a badge\n * beside each reporting a full slice — and the renderer had **fifteen free slots at the time**,\n * because the loss happened during the load and nothing brings a context back.\n *\n * `preventDefault()` is what asks the browser to try a restore at all; without it there is no\n * `webglcontextrestored` event to hear. We do not rebuild on it yet — that means re-uploading\n * every buffer from a slice this hook does not hold — so the honest thing is to say so through\n * the one callback this package makes required, and `/docs/design/graph` carries what a rebuild\n * would take. An empty box that explains itself is the floor, not the ceiling.\n */\n const onLost = (event: Event) => {\n event.preventDefault();\n callbacks.current.onFailure(\n \"The graph's WebGL context was lost. A browser keeps a limited number of them and drops the oldest; reload the page to get one back.\",\n );\n };\n // **Attached inside `whenReady`, and the first version of this was attached outside it and did\n // nothing.** cosmos.gl creates its canvas with the device, which is asynchronous — so\n // `host.querySelector(\"canvas\")` in this line's position answers `null`, the listener goes on\n // nothing, and the release below frees nothing. It looked correct and changed no behaviour at\n // all, which is the second time on this hook that a device call has been written as though the\n // instance were ready.\n const listening = whenReady(graph, () => {\n host.querySelector(\"canvas\")?.addEventListener(\"webglcontextlost\", onLost);\n });\n // Without a simulation there is nothing to settle and nothing to wait for, so the badge starts\n // where it ends. With one, construction fires no `onSimulationStart` — the graph is already\n // turning by the time we get here, and without this the transport opens showing Play over a\n // moving graph.\n callbacks.current.report(simulate && graph.isSimulationRunning ? \"running\" : \"settled\");\n const floor = setTimeout(frameOnce, FRAME_BY);\n return () => {\n clearTimeout(floor);\n painted();\n listening();\n // Read here rather than remembered from construction, and before `destroy()` rather than\n // after: the element does not exist until the device does, and it goes away with the graph.\n const canvas = host.querySelector(\"canvas\");\n canvas?.removeEventListener(\"webglcontextlost\", onLost);\n graph.destroy();\n releaseContext(canvas);\n graphRef.current = null;\n };\n // **`onFailure` and `report` are deliberately absent**, and the ref above says why: a renderer\n // whose lifetime follows a caller's render identity is a renderer that never lives long enough\n // to be given anything. `simulate` stays, because it is a construction option — and `progress`\n // stays because it is a `useCallback` over an empty list that reads the ref itself, so it is\n // stable by construction rather than by a caller remembering to make it so.\n }, [graphRef, hostRef, progress, simulate]);\n\n /**\n * Cluster seeding, and only under a live layout — it is a force, not a colour.\n *\n * Both calls or neither is worth having: clusters without positions is a pull toward a centroid\n * that moves with its own group. Neither flushes anything on its own; the next `render()` does,\n * and the query loop renders on every slice.\n */\n useEffect(() => {\n const graph = graphRef.current;\n if (!graph || !simulate || !clusters) return;\n return whenReady(graph, (ready) => {\n ready.setPointClusters(clusters);\n // The box the ring is placed in is the renderer's live one — `graph.config` is always fully\n // populated, so this reads either cosmos.gl's default or the extent `useQueryLoop` set.\n // Read after `ready` for the same reason it is written after it: before the device, the\n // config is cosmos.gl's default and the ring would be sized for a box nobody is drawing in.\n ready.setClusterPositions(clusterRing(clusters, ready.config.spaceSize));\n ready.render();\n });\n }, [clusters, graphRef, simulate]);\n\n /**\n * A change in the forces re-heats: the point of a live layout is that you can feel the parameter.\n * Equality on mount is what keeps a re-render from disturbing a settled graph.\n *\n * **By value, not by reference**, and the reason is what `sim` became. It takes a `Partial<Sim>` at\n * the top of the stack now, which invites the literal a host writes without thinking —\n * `sim={{ gravity: 0.2 }}` — and a fresh object per render against a reference comparison is a\n * `start()` per render into a layout nobody touched. `useGraph` memoises the merge, so this only\n * bites where the memo cannot help; six numbers is a cheap thing to be certain about.\n */\n useEffect(() => {\n const graph = graphRef.current;\n if (!graph || !simulate || sameForces(applied.current, sim)) return;\n applied.current = sim;\n return whenReady(graph, (ready) => {\n ready.setConfigPartial(forces(sim));\n ready.start(REHEAT);\n });\n }, [graphRef, sim, simulate]);\n}\n\n/** Whether two sets of coefficients would produce the same simulation. Six numbers, all of them. */\nfunction sameForces(a: Sim, b: Sim): boolean {\n return (\n a === b ||\n (a.gravity === b.gravity &&\n a.repulsion === b.repulsion &&\n a.linkSpring === b.linkSpring &&\n a.linkDistance === b.linkDistance &&\n a.friction === b.friction &&\n a.cluster === b.cluster)\n );\n}\n\n/**\n * The energy a wake puts back into a converged layout — enough to reorganise around a changed force,\n * not so much that the picture you were reading is thrown away. A full `start(1)` is what Re-run is\n * for.\n */\nexport const REHEAT = 0.35;\n\n/** The settle fit: long enough to read as the camera moving, and the same air the init fit leaves. */\nconst FIT_DURATION = 450;\nconst FIT_PADDING = 0.18;\n\n/**\n * When the camera frames the view — 6 s after the graph is built.\n *\n * Late enough that a layout has done its spreading and contracting, early enough that nobody has\n * started reading the wrong framing. It is a wall clock, so it is also the answer for a display that\n * is not running at 60 fps, where a settle at `simulationDecay` frames arrives late.\n */\nconst FRAME_BY = 6000;\n\n/**\n * How finely settling progress is reported: twentieths, so a settle costs 20 renders of everything\n * reading the graph's context rather than one per frame.\n */\nconst PROGRESS_STEPS = 20;\n"],"names":[],"mappings":";;;;;;;AAwCA;AACE;AACA;AACE;AACA;AAA4E;AAE5E;AAAO;AAEX;AAqBA;;AACE;AACA;AACF;AAoFA;AAAoB;AAGb;AACL;AAAM;AACJ;AACS;AACT;AACA;AACA;AACS;AACQ;AACX;AACK;AAYb;AAqBA;AACA;AAYA;AAKE;AACA;AAEwD;AAG1D;AACE;AACA;AAEA;AACE;AACA;AAAA;AAIF;AACE;AACA;AACA;AACA;AAA+E;AAMjF;AAIA;AACE;AAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeJ;AACO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ2B;AAC3B;AACG;AACD;AACE;AACI;AACP;AAC8C;;AAEzD;AAGA;AACF;AAC0D;AACG;;AAE3D;AACA;AACA;AACF;;AACc;AAAA;AAAA;;AAEZ;AAC6B;AAC/B;;AAEE;AACA;AACF;AAEE;AAAW;AACb;;AAEE;AACW;AACb;;AAEE;AACA;AAAoD;AACtD;;AACyB;AAAA;AAAA;AAC1B;AAED;AACA;AAAA;AAEF;AACA;AAiBE;AACkB;AAChB;AAAA;;AAUF;AAAmE;AAMrE;AACA;AACA;AACE;AAKA;AACA;AAGmB;AACrB;AAgBA;AACA;AACA;AACE;AAMM;AACP;AAcD;AACA;AACA;AAEE;AACkB;AACnB;AAEL;AAGA;AACE;AASF;AAOO;;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"when-ready.d.ts","sourceRoot":"","sources":["../src/when-ready.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI,CAQjF;AAeD,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAI7C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"when-ready.js","sources":["../src/when-ready.ts"],"sourcesContent":["import type { Graph } from \"@cosmos.gl/graph\";\n\n/**\n * **Every write into cosmos.gl goes through here, because a non-null instance is not a usable one.**\n *\n * cosmos.gl 3.x builds its device asynchronously. The constructor returns immediately and\n * `graphRef.current` is set, but for tens of milliseconds — longer when several graphs mount on one\n * page — the instance has no points, no links and no config to change. What happens then is not one\n * failure mode but two, and the quiet one is worse:\n *\n * - `setPointPositions` **throws** `Cannot set properties of undefined (setting 'shouldSkipRescale')`.\n * React swallows it into the effect boundary, so it reaches the console and nothing else.\n * - `setPointColors`, `setPointSizes`, `setConfigPartial` and `fitViewByPointPositions` **do not**.\n * They raise a dirty flag on something that is not there and return, so the picture is simply\n * never uploaded: a blank canvas beside a badge reporting a full slice, with `onFailure` silent\n * and nothing in the console at all.\n *\n * Measured on `/docs/graph`, where three graphs mount together and none of them drew a single point.\n * Upstream states the contract in its own `.d.ts` for `findPointsInRect` and `findPointsInPolygon`\n * — *must only be called when the graph is ready* — and it holds for every setter too.\n *\n * **The rule is a helper rather than five `await`s** because it was broken at five call sites in\n * four modules, which is what `CONVENTIONS.md` means by a rule that has to become a test.\n * `when-ready.test.ts` is that test, and it reads the source rather than the behaviour.\n *\n * **`ready` has no failure path.** When the device cannot be made, cosmos.gl does not reject — the\n * promise simply never settles, so `apply` never runs and the canvas stays empty. That is the state\n * `hasWebGL()` in `use-renderer.ts` probes for before any of this, and it is why this returns a\n * cancel rather than being awaited: nothing here may hold a caller open.\n *\n * @returns a cancel. Call it from an effect's cleanup — during a pan the slices arrive faster than\n * a frame, and every one but the last is superseded before it could have been drawn.\n */\nexport function whenReady(graph: Graph, apply: (graph: Graph) => void): () => void {\n let live = true;\n void graph.ready.then(() => {\n if (live) apply(graph);\n });\n return () => {\n live = false;\n };\n}\n\n/**\n * Whether this instance's device has arrived, answered **synchronously**.\n *\n * For the two call sites that cannot wait: `findPointsInRect` and `findPointsInPolygon` run inside a\n * pointer handler and have to return a number, and upstream marks exactly those two — and nothing\n * else in its `.d.ts` — *must only be called when the graph is ready*.\n *\n * The flag is kept beside the instance rather than on it, in a `WeakSet`, because the promise is the\n * only thing cosmos.gl exposes and a promise cannot be asked whether it has settled. A graph that is\n * never asked about is never added, which costs one `false` and one hit test that selects nothing.\n */\nconst arrived = new WeakSet<Graph>();\n\nexport function isReady(graph: Graph): boolean {\n if (arrived.has(graph)) return true;\n void graph.ready.then(() => arrived.add(graph));\n return false;\n}\n"],"names":["whenReady","graph","apply","live","arrived","isReady"],"mappings":"AAiCO,SAASA,EAAUC,GAAcC,GAA2C;AACjF,MAAIC,IAAO;AACX,SAAKF,EAAM,MAAM,KAAK,MAAM;AAC1B,IAAIE,OAAYF,CAAK;AAAA,EACvB,CAAC,GACM,MAAM;AACX,IAAAE,IAAO;AAAA,EACT;AACF;AAaA,MAAMC,wBAAc,QAAA;AAEb,SAASC,EAAQJ,GAAuB;AAC7C,SAAIG,EAAQ,IAAIH,CAAK,IAAU,MAC1BA,EAAM,MAAM,KAAK,MAAMG,EAAQ,IAAIH,CAAK,CAAC,GACvC;AACT;"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes