UNPKG

vue-data-ui

Version:

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

646 lines (645 loc) 23.6 kB
import { useCssVars as Ge, computed as y, createElementBlock as m, openBlock as r, createElementVNode as N, renderSlot as i, createVNode as ne, normalizeStyle as J, ref as n, watch as H, onMounted as Le, onBeforeUnmount as Xe, unref as c, createBlock as M, createCommentVNode as k, createSlots as je, withCtx as h, normalizeProps as S, guardReactiveProps as F, normalizeClass as $e, Fragment as qe, renderList as He, toDisplayString as xe, createTextVNode as Ye, nextTick as Te } from "vue"; import { u as Je, c as Se, a5 as Ke, v as Qe, t as Ze, p as Y, a as et, o as tt, e as Fe, g as ot, f as at, X as lt, q as st, r as nt, x as rt } from "./index-CHWA6Lnw.js"; import { _ as ut } from "./Title-BwZtefYd.js"; import { u as it, U as ct } from "./usePrinter-DibtVl2x.js"; import { d as dt, t as vt, u as ht } from "./useResponsive-vZgZwV-S.js"; import mt from "./vue-ui-accordion-gHGrRoVr.js"; import { D as ft } from "./DataTable-B4YF6guk.js"; import pt from "./BaseIcon-AmoKryXo.js"; import { _ as ze } from "./_plugin-vue_export-helper-CHgC5LLL.js"; import { u as Ne } from "./useNestedProp-ByBiJC9_.js"; import { _ as gt } from "./PackageVersion-DcMafJMi.js"; import { _ as yt } from "./Tooltip-eCCz9HFo.js"; import { P as bt } from "./PenAndPaper-ljJaW1FE.js"; import { u as Ct } from "./useUserOptionState-BIvW1Kz7.js"; import { u as kt } from "./useChartAccessibility-BWojgys7.js"; const wt = { "data-html2canvas-ignore": "" }, $t = { key: 0, class: "reset-wrapper" }, xt = { key: 1, class: "reset-wrapper" }, Tt = { class: "mono-slicer" }, St = ["min", "max", "value"], Ft = { __name: "MonoSlicer", props: { min: { type: Number, default: 0 }, max: { type: Number, default: 0 }, inputColor: { type: String, default: "#1A1A1A" }, background: { type: String, default: "#FFFFFF" }, borderColor: { type: String, default: "#FFFFFF" }, selectColor: { type: String, default: "#4A4A4A" }, textColor: { type: String, default: "#1A1A1A" }, useResetSlot: { type: Boolean, default: !1 }, value: { type: Number, default: 0 }, source: { type: Number, default: 0 } }, emits: ["update:value", "reset"], setup(f, { emit: K }) { Ge((x) => ({ "782b8172": d.value, "102109e6": V.value, "642212d7": _.value, "1f5369d4": f.selectColor, "22b98ab8": z.value })); const p = f, d = y(() => p.inputColor), z = y(() => p.background), _ = y(() => `${p.selectColor}33`), V = y(() => p.borderColor), w = K; function R() { w("reset"); } const B = y(() => { const x = p.max - p.min, b = 0, T = (p.value - p.min) / x * 100; return { left: `${b}%`, width: `${T - b}%`, background: p.selectColor }; }); return (x, b) => (r(), m("div", wt, [ f.value !== f.source ? (r(), m("div", $t, [ f.useResetSlot ? i(x.$slots, "reset-action", { key: 1, reset: R }, void 0, !0) : (r(), m("button", { key: 0, "data-cy-reset": "", tabindex: "0", role: "button", class: "vue-data-ui-refresh-button", onClick: R }, [ ne(pt, { name: "refresh", stroke: f.textColor }, null, 8, ["stroke"]) ])) ])) : (r(), m("div", xt)), N("div", Tt, [ b[1] || (b[1] = N("div", { class: "slider-track" }, null, -1)), N("div", { class: "range-highlight", style: J(B.value) }, null, 4), N("input", { type: "range", min: f.min, max: f.max, value: Number(f.value), onInput: b[0] || (b[0] = (T) => w("update:value", Number(T.target.value))) }, null, 40, St) ]) ])); } }, Nt = /* @__PURE__ */ ze(Ft, [["__scopeId", "data-v-b4e6aee9"]]), zt = ["id"], At = ["xmlns", "viewBox"], Ot = ["width", "height"], Pt = ["transform"], It = ["fill", "font-weight", "x", "y", "font-size", "transform", "onMouseover"], Mt = { key: 4, class: "vue-data-ui-watermark" }, _t = ["innerHTML"], Rt = { __name: "vue-ui-word-cloud", props: { config: { type: Object, default() { return {}; } }, dataset: { type: [Array, String], default() { return []; } } }, setup(f, { expose: K }) { const { vue_ui_word_cloud: p } = Je(), d = f, z = y({ get() { return !!d.dataset && d.dataset.length; }, set(t) { return t; } }), _ = n(Se()), V = n(0), w = n(null), R = n(null), B = n(null), x = n(0), b = n(0), T = n(!1), e = y({ get: () => de(), set: (t) => t }), A = n(re()); function re() { return typeof d.dataset == "string" ? Ke(d.dataset) : d.dataset.map((t, a) => ({ ...t, value: Qe(t.value) })); } H(() => d.dataset, () => { A.value = re(), E(); }); const { userOptionsVisible: Q, setUserOptionsVisibility: ue, keepUserOptionState: ie } = Ct({ config: e.value }), { svgRef: ce } = kt({ config: e.value.style.chart.title }); function de() { const t = Ne({ userConfig: d.config, defaultConfig: p }); return t.theme ? { ...Ne({ userConfig: et.vue_ui_word_cloud[t.theme] || d.config, defaultConfig: t }), customPalette: Ze[t.theme] || Y } : t; } H(() => d.config, (t) => { e.value = de(), Q.value = !e.value.userOptions.showOnChartHover, he(), x.value += 1, b.value += 1, Z(), v.value.showTable = e.value.table.show, v.value.showTooltip = e.value.style.chart.tooltip.show; }, { deep: !0 }); const ve = n(null), O = n(0), s = n({ width: e.value.style.chart.width, height: e.value.style.chart.height, maxFontSize: e.value.style.chart.words.maxFontSize, minFontSize: e.value.style.chart.words.minFontSize }), Ae = vt(() => { const { width: t, height: a } = ht({ chart: w.value, title: e.value.style.chart.title.text ? R.value : null, slicer: e.value.style.chart.zoom.show && ve.value, source: B.value }); requestAnimationFrame(() => { s.value.width = t, s.value.height = a, Te(E); }); }); H(() => O.value, () => { Oe(); }); const Oe = dt(() => { E(); }, 10); function Z() { O.value = ee.value; } const D = n(null); Le(() => { he(), Z(); }); function he() { tt(d.dataset) ? Fe({ componentName: "VueUiWordCloud", type: "dataset" }) : A.value.forEach((t, a) => { ot({ datasetObject: t, requiredAttributes: ["name", "value"] }).forEach((o) => { z.value = !1, Fe({ componentName: "VueUiWordCloud", type: "datasetSerieAttribute", property: o, index: a }); }); }), e.value.responsive && (D.value = new ResizeObserver(Ae), D.value.observe(w.value.parentNode)); } Xe(() => { D.value && D.value.disconnect(); }); const { isPrinting: me, isImaging: fe, generatePdf: pe, generateImage: ge } = it({ elementId: `wordCloud_${_.value}`, fileName: e.value.style.chart.title.text || "vue-ui-word-cloud" }), v = n({ showTable: e.value.table.show, showTooltip: e.value.style.chart.tooltip.show }); function Pe(t, a, o = "Arial") { const l = document.createElement("canvas").getContext("2d"); return l.font = `${a}px ${e.value.style.chart.words.bold ? "bold" : "normal"} ${o}`, { width: l.measureText(t).width + e.value.style.chart.words.proximity, height: a }; } function Ie(t, a) { return t.x < a.x + a.width && t.x + t.width > a.x && t.y < a.y + a.height && t.y + t.height > a.y; } function Me(t, a, o) { const u = [], l = { x: -a / 2, y: -o / 2, width: a, height: o }, g = 0, C = 0; return t.forEach((I) => { let le = !1; for (let q = 0; q < Math.max(a, o) / 2 && !le; q += e.value.style.chart.words.packingWeight) for (let se = 0; se < 360 && !le; se += e.value.style.chart.words.packingWeight) { const we = se * Math.PI / 180, Ue = g + q * Math.cos(we) - I.width / 2, Ve = C + q * Math.sin(we) - I.height / 2, $ = { ...I, x: Ue, y: Ve }, Be = $.x >= l.x && $.y >= l.y && $.x + $.width <= l.x + l.width && $.y + $.height <= l.y + l.height, De = u.some((Ee) => Ie($, Ee)); Be && !De && (u.push($), le = !0); } }), u; } const W = n([]); H(() => d.dataset, E, { immediate: !0 }); const ee = y(() => Math.round(Math.min(...A.value.map((t) => t.value)))), ye = y(() => Math.round(Math.max(...A.value.map((t) => t.value)))); function E() { const t = [...A.value].filter((l) => l.value >= O.value).map((l) => l.value), a = Math.max(...t), o = Math.min(...t), u = [...A.value].filter((l) => l.value >= O.value).map((l, g) => { let C = (l.value - o) / (a - o) * (s.value.maxFontSize - s.value.minFontSize) + s.value.minFontSize; C = isNaN(C) ? s.value.minFontSize : C; const I = Pe(l.name, C); return { ...l, id: Se(), fontSize: C, width: I.width, height: I.height, color: e.value.style.chart.words.usePalette ? e.value.customPalette[g] || e.value.customPalette[g % e.value.customPalette.length] || Y[g] || Y[g % Y.length] : e.value.style.chart.words.color }; }); W.value = Me(u, s.value.width, s.value.height).sort((l, g) => g.fontSize - l.fontSize); } const G = y(() => { const t = W.value.map((o) => ({ name: o.name, color: o.color })), a = W.value.map((o) => o.value); return { head: t, body: a }; }); function be() { Te(() => { const t = G.value.head.map((u, l) => [[ u.name ], [G.value.body[l]]]), a = [[e.value.style.chart.title.text], [e.value.style.chart.title.subtitle.text], [[""], [e.value.table.columnNames.value]]].concat(t), o = st(a); nt({ csvContent: o, title: e.value.style.chart.title.text || "vue-ui-word-cloud" }); }); } const L = y(() => { const t = [ e.value.table.columnNames.series, e.value.table.columnNames.value ], a = G.value.head.map((l, g) => { const C = at({ p: e.value.table.td.prefix, v: G.value.body[g], s: e.value.table.td.suffix, r: e.value.table.td.roundingValue }); return [ { color: l.color, name: l.name }, C ]; }), 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.series, e.value.table.columnNames.value ], head: t, body: a, config: o }; }), X = n(!1); function _e(t) { X.value = t, V.value += 1; } function Re() { return W.value; } function Ce() { v.value.showTable = !v.value.showTable; } function ke() { v.value.showTooltip = !v.value.showTooltip; } const j = n(!1); function te() { j.value = !j.value; } K({ getData: Re, generateCsv: be, generatePdf: pe, generateImage: ge, toggleTable: Ce, toggleTooltip: ke, toggleAnnotator: te }); const P = n(null), U = n(!1), oe = n(""), ae = n(null); function We(t) { if (!v.value.showTooltip) return; P.value = t.id, ae.value = { datapoint: t, config: e.value }; const a = e.value.style.chart.tooltip.customFormat; if (U.value = !1, rt(a)) try { const o = a({ datapoint: t, config: e.value }); typeof o == "string" && (oe.value = o, U.value = !0); } catch { console.warn("Custom format cannot be applied."), U.value = !1; } if (!U.value) { let o = `<svg viewBox="0 0 10 10" height="${e.value.style.chart.tooltip.fontSize}"><circle cx="5" cy="5" r="5" fill="${t.color}"/></svg><span>${t.name}:</span><b>${(t.value || 0).toFixed(e.value.style.chart.tooltip.roundingValue)}</b>`; oe.value = `<div dir="auto" style="display:flex; gap:4px; align-items:center; jsutify-content:center;">${o}</div>`; } T.value = !0; } return (t, a) => (r(), m("div", { class: "vue-ui-word-cloud", ref_key: "wordCloudChart", ref: w, id: `wordCloud_${_.value}`, style: J(`width: 100%; font-family:${e.value.style.fontFamily};background:${e.value.style.chart.backgroundColor};${e.value.responsive ? "height:100%" : ""}`), onMouseenter: a[3] || (a[3] = () => c(ue)(!0)), onMouseleave: a[4] || (a[4] = () => c(ue)(!1)) }, [ e.value.userOptions.buttons.annotator ? (r(), M(bt, { key: 0, svgRef: c(ce), backgroundColor: e.value.style.chart.backgroundColor, color: e.value.style.chart.color, active: j.value, onClose: te }, null, 8, ["svgRef", "backgroundColor", "color", "active"])) : k("", !0), e.value.style.chart.title.text ? (r(), m("div", { key: 1, ref_key: "chartTitle", ref: R, style: "width:100%;background:transparent;padding-bottom:24px" }, [ (r(), M(ut, { key: `title_${x.value}`, config: { title: { ...e.value.style.chart.title }, subtitle: { ...e.value.style.chart.title.subtitle } } }, null, 8, ["config"])) ], 512)) : k("", !0), e.value.userOptions.show && z.value && (c(ie) || c(Q)) ? (r(), M(ct, { ref: "details", key: `user_option_${V.value}`, backgroundColor: e.value.style.chart.backgroundColor, color: e.value.style.chart.color, isPrinting: c(me), isImaging: c(fe), uid: _.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: X.value, titles: { ...e.value.userOptions.buttonTitles }, chartElement: w.value, position: e.value.userOptions.position, hasTooltip: e.value.style.chart.tooltip.show && e.value.userOptions.buttons.tooltip, isTooltip: v.value.showTooltip, hasAnnotator: e.value.userOptions.buttons.annotator, isAnnotation: j.value, onToggleFullscreen: _e, onGeneratePdf: c(pe), onGenerateCsv: be, onGenerateImage: c(ge), onToggleTable: Ce, onToggleTooltip: ke, onToggleAnnotator: te, style: J({ visibility: c(ie) ? c(Q) ? "visible" : "hidden" : "visible" }) }, je({ _: 2 }, [ t.$slots.menuIcon ? { name: "menuIcon", fn: h(({ isOpen: o, color: u }) => [ i(t.$slots, "menuIcon", S(F({ isOpen: o, color: u })), void 0, !0) ]), key: "0" } : void 0, t.$slots.optionPdf ? { name: "optionPdf", fn: h(() => [ i(t.$slots, "optionPdf", {}, void 0, !0) ]), key: "1" } : void 0, t.$slots.optionCsv ? { name: "optionCsv", fn: h(() => [ i(t.$slots, "optionCsv", {}, void 0, !0) ]), key: "2" } : void 0, t.$slots.optionImg ? { name: "optionImg", fn: h(() => [ i(t.$slots, "optionImg", {}, void 0, !0) ]), key: "3" } : void 0, t.$slots.optionTable ? { name: "optionTable", fn: h(() => [ i(t.$slots, "optionTable", {}, void 0, !0) ]), key: "4" } : void 0, t.$slots.optionFullscreen ? { name: "optionFullscreen", fn: h(({ toggleFullscreen: o, isFullscreen: u }) => [ i(t.$slots, "optionFullscreen", S(F({ toggleFullscreen: o, isFullscreen: u })), void 0, !0) ]), key: "5" } : void 0, t.$slots.optionAnnotator ? { name: "optionAnnotator", fn: h(({ toggleAnnotator: o, isAnnotator: u }) => [ i(t.$slots, "optionAnnotator", S(F({ toggleAnnotator: o, isAnnotator: u })), void 0, !0) ]), key: "6" } : void 0 ]), 1032, ["backgroundColor", "color", "isPrinting", "isImaging", "uid", "hasPdf", "hasXls", "hasImg", "hasTable", "hasFullscreen", "isFullscreen", "titles", "chartElement", "position", "hasTooltip", "isTooltip", "hasAnnotator", "isAnnotation", "onGeneratePdf", "onGenerateImage", "style"])) : k("", !0), z.value ? (r(), m("svg", { key: 3, ref_key: "svgRef", ref: ce, class: $e({ "vue-data-ui-fullscreen--on": X.value, "vue-data-ui-fulscreen--off": !X.value }), xmlns: c(lt), viewBox: `0 0 ${s.value.width <= 0 ? 10 : s.value.width} ${s.value.height <= 0 ? 10 : s.value.height}`, style: "overflow:visible;background:transparent;" }, [ ne(gt), t.$slots["chart-background"] ? (r(), m("foreignObject", { key: 0, x: 0, y: 0, width: s.value.width <= 0 ? 10 : s.value.width, height: s.value.height <= 0 ? 10 : s.value.height, style: { pointerEvents: "none" } }, [ i(t.$slots, "chart-background", {}, void 0, !0) ], 8, Ot)) : k("", !0), N("g", { transform: `translate(${(s.value.width <= 0 ? 10 : s.value.width) / 2}, ${(s.value.height <= 0 ? 10 : s.value.height) / 2})` }, [ (r(!0), m(qe, null, He(W.value, (o, u) => (r(), m("g", null, [ (r(), m("text", { fill: o.color, "font-weight": e.value.style.chart.words.bold ? "bold" : "normal", key: u, x: o.x, y: o.y, "font-size": o.fontSize, transform: `translate(${o.width / 2}, ${o.height / 2})`, class: $e({ animated: e.value.useCssAnimation, "word-selected": P.value && P.value === o.id && v.value.showTooltip, "word-not-selected": P.value && P.value !== o.id && v.value.showTooltip }), "text-anchor": "middle", "dominant-baseline": "central", onMouseover: (l) => We(o), onMouseleave: a[0] || (a[0] = (l) => { P.value = null, T.value = !1; }), style: J(`animation-delay:${u * e.value.animationDelayMs}ms !important;`) }, xe(o.name), 47, It)) ]))), 256)) ], 8, Pt), i(t.$slots, "svg", { svg: { height: s.value.height, width: s.value.width } }, void 0, !0) ], 10, At)) : k("", !0), t.$slots.watermark ? (r(), m("div", Mt, [ i(t.$slots, "watermark", S(F({ isPrinting: c(me) || c(fe) })), void 0, !0) ])) : k("", !0), ne(yt, { show: v.value.showTooltip && T.value, backgroundColor: e.value.style.chart.tooltip.backgroundColor, color: e.value.style.chart.tooltip.color, fontSize: e.value.style.chart.tooltip.fontSize, borderRadius: e.value.style.chart.tooltip.borderRadius, borderColor: e.value.style.chart.tooltip.borderColor, borderWidth: e.value.style.chart.tooltip.borderWidth, backgroundOpacity: e.value.style.chart.tooltip.backgroundOpacity, position: e.value.style.chart.tooltip.position, offsetY: e.value.style.chart.tooltip.offsetY, parent: w.value, content: oe.value, isCustom: U.value }, { "tooltip-before": h(() => [ i(t.$slots, "tooltip-before", S(F({ ...ae.value })), void 0, !0) ]), "tooltip-after": h(() => [ i(t.$slots, "tooltip-after", S(F({ ...ae.value })), void 0, !0) ]), _: 3 }, 8, ["show", "backgroundColor", "color", "fontSize", "borderRadius", "borderColor", "borderWidth", "backgroundOpacity", "position", "offsetY", "parent", "content", "isCustom"]), N("div", { ref_key: "chartSlicer", ref: ve, style: "width:100%;background:transparent", "data-html2canvas-ignore": "" }, [ e.value.style.chart.zoom.show && ee.value < ye.value ? (r(), M(Nt, { key: 0, value: O.value, "onUpdate:value": a[1] || (a[1] = (o) => O.value = o), min: ee.value, max: ye.value, textColor: e.value.style.chart.color, inputColor: e.value.style.chart.zoom.color, selectColor: e.value.style.chart.zoom.highlightColor, useResetSlot: e.value.style.chart.zoom.useResetSlot, background: e.value.style.chart.zoom.color, borderColor: e.value.style.chart.backgroundColor, source: e.value.style.chart.width, onReset: Z }, { "reset-action": h(({ reset: o }) => [ i(t.$slots, "reset-action", S(F({ reset: o })), void 0, !0) ]), _: 3 }, 8, ["value", "min", "max", "textColor", "inputColor", "selectColor", "useResetSlot", "background", "borderColor", "source"])) : k("", !0) ], 512), t.$slots.source ? (r(), m("div", { key: 5, ref_key: "source", ref: B, dir: "auto" }, [ i(t.$slots, "source", {}, void 0, !0) ], 512)) : k("", !0), z.value ? (r(), M(mt, { key: 6, 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: h(() => [ (r(), M(ft, { key: `table_${b.value}`, colNames: L.value.colNames, head: L.value.head, body: L.value.body, config: L.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[2] || (a[2] = (o) => v.value.showTable = !1) }, { th: h(({ th: o }) => [ N("div", { innerHTML: o, style: { display: "flex", "align-items": "center" } }, null, 8, _t) ]), td: h(({ td: o }) => [ Ye(xe(o.name || o), 1) ]), _: 1 }, 8, ["colNames", "head", "body", "config", "title"])) ]), _: 1 }, 8, ["config"])) : k("", !0) ], 44, zt)); } }, Qt = /* @__PURE__ */ ze(Rt, [["__scopeId", "data-v-e87563ab"]]); export { Qt as default };