@vielzeug/prism 26.10.14 → 26.10.16

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 (162) hide show
  1. package/dist/_dev.cjs.map +1 -1
  2. package/dist/_dev.js +6 -1
  3. package/dist/_dev.js.map +1 -1
  4. package/dist/_tappers.cjs.map +1 -1
  5. package/dist/_tappers.js +25 -1
  6. package/dist/_tappers.js.map +1 -1
  7. package/dist/animation/easing.cjs.map +1 -1
  8. package/dist/animation/easing.js +15 -1
  9. package/dist/animation/easing.js.map +1 -1
  10. package/dist/animation/motion.cjs.map +1 -1
  11. package/dist/animation/motion.js +15 -1
  12. package/dist/animation/motion.js.map +1 -1
  13. package/dist/animation/reveal.cjs.map +1 -1
  14. package/dist/animation/reveal.js +97 -1
  15. package/dist/animation/reveal.js.map +1 -1
  16. package/dist/animation/transition.cjs.map +1 -1
  17. package/dist/animation/transition.js +39 -1
  18. package/dist/animation/transition.js.map +1 -1
  19. package/dist/animation/tween.cjs.map +1 -1
  20. package/dist/animation/tween.js +7 -1
  21. package/dist/animation/tween.js.map +1 -1
  22. package/dist/axes/axis.cjs.map +1 -1
  23. package/dist/axes/axis.js +76 -1
  24. package/dist/axes/axis.js.map +1 -1
  25. package/dist/axes/grid.cjs.map +1 -1
  26. package/dist/axes/grid.js +29 -1
  27. package/dist/axes/grid.js.map +1 -1
  28. package/dist/axes/scale-utils.cjs.map +1 -1
  29. package/dist/axes/scale-utils.js +10 -1
  30. package/dist/axes/scale-utils.js.map +1 -1
  31. package/dist/charts/area/area-chart.cjs.map +1 -1
  32. package/dist/charts/area/area-chart.js +71 -1
  33. package/dist/charts/area/area-chart.js.map +1 -1
  34. package/dist/charts/area/area-renderer.cjs.map +1 -1
  35. package/dist/charts/area/area-renderer.js +128 -1
  36. package/dist/charts/area/area-renderer.js.map +1 -1
  37. package/dist/charts/bar/bar-chart.cjs.map +1 -1
  38. package/dist/charts/bar/bar-chart.js +228 -1
  39. package/dist/charts/bar/bar-chart.js.map +1 -1
  40. package/dist/charts/bar/bar-hit-test.cjs.map +1 -1
  41. package/dist/charts/bar/bar-hit-test.js +25 -1
  42. package/dist/charts/bar/bar-hit-test.js.map +1 -1
  43. package/dist/charts/bar/bar-renderer.cjs.map +1 -1
  44. package/dist/charts/bar/bar-renderer.js +139 -1
  45. package/dist/charts/bar/bar-renderer.js.map +1 -1
  46. package/dist/charts/line/line-chart.cjs.map +1 -1
  47. package/dist/charts/line/line-chart.js +93 -1
  48. package/dist/charts/line/line-chart.js.map +1 -1
  49. package/dist/charts/line/line-renderer.cjs.map +1 -1
  50. package/dist/charts/line/line-renderer.js +143 -1
  51. package/dist/charts/line/line-renderer.js.map +1 -1
  52. package/dist/charts/pie/pie-chart.cjs +1 -1
  53. package/dist/charts/pie/pie-chart.cjs.map +1 -1
  54. package/dist/charts/pie/pie-chart.js +207 -1
  55. package/dist/charts/pie/pie-chart.js.map +1 -1
  56. package/dist/charts/pie/pie-renderer.cjs.map +1 -1
  57. package/dist/charts/pie/pie-renderer.js +68 -1
  58. package/dist/charts/pie/pie-renderer.js.map +1 -1
  59. package/dist/charts/radar/radar-chart.cjs +1 -1
  60. package/dist/charts/radar/radar-chart.cjs.map +1 -1
  61. package/dist/charts/radar/radar-chart.js +281 -1
  62. package/dist/charts/radar/radar-chart.js.map +1 -1
  63. package/dist/charts/radar/radar-geometry.cjs.map +1 -1
  64. package/dist/charts/radar/radar-geometry.js +69 -1
  65. package/dist/charts/radar/radar-geometry.js.map +1 -1
  66. package/dist/charts/scatter/scatter-chart.cjs.map +1 -1
  67. package/dist/charts/scatter/scatter-chart.js +69 -1
  68. package/dist/charts/scatter/scatter-chart.js.map +1 -1
  69. package/dist/charts/scatter/scatter-renderer.cjs.map +1 -1
  70. package/dist/charts/scatter/scatter-renderer.js +57 -1
  71. package/dist/charts/scatter/scatter-renderer.js.map +1 -1
  72. package/dist/charts/sparkline/sparkline.cjs +1 -1
  73. package/dist/charts/sparkline/sparkline.cjs.map +1 -1
  74. package/dist/charts/sparkline/sparkline.js +251 -1
  75. package/dist/charts/sparkline/sparkline.js.map +1 -1
  76. package/dist/core/cartesian-model.cjs +1 -1
  77. package/dist/core/cartesian-model.cjs.map +1 -1
  78. package/dist/core/cartesian-model.js +26 -1
  79. package/dist/core/cartesian-model.js.map +1 -1
  80. package/dist/core/cartesian-scales.cjs.map +1 -1
  81. package/dist/core/cartesian-scales.js +38 -1
  82. package/dist/core/cartesian-scales.js.map +1 -1
  83. package/dist/core/chart-base.cjs.map +1 -1
  84. package/dist/core/chart-base.js +62 -1
  85. package/dist/core/chart-base.js.map +1 -1
  86. package/dist/core/chart-scaffold.cjs.map +1 -1
  87. package/dist/core/chart-scaffold.js +103 -1
  88. package/dist/core/chart-scaffold.js.map +1 -1
  89. package/dist/core/datum-style.cjs +1 -1
  90. package/dist/core/datum-style.cjs.map +1 -1
  91. package/dist/core/datum-style.js +22 -1
  92. package/dist/core/datum-style.js.map +1 -1
  93. package/dist/core/ids.cjs.map +1 -1
  94. package/dist/core/ids.js +8 -1
  95. package/dist/core/ids.js.map +1 -1
  96. package/dist/core/layout.cjs.map +1 -1
  97. package/dist/core/layout.js +22 -1
  98. package/dist/core/layout.js.map +1 -1
  99. package/dist/core/polar.cjs.map +1 -1
  100. package/dist/core/polar.js +13 -1
  101. package/dist/core/polar.js.map +1 -1
  102. package/dist/core/responsive.cjs.map +1 -1
  103. package/dist/core/responsive.js +20 -1
  104. package/dist/core/responsive.js.map +1 -1
  105. package/dist/core/series-id.cjs.map +1 -1
  106. package/dist/core/series-id.js +7 -1
  107. package/dist/core/series-id.js.map +1 -1
  108. package/dist/errors.cjs.map +1 -1
  109. package/dist/errors.js +9 -1
  110. package/dist/errors.js.map +1 -1
  111. package/dist/index.js +13 -1
  112. package/dist/interaction/announcer.cjs.map +1 -1
  113. package/dist/interaction/announcer.js +25 -1
  114. package/dist/interaction/announcer.js.map +1 -1
  115. package/dist/interaction/crosshair.cjs.map +1 -1
  116. package/dist/interaction/crosshair.js +37 -1
  117. package/dist/interaction/crosshair.js.map +1 -1
  118. package/dist/interaction/events.cjs.map +1 -1
  119. package/dist/interaction/events.js +11 -1
  120. package/dist/interaction/events.js.map +1 -1
  121. package/dist/interaction/legend.cjs.map +1 -1
  122. package/dist/interaction/legend.js +31 -1
  123. package/dist/interaction/legend.js.map +1 -1
  124. package/dist/interaction/scatter-interaction.cjs.map +1 -1
  125. package/dist/interaction/scatter-interaction.js +105 -1
  126. package/dist/interaction/scatter-interaction.js.map +1 -1
  127. package/dist/interaction/series-interaction.cjs.map +1 -1
  128. package/dist/interaction/series-interaction.js +163 -1
  129. package/dist/interaction/series-interaction.js.map +1 -1
  130. package/dist/interaction/tooltip.cjs +1 -1
  131. package/dist/interaction/tooltip.cjs.map +1 -1
  132. package/dist/interaction/tooltip.js +87 -1
  133. package/dist/interaction/tooltip.js.map +1 -1
  134. package/dist/prism.cjs +1 -1
  135. package/dist/prism.cjs.map +1 -1
  136. package/dist/prism.iife.js +1 -1
  137. package/dist/prism.iife.js.map +1 -1
  138. package/dist/prism.js +2930 -1
  139. package/dist/prism.js.map +1 -1
  140. package/dist/scales/band.cjs.map +1 -1
  141. package/dist/scales/band.js +39 -1
  142. package/dist/scales/band.js.map +1 -1
  143. package/dist/scales/linear.cjs.map +1 -1
  144. package/dist/scales/linear.js +43 -1
  145. package/dist/scales/linear.js.map +1 -1
  146. package/dist/scales/time.cjs.map +1 -1
  147. package/dist/scales/time.js +61 -1
  148. package/dist/scales/time.js.map +1 -1
  149. package/dist/svg/element.cjs +1 -1
  150. package/dist/svg/element.cjs.map +1 -1
  151. package/dist/svg/element.js +16 -1
  152. package/dist/svg/element.js.map +1 -1
  153. package/dist/svg/path.cjs.map +1 -1
  154. package/dist/svg/path.js +48 -1
  155. package/dist/svg/path.js.map +1 -1
  156. package/dist/svg/text.cjs.map +1 -1
  157. package/dist/svg/text.js +13 -1
  158. package/dist/svg/text.js.map +1 -1
  159. package/dist/theme/index.cjs.map +1 -1
  160. package/dist/theme/index.js +37 -1
  161. package/dist/theme/index.js.map +1 -1
  162. package/package.json +5 -5
