UNPKG

vue-data-ui

Version:

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

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