@vielzeug/prism 2.2.6 → 26.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/README.md +19 -40
  2. package/dist/_dev.cjs +1 -1
  3. package/dist/_dev.cjs.map +1 -1
  4. package/dist/_dev.js +1 -6
  5. package/dist/_dev.js.map +1 -1
  6. package/dist/animation/easing.cjs +1 -1
  7. package/dist/animation/easing.cjs.map +1 -1
  8. package/dist/animation/easing.js +1 -13
  9. package/dist/animation/easing.js.map +1 -1
  10. package/dist/animation/motion.cjs +1 -1
  11. package/dist/animation/motion.cjs.map +1 -1
  12. package/dist/animation/motion.js +1 -12
  13. package/dist/animation/motion.js.map +1 -1
  14. package/dist/animation/transition.cjs +1 -1
  15. package/dist/animation/transition.cjs.map +1 -1
  16. package/dist/animation/transition.js +1 -28
  17. package/dist/animation/transition.js.map +1 -1
  18. package/dist/animation/tween.cjs +1 -1
  19. package/dist/animation/tween.cjs.map +1 -1
  20. package/dist/animation/tween.js +1 -7
  21. package/dist/animation/tween.js.map +1 -1
  22. package/dist/axes/axis.cjs +1 -1
  23. package/dist/axes/axis.cjs.map +1 -1
  24. package/dist/axes/axis.d.ts +1 -0
  25. package/dist/axes/axis.d.ts.map +1 -1
  26. package/dist/axes/axis.js +1 -59
  27. package/dist/axes/axis.js.map +1 -1
  28. package/dist/axes/grid.cjs +1 -1
  29. package/dist/axes/grid.cjs.map +1 -1
  30. package/dist/axes/grid.js +1 -29
  31. package/dist/axes/grid.js.map +1 -1
  32. package/dist/axes/scale-utils.cjs +1 -1
  33. package/dist/axes/scale-utils.cjs.map +1 -1
  34. package/dist/axes/scale-utils.js +1 -10
  35. package/dist/axes/scale-utils.js.map +1 -1
  36. package/dist/charts/area/area-chart.cjs +1 -1
  37. package/dist/charts/area/area-chart.cjs.map +1 -1
  38. package/dist/charts/area/area-chart.d.ts +2 -2
  39. package/dist/charts/area/area-chart.d.ts.map +1 -1
  40. package/dist/charts/area/area-chart.js +1 -61
  41. package/dist/charts/area/area-chart.js.map +1 -1
  42. package/dist/charts/area/area-renderer.cjs +1 -1
  43. package/dist/charts/area/area-renderer.cjs.map +1 -1
  44. package/dist/charts/area/area-renderer.d.ts +2 -2
  45. package/dist/charts/area/area-renderer.d.ts.map +1 -1
  46. package/dist/charts/area/area-renderer.js +1 -73
  47. package/dist/charts/area/area-renderer.js.map +1 -1
  48. package/dist/charts/bar/bar-chart.cjs +1 -1
  49. package/dist/charts/bar/bar-chart.cjs.map +1 -1
  50. package/dist/charts/bar/bar-chart.d.ts +2 -2
  51. package/dist/charts/bar/bar-chart.d.ts.map +1 -1
  52. package/dist/charts/bar/bar-chart.js +1 -172
  53. package/dist/charts/bar/bar-chart.js.map +1 -1
  54. package/dist/charts/bar/bar-hit-test.cjs +1 -1
  55. package/dist/charts/bar/bar-hit-test.cjs.map +1 -1
  56. package/dist/charts/bar/bar-hit-test.js +1 -28
  57. package/dist/charts/bar/bar-hit-test.js.map +1 -1
  58. package/dist/charts/bar/bar-renderer.cjs +1 -1
  59. package/dist/charts/bar/bar-renderer.cjs.map +1 -1
  60. package/dist/charts/bar/bar-renderer.js +1 -106
  61. package/dist/charts/bar/bar-renderer.js.map +1 -1
  62. package/dist/charts/line/line-chart.cjs +1 -1
  63. package/dist/charts/line/line-chart.cjs.map +1 -1
  64. package/dist/charts/line/line-chart.d.ts +2 -2
  65. package/dist/charts/line/line-chart.d.ts.map +1 -1
  66. package/dist/charts/line/line-chart.js +1 -62
  67. package/dist/charts/line/line-chart.js.map +1 -1
  68. package/dist/charts/line/line-renderer.cjs +1 -1
  69. package/dist/charts/line/line-renderer.cjs.map +1 -1
  70. package/dist/charts/line/line-renderer.d.ts +2 -2
  71. package/dist/charts/line/line-renderer.d.ts.map +1 -1
  72. package/dist/charts/line/line-renderer.js +1 -100
  73. package/dist/charts/line/line-renderer.js.map +1 -1
  74. package/dist/charts/pie/pie-chart.cjs +1 -1
  75. package/dist/charts/pie/pie-chart.cjs.map +1 -1
  76. package/dist/charts/pie/pie-chart.d.ts +2 -2
  77. package/dist/charts/pie/pie-chart.d.ts.map +1 -1
  78. package/dist/charts/pie/pie-chart.js +1 -160
  79. package/dist/charts/pie/pie-chart.js.map +1 -1
  80. package/dist/charts/pie/pie-renderer.cjs +1 -1
  81. package/dist/charts/pie/pie-renderer.cjs.map +1 -1
  82. package/dist/charts/pie/pie-renderer.js +1 -76
  83. package/dist/charts/pie/pie-renderer.js.map +1 -1
  84. package/dist/charts/sparkline/sparkline.cjs +1 -1
  85. package/dist/charts/sparkline/sparkline.cjs.map +1 -1
  86. package/dist/charts/sparkline/sparkline.d.ts +2 -2
  87. package/dist/charts/sparkline/sparkline.d.ts.map +1 -1
  88. package/dist/charts/sparkline/sparkline.js +1 -192
  89. package/dist/charts/sparkline/sparkline.js.map +1 -1
  90. package/dist/core/cartesian-model.cjs +1 -1
  91. package/dist/core/cartesian-model.cjs.map +1 -1
  92. package/dist/core/cartesian-model.js +1 -30
  93. package/dist/core/cartesian-model.js.map +1 -1
  94. package/dist/core/cartesian-scales.cjs +1 -1
  95. package/dist/core/cartesian-scales.cjs.map +1 -1
  96. package/dist/core/cartesian-scales.js +1 -37
  97. package/dist/core/cartesian-scales.js.map +1 -1
  98. package/dist/core/chart-base.cjs +1 -1
  99. package/dist/core/chart-base.cjs.map +1 -1
  100. package/dist/core/chart-base.d.ts +2 -4
  101. package/dist/core/chart-base.d.ts.map +1 -1
  102. package/dist/core/chart-base.js +1 -62
  103. package/dist/core/chart-base.js.map +1 -1
  104. package/dist/core/chart-scaffold.cjs +1 -1
  105. package/dist/core/chart-scaffold.cjs.map +1 -1
  106. package/dist/core/chart-scaffold.d.ts +9 -10
  107. package/dist/core/chart-scaffold.d.ts.map +1 -1
  108. package/dist/core/chart-scaffold.js +1 -101
  109. package/dist/core/chart-scaffold.js.map +1 -1
  110. package/dist/core/index.d.ts +0 -1
  111. package/dist/core/index.d.ts.map +1 -1
  112. package/dist/core/layout.cjs +1 -1
  113. package/dist/core/layout.cjs.map +1 -1
  114. package/dist/core/layout.js +1 -22
  115. package/dist/core/layout.js.map +1 -1
  116. package/dist/core/responsive.cjs +1 -1
  117. package/dist/core/responsive.cjs.map +1 -1
  118. package/dist/core/responsive.js +1 -19
  119. package/dist/core/responsive.js.map +1 -1
  120. package/dist/devtools.cjs +1 -1
  121. package/dist/devtools.cjs.map +1 -1
  122. package/dist/devtools.js +1 -18
  123. package/dist/devtools.js.map +1 -1
  124. package/dist/errors.cjs +1 -1
  125. package/dist/errors.cjs.map +1 -1
  126. package/dist/errors.js +1 -9
  127. package/dist/errors.js.map +1 -1
  128. package/dist/index.cjs +1 -1
  129. package/dist/index.d.ts +2 -6
  130. package/dist/index.d.ts.map +1 -1
  131. package/dist/index.js +1 -12
  132. package/dist/interaction/crosshair.cjs +1 -1
  133. package/dist/interaction/crosshair.cjs.map +1 -1
  134. package/dist/interaction/crosshair.js +1 -45
  135. package/dist/interaction/crosshair.js.map +1 -1
  136. package/dist/interaction/events.cjs +1 -1
  137. package/dist/interaction/events.cjs.map +1 -1
  138. package/dist/interaction/events.js +1 -11
  139. package/dist/interaction/events.js.map +1 -1
  140. package/dist/interaction/legend.cjs +1 -1
  141. package/dist/interaction/legend.cjs.map +1 -1
  142. package/dist/interaction/legend.js +1 -30
  143. package/dist/interaction/legend.js.map +1 -1
  144. package/dist/interaction/series-interaction.cjs +1 -1
  145. package/dist/interaction/series-interaction.cjs.map +1 -1
  146. package/dist/interaction/series-interaction.js +1 -97
  147. package/dist/interaction/series-interaction.js.map +1 -1
  148. package/dist/interaction/tooltip.cjs +1 -1
  149. package/dist/interaction/tooltip.cjs.map +1 -1
  150. package/dist/interaction/tooltip.d.ts.map +1 -1
  151. package/dist/interaction/tooltip.js +1 -63
  152. package/dist/interaction/tooltip.js.map +1 -1
  153. package/dist/prism.cjs +1 -1
  154. package/dist/prism.cjs.map +1 -1
  155. package/dist/prism.iife.js +1 -1
  156. package/dist/prism.iife.js.map +1 -1
  157. package/dist/prism.js +1 -1
  158. package/dist/prism.js.map +1 -1
  159. package/dist/scales/band.cjs +1 -1
  160. package/dist/scales/band.cjs.map +1 -1
  161. package/dist/scales/band.js +1 -39
  162. package/dist/scales/band.js.map +1 -1
  163. package/dist/scales/linear.cjs +1 -1
  164. package/dist/scales/linear.cjs.map +1 -1
  165. package/dist/scales/linear.js +1 -43
  166. package/dist/scales/linear.js.map +1 -1
  167. package/dist/scales/time.cjs +1 -1
  168. package/dist/scales/time.cjs.map +1 -1
  169. package/dist/scales/time.js +1 -61
  170. package/dist/scales/time.js.map +1 -1
  171. package/dist/svg/element.cjs +1 -1
  172. package/dist/svg/element.cjs.map +1 -1
  173. package/dist/svg/element.js +1 -22
  174. package/dist/svg/element.js.map +1 -1
  175. package/dist/svg/path.cjs +1 -1
  176. package/dist/svg/path.cjs.map +1 -1
  177. package/dist/svg/path.js +1 -48
  178. package/dist/svg/path.js.map +1 -1
  179. package/dist/svg/text.cjs +1 -1
  180. package/dist/svg/text.cjs.map +1 -1
  181. package/dist/svg/text.js +1 -9
  182. package/dist/svg/text.js.map +1 -1
  183. package/dist/theme/index.cjs +1 -1
  184. package/dist/theme/index.cjs.map +1 -1
  185. package/dist/theme/index.js +1 -19
  186. package/dist/theme/index.js.map +1 -1
  187. package/dist/types.d.ts +24 -48
  188. package/dist/types.d.ts.map +1 -1
  189. package/package.json +8 -9
  190. package/dist/core/resolve.cjs +0 -2
  191. package/dist/core/resolve.cjs.map +0 -1
  192. package/dist/core/resolve.d.ts +0 -9
  193. package/dist/core/resolve.d.ts.map +0 -1
  194. package/dist/core/resolve.js +0 -15
  195. package/dist/core/resolve.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"crosshair.cjs","names":[],"sources":["../../src/interaction/crosshair.ts"],"sourcesContent":["import { createSvgElement, setAttributes } from '../svg/element';\nimport type { CrosshairConfig } from '../types';\n\nexport interface CrosshairState {\n hide(): void;\n /**\n * @param announceText Optional text describing the value at the crosshair position,\n * announced via the crosshair's ARIA live region — used when no tooltip is also shown.\n */\n show(x: number, y: number, width: number, height: number, announceText?: string): void;\n /** When `false`, the crosshair follows the raw mouse position instead of snapping to the nearest datum. */\n readonly snap: boolean;\n}\n\nexport function createCrosshair(parent: SVGGElement, config?: CrosshairConfig | true): CrosshairState {\n const showVertical = config === true || config?.vertical !== false;\n const showHorizontal = config !== true && config?.horizontal === true;\n const snap = config === true || config?.snap !== false;\n\n const group = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-crosshair', style: 'display:none' });\n\n const vLine = showVertical\n ? createSvgElement('line', { class: 'prism-crosshair-v', 'stroke-dasharray': 'var(--prism-crosshair-dash, 4 2)' })\n : null;\n const hLine = showHorizontal\n ? createSvgElement('line', { class: 'prism-crosshair-h', 'stroke-dasharray': 'var(--prism-crosshair-dash, 4 2)' })\n : null;\n\n if (vLine) group.appendChild(vLine);\n\n if (hLine) group.appendChild(hLine);\n\n parent.appendChild(group);\n\n // Non-modal status region for screen readers — the visual crosshair lines above are\n // aria-hidden (purely decorative), so the current value is announced here instead.\n // Positioned off-canvas rather than visually hidden via CSS so it works without prism's stylesheet.\n const liveRegion = createSvgElement('text', {\n 'aria-live': 'polite',\n class: 'prism-crosshair-live',\n role: 'status',\n x: -9999,\n y: -9999,\n });\n\n parent.appendChild(liveRegion);\n\n return {\n hide() {\n group.style.display = 'none';\n liveRegion.textContent = '';\n },\n show(x: number, y: number, width: number, height: number, announceText?: string) {\n group.style.display = '';\n\n if (vLine) setAttributes(vLine, { x1: x, x2: x, y1: 0, y2: height });\n\n if (hLine) setAttributes(hLine, { x1: 0, x2: width, y1: y, y2: y });\n\n if (announceText !== undefined) liveRegion.textContent = announceText;\n },\n snap,\n };\n}\n"],"mappings":"sCAcA,SAAgB,EAAgB,EAAqB,EAAiD,CACpG,IAAM,EAAe,IAAW,IAAQ,GAAQ,WAAa,GACvD,EAAiB,IAAW,IAAQ,GAAQ,aAAe,GAC3D,EAAO,IAAW,IAAQ,GAAQ,OAAS,GAE3C,EAAQ,EAAA,iBAAiB,IAAK,CAAE,cAAe,OAAQ,MAAO,kBAAmB,MAAO,cAAe,CAAC,EAExG,EAAQ,EACV,EAAA,iBAAiB,OAAQ,CAAE,MAAO,oBAAqB,mBAAoB,kCAAmC,CAAC,EAC/G,KACE,EAAQ,EACV,EAAA,iBAAiB,OAAQ,CAAE,MAAO,oBAAqB,mBAAoB,kCAAmC,CAAC,EAC/G,KAEA,GAAO,EAAM,YAAY,CAAK,EAE9B,GAAO,EAAM,YAAY,CAAK,EAElC,EAAO,YAAY,CAAK,EAKxB,IAAM,EAAa,EAAA,iBAAiB,OAAQ,CAC1C,YAAa,SACb,MAAO,uBACP,KAAM,SACN,EAAG,MACH,EAAG,KACL,CAAC,EAID,OAFA,EAAO,YAAY,CAAU,EAEtB,CACL,MAAO,CACL,EAAM,MAAM,QAAU,OACtB,EAAW,YAAc,EAC3B,EACA,KAAK,EAAW,EAAW,EAAe,EAAgB,EAAuB,CAC/E,EAAM,MAAM,QAAU,GAElB,GAAO,EAAA,cAAc,EAAO,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,GAAI,CAAO,CAAC,EAE/D,GAAO,EAAA,cAAc,EAAO,CAAE,GAAI,EAAG,GAAI,EAAO,GAAI,EAAG,GAAI,CAAE,CAAC,EAE9D,IAAiB,IAAA,KAAW,EAAW,YAAc,EAC3D,EACA,MACF,CACF"}
