UNPKG

vue-data-ui-hq

Version:

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

540 lines (539 loc) 19.6 kB
import { computed as g, onMounted as ze, ref as b, watch as Ye, openBlock as u, createElementBlock as c, normalizeClass as me, unref as e, normalizeStyle as x, createBlock as P, createCommentVNode as k, createSlots as De, withCtx as w, renderSlot as m, normalizeProps as W, guardReactiveProps as q, createVNode as ye, createElementVNode as M, Fragment as F, renderList as I, toDisplayString as R, createTextVNode as Ge, nextTick as Ue } from "vue"; import { u as Ve, o as Be, e as je, c as be, t as Xe, a as We, p as Z, b as qe, v as f, f as ke, X as Re, G as we, L as Ze, i as Je, q as Ke, r as Qe } from "./index-WrV3SAID.js"; import { _ as et } from "./Title-BR-xoRp4.js"; import { u as tt, U as ot } from "./usePrinter-kVpf1iV8.js"; import { D as nt } from "./DataTable-DNPvKWC0.js"; import lt from "./vue-ui-accordion-BQCDXXDs.js"; import st from "./vue-ui-skeleton-Qec_XSRf.js"; import { u as Ce } from "./useNestedProp-Cj0kHD7k.js"; import { _ as at } from "./PackageVersion-1NslmM8M.js"; import { P as rt } from "./PenAndPaper-BF1ZRVm3.js"; import { u as it } from "./useUserOptionState-BIvW1Kz7.js"; import { _ as ut } from "./_plugin-vue_export-helper-CHgC5LLL.js"; const ct = ["id"], dt = { key: 1, ref: "noTitle", class: "vue-data-ui-no-title-space", style: "height:36px; width: 100%;background:transparent" }, ht = { key: 2, style: "width:100%;background:transparent;padding-bottom:24px" }, ft = ["xmlns", "viewBox"], pt = ["width", "height"], gt = ["id"], vt = ["stop-color"], mt = ["stop-color"], yt = ["d", "fill", "stroke", "stroke-width"], bt = ["x", "y", "height", "width", "fill", "stroke", "stroke-width", "onMouseenter"], kt = ["x", "y", "font-size", "fill"], wt = ["x", "y", "font-size", "fill"], Ct = { key: 4, class: "vue-data-ui-watermark" }, $t = { key: 6, ref: "source", dir: "auto" }, xt = ["innerHTML"], _t = { __name: "vue-ui-flow", props: { config: { type: Object, default() { return {}; } }, dataset: { type: Array, default() { return []; } } }, setup($e, { expose: xe }) { const { vue_ui_flow: _e } = Ve(), v = $e, z = g(() => !!v.dataset && v.dataset.length); ze(() => { J(); }); function J() { Be(v.dataset) && je({ componentName: "VueUiFlow", type: "dataset" }); } const Y = b(be()), D = b(null), K = b(0), Q = b(0), T = b(!1); function Ne(o) { T.value = o, K.value += 1; } const t = g({ get: () => oe(), set: (o) => o }), { userOptionsVisible: G, setUserOptionsVisibility: ee, keepUserOptionState: te } = it({ config: t.value }); function oe() { const o = Ce({ userConfig: v.config, defaultConfig: _e }); return o.theme ? { ...Ce({ userConfig: Xe.vue_ui_flow[o.theme] || v.config, defaultConfig: o }), customPalette: We[o.theme] || Z } : o; } Ye(() => v.config, (o) => { t.value = oe(), G.value = !t.value.showOnChartHover, J(), Q.value += 1; }, { deep: !0 }); const { isPrinting: ne, isImaging: le, generatePdf: se, generateImage: ae } = tt({ elementId: `flow_${Y.value}`, fileName: t.value.style.chart.title.text || "vue-ui-flow" }), Te = g(() => t.value.userOptions.show && !t.value.style.chart.title.text), U = g(() => qe(t.value.customPalette)), re = g(() => t.value.style.chart.nodes.gap), _ = g(() => t.value.style.chart.nodes.width), L = b({ showTable: t.value.table.show }), ie = g(() => t.value.style.chart.links.width), V = g(() => !v.dataset || !v.dataset.length ? [] : v.dataset.map((o) => [ o[0], o[1], f(o[2]) ])), ue = g(() => { const o = {}; function l(a) { o[a] || (o[a] = { inflow: 0, outflow: 0 }); } V.value.forEach(([a, s, h]) => { l(a), l(s), o[a].outflow += h, o[s].inflow += h; }); let n = 0; for (const a in o) { const s = Math.max(o[a].inflow, o[a].outflow); n = Math.max(n, s); } return n; }); function Oe(o) { return o / ue.value * 100 + t.value.style.chart.nodes.minHeight; } function Pe(o) { const l = t.value.style.chart.nodes.minHeight; return (o - l) / 100 * ue.value; } function Fe(o) { const l = {}, n = {}; function a(r, i) { l[r] || (l[r] = { height: 0, level: null, inflow: 0, outflow: 0 }), l[r].level === null && (l[r].level = i), n[i] || (n[i] = []), n[i].includes(r) || n[i].push(r); } o.forEach(([r, i, p], N) => { const $ = l[r] ? l[r].level : 0, E = $ + 1; a(r, $), a(i, E), l[r].children || (l[r].children = []), l[r].children.push({ target: i, value: p }), l[r].outflow += p, l[i].inflow += p; }), Object.keys(l).forEach((r, i) => { l[r].color = U.value[i] || U.value[i % U.value.length] || Z[i] || Z[i % d.length]; }); for (const r in l) l[r].height = Oe(Math.max(l[r].inflow, l[r].outflow)), l[r].name = r; const s = {}; for (const r in n) { let i = 0; n[r].forEach((p, N) => { const $ = l[p].height; s[p] = { x: parseInt(r, 10) * ie.value + t.value.style.chart.padding.left, y: i, absoluteY: i, height: $, i: N, color: l[p].color, value: Pe($) }, i += $ + re.value; }); } const h = []; for (const r in l) { let i = s[r].absoluteY + t.value.style.chart.padding.top; l[r].children && l[r].children.forEach(({ target: p, value: N }, $) => { const E = s[p].y + t.value.style.chart.padding.top, j = s[r], X = s[p], fe = f(i), pe = f(i + N / l[r].outflow * j.height), ge = f(E), ve = f(E + N / l[p].inflow * X.height), Me = { id: be(), source: r, target: p, path: `M ${f(j.x) + f(_.value)} ${fe} L ${f(j.x) + f(_.value)} ${pe} L ${f(X.x)} ${ve} L ${f(X.x)} ${ge} Z`, value: N, sourceColor: l[r].color, targetColor: l[p].color }; h.push(Me), i += pe - fe, s[p].y += ve - ge; }); } return { nodeCoordinates: s, links: h }; } const y = g(() => { const o = Fe(v.dataset); return { nodes: Object.keys(o.nodeCoordinates).map((l, n) => ({ ...o.nodeCoordinates[l], name: l })), links: o.links }; }), Ie = g(() => Le(y.value.nodes)); function Le(o) { const l = {}; for (const a in o) { const { x: s, height: h } = o[a]; l[s] || (l[s] = 0), l[s] += h + re.value; } return Math.max(...Object.values(l)); } const O = g(() => { const { top: o, right: l, left: n, bottom: a } = t.value.style.chart.padding, s = V.value.length * ie.value; return { height: Ie.value + o + a, width: l + Math.max(...y.value.nodes.map((h) => h.x)) + _.value, left: n, top: o, right: s - l, p_top: o, p_bottom: a }; }); function Ae(o) { const l = {}, n = {}, a = /* @__PURE__ */ new Set(); return V.value.forEach(([s, h, r]) => { l[s] || (l[s] = []), n[h] || (n[h] = []), l[s].push(h), n[h].push(s); }), l[o] && l[o].forEach((s) => a.add(s)), n[o] && n[o].forEach((s) => a.add(s)), Array.from(a).concat(o); } const C = b(null), A = b(null); function He(o) { C.value = Ae(o.name), A.value = o.name; } function Se() { C.value = null, A.value = null; } const ce = g(() => y.value.links.map(({ source: o, target: l, sourceColor: n, targetColor: a, value: s }) => ({ source: o, target: l, sourceColor: n, targetColor: a, value: s }))); function de() { Ue(() => { const o = ce.value.map((a, s) => [ [a.source], [a.target], [a.value] ]), l = [ [t.value.style.chart.title.text], [t.value.style.chart.title.subtitle.text], [ [t.value.table.columnNames.source], [t.value.table.columnNames.target], [t.value.table.columnNames.value] ] ].concat(o), n = Ke(l); Qe({ csvContent: n, title: t.value.style.chart.title.text || "vue-ui-flow" }); }); } const H = g(() => { const o = [ t.value.table.columnNames.source, t.value.table.columnNames.target, t.value.table.columnNames.value ], l = ce.value.map((s, h) => [ { color: s.sourceColor, name: s.source }, { color: s.targetColor, name: s.target }, ke({ p: t.value.style.chart.nodes.labels.prefix, v: s.value, s: t.value.style.chart.nodes.labels.suffix, r: t.value.style.chart.nodes.labels.rounding }) ]), n = { th: { backgroundColor: t.value.table.th.backgroundColor, color: t.value.table.th.color, outline: t.value.table.th.outline }, td: { backgroundColor: t.value.table.td.backgroundColor, color: t.value.table.td.color, outline: t.value.table.td.outline }, breakpoint: t.value.table.responsiveBreakpoint }; return { colNames: [ t.value.table.columnNames.source, t.value.table.columnNames.target, t.value.table.columnNames.value ], head: o, body: l, config: n }; }); function Ee() { return y.value; } function he() { L.value.showTable = !L.value.showTable; } const S = b(!1); function B() { S.value = !S.value; } return xe({ getData: Ee, generateCsv: de, generateImage: ae, generatePdf: se, toggleTable: he, toggleAnnotator: B }), (o, l) => (u(), c("div", { ref_key: "flowChart", ref: D, class: me(`vue-ui-flow ${e(T) ? "vue-data-ui-wrapper-fullscreen" : ""}`), style: x(`font-family:${e(t).style.fontFamily};width:100%; text-align:center;background:${e(t).style.chart.backgroundColor}`), id: `flow_${e(Y)}`, onMouseenter: l[2] || (l[2] = () => e(ee)(!0)), onMouseleave: l[3] || (l[3] = () => e(ee)(!1)) }, [ e(t).userOptions.buttons.annotator ? (u(), P(rt, { key: 0, parent: e(D), backgroundColor: e(t).style.chart.backgroundColor, color: e(t).style.chart.color, active: e(S), onClose: B }, null, 8, ["parent", "backgroundColor", "color", "active"])) : k("", !0), e(Te) ? (u(), c("div", dt, null, 512)) : k("", !0), e(t).style.chart.title.text ? (u(), c("div", ht, [ (u(), P(et, { key: `title_${e(Q)}`, config: { title: { cy: "flow-title", ...e(t).style.chart.title }, subtitle: { cy: "flow-subtitle", ...e(t).style.chart.title.subtitle } } }, null, 8, ["config"])) ])) : k("", !0), e(t).userOptions.show && e(z) && (e(te) || e(G)) ? (u(), P(ot, { ref: "details", key: `user_option_${e(K)}`, backgroundColor: e(t).style.chart.backgroundColor, color: e(t).style.chart.color, isPrinting: e(ne), isImaging: e(le), uid: e(Y), hasPdf: e(t).userOptions.buttons.pdf, hasXls: e(t).userOptions.buttons.csv, hasImg: e(t).userOptions.buttons.img, hasTable: e(t).userOptions.buttons.table, hasFullscreen: e(t).userOptions.buttons.fullscreen, isFullscreen: e(T), titles: { ...e(t).userOptions.buttonTitles }, chartElement: e(D), position: e(t).userOptions.position, hasAnnotator: e(t).userOptions.buttons.annotator, isAnnotation: e(S), onToggleFullscreen: Ne, onGeneratePdf: e(se), onGenerateCsv: de, onGenerateImage: e(ae), onToggleTable: he, onToggleAnnotator: B, style: x({ visibility: e(te) ? e(G) ? "visible" : "hidden" : "visible" }) }, De({ _: 2 }, [ o.$slots.optionPdf ? { name: "optionPdf", fn: w(() => [ m(o.$slots, "optionPdf", {}, void 0, !0) ]), key: "0" } : void 0, o.$slots.optionCsv ? { name: "optionCsv", fn: w(() => [ m(o.$slots, "optionCsv", {}, void 0, !0) ]), key: "1" } : void 0, o.$slots.optionImg ? { name: "optionImg", fn: w(() => [ m(o.$slots, "optionImg", {}, void 0, !0) ]), key: "2" } : void 0, o.$slots.optionTable ? { name: "optionTable", fn: w(() => [ m(o.$slots, "optionTable", {}, void 0, !0) ]), key: "3" } : void 0, o.$slots.optionFullscreen ? { name: "optionFullscreen", fn: w(({ toggleFullscreen: n, isFullscreen: a }) => [ m(o.$slots, "optionFullscreen", W(q({ toggleFullscreen: n, isFullscreen: a })), void 0, !0) ]), key: "4" } : void 0, o.$slots.optionAnnotator ? { name: "optionAnnotator", fn: w(({ toggleAnnotator: n, isAnnotator: a }) => [ m(o.$slots, "optionAnnotator", W(q({ toggleAnnotator: n, isAnnotator: a })), void 0, !0) ]), key: "5" } : void 0 ]), 1032, ["backgroundColor", "color", "isPrinting", "isImaging", "uid", "hasPdf", "hasXls", "hasImg", "hasTable", "hasFullscreen", "isFullscreen", "titles", "chartElement", "position", "hasAnnotator", "isAnnotation", "onGeneratePdf", "onGenerateImage", "style"])) : k("", !0), (u(), c("svg", { xmlns: e(Re), viewBox: `0 0 ${e(O).width} ${e(O).height}`, class: me({ "vue-data-ui-fullscreen--on": e(T), "vue-data-ui-fulscreen--off": !e(T) }), style: x(`max-width:100%; overflow: visible; background:transparent;color:${e(t).style.chart.color}`) }, [ ye(at), o.$slots["chart-background"] ? (u(), c("foreignObject", { key: 0, x: 0, y: 0, width: e(O).width, height: e(O).height, style: { pointerEvents: "none" } }, [ m(o.$slots, "chart-background", {}, void 0, !0) ], 8, pt)) : k("", !0), M("defs", null, [ (u(!0), c(F, null, I(e(y).links, (n, a) => (u(), c("linearGradient", { id: n.id, x1: "0%", y1: "0%", x2: "100%", y2: "0%" }, [ M("stop", { offset: "0%", "stop-color": n.sourceColor }, null, 8, vt), M("stop", { offset: "100%", "stop-color": n.targetColor }, null, 8, mt) ], 8, gt))), 256)) ]), (u(!0), c(F, null, I(e(y).links, (n) => (u(), c("path", { class: "vue-ui-flow-link", d: n.path, fill: `url(#${n.id})`, stroke: e(t).style.chart.links.stroke, "stroke-width": e(t).style.chart.links.strokeWidth, style: x(`opacity:${e(A) ? [n.target, n.source].includes(e(A)) ? 1 : 0.3 : e(t).style.chart.links.opacity}`) }, null, 12, yt))), 256)), (u(!0), c(F, null, I(e(y).nodes, (n, a) => (u(), c("rect", { class: "vue-ui-flow-node", x: n.x, y: e(f)(n.absoluteY) + e(t).style.chart.padding.top, height: e(f)(n.height), width: e(_), fill: n.color, stroke: e(t).style.chart.nodes.stroke, "stroke-width": e(t).style.chart.nodes.strokeWidth, onMouseenter: (s) => He(n), onMouseleave: l[0] || (l[0] = (s) => Se()), style: x(`opacity:${e(C) ? e(C).includes(n.name) ? 1 : 0.2 : 1}`) }, null, 44, bt))), 256)), (u(!0), c(F, null, I(e(y).nodes, (n, a) => (u(), c("text", { x: n.x + e(_) / 2, y: e(f)(n.absoluteY + n.height / 2 - e(t).style.chart.nodes.labels.fontSize / 4) + e(t).style.chart.padding.top, "font-size": e(t).style.chart.nodes.labels.fontSize, fill: e(we)(n.color), "text-anchor": "middle", style: x(`pointer-events: none; opacity:${e(C) ? e(C).includes(n.name) ? 1 : 0 : 1}`) }, R(e(t).style.chart.nodes.labels.abbreviation.use ? e(Ze)({ source: n.name, length: e(t).style.chart.nodes.labels.abbreviation.length }) : n.name), 13, kt))), 256)), (u(!0), c(F, null, I(e(y).nodes, (n, a) => (u(), c("text", { x: n.x + e(_) / 2, y: e(f)(n.absoluteY + n.height / 2 + e(t).style.chart.nodes.labels.fontSize) + e(t).style.chart.padding.top, "font-size": e(t).style.chart.nodes.labels.fontSize, fill: e(we)(n.color), "text-anchor": "middle", style: x(`pointer-events: none; opacity:${e(C) ? e(C).includes(n.name) ? 1 : 0 : 1}`) }, R(e(Je)( e(t).style.chart.nodes.labels.formatter, n.value, e(ke)({ p: e(t).style.chart.nodes.labels.prefix, v: n.value, s: e(t).style.chart.nodes.labels.suffix, r: e(t).style.chart.nodes.labels.rounding }), { datapoint: n, seriesIndex: a } )), 13, wt))), 256)), m(o.$slots, "svg", { svg: e(O) }, void 0, !0) ], 14, ft)), o.$slots.watermark ? (u(), c("div", Ct, [ m(o.$slots, "watermark", W(q({ isPrinting: e(ne) || e(le) })), void 0, !0) ])) : k("", !0), e(z) ? k("", !0) : (u(), P(st, { key: 5, config: { type: "flow", style: { backgroundColor: e(t).style.chart.backgroundColor } } }, null, 8, ["config"])), o.$slots.source ? (u(), c("div", $t, [ m(o.$slots, "source", {}, void 0, !0) ], 512)) : k("", !0), e(z) ? (u(), P(lt, { key: 7, hideDetails: "", config: { open: e(L).showTable, maxHeight: 1e4, body: { backgroundColor: e(t).style.chart.backgroundColor, color: e(t).style.chart.color }, head: { backgroundColor: e(t).style.chart.backgroundColor, color: e(t).style.chart.color } } }, { content: w(() => [ ye(nt, { colNames: e(H).colNames, head: e(H).head, body: e(H).body, config: e(H).config, title: `${e(t).style.chart.title.text}${e(t).style.chart.title.subtitle.text ? ` : ${e(t).style.chart.title.subtitle.text}` : ""}`, onClose: l[1] || (l[1] = (n) => e(L).showTable = !1) }, { th: w(({ th: n }) => [ M("div", { innerHTML: n, style: { display: "flex", "align-items": "center" } }, null, 8, xt) ]), td: w(({ td: n }) => [ Ge(R(n.name || n), 1) ]), _: 1 }, 8, ["colNames", "head", "body", "config", "title"]) ]), _: 1 }, 8, ["config"])) : k("", !0) ], 46, ct)); } }, zt = /* @__PURE__ */ ut(_t, [["__scopeId", "data-v-ae461a22"]]); export { zt as default };