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