1
+ {"version":3,"file":"crosshair.cjs","names":[],"sources":["../../src/interaction/crosshair.ts"],"sourcesContent":["import { createSvgElement, setAttributes } from '../svg/element';\nimport type { CrosshairConfig } from '../types';\n\nexport interface CrosshairState {\n hide(): void;\n /**\n * @param announceText Optional text describing the value at the crosshair position,\n * announced via the crosshair's ARIA live region — used when no tooltip is also shown.\n */\n show(x: number, y: number, width: number, height: number, announceText?: string): void;\n /** When `false`, the crosshair follows the raw mouse position instead of snapping to the nearest datum. */\n readonly snap: boolean;\n}\n\nexport function createCrosshair(parent: SVGGElement, config?: CrosshairConfig | true): CrosshairState {\n const showVertical = config === true || config?.vertical !== false;\n const showHorizontal = config !== true && config?.horizontal === true;\n const snap = config === true || config?.snap !== false;\n\n const group = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-crosshair', style: 'display:none' });\n\n const vLine = showVertical\n ? createSvgElement('line', { class: 'prism-crosshair-v', 'stroke-dasharray': 'var(--prism-crosshair-dash, 4 2)' })\n : null;\n const hLine = showHorizontal\n ? createSvgElement('line', { class: 'prism-crosshair-h', 'stroke-dasharray': 'var(--prism-crosshair-dash, 4 2)' })\n : null;\n\n if (vLine) group.appendChild(vLine);\n\n if (hLine) group.appendChild(hLine);\n\n parent.appendChild(group);\n\n // Non-modal status region for screen readers — the visual crosshair lines above are\n // aria-hidden (purely decorative), so the current value is announced here instead.\n // Positioned off-canvas rather than visually hidden via CSS so it works without prism's stylesheet.\n const liveRegion = createSvgElement('text', {\n 'aria-live': 'polite',\n class: 'prism-crosshair-live',\n role: 'status',\n x: -9999,\n y: -9999,\n });\n\n parent.appendChild(liveRegion);\n\n return {\n hide() {\n group.style.display = 'none';\n liveRegion.textContent = '';\n },\n show(x: number, y: number, width: number, height: number, announceText?: string) {\n group.style.display = '';\n\n if (vLine) setAttributes(vLine, { x1: x, x2: x, y1: 0, y2: height });\n\n if (hLine) setAttributes(hLine, { x1: 0, x2: width, y1: y, y2: y });\n\n if (announceText !== undefined) liveRegion.textContent = announceText;\n },\n snap,\n };\n}\n"],"mappings":"sCAcA,SAAgB,gBAAgB,EAAqB,EAAiD,CACpG,IAAM,EAAe,IAAW,IAAQ,GAAQ,WAAa,GACvD,EAAiB,IAAW,IAAQ,GAAQ,aAAe,GAC3D,EAAO,IAAW,IAAQ,GAAQ,OAAS,GAE3C,EAAQ,EAAA,iBAAiB,IAAK,CAAE,cAAe,OAAQ,MAAO,kBAAmB,MAAO,cAAe,CAAC,EAExG,EAAQ,EACV,EAAA,iBAAiB,OAAQ,CAAE,MAAO,oBAAqB,mBAAoB,kCAAmC,CAAC,EAC/G,KACE,EAAQ,EACV,EAAA,iBAAiB,OAAQ,CAAE,MAAO,oBAAqB,mBAAoB,kCAAmC,CAAC,EAC/G,KAEA,GAAO,EAAM,YAAY,CAAK,EAE9B,GAAO,EAAM,YAAY,CAAK,EAElC,EAAO,YAAY,CAAK,EAKxB,IAAM,EAAa,EAAA,iBAAiB,OAAQ,CAC1C,YAAa,SACb,MAAO,uBACP,KAAM,SACN,EAAG,MACH,EAAG,KACL,CAAC,EAID,OAFA,EAAO,YAAY,CAAU,EAEtB,CACL,MAAO,CACL,EAAM,MAAM,QAAU,OACtB,EAAW,YAAc,EAC3B,EACA,KAAK,EAAW,EAAW,EAAe,EAAgB,EAAuB,CAC/E,EAAM,MAAM,QAAU,GAElB,GAAO,EAAA,cAAc,EAAO,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,GAAI,CAAO,CAAC,EAE/D,GAAO,EAAA,cAAc,EAAO,CAAE,GAAI,EAAG,GAAI,EAAO,GAAI,EAAG,GAAI,CAAE,CAAC,EAE9D,IAAiB,IAAA,KAAW,EAAW,YAAc,EAC3D,EACA,MACF,CACF"}
@@ -1,46 +1,2 @@
1
- import { createSvgElement as e, setAttributes as t } from "../svg/element.js";
2
- //#region src/interaction/crosshair.ts
3
- function n(n, r) {
4
- let i = r === !0 || r?.vertical !== !1, a = r !== !0 && r?.horizontal === !0, o = r === !0 || r?.snap !== !1, s = e("g", {
5
- "aria-hidden": "true",
6
- class: "prism-crosshair",
7
- style: "display:none"
8
- }), c = i ? e("line", {
9
- class: "prism-crosshair-v",
10
- "stroke-dasharray": "var(--prism-crosshair-dash, 4 2)"
11
- }) : null, l = a ? e("line", {
12
- class: "prism-crosshair-h",
13
- "stroke-dasharray": "var(--prism-crosshair-dash, 4 2)"
14
- }) : null;
15
- c && s.appendChild(c), l && s.appendChild(l), n.appendChild(s);
16
- let u = e("text", {
17
- "aria-live": "polite",
18
- class: "prism-crosshair-live",
19
- role: "status",
20
- x: -9999,
21
- y: -9999
22
- });
23
- return n.appendChild(u), {
24
- hide() {
25
- s.style.display = "none", u.textContent = "";
26
- },
27
- show(e, n, r, i, a) {
28
- s.style.display = "", c && t(c, {
29
- x1: e,
30
- x2: e,
31
- y1: 0,
32
- y2: i
33
- }), l && t(l, {
34
- x1: 0,
35
- x2: r,
36
- y1: n,
37
- y2: n
38
- }), a !== void 0 && (u.textContent = a);
39
- },
40
- snap: o
41
- };
42
- }
43
- //#endregion
44
- export { n as createCrosshair };
45
-
1
+ import{createSvgElement as e,setAttributes as t}from"../svg/element.js";function createCrosshair(n,r){let i=r===!0||r?.vertical!==!1,a=r!==!0&&r?.horizontal===!0,o=r===!0||r?.snap!==!1,s=e(`g`,{"aria-hidden":`true`,class:`prism-crosshair`,style:`display:none`}),c=i?e(`line`,{class:`prism-crosshair-v`,"stroke-dasharray":`var(--prism-crosshair-dash, 4 2)`}):null,l=a?e(`line`,{class:`prism-crosshair-h`,"stroke-dasharray":`var(--prism-crosshair-dash, 4 2)`}):null;c&&s.appendChild(c),l&&s.appendChild(l),n.appendChild(s);let u=e(`text`,{"aria-live":`polite`,class:`prism-crosshair-live`,role:`status`,x:-9999,y:-9999});return n.appendChild(u),{hide(){s.style.display=`none`,u.textContent=``},show(e,n,r,i,a){s.style.display=``,c&&t(c,{x1:e,x2:e,y1:0,y2:i}),l&&t(l,{x1:0,x2:r,y1:n,y2:n}),a!==void 0&&(u.textContent=a)},snap:o}}export{createCrosshair};
46
2
  //# sourceMappingURL=crosshair.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"crosshair.js","names":[],"sources":["../../src/interaction/crosshair.ts"],"sourcesContent":["import { createSvgElement, setAttributes } from '../svg/element';\nimport type { CrosshairConfig } from '../types';\n\nexport interface CrosshairState {\n hide(): void;\n /**\n * @param announceText Optional text describing the value at the crosshair position,\n * announced via the crosshair's ARIA live region — used when no tooltip is also shown.\n */\n show(x: number, y: number, width: number, height: number, announceText?: string): void;\n /** When `false`, the crosshair follows the raw mouse position instead of snapping to the nearest datum. */\n readonly snap: boolean;\n}\n\nexport function createCrosshair(parent: SVGGElement, config?: CrosshairConfig | true): CrosshairState {\n const showVertical = config === true || config?.vertical !== false;\n const showHorizontal = config !== true && config?.horizontal === true;\n const snap = config === true || config?.snap !== false;\n\n const group = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-crosshair', style: 'display:none' });\n\n const vLine = showVertical\n ? createSvgElement('line', { class: 'prism-crosshair-v', 'stroke-dasharray': 'var(--prism-crosshair-dash, 4 2)' })\n : null;\n const hLine = showHorizontal\n ? createSvgElement('line', { class: 'prism-crosshair-h', 'stroke-dasharray': 'var(--prism-crosshair-dash, 4 2)' })\n : null;\n\n if (vLine) group.appendChild(vLine);\n\n if (hLine) group.appendChild(hLine);\n\n parent.appendChild(group);\n\n // Non-modal status region for screen readers — the visual crosshair lines above are\n // aria-hidden (purely decorative), so the current value is announced here instead.\n // Positioned off-canvas rather than visually hidden via CSS so it works without prism's stylesheet.\n const liveRegion = createSvgElement('text', {\n 'aria-live': 'polite',\n class: 'prism-crosshair-live',\n role: 'status',\n x: -9999,\n y: -9999,\n });\n\n parent.appendChild(liveRegion);\n\n return {\n hide() {\n group.style.display = 'none';\n liveRegion.textContent = '';\n },\n show(x: number, y: number, width: number, height: number, announceText?: string) {\n group.style.display = '';\n\n if (vLine) setAttributes(vLine, { x1: x, x2: x, y1: 0, y2: height });\n\n if (hLine) setAttributes(hLine, { x1: 0, x2: width, y1: y, y2: y });\n\n if (announceText !== undefined) liveRegion.textContent = announceText;\n },\n snap,\n };\n}\n"],"mappings":";;AAcA,SAAgB,EAAgB,GAAqB,GAAiD;CACpG,IAAM,IAAe,MAAW,MAAQ,GAAQ,aAAa,IACvD,IAAiB,MAAW,MAAQ,GAAQ,eAAe,IAC3D,IAAO,MAAW,MAAQ,GAAQ,SAAS,IAE3C,IAAQ,EAAiB,KAAK;EAAE,eAAe;EAAQ,OAAO;EAAmB,OAAO;CAAe,CAAC,GAExG,IAAQ,IACV,EAAiB,QAAQ;EAAE,OAAO;EAAqB,oBAAoB;CAAmC,CAAC,IAC/G,MACE,IAAQ,IACV,EAAiB,QAAQ;EAAE,OAAO;EAAqB,oBAAoB;CAAmC,CAAC,IAC/G;CAMJ,AAJI,KAAO,EAAM,YAAY,CAAK,GAE9B,KAAO,EAAM,YAAY,CAAK,GAElC,EAAO,YAAY,CAAK;CAKxB,IAAM,IAAa,EAAiB,QAAQ;EAC1C,aAAa;EACb,OAAO;EACP,MAAM;EACN,GAAG;EACH,GAAG;CACL,CAAC;CAID,OAFA,EAAO,YAAY,CAAU,GAEtB;EACL,OAAO;GAEL,AADA,EAAM,MAAM,UAAU,QACtB,EAAW,cAAc;EAC3B;EACA,KAAK,GAAW,GAAW,GAAe,GAAgB,GAAuB;GAO/E,AANA,EAAM,MAAM,UAAU,IAElB,KAAO,EAAc,GAAO;IAAE,IAAI;IAAG,IAAI;IAAG,IAAI;IAAG,IAAI;GAAO,CAAC,GAE/D,KAAO,EAAc,GAAO;IAAE,IAAI;IAAG,IAAI;IAAO,IAAI;IAAG,IAAI;GAAE,CAAC,GAE9D,MAAiB,KAAA,MAAW,EAAW,cAAc;EAC3D;EACA;CACF;AACF"}
1
+ {"version":3,"file":"crosshair.js","names":[],"sources":["../../src/interaction/crosshair.ts"],"sourcesContent":["import { createSvgElement, setAttributes } from '../svg/element';\nimport type { CrosshairConfig } from '../types';\n\nexport interface CrosshairState {\n hide(): void;\n /**\n * @param announceText Optional text describing the value at the crosshair position,\n * announced via the crosshair's ARIA live region — used when no tooltip is also shown.\n */\n show(x: number, y: number, width: number, height: number, announceText?: string): void;\n /** When `false`, the crosshair follows the raw mouse position instead of snapping to the nearest datum. */\n readonly snap: boolean;\n}\n\nexport function createCrosshair(parent: SVGGElement, config?: CrosshairConfig | true): CrosshairState {\n const showVertical = config === true || config?.vertical !== false;\n const showHorizontal = config !== true && config?.horizontal === true;\n const snap = config === true || config?.snap !== false;\n\n const group = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-crosshair', style: 'display:none' });\n\n const vLine = showVertical\n ? createSvgElement('line', { class: 'prism-crosshair-v', 'stroke-dasharray': 'var(--prism-crosshair-dash, 4 2)' })\n : null;\n const hLine = showHorizontal\n ? createSvgElement('line', { class: 'prism-crosshair-h', 'stroke-dasharray': 'var(--prism-crosshair-dash, 4 2)' })\n : null;\n\n if (vLine) group.appendChild(vLine);\n\n if (hLine) group.appendChild(hLine);\n\n parent.appendChild(group);\n\n // Non-modal status region for screen readers — the visual crosshair lines above are\n // aria-hidden (purely decorative), so the current value is announced here instead.\n // Positioned off-canvas rather than visually hidden via CSS so it works without prism's stylesheet.\n const liveRegion = createSvgElement('text', {\n 'aria-live': 'polite',\n class: 'prism-crosshair-live',\n role: 'status',\n x: -9999,\n y: -9999,\n });\n\n parent.appendChild(liveRegion);\n\n return {\n hide() {\n group.style.display = 'none';\n liveRegion.textContent = '';\n },\n show(x: number, y: number, width: number, height: number, announceText?: string) {\n group.style.display = '';\n\n if (vLine) setAttributes(vLine, { x1: x, x2: x, y1: 0, y2: height });\n\n if (hLine) setAttributes(hLine, { x1: 0, x2: width, y1: y, y2: y });\n\n if (announceText !== undefined) liveRegion.textContent = announceText;\n },\n snap,\n };\n}\n"],"mappings":"wEAcA,SAAgB,gBAAgB,EAAqB,EAAiD,CACpG,IAAM,EAAe,IAAW,IAAQ,GAAQ,WAAa,GACvD,EAAiB,IAAW,IAAQ,GAAQ,aAAe,GAC3D,EAAO,IAAW,IAAQ,GAAQ,OAAS,GAE3C,EAAQ,EAAiB,IAAK,CAAE,cAAe,OAAQ,MAAO,kBAAmB,MAAO,cAAe,CAAC,EAExG,EAAQ,EACV,EAAiB,OAAQ,CAAE,MAAO,oBAAqB,mBAAoB,kCAAmC,CAAC,EAC/G,KACE,EAAQ,EACV,EAAiB,OAAQ,CAAE,MAAO,oBAAqB,mBAAoB,kCAAmC,CAAC,EAC/G,KAEA,GAAO,EAAM,YAAY,CAAK,EAE9B,GAAO,EAAM,YAAY,CAAK,EAElC,EAAO,YAAY,CAAK,EAKxB,IAAM,EAAa,EAAiB,OAAQ,CAC1C,YAAa,SACb,MAAO,uBACP,KAAM,SACN,EAAG,MACH,EAAG,KACL,CAAC,EAID,OAFA,EAAO,YAAY,CAAU,EAEtB,CACL,MAAO,CACL,EAAM,MAAM,QAAU,OACtB,EAAW,YAAc,EAC3B,EACA,KAAK,EAAW,EAAW,EAAe,EAAgB,EAAuB,CAC/E,EAAM,MAAM,QAAU,GAElB,GAAO,EAAc,EAAO,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,GAAI,CAAO,CAAC,EAE/D,GAAO,EAAc,EAAO,CAAE,GAAI,EAAG,GAAI,EAAO,GAAI,EAAG,GAAI,CAAE,CAAC,EAE9D,IAAiB,IAAA,KAAW,EAAW,YAAc,EAC3D,EACA,MACF,CACF"}
@@ -1,2 +1,2 @@
1
- function e(e,t,n,r){let i=e.getBoundingClientRect();return{x:t.clientX-i.left-n,y:t.clientY-i.top-r}}exports.getMousePosition=e;
1
+ function getMousePosition(e,t,n,r){let i=e.getBoundingClientRect();return{x:t.clientX-i.left-n,y:t.clientY-i.top-r}}exports.getMousePosition=getMousePosition;
2
2
  //# sourceMappingURL=events.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.cjs","names":[],"sources":["../../src/interaction/events.ts"],"sourcesContent":["import type { Point } from '../svg/path';\n\nexport function getMousePosition(svg: SVGSVGElement, event: MouseEvent, offsetX: number, offsetY: number): Point {\n const rect = svg.getBoundingClientRect();\n\n return {\n x: event.clientX - rect.left - offsetX,\n y: event.clientY - rect.top - offsetY,\n };\n}\n"],"mappings":"AAEA,SAAgB,EAAiB,EAAoB,EAAmB,EAAiB,EAAwB,CAC/G,IAAM,EAAO,EAAI,sBAAsB,EAEvC,MAAO,CACL,EAAG,EAAM,QAAU,EAAK,KAAO,EAC/B,EAAG,EAAM,QAAU,EAAK,IAAM,CAChC,CACF"}
