@vielzeug/prism 2.1.0 → 2.1.2
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/animation/easing.cjs.map +1 -1
- package/dist/animation/easing.js.map +1 -1
- package/dist/animation/index.d.ts +2 -2
- package/dist/animation/index.d.ts.map +1 -1
- package/dist/axes/axis.cjs.map +1 -1
- package/dist/axes/axis.d.ts.map +1 -1
- package/dist/axes/axis.js.map +1 -1
- package/dist/axes/grid.cjs.map +1 -1
- package/dist/axes/grid.d.ts.map +1 -1
- package/dist/axes/grid.js.map +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.map +1 -1
- package/dist/charts/area/area-renderer.cjs +1 -1
- package/dist/charts/area/area-renderer.cjs.map +1 -1
- package/dist/charts/area/area-renderer.d.ts.map +1 -1
- package/dist/charts/area/area-renderer.js +14 -14
- package/dist/charts/area/area-renderer.js.map +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.map +1 -1
- package/dist/charts/bar/bar-renderer.cjs +1 -1
- package/dist/charts/bar/bar-renderer.cjs.map +1 -1
- package/dist/charts/bar/bar-renderer.d.ts.map +1 -1
- package/dist/charts/bar/bar-renderer.js +24 -24
- package/dist/charts/bar/bar-renderer.js.map +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.map +1 -1
- package/dist/charts/line/line-renderer.cjs +1 -1
- package/dist/charts/line/line-renderer.cjs.map +1 -1
- package/dist/charts/line/line-renderer.d.ts.map +1 -1
- package/dist/charts/line/line-renderer.js +34 -34
- package/dist/charts/line/line-renderer.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 +34 -34
- 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 +64 -64
- package/dist/charts/sparkline/sparkline.js.map +1 -1
- package/dist/core/cartesian-model.cjs.map +1 -1
- package/dist/core/cartesian-model.d.ts.map +1 -1
- package/dist/core/cartesian-model.js.map +1 -1
- package/dist/core/cartesian-scales.cjs.map +1 -1
- package/dist/core/cartesian-scales.d.ts.map +1 -1
- package/dist/core/cartesian-scales.js.map +1 -1
- package/dist/core/chart-base.cjs +1 -1
- package/dist/core/chart-base.cjs.map +1 -1
- package/dist/core/chart-base.d.ts +1 -1
- package/dist/core/chart-base.d.ts.map +1 -1
- package/dist/core/chart-base.js +12 -12
- package/dist/core/chart-base.js.map +1 -1
- package/dist/core/chart-scaffold.cjs.map +1 -1
- package/dist/core/chart-scaffold.d.ts +2 -2
- package/dist/core/chart-scaffold.d.ts.map +1 -1
- package/dist/core/chart-scaffold.js.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -8
- package/dist/interaction/crosshair.cjs.map +1 -1
- package/dist/interaction/crosshair.d.ts +2 -2
- package/dist/interaction/crosshair.d.ts.map +1 -1
- package/dist/interaction/crosshair.js.map +1 -1
- package/dist/interaction/index.d.ts +3 -3
- package/dist/interaction/index.d.ts.map +1 -1
- package/dist/interaction/legend.cjs.map +1 -1
- package/dist/interaction/legend.d.ts +1 -1
- package/dist/interaction/legend.d.ts.map +1 -1
- package/dist/interaction/legend.js.map +1 -1
- package/dist/interaction/series-interaction.cjs.map +1 -1
- package/dist/interaction/series-interaction.d.ts.map +1 -1
- package/dist/interaction/series-interaction.js.map +1 -1
- package/dist/interaction/tooltip.cjs.map +1 -1
- package/dist/interaction/tooltip.d.ts +1 -1
- package/dist/interaction/tooltip.d.ts.map +1 -1
- package/dist/interaction/tooltip.js.map +1 -1
- 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/dist/scales/band.cjs.map +1 -1
- package/dist/scales/band.d.ts.map +1 -1
- package/dist/scales/band.js.map +1 -1
- package/dist/scales/linear.cjs.map +1 -1
- package/dist/scales/linear.js.map +1 -1
- package/dist/svg/index.d.ts +1 -1
- package/dist/svg/index.d.ts.map +1 -1
- package/dist/svg/text.cjs.map +1 -1
- package/dist/svg/text.js.map +1 -1
- package/package.json +32 -32
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pie-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/pie/pie-chart.ts"],"names":[],"mappings":"
|
|
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,CAkP1F"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { resolveEasing as e } from "../../animation/easing.js";
|
|
2
|
+
import { resolveMotion as t } from "../../animation/motion.js";
|
|
3
|
+
import { tweenNumber as n } from "../../animation/tween.js";
|
|
4
|
+
import { createSvgElement as r, setAttributes as i } from "../../svg/element.js";
|
|
5
|
+
import { createRadialScaffold as a } from "../../core/chart-scaffold.js";
|
|
6
|
+
import { seriesColor as o } from "../../theme/index.js";
|
|
7
7
|
import { arcCentroid as s, arcPath as c, computeArcs as l } from "./pie-renderer.js";
|
|
8
8
|
import { isReactive as u } from "@vielzeug/ripple";
|
|
9
9
|
//#region src/charts/pie/pie-chart.ts
|
|
@@ -18,23 +18,23 @@ 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 =
|
|
21
|
+
let p = f.variant ?? "pie", h = f.padPixels ?? (p === "pie" ? 0 : 8), _ = f.cornerRadius ?? (p === "pie" ? 0 : 8), v = r("circle", {
|
|
22
22
|
class: "prism-pie-bg",
|
|
23
23
|
"pointer-events": "none"
|
|
24
|
-
}), y =
|
|
24
|
+
}), y = r("g", {
|
|
25
25
|
class: "prism-pie-slices",
|
|
26
26
|
"shape-rendering": "geometricPrecision"
|
|
27
|
-
}), b =
|
|
27
|
+
}), b = r("g", {
|
|
28
28
|
class: "prism-pie-labels",
|
|
29
29
|
"pointer-events": "none"
|
|
30
30
|
}), x = [], S = null;
|
|
31
|
-
function C(
|
|
31
|
+
function C(e) {
|
|
32
32
|
for (; b.children.length > x.length;) b.removeChild(b.lastChild);
|
|
33
|
-
for (let
|
|
34
|
-
let
|
|
33
|
+
for (let t = 0; t < x.length; t++) {
|
|
34
|
+
let n = x[t], a = e[t];
|
|
35
35
|
if (!a?.label) continue;
|
|
36
|
-
let { x: o, y: c } = s(
|
|
37
|
-
l || (l =
|
|
36
|
+
let { x: o, y: c } = s(n), l = b.children[t];
|
|
37
|
+
l || (l = r("text", { class: "prism-pie-label" }), b.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)",
|
|
@@ -45,49 +45,49 @@ function h(d, f) {
|
|
|
45
45
|
}), l.textContent = a.label;
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
let w =
|
|
48
|
+
let w = a(d, {
|
|
49
49
|
a11y: f.a11y,
|
|
50
50
|
ariaLabel: f.ariaLabel,
|
|
51
51
|
legend: f.legend,
|
|
52
52
|
plugins: f.plugins,
|
|
53
53
|
tooltip: f.tooltip
|
|
54
|
-
}, (
|
|
55
|
-
let { legend: w, svg: T, tooltip: E } =
|
|
54
|
+
}, (a) => {
|
|
55
|
+
let { legend: w, svg: T, tooltip: E } = a;
|
|
56
56
|
T.contains(v) || (T.appendChild(v), T.appendChild(y), T.appendChild(b));
|
|
57
|
-
let { height: D, width: O } =
|
|
58
|
-
for (x = l(I, A, j, F, P, R, L, h, _, (e) =>
|
|
57
|
+
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 = u(f.data) ? f.data.value : f.data, { end: L, start: R } = m(p);
|
|
58
|
+
for (x = l(I, A, j, F, P, R, L, h, _, (e) => o(e), !1), i(v, {
|
|
59
59
|
cx: A,
|
|
60
60
|
cy: j,
|
|
61
61
|
r: P > 0 ? P : 0
|
|
62
62
|
}), v.setAttribute("style", "fill:var(--prism-bg,#fff)"); y.children.length > x.length;) y.removeChild(y.lastChild);
|
|
63
63
|
for (; b.children.length > x.length;) b.removeChild(b.lastChild);
|
|
64
|
-
let z =
|
|
65
|
-
for (let
|
|
66
|
-
let
|
|
67
|
-
|
|
64
|
+
let z = t(f.transition, 0), B = z.duration, V = e(z.easing);
|
|
65
|
+
for (let e = 0; e < x.length; e++) {
|
|
66
|
+
let t = x[e], n = y.children[e];
|
|
67
|
+
n || (n = r("path", { class: "prism-pie-slice" }), y.appendChild(n)), n.setAttribute("fill", t.color), n.setAttribute("stroke", "none"), n.style.cursor = f.onClick || f.onHover ? "pointer" : "";
|
|
68
68
|
}
|
|
69
69
|
if (S !== null && (cancelAnimationFrame(S), S = null), B > 0) {
|
|
70
|
-
let e = null,
|
|
70
|
+
let e = null, t = (r) => {
|
|
71
71
|
e === null && (e = r);
|
|
72
|
-
let
|
|
72
|
+
let a = V(Math.min(1, (r - e) / B)), o = n(R, L, a);
|
|
73
73
|
for (let e = 0; e < x.length; e++) {
|
|
74
|
-
let
|
|
75
|
-
if (
|
|
74
|
+
let t = x[e], n = y.children[e];
|
|
75
|
+
if (n) if (o <= t.startAngle) i(n, { d: "" });
|
|
76
76
|
else {
|
|
77
|
-
let e = Math.min(
|
|
78
|
-
|
|
79
|
-
...
|
|
77
|
+
let e = Math.min(t.endAngle, o);
|
|
78
|
+
i(n, { d: c({
|
|
79
|
+
...t,
|
|
80
80
|
endAngle: e
|
|
81
81
|
}) });
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
-
|
|
84
|
+
a < 1 ? S = requestAnimationFrame(t) : (S = null, C(I));
|
|
85
85
|
};
|
|
86
|
-
S = requestAnimationFrame(
|
|
86
|
+
S = requestAnimationFrame(t);
|
|
87
87
|
} else {
|
|
88
88
|
for (let e = 0; e < x.length; e++) {
|
|
89
|
-
let
|
|
90
|
-
|
|
89
|
+
let t = x[e], n = y.children[e];
|
|
90
|
+
n && i(n, { d: c(t) });
|
|
91
91
|
}
|
|
92
92
|
C(I);
|
|
93
93
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pie-chart.js","names":[],"sources":["../../../src/charts/pie/pie-chart.ts"],"sourcesContent":["import { isReactive } from '@vielzeug/ripple';\n\nimport type { ChartEventHandlers } from '../../core/chart-scaffold';\nimport type { ChartHandle, PieChartConfig, PieSliceConfig } from '../../types';\n\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport { createRadialScaffold } from '../../core/chart-scaffold';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { seriesColor } from '../../theme';\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 ariaLabel: config.ariaLabel,\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 { 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 ariaLabel: config.ariaLabel,\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,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../
|
|
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 o=require("@vielzeug/ripple");function s(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 c(e,t,n,r=`linear`){if(e.length===0)return``;let i=s(e,t,n),o=i.map(e=>({x:e.x,y:n}));return a.areaPath(i,o,r??`linear`)}function l(e,t,n,r){if(e.length===0)return``;let i=s(e,t,n);return r===`monotone`?a.monotonePath(i):r===`step`?a.stepPath(i):a.linePath(i)}function u(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 d(e){return e.length>0&&e[0]!==null&&typeof e[0]==`object`}function f(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 p(e){return`var(--prism-color-${e%8+1})`}function m(e,t){let n=t.variant??`line`,a=t.color??`var(--prism-color-1)`,s=t.curve??`linear`,m=t.strokeWidth??1.5,h=t.fillOpacity??.2,g=i.createChartBase(e,{...t.ariaLabel?{ariaLabel:t.ariaLabel}:{ariaHidden:!0},margin:{bottom:0,left:0,right:0,top:0}}),{svg:_}=g;_.classList.add(`prism-sparkline`);let v=r.createSvgElement(`g`,{class:`prism-spark-inner`});_.appendChild(v);let y;function b(){let{height:e,width:i}=g.dimensions.value,_=(0,o.isReactive)(t.data)?t.data.value:t.data;for(;v.firstChild;)v.removeChild(v.firstChild);if(_.length!==0){if(n===`stack`&&d(_)){let n=r.createSvgElement(`g`,{class:`prism-spark-stack`});v.appendChild(n);let a=t.cornerRadius??4,o=_,s=o.reduce((e,t)=>e+Math.max(0,t.value),0);if(s>0){let c=(t.padPixels??0)/2,l=0;o.forEach((t,u)=>{let d=Math.round(l);l+=Math.max(0,t.value)/s*i;let m=u===o.length-1?i:Math.round(l),h=u===0,g=u===o.length-1,_=f(d+(h?0:c),0,Math.max(0,m-d-(h?0:c)-(g?0:c)),e,a,h,g),v=r.createSvgElement(`path`,{class:`prism-spark-stack-segment`});r.setAttributes(v,{d:_,fill:t.color??p(u)}),n.appendChild(v)})}}else if(n===`bar`){let n=r.createSvgElement(`g`,{class:`prism-spark-bars`});v.appendChild(n),u(n,_,i,e,a,t.transition,S.signal)}else{if(n===`area`){let t=r.createSvgElement(`path`,{class:`prism-spark-fill`}),n=c(_,i,e,s);r.setAttributes(t,{d:n,fill:a,"fill-opacity":h,stroke:`none`}),v.appendChild(t)}let t=r.createSvgElement(`path`,{class:`prism-spark-line`}),o=l(_,i,e,s);r.setAttributes(t,{d:o,fill:`none`,stroke:a,"stroke-width":m}),v.appendChild(t)}d(_)||x(_)}}function x(e){if(y?.(),y=void 0,!t.onHover&&!t.onClick||e.length<=1)return;let{width:n}=g.dimensions.value;_.style.cursor=`crosshair`;let r=n/(e.length-1),i=n=>{let i=_.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=_.getBoundingClientRect(),a=n.clientX-i.left,o=Math.max(0,Math.min(e.length-1,Math.round(a/r)));t.onClick(o,e[o])};_.addEventListener(`mousemove`,i),_.addEventListener(`mouseleave`,a),_.addEventListener(`click`,o),y=()=>{_.removeEventListener(`mousemove`,i),_.removeEventListener(`mouseleave`,a),_.removeEventListener(`click`,o)}}let S=new AbortController,C=(0,o.createScope)();C.run(()=>{(0,o.effect)(()=>{b()},{scheduler:`microtask`})});let w=!1;return{get disposalSignal(){return S.signal},dispose(){w||(w=!0,S.abort(),y?.(),C.dispose(),g.dispose())},get disposed(){return w},el:_,[Symbol.dispose](){this.dispose()}}}exports.createSparkline=m;
|
|
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';\n\nimport type { Point } from '../../svg/path';\nimport type { ChartHandle, SparklineConfig, StackSegment } from '../../types';\n\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 { areaPath, linePath, monotonePath, stepPath } from '../../svg/path';\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.ariaLabel ? { ariaLabel: config.ariaLabel } : { 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, 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.ariaLabel ? { ariaLabel: config.ariaLabel } : { 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 +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":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAgB,MAAM,aAAa,CAAC;AAkJ9E,wBAAgB,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,GAAG,WAAW,CAyK5F"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { resolveEasing as e } from "../../animation/easing.js";
|
|
2
|
+
import { resolveMotion as t } from "../../animation/motion.js";
|
|
3
|
+
import { tweenNumber as n } from "../../animation/tween.js";
|
|
4
|
+
import { createSvgElement as r, setAttributes as i } from "../../svg/element.js";
|
|
5
|
+
import { createChartBase as a } from "../../core/chart-base.js";
|
|
6
6
|
import { areaPath as o, linePath as s, monotonePath as c, stepPath as l } from "../../svg/path.js";
|
|
7
7
|
import { createScope as u, effect as d, isReactive as f } from "@vielzeug/ripple";
|
|
8
8
|
//#region src/charts/sparkline/sparkline.ts
|
|
@@ -27,41 +27,41 @@ function h(e, t, n, r) {
|
|
|
27
27
|
let i = p(e, t, n);
|
|
28
28
|
return r === "monotone" ? c(i) : r === "step" ? l(i) : s(i);
|
|
29
29
|
}
|
|
30
|
-
function g(
|
|
31
|
-
let f = o.length, p = Math.max(1, s / f - 1), m = s / f, h = Math.min(0, ...o), g = Math.max(...o) - h || 1, _ =
|
|
32
|
-
for (;
|
|
33
|
-
let e =
|
|
34
|
-
e &&
|
|
30
|
+
function g(a, o, s, c, l, u, d) {
|
|
31
|
+
let f = o.length, p = Math.max(1, s / f - 1), m = s / f, h = Math.min(0, ...o), g = Math.max(...o) - h || 1, _ = t(u, 0), v = _.duration, y = e(_.easing);
|
|
32
|
+
for (; a.children.length > f;) {
|
|
33
|
+
let e = a.lastElementChild;
|
|
34
|
+
e && a.removeChild(e);
|
|
35
35
|
}
|
|
36
|
-
for (let
|
|
37
|
-
let
|
|
38
|
-
if (u || (u =
|
|
36
|
+
for (let e = 0; e < f; e++) {
|
|
37
|
+
let t = Math.max(1, (o[e] - h) / g * c), s = c - t, u = a.children[e];
|
|
38
|
+
if (u || (u = r("rect", { class: "prism-spark-bar" }), a.appendChild(u)), i(u, {
|
|
39
39
|
fill: l,
|
|
40
40
|
width: p,
|
|
41
|
-
x:
|
|
41
|
+
x: e * m
|
|
42
42
|
}), v > 0 && !u.hasAttribute("data-init")) {
|
|
43
|
-
u.setAttribute("data-init", "1"),
|
|
43
|
+
u.setAttribute("data-init", "1"), i(u, {
|
|
44
44
|
height: 0,
|
|
45
45
|
y: c
|
|
46
46
|
});
|
|
47
|
-
let e = null,
|
|
47
|
+
let e = null, r = {
|
|
48
48
|
h: 0,
|
|
49
49
|
y: c
|
|
50
|
-
},
|
|
51
|
-
h:
|
|
50
|
+
}, a = {
|
|
51
|
+
h: t,
|
|
52
52
|
y: s
|
|
53
|
-
}, o = (
|
|
53
|
+
}, o = (t) => {
|
|
54
54
|
if (d?.aborted) return;
|
|
55
|
-
e === null && (e =
|
|
56
|
-
let s = y(Math.min(1, (
|
|
57
|
-
|
|
58
|
-
height:
|
|
59
|
-
y:
|
|
55
|
+
e === null && (e = t);
|
|
56
|
+
let s = y(Math.min(1, (t - e) / v));
|
|
57
|
+
i(u, {
|
|
58
|
+
height: n(r.h, a.h, s),
|
|
59
|
+
y: n(r.y, a.y, s)
|
|
60
60
|
}), s < 1 && requestAnimationFrame(o);
|
|
61
61
|
};
|
|
62
62
|
requestAnimationFrame(o);
|
|
63
|
-
} else u.setAttribute("data-init", "1"),
|
|
64
|
-
height:
|
|
63
|
+
} else u.setAttribute("data-init", "1"), i(u, {
|
|
64
|
+
height: t,
|
|
65
65
|
y: s
|
|
66
66
|
});
|
|
67
67
|
}
|
|
@@ -87,9 +87,9 @@ function v(e, t, n, r, i, a, o) {
|
|
|
87
87
|
function y(e) {
|
|
88
88
|
return `var(--prism-color-${e % 8 + 1})`;
|
|
89
89
|
}
|
|
90
|
-
function b(
|
|
91
|
-
let
|
|
92
|
-
...
|
|
90
|
+
function b(e, t) {
|
|
91
|
+
let n = t.variant ?? "line", o = t.color ?? "var(--prism-color-1)", s = t.curve ?? "linear", c = t.strokeWidth ?? 1.5, l = t.fillOpacity ?? .2, p = a(e, {
|
|
92
|
+
...t.ariaLabel ? { ariaLabel: t.ariaLabel } : { ariaHidden: !0 },
|
|
93
93
|
margin: {
|
|
94
94
|
bottom: 0,
|
|
95
95
|
left: 0,
|
|
@@ -98,67 +98,67 @@ function b(r, i) {
|
|
|
98
98
|
}
|
|
99
99
|
}), { svg: b } = p;
|
|
100
100
|
b.classList.add("prism-sparkline");
|
|
101
|
-
let x =
|
|
101
|
+
let x = r("g", { class: "prism-spark-inner" });
|
|
102
102
|
b.appendChild(x);
|
|
103
103
|
let S;
|
|
104
104
|
function C() {
|
|
105
|
-
let { height:
|
|
105
|
+
let { height: e, width: a } = p.dimensions.value, u = f(t.data) ? t.data.value : t.data;
|
|
106
106
|
for (; x.firstChild;) x.removeChild(x.firstChild);
|
|
107
107
|
if (u.length !== 0) {
|
|
108
|
-
if (
|
|
109
|
-
let
|
|
110
|
-
x.appendChild(
|
|
111
|
-
let o =
|
|
108
|
+
if (n === "stack" && _(u)) {
|
|
109
|
+
let n = r("g", { class: "prism-spark-stack" });
|
|
110
|
+
x.appendChild(n);
|
|
111
|
+
let o = t.cornerRadius ?? 4, s = u, c = s.reduce((e, t) => e + Math.max(0, t.value), 0);
|
|
112
112
|
if (c > 0) {
|
|
113
|
-
let l = (
|
|
114
|
-
s.forEach((
|
|
113
|
+
let l = (t.padPixels ?? 0) / 2, u = 0;
|
|
114
|
+
s.forEach((t, d) => {
|
|
115
115
|
let f = Math.round(u);
|
|
116
|
-
u += Math.max(0,
|
|
117
|
-
let p = d === s.length - 1 ?
|
|
118
|
-
|
|
116
|
+
u += Math.max(0, t.value) / c * a;
|
|
117
|
+
let p = d === s.length - 1 ? a : Math.round(u), m = d === 0, h = d === s.length - 1, g = v(f + (m ? 0 : l), 0, Math.max(0, p - f - (m ? 0 : l) - (h ? 0 : l)), e, o, m, h), _ = r("path", { class: "prism-spark-stack-segment" });
|
|
118
|
+
i(_, {
|
|
119
119
|
d: g,
|
|
120
|
-
fill:
|
|
121
|
-
}),
|
|
120
|
+
fill: t.color ?? y(d)
|
|
121
|
+
}), n.appendChild(_);
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
|
-
} else if (
|
|
125
|
-
let
|
|
126
|
-
x.appendChild(
|
|
124
|
+
} else if (n === "bar") {
|
|
125
|
+
let n = r("g", { class: "prism-spark-bars" });
|
|
126
|
+
x.appendChild(n), g(n, u, a, e, o, t.transition, T.signal);
|
|
127
127
|
} else {
|
|
128
|
-
if (
|
|
129
|
-
let
|
|
130
|
-
t
|
|
131
|
-
d:
|
|
128
|
+
if (n === "area") {
|
|
129
|
+
let t = r("path", { class: "prism-spark-fill" }), n = m(u, a, e, s);
|
|
130
|
+
i(t, {
|
|
131
|
+
d: n,
|
|
132
132
|
fill: o,
|
|
133
133
|
"fill-opacity": l,
|
|
134
134
|
stroke: "none"
|
|
135
|
-
}), x.appendChild(
|
|
135
|
+
}), x.appendChild(t);
|
|
136
136
|
}
|
|
137
|
-
let
|
|
138
|
-
t
|
|
137
|
+
let t = r("path", { class: "prism-spark-line" }), d = h(u, a, e, s);
|
|
138
|
+
i(t, {
|
|
139
139
|
d,
|
|
140
140
|
fill: "none",
|
|
141
141
|
stroke: o,
|
|
142
142
|
"stroke-width": c
|
|
143
|
-
}), x.appendChild(
|
|
143
|
+
}), x.appendChild(t);
|
|
144
144
|
}
|
|
145
145
|
_(u) || w(u);
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
function w(e) {
|
|
149
|
-
if (S?.(), S = void 0, !
|
|
150
|
-
let { width:
|
|
149
|
+
if (S?.(), S = void 0, !t.onHover && !t.onClick || e.length <= 1) return;
|
|
150
|
+
let { width: n } = p.dimensions.value;
|
|
151
151
|
b.style.cursor = "crosshair";
|
|
152
|
-
let
|
|
153
|
-
let
|
|
154
|
-
|
|
155
|
-
}, a = () =>
|
|
156
|
-
if (!
|
|
157
|
-
let
|
|
158
|
-
|
|
152
|
+
let r = n / (e.length - 1), i = (n) => {
|
|
153
|
+
let i = b.getBoundingClientRect(), a = n.clientX - i.left, o = Math.max(0, Math.min(e.length - 1, Math.round(a / r)));
|
|
154
|
+
t.onHover?.(o, e[o]);
|
|
155
|
+
}, a = () => t.onHover?.(null, null), o = (n) => {
|
|
156
|
+
if (!t.onClick) return;
|
|
157
|
+
let i = b.getBoundingClientRect(), a = n.clientX - i.left, o = Math.max(0, Math.min(e.length - 1, Math.round(a / r)));
|
|
158
|
+
t.onClick(o, e[o]);
|
|
159
159
|
};
|
|
160
|
-
b.addEventListener("mousemove",
|
|
161
|
-
b.removeEventListener("mousemove",
|
|
160
|
+
b.addEventListener("mousemove", i), b.addEventListener("mouseleave", a), b.addEventListener("click", o), S = () => {
|
|
161
|
+
b.removeEventListener("mousemove", i), b.removeEventListener("mouseleave", a), b.removeEventListener("click", o);
|
|
162
162
|
};
|
|
163
163
|
}
|
|
164
164
|
let T = new AbortController(), E = u();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sparkline.js","names":[],"sources":["../../../src/charts/sparkline/sparkline.ts"],"sourcesContent":["import { createScope, effect, isReactive } from '@vielzeug/ripple';\n\nimport type { Point } from '../../svg/path';\nimport type { ChartHandle, SparklineConfig, StackSegment } from '../../types';\n\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 { areaPath, linePath, monotonePath, stepPath } from '../../svg/path';\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.ariaLabel ? { ariaLabel: config.ariaLabel } : { 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.js","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.ariaLabel ? { ariaLabel: config.ariaLabel } : { 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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cartesian-model.cjs","names":[],"sources":["../../src/core/cartesian-model.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"cartesian-model.cjs","names":[],"sources":["../../src/core/cartesian-model.ts"],"sourcesContent":["import { warn } from '../_dev';\nimport type { Datum, Series } from '../types';\n\nexport type CartesianKey = string;\n\nexport interface CartesianSeries<S extends Series = Series> {\n readonly byKey: ReadonlyMap<CartesianKey, Datum>;\n readonly config: S;\n}\n\nexport interface CartesianModel<S extends Series = Series> {\n readonly domain: CartesianKey[];\n readonly labels: ReadonlyMap<CartesianKey, Datum['key']>;\n readonly series: readonly CartesianSeries<S>[];\n}\n\nexport function keyId(key: Datum['key']): CartesianKey {\n if (key instanceof Date) return `date:${key.getTime()}`;\n\n return `${typeof key}:${String(key)}`;\n}\n\nexport function normalizeCartesianSeries<S extends Series>(\n series: readonly S[],\n data: readonly (readonly Datum[])[],\n): CartesianModel<S> {\n const domain: CartesianKey[] = [];\n const labels = new Map<CartesianKey, Datum['key']>();\n const normalized = series.map((config, seriesIndex) => {\n const byKey = new Map<CartesianKey, Datum>();\n\n for (const datum of data[seriesIndex] ?? []) {\n const id = keyId(datum.key);\n\n if (byKey.has(id)) {\n warn(`Duplicate datum key \"${String(datum.key)}\" in series \"${config.name}\"; keeping the first value.`);\n continue;\n }\n\n byKey.set(id, datum);\n\n if (!labels.has(id)) {\n labels.set(id, datum.key);\n domain.push(id);\n }\n }\n\n return { byKey, config } satisfies CartesianSeries<S>;\n });\n\n return { domain, labels, series: normalized };\n}\n"],"mappings":"uBAgBA,SAAgB,EAAM,EAAiC,CAGrD,OAFI,aAAe,KAAa,QAAQ,EAAI,QAAQ,IAE7C,GAAG,OAAO,EAAI,GAAG,OAAO,CAAG,GACpC,CAEA,SAAgB,EACd,EACA,EACmB,CACnB,IAAM,EAAyB,CAAC,EAC1B,EAAS,IAAI,IAuBnB,MAAO,CAAE,SAAQ,SAAQ,OAtBN,EAAO,KAAK,EAAQ,IAAgB,CACrD,IAAM,EAAQ,IAAI,IAElB,IAAK,IAAM,KAAS,EAAK,IAAgB,CAAC,EAAG,CAC3C,IAAM,EAAK,EAAM,EAAM,GAAG,EAE1B,GAAI,EAAM,IAAI,CAAE,EAAG,CACZ,GAAwB,OAAO,EAAM,GAAG,EAAxC,EAAyD,EAAO,KAAhE,EACL,QACF,CAEA,EAAM,IAAI,EAAI,CAAK,EAEd,EAAO,IAAI,CAAE,IAChB,EAAO,IAAI,EAAI,EAAM,GAAG,EACxB,EAAO,KAAK,CAAE,EAElB,CAEA,MAAO,CAAE,QAAO,QAAO,CACzB,CAEiC,CAAW,CAC9C"}
|