vue-data-ui
Version:
A user-empowering data visualization Vue 3 components library for eloquent data storytelling
751 lines (750 loc) • 32.2 kB
JavaScript
import { isRef as Lt, ref as Ct, onMounted as Pt, watch as Rt, nextTick as Wt, unref as Vt } from "vue";
const et = "http://www.w3.org/2000/svg", yt = "http://www.w3.org/1999/xlink", Bt = 'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif';
let At = /* @__PURE__ */ new WeakMap();
function gt(N) {
let v = At.get(N);
return v || (v = getComputedStyle(N), At.set(N, v)), v;
}
function Mt() {
At = /* @__PURE__ */ new WeakMap();
}
function P(N) {
return document.createElementNS(et, N);
}
function wt(N) {
return `${N}, ${Bt}`;
}
function Ot({
svg: N,
// ref
title: v,
// computed
legend: F,
// computed
legendItems: rt,
// computed
backgroundColor: ot,
// computed
stretchTitle: I = !1,
// bool (when rotateX is applied on the svg like in VueUiWheel, title transform style needs to be compensated)
titleEmbedded: at = !1
// when title is already part of the svg (VueUiChestnut)
}) {
const lt = Lt(N) ? N : Ct(N), nt = Ct(!1), W = [
"fill",
"fill-opacity",
"stroke",
"stroke-width",
"stroke-opacity",
"opacity",
"color",
"stroke-linecap",
"stroke-linejoin",
"stroke-miterlimit",
"stroke-dasharray",
"stroke-dashoffset",
"font-family",
"font-size",
"font-style",
"font-weight",
"font-variant",
"letter-spacing",
"word-spacing",
"text-anchor",
"dominant-baseline",
"shape-rendering",
"vector-effect",
"paint-order",
"mix-blend-mode",
"isolation",
"filter",
"clip-path",
"mask",
"transform",
"transform-origin",
"visibility",
"display"
], j = /* @__PURE__ */ new Set(["font-family"]);
async function b({ timeoutMs: e = 4e3, log: o = "warn" } = {}) {
if (typeof window > "u" || typeof document > "u")
return console.warn("SVG export only works in the browser."), null;
const h = performance.now() + e, u = () => {
const C = Vt(lt);
return C && document.contains(C) ? C : null;
};
let c = u();
if (c)
return c;
let t = !1;
const S = (C) => {
if (!t && C)
try {
C.disconnect();
} catch {
}
t = !0;
};
let w;
const A = new Promise((C) => {
try {
w = new MutationObserver(() => {
const M = u();
M && (S(w), C(M));
}), w.observe(document.documentElement, { childList: !0, subtree: !0 });
} catch {
C(null);
}
});
for (; performance.now() < h; ) {
const C = await Promise.race([
A,
new Promise((M) => requestAnimationFrame(M))
]);
if (await Wt(), c = u() || C, c)
return S(w), c;
}
return S(w), console.warn("SVG element not found or not mounted (timed out)."), null;
}
Pt(async () => {
try {
await b(), nt.value = !0;
} catch {
nt.value = !1;
}
}), Rt(lt, async () => {
try {
await b(), nt.value = !0;
} catch {
nt.value = !1;
}
});
const f = /* @__PURE__ */ new Map();
function y(e) {
if (f.has(e))
return f.get(e);
const o = P("svg");
o.setAttribute("width", "0"), o.setAttribute("height", "0"), o.style.position = "absolute", o.style.left = "-99999px", o.style.top = "-99999px";
const h = P(e);
o.appendChild(h), document.body.appendChild(o);
const u = window.getComputedStyle(h), c = {};
for (const t of W)
c[t] = u.getPropertyValue(t);
return document.body.removeChild(o), f.set(e, c), c;
}
function $(e) {
const o = gt(e), h = y(e.tagName.toLowerCase()), u = [];
for (const c of W) {
let t = o.getPropertyValue(c) || "";
const S = h[c] || "";
if (j.has(c)) {
c === "font-family" && t && (t = wt(t)), t && u.push(`${c}:${t};`);
continue;
}
t && t !== S && u.push(`${c}:${t};`);
}
return u.join("");
}
function z(e, o) {
e.getAttribute("width") && o.setAttribute("width", e.getAttribute("width")), e.getAttribute("height") && o.setAttribute("height", e.getAttribute("height")), e.getAttribute("viewBox") && o.setAttribute("viewBox", e.getAttribute("viewBox"));
const h = [e, ...Array.from(e.querySelectorAll("*"))], u = [o, ...Array.from(o.querySelectorAll("*"))];
for (let c = 0; c < h.length; c += 1) {
const t = h[c], S = u[c], w = $(t);
w && S.setAttribute("style", w), ["fill", "stroke", "filter", "clip-path", "mask"].forEach((A) => {
const C = t.getAttribute(A);
C && S.setAttribute(A, C);
});
}
}
function L(e) {
const o = e.getAttribute("viewBox");
if (!o)
return null;
const [h, u, c, t] = o.split(/\s+|,/).map(Number);
return [h, u, c, t].some((S) => Number.isNaN(S)) ? null : { minX: h, minY: u, width: c, height: t };
}
function O(e) {
e.getAttribute("xmlns") || e.setAttribute("xmlns", et), e.getAttribute("xmlns:xlink") || e.setAttribute("xmlns:xlink", yt), e.getAttribute("xml:space") || e.setAttribute("xml:space", "preserve");
}
function it(e) {
const o = document.createElement("div");
return o.style.position = "absolute", o.style.left = "-99999px", o.style.top = "-99999px", o.style.width = "0", o.style.height = "0", document.body.appendChild(o), o.appendChild(e), o;
}
function st(e) {
try {
e.remove();
} catch {
}
}
function dt(e, o, h, u, c) {
if (!v.value || !v.value.text)
return 0;
const t = {
text: v.value.text || "",
color: v.value.color || "#111",
fontSize: v.value.fontSize || 20,
bold: !!v.value.bold,
textAlign: (v.value?.textAlign || "center").toLowerCase(),
paddingLeft: v.value.paddingLeft ?? 0,
paddingRight: v.value.paddingRight ?? 0,
subtitle: v.value.subtitle || null
}, S = P("g");
S.setAttribute("id", "__vdu_export_title"), e.appendChild(S);
const w = h + t.paddingLeft, A = h + o - (t.paddingRight || 0), C = h + o / 2;
let M = "start", X = w;
t.textAlign === "center" ? (M = "middle", X = C) : t.textAlign === "right" && (M = "end", X = A);
const D = u, T = Math.round(t.fontSize * 0.4), R = P("text");
R.setAttribute("x", String(X)), R.setAttribute("y", String(D + t.fontSize)), R.setAttribute("text-anchor", M), R.setAttribute("dominant-baseline", "ideographic"), R.setAttribute("style", `font-family:${c}; font-size:${t.fontSize}px; font-weight:${t.bold ? "700" : "400"}; fill:${t.color}; ${I ? "transform: scale(0.65, 1); transform-origin: center;" : ""}`), R.textContent = t.text, S.appendChild(R);
let J = t.fontSize;
if (t.subtitle && t.subtitle.text) {
const E = {
color: t.subtitle.color || "#666",
text: t.subtitle.text,
fontSize: t.subtitle.fontSize || Math.max(12, Math.round(t.fontSize * 0.8)),
bold: !!t.subtitle.bold
}, V = P("text");
V.setAttribute("x", String(X)), V.setAttribute("y", String(D + t.fontSize + T + E.fontSize)), V.setAttribute("text-anchor", M), V.setAttribute("dominant-baseline", "ideographic"), V.setAttribute("style", `font-family:${c}; font-size:${E.fontSize}px; font-weight:${E.bold ? "600" : "400"}; fill:${E.color}; ${I ? "transform: scale(0.65, 1); transform-origin: center;" : ""}`), V.textContent = E.text, S.appendChild(V), J += T + E.fontSize;
}
return J + Math.round(t.fontSize * 0.4);
}
function q(e, o, h, u, c) {
if (!F.value || !F.value.show || !Array.isArray(rt.value) || !rt.value.length)
return 0;
const t = {
bold: !!F.value.bold,
backgroundColor: F.value.backgroundColor || "transparent",
color: F.value.color || "#111",
fontSize: F.value.fontSize || 14,
paddingX: 14,
paddingY: 10,
itemGapX: 18,
itemGapY: 12,
markerSize: Math.max(8, Math.round((F.value.fontSize || 14) * 0.9)),
markerTextGap: 8,
lineHeight: Math.round((F.value.fontSize || 14) * 1.2),
maxWidth: o
}, S = P("g");
S.setAttribute("id", "__vdu_export_legend"), S.setAttribute("transform", `translate(${h}, ${u})`), e.appendChild(S);
const w = P("rect");
w.setAttribute("rx", "6"), w.setAttribute("ry", "6"), w.setAttribute("fill", t.backgroundColor), S.appendChild(w);
const A = P("g");
S.appendChild(A);
const C = P("text");
C.setAttribute("x", "0"), C.setAttribute("y", "0"), C.setAttribute("style", `font-family:${c}; font-size:${t.fontSize}px; font-weight:${t.bold ? "600" : "400"}; opacity:0;`), A.appendChild(C);
const M = (s) => (C.textContent = s || "", C.getComputedTextLength()), X = Math.max(1, t.maxWidth - t.paddingX * 2);
function D(s, a) {
const l = String(s || "").split(/\s+/).filter(Boolean), m = [];
if (!l.length)
return [""];
let d = l.shift();
for (; l.length; ) {
const g = `${d} ${l[0]}`;
if (M(g) <= a)
d = g, l.shift();
else if (M(d) > a && d.length > 1) {
let x = "";
for (const H of d) {
const Q = x + H;
if (M(Q) <= a)
x = Q;
else break;
}
const _ = d.slice(x.length);
m.push(x), d = _.length ? _ : l.shift() || "";
} else
m.push(d), d = l.shift() || "";
}
d && m.push(d);
const k = m[m.length - 1] || "";
if (M(k) > a && k.length > 1) {
let g = "";
for (const _ of k) {
const H = g + _;
if (M(H) <= a)
g = H;
else break;
}
const x = k.slice(g.length);
m[m.length - 1] = g, x && m.push(x);
}
return m;
}
const T = Math.PI / 180;
function R(s, a, l, m, d = -90) {
const k = d * T;
let g = "";
for (let x = 0; x < l; x += 1) {
const _ = k + x * 2 * Math.PI / l, H = s + Math.cos(_) * m, Q = a + Math.sin(_) * m;
g += (x === 0 ? "M" : "L") + H + "," + Q;
}
return g + "Z";
}
function J(s, a, l = 5, m, d) {
const k = -90 * T;
let g = "";
for (let x = 0; x < l * 2; x += 1) {
const _ = x % 2 === 0 ? m : d, H = k + x * Math.PI / l, Q = s + Math.cos(H) * _, Y = a + Math.sin(H) * _;
g += (x === 0 ? "M" : "L") + Q + "," + Y;
}
return g + "Z";
}
const E = rt.value.map((s) => {
const a = Math.max(1, X - (t.markerSize + t.markerTextGap)), l = D(s.name || "", a), m = Math.max(...l.map(M), 0), d = t.markerSize + t.markerTextGap + m, k = Math.max(t.markerSize, l.length * t.lineHeight);
return {
...s,
lines: l,
itemW: d,
itemH: k
};
}), V = [];
let n = {
items: [],
width: 0,
height: 0
};
for (const s of E) {
const a = (n.items.length ? t.itemGapX : 0) + s.itemW;
n.items.length && n.width + a > X ? (V.push(n), n = {
items: [s],
width: s.itemW,
height: s.itemH
}) : (n.items.push(s), n.width += a, n.height = Math.max(n.height, s.itemH));
}
n.items.length && V.push(n);
let r = t.paddingY;
for (const s of V) {
let l = Math.max(t.paddingX, (t.maxWidth - s.width) / 2);
for (let m = 0; m < s.items.length; m += 1) {
const d = s.items[m], k = l + t.markerSize / 2, g = r + s.height / 2.5, x = t.markerSize / 2, _ = String(d.shape || "rect").toLowerCase();
if (_ === "circle") {
const p = P("circle");
p.setAttribute("cx", String(k)), p.setAttribute("cy", String(g)), p.setAttribute("r", String(x * 0.8)), p.setAttribute("fill", d.color || "#000"), A.appendChild(p);
} else if (_ === "rect" || _ === "square") {
const p = P("path");
p.setAttribute("d", R(k, g, 4, x, -45)), p.setAttribute("fill", d.color || "#000"), A.appendChild(p);
} else if (_ === "diamond") {
const p = P("path");
p.setAttribute("d", R(k, g, 4, x, 45)), p.setAttribute("fill", d.color || "#000"), A.appendChild(p);
} else if (_ === "triangle") {
const p = P("path");
p.setAttribute("d", R(k, g, 3, x, -90)), p.setAttribute("fill", d.color || "#000"), A.appendChild(p);
} else if (_ === "pentagon") {
const p = P("path");
p.setAttribute("d", R(k, g, 5, x, -90)), p.setAttribute("fill", d.color || "#000"), A.appendChild(p);
} else if (_ === "hexagon") {
const p = P("path");
p.setAttribute("d", R(k, g, 6, x, 0)), p.setAttribute("fill", d.color || "#000"), A.appendChild(p);
} else if (_ === "star") {
const p = P("path"), tt = x, pt = x * 0.5;
p.setAttribute("d", J(k, g, 5, tt, pt)), p.setAttribute("fill", d.color || "#000"), A.appendChild(p);
} else {
const p = P("rect");
p.setAttribute("x", String(l)), p.setAttribute("y", String(r + (s.height - t.markerSize) / 2)), p.setAttribute("width", String(t.markerSize)), p.setAttribute("height", String(t.markerSize)), p.setAttribute("fill", d.color || "#000"), A.appendChild(p);
}
const H = l + t.markerSize + t.markerTextGap, Q = r + (s.height - d.lines.length * t.lineHeight) / 2 + t.fontSize, Y = P("text");
Y.setAttribute("x", String(H)), Y.setAttribute("y", String(Q)), Y.setAttribute("style", `font-family:${c}; font-size:${t.fontSize}px; font-weight:${t.bold ? "600" : "400"}; fill:${t.color};`), Y.setAttribute("dominant-baseline", "ideographic");
let mt = !0;
for (const p of d.lines) {
const tt = P("tspan");
mt || tt.setAttribute("dy", String(t.lineHeight)), tt.setAttribute("x", String(H)), tt.textContent = p, Y.appendChild(tt), mt = !1;
}
A.appendChild(Y), l += d.itemW + (m < s.items.length - 1 ? t.itemGapX : 0);
}
r += s.height + t.itemGapY;
}
V.length && (r -= t.itemGapY);
const i = r + t.paddingY;
return w.setAttribute("x", "0"), w.setAttribute("y", "0"), w.setAttribute("width", String(t.maxWidth)), w.setAttribute("height", String(i)), C.remove(), i + Math.round(t.fontSize * 0.4);
}
function ht(e) {
const o = e.cloneNode(!0);
return o.querySelectorAll("script").forEach((h) => h.remove()), z(e, o), O(o), o;
}
function B(e) {
const o = Array.from(e.childNodes).filter((c) => c.nodeType === 1 && c.nodeName.toLowerCase() === "defs"), h = Array.from(e.childNodes).filter((c) => !(c.nodeType === 1 && c.nodeName.toLowerCase() === "defs")), u = document.createElementNS(et, "g");
u.setAttribute("id", "__vdu_export_content");
for (const c of h) u.appendChild(c);
for (const c of o) e.appendChild(c);
return e.appendChild(u), u;
}
function K(e, o) {
o <= 0 || e.setAttribute("transform", `translate(0, ${o})`);
}
function ct(e, o) {
if (o <= 0) return;
const h = L(e), u = e.getAttribute("height");
if (h)
e.setAttribute("viewBox", `${h.minX} ${h.minY} ${h.width} ${h.height + o}`), u && e.setAttribute("height", String(Number(u) + o));
else if (u)
e.setAttribute("height", String(Number(u) + o));
else {
const c = e.getBBox();
e.setAttribute("viewBox", `0 0 ${Math.max(1, c.width)} ${Math.max(1, c.height + o)}`);
}
}
function U(e) {
const o = L(e);
if (o)
return o.width;
const h = Number(e.getAttribute("width"));
return !Number.isNaN(h) && h > 0 ? h : e.getBBox().width || 0;
}
function G(e) {
const o = L(e);
if (o) return o.height;
const h = Number(e.getAttribute("height"));
return !Number.isNaN(h) && h > 0 ? h : e.getBBox().height || 0;
}
async function ut(e) {
const o = it(e);
Mt();
try {
if (document.fonts?.ready)
try {
await Promise.race([document.fonts.ready, new Promise((T) => setTimeout(T, 4e3))]);
} catch {
}
const h = B(e), u = L(e), c = u ? u.minX : 0, t = u ? u.minY : 0, S = Math.max(1, U(e)), w = Math.max(1, G(e)), A = wt(gt(e).getPropertyValue("font-family") || "");
let M = (at ? null : dt(e, S, c, t, A)) ?? 0;
const X = F && F.value && F.value.position ? String(F.value.position).toLowerCase() : "top";
F && F.value && F.value.show && X === "top" && (M += q(e, S, c, t + M, A)), K(h, M);
let D = 0;
F && F.value && F.value.show && X === "bottom" && (D += q(e, S, c, t + M + w, A)), ct(e, M + D), e.style.backgroundColor = ot.value ?? "#FFF", await Et(e, { mode: "raster" }), Tt(e, v.value.text ? -6 : -48);
} finally {
st(o), Mt();
}
}
async function Z() {
const e = await b(), o = ht(e);
await ut(o);
const u = `<?xml version="1.0" standalone="no"?>
${new XMLSerializer().serializeToString(o)}`, c = new Blob([u], { type: "image/svg+xml;charset=utf-8" }), t = URL.createObjectURL(c), S = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(u)}`;
return { blob: c, url: t, text: u, dataUrl: S };
}
async function ft(e) {
const { url: o } = await Z(), h = e || v.value?.text || "chart", u = document.createElement("a");
u.href = o, u.download = h.endsWith(".svg") ? h : `${h}.svg`, document.body.appendChild(u), u.click(), document.body.removeChild(u), URL.revokeObjectURL(o);
}
return { ready: nt, getSvg: Z, exportSvg: ft };
}
function Tt(N, v = -50) {
if (!v) return;
const F = N.getAttribute("viewBox"), rt = (W) => {
if (!W) return;
const j = N.getAttribute("height");
if (!j) return;
const b = /^(\d+(\.\d+)?)(px)?$/.exec(j.trim());
if (!b) return;
const f = parseFloat(b[1]) || 0, y = Math.max(1, f + W);
N.setAttribute("height", String(y));
};
if (F) {
const W = F.trim().split(/\s+|,/).map(Number);
if (W.length !== 4 || W.some((O) => !Number.isFinite(O))) return;
const [j, b, f, y] = W, $ = b + v, z = -v, L = Math.max(1, y + z);
N.setAttribute("viewBox", `${j} ${$} ${f} ${L}`), rt(z);
return;
}
let ot = Number(N.getAttribute("width")), I = Number(N.getAttribute("height"));
if (!(ot > 0 && I > 0)) {
const W = N.getBBox();
ot = Math.max(1, W.width || 1), I = Math.max(1, W.height || 1);
}
const at = v, lt = -v, nt = Math.max(1, I + lt);
N.setAttribute("viewBox", `0 ${at} ${ot} ${nt}`), (function() {
const j = N.getAttribute("height");
if (!j) return;
const b = /^(\d+(\.\d+)?)(px)?$/.exec(j.trim());
if (!b) return;
const f = parseFloat(b[1]) || 0, y = Math.max(1, f + lt);
N.setAttribute("height", String(y));
})();
}
async function Et(N, { mode: v = "raster" } = {}) {
const F = Array.from(N.querySelectorAll("foreignObject"));
if (!F.length) return { converted: 0, rasterized: 0, skipped: 0, errors: 0 };
let rt = 0, ot = 0, I = 0, at = 0;
const lt = (b) => ["div", "p", "span", "strong", "em", "b", "i", "br"].includes(b), nt = (b) => {
try {
const f = b.firstElementChild;
if (!f) return !1;
const y = [f];
for (; y.length; ) {
const $ = y.pop();
if ($.nodeType === 3)
continue;
if ($.nodeType !== 1)
return !1;
const z = ($.tagName || "").toLowerCase();
if (!lt(z) || $.querySelector?.("img,svg,canvas,video,foreignObject"))
return !1;
for (const L of Array.from($.childNodes))
y.push(L);
}
return !0;
} catch {
return !1;
}
};
function W(b) {
try {
const f = b.firstElementChild;
if (!f) return null;
const y = (n, r = 0) => Number.isFinite(+n) ? +n : r, $ = y(b.getAttribute("x"), 0), z = y(b.getAttribute("y"), 0);
let L = y(b.getAttribute("width"), NaN);
if (!Number.isFinite(L) || L <= 0) {
const n = b.getBBox?.();
L = Math.max(1, y(n?.width, 0));
}
const O = (n, r) => {
if (!n) return Math.round(r * 1.2);
const i = n.trim().toLowerCase();
if (i === "normal") return Math.round(r * 1.2);
if (i.endsWith("px")) return parseFloat(i) || Math.round(r * 1.2);
if (i.endsWith("%")) return parseFloat(i) / 100 * r || Math.round(r * 1.2);
if (i.endsWith("em")) return (parseFloat(i) || 1) * r;
if (i.endsWith("rem")) {
const a = parseFloat(getComputedStyle(document.documentElement).fontSize) || r;
return (parseFloat(i) || 1) * a;
}
const s = Number(i);
return Number.isFinite(s) ? s * r : Math.round(r * 1.2);
}, it = (n) => {
const r = (s) => {
const a = (s || "").trim().toLowerCase();
if (a.endsWith("px")) return parseFloat(a) || 0;
if (a.endsWith("rem")) {
const m = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
return (parseFloat(a) || 0) * m;
}
if (a.endsWith("em")) {
const m = parseFloat(getComputedStyle(document.body).fontSize) || 16;
return (parseFloat(a) || 0) * m;
}
const l = Number(a);
return Number.isFinite(l) ? l : 0;
}, i = (n || "").split(/\s+/).map(r).filter(Number.isFinite);
return i.length ? i.length === 1 ? [i[0], i[0], i[0], i[0]] : i.length === 2 ? [i[0], i[1], i[0], i[1]] : i.length === 3 ? [i[0], i[1], i[2], i[1]] : [i[0], i[1], i[2], i[3]] : [0, 0, 0, 0];
}, st = (n, r) => {
const i = gt(n);
let s = i.getPropertyValue("font-family") || r?.ff || "system-ui";
s = wt(s);
let a = parseFloat(i.getPropertyValue("font-size"));
Number.isFinite(a) || (a = r?.fs || 14);
const l = i.getPropertyValue("font-weight") || r?.fw || "400", m = i.getPropertyValue("font-style") || r?.fsty || "normal", d = i.getPropertyValue("font-stretch") || r?.fstc || "normal", k = i.getPropertyValue("letter-spacing") || r?.lsp || "normal", g = i.getPropertyValue("word-spacing") || r?.wsp || "0px", x = i.getPropertyValue("font-kerning") || r?.kern || "auto", _ = i.getPropertyValue("font-variant-ligatures") || r?.liga || "normal", H = i.getPropertyValue("text-transform") || r?.ttfm || "none", Q = i.getPropertyValue("color") || r?.fill || "#000", Y = i.getPropertyValue("line-height"), mt = !Y || Y.trim().toLowerCase() === "normal" ? r?.lh ?? Math.round(a * 1.2) : O(Y, a), p = (i.getPropertyValue("text-align") || r?.ta || "start").trim().toLowerCase();
let tt = parseFloat(i.getPropertyValue("padding-top")) || 0, pt = parseFloat(i.getPropertyValue("padding-right")) || 0, bt = parseFloat(i.getPropertyValue("padding-bottom")) || 0, xt = parseFloat(i.getPropertyValue("padding-left")) || 0;
const St = i.getPropertyValue("padding");
if (St && tt === 0 && pt === 0 && bt === 0 && xt === 0) {
const [kt, Ft, _t, zt] = it(St);
tt = kt, pt = Ft, bt = _t, xt = zt;
}
const Nt = parseFloat(i.getPropertyValue("border-left-width")) || 0, vt = parseFloat(i.getPropertyValue("border-right-width")) || 0, $t = i.getPropertyValue("box-sizing") || "content-box";
return { ff: s, fs: a, fw: l, fsty: m, fstc: d, lsp: k, wsp: g, kern: x, liga: _, ttfm: H, fill: Q, lh: mt, ta: p, padL: xt, padR: pt, padT: tt, padB: bt, bL: Nt, bR: vt, box: $t };
}, dt = (n) => /^(div|p|section|article|ul|ol|li|h[1-6])$/.test(n), q = { __para__: !0 }, ht = { __br__: !0 }, B = [], K = st(f), ct = (n, r, i) => {
if (n.nodeType === 3) {
const m = (n.nodeValue || "").replace(/\s+/g, " ").trim();
m && B.push({ text: m, style: r, path: i.slice() });
return;
}
if (n.nodeType !== 1) return;
const s = n.tagName.toLowerCase();
if (s === "br") {
B.push({ ...ht, path: i.slice() });
return;
}
const a = st(n, r);
i.push(n);
for (const l of Array.from(n.childNodes)) ct(l, a, i);
i.pop(), dt(s) && B.push({ ...q, path: i.slice() });
};
for (ct(f, K, [f]); B.length && (B.at(-1).__para__ || B.at(-1).__br__); ) B.pop();
if (!B.length) return null;
const U = B.filter((n) => !n.__para__ && !n.__br__), G = (() => {
if (!U.length) return [f];
const n = U.map((s) => s.path), r = Math.min(...n.map((s) => s.length));
let i = 0;
for (; i < r; ) {
const s = n[0][i];
if (n.every((a) => a[i] === s)) i += 1;
else break;
}
return n[0].slice(0, Math.max(1, i));
})(), ut = G[G.length - 1] || f, Z = st(ut);
let ft = 0, e = 0, o = 0;
for (const n of G) {
const r = st(n);
ft += r.padL, e += r.padR, o += r.padT;
}
const h = [Math.max(1, L - ft - e)];
for (const n of G)
try {
const r = gt(n);
if (n.clientWidth && n.clientWidth > 0) {
const a = parseFloat(r.paddingLeft) || 0, l = parseFloat(r.paddingRight) || 0, m = Math.max(1, n.clientWidth - a - l);
h.push(m);
}
const i = r.width, s = parseFloat(i);
if (Number.isFinite(s) && s > 0) {
const a = r.boxSizing || r.getPropertyValue("box-sizing") || "content-box", l = parseFloat(r.paddingLeft) || 0, m = parseFloat(r.paddingRight) || 0, d = parseFloat(r.borderLeftWidth) || 0, k = parseFloat(r.borderRightWidth) || 0, g = a === "border-box" ? Math.max(1, s - l - m - d - k) : Math.max(1, s);
h.push(g);
}
} catch {
}
let u = Math.floor(Math.min(...h.filter(Number.isFinite))) - 1;
u > 0 || (u = 1);
let c = "start", t = $ + ft;
Z.ta === "center" ? (c = "middle", t = $ + ft + u / 2) : (Z.ta === "right" || Z.ta === "end") && (c = "end", t = $ + (L - e));
const S = b.ownerSVGElement || b.closest("svg"), w = document.createElementNS(et, "text");
w.setAttribute("x", String(t)), w.setAttribute("y", String(z + o)), w.setAttribute("text-anchor", c), w.setAttribute("dominant-baseline", "text-before-edge"), w.setAttribute("xml:space", "preserve");
const A = document.createElementNS(et, "text");
A.setAttribute("x", "0"), A.setAttribute("y", "0"), A.setAttribute("opacity", "0"), (S || b).appendChild(A);
const C = (n) => `font-family:${n.ff}; font-size:${n.fs}px; font-weight:${n.fw}; font-style:${n.fsty}; font-stretch:${n.fstc}; letter-spacing:${n.lsp}; word-spacing:${n.wsp}; font-kerning:${n.kern}; font-variant-ligatures:${n.liga}; text-transform:${n.ttfm};`, M = (n, r) => (A.textContent = n || "", A.setAttribute("style", C(r)), A.getComputedTextLength()), X = (n) => M(" ", n), D = [];
let T = [], R = 0;
const J = () => {
T.length && D.push({ segs: T.slice() }), T = [], R = 0;
}, E = (n, r, i) => {
let s = M(n, r);
if (i) {
const a = X(r);
s += a, T.push({ text: " ", ...r, w: a, isSpace: !0 });
}
T.push({ text: n, ...r, w: s }), R += s;
}, V = (n, r, i) => {
let s = "";
for (const a of n) {
const l = s + a;
if (M(l, r) <= i) s = l;
else break;
}
return s || n[0] || "";
};
for (const n of B) {
if (n.__para__ || n.__br__) {
J();
continue;
}
const r = n.style, i = n.text.split(/(\s+)/).filter((l) => l.length > 0), s = (l, m) => {
if (!l) return;
const d = Math.max(1, u), k = M(l, r) + (m ? X(r) : 0);
if (T.length === 0)
if (k <= d)
E(l, r, !1);
else {
let g = l;
for (; g; ) {
const x = V(g, r, d);
E(x, r, !1), g = g.slice(x.length), g && J();
}
}
else if (R + k <= d)
E(l, r, m);
else if (J(), M(l, r) <= d)
E(l, r, !1);
else {
let g = l;
for (; g; ) {
const x = V(g, r, d);
E(x, r, !1), g = g.slice(x.length), g && J();
}
}
};
let a = !1;
for (const l of i) {
if (/^\s+$/.test(l)) {
a = !0;
continue;
}
s(l, a), a = !1;
}
}
J();
for (let n = 0; n < D.length; n += 1) {
const r = D[n].segs, i = Math.max(...r.map((a) => a.fs || Z.fs), Z.fs);
let s = !0;
for (const a of r) {
const l = document.createElementNS(et, "tspan");
s && (l.setAttribute("x", String(t)), n > 0 && l.setAttribute("dy", String(i)), s = !1), l.setAttribute("style", `${C(a)} fill:${a.fill};`), l.textContent = a.text, w.appendChild(l);
}
if (!r.length && n > 0) {
const a = document.createElementNS(et, "tspan");
a.setAttribute("x", String(t)), a.setAttribute("dy", String(i)), a.textContent = "", w.appendChild(a);
}
}
try {
A.remove();
} catch {
}
return w;
} catch {
return null;
}
}
const j = (b) => {
try {
const f = document.createElement("div");
f.style.position = "absolute", f.style.left = "-99999px", f.style.top = "-99999px", f.style.visibility = "hidden", f.style.pointerEvents = "none", f.style.width = "auto", f.style.height = "auto";
const y = b.cloneNode(!0);
y.style.width = "auto", y.style.height = "auto", y.style.display = "inline-block", y.style.maxWidth = "none", y.style.maxHeight = "none", y.style.boxSizing = "content-box", document.body.appendChild(f), f.appendChild(y);
const $ = y.getBoundingClientRect(), z = Math.ceil($.width || y.scrollWidth || 0), L = Math.ceil($.height || y.scrollHeight || 0);
return f.remove(), { w: Math.max(1, z), h: Math.max(1, L) };
} catch {
return { w: 0, h: 0 };
}
};
for (const b of F)
try {
if (b.hasAttribute("data-no-svg-export")) {
b.remove(), I += 1;
continue;
}
if (nt(b)) {
const f = W(b);
if (f) {
b.parentNode.replaceChild(f, b), rt += 1;
continue;
}
}
I += 1;
} catch {
at += 1;
}
if (v === "raster") {
const b = Array.from(N.querySelectorAll("foreignObject"));
for (const f of b)
try {
if (f.hasAttribute("data-no-svg-export")) {
f.remove(), I += 1;
continue;
}
await new Promise((G) => requestAnimationFrame(G));
const y = f.getBBox();
let $ = Math.max(1, Math.ceil(y.width)), z = Math.max(1, Math.ceil(y.height));
const L = f.firstElementChild;
if (L) {
const G = j(L), ut = parseFloat(f.getAttribute("width") || "0") || 0, Z = parseFloat(f.getAttribute("height") || "0") || 0;
$ = Math.max($, ut, G.w), z = Math.max(z, Z, G.h);
}
if (!($ > 0 && z > 0)) {
I += 1;
continue;
}
const O = document.createElementNS(et, "svg");
O.setAttribute("xmlns", et), O.setAttribute("xmlns:xlink", yt), O.setAttribute("width", String($)), O.setAttribute("height", String(z)), O.setAttribute("viewBox", `0 0 ${$} ${z}`);
const it = f.cloneNode(!0);
it.setAttribute("x", "0"), it.setAttribute("y", "0"), it.setAttribute("width", String($)), it.setAttribute("height", String(z)), O.appendChild(it);
const st = new XMLSerializer().serializeToString(O), dt = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(st), q = document.createElement("canvas"), ht = 2;
q.width = Math.max(1, Math.floor($ * ht)), q.height = Math.max(1, Math.floor(z * ht));
const B = q.getContext("2d"), K = new Image();
K.decoding = "sync", K.crossOrigin = "anonymous", await new Promise((G, ut) => {
K.onload = G, K.onerror = ut, K.src = dt;
}), B.drawImage(K, 0, 0, q.width, q.height);
const ct = q.toDataURL("image/png"), U = document.createElementNS(et, "image");
U.setAttributeNS(yt, "href", ct), U.setAttribute("href", ct), U.setAttribute("x", f.getAttribute("x") || String(y.x)), U.setAttribute("y", f.getAttribute("y") || String(y.y)), U.setAttribute("width", String($)), U.setAttribute("height", String(z)), f.parentNode.replaceChild(U, f), ot += 1;
} catch {
at += 1;
}
}
return { converted: rt, rasterized: ot, skipped: I, errors: at };
}
export {
Ot as u
};