1
+ {"version":3,"file":"events.cjs","names":[],"sources":["../../src/interaction/events.ts"],"sourcesContent":["import type { Point } from '../svg/path';\n\nexport function getMousePosition(svg: SVGSVGElement, event: MouseEvent, offsetX: number, offsetY: number): Point {\n const rect = svg.getBoundingClientRect();\n\n return {\n x: event.clientX - rect.left - offsetX,\n y: event.clientY - rect.top - offsetY,\n };\n}\n"],"mappings":"AAEA,SAAgB,iBAAiB,EAAoB,EAAmB,EAAiB,EAAwB,CAC/G,IAAM,EAAO,EAAI,sBAAsB,EAEvC,MAAO,CACL,EAAG,EAAM,QAAU,EAAK,KAAO,EAC/B,EAAG,EAAM,QAAU,EAAK,IAAM,CAChC,CACF"}
@@ -1,12 +1,2 @@
1
- //#region src/interaction/events.ts
2
- function e(e, t, n, r) {
3
- let i = e.getBoundingClientRect();
4
- return {
5
- x: t.clientX - i.left - n,
6
- y: t.clientY - i.top - r
7
- };
8
- }
9
- //#endregion
10
- export { e as getMousePosition };
11
-
1
+ function getMousePosition(e,t,n,r){let i=e.getBoundingClientRect();return{x:t.clientX-i.left-n,y:t.clientY-i.top-r}}export{getMousePosition};
12
2
  //# sourceMappingURL=events.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","names":[],"sources":["../../src/interaction/events.ts"],"sourcesContent":["import type { Point } from '../svg/path';\n\nexport function getMousePosition(svg: SVGSVGElement, event: MouseEvent, offsetX: number, offsetY: number): Point {\n const rect = svg.getBoundingClientRect();\n\n return {\n x: event.clientX - rect.left - offsetX,\n y: event.clientY - rect.top - offsetY,\n };\n}\n"],"mappings":";AAEA,SAAgB,EAAiB,GAAoB,GAAmB,GAAiB,GAAwB;CAC/G,IAAM,IAAO,EAAI,sBAAsB;CAEvC,OAAO;EACL,GAAG,EAAM,UAAU,EAAK,OAAO;EAC/B,GAAG,EAAM,UAAU,EAAK,MAAM;CAChC;AACF"}
1
+ {"version":3,"file":"events.js","names":[],"sources":["../../src/interaction/events.ts"],"sourcesContent":["import type { Point } from '../svg/path';\n\nexport function getMousePosition(svg: SVGSVGElement, event: MouseEvent, offsetX: number, offsetY: number): Point {\n const rect = svg.getBoundingClientRect();\n\n return {\n x: event.clientX - rect.left - offsetX,\n y: event.clientY - rect.top - offsetY,\n };\n}\n"],"mappings":"AAEA,SAAgB,iBAAiB,EAAoB,EAAmB,EAAiB,EAAwB,CAC/G,IAAM,EAAO,EAAI,sBAAsB,EAEvC,MAAO,CACL,EAAG,EAAM,QAAU,EAAK,KAAO,EAC/B,EAAG,EAAM,QAAU,EAAK,IAAM,CAChC,CACF"}
@@ -1,2 +1,2 @@
1
- function e(e){return e===!0?`bottom`:e.position??`bottom`}function t(t,n){let r=e(n),i=document.createElement(`div`);i.className=`prism-legend prism-legend-${r}`,r===`top`?t.insertBefore(i,t.firstChild):t.appendChild(i);let a=()=>{i.remove()};return{dispose:a,el:i,[Symbol.dispose]:a,update(e){i.innerHTML=``;for(let t of e){let e=document.createElement(`div`);e.className=`prism-legend-item`;let n=document.createElement(`span`);n.className=`prism-legend-dot`,n.style.backgroundColor=t.color;let r=document.createElement(`span`);r.className=`prism-legend-label`,r.textContent=t.name,e.appendChild(n),e.appendChild(r),i.appendChild(e)}}}}exports.createLegend=t;
1
+ function resolvePosition(e){return e===!0?`bottom`:e.position??`bottom`}function createLegend(e,t){let n=resolvePosition(t),r=document.createElement(`div`);r.className=`prism-legend prism-legend-${n}`,n===`top`?e.insertBefore(r,e.firstChild):e.appendChild(r);let disposeHandle=()=>{r.remove()};return{dispose:disposeHandle,el:r,[Symbol.dispose]:disposeHandle,update(e){r.replaceChildren();for(let t of e){let e=document.createElement(`div`);e.className=`prism-legend-item`;let n=document.createElement(`span`);n.className=`prism-legend-dot`,n.style.backgroundColor=t.color;let i=document.createElement(`span`);i.className=`prism-legend-label`,i.textContent=t.name,e.appendChild(n),e.appendChild(i),r.appendChild(e)}}}}exports.createLegend=createLegend;
2
2
  //# sourceMappingURL=legend.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"legend.cjs","names":[],"sources":["../../src/interaction/legend.ts"],"sourcesContent":["import type { LegendConfig, LegendPosition } from '../types';\n\nexport interface LegendState {\n dispose(): void;\n el: HTMLDivElement | null;\n update(series: { color: string; name: string }[]): void;\n [Symbol.dispose](): void;\n}\n\nfunction resolvePosition(config: LegendConfig | true): LegendPosition {\n if (config === true) return 'bottom';\n\n return config.position ?? 'bottom';\n}\n\nexport function createLegend(container: HTMLElement, config: LegendConfig | true): LegendState {\n const position = resolvePosition(config);\n const el = document.createElement('div');\n\n el.className = `prism-legend prism-legend-${position}`;\n\n if (position === 'top') {\n container.insertBefore(el, container.firstChild);\n } else {\n container.appendChild(el);\n }\n\n const disposeHandle = (): void => {\n el.remove();\n };\n\n return {\n dispose: disposeHandle,\n el,\n [Symbol.dispose]: disposeHandle,\n update(series) {\n el.innerHTML = '';\n for (const s of series) {\n const item = document.createElement('div');\n\n item.className = 'prism-legend-item';\n\n const dot = document.createElement('span');\n\n dot.className = 'prism-legend-dot';\n dot.style.backgroundColor = s.color;\n\n const label = document.createElement('span');\n\n label.className = 'prism-legend-label';\n label.textContent = s.name;\n\n item.appendChild(dot);\n item.appendChild(label);\n el.appendChild(item);\n }\n },\n };\n}\n"],"mappings":"AASA,SAAS,EAAgB,EAA6C,CAGpE,OAFI,IAAW,GAAa,SAErB,EAAO,UAAY,QAC5B,CAEA,SAAgB,EAAa,EAAwB,EAA0C,CAC7F,IAAM,EAAW,EAAgB,CAAM,EACjC,EAAK,SAAS,cAAc,KAAK,EAEvC,EAAG,UAAY,6BAA6B,IAExC,IAAa,MACf,EAAU,aAAa,EAAI,EAAU,UAAU,EAE/C,EAAU,YAAY,CAAE,EAG1B,IAAM,MAA4B,CAChC,EAAG,OAAO,CACZ,EAEA,MAAO,CACL,QAAS,EACT,MACC,OAAO,SAAU,EAClB,OAAO,EAAQ,CACb,EAAG,UAAY,GACf,IAAK,IAAM,KAAK,EAAQ,CACtB,IAAM,EAAO,SAAS,cAAc,KAAK,EAEzC,EAAK,UAAY,oBAEjB,IAAM,EAAM,SAAS,cAAc,MAAM,EAEzC,EAAI,UAAY,mBAChB,EAAI,MAAM,gBAAkB,EAAE,MAE9B,IAAM,EAAQ,SAAS,cAAc,MAAM,EAE3C,EAAM,UAAY,qBAClB,EAAM,YAAc,EAAE,KAEtB,EAAK,YAAY,CAAG,EACpB,EAAK,YAAY,CAAK,EACtB,EAAG,YAAY,CAAI,CACrB,CACF,CACF,CACF"}
1
+ {"version":3,"file":"legend.cjs","names":[],"sources":["../../src/interaction/legend.ts"],"sourcesContent":["import type { LegendConfig, LegendPosition } from '../types';\n\nexport interface LegendState {\n dispose(): void;\n el: HTMLDivElement | null;\n update(series: { color: string; name: string }[]): void;\n [Symbol.dispose](): void;\n}\n\nfunction resolvePosition(config: LegendConfig | true): LegendPosition {\n if (config === true) return 'bottom';\n\n return config.position ?? 'bottom';\n}\n\nexport function createLegend(container: HTMLElement, config: LegendConfig | true): LegendState {\n const position = resolvePosition(config);\n const el = document.createElement('div');\n\n el.className = `prism-legend prism-legend-${position}`;\n\n if (position === 'top') {\n container.insertBefore(el, container.firstChild);\n } else {\n container.appendChild(el);\n }\n\n const disposeHandle = (): void => {\n el.remove();\n };\n\n return {\n dispose: disposeHandle,\n el,\n [Symbol.dispose]: disposeHandle,\n update(series) {\n el.replaceChildren();\n for (const s of series) {\n const item = document.createElement('div');\n\n item.className = 'prism-legend-item';\n\n const dot = document.createElement('span');\n\n dot.className = 'prism-legend-dot';\n dot.style.backgroundColor = s.color;\n\n const label = document.createElement('span');\n\n label.className = 'prism-legend-label';\n label.textContent = s.name;\n\n item.appendChild(dot);\n item.appendChild(label);\n el.appendChild(item);\n }\n },\n };\n}\n"],"mappings":"AASA,SAAS,gBAAgB,EAA6C,CAGpE,OAFI,IAAW,GAAa,SAErB,EAAO,UAAY,QAC5B,CAEA,SAAgB,aAAa,EAAwB,EAA0C,CAC7F,IAAM,EAAW,gBAAgB,CAAM,EACjC,EAAK,SAAS,cAAc,KAAK,EAEvC,EAAG,UAAY,6BAA6B,IAExC,IAAa,MACf,EAAU,aAAa,EAAI,EAAU,UAAU,EAE/C,EAAU,YAAY,CAAE,EAG1B,IAAM,kBAA4B,CAChC,EAAG,OAAO,CACZ,EAEA,MAAO,CACL,QAAS,cACT,MACC,OAAO,SAAU,cAClB,OAAO,EAAQ,CACb,EAAG,gBAAgB,EACnB,IAAK,IAAM,KAAK,EAAQ,CACtB,IAAM,EAAO,SAAS,cAAc,KAAK,EAEzC,EAAK,UAAY,oBAEjB,IAAM,EAAM,SAAS,cAAc,MAAM,EAEzC,EAAI,UAAY,mBAChB,EAAI,MAAM,gBAAkB,EAAE,MAE9B,IAAM,EAAQ,SAAS,cAAc,MAAM,EAE3C,EAAM,UAAY,qBAClB,EAAM,YAAc,EAAE,KAEtB,EAAK,YAAY,CAAG,EACpB,EAAK,YAAY,CAAK,EACtB,EAAG,YAAY,CAAI,CACrB,CACF,CACF,CACF"}
@@ -1,31 +1,2 @@
1
- //#region src/interaction/legend.ts
2
- function e(e) {
3
- return e === !0 ? "bottom" : e.position ?? "bottom";
4
- }
5
- function t(t, n) {
6
- let r = e(n), i = document.createElement("div");
7
- i.className = `prism-legend prism-legend-${r}`, r === "top" ? t.insertBefore(i, t.firstChild) : t.appendChild(i);
8
- let a = () => {
9
- i.remove();
10
- };
11
- return {
12
- dispose: a,
13
- el: i,
14
- [Symbol.dispose]: a,
15
- update(e) {
16
- i.innerHTML = "";
17
- for (let t of e) {
18
- let e = document.createElement("div");
19
- e.className = "prism-legend-item";
20
- let n = document.createElement("span");
21
- n.className = "prism-legend-dot", n.style.backgroundColor = t.color;
22
- let r = document.createElement("span");
23
- r.className = "prism-legend-label", r.textContent = t.name, e.appendChild(n), e.appendChild(r), i.appendChild(e);
24
- }
25
- }
26
- };
27
- }
28
- //#endregion
29
- export { t as createLegend };
30
-
1
+ function resolvePosition(e){return e===!0?`bottom`:e.position??`bottom`}function createLegend(e,t){let n=resolvePosition(t),r=document.createElement(`div`);r.className=`prism-legend prism-legend-${n}`,n===`top`?e.insertBefore(r,e.firstChild):e.appendChild(r);let disposeHandle=()=>{r.remove()};return{dispose:disposeHandle,el:r,[Symbol.dispose]:disposeHandle,update(e){r.replaceChildren();for(let t of e){let e=document.createElement(`div`);e.className=`prism-legend-item`;let n=document.createElement(`span`);n.className=`prism-legend-dot`,n.style.backgroundColor=t.color;let i=document.createElement(`span`);i.className=`prism-legend-label`,i.textContent=t.name,e.appendChild(n),e.appendChild(i),r.appendChild(e)}}}}export{createLegend};
31
2
  //# sourceMappingURL=legend.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"legend.js","names":[],"sources":["../../src/interaction/legend.ts"],"sourcesContent":["import type { LegendConfig, LegendPosition } from '../types';\n\nexport interface LegendState {\n dispose(): void;\n el: HTMLDivElement | null;\n update(series: { color: string; name: string }[]): void;\n [Symbol.dispose](): void;\n}\n\nfunction resolvePosition(config: LegendConfig | true): LegendPosition {\n if (config === true) return 'bottom';\n\n return config.position ?? 'bottom';\n}\n\nexport function createLegend(container: HTMLElement, config: LegendConfig | true): LegendState {\n const position = resolvePosition(config);\n const el = document.createElement('div');\n\n el.className = `prism-legend prism-legend-${position}`;\n\n if (position === 'top') {\n container.insertBefore(el, container.firstChild);\n } else {\n container.appendChild(el);\n }\n\n const disposeHandle = (): void => {\n el.remove();\n };\n\n return {\n dispose: disposeHandle,\n el,\n [Symbol.dispose]: disposeHandle,\n update(series) {\n el.innerHTML = '';\n for (const s of series) {\n const item = document.createElement('div');\n\n item.className = 'prism-legend-item';\n\n const dot = document.createElement('span');\n\n dot.className = 'prism-legend-dot';\n dot.style.backgroundColor = s.color;\n\n const label = document.createElement('span');\n\n label.className = 'prism-legend-label';\n label.textContent = s.name;\n\n item.appendChild(dot);\n item.appendChild(label);\n el.appendChild(item);\n }\n },\n };\n}\n"],"mappings":";AASA,SAAS,EAAgB,GAA6C;CAGpE,OAFI,MAAW,KAAa,WAErB,EAAO,YAAY;AAC5B;AAEA,SAAgB,EAAa,GAAwB,GAA0C;CAC7F,IAAM,IAAW,EAAgB,CAAM,GACjC,IAAK,SAAS,cAAc,KAAK;CAIvC,AAFA,EAAG,YAAY,6BAA6B,KAExC,MAAa,QACf,EAAU,aAAa,GAAI,EAAU,UAAU,IAE/C,EAAU,YAAY,CAAE;CAG1B,IAAM,UAA4B;EAChC,EAAG,OAAO;CACZ;CAEA,OAAO;EACL,SAAS;EACT;GACC,OAAO,UAAU;EAClB,OAAO,GAAQ;GACb,EAAG,YAAY;GACf,KAAK,IAAM,KAAK,GAAQ;IACtB,IAAM,IAAO,SAAS,cAAc,KAAK;IAEzC,EAAK,YAAY;IAEjB,IAAM,IAAM,SAAS,cAAc,MAAM;IAGzC,AADA,EAAI,YAAY,oBAChB,EAAI,MAAM,kBAAkB,EAAE;IAE9B,IAAM,IAAQ,SAAS,cAAc,MAAM;IAO3C,AALA,EAAM,YAAY,sBAClB,EAAM,cAAc,EAAE,MAEtB,EAAK,YAAY,CAAG,GACpB,EAAK,YAAY,CAAK,GACtB,EAAG,YAAY,CAAI;GACrB;EACF;CACF;AACF"}
