@vielzeug/prism 26.10.2 → 26.10.3

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 (89) hide show
  1. package/dist/_dev.cjs.map +1 -1
  2. package/dist/_dev.js.map +1 -1
  3. package/dist/_tappers.cjs +2 -0
  4. package/dist/_tappers.cjs.map +1 -0
  5. package/dist/_tappers.d.ts +10 -0
  6. package/dist/_tappers.d.ts.map +1 -0
  7. package/dist/_tappers.js +2 -0
  8. package/dist/_tappers.js.map +1 -0
  9. package/dist/animation/transition.cjs +1 -1
  10. package/dist/animation/transition.cjs.map +1 -1
  11. package/dist/animation/transition.d.ts +32 -3
  12. package/dist/animation/transition.d.ts.map +1 -1
  13. package/dist/animation/transition.js +1 -1
  14. package/dist/animation/transition.js.map +1 -1
  15. package/dist/charts/area/area-chart.cjs +1 -1
  16. package/dist/charts/area/area-chart.cjs.map +1 -1
  17. package/dist/charts/area/area-chart.d.ts.map +1 -1
  18. package/dist/charts/area/area-chart.js +1 -1
  19. package/dist/charts/area/area-chart.js.map +1 -1
  20. package/dist/charts/area/area-renderer.cjs +1 -1
  21. package/dist/charts/area/area-renderer.cjs.map +1 -1
  22. package/dist/charts/area/area-renderer.d.ts.map +1 -1
  23. package/dist/charts/area/area-renderer.js +1 -1
  24. package/dist/charts/area/area-renderer.js.map +1 -1
  25. package/dist/charts/line/line-chart.cjs +1 -1
  26. package/dist/charts/line/line-chart.cjs.map +1 -1
  27. package/dist/charts/line/line-chart.d.ts.map +1 -1
  28. package/dist/charts/line/line-chart.js +1 -1
  29. package/dist/charts/line/line-chart.js.map +1 -1
  30. package/dist/charts/line/line-renderer.cjs +1 -1
  31. package/dist/charts/line/line-renderer.cjs.map +1 -1
  32. package/dist/charts/line/line-renderer.d.ts.map +1 -1
  33. package/dist/charts/line/line-renderer.js +1 -1
  34. package/dist/charts/line/line-renderer.js.map +1 -1
  35. package/dist/charts/pie/pie-chart.cjs +1 -1
  36. package/dist/charts/pie/pie-chart.cjs.map +1 -1
  37. package/dist/charts/pie/pie-chart.d.ts.map +1 -1
  38. package/dist/charts/pie/pie-chart.js +1 -1
  39. package/dist/charts/pie/pie-chart.js.map +1 -1
  40. package/dist/charts/radar/radar-chart.cjs +1 -1
  41. package/dist/charts/radar/radar-chart.cjs.map +1 -1
  42. package/dist/charts/radar/radar-chart.d.ts.map +1 -1
  43. package/dist/charts/radar/radar-chart.js +1 -1
  44. package/dist/charts/radar/radar-chart.js.map +1 -1
  45. package/dist/charts/sparkline/sparkline.cjs +1 -1
  46. package/dist/charts/sparkline/sparkline.cjs.map +1 -1
  47. package/dist/charts/sparkline/sparkline.d.ts.map +1 -1
  48. package/dist/charts/sparkline/sparkline.js +1 -1
  49. package/dist/charts/sparkline/sparkline.js.map +1 -1
  50. package/dist/core/chart-scaffold.cjs +1 -1
  51. package/dist/core/chart-scaffold.cjs.map +1 -1
  52. package/dist/core/chart-scaffold.d.ts.map +1 -1
  53. package/dist/core/chart-scaffold.js +1 -1
  54. package/dist/core/chart-scaffold.js.map +1 -1
  55. package/dist/index.d.ts +1 -1
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/interaction/series-interaction.cjs +1 -1
  58. package/dist/interaction/series-interaction.cjs.map +1 -1
  59. package/dist/interaction/series-interaction.d.ts +3 -1
  60. package/dist/interaction/series-interaction.d.ts.map +1 -1
  61. package/dist/interaction/series-interaction.js +1 -1
  62. package/dist/interaction/series-interaction.js.map +1 -1
  63. package/dist/prism.cjs +1 -1
  64. package/dist/prism.cjs.map +1 -1
  65. package/dist/prism.iife.js +1 -1
  66. package/dist/prism.iife.js.map +1 -1
  67. package/dist/prism.js +1 -1
  68. package/dist/prism.js.map +1 -1
  69. package/dist/types.d.ts +37 -4
  70. package/dist/types.d.ts.map +1 -1
  71. package/package.json +2 -14
  72. package/dist/animation/index.d.ts +0 -6
  73. package/dist/animation/index.d.ts.map +0 -1
  74. package/dist/axes/index.d.ts +0 -3
  75. package/dist/axes/index.d.ts.map +0 -1
  76. package/dist/core/index.d.ts +0 -7
  77. package/dist/core/index.d.ts.map +0 -1
  78. package/dist/devtools/index.d.ts +0 -52
  79. package/dist/devtools/index.d.ts.map +0 -1
  80. package/dist/devtools.cjs +0 -2
  81. package/dist/devtools.cjs.map +0 -1
  82. package/dist/devtools.js +0 -2
  83. package/dist/devtools.js.map +0 -1
  84. package/dist/interaction/index.d.ts +0 -8
  85. package/dist/interaction/index.d.ts.map +0 -1
  86. package/dist/scales/index.d.ts +0 -4
  87. package/dist/scales/index.d.ts.map +0 -1
  88. package/dist/svg/index.d.ts +0 -5
  89. package/dist/svg/index.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"line-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/line/line-chart.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGlF,wBAAgB,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,GAAG,WAAW,CAAC,gBAAgB,EAAE,CAAC,CAoJhH"}
1
+ {"version":3,"file":"line-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/line/line-chart.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGlF,wBAAgB,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,GAAG,WAAW,CAAC,gBAAgB,EAAE,CAAC,CA2JhH"}
@@ -1,2 +1,2 @@
1
- import{createSvgElement as e}from"../../svg/element.js";import{positionAxis as t,renderAxis as n,resolveTickCount as r}from"../../axes/axis.js";import{renderGrid as i}from"../../axes/grid.js";import{buildXScale as a,buildYScale as o}from"../../core/cartesian-scales.js";import{chartArea as s,resolveMargin as c}from"../../core/layout.js";import{clearCartesianDom as l,createChartScaffold as u}from"../../core/chart-scaffold.js";import{seriesDomId as d}from"../../core/series-id.js";import{createCrosshair as f}from"../../interaction/crosshair.js";import{createSeriesInteraction as p,ensureMarkerGroup as m}from"../../interaction/series-interaction.js";import{seriesColor as h}from"../../theme/index.js";import{computePoints as g,renderLine as _}from"./line-renderer.js";function createLineChart(v,y){let b=null,x=null,S=null,C=y.series;return u(v,y,u=>{let{groups:v,legend:w,tooltip:T}=u,E=u.dimensions,D=C.some(e=>e.yAxis===`right`),O=C.some(e=>e.yAxis!==`right`&&e.data.length>0);E.margin.right=y.margin?.right??(D?y.rightYAxis?.label?72:50:c(y.margin).right);let k=s(E.width,E.height,E.margin),A=C.map(e=>e.data),j=A.flat().map(e=>e.key),M=C.filter(e=>e.yAxis!==`right`).flatMap(e=>e.data.map(e=>e.value)),N=C.filter(e=>e.yAxis===`right`).flatMap(e=>e.data.map(e=>e.value));if(j.length===0){l(v,w,T,b),x?.replaceChildren(),S?.replaceChildren();return}y.crosshair&&!b&&(b=f(u.chartArea,y.crosshair));let P=a(j,k.width),F=o(M,k.height),I=o(N,k.height);if(y.yAxis?.grid&&(!D||O)?i(v.grid,F,y.yAxis.grid,k.width,`horizontal`,r(y.yAxis,k.height,`left`)):v.grid.replaceChildren(),y.xAxis?.grid&&i(v.grid,P,y.xAxis.grid,k.height,`vertical`,r(y.xAxis,k.width,`bottom`)),y.xAxis&&(t(v.xAxis,y.xAxis.position??`bottom`,k.width,k.height),n(v.xAxis,P,y.xAxis,k.width,`bottom`)),y.yAxis&&(!D||O)){let e={...y.yAxis,position:D?`left`:y.yAxis.position??`left`};t(v.yAxis,e.position,k.width,k.height),n(v.yAxis,F,e,k.height,`left`)}else v.yAxis.replaceChildren();if(D){S||(S=e(`g`,{class:`prism-y-axis-right`}),u.chartArea.appendChild(S));let r={...y.rightYAxis,position:`right`};t(S,`right`,k.width,k.height),n(S,I,r,k.height,`right`)}else S?.replaceChildren();for(;v.series.children.length>C.length;)v.series.removeChild(v.series.lastChild);let L=[];for(let t=0;t<C.length;t++){let n=C[t],r=v.series.children[t];r||(r=e(`g`,{class:`prism-line-series`}),v.series.appendChild(r)),r.setAttribute(`data-series-id`,d(n,t));let i=g(A[t],P,n.yAxis===`right`?I:F);L.push(i),_(r,i,{color:h(t,n.color),curve:n.curve??`linear`,disposalSignal:u.disposalSignal,marks:n.data,pointRadius:n.pointRadius??3,showPoints:n.showPoints??!1,strokeWidth:n.strokeWidth,transition:y.transition})}return w?.update(C.map((e,t)=>({color:h(t,e.color),name:e.name}))),T?.hide(),x=m(u.chartArea,x),p({announcer:u.announcer,colors:()=>C.map((e,t)=>h(t,e.color)),crosshair:b,dims:()=>u.dimensions,getData:()=>A,getPoints:()=>L,getSeriesList:()=>C,markers:x,onClick:y.onClick,onHover:y.onHover,seriesGroup:v.series,svg:u.svg,tooltip:T})},e=>{C=e})}export{createLineChart};
1
+ import{createSvgElement as e}from"../../svg/element.js";import{positionAxis as t,renderAxis as n,resolveTickCount as r}from"../../axes/axis.js";import{renderGrid as i}from"../../axes/grid.js";import{buildXScale as a,buildYScale as o}from"../../core/cartesian-scales.js";import{chartArea as s,resolveMargin as c}from"../../core/layout.js";import{clearCartesianDom as l,createChartScaffold as u}from"../../core/chart-scaffold.js";import{seriesDomId as d}from"../../core/series-id.js";import{createCrosshair as f}from"../../interaction/crosshair.js";import{createSeriesInteraction as p,ensureMarkerGroup as m}from"../../interaction/series-interaction.js";import{seriesColor as h}from"../../theme/index.js";import{computePoints as g,renderLine as _}from"./line-renderer.js";function createLineChart(v,y){let b=null,x=null,S=null,C=y.series;return u(v,y,u=>{let{groups:v,legend:w,tooltip:T}=u,E=u.dimensions,D=C.some(e=>e.yAxis===`right`),O=C.some(e=>e.yAxis!==`right`&&e.data.length>0),k={...c(y.margin),right:y.margin?.right??(D?y.rightYAxis?.label?72:50:c(y.margin).right)},A=s(E.width,E.height,k),j=C.map(e=>e.data),M=j.flat().map(e=>e.key),N=C.filter(e=>e.yAxis!==`right`).flatMap(e=>e.data.map(e=>e.value)),P=C.filter(e=>e.yAxis===`right`).flatMap(e=>e.data.map(e=>e.value));if(M.length===0){l(v,w,T,b),x?.replaceChildren(),S?.replaceChildren();return}y.crosshair&&!b&&(b=f(u.chartArea,y.crosshair));let F=a(M,A.width),I=o(N,A.height),L=o(P,A.height);if(y.yAxis?.grid&&(!D||O)?i(v.grid,I,y.yAxis.grid,A.width,`horizontal`,r(y.yAxis,A.height,`left`)):v.grid.replaceChildren(),y.xAxis?.grid&&i(v.grid,F,y.xAxis.grid,A.height,`vertical`,r(y.xAxis,A.width,`bottom`)),y.xAxis&&(t(v.xAxis,y.xAxis.position??`bottom`,A.width,A.height),n(v.xAxis,F,y.xAxis,A.width,`bottom`)),y.yAxis&&(!D||O)){let e={...y.yAxis,position:D?`left`:y.yAxis.position??`left`};t(v.yAxis,e.position,A.width,A.height),n(v.yAxis,I,e,A.height,`left`)}else v.yAxis.replaceChildren();if(D){S||(S=e(`g`,{class:`prism-y-axis-right`}),u.chartArea.appendChild(S));let r={...y.rightYAxis,position:`right`};t(S,`right`,A.width,A.height),n(S,L,r,A.height,`right`)}else S?.replaceChildren();for(;v.series.children.length>C.length;)v.series.removeChild(v.series.lastChild);let R=[];for(let t=0;t<C.length;t++){let n=C[t],r=v.series.children[t];r||(r=e(`g`,{class:`prism-line-series`}),v.series.appendChild(r)),r.setAttribute(`data-series-id`,d(n,t));let i=g(j[t],F,n.yAxis===`right`?L:I);R.push(i),_(r,i,{color:h(t,n.color),curve:n.curve??`linear`,disposalSignal:u.disposalSignal,marks:n.data,pointRadius:n.pointRadius??3,showPoints:n.showPoints??!1,strokeWidth:n.strokeWidth,transition:y.transition})}return w?.update(C.map((e,t)=>({color:h(t,e.color),name:e.name}))),T?.hide(),x=m(u.chartArea,x),p({announcer:u.announcer,colors:()=>C.map((e,t)=>h(t,e.color)),crosshair:b,dims:()=>u.dimensions,getData:()=>j,getPoints:()=>R,getSeriesList:()=>C,margin:k,markers:x,onClick:y.onClick,onHover:y.onHover,seriesGroup:v.series,svg:u.svg,tooltip:T})},e=>{C=e})}export{createLineChart};
2
2
  //# sourceMappingURL=line-chart.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"line-chart.js","names":[],"sources":["../../../src/charts/line/line-chart.ts"],"sourcesContent":["import { positionAxis, renderAxis, resolveTickCount } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { buildXScale, buildYScale } from '../../core/cartesian-scales';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea, resolveMargin } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createSeriesInteraction, ensureMarkerGroup } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, LineChartConfig, LineSeriesConfig } from '../../types';\nimport { computePoints, renderLine } from './line-renderer';\n\nexport function createLineChart(container: HTMLElement, config: LineChartConfig): ChartHandle<LineSeriesConfig[]> {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n let markers: SVGGElement | null = null;\n let rightAxis: SVGGElement | null = null;\n let seriesList = config.series;\n\n return createChartScaffold(\n container,\n config,\n (ctx) => {\n const { groups, legend, tooltip } = ctx;\n const dims = ctx.dimensions;\n const hasRight = seriesList.some((series) => series.yAxis === 'right');\n const hasLeftData = seriesList.some((series) => series.yAxis !== 'right' && series.data.length > 0);\n dims.margin.right =\n config.margin?.right ?? (hasRight ? (config.rightYAxis?.label ? 72 : 50) : resolveMargin(config.margin).right);\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 leftY = seriesList\n .filter((series) => series.yAxis !== 'right')\n .flatMap((series) => series.data.map((datum) => datum.value));\n const rightY = seriesList\n .filter((series) => series.yAxis === 'right')\n .flatMap((series) => series.data.map((datum) => datum.value));\n\n if (allX.length === 0) {\n clearCartesianDom(groups, legend, tooltip, crosshair);\n markers?.replaceChildren();\n rightAxis?.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 const yScale = buildYScale(leftY, area.height);\n const rightYScale = buildYScale(rightY, area.height);\n\n if (config.yAxis?.grid && (!hasRight || hasLeftData)) {\n renderGrid(\n groups.grid,\n yScale,\n config.yAxis.grid,\n area.width,\n 'horizontal',\n resolveTickCount(config.yAxis, area.height, 'left'),\n );\n } else {\n groups.grid.replaceChildren();\n }\n\n if (config.xAxis?.grid) {\n renderGrid(\n groups.grid,\n xScale,\n config.xAxis.grid,\n area.height,\n 'vertical',\n resolveTickCount(config.xAxis, area.width, 'bottom'),\n );\n }\n\n if (config.xAxis) {\n positionAxis(groups.xAxis, config.xAxis.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, xScale, config.xAxis, area.width, 'bottom');\n }\n\n if (config.yAxis && (!hasRight || hasLeftData)) {\n const axis = { ...config.yAxis, position: hasRight ? ('left' as const) : (config.yAxis.position ?? 'left') };\n positionAxis(groups.yAxis, axis.position, area.width, area.height);\n renderAxis(groups.yAxis, yScale, axis, area.height, 'left');\n } else {\n groups.yAxis.replaceChildren();\n }\n\n if (hasRight) {\n if (!rightAxis) {\n rightAxis = createSvgElement('g', { class: 'prism-y-axis-right' });\n ctx.chartArea.appendChild(rightAxis);\n }\n const axis = { ...config.rightYAxis, position: 'right' as const };\n positionAxis(rightAxis, 'right', area.width, area.height);\n renderAxis(rightAxis, rightYScale, axis, area.height, 'right');\n } else {\n rightAxis?.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 (let i = 0; i < seriesList.length; i++) {\n const series = seriesList[i];\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-line-series' });\n groups.series.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const points = computePoints(allData[i], xScale, series.yAxis === 'right' ? rightYScale : yScale);\n\n allPoints.push(points);\n\n renderLine(group, points, {\n color: seriesColor(i, series.color),\n curve: series.curve ?? 'linear',\n disposalSignal: ctx.disposalSignal,\n marks: series.data,\n pointRadius: series.pointRadius ?? 3,\n showPoints: series.showPoints ?? false,\n strokeWidth: series.strokeWidth,\n transition: config.transition,\n });\n }\n\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n tooltip?.hide();\n markers = ensureMarkerGroup(ctx.chartArea, markers);\n\n return createSeriesInteraction({\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 markers,\n onClick: config.onClick,\n onHover: config.onHover,\n seriesGroup: groups.series,\n svg: ctx.svg,\n tooltip,\n });\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"kwBAcA,SAAgB,gBAAgB,EAAwB,EAA0D,CAChH,IAAI,EAAuD,KACvD,EAA8B,KAC9B,EAAgC,KAChC,EAAa,EAAO,OAExB,OAAO,EACL,EACA,EACC,GAAQ,CACP,GAAM,CAAE,SAAQ,SAAQ,WAAY,EAC9B,EAAO,EAAI,WACX,EAAW,EAAW,KAAM,GAAW,EAAO,QAAU,OAAO,EAC/D,EAAc,EAAW,KAAM,GAAW,EAAO,QAAU,SAAW,EAAO,KAAK,OAAS,CAAC,EAClG,EAAK,OAAO,MACV,EAAO,QAAQ,QAAU,EAAY,EAAO,YAAY,MAAQ,GAAK,GAAM,EAAc,EAAO,MAAM,CAAC,CAAC,OAC1G,IAAM,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,EAAQ,EACX,OAAQ,GAAW,EAAO,QAAU,OAAO,CAAC,CAC5C,QAAS,GAAW,EAAO,KAAK,IAAK,GAAU,EAAM,KAAK,CAAC,EACxD,EAAS,EACZ,OAAQ,GAAW,EAAO,QAAU,OAAO,CAAC,CAC5C,QAAS,GAAW,EAAO,KAAK,IAAK,GAAU,EAAM,KAAK,CAAC,EAE9D,GAAI,EAAK,SAAW,EAAG,CACrB,EAAkB,EAAQ,EAAQ,EAAS,CAAS,EACpD,GAAS,gBAAgB,EACzB,GAAW,gBAAgB,EAE3B,MACF,CAEI,EAAO,WAAa,CAAC,IACvB,EAAY,EAAgB,EAAI,UAAW,EAAO,SAAS,GAG7D,IAAM,EAAS,EAAY,EAAM,EAAK,KAAK,EACrC,EAAS,EAAY,EAAO,EAAK,MAAM,EACvC,EAAc,EAAY,EAAQ,EAAK,MAAM,EA+BnD,GA7BI,EAAO,OAAO,OAAS,CAAC,GAAY,GACtC,EACE,EAAO,KACP,EACA,EAAO,MAAM,KACb,EAAK,MACL,aACA,EAAiB,EAAO,MAAO,EAAK,OAAQ,MAAM,CACpD,EAEA,EAAO,KAAK,gBAAgB,EAG1B,EAAO,OAAO,MAChB,EACE,EAAO,KACP,EACA,EAAO,MAAM,KACb,EAAK,OACL,WACA,EAAiB,EAAO,MAAO,EAAK,MAAO,QAAQ,CACrD,EAGE,EAAO,QACT,EAAa,EAAO,MAAO,EAAO,MAAM,UAAY,SAAU,EAAK,MAAO,EAAK,MAAM,EACrF,EAAW,EAAO,MAAO,EAAQ,EAAO,MAAO,EAAK,MAAO,QAAQ,GAGjE,EAAO,QAAU,CAAC,GAAY,GAAc,CAC9C,IAAM,EAAO,CAAE,GAAG,EAAO,MAAO,SAAU,EAAY,OAAoB,EAAO,MAAM,UAAY,MAAQ,EAC3G,EAAa,EAAO,MAAO,EAAK,SAAU,EAAK,MAAO,EAAK,MAAM,EACjE,EAAW,EAAO,MAAO,EAAQ,EAAM,EAAK,OAAQ,MAAM,CAC5D,MACE,EAAO,MAAM,gBAAgB,EAG/B,GAAI,EAAU,CACP,IACH,EAAY,EAAiB,IAAK,CAAE,MAAO,oBAAqB,CAAC,EACjE,EAAI,UAAU,YAAY,CAAS,GAErC,IAAM,EAAO,CAAE,GAAG,EAAO,WAAY,SAAU,OAAiB,EAChE,EAAa,EAAW,QAAS,EAAK,MAAO,EAAK,MAAM,EACxD,EAAW,EAAW,EAAa,EAAM,EAAK,OAAQ,OAAO,CAC/D,MACE,GAAW,gBAAgB,EAG7B,KAAO,EAAO,OAAO,SAAS,OAAS,EAAW,QAChD,EAAO,OAAO,YAAY,EAAO,OAAO,SAAU,EAGpD,IAAM,EAAuB,CAAC,EAE9B,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,OAAQ,IAAK,CAC1C,IAAM,EAAS,EAAW,GACtB,EAAQ,EAAO,OAAO,SAAS,GAE9B,IACH,EAAQ,EAAiB,IAAK,CAAE,MAAO,mBAAoB,CAAC,EAC5D,EAAO,OAAO,YAAY,CAAK,GAGjC,EAAM,aAAa,iBAAkB,EAAY,EAAQ,CAAC,CAAC,EAE3D,IAAM,EAAS,EAAc,EAAQ,GAAI,EAAQ,EAAO,QAAU,QAAU,EAAc,CAAM,EAEhG,EAAU,KAAK,CAAM,EAErB,EAAW,EAAO,EAAQ,CACxB,MAAO,EAAY,EAAG,EAAO,KAAK,EAClC,MAAO,EAAO,OAAS,SACvB,eAAgB,EAAI,eACpB,MAAO,EAAO,KACd,YAAa,EAAO,aAAe,EACnC,WAAY,EAAO,YAAc,GACjC,YAAa,EAAO,YACpB,WAAY,EAAO,UACrB,CAAC,CACH,CAMA,OAJA,GAAQ,OAAO,EAAW,KAAK,EAAG,KAAO,CAAE,MAAO,EAAY,EAAG,EAAE,KAAK,EAAG,KAAM,EAAE,IAAK,EAAE,CAAC,EAC3F,GAAS,KAAK,EACd,EAAU,EAAkB,EAAI,UAAW,CAAO,EAE3C,EAAwB,CAC7B,UAAW,EAAI,UACf,WAAc,EAAW,KAAK,EAAG,IAAM,EAAY,EAAG,EAAE,KAAK,CAAC,EAC9D,YACA,SAAY,EAAI,WAChB,YAAe,EACf,cAAiB,EACjB,kBAAqB,EACrB,UACA,QAAS,EAAO,QAChB,QAAS,EAAO,QAChB,YAAa,EAAO,OACpB,IAAK,EAAI,IACT,SACF,CAAC,CACH,EACC,GAAS,CACR,EAAa,CACf,CACF,CACF"}
