UNPKG

vue-data-ui

Version:

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

1,528 lines (1,526 loc) 97.4 kB
import { t as e } from "./rolldown-runtime-Dy4uBu1J.js"; import { C as t, Jt as n, Nt as r, q as i } from "./lib-Bttd6u5E.js"; import { n as a, t as o } from "./useHints-Dq_w2E8B.js"; import { t as s } from "./useConfig-D3scuR88.js"; import { t as ee } from "./usePrinter-DN5bYhTG.js"; import { t as c } from "./dom-to-png-BYIvdTe8.js"; import { t as l } from "./_plugin-vue_export-helper-B3ysoDQm.js"; import { t as u } from "./BaseIcon-BfndwIWE.js"; import { t as te } from "./vue-ui-accordion-BxGriZik.js"; import { t as ne } from "./ColorPicker--ayG2YHf.js"; import { Fragment as re, Teleport as ie, computed as d, createBlock as f, createCommentVNode as p, createElementBlock as m, createElementVNode as h, createTextVNode as g, createVNode as _, nextTick as ae, normalizeClass as v, normalizeStyle as y, onBeforeUnmount as oe, onMounted as se, openBlock as b, ref as x, renderList as ce, renderSlot as le, toDisplayString as S, unref as ue, vModelCheckbox as de, vModelText as fe, watch as pe, withCtx as C, withDirectives as me, withModifiers as he } from "vue"; //#region src/registerAnnotatorShortcuts.js function ge(e) { let t = (t) => e.isMacLike.value ? t.metaKey : t.ctrlKey, n = (e) => { let t = e; if (!t) return !1; let n = (t.tagName || "").toLowerCase(); return t.isContentEditable || n === "input" || n === "textarea" || n === "select"; }, r = (t) => !!(!e.isSummaryOpen.value || n(t.target) || e.isWriting.value), i = () => { e.isDeleteMode.value = !1, e.isMoveMode.value = !1, e.isResizeMode.value = !1, e.isSelectMode.value = !1, e.isDrawMode.value = !1, e.isTextMode.value = !1, e.activeShape.value = void 0, e.showCaret.value = !1; }, a = (t) => { switch (i(), t) { case "m": e.isMoveMode.value = !0; break; case "r": e.isResizeMode.value = !0; break; case "d": e.isDeleteMode.value = !0; break; case "g": e.isSelectMode.value = !0, e.setShapeTo("group"), e.activeShape.value = "group"; break; case "t": e.isTextMode.value = !0, e.isWriting.value = !1, e.showCaret.value = !1; } }, o = (t) => { switch (t) { case "c": e.setShapeTo("circle"); break; case "s": e.setShapeTo("rect"); break; case "a": e.setShapeTo("arrow"); break; case "l": e.setShapeTo("line"); } }, s = (t, n) => { let r = e.lastSelectedShape.value; if (!r) return; let i = (e, t) => { typeof r[e] == "number" && (r[e] += t); }; switch (r.type) { case "rect": case "circle": case "text": i("x", t), i("y", n); break; case "arrow": i("x", t), i("y", n), i("endX", t), i("endY", n); } }, ee = () => { let t = e.lastSelectedShape.value; t && (e.shapes.value = e.shapes.value.filter((e) => e.id !== t.id), e.lastSelectedShape.value = void 0); }, c = !1, l = null, u = () => { c || (c = !0, e.history?.value?.begin?.("nudge")); }, te = () => { c && (clearTimeout(l), l = setTimeout(() => { c = !1, e.history?.value?.end?.(); }, 160)); }, ne = () => { clearTimeout(l), c && e.history?.value?.end?.(), c = !1; }, re = (n) => { if (t(n) && !n.shiftKey && n.key.toLowerCase() === "z") { if (r(n)) return; n.preventDefault(), e.undoLastShape?.(); return; } if (t(n) && n.shiftKey && n.key.toLowerCase() === "z" || t(n) && n.key.toLowerCase() === "y") { if (r(n)) return; n.preventDefault(), typeof e.redoLastShape == "function" ? e.redoLastShape() : e.history?.value?.redo?.(); return; } if (r(n)) return; let c = n.key.toLowerCase(); if (c === "escape") { n.preventDefault(), i(); return; } if (c === "delete" || c === "backspace") { n.preventDefault(), ee(); return; } if ([ "m", "r", "d", "g", "t" ].includes(c)) { n.preventDefault(), a(c); return; } if ([ "c", "a", "l", "s" ].includes(c)) { n.preventDefault(), o(c); return; } if (n.key === "ArrowUp" || n.key === "ArrowDown" || n.key === "ArrowLeft" || n.key === "ArrowRight") { n.preventDefault(), u(); let e = n.shiftKey ? 10 : 1; n.key === "ArrowUp" && s(0, -e), n.key === "ArrowDown" && s(0, e), n.key === "ArrowLeft" && s(-e, 0), n.key === "ArrowRight" && s(e, 0), te(); } }, ie = (e) => { e.key.startsWith("Arrow") && te(); }; return window.addEventListener("keydown", re), window.addEventListener("keyup", ie), function() { window.removeEventListener("keydown", re), window.removeEventListener("keyup", ie), ne(); }; } //#endregion //#region src/atoms/TeleportedTooltip.vue var _e = { class: "teleport-tooltip__inner" }, w = /*#__PURE__*/ l({ __name: "TeleportedTooltip", props: { show: { type: Boolean, default: !1 }, x: { type: Number, required: !0 }, y: { type: Number, required: !0 }, placement: { type: String, default: "top" }, styleObject: { type: Object, default() { return {}; } }, delay: { type: Number, default: 0 }, delayIn: { type: Number, default: 300 }, delayOut: { type: Number, default: 0 } }, setup(e) { let t = e, n = d(() => t.delayIn ?? t.delay), r = d(() => t.delayOut ?? t.delay), i = x(!1), a = null, o = null; function s() { a &&= (clearTimeout(a), null), o &&= (clearTimeout(o), null); } function ee() { s(); let e = Math.max(0, n.value || 0); e === 0 ? i.value = !0 : a = setTimeout(() => { i.value = !0, a = null; }, e); } function c() { s(); let e = Math.max(0, r.value || 0); e === 0 ? i.value = !1 : o = setTimeout(() => { i.value = !1, o = null; }, e); } pe(() => t.show, (e) => { e ? ee() : c(); }, { immediate: !0 }), se(() => { t.show && ee(); }), oe(() => { s(); }); let l = d(() => ({ position: "fixed", zIndex: 2147483647, top: `${t.y}px`, left: `${t.x}px`, transform: t.placement === "bottom" ? "translate(-50%, 8px)" : "translate(-50%, -100%)", pointerEvents: "none", ...t.styleObject })); return (t, n) => (b(), f(ie, { to: "body" }, [i.value ? (b(), m("div", { key: 0, class: v(["teleport-tooltip", e.placement]), style: y(l.value), role: "tooltip", "aria-hidden": "false" }, [h("div", _e, [le(t.$slots, "default", {}, void 0, !0)])], 6)) : p("", !0)])); } }, [["__scopeId", "data-v-c292996f"]]), ve = /* @__PURE__ */ e({ default: () => yt }), ye = { class: "vue-data-ui-component vue-ui-annotator" }, be = { "data-dom-to-png-ignore": "" }, xe = ["disabled"], Se = ["disabled"], Ce = ["disabled"], we = ["disabled"], Te = ["disabled"], Ee = ["disabled"], De = ["disabled"], Oe = ["disabled"], ke = ["disabled"], Ae = { class: "tool-selection", style: { "margin-top": "6px" } }, je = { viewBox: "0 0 12 12", style: { width: "100%" } }, Me = ["fill"], Ne = { key: 0 }, Pe = { class: "tool-input" }, Fe = ["checked"], Ie = { viewBox: "0 0 12 12", style: { width: "100%" } }, Le = ["fill"], Re = { key: 1 }, ze = { class: "tool-input" }, Be = ["checked"], Ve = { viewBox: "0 0 24 24", style: { width: "100%" } }, He = ["stroke"], Ue = { key: 2 }, We = { style: { display: "flex", "flex-direction": "column", "align-items": "center", "justify-content": "center" } }, Ge = { class: "tool-input" }, Ke = { key: 3 }, qe = { style: { display: "flex", "flex-direction": "column", "align-items": "center", "justify-content": "center" } }, Je = { class: "tool-input" }, Ye = { viewBox: "0 0 24 24", height: "24", width: "24", style: { "margin-bottom": "-5px", "margin-top": "-10px" } }, Xe = ["checked"], Ze = { key: 4 }, Qe = { style: { display: "flex", "flex-direction": "column", "align-items": "center", "justify-content": "center" } }, $e = { class: "tool-input" }, et = { key: 5 }, tt = { key: 6 }, nt = ["disabled"], rt = { key: 7 }, it = ["disabled"], at = { key: 8 }, ot = { key: 9 }, st = { key: 10 }, ct = { key: 11 }, lt = { style: { display: "flex", "flex-direction": "column", "align-items": "center", "justify-content": "center" }, class: "tooltip" }, ut = { style: { display: "flex", "flex-direction": "column", "align-items": "start", "justify-content": "center" } }, dt = { class: "tool-input", style: { "font-variant-numeric": "tabular-nums" } }, ft = ["id"], pt = [ "viewBox", "width", "height" ], mt = [ "width", "height", "pointer-events" ], ht = ["innerHTML"], gt = [ "height", "viewBox", "width" ], _t = ["cx", "cy"], vt = "annotations", yt = /*#__PURE__*/ l({ __name: "vue-ui-annotator", props: { config: { type: Object, default() { return {}; } }, dataset: { type: Object, default() { return { shapes: [], lastSelectedShape: void 0 }; } } }, emits: ["toggleOpenState", "saveAnnotations"], setup(e, { emit: l }) { let ie = e, _e = l, ve = x(i()), { isImaging: yt, generateImage: bt } = ee({ elementId: ve.value, fileName: vt }), T = x(void 0), xt = x(1), E = x({ start: { x: 0, y: 0 }, end: { x: 0, y: 0 } }), D = x(void 0), O = x(void 0), St = x(!1), k = x(!1), Ct = x(!1), A = x(!1), wt = x(!1), Tt = x(!0), j = x(!1), Et = x(!1), Dt = x(!1), M = x(!1), Ot = x(!1), N = x(!1), P = x(!1), kt = x(!1), F = x(!1), At = x(!1), I = x(!1), L = x(ie.dataset?.lastSelectedShape ?? void 0), R = x({ x: 0, y: 0 }), jt = x(!0), z = x([]), B = x(ie.dataset?.shapes || []); x([]); let Mt = x(Math.round(Math.random()) * 1e5), Nt = x(1e3), Pt = x(1e3), V = x({ arrow: { color: "grey", filled: !0 }, circle: { color: "grey", filled: !1, radius: 3, strokeWidth: 2 }, rect: { color: "grey", filled: !1, strokeWidth: 2, height: 12, width: 12 } }), Ft = x("#1A1A1A"), H = x(!1), It = x(1), Lt = x(void 0), Rt = x(1), zt = x(1), U = x("start"), Bt = x(20), Vt = x(100), Ht = r, Ut = x(null), W = x(!1), G = x(null), K = x({ x: 0, y: 0 }), Wt = x(null), q = x([]), Gt = x(!1), Kt = x(null), qt = x({ undo: 0, redo: 0 }), Jt = x(null); x(null), x(null); let Yt = x(null), J = d(() => { let e = s().vue_ui_annotator; if (!Object.keys(ie.config || {}).length) return e; let r = n({ defaultConfig: e, userConfig: ie.config }); return t(r); }); a({ config: () => J.value, dataset: () => [], component: "VueUiAnnotator", rules: [o.noHint] }); let Y = d(() => J.value.useCursorPointer), X = d(() => { let e = J.value.style.tooltips; return { backgroundColor: e.backgroundColor, color: e.color, border: e.border, borderRadius: `${e.borderRadius}px`, boxShadow: e.boxShadow }; }), Xt = d(() => B.value.filter((e) => !["line", "group"].includes(e.type)).length > 1), Zt = d(() => Ht[Vt.value > 98 ? 98 : Vt.value]), Qt = d(() => { switch (!0) { case A.value: return "default"; case M.value: return "move"; case F.value: return "text"; case N.value: return "se-resize"; default: return ""; } }), $t = d(() => B.value), en = x(null); function tn(e) { if (e) switch (!0) { case e.type === "rect": return ` <rect id="${e.id}" style="stroke-dasharray: 10; display:${O.value && O.value === e.id ? "initial" : "none"}" x="${e.x - 20}" y="${e.y - 20}" height="${e.rectHeight + 40}" width="${e.rectWidth + 40}" fill="transparent" stroke="grey" /> `; case e.type === "circle": return ` <rect id="${e.id}" style="stroke-dasharray: 10; display:${O.value && O.value === e.id ? "initial" : "none"}" x="${e.x - e.circleRadius - 20}" y="${e.y - e.circleRadius - 20}" height="${e.circleRadius * 2 + 40}" width="${e.circleRadius * 2 + 40}" fill="transparent" stroke="grey" /> `; case e.type === "arrow": let t = e.endX - e.x > 0, n = e.endY - e.y > 0; return ` <rect id="${e.id}" style="stroke-dasharray: 10; display:${O.value && O.value === e.id ? "initial" : "none"}" x="${t ? e.x - 20 : e.endX - 20}" y="${n ? e.y - 20 : e.endY - 20}" height="${n ? e.endY - e.y + 40 : e.y - e.endY + 40}" width="${t ? e.endX - e.x + 40 : e.x - e.endX + 40}" fill="transparent" stroke="grey" /> `; case e.type === "text": let r = en.value ? Array.from(en.value.getElementsByTagName("text")).find((t) => t.id === e.id) : null; if (!r) return; let { x: i, y: a, width: o, height: s } = r.getBBox(); return ` <rect id="${e.id}" style="stroke-dasharray: 10; display:${O.value && O.value === e.id ? "initial" : "none"}" x="${i - 20}" y="${a - 20}" height="${s + 40}" width="${o + 40}" fill="transparent" stroke="grey" /> `; default: return ""; } } function nn(e, t = !1) { switch (!0) { case e.type === "circle": return ` <g id="${e.id}" style="display:${A.value ? "initial" : "none"};"> <circle id="${e.id}" cx="${e.x}" cy="${e.y}" r="12" fill="red"/> <line stroke="white" stroke-width="2" id="${e.id}" x1="${e.x - 4}" y1="${e.y - 4}" x2="${e.x + 4}" y2="${e.y + 4}"/> <line stroke="white" stroke-width="2" id="${e.id}" x1="${e.x + 4}" y1="${e.y - 4}" x2="${e.x - 4}" y2="${e.y + 4}"/> </g> `; case e.type === "text": let n, r = [ -8, -12, -4, -12, -4 ]; switch (!0) { case e.textAlign === "start": n = t ? [ -20, -24, -16, -16, -24 ] : [ -16, -20, -12, -12, -20 ]; break; case e.textAlign === "middle": n = [ 0, -4, 4, 4, -4 ], r = [ -32, -36, -28, -36, -28 ]; break; case e.textAlign === "end": n = [ 16, 20, 12, 12, 20 ]; break; default: n = [ 0, 0, 0 ]; } return ` <g id="${e.id}" style="display:${A.value ? "initial" : "none"};"> <circle id="${e.id}" cx="${e.x + n[0]}" cy="${e.y + r[0]}" r="12" fill="red"/> <line stroke="white" stroke-width="2" id="${e.id}" x1="${e.x + n[1]}" y1="${e.y + r[1]}" x2="${e.x + n[2]}" y2="${e.y + r[2]}"/> <line stroke="white" stroke-width="2" id="${e.id}" x1="${e.x + n[3]}" y1="${e.y + r[3]}" x2="${e.x + n[4]}" y2="${e.y + r[4]}"/> </g> `; default: return ` <g id="${e.id}" style="display:${A.value ? "initial" : "none"};"> <circle id="${e.id}" cx="${e.x - 4}" cy="${e.y - 4}" r="12" fill="red"/> <line stroke="white" stroke-width="2" id="${e.id}" x1="${e.x - 8}" y1="${e.y - 8}" x2="${e.x}" y2="${e.y}"/> <line stroke="white" stroke-width="2" id="${e.id}" x1="${e.x}" y1="${e.y - 8}" x2="${e.x - 8}" y2="${e.y}"/> </g> `; } } function rn(e) { switch (!0) { case e.textAlign === "middle": return `<path class="vue-ui-annotator-caret" stroke="black" stroke-width="2" d="M${e.x},${e.y - e.fontSize} ${e.x},${e.y - e.fontSize - 15}" /> <path class="vue-ui-annotator-caret" stroke="black" stroke-width="2" d="M${e.x - 3},${e.y - e.fontSize - 5} ${e.x},${e.y - e.fontSize} ${e.x + 3},${e.y - e.fontSize - 5}"/>`; case e.textAlign === "start": let t = e.isBulletTextMode ? e.fontSize : 0; return `<path class="vue-ui-annotator-caret" d="M${e.x - 20 - t},${e.y - e.fontSize / 6} ${e.x - 5 - t},${e.y - e.fontSize / 6}" stroke="black" stroke-width="2" /> <path class="vue-ui-annotator-caret" d="M${e.x - 10 - t},${e.y - e.fontSize / 3} ${e.x - 5 - t},${e.y - e.fontSize / 6} ${e.x - 10 - t},${e.y}" stroke="black" stroke-width="2">`; case e.textAlign === "end": return `<path class="vue-ui-annotator-caret" d="M${e.x + 20},${e.y - e.fontSize / 6} ${e.x + 5},${e.y - e.fontSize / 6}" stroke="black" stroke-width="2" /> <path class="vue-ui-annotator-caret" d="M${e.x + 10},${e.y - e.fontSize / 3} ${e.x + 5},${e.y - e.fontSize / 6} ${e.x + 10},${e.y}" stroke="black" stroke-width="2">`; default: return ""; } } function an(e, t, n = !1) { switch (!0) { case e.textAlign === "start": return ` <g id="${e.id}"> <rect id="${e.id}" style="display:${L.value && L.value.id === e.id ? "initial" : "none"};" x="${e.x}" y="${e.y - 50}" height="${e.lines === 0 || e.lines === 1 ? e.fontSize * 4 : e.fontSize * 2 * e.lines}" width="100" fill="rgba(0,0,0,0)" /> <text style="user-select:none; height:100px;" id="${e.id}" x="${e.x}" y="${e.y}" text-anchor="${e.textAlign}" font-size="${e.fontSize}" fill="${e.color}" font-weight="${e.isBold ? "bold" : "normal"}" font-style="${e.isItalic ? "italic" : "normal"}" text-decoration="${e.isUnderline ? "underline" : "none"}" > ${t.join("")} </text> ${H.value && L.value && L.value.id === e.id ? rn(e) : ""} ${nn(e, n)} </g> `; case e.textAlign === "middle": return ` <g id="${e.id}"> <rect id="${e.id}" style="display:${L.value && L.value.id === e.id ? "initial" : "none"};" x="${e.x - 50}" y="${e.y - 50}" height="${e.lines === 0 || e.lines === 1 ? e.fontSize * 4 : e.fontSize * 2 * e.lines}" width="100" fill="rgba(0,0,0,0)" /> <text style="user-select:none; height:100px;" id="${e.id}" x="${e.x}" y="${e.y}" text-anchor="${e.textAlign}" font-size="${e.fontSize}" fill="${e.color}" font-weight="${e.isBold ? "bold" : "normal"}" font-style="${e.isItalic ? "italic" : "normal"}" text-decoration="${e.isUnderline ? "underline" : "none"}" > ${t.join("")} </text> ${H.value && L.value && L.value.id === e.id ? rn(e) : ""} ${nn(e)} </g> `; case e.textAlign === "end": return ` <g id="${e.id}"> <rect id="${e.id}" style="display:${L.value && L.value.id === e.id ? "initial" : "none"};" x="${e.x - 100}" y="${e.y - 50}" height="${e.lines === 0 || e.lines === 1 ? e.fontSize * 4 : e.fontSize * 2 * e.lines}" width="100" fill="rgba(0,0,0,0)" /> <text style="user-select:none; height:100px;" id="${e.id}" x="${e.x}" y="${e.y}" text-anchor="${e.textAlign}" font-size="${e.fontSize}" fill="${e.color}" font-weight="${e.isBold ? "bold" : "normal"}" font-style="${e.isItalic ? "italic" : "normal"}" text-decoration="${e.isUnderline ? "underline" : "none"}" > ${t.join("")} </text> ${H.value && L.value && L.value.id === e.id ? rn(e) : ""} ${nn(e)} </g> `; default: return ""; } } let on = d(() => $t.value.map((e) => { switch (!0) { case e && e.type === "arrow": let t = e.strokeWidth > 3 ? 5 : 10, n = e.strokeWidth > 3 ? 2.5 : 5; return { html: ` <defs> <marker id="${e.id}" markerWidth="${t}" markerHeight="${t}" refX="0" refY="${n}" orient="auto" > <polygon points="0 0,${t} ${n}, 0 ${t}" fill="${e.color}" /> </marker> </defs> ${tn(e)} <g id="${e.id}"> <path style="stroke-linecap: round !important; ${e.isDash ? `stroke-dasharray: ${e.strokeWidth * 3}` : ""}" stroke="${e.color}" id="${e.id}" d="M${e.x},${e.y} ${e.endX},${e.endY}" stroke-width="${e.strokeWidth}" marker-end="url(#${e.id})" /> </g> <g id="${e.id}"> <rect id="${e.id}" x="${e.x - 10}" y="${e.y - 10}" height="20" width="20" fill="rgba(0,0,0,0.3)" style="display:${N.value || M.value ? "initial" : "none"}; rx:1 !important; ry:1 !important;" /> </g> ${nn(e)} </g> `, id: e.id }; case e && e.type === "circle": return { html: ` <g id="${e.id}"> ${tn(e)} <circle id="${e.id}" cx="${e.x}" cy="${e.y}" r="${e.circleRadius ? e.circleRadius : Number.MIN_VALUE}" fill="${e.isFilled ? e.color + e.alpha : "rgba(255,255,255,0.001)"}" stroke="${e.color + e.alpha}" stroke-width="${e.strokeWidth}" style="${e.isDash ? `stroke-dasharray: ${e.strokeWidth * 3}` : ""}" > </circle> </g> ${nn(e)}`, id: e.id }; case e && e.type === "group": return { html: `<g id="${e.id}"> <rect id="${N.value ? "" : e.id}" x="${e.x}" y="${e.y}" fill="transparent" height="${e.rectHeight}" width="${e.rectWidth}" stroke="grey" stroke-width="1" style="rx:1 !important; ry:1 !important; ${e.isDash ? `stroke-dasharray: ${e.strokeWidth * 3}` : ""}; display:${P.value || A.value || O.value && O.value === e.id ? "initial" : "none"};" /> <g id="${e.id}"> ${e.content ? e.content : ""} </g> ${nn(e)} </g> `, id: e.id }; case e && e.type === "rect": return { html: `<g id="${e.id}"> ${tn(e)} <rect id="${N.value ? "" : e.id}" x="${e.x}" y="${e.y}" fill="${e.isFilled ? e.color + e.alpha : "rgba(255,255,255,0.001)"}" height="${e.rectHeight}" width="${e.rectWidth}" stroke="${e.color + e.alpha}" stroke-width="${e.strokeWidth}" style="rx:1 !important; ry:1 !important; ${e.isDash ? `stroke-dasharray: ${e.strokeWidth * 3}` : ""}" /> <rect id="${e.id}" x="${e.x + e.rectWidth}" y="${e.y + e.rectHeight}" height="20" width="20" fill="rgba(0,0,0,0.3)" style="display:${N.value ? "initial" : "none"}; rx:1 !important; ry:1 !important;" /> ${nn(e)} </g> `, id: e.id }; case e && e.type === "line": return { html: ` <g id="${e.id}"> <path id="${e.id}" d="M${e.path ? e.path : ""}" style="stroke:${e.color + e.alpha} !important; fill:none; stroke-width:${e.strokeWidth} !important; stroke-linecap: round !important; stroke-linejoin: round !important;" /> ${nn(e)} </g> `, id: e.id }; case e && e.type === "text": let r = e.textContent.split("‎"), i = []; for (let t = 0; t < r.length; t += 1) i.push(` ${e.isBulletTextMode ? `<tspan x="${e.x - e.fontSize}" y="${e.y + e.fontSize * t}" id="${e.id}" font-size="${e.fontSize / 2}">⬤</tspan>` : ""} <tspan id="${e.id}" x="${e.x}" y="${e.y + e.fontSize * t}"> ${r[t]} </tspan>`); return { html: ` ${tn(e)} ${an(e, i, e.isBulletTextMode)} `, id: e.id }; } })); function Z(e) { if (e == null) return e; try { return typeof structuredClone == "function" ? structuredClone(e) : JSON.parse(JSON.stringify(e)); } catch { return Array.isArray(e) ? e.map((e) => Z(e)) : typeof e == "object" ? Object.fromEntries(Object.entries(e).map(([e, t]) => [e, Z(t)])) : e; } } function sn(e = !1) { if (!T.value || !wt.value) return; E.value.end = { x: R.value.x, y: R.value.y }; let t; B.value.length > 0 && D.value && (t = [...B.value].find((e) => e.id === D.value.id)); let n, r, i; t && (n = t.x - E.value.end.x, r = t.y - E.value.end.y, i = Math.sqrt(n * n + r * r)); let a, o; switch (e ? (a = Math.max(E.value.end.x, t.x), o = Math.min(E.value.end.x, t.x), Math.max(E.value.end.y, t.y), Math.min(E.value.end.y, t.y)) : (a = Math.max(E.value.end.x, E.value.start.x), o = Math.min(E.value.end.x, E.value.start.x), Math.max(E.value.end.y, E.value.start.y), Math.min(E.value.end.y, E.value.start.y)), !0) { case T.value === "arrow": B.value.at(-1).endX = E.value.end.x, B.value.at(-1).endY = E.value.end.y; break; case T.value === "circle": B.value.at(-1).circleRadius = Tt.value ? Z(a - o) + 20 : i + 20; break; case T.value === "line": B.value.at(-1).path += ` ${R.value.x} ${R.value.y} `; break; case ["rect", "group"].includes(T.value): B.value.at(-1).rectWidth = Z(E.value.end.x - B.value.at(-1).x) > 0 ? Z(E.value.end.x - B.value.at(-1).x) : 20, B.value.at(-1).rectHeight = Z(E.value.end.y - B.value.at(-1).y) > 0 ? Z(E.value.end.y - B.value.at(-1).y) : 20; } } function cn() { if (!wt.value) { Jt.value = null; return; } sn(), Jt.value = requestAnimationFrame(cn); } function ln(e) { let t = B.value.findIndex((t) => t.id === e); if (t > -1 && t !== B.value.length - 1) { let [e] = B.value.splice(t, 1); B.value.push(e); } } function un(e) { let t = (e) => !!e && B.value.some((t) => t.id === e); if (t(e?.target?.id)) return e.target.id; let n = en.value?.querySelector(".annotator__glass"); if (!n) return null; let r = n.style.pointerEvents; n.style.pointerEvents = "none"; let i = document.elementFromPoint(e.clientX, e.clientY); return n.style.pointerEvents = r || "all", t(i?.id) ? i.id : null; } function dn(e = {}) { let { maxEntries: t = 200, maxBytes: n = 2e6 } = e, r = { open: !1, before: null, undo: [], redo: [] }, i = { undo: 0, redo: 0 }, a = (e) => typeof e == "string" ? e.length * 2 : 0, o = () => JSON.stringify({ shapes: Z(B.value), lastSelectedShape: Z(L.value) }), s = (e) => { let t = JSON.parse(e); B.value = t.shapes, L.value = t.lastSelectedShape; }, ee = () => { qt.value.undo = r.undo.length, qt.value.redo = r.redo.length; }, c = (e, o) => { let s = r[e]; for (s.push(o), i[e] += a(o); s.length > t || i[e] > n;) { let t = s.shift(); i[e] -= a(t); } }; return { begin() { r.open || (r.open = !0, r.before = o()); }, end() { r.open && (r.open = !1, o() !== r.before && (c("undo", r.before), r.redo.length = 0, i.redo = 0), r.before = null, ee()); }, undo() { let e = r.undo.pop(); if (!e) return; i.undo -= a(e); let t = o(); c("redo", t), s(e), ee(); }, redo() { let e = r.redo.pop(); if (!e) return; i.redo -= a(e); let t = o(); c("undo", t), s(e), ee(); }, size() { return { undo: r.undo.length, redo: r.redo.length, approxBytes: { undo: i.undo, redo: i.redo } }; } }; } function fn() { if (!Wt.value) return; let e = Wt.value.getBoundingClientRect(); K.value = { x: e.left + e.width / 2, y: e.top }; } function Q(e, t, n = "top") { G.value = e, Wt.value = t.currentTarget || t.target, fn(), W.value = !0, window.addEventListener("scroll", fn, !0), window.addEventListener("resize", fn, { passive: !0 }); } function $() { W.value = !1, G.value = null, Wt.value = null, window.removeEventListener("scroll", fn, !0), window.removeEventListener("resize", fn); } function pn(e) { let t = e?.target && e.target.id || D.value && D.value.id, n = B.value.find((e) => e.id === t); if (!n) { Ut.value = null; return; } L.value = n; let r = R.value.x, i = R.value.y; switch (n.type) { case "rect": case "circle": case "text": Ut.value = { dx: r - n.x, dy: i - n.y }; break; case "arrow": Ut.value = { dx: r - n.x, dy: i - n.y, endDx: r - n.endX, endDy: i - n.endY }; break; case "group": Ut.value = { dx: r - (n.x || 0), dy: i - (n.y || 0) }; break; default: Ut.value = { dx: 0, dy: 0 }; } } function mn(e) { let t = B.value.find((e) => e.id === L.value.id); switch (!0) { case e === "front": B.value = B.value.filter((e) => e.id !== t.id), B.value.push(t); break; case e === "back": B.value = B.value.filter((e) => e.id !== t.id), B.value = [t, ...B.value]; break; default: return; } } function hn() { if (!L.value?.id) return; let e = { ...L.value, id: `${L.value.id}_copy_${i()}`, x: L.value.x - 100 < 0 ? 1 : L.value.x - 100, y: L.value.y - 100 < 0 ? 1 : L.value.y - 100 }; B.value.push(e); } function gn(e) { e.preventDefault(), jt.value = !1, e.target && e.target.id && (O.value = e.target.id); } function _n() { !L.value || !L.value.id.includes("text") || L.value.textContent === "" && (B.value = B.value.filter((e) => e.id !== L.value.id), L.value = B.value.at(-1)); } function vn(e) { if (A.value) return; e.preventDefault(), e.stopPropagation(), _n(), F.value ? (I.value = !0, H.value = !0) : (I.value = !1, H.value = !1, F.value = !1); let t = `text_${i()}`; if (I.value) { q.value?.begin(), B.value.push({ id: t, type: "text", lines: 0, x: R.value.x, y: R.value.y, textContent: "", fontSize: Z(Bt.value), textAlign: Z(U.value), isBold: Z(St.value), isItalic: Z(Et.value), isUnderline: Z(At.value), color: Z(Ft.value), isBulletTextMode: Z(k.value) }), D.value = B.value.at(-1), L.value = B.value.at(-1), q.value?.end(); return; } let n = () => { Ct.value = B.value.find((t) => t.id === e.target.id).isDash; }, r = () => { xt.value = B.value.find((t) => t.id === e.target.id).strokeWidth; }; if (P.value = !1, e.target.id.includes("arrow")) { T.value = "arrow", n(), r(); return; } if (e.target.id.includes("circle")) { T.value = "circle", V.value.circle.filled = B.value.find((t) => t.id === e.target.id).isFilled, n(), r(); return; } if (e.target.id.includes("rect")) { T.value = "rect", V.value.rect.filled = B.value.find((t) => t.id === e.target.id).isFilled, n(), r(); return; } if (e.target.id.includes("line")) { T.value = "line", r(); return; } if (e.target.id.includes("text")) { F.value = !0, I.value = !0, H.value = !0; let t = B.value.find((t) => t.id === e.target.id); t && t.textAlign && (U.value = B.value.find((t) => t.id === e.target.id).textAlign), t && (k.value = B.value.find((t) => t.id === e.target.id).isBulletTextMode); return; } } function yn(e) { !L.value || L.value.type !== "text" || (L.value.textAlign = e); } function bn() { q.value?.undo?.(); } function xn() { q.value?.redo?.(); } let Sn = [ 16, 17, 18, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 91, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 221, 255, "Unidentified" ]; function Cn(e) { if (jt.value) return; e.preventDefault(); let t = e.keyCode; if (!I.value) return; H.value = !0; let n; if (n = L.value.type === "text" ? B.value.find((e) => e.id === L.value.id) : B.value.at(-1), D.value = n, n.type === "text") switch (D.value.isBold = Z(St.value), D.value.isItalic = Z(Et.value), D.value.isUnderline = Z(At.value), !0) { case [8, 46].includes(t): n.textContent = n.textContent.slice(0, -1); break; case t === 9: n.textContent += "&nbsp; &nbsp; &nbsp; &nbsp;"; break; case t === 13: n.lines += 1, n.textContent += "‎"; return; case Sn.includes(t): return; default: n.textContent += e.key; } } function wn() { if (z.value = [], T.value !== "group") { P.value = !1, B.value = B.value.filter((e) => e.type !== "group"); return; } let e = B.value.at(-1); if (B.value.forEach((t) => { if (t.type !== "group") switch (!0) { case t.type === "arrow": let n = t.x <= t.endX && t.y <= t.endY && e.x <= t.x && e.y <= t.y && e.x + e.rectWidth >= t.endX && e.y + e.rectHeight >= t.endY, r = t.endY < t.y && t.x < t.endX && e.x <= t.x && e.y <= t.y && e.x + e.rectWidth >= t.endX && e.y + e.rectHeight >= t.y, i = t.x > t.endX && t.y < t.endY && e.x <= t.endX && e.y <= t.endY && e.x + e.rectWidth >= t.x && e.y + e.rectHeight >= t.endY, a = t.x > t.endX && t.y > t.endY && e.x <= t.endX && e.y <= t.endY && e.x + e.rectWidth >= t.x && e.y + e.rectHeight >= t.y; (n || r || i || a) && z.value.push(t); break; case t.type === "circle": e.x <= t.x + t.circleRadius && e.y <= t.y + t.circleRadius && t.x + t.circleRadius <= e.x + e.rectWidth && t.y + t.circleRadius <= e.y + e.rectHeight && z.value.push(t); break; case t.type === "rect": e.x <= t.x && e.y <= t.y && t.x <= e.x + e.rectWidth && t.y <= e.y + e.rectHeight && t.x + t.rectWidth <= e.x + e.rectWidth && t.y + t.rectHeight <= e.y + e.rectHeight && t.rectWidth <= e.rectWidth && t.rectHeight <= e.rectHeight && z.value.push(t); break; case t.type === "text": e.x <= t.x && e.y <= t.y && z.value.push(t); } }), z.value = z.value.map((t) => ({ ...t, id: e.id, oldId: t.id, diffX: t.x - e.x, diffY: t.y - e.y, diffEndX: t.endX ? t.endX - e.x : 0, diffEndY: t.endY ? t.endY - e.y : 0 })), e.source = z.value, z.value.length > 1) { let t = Z(z.value).map((e) => e.oldId); B.value = B.value.filter((e) => !t.includes(e.id)), z.value.forEach((t) => { switch (!0) { case t.type === "circle": e.content += ` <circle id="${t.id}" cx="${t.x}" cy="${t.y}" r="${t.circleRadius ? t.circleRadius : Number.MIN_VALUE}" fill="${t.isFilled ? t.color + t.alpha : "rgba(255,255,255,0.001)"}" stroke="${t.color + t.alpha}" stroke-width="${t.strokeWidth}" style="${t.isDash ? `stroke-dasharray: ${t.strokeWidth * 3}` : ""}" /> `; break; case t.type === "rect": e.content += ` <rect id="${N.value ? "" : t.id}" x="${t.x}" y="${t.y}" fill="${t.isFilled ? t.color + t.alpha : "rgba(255,255,255,0.001)"}" height="${t.rectHeight}" width="${t.rectWidth}" stroke="${t.color + t.alpha}" stroke-width="${t.strokeWidth}" style="rx:1 !important; ry:1 !important; ${t.isDash ? `stroke-dasharray: ${t.strokeWidth * 3}` : ""}" /> `; break; case t.type === "arrow": let n = t.strokeWidth > 3 ? 5 : 10, r = t.strokeWidth > 3 ? 2.5 : 5, a = i(); e.content += ` <g id="${t.id}"> <defs> <marker id="${a}" markerWidth="${n}" markerHeight="${n}" refX="0" refY="${r}" orient="auto" > <polygon points="0 0,${n} ${r}, 0 ${n}" fill="${t.color}" /> </marker> </defs> <path style="stroke-linecap: round !important; ${t.isDash ? `stroke-dasharray: ${t.strokeWidth * 3}` : ""}" stroke="${t.color}" id="${t.id}" d="M${t.x},${t.y} ${t.endX},${t.endY}" stroke-width="${t.strokeWidth}" marker-end="url(#${a})" /> </g> `; break; case t.type === "text": let o = t.textContent.split("‎"), s = []; for (let e = 0; e < o.length; e += 1) s.push(` ${t.isBulletTextMode ? `<tspan x="${t.x - t.fontSize}" y="${t.y + t.fontSize * e}" id="${t.id}" font-size="${t.fontSize / 2}">⬤</tspan>` : ""} <tspan id="${t.id}" x="${t.x}" y="${t.y + t.fontSize * e}"> ${o[e]} </tspan>`); e.content += ` ${an(t, s, t.isBulletTextMode)} `; } }); } else B.value = B.value.filter((t) => t.id !== e.id); } function Tn(e) { e.content = ""; let t = e.x || 0, n = e.y || 0; (e.source || []).forEach((r) => { switch (r.type) { case "circle": { let i = t + r.diffX, a = n + r.diffY; e.content += ` <circle id="${r.id}" cx="${i}" cy="${a}" r="${r.circleRadius ? r.circleRadius : Number.MIN_VALUE}" fill="${r.isFilled ? r.color + r.alpha : "rgba(255,255,255,0.001)"}" stroke="${r.color + r.alpha}" stroke-width="${r.strokeWidth}" style="${r.isDash ? `stroke-dasharray: ${r.strokeWidth * 3}` : ""}" /> `; break; } case "rect": { let i = t + r.diffX, a = n + r.diffY; e.content += ` <rect id="${N.value ? "" : r.id}" x="${i}" y="${a}" fill="${r.isFilled ? r.color + r.alpha : "rgba(255,255,255,0.001)"}" height="${r.rectHeight}" width="${r.rectWidth}" stroke="${r.color + r.alpha}" stroke-width="${r.strokeWidth}" style="rx:1 !important; ry:1 !important; ${r.isDash ? `stroke-dasharray: ${r.strokeWidth * 3}` : ""}" /> `; break; } case "arrow": { let a = t + r.diffX, o = n + r.diffY, s = t + r.diffEndX, ee = n + r.diffEndY, c = r.strokeWidth > 3 ? 5 : 10, l = r.strokeWidth > 3 ? 2.5 : 5, u = `m_${r.id}_${i()}`; e.content += ` <g id="${r.id}"> <defs> <marker id="${u}" markerWidth="${c}" markerHeight="${c}" refX="0" refY="${l}" orient="auto"> <polygon points="0 0,${c} ${l}, 0 ${c}" fill="${r.color}" /> </marker> </defs> <path style="stroke-linecap: round !important; ${r.isDash ? `stroke-dasharray: ${r.strokeWidth * 3}` : ""}" stroke="${r.color}" id="${r.id}" d="M${a},${o} ${s},${ee}" stroke-width="${r.strokeWidth}" marker-end="url(#${u})" /> </g> `; break; } case "text": { let i = (r.textContent || "").split("‎").map((e, i) => ` ${r.isBulletTextMode ? `<tspan x="${t + r.diffX - r.fontSize}" y="${n + r.diffY + r.fontSize * i}" id="${r.id}" font-size="${r.fontSize / 2}">⬤</tspan>` : ""} <tspan id="${r.id}" x="${t + r.diffX}" y="${n + r.diffY + r.fontSize * i}"> ${e} </tspan> `).join(""); e.content += ` <g id="${r.id}"> <text style="user-select:none; height:100px;" id="${r.id}" x="${t + r.diffX}" y="${n + r.diffY}" text-anchor="${r.textAlign}" font-size="${r.fontSize}" fill="${r.color}" font-weight="${r.isBold ? "bold" : "normal"}" font-style="${r.isItalic ? "italic" : "normal"}" text-decoration="${r.isUnderline ? "underline" : "none"}"> ${i} </text> </g> `; break; } } }); } function En(e) { e.relatedTarget && en.value && en.value.contains(e.relatedTarget) || (jt.value = !0, O.value = void 0); } function Dn() { if (wt.value = !0, !T.value && !P.value || !wt.value) return; Tt.value = !0, E.value.start = { x: R.value.x, y: R.value.y }; let e = `${P.value ? "group" : T.value}_${i()}`; switch (!0) { case T.value === "arrow": B.value.push({ id: e, x: R.value.x, y: R.value.y, endX: R.value.x, endY: R.value.y, type: T.value, color: Z(Ft.value), strokeWidth: Z(Math.abs(xt.value)), isDash: Z(Ct.value) }), L.value = B.value.at(-1); break; case T.value === "circle": B.value.push({ alpha: V.value.circle.filled ? Zt.value : "", id: e, color: Z(Ft.value), isFilled: Z(V.value.circle.filled), circleRadius: Z(V.value.circle.radius), circleStrokeWidth: Z(V.value.circle.strokeWidth), type: T.value, x: R.value.x, y: R.value.y, strokeWidth: Z(Math.abs(xt.value)), isDash: Z(Ct.value) }), L.value = B.value.at(-1); break; case T.value === "line": B.value.push({ alpha: Z(Zt.value), id: e, x: R.value.x, y: R.value.y, type: T.value, color: Z(Ft.value), strokeWidth: Z(Math.abs(xt.value)), isDash: Z(Ct.value), path: `${R.value.x} ${R.value.y}` }), L.value = B.value.at(-1); break; case T.value === "rect": B.value.push({ alpha: V.value.rect.filled ? Zt.value : "", id: e, color: Z(Ft.value), isFilled: Z(V.value.rect.filled), rectStrokeWidth: Z(V.value.rect.strokeWidth), rectHeight: Z(V.value.rect.height), rectWidth: Z(V.value.rect.width), type: T.value, x: R.value.x, y: R.value.y, strokeWidth: Z(Math.abs(xt.value)), isDash: Z(Ct.value) }), L.value = B.value.at(-1); break; case T.value === "group": B.value.push({ alpha: 1, id: `group_${i()}`, x: R.value.x, y: R.value.y, isFilled: !1, rectHeight: Z(V.value.rect.height), rectWidth: Z(V.value.rect.width), rectStrokeWidth: 1, type: "group", color: "grey", strokeWidth: 1, isDash: !0, content: "" }); } Jt.value ||= requestAnimationFrame(cn); } function On(e) { if (A.value) { Dt.value = !1; return; } if (e.preventDefault(), e.stopPropagation(), Dt.value = !0, e.pointerId != null) { try { en.value?.setPointerCapture?.(e.pointerId); } catch {} Yt.value = e.pointerId; } else Yt.value = null; if ((j.value || M.value || N.value || P.value) && q.value?.begin?.(), j.value) { Dn(); return; } if (M.value) { let t = un(e) || O.value || L.value?.id; t && (ln(t), D.value = { id: t }), pn(e); } } function kn(e) { if (!e || !e.id || e.type === "line" || !Ut.value && (pn({ target: { id: e.id } }), !Ut.value)) return; let { dx: t, dy: n, endDx: r, endDy: i } = Ut.value, a = R.value.x, o = R.value.y; switch (L.value = e, e.type) { case "arrow": e.x = a - t, e.y = o - n, e.endX = a - (r ?? t), e.endY = o - (i ?? n); break; case "circle": e.x = a - t, e.y = o - n; break; case "rect": e.x = a - t, e.y = o - n; break; case "text": e.x = a - t, e.y = o - n; break; case "group": e.x = a - t, e.y = o - n, Tn(e); } } function An() { let e = D.value?.id || O.value; if (!e) return; let t = B.value.find((t) => t.id === e); t && kn(t); } function jn() { Tt.value = !1; let e = D.value.id; if (!e) return; wt.value = !0; let t = B.value.find((t) => t.id === e); T.value = t.type, B.value = B.value.filter((t) => t.id !== e), B.value.push(t), sn(!0); } function Mn(e) { A.value || (e.preventDefault(), e.stopPropagation(), e.target.localName !== "svg" && (D.value = e.target), M.value && Dt.value ? An() : N.value && Dt.value && jn()); } function Nn(e) { let t = e.target.id; switch (!0) { case A.value: q.value?.begin(), B.value = [...B.value].filter((e) => e.id !== t), L.value = void 0, q.value?.end(); return; default: L.value = B.value.find((e) => e.id === t); } } let Pn = x(null); function Fn(e, t) { for (t(e), e = e.firstChild; e;) Fn(e, t), e = e.nextSibling; } function In() { Ot.value = !0, A.value = !1, M.value = !1, N.value = !1, F.value = !1, I.value = !1, P.value = !1, T.value = void 0, H.value = !1, ae(async () => { let e = Pn.value; if (e) { Fn(e, (e) => { e && e.nodeType === 1 && (e.setAttribute("font-family", "Helvetica"), e.style.fontFamily = "Helvetica"); }); try { let t; try { t = (await import("jspdf")).default; } catch { throw Error("jspdf is not installed. Run npm install jspdf"); } let n = await c({ container: e, scale: 2 }), r = new Image(); r.src = n, r.onload = () => { let e = { width: 595.28, height: 841.89 }, i = r.width, a = r.height, o = i / e.width * e.height, s = e.width, ee = s / i * a, c = new t("", "pt", "a4"), l = 0, u = a; if (u < o) c.addImage(n, "PNG", 0, 0, s, ee, "", "FAST"); else for (; u > 0;) c.addImage(n, "PNG", 0, l, s, ee, "", "FAST"), u -= o, l -= e.height, u > 0 && c.addPage(); c.save(`${(/* @__PURE__ */ new Date()).toLocaleDateString()}_annotations.pdf`); }; } catch (e) { console.error("Error generating image:", e); } finally { Ot.value = !1, Fn(e, (e) => { e && e.nodeType === 1 && (e.setAttribute("font-family", J.value.style.fontFamily), e.style.fontFamily = J.value.style.fontFamily); }); } } }); } function Ln(e) { if (!A.value && e && (e.preventDefault(), e.stopPropagation()), wt.value = !1, Dt.value = !1, Ut.value = null, Yt.value != null) { try { en.value?.releasePointerCapture?.(Yt.value); } catch {} Yt.value = null; } Jt.value &&= (cancelAnimationFrame(Jt.value), null), P.value && wn(), q.value?.end(); } function Rn() { !L.value || !L.value.id.includes("rect") || (L.value.isFilled = !L.value.isFilled); } function zn() { !L.value || !L.value.id.includes("circle") || (L.value.isFilled = !L.value.isFilled); } function Bn() { !L.value || L.value.type === "text" || (L.value.isDash = Z(Ct.value)); } function Vn() { !L.value || ["arrow", "text"].includes(L.value.id) || (L.value.alpha = Z(Zt.value)); } function Hn() { !L.value || ![ "arrow", "circle", "rect", "line" ].includes(L.value.type) || (L.value.strokeWidth = Z(Math.abs(xt.value))); } function Un() { !L.value || L.value.type !== "text" || (L.value.isBold = Z(St.value), L.value.isItalic = Z(Et.value), L.value.isUnderline = Z(At.value), L.value.fontSize = Z(Bt.value), L.value.isBulletTextMode = Z(k.value)); } function Wn(e) { if (e.preventDefault(), !en.value) return; let t = en.value.getBoundingClientRect(), n, r; e.touches && e.touches.length > 0 ? (n = e.touches[0].clientX, r = e.touches[0].clientY) : (n = e.clientX, r = e.clientY), R.value.x = (n - t.left) / t.width * Pt.value, R.value.y = (r - t.top) / t.height * Nt.value; } function Gn(e) { if (H.value = !1, _n(), e === T.value) { T.value = void 0, j.value = !1; return; } j.value = !0, A.value = !1, M.value = !1, N.value = !1, F.value = !1, T.value = e; } function Kn() { kt.value = !kt.value, kt.value || (M.value = !1, N.value = !1, F.value = !1, I.value = !1, T.value = void 0, H.value = !1, A.value = !1, I.value = !1), _e("toggleOpenState", { isOpen: kt.value }); } function qn() { _e("saveAnnotations", { shapes: B.value, lastSelectedShape: L.value }); } let Jn = null; return se(() => { if (Pn.value) { let e = !1; Fn(Pn.value, (t) => { if (!e && [ "DIV", "svg", "section", "canvas" ].includes(t.tagName)) { Lt.value = t, e = !0; return; } }); } Gt.value = (() => { if (typeof navigator > "u") return !1; let e = navigator.userAgentData?.platform ?? ""; if (e) return /mac|ios/i.test(e); let t = navigator.userAgent ?? ""; return /(Mac|iPhone|iPad|iPod)/i.test(t); })(); let e = Lt?.value.getBoundingClientRect(); if (It.value = e.height / e.widt