@pibbl/core 0.0.2 → 0.0.3-alpha.90.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/THIRD_PARTY_NOTICES.txt +81 -0
  2. package/dist/features/textures/index.d.ts +12 -2
  3. package/dist/features/textures/index.js +33 -1
  4. package/dist/features/textures/index.js.map +2 -2
  5. package/dist/features/textures/lib/chemical-field.d.ts +56 -0
  6. package/dist/features/textures/lib/chemical-field.js +154 -0
  7. package/dist/features/textures/lib/chemical-field.js.map +7 -0
  8. package/dist/features/textures/lib/chemical-recipes.d.ts +119 -0
  9. package/dist/features/textures/lib/chemical-recipes.js +275 -0
  10. package/dist/features/textures/lib/chemical-recipes.js.map +7 -0
  11. package/dist/features/textures/lib/definitions.d.ts +3 -18
  12. package/dist/features/textures/lib/definitions.js +15 -20
  13. package/dist/features/textures/lib/definitions.js.map +2 -2
  14. package/dist/features/textures/lib/geometric-patterns.d.ts +149 -0
  15. package/dist/features/textures/lib/geometric-patterns.js +305 -0
  16. package/dist/features/textures/lib/geometric-patterns.js.map +7 -0
  17. package/dist/features/textures/lib/gray-scott.d.ts +55 -0
  18. package/dist/features/textures/lib/gray-scott.js +39 -0
  19. package/dist/features/textures/lib/gray-scott.js.map +7 -0
  20. package/dist/features/textures/lib/patterns.d.ts +123 -0
  21. package/dist/features/textures/lib/patterns.js +344 -0
  22. package/dist/features/textures/lib/patterns.js.map +7 -0
  23. package/dist/features/textures/lib/reaction-diffusion.d.ts +3 -2
  24. package/dist/features/textures/lib/reaction-diffusion.js +9 -20
  25. package/dist/features/textures/lib/reaction-diffusion.js.map +2 -2
  26. package/dist/features/textures/lib/simulation.d.ts +10 -4
  27. package/dist/features/textures/lib/simulation.js +23 -13
  28. package/dist/features/textures/lib/simulation.js.map +2 -2
  29. package/dist/features/viz/index.d.ts +68 -6
  30. package/dist/features/viz/index.js +164 -2
  31. package/dist/features/viz/index.js.map +2 -2
  32. package/dist/features/viz/inspection/bar.d.ts +79 -0
  33. package/dist/features/viz/inspection/bar.js +49 -0
  34. package/dist/features/viz/inspection/bar.js.map +7 -0
  35. package/dist/features/viz/inspection/candle.d.ts +156 -0
  36. package/dist/features/viz/inspection/candle.js +120 -0
  37. package/dist/features/viz/inspection/candle.js.map +7 -0
  38. package/dist/features/viz/inspection/capture-types.d.ts +65 -0
  39. package/dist/features/viz/inspection/capture.d.ts +16 -0
  40. package/dist/features/viz/inspection/capture.js +49 -0
  41. package/dist/features/viz/inspection/capture.js.map +7 -0
  42. package/dist/features/viz/inspection/handler.d.ts +36 -0
  43. package/dist/features/viz/inspection/handler.js +91 -0
  44. package/dist/features/viz/inspection/handler.js.map +7 -0
  45. package/dist/features/viz/inspection/ohlc-bar.d.ts +132 -0
  46. package/dist/features/viz/inspection/ohlc-bar.js +118 -0
  47. package/dist/features/viz/inspection/ohlc-bar.js.map +7 -0
  48. package/dist/features/viz/inspection/owned-ref.d.ts +16 -0
  49. package/dist/features/viz/inspection/owned-ref.js +99 -0
  50. package/dist/features/viz/inspection/owned-ref.js.map +7 -0
  51. package/dist/features/viz/inspection/painted-point.d.ts +22 -0
  52. package/dist/features/viz/inspection/painted-point.js +29 -0
  53. package/dist/features/viz/inspection/painted-point.js.map +7 -0
  54. package/dist/features/viz/inspection/queries.d.ts +100 -0
  55. package/dist/features/viz/inspection/queries.js +192 -0
  56. package/dist/features/viz/inspection/queries.js.map +7 -0
  57. package/dist/features/viz/inspection/query-types.d.ts +177 -0
  58. package/dist/features/viz/inspection/volume.d.ts +104 -0
  59. package/dist/features/viz/inspection/volume.js +95 -0
  60. package/dist/features/viz/inspection/volume.js.map +7 -0
  61. package/dist/features/viz/inspection.d.ts +19 -0
  62. package/dist/features/viz/inspection.js +54 -0
  63. package/dist/features/viz/inspection.js.map +7 -0
  64. package/dist/features/viz/inspection.mjs +1 -0
  65. package/dist/features/viz/lib/area-series.d.ts +62 -0
  66. package/dist/features/viz/lib/area-series.js +120 -0
  67. package/dist/features/viz/lib/area-series.js.map +7 -0
  68. package/dist/features/viz/lib/axis.js +1 -1
  69. package/dist/features/viz/lib/axis.js.map +2 -2
  70. package/dist/features/viz/lib/bar-series.d.ts +3 -1
  71. package/dist/features/viz/lib/bar-series.js +16 -1
  72. package/dist/features/viz/lib/bar-series.js.map +2 -2
  73. package/dist/features/viz/lib/baseline-series.d.ts +55 -0
  74. package/dist/features/viz/lib/baseline-series.js +136 -0
  75. package/dist/features/viz/lib/baseline-series.js.map +7 -0
  76. package/dist/features/viz/lib/candlestick-series.d.ts +62 -0
  77. package/dist/features/viz/lib/candlestick-series.js +150 -0
  78. package/dist/features/viz/lib/candlestick-series.js.map +7 -0
  79. package/dist/features/viz/lib/censored-point-series.d.ts +71 -0
  80. package/dist/features/viz/lib/censored-point-series.js +129 -0
  81. package/dist/features/viz/lib/censored-point-series.js.map +7 -0
  82. package/dist/features/viz/lib/color-context.d.ts +4 -0
  83. package/dist/features/viz/lib/color-context.js +41 -0
  84. package/dist/features/viz/lib/color-context.js.map +7 -0
  85. package/dist/features/viz/lib/color-math.d.ts +4 -0
  86. package/dist/features/viz/lib/color-math.js +31 -0
  87. package/dist/features/viz/lib/color-math.js.map +7 -0
  88. package/dist/features/viz/lib/color-types.d.ts +53 -0
  89. package/dist/features/viz/lib/curve-definition.d.ts +49 -0
  90. package/dist/features/viz/lib/curve-definition.js +148 -0
  91. package/dist/features/viz/lib/curve-definition.js.map +7 -0
  92. package/dist/features/viz/lib/diverging-color-scale.d.ts +11 -0
  93. package/dist/features/viz/lib/diverging-color-scale.js +51 -0
  94. package/dist/features/viz/lib/diverging-color-scale.js.map +7 -0
  95. package/dist/features/viz/lib/domain-navigation.d.ts +40 -0
  96. package/dist/features/viz/lib/domain-navigation.js +77 -0
  97. package/dist/features/viz/lib/domain-navigation.js.map +7 -0
  98. package/dist/features/viz/lib/editable-chart-elements.d.ts +178 -0
  99. package/dist/features/viz/lib/editable-chart-elements.js +733 -0
  100. package/dist/features/viz/lib/editable-chart-elements.js.map +7 -0
  101. package/dist/features/viz/lib/financial-aggregation.d.ts +127 -0
  102. package/dist/features/viz/lib/financial-aggregation.js +116 -0
  103. package/dist/features/viz/lib/financial-aggregation.js.map +7 -0
  104. package/dist/features/viz/lib/financial-autoscale.d.ts +64 -0
  105. package/dist/features/viz/lib/financial-autoscale.js +61 -0
  106. package/dist/features/viz/lib/financial-autoscale.js.map +7 -0
  107. package/dist/features/viz/lib/financial-comparison.d.ts +62 -0
  108. package/dist/features/viz/lib/financial-comparison.js +98 -0
  109. package/dist/features/viz/lib/financial-comparison.js.map +7 -0
  110. package/dist/features/viz/lib/financial-geometry.d.ts +77 -0
  111. package/dist/features/viz/lib/financial-geometry.js +67 -0
  112. package/dist/features/viz/lib/financial-geometry.js.map +7 -0
  113. package/dist/features/viz/lib/financial-indicators.d.ts +114 -0
  114. package/dist/features/viz/lib/financial-indicators.js +135 -0
  115. package/dist/features/viz/lib/financial-indicators.js.map +7 -0
  116. package/dist/features/viz/lib/financial-oscillators.d.ts +171 -0
  117. package/dist/features/viz/lib/financial-oscillators.js +265 -0
  118. package/dist/features/viz/lib/financial-oscillators.js.map +7 -0
  119. package/dist/features/viz/lib/graph/bipartite.d.ts +14 -0
  120. package/dist/features/viz/lib/graph/bipartite.js +250 -0
  121. package/dist/features/viz/lib/graph/bipartite.js.map +7 -0
  122. package/dist/features/viz/lib/graph/chord.d.ts +44 -0
  123. package/dist/features/viz/lib/graph/chord.js +348 -0
  124. package/dist/features/viz/lib/graph/chord.js.map +7 -0
  125. package/dist/features/viz/lib/graph/dependency.d.ts +26 -0
  126. package/dist/features/viz/lib/graph/dependency.js +141 -0
  127. package/dist/features/viz/lib/graph/dependency.js.map +7 -0
  128. package/dist/features/viz/lib/graph/force.d.ts +28 -0
  129. package/dist/features/viz/lib/graph/force.js +580 -0
  130. package/dist/features/viz/lib/graph/force.js.map +7 -0
  131. package/dist/features/viz/lib/graph/hierarchy.d.ts +21 -0
  132. package/dist/features/viz/lib/graph/hierarchy.js +112 -0
  133. package/dist/features/viz/lib/graph/hierarchy.js.map +7 -0
  134. package/dist/features/viz/lib/graph/icicle.d.ts +16 -0
  135. package/dist/features/viz/lib/graph/icicle.js +153 -0
  136. package/dist/features/viz/lib/graph/icicle.js.map +7 -0
  137. package/dist/features/viz/lib/graph/matrix.d.ts +30 -0
  138. package/dist/features/viz/lib/graph/matrix.js +243 -0
  139. package/dist/features/viz/lib/graph/matrix.js.map +7 -0
  140. package/dist/features/viz/lib/graph/neighborhood.d.ts +11 -0
  141. package/dist/features/viz/lib/graph/neighborhood.js +281 -0
  142. package/dist/features/viz/lib/graph/neighborhood.js.map +7 -0
  143. package/dist/features/viz/lib/graph/routes.d.ts +35 -0
  144. package/dist/features/viz/lib/graph/routes.js +102 -0
  145. package/dist/features/viz/lib/graph/routes.js.map +7 -0
  146. package/dist/features/viz/lib/graph/sankey.d.ts +44 -0
  147. package/dist/features/viz/lib/graph/sankey.js +341 -0
  148. package/dist/features/viz/lib/graph/sankey.js.map +7 -0
  149. package/dist/features/viz/lib/graph/shared.d.ts +59 -0
  150. package/dist/features/viz/lib/graph/shared.js +296 -0
  151. package/dist/features/viz/lib/graph/shared.js.map +7 -0
  152. package/dist/features/viz/lib/graph/tree.d.ts +11 -0
  153. package/dist/features/viz/lib/graph/tree.js +232 -0
  154. package/dist/features/viz/lib/graph/tree.js.map +7 -0
  155. package/dist/features/viz/lib/graph/treemap.d.ts +20 -0
  156. package/dist/features/viz/lib/graph/treemap.js +227 -0
  157. package/dist/features/viz/lib/graph/treemap.js.map +7 -0
  158. package/dist/features/viz/lib/graph/types.d.ts +1097 -0
  159. package/dist/features/viz/lib/hover-data.d.ts +1 -1
  160. package/dist/features/viz/lib/hover-data.js +5 -2
  161. package/dist/features/viz/lib/hover-data.js.map +2 -2
  162. package/dist/features/viz/lib/interval-band-series.d.ts +49 -0
  163. package/dist/features/viz/lib/interval-band-series.js +136 -0
  164. package/dist/features/viz/lib/interval-band-series.js.map +7 -0
  165. package/dist/features/viz/lib/interval-diamond-series.d.ts +43 -0
  166. package/dist/features/viz/lib/interval-diamond-series.js +124 -0
  167. package/dist/features/viz/lib/interval-diamond-series.js.map +7 -0
  168. package/dist/features/viz/lib/interval-series.d.ts +79 -0
  169. package/dist/features/viz/lib/interval-series.js +158 -0
  170. package/dist/features/viz/lib/interval-series.js.map +7 -0
  171. package/dist/features/viz/lib/line-series.d.ts +1 -1
  172. package/dist/features/viz/lib/line-series.js +47 -28
  173. package/dist/features/viz/lib/line-series.js.map +2 -2
  174. package/dist/features/viz/lib/linear-scale.js +1 -1
  175. package/dist/features/viz/lib/linear-scale.js.map +2 -2
  176. package/dist/features/viz/lib/monotone-curve.d.ts +11 -0
  177. package/dist/features/viz/lib/monotone-curve.js +63 -0
  178. package/dist/features/viz/lib/monotone-curve.js.map +7 -0
  179. package/dist/features/viz/lib/numeric-range-interpolation.d.ts +15 -0
  180. package/dist/features/viz/lib/numeric-range-interpolation.js +36 -0
  181. package/dist/features/viz/lib/numeric-range-interpolation.js.map +7 -0
  182. package/dist/features/viz/lib/ohlc-bar-series.d.ts +55 -0
  183. package/dist/features/viz/lib/ohlc-bar-series.js +168 -0
  184. package/dist/features/viz/lib/ohlc-bar-series.js.map +7 -0
  185. package/dist/features/viz/lib/paired-series.d.ts +44 -0
  186. package/dist/features/viz/lib/paired-series.js +93 -0
  187. package/dist/features/viz/lib/paired-series.js.map +7 -0
  188. package/dist/features/viz/lib/plot-series.js +11 -6
  189. package/dist/features/viz/lib/plot-series.js.map +2 -2
  190. package/dist/features/viz/lib/plot-types.d.ts +4 -3
  191. package/dist/features/viz/lib/point-series.d.ts +1 -1
  192. package/dist/features/viz/lib/point-series.js +36 -9
  193. package/dist/features/viz/lib/point-series.js.map +2 -2
  194. package/dist/features/viz/lib/point-types.d.ts +5 -2
  195. package/dist/features/viz/lib/scale-context.d.ts +1 -1
  196. package/dist/features/viz/lib/scale-ticks.js +21 -6
  197. package/dist/features/viz/lib/scale-ticks.js.map +2 -2
  198. package/dist/features/viz/lib/sequential-color-scale.d.ts +11 -0
  199. package/dist/features/viz/lib/sequential-color-scale.js +49 -0
  200. package/dist/features/viz/lib/sequential-color-scale.js.map +7 -0
  201. package/dist/features/viz/lib/series-position.d.ts +12 -0
  202. package/dist/features/viz/lib/series-position.js +44 -0
  203. package/dist/features/viz/lib/series-position.js.map +7 -0
  204. package/dist/features/viz/lib/step-curves.d.ts +19 -0
  205. package/dist/features/viz/lib/step-curves.js +53 -0
  206. package/dist/features/viz/lib/step-curves.js.map +7 -0
  207. package/dist/features/viz/lib/threshold-color-scale.d.ts +43 -0
  208. package/dist/features/viz/lib/threshold-color-scale.js +59 -0
  209. package/dist/features/viz/lib/threshold-color-scale.js.map +7 -0
  210. package/dist/features/viz/lib/trading-time-mapping.d.ts +32 -0
  211. package/dist/features/viz/lib/trading-time-mapping.js +89 -0
  212. package/dist/features/viz/lib/trading-time-mapping.js.map +7 -0
  213. package/dist/features/viz/lib/trading-time-scale.d.ts +83 -0
  214. package/dist/features/viz/lib/trading-time-scale.js +96 -0
  215. package/dist/features/viz/lib/trading-time-scale.js.map +7 -0
  216. package/dist/features/viz/lib/trajectory-series.d.ts +71 -0
  217. package/dist/features/viz/lib/trajectory-series.js +111 -0
  218. package/dist/features/viz/lib/trajectory-series.js.map +7 -0
  219. package/dist/features/viz/lib/types.d.ts +20 -4
  220. package/dist/features/viz/lib/use-continuous-scale.js +6 -1
  221. package/dist/features/viz/lib/use-continuous-scale.js.map +2 -2
  222. package/dist/features/viz/lib/volume-series.d.ts +59 -0
  223. package/dist/features/viz/lib/volume-series.js +117 -0
  224. package/dist/features/viz/lib/volume-series.js.map +7 -0
  225. package/dist/features/viz/lib/weighted-point-series.d.ts +71 -0
  226. package/dist/features/viz/lib/weighted-point-series.js +169 -0
  227. package/dist/features/viz/lib/weighted-point-series.js.map +7 -0
  228. package/dist/filters/backdrop-contrast-gpu.d.ts +5 -0
  229. package/dist/filters/backdrop-contrast-gpu.js +33 -0
  230. package/dist/filters/backdrop-contrast-gpu.js.map +7 -0
  231. package/dist/filters/backdrop-contrast.d.ts +21 -0
  232. package/dist/filters/backdrop-contrast.js +61 -0
  233. package/dist/filters/backdrop-contrast.js.map +7 -0
  234. package/dist/filters/emboss-gpu.d.ts +4 -0
  235. package/dist/filters/emboss-gpu.js +39 -0
  236. package/dist/filters/emboss-gpu.js.map +7 -0
  237. package/dist/filters/emboss.d.ts +32 -0
  238. package/dist/filters/emboss.js +106 -0
  239. package/dist/filters/emboss.js.map +7 -0
  240. package/dist/filters/filter-executor.d.ts +11 -4
  241. package/dist/filters/filter-executor.js +104 -49
  242. package/dist/filters/filter-executor.js.map +2 -2
  243. package/dist/filters/reflection-gpu.d.ts +3 -1
  244. package/dist/filters/reflection-gpu.js +5 -2
  245. package/dist/filters/reflection-gpu.js.map +2 -2
  246. package/dist/filters/render-backdrop-contrast-boundary.d.ts +31 -0
  247. package/dist/filters/render-backdrop-contrast-boundary.js +116 -0
  248. package/dist/filters/render-backdrop-contrast-boundary.js.map +7 -0
  249. package/dist/filters/render-emboss-boundary.d.ts +13 -0
  250. package/dist/filters/render-emboss-boundary.js +131 -0
  251. package/dist/filters/render-emboss-boundary.js.map +7 -0
  252. package/dist/filters.d.ts +9 -5
  253. package/dist/filters.js +4 -0
  254. package/dist/filters.js.map +2 -2
  255. package/dist/index.d.ts +2 -0
  256. package/dist/index.js +3 -0
  257. package/dist/index.js.map +2 -2
  258. package/dist/internal.d.ts +2 -0
  259. package/dist/internal.js +4 -0
  260. package/dist/internal.js.map +2 -2
  261. package/dist/lib/events/event-facade.d.ts +13 -0
  262. package/dist/lib/events/event-facade.js +23 -0
  263. package/dist/lib/events/event-facade.js.map +2 -2
  264. package/dist/lib/events/propagation.js +19 -14
  265. package/dist/lib/events/propagation.js.map +2 -2
  266. package/dist/lib/execute-render.js +13 -0
  267. package/dist/lib/execute-render.js.map +2 -2
  268. package/dist/lib/recording/recording.d.ts +43 -0
  269. package/dist/lib/recording/recording.js +555 -0
  270. package/dist/lib/recording/recording.js.map +7 -0
  271. package/dist/lib/recording/types.d.ts +118 -0
  272. package/dist/lib/recording/wasm-bytes.d.ts +1 -0
  273. package/dist/lib/recording/wasm-bytes.js +5 -0
  274. package/dist/lib/recording/wasm-bytes.js.map +7 -0
  275. package/dist/lib/recording/worker-source.d.ts +1 -0
  276. package/dist/lib/recording/worker-source.js +5 -0
  277. package/dist/lib/recording/worker-source.js.map +7 -0
  278. package/dist/lib/render-transaction.d.ts +5 -2
  279. package/dist/lib/render-transaction.js +23 -1
  280. package/dist/lib/render-transaction.js.map +2 -2
  281. package/dist/lib/series-inspection-frame.d.ts +18 -0
  282. package/dist/lib/series-inspection-frame.js +70 -0
  283. package/dist/lib/series-inspection-frame.js.map +7 -0
  284. package/dist/lib/types.d.ts +6 -0
  285. package/package.json +10 -2
