UNPKG

vue-data-ui-hq

Version:

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

651 lines (650 loc) 26.5 kB
import { useCssVars as $e, ref as p, useSlots as ze, onMounted as pe, computed as _, watch as fe, openBlock as d, createElementBlock as v, normalizeClass as X, unref as e, normalizeStyle as i, createElementVNode as f, toDisplayString as C, createCommentVNode as b, withDirectives as De, createVNode as $, Fragment as J, renderList as K, createBlock as Pe, createSlots as Ne, withCtx as N, renderSlot as z, mergeProps as Fe, nextTick as Ve } from "vue"; import { u as Te, c as We, t as Me, a as Ee, p as F, b as Ue, o as Be, e as me, g as Ge, $ as Le, d as Re, i as V, f as T, q as He, r as qe } from "./index-WrV3SAID.js"; import { u as ge } from "./useNestedProp-Cj0kHD7k.js"; import Xe from "./vue-ui-sparkline-CT-jTpEu.js"; import W from "./BaseIcon-MqKW8Nkx.js"; import { u as Je, U as Ke, v as Qe } from "./usePrinter-kVpf1iV8.js"; import { u as Ye } from "./useUserOptionState-BIvW1Kz7.js"; import { _ as Ze } from "./_plugin-vue_export-helper-CHgC5LLL.js"; const je = ["id"], et = { style: { "z-index": "1", "padding-right": "24px" } }, tt = { key: 0, style: { display: "flex", flexDirection: "row", alignItems: "center" } }, ot = { key: 0, style: { display: "flex", flexDirection: "row", alignItems: "center" } }, at = ["onClick"], nt = ["onClick"], lt = ["data-cell"], st = ["data-cell", "onPointerenter"], rt = ["data-cell"], it = ["data-cell"], ut = ["data-cell"], dt = ["data-cell"], ct = { key: 1, ref: "source", dir: "auto" }, vt = { __name: "vue-ui-table-sparkline", props: { config: { type: Object, default() { return {}; } }, dataset: { type: Array, default() { return []; } } }, setup(be, { expose: ye }) { $e((o) => ({ "2d36faad": o.tdo })); const { vue_ui_table_sparkline: he } = Te(), x = be, M = p(We()), Q = p(0), E = p(0), U = p(null), ke = ze(); pe(() => { ke["chart-background"] && console.warn("VueUiTableSparkline does not support the #chart-background slot."); }); const t = _({ get: () => j(), set: (o) => o }), { userOptionsVisible: B, setUserOptionsVisibility: Y, keepUserOptionState: Z } = Ye({ config: t.value }); function j() { const o = ge({ userConfig: x.config, defaultConfig: he }); return o.theme ? { ...ge({ userConfig: Me.vue_ui_table_sparkline[o.theme] || x.config, defaultConfig: o }), customPalette: Ee[o.theme] || F } : o; } fe(() => x.config, (o) => { t.value = j(), B.value = !t.value.showOnChartHover, ne(), E.value += 1; }, { deep: !0 }), fe(() => x.dataset, (o) => { m.value = A.value, E.value += 1; }, { deep: !0 }); const { isPrinting: ee, isImaging: te, generatePdf: oe, generateImage: ae } = Je({ elementId: `table_${M.value}`, fileName: t.value.title.text || "vue-ui-table-sparkline" }), _e = _(() => Ue(t.value.customPalette)), D = p(null), G = p(!1), Ce = _(() => t.value.responsiveBreakpoint); pe(() => { ne(); }); const L = p(t.value.colNames); function ne() { Be(x.dataset) && me({ componentName: "VueUiTableSparkline", type: "dataset" }); const o = new ResizeObserver((n) => { n.forEach((a) => { G.value = a.contentRect.width < Ce.value; }); }); D.value && o.observe(D.value), L.value = []; for (let n = 0; n < re.value; n += 1) L.value.push(t.value.colNames[n] || `col ${n}`); } const le = _(() => (x.dataset.forEach((o, n) => { Ge({ datasetObject: o, requiredAttributes: ["name", "values"] }).forEach((a) => { me({ componentName: "VueUiTableSparkline", type: "datasetSerieAttribute", property: a, index: n }); }); }), x.dataset.map((o, n) => { const a = (o.values || []).map((c) => isNaN(c) ? 0 : c ?? 0), l = a.reduce((c, u) => c + u, 0), r = l / a.length, s = Le(a); return { ...o, values: o.values || [], color: Re(o.color) || _e.value[n] || F[n] || F[n % F.length], sum: l, average: r, median: s, sparklineDataset: a.map((c, u) => ({ period: t.value.colNames[u] || `col ${u}`, value: c || 0 })) }; }))); function xe(o) { const a = (o[0].values || []).map( (r, s) => o.map((c) => c.values[s] || []) ).map( (r) => r.map((s, c) => [s, c]).sort((s, c) => c[0] - s[0]).map((s) => s[1]) ); return o.map((r, s) => ({ ...r, values: r.values || [], orders: a[s] })); } const A = _(() => xe(le.value)), m = p(A.value), we = _(() => Math.max(...m.value.map((o) => (o.values || []).length))), R = p(void 0), H = p(!1), g = p(void 0), se = p(1); function I() { H.value = !1, g.value = void 0, y.value = void 0, se.value = 1, O.value.forEach((o) => o.state = 1), w.value = { name: 1, sum: 1, average: 1, median: 1 }, m.value = A.value; } function P(o, n, a) { if (["name", "sum", "average", "median"].includes(o.type)) { Se(o.type, n, a); return; } if (!de(n)) return; if (S.value = n, y.value = void 0, ![null, void 0].includes(g.value) && n !== g.value && (g.value = void 0, I()), O.value[n].state === a && g.value === n) { g.value = void 0, I(); return; } H.value = !0, g.value = n; const l = A.value.map((u) => u.values[n] || []), r = a; O.value[n].state = r, se.value = r, n === R.value ? R.value = void 0 : R.value = n; const c = l.map((u, h) => [h, u]).sort((u, h) => r * (h[1] - u[1])).map((u) => u[0]).map((u) => A.value[u]); m.value = c, E.value += 1; } const re = _(() => Math.max(...x.dataset.map((o) => (o.values || []).length))), k = _(() => { let o = L.value.map((a) => ({ type: "reg", value: a })); if (!o.length) for (let a = 0; a < re.value; a += 1) o.push({ type: "reg", value: `col ${a + 1}` }); t.value.showTotal && (o = [...o, { type: "sum", value: t.value.translations.total }]); let n; return t.value.showAverage && t.value.showMedian ? n = [ ...o, { type: "average", value: t.value.translations.average }, { type: "median", value: t.value.translations.median } ] : t.value.showAverage && !t.value.showMedian ? n = [...o, { type: "average", value: t.value.translations.average }] : !t.value.showAverage && t.value.showMedian ? n = [...o, { type: "median", value: t.value.translations.median }] : n = o, t.value.showSparklines ? [...n, { type: "chart", value: t.value.translations.chart }] : n; }), w = p({ name: 1, sum: 1, average: 1, median: 1 }), y = p(void 0); function Se(o, n, a) { if (!m.value || m.value.length === 0 || !ce(o)) return; if (y.value !== o && (y.value = void 0), ![null, void 0].includes(g.value) && n !== g.value && I(), g.value = void 0, w.value[o] === a && y.value) { y.value = void 0, I(); return; } y.value = o, H.value = !0, w.value[o] = a, [null, void 0].includes(n) || (O.value[n].state = w.value[o]); const l = w.value[o], r = [...m.value].sort((s, c) => { const u = s[o] ?? (typeof s[o] == "number" ? 0 : ""), h = c[o] ?? (typeof c[o] == "number" ? 0 : ""); return typeof u == "string" && typeof h == "string" ? l === -1 ? u.localeCompare(h) : h.localeCompare(u) : typeof u == "number" && typeof h == "number" ? l === -1 ? u - h : h - u : 0; }); m.value = r; } const S = p(void 0), q = p(void 0); function Ie({ dataIndex: o, serieIndex: n }) { S.value = o, q.value = n, U.value[o] && !G.value && U.value[o].scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center" }); } const ie = p(!1); function Ae(o) { ie.value = o, Q.value += 1; } function ue() { Ve(() => { const o = [t.value.translations.serie].concat(k.value), n = le.value.map((r, s) => [ [r.name], r.values, [r.sum], [r.average], [r.median] ]), a = [o].concat(n), l = He(a); qe({ csvContent: l, title: t.value.title.text || "vue-ui-table-sparkline" }); }); } function de(o) { return t.value.sortedDataColumnIndices.includes(o); } function ce(o) { return o.type === "name" || o === "name" ? t.value.sortedSeriesName : o.type === "sum" || o === "sum" ? t.value.sortedSum : o.type === "average" || o === "average" ? t.value.sortedAverage : o.type === "median" || o === "median" ? t.value.sortedMedian : !1; } function ve(o, n, a) { return ["sum", "average", "median"].includes(n.type) ? y.value === n.type && w.value[n.type] === a ? 1 : 0.3 : o === g.value && O.value[o].state === a ? 1 : 0.3; } function Oe() { t.value.resetSortOnClickOutside && I(); } const O = _({ get: () => k.value.map((o) => ({ state: 1 })), set: (o) => o }); return ye({ generatePdf: oe, generateImage: ae, generateCsv: ue, restoreOrder: I }), (o, n) => (d(), v("div", { ref_key: "tableContainer", ref: D, class: X({ "vue-ui-responsive": e(G) }), style: { overflow: "hidden" }, id: `table_${e(M)}`, onMouseenter: n[3] || (n[3] = () => e(Y)(!0)), onMouseleave: n[4] || (n[4] = () => e(Y)(!1)) }, [ e(t).title.text ? (d(), v("div", { key: 0, class: "vue-ui-table-sparkline-caption", style: i({ backgroundColor: e(t).title.backgroundColor }) }, [ f("div", { style: i({ fontSize: `${e(t).title.fontSize}px`, fontWeight: e(t).title.bold ? "bold" : "normal", color: e(t).title.color, textAlign: e(t).title.textAlign }) }, C(e(t).title.text), 5), e(t).title.subtitle.text ? (d(), v("div", { key: 0, style: i({ fontSize: `${e(t).title.subtitle.fontSize}px`, fontWeight: e(t).title.subtitle.bold ? "bold" : "normal", color: e(t).title.subtitle.color, textAlign: e(t).title.textAlign }) }, C(e(t).title.subtitle.text), 5)) : b("", !0) ], 4)) : b("", !0), f("div", { style: { overflow: "auto" }, onPointerleave: n[2] || (n[2] = (a) => { q.value = void 0, S.value = void 0; }) }, [ f("table", { class: "vue-ui-data-table", style: i({ fontFamily: e(t).fontFamily, position: "relative" }) }, [ f("thead", et, [ De((d(), v("tr", { role: "row", class: "vue-ui-data-table__thead-row", style: i({ backgroundColor: e(t).thead.backgroundColor, color: e(t).thead.color }) }, [ f("th", { role: "cell", style: i({ backgroundColor: e(t).thead.backgroundColor, border: e(t).thead.outline, textAlign: e(t).thead.textAlign, fontWeight: e(t).thead.bold ? "bold" : "normal" }), class: "sticky-col-first" }, [ f("div", { style: i({ display: "flex", flexDirection: "row", alignItems: "center", gap: "3px", justifyContent: e(t).thead.textAlign }) }, [ f("span", null, C(e(t).translations.serie), 1), e(m).length > 1 && e(t).sortedSeriesName ? (d(), v("div", tt, [ f("button", { class: "vue-ui-table-sparkline-sorting-button vue-ui-table-sparkline-sorting-button-down", onClick: n[0] || (n[0] = (a) => P({ type: "name" }, null, -1)) }, [ $(W, { size: 12, name: "arrowBottom", stroke: e(t).thead.color, style: i({ opacity: e(y) === "name" && e(w).name === -1 ? 1 : 0.3 }) }, null, 8, ["stroke", "style"]) ]), f("button", { class: "vue-ui-table-sparkline-sorting-button vue-ui-table-sparkline-sorting-button-up", onClick: n[1] || (n[1] = (a) => P({ type: "name" }, null, 1)) }, [ $(W, { size: 12, name: "arrowTop", stroke: e(t).thead.color, style: i({ opacity: e(y) === "name" && e(w).name === 1 ? 1 : 0.3 }) }, null, 8, ["stroke", "style"]) ]) ])) : b("", !0) ], 4) ], 4), (d(!0), v(J, null, K(e(k), (a, l) => (d(), v("th", { role: "cell", style: i({ background: e(t).thead.backgroundColor, border: e(t).thead.outline, textAlign: e(t).thead.textAlign, fontWeight: e(t).thead.bold ? "bold" : "normal", minWidth: l === e(k).length - 1 ? `${e(t).sparkline.dimensions.width}px` : "48px", paddingRight: l === e(k).length - 1 && e(t).userOptions.show ? "36px" : "" }), class: X({ "sticky-col": l === e(k).length - 1 && e(t).showSparklines }) }, [ f("div", { style: i({ display: "flex", flexDirection: "row", alignItems: "center", gap: "3px", justifyContent: e(t).thead.textAlign }) }, [ f("span", null, C(a.value), 1), e(m).length > 1 && (de(l) || ce(a)) ? (d(), v("div", ot, [ f("button", { class: "vue-ui-table-sparkline-sorting-button vue-ui-table-sparkline-sorting-button-down", onClick: () => P(a, l, -1) }, [ $(W, { size: 12, name: "arrowBottom", stroke: e(t).thead.color, style: i({ opacity: ve(l, a, -1) }) }, null, 8, ["stroke", "style"]) ], 8, at), f("button", { class: "vue-ui-table-sparkline-sorting-button vue-ui-table-sparkline-sorting-button-up", onClick: () => P(a, l, 1) }, [ $(W, { size: 12, name: "arrowTop", stroke: e(t).thead.color, style: i({ opacity: ve(l, a, 1) }) }, null, 8, ["stroke", "style"]) ], 8, nt) ])) : b("", !0) ], 4), e(t).userOptions.show && l === e(k).length - 1 && (e(Z) || e(B)) ? (d(), Pe(Ke, { ref_for: !0, ref: "details", key: `user_option_${e(Q)}`, backgroundColor: e(t).thead.backgroundColor, color: e(t).thead.color, isPrinting: e(ee), isImaging: e(te), uid: e(M), hasPdf: e(t).userOptions.buttons.pdf, hasXls: e(t).userOptions.buttons.csv, hasImg: e(t).userOptions.buttons.img, hasFullscreen: e(t).userOptions.buttons.fullscreen, isFullscreen: e(ie), titles: { ...e(t).userOptions.buttonTitles }, chartElement: e(D), position: e(t).userOptions.position, onToggleFullscreen: Ae, onGeneratePdf: e(oe), onGenerateImage: e(ae), onGenerateCsv: ue, style: i({ visibility: e(Z) ? e(B) ? "visible" : "hidden" : "visible" }) }, Ne({ _: 2 }, [ o.$slots.optionPdf ? { name: "optionPdf", fn: N(() => [ z(o.$slots, "optionPdf", {}, void 0, !0) ]), key: "0" } : void 0, o.$slots.optionCsv ? { name: "optionCsv", fn: N(() => [ z(o.$slots, "optionCsv", {}, void 0, !0) ]), key: "1" } : void 0, o.$slots.optionImg ? { name: "optionImg", fn: N(() => [ z(o.$slots, "optionImg", {}, void 0, !0) ]), key: "2" } : void 0, o.$slots.optionFullscreen ? { name: "optionFullscreen", fn: N(({ toggleFullscreen: r, isFullscreen: s }) => [ z(o.$slots, "optionFullscreen", Fe({ ref_for: !0 }, { toggleFullscreen: r, isFullscreen: s }), void 0, !0) ]), key: "3" } : void 0 ]), 1032, ["backgroundColor", "color", "isPrinting", "isImaging", "uid", "hasPdf", "hasXls", "hasImg", "hasFullscreen", "isFullscreen", "titles", "chartElement", "position", "onGeneratePdf", "onGenerateImage", "style"])) : b("", !0) ], 6))), 256)) ], 4)), [ [e(Qe), Oe] ]) ]), f("tbody", null, [ (d(!0), v(J, null, K(e(m), (a, l) => (d(), v("tr", { role: "row", style: i({ backgroundColor: e(t).tbody.backgroundColor, color: e(t).tbody.color }), class: X({ "vue-ui-data-table__tbody__row": !0, "vue-ui-data-table__tbody__row-even": l % 2 === 0, "vue-ui-data-table__tbody__row-odd": l % 2 !== 0 }) }, [ f("td", { role: "cell", style: i({ backgroundColor: e(t).tbody.backgroundColor, border: e(t).tbody.outline, fontSize: `${e(t).tbody.fontSize}px`, fontWeight: e(t).tbody.bold ? "bold" : "normal", textAlign: e(t).tbody.textAlign }), "data-cell": e(t).translations.serie, class: "vue-ui-data-table__tbody__td sticky-col-first" }, [ f("div", { dir: "auto", style: i({ display: "flex", flexDirection: "row", alignItems: "center", gap: "6px", justifyContent: e(t).tbody.textAlign }) }, [ e(t).tbody.showColorMarker ? (d(), v("span", { key: 0, style: i({ color: a.color }) }, "⬤", 4)) : b("", !0), f("span", null, C(a.name ?? "-"), 1) ], 4) ], 12, lt), (d(!0), v(J, null, K(e(we), (r, s) => (d(), v("td", { dir: "auto", role: "cell", ref_for: !0, ref_key: "TD", ref: U, style: i({ border: e(t).tbody.outline, fontSize: `${e(t).tbody.fontSize}px`, fontWeight: e(t).tbody.bold ? "bold" : "normal", textAlign: e(t).tbody.textAlign, background: e(S) !== void 0 && s === e(S) ? e(t).tbody.selectedColor.useSerieColor ? `${a.color.length > 7 ? a.color.slice(0, -2) : a.color}33` : e(t).tbody.selectedColor.fallback : "" }), "data-cell": e(k)[s] ? e(k)[s].value : "", class: "vue-ui-data-table__tbody__td", onPointerenter: (c) => { q.value = l, S.value = s; } }, C([null, void 0].includes(a.values[s]) ? "-" : e(V)( e(t).formatter, Number(a.values[s]), e(T)({ p: e(t).prefix, v: Number(a.values[s]), s: e(t).suffix, r: e(t).roundingValues }), { datapoint: a, seriesIndex: l, datapointIndex: s } )), 45, st))), 256)), e(t).showTotal ? (d(), v("td", { key: 0, dir: "auto", role: "cell", style: i({ border: e(t).tbody.outline, fontSize: `${e(t).tbody.fontSize}px`, fontWeight: e(t).tbody.bold ? "bold" : "normal", textAlign: e(t).tbody.textAlign }), "data-cell": e(t).translations.total, class: "vue-ui-data-table__tbody__td" }, C(e(V)( e(t).formatter, a.sum, e(T)({ p: e(t).prefix, v: a.sum, s: e(t).suffix, r: e(t).roundingTotal }), { datapoint: a.sum, seriesIndex: l } )), 13, rt)) : b("", !0), e(t).showAverage ? (d(), v("td", { key: 1, dir: "auto", role: "cell", style: i({ border: e(t).tbody.outline, fontSize: `${e(t).tbody.fontSize}px`, fontWeight: e(t).tbody.bold ? "bold" : "normal", textAlign: e(t).tbody.textAlign }), "data-cell": e(t).translations.average, class: "vue-ui-data-table__tbody__td" }, C(e(V)( e(t).formatter, a.average, e(T)({ p: e(t).prefix, v: a.average, s: e(t).suffix, r: e(t).roundingAverage }), { datapoint: a.average, seriesIndex: l } )), 13, it)) : b("", !0), e(t).showMedian ? (d(), v("td", { key: 2, dir: "auto", role: "cell", style: i({ border: e(t).tbody.outline, fontSize: `${e(t).tbody.fontSize}px`, fontWeight: e(t).tbody.bold ? "bold" : "normal", textAlign: e(t).tbody.textAlign }), "data-cell": e(t).translations.median, class: "vue-ui-data-table__tbody__td" }, C(e(V)( e(t).formatter, a.median, e(T)({ p: e(t).prefix, v: a.median, s: e(t).suffix, r: e(t).roundingMedian }), { datapoint: a.median, seriesIndex: l } )), 13, ut)) : b("", !0), e(t).showSparklines ? (d(), v("td", { key: 3, role: "cell", "data-cell": e(t).translations.chart, style: i({ border: e(t).tbody.outline, fontSize: `${e(t).tbody.fontSize}px`, fontWeight: e(t).tbody.bold ? "bold" : "normal", textAlign: e(t).tbody.textAlign, backgroundColor: e(t).tbody.backgroundColor, padding: "0" }), class: "vue-ui-data-table__tbody__td sticky-col" }, [ $(Xe, { onHoverIndex: ({ index: r }) => Ie({ dataIndex: r, serieIndex: l }), "height-ratio": e(t).sparkline.dimensions.heightRatio, "forced-padding": 30, dataset: a.sparklineDataset, showInfo: !1, selectedIndex: e(S), config: { type: e(t).sparkline.type, style: { backgroundColor: "transparent", animation: { show: e(t).sparkline.animation.show && !e(ee) && !e(te), animationFrames: e(t).sparkline.animation.animationFrames }, line: { color: a.color, smooth: e(t).sparkline.smooth, strokeWidth: e(t).sparkline.strokeWidth }, bar: { color: a.color }, area: { color: a.color, opacity: e(t).sparkline.showArea ? 16 : 0, useGradient: e(t).sparkline.useGradient }, verticalIndicator: { color: a.color }, plot: { radius: 9, stroke: e(t).tbody.backgroundColor, strokeWidth: 3 } } } }, null, 8, ["onHoverIndex", "height-ratio", "dataset", "selectedIndex", "config"]) ], 12, dt)) : b("", !0) ], 6))), 256)) ]) ], 4) ], 32), o.$slots.source ? (d(), v("div", ct, [ z(o.$slots, "source", {}, void 0, !0) ], 512)) : b("", !0) ], 42, je)); } }, _t = /* @__PURE__ */ Ze(vt, [["__scopeId", "data-v-26859642"]]); export { _t as default };