1
+ {"version":3,"file":"legend.js","names":[],"sources":["../../src/interaction/legend.ts"],"sourcesContent":["import type { LegendConfig, LegendPosition } from '../types';\n\nexport interface LegendState {\n dispose(): void;\n el: HTMLDivElement | null;\n update(series: { color: string; name: string }[]): void;\n [Symbol.dispose](): void;\n}\n\nfunction resolvePosition(config: LegendConfig | true): LegendPosition {\n if (config === true) return 'bottom';\n\n return config.position ?? 'bottom';\n}\n\nexport function createLegend(container: HTMLElement, config: LegendConfig | true): LegendState {\n const position = resolvePosition(config);\n const el = document.createElement('div');\n\n el.className = `prism-legend prism-legend-${position}`;\n\n if (position === 'top') {\n container.insertBefore(el, container.firstChild);\n } else {\n container.appendChild(el);\n }\n\n const disposeHandle = (): void => {\n el.remove();\n };\n\n return {\n dispose: disposeHandle,\n el,\n [Symbol.dispose]: disposeHandle,\n update(series) {\n el.replaceChildren();\n for (const s of series) {\n const item = document.createElement('div');\n\n item.className = 'prism-legend-item';\n\n const dot = document.createElement('span');\n\n dot.className = 'prism-legend-dot';\n dot.style.backgroundColor = s.color;\n\n const label = document.createElement('span');\n\n label.className = 'prism-legend-label';\n label.textContent = s.name;\n\n item.appendChild(dot);\n item.appendChild(label);\n el.appendChild(item);\n }\n },\n };\n}\n"],"mappings":"AASA,SAAS,gBAAgB,EAA6C,CAGpE,OAFI,IAAW,GAAa,SAErB,EAAO,UAAY,QAC5B,CAEA,SAAgB,aAAa,EAAwB,EAA0C,CAC7F,IAAM,EAAW,gBAAgB,CAAM,EACjC,EAAK,SAAS,cAAc,KAAK,EAEvC,EAAG,UAAY,6BAA6B,IAExC,IAAa,MACf,EAAU,aAAa,EAAI,EAAU,UAAU,EAE/C,EAAU,YAAY,CAAE,EAG1B,IAAM,kBAA4B,CAChC,EAAG,OAAO,CACZ,EAEA,MAAO,CACL,QAAS,cACT,MACC,OAAO,SAAU,cAClB,OAAO,EAAQ,CACb,EAAG,gBAAgB,EACnB,IAAK,IAAM,KAAK,EAAQ,CACtB,IAAM,EAAO,SAAS,cAAc,KAAK,EAEzC,EAAK,UAAY,oBAEjB,IAAM,EAAM,SAAS,cAAc,MAAM,EAEzC,EAAI,UAAY,mBAChB,EAAI,MAAM,gBAAkB,EAAE,MAE9B,IAAM,EAAQ,SAAS,cAAc,MAAM,EAE3C,EAAM,UAAY,qBAClB,EAAM,YAAc,EAAE,KAEtB,EAAK,YAAY,CAAG,EACpB,EAAK,YAAY,CAAK,EACtB,EAAG,YAAY,CAAI,CACrB,CACF,CACF,CACF"}
@@ -1,2 +1,2 @@
1
- const e=require("../core/layout.cjs"),t=require("../core/cartesian-model.cjs"),n=require("./events.cjs");function r(e,t,n){let r=null,i=1/0;for(let a=0;a<t.length;a++)for(let o=0;o<(t[a]?.length??0);o++){let s=e[a]?.[o],c=t[a]?.[o];if(!s||!c)continue;let l=Math.abs(c.x-n);l<i&&(i=l,r=s.key)}return r}function i(e,n,r,i){let a=t.keyId(r),o=null,s=1/0;for(let r=0;r<n.length;r++){let c=e[r]?.findIndex(e=>t.keyId(e.key)===a)??-1,l=c===-1?void 0:e[r]?.[c],u=c===-1?void 0:n[r]?.[c];if(!l||!u)continue;let d=Number.isFinite(i)?Math.abs(u.y-i):0;d<s&&(s=d,o={datum:l,point:u,seriesIndex:r})}return o}function a(a){let o=0;return{onClick:t=>{if(!a.onClick)return;let o=a.getPoints();if(o.length===0||o[0].length===0)return;let s=a.dims(),c=n.getMousePosition(a.svg,t,s.margin.left,s.margin.top),l=e.chartArea(s.width,s.height,s.margin);if(c.x<0||c.x>l.width||c.y<0||c.y>l.height)return;let u=r(a.getData(),o,c.x);if(u===null)return;let d=i(a.getData(),o,u,c.y),f=d?a.getSeriesList()[d.seriesIndex]:void 0;d&&f&&a.onClick({datum:d.datum,originalEvent:t,series:f})},onKeyDown:e=>{let n=a.getData(),r=a.getPoints(),s=[...new Map(n.flat().map(e=>[t.keyId(e.key),e.key])).values()];if(s.length!==0){if(e.key===`ArrowLeft`||e.key===`ArrowRight`){e.preventDefault(),o=Math.max(0,Math.min(s.length-1,o+(e.key===`ArrowLeft`?-1:1)));let t=s[o],c=i(n,r,t,1/0),l=c?a.getSeriesList()[c.seriesIndex]:void 0;if(!c||!l)return;let u=a.tooltip?void 0:`${l.name}: ${c.datum.value}`;a.crosshair?.show(c.point.x,c.point.y,a.dims().width,a.dims().height,u),a.tooltip?.show(c.point.x+a.dims().margin.left,c.point.y+a.dims().margin.top,c.datum,l),a.onHover?.({datum:c.datum,originalEvent:e,series:l})}if((e.key===`Enter`||e.key===` `)&&a.onClick){e.preventDefault();let t=s[o],c=i(n,r,t,1/0),l=c?a.getSeriesList()[c.seriesIndex]:void 0;c&&l&&a.onClick({datum:c.datum,originalEvent:e,series:l})}e.key===`Escape`&&(a.crosshair?.hide(),a.tooltip?.hide(),a.onHover?.(null))}},onMouseLeave:()=>{a.crosshair?.hide(),a.tooltip?.hide(),a.onHover?.(null)},onMouseMove:t=>{let o=a.getPoints();if(o.length===0||o[0].length===0)return;let s=a.dims(),c=n.getMousePosition(a.svg,t,s.margin.left,s.margin.top),l=e.chartArea(s.width,s.height,s.margin);if(c.x<0||c.x>l.width||c.y<0||c.y>l.height){a.crosshair?.hide(),a.tooltip?.hide();return}let u=r(a.getData(),o,c.x);if(u===null)return;let d=i(a.getData(),o,u,c.y),f=d?a.getSeriesList()[d.seriesIndex]:void 0,p=a.crosshair?.snap===!1?c.x:d?.point.x??c.x,m=a.crosshair?.snap===!1?c.y:d?.point.y??c.y,h=!a.tooltip&&f&&d?`${f.name}: ${d.datum.value}`:void 0;a.crosshair?.show(p,m,l.width,l.height,h),d&&f&&(a.tooltip?.show(d.point.x+s.margin.left,d.point.y+s.margin.top,d.datum,f),a.onHover?.({datum:d.datum,originalEvent:t,series:f}))}}}exports.createSeriesInteraction=a;
1
+ const e=require("../core/layout.cjs"),t=require("../core/cartesian-model.cjs"),n=require("./events.cjs");function findNearestKey(e,t,n){let r=null,i=1/0;for(let a=0;a<t.length;a++)for(let o=0;o<(t[a]?.length??0);o++){let s=e[a]?.[o],c=t[a]?.[o];if(!s||!c)continue;let l=Math.abs(c.x-n);l<i&&(i=l,r=s.key)}return r}function findNearestSeries(e,n,r,i){let a=t.keyId(r),o=null,s=1/0;for(let r=0;r<n.length;r++){let c=e[r]?.findIndex(e=>t.keyId(e.key)===a)??-1,l=c===-1?void 0:e[r]?.[c],u=c===-1?void 0:n[r]?.[c];if(!l||!u)continue;let d=Number.isFinite(i)?Math.abs(u.y-i):0;d<s&&(s=d,o={datum:l,point:u,seriesIndex:r})}return o}function createSeriesInteraction(r){let i=0,onMouseMove=t=>{let i=r.getPoints();if(i.length===0||i[0].length===0)return;let a=r.dims(),o=n.getMousePosition(r.svg,t,a.margin.left,a.margin.top),s=e.chartArea(a.width,a.height,a.margin);if(o.x<0||o.x>s.width||o.y<0||o.y>s.height){r.crosshair?.hide(),r.tooltip?.hide();return}let c=findNearestKey(r.getData(),i,o.x);if(c===null)return;let l=findNearestSeries(r.getData(),i,c,o.y),u=l?r.getSeriesList()[l.seriesIndex]:void 0,d=r.crosshair?.snap===!1?o.x:l?.point.x??o.x,f=r.crosshair?.snap===!1?o.y:l?.point.y??o.y,p=!r.tooltip&&u&&l?`${u.name}: ${l.datum.value}`:void 0;r.crosshair?.show(d,f,s.width,s.height,p),l&&u&&(r.tooltip?.show(l.point.x+a.margin.left,l.point.y+a.margin.top,l.datum,u),r.onHover?.({datum:l.datum,originalEvent:t,series:u}))},onMouseLeave=()=>{r.crosshair?.hide(),r.tooltip?.hide(),r.onHover?.(null)},onClick=t=>{if(!r.onClick)return;let i=r.getPoints();if(i.length===0||i[0].length===0)return;let a=r.dims(),o=n.getMousePosition(r.svg,t,a.margin.left,a.margin.top),s=e.chartArea(a.width,a.height,a.margin);if(o.x<0||o.x>s.width||o.y<0||o.y>s.height)return;let c=findNearestKey(r.getData(),i,o.x);if(c===null)return;let l=findNearestSeries(r.getData(),i,c,o.y),u=l?r.getSeriesList()[l.seriesIndex]:void 0;l&&u&&r.onClick({datum:l.datum,originalEvent:t,series:u})},onKeyDown=e=>{let n=r.getData(),a=r.getPoints(),o=[...new Map(n.flat().map(e=>[t.keyId(e.key),e.key])).values()];if(o.length!==0){if(e.key===`ArrowLeft`||e.key===`ArrowRight`){e.preventDefault(),i=Math.max(0,Math.min(o.length-1,i+(e.key===`ArrowLeft`?-1:1)));let t=o[i],s=findNearestSeries(n,a,t,1/0),c=s?r.getSeriesList()[s.seriesIndex]:void 0;if(!s||!c)return;let l=r.tooltip?void 0:`${c.name}: ${s.datum.value}`;r.crosshair?.show(s.point.x,s.point.y,r.dims().width,r.dims().height,l),r.tooltip?.show(s.point.x+r.dims().margin.left,s.point.y+r.dims().margin.top,s.datum,c),r.onHover?.({datum:s.datum,originalEvent:e,series:c})}if((e.key===`Enter`||e.key===` `)&&r.onClick){e.preventDefault();let t=o[i],s=findNearestSeries(n,a,t,1/0),c=s?r.getSeriesList()[s.seriesIndex]:void 0;s&&c&&r.onClick({datum:s.datum,originalEvent:e,series:c})}e.key===`Escape`&&(r.crosshair?.hide(),r.tooltip?.hide(),r.onHover?.(null))}};return{onClick,onKeyDown,onMouseLeave,onMouseMove}}exports.createSeriesInteraction=createSeriesInteraction;
2
2
  //# sourceMappingURL=series-interaction.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"series-interaction.cjs","names":[],"sources":["../../src/interaction/series-interaction.ts"],"sourcesContent":["import { keyId } from '../core/cartesian-model';\nimport type { ChartEventHandlers } from '../core/chart-scaffold';\nimport { chartArea } from '../core/layout';\nimport type { Point } from '../svg/path';\nimport type { ChartDimensions, ChartEvent, Datum, Series } from '../types';\nimport type { CrosshairState } from './crosshair';\nimport { getMousePosition } from './events';\nimport type { TooltipState } from './tooltip';\n\nexport interface SeriesInteractionOptions {\n crosshair?: CrosshairState | null;\n dims: () => ChartDimensions;\n getData: () => Datum[][];\n getPoints: () => Point[][];\n getSeriesList: () => Series[];\n onClick?: ((event: ChartEvent) => void) | undefined;\n onHover?: ((event: ChartEvent | null) => void) | undefined;\n svg: SVGSVGElement;\n tooltip?: TooltipState | null;\n}\n\ntype SeriesPoint = { datum: Datum; point: Point; seriesIndex: number };\n\nfunction findNearestKey(allData: Datum[][], allPoints: Point[][], posX: number): Datum['key'] | null {\n let nearest: Datum['key'] | null = null;\n let minXDistance = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n for (let datumIndex = 0; datumIndex < (allPoints[seriesIndex]?.length ?? 0); datumIndex++) {\n const datum = allData[seriesIndex]?.[datumIndex];\n const point = allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Math.abs(point.x - posX);\n\n if (distance < minXDistance) {\n minXDistance = distance;\n nearest = datum.key;\n }\n }\n }\n\n return nearest;\n}\n\nfunction findNearestSeries(\n allData: Datum[][],\n allPoints: Point[][],\n key: Datum['key'],\n posY: number,\n): SeriesPoint | null {\n const id = keyId(key);\n let nearest: { datum: Datum; point: Point; seriesIndex: number } | null = null;\n let minYDist = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n const datumIndex = allData[seriesIndex]?.findIndex((datum) => keyId(datum.key) === id) ?? -1;\n const datum = datumIndex === -1 ? undefined : allData[seriesIndex]?.[datumIndex];\n const point = datumIndex === -1 ? undefined : allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Number.isFinite(posY) ? Math.abs(point.y - posY) : 0;\n\n if (distance < minYDist) {\n minYDist = distance;\n nearest = { datum, point, seriesIndex };\n }\n }\n\n return nearest;\n}\n\nexport function createSeriesInteraction(opts: SeriesInteractionOptions): ChartEventHandlers {\n let keyboardIndex = 0;\n\n const onMouseMove = (event: MouseEvent) => {\n const allPoints = opts.getPoints();\n\n if (allPoints.length === 0 || allPoints[0].length === 0) return;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n\n return;\n }\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n if (key === null) return;\n\n const nearest = findNearestSeries(opts.getData(), allPoints, key, pos.y);\n const series = nearest ? opts.getSeriesList()[nearest.seriesIndex] : undefined;\n const crosshairX = opts.crosshair?.snap === false ? pos.x : (nearest?.point.x ?? pos.x);\n const crosshairY = opts.crosshair?.snap === false ? pos.y : (nearest?.point.y ?? pos.y);\n\n // When a tooltip is present it already carries role=\"status\" + aria-live=\"polite\",\n // so the crosshair's own live region must stay silent to avoid double-announcing.\n const announceText = !opts.tooltip && series && nearest ? `${series.name}: ${nearest.datum.value}` : undefined;\n\n opts.crosshair?.show(crosshairX, crosshairY, area.width, area.height, announceText);\n\n if (nearest && series) {\n opts.tooltip?.show(nearest.point.x + dims.margin.left, nearest.point.y + dims.margin.top, nearest.datum, series);\n opts.onHover?.({ datum: nearest.datum, originalEvent: event, series });\n }\n };\n\n const onMouseLeave = () => {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.onHover?.(null);\n };\n\n const onClick = (event: MouseEvent) => {\n if (!opts.onClick) return;\n\n const allPoints = opts.getPoints();\n\n if (allPoints.length === 0 || allPoints[0].length === 0) return;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) return;\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n if (key === null) return;\n\n const nearest = findNearestSeries(opts.getData(), allPoints, key, pos.y);\n const series = nearest ? opts.getSeriesList()[nearest.seriesIndex] : undefined;\n\n if (nearest && series) {\n opts.onClick({ datum: nearest.datum, originalEvent: event, series });\n }\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const allData = opts.getData();\n const allPoints = opts.getPoints();\n const domain = [...new Map(allData.flat().map((datum) => [keyId(datum.key), datum.key])).values()];\n\n if (domain.length === 0) return;\n\n if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {\n event.preventDefault();\n keyboardIndex = Math.max(0, Math.min(domain.length - 1, keyboardIndex + (event.key === 'ArrowLeft' ? -1 : 1)));\n\n const key = domain[keyboardIndex]!;\n const candidate = findNearestSeries(allData, allPoints, key, Number.POSITIVE_INFINITY);\n const series = candidate ? opts.getSeriesList()[candidate.seriesIndex] : undefined;\n\n if (!candidate || !series) return;\n\n // Same dedup as onMouseMove — tooltip announces when present.\n const announceText = !opts.tooltip ? `${series.name}: ${candidate.datum.value}` : undefined;\n\n opts.crosshair?.show(candidate.point.x, candidate.point.y, opts.dims().width, opts.dims().height, announceText);\n opts.tooltip?.show(\n candidate.point.x + opts.dims().margin.left,\n candidate.point.y + opts.dims().margin.top,\n candidate.datum,\n series,\n );\n opts.onHover?.({ datum: candidate.datum, originalEvent: event, series });\n }\n\n if ((event.key === 'Enter' || event.key === ' ') && opts.onClick) {\n event.preventDefault();\n\n const key = domain[keyboardIndex]!;\n const candidate = findNearestSeries(allData, allPoints, key, Number.POSITIVE_INFINITY);\n const series = candidate ? opts.getSeriesList()[candidate.seriesIndex] : undefined;\n\n if (candidate && series) opts.onClick({ datum: candidate.datum, originalEvent: event, series });\n }\n\n if (event.key === 'Escape') {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.onHover?.(null);\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave, onMouseMove };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"series-interaction.cjs","names":[],"sources":["../../src/interaction/series-interaction.ts"],"sourcesContent":["import { keyId } from '../core/cartesian-model';\nimport type { ChartEventHandlers } from '../core/chart-scaffold';\nimport { chartArea } from '../core/layout';\nimport type { Point } from '../svg/path';\nimport type { ChartDimensions, ChartEvent, Datum, Series } from '../types';\nimport type { CrosshairState } from './crosshair';\nimport { getMousePosition } from './events';\nimport type { TooltipState } from './tooltip';\n\nexport interface SeriesInteractionOptions {\n crosshair?: CrosshairState | null;\n dims: () => ChartDimensions;\n getData: () => Datum[][];\n getPoints: () => Point[][];\n getSeriesList: () => Series[];\n onClick?: ((event: ChartEvent) => void) | undefined;\n onHover?: ((event: ChartEvent | null) => void) | undefined;\n svg: SVGSVGElement;\n tooltip?: TooltipState | null;\n}\n\ntype SeriesPoint = { datum: Datum; point: Point; seriesIndex: number };\n\nfunction findNearestKey(allData: Datum[][], allPoints: Point[][], posX: number): Datum['key'] | null {\n let nearest: Datum['key'] | null = null;\n let minXDistance = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n for (let datumIndex = 0; datumIndex < (allPoints[seriesIndex]?.length ?? 0); datumIndex++) {\n const datum = allData[seriesIndex]?.[datumIndex];\n const point = allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Math.abs(point.x - posX);\n\n if (distance < minXDistance) {\n minXDistance = distance;\n nearest = datum.key;\n }\n }\n }\n\n return nearest;\n}\n\nfunction findNearestSeries(\n allData: Datum[][],\n allPoints: Point[][],\n key: Datum['key'],\n posY: number,\n): SeriesPoint | null {\n const id = keyId(key);\n let nearest: { datum: Datum; point: Point; seriesIndex: number } | null = null;\n let minYDist = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n const datumIndex = allData[seriesIndex]?.findIndex((datum) => keyId(datum.key) === id) ?? -1;\n const datum = datumIndex === -1 ? undefined : allData[seriesIndex]?.[datumIndex];\n const point = datumIndex === -1 ? undefined : allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Number.isFinite(posY) ? Math.abs(point.y - posY) : 0;\n\n if (distance < minYDist) {\n minYDist = distance;\n nearest = { datum, point, seriesIndex };\n }\n }\n\n return nearest;\n}\n\nexport function createSeriesInteraction(opts: SeriesInteractionOptions): ChartEventHandlers {\n let keyboardIndex = 0;\n\n const onMouseMove = (event: MouseEvent) => {\n const allPoints = opts.getPoints();\n\n if (allPoints.length === 0 || allPoints[0].length === 0) return;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n\n return;\n }\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n if (key === null) return;\n\n const nearest = findNearestSeries(opts.getData(), allPoints, key, pos.y);\n const series = nearest ? opts.getSeriesList()[nearest.seriesIndex] : undefined;\n const crosshairX = opts.crosshair?.snap === false ? pos.x : (nearest?.point.x ?? pos.x);\n const crosshairY = opts.crosshair?.snap === false ? pos.y : (nearest?.point.y ?? pos.y);\n\n // When a tooltip is present it already carries role=\"status\" + aria-live=\"polite\",\n // so the crosshair's own live region must stay silent to avoid double-announcing.\n const announceText = !opts.tooltip && series && nearest ? `${series.name}: ${nearest.datum.value}` : undefined;\n\n opts.crosshair?.show(crosshairX, crosshairY, area.width, area.height, announceText);\n\n if (nearest && series) {\n opts.tooltip?.show(nearest.point.x + dims.margin.left, nearest.point.y + dims.margin.top, nearest.datum, series);\n opts.onHover?.({ datum: nearest.datum, originalEvent: event, series });\n }\n };\n\n const onMouseLeave = () => {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.onHover?.(null);\n };\n\n const onClick = (event: MouseEvent) => {\n if (!opts.onClick) return;\n\n const allPoints = opts.getPoints();\n\n if (allPoints.length === 0 || allPoints[0].length === 0) return;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) return;\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n if (key === null) return;\n\n const nearest = findNearestSeries(opts.getData(), allPoints, key, pos.y);\n const series = nearest ? opts.getSeriesList()[nearest.seriesIndex] : undefined;\n\n if (nearest && series) {\n opts.onClick({ datum: nearest.datum, originalEvent: event, series });\n }\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const allData = opts.getData();\n const allPoints = opts.getPoints();\n const domain = [...new Map(allData.flat().map((datum) => [keyId(datum.key), datum.key])).values()];\n\n if (domain.length === 0) return;\n\n if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {\n event.preventDefault();\n keyboardIndex = Math.max(0, Math.min(domain.length - 1, keyboardIndex + (event.key === 'ArrowLeft' ? -1 : 1)));\n\n const key = domain[keyboardIndex]!;\n const candidate = findNearestSeries(allData, allPoints, key, Number.POSITIVE_INFINITY);\n const series = candidate ? opts.getSeriesList()[candidate.seriesIndex] : undefined;\n\n if (!candidate || !series) return;\n\n // Same dedup as onMouseMove — tooltip announces when present.\n const announceText = !opts.tooltip ? `${series.name}: ${candidate.datum.value}` : undefined;\n\n opts.crosshair?.show(candidate.point.x, candidate.point.y, opts.dims().width, opts.dims().height, announceText);\n opts.tooltip?.show(\n candidate.point.x + opts.dims().margin.left,\n candidate.point.y + opts.dims().margin.top,\n candidate.datum,\n series,\n );\n opts.onHover?.({ datum: candidate.datum, originalEvent: event, series });\n }\n\n if ((event.key === 'Enter' || event.key === ' ') && opts.onClick) {\n event.preventDefault();\n\n const key = domain[keyboardIndex]!;\n const candidate = findNearestSeries(allData, allPoints, key, Number.POSITIVE_INFINITY);\n const series = candidate ? opts.getSeriesList()[candidate.seriesIndex] : undefined;\n\n if (candidate && series) opts.onClick({ datum: candidate.datum, originalEvent: event, series });\n }\n\n if (event.key === 'Escape') {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.onHover?.(null);\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave, onMouseMove };\n}\n"],"mappings":"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"}
