vue-data-ui
Version:
A user-empowering data visualization Vue 3 components library for eloquent data storytelling
514 lines (513 loc) • 22.8 kB
JavaScript
import { defineAsyncComponent as he, computed as h, ref as y, toRefs as Pe, watch as J, shallowRef as fe, onMounted as Re, onBeforeUnmount as ye, createElementBlock as c, openBlock as s, normalizeStyle as D, renderSlot as I, createCommentVNode as f, createBlock as pe, normalizeProps as ge, guardReactiveProps as me, createElementVNode as p, toDisplayString as T, unref as n, createVNode as Fe, Fragment as Q, renderList as ee, withCtx as Ee, createTextVNode as Oe, nextTick as Be } from "vue";
import { u as Ge, c as je, t as Ue, b as Xe, C as be, a6 as te, o as ke, f as xe, g as Ye, x as W, a7 as qe, a8 as Ze, X as Ke, s as P, V as _e, U as He, a9 as we, k as ae, i as le, aa as Je } from "./index-q-LPw2IT.js";
import { u as Le } from "./useNestedProp-04aFeUYu.js";
import { t as Qe, u as et } from "./useResponsive-DfdjqQps.js";
import { u as tt } from "./useChartAccessibility-9icAAmYg.js";
import { u as at, B as lt } from "./useLoading-D7YHNtLX.js";
import { u as ut } from "./useTimeLabels-DkzmKfZn.js";
import { _ as ot } from "./_plugin-vue_export-helper-CHgC5LLL.js";
const st = ["id"], nt = ["xmlns", "viewBox"], rt = ["width", "height"], it = ["id"], vt = ["stop-color"], dt = ["stop-color"], ct = ["id"], ht = ["stop-color"], ft = ["stop-color"], yt = ["id"], pt = ["stop-color"], gt = ["stop-color"], mt = { key: 1 }, bt = ["d", "fill"], kt = ["d", "fill"], xt = ["d", "stroke", "stroke-width"], _t = ["d", "stroke", "stroke-width"], wt = ["x", "y", "width", "height", "fill", "rx"], Lt = ["x1", "x2", "y1", "y2", "stroke", "stroke-width", "stroke-dasharray"], At = ["x1", "x2", "y1", "y2", "stroke", "stroke-dasharray", "stroke-width"], $t = ["cx", "cy", "r", "fill", "stroke", "stroke-width"], Nt = ["x", "y", "font-size", "font-weight", "fill"], Mt = ["x", "y", "height", "width", "onMouseenter", "onMouseleave", "onClick"], Ct = {
__name: "vue-ui-sparkline",
props: {
config: {
type: Object,
default() {
return {};
}
},
dataset: {
type: Array,
default() {
return [];
}
},
showInfo: {
type: Boolean,
default: !0
},
selectedIndex: {
type: Number,
default: void 0
},
heightRatio: {
type: Number,
default: 1
},
forcedPadding: {
type: Number,
default: 30
}
},
emits: ["hoverIndex", "selectDatapoint"],
setup(x, { emit: Ae }) {
const $e = he(() => import("./PackageVersion-5ZjKSIei.js")), Ne = he(() => import("./SparkTooltip-Diyt3BTN.js")), { vue_ui_sparkline: Me } = Ge(), r = x, ue = h(() => Array.isArray(r.dataset) && r.dataset.length > 0), g = y(je()), R = y(null), oe = y(null), se = y(null), e = y(O());
function Ce(t) {
return Je(t).map((a) => ({ period: "-", value: a }));
}
const { loading: F, FINAL_DATASET: S, manualLoading: E } = at({
...Pe(r),
FINAL_CONFIG: e,
prepareConfig: O,
callback: () => {
Promise.resolve().then(async () => {
await Be(), X();
});
},
skeletonDataset: Ce(12),
skeletonConfig: Ue({
defaultConfig: e.value,
userConfig: {
style: {
backgroundColor: "#99999930",
scaleMin: 0,
scaleMax: null,
animation: { show: !1 },
line: { color: "#AAAAAA" },
bar: { color: "#AAAAAA" },
area: { color: "#CACACA" },
zeroLine: { color: "#6A6A6A" },
dataLabel: { show: !1 },
tooltip: { show: !1 }
}
}
})
}), { svgRef: ne } = tt({ config: e.value.style.title });
function O() {
const t = Le({
userConfig: r.config,
defaultConfig: Me
});
let a = {};
return t.theme ? a = {
...Le({
userConfig: Xe.vue_ui_sparkline[t.theme] || r.config,
defaultConfig: t
})
} : a = t, r.config && be(r.config, "style.scaleMin") ? a.style.scaleMin = r.config.style.scaleMin : a.style.scaleMin = null, r.config && be(r.config, "style.scaleMax") ? a.style.scaleMax = r.config.style.scaleMax : a.style.scaleMax = null, a;
}
const _ = h(() => te({
data: S.value,
threshold: e.value.downsample.threshold
}));
J(() => r.config, (t) => {
F.value || (e.value = O()), ie(), o.value.chartWidth = e.value.style.chartWidth;
}, { deep: !0 }), J(() => r.dataset, (t) => {
Array.isArray(t) && t.length > 0 && (E.value = !1), m.value = te({
data: S.value.map((a) => ({
...a,
value: [void 0].includes(a.value) ? null : a.value
})),
threshold: e.value.downsample.threshold
});
}, { deep: !0 });
const m = y(Ie());
function Ie() {
return te({
data: S.value.map((t) => e.value.style.animation.show && S.value.length > 1 ? {
...t,
value: null
} : {
...t,
value: [void 0].includes(t.value) ? null : t.value
}),
threshold: e.value.downsample.threshold
});
}
const b = fe(null), w = fe(null), B = y(!1), N = y(0), G = y([]), j = y(""), U = h(() => {
const a = (_.value || []).map((u) => `${u.period}::${Number.isFinite(u.value) ? u.value : 0}`).join("|"), l = e.value?.style?.animation || {};
return `${a}#${!!l.show}#${l.animationFrames || 0}`;
});
function V() {
N.value && (cancelAnimationFrame(N.value), N.value = 0), G.value.forEach((t) => clearTimeout(t)), G.value = [], B.value = !1;
}
function X() {
const t = e.value?.style?.animation || {}, a = _.value || [], l = U.value;
if (l && l === j.value && (B.value || m.value.length === a.length))
return;
if (V(), !t.show || F.value || a.length <= 1) {
m.value = a, j.value = l;
return;
}
B.value = !0, j.value = l, m.value = [];
const u = Math.max(1, Number(t.animationFrames) || 1), K = Math.max(1, Math.floor(u / a.length));
let H = 0;
const ce = () => {
if (l !== U.value) {
V();
return;
}
if (H < a.length) {
m.value.push(a[H]);
const We = setTimeout(() => {
N.value = requestAnimationFrame(ce);
}, K);
G.value.push(We), H += 1;
} else
m.value = a, V();
};
N.value = requestAnimationFrame(ce);
}
J(U, () => {
X();
}), Re(() => {
ie(), X();
}), ye(() => {
V();
});
const re = h(() => !!e.value.debug);
function ie() {
if (ke(r.dataset) ? (xe({
componentName: "VueUiSparkline",
type: "dataset",
debug: re.value
}), E.value = !0) : r.dataset.forEach((t, a) => {
Ye({
datasetObject: t,
requiredAttributes: ["period", "value"]
}).forEach((l) => {
xe({
componentName: "VueUiSparkline",
type: "datasetSerieAttribute",
property: l,
index: a,
debug: re.value
});
});
}), ke(r.dataset) || (E.value = e.value.loading), e.value.responsive) {
const t = Qe(() => {
const { width: a, height: l } = et({
chart: R.value,
title: e.value.style.title.show && r.showInfo ? oe.value : null,
source: se.value
});
requestAnimationFrame(() => {
o.value.width = a, o.value.height = l, o.value.chartWidth = e.value.style.chartWidth / 500 * a, o.value.padding = r.forcedPadding / 500 * a;
});
});
b.value && (w.value && b.value.unobserve(w.value), b.value.disconnect()), b.value = new ResizeObserver(t), w.value = R.value.parentNode, b.value.observe(w.value);
}
}
ye(() => {
b.value && (w.value && b.value.unobserve(w.value), b.value.disconnect());
});
const o = y({
height: 80 * r.heightRatio,
width: 500,
chartWidth: e.value.style.chartWidth,
padding: r.forcedPadding
}), Y = Ae, i = h(() => {
const { top: t, right: a, bottom: l, left: u } = e.value.style.padding;
return {
top: t,
left: u,
right: o.value.width - a,
bottom: o.value.height - l,
start: r.showInfo && e.value.style.dataLabel.show && e.value.style.dataLabel.position === "left" ? o.value.width - o.value.chartWidth + u : o.value.padding + u,
width: r.showInfo && e.value.style.dataLabel.show ? o.value.chartWidth - u - a : o.value.width - o.value.padding - u - a,
height: o.value.height - t - l
};
}), q = h(() => [null, void 0].includes(e.value.style.scaleMin) ? Math.min(...m.value.map((t) => isNaN(t.value) || [void 0, null, "NaN", NaN, 1 / 0, -1 / 0].includes(t.value) ? 0 : t.value || 0)) : e.value.style.scaleMin), Se = h(() => [null, void 0].includes(e.value.style.scaleMax) ? Math.max(...m.value.map((t) => isNaN(t.value) || [void 0, null, "NaN", NaN, 1 / 0, -1 / 0].includes(t.value) ? 0 : t.value || 0)) : e.value.style.scaleMax), M = h(() => {
const t = q.value >= 0 ? 0 : q.value;
return Math.abs(t);
}), ve = h(() => Se.value + M.value), L = h(() => i.value.bottom - i.value.height * Z(M.value));
function Z(t) {
return isNaN(t / ve.value) ? 0 : t / ve.value;
}
const A = h(() => _.value.length - 1 || 1), z = h(() => ut({
values: _.value.map((t) => t.period),
maxDatapoints: _.value.length,
formatter: e.value.style.dataLabel.datetimeFormatter,
start: 0,
end: _.value.length
})), d = h(() => m.value.map((t, a) => {
const l = isNaN(t.value) || [void 0, null, "NaN", NaN, 1 / 0, -1 / 0].includes(t.value) ? 0 : t.value || 0, u = i.value.width / A.value;
return {
absoluteValue: l,
period: z.value && z.value[a] && z.value[a].text ? z.value[a].text : t.period,
plotValue: l + M.value,
toMax: Z(l + M.value),
x: i.value.start + a * u,
y: i.value.bottom - i.value.height * Z(l + M.value),
id: `plot_${g.value}_${a}`,
color: C.value ? e.value.style.bar.color : e.value.style.area.useGradient ? W(e.value.style.line.color, 0.05 * (1 - a / A.value)) : e.value.style.line.color,
width: u
};
})), Ve = h(() => {
const t = { x: d.value[0].x || 0, y: (o.value.height || 0) - 6 }, a = { x: d.value[d.value.length - 1].x || 0, y: (o.value.height || 0) - 6 }, l = [];
return d.value.forEach((u) => {
l.push(`${u.x || 0},${u.y || 0} `);
}), [t.x, t.y, ...l, a.x, a.y].toString();
}), v = y(void 0), $ = y(void 0);
function ze(t, a) {
e.value.events.datapointEnter && e.value.events.datapointEnter({ datapoint: t, seriesIndex: a }), v.value = t, $.value || ($.value = t), Y("hoverIndex", { index: a });
}
function De(t, a) {
e.value.events.datapointLeave && e.value.events.datapointLeave({ datapoint: t, seriesIndex: a }), $.value = v.value, v.value = void 0, Y("hoverIndex", { index: void 0 });
}
const k = h(() => {
if (ue.value) {
const t = d.value.map((l) => l.absoluteValue), a = t.reduce((l, u) => l + u, 0);
return {
latest: d.value[d.value.length - 1] ? d.value[d.value.length - 1].absoluteValue : 0,
sum: a,
average: a / d.value.length,
median: Ze(t),
trend: qe(d.value.map(({ x: l, y: u, absoluteValue: K }) => ({
x: l,
y: u,
value: K
}))).trend
};
} else
return {
latest: null,
sum: null,
average: null,
median: null,
trend: null
};
}), de = h(() => ue.value ? e.value.style.dataLabel.valueType === "latest" ? k.value.latest : e.value.style.dataLabel.valueType === "sum" ? k.value.sum : e.value.style.dataLabel.valueType === "average" ? k.value.average : 0 : 0), C = h(() => e.value.type && e.value.type === "bar");
function Te(t, a) {
e.value.events.datapointClick && e.value.events.datapointClick({ datapoint: t, seriesIndex: a }), Y("selectDatapoint", { datapoint: t, index: a });
}
return (t, a) => (s(), c("div", {
ref_key: "sparklineChart",
ref: R,
class: "vue-ui-sparkline",
id: g.value,
style: D(`width:100%;font-family:${e.value.style.fontFamily};`)
}, [
I(t.$slots, "before", ge(me({
selected: v.value,
latest: k.value.latest,
sum: k.value.sum,
average: k.value.average,
median: k.value.median,
trend: k.value.trend
})), void 0, !0),
e.value.style.title.show && x.showInfo ? (s(), c("div", {
key: 0,
ref_key: "chartTitle",
ref: oe,
class: "vue-ui-sparkline-title",
style: D(`display:flex;align-items:center;width:100%;color:${e.value.style.title.color};background:${e.value.style.backgroundColor};justify-content:${e.value.style.title.textAlign === "left" ? "flex-start" : e.value.style.title.textAlign === "right" ? "flex-end" : "center"};height:${e.value.style.title.fontSize * 2}px;font-size:${e.value.style.title.fontSize}px;font-weight:${e.value.style.title.bold ? "bold" : "normal"};`)
}, [
p("span", {
style: D(`padding:${e.value.style.title.textAlign === "left" ? "0 0 0 12px" : e.value.style.title.textAlign === "right" ? "0 12px 0 0" : "0"}`)
}, T(v.value ? v.value.period : e.value.style.title.text), 5)
], 4)) : f("", !0),
(s(), c("svg", {
ref_key: "svgRef",
ref: ne,
xmlns: n(Ke),
viewBox: `0 0 ${o.value.width} ${o.value.height}`,
style: D(`background:${e.value.style.backgroundColor};overflow:visible`),
onMouseleave: a[0] || (a[0] = (l) => $.value = void 0)
}, [
Fe(n($e)),
t.$slots["chart-background"] ? (s(), c("foreignObject", {
key: 0,
x: 0,
y: 0,
width: o.value.width <= 0 ? 10 : o.value.width,
height: o.value.height <= 0 ? 10 : o.value.height,
style: {
pointerEvents: "none"
}
}, [
I(t.$slots, "chart-background", {}, void 0, !0)
], 8, rt)) : f("", !0),
p("defs", null, [
p("linearGradient", {
x1: "0%",
y1: "0%",
x2: "100%",
y2: "0%",
id: `sparkline_gradient_${g.value}`
}, [
p("stop", {
offset: "0%",
"stop-color": n(P)(n(W)(e.value.style.area.color, 0.05), e.value.style.area.opacity)
}, null, 8, vt),
p("stop", {
offset: "100%",
"stop-color": n(P)(e.value.style.area.color, e.value.style.area.opacity)
}, null, 8, dt)
], 8, it),
p("linearGradient", {
x2: "0%",
y2: "100%",
id: `sparkline_bar_gradient_pos_${g.value}`
}, [
p("stop", {
offset: "0%",
"stop-color": e.value.style.bar.color
}, null, 8, ht),
p("stop", {
offset: "100%",
"stop-color": n(W)(e.value.style.bar.color, 0.05)
}, null, 8, ft)
], 8, ct),
p("linearGradient", {
x2: "0%",
y2: "100%",
id: `sparkline_bar_gradient_neg_${g.value}`
}, [
p("stop", {
offset: "0%",
"stop-color": n(W)(e.value.style.bar.color, 0.05)
}, null, 8, pt),
p("stop", {
offset: "100%",
"stop-color": e.value.style.bar.color
}, null, 8, gt)
], 8, yt)
]),
e.value.style.area.show && !C.value && d.value[0] && d.value.length > 1 ? (s(), c("g", mt, [
e.value.style.line.smooth ? (s(), c("path", {
key: 0,
d: `M ${d.value[0].x},${i.value.bottom} ${n(_e)(d.value)} L ${d.value.at(-1).x},${i.value.bottom} Z`,
fill: e.value.style.area.useGradient ? `url(#sparkline_gradient_${g.value})` : n(P)(e.value.style.area.color, e.value.style.area.opacity)
}, null, 8, bt)) : (s(), c("path", {
key: 1,
d: `M${Ve.value}Z`,
fill: e.value.style.area.useGradient ? `url(#sparkline_gradient_${g.value})` : n(P)(e.value.style.area.color, e.value.style.area.opacity)
}, null, 8, kt))
])) : f("", !0),
e.value.style.line.smooth && !C.value ? (s(), c("path", {
key: 2,
d: `M ${n(_e)(d.value) || "0,0"}`,
stroke: e.value.style.line.color,
fill: "none",
"stroke-width": e.value.style.line.strokeWidth,
"stroke-linecap": "round"
}, null, 8, xt)) : f("", !0),
!e.value.style.line.smooth && !C.value ? (s(), c("path", {
key: 3,
d: `M ${n(He)(d.value) || "0,0"}`,
stroke: e.value.style.line.color,
fill: "none",
"stroke-width": e.value.style.line.strokeWidth,
"stroke-linecap": "round"
}, null, 8, _t)) : f("", !0),
(s(!0), c(Q, null, ee(d.value, (l, u) => (s(), c("g", null, [
C.value ? (s(), c("rect", {
key: 0,
x: l.x - l.width / 2,
y: isNaN(l.absoluteValue > 0 ? l.y : L.value) ? 0 : l.absoluteValue > 0 ? l.y : L.value,
width: l.width,
height: isNaN(Math.abs(l.y - L.value)) ? 0 : Math.abs(l.y - L.value),
fill: l.absoluteValue > 0 ? `url(#sparkline_bar_gradient_pos_${g.value})` : `url(#sparkline_bar_gradient_neg_${g.value})`,
rx: e.value.style.bar.borderRadius
}, null, 8, wt)) : f("", !0),
e.value.style.verticalIndicator.show && (v.value && l.id === v.value.id || x.selectedIndex === u) ? (s(), c("line", {
key: 1,
x1: l.x,
x2: l.x,
y1: i.value.top - 6,
y2: i.value.bottom,
stroke: e.value.style.verticalIndicator.color || l.color,
"stroke-width": e.value.style.verticalIndicator.strokeWidth,
"stroke-linecap": "round",
"stroke-dasharray": e.value.style.verticalIndicator.strokeDasharray || 0
}, null, 8, Lt)) : f("", !0)
]))), 256)),
q.value < 0 ? (s(), c("line", {
key: 4,
x1: i.value.start,
x2: i.value.start + i.value.width,
y1: n(we)(L.value, i.value.bottom),
y2: n(we)(L.value, i.value.bottom),
stroke: e.value.style.zeroLine.color,
"stroke-dasharray": e.value.style.zeroLine.strokeWidth * 2,
"stroke-width": e.value.style.zeroLine.strokeWidth,
"stroke-linecap": "round"
}, null, 8, At)) : f("", !0),
e.value.style.plot.show ? (s(!0), c(Q, { key: 5 }, ee(d.value, (l, u) => (s(), c("g", null, [
v.value && l.id === v.value.id || x.selectedIndex === u || x.dataset.length === 1 ? (s(), c("circle", {
key: 0,
cx: l.x,
cy: l.y,
r: e.value.style.plot.radius,
fill: l.color,
stroke: e.value.style.plot.stroke,
"stroke-width": e.value.style.plot.strokeWidth
}, null, 8, $t)) : f("", !0)
]))), 256)) : f("", !0),
x.showInfo && e.value.style.dataLabel.show ? (s(), c("text", {
key: 6,
x: e.value.style.dataLabel.position === "left" ? 12 + e.value.style.dataLabel.offsetX : i.value.width + 12 + e.value.style.dataLabel.offsetX,
y: o.value.height / 2 + e.value.style.dataLabel.fontSize / 2.5 + e.value.style.dataLabel.offsetY,
"font-size": e.value.style.dataLabel.fontSize,
"font-weight": e.value.style.dataLabel.bold ? "bold" : "normal",
fill: e.value.style.dataLabel.color
}, T(v.value ? n(ae)(
e.value.style.dataLabel.formatter,
v.value.absoluteValue,
n(le)({ p: e.value.style.dataLabel.prefix, v: v.value.absoluteValue, s: e.value.style.dataLabel.suffix, r: e.value.style.dataLabel.roundingValue }),
{ datapoint: v.value }
) : n(ae)(
e.value.style.dataLabel.formatter,
de.value,
n(le)({ p: e.value.style.dataLabel.prefix, v: de.value, s: e.value.style.dataLabel.suffix, r: e.value.style.dataLabel.roundingValue })
)), 9, Nt)) : f("", !0),
(s(!0), c(Q, null, ee(d.value, (l, u) => (s(), c("rect", {
x: l.x - (i.value.width / (A.value + 1) > o.value.padding ? o.value.padding : i.value.width / (A.value + 1)) / 2,
y: i.value.top - 6,
height: i.value.height + 6,
width: i.value.width / (A.value + 1) > o.value.padding ? o.value.padding : i.value.width / (A.value + 1),
fill: "transparent",
onMouseenter: () => ze(l, u),
onMouseleave: () => De(l, u),
onClick: () => Te(l, u)
}, null, 40, Mt))), 256)),
I(t.$slots, "svg", { svg: o.value }, void 0, !0)
], 44, nt)),
v.value && e.value.style.tooltip.show ? (s(), pe(n(Ne), {
key: 1,
x: v.value.x,
y: v.value.y,
prevX: $.value.x,
prevY: $.value.y,
offsetY: e.value.style.plot.radius * 3 + e.value.style.tooltip.offsetY,
svgRef: n(ne),
background: e.value.style.tooltip.backgroundColor,
color: e.value.style.tooltip.color,
fontSize: e.value.style.tooltip.fontSize,
borderWidth: e.value.style.tooltip.borderWidth,
borderColor: e.value.style.tooltip.borderColor,
borderRadius: e.value.style.tooltip.borderRadius,
backgroundOpacity: e.value.style.tooltip.backgroundOpacity
}, {
default: Ee(() => [
I(t.$slots, "tooltip", ge(me({ ...v.value })), () => [
Oe(T(v.value.period) + ": " + T(n(ae)(
e.value.style.dataLabel.formatter,
v.value.absoluteValue,
n(le)({
p: e.value.style.dataLabel.prefix,
v: v.value.absoluteValue,
s: e.value.style.dataLabel.suffix,
r: e.value.style.dataLabel.roundingValue
}),
{ datapoint: v.value }
)), 1)
], !0)
]),
_: 3
}, 8, ["x", "y", "prevX", "prevY", "offsetY", "svgRef", "background", "color", "fontSize", "borderWidth", "borderColor", "borderRadius", "backgroundOpacity"])) : f("", !0),
t.$slots.source ? (s(), c("div", {
key: 2,
ref_key: "source",
ref: se,
dir: "auto"
}, [
I(t.$slots, "source", {}, void 0, !0)
], 512)) : f("", !0),
n(F) ? (s(), pe(lt, { key: 3 })) : f("", !0)
], 12, st));
}
}, Rt = /* @__PURE__ */ ot(Ct, [["__scopeId", "data-v-12334391"]]);
export {
Rt as default
};