UNPKG

vue-data-ui

Version:

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

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