1
+ {"version":3,"file":"line-chart.js","names":[],"sources":["../../../src/charts/line/line-chart.ts"],"sourcesContent":["import { positionAxis, renderAxis, resolveTickCount } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { buildXScale, buildYScale } from '../../core/cartesian-scales';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea, resolveMargin } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createSeriesInteraction, ensureMarkerGroup } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, LineChartConfig, LineSeriesConfig } from '../../types';\nimport { computePoints, renderLine } from './line-renderer';\n\nexport function createLineChart(container: HTMLElement, config: LineChartConfig): ChartHandle<LineSeriesConfig[]> {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n let markers: SVGGElement | null = null;\n let rightAxis: SVGGElement | null = null;\n let seriesList = config.series;\n\n return createChartScaffold(\n container,\n config,\n (ctx) => {\n const { groups, legend, tooltip } = ctx;\n const dims = ctx.dimensions;\n const hasRight = seriesList.some((series) => series.yAxis === 'right');\n const hasLeftData = seriesList.some((series) => series.yAxis !== 'right' && series.data.length > 0);\n // The right axis widens the right margin; the effective margin stays local to this\n // render pass (and is handed to the interaction layer) instead of mutating shared dims.\n const margin = {\n ...resolveMargin(config.margin),\n right:\n config.margin?.right ??\n (hasRight ? (config.rightYAxis?.label ? 72 : 50) : resolveMargin(config.margin).right),\n };\n const area = chartArea(dims.width, dims.height, margin);\n const allData = seriesList.map((series) => series.data);\n const allX = allData.flat().map((datum) => datum.key);\n const leftY = seriesList\n .filter((series) => series.yAxis !== 'right')\n .flatMap((series) => series.data.map((datum) => datum.value));\n const rightY = seriesList\n .filter((series) => series.yAxis === 'right')\n .flatMap((series) => series.data.map((datum) => datum.value));\n\n if (allX.length === 0) {\n clearCartesianDom(groups, legend, tooltip, crosshair);\n markers?.replaceChildren();\n rightAxis?.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 const yScale = buildYScale(leftY, area.height);\n const rightYScale = buildYScale(rightY, area.height);\n\n if (config.yAxis?.grid && (!hasRight || hasLeftData)) {\n renderGrid(\n groups.grid,\n yScale,\n config.yAxis.grid,\n area.width,\n 'horizontal',\n resolveTickCount(config.yAxis, area.height, 'left'),\n );\n } else {\n groups.grid.replaceChildren();\n }\n\n if (config.xAxis?.grid) {\n renderGrid(\n groups.grid,\n xScale,\n config.xAxis.grid,\n area.height,\n 'vertical',\n resolveTickCount(config.xAxis, area.width, 'bottom'),\n );\n }\n\n if (config.xAxis) {\n positionAxis(groups.xAxis, config.xAxis.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, xScale, config.xAxis, area.width, 'bottom');\n }\n\n if (config.yAxis && (!hasRight || hasLeftData)) {\n const axis = { ...config.yAxis, position: hasRight ? ('left' as const) : (config.yAxis.position ?? 'left') };\n positionAxis(groups.yAxis, axis.position, area.width, area.height);\n renderAxis(groups.yAxis, yScale, axis, area.height, 'left');\n } else {\n groups.yAxis.replaceChildren();\n }\n\n if (hasRight) {\n if (!rightAxis) {\n rightAxis = createSvgElement('g', { class: 'prism-y-axis-right' });\n ctx.chartArea.appendChild(rightAxis);\n }\n const axis = { ...config.rightYAxis, position: 'right' as const };\n positionAxis(rightAxis, 'right', area.width, area.height);\n renderAxis(rightAxis, rightYScale, axis, area.height, 'right');\n } else {\n rightAxis?.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 (let i = 0; i < seriesList.length; i++) {\n const series = seriesList[i];\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-line-series' });\n groups.series.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const points = computePoints(allData[i], xScale, series.yAxis === 'right' ? rightYScale : yScale);\n\n allPoints.push(points);\n\n renderLine(group, points, {\n color: seriesColor(i, series.color),\n curve: series.curve ?? 'linear',\n disposalSignal: ctx.disposalSignal,\n marks: series.data,\n pointRadius: series.pointRadius ?? 3,\n showPoints: series.showPoints ?? false,\n strokeWidth: series.strokeWidth,\n transition: config.transition,\n });\n }\n\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n tooltip?.hide();\n markers = ensureMarkerGroup(ctx.chartArea, markers);\n\n return createSeriesInteraction({\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,\n markers,\n onClick: config.onClick,\n onHover: config.onHover,\n seriesGroup: groups.series,\n svg: ctx.svg,\n tooltip,\n });\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../animation/easing.cjs"),n=require("../../animation/motion.cjs"),r=require("../../animation/tween.cjs"),i=require("../../core/datum-style.cjs"),a=require("../../svg/path.cjs");var o=new WeakMap;function buildPath(e,t){return t===`monotone`?a.monotonePath(e):t===`step`?a.stepPath(e):a.linePath(e)}function renderLine(a,s,c){let l=i.hasStyledRuns(c.marks),u=c.marks??[],d=n.resolveMotion(c.transition,0),f=d.duration,p=t.resolveEasing(d.easing),m=null,h=[],g=[];if(l){h=i.computeStyleRuns(u,s.length);let t=[...a.querySelectorAll(`.prism-line-path`)];for(let e of t.slice(h.length))e.remove();g=h.map((n,r)=>{let i=t[r];if(i)return i;let o=e.createSvgElement(`path`,{class:`prism-line-path`,fill:`none`});return a.appendChild(o),o});for(let[t,n]of h.entries())e.setAttributes(g[t],{opacity:n.opacity,stroke:c.color,"stroke-dasharray":n.dash,"stroke-width":c.strokeWidth??2}),g[t].style.strokeWidth=c.strokeWidth===void 0?``:String(c.strokeWidth)}else{let t=[...a.querySelectorAll(`.prism-line-path`)];m=t[0]??null;for(let e of t.slice(1))e.remove();m||(m=e.createSvgElement(`path`,{class:`prism-line-path`,fill:`none`}),a.appendChild(m)),e.setAttributes(m,{opacity:void 0,stroke:c.color,"stroke-dasharray":void 0,"stroke-width":c.strokeWidth??2}),m.style.strokeWidth=c.strokeWidth===void 0?``:String(c.strokeWidth)}let draw=t=>{if(l)for(let[n,r]of h.entries())e.setAttributes(g[n],{d:buildPath(t.slice(r.start,r.end+1),c.curve)});else e.setAttributes(m,{d:buildPath(t,c.curve)})},_=a.querySelector(`.prism-line-dots`);if(c.showPoints?_||(_=e.createSvgElement(`g`,{class:`prism-line-dots`}),a.appendChild(_)):_&&=(_.remove(),null),f===0){if(draw(s),_){for(;_.children.length>s.length;)_.removeChild(_.lastChild);for(let t=0;t<s.length;t++){let n=_.children[t];n||(n=e.createSvgElement(`circle`,{class:`prism-line-dot`}),_.appendChild(n)),e.setAttributes(n,{cx:s[t].x,cy:s[t].y,fill:c.color,opacity:u[t]?.opacity,r:c.pointRadius})}}return}o.get(a)?.();let v=l?g.some(e=>e.hasAttribute(`d`)):!!m?.getAttribute(`d`),y=[],b=null;if(_){let t=_.children.length;for(let e=0;e<t;e++){let t=_.children[e],n={x:Number(t.getAttribute(`cx`)),y:Number(t.getAttribute(`cy`))};y.push(n),b=n}for(;_.children.length>s.length;)_.removeChild(_.lastChild);for(let t=_.children.length;t<s.length;t++){let n=e.createSvgElement(`circle`,{class:`prism-line-dot`});e.setAttributes(n,{cx:s[t].x,cy:s[t].y,fill:c.color,opacity:u[t]?.opacity,r:c.pointRadius}),_.appendChild(n)}for(let t=0;t<_.children.length;t++)e.setAttributes(_.children[t],{opacity:u[t]?.opacity})}for(let e=y.length;e<s.length;e++)y.push(b??s[e]);let x=null;function frame(t){if(c.disposalSignal?.aborted){o.delete(a);return}x===null&&(x=t);let n=Math.min(1,(t-x)/f),i=p(n),l=s.map((e,t)=>{let n=y[t]??e;return{x:r.tweenNumber(n.x,e.x,i),y:r.tweenNumber(n.y,e.y,i)}});if(draw(l),_)for(let t=0;t<s.length;t++){let n=_.children[t];n&&e.setAttributes(n,{cx:l[t].x,cy:l[t].y})}if(n<1){let e=requestAnimationFrame(frame);o.set(a,()=>cancelAnimationFrame(e))}else o.delete(a)}if(!v)draw(s);else{let e=requestAnimationFrame(frame);o.set(a,()=>cancelAnimationFrame(e))}}function computePoints(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)}))}exports.computePoints=computePoints,exports.renderLine=renderLine;
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"),a=require("../../core/datum-style.cjs"),o=require("../../svg/path.cjs");var s=new WeakMap;function buildPath(e,t){return t===`monotone`?o.monotonePath(e):t===`step`?o.stepPath(e):o.linePath(e)}function renderLine(o,c,l){let u=a.hasStyledRuns(l.marks),d=l.marks??[],f=n.resolveMotion(l.transition,0),p=f.duration,m=t.resolveEasing(f.easing),h=null,g=[],_=[];if(u){g=a.computeStyleRuns(d,c.length);let t=[...o.querySelectorAll(`.prism-line-path`)];for(let e of t.slice(g.length))e.remove();_=g.map((n,r)=>{let i=t[r];if(i)return i;let a=e.createSvgElement(`path`,{class:`prism-line-path`,fill:`none`});return o.appendChild(a),a});for(let[t,n]of g.entries())e.setAttributes(_[t],{opacity:n.opacity,stroke:l.color,"stroke-dasharray":n.dash,"stroke-width":l.strokeWidth??2}),_[t].style.strokeWidth=l.strokeWidth===void 0?``:String(l.strokeWidth)}else{let t=[...o.querySelectorAll(`.prism-line-path`)];h=t[0]??null;for(let e of t.slice(1))e.remove();h||(h=e.createSvgElement(`path`,{class:`prism-line-path`,fill:`none`}),o.appendChild(h)),e.setAttributes(h,{opacity:void 0,stroke:l.color,"stroke-dasharray":void 0,"stroke-width":l.strokeWidth??2}),h.style.strokeWidth=l.strokeWidth===void 0?``:String(l.strokeWidth)}let draw=t=>{if(u)for(let[n,r]of g.entries())e.setAttributes(_[n],{d:buildPath(t.slice(r.start,r.end+1),l.curve)});else e.setAttributes(h,{d:buildPath(t,l.curve)})},v=o.querySelector(`.prism-line-dots`);if(l.showPoints?v||(v=e.createSvgElement(`g`,{class:`prism-line-dots`}),o.appendChild(v)):v&&=(v.remove(),null),p===0){if(draw(c),v){for(;v.children.length>c.length;)v.removeChild(v.lastChild);for(let t=0;t<c.length;t++){let n=v.children[t];n||(n=e.createSvgElement(`circle`,{class:`prism-line-dot`}),v.appendChild(n)),e.setAttributes(n,{cx:c[t].x,cy:c[t].y,fill:l.color,opacity:d[t]?.opacity,r:l.pointRadius})}}return}s.get(o)?.();let y=u?_.some(e=>e.hasAttribute(`d`)):!!h?.getAttribute(`d`),b=[],x=null;if(v){let t=v.children.length;for(let e=0;e<t;e++){let t=v.children[e],n={x:Number(t.getAttribute(`cx`)),y:Number(t.getAttribute(`cy`))};b.push(n),x=n}for(;v.children.length>c.length;)v.removeChild(v.lastChild);for(let t=v.children.length;t<c.length;t++){let n=e.createSvgElement(`circle`,{class:`prism-line-dot`});e.setAttributes(n,{cx:c[t].x,cy:c[t].y,fill:l.color,opacity:d[t]?.opacity,r:l.pointRadius}),v.appendChild(n)}for(let t=0;t<v.children.length;t++)e.setAttributes(v.children[t],{opacity:d[t]?.opacity})}for(let e=b.length;e<c.length;e++)b.push(x??c[e]);if(!y){draw(c);return}s.set(o,i.startTween({count:1,duration:p,easing:m,onComplete:()=>s.delete(o),onFrame:t=>{let n=t(0),i=c.map((e,t)=>{let i=b[t]??e;return{x:r.tweenNumber(i.x,e.x,n),y:r.tweenNumber(i.y,e.y,n)}});if(draw(i),v)for(let t=0;t<c.length;t++){let n=v.children[t];n&&e.setAttributes(n,{cx:i[t].x,cy:i[t].y})}},signal:l.disposalSignal}))}function computePoints(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)}))}exports.computePoints=computePoints,exports.renderLine=renderLine;
2
2
  //# sourceMappingURL=line-renderer.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"line-renderer.cjs","names":[],"sources":["../../../src/charts/line/line-renderer.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport { computeStyleRuns, type DatumMark, hasStyledRuns, type StyleRun } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionConfig } from '../../types';\n\nexport interface LineRenderOptions {\n color: string;\n curve: 'linear' | 'monotone' | 'step';\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`; styled runs split the line into subpaths. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n showPoints: boolean;\n /** Explicit width beats the `--prism-line-width` theme token. */\n strokeWidth?: number;\n transition?: TransitionConfig;\n}\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n\nfunction buildPath(pts: Point[], curve: LineRenderOptions['curve']): string {\n return curve === 'monotone' ? monotonePath(pts) : curve === 'step' ? stepPath(pts) : linePath(pts);\n}\n\nexport function renderLine(parent: SVGGElement, points: Point[], options: LineRenderOptions): void {\n const styled = hasStyledRuns(options.marks);\n const marks = options.marks ?? [];\n const motion = resolveMotion(options.transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n let path: SVGPathElement | null = null;\n let runs: readonly StyleRun[] = [];\n let runPaths: SVGPathElement[] = [];\n\n if (styled) {\n runs = computeStyleRuns(marks, points.length);\n\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n for (const extra of existing.slice(runs.length)) extra.remove();\n\n runPaths = runs.map((_, r) => {\n const reuse = existing[r];\n\n if (reuse) return reuse;\n\n const created = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n\n parent.appendChild(created);\n\n return created;\n });\n\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], {\n opacity: run.opacity,\n stroke: options.color,\n 'stroke-dasharray': run.dash,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n runPaths[r].style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n } else {\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n path = existing[0] ?? null;\n\n for (const stale of existing.slice(1)) stale.remove();\n\n if (!path) {\n path = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n parent.appendChild(path);\n }\n\n setAttributes(path, {\n opacity: undefined,\n stroke: options.color,\n 'stroke-dasharray': undefined,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n path.style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n\n const draw = (pts: Point[]): void => {\n if (styled) {\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], { d: buildPath(pts.slice(run.start, run.end + 1), options.curve) });\n }\n } else {\n setAttributes(path!, { d: buildPath(pts, options.curve) });\n }\n };\n\n let dotsGroup = parent.querySelector<SVGGElement>('.prism-line-dots');\n\n if (options.showPoints) {\n if (!dotsGroup) {\n dotsGroup = createSvgElement('g', { class: 'prism-line-dots' });\n parent.appendChild(dotsGroup);\n }\n } else if (dotsGroup) {\n dotsGroup.remove();\n dotsGroup = null;\n }\n\n if (dur === 0) {\n draw(points);\n\n if (dotsGroup) {\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = 0; i < points.length; i++) {\n let c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (!c) {\n c = createSvgElement('circle', { class: 'prism-line-dot' });\n dotsGroup.appendChild(c);\n }\n\n setAttributes(c, {\n cx: points[i].x,\n cy: points[i].y,\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n }\n }\n\n return;\n }\n\n activeAnimations.get(parent)?.();\n\n const hasExisting = styled ? runPaths.some((p) => p.hasAttribute('d')) : !!path?.getAttribute('d');\n\n const fromPts: Point[] = [];\n let lastKnown: Point | null = null;\n\n if (dotsGroup) {\n const existingCount = dotsGroup.children.length;\n\n for (let i = 0; i < existingCount; i++) {\n const c = dotsGroup.children[i] as SVGCircleElement;\n const pt = { x: Number(c.getAttribute('cx')), y: Number(c.getAttribute('cy')) };\n\n fromPts.push(pt);\n lastKnown = pt;\n }\n\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = dotsGroup.children.length; i < points.length; i++) {\n const c = createSvgElement('circle', { class: 'prism-line-dot' });\n\n setAttributes(c, {\n cx: points[i].x,\n cy: points[i].y,\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n dotsGroup.appendChild(c);\n }\n\n for (let i = 0; i < dotsGroup.children.length; i++) {\n setAttributes(dotsGroup.children[i] as SVGCircleElement, { opacity: marks[i]?.opacity });\n }\n }\n\n for (let i = fromPts.length; i < points.length; i++) {\n fromPts.push(lastKnown ?? points[i]);\n }\n\n let startTime: number | null = null;\n\n function frame(ts: number) {\n if (options.disposalSignal?.aborted) {\n activeAnimations.delete(parent);\n\n return;\n }\n\n if (startTime === null) startTime = ts;\n\n const t = Math.min(1, (ts - startTime) / dur);\n const e = easing(t);\n const interpolated: Point[] = points.map((to, i) => {\n const from = fromPts[i] ?? to;\n\n return { x: tweenNumber(from.x, to.x, e), y: tweenNumber(from.y, to.y, e) };\n });\n\n draw(interpolated);\n\n if (dotsGroup) {\n for (let i = 0; i < points.length; i++) {\n const c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (c) setAttributes(c, { cx: interpolated[i].x, cy: interpolated[i].y });\n }\n }\n\n if (t < 1) {\n const id = requestAnimationFrame(frame);\n\n activeAnimations.set(parent, () => cancelAnimationFrame(id));\n } else {\n activeAnimations.delete(parent);\n }\n }\n\n if (!hasExisting) {\n draw(points);\n } else {\n const id = requestAnimationFrame(frame);\n\n activeAnimations.set(parent, () => cancelAnimationFrame(id));\n }\n}\n\nexport function computePoints(data: ContinuousDatum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computePoints: 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('computePoints: string keys are not supported for line/area charts: use numeric or Date keys.');\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"],"mappings":"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"}