@@ -1,98 +1,2 @@
1
- import { chartArea as e } from "../core/layout.js";
2
- import { keyId as t } from "../core/cartesian-model.js";
3
- import { getMousePosition as n } from "./events.js";
4
- //#region src/interaction/series-interaction.ts
5
- function r(e, t, n) {
6
- let r = null, i = Infinity;
7
- for (let a = 0; a < t.length; a++) for (let o = 0; o < (t[a]?.length ?? 0); o++) {
8
- let s = e[a]?.[o], c = t[a]?.[o];
9
- if (!s || !c) continue;
10
- let l = Math.abs(c.x - n);
11
- l < i && (i = l, r = s.key);
12
- }
13
- return r;
14
- }
15
- function i(e, n, r, i) {
16
- let a = t(r), o = null, s = Infinity;
17
- for (let r = 0; r < n.length; r++) {
18
- let c = e[r]?.findIndex((e) => t(e.key) === a) ?? -1, l = c === -1 ? void 0 : e[r]?.[c], u = c === -1 ? void 0 : n[r]?.[c];
19
- if (!l || !u) continue;
20
- let d = Number.isFinite(i) ? Math.abs(u.y - i) : 0;
21
- d < s && (s = d, o = {
22
- datum: l,
23
- point: u,
24
- seriesIndex: r
25
- });
26
- }
27
- return o;
28
- }
29
- function a(a) {
30
- let o = 0;
31
- return {
32
- onClick: (t) => {
33
- if (!a.onClick) return;
34
- let o = a.getPoints();
35
- if (o.length === 0 || o[0].length === 0) return;
36
- let s = a.dims(), c = n(a.svg, t, s.margin.left, s.margin.top), l = e(s.width, s.height, s.margin);
37
- if (c.x < 0 || c.x > l.width || c.y < 0 || c.y > l.height) return;
38
- let u = r(a.getData(), o, c.x);
39
- if (u === null) return;
40
- let d = i(a.getData(), o, u, c.y), f = d ? a.getSeriesList()[d.seriesIndex] : void 0;
41
- d && f && a.onClick({
42
- datum: d.datum,
43
- originalEvent: t,
44
- series: f
45
- });
46
- },
47
- onKeyDown: (e) => {
48
- let n = a.getData(), r = a.getPoints(), s = [...new Map(n.flat().map((e) => [t(e.key), e.key])).values()];
49
- if (s.length !== 0) {
50
- if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
51
- e.preventDefault(), o = Math.max(0, Math.min(s.length - 1, o + (e.key === "ArrowLeft" ? -1 : 1)));
52
- let t = s[o], c = i(n, r, t, Infinity), l = c ? a.getSeriesList()[c.seriesIndex] : void 0;
53
- if (!c || !l) return;
54
- let u = a.tooltip ? void 0 : `${l.name}: ${c.datum.value}`;
55
- a.crosshair?.show(c.point.x, c.point.y, a.dims().width, a.dims().height, u), a.tooltip?.show(c.point.x + a.dims().margin.left, c.point.y + a.dims().margin.top, c.datum, l), a.onHover?.({
56
- datum: c.datum,
57
- originalEvent: e,
58
- series: l
59
- });
60
- }
61
- if ((e.key === "Enter" || e.key === " ") && a.onClick) {
62
- e.preventDefault();
63
- let t = s[o], c = i(n, r, t, Infinity), l = c ? a.getSeriesList()[c.seriesIndex] : void 0;
64
- c && l && a.onClick({
65
- datum: c.datum,
66
- originalEvent: e,
67
- series: l
68
- });
69
- }
70
- e.key === "Escape" && (a.crosshair?.hide(), a.tooltip?.hide(), a.onHover?.(null));
71
- }
72
- },
73
- onMouseLeave: () => {
74
- a.crosshair?.hide(), a.tooltip?.hide(), a.onHover?.(null);
75
- },
76
- onMouseMove: (t) => {
77
- let o = a.getPoints();
78
- if (o.length === 0 || o[0].length === 0) return;
79
- let s = a.dims(), c = n(a.svg, t, s.margin.left, s.margin.top), l = e(s.width, s.height, s.margin);
80
- if (c.x < 0 || c.x > l.width || c.y < 0 || c.y > l.height) {
81
- a.crosshair?.hide(), a.tooltip?.hide();
82
- return;
83
- }
84
- let u = r(a.getData(), o, c.x);
85
- if (u === null) return;
86
- let d = i(a.getData(), o, u, c.y), f = d ? a.getSeriesList()[d.seriesIndex] : void 0, p = a.crosshair?.snap === !1 ? c.x : d?.point.x ?? c.x, m = a.crosshair?.snap === !1 ? c.y : d?.point.y ?? c.y, h = !a.tooltip && f && d ? `${f.name}: ${d.datum.value}` : void 0;
87
- a.crosshair?.show(p, m, l.width, l.height, h), d && f && (a.tooltip?.show(d.point.x + s.margin.left, d.point.y + s.margin.top, d.datum, f), a.onHover?.({
88
- datum: d.datum,
89
- originalEvent: t,
90
- series: f
91
- }));
92
- }
93
- };
94
- }
95
- //#endregion
96
- export { a as createSeriesInteraction };
97
-
1
+ import{chartArea as e}from"../core/layout.js";import{keyId as t}from"../core/cartesian-model.js";import{getMousePosition as n}from"./events.js";function findNearestKey(e,t,n){let r=null,i=1/0;for(let a=0;a<t.length;a++)for(let o=0;o<(t[a]?.length??0);o++){let s=e[a]?.[o],c=t[a]?.[o];if(!s||!c)continue;let l=Math.abs(c.x-n);l<i&&(i=l,r=s.key)}return r}function findNearestSeries(e,n,r,i){let a=t(r),o=null,s=1/0;for(let r=0;r<n.length;r++){let c=e[r]?.findIndex(e=>t(e.key)===a)??-1,l=c===-1?void 0:e[r]?.[c],u=c===-1?void 0:n[r]?.[c];if(!l||!u)continue;let d=Number.isFinite(i)?Math.abs(u.y-i):0;d<s&&(s=d,o={datum:l,point:u,seriesIndex:r})}return o}function createSeriesInteraction(r){let i=0,onMouseMove=t=>{let i=r.getPoints();if(i.length===0||i[0].length===0)return;let a=r.dims(),o=n(r.svg,t,a.margin.left,a.margin.top),s=e(a.width,a.height,a.margin);if(o.x<0||o.x>s.width||o.y<0||o.y>s.height){r.crosshair?.hide(),r.tooltip?.hide();return}let c=findNearestKey(r.getData(),i,o.x);if(c===null)return;let l=findNearestSeries(r.getData(),i,c,o.y),u=l?r.getSeriesList()[l.seriesIndex]:void 0,d=r.crosshair?.snap===!1?o.x:l?.point.x??o.x,f=r.crosshair?.snap===!1?o.y:l?.point.y??o.y,p=!r.tooltip&&u&&l?`${u.name}: ${l.datum.value}`:void 0;r.crosshair?.show(d,f,s.width,s.height,p),l&&u&&(r.tooltip?.show(l.point.x+a.margin.left,l.point.y+a.margin.top,l.datum,u),r.onHover?.({datum:l.datum,originalEvent:t,series:u}))},onMouseLeave=()=>{r.crosshair?.hide(),r.tooltip?.hide(),r.onHover?.(null)},onClick=t=>{if(!r.onClick)return;let i=r.getPoints();if(i.length===0||i[0].length===0)return;let a=r.dims(),o=n(r.svg,t,a.margin.left,a.margin.top),s=e(a.width,a.height,a.margin);if(o.x<0||o.x>s.width||o.y<0||o.y>s.height)return;let c=findNearestKey(r.getData(),i,o.x);if(c===null)return;let l=findNearestSeries(r.getData(),i,c,o.y),u=l?r.getSeriesList()[l.seriesIndex]:void 0;l&&u&&r.onClick({datum:l.datum,originalEvent:t,series:u})},onKeyDown=e=>{let n=r.getData(),a=r.getPoints(),o=[...new Map(n.flat().map(e=>[t(e.key),e.key])).values()];if(o.length!==0){if(e.key===`ArrowLeft`||e.key===`ArrowRight`){e.preventDefault(),i=Math.max(0,Math.min(o.length-1,i+(e.key===`ArrowLeft`?-1:1)));let t=o[i],s=findNearestSeries(n,a,t,1/0),c=s?r.getSeriesList()[s.seriesIndex]:void 0;if(!s||!c)return;let l=r.tooltip?void 0:`${c.name}: ${s.datum.value}`;r.crosshair?.show(s.point.x,s.point.y,r.dims().width,r.dims().height,l),r.tooltip?.show(s.point.x+r.dims().margin.left,s.point.y+r.dims().margin.top,s.datum,c),r.onHover?.({datum:s.datum,originalEvent:e,series:c})}if((e.key===`Enter`||e.key===` `)&&r.onClick){e.preventDefault();let t=o[i],s=findNearestSeries(n,a,t,1/0),c=s?r.getSeriesList()[s.seriesIndex]:void 0;s&&c&&r.onClick({datum:s.datum,originalEvent:e,series:c})}e.key===`Escape`&&(r.crosshair?.hide(),r.tooltip?.hide(),r.onHover?.(null))}};return{onClick,onKeyDown,onMouseLeave,onMouseMove}}export{createSeriesInteraction};
98
2
  //# sourceMappingURL=series-interaction.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"series-interaction.js","names":[],"sources":["../../src/interaction/series-interaction.ts"],"sourcesContent":["import { keyId } from '../core/cartesian-model';\nimport type { ChartEventHandlers } from '../core/chart-scaffold';\nimport { chartArea } from '../core/layout';\nimport type { Point } from '../svg/path';\nimport type { ChartDimensions, ChartEvent, Datum, Series } from '../types';\nimport type { CrosshairState } from './crosshair';\nimport { getMousePosition } from './events';\nimport type { TooltipState } from './tooltip';\n\nexport interface SeriesInteractionOptions {\n crosshair?: CrosshairState | null;\n dims: () => ChartDimensions;\n getData: () => Datum[][];\n getPoints: () => Point[][];\n getSeriesList: () => Series[];\n onClick?: ((event: ChartEvent) => void) | undefined;\n onHover?: ((event: ChartEvent | null) => void) | undefined;\n svg: SVGSVGElement;\n tooltip?: TooltipState | null;\n}\n\ntype SeriesPoint = { datum: Datum; point: Point; seriesIndex: number };\n\nfunction findNearestKey(allData: Datum[][], allPoints: Point[][], posX: number): Datum['key'] | null {\n let nearest: Datum['key'] | null = null;\n let minXDistance = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n for (let datumIndex = 0; datumIndex < (allPoints[seriesIndex]?.length ?? 0); datumIndex++) {\n const datum = allData[seriesIndex]?.[datumIndex];\n const point = allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Math.abs(point.x - posX);\n\n if (distance < minXDistance) {\n minXDistance = distance;\n nearest = datum.key;\n }\n }\n }\n\n return nearest;\n}\n\nfunction findNearestSeries(\n allData: Datum[][],\n allPoints: Point[][],\n key: Datum['key'],\n posY: number,\n): SeriesPoint | null {\n const id = keyId(key);\n let nearest: { datum: Datum; point: Point; seriesIndex: number } | null = null;\n let minYDist = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n const datumIndex = allData[seriesIndex]?.findIndex((datum) => keyId(datum.key) === id) ?? -1;\n const datum = datumIndex === -1 ? undefined : allData[seriesIndex]?.[datumIndex];\n const point = datumIndex === -1 ? undefined : allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Number.isFinite(posY) ? Math.abs(point.y - posY) : 0;\n\n if (distance < minYDist) {\n minYDist = distance;\n nearest = { datum, point, seriesIndex };\n }\n }\n\n return nearest;\n}\n\nexport function createSeriesInteraction(opts: SeriesInteractionOptions): ChartEventHandlers {\n let keyboardIndex = 0;\n\n const onMouseMove = (event: MouseEvent) => {\n const allPoints = opts.getPoints();\n\n if (allPoints.length === 0 || allPoints[0].length === 0) return;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n\n return;\n }\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n if (key === null) return;\n\n const nearest = findNearestSeries(opts.getData(), allPoints, key, pos.y);\n const series = nearest ? opts.getSeriesList()[nearest.seriesIndex] : undefined;\n const crosshairX = opts.crosshair?.snap === false ? pos.x : (nearest?.point.x ?? pos.x);\n const crosshairY = opts.crosshair?.snap === false ? pos.y : (nearest?.point.y ?? pos.y);\n\n // When a tooltip is present it already carries role=\"status\" + aria-live=\"polite\",\n // so the crosshair's own live region must stay silent to avoid double-announcing.\n const announceText = !opts.tooltip && series && nearest ? `${series.name}: ${nearest.datum.value}` : undefined;\n\n opts.crosshair?.show(crosshairX, crosshairY, area.width, area.height, announceText);\n\n if (nearest && series) {\n opts.tooltip?.show(nearest.point.x + dims.margin.left, nearest.point.y + dims.margin.top, nearest.datum, series);\n opts.onHover?.({ datum: nearest.datum, originalEvent: event, series });\n }\n };\n\n const onMouseLeave = () => {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.onHover?.(null);\n };\n\n const onClick = (event: MouseEvent) => {\n if (!opts.onClick) return;\n\n const allPoints = opts.getPoints();\n\n if (allPoints.length === 0 || allPoints[0].length === 0) return;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) return;\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n if (key === null) return;\n\n const nearest = findNearestSeries(opts.getData(), allPoints, key, pos.y);\n const series = nearest ? opts.getSeriesList()[nearest.seriesIndex] : undefined;\n\n if (nearest && series) {\n opts.onClick({ datum: nearest.datum, originalEvent: event, series });\n }\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const allData = opts.getData();\n const allPoints = opts.getPoints();\n const domain = [...new Map(allData.flat().map((datum) => [keyId(datum.key), datum.key])).values()];\n\n if (domain.length === 0) return;\n\n if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {\n event.preventDefault();\n keyboardIndex = Math.max(0, Math.min(domain.length - 1, keyboardIndex + (event.key === 'ArrowLeft' ? -1 : 1)));\n\n const key = domain[keyboardIndex]!;\n const candidate = findNearestSeries(allData, allPoints, key, Number.POSITIVE_INFINITY);\n const series = candidate ? opts.getSeriesList()[candidate.seriesIndex] : undefined;\n\n if (!candidate || !series) return;\n\n // Same dedup as onMouseMove — tooltip announces when present.\n const announceText = !opts.tooltip ? `${series.name}: ${candidate.datum.value}` : undefined;\n\n opts.crosshair?.show(candidate.point.x, candidate.point.y, opts.dims().width, opts.dims().height, announceText);\n opts.tooltip?.show(\n candidate.point.x + opts.dims().margin.left,\n candidate.point.y + opts.dims().margin.top,\n candidate.datum,\n series,\n );\n opts.onHover?.({ datum: candidate.datum, originalEvent: event, series });\n }\n\n if ((event.key === 'Enter' || event.key === ' ') && opts.onClick) {\n event.preventDefault();\n\n const key = domain[keyboardIndex]!;\n const candidate = findNearestSeries(allData, allPoints, key, Number.POSITIVE_INFINITY);\n const series = candidate ? opts.getSeriesList()[candidate.seriesIndex] : undefined;\n\n if (candidate && series) opts.onClick({ datum: candidate.datum, originalEvent: event, series });\n }\n\n if (event.key === 'Escape') {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.onHover?.(null);\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave, onMouseMove };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"series-interaction.js","names":[],"sources":["../../src/interaction/series-interaction.ts"],"sourcesContent":["import { keyId } from '../core/cartesian-model';\nimport type { ChartEventHandlers } from '../core/chart-scaffold';\nimport { chartArea } from '../core/layout';\nimport type { Point } from '../svg/path';\nimport type { ChartDimensions, ChartEvent, Datum, Series } from '../types';\nimport type { CrosshairState } from './crosshair';\nimport { getMousePosition } from './events';\nimport type { TooltipState } from './tooltip';\n\nexport interface SeriesInteractionOptions {\n crosshair?: CrosshairState | null;\n dims: () => ChartDimensions;\n getData: () => Datum[][];\n getPoints: () => Point[][];\n getSeriesList: () => Series[];\n onClick?: ((event: ChartEvent) => void) | undefined;\n onHover?: ((event: ChartEvent | null) => void) | undefined;\n svg: SVGSVGElement;\n tooltip?: TooltipState | null;\n}\n\ntype SeriesPoint = { datum: Datum; point: Point; seriesIndex: number };\n\nfunction findNearestKey(allData: Datum[][], allPoints: Point[][], posX: number): Datum['key'] | null {\n let nearest: Datum['key'] | null = null;\n let minXDistance = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n for (let datumIndex = 0; datumIndex < (allPoints[seriesIndex]?.length ?? 0); datumIndex++) {\n const datum = allData[seriesIndex]?.[datumIndex];\n const point = allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Math.abs(point.x - posX);\n\n if (distance < minXDistance) {\n minXDistance = distance;\n nearest = datum.key;\n }\n }\n }\n\n return nearest;\n}\n\nfunction findNearestSeries(\n allData: Datum[][],\n allPoints: Point[][],\n key: Datum['key'],\n posY: number,\n): SeriesPoint | null {\n const id = keyId(key);\n let nearest: { datum: Datum; point: Point; seriesIndex: number } | null = null;\n let minYDist = Infinity;\n\n for (let seriesIndex = 0; seriesIndex < allPoints.length; seriesIndex++) {\n const datumIndex = allData[seriesIndex]?.findIndex((datum) => keyId(datum.key) === id) ?? -1;\n const datum = datumIndex === -1 ? undefined : allData[seriesIndex]?.[datumIndex];\n const point = datumIndex === -1 ? undefined : allPoints[seriesIndex]?.[datumIndex];\n\n if (!datum || !point) continue;\n\n const distance = Number.isFinite(posY) ? Math.abs(point.y - posY) : 0;\n\n if (distance < minYDist) {\n minYDist = distance;\n nearest = { datum, point, seriesIndex };\n }\n }\n\n return nearest;\n}\n\nexport function createSeriesInteraction(opts: SeriesInteractionOptions): ChartEventHandlers {\n let keyboardIndex = 0;\n\n const onMouseMove = (event: MouseEvent) => {\n const allPoints = opts.getPoints();\n\n if (allPoints.length === 0 || allPoints[0].length === 0) return;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n\n return;\n }\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n if (key === null) return;\n\n const nearest = findNearestSeries(opts.getData(), allPoints, key, pos.y);\n const series = nearest ? opts.getSeriesList()[nearest.seriesIndex] : undefined;\n const crosshairX = opts.crosshair?.snap === false ? pos.x : (nearest?.point.x ?? pos.x);\n const crosshairY = opts.crosshair?.snap === false ? pos.y : (nearest?.point.y ?? pos.y);\n\n // When a tooltip is present it already carries role=\"status\" + aria-live=\"polite\",\n // so the crosshair's own live region must stay silent to avoid double-announcing.\n const announceText = !opts.tooltip && series && nearest ? `${series.name}: ${nearest.datum.value}` : undefined;\n\n opts.crosshair?.show(crosshairX, crosshairY, area.width, area.height, announceText);\n\n if (nearest && series) {\n opts.tooltip?.show(nearest.point.x + dims.margin.left, nearest.point.y + dims.margin.top, nearest.datum, series);\n opts.onHover?.({ datum: nearest.datum, originalEvent: event, series });\n }\n };\n\n const onMouseLeave = () => {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.onHover?.(null);\n };\n\n const onClick = (event: MouseEvent) => {\n if (!opts.onClick) return;\n\n const allPoints = opts.getPoints();\n\n if (allPoints.length === 0 || allPoints[0].length === 0) return;\n\n const dims = opts.dims();\n const pos = getMousePosition(opts.svg, event, dims.margin.left, dims.margin.top);\n const area = chartArea(dims.width, dims.height, dims.margin);\n\n if (pos.x < 0 || pos.x > area.width || pos.y < 0 || pos.y > area.height) return;\n\n const key = findNearestKey(opts.getData(), allPoints, pos.x);\n\n if (key === null) return;\n\n const nearest = findNearestSeries(opts.getData(), allPoints, key, pos.y);\n const series = nearest ? opts.getSeriesList()[nearest.seriesIndex] : undefined;\n\n if (nearest && series) {\n opts.onClick({ datum: nearest.datum, originalEvent: event, series });\n }\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const allData = opts.getData();\n const allPoints = opts.getPoints();\n const domain = [...new Map(allData.flat().map((datum) => [keyId(datum.key), datum.key])).values()];\n\n if (domain.length === 0) return;\n\n if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {\n event.preventDefault();\n keyboardIndex = Math.max(0, Math.min(domain.length - 1, keyboardIndex + (event.key === 'ArrowLeft' ? -1 : 1)));\n\n const key = domain[keyboardIndex]!;\n const candidate = findNearestSeries(allData, allPoints, key, Number.POSITIVE_INFINITY);\n const series = candidate ? opts.getSeriesList()[candidate.seriesIndex] : undefined;\n\n if (!candidate || !series) return;\n\n // Same dedup as onMouseMove — tooltip announces when present.\n const announceText = !opts.tooltip ? `${series.name}: ${candidate.datum.value}` : undefined;\n\n opts.crosshair?.show(candidate.point.x, candidate.point.y, opts.dims().width, opts.dims().height, announceText);\n opts.tooltip?.show(\n candidate.point.x + opts.dims().margin.left,\n candidate.point.y + opts.dims().margin.top,\n candidate.datum,\n series,\n );\n opts.onHover?.({ datum: candidate.datum, originalEvent: event, series });\n }\n\n if ((event.key === 'Enter' || event.key === ' ') && opts.onClick) {\n event.preventDefault();\n\n const key = domain[keyboardIndex]!;\n const candidate = findNearestSeries(allData, allPoints, key, Number.POSITIVE_INFINITY);\n const series = candidate ? opts.getSeriesList()[candidate.seriesIndex] : undefined;\n\n if (candidate && series) opts.onClick({ datum: candidate.datum, originalEvent: event, series });\n }\n\n if (event.key === 'Escape') {\n opts.crosshair?.hide();\n opts.tooltip?.hide();\n opts.onHover?.(null);\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave, onMouseMove };\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- require("../_dev.cjs");let e=require("@vielzeug/orbit");function t(t,n){getComputedStyle(t).position===`static`&&(t.style.position=`relative`);let r=t.ownerDocument.createElement(`div`);r.className=`prism-tooltip`,r.style.position=`absolute`,r.style.pointerEvents=`none`,r.style.top=`0`,r.style.left=`0`,r.setAttribute(`role`,`status`),r.setAttribute(`aria-live`,`polite`),t.appendChild(r);let i=n!==!0&&n?.offset||8,a=n===!0?void 0:n?.render,o=n===!0?void 0:n?.sanitize,s=null,c=null,l=!1,u=()=>{c!==null&&(clearTimeout(c),c=null)},d=()=>{s!==null&&(cancelAnimationFrame(s),s=null)},f=()=>{d(),u(),r.remove()};return{dispose:f,el:r,hide(){d(),u(),l=!1,r.style.opacity=`0`,c=setTimeout(()=>{c=null,l||(r.textContent=``)},150)},show(n,c,d,f){if(!t.isConnected)return;if(u(),a){let e=a(d,f);o?r.innerHTML=o(e):r.textContent=e}else r.textContent=`${f.name}: ${d.value}`;let{x:p,y:m}=(0,e.computePosition)({getBoundingClientRect:()=>{let e=t.getBoundingClientRect();return{bottom:e.top+c,height:0,left:e.left+n,right:e.left+n,top:e.top+c,width:0,x:e.left+n,y:e.top+c}}},r,{containingBlock:t,middleware:[(0,e.offset)(i),(0,e.flip)(),(0,e.shift)({padding:8})],placement:`top`});if(r.style.left=`${p}px`,r.style.top=`${m}px`,l){s===null&&(r.style.opacity=`1`);return}l=!0,r.style.opacity=`0`,s=requestAnimationFrame(()=>{s=null,l&&(r.style.opacity=`1`)})},[Symbol.dispose]:f}}exports.createTooltip=t;
