vue-data-ui
Version:
A user-empowering data visualization Vue 3 components library for eloquent data storytelling
1,259 lines (1,258 loc) • 42.7 kB
JavaScript
import { t as e } from "./rolldown-runtime-Dy4uBu1J.js";
import { $ as t, D as n, Jt as r, Kt as i, Pt as a, S as o, X as s, ct as ee, i as te, jt as ne, q as re, t as ie, tt as ae, w as oe, xt as se } from "./lib-Bttd6u5E.js";
import { n as ce, t as le } from "./useHints-Dq_w2E8B.js";
import { t as ue } from "./useConfig-D3scuR88.js";
import { t as de } from "./usePrinter-DN5bYhTG.js";
import { n as fe, t as pe } from "./BaseScanner-DZvpgOjM.js";
import { t as me } from "./useSvgExport-DH-FfcqQ.js";
import { t as he } from "./useNestedProp-vPNvh7rV.js";
import { t as ge } from "./useThemeCheck-C43Tcqmk.js";
import { t as _e } from "./useTransitions-g_zBREk2.js";
import { t as ve } from "./img-Bnokohej.js";
import { n as ye } from "./Title-BE3qg9xl.js";
import { t as be } from "./_plugin-vue_export-helper-B3ysoDQm.js";
import { l as xe, t as Se } from "./useResponsive-ZtArZtUf.js";
import { t as Ce } from "./BaseLegendToggle-DZVucLnv.js";
import { t as we } from "./A11yDataTable-DdRsVULz.js";
import { t as Te } from "./useUserOptionState-DK-_1ddE.js";
import { t as Ee } from "./useChartAccessibility-DYqac8yF.js";
import { t as De } from "./labelUtils-BeVpDvTJ.js";
import { t as Oe } from "./Legend-CQxUgOd-.js";
import { t as ke } from "./useAutoSizeLabelsInsideViewbox-DvDwcwi_.js";
import { t as Ae } from "./vue_ui_onion-1FTFFS46.js";
import { Fragment as je, Teleport as Me, computed as c, createBlock as l, createCommentVNode as u, createElementBlock as d, createElementVNode as f, createSlots as Ne, createTextVNode as Pe, createVNode as Fe, defineAsyncComponent as p, guardReactiveProps as m, mergeProps as Ie, nextTick as Le, normalizeClass as h, normalizeProps as g, normalizeStyle as _, onBeforeUnmount as Re, onMounted as ze, openBlock as v, ref as y, renderList as Be, renderSlot as b, resolveDynamicComponent as Ve, shallowRef as He, toDisplayString as x, toRefs as Ue, unref as S, watch as C, withCtx as w } from "vue";
//#region src/components/vue-ui-onion.vue
var We = /* @__PURE__ */ e({ default: () => ft }), Ge = ["id"], Ke = ["id"], qe = ["id"], Je = { style: { position: "relative" } }, Ye = [
"xmlns",
"aria-describedby",
"viewBox"
], Xe = ["width", "height"], Ze = [
"cx",
"cy",
"r",
"stroke",
"stroke-width",
"stroke-dasharray",
"stroke-dashoffset"
], Qe = [
"cx",
"cy",
"r",
"stroke",
"stroke-width",
"stroke-dasharray",
"stroke-dashoffset"
], $e = ["id"], et = ["stdDeviation"], tt = ["filter"], nt = [
"cx",
"cy",
"r",
"stroke-width",
"stroke-dasharray",
"stroke-dashoffset"
], rt = [
"cx",
"cy",
"r",
"stroke-width",
"stroke-dasharray",
"stroke-dashoffset",
"onMouseenter",
"onMouseleave",
"onClick"
], it = { key: 2 }, at = [
"onMouseenter",
"onMouseleave",
"onClick"
], ot = [
"transform",
"font-size",
"fill",
"font-weight"
], st = {
key: 0,
style: {
position: "absolute",
top: "100%",
left: "0",
width: "100%"
},
"data-dom-to-png-ignore": "",
"aria-hidden": "true"
}, ct = {
key: 5,
class: "vue-data-ui-watermark"
}, lt = ["id"], ut = ["onClick"], dt = ["innerHTML"], ft = /*#__PURE__*/ be({
__name: "vue-ui-onion",
props: {
config: {
type: Object,
default() {
return {};
}
},
dataset: {
type: Array,
default() {
return [];
}
}
},
emits: ["selectLegend", "copyAlt"],
setup(e, { expose: be, emit: We }) {
let ft = p(() => import("./Tooltip-DhjyfHwz.js")), pt = p(() => import("./BaseIcon-BfndwIWE.js").then((e) => e.n)), mt = p(() => import("./vue-ui-accordion-BxGriZik.js").then((e) => e.n)), ht = p(() => import("./DataTable-BbKgJ5UI.js")), gt = p(() => import("./UserOptions-Dt98of5H.js").then((e) => e.n)), _t = p(() => import("./PenAndPaper-DAE-tnEQ.js").then((e) => e.t)), vt = p(() => import("./PackageVersion-D6d8SCp9.js").then((e) => e.t)), yt = p(() => import("./BaseDraggableDialog-LoqqwRtV.js").then((e) => e.n)), { vue_ui_onion: bt } = ue(), { isThemeValid: xt, warnInvalidTheme: St } = ge(), T = e, Ct = c(() => !!T.dataset && T.dataset.length), E = y(re()), wt = y(null), Tt = y(0), Et = y(!1), Dt = y(""), D = y([]), O = y(null), Ot = y(null), kt = y(null), At = y(null), jt = y(null), Mt = y(0), Nt = y(0), Pt = y(0), k = y(!1), Ft = y(!1), A = y(null), It = y(!1), Lt = y(!1), j = y(null), Rt = y({
x: 0,
y: 0
}), zt = y("pointer"), Bt = y(!1), M = y(qt());
ce({
config: () => M.value,
dataset: () => T.dataset,
component: "VueUiOnion",
rules: [le.emptyArray, {
test: (e) => e.length > 8,
message: [
"👀 The number of series is > 8. Consider:",
"",
"▶️ Grouping small values dynamically into a single \"Other\" series.",
"",
"▶️ Using filters to let users choose a maximum number of series to display.",
"",
"▶️ Using VueUiHorizontalBar instead to make the dataset breakdown easier to read."
]
}]
});
let { transitionEnabled: N } = _e({
config: () => M.value.transitions,
dataset: () => T.dataset
}), P = c(() => M.value.userOptions.useCursorPointer), Vt = c(() => r({
defaultConfig: {
userOptions: { show: !1 },
table: { show: !1 },
style: { chart: {
backgroundColor: "#99999930",
layout: {
gutter: { color: "#99999950" },
labels: { show: !1 }
},
legend: { backgroundColor: "transparent" }
} }
},
userConfig: M.value.skeletonConfig ?? {}
})), { loading: F, FINAL_DATASET: Ht, manualLoading: Ut } = fe({
...Ue(T),
FINAL_CONFIG: M,
prepareConfig: qt,
callback: () => {
Promise.resolve().then(async () => {
await Le(), pn();
});
},
skeletonDataset: T.config?.skeletonDataset ?? [
{
name: "_",
percentage: 50,
value: 1,
color: "#DBDBDB"
},
{
name: "_",
percentage: 50,
value: 1,
color: "#C4C4C4"
},
{
name: "_",
percentage: 50,
value: 1,
color: "#ADADAD"
},
{
name: "_",
percentage: 50,
value: 1,
color: "#969696"
}
],
skeletonConfig: r({
defaultConfig: M.value,
userConfig: Vt.value
})
}), { userOptionsVisible: Wt, setUserOptionsVisibility: Gt, keepUserOptionState: Kt } = Te({ config: M.value }), { svgRef: I } = Ee({ config: M.value.style.chart.title });
function qt() {
let e = he({
userConfig: T.config,
defaultConfig: bt
}), t = e.theme;
if (!t) return e;
if (!xt.value(e)) return St(e), e;
let n = he({
userConfig: Ae[t] || T.config,
defaultConfig: e
}), r = he({
userConfig: T.config,
defaultConfig: n
});
return {
...r,
customPalette: r.customPalette.length ? r.customPalette : i[t] || a
};
}
C(() => T.config, (e) => {
F.value || (M.value = qt()), Wt.value = !M.value.userOptions.showOnChartHover, cn(), Mt.value += 1, Nt.value += 1, Pt.value += 1, L.value.showTable = M.value.table.show, L.value.showTooltip = M.value.style.chart.tooltip.show;
}, { deep: !0 });
let { isPrinting: Jt, isImaging: Yt, generatePdf: Xt, generateImage: Zt } = de({
elementId: `vue-ui-onion_${E.value}`,
fileName: M.value.style.chart.title.text || "vue-ui-onion",
options: M.value.userOptions.print
}), Qt = c(() => M.value.userOptions.show && !M.value.style.chart.title.text), $t = c(() => oe(M.value.customPalette)), L = y({
showTable: M.value.table.show,
showTooltip: M.value.style.chart.tooltip.show
});
C(M, () => {
L.value = {
showTable: M.value.table.show,
showTooltip: M.value.style.chart.tooltip.show
};
}, { immediate: !0 });
let R = y({
height: 512,
width: 512,
padding: {
top: 64,
left: 64,
right: 64,
bottom: 64
},
minRadius: 64
}), z = He(null), B = He(null);
ze(() => {
Ft.value = !0, cn();
});
let { autoSizeLabels: en } = ke({
svgRef: I,
fontSize: () => M.value.style.chart.layout.labels.fontSize,
minFontSize: () => M.value.style.chart.layout.labels.minFontSize,
labelClass: ".vue-ui-onion-label"
}), V = null, H = null, U = 0;
function tn() {
V !== null && (cancelAnimationFrame(V), V = null), H !== null && (clearTimeout(H), H = null);
}
function nn(e) {
return String(e).split(",").map((e) => {
let t = e.trim(), n = Number.parseFloat(t);
return Number.isFinite(n) ? t.endsWith("ms") ? n : n * 1e3 : 0;
});
}
function rn() {
return typeof window > "u" || !N.value || k.value || F.value || !I.value ? 0 : Array.from(I.value.querySelectorAll(".vue-ui-onion-label.vue-data-ui-transition")).reduce((e, t) => {
let n = window.getComputedStyle(t);
if (n.transitionProperty === "none") return e;
let r = nn(n.transitionDuration), i = nn(n.transitionDelay), a = Math.max(r.length, i.length), o = Array.from({ length: a }, (e, t) => (r[t % r.length] ?? 0) + (i[t % i.length] ?? 0)).reduce((e, t) => Math.max(e, t), 0);
return Math.max(e, o);
}, 0);
}
function an() {
typeof window > "u" || (V = requestAnimationFrame(() => {
V = null, en();
}));
}
function W() {
if (typeof window > "u") return;
let e = ++U;
tn(), Le(() => {
e === U && (V = requestAnimationFrame(() => {
if (V = null, e !== U) return;
let t = rn();
if (t <= 0) {
an();
return;
}
H = setTimeout(() => {
H = null, e === U && an();
}, t + 34);
}));
});
}
let on = c(() => M.value.debug), sn = null;
function cn() {
if (ne(T.dataset) && (ae({
componentName: "VueUiOnion",
type: "dataset",
debug: on.value
}), Ut.value = !0), ne(T.dataset) || (Ut.value = M.value.loading), M.value.responsive) {
let e = 64 / 512, t = xe(() => {
sn && clearTimeout(sn), k.value = !0;
let { width: t, height: n } = Se({
chart: O.value,
title: M.value.style.chart.title.text ? Ot.value : null,
legend: M.value.style.chart.legend.show ? kt.value : null,
source: At.value,
noTitle: jt.value
});
n -= 12, requestAnimationFrame(async () => {
R.value.width = t, R.value.height = n, R.value.padding.top = Math.max(t, n) * e, R.value.padding.right = Math.max(t, n) * e, R.value.padding.bottom = Math.max(t, n) * e, R.value.padding.left = Math.max(t, n) * e, R.value.minRadius = Math.min(t, n) * e, sn = setTimeout(() => {
k.value = !1, W();
}, 0);
});
});
z.value && (B.value && z.value.unobserve(B.value), z.value.disconnect()), z.value = new ResizeObserver(t), B.value = O.value.parentNode, z.value.observe(B.value);
}
W();
}
Re(() => {
U += 1, tn(), z.value && (B.value && z.value.unobserve(B.value), z.value.disconnect());
});
let G = c(() => ({
top: R.value.padding.top,
left: R.value.padding.left,
right: R.value.width - R.value.padding.right,
bottom: R.value.height - R.value.padding.bottom,
centerX: R.value.width / 2,
centerY: R.value.height / 2,
width: R.value.width - R.value.padding.right - R.value.padding.left,
height: R.value.height - R.value.padding.bottom - R.value.padding.top,
minRadius: R.value.minRadius,
maxRadius: Math.min(R.value.width, R.value.height) - R.value.padding.top * 2
})), K = c(() => (Ht.value.forEach((e, t) => {
[null, void 0].includes(e.name) && ae({
componentName: "VueUiOnion",
type: "datasetSerieAttribute",
property: "name",
index: t
}), [void 0].includes(e.percentage) && ae({
componentName: "VueUiOnion",
type: "datasetSerieAttribute",
property: "percentage",
index: t
});
}), Ht.value.map((e, t) => {
let n = `onion_serie_${t}_${E.value}`;
return {
...e,
percentage: e.percentage || 0,
targetPercentage: e.percentage || 0,
color: o(e.color) || $t.value[t] || a[t],
id: n,
shape: "circle",
opacity: D.value.includes(n) ? .5 : 1,
absoluteIndex: t,
segregate: () => yn(n),
isSegregated: D.value.includes(n)
};
}))), q = c(() => K.value.map((e, t) => {
let n = M.value.style.chart.legend.showValue, r = M.value.style.chart.legend.showPercentage, i = kn({
showVal: n,
showPercentage: r,
val: te(M.value.style.chart.layout.labels.value.formatter, e.value, s({
p: e.prefix || "",
v: e.value,
s: e.suffix || "",
r: M.value.style.chart.legend.roundingValue
})),
percentage: s({
v: e.percentage ?? 0,
s: "%",
r: M.value.style.chart.legend.roundingPercentage
}),
config: M.value.style.chart.legend
});
return {
...e,
display: `${e.name}${n || r ? ": " : ""}${i}`
};
})), J = y(K.value), ln = c(() => M.value.useStartAnimation), un = y(null), dn = c(() => Math.max(...K.value.map((e) => e.percentage))), fn = y(!1);
C(() => K.value, pn, {
immediate: !0,
deep: !0
}), C(() => T.dataset, (e) => {
Array.isArray(e) && e.length > 0 && (Ut.value = !1), W();
}, {
deep: !0,
flush: "post"
});
function pn() {
if (ln.value && !fn.value && !F.value) {
J.value = K.value.map((e) => ({
...e,
percentage: 0
}));
let e = 0;
function t() {
e >= dn.value ? (cancelAnimationFrame(un.value), J.value = K.value, fn.value = !0) : (J.value = K.value.map((t) => ({
...t,
percentage: e < t.targetPercentage ? e : t.targetPercentage
})), e += 1, requestAnimationFrame(t), fn.value = !0);
}
t();
} else J.value = K.value;
}
let mn = c(() => ({
cy: "onion-div-legend",
backgroundColor: M.value.style.chart.legend.backgroundColor,
color: M.value.style.chart.legend.color,
fontSize: M.value.style.chart.legend.fontSize,
paddingBottom: 12,
fontWeight: M.value.style.chart.legend.bold ? "bold" : ""
})), hn = c(() => K.value.filter((e) => !D.value.includes(e.id)).length), Y = c(() => {
let e = Math.min(G.value.width, G.value.height) / 2 / K.value.length;
return {
gutter: (e > M.value.style.chart.layout.maxThickness ? M.value.style.chart.layout.maxThickness : e) * M.value.style.chart.layout.gutter.width,
track: (e > M.value.style.chart.layout.maxThickness ? M.value.style.chart.layout.maxThickness : e) * M.value.style.chart.layout.track.width
};
}), X = c(() => J.value.filter((e) => !D.value.includes(e.id)).map((e, t) => {
let n = (G.value.maxRadius - Y.value.track) / hn.value / 2 * (1 + t), r = G.value.centerY - n;
return {
percentage: e.percentage || 0,
...e,
labelY: r,
radius: n,
path: gn(n, e.percentage || 0)
};
}));
function gn(e, t) {
let n = 2 * Math.PI * e, r = n * .75, i = `${r} ${n}`, a = r * (1 - t / 100);
return {
bgDashArray: `${r} ${n}`,
bgDashOffset: 0,
dashArray: i,
dashOffset: a,
fullOffset: 0,
active: `
M ${G.value.centerX},${G.value.centerY - e}
A ${e},${e} 0 1 1
${G.value.centerX + e * Math.cos(Math.PI * 3 / 4)},${G.value.centerY + e * Math.sin(Math.PI * 3 / 4)}
`.trim()
};
}
let _n = We;
function vn() {
D.value.length ? D.value = [] : q.value.forEach((e) => {
D.value.push(e.id);
}), W(), _n("selectLegend", X.value);
}
function yn(e) {
if (D.value.includes(e)) D.value = D.value.filter((t) => t !== e);
else {
if (D.value.length === K.value.length - 1) return;
D.value.push(e);
}
W(), _n("selectLegend", X.value);
}
function bn(e) {
return K.value.length ? K.value.find((t) => t.name === e) || (M.value.debug && console.warn(`VueUiOnion - Series name not found "${e}"`), null) : (M.value.debug && console.warn("VueUiOnion - There are no series to show."), null);
}
function xn(e) {
let t = bn(e);
t !== null && D.value.includes(t.id) && yn(t.id);
}
function Sn(e) {
let t = bn(e);
t !== null && (D.value.includes(t.id) || yn(t.id));
}
function Cn() {
return X.value;
}
let wn = c(() => ({
head: [
M.value.table.translations.serie,
M.value.table.translations.percentage,
M.value.table.translations.value
],
body: X.value.map((e) => [
e.name,
e.percentage,
e.value
])
})), Z = c(() => {
let e = wn.value.head;
return {
head: e,
body: X.value.map((e) => [
`<span style="color:${e.color}" aria-hidden="true">⬤</span> ${e.name}`,
`${Number(e.percentage ?? 0).toFixed(M.value.table.td.roundingPercentage).toLocaleString()}%`,
`${e.prefix || ""}${[
null,
void 0,
NaN,
"NaN"
].includes(e.value) ? "-" : e.value.toFixed(M.value.table.td.roundingValue).toLocaleString()}${e.suffix || ""}`
]),
config: {
th: {
backgroundColor: M.value.table.th.backgroundColor,
color: M.value.table.th.color,
outline: M.value.table.th.outline
},
td: {
backgroundColor: M.value.table.td.backgroundColor,
color: M.value.table.td.color,
outline: M.value.table.td.outline
},
breakpoint: M.value.table.responsiveBreakpoint
},
colNames: e
};
});
function Tn(e = null) {
Le(() => {
let r = [
[M.value.style.chart.title.text],
[M.value.style.chart.title.subtitle.text],
[""]
], i = wn.value.head, a = wn.value.body, o = r.concat([i]).concat(a), s = n(o);
e ? e(s) : t({
csvContent: s,
title: M.value.style.chart.title.text || "vue-ui-onion"
});
});
}
let Q = y(void 0), $ = y(!1);
function En(e) {
$.value = e, Tt.value += 1;
}
function Dn({ datapoint: e }) {
M.value.events.datapointClick && M.value.events.datapointClick({
datapoint: e,
seriesIndex: e.absoluteIndex
});
}
function On({ datapoint: e }) {
Q.value = void 0, Et.value = !1, j.value = null, zt.value = "pointer", M.value.events.datapointLeave && M.value.events.datapointLeave({
datapoint: e,
seriesIndex: e.absoluteIndex
});
}
function kn({ val: e, percentage: t, showVal: n, showPercentage: r, config: i }) {
return De({
config: i,
val: e,
percentage: t,
showVal: n,
showPercentage: r
});
}
function An(e, t) {
let n = M.value.style.chart.layout.labels.value.show, r = M.value.style.chart.layout.labels.percentage.show, i = kn({
config: M.value.style.chart.layout.labels,
showVal: n,
showPercentage: r,
val: te(M.value.style.chart.layout.labels.value.formatter, e.value, s({
p: e.prefix || "",
v: e.value || 0,
s: e.suffix || "",
r: M.value.style.chart.layout.labels.roundingValue
}), {
datapoint: e,
seriesIndex: t
}),
percentage: s({
v: e.percentage,
s: "%",
r: M.value.style.chart.layout.labels.roundingPercentage
})
});
return `${e.name}${n || r ? ": " : ""}${i}`;
}
let jn = y(null);
function Mn({ datapoint: e, seriesIndex: t, show: n = !0, triggerMode: r = "pointer" }) {
M.value.events.datapointEnter && M.value.events.datapointEnter({
datapoint: e,
seriesIndex: e.absoluteIndex
}), zt.value = r, j.value = t;
let i = e.absoluteIndex;
Q.value = t, jn.value = {
datapoint: e,
seriesIndex: i,
series: K.value,
config: M.value
}, Et.value = n;
let a = "", o = M.value.style.chart.tooltip.customFormat;
if (se(o) && ee(() => o({
seriesIndex: i,
datapoint: e,
series: K.value,
config: M.value
}))) Dt.value = o({
seriesIndex: i,
datapoint: e,
series: K.value,
config: M.value
});
else {
let n = M.value.style.chart.tooltip.showPercentage, r = M.value.style.chart.tooltip.showValue;
a += `<div style="width:100%;text-align:center;border-bottom:1px solid ${M.value.style.chart.tooltip.borderColor};padding-bottom:6px;margin-bottom:3px;">${e.name}</div>`, a += `<div style="display:flex;flex-direction:row;gap:6px;align-items:center;"><svg viewBox="0 0 60 60" height="14" width="14"><circle cx="30" cy="30" r="30" stroke="none" fill="${e.color}"/></svg>`, a += `<b>${kn({
config: M.value.style.chart.tooltip,
showVal: r,
showPercentage: n,
val: `<span>${te(M.value.style.chart.layout.labels.value.formatter, e.value, s({
p: e.prefix || "",
v: e.value,
s: e.suffix || "",
r: M.value.style.chart.tooltip.roundingValue
}), {
datapoint: e,
seriesIndex: t
})}</span>`,
percentage: s({
v: e.percentage,
s: "%",
r: M.value.style.chart.tooltip.roundingPercentage
})
})}</b></div>`, Dt.value = `<div>${a}</div>`;
}
}
function Nn() {
L.value.showTable = !L.value.showTable;
}
function Pn() {
L.value.showTooltip = !L.value.showTooltip;
}
let Fn = y(!1);
function In() {
Fn.value = !Fn.value;
}
async function Ln({ scale: e = 2 } = {}) {
if (!O.value) return;
let { width: t, height: n } = O.value.getBoundingClientRect(), r = t / n, { imageUri: i, base64: a } = await ve({
domElement: O.value,
base64: !0,
img: !0,
scale: e
});
return {
imageUri: i,
base64: a,
title: M.value.style.chart.title.text,
width: t,
height: n,
aspectRatio: r
};
}
let Rn = c(() => {
let e = M.value.table.useDialog && !M.value.table.show, t = L.value.showTable;
return {
component: e ? yt : mt,
title: `${M.value.style.chart.title.text}${M.value.style.chart.title.subtitle.text ? `: ${M.value.style.chart.title.subtitle.text}` : ""}`,
props: e ? {
backgroundColor: M.value.table.th.backgroundColor,
color: M.value.table.th.color,
headerColor: M.value.table.th.color,
headerBg: M.value.table.th.backgroundColor,
isFullscreen: $.value,
fullscreenParent: O.value,
forcedWidth: Math.min(600, window.innerWidth * .8),
isCursorPointer: P.value
} : {
hideDetails: !0,
config: {
open: t,
maxHeight: 1e4,
body: {
backgroundColor: M.value.style.chart.backgroundColor,
color: M.value.style.chart.color
},
head: {
backgroundColor: M.value.style.chart.backgroundColor,
color: M.value.style.chart.color
}
}
}
};
});
C(() => L.value.showTable, (e) => {
M.value.table.show || (e && M.value.table.useDialog && A.value ? A.value.open() : "close" in A.value && A.value.close());
});
let zn = c(() => q.value.map((e) => ({
...e,
name: e.display
}))), Bn = c(() => M.value.style.chart.backgroundColor), Vn = c(() => M.value.style.chart.legend), Hn = c(() => M.value.style.chart.title), { exportSvg: Un, getSvg: Wn } = me({
svg: I,
title: Hn,
legend: Vn,
legendItems: zn,
backgroundColor: Bn
});
async function Gn({ isCb: e }) {
Lt.value = !0, await Le();
try {
if (e) {
let { blob: e, url: t, text: n, dataUrl: r } = await Wn();
await Promise.resolve(M.value.userOptions.callbacks.svg({
blob: e,
url: t,
text: n,
dataUrl: r
}));
} else await Promise.resolve(Un());
} finally {
Lt.value = !1;
}
}
function Kn(e) {
if (e?.stage === "start") {
It.value = !0;
return;
}
if (e?.stage === "end") {
It.value = !1;
return;
}
Zt();
}
async function qn() {
if (_n("copyAlt", {
config: M.value,
dataset: X.value
}), !M.value.userOptions.callbacks.altCopy) {
console.warn("Vue Data UI - A callback must be set for `altCopy` in userOptions.");
return;
}
await Promise.resolve(M.value.userOptions.callbacks.altCopy({
config: M.value,
dataset: X.value
}));
}
function Jn() {
j.value = null, Bt.value = !0;
}
function Yn() {
j.value = null, zt.value = "pointer", Et.value = !1, Q.value = void 0, Bt.value = !1;
}
function Xn(e) {
if (!I.value || Fn.value || document.activeElement !== I.value || !X.value.length) return;
let t = ["ArrowLeft", "ArrowDown"].includes(e.key), n = ["ArrowRight", "ArrowUp"].includes(e.key), r = e.key === "Enter" || e.key === " ", i = e.key === "Escape";
if (!t && !n && !r && !i) return;
if (e.preventDefault(), e.stopPropagation(), i) {
j.value = null, zt.value = "pointer", Et.value = !1, Q.value = void 0;
return;
}
if (r) {
if (j.value === null) return;
let e = X.value[j.value];
if (!e) return;
Dn({ datapoint: e });
return;
}
let a = j.value;
a === null || a < 0 || a >= X.value.length ? a = n ? 0 : X.value.length - 1 : n ? (a += 1, a >= X.value.length && (a = 0)) : t && (--a, a < 0 && (a = X.value.length - 1));
let o = X.value[a];
o && (Zn(a), Mn({
datapoint: o,
seriesIndex: a,
show: !0,
triggerMode: "keyboard"
}));
}
function Zn(e) {
if (!Number.isFinite(e) || !I.value) return;
let t = X.value[e];
if (!t) return;
let n = t.radius, r = Math.PI * 7 / 4, i = G.value.centerX + n * Math.cos(r), a = G.value.centerY + n * Math.sin(r), o = I.value.getBoundingClientRect();
Rt.value = {
x: o.left + i / R.value.width * o.width,
y: o.top + a / R.value.height * o.height
};
}
let Qn = c(() => ({
headers: Z.value?.colNames ?? [],
rows: Z.value?.body ?? []
}));
return be({
getData: Cn,
getImage: Ln,
generatePdf: Xt,
generateCsv: Tn,
generateImage: Zt,
generateSvg: Gn,
hideSeries: Sn,
showSeries: xn,
toggleTable: Nn,
toggleTooltip: Pn,
toggleAnnotator: In,
toggleFullscreen: En,
copyAlt: qn
}), (e, t) => (v(), d("div", {
class: h(`vue-data-ui-component vue-ui-onion ${$.value ? "vue-data-ui-wrapper-fullscreen" : ""} ${M.value.useCssAnimation ? "" : "vue-ui-dna"}`),
ref_key: "onionChart",
ref: O,
id: `vue-ui-onion_${E.value}`,
style: _(`font-family:${M.value.style.fontFamily};width:100%; ${M.value.responsive ? "height: 100%;" : ""} text-align:center;background:${M.value.style.chart.backgroundColor}`),
onMouseenter: t[4] ||= () => S(Gt)(!0),
onMouseleave: t[5] ||= () => S(Gt)(!1)
}, [
f("div", {
id: `chart-instructions-${E.value}`,
class: "sr-only"
}, [f("p", null, x(M.value.a11y.translations.keyboardNavigation), 1)], 8, Ke),
Qn.value?.rows?.length ? (v(), l(we, {
key: 0,
uid: E.value,
head: Qn.value.headers,
body: Qn.value.rows,
notice: M.value.a11y.translations.tableAvailable,
caption: M.value.a11y.translations.tableCaption
}, null, 8, [
"uid",
"head",
"body",
"notice",
"caption"
])) : u("", !0),
M.value.userOptions.buttons.annotator ? (v(), l(S(_t), {
key: 1,
svgRef: S(I),
backgroundColor: M.value.style.chart.backgroundColor,
color: M.value.style.chart.color,
active: Fn.value,
isCursorPointer: P.value,
onClose: In
}, {
"annotator-action-close": w(() => [b(e.$slots, "annotator-action-close", {}, void 0, !0)]),
"annotator-action-color": w(({ color: t }) => [b(e.$slots, "annotator-action-color", g(m({ color: t })), void 0, !0)]),
"annotator-action-draw": w(({ mode: t }) => [b(e.$slots, "annotator-action-draw", g(m({ mode: t })), void 0, !0)]),
"annotator-action-undo": w(({ disabled: t }) => [b(e.$slots, "annotator-action-undo", g(m({ disabled: t })), void 0, !0)]),
"annotator-action-redo": w(({ disabled: t }) => [b(e.$slots, "annotator-action-redo", g(m({ disabled: t })), void 0, !0)]),
"annotator-action-delete": w(({ disabled: t }) => [b(e.$slots, "annotator-action-delete", g(m({ disabled: t })), void 0, !0)]),
_: 3
}, 8, [
"svgRef",
"backgroundColor",
"color",
"active",
"isCursorPointer"
])) : u("", !0),
Qt.value ? (v(), d("div", {
key: 2,
ref_key: "noTitle",
ref: jt,
class: "vue-data-ui-no-title-space",
style: "height:36px; width: 100%;background:transparent"
}, null, 512)) : u("", !0),
M.value.style.chart.title.text ? (v(), d("div", {
key: 3,
ref_key: "chartTitle",
ref: Ot,
style: "width:100%;background:transparent"
}, [(v(), l(ye, {
key: `title_${Mt.value}`,
config: {
title: {
cy: "onion-div-title",
...M.value.style.chart.title
},
subtitle: {
cy: "onion-div-subtitle",
...M.value.style.chart.title.subtitle
}
}
}, null, 8, ["config"]))], 512)) : u("", !0),
f("div", { id: `legend-top-${E.value}` }, null, 8, qe),
M.value.userOptions.show && Ct.value && (S(Kt) || S(Wt)) ? (v(), l(S(gt), {
ref_key: "details",
ref: wt,
key: `user_options${Tt.value}`,
backgroundColor: M.value.style.chart.backgroundColor,
color: M.value.style.chart.color,
isImaging: S(Yt),
isPrinting: S(Jt),
uid: E.value,
hasTooltip: M.value.userOptions.buttons.tooltip && M.value.style.chart.tooltip.show,
hasPdf: M.value.userOptions.buttons.pdf,
hasImg: M.value.userOptions.buttons.img,
hasSvg: M.value.userOptions.buttons.svg,
hasXls: M.value.userOptions.buttons.csv,
hasTable: M.value.userOptions.buttons.table,
hasFullscreen: M.value.userOptions.buttons.fullscreen,
hasAltCopy: M.value.userOptions.buttons.altCopy,
isFullscreen: $.value,
isTooltip: L.value.showTooltip,
titles: { ...M.value.userOptions.buttonTitles },
chartElement: O.value,
position: M.value.userOptions.position,
hasAnnotator: M.value.userOptions.buttons.annotator,
isAnnotation: Fn.value,
callbacks: M.value.userOptions.callbacks,
printScale: M.value.userOptions.print.scale,
tableDialog: M.value.table.useDialog,
isCursorPointer: P.value,
onToggleFullscreen: En,
onGeneratePdf: S(Xt),
onGenerateCsv: Tn,
onGenerateImage: Kn,
onGenerateSvg: Gn,
onToggleTable: Nn,
onToggleTooltip: Pn,
onToggleAnnotator: In,
onCopyAlt: qn,
style: _({ visibility: S(Kt) ? S(Wt) ? "visible" : "hidden" : "visible" })
}, Ne({ _: 2 }, [
e.$slots.menuIcon ? {
name: "menuIcon",
fn: w(({ isOpen: t, color: n }) => [b(e.$slots, "menuIcon", g(m({
isOpen: t,
color: n
})), void 0, !0)]),
key: "0"
} : void 0,
e.$slots.optionTooltip ? {
name: "optionTooltip",
fn: w(() => [b(e.$slots, "optionTooltip", {}, void 0, !0)]),
key: "1"
} : void 0,
e.$slots.optionPdf ? {
name: "optionPdf",
fn: w(() => [b(e.$slots, "optionPdf", {}, void 0, !0)]),
key: "2"
} : void 0,
e.$slots.optionCsv ? {
name: "optionCsv",
fn: w(() => [b(e.$slots, "optionCsv", {}, void 0, !0)]),
key: "3"
} : void 0,
e.$slots.optionImg ? {
name: "optionImg",
fn: w(() => [b(e.$slots, "optionImg", {}, void 0, !0)]),
key: "4"
} : void 0,
e.$slots.optionSvg ? {
name: "optionSvg",
fn: w(() => [b(e.$slots, "optionSvg", {}, void 0, !0)]),
key: "5"
} : void 0,
e.$slots.optionTable ? {
name: "optionTable",
fn: w(() => [b(e.$slots, "optionTable", {}, void 0, !0)]),
key: "6"
} : void 0,
e.$slots.optionFullscreen ? {
name: "optionFullscreen",
fn: w(({ toggleFullscreen: t, isFullscreen: n }) => [b(e.$slots, "optionFullscreen", g(m({
toggleFullscreen: t,
isFullscreen: n
})), void 0, !0)]),
key: "7"
} : void 0,
e.$slots.optionAnnotator ? {
name: "optionAnnotator",
fn: w(({ toggleAnnotator: t, isAnnotator: n }) => [b(e.$slots, "optionAnnotator", g(m({
toggleAnnotator: t,
isAnnotator: n
})), void 0, !0)]),
key: "8"
} : void 0,
e.$slots.optionAltCopy ? {
name: "optionAltCopy",
fn: w(({ altCopy: t }) => [b(e.$slots, "optionAltCopy", g(m({ altCopy: t })), void 0, !0)]),
key: "9"
} : void 0,
e.$slots["custom-menu-before"] ? {
name: "custom-menu-before",
fn: w(() => [b(e.$slots, "custom-menu-before", {}, void 0, !0)]),
key: "10"
} : void 0,
e.$slots["custom-menu-after"] ? {
name: "custom-menu-after",
fn: w(() => [b(e.$slots, "custom-menu-after", {}, void 0, !0)]),
key: "11"
} : void 0
]), 1032, /* @__PURE__ */ "backgroundColor.color.isImaging.isPrinting.uid.hasTooltip.hasPdf.hasImg.hasSvg.hasXls.hasTable.hasFullscreen.hasAltCopy.isFullscreen.isTooltip.titles.chartElement.position.hasAnnotator.isAnnotation.callbacks.printScale.tableDialog.isCursorPointer.onGeneratePdf.style".split("."))) : u("", !0),
f("div", Je, [(v(), d("svg", {
ref_key: "svgRef",
ref: I,
xmlns: S(ie),
"aria-describedby": `chart-instructions-${E.value}`,
class: h({
"vue-data-ui-fullscreen--on": $.value,
"vue-data-ui-fulscreen--off": !$.value,
resizing: k.value,
"vue-data-ui-no-transition": !S(N) || k.value || S(F)
}),
viewBox: `0 0 ${R.value.width <= 0 ? 10 : R.value.width} ${R.value.height <= 0 ? 10 : R.value.height}`,
style: _(`max-width:100%;overflow:visible;background:transparent;color:${M.value.style.chart.color}`),
tabindex: "0",
onFocus: Jn,
onBlur: Yn,
onKeydown: Xn
}, [
Fe(S(vt)),
e.$slots["chart-background"] ? (v(), d("foreignObject", {
key: 0,
x: 0,
y: 0,
width: R.value.width <= 0 ? 10 : R.value.width,
height: R.value.height <= 0 ? 10 : R.value.height,
style: { pointerEvents: "none" }
}, [b(e.$slots, "chart-background", {}, void 0, !0)], 8, Xe)) : u("", !0),
(v(!0), d(je, null, Be(X.value, (e, t) => (v(), d("circle", {
cx: G.value.centerX,
cy: G.value.centerY,
r: e.radius <= 0 ? 1e-4 : e.radius,
stroke: M.value.style.chart.layout.gutter.color,
"stroke-width": Y.value.gutter,
fill: "none",
"stroke-dasharray": e.path.bgDashArray,
"stroke-dashoffset": e.path.fullOffset,
"stroke-linecap": "round",
class: h({
"vue-ui-onion-path": !0,
"vue-ui-onion-blur": M.value.useBlurOnHover && ![null, void 0].includes(Q.value) && Q.value !== t,
"vue-data-ui-transition": S(N)
}),
style: {
transform: "rotate(-90deg)",
transformOrigin: "50% 50%"
}
}, null, 10, Ze))), 256)),
(v(!0), d(je, null, Be(X.value, (e, t) => (v(), d("circle", {
cx: G.value.centerX,
cy: G.value.centerY,
r: e.radius < 0 ? 1e-4 : e.radius,
stroke: `${e.color}`,
"stroke-width": Y.value.track,
fill: "none",
"stroke-dasharray": e.path.dashArray,
"stroke-dashoffset": e.path.dashOffset,
class: h({
"vue-ui-onion-path": !0,
"vue-ui-onion-blur": M.value.useBlurOnHover && ![null, void 0].includes(Q.value) && Q.value !== t,
"vue-data-ui-transition": S(N)
}),
"stroke-linecap": "round",
style: {
transform: "rotate(-90deg)",
transformOrigin: "50% 50%"
}
}, null, 10, Qe))), 256)),
f("defs", null, [f("filter", {
id: `blur_${E.value}`,
x: "-50%",
y: "-50%",
width: "200%",
height: "200%"
}, [f("feGaussianBlur", {
in: "SourceGraphic",
stdDeviation: 100 / M.value.style.chart.gradientIntensity
}, null, 8, et)], 8, $e)]),
M.value.style.chart.useGradient ? (v(), d("g", {
key: 1,
filter: `url(#blur_${E.value})`
}, [(v(!0), d(je, null, Be(X.value, (e, t) => (v(), d("circle", {
cx: G.value.centerX,
cy: G.value.centerY,
r: e.radius <= 0 ? 1e-4 : e.radius,
stroke: "white",
"stroke-width": Y.value.track / 3,
fill: "none",
"stroke-linecap": "round",
"stroke-dasharray": e.path.dashArray,
"stroke-dashoffset": e.path.dashOffset,
style: {
transform: "rotate(-90deg)",
transformOrigin: "50% 50%"
},
class: h({ "vue-data-ui-transition": S(N) })
}, null, 10, nt))), 256))], 8, tt)) : u("", !0),
(v(!0), d(je, null, Be(X.value, (e, t) => (v(), d("circle", {
cx: G.value.centerX,
cy: G.value.centerY,
r: e.radius <= 0 ? 1e-4 : e.radius,
stroke: "transparent",
"stroke-width": Math.max(Y.value.track, Y.value.gutter),
fill: "none",
"stroke-dasharray": e.path.bgDashArray,
"stroke-dashoffset": e.path.fullOffset,
"stroke-linecap": "round",
class: "vue-ui-onion-path",
style: {
transform: "rotate(-90deg)",
transformOrigin: "50% 50%"
},
onMouseenter: (n) => Mn({
datapoint: e,
show: !0,
seriesIndex: t,
triggerMode: "pointer"
}),
onMouseleave: (t) => On({ datapoint: e }),
onClick: (t) => Dn({ datapoint: e })
}, null, 40, rt))), 256)),
M.value.style.chart.layout.labels.show ? (v(), d("g", it, [(v(!0), d(je, null, Be(X.value, (e, t) => (v(), d("g", {
key: `dl_${e.id}`,
onMouseenter: (n) => Mn({
datapoint: e,
show: !0,
seriesIndex: t,
triggerMode: "pointer"
}),
onMouseleave: (t) => On({ datapoint: e }),
onClick: (t) => Dn({ datapoint: e })
}, [D.value.includes(e.id) ? u("", !0) : (v(), d("text", {
key: 0,
class: h(["vue-ui-onion-label", { "vue-data-ui-transition": S(N) }]),
transform: `translate(${R.value.width / 2 - Y.value.gutter * .8 + M.value.style.chart.layout.labels.offsetX},${e.labelY + M.value.style.chart.layout.labels.offsetY})`,
"text-anchor": "end",
"font-size": M.value.style.chart.layout.labels.fontSize,
fill: M.value.useBlurOnHover && ![null, void 0].includes(Q.value) && Q.value === t ? e.color : M.value.style.chart.layout.labels.color,
"font-weight": M.value.style.chart.layout.labels.bold ? "bold" : "normal"
}, x(An(e, t)), 11, ot))], 40, at))), 128))])) : u("", !0),
b(e.$slots, "svg", { svg: {
...R.value,
drawingArea: G.value,
isPrintingImg: S(Jt) || S(Yt) || It.value,
isPrintingSvg: Lt.value
} }, void 0, !0)
], 46, Ye)), e.$slots.hint ? (v(), d("div", st, [b(e.$slots, "hint", g(m({
hint: M.value.a11y.translations.keyboardNavigation,
isVisible: Bt.value
})), void 0, !0)])) : u("", !0)]),
e.$slots.watermark ? (v(), d("div", ct, [b(e.$slots, "watermark", g(m({ isPrinting: S(Jt) || S(Yt) || It.value || Lt.value })), void 0, !0)])) : u("", !0),
f("div", { id: `legend-bottom-${E.value}` }, null, 8, lt),
Ft.value && (M.value.style.chart.legend.show || e.$slots.legend) ? (v(), l(Me, {
key: 6,
to: M.value.style.chart.legend.position === "top" ? `#legend-top-${E.value}` : `#legend-bottom-${E.value}`
}, [f("div", {
ref_key: "chartLegend",
ref: kt
}, [b(e.$slots, "legend", { legend: q.value }, () => [M.value.style.chart.legend.show ? (v(), l(Oe, {
key: `legend_${Pt.value}`,
legendSet: q.value,
config: mn.value,
isCursorPointer: P.value,
onClickMarker: t[0] ||= ({ legend: e }) => yn(e.id)
}, {
item: w(({ legend: e }) => [S(F) ? u("", !0) : (v(), d("div", {
key: 0,
"data-cy-legend-item": "",
onClick: (t) => e.segregate(),
style: _(`opacity:${D.value.includes(e.id) ? .5 : 1}`)
}, x(e.display), 13, ut))]),
legendToggle: w(() => [q.value.length > 2 && M.value.style.chart.legend.selectAllToggle.show && !S(F) ? (v(), l(Ce, {
key: 0,
backgroundColor: M.value.style.chart.legend.selectAllToggle.backgroundColor,
color: M.value.style.chart.legend.selectAllToggle.color,
fontSize: M.value.style.chart.legend.fontSize,
checked: D.value.length > 0,
isCursorPointer: P.value,
onToggle: vn
}, null, 8, [
"backgroundColor",
"color",
"fontSize",
"checked",
"isCursorPointer"
])) : u("", !0)]),
_: 1
}, 8, [
"legendSet",
"config",
"isCursorPointer"
])) : u("", !0)], !0)], 512)], 8, ["to"])) : u("", !0),
e.$slots.source ? (v(), d("div", {
key: 7,
ref_key: "source",
ref: At,
dir: "auto"
}, [b(e.$slots, "source", {}, void 0, !0)], 512)) : u("", !0),
Fe(S(ft), {
teleportTo: M.value.style.chart.tooltip.teleportTo,
show: L.value.showTooltip && Et.value,
backgroundColor: M.value.style.chart.tooltip.backgroundColor,
color: M.value.style.chart.tooltip.color,
borderRadius: M.value.style.chart.tooltip.borderRadius,
borderColor: M.value.style.chart.tooltip.borderColor,
borderWidth: M.value.style.chart.tooltip.borderWidth,
fontSize: M.value.style.chart.tooltip.fontSize,
backgroundOpacity: M.value.style.chart.tooltip.backgroundOpacity,
position: M.value.style.chart.tooltip.position,
offsetX: M.value.style.chart.tooltip.offsetX,
offsetY: M.value.style.chart.tooltip.offsetY,
parent: O.value,
content: Dt.value,
isFullscreen: $.value,
isCustom: S(se)(M.value.style.chart.tooltip.customFormat),
smooth: M.value.style.chart.tooltip.smooth,
backdropFilter: M.value.style.chart.tooltip.backdropFilter,
smoothForce: M.value.style.chart.tooltip.smoothForce,
smoothSnapThreshold: M.value.style.chart.tooltip.smoothSnapThreshold,
isA11yMode: zt.value === "keyboard",
a11yPosition: Rt.value
}, {
"tooltip-before": w(() => [b(e.$slots, "tooltip-before", g(m({ ...jn.value })), void 0, !0)]),
tooltip: w(() => [b(e.$slots, "tooltip", g(m({ ...jn.value })), void 0, !0)]),
"tooltip-after": w(() => [b(e.$slots, "tooltip-after", g(m({ ...jn.value })), void 0, !0)]),
_: 3
}, 8, [
"teleportTo",
"show",
"backgroundColor",
"color",
"borderRadius",
"borderColor",
"borderWidth",
"fontSize",
"backgroundOpacity",
"position",
"offsetX",
"offsetY",
"parent",
"content",
"isFullscreen",
"isCustom",
"smooth",
"backdropFilter",
"smoothForce",
"smoothSnapThreshold",
"isA11yMode",
"a11yPosition"
]),
Ct.value && M.value.userOptions.buttons.table ? (v(), l(Ve(Rn.value.component), Ie({ key: 8 }, Rn.value.props, {
ref_key: "tableUnit",
ref: A,
onClose: t[3] ||= (e) => L.value.showTable = !1
}), Ne({
content: w(() => [(v(), l(S(ht), {
key: `table_${Nt.value}`,
colNames: Z.value.colNames,
head: Z.value.head,
body: Z.value.body,
config: Z.value.config,
title: M.value.table.useDialog ? "" : Rn.value.title,
withCloseButton: !M.value.table.useDialog,
isCursorPointer: P.value,
onClose: t[2] ||= (e) => L.value.showTable = !1
}, {
th: w(({ th: e }) => [Pe(x(e), 1)]),
td: w(({ td: e }) => [f("div", { innerHTML: e }, null, 8, dt)]),
_: 1
}, 8, [
"colNames",
"head",
"body",
"config",
"title",
"withCloseButton",
"isCursorPointer"
]))]),
_: 2
}, [M.value.table.useDialog ? {
name: "title",
fn: w(() => [Pe(x(Rn.value.title), 1)]),
key: "0"
} : void 0, M.value.table.useDialog ? {
name: "actions",
fn: w(() => [f("button", {
tabindex: "0",
class: "vue-ui-user-options-button",
onClick: t[1] ||= (e) => Tn(M.value.userOptions.callbacks.csv),
style: _({ cursor: P.value ? "pointer" : "default" })
}, [Fe(S(pt), {
name: "fileCsv",
stroke: Rn.value.props.color
}, null, 8, ["stroke"])], 4)]),
key: "1"
} : void 0]), 1040)) : u("", !0),
b(e.$slots, "skeleton", {}, () => [S(F) ? (v(), l(pe, { key: 0 })) : u("", !0)], !0)
], 46, Ge));
}
}, [["__scopeId", "data-v-4d2bd2f8"]]);
//#endregion
export { We as n, ft as t };