@vielzeug/prism 2.2.5 → 2.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/charts/area/area-chart.cjs +1 -1
- package/dist/charts/area/area-chart.cjs.map +1 -1
- package/dist/charts/area/area-chart.d.ts.map +1 -1
- package/dist/charts/area/area-chart.js +47 -43
- package/dist/charts/area/area-chart.js.map +1 -1
- package/dist/charts/bar/bar-chart.cjs +1 -1
- package/dist/charts/bar/bar-chart.cjs.map +1 -1
- package/dist/charts/bar/bar-chart.d.ts.map +1 -1
- package/dist/charts/bar/bar-chart.js +145 -140
- package/dist/charts/bar/bar-chart.js.map +1 -1
- package/dist/charts/line/line-chart.cjs +1 -1
- package/dist/charts/line/line-chart.cjs.map +1 -1
- package/dist/charts/line/line-chart.d.ts.map +1 -1
- package/dist/charts/line/line-chart.js +48 -44
- package/dist/charts/line/line-chart.js.map +1 -1
- package/dist/charts/pie/pie-chart.cjs +1 -1
- package/dist/charts/pie/pie-chart.cjs.map +1 -1
- package/dist/charts/pie/pie-chart.d.ts.map +1 -1
- package/dist/charts/pie/pie-chart.js +101 -97
- package/dist/charts/pie/pie-chart.js.map +1 -1
- package/dist/charts/sparkline/sparkline.cjs +1 -1
- package/dist/charts/sparkline/sparkline.cjs.map +1 -1
- package/dist/charts/sparkline/sparkline.d.ts.map +1 -1
- package/dist/charts/sparkline/sparkline.js +65 -62
- package/dist/charts/sparkline/sparkline.js.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/resolve.cjs +2 -0
- package/dist/core/resolve.cjs.map +1 -0
- package/dist/core/resolve.d.ts +9 -0
- package/dist/core/resolve.d.ts.map +1 -0
- package/dist/core/resolve.js +15 -0
- package/dist/core/resolve.js.map +1 -0
- package/dist/prism.cjs +1 -1
- package/dist/prism.cjs.map +1 -1
- package/dist/prism.iife.js +1 -1
- package/dist/prism.iife.js.map +1 -1
- package/dist/prism.js +1 -1
- package/dist/prism.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pie-chart.cjs","names":[],"sources":["../../../src/charts/pie/pie-chart.ts"],"sourcesContent":["import { isReactive } from '@vielzeug/ripple';\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 { createSvgElement, setAttributes } from '../../svg/element';\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\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 {\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\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 while (labelGroup.children.length > currentArcs.length) labelGroup.removeChild(labelGroup.lastChild!);\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) continue;\n\n const { x, y } = arcCentroid(arc);\n let text = labelGroup.children[i] as SVGTextElement | undefined;\n\n if (!text) {\n text = createSvgElement('text', { class: 'prism-pie-label' });\n labelGroup.appendChild(text);\n }\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 }\n }\n\n const handle = createRadialScaffold(\n container,\n {\n a11y: config.a11y,\n legend: config.legend,\n plugins: config.plugins,\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.value;\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 = isReactive(config.data) ? config.data.value : config.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 while (labelGroup.children.length > currentArcs.length) labelGroup.removeChild(labelGroup.lastChild!);\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 onMouseMove = (e: MouseEvent): void => {\n const svgRect = svg.getBoundingClientRect();\n const mx = e.clientX - svgRect.left;\n const my = e.clientY - svgRect.top;\n const hit = hitTestArc(currentArcs, mx, my, variant);\n\n if (hit >= 0) {\n const arc = currentArcs[hit];\n\n config.onHover?.(arc.slice, hit);\n\n const { x, y } = arcCentroid(arc);\n const contR = container.getBoundingClientRect();\n\n tooltip?.show(\n x + (svgRect.left - contR.left),\n y + (svgRect.top - contR.top),\n { key: hit, value: arc.slice.value },\n { color: arc.color, data: [], name: arc.slice.label ?? '' },\n );\n } else {\n config.onHover?.(null, null);\n tooltip?.hide();\n }\n };\n\n const onMouseLeave = (): void => {\n config.onHover?.(null, null);\n tooltip?.hide();\n };\n\n const onClick = (e: MouseEvent): void => {\n if (!config.onClick) return;\n\n const svgRect = svg.getBoundingClientRect();\n const mx = e.clientX - svgRect.left;\n const my = e.clientY - svgRect.top;\n const hit = hitTestArc(currentArcs, mx, my, variant);\n\n if (hit >= 0) config.onClick(currentArcs[hit].slice, hit);\n };\n\n return { onClick, onMouseLeave, onMouseMove };\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 [Symbol.dispose]() {\n this.dispose();\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
|
+
{"version":3,"file":"pie-chart.cjs","names":[],"sources":["../../../src/charts/pie/pie-chart.ts"],"sourcesContent":["import { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport type { ChartEventHandlers } from '../../core/chart-scaffold';\nimport { createRadialScaffold } from '../../core/chart-scaffold';\nimport { resolveMaybeSignal } from '../../core/resolve';\nimport { createSvgElement, setAttributes } from '../../svg/element';\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\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 {\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 const dataSignal = resolveMaybeSignal(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 while (labelGroup.children.length > currentArcs.length) labelGroup.removeChild(labelGroup.lastChild!);\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) continue;\n\n const { x, y } = arcCentroid(arc);\n let text = labelGroup.children[i] as SVGTextElement | undefined;\n\n if (!text) {\n text = createSvgElement('text', { class: 'prism-pie-label' });\n labelGroup.appendChild(text);\n }\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 }\n }\n\n let handle: ReturnType<typeof createRadialScaffold> | undefined;\n\n try {\n handle = createRadialScaffold(\n container,\n {\n a11y: config.a11y,\n legend: config.legend,\n plugins: config.plugins,\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.value;\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 = dataSignal.value;\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 while (labelGroup.children.length > currentArcs.length) labelGroup.removeChild(labelGroup.lastChild!);\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 onMouseMove = (e: MouseEvent): void => {\n const svgRect = svg.getBoundingClientRect();\n const mx = e.clientX - svgRect.left;\n const my = e.clientY - svgRect.top;\n const hit = hitTestArc(currentArcs, mx, my, variant);\n\n if (hit >= 0) {\n const arc = currentArcs[hit];\n\n config.onHover?.(arc.slice, hit);\n\n const { x, y } = arcCentroid(arc);\n const contR = container.getBoundingClientRect();\n\n tooltip?.show(\n x + (svgRect.left - contR.left),\n y + (svgRect.top - contR.top),\n { key: hit, value: arc.slice.value },\n { color: arc.color, data: [], name: arc.slice.label ?? '' },\n );\n } else {\n config.onHover?.(null, null);\n tooltip?.hide();\n }\n };\n\n const onMouseLeave = (): void => {\n config.onHover?.(null, null);\n tooltip?.hide();\n };\n\n const onClick = (e: MouseEvent): void => {\n if (!config.onClick) return;\n\n const svgRect = svg.getBoundingClientRect();\n const mx = e.clientX - svgRect.left;\n const my = e.clientY - svgRect.top;\n const hit = hitTestArc(currentArcs, mx, my, variant);\n\n if (hit >= 0) config.onClick(currentArcs[hit].slice, hit);\n };\n\n return { onClick, onMouseLeave, onMouseMove };\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 [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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pie-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/pie/pie-chart.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAkB,MAAM,aAAa,CAAC;AAY/E,wBAAgB,cAAc,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"pie-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/pie/pie-chart.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAkB,MAAM,aAAa,CAAC;AAY/E,wBAAgB,cAAc,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,GAAG,WAAW,CAyP1F"}
|
|
@@ -3,9 +3,9 @@ import { resolveMotion as t } from "../../animation/motion.js";
|
|
|
3
3
|
import { tweenNumber as n } from "../../animation/tween.js";
|
|
4
4
|
import { createSvgElement as r, setAttributes as i } from "../../svg/element.js";
|
|
5
5
|
import { createRadialScaffold as a } from "../../core/chart-scaffold.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { resolveMaybeSignal as o } from "../../core/resolve.js";
|
|
7
|
+
import { seriesColor as s } from "../../theme/index.js";
|
|
8
|
+
import { arcCentroid as c, arcPath as l, computeArcs as u } from "./pie-renderer.js";
|
|
9
9
|
//#region src/charts/pie/pie-chart.ts
|
|
10
10
|
var d = 2 * Math.PI, f = -Math.PI / 2, p = Math.PI / 2;
|
|
11
11
|
function m(e) {
|
|
@@ -18,123 +18,127 @@ function m(e) {
|
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
function h(d, f) {
|
|
21
|
-
let p = f.variant ?? "pie", h = f.padPixels ?? (p === "pie" ? 0 : 8), _ = f.cornerRadius ?? (p === "pie" ? 0 : 8), v = r("circle", {
|
|
21
|
+
let p = f.variant ?? "pie", h = f.padPixels ?? (p === "pie" ? 0 : 8), _ = f.cornerRadius ?? (p === "pie" ? 0 : 8), v = o(f.data), y = r("circle", {
|
|
22
22
|
class: "prism-pie-bg",
|
|
23
23
|
"pointer-events": "none"
|
|
24
|
-
}),
|
|
24
|
+
}), b = r("g", {
|
|
25
25
|
class: "prism-pie-slices",
|
|
26
26
|
"shape-rendering": "geometricPrecision"
|
|
27
|
-
}),
|
|
27
|
+
}), x = r("g", {
|
|
28
28
|
class: "prism-pie-labels",
|
|
29
29
|
"pointer-events": "none"
|
|
30
|
-
}),
|
|
31
|
-
function
|
|
32
|
-
for (;
|
|
33
|
-
for (let t = 0; t <
|
|
34
|
-
let n =
|
|
30
|
+
}), S = [], C = null;
|
|
31
|
+
function w(e) {
|
|
32
|
+
for (; x.children.length > S.length;) x.removeChild(x.lastChild);
|
|
33
|
+
for (let t = 0; t < S.length; t++) {
|
|
34
|
+
let n = S[t], a = e[t];
|
|
35
35
|
if (!a?.label) continue;
|
|
36
|
-
let { x: o, y:
|
|
37
|
-
l || (l = r("text", { class: "prism-pie-label" }),
|
|
36
|
+
let { x: o, y: s } = c(n), l = x.children[t];
|
|
37
|
+
l || (l = r("text", { class: "prism-pie-label" }), x.appendChild(l)), i(l, {
|
|
38
38
|
"dominant-baseline": "middle",
|
|
39
39
|
fill: "var(--prism-pie-label-color, #fff)",
|
|
40
40
|
"font-family": "var(--prism-font-family, system-ui)",
|
|
41
41
|
"font-size": "var(--prism-pie-label-size, 12px)",
|
|
42
42
|
"text-anchor": "middle",
|
|
43
43
|
x: o,
|
|
44
|
-
y:
|
|
44
|
+
y: s
|
|
45
45
|
}), l.textContent = a.label;
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
let
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
let t =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
let
|
|
72
|
-
|
|
73
|
-
let
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
48
|
+
let T;
|
|
49
|
+
try {
|
|
50
|
+
return T = a(d, {
|
|
51
|
+
a11y: f.a11y,
|
|
52
|
+
legend: f.legend,
|
|
53
|
+
plugins: f.plugins,
|
|
54
|
+
tooltip: f.tooltip
|
|
55
|
+
}, (a) => {
|
|
56
|
+
let { legend: o, svg: T, tooltip: E } = a;
|
|
57
|
+
T.contains(y) || (T.appendChild(y), T.appendChild(b), T.appendChild(x));
|
|
58
|
+
let { height: D, width: O } = a.dimensions.value, k = p === "semi", A = O / 2, j = k ? D * .85 : D / 2, M = k ? Math.min(A, j) - 8 : Math.min(O, D) / 2 - 8, N = p === "pie" ? 0 : Math.round(M * .55), P = f.innerRadius === void 0 ? N : f.innerRadius, F = Math.max(P + 1, M), I = v.value, { end: L, start: R } = m(p);
|
|
59
|
+
for (S = u(I, A, j, F, P, R, L, h, _, (e) => s(e), !1), i(y, {
|
|
60
|
+
cx: A,
|
|
61
|
+
cy: j,
|
|
62
|
+
r: P > 0 ? P : 0
|
|
63
|
+
}), y.setAttribute("style", "fill:var(--prism-bg,#fff)"); b.children.length > S.length;) b.removeChild(b.lastChild);
|
|
64
|
+
for (; x.children.length > S.length;) x.removeChild(x.lastChild);
|
|
65
|
+
let z = t(f.transition, 0), B = z.duration, V = e(z.easing);
|
|
66
|
+
for (let e = 0; e < S.length; e++) {
|
|
67
|
+
let t = S[e], n = b.children[e];
|
|
68
|
+
n || (n = r("path", { class: "prism-pie-slice" }), b.appendChild(n)), n.setAttribute("fill", t.color), n.setAttribute("stroke", "none"), n.style.cursor = f.onClick || f.onHover ? "pointer" : "";
|
|
69
|
+
}
|
|
70
|
+
if (C !== null && (cancelAnimationFrame(C), C = null), B > 0) {
|
|
71
|
+
let e = null, t = (r) => {
|
|
72
|
+
e === null && (e = r);
|
|
73
|
+
let a = V(Math.min(1, (r - e) / B)), o = n(R, L, a);
|
|
74
|
+
for (let e = 0; e < S.length; e++) {
|
|
75
|
+
let t = S[e], n = b.children[e];
|
|
76
|
+
if (n) if (o <= t.startAngle) i(n, { d: "" });
|
|
77
|
+
else {
|
|
78
|
+
let e = Math.min(t.endAngle, o);
|
|
79
|
+
i(n, { d: l({
|
|
80
|
+
...t,
|
|
81
|
+
endAngle: e
|
|
82
|
+
}) });
|
|
83
|
+
}
|
|
81
84
|
}
|
|
85
|
+
a < 1 ? C = requestAnimationFrame(t) : (C = null, w(I));
|
|
86
|
+
};
|
|
87
|
+
C = requestAnimationFrame(t);
|
|
88
|
+
} else {
|
|
89
|
+
for (let e = 0; e < S.length; e++) {
|
|
90
|
+
let t = S[e], n = b.children[e];
|
|
91
|
+
n && i(n, { d: l(t) });
|
|
82
92
|
}
|
|
83
|
-
|
|
84
|
-
};
|
|
85
|
-
S = requestAnimationFrame(t);
|
|
86
|
-
} else {
|
|
87
|
-
for (let e = 0; e < x.length; e++) {
|
|
88
|
-
let t = x[e], n = y.children[e];
|
|
89
|
-
n && i(n, { d: c(t) });
|
|
93
|
+
w(I);
|
|
90
94
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
return o?.update(S.map((e) => ({
|
|
96
|
+
color: e.color,
|
|
97
|
+
name: e.slice.label ?? ""
|
|
98
|
+
}))), E?.hide(), {
|
|
99
|
+
onClick: (e) => {
|
|
100
|
+
if (!f.onClick) return;
|
|
101
|
+
let t = T.getBoundingClientRect(), n = e.clientX - t.left, r = e.clientY - t.top, i = g(S, n, r, p);
|
|
102
|
+
i >= 0 && f.onClick(S[i].slice, i);
|
|
103
|
+
},
|
|
104
|
+
onMouseLeave: () => {
|
|
105
|
+
f.onHover?.(null, null), E?.hide();
|
|
106
|
+
},
|
|
107
|
+
onMouseMove: (e) => {
|
|
108
|
+
let t = T.getBoundingClientRect(), n = e.clientX - t.left, r = e.clientY - t.top, i = g(S, n, r, p);
|
|
109
|
+
if (i >= 0) {
|
|
110
|
+
let e = S[i];
|
|
111
|
+
f.onHover?.(e.slice, i);
|
|
112
|
+
let { x: n, y: r } = c(e), a = d.getBoundingClientRect();
|
|
113
|
+
E?.show(n + (t.left - a.left), r + (t.top - a.top), {
|
|
114
|
+
key: i,
|
|
115
|
+
value: e.slice.value
|
|
116
|
+
}, {
|
|
117
|
+
color: e.color,
|
|
118
|
+
data: [],
|
|
119
|
+
name: e.slice.label ?? ""
|
|
120
|
+
});
|
|
121
|
+
} else f.onHover?.(null, null), E?.hide();
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}), {
|
|
125
|
+
get disposalSignal() {
|
|
126
|
+
return T.disposalSignal;
|
|
127
|
+
},
|
|
128
|
+
dispose() {
|
|
129
|
+
C !== null && (cancelAnimationFrame(C), C = null), T.dispose();
|
|
101
130
|
},
|
|
102
|
-
|
|
103
|
-
|
|
131
|
+
get disposed() {
|
|
132
|
+
return T.disposed;
|
|
104
133
|
},
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
let e = x[i];
|
|
109
|
-
f.onHover?.(e.slice, i);
|
|
110
|
-
let { x: n, y: r } = s(e), a = d.getBoundingClientRect();
|
|
111
|
-
E?.show(n + (t.left - a.left), r + (t.top - a.top), {
|
|
112
|
-
key: i,
|
|
113
|
-
value: e.slice.value
|
|
114
|
-
}, {
|
|
115
|
-
color: e.color,
|
|
116
|
-
data: [],
|
|
117
|
-
name: e.slice.label ?? ""
|
|
118
|
-
});
|
|
119
|
-
} else f.onHover?.(null, null), E?.hide();
|
|
134
|
+
el: T.el,
|
|
135
|
+
[Symbol.dispose]() {
|
|
136
|
+
this.dispose();
|
|
120
137
|
}
|
|
121
138
|
};
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return w.disposalSignal;
|
|
126
|
-
},
|
|
127
|
-
dispose() {
|
|
128
|
-
S !== null && (cancelAnimationFrame(S), S = null), w.dispose();
|
|
129
|
-
},
|
|
130
|
-
get disposed() {
|
|
131
|
-
return w.disposed;
|
|
132
|
-
},
|
|
133
|
-
el: w.el,
|
|
134
|
-
[Symbol.dispose]() {
|
|
135
|
-
this.dispose();
|
|
136
|
-
}
|
|
137
|
-
};
|
|
139
|
+
} catch (e) {
|
|
140
|
+
throw T?.dispose(), e;
|
|
141
|
+
}
|
|
138
142
|
}
|
|
139
143
|
function g(e, t, n, r) {
|
|
140
144
|
for (let i = 0; i < e.length; i++) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pie-chart.js","names":[],"sources":["../../../src/charts/pie/pie-chart.ts"],"sourcesContent":["import { isReactive } from '@vielzeug/ripple';\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 { createSvgElement, setAttributes } from '../../svg/element';\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\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 {\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\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 while (labelGroup.children.length > currentArcs.length) labelGroup.removeChild(labelGroup.lastChild!);\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) continue;\n\n const { x, y } = arcCentroid(arc);\n let text = labelGroup.children[i] as SVGTextElement | undefined;\n\n if (!text) {\n text = createSvgElement('text', { class: 'prism-pie-label' });\n labelGroup.appendChild(text);\n }\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 }\n }\n\n const handle = createRadialScaffold(\n container,\n {\n a11y: config.a11y,\n legend: config.legend,\n plugins: config.plugins,\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.value;\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 = isReactive(config.data) ? config.data.value : config.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 while (labelGroup.children.length > currentArcs.length) labelGroup.removeChild(labelGroup.lastChild!);\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 onMouseMove = (e: MouseEvent): void => {\n const svgRect = svg.getBoundingClientRect();\n const mx = e.clientX - svgRect.left;\n const my = e.clientY - svgRect.top;\n const hit = hitTestArc(currentArcs, mx, my, variant);\n\n if (hit >= 0) {\n const arc = currentArcs[hit];\n\n config.onHover?.(arc.slice, hit);\n\n const { x, y } = arcCentroid(arc);\n const contR = container.getBoundingClientRect();\n\n tooltip?.show(\n x + (svgRect.left - contR.left),\n y + (svgRect.top - contR.top),\n { key: hit, value: arc.slice.value },\n { color: arc.color, data: [], name: arc.slice.label ?? '' },\n );\n } else {\n config.onHover?.(null, null);\n tooltip?.hide();\n }\n };\n\n const onMouseLeave = (): void => {\n config.onHover?.(null, null);\n tooltip?.hide();\n };\n\n const onClick = (e: MouseEvent): void => {\n if (!config.onClick) return;\n\n const svgRect = svg.getBoundingClientRect();\n const mx = e.clientX - svgRect.left;\n const my = e.clientY - svgRect.top;\n const hit = hitTestArc(currentArcs, mx, my, variant);\n\n if (hit >= 0) config.onClick(currentArcs[hit].slice, hit);\n };\n\n return { onClick, onMouseLeave, onMouseMove };\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 [Symbol.dispose]() {\n this.dispose();\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
|
+
{"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 { resolveMaybeSignal } from '../../core/resolve';\nimport { createSvgElement, setAttributes } from '../../svg/element';\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\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 {\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 const dataSignal = resolveMaybeSignal(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 while (labelGroup.children.length > currentArcs.length) labelGroup.removeChild(labelGroup.lastChild!);\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) continue;\n\n const { x, y } = arcCentroid(arc);\n let text = labelGroup.children[i] as SVGTextElement | undefined;\n\n if (!text) {\n text = createSvgElement('text', { class: 'prism-pie-label' });\n labelGroup.appendChild(text);\n }\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 }\n }\n\n let handle: ReturnType<typeof createRadialScaffold> | undefined;\n\n try {\n handle = createRadialScaffold(\n container,\n {\n a11y: config.a11y,\n legend: config.legend,\n plugins: config.plugins,\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.value;\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 = dataSignal.value;\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 while (labelGroup.children.length > currentArcs.length) labelGroup.removeChild(labelGroup.lastChild!);\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 onMouseMove = (e: MouseEvent): void => {\n const svgRect = svg.getBoundingClientRect();\n const mx = e.clientX - svgRect.left;\n const my = e.clientY - svgRect.top;\n const hit = hitTestArc(currentArcs, mx, my, variant);\n\n if (hit >= 0) {\n const arc = currentArcs[hit];\n\n config.onHover?.(arc.slice, hit);\n\n const { x, y } = arcCentroid(arc);\n const contR = container.getBoundingClientRect();\n\n tooltip?.show(\n x + (svgRect.left - contR.left),\n y + (svgRect.top - contR.top),\n { key: hit, value: arc.slice.value },\n { color: arc.color, data: [], name: arc.slice.label ?? '' },\n );\n } else {\n config.onHover?.(null, null);\n tooltip?.hide();\n }\n };\n\n const onMouseLeave = (): void => {\n config.onHover?.(null, null);\n tooltip?.hide();\n };\n\n const onClick = (e: MouseEvent): void => {\n if (!config.onClick) return;\n\n const svgRect = svg.getBoundingClientRect();\n const mx = e.clientX - svgRect.left;\n const my = e.clientY - svgRect.top;\n const hit = hitTestArc(currentArcs, mx, my, variant);\n\n if (hit >= 0) config.onClick(currentArcs[hit].slice, hit);\n };\n\n return { onClick, onMouseLeave, onMouseMove };\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 [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,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../animation/easing.cjs"),t=require("../../animation/motion.cjs"),n=require("../../animation/tween.cjs"),r=require("../../svg/element.cjs"),i=require("../../core/chart-base.cjs"),a=require("../../svg/path.cjs");let
|
|
1
|
+
const e=require("../../animation/easing.cjs"),t=require("../../animation/motion.cjs"),n=require("../../animation/tween.cjs"),r=require("../../svg/element.cjs"),i=require("../../core/chart-base.cjs"),a=require("../../core/resolve.cjs"),o=require("../../svg/path.cjs");let s=require("@vielzeug/ripple");function c(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 l(e,t,n,r=`linear`){if(e.length===0)return``;let i=c(e,t,n),a=i.map(e=>({x:e.x,y:n}));return o.areaPath(i,a,r??`linear`)}function u(e,t,n,r){if(e.length===0)return``;let i=c(e,t,n);return r===`monotone`?o.monotonePath(i):r===`step`?o.stepPath(i):o.linePath(i)}function d(i,a,o,s,c,l,u){let d=a.length,f=Math.max(1,o/d-1),p=o/d,m=Math.min(0,...a),h=Math.max(...a)-m||1,g=t.resolveMotion(l,0),_=g.duration,v=e.resolveEasing(g.easing);for(;i.children.length>d;){let e=i.lastElementChild;e&&i.removeChild(e)}for(let e=0;e<d;e++){let t=Math.max(1,(a[e]-m)/h*s),o=s-t,l=i.children[e];if(l||(l=r.createSvgElement(`rect`,{class:`prism-spark-bar`}),i.appendChild(l)),r.setAttributes(l,{fill:c,width:f,x:e*p}),_>0&&!l.hasAttribute(`data-init`)){l.setAttribute(`data-init`,`1`),r.setAttributes(l,{height:0,y:s});let e=null,i={h:0,y:s},a={h:t,y:o},c=t=>{if(u?.aborted)return;e===null&&(e=t);let o=v(Math.min(1,(t-e)/_));r.setAttributes(l,{height:n.tweenNumber(i.h,a.h,o),y:n.tweenNumber(i.y,a.y,o)}),o<1&&requestAnimationFrame(c)};requestAnimationFrame(c)}else l.setAttribute(`data-init`,`1`),r.setAttributes(l,{height:t,y:o})}}function f(e){return e.length>0&&e[0]!==null&&typeof e[0]==`object`}function p(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 m(e){return`var(--prism-color-${e%8+1})`}function h(e,t){let n=t.variant??`line`,o=t.color??`var(--prism-color-1)`,c=t.curve??`linear`,h=t.strokeWidth??1.5,g=t.fillOpacity??.2,_=a.resolveMaybeSignal(t.data),v=i.createChartBase(e,{...t.a11y?{a11y:t.a11y}:{ariaHidden:!0},margin:{bottom:0,left:0,right:0,top:0}}),{svg:y}=v;y.classList.add(`prism-sparkline`);let b=r.createSvgElement(`g`,{class:`prism-spark-inner`});y.appendChild(b);let x;function S(){let{height:e,width:i}=v.dimensions.value,a=_.value;for(;b.firstChild;)b.removeChild(b.firstChild);if(a.length!==0){if(n===`stack`&&f(a)){let n=r.createSvgElement(`g`,{class:`prism-spark-stack`});b.appendChild(n);let o=t.cornerRadius??4,s=a,c=s.reduce((e,t)=>e+Math.max(0,t.value),0);if(c>0){let a=(t.padPixels??0)/2,l=0;s.forEach((t,u)=>{let d=Math.round(l);l+=Math.max(0,t.value)/c*i;let f=u===s.length-1?i:Math.round(l),h=u===0,g=u===s.length-1,_=p(d+(h?0:a),0,Math.max(0,f-d-(h?0:a)-(g?0:a)),e,o,h,g),v=r.createSvgElement(`path`,{class:`prism-spark-stack-segment`});r.setAttributes(v,{d:_,fill:t.color??m(u)}),n.appendChild(v)})}}else if(n===`bar`){let n=r.createSvgElement(`g`,{class:`prism-spark-bars`});b.appendChild(n),d(n,a,i,e,o,t.transition,w.signal)}else{if(n===`area`){let t=r.createSvgElement(`path`,{class:`prism-spark-fill`}),n=l(a,i,e,c);r.setAttributes(t,{d:n,fill:o,"fill-opacity":g,stroke:`none`}),b.appendChild(t)}let t=r.createSvgElement(`path`,{class:`prism-spark-line`}),s=u(a,i,e,c);r.setAttributes(t,{d:s,fill:`none`,stroke:o,"stroke-width":h}),b.appendChild(t)}f(a)||C(a)}}function C(e){if(x?.(),x=void 0,!t.onHover&&!t.onClick||e.length<=1)return;let{width:n}=v.dimensions.value;y.style.cursor=`crosshair`;let r=n/(e.length-1),i=n=>{let i=y.getBoundingClientRect(),a=n.clientX-i.left,o=Math.max(0,Math.min(e.length-1,Math.round(a/r)));t.onHover?.(o,e[o])},a=()=>t.onHover?.(null,null),o=n=>{if(!t.onClick)return;let i=y.getBoundingClientRect(),a=n.clientX-i.left,o=Math.max(0,Math.min(e.length-1,Math.round(a/r)));t.onClick(o,e[o])};y.addEventListener(`mousemove`,i),y.addEventListener(`mouseleave`,a),y.addEventListener(`click`,o),x=()=>{y.removeEventListener(`mousemove`,i),y.removeEventListener(`mouseleave`,a),y.removeEventListener(`click`,o)}}let w=new AbortController,T=(0,s.createScope)(),E=!1;try{return T.run(()=>{(0,s.effect)(()=>{S()},{scheduler:`microtask`})}),{get disposalSignal(){return w.signal},dispose(){E||(E=!0,w.abort(),x?.(),T.dispose(),v.dispose())},get disposed(){return E},el:y,[Symbol.dispose](){this.dispose()}}}catch(e){throw w.abort(),T.dispose(),v.dispose(),e}}exports.createSparkline=h;
|
|
2
2
|
//# sourceMappingURL=sparkline.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sparkline.cjs","names":[],"sources":["../../../src/charts/sparkline/sparkline.ts"],"sourcesContent":["import { createScope, effect, isReactive } from '@vielzeug/ripple';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport { createChartBase } from '../../core/chart-base';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { areaPath, linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ChartHandle, SparklineConfig, StackSegment } from '../../types';\n\nfunction buildTopPoints(data: number[], width: number, height: number): Point[] {\n if (data.length === 0) return [];\n\n const xStep = width / Math.max(1, data.length - 1);\n const min = Math.min(...data);\n const max = Math.max(...data);\n const yRange = max - min || 1;\n\n return data.map((v, i) => ({\n x: i * xStep,\n y: height - ((v - min) / yRange) * height,\n }));\n}\n\nfunction buildAreaPath(\n data: number[],\n width: number,\n height: number,\n curve: SparklineConfig['curve'] = 'linear',\n): string {\n if (data.length === 0) return '';\n\n const top = buildTopPoints(data, width, height);\n const bottom = top.map((p) => ({ x: p.x, y: height }));\n\n return areaPath(top, bottom, curve ?? 'linear');\n}\n\nfunction buildPath(data: number[], width: number, height: number, curve: SparklineConfig['curve']): string {\n if (data.length === 0) return '';\n\n const points = buildTopPoints(data, width, height);\n\n return curve === 'monotone' ? monotonePath(points) : curve === 'step' ? stepPath(points) : linePath(points);\n}\n\nfunction renderSparkBars(\n parent: SVGGElement,\n data: number[],\n width: number,\n height: number,\n color: string,\n transition?: SparklineConfig['transition'],\n disposalSignal?: AbortSignal,\n): void {\n const count = data.length;\n const barW = Math.max(1, width / count - 1);\n const gap = width / count;\n const min = Math.min(0, ...data);\n const max = Math.max(...data);\n const yRange = max - min || 1;\n const motion = resolveMotion(transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n while (parent.children.length > count) {\n const last = parent.lastElementChild;\n\n if (last) parent.removeChild(last);\n }\n\n for (let i = 0; i < count; i++) {\n const finalH = Math.max(1, ((data[i] - min) / yRange) * height);\n const finalY = height - finalH;\n\n let rect = parent.children[i] as SVGRectElement | undefined;\n\n if (!rect) {\n rect = createSvgElement('rect', { class: 'prism-spark-bar' });\n parent.appendChild(rect);\n }\n\n setAttributes(rect, { fill: color, width: barW, x: i * gap });\n\n if (dur > 0 && !rect.hasAttribute('data-init')) {\n rect.setAttribute('data-init', '1');\n setAttributes(rect, { height: 0, y: height });\n\n let start: number | null = null;\n const from = { h: 0, y: height };\n const to = { h: finalH, y: finalY };\n\n const frame = (ts: number) => {\n if (disposalSignal?.aborted) return;\n\n if (start === null) start = ts;\n\n const t = easing(Math.min(1, (ts - start) / dur));\n\n setAttributes(rect!, {\n height: tweenNumber(from.h, to.h, t),\n y: tweenNumber(from.y, to.y, t),\n });\n\n if (t < 1) requestAnimationFrame(frame);\n };\n\n requestAnimationFrame(frame);\n } else {\n rect.setAttribute('data-init', '1');\n setAttributes(rect, { height: finalH, y: finalY });\n }\n }\n}\n\nfunction isStackData(data: number[] | StackSegment[]): data is StackSegment[] {\n return data.length > 0 && data[0] !== null && typeof data[0] === 'object';\n}\n\nfunction buildRoundedStackRect(\n x: number,\n y: number,\n w: number,\n h: number,\n r: number,\n roundLeft: boolean,\n roundRight: boolean,\n): string {\n const maxR = Math.min(r, w / 2, h / 2);\n const tl = roundLeft ? maxR : 0;\n const bl = roundLeft ? maxR : 0;\n const tr = roundRight ? maxR : 0;\n const br = roundRight ? maxR : 0;\n\n return [\n `M${x + tl},${y}`,\n `H${x + w - tr}`,\n tr ? `Q${x + w},${y} ${x + w},${y + tr}` : '',\n `V${y + h - br}`,\n br ? `Q${x + w},${y + h} ${x + w - br},${y + h}` : '',\n `H${x + bl}`,\n bl ? `Q${x},${y + h} ${x},${y + h - bl}` : '',\n `V${y + tl}`,\n tl ? `Q${x},${y} ${x + tl},${y}` : '',\n 'Z',\n ]\n .filter(Boolean)\n .join('');\n}\n\nfunction defaultStackColor(i: number): string {\n return `var(--prism-color-${(i % 8) + 1})`;\n}\n\nexport function createSparkline(container: HTMLElement, config: SparklineConfig): ChartHandle {\n const variant = config.variant ?? 'line';\n const color = config.color ?? 'var(--prism-color-1)';\n const curve = config.curve ?? 'linear';\n const strokeWidth = config.strokeWidth ?? 1.5;\n const fillOpacity = config.fillOpacity ?? 0.2;\n\n const base = createChartBase(container, {\n ...(config.a11y ? { a11y: config.a11y } : { ariaHidden: true }),\n margin: { bottom: 0, left: 0, right: 0, top: 0 },\n });\n\n const { svg } = base;\n\n svg.classList.add('prism-sparkline');\n\n const innerGroup = createSvgElement('g', { class: 'prism-spark-inner' });\n\n svg.appendChild(innerGroup);\n\n let cleanupInteraction: (() => void) | undefined;\n\n function renderAll(): void {\n const { height: h, width: w } = base.dimensions.value;\n const data = isReactive(config.data) ? config.data.value : config.data;\n\n while (innerGroup.firstChild) innerGroup.removeChild(innerGroup.firstChild);\n\n if (data.length === 0) return;\n\n if (variant === 'stack' && isStackData(data)) {\n const stackGroup = createSvgElement('g', { class: 'prism-spark-stack' });\n\n innerGroup.appendChild(stackGroup);\n\n const cornerRadius = config.cornerRadius ?? 4;\n const segs = data as StackSegment[];\n const total = segs.reduce((s, d) => s + Math.max(0, d.value), 0);\n\n if (total > 0) {\n const half = (config.padPixels ?? 0) / 2;\n let xAcc = 0;\n\n segs.forEach((seg, i) => {\n const xStart = Math.round(xAcc);\n\n xAcc += (Math.max(0, seg.value) / total) * w;\n\n const xEnd = i === segs.length - 1 ? w : Math.round(xAcc);\n const isFirst = i === 0;\n const isLast = i === segs.length - 1;\n const drawX = xStart + (isFirst ? 0 : half);\n const drawW = Math.max(0, xEnd - xStart - (isFirst ? 0 : half) - (isLast ? 0 : half));\n const d = buildRoundedStackRect(drawX, 0, drawW, h, cornerRadius, isFirst, isLast);\n const path = createSvgElement('path', { class: 'prism-spark-stack-segment' });\n\n setAttributes(path, { d, fill: seg.color ?? defaultStackColor(i) });\n stackGroup.appendChild(path);\n });\n }\n } else if (variant === 'bar') {\n const barsGroup = createSvgElement('g', { class: 'prism-spark-bars' });\n\n innerGroup.appendChild(barsGroup);\n renderSparkBars(barsGroup, data as number[], w, h, color, config.transition, ac.signal);\n } else {\n if (variant === 'area') {\n const fill = createSvgElement('path', { class: 'prism-spark-fill' });\n const fillD = buildAreaPath(data as number[], w, h, curve);\n\n setAttributes(fill, { d: fillD, fill: color, 'fill-opacity': fillOpacity, stroke: 'none' });\n innerGroup.appendChild(fill);\n }\n\n const path = createSvgElement('path', { class: 'prism-spark-line' });\n const pathD = buildPath(data as number[], w, h, curve);\n\n setAttributes(path, { d: pathD, fill: 'none', stroke: color, 'stroke-width': strokeWidth });\n innerGroup.appendChild(path);\n }\n\n if (!isStackData(data)) attachInteraction(data as number[]);\n }\n\n function attachInteraction(data: number[]): void {\n cleanupInteraction?.();\n cleanupInteraction = undefined;\n\n if (!config.onHover && !config.onClick) return;\n\n if (data.length <= 1) return;\n\n const { width: w } = base.dimensions.value;\n\n svg.style.cursor = 'crosshair';\n\n const xStep = w / (data.length - 1);\n\n const handleMove = (e: MouseEvent) => {\n const rect = svg.getBoundingClientRect();\n const relX = e.clientX - rect.left;\n const idx = Math.max(0, Math.min(data.length - 1, Math.round(relX / xStep)));\n\n config.onHover?.(idx, data[idx]);\n };\n\n const handleLeave = () => config.onHover?.(null, null);\n\n const handleClick = (e: MouseEvent) => {\n if (!config.onClick) return;\n\n const rect = svg.getBoundingClientRect();\n const relX = e.clientX - rect.left;\n const idx = Math.max(0, Math.min(data.length - 1, Math.round(relX / xStep)));\n\n config.onClick(idx, data[idx]);\n };\n\n svg.addEventListener('mousemove', handleMove);\n svg.addEventListener('mouseleave', handleLeave);\n svg.addEventListener('click', handleClick);\n\n cleanupInteraction = () => {\n svg.removeEventListener('mousemove', handleMove);\n svg.removeEventListener('mouseleave', handleLeave);\n svg.removeEventListener('click', handleClick);\n };\n }\n\n const ac = new AbortController();\n\n const scope = createScope();\n\n scope.run(() => {\n effect(\n () => {\n renderAll();\n },\n { scheduler: 'microtask' },\n );\n });\n\n let isDisposed = false;\n\n return {\n get disposalSignal(): AbortSignal {\n return ac.signal;\n },\n\n dispose() {\n if (isDisposed) return;\n\n isDisposed = true;\n ac.abort();\n cleanupInteraction?.();\n scope.dispose();\n base.dispose();\n },\n\n get disposed(): boolean {\n return isDisposed;\n },\n\n el: svg,\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sparkline.cjs","names":[],"sources":["../../../src/charts/sparkline/sparkline.ts"],"sourcesContent":["import { createScope, effect } from '@vielzeug/ripple';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport { createChartBase } from '../../core/chart-base';\nimport { resolveMaybeSignal } from '../../core/resolve';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { areaPath, linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ChartHandle, SparklineConfig, StackSegment } from '../../types';\n\nfunction buildTopPoints(data: number[], width: number, height: number): Point[] {\n if (data.length === 0) return [];\n\n const xStep = width / Math.max(1, data.length - 1);\n const min = Math.min(...data);\n const max = Math.max(...data);\n const yRange = max - min || 1;\n\n return data.map((v, i) => ({\n x: i * xStep,\n y: height - ((v - min) / yRange) * height,\n }));\n}\n\nfunction buildAreaPath(\n data: number[],\n width: number,\n height: number,\n curve: SparklineConfig['curve'] = 'linear',\n): string {\n if (data.length === 0) return '';\n\n const top = buildTopPoints(data, width, height);\n const bottom = top.map((p) => ({ x: p.x, y: height }));\n\n return areaPath(top, bottom, curve ?? 'linear');\n}\n\nfunction buildPath(data: number[], width: number, height: number, curve: SparklineConfig['curve']): string {\n if (data.length === 0) return '';\n\n const points = buildTopPoints(data, width, height);\n\n return curve === 'monotone' ? monotonePath(points) : curve === 'step' ? stepPath(points) : linePath(points);\n}\n\nfunction renderSparkBars(\n parent: SVGGElement,\n data: number[],\n width: number,\n height: number,\n color: string,\n transition?: SparklineConfig['transition'],\n disposalSignal?: AbortSignal,\n): void {\n const count = data.length;\n const barW = Math.max(1, width / count - 1);\n const gap = width / count;\n const min = Math.min(0, ...data);\n const max = Math.max(...data);\n const yRange = max - min || 1;\n const motion = resolveMotion(transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n while (parent.children.length > count) {\n const last = parent.lastElementChild;\n\n if (last) parent.removeChild(last);\n }\n\n for (let i = 0; i < count; i++) {\n const finalH = Math.max(1, ((data[i] - min) / yRange) * height);\n const finalY = height - finalH;\n\n let rect = parent.children[i] as SVGRectElement | undefined;\n\n if (!rect) {\n rect = createSvgElement('rect', { class: 'prism-spark-bar' });\n parent.appendChild(rect);\n }\n\n setAttributes(rect, { fill: color, width: barW, x: i * gap });\n\n if (dur > 0 && !rect.hasAttribute('data-init')) {\n rect.setAttribute('data-init', '1');\n setAttributes(rect, { height: 0, y: height });\n\n let start: number | null = null;\n const from = { h: 0, y: height };\n const to = { h: finalH, y: finalY };\n\n const frame = (ts: number) => {\n if (disposalSignal?.aborted) return;\n\n if (start === null) start = ts;\n\n const t = easing(Math.min(1, (ts - start) / dur));\n\n setAttributes(rect!, {\n height: tweenNumber(from.h, to.h, t),\n y: tweenNumber(from.y, to.y, t),\n });\n\n if (t < 1) requestAnimationFrame(frame);\n };\n\n requestAnimationFrame(frame);\n } else {\n rect.setAttribute('data-init', '1');\n setAttributes(rect, { height: finalH, y: finalY });\n }\n }\n}\n\nfunction isStackData(data: number[] | StackSegment[]): data is StackSegment[] {\n return data.length > 0 && data[0] !== null && typeof data[0] === 'object';\n}\n\nfunction buildRoundedStackRect(\n x: number,\n y: number,\n w: number,\n h: number,\n r: number,\n roundLeft: boolean,\n roundRight: boolean,\n): string {\n const maxR = Math.min(r, w / 2, h / 2);\n const tl = roundLeft ? maxR : 0;\n const bl = roundLeft ? maxR : 0;\n const tr = roundRight ? maxR : 0;\n const br = roundRight ? maxR : 0;\n\n return [\n `M${x + tl},${y}`,\n `H${x + w - tr}`,\n tr ? `Q${x + w},${y} ${x + w},${y + tr}` : '',\n `V${y + h - br}`,\n br ? `Q${x + w},${y + h} ${x + w - br},${y + h}` : '',\n `H${x + bl}`,\n bl ? `Q${x},${y + h} ${x},${y + h - bl}` : '',\n `V${y + tl}`,\n tl ? `Q${x},${y} ${x + tl},${y}` : '',\n 'Z',\n ]\n .filter(Boolean)\n .join('');\n}\n\nfunction defaultStackColor(i: number): string {\n return `var(--prism-color-${(i % 8) + 1})`;\n}\n\nexport function createSparkline(container: HTMLElement, config: SparklineConfig): ChartHandle {\n const variant = config.variant ?? 'line';\n const color = config.color ?? 'var(--prism-color-1)';\n const curve = config.curve ?? 'linear';\n const strokeWidth = config.strokeWidth ?? 1.5;\n const fillOpacity = config.fillOpacity ?? 0.2;\n const dataSignal = resolveMaybeSignal(config.data);\n\n const base = createChartBase(container, {\n ...(config.a11y ? { a11y: config.a11y } : { ariaHidden: true }),\n margin: { bottom: 0, left: 0, right: 0, top: 0 },\n });\n\n const { svg } = base;\n\n svg.classList.add('prism-sparkline');\n\n const innerGroup = createSvgElement('g', { class: 'prism-spark-inner' });\n\n svg.appendChild(innerGroup);\n\n let cleanupInteraction: (() => void) | undefined;\n\n function renderAll(): void {\n const { height: h, width: w } = base.dimensions.value;\n const data = dataSignal.value;\n\n while (innerGroup.firstChild) innerGroup.removeChild(innerGroup.firstChild);\n\n if (data.length === 0) return;\n\n if (variant === 'stack' && isStackData(data)) {\n const stackGroup = createSvgElement('g', { class: 'prism-spark-stack' });\n\n innerGroup.appendChild(stackGroup);\n\n const cornerRadius = config.cornerRadius ?? 4;\n const segs = data as StackSegment[];\n const total = segs.reduce((s, d) => s + Math.max(0, d.value), 0);\n\n if (total > 0) {\n const half = (config.padPixels ?? 0) / 2;\n let xAcc = 0;\n\n segs.forEach((seg, i) => {\n const xStart = Math.round(xAcc);\n\n xAcc += (Math.max(0, seg.value) / total) * w;\n\n const xEnd = i === segs.length - 1 ? w : Math.round(xAcc);\n const isFirst = i === 0;\n const isLast = i === segs.length - 1;\n const drawX = xStart + (isFirst ? 0 : half);\n const drawW = Math.max(0, xEnd - xStart - (isFirst ? 0 : half) - (isLast ? 0 : half));\n const d = buildRoundedStackRect(drawX, 0, drawW, h, cornerRadius, isFirst, isLast);\n const path = createSvgElement('path', { class: 'prism-spark-stack-segment' });\n\n setAttributes(path, { d, fill: seg.color ?? defaultStackColor(i) });\n stackGroup.appendChild(path);\n });\n }\n } else if (variant === 'bar') {\n const barsGroup = createSvgElement('g', { class: 'prism-spark-bars' });\n\n innerGroup.appendChild(barsGroup);\n renderSparkBars(barsGroup, data as number[], w, h, color, config.transition, ac.signal);\n } else {\n if (variant === 'area') {\n const fill = createSvgElement('path', { class: 'prism-spark-fill' });\n const fillD = buildAreaPath(data as number[], w, h, curve);\n\n setAttributes(fill, { d: fillD, fill: color, 'fill-opacity': fillOpacity, stroke: 'none' });\n innerGroup.appendChild(fill);\n }\n\n const path = createSvgElement('path', { class: 'prism-spark-line' });\n const pathD = buildPath(data as number[], w, h, curve);\n\n setAttributes(path, { d: pathD, fill: 'none', stroke: color, 'stroke-width': strokeWidth });\n innerGroup.appendChild(path);\n }\n\n if (!isStackData(data)) attachInteraction(data as number[]);\n }\n\n function attachInteraction(data: number[]): void {\n cleanupInteraction?.();\n cleanupInteraction = undefined;\n\n if (!config.onHover && !config.onClick) return;\n\n if (data.length <= 1) return;\n\n const { width: w } = base.dimensions.value;\n\n svg.style.cursor = 'crosshair';\n\n const xStep = w / (data.length - 1);\n\n const handleMove = (e: MouseEvent) => {\n const rect = svg.getBoundingClientRect();\n const relX = e.clientX - rect.left;\n const idx = Math.max(0, Math.min(data.length - 1, Math.round(relX / xStep)));\n\n config.onHover?.(idx, data[idx]);\n };\n\n const handleLeave = () => config.onHover?.(null, null);\n\n const handleClick = (e: MouseEvent) => {\n if (!config.onClick) return;\n\n const rect = svg.getBoundingClientRect();\n const relX = e.clientX - rect.left;\n const idx = Math.max(0, Math.min(data.length - 1, Math.round(relX / xStep)));\n\n config.onClick(idx, data[idx]);\n };\n\n svg.addEventListener('mousemove', handleMove);\n svg.addEventListener('mouseleave', handleLeave);\n svg.addEventListener('click', handleClick);\n\n cleanupInteraction = () => {\n svg.removeEventListener('mousemove', handleMove);\n svg.removeEventListener('mouseleave', handleLeave);\n svg.removeEventListener('click', handleClick);\n };\n }\n\n const ac = new AbortController();\n\n const scope = createScope();\n\n let isDisposed = false;\n\n try {\n scope.run(() => {\n effect(\n () => {\n renderAll();\n },\n { scheduler: 'microtask' },\n );\n });\n\n return {\n get disposalSignal(): AbortSignal {\n return ac.signal;\n },\n\n dispose() {\n if (isDisposed) return;\n\n isDisposed = true;\n ac.abort();\n cleanupInteraction?.();\n scope.dispose();\n base.dispose();\n },\n\n get disposed(): boolean {\n return isDisposed;\n },\n\n el: svg,\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n } catch (error) {\n ac.abort();\n scope.dispose();\n base.dispose();\n throw error;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sparkline.d.ts","sourceRoot":"","sources":["../../../src/charts/sparkline/sparkline.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sparkline.d.ts","sourceRoot":"","sources":["../../../src/charts/sparkline/sparkline.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAgB,MAAM,aAAa,CAAC;AAkJ9E,wBAAgB,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,GAAG,WAAW,CAiL5F"}
|