1
+ let e=require("@vielzeug/orbit");function createTooltip(t,n){let r=t.style.position,i=getComputedStyle(t).position===`static`;i&&(t.style.position=`relative`);let a=t.ownerDocument.createElement(`div`);a.className=`prism-tooltip`,a.style.position=`absolute`,a.style.pointerEvents=`none`,a.style.top=`0`,a.style.left=`0`,a.setAttribute(`role`,`status`),a.setAttribute(`aria-live`,`polite`),t.appendChild(a);let o=n!==!0&&n?.offset||8,s=n===!0?void 0:n?.render,c=null,l=null,u=!1,cancelClear=()=>{l!==null&&(clearTimeout(l),l=null)},cancelReveal=()=>{c!==null&&(cancelAnimationFrame(c),c=null)},disposeHandle=()=>{cancelReveal(),cancelClear(),a.remove(),i&&t.style.position===`relative`&&(t.style.position=r)};return{dispose:disposeHandle,el:a,hide(){cancelReveal(),cancelClear(),u=!1,a.style.opacity=`0`,l=setTimeout(()=>{l=null,u||(a.textContent=``)},150)},show(n,r,i,l){if(!t.isConnected)return;if(cancelClear(),s){let e=s(i,l);typeof e==`string`?a.textContent=e:a.replaceChildren(e)}else a.textContent=`${l.name}: ${i.value}`;let{x:d,y:f}=(0,e.computePosition)({getBoundingClientRect:()=>{let e=t.getBoundingClientRect();return{bottom:e.top+r,height:0,left:e.left+n,right:e.left+n,top:e.top+r,width:0,x:e.left+n,y:e.top+r}}},a,{containingBlock:t,middleware:[(0,e.offset)(o),(0,e.flip)(),(0,e.shift)({padding:8})],placement:`top`});if(a.style.left=`${d}px`,a.style.top=`${f}px`,u){c===null&&(a.style.opacity=`1`);return}u=!0,a.style.opacity=`0`,c=requestAnimationFrame(()=>{c=null,u&&(a.style.opacity=`1`)})},[Symbol.dispose]:disposeHandle}}exports.createTooltip=createTooltip;
2
2
  //# sourceMappingURL=tooltip.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.cjs","names":[],"sources":["../../src/interaction/tooltip.ts"],"sourcesContent":["import { computePosition, flip, offset, shift } from '@vielzeug/orbit';\nimport { warn } from '../_dev';\nimport type { Datum, Series, TooltipConfig } from '../types';\n\nexport interface TooltipState {\n dispose(): void;\n el: HTMLDivElement | null;\n hide(): void;\n show(x: number, y: number, datum: Datum, series: Series): void;\n [Symbol.dispose](): void;\n}\n\nexport function createTooltip(container: HTMLElement, config?: TooltipConfig | true): TooltipState {\n if (getComputedStyle(container).position === 'static') {\n container.style.position = 'relative';\n }\n\n const el = container.ownerDocument.createElement('div');\n\n el.className = 'prism-tooltip';\n el.style.position = 'absolute';\n el.style.pointerEvents = 'none';\n el.style.top = '0';\n el.style.left = '0';\n // Non-modal status text — announced by assistive tech whenever content/hide state changes.\n el.setAttribute('role', 'status');\n el.setAttribute('aria-live', 'polite');\n container.appendChild(el);\n\n const tooltipOffset: number = (config !== true && config?.offset) || 8;\n const render = config !== true ? config?.render : undefined;\n const sanitize = config !== true ? config?.sanitize : undefined;\n\n if (render && !sanitize) {\n warn(\n 'createTooltip: `render` is set without `sanitize` — falling back to plain-text rendering of the returned string to avoid an XSS risk. Pass `sanitize` to render HTML.',\n );\n }\n\n let revealFrame: number | null = null;\n let clearTimer: ReturnType<typeof setTimeout> | null = null;\n let visible = false;\n\n const cancelClear = (): void => {\n if (clearTimer === null) return;\n\n clearTimeout(clearTimer);\n clearTimer = null;\n };\n\n const cancelReveal = (): void => {\n if (revealFrame === null) return;\n\n cancelAnimationFrame(revealFrame);\n revealFrame = null;\n };\n\n const disposeHandle = (): void => {\n cancelReveal();\n cancelClear();\n el.remove();\n };\n\n return {\n dispose: disposeHandle,\n el,\n hide() {\n cancelReveal();\n cancelClear();\n visible = false;\n el.style.opacity = '0';\n clearTimer = setTimeout(() => {\n clearTimer = null;\n\n if (!visible) el.textContent = '';\n }, 150);\n },\n show(x: number, y: number, datum: Datum, series: Series) {\n if (!container.isConnected) return;\n\n cancelClear();\n\n if (render) {\n const html = render(datum, series);\n\n if (sanitize) {\n el.innerHTML = sanitize(html);\n } else {\n // No sanitizer provided — never inject the raw string as HTML. Render it as text instead.\n el.textContent = html;\n }\n } else {\n el.textContent = `${series.name}: ${datum.value}`;\n }\n\n const virtualRef = {\n getBoundingClientRect: () => {\n const rect = container.getBoundingClientRect();\n\n return {\n bottom: rect.top + y,\n height: 0,\n left: rect.left + x,\n right: rect.left + x,\n top: rect.top + y,\n width: 0,\n x: rect.left + x,\n y: rect.top + y,\n };\n },\n };\n\n const { x: positionX, y: positionY } = computePosition(virtualRef, el, {\n containingBlock: container,\n middleware: [offset(tooltipOffset), flip(), shift({ padding: 8 })],\n placement: 'top',\n });\n\n el.style.left = `${positionX}px`;\n el.style.top = `${positionY}px`;\n\n if (visible) {\n if (revealFrame === null) el.style.opacity = '1';\n\n return;\n }\n\n visible = true;\n el.style.opacity = '0';\n revealFrame = requestAnimationFrame(() => {\n revealFrame = null;\n\n if (visible) el.style.opacity = '1';\n });\n },\n [Symbol.dispose]: disposeHandle,\n };\n}\n"],"mappings":"wDAYA,SAAgB,EAAc,EAAwB,EAA6C,CAC7F,iBAAiB,CAAS,CAAC,CAAC,WAAa,WAC3C,EAAU,MAAM,SAAW,YAG7B,IAAM,EAAK,EAAU,cAAc,cAAc,KAAK,EAEtD,EAAG,UAAY,gBACf,EAAG,MAAM,SAAW,WACpB,EAAG,MAAM,cAAgB,OACzB,EAAG,MAAM,IAAM,IACf,EAAG,MAAM,KAAO,IAEhB,EAAG,aAAa,OAAQ,QAAQ,EAChC,EAAG,aAAa,YAAa,QAAQ,EACrC,EAAU,YAAY,CAAE,EAExB,IAAM,EAAyB,IAAW,IAAQ,GAAQ,QAAW,EAC/D,EAAS,IAAW,GAAwB,IAAA,GAAjB,GAAQ,OACnC,EAAW,IAAW,GAA0B,IAAA,GAAnB,GAAQ,SAQvC,EAA6B,KAC7B,EAAmD,KACnD,EAAU,GAER,MAA0B,CAC1B,IAAe,OAEnB,aAAa,CAAU,EACvB,EAAa,KACf,EAEM,MAA2B,CAC3B,IAAgB,OAEpB,qBAAqB,CAAW,EAChC,EAAc,KAChB,EAEM,MAA4B,CAChC,EAAa,EACb,EAAY,EACZ,EAAG,OAAO,CACZ,EAEA,MAAO,CACL,QAAS,EACT,KACA,MAAO,CACL,EAAa,EACb,EAAY,EACZ,EAAU,GACV,EAAG,MAAM,QAAU,IACnB,EAAa,eAAiB,CAC5B,EAAa,KAER,IAAS,EAAG,YAAc,GACjC,EAAG,GAAG,CACR,EACA,KAAK,EAAW,EAAW,EAAc,EAAgB,CACvD,GAAI,CAAC,EAAU,YAAa,OAI5B,GAFA,EAAY,EAER,EAAQ,CACV,IAAM,EAAO,EAAO,EAAO,CAAM,EAE7B,EACF,EAAG,UAAY,EAAS,CAAI,EAG5B,EAAG,YAAc,CAErB,KACE,GAAG,YAAc,GAAG,EAAO,KAAK,IAAI,EAAM,QAoB5C,GAAM,CAAE,EAAG,EAAW,EAAG,IAAA,EAAc,EAAA,gBAAA,CAAgB,CAhBrD,0BAA6B,CAC3B,IAAM,EAAO,EAAU,sBAAsB,EAE7C,MAAO,CACL,OAAQ,EAAK,IAAM,EACnB,OAAQ,EACR,KAAM,EAAK,KAAO,EAClB,MAAO,EAAK,KAAO,EACnB,IAAK,EAAK,IAAM,EAChB,MAAO,EACP,EAAG,EAAK,KAAO,EACf,EAAG,EAAK,IAAM,CAChB,CACF,CAGqD,EAAY,EAAI,CACrE,gBAAiB,EACjB,WAAY,EAAC,EAAA,EAAA,OAAA,CAAO,CAAa,GAAG,EAAA,EAAA,KAAA,CAAK,GAAG,EAAA,EAAA,MAAA,CAAM,CAAE,QAAS,CAAE,CAAC,CAAC,EACjE,UAAW,KACb,CAAC,EAKD,GAHA,EAAG,MAAM,KAAO,GAAG,EAAU,IAC7B,EAAG,MAAM,IAAM,GAAG,EAAU,IAExB,EAAS,CACP,IAAgB,OAAM,EAAG,MAAM,QAAU,KAE7C,MACF,CAEA,EAAU,GACV,EAAG,MAAM,QAAU,IACnB,EAAc,0BAA4B,CACxC,EAAc,KAEV,IAAS,EAAG,MAAM,QAAU,IAClC,CAAC,CACH,GACC,OAAO,SAAU,CACpB,CACF"}
