@vielzeug/prism 26.10.2 → 26.10.4

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 (138) hide show
  1. package/README.md +1 -1
  2. package/dist/_dev.cjs.map +1 -1
  3. package/dist/_dev.js.map +1 -1
  4. package/dist/_tappers.cjs +2 -0
  5. package/dist/_tappers.cjs.map +1 -0
  6. package/dist/_tappers.d.ts +10 -0
  7. package/dist/_tappers.d.ts.map +1 -0
  8. package/dist/_tappers.js +2 -0
  9. package/dist/_tappers.js.map +1 -0
  10. package/dist/animation/easing.cjs +1 -1
  11. package/dist/animation/easing.cjs.map +1 -1
  12. package/dist/animation/easing.d.ts +15 -1
  13. package/dist/animation/easing.d.ts.map +1 -1
  14. package/dist/animation/easing.js +1 -1
  15. package/dist/animation/easing.js.map +1 -1
  16. package/dist/animation/motion.cjs +1 -1
  17. package/dist/animation/motion.cjs.map +1 -1
  18. package/dist/animation/motion.d.ts +17 -2
  19. package/dist/animation/motion.d.ts.map +1 -1
  20. package/dist/animation/motion.js +1 -1
  21. package/dist/animation/motion.js.map +1 -1
  22. package/dist/animation/transition.cjs +1 -1
  23. package/dist/animation/transition.cjs.map +1 -1
  24. package/dist/animation/transition.d.ts +32 -3
  25. package/dist/animation/transition.d.ts.map +1 -1
  26. package/dist/animation/transition.js +1 -1
  27. package/dist/animation/transition.js.map +1 -1
  28. package/dist/charts/area/area-chart.cjs +1 -1
  29. package/dist/charts/area/area-chart.cjs.map +1 -1
  30. package/dist/charts/area/area-chart.d.ts.map +1 -1
  31. package/dist/charts/area/area-chart.js +1 -1
  32. package/dist/charts/area/area-chart.js.map +1 -1
  33. package/dist/charts/area/area-renderer.cjs +1 -1
  34. package/dist/charts/area/area-renderer.cjs.map +1 -1
  35. package/dist/charts/area/area-renderer.d.ts +2 -2
  36. package/dist/charts/area/area-renderer.d.ts.map +1 -1
  37. package/dist/charts/area/area-renderer.js +1 -1
  38. package/dist/charts/area/area-renderer.js.map +1 -1
  39. package/dist/charts/bar/bar-chart.cjs +1 -1
  40. package/dist/charts/bar/bar-chart.cjs.map +1 -1
  41. package/dist/charts/bar/bar-chart.d.ts.map +1 -1
  42. package/dist/charts/bar/bar-chart.js +1 -1
  43. package/dist/charts/bar/bar-chart.js.map +1 -1
  44. package/dist/charts/bar/bar-renderer.cjs +1 -1
  45. package/dist/charts/bar/bar-renderer.cjs.map +1 -1
  46. package/dist/charts/bar/bar-renderer.d.ts +2 -2
  47. package/dist/charts/bar/bar-renderer.d.ts.map +1 -1
  48. package/dist/charts/bar/bar-renderer.js +1 -1
  49. package/dist/charts/bar/bar-renderer.js.map +1 -1
  50. package/dist/charts/line/line-chart.cjs +1 -1
  51. package/dist/charts/line/line-chart.cjs.map +1 -1
  52. package/dist/charts/line/line-chart.d.ts.map +1 -1
  53. package/dist/charts/line/line-chart.js +1 -1
  54. package/dist/charts/line/line-chart.js.map +1 -1
  55. package/dist/charts/line/line-renderer.cjs +1 -1
  56. package/dist/charts/line/line-renderer.cjs.map +1 -1
  57. package/dist/charts/line/line-renderer.d.ts +4 -2
  58. package/dist/charts/line/line-renderer.d.ts.map +1 -1
  59. package/dist/charts/line/line-renderer.js +1 -1
  60. package/dist/charts/line/line-renderer.js.map +1 -1
  61. package/dist/charts/pie/pie-chart.cjs +1 -1
  62. package/dist/charts/pie/pie-chart.cjs.map +1 -1
  63. package/dist/charts/pie/pie-chart.d.ts.map +1 -1
  64. package/dist/charts/pie/pie-chart.js +1 -1
  65. package/dist/charts/pie/pie-chart.js.map +1 -1
  66. package/dist/charts/radar/radar-chart.cjs +1 -1
  67. package/dist/charts/radar/radar-chart.cjs.map +1 -1
  68. package/dist/charts/radar/radar-chart.d.ts.map +1 -1
  69. package/dist/charts/radar/radar-chart.js +1 -1
  70. package/dist/charts/radar/radar-chart.js.map +1 -1
  71. package/dist/charts/sparkline/sparkline.cjs +1 -1
  72. package/dist/charts/sparkline/sparkline.cjs.map +1 -1
  73. package/dist/charts/sparkline/sparkline.d.ts.map +1 -1
  74. package/dist/charts/sparkline/sparkline.js +1 -1
  75. package/dist/charts/sparkline/sparkline.js.map +1 -1
  76. package/dist/core/chart-scaffold.cjs +1 -1
  77. package/dist/core/chart-scaffold.cjs.map +1 -1
  78. package/dist/core/chart-scaffold.d.ts.map +1 -1
  79. package/dist/core/chart-scaffold.js +1 -1
  80. package/dist/core/chart-scaffold.js.map +1 -1
  81. package/dist/core/responsive.cjs +1 -1
  82. package/dist/core/responsive.cjs.map +1 -1
  83. package/dist/core/responsive.d.ts.map +1 -1
  84. package/dist/core/responsive.js +1 -1
  85. package/dist/core/responsive.js.map +1 -1
  86. package/dist/index.d.ts +2 -2
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/interaction/crosshair.cjs +1 -1
  89. package/dist/interaction/crosshair.cjs.map +1 -1
  90. package/dist/interaction/crosshair.d.ts +7 -0
  91. package/dist/interaction/crosshair.d.ts.map +1 -1
  92. package/dist/interaction/crosshair.js +1 -1
  93. package/dist/interaction/crosshair.js.map +1 -1
  94. package/dist/interaction/series-interaction.cjs +1 -1
  95. package/dist/interaction/series-interaction.cjs.map +1 -1
  96. package/dist/interaction/series-interaction.d.ts +3 -1
  97. package/dist/interaction/series-interaction.d.ts.map +1 -1
  98. package/dist/interaction/series-interaction.js +1 -1
  99. package/dist/interaction/series-interaction.js.map +1 -1
  100. package/dist/interaction/tooltip.cjs +1 -1
  101. package/dist/interaction/tooltip.cjs.map +1 -1
  102. package/dist/interaction/tooltip.d.ts.map +1 -1
  103. package/dist/interaction/tooltip.js +1 -1
  104. package/dist/interaction/tooltip.js.map +1 -1
  105. package/dist/prism.cjs +1 -1
  106. package/dist/prism.cjs.map +1 -1
  107. package/dist/prism.iife.js +1 -1
  108. package/dist/prism.iife.js.map +1 -1
  109. package/dist/prism.js +1 -1
  110. package/dist/prism.js.map +1 -1
  111. package/dist/theme/index.cjs +1 -1
  112. package/dist/theme/index.cjs.map +1 -1
  113. package/dist/theme/index.d.ts +9 -4
  114. package/dist/theme/index.d.ts.map +1 -1
  115. package/dist/theme/index.js +1 -1
  116. package/dist/theme/index.js.map +1 -1
  117. package/dist/theme/prism.css +18 -4
  118. package/dist/types.d.ts +76 -9
  119. package/dist/types.d.ts.map +1 -1
  120. package/package.json +3 -18
  121. package/dist/animation/index.d.ts +0 -6
  122. package/dist/animation/index.d.ts.map +0 -1
  123. package/dist/axes/index.d.ts +0 -3
  124. package/dist/axes/index.d.ts.map +0 -1
  125. package/dist/core/index.d.ts +0 -7
  126. package/dist/core/index.d.ts.map +0 -1
  127. package/dist/devtools/index.d.ts +0 -52
  128. package/dist/devtools/index.d.ts.map +0 -1
  129. package/dist/devtools.cjs +0 -2
  130. package/dist/devtools.cjs.map +0 -1
  131. package/dist/devtools.js +0 -2
  132. package/dist/devtools.js.map +0 -1
  133. package/dist/interaction/index.d.ts +0 -8
  134. package/dist/interaction/index.d.ts.map +0 -1
  135. package/dist/scales/index.d.ts +0 -4
  136. package/dist/scales/index.d.ts.map +0 -1
  137. package/dist/svg/index.d.ts +0 -5
  138. package/dist/svg/index.d.ts.map +0 -1
