@vielzeug/prism 26.10.4 → 26.10.6

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 (119) hide show
  1. package/README.md +15 -26
  2. package/dist/animation/reveal.cjs +2 -0
  3. package/dist/animation/reveal.cjs.map +1 -0
  4. package/dist/animation/reveal.d.ts +29 -0
  5. package/dist/animation/reveal.d.ts.map +1 -0
  6. package/dist/animation/reveal.js +2 -0
  7. package/dist/animation/reveal.js.map +1 -0
  8. package/dist/axes/axis.cjs +1 -1
  9. package/dist/axes/axis.cjs.map +1 -1
  10. package/dist/axes/axis.d.ts +10 -3
  11. package/dist/axes/axis.d.ts.map +1 -1
  12. package/dist/axes/axis.js +1 -1
  13. package/dist/axes/axis.js.map +1 -1
  14. package/dist/axes/grid.cjs +1 -1
  15. package/dist/axes/grid.cjs.map +1 -1
  16. package/dist/axes/grid.d.ts +1 -1
  17. package/dist/axes/grid.d.ts.map +1 -1
  18. package/dist/axes/grid.js +1 -1
  19. package/dist/axes/grid.js.map +1 -1
  20. package/dist/charts/area/area-chart.cjs +1 -1
  21. package/dist/charts/area/area-chart.cjs.map +1 -1
  22. package/dist/charts/area/area-chart.d.ts.map +1 -1
  23. package/dist/charts/area/area-chart.js +1 -1
  24. package/dist/charts/area/area-chart.js.map +1 -1
  25. package/dist/charts/bar/bar-chart.cjs +1 -1
  26. package/dist/charts/bar/bar-chart.cjs.map +1 -1
  27. package/dist/charts/bar/bar-chart.d.ts.map +1 -1
  28. package/dist/charts/bar/bar-chart.js +1 -1
  29. package/dist/charts/bar/bar-chart.js.map +1 -1
  30. package/dist/charts/bar/bar-renderer.cjs +1 -1
  31. package/dist/charts/bar/bar-renderer.cjs.map +1 -1
  32. package/dist/charts/bar/bar-renderer.d.ts.map +1 -1
  33. package/dist/charts/bar/bar-renderer.js +1 -1
  34. package/dist/charts/bar/bar-renderer.js.map +1 -1
  35. package/dist/charts/line/line-chart.cjs +1 -1
  36. package/dist/charts/line/line-chart.cjs.map +1 -1
  37. package/dist/charts/line/line-chart.d.ts.map +1 -1
  38. package/dist/charts/line/line-chart.js +1 -1
  39. package/dist/charts/line/line-chart.js.map +1 -1
  40. package/dist/charts/line/line-renderer.cjs +1 -1
  41. package/dist/charts/line/line-renderer.cjs.map +1 -1
  42. package/dist/charts/line/line-renderer.d.ts +5 -2
  43. package/dist/charts/line/line-renderer.d.ts.map +1 -1
  44. package/dist/charts/line/line-renderer.js +1 -1
  45. package/dist/charts/line/line-renderer.js.map +1 -1
  46. package/dist/charts/pie/pie-chart.cjs +1 -1
  47. package/dist/charts/pie/pie-chart.cjs.map +1 -1
  48. package/dist/charts/pie/pie-chart.d.ts.map +1 -1
  49. package/dist/charts/pie/pie-chart.js +1 -1
  50. package/dist/charts/pie/pie-chart.js.map +1 -1
  51. package/dist/charts/scatter/index.d.ts +2 -0
  52. package/dist/charts/scatter/index.d.ts.map +1 -0
  53. package/dist/charts/scatter/scatter-chart.cjs +2 -0
  54. package/dist/charts/scatter/scatter-chart.cjs.map +1 -0
  55. package/dist/charts/scatter/scatter-chart.d.ts +3 -0
  56. package/dist/charts/scatter/scatter-chart.d.ts.map +1 -0
  57. package/dist/charts/scatter/scatter-chart.js +2 -0
  58. package/dist/charts/scatter/scatter-chart.js.map +1 -0
  59. package/dist/charts/scatter/scatter-renderer.cjs +2 -0
  60. package/dist/charts/scatter/scatter-renderer.cjs.map +1 -0
  61. package/dist/charts/scatter/scatter-renderer.d.ts +24 -0
  62. package/dist/charts/scatter/scatter-renderer.d.ts.map +1 -0
  63. package/dist/charts/scatter/scatter-renderer.js +2 -0
  64. package/dist/charts/scatter/scatter-renderer.js.map +1 -0
  65. package/dist/core/chart-base.cjs +1 -1
  66. package/dist/core/chart-base.cjs.map +1 -1
  67. package/dist/core/chart-base.d.ts +1 -0
  68. package/dist/core/chart-base.d.ts.map +1 -1
  69. package/dist/core/chart-base.js +1 -1
  70. package/dist/core/chart-base.js.map +1 -1
  71. package/dist/core/chart-scaffold.cjs +1 -1
  72. package/dist/core/chart-scaffold.cjs.map +1 -1
  73. package/dist/core/chart-scaffold.d.ts +4 -2
  74. package/dist/core/chart-scaffold.d.ts.map +1 -1
  75. package/dist/core/chart-scaffold.js +1 -1
  76. package/dist/core/chart-scaffold.js.map +1 -1
  77. package/dist/index.cjs +1 -1
  78. package/dist/index.d.ts +2 -1
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +1 -1
  81. package/dist/interaction/announcer.cjs +1 -1
  82. package/dist/interaction/announcer.cjs.map +1 -1
  83. package/dist/interaction/announcer.d.ts +1 -1
  84. package/dist/interaction/announcer.d.ts.map +1 -1
  85. package/dist/interaction/announcer.js +1 -1
  86. package/dist/interaction/announcer.js.map +1 -1
  87. package/dist/interaction/legend.cjs +1 -1
  88. package/dist/interaction/legend.cjs.map +1 -1
  89. package/dist/interaction/legend.d.ts +1 -1
  90. package/dist/interaction/legend.d.ts.map +1 -1
  91. package/dist/interaction/legend.js +1 -1
  92. package/dist/interaction/legend.js.map +1 -1
  93. package/dist/interaction/scatter-interaction.cjs +2 -0
  94. package/dist/interaction/scatter-interaction.cjs.map +1 -0
  95. package/dist/interaction/scatter-interaction.d.ts +36 -0
  96. package/dist/interaction/scatter-interaction.d.ts.map +1 -0
  97. package/dist/interaction/scatter-interaction.js +2 -0
  98. package/dist/interaction/scatter-interaction.js.map +1 -0
  99. package/dist/interaction/series-interaction.cjs +1 -1
  100. package/dist/interaction/series-interaction.cjs.map +1 -1
  101. package/dist/interaction/series-interaction.d.ts +3 -1
  102. package/dist/interaction/series-interaction.d.ts.map +1 -1
  103. package/dist/interaction/series-interaction.js +1 -1
  104. package/dist/interaction/series-interaction.js.map +1 -1
  105. package/dist/interaction/tooltip.cjs +1 -1
  106. package/dist/interaction/tooltip.cjs.map +1 -1
  107. package/dist/interaction/tooltip.d.ts.map +1 -1
  108. package/dist/interaction/tooltip.js +1 -1
  109. package/dist/interaction/tooltip.js.map +1 -1
  110. package/dist/prism.cjs +1 -1
  111. package/dist/prism.cjs.map +1 -1
  112. package/dist/prism.iife.js +1 -1
  113. package/dist/prism.iife.js.map +1 -1
  114. package/dist/prism.js +1 -1
  115. package/dist/prism.js.map +1 -1
  116. package/dist/theme/prism.css +6 -0
  117. package/dist/types.d.ts +39 -6
  118. package/dist/types.d.ts.map +1 -1
  119. package/package.json +4 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scatter-chart.js","names":[],"sources":["../../../src/charts/scatter/scatter-chart.ts"],"sourcesContent":["import { positionAxis, renderAxis, resolveTickCount, resolveTicks } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { buildXScale, buildYScale } from '../../core/cartesian-scales';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createScatterInteraction } from '../../interaction/scatter-interaction';\nimport { ensureMarkerGroup } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, ScatterChartConfig, ScatterSeriesConfig, XAxisConfig, YAxisConfig } from '../../types';\nimport { computeScatterPoints, renderScatterPoints } from './scatter-renderer';\n\nexport function createScatterChart(\n container: HTMLElement,\n config: ScatterChartConfig,\n): ChartHandle<ScatterSeriesConfig[]> {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n let markers: SVGGElement | null = null;\n let seriesList = config.series;\n\n return createChartScaffold(\n container,\n config,\n (ctx, reason) => {\n const { groups, legend, tooltip } = ctx;\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n const dims = ctx.dimensions;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const allData = seriesList.map((series) => series.data);\n const allX = allData.flat().map((datum) => datum.key);\n const allY = allData.flat().map((datum) => datum.value);\n\n if (allX.length === 0) {\n clearCartesianDom(groups, legend, tooltip, crosshair);\n markers?.replaceChildren();\n\n return;\n }\n\n if (config.crosshair && !crosshair) {\n crosshair = createCrosshair(ctx.chartArea, config.crosshair);\n }\n\n const xScale = buildXScale(allX, area.width);\n // Independent points have no baseline to anchor, so the y domain fits the data.\n const yScale = buildYScale(allY, area.height, false);\n\n // Axes render by default (value axis with gridlines); `false` opts out. The value\n // axis merges over its default so a partial config keeps the default gridlines.\n const xAxisConfig: XAxisConfig | false = config.xAxis === false ? false : (config.xAxis ?? {});\n const yAxisConfig: YAxisConfig | false = config.yAxis === false ? false : { grid: true, ...config.yAxis };\n\n if (yAxisConfig && yAxisConfig.grid) {\n renderGrid(\n groups.grid,\n yScale,\n yAxisConfig.grid,\n area.width,\n 'horizontal',\n resolveTicks(yScale, yAxisConfig, resolveTickCount(yAxisConfig, area.height, 'left')),\n );\n } else {\n groups.grid.replaceChildren();\n }\n\n if (xAxisConfig && xAxisConfig.grid) {\n renderGrid(\n groups.grid,\n xScale,\n xAxisConfig.grid,\n area.height,\n 'vertical',\n resolveTicks(xScale, xAxisConfig, resolveTickCount(xAxisConfig, area.width, 'bottom')),\n );\n }\n\n if (xAxisConfig) {\n positionAxis(groups.xAxis, xAxisConfig.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, xScale, xAxisConfig, area.width, 'bottom');\n } else {\n groups.xAxis.replaceChildren();\n }\n\n if (yAxisConfig) {\n positionAxis(groups.yAxis, yAxisConfig.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, yScale, yAxisConfig, area.height, 'left');\n } else {\n groups.yAxis.replaceChildren();\n }\n\n while (groups.series.children.length > seriesList.length) {\n groups.series.removeChild(groups.series.lastChild!);\n }\n\n const allPoints: Point[][] = [];\n\n for (const [i, series] of seriesList.entries()) {\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-scatter-series' });\n groups.series.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const points = computeScatterPoints(series.data, xScale, yScale);\n\n allPoints.push(points);\n\n renderScatterPoints(group, points, {\n color: seriesColor(i, series.color),\n disposalSignal: ctx.disposalSignal,\n marks: series.data,\n pointRadius: series.pointRadius ?? 3,\n transition: reason === 'resize' ? false : config.transition,\n });\n }\n\n tooltip?.hide();\n markers = ensureMarkerGroup(ctx.chartArea, markers);\n\n return createScatterInteraction({\n announcer: ctx.announcer,\n colors: () => seriesList.map((s, i) => seriesColor(i, s.color)),\n crosshair,\n dims: () => ctx.dimensions,\n getData: () => allData,\n getPoints: () => allPoints,\n getSeriesList: () => seriesList,\n margin: dims.margin,\n markers,\n onClick: config.onClick,\n onHover: config.onHover,\n seriesGroup: groups.series,\n svg: ctx.svg,\n tooltip,\n tooltipFormat: typeof config.tooltip === 'object' ? config.tooltip : undefined,\n });\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"20BAeA,SAAgB,mBACd,EACA,EACoC,CACpC,IAAI,EAAuD,KACvD,EAA8B,KAC9B,EAAa,EAAO,OAExB,OAAO,EACL,EACA,GACC,EAAK,IAAW,CACf,GAAM,CAAE,SAAQ,SAAQ,WAAY,EACpC,GAAQ,OAAO,EAAW,KAAK,EAAG,KAAO,CAAE,MAAO,EAAY,EAAG,EAAE,KAAK,EAAG,KAAM,EAAE,IAAK,EAAE,CAAC,EAC3F,IAAM,EAAO,EAAI,WACX,EAAO,EAAU,EAAK,MAAO,EAAK,OAAQ,EAAK,MAAM,EACrD,EAAU,EAAW,IAAK,GAAW,EAAO,IAAI,EAChD,EAAO,EAAQ,KAAK,CAAC,CAAC,IAAK,GAAU,EAAM,GAAG,EAC9C,EAAO,EAAQ,KAAK,CAAC,CAAC,IAAK,GAAU,EAAM,KAAK,EAEtD,GAAI,EAAK,SAAW,EAAG,CACrB,EAAkB,EAAQ,EAAQ,EAAS,CAAS,EACpD,GAAS,gBAAgB,EAEzB,MACF,CAEI,EAAO,WAAa,CAAC,IACvB,EAAY,EAAgB,EAAI,UAAW,EAAO,SAAS,GAG7D,IAAM,EAAS,EAAY,EAAM,EAAK,KAAK,EAErC,EAAS,EAAY,EAAM,EAAK,OAAQ,EAAK,EAI7C,EAAmC,EAAO,QAAU,GAAQ,GAAS,EAAO,OAAS,CAAC,EACtF,EAAmC,EAAO,QAAU,IAAgB,CAAE,KAAM,GAAM,GAAG,EAAO,KAAM,EAwCxG,IAtCI,GAAe,EAAY,KAC7B,EACE,EAAO,KACP,EACA,EAAY,KACZ,EAAK,MACL,aACA,EAAa,EAAQ,EAAa,EAAiB,EAAa,EAAK,OAAQ,MAAM,CAAC,CACtF,EAEA,EAAO,KAAK,gBAAgB,EAG1B,GAAe,EAAY,MAC7B,EACE,EAAO,KACP,EACA,EAAY,KACZ,EAAK,OACL,WACA,EAAa,EAAQ,EAAa,EAAiB,EAAa,EAAK,MAAO,QAAQ,CAAC,CACvF,EAGE,GACF,EAAa,EAAO,MAAO,EAAY,UAAY,SAAU,EAAK,MAAO,EAAK,MAAM,EACpF,EAAW,EAAO,MAAO,EAAQ,EAAa,EAAK,MAAO,QAAQ,GAElE,EAAO,MAAM,gBAAgB,EAG3B,GACF,EAAa,EAAO,MAAO,EAAY,UAAY,OAAQ,EAAK,MAAO,EAAK,MAAM,EAClF,EAAW,EAAO,MAAO,EAAQ,EAAa,EAAK,OAAQ,MAAM,GAEjE,EAAO,MAAM,gBAAgB,EAGxB,EAAO,OAAO,SAAS,OAAS,EAAW,QAChD,EAAO,OAAO,YAAY,EAAO,OAAO,SAAU,EAGpD,IAAM,EAAuB,CAAC,EAE9B,IAAK,GAAM,CAAC,EAAG,KAAW,EAAW,QAAQ,EAAG,CAC9C,IAAI,EAAQ,EAAO,OAAO,SAAS,GAE9B,IACH,EAAQ,EAAiB,IAAK,CAAE,MAAO,sBAAuB,CAAC,EAC/D,EAAO,OAAO,YAAY,CAAK,GAGjC,EAAM,aAAa,iBAAkB,EAAY,EAAQ,CAAC,CAAC,EAE3D,IAAM,EAAS,EAAqB,EAAO,KAAM,EAAQ,CAAM,EAE/D,EAAU,KAAK,CAAM,EAErB,EAAoB,EAAO,EAAQ,CACjC,MAAO,EAAY,EAAG,EAAO,KAAK,EAClC,eAAgB,EAAI,eACpB,MAAO,EAAO,KACd,YAAa,EAAO,aAAe,EACnC,WAAY,IAAW,UAAmB,EAAO,UACnD,CAAC,CACH,CAKA,OAHA,GAAS,KAAK,EACd,EAAU,EAAkB,EAAI,UAAW,CAAO,EAE3C,EAAyB,CAC9B,UAAW,EAAI,UACf,WAAc,EAAW,KAAK,EAAG,IAAM,EAAY,EAAG,EAAE,KAAK,CAAC,EAC9D,YACA,SAAY,EAAI,WAChB,YAAe,EACf,cAAiB,EACjB,kBAAqB,EACrB,OAAQ,EAAK,OACb,UACA,QAAS,EAAO,QAChB,QAAS,EAAO,QAChB,YAAa,EAAO,OACpB,IAAK,EAAI,IACT,UACA,cAAe,OAAO,EAAO,SAAY,SAAW,EAAO,QAAU,IAAA,EACvE,CAAC,CACH,EACC,GAAS,CACR,EAAa,CACf,CACF,CACF"}
@@ -0,0 +1,2 @@
1
+ require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../animation/easing.cjs"),n=require("../../animation/motion.cjs"),r=require("../../animation/tween.cjs"),i=require("../../animation/transition.cjs");var a=400,o=new WeakMap,s=new WeakMap;function computeScatterPoints(e,t,n){return e.some(e=>e.key==null)||e.some(e=>typeof e.key==`string`),e.map(e=>({x:t.map(e.key),y:n.map(e.value)}))}function renderScatterPoints(c,l,u){let d=n.resolveMotion(u.transition),f=u.marks??[],p=u.pointRadius;for(o.get(c)?.(),o.delete(c);c.children.length>l.length;)c.lastChild.remove();let m=s.get(c)??[],h=[],g=l.map((t,n)=>{let r=c.children[n];return r?h.push(Number(r.getAttribute(`r`))||0):(r=e.createSvgElement(`circle`,{class:`prism-scatter-point`}),c.appendChild(r),h.push(0)),e.setAttributes(r,{fill:u.color,opacity:f[n]?.opacity}),r}),paint=(t,n)=>{for(let[r,i]of g.entries())e.setAttributes(i,{cx:t[r].x,cy:t[r].y,r:n(r)});s.set(c,t)};if(d.duration===0){paint(l,()=>p);return}let _=l.map((e,t)=>m[t]??e),v=l.map((e,t)=>t).filter(e=>e>=m.length),y=new Map([...v].sort((e,t)=>l[e].x-l[t].x).map((e,t)=>[e,t])),b=Math.min(d.stagger,a/Math.max(1,v.length)),paintFrame=e=>{let t=l.map((t,n)=>e(y.get(n)??0));paint(l.map((e,n)=>({x:r.tweenNumber(_[n].x,e.x,t[n]),y:r.tweenNumber(_[n].y,e.y,t[n])})),e=>r.tweenNumber(h[e],p,t[e]))};paintFrame(()=>0),o.set(c,i.startTween({count:Math.max(1,v.length),duration:d.duration,easing:t.resolveEasing(d.easing),onComplete:()=>{o.delete(c),paint(l,()=>p)},onFrame:paintFrame,signal:u.disposalSignal,stagger:b}))}exports.computeScatterPoints=computeScatterPoints,exports.renderScatterPoints=renderScatterPoints;
2
+ //# sourceMappingURL=scatter-renderer.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scatter-renderer.cjs","names":[],"sources":["../../../src/charts/scatter/scatter-renderer.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport type { DatumMark } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionOption } from '../../types';\n\nexport interface ScatterRenderOptions {\n color: string;\n /** Aborted when the owning chart is disposed: stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n /** Per-datum presentation parallel to `points`; only `opacity` applies to a scatter marker. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n transition?: TransitionOption;\n}\n\n/** Upper bound on the total staggered delay entering points may add, whatever the per-point value. */\nconst MAX_STAGGER_TOTAL = 400;\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n// Point positions currently on screen, so an update slides from them even mid-tween.\nconst drawnPoints = new WeakMap<SVGGElement, Point[]>();\n\n/**\n * Maps scatter data to plot-area points: `key` is the x position, `value` the y.\n * A string key is a data error here, not a band position.\n */\nexport function computeScatterPoints(\n data: ContinuousDatum[],\n xScale: Scale<Date | number>,\n yScale: Scale<number>,\n): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computeScatterPoints: datum.key is null or undefined: data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computeScatterPoints: string keys are not supported: scatter x values must be numbers or Dates.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n\n/**\n * Draws one scatter series as point markers. Entering points grow from radius 0 at\n * their final position (staggered in x order when `stagger` is set); existing points\n * slide from their drawn position. Disabled or reduced motion paints synchronously.\n */\nexport function renderScatterPoints(parent: SVGGElement, points: Point[], options: ScatterRenderOptions): void {\n const motion = resolveMotion(options.transition);\n const marks = options.marks ?? [];\n const radius = options.pointRadius;\n\n activeAnimations.get(parent)?.();\n activeAnimations.delete(parent);\n\n while (parent.children.length > points.length) parent.lastChild!.remove();\n\n const drawn = drawnPoints.get(parent) ?? [];\n const fromRadius: number[] = [];\n const circles = points.map((_, i) => {\n let circle = parent.children[i] as SVGCircleElement | undefined;\n\n if (circle) {\n fromRadius.push(Number(circle.getAttribute('r')) || 0);\n } else {\n circle = createSvgElement('circle', { class: 'prism-scatter-point' });\n parent.appendChild(circle);\n fromRadius.push(0);\n }\n\n setAttributes(circle, { fill: options.color, opacity: marks[i]?.opacity });\n\n return circle;\n });\n\n const paint = (pts: Point[], radii: (i: number) => number): void => {\n for (const [i, circle] of circles.entries()) setAttributes(circle, { cx: pts[i].x, cy: pts[i].y, r: radii(i) });\n\n drawnPoints.set(parent, pts);\n };\n\n if (motion.duration === 0) {\n paint(points, () => radius);\n\n return;\n }\n\n const fromPts = points.map((to, i) => drawn[i] ?? to);\n // Entering points (no drawn marker yet) take their own stagger lane in x order;\n // moving points all share lane 0 so an update never crawls.\n const entering = points.map((_, i) => i).filter((i) => i >= drawn.length);\n const lanes = new Map(\n [...entering].sort((a, b) => points[a].x - points[b].x).map((pointIndex, lane) => [pointIndex, lane]),\n );\n const stagger = Math.min(motion.stagger, MAX_STAGGER_TOTAL / Math.max(1, entering.length));\n\n const paintFrame = (progress: (lane: number) => number): void => {\n const eased = points.map((_, i) => progress(lanes.get(i) ?? 0));\n\n paint(\n points.map((to, i) => ({\n x: tweenNumber(fromPts[i].x, to.x, eased[i]),\n y: tweenNumber(fromPts[i].y, to.y, eased[i]),\n })),\n (i) => tweenNumber(fromRadius[i], radius, eased[i]),\n );\n };\n\n // The starting state goes on screen immediately: `startTween` only paints on\n // the first frame callback, which would otherwise leave one stale frame.\n paintFrame(() => 0);\n\n activeAnimations.set(\n parent,\n startTween({\n count: Math.max(1, entering.length),\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: () => {\n activeAnimations.delete(parent);\n paint(points, () => radius);\n },\n onFrame: paintFrame,\n signal: options.disposalSignal,\n stagger,\n }),\n );\n}\n"],"mappings":"sOAqBA,IAAM,EAAoB,IAEpB,EAAmB,IAAI,QAEvB,EAAc,IAAI,QAMxB,SAAgB,qBACd,EACA,EACA,EACS,CAST,OARI,EAAK,KAAM,GAAM,EAAE,KAAO,IAAI,GAIvB,EAAK,KAAM,GAAM,OAAO,EAAE,KAAQ,QAAQ,EAI9C,EAAK,IAAK,IAAO,CACtB,EAAG,EAAO,IAAI,EAAE,GAAoB,EACpC,EAAG,EAAO,IAAI,EAAE,KAAK,CACvB,EAAE,CACJ,CAOA,SAAgB,oBAAoB,EAAqB,EAAiB,EAAqC,CAC7G,IAAM,EAAS,EAAA,cAAc,EAAQ,UAAU,EACzC,EAAQ,EAAQ,OAAS,CAAC,EAC1B,EAAS,EAAQ,YAKvB,IAHA,EAAiB,IAAI,CAAM,CAAC,GAAG,EAC/B,EAAiB,OAAO,CAAM,EAEvB,EAAO,SAAS,OAAS,EAAO,QAAQ,EAAO,UAAW,OAAO,EAExE,IAAM,EAAQ,EAAY,IAAI,CAAM,GAAK,CAAC,EACpC,EAAuB,CAAC,EACxB,EAAU,EAAO,KAAK,EAAG,IAAM,CACnC,IAAI,EAAS,EAAO,SAAS,GAY7B,OAVI,EACF,EAAW,KAAK,OAAO,EAAO,aAAa,GAAG,CAAC,GAAK,CAAC,GAErD,EAAS,EAAA,iBAAiB,SAAU,CAAE,MAAO,qBAAsB,CAAC,EACpE,EAAO,YAAY,CAAM,EACzB,EAAW,KAAK,CAAC,GAGnB,EAAA,cAAc,EAAQ,CAAE,KAAM,EAAQ,MAAO,QAAS,EAAM,EAAE,EAAE,OAAQ,CAAC,EAElE,CACT,CAAC,EAEK,OAAS,EAAc,IAAuC,CAClE,IAAK,GAAM,CAAC,EAAG,KAAW,EAAQ,QAAQ,EAAG,EAAA,cAAc,EAAQ,CAAE,GAAI,EAAI,EAAE,CAAC,EAAG,GAAI,EAAI,EAAE,CAAC,EAAG,EAAG,EAAM,CAAC,CAAE,CAAC,EAE9G,EAAY,IAAI,EAAQ,CAAG,CAC7B,EAEA,GAAI,EAAO,WAAa,EAAG,CACzB,MAAM,MAAc,CAAM,EAE1B,MACF,CAEA,IAAM,EAAU,EAAO,KAAK,EAAI,IAAM,EAAM,IAAM,CAAE,EAG9C,EAAW,EAAO,KAAK,EAAG,IAAM,CAAC,CAAC,CAAC,OAAQ,GAAM,GAAK,EAAM,MAAM,EAClE,EAAQ,IAAI,IAChB,CAAC,GAAG,CAAQ,CAAC,CAAC,MAAM,EAAG,IAAM,EAAO,EAAE,CAAC,EAAI,EAAO,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,EAAY,IAAS,CAAC,EAAY,CAAI,CAAC,CACtG,EACM,EAAU,KAAK,IAAI,EAAO,QAAS,EAAoB,KAAK,IAAI,EAAG,EAAS,MAAM,CAAC,EAEnF,WAAc,GAA6C,CAC/D,IAAM,EAAQ,EAAO,KAAK,EAAG,IAAM,EAAS,EAAM,IAAI,CAAC,GAAK,CAAC,CAAC,EAE9D,MACE,EAAO,KAAK,EAAI,KAAO,CACrB,EAAG,EAAA,YAAY,EAAQ,EAAE,CAAC,EAAG,EAAG,EAAG,EAAM,EAAE,EAC3C,EAAG,EAAA,YAAY,EAAQ,EAAE,CAAC,EAAG,EAAG,EAAG,EAAM,EAAE,CAC7C,EAAE,EACD,GAAM,EAAA,YAAY,EAAW,GAAI,EAAQ,EAAM,EAAE,CACpD,CACF,EAIA,eAAiB,CAAC,EAElB,EAAiB,IACf,EACA,EAAA,WAAW,CACT,MAAO,KAAK,IAAI,EAAG,EAAS,MAAM,EAClC,SAAU,EAAO,SACjB,OAAQ,EAAA,cAAc,EAAO,MAAM,EACnC,eAAkB,CAChB,EAAiB,OAAO,CAAM,EAC9B,MAAM,MAAc,CAAM,CAC5B,EACA,QAAS,WACT,OAAQ,EAAQ,eAChB,SACF,CAAC,CACH,CACF"}
@@ -0,0 +1,24 @@
1
+ import type { DatumMark } from '../../core/datum-style';
2
+ import type { Point } from '../../svg/path';
3
+ import type { ContinuousDatum, Scale, TransitionOption } from '../../types';
4
+ export interface ScatterRenderOptions {
5
+ color: string;
6
+ /** Aborted when the owning chart is disposed: stops the transition's `requestAnimationFrame` loop from rescheduling. */
7
+ disposalSignal?: AbortSignal;
8
+ /** Per-datum presentation parallel to `points`; only `opacity` applies to a scatter marker. */
9
+ marks?: readonly DatumMark[];
10
+ pointRadius: number;
11
+ transition?: TransitionOption;
12
+ }
13
+ /**
14
+ * Maps scatter data to plot-area points: `key` is the x position, `value` the y.
15
+ * A string key is a data error here, not a band position.
16
+ */
17
+ export declare function computeScatterPoints(data: ContinuousDatum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[];
18
+ /**
19
+ * Draws one scatter series as point markers. Entering points grow from radius 0 at
20
+ * their final position (staggered in x order when `stagger` is set); existing points
21
+ * slide from their drawn position. Disabled or reduced motion paints synchronously.
22
+ */
23
+ export declare function renderScatterPoints(parent: SVGGElement, points: Point[], options: ScatterRenderOptions): void;
24
+ //# sourceMappingURL=scatter-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scatter-renderer.d.ts","sourceRoot":"","sources":["../../../src/charts/scatter/scatter-renderer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE5E,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,wHAAwH;IACxH,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,+FAA+F;IAC/F,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AASD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,eAAe,EAAE,EACvB,MAAM,EAAE,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,EAC5B,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GACpB,KAAK,EAAE,CAaT;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAgF7G"}
@@ -0,0 +1,2 @@
1
+ import"../../_dev.js";import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{resolveEasing as n}from"../../animation/easing.js";import{resolveMotion as r}from"../../animation/motion.js";import{tweenNumber as i}from"../../animation/tween.js";import{startTween as a}from"../../animation/transition.js";var o=400,s=new WeakMap,c=new WeakMap;function computeScatterPoints(e,t,n){return e.some(e=>e.key==null)||e.some(e=>typeof e.key==`string`),e.map(e=>({x:t.map(e.key),y:n.map(e.value)}))}function renderScatterPoints(l,u,d){let f=r(d.transition),p=d.marks??[],m=d.pointRadius;for(s.get(l)?.(),s.delete(l);l.children.length>u.length;)l.lastChild.remove();let h=c.get(l)??[],g=[],_=u.map((n,r)=>{let i=l.children[r];return i?g.push(Number(i.getAttribute(`r`))||0):(i=e(`circle`,{class:`prism-scatter-point`}),l.appendChild(i),g.push(0)),t(i,{fill:d.color,opacity:p[r]?.opacity}),i}),paint=(e,n)=>{for(let[r,i]of _.entries())t(i,{cx:e[r].x,cy:e[r].y,r:n(r)});c.set(l,e)};if(f.duration===0){paint(u,()=>m);return}let v=u.map((e,t)=>h[t]??e),y=u.map((e,t)=>t).filter(e=>e>=h.length),b=new Map([...y].sort((e,t)=>u[e].x-u[t].x).map((e,t)=>[e,t])),x=Math.min(f.stagger,o/Math.max(1,y.length)),paintFrame=e=>{let t=u.map((t,n)=>e(b.get(n)??0));paint(u.map((e,n)=>({x:i(v[n].x,e.x,t[n]),y:i(v[n].y,e.y,t[n])})),e=>i(g[e],m,t[e]))};paintFrame(()=>0),s.set(l,a({count:Math.max(1,y.length),duration:f.duration,easing:n(f.easing),onComplete:()=>{s.delete(l),paint(u,()=>m)},onFrame:paintFrame,signal:d.disposalSignal,stagger:x}))}export{computeScatterPoints,renderScatterPoints};
2
+ //# sourceMappingURL=scatter-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scatter-renderer.js","names":[],"sources":["../../../src/charts/scatter/scatter-renderer.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport type { DatumMark } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionOption } from '../../types';\n\nexport interface ScatterRenderOptions {\n color: string;\n /** Aborted when the owning chart is disposed: stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n /** Per-datum presentation parallel to `points`; only `opacity` applies to a scatter marker. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n transition?: TransitionOption;\n}\n\n/** Upper bound on the total staggered delay entering points may add, whatever the per-point value. */\nconst MAX_STAGGER_TOTAL = 400;\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n// Point positions currently on screen, so an update slides from them even mid-tween.\nconst drawnPoints = new WeakMap<SVGGElement, Point[]>();\n\n/**\n * Maps scatter data to plot-area points: `key` is the x position, `value` the y.\n * A string key is a data error here, not a band position.\n */\nexport function computeScatterPoints(\n data: ContinuousDatum[],\n xScale: Scale<Date | number>,\n yScale: Scale<number>,\n): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computeScatterPoints: datum.key is null or undefined: data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computeScatterPoints: string keys are not supported: scatter x values must be numbers or Dates.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n\n/**\n * Draws one scatter series as point markers. Entering points grow from radius 0 at\n * their final position (staggered in x order when `stagger` is set); existing points\n * slide from their drawn position. Disabled or reduced motion paints synchronously.\n */\nexport function renderScatterPoints(parent: SVGGElement, points: Point[], options: ScatterRenderOptions): void {\n const motion = resolveMotion(options.transition);\n const marks = options.marks ?? [];\n const radius = options.pointRadius;\n\n activeAnimations.get(parent)?.();\n activeAnimations.delete(parent);\n\n while (parent.children.length > points.length) parent.lastChild!.remove();\n\n const drawn = drawnPoints.get(parent) ?? [];\n const fromRadius: number[] = [];\n const circles = points.map((_, i) => {\n let circle = parent.children[i] as SVGCircleElement | undefined;\n\n if (circle) {\n fromRadius.push(Number(circle.getAttribute('r')) || 0);\n } else {\n circle = createSvgElement('circle', { class: 'prism-scatter-point' });\n parent.appendChild(circle);\n fromRadius.push(0);\n }\n\n setAttributes(circle, { fill: options.color, opacity: marks[i]?.opacity });\n\n return circle;\n });\n\n const paint = (pts: Point[], radii: (i: number) => number): void => {\n for (const [i, circle] of circles.entries()) setAttributes(circle, { cx: pts[i].x, cy: pts[i].y, r: radii(i) });\n\n drawnPoints.set(parent, pts);\n };\n\n if (motion.duration === 0) {\n paint(points, () => radius);\n\n return;\n }\n\n const fromPts = points.map((to, i) => drawn[i] ?? to);\n // Entering points (no drawn marker yet) take their own stagger lane in x order;\n // moving points all share lane 0 so an update never crawls.\n const entering = points.map((_, i) => i).filter((i) => i >= drawn.length);\n const lanes = new Map(\n [...entering].sort((a, b) => points[a].x - points[b].x).map((pointIndex, lane) => [pointIndex, lane]),\n );\n const stagger = Math.min(motion.stagger, MAX_STAGGER_TOTAL / Math.max(1, entering.length));\n\n const paintFrame = (progress: (lane: number) => number): void => {\n const eased = points.map((_, i) => progress(lanes.get(i) ?? 0));\n\n paint(\n points.map((to, i) => ({\n x: tweenNumber(fromPts[i].x, to.x, eased[i]),\n y: tweenNumber(fromPts[i].y, to.y, eased[i]),\n })),\n (i) => tweenNumber(fromRadius[i], radius, eased[i]),\n );\n };\n\n // The starting state goes on screen immediately: `startTween` only paints on\n // the first frame callback, which would otherwise leave one stale frame.\n paintFrame(() => 0);\n\n activeAnimations.set(\n parent,\n startTween({\n count: Math.max(1, entering.length),\n duration: motion.duration,\n easing: resolveEasing(motion.easing),\n onComplete: () => {\n activeAnimations.delete(parent);\n paint(points, () => radius);\n },\n onFrame: paintFrame,\n signal: options.disposalSignal,\n stagger,\n }),\n );\n}\n"],"mappings":"uUAqBA,IAAM,EAAoB,IAEpB,EAAmB,IAAI,QAEvB,EAAc,IAAI,QAMxB,SAAgB,qBACd,EACA,EACA,EACS,CAST,OARI,EAAK,KAAM,GAAM,EAAE,KAAO,IAAI,GAIvB,EAAK,KAAM,GAAM,OAAO,EAAE,KAAQ,QAAQ,EAI9C,EAAK,IAAK,IAAO,CACtB,EAAG,EAAO,IAAI,EAAE,GAAoB,EACpC,EAAG,EAAO,IAAI,EAAE,KAAK,CACvB,EAAE,CACJ,CAOA,SAAgB,oBAAoB,EAAqB,EAAiB,EAAqC,CAC7G,IAAM,EAAS,EAAc,EAAQ,UAAU,EACzC,EAAQ,EAAQ,OAAS,CAAC,EAC1B,EAAS,EAAQ,YAKvB,IAHA,EAAiB,IAAI,CAAM,CAAC,GAAG,EAC/B,EAAiB,OAAO,CAAM,EAEvB,EAAO,SAAS,OAAS,EAAO,QAAQ,EAAO,UAAW,OAAO,EAExE,IAAM,EAAQ,EAAY,IAAI,CAAM,GAAK,CAAC,EACpC,EAAuB,CAAC,EACxB,EAAU,EAAO,KAAK,EAAG,IAAM,CACnC,IAAI,EAAS,EAAO,SAAS,GAY7B,OAVI,EACF,EAAW,KAAK,OAAO,EAAO,aAAa,GAAG,CAAC,GAAK,CAAC,GAErD,EAAS,EAAiB,SAAU,CAAE,MAAO,qBAAsB,CAAC,EACpE,EAAO,YAAY,CAAM,EACzB,EAAW,KAAK,CAAC,GAGnB,EAAc,EAAQ,CAAE,KAAM,EAAQ,MAAO,QAAS,EAAM,EAAE,EAAE,OAAQ,CAAC,EAElE,CACT,CAAC,EAEK,OAAS,EAAc,IAAuC,CAClE,IAAK,GAAM,CAAC,EAAG,KAAW,EAAQ,QAAQ,EAAG,EAAc,EAAQ,CAAE,GAAI,EAAI,EAAE,CAAC,EAAG,GAAI,EAAI,EAAE,CAAC,EAAG,EAAG,EAAM,CAAC,CAAE,CAAC,EAE9G,EAAY,IAAI,EAAQ,CAAG,CAC7B,EAEA,GAAI,EAAO,WAAa,EAAG,CACzB,MAAM,MAAc,CAAM,EAE1B,MACF,CAEA,IAAM,EAAU,EAAO,KAAK,EAAI,IAAM,EAAM,IAAM,CAAE,EAG9C,EAAW,EAAO,KAAK,EAAG,IAAM,CAAC,CAAC,CAAC,OAAQ,GAAM,GAAK,EAAM,MAAM,EAClE,EAAQ,IAAI,IAChB,CAAC,GAAG,CAAQ,CAAC,CAAC,MAAM,EAAG,IAAM,EAAO,EAAE,CAAC,EAAI,EAAO,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,EAAY,IAAS,CAAC,EAAY,CAAI,CAAC,CACtG,EACM,EAAU,KAAK,IAAI,EAAO,QAAS,EAAoB,KAAK,IAAI,EAAG,EAAS,MAAM,CAAC,EAEnF,WAAc,GAA6C,CAC/D,IAAM,EAAQ,EAAO,KAAK,EAAG,IAAM,EAAS,EAAM,IAAI,CAAC,GAAK,CAAC,CAAC,EAE9D,MACE,EAAO,KAAK,EAAI,KAAO,CACrB,EAAG,EAAY,EAAQ,EAAE,CAAC,EAAG,EAAG,EAAG,EAAM,EAAE,EAC3C,EAAG,EAAY,EAAQ,EAAE,CAAC,EAAG,EAAG,EAAG,EAAM,EAAE,CAC7C,EAAE,EACD,GAAM,EAAY,EAAW,GAAI,EAAQ,EAAM,EAAE,CACpD,CACF,EAIA,eAAiB,CAAC,EAElB,EAAiB,IACf,EACA,EAAW,CACT,MAAO,KAAK,IAAI,EAAG,EAAS,MAAM,EAClC,SAAU,EAAO,SACjB,OAAQ,EAAc,EAAO,MAAM,EACnC,eAAkB,CAChB,EAAiB,OAAO,CAAM,EAC9B,MAAM,MAAc,CAAM,CAC5B,EACA,QAAS,WACT,OAAQ,EAAQ,eAChB,SACF,CAAC,CACH,CACF"}
@@ -1,2 +1,2 @@
1
- require("../_dev.cjs");const e=require("../svg/element.cjs"),t=require("../errors.cjs"),n=require("./layout.cjs"),r=require("./responsive.cjs");function createChartBase(i,a,o){if(!(typeof i==`object`&&i&&i.nodeType===1&&typeof i.appendChild==`function`&&typeof i.getBoundingClientRect==`function`)){let e=i,n=e===null?`null`:typeof e==`object`?e.constructor?.name??`object`:typeof e;throw new t.PrismRenderError(`Invalid chart configuration: \`container\` must be a DOM Element, received ${n}.`)}let s=n.resolveMargin(a.margin),c=a.a11y,l=e.createSvgElement(`svg`,{...!c||c.decorative?{"aria-hidden":`true`}:{"aria-label":c.ariaLabel,role:`img`,tabindex:`0`},class:`prism-chart`,style:`display:block;max-width:100%`}),u=e.createSvgElement(`g`,{class:`prism-chart-area`,transform:`translate(${s.left},${s.top})`});l.appendChild(u);let d=i.getBoundingClientRect();d.width===0||d.height;let f={height:d.height||300,margin:s,width:d.width||600},p=r.observeResize(i,(t,n)=>{let r=a.chrome?.()?.offsetHeight??0,i=Math.max(0,n-r);f.height=i,f.width=t,e.setAttributes(l,{height:i,viewBox:`0 0 ${t} ${i}`,width:t}),o?.()}),m=d.width||600,h=d.height||300;return e.setAttributes(l,{height:h,viewBox:`0 0 ${m} ${h}`,width:m}),i.appendChild(l),{chartArea:u,dimensions:f,dispose(){p(),l.remove()},svg:l}}exports.createChartBase=createChartBase;
1
+ require("../_dev.cjs");const e=require("../svg/element.cjs"),t=require("../errors.cjs"),n=require("./layout.cjs"),r=require("./responsive.cjs");function createChartBase(i,a,o){if(!(typeof i==`object`&&i&&i.nodeType===1&&typeof i.appendChild==`function`&&typeof i.getBoundingClientRect==`function`)){let e=i,n=e===null?`null`:typeof e==`object`?e.constructor?.name??`object`:typeof e;throw new t.PrismRenderError(`Invalid chart configuration: \`container\` must be a DOM Element, received ${n}.`)}let s=n.resolveMargin(a.margin),c=a.a11y,l=e.createSvgElement(`svg`,{...!c||c.decorative?{"aria-hidden":`true`}:{"aria-label":c.ariaLabel,role:`img`,tabindex:`0`},class:`prism-chart`,style:`display:block;max-width:100%`}),u=e.createSvgElement(`g`,{class:`prism-chart-area`,transform:`translate(${s.left},${s.top})`});l.appendChild(u);let d=i.getBoundingClientRect();d.width===0||d.height;let f=d.width||600,p=d.height||300,m={height:p,margin:s,width:f},h=f,g=p,_=p,syncChrome=()=>{let t=Math.max(0,_-(a.chrome?.()?.offsetHeight??0));g=t,m.height=t,e.setAttributes(l,{height:t,viewBox:`0 0 ${m.width} ${t}`})},v=r.observeResize(i,(t,n)=>{_=n;let r=a.chrome?.()?.offsetHeight??0,i=Math.max(0,n-r);(t!==h||i!==g)&&(h=t,g=i,m.height=i,m.width=t,e.setAttributes(l,{height:i,viewBox:`0 0 ${t} ${i}`,width:t}),o?.())});return e.setAttributes(l,{height:p,viewBox:`0 0 ${f} ${p}`,width:f}),i.appendChild(l),{chartArea:u,dimensions:m,dispose(){v(),l.remove()},svg:l,syncChrome}}exports.createChartBase=createChartBase;
2
2
  //# sourceMappingURL=chart-base.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-base.cjs","names":[],"sources":["../../src/core/chart-base.ts"],"sourcesContent":["import { warn } from '../_dev';\nimport { PrismRenderError } from '../errors';\nimport { createSvgElement, setAttributes } from '../svg/element';\nimport type { ChartA11y, ChartDimensions, ChartMargin } from '../types';\nimport { resolveMargin } from './layout';\nimport { observeResize } from './responsive';\n\nexport interface ChartBase {\n chartArea: SVGGElement;\n dimensions: ChartDimensions;\n dispose(): void;\n svg: SVGSVGElement;\n}\n\nexport function createChartBase(\n container: HTMLElement,\n options: {\n a11y?: ChartA11y;\n /**\n * The chart's own in-flow chrome inside the container (the legend). Its height is\n * subtracted from every resize-driven svg height: the container's content box contains\n * the svg plus this chrome, so assigning the full content height back to the svg would\n * grow the container by the chrome's height on every pass — unbounded growth in any\n * auto-height container. Subtracting it makes the layout converge on the fixed point\n * `container = svg + chrome` instead.\n */\n chrome?: () => HTMLElement | null;\n margin?: Partial<ChartMargin>;\n },\n onResize?: () => void,\n): ChartBase {\n // Duck-typed rather than `instanceof Element`: an `instanceof` check would reject a\n // structurally valid Element from a different realm (e.g. an Element created via\n // `iframe.contentDocument.createElement(...)`, whose prototype chain terminates in that\n // iframe's own `Element` constructor), which is a legitimate usage pattern this package\n // doesn't otherwise restrict.\n const isElementLike =\n typeof container === 'object' &&\n container !== null &&\n container.nodeType === 1 &&\n typeof container.appendChild === 'function' &&\n typeof container.getBoundingClientRect === 'function';\n\n if (!isElementLike) {\n const received: unknown = container;\n const kind =\n received === null\n ? 'null'\n : typeof received === 'object'\n ? (received.constructor?.name ?? 'object')\n : typeof received;\n\n throw new PrismRenderError(`Invalid chart configuration: \\`container\\` must be a DOM Element, received ${kind}.`);\n }\n\n const margin = resolveMargin(options.margin);\n const a11y = options.a11y;\n const svg = createSvgElement('svg', {\n ...(!a11y || a11y.decorative\n ? { 'aria-hidden': 'true' }\n : { 'aria-label': a11y.ariaLabel, role: 'img', tabindex: '0' }),\n class: 'prism-chart',\n // The svg's width/height attributes are its single source of sizing truth (set below and\n // on every resize pass, chrome excluded). CSS percentage sizing here would override the\n // attributes: `height: 100%` fills the whole container, so the in-flow legend rides past\n // the container's edge instead of inside the height the resize pass reserved for it.\n style: 'display:block;max-width:100%',\n });\n\n const chartAreaGroup = createSvgElement('g', {\n class: 'prism-chart-area',\n transform: `translate(${margin.left},${margin.top})`,\n });\n\n svg.appendChild(chartAreaGroup);\n\n const rect = container.getBoundingClientRect();\n\n if (rect.width === 0 || rect.height === 0) {\n warn(\n 'Chart container has zero dimensions. Ensure the container has a defined width and height before mounting a chart.',\n );\n }\n\n const dimensions: ChartDimensions = {\n height: rect.height || 300,\n margin,\n width: rect.width || 600,\n };\n\n const stopObserving = observeResize(container, (width, height) => {\n const chromeHeight = options.chrome?.()?.offsetHeight ?? 0;\n const svgHeight = Math.max(0, height - chromeHeight);\n\n dimensions.height = svgHeight;\n dimensions.width = width;\n setAttributes(svg, { height: svgHeight, viewBox: `0 0 ${width} ${svgHeight}`, width });\n onResize?.();\n });\n\n const initialWidth = rect.width || 600;\n const initialHeight = rect.height || 300;\n\n setAttributes(svg, {\n height: initialHeight,\n viewBox: `0 0 ${initialWidth} ${initialHeight}`,\n width: initialWidth,\n });\n\n container.appendChild(svg);\n\n return {\n chartArea: chartAreaGroup,\n dimensions,\n dispose() {\n stopObserving();\n svg.remove();\n },\n svg,\n };\n}\n"],"mappings":"gJAcA,SAAgB,gBACd,EACA,EAaA,EACW,CAaX,GAAI,EANF,OAAO,GAAc,UACrB,GACA,EAAU,WAAa,GACvB,OAAO,EAAU,aAAgB,YACjC,OAAO,EAAU,uBAA0B,YAEzB,CAClB,IAAM,EAAoB,EACpB,EACJ,IAAa,KACT,OACA,OAAO,GAAa,SACjB,EAAS,aAAa,MAAQ,SAC/B,OAAO,EAEf,MAAM,IAAI,EAAA,iBAAiB,8EAA8E,EAAK,EAAE,CAClH,CAEA,IAAM,EAAS,EAAA,cAAc,EAAQ,MAAM,EACrC,EAAO,EAAQ,KACf,EAAM,EAAA,iBAAiB,MAAO,CAClC,GAAI,CAAC,GAAQ,EAAK,WACd,CAAE,cAAe,MAAO,EACxB,CAAE,aAAc,EAAK,UAAW,KAAM,MAAO,SAAU,GAAI,EAC/D,MAAO,cAKP,MAAO,8BACT,CAAC,EAEK,EAAiB,EAAA,iBAAiB,IAAK,CAC3C,MAAO,mBACP,UAAW,aAAa,EAAO,KAAK,GAAG,EAAO,IAAI,EACpD,CAAC,EAED,EAAI,YAAY,CAAc,EAE9B,IAAM,EAAO,EAAU,sBAAsB,EAEzC,EAAK,QAAU,GAAK,EAAK,OAM7B,IAAM,EAA8B,CAClC,OAAQ,EAAK,QAAU,IACvB,SACA,MAAO,EAAK,OAAS,GACvB,EAEM,EAAgB,EAAA,cAAc,GAAY,EAAO,IAAW,CAChE,IAAM,EAAe,EAAQ,SAAS,CAAC,EAAE,cAAgB,EACnD,EAAY,KAAK,IAAI,EAAG,EAAS,CAAY,EAEnD,EAAW,OAAS,EACpB,EAAW,MAAQ,EACnB,EAAA,cAAc,EAAK,CAAE,OAAQ,EAAW,QAAS,OAAO,EAAM,GAAG,IAAa,OAAM,CAAC,EACrF,IAAW,CACb,CAAC,EAEK,EAAe,EAAK,OAAS,IAC7B,EAAgB,EAAK,QAAU,IAUrC,OARA,EAAA,cAAc,EAAK,CACjB,OAAQ,EACR,QAAS,OAAO,EAAa,GAAG,IAChC,MAAO,CACT,CAAC,EAED,EAAU,YAAY,CAAG,EAElB,CACL,UAAW,EACX,aACA,SAAU,CACR,EAAc,EACd,EAAI,OAAO,CACb,EACA,KACF,CACF"}
1
+ {"version":3,"file":"chart-base.cjs","names":[],"sources":["../../src/core/chart-base.ts"],"sourcesContent":["import { warn } from '../_dev';\nimport { PrismRenderError } from '../errors';\nimport { createSvgElement, setAttributes } from '../svg/element';\nimport type { ChartA11y, ChartDimensions, ChartMargin } from '../types';\nimport { resolveMargin } from './layout';\nimport { observeResize } from './responsive';\n\nexport interface ChartBase {\n chartArea: SVGGElement;\n dimensions: ChartDimensions;\n dispose(): void;\n svg: SVGSVGElement;\n syncChrome(): void;\n}\n\nexport function createChartBase(\n container: HTMLElement,\n options: {\n a11y?: ChartA11y;\n /**\n * The chart's own in-flow chrome inside the container (the legend). Its height is\n * subtracted from every resize-driven svg height: the container's content box contains\n * the svg plus this chrome, so assigning the full content height back to the svg would\n * grow the container by the chrome's height on every pass — unbounded growth in any\n * auto-height container. Subtracting it makes the layout converge on the fixed point\n * `container = svg + chrome` instead.\n */\n chrome?: () => HTMLElement | null;\n margin?: Partial<ChartMargin>;\n },\n onResize?: () => void,\n): ChartBase {\n // Duck-typed rather than `instanceof Element`: an `instanceof` check would reject a\n // structurally valid Element from a different realm (e.g. an Element created via\n // `iframe.contentDocument.createElement(...)`, whose prototype chain terminates in that\n // iframe's own `Element` constructor), which is a legitimate usage pattern this package\n // doesn't otherwise restrict.\n const isElementLike =\n typeof container === 'object' &&\n container !== null &&\n container.nodeType === 1 &&\n typeof container.appendChild === 'function' &&\n typeof container.getBoundingClientRect === 'function';\n\n if (!isElementLike) {\n const received: unknown = container;\n const kind =\n received === null\n ? 'null'\n : typeof received === 'object'\n ? (received.constructor?.name ?? 'object')\n : typeof received;\n\n throw new PrismRenderError(`Invalid chart configuration: \\`container\\` must be a DOM Element, received ${kind}.`);\n }\n\n const margin = resolveMargin(options.margin);\n const a11y = options.a11y;\n const svg = createSvgElement('svg', {\n ...(!a11y || a11y.decorative\n ? { 'aria-hidden': 'true' }\n : { 'aria-label': a11y.ariaLabel, role: 'img', tabindex: '0' }),\n class: 'prism-chart',\n // The svg's width/height attributes are its single source of sizing truth (set below and\n // on every resize pass, chrome excluded). CSS percentage sizing here would override the\n // attributes: `height: 100%` fills the whole container, so the in-flow legend rides past\n // the container's edge instead of inside the height the resize pass reserved for it.\n style: 'display:block;max-width:100%',\n });\n\n const chartAreaGroup = createSvgElement('g', {\n class: 'prism-chart-area',\n transform: `translate(${margin.left},${margin.top})`,\n });\n\n svg.appendChild(chartAreaGroup);\n\n const rect = container.getBoundingClientRect();\n\n if (rect.width === 0 || rect.height === 0) {\n warn(\n 'Chart container has zero dimensions. Ensure the container has a defined width and height before mounting a chart.',\n );\n }\n\n const initialWidth = rect.width || 600;\n const initialHeight = rect.height || 300;\n\n const dimensions: ChartDimensions = {\n height: initialHeight,\n margin,\n width: initialWidth,\n };\n\n // The dimensions the svg currently carries. A resize pass only re-renders when the\n // effective drawing size moves away from these.\n let appliedWidth = initialWidth;\n let appliedHeight = initialHeight;\n let containerHeight = initialHeight;\n\n // Legend updates reserve their space synchronously, before a renderer builds scales.\n const syncChrome = (): void => {\n const height = Math.max(0, containerHeight - (options.chrome?.()?.offsetHeight ?? 0));\n\n appliedHeight = height;\n dimensions.height = height;\n setAttributes(svg, { height, viewBox: `0 0 ${dimensions.width} ${height}` });\n };\n\n const stopObserving = observeResize(container, (width, height) => {\n containerHeight = height;\n const chromeHeight = options.chrome?.()?.offsetHeight ?? 0;\n const svgHeight = Math.max(0, height - chromeHeight);\n\n // A ResizeObserver fires once for the initial observation, at the size the chart was\n // already built at. Re-rendering there is a no-op for layout but cancels a mount\n // entrance still in flight (the renderers treat the redraw as an already-drawn\n // update and snap to final), so a chart would never animate on first paint. Skip the\n // pass unless the effective size — legend chrome included — has genuinely changed.\n if (width === appliedWidth && svgHeight === appliedHeight) return;\n\n appliedWidth = width;\n appliedHeight = svgHeight;\n dimensions.height = svgHeight;\n dimensions.width = width;\n setAttributes(svg, { height: svgHeight, viewBox: `0 0 ${width} ${svgHeight}`, width });\n onResize?.();\n });\n\n setAttributes(svg, {\n height: initialHeight,\n viewBox: `0 0 ${initialWidth} ${initialHeight}`,\n width: initialWidth,\n });\n\n container.appendChild(svg);\n\n return {\n chartArea: chartAreaGroup,\n dimensions,\n dispose() {\n stopObserving();\n svg.remove();\n },\n svg,\n syncChrome,\n };\n}\n"],"mappings":"gJAeA,SAAgB,gBACd,EACA,EAaA,EACW,CAaX,GAAI,EANF,OAAO,GAAc,UACrB,GACA,EAAU,WAAa,GACvB,OAAO,EAAU,aAAgB,YACjC,OAAO,EAAU,uBAA0B,YAEzB,CAClB,IAAM,EAAoB,EACpB,EACJ,IAAa,KACT,OACA,OAAO,GAAa,SACjB,EAAS,aAAa,MAAQ,SAC/B,OAAO,EAEf,MAAM,IAAI,EAAA,iBAAiB,8EAA8E,EAAK,EAAE,CAClH,CAEA,IAAM,EAAS,EAAA,cAAc,EAAQ,MAAM,EACrC,EAAO,EAAQ,KACf,EAAM,EAAA,iBAAiB,MAAO,CAClC,GAAI,CAAC,GAAQ,EAAK,WACd,CAAE,cAAe,MAAO,EACxB,CAAE,aAAc,EAAK,UAAW,KAAM,MAAO,SAAU,GAAI,EAC/D,MAAO,cAKP,MAAO,8BACT,CAAC,EAEK,EAAiB,EAAA,iBAAiB,IAAK,CAC3C,MAAO,mBACP,UAAW,aAAa,EAAO,KAAK,GAAG,EAAO,IAAI,EACpD,CAAC,EAED,EAAI,YAAY,CAAc,EAE9B,IAAM,EAAO,EAAU,sBAAsB,EAEzC,EAAK,QAAU,GAAK,EAAK,OAM7B,IAAM,EAAe,EAAK,OAAS,IAC7B,EAAgB,EAAK,QAAU,IAE/B,EAA8B,CAClC,OAAQ,EACR,SACA,MAAO,CACT,EAII,EAAe,EACf,EAAgB,EAChB,EAAkB,EAGhB,eAAyB,CAC7B,IAAM,EAAS,KAAK,IAAI,EAAG,GAAmB,EAAQ,SAAS,CAAC,EAAE,cAAgB,EAAE,EAEpF,EAAgB,EAChB,EAAW,OAAS,EACpB,EAAA,cAAc,EAAK,CAAE,SAAQ,QAAS,OAAO,EAAW,MAAM,GAAG,GAAS,CAAC,CAC7E,EAEM,EAAgB,EAAA,cAAc,GAAY,EAAO,IAAW,CAChE,EAAkB,EAClB,IAAM,EAAe,EAAQ,SAAS,CAAC,EAAE,cAAgB,EACnD,EAAY,KAAK,IAAI,EAAG,EAAS,CAAY,GAO/C,IAAU,GAAgB,IAAc,KAE5C,EAAe,EACf,EAAgB,EAChB,EAAW,OAAS,EACpB,EAAW,MAAQ,EACnB,EAAA,cAAc,EAAK,CAAE,OAAQ,EAAW,QAAS,OAAO,EAAM,GAAG,IAAa,OAAM,CAAC,EACrF,IAAW,EACb,CAAC,EAUD,OARA,EAAA,cAAc,EAAK,CACjB,OAAQ,EACR,QAAS,OAAO,EAAa,GAAG,IAChC,MAAO,CACT,CAAC,EAED,EAAU,YAAY,CAAG,EAElB,CACL,UAAW,EACX,aACA,SAAU,CACR,EAAc,EACd,EAAI,OAAO,CACb,EACA,MACA,UACF,CACF"}
@@ -4,6 +4,7 @@ export interface ChartBase {
4
4
  dimensions: ChartDimensions;
5
5
  dispose(): void;
6
6
  svg: SVGSVGElement;
7
+ syncChrome(): void;
7
8
  }
8
9
  export declare function createChartBase(container: HTMLElement, options: {
9
10
  a11y?: ChartA11y;
@@ -1 +1 @@
1
- {"version":3,"file":"chart-base.d.ts","sourceRoot":"","sources":["../../src/core/chart-base.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAIxE,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,WAAW,CAAC;IACvB,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,IAAI,IAAI,CAAC;IAChB,GAAG,EAAE,aAAa,CAAC;CACpB;AAED,wBAAgB,eAAe,CAC7B,SAAS,EAAE,WAAW,EACtB,OAAO,EAAE;IACP,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC/B,EACD,QAAQ,CAAC,EAAE,MAAM,IAAI,GACpB,SAAS,CA0FX"}
1
+ {"version":3,"file":"chart-base.d.ts","sourceRoot":"","sources":["../../src/core/chart-base.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAIxE,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,WAAW,CAAC;IACvB,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,IAAI,IAAI,CAAC;IAChB,GAAG,EAAE,aAAa,CAAC;IACnB,UAAU,IAAI,IAAI,CAAC;CACpB;AAED,wBAAgB,eAAe,CAC7B,SAAS,EAAE,WAAW,EACtB,OAAO,EAAE;IACP,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC/B,EACD,QAAQ,CAAC,EAAE,MAAM,IAAI,GACpB,SAAS,CAoHX"}
@@ -1,2 +1,2 @@
1
- import"../_dev.js";import{createSvgElement as e,setAttributes as t}from"../svg/element.js";import{PrismRenderError as n}from"../errors.js";import{resolveMargin as r}from"./layout.js";import{observeResize as i}from"./responsive.js";function createChartBase(a,o,s){if(!(typeof a==`object`&&a&&a.nodeType===1&&typeof a.appendChild==`function`&&typeof a.getBoundingClientRect==`function`)){let e=a,t=e===null?`null`:typeof e==`object`?e.constructor?.name??`object`:typeof e;throw new n(`Invalid chart configuration: \`container\` must be a DOM Element, received ${t}.`)}let c=r(o.margin),l=o.a11y,u=e(`svg`,{...!l||l.decorative?{"aria-hidden":`true`}:{"aria-label":l.ariaLabel,role:`img`,tabindex:`0`},class:`prism-chart`,style:`display:block;max-width:100%`}),d=e(`g`,{class:`prism-chart-area`,transform:`translate(${c.left},${c.top})`});u.appendChild(d);let f=a.getBoundingClientRect();f.width===0||f.height;let p={height:f.height||300,margin:c,width:f.width||600},m=i(a,(e,n)=>{let r=o.chrome?.()?.offsetHeight??0,i=Math.max(0,n-r);p.height=i,p.width=e,t(u,{height:i,viewBox:`0 0 ${e} ${i}`,width:e}),s?.()}),h=f.width||600,g=f.height||300;return t(u,{height:g,viewBox:`0 0 ${h} ${g}`,width:h}),a.appendChild(u),{chartArea:d,dimensions:p,dispose(){m(),u.remove()},svg:u}}export{createChartBase};
1
+ import"../_dev.js";import{createSvgElement as e,setAttributes as t}from"../svg/element.js";import{PrismRenderError as n}from"../errors.js";import{resolveMargin as r}from"./layout.js";import{observeResize as i}from"./responsive.js";function createChartBase(a,o,s){if(!(typeof a==`object`&&a&&a.nodeType===1&&typeof a.appendChild==`function`&&typeof a.getBoundingClientRect==`function`)){let e=a,t=e===null?`null`:typeof e==`object`?e.constructor?.name??`object`:typeof e;throw new n(`Invalid chart configuration: \`container\` must be a DOM Element, received ${t}.`)}let c=r(o.margin),l=o.a11y,u=e(`svg`,{...!l||l.decorative?{"aria-hidden":`true`}:{"aria-label":l.ariaLabel,role:`img`,tabindex:`0`},class:`prism-chart`,style:`display:block;max-width:100%`}),d=e(`g`,{class:`prism-chart-area`,transform:`translate(${c.left},${c.top})`});u.appendChild(d);let f=a.getBoundingClientRect();f.width===0||f.height;let p=f.width||600,m=f.height||300,h={height:m,margin:c,width:p},g=p,_=m,v=m,syncChrome=()=>{let e=Math.max(0,v-(o.chrome?.()?.offsetHeight??0));_=e,h.height=e,t(u,{height:e,viewBox:`0 0 ${h.width} ${e}`})},y=i(a,(e,n)=>{v=n;let r=o.chrome?.()?.offsetHeight??0,i=Math.max(0,n-r);(e!==g||i!==_)&&(g=e,_=i,h.height=i,h.width=e,t(u,{height:i,viewBox:`0 0 ${e} ${i}`,width:e}),s?.())});return t(u,{height:m,viewBox:`0 0 ${p} ${m}`,width:p}),a.appendChild(u),{chartArea:d,dimensions:h,dispose(){y(),u.remove()},svg:u,syncChrome}}export{createChartBase};
2
2
  //# sourceMappingURL=chart-base.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-base.js","names":[],"sources":["../../src/core/chart-base.ts"],"sourcesContent":["import { warn } from '../_dev';\nimport { PrismRenderError } from '../errors';\nimport { createSvgElement, setAttributes } from '../svg/element';\nimport type { ChartA11y, ChartDimensions, ChartMargin } from '../types';\nimport { resolveMargin } from './layout';\nimport { observeResize } from './responsive';\n\nexport interface ChartBase {\n chartArea: SVGGElement;\n dimensions: ChartDimensions;\n dispose(): void;\n svg: SVGSVGElement;\n}\n\nexport function createChartBase(\n container: HTMLElement,\n options: {\n a11y?: ChartA11y;\n /**\n * The chart's own in-flow chrome inside the container (the legend). Its height is\n * subtracted from every resize-driven svg height: the container's content box contains\n * the svg plus this chrome, so assigning the full content height back to the svg would\n * grow the container by the chrome's height on every pass — unbounded growth in any\n * auto-height container. Subtracting it makes the layout converge on the fixed point\n * `container = svg + chrome` instead.\n */\n chrome?: () => HTMLElement | null;\n margin?: Partial<ChartMargin>;\n },\n onResize?: () => void,\n): ChartBase {\n // Duck-typed rather than `instanceof Element`: an `instanceof` check would reject a\n // structurally valid Element from a different realm (e.g. an Element created via\n // `iframe.contentDocument.createElement(...)`, whose prototype chain terminates in that\n // iframe's own `Element` constructor), which is a legitimate usage pattern this package\n // doesn't otherwise restrict.\n const isElementLike =\n typeof container === 'object' &&\n container !== null &&\n container.nodeType === 1 &&\n typeof container.appendChild === 'function' &&\n typeof container.getBoundingClientRect === 'function';\n\n if (!isElementLike) {\n const received: unknown = container;\n const kind =\n received === null\n ? 'null'\n : typeof received === 'object'\n ? (received.constructor?.name ?? 'object')\n : typeof received;\n\n throw new PrismRenderError(`Invalid chart configuration: \\`container\\` must be a DOM Element, received ${kind}.`);\n }\n\n const margin = resolveMargin(options.margin);\n const a11y = options.a11y;\n const svg = createSvgElement('svg', {\n ...(!a11y || a11y.decorative\n ? { 'aria-hidden': 'true' }\n : { 'aria-label': a11y.ariaLabel, role: 'img', tabindex: '0' }),\n class: 'prism-chart',\n // The svg's width/height attributes are its single source of sizing truth (set below and\n // on every resize pass, chrome excluded). CSS percentage sizing here would override the\n // attributes: `height: 100%` fills the whole container, so the in-flow legend rides past\n // the container's edge instead of inside the height the resize pass reserved for it.\n style: 'display:block;max-width:100%',\n });\n\n const chartAreaGroup = createSvgElement('g', {\n class: 'prism-chart-area',\n transform: `translate(${margin.left},${margin.top})`,\n });\n\n svg.appendChild(chartAreaGroup);\n\n const rect = container.getBoundingClientRect();\n\n if (rect.width === 0 || rect.height === 0) {\n warn(\n 'Chart container has zero dimensions. Ensure the container has a defined width and height before mounting a chart.',\n );\n }\n\n const dimensions: ChartDimensions = {\n height: rect.height || 300,\n margin,\n width: rect.width || 600,\n };\n\n const stopObserving = observeResize(container, (width, height) => {\n const chromeHeight = options.chrome?.()?.offsetHeight ?? 0;\n const svgHeight = Math.max(0, height - chromeHeight);\n\n dimensions.height = svgHeight;\n dimensions.width = width;\n setAttributes(svg, { height: svgHeight, viewBox: `0 0 ${width} ${svgHeight}`, width });\n onResize?.();\n });\n\n const initialWidth = rect.width || 600;\n const initialHeight = rect.height || 300;\n\n setAttributes(svg, {\n height: initialHeight,\n viewBox: `0 0 ${initialWidth} ${initialHeight}`,\n width: initialWidth,\n });\n\n container.appendChild(svg);\n\n return {\n chartArea: chartAreaGroup,\n dimensions,\n dispose() {\n stopObserving();\n svg.remove();\n },\n svg,\n };\n}\n"],"mappings":"uOAcA,SAAgB,gBACd,EACA,EAaA,EACW,CAaX,GAAI,EANF,OAAO,GAAc,UACrB,GACA,EAAU,WAAa,GACvB,OAAO,EAAU,aAAgB,YACjC,OAAO,EAAU,uBAA0B,YAEzB,CAClB,IAAM,EAAoB,EACpB,EACJ,IAAa,KACT,OACA,OAAO,GAAa,SACjB,EAAS,aAAa,MAAQ,SAC/B,OAAO,EAEf,MAAM,IAAI,EAAiB,8EAA8E,EAAK,EAAE,CAClH,CAEA,IAAM,EAAS,EAAc,EAAQ,MAAM,EACrC,EAAO,EAAQ,KACf,EAAM,EAAiB,MAAO,CAClC,GAAI,CAAC,GAAQ,EAAK,WACd,CAAE,cAAe,MAAO,EACxB,CAAE,aAAc,EAAK,UAAW,KAAM,MAAO,SAAU,GAAI,EAC/D,MAAO,cAKP,MAAO,8BACT,CAAC,EAEK,EAAiB,EAAiB,IAAK,CAC3C,MAAO,mBACP,UAAW,aAAa,EAAO,KAAK,GAAG,EAAO,IAAI,EACpD,CAAC,EAED,EAAI,YAAY,CAAc,EAE9B,IAAM,EAAO,EAAU,sBAAsB,EAEzC,EAAK,QAAU,GAAK,EAAK,OAM7B,IAAM,EAA8B,CAClC,OAAQ,EAAK,QAAU,IACvB,SACA,MAAO,EAAK,OAAS,GACvB,EAEM,EAAgB,EAAc,GAAY,EAAO,IAAW,CAChE,IAAM,EAAe,EAAQ,SAAS,CAAC,EAAE,cAAgB,EACnD,EAAY,KAAK,IAAI,EAAG,EAAS,CAAY,EAEnD,EAAW,OAAS,EACpB,EAAW,MAAQ,EACnB,EAAc,EAAK,CAAE,OAAQ,EAAW,QAAS,OAAO,EAAM,GAAG,IAAa,OAAM,CAAC,EACrF,IAAW,CACb,CAAC,EAEK,EAAe,EAAK,OAAS,IAC7B,EAAgB,EAAK,QAAU,IAUrC,OARA,EAAc,EAAK,CACjB,OAAQ,EACR,QAAS,OAAO,EAAa,GAAG,IAChC,MAAO,CACT,CAAC,EAED,EAAU,YAAY,CAAG,EAElB,CACL,UAAW,EACX,aACA,SAAU,CACR,EAAc,EACd,EAAI,OAAO,CACb,EACA,KACF,CACF"}
1
+ {"version":3,"file":"chart-base.js","names":[],"sources":["../../src/core/chart-base.ts"],"sourcesContent":["import { warn } from '../_dev';\nimport { PrismRenderError } from '../errors';\nimport { createSvgElement, setAttributes } from '../svg/element';\nimport type { ChartA11y, ChartDimensions, ChartMargin } from '../types';\nimport { resolveMargin } from './layout';\nimport { observeResize } from './responsive';\n\nexport interface ChartBase {\n chartArea: SVGGElement;\n dimensions: ChartDimensions;\n dispose(): void;\n svg: SVGSVGElement;\n syncChrome(): void;\n}\n\nexport function createChartBase(\n container: HTMLElement,\n options: {\n a11y?: ChartA11y;\n /**\n * The chart's own in-flow chrome inside the container (the legend). Its height is\n * subtracted from every resize-driven svg height: the container's content box contains\n * the svg plus this chrome, so assigning the full content height back to the svg would\n * grow the container by the chrome's height on every pass — unbounded growth in any\n * auto-height container. Subtracting it makes the layout converge on the fixed point\n * `container = svg + chrome` instead.\n */\n chrome?: () => HTMLElement | null;\n margin?: Partial<ChartMargin>;\n },\n onResize?: () => void,\n): ChartBase {\n // Duck-typed rather than `instanceof Element`: an `instanceof` check would reject a\n // structurally valid Element from a different realm (e.g. an Element created via\n // `iframe.contentDocument.createElement(...)`, whose prototype chain terminates in that\n // iframe's own `Element` constructor), which is a legitimate usage pattern this package\n // doesn't otherwise restrict.\n const isElementLike =\n typeof container === 'object' &&\n container !== null &&\n container.nodeType === 1 &&\n typeof container.appendChild === 'function' &&\n typeof container.getBoundingClientRect === 'function';\n\n if (!isElementLike) {\n const received: unknown = container;\n const kind =\n received === null\n ? 'null'\n : typeof received === 'object'\n ? (received.constructor?.name ?? 'object')\n : typeof received;\n\n throw new PrismRenderError(`Invalid chart configuration: \\`container\\` must be a DOM Element, received ${kind}.`);\n }\n\n const margin = resolveMargin(options.margin);\n const a11y = options.a11y;\n const svg = createSvgElement('svg', {\n ...(!a11y || a11y.decorative\n ? { 'aria-hidden': 'true' }\n : { 'aria-label': a11y.ariaLabel, role: 'img', tabindex: '0' }),\n class: 'prism-chart',\n // The svg's width/height attributes are its single source of sizing truth (set below and\n // on every resize pass, chrome excluded). CSS percentage sizing here would override the\n // attributes: `height: 100%` fills the whole container, so the in-flow legend rides past\n // the container's edge instead of inside the height the resize pass reserved for it.\n style: 'display:block;max-width:100%',\n });\n\n const chartAreaGroup = createSvgElement('g', {\n class: 'prism-chart-area',\n transform: `translate(${margin.left},${margin.top})`,\n });\n\n svg.appendChild(chartAreaGroup);\n\n const rect = container.getBoundingClientRect();\n\n if (rect.width === 0 || rect.height === 0) {\n warn(\n 'Chart container has zero dimensions. Ensure the container has a defined width and height before mounting a chart.',\n );\n }\n\n const initialWidth = rect.width || 600;\n const initialHeight = rect.height || 300;\n\n const dimensions: ChartDimensions = {\n height: initialHeight,\n margin,\n width: initialWidth,\n };\n\n // The dimensions the svg currently carries. A resize pass only re-renders when the\n // effective drawing size moves away from these.\n let appliedWidth = initialWidth;\n let appliedHeight = initialHeight;\n let containerHeight = initialHeight;\n\n // Legend updates reserve their space synchronously, before a renderer builds scales.\n const syncChrome = (): void => {\n const height = Math.max(0, containerHeight - (options.chrome?.()?.offsetHeight ?? 0));\n\n appliedHeight = height;\n dimensions.height = height;\n setAttributes(svg, { height, viewBox: `0 0 ${dimensions.width} ${height}` });\n };\n\n const stopObserving = observeResize(container, (width, height) => {\n containerHeight = height;\n const chromeHeight = options.chrome?.()?.offsetHeight ?? 0;\n const svgHeight = Math.max(0, height - chromeHeight);\n\n // A ResizeObserver fires once for the initial observation, at the size the chart was\n // already built at. Re-rendering there is a no-op for layout but cancels a mount\n // entrance still in flight (the renderers treat the redraw as an already-drawn\n // update and snap to final), so a chart would never animate on first paint. Skip the\n // pass unless the effective size — legend chrome included — has genuinely changed.\n if (width === appliedWidth && svgHeight === appliedHeight) return;\n\n appliedWidth = width;\n appliedHeight = svgHeight;\n dimensions.height = svgHeight;\n dimensions.width = width;\n setAttributes(svg, { height: svgHeight, viewBox: `0 0 ${width} ${svgHeight}`, width });\n onResize?.();\n });\n\n setAttributes(svg, {\n height: initialHeight,\n viewBox: `0 0 ${initialWidth} ${initialHeight}`,\n width: initialWidth,\n });\n\n container.appendChild(svg);\n\n return {\n chartArea: chartAreaGroup,\n dimensions,\n dispose() {\n stopObserving();\n svg.remove();\n },\n svg,\n syncChrome,\n };\n}\n"],"mappings":"uOAeA,SAAgB,gBACd,EACA,EAaA,EACW,CAaX,GAAI,EANF,OAAO,GAAc,UACrB,GACA,EAAU,WAAa,GACvB,OAAO,EAAU,aAAgB,YACjC,OAAO,EAAU,uBAA0B,YAEzB,CAClB,IAAM,EAAoB,EACpB,EACJ,IAAa,KACT,OACA,OAAO,GAAa,SACjB,EAAS,aAAa,MAAQ,SAC/B,OAAO,EAEf,MAAM,IAAI,EAAiB,8EAA8E,EAAK,EAAE,CAClH,CAEA,IAAM,EAAS,EAAc,EAAQ,MAAM,EACrC,EAAO,EAAQ,KACf,EAAM,EAAiB,MAAO,CAClC,GAAI,CAAC,GAAQ,EAAK,WACd,CAAE,cAAe,MAAO,EACxB,CAAE,aAAc,EAAK,UAAW,KAAM,MAAO,SAAU,GAAI,EAC/D,MAAO,cAKP,MAAO,8BACT,CAAC,EAEK,EAAiB,EAAiB,IAAK,CAC3C,MAAO,mBACP,UAAW,aAAa,EAAO,KAAK,GAAG,EAAO,IAAI,EACpD,CAAC,EAED,EAAI,YAAY,CAAc,EAE9B,IAAM,EAAO,EAAU,sBAAsB,EAEzC,EAAK,QAAU,GAAK,EAAK,OAM7B,IAAM,EAAe,EAAK,OAAS,IAC7B,EAAgB,EAAK,QAAU,IAE/B,EAA8B,CAClC,OAAQ,EACR,SACA,MAAO,CACT,EAII,EAAe,EACf,EAAgB,EAChB,EAAkB,EAGhB,eAAyB,CAC7B,IAAM,EAAS,KAAK,IAAI,EAAG,GAAmB,EAAQ,SAAS,CAAC,EAAE,cAAgB,EAAE,EAEpF,EAAgB,EAChB,EAAW,OAAS,EACpB,EAAc,EAAK,CAAE,SAAQ,QAAS,OAAO,EAAW,MAAM,GAAG,GAAS,CAAC,CAC7E,EAEM,EAAgB,EAAc,GAAY,EAAO,IAAW,CAChE,EAAkB,EAClB,IAAM,EAAe,EAAQ,SAAS,CAAC,EAAE,cAAgB,EACnD,EAAY,KAAK,IAAI,EAAG,EAAS,CAAY,GAO/C,IAAU,GAAgB,IAAc,KAE5C,EAAe,EACf,EAAgB,EAChB,EAAW,OAAS,EACpB,EAAW,MAAQ,EACnB,EAAc,EAAK,CAAE,OAAQ,EAAW,QAAS,OAAO,EAAM,GAAG,IAAa,OAAM,CAAC,EACrF,IAAW,EACb,CAAC,EAUD,OARA,EAAc,EAAK,CACjB,OAAQ,EACR,QAAS,OAAO,EAAa,GAAG,IAChC,MAAO,CACT,CAAC,EAED,EAAU,YAAY,CAAG,EAElB,CACL,UAAW,EACX,aACA,SAAU,CACR,EAAc,EACd,EAAI,OAAO,CACb,EACA,MACA,UACF,CACF"}
@@ -1,2 +1,2 @@
1
- const e=require("../svg/element.cjs"),t=require("../_tappers.cjs"),n=require("../errors.cjs"),r=require("../interaction/announcer.cjs"),i=require("../interaction/legend.cjs"),a=require("../interaction/tooltip.cjs"),o=require("./chart-base.cjs");function clearCartesianDom(t,n,r,i){e.removeChildren(t.series),e.removeChildren(t.grid),e.removeChildren(t.xAxis),e.removeChildren(t.yAxis),n?.update([]),r?.hide(),i?.hide()}function runScaffold(e,s,c,l,u){let render=()=>{},d=t.createTappers(),f=null,p=o.createChartBase(e,{a11y:s.a11y,chrome:()=>f?.el??null,margin:s.margin},()=>{d.emit({height:p.dimensions.height,type:`resize`,width:p.dimensions.width}),render()}),m=s.tooltip?a.createTooltip(e,s.tooltip):null;f=s.legend?i.createLegend(e,s.legend):null;let h=new AbortController,g=c(p,m,f,h.signal,r.createAnnouncer(p.svg,`prism-live`)),_=!1,v=makeEventManager(p.svg);render=()=>{_||v.attach(l(g))};try{render()}catch(e){throw _=!0,h.abort(),v.detach(),m?.dispose(),f?.dispose(),p.dispose(),e instanceof n.PrismRenderError?e:new n.PrismRenderError(`Failed to render chart.`,{cause:e})}return{get disposalSignal(){return h.signal},dispose(){_||(_=!0,d.emit({type:`dispose`}),d.stop(),h.abort(),v.detach(),m?.dispose(),f?.dispose(),p.dispose())},get disposed(){return _},el:p.svg,tap:d.tap,update(e){if(_)throw new n.PrismRenderError(`Cannot update a disposed chart.`);u(e),render()},[Symbol.dispose](){this.dispose()}}}function makeEventManager(e){let t=null;return{attach(n){t&&=(t.onMouseMove&&e.removeEventListener(`mousemove`,t.onMouseMove),t.onMouseLeave&&e.removeEventListener(`mouseleave`,t.onMouseLeave),t.onClick&&e.removeEventListener(`click`,t.onClick),t.onKeyDown&&e.removeEventListener(`keydown`,t.onKeyDown),null),n&&(t=n,n.onMouseMove&&e.addEventListener(`mousemove`,n.onMouseMove),n.onMouseLeave&&e.addEventListener(`mouseleave`,n.onMouseLeave),n.onClick&&e.addEventListener(`click`,n.onClick),n.onKeyDown&&e.addEventListener(`keydown`,n.onKeyDown))},detach(){this.attach(void 0)}}}function createChartScaffold(t,n,r,i){return runScaffold(t,n,(n,r,i,a,o)=>{let s={grid:e.createSvgElement(`g`,{"aria-hidden":`true`,class:`prism-grid`}),series:e.createSvgElement(`g`,{class:`prism-series`}),xAxis:e.createSvgElement(`g`,{class:`prism-x-axis`}),yAxis:e.createSvgElement(`g`,{class:`prism-y-axis`})};return n.chartArea.appendChild(s.grid),n.chartArea.appendChild(s.xAxis),n.chartArea.appendChild(s.yAxis),n.chartArea.appendChild(s.series),{announcer:o,chartArea:n.chartArea,container:t,dimensions:n.dimensions,disposalSignal:a,groups:s,legend:i,svg:n.svg,tooltip:r}},r,i)}function createRadialScaffold(e,t,n,r){return runScaffold(e,t,(t,n,r,i,a)=>({announcer:a,container:e,dimensions:t.dimensions,disposalSignal:i,legend:r,svg:t.svg,tooltip:n}),n,r)}exports.clearCartesianDom=clearCartesianDom,exports.createChartScaffold=createChartScaffold,exports.createRadialScaffold=createRadialScaffold;
1
+ const e=require("../svg/element.cjs"),t=require("../_tappers.cjs"),n=require("../errors.cjs"),r=require("../interaction/announcer.cjs"),i=require("../interaction/legend.cjs"),a=require("../interaction/tooltip.cjs"),o=require("./chart-base.cjs");function clearCartesianDom(t,n,r,i){e.removeChildren(t.series),e.removeChildren(t.grid),e.removeChildren(t.xAxis),e.removeChildren(t.yAxis),n?.update([]),r?.hide(),i?.hide()}function runScaffold(e,s,c,l,u){let render=e=>{},d=t.createTappers(),f=null,p=o.createChartBase(e,{a11y:s.a11y,chrome:()=>f?.el??null,margin:s.margin},()=>{d.emit({height:p.dimensions.height,type:`resize`,width:p.dimensions.width}),render(`resize`)}),m=s.tooltip?a.createTooltip(e,s.tooltip):null;f=s.legend?i.createLegend(e,s.legend,()=>p.syncChrome()):null;let h=new AbortController,g=c(p,m,f,h.signal,r.createAnnouncer(p.svg,`prism-live`)),_=!1,v=makeEventManager(p.svg);render=e=>{_||v.attach(l(g,e))};try{render(`mount`)}catch(e){throw _=!0,h.abort(),v.detach(),m?.dispose(),f?.dispose(),p.dispose(),e instanceof n.PrismRenderError?e:new n.PrismRenderError(`Failed to render chart.`,{cause:e})}return{get disposalSignal(){return h.signal},dispose(){_||(_=!0,d.emit({type:`dispose`}),d.stop(),h.abort(),v.detach(),m?.dispose(),f?.dispose(),p.dispose())},get disposed(){return _},el:p.svg,tap:d.tap,update(e){if(_)throw new n.PrismRenderError(`Cannot update a disposed chart.`);u(e),render(`update`)},[Symbol.dispose](){this.dispose()}}}function makeEventManager(e){let t=null;return{attach(n){t&&=(t.onMouseMove&&e.removeEventListener(`mousemove`,t.onMouseMove),t.onMouseLeave&&e.removeEventListener(`mouseleave`,t.onMouseLeave),t.onClick&&e.removeEventListener(`click`,t.onClick),t.onKeyDown&&e.removeEventListener(`keydown`,t.onKeyDown),null),n&&(t=n,n.onMouseMove&&e.addEventListener(`mousemove`,n.onMouseMove),n.onMouseLeave&&e.addEventListener(`mouseleave`,n.onMouseLeave),n.onClick&&e.addEventListener(`click`,n.onClick),n.onKeyDown&&e.addEventListener(`keydown`,n.onKeyDown))},detach(){this.attach(void 0)}}}function createChartScaffold(t,n,r,i){return runScaffold(t,n,(n,r,i,a,o)=>{let s={grid:e.createSvgElement(`g`,{"aria-hidden":`true`,class:`prism-grid`}),series:e.createSvgElement(`g`,{class:`prism-series`}),xAxis:e.createSvgElement(`g`,{class:`prism-x-axis`}),yAxis:e.createSvgElement(`g`,{class:`prism-y-axis`})};return n.chartArea.appendChild(s.grid),n.chartArea.appendChild(s.xAxis),n.chartArea.appendChild(s.yAxis),n.chartArea.appendChild(s.series),{announcer:o,chartArea:n.chartArea,container:t,dimensions:n.dimensions,disposalSignal:a,groups:s,legend:i,svg:n.svg,tooltip:r}},r,i)}function createRadialScaffold(e,t,n,r){return runScaffold(e,t,(t,n,r,i,a)=>({announcer:a,container:e,dimensions:t.dimensions,disposalSignal:i,legend:r,svg:t.svg,tooltip:n}),n,r)}exports.clearCartesianDom=clearCartesianDom,exports.createChartScaffold=createChartScaffold,exports.createRadialScaffold=createRadialScaffold;
2
2
  //# sourceMappingURL=chart-scaffold.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-scaffold.cjs","names":[],"sources":["../../src/core/chart-scaffold.ts"],"sourcesContent":["import { createTappers } from '../_tappers';\nimport { PrismRenderError } from '../errors';\nimport { type Announcer, createAnnouncer } from '../interaction/announcer';\nimport type { CrosshairState } from '../interaction/crosshair';\nimport type { LegendState } from '../interaction/legend';\nimport { createLegend } from '../interaction/legend';\nimport type { TooltipState } from '../interaction/tooltip';\nimport { createTooltip } from '../interaction/tooltip';\nimport { createSvgElement, removeChildren } from '../svg/element';\nimport type { BaseChartConfig, ChartDimensions, ChartHandle, PrismEvent } from '../types';\nimport { createChartBase } from './chart-base';\n\nexport interface ScaffoldGroups {\n grid: SVGGElement;\n series: SVGGElement;\n xAxis: SVGGElement;\n yAxis: SVGGElement;\n}\n\n/**\n * Clears a cartesian chart's series/grid/axis groups and hides its legend/tooltip/crosshair :\n * shared by every cartesian chart factory's \"no data\" early-return so an update\n * to empty data leaves a fully blank chart, not a half-cleared one.\n */\nexport function clearCartesianDom(\n groups: ScaffoldGroups,\n legend: LegendState | null,\n tooltip: TooltipState | null,\n crosshair?: CrosshairState | null,\n): void {\n removeChildren(groups.series);\n removeChildren(groups.grid);\n removeChildren(groups.xAxis);\n removeChildren(groups.yAxis);\n legend?.update([]);\n tooltip?.hide();\n crosshair?.hide();\n}\n\nexport interface ScaffoldContext {\n /** Speaks hover/keyboard values when no tooltip is shown (the tooltip is its own live region). */\n announcer: Announcer;\n chartArea: SVGGElement;\n container: HTMLElement;\n dimensions: ChartDimensions;\n /** Aborted when the chart is disposed: renderers use this to stop rescheduling in-flight `requestAnimationFrame` transitions. */\n disposalSignal: AbortSignal;\n groups: ScaffoldGroups;\n legend: LegendState | null;\n svg: SVGSVGElement;\n tooltip: TooltipState | null;\n}\n\nexport interface RadialScaffoldContext {\n announcer: Announcer;\n container: HTMLElement;\n dimensions: ChartDimensions;\n /** Aborted when the chart is disposed: renderers use this to stop rescheduling in-flight `requestAnimationFrame` transitions. */\n disposalSignal: AbortSignal;\n legend: LegendState | null;\n svg: SVGSVGElement;\n tooltip: TooltipState | null;\n}\n\nexport interface ChartEventHandlers {\n onClick?: (event: MouseEvent) => void;\n onKeyDown?: (event: KeyboardEvent) => void;\n onMouseLeave?: (event: MouseEvent) => void;\n onMouseMove?: (event: MouseEvent) => void;\n}\n\nfunction runScaffold<TCtx, TData>(\n container: HTMLElement,\n config: BaseChartConfig,\n buildCtx: (\n base: {\n chartArea: SVGGElement;\n dimensions: ChartDimensions;\n svg: SVGSVGElement;\n },\n tooltip: TooltipState | null,\n legend: LegendState | null,\n disposalSignal: AbortSignal,\n announcer: Announcer,\n ) => TCtx,\n renderFn: (ctx: TCtx) => ChartEventHandlers | undefined,\n updateData: (data: TData) => void,\n): ChartHandle<TData> {\n let render = () => {};\n const tappers = createTappers<PrismEvent>();\n // The legend is created after the base (bottom legends append after the svg), but the\n // chrome accessor runs only from the resize observer's async callback — by which time\n // the legend exists — so the deferred reference is safe.\n let legend: LegendState | null = null;\n const base = createChartBase(\n container,\n { a11y: config.a11y, chrome: () => legend?.el ?? null, margin: config.margin },\n () => {\n tappers.emit({ height: base.dimensions.height, type: 'resize', width: base.dimensions.width });\n render();\n },\n );\n const tooltip = config.tooltip ? createTooltip(container, config.tooltip) : null;\n legend = config.legend ? createLegend(container, config.legend) : null;\n const ac = new AbortController();\n const ctx = buildCtx(base, tooltip, legend, ac.signal, createAnnouncer(base.svg, 'prism-live'));\n\n let disposed = false;\n const events = makeEventManager(base.svg);\n\n render = () => {\n if (disposed) return;\n events.attach(renderFn(ctx));\n };\n\n try {\n render();\n } catch (error) {\n disposed = true;\n ac.abort();\n events.detach();\n tooltip?.dispose();\n legend?.dispose();\n base.dispose();\n throw error instanceof PrismRenderError ? error : new PrismRenderError('Failed to render chart.', { cause: error });\n }\n\n return {\n get disposalSignal(): AbortSignal {\n return ac.signal;\n },\n\n dispose() {\n if (disposed) return;\n\n disposed = true;\n tappers.emit({ type: 'dispose' });\n tappers.stop();\n ac.abort();\n events.detach();\n tooltip?.dispose();\n legend?.dispose();\n base.dispose();\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n el: base.svg,\n\n tap: tappers.tap,\n\n update(data) {\n if (disposed) throw new PrismRenderError('Cannot update a disposed chart.');\n updateData(data);\n render();\n },\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n}\n\nfunction makeEventManager(svg: SVGSVGElement): {\n attach(handlers: ChartEventHandlers | undefined): void;\n detach(): void;\n} {\n let active: ChartEventHandlers | null = null;\n\n return {\n attach(handlers) {\n if (active) {\n if (active.onMouseMove) svg.removeEventListener('mousemove', active.onMouseMove);\n\n if (active.onMouseLeave) svg.removeEventListener('mouseleave', active.onMouseLeave);\n\n if (active.onClick) svg.removeEventListener('click', active.onClick);\n\n if (active.onKeyDown) svg.removeEventListener('keydown', active.onKeyDown);\n\n active = null;\n }\n\n if (!handlers) return;\n\n active = handlers;\n\n if (handlers.onMouseMove) svg.addEventListener('mousemove', handlers.onMouseMove);\n\n if (handlers.onMouseLeave) svg.addEventListener('mouseleave', handlers.onMouseLeave);\n\n if (handlers.onClick) svg.addEventListener('click', handlers.onClick);\n\n if (handlers.onKeyDown) svg.addEventListener('keydown', handlers.onKeyDown);\n },\n detach() {\n this.attach(undefined);\n },\n };\n}\n\n/**\n * Cartesian scaffold: provides grid/axis/series SVG groups and a render loop.\n * `renderFn` returns optional `ChartEventHandlers` that are attached/replaced\n * after every data update or resize.\n */\nexport function createChartScaffold<TData>(\n container: HTMLElement,\n config: BaseChartConfig,\n renderFn: (ctx: ScaffoldContext) => ChartEventHandlers | undefined,\n updateData: (data: TData) => void,\n): ChartHandle<TData> {\n return runScaffold(\n container,\n config,\n (base, tooltip, legend, disposalSignal, announcer) => {\n const groups: ScaffoldGroups = {\n // Grid lines are purely decorative relative to the root svg's own role=\"img\"/aria-label.\n // Axis groups are NOT hidden wholesale: they can contain a meaningful `.prism-axis-title`;\n // `renderAxis` marks its own decorative tick lines/labels individually instead.\n grid: createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-grid' }),\n series: createSvgElement('g', { class: 'prism-series' }),\n xAxis: createSvgElement('g', { class: 'prism-x-axis' }),\n yAxis: createSvgElement('g', { class: 'prism-y-axis' }),\n };\n\n base.chartArea.appendChild(groups.grid);\n base.chartArea.appendChild(groups.xAxis);\n base.chartArea.appendChild(groups.yAxis);\n base.chartArea.appendChild(groups.series);\n\n return {\n announcer,\n chartArea: base.chartArea,\n container,\n dimensions: base.dimensions,\n disposalSignal,\n groups,\n legend,\n svg: base.svg,\n tooltip,\n } satisfies ScaffoldContext;\n },\n renderFn,\n updateData,\n );\n}\n\n/**\n * Radial scaffold: for charts that do not use cartesian axis groups\n * (pie, donut, semi). Provides only tooltip, legend, and the SVG root.\n */\nexport function createRadialScaffold<TData>(\n container: HTMLElement,\n config: BaseChartConfig,\n renderFn: (ctx: RadialScaffoldContext) => ChartEventHandlers | undefined,\n updateData: (data: TData) => void,\n): ChartHandle<TData> {\n return runScaffold(\n container,\n config,\n (base, tooltip, legend, disposalSignal, announcer) =>\n ({\n announcer,\n container,\n dimensions: base.dimensions,\n disposalSignal,\n legend,\n svg: base.svg,\n tooltip,\n }) satisfies RadialScaffoldContext,\n renderFn,\n updateData,\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"chart-scaffold.cjs","names":[],"sources":["../../src/core/chart-scaffold.ts"],"sourcesContent":["import { createTappers } from '../_tappers';\nimport { PrismRenderError } from '../errors';\nimport { type Announcer, createAnnouncer } from '../interaction/announcer';\nimport type { CrosshairState } from '../interaction/crosshair';\nimport type { LegendState } from '../interaction/legend';\nimport { createLegend } from '../interaction/legend';\nimport type { TooltipState } from '../interaction/tooltip';\nimport { createTooltip } from '../interaction/tooltip';\nimport { createSvgElement, removeChildren } from '../svg/element';\nimport type { BaseChartConfig, ChartDimensions, ChartHandle, PrismEvent } from '../types';\nimport { createChartBase } from './chart-base';\n\nexport interface ScaffoldGroups {\n grid: SVGGElement;\n series: SVGGElement;\n xAxis: SVGGElement;\n yAxis: SVGGElement;\n}\n\n/**\n * Clears a cartesian chart's series/grid/axis groups and hides its legend/tooltip/crosshair :\n * shared by every cartesian chart factory's \"no data\" early-return so an update\n * to empty data leaves a fully blank chart, not a half-cleared one.\n */\nexport function clearCartesianDom(\n groups: ScaffoldGroups,\n legend: LegendState | null,\n tooltip: TooltipState | null,\n crosshair?: CrosshairState | null,\n): void {\n removeChildren(groups.series);\n removeChildren(groups.grid);\n removeChildren(groups.xAxis);\n removeChildren(groups.yAxis);\n legend?.update([]);\n tooltip?.hide();\n crosshair?.hide();\n}\n\nexport interface ScaffoldContext {\n /** Speaks hover/keyboard values when no tooltip is shown (the tooltip is its own live region). */\n announcer: Announcer;\n chartArea: SVGGElement;\n container: HTMLElement;\n dimensions: ChartDimensions;\n /** Aborted when the chart is disposed: renderers use this to stop rescheduling in-flight `requestAnimationFrame` transitions. */\n disposalSignal: AbortSignal;\n groups: ScaffoldGroups;\n legend: LegendState | null;\n svg: SVGSVGElement;\n tooltip: TooltipState | null;\n}\n\nexport interface RadialScaffoldContext {\n announcer: Announcer;\n container: HTMLElement;\n dimensions: ChartDimensions;\n /** Aborted when the chart is disposed: renderers use this to stop rescheduling in-flight `requestAnimationFrame` transitions. */\n disposalSignal: AbortSignal;\n legend: LegendState | null;\n svg: SVGSVGElement;\n tooltip: TooltipState | null;\n}\n\nexport interface ChartEventHandlers {\n onClick?: (event: MouseEvent) => void;\n onKeyDown?: (event: KeyboardEvent) => void;\n onMouseLeave?: (event: MouseEvent) => void;\n onMouseMove?: (event: MouseEvent) => void;\n}\n\ntype RenderReason = 'mount' | 'resize' | 'update';\n\nfunction runScaffold<TCtx, TData>(\n container: HTMLElement,\n config: BaseChartConfig,\n buildCtx: (\n base: {\n chartArea: SVGGElement;\n dimensions: ChartDimensions;\n svg: SVGSVGElement;\n },\n tooltip: TooltipState | null,\n legend: LegendState | null,\n disposalSignal: AbortSignal,\n announcer: Announcer,\n ) => TCtx,\n renderFn: (ctx: TCtx, reason: RenderReason) => ChartEventHandlers | undefined,\n updateData: (data: TData) => void,\n): ChartHandle<TData> {\n let render = (_reason: RenderReason) => {};\n const tappers = createTappers<PrismEvent>();\n // Bottom legends follow the SVG. Populate them before measuring chart geometry,\n // so the first observer notification does not interrupt the entrance.\n let legend: LegendState | null = null;\n const base = createChartBase(\n container,\n { a11y: config.a11y, chrome: () => legend?.el ?? null, margin: config.margin },\n () => {\n tappers.emit({ height: base.dimensions.height, type: 'resize', width: base.dimensions.width });\n render('resize');\n },\n );\n const tooltip = config.tooltip ? createTooltip(container, config.tooltip) : null;\n legend = config.legend ? createLegend(container, config.legend, () => base.syncChrome()) : null;\n const ac = new AbortController();\n const ctx = buildCtx(base, tooltip, legend, ac.signal, createAnnouncer(base.svg, 'prism-live'));\n\n let disposed = false;\n const events = makeEventManager(base.svg);\n\n render = (reason) => {\n if (disposed) return;\n events.attach(renderFn(ctx, reason));\n };\n\n try {\n render('mount');\n } catch (error) {\n disposed = true;\n ac.abort();\n events.detach();\n tooltip?.dispose();\n legend?.dispose();\n base.dispose();\n throw error instanceof PrismRenderError ? error : new PrismRenderError('Failed to render chart.', { cause: error });\n }\n\n return {\n get disposalSignal(): AbortSignal {\n return ac.signal;\n },\n\n dispose() {\n if (disposed) return;\n\n disposed = true;\n tappers.emit({ type: 'dispose' });\n tappers.stop();\n ac.abort();\n events.detach();\n tooltip?.dispose();\n legend?.dispose();\n base.dispose();\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n el: base.svg,\n\n tap: tappers.tap,\n\n update(data) {\n if (disposed) throw new PrismRenderError('Cannot update a disposed chart.');\n updateData(data);\n render('update');\n },\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n}\n\nfunction makeEventManager(svg: SVGSVGElement): {\n attach(handlers: ChartEventHandlers | undefined): void;\n detach(): void;\n} {\n let active: ChartEventHandlers | null = null;\n\n return {\n attach(handlers) {\n if (active) {\n if (active.onMouseMove) svg.removeEventListener('mousemove', active.onMouseMove);\n\n if (active.onMouseLeave) svg.removeEventListener('mouseleave', active.onMouseLeave);\n\n if (active.onClick) svg.removeEventListener('click', active.onClick);\n\n if (active.onKeyDown) svg.removeEventListener('keydown', active.onKeyDown);\n\n active = null;\n }\n\n if (!handlers) return;\n\n active = handlers;\n\n if (handlers.onMouseMove) svg.addEventListener('mousemove', handlers.onMouseMove);\n\n if (handlers.onMouseLeave) svg.addEventListener('mouseleave', handlers.onMouseLeave);\n\n if (handlers.onClick) svg.addEventListener('click', handlers.onClick);\n\n if (handlers.onKeyDown) svg.addEventListener('keydown', handlers.onKeyDown);\n },\n detach() {\n this.attach(undefined);\n },\n };\n}\n\n/**\n * Cartesian scaffold: provides grid/axis/series SVG groups and a render loop.\n * `renderFn` returns optional `ChartEventHandlers` that are attached/replaced\n * after every data update or resize.\n */\nexport function createChartScaffold<TData>(\n container: HTMLElement,\n config: BaseChartConfig,\n renderFn: (ctx: ScaffoldContext, reason: RenderReason) => ChartEventHandlers | undefined,\n updateData: (data: TData) => void,\n): ChartHandle<TData> {\n return runScaffold(\n container,\n config,\n (base, tooltip, legend, disposalSignal, announcer) => {\n const groups: ScaffoldGroups = {\n // Grid lines are purely decorative relative to the root svg's own role=\"img\"/aria-label.\n // Axis groups are NOT hidden wholesale: they can contain a meaningful `.prism-axis-title`;\n // `renderAxis` marks its own decorative tick lines/labels individually instead.\n grid: createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-grid' }),\n series: createSvgElement('g', { class: 'prism-series' }),\n xAxis: createSvgElement('g', { class: 'prism-x-axis' }),\n yAxis: createSvgElement('g', { class: 'prism-y-axis' }),\n };\n\n base.chartArea.appendChild(groups.grid);\n base.chartArea.appendChild(groups.xAxis);\n base.chartArea.appendChild(groups.yAxis);\n base.chartArea.appendChild(groups.series);\n\n return {\n announcer,\n chartArea: base.chartArea,\n container,\n dimensions: base.dimensions,\n disposalSignal,\n groups,\n legend,\n svg: base.svg,\n tooltip,\n } satisfies ScaffoldContext;\n },\n renderFn,\n updateData,\n );\n}\n\n/**\n * Radial scaffold: for charts that do not use cartesian axis groups\n * (pie, donut, semi). Provides only tooltip, legend, and the SVG root.\n */\nexport function createRadialScaffold<TData>(\n container: HTMLElement,\n config: BaseChartConfig,\n renderFn: (ctx: RadialScaffoldContext, reason: RenderReason) => ChartEventHandlers | undefined,\n updateData: (data: TData) => void,\n): ChartHandle<TData> {\n return runScaffold(\n container,\n config,\n (base, tooltip, legend, disposalSignal, announcer) =>\n ({\n announcer,\n container,\n dimensions: base.dimensions,\n disposalSignal,\n legend,\n svg: base.svg,\n tooltip,\n }) satisfies RadialScaffoldContext,\n renderFn,\n updateData,\n );\n}\n"],"mappings":"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"}
@@ -44,15 +44,17 @@ export interface ChartEventHandlers {
44
44
  onMouseLeave?: (event: MouseEvent) => void;
45
45
  onMouseMove?: (event: MouseEvent) => void;
46
46
  }
47
+ type RenderReason = 'mount' | 'resize' | 'update';
47
48
  /**
48
49
  * Cartesian scaffold: provides grid/axis/series SVG groups and a render loop.
49
50
  * `renderFn` returns optional `ChartEventHandlers` that are attached/replaced
50
51
  * after every data update or resize.
51
52
  */
52
- export declare function createChartScaffold<TData>(container: HTMLElement, config: BaseChartConfig, renderFn: (ctx: ScaffoldContext) => ChartEventHandlers | undefined, updateData: (data: TData) => void): ChartHandle<TData>;
53
+ export declare function createChartScaffold<TData>(container: HTMLElement, config: BaseChartConfig, renderFn: (ctx: ScaffoldContext, reason: RenderReason) => ChartEventHandlers | undefined, updateData: (data: TData) => void): ChartHandle<TData>;
53
54
  /**
54
55
  * Radial scaffold: for charts that do not use cartesian axis groups
55
56
  * (pie, donut, semi). Provides only tooltip, legend, and the SVG root.
56
57
  */
57
- export declare function createRadialScaffold<TData>(container: HTMLElement, config: BaseChartConfig, renderFn: (ctx: RadialScaffoldContext) => ChartEventHandlers | undefined, updateData: (data: TData) => void): ChartHandle<TData>;
58
+ export declare function createRadialScaffold<TData>(container: HTMLElement, config: BaseChartConfig, renderFn: (ctx: RadialScaffoldContext, reason: RenderReason) => ChartEventHandlers | undefined, updateData: (data: TData) => void): ChartHandle<TData>;
59
+ export {};
58
60
  //# sourceMappingURL=chart-scaffold.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-scaffold.d.ts","sourceRoot":"","sources":["../../src/core/chart-scaffold.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAc,MAAM,UAAU,CAAC;AAG1F,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,WAAW,GAAG,IAAI,EAC1B,OAAO,EAAE,YAAY,GAAG,IAAI,EAC5B,SAAS,CAAC,EAAE,cAAc,GAAG,IAAI,GAChC,IAAI,CAQN;AAED,MAAM,WAAW,eAAe;IAC9B,kGAAkG;IAClG,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,EAAE,WAAW,CAAC;IACvB,UAAU,EAAE,eAAe,CAAC;IAC5B,iIAAiI;IACjI,cAAc,EAAE,WAAW,CAAC;IAC5B,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,WAAW,CAAC;IACvB,UAAU,EAAE,eAAe,CAAC;IAC5B,iIAAiI;IACjI,cAAc,EAAE,WAAW,CAAC;IAC5B,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC3C,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CAC3C;AAsID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EACvC,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,kBAAkB,GAAG,SAAS,EAClE,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,GAChC,WAAW,CAAC,KAAK,CAAC,CAmCpB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EACxC,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,kBAAkB,GAAG,SAAS,EACxE,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,GAChC,WAAW,CAAC,KAAK,CAAC,CAiBpB"}
1
+ {"version":3,"file":"chart-scaffold.d.ts","sourceRoot":"","sources":["../../src/core/chart-scaffold.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAc,MAAM,UAAU,CAAC;AAG1F,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,WAAW,GAAG,IAAI,EAC1B,OAAO,EAAE,YAAY,GAAG,IAAI,EAC5B,SAAS,CAAC,EAAE,cAAc,GAAG,IAAI,GAChC,IAAI,CAQN;AAED,MAAM,WAAW,eAAe;IAC9B,kGAAkG;IAClG,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,EAAE,WAAW,CAAC;IACvB,UAAU,EAAE,eAAe,CAAC;IAC5B,iIAAiI;IACjI,cAAc,EAAE,WAAW,CAAC;IAC5B,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,WAAW,CAAC;IACvB,UAAU,EAAE,eAAe,CAAC;IAC5B,iIAAiI;IACjI,cAAc,EAAE,WAAW,CAAC;IAC5B,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC3C,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CAC3C;AAED,KAAK,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAqIlD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EACvC,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,KAAK,kBAAkB,GAAG,SAAS,EACxF,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,GAChC,WAAW,CAAC,KAAK,CAAC,CAmCpB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EACxC,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,CAAC,GAAG,EAAE,qBAAqB,EAAE,MAAM,EAAE,YAAY,KAAK,kBAAkB,GAAG,SAAS,EAC9F,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,GAChC,WAAW,CAAC,KAAK,CAAC,CAiBpB"}
@@ -1,2 +1,2 @@
1
- import{createSvgElement as e,removeChildren as t}from"../svg/element.js";import{createTappers as n}from"../_tappers.js";import{PrismRenderError as r}from"../errors.js";import{createAnnouncer as i}from"../interaction/announcer.js";import{createLegend as a}from"../interaction/legend.js";import{createTooltip as o}from"../interaction/tooltip.js";import{createChartBase as s}from"./chart-base.js";function clearCartesianDom(e,n,r,i){t(e.series),t(e.grid),t(e.xAxis),t(e.yAxis),n?.update([]),r?.hide(),i?.hide()}function runScaffold(e,t,c,l,u){let render=()=>{},d=n(),f=null,p=s(e,{a11y:t.a11y,chrome:()=>f?.el??null,margin:t.margin},()=>{d.emit({height:p.dimensions.height,type:`resize`,width:p.dimensions.width}),render()}),m=t.tooltip?o(e,t.tooltip):null;f=t.legend?a(e,t.legend):null;let h=new AbortController,g=c(p,m,f,h.signal,i(p.svg,`prism-live`)),_=!1,v=makeEventManager(p.svg);render=()=>{_||v.attach(l(g))};try{render()}catch(e){throw _=!0,h.abort(),v.detach(),m?.dispose(),f?.dispose(),p.dispose(),e instanceof r?e:new r(`Failed to render chart.`,{cause:e})}return{get disposalSignal(){return h.signal},dispose(){_||(_=!0,d.emit({type:`dispose`}),d.stop(),h.abort(),v.detach(),m?.dispose(),f?.dispose(),p.dispose())},get disposed(){return _},el:p.svg,tap:d.tap,update(e){if(_)throw new r(`Cannot update a disposed chart.`);u(e),render()},[Symbol.dispose](){this.dispose()}}}function makeEventManager(e){let t=null;return{attach(n){t&&=(t.onMouseMove&&e.removeEventListener(`mousemove`,t.onMouseMove),t.onMouseLeave&&e.removeEventListener(`mouseleave`,t.onMouseLeave),t.onClick&&e.removeEventListener(`click`,t.onClick),t.onKeyDown&&e.removeEventListener(`keydown`,t.onKeyDown),null),n&&(t=n,n.onMouseMove&&e.addEventListener(`mousemove`,n.onMouseMove),n.onMouseLeave&&e.addEventListener(`mouseleave`,n.onMouseLeave),n.onClick&&e.addEventListener(`click`,n.onClick),n.onKeyDown&&e.addEventListener(`keydown`,n.onKeyDown))},detach(){this.attach(void 0)}}}function createChartScaffold(t,n,r,i){return runScaffold(t,n,(n,r,i,a,o)=>{let s={grid:e(`g`,{"aria-hidden":`true`,class:`prism-grid`}),series:e(`g`,{class:`prism-series`}),xAxis:e(`g`,{class:`prism-x-axis`}),yAxis:e(`g`,{class:`prism-y-axis`})};return n.chartArea.appendChild(s.grid),n.chartArea.appendChild(s.xAxis),n.chartArea.appendChild(s.yAxis),n.chartArea.appendChild(s.series),{announcer:o,chartArea:n.chartArea,container:t,dimensions:n.dimensions,disposalSignal:a,groups:s,legend:i,svg:n.svg,tooltip:r}},r,i)}function createRadialScaffold(e,t,n,r){return runScaffold(e,t,(t,n,r,i,a)=>({announcer:a,container:e,dimensions:t.dimensions,disposalSignal:i,legend:r,svg:t.svg,tooltip:n}),n,r)}export{clearCartesianDom,createChartScaffold,createRadialScaffold};
1
+ import{createSvgElement as e,removeChildren as t}from"../svg/element.js";import{createTappers as n}from"../_tappers.js";import{PrismRenderError as r}from"../errors.js";import{createAnnouncer as i}from"../interaction/announcer.js";import{createLegend as a}from"../interaction/legend.js";import{createTooltip as o}from"../interaction/tooltip.js";import{createChartBase as s}from"./chart-base.js";function clearCartesianDom(e,n,r,i){t(e.series),t(e.grid),t(e.xAxis),t(e.yAxis),n?.update([]),r?.hide(),i?.hide()}function runScaffold(e,t,c,l,u){let render=e=>{},d=n(),f=null,p=s(e,{a11y:t.a11y,chrome:()=>f?.el??null,margin:t.margin},()=>{d.emit({height:p.dimensions.height,type:`resize`,width:p.dimensions.width}),render(`resize`)}),m=t.tooltip?o(e,t.tooltip):null;f=t.legend?a(e,t.legend,()=>p.syncChrome()):null;let h=new AbortController,g=c(p,m,f,h.signal,i(p.svg,`prism-live`)),_=!1,v=makeEventManager(p.svg);render=e=>{_||v.attach(l(g,e))};try{render(`mount`)}catch(e){throw _=!0,h.abort(),v.detach(),m?.dispose(),f?.dispose(),p.dispose(),e instanceof r?e:new r(`Failed to render chart.`,{cause:e})}return{get disposalSignal(){return h.signal},dispose(){_||(_=!0,d.emit({type:`dispose`}),d.stop(),h.abort(),v.detach(),m?.dispose(),f?.dispose(),p.dispose())},get disposed(){return _},el:p.svg,tap:d.tap,update(e){if(_)throw new r(`Cannot update a disposed chart.`);u(e),render(`update`)},[Symbol.dispose](){this.dispose()}}}function makeEventManager(e){let t=null;return{attach(n){t&&=(t.onMouseMove&&e.removeEventListener(`mousemove`,t.onMouseMove),t.onMouseLeave&&e.removeEventListener(`mouseleave`,t.onMouseLeave),t.onClick&&e.removeEventListener(`click`,t.onClick),t.onKeyDown&&e.removeEventListener(`keydown`,t.onKeyDown),null),n&&(t=n,n.onMouseMove&&e.addEventListener(`mousemove`,n.onMouseMove),n.onMouseLeave&&e.addEventListener(`mouseleave`,n.onMouseLeave),n.onClick&&e.addEventListener(`click`,n.onClick),n.onKeyDown&&e.addEventListener(`keydown`,n.onKeyDown))},detach(){this.attach(void 0)}}}function createChartScaffold(t,n,r,i){return runScaffold(t,n,(n,r,i,a,o)=>{let s={grid:e(`g`,{"aria-hidden":`true`,class:`prism-grid`}),series:e(`g`,{class:`prism-series`}),xAxis:e(`g`,{class:`prism-x-axis`}),yAxis:e(`g`,{class:`prism-y-axis`})};return n.chartArea.appendChild(s.grid),n.chartArea.appendChild(s.xAxis),n.chartArea.appendChild(s.yAxis),n.chartArea.appendChild(s.series),{announcer:o,chartArea:n.chartArea,container:t,dimensions:n.dimensions,disposalSignal:a,groups:s,legend:i,svg:n.svg,tooltip:r}},r,i)}function createRadialScaffold(e,t,n,r){return runScaffold(e,t,(t,n,r,i,a)=>({announcer:a,container:e,dimensions:t.dimensions,disposalSignal:i,legend:r,svg:t.svg,tooltip:n}),n,r)}export{clearCartesianDom,createChartScaffold,createRadialScaffold};
2
2
  //# sourceMappingURL=chart-scaffold.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-scaffold.js","names":[],"sources":["../../src/core/chart-scaffold.ts"],"sourcesContent":["import { createTappers } from '../_tappers';\nimport { PrismRenderError } from '../errors';\nimport { type Announcer, createAnnouncer } from '../interaction/announcer';\nimport type { CrosshairState } from '../interaction/crosshair';\nimport type { LegendState } from '../interaction/legend';\nimport { createLegend } from '../interaction/legend';\nimport type { TooltipState } from '../interaction/tooltip';\nimport { createTooltip } from '../interaction/tooltip';\nimport { createSvgElement, removeChildren } from '../svg/element';\nimport type { BaseChartConfig, ChartDimensions, ChartHandle, PrismEvent } from '../types';\nimport { createChartBase } from './chart-base';\n\nexport interface ScaffoldGroups {\n grid: SVGGElement;\n series: SVGGElement;\n xAxis: SVGGElement;\n yAxis: SVGGElement;\n}\n\n/**\n * Clears a cartesian chart's series/grid/axis groups and hides its legend/tooltip/crosshair :\n * shared by every cartesian chart factory's \"no data\" early-return so an update\n * to empty data leaves a fully blank chart, not a half-cleared one.\n */\nexport function clearCartesianDom(\n groups: ScaffoldGroups,\n legend: LegendState | null,\n tooltip: TooltipState | null,\n crosshair?: CrosshairState | null,\n): void {\n removeChildren(groups.series);\n removeChildren(groups.grid);\n removeChildren(groups.xAxis);\n removeChildren(groups.yAxis);\n legend?.update([]);\n tooltip?.hide();\n crosshair?.hide();\n}\n\nexport interface ScaffoldContext {\n /** Speaks hover/keyboard values when no tooltip is shown (the tooltip is its own live region). */\n announcer: Announcer;\n chartArea: SVGGElement;\n container: HTMLElement;\n dimensions: ChartDimensions;\n /** Aborted when the chart is disposed: renderers use this to stop rescheduling in-flight `requestAnimationFrame` transitions. */\n disposalSignal: AbortSignal;\n groups: ScaffoldGroups;\n legend: LegendState | null;\n svg: SVGSVGElement;\n tooltip: TooltipState | null;\n}\n\nexport interface RadialScaffoldContext {\n announcer: Announcer;\n container: HTMLElement;\n dimensions: ChartDimensions;\n /** Aborted when the chart is disposed: renderers use this to stop rescheduling in-flight `requestAnimationFrame` transitions. */\n disposalSignal: AbortSignal;\n legend: LegendState | null;\n svg: SVGSVGElement;\n tooltip: TooltipState | null;\n}\n\nexport interface ChartEventHandlers {\n onClick?: (event: MouseEvent) => void;\n onKeyDown?: (event: KeyboardEvent) => void;\n onMouseLeave?: (event: MouseEvent) => void;\n onMouseMove?: (event: MouseEvent) => void;\n}\n\nfunction runScaffold<TCtx, TData>(\n container: HTMLElement,\n config: BaseChartConfig,\n buildCtx: (\n base: {\n chartArea: SVGGElement;\n dimensions: ChartDimensions;\n svg: SVGSVGElement;\n },\n tooltip: TooltipState | null,\n legend: LegendState | null,\n disposalSignal: AbortSignal,\n announcer: Announcer,\n ) => TCtx,\n renderFn: (ctx: TCtx) => ChartEventHandlers | undefined,\n updateData: (data: TData) => void,\n): ChartHandle<TData> {\n let render = () => {};\n const tappers = createTappers<PrismEvent>();\n // The legend is created after the base (bottom legends append after the svg), but the\n // chrome accessor runs only from the resize observer's async callback — by which time\n // the legend exists — so the deferred reference is safe.\n let legend: LegendState | null = null;\n const base = createChartBase(\n container,\n { a11y: config.a11y, chrome: () => legend?.el ?? null, margin: config.margin },\n () => {\n tappers.emit({ height: base.dimensions.height, type: 'resize', width: base.dimensions.width });\n render();\n },\n );\n const tooltip = config.tooltip ? createTooltip(container, config.tooltip) : null;\n legend = config.legend ? createLegend(container, config.legend) : null;\n const ac = new AbortController();\n const ctx = buildCtx(base, tooltip, legend, ac.signal, createAnnouncer(base.svg, 'prism-live'));\n\n let disposed = false;\n const events = makeEventManager(base.svg);\n\n render = () => {\n if (disposed) return;\n events.attach(renderFn(ctx));\n };\n\n try {\n render();\n } catch (error) {\n disposed = true;\n ac.abort();\n events.detach();\n tooltip?.dispose();\n legend?.dispose();\n base.dispose();\n throw error instanceof PrismRenderError ? error : new PrismRenderError('Failed to render chart.', { cause: error });\n }\n\n return {\n get disposalSignal(): AbortSignal {\n return ac.signal;\n },\n\n dispose() {\n if (disposed) return;\n\n disposed = true;\n tappers.emit({ type: 'dispose' });\n tappers.stop();\n ac.abort();\n events.detach();\n tooltip?.dispose();\n legend?.dispose();\n base.dispose();\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n el: base.svg,\n\n tap: tappers.tap,\n\n update(data) {\n if (disposed) throw new PrismRenderError('Cannot update a disposed chart.');\n updateData(data);\n render();\n },\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n}\n\nfunction makeEventManager(svg: SVGSVGElement): {\n attach(handlers: ChartEventHandlers | undefined): void;\n detach(): void;\n} {\n let active: ChartEventHandlers | null = null;\n\n return {\n attach(handlers) {\n if (active) {\n if (active.onMouseMove) svg.removeEventListener('mousemove', active.onMouseMove);\n\n if (active.onMouseLeave) svg.removeEventListener('mouseleave', active.onMouseLeave);\n\n if (active.onClick) svg.removeEventListener('click', active.onClick);\n\n if (active.onKeyDown) svg.removeEventListener('keydown', active.onKeyDown);\n\n active = null;\n }\n\n if (!handlers) return;\n\n active = handlers;\n\n if (handlers.onMouseMove) svg.addEventListener('mousemove', handlers.onMouseMove);\n\n if (handlers.onMouseLeave) svg.addEventListener('mouseleave', handlers.onMouseLeave);\n\n if (handlers.onClick) svg.addEventListener('click', handlers.onClick);\n\n if (handlers.onKeyDown) svg.addEventListener('keydown', handlers.onKeyDown);\n },\n detach() {\n this.attach(undefined);\n },\n };\n}\n\n/**\n * Cartesian scaffold: provides grid/axis/series SVG groups and a render loop.\n * `renderFn` returns optional `ChartEventHandlers` that are attached/replaced\n * after every data update or resize.\n */\nexport function createChartScaffold<TData>(\n container: HTMLElement,\n config: BaseChartConfig,\n renderFn: (ctx: ScaffoldContext) => ChartEventHandlers | undefined,\n updateData: (data: TData) => void,\n): ChartHandle<TData> {\n return runScaffold(\n container,\n config,\n (base, tooltip, legend, disposalSignal, announcer) => {\n const groups: ScaffoldGroups = {\n // Grid lines are purely decorative relative to the root svg's own role=\"img\"/aria-label.\n // Axis groups are NOT hidden wholesale: they can contain a meaningful `.prism-axis-title`;\n // `renderAxis` marks its own decorative tick lines/labels individually instead.\n grid: createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-grid' }),\n series: createSvgElement('g', { class: 'prism-series' }),\n xAxis: createSvgElement('g', { class: 'prism-x-axis' }),\n yAxis: createSvgElement('g', { class: 'prism-y-axis' }),\n };\n\n base.chartArea.appendChild(groups.grid);\n base.chartArea.appendChild(groups.xAxis);\n base.chartArea.appendChild(groups.yAxis);\n base.chartArea.appendChild(groups.series);\n\n return {\n announcer,\n chartArea: base.chartArea,\n container,\n dimensions: base.dimensions,\n disposalSignal,\n groups,\n legend,\n svg: base.svg,\n tooltip,\n } satisfies ScaffoldContext;\n },\n renderFn,\n updateData,\n );\n}\n\n/**\n * Radial scaffold: for charts that do not use cartesian axis groups\n * (pie, donut, semi). Provides only tooltip, legend, and the SVG root.\n */\nexport function createRadialScaffold<TData>(\n container: HTMLElement,\n config: BaseChartConfig,\n renderFn: (ctx: RadialScaffoldContext) => ChartEventHandlers | undefined,\n updateData: (data: TData) => void,\n): ChartHandle<TData> {\n return runScaffold(\n container,\n config,\n (base, tooltip, legend, disposalSignal, announcer) =>\n ({\n announcer,\n container,\n dimensions: base.dimensions,\n disposalSignal,\n legend,\n svg: base.svg,\n tooltip,\n }) satisfies RadialScaffoldContext,\n renderFn,\n updateData,\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"chart-scaffold.js","names":[],"sources":["../../src/core/chart-scaffold.ts"],"sourcesContent":["import { createTappers } from '../_tappers';\nimport { PrismRenderError } from '../errors';\nimport { type Announcer, createAnnouncer } from '../interaction/announcer';\nimport type { CrosshairState } from '../interaction/crosshair';\nimport type { LegendState } from '../interaction/legend';\nimport { createLegend } from '../interaction/legend';\nimport type { TooltipState } from '../interaction/tooltip';\nimport { createTooltip } from '../interaction/tooltip';\nimport { createSvgElement, removeChildren } from '../svg/element';\nimport type { BaseChartConfig, ChartDimensions, ChartHandle, PrismEvent } from '../types';\nimport { createChartBase } from './chart-base';\n\nexport interface ScaffoldGroups {\n grid: SVGGElement;\n series: SVGGElement;\n xAxis: SVGGElement;\n yAxis: SVGGElement;\n}\n\n/**\n * Clears a cartesian chart's series/grid/axis groups and hides its legend/tooltip/crosshair :\n * shared by every cartesian chart factory's \"no data\" early-return so an update\n * to empty data leaves a fully blank chart, not a half-cleared one.\n */\nexport function clearCartesianDom(\n groups: ScaffoldGroups,\n legend: LegendState | null,\n tooltip: TooltipState | null,\n crosshair?: CrosshairState | null,\n): void {\n removeChildren(groups.series);\n removeChildren(groups.grid);\n removeChildren(groups.xAxis);\n removeChildren(groups.yAxis);\n legend?.update([]);\n tooltip?.hide();\n crosshair?.hide();\n}\n\nexport interface ScaffoldContext {\n /** Speaks hover/keyboard values when no tooltip is shown (the tooltip is its own live region). */\n announcer: Announcer;\n chartArea: SVGGElement;\n container: HTMLElement;\n dimensions: ChartDimensions;\n /** Aborted when the chart is disposed: renderers use this to stop rescheduling in-flight `requestAnimationFrame` transitions. */\n disposalSignal: AbortSignal;\n groups: ScaffoldGroups;\n legend: LegendState | null;\n svg: SVGSVGElement;\n tooltip: TooltipState | null;\n}\n\nexport interface RadialScaffoldContext {\n announcer: Announcer;\n container: HTMLElement;\n dimensions: ChartDimensions;\n /** Aborted when the chart is disposed: renderers use this to stop rescheduling in-flight `requestAnimationFrame` transitions. */\n disposalSignal: AbortSignal;\n legend: LegendState | null;\n svg: SVGSVGElement;\n tooltip: TooltipState | null;\n}\n\nexport interface ChartEventHandlers {\n onClick?: (event: MouseEvent) => void;\n onKeyDown?: (event: KeyboardEvent) => void;\n onMouseLeave?: (event: MouseEvent) => void;\n onMouseMove?: (event: MouseEvent) => void;\n}\n\ntype RenderReason = 'mount' | 'resize' | 'update';\n\nfunction runScaffold<TCtx, TData>(\n container: HTMLElement,\n config: BaseChartConfig,\n buildCtx: (\n base: {\n chartArea: SVGGElement;\n dimensions: ChartDimensions;\n svg: SVGSVGElement;\n },\n tooltip: TooltipState | null,\n legend: LegendState | null,\n disposalSignal: AbortSignal,\n announcer: Announcer,\n ) => TCtx,\n renderFn: (ctx: TCtx, reason: RenderReason) => ChartEventHandlers | undefined,\n updateData: (data: TData) => void,\n): ChartHandle<TData> {\n let render = (_reason: RenderReason) => {};\n const tappers = createTappers<PrismEvent>();\n // Bottom legends follow the SVG. Populate them before measuring chart geometry,\n // so the first observer notification does not interrupt the entrance.\n let legend: LegendState | null = null;\n const base = createChartBase(\n container,\n { a11y: config.a11y, chrome: () => legend?.el ?? null, margin: config.margin },\n () => {\n tappers.emit({ height: base.dimensions.height, type: 'resize', width: base.dimensions.width });\n render('resize');\n },\n );\n const tooltip = config.tooltip ? createTooltip(container, config.tooltip) : null;\n legend = config.legend ? createLegend(container, config.legend, () => base.syncChrome()) : null;\n const ac = new AbortController();\n const ctx = buildCtx(base, tooltip, legend, ac.signal, createAnnouncer(base.svg, 'prism-live'));\n\n let disposed = false;\n const events = makeEventManager(base.svg);\n\n render = (reason) => {\n if (disposed) return;\n events.attach(renderFn(ctx, reason));\n };\n\n try {\n render('mount');\n } catch (error) {\n disposed = true;\n ac.abort();\n events.detach();\n tooltip?.dispose();\n legend?.dispose();\n base.dispose();\n throw error instanceof PrismRenderError ? error : new PrismRenderError('Failed to render chart.', { cause: error });\n }\n\n return {\n get disposalSignal(): AbortSignal {\n return ac.signal;\n },\n\n dispose() {\n if (disposed) return;\n\n disposed = true;\n tappers.emit({ type: 'dispose' });\n tappers.stop();\n ac.abort();\n events.detach();\n tooltip?.dispose();\n legend?.dispose();\n base.dispose();\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n el: base.svg,\n\n tap: tappers.tap,\n\n update(data) {\n if (disposed) throw new PrismRenderError('Cannot update a disposed chart.');\n updateData(data);\n render('update');\n },\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n}\n\nfunction makeEventManager(svg: SVGSVGElement): {\n attach(handlers: ChartEventHandlers | undefined): void;\n detach(): void;\n} {\n let active: ChartEventHandlers | null = null;\n\n return {\n attach(handlers) {\n if (active) {\n if (active.onMouseMove) svg.removeEventListener('mousemove', active.onMouseMove);\n\n if (active.onMouseLeave) svg.removeEventListener('mouseleave', active.onMouseLeave);\n\n if (active.onClick) svg.removeEventListener('click', active.onClick);\n\n if (active.onKeyDown) svg.removeEventListener('keydown', active.onKeyDown);\n\n active = null;\n }\n\n if (!handlers) return;\n\n active = handlers;\n\n if (handlers.onMouseMove) svg.addEventListener('mousemove', handlers.onMouseMove);\n\n if (handlers.onMouseLeave) svg.addEventListener('mouseleave', handlers.onMouseLeave);\n\n if (handlers.onClick) svg.addEventListener('click', handlers.onClick);\n\n if (handlers.onKeyDown) svg.addEventListener('keydown', handlers.onKeyDown);\n },\n detach() {\n this.attach(undefined);\n },\n };\n}\n\n/**\n * Cartesian scaffold: provides grid/axis/series SVG groups and a render loop.\n * `renderFn` returns optional `ChartEventHandlers` that are attached/replaced\n * after every data update or resize.\n */\nexport function createChartScaffold<TData>(\n container: HTMLElement,\n config: BaseChartConfig,\n renderFn: (ctx: ScaffoldContext, reason: RenderReason) => ChartEventHandlers | undefined,\n updateData: (data: TData) => void,\n): ChartHandle<TData> {\n return runScaffold(\n container,\n config,\n (base, tooltip, legend, disposalSignal, announcer) => {\n const groups: ScaffoldGroups = {\n // Grid lines are purely decorative relative to the root svg's own role=\"img\"/aria-label.\n // Axis groups are NOT hidden wholesale: they can contain a meaningful `.prism-axis-title`;\n // `renderAxis` marks its own decorative tick lines/labels individually instead.\n grid: createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-grid' }),\n series: createSvgElement('g', { class: 'prism-series' }),\n xAxis: createSvgElement('g', { class: 'prism-x-axis' }),\n yAxis: createSvgElement('g', { class: 'prism-y-axis' }),\n };\n\n base.chartArea.appendChild(groups.grid);\n base.chartArea.appendChild(groups.xAxis);\n base.chartArea.appendChild(groups.yAxis);\n base.chartArea.appendChild(groups.series);\n\n return {\n announcer,\n chartArea: base.chartArea,\n container,\n dimensions: base.dimensions,\n disposalSignal,\n groups,\n legend,\n svg: base.svg,\n tooltip,\n } satisfies ScaffoldContext;\n },\n renderFn,\n updateData,\n );\n}\n\n/**\n * Radial scaffold: for charts that do not use cartesian axis groups\n * (pie, donut, semi). Provides only tooltip, legend, and the SVG root.\n */\nexport function createRadialScaffold<TData>(\n container: HTMLElement,\n config: BaseChartConfig,\n renderFn: (ctx: RadialScaffoldContext, reason: RenderReason) => ChartEventHandlers | undefined,\n updateData: (data: TData) => void,\n): ChartHandle<TData> {\n return runScaffold(\n container,\n config,\n (base, tooltip, legend, disposalSignal, announcer) =>\n ({\n announcer,\n container,\n dimensions: base.dimensions,\n disposalSignal,\n legend,\n svg: base.svg,\n tooltip,\n }) satisfies RadialScaffoldContext,\n renderFn,\n updateData,\n );\n}\n"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./scales/linear.cjs"),t=require("./scales/time.cjs"),n=require("./errors.cjs"),r=require("./theme/index.cjs"),i=require("./charts/area/area-chart.cjs"),a=require("./scales/band.cjs"),o=require("./charts/bar/bar-chart.cjs"),s=require("./charts/line/line-chart.cjs"),c=require("./charts/pie/pie-chart.cjs"),l=require("./charts/radar/radar-chart.cjs"),u=require("./charts/sparkline/sparkline.cjs");exports.PrismError=n.PrismError,exports.PrismRenderError=n.PrismRenderError,exports.bandScale=a.bandScale,exports.createAreaChart=i.createAreaChart,exports.createBarChart=o.createBarChart,exports.createLineChart=s.createLineChart,exports.createPieChart=c.createPieChart,exports.createRadarChart=l.createRadarChart,exports.createSparkline=u.createSparkline,exports.linearScale=e.linearScale,exports.resetTheme=r.resetTheme,exports.seriesColor=r.seriesColor,exports.setTheme=r.setTheme,exports.timeScale=t.timeScale;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./scales/linear.cjs"),t=require("./scales/time.cjs"),n=require("./errors.cjs"),r=require("./theme/index.cjs"),i=require("./charts/area/area-chart.cjs"),a=require("./scales/band.cjs"),o=require("./charts/bar/bar-chart.cjs"),s=require("./charts/line/line-chart.cjs"),c=require("./charts/pie/pie-chart.cjs"),l=require("./charts/radar/radar-chart.cjs"),u=require("./charts/scatter/scatter-chart.cjs"),d=require("./charts/sparkline/sparkline.cjs");exports.PrismError=n.PrismError,exports.PrismRenderError=n.PrismRenderError,exports.bandScale=a.bandScale,exports.createAreaChart=i.createAreaChart,exports.createBarChart=o.createBarChart,exports.createLineChart=s.createLineChart,exports.createPieChart=c.createPieChart,exports.createRadarChart=l.createRadarChart,exports.createScatterChart=u.createScatterChart,exports.createSparkline=d.createSparkline,exports.linearScale=e.linearScale,exports.resetTheme=r.resetTheme,exports.seriesColor=r.seriesColor,exports.setTheme=r.setTheme,exports.timeScale=t.timeScale;
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export { createBarChart } from './charts/bar';
4
4
  export { createLineChart } from './charts/line';
5
5
  export { createPieChart } from './charts/pie';
6
6
  export { createRadarChart } from './charts/radar';
7
+ export { createScatterChart } from './charts/scatter';
7
8
  export { createSparkline } from './charts/sparkline';
8
9
  export { PrismError, PrismRenderError } from './errors';
9
10
  export { bandScale } from './scales/band';
@@ -11,5 +12,5 @@ export { linearScale } from './scales/linear';
11
12
  export { timeScale } from './scales/time';
12
13
  export type { BandScaleConfig, LinearScaleConfig, TimeScaleConfig } from './scales/types';
13
14
  export { resetTheme, seriesColor, setTheme } from './theme';
14
- export type { AreaChartConfig, AreaSeriesConfig, AxisConfig, AxisPosition, BandScale, BarChartConfig, BarSeriesConfig, BarVariant, BaseChartConfig, ChartA11y, ChartDimensions, ChartEvent, ChartHandle, ChartMargin, ContinuousDatum, CrosshairConfig, Datum, GridConfig, HorizontalAxisPosition, LegendConfig, LegendPosition, LineChartConfig, LineSeriesConfig, PieChartConfig, PieEvent, PieSliceConfig, PieVariant, PrismEvent, PrismTheme, RadarAxisConfig, RadarAxisValue, RadarChartConfig, RadarEvent, RadarGridConfig, RadarSeriesConfig, Scale, Series, SeriesValue, SparklineConfig, SparklineEvent, SparklineVariant, StackSegment, ThemeScope, TooltipConfig, TransitionConfig, TransitionOption, VerticalAxisPosition, XAxisConfig, YAxisConfig, } from './types';
15
+ export type { AreaChartConfig, AreaSeriesConfig, AxisConfig, AxisPosition, BandScale, BarChartConfig, BarSeriesConfig, BarVariant, BaseChartConfig, ChartA11y, ChartDimensions, ChartEvent, ChartHandle, ChartMargin, ContinuousDatum, CrosshairConfig, Datum, GridConfig, HorizontalAxisPosition, LegendConfig, LegendPosition, LineChartConfig, LineSeriesConfig, PieChartConfig, PieEvent, PieSliceConfig, PieVariant, PrismEvent, PrismTheme, RadarAxisConfig, RadarAxisValue, RadarChartConfig, RadarEvent, RadarGridConfig, RadarSeriesConfig, Scale, ScatterChartConfig, ScatterSeriesConfig, Series, SeriesValue, SparklineConfig, SparklineEvent, SparklineVariant, StackSegment, ThemeScope, TooltipConfig, TransitionConfig, TransitionOption, VerticalAxisPosition, XAxisConfig, YAxisConfig, } from './types';
15
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAE1F,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,SAAS,EACT,cAAc,EACd,eAAe,EACf,UAAU,EACV,eAAe,EACf,SAAS,EACT,eAAe,EACf,UAAU,EACV,WAAW,EACX,WAAW,EACX,eAAe,EACf,eAAe,EACf,KAAK,EACL,UAAU,EACV,sBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,QAAQ,EACR,cAAc,EACd,UAAU,EACV,UAAU,EACV,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,KAAK,EACL,MAAM,EACN,WAAW,EACX,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,WAAW,GACZ,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAE1F,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,SAAS,EACT,cAAc,EACd,eAAe,EACf,UAAU,EACV,eAAe,EACf,SAAS,EACT,eAAe,EACf,UAAU,EACV,WAAW,EACX,WAAW,EACX,eAAe,EACf,eAAe,EACf,KAAK,EACL,UAAU,EACV,sBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,QAAQ,EACR,cAAc,EACd,UAAU,EACV,UAAU,EACV,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,KAAK,EACL,kBAAkB,EAClB,mBAAmB,EACnB,MAAM,EACN,WAAW,EACX,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,WAAW,GACZ,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{linearScale as e}from"./scales/linear.js";import{timeScale as t}from"./scales/time.js";import{PrismError as n,PrismRenderError as r}from"./errors.js";import{resetTheme as i,seriesColor as a,setTheme as o}from"./theme/index.js";import{createAreaChart as s}from"./charts/area/area-chart.js";import{bandScale as c}from"./scales/band.js";import{createBarChart as l}from"./charts/bar/bar-chart.js";import{createLineChart as u}from"./charts/line/line-chart.js";import{createPieChart as d}from"./charts/pie/pie-chart.js";import{createRadarChart as f}from"./charts/radar/radar-chart.js";import{createSparkline as p}from"./charts/sparkline/sparkline.js";export{n as PrismError,r as PrismRenderError,c as bandScale,s as createAreaChart,l as createBarChart,u as createLineChart,d as createPieChart,f as createRadarChart,p as createSparkline,e as linearScale,i as resetTheme,a as seriesColor,o as setTheme,t as timeScale};
1
+ import{linearScale as e}from"./scales/linear.js";import{timeScale as t}from"./scales/time.js";import{PrismError as n,PrismRenderError as r}from"./errors.js";import{resetTheme as i,seriesColor as a,setTheme as o}from"./theme/index.js";import{createAreaChart as s}from"./charts/area/area-chart.js";import{bandScale as c}from"./scales/band.js";import{createBarChart as l}from"./charts/bar/bar-chart.js";import{createLineChart as u}from"./charts/line/line-chart.js";import{createPieChart as d}from"./charts/pie/pie-chart.js";import{createRadarChart as f}from"./charts/radar/radar-chart.js";import{createScatterChart as p}from"./charts/scatter/scatter-chart.js";import{createSparkline as m}from"./charts/sparkline/sparkline.js";export{n as PrismError,r as PrismRenderError,c as bandScale,s as createAreaChart,l as createBarChart,u as createLineChart,d as createPieChart,f as createRadarChart,p as createScatterChart,m as createSparkline,e as linearScale,i as resetTheme,a as seriesColor,o as setTheme,t as timeScale};
@@ -1,2 +1,2 @@
1
- const e=require("../svg/element.cjs");function describeValues(e,t,n=String){return`${e}: ${t.map(({datum:e,series:t})=>`${t.name} ${e?n(e.value):`n/a`}`).join(`, `)}`}function createAnnouncer(t,n){let r=e.createSvgElement(`text`,{"aria-live":`polite`,class:n,role:`status`,x:-9999,y:-9999});return t.appendChild(r),{announce(e){r.textContent=e},clear(){r.textContent=``}}}exports.createAnnouncer=createAnnouncer,exports.describeValues=describeValues;
1
+ const e=require("../svg/element.cjs");function describeValues(e,t,n=String){return`${e}: ${t.map(({datum:e,series:t})=>`${t.name} ${e?n(e.value,e,t):`n/a`}`).join(`, `)}`}function createAnnouncer(t,n){let r=e.createSvgElement(`text`,{"aria-live":`polite`,class:n,role:`status`,x:-9999,y:-9999});return t.appendChild(r),{announce(e){r.textContent=e},clear(){r.textContent=``}}}exports.createAnnouncer=createAnnouncer,exports.describeValues=describeValues;
2
2
  //# sourceMappingURL=announcer.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"announcer.cjs","names":[],"sources":["../../src/interaction/announcer.ts"],"sourcesContent":["import { createSvgElement } from '../svg/element';\nimport type { Datum, Series } from '../types';\n\nexport interface Announcer {\n announce(text: string): void;\n clear(): void;\n}\n\n/** \"Label: A 6, B 9\": the comparison text shared by tooltips and announcements. */\nexport function describeValues(\n label: string,\n values: readonly { datum: Datum | undefined; series: Series }[],\n format: (value: number) => string = String,\n): string {\n return `${label}: ${values.map(({ datum, series }) => `${series.name} ${datum ? format(datum.value) : 'n/a'}`).join(', ')}`;\n}\n\n/** Polite status region for charts whose visuals are aria-hidden. */\nexport function createAnnouncer(parent: SVGElement, className: string): Announcer {\n // Off-canvas rather than CSS-hidden so announcements work without prism's stylesheet.\n const region = createSvgElement('text', {\n 'aria-live': 'polite',\n class: className,\n role: 'status',\n x: -9999,\n y: -9999,\n });\n\n parent.appendChild(region);\n\n return {\n announce(text) {\n region.textContent = text;\n },\n clear() {\n region.textContent = '';\n },\n };\n}\n"],"mappings":"sCASA,SAAgB,eACd,EACA,EACA,EAAoC,OAC5B,CACR,MAAO,GAAG,EAAM,IAAI,EAAO,KAAK,CAAE,QAAO,YAAa,GAAG,EAAO,KAAK,GAAG,EAAQ,EAAO,EAAM,KAAK,EAAI,OAAO,CAAC,CAAC,KAAK,IAAI,GAC1H,CAGA,SAAgB,gBAAgB,EAAoB,EAA8B,CAEhF,IAAM,EAAS,EAAA,iBAAiB,OAAQ,CACtC,YAAa,SACb,MAAO,EACP,KAAM,SACN,EAAG,MACH,EAAG,KACL,CAAC,EAID,OAFA,EAAO,YAAY,CAAM,EAElB,CACL,SAAS,EAAM,CACb,EAAO,YAAc,CACvB,EACA,OAAQ,CACN,EAAO,YAAc,EACvB,CACF,CACF"}
1
+ {"version":3,"file":"announcer.cjs","names":[],"sources":["../../src/interaction/announcer.ts"],"sourcesContent":["import { createSvgElement } from '../svg/element';\nimport type { Datum, Series } from '../types';\n\nexport interface Announcer {\n announce(text: string): void;\n clear(): void;\n}\n\n/** \"Label: A 6, B 9\": the comparison text shared by tooltips and announcements. */\nexport function describeValues(\n label: string,\n values: readonly { datum: Datum | undefined; series: Series }[],\n format: (value: number, datum: Datum, series: Series) => string = String,\n): string {\n return `${label}: ${values\n .map(({ datum, series }) => `${series.name} ${datum ? format(datum.value, datum, series) : 'n/a'}`)\n .join(', ')}`;\n}\n\n/** Polite status region for charts whose visuals are aria-hidden. */\nexport function createAnnouncer(parent: SVGElement, className: string): Announcer {\n // Off-canvas rather than CSS-hidden so announcements work without prism's stylesheet.\n const region = createSvgElement('text', {\n 'aria-live': 'polite',\n class: className,\n role: 'status',\n x: -9999,\n y: -9999,\n });\n\n parent.appendChild(region);\n\n return {\n announce(text) {\n region.textContent = text;\n },\n clear() {\n region.textContent = '';\n },\n };\n}\n"],"mappings":"sCASA,SAAgB,eACd,EACA,EACA,EAAkE,OAC1D,CACR,MAAO,GAAG,EAAM,IAAI,EACjB,KAAK,CAAE,QAAO,YAAa,GAAG,EAAO,KAAK,GAAG,EAAQ,EAAO,EAAM,MAAO,EAAO,CAAM,EAAI,OAAO,CAAC,CAClG,KAAK,IAAI,GACd,CAGA,SAAgB,gBAAgB,EAAoB,EAA8B,CAEhF,IAAM,EAAS,EAAA,iBAAiB,OAAQ,CACtC,YAAa,SACb,MAAO,EACP,KAAM,SACN,EAAG,MACH,EAAG,KACL,CAAC,EAID,OAFA,EAAO,YAAY,CAAM,EAElB,CACL,SAAS,EAAM,CACb,EAAO,YAAc,CACvB,EACA,OAAQ,CACN,EAAO,YAAc,EACvB,CACF,CACF"}
@@ -7,7 +7,7 @@ export interface Announcer {
7
7
  export declare function describeValues(label: string, values: readonly {
8
8
  datum: Datum | undefined;
9
9
  series: Series;
10
- }[], format?: (value: number) => string): string;
10
+ }[], format?: (value: number, datum: Datum, series: Series) => string): string;
11
11
  /** Polite status region for charts whose visuals are aria-hidden. */
12
12
  export declare function createAnnouncer(parent: SVGElement, className: string): Announcer;
13
13
  //# sourceMappingURL=announcer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"announcer.d.ts","sourceRoot":"","sources":["../../src/interaction/announcer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;CACf;AAED,mFAAmF;AACnF,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS;IAAE,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,EAC/D,MAAM,GAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAe,GACzC,MAAM,CAER;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,CAoBhF"}
1
+ {"version":3,"file":"announcer.d.ts","sourceRoot":"","sources":["../../src/interaction/announcer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;CACf;AAED,mFAAmF;AACnF,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS;IAAE,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,EAC/D,MAAM,GAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,KAAK,MAAe,GACvE,MAAM,CAIR;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,CAoBhF"}
@@ -1,2 +1,2 @@
1
- import{createSvgElement as e}from"../svg/element.js";function describeValues(e,t,n=String){return`${e}: ${t.map(({datum:e,series:t})=>`${t.name} ${e?n(e.value):`n/a`}`).join(`, `)}`}function createAnnouncer(t,n){let r=e(`text`,{"aria-live":`polite`,class:n,role:`status`,x:-9999,y:-9999});return t.appendChild(r),{announce(e){r.textContent=e},clear(){r.textContent=``}}}export{createAnnouncer,describeValues};
1
+ import{createSvgElement as e}from"../svg/element.js";function describeValues(e,t,n=String){return`${e}: ${t.map(({datum:e,series:t})=>`${t.name} ${e?n(e.value,e,t):`n/a`}`).join(`, `)}`}function createAnnouncer(t,n){let r=e(`text`,{"aria-live":`polite`,class:n,role:`status`,x:-9999,y:-9999});return t.appendChild(r),{announce(e){r.textContent=e},clear(){r.textContent=``}}}export{createAnnouncer,describeValues};
2
2
  //# sourceMappingURL=announcer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"announcer.js","names":[],"sources":["../../src/interaction/announcer.ts"],"sourcesContent":["import { createSvgElement } from '../svg/element';\nimport type { Datum, Series } from '../types';\n\nexport interface Announcer {\n announce(text: string): void;\n clear(): void;\n}\n\n/** \"Label: A 6, B 9\": the comparison text shared by tooltips and announcements. */\nexport function describeValues(\n label: string,\n values: readonly { datum: Datum | undefined; series: Series }[],\n format: (value: number) => string = String,\n): string {\n return `${label}: ${values.map(({ datum, series }) => `${series.name} ${datum ? format(datum.value) : 'n/a'}`).join(', ')}`;\n}\n\n/** Polite status region for charts whose visuals are aria-hidden. */\nexport function createAnnouncer(parent: SVGElement, className: string): Announcer {\n // Off-canvas rather than CSS-hidden so announcements work without prism's stylesheet.\n const region = createSvgElement('text', {\n 'aria-live': 'polite',\n class: className,\n role: 'status',\n x: -9999,\n y: -9999,\n });\n\n parent.appendChild(region);\n\n return {\n announce(text) {\n region.textContent = text;\n },\n clear() {\n region.textContent = '';\n },\n };\n}\n"],"mappings":"qDASA,SAAgB,eACd,EACA,EACA,EAAoC,OAC5B,CACR,MAAO,GAAG,EAAM,IAAI,EAAO,KAAK,CAAE,QAAO,YAAa,GAAG,EAAO,KAAK,GAAG,EAAQ,EAAO,EAAM,KAAK,EAAI,OAAO,CAAC,CAAC,KAAK,IAAI,GAC1H,CAGA,SAAgB,gBAAgB,EAAoB,EAA8B,CAEhF,IAAM,EAAS,EAAiB,OAAQ,CACtC,YAAa,SACb,MAAO,EACP,KAAM,SACN,EAAG,MACH,EAAG,KACL,CAAC,EAID,OAFA,EAAO,YAAY,CAAM,EAElB,CACL,SAAS,EAAM,CACb,EAAO,YAAc,CACvB,EACA,OAAQ,CACN,EAAO,YAAc,EACvB,CACF,CACF"}
1
+ {"version":3,"file":"announcer.js","names":[],"sources":["../../src/interaction/announcer.ts"],"sourcesContent":["import { createSvgElement } from '../svg/element';\nimport type { Datum, Series } from '../types';\n\nexport interface Announcer {\n announce(text: string): void;\n clear(): void;\n}\n\n/** \"Label: A 6, B 9\": the comparison text shared by tooltips and announcements. */\nexport function describeValues(\n label: string,\n values: readonly { datum: Datum | undefined; series: Series }[],\n format: (value: number, datum: Datum, series: Series) => string = String,\n): string {\n return `${label}: ${values\n .map(({ datum, series }) => `${series.name} ${datum ? format(datum.value, datum, series) : 'n/a'}`)\n .join(', ')}`;\n}\n\n/** Polite status region for charts whose visuals are aria-hidden. */\nexport function createAnnouncer(parent: SVGElement, className: string): Announcer {\n // Off-canvas rather than CSS-hidden so announcements work without prism's stylesheet.\n const region = createSvgElement('text', {\n 'aria-live': 'polite',\n class: className,\n role: 'status',\n x: -9999,\n y: -9999,\n });\n\n parent.appendChild(region);\n\n return {\n announce(text) {\n region.textContent = text;\n },\n clear() {\n region.textContent = '';\n },\n };\n}\n"],"mappings":"qDASA,SAAgB,eACd,EACA,EACA,EAAkE,OAC1D,CACR,MAAO,GAAG,EAAM,IAAI,EACjB,KAAK,CAAE,QAAO,YAAa,GAAG,EAAO,KAAK,GAAG,EAAQ,EAAO,EAAM,MAAO,EAAO,CAAM,EAAI,OAAO,CAAC,CAClG,KAAK,IAAI,GACd,CAGA,SAAgB,gBAAgB,EAAoB,EAA8B,CAEhF,IAAM,EAAS,EAAiB,OAAQ,CACtC,YAAa,SACb,MAAO,EACP,KAAM,SACN,EAAG,MACH,EAAG,KACL,CAAC,EAID,OAFA,EAAO,YAAY,CAAM,EAElB,CACL,SAAS,EAAM,CACb,EAAO,YAAc,CACvB,EACA,OAAQ,CACN,EAAO,YAAc,EACvB,CACF,CACF"}
@@ -1,2 +1,2 @@
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;
1
+ function resolvePosition(e){return e===!0?`bottom`:e.position??`bottom`}function createLegend(e,t,n){let r=resolvePosition(t),i=document.createElement(`div`);i.className=`prism-legend prism-legend-${r}`,r===`top`?e.insertBefore(i,e.firstChild):e.appendChild(i);let disposeHandle=()=>{i.remove()};return{dispose:disposeHandle,el:i,[Symbol.dispose]:disposeHandle,update(e){i.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 r=document.createElement(`span`);r.className=`prism-legend-label`,r.textContent=t.name,e.appendChild(n),e.appendChild(r),i.appendChild(e)}n?.()}}}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.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
+ {"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, onLayout?: () => void): 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 onLayout?.();\n },\n };\n}\n"],"mappings":"AASA,SAAS,gBAAgB,EAA6C,CAGpE,OAFI,IAAW,GAAa,SAErB,EAAO,UAAY,QAC5B,CAEA,SAAgB,aAAa,EAAwB,EAA6B,EAAoC,CACpH,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,CACA,IAAW,CACb,CACF,CACF"}
@@ -8,5 +8,5 @@ export interface LegendState {
8
8
  }[]): void;
9
9
  [Symbol.dispose](): void;
10
10
  }
11
- export declare function createLegend(container: HTMLElement, config: LegendConfig | true): LegendState;
11
+ export declare function createLegend(container: HTMLElement, config: LegendConfig | true, onLayout?: () => void): LegendState;
12
12
  //# sourceMappingURL=legend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"legend.d.ts","sourceRoot":"","sources":["../../src/interaction/legend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,UAAU,CAAC;AAE7D,MAAM,WAAW,WAAW;IAC1B,OAAO,IAAI,IAAI,CAAC;IAChB,EAAE,EAAE,cAAc,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,IAAI,CAAC;IACxD,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B;AAQD,wBAAgB,YAAY,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,WAAW,CA2C7F"}
1
+ {"version":3,"file":"legend.d.ts","sourceRoot":"","sources":["../../src/interaction/legend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,UAAU,CAAC;AAE7D,MAAM,WAAW,WAAW;IAC1B,OAAO,IAAI,IAAI,CAAC;IAChB,EAAE,EAAE,cAAc,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,IAAI,CAAC;IACxD,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B;AAQD,wBAAgB,YAAY,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,WAAW,CA4CpH"}
@@ -1,2 +1,2 @@
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};
1
+ function resolvePosition(e){return e===!0?`bottom`:e.position??`bottom`}function createLegend(e,t,n){let r=resolvePosition(t),i=document.createElement(`div`);i.className=`prism-legend prism-legend-${r}`,r===`top`?e.insertBefore(i,e.firstChild):e.appendChild(i);let disposeHandle=()=>{i.remove()};return{dispose:disposeHandle,el:i,[Symbol.dispose]:disposeHandle,update(e){i.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 r=document.createElement(`span`);r.className=`prism-legend-label`,r.textContent=t.name,e.appendChild(n),e.appendChild(r),i.appendChild(e)}n?.()}}}export{createLegend};
2
2
  //# sourceMappingURL=legend.js.map