@@ -1,2 +1,70 @@
1
- import{estimateTextWidth as e}from"../../svg/text.js";import{linearScale as t}from"../../scales/linear.js";import{polarX as n,polarY as r}from"../../core/polar.js";var i=2*Math.PI;function toRadians(e){return e*Math.PI/180}function axisAngles(e,t=0){return Array.from({length:e},(n,r)=>t+r*i/e)}function resolveAxisDomains(e,n,r){let i=r;if(!i){let e=n.flatMap(e=>e.data.map(e=>e.value)).filter(Number.isFinite),r=Math.min(0,...e),a=e.length?Math.max(...e):1;i=t({domain:[r,a>r?a:r+1],range:[0,1]}).domain}return e.map(e=>[e.min??i[0],e.max??i[1]])}function normalize(e,[t,n]){return n===t?0:Math.max(0,Math.min(1,(e-t)/(n-t)))}function radarPoints(e,t,i,a,o){return e.map((e,s)=>({x:n(t,a*e,o[s]),y:r(i,a*e,o[s])}))}function closedPath(e,t=`linear`){let n=e.length;if(n===0)return``;let[r]=e;if(t===`linear`||n<3)return`M${r.x},${r.y}${e.slice(1).map(e=>`L${e.x},${e.y}`).join(``)}Z`;let i=`M${r.x},${r.y}`;for(let t=0;t<n;t++){let r=e[(t-1+n)%n],a=e[t],o=e[(t+1)%n],s=e[(t+2)%n];i+=`C${a.x+(o.x-r.x)/6},${a.y+(o.y-r.y)/6} ${o.x-(s.x-a.x)/6},${o.y-(s.y-a.y)/6} ${o.x},${o.y}`}return`${i}Z`}function ringPath(e,t,n,r,i){return r<=0?``:e===`circle`?`M${t},${n-r}A${r},${r} 0 1 1 ${t},${n+r}A${r},${r} 0 1 1 ${t},${n-r}Z`:closedPath(radarPoints(i.map(()=>1),t,n,r,i))}function labelPlacement(e){let t=Math.sin(e),n=Math.cos(e);return{anchor:Math.abs(t)<.1?`middle`:t>0?`start`:`end`,baseline:n>.9?`auto`:n<-.9?`hanging`:`middle`}}function fitRadius(t,n,r,i,a,o){let s=0;r.forEach((t,n)=>{labelPlacement(i[n]).anchor!==`middle`&&(s=Math.max(s,e(t,a)))});let c=a*1.3;return Math.max(8,Math.min(t/2-o-s,n/2-o-c))}function nearestAxis(e,t,n,r=0){if(n===0)return-1;let a=i/n,o=((Math.atan2(e,-t)-r)%i+i)%i;return Math.round(o/a)%n}export{axisAngles,closedPath,fitRadius,labelPlacement,nearestAxis,normalize,radarPoints,resolveAxisDomains,ringPath,toRadians};
1
+ import { estimateTextWidth as e } from "../../svg/text.js";
2
+ import { linearScale as t } from "../../scales/linear.js";
3
+ import { polarX as n, polarY as r } from "../../core/polar.js";
4
+ //#region src/charts/radar/radar-geometry.ts
5
+ var i = 2 * Math.PI;
6
+ function toRadians(e) {
7
+ return e * Math.PI / 180;
8
+ }
9
+ function axisAngles(e, t = 0) {
10
+ return Array.from({ length: e }, (n, r) => t + r * i / e);
11
+ }
12
+ function resolveAxisDomains(e, n, r) {
13
+ let i = r;
14
+ if (!i) {
15
+ let e = n.flatMap((e) => e.data.map((e) => e.value)).filter(Number.isFinite), r = Math.min(0, ...e), a = e.length ? Math.max(...e) : 1;
16
+ i = t({
17
+ domain: [r, a > r ? a : r + 1],
18
+ range: [0, 1]
19
+ }).domain;
20
+ }
21
+ return e.map((e) => [e.min ?? i[0], e.max ?? i[1]]);
22
+ }
23
+ function normalize(e, [t, n]) {
24
+ return n === t ? 0 : Math.max(0, Math.min(1, (e - t) / (n - t)));
25
+ }
26
+ function radarPoints(e, t, i, a, o) {
27
+ return e.map((e, s) => ({
28
+ x: n(t, a * e, o[s]),
29
+ y: r(i, a * e, o[s])
30
+ }));
31
+ }
32
+ function closedPath(e, t = "linear") {
33
+ let n = e.length;
34
+ if (n === 0) return "";
35
+ let [r] = e;
36
+ if (t === "linear" || n < 3) return `M${r.x},${r.y}${e.slice(1).map((e) => `L${e.x},${e.y}`).join("")}Z`;
37
+ let i = `M${r.x},${r.y}`;
38
+ for (let t = 0; t < n; t++) {
39
+ let r = e[(t - 1 + n) % n], a = e[t], o = e[(t + 1) % n], s = e[(t + 2) % n];
40
+ i += `C${a.x + (o.x - r.x) / 6},${a.y + (o.y - r.y) / 6} ${o.x - (s.x - a.x) / 6},${o.y - (s.y - a.y) / 6} ${o.x},${o.y}`;
41
+ }
42
+ return `${i}Z`;
43
+ }
44
+ function ringPath(e, t, n, r, i) {
45
+ return r <= 0 ? "" : e === "circle" ? `M${t},${n - r}A${r},${r} 0 1 1 ${t},${n + r}A${r},${r} 0 1 1 ${t},${n - r}Z` : closedPath(radarPoints(i.map(() => 1), t, n, r, i));
46
+ }
47
+ function labelPlacement(e) {
48
+ let t = Math.sin(e), n = Math.cos(e);
49
+ return {
50
+ anchor: Math.abs(t) < .1 ? "middle" : t > 0 ? "start" : "end",
51
+ baseline: n > .9 ? "auto" : n < -.9 ? "hanging" : "middle"
52
+ };
53
+ }
54
+ function fitRadius(t, n, r, i, a, o) {
55
+ let s = 0;
56
+ r.forEach((t, n) => {
57
+ labelPlacement(i[n]).anchor !== "middle" && (s = Math.max(s, e(t, a)));
58
+ });
59
+ let c = a * 1.3;
60
+ return Math.max(8, Math.min(t / 2 - o - s, n / 2 - o - c));
61
+ }
62
+ function nearestAxis(e, t, n, r = 0) {
63
+ if (n === 0) return -1;
64
+ let a = i / n, o = ((Math.atan2(e, -t) - r) % i + i) % i;
65
+ return Math.round(o / a) % n;
66
+ }
67
+ //#endregion
68
+ export { axisAngles, closedPath, fitRadius, labelPlacement, nearestAxis, normalize, radarPoints, resolveAxisDomains, ringPath, toRadians };
69
+
2
70
  //# sourceMappingURL=radar-geometry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"radar-geometry.js","names":[],"sources":["../../../src/charts/radar/radar-geometry.ts"],"sourcesContent":["import { polarX, polarY } from '../../core/polar';\nimport { linearScale } from '../../scales/linear';\nimport type { Point } from '../../svg/path';\nimport { estimateTextWidth } from '../../svg/text';\nimport type { RadarAxisConfig, RadarSeriesConfig } from '../../types';\n\nconst TWO_PI = 2 * Math.PI;\n\nexport type LabelAnchor = 'end' | 'middle' | 'start';\nexport type LabelBaseline = 'auto' | 'hanging' | 'middle';\n\nexport function toRadians(degrees: number): number {\n return (degrees * Math.PI) / 180;\n}\n\nexport function axisAngles(count: number, startAngle = 0): number[] {\n return Array.from({ length: count }, (_, i) => startAngle + (i * TWO_PI) / count);\n}\n\n/** Per-axis `[min, max]`: axis overrides win over `domain`, which wins over a nice range around the data. */\nexport function resolveAxisDomains(\n axes: readonly RadarAxisConfig[],\n series: readonly RadarSeriesConfig[],\n domain?: [number, number],\n): [number, number][] {\n let shared = domain;\n\n if (!shared) {\n const values = series.flatMap((s) => s.data.map((d) => d.value)).filter(Number.isFinite);\n const min = Math.min(0, ...values);\n const max = values.length ? Math.max(...values) : 1;\n\n shared = linearScale({ domain: [min, max > min ? max : min + 1], range: [0, 1] }).domain as [number, number];\n }\n\n return axes.map((axis) => [axis.min ?? shared[0], axis.max ?? shared[1]]);\n}\n\nexport function normalize(value: number, [min, max]: readonly [number, number]): number {\n if (max === min) return 0;\n\n return Math.max(0, Math.min(1, (value - min) / (max - min)));\n}\n\nexport function radarPoints(\n fractions: readonly number[],\n cx: number,\n cy: number,\n radius: number,\n angles: readonly number[],\n): Point[] {\n return fractions.map((f, i) => ({ x: polarX(cx, radius * f, angles[i]), y: polarY(cy, radius * f, angles[i]) }));\n}\n\n/** Closed outline through every point; `rounded` uses a closed Catmull–Rom spline. */\nexport function closedPath(points: readonly Point[], curve: 'linear' | 'rounded' = 'linear'): string {\n const n = points.length;\n\n if (n === 0) return '';\n\n const [first] = points;\n\n if (curve === 'linear' || n < 3) {\n return `M${first.x},${first.y}${points\n .slice(1)\n .map((p) => `L${p.x},${p.y}`)\n .join('')}Z`;\n }\n\n let d = `M${first.x},${first.y}`;\n\n for (let i = 0; i < n; i++) {\n const p0 = points[(i - 1 + n) % n];\n const p1 = points[i];\n const p2 = points[(i + 1) % n];\n const p3 = points[(i + 2) % n];\n\n d += `C${p1.x + (p2.x - p0.x) / 6},${p1.y + (p2.y - p0.y) / 6} ${p2.x - (p3.x - p1.x) / 6},${p2.y - (p3.y - p1.y) / 6} ${p2.x},${p2.y}`;\n }\n\n return `${d}Z`;\n}\n\nexport function ringPath(\n shape: 'circle' | 'polygon',\n cx: number,\n cy: number,\n r: number,\n angles: readonly number[],\n): string {\n if (r <= 0) return '';\n\n if (shape === 'circle') return `M${cx},${cy - r}A${r},${r} 0 1 1 ${cx},${cy + r}A${r},${r} 0 1 1 ${cx},${cy - r}Z`;\n\n return closedPath(\n radarPoints(\n angles.map(() => 1),\n cx,\n cy,\n r,\n angles,\n ),\n );\n}\n\nexport function labelPlacement(angle: number): { anchor: LabelAnchor; baseline: LabelBaseline } {\n const sin = Math.sin(angle);\n const cos = Math.cos(angle);\n\n return {\n anchor: Math.abs(sin) < 0.1 ? 'middle' : sin > 0 ? 'start' : 'end',\n baseline: cos > 0.9 ? 'auto' : cos < -0.9 ? 'hanging' : 'middle',\n };\n}\n\n/** Largest radius that leaves room for the axis labels around it. */\nexport function fitRadius(\n width: number,\n height: number,\n labels: readonly string[],\n angles: readonly number[],\n fontSize: number,\n gap: number,\n): number {\n let side = 0;\n\n labels.forEach((label, i) => {\n if (labelPlacement(angles[i]).anchor !== 'middle') side = Math.max(side, estimateTextWidth(label, fontSize));\n });\n\n const lineHeight = fontSize * 1.3;\n\n return Math.max(8, Math.min(width / 2 - gap - side, height / 2 - gap - lineHeight));\n}\n\n/** Index of the axis closest in angle to the offset `(dx, dy)` from the centre. */\nexport function nearestAxis(dx: number, dy: number, count: number, startAngle = 0): number {\n if (count === 0) return -1;\n\n const step = TWO_PI / count;\n const angle = (((Math.atan2(dx, -dy) - startAngle) % TWO_PI) + TWO_PI) % TWO_PI;\n\n return Math.round(angle / step) % count;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"radar-geometry.js","names":["TWO_PI","degrees","count","startAngle","i","shared","domain","values","series","s","d","min","max","linearScale","axes","axis","value","fractions","polarX","cx","radius","f","angles","polarY","cy","points","first","curve","p","p0","p1","p2","p3","shape","sin","angle","cos","side","estimateTextWidth","label","fontSize","lineHeight","width","gap","height","step","dx","dy"],"sources":["../../../src/charts/radar/radar-geometry.ts"],"sourcesContent":["import { polarX, polarY } from '../../core/polar';\nimport { linearScale } from '../../scales/linear';\nimport type { Point } from '../../svg/path';\nimport { estimateTextWidth } from '../../svg/text';\nimport type { RadarAxisConfig, RadarSeriesConfig } from '../../types';\n\nconst TWO_PI = 2 * Math.PI;\n\nexport type LabelAnchor = 'end' | 'middle' | 'start';\nexport type LabelBaseline = 'auto' | 'hanging' | 'middle';\n\nexport function toRadians(degrees: number): number {\n return (degrees * Math.PI) / 180;\n}\n\nexport function axisAngles(count: number, startAngle = 0): number[] {\n return Array.from({ length: count }, (_, i) => startAngle + (i * TWO_PI) / count);\n}\n\n/** Per-axis `[min, max]`: axis overrides win over `domain`, which wins over a nice range around the data. */\nexport function resolveAxisDomains(\n axes: readonly RadarAxisConfig[],\n series: readonly RadarSeriesConfig[],\n domain?: [number, number],\n): [number, number][] {\n let shared = domain;\n\n if (!shared) {\n const values = series.flatMap((s) => s.data.map((d) => d.value)).filter(Number.isFinite);\n const min = Math.min(0, ...values);\n const max = values.length ? Math.max(...values) : 1;\n\n shared = linearScale({ domain: [min, max > min ? max : min + 1], range: [0, 1] }).domain as [number, number];\n }\n\n return axes.map((axis) => [axis.min ?? shared[0], axis.max ?? shared[1]]);\n}\n\nexport function normalize(value: number, [min, max]: readonly [number, number]): number {\n if (max === min) return 0;\n\n return Math.max(0, Math.min(1, (value - min) / (max - min)));\n}\n\nexport function radarPoints(\n fractions: readonly number[],\n cx: number,\n cy: number,\n radius: number,\n angles: readonly number[],\n): Point[] {\n return fractions.map((f, i) => ({ x: polarX(cx, radius * f, angles[i]), y: polarY(cy, radius * f, angles[i]) }));\n}\n\n/** Closed outline through every point; `rounded` uses a closed Catmull–Rom spline. */\nexport function closedPath(points: readonly Point[], curve: 'linear' | 'rounded' = 'linear'): string {\n const n = points.length;\n\n if (n === 0) return '';\n\n const [first] = points;\n\n if (curve === 'linear' || n < 3) {\n return `M${first.x},${first.y}${points\n .slice(1)\n .map((p) => `L${p.x},${p.y}`)\n .join('')}Z`;\n }\n\n let d = `M${first.x},${first.y}`;\n\n for (let i = 0; i < n; i++) {\n const p0 = points[(i - 1 + n) % n];\n const p1 = points[i];\n const p2 = points[(i + 1) % n];\n const p3 = points[(i + 2) % n];\n\n d += `C${p1.x + (p2.x - p0.x) / 6},${p1.y + (p2.y - p0.y) / 6} ${p2.x - (p3.x - p1.x) / 6},${p2.y - (p3.y - p1.y) / 6} ${p2.x},${p2.y}`;\n }\n\n return `${d}Z`;\n}\n\nexport function ringPath(\n shape: 'circle' | 'polygon',\n cx: number,\n cy: number,\n r: number,\n angles: readonly number[],\n): string {\n if (r <= 0) return '';\n\n if (shape === 'circle') return `M${cx},${cy - r}A${r},${r} 0 1 1 ${cx},${cy + r}A${r},${r} 0 1 1 ${cx},${cy - r}Z`;\n\n return closedPath(\n radarPoints(\n angles.map(() => 1),\n cx,\n cy,\n r,\n angles,\n ),\n );\n}\n\nexport function labelPlacement(angle: number): { anchor: LabelAnchor; baseline: LabelBaseline } {\n const sin = Math.sin(angle);\n const cos = Math.cos(angle);\n\n return {\n anchor: Math.abs(sin) < 0.1 ? 'middle' : sin > 0 ? 'start' : 'end',\n baseline: cos > 0.9 ? 'auto' : cos < -0.9 ? 'hanging' : 'middle',\n };\n}\n\n/** Largest radius that leaves room for the axis labels around it. */\nexport function fitRadius(\n width: number,\n height: number,\n labels: readonly string[],\n angles: readonly number[],\n fontSize: number,\n gap: number,\n): number {\n let side = 0;\n\n labels.forEach((label, i) => {\n if (labelPlacement(angles[i]).anchor !== 'middle') side = Math.max(side, estimateTextWidth(label, fontSize));\n });\n\n const lineHeight = fontSize * 1.3;\n\n return Math.max(8, Math.min(width / 2 - gap - side, height / 2 - gap - lineHeight));\n}\n\n/** Index of the axis closest in angle to the offset `(dx, dy)` from the centre. */\nexport function nearestAxis(dx: number, dy: number, count: number, startAngle = 0): number {\n if (count === 0) return -1;\n\n const step = TWO_PI / count;\n const angle = (((Math.atan2(dx, -dy) - startAngle) % TWO_PI) + TWO_PI) % TWO_PI;\n\n return Math.round(angle / step) % count;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"scatter-chart.cjs","names":[],"sources":["../../../src/charts/scatter/scatter-chart.ts"],"sourcesContent":["import { positionAxis, renderAxis, resolveTickCount, resolveTicks } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { buildXScale, buildYScale } from '../../core/cartesian-scales';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createScatterInteraction } from '../../interaction/scatter-interaction';\nimport { ensureMarkerGroup } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, ScatterChartConfig, ScatterSeriesConfig, XAxisConfig, YAxisConfig } from '../../types';\nimport { computeScatterPoints, renderScatterPoints } from './scatter-renderer';\n\nexport function createScatterChart(\n container: HTMLElement,\n config: ScatterChartConfig,\n): ChartHandle<ScatterSeriesConfig[]> {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n let markers: SVGGElement | null = null;\n let seriesList = config.series;\n\n return createChartScaffold(\n container,\n config,\n (ctx, reason) => {\n const { groups, legend, tooltip } = ctx;\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n const dims = ctx.dimensions;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const allData = seriesList.map((series) => series.data);\n const allX = allData.flat().map((datum) => datum.key);\n const allY = allData.flat().map((datum) => datum.value);\n\n if (allX.length === 0) {\n clearCartesianDom(groups, legend, tooltip, crosshair);\n markers?.replaceChildren();\n\n return;\n }\n\n if (config.crosshair && !crosshair) {\n crosshair = createCrosshair(ctx.chartArea, config.crosshair);\n }\n\n const xScale = buildXScale(allX, area.width);\n // Independent points have no baseline to anchor, so the y domain fits the data.\n const yScale = buildYScale(allY, area.height, false);\n\n // Axes render by default (value axis with gridlines); `false` opts out. The value\n // axis merges over its default so a partial config keeps the default gridlines.\n const xAxisConfig: XAxisConfig | false = config.xAxis === false ? false : (config.xAxis ?? {});\n const yAxisConfig: YAxisConfig | false = config.yAxis === false ? false : { grid: true, ...config.yAxis };\n\n if (yAxisConfig && yAxisConfig.grid) {\n renderGrid(\n groups.grid,\n yScale,\n yAxisConfig.grid,\n area.width,\n 'horizontal',\n resolveTicks(yScale, yAxisConfig, resolveTickCount(yAxisConfig, area.height, 'left')),\n );\n } else {\n groups.grid.replaceChildren();\n }\n\n if (xAxisConfig && xAxisConfig.grid) {\n renderGrid(\n groups.grid,\n xScale,\n xAxisConfig.grid,\n area.height,\n 'vertical',\n resolveTicks(xScale, xAxisConfig, resolveTickCount(xAxisConfig, area.width, 'bottom')),\n );\n }\n\n if (xAxisConfig) {\n positionAxis(groups.xAxis, xAxisConfig.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, xScale, xAxisConfig, area.width, 'bottom');\n } else {\n groups.xAxis.replaceChildren();\n }\n\n if (yAxisConfig) {\n positionAxis(groups.yAxis, yAxisConfig.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, yScale, yAxisConfig, area.height, 'left');\n } else {\n groups.yAxis.replaceChildren();\n }\n\n while (groups.series.children.length > seriesList.length) {\n groups.series.removeChild(groups.series.lastChild!);\n }\n\n const allPoints: Point[][] = [];\n\n for (const [i, series] of seriesList.entries()) {\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-scatter-series' });\n groups.series.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const points = computeScatterPoints(series.data, xScale, yScale);\n\n allPoints.push(points);\n\n renderScatterPoints(group, points, {\n color: seriesColor(i, series.color),\n disposalSignal: ctx.disposalSignal,\n marks: series.data,\n pointRadius: series.pointRadius ?? 3,\n transition: reason === 'resize' ? false : config.transition,\n });\n }\n\n tooltip?.hide();\n markers = ensureMarkerGroup(ctx.chartArea, markers);\n\n return createScatterInteraction({\n announcer: ctx.announcer,\n colors: () => seriesList.map((s, i) => seriesColor(i, s.color)),\n crosshair,\n dims: () => ctx.dimensions,\n getData: () => allData,\n getPoints: () => allPoints,\n getSeriesList: () => seriesList,\n margin: dims.margin,\n markers,\n onClick: config.onClick,\n onHover: config.onHover,\n seriesGroup: groups.series,\n svg: ctx.svg,\n tooltip,\n tooltipFormat: typeof config.tooltip === 'object' ? config.tooltip : undefined,\n });\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"scatter-chart.cjs","names":["createChartScaffold","seriesColor","chartArea","createCrosshair","buildXScale","buildYScale","resolveTicks","resolveTickCount","createSvgElement","seriesDomId","computeScatterPoints","ensureMarkerGroup","createScatterInteraction","require_element","require_axis","require_grid","require_cartesian_scales","require_layout","require_chart_scaffold","require_series_id","require_crosshair","require_series_interaction","require_index","require_scatter_interaction","require_scatter_renderer","crosshair","markers","seriesList","config","container","ctx","legend","i","s","dims","area","allData","series","allX","datum","allY","groups","tooltip","xScale","yScale","xAxisConfig","yAxisConfig","allPoints","group","points","reason","data"],"sources":["../../../src/charts/scatter/scatter-chart.ts"],"sourcesContent":["import { positionAxis, renderAxis, resolveTickCount, resolveTicks } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { buildXScale, buildYScale } from '../../core/cartesian-scales';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createScatterInteraction } from '../../interaction/scatter-interaction';\nimport { ensureMarkerGroup } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, ScatterChartConfig, ScatterSeriesConfig, XAxisConfig, YAxisConfig } from '../../types';\nimport { computeScatterPoints, renderScatterPoints } from './scatter-renderer';\n\nexport function createScatterChart(\n container: HTMLElement,\n config: ScatterChartConfig,\n): ChartHandle<ScatterSeriesConfig[]> {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n let markers: SVGGElement | null = null;\n let seriesList = config.series;\n\n return createChartScaffold(\n container,\n config,\n (ctx, reason) => {\n const { groups, legend, tooltip } = ctx;\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n const dims = ctx.dimensions;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const allData = seriesList.map((series) => series.data);\n const allX = allData.flat().map((datum) => datum.key);\n const allY = allData.flat().map((datum) => datum.value);\n\n if (allX.length === 0) {\n clearCartesianDom(groups, legend, tooltip, crosshair);\n markers?.replaceChildren();\n\n return;\n }\n\n if (config.crosshair && !crosshair) {\n crosshair = createCrosshair(ctx.chartArea, config.crosshair);\n }\n\n const xScale = buildXScale(allX, area.width);\n // Independent points have no baseline to anchor, so the y domain fits the data.\n const yScale = buildYScale(allY, area.height, false);\n\n // Axes render by default (value axis with gridlines); `false` opts out. The value\n // axis merges over its default so a partial config keeps the default gridlines.\n const xAxisConfig: XAxisConfig | false = config.xAxis === false ? false : (config.xAxis ?? {});\n const yAxisConfig: YAxisConfig | false = config.yAxis === false ? false : { grid: true, ...config.yAxis };\n\n if (yAxisConfig && yAxisConfig.grid) {\n renderGrid(\n groups.grid,\n yScale,\n yAxisConfig.grid,\n area.width,\n 'horizontal',\n resolveTicks(yScale, yAxisConfig, resolveTickCount(yAxisConfig, area.height, 'left')),\n );\n } else {\n groups.grid.replaceChildren();\n }\n\n if (xAxisConfig && xAxisConfig.grid) {\n renderGrid(\n groups.grid,\n xScale,\n xAxisConfig.grid,\n area.height,\n 'vertical',\n resolveTicks(xScale, xAxisConfig, resolveTickCount(xAxisConfig, area.width, 'bottom')),\n );\n }\n\n if (xAxisConfig) {\n positionAxis(groups.xAxis, xAxisConfig.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, xScale, xAxisConfig, area.width, 'bottom');\n } else {\n groups.xAxis.replaceChildren();\n }\n\n if (yAxisConfig) {\n positionAxis(groups.yAxis, yAxisConfig.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, yScale, yAxisConfig, area.height, 'left');\n } else {\n groups.yAxis.replaceChildren();\n }\n\n while (groups.series.children.length > seriesList.length) {\n groups.series.removeChild(groups.series.lastChild!);\n }\n\n const allPoints: Point[][] = [];\n\n for (const [i, series] of seriesList.entries()) {\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-scatter-series' });\n groups.series.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const points = computeScatterPoints(series.data, xScale, yScale);\n\n allPoints.push(points);\n\n renderScatterPoints(group, points, {\n color: seriesColor(i, series.color),\n disposalSignal: ctx.disposalSignal,\n marks: series.data,\n pointRadius: series.pointRadius ?? 3,\n transition: reason === 'resize' ? false : config.transition,\n });\n }\n\n tooltip?.hide();\n markers = ensureMarkerGroup(ctx.chartArea, markers);\n\n return createScatterInteraction({\n announcer: ctx.announcer,\n colors: () => seriesList.map((s, i) => seriesColor(i, s.color)),\n crosshair,\n dims: () => ctx.dimensions,\n getData: () => allData,\n getPoints: () => allPoints,\n getSeriesList: () => seriesList,\n margin: dims.margin,\n markers,\n onClick: config.onClick,\n onHover: config.onHover,\n seriesGroup: groups.series,\n svg: ctx.svg,\n tooltip,\n tooltipFormat: typeof config.tooltip === 'object' ? config.tooltip : undefined,\n });\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,70 @@
