vue-data-ui
Version:
A user-empowering data visualization Vue 3 components library for eloquent data storytelling
542 lines (541 loc) • 22.6 kB
JavaScript
import { useCssVars as ze, computed as c, defineAsyncComponent as j, ref as v, onMounted as We, toRefs as Ue, watch as Le, createElementBlock as u, openBlock as a, unref as n, normalizeStyle as ve, normalizeClass as z, createBlock as W, createCommentVNode as i, createSlots as Ne, withCtx as A, renderSlot as m, normalizeProps as U, guardReactiveProps as L, createVNode as Ye, createElementVNode as d, Fragment as N, renderList as de, toDisplayString as He } from "vue";
import { u as Ee, c as Re, t as Ve, o as qe, f as ye, g as Ge, a as Be, p as F, b as De, d as je, h as f, e as Y, X as Xe, s as Je, k as Ke, i as Qe } from "./index-q-LPw2IT.js";
import { t as Ze, u as et } from "./useResponsive-DfdjqQps.js";
import { u as tt, B as st } from "./useLoading-D7YHNtLX.js";
import { u as ot } from "./usePrinter-DX7efa1s.js";
import { u as me } from "./useNestedProp-04aFeUYu.js";
import { u as lt } from "./useUserOptionState-BIvW1Kz7.js";
import { u as at } from "./useChartAccessibility-9icAAmYg.js";
import { u as rt } from "./useAutoSizeLabelsInsideViewbox-bEAG5sD1.js";
import ut from "./Title-B55R8CAZ.js";
import nt from "./img-Ctts6JQb.js";
import { _ as it } from "./_plugin-vue_export-helper-CHgC5LLL.js";
const ht = ["id"], ct = {
key: 1,
ref: "noTitle",
class: "vue-data-ui-no-title-space",
style: "height:36px; width: 100%;background:transparent"
}, vt = ["xmlns", "viewBox"], dt = ["width", "height"], yt = ["id"], mt = ["x", "y", "width", "height", "rx", "ry"], ft = ["id"], gt = ["stop-color"], pt = ["stop-color"], kt = ["stop-color"], bt = ["clip-path"], xt = ["x", "y", "height", "width"], wt = ["x", "y", "height", "width", "fill"], _t = ["x1", "x2", "y1", "y2", "stroke-width", "stroke"], Ct = ["x1", "x2", "y1", "y2", "stroke-width", "stroke"], $t = ["x1", "x2", "y1", "y2", "stroke-width", "stroke"], At = ["x1", "x2", "y1", "y2", "stroke-width", "stroke"], Ft = ["x1", "x2", "y1", "y2", "stroke-width", "stroke"], Ot = ["x1", "x2", "y1", "y2", "stroke-width", "stroke"], It = ["x1", "x2", "y1", "y2", "stroke-width", "stroke"], Pt = ["x1", "x2", "y1", "y2", "stroke-width", "stroke"], St = ["x", "y", "height", "width"], Mt = { key: 1 }, Tt = ["x", "y", "height"], zt = ["y", "x", "fill", "font-size", "font-weight"], Wt = {
key: 4,
class: "vue-data-ui-watermark"
}, Ut = {
__name: "vue-ui-thermometer",
props: {
dataset: {
type: Object,
default() {
return {};
}
},
config: {
type: Object,
default() {
return {};
}
}
},
setup(O, { expose: fe }) {
ze((s) => ({
25439570: Fe.value,
"6fd0a11e": Ae.value,
"1ea034ea": $e.value
}));
const ge = j(() => import("./PackageVersion-5ZjKSIei.js")), pe = j(() => import("./PenAndPaper-BJ0hcgsa.js")), ke = j(() => import("./UserOptions-DVzyjG-W.js")), { vue_ui_thermometer: be } = Ee(), g = O, p = v(Re()), k = v(null), X = v(0), J = v(0), K = v(null), Q = v(null), b = v(null), I = v(null), xe = c(() => !!g.dataset && Object.keys(g.dataset).length);
We(() => {
te();
});
const e = v(q()), we = v(e.value.style.chart.thermometer.width), H = v(e.value.style.chart.height), E = v(e.value.style.chart.width), { loading: Z, FINAL_DATASET: h } = tt({
...Ue(g),
FINAL_CONFIG: e,
prepareConfig: q,
skeletonDataset: { value: 0, from: -100, to: 100, steps: 20, colors: { from: "#A1A1A1", to: "#CACACA" } },
skeletonConfig: Ve({
defaultConfig: e.value,
userConfig: {
userOptions: { show: !1 },
style: {
chart: {
animation: { use: !1 },
backgroundColor: "#99999930",
graduations: {
stroke: "#6A6A6A"
}
}
}
}
})
}), ee = c(() => !!e.value.debug);
function te() {
if (qe(g.dataset) ? ye({
componentName: "VueUiThermometer",
type: "dataset",
debug: ee.value
}) : Ge({
datasetObject: g.dataset,
requiredAttributes: ["value", "from", "to"]
}).forEach((s) => {
ye({
componentName: "VueUiThermometer",
type: "datasetAttribute",
property: s,
debug: ee.value
});
}), e.value.responsive) {
const s = Ze(() => {
const { width: l, height: t } = et({
chart: k.value,
title: e.value.style.title.text ? K.value : null,
source: Q.value
});
requestAnimationFrame(() => {
H.value = Math.max(0.1, t - 12), E.value = l, ce();
});
});
b.value && (I.value && b.value.unobserve(I.value), b.value.disconnect()), b.value = new ResizeObserver(s), I.value = k.value, b.value.observe(I.value);
}
ce();
}
const { userOptionsVisible: R, setUserOptionsVisibility: se, keepUserOptionState: oe } = lt({ config: e.value }), { svgRef: V } = at({ config: e.value.style.title });
function q() {
const s = me({
userConfig: g.config,
defaultConfig: be
});
return s.theme ? {
...me({
userConfig: De.vue_ui_thermometer[s.theme] || g.config,
defaultConfig: s
}),
customPalette: Be[s.theme] || F
} : s;
}
Le(() => g.config, (s) => {
e.value = q(), R.value = !e.value.userOptions.showOnChartHover, we.value = e.value.style.chart.thermometer.width, H.value = e.value.style.chart.height, E.value = e.value.style.chart.width, te(), J.value += 1;
}, { deep: !0 });
const { isPrinting: le, isImaging: ae, generatePdf: re, generateImage: ue } = ot({
elementId: `thermometer__${p.value}`,
fileName: e.value.style.title.text || "vue-ui-thermometer",
options: e.value.userOptions.print
}), _e = c(() => e.value.userOptions.show && !e.value.style.title.text), P = c(() => je(e.value.customPalette)), y = c(() => h.value.steps || 10);
function S(s, l, t) {
const r = [], _ = ne(s), C = ne(l);
for (let $ = 0; $ < t; $++) {
const Pe = G(_.red, C.red, $, t), Se = G(_.green, C.green, $, t), Me = G(_.blue, C.blue, $, t), Te = `#${B(Pe)}${B(Se)}${B(Me)}`;
r.push(Te);
}
return r;
}
function ne(s) {
const l = s.slice(1);
return {
red: parseInt(l.slice(0, 2), 16),
green: parseInt(l.slice(2, 4), 16),
blue: parseInt(l.slice(4, 6), 16)
};
}
function G(s, l, t, r) {
return Math.round(s + (l - s) * t / r);
}
function B(s) {
return s.toString(16).padStart(2, "0");
}
const o = c(() => {
const s = Math.max(0.1, E.value), l = Math.max(0.1, H.value), t = e.value.style.chart.padding;
return {
width: s,
left: s / 2 - e.value.style.chart.thermometer.width / 2,
right: s / 2 + e.value.style.chart.thermometer.width / 2,
top: t.top,
bottom: l - t.bottom - t.top,
height: l,
thermoHeight: l - t.top - t.bottom,
thermoWidth: e.value.style.chart.thermometer.width
};
}), Ce = c(() => o.value), M = c(() => {
const s = f(h.value.from) < 0 ? Math.abs(f(h.value.from)) : f(h.value.from), l = f(h.value.to) < 0 ? Math.abs(f(h.value.to)) : f(h.value.to);
let t = 0;
return f(h.value.to) > 0 ? t = s + l : s > l ? t = s - l : t = l - s, (1 - (Math.abs(f(h.value.from)) + f(h.value.value)) / t) * o.value.thermoHeight;
}), $e = c(() => `${M.value}px`), Ae = c(() => `${o.value.thermoHeight}px`), Fe = c(() => `${e.value.style.chart.animation.speedMs}ms`), Oe = c(() => {
if (h.value.colors) {
if (!h.value.colors.from)
return S(P.value[0] || F[0], Y(h.value.colors.to), y.value || 10);
if (!h.value.colors.to)
return S(Y(h.value.colors.from), P.value[1] || F[1], y.value || 10);
} else
return S(P.value[1] || F[1], P.value[0] || F[0], y.value || 10);
return S(Y(h.value.colors.from), Y(h.value.colors.to), y.value || 10);
}), ie = c(() => {
const s = [];
let l = 0;
const t = o.value.thermoHeight;
for (let r = 0; r < t - 1; r += t / y.value)
s.push({
x: o.value.left,
y: o.value.top + r,
qYLess: o.value.top + r + t / y.value / 4,
halfY: o.value.top + r + t / y.value / 2,
qYMore: o.value.top + r + t / y.value / 4 * 3,
color: Oe.value[l],
height: Math.max(0.1, t / y.value)
}), l += 1;
return s;
}), x = v(!1);
function he(s) {
x.value = s, X.value += 1;
}
const T = v(!1);
function D() {
T.value = !T.value;
}
async function Ie({ scale: s = 2 } = {}) {
if (!k.value) return;
const { width: l, height: t } = k.value.getBoundingClientRect(), r = l / t, { imageUri: _, base64: C } = await nt({ domElement: k.value, base64: !0, img: !0, scale: s });
return {
imageUri: _,
base64: C,
title: e.value.style.title.text,
width: l,
height: t,
aspectRatio: r
};
}
const w = c({
get: () => e.value.style.chart.label.fontSize,
set: (s) => s
}), { autoSizeLabels: ce } = rt({
svgRef: V,
fontSize: e.value.style.chart.label.fontSize,
minFontSize: e.value.style.chart.label.minFontSize,
sizeRef: w,
labelClass: ".vue-ui-thermometer-label"
});
return fe({
getImage: Ie,
generatePdf: re,
generateImage: ue,
toggleAnnotator: D,
toggleFullscreen: he
}), (s, l) => (a(), u("div", {
ref_key: "thermoChart",
ref: k,
class: z(`vue-ui-thermometer ${x.value ? "vue-data-ui-wrapper-fullscreen" : ""}`),
style: ve(`width:100%;background:${e.value.style.chart.backgroundColor};color:${e.value.style.chart.color};font-family:${e.value.style.fontFamily}`),
id: `thermometer__${p.value}`,
onMouseenter: l[0] || (l[0] = () => n(se)(!0)),
onMouseleave: l[1] || (l[1] = () => n(se)(!1))
}, [
e.value.userOptions.buttons.annotator ? (a(), W(n(pe), {
key: 0,
svgRef: n(V),
backgroundColor: e.value.style.chart.backgroundColor,
color: e.value.style.chart.color,
active: T.value,
onClose: D
}, null, 8, ["svgRef", "backgroundColor", "color", "active"])) : i("", !0),
_e.value ? (a(), u("div", ct, null, 512)) : i("", !0),
e.value.style.title.text ? (a(), u("div", {
key: 2,
ref_key: "chartTitle",
ref: K,
style: "width:100%"
}, [
(a(), W(ut, {
key: `title_${J.value}`,
config: {
title: {
cy: "thermometer-div-title",
...e.value.style.title
},
subtitle: {
cy: "thermometer-div-subtitle",
...e.value.style.title.subtitle
}
}
}, null, 8, ["config"]))
], 512)) : i("", !0),
e.value.userOptions.show && xe.value && (n(oe) || n(R)) ? (a(), W(n(ke), {
ref: "details",
key: `user_options_${X.value}`,
backgroundColor: e.value.style.chart.backgroundColor,
color: e.value.style.chart.color,
isImaging: n(ae),
isPrinting: n(le),
uid: p.value,
hasPdf: e.value.userOptions.buttons.pdf,
hasImg: e.value.userOptions.buttons.img,
hasFullscreen: e.value.userOptions.buttons.fullscreen,
hasXls: !1,
isFullscreen: x.value,
titles: { ...e.value.userOptions.buttonTitles },
chartElement: k.value,
position: e.value.userOptions.position,
hasAnnotator: e.value.userOptions.buttons.annotator,
isAnnotation: T.value,
callbacks: e.value.userOptions.callbacks,
printScale: e.value.userOptions.print.scale,
onToggleFullscreen: he,
onGeneratePdf: n(re),
onGenerateImage: n(ue),
onToggleAnnotator: D,
style: ve({
visibility: n(oe) ? n(R) ? "visible" : "hidden" : "visible"
})
}, Ne({ _: 2 }, [
s.$slots.menuIcon ? {
name: "menuIcon",
fn: A(({ isOpen: t, color: r }) => [
m(s.$slots, "menuIcon", U(L({ isOpen: t, color: r })), void 0, !0)
]),
key: "0"
} : void 0,
s.$slots.optionPdf ? {
name: "optionPdf",
fn: A(() => [
m(s.$slots, "optionPdf", {}, void 0, !0)
]),
key: "1"
} : void 0,
s.$slots.optionImg ? {
name: "optionImg",
fn: A(() => [
m(s.$slots, "optionImg", {}, void 0, !0)
]),
key: "2"
} : void 0,
s.$slots.optionFullscreen ? {
name: "optionFullscreen",
fn: A(({ toggleFullscreen: t, isFullscreen: r }) => [
m(s.$slots, "optionFullscreen", U(L({ toggleFullscreen: t, isFullscreen: r })), void 0, !0)
]),
key: "3"
} : void 0,
s.$slots.optionAnnotator ? {
name: "optionAnnotator",
fn: A(({ toggleAnnotator: t, isAnnotator: r }) => [
m(s.$slots, "optionAnnotator", U(L({ toggleAnnotator: t, isAnnotator: r })), void 0, !0)
]),
key: "4"
} : void 0
]), 1032, ["backgroundColor", "color", "isImaging", "isPrinting", "uid", "hasPdf", "hasImg", "hasFullscreen", "isFullscreen", "titles", "chartElement", "position", "hasAnnotator", "isAnnotation", "callbacks", "printScale", "onGeneratePdf", "onGenerateImage", "style"])) : i("", !0),
(a(), u("svg", {
ref_key: "svgRef",
ref: V,
xmlns: n(Xe),
class: z({ "vue-data-ui-fullscreen--on": x.value, "vue-data-ui-fulscreen--off": !x.value }),
width: "100%",
viewBox: `0 0 ${o.value.width} ${o.value.height}`,
style: "background:transparent"
}, [
Ye(n(ge)),
s.$slots["chart-background"] ? (a(), u("foreignObject", {
key: 0,
x: 0,
y: 0,
width: o.value.width,
height: o.value.height,
style: {
pointerEvents: "none"
}
}, [
m(s.$slots, "chart-background", {}, void 0, !0)
], 8, dt)) : i("", !0),
d("defs", null, [
d("clipPath", {
id: `vueUiPill-${p.value}`,
clipPathUnits: "userSpaceOnUse"
}, [
d("rect", {
x: o.value.left,
y: o.value.top,
width: o.value.thermoWidth,
height: o.value.thermoHeight,
rx: o.value.thermoWidth / 2,
ry: o.value.thermoWidth / 2
}, null, 8, mt)
], 8, yt),
(a(!0), u(N, null, de(ie.value, (t, r) => (a(), u("linearGradient", {
id: `vueUiThermometerGradient_${r}_${p.value}`,
x1: "0%",
y1: "0%",
x2: "100%",
y2: "0%"
}, [
d("stop", {
offset: "0%",
"stop-color": t.color
}, null, 8, gt),
d("stop", {
offset: "50%",
"stop-color": n(Je)(t.color, 100 - e.value.style.chart.graduations.gradient.intensity)
}, null, 8, pt),
d("stop", {
offset: "100%",
"stop-color": t.color
}, null, 8, kt)
], 8, ft))), 256))
]),
d("g", {
"clip-path": `url(#vueUiPill-${p.value})`
}, [
d("rect", {
x: o.value.left,
y: o.value.top,
height: o.value.thermoHeight,
width: o.value.thermoWidth,
fill: "#FFFFFF"
}, null, 8, xt),
(a(!0), u(N, null, de(ie.value, (t, r) => (a(), u("g", {
key: `graduation_${r}`
}, [
d("rect", {
x: t.x,
y: t.y,
height: t.height,
width: o.value.thermoWidth,
fill: e.value.style.chart.graduations.gradient.show ? `url(#vueUiThermometerGradient_${r}_${p.value})` : t.color,
"shape-rendering": "crispEdges"
}, null, 8, wt),
e.value.style.chart.graduations.show && ["both", "left"].includes(e.value.style.chart.graduations.sides) ? (a(), u("line", {
key: 0,
x1: t.x,
x2: t.x + 10,
y1: t.y,
y2: t.y,
"stroke-width": e.value.style.chart.graduations.strokeWidth,
stroke: e.value.style.chart.graduations.stroke,
"stroke-linecap": "round"
}, null, 8, _t)) : i("", !0),
e.value.style.chart.graduations.showIntermediate ? (a(), u(N, { key: 1 }, [
e.value.style.chart.graduations.show && ["both", "left"].includes(e.value.style.chart.graduations.sides) ? (a(), u("line", {
key: 0,
x1: t.x,
x2: t.x + 5,
y1: t.halfY,
y2: t.halfY,
"stroke-width": e.value.style.chart.graduations.strokeWidth / 2,
stroke: e.value.style.chart.graduations.stroke,
"stroke-linecap": "round"
}, null, 8, Ct)) : i("", !0),
e.value.style.chart.graduations.show && ["both", "left"].includes(e.value.style.chart.graduations.sides) ? (a(), u("line", {
key: 1,
x1: t.x,
x2: t.x + 2.5,
y1: t.qYLess,
y2: t.qYLess,
"stroke-width": e.value.style.chart.graduations.strokeWidth / 2,
stroke: e.value.style.chart.graduations.stroke,
"stroke-linecap": "round"
}, null, 8, $t)) : i("", !0),
e.value.style.chart.graduations.show && ["both", "left"].includes(e.value.style.chart.graduations.sides) ? (a(), u("line", {
key: 2,
x1: t.x,
x2: t.x + 2.5,
y1: t.qYMore,
y2: t.qYMore,
"stroke-width": e.value.style.chart.graduations.strokeWidth / 2,
stroke: e.value.style.chart.graduations.stroke,
"stroke-linecap": "round"
}, null, 8, At)) : i("", !0)
], 64)) : i("", !0),
e.value.style.chart.graduations.show && ["both", "right"].includes(e.value.style.chart.graduations.sides) ? (a(), u("line", {
key: 2,
x1: o.value.right,
x2: o.value.right - 10,
y1: t.y,
y2: t.y,
"stroke-width": e.value.style.chart.graduations.strokeWidth,
stroke: e.value.style.chart.graduations.stroke,
"stroke-linecap": "round"
}, null, 8, Ft)) : i("", !0),
e.value.style.chart.graduations.showIntermediate ? (a(), u(N, { key: 3 }, [
e.value.style.chart.graduations.show && ["both", "right"].includes(e.value.style.chart.graduations.sides) ? (a(), u("line", {
key: 0,
x1: o.value.right,
x2: o.value.right - 5,
y1: t.halfY,
y2: t.halfY,
"stroke-width": e.value.style.chart.graduations.strokeWidth / 2,
stroke: e.value.style.chart.graduations.stroke,
"stroke-linecap": "round"
}, null, 8, Ot)) : i("", !0),
e.value.style.chart.graduations.show && ["both", "right"].includes(e.value.style.chart.graduations.sides) ? (a(), u("line", {
key: 1,
x1: o.value.right,
x2: o.value.right - 2.5,
y1: t.qYLess,
y2: t.qYLess,
"stroke-width": e.value.style.chart.graduations.strokeWidth / 2,
stroke: e.value.style.chart.graduations.stroke,
"stroke-linecap": "round"
}, null, 8, It)) : i("", !0),
e.value.style.chart.graduations.show && ["both", "right"].includes(e.value.style.chart.graduations.sides) ? (a(), u("line", {
key: 2,
x1: o.value.right,
x2: o.value.right - 2.5,
y1: t.qYMore,
y2: t.qYMore,
"stroke-width": e.value.style.chart.graduations.strokeWidth / 2,
stroke: e.value.style.chart.graduations.stroke,
"stroke-linecap": "round"
}, null, 8, Pt)) : i("", !0)
], 64)) : i("", !0)
]))), 128)),
d("rect", {
class: z({ "vue-ui-thermometer-temperature": e.value.style.chart.animation.use }),
x: o.value.left,
y: o.value.top,
height: M.value,
width: o.value.thermoWidth,
fill: "#FFFFFF66"
}, null, 10, St)
], 8, bt),
e.value.style.chart.label.show ? (a(), u("g", Mt, [
n(Z) ? (a(), u("rect", {
key: 0,
x: o.value.left - 60,
y: M.value + o.value.top - w.value / 2,
width: 50,
height: w.value,
fill: "#6A6A6A40",
rx: "3"
}, null, 8, Tt)) : (a(), u("text", {
key: 1,
class: z({ "vue-ui-thermometer-temperature-value": e.value.style.chart.animation.use, "vue-ui-thermometer-label": !0 }),
y: M.value + o.value.top + w.value / 3,
x: o.value.left - 10,
"text-anchor": "end",
fill: e.value.style.chart.label.color,
"font-size": w.value,
"font-weight": e.value.style.chart.label.bold ? "bold" : "normal"
}, He(n(Ke)(
e.value.style.chart.label.formatter,
O.dataset.value,
n(Qe)({
p: e.value.style.chart.label.prefix,
v: O.dataset.value,
s: e.value.style.chart.label.suffix,
r: e.value.style.chart.label.rounding
}),
{ datapoint: O.dataset }
)), 11, zt))
])) : i("", !0),
m(s.$slots, "svg", { svg: Ce.value }, void 0, !0)
], 10, vt)),
s.$slots.watermark ? (a(), u("div", Wt, [
m(s.$slots, "watermark", U(L({ isPrinting: n(le) || n(ae) })), void 0, !0)
])) : i("", !0),
s.$slots.source ? (a(), u("div", {
key: 5,
ref_key: "source",
ref: Q,
dir: "auto"
}, [
m(s.$slots, "source", {}, void 0, !0)
], 512)) : i("", !0),
n(Z) ? (a(), W(st, { key: 6 })) : i("", !0)
], 46, ht));
}
}, Xt = /* @__PURE__ */ it(Ut, [["__scopeId", "data-v-0a386d4f"]]);
export {
Xt as default
};