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
JavaScript
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
};