@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-model.d.ts","sourceRoot":"","sources":["../../src/render/graph-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAyC,KAAK,IAAI,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAEvC;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,SAAc;qBAI7C,MAAM,KAAG,MAAM;qBAIf,MAAM,KAAG,KAAK;EAElC;AAED,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,YAAY,CAAC;IACzB,UAAU,EAAE,YAAY,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,GAAE,QAAa,GAAG,KAAK,CAkDzG;AAED,qGAAqG;AACrG,wBAAgB,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,WAAW,CAS5C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,GAAG,WAAW,CAkBjE"}
@@ -0,0 +1,80 @@
1
+ import { CHART_SLOTS as P, categoricalColor as R, categoricalCapacity as F } from "@kanzo-tech/ui";
2
+ import { isColour as S } from "../core/channels.js";
3
+ import { toHex as y, resolveToken as c } from "./css-color.js";
4
+ import { SHAPE_ORDER as D, SHAPE_OTHER as E, SHAPE_INDEX as H } from "./graph-looks.js";
5
+ function M(r, i = P) {
6
+ const l = S(r.fill) ? r.fill : void 0, s = r.symbol !== void 0;
7
+ return {
8
+ color: (e) => l || (e >= i ? "var(--muted-foreground)" : R(e, void 0, i)),
9
+ shape: (e) => s ? D[e] ?? E : "circle"
10
+ };
11
+ }
12
+ function N(r, i, l, s = {}) {
13
+ var b;
14
+ const e = M(s, F(l)), v = /* @__PURE__ */ new Map(), A = (t) => {
15
+ let n = v.get(t);
16
+ return n || v.set(t, n = c(l, e.color(t))), n;
17
+ }, d = r.positions.length / 2, o = new Float32Array(d * 4), m = new Float32Array(d), h = new Float32Array(d), u = r.sizes;
18
+ let g = 0, w = 1;
19
+ if (u && r.marks > 0) {
20
+ let t = Number.POSITIVE_INFINITY, n = 0;
21
+ for (let a = 0; a < r.marks; a++) {
22
+ const k = u[a];
23
+ k < t && (t = k), k > n && (n = k);
24
+ }
25
+ g = Math.sqrt(Number.isFinite(t) ? t : 0), w = Math.sqrt(n) - g || 1;
26
+ }
27
+ for (let t = 0; t < r.marks; t++) {
28
+ const n = r.categories[t] ?? 0;
29
+ o.set(A(n), t * 4);
30
+ const a = u ? (Math.sqrt(u[t]) - g) / w : 0;
31
+ m[t] = i.size[0] + a * (i.size[1] - i.size[0]), h[t] = H[e.shape(n)];
32
+ }
33
+ const p = r.links.length / 2, C = new Float32Array(p * 4), O = new Float32Array(p), f = s.stroke ? c(l, s.stroke) : null;
34
+ for (let t = 0; t < p; t++) {
35
+ const n = r.links[t * 2] ?? 0;
36
+ C.set(
37
+ f ? [f[0], f[1], f[2], 1] : [o[n * 4] ?? 0.7, o[n * 4 + 1] ?? 0.7, o[n * 4 + 2] ?? 0.7, 1],
38
+ t * 4
39
+ );
40
+ const a = ((b = r.weights) == null ? void 0 : b[t]) ?? 1;
41
+ O[t] = i.link.width * (1 + Math.log2(Math.max(1, a)) / 2);
42
+ }
43
+ return { colors: o, sizes: m, shapes: h, linkColors: C, linkWidths: O };
44
+ }
45
+ function _(r) {
46
+ return {
47
+ simulationGravity: r.gravity,
48
+ simulationRepulsion: r.repulsion,
49
+ simulationLinkSpring: r.linkSpring,
50
+ simulationLinkDistance: r.linkDistance,
51
+ simulationFriction: r.friction,
52
+ simulationCluster: r.cluster
53
+ };
54
+ }
55
+ function x(r, i) {
56
+ return {
57
+ backgroundColor: y(c(i, "var(--background)")),
58
+ scalePointsOnZoom: !1,
59
+ renderLinks: r.link.render,
60
+ linkOpacity: r.link.opacity,
61
+ linkDefaultWidth: r.link.width,
62
+ linkBlending: r.link.blend,
63
+ curvedLinks: r.link.curve > 0,
64
+ curvedLinkControlPointDistance: r.link.curve,
65
+ linkVisibilityDistanceRange: r.link.fade,
66
+ linkVisibilityMinTransparency: 0.12,
67
+ renderHoveredPointRing: !0,
68
+ hoveredPointRingColor: y(c(i, "var(--primary)")),
69
+ focusedPointRingColor: y(c(i, "var(--primary)")),
70
+ pointGreyoutOpacity: 0.1,
71
+ linkGreyoutOpacity: 0.025
72
+ };
73
+ }
74
+ export {
75
+ x as appearance,
76
+ _ as forces,
77
+ N as paint,
78
+ M as scaleOf
79
+ };
80
+ //# sourceMappingURL=graph-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-model.js","sources":["../../src/render/graph-model.ts"],"sourcesContent":["import type { GraphConfig } from \"@cosmos.gl/graph\";\nimport { CHART_SLOTS, categoricalCapacity, categoricalColor } from \"@kanzo-tech/ui\";\nimport { isColour, type Channels } from \"../core/channels\";\nimport type { Composition } from \"./compose\";\nimport { resolveToken, toHex, type Rgba } from \"./css-color\";\nimport { SHAPE_INDEX, SHAPE_ORDER, SHAPE_OTHER, type Look, type Shape } from \"./graph-looks\";\nimport type { Sim } from \"./graph-sim\";\n\n/**\n * The categorical scale the bindings imply — what colour and what shape a category rank wears.\n *\n * One answer for the GPU buffers, the hover card and the legend, because three answers is how a\n * legend ends up disagreeing with the canvas it explains. Values are CSS strings: the DOM resolves\n * them itself, and the buffer path resolves them once on its way to the GPU.\n *\n * `capacity` is where Other begins, and it is the document's number rather than the token\n * vocabulary's: a set derived from a client's brand names 6 to 8 real categories, not always 8.\n */\nexport function scaleOf(channels: Channels, capacity = CHART_SLOTS) {\n const constant = isColour(channels.fill) ? channels.fill : undefined;\n const shaped = channels.symbol !== undefined;\n return {\n color: (ordinal: number): string => {\n if (constant) return constant;\n return ordinal >= capacity ? \"var(--muted-foreground)\" : categoricalColor(ordinal, undefined, capacity);\n },\n shape: (ordinal: number): Shape => (shaped ? (SHAPE_ORDER[ordinal] ?? SHAPE_OTHER) : \"circle\"),\n };\n}\n\nexport interface Paint {\n colors: Float32Array;\n sizes: Float32Array;\n shapes: Float32Array;\n linkColors: Float32Array;\n linkWidths: Float32Array;\n}\n\n/**\n * Every per-point and per-link attribute, from one composition and the live theme — what a look or a\n * theme change re-uploads, and all it re-uploads.\n *\n * `host` is the element the tokens are read against, so `var(--primary)` resolves for the tree the\n * canvas sits in. The ramp is `√value` over **this composition** — the biggest node here is what a\n * reader is looking at. A far end past `marks` is drawn at radius zero and alpha zero: it is in the\n * buffers only so an edge has somewhere to end.\n */\nexport function paint(composition: Composition, look: Look, host: Element, channels: Channels = {}): Paint {\n const scale = scaleOf(channels, categoricalCapacity(host));\n const rgba = new Map<number, Rgba>();\n const colourOf = (ordinal: number): Rgba => {\n let resolved = rgba.get(ordinal);\n if (!resolved) rgba.set(ordinal, (resolved = resolveToken(host, scale.color(ordinal))));\n return resolved;\n };\n const n = composition.positions.length / 2;\n const colors = new Float32Array(n * 4);\n const sizes = new Float32Array(n);\n const shapes = new Float32Array(n);\n const ramp = composition.sizes;\n let lo = 0;\n let span = 1;\n if (ramp && composition.marks > 0) {\n let min = Number.POSITIVE_INFINITY;\n let max = 0;\n for (let i = 0; i < composition.marks; i++) {\n const value = ramp[i] as number;\n if (value < min) min = value;\n if (value > max) max = value;\n }\n lo = Math.sqrt(Number.isFinite(min) ? min : 0);\n span = Math.sqrt(max) - lo || 1;\n }\n for (let i = 0; i < composition.marks; i++) {\n const ordinal = composition.categories[i] ?? 0;\n colors.set(colourOf(ordinal), i * 4);\n const t = ramp ? (Math.sqrt(ramp[i] as number) - lo) / span : 0;\n sizes[i] = look.size[0] + t * (look.size[1] - look.size[0]);\n shapes[i] = SHAPE_INDEX[scale.shape(ordinal)] as number;\n }\n\n const count = composition.links.length / 2;\n const linkColors = new Float32Array(count * 4);\n const linkWidths = new Float32Array(count);\n const neutral = channels.stroke ? resolveToken(host, channels.stroke) : null;\n for (let e = 0; e < count; e++) {\n const src = composition.links[e * 2] ?? 0;\n // Link alpha stays 1: `linkOpacity` and the distance fade multiply into it, and a second\n // opacity here would compound with both.\n linkColors.set(\n neutral ? [neutral[0], neutral[1], neutral[2], 1] : [colors[src * 4] ?? 0.7, colors[src * 4 + 1] ?? 0.7, colors[src * 4 + 2] ?? 0.7, 1],\n e * 4,\n );\n const weight = composition.weights?.[e] ?? 1;\n linkWidths[e] = look.link.width * (1 + Math.log2(Math.max(1, weight)) / 2);\n }\n return { colors, sizes, shapes, linkColors, linkWidths };\n}\n\n/** The simulation coefficients, in cosmos.gl's spelling. Shared by construction and every change. */\nexport function forces(sim: Sim): GraphConfig {\n return {\n simulationGravity: sim.gravity,\n simulationRepulsion: sim.repulsion,\n simulationLinkSpring: sim.linkSpring,\n simulationLinkDistance: sim.linkDistance,\n simulationFriction: sim.friction,\n simulationCluster: sim.cluster,\n };\n}\n\n/**\n * Everything the picture needs that is *one number for the whole canvas* — cosmos.gl's uniforms, read\n * fresh on every draw, so a look change costs a `setConfigPartial` and no upload at all.\n */\nexport function appearance(look: Look, host: Element): GraphConfig {\n return {\n backgroundColor: toHex(resolveToken(host, \"var(--background)\")),\n scalePointsOnZoom: false,\n renderLinks: look.link.render,\n linkOpacity: look.link.opacity,\n linkDefaultWidth: look.link.width,\n linkBlending: look.link.blend,\n curvedLinks: look.link.curve > 0,\n curvedLinkControlPointDistance: look.link.curve,\n linkVisibilityDistanceRange: look.link.fade,\n linkVisibilityMinTransparency: 0.12,\n renderHoveredPointRing: true,\n hoveredPointRingColor: toHex(resolveToken(host, \"var(--primary)\")),\n focusedPointRingColor: toHex(resolveToken(host, \"var(--primary)\")),\n pointGreyoutOpacity: 0.1,\n linkGreyoutOpacity: 0.025,\n };\n}\n"],"names":["scaleOf","channels","capacity","CHART_SLOTS","constant","isColour","shaped","ordinal","categoricalColor","SHAPE_ORDER","SHAPE_OTHER","paint","composition","look","host","scale","categoricalCapacity","rgba","colourOf","resolved","resolveToken","n","colors","sizes","shapes","ramp","lo","span","min","max","i","value","t","SHAPE_INDEX","count","linkColors","linkWidths","neutral","e","src","weight","_a","forces","sim","appearance","toHex"],"mappings":"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"}
@@ -25,7 +25,7 @@ export interface Sim {
25
25
  *
26
26
  * Chosen against a corpus of that size, and they are a starting point rather than a law: a graph
27
27
  * two orders of magnitude larger wants less repulsion and more friction, and the measurements in
28
- * `BENCHMARKS.md` say a live simulation is finished by around 200,000 points regardless. What a
28
+ * `/docs/graph/benchmarks` say a live simulation is finished by around 200,000 points regardless. What a
29
29
  * corpus of a given size wants is computed rather than chosen — see `adaptive` — and a host that
30
30
  * knows its corpus should start its users at that answer through the tenant policy.
31
31
  *
@@ -47,7 +47,7 @@ export declare const DEFAULT_SIM: Sim;
47
47
  * The coefficients a caller wants different, over the ones this package chose.
48
48
  *
49
49
  * Flat, so a spread is the whole merge. `undefined` returns the shared constant rather than a copy:
50
- * `useRenderer` re-heats when the forces change and tells them apart by reference, so a fresh object
50
+ * the renderer re-heats when the forces change, so a fresh object
51
51
  * per render would put energy back into a settled layout on every render.
52
52
  */
53
53
  export declare function resolveSim(patch?: Partial<Sim>): Sim;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-sim.d.ts","sourceRoot":"","sources":["../../src/render/graph-sim.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,iEAAiE;AACjE,MAAM,WAAW,GAAG;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,mGAAmG;IACnG,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,MAAM,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAM,GAAG,GAAG,CAatF;AAED;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,EAAE,GAAe,CAAC;AAE1C;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAGpD"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-sim.js","sources":["../../src/render/graph-sim.ts"],"sourcesContent":["/**\n * The force coefficients, and the one function that builds them from the axes a person chose.\n *\n * `graph-looks.ts`'s sibling, and deliberately its twin: a type the renderer consumes, one builder\n * that reads declared string values, and a default that is the builder called with nothing. What was\n * here before is what was there before — an interface, a `DEFAULT_SIM` table beside it, and a dock\n * that held six of them in React state and drew six sliders by hand.\n *\n * **A coefficient is not appearance, and it is still a preference.** `section.ts` says why it shares\n * the manifest: `tokens` are the colours a document may move, `prefs` are what the person on the\n * screen decides, and somebody tuning a layout until it settles is deciding.\n */\n\n/** Force coefficients, handed straight to the GPU simulation. */\nexport interface Sim {\n gravity: number;\n repulsion: number;\n linkSpring: number;\n linkDistance: number;\n friction: number;\n /** Pull toward the node's group position on the cluster ring. Zero lets the links decide alone. */\n cluster: number;\n}\n\n/**\n * Coefficients that settle a few-hundred-node graph into something readable.\n *\n * Chosen against a corpus of that size, and they are a starting point rather than a law: a graph\n * two orders of magnitude larger wants less repulsion and more friction, and the measurements in\n * `/docs/graph/benchmarks` say a live simulation is finished by around 200,000 points regardless. What a\n * corpus of a given size wants is computed rather than chosen — see `adaptive` — and a host that\n * knows its corpus should start its users at that answer through the tenant policy.\n *\n * The values are strings for the reason `lookFrom`'s are: a contributed preference is a string in\n * all three kinds, so an unrecognised namespace rides through a write untouched. A key that is\n * missing, or that carries a value the section never offered, takes the default below — which is\n * what a graph simulated before any of this existed.\n */\nexport function simFrom(values: Readonly<Record<string, string | undefined>> = {}): Sim {\n const num = (key: string, fallback: number) => {\n const value = Number.parseFloat(values[key] ?? \"\");\n return Number.isFinite(value) ? value : fallback;\n };\n return {\n gravity: num(\"gravity\", 0.14),\n repulsion: num(\"repulsion\", 1.1),\n linkSpring: num(\"link-spring\", 0.6),\n linkDistance: num(\"link-distance\", 18),\n friction: num(\"friction\", 0.86),\n cluster: num(\"cluster\", 0.1),\n };\n}\n\n/**\n * What a canvas simulates with when nobody has chosen anything.\n *\n * **Not on the barrel, and it used to be** — for the reason its twin was: it is `simFrom()`, a\n * second public name for a value already available on request, exported only because `sim` took a\n * whole `Sim` and a host changing `gravity` had to supply the other five.\n */\nexport const DEFAULT_SIM: Sim = simFrom();\n\n/**\n * The coefficients a caller wants different, over the ones this package chose.\n *\n * Flat, so a spread is the whole merge. `undefined` returns the shared constant rather than a copy:\n * the renderer re-heats when the forces change, so a fresh object\n * per render would put energy back into a settled layout on every render.\n */\nexport function resolveSim(patch?: Partial<Sim>): Sim {\n if (!patch) return DEFAULT_SIM;\n return { ...DEFAULT_SIM, ...patch };\n}\n"],"names":["simFrom","values","num","key","fallback","value","DEFAULT_SIM","resolveSim","patch"],"mappings":"AAsCO,SAASA,EAAQC,IAAuD,IAAS;AACtF,QAAMC,IAAM,CAACC,GAAaC,MAAqB;AAC7C,UAAMC,IAAQ,OAAO,WAAWJ,EAAOE,CAAG,KAAK,EAAE;AACjD,WAAO,OAAO,SAASE,CAAK,IAAIA,IAAQD;AAAA,EAC1C;AACA,SAAO;AAAA,IACL,SAASF,EAAI,WAAW,IAAI;AAAA,IAC5B,WAAWA,EAAI,aAAa,GAAG;AAAA,IAC/B,YAAYA,EAAI,eAAe,GAAG;AAAA,IAClC,cAAcA,EAAI,iBAAiB,EAAE;AAAA,IACrC,UAAUA,EAAI,YAAY,IAAI;AAAA,IAC9B,SAASA,EAAI,WAAW,GAAG;AAAA,EAAA;AAE/B;AASO,MAAMI,IAAmBN,EAAA;AASzB,SAASO,EAAWC,GAA2B;AACpD,SAAKA,IACE,EAAE,GAAGF,GAAa,GAAGE,EAAA,IADTF;AAErB;"}