@@ -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 // The geometry actually on screen right now (mid-tween included): the update\n // morph interpolates from this, so interrupting a tween never jumps.\n let drawnArcs: 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);\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 // Mount sweeps the ring in once; an update morphs every slice from its\n // drawn angles to the new ones, which reads as the data changing rather\n // than the chart redrawing.\n const isMount = drawnArcs.length === 0;\n const fromArcs = drawnArcs;\n\n activeTween = startTween({\n count: 1,\n duration: dur,\n easing,\n onComplete: () => renderLabels(slices),\n onFrame: (progress) => {\n const e = progress(0);\n\n if (isMount) {\n const revealAngle = tweenNumber(start, end, e);\n\n drawnArcs = currentArcs.map((a, j) => {\n const el = pieGroup.children[j] as SVGPathElement | undefined;\n\n if (!el) return a;\n\n if (revealAngle <= a.startAngle) {\n setAttributes(el, { d: '' });\n\n return { ...a, endAngle: a.startAngle };\n }\n\n const visibleEnd = Math.min(a.endAngle, revealAngle);\n\n setAttributes(el, { d: arcPath({ ...a, endAngle: visibleEnd }) });\n\n return { ...a, endAngle: visibleEnd };\n });\n\n return;\n }\n\n drawnArcs = currentArcs.map((to, j) => {\n const el = pieGroup.children[j] as SVGPathElement | undefined;\n const lastDrawn = fromArcs.at(-1);\n // A slice that was not drawn before grows out of the end of the last drawn one.\n const from: Arc = fromArcs[j] ?? {\n ...to,\n endAngle: lastDrawn?.endAngle ?? start,\n startAngle: lastDrawn?.endAngle ?? start,\n };\n const morphed: Arc = {\n ...to,\n endAngle: tweenNumber(from.endAngle, to.endAngle, e),\n innerRadius: tweenNumber(from.innerRadius, to.innerRadius, e),\n outerRadius: tweenNumber(from.outerRadius, to.outerRadius, e),\n padAngle: tweenNumber(from.padAngle, to.padAngle, e),\n startAngle: tweenNumber(from.startAngle, to.startAngle, e),\n };\n\n if (!el) return morphed;\n\n setAttributes(el, {\n d: morphed.endAngle - morphed.startAngle <= 1e-6 ? '' : arcPath(morphed),\n });\n\n return morphed;\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,{defaultDuration: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
@@ -1 +1 @@
1
- {"version":3,"file":"radar-chart.cjs","names":[],"sources":["../../../src/charts/radar/radar-chart.ts"],"sourcesContent":["import { devOnly, warn } from '../../_dev';\nimport { 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 { uniqueId } from '../../core/ids';\nimport { polarX, polarY } from '../../core/polar';\nimport { seriesDomId } from '../../core/series-id';\nimport { describeValues } from '../../interaction/announcer';\nimport { comparisonContent } from '../../interaction/tooltip';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport type {\n ChartHandle,\n RadarAxisConfig,\n RadarAxisValue,\n RadarChartConfig,\n RadarEvent,\n RadarGridConfig,\n RadarSeriesConfig,\n} from '../../types';\nimport {\n axisAngles,\n closedPath,\n fitRadius,\n labelPlacement,\n nearestAxis,\n normalize,\n radarPoints,\n resolveAxisDomains,\n ringPath,\n toRadians,\n} from './radar-geometry';\n\n/** Default `--prism-font-size-label` (0.6875rem) in px, used to reserve label room. */\nconst LABEL_FONT_SIZE = 11;\nconst LABEL_GAP = 12;\nconst VALUE_OFFSET = 10;\nconst ARROW_STEPS: Record<string, number> = { ArrowDown: 1, ArrowLeft: -1, ArrowRight: 1, ArrowUp: -1 };\n\nfunction warnOnInvalid(axes: readonly RadarAxisConfig[], series: readonly RadarSeriesConfig[]): void {\n devOnly(() => {\n if (axes.length < 3) warn(`Radar chart needs at least 3 axes, received ${axes.length}.`);\n\n const keys = new Set(axes.map((axis) => axis.key));\n\n if (keys.size !== axes.length) warn('Radar chart axis keys must be unique.');\n\n for (const s of series) {\n for (const d of s.data) {\n if (!keys.has(d.key)) warn(`Radar series \"${s.name}\" has a value for unknown axis \"${d.key}\".`);\n }\n }\n });\n}\n\nfunction resolveGrid(grid: RadarChartConfig['grid']): Required<RadarGridConfig> | null {\n if (grid === false) return null;\n\n return { bands: true, labels: false, levels: 4, shape: 'polygon', ...(typeof grid === 'object' ? grid : {}) };\n}\n\nexport function createRadarChart(container: HTMLElement, config: RadarChartConfig): ChartHandle<RadarSeriesConfig[]> {\n const { axes } = config;\n const curve = config.curve ?? 'linear';\n const fill = config.fill ?? 'solid';\n const showPoints = config.showPoints ?? true;\n const grid = resolveGrid(config.grid);\n const startAngle = toRadians(config.startAngle ?? 0);\n const angles = axisAngles(axes.length, startAngle);\n const labelGap = LABEL_GAP + (config.showValues ? VALUE_OFFSET : 0);\n const id = uniqueId('prism-radar');\n let series = config.series;\n\n warnOnInvalid(axes, series);\n\n const root = createSvgElement('g', { class: 'prism-radar' });\n const defs = createSvgElement('defs');\n const gridGroup = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-radar-grid' });\n const seriesGroup = createSvgElement('g', { class: 'prism-radar-series-group' });\n const labelGroup = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-radar-labels' });\n\n root.append(defs, gridGroup, seriesGroup, labelGroup);\n\n let drawn: number[][] = [];\n let activeRaf: number | null = null;\n let activeIndex = -1;\n let layout = { cx: 0, cy: 0, radius: 0 };\n\n const datumAt = (s: RadarSeriesConfig, index: number) => s.data.find((d) => d.key === axes[index].key);\n const valuesAt = (index: number): RadarAxisValue[] => series.map((s) => ({ datum: datumAt(s, index), series: s }));\n const formatValue = (index: number, value: number): string => axes[index].format?.(value) ?? String(value);\n const describe = (index: number): string =>\n describeValues(axes[index].label, valuesAt(index), (value) => formatValue(index, value));\n\n function draw(fractions: number[][]): void {\n const { cx, cy, radius } = layout;\n\n fractions.forEach((row, i) => {\n const group = seriesGroup.children[i];\n\n if (!group) return;\n\n const points = radarPoints(row, cx, cy, radius, angles);\n\n group.querySelector('.prism-radar-area')?.setAttribute('d', closedPath(points, curve));\n group.querySelectorAll<SVGCircleElement>('.prism-radar-point').forEach((dot, j) => {\n setAttributes(dot, { cx: points[j].x, cy: points[j].y });\n });\n group.querySelectorAll<SVGTextElement>('.prism-radar-value').forEach((text, j) => {\n const r = radius * row[j] + VALUE_OFFSET;\n\n setAttributes(text, { x: polarX(cx, r, angles[j]), y: polarY(cy, r, angles[j]) });\n });\n });\n }\n\n function renderGrid(domains: [number, number][]): void {\n gridGroup.replaceChildren();\n\n if (!grid) return;\n\n const { cx, cy, radius } = layout;\n const levels = Math.max(1, Math.round(grid.levels));\n const rings = Array.from({ length: levels }, (_, k) =>\n ringPath(grid.shape, cx, cy, (radius * (k + 1)) / levels, angles),\n );\n\n if (grid.bands) {\n // Shade alternate rings, starting from the outermost.\n for (let k = levels - 1; k >= 0; k -= 2) {\n gridGroup.appendChild(\n createSvgElement('path', {\n class: 'prism-radar-band',\n d: `${rings[k]}${rings[k - 1] ?? ''}`,\n 'fill-rule': 'evenodd',\n }),\n );\n }\n }\n\n for (const d of rings)\n gridGroup.appendChild(createSvgElement('path', { class: 'prism-radar-ring', d, fill: 'none' }));\n\n angles.forEach((angle, i) => {\n gridGroup.appendChild(\n createSvgElement('line', {\n class: 'prism-radar-spoke',\n 'data-axis': i,\n x1: cx,\n x2: polarX(cx, radius, angle),\n y1: cy,\n y2: polarY(cy, radius, angle),\n }),\n );\n });\n\n const [d0, d1] = domains[0];\n const shared = domains.every(([a, b]) => a === d0 && b === d1);\n\n if (!grid.labels || !shared) return;\n\n // Between the first two spokes, so level values never collide with vertex values.\n const angle = angles[0] + Math.PI / angles.length;\n\n for (let k = 1; k <= levels; k++) {\n const r = (radius * k) / levels;\n const text = createSvgElement('text', {\n class: 'prism-radar-level',\n 'dominant-baseline': 'middle',\n 'text-anchor': 'middle',\n x: polarX(cx, r, angle),\n y: polarY(cy, r, angle),\n });\n\n text.textContent = formatValue(0, Math.round((d0 + ((d1 - d0) * k) / levels) * 100) / 100);\n gridGroup.appendChild(text);\n }\n }\n\n function renderLabels(): void {\n labelGroup.replaceChildren();\n\n const { cx, cy, radius } = layout;\n\n axes.forEach((axis, i) => {\n const { anchor, baseline } = labelPlacement(angles[i]);\n const text = createSvgElement('text', {\n class: 'prism-radar-axis-label',\n 'dominant-baseline': baseline,\n 'text-anchor': anchor,\n x: polarX(cx, radius + labelGap, angles[i]),\n y: polarY(cy, radius + labelGap, angles[i]),\n });\n\n text.textContent = axis.label;\n labelGroup.appendChild(text);\n });\n }\n\n function renderSeries(): void {\n const { cx, cy, radius } = layout;\n\n defs.replaceChildren();\n\n while (seriesGroup.children.length > series.length) seriesGroup.lastChild?.remove();\n\n series.forEach((s, i) => {\n const color = s.color ?? seriesColor(i);\n let group = seriesGroup.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-radar-series' });\n seriesGroup.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(s, i));\n\n group.replaceChildren();\n\n const area = createSvgElement('path', {\n class: `prism-radar-area prism-radar-area--${fill}`,\n stroke: color,\n 'stroke-linejoin': 'round',\n 'stroke-width': 2,\n });\n\n if (fill === 'gradient') {\n const gradientId = `${id}-fill-${i}`;\n const gradient = createSvgElement('radialGradient', {\n cx,\n cy,\n gradientUnits: 'userSpaceOnUse',\n id: gradientId,\n r: radius,\n });\n\n for (const [offset, opacity] of [\n [0, 0.08],\n [1, 0.55],\n ]) {\n gradient.appendChild(\n createSvgElement('stop', {\n offset,\n 'stop-color': color,\n 'stop-opacity': opacity,\n style: `stop-color:${color}`,\n }),\n );\n }\n\n defs.appendChild(gradient);\n setAttributes(area, { fill: `url(#${gradientId})` });\n } else {\n setAttributes(area, { fill: fill === 'none' ? 'none' : color, 'fill-opacity': 0.25 });\n }\n\n group.appendChild(area);\n\n if (showPoints) {\n axes.forEach((_, j) => {\n const missing = !Number.isFinite(datumAt(s, j)?.value);\n\n group.appendChild(\n createSvgElement('circle', {\n class: `prism-radar-point${missing ? ' prism-radar-point--missing' : ''}`,\n 'data-axis': j,\n fill: missing ? 'none' : color,\n r: 3,\n stroke: color,\n }),\n );\n });\n }\n\n if (config.showValues) {\n axes.forEach((_, j) => {\n const datum = datumAt(s, j);\n const { anchor, baseline } = labelPlacement(angles[j]);\n const text = createSvgElement('text', {\n 'aria-hidden': 'true',\n class: 'prism-radar-value',\n 'dominant-baseline': baseline,\n 'text-anchor': anchor,\n });\n\n text.textContent = datum && Number.isFinite(datum.value) ? formatValue(j, datum.value) : '';\n group.appendChild(text);\n });\n }\n });\n }\n\n function setActive(index: number): void {\n activeIndex = index;\n for (const el of root.querySelectorAll('[data-axis]')) {\n const active = Number(el.getAttribute('data-axis')) === index;\n\n el.classList.toggle(el.tagName === 'line' ? 'prism-radar-spoke--active' : 'prism-radar-point--active', active);\n }\n }\n\n function animateTo(targets: number[][]): void {\n if (activeRaf !== null) {\n cancelAnimationFrame(activeRaf);\n activeRaf = null;\n }\n\n const from = targets.map((row, i) => row.map((_, j) => drawn[i]?.[j] ?? 0));\n const motion = resolveMotion(config.transition, 400);\n const easing = resolveEasing(motion.easing ?? 'ease-out');\n const unchanged = from.every((row, i) => row.every((v, j) => v === targets[i][j]));\n\n if (motion.duration === 0 || unchanged) {\n drawn = targets;\n draw(targets);\n\n return;\n }\n\n let start: number | null = null;\n\n const frame = (ts: number): void => {\n if (start === null) start = ts;\n\n const elapsed = ts - start;\n let done = true;\n\n drawn = targets.map((row, i) => {\n const raw = Math.max(0, Math.min(1, (elapsed - i * motion.stagger) / motion.duration));\n\n if (raw < 1) done = false;\n\n return row.map((to, j) => tweenNumber(from[i][j], to, easing(raw)));\n });\n draw(drawn);\n activeRaf = done ? null : requestAnimationFrame(frame);\n };\n\n activeRaf = requestAnimationFrame(frame);\n }\n\n let handle: ChartHandle<RadarSeriesConfig[]> | undefined;\n\n try {\n handle = createRadialScaffold(\n container,\n { a11y: config.a11y, legend: config.legend, tooltip: config.tooltip },\n (ctx): ChartEventHandlers | undefined => {\n const { legend, svg, tooltip } = ctx;\n\n if (!svg.contains(root)) svg.appendChild(root);\n\n tooltip?.hide();\n legend?.update(series.map((s, i) => ({ color: s.color ?? seriesColor(i), name: s.name })));\n\n if (axes.length < 3) {\n for (const group of [defs, gridGroup, seriesGroup, labelGroup]) group.replaceChildren();\n drawn = [];\n\n return undefined;\n }\n\n const { height, width } = ctx.dimensions;\n const radius = fitRadius(\n width,\n height,\n axes.map((axis) => axis.label),\n angles,\n LABEL_FONT_SIZE,\n labelGap,\n );\n\n layout = { cx: width / 2, cy: height / 2, radius };\n\n const domains = resolveAxisDomains(axes, series, config.domain);\n\n renderGrid(domains);\n renderLabels();\n renderSeries();\n animateTo(\n series.map((s) =>\n axes.map((_, j) => {\n const value = datumAt(s, j)?.value;\n\n return value !== undefined && Number.isFinite(value) ? normalize(value, domains[j]) : 0;\n }),\n ),\n );\n setActive(activeIndex);\n\n const eventFor = (index: number, originalEvent: Event): RadarEvent => ({\n axis: axes[index],\n index,\n originalEvent,\n values: valuesAt(index),\n });\n\n const activate = (index: number, originalEvent: Event): void => {\n setActive(index);\n config.onHover?.(eventFor(index, originalEvent));\n\n const text = describe(index);\n\n if (!tooltip) {\n ctx.announcer.announce(text);\n\n return;\n }\n\n const reach = Math.max(0, ...drawn.map((row) => row[index] ?? 0));\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const values = valuesAt(index);\n const first = values.find((v) => v.datum)?.datum;\n const rows = values.flatMap(({ datum, series: s }) =>\n datum\n ? [\n {\n color: s.color ?? seriesColor(series.indexOf(s)),\n name: s.name,\n value: formatValue(index, datum.value),\n },\n ]\n : [],\n );\n\n tooltip.show(\n polarX(layout.cx, layout.radius * reach, angles[index]) + (svgRect.left - containerRect.left),\n polarY(layout.cy, layout.radius * reach, angles[index]) + (svgRect.top - containerRect.top),\n { key: axes[index].key, meta: { axis: axes[index], text, values }, value: first?.value ?? 0 },\n { color: series[0]?.color ?? seriesColor(0), data: [], name: axes[index].label },\n comparisonContent(svg.ownerDocument, axes[index].label, rows, text),\n );\n };\n\n const deactivate = (): void => {\n setActive(-1);\n config.onHover?.(null);\n tooltip?.hide();\n ctx.announcer.clear();\n };\n\n const hitIndex = (event: MouseEvent): number => {\n const rect = svg.getBoundingClientRect();\n const dx = event.clientX - rect.left - layout.cx;\n const dy = event.clientY - rect.top - layout.cy;\n\n if (Math.hypot(dx, dy) > layout.radius + labelGap + LABEL_FONT_SIZE * 2) return -1;\n\n return nearestAxis(dx, dy, axes.length, startAngle);\n };\n\n return {\n onClick(event) {\n const index = hitIndex(event);\n\n if (index >= 0) config.onClick?.(eventFor(index, event));\n },\n onKeyDown(event) {\n const step = ARROW_STEPS[event.key];\n\n if (step !== undefined) {\n event.preventDefault();\n activate(activeIndex < 0 ? 0 : (activeIndex + step + axes.length) % axes.length, event);\n } else if ((event.key === 'Enter' || event.key === ' ') && activeIndex >= 0 && config.onClick) {\n event.preventDefault();\n config.onClick(eventFor(activeIndex, event));\n } else if (event.key === 'Escape') {\n deactivate();\n }\n },\n onMouseLeave: deactivate,\n onMouseMove(event) {\n const index = hitIndex(event);\n\n if (index < 0) {\n if (activeIndex >= 0) deactivate();\n } else if (index !== activeIndex) {\n activate(index, event);\n }\n },\n };\n },\n (next) => {\n series = next;\n warnOnInvalid(axes, series);\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"],"mappings":"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"}
1
+ {"version":3,"file":"radar-chart.cjs","names":[],"sources":["../../../src/charts/radar/radar-chart.ts"],"sourcesContent":["import { devOnly, warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport type { ChartEventHandlers } from '../../core/chart-scaffold';\nimport { createRadialScaffold } from '../../core/chart-scaffold';\nimport { uniqueId } from '../../core/ids';\nimport { polarX, polarY } from '../../core/polar';\nimport { seriesDomId } from '../../core/series-id';\nimport { describeValues } from '../../interaction/announcer';\nimport { comparisonContent } from '../../interaction/tooltip';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport type {\n ChartHandle,\n RadarAxisConfig,\n RadarAxisValue,\n RadarChartConfig,\n RadarEvent,\n RadarGridConfig,\n RadarSeriesConfig,\n} from '../../types';\nimport {\n axisAngles,\n closedPath,\n fitRadius,\n labelPlacement,\n nearestAxis,\n normalize,\n radarPoints,\n resolveAxisDomains,\n ringPath,\n toRadians,\n} from './radar-geometry';\n\n/** Default `--prism-font-size-label` (0.6875rem) in px, used to reserve label room. */\nconst LABEL_FONT_SIZE = 11;\nconst LABEL_GAP = 12;\nconst VALUE_OFFSET = 10;\nconst ARROW_STEPS: Record<string, number> = { ArrowDown: 1, ArrowLeft: -1, ArrowRight: 1, ArrowUp: -1 };\n\nfunction warnOnInvalid(axes: readonly RadarAxisConfig[], series: readonly RadarSeriesConfig[]): void {\n devOnly(() => {\n if (axes.length < 3) warn(`Radar chart needs at least 3 axes, received ${axes.length}.`);\n\n const keys = new Set(axes.map((axis) => axis.key));\n\n if (keys.size !== axes.length) warn('Radar chart axis keys must be unique.');\n\n for (const s of series) {\n for (const d of s.data) {\n if (!keys.has(d.key)) warn(`Radar series \"${s.name}\" has a value for unknown axis \"${d.key}\".`);\n }\n }\n });\n}\n\nfunction resolveGrid(grid: RadarChartConfig['grid']): Required<RadarGridConfig> | null {\n if (grid === false) return null;\n\n return { bands: true, labels: false, levels: 4, shape: 'polygon', ...(typeof grid === 'object' ? grid : {}) };\n}\n\nexport function createRadarChart(container: HTMLElement, config: RadarChartConfig): ChartHandle<RadarSeriesConfig[]> {\n const { axes } = config;\n const curve = config.curve ?? 'linear';\n const fill = config.fill ?? 'solid';\n const showPoints = config.showPoints ?? true;\n const grid = resolveGrid(config.grid);\n const startAngle = toRadians(config.startAngle ?? 0);\n const angles = axisAngles(axes.length, startAngle);\n const labelGap = LABEL_GAP + (config.showValues ? VALUE_OFFSET : 0);\n const id = uniqueId('prism-radar');\n let series = config.series;\n\n warnOnInvalid(axes, series);\n\n const root = createSvgElement('g', { class: 'prism-radar' });\n const defs = createSvgElement('defs');\n const gridGroup = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-radar-grid' });\n const seriesGroup = createSvgElement('g', { class: 'prism-radar-series-group' });\n const labelGroup = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-radar-labels' });\n\n root.append(defs, gridGroup, seriesGroup, labelGroup);\n\n let drawn: number[][] = [];\n let activeTween: (() => void) | null = null;\n let activeIndex = -1;\n let layout = { cx: 0, cy: 0, radius: 0 };\n\n const datumAt = (s: RadarSeriesConfig, index: number) => s.data.find((d) => d.key === axes[index].key);\n const valuesAt = (index: number): RadarAxisValue[] => series.map((s) => ({ datum: datumAt(s, index), series: s }));\n const formatValue = (index: number, value: number): string => axes[index].format?.(value) ?? String(value);\n const describe = (index: number): string =>\n describeValues(axes[index].label, valuesAt(index), (value) => formatValue(index, value));\n\n function draw(fractions: number[][]): void {\n const { cx, cy, radius } = layout;\n\n fractions.forEach((row, i) => {\n const group = seriesGroup.children[i];\n\n if (!group) return;\n\n const points = radarPoints(row, cx, cy, radius, angles);\n\n group.querySelector('.prism-radar-area')?.setAttribute('d', closedPath(points, curve));\n group.querySelectorAll<SVGCircleElement>('.prism-radar-point').forEach((dot, j) => {\n setAttributes(dot, { cx: points[j].x, cy: points[j].y });\n });\n group.querySelectorAll<SVGTextElement>('.prism-radar-value').forEach((text, j) => {\n const r = radius * row[j] + VALUE_OFFSET;\n\n setAttributes(text, { x: polarX(cx, r, angles[j]), y: polarY(cy, r, angles[j]) });\n });\n });\n }\n\n function renderGrid(domains: [number, number][]): void {\n gridGroup.replaceChildren();\n\n if (!grid) return;\n\n const { cx, cy, radius } = layout;\n const levels = Math.max(1, Math.round(grid.levels));\n const rings = Array.from({ length: levels }, (_, k) =>\n ringPath(grid.shape, cx, cy, (radius * (k + 1)) / levels, angles),\n );\n\n if (grid.bands) {\n // Shade alternate rings, starting from the outermost.\n for (let k = levels - 1; k >= 0; k -= 2) {\n gridGroup.appendChild(\n createSvgElement('path', {\n class: 'prism-radar-band',\n d: `${rings[k]}${rings[k - 1] ?? ''}`,\n 'fill-rule': 'evenodd',\n }),\n );\n }\n }\n\n for (const d of rings)\n gridGroup.appendChild(createSvgElement('path', { class: 'prism-radar-ring', d, fill: 'none' }));\n\n angles.forEach((angle, i) => {\n gridGroup.appendChild(\n createSvgElement('line', {\n class: 'prism-radar-spoke',\n 'data-axis': i,\n x1: cx,\n x2: polarX(cx, radius, angle),\n y1: cy,\n y2: polarY(cy, radius, angle),\n }),\n );\n });\n\n const [d0, d1] = domains[0];\n const shared = domains.every(([a, b]) => a === d0 && b === d1);\n\n if (!grid.labels || !shared) return;\n\n // Between the first two spokes, so level values never collide with vertex values.\n const angle = angles[0] + Math.PI / angles.length;\n\n for (let k = 1; k <= levels; k++) {\n const r = (radius * k) / levels;\n const text = createSvgElement('text', {\n class: 'prism-radar-level',\n 'dominant-baseline': 'middle',\n 'text-anchor': 'middle',\n x: polarX(cx, r, angle),\n y: polarY(cy, r, angle),\n });\n\n text.textContent = formatValue(0, Math.round((d0 + ((d1 - d0) * k) / levels) * 100) / 100);\n gridGroup.appendChild(text);\n }\n }\n\n function renderLabels(): void {\n labelGroup.replaceChildren();\n\n const { cx, cy, radius } = layout;\n\n axes.forEach((axis, i) => {\n const { anchor, baseline } = labelPlacement(angles[i]);\n const text = createSvgElement('text', {\n class: 'prism-radar-axis-label',\n 'dominant-baseline': baseline,\n 'text-anchor': anchor,\n x: polarX(cx, radius + labelGap, angles[i]),\n y: polarY(cy, radius + labelGap, angles[i]),\n });\n\n text.textContent = axis.label;\n labelGroup.appendChild(text);\n });\n }\n\n function renderSeries(): void {\n const { cx, cy, radius } = layout;\n\n defs.replaceChildren();\n\n while (seriesGroup.children.length > series.length) seriesGroup.lastChild?.remove();\n\n series.forEach((s, i) => {\n const color = s.color ?? seriesColor(i);\n let group = seriesGroup.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-radar-series' });\n seriesGroup.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(s, i));\n\n group.replaceChildren();\n\n const area = createSvgElement('path', {\n class: `prism-radar-area prism-radar-area--${fill}`,\n stroke: color,\n 'stroke-linejoin': 'round',\n 'stroke-width': 2,\n });\n\n if (fill === 'gradient') {\n const gradientId = `${id}-fill-${i}`;\n const gradient = createSvgElement('radialGradient', {\n cx,\n cy,\n gradientUnits: 'userSpaceOnUse',\n id: gradientId,\n r: radius,\n });\n\n for (const [offset, opacity] of [\n [0, 0.08],\n [1, 0.55],\n ]) {\n gradient.appendChild(\n createSvgElement('stop', {\n offset,\n 'stop-color': color,\n 'stop-opacity': opacity,\n style: `stop-color:${color}`,\n }),\n );\n }\n\n defs.appendChild(gradient);\n setAttributes(area, { fill: `url(#${gradientId})` });\n } else {\n setAttributes(area, { fill: fill === 'none' ? 'none' : color, 'fill-opacity': 0.25 });\n }\n\n group.appendChild(area);\n\n if (showPoints) {\n axes.forEach((_, j) => {\n const missing = !Number.isFinite(datumAt(s, j)?.value);\n\n group.appendChild(\n createSvgElement('circle', {\n class: `prism-radar-point${missing ? ' prism-radar-point--missing' : ''}`,\n 'data-axis': j,\n fill: missing ? 'none' : color,\n r: 3,\n stroke: color,\n }),\n );\n });\n }\n\n if (config.showValues) {\n axes.forEach((_, j) => {\n const datum = datumAt(s, j);\n const { anchor, baseline } = labelPlacement(angles[j]);\n const text = createSvgElement('text', {\n 'aria-hidden': 'true',\n class: 'prism-radar-value',\n 'dominant-baseline': baseline,\n 'text-anchor': anchor,\n });\n\n text.textContent = datum && Number.isFinite(datum.value) ? formatValue(j, datum.value) : '';\n group.appendChild(text);\n });\n }\n });\n }\n\n function setActive(index: number): void {\n activeIndex = index;\n for (const el of root.querySelectorAll('[data-axis]')) {\n const active = Number(el.getAttribute('data-axis')) === index;\n\n el.classList.toggle(el.tagName === 'line' ? 'prism-radar-spoke--active' : 'prism-radar-point--active', active);\n }\n }\n\n function animateTo(targets: number[][], signal: AbortSignal): void {\n activeTween?.();\n\n const from = targets.map((row, i) => row.map((_, j) => drawn[i]?.[j] ?? 0));\n // Radar morphs a whole polygon, so it reads better slightly slower than the shared default.\n const motion = resolveMotion(config.transition, { defaultDuration: 400 });\n const easing = resolveEasing(motion.easing ?? 'ease-out');\n const unchanged = from.every((row, i) => row.every((v, j) => v === targets[i][j]));\n\n if (motion.duration === 0 || unchanged) {\n drawn = targets;\n draw(targets);\n\n return;\n }\n\n activeTween = startTween({\n count: targets.length,\n duration: motion.duration,\n easing,\n onFrame: (progress) => {\n drawn = targets.map((row, i) => {\n const e = progress(i);\n\n return row.map((to, j) => tweenNumber(from[i][j], to, e));\n });\n draw(drawn);\n },\n signal,\n stagger: motion.stagger,\n });\n }\n\n return createRadialScaffold(\n container,\n { a11y: config.a11y, legend: config.legend, tooltip: config.tooltip },\n (ctx): ChartEventHandlers | undefined => {\n const { legend, svg, tooltip } = ctx;\n\n if (!svg.contains(root)) svg.appendChild(root);\n\n tooltip?.hide();\n legend?.update(series.map((s, i) => ({ color: s.color ?? seriesColor(i), name: s.name })));\n\n if (axes.length < 3) {\n for (const group of [defs, gridGroup, seriesGroup, labelGroup]) group.replaceChildren();\n drawn = [];\n\n return undefined;\n }\n\n const { height, width } = ctx.dimensions;\n const radius = fitRadius(\n width,\n height,\n axes.map((axis) => axis.label),\n angles,\n LABEL_FONT_SIZE,\n labelGap,\n );\n\n layout = { cx: width / 2, cy: height / 2, radius };\n\n const domains = resolveAxisDomains(axes, series, config.domain);\n\n renderGrid(domains);\n renderLabels();\n renderSeries();\n animateTo(\n series.map((s) =>\n axes.map((_, j) => {\n const value = datumAt(s, j)?.value;\n\n return value !== undefined && Number.isFinite(value) ? normalize(value, domains[j]) : 0;\n }),\n ),\n ctx.disposalSignal,\n );\n setActive(activeIndex);\n\n const eventFor = (index: number, originalEvent: Event): RadarEvent => ({\n axis: axes[index],\n index,\n originalEvent,\n values: valuesAt(index),\n });\n\n const activate = (index: number, originalEvent: Event): void => {\n setActive(index);\n config.onHover?.(eventFor(index, originalEvent));\n\n const text = describe(index);\n\n if (!tooltip) {\n ctx.announcer.announce(text);\n\n return;\n }\n\n const reach = Math.max(0, ...drawn.map((row) => row[index] ?? 0));\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const values = valuesAt(index);\n const first = values.find((v) => v.datum)?.datum;\n const rows = values.flatMap(({ datum, series: s }) =>\n datum\n ? [\n {\n color: s.color ?? seriesColor(series.indexOf(s)),\n name: s.name,\n value: formatValue(index, datum.value),\n },\n ]\n : [],\n );\n\n tooltip.show(\n polarX(layout.cx, layout.radius * reach, angles[index]) + (svgRect.left - containerRect.left),\n polarY(layout.cy, layout.radius * reach, angles[index]) + (svgRect.top - containerRect.top),\n { key: axes[index].key, meta: { axis: axes[index], text, values }, value: first?.value ?? 0 },\n { color: series[0]?.color ?? seriesColor(0), data: [], name: axes[index].label },\n comparisonContent(svg.ownerDocument, axes[index].label, rows, text),\n );\n };\n\n const deactivate = (): void => {\n setActive(-1);\n config.onHover?.(null);\n tooltip?.hide();\n ctx.announcer.clear();\n };\n\n const hitIndex = (event: MouseEvent): number => {\n const rect = svg.getBoundingClientRect();\n const dx = event.clientX - rect.left - layout.cx;\n const dy = event.clientY - rect.top - layout.cy;\n\n if (Math.hypot(dx, dy) > layout.radius + labelGap + LABEL_FONT_SIZE * 2) return -1;\n\n return nearestAxis(dx, dy, axes.length, startAngle);\n };\n\n return {\n onClick(event) {\n const index = hitIndex(event);\n\n if (index >= 0) config.onClick?.(eventFor(index, event));\n },\n onKeyDown(event) {\n const step = ARROW_STEPS[event.key];\n\n if (step !== undefined) {\n event.preventDefault();\n activate(activeIndex < 0 ? 0 : (activeIndex + step + axes.length) % axes.length, event);\n } else if ((event.key === 'Enter' || event.key === ' ') && activeIndex >= 0 && config.onClick) {\n event.preventDefault();\n config.onClick(eventFor(activeIndex, event));\n } else if (event.key === 'Escape') {\n deactivate();\n }\n },\n onMouseLeave: deactivate,\n onMouseMove(event) {\n const index = hitIndex(event);\n\n if (index < 0) {\n if (activeIndex >= 0) deactivate();\n } else if (index !== activeIndex) {\n activate(index, event);\n }\n },\n };\n },\n (next) => {\n series = next;\n warnOnInvalid(axes, series);\n },\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"radar-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/radar/radar-chart.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,WAAW,EAGX,gBAAgB,EAGhB,iBAAiB,EAClB,MAAM,aAAa,CAAC;AA0CrB,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,GAAG,WAAW,CAAC,iBAAiB,EAAE,CAAC,CA4cnH"}
1
+ {"version":3,"file":"radar-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/radar/radar-chart.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,WAAW,EAGX,gBAAgB,EAGhB,iBAAiB,EAClB,MAAM,aAAa,CAAC;AA0CrB,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,GAAG,WAAW,CAAC,iBAAiB,EAAE,CAAC,CAkanH"}
@@ -1,2 +1,2 @@
1
- import"../../_dev.js";import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{describeValues as n}from"../../interaction/announcer.js";import{comparisonContent as r}from"../../interaction/tooltip.js";import{createRadialScaffold as i}from"../../core/chart-scaffold.js";import{seriesDomId as a}from"../../core/series-id.js";import{seriesColor as o}from"../../theme/index.js";import{resolveEasing as s}from"../../animation/easing.js";import{resolveMotion as c}from"../../animation/motion.js";import{tweenNumber as l}from"../../animation/tween.js";import{uniqueId as u}from"../../core/ids.js";import{polarX as d,polarY as f}from"../../core/polar.js";import{axisAngles as p,closedPath as m,fitRadius as h,labelPlacement as g,nearestAxis as _,normalize as v,radarPoints as y,resolveAxisDomains as b,ringPath as x,toRadians as S}from"./radar-geometry.js";var C=11,w=12,T=10,E={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(D,O){let{axes:k}=O,A=O.curve??`linear`,j=O.fill??`solid`,M=O.showPoints??!0,N=resolveGrid(O.grid),P=S(O.startAngle??0),F=p(k.length,P),I=w+(O.showValues?T:0),L=u(`prism-radar`),R=O.series,z=e(`g`,{class:`prism-radar`}),B=e(`defs`),V=e(`g`,{"aria-hidden":`true`,class:`prism-radar-grid`}),H=e(`g`,{class:`prism-radar-series-group`}),U=e(`g`,{"aria-hidden":`true`,class:`prism-radar-labels`});z.append(B,V,H,U);let W=[],G=null,K=-1,q={cx:0,cy:0,radius:0},datumAt=(e,t)=>e.data.find(e=>e.key===k[t].key),valuesAt=e=>R.map(t=>({datum:datumAt(t,e),series:t})),formatValue=(e,t)=>k[e].format?.(t)??String(t),describe=e=>n(k[e].label,valuesAt(e),t=>formatValue(e,t));function draw(e){let{cx:n,cy:r,radius:i}=q;e.forEach((e,a)=>{let o=H.children[a];if(!o)return;let s=y(e,n,r,i,F);o.querySelector(`.prism-radar-area`)?.setAttribute(`d`,m(s,A)),o.querySelectorAll(`.prism-radar-point`).forEach((e,n)=>{t(e,{cx:s[n].x,cy:s[n].y})}),o.querySelectorAll(`.prism-radar-value`).forEach((a,o)=>{let s=i*e[o]+T;t(a,{x:d(n,s,F[o]),y:f(r,s,F[o])})})})}function renderGrid(t){if(V.replaceChildren(),!N)return;let{cx:n,cy:r,radius:i}=q,a=Math.max(1,Math.round(N.levels)),o=Array.from({length:a},(e,t)=>x(N.shape,n,r,i*(t+1)/a,F));if(N.bands)for(let t=a-1;t>=0;t-=2)V.appendChild(e(`path`,{class:`prism-radar-band`,d:`${o[t]}${o[t-1]??``}`,"fill-rule":`evenodd`}));for(let t of o)V.appendChild(e(`path`,{class:`prism-radar-ring`,d:t,fill:`none`}));F.forEach((t,a)=>{V.appendChild(e(`line`,{class:`prism-radar-spoke`,"data-axis":a,x1:n,x2:d(n,i,t),y1:r,y2:f(r,i,t)}))});let[s,c]=t[0],l=t.every(([e,t])=>e===s&&t===c);if(!N.labels||!l)return;let u=F[0]+Math.PI/F.length;for(let t=1;t<=a;t++){let o=i*t/a,l=e(`text`,{class:`prism-radar-level`,"dominant-baseline":`middle`,"text-anchor":`middle`,x:d(n,o,u),y:f(r,o,u)});l.textContent=formatValue(0,Math.round((s+(c-s)*t/a)*100)/100),V.appendChild(l)}}function renderLabels(){U.replaceChildren();let{cx:t,cy:n,radius:r}=q;k.forEach((i,a)=>{let{anchor:o,baseline:s}=g(F[a]),c=e(`text`,{class:`prism-radar-axis-label`,"dominant-baseline":s,"text-anchor":o,x:d(t,r+I,F[a]),y:f(n,r+I,F[a])});c.textContent=i.label,U.appendChild(c)})}function renderSeries(){let{cx:n,cy:r,radius:i}=q;for(B.replaceChildren();H.children.length>R.length;)H.lastChild?.remove();R.forEach((s,c)=>{let l=s.color??o(c),u=H.children[c];u||(u=e(`g`,{class:`prism-radar-series`}),H.appendChild(u)),u.setAttribute(`data-series-id`,a(s,c)),u.replaceChildren();let d=e(`path`,{class:`prism-radar-area prism-radar-area--${j}`,stroke:l,"stroke-linejoin":`round`,"stroke-width":2});if(j===`gradient`){let a=`${L}-fill-${c}`,o=e(`radialGradient`,{cx:n,cy:r,gradientUnits:`userSpaceOnUse`,id:a,r:i});for(let[t,n]of[[0,.08],[1,.55]])o.appendChild(e(`stop`,{offset:t,"stop-color":l,"stop-opacity":n,style:`stop-color:${l}`}));B.appendChild(o),t(d,{fill:`url(#${a})`})}else t(d,{fill:j===`none`?`none`:l,"fill-opacity":.25});u.appendChild(d),M&&k.forEach((t,n)=>{let r=!Number.isFinite(datumAt(s,n)?.value);u.appendChild(e(`circle`,{class:`prism-radar-point${r?` prism-radar-point--missing`:``}`,"data-axis":n,fill:r?`none`:l,r:3,stroke:l}))}),O.showValues&&k.forEach((t,n)=>{let r=datumAt(s,n),{anchor:i,baseline:a}=g(F[n]),o=e(`text`,{"aria-hidden":`true`,class:`prism-radar-value`,"dominant-baseline":a,"text-anchor":i});o.textContent=r&&Number.isFinite(r.value)?formatValue(n,r.value):``,u.appendChild(o)})})}function setActive(e){K=e;for(let t of z.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){G!==null&&(cancelAnimationFrame(G),G=null);let t=e.map((e,t)=>e.map((e,n)=>W[t]?.[n]??0)),n=c(O.transition,400),r=s(n.easing??`ease-out`),i=t.every((t,n)=>t.every((t,r)=>t===e[n][r]));if(n.duration===0||i){W=e,draw(e);return}let a=null,frame=i=>{a===null&&(a=i);let o=i-a,s=!0;W=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)=>l(t[i][n],e,r(a)))}),draw(W),G=s?null:requestAnimationFrame(frame)};G=requestAnimationFrame(frame)}let J;try{return J=i(D,{a11y:O.a11y,legend:O.legend,tooltip:O.tooltip},e=>{let{legend:t,svg:n,tooltip:i}=e;if(n.contains(z)||n.appendChild(z),i?.hide(),t?.update(R.map((e,t)=>({color:e.color??o(t),name:e.name}))),k.length<3){for(let e of[B,V,H,U])e.replaceChildren();W=[];return}let{height:a,width:s}=e.dimensions,c=h(s,a,k.map(e=>e.label),F,C,I);q={cx:s/2,cy:a/2,radius:c};let l=b(k,R,O.domain);renderGrid(l),renderLabels(),renderSeries(),animateTo(R.map(e=>k.map((t,n)=>{let r=datumAt(e,n)?.value;return r!==void 0&&Number.isFinite(r)?v(r,l[n]):0}))),setActive(K);let eventFor=(e,t)=>({axis:k[e],index:e,originalEvent:t,values:valuesAt(e)}),activate=(t,a)=>{setActive(t),O.onHover?.(eventFor(t,a));let s=describe(t);if(!i){e.announcer.announce(s);return}let c=Math.max(0,...W.map(e=>e[t]??0)),l=n.getBoundingClientRect(),u=D.getBoundingClientRect(),p=valuesAt(t),m=p.find(e=>e.datum)?.datum,h=p.flatMap(({datum:e,series:n})=>e?[{color:n.color??o(R.indexOf(n)),name:n.name,value:formatValue(t,e.value)}]:[]);i.show(d(q.cx,q.radius*c,F[t])+(l.left-u.left),f(q.cy,q.radius*c,F[t])+(l.top-u.top),{key:k[t].key,meta:{axis:k[t],text:s,values:p},value:m?.value??0},{color:R[0]?.color??o(0),data:[],name:k[t].label},r(n.ownerDocument,k[t].label,h,s))},deactivate=()=>{setActive(-1),O.onHover?.(null),i?.hide(),e.announcer.clear()},hitIndex=e=>{let t=n.getBoundingClientRect(),r=e.clientX-t.left-q.cx,i=e.clientY-t.top-q.cy;return Math.hypot(r,i)>q.radius+I+22?-1:_(r,i,k.length,P)};return{onClick(e){let t=hitIndex(e);t>=0&&O.onClick?.(eventFor(t,e))},onKeyDown(e){let t=E[e.key];t===void 0?(e.key===`Enter`||e.key===` `)&&K>=0&&O.onClick?(e.preventDefault(),O.onClick(eventFor(K,e))):e.key===`Escape`&&deactivate():(e.preventDefault(),activate(K<0?0:(K+t+k.length)%k.length,e))},onMouseLeave:deactivate,onMouseMove(e){let t=hitIndex(e);t<0?K>=0&&deactivate():t!==K&&activate(t,e)}}},e=>{R=e}),{get disposalSignal(){return J.disposalSignal},dispose(){G!==null&&(cancelAnimationFrame(G),G=null),J.dispose()},get disposed(){return J.disposed},el:J.el,update(e){J.update(e)},[Symbol.dispose](){this.dispose()}}}catch(e){throw J?.dispose(),e}}export{createRadarChart};
1
+ import"../../_dev.js";import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{describeValues as n}from"../../interaction/announcer.js";import{comparisonContent as r}from"../../interaction/tooltip.js";import{createRadialScaffold as i}from"../../core/chart-scaffold.js";import{seriesDomId as a}from"../../core/series-id.js";import{seriesColor as o}from"../../theme/index.js";import{resolveEasing as s}from"../../animation/easing.js";import{resolveMotion as c}from"../../animation/motion.js";import{tweenNumber as l}from"../../animation/tween.js";import{startTween as u}from"../../animation/transition.js";import{uniqueId as d}from"../../core/ids.js";import{polarX as f,polarY as p}from"../../core/polar.js";import{axisAngles as m,closedPath as h,fitRadius as g,labelPlacement as _,nearestAxis as v,normalize as y,radarPoints as b,resolveAxisDomains as x,ringPath as S,toRadians as C}from"./radar-geometry.js";var w=11,T=12,E=10,D={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(O,k){let{axes:A}=k,j=k.curve??`linear`,M=k.fill??`solid`,N=k.showPoints??!0,P=resolveGrid(k.grid),F=C(k.startAngle??0),I=m(A.length,F),L=T+(k.showValues?E:0),R=d(`prism-radar`),z=k.series,B=e(`g`,{class:`prism-radar`}),V=e(`defs`),H=e(`g`,{"aria-hidden":`true`,class:`prism-radar-grid`}),U=e(`g`,{class:`prism-radar-series-group`}),W=e(`g`,{"aria-hidden":`true`,class:`prism-radar-labels`});B.append(V,H,U,W);let G=[],K=null,q=-1,J={cx:0,cy:0,radius:0},datumAt=(e,t)=>e.data.find(e=>e.key===A[t].key),valuesAt=e=>z.map(t=>({datum:datumAt(t,e),series:t})),formatValue=(e,t)=>A[e].format?.(t)??String(t),describe=e=>n(A[e].label,valuesAt(e),t=>formatValue(e,t));function draw(e){let{cx:n,cy:r,radius:i}=J;e.forEach((e,a)=>{let o=U.children[a];if(!o)return;let s=b(e,n,r,i,I);o.querySelector(`.prism-radar-area`)?.setAttribute(`d`,h(s,j)),o.querySelectorAll(`.prism-radar-point`).forEach((e,n)=>{t(e,{cx:s[n].x,cy:s[n].y})}),o.querySelectorAll(`.prism-radar-value`).forEach((a,o)=>{let s=i*e[o]+E;t(a,{x:f(n,s,I[o]),y:p(r,s,I[o])})})})}function renderGrid(t){if(H.replaceChildren(),!P)return;let{cx:n,cy:r,radius:i}=J,a=Math.max(1,Math.round(P.levels)),o=Array.from({length:a},(e,t)=>S(P.shape,n,r,i*(t+1)/a,I));if(P.bands)for(let t=a-1;t>=0;t-=2)H.appendChild(e(`path`,{class:`prism-radar-band`,d:`${o[t]}${o[t-1]??``}`,"fill-rule":`evenodd`}));for(let t of o)H.appendChild(e(`path`,{class:`prism-radar-ring`,d:t,fill:`none`}));I.forEach((t,a)=>{H.appendChild(e(`line`,{class:`prism-radar-spoke`,"data-axis":a,x1:n,x2:f(n,i,t),y1:r,y2:p(r,i,t)}))});let[s,c]=t[0],l=t.every(([e,t])=>e===s&&t===c);if(!P.labels||!l)return;let u=I[0]+Math.PI/I.length;for(let t=1;t<=a;t++){let o=i*t/a,l=e(`text`,{class:`prism-radar-level`,"dominant-baseline":`middle`,"text-anchor":`middle`,x:f(n,o,u),y:p(r,o,u)});l.textContent=formatValue(0,Math.round((s+(c-s)*t/a)*100)/100),H.appendChild(l)}}function renderLabels(){W.replaceChildren();let{cx:t,cy:n,radius:r}=J;A.forEach((i,a)=>{let{anchor:o,baseline:s}=_(I[a]),c=e(`text`,{class:`prism-radar-axis-label`,"dominant-baseline":s,"text-anchor":o,x:f(t,r+L,I[a]),y:p(n,r+L,I[a])});c.textContent=i.label,W.appendChild(c)})}function renderSeries(){let{cx:n,cy:r,radius:i}=J;for(V.replaceChildren();U.children.length>z.length;)U.lastChild?.remove();z.forEach((s,c)=>{let l=s.color??o(c),u=U.children[c];u||(u=e(`g`,{class:`prism-radar-series`}),U.appendChild(u)),u.setAttribute(`data-series-id`,a(s,c)),u.replaceChildren();let d=e(`path`,{class:`prism-radar-area prism-radar-area--${M}`,stroke:l,"stroke-linejoin":`round`,"stroke-width":2});if(M===`gradient`){let a=`${R}-fill-${c}`,o=e(`radialGradient`,{cx:n,cy:r,gradientUnits:`userSpaceOnUse`,id:a,r:i});for(let[t,n]of[[0,.08],[1,.55]])o.appendChild(e(`stop`,{offset:t,"stop-color":l,"stop-opacity":n,style:`stop-color:${l}`}));V.appendChild(o),t(d,{fill:`url(#${a})`})}else t(d,{fill:M===`none`?`none`:l,"fill-opacity":.25});u.appendChild(d),N&&A.forEach((t,n)=>{let r=!Number.isFinite(datumAt(s,n)?.value);u.appendChild(e(`circle`,{class:`prism-radar-point${r?` prism-radar-point--missing`:``}`,"data-axis":n,fill:r?`none`:l,r:3,stroke:l}))}),k.showValues&&A.forEach((t,n)=>{let r=datumAt(s,n),{anchor:i,baseline:a}=_(I[n]),o=e(`text`,{"aria-hidden":`true`,class:`prism-radar-value`,"dominant-baseline":a,"text-anchor":i});o.textContent=r&&Number.isFinite(r.value)?formatValue(n,r.value):``,u.appendChild(o)})})}function setActive(e){q=e;for(let t of B.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){K?.();let n=e.map((e,t)=>e.map((e,n)=>G[t]?.[n]??0)),r=c(k.transition,{defaultDuration:400}),i=s(r.easing??`ease-out`),a=n.every((t,n)=>t.every((t,r)=>t===e[n][r]));if(r.duration===0||a){G=e,draw(e);return}K=u({count:e.length,duration:r.duration,easing:i,onFrame:t=>{G=e.map((e,r)=>{let i=t(r);return e.map((e,t)=>l(n[r][t],e,i))}),draw(G)},signal:t,stagger:r.stagger})}return i(O,{a11y:k.a11y,legend:k.legend,tooltip:k.tooltip},e=>{let{legend:t,svg:n,tooltip:i}=e;if(n.contains(B)||n.appendChild(B),i?.hide(),t?.update(z.map((e,t)=>({color:e.color??o(t),name:e.name}))),A.length<3){for(let e of[V,H,U,W])e.replaceChildren();G=[];return}let{height:a,width:s}=e.dimensions,c=g(s,a,A.map(e=>e.label),I,w,L);J={cx:s/2,cy:a/2,radius:c};let l=x(A,z,k.domain);renderGrid(l),renderLabels(),renderSeries(),animateTo(z.map(e=>A.map((t,n)=>{let r=datumAt(e,n)?.value;return r!==void 0&&Number.isFinite(r)?y(r,l[n]):0})),e.disposalSignal),setActive(q);let eventFor=(e,t)=>({axis:A[e],index:e,originalEvent:t,values:valuesAt(e)}),activate=(t,a)=>{setActive(t),k.onHover?.(eventFor(t,a));let s=describe(t);if(!i){e.announcer.announce(s);return}let c=Math.max(0,...G.map(e=>e[t]??0)),l=n.getBoundingClientRect(),u=O.getBoundingClientRect(),d=valuesAt(t),m=d.find(e=>e.datum)?.datum,h=d.flatMap(({datum:e,series:n})=>e?[{color:n.color??o(z.indexOf(n)),name:n.name,value:formatValue(t,e.value)}]:[]);i.show(f(J.cx,J.radius*c,I[t])+(l.left-u.left),p(J.cy,J.radius*c,I[t])+(l.top-u.top),{key:A[t].key,meta:{axis:A[t],text:s,values:d},value:m?.value??0},{color:z[0]?.color??o(0),data:[],name:A[t].label},r(n.ownerDocument,A[t].label,h,s))},deactivate=()=>{setActive(-1),k.onHover?.(null),i?.hide(),e.announcer.clear()},hitIndex=e=>{let t=n.getBoundingClientRect(),r=e.clientX-t.left-J.cx,i=e.clientY-t.top-J.cy;return Math.hypot(r,i)>J.radius+L+22?-1:v(r,i,A.length,F)};return{onClick(e){let t=hitIndex(e);t>=0&&k.onClick?.(eventFor(t,e))},onKeyDown(e){let t=D[e.key];t===void 0?(e.key===`Enter`||e.key===` `)&&q>=0&&k.onClick?(e.preventDefault(),k.onClick(eventFor(q,e))):e.key===`Escape`&&deactivate():(e.preventDefault(),activate(q<0?0:(q+t+A.length)%A.length,e))},onMouseLeave:deactivate,onMouseMove(e){let t=hitIndex(e);t<0?q>=0&&deactivate():t!==q&&activate(t,e)}}},e=>{z=e})}export{createRadarChart};
2
2
  //# sourceMappingURL=radar-chart.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"radar-chart.js","names":[],"sources":["../../../src/charts/radar/radar-chart.ts"],"sourcesContent":["import { devOnly, warn } from '../../_dev';\nimport { 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 { uniqueId } from '../../core/ids';\nimport { polarX, polarY } from '../../core/polar';\nimport { seriesDomId } from '../../core/series-id';\nimport { describeValues } from '../../interaction/announcer';\nimport { comparisonContent } from '../../interaction/tooltip';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport type {\n ChartHandle,\n RadarAxisConfig,\n RadarAxisValue,\n RadarChartConfig,\n RadarEvent,\n RadarGridConfig,\n RadarSeriesConfig,\n} from '../../types';\nimport {\n axisAngles,\n closedPath,\n fitRadius,\n labelPlacement,\n nearestAxis,\n normalize,\n radarPoints,\n resolveAxisDomains,\n ringPath,\n toRadians,\n} from './radar-geometry';\n\n/** Default `--prism-font-size-label` (0.6875rem) in px, used to reserve label room. */\nconst LABEL_FONT_SIZE = 11;\nconst LABEL_GAP = 12;\nconst VALUE_OFFSET = 10;\nconst ARROW_STEPS: Record<string, number> = { ArrowDown: 1, ArrowLeft: -1, ArrowRight: 1, ArrowUp: -1 };\n\nfunction warnOnInvalid(axes: readonly RadarAxisConfig[], series: readonly RadarSeriesConfig[]): void {\n devOnly(() => {\n if (axes.length < 3) warn(`Radar chart needs at least 3 axes, received ${axes.length}.`);\n\n const keys = new Set(axes.map((axis) => axis.key));\n\n if (keys.size !== axes.length) warn('Radar chart axis keys must be unique.');\n\n for (const s of series) {\n for (const d of s.data) {\n if (!keys.has(d.key)) warn(`Radar series \"${s.name}\" has a value for unknown axis \"${d.key}\".`);\n }\n }\n });\n}\n\nfunction resolveGrid(grid: RadarChartConfig['grid']): Required<RadarGridConfig> | null {\n if (grid === false) return null;\n\n return { bands: true, labels: false, levels: 4, shape: 'polygon', ...(typeof grid === 'object' ? grid : {}) };\n}\n\nexport function createRadarChart(container: HTMLElement, config: RadarChartConfig): ChartHandle<RadarSeriesConfig[]> {\n const { axes } = config;\n const curve = config.curve ?? 'linear';\n const fill = config.fill ?? 'solid';\n const showPoints = config.showPoints ?? true;\n const grid = resolveGrid(config.grid);\n const startAngle = toRadians(config.startAngle ?? 0);\n const angles = axisAngles(axes.length, startAngle);\n const labelGap = LABEL_GAP + (config.showValues ? VALUE_OFFSET : 0);\n const id = uniqueId('prism-radar');\n let series = config.series;\n\n warnOnInvalid(axes, series);\n\n const root = createSvgElement('g', { class: 'prism-radar' });\n const defs = createSvgElement('defs');\n const gridGroup = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-radar-grid' });\n const seriesGroup = createSvgElement('g', { class: 'prism-radar-series-group' });\n const labelGroup = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-radar-labels' });\n\n root.append(defs, gridGroup, seriesGroup, labelGroup);\n\n let drawn: number[][] = [];\n let activeRaf: number | null = null;\n let activeIndex = -1;\n let layout = { cx: 0, cy: 0, radius: 0 };\n\n const datumAt = (s: RadarSeriesConfig, index: number) => s.data.find((d) => d.key === axes[index].key);\n const valuesAt = (index: number): RadarAxisValue[] => series.map((s) => ({ datum: datumAt(s, index), series: s }));\n const formatValue = (index: number, value: number): string => axes[index].format?.(value) ?? String(value);\n const describe = (index: number): string =>\n describeValues(axes[index].label, valuesAt(index), (value) => formatValue(index, value));\n\n function draw(fractions: number[][]): void {\n const { cx, cy, radius } = layout;\n\n fractions.forEach((row, i) => {\n const group = seriesGroup.children[i];\n\n if (!group) return;\n\n const points = radarPoints(row, cx, cy, radius, angles);\n\n group.querySelector('.prism-radar-area')?.setAttribute('d', closedPath(points, curve));\n group.querySelectorAll<SVGCircleElement>('.prism-radar-point').forEach((dot, j) => {\n setAttributes(dot, { cx: points[j].x, cy: points[j].y });\n });\n group.querySelectorAll<SVGTextElement>('.prism-radar-value').forEach((text, j) => {\n const r = radius * row[j] + VALUE_OFFSET;\n\n setAttributes(text, { x: polarX(cx, r, angles[j]), y: polarY(cy, r, angles[j]) });\n });\n });\n }\n\n function renderGrid(domains: [number, number][]): void {\n gridGroup.replaceChildren();\n\n if (!grid) return;\n\n const { cx, cy, radius } = layout;\n const levels = Math.max(1, Math.round(grid.levels));\n const rings = Array.from({ length: levels }, (_, k) =>\n ringPath(grid.shape, cx, cy, (radius * (k + 1)) / levels, angles),\n );\n\n if (grid.bands) {\n // Shade alternate rings, starting from the outermost.\n for (let k = levels - 1; k >= 0; k -= 2) {\n gridGroup.appendChild(\n createSvgElement('path', {\n class: 'prism-radar-band',\n d: `${rings[k]}${rings[k - 1] ?? ''}`,\n 'fill-rule': 'evenodd',\n }),\n );\n }\n }\n\n for (const d of rings)\n gridGroup.appendChild(createSvgElement('path', { class: 'prism-radar-ring', d, fill: 'none' }));\n\n angles.forEach((angle, i) => {\n gridGroup.appendChild(\n createSvgElement('line', {\n class: 'prism-radar-spoke',\n 'data-axis': i,\n x1: cx,\n x2: polarX(cx, radius, angle),\n y1: cy,\n y2: polarY(cy, radius, angle),\n }),\n );\n });\n\n const [d0, d1] = domains[0];\n const shared = domains.every(([a, b]) => a === d0 && b === d1);\n\n if (!grid.labels || !shared) return;\n\n // Between the first two spokes, so level values never collide with vertex values.\n const angle = angles[0] + Math.PI / angles.length;\n\n for (let k = 1; k <= levels; k++) {\n const r = (radius * k) / levels;\n const text = createSvgElement('text', {\n class: 'prism-radar-level',\n 'dominant-baseline': 'middle',\n 'text-anchor': 'middle',\n x: polarX(cx, r, angle),\n y: polarY(cy, r, angle),\n });\n\n text.textContent = formatValue(0, Math.round((d0 + ((d1 - d0) * k) / levels) * 100) / 100);\n gridGroup.appendChild(text);\n }\n }\n\n function renderLabels(): void {\n labelGroup.replaceChildren();\n\n const { cx, cy, radius } = layout;\n\n axes.forEach((axis, i) => {\n const { anchor, baseline } = labelPlacement(angles[i]);\n const text = createSvgElement('text', {\n class: 'prism-radar-axis-label',\n 'dominant-baseline': baseline,\n 'text-anchor': anchor,\n x: polarX(cx, radius + labelGap, angles[i]),\n y: polarY(cy, radius + labelGap, angles[i]),\n });\n\n text.textContent = axis.label;\n labelGroup.appendChild(text);\n });\n }\n\n function renderSeries(): void {\n const { cx, cy, radius } = layout;\n\n defs.replaceChildren();\n\n while (seriesGroup.children.length > series.length) seriesGroup.lastChild?.remove();\n\n series.forEach((s, i) => {\n const color = s.color ?? seriesColor(i);\n let group = seriesGroup.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-radar-series' });\n seriesGroup.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(s, i));\n\n group.replaceChildren();\n\n const area = createSvgElement('path', {\n class: `prism-radar-area prism-radar-area--${fill}`,\n stroke: color,\n 'stroke-linejoin': 'round',\n 'stroke-width': 2,\n });\n\n if (fill === 'gradient') {\n const gradientId = `${id}-fill-${i}`;\n const gradient = createSvgElement('radialGradient', {\n cx,\n cy,\n gradientUnits: 'userSpaceOnUse',\n id: gradientId,\n r: radius,\n });\n\n for (const [offset, opacity] of [\n [0, 0.08],\n [1, 0.55],\n ]) {\n gradient.appendChild(\n createSvgElement('stop', {\n offset,\n 'stop-color': color,\n 'stop-opacity': opacity,\n style: `stop-color:${color}`,\n }),\n );\n }\n\n defs.appendChild(gradient);\n setAttributes(area, { fill: `url(#${gradientId})` });\n } else {\n setAttributes(area, { fill: fill === 'none' ? 'none' : color, 'fill-opacity': 0.25 });\n }\n\n group.appendChild(area);\n\n if (showPoints) {\n axes.forEach((_, j) => {\n const missing = !Number.isFinite(datumAt(s, j)?.value);\n\n group.appendChild(\n createSvgElement('circle', {\n class: `prism-radar-point${missing ? ' prism-radar-point--missing' : ''}`,\n 'data-axis': j,\n fill: missing ? 'none' : color,\n r: 3,\n stroke: color,\n }),\n );\n });\n }\n\n if (config.showValues) {\n axes.forEach((_, j) => {\n const datum = datumAt(s, j);\n const { anchor, baseline } = labelPlacement(angles[j]);\n const text = createSvgElement('text', {\n 'aria-hidden': 'true',\n class: 'prism-radar-value',\n 'dominant-baseline': baseline,\n 'text-anchor': anchor,\n });\n\n text.textContent = datum && Number.isFinite(datum.value) ? formatValue(j, datum.value) : '';\n group.appendChild(text);\n });\n }\n });\n }\n\n function setActive(index: number): void {\n activeIndex = index;\n for (const el of root.querySelectorAll('[data-axis]')) {\n const active = Number(el.getAttribute('data-axis')) === index;\n\n el.classList.toggle(el.tagName === 'line' ? 'prism-radar-spoke--active' : 'prism-radar-point--active', active);\n }\n }\n\n function animateTo(targets: number[][]): void {\n if (activeRaf !== null) {\n cancelAnimationFrame(activeRaf);\n activeRaf = null;\n }\n\n const from = targets.map((row, i) => row.map((_, j) => drawn[i]?.[j] ?? 0));\n const motion = resolveMotion(config.transition, 400);\n const easing = resolveEasing(motion.easing ?? 'ease-out');\n const unchanged = from.every((row, i) => row.every((v, j) => v === targets[i][j]));\n\n if (motion.duration === 0 || unchanged) {\n drawn = targets;\n draw(targets);\n\n return;\n }\n\n let start: number | null = null;\n\n const frame = (ts: number): void => {\n if (start === null) start = ts;\n\n const elapsed = ts - start;\n let done = true;\n\n drawn = targets.map((row, i) => {\n const raw = Math.max(0, Math.min(1, (elapsed - i * motion.stagger) / motion.duration));\n\n if (raw < 1) done = false;\n\n return row.map((to, j) => tweenNumber(from[i][j], to, easing(raw)));\n });\n draw(drawn);\n activeRaf = done ? null : requestAnimationFrame(frame);\n };\n\n activeRaf = requestAnimationFrame(frame);\n }\n\n let handle: ChartHandle<RadarSeriesConfig[]> | undefined;\n\n try {\n handle = createRadialScaffold(\n container,\n { a11y: config.a11y, legend: config.legend, tooltip: config.tooltip },\n (ctx): ChartEventHandlers | undefined => {\n const { legend, svg, tooltip } = ctx;\n\n if (!svg.contains(root)) svg.appendChild(root);\n\n tooltip?.hide();\n legend?.update(series.map((s, i) => ({ color: s.color ?? seriesColor(i), name: s.name })));\n\n if (axes.length < 3) {\n for (const group of [defs, gridGroup, seriesGroup, labelGroup]) group.replaceChildren();\n drawn = [];\n\n return undefined;\n }\n\n const { height, width } = ctx.dimensions;\n const radius = fitRadius(\n width,\n height,\n axes.map((axis) => axis.label),\n angles,\n LABEL_FONT_SIZE,\n labelGap,\n );\n\n layout = { cx: width / 2, cy: height / 2, radius };\n\n const domains = resolveAxisDomains(axes, series, config.domain);\n\n renderGrid(domains);\n renderLabels();\n renderSeries();\n animateTo(\n series.map((s) =>\n axes.map((_, j) => {\n const value = datumAt(s, j)?.value;\n\n return value !== undefined && Number.isFinite(value) ? normalize(value, domains[j]) : 0;\n }),\n ),\n );\n setActive(activeIndex);\n\n const eventFor = (index: number, originalEvent: Event): RadarEvent => ({\n axis: axes[index],\n index,\n originalEvent,\n values: valuesAt(index),\n });\n\n const activate = (index: number, originalEvent: Event): void => {\n setActive(index);\n config.onHover?.(eventFor(index, originalEvent));\n\n const text = describe(index);\n\n if (!tooltip) {\n ctx.announcer.announce(text);\n\n return;\n }\n\n const reach = Math.max(0, ...drawn.map((row) => row[index] ?? 0));\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const values = valuesAt(index);\n const first = values.find((v) => v.datum)?.datum;\n const rows = values.flatMap(({ datum, series: s }) =>\n datum\n ? [\n {\n color: s.color ?? seriesColor(series.indexOf(s)),\n name: s.name,\n value: formatValue(index, datum.value),\n },\n ]\n : [],\n );\n\n tooltip.show(\n polarX(layout.cx, layout.radius * reach, angles[index]) + (svgRect.left - containerRect.left),\n polarY(layout.cy, layout.radius * reach, angles[index]) + (svgRect.top - containerRect.top),\n { key: axes[index].key, meta: { axis: axes[index], text, values }, value: first?.value ?? 0 },\n { color: series[0]?.color ?? seriesColor(0), data: [], name: axes[index].label },\n comparisonContent(svg.ownerDocument, axes[index].label, rows, text),\n );\n };\n\n const deactivate = (): void => {\n setActive(-1);\n config.onHover?.(null);\n tooltip?.hide();\n ctx.announcer.clear();\n };\n\n const hitIndex = (event: MouseEvent): number => {\n const rect = svg.getBoundingClientRect();\n const dx = event.clientX - rect.left - layout.cx;\n const dy = event.clientY - rect.top - layout.cy;\n\n if (Math.hypot(dx, dy) > layout.radius + labelGap + LABEL_FONT_SIZE * 2) return -1;\n\n return nearestAxis(dx, dy, axes.length, startAngle);\n };\n\n return {\n onClick(event) {\n const index = hitIndex(event);\n\n if (index >= 0) config.onClick?.(eventFor(index, event));\n },\n onKeyDown(event) {\n const step = ARROW_STEPS[event.key];\n\n if (step !== undefined) {\n event.preventDefault();\n activate(activeIndex < 0 ? 0 : (activeIndex + step + axes.length) % axes.length, event);\n } else if ((event.key === 'Enter' || event.key === ' ') && activeIndex >= 0 && config.onClick) {\n event.preventDefault();\n config.onClick(eventFor(activeIndex, event));\n } else if (event.key === 'Escape') {\n deactivate();\n }\n },\n onMouseLeave: deactivate,\n onMouseMove(event) {\n const index = hitIndex(event);\n\n if (index < 0) {\n if (activeIndex >= 0) deactivate();\n } else if (index !== activeIndex) {\n activate(index, event);\n }\n },\n };\n },\n (next) => {\n series = next;\n warnOnInvalid(axes, series);\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"],"mappings":"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"}
1
+ {"version":3,"file":"radar-chart.js","names":[],"sources":["../../../src/charts/radar/radar-chart.ts"],"sourcesContent":["import { devOnly, warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport type { ChartEventHandlers } from '../../core/chart-scaffold';\nimport { createRadialScaffold } from '../../core/chart-scaffold';\nimport { uniqueId } from '../../core/ids';\nimport { polarX, polarY } from '../../core/polar';\nimport { seriesDomId } from '../../core/series-id';\nimport { describeValues } from '../../interaction/announcer';\nimport { comparisonContent } from '../../interaction/tooltip';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport type {\n ChartHandle,\n RadarAxisConfig,\n RadarAxisValue,\n RadarChartConfig,\n RadarEvent,\n RadarGridConfig,\n RadarSeriesConfig,\n} from '../../types';\nimport {\n axisAngles,\n closedPath,\n fitRadius,\n labelPlacement,\n nearestAxis,\n normalize,\n radarPoints,\n resolveAxisDomains,\n ringPath,\n toRadians,\n} from './radar-geometry';\n\n/** Default `--prism-font-size-label` (0.6875rem) in px, used to reserve label room. */\nconst LABEL_FONT_SIZE = 11;\nconst LABEL_GAP = 12;\nconst VALUE_OFFSET = 10;\nconst ARROW_STEPS: Record<string, number> = { ArrowDown: 1, ArrowLeft: -1, ArrowRight: 1, ArrowUp: -1 };\n\nfunction warnOnInvalid(axes: readonly RadarAxisConfig[], series: readonly RadarSeriesConfig[]): void {\n devOnly(() => {\n if (axes.length < 3) warn(`Radar chart needs at least 3 axes, received ${axes.length}.`);\n\n const keys = new Set(axes.map((axis) => axis.key));\n\n if (keys.size !== axes.length) warn('Radar chart axis keys must be unique.');\n\n for (const s of series) {\n for (const d of s.data) {\n if (!keys.has(d.key)) warn(`Radar series \"${s.name}\" has a value for unknown axis \"${d.key}\".`);\n }\n }\n });\n}\n\nfunction resolveGrid(grid: RadarChartConfig['grid']): Required<RadarGridConfig> | null {\n if (grid === false) return null;\n\n return { bands: true, labels: false, levels: 4, shape: 'polygon', ...(typeof grid === 'object' ? grid : {}) };\n}\n\nexport function createRadarChart(container: HTMLElement, config: RadarChartConfig): ChartHandle<RadarSeriesConfig[]> {\n const { axes } = config;\n const curve = config.curve ?? 'linear';\n const fill = config.fill ?? 'solid';\n const showPoints = config.showPoints ?? true;\n const grid = resolveGrid(config.grid);\n const startAngle = toRadians(config.startAngle ?? 0);\n const angles = axisAngles(axes.length, startAngle);\n const labelGap = LABEL_GAP + (config.showValues ? VALUE_OFFSET : 0);\n const id = uniqueId('prism-radar');\n let series = config.series;\n\n warnOnInvalid(axes, series);\n\n const root = createSvgElement('g', { class: 'prism-radar' });\n const defs = createSvgElement('defs');\n const gridGroup = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-radar-grid' });\n const seriesGroup = createSvgElement('g', { class: 'prism-radar-series-group' });\n const labelGroup = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-radar-labels' });\n\n root.append(defs, gridGroup, seriesGroup, labelGroup);\n\n let drawn: number[][] = [];\n let activeTween: (() => void) | null = null;\n let activeIndex = -1;\n let layout = { cx: 0, cy: 0, radius: 0 };\n\n const datumAt = (s: RadarSeriesConfig, index: number) => s.data.find((d) => d.key === axes[index].key);\n const valuesAt = (index: number): RadarAxisValue[] => series.map((s) => ({ datum: datumAt(s, index), series: s }));\n const formatValue = (index: number, value: number): string => axes[index].format?.(value) ?? String(value);\n const describe = (index: number): string =>\n describeValues(axes[index].label, valuesAt(index), (value) => formatValue(index, value));\n\n function draw(fractions: number[][]): void {\n const { cx, cy, radius } = layout;\n\n fractions.forEach((row, i) => {\n const group = seriesGroup.children[i];\n\n if (!group) return;\n\n const points = radarPoints(row, cx, cy, radius, angles);\n\n group.querySelector('.prism-radar-area')?.setAttribute('d', closedPath(points, curve));\n group.querySelectorAll<SVGCircleElement>('.prism-radar-point').forEach((dot, j) => {\n setAttributes(dot, { cx: points[j].x, cy: points[j].y });\n });\n group.querySelectorAll<SVGTextElement>('.prism-radar-value').forEach((text, j) => {\n const r = radius * row[j] + VALUE_OFFSET;\n\n setAttributes(text, { x: polarX(cx, r, angles[j]), y: polarY(cy, r, angles[j]) });\n });\n });\n }\n\n function renderGrid(domains: [number, number][]): void {\n gridGroup.replaceChildren();\n\n if (!grid) return;\n\n const { cx, cy, radius } = layout;\n const levels = Math.max(1, Math.round(grid.levels));\n const rings = Array.from({ length: levels }, (_, k) =>\n ringPath(grid.shape, cx, cy, (radius * (k + 1)) / levels, angles),\n );\n\n if (grid.bands) {\n // Shade alternate rings, starting from the outermost.\n for (let k = levels - 1; k >= 0; k -= 2) {\n gridGroup.appendChild(\n createSvgElement('path', {\n class: 'prism-radar-band',\n d: `${rings[k]}${rings[k - 1] ?? ''}`,\n 'fill-rule': 'evenodd',\n }),\n );\n }\n }\n\n for (const d of rings)\n gridGroup.appendChild(createSvgElement('path', { class: 'prism-radar-ring', d, fill: 'none' }));\n\n angles.forEach((angle, i) => {\n gridGroup.appendChild(\n createSvgElement('line', {\n class: 'prism-radar-spoke',\n 'data-axis': i,\n x1: cx,\n x2: polarX(cx, radius, angle),\n y1: cy,\n y2: polarY(cy, radius, angle),\n }),\n );\n });\n\n const [d0, d1] = domains[0];\n const shared = domains.every(([a, b]) => a === d0 && b === d1);\n\n if (!grid.labels || !shared) return;\n\n // Between the first two spokes, so level values never collide with vertex values.\n const angle = angles[0] + Math.PI / angles.length;\n\n for (let k = 1; k <= levels; k++) {\n const r = (radius * k) / levels;\n const text = createSvgElement('text', {\n class: 'prism-radar-level',\n 'dominant-baseline': 'middle',\n 'text-anchor': 'middle',\n x: polarX(cx, r, angle),\n y: polarY(cy, r, angle),\n });\n\n text.textContent = formatValue(0, Math.round((d0 + ((d1 - d0) * k) / levels) * 100) / 100);\n gridGroup.appendChild(text);\n }\n }\n\n function renderLabels(): void {\n labelGroup.replaceChildren();\n\n const { cx, cy, radius } = layout;\n\n axes.forEach((axis, i) => {\n const { anchor, baseline } = labelPlacement(angles[i]);\n const text = createSvgElement('text', {\n class: 'prism-radar-axis-label',\n 'dominant-baseline': baseline,\n 'text-anchor': anchor,\n x: polarX(cx, radius + labelGap, angles[i]),\n y: polarY(cy, radius + labelGap, angles[i]),\n });\n\n text.textContent = axis.label;\n labelGroup.appendChild(text);\n });\n }\n\n function renderSeries(): void {\n const { cx, cy, radius } = layout;\n\n defs.replaceChildren();\n\n while (seriesGroup.children.length > series.length) seriesGroup.lastChild?.remove();\n\n series.forEach((s, i) => {\n const color = s.color ?? seriesColor(i);\n let group = seriesGroup.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-radar-series' });\n seriesGroup.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(s, i));\n\n group.replaceChildren();\n\n const area = createSvgElement('path', {\n class: `prism-radar-area prism-radar-area--${fill}`,\n stroke: color,\n 'stroke-linejoin': 'round',\n 'stroke-width': 2,\n });\n\n if (fill === 'gradient') {\n const gradientId = `${id}-fill-${i}`;\n const gradient = createSvgElement('radialGradient', {\n cx,\n cy,\n gradientUnits: 'userSpaceOnUse',\n id: gradientId,\n r: radius,\n });\n\n for (const [offset, opacity] of [\n [0, 0.08],\n [1, 0.55],\n ]) {\n gradient.appendChild(\n createSvgElement('stop', {\n offset,\n 'stop-color': color,\n 'stop-opacity': opacity,\n style: `stop-color:${color}`,\n }),\n );\n }\n\n defs.appendChild(gradient);\n setAttributes(area, { fill: `url(#${gradientId})` });\n } else {\n setAttributes(area, { fill: fill === 'none' ? 'none' : color, 'fill-opacity': 0.25 });\n }\n\n group.appendChild(area);\n\n if (showPoints) {\n axes.forEach((_, j) => {\n const missing = !Number.isFinite(datumAt(s, j)?.value);\n\n group.appendChild(\n createSvgElement('circle', {\n class: `prism-radar-point${missing ? ' prism-radar-point--missing' : ''}`,\n 'data-axis': j,\n fill: missing ? 'none' : color,\n r: 3,\n stroke: color,\n }),\n );\n });\n }\n\n if (config.showValues) {\n axes.forEach((_, j) => {\n const datum = datumAt(s, j);\n const { anchor, baseline } = labelPlacement(angles[j]);\n const text = createSvgElement('text', {\n 'aria-hidden': 'true',\n class: 'prism-radar-value',\n 'dominant-baseline': baseline,\n 'text-anchor': anchor,\n });\n\n text.textContent = datum && Number.isFinite(datum.value) ? formatValue(j, datum.value) : '';\n group.appendChild(text);\n });\n }\n });\n }\n\n function setActive(index: number): void {\n activeIndex = index;\n for (const el of root.querySelectorAll('[data-axis]')) {\n const active = Number(el.getAttribute('data-axis')) === index;\n\n el.classList.toggle(el.tagName === 'line' ? 'prism-radar-spoke--active' : 'prism-radar-point--active', active);\n }\n }\n\n function animateTo(targets: number[][], signal: AbortSignal): void {\n activeTween?.();\n\n const from = targets.map((row, i) => row.map((_, j) => drawn[i]?.[j] ?? 0));\n // Radar morphs a whole polygon, so it reads better slightly slower than the shared default.\n const motion = resolveMotion(config.transition, { defaultDuration: 400 });\n const easing = resolveEasing(motion.easing ?? 'ease-out');\n const unchanged = from.every((row, i) => row.every((v, j) => v === targets[i][j]));\n\n if (motion.duration === 0 || unchanged) {\n drawn = targets;\n draw(targets);\n\n return;\n }\n\n activeTween = startTween({\n count: targets.length,\n duration: motion.duration,\n easing,\n onFrame: (progress) => {\n drawn = targets.map((row, i) => {\n const e = progress(i);\n\n return row.map((to, j) => tweenNumber(from[i][j], to, e));\n });\n draw(drawn);\n },\n signal,\n stagger: motion.stagger,\n });\n }\n\n return createRadialScaffold(\n container,\n { a11y: config.a11y, legend: config.legend, tooltip: config.tooltip },\n (ctx): ChartEventHandlers | undefined => {\n const { legend, svg, tooltip } = ctx;\n\n if (!svg.contains(root)) svg.appendChild(root);\n\n tooltip?.hide();\n legend?.update(series.map((s, i) => ({ color: s.color ?? seriesColor(i), name: s.name })));\n\n if (axes.length < 3) {\n for (const group of [defs, gridGroup, seriesGroup, labelGroup]) group.replaceChildren();\n drawn = [];\n\n return undefined;\n }\n\n const { height, width } = ctx.dimensions;\n const radius = fitRadius(\n width,\n height,\n axes.map((axis) => axis.label),\n angles,\n LABEL_FONT_SIZE,\n labelGap,\n );\n\n layout = { cx: width / 2, cy: height / 2, radius };\n\n const domains = resolveAxisDomains(axes, series, config.domain);\n\n renderGrid(domains);\n renderLabels();\n renderSeries();\n animateTo(\n series.map((s) =>\n axes.map((_, j) => {\n const value = datumAt(s, j)?.value;\n\n return value !== undefined && Number.isFinite(value) ? normalize(value, domains[j]) : 0;\n }),\n ),\n ctx.disposalSignal,\n );\n setActive(activeIndex);\n\n const eventFor = (index: number, originalEvent: Event): RadarEvent => ({\n axis: axes[index],\n index,\n originalEvent,\n values: valuesAt(index),\n });\n\n const activate = (index: number, originalEvent: Event): void => {\n setActive(index);\n config.onHover?.(eventFor(index, originalEvent));\n\n const text = describe(index);\n\n if (!tooltip) {\n ctx.announcer.announce(text);\n\n return;\n }\n\n const reach = Math.max(0, ...drawn.map((row) => row[index] ?? 0));\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const values = valuesAt(index);\n const first = values.find((v) => v.datum)?.datum;\n const rows = values.flatMap(({ datum, series: s }) =>\n datum\n ? [\n {\n color: s.color ?? seriesColor(series.indexOf(s)),\n name: s.name,\n value: formatValue(index, datum.value),\n },\n ]\n : [],\n );\n\n tooltip.show(\n polarX(layout.cx, layout.radius * reach, angles[index]) + (svgRect.left - containerRect.left),\n polarY(layout.cy, layout.radius * reach, angles[index]) + (svgRect.top - containerRect.top),\n { key: axes[index].key, meta: { axis: axes[index], text, values }, value: first?.value ?? 0 },\n { color: series[0]?.color ?? seriesColor(0), data: [], name: axes[index].label },\n comparisonContent(svg.ownerDocument, axes[index].label, rows, text),\n );\n };\n\n const deactivate = (): void => {\n setActive(-1);\n config.onHover?.(null);\n tooltip?.hide();\n ctx.announcer.clear();\n };\n\n const hitIndex = (event: MouseEvent): number => {\n const rect = svg.getBoundingClientRect();\n const dx = event.clientX - rect.left - layout.cx;\n const dy = event.clientY - rect.top - layout.cy;\n\n if (Math.hypot(dx, dy) > layout.radius + labelGap + LABEL_FONT_SIZE * 2) return -1;\n\n return nearestAxis(dx, dy, axes.length, startAngle);\n };\n\n return {\n onClick(event) {\n const index = hitIndex(event);\n\n if (index >= 0) config.onClick?.(eventFor(index, event));\n },\n onKeyDown(event) {\n const step = ARROW_STEPS[event.key];\n\n if (step !== undefined) {\n event.preventDefault();\n activate(activeIndex < 0 ? 0 : (activeIndex + step + axes.length) % axes.length, event);\n } else if ((event.key === 'Enter' || event.key === ' ') && activeIndex >= 0 && config.onClick) {\n event.preventDefault();\n config.onClick(eventFor(activeIndex, event));\n } else if (event.key === 'Escape') {\n deactivate();\n }\n },\n onMouseLeave: deactivate,\n onMouseMove(event) {\n const index = hitIndex(event);\n\n if (index < 0) {\n if (activeIndex >= 0) deactivate();\n } else if (index !== activeIndex) {\n activate(index, event);\n }\n },\n };\n },\n (next) => {\n series = next;\n warnOnInvalid(axes, series);\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("../../errors.cjs"),n=require("../../core/chart-base.cjs"),r=require("../../animation/easing.cjs"),i=require("../../animation/motion.cjs"),a=require("../../animation/tween.cjs"),o=require("../../core/ids.cjs"),s=require("../../svg/path.cjs");var c=5;function buildTopPoints(e,t,n){if(e.length===0)return[];let r=t/Math.max(1,e.length-1),i=Math.min(...e),a=Math.max(...e)-i||1;return e.map((e,t)=>({x:t*r,y:n-(e-i)/a*n}))}function buildAreaPath(e,t,n,r=`linear`){if(e.length===0)return``;let i=buildTopPoints(e,t,n),a=i.map(e=>({x:e.x,y:n}));return s.areaPath(i,a,r??`linear`)}function buildPath(e,t,n,r){if(e.length===0)return``;let i=buildTopPoints(e,t,n);return r===`monotone`?s.monotonePath(i):r===`step`?s.stepPath(i):s.linePath(i)}function renderSparkBars(t,n,o,s,c,l,u){let d=n.length,f=Math.max(1,o/d-1),p=o/d,m=Math.min(0,...n),h=Math.max(...n)-m||1,g=i.resolveMotion(l,0),_=g.duration,v=r.resolveEasing(g.easing);for(;t.children.length>d;){let e=t.lastElementChild;e&&t.removeChild(e)}for(let r=0;r<d;r++){let i=Math.max(1,(n[r]-m)/h*s),o=s-i,l=t.children[r];if(l||(l=e.createSvgElement(`rect`,{class:`prism-spark-bar`}),t.appendChild(l)),e.setAttributes(l,{fill:c,width:f,x:r*p}),_>0&&!l.hasAttribute(`data-init`)){l.setAttribute(`data-init`,`1`),e.setAttributes(l,{height:0,y:s});let t=null,n={h:0,y:s},r={h:i,y:o},frame=i=>{if(u?.aborted)return;t===null&&(t=i);let o=v(Math.min(1,(i-t)/_));e.setAttributes(l,{height:a.tweenNumber(n.h,r.h,o),y:a.tweenNumber(n.y,r.y,o)}),o<1&&requestAnimationFrame(frame)};requestAnimationFrame(frame)}else l.setAttribute(`data-init`,`1`),e.setAttributes(l,{height:i,y:o})}}function isStackData(e){return e.length>0&&e[0]!==null&&typeof e[0]==`object`}function buildRoundedStackRect(e,t,n,r,i,a,o){let s=Math.min(i,n/2,r/2),c=a?s:0,l=a?s:0,u=o?s:0,d=o?s:0;return[`M${e+c},${t}`,`H${e+n-u}`,u?`Q${e+n},${t} ${e+n},${t+u}`:``,`V${t+r-d}`,d?`Q${e+n},${t+r} ${e+n-d},${t+r}`:``,`H${e+l}`,l?`Q${e},${t+r} ${e},${t+r-l}`:``,`V${t+c}`,c?`Q${e},${t} ${e+c},${t}`:``,`Z`].filter(Boolean).join(``)}function defaultStackColor(e){return`var(--prism-color-${e%8+1})`}function createSparkline(r,i){let a=i.variant??`line`,s=i.color??`var(--prism-color-1)`,l=i.curve??`linear`,u=i.strokeWidth??1.5,d=i.fillOpacity,f=i.showEndPoint??!0,p=o.uniqueId(`prism-spark-fill`),m=i.data,h=n.createChartBase(r,{a11y:i.a11y,margin:{bottom:0,left:0,right:0,top:0}},renderAll),{svg:g}=h;g.classList.add(`prism-sparkline`);let _=e.createSvgElement(`g`,{class:`prism-spark-inner`});g.appendChild(_);let cleanupInteraction;function plotArea(){let{height:e,width:t}=h.dimensions,n=a===`line`||a===`area`?c:0;return{h:Math.max(1,e-n*2),inset:n,w:Math.max(1,t-n*2)}}function renderAll(){let{height:t,width:n}=h.dimensions,r=plotArea();for(;_.firstChild;)_.removeChild(_.firstChild);if(_.setAttribute(`transform`,`translate(${r.inset},${r.inset})`),m.length!==0){if(!isStackData(m)&&m.some(e=>!Number.isFinite(e)),a===`stack`&&isStackData(m)){let r=e.createSvgElement(`g`,{class:`prism-spark-stack`});_.appendChild(r);let a=i.cornerRadius??4,o=m,s=o.reduce((e,t)=>e+Math.max(0,t.value),0);if(s>0){let c=(i.padPixels??0)/2,l=0;o.forEach((i,u)=>{let d=Math.round(l);l+=Math.max(0,i.value)/s*n;let f=u===o.length-1?n:Math.round(l),p=u===0,m=u===o.length-1,h=buildRoundedStackRect(d+(p?0:c),0,Math.max(0,f-d-(p?0:c)-(m?0:c)),t,a,p,m),g=e.createSvgElement(`path`,{class:`prism-spark-stack-segment`});e.setAttributes(g,{d:h,fill:i.color??defaultStackColor(u)}),r.appendChild(g)})}}else if(a===`bar`){let r=e.createSvgElement(`g`,{class:`prism-spark-bars`});_.appendChild(r),renderSparkBars(r,m,n,t,s,i.transition,v.signal)}else{if(a===`area`){let t=e.createSvgElement(`defs`),n=e.createSvgElement(`linearGradient`,{id:p,x1:0,x2:0,y1:0,y2:1});for(let[t,r]of[[0,`prism-spark-stop-top`],[1,`prism-spark-stop-bottom`]]){let i=e.createSvgElement(`stop`,{class:r,offset:t,"stop-color":s});i.style.stopColor=s,n.appendChild(i)}t.appendChild(n),_.appendChild(t);let i=e.createSvgElement(`path`,{class:`prism-spark-fill`}),a=buildAreaPath(m,r.w,r.h,l);e.setAttributes(i,{d:a,fill:`url(#${p})`,stroke:`none`}),i.style.fillOpacity=d===void 0?``:String(d),_.appendChild(i)}let t=e.createSvgElement(`path`,{class:`prism-spark-line`}),n=buildPath(m,r.w,r.h,l);e.setAttributes(t,{d:n,fill:`none`,stroke:s,"stroke-width":u}),_.appendChild(t);let i=buildTopPoints(m,r.w,r.h).at(-1);f&&i&&_.appendChild(e.createSvgElement(`circle`,{class:`prism-spark-end`,cx:i.x,cy:i.y,fill:s,r:2.5}))}isStackData(m)||attachInteraction(m)}}function attachInteraction(t){if(cleanupInteraction?.(),cleanupInteraction=void 0,!i.onHover&&!i.onClick||t.length<=1)return;let{h:n,inset:r,w:o}=plotArea();g.style.cursor=`crosshair`;let c=o/(t.length-1),l=a===`bar`?[]:buildTopPoints(t,o,n),u=e.createSvgElement(`circle`,{class:`prism-spark-marker`,fill:s,r:3.5}),indexAt=e=>Math.max(0,Math.min(t.length-1,Math.round((e-g.getBoundingClientRect().left-r)/c)));u.style.display=`none`,_.appendChild(u);let handleMove=n=>{let r=indexAt(n.clientX),a=l[r];a&&(e.setAttributes(u,{cx:a.x,cy:a.y}),u.style.display=``),i.onHover?.(r,t[r])},handleLeave=()=>{u.style.display=`none`,i.onHover?.(null,null)},handleClick=e=>{if(!i.onClick)return;let n=indexAt(e.clientX);i.onClick(n,t[n])};g.addEventListener(`mousemove`,handleMove),g.addEventListener(`mouseleave`,handleLeave),g.addEventListener(`click`,handleClick),cleanupInteraction=()=>{g.removeEventListener(`mousemove`,handleMove),g.removeEventListener(`mouseleave`,handleLeave),g.removeEventListener(`click`,handleClick)}}let v=new AbortController,y=!1;try{return renderAll(),{get disposalSignal(){return v.signal},dispose(){y||(y=!0,v.abort(),cleanupInteraction?.(),h.dispose())},get disposed(){return y},el:g,update(e){if(y)throw new t.PrismRenderError(`Cannot update a disposed chart.`);m=e,renderAll()},[Symbol.dispose](){this.dispose()}}}catch(e){throw v.abort(),cleanupInteraction?.(),h.dispose(),e instanceof t.PrismRenderError?e:new t.PrismRenderError(`Failed to render chart.`,{cause:e})}}exports.createSparkline=createSparkline;
1
+ require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../_tappers.cjs"),n=require("../../errors.cjs"),r=require("../../core/chart-base.cjs"),i=require("../../animation/easing.cjs"),a=require("../../animation/motion.cjs"),o=require("../../animation/tween.cjs"),s=require("../../animation/transition.cjs"),c=require("../../core/ids.cjs"),l=require("../../svg/path.cjs");var u=5;function buildTopPoints(e,t,n){if(e.length===0)return[];let r=t/Math.max(1,e.length-1),i=Math.min(...e),a=Math.max(...e)-i||1;return e.map((e,t)=>({x:t*r,y:n-(e-i)/a*n}))}function buildAreaPathFromPoints(e,t,n){if(e.length===0)return``;let r=e.map(e=>({x:e.x,y:t}));return l.areaPath(e,r,n??`linear`)}function buildPathFromPoints(e,t){return e.length===0?``:t===`monotone`?l.monotonePath(e):t===`step`?l.stepPath(e):l.linePath(e)}function isStackData(e){return e.length>0&&e[0]!==null&&typeof e[0]==`object`}function buildRoundedStackRect(e,t,n,r,i,a,o){let s=Math.min(i,n/2,r/2),c=a?s:0,l=a?s:0,u=o?s:0,d=o?s:0;return[`M${e+c},${t}`,`H${e+n-u}`,u?`Q${e+n},${t} ${e+n},${t+u}`:``,`V${t+r-d}`,d?`Q${e+n},${t+r} ${e+n-d},${t+r}`:``,`H${e+l}`,l?`Q${e},${t+r} ${e},${t+r-l}`:``,`V${t+c}`,c?`Q${e},${t} ${e+c},${t}`:``,`Z`].filter(Boolean).join(``)}function defaultStackColor(e){return`var(--prism-color-${e%8+1})`}function createSparkline(l,d){let f=d.variant??`line`,p=d.color??`var(--prism-color-1)`,m=d.curve??`linear`,h=d.strokeWidth??1.5,g=d.fillOpacity,_=d.showEndPoint??!0,v=c.uniqueId(`prism-spark-fill`),y=t.createTappers(),b=a.resolveMotion(d.transition),x=i.resolveEasing(b.easing),S=d.data,C=null,w=null,T=r.createChartBase(l,{a11y:d.a11y,margin:{bottom:0,left:0,right:0,top:0}},()=>{y.emit({height:T.dimensions.height,type:`resize`,width:T.dimensions.width}),renderAll()}),{svg:E}=T;E.classList.add(`prism-sparkline`);let D=e.createSvgElement(`g`,{class:`prism-spark-inner`});E.appendChild(D);let cleanupInteraction;function plotArea(){let{height:e,width:t}=T.dimensions,n=f===`line`||f===`area`?u:0;return{h:Math.max(1,e-n*2),inset:n,w:Math.max(1,t-n*2)}}function animateValues(e,t,n){w?.();let r=C?.length===e.length?C:e.map(()=>t);if(r.every((t,n)=>t===e[n])||b.duration===0){C=e,n(e);return}w=s.startTween({count:1,duration:b.duration,easing:x,onFrame:t=>{let i=t(0),a=e.map((e,t)=>o.tweenNumber(r[t],e,i));C=a,n(a)},signal:O.signal}),C=r,n(r)}function renderAll(){let{height:t,width:n}=T.dimensions,r=plotArea();for(;D.firstChild;)D.removeChild(D.firstChild);if(D.setAttribute(`transform`,`translate(${r.inset},${r.inset})`),S.length===0){C=null;return}if(!isStackData(S)&&S.some(e=>!Number.isFinite(e)),f===`stack`&&isStackData(S)){let r=e.createSvgElement(`g`,{class:`prism-spark-stack`});D.appendChild(r);let i=d.cornerRadius??4,a=S,o=a.reduce((e,t)=>e+Math.max(0,t.value),0),s=a.map((t,n)=>{let i=e.createSvgElement(`path`,{class:`prism-spark-stack-segment`});return e.setAttributes(i,{fill:t.color??defaultStackColor(n)}),r.appendChild(i),i});o>0?animateValues(a.map(e=>Math.max(0,e.value)),0,e=>{let r=e.reduce((e,t)=>e+t,0)||1,a=(d.padPixels??0)/2,o=0;e.forEach((c,l)=>{let u=Math.round(o);o+=c/r*n;let d=l===e.length-1?n:Math.round(o),f=l===0,p=l===e.length-1,m=u+(f?0:a),h=Math.max(0,d-u-(f?0:a)-(p?0:a));s[l]?.setAttribute(`d`,buildRoundedStackRect(m,0,h,t,i,f,p))})}):(w?.(),C=null)}else if(f===`bar`){let r=e.createSvgElement(`g`,{class:`prism-spark-bars`});D.appendChild(r);let i=S,a=Math.min(0,...i),o=Math.max(...i)-a||1,s=Math.max(1,n/i.length-1),c=n/i.length,l=i.map(()=>{let t=e.createSvgElement(`rect`,{class:`prism-spark-bar`,fill:p});return r.appendChild(t),t});animateValues(i,a,n=>{for(let[r,i]of l.entries()){let l=Math.max(1,(n[r]-a)/o*t);e.setAttributes(i,{height:l,width:s,x:r*c,y:t-l})}})}else{let t=S,n=Math.min(...t),i=Math.max(...t)-n||1,a=r.w/Math.max(1,t.length-1),pointsFromValues=e=>e.map((e,t)=>({x:t*a,y:r.h-(e-n)/i*r.h})),o=null;if(f===`area`){let t=e.createSvgElement(`defs`),n=e.createSvgElement(`linearGradient`,{id:v,x1:0,x2:0,y1:0,y2:1});for(let[t,r]of[[0,`prism-spark-stop-top`],[1,`prism-spark-stop-bottom`]]){let i=e.createSvgElement(`stop`,{class:r,offset:t,"stop-color":p});i.style.stopColor=p,n.appendChild(i)}t.appendChild(n),D.appendChild(t),o=e.createSvgElement(`path`,{class:`prism-spark-fill`}),e.setAttributes(o,{fill:`url(#${v})`,stroke:`none`}),o.style.fillOpacity=g===void 0?``:String(g),D.appendChild(o)}let s=e.createSvgElement(`path`,{class:`prism-spark-line`});e.setAttributes(s,{fill:`none`,stroke:p,"stroke-width":h}),D.appendChild(s);let c=_&&t.length>0?e.createSvgElement(`circle`,{class:`prism-spark-end`,fill:p,r:2.5}):null;c&&D.appendChild(c),animateValues(t,n,t=>{let n=pointsFromValues(t);e.setAttributes(s,{d:buildPathFromPoints(n,m)}),o&&e.setAttributes(o,{d:buildAreaPathFromPoints(n,r.h,m)});let i=n.at(-1);c&&i&&e.setAttributes(c,{cx:i.x,cy:i.y})})}isStackData(S)||attachInteraction(S)}function attachInteraction(t){if(cleanupInteraction?.(),cleanupInteraction=void 0,!d.onHover&&!d.onClick||t.length<=1)return;let{h:n,inset:r,w:i}=plotArea();E.style.cursor=`crosshair`;let a=i/(t.length-1),o=f===`bar`?[]:buildTopPoints(t,i,n),s=e.createSvgElement(`circle`,{class:`prism-spark-marker`,fill:p,r:3.5}),indexAt=e=>Math.max(0,Math.min(t.length-1,Math.round((e-E.getBoundingClientRect().left-r)/a)));s.style.display=`none`,D.appendChild(s);let handleMove=n=>{let r=indexAt(n.clientX),i=o[r];i&&(e.setAttributes(s,{cx:i.x,cy:i.y}),s.style.display=``),d.onHover?.({index:r,originalEvent:n,value:t[r]})},handleLeave=()=>{s.style.display=`none`,d.onHover?.(null)},handleClick=e=>{if(!d.onClick)return;let n=indexAt(e.clientX);d.onClick({index:n,originalEvent:e,value:t[n]})};E.addEventListener(`mousemove`,handleMove),E.addEventListener(`mouseleave`,handleLeave),E.addEventListener(`click`,handleClick),cleanupInteraction=()=>{E.removeEventListener(`mousemove`,handleMove),E.removeEventListener(`mouseleave`,handleLeave),E.removeEventListener(`click`,handleClick)}}let O=new AbortController,k=!1;try{return renderAll(),{get disposalSignal(){return O.signal},dispose(){k||(k=!0,y.emit({type:`dispose`}),y.stop(),O.abort(),cleanupInteraction?.(),T.dispose())},get disposed(){return k},el:E,tap:y.tap,update(e){if(k)throw new n.PrismRenderError(`Cannot update a disposed chart.`);S=e,renderAll()},[Symbol.dispose](){this.dispose()}}}catch(e){throw O.abort(),cleanupInteraction?.(),T.dispose(),e instanceof n.PrismRenderError?e:new n.PrismRenderError(`Failed to render chart.`,{cause:e})}}exports.createSparkline=createSparkline;
2
2
  //# sourceMappingURL=sparkline.cjs.map