1
+ {"version":3,"file":"tooltip.cjs","names":[],"sources":["../../src/interaction/tooltip.ts"],"sourcesContent":["import { computePosition, flip, offset, shift } from '@vielzeug/orbit';\nimport type { Datum, Series, TooltipConfig } from '../types';\n\nexport interface TooltipState {\n dispose(): void;\n el: HTMLDivElement | null;\n hide(): void;\n show(x: number, y: number, datum: Datum, series: Series): void;\n [Symbol.dispose](): void;\n}\n\nexport function createTooltip(container: HTMLElement, config?: TooltipConfig | true): TooltipState {\n const previousPosition = container.style.position;\n const changedPosition = getComputedStyle(container).position === 'static';\n\n if (changedPosition) container.style.position = 'relative';\n\n const el = container.ownerDocument.createElement('div');\n\n el.className = 'prism-tooltip';\n el.style.position = 'absolute';\n el.style.pointerEvents = 'none';\n el.style.top = '0';\n el.style.left = '0';\n // Non-modal status text — announced by assistive tech whenever content/hide state changes.\n el.setAttribute('role', 'status');\n el.setAttribute('aria-live', 'polite');\n container.appendChild(el);\n\n const tooltipOffset: number = (config !== true && config?.offset) || 8;\n const render = config !== true ? config?.render : undefined;\n\n let revealFrame: number | null = null;\n let clearTimer: ReturnType<typeof setTimeout> | null = null;\n let visible = false;\n\n const cancelClear = (): void => {\n if (clearTimer === null) return;\n\n clearTimeout(clearTimer);\n clearTimer = null;\n };\n\n const cancelReveal = (): void => {\n if (revealFrame === null) return;\n\n cancelAnimationFrame(revealFrame);\n revealFrame = null;\n };\n\n const disposeHandle = (): void => {\n cancelReveal();\n cancelClear();\n el.remove();\n if (changedPosition && container.style.position === 'relative') container.style.position = previousPosition;\n };\n\n return {\n dispose: disposeHandle,\n el,\n hide() {\n cancelReveal();\n cancelClear();\n visible = false;\n el.style.opacity = '0';\n clearTimer = setTimeout(() => {\n clearTimer = null;\n\n if (!visible) el.textContent = '';\n }, 150);\n },\n show(x: number, y: number, datum: Datum, series: Series) {\n if (!container.isConnected) return;\n\n cancelClear();\n\n if (render) {\n const content = render(datum, series);\n\n if (typeof content === 'string') el.textContent = content;\n else el.replaceChildren(content);\n } else {\n el.textContent = `${series.name}: ${datum.value}`;\n }\n\n const virtualRef = {\n getBoundingClientRect: () => {\n const rect = container.getBoundingClientRect();\n\n return {\n bottom: rect.top + y,\n height: 0,\n left: rect.left + x,\n right: rect.left + x,\n top: rect.top + y,\n width: 0,\n x: rect.left + x,\n y: rect.top + y,\n };\n },\n };\n\n const { x: positionX, y: positionY } = computePosition(virtualRef, el, {\n containingBlock: container,\n middleware: [offset(tooltipOffset), flip(), shift({ padding: 8 })],\n placement: 'top',\n });\n\n el.style.left = `${positionX}px`;\n el.style.top = `${positionY}px`;\n\n if (visible) {\n if (revealFrame === null) el.style.opacity = '1';\n\n return;\n }\n\n visible = true;\n el.style.opacity = '0';\n revealFrame = requestAnimationFrame(() => {\n revealFrame = null;\n\n if (visible) el.style.opacity = '1';\n });\n },\n [Symbol.dispose]: disposeHandle,\n };\n}\n"],"mappings":"iCAWA,SAAgB,cAAc,EAAwB,EAA6C,CACjG,IAAM,EAAmB,EAAU,MAAM,SACnC,EAAkB,iBAAiB,CAAS,CAAC,CAAC,WAAa,SAE7D,IAAiB,EAAU,MAAM,SAAW,YAEhD,IAAM,EAAK,EAAU,cAAc,cAAc,KAAK,EAEtD,EAAG,UAAY,gBACf,EAAG,MAAM,SAAW,WACpB,EAAG,MAAM,cAAgB,OACzB,EAAG,MAAM,IAAM,IACf,EAAG,MAAM,KAAO,IAEhB,EAAG,aAAa,OAAQ,QAAQ,EAChC,EAAG,aAAa,YAAa,QAAQ,EACrC,EAAU,YAAY,CAAE,EAExB,IAAM,EAAyB,IAAW,IAAQ,GAAQ,QAAW,EAC/D,EAAS,IAAW,GAAwB,IAAA,GAAjB,GAAQ,OAErC,EAA6B,KAC7B,EAAmD,KACnD,EAAU,GAER,gBAA0B,CAC1B,IAAe,OAEnB,aAAa,CAAU,EACvB,EAAa,KACf,EAEM,iBAA2B,CAC3B,IAAgB,OAEpB,qBAAqB,CAAW,EAChC,EAAc,KAChB,EAEM,kBAA4B,CAChC,aAAa,EACb,YAAY,EACZ,EAAG,OAAO,EACN,GAAmB,EAAU,MAAM,WAAa,aAAY,EAAU,MAAM,SAAW,EAC7F,EAEA,MAAO,CACL,QAAS,cACT,KACA,MAAO,CACL,aAAa,EACb,YAAY,EACZ,EAAU,GACV,EAAG,MAAM,QAAU,IACnB,EAAa,eAAiB,CAC5B,EAAa,KAER,IAAS,EAAG,YAAc,GACjC,EAAG,GAAG,CACR,EACA,KAAK,EAAW,EAAW,EAAc,EAAgB,CACvD,GAAI,CAAC,EAAU,YAAa,OAI5B,GAFA,YAAY,EAER,EAAQ,CACV,IAAM,EAAU,EAAO,EAAO,CAAM,EAEhC,OAAO,GAAY,SAAU,EAAG,YAAc,EAC7C,EAAG,gBAAgB,CAAO,CACjC,KACE,GAAG,YAAc,GAAG,EAAO,KAAK,IAAI,EAAM,QAoB5C,GAAM,CAAE,EAAG,EAAW,EAAG,IAAA,EAAc,EAAA,gBAAA,CAAgB,CAhBrD,0BAA6B,CAC3B,IAAM,EAAO,EAAU,sBAAsB,EAE7C,MAAO,CACL,OAAQ,EAAK,IAAM,EACnB,OAAQ,EACR,KAAM,EAAK,KAAO,EAClB,MAAO,EAAK,KAAO,EACnB,IAAK,EAAK,IAAM,EAChB,MAAO,EACP,EAAG,EAAK,KAAO,EACf,EAAG,EAAK,IAAM,CAChB,CACF,CAGqD,EAAY,EAAI,CACrE,gBAAiB,EACjB,WAAY,EAAC,EAAA,EAAA,OAAA,CAAO,CAAa,GAAG,EAAA,EAAA,KAAA,CAAK,GAAG,EAAA,EAAA,MAAA,CAAM,CAAE,QAAS,CAAE,CAAC,CAAC,EACjE,UAAW,KACb,CAAC,EAKD,GAHA,EAAG,MAAM,KAAO,GAAG,EAAU,IAC7B,EAAG,MAAM,IAAM,GAAG,EAAU,IAExB,EAAS,CACP,IAAgB,OAAM,EAAG,MAAM,QAAU,KAE7C,MACF,CAEA,EAAU,GACV,EAAG,MAAM,QAAU,IACnB,EAAc,0BAA4B,CACxC,EAAc,KAEV,IAAS,EAAG,MAAM,QAAU,IAClC,CAAC,CACH,GACC,OAAO,SAAU,aACpB,CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../src/interaction/tooltip.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,OAAO,IAAI,IAAI,CAAC;IAChB,EAAE,EAAE,cAAc,GAAG,IAAI,CAAC;IAC1B,IAAI,IAAI,IAAI,CAAC;IACb,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI,GAAG,YAAY,CA6HjG"}
1
+ {"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../src/interaction/tooltip.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,OAAO,IAAI,IAAI,CAAC;IAChB,EAAE,EAAE,cAAc,GAAG,IAAI,CAAC;IAC1B,IAAI,IAAI,IAAI,CAAC;IACb,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI,GAAG,YAAY,CAoHjG"}
@@ -1,64 +1,2 @@
1
- import "../_dev.js";
2
- import { computePosition as e, flip as t, offset as n, shift as r } from "@vielzeug/orbit";
3
- //#region src/interaction/tooltip.ts
4
- function i(i, a) {
5
- getComputedStyle(i).position === "static" && (i.style.position = "relative");
6
- let o = i.ownerDocument.createElement("div");
7
- o.className = "prism-tooltip", o.style.position = "absolute", o.style.pointerEvents = "none", o.style.top = "0", o.style.left = "0", o.setAttribute("role", "status"), o.setAttribute("aria-live", "polite"), i.appendChild(o);
8
- let s = a !== !0 && a?.offset || 8, c = a === !0 ? void 0 : a?.render, l = a === !0 ? void 0 : a?.sanitize, u = null, d = null, f = !1, p = () => {
9
- d !== null && (clearTimeout(d), d = null);
10
- }, m = () => {
11
- u !== null && (cancelAnimationFrame(u), u = null);
12
- }, h = () => {
13
- m(), p(), o.remove();
14
- };
15
- return {
16
- dispose: h,
17
- el: o,
18
- hide() {
19
- m(), p(), f = !1, o.style.opacity = "0", d = setTimeout(() => {
20
- d = null, f || (o.textContent = "");
21
- }, 150);
22
- },
23
- show(a, d, m, h) {
24
- if (!i.isConnected) return;
25
- if (p(), c) {
26
- let e = c(m, h);
27
- l ? o.innerHTML = l(e) : o.textContent = e;
28
- } else o.textContent = `${h.name}: ${m.value}`;
29
- let { x: g, y: _ } = e({ getBoundingClientRect: () => {
30
- let e = i.getBoundingClientRect();
31
- return {
32
- bottom: e.top + d,
33
- height: 0,
34
- left: e.left + a,
35
- right: e.left + a,
36
- top: e.top + d,
37
- width: 0,
38
- x: e.left + a,
39
- y: e.top + d
40
- };
41
- } }, o, {
42
- containingBlock: i,
43
- middleware: [
44
- n(s),
45
- t(),
46
- r({ padding: 8 })
47
- ],
48
- placement: "top"
49
- });
50
- if (o.style.left = `${g}px`, o.style.top = `${_}px`, f) {
51
- u === null && (o.style.opacity = "1");
52
- return;
53
- }
54
- f = !0, o.style.opacity = "0", u = requestAnimationFrame(() => {
55
- u = null, f && (o.style.opacity = "1");
56
- });
57
- },
58
- [Symbol.dispose]: h
59
- };
60
- }
61
- //#endregion
62
- export { i as createTooltip };
63
-
1
+ import{computePosition as e,flip as t,offset as n,shift as r}from"@vielzeug/orbit";function createTooltip(i,a){let o=i.style.position,s=getComputedStyle(i).position===`static`;s&&(i.style.position=`relative`);let c=i.ownerDocument.createElement(`div`);c.className=`prism-tooltip`,c.style.position=`absolute`,c.style.pointerEvents=`none`,c.style.top=`0`,c.style.left=`0`,c.setAttribute(`role`,`status`),c.setAttribute(`aria-live`,`polite`),i.appendChild(c);let l=a!==!0&&a?.offset||8,u=a===!0?void 0:a?.render,d=null,f=null,p=!1,cancelClear=()=>{f!==null&&(clearTimeout(f),f=null)},cancelReveal=()=>{d!==null&&(cancelAnimationFrame(d),d=null)},disposeHandle=()=>{cancelReveal(),cancelClear(),c.remove(),s&&i.style.position===`relative`&&(i.style.position=o)};return{dispose:disposeHandle,el:c,hide(){cancelReveal(),cancelClear(),p=!1,c.style.opacity=`0`,f=setTimeout(()=>{f=null,p||(c.textContent=``)},150)},show(a,o,s,f){if(!i.isConnected)return;if(cancelClear(),u){let e=u(s,f);typeof e==`string`?c.textContent=e:c.replaceChildren(e)}else c.textContent=`${f.name}: ${s.value}`;let{x:m,y:h}=e({getBoundingClientRect:()=>{let e=i.getBoundingClientRect();return{bottom:e.top+o,height:0,left:e.left+a,right:e.left+a,top:e.top+o,width:0,x:e.left+a,y:e.top+o}}},c,{containingBlock:i,middleware:[n(l),t(),r({padding:8})],placement:`top`});if(c.style.left=`${m}px`,c.style.top=`${h}px`,p){d===null&&(c.style.opacity=`1`);return}p=!0,c.style.opacity=`0`,d=requestAnimationFrame(()=>{d=null,p&&(c.style.opacity=`1`)})},[Symbol.dispose]:disposeHandle}}export{createTooltip};
64
2
  //# sourceMappingURL=tooltip.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.js","names":[],"sources":["../../src/interaction/tooltip.ts"],"sourcesContent":["import { computePosition, flip, offset, shift } from '@vielzeug/orbit';\nimport { warn } from '../_dev';\nimport type { Datum, Series, TooltipConfig } from '../types';\n\nexport interface TooltipState {\n dispose(): void;\n el: HTMLDivElement | null;\n hide(): void;\n show(x: number, y: number, datum: Datum, series: Series): void;\n [Symbol.dispose](): void;\n}\n\nexport function createTooltip(container: HTMLElement, config?: TooltipConfig | true): TooltipState {\n if (getComputedStyle(container).position === 'static') {\n container.style.position = 'relative';\n }\n\n const el = container.ownerDocument.createElement('div');\n\n el.className = 'prism-tooltip';\n el.style.position = 'absolute';\n el.style.pointerEvents = 'none';\n el.style.top = '0';\n el.style.left = '0';\n // Non-modal status text — announced by assistive tech whenever content/hide state changes.\n el.setAttribute('role', 'status');\n el.setAttribute('aria-live', 'polite');\n container.appendChild(el);\n\n const tooltipOffset: number = (config !== true && config?.offset) || 8;\n const render = config !== true ? config?.render : undefined;\n const sanitize = config !== true ? config?.sanitize : undefined;\n\n if (render && !sanitize) {\n warn(\n 'createTooltip: `render` is set without `sanitize` — falling back to plain-text rendering of the returned string to avoid an XSS risk. Pass `sanitize` to render HTML.',\n );\n }\n\n let revealFrame: number | null = null;\n let clearTimer: ReturnType<typeof setTimeout> | null = null;\n let visible = false;\n\n const cancelClear = (): void => {\n if (clearTimer === null) return;\n\n clearTimeout(clearTimer);\n clearTimer = null;\n };\n\n const cancelReveal = (): void => {\n if (revealFrame === null) return;\n\n cancelAnimationFrame(revealFrame);\n revealFrame = null;\n };\n\n const disposeHandle = (): void => {\n cancelReveal();\n cancelClear();\n el.remove();\n };\n\n return {\n dispose: disposeHandle,\n el,\n hide() {\n cancelReveal();\n cancelClear();\n visible = false;\n el.style.opacity = '0';\n clearTimer = setTimeout(() => {\n clearTimer = null;\n\n if (!visible) el.textContent = '';\n }, 150);\n },\n show(x: number, y: number, datum: Datum, series: Series) {\n if (!container.isConnected) return;\n\n cancelClear();\n\n if (render) {\n const html = render(datum, series);\n\n if (sanitize) {\n el.innerHTML = sanitize(html);\n } else {\n // No sanitizer provided — never inject the raw string as HTML. Render it as text instead.\n el.textContent = html;\n }\n } else {\n el.textContent = `${series.name}: ${datum.value}`;\n }\n\n const virtualRef = {\n getBoundingClientRect: () => {\n const rect = container.getBoundingClientRect();\n\n return {\n bottom: rect.top + y,\n height: 0,\n left: rect.left + x,\n right: rect.left + x,\n top: rect.top + y,\n width: 0,\n x: rect.left + x,\n y: rect.top + y,\n };\n },\n };\n\n const { x: positionX, y: positionY } = computePosition(virtualRef, el, {\n containingBlock: container,\n middleware: [offset(tooltipOffset), flip(), shift({ padding: 8 })],\n placement: 'top',\n });\n\n el.style.left = `${positionX}px`;\n el.style.top = `${positionY}px`;\n\n if (visible) {\n if (revealFrame === null) el.style.opacity = '1';\n\n return;\n }\n\n visible = true;\n el.style.opacity = '0';\n revealFrame = requestAnimationFrame(() => {\n revealFrame = null;\n\n if (visible) el.style.opacity = '1';\n });\n },\n [Symbol.dispose]: disposeHandle,\n };\n}\n"],"mappings":";;;AAYA,SAAgB,EAAc,GAAwB,GAA6C;CACjG,AAAI,iBAAiB,CAAS,CAAC,CAAC,aAAa,aAC3C,EAAU,MAAM,WAAW;CAG7B,IAAM,IAAK,EAAU,cAAc,cAAc,KAAK;CAUtD,AARA,EAAG,YAAY,iBACf,EAAG,MAAM,WAAW,YACpB,EAAG,MAAM,gBAAgB,QACzB,EAAG,MAAM,MAAM,KACf,EAAG,MAAM,OAAO,KAEhB,EAAG,aAAa,QAAQ,QAAQ,GAChC,EAAG,aAAa,aAAa,QAAQ,GACrC,EAAU,YAAY,CAAE;CAExB,IAAM,IAAyB,MAAW,MAAQ,GAAQ,UAAW,GAC/D,IAAS,MAAW,KAAwB,KAAA,IAAjB,GAAQ,QACnC,IAAW,MAAW,KAA0B,KAAA,IAAnB,GAAQ,UAQvC,IAA6B,MAC7B,IAAmD,MACnD,IAAU,IAER,UAA0B;EAC1B,MAAe,SAEnB,aAAa,CAAU,GACvB,IAAa;CACf,GAEM,UAA2B;EAC3B,MAAgB,SAEpB,qBAAqB,CAAW,GAChC,IAAc;CAChB,GAEM,UAA4B;EAGhC,AAFA,EAAa,GACb,EAAY,GACZ,EAAG,OAAO;CACZ;CAEA,OAAO;EACL,SAAS;EACT;EACA,OAAO;GAKL,AAJA,EAAa,GACb,EAAY,GACZ,IAAU,IACV,EAAG,MAAM,UAAU,KACnB,IAAa,iBAAiB;IAG5B,AAFA,IAAa,MAER,MAAS,EAAG,cAAc;GACjC,GAAG,GAAG;EACR;EACA,KAAK,GAAW,GAAW,GAAc,GAAgB;GACvD,IAAI,CAAC,EAAU,aAAa;GAI5B,IAFA,EAAY,GAER,GAAQ;IACV,IAAM,IAAO,EAAO,GAAO,CAAM;IAEjC,AAAI,IACF,EAAG,YAAY,EAAS,CAAI,IAG5B,EAAG,cAAc;GAErB,OACE,EAAG,cAAc,GAAG,EAAO,KAAK,IAAI,EAAM;GAoB5C,IAAM,EAAE,GAAG,GAAW,GAAG,MAAc,EAAgB,EAhBrD,6BAA6B;IAC3B,IAAM,IAAO,EAAU,sBAAsB;IAE7C,OAAO;KACL,QAAQ,EAAK,MAAM;KACnB,QAAQ;KACR,MAAM,EAAK,OAAO;KAClB,OAAO,EAAK,OAAO;KACnB,KAAK,EAAK,MAAM;KAChB,OAAO;KACP,GAAG,EAAK,OAAO;KACf,GAAG,EAAK,MAAM;IAChB;GACF,EAGqD,GAAY,GAAI;IACrE,iBAAiB;IACjB,YAAY;KAAC,EAAO,CAAa;KAAG,EAAK;KAAG,EAAM,EAAE,SAAS,EAAE,CAAC;IAAC;IACjE,WAAW;GACb,CAAC;GAKD,IAHA,EAAG,MAAM,OAAO,GAAG,EAAU,KAC7B,EAAG,MAAM,MAAM,GAAG,EAAU,KAExB,GAAS;IACX,AAAI,MAAgB,SAAM,EAAG,MAAM,UAAU;IAE7C;GACF;GAIA,AAFA,IAAU,IACV,EAAG,MAAM,UAAU,KACnB,IAAc,4BAA4B;IAGxC,AAFA,IAAc,MAEV,MAAS,EAAG,MAAM,UAAU;GAClC,CAAC;EACH;GACC,OAAO,UAAU;CACpB;AACF"}