@@ -1,4 +1,4 @@
1
- import { Channels } from './graph-model';
1
+ import { Channels } from '../core/channels';
2
2
  import { Look } from './graph-looks';
3
3
  /**
4
4
  * What the graph's geometry owes, as a report rather than as prose.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obligations.d.ts","sourceRoot":"","sources":["../../src/render/obligations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAsC,KAAK,IAAI,EAAE,MAAM,eAAe,CAAC;AAE9E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,UAAU;IACzB,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gDAAgD;IAChD,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,0FAA0F;IAC1F,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAgDD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,GAAG,KAAK,GAAG,IAAI,CAK7E;AAED,eAAO,MAAM,WAAW,EAAE,SAAS,UAAU,EAiE5C,CAAC;AAEF,8DAA8D;AAC9D,MAAM,WAAW,KAAM,SAAQ,UAAU;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,OAAO,CAAC;CACb;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,IAAI,KAAK,EAAE,CAa/B"}
@@ -0,0 +1,38 @@
1
+ import { Graph } from '@cosmos.gl/graph';
2
+ import { Resident } from '../core/resident';
3
+ import { GraphStore } from '../core/store';
4
+ import { GraphCommands } from '../core/types';
5
+ import { Composition } from './compose';
6
+ export interface RendererEvents {
7
+ /** After every frame and every camera move — where the overlays repaint. */
8
+ onFrame?: () => void;
9
+ /** A new composition was uploaded. */
10
+ onComposed?: (composition: Composition) => void;
11
+ }
12
+ export interface Renderer extends GraphCommands {
13
+ readonly graph: Graph;
14
+ resident(): Resident;
15
+ composition(): Composition | null;
16
+ /** The theme moved under the canvas: colours are resolved again, nothing else. */
17
+ repaint(): void;
18
+ /** The drawn points inside a screen rectangle or polygon, once the device is ready. */
19
+ hit(shape: {
20
+ rect: [[number, number], [number, number]];
21
+ } | {
22
+ polygon: [number, number][];
23
+ }): number[];
24
+ destroy(): void;
25
+ }
26
+ /**
27
+ * **cosmos.gl's lifetime, and the frame that renders once.** Built once per element; it subscribes to
28
+ * the store and discharges what changed in one `requestAnimationFrame`:
29
+ *
30
+ * - a change of visible tiles recomposes, and dirties positions, links and the per-point arrays;
31
+ * - a look or a theme change dirties colours, sizes and shapes and nothing else;
32
+ * - a selection, a focus or a pin sets two config fields and uploads nothing;
33
+ * - a snapshot that changed none of those schedules nothing.
34
+ *
35
+ * Every callback reads the store's latest options, so a host's inline `onFailure` never rebuilds it.
36
+ */
37
+ export declare function createRenderer(host: HTMLDivElement, store: GraphStore, events?: RendererEvents): Renderer | null;
38
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/render/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,kBAAkB,CAAC;AAE3D,OAAO,KAAK,EAAiB,UAAU,EAAE,MAAM,eAAe,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAO7D,MAAM,WAAW,cAAc;IAC7B,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,sCAAsC;IACtC,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,CAAC;CACjD;AAED,MAAM,WAAW,QAAS,SAAQ,aAAa;IAC7C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,IAAI,QAAQ,CAAC;IACrB,WAAW,IAAI,WAAW,GAAG,IAAI,CAAC;IAClC,kFAAkF;IAClF,OAAO,IAAI,IAAI,CAAC;IAChB,uFAAuF;IACvF,GAAG,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;KAAE,GAAG,MAAM,EAAE,CAAC;IACvG,OAAO,IAAI,IAAI,CAAC;CACjB;AAUD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,GAAE,cAAmB,GAAG,QAAQ,GAAG,IAAI,CA8TpH"}
@@ -0,0 +1,235 @@
1
+ import { Graph as nt } from "@cosmos.gl/graph";
2
+ import { denseOf as it } from "../core/resident.js";
3
+ import { tileOfDense as et } from "../core/tile-matrix.js";
4
+ import { createComposer as ot } from "./compose.js";
5
+ import { resolveLook as U } from "./graph-looks.js";
6
+ import { forces as Z, appearance as _, paint as st } from "./graph-model.js";
7
+ import { resolveSim as j } from "./graph-sim.js";
8
+ import { whenReady as c, isReady as y } from "./when-ready.js";
9
+ import { hasWebGL as rt, releaseContext as at } from "./webgl.js";
10
+ const b = 420, k = 0.18, L = 0.35, H = 20, C = (u) => [u.x, u.y, u.x + u.w, u.y + u.h];
11
+ function xt(u, i, l = {}) {
12
+ const M = (t) => i.getOptions().onFailure(t);
13
+ if (!rt())
14
+ return M("This canvas renders on the GPU, and this browser offers no WebGL context."), null;
15
+ let I = j(i.getOptions().sim), R = null, w = null, B = -1;
16
+ const D = (t) => {
17
+ const n = Math.round(t * H);
18
+ n !== B && (B = n, i.reportProgress(n / H));
19
+ }, Y = ot();
20
+ let m = null, O = U(i.getOptions().look), E = i.getOptions().look;
21
+ const a = { compose: !0, paint: !0, state: !0 };
22
+ let x = 0, F = null, S = null, d = i.getSnapshot(), P = i.getOptions();
23
+ const h = () => (m == null ? void 0 : m.resident) ?? lt, A = () => {
24
+ const { height: t, width: n } = u.getBoundingClientRect();
25
+ if (!y(e) || n === 0 || t === 0) return null;
26
+ const [o, r] = e.screenToSpacePosition([0, 0]), [p, g] = e.screenToSpacePosition([n, t]), f = { xMin: Math.min(o, p), yMin: Math.min(r, g), xMax: Math.max(o, p), yMax: Math.max(r, g) };
27
+ return { view: f, perPixel: (f.xMax - f.xMin) / n };
28
+ }, z = () => {
29
+ const t = A();
30
+ t && i.setViewport(t.view);
31
+ };
32
+ let e;
33
+ try {
34
+ e = new nt(u, {
35
+ // No `spaceSize` here: the box is the corpus's extent, set when the matrix arrives.
36
+ // `rescalePositions: false` because the corpus's coordinates are the camera's — a rescale
37
+ // between them means the cull and the viewport describe different places.
38
+ rescalePositions: !1,
39
+ enableSimulation: i.getOptions().simulate ?? !1,
40
+ ...Z(I),
41
+ // Frames to convergence: alpha reaches its floor after exactly this many rendered frames.
42
+ simulationDecay: 400,
43
+ randomSeed: "kanzo-discovery",
44
+ pixelRatio: window.devicePixelRatio || 1,
45
+ enableDrag: !0,
46
+ hoveredPointCursor: "pointer",
47
+ attribution: "",
48
+ onSimulationStart: () => i.report("running"),
49
+ onSimulationEnd: () => {
50
+ var t;
51
+ i.report("settled"), D(1), (t = l.onFrame) == null || t.call(l);
52
+ },
53
+ onSimulationPause: () => i.report("paused"),
54
+ onSimulationUnpause: () => i.report("running"),
55
+ onSimulationTick: () => {
56
+ var t;
57
+ D(e.progress), (t = l.onFrame) == null || t.call(l);
58
+ },
59
+ onZoom: () => {
60
+ var t;
61
+ z(), (t = l.onFrame) == null || t.call(l);
62
+ },
63
+ onPointMouseOver: (t) => {
64
+ R = t, i.hover(h().at(t) ?? null);
65
+ },
66
+ onPointMouseOut: () => {
67
+ R = null, i.hover(null);
68
+ },
69
+ onDragStart: () => {
70
+ w = R;
71
+ },
72
+ onDragEnd: () => {
73
+ const t = w === null ? void 0 : h().at(w);
74
+ w = null, t !== void 0 && i.pin([...i.getSnapshot().pinned, t]);
75
+ },
76
+ onPointClick: (t) => {
77
+ const n = h().at(t);
78
+ n !== void 0 && V(n, t);
79
+ },
80
+ onBackgroundClick: () => W()
81
+ });
82
+ } catch (t) {
83
+ return M(`The renderer failed to start. (${String(t)})`), null;
84
+ }
85
+ const T = () => {
86
+ x || (x = requestAnimationFrame(() => {
87
+ x = 0, c(e, $);
88
+ }));
89
+ };
90
+ function $(t) {
91
+ var p, g, f;
92
+ const n = i.getSnapshot(), o = i.getOptions();
93
+ let r = !1;
94
+ if (a.compose && n.matrix) {
95
+ a.compose = !1;
96
+ const s = Y({
97
+ matrix: n.matrix,
98
+ typeIndex: n.typeIndex,
99
+ binding: n.binding,
100
+ modeColumn: n.modeColumn,
101
+ domain: n.domain,
102
+ visible: n.visible,
103
+ cached: n.cached,
104
+ perPixel: ((p = A()) == null ? void 0 : p.perPixel) ?? 0
105
+ });
106
+ if (s && (m = s, t.setPointPositions(s.positions, !0), t.setLinks(s.links), a.paint = !0, a.state = !0, r = !0, (g = l.onComposed) == null || g.call(l, s), S !== null && s.resident.indexOf(S) !== void 0)) {
107
+ const tt = S;
108
+ S = null, queueMicrotask(() => q(tt));
109
+ }
110
+ const v = s && { marks: s.marks, represented: s.represented, domain: s.domain, tally: s.tally };
111
+ i.reportDrawn(n.visible, v);
112
+ }
113
+ if (a.paint && m) {
114
+ a.paint = !1;
115
+ const s = st(m, O, u, o);
116
+ t.setPointColors(s.colors), t.setPointSizes(s.sizes), t.setPointShapes(s.shapes), t.setLinkColors(s.linkColors), t.setLinkWidths(s.linkWidths), t.setConfigPartial(_(O, u)), r = !0;
117
+ }
118
+ if (a.state && m) {
119
+ a.state = !1;
120
+ const s = m.resident;
121
+ t.setConfigPartial({
122
+ highlightedPointIndices: n.selection ? s.indicesOf(n.selection.vertices) : void 0,
123
+ focusedPointIndex: n.focus === null ? void 0 : s.indexOf(n.focus)
124
+ });
125
+ const v = s.indicesOf(n.pinned);
126
+ t.setPinnedPoints(v.length > 0 ? v : null), r = !0;
127
+ }
128
+ r && t.render(), (f = l.onFrame) == null || f.call(l);
129
+ }
130
+ const G = (t) => {
131
+ var o;
132
+ const n = (o = t.matrix) == null ? void 0 : o.extent;
133
+ !n || t.matrix === F || (F = t.matrix, c(e, (r) => {
134
+ r.setConfigPartial({ spaceSize: Math.max(n.w, n.h) }), r.fitViewByPointPositions(C(n), 0, k), z();
135
+ }));
136
+ }, J = i.subscribe(() => {
137
+ const t = i.getSnapshot(), n = i.getOptions();
138
+ G(t), (t.visible !== d.visible || t.binding !== d.binding || t.domain !== d.domain) && (a.compose = !0), n.look !== E && (E = n.look, O = U(n.look), a.paint = !0), (n.fill !== P.fill || n.symbol !== P.symbol || n.stroke !== P.stroke) && (a.paint = !0), (t.selection !== d.selection || t.focus !== d.focus || t.pinned !== d.pinned) && (a.state = !0), (n.sim !== P.sim || n.simulate !== P.simulate) && K(n.sim, n.simulate), d = t, P = n, (a.compose || a.paint || a.state) && T();
139
+ });
140
+ function K(t, n = !1) {
141
+ const o = j(t), r = Object.keys(o).some((p) => o[p] !== I[p]);
142
+ I = o, c(e, (p) => {
143
+ p.setConfigPartial({ enableSimulation: n, ...Z(o) }), n && r && p.start(L);
144
+ });
145
+ }
146
+ function V(t, n) {
147
+ const o = h(), r = y(e) ? o.verticesAt(e.getNeighboringPointIndices(n)) : [];
148
+ i.select([t, ...r], "node", "Node"), i.focus(t);
149
+ }
150
+ function W() {
151
+ i.select(null), i.focus(null);
152
+ }
153
+ function q(t) {
154
+ var g, f;
155
+ const n = h().indexOf(t);
156
+ if (n !== void 0) {
157
+ V(t, n), c(e, (s) => s.zoomToPointByIndex(n, 500, 5, !0));
158
+ return;
159
+ }
160
+ const o = i.getSnapshot().matrix, r = o ? et(o, it(t)) : null, p = r && ((f = (g = o == null ? void 0 : o.tileMatrices[r.z]) == null ? void 0 : g.tiles[r.tile]) == null ? void 0 : f.bbox);
161
+ p && (S = t, c(e, (s) => s.fitViewByPointPositions(C(p), b, k)));
162
+ }
163
+ y(e);
164
+ const Q = c(e, (t) => {
165
+ t.setConfigPartial(_(O, u)), t.render();
166
+ }), N = (t) => {
167
+ t.preventDefault(), M("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.");
168
+ }, X = c(e, () => {
169
+ var t;
170
+ (t = u.querySelector("canvas")) == null || t.addEventListener("webglcontextlost", N);
171
+ });
172
+ return i.report(i.getOptions().simulate && e.isSimulationRunning ? "running" : "settled"), G(d), T(), {
173
+ graph: e,
174
+ resident: h,
175
+ composition: () => m,
176
+ repaint() {
177
+ a.paint = !0, T();
178
+ },
179
+ hit(t) {
180
+ if (!y(e)) return [];
181
+ const n = "rect" in t ? e.findPointsInRect(t.rect) : e.findPointsInPolygon(t.polygon);
182
+ return Array.from(n);
183
+ },
184
+ zoomBy(t) {
185
+ c(e, (n) => n.setZoomLevel(n.getZoomLevel() * t, 220));
186
+ },
187
+ fit() {
188
+ var n;
189
+ const t = (n = i.getSnapshot().matrix) == null ? void 0 : n.extent;
190
+ c(
191
+ e,
192
+ (o) => t ? o.fitViewByPointPositions(C(t), b, k) : o.fitView(b, k)
193
+ );
194
+ },
195
+ pause: () => c(e, (t) => t.pause()),
196
+ resume() {
197
+ const t = i.getSnapshot().motion === "settled";
198
+ c(e, (n) => t ? n.start(L) : n.unpause());
199
+ },
200
+ restart() {
201
+ i.pin([]), c(e, (t) => t.start(1));
202
+ },
203
+ unpin() {
204
+ i.getSnapshot().pinned.length !== 0 && (i.pin([]), c(e, (t) => t.start(L)));
205
+ },
206
+ reveal: q,
207
+ frameBox(t, { duration: n = b, padding: o = k } = {}) {
208
+ c(e, (r) => r.fitViewByPointPositions(C(t), n, o));
209
+ },
210
+ frameSelection() {
211
+ var n;
212
+ const t = h().indicesOf(((n = i.getSnapshot().selection) == null ? void 0 : n.vertices) ?? []);
213
+ t.length > 0 && c(e, (o) => o.fitViewByPointIndices(t, b, 0.25));
214
+ },
215
+ clear: W,
216
+ destroy() {
217
+ J(), x && cancelAnimationFrame(x), Q(), X();
218
+ const t = u.querySelector("canvas");
219
+ t == null || t.removeEventListener("webglcontextlost", N), e.destroy(), at(t);
220
+ }
221
+ };
222
+ }
223
+ const lt = {
224
+ size: 0,
225
+ indexOf: () => {
226
+ },
227
+ at: () => {
228
+ },
229
+ indicesOf: () => [],
230
+ verticesAt: () => []
231
+ };
232
+ export {
233
+ xt as createRenderer
234
+ };
235
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sources":["../../src/render/renderer.ts"],"sourcesContent":["import { Graph } from \"@cosmos.gl/graph\";\nimport type { Box } from \"@fossil-lang/corpus\";\nimport type { Resident, VertexId } from \"../core/resident\";\nimport { denseOf } from \"../core/resident\";\nimport type { GraphSnapshot, GraphStore } from \"../core/store\";\nimport { tileOfDense, type Viewport } from \"../core/tile-matrix\";\nimport type { GraphCommands } from \"../core/types\";\nimport { createComposer, type Composition } from \"./compose\";\nimport { resolveLook, type Look } from \"./graph-looks\";\nimport { appearance, forces, paint } from \"./graph-model\";\nimport { resolveSim, type Sim } from \"./graph-sim\";\nimport { isReady, whenReady } from \"./when-ready\";\nimport { hasWebGL, releaseContext } from \"./webgl\";\n\nexport interface RendererEvents {\n /** After every frame and every camera move — where the overlays repaint. */\n onFrame?: () => void;\n /** A new composition was uploaded. */\n onComposed?: (composition: Composition) => void;\n}\n\nexport interface Renderer extends GraphCommands {\n readonly graph: Graph;\n resident(): Resident;\n composition(): Composition | null;\n /** The theme moved under the canvas: colours are resolved again, nothing else. */\n repaint(): void;\n /** The drawn points inside a screen rectangle or polygon, once the device is ready. */\n hit(shape: { rect: [[number, number], [number, number]] } | { polygon: [number, number][] }): number[];\n destroy(): void;\n}\n\nconst FIT_DURATION = 420;\nconst FIT_PADDING = 0.18;\nconst REHEAT = 0.35;\n/** Twentieths: a settle costs twenty reports rather than one per frame. */\nconst PROGRESS_STEPS = 20;\n\nconst corners = (box: Box) => [box.x, box.y, box.x + box.w, box.y + box.h];\n\n/**\n * **cosmos.gl's lifetime, and the frame that renders once.** Built once per element; it subscribes to\n * the store and discharges what changed in one `requestAnimationFrame`:\n *\n * - a change of visible tiles recomposes, and dirties positions, links and the per-point arrays;\n * - a look or a theme change dirties colours, sizes and shapes and nothing else;\n * - a selection, a focus or a pin sets two config fields and uploads nothing;\n * - a snapshot that changed none of those schedules nothing.\n *\n * Every callback reads the store's latest options, so a host's inline `onFailure` never rebuilds it.\n */\nexport function createRenderer(host: HTMLDivElement, store: GraphStore, events: RendererEvents = {}): Renderer | null {\n const fail = (message: string) => store.getOptions().onFailure(message);\n if (!hasWebGL()) {\n fail(\"This canvas renders on the GPU, and this browser offers no WebGL context.\");\n return null;\n }\n\n let sim: Sim = resolveSim(store.getOptions().sim);\n let hovering: number | null = null;\n let dragging: number | null = null;\n let reported = -1;\n const progress = (value: number) => {\n const bucket = Math.round(value * PROGRESS_STEPS);\n if (bucket === reported) return;\n reported = bucket;\n store.reportProgress(bucket / PROGRESS_STEPS);\n };\n\n const compose = createComposer();\n let composition: Composition | null = null;\n let look: Look = resolveLook(store.getOptions().look);\n let lookPatch = store.getOptions().look;\n const dirty = { compose: true, paint: true, state: true };\n let frame = 0;\n let framed: GraphSnapshot[\"matrix\"] = null;\n let pendingReveal: VertexId | null = null;\n let last = store.getSnapshot();\n let lastOptions = store.getOptions();\n\n const resident = () => composition?.resident ?? EMPTY;\n\n const viewport = (): { view: Viewport; perPixel: number } | null => {\n const { height, width } = host.getBoundingClientRect();\n if (!isReady(graph) || width === 0 || height === 0) return null;\n const [ax, ay] = graph.screenToSpacePosition([0, 0]);\n const [bx, by] = graph.screenToSpacePosition([width, height]);\n const view = { xMin: Math.min(ax, bx), yMin: Math.min(ay, by), xMax: Math.max(ax, bx), yMax: Math.max(ay, by) };\n return { view, perPixel: (view.xMax - view.xMin) / width };\n };\n const observe = () => {\n const camera = viewport();\n if (camera) store.setViewport(camera.view);\n };\n\n let graph: Graph;\n try {\n graph = new Graph(host, {\n // No `spaceSize` here: the box is the corpus's extent, set when the matrix arrives.\n // `rescalePositions: false` because the corpus's coordinates are the camera's — a rescale\n // between them means the cull and the viewport describe different places.\n rescalePositions: false,\n enableSimulation: store.getOptions().simulate ?? false,\n ...forces(sim),\n // Frames to convergence: alpha reaches its floor after exactly this many rendered frames.\n simulationDecay: 400,\n randomSeed: \"kanzo-discovery\",\n pixelRatio: window.devicePixelRatio || 1,\n enableDrag: true,\n hoveredPointCursor: \"pointer\",\n attribution: \"\",\n onSimulationStart: () => store.report(\"running\"),\n onSimulationEnd: () => {\n store.report(\"settled\");\n progress(1);\n events.onFrame?.();\n },\n onSimulationPause: () => store.report(\"paused\"),\n onSimulationUnpause: () => store.report(\"running\"),\n onSimulationTick: () => {\n progress(graph.progress);\n events.onFrame?.();\n },\n onZoom: () => {\n observe();\n events.onFrame?.();\n },\n onPointMouseOver: (index) => {\n hovering = index;\n store.hover(resident().at(index) ?? null);\n },\n onPointMouseOut: () => {\n hovering = null;\n store.hover(null);\n },\n onDragStart: () => {\n dragging = hovering;\n },\n onDragEnd: () => {\n const vertex = dragging === null ? undefined : resident().at(dragging);\n dragging = null;\n if (vertex !== undefined) store.pin([...store.getSnapshot().pinned, vertex]);\n },\n onPointClick: (index) => {\n const vertex = resident().at(index);\n if (vertex !== undefined) focusOn(vertex, index);\n },\n onBackgroundClick: () => clear(),\n });\n } catch (error) {\n fail(`The renderer failed to start. (${String(error)})`);\n return null;\n }\n\n const schedule = () => {\n if (frame) return;\n frame = requestAnimationFrame(() => {\n frame = 0;\n whenReady(graph, draw);\n });\n };\n\n function draw(ready: Graph): void {\n const snapshot = store.getSnapshot();\n const options = store.getOptions();\n let changed = false;\n if (dirty.compose && snapshot.matrix) {\n dirty.compose = false;\n const next = compose({\n matrix: snapshot.matrix,\n typeIndex: snapshot.typeIndex,\n binding: snapshot.binding,\n modeColumn: snapshot.modeColumn,\n domain: snapshot.domain,\n visible: snapshot.visible,\n cached: snapshot.cached,\n perPixel: viewport()?.perPixel ?? 0,\n });\n if (next) {\n composition = next;\n ready.setPointPositions(next.positions, true);\n ready.setLinks(next.links);\n dirty.paint = true;\n dirty.state = true;\n changed = true;\n events.onComposed?.(next);\n if (pendingReveal !== null && next.resident.indexOf(pendingReveal) !== undefined) {\n const vertex = pendingReveal;\n pendingReveal = null;\n queueMicrotask(() => reveal(vertex));\n }\n }\n const drawn = next && { marks: next.marks, represented: next.represented, domain: next.domain, tally: next.tally };\n store.reportDrawn(snapshot.visible, drawn);\n }\n if (dirty.paint && composition) {\n dirty.paint = false;\n const buffers = paint(composition, look, host, options);\n ready.setPointColors(buffers.colors);\n ready.setPointSizes(buffers.sizes);\n ready.setPointShapes(buffers.shapes);\n ready.setLinkColors(buffers.linkColors);\n ready.setLinkWidths(buffers.linkWidths);\n ready.setConfigPartial(appearance(look, host));\n changed = true;\n }\n if (dirty.state && composition) {\n dirty.state = false;\n const drawn = composition.resident;\n ready.setConfigPartial({\n highlightedPointIndices: snapshot.selection ? drawn.indicesOf(snapshot.selection.vertices) : undefined,\n focusedPointIndex: snapshot.focus === null ? undefined : drawn.indexOf(snapshot.focus),\n });\n const pinned = drawn.indicesOf(snapshot.pinned);\n ready.setPinnedPoints(pinned.length > 0 ? pinned : null);\n changed = true;\n }\n if (changed) ready.render();\n events.onFrame?.();\n }\n\n const frameExtent = (snapshot: GraphSnapshot) => {\n const extent = snapshot.matrix?.extent;\n if (!extent || snapshot.matrix === framed) return;\n framed = snapshot.matrix;\n whenReady(graph, (ready) => {\n ready.setConfigPartial({ spaceSize: Math.max(extent.w, extent.h) });\n ready.fitViewByPointPositions(corners(extent), 0, FIT_PADDING);\n observe();\n });\n };\n\n const unsubscribe = store.subscribe(() => {\n const snapshot = store.getSnapshot();\n const options = store.getOptions();\n frameExtent(snapshot);\n if (snapshot.visible !== last.visible || snapshot.binding !== last.binding || snapshot.domain !== last.domain) {\n dirty.compose = true;\n }\n if (options.look !== lookPatch) {\n lookPatch = options.look;\n look = resolveLook(options.look);\n dirty.paint = true;\n }\n if (options.fill !== lastOptions.fill || options.symbol !== lastOptions.symbol || options.stroke !== lastOptions.stroke) {\n dirty.paint = true;\n }\n if (snapshot.selection !== last.selection || snapshot.focus !== last.focus || snapshot.pinned !== last.pinned) {\n dirty.state = true;\n }\n if (options.sim !== lastOptions.sim || options.simulate !== lastOptions.simulate) applyForces(options.sim, options.simulate);\n last = snapshot;\n lastOptions = options;\n if (dirty.compose || dirty.paint || dirty.state) schedule();\n });\n\n function applyForces(patch: Partial<Sim> | undefined, simulate = false): void {\n const next = resolveSim(patch);\n const moved = Object.keys(next).some((key) => next[key as keyof Sim] !== sim[key as keyof Sim]);\n sim = next;\n whenReady(graph, (ready) => {\n ready.setConfigPartial({ enableSimulation: simulate, ...forces(next) });\n if (simulate && moved) ready.start(REHEAT);\n });\n }\n\n function focusOn(vertex: VertexId, index: number): void {\n const drawn = resident();\n const around = isReady(graph) ? drawn.verticesAt(graph.getNeighboringPointIndices(index)) : [];\n store.select([vertex, ...around], \"node\", \"Node\");\n store.focus(vertex);\n }\n\n function clear(): void {\n store.select(null);\n store.focus(null);\n }\n\n /** Centre and select one vertex; one that is not drawn is framed by its tile first, then revealed. */\n function reveal(vertex: VertexId): void {\n const index = resident().indexOf(vertex);\n if (index !== undefined) {\n focusOn(vertex, index);\n whenReady(graph, (ready) => ready.zoomToPointByIndex(index, 500, 5, true));\n return;\n }\n const matrix = store.getSnapshot().matrix;\n const address = matrix ? tileOfDense(matrix, denseOf(vertex)) : null;\n const box = address && matrix?.tileMatrices[address.z]?.tiles[address.tile]?.bbox;\n if (!box) return;\n pendingReveal = vertex;\n whenReady(graph, (ready) => ready.fitViewByPointPositions(corners(box), FIT_DURATION, FIT_PADDING));\n }\n\n // Primed first, so every `whenReady` below runs with `isReady` already answering true.\n isReady(graph);\n const painted = whenReady(graph, (ready) => {\n ready.setConfigPartial(appearance(look, host));\n ready.render();\n });\n const onLost = (event: Event) => {\n event.preventDefault();\n fail(\"The graph's WebGL context was lost. A browser keeps a limited number of them and drops the oldest; reload the page to get one back.\");\n };\n // Inside `whenReady`: cosmos.gl makes its canvas with the device, which is asynchronous.\n const listening = whenReady(graph, () => {\n host.querySelector(\"canvas\")?.addEventListener(\"webglcontextlost\", onLost);\n });\n store.report(store.getOptions().simulate && graph.isSimulationRunning ? \"running\" : \"settled\");\n frameExtent(last);\n schedule();\n\n return {\n graph,\n resident,\n composition: () => composition,\n repaint() {\n dirty.paint = true;\n schedule();\n },\n hit(shape) {\n if (!isReady(graph)) return [];\n const found = \"rect\" in shape ? graph.findPointsInRect(shape.rect) : graph.findPointsInPolygon(shape.polygon);\n return Array.from(found);\n },\n zoomBy(factor) {\n whenReady(graph, (ready) => ready.setZoomLevel(ready.getZoomLevel() * factor, 220));\n },\n fit() {\n const extent = store.getSnapshot().matrix?.extent;\n whenReady(graph, (ready) =>\n extent ? ready.fitViewByPointPositions(corners(extent), FIT_DURATION, FIT_PADDING) : ready.fitView(FIT_DURATION, FIT_PADDING),\n );\n },\n pause: () => whenReady(graph, (ready) => ready.pause()),\n resume() {\n const settled = store.getSnapshot().motion === \"settled\";\n whenReady(graph, (ready) => (settled ? ready.start(REHEAT) : ready.unpause()));\n },\n restart() {\n store.pin([]);\n whenReady(graph, (ready) => ready.start(1));\n },\n unpin() {\n if (store.getSnapshot().pinned.length === 0) return;\n store.pin([]);\n whenReady(graph, (ready) => ready.start(REHEAT));\n },\n reveal,\n frameBox(box, { duration = FIT_DURATION, padding = FIT_PADDING } = {}) {\n whenReady(graph, (ready) => ready.fitViewByPointPositions(corners(box), duration, padding));\n },\n frameSelection() {\n const indices = resident().indicesOf(store.getSnapshot().selection?.vertices ?? []);\n if (indices.length > 0) whenReady(graph, (ready) => ready.fitViewByPointIndices(indices, FIT_DURATION, 0.25));\n },\n clear,\n destroy() {\n unsubscribe();\n if (frame) cancelAnimationFrame(frame);\n painted();\n listening();\n // Read here rather than remembered from construction: the element exists only with the device.\n const canvas = host.querySelector(\"canvas\");\n canvas?.removeEventListener(\"webglcontextlost\", onLost);\n graph.destroy();\n releaseContext(canvas);\n },\n };\n}\n\nconst EMPTY: Resident = {\n size: 0,\n indexOf: () => undefined,\n at: () => undefined,\n indicesOf: () => [],\n verticesAt: () => [],\n};\n"],"names":["FIT_DURATION","FIT_PADDING","REHEAT","PROGRESS_STEPS","corners","box","createRenderer","host","store","events","fail","message","hasWebGL","sim","resolveSim","hovering","dragging","reported","progress","value","bucket","compose","createComposer","composition","look","resolveLook","lookPatch","dirty","frame","framed","pendingReveal","last","lastOptions","resident","EMPTY","viewport","height","width","isReady","graph","ax","ay","bx","by","view","observe","camera","Graph","forces","_a","index","vertex","focusOn","clear","error","schedule","whenReady","draw","ready","snapshot","options","changed","next","_b","reveal","drawn","buffers","paint","appearance","pinned","_c","frameExtent","extent","unsubscribe","applyForces","patch","simulate","moved","key","around","matrix","address","tileOfDense","denseOf","painted","onLost","event","listening","shape","found","factor","settled","duration","padding","indices","canvas","releaseContext"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Whether this browser can run the renderer at all. cosmos.gl draws its own message rather than
3
+ * throwing, and under 3.x `graph.ready` never settles when no device can be made — so the probe
4
+ * answers the common case before either can happen.
5
+ */
6
+ export declare function hasWebGL(): boolean;
7
+ /**
8
+ * **Give the WebGL context back, because cosmos.gl does not.** `WEBGL_lose_context` appears zero times
9
+ * in `@cosmos.gl/graph@3.4.0`, and Chrome keeps sixteen contexts per renderer process and evicts the
10
+ * oldest without an error: `/docs/graph` mounts four graphs under StrictMode and three of them
11
+ * measured `isContextLost === true` before this existed.
12
+ */
13
+ export declare function releaseContext(canvas: HTMLCanvasElement | null): void;
14
+ //# sourceMappingURL=webgl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webgl.d.ts","sourceRoot":"","sources":["../../src/render/webgl.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAQlC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAGrE"}
@@ -0,0 +1,19 @@
1
+ function n() {
2
+ if (typeof document > "u") return !1;
3
+ try {
4
+ const e = document.createElement("canvas");
5
+ return e.getContext("webgl2") !== null || e.getContext("webgl") !== null;
6
+ } catch {
7
+ return !1;
8
+ }
9
+ }
10
+ function l(e) {
11
+ var o;
12
+ const t = (e == null ? void 0 : e.getContext("webgl2")) ?? (e == null ? void 0 : e.getContext("webgl"));
13
+ t && !t.isContextLost() && ((o = t.getExtension("WEBGL_lose_context")) == null || o.loseContext());
14
+ }
15
+ export {
16
+ n as hasWebGL,
17
+ l as releaseContext
18
+ };
19
+ //# sourceMappingURL=webgl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webgl.js","sources":["../../src/render/webgl.ts"],"sourcesContent":["/**\n * Whether this browser can run the renderer at all. cosmos.gl draws its own message rather than\n * throwing, and under 3.x `graph.ready` never settles when no device can be made — so the probe\n * answers the common case before either can happen.\n */\nexport function 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.** `WEBGL_lose_context` appears zero times\n * in `@cosmos.gl/graph@3.4.0`, and Chrome keeps sixteen contexts per renderer process and evicts the\n * oldest without an error: `/docs/graph` mounts four graphs under StrictMode and three of them\n * measured `isContextLost === true` before this existed.\n */\nexport function 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"],"names":["hasWebGL","probe","releaseContext","canvas","_a","gl"],"mappings":"AAKO,SAASA,IAAoB;AAClC,MAAI,OAAO,WAAa,IAAa,QAAO;AAC5C,MAAI;AACF,UAAMC,IAAQ,SAAS,cAAc,QAAQ;AAC7C,WAAOA,EAAM,WAAW,QAAQ,MAAM,QAAQA,EAAM,WAAW,OAAO,MAAM;AAAA,EAC9E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQO,SAASC,EAAeC,GAAwC;AAhBhE,MAAAC;AAiBL,QAAMC,KAAKF,KAAA,gBAAAA,EAAQ,WAAW,eAAaA,KAAA,gBAAAA,EAAQ,WAAW;AAC9D,EAAIE,KAAM,CAACA,EAAG,cAAA,OAAiBD,IAAAC,EAAG,aAAa,oBAAoB,MAApC,QAAAD,EAAuC;AACxE;"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"when-ready.d.ts","sourceRoot":"","sources":["../../src/render/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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"when-ready.js","sources":["../../src/render/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;"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kanzo-tech/graph",
3
- "version": "0.9.0",
4
- "description": "Kanzo graph rendering — a GPU force layout over cosmos.gl, the DuckDB relation that feeds it, and the Mosaic client that keeps it inside a crossfilter. Sibling of @kanzo-tech/ui, not part of it: the admission rules exclude graphs from the generic vocabulary by name.",
3
+ "version": "0.11.0",
4
+ "description": "Kanzo graph view — a tileset over a fossil corpus's scan, drawn with cosmos.gl, inside the page's Mosaic crossfilter. 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",
7
7
  "sideEffects": false,
@@ -16,36 +16,25 @@
16
16
  "types": "./dist/index.d.ts",
17
17
  "import": "./dist/index.js"
18
18
  },
