vue-data-ui
Version:
A user-empowering data visualization Vue 3 components library for eloquent data storytelling
606 lines (605 loc) • 23.7 kB
JavaScript
import { useCssVars as Le, computed as v, onMounted as Te, ref as c, watch as Ae, createElementBlock as u, openBlock as s, unref as n, normalizeStyle as _, normalizeClass as T, createBlock as A, createCommentVNode as f, createSlots as Ne, withCtx as g, renderSlot as b, normalizeProps as M, guardReactiveProps as R, createVNode as Oe, createElementVNode as C, mergeProps as q, Fragment as V, renderList as B, toDisplayString as U, createTextVNode as ze, nextTick as Se } from "vue";
import { u as Pe, o as Fe, e as me, g as Ie, c as De, d as Me, l as Re, i as E, f as G, X as Ve, G as Be, F as Y, a as Ue, q as Ee, r as Ge } from "./index-CHWA6Lnw.js";
import { u as be } from "./useNestedProp-ByBiJC9_.js";
import { u as je, U as He } from "./usePrinter-DibtVl2x.js";
import { _ as Xe } from "./Title-BwZtefYd.js";
import { P as qe } from "./PenAndPaper-ljJaW1FE.js";
import { D as Ye } from "./DataTable-B4YF6guk.js";
import We from "./vue-ui-accordion-gHGrRoVr.js";
import { t as Je, u as Ke } from "./useResponsive-vZgZwV-S.js";
import Qe from "./vue-ui-skeleton-BSUFPx4a.js";
import { u as Ze } from "./useUserOptionState-BIvW1Kz7.js";
import { _ as et } from "./PackageVersion-DcMafJMi.js";
import { u as tt } from "./useChartAccessibility-BWojgys7.js";
import { _ as at } from "./_plugin-vue_export-helper-CHgC5LLL.js";
const lt = ["id"], st = ["xmlns", "viewBox"], ot = ["width", "height"], nt = ["id"], rt = ["stop-color"], ut = ["stop-color"], it = ["stop-color"], ct = ["stroke", "stroke-width"], vt = ["stroke", "stroke-width"], dt = ["x", "y", "font-size", "fill", "font-weight"], ht = ["points", "fill"], ft = ["stroke", "stroke-width", "rx"], mt = ["x", "y", "font-size", "fill", "font-weight"], bt = ["x", "y", "font-size", "fill", "font-weight"], yt = {
key: 5,
class: "vue-data-ui-watermark"
}, gt = ["innerHTML"], pt = {
__name: "vue-ui-funnel",
props: {
config: {
type: Object,
default() {
return {};
}
},
dataset: {
type: Array,
default() {
return [];
}
}
},
setup(ye, { expose: ge }) {
Le((t) => ({
"4a21a112": _e.value
}));
const { vue_ui_funnel: pe } = Pe(), y = ye, x = v(() => !!y.dataset && y.dataset.length);
Te(W);
function W() {
if (Fe(y.dataset) ? me({
componentName: "VueUiFunnel",
type: "dataset"
}) : y.dataset.forEach((t, l) => {
Ie({
datasetObject: t,
requiredAttributes: ["name", "value"]
}).forEach((a) => {
x.value = !1, me({
componentName: "VueUiFunnel",
type: "datasetSerieAttribute",
property: a,
index: l
});
});
}), e.value.responsive) {
const t = Je(() => {
const { width: l, height: a } = Ke({
chart: F.value,
title: e.value.style.chart.title.text ? te.value : null,
source: ee.value,
noTitle: Z.value
});
requestAnimationFrame(() => {
i.value.height = a, i.value.width = l, k.value = ve(), d.value.circles = Y({
relator: Math.min(l, a),
adjuster: 600,
source: e.value.style.chart.circles.dataLabels.fontSize,
threshold: 10,
fallback: 10
}), d.value.names = Y({
relator: Math.min(l, a),
adjuster: 600,
source: e.value.style.chart.bars.dataLabels.name.fontSize,
threshold: 10,
fallback: 10
}), d.value.values = Y({
relator: Math.min(l, a),
adjuster: 600,
source: e.value.style.chart.bars.dataLabels.value.fontSize,
threshold: 10,
fallback: 10
});
});
});
ae.value = new ResizeObserver(t), ae.value.observe(F.value.parentNode);
}
}
const F = c(null), N = c(De()), J = c(0), K = c(0), Q = c(0), Z = c(null), ee = c(null), te = c(null), ae = c(null), w = c(!1);
function le() {
const t = be({
userConfig: y.config,
defaultConfig: pe
});
return t.theme ? {
...be({
userConfig: Ue.vue_ui_funnel[t.theme] || y.config,
defaultConfig: t
})
} : t;
}
const e = v({
get: () => le(),
set: (t) => t
}), { userOptionsVisible: j, setUserOptionsVisibility: se, keepUserOptionState: oe } = Ze({ config: e.value }), { svgRef: ne } = tt({ config: e.value.style.chart.title });
Ae(() => y.config, (t) => {
e.value = le(), j.value = !e.value.userOptions.showOnChartHover, W(), K.value += 1, Q.value += 1, d.value.circles = e.value.style.chart.circles.dataLabels.fontSize, d.value.names = e.value.style.chart.bars.dataLabels.name.fontSize, d.value.values = e.value.style.chart.bars.dataLabels.value.fontSize, O.value.showTable = e.value.table.show;
}, { deep: !0 });
const { isPrinting: re, isImaging: ue, generatePdf: ie, generateImage: ce } = je({
elementId: `funnel_${N.value}`,
fileName: e.value.style.chart.title.text || "vue-ui-funnel"
}), ke = v(() => e.value.userOptions.show && !e.value.style.chart.title.text), O = c({
showTable: e.value.table.show
}), d = c({
circles: e.value.style.chart.circles.dataLabels.fontSize,
names: e.value.style.chart.bars.dataLabels.name.fontSize,
values: e.value.style.chart.bars.dataLabels.value.fontSize
}), i = v({
get: () => ({
height: e.value.style.chart.height,
width: e.value.style.chart.width
}),
set: (t) => t
}), p = v(() => x.value ? y.dataset.map((t, l) => ({
...t,
color: t.color ? Me(t.color) : Re(e.value.style.chart.bars.defaultColor, l / y.dataset.length)
})) : []);
setTimeout(() => {
w.value = !0;
}, p.value.length * 150);
function ve() {
const t = e.value.style.chart.padding.left, l = e.value.style.chart.padding.top;
return {
left: t,
top: l,
right: i.value.width - e.value.style.chart.padding.right,
bottom: i.value.height - e.value.style.chart.padding.bottom,
width: i.value.width - t - e.value.style.chart.padding.right,
height: i.value.height - l - e.value.style.chart.padding.bottom
};
}
const k = c(ve()), L = v(() => k.value.height / y.dataset.length), $ = v(() => L.value * e.value.style.chart.bars.gapRatio), de = v(() => k.value.width * e.value.style.chart.barCircleSpacingRatio), r = v(() => p.value.map((t, l) => {
const a = L.value - $.value, o = k.value.top + $.value / 2 * l + (L.value - $.value / 2) * l + $.value / 2, m = t.value / p.value[0].value, h = (k.value.width - a - de.value) * (t.value / p.value[0].value);
return {
...t,
cx: k.value.left + a / 2,
cy: o + a / 2,
datapointIndex: l,
fill: t.color,
height: Math.max(a, 0),
proportion: m,
r: Math.max(a / 2, 0),
width: Math.max(h, 0),
x: k.value.left + a + de.value,
y: o
};
})), Ce = v(() => {
const t = r.value.map((l) => `${l.x + l.width},${l.y + (L.value - $.value) / 2}`);
return `${r.value[0].x},${r.value[0].y + (L.value - $.value) / 2} ${t.toString()} ${r.value.at(-1).x},${r.value.at(-1).y + (L.value - $.value) / 2}`;
}), we = v(() => ({
x1: r.value[0].cx,
y1: r.value[0].cy,
x2: r.value.at(-1).cx,
y2: r.value.at(-1).cy
})), z = c(!1);
function $e(t) {
z.value = t, J.value += 1;
}
const _e = v(() => `${p.value.length * 150}ms`), I = c(!1);
function H() {
I.value = !I.value;
}
function he() {
O.value.showTable = !O.value.showTable;
}
const S = v(() => {
const t = p.value.map((a) => ({
name: a.name,
color: a.color
})), l = p.value.map((a) => a.value);
return { head: t, body: l };
}), D = v(() => {
const t = [
e.value.table.columnNames.series,
e.value.table.columnNames.value,
e.value.table.columnNames.percentage
], l = S.value.head.map((m, h) => {
const P = E(
e.value.style.chart.bars.dataLabels.value.formatter,
S.value.body[h],
G({
p: e.value.style.chart.bars.dataLabels.value.prefix,
v: S.value.body[h],
s: e.value.style.chart.bars.dataLabels.value.suffix,
r: e.value.table.td.roundingValue
}),
{ datapoint: r.value[h] }
), X = E(
e.value.style.chart.circles.dataLabels.formatter,
r.value[h].proportion * 100,
G({
v: r.value[h].proportion * 100,
s: "%",
r: e.value.table.td.roundingPercentage
}),
{ datapoint: r.value[h] }
);
return [
{ color: m.color, name: m.name },
P,
X
];
}), a = {
th: {
backgroundColor: e.value.table.th.backgroundColor,
color: e.value.table.th.color,
outline: e.value.table.th.outline
},
td: {
backgroundColor: e.value.table.td.backgroundColor,
color: e.value.table.td.color,
outline: e.value.table.td.outline
},
breakpoint: e.value.table.responsiveBreakpoint
};
return {
colNames: [
e.value.table.columnNames.series,
e.value.table.columnNames.value,
e.value.table.columnNames.percentage
],
head: t,
body: l,
config: a
};
});
function fe() {
Se(() => {
const t = S.value.head.map((o, m) => [[
o.name
], [S.value.body[m]], [r.value[m].proportion * 100]]), l = [[e.value.style.chart.title.text], [e.value.style.chart.title.subtitle.text], [[e.value.table.columnNames.series], [e.value.table.columnNames.value], ["%"]]].concat(t), a = Ee(l);
Ge({ csvContent: a, title: e.value.style.chart.title.text || "vue-ui-funnel" });
});
}
function xe() {
return p.value;
}
return ge({
getData: xe,
generatePdf: ie,
generateCsv: fe,
generateImage: ce,
toggleTable: he,
toggleAnnotator: H
}), (t, l) => (s(), u("div", {
ref_key: "funnelChart",
ref: F,
class: T(`vue-ui-funnel ${z.value ? "vue-data-ui-wrapper-fullscreen" : ""} ${e.value.useCssAnimation ? "" : "vue-ui-dna"}`),
style: _(`font-family:${e.value.style.fontFamily};width:100%; ${e.value.responsive ? "height:100%;" : ""} text-align:center;background:${e.value.style.chart.backgroundColor}`),
id: `funnel_${N.value}`,
onMouseenter: l[1] || (l[1] = () => n(se)(!0)),
onMouseleave: l[2] || (l[2] = () => n(se)(!1))
}, [
e.value.userOptions.buttons.annotator ? (s(), A(qe, {
key: 0,
svgRef: n(ne),
backgroundColor: e.value.style.chart.backgroundColor,
color: e.value.style.chart.color,
active: I.value,
onClose: H
}, null, 8, ["svgRef", "backgroundColor", "color", "active"])) : f("", !0),
ke.value ? (s(), u("div", {
key: 1,
ref_key: "noTitle",
ref: Z,
class: "vue-data-ui-no-title-space",
style: "height:36px; width: 100%;background:transparent"
}, null, 512)) : f("", !0),
e.value.style.chart.title.text ? (s(), u("div", {
key: 2,
ref_key: "chartTitle",
ref: te,
style: "width:100%;background:transparent;padding-bottom:24px"
}, [
(s(), A(Xe, {
key: `title_${K.value}`,
config: {
title: {
cy: "funnel-div-title",
...e.value.style.chart.title
},
subtitle: {
cy: "funnel-div-subtitle",
...e.value.style.chart.title.subtitle
}
}
}, null, 8, ["config"]))
], 512)) : f("", !0),
e.value.userOptions.show && x.value && (n(oe) || n(j)) ? (s(), A(He, {
ref: "details",
key: `user_option_${J.value}`,
backgroundColor: e.value.style.chart.backgroundColor,
color: e.value.style.chart.color,
isPrinting: n(re),
isImaging: n(ue),
uid: N.value,
hasTooltip: !1,
hasPdf: e.value.userOptions.buttons.pdf,
hasImg: e.value.userOptions.buttons.img,
hasXls: e.value.userOptions.buttons.csv,
hasTable: e.value.userOptions.buttons.table,
hasLabel: !1,
hasFullscreen: e.value.userOptions.buttons.fullscreen,
isFullscreen: z.value,
chartElement: F.value,
position: e.value.userOptions.position,
titles: { ...e.value.userOptions.buttonTitles },
hasAnnotator: e.value.userOptions.buttons.annotator,
isAnnotation: I.value,
onToggleAnnotator: H,
onToggleFullscreen: $e,
onGeneratePdf: n(ie),
onGenerateImage: n(ce),
onToggleTable: he,
onGenerateCsv: fe,
style: _({
visibility: n(oe) ? n(j) ? "visible" : "hidden" : "visible"
})
}, Ne({ _: 2 }, [
t.$slots.menuIcon ? {
name: "menuIcon",
fn: g(({ isOpen: a, color: o }) => [
b(t.$slots, "menuIcon", M(R({ isOpen: a, color: o })), void 0, !0)
]),
key: "0"
} : void 0,
t.$slots.optionPdf ? {
name: "optionPdf",
fn: g(() => [
b(t.$slots, "optionPdf", {}, void 0, !0)
]),
key: "1"
} : void 0,
t.$slots.optionCsv ? {
name: "optionCsv",
fn: g(() => [
b(t.$slots, "optionCsv", {}, void 0, !0)
]),
key: "2"
} : void 0,
t.$slots.optionImg ? {
name: "optionImg",
fn: g(() => [
b(t.$slots, "optionImg", {}, void 0, !0)
]),
key: "3"
} : void 0,
t.$slots.optionTable ? {
name: "optionTable",
fn: g(() => [
b(t.$slots, "optionTable", {}, void 0, !0)
]),
key: "4"
} : void 0,
t.$slots.optionFullscreen ? {
name: "optionFullscreen",
fn: g(({ toggleFullscreen: a, isFullscreen: o }) => [
b(t.$slots, "optionFullscreen", M(R({ toggleFullscreen: a, isFullscreen: o })), void 0, !0)
]),
key: "5"
} : void 0,
t.$slots.optionAnnotator ? {
name: "optionAnnotator",
fn: g(({ toggleAnnotator: a, isAnnotator: o }) => [
b(t.$slots, "optionAnnotator", M(R({ toggleAnnotator: a, isAnnotator: o })), void 0, !0)
]),
key: "6"
} : void 0
]), 1032, ["backgroundColor", "color", "isPrinting", "isImaging", "uid", "hasPdf", "hasImg", "hasXls", "hasTable", "hasFullscreen", "isFullscreen", "chartElement", "position", "titles", "hasAnnotator", "isAnnotation", "onGeneratePdf", "onGenerateImage", "style"])) : f("", !0),
x.value ? (s(), u("svg", {
key: 4,
ref_key: "svgRef",
ref: ne,
xmlns: n(Ve),
class: T({ "vue-data-ui-fullscreen--on": z.value, "vue-data-ui-fulscreen--off": !z.value }),
viewBox: `0 0 ${i.value.width <= 0 ? 10 : i.value.width} ${i.value.height <= 0 ? 10 : i.value.height}`,
style: _(`max-width:100%; overflow: visible; background:transparent;color:${e.value.style.chart.color}`)
}, [
Oe(et),
t.$slots["chart-background"] ? (s(), u("foreignObject", {
key: 0,
x: 0,
y: 0,
width: i.value.width <= 0 ? 10 : i.value.width,
height: i.value.height <= 0 ? 10 : i.value.height,
style: {
pointerEvents: "none"
}
}, [
b(t.$slots, "chart-background", {}, void 0, !0)
], 8, ot)) : f("", !0),
C("defs", null, [
C("linearGradient", {
id: `funnel_area_${N.value}`,
x1: "0%",
x2: "100%",
y1: "0%",
y2: "0%"
}, [
C("stop", {
offset: "0%",
"stop-color": e.value.style.chart.backgroundColor,
"stop-opacity": 0
}, null, 8, rt),
C("stop", {
offset: "20%",
"stop-color": e.value.style.chart.area.color
}, null, 8, ut),
C("stop", {
offset: "100%",
"stop-color": e.value.style.chart.area.color
}, null, 8, it)
], 8, nt)
]),
e.value.style.chart.circleLinks.show ? (s(), u("line", q({ key: 1 }, we.value, {
stroke: e.value.style.chart.circleLinks.color,
"stroke-width": 12 * e.value.style.chart.circleLinks.widthRatio,
"stroke-linecap": "round",
class: {
animated: e.value.useCssAnimation
},
style: {
strokeDasharray: e.value.useCssAnimation ? k.value.height : 0,
strokeDashoffset: e.value.useCssAnimation ? k.value.height : 0
}
}), null, 16, ct)) : f("", !0),
(s(!0), u(V, null, B(r.value, ({ cx: a, cy: o, r: m, fill: h }, P) => (s(), u("circle", q({ ref_for: !0 }, { cx: a, cy: o, r: m, fill: h }, {
stroke: e.value.style.chart.circles.stroke,
"stroke-width": e.value.style.chart.circles.strokeWidth,
class: {
animated: e.value.useCssAnimation && !w.value
},
style: {
animationDelay: `${150 * P}ms`
}
}), null, 16, vt))), 256)),
(s(!0), u(V, null, B(r.value, (a, o) => (s(), u("text", {
x: a.cx,
y: a.cy + d.value.circles / 3 + e.value.style.chart.circles.dataLabels.offsetY,
"text-anchor": "middle",
"font-size": d.value.circles,
fill: e.value.style.chart.circles.dataLabels.adaptColorToBackground ? n(Be)(a.color) : e.value.style.chart.circles.dataLabels.color,
"font-weight": e.value.style.chart.circles.dataLabels.bold ? "bold" : "normal",
class: T({
animated: e.value.useCssAnimation && !w.value
}),
style: _({
animationDelay: `${150 * o}ms`
})
}, U(n(E)(
e.value.style.chart.circles.dataLabels.formatter,
a.proportion * 100,
n(G)({
v: a.proportion * 100,
s: "%",
r: e.value.style.chart.circles.dataLabels.rounding
}),
{ datapoint: a }
)), 15, dt))), 256)),
e.value.style.chart.area.show ? (s(), u("polygon", {
key: 2,
points: Ce.value,
fill: `url(#funnel_area_${N.value})`,
class: T({
animated: e.value.useCssAnimation && !w.value
}),
style: _({
transition: e.value.useCssAnimation ? `all ${150 * p.value.length}ms ease-in` : "none"
})
}, null, 14, ht)) : f("", !0),
(s(!0), u(V, null, B(r.value, ({ x: a, y: o, height: m, width: h, fill: P }, X) => (s(), u("rect", q({ ref_for: !0 }, { x: a, y: o, height: m, width: h, fill: P }, {
stroke: e.value.style.chart.bars.stroke,
"stroke-width": e.value.style.chart.bars.strokeWidth,
rx: e.value.style.chart.bars.borderRadius,
class: {
animated: e.value.useCssAnimation && !w.value
},
style: {
animationDelay: `${150 * X}ms`
}
}), null, 16, ft))), 256)),
(s(!0), u(V, null, B(r.value, (a, o) => (s(), u("g", null, [
C("text", {
x: a.x + a.width + e.value.style.chart.bars.dataLabels.name.offsetX + 12,
y: a.cy - d.value.names / 2 + e.value.style.chart.bars.dataLabels.name.offsetY,
"text-anchor": "start",
"font-size": d.value.names,
fill: e.value.style.chart.bars.dataLabels.name.color,
"font-weight": e.value.style.chart.bars.dataLabels.name.bold ? "bold" : "normal",
class: T({
animated: e.value.useCssAnimation && !w.value
}),
style: _({
animationDelay: `${150 * o}ms`
})
}, U(a.name), 15, mt),
C("text", {
x: a.x + a.width + e.value.style.chart.bars.dataLabels.value.offsetX + 12,
y: a.cy + d.value.values + e.value.style.chart.bars.dataLabels.value.offsetY,
"text-anchor": "start",
"font-size": d.value.values,
fill: e.value.style.chart.bars.dataLabels.value.color,
"font-weight": e.value.style.chart.bars.dataLabels.value.bold ? "bold" : "normal",
class: T({
animated: e.value.useCssAnimation && !w.value
}),
style: _({
animationDelay: `${150 * o}ms`
})
}, U(n(E)(
e.value.style.chart.bars.dataLabels.value.formatter,
a.value,
n(G)({
p: e.value.style.chart.bars.dataLabels.value.prefix,
v: a.value,
s: e.value.style.chart.bars.dataLabels.value.suffix,
r: e.value.style.chart.bars.dataLabels.value.rounding
}),
{ datapoint: a }
)), 15, bt)
]))), 256)),
b(t.$slots, "svg", { svg: i.value }, void 0, !0)
], 14, st)) : f("", !0),
t.$slots.watermark ? (s(), u("div", yt, [
b(t.$slots, "watermark", M(R({ isPrinting: n(re) || n(ue) })), void 0, !0)
])) : f("", !0),
x.value ? f("", !0) : (s(), A(Qe, {
key: 6,
config: {
type: "verticalBar",
style: {
backgroundColor: e.value.style.chart.backgroundColor,
verticalBar: {
axis: {
color: "#CCCCCC"
},
color: "#CCCCCC"
}
}
}
}, null, 8, ["config"])),
t.$slots.source ? (s(), u("div", {
key: 7,
ref_key: "source",
ref: ee,
dir: "auto"
}, [
b(t.$slots, "source", {}, void 0, !0)
], 512)) : f("", !0),
x.value ? (s(), A(We, {
key: 8,
hideDetails: "",
config: {
open: O.value.showTable,
maxHeight: 1e4,
body: {
backgroundColor: e.value.style.chart.backgroundColor,
color: e.value.style.chart.color
},
head: {
backgroundColor: e.value.style.chart.backgroundColor,
color: e.value.style.chart.color
}
}
}, {
content: g(() => [
(s(), A(Ye, {
key: `table_${Q.value}`,
colNames: D.value.colNames,
head: D.value.head,
body: D.value.body,
config: D.value.config,
title: `${e.value.style.chart.title.text}${e.value.style.chart.title.subtitle.text ? ` : ${e.value.style.chart.title.subtitle.text}` : ""}`,
onClose: l[0] || (l[0] = (a) => O.value.showTable = !1)
}, {
th: g(({ th: a }) => [
C("div", {
innerHTML: a,
style: { display: "flex", "align-items": "center" }
}, null, 8, gt)
]),
td: g(({ td: a }) => [
ze(U(a.name ? a.name : a), 1)
]),
_: 1
}, 8, ["colNames", "head", "body", "config", "title"]))
]),
_: 1
}, 8, ["config"])) : f("", !0)
], 46, lt));
}
}, Ft = /* @__PURE__ */ at(pt, [["__scopeId", "data-v-fb07d7cc"]]);
export {
Ft as default
};