1
- import{createSvgElement as e}from"../../svg/element.js";import{positionAxis as t,renderAxis as n,resolveTickCount as r,resolveTicks as i}from"../../axes/axis.js";import{renderGrid as a}from"../../axes/grid.js";import{buildXScale as o,buildYScale as s}from"../../core/cartesian-scales.js";import{chartArea as c}from"../../core/layout.js";import{clearCartesianDom as l,createChartScaffold as u}from"../../core/chart-scaffold.js";import{seriesDomId as d}from"../../core/series-id.js";import{createCrosshair as f}from"../../interaction/crosshair.js";import{ensureMarkerGroup as p}from"../../interaction/series-interaction.js";import{seriesColor as m}from"../../theme/index.js";import{createScatterInteraction as h}from"../../interaction/scatter-interaction.js";import{computeScatterPoints as g,renderScatterPoints as _}from"./scatter-renderer.js";function createScatterChart(v,y){let b=null,x=null,S=y.series;return u(v,y,(u,v)=>{let{groups:C,legend:w,tooltip:T}=u;w?.update(S.map((e,t)=>({color:m(t,e.color),name:e.name})));let E=u.dimensions,D=c(E.width,E.height,E.margin),O=S.map(e=>e.data),k=O.flat().map(e=>e.key),A=O.flat().map(e=>e.value);if(k.length===0){l(C,w,T,b),x?.replaceChildren();return}y.crosshair&&!b&&(b=f(u.chartArea,y.crosshair));let j=o(k,D.width),M=s(A,D.height,!1),N=y.xAxis===!1?!1:y.xAxis??{},P=y.yAxis!==!1&&{grid:!0,...y.yAxis};for(P&&P.grid?a(C.grid,M,P.grid,D.width,`horizontal`,i(M,P,r(P,D.height,`left`))):C.grid.replaceChildren(),N&&N.grid&&a(C.grid,j,N.grid,D.height,`vertical`,i(j,N,r(N,D.width,`bottom`))),N?(t(C.xAxis,N.position??`bottom`,D.width,D.height),n(C.xAxis,j,N,D.width,`bottom`)):C.xAxis.replaceChildren(),P?(t(C.yAxis,P.position??`left`,D.width,D.height),n(C.yAxis,M,P,D.height,`left`)):C.yAxis.replaceChildren();C.series.children.length>S.length;)C.series.removeChild(C.series.lastChild);let F=[];for(let[t,n]of S.entries()){let r=C.series.children[t];r||(r=e(`g`,{class:`prism-scatter-series`}),C.series.appendChild(r)),r.setAttribute(`data-series-id`,d(n,t));let i=g(n.data,j,M);F.push(i),_(r,i,{color:m(t,n.color),disposalSignal:u.disposalSignal,marks:n.data,pointRadius:n.pointRadius??3,transition:v!==`resize`&&y.transition})}return T?.hide(),x=p(u.chartArea,x),h({announcer:u.announcer,colors:()=>S.map((e,t)=>m(t,e.color)),crosshair:b,dims:()=>u.dimensions,getData:()=>O,getPoints:()=>F,getSeriesList:()=>S,margin:E.margin,markers:x,onClick:y.onClick,onHover:y.onHover,seriesGroup:C.series,svg:u.svg,tooltip:T,tooltipFormat:typeof y.tooltip==`object`?y.tooltip:void 0})},e=>{S=e})}export{createScatterChart};
1
+ import { createSvgElement as e } from "../../svg/element.js";
2
+ import { positionAxis as t, renderAxis as n, resolveTickCount as r, resolveTicks as i } from "../../axes/axis.js";
3
+ import { renderGrid as a } from "../../axes/grid.js";
4
+ import { buildXScale as o, buildYScale as s } from "../../core/cartesian-scales.js";
5
+ import { chartArea as c } from "../../core/layout.js";
6
+ import { clearCartesianDom as l, createChartScaffold as u } from "../../core/chart-scaffold.js";
7
+ import { seriesDomId as d } from "../../core/series-id.js";
8
+ import { createCrosshair as f } from "../../interaction/crosshair.js";
9
+ import { ensureMarkerGroup as p } from "../../interaction/series-interaction.js";
10
+ import { seriesColor as m } from "../../theme/index.js";
11
+ import { createScatterInteraction as h } from "../../interaction/scatter-interaction.js";
12
+ import { computeScatterPoints as g, renderScatterPoints as _ } from "./scatter-renderer.js";
13
+ //#region src/charts/scatter/scatter-chart.ts
14
+ function createScatterChart(v, y) {
15
+ let b = null, x = null, S = y.series;
16
+ return u(v, y, (u, v) => {
17
+ let { groups: C, legend: w, tooltip: T } = u;
18
+ w?.update(S.map((e, t) => ({
19
+ color: m(t, e.color),
20
+ name: e.name
21
+ })));
22
+ let E = u.dimensions, D = c(E.width, E.height, E.margin), O = S.map((e) => e.data), k = O.flat().map((e) => e.key), A = O.flat().map((e) => e.value);
23
+ if (k.length === 0) {
24
+ l(C, w, T, b), x?.replaceChildren();
25
+ return;
26
+ }
27
+ y.crosshair && !b && (b = f(u.chartArea, y.crosshair));
28
+ let j = o(k, D.width), M = s(A, D.height, !1), N = y.xAxis === !1 ? !1 : y.xAxis ?? {}, P = y.yAxis !== !1 && {
29
+ grid: !0,
30
+ ...y.yAxis
31
+ };
32
+ for (P && P.grid ? a(C.grid, M, P.grid, D.width, "horizontal", i(M, P, r(P, D.height, "left"))) : C.grid.replaceChildren(), N && N.grid && a(C.grid, j, N.grid, D.height, "vertical", i(j, N, r(N, D.width, "bottom"))), N ? (t(C.xAxis, N.position ?? "bottom", D.width, D.height), n(C.xAxis, j, N, D.width, "bottom")) : C.xAxis.replaceChildren(), P ? (t(C.yAxis, P.position ?? "left", D.width, D.height), n(C.yAxis, M, P, D.height, "left")) : C.yAxis.replaceChildren(); C.series.children.length > S.length;) C.series.removeChild(C.series.lastChild);
33
+ let F = [];
34
+ for (let [t, n] of S.entries()) {
35
+ let r = C.series.children[t];
36
+ r || (r = e("g", { class: "prism-scatter-series" }), C.series.appendChild(r)), r.setAttribute("data-series-id", d(n, t));
37
+ let i = g(n.data, j, M);
38
+ F.push(i), _(r, i, {
39
+ color: m(t, n.color),
40
+ disposalSignal: u.disposalSignal,
41
+ marks: n.data,
42
+ pointRadius: n.pointRadius ?? 3,
43
+ transition: v !== "resize" && y.transition
44
+ });
45
+ }
46
+ return T?.hide(), x = p(u.chartArea, x), h({
47
+ announcer: u.announcer,
48
+ colors: () => S.map((e, t) => m(t, e.color)),
49
+ crosshair: b,
50
+ dims: () => u.dimensions,
51
+ getData: () => O,
52
+ getPoints: () => F,
53
+ getSeriesList: () => S,
54
+ margin: E.margin,
55
+ markers: x,
56
+ onClick: y.onClick,
57
+ onHover: y.onHover,
58
+ seriesGroup: C.series,
59
+ svg: u.svg,
60
+ tooltip: T,
61
+ tooltipFormat: typeof y.tooltip == "object" ? y.tooltip : void 0
62
+ });
63
+ }, (e) => {
64
+ S = e;
65
+ });
66
+ }
67
+ //#endregion
68
+ export { createScatterChart };
69
+
2
70
  //# sourceMappingURL=scatter-chart.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scatter-chart.js","names":[],"sources":["../../../src/charts/scatter/scatter-chart.ts"],"sourcesContent":["import { positionAxis, renderAxis, resolveTickCount, resolveTicks } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { buildXScale, buildYScale } from '../../core/cartesian-scales';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createScatterInteraction } from '../../interaction/scatter-interaction';\nimport { ensureMarkerGroup } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, ScatterChartConfig, ScatterSeriesConfig, XAxisConfig, YAxisConfig } from '../../types';\nimport { computeScatterPoints, renderScatterPoints } from './scatter-renderer';\n\nexport function createScatterChart(\n container: HTMLElement,\n config: ScatterChartConfig,\n): ChartHandle<ScatterSeriesConfig[]> {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n let markers: SVGGElement | null = null;\n let seriesList = config.series;\n\n return createChartScaffold(\n container,\n config,\n (ctx, reason) => {\n const { groups, legend, tooltip } = ctx;\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n const dims = ctx.dimensions;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const allData = seriesList.map((series) => series.data);\n const allX = allData.flat().map((datum) => datum.key);\n const allY = allData.flat().map((datum) => datum.value);\n\n if (allX.length === 0) {\n clearCartesianDom(groups, legend, tooltip, crosshair);\n markers?.replaceChildren();\n\n return;\n }\n\n if (config.crosshair && !crosshair) {\n crosshair = createCrosshair(ctx.chartArea, config.crosshair);\n }\n\n const xScale = buildXScale(allX, area.width);\n // Independent points have no baseline to anchor, so the y domain fits the data.\n const yScale = buildYScale(allY, area.height, false);\n\n // Axes render by default (value axis with gridlines); `false` opts out. The value\n // axis merges over its default so a partial config keeps the default gridlines.\n const xAxisConfig: XAxisConfig | false = config.xAxis === false ? false : (config.xAxis ?? {});\n const yAxisConfig: YAxisConfig | false = config.yAxis === false ? false : { grid: true, ...config.yAxis };\n\n if (yAxisConfig && yAxisConfig.grid) {\n renderGrid(\n groups.grid,\n yScale,\n yAxisConfig.grid,\n area.width,\n 'horizontal',\n resolveTicks(yScale, yAxisConfig, resolveTickCount(yAxisConfig, area.height, 'left')),\n );\n } else {\n groups.grid.replaceChildren();\n }\n\n if (xAxisConfig && xAxisConfig.grid) {\n renderGrid(\n groups.grid,\n xScale,\n xAxisConfig.grid,\n area.height,\n 'vertical',\n resolveTicks(xScale, xAxisConfig, resolveTickCount(xAxisConfig, area.width, 'bottom')),\n );\n }\n\n if (xAxisConfig) {\n positionAxis(groups.xAxis, xAxisConfig.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, xScale, xAxisConfig, area.width, 'bottom');\n } else {\n groups.xAxis.replaceChildren();\n }\n\n if (yAxisConfig) {\n positionAxis(groups.yAxis, yAxisConfig.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, yScale, yAxisConfig, area.height, 'left');\n } else {\n groups.yAxis.replaceChildren();\n }\n\n while (groups.series.children.length > seriesList.length) {\n groups.series.removeChild(groups.series.lastChild!);\n }\n\n const allPoints: Point[][] = [];\n\n for (const [i, series] of seriesList.entries()) {\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-scatter-series' });\n groups.series.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const points = computeScatterPoints(series.data, xScale, yScale);\n\n allPoints.push(points);\n\n renderScatterPoints(group, points, {\n color: seriesColor(i, series.color),\n disposalSignal: ctx.disposalSignal,\n marks: series.data,\n pointRadius: series.pointRadius ?? 3,\n transition: reason === 'resize' ? false : config.transition,\n });\n }\n\n tooltip?.hide();\n markers = ensureMarkerGroup(ctx.chartArea, markers);\n\n return createScatterInteraction({\n announcer: ctx.announcer,\n colors: () => seriesList.map((s, i) => seriesColor(i, s.color)),\n crosshair,\n dims: () => ctx.dimensions,\n getData: () => allData,\n getPoints: () => allPoints,\n getSeriesList: () => seriesList,\n margin: dims.margin,\n markers,\n onClick: config.onClick,\n onHover: config.onHover,\n seriesGroup: groups.series,\n svg: ctx.svg,\n tooltip,\n tooltipFormat: typeof config.tooltip === 'object' ? config.tooltip : undefined,\n });\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"scatter-chart.js","names":["crosshair","markers","seriesList","config","createChartScaffold","container","ctx","seriesColor","i","s","dims","area","chartArea","allData","series","allX","datum","allY","clearCartesianDom","groups","legend","tooltip","createCrosshair","xScale","buildXScale","yScale","buildYScale","xAxisConfig","yAxisConfig","renderGrid","resolveTicks","resolveTickCount","positionAxis","renderAxis","allPoints","group","createSvgElement","seriesDomId","points","computeScatterPoints","renderScatterPoints","reason","ensureMarkerGroup","createScatterInteraction","data"],"sources":["../../../src/charts/scatter/scatter-chart.ts"],"sourcesContent":["import { positionAxis, renderAxis, resolveTickCount, resolveTicks } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { buildXScale, buildYScale } from '../../core/cartesian-scales';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createScatterInteraction } from '../../interaction/scatter-interaction';\nimport { ensureMarkerGroup } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, ScatterChartConfig, ScatterSeriesConfig, XAxisConfig, YAxisConfig } from '../../types';\nimport { computeScatterPoints, renderScatterPoints } from './scatter-renderer';\n\nexport function createScatterChart(\n container: HTMLElement,\n config: ScatterChartConfig,\n): ChartHandle<ScatterSeriesConfig[]> {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n let markers: SVGGElement | null = null;\n let seriesList = config.series;\n\n return createChartScaffold(\n container,\n config,\n (ctx, reason) => {\n const { groups, legend, tooltip } = ctx;\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n const dims = ctx.dimensions;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const allData = seriesList.map((series) => series.data);\n const allX = allData.flat().map((datum) => datum.key);\n const allY = allData.flat().map((datum) => datum.value);\n\n if (allX.length === 0) {\n clearCartesianDom(groups, legend, tooltip, crosshair);\n markers?.replaceChildren();\n\n return;\n }\n\n if (config.crosshair && !crosshair) {\n crosshair = createCrosshair(ctx.chartArea, config.crosshair);\n }\n\n const xScale = buildXScale(allX, area.width);\n // Independent points have no baseline to anchor, so the y domain fits the data.\n const yScale = buildYScale(allY, area.height, false);\n\n // Axes render by default (value axis with gridlines); `false` opts out. The value\n // axis merges over its default so a partial config keeps the default gridlines.\n const xAxisConfig: XAxisConfig | false = config.xAxis === false ? false : (config.xAxis ?? {});\n const yAxisConfig: YAxisConfig | false = config.yAxis === false ? false : { grid: true, ...config.yAxis };\n\n if (yAxisConfig && yAxisConfig.grid) {\n renderGrid(\n groups.grid,\n yScale,\n yAxisConfig.grid,\n area.width,\n 'horizontal',\n resolveTicks(yScale, yAxisConfig, resolveTickCount(yAxisConfig, area.height, 'left')),\n );\n } else {\n groups.grid.replaceChildren();\n }\n\n if (xAxisConfig && xAxisConfig.grid) {\n renderGrid(\n groups.grid,\n xScale,\n xAxisConfig.grid,\n area.height,\n 'vertical',\n resolveTicks(xScale, xAxisConfig, resolveTickCount(xAxisConfig, area.width, 'bottom')),\n );\n }\n\n if (xAxisConfig) {\n positionAxis(groups.xAxis, xAxisConfig.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, xScale, xAxisConfig, area.width, 'bottom');\n } else {\n groups.xAxis.replaceChildren();\n }\n\n if (yAxisConfig) {\n positionAxis(groups.yAxis, yAxisConfig.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, yScale, yAxisConfig, area.height, 'left');\n } else {\n groups.yAxis.replaceChildren();\n }\n\n while (groups.series.children.length > seriesList.length) {\n groups.series.removeChild(groups.series.lastChild!);\n }\n\n const allPoints: Point[][] = [];\n\n for (const [i, series] of seriesList.entries()) {\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-scatter-series' });\n groups.series.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const points = computeScatterPoints(series.data, xScale, yScale);\n\n allPoints.push(points);\n\n renderScatterPoints(group, points, {\n color: seriesColor(i, series.color),\n disposalSignal: ctx.disposalSignal,\n marks: series.data,\n pointRadius: series.pointRadius ?? 3,\n transition: reason === 'resize' ? false : config.transition,\n });\n }\n\n tooltip?.hide();\n markers = ensureMarkerGroup(ctx.chartArea, markers);\n\n return createScatterInteraction({\n announcer: ctx.announcer,\n colors: () => seriesList.map((s, i) => seriesColor(i, s.color)),\n crosshair,\n dims: () => ctx.dimensions,\n getData: () => allData,\n getPoints: () => allPoints,\n getSeriesList: () => seriesList,\n margin: dims.margin,\n markers,\n onClick: config.onClick,\n onHover: config.onHover,\n seriesGroup: groups.series,\n svg: ctx.svg,\n tooltip,\n tooltipFormat: typeof config.tooltip === 'object' ? config.tooltip : undefined,\n });\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"scatter-renderer.cjs","names":[],"sources":["../../../src/charts/scatter/scatter-renderer.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport type { DatumMark } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionOption } from '../../types';\n\nexport interface ScatterRenderOptions {\n color: string;\n /** Aborted when the owning chart is disposed: stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n /** Per-datum presentation parallel to `points`; only `opacity` applies to a scatter marker. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n transition?: TransitionOption;\n}\n\n/** Upper bound on the total staggered delay entering points may add, whatever the per-point value. */\nconst MAX_STAGGER_TOTAL = 400;\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n// Point positions currently on screen, so an update slides from them even mid-tween.\nconst drawnPoints = new WeakMap<SVGGElement, Point[]>();\n\n/**\n * Maps scatter data to plot-area points: `key` is the x position, `value` the y.\n * A string key is a data error here, not a band position.\n */\nexport function computeScatterPoints(\n data: ContinuousDatum[],\n xScale: Scale<Date | number>,\n yScale: Scale<number>,\n): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computeScatterPoints: datum.key is null or undefined: data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computeScatterPoints: string keys are not supported: scatter x values must be numbers or Dates.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n\n/**\n * Draws one scatter series as point markers. Entering points grow from radius 0 at\n * their final position (staggered in x order when `stagger` is set); existing points\n * slide from their drawn position. Disabled or reduced motion paints synchronously.\n */\nexport function renderScatterPoints(parent: SVGGElement, points: Point[], options: ScatterRenderOptions): void {\n const motion = resolveMotion(options.transition);\n const marks = options.marks ?? [];\n const radius = options.pointRadius;\n\n activeAnimations.get(parent)?.();\n activeAnimations.delete(parent);\n\n while (parent.children.length > points.length) parent.lastChild!.remove();\n\n const drawn = drawnPoints.get(parent) ?? [];\n const fromRadius: number[] = [];\n const circles = points.map((_, i) => {\n let circle = parent.children[i] as SVGCircleElement | undefined;\n\n if (circle) {\n fromRadius.push(Number(circle.getAttribute('r')) || 0);\n } else {\n circle = createSvgElement('circle', { class: 'prism-scatter-point' });\n parent.appendChild(circle);\n fromRadius.push(0);\n }\n\n setAttributes(circle, { fill: options.color, opacity: marks[i]?.opacity });\n\n return circle;\n });\n\n const paint = (pts: Point[], radii: (i: number) => number): void => {\n for (const [i, circle] of circles.entries()) setAttributes(circle, { cx: pts[i].x, cy: pts[i].y, r: radii(i) });\n\n drawnPoints.set(parent, pts);\n };\n\n if (motion.duration === 0) {\n paint(points, () => radius);\n\n return;\n }\n\n const fromPts = points.map((to, i) => drawn[i] ?? to);\n // Entering points (no drawn marker yet) take their own stagger lane in x order;\n // moving points all share lane 0 so an update never crawls.\n const entering = points.map((_, i) => i).filter((i) => i >= drawn.length);\n const lanes = new Map(\n [...entering].sort((a, b) => points[a].x - points[b].x).map((pointIndex, lane) => [pointIndex, lane]),\n );\n const stagger = Math.min(motion.stagger, MAX_STAGGER_TOTAL / Math.max(1, entering.length));\n\n const paintFrame = (progress: (lane: number) => number): void => {\n const eased = points.map((_, i) => progress(lanes.get(i) ?? 0));\n\n paint(\n points.map((to, i) => ({\n x: tweenNumber(fromPts[i].x, to.x, eased[i]),\n y: tweenNumber(fromPts[i].y, to.y, eased[i]),\n })),\n (i) => tweenNumber(fromRadius[i], radius, eased[i]),\n );\n };\n\n // The starting state goes on screen immediately: `startTween` only paints on\n // the first frame callback, which would otherwise leave one stale frame.\n paintFrame(() => 0);\n\n activeAnimations.set(\n parent,\n startTween({\n count: Math.max(1, entering.length),\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: () => {\n activeAnimations.delete(parent);\n paint(points, () => radius);\n },\n onFrame: paintFrame,\n signal: options.disposalSignal,\n stagger,\n }),\n );\n}\n"],"mappings":"sOAqBA,IAAM,EAAoB,IAEpB,EAAmB,IAAI,QAEvB,EAAc,IAAI,QAMxB,SAAgB,qBACd,EACA,EACA,EACS,CAST,OARI,EAAK,KAAM,GAAM,EAAE,KAAO,IAAI,GAIvB,EAAK,KAAM,GAAM,OAAO,EAAE,KAAQ,QAAQ,EAI9C,EAAK,IAAK,IAAO,CACtB,EAAG,EAAO,IAAI,EAAE,GAAoB,EACpC,EAAG,EAAO,IAAI,EAAE,KAAK,CACvB,EAAE,CACJ,CAOA,SAAgB,oBAAoB,EAAqB,EAAiB,EAAqC,CAC7G,IAAM,EAAS,EAAA,cAAc,EAAQ,UAAU,EACzC,EAAQ,EAAQ,OAAS,CAAC,EAC1B,EAAS,EAAQ,YAKvB,IAHA,EAAiB,IAAI,CAAM,CAAC,GAAG,EAC/B,EAAiB,OAAO,CAAM,EAEvB,EAAO,SAAS,OAAS,EAAO,QAAQ,EAAO,UAAW,OAAO,EAExE,IAAM,EAAQ,EAAY,IAAI,CAAM,GAAK,CAAC,EACpC,EAAuB,CAAC,EACxB,EAAU,EAAO,KAAK,EAAG,IAAM,CACnC,IAAI,EAAS,EAAO,SAAS,GAY7B,OAVI,EACF,EAAW,KAAK,OAAO,EAAO,aAAa,GAAG,CAAC,GAAK,CAAC,GAErD,EAAS,EAAA,iBAAiB,SAAU,CAAE,MAAO,qBAAsB,CAAC,EACpE,EAAO,YAAY,CAAM,EACzB,EAAW,KAAK,CAAC,GAGnB,EAAA,cAAc,EAAQ,CAAE,KAAM,EAAQ,MAAO,QAAS,EAAM,EAAE,EAAE,OAAQ,CAAC,EAElE,CACT,CAAC,EAEK,OAAS,EAAc,IAAuC,CAClE,IAAK,GAAM,CAAC,EAAG,KAAW,EAAQ,QAAQ,EAAG,EAAA,cAAc,EAAQ,CAAE,GAAI,EAAI,EAAE,CAAC,EAAG,GAAI,EAAI,EAAE,CAAC,EAAG,EAAG,EAAM,CAAC,CAAE,CAAC,EAE9G,EAAY,IAAI,EAAQ,CAAG,CAC7B,EAEA,GAAI,EAAO,WAAa,EAAG,CACzB,MAAM,MAAc,CAAM,EAE1B,MACF,CAEA,IAAM,EAAU,EAAO,KAAK,EAAI,IAAM,EAAM,IAAM,CAAE,EAG9C,EAAW,EAAO,KAAK,EAAG,IAAM,CAAC,CAAC,CAAC,OAAQ,GAAM,GAAK,EAAM,MAAM,EAClE,EAAQ,IAAI,IAChB,CAAC,GAAG,CAAQ,CAAC,CAAC,MAAM,EAAG,IAAM,EAAO,EAAE,CAAC,EAAI,EAAO,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,EAAY,IAAS,CAAC,EAAY,CAAI,CAAC,CACtG,EACM,EAAU,KAAK,IAAI,EAAO,QAAS,EAAoB,KAAK,IAAI,EAAG,EAAS,MAAM,CAAC,EAEnF,WAAc,GAA6C,CAC/D,IAAM,EAAQ,EAAO,KAAK,EAAG,IAAM,EAAS,EAAM,IAAI,CAAC,GAAK,CAAC,CAAC,EAE9D,MACE,EAAO,KAAK,EAAI,KAAO,CACrB,EAAG,EAAA,YAAY,EAAQ,EAAE,CAAC,EAAG,EAAG,EAAG,EAAM,EAAE,EAC3C,EAAG,EAAA,YAAY,EAAQ,EAAE,CAAC,EAAG,EAAG,EAAG,EAAM,EAAE,CAC7C,EAAE,EACD,GAAM,EAAA,YAAY,EAAW,GAAI,EAAQ,EAAM,EAAE,CACpD,CACF,EAIA,eAAiB,CAAC,EAElB,EAAiB,IACf,EACA,EAAA,WAAW,CACT,MAAO,KAAK,IAAI,EAAG,EAAS,MAAM,EAClC,SAAU,EAAO,SACjB,OAAQ,EAAA,cAAc,EAAO,MAAM,EACnC,eAAkB,CAChB,EAAiB,OAAO,CAAM,EAC9B,MAAM,MAAc,CAAM,CAC5B,EACA,QAAS,WACT,OAAQ,EAAQ,eAChB,SACF,CAAC,CACH,CACF"}
