UNPKG

vue-data-ui

Version:

A user-empowering data visualization Vue 3 components library for eloquent data storytelling

693 lines (692 loc) 22.9 kB
import { t as e } from "./rolldown-runtime-Dy4uBu1J.js"; import { Bt as t, Jt as n, Kt as r, Pt as i, S as a, Vt as o, X as s, i as c, jt as ee, pt as te, q as ne, t as re, tt as ie, w as ae, xt as oe } from "./lib-Bttd6u5E.js"; import { n as se, t as ce } from "./useHints-Dq_w2E8B.js"; import { t as le } from "./useConfig-D3scuR88.js"; import { n as ue, t as de } from "./BaseScanner-DZvpgOjM.js"; import { t as l } from "./useNestedProp-vPNvh7rV.js"; import { t as fe } from "./useThemeCheck-C43Tcqmk.js"; import { t as pe } from "./_plugin-vue_export-helper-B3ysoDQm.js"; import { t as me } from "./DefGrad-DVBqDjhO.js"; import { t as he } from "./BaseLegendToggle-DZVucLnv.js"; import { t as ge } from "./A11yDataTable-DdRsVULz.js"; import { t as _e } from "./useChartAccessibility-DYqac8yF.js"; import { t as ve } from "./usePrefersMotion-BC-CsqR1.js"; import { t as ye } from "./vue_ui_sparkstackbar-BOjuQnZd.js"; import { Fragment as u, computed as d, createBlock as f, createCommentVNode as p, createElementBlock as m, createElementVNode as h, createVNode as g, defineAsyncComponent as be, guardReactiveProps as _, normalizeClass as v, normalizeProps as y, normalizeStyle as b, onMounted as xe, openBlock as x, ref as S, renderList as C, renderSlot as w, toDisplayString as T, toRefs as Se, unref as E, useSlots as Ce, watch as we, withCtx as D } from "vue"; //#region src/components/vue-ui-sparkstackbar.vue var Te = /* @__PURE__ */ e({ default: () => He }), Ee = ["id"], De = { style: { position: "relative" } }, Oe = [ "xmlns", "viewBox", "aria-describedby" ], ke = { id: "stackPill", clipPathUnits: "objectBoundingBox" }, Ae = ["fill"], je = { key: 0, "clip-path": "url(#stackPill)" }, Me = [ "x", "width", "height", "fill" ], Ne = [ "x", "width", "height", "fill", "stroke" ], Pe = [ "x", "width", "height", "onClick", "onMouseenter", "onMouseleave" ], Fe = [ "width", "height", "rx" ], Ie = { key: 0, style: { position: "absolute", top: "100%", left: "0", width: "100%" }, "data-dom-to-png-ignore": "", "aria-hidden": "true" }, Le = [ "aria-pressed", "aria-label", "onClick", "onFocus", "onKeydown" ], Re = { style: { display: "flex", "flex-direction": "row", "align-items": "center", gap: "4px", "justify-content": "center" } }, ze = ["height", "width"], Be = ["fill"], Ve = { key: 3, ref: "source", dir: "auto" }, He = /*#__PURE__*/ pe({ __name: "vue-ui-sparkstackbar", props: { config: { type: Object, default() { return {}; } }, dataset: { type: Array, default() { return []; } } }, emits: ["selectDatapoint", "selectLegend"], setup(e, { expose: pe, emit: Te }) { let He = be(() => import("./PackageVersion-D6d8SCp9.js").then((e) => e.t)), Ue = be(() => import("./Tooltip-DhjyfHwz.js")), { vue_ui_sparkstackbar: We } = le(), { isThemeValid: Ge, warnInvalidTheme: Ke } = fe(), qe = ve(), O = e, Je = Ce(); xe(() => { Je["chart-background"] && console.warn("VueUiSparkStackbar does not support the #chart-background slot."); }); let Ye = S(null), k = S(ne()), A = S(!1), j = S(""), M = S(null), N = S(!1), P = S(null), Xe = S({ x: 0, y: 0 }), F = S("pointer"), I = S(!1), L = S(null), Ze = S([]), R = S(H()); se({ config: () => R.value, dataset: () => O.dataset, component: "VueUiSparkStackbar", rules: [ce.emptyArray, { test: (e) => e.length > 6, message: [ "👀 The number of series is > 6. Consider:", "", "▶️ Grouping small values dynamically into a single \"Other\" series.", "", "▶️ Using VueUiHorizontalBar instead to make the dataset breakdown easier to read." ] }] }); let Qe = d(() => R.value.useCursorPointer), $e = d(() => n({ defaultConfig: { style: { backgroundColor: "#99999930", animation: { show: !1 }, bar: { gradient: { inderlayerColor: "#6A6A6A" } }, title: { backgroundColor: "transparent" } } }, userConfig: R.value.skeletonConfig ?? {} })), { loading: z, FINAL_DATASET: B } = ue({ ...Se(O), FINAL_CONFIG: R, prepareConfig: H, skeletonDataset: O.config?.skeletonDataset ?? [ { name: "_", value: 8, color: "#808080" }, { name: "_", value: 5, color: "#ADADAD" }, { name: "_", value: 3, color: "#DBDBDB" } ], skeletonConfig: n({ defaultConfig: R.value, userConfig: $e.value }) }), { svgRef: V } = _e({ config: R.value.style.title }); function H() { let e = l({ userConfig: O.config, defaultConfig: We }), t = e.theme; if (!t) return e; if (!Ge.value(e)) return Ke(e), e; let n = l({ userConfig: ye[t] || O.config, defaultConfig: e }), a = l({ userConfig: O.config, defaultConfig: n }); return { ...a, customPalette: a.customPalette.length ? a.customPalette : r[t] || i }; } we(() => O.config, (e) => { R.value = H(), nt(); }, { deep: !0 }), we(() => B.value, (e) => { W.value = B.value.map((e, t) => ({ ...e, color: e.color ? a(e.color) : U.value[t] || i[t] || i[t % i.length] })), et(); }, { deep: !0 }); let U = d(() => ae(R.value.customPalette)), W = S(B.value.map((e, t) => ({ ...e, value: R.value.style.animation.show ? 0 : e.value || 0, color: e.color ? a(e.color) : U.value[t] || i[t] || i[t % i.length] }))), G = S(!0); function et() { if (!R.value.style.animation.show || qe.value) { G.value = !1; return; } let e = R.value.style.animation.animationFrames, t = B.value.map((e) => e.value || 0), n = t.map((t) => t / e), r = t.reduce((e, t) => e + t, 0), o = 0; G.value = !0, W.value = B.value.map((e, t) => ({ ...e, value: 0, color: e.color ? a(e.color) : U.value[t] || i[t] || i[t % i.length] })); function s() { o += r / e, o < r ? (W.value = W.value.map((e, r) => ({ ...e, value: Math.min(e.value + n[r], t[r]), color: e.color ? a(e.color) : U.value[r] || i[r] || i[r % i.length] })), requestAnimationFrame(s)) : (G.value = !1, W.value = B.value.map((e, n) => ({ ...e, value: t[n], color: e.color ? a(e.color) : U.value[n] || i[n] || i[n % i.length], id: ne() }))); } s(); } xe(() => { nt(); }); let tt = d(() => R.value.debug); function nt() { ee(O.dataset) ? ie({ componentName: "VueUiSparkStackbar", type: "dataset", debug: tt.value }) : O.dataset.forEach((e, t) => { te({ datasetObject: e, requiredAttributes: ["name", "value"] }).forEach((e) => { ie({ componentName: "VueUiSparkStackbar", type: "datasetSerieAttribute", property: e, index: t, debug: tt.value }); }); }), et(); } let K = S({ width: 500, height: 16 }), q = S([]), rt = d(() => B.value.map((e) => e.value || 0).filter((e, t) => !q.value.includes(t)).reduce((e, t) => e + t, 0)), J = d(() => W.value.map((e, t) => { let n = e.value || 0, r = n / rt.value, o = isNaN(r) ? 0 : r, c = o * K.value.width; return { ...e, color: a(B.value[t]?.color ? B.value[t]?.color : U.value[t] || i[t] || i[t % i.length]), value: n, proportion: o, width: c, seriesIndex: t, proportionLabel: s({ v: o * 100, s: "%", r: R.value.style.legend.percentage.rounding }) }; })), Y = d(() => J.value.filter((e, t) => !q.value.includes(t))); function it() { q.value.length ? q.value = [] : J.value.forEach((e, t) => { q.value.push(t); }), ct("selectLegend", Y.value); } function X(e) { q.value.includes(e) ? q.value = q.value.filter((t) => t !== e) : q.value.length < W.value.length - 1 && q.value.push(e), ct("selectLegend", Y.value); } function at(e) { return J.value.length ? J.value.find((t) => t.name === e) || (R.value.debug && console.warn(`VueUiSparkStackbar - Series name not found "${e}"`), null) : (R.value.debug && console.warn("VueUiSparkStackbar - There are no series to show."), null); } function ot(e) { let t = at(e); t !== null && q.value.includes(t.id) && X(t.seriesIndex); } function st(e) { let t = at(e); t !== null && (q.value.includes(t.id) || X(t.seriesIndex)); } let Z = d(() => { let e = 0, t = []; for (let n = 0; n < Y.value.length; n += 1) t.push({ ...Y.value[n], start: e }), e += Y.value[n].width; return t; }), ct = Te; function Q(e, t, n = !1) { ct("selectDatapoint", { datapoint: e, index: t }), R.value.events.datapointClick && !n && R.value.events.datapointClick({ datapoint: e, seriesIndex: e.seriesIndex }); } function lt({ datapoint: e, seriesIndex: t }) { A.value = !1, L.value = null, P.value = null, F.value = "pointer", R.value.events.datapointLeave && R.value.events.datapointLeave({ datapoint: e, seriesIndex: e.seriesIndex }); } function ut({ datapoint: e, seriesIndex: t, triggerMode: n = "pointer" }) { if (N.value = !1, R.value.events.datapointEnter && R.value.events.datapointEnter({ datapoint: e, seriesIndex: e.seriesIndex }), !R.value.style.tooltip.show) return; F.value = n, M.value = { datapoint: e, seriesIndex: t, config: R.value, series: J.value }, A.value = !0, L.value = t; let r = R.value.style.tooltip.customFormat; if (oe(r)) try { let t = r({ seriesIndex: e.seriesIndex, datapoint: e, series: J.value, config: R.value }); typeof t == "string" && (j.value = t, N.value = !0); } catch { console.warn("Custom format cannot be applied."), N.value = !1; } if (!N.value) { let n = ""; n += `<div style="width:100%;text-align:center;border-bottom:1px solid ${R.value.style.tooltip.borderColor};padding-bottom:6px;margin-bottom:3px;">${e.name}</div>`, n += `<div style="display:flex;flex-direction:row;gap:6px;align-items:center;"><svg viewBox="0 0 12 12" height="14" width="14"><circle cx="6" cy="6" r="6" stroke="none" fill="${e.color}"/></svg>`, n += `<b>${e.proportionLabel}</b>`, n += `<span>(${c(R.value.style.legend.value.formatter, e.value, s({ p: R.value.style.legend.value.prefix, v: e.value, s: R.value.style.legend.value.suffix, r: R.value.style.legend.value.rounding }), { datapoint: e, seriesIndex: t })})</span>`, j.value = `<div>${n}</div>`; } } function $(e) { let t = Ze.value[e]; t && typeof t.focus == "function" && t.focus(); } function dt(e) { if (!Number.isFinite(e) || !V.value) return; let t = Z.value[e]; if (!t) return; let n = V.value.getBoundingClientRect(), r = t.start + t.width / 2, i = K.value.height / 2; Xe.value = { x: n.left + r / K.value.width * n.width, y: n.top + i / K.value.height * n.height }; } function ft() { P.value = null, I.value = !0; } function pt() { P.value = null, F.value = "pointer", A.value = !1, L.value = null, I.value = !1; } function mt(e) { if (!V.value || document.activeElement !== V.value || !Z.value.length) return; let t = e.key === "ArrowLeft", n = e.key === "ArrowRight", r = e.key === "Enter" || e.key === " ", i = e.key === "Escape", a = e.key === "Home", o = e.key === "End"; if (!t && !n && !r && !i && !a && !o) return; if (e.preventDefault(), e.stopPropagation(), i) { P.value = null, F.value = "pointer", A.value = !1, L.value = null; return; } if (r) { if (P.value === null) return; let e = Z.value[P.value]; if (!e) return; Q(e, e.seriesIndex); return; } let s = P.value; a ? s = 0 : o ? s = Z.value.length - 1 : s === null || s < 0 || s >= Z.value.length ? s = n ? 0 : Z.value.length - 1 : n ? (s += 1, s >= Z.value.length && (s = 0)) : t && (--s, s < 0 && (s = Z.value.length - 1)); let c = Z.value[s]; c && (P.value = s, dt(s), ut({ datapoint: c, seriesIndex: c.seriesIndex, triggerMode: "keyboard" })); } function ht(e) { A.value = !1, P.value = null, F.value = "pointer", L.value = e.seriesIndex; } function gt() { P.value = null, F.value = "pointer", A.value = !1, L.value = null; } function _t(e, t, n) { let r = e.key === "Enter" || e.key === " ", i = e.key === "ArrowLeft" || e.key === "ArrowUp", a = e.key === "ArrowRight" || e.key === "ArrowDown", o = e.key === "Home", s = e.key === "End", c = e.key === "Escape"; if (!(!r && !i && !a && !o && !s && !c)) { if (e.preventDefault(), e.stopPropagation(), c) { gt(); return; } if (r) { X(n), Q(t, n, !0); return; } if (o) { $(0); return; } if (s) { $(J.value.length - 1); return; } if (i) { $(n <= 0 ? J.value.length - 1 : n - 1); return; } a && $(n >= J.value.length - 1 ? 0 : n + 1); } } let vt = d(() => ({ headers: [ R.value.a11y.translations.series, R.value.a11y.translations.percentage, R.value.a11y.translations.value ], rows: J.value.map((e, t) => [ e.name, q.value.includes(t) ? " - " : e.proportionLabel, c(R.value.style.legend.value.formatter, e.value, s({ p: R.value.style.legend.value.prefix, v: e.value, s: R.value.style.legend.value.suffix, r: R.value.style.legend.value.rounding }), { datapoint: e, seriesIndex: t }) ]) })); return pe({ hideSeries: st, showSeries: ot }), (e, n) => (x(), m("div", { class: "vue-data-ui-component vue-ui-spark-stackbar", ref_key: "sparkstackbarChart", ref: Ye, style: b(`width:100%; background:${R.value.style.backgroundColor}`) }, [ h("div", { id: `chart-instructions-${k.value}`, class: "sr-only" }, [h("p", null, T(R.value.a11y.translations.keyboardNavigation), 1)], 8, Ee), vt.value?.rows?.length ? (x(), f(ge, { key: 0, uid: k.value, head: vt.value.headers, body: vt.value.rows, notice: R.value.a11y.translations.tableAvailable, caption: R.value.a11y.translations.tableCaption }, null, 8, [ "uid", "head", "body", "notice", "caption" ])) : p("", !0), R.value.style.title.text ? (x(), m("div", { key: 1, style: b(`width:calc(100% - 12px);background:transparent;margin:0 auto;margin:${R.value.style.title.margin};padding: 0 6px;text-align:${R.value.style.title.textAlign}`) }, [h("div", { class: "atom-title", style: b(`font-size:${R.value.style.title.fontSize}px;color:${R.value.style.title.color};font-weight:${R.value.style.title.bold ? "bold" : "normal"}`) }, T(R.value.style.title.text), 5), R.value.style.title.subtitle.text ? (x(), m("div", { key: 0, class: "atom-subtitle", style: b(`font-size:${R.value.style.title.subtitle.fontSize}px;color:${R.value.style.title.subtitle.color};font-weight:${R.value.style.title.subtitle.bold ? "bold" : "normal"}`) }, T(R.value.style.title.subtitle.text), 5)) : p("", !0)], 4)) : p("", !0), h("div", De, [(x(), m("svg", { ref_key: "svgRef", ref: V, xmlns: E(re), width: "100%", viewBox: `0 0 ${K.value.width} ${K.value.height}`, "aria-describedby": `chart-instructions-${k.value}`, tabindex: "0", onFocus: ft, onBlur: pt, onKeydown: mt }, [ g(E(He)), h("defs", null, [(x(!0), m(u, null, C(Z.value, (e, n) => (x(), f(me, { t: "linear", id: `stack_gradient_${n}_${k.value}`, key: `stack_gradient_${n}`, gradientTransform: "rotate(90)", stops: [ [ "0%", e.color, 1 ], [ "50%", E(t)(E(o)(e.color, .05), 100 - R.value.style.bar.gradient.intensity), 1 ], [ "100%", e.color, 1 ] ] }, null, 8, ["id", "stops"]))), 128)), h("clipPath", ke, [h("rect", { x: "0.005", y: "-2", width: "0.99", height: "5", rx: "3", ry: "3", fill: R.value.style.backgroundColor }, null, 8, Ae)])]), rt.value > 0 ? (x(), m("g", je, [ (x(!0), m(u, null, C(Z.value, (e, t) => (x(), m("rect", { key: `stack_underlayer_${t}`, x: e.start, y: 0, width: e.width, height: K.value.height, fill: R.value.style.bar.gradient.underlayerColor, class: v({ animated: !G.value && !E(z) }), style: b({ opacity: L.value !== null && R.value.style.tooltip.show ? L.value === t ? 1 : .5 : 1 }) }, null, 14, Me))), 128)), (x(!0), m(u, null, C(Z.value, (e, t) => (x(), m("rect", { key: `stack_${t}`, x: e.start, y: 0, width: e.width, height: K.value.height, fill: R.value.style.bar.gradient.show ? `url(#stack_gradient_${t}_${k.value})` : e.color, stroke: R.value.style.backgroundColor, "stroke-linecap": "round", class: v({ animated: !G.value && !E(z) }), style: b({ opacity: L.value !== null && R.value.style.tooltip.show ? L.value === t ? 1 : .5 : 1 }) }, null, 14, Ne))), 128)), (x(!0), m(u, null, C(Z.value, (e, t) => (x(), m("rect", { key: `stack_trap_${t}`, x: e.start, y: 0, width: e.width, height: K.value.height, fill: "transparent", stroke: "none", class: v({ animated: !G.value && !E(z) }), onClick: () => Q(e, t), onMouseenter: () => ut({ datapoint: e, seriesIndex: t }), onMouseleave: (n) => lt({ datapoint: e, seriesIndex: t }) }, null, 42, Pe))), 128)) ])) : (x(), m("rect", { key: 1, x: 2, y: 1, width: K.value.width - 4, height: K.value.height - 2, stroke: "#CCCCCC", "stroke-width": "2", fill: "transparent", rx: (K.value.height - 4) / 2 }, null, 8, Fe)) ], 40, Oe)), e.$slots.hint ? (x(), m("div", Ie, [w(e.$slots, "hint", y(_({ hint: R.value.a11y.translations.keyboardNavigation, isVisible: I.value })), void 0, !0)])) : p("", !0)]), R.value.style.legend.show ? (x(), m("div", { key: 2, style: b(`background:transparent;margin:0 auto;margin:${R.value.style.legend.margin};justify-content:${R.value.style.legend.textAlign === "left" ? "flex-start" : R.value.style.legend.textAlign === "right" ? "flex-end" : "center"}`), class: "vue-ui-sparkstackbar-legend", "aria-label": "legend", role: "toolbar" }, [R.value.style.legend.selectAllToggle.show && J.value.length > 2 && !E(z) ? (x(), f(he, { key: 0, backgroundColor: R.value.style.legend.selectAllToggle.backgroundColor, color: R.value.style.legend.selectAllToggle.color, fontSize: R.value.style.legend.fontSize, checked: q.value.length > 0, isCursorPointer: Qe.value, onToggle: it }, null, 8, [ "backgroundColor", "color", "fontSize", "checked", "isCursorPointer" ])) : p("", !0), (x(!0), m(u, null, C(J.value, (e, n) => (x(), m("div", { role: "button", tabindex: "0", "aria-pressed": q.value.includes(n), "aria-label": `${e.name}, ${q.value.includes(n) ? "hidden" : "visible"}, ${e.proportionLabel}`, style: b(`font-size:${R.value.style.legend.fontSize}px;cursor:${Qe.value ? "pointer" : "default"}`), class: v({ "vue-ui-sparkstackbar-legend-item": !0, "vue-ui-sparkstackbar-legend-item-unselected": q.value.includes(n) }), onClick: (t) => { X(n), Q(e, n, !0); }, onFocus: (t) => ht(e), onBlur: gt, onKeydown: (t) => _t(t, e, n) }, [h("div", Re, [(x(), m("svg", { height: `${R.value.style.legend.fontSize}px`, width: `${R.value.style.legend.fontSize}px`, viewBox: "0 0 10 10" }, [h("defs", null, [g(me, { t: "radial", id: `legend_grad_${n}-${k.value}`, stops: [[ "0%", E(z) ? "#FFFFFF" : E(t)(E(o)(e.color, .05), 100 - R.value.style.bar.gradient.intensity), 1 ], [ "100%", e.color, 1 ]] }, null, 8, ["id", "stops"])]), h("circle", { cx: 5, cy: 5, r: 5, fill: R.value.style.bar.gradient.show ? `url(#legend_grad_${n}-${k.value})` : e.color }, null, 8, Be)], 8, ze)), E(z) ? p("", !0) : (x(), m(u, { key: 0 }, [h("span", { style: b(`color:${R.value.style.legend.name.color}; font-weight:${R.value.style.legend.name.bold ? "bold" : "normal"}`) }, T(e.name), 5), G.value ? p("", !0) : (x(), m(u, { key: 0 }, [R.value.style.legend.percentage.show ? (x(), m("span", { key: 0, style: b(`font-weight:${R.value.style.legend.percentage.bold ? "bold" : "normal"};color:${R.value.style.legend.percentage.color}`) }, T(q.value.includes(n) ? " - " : e.proportionLabel), 5)) : p("", !0), R.value.style.legend.value.show ? (x(), m("span", { key: 1, style: b(`font-weight:${R.value.style.legend.value.bold ? "bold" : "normal"};color:${R.value.style.legend.value.color}`) }, " (" + T(E(c)(R.value.style.legend.value.formatter, e.value, E(s)({ p: R.value.style.legend.value.prefix, v: e.value, s: R.value.style.legend.value.suffix, r: R.value.style.legend.value.rounding }), { datapoint: e, seriesIndex: n })) + ") ", 5)) : p("", !0)], 64))], 64))])], 46, Le))), 256))], 4)) : p("", !0), g(E(Ue), { teleportTo: R.value.style.tooltip.teleportTo, show: A.value && R.value.style.tooltip.show, parent: Ye.value, backgroundColor: R.value.style.tooltip.backgroundColor, color: R.value.style.tooltip.color, fontSize: R.value.style.tooltip.fontSize, borderRadius: R.value.style.tooltip.borderRadius, borderColor: R.value.style.tooltip.borderColor, borderWidth: R.value.style.tooltip.borderWidth, backgroundOpacity: R.value.style.tooltip.backgroundOpacity, position: R.value.style.tooltip.position, content: j.value, isCustom: N.value, offsetX: R.value.style.tooltip.offsetX, offsetY: -124 + R.value.style.tooltip.offsetY, blockShiftY: !0, smooth: R.value.style.tooltip.smooth, backdropFilter: R.value.style.tooltip.backdropFilter, smoothForce: R.value.style.tooltip.smoothForce, smoothSnapThreshold: R.value.style.tooltip.smoothSnapThreshold, isA11yMode: F.value === "keyboard", a11yPosition: Xe.value }, { "tooltip-before": D(() => [w(e.$slots, "tooltip-before", y(_({ ...M.value })), void 0, !0)]), tooltip: D(() => [w(e.$slots, "tooltip", y(_({ ...M.value })), void 0, !0)]), "tooltip-after": D(() => [w(e.$slots, "tooltip-after", y(_({ ...M.value })), void 0, !0)]), _: 3 }, 8, [ "teleportTo", "show", "parent", "backgroundColor", "color", "fontSize", "borderRadius", "borderColor", "borderWidth", "backgroundOpacity", "position", "content", "isCustom", "offsetX", "offsetY", "smooth", "backdropFilter", "smoothForce", "smoothSnapThreshold", "isA11yMode", "a11yPosition" ]), e.$slots.source ? (x(), m("div", Ve, [w(e.$slots, "source", {}, void 0, !0)], 512)) : p("", !0), w(e.$slots, "skeleton", {}, () => [E(z) ? (x(), f(de, { key: 0 })) : p("", !0)], !0) ], 4)); } }, [["__scopeId", "data-v-a69e0725"]]); //#endregion export { Te as n, He as t };