1
+ {"version":3,"file":"line-renderer.cjs","names":[],"sources":["../../../src/charts/line/line-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 { computeStyleRuns, type DatumMark, hasStyledRuns, type StyleRun } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionConfig } from '../../types';\n\nexport interface LineRenderOptions {\n color: string;\n curve: 'linear' | 'monotone' | 'step';\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`; styled runs split the line into subpaths. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n showPoints: boolean;\n /** Explicit width beats the `--prism-line-width` theme token. */\n strokeWidth?: number;\n transition?: TransitionConfig;\n}\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n\nfunction buildPath(pts: Point[], curve: LineRenderOptions['curve']): string {\n return curve === 'monotone' ? monotonePath(pts) : curve === 'step' ? stepPath(pts) : linePath(pts);\n}\n\nexport function renderLine(parent: SVGGElement, points: Point[], options: LineRenderOptions): void {\n const styled = hasStyledRuns(options.marks);\n const marks = options.marks ?? [];\n const motion = resolveMotion(options.transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n let path: SVGPathElement | null = null;\n let runs: readonly StyleRun[] = [];\n let runPaths: SVGPathElement[] = [];\n\n if (styled) {\n runs = computeStyleRuns(marks, points.length);\n\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n for (const extra of existing.slice(runs.length)) extra.remove();\n\n runPaths = runs.map((_, r) => {\n const reuse = existing[r];\n\n if (reuse) return reuse;\n\n const created = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n\n parent.appendChild(created);\n\n return created;\n });\n\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], {\n opacity: run.opacity,\n stroke: options.color,\n 'stroke-dasharray': run.dash,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n runPaths[r].style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n } else {\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n path = existing[0] ?? null;\n\n for (const stale of existing.slice(1)) stale.remove();\n\n if (!path) {\n path = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n parent.appendChild(path);\n }\n\n setAttributes(path, {\n opacity: undefined,\n stroke: options.color,\n 'stroke-dasharray': undefined,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n path.style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n\n const draw = (pts: Point[]): void => {\n if (styled) {\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], { d: buildPath(pts.slice(run.start, run.end + 1), options.curve) });\n }\n } else {\n setAttributes(path!, { d: buildPath(pts, options.curve) });\n }\n };\n\n let dotsGroup = parent.querySelector<SVGGElement>('.prism-line-dots');\n\n if (options.showPoints) {\n if (!dotsGroup) {\n dotsGroup = createSvgElement('g', { class: 'prism-line-dots' });\n parent.appendChild(dotsGroup);\n }\n } else if (dotsGroup) {\n dotsGroup.remove();\n dotsGroup = null;\n }\n\n if (dur === 0) {\n draw(points);\n\n if (dotsGroup) {\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = 0; i < points.length; i++) {\n let c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (!c) {\n c = createSvgElement('circle', { class: 'prism-line-dot' });\n dotsGroup.appendChild(c);\n }\n\n setAttributes(c, {\n cx: points[i].x,\n cy: points[i].y,\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n }\n }\n\n return;\n }\n\n activeAnimations.get(parent)?.();\n\n const hasExisting = styled ? runPaths.some((p) => p.hasAttribute('d')) : !!path?.getAttribute('d');\n\n const fromPts: Point[] = [];\n let lastKnown: Point | null = null;\n\n if (dotsGroup) {\n const existingCount = dotsGroup.children.length;\n\n for (let i = 0; i < existingCount; i++) {\n const c = dotsGroup.children[i] as SVGCircleElement;\n const pt = { x: Number(c.getAttribute('cx')), y: Number(c.getAttribute('cy')) };\n\n fromPts.push(pt);\n lastKnown = pt;\n }\n\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = dotsGroup.children.length; i < points.length; i++) {\n const c = createSvgElement('circle', { class: 'prism-line-dot' });\n\n setAttributes(c, {\n cx: points[i].x,\n cy: points[i].y,\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n dotsGroup.appendChild(c);\n }\n\n for (let i = 0; i < dotsGroup.children.length; i++) {\n setAttributes(dotsGroup.children[i] as SVGCircleElement, { opacity: marks[i]?.opacity });\n }\n }\n\n for (let i = fromPts.length; i < points.length; i++) {\n fromPts.push(lastKnown ?? points[i]);\n }\n\n if (!hasExisting) {\n draw(points);\n\n return;\n }\n\n activeAnimations.set(\n parent,\n startTween({\n count: 1,\n duration: dur,\n easing,\n onComplete: () => activeAnimations.delete(parent),\n onFrame: (progress) => {\n const e = progress(0);\n const interpolated: Point[] = points.map((to, i) => {\n const from = fromPts[i] ?? to;\n\n return { x: tweenNumber(from.x, to.x, e), y: tweenNumber(from.y, to.y, e) };\n });\n\n draw(interpolated);\n\n if (dotsGroup) {\n for (let i = 0; i < points.length; i++) {\n const c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (c) setAttributes(c, { cx: interpolated[i].x, cy: interpolated[i].y });\n }\n }\n },\n signal: options.disposalSignal,\n }),\n );\n}\n\nexport function computePoints(data: ContinuousDatum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computePoints: 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('computePoints: string keys are not supported for line/area charts: use numeric or Date keys.');\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"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"line-renderer.d.ts","sourceRoot":"","sources":["../../../src/charts/line/line-renderer.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoB,KAAK,SAAS,EAAgC,MAAM,wBAAwB,CAAC;AAExG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE5E,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;IACtC,wHAAwH;IACxH,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,6FAA6F;IAC7F,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAQD,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAoMjG;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,EAAE,CAanH"}
1
+ {"version":3,"file":"line-renderer.d.ts","sourceRoot":"","sources":["../../../src/charts/line/line-renderer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAoB,KAAK,SAAS,EAAgC,MAAM,wBAAwB,CAAC;AAExG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE5E,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;IACtC,wHAAwH;IACxH,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,6FAA6F;IAC7F,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAQD,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAyLjG;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,EAAE,CAanH"}
@@ -1,2 +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{computeStyleRuns as a,hasStyledRuns as o}from"../../core/datum-style.js";import{linePath as s,monotonePath as c,stepPath as l}from"../../svg/path.js";var u=new WeakMap;function buildPath(e,t){return t===`monotone`?c(e):t===`step`?l(e):s(e)}function renderLine(s,c,l){let d=o(l.marks),f=l.marks??[],p=r(l.transition,0),m=p.duration,h=n(p.easing),g=null,_=[],v=[];if(d){_=a(f,c.length);let n=[...s.querySelectorAll(`.prism-line-path`)];for(let e of n.slice(_.length))e.remove();v=_.map((t,r)=>{let i=n[r];if(i)return i;let a=e(`path`,{class:`prism-line-path`,fill:`none`});return s.appendChild(a),a});for(let[e,n]of _.entries())t(v[e],{opacity:n.opacity,stroke:l.color,"stroke-dasharray":n.dash,"stroke-width":l.strokeWidth??2}),v[e].style.strokeWidth=l.strokeWidth===void 0?``:String(l.strokeWidth)}else{let n=[...s.querySelectorAll(`.prism-line-path`)];g=n[0]??null;for(let e of n.slice(1))e.remove();g||(g=e(`path`,{class:`prism-line-path`,fill:`none`}),s.appendChild(g)),t(g,{opacity:void 0,stroke:l.color,"stroke-dasharray":void 0,"stroke-width":l.strokeWidth??2}),g.style.strokeWidth=l.strokeWidth===void 0?``:String(l.strokeWidth)}let draw=e=>{if(d)for(let[n,r]of _.entries())t(v[n],{d:buildPath(e.slice(r.start,r.end+1),l.curve)});else t(g,{d:buildPath(e,l.curve)})},y=s.querySelector(`.prism-line-dots`);if(l.showPoints?y||(y=e(`g`,{class:`prism-line-dots`}),s.appendChild(y)):y&&=(y.remove(),null),m===0){if(draw(c),y){for(;y.children.length>c.length;)y.removeChild(y.lastChild);for(let n=0;n<c.length;n++){let r=y.children[n];r||(r=e(`circle`,{class:`prism-line-dot`}),y.appendChild(r)),t(r,{cx:c[n].x,cy:c[n].y,fill:l.color,opacity:f[n]?.opacity,r:l.pointRadius})}}return}u.get(s)?.();let b=d?v.some(e=>e.hasAttribute(`d`)):!!g?.getAttribute(`d`),x=[],S=null;if(y){let n=y.children.length;for(let e=0;e<n;e++){let t=y.children[e],n={x:Number(t.getAttribute(`cx`)),y:Number(t.getAttribute(`cy`))};x.push(n),S=n}for(;y.children.length>c.length;)y.removeChild(y.lastChild);for(let n=y.children.length;n<c.length;n++){let r=e(`circle`,{class:`prism-line-dot`});t(r,{cx:c[n].x,cy:c[n].y,fill:l.color,opacity:f[n]?.opacity,r:l.pointRadius}),y.appendChild(r)}for(let e=0;e<y.children.length;e++)t(y.children[e],{opacity:f[e]?.opacity})}for(let e=x.length;e<c.length;e++)x.push(S??c[e]);let C=null;function frame(e){if(l.disposalSignal?.aborted){u.delete(s);return}C===null&&(C=e);let n=Math.min(1,(e-C)/m),r=h(n),a=c.map((e,t)=>{let n=x[t]??e;return{x:i(n.x,e.x,r),y:i(n.y,e.y,r)}});if(draw(a),y)for(let e=0;e<c.length;e++){let n=y.children[e];n&&t(n,{cx:a[e].x,cy:a[e].y})}if(n<1){let e=requestAnimationFrame(frame);u.set(s,()=>cancelAnimationFrame(e))}else u.delete(s)}if(!b)draw(c);else{let e=requestAnimationFrame(frame);u.set(s,()=>cancelAnimationFrame(e))}}function computePoints(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)}))}export{computePoints,renderLine};
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";import{computeStyleRuns as o,hasStyledRuns as s}from"../../core/datum-style.js";import{linePath as c,monotonePath as l,stepPath as u}from"../../svg/path.js";var d=new WeakMap;function buildPath(e,t){return t===`monotone`?l(e):t===`step`?u(e):c(e)}function renderLine(c,l,u){let f=s(u.marks),p=u.marks??[],m=r(u.transition,0),h=m.duration,g=n(m.easing),_=null,v=[],y=[];if(f){v=o(p,l.length);let n=[...c.querySelectorAll(`.prism-line-path`)];for(let e of n.slice(v.length))e.remove();y=v.map((t,r)=>{let i=n[r];if(i)return i;let a=e(`path`,{class:`prism-line-path`,fill:`none`});return c.appendChild(a),a});for(let[e,n]of v.entries())t(y[e],{opacity:n.opacity,stroke:u.color,"stroke-dasharray":n.dash,"stroke-width":u.strokeWidth??2}),y[e].style.strokeWidth=u.strokeWidth===void 0?``:String(u.strokeWidth)}else{let n=[...c.querySelectorAll(`.prism-line-path`)];_=n[0]??null;for(let e of n.slice(1))e.remove();_||(_=e(`path`,{class:`prism-line-path`,fill:`none`}),c.appendChild(_)),t(_,{opacity:void 0,stroke:u.color,"stroke-dasharray":void 0,"stroke-width":u.strokeWidth??2}),_.style.strokeWidth=u.strokeWidth===void 0?``:String(u.strokeWidth)}let draw=e=>{if(f)for(let[n,r]of v.entries())t(y[n],{d:buildPath(e.slice(r.start,r.end+1),u.curve)});else t(_,{d:buildPath(e,u.curve)})},b=c.querySelector(`.prism-line-dots`);if(u.showPoints?b||(b=e(`g`,{class:`prism-line-dots`}),c.appendChild(b)):b&&=(b.remove(),null),h===0){if(draw(l),b){for(;b.children.length>l.length;)b.removeChild(b.lastChild);for(let n=0;n<l.length;n++){let r=b.children[n];r||(r=e(`circle`,{class:`prism-line-dot`}),b.appendChild(r)),t(r,{cx:l[n].x,cy:l[n].y,fill:u.color,opacity:p[n]?.opacity,r:u.pointRadius})}}return}d.get(c)?.();let x=f?y.some(e=>e.hasAttribute(`d`)):!!_?.getAttribute(`d`),S=[],C=null;if(b){let n=b.children.length;for(let e=0;e<n;e++){let t=b.children[e],n={x:Number(t.getAttribute(`cx`)),y:Number(t.getAttribute(`cy`))};S.push(n),C=n}for(;b.children.length>l.length;)b.removeChild(b.lastChild);for(let n=b.children.length;n<l.length;n++){let r=e(`circle`,{class:`prism-line-dot`});t(r,{cx:l[n].x,cy:l[n].y,fill:u.color,opacity:p[n]?.opacity,r:u.pointRadius}),b.appendChild(r)}for(let e=0;e<b.children.length;e++)t(b.children[e],{opacity:p[e]?.opacity})}for(let e=S.length;e<l.length;e++)S.push(C??l[e]);if(!x){draw(l);return}d.set(c,a({count:1,duration:h,easing:g,onComplete:()=>d.delete(c),onFrame:e=>{let n=e(0),r=l.map((e,t)=>{let r=S[t]??e;return{x:i(r.x,e.x,n),y:i(r.y,e.y,n)}});if(draw(r),b)for(let e=0;e<l.length;e++){let n=b.children[e];n&&t(n,{cx:r[e].x,cy:r[e].y})}},signal:u.disposalSignal}))}function computePoints(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)}))}export{computePoints,renderLine};
2
2
  //# sourceMappingURL=line-renderer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"line-renderer.js","names":[],"sources":["../../../src/charts/line/line-renderer.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport { computeStyleRuns, type DatumMark, hasStyledRuns, type StyleRun } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionConfig } from '../../types';\n\nexport interface LineRenderOptions {\n color: string;\n curve: 'linear' | 'monotone' | 'step';\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`; styled runs split the line into subpaths. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n showPoints: boolean;\n /** Explicit width beats the `--prism-line-width` theme token. */\n strokeWidth?: number;\n transition?: TransitionConfig;\n}\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n\nfunction buildPath(pts: Point[], curve: LineRenderOptions['curve']): string {\n return curve === 'monotone' ? monotonePath(pts) : curve === 'step' ? stepPath(pts) : linePath(pts);\n}\n\nexport function renderLine(parent: SVGGElement, points: Point[], options: LineRenderOptions): void {\n const styled = hasStyledRuns(options.marks);\n const marks = options.marks ?? [];\n const motion = resolveMotion(options.transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n let path: SVGPathElement | null = null;\n let runs: readonly StyleRun[] = [];\n let runPaths: SVGPathElement[] = [];\n\n if (styled) {\n runs = computeStyleRuns(marks, points.length);\n\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n for (const extra of existing.slice(runs.length)) extra.remove();\n\n runPaths = runs.map((_, r) => {\n const reuse = existing[r];\n\n if (reuse) return reuse;\n\n const created = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n\n parent.appendChild(created);\n\n return created;\n });\n\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], {\n opacity: run.opacity,\n stroke: options.color,\n 'stroke-dasharray': run.dash,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n runPaths[r].style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n } else {\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n path = existing[0] ?? null;\n\n for (const stale of existing.slice(1)) stale.remove();\n\n if (!path) {\n path = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n parent.appendChild(path);\n }\n\n setAttributes(path, {\n opacity: undefined,\n stroke: options.color,\n 'stroke-dasharray': undefined,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n path.style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n\n const draw = (pts: Point[]): void => {\n if (styled) {\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], { d: buildPath(pts.slice(run.start, run.end + 1), options.curve) });\n }\n } else {\n setAttributes(path!, { d: buildPath(pts, options.curve) });\n }\n };\n\n let dotsGroup = parent.querySelector<SVGGElement>('.prism-line-dots');\n\n if (options.showPoints) {\n if (!dotsGroup) {\n dotsGroup = createSvgElement('g', { class: 'prism-line-dots' });\n parent.appendChild(dotsGroup);\n }\n } else if (dotsGroup) {\n dotsGroup.remove();\n dotsGroup = null;\n }\n\n if (dur === 0) {\n draw(points);\n\n if (dotsGroup) {\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = 0; i < points.length; i++) {\n let c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (!c) {\n c = createSvgElement('circle', { class: 'prism-line-dot' });\n dotsGroup.appendChild(c);\n }\n\n setAttributes(c, {\n cx: points[i].x,\n cy: points[i].y,\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n }\n }\n\n return;\n }\n\n activeAnimations.get(parent)?.();\n\n const hasExisting = styled ? runPaths.some((p) => p.hasAttribute('d')) : !!path?.getAttribute('d');\n\n const fromPts: Point[] = [];\n let lastKnown: Point | null = null;\n\n if (dotsGroup) {\n const existingCount = dotsGroup.children.length;\n\n for (let i = 0; i < existingCount; i++) {\n const c = dotsGroup.children[i] as SVGCircleElement;\n const pt = { x: Number(c.getAttribute('cx')), y: Number(c.getAttribute('cy')) };\n\n fromPts.push(pt);\n lastKnown = pt;\n }\n\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = dotsGroup.children.length; i < points.length; i++) {\n const c = createSvgElement('circle', { class: 'prism-line-dot' });\n\n setAttributes(c, {\n cx: points[i].x,\n cy: points[i].y,\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n dotsGroup.appendChild(c);\n }\n\n for (let i = 0; i < dotsGroup.children.length; i++) {\n setAttributes(dotsGroup.children[i] as SVGCircleElement, { opacity: marks[i]?.opacity });\n }\n }\n\n for (let i = fromPts.length; i < points.length; i++) {\n fromPts.push(lastKnown ?? points[i]);\n }\n\n let startTime: number | null = null;\n\n function frame(ts: number) {\n if (options.disposalSignal?.aborted) {\n activeAnimations.delete(parent);\n\n return;\n }\n\n if (startTime === null) startTime = ts;\n\n const t = Math.min(1, (ts - startTime) / dur);\n const e = easing(t);\n const interpolated: Point[] = points.map((to, i) => {\n const from = fromPts[i] ?? to;\n\n return { x: tweenNumber(from.x, to.x, e), y: tweenNumber(from.y, to.y, e) };\n });\n\n draw(interpolated);\n\n if (dotsGroup) {\n for (let i = 0; i < points.length; i++) {\n const c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (c) setAttributes(c, { cx: interpolated[i].x, cy: interpolated[i].y });\n }\n }\n\n if (t < 1) {\n const id = requestAnimationFrame(frame);\n\n activeAnimations.set(parent, () => cancelAnimationFrame(id));\n } else {\n activeAnimations.delete(parent);\n }\n }\n\n if (!hasExisting) {\n draw(points);\n } else {\n const id = requestAnimationFrame(frame);\n\n activeAnimations.set(parent, () => cancelAnimationFrame(id));\n }\n}\n\nexport function computePoints(data: ContinuousDatum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computePoints: 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('computePoints: string keys are not supported for line/area charts: use numeric or Date keys.');\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"],"mappings":"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"}