@@ -0,0 +1,250 @@
1
+ import { jsx, jsxs } from "@pibbl/core/jsx-runtime";
2
+ import { Group, SvgPath, resolveSignalValue } from "@pibbl/core";
3
+ import {
4
+ defaultGraphEdgeStyle,
5
+ defaultGraphLabelStyle,
6
+ defaultGraphNodeStyle,
7
+ GraphLabel,
8
+ GraphNode,
9
+ resolveMarkStyle,
10
+ useGraphFrame
11
+ } from "./shared.js";
12
+ function access(input, datum) {
13
+ return typeof input === "function" ? input(datum) : datum[input];
14
+ }
15
+ function finite(value, name, zero = false) {
16
+ if (!Number.isFinite(value) || zero && value < 0)
17
+ throw new RangeError(
18
+ `layoutBipartite: ${name} must be finite${zero ? " and nonnegative" : ""}.`
19
+ );
20
+ return value;
21
+ }
22
+ function label(text, bounds) {
23
+ return Object.freeze({
24
+ text,
25
+ bounds: Object.freeze(bounds),
26
+ rotationDegrees: 0
27
+ });
28
+ }
29
+ function route(a, b) {
30
+ const middle = (a.x + b.x) / 2;
31
+ const segments = Object.freeze([
32
+ { type: "move", x: a.x, y: a.y },
33
+ {
34
+ type: "cubic",
35
+ cp1x: middle,
36
+ cp1y: a.y,
37
+ cp2x: middle,
38
+ cp2y: b.y,
39
+ x: b.x,
40
+ y: b.y
41
+ }
42
+ ]);
43
+ return Object.freeze({
44
+ sourceAnchor: Object.freeze(a),
45
+ targetAnchor: Object.freeze(b),
46
+ segments,
47
+ arrowSegments: null
48
+ });
49
+ }
50
+ function path(route2) {
51
+ return route2.segments.map(
52
+ (segment) => segment.type === "move" ? `M ${segment.x} ${segment.y}` : segment.type === "cubic" ? `C ${segment.cp1x} ${segment.cp1y} ${segment.cp2x} ${segment.cp2y} ${segment.x} ${segment.y}` : ""
53
+ ).join(" ");
54
+ }
55
+ function placed(data, keyBy, labelBy, atX, bounds, size, gap) {
56
+ const total = data.reduce((sum, datum) => sum + (size?.(datum).height ?? 34), 0) + Math.max(0, data.length - 1) * gap;
57
+ let y = bounds.y + Math.max(0, (bounds.height - total) / 2);
58
+ const seen = /* @__PURE__ */ new Set();
59
+ return Object.freeze(
60
+ data.map((datum) => {
61
+ const key = access(keyBy, datum);
62
+ if (seen.has(key))
63
+ throw new Error(
64
+ `layoutBipartite: duplicate node key ${String(key)} on one side.`
65
+ );
66
+ seen.add(key);
67
+ const dimensions = size?.(datum) ?? { width: 150, height: 34 };
68
+ const box = {
69
+ x: atX,
70
+ y,
71
+ width: dimensions.width,
72
+ height: dimensions.height
73
+ };
74
+ y += dimensions.height + gap;
75
+ return Object.freeze({
76
+ key,
77
+ datum,
78
+ bounds: Object.freeze(box),
79
+ label: label(labelBy ? access(labelBy, datum) : String(key), box),
80
+ detail: null
81
+ });
82
+ })
83
+ );
84
+ }
85
+ function layoutBipartite(graph, options) {
86
+ const b = options.bounds;
87
+ finite(b.x, "bounds.x");
88
+ finite(b.y, "bounds.y");
89
+ finite(b.width, "bounds.width", true);
90
+ finite(b.height, "bounds.height", true);
91
+ const gap = finite(options.nodeGap ?? 12, "nodeGap", true), columnGap = finite(options.columnGap ?? 120, "columnGap", true);
92
+ const leftSize = options.leftSize, leftResolver = typeof leftSize === "function" ? leftSize : leftSize === void 0 ? void 0 : () => leftSize;
93
+ const rightSize = options.rightSize, rightResolver = typeof rightSize === "function" ? rightSize : rightSize === void 0 ? void 0 : () => rightSize;
94
+ const left = placed(
95
+ graph.left,
96
+ options.leftKey,
97
+ options.leftLabel,
98
+ b.x,
99
+ b,
100
+ leftResolver,
101
+ gap
102
+ );
103
+ const rightWidth = typeof rightSize === "function" ? 150 : rightSize?.width ?? 150;
104
+ const right = placed(
105
+ graph.right,
106
+ options.rightKey,
107
+ options.rightLabel,
108
+ Math.max(b.x, b.x + b.width - rightWidth),
109
+ b,
110
+ rightResolver,
111
+ gap
112
+ );
113
+ const leftByKey = new Map(left.map((node) => [node.key, node])), rightByKey = new Map(right.map((node) => [node.key, node]));
114
+ const edgeKeys = /* @__PURE__ */ new Set();
115
+ const edges = graph.edges.map((edge) => {
116
+ const key = access(options.edgeKey, edge);
117
+ if (edgeKeys.has(key))
118
+ throw new Error(`layoutBipartite: duplicate edge key ${String(key)}.`);
119
+ edgeKeys.add(key);
120
+ const source = access(options.source, edge), target = access(options.target, edge), leftNode = leftByKey.get(source), rightNode = rightByKey.get(target);
121
+ if (!leftNode || !rightNode)
122
+ throw new RangeError(
123
+ "layoutBipartite: every edge must point from a known left key to a known right key."
124
+ );
125
+ const r = route(
126
+ {
127
+ x: leftNode.bounds.x + leftNode.bounds.width,
128
+ y: leftNode.bounds.y + leftNode.bounds.height / 2
129
+ },
130
+ {
131
+ x: rightNode.bounds.x,
132
+ y: rightNode.bounds.y + rightNode.bounds.height / 2
133
+ }
134
+ );
135
+ return Object.freeze({
136
+ key,
137
+ datum: edge,
138
+ sourceKey: source,
139
+ targetKey: target,
140
+ left: leftNode,
141
+ right: rightNode,
142
+ route: r,
143
+ path: path(r),
144
+ arrowPath: null
145
+ });
146
+ });
147
+ if (left.length && right.length && right[0].bounds.x - (left[0].bounds.x + left[0].bounds.width) < columnGap)
148
+ throw new RangeError(
149
+ "layoutBipartite: bounds are too narrow for node sizes and columnGap."
150
+ );
151
+ return Object.freeze({
152
+ bounds: Object.freeze({ ...b }),
153
+ left,
154
+ right,
155
+ edges: Object.freeze(edges)
156
+ });
157
+ }
158
+ function BipartiteGraph(props) {
159
+ const frame = useGraphFrame(props.style), style = frame.style;
160
+ if (!frame.bounds.width || !frame.bounds.height)
161
+ return /* @__PURE__ */ jsx(Group, { style: frame.groupStyle, children: null });
162
+ const layout = layoutBipartite(resolveSignalValue(props.graph), {
163
+ ...props,
164
+ bounds: frame.bounds,
165
+ columnGap: style.columnGap,
166
+ nodeGap: style.nodeGap
167
+ });
168
+ return /* @__PURE__ */ jsxs(Group, { style: frame.groupStyle, children: [
169
+ layout.edges.map((edge) => /* @__PURE__ */ jsx(
170
+ Group,
171
+ {
172
+ onClick: (event) => props.onEdgeClick?.(edge, event),
173
+ children: props.renderEdge ? props.renderEdge(edge) : /* @__PURE__ */ jsx(
174
+ SvgPath,
175
+ {
176
+ style: {
177
+ ...defaultGraphEdgeStyle(edge),
178
+ ...resolveMarkStyle(edge, props.edgeStyle),
179
+ d: edge.path
180
+ }
181
+ }
182
+ )
183
+ },
184
+ String(edge.key)
185
+ )),
186
+ layout.left.map((node) => /* @__PURE__ */ jsx(
187
+ Group,
188
+ {
189
+ onClick: (event) => props.onLeftNodeClick?.(node, event),
190
+ children: props.renderLeftNode ? props.renderLeftNode(node) : /* @__PURE__ */ jsxs(Group, { children: [
191
+ /* @__PURE__ */ jsx(
192
+ GraphNode,
193
+ {
194
+ node,
195
+ style: {
196
+ ...defaultGraphNodeStyle(node),
197
+ ...resolveMarkStyle(node, props.leftNodeStyle)
198
+ }
199
+ }
200
+ ),
201
+ /* @__PURE__ */ jsx(
202
+ GraphLabel,
203
+ {
204
+ label: node.label,
205
+ style: {
206
+ ...defaultGraphLabelStyle(node.label),
207
+ ...resolveSignalValue(props.labelStyle)
208
+ }
209
+ }
210
+ )
211
+ ] })
212
+ },
213
+ `left-${String(node.key)}`
214
+ )),
215
+ layout.right.map((node) => /* @__PURE__ */ jsx(
216
+ Group,
217
+ {
218
+ onClick: (event) => props.onRightNodeClick?.(node, event),
219
+ children: props.renderRightNode ? props.renderRightNode(node) : /* @__PURE__ */ jsxs(Group, { children: [
220
+ /* @__PURE__ */ jsx(
221
+ GraphNode,
222
+ {
223
+ node,
224
+ style: {
225
+ ...defaultGraphNodeStyle(node),
226
+ ...resolveMarkStyle(node, props.rightNodeStyle)
227
+ }
228
+ }
229
+ ),
230
+ /* @__PURE__ */ jsx(
231
+ GraphLabel,
232
+ {
233
+ label: node.label,
234
+ style: {
235
+ ...defaultGraphLabelStyle(node.label),
236
+ ...resolveSignalValue(props.labelStyle)
237
+ }
238
+ }
239
+ )
240
+ ] })
241
+ },
242
+ `right-${String(node.key)}`
243
+ ))
244
+ ] });
245
+ }
246
+ export {
247
+ BipartiteGraph,
248
+ layoutBipartite
249
+ };
250
+ //# sourceMappingURL=bipartite.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/features/viz/lib/graph/bipartite.tsx"],
4
+ "sourcesContent": ["import { Group, SvgPath, resolveSignalValue } from \"@pibbl/core\";\nimport type { PathSegment, PibblNode } from \"@pibbl/core\";\nimport type {\n Accessor,\n BipartiteData,\n BipartiteGraphProps,\n BipartiteLayout,\n BipartiteOptions,\n GraphNodeGeometry,\n Size,\n VizKey,\n} from \"./types.js\";\nimport {\n defaultGraphEdgeStyle,\n defaultGraphLabelStyle,\n defaultGraphNodeStyle,\n GraphLabel,\n GraphNode,\n resolveMarkStyle,\n useGraphFrame,\n} from \"./shared.js\";\n\nfunction access<D, V>(input: Accessor<D, V>, datum: D): V {\n return typeof input === \"function\"\n ? input(datum)\n : (datum as Record<PropertyKey, V>)[input];\n}\nfunction finite(value: number, name: string, zero = false) {\n if (!Number.isFinite(value) || (zero && value < 0))\n throw new RangeError(\n `layoutBipartite: ${name} must be finite${zero ? \" and nonnegative\" : \"\"}.`,\n );\n return value;\n}\nfunction label(\n text: string,\n bounds: { x: number; y: number; width: number; height: number },\n) {\n return Object.freeze({\n text,\n bounds: Object.freeze(bounds),\n rotationDegrees: 0,\n });\n}\nfunction route(a: { x: number; y: number }, b: { x: number; y: number }) {\n const middle = (a.x + b.x) / 2;\n const segments = Object.freeze([\n { type: \"move\" as const, x: a.x, y: a.y },\n {\n type: \"cubic\" as const,\n cp1x: middle,\n cp1y: a.y,\n cp2x: middle,\n cp2y: b.y,\n x: b.x,\n y: b.y,\n },\n ]);\n return Object.freeze({\n sourceAnchor: Object.freeze(a),\n targetAnchor: Object.freeze(b),\n segments,\n arrowSegments: null,\n });\n}\nfunction path(route: { segments: readonly PathSegment[] }) {\n return route.segments\n .map((segment) =>\n segment.type === \"move\"\n ? `M ${segment.x} ${segment.y}`\n : segment.type === \"cubic\"\n ? `C ${segment.cp1x} ${segment.cp1y} ${segment.cp2x} ${segment.cp2y} ${segment.x} ${segment.y}`\n : \"\",\n )\n .join(\" \");\n}\nfunction placed<D>(\n data: readonly D[],\n keyBy: Accessor<D, VizKey>,\n labelBy: Accessor<D, string> | undefined,\n atX: number,\n bounds: { y: number; height: number },\n size: ((datum: D) => Size) | undefined,\n gap: number,\n): readonly GraphNodeGeometry<D>[] {\n const total =\n data.reduce((sum, datum) => sum + (size?.(datum).height ?? 34), 0) +\n Math.max(0, data.length - 1) * gap;\n let y = bounds.y + Math.max(0, (bounds.height - total) / 2);\n const seen = new Set<VizKey>();\n return Object.freeze(\n data.map((datum) => {\n const key = access(keyBy, datum);\n if (seen.has(key))\n throw new Error(\n `layoutBipartite: duplicate node key ${String(key)} on one side.`,\n );\n seen.add(key);\n const dimensions = size?.(datum) ?? { width: 150, height: 34 };\n const box = {\n x: atX,\n y,\n width: dimensions.width,\n height: dimensions.height,\n };\n y += dimensions.height + gap;\n return Object.freeze({\n key,\n datum,\n bounds: Object.freeze(box),\n label: label(labelBy ? access(labelBy, datum) : String(key), box),\n detail: null,\n });\n }),\n );\n}\n\n/** Arranges two explicit entity sets in columns, retaining side-qualified identity.\n * @param graph - Explicit left and right entities with cross-set edges. See {@link BipartiteData}.\n * @param options - Accessors, dimensions, and column spacing. See {@link BipartiteOptions}.\n * @returns Immutable side-aware nodes and routed edges. See {@link BipartiteLayout}.\n */\nexport function layoutBipartite<L, R, E>(\n graph: BipartiteData<L, R, E>,\n options: BipartiteOptions<L, R, E>,\n): BipartiteLayout<L, R, E> {\n const b = options.bounds;\n finite(b.x, \"bounds.x\");\n finite(b.y, \"bounds.y\");\n finite(b.width, \"bounds.width\", true);\n finite(b.height, \"bounds.height\", true);\n const gap = finite(options.nodeGap ?? 12, \"nodeGap\", true),\n columnGap = finite(options.columnGap ?? 120, \"columnGap\", true);\n const leftSize = options.leftSize,\n leftResolver: ((datum: L) => Size) | undefined =\n typeof leftSize === \"function\"\n ? leftSize\n : leftSize === undefined\n ? undefined\n : () => leftSize;\n const rightSize = options.rightSize,\n rightResolver: ((datum: R) => Size) | undefined =\n typeof rightSize === \"function\"\n ? rightSize\n : rightSize === undefined\n ? undefined\n : () => rightSize;\n const left = placed(\n graph.left,\n options.leftKey,\n options.leftLabel,\n b.x,\n b,\n leftResolver,\n gap,\n );\n const rightWidth =\n typeof rightSize === \"function\" ? 150 : (rightSize?.width ?? 150);\n const right = placed(\n graph.right,\n options.rightKey,\n options.rightLabel,\n Math.max(b.x, b.x + b.width - rightWidth),\n b,\n rightResolver,\n gap,\n );\n const leftByKey = new Map(left.map((node) => [node.key, node])),\n rightByKey = new Map(right.map((node) => [node.key, node]));\n const edgeKeys = new Set<VizKey>();\n const edges = graph.edges.map((edge) => {\n const key = access(options.edgeKey, edge);\n if (edgeKeys.has(key))\n throw new Error(`layoutBipartite: duplicate edge key ${String(key)}.`);\n edgeKeys.add(key);\n const source = access(options.source, edge),\n target = access(options.target, edge),\n leftNode = leftByKey.get(source),\n rightNode = rightByKey.get(target);\n if (!leftNode || !rightNode)\n throw new RangeError(\n \"layoutBipartite: every edge must point from a known left key to a known right key.\",\n );\n const r = route(\n {\n x: leftNode.bounds.x + leftNode.bounds.width,\n y: leftNode.bounds.y + leftNode.bounds.height / 2,\n },\n {\n x: rightNode.bounds.x,\n y: rightNode.bounds.y + rightNode.bounds.height / 2,\n },\n );\n return Object.freeze({\n key,\n datum: edge,\n sourceKey: source,\n targetKey: target,\n left: leftNode,\n right: rightNode,\n route: r,\n path: path(r),\n arrowPath: null,\n });\n });\n if (\n left.length &&\n right.length &&\n right[0].bounds.x - (left[0].bounds.x + left[0].bounds.width) < columnGap\n )\n throw new RangeError(\n \"layoutBipartite: bounds are too narrow for node sizes and columnGap.\",\n );\n return Object.freeze({\n bounds: Object.freeze({ ...b }),\n left,\n right,\n edges: Object.freeze(edges),\n });\n}\n\n/** Render left/right entity sets and their cross-set relationships.\n * @param props - Entity data and presentation.\n * @returns Canvas node.\n * @see {@link layoutBipartite}\n */\nexport function BipartiteGraph<L, R, E>(\n props: BipartiteGraphProps<L, R, E>,\n): PibblNode {\n const frame = useGraphFrame(props.style),\n style = frame.style;\n if (!frame.bounds.width || !frame.bounds.height)\n return <Group style={frame.groupStyle}>{null}</Group>;\n const layout = layoutBipartite(resolveSignalValue(props.graph), {\n ...props,\n bounds: frame.bounds,\n columnGap: style.columnGap,\n nodeGap: style.nodeGap,\n });\n return (\n <Group style={frame.groupStyle}>\n {layout.edges.map((edge) => (\n <Group\n key={String(edge.key)}\n onClick={(event) => props.onEdgeClick?.(edge, event)}\n >\n {props.renderEdge ? (\n props.renderEdge(edge)\n ) : (\n <SvgPath\n style={{\n ...defaultGraphEdgeStyle(edge),\n ...resolveMarkStyle(edge, props.edgeStyle),\n d: edge.path,\n }}\n />\n )}\n </Group>\n ))}\n {layout.left.map((node) => (\n <Group\n key={`left-${String(node.key)}`}\n onClick={(event) => props.onLeftNodeClick?.(node, event)}\n >\n {props.renderLeftNode ? (\n props.renderLeftNode(node)\n ) : (\n <Group>\n <GraphNode\n node={node}\n style={{\n ...defaultGraphNodeStyle(node),\n ...resolveMarkStyle(node, props.leftNodeStyle),\n }}\n />\n <GraphLabel\n label={node.label}\n style={{\n ...defaultGraphLabelStyle(node.label),\n ...resolveSignalValue(props.labelStyle),\n }}\n />\n </Group>\n )}\n </Group>\n ))}\n {layout.right.map((node) => (\n <Group\n key={`right-${String(node.key)}`}\n onClick={(event) => props.onRightNodeClick?.(node, event)}\n >\n {props.renderRightNode ? (\n props.renderRightNode(node)\n ) : (\n <Group>\n <GraphNode\n node={node}\n style={{\n ...defaultGraphNodeStyle(node),\n ...resolveMarkStyle(node, props.rightNodeStyle),\n }}\n />\n <GraphLabel\n label={node.label}\n style={{\n ...defaultGraphLabelStyle(node.label),\n ...resolveSignalValue(props.labelStyle),\n }}\n />\n </Group>\n )}\n </Group>\n ))}\n </Group>\n );\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["route"]
7
+ }
@@ -0,0 +1,44 @@
1
+ import type { PibblNode } from "@pibbl/core";
2
+ import type { ChordBandGeometry, ChordData, ChordDiagramProps, ChordLayout, ChordOptions, ChordRibbonGeometry, EdgeStyle, MarkInteraction, Style } from "./types.js";
3
+ /** Computes a directed chord layout, aggregating repeated ordered transfer pairs.
4
+ * @param data - Ordered category transfers. See {@link ChordData}.
5
+ * @param options - Accessors, bounds, angular spacing, and unit. See {@link ChordOptions}.
6
+ * @returns Immutable bands and directed ribbon geometry. See {@link ChordLayout}.
7
+ */
8
+ export declare function layoutChords<C, T>(data: ChordData<C, T>, options: ChordOptions<C, T>): ChordLayout<C, T>;
9
+ /** Default outer-band paint for custom chord compositions.
10
+ * @param _band - Band geometry.
11
+ * @returns Resolved band paint.
12
+ * @see {@link ChordBand}
13
+ */
14
+ export declare function defaultChordBandStyle<C>(_band: ChordBandGeometry<C>): EdgeStyle;
15
+ /** Default directed-ribbon paint for custom chord compositions.
16
+ * @param _ribbon - Ribbon geometry.
17
+ * @returns Resolved ribbon paint.
18
+ * @see {@link ChordRibbon}
19
+ */
20
+ export declare function defaultChordRibbonStyle<T>(_ribbon: ChordRibbonGeometry<T>): EdgeStyle;
21
+ /** Draw one supplied category band.
22
+ * @param argument - Band props.
23
+ * @returns Canvas node.
24
+ * @see {@link ChordBandGeometry}
25
+ */
26
+ export declare function ChordBand<C>({ band, style: input, ...events }: MarkInteraction & {
27
+ readonly band: ChordBandGeometry<C>;
28
+ readonly style?: Style<EdgeStyle>;
29
+ }): PibblNode;
30
+ /** Draw one supplied directed ribbon.
31
+ * @param argument - Ribbon props.
32
+ * @returns Canvas node.
33
+ * @see {@link ChordRibbonGeometry}
34
+ */
35
+ export declare function ChordRibbon<T>({ ribbon, style: input, ...events }: MarkInteraction & {
36
+ readonly ribbon: ChordRibbonGeometry<T>;
37
+ readonly style?: Style<EdgeStyle>;
38
+ }): PibblNode;
39
+ /** Render a directed transfer chord diagram.
40
+ * @param props - Transfer data and presentation.
41
+ * @returns Canvas node.
42
+ * @see {@link layoutChords}
43
+ */
44
+ export declare function ChordDiagram<C, T>(props: ChordDiagramProps<C, T>): PibblNode;
@@ -0,0 +1,348 @@
1
+ import { jsx, jsxs } from "@pibbl/core/jsx-runtime";
2
+ import {
3
+ Group,
4
+ SvgPath,
5
+ resolveSignalValue,
6
+ PathGeometry,
7
+ toSvgPathData
8
+ } from "@pibbl/core";
9
+ import {
10
+ defaultGraphLabelStyle,
11
+ GraphLabel,
12
+ resolveMarkStyle,
13
+ useGraphFrame
14
+ } from "./shared.js";
15
+ function access(input, datum) {
16
+ return typeof input === "function" ? input(datum) : datum[input];
17
+ }
18
+ function finite(value, name, zero = false) {
19
+ if (!Number.isFinite(value) || zero && value < 0)
20
+ throw new RangeError(
21
+ `layoutChords: ${name} must be finite${zero ? " and nonnegative" : ""}.`
22
+ );
23
+ return value;
24
+ }
25
+ function point(cx, cy, radius, degrees) {
26
+ const radians = (degrees - 90) * Math.PI / 180;
27
+ return {
28
+ x: cx + Math.cos(radians) * radius,
29
+ y: cy + Math.sin(radians) * radius
30
+ };
31
+ }
32
+ function svg(segments) {
33
+ const geometry = new PathGeometry();
34
+ geometry.spliceSegments(0, 0, segments);
35
+ return toSvgPathData(geometry);
36
+ }
37
+ function bandSegments(cx, cy, outer, inner, start, end) {
38
+ const first = point(cx, cy, outer, start), last = point(cx, cy, inner, end), radians = Math.PI / 180;
39
+ return Object.freeze([
40
+ { type: "move", ...first },
41
+ {
42
+ type: "arc",
43
+ cx,
44
+ cy,
45
+ ux: outer,
46
+ uy: 0,
47
+ vx: 0,
48
+ vy: outer,
49
+ startAngle: (start - 90) * radians,
50
+ sweep: (end - start) * radians
51
+ },
52
+ { type: "line", ...last },
53
+ {
54
+ type: "arc",
55
+ cx,
56
+ cy,
57
+ ux: inner,
58
+ uy: 0,
59
+ vx: 0,
60
+ vy: inner,
61
+ startAngle: (end - 90) * radians,
62
+ sweep: (start - end) * radians
63
+ },
64
+ { type: "close" }
65
+ ]);
66
+ }
67
+ function layoutChords(data, options) {
68
+ const b = options.bounds;
69
+ finite(b.x, "bounds.x");
70
+ finite(b.y, "bounds.y");
71
+ finite(b.width, "bounds.width", true);
72
+ finite(b.height, "bounds.height", true);
73
+ const width = finite(options.bandWidth ?? 20, "bandWidth", true), pad = finite(options.padAngle ?? 2, "padAngle", true), start = finite(options.startAngle ?? 0, "startAngle");
74
+ if (data.categories.length * pad >= 360 && data.categories.length)
75
+ throw new RangeError(
76
+ "layoutChords: total padAngle must be less than 360 degrees."
77
+ );
78
+ const categories = /* @__PURE__ */ new Map();
79
+ for (const category of data.categories) {
80
+ const key = access(options.categoryKey, category);
81
+ if (categories.has(key))
82
+ throw new Error(`layoutChords: duplicate category key ${String(key)}.`);
83
+ categories.set(key, category);
84
+ }
85
+ const groups = /* @__PURE__ */ new Map();
86
+ const incoming = /* @__PURE__ */ new Map(), outgoing = /* @__PURE__ */ new Map();
87
+ for (const key of categories.keys()) {
88
+ incoming.set(key, 0);
89
+ outgoing.set(key, 0);
90
+ }
91
+ for (const transfer of data.transfers) {
92
+ const source = access(options.source, transfer), target = access(options.target, transfer), amount = finite(access(options.value, transfer), "transfer value", true);
93
+ if (!categories.has(source) || !categories.has(target))
94
+ throw new RangeError(
95
+ "layoutChords: transfer endpoint is not a category key."
96
+ );
97
+ incoming.set(
98
+ target,
99
+ finite(incoming.get(target) + amount, "incoming total", true)
100
+ );
101
+ outgoing.set(
102
+ source,
103
+ finite(outgoing.get(source) + amount, "outgoing total", true)
104
+ );
105
+ const id = `chord:${typeof source}:${String(source)}\0${typeof target}:${String(target)}`;
106
+ const prior = groups.get(id);
107
+ if (prior) {
108
+ prior.records.push(transfer);
109
+ prior.value = finite(prior.value + amount, "transfer total", true);
110
+ } else
111
+ groups.set(id, { source, target, records: [transfer], value: amount });
112
+ }
113
+ const total = Array.from(groups.values()).reduce(
114
+ (sum2, entry) => sum2 + entry.value,
115
+ 0
116
+ );
117
+ const cx = b.x + b.width / 2, cy = b.y + b.height / 2, radius = Math.max(0, Math.min(b.width, b.height) / 2 - 28), inner = Math.max(0, radius - width);
118
+ const weight = Array.from(categories.keys()).map(
119
+ (key) => incoming.get(key) + outgoing.get(key)
120
+ );
121
+ const sum = weight.reduce((a, n) => a + n, 0);
122
+ finite(total, "transfer total", true);
123
+ finite(sum, "incident total", true);
124
+ const usable = 360 - data.categories.length * pad;
125
+ let angle = start;
126
+ const bands = [];
127
+ const arcs = /* @__PURE__ */ new Map();
128
+ for (let index = 0; index < data.categories.length; index++) {
129
+ const datum = data.categories[index], key = access(options.categoryKey, datum), span = sum === 0 ? 0 : weight[index] / sum * usable, arc = Object.freeze({
130
+ center: Object.freeze({ x: cx, y: cy }),
131
+ radius,
132
+ startAngleDegrees: angle,
133
+ endAngleDegrees: angle + span
134
+ });
135
+ const segments = bandSegments(cx, cy, radius, inner, angle, angle + span);
136
+ const mid = angle + span / 2, labelPoint = point(cx, cy, radius + 18, mid);
137
+ const label = Object.freeze({
138
+ text: options.label ? access(options.label, datum) : String(key),
139
+ bounds: Object.freeze({
140
+ x: labelPoint.x - 45,
141
+ y: labelPoint.y - 10,
142
+ width: 90,
143
+ height: 20
144
+ }),
145
+ rotationDegrees: 0
146
+ });
147
+ bands.push(
148
+ Object.freeze({
149
+ key,
150
+ datum,
151
+ incomingValue: incoming.get(key),
152
+ outgoingValue: outgoing.get(key),
153
+ arc,
154
+ innerRadius: inner,
155
+ segments,
156
+ path: svg(segments),
157
+ label
158
+ })
159
+ );
160
+ arcs.set(key, { start: angle, end: angle + span, cursor: angle });
161
+ angle += span + pad;
162
+ }
163
+ const ribbons = [];
164
+ for (const entry of groups.values()) {
165
+ if (entry.value === 0) continue;
166
+ const source = arcs.get(entry.source), target = arcs.get(entry.target);
167
+ const sourceWeight = incoming.get(entry.source) + outgoing.get(entry.source), targetWeight = incoming.get(entry.target) + outgoing.get(entry.target);
168
+ const sourceSpan = sourceWeight === 0 ? 0 : (source.end - source.start) * entry.value / sourceWeight, targetSpan = targetWeight === 0 ? 0 : (target.end - target.start) * entry.value / targetWeight;
169
+ const sourceArc = Object.freeze({
170
+ center: Object.freeze({ x: cx, y: cy }),
171
+ radius: inner,
172
+ startAngleDegrees: source.cursor,
173
+ endAngleDegrees: source.cursor + sourceSpan
174
+ });
175
+ source.cursor += sourceSpan;
176
+ const targetStart = target.cursor;
177
+ const targetArc = Object.freeze({
178
+ center: Object.freeze({ x: cx, y: cy }),
179
+ radius: inner,
180
+ startAngleDegrees: targetStart,
181
+ endAngleDegrees: targetStart + targetSpan
182
+ });
183
+ target.cursor += targetSpan;
184
+ const a = point(cx, cy, inner, sourceArc.startAngleDegrees), d = point(cx, cy, inner, targetArc.startAngleDegrees);
185
+ const segments = Object.freeze([
186
+ { type: "move", ...a },
187
+ {
188
+ type: "arc",
189
+ cx,
190
+ cy,
191
+ ux: inner,
192
+ uy: 0,
193
+ vx: 0,
194
+ vy: inner,
195
+ startAngle: (sourceArc.startAngleDegrees - 90) * Math.PI / 180,
196
+ sweep: (sourceArc.endAngleDegrees - sourceArc.startAngleDegrees) * Math.PI / 180
197
+ },
198
+ {
199
+ type: "quadratic",
200
+ cpx: cx,
201
+ cpy: cy,
202
+ x: d.x,
203
+ y: d.y
204
+ },
205
+ {
206
+ type: "arc",
207
+ cx,
208
+ cy,
209
+ ux: inner,
210
+ uy: 0,
211
+ vx: 0,
212
+ vy: inner,
213
+ startAngle: (targetArc.startAngleDegrees - 90) * Math.PI / 180,
214
+ sweep: (targetArc.endAngleDegrees - targetArc.startAngleDegrees) * Math.PI / 180
215
+ },
216
+ {
217
+ type: "quadratic",
218
+ cpx: cx,
219
+ cpy: cy,
220
+ x: a.x,
221
+ y: a.y
222
+ },
223
+ { type: "close" }
224
+ ]);
225
+ ribbons.push(
226
+ Object.freeze({
227
+ key: `${typeof entry.source}:${String(entry.source)}\0${typeof entry.target}:${String(entry.target)}`,
228
+ sourceKey: entry.source,
229
+ targetKey: entry.target,
230
+ records: Object.freeze(entry.records),
231
+ value: entry.value,
232
+ sourceArc,
233
+ targetArc,
234
+ segments,
235
+ path: svg(segments)
236
+ })
237
+ );
238
+ }
239
+ return Object.freeze({
240
+ bounds: Object.freeze({ ...b }),
241
+ unit: options.unit,
242
+ total,
243
+ bands: Object.freeze(bands),
244
+ ribbons: Object.freeze(ribbons)
245
+ });
246
+ }
247
+ function defaultChordBandStyle(_band) {
248
+ return { fill: "#0f766e" };
249
+ }
250
+ function defaultChordRibbonStyle(_ribbon) {
251
+ return { fill: "rgba(15, 118, 110, 0.3)" };
252
+ }
253
+ function ChordBand({
254
+ band,
255
+ style: input,
256
+ ...events
257
+ }) {
258
+ return /* @__PURE__ */ jsx(
259
+ SvgPath,
260
+ {
261
+ ...events,
262
+ style: { ...resolveSignalValue(input) ?? {}, d: band.path }
263
+ }
264
+ );
265
+ }
266
+ function ChordRibbon({
267
+ ribbon,
268
+ style: input,
269
+ ...events
270
+ }) {
271
+ return /* @__PURE__ */ jsx(
272
+ SvgPath,
273
+ {
274
+ ...events,
275
+ style: { ...resolveSignalValue(input) ?? {}, d: ribbon.path }
276
+ }
277
+ );
278
+ }
279
+ function ChordDiagram(props) {
280
+ const frame = useGraphFrame(props.style), style = frame.style;
281
+ if (!frame.bounds.width || !frame.bounds.height)
282
+ return /* @__PURE__ */ jsx(Group, { style: frame.groupStyle, children: null });
283
+ const layout = layoutChords(resolveSignalValue(props.data), {
284
+ ...props,
285
+ bounds: frame.bounds,
286
+ bandWidth: style.bandWidth,
287
+ padAngle: style.padAngle,
288
+ startAngle: style.startAngle
289
+ });
290
+ return /* @__PURE__ */ jsxs(Group, { style: frame.groupStyle, children: [
291
+ layout.ribbons.map((ribbon) => /* @__PURE__ */ jsx(
292
+ Group,
293
+ {
294
+ onClick: (event) => props.onRibbonClick?.(ribbon, event),
295
+ children: props.renderRibbon ? props.renderRibbon(ribbon) : /* @__PURE__ */ jsx(
296
+ ChordRibbon,
297
+ {
298
+ ribbon,
299
+ keyboardFocusable: Boolean(props.onRibbonClick),
300
+ style: {
301
+ ...defaultChordRibbonStyle(ribbon),
302
+ ...resolveMarkStyle(ribbon, props.ribbonStyle)
303
+ }
304
+ }
305
+ )
306
+ },
307
+ ribbon.key
308
+ )),
309
+ layout.bands.map((band) => /* @__PURE__ */ jsx(
310
+ Group,
311
+ {
312
+ onClick: (event) => props.onBandClick?.(band, event),
313
+ children: props.renderBand ? props.renderBand(band) : /* @__PURE__ */ jsxs(Group, { children: [
314
+ /* @__PURE__ */ jsx(
315
+ ChordBand,
316
+ {
317
+ band,
318
+ style: {
319
+ ...defaultChordBandStyle(band),
320
+ ...resolveMarkStyle(band, props.bandStyle)
321
+ }
322
+ }
323
+ ),
324
+ /* @__PURE__ */ jsx(
325
+ GraphLabel,
326
+ {
327
+ label: band.label,
328
+ style: {
329
+ ...defaultGraphLabelStyle(band.label),
330
+ ...resolveSignalValue(props.labelStyle)
331
+ }
332
+ }
333
+ )
334
+ ] })
335
+ },
336
+ String(band.key)
337
+ ))
338
+ ] });
339
+ }
340
+ export {
341
+ ChordBand,
342
+ ChordDiagram,
343
+ ChordRibbon,
344
+ defaultChordBandStyle,
345
+ defaultChordRibbonStyle,
346
+ layoutChords
347
+ };
348
+ //# sourceMappingURL=chord.js.map