1
+ {"version":3,"file":"tooltip.js","names":[],"sources":["../../src/interaction/tooltip.ts"],"sourcesContent":["import { computePosition, flip, offset, shift } from '@vielzeug/orbit';\nimport type { Datum, Series, TooltipConfig } from '../types';\n\nexport interface TooltipState {\n dispose(): void;\n el: HTMLDivElement | null;\n hide(): void;\n show(x: number, y: number, datum: Datum, series: Series): void;\n [Symbol.dispose](): void;\n}\n\nexport function createTooltip(container: HTMLElement, config?: TooltipConfig | true): TooltipState {\n const previousPosition = container.style.position;\n const changedPosition = getComputedStyle(container).position === 'static';\n\n if (changedPosition) container.style.position = 'relative';\n\n const el = container.ownerDocument.createElement('div');\n\n el.className = 'prism-tooltip';\n el.style.position = 'absolute';\n el.style.pointerEvents = 'none';\n el.style.top = '0';\n el.style.left = '0';\n // Non-modal status text — announced by assistive tech whenever content/hide state changes.\n el.setAttribute('role', 'status');\n el.setAttribute('aria-live', 'polite');\n container.appendChild(el);\n\n const tooltipOffset: number = (config !== true && config?.offset) || 8;\n const render = config !== true ? config?.render : undefined;\n\n let revealFrame: number | null = null;\n let clearTimer: ReturnType<typeof setTimeout> | null = null;\n let visible = false;\n\n const cancelClear = (): void => {\n if (clearTimer === null) return;\n\n clearTimeout(clearTimer);\n clearTimer = null;\n };\n\n const cancelReveal = (): void => {\n if (revealFrame === null) return;\n\n cancelAnimationFrame(revealFrame);\n revealFrame = null;\n };\n\n const disposeHandle = (): void => {\n cancelReveal();\n cancelClear();\n el.remove();\n if (changedPosition && container.style.position === 'relative') container.style.position = previousPosition;\n };\n\n return {\n dispose: disposeHandle,\n el,\n hide() {\n cancelReveal();\n cancelClear();\n visible = false;\n el.style.opacity = '0';\n clearTimer = setTimeout(() => {\n clearTimer = null;\n\n if (!visible) el.textContent = '';\n }, 150);\n },\n show(x: number, y: number, datum: Datum, series: Series) {\n if (!container.isConnected) return;\n\n cancelClear();\n\n if (render) {\n const content = render(datum, series);\n\n if (typeof content === 'string') el.textContent = content;\n else el.replaceChildren(content);\n } else {\n el.textContent = `${series.name}: ${datum.value}`;\n }\n\n const virtualRef = {\n getBoundingClientRect: () => {\n const rect = container.getBoundingClientRect();\n\n return {\n bottom: rect.top + y,\n height: 0,\n left: rect.left + x,\n right: rect.left + x,\n top: rect.top + y,\n width: 0,\n x: rect.left + x,\n y: rect.top + y,\n };\n },\n };\n\n const { x: positionX, y: positionY } = computePosition(virtualRef, el, {\n containingBlock: container,\n middleware: [offset(tooltipOffset), flip(), shift({ padding: 8 })],\n placement: 'top',\n });\n\n el.style.left = `${positionX}px`;\n el.style.top = `${positionY}px`;\n\n if (visible) {\n if (revealFrame === null) el.style.opacity = '1';\n\n return;\n }\n\n visible = true;\n el.style.opacity = '0';\n revealFrame = requestAnimationFrame(() => {\n revealFrame = null;\n\n if (visible) el.style.opacity = '1';\n });\n },\n [Symbol.dispose]: disposeHandle,\n };\n}\n"],"mappings":"mFAWA,SAAgB,cAAc,EAAwB,EAA6C,CACjG,IAAM,EAAmB,EAAU,MAAM,SACnC,EAAkB,iBAAiB,CAAS,CAAC,CAAC,WAAa,SAE7D,IAAiB,EAAU,MAAM,SAAW,YAEhD,IAAM,EAAK,EAAU,cAAc,cAAc,KAAK,EAEtD,EAAG,UAAY,gBACf,EAAG,MAAM,SAAW,WACpB,EAAG,MAAM,cAAgB,OACzB,EAAG,MAAM,IAAM,IACf,EAAG,MAAM,KAAO,IAEhB,EAAG,aAAa,OAAQ,QAAQ,EAChC,EAAG,aAAa,YAAa,QAAQ,EACrC,EAAU,YAAY,CAAE,EAExB,IAAM,EAAyB,IAAW,IAAQ,GAAQ,QAAW,EAC/D,EAAS,IAAW,GAAwB,IAAA,GAAjB,GAAQ,OAErC,EAA6B,KAC7B,EAAmD,KACnD,EAAU,GAER,gBAA0B,CAC1B,IAAe,OAEnB,aAAa,CAAU,EACvB,EAAa,KACf,EAEM,iBAA2B,CAC3B,IAAgB,OAEpB,qBAAqB,CAAW,EAChC,EAAc,KAChB,EAEM,kBAA4B,CAChC,aAAa,EACb,YAAY,EACZ,EAAG,OAAO,EACN,GAAmB,EAAU,MAAM,WAAa,aAAY,EAAU,MAAM,SAAW,EAC7F,EAEA,MAAO,CACL,QAAS,cACT,KACA,MAAO,CACL,aAAa,EACb,YAAY,EACZ,EAAU,GACV,EAAG,MAAM,QAAU,IACnB,EAAa,eAAiB,CAC5B,EAAa,KAER,IAAS,EAAG,YAAc,GACjC,EAAG,GAAG,CACR,EACA,KAAK,EAAW,EAAW,EAAc,EAAgB,CACvD,GAAI,CAAC,EAAU,YAAa,OAI5B,GAFA,YAAY,EAER,EAAQ,CACV,IAAM,EAAU,EAAO,EAAO,CAAM,EAEhC,OAAO,GAAY,SAAU,EAAG,YAAc,EAC7C,EAAG,gBAAgB,CAAO,CACjC,KACE,GAAG,YAAc,GAAG,EAAO,KAAK,IAAI,EAAM,QAoB5C,GAAM,CAAE,EAAG,EAAW,EAAG,GAAc,EAAgB,CAhBrD,0BAA6B,CAC3B,IAAM,EAAO,EAAU,sBAAsB,EAE7C,MAAO,CACL,OAAQ,EAAK,IAAM,EACnB,OAAQ,EACR,KAAM,EAAK,KAAO,EAClB,MAAO,EAAK,KAAO,EACnB,IAAK,EAAK,IAAM,EAChB,MAAO,EACP,EAAG,EAAK,KAAO,EACf,EAAG,EAAK,IAAM,CAChB,CACF,CAGqD,EAAY,EAAI,CACrE,gBAAiB,EACjB,WAAY,CAAC,EAAO,CAAa,EAAG,EAAK,EAAG,EAAM,CAAE,QAAS,CAAE,CAAC,CAAC,EACjE,UAAW,KACb,CAAC,EAKD,GAHA,EAAG,MAAM,KAAO,GAAG,EAAU,IAC7B,EAAG,MAAM,IAAM,GAAG,EAAU,IAExB,EAAS,CACP,IAAgB,OAAM,EAAG,MAAM,QAAU,KAE7C,MACF,CAEA,EAAU,GACV,EAAG,MAAM,QAAU,IACnB,EAAc,0BAA4B,CACxC,EAAc,KAEV,IAAS,EAAG,MAAM,QAAU,IAClC,CAAC,CACH,GACC,OAAO,SAAU,aACpB,CACF"}