1
+ {"version":3,"file":"line-renderer.js","names":[],"sources":["../../../src/charts/line/line-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 { computeStyleRuns, type DatumMark, hasStyledRuns, type StyleRun } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionConfig } from '../../types';\n\nexport interface LineRenderOptions {\n color: string;\n curve: 'linear' | 'monotone' | 'step';\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`; styled runs split the line into subpaths. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n showPoints: boolean;\n /** Explicit width beats the `--prism-line-width` theme token. */\n strokeWidth?: number;\n transition?: TransitionConfig;\n}\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n\nfunction buildPath(pts: Point[], curve: LineRenderOptions['curve']): string {\n return curve === 'monotone' ? monotonePath(pts) : curve === 'step' ? stepPath(pts) : linePath(pts);\n}\n\nexport function renderLine(parent: SVGGElement, points: Point[], options: LineRenderOptions): void {\n const styled = hasStyledRuns(options.marks);\n const marks = options.marks ?? [];\n const motion = resolveMotion(options.transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n let path: SVGPathElement | null = null;\n let runs: readonly StyleRun[] = [];\n let runPaths: SVGPathElement[] = [];\n\n if (styled) {\n runs = computeStyleRuns(marks, points.length);\n\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n for (const extra of existing.slice(runs.length)) extra.remove();\n\n runPaths = runs.map((_, r) => {\n const reuse = existing[r];\n\n if (reuse) return reuse;\n\n const created = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n\n parent.appendChild(created);\n\n return created;\n });\n\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], {\n opacity: run.opacity,\n stroke: options.color,\n 'stroke-dasharray': run.dash,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n runPaths[r].style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n } else {\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n path = existing[0] ?? null;\n\n for (const stale of existing.slice(1)) stale.remove();\n\n if (!path) {\n path = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n parent.appendChild(path);\n }\n\n setAttributes(path, {\n opacity: undefined,\n stroke: options.color,\n 'stroke-dasharray': undefined,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n path.style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n\n const draw = (pts: Point[]): void => {\n if (styled) {\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], { d: buildPath(pts.slice(run.start, run.end + 1), options.curve) });\n }\n } else {\n setAttributes(path!, { d: buildPath(pts, options.curve) });\n }\n };\n\n let dotsGroup = parent.querySelector<SVGGElement>('.prism-line-dots');\n\n if (options.showPoints) {\n if (!dotsGroup) {\n dotsGroup = createSvgElement('g', { class: 'prism-line-dots' });\n parent.appendChild(dotsGroup);\n }\n } else if (dotsGroup) {\n dotsGroup.remove();\n dotsGroup = null;\n }\n\n if (dur === 0) {\n draw(points);\n\n if (dotsGroup) {\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = 0; i < points.length; i++) {\n let c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (!c) {\n c = createSvgElement('circle', { class: 'prism-line-dot' });\n dotsGroup.appendChild(c);\n }\n\n setAttributes(c, {\n cx: points[i].x,\n cy: points[i].y,\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n }\n }\n\n return;\n }\n\n activeAnimations.get(parent)?.();\n\n const hasExisting = styled ? runPaths.some((p) => p.hasAttribute('d')) : !!path?.getAttribute('d');\n\n const fromPts: Point[] = [];\n let lastKnown: Point | null = null;\n\n if (dotsGroup) {\n const existingCount = dotsGroup.children.length;\n\n for (let i = 0; i < existingCount; i++) {\n const c = dotsGroup.children[i] as SVGCircleElement;\n const pt = { x: Number(c.getAttribute('cx')), y: Number(c.getAttribute('cy')) };\n\n fromPts.push(pt);\n lastKnown = pt;\n }\n\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = dotsGroup.children.length; i < points.length; i++) {\n const c = createSvgElement('circle', { class: 'prism-line-dot' });\n\n setAttributes(c, {\n cx: points[i].x,\n cy: points[i].y,\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n dotsGroup.appendChild(c);\n }\n\n for (let i = 0; i < dotsGroup.children.length; i++) {\n setAttributes(dotsGroup.children[i] as SVGCircleElement, { opacity: marks[i]?.opacity });\n }\n }\n\n for (let i = fromPts.length; i < points.length; i++) {\n fromPts.push(lastKnown ?? points[i]);\n }\n\n if (!hasExisting) {\n draw(points);\n\n return;\n }\n\n activeAnimations.set(\n parent,\n startTween({\n count: 1,\n duration: dur,\n easing,\n onComplete: () => activeAnimations.delete(parent),\n onFrame: (progress) => {\n const e = progress(0);\n const interpolated: Point[] = points.map((to, i) => {\n const from = fromPts[i] ?? to;\n\n return { x: tweenNumber(from.x, to.x, e), y: tweenNumber(from.y, to.y, e) };\n });\n\n draw(interpolated);\n\n if (dotsGroup) {\n for (let i = 0; i < points.length; i++) {\n const c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (c) setAttributes(c, { cx: interpolated[i].x, cy: interpolated[i].y });\n }\n }\n },\n signal: options.disposalSignal,\n }),\n );\n}\n\nexport function computePoints(data: ContinuousDatum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computePoints: 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('computePoints: string keys are not supported for line/area charts: use numeric or Date keys.');\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"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("../../svg/element.cjs"),t=require("../../svg/text.cjs"),n=require("../../core/chart-scaffold.cjs"),r=require("../../theme/index.cjs"),i=require("../../animation/easing.cjs"),a=require("../../animation/motion.cjs"),o=require("../../animation/tween.cjs"),s=require("./pie-renderer.cjs");var c=2*Math.PI,l=12;function labelFits(e,n){let r=e.outerRadius-e.innerRadius,i=(e.outerRadius+e.innerRadius)/2,a=(e.endAngle-e.startAngle-2*e.padAngle)*i;return r>=l*1.4&&a>=t.estimateTextWidth(n,l)+8}var u=-Math.PI/2,d=Math.PI/2;function semiAngles(e){return e===`semi`?{end:d,start:u}:{end:c,start:0}}function createPieChart(t,c){let l=c.variant??`pie`,u=c.padPixels??(l===`pie`?0:8),d=c.cornerRadius??(l===`pie`?0:8),f=c.data,p=e.createSvgElement(`circle`,{class:`prism-pie-bg`,"pointer-events":`none`}),m=e.createSvgElement(`g`,{class:`prism-pie-slices`,"shape-rendering":`geometricPrecision`}),h=e.createSvgElement(`g`,{class:`prism-pie-labels`,"pointer-events":`none`}),g=[],_=null;function renderLabels(t){h.replaceChildren();for(let n=0;n<g.length;n++){let r=g[n],i=t[n];if(!i?.label||!labelFits(r,i.label))continue;let{x:a,y:o}=s.arcCentroid(r),c=e.createSvgElement(`text`,{class:`prism-pie-label`});e.setAttributes(c,{"dominant-baseline":`middle`,fill:`var(--prism-pie-label-color, #fff)`,"font-family":`var(--prism-font-family, system-ui)`,"font-size":`var(--prism-pie-label-size, 12px)`,"text-anchor":`middle`,x:a,y:o}),c.textContent=i.label,h.appendChild(c)}}let v;try{return v=n.createRadialScaffold(t,{a11y:c.a11y,legend:c.legend,tooltip:c.tooltip},n=>{let{legend:v,svg:y,tooltip:b}=n;y.contains(p)||(y.appendChild(p),y.appendChild(m),y.appendChild(h));let{height:x,width:S}=n.dimensions,C=l===`semi`,w=S/2,T=C?x*.85:x/2,E=C?Math.min(w,T)-8:Math.min(S,x)/2-8,D=l===`pie`?0:Math.round(E*.55),O=c.innerRadius===void 0?D:c.innerRadius,k=Math.max(O+1,E),A=f,{end:j,start:M}=semiAngles(l);for(g=s.computeArcs(A,w,T,k,O,M,j,u,d,e=>r.seriesColor(e),!1),e.setAttributes(p,{cx:w,cy:T,r:O>0?O:0}),p.setAttribute(`style`,`fill:var(--prism-bg,#fff)`);m.children.length>g.length;)m.removeChild(m.lastChild);h.replaceChildren();let N=a.resolveMotion(c.transition,0),P=N.duration,F=i.resolveEasing(N.easing);for(let t=0;t<g.length;t++){let n=g[t],r=m.children[t];r||(r=e.createSvgElement(`path`,{class:`prism-pie-slice`}),m.appendChild(r)),r.setAttribute(`fill`,n.color),r.setAttribute(`stroke`,`none`),r.style.cursor=c.onClick||c.onHover?`pointer`:``}if(_!==null&&(cancelAnimationFrame(_),_=null),P>0){let t=null,frame=n=>{t===null&&(t=n);let r=F(Math.min(1,(n-t)/P)),i=o.tweenNumber(M,j,r);for(let t=0;t<g.length;t++){let n=g[t],r=m.children[t];if(r){if(i<=n.startAngle)e.setAttributes(r,{d:``});else{let t=Math.min(n.endAngle,i);e.setAttributes(r,{d:s.arcPath({...n,endAngle:t})})}}}r<1?_=requestAnimationFrame(frame):(_=null,renderLabels(A))};_=requestAnimationFrame(frame)}else{for(let t=0;t<g.length;t++){let n=g[t],r=m.children[t];r&&e.setAttributes(r,{d:s.arcPath(n)})}renderLabels(A)}v?.update(g.map(e=>({color:e.color,name:e.slice.label??``}))),b?.hide();let I=g.reduce((e,t)=>e+Math.max(0,t.slice.value),0),L=-1,describe=e=>{let t=I>0?Math.round(Math.max(0,e.slice.value)/I*1e3)/10:0;return`${e.slice.label??`Slice ${e.index+1}`}: ${e.slice.value} (${t}%)`},setActive=e=>{L=e,m.classList.toggle(`prism-pie-focused`,e>=0);for(let[t,n]of[...m.children].entries())n.classList.toggle(`prism-pie-slice--active`,t===e)},activate=e=>{let r=g[e];if(!r)return;setActive(e),c.onHover?.(r.slice,e);let i=describe(r);if(!b){n.announcer.announce(i);return}let{x:a,y:o}=s.arcCentroid(r),l=y.getBoundingClientRect(),u=t.getBoundingClientRect();b.show(a+(l.left-u.left),o+(l.top-u.top),{key:e,value:r.slice.value},{color:r.color,data:[],name:r.slice.label??``},i)},deactivate=()=>{setActive(-1),b?.hide(),n.announcer.clear(),c.onHover?.(null,null)},hitAt=e=>{let t=y.getBoundingClientRect();return hitTestArc(g,e.clientX-t.left,e.clientY-t.top,l)},onMouseMove=e=>{let t=hitAt(e);t>=0?t!==L&&activate(t):L>=0&&deactivate()},onClick=e=>{if(!c.onClick)return;let t=hitAt(e);t>=0&&c.onClick(g[t].slice,t)},onKeyDown=e=>{let t=g.length;if(t===0)return;let n={ArrowDown:1,ArrowLeft:-1,ArrowRight:1,ArrowUp:-1};e.key in n?(e.preventDefault(),activate(L<0?n[e.key]>0?0:t-1:(L+n[e.key]+t)%t)):e.key===`Home`||e.key===`End`?(e.preventDefault(),activate(e.key===`Home`?0:t-1)):(e.key===`Enter`||e.key===` `)&&L>=0&&c.onClick?(e.preventDefault(),c.onClick(g[L].slice,L)):e.key===`Escape`&&deactivate()};return{onClick,onKeyDown,onMouseLeave:deactivate,onMouseMove}},e=>{f=e}),{get disposalSignal(){return v.disposalSignal},dispose(){_!==null&&(cancelAnimationFrame(_),_=null),v.dispose()},get disposed(){return v.disposed},el:v.el,update(e){v.update(e)},[Symbol.dispose](){this.dispose()}}}catch(e){throw v?.dispose(),e}}function hitTestArc(e,t,n,r){for(let i=0;i<e.length;i++){let a=e[i],o=t-a.centerX,s=n-a.centerY,l=Math.sqrt(o*o+s*s);if(l<a.outerRadius&&l>=a.innerRadius){let e=Math.atan2(o,-s);if(r===`semi`){if(e>=a.startAngle-1e-9&&e<=a.endAngle+1e-9)return i}else{let t=e<0?e+c:e;if(t>=a.startAngle-1e-9&&t<=a.endAngle+1e-9)return i}}}return-1}exports.createPieChart=createPieChart;
1
+ const e=require("../../svg/element.cjs"),t=require("../../svg/text.cjs"),n=require("../../core/chart-scaffold.cjs"),r=require("../../theme/index.cjs"),i=require("../../animation/easing.cjs"),a=require("../../animation/motion.cjs"),o=require("../../animation/tween.cjs"),s=require("../../animation/transition.cjs"),c=require("./pie-renderer.cjs");var l=2*Math.PI,u=12;function labelFits(e,n){let r=e.outerRadius-e.innerRadius,i=(e.outerRadius+e.innerRadius)/2,a=(e.endAngle-e.startAngle-2*e.padAngle)*i;return r>=u*1.4&&a>=t.estimateTextWidth(n,u)+8}var d=-Math.PI/2,f=Math.PI/2;function semiAngles(e){return e===`semi`?{end:f,start:d}:{end:l,start:0}}function createPieChart(t,l){let u=l.variant??`pie`,d=l.padPixels??(u===`pie`?0:8),f=l.cornerRadius??(u===`pie`?0:8),p=l.data,m=e.createSvgElement(`circle`,{class:`prism-pie-bg`,"pointer-events":`none`}),h=e.createSvgElement(`g`,{class:`prism-pie-slices`,"shape-rendering":`geometricPrecision`}),g=e.createSvgElement(`g`,{class:`prism-pie-labels`,"pointer-events":`none`}),_=[],v=null;function renderLabels(t){g.replaceChildren();for(let n=0;n<_.length;n++){let r=_[n],i=t[n];if(!i?.label||!labelFits(r,i.label))continue;let{x:a,y:o}=c.arcCentroid(r),s=e.createSvgElement(`text`,{class:`prism-pie-label`});e.setAttributes(s,{"dominant-baseline":`middle`,fill:`var(--prism-pie-label-color, #fff)`,"font-family":`var(--prism-font-family, system-ui)`,"font-size":`var(--prism-pie-label-size, 12px)`,"text-anchor":`middle`,x:a,y:o}),s.textContent=i.label,g.appendChild(s)}}return n.createRadialScaffold(t,{a11y:l.a11y,legend:l.legend,tooltip:l.tooltip},n=>{let{legend:y,svg:b,tooltip:x}=n;b.contains(m)||(b.appendChild(m),b.appendChild(h),b.appendChild(g));let{height:S,width:C}=n.dimensions,w=u===`semi`,T=C/2,E=w?S*.85:S/2,D=w?Math.min(T,E)-8:Math.min(C,S)/2-8,O=u===`pie`?0:Math.round(D*.55),k=l.innerRadius===void 0?O:l.innerRadius,A=Math.max(k+1,D),j=p,{end:M,start:N}=semiAngles(u);for(_=c.computeArcs(j,T,E,A,k,N,M,d,f,e=>r.seriesColor(e),!1),e.setAttributes(m,{cx:T,cy:E,r:k>0?k:0}),m.setAttribute(`style`,`fill:var(--prism-bg,#fff)`);h.children.length>_.length;)h.removeChild(h.lastChild);g.replaceChildren();let P=a.resolveMotion(l.transition,0),F=P.duration,I=i.resolveEasing(P.easing);for(let t=0;t<_.length;t++){let n=_[t],r=h.children[t];r||(r=e.createSvgElement(`path`,{class:`prism-pie-slice`}),h.appendChild(r)),r.setAttribute(`fill`,n.color),r.setAttribute(`stroke`,`none`),r.style.cursor=l.onClick||l.onHover?`pointer`:``}v?.(),v=s.startTween({count:1,duration:F,easing:I,onComplete:()=>renderLabels(j),onFrame:t=>{let n=o.tweenNumber(N,M,t(0));for(let t=0;t<_.length;t++){let r=_[t],i=h.children[t];if(i){if(n<=r.startAngle)e.setAttributes(i,{d:``});else{let t=Math.min(r.endAngle,n);e.setAttributes(i,{d:c.arcPath({...r,endAngle:t})})}}}},signal:n.disposalSignal}),y?.update(_.map(e=>({color:e.color,name:e.slice.label??``}))),x?.hide();let L=_.reduce((e,t)=>e+Math.max(0,t.slice.value),0),R=-1,describe=e=>{let t=L>0?Math.round(Math.max(0,e.slice.value)/L*1e3)/10:0;return`${e.slice.label??`Slice ${e.index+1}`}: ${e.slice.value} (${t}%)`},setActive=e=>{R=e,h.classList.toggle(`prism-pie-focused`,e>=0);for(let[t,n]of[...h.children].entries())n.classList.toggle(`prism-pie-slice--active`,t===e)},activate=(e,r)=>{let i=_[e];if(!i)return;setActive(e),l.onHover?.({index:e,originalEvent:r,slice:i.slice});let a=describe(i);if(!x){n.announcer.announce(a);return}let{x:o,y:s}=c.arcCentroid(i),u=b.getBoundingClientRect(),d=t.getBoundingClientRect();x.show(o+(u.left-d.left),s+(u.top-d.top),{key:e,value:i.slice.value},{color:i.color,data:[],name:i.slice.label??``},a)},deactivate=()=>{setActive(-1),x?.hide(),n.announcer.clear(),l.onHover?.(null)},hitAt=e=>{let t=b.getBoundingClientRect();return hitTestArc(_,e.clientX-t.left,e.clientY-t.top,u)},onMouseMove=e=>{let t=hitAt(e);t>=0?t!==R&&activate(t,e):R>=0&&deactivate()},onClick=e=>{if(!l.onClick)return;let t=hitAt(e);t>=0&&l.onClick({index:t,originalEvent:e,slice:_[t].slice})},onKeyDown=e=>{let t=_.length;if(t===0)return;let n={ArrowDown:1,ArrowLeft:-1,ArrowRight:1,ArrowUp:-1};e.key in n?(e.preventDefault(),activate(R<0?n[e.key]>0?0:t-1:(R+n[e.key]+t)%t,e)):e.key===`Home`||e.key===`End`?(e.preventDefault(),activate(e.key===`Home`?0:t-1,e)):(e.key===`Enter`||e.key===` `)&&R>=0&&l.onClick?(e.preventDefault(),l.onClick({index:R,originalEvent:e,slice:_[R].slice})):e.key===`Escape`&&deactivate()};return{onClick,onKeyDown,onMouseLeave:deactivate,onMouseMove}},e=>{p=e})}function hitTestArc(e,t,n,r){for(let i=0;i<e.length;i++){let a=e[i],o=t-a.centerX,s=n-a.centerY,c=Math.sqrt(o*o+s*s);if(c<a.outerRadius&&c>=a.innerRadius){let e=Math.atan2(o,-s);if(r===`semi`){if(e>=a.startAngle-1e-9&&e<=a.endAngle+1e-9)return i}else{let t=e<0?e+l:e;if(t>=a.startAngle-1e-9&&t<=a.endAngle+1e-9)return i}}}return-1}exports.createPieChart=createPieChart;
2
2
  //# sourceMappingURL=pie-chart.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pie-chart.cjs","names":[],"sources":["../../../src/charts/pie/pie-chart.ts"],"sourcesContent":["import { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport type { ChartEventHandlers } from '../../core/chart-scaffold';\nimport { createRadialScaffold } from '../../core/chart-scaffold';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { estimateTextWidth } from '../../svg/text';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, PieChartConfig, PieSliceConfig } from '../../types';\nimport { type Arc, arcCentroid, arcPath, computeArcs } from './pie-renderer';\n\nconst TWO_PI = 2 * Math.PI;\n/** Default `--prism-pie-label-size` in px, used to decide whether a label fits its slice. */\nconst LABEL_FONT_SIZE = 12;\n\n/** A label fits when its slice is wide enough along the centroid arc and thick enough radially. */\nfunction labelFits(arc: Arc, label: string): boolean {\n const thickness = arc.outerRadius - arc.innerRadius;\n const midRadius = (arc.outerRadius + arc.innerRadius) / 2;\n const arcLength = (arc.endAngle - arc.startAngle - 2 * arc.padAngle) * midRadius;\n\n return thickness >= LABEL_FONT_SIZE * 1.4 && arcLength >= estimateTextWidth(label, LABEL_FONT_SIZE) + 8;\n}\n\nconst SEMI_START = -Math.PI / 2; // -90° = 9-o'clock (left)\nconst SEMI_END = Math.PI / 2; // +90° = 3-o'clock (right) → true 180° half-circle\n\nfunction semiAngles(variant: PieChartConfig['variant']): { end: number; start: number } {\n return variant === 'semi' ? { end: SEMI_END, start: SEMI_START } : { end: TWO_PI, start: 0 };\n}\n\nexport function createPieChart(container: HTMLElement, config: PieChartConfig): ChartHandle<PieSliceConfig[]> {\n const variant = config.variant ?? 'pie';\n const padPixels = config.padPixels ?? (variant === 'pie' ? 0 : 8);\n const cornerRadius = config.cornerRadius ?? (variant === 'pie' ? 0 : 8);\n let data = config.data;\n\n // Pie SVG elements live directly on the SVG (not inside chartArea groups).\n // We create them once and reuse across renders.\n const bgCircle = createSvgElement('circle', { class: 'prism-pie-bg', 'pointer-events': 'none' });\n const pieGroup = createSvgElement('g', {\n class: 'prism-pie-slices',\n 'shape-rendering': 'geometricPrecision',\n });\n const labelGroup = createSvgElement('g', { class: 'prism-pie-labels', 'pointer-events': 'none' });\n\n // Current arcs shared between renderFn and event handlers via closure.\n let currentArcs: Arc[] = [];\n let activeRaf: number | null = null;\n\n function renderLabels(slices: PieSliceConfig[]): void {\n labelGroup.replaceChildren();\n\n for (let i = 0; i < currentArcs.length; i++) {\n const arc = currentArcs[i];\n const slice = slices[i];\n\n if (!slice?.label || !labelFits(arc, slice.label)) continue;\n\n const { x, y } = arcCentroid(arc);\n const text = createSvgElement('text', { class: 'prism-pie-label' });\n\n setAttributes(text, {\n 'dominant-baseline': 'middle',\n fill: 'var(--prism-pie-label-color, #fff)',\n 'font-family': 'var(--prism-font-family, system-ui)',\n 'font-size': 'var(--prism-pie-label-size, 12px)',\n 'text-anchor': 'middle',\n x,\n y,\n });\n\n text.textContent = slice.label;\n labelGroup.appendChild(text);\n }\n }\n\n let handle: ChartHandle<PieSliceConfig[]> | undefined;\n\n try {\n handle = createRadialScaffold(\n container,\n {\n a11y: config.a11y,\n legend: config.legend,\n tooltip: config.tooltip,\n },\n (ctx): ChartEventHandlers => {\n const { legend, svg, tooltip } = ctx;\n\n // Append pie groups to SVG on first render (idempotent).\n if (!svg.contains(bgCircle)) {\n svg.appendChild(bgCircle);\n svg.appendChild(pieGroup);\n svg.appendChild(labelGroup);\n }\n\n const { height: h, width: w } = ctx.dimensions;\n const isSemi = variant === 'semi';\n const cx = w / 2;\n const cy = isSemi ? h * 0.85 : h / 2;\n const padding = 8;\n const outer = isSemi ? Math.min(cx, cy) - padding : Math.min(w, h) / 2 - padding;\n const defaultInner = variant === 'pie' ? 0 : Math.round(outer * 0.55);\n const inner = config.innerRadius !== undefined ? config.innerRadius : defaultInner;\n const outerR = Math.max(inner + 1, outer);\n\n const slices = data;\n const { end, start } = semiAngles(variant);\n\n currentArcs = computeArcs(\n slices,\n cx,\n cy,\n outerR,\n inner,\n start,\n end,\n padPixels,\n cornerRadius,\n (i) => seriesColor(i),\n false,\n );\n\n setAttributes(bgCircle, { cx, cy, r: inner > 0 ? inner : 0 });\n bgCircle.setAttribute('style', 'fill:var(--prism-bg,#fff)');\n\n while (pieGroup.children.length > currentArcs.length) pieGroup.removeChild(pieGroup.lastChild!);\n\n labelGroup.replaceChildren();\n\n const motion = resolveMotion(config.transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n for (let i = 0; i < currentArcs.length; i++) {\n const arc = currentArcs[i];\n let path = pieGroup.children[i] as SVGPathElement | undefined;\n\n if (!path) {\n path = createSvgElement('path', { class: 'prism-pie-slice' });\n pieGroup.appendChild(path);\n }\n\n path.setAttribute('fill', arc.color);\n path.setAttribute('stroke', 'none');\n path.style.cursor = config.onClick || config.onHover ? 'pointer' : '';\n }\n\n if (activeRaf !== null) {\n cancelAnimationFrame(activeRaf);\n activeRaf = null;\n }\n\n if (dur > 0) {\n let rafStart: number | null = null;\n\n const frame = (ts: number) => {\n if (rafStart === null) rafStart = ts;\n\n const t = easing(Math.min(1, (ts - rafStart) / dur));\n const revealAngle = tweenNumber(start, end, t);\n\n for (let j = 0; j < currentArcs.length; j++) {\n const a = currentArcs[j];\n const el = pieGroup.children[j] as SVGPathElement | undefined;\n\n if (!el) continue;\n\n if (revealAngle <= a.startAngle) {\n setAttributes(el, { d: '' });\n } else {\n const visibleEnd = Math.min(a.endAngle, revealAngle);\n\n setAttributes(el, { d: arcPath({ ...a, endAngle: visibleEnd }) });\n }\n }\n\n if (t < 1) {\n activeRaf = requestAnimationFrame(frame);\n } else {\n activeRaf = null;\n renderLabels(slices);\n }\n };\n\n activeRaf = requestAnimationFrame(frame);\n } else {\n for (let j = 0; j < currentArcs.length; j++) {\n const a = currentArcs[j];\n const el = pieGroup.children[j] as SVGPathElement | undefined;\n\n if (el) setAttributes(el, { d: arcPath(a) });\n }\n\n renderLabels(slices);\n }\n\n legend?.update(currentArcs.map((arc) => ({ color: arc.color, name: arc.slice.label ?? '' })));\n tooltip?.hide();\n\n const total = currentArcs.reduce((sum, arc) => sum + Math.max(0, arc.slice.value), 0);\n let activeIndex = -1;\n\n const describe = (arc: Arc): string => {\n const percent = total > 0 ? Math.round((Math.max(0, arc.slice.value) / total) * 1000) / 10 : 0;\n\n return `${arc.slice.label ?? `Slice ${arc.index + 1}`}: ${arc.slice.value} (${percent}%)`;\n };\n\n const setActive = (index: number): void => {\n activeIndex = index;\n pieGroup.classList.toggle('prism-pie-focused', index >= 0);\n for (const [i, el] of [...pieGroup.children].entries())\n el.classList.toggle('prism-pie-slice--active', i === index);\n };\n\n const activate = (index: number): void => {\n const arc = currentArcs[index];\n\n if (!arc) return;\n\n setActive(index);\n config.onHover?.(arc.slice, index);\n\n const text = describe(arc);\n\n if (!tooltip) {\n ctx.announcer.announce(text);\n\n return;\n }\n\n const { x, y } = arcCentroid(arc);\n const svgRect = svg.getBoundingClientRect();\n const contR = container.getBoundingClientRect();\n\n tooltip.show(\n x + (svgRect.left - contR.left),\n y + (svgRect.top - contR.top),\n { key: index, value: arc.slice.value },\n { color: arc.color, data: [], name: arc.slice.label ?? '' },\n text,\n );\n };\n\n const deactivate = (): void => {\n setActive(-1);\n tooltip?.hide();\n ctx.announcer.clear();\n config.onHover?.(null, null);\n };\n\n const hitAt = (e: MouseEvent): number => {\n const svgRect = svg.getBoundingClientRect();\n\n return hitTestArc(currentArcs, e.clientX - svgRect.left, e.clientY - svgRect.top, variant);\n };\n\n const onMouseMove = (e: MouseEvent): void => {\n const hit = hitAt(e);\n\n if (hit >= 0) {\n if (hit !== activeIndex) activate(hit);\n } else if (activeIndex >= 0) {\n deactivate();\n }\n };\n\n const onClick = (e: MouseEvent): void => {\n if (!config.onClick) return;\n\n const hit = hitAt(e);\n\n if (hit >= 0) config.onClick(currentArcs[hit].slice, hit);\n };\n\n const onKeyDown = (e: KeyboardEvent): void => {\n const count = currentArcs.length;\n\n if (count === 0) return;\n\n const step: Record<string, number> = { ArrowDown: 1, ArrowLeft: -1, ArrowRight: 1, ArrowUp: -1 };\n\n if (e.key in step) {\n e.preventDefault();\n activate(activeIndex < 0 ? (step[e.key] > 0 ? 0 : count - 1) : (activeIndex + step[e.key] + count) % count);\n } else if (e.key === 'Home' || e.key === 'End') {\n e.preventDefault();\n activate(e.key === 'Home' ? 0 : count - 1);\n } else if ((e.key === 'Enter' || e.key === ' ') && activeIndex >= 0 && config.onClick) {\n e.preventDefault();\n config.onClick(currentArcs[activeIndex].slice, activeIndex);\n } else if (e.key === 'Escape') {\n deactivate();\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave: deactivate, onMouseMove };\n },\n (next) => {\n data = next;\n },\n );\n\n return {\n get disposalSignal(): AbortSignal {\n return handle!.disposalSignal;\n },\n\n dispose() {\n if (activeRaf !== null) {\n cancelAnimationFrame(activeRaf);\n activeRaf = null;\n }\n\n handle!.dispose();\n },\n\n get disposed(): boolean {\n return handle!.disposed;\n },\n\n el: handle!.el,\n\n update(next) {\n handle!.update(next);\n },\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n } catch (error) {\n handle?.dispose();\n throw error;\n }\n}\n\nfunction hitTestArc(arcs: Arc[], mx: number, my: number, variant: PieChartConfig['variant']): number {\n for (let i = 0; i < arcs.length; i++) {\n const arc = arcs[i];\n const dx = mx - arc.centerX;\n const dy = my - arc.centerY;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n if (dist < arc.outerRadius && dist >= arc.innerRadius) {\n const rawAngle = Math.atan2(dx, -dy);\n\n if (variant === 'semi') {\n if (rawAngle >= arc.startAngle - 1e-9 && rawAngle <= arc.endAngle + 1e-9) return i;\n } else {\n const angle = rawAngle < 0 ? rawAngle + TWO_PI : rawAngle;\n\n if (angle >= arc.startAngle - 1e-9 && angle <= arc.endAngle + 1e-9) return i;\n }\n }\n }\n\n return -1;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pie-chart.cjs","names":[],"sources":["../../../src/charts/pie/pie-chart.ts"],"sourcesContent":["import { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport type { ChartEventHandlers } from '../../core/chart-scaffold';\nimport { createRadialScaffold } from '../../core/chart-scaffold';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { estimateTextWidth } from '../../svg/text';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, PieChartConfig, PieSliceConfig } from '../../types';\nimport { type Arc, arcCentroid, arcPath, computeArcs } from './pie-renderer';\n\nconst TWO_PI = 2 * Math.PI;\n/** Default `--prism-pie-label-size` in px, used to decide whether a label fits its slice. */\nconst LABEL_FONT_SIZE = 12;\n\n/** A label fits when its slice is wide enough along the centroid arc and thick enough radially. */\nfunction labelFits(arc: Arc, label: string): boolean {\n const thickness = arc.outerRadius - arc.innerRadius;\n const midRadius = (arc.outerRadius + arc.innerRadius) / 2;\n const arcLength = (arc.endAngle - arc.startAngle - 2 * arc.padAngle) * midRadius;\n\n return thickness >= LABEL_FONT_SIZE * 1.4 && arcLength >= estimateTextWidth(label, LABEL_FONT_SIZE) + 8;\n}\n\nconst SEMI_START = -Math.PI / 2; // -90° = 9-o'clock (left)\nconst SEMI_END = Math.PI / 2; // +90° = 3-o'clock (right) → true 180° half-circle\n\nfunction semiAngles(variant: PieChartConfig['variant']): { end: number; start: number } {\n return variant === 'semi' ? { end: SEMI_END, start: SEMI_START } : { end: TWO_PI, start: 0 };\n}\n\nexport function createPieChart(container: HTMLElement, config: PieChartConfig): ChartHandle<PieSliceConfig[]> {\n const variant = config.variant ?? 'pie';\n const padPixels = config.padPixels ?? (variant === 'pie' ? 0 : 8);\n const cornerRadius = config.cornerRadius ?? (variant === 'pie' ? 0 : 8);\n let data = config.data;\n\n // Pie SVG elements live directly on the SVG (not inside chartArea groups).\n // We create them once and reuse across renders.\n const bgCircle = createSvgElement('circle', { class: 'prism-pie-bg', 'pointer-events': 'none' });\n const pieGroup = createSvgElement('g', {\n class: 'prism-pie-slices',\n 'shape-rendering': 'geometricPrecision',\n });\n const labelGroup = createSvgElement('g', { class: 'prism-pie-labels', 'pointer-events': 'none' });\n\n // Current arcs shared between renderFn and event handlers via closure.\n let currentArcs: Arc[] = [];\n let activeTween: (() => void) | null = null;\n\n function renderLabels(slices: PieSliceConfig[]): void {\n labelGroup.replaceChildren();\n\n for (let i = 0; i < currentArcs.length; i++) {\n const arc = currentArcs[i];\n const slice = slices[i];\n\n if (!slice?.label || !labelFits(arc, slice.label)) continue;\n\n const { x, y } = arcCentroid(arc);\n const text = createSvgElement('text', { class: 'prism-pie-label' });\n\n setAttributes(text, {\n 'dominant-baseline': 'middle',\n fill: 'var(--prism-pie-label-color, #fff)',\n 'font-family': 'var(--prism-font-family, system-ui)',\n 'font-size': 'var(--prism-pie-label-size, 12px)',\n 'text-anchor': 'middle',\n x,\n y,\n });\n\n text.textContent = slice.label;\n labelGroup.appendChild(text);\n }\n }\n\n return createRadialScaffold(\n container,\n {\n a11y: config.a11y,\n legend: config.legend,\n tooltip: config.tooltip,\n },\n (ctx): ChartEventHandlers => {\n const { legend, svg, tooltip } = ctx;\n\n // Append pie groups to SVG on first render (idempotent).\n if (!svg.contains(bgCircle)) {\n svg.appendChild(bgCircle);\n svg.appendChild(pieGroup);\n svg.appendChild(labelGroup);\n }\n\n const { height: h, width: w } = ctx.dimensions;\n const isSemi = variant === 'semi';\n const cx = w / 2;\n const cy = isSemi ? h * 0.85 : h / 2;\n const padding = 8;\n const outer = isSemi ? Math.min(cx, cy) - padding : Math.min(w, h) / 2 - padding;\n const defaultInner = variant === 'pie' ? 0 : Math.round(outer * 0.55);\n const inner = config.innerRadius !== undefined ? config.innerRadius : defaultInner;\n const outerR = Math.max(inner + 1, outer);\n\n const slices = data;\n const { end, start } = semiAngles(variant);\n\n currentArcs = computeArcs(\n slices,\n cx,\n cy,\n outerR,\n inner,\n start,\n end,\n padPixels,\n cornerRadius,\n (i) => seriesColor(i),\n false,\n );\n\n setAttributes(bgCircle, { cx, cy, r: inner > 0 ? inner : 0 });\n bgCircle.setAttribute('style', 'fill:var(--prism-bg,#fff)');\n\n while (pieGroup.children.length > currentArcs.length) pieGroup.removeChild(pieGroup.lastChild!);\n\n labelGroup.replaceChildren();\n\n const motion = resolveMotion(config.transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n for (let i = 0; i < currentArcs.length; i++) {\n const arc = currentArcs[i];\n let path = pieGroup.children[i] as SVGPathElement | undefined;\n\n if (!path) {\n path = createSvgElement('path', { class: 'prism-pie-slice' });\n pieGroup.appendChild(path);\n }\n\n path.setAttribute('fill', arc.color);\n path.setAttribute('stroke', 'none');\n path.style.cursor = config.onClick || config.onHover ? 'pointer' : '';\n }\n\n activeTween?.();\n\n activeTween = startTween({\n count: 1,\n duration: dur,\n easing,\n onComplete: () => renderLabels(slices),\n onFrame: (progress) => {\n const revealAngle = tweenNumber(start, end, progress(0));\n\n for (let j = 0; j < currentArcs.length; j++) {\n const a = currentArcs[j];\n const el = pieGroup.children[j] as SVGPathElement | undefined;\n\n if (!el) continue;\n\n if (revealAngle <= a.startAngle) {\n setAttributes(el, { d: '' });\n } else {\n const visibleEnd = Math.min(a.endAngle, revealAngle);\n\n setAttributes(el, { d: arcPath({ ...a, endAngle: visibleEnd }) });\n }\n }\n },\n signal: ctx.disposalSignal,\n });\n\n legend?.update(currentArcs.map((arc) => ({ color: arc.color, name: arc.slice.label ?? '' })));\n tooltip?.hide();\n\n const total = currentArcs.reduce((sum, arc) => sum + Math.max(0, arc.slice.value), 0);\n let activeIndex = -1;\n\n const describe = (arc: Arc): string => {\n const percent = total > 0 ? Math.round((Math.max(0, arc.slice.value) / total) * 1000) / 10 : 0;\n\n return `${arc.slice.label ?? `Slice ${arc.index + 1}`}: ${arc.slice.value} (${percent}%)`;\n };\n\n const setActive = (index: number): void => {\n activeIndex = index;\n pieGroup.classList.toggle('prism-pie-focused', index >= 0);\n for (const [i, el] of [...pieGroup.children].entries())\n el.classList.toggle('prism-pie-slice--active', i === index);\n };\n\n const activate = (index: number, originalEvent: Event): void => {\n const arc = currentArcs[index];\n\n if (!arc) return;\n\n setActive(index);\n config.onHover?.({ index, originalEvent, slice: arc.slice });\n\n const text = describe(arc);\n\n if (!tooltip) {\n ctx.announcer.announce(text);\n\n return;\n }\n\n const { x, y } = arcCentroid(arc);\n const svgRect = svg.getBoundingClientRect();\n const contR = container.getBoundingClientRect();\n\n tooltip.show(\n x + (svgRect.left - contR.left),\n y + (svgRect.top - contR.top),\n { key: index, value: arc.slice.value },\n { color: arc.color, data: [], name: arc.slice.label ?? '' },\n text,\n );\n };\n\n const deactivate = (): void => {\n setActive(-1);\n tooltip?.hide();\n ctx.announcer.clear();\n config.onHover?.(null);\n };\n\n const hitAt = (e: MouseEvent): number => {\n const svgRect = svg.getBoundingClientRect();\n\n return hitTestArc(currentArcs, e.clientX - svgRect.left, e.clientY - svgRect.top, variant);\n };\n\n const onMouseMove = (e: MouseEvent): void => {\n const hit = hitAt(e);\n\n if (hit >= 0) {\n if (hit !== activeIndex) activate(hit, e);\n } else if (activeIndex >= 0) {\n deactivate();\n }\n };\n\n const onClick = (e: MouseEvent): void => {\n if (!config.onClick) return;\n\n const hit = hitAt(e);\n\n if (hit >= 0) config.onClick({ index: hit, originalEvent: e, slice: currentArcs[hit].slice });\n };\n\n const onKeyDown = (e: KeyboardEvent): void => {\n const count = currentArcs.length;\n\n if (count === 0) return;\n\n const step: Record<string, number> = { ArrowDown: 1, ArrowLeft: -1, ArrowRight: 1, ArrowUp: -1 };\n\n if (e.key in step) {\n e.preventDefault();\n activate(\n activeIndex < 0 ? (step[e.key] > 0 ? 0 : count - 1) : (activeIndex + step[e.key] + count) % count,\n e,\n );\n } else if (e.key === 'Home' || e.key === 'End') {\n e.preventDefault();\n activate(e.key === 'Home' ? 0 : count - 1, e);\n } else if ((e.key === 'Enter' || e.key === ' ') && activeIndex >= 0 && config.onClick) {\n e.preventDefault();\n config.onClick({ index: activeIndex, originalEvent: e, slice: currentArcs[activeIndex].slice });\n } else if (e.key === 'Escape') {\n deactivate();\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave: deactivate, onMouseMove };\n },\n (next) => {\n data = next;\n },\n );\n}\n\nfunction hitTestArc(arcs: Arc[], mx: number, my: number, variant: PieChartConfig['variant']): number {\n for (let i = 0; i < arcs.length; i++) {\n const arc = arcs[i];\n const dx = mx - arc.centerX;\n const dy = my - arc.centerY;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n if (dist < arc.outerRadius && dist >= arc.innerRadius) {\n const rawAngle = Math.atan2(dx, -dy);\n\n if (variant === 'semi') {\n if (rawAngle >= arc.startAngle - 1e-9 && rawAngle <= arc.endAngle + 1e-9) return i;\n } else {\n const angle = rawAngle < 0 ? rawAngle + TWO_PI : rawAngle;\n\n if (angle >= arc.startAngle - 1e-9 && angle <= arc.endAngle + 1e-9) return i;\n }\n }\n }\n\n return -1;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"pie-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/pie/pie-chart.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAuB/E,wBAAgB,cAAc,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,GAAG,WAAW,CAAC,cAAc,EAAE,CAAC,CAkT5G"}
1
+ {"version":3,"file":"pie-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/pie/pie-chart.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAuB/E,wBAAgB,cAAc,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,GAAG,WAAW,CAAC,cAAc,EAAE,CAAC,CA4P5G"}
@@ -1,2 +1,2 @@
1
- import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{estimateTextWidth as n}from"../../svg/text.js";import{createRadialScaffold as r}from"../../core/chart-scaffold.js";import{seriesColor as i}from"../../theme/index.js";import{resolveEasing as a}from"../../animation/easing.js";import{resolveMotion as o}from"../../animation/motion.js";import{tweenNumber as s}from"../../animation/tween.js";import{arcCentroid as c,arcPath as l,computeArcs as u}from"./pie-renderer.js";var d=2*Math.PI,f=12;function labelFits(e,t){let r=e.outerRadius-e.innerRadius,i=(e.outerRadius+e.innerRadius)/2,a=(e.endAngle-e.startAngle-2*e.padAngle)*i;return r>=f*1.4&&a>=n(t,f)+8}var p=-Math.PI/2,m=Math.PI/2;function semiAngles(e){return e===`semi`?{end:m,start:p}:{end:d,start:0}}function createPieChart(n,d){let f=d.variant??`pie`,p=d.padPixels??(f===`pie`?0:8),m=d.cornerRadius??(f===`pie`?0:8),h=d.data,g=e(`circle`,{class:`prism-pie-bg`,"pointer-events":`none`}),_=e(`g`,{class:`prism-pie-slices`,"shape-rendering":`geometricPrecision`}),v=e(`g`,{class:`prism-pie-labels`,"pointer-events":`none`}),y=[],b=null;function renderLabels(n){v.replaceChildren();for(let r=0;r<y.length;r++){let i=y[r],a=n[r];if(!a?.label||!labelFits(i,a.label))continue;let{x:o,y:s}=c(i),l=e(`text`,{class:`prism-pie-label`});t(l,{"dominant-baseline":`middle`,fill:`var(--prism-pie-label-color, #fff)`,"font-family":`var(--prism-font-family, system-ui)`,"font-size":`var(--prism-pie-label-size, 12px)`,"text-anchor":`middle`,x:o,y:s}),l.textContent=a.label,v.appendChild(l)}}let x;try{return x=r(n,{a11y:d.a11y,legend:d.legend,tooltip:d.tooltip},r=>{let{legend:x,svg:S,tooltip:C}=r;S.contains(g)||(S.appendChild(g),S.appendChild(_),S.appendChild(v));let{height:w,width:T}=r.dimensions,E=f===`semi`,D=T/2,O=E?w*.85:w/2,k=E?Math.min(D,O)-8:Math.min(T,w)/2-8,A=f===`pie`?0:Math.round(k*.55),j=d.innerRadius===void 0?A:d.innerRadius,M=Math.max(j+1,k),N=h,{end:P,start:F}=semiAngles(f);for(y=u(N,D,O,M,j,F,P,p,m,e=>i(e),!1),t(g,{cx:D,cy:O,r:j>0?j:0}),g.setAttribute(`style`,`fill:var(--prism-bg,#fff)`);_.children.length>y.length;)_.removeChild(_.lastChild);v.replaceChildren();let I=o(d.transition,0),L=I.duration,R=a(I.easing);for(let t=0;t<y.length;t++){let n=y[t],r=_.children[t];r||(r=e(`path`,{class:`prism-pie-slice`}),_.appendChild(r)),r.setAttribute(`fill`,n.color),r.setAttribute(`stroke`,`none`),r.style.cursor=d.onClick||d.onHover?`pointer`:``}if(b!==null&&(cancelAnimationFrame(b),b=null),L>0){let e=null,frame=n=>{e===null&&(e=n);let r=R(Math.min(1,(n-e)/L)),i=s(F,P,r);for(let e=0;e<y.length;e++){let n=y[e],r=_.children[e];if(r){if(i<=n.startAngle)t(r,{d:``});else{let e=Math.min(n.endAngle,i);t(r,{d:l({...n,endAngle:e})})}}}r<1?b=requestAnimationFrame(frame):(b=null,renderLabels(N))};b=requestAnimationFrame(frame)}else{for(let e=0;e<y.length;e++){let n=y[e],r=_.children[e];r&&t(r,{d:l(n)})}renderLabels(N)}x?.update(y.map(e=>({color:e.color,name:e.slice.label??``}))),C?.hide();let z=y.reduce((e,t)=>e+Math.max(0,t.slice.value),0),B=-1,describe=e=>{let t=z>0?Math.round(Math.max(0,e.slice.value)/z*1e3)/10:0;return`${e.slice.label??`Slice ${e.index+1}`}: ${e.slice.value} (${t}%)`},setActive=e=>{B=e,_.classList.toggle(`prism-pie-focused`,e>=0);for(let[t,n]of[..._.children].entries())n.classList.toggle(`prism-pie-slice--active`,t===e)},activate=e=>{let t=y[e];if(!t)return;setActive(e),d.onHover?.(t.slice,e);let i=describe(t);if(!C){r.announcer.announce(i);return}let{x:a,y:o}=c(t),s=S.getBoundingClientRect(),l=n.getBoundingClientRect();C.show(a+(s.left-l.left),o+(s.top-l.top),{key:e,value:t.slice.value},{color:t.color,data:[],name:t.slice.label??``},i)},deactivate=()=>{setActive(-1),C?.hide(),r.announcer.clear(),d.onHover?.(null,null)},hitAt=e=>{let t=S.getBoundingClientRect();return hitTestArc(y,e.clientX-t.left,e.clientY-t.top,f)},onMouseMove=e=>{let t=hitAt(e);t>=0?t!==B&&activate(t):B>=0&&deactivate()},onClick=e=>{if(!d.onClick)return;let t=hitAt(e);t>=0&&d.onClick(y[t].slice,t)},onKeyDown=e=>{let t=y.length;if(t===0)return;let n={ArrowDown:1,ArrowLeft:-1,ArrowRight:1,ArrowUp:-1};e.key in n?(e.preventDefault(),activate(B<0?n[e.key]>0?0:t-1:(B+n[e.key]+t)%t)):e.key===`Home`||e.key===`End`?(e.preventDefault(),activate(e.key===`Home`?0:t-1)):(e.key===`Enter`||e.key===` `)&&B>=0&&d.onClick?(e.preventDefault(),d.onClick(y[B].slice,B)):e.key===`Escape`&&deactivate()};return{onClick,onKeyDown,onMouseLeave:deactivate,onMouseMove}},e=>{h=e}),{get disposalSignal(){return x.disposalSignal},dispose(){b!==null&&(cancelAnimationFrame(b),b=null),x.dispose()},get disposed(){return x.disposed},el:x.el,update(e){x.update(e)},[Symbol.dispose](){this.dispose()}}}catch(e){throw x?.dispose(),e}}function hitTestArc(e,t,n,r){for(let i=0;i<e.length;i++){let a=e[i],o=t-a.centerX,s=n-a.centerY,c=Math.sqrt(o*o+s*s);if(c<a.outerRadius&&c>=a.innerRadius){let e=Math.atan2(o,-s);if(r===`semi`){if(e>=a.startAngle-1e-9&&e<=a.endAngle+1e-9)return i}else{let t=e<0?e+d:e;if(t>=a.startAngle-1e-9&&t<=a.endAngle+1e-9)return i}}}return-1}export{createPieChart};
1
+ import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{estimateTextWidth as n}from"../../svg/text.js";import{createRadialScaffold as r}from"../../core/chart-scaffold.js";import{seriesColor as i}from"../../theme/index.js";import{resolveEasing as a}from"../../animation/easing.js";import{resolveMotion as o}from"../../animation/motion.js";import{tweenNumber as s}from"../../animation/tween.js";import{startTween as c}from"../../animation/transition.js";import{arcCentroid as l,arcPath as u,computeArcs as d}from"./pie-renderer.js";var f=2*Math.PI,p=12;function labelFits(e,t){let r=e.outerRadius-e.innerRadius,i=(e.outerRadius+e.innerRadius)/2,a=(e.endAngle-e.startAngle-2*e.padAngle)*i;return r>=p*1.4&&a>=n(t,p)+8}var m=-Math.PI/2,h=Math.PI/2;function semiAngles(e){return e===`semi`?{end:h,start:m}:{end:f,start:0}}function createPieChart(n,f){let p=f.variant??`pie`,m=f.padPixels??(p===`pie`?0:8),h=f.cornerRadius??(p===`pie`?0:8),g=f.data,_=e(`circle`,{class:`prism-pie-bg`,"pointer-events":`none`}),v=e(`g`,{class:`prism-pie-slices`,"shape-rendering":`geometricPrecision`}),y=e(`g`,{class:`prism-pie-labels`,"pointer-events":`none`}),b=[],x=null;function renderLabels(n){y.replaceChildren();for(let r=0;r<b.length;r++){let i=b[r],a=n[r];if(!a?.label||!labelFits(i,a.label))continue;let{x:o,y:s}=l(i),c=e(`text`,{class:`prism-pie-label`});t(c,{"dominant-baseline":`middle`,fill:`var(--prism-pie-label-color, #fff)`,"font-family":`var(--prism-font-family, system-ui)`,"font-size":`var(--prism-pie-label-size, 12px)`,"text-anchor":`middle`,x:o,y:s}),c.textContent=a.label,y.appendChild(c)}}return r(n,{a11y:f.a11y,legend:f.legend,tooltip:f.tooltip},r=>{let{legend:S,svg:C,tooltip:w}=r;C.contains(_)||(C.appendChild(_),C.appendChild(v),C.appendChild(y));let{height:T,width:E}=r.dimensions,D=p===`semi`,O=E/2,k=D?T*.85:T/2,A=D?Math.min(O,k)-8:Math.min(E,T)/2-8,j=p===`pie`?0:Math.round(A*.55),M=f.innerRadius===void 0?j:f.innerRadius,N=Math.max(M+1,A),P=g,{end:F,start:I}=semiAngles(p);for(b=d(P,O,k,N,M,I,F,m,h,e=>i(e),!1),t(_,{cx:O,cy:k,r:M>0?M:0}),_.setAttribute(`style`,`fill:var(--prism-bg,#fff)`);v.children.length>b.length;)v.removeChild(v.lastChild);y.replaceChildren();let L=o(f.transition,0),R=L.duration,z=a(L.easing);for(let t=0;t<b.length;t++){let n=b[t],r=v.children[t];r||(r=e(`path`,{class:`prism-pie-slice`}),v.appendChild(r)),r.setAttribute(`fill`,n.color),r.setAttribute(`stroke`,`none`),r.style.cursor=f.onClick||f.onHover?`pointer`:``}x?.(),x=c({count:1,duration:R,easing:z,onComplete:()=>renderLabels(P),onFrame:e=>{let n=s(I,F,e(0));for(let e=0;e<b.length;e++){let r=b[e],i=v.children[e];if(i){if(n<=r.startAngle)t(i,{d:``});else{let e=Math.min(r.endAngle,n);t(i,{d:u({...r,endAngle:e})})}}}},signal:r.disposalSignal}),S?.update(b.map(e=>({color:e.color,name:e.slice.label??``}))),w?.hide();let B=b.reduce((e,t)=>e+Math.max(0,t.slice.value),0),V=-1,describe=e=>{let t=B>0?Math.round(Math.max(0,e.slice.value)/B*1e3)/10:0;return`${e.slice.label??`Slice ${e.index+1}`}: ${e.slice.value} (${t}%)`},setActive=e=>{V=e,v.classList.toggle(`prism-pie-focused`,e>=0);for(let[t,n]of[...v.children].entries())n.classList.toggle(`prism-pie-slice--active`,t===e)},activate=(e,t)=>{let i=b[e];if(!i)return;setActive(e),f.onHover?.({index:e,originalEvent:t,slice:i.slice});let a=describe(i);if(!w){r.announcer.announce(a);return}let{x:o,y:s}=l(i),c=C.getBoundingClientRect(),u=n.getBoundingClientRect();w.show(o+(c.left-u.left),s+(c.top-u.top),{key:e,value:i.slice.value},{color:i.color,data:[],name:i.slice.label??``},a)},deactivate=()=>{setActive(-1),w?.hide(),r.announcer.clear(),f.onHover?.(null)},hitAt=e=>{let t=C.getBoundingClientRect();return hitTestArc(b,e.clientX-t.left,e.clientY-t.top,p)},onMouseMove=e=>{let t=hitAt(e);t>=0?t!==V&&activate(t,e):V>=0&&deactivate()},onClick=e=>{if(!f.onClick)return;let t=hitAt(e);t>=0&&f.onClick({index:t,originalEvent:e,slice:b[t].slice})},onKeyDown=e=>{let t=b.length;if(t===0)return;let n={ArrowDown:1,ArrowLeft:-1,ArrowRight:1,ArrowUp:-1};e.key in n?(e.preventDefault(),activate(V<0?n[e.key]>0?0:t-1:(V+n[e.key]+t)%t,e)):e.key===`Home`||e.key===`End`?(e.preventDefault(),activate(e.key===`Home`?0:t-1,e)):(e.key===`Enter`||e.key===` `)&&V>=0&&f.onClick?(e.preventDefault(),f.onClick({index:V,originalEvent:e,slice:b[V].slice})):e.key===`Escape`&&deactivate()};return{onClick,onKeyDown,onMouseLeave:deactivate,onMouseMove}},e=>{g=e})}function hitTestArc(e,t,n,r){for(let i=0;i<e.length;i++){let a=e[i],o=t-a.centerX,s=n-a.centerY,c=Math.sqrt(o*o+s*s);if(c<a.outerRadius&&c>=a.innerRadius){let e=Math.atan2(o,-s);if(r===`semi`){if(e>=a.startAngle-1e-9&&e<=a.endAngle+1e-9)return i}else{let t=e<0?e+f:e;if(t>=a.startAngle-1e-9&&t<=a.endAngle+1e-9)return i}}}return-1}export{createPieChart};
2
2
  //# sourceMappingURL=pie-chart.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pie-chart.js","names":[],"sources":["../../../src/charts/pie/pie-chart.ts"],"sourcesContent":["import { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport type { ChartEventHandlers } from '../../core/chart-scaffold';\nimport { createRadialScaffold } from '../../core/chart-scaffold';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { estimateTextWidth } from '../../svg/text';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, PieChartConfig, PieSliceConfig } from '../../types';\nimport { type Arc, arcCentroid, arcPath, computeArcs } from './pie-renderer';\n\nconst TWO_PI = 2 * Math.PI;\n/** Default `--prism-pie-label-size` in px, used to decide whether a label fits its slice. */\nconst LABEL_FONT_SIZE = 12;\n\n/** A label fits when its slice is wide enough along the centroid arc and thick enough radially. */\nfunction labelFits(arc: Arc, label: string): boolean {\n const thickness = arc.outerRadius - arc.innerRadius;\n const midRadius = (arc.outerRadius + arc.innerRadius) / 2;\n const arcLength = (arc.endAngle - arc.startAngle - 2 * arc.padAngle) * midRadius;\n\n return thickness >= LABEL_FONT_SIZE * 1.4 && arcLength >= estimateTextWidth(label, LABEL_FONT_SIZE) + 8;\n}\n\nconst SEMI_START = -Math.PI / 2; // -90° = 9-o'clock (left)\nconst SEMI_END = Math.PI / 2; // +90° = 3-o'clock (right) → true 180° half-circle\n\nfunction semiAngles(variant: PieChartConfig['variant']): { end: number; start: number } {\n return variant === 'semi' ? { end: SEMI_END, start: SEMI_START } : { end: TWO_PI, start: 0 };\n}\n\nexport function createPieChart(container: HTMLElement, config: PieChartConfig): ChartHandle<PieSliceConfig[]> {\n const variant = config.variant ?? 'pie';\n const padPixels = config.padPixels ?? (variant === 'pie' ? 0 : 8);\n const cornerRadius = config.cornerRadius ?? (variant === 'pie' ? 0 : 8);\n let data = config.data;\n\n // Pie SVG elements live directly on the SVG (not inside chartArea groups).\n // We create them once and reuse across renders.\n const bgCircle = createSvgElement('circle', { class: 'prism-pie-bg', 'pointer-events': 'none' });\n const pieGroup = createSvgElement('g', {\n class: 'prism-pie-slices',\n 'shape-rendering': 'geometricPrecision',\n });\n const labelGroup = createSvgElement('g', { class: 'prism-pie-labels', 'pointer-events': 'none' });\n\n // Current arcs shared between renderFn and event handlers via closure.\n let currentArcs: Arc[] = [];\n let activeRaf: number | null = null;\n\n function renderLabels(slices: PieSliceConfig[]): void {\n labelGroup.replaceChildren();\n\n for (let i = 0; i < currentArcs.length; i++) {\n const arc = currentArcs[i];\n const slice = slices[i];\n\n if (!slice?.label || !labelFits(arc, slice.label)) continue;\n\n const { x, y } = arcCentroid(arc);\n const text = createSvgElement('text', { class: 'prism-pie-label' });\n\n setAttributes(text, {\n 'dominant-baseline': 'middle',\n fill: 'var(--prism-pie-label-color, #fff)',\n 'font-family': 'var(--prism-font-family, system-ui)',\n 'font-size': 'var(--prism-pie-label-size, 12px)',\n 'text-anchor': 'middle',\n x,\n y,\n });\n\n text.textContent = slice.label;\n labelGroup.appendChild(text);\n }\n }\n\n let handle: ChartHandle<PieSliceConfig[]> | undefined;\n\n try {\n handle = createRadialScaffold(\n container,\n {\n a11y: config.a11y,\n legend: config.legend,\n tooltip: config.tooltip,\n },\n (ctx): ChartEventHandlers => {\n const { legend, svg, tooltip } = ctx;\n\n // Append pie groups to SVG on first render (idempotent).\n if (!svg.contains(bgCircle)) {\n svg.appendChild(bgCircle);\n svg.appendChild(pieGroup);\n svg.appendChild(labelGroup);\n }\n\n const { height: h, width: w } = ctx.dimensions;\n const isSemi = variant === 'semi';\n const cx = w / 2;\n const cy = isSemi ? h * 0.85 : h / 2;\n const padding = 8;\n const outer = isSemi ? Math.min(cx, cy) - padding : Math.min(w, h) / 2 - padding;\n const defaultInner = variant === 'pie' ? 0 : Math.round(outer * 0.55);\n const inner = config.innerRadius !== undefined ? config.innerRadius : defaultInner;\n const outerR = Math.max(inner + 1, outer);\n\n const slices = data;\n const { end, start } = semiAngles(variant);\n\n currentArcs = computeArcs(\n slices,\n cx,\n cy,\n outerR,\n inner,\n start,\n end,\n padPixels,\n cornerRadius,\n (i) => seriesColor(i),\n false,\n );\n\n setAttributes(bgCircle, { cx, cy, r: inner > 0 ? inner : 0 });\n bgCircle.setAttribute('style', 'fill:var(--prism-bg,#fff)');\n\n while (pieGroup.children.length > currentArcs.length) pieGroup.removeChild(pieGroup.lastChild!);\n\n labelGroup.replaceChildren();\n\n const motion = resolveMotion(config.transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n for (let i = 0; i < currentArcs.length; i++) {\n const arc = currentArcs[i];\n let path = pieGroup.children[i] as SVGPathElement | undefined;\n\n if (!path) {\n path = createSvgElement('path', { class: 'prism-pie-slice' });\n pieGroup.appendChild(path);\n }\n\n path.setAttribute('fill', arc.color);\n path.setAttribute('stroke', 'none');\n path.style.cursor = config.onClick || config.onHover ? 'pointer' : '';\n }\n\n if (activeRaf !== null) {\n cancelAnimationFrame(activeRaf);\n activeRaf = null;\n }\n\n if (dur > 0) {\n let rafStart: number | null = null;\n\n const frame = (ts: number) => {\n if (rafStart === null) rafStart = ts;\n\n const t = easing(Math.min(1, (ts - rafStart) / dur));\n const revealAngle = tweenNumber(start, end, t);\n\n for (let j = 0; j < currentArcs.length; j++) {\n const a = currentArcs[j];\n const el = pieGroup.children[j] as SVGPathElement | undefined;\n\n if (!el) continue;\n\n if (revealAngle <= a.startAngle) {\n setAttributes(el, { d: '' });\n } else {\n const visibleEnd = Math.min(a.endAngle, revealAngle);\n\n setAttributes(el, { d: arcPath({ ...a, endAngle: visibleEnd }) });\n }\n }\n\n if (t < 1) {\n activeRaf = requestAnimationFrame(frame);\n } else {\n activeRaf = null;\n renderLabels(slices);\n }\n };\n\n activeRaf = requestAnimationFrame(frame);\n } else {\n for (let j = 0; j < currentArcs.length; j++) {\n const a = currentArcs[j];\n const el = pieGroup.children[j] as SVGPathElement | undefined;\n\n if (el) setAttributes(el, { d: arcPath(a) });\n }\n\n renderLabels(slices);\n }\n\n legend?.update(currentArcs.map((arc) => ({ color: arc.color, name: arc.slice.label ?? '' })));\n tooltip?.hide();\n\n const total = currentArcs.reduce((sum, arc) => sum + Math.max(0, arc.slice.value), 0);\n let activeIndex = -1;\n\n const describe = (arc: Arc): string => {\n const percent = total > 0 ? Math.round((Math.max(0, arc.slice.value) / total) * 1000) / 10 : 0;\n\n return `${arc.slice.label ?? `Slice ${arc.index + 1}`}: ${arc.slice.value} (${percent}%)`;\n };\n\n const setActive = (index: number): void => {\n activeIndex = index;\n pieGroup.classList.toggle('prism-pie-focused', index >= 0);\n for (const [i, el] of [...pieGroup.children].entries())\n el.classList.toggle('prism-pie-slice--active', i === index);\n };\n\n const activate = (index: number): void => {\n const arc = currentArcs[index];\n\n if (!arc) return;\n\n setActive(index);\n config.onHover?.(arc.slice, index);\n\n const text = describe(arc);\n\n if (!tooltip) {\n ctx.announcer.announce(text);\n\n return;\n }\n\n const { x, y } = arcCentroid(arc);\n const svgRect = svg.getBoundingClientRect();\n const contR = container.getBoundingClientRect();\n\n tooltip.show(\n x + (svgRect.left - contR.left),\n y + (svgRect.top - contR.top),\n { key: index, value: arc.slice.value },\n { color: arc.color, data: [], name: arc.slice.label ?? '' },\n text,\n );\n };\n\n const deactivate = (): void => {\n setActive(-1);\n tooltip?.hide();\n ctx.announcer.clear();\n config.onHover?.(null, null);\n };\n\n const hitAt = (e: MouseEvent): number => {\n const svgRect = svg.getBoundingClientRect();\n\n return hitTestArc(currentArcs, e.clientX - svgRect.left, e.clientY - svgRect.top, variant);\n };\n\n const onMouseMove = (e: MouseEvent): void => {\n const hit = hitAt(e);\n\n if (hit >= 0) {\n if (hit !== activeIndex) activate(hit);\n } else if (activeIndex >= 0) {\n deactivate();\n }\n };\n\n const onClick = (e: MouseEvent): void => {\n if (!config.onClick) return;\n\n const hit = hitAt(e);\n\n if (hit >= 0) config.onClick(currentArcs[hit].slice, hit);\n };\n\n const onKeyDown = (e: KeyboardEvent): void => {\n const count = currentArcs.length;\n\n if (count === 0) return;\n\n const step: Record<string, number> = { ArrowDown: 1, ArrowLeft: -1, ArrowRight: 1, ArrowUp: -1 };\n\n if (e.key in step) {\n e.preventDefault();\n activate(activeIndex < 0 ? (step[e.key] > 0 ? 0 : count - 1) : (activeIndex + step[e.key] + count) % count);\n } else if (e.key === 'Home' || e.key === 'End') {\n e.preventDefault();\n activate(e.key === 'Home' ? 0 : count - 1);\n } else if ((e.key === 'Enter' || e.key === ' ') && activeIndex >= 0 && config.onClick) {\n e.preventDefault();\n config.onClick(currentArcs[activeIndex].slice, activeIndex);\n } else if (e.key === 'Escape') {\n deactivate();\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave: deactivate, onMouseMove };\n },\n (next) => {\n data = next;\n },\n );\n\n return {\n get disposalSignal(): AbortSignal {\n return handle!.disposalSignal;\n },\n\n dispose() {\n if (activeRaf !== null) {\n cancelAnimationFrame(activeRaf);\n activeRaf = null;\n }\n\n handle!.dispose();\n },\n\n get disposed(): boolean {\n return handle!.disposed;\n },\n\n el: handle!.el,\n\n update(next) {\n handle!.update(next);\n },\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n } catch (error) {\n handle?.dispose();\n throw error;\n }\n}\n\nfunction hitTestArc(arcs: Arc[], mx: number, my: number, variant: PieChartConfig['variant']): number {\n for (let i = 0; i < arcs.length; i++) {\n const arc = arcs[i];\n const dx = mx - arc.centerX;\n const dy = my - arc.centerY;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n if (dist < arc.outerRadius && dist >= arc.innerRadius) {\n const rawAngle = Math.atan2(dx, -dy);\n\n if (variant === 'semi') {\n if (rawAngle >= arc.startAngle - 1e-9 && rawAngle <= arc.endAngle + 1e-9) return i;\n } else {\n const angle = rawAngle < 0 ? rawAngle + TWO_PI : rawAngle;\n\n if (angle >= arc.startAngle - 1e-9 && angle <= arc.endAngle + 1e-9) return i;\n }\n }\n }\n\n return -1;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pie-chart.js","names":[],"sources":["../../../src/charts/pie/pie-chart.ts"],"sourcesContent":["import { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport type { ChartEventHandlers } from '../../core/chart-scaffold';\nimport { createRadialScaffold } from '../../core/chart-scaffold';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { estimateTextWidth } from '../../svg/text';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, PieChartConfig, PieSliceConfig } from '../../types';\nimport { type Arc, arcCentroid, arcPath, computeArcs } from './pie-renderer';\n\nconst TWO_PI = 2 * Math.PI;\n/** Default `--prism-pie-label-size` in px, used to decide whether a label fits its slice. */\nconst LABEL_FONT_SIZE = 12;\n\n/** A label fits when its slice is wide enough along the centroid arc and thick enough radially. */\nfunction labelFits(arc: Arc, label: string): boolean {\n const thickness = arc.outerRadius - arc.innerRadius;\n const midRadius = (arc.outerRadius + arc.innerRadius) / 2;\n const arcLength = (arc.endAngle - arc.startAngle - 2 * arc.padAngle) * midRadius;\n\n return thickness >= LABEL_FONT_SIZE * 1.4 && arcLength >= estimateTextWidth(label, LABEL_FONT_SIZE) + 8;\n}\n\nconst SEMI_START = -Math.PI / 2; // -90° = 9-o'clock (left)\nconst SEMI_END = Math.PI / 2; // +90° = 3-o'clock (right) → true 180° half-circle\n\nfunction semiAngles(variant: PieChartConfig['variant']): { end: number; start: number } {\n return variant === 'semi' ? { end: SEMI_END, start: SEMI_START } : { end: TWO_PI, start: 0 };\n}\n\nexport function createPieChart(container: HTMLElement, config: PieChartConfig): ChartHandle<PieSliceConfig[]> {\n const variant = config.variant ?? 'pie';\n const padPixels = config.padPixels ?? (variant === 'pie' ? 0 : 8);\n const cornerRadius = config.cornerRadius ?? (variant === 'pie' ? 0 : 8);\n let data = config.data;\n\n // Pie SVG elements live directly on the SVG (not inside chartArea groups).\n // We create them once and reuse across renders.\n const bgCircle = createSvgElement('circle', { class: 'prism-pie-bg', 'pointer-events': 'none' });\n const pieGroup = createSvgElement('g', {\n class: 'prism-pie-slices',\n 'shape-rendering': 'geometricPrecision',\n });\n const labelGroup = createSvgElement('g', { class: 'prism-pie-labels', 'pointer-events': 'none' });\n\n // Current arcs shared between renderFn and event handlers via closure.\n let currentArcs: Arc[] = [];\n let activeTween: (() => void) | null = null;\n\n function renderLabels(slices: PieSliceConfig[]): void {\n labelGroup.replaceChildren();\n\n for (let i = 0; i < currentArcs.length; i++) {\n const arc = currentArcs[i];\n const slice = slices[i];\n\n if (!slice?.label || !labelFits(arc, slice.label)) continue;\n\n const { x, y } = arcCentroid(arc);\n const text = createSvgElement('text', { class: 'prism-pie-label' });\n\n setAttributes(text, {\n 'dominant-baseline': 'middle',\n fill: 'var(--prism-pie-label-color, #fff)',\n 'font-family': 'var(--prism-font-family, system-ui)',\n 'font-size': 'var(--prism-pie-label-size, 12px)',\n 'text-anchor': 'middle',\n x,\n y,\n });\n\n text.textContent = slice.label;\n labelGroup.appendChild(text);\n }\n }\n\n return createRadialScaffold(\n container,\n {\n a11y: config.a11y,\n legend: config.legend,\n tooltip: config.tooltip,\n },\n (ctx): ChartEventHandlers => {\n const { legend, svg, tooltip } = ctx;\n\n // Append pie groups to SVG on first render (idempotent).\n if (!svg.contains(bgCircle)) {\n svg.appendChild(bgCircle);\n svg.appendChild(pieGroup);\n svg.appendChild(labelGroup);\n }\n\n const { height: h, width: w } = ctx.dimensions;\n const isSemi = variant === 'semi';\n const cx = w / 2;\n const cy = isSemi ? h * 0.85 : h / 2;\n const padding = 8;\n const outer = isSemi ? Math.min(cx, cy) - padding : Math.min(w, h) / 2 - padding;\n const defaultInner = variant === 'pie' ? 0 : Math.round(outer * 0.55);\n const inner = config.innerRadius !== undefined ? config.innerRadius : defaultInner;\n const outerR = Math.max(inner + 1, outer);\n\n const slices = data;\n const { end, start } = semiAngles(variant);\n\n currentArcs = computeArcs(\n slices,\n cx,\n cy,\n outerR,\n inner,\n start,\n end,\n padPixels,\n cornerRadius,\n (i) => seriesColor(i),\n false,\n );\n\n setAttributes(bgCircle, { cx, cy, r: inner > 0 ? inner : 0 });\n bgCircle.setAttribute('style', 'fill:var(--prism-bg,#fff)');\n\n while (pieGroup.children.length > currentArcs.length) pieGroup.removeChild(pieGroup.lastChild!);\n\n labelGroup.replaceChildren();\n\n const motion = resolveMotion(config.transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n for (let i = 0; i < currentArcs.length; i++) {\n const arc = currentArcs[i];\n let path = pieGroup.children[i] as SVGPathElement | undefined;\n\n if (!path) {\n path = createSvgElement('path', { class: 'prism-pie-slice' });\n pieGroup.appendChild(path);\n }\n\n path.setAttribute('fill', arc.color);\n path.setAttribute('stroke', 'none');\n path.style.cursor = config.onClick || config.onHover ? 'pointer' : '';\n }\n\n activeTween?.();\n\n activeTween = startTween({\n count: 1,\n duration: dur,\n easing,\n onComplete: () => renderLabels(slices),\n onFrame: (progress) => {\n const revealAngle = tweenNumber(start, end, progress(0));\n\n for (let j = 0; j < currentArcs.length; j++) {\n const a = currentArcs[j];\n const el = pieGroup.children[j] as SVGPathElement | undefined;\n\n if (!el) continue;\n\n if (revealAngle <= a.startAngle) {\n setAttributes(el, { d: '' });\n } else {\n const visibleEnd = Math.min(a.endAngle, revealAngle);\n\n setAttributes(el, { d: arcPath({ ...a, endAngle: visibleEnd }) });\n }\n }\n },\n signal: ctx.disposalSignal,\n });\n\n legend?.update(currentArcs.map((arc) => ({ color: arc.color, name: arc.slice.label ?? '' })));\n tooltip?.hide();\n\n const total = currentArcs.reduce((sum, arc) => sum + Math.max(0, arc.slice.value), 0);\n let activeIndex = -1;\n\n const describe = (arc: Arc): string => {\n const percent = total > 0 ? Math.round((Math.max(0, arc.slice.value) / total) * 1000) / 10 : 0;\n\n return `${arc.slice.label ?? `Slice ${arc.index + 1}`}: ${arc.slice.value} (${percent}%)`;\n };\n\n const setActive = (index: number): void => {\n activeIndex = index;\n pieGroup.classList.toggle('prism-pie-focused', index >= 0);\n for (const [i, el] of [...pieGroup.children].entries())\n el.classList.toggle('prism-pie-slice--active', i === index);\n };\n\n const activate = (index: number, originalEvent: Event): void => {\n const arc = currentArcs[index];\n\n if (!arc) return;\n\n setActive(index);\n config.onHover?.({ index, originalEvent, slice: arc.slice });\n\n const text = describe(arc);\n\n if (!tooltip) {\n ctx.announcer.announce(text);\n\n return;\n }\n\n const { x, y } = arcCentroid(arc);\n const svgRect = svg.getBoundingClientRect();\n const contR = container.getBoundingClientRect();\n\n tooltip.show(\n x + (svgRect.left - contR.left),\n y + (svgRect.top - contR.top),\n { key: index, value: arc.slice.value },\n { color: arc.color, data: [], name: arc.slice.label ?? '' },\n text,\n );\n };\n\n const deactivate = (): void => {\n setActive(-1);\n tooltip?.hide();\n ctx.announcer.clear();\n config.onHover?.(null);\n };\n\n const hitAt = (e: MouseEvent): number => {\n const svgRect = svg.getBoundingClientRect();\n\n return hitTestArc(currentArcs, e.clientX - svgRect.left, e.clientY - svgRect.top, variant);\n };\n\n const onMouseMove = (e: MouseEvent): void => {\n const hit = hitAt(e);\n\n if (hit >= 0) {\n if (hit !== activeIndex) activate(hit, e);\n } else if (activeIndex >= 0) {\n deactivate();\n }\n };\n\n const onClick = (e: MouseEvent): void => {\n if (!config.onClick) return;\n\n const hit = hitAt(e);\n\n if (hit >= 0) config.onClick({ index: hit, originalEvent: e, slice: currentArcs[hit].slice });\n };\n\n const onKeyDown = (e: KeyboardEvent): void => {\n const count = currentArcs.length;\n\n if (count === 0) return;\n\n const step: Record<string, number> = { ArrowDown: 1, ArrowLeft: -1, ArrowRight: 1, ArrowUp: -1 };\n\n if (e.key in step) {\n e.preventDefault();\n activate(\n activeIndex < 0 ? (step[e.key] > 0 ? 0 : count - 1) : (activeIndex + step[e.key] + count) % count,\n e,\n );\n } else if (e.key === 'Home' || e.key === 'End') {\n e.preventDefault();\n activate(e.key === 'Home' ? 0 : count - 1, e);\n } else if ((e.key === 'Enter' || e.key === ' ') && activeIndex >= 0 && config.onClick) {\n e.preventDefault();\n config.onClick({ index: activeIndex, originalEvent: e, slice: currentArcs[activeIndex].slice });\n } else if (e.key === 'Escape') {\n deactivate();\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave: deactivate, onMouseMove };\n },\n (next) => {\n data = next;\n },\n );\n}\n\nfunction hitTestArc(arcs: Arc[], mx: number, my: number, variant: PieChartConfig['variant']): number {\n for (let i = 0; i < arcs.length; i++) {\n const arc = arcs[i];\n const dx = mx - arc.centerX;\n const dy = my - arc.centerY;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n if (dist < arc.outerRadius && dist >= arc.innerRadius) {\n const rawAngle = Math.atan2(dx, -dy);\n\n if (variant === 'semi') {\n if (rawAngle >= arc.startAngle - 1e-9 && rawAngle <= arc.endAngle + 1e-9) return i;\n } else {\n const angle = rawAngle < 0 ? rawAngle + TWO_PI : rawAngle;\n\n if (angle >= arc.startAngle - 1e-9 && angle <= arc.endAngle + 1e-9) return i;\n }\n }\n }\n\n return -1;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../interaction/announcer.cjs"),n=require("../../interaction/tooltip.cjs"),r=require("../../core/chart-scaffold.cjs"),i=require("../../core/series-id.cjs"),a=require("../../theme/index.cjs"),o=require("../../animation/easing.cjs"),s=require("../../animation/motion.cjs"),c=require("../../animation/tween.cjs"),l=require("../../core/ids.cjs"),u=require("../../core/polar.cjs"),d=require("./radar-geometry.cjs");var f=11,p=12,m=10,h={ArrowDown:1,ArrowLeft:-1,ArrowRight:1,ArrowUp:-1};function resolveGrid(e){return e===!1?null:{bands:!0,labels:!1,levels:4,shape:`polygon`,...typeof e==`object`?e:{}}}function createRadarChart(g,_){let{axes:v}=_,y=_.curve??`linear`,b=_.fill??`solid`,x=_.showPoints??!0,S=resolveGrid(_.grid),C=d.toRadians(_.startAngle??0),w=d.axisAngles(v.length,C),T=p+(_.showValues?m:0),E=l.uniqueId(`prism-radar`),D=_.series,O=e.createSvgElement(`g`,{class:`prism-radar`}),k=e.createSvgElement(`defs`),A=e.createSvgElement(`g`,{"aria-hidden":`true`,class:`prism-radar-grid`}),j=e.createSvgElement(`g`,{class:`prism-radar-series-group`}),M=e.createSvgElement(`g`,{"aria-hidden":`true`,class:`prism-radar-labels`});O.append(k,A,j,M);let N=[],P=null,F=-1,I={cx:0,cy:0,radius:0},datumAt=(e,t)=>e.data.find(e=>e.key===v[t].key),valuesAt=e=>D.map(t=>({datum:datumAt(t,e),series:t})),formatValue=(e,t)=>v[e].format?.(t)??String(t),describe=e=>t.describeValues(v[e].label,valuesAt(e),t=>formatValue(e,t));function draw(t){let{cx:n,cy:r,radius:i}=I;t.forEach((t,a)=>{let o=j.children[a];if(!o)return;let s=d.radarPoints(t,n,r,i,w);o.querySelector(`.prism-radar-area`)?.setAttribute(`d`,d.closedPath(s,y)),o.querySelectorAll(`.prism-radar-point`).forEach((t,n)=>{e.setAttributes(t,{cx:s[n].x,cy:s[n].y})}),o.querySelectorAll(`.prism-radar-value`).forEach((a,o)=>{let s=i*t[o]+m;e.setAttributes(a,{x:u.polarX(n,s,w[o]),y:u.polarY(r,s,w[o])})})})}function renderGrid(t){if(A.replaceChildren(),!S)return;let{cx:n,cy:r,radius:i}=I,a=Math.max(1,Math.round(S.levels)),o=Array.from({length:a},(e,t)=>d.ringPath(S.shape,n,r,i*(t+1)/a,w));if(S.bands)for(let t=a-1;t>=0;t-=2)A.appendChild(e.createSvgElement(`path`,{class:`prism-radar-band`,d:`${o[t]}${o[t-1]??``}`,"fill-rule":`evenodd`}));for(let t of o)A.appendChild(e.createSvgElement(`path`,{class:`prism-radar-ring`,d:t,fill:`none`}));w.forEach((t,a)=>{A.appendChild(e.createSvgElement(`line`,{class:`prism-radar-spoke`,"data-axis":a,x1:n,x2:u.polarX(n,i,t),y1:r,y2:u.polarY(r,i,t)}))});let[s,c]=t[0],l=t.every(([e,t])=>e===s&&t===c);if(!S.labels||!l)return;let f=w[0]+Math.PI/w.length;for(let t=1;t<=a;t++){let o=i*t/a,l=e.createSvgElement(`text`,{class:`prism-radar-level`,"dominant-baseline":`middle`,"text-anchor":`middle`,x:u.polarX(n,o,f),y:u.polarY(r,o,f)});l.textContent=formatValue(0,Math.round((s+(c-s)*t/a)*100)/100),A.appendChild(l)}}function renderLabels(){M.replaceChildren();let{cx:t,cy:n,radius:r}=I;v.forEach((i,a)=>{let{anchor:o,baseline:s}=d.labelPlacement(w[a]),c=e.createSvgElement(`text`,{class:`prism-radar-axis-label`,"dominant-baseline":s,"text-anchor":o,x:u.polarX(t,r+T,w[a]),y:u.polarY(n,r+T,w[a])});c.textContent=i.label,M.appendChild(c)})}function renderSeries(){let{cx:t,cy:n,radius:r}=I;for(k.replaceChildren();j.children.length>D.length;)j.lastChild?.remove();D.forEach((o,s)=>{let c=o.color??a.seriesColor(s),l=j.children[s];l||(l=e.createSvgElement(`g`,{class:`prism-radar-series`}),j.appendChild(l)),l.setAttribute(`data-series-id`,i.seriesDomId(o,s)),l.replaceChildren();let u=e.createSvgElement(`path`,{class:`prism-radar-area prism-radar-area--${b}`,stroke:c,"stroke-linejoin":`round`,"stroke-width":2});if(b===`gradient`){let i=`${E}-fill-${s}`,a=e.createSvgElement(`radialGradient`,{cx:t,cy:n,gradientUnits:`userSpaceOnUse`,id:i,r});for(let[t,n]of[[0,.08],[1,.55]])a.appendChild(e.createSvgElement(`stop`,{offset:t,"stop-color":c,"stop-opacity":n,style:`stop-color:${c}`}));k.appendChild(a),e.setAttributes(u,{fill:`url(#${i})`})}else e.setAttributes(u,{fill:b===`none`?`none`:c,"fill-opacity":.25});l.appendChild(u),x&&v.forEach((t,n)=>{let r=!Number.isFinite(datumAt(o,n)?.value);l.appendChild(e.createSvgElement(`circle`,{class:`prism-radar-point${r?` prism-radar-point--missing`:``}`,"data-axis":n,fill:r?`none`:c,r:3,stroke:c}))}),_.showValues&&v.forEach((t,n)=>{let r=datumAt(o,n),{anchor:i,baseline:a}=d.labelPlacement(w[n]),s=e.createSvgElement(`text`,{"aria-hidden":`true`,class:`prism-radar-value`,"dominant-baseline":a,"text-anchor":i});s.textContent=r&&Number.isFinite(r.value)?formatValue(n,r.value):``,l.appendChild(s)})})}function setActive(e){F=e;for(let t of O.querySelectorAll(`[data-axis]`)){let n=Number(t.getAttribute(`data-axis`))===e;t.classList.toggle(t.tagName===`line`?`prism-radar-spoke--active`:`prism-radar-point--active`,n)}}function animateTo(e){P!==null&&(cancelAnimationFrame(P),P=null);let t=e.map((e,t)=>e.map((e,n)=>N[t]?.[n]??0)),n=s.resolveMotion(_.transition,400),r=o.resolveEasing(n.easing??`ease-out`),i=t.every((t,n)=>t.every((t,r)=>t===e[n][r]));if(n.duration===0||i){N=e,draw(e);return}let a=null,frame=i=>{a===null&&(a=i);let o=i-a,s=!0;N=e.map((e,i)=>{let a=Math.max(0,Math.min(1,(o-i*n.stagger)/n.duration));return a<1&&(s=!1),e.map((e,n)=>c.tweenNumber(t[i][n],e,r(a)))}),draw(N),P=s?null:requestAnimationFrame(frame)};P=requestAnimationFrame(frame)}let L;try{return L=r.createRadialScaffold(g,{a11y:_.a11y,legend:_.legend,tooltip:_.tooltip},e=>{let{legend:t,svg:r,tooltip:i}=e;if(r.contains(O)||r.appendChild(O),i?.hide(),t?.update(D.map((e,t)=>({color:e.color??a.seriesColor(t),name:e.name}))),v.length<3){for(let e of[k,A,j,M])e.replaceChildren();N=[];return}let{height:o,width:s}=e.dimensions,c=d.fitRadius(s,o,v.map(e=>e.label),w,f,T);I={cx:s/2,cy:o/2,radius:c};let l=d.resolveAxisDomains(v,D,_.domain);renderGrid(l),renderLabels(),renderSeries(),animateTo(D.map(e=>v.map((t,n)=>{let r=datumAt(e,n)?.value;return r!==void 0&&Number.isFinite(r)?d.normalize(r,l[n]):0}))),setActive(F);let eventFor=(e,t)=>({axis:v[e],index:e,originalEvent:t,values:valuesAt(e)}),activate=(t,o)=>{setActive(t),_.onHover?.(eventFor(t,o));let s=describe(t);if(!i){e.announcer.announce(s);return}let c=Math.max(0,...N.map(e=>e[t]??0)),l=r.getBoundingClientRect(),d=g.getBoundingClientRect(),f=valuesAt(t),p=f.find(e=>e.datum)?.datum,m=f.flatMap(({datum:e,series:n})=>e?[{color:n.color??a.seriesColor(D.indexOf(n)),name:n.name,value:formatValue(t,e.value)}]:[]);i.show(u.polarX(I.cx,I.radius*c,w[t])+(l.left-d.left),u.polarY(I.cy,I.radius*c,w[t])+(l.top-d.top),{key:v[t].key,meta:{axis:v[t],text:s,values:f},value:p?.value??0},{color:D[0]?.color??a.seriesColor(0),data:[],name:v[t].label},n.comparisonContent(r.ownerDocument,v[t].label,m,s))},deactivate=()=>{setActive(-1),_.onHover?.(null),i?.hide(),e.announcer.clear()},hitIndex=e=>{let t=r.getBoundingClientRect(),n=e.clientX-t.left-I.cx,i=e.clientY-t.top-I.cy;return Math.hypot(n,i)>I.radius+T+22?-1:d.nearestAxis(n,i,v.length,C)};return{onClick(e){let t=hitIndex(e);t>=0&&_.onClick?.(eventFor(t,e))},onKeyDown(e){let t=h[e.key];t===void 0?(e.key===`Enter`||e.key===` `)&&F>=0&&_.onClick?(e.preventDefault(),_.onClick(eventFor(F,e))):e.key===`Escape`&&deactivate():(e.preventDefault(),activate(F<0?0:(F+t+v.length)%v.length,e))},onMouseLeave:deactivate,onMouseMove(e){let t=hitIndex(e);t<0?F>=0&&deactivate():t!==F&&activate(t,e)}}},e=>{D=e}),{get disposalSignal(){return L.disposalSignal},dispose(){P!==null&&(cancelAnimationFrame(P),P=null),L.dispose()},get disposed(){return L.disposed},el:L.el,update(e){L.update(e)},[Symbol.dispose](){this.dispose()}}}catch(e){throw L?.dispose(),e}}exports.createRadarChart=createRadarChart;
1
+ require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../interaction/announcer.cjs"),n=require("../../interaction/tooltip.cjs"),r=require("../../core/chart-scaffold.cjs"),i=require("../../core/series-id.cjs"),a=require("../../theme/index.cjs"),o=require("../../animation/easing.cjs"),s=require("../../animation/motion.cjs"),c=require("../../animation/tween.cjs"),l=require("../../animation/transition.cjs"),u=require("../../core/ids.cjs"),d=require("../../core/polar.cjs"),f=require("./radar-geometry.cjs");var p=11,m=12,h=10,g={ArrowDown:1,ArrowLeft:-1,ArrowRight:1,ArrowUp:-1};function resolveGrid(e){return e===!1?null:{bands:!0,labels:!1,levels:4,shape:`polygon`,...typeof e==`object`?e:{}}}function createRadarChart(_,v){let{axes:y}=v,b=v.curve??`linear`,x=v.fill??`solid`,S=v.showPoints??!0,C=resolveGrid(v.grid),w=f.toRadians(v.startAngle??0),T=f.axisAngles(y.length,w),E=m+(v.showValues?h:0),D=u.uniqueId(`prism-radar`),O=v.series,k=e.createSvgElement(`g`,{class:`prism-radar`}),A=e.createSvgElement(`defs`),j=e.createSvgElement(`g`,{"aria-hidden":`true`,class:`prism-radar-grid`}),M=e.createSvgElement(`g`,{class:`prism-radar-series-group`}),N=e.createSvgElement(`g`,{"aria-hidden":`true`,class:`prism-radar-labels`});k.append(A,j,M,N);let P=[],F=null,I=-1,L={cx:0,cy:0,radius:0},datumAt=(e,t)=>e.data.find(e=>e.key===y[t].key),valuesAt=e=>O.map(t=>({datum:datumAt(t,e),series:t})),formatValue=(e,t)=>y[e].format?.(t)??String(t),describe=e=>t.describeValues(y[e].label,valuesAt(e),t=>formatValue(e,t));function draw(t){let{cx:n,cy:r,radius:i}=L;t.forEach((t,a)=>{let o=M.children[a];if(!o)return;let s=f.radarPoints(t,n,r,i,T);o.querySelector(`.prism-radar-area`)?.setAttribute(`d`,f.closedPath(s,b)),o.querySelectorAll(`.prism-radar-point`).forEach((t,n)=>{e.setAttributes(t,{cx:s[n].x,cy:s[n].y})}),o.querySelectorAll(`.prism-radar-value`).forEach((a,o)=>{let s=i*t[o]+h;e.setAttributes(a,{x:d.polarX(n,s,T[o]),y:d.polarY(r,s,T[o])})})})}function renderGrid(t){if(j.replaceChildren(),!C)return;let{cx:n,cy:r,radius:i}=L,a=Math.max(1,Math.round(C.levels)),o=Array.from({length:a},(e,t)=>f.ringPath(C.shape,n,r,i*(t+1)/a,T));if(C.bands)for(let t=a-1;t>=0;t-=2)j.appendChild(e.createSvgElement(`path`,{class:`prism-radar-band`,d:`${o[t]}${o[t-1]??``}`,"fill-rule":`evenodd`}));for(let t of o)j.appendChild(e.createSvgElement(`path`,{class:`prism-radar-ring`,d:t,fill:`none`}));T.forEach((t,a)=>{j.appendChild(e.createSvgElement(`line`,{class:`prism-radar-spoke`,"data-axis":a,x1:n,x2:d.polarX(n,i,t),y1:r,y2:d.polarY(r,i,t)}))});let[s,c]=t[0],l=t.every(([e,t])=>e===s&&t===c);if(!C.labels||!l)return;let u=T[0]+Math.PI/T.length;for(let t=1;t<=a;t++){let o=i*t/a,l=e.createSvgElement(`text`,{class:`prism-radar-level`,"dominant-baseline":`middle`,"text-anchor":`middle`,x:d.polarX(n,o,u),y:d.polarY(r,o,u)});l.textContent=formatValue(0,Math.round((s+(c-s)*t/a)*100)/100),j.appendChild(l)}}function renderLabels(){N.replaceChildren();let{cx:t,cy:n,radius:r}=L;y.forEach((i,a)=>{let{anchor:o,baseline:s}=f.labelPlacement(T[a]),c=e.createSvgElement(`text`,{class:`prism-radar-axis-label`,"dominant-baseline":s,"text-anchor":o,x:d.polarX(t,r+E,T[a]),y:d.polarY(n,r+E,T[a])});c.textContent=i.label,N.appendChild(c)})}function renderSeries(){let{cx:t,cy:n,radius:r}=L;for(A.replaceChildren();M.children.length>O.length;)M.lastChild?.remove();O.forEach((o,s)=>{let c=o.color??a.seriesColor(s),l=M.children[s];l||(l=e.createSvgElement(`g`,{class:`prism-radar-series`}),M.appendChild(l)),l.setAttribute(`data-series-id`,i.seriesDomId(o,s)),l.replaceChildren();let u=e.createSvgElement(`path`,{class:`prism-radar-area prism-radar-area--${x}`,stroke:c,"stroke-linejoin":`round`,"stroke-width":2});if(x===`gradient`){let i=`${D}-fill-${s}`,a=e.createSvgElement(`radialGradient`,{cx:t,cy:n,gradientUnits:`userSpaceOnUse`,id:i,r});for(let[t,n]of[[0,.08],[1,.55]])a.appendChild(e.createSvgElement(`stop`,{offset:t,"stop-color":c,"stop-opacity":n,style:`stop-color:${c}`}));A.appendChild(a),e.setAttributes(u,{fill:`url(#${i})`})}else e.setAttributes(u,{fill:x===`none`?`none`:c,"fill-opacity":.25});l.appendChild(u),S&&y.forEach((t,n)=>{let r=!Number.isFinite(datumAt(o,n)?.value);l.appendChild(e.createSvgElement(`circle`,{class:`prism-radar-point${r?` prism-radar-point--missing`:``}`,"data-axis":n,fill:r?`none`:c,r:3,stroke:c}))}),v.showValues&&y.forEach((t,n)=>{let r=datumAt(o,n),{anchor:i,baseline:a}=f.labelPlacement(T[n]),s=e.createSvgElement(`text`,{"aria-hidden":`true`,class:`prism-radar-value`,"dominant-baseline":a,"text-anchor":i});s.textContent=r&&Number.isFinite(r.value)?formatValue(n,r.value):``,l.appendChild(s)})})}function setActive(e){I=e;for(let t of k.querySelectorAll(`[data-axis]`)){let n=Number(t.getAttribute(`data-axis`))===e;t.classList.toggle(t.tagName===`line`?`prism-radar-spoke--active`:`prism-radar-point--active`,n)}}function animateTo(e,t){F?.();let n=e.map((e,t)=>e.map((e,n)=>P[t]?.[n]??0)),r=s.resolveMotion(v.transition,400),i=o.resolveEasing(r.easing??`ease-out`),a=n.every((t,n)=>t.every((t,r)=>t===e[n][r]));if(r.duration===0||a){P=e,draw(e);return}F=l.startTween({count:e.length,duration:r.duration,easing:i,onFrame:t=>{P=e.map((e,r)=>{let i=t(r);return e.map((e,t)=>c.tweenNumber(n[r][t],e,i))}),draw(P)},signal:t,stagger:r.stagger})}return r.createRadialScaffold(_,{a11y:v.a11y,legend:v.legend,tooltip:v.tooltip},e=>{let{legend:t,svg:r,tooltip:i}=e;if(r.contains(k)||r.appendChild(k),i?.hide(),t?.update(O.map((e,t)=>({color:e.color??a.seriesColor(t),name:e.name}))),y.length<3){for(let e of[A,j,M,N])e.replaceChildren();P=[];return}let{height:o,width:s}=e.dimensions,c=f.fitRadius(s,o,y.map(e=>e.label),T,p,E);L={cx:s/2,cy:o/2,radius:c};let l=f.resolveAxisDomains(y,O,v.domain);renderGrid(l),renderLabels(),renderSeries(),animateTo(O.map(e=>y.map((t,n)=>{let r=datumAt(e,n)?.value;return r!==void 0&&Number.isFinite(r)?f.normalize(r,l[n]):0})),e.disposalSignal),setActive(I);let eventFor=(e,t)=>({axis:y[e],index:e,originalEvent:t,values:valuesAt(e)}),activate=(t,o)=>{setActive(t),v.onHover?.(eventFor(t,o));let s=describe(t);if(!i){e.announcer.announce(s);return}let c=Math.max(0,...P.map(e=>e[t]??0)),l=r.getBoundingClientRect(),u=_.getBoundingClientRect(),f=valuesAt(t),p=f.find(e=>e.datum)?.datum,m=f.flatMap(({datum:e,series:n})=>e?[{color:n.color??a.seriesColor(O.indexOf(n)),name:n.name,value:formatValue(t,e.value)}]:[]);i.show(d.polarX(L.cx,L.radius*c,T[t])+(l.left-u.left),d.polarY(L.cy,L.radius*c,T[t])+(l.top-u.top),{key:y[t].key,meta:{axis:y[t],text:s,values:f},value:p?.value??0},{color:O[0]?.color??a.seriesColor(0),data:[],name:y[t].label},n.comparisonContent(r.ownerDocument,y[t].label,m,s))},deactivate=()=>{setActive(-1),v.onHover?.(null),i?.hide(),e.announcer.clear()},hitIndex=e=>{let t=r.getBoundingClientRect(),n=e.clientX-t.left-L.cx,i=e.clientY-t.top-L.cy;return Math.hypot(n,i)>L.radius+E+22?-1:f.nearestAxis(n,i,y.length,w)};return{onClick(e){let t=hitIndex(e);t>=0&&v.onClick?.(eventFor(t,e))},onKeyDown(e){let t=g[e.key];t===void 0?(e.key===`Enter`||e.key===` `)&&I>=0&&v.onClick?(e.preventDefault(),v.onClick(eventFor(I,e))):e.key===`Escape`&&deactivate():(e.preventDefault(),activate(I<0?0:(I+t+y.length)%y.length,e))},onMouseLeave:deactivate,onMouseMove(e){let t=hitIndex(e);t<0?I>=0&&deactivate():t!==I&&activate(t,e)}}},e=>{O=e})}exports.createRadarChart=createRadarChart;
2
2
  //# sourceMappingURL=radar-chart.cjs.map