UNPKG

vue-data-ui

Version:

A user-empowering data visualization Vue 3 components library for eloquent data storytelling

657 lines (656 loc) 24.6 kB
import { useCssVars as nt, defineAsyncComponent as m, computed as y, onMounted as rt, ref as i, toRefs as it, watch as Q, nextTick as x, createElementBlock as C, openBlock as u, unref as l, normalizeStyle as E, normalizeClass as Ae, createBlock as k, createCommentVNode as g, createVNode as N, createSlots as ut, withCtx as d, renderSlot as c, normalizeProps as w, guardReactiveProps as $, createElementVNode as L, Fragment as ct, renderList as dt, createTextVNode as vt, toDisplayString as pt } from "vue"; import { u as ht, o as ft, f as mt, c as ke, t as gt, a as Ct, p as we, b as bt, d as yt, Q as At, X as kt, l as wt, R as $t, e as $e, v as Tt, w as _t, y as Ot, z as It } from "./index-q-LPw2IT.js"; import { u as Pt, B as Ft } from "./useLoading-D7YHNtLX.js"; import { u as Nt } from "./usePrinter-DX7efa1s.js"; import { u as Te } from "./useNestedProp-04aFeUYu.js"; import { u as Lt } from "./useUserOptionState-BIvW1Kz7.js"; import { u as St } from "./useChartAccessibility-9icAAmYg.js"; import Dt from "./img-Ctts6JQb.js"; import { u as Bt } from "./usePanZoom-BVca3eMk.js"; import { _ as xt } from "./_plugin-vue_export-helper-CHgC5LLL.js"; const Et = ["id"], Rt = { key: 1, ref: "noTitle", class: "vue-data-ui-no-title-space", style: "height:36px; width: 100%;background:transparent" }, Ut = { key: 2, style: "width:100%;background:transparent;" }, zt = ["xmlns", "viewBox"], Ht = ["width", "height"], Mt = ["id"], Vt = ["stop-color"], Gt = ["stop-color"], Wt = { key: 4, class: "vue-data-ui-watermark" }, Xt = { key: 5, "data-dom-to-png-ignore": "", class: "reset-wrapper" }, jt = { key: 6, ref: "source", dir: "auto" }, Yt = ["innerHTML"], Zt = { __name: "vue-ui-molecule", props: { config: { type: Object, default() { return {}; } }, dataset: { type: Array, default() { return []; } } }, emits: ["selectNode"], setup(_e, { expose: Oe, emit: Ie }) { nt((t) => ({ "00aed812": t.slicerColor })); const Pe = m(() => import("./Title-B55R8CAZ.js")), Fe = m(() => import("./Tooltip-BMOddG-M.js")), Ne = m(() => import("./BaseIcon-CCivwZUq.js")), Le = m(() => import("./vue-ui-accordion-D46i_gkB.js")), Se = m(() => import("./DataTable-rj9-mAwF.js")), De = m(() => import("./PenAndPaper-BJ0hcgsa.js")), Be = m(() => import("./UserOptions-DVzyjG-W.js")), xe = m(() => import("./PackageVersion-5ZjKSIei.js")), Ee = m(() => import("./RecursiveLinks-00zGWPf9.js")), Re = m(() => import("./RecursiveLabels-Bgcv0pzu.js")), Ue = m(() => import("./RecursiveCircles-BcLb1aRS.js")), { vue_ui_molecule: ze } = ht(), A = _e, He = Ie, q = y(() => !!A.dataset && A.dataset.length); rt(() => { J(); }); const Me = y(() => e.value.debug); function J() { ft(A.dataset) && mt({ componentName: "VueUiMolecule", type: "dataset", debug: Me.value }); } const R = i(ke()), Ve = i(null), U = i(!1), S = i(""), T = i(null), K = i(0), ee = i(0), te = i(0), e = i(G()), { loading: z, FINAL_DATASET: H } = Pt({ ...it(A), FINAL_CONFIG: e, prepareConfig: G, skeletonDataset: [ { name: "_", color: "#CACACA", nodes: [ { name: "_", color: "#CACACA", nodes: [ { name: "_", color: "#CACACA" }, { name: "_", color: "#CACACA" }, { name: "_", color: "#CACACA" } ] }, { name: "_", color: "#CACACA", nodes: [ { name: "_", color: "#CACACA" }, { name: "_", color: "#CACACA" }, { name: "_", color: "#CACACA" } ] }, { name: "_", color: "#CACACA", nodes: [ { name: "_", color: "#CACACA" }, { name: "_", color: "#CACACA" }, { name: "_", color: "#CACACA" } ] }, { name: "_", color: "#CACACA", nodes: [ { name: "_", color: "#CACACA" }, { name: "_", color: "#CACACA" }, { name: "_", color: "#CACACA" } ] }, { name: "_", color: "#CACACA", nodes: [ { name: "_", color: "#CACACA" }, { name: "_", color: "#CACACA" }, { name: "_", color: "#CACACA" } ] }, { name: "_", color: "#CACACA", nodes: [ { name: "_", color: "#CACACA" }, { name: "_", color: "#CACACA" }, { name: "_", color: "#CACACA" } ] } ] } ], skeletonConfig: gt({ defaultConfig: e.value, userConfig: { userOptions: { show: !1 }, table: { show: !1 }, style: { chart: { backgroundColor: "#99999930", nodes: { stroke: "#6A6A6A" }, links: { stroke: "#6A6A6A80" } } } } }) }), { userOptionsVisible: M, setUserOptionsVisibility: oe, keepUserOptionState: le } = Lt({ config: e.value }), { svgRef: V } = St({ config: e.value.style.chart.title }); function G() { const t = Te({ userConfig: A.config, defaultConfig: ze }); return t.theme ? { ...Te({ userConfig: bt.vue_ui_molecule[t.theme] || A.config, defaultConfig: t }), customPalette: Ct[t.theme] || we } : t; } Q(() => A.config, (t) => { e.value = G(), M.value = !e.value.userOptions.showOnChartHover, J(), ee.value += 1, te.value += 1, v.value.showTable = e.value.table.show, v.value.showTooltip = e.value.style.chart.tooltip.show; }, { deep: !0 }); const ae = i(0), Ge = () => { ae.value += 1; }; Q([() => z.value, () => H.value], async ([t]) => { t || (await x(), p.value = ce(), await x(), Ge(), await x(), ot({ x: 0, y: 0, width: 400, height: 400 }), j(!1)); }, { flush: "post", deep: !1 }); const { isPrinting: se, isImaging: ne, generatePdf: re, generateImage: ie } = Nt({ elementId: `cluster_${R.value}`, fileName: e.value.style.chart.title.text || "vue-ui-molecule", options: e.value.userOptions.print }), We = y(() => e.value.userOptions.show && !e.value.style.chart.title.text), Xe = y(() => yt(e.value.customPalette)), v = i({ showTable: e.value.table.show, showDataLabels: !0, showTooltip: e.value.style.chart.tooltip.show }); Q(e, () => { v.value = { showTable: e.value.table.show, showDataLabels: !0, showTooltip: e.value.style.chart.tooltip.show }; }, { immediate: !0 }); function ue(t, a = 0) { return Array.isArray(t) && t.length > 0 && t[0].nodes ? ue(t[0].nodes, a + 1) : a; } function ce() { const t = ue(H.value); let a = 100, o = a; for (let n = 0; n < t; n += 1) a /= 1, o += a; return { height: o, width: o }; } const p = i(ce()); function de(t, a = { x: -p.value.width / 2.43, y: p.value.height / 2 }, o = p.value.width / 1.1, n = 24, s = 0, r = 0, h = "#BBBBBB", Y = 0) { if (!Array.isArray(t) || t.length === 0) return t; const st = $t({ plot: a, radius: o, sides: t.length, rotation: s }); return t.forEach((f, Ce) => { const be = st.coordinates[Ce], ye = f.color ? (() => { let Z = $e(f.color); return Z.startsWith("#") ? Z : `#${Z}`; })() : null; let O; ye ? O = ye : Y === 0 ? O = h : Y === 1 ? (O = Xe.value[r] || we[r] || h, r += 1) : O = h, f.polygonPath = { coordinates: [be] }, f.circleRadius = n, f.color = O, f.uid = ke(), Array.isArray(f.nodes) && f.nodes.length && (f.nodes = de( f.nodes, be, o / 2.9, n / 2.2, s + Math.PI * Ce / f.nodes.length, r, O, Y + 1 )); }), t; } function je(t) { const a = /* @__PURE__ */ new Set(); function o(s) { s.forEach((r) => { if (!r.color) return; let h = r.color; /^#?[0-9A-F]{6}$/i.test(h) || (h = $e(h)), h.startsWith("#") || (h = `#${h}`), a.add(h), Array.isArray(r.nodes) && r.nodes.length && o(r.nodes); }); } o(t); const n = {}; return Array.from(a).forEach((s) => { const r = s.slice(1); n[s] = `gradient_${r}`; }), n; } const Ye = y(() => je(b.value)), b = y(() => { const t = At(H.value); return de(t); }), W = i(null); function Ze(t) { W.value = { datapoint: t, seriesIndex: -1, series: b.value, config: e.value }; const a = e.value.style.chart.tooltip.customFormat; if (Ot(a) && It(() => a({ seriesIndex: -1, datapoint: t, series: b.value, config: e.value }))) S.value = a({ seriesIndex: -1, // well, ok datapoint: t, series: b.value, config: e.value }); else { let o = ""; o += `<div style="display:flex;align-items:center;gap:3px"><div style="color:${t.color}">⬤</div><div>${t.name}</div></div>`, t.details && (o += `<div style="width:100%;border-top:1px solid ${e.value.style.chart.tooltip.borderColor};margin-top: 2px">${t.details}</div>`), S.value = `<div style="font-family:inherit">${o}</div>`; } } const D = i(null), I = i(null), ve = i(null); function Qe(t) { ve.value = D.value, D.value = t, t ? e.value.events.datapointEnter && e.value.events.datapointEnter({ datapoint: t, seriesIndex: -1 }) : e.value.events.datapointLeave && e.value.events.datapointLeave({ datapoint: ve.value || D.value, seriesIndex: -1 }), t ? (U.value = !0, Ze(t), I.value = t.uid) : (U.value = !1, S.value = "", I.value = null); } function qe(t) { const a = []; function o(n) { n.forEach((s) => { const r = { name: s.name, details: s.details || "-", ancestor: s.ancestor && s.ancestor.name || "-", color: s.color || "" }; a.push(r), s.nodes && s.nodes.length > 0 && o(s.nodes, s.name); }); } return o(t), a; } const Je = y(() => qe(b.value)), _ = y(() => { const t = [ e.value.table.translations.nodeName, e.value.table.translations.details, e.value.table.translations.ancestor ], a = Je.value.map((s, r) => [ { color: s.color, name: s.name }, s.details, s.ancestor || "" ]), o = { 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 }, n = [ e.value.table.translations.nodeName, e.value.table.translations.details, e.value.table.translations.ancestor ]; return { head: t, body: a, config: o, colNames: n }; }); function pe(t = null) { x(() => { const a = _.value.body.map((s, r) => [[s[0].name], [s[1]], [s[2]]]), o = [[e.value.style.chart.title.text], [e.value.style.chart.title.subtitle.text], [[..._.value.head]]].concat(a), n = Tt(o); t ? t(n) : _t({ csvContent: n, title: e.value.style.chart.title.text || "vue-ui-molecule" }); }); } function Ke() { return b.value; } const P = i(!1); function he(t) { P.value = t, K.value += 1; } function fe() { v.value.showTable = !v.value.showTable; } function me() { v.value.showDataLabels = !v.value.showDataLabels; } function ge() { v.value.showTooltip = !v.value.showTooltip; } const F = i(!1); function X() { F.value = !F.value; } const et = y(() => !F.value), { viewBox: B, resetZoom: j, isZoom: tt, setInitialViewBox: ot } = Bt(V, { x: 0, y: 0, width: Math.max(10, p.value.width), height: Math.max(10, p.value.height) }, e.value.style.chart.zoom.speed, et); function lt(t) { e.value.events.datapointClick && e.value.events.datapointClick({ datapoint: t, seriesIndex: -1 }), He("selectNode", t); } async function at({ scale: t = 2 } = {}) { if (!T.value) return; const { width: a, height: o } = T.value.getBoundingClientRect(), n = a / o, { imageUri: s, base64: r } = await Dt({ domElement: T.value, base64: !0, img: !0, scale: t }); return { imageUri: s, base64: r, title: e.value.style.chart.title.text, width: a, height: o, aspectRatio: n }; } return Oe({ getData: Ke, getImage: at, generatePdf: re, generateCsv: pe, generateImage: ie, toggleTable: fe, toggleLabels: me, toggleTooltip: ge, toggleAnnotator: X, toggleFullscreen: he }), (t, a) => (u(), C("div", { ref_key: "moleculeChart", ref: T, class: Ae(`vue-ui-molecule ${P.value ? "vue-data-ui-wrapper-fullscreen" : ""}`), style: E(`font-family:${e.value.style.fontFamily};width:100%; text-align:center;background:${e.value.style.chart.backgroundColor}`), id: `cluster_${R.value}`, onMouseleave: a[2] || (a[2] = (o) => { D.value = null, I.value = null, l(oe)(!1); }), onMouseenter: a[3] || (a[3] = () => l(oe)(!0)) }, [ e.value.userOptions.buttons.annotator ? (u(), k(l(De), { key: 0, svgRef: l(V), backgroundColor: e.value.style.chart.backgroundColor, color: e.value.style.chart.color, active: F.value, onClose: X }, null, 8, ["svgRef", "backgroundColor", "color", "active"])) : g("", !0), We.value ? (u(), C("div", Rt, null, 512)) : g("", !0), e.value.style.chart.title.text ? (u(), C("div", Ut, [ (u(), k(l(Pe), { key: `title_${ee.value}`, config: { title: { cy: "molecule-div-title", ...e.value.style.chart.title }, subtitle: { cy: "molecule-div-subtitle", ...e.value.style.chart.title.subtitle } } }, null, 8, ["config"])) ])) : g("", !0), e.value.userOptions.show && q.value && (l(le) || l(M)) ? (u(), k(l(Be), { ref_key: "details", ref: Ve, key: `user_options_${K.value}`, backgroundColor: e.value.style.chart.backgroundColor, color: e.value.style.chart.color, isPrinting: l(se), isImaging: l(ne), uid: R.value, hasTooltip: e.value.userOptions.buttons.tooltip && e.value.style.chart.tooltip.show, hasPdf: e.value.userOptions.buttons.pdf, hasXls: e.value.userOptions.buttons.csv, hasImg: e.value.userOptions.buttons.img, hasTable: e.value.userOptions.buttons.table, hasLabel: e.value.userOptions.buttons.labels, hasFullscreen: e.value.userOptions.buttons.fullscreen, isTooltip: v.value.showTooltip, titles: { ...e.value.userOptions.buttonTitles }, chartElement: T.value, position: e.value.userOptions.position, hasAnnotator: e.value.userOptions.buttons.annotator, isAnnotation: F.value, callbacks: e.value.userOptions.callbacks, printScale: e.value.userOptions.print.scale, onToggleFullscreen: he, onGeneratePdf: l(re), onGenerateCsv: pe, onGenerateImage: l(ie), onToggleTable: fe, onToggleLabels: me, onToggleTooltip: ge, onToggleAnnotator: X, style: E({ visibility: l(le) ? l(M) ? "visible" : "hidden" : "visible" }) }, ut({ _: 2 }, [ t.$slots.menuIcon ? { name: "menuIcon", fn: d(({ isOpen: o, color: n }) => [ c(t.$slots, "menuIcon", w($({ isOpen: o, color: n })), void 0, !0) ]), key: "0" } : void 0, t.$slots.optionTooltip ? { name: "optionTooltip", fn: d(() => [ c(t.$slots, "optionTooltip", {}, void 0, !0) ]), key: "1" } : void 0, t.$slots.optionPdf ? { name: "optionPdf", fn: d(() => [ c(t.$slots, "optionPdf", {}, void 0, !0) ]), key: "2" } : void 0, t.$slots.optionCsv ? { name: "optionCsv", fn: d(() => [ c(t.$slots, "optionCsv", {}, void 0, !0) ]), key: "3" } : void 0, t.$slots.optionImg ? { name: "optionImg", fn: d(() => [ c(t.$slots, "optionImg", {}, void 0, !0) ]), key: "4" } : void 0, t.$slots.optionTable ? { name: "optionTable", fn: d(() => [ c(t.$slots, "optionTable", {}, void 0, !0) ]), key: "5" } : void 0, t.$slots.optionLabels ? { name: "optionLabels", fn: d(() => [ c(t.$slots, "optionLabels", {}, void 0, !0) ]), key: "6" } : void 0, t.$slots.optionFullscreen ? { name: "optionFullscreen", fn: d(({ toggleFullscreen: o, isFullscreen: n }) => [ c(t.$slots, "optionFullscreen", w($({ toggleFullscreen: o, isFullscreen: n })), void 0, !0) ]), key: "7" } : void 0, t.$slots.optionAnnotator ? { name: "optionAnnotator", fn: d(({ toggleAnnotator: o, isAnnotator: n }) => [ c(t.$slots, "optionAnnotator", w($({ toggleAnnotator: o, isAnnotator: n })), void 0, !0) ]), key: "8" } : void 0 ]), 1032, ["backgroundColor", "color", "isPrinting", "isImaging", "uid", "hasTooltip", "hasPdf", "hasXls", "hasImg", "hasTable", "hasLabel", "hasFullscreen", "isTooltip", "titles", "chartElement", "position", "hasAnnotator", "isAnnotation", "callbacks", "printScale", "onGeneratePdf", "onGenerateImage", "style"])) : g("", !0), (u(), C("svg", { ref_key: "svgRef", ref: V, key: `svg_${ae.value}`, xmlns: l(kt), viewBox: `${l(B).x} ${l(B).y} ${l(B).width} ${l(B).height}`, class: Ae({ "vue-data-ui-fullscreen--on": P.value, "vue-data-ui-fulscreen--off": !P.value }), style: E(`overflow: hidden; background:transparent;color:${e.value.style.chart.color}`) }, [ N(l(xe)), t.$slots["chart-background"] ? (u(), C("foreignObject", { key: 0, x: 0, y: 0, width: p.value.width <= 0 ? 10 : p.value.width, height: p.value.height <= 0 ? 10 : p.value.height, style: { pointerEvents: "none" } }, [ c(t.$slots, "chart-background", {}, void 0, !0) ], 8, Ht)) : g("", !0), L("defs", null, [ (u(!0), C(ct, null, dt(Object.keys(Ye.value), (o) => (u(), C("radialGradient", { id: `gradient_${o}`, cx: "50%", cy: "30%", r: "50%", fx: "50%", fy: "50%" }, [ L("stop", { offset: "0%", "stop-color": l(wt)(o, 0.5) }, null, 8, Vt), L("stop", { offset: "100%", "stop-color": o }, null, 8, Gt) ], 8, Mt))), 256)) ]), N(l(Ee), { dataset: b.value, color: e.value.style.chart.links.stroke, backgroundColor: e.value.style.chart.backgroundColor }, null, 8, ["dataset", "color", "backgroundColor"]), N(l(Ue), { dataset: b.value, hoveredUid: I.value, stroke: e.value.style.chart.nodes.stroke, strokeHovered: e.value.style.chart.nodes.strokeHovered, onClick: lt, onHover: Qe }, { node: d(({ node: o }) => [ c(t.$slots, "node", w($({ node: o })), void 0, !0) ]), _: 3 }, 8, ["dataset", "hoveredUid", "stroke", "strokeHovered"]), v.value.showDataLabels && !l(z) ? (u(), k(l(Re), { key: 1, dataset: b.value, color: e.value.style.chart.color, hoveredUid: I.value }, null, 8, ["dataset", "color", "hoveredUid"])) : g("", !0), c(t.$slots, "svg", { svg: p.value }, void 0, !0) ], 14, zt)), t.$slots.watermark ? (u(), C("div", Wt, [ c(t.$slots, "watermark", w($({ isPrinting: l(se) || l(ne) })), void 0, !0) ])) : g("", !0), l(tt) ? (u(), C("div", Xt, [ c(t.$slots, "reset-action", { reset: l(j) }, () => [ L("button", { "data-cy-reset": "", tabindex: "0", role: "button", class: "vue-data-ui-refresh-button", style: E({ background: e.value.style.chart.backgroundColor }), onClick: a[0] || (a[0] = (o) => l(j)(!0)) }, [ N(l(Ne), { name: "refresh", stroke: e.value.style.chart.color }, null, 8, ["stroke"]) ], 4) ], !0) ])) : g("", !0), t.$slots.source ? (u(), C("div", jt, [ c(t.$slots, "source", {}, void 0, !0) ], 512)) : g("", !0), N(l(Fe), { show: v.value.showTooltip && U.value, backgroundColor: e.value.style.chart.tooltip.backgroundColor, color: e.value.style.chart.tooltip.color, borderRadius: e.value.style.chart.tooltip.borderRadius, borderColor: e.value.style.chart.tooltip.borderColor, borderWidth: e.value.style.chart.tooltip.borderWidth, fontSize: e.value.style.chart.tooltip.fontSize, backgroundOpacity: e.value.style.chart.tooltip.backgroundOpacity, position: e.value.style.chart.tooltip.position, offsetY: e.value.style.chart.tooltip.offsetY, parent: T.value, content: S.value, isFullscreen: P.value, isCustom: e.value.style.chart.tooltip.customFormat && typeof e.value.style.chart.tooltip.customFormat == "function", smooth: e.value.style.chart.tooltip.smooth, backdropFilter: e.value.style.chart.tooltip.backdropFilter }, { "tooltip-before": d(() => [ c(t.$slots, "tooltip-before", w($({ ...W.value })), void 0, !0) ]), "tooltip-after": d(() => [ c(t.$slots, "tooltip-after", w($({ ...W.value })), void 0, !0) ]), _: 3 }, 8, ["show", "backgroundColor", "color", "borderRadius", "borderColor", "borderWidth", "fontSize", "backgroundOpacity", "position", "offsetY", "parent", "content", "isFullscreen", "isCustom", "smooth", "backdropFilter"]), q.value ? (u(), k(l(Le), { key: 7, hideDetails: "", config: { open: v.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: d(() => [ (u(), k(l(Se), { key: `table_${te.value}`, colNames: _.value.colNames, head: _.value.head, body: _.value.body, config: _.value.config, title: `${e.value.style.chart.title.text}${e.value.style.chart.title.subtitle.text ? ` : ${e.value.style.chart.title.subtitle.text}` : ""}`, onClose: a[1] || (a[1] = (o) => v.value.showTable = !1) }, { th: d(({ th: o }) => [ L("div", { innerHTML: o, style: { display: "flex", "align-items": "center" } }, null, 8, Yt) ]), td: d(({ td: o }) => [ vt(pt(o.name || o), 1) ]), _: 1 }, 8, ["colNames", "head", "body", "config", "title"])) ]), _: 1 }, 8, ["config"])) : g("", !0), l(z) ? (u(), k(Ft, { key: 8 })) : g("", !0) ], 46, Et)); } }, no = /* @__PURE__ */ xt(Zt, [["__scopeId", "data-v-8a23b240"]]); export { no as default };