UNPKG

vue-data-ui

Version:

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

560 lines (559 loc) • 20.4 kB
import { t as e } from "./rolldown-runtime-Dy4uBu1J.js"; import { Jt as t, Vt as n, X as r, b as i, i as a, jt as o, q as s, t as c, tt as l } from "./lib-Bttd6u5E.js"; import { n as ee, t as te } from "./useHints-Dq_w2E8B.js"; import { t as ne } from "./useConfig-D3scuR88.js"; import { t as re } from "./usePrinter-DN5bYhTG.js"; import { n as ie, t as ae } from "./BaseScanner-DZvpgOjM.js"; import { t as oe } from "./useSvgExport-DH-FfcqQ.js"; import { t as u } from "./useNestedProp-vPNvh7rV.js"; import { t as se } from "./useThemeCheck-C43Tcqmk.js"; import { t as ce } from "./img-Bnokohej.js"; import { n as le } from "./Title-BE3qg9xl.js"; import { t as ue } from "./_plugin-vue_export-helper-B3ysoDQm.js"; import { l as de, t as fe } from "./useResponsive-ZtArZtUf.js"; import { t as pe } from "./useUserOptionState-DK-_1ddE.js"; import { t as me } from "./useChartAccessibility-DYqac8yF.js"; import { t as he } from "./usePrefersMotion-BC-CsqR1.js"; import { t as ge } from "./vue_ui_tiremarks-CdEPieWV.js"; import { Fragment as _e, computed as d, createBlock as f, createCommentVNode as p, createElementBlock as m, createElementVNode as ve, createSlots as ye, createVNode as be, defineAsyncComponent as h, guardReactiveProps as g, nextTick as xe, normalizeClass as _, normalizeProps as v, normalizeStyle as y, onMounted as Se, openBlock as b, ref as x, renderList as Ce, renderSlot as S, toDisplayString as we, toRefs as Te, unref as C, watch as Ee, withCtx as w } from "vue"; //#region src/components/vue-ui-tiremarks.vue var De = /* @__PURE__ */ e({ default: () => T }), Oe = ["id"], ke = [ "xmlns", "viewBox", "aria-labelledby", "aria-describedby" ], Ae = ["id"], je = ["id"], Me = ["width", "height"], Ne = { key: 1 }, Pe = [ "d", "stroke-width", "stroke" ], Fe = { key: 2 }, Ie = [ "x1", "y1", "x2", "y2", "stroke-width", "stroke" ], Le = ["aria-label"], Re = [ "x", "y", "height" ], ze = [ "x", "y", "font-size", "fill", "font-weight", "text-anchor" ], Be = { key: 4, class: "vue-data-ui-watermark" }, T = /*#__PURE__*/ ue({ __name: "vue-ui-tiremarks", props: { config: { type: Object, default() { return {}; } }, dataset: { type: Object, default() { return {}; } } }, emits: ["copyAlt"], setup(e, { expose: ue, emit: De }) { let T = h(() => import("./PenAndPaper-DAE-tnEQ.js").then((e) => e.t)), Ve = h(() => import("./UserOptions-Dt98of5H.js").then((e) => e.n)), He = h(() => import("./PackageVersion-D6d8SCp9.js").then((e) => e.t)), { vue_ui_tiremarks: Ue } = ne(), { isThemeValid: We, warnInvalidTheme: Ge } = se(), E = he(), D = e, Ke = De, qe = d(() => !!D.dataset && Object.keys(D.dataset).length), O = x(s()), k = x(null), Je = x(null), Ye = x(null), Xe = x(null), Ze = x(0), Qe = x(0), A = x(null), j = x(null), M = x(!1), N = x(!1), P = x(z()); ee({ config: () => P.value, dataset: () => D.dataset, component: "VueUiTiremarks", rules: [te.noHint] }); let $e = d(() => P.value.userOptions.useCursorPointer), et = d(() => t({ defaultConfig: { userOptions: { show: !1 }, style: { chart: { backgroundColor: "#99999930", animation: { use: !1 }, layout: { activeColor: "#6A6A6A80", inactiveColor: "#CACACA80", ticks: { gradient: { show: !1 } } } } } }, userConfig: P.value.skeletonConfig ?? {} })), { loading: F, FINAL_DATASET: I } = ie({ ...Te(D), FINAL_CONFIG: P, prepareConfig: z, skeletonDataset: D.config?.skeletonDataset ?? { percentage: 50 }, skeletonConfig: t({ defaultConfig: P.value, userConfig: et.value }) }), { userOptionsVisible: L, setUserOptionsVisibility: tt, keepUserOptionState: nt } = pe({ config: P.value }), { svgRef: R } = me({ config: P.value.style.chart.title }); function z() { let e = u({ userConfig: D.config, defaultConfig: Ue }), t = e.theme; if (!t) return e; if (!We.value(e)) return Ge(e), e; let n = u({ userConfig: ge[t] || D.config, defaultConfig: e }); return u({ userConfig: D.config, defaultConfig: n }); } Ee(() => D.config, (e) => { P.value = z(), L.value = !P.value.userOptions.showOnChartHover, K.value = P.value.style.chart.width, q.value = P.value.style.chart.height, ct(), Qe.value += 1; }, { deep: !0 }); let { isPrinting: B, isImaging: V, generatePdf: rt, generateImage: it } = re({ elementId: O.value, fileName: P.value.style.chart.title.text || "vue-ui-tiremarks", options: P.value.userOptions.print }), at = d(() => P.value.userOptions.show && !P.value.style.chart.title.text), H = x(P.value.style.chart.animation.use && !E.value ? 0 : i(I.value.percentage)); Ee(() => I.value, (e) => { P.value.style.chart.animation.use && !E.value ? ot(e.percentage) : H.value = e.percentage || 0; }, { deep: !0 }), Se(() => { ct(); }); function ot(e) { let t = P.value.style.chart.animation.speed, n = Math.abs(e - H.value) / (t * 120); function r() { H.value < e ? H.value = Math.min(H.value + n, e) : H.value > e && (H.value = Math.max(H.value - n, e)), H.value !== e && requestAnimationFrame(r); } r(); } let st = d(() => !!P.value.debug); function ct() { if (o(D.dataset) && l({ componentName: "VueUiTiremarks", type: "dataset", debug: st.value }), P.value.responsive) { let e = de(() => { let { width: e, height: t } = fe({ chart: k.value, title: P.value.style.chart.title.text ? Ye.value : null, source: Xe.value }); requestAnimationFrame(() => { K.value = Math.max(.1, e), q.value = Math.max(.1, t - 12); }); }); A.value && (j.value && A.value.unobserve(j.value), A.value.disconnect()), A.value = new ResizeObserver(e), j.value = k.value.parentNode, A.value.observe(j.value); } ot(I.value.percentage || 0); } let U = d(() => P.value.style.chart.layout.display === "vertical"), W = d(() => { let e = P.value.style.chart.percentage.show, t = { top: e ? 48 : 12, left: e ? 64 : 16, right: e ? 64 : 16, bottom: e ? 48 : 12 }; return U.value ? { top: P.value.style.chart.percentage.verticalPosition === "top" ? t.top : 3, left: 3, right: 3, bottom: P.value.style.chart.percentage.verticalPosition === "bottom" ? t.bottom : 3 } : { top: 0, bottom: 0, left: P.value.style.chart.percentage.horizontalPosition === "left" ? t.left : 16, right: P.value.style.chart.percentage.horizontalPosition === "right" ? t.right : 10 }; }), G = d(() => Object.values(W.value).reduce((e, t) => e + t, 0)), K = x(P.value.style.chart.width), q = x(P.value.style.chart.height), J = d(() => ({ height: q.value, width: K.value })), lt = d(() => ({ horizontal: { x: X.value.x + (P.value.style.chart.percentage.horizontalPosition === "left" ? 6 : 3), y: J.value.height / 2 - X.value.fontSize / 2 }, vertical: { x: J.value.width / 2 - 20, y: X.value.y - X.value.fontSize / 2 } })[P.value.style.chart.layout.display]), Y = d(() => U.value ? { mark: (J.value.height - G.value) / 100 * .5, space: (J.value.height - G.value) / 100 * .5 } : { mark: (J.value.width - G.value) / 100 * .5, space: (J.value.width - G.value) / 100 * .5 }), ut = d(() => { let e = []; for (let t = 0; t < 100; t += 1) { let r = P.value.style.chart.layout.ticks.gradient.show ? n(P.value.style.chart.layout.activeColor, t / 100 * (P.value.style.chart.layout.ticks.gradient.shiftHueIntensity / 100)) : P.value.style.chart.layout.activeColor; if (U.value) { let n = P.value.style.chart.layout.crescendo ? (100 - t) * (J.value.width - W.value.left - W.value.right) / 100 / 3 : 0, i = W.value.left + 4 + n, a = J.value.width - W.value.right - 4 - n, o = J.value.height - W.value.bottom - t * Y.value.mark - t * Y.value.space - Y.value.mark, s = J.value.height - W.value.bottom - t * Y.value.mark - t * Y.value.space - Y.value.mark, c = (a - i) / P.value.style.chart.layout.curveAngleX, l = P.value.style.chart.layout.curveAngleY * ((1 + t) / 100); e.push({ x1: i, x2: a, y1: o, y2: s, curve: `M ${i} ${o} C ${i + c} ${o - l}, ${a - c} ${s - l}, ${a} ${s}`, color: r }); } else { let n = P.value.style.chart.layout.crescendo ? (100 - t) * (J.value.height - W.value.top - W.value.bottom) / 100 / 3 : 0, i = W.value.left + t * Y.value.mark + t * Y.value.space - Y.value.mark, a = i, o = W.value.top + 4 + n, s = J.value.height - W.value.bottom - 4 - n, c = P.value.style.chart.layout.curveAngleY * ((1 + t) / 100), l = (s - o) / P.value.style.chart.layout.curveAngleX; e.push({ x1: i, x2: a, y1: o, y2: s, curve: `M ${i} ${o} C ${i + c} ${o + l}, ${a + c} ${s - l}, ${a} ${s}`, color: r }); } } return e; }), X = d(() => { let e, t, n, r = P.value.style.chart.percentage.fontSize / 3; return U.value ? P.value.style.chart.percentage.verticalPosition === "top" ? (e = J.value.width / 2, t = W.value.top / 2, n = "middle") : P.value.style.chart.percentage.verticalPosition === "bottom" && (e = J.value.width / 2, t = J.value.height - W.value.bottom / 2 + r, n = "middle") : P.value.style.chart.percentage.horizontalPosition === "left" ? (e = 4, t = J.value.height / 2 + r, n = "start") : P.value.style.chart.percentage.horizontalPosition === "right" && (e = J.value.width - W.value.right + 8, t = J.value.height / 2 + r, n = "start"), { x: e, y: t, textAnchor: n, bold: P.value.style.chart.percentage.bold, fontSize: P.value.style.chart.percentage.fontSize, fill: P.value.style.chart.percentage.color }; }), Z = x(!1); function dt(e) { Z.value = e, Ze.value += 1; } let Q = x(!1); function $() { Q.value = !Q.value; } async function ft({ scale: e = 2 } = {}) { if (!k.value) return; let { width: t, height: n } = k.value.getBoundingClientRect(), r = t / n, { imageUri: i, base64: a } = await ce({ domElement: k.value, base64: !0, img: !0, scale: e }); return { imageUri: i, base64: a, title: P.value.style.chart.title.text, width: t, height: n, aspectRatio: r }; } let pt = d(() => P.value.style.chart.backgroundColor), mt = d(() => P.value.style.chart.title), { exportSvg: ht, getSvg: gt } = oe({ svg: R, title: mt, backgroundColor: pt }); async function _t({ isCb: e }) { N.value = !0, await xe(); try { if (e) { let { blob: e, url: t, text: n, dataUrl: r } = await gt(); await Promise.resolve(P.value.userOptions.callbacks.svg({ blob: e, url: t, text: n, dataUrl: r })); } else await Promise.resolve(ht()); } finally { N.value = !1; } } function vt(e) { if (e?.stage === "start") { M.value = !0; return; } if (e?.stage === "end") { M.value = !1; return; } it(); } async function yt() { if (Ke("copyAlt", { config: P.value, dataset: I.value }), !P.value.userOptions.callbacks.altCopy) { console.warn("Vue Data UI - A callback must be set for `altCopy` in userOptions."); return; } await Promise.resolve(P.value.userOptions.callbacks.altCopy({ config: P.value, dataset: I.value })); } let bt = d(() => `${O.value}-title`), xt = d(() => `${O.value}-desc`), St = d(() => a(P.value.style.chart.percentage.formatter, H.value, r({ v: H.value, s: "%", r: P.value.style.chart.percentage.rounding }))), Ct = d(() => P.value.style.chart.title.text || ""), wt = d(() => F.value ? "Loading data" : `Value: ${St.value}`); return ue({ getImage: ft, generatePdf: rt, generateImage: it, generateSvg: _t, toggleAnnotator: $, toggleFullscreen: dt, copyAlt: yt }), (e, t) => (b(), m("div", { ref_key: "tiremarksChart", ref: k, class: _(`vue-data-ui-component vue-ui-tiremarks ${P.value.useCssAnimation ? "" : "vue-ui-dna"}`), style: y(`font-family:${P.value.style.fontFamily};width:100%; text-align:center;background:${P.value.style.chart.backgroundColor}`), id: O.value, onMouseenter: t[0] ||= () => C(tt)(!0), onMouseleave: t[1] ||= () => C(tt)(!1) }, [ P.value.userOptions.buttons.annotator ? (b(), f(C(T), { key: 0, svgRef: C(R), backgroundColor: P.value.style.chart.backgroundColor, color: P.value.style.chart.color, active: Q.value, isCursorPointer: $e.value, onClose: $ }, { "annotator-action-close": w(() => [S(e.$slots, "annotator-action-close", {}, void 0, !0)]), "annotator-action-color": w(({ color: t }) => [S(e.$slots, "annotator-action-color", v(g({ color: t })), void 0, !0)]), "annotator-action-draw": w(({ mode: t }) => [S(e.$slots, "annotator-action-draw", v(g({ mode: t })), void 0, !0)]), "annotator-action-undo": w(({ disabled: t }) => [S(e.$slots, "annotator-action-undo", v(g({ disabled: t })), void 0, !0)]), "annotator-action-redo": w(({ disabled: t }) => [S(e.$slots, "annotator-action-redo", v(g({ disabled: t })), void 0, !0)]), "annotator-action-delete": w(({ disabled: t }) => [S(e.$slots, "annotator-action-delete", v(g({ disabled: t })), void 0, !0)]), _: 3 }, 8, [ "svgRef", "backgroundColor", "color", "active", "isCursorPointer" ])) : p("", !0), at.value ? (b(), m("div", { key: 1, ref_key: "noTitle", ref: Je, class: "vue-data-ui-no-title-space", style: "height:36px; width: 100%;background:transparent" }, null, 512)) : p("", !0), P.value.style.chart.title.text ? (b(), m("div", { key: 2, ref_key: "chartTitle", ref: Ye, style: "width:100%;background:transparent;padding-bottom:12px" }, [(b(), f(le, { key: `title_${Qe.value}`, config: { title: { cy: "wheel-title", ...P.value.style.chart.title }, subtitle: { cy: "wheel-subtitle", ...P.value.style.chart.title.subtitle } } }, null, 8, ["config"]))], 512)) : p("", !0), P.value.userOptions.show && qe.value && (C(nt) || C(L)) ? (b(), f(C(Ve), { ref: "details", key: `user_options_${Ze.value}`, backgroundColor: P.value.style.chart.backgroundColor, color: P.value.style.chart.color, isPrinting: C(B), isImaging: C(V), uid: O.value, hasPdf: P.value.userOptions.buttons.pdf, hasImg: P.value.userOptions.buttons.img, hasSvg: P.value.userOptions.buttons.svg, hasFullscreen: P.value.userOptions.buttons.fullscreen, hasAltCopy: P.value.userOptions.buttons.altCopy, hasXls: !1, isFullscreen: Z.value, titles: { ...P.value.userOptions.buttonTitles }, chartElement: k.value, position: P.value.userOptions.position, hasAnnotator: P.value.userOptions.buttons.annotator, isAnnotation: Q.value, callbacks: P.value.userOptions.callbacks, printScale: P.value.userOptions.print.scale, isCursorPointer: $e.value, onToggleFullscreen: dt, onGeneratePdf: C(rt), onGenerateImage: vt, onGenerateSvg: _t, onToggleAnnotator: $, onCopyAlt: yt, style: y({ visibility: C(nt) ? C(L) ? "visible" : "hidden" : "visible" }) }, ye({ _: 2 }, [ e.$slots.menuIcon ? { name: "menuIcon", fn: w(({ isOpen: t, color: n }) => [S(e.$slots, "menuIcon", v(g({ isOpen: t, color: n })), void 0, !0)]), key: "0" } : void 0, e.$slots.optionPdf ? { name: "optionPdf", fn: w(() => [S(e.$slots, "optionPdf", {}, void 0, !0)]), key: "1" } : void 0, e.$slots.optionImg ? { name: "optionImg", fn: w(() => [S(e.$slots, "optionImg", {}, void 0, !0)]), key: "2" } : void 0, e.$slots.optionSvg ? { name: "optionSvg", fn: w(() => [S(e.$slots, "optionSvg", {}, void 0, !0)]), key: "3" } : void 0, e.$slots.optionFullscreen ? { name: "optionFullscreen", fn: w(({ toggleFullscreen: t, isFullscreen: n }) => [S(e.$slots, "optionFullscreen", v(g({ toggleFullscreen: t, isFullscreen: n })), void 0, !0)]), key: "4" } : void 0, e.$slots.optionAnnotator ? { name: "optionAnnotator", fn: w(({ toggleAnnotator: t, isAnnotator: n }) => [S(e.$slots, "optionAnnotator", v(g({ toggleAnnotator: t, isAnnotator: n })), void 0, !0)]), key: "5" } : void 0, e.$slots.optionAltCopy ? { name: "optionAltCopy", fn: w(({ altCopy: t }) => [S(e.$slots, "optionAltCopy", v(g({ altCopy: t })), void 0, !0)]), key: "6" } : void 0, e.$slots["custom-menu-before"] ? { name: "custom-menu-before", fn: w(() => [S(e.$slots, "custom-menu-before", {}, void 0, !0)]), key: "7" } : void 0, e.$slots["custom-menu-after"] ? { name: "custom-menu-after", fn: w(() => [S(e.$slots, "custom-menu-after", {}, void 0, !0)]), key: "8" } : void 0 ]), 1032, [ "backgroundColor", "color", "isPrinting", "isImaging", "uid", "hasPdf", "hasImg", "hasSvg", "hasFullscreen", "hasAltCopy", "isFullscreen", "titles", "chartElement", "position", "hasAnnotator", "isAnnotation", "callbacks", "printScale", "isCursorPointer", "onGeneratePdf", "style" ])) : p("", !0), (b(), m("svg", { ref_key: "svgRef", ref: R, xmlns: C(c), class: _({ "vue-data-ui-fullscreen--on": Z.value, "vue-data-ui-fulscreen--off": !Z.value }), viewBox: `0 0 ${K.value} ${q.value}`, style: y(`max-width:100%; overflow: visible; background:transparent;color:${P.value.style.chart.color}`), role: "img", "aria-labelledby": bt.value, "aria-describedby": xt.value }, [ ve("title", { id: bt.value }, we(Ct.value), 9, Ae), ve("desc", { id: xt.value }, we(wt.value), 9, je), be(C(He)), e.$slots["chart-background"] ? (b(), m("foreignObject", { key: 0, x: 0, y: 0, width: J.value.width, height: J.value.height, style: { pointerEvents: "none" } }, [S(e.$slots, "chart-background", {}, void 0, !0)], 8, Me)) : p("", !0), P.value.style.chart.layout.curved ? (b(), m("g", Ne, [(b(!0), m(_e, null, Ce(ut.value, (e, t) => (b(), m("path", { d: e.curve, "stroke-width": Y.value.mark, stroke: H.value >= t ? e.color : P.value.style.chart.layout.inactiveColor, "stroke-linecap": "round", fill: "none", class: _({ "vue-ui-tick-animated": P.value.style.chart.animation.use && !C(E) && t <= H.value }) }, null, 10, Pe))), 256))])) : (b(), m("g", Fe, [(b(!0), m(_e, null, Ce(ut.value, (e, t) => (b(), m("line", { x1: e.x1, y1: e.y1, x2: e.x2, y2: e.y2, "stroke-width": Y.value.mark, stroke: H.value >= t ? e.color : P.value.style.chart.layout.inactiveColor, "stroke-linecap": "round" }, null, 8, Ie))), 256))])), P.value.style.chart.percentage.show ? (b(), m("g", { key: 3, role: "status", "aria-live": "polite", "aria-label": C(F) ? "..." : `${St.value}` }, [C(F) ? (b(), m("rect", { key: 0, x: lt.value.x, y: lt.value.y, width: 40, height: X.value.fontSize, fill: "#6A6A6A80", rx: 3 }, null, 8, Re)) : (b(), m("text", { key: 1, "aria-hidden": "true", x: X.value.x, y: X.value.y, "font-size": X.value.fontSize, fill: P.value.style.chart.layout.ticks.gradient.show && P.value.style.chart.percentage.useGradientColor ? C(n)(P.value.style.chart.layout.activeColor, H.value / 100 * (P.value.style.chart.layout.ticks.gradient.shiftHueIntensity / 100)) : P.value.style.chart.percentage.color, "font-weight": X.value.bold ? "bold" : "normal", "text-anchor": X.value.textAnchor }, we(St.value), 9, ze))], 8, Le)) : p("", !0), S(e.$slots, "svg", { svg: { ...J.value, isPrintingImg: C(B) || C(V) || M.value, isPrintingSvg: N.value } }, void 0, !0) ], 14, ke)), e.$slots.watermark ? (b(), m("div", Be, [S(e.$slots, "watermark", v(g({ isPrinting: C(B) || C(V) || M.value || N.value })), void 0, !0)])) : p("", !0), e.$slots.source ? (b(), m("div", { key: 5, ref_key: "source", ref: Xe, dir: "auto" }, [S(e.$slots, "source", {}, void 0, !0)], 512)) : p("", !0), S(e.$slots, "skeleton", {}, () => [C(F) ? (b(), f(ae, { key: 0 })) : p("", !0)], !0) ], 46, Oe)); } }, [["__scopeId", "data-v-7f57d45c"]]); //#endregion export { De as n, T as t };