@squirkle-ui/charts 0.0.0-stage → 0.1.0

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.
@@ -0,0 +1,455 @@
1
+ import { defineComponent, ref, onMounted, onBeforeUnmount, computed } from "vue";
2
+ import { SqShape, colorValue } from "@squirkle-ui/ui/vue2";
3
+ import { niceTicks } from "@squirkle-ui/core";
4
+ const _sfc_main$4 = defineComponent({
5
+ name: "SqChartFrame",
6
+ components: { SqShape },
7
+ props: {
8
+ title: { type: String, default: void 0 },
9
+ subtitle: { type: String, default: void 0 },
10
+ flat: Boolean,
11
+ legend: { type: Array, default: () => [] },
12
+ table: { type: Object, default: () => ({ head: [], rows: [] }) }
13
+ }
14
+ });
15
+ function normalizeComponent(scriptExports, render6, staticRenderFns, functionalTemplate, injectStyles, scopeId, moduleIdentifier, shadowMode) {
16
+ var options = typeof scriptExports === "function" ? scriptExports.options : scriptExports;
17
+ if (render6) {
18
+ options.render = render6;
19
+ options.staticRenderFns = staticRenderFns;
20
+ options._compiled = true;
21
+ }
22
+ return {
23
+ exports: scriptExports,
24
+ options
25
+ };
26
+ }
27
+ var _sfc_render$4 = function render() {
28
+ var _vm = this, _c = _vm._self._c;
29
+ _vm._self._setupProxy;
30
+ return _c("figure", { staticClass: "sq-chart sq-surface", class: { "sq-chart--flat": _vm.flat } }, [!_vm.flat ? _c("SqShape") : _vm._e(), _vm.title || _vm.subtitle ? _c("figcaption", { staticClass: "sq-chart__caption" }, [_vm.title ? _c("div", { staticClass: "sq-chart__title" }, [_vm._v(_vm._s(_vm.title))]) : _vm._e(), _vm.subtitle ? _c("div", { staticClass: "sq-chart__subtitle" }, [_vm._v(_vm._s(_vm.subtitle))]) : _vm._e()]) : _vm._e(), _vm.legend.length > 1 ? _c("div", { staticClass: "sq-chart__legend", attrs: { "role": "list" } }, _vm._l(_vm.legend, function(l, i) {
31
+ return _c("span", { key: l.name, staticClass: "sq-chart__legend-item", attrs: { "role": "listitem" } }, [_c("span", { staticClass: "sq-chart__swatch", style: { background: l.color } }), _vm._v(_vm._s(l.name) + " ")]);
32
+ }), 0) : _vm._e(), _vm._t("default"), _c("table", { staticClass: "sq-sr-only" }, [_c("caption", [_vm._v(_vm._s(_vm.title || "Chart data"))]), _c("thead", [_c("tr", _vm._l(_vm.table.head, function(h) {
33
+ return _c("th", { key: h }, [_vm._v(_vm._s(h))]);
34
+ }), 0)]), _c("tbody", _vm._l(_vm.table.rows, function(r, i) {
35
+ return _c("tr", { key: i }, _vm._l(r, function(c, j) {
36
+ return _c("td", { key: j }, [_vm._v(_vm._s(c))]);
37
+ }), 0);
38
+ }), 0)])], 2);
39
+ };
40
+ var _sfc_staticRenderFns$4 = [];
41
+ var __component__$4 = /* @__PURE__ */ normalizeComponent(
42
+ _sfc_main$4,
43
+ _sfc_render$4,
44
+ _sfc_staticRenderFns$4
45
+ );
46
+ const ChartFrame = __component__$4.exports;
47
+ const seriesColor = (i, override) => override != null ? override : `var(--sq-series-${i % 8 + 1})`;
48
+ function useSize(el, fallbackHeight) {
49
+ const width = ref(600);
50
+ const height = ref(fallbackHeight);
51
+ let ro;
52
+ onMounted(() => {
53
+ const measure = () => {
54
+ if (!el.value) return;
55
+ width.value = el.value.clientWidth || 600;
56
+ height.value = el.value.clientHeight || fallbackHeight;
57
+ };
58
+ measure();
59
+ if (typeof ResizeObserver !== "undefined" && el.value) {
60
+ ro = new ResizeObserver(measure);
61
+ ro.observe(el.value);
62
+ }
63
+ });
64
+ onBeforeUnmount(() => ro == null ? void 0 : ro.disconnect());
65
+ return { width, height };
66
+ }
67
+ function linearScale(d0, d1, r0, r1) {
68
+ const k = d1 === d0 ? 0 : (r1 - r0) / (d1 - d0);
69
+ return (v) => r0 + (v - d0) * k;
70
+ }
71
+ function yDomain(values, zero = true) {
72
+ let min = Math.min(...values);
73
+ let max = Math.max(...values);
74
+ if (zero) {
75
+ min = Math.min(0, min);
76
+ max = Math.max(0, max);
77
+ }
78
+ if (!isFinite(min) || !isFinite(max)) return { ticks: [0, 1], min: 0, max: 1 };
79
+ if (min === max) max = min + 1;
80
+ const ticks = niceTicks(min, max, 5);
81
+ return { ticks, min: ticks[0], max: ticks[ticks.length - 1] };
82
+ }
83
+ function smoothPath(pts) {
84
+ if (pts.length < 2) return pts.length ? `M${pts[0][0]},${pts[0][1]}` : "";
85
+ const n = pts.length;
86
+ const dx = [];
87
+ const m = [];
88
+ for (let i = 0; i < n - 1; i++) {
89
+ dx.push(pts[i + 1][0] - pts[i][0]);
90
+ m.push((pts[i + 1][1] - pts[i][1]) / (dx[i] || 1));
91
+ }
92
+ const t = [m[0]];
93
+ for (let i = 1; i < n - 1; i++) t.push(m[i - 1] * m[i] <= 0 ? 0 : 3 * (dx[i - 1] + dx[i]) / ((2 * dx[i] + dx[i - 1]) / m[i - 1] + (dx[i] + 2 * dx[i - 1]) / m[i]));
94
+ t.push(m[n - 2]);
95
+ let d = `M${pts[0][0]},${pts[0][1]}`;
96
+ for (let i = 0; i < n - 1; i++) {
97
+ const h = dx[i] / 3;
98
+ d += ` C${pts[i][0] + h},${pts[i][1] + t[i] * h} ${pts[i + 1][0] - h},${pts[i + 1][1] - t[i + 1] * h} ${pts[i + 1][0]},${pts[i + 1][1]}`;
99
+ }
100
+ return d;
101
+ }
102
+ const compact = (v, locale = "en-US") => new Intl.NumberFormat(locale, { notation: "compact", maximumFractionDigits: 1 }).format(v);
103
+ function barPath(x, y, w, h, r, horizontal = false, negative = false) {
104
+ if (w <= 0 || h <= 0) return "";
105
+ const rr = Math.min(r, (horizontal ? h : w) / 2, horizontal ? w : h);
106
+ const k = rr * 0.45;
107
+ if (horizontal) {
108
+ if (negative) return `M${x + w},${y} H${x + rr} C${x + rr - k},${y} ${x},${y + rr - k} ${x},${y + rr} V${y + h - rr} C${x},${y + h - rr + k} ${x + rr - k},${y + h} ${x + rr},${y + h} H${x + w} Z`;
109
+ return `M${x},${y} H${x + w - rr} C${x + w - rr + k},${y} ${x + w},${y + rr - k} ${x + w},${y + rr} V${y + h - rr} C${x + w},${y + h - rr + k} ${x + w - rr + k},${y + h} ${x + w - rr},${y + h} H${x} Z`;
110
+ }
111
+ if (negative) return `M${x},${y} H${x + w} V${y + h - rr} C${x + w},${y + h - rr + k} ${x + w - rr + k},${y + h} ${x + w - rr},${y + h} H${x + rr} C${x + rr - k},${y + h} ${x},${y + h - rr + k} ${x},${y + h - rr} Z`;
112
+ return `M${x},${y + h} V${y + rr} C${x},${y + rr - k} ${x + rr - k},${y} ${x + rr},${y} H${x + w - rr} C${x + w - rr + k},${y} ${x + w},${y + rr - k} ${x + w},${y + rr} V${y + h} Z`;
113
+ }
114
+ const _sfc_main$3 = defineComponent({
115
+ name: "SqLineChart",
116
+ components: { ChartFrame },
117
+ props: {
118
+ labels: { type: Array, default: () => [] },
119
+ series: { type: Array, default: () => [] },
120
+ title: { type: String, default: void 0 },
121
+ subtitle: { type: String, default: void 0 },
122
+ height: { type: Number, default: 260 },
123
+ area: Boolean,
124
+ smooth: { type: Boolean, default: true },
125
+ points: Boolean,
126
+ /** Start y at zero (recommended for areas). */
127
+ zero: { type: Boolean, default: true },
128
+ flat: Boolean,
129
+ format: { type: Function, default: void 0 }
130
+ },
131
+ setup(props) {
132
+ const box = ref(null);
133
+ const { width: w } = useSize(box, props.height);
134
+ const pad = { t: 12, r: 16, b: 26, l: 44 };
135
+ const hover = ref(-1);
136
+ const y = computed(() => yDomain(props.series.flatMap((s) => s.data.filter((v) => v != null)), props.zero || props.area));
137
+ const sy = computed(() => linearScale(y.value.min, y.value.max, props.height - pad.b, pad.t));
138
+ const sx = computed(() => {
139
+ const n = Math.max(1, props.labels.length - 1);
140
+ return (i) => pad.l + (w.value - pad.l - pad.r) * i / n;
141
+ });
142
+ const colorOf = (i) => {
143
+ var _a;
144
+ return seriesColor(i, (_a = props.series[i]) == null ? void 0 : _a.color);
145
+ };
146
+ const fmt = (v) => props.format ? props.format(v) : compact(v);
147
+ const fmtCell = (v) => v == null ? "–" : fmt(v);
148
+ const paths = computed(
149
+ () => props.series.map((s, i) => {
150
+ const pts = s.data.map((v, k) => [sx.value(k), v == null ? null : sy.value(v)]);
151
+ const valid = pts.filter((p) => p[1] != null);
152
+ const line = props.smooth ? smoothPath(valid) : valid.map((p, k) => `${k ? "L" : "M"}${p[0]},${p[1]}`).join(" ");
153
+ const base = sy.value(Math.max(y.value.min, 0));
154
+ const area = valid.length ? `${line} L${valid[valid.length - 1][0]},${base} L${valid[0][0]},${base} Z` : "";
155
+ return { name: s.name, color: colorOf(i), pts, line, area };
156
+ })
157
+ );
158
+ const showLabel = (i) => {
159
+ const n = props.labels.length;
160
+ const every = Math.ceil(n / Math.max(2, Math.floor((w.value - pad.l) / 64)));
161
+ return i % every === 0 || i === n - 1;
162
+ };
163
+ const onMove = (e) => {
164
+ const r = box.value.getBoundingClientRect();
165
+ const n = props.labels.length;
166
+ if (!n) return;
167
+ const i = Math.round((e.clientX - r.left - pad.l) / (w.value - pad.l - pad.r) * (n - 1));
168
+ hover.value = Math.max(0, Math.min(n - 1, i));
169
+ };
170
+ const tipStyle = computed(() => {
171
+ const x = sx.value(hover.value);
172
+ return x > w.value / 2 ? { right: `${w.value - x + 12}px`, top: "8px" } : { left: `${x + 12}px`, top: "8px" };
173
+ });
174
+ const legend = computed(() => props.series.map((s, i) => ({ name: s.name, color: colorOf(i) })));
175
+ const table = computed(() => ({ head: ["", ...props.series.map((s) => s.name)], rows: props.labels.map((l, k) => [l, ...props.series.map((s) => {
176
+ var _a;
177
+ return (_a = s.data[k]) != null ? _a : "";
178
+ })]) }));
179
+ return { fmtCell, box, w, pad, hover, y, sy, sx, paths, colorOf, fmt, showLabel, onMove, tipStyle, legend, table };
180
+ }
181
+ });
182
+ var _sfc_render$3 = function render2() {
183
+ var _vm = this, _c = _vm._self._c;
184
+ _vm._self._setupProxy;
185
+ return _c("ChartFrame", { attrs: { "title": _vm.title, "subtitle": _vm.subtitle, "flat": _vm.flat, "legend": _vm.legend, "table": _vm.table } }, [_c("div", { ref: "box", staticClass: "sq-chart__plot", style: { height: _vm.height + "px" }, on: { "pointermove": _vm.onMove, "pointerleave": function($event) {
186
+ _vm.hover = -1;
187
+ } } }, [_c("svg", { attrs: { "width": _vm.w, "height": _vm.height, "role": "img", "aria-label": _vm.title || "Line chart" } }, [_c("g", { staticClass: "sq-chart__grid" }, _vm._l(_vm.y.ticks, function(t) {
188
+ return _c("line", { key: "g" + t, attrs: { "x1": _vm.pad.l, "x2": _vm.w - _vm.pad.r, "y1": _vm.sy(t), "y2": _vm.sy(t) } });
189
+ }), 0), _c("g", { staticClass: "sq-chart__axis" }, [_vm._l(_vm.y.ticks, function(t) {
190
+ return _c("text", { key: "y" + t, attrs: { "x": _vm.pad.l - 8, "y": _vm.sy(t), "text-anchor": "end", "dominant-baseline": "middle" } }, [_vm._v(_vm._s(_vm.fmt(t)))]);
191
+ }), _vm._l(_vm.labels, function(l, i) {
192
+ return _c("text", { directives: [{ name: "show", rawName: "v-show", value: _vm.showLabel(i), expression: "showLabel(i)" }], key: "x" + i, attrs: { "x": _vm.sx(i), "y": _vm.height - 6, "text-anchor": "middle" } }, [_vm._v(_vm._s(l))]);
193
+ })], 2), _vm._l(_vm.paths, function(s, si) {
194
+ return _c("g", { key: s.name }, [_vm.area ? _c("path", { staticClass: "sq-chart__area", attrs: { "d": s.area, "fill": s.color } }) : _vm._e(), _c("path", { staticClass: "sq-chart__line", attrs: { "d": s.line, "stroke": s.color } })]);
195
+ }), _vm.hover >= 0 ? _c("line", { staticClass: "sq-chart__crosshair", attrs: { "x1": _vm.sx(_vm.hover), "x2": _vm.sx(_vm.hover), "y1": _vm.pad.t, "y2": _vm.height - _vm.pad.b } }) : _vm._e(), _vm.hover >= 0 ? _c("g", _vm._l(_vm.paths, function(s) {
196
+ var _a;
197
+ return _c("circle", { directives: [{ name: "show", rawName: "v-show", value: s.pts[_vm.hover] && s.pts[_vm.hover][1] != null, expression: "s.pts[hover] && s.pts[hover][1] != null" }], key: "p" + s.name, staticClass: "sq-chart__dot", attrs: { "cx": _vm.sx(_vm.hover), "cy": s.pts[_vm.hover] ? (_a = s.pts[_vm.hover][1]) != null ? _a : 0 : 0, "r": "4.5", "fill": s.color } });
198
+ }), 0) : _vm._e(), _vm.points && _vm.hover < 0 ? _c("g", _vm._l(_vm.paths, function(s) {
199
+ return _c("g", { key: "pp" + s.name }, _vm._l(s.pts, function(p, i) {
200
+ var _a;
201
+ return _c("circle", { directives: [{ name: "show", rawName: "v-show", value: p[1] != null, expression: "p[1] != null" }], key: i, staticClass: "sq-chart__dot", attrs: { "cx": p[0], "cy": (_a = p[1]) != null ? _a : 0, "r": "4", "fill": s.color } });
202
+ }), 0);
203
+ }), 0) : _vm._e()], 2), _vm.hover >= 0 ? _c("div", { staticClass: "sq-chart__tooltip sq-squircle", style: _vm.tipStyle }, [_c("div", { staticClass: "sq-chart__tooltip-title" }, [_vm._v(_vm._s(_vm.labels[_vm.hover]))]), _vm._l(_vm.series, function(s, i) {
204
+ return _c("div", { key: s.name, staticClass: "sq-chart__tooltip-row" }, [_c("span", { staticClass: "sq-chart__swatch", style: { background: _vm.colorOf(i) } }), _vm._v(_vm._s(s.name)), _c("b", [_vm._v(_vm._s(_vm.fmtCell(s.data[_vm.hover])))])]);
205
+ })], 2) : _vm._e()])]);
206
+ };
207
+ var _sfc_staticRenderFns$3 = [];
208
+ var __component__$3 = /* @__PURE__ */ normalizeComponent(
209
+ _sfc_main$3,
210
+ _sfc_render$3,
211
+ _sfc_staticRenderFns$3
212
+ );
213
+ const SqLineChart = __component__$3.exports;
214
+ const _sfc_main$2 = defineComponent({
215
+ name: "SqBarChart",
216
+ components: { ChartFrame },
217
+ props: {
218
+ labels: { type: Array, default: () => [] },
219
+ series: { type: Array, default: () => [] },
220
+ title: { type: String, default: void 0 },
221
+ subtitle: { type: String, default: void 0 },
222
+ height: { type: Number, default: 260 },
223
+ stacked: Boolean,
224
+ horizontal: Boolean,
225
+ radius: { type: Number, default: 6 },
226
+ flat: Boolean,
227
+ format: { type: Function, default: void 0 }
228
+ },
229
+ setup(props) {
230
+ const box = ref(null);
231
+ const { width: w } = useSize(box, props.height);
232
+ const pad = computed(() => props.horizontal ? { t: 8, r: 16, b: 24, l: 84 } : { t: 12, r: 16, b: 26, l: 44 });
233
+ const hover = ref(null);
234
+ const colorOf = (i) => {
235
+ var _a;
236
+ return seriesColor(i, (_a = props.series[i]) == null ? void 0 : _a.color);
237
+ };
238
+ const fmt = (v) => props.format ? props.format(v) : compact(v);
239
+ const fmtCell = (v) => v == null ? "–" : fmt(v);
240
+ const y = computed(() => {
241
+ const vals = props.stacked ? props.labels.flatMap((_, k) => {
242
+ var _a;
243
+ let pos = 0;
244
+ let neg = 0;
245
+ for (const s of props.series) {
246
+ const v = (_a = s.data[k]) != null ? _a : 0;
247
+ v >= 0 ? pos += v : neg += v;
248
+ }
249
+ return [pos, neg];
250
+ }) : props.series.flatMap((s) => s.data.filter((v) => v != null));
251
+ return yDomain(vals, true);
252
+ });
253
+ const sv = computed(() => props.horizontal ? linearScale(y.value.min, y.value.max, pad.value.l, w.value - pad.value.r) : linearScale(y.value.min, y.value.max, props.height - pad.value.b, pad.value.t));
254
+ const band = computed(() => {
255
+ const n = Math.max(1, props.labels.length);
256
+ const len = props.horizontal ? props.height - pad.value.t - pad.value.b : w.value - pad.value.l - pad.value.r;
257
+ const step = len / n;
258
+ return { step, inner: step * 0.72, start: props.horizontal ? pad.value.t : pad.value.l };
259
+ });
260
+ const bars = computed(() => {
261
+ const out = [];
262
+ const gap = 2;
263
+ const zero = sv.value(0);
264
+ props.labels.forEach((_, k) => {
265
+ const c0 = band.value.start + band.value.step * k + (band.value.step - band.value.inner) / 2;
266
+ let pos = 0;
267
+ let neg = 0;
268
+ const n = props.series.length;
269
+ props.series.forEach((s, i) => {
270
+ const v = s.data[k];
271
+ if (v == null) return;
272
+ let a;
273
+ let b;
274
+ let c;
275
+ let thick;
276
+ if (props.stacked) {
277
+ const from = v >= 0 ? pos : neg;
278
+ const to = from + v;
279
+ v >= 0 ? pos = to : neg = to;
280
+ a = sv.value(from);
281
+ b = sv.value(to);
282
+ c = c0;
283
+ thick = band.value.inner;
284
+ } else {
285
+ a = zero;
286
+ b = sv.value(v);
287
+ thick = Math.max(1, (band.value.inner - gap * (n - 1)) / n);
288
+ c = c0 + i * (thick + gap);
289
+ }
290
+ const lo = Math.min(a, b);
291
+ const len = Math.abs(b - a) - (props.stacked ? gap : 0);
292
+ const top = props.stacked ? props.series.slice(i + 1).every((x) => {
293
+ var _a, _b;
294
+ return ((_a = x.data[k]) != null ? _a : 0) === 0 || Math.sign((_b = x.data[k]) != null ? _b : 0) !== Math.sign(v);
295
+ }) : true;
296
+ const r = top ? props.radius : 0;
297
+ const d = props.horizontal ? barPath(v >= 0 ? lo : lo + (props.stacked ? gap : 0), c, Math.max(0, len), thick, r, true, v < 0) : barPath(c, v >= 0 ? lo + (props.stacked ? gap : 0) : lo, thick, Math.max(0, len), r, false, v < 0);
298
+ out.push({ key: `${k}-${i}`, d, color: colorOf(i), cat: k, cx: props.horizontal ? Math.max(a, b) : c + thick / 2, cy: props.horizontal ? c : Math.min(a, b) });
299
+ });
300
+ });
301
+ return out;
302
+ });
303
+ const gridLine = (t) => props.horizontal ? { x1: sv.value(t), x2: sv.value(t), y1: pad.value.t, y2: props.height - pad.value.b } : { x1: pad.value.l, x2: w.value - pad.value.r, y1: sv.value(t), y2: sv.value(t) };
304
+ const valueTick = (t) => props.horizontal ? { x: sv.value(t), y: props.height - 6, "text-anchor": "middle" } : { x: pad.value.l - 8, y: sv.value(t), "text-anchor": "end", "dominant-baseline": "middle" };
305
+ const catTick = (i) => {
306
+ const mid = band.value.start + band.value.step * (i + 0.5);
307
+ return props.horizontal ? { x: pad.value.l - 8, y: mid, "text-anchor": "end", "dominant-baseline": "middle" } : { x: mid, y: props.height - 6, "text-anchor": "middle" };
308
+ };
309
+ const tipStyle = computed(() => {
310
+ const h = hover.value;
311
+ if (!h) return {};
312
+ return h.x > w.value / 2 ? { right: `${w.value - h.x + 10}px`, top: `${Math.max(4, h.y - 10)}px` } : { left: `${h.x + 10}px`, top: `${Math.max(4, h.y - 10)}px` };
313
+ });
314
+ const legend = computed(() => props.series.map((s, i) => ({ name: s.name, color: colorOf(i) })));
315
+ const table = computed(() => ({ head: ["", ...props.series.map((s) => s.name)], rows: props.labels.map((l, k) => [l, ...props.series.map((s) => {
316
+ var _a;
317
+ return (_a = s.data[k]) != null ? _a : "";
318
+ })]) }));
319
+ return { fmtCell, box, w, hover, y, bars, gridLine, valueTick, catTick, colorOf, fmt, tipStyle, legend, table };
320
+ }
321
+ });
322
+ var _sfc_render$2 = function render3() {
323
+ var _vm = this, _c = _vm._self._c;
324
+ _vm._self._setupProxy;
325
+ return _c("ChartFrame", { attrs: { "title": _vm.title, "subtitle": _vm.subtitle, "flat": _vm.flat, "legend": _vm.legend, "table": _vm.table } }, [_c("div", { ref: "box", staticClass: "sq-chart__plot", style: { height: _vm.height + "px" }, on: { "pointerleave": function($event) {
326
+ _vm.hover = null;
327
+ } } }, [_c("svg", { attrs: { "width": _vm.w, "height": _vm.height, "role": "img", "aria-label": _vm.title || "Bar chart" } }, [_c("g", { staticClass: "sq-chart__grid" }, _vm._l(_vm.y.ticks, function(t) {
328
+ return _c("line", _vm._b({ key: "g" + t }, "line", _vm.gridLine(t), false));
329
+ }), 0), _c("g", { staticClass: "sq-chart__axis" }, [_vm._l(_vm.y.ticks, function(t) {
330
+ return _c("text", _vm._b({ key: "y" + t }, "text", _vm.valueTick(t), false), [_vm._v(_vm._s(_vm.fmt(t)))]);
331
+ }), _vm._l(_vm.labels, function(l, i) {
332
+ return _c("text", _vm._b({ key: "x" + i }, "text", _vm.catTick(i), false), [_vm._v(_vm._s(l))]);
333
+ })], 2), _vm._l(_vm.bars, function(b) {
334
+ return _c("path", { key: b.key, staticClass: "sq-chart__bar", class: { "sq-chart__bar--dim": _vm.hover && _vm.hover.cat !== b.cat }, attrs: { "d": b.d, "fill": b.color }, on: { "pointerenter": function($event) {
335
+ _vm.hover = { cat: b.cat, x: b.cx, y: b.cy };
336
+ } } });
337
+ })], 2), _vm.hover ? _c("div", { staticClass: "sq-chart__tooltip sq-squircle", style: _vm.tipStyle }, [_c("div", { staticClass: "sq-chart__tooltip-title" }, [_vm._v(_vm._s(_vm.labels[_vm.hover.cat]))]), _vm._l(_vm.series, function(s, i) {
338
+ return _c("div", { key: s.name, staticClass: "sq-chart__tooltip-row" }, [_c("span", { staticClass: "sq-chart__swatch", style: { background: _vm.colorOf(i) } }), _vm._v(_vm._s(s.name)), _c("b", [_vm._v(_vm._s(_vm.fmtCell(s.data[_vm.hover.cat])))])]);
339
+ })], 2) : _vm._e()])]);
340
+ };
341
+ var _sfc_staticRenderFns$2 = [];
342
+ var __component__$2 = /* @__PURE__ */ normalizeComponent(
343
+ _sfc_main$2,
344
+ _sfc_render$2,
345
+ _sfc_staticRenderFns$2
346
+ );
347
+ const SqBarChart = __component__$2.exports;
348
+ const _sfc_main$1 = defineComponent({
349
+ name: "SqDonutChart",
350
+ components: { ChartFrame },
351
+ props: {
352
+ data: { type: Array, default: () => [] },
353
+ title: { type: String, default: void 0 },
354
+ subtitle: { type: String, default: void 0 },
355
+ size: { type: Number, default: 220 },
356
+ /** Ring thickness as a fraction of the radius; 1 = pie. */
357
+ thickness: { type: Number, default: 0.34 },
358
+ totalLabel: { type: String, default: "Total" },
359
+ flat: Boolean,
360
+ format: { type: Function, default: void 0 }
361
+ },
362
+ setup(props) {
363
+ const hover = ref(-1);
364
+ const total = computed(() => props.data.reduce((s, d) => s + Math.max(0, d.value), 0));
365
+ const fmt = (v) => props.format ? props.format(v) : compact(v);
366
+ const arcs = computed(() => {
367
+ const c = props.size / 2;
368
+ const R = c - 4;
369
+ const r = R * (1 - props.thickness);
370
+ const gap = props.data.length > 1 ? 2 / R : 0;
371
+ let a0 = -Math.PI / 2;
372
+ return props.data.map((d, i) => {
373
+ const sweep = total.value ? Math.max(0, d.value) / total.value * Math.PI * 2 : 0;
374
+ const s = a0 + gap / 2;
375
+ const e = a0 + sweep - gap / 2;
376
+ a0 += sweep;
377
+ const large = e - s > Math.PI ? 1 : 0;
378
+ const p = (rad, ang) => `${c + rad * Math.cos(ang)},${c + rad * Math.sin(ang)}`;
379
+ const dPath = e <= s ? "" : r > 0 ? `M${p(R, s)} A${R},${R} 0 ${large} 1 ${p(R, e)} L${p(r, e)} A${r},${r} 0 ${large} 0 ${p(r, s)} Z` : `M${c},${c} L${p(R, s)} A${R},${R} 0 ${large} 1 ${p(R, e)} Z`;
380
+ return { label: d.label, color: seriesColor(i, d.color), d: dPath };
381
+ });
382
+ });
383
+ const legend = computed(() => props.data.map((d, i) => ({ name: `${d.label} · ${total.value ? Math.round(d.value / total.value * 100) : 0}%`, color: seriesColor(i, d.color) })));
384
+ const table = computed(() => ({ head: ["Label", "Value"], rows: props.data.map((d) => [d.label, d.value]) }));
385
+ return { hover, total, fmt, arcs, legend, table };
386
+ }
387
+ });
388
+ var _sfc_render$1 = function render4() {
389
+ var _vm = this, _c = _vm._self._c;
390
+ _vm._self._setupProxy;
391
+ return _c("ChartFrame", { attrs: { "title": _vm.title, "subtitle": _vm.subtitle, "flat": _vm.flat, "legend": _vm.legend, "table": _vm.table } }, [_c("div", { staticClass: "sq-chart__donut", style: { height: _vm.size + "px" } }, [_c("svg", { attrs: { "width": _vm.size, "height": _vm.size, "viewBox": `0 0 ${_vm.size} ${_vm.size}`, "role": "img", "aria-label": _vm.title || "Donut chart" }, on: { "pointerleave": function($event) {
392
+ _vm.hover = -1;
393
+ } } }, _vm._l(_vm.arcs, function(a, i) {
394
+ return _c("path", { key: a.label, staticClass: "sq-chart__arc", class: { "sq-chart__arc--dim": _vm.hover >= 0 && _vm.hover !== i }, attrs: { "d": a.d, "fill": a.color }, on: { "pointerenter": function($event) {
395
+ _vm.hover = i;
396
+ } } });
397
+ }), 0), _c("div", { staticClass: "sq-chart__donut-center" }, [_vm._t("center", function() {
398
+ return [_c("div", { staticClass: "sq-chart__donut-value" }, [_vm._v(_vm._s(_vm.hover >= 0 ? _vm.fmt(_vm.data[_vm.hover].value) : _vm.fmt(_vm.total)))]), _c("div", { staticClass: "sq-chart__donut-label" }, [_vm._v(_vm._s(_vm.hover >= 0 ? _vm.data[_vm.hover].label : _vm.totalLabel))])];
399
+ }, { "hover": _vm.hover >= 0 ? _vm.data[_vm.hover] : null, "total": _vm.total })], 2)])]);
400
+ };
401
+ var _sfc_staticRenderFns$1 = [];
402
+ var __component__$1 = /* @__PURE__ */ normalizeComponent(
403
+ _sfc_main$1,
404
+ _sfc_render$1,
405
+ _sfc_staticRenderFns$1
406
+ );
407
+ const SqDonutChart = __component__$1.exports;
408
+ const _sfc_main = defineComponent({
409
+ name: "SqSparkline",
410
+ props: {
411
+ data: { type: Array, default: () => [] },
412
+ width: { type: Number, default: 120 },
413
+ height: { type: Number, default: 32 },
414
+ color: { type: String, default: "primary" },
415
+ fill: Boolean,
416
+ label: { type: String, default: "Trend" }
417
+ },
418
+ setup(props) {
419
+ const pts = computed(() => {
420
+ const d = props.data;
421
+ if (!d.length) return [];
422
+ const min = Math.min(...d);
423
+ const max = Math.max(...d);
424
+ const span = max - min || 1;
425
+ return d.map((v, i) => [3 + (props.width - 6) * i / Math.max(1, d.length - 1), 3 + (props.height - 6) * (1 - (v - min) / span)]);
426
+ });
427
+ const lineD = computed(() => smoothPath(pts.value));
428
+ const areaD = computed(() => pts.value.length ? `${lineD.value} L${pts.value[pts.value.length - 1][0]},${props.height} L${pts.value[0][0]},${props.height} Z` : "");
429
+ return { pts, lineD, areaD, stroke: computed(() => colorValue(props.color)) };
430
+ }
431
+ });
432
+ var _sfc_render = function render5() {
433
+ var _vm = this, _c = _vm._self._c;
434
+ _vm._self._setupProxy;
435
+ return _c("svg", { ref: "el", staticClass: "sq-sparkline", attrs: { "width": _vm.width, "height": _vm.height, "viewBox": `0 0 ${_vm.width} ${_vm.height}`, "role": "img", "aria-label": _vm.label } }, [_vm.fill ? _c("path", { staticClass: "sq-sparkline__area", attrs: { "d": _vm.areaD, "fill": _vm.stroke } }) : _vm._e(), _c("path", { staticClass: "sq-sparkline__line", attrs: { "d": _vm.lineD, "stroke": _vm.stroke } }), _vm.pts.length ? _c("circle", { attrs: { "cx": _vm.pts[_vm.pts.length - 1][0], "cy": _vm.pts[_vm.pts.length - 1][1], "r": "2.5", "fill": _vm.stroke } }) : _vm._e()]);
436
+ };
437
+ var _sfc_staticRenderFns = [];
438
+ var __component__ = /* @__PURE__ */ normalizeComponent(
439
+ _sfc_main,
440
+ _sfc_render,
441
+ _sfc_staticRenderFns
442
+ );
443
+ const SqSparkline = __component__.exports;
444
+ const componentNames = ["SqLineChart", "SqBarChart", "SqDonutChart", "SqSparkline"];
445
+ export {
446
+ SqBarChart,
447
+ SqDonutChart,
448
+ SqLineChart,
449
+ SqSparkline,
450
+ barPath,
451
+ componentNames,
452
+ seriesColor,
453
+ smoothPath
454
+ };
455
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../src/components/ChartFrame.vue","../../src/utils.ts","../../src/components/SqLineChart.vue","../../src/components/SqBarChart.vue","../../src/components/SqDonutChart.vue","../../src/components/SqSparkline.vue","../../src/index.ts"],"sourcesContent":["<template>\n <figure class=\"sq-chart sq-surface\" :class=\"{ 'sq-chart--flat': flat }\">\n <SqShape v-if=\"!flat\" />\n <figcaption v-if=\"title || subtitle\" class=\"sq-chart__caption\">\n <div v-if=\"title\" class=\"sq-chart__title\">{{ title }}</div>\n <div v-if=\"subtitle\" class=\"sq-chart__subtitle\">{{ subtitle }}</div>\n </figcaption>\n <div v-if=\"legend.length > 1\" class=\"sq-chart__legend\" role=\"list\">\n <span v-for=\"(l, i) in legend\" :key=\"l.name\" class=\"sq-chart__legend-item\" role=\"listitem\">\n <span class=\"sq-chart__swatch\" :style=\"{ background: l.color }\"></span>{{ l.name }}\n </span>\n </div>\n <slot />\n <table class=\"sq-sr-only\">\n <caption>{{ title || 'Chart data' }}</caption>\n <thead><tr><th v-for=\"h in table.head\" :key=\"h\">{{ h }}</th></tr></thead>\n <tbody><tr v-for=\"(r, i) in table.rows\" :key=\"i\"><td v-for=\"(c, j) in r\" :key=\"j\">{{ c }}</td></tr></tbody>\n </table>\n </figure>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, type PropType } from 'vue'\nimport { SqShape } from '@squirkle-ui/ui'\n\n/** Card, caption, legend and an accessible data table shared by every chart (internal). */\nexport default defineComponent({\n name: 'SqChartFrame',\n components: { SqShape },\n props: {\n title: { type: String, default: undefined },\n subtitle: { type: String, default: undefined },\n flat: Boolean,\n legend: { type: Array as PropType<{ name: string; color: string }[]>, default: () => [] },\n table: { type: Object as PropType<{ head: string[]; rows: (string | number)[][] }>, default: () => ({ head: [], rows: [] }) },\n },\n})\n</script>\n","import { onBeforeUnmount, onMounted, ref, type Ref } from 'vue'\nimport { niceTicks } from '@squirkle-ui/core'\n\nexport interface DonutDatum { label: string; value: number; color?: string }\n\nexport interface Series { name: string; data: (number | null)[]; color?: string }\n\n/** Validated categorical order (dataviz reference palette); slots are CSS vars so light/dark swap via theme. */\nexport const seriesColor = (i: number, override?: string) => override ?? `var(--sq-series-${(i % 8) + 1})`\n\nexport function useSize(el: Ref<HTMLElement | null>, fallbackHeight: number) {\n const width = ref(600)\n const height = ref(fallbackHeight)\n let ro: ResizeObserver | undefined\n onMounted(() => {\n const measure = () => {\n if (!el.value) return\n width.value = el.value.clientWidth || 600\n height.value = el.value.clientHeight || fallbackHeight\n }\n measure()\n if (typeof ResizeObserver !== 'undefined' && el.value) { ro = new ResizeObserver(measure); ro.observe(el.value) }\n })\n onBeforeUnmount(() => ro?.disconnect())\n return { width, height }\n}\n\nexport function linearScale(d0: number, d1: number, r0: number, r1: number) {\n const k = d1 === d0 ? 0 : (r1 - r0) / (d1 - d0)\n return (v: number) => r0 + (v - d0) * k\n}\n\nexport function yDomain(values: number[], zero = true) {\n let min = Math.min(...values)\n let max = Math.max(...values)\n if (zero) { min = Math.min(0, min); max = Math.max(0, max) }\n if (!isFinite(min) || !isFinite(max)) return { ticks: [0, 1], min: 0, max: 1 }\n if (min === max) max = min + 1\n const ticks = niceTicks(min, max, 5)\n return { ticks, min: ticks[0], max: ticks[ticks.length - 1] }\n}\n\n/** Monotone cubic (Fritsch–Carlson) path through points — smooth without overshoot. */\nexport function smoothPath(pts: [number, number][]): string {\n if (pts.length < 2) return pts.length ? `M${pts[0][0]},${pts[0][1]}` : ''\n const n = pts.length\n const dx: number[] = []\n const m: number[] = []\n for (let i = 0; i < n - 1; i++) {\n dx.push(pts[i + 1][0] - pts[i][0])\n m.push((pts[i + 1][1] - pts[i][1]) / (dx[i] || 1))\n }\n const t = [m[0]]\n for (let i = 1; i < n - 1; i++) t.push(m[i - 1] * m[i] <= 0 ? 0 : (3 * (dx[i - 1] + dx[i])) / ((2 * dx[i] + dx[i - 1]) / m[i - 1] + (dx[i] + 2 * dx[i - 1]) / m[i]))\n t.push(m[n - 2])\n let d = `M${pts[0][0]},${pts[0][1]}`\n for (let i = 0; i < n - 1; i++) {\n const h = dx[i] / 3\n d += ` C${pts[i][0] + h},${pts[i][1] + t[i] * h} ${pts[i + 1][0] - h},${pts[i + 1][1] - t[i + 1] * h} ${pts[i + 1][0]},${pts[i + 1][1]}`\n }\n return d\n}\n\nexport const compact = (v: number, locale = 'en-US') => new Intl.NumberFormat(locale, { notation: 'compact', maximumFractionDigits: 1 }).format(v)\n\n/** Bar with squircle-rounded data end (top for positive, bottom for negative), square at the baseline. */\nexport function barPath(x: number, y: number, w: number, h: number, r: number, horizontal = false, negative = false): string {\n if (w <= 0 || h <= 0) return ''\n const rr = Math.min(r, (horizontal ? h : w) / 2, horizontal ? w : h)\n const k = rr * 0.45 // control distance → superellipse-like corner\n if (horizontal) {\n if (negative) return `M${x + w},${y} H${x + rr} C${x + rr - k},${y} ${x},${y + rr - k} ${x},${y + rr} V${y + h - rr} C${x},${y + h - rr + k} ${x + rr - k},${y + h} ${x + rr},${y + h} H${x + w} Z`\n return `M${x},${y} H${x + w - rr} C${x + w - rr + k},${y} ${x + w},${y + rr - k} ${x + w},${y + rr} V${y + h - rr} C${x + w},${y + h - rr + k} ${x + w - rr + k},${y + h} ${x + w - rr},${y + h} H${x} Z`\n }\n if (negative) return `M${x},${y} H${x + w} V${y + h - rr} C${x + w},${y + h - rr + k} ${x + w - rr + k},${y + h} ${x + w - rr},${y + h} H${x + rr} C${x + rr - k},${y + h} ${x},${y + h - rr + k} ${x},${y + h - rr} Z`\n return `M${x},${y + h} V${y + rr} C${x},${y + rr - k} ${x + rr - k},${y} ${x + rr},${y} H${x + w - rr} C${x + w - rr + k},${y} ${x + w},${y + rr - k} ${x + w},${y + rr} V${y + h} Z`\n}\n","<template>\n <ChartFrame :title=\"title\" :subtitle=\"subtitle\" :flat=\"flat\" :legend=\"legend\" :table=\"table\">\n <div ref=\"box\" class=\"sq-chart__plot\" :style=\"{ height: height + 'px' }\" @pointermove=\"onMove\" @pointerleave=\"hover = -1\">\n <svg :width=\"w\" :height=\"height\" role=\"img\" :aria-label=\"title || 'Line chart'\">\n <g class=\"sq-chart__grid\">\n <line v-for=\"t in y.ticks\" :key=\"'g' + t\" :x1=\"pad.l\" :x2=\"w - pad.r\" :y1=\"sy(t)\" :y2=\"sy(t)\" />\n </g>\n <g class=\"sq-chart__axis\">\n <text v-for=\"t in y.ticks\" :key=\"'y' + t\" :x=\"pad.l - 8\" :y=\"sy(t)\" text-anchor=\"end\" dominant-baseline=\"middle\">{{ fmt(t) }}</text>\n <text v-for=\"(l, i) in labels\" v-show=\"showLabel(i)\" :key=\"'x' + i\" :x=\"sx(i)\" :y=\"height - 6\" text-anchor=\"middle\">{{ l }}</text>\n </g>\n <g v-for=\"(s, si) in paths\" :key=\"s.name\">\n <path v-if=\"area\" :d=\"s.area\" :fill=\"s.color\" class=\"sq-chart__area\" />\n <path :d=\"s.line\" :stroke=\"s.color\" class=\"sq-chart__line\" />\n </g>\n <line v-if=\"hover >= 0\" class=\"sq-chart__crosshair\" :x1=\"sx(hover)\" :x2=\"sx(hover)\" :y1=\"pad.t\" :y2=\"height - pad.b\" />\n <g v-if=\"hover >= 0\">\n <circle v-for=\"s in paths\" v-show=\"s.pts[hover] && s.pts[hover][1] != null\" :key=\"'p' + s.name\" :cx=\"sx(hover)\" :cy=\"s.pts[hover] ? s.pts[hover][1] ?? 0 : 0\" r=\"4.5\" :fill=\"s.color\" class=\"sq-chart__dot\" />\n </g>\n <g v-if=\"points && hover < 0\">\n <g v-for=\"s in paths\" :key=\"'pp' + s.name\">\n <circle v-for=\"(p, i) in s.pts\" v-show=\"p[1] != null\" :key=\"i\" :cx=\"p[0]\" :cy=\"p[1] ?? 0\" r=\"4\" :fill=\"s.color\" class=\"sq-chart__dot\" />\n </g>\n </g>\n </svg>\n <div v-if=\"hover >= 0\" class=\"sq-chart__tooltip sq-squircle\" :style=\"tipStyle\">\n <div class=\"sq-chart__tooltip-title\">{{ labels[hover] }}</div>\n <div v-for=\"(s, i) in series\" :key=\"s.name\" class=\"sq-chart__tooltip-row\"><span class=\"sq-chart__swatch\" :style=\"{ background: colorOf(i) }\"></span>{{ s.name }}<b>{{ fmtCell(s.data[hover]) }}</b></div>\n </div>\n </div>\n </ChartFrame>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, ref, type PropType } from 'vue'\nimport ChartFrame from './ChartFrame.vue'\nimport { compact, linearScale, seriesColor, smoothPath, useSize, yDomain, type Series } from '../utils'\n\n/** Line / area chart with crosshair tooltip. One y-axis only (by design). */\nexport default defineComponent({\n name: 'SqLineChart',\n components: { ChartFrame },\n props: {\n labels: { type: Array as PropType<string[]>, default: () => [] },\n series: { type: Array as PropType<Series[]>, default: () => [] },\n title: { type: String, default: undefined },\n subtitle: { type: String, default: undefined },\n height: { type: Number, default: 260 },\n area: Boolean,\n smooth: { type: Boolean, default: true },\n points: Boolean,\n /** Start y at zero (recommended for areas). */\n zero: { type: Boolean, default: true },\n flat: Boolean,\n format: { type: Function as PropType<(v: number) => string>, default: undefined },\n },\n setup(props) {\n const box = ref<HTMLElement | null>(null)\n const { width: w } = useSize(box, props.height)\n const pad = { t: 12, r: 16, b: 26, l: 44 }\n const hover = ref(-1)\n const y = computed(() => yDomain(props.series.flatMap((s) => s.data.filter((v): v is number => v != null)), props.zero || props.area))\n const sy = computed(() => linearScale(y.value.min, y.value.max, props.height - pad.b, pad.t))\n const sx = computed(() => {\n const n = Math.max(1, props.labels.length - 1)\n return (i: number) => pad.l + ((w.value - pad.l - pad.r) * i) / n\n })\n const colorOf = (i: number) => seriesColor(i, props.series[i]?.color)\n const fmt = (v: number) => (props.format ? props.format(v) : compact(v))\n const fmtCell = (v: number | null | undefined) => (v == null ? '–' : fmt(v))\n const paths = computed(() =>\n props.series.map((s, i) => {\n const pts = s.data.map((v, k) => [sx.value(k), v == null ? null : sy.value(v)] as [number, number | null])\n const valid = pts.filter((p): p is [number, number] => p[1] != null)\n const line = props.smooth ? smoothPath(valid) : valid.map((p, k) => `${k ? 'L' : 'M'}${p[0]},${p[1]}`).join(' ')\n const base = sy.value(Math.max(y.value.min, 0))\n const area = valid.length ? `${line} L${valid[valid.length - 1][0]},${base} L${valid[0][0]},${base} Z` : ''\n return { name: s.name, color: colorOf(i), pts, line, area }\n }),\n )\n const showLabel = (i: number) => {\n const n = props.labels.length\n const every = Math.ceil(n / Math.max(2, Math.floor((w.value - pad.l) / 64)))\n return i % every === 0 || i === n - 1\n }\n const onMove = (e: PointerEvent) => {\n const r = box.value!.getBoundingClientRect()\n const n = props.labels.length\n if (!n) return\n const i = Math.round(((e.clientX - r.left - pad.l) / (w.value - pad.l - pad.r)) * (n - 1))\n hover.value = Math.max(0, Math.min(n - 1, i))\n }\n const tipStyle = computed(() => {\n const x = sx.value(hover.value)\n return x > w.value / 2 ? { right: `${w.value - x + 12}px`, top: '8px' } : { left: `${x + 12}px`, top: '8px' }\n })\n const legend = computed(() => props.series.map((s, i) => ({ name: s.name, color: colorOf(i) })))\n const table = computed(() => ({ head: ['', ...props.series.map((s) => s.name)], rows: props.labels.map((l, k) => [l, ...props.series.map((s) => s.data[k] ?? '')]) }))\n return { fmtCell, box, w, pad, hover, y, sy, sx, paths, colorOf, fmt, showLabel, onMove, tipStyle, legend, table }\n },\n})\n</script>\n","<template>\n <ChartFrame :title=\"title\" :subtitle=\"subtitle\" :flat=\"flat\" :legend=\"legend\" :table=\"table\">\n <div ref=\"box\" class=\"sq-chart__plot\" :style=\"{ height: height + 'px' }\" @pointerleave=\"hover = null\">\n <svg :width=\"w\" :height=\"height\" role=\"img\" :aria-label=\"title || 'Bar chart'\">\n <g class=\"sq-chart__grid\">\n <line v-for=\"t in y.ticks\" :key=\"'g' + t\" v-bind=\"gridLine(t)\" />\n </g>\n <g class=\"sq-chart__axis\">\n <text v-for=\"t in y.ticks\" :key=\"'y' + t\" v-bind=\"valueTick(t)\">{{ fmt(t) }}</text>\n <text v-for=\"(l, i) in labels\" :key=\"'x' + i\" v-bind=\"catTick(i)\">{{ l }}</text>\n </g>\n <path\n v-for=\"b in bars\"\n :key=\"b.key\"\n :d=\"b.d\"\n :fill=\"b.color\"\n class=\"sq-chart__bar\"\n :class=\"{ 'sq-chart__bar--dim': hover && hover.cat !== b.cat }\"\n @pointerenter=\"hover = { cat: b.cat, x: b.cx, y: b.cy }\"\n />\n </svg>\n <div v-if=\"hover\" class=\"sq-chart__tooltip sq-squircle\" :style=\"tipStyle\">\n <div class=\"sq-chart__tooltip-title\">{{ labels[hover.cat] }}</div>\n <div v-for=\"(s, i) in series\" :key=\"s.name\" class=\"sq-chart__tooltip-row\"><span class=\"sq-chart__swatch\" :style=\"{ background: colorOf(i) }\"></span>{{ s.name }}<b>{{ fmtCell(s.data[hover.cat]) }}</b></div>\n </div>\n </div>\n </ChartFrame>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, ref, type PropType } from 'vue'\nimport ChartFrame from './ChartFrame.vue'\nimport { barPath, compact, linearScale, seriesColor, useSize, yDomain, type Series } from '../utils'\n\n/** Grouped or stacked bars with squircle data-ends, vertical or horizontal. */\nexport default defineComponent({\n name: 'SqBarChart',\n components: { ChartFrame },\n props: {\n labels: { type: Array as PropType<string[]>, default: () => [] },\n series: { type: Array as PropType<Series[]>, default: () => [] },\n title: { type: String, default: undefined },\n subtitle: { type: String, default: undefined },\n height: { type: Number, default: 260 },\n stacked: Boolean,\n horizontal: Boolean,\n radius: { type: Number, default: 6 },\n flat: Boolean,\n format: { type: Function as PropType<(v: number) => string>, default: undefined },\n },\n setup(props) {\n const box = ref<HTMLElement | null>(null)\n const { width: w } = useSize(box, props.height)\n const pad = computed(() => (props.horizontal ? { t: 8, r: 16, b: 24, l: 84 } : { t: 12, r: 16, b: 26, l: 44 }))\n const hover = ref<{ cat: number; x: number; y: number } | null>(null)\n const colorOf = (i: number) => seriesColor(i, props.series[i]?.color)\n const fmt = (v: number) => (props.format ? props.format(v) : compact(v))\n const fmtCell = (v: number | null | undefined) => (v == null ? '–' : fmt(v))\n const y = computed(() => {\n const vals = props.stacked\n ? props.labels.flatMap((_, k) => {\n let pos = 0\n let neg = 0\n for (const s of props.series) { const v = s.data[k] ?? 0; v >= 0 ? (pos += v) : (neg += v) }\n return [pos, neg]\n })\n : props.series.flatMap((s) => s.data.filter((v): v is number => v != null))\n return yDomain(vals, true)\n })\n // value axis → pixel along the value direction\n const sv = computed(() => (props.horizontal ? linearScale(y.value.min, y.value.max, pad.value.l, w.value - pad.value.r) : linearScale(y.value.min, y.value.max, props.height - pad.value.b, pad.value.t)))\n const band = computed(() => {\n const n = Math.max(1, props.labels.length)\n const len = props.horizontal ? props.height - pad.value.t - pad.value.b : w.value - pad.value.l - pad.value.r\n const step = len / n\n return { step, inner: step * 0.72, start: props.horizontal ? pad.value.t : pad.value.l }\n })\n const bars = computed(() => {\n const out: { key: string; d: string; color: string; cat: number; cx: number; cy: number }[] = []\n const gap = 2\n const zero = sv.value(0)\n props.labels.forEach((_, k) => {\n const c0 = band.value.start + band.value.step * k + (band.value.step - band.value.inner) / 2\n let pos = 0\n let neg = 0\n const n = props.series.length\n props.series.forEach((s, i) => {\n const v = s.data[k]\n if (v == null) return\n let a: number\n let b: number\n let c: number\n let thick: number\n if (props.stacked) {\n const from = v >= 0 ? pos : neg\n const to = from + v\n v >= 0 ? (pos = to) : (neg = to)\n a = sv.value(from)\n b = sv.value(to)\n c = c0\n thick = band.value.inner\n } else {\n a = zero\n b = sv.value(v)\n thick = Math.max(1, (band.value.inner - gap * (n - 1)) / n)\n c = c0 + i * (thick + gap)\n }\n const lo = Math.min(a, b)\n const len = Math.abs(b - a) - (props.stacked ? gap : 0)\n const top = props.stacked ? props.series.slice(i + 1).every((x) => (x.data[k] ?? 0) === 0 || Math.sign(x.data[k] ?? 0) !== Math.sign(v)) : true\n const r = top ? props.radius : 0\n const d = props.horizontal\n ? barPath(v >= 0 ? lo : lo + (props.stacked ? gap : 0), c, Math.max(0, len), thick, r, true, v < 0)\n : barPath(c, v >= 0 ? lo + (props.stacked ? gap : 0) : lo, thick, Math.max(0, len), r, false, v < 0)\n out.push({ key: `${k}-${i}`, d, color: colorOf(i), cat: k, cx: props.horizontal ? Math.max(a, b) : c + thick / 2, cy: props.horizontal ? c : Math.min(a, b) })\n })\n })\n return out\n })\n const gridLine = (t: number) => (props.horizontal ? { x1: sv.value(t), x2: sv.value(t), y1: pad.value.t, y2: props.height - pad.value.b } : { x1: pad.value.l, x2: w.value - pad.value.r, y1: sv.value(t), y2: sv.value(t) })\n const valueTick = (t: number) => (props.horizontal ? { x: sv.value(t), y: props.height - 6, 'text-anchor': 'middle' } : { x: pad.value.l - 8, y: sv.value(t), 'text-anchor': 'end', 'dominant-baseline': 'middle' })\n const catTick = (i: number) => {\n const mid = band.value.start + band.value.step * (i + 0.5)\n return props.horizontal ? { x: pad.value.l - 8, y: mid, 'text-anchor': 'end', 'dominant-baseline': 'middle' } : { x: mid, y: props.height - 6, 'text-anchor': 'middle' }\n }\n const tipStyle = computed(() => {\n const h = hover.value\n if (!h) return {}\n return h.x > w.value / 2 ? { right: `${w.value - h.x + 10}px`, top: `${Math.max(4, h.y - 10)}px` } : { left: `${h.x + 10}px`, top: `${Math.max(4, h.y - 10)}px` }\n })\n const legend = computed(() => props.series.map((s, i) => ({ name: s.name, color: colorOf(i) })))\n const table = computed(() => ({ head: ['', ...props.series.map((s) => s.name)], rows: props.labels.map((l, k) => [l, ...props.series.map((s) => s.data[k] ?? '')]) }))\n return { fmtCell, box, w, hover, y, bars, gridLine, valueTick, catTick, colorOf, fmt, tipStyle, legend, table }\n },\n})\n</script>\n","<template>\n <ChartFrame :title=\"title\" :subtitle=\"subtitle\" :flat=\"flat\" :legend=\"legend\" :table=\"table\">\n <div class=\"sq-chart__donut\" :style=\"{ height: size + 'px' }\">\n <svg :width=\"size\" :height=\"size\" :viewBox=\"`0 0 ${size} ${size}`\" role=\"img\" :aria-label=\"title || 'Donut chart'\" @pointerleave=\"hover = -1\">\n <path\n v-for=\"(a, i) in arcs\"\n :key=\"a.label\"\n :d=\"a.d\"\n :fill=\"a.color\"\n class=\"sq-chart__arc\"\n :class=\"{ 'sq-chart__arc--dim': hover >= 0 && hover !== i }\"\n @pointerenter=\"hover = i\"\n />\n </svg>\n <div class=\"sq-chart__donut-center\">\n <slot name=\"center\" :hover=\"hover >= 0 ? data[hover] : null\" :total=\"total\">\n <div class=\"sq-chart__donut-value\">{{ hover >= 0 ? fmt(data[hover].value) : fmt(total) }}</div>\n <div class=\"sq-chart__donut-label\">{{ hover >= 0 ? data[hover].label : totalLabel }}</div>\n </slot>\n </div>\n </div>\n </ChartFrame>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, ref, type PropType } from 'vue'\nimport ChartFrame from './ChartFrame.vue'\nimport { compact, seriesColor, type DonutDatum } from '../utils'\n\n/** Pie / donut with a 2px surface gap between segments; legend always shown for 2+ segments. */\nexport default defineComponent({\n name: 'SqDonutChart',\n components: { ChartFrame },\n props: {\n data: { type: Array as PropType<DonutDatum[]>, default: () => [] },\n title: { type: String, default: undefined },\n subtitle: { type: String, default: undefined },\n size: { type: Number, default: 220 },\n /** Ring thickness as a fraction of the radius; 1 = pie. */\n thickness: { type: Number, default: 0.34 },\n totalLabel: { type: String, default: 'Total' },\n flat: Boolean,\n format: { type: Function as PropType<(v: number) => string>, default: undefined },\n },\n setup(props) {\n const hover = ref(-1)\n const total = computed(() => props.data.reduce((s, d) => s + Math.max(0, d.value), 0))\n const fmt = (v: number) => (props.format ? props.format(v) : compact(v))\n const arcs = computed(() => {\n const c = props.size / 2\n const R = c - 4\n const r = R * (1 - props.thickness)\n const gap = props.data.length > 1 ? 2 / R : 0\n let a0 = -Math.PI / 2\n return props.data.map((d, i) => {\n const sweep = total.value ? (Math.max(0, d.value) / total.value) * Math.PI * 2 : 0\n const s = a0 + gap / 2\n const e = a0 + sweep - gap / 2\n a0 += sweep\n const large = e - s > Math.PI ? 1 : 0\n const p = (rad: number, ang: number) => `${c + rad * Math.cos(ang)},${c + rad * Math.sin(ang)}`\n const dPath = e <= s ? '' : r > 0\n ? `M${p(R, s)} A${R},${R} 0 ${large} 1 ${p(R, e)} L${p(r, e)} A${r},${r} 0 ${large} 0 ${p(r, s)} Z`\n : `M${c},${c} L${p(R, s)} A${R},${R} 0 ${large} 1 ${p(R, e)} Z`\n return { label: d.label, color: seriesColor(i, d.color), d: dPath }\n })\n })\n const legend = computed(() => props.data.map((d, i) => ({ name: `${d.label} · ${total.value ? Math.round((d.value / total.value) * 100) : 0}%`, color: seriesColor(i, d.color) })))\n const table = computed(() => ({ head: ['Label', 'Value'], rows: props.data.map((d) => [d.label, d.value]) }))\n return { hover, total, fmt, arcs, legend, table }\n },\n})\n</script>\n","<template>\n <svg ref=\"el\" class=\"sq-sparkline\" :width=\"width\" :height=\"height\" :viewBox=\"`0 0 ${width} ${height}`\" role=\"img\" :aria-label=\"label\">\n <path v-if=\"fill\" :d=\"areaD\" :fill=\"stroke\" class=\"sq-sparkline__area\" />\n <path :d=\"lineD\" :stroke=\"stroke\" class=\"sq-sparkline__line\" />\n <circle v-if=\"pts.length\" :cx=\"pts[pts.length - 1][0]\" :cy=\"pts[pts.length - 1][1]\" r=\"2.5\" :fill=\"stroke\" />\n </svg>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, type PropType } from 'vue'\nimport { colorValue } from '@squirkle-ui/ui'\nimport { smoothPath } from '../utils'\n\n/** Inline trend line for stat tiles and table cells (no axes, no tooltip). */\nexport default defineComponent({\n name: 'SqSparkline',\n props: {\n data: { type: Array as PropType<number[]>, default: () => [] },\n width: { type: Number, default: 120 },\n height: { type: Number, default: 32 },\n color: { type: String, default: 'primary' },\n fill: Boolean,\n label: { type: String, default: 'Trend' },\n },\n setup(props) {\n const pts = computed<[number, number][]>(() => {\n const d = props.data\n if (!d.length) return []\n const min = Math.min(...d)\n const max = Math.max(...d)\n const span = max - min || 1\n return d.map((v, i) => [3 + ((props.width - 6) * i) / Math.max(1, d.length - 1), 3 + (props.height - 6) * (1 - (v - min) / span)])\n })\n const lineD = computed(() => smoothPath(pts.value))\n const areaD = computed(() => (pts.value.length ? `${lineD.value} L${pts.value[pts.value.length - 1][0]},${props.height} L${pts.value[0][0]},${props.height} Z` : ''))\n return { pts, lineD, areaD, stroke: computed(() => colorValue(props.color)) }\n },\n})\n</script>\n","import './styles.css'\nimport SqLineChart from './components/SqLineChart.vue'\nimport SqBarChart from './components/SqBarChart.vue'\nimport SqDonutChart from './components/SqDonutChart.vue'\nimport SqSparkline from './components/SqSparkline.vue'\n\nexport { SqLineChart, SqBarChart, SqDonutChart, SqSparkline }\nexport { seriesColor, smoothPath, barPath, type Series, type DonutDatum } from './utils'\nexport const componentNames = ['SqLineChart', 'SqBarChart', 'SqDonutChart', 'SqSparkline'] as const\n"],"names":[],"mappings":"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"}