19
- "./duckdb": {
20
- "types": "./dist/duck-source.d.ts",
21
- "import": "./dist/duck-source.js"
22
- },
23
19
  "./section": {
24
20
  "types": "./dist/section.d.ts",
25
21
  "import": "./dist/section.js"
26
22
  },
27
23
  "./package.json": "./package.json"
28
24
  },
29
- "//peers": "cosmos.gl is a real, required peer — this package is a renderer and there is nothing left of it without one. The Mosaic half is optional and lives entirely on `./duckdb`, and the reason moved when the second source left: it used to be `a consumer drawing a graph from arrays it already has should not pay for a database`, which stopped being true the day `memorySource` was deleted — there is no arrays-in-hand consumer to protect any more. What the split protects now is the ROOT BARREL, which is a rendering surface: hooks, looks, identity, the buffers a slice implies, and no source at all. A host embedding a canvas whose slices arrive from somewhere else — its own `BoundedSource`, a worker, a test — installs cosmos.gl and nothing else, and `openCorpus` is what costs a database. That half is now ONE entry, `@kanzo-tech/mosaic`, and the list is shorter than the thing it replaced for a reason worth keeping: this package used to reach the coordinator through `@kanzo-tech/ui/analytics`, whose barrel re-exports the React charts and `@uwdata/vgplot` with them. The import is static, so a host that installed the two peers we documented — mosaic-core and mosaic-sql — still could not open `./duckdb`, and vgplot had to be declared here to paper over a dependency this package never names. It names none of the three now: they are `@kanzo-tech/mosaic`'s peers, declared once, which is also why their version ranges can no longer disagree. @duckdb/duckdb-wasm stays absent for the reason it always was — nothing in any of our dist names it, and a host that boots its own DuckDB depends on it directly. `scripts/smoke-install.mjs` installs no optional peer and imports the root barrel, which is the check that reads this list rather than trusting it.",
30
- "//fossil": "The reader is on npm, so the range is a range. This entry said LOCAL LINK, NOT A RELEASE STATE while `@fossil-lang/corpus` existed only in a checkout beside this one; it was published as `0.3.0-alpha.5` and the `link:` and the `*` went with the reason for them. The peer itself is not temporary: fossil's reader sits beside `@kanzo-tech/mosaic` on `./duckdb` and is wanted for the same reason — a host reading a corpus brings its own, and a host that only renders pays for neither. The residual cost this entry used to name is GONE rather than mitigated: `duckBoundedSource` shared the subpath and did not need this peer, so a host on it either installed the reader or the entry had to be split. There is nothing on `./duckdb` now that does not want fossil, so the subpath and the peer are the same decision and there is no entry to split. The floor is `0.3.0-alpha.10` because `openCorpus` takes the corpus the host opened and hands on the names fossil's verbs query it by — `CorpusRelation.sql`, qualified by the corpus's own catalog — and that release is the one that answers with them.",
25
+ "//peers": "All required. cosmos.gl draws; `lucide-react` is the icon set the parts draw their buttons with, `@kanzo-tech/ui`'s own peer; `@fossil-lang/corpus` is the backend — the host opens a corpus with its `open` on `@kanzo-tech/mosaic`'s `engine()` and this package draws it through `tileMatrix`, `scan` and `edges`, writing no SQL of its own; `@kanzo-tech/mosaic` carries the crossfilter the graph listens to and publishes into. They were optional while a root barrel with no source and a `./duckdb` entry with one existed side by side; there is one path now and nothing on it is optional (`/docs/design/graph`, *the one host path*). The Mosaic stack itself — mosaic-core, mosaic-sql — is `@kanzo-tech/mosaic`'s peer, declared once there.",
26
+ "//fossil": "The floor is `0.3.0-alpha.13`, the release whose `scan(…).read` and `edges` take a list of addresses and answer one batch per tile, and an `Engine.query` that answers in columns and interrupts on abort, over corpora whose `dense_id` is the Hilbert rank. Only types and the writer's role table (`PAYLOAD_*`) are imported; `src/layers.test.ts` holds that.",
31
27
  "peerDependencies": {
32
28
  "@cosmos.gl/graph": "^3.4.0",
33
- "@fossil-lang/corpus": "^0.3.0-alpha.10",
29
+ "@fossil-lang/corpus": "^0.3.0-alpha.13",
30
+ "lucide-react": ">=1",
34
31
  "react": "^19.0.0",
35
- "@kanzo-tech/mosaic": "0.9.0",
36
- "@kanzo-tech/ui": "0.9.0"
37
- },
38
- "peerDependenciesMeta": {
39
- "@fossil-lang/corpus": {
40
- "optional": true
41
- },
42
- "@kanzo-tech/mosaic": {
43
- "optional": true
44
- }
32
+ "@kanzo-tech/ui": "0.11.0",
33
+ "@kanzo-tech/mosaic": "0.11.0"
45
34
  },
46
35
  "devDependencies": {
47
36
  "@cosmos.gl/graph": "^3.4.0",
48
- "@fossil-lang/corpus": "^0.3.0-alpha.10",
37
+ "@fossil-lang/corpus": "^0.3.0-alpha.13",
49
38
  "@testing-library/dom": "^10.4.1",
50
39
  "@testing-library/react": "^16.3.2",
51
40
  "@types/react": "^19.0.0",
@@ -53,10 +42,11 @@
53
42
  "@uwdata/mosaic-core": "^0.29.2",
54
43
  "@uwdata/mosaic-sql": "^0.29.0",
55
44
  "jsdom": "^25.0.0",
45
+ "lucide-react": "^1.23.0",
56
46
  "react": "^19.0.0",
57
47
  "react-dom": "^19.0.0",
58
48
  "rollup-plugin-preserve-directives": "^0.4.0",
59
- "@kanzo-tech/mosaic": "0.9.0"
49
+ "@kanzo-tech/mosaic": "0.11.0"
60
50
  },
61
51
  "repository": {
62
52
  "type": "git",