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