1
+ {"version":3,"file":"scatter-renderer.cjs","names":["resolveMotion","createSvgElement","tweenNumber","startTween","resolveEasing","require_element","require_easing","require_motion","require_tween","require_transition","MAX_STAGGER_TOTAL","activeAnimations","drawnPoints","data","d","xScale","yScale","motion","options","marks","radius","parent","points","drawn","fromRadius","circles","circle","i","pts","radii","fromPts","to","entering","lanes","a","b","pointIndex","lane","stagger","eased","progress"],"sources":["../../../src/charts/scatter/scatter-renderer.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport type { DatumMark } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionOption } from '../../types';\n\nexport interface ScatterRenderOptions {\n color: string;\n /** Aborted when the owning chart is disposed: stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n /** Per-datum presentation parallel to `points`; only `opacity` applies to a scatter marker. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n transition?: TransitionOption;\n}\n\n/** Upper bound on the total staggered delay entering points may add, whatever the per-point value. */\nconst MAX_STAGGER_TOTAL = 400;\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n// Point positions currently on screen, so an update slides from them even mid-tween.\nconst drawnPoints = new WeakMap<SVGGElement, Point[]>();\n\n/**\n * Maps scatter data to plot-area points: `key` is the x position, `value` the y.\n * A string key is a data error here, not a band position.\n */\nexport function computeScatterPoints(\n data: ContinuousDatum[],\n xScale: Scale<Date | number>,\n yScale: Scale<number>,\n): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computeScatterPoints: datum.key is null or undefined: data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computeScatterPoints: string keys are not supported: scatter x values must be numbers or Dates.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n\n/**\n * Draws one scatter series as point markers. Entering points grow from radius 0 at\n * their final position (staggered in x order when `stagger` is set); existing points\n * slide from their drawn position. Disabled or reduced motion paints synchronously.\n */\nexport function renderScatterPoints(parent: SVGGElement, points: Point[], options: ScatterRenderOptions): void {\n const motion = resolveMotion(options.transition);\n const marks = options.marks ?? [];\n const radius = options.pointRadius;\n\n activeAnimations.get(parent)?.();\n activeAnimations.delete(parent);\n\n while (parent.children.length > points.length) parent.lastChild!.remove();\n\n const drawn = drawnPoints.get(parent) ?? [];\n const fromRadius: number[] = [];\n const circles = points.map((_, i) => {\n let circle = parent.children[i] as SVGCircleElement | undefined;\n\n if (circle) {\n fromRadius.push(Number(circle.getAttribute('r')) || 0);\n } else {\n circle = createSvgElement('circle', { class: 'prism-scatter-point' });\n parent.appendChild(circle);\n fromRadius.push(0);\n }\n\n setAttributes(circle, { fill: options.color, opacity: marks[i]?.opacity });\n\n return circle;\n });\n\n const paint = (pts: Point[], radii: (i: number) => number): void => {\n for (const [i, circle] of circles.entries()) setAttributes(circle, { cx: pts[i].x, cy: pts[i].y, r: radii(i) });\n\n drawnPoints.set(parent, pts);\n };\n\n if (motion.duration === 0) {\n paint(points, () => radius);\n\n return;\n }\n\n const fromPts = points.map((to, i) => drawn[i] ?? to);\n // Entering points (no drawn marker yet) take their own stagger lane in x order;\n // moving points all share lane 0 so an update never crawls.\n const entering = points.map((_, i) => i).filter((i) => i >= drawn.length);\n const lanes = new Map(\n [...entering].sort((a, b) => points[a].x - points[b].x).map((pointIndex, lane) => [pointIndex, lane]),\n );\n const stagger = Math.min(motion.stagger, MAX_STAGGER_TOTAL / Math.max(1, entering.length));\n\n const paintFrame = (progress: (lane: number) => number): void => {\n const eased = points.map((_, i) => progress(lanes.get(i) ?? 0));\n\n paint(\n points.map((to, i) => ({\n x: tweenNumber(fromPts[i].x, to.x, eased[i]),\n y: tweenNumber(fromPts[i].y, to.y, eased[i]),\n })),\n (i) => tweenNumber(fromRadius[i], radius, eased[i]),\n );\n };\n\n // The starting state goes on screen immediately: `startTween` only paints on\n // the first frame callback, which would otherwise leave one stale frame.\n paintFrame(() => 0);\n\n activeAnimations.set(\n parent,\n startTween({\n count: Math.max(1, entering.length),\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: () => {\n activeAnimations.delete(parent);\n paint(points, () => radius);\n },\n onFrame: paintFrame,\n signal: options.disposalSignal,\n stagger,\n }),\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,58 @@
1
- import"../../_dev.js";import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{resolveEasing as n}from"../../animation/easing.js";import{resolveMotion as r}from"../../animation/motion.js";import{tweenNumber as i}from"../../animation/tween.js";import{startTween as a}from"../../animation/transition.js";var o=400,s=new WeakMap,c=new WeakMap;function computeScatterPoints(e,t,n){return e.some(e=>e.key==null)||e.some(e=>typeof e.key==`string`),e.map(e=>({x:t.map(e.key),y:n.map(e.value)}))}function renderScatterPoints(l,u,d){let f=r(d.transition),p=d.marks??[],m=d.pointRadius;for(s.get(l)?.(),s.delete(l);l.children.length>u.length;)l.lastChild.remove();let h=c.get(l)??[],g=[],_=u.map((n,r)=>{let i=l.children[r];return i?g.push(Number(i.getAttribute(`r`))||0):(i=e(`circle`,{class:`prism-scatter-point`}),l.appendChild(i),g.push(0)),t(i,{fill:d.color,opacity:p[r]?.opacity}),i}),paint=(e,n)=>{for(let[r,i]of _.entries())t(i,{cx:e[r].x,cy:e[r].y,r:n(r)});c.set(l,e)};if(f.duration===0){paint(u,()=>m);return}let v=u.map((e,t)=>h[t]??e),y=u.map((e,t)=>t).filter(e=>e>=h.length),b=new Map([...y].sort((e,t)=>u[e].x-u[t].x).map((e,t)=>[e,t])),x=Math.min(f.stagger,o/Math.max(1,y.length)),paintFrame=e=>{let t=u.map((t,n)=>e(b.get(n)??0));paint(u.map((e,n)=>({x:i(v[n].x,e.x,t[n]),y:i(v[n].y,e.y,t[n])})),e=>i(g[e],m,t[e]))};paintFrame(()=>0),s.set(l,a({count:Math.max(1,y.length),duration:f.duration,easing:n(f.easing),onComplete:()=>{s.delete(l),paint(u,()=>m)},onFrame:paintFrame,signal:d.disposalSignal,stagger:x}))}export{computeScatterPoints,renderScatterPoints};
1
+ import "../../_dev.js";
2
+ import { createSvgElement as e, setAttributes as t } from "../../svg/element.js";
3
+ import { resolveEasing as n } from "../../animation/easing.js";
4
+ import { resolveMotion as r } from "../../animation/motion.js";
5
+ import { tweenNumber as i } from "../../animation/tween.js";
6
+ import { startTween as a } from "../../animation/transition.js";
7
+ //#region src/charts/scatter/scatter-renderer.ts
8
+ var o = 400, s = /* @__PURE__ */ new WeakMap(), c = /* @__PURE__ */ new WeakMap();
9
+ function computeScatterPoints(e, t, n) {
10
+ return e.some((e) => e.key == null) || e.some((e) => typeof e.key == "string"), e.map((e) => ({
11
+ x: t.map(e.key),
12
+ y: n.map(e.value)
13
+ }));
14
+ }
15
+ function renderScatterPoints(l, u, d) {
16
+ let f = r(d.transition), p = d.marks ?? [], m = d.pointRadius;
17
+ for (s.get(l)?.(), s.delete(l); l.children.length > u.length;) l.lastChild.remove();
18
+ let h = c.get(l) ?? [], g = [], _ = u.map((n, r) => {
19
+ let i = l.children[r];
20
+ return i ? g.push(Number(i.getAttribute("r")) || 0) : (i = e("circle", { class: "prism-scatter-point" }), l.appendChild(i), g.push(0)), t(i, {
21
+ fill: d.color,
22
+ opacity: p[r]?.opacity
23
+ }), i;
24
+ }), paint = (e, n) => {
25
+ for (let [r, i] of _.entries()) t(i, {
26
+ cx: e[r].x,
27
+ cy: e[r].y,
28
+ r: n(r)
29
+ });
30
+ c.set(l, e);
31
+ };
32
+ if (f.duration === 0) {
33
+ paint(u, () => m);
34
+ return;
35
+ }
36
+ let v = u.map((e, t) => h[t] ?? e), y = u.map((e, t) => t).filter((e) => e >= h.length), b = new Map([...y].sort((e, t) => u[e].x - u[t].x).map((e, t) => [e, t])), x = Math.min(f.stagger, o / Math.max(1, y.length)), paintFrame = (e) => {
37
+ let t = u.map((t, n) => e(b.get(n) ?? 0));
38
+ paint(u.map((e, n) => ({
39
+ x: i(v[n].x, e.x, t[n]),
40
+ y: i(v[n].y, e.y, t[n])
41
+ })), (e) => i(g[e], m, t[e]));
42
+ };
43
+ paintFrame(() => 0), s.set(l, a({
44
+ count: Math.max(1, y.length),
45
+ duration: f.duration,
46
+ easing: n(f.easing),
47
+ onComplete: () => {
48
+ s.delete(l), paint(u, () => m);
49
+ },
50
+ onFrame: paintFrame,
51
+ signal: d.disposalSignal,
52
+ stagger: x
53
+ }));
54
+ }
55
+ //#endregion
56
+ export { computeScatterPoints, renderScatterPoints };
57
+
2
58
  //# sourceMappingURL=scatter-renderer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scatter-renderer.js","names":[],"sources":["../../../src/charts/scatter/scatter-renderer.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport type { DatumMark } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionOption } from '../../types';\n\nexport interface ScatterRenderOptions {\n color: string;\n /** Aborted when the owning chart is disposed: stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n /** Per-datum presentation parallel to `points`; only `opacity` applies to a scatter marker. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n transition?: TransitionOption;\n}\n\n/** Upper bound on the total staggered delay entering points may add, whatever the per-point value. */\nconst MAX_STAGGER_TOTAL = 400;\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n// Point positions currently on screen, so an update slides from them even mid-tween.\nconst drawnPoints = new WeakMap<SVGGElement, Point[]>();\n\n/**\n * Maps scatter data to plot-area points: `key` is the x position, `value` the y.\n * A string key is a data error here, not a band position.\n */\nexport function computeScatterPoints(\n data: ContinuousDatum[],\n xScale: Scale<Date | number>,\n yScale: Scale<number>,\n): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computeScatterPoints: datum.key is null or undefined: data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computeScatterPoints: string keys are not supported: scatter x values must be numbers or Dates.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n\n/**\n * Draws one scatter series as point markers. Entering points grow from radius 0 at\n * their final position (staggered in x order when `stagger` is set); existing points\n * slide from their drawn position. Disabled or reduced motion paints synchronously.\n */\nexport function renderScatterPoints(parent: SVGGElement, points: Point[], options: ScatterRenderOptions): void {\n const motion = resolveMotion(options.transition);\n const marks = options.marks ?? [];\n const radius = options.pointRadius;\n\n activeAnimations.get(parent)?.();\n activeAnimations.delete(parent);\n\n while (parent.children.length > points.length) parent.lastChild!.remove();\n\n const drawn = drawnPoints.get(parent) ?? [];\n const fromRadius: number[] = [];\n const circles = points.map((_, i) => {\n let circle = parent.children[i] as SVGCircleElement | undefined;\n\n if (circle) {\n fromRadius.push(Number(circle.getAttribute('r')) || 0);\n } else {\n circle = createSvgElement('circle', { class: 'prism-scatter-point' });\n parent.appendChild(circle);\n fromRadius.push(0);\n }\n\n setAttributes(circle, { fill: options.color, opacity: marks[i]?.opacity });\n\n return circle;\n });\n\n const paint = (pts: Point[], radii: (i: number) => number): void => {\n for (const [i, circle] of circles.entries()) setAttributes(circle, { cx: pts[i].x, cy: pts[i].y, r: radii(i) });\n\n drawnPoints.set(parent, pts);\n };\n\n if (motion.duration === 0) {\n paint(points, () => radius);\n\n return;\n }\n\n const fromPts = points.map((to, i) => drawn[i] ?? to);\n // Entering points (no drawn marker yet) take their own stagger lane in x order;\n // moving points all share lane 0 so an update never crawls.\n const entering = points.map((_, i) => i).filter((i) => i >= drawn.length);\n const lanes = new Map(\n [...entering].sort((a, b) => points[a].x - points[b].x).map((pointIndex, lane) => [pointIndex, lane]),\n );\n const stagger = Math.min(motion.stagger, MAX_STAGGER_TOTAL / Math.max(1, entering.length));\n\n const paintFrame = (progress: (lane: number) => number): void => {\n const eased = points.map((_, i) => progress(lanes.get(i) ?? 0));\n\n paint(\n points.map((to, i) => ({\n x: tweenNumber(fromPts[i].x, to.x, eased[i]),\n y: tweenNumber(fromPts[i].y, to.y, eased[i]),\n })),\n (i) => tweenNumber(fromRadius[i], radius, eased[i]),\n );\n };\n\n // The starting state goes on screen immediately: `startTween` only paints on\n // the first frame callback, which would otherwise leave one stale frame.\n paintFrame(() => 0);\n\n activeAnimations.set(\n parent,\n startTween({\n count: Math.max(1, entering.length),\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: () => {\n activeAnimations.delete(parent);\n paint(points, () => radius);\n },\n onFrame: paintFrame,\n signal: options.disposalSignal,\n stagger,\n }),\n );\n}\n"],"mappings":"uUAqBA,IAAM,EAAoB,IAEpB,EAAmB,IAAI,QAEvB,EAAc,IAAI,QAMxB,SAAgB,qBACd,EACA,EACA,EACS,CAST,OARI,EAAK,KAAM,GAAM,EAAE,KAAO,IAAI,GAIvB,EAAK,KAAM,GAAM,OAAO,EAAE,KAAQ,QAAQ,EAI9C,EAAK,IAAK,IAAO,CACtB,EAAG,EAAO,IAAI,EAAE,GAAoB,EACpC,EAAG,EAAO,IAAI,EAAE,KAAK,CACvB,EAAE,CACJ,CAOA,SAAgB,oBAAoB,EAAqB,EAAiB,EAAqC,CAC7G,IAAM,EAAS,EAAc,EAAQ,UAAU,EACzC,EAAQ,EAAQ,OAAS,CAAC,EAC1B,EAAS,EAAQ,YAKvB,IAHA,EAAiB,IAAI,CAAM,CAAC,GAAG,EAC/B,EAAiB,OAAO,CAAM,EAEvB,EAAO,SAAS,OAAS,EAAO,QAAQ,EAAO,UAAW,OAAO,EAExE,IAAM,EAAQ,EAAY,IAAI,CAAM,GAAK,CAAC,EACpC,EAAuB,CAAC,EACxB,EAAU,EAAO,KAAK,EAAG,IAAM,CACnC,IAAI,EAAS,EAAO,SAAS,GAY7B,OAVI,EACF,EAAW,KAAK,OAAO,EAAO,aAAa,GAAG,CAAC,GAAK,CAAC,GAErD,EAAS,EAAiB,SAAU,CAAE,MAAO,qBAAsB,CAAC,EACpE,EAAO,YAAY,CAAM,EACzB,EAAW,KAAK,CAAC,GAGnB,EAAc,EAAQ,CAAE,KAAM,EAAQ,MAAO,QAAS,EAAM,EAAE,EAAE,OAAQ,CAAC,EAElE,CACT,CAAC,EAEK,OAAS,EAAc,IAAuC,CAClE,IAAK,GAAM,CAAC,EAAG,KAAW,EAAQ,QAAQ,EAAG,EAAc,EAAQ,CAAE,GAAI,EAAI,EAAE,CAAC,EAAG,GAAI,EAAI,EAAE,CAAC,EAAG,EAAG,EAAM,CAAC,CAAE,CAAC,EAE9G,EAAY,IAAI,EAAQ,CAAG,CAC7B,EAEA,GAAI,EAAO,WAAa,EAAG,CACzB,MAAM,MAAc,CAAM,EAE1B,MACF,CAEA,IAAM,EAAU,EAAO,KAAK,EAAI,IAAM,EAAM,IAAM,CAAE,EAG9C,EAAW,EAAO,KAAK,EAAG,IAAM,CAAC,CAAC,CAAC,OAAQ,GAAM,GAAK,EAAM,MAAM,EAClE,EAAQ,IAAI,IAChB,CAAC,GAAG,CAAQ,CAAC,CAAC,MAAM,EAAG,IAAM,EAAO,EAAE,CAAC,EAAI,EAAO,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,EAAY,IAAS,CAAC,EAAY,CAAI,CAAC,CACtG,EACM,EAAU,KAAK,IAAI,EAAO,QAAS,EAAoB,KAAK,IAAI,EAAG,EAAS,MAAM,CAAC,EAEnF,WAAc,GAA6C,CAC/D,IAAM,EAAQ,EAAO,KAAK,EAAG,IAAM,EAAS,EAAM,IAAI,CAAC,GAAK,CAAC,CAAC,EAE9D,MACE,EAAO,KAAK,EAAI,KAAO,CACrB,EAAG,EAAY,EAAQ,EAAE,CAAC,EAAG,EAAG,EAAG,EAAM,EAAE,EAC3C,EAAG,EAAY,EAAQ,EAAE,CAAC,EAAG,EAAG,EAAG,EAAM,EAAE,CAC7C,EAAE,EACD,GAAM,EAAY,EAAW,GAAI,EAAQ,EAAM,EAAE,CACpD,CACF,EAIA,eAAiB,CAAC,EAElB,EAAiB,IACf,EACA,EAAW,CACT,MAAO,KAAK,IAAI,EAAG,EAAS,MAAM,EAClC,SAAU,EAAO,SACjB,OAAQ,EAAc,EAAO,MAAM,EACnC,eAAkB,CAChB,EAAiB,OAAO,CAAM,EAC9B,MAAM,MAAc,CAAM,CAC5B,EACA,QAAS,WACT,OAAQ,EAAQ,eAChB,SACF,CAAC,CACH,CACF"}
1
+ {"version":3,"file":"scatter-renderer.js","names":["MAX_STAGGER_TOTAL","activeAnimations","drawnPoints","data","d","xScale","yScale","motion","resolveMotion","options","marks","radius","parent","points","drawn","fromRadius","circles","circle","i","createSvgElement","setAttributes","pts","radii","fromPts","to","entering","lanes","a","b","pointIndex","lane","stagger","eased","progress","tweenNumber","startTween","resolveEasing"],"sources":["../../../src/charts/scatter/scatter-renderer.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport type { DatumMark } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionOption } from '../../types';\n\nexport interface ScatterRenderOptions {\n color: string;\n /** Aborted when the owning chart is disposed: stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n /** Per-datum presentation parallel to `points`; only `opacity` applies to a scatter marker. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n transition?: TransitionOption;\n}\n\n/** Upper bound on the total staggered delay entering points may add, whatever the per-point value. */\nconst MAX_STAGGER_TOTAL = 400;\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n// Point positions currently on screen, so an update slides from them even mid-tween.\nconst drawnPoints = new WeakMap<SVGGElement, Point[]>();\n\n/**\n * Maps scatter data to plot-area points: `key` is the x position, `value` the y.\n * A string key is a data error here, not a band position.\n */\nexport function computeScatterPoints(\n data: ContinuousDatum[],\n xScale: Scale<Date | number>,\n yScale: Scale<number>,\n): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computeScatterPoints: datum.key is null or undefined: data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computeScatterPoints: string keys are not supported: scatter x values must be numbers or Dates.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n\n/**\n * Draws one scatter series as point markers. Entering points grow from radius 0 at\n * their final position (staggered in x order when `stagger` is set); existing points\n * slide from their drawn position. Disabled or reduced motion paints synchronously.\n */\nexport function renderScatterPoints(parent: SVGGElement, points: Point[], options: ScatterRenderOptions): void {\n const motion = resolveMotion(options.transition);\n const marks = options.marks ?? [];\n const radius = options.pointRadius;\n\n activeAnimations.get(parent)?.();\n activeAnimations.delete(parent);\n\n while (parent.children.length > points.length) parent.lastChild!.remove();\n\n const drawn = drawnPoints.get(parent) ?? [];\n const fromRadius: number[] = [];\n const circles = points.map((_, i) => {\n let circle = parent.children[i] as SVGCircleElement | undefined;\n\n if (circle) {\n fromRadius.push(Number(circle.getAttribute('r')) || 0);\n } else {\n circle = createSvgElement('circle', { class: 'prism-scatter-point' });\n parent.appendChild(circle);\n fromRadius.push(0);\n }\n\n setAttributes(circle, { fill: options.color, opacity: marks[i]?.opacity });\n\n return circle;\n });\n\n const paint = (pts: Point[], radii: (i: number) => number): void => {\n for (const [i, circle] of circles.entries()) setAttributes(circle, { cx: pts[i].x, cy: pts[i].y, r: radii(i) });\n\n drawnPoints.set(parent, pts);\n };\n\n if (motion.duration === 0) {\n paint(points, () => radius);\n\n return;\n }\n\n const fromPts = points.map((to, i) => drawn[i] ?? to);\n // Entering points (no drawn marker yet) take their own stagger lane in x order;\n // moving points all share lane 0 so an update never crawls.\n const entering = points.map((_, i) => i).filter((i) => i >= drawn.length);\n const lanes = new Map(\n [...entering].sort((a, b) => points[a].x - points[b].x).map((pointIndex, lane) => [pointIndex, lane]),\n );\n const stagger = Math.min(motion.stagger, MAX_STAGGER_TOTAL / Math.max(1, entering.length));\n\n const paintFrame = (progress: (lane: number) => number): void => {\n const eased = points.map((_, i) => progress(lanes.get(i) ?? 0));\n\n paint(\n points.map((to, i) => ({\n x: tweenNumber(fromPts[i].x, to.x, eased[i]),\n y: tweenNumber(fromPts[i].y, to.y, eased[i]),\n })),\n (i) => tweenNumber(fromRadius[i], radius, eased[i]),\n );\n };\n\n // The starting state goes on screen immediately: `startTween` only paints on\n // the first frame callback, which would otherwise leave one stale frame.\n paintFrame(() => 0);\n\n activeAnimations.set(\n parent,\n startTween({\n count: Math.max(1, entering.length),\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: () => {\n activeAnimations.delete(parent);\n paint(points, () => radius);\n },\n onFrame: paintFrame,\n signal: options.disposalSignal,\n stagger,\n }),\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../_tappers.cjs"),n=require("../../errors.cjs"),r=require("../../core/chart-base.cjs"),i=require("../../animation/easing.cjs"),a=require("../../animation/motion.cjs"),o=require("../../animation/tween.cjs"),s=require("../../animation/transition.cjs"),c=require("../../core/ids.cjs"),l=require("../../svg/path.cjs");var u=5;function buildTopPoints(e,t,n){if(e.length===0)return[];let r=t/Math.max(1,e.length-1),i=Math.min(...e),a=Math.max(...e)-i||1;return e.map((e,t)=>({x:t*r,y:n-(e-i)/a*n}))}function buildAreaPathFromPoints(e,t,n){if(e.length===0)return``;let r=e.map(e=>({x:e.x,y:t}));return l.areaPath(e,r,n??`linear`)}function buildPathFromPoints(e,t){return e.length===0?``:t===`monotone`?l.monotonePath(e):t===`step`?l.stepPath(e):l.linePath(e)}function isStackData(e){return e.length>0&&e[0]!==null&&typeof e[0]==`object`}function buildRoundedStackRect(e,t,n,r,i,a,o){let s=Math.min(i,n/2,r/2),c=a?s:0,l=a?s:0,u=o?s:0,d=o?s:0;return[`M${e+c},${t}`,`H${e+n-u}`,u?`Q${e+n},${t} ${e+n},${t+u}`:``,`V${t+r-d}`,d?`Q${e+n},${t+r} ${e+n-d},${t+r}`:``,`H${e+l}`,l?`Q${e},${t+r} ${e},${t+r-l}`:``,`V${t+c}`,c?`Q${e},${t} ${e+c},${t}`:``,`Z`].filter(Boolean).join(``)}function defaultStackColor(e){return`var(--prism-color-${e%8+1})`}function createSparkline(l,d){let f=d.variant??`line`,p=d.color??`var(--prism-color-1)`,m=d.curve??`linear`,h=d.strokeWidth??1.5,g=d.fillOpacity,_=d.showEndPoint??!0,v=c.uniqueId(`prism-spark-fill`),y=t.createTappers(),b=a.resolveMotion(d.transition),x=i.resolveEasing(b.easing),S=d.data,C=null,w=null,T=r.createChartBase(l,{a11y:d.a11y,margin:{bottom:0,left:0,right:0,top:0}},()=>{y.emit({height:T.dimensions.height,type:`resize`,width:T.dimensions.width}),renderAll()}),{svg:E}=T;E.classList.add(`prism-sparkline`);let D=e.createSvgElement(`g`,{class:`prism-spark-inner`});E.appendChild(D);let cleanupInteraction;function plotArea(){let{height:e,width:t}=T.dimensions,n=f===`line`||f===`area`?u:0;return{h:Math.max(1,e-n*2),inset:n,w:Math.max(1,t-n*2)}}function animateValues(e,t,n){w?.();let r=C?.length===e.length?C:e.map(()=>t);if(r.every((t,n)=>t===e[n])||b.duration===0){C=e,n(e);return}w=s.startTween({count:1,duration:b.duration,easing:x,onFrame:t=>{let i=t(0),a=e.map((e,t)=>o.tweenNumber(r[t],e,i));C=a,n(a)},signal:O.signal}),C=r,n(r)}function renderAll(){let{height:t,width:n}=T.dimensions,r=plotArea();for(;D.firstChild;)D.removeChild(D.firstChild);if(D.setAttribute(`transform`,`translate(${r.inset},${r.inset})`),S.length===0){C=null;return}if(!isStackData(S)&&S.some(e=>!Number.isFinite(e)),f===`stack`&&isStackData(S)){let r=e.createSvgElement(`g`,{class:`prism-spark-stack`});D.appendChild(r);let i=d.cornerRadius??4,a=S,o=a.reduce((e,t)=>e+Math.max(0,t.value),0),s=a.map((t,n)=>{let i=e.createSvgElement(`path`,{class:`prism-spark-stack-segment`});return e.setAttributes(i,{fill:t.color??defaultStackColor(n)}),r.appendChild(i),i});o>0?animateValues(a.map(e=>Math.max(0,e.value)),0,e=>{let r=e.reduce((e,t)=>e+t,0)||1,a=(d.padPixels??0)/2,o=0;e.forEach((c,l)=>{let u=Math.round(o);o+=c/r*n;let d=l===e.length-1?n:Math.round(o),f=l===0,p=l===e.length-1,m=u+(f?0:a),h=Math.max(0,d-u-(f?0:a)-(p?0:a));s[l]?.setAttribute(`d`,buildRoundedStackRect(m,0,h,t,i,f,p))})}):(w?.(),C=null)}else if(f===`bar`){let r=e.createSvgElement(`g`,{class:`prism-spark-bars`});D.appendChild(r);let i=S,a=Math.min(0,...i),o=Math.max(...i)-a||1,s=Math.max(1,n/i.length-1),c=n/i.length,l=i.map(()=>{let t=e.createSvgElement(`rect`,{class:`prism-spark-bar`,fill:p});return r.appendChild(t),t});animateValues(i,a,n=>{for(let[r,i]of l.entries()){let l=Math.max(1,(n[r]-a)/o*t);e.setAttributes(i,{height:l,width:s,x:r*c,y:t-l})}})}else{let t=S,n=Math.min(...t),i=Math.max(...t)-n||1,a=r.w/Math.max(1,t.length-1),pointsFromValues=e=>e.map((e,t)=>({x:t*a,y:r.h-(e-n)/i*r.h})),o=null;if(f===`area`){let t=e.createSvgElement(`defs`),n=e.createSvgElement(`linearGradient`,{id:v,x1:0,x2:0,y1:0,y2:1});for(let[t,r]of[[0,`prism-spark-stop-top`],[1,`prism-spark-stop-bottom`]]){let i=e.createSvgElement(`stop`,{class:r,offset:t,"stop-color":p});i.style.stopColor=p,n.appendChild(i)}t.appendChild(n),D.appendChild(t),o=e.createSvgElement(`path`,{class:`prism-spark-fill`}),e.setAttributes(o,{fill:`url(#${v})`,stroke:`none`}),o.style.fillOpacity=g===void 0?``:String(g),D.appendChild(o)}let s=e.createSvgElement(`path`,{class:`prism-spark-line`});e.setAttributes(s,{fill:`none`,stroke:p,"stroke-width":h}),D.appendChild(s);let c=_&&t.length>0?e.createSvgElement(`circle`,{class:`prism-spark-end`,fill:p,r:2.5}):null;c&&D.appendChild(c),animateValues(t,n,t=>{let n=pointsFromValues(t);e.setAttributes(s,{d:buildPathFromPoints(n,m)}),o&&e.setAttributes(o,{d:buildAreaPathFromPoints(n,r.h,m)});let i=n.at(-1);c&&i&&e.setAttributes(c,{cx:i.x,cy:i.y})})}isStackData(S)||attachInteraction(S)}function attachInteraction(t){if(cleanupInteraction?.(),cleanupInteraction=void 0,!d.onHover&&!d.onClick||t.length<=1)return;let{h:n,inset:r,w:i}=plotArea();E.style.cursor=`crosshair`;let a=i/(t.length-1),o=f===`bar`?[]:buildTopPoints(t,i,n),s=e.createSvgElement(`circle`,{class:`prism-spark-marker`,fill:p,r:3.5}),indexAt=e=>Math.max(0,Math.min(t.length-1,Math.round((e-E.getBoundingClientRect().left-r)/a)));s.style.display=`none`,D.appendChild(s);let handleMove=n=>{let r=indexAt(n.clientX),i=o[r];i&&(e.setAttributes(s,{cx:i.x,cy:i.y}),s.style.display=``),d.onHover?.({index:r,originalEvent:n,value:t[r]})},handleLeave=()=>{s.style.display=`none`,d.onHover?.(null)},handleClick=e=>{if(!d.onClick)return;let n=indexAt(e.clientX);d.onClick({index:n,originalEvent:e,value:t[n]})};E.addEventListener(`mousemove`,handleMove),E.addEventListener(`mouseleave`,handleLeave),E.addEventListener(`click`,handleClick),cleanupInteraction=()=>{E.removeEventListener(`mousemove`,handleMove),E.removeEventListener(`mouseleave`,handleLeave),E.removeEventListener(`click`,handleClick)}}let O=new AbortController,k=!1;try{return renderAll(),{get disposalSignal(){return O.signal},dispose(){k||(k=!0,y.emit({type:`dispose`}),y.stop(),O.abort(),cleanupInteraction?.(),T.dispose())},get disposed(){return k},el:E,tap:y.tap,update(e){if(k)throw new n.PrismRenderError(`Cannot update a disposed chart.`);S=e,renderAll()},[Symbol.dispose](){this.dispose()}}}catch(e){throw O.abort(),cleanupInteraction?.(),T.dispose(),e instanceof n.PrismRenderError?e:new n.PrismRenderError(`Failed to render chart.`,{cause:e})}}exports.createSparkline=createSparkline;
1
+ require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../_tappers.cjs"),n=require("../../errors.cjs"),r=require("../../core/chart-base.cjs"),i=require("../../animation/easing.cjs"),a=require("../../animation/motion.cjs"),o=require("../../animation/tween.cjs"),s=require("../../animation/transition.cjs"),c=require("../../core/ids.cjs"),l=require("../../svg/path.cjs");var u=5;function buildTopPoints(e,t,n){if(e.length===0)return[];let r=t/Math.max(1,e.length-1),i=Math.min(...e),a=Math.max(...e)-i||1;return e.map((e,t)=>({x:t*r,y:n-(e-i)/a*n}))}function buildAreaPathFromPoints(e,t,n){if(e.length===0)return``;let r=e.map(e=>({x:e.x,y:t}));return l.areaPath(e,r,n??`linear`)}function buildPathFromPoints(e,t){return e.length===0?``:t===`monotone`?l.monotonePath(e):t===`step`?l.stepPath(e):l.linePath(e)}function isStackData(e){return e.length>0&&e[0]!==null&&typeof e[0]==`object`}function buildRoundedStackRect(e,t,n,r,i,a,o){let s=Math.min(i,n/2,r/2),c=a?s:0,l=a?s:0,u=o?s:0,d=o?s:0;return[`M${e+c},${t}`,`H${e+n-u}`,u?`Q${e+n},${t} ${e+n},${t+u}`:``,`V${t+r-d}`,d?`Q${e+n},${t+r} ${e+n-d},${t+r}`:``,`H${e+l}`,l?`Q${e},${t+r} ${e},${t+r-l}`:``,`V${t+c}`,c?`Q${e},${t} ${e+c},${t}`:``,`Z`].filter(Boolean).join(``)}function defaultStackColor(e){return`var(--prism-color-${e%8+1})`}function createSparkline(l,d){let f=d.variant??`line`,p=d.color??`var(--prism-color-1)`,m=d.curve??`linear`,h=d.strokeWidth??1.5,g=d.fillOpacity,_=d.showEndPoint??!0,v=c.uniqueId(`prism-spark-fill`),y=t.createTappers(),b=a.resolveMotion(d.transition),x=i.resolveEasing(b.easing),S=d.data,C=null,w=null,T=r.createChartBase(l,{a11y:d.a11y,margin:{bottom:0,left:0,right:0,top:0}},()=>{y.emit({height:T.dimensions.height,type:`resize`,width:T.dimensions.width}),renderAll()}),{svg:E}=T;E.classList.add(`prism-sparkline`);let D=e.createSvgElement(`g`,{class:`prism-spark-inner`});E.appendChild(D);let cleanupInteraction;function plotArea(){let{height:e,width:t}=T.dimensions,n=f===`line`||f===`area`?u:0;return{h:Math.max(1,e-n*2),inset:n,w:Math.max(1,t-n*2)}}function animateValues(e,t,n){w?.();let r=C?.length===e.length?C:e.map(()=>t);r.every((t,n)=>t===e[n])||b.duration===0?(C=e,n(e)):(w=s.startTween({count:1,duration:b.duration,easing:x,onFrame:t=>{let i=t(0),a=e.map((e,t)=>o.tweenNumber(r[t],e,i));C=a,n(a)},signal:O.signal}),C=r,n(r))}function renderAll(){let{height:t,width:n}=T.dimensions,r=plotArea();for(;D.firstChild;)D.removeChild(D.firstChild);if(D.setAttribute(`transform`,`translate(${r.inset},${r.inset})`),S.length===0)C=null;else{if(!isStackData(S)&&S.some(e=>!Number.isFinite(e)),f===`stack`&&isStackData(S)){let r=e.createSvgElement(`g`,{class:`prism-spark-stack`});D.appendChild(r);let i=d.cornerRadius??4,a=S,o=a.reduce((e,t)=>e+Math.max(0,t.value),0),s=a.map((t,n)=>{let i=e.createSvgElement(`path`,{class:`prism-spark-stack-segment`});return e.setAttributes(i,{fill:t.color??defaultStackColor(n)}),r.appendChild(i),i});o>0?animateValues(a.map(e=>Math.max(0,e.value)),0,e=>{let r=e.reduce((e,t)=>e+t,0)||1,a=(d.padPixels??0)/2,o=0;e.forEach((c,l)=>{let u=Math.round(o);o+=c/r*n;let d=l===e.length-1?n:Math.round(o),f=l===0,p=l===e.length-1,m=u+(f?0:a),h=Math.max(0,d-u-(f?0:a)-(p?0:a));s[l]?.setAttribute(`d`,buildRoundedStackRect(m,0,h,t,i,f,p))})}):(w?.(),C=null)}else if(f===`bar`){let r=e.createSvgElement(`g`,{class:`prism-spark-bars`});D.appendChild(r);let i=S,a=Math.min(0,...i),o=Math.max(...i)-a||1,s=Math.max(1,n/i.length-1),c=n/i.length,l=i.map(()=>{let t=e.createSvgElement(`rect`,{class:`prism-spark-bar`,fill:p});return r.appendChild(t),t});animateValues(i,a,n=>{for(let[r,i]of l.entries()){let l=Math.max(1,(n[r]-a)/o*t);e.setAttributes(i,{height:l,width:s,x:r*c,y:t-l})}})}else{let t=S,n=Math.min(...t),i=Math.max(...t)-n||1,a=r.w/Math.max(1,t.length-1),pointsFromValues=e=>e.map((e,t)=>({x:t*a,y:r.h-(e-n)/i*r.h})),o=null;if(f===`area`){let t=e.createSvgElement(`defs`),n=e.createSvgElement(`linearGradient`,{id:v,x1:0,x2:0,y1:0,y2:1});for(let[t,r]of[[0,`prism-spark-stop-top`],[1,`prism-spark-stop-bottom`]]){let i=e.createSvgElement(`stop`,{class:r,offset:t,"stop-color":p});i.style.stopColor=p,n.appendChild(i)}t.appendChild(n),D.appendChild(t),o=e.createSvgElement(`path`,{class:`prism-spark-fill`}),e.setAttributes(o,{fill:`url(#${v})`,stroke:`none`}),o.style.fillOpacity=g===void 0?``:String(g),D.appendChild(o)}let s=e.createSvgElement(`path`,{class:`prism-spark-line`});e.setAttributes(s,{fill:`none`,stroke:p,"stroke-width":h}),D.appendChild(s);let c=_&&t.length>0?e.createSvgElement(`circle`,{class:`prism-spark-end`,fill:p,r:2.5}):null;c&&D.appendChild(c),animateValues(t,n,t=>{let n=pointsFromValues(t);e.setAttributes(s,{d:buildPathFromPoints(n,m)}),o&&e.setAttributes(o,{d:buildAreaPathFromPoints(n,r.h,m)});let i=n.at(-1);c&&i&&e.setAttributes(c,{cx:i.x,cy:i.y})})}isStackData(S)||attachInteraction(S)}}function attachInteraction(t){if(cleanupInteraction?.(),cleanupInteraction=void 0,!d.onHover&&!d.onClick||t.length<=1)return;let{h:n,inset:r,w:i}=plotArea();E.style.cursor=`crosshair`;let a=i/(t.length-1),o=f===`bar`?[]:buildTopPoints(t,i,n),s=e.createSvgElement(`circle`,{class:`prism-spark-marker`,fill:p,r:3.5}),indexAt=e=>Math.max(0,Math.min(t.length-1,Math.round((e-E.getBoundingClientRect().left-r)/a)));s.style.display=`none`,D.appendChild(s);let handleMove=n=>{let r=indexAt(n.clientX),i=o[r];i&&(e.setAttributes(s,{cx:i.x,cy:i.y}),s.style.display=``),d.onHover?.({index:r,originalEvent:n,value:t[r]})},handleLeave=()=>{s.style.display=`none`,d.onHover?.(null)},handleClick=e=>{if(!d.onClick)return;let n=indexAt(e.clientX);d.onClick({index:n,originalEvent:e,value:t[n]})};E.addEventListener(`mousemove`,handleMove),E.addEventListener(`mouseleave`,handleLeave),E.addEventListener(`click`,handleClick),cleanupInteraction=()=>{E.removeEventListener(`mousemove`,handleMove),E.removeEventListener(`mouseleave`,handleLeave),E.removeEventListener(`click`,handleClick)}}let O=new AbortController,k=!1;try{return renderAll(),{get disposalSignal(){return O.signal},dispose(){k||(k=!0,y.emit({type:`dispose`}),y.stop(),O.abort(),cleanupInteraction?.(),T.dispose())},get disposed(){return k},el:E,tap:y.tap,update(e){if(k)throw new n.PrismRenderError(`Cannot update a disposed chart.`);S=e,renderAll()},[Symbol.dispose](){this.dispose()}}}catch(e){throw O.abort(),cleanupInteraction?.(),T.dispose(),e instanceof n.PrismRenderError?e:new n.PrismRenderError(`Failed to render chart.`,{cause:e})}}exports.createSparkline=createSparkline;
2
2
  //# sourceMappingURL=sparkline.cjs.map