document-scanner-vue
Version:
Vue 3 Document Scanner with OpenCV.js - Mobile optimized with camera/gallery support
1,146 lines • 132 kB
JavaScript
var Ze = Object.defineProperty;
var Ke = (a, e, t) => e in a ? Ze(a, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[e] = t;
var Le = (a, e, t) => Ke(a, typeof e != "symbol" ? e + "" : e, t);
import { ref as A, readonly as ue, computed as X, watch as we, defineComponent as ge, createElementBlock as Y, openBlock as V, createElementVNode as b, toDisplayString as de, h as Oe, normalizeClass as ke, createVNode as Z, unref as O, onMounted as Me, onUnmounted as Re, createCommentVNode as fe, normalizeStyle as _e, nextTick as Te, renderSlot as Qe, Fragment as He, useCssVars as et, reactive as tt, watchEffect as nt, renderList as at, withModifiers as ot, provide as rt, createBlock as xe, Teleport as st, inject as it, getCurrentInstance as lt, onErrorCaptured as ct, toRef as ut } from "vue";
import { onKeyStroke as Ae } from "@vueuse/core";
import dt from "jspdf";
function gt(a) {
if (!cv || !cv.imread)
throw console.error("OpenCV (cv.imread) is not available."), new Error("OpenCV (cv.imread) is not available.");
return cv.imread(a);
}
function mt(a) {
if (!cv || !cv.imshow)
throw console.error("OpenCV (cv.imshow) is not available."), new Error("OpenCV (cv.imshow) is not available.");
const e = document.createElement("canvas");
return cv.imshow(e, a), e.toDataURL("image/jpeg");
}
function pt(a, e, t, o, r) {
let n = 0;
const l = e / o;
n += l * 1e6;
const g = [0.707, 1, 1.414];
let u = 0;
for (const P of g) {
const R = Math.abs(t - P);
R < 0.3 && (u = Math.max(u, (0.3 - R) * 1e5));
}
n += u, r && (n += 5e4), l > 0.1 && (n += 1e5), l > 0.2 && (n += 2e5), (t < 0.05 || t > 20) && (n -= 15e4);
const d = cv.boundingRect(a), w = Math.min(d.width, d.height), y = Math.max(d.width, d.height);
return w > 10 && y > 20 && (n += 25e3), w > 50 && y > 100 && (n += 5e4), w > 100 && y > 200 && (n += 75e3), e > 10 && (n += 1e4), n;
}
async function De(a) {
if (!cv || !cv.Mat || !cv.cvtColor || !cv.GaussianBlur || !cv.Canny || !cv.findContours || !cv.arcLength || !cv.approxPolyDP || !cv.contourArea)
return console.error("A required OpenCV function is not available in detectDocumentCorners."), null;
let e = null, t = null, o = null, r = null, n = null;
try {
const l = new Image();
l.src = a, await new Promise((v, m) => {
l.onload = () => v(), l.onerror = (L) => m(new Error("Image load failed in detectDocumentCorners"));
}), e = cv.imread(l);
const g = e.cols, u = e.rows, d = g * u;
console.log(`[DEBUG] Original image dimensions: ${g}x${u}, Total area: ${d}`);
let w = e, y = 1;
const P = 1200, R = Math.max(g, u);
if (R > P) {
y = P / R;
const v = Math.round(g * y), m = Math.round(u * y);
t = new cv.Mat();
const L = new cv.Size(v, m);
cv.resize(e, t, L, 0, 0, cv.INTER_AREA), w = t, console.log(`[DEBUG] Downsampled to: ${v}x${m} (factor: ${y.toFixed(3)}) for processing`);
} else
console.log("[DEBUG] No downsampling needed, processing at original size");
o = new cv.Mat(), cv.cvtColor(w, o, cv.COLOR_RGBA2GRAY, 0), r = new cv.Mat(), cv.GaussianBlur(o, r, new cv.Size(5, 5), 0, 0, cv.BORDER_DEFAULT);
const T = w.cols * w.rows;
console.log(`[DEBUG] Processing dimensions: ${w.cols}x${w.rows}, Processing area: ${T}`);
const U = d > 8e6, S = d > 2e6;
console.log(`[DEBUG] Image classification: ${U ? "High-res (likely mobile camera)" : S ? "Medium-res" : "Low-res (likely compressed)"}`);
const i = (v) => U ? v * 0.1 : S ? v * 0.5 : v, s = (v, m) => U ? {
low: Math.max(1, Math.round(v * 0.6)),
// 40% lower
high: Math.max(5, Math.round(m * 0.7))
// 30% lower
} : S ? {
low: Math.max(1, Math.round(v * 0.8)),
// 20% lower
high: Math.max(5, Math.round(m * 0.9))
// 10% lower
} : { low: v, high: m }, c = [
{
name: "Standard",
cannyLow: s(50, 150).low,
cannyHigh: s(50, 150).high,
areaThreshold: i(0.05),
// 5% -> adaptive
minAspectRatio: 0.5,
maxAspectRatio: 2,
approxEpsilon: 0.015
},
{
name: "Relaxed",
cannyLow: s(30, 100).low,
cannyHigh: s(30, 100).high,
areaThreshold: i(0.03),
// 3% -> adaptive
minAspectRatio: 0.3,
maxAspectRatio: 3,
approxEpsilon: 0.02
},
{
name: "VeryRelaxed",
cannyLow: s(75, 200).low,
cannyHigh: s(75, 200).high,
areaThreshold: i(0.01),
// 1% -> adaptive
minAspectRatio: 0.2,
maxAspectRatio: 4,
approxEpsilon: 0.025
},
{
name: "Aggressive",
cannyLow: s(20, 80).low,
cannyHigh: s(20, 80).high,
areaThreshold: i(5e-3),
// 0.5% -> adaptive
minAspectRatio: 0.1,
maxAspectRatio: 5,
approxEpsilon: 0.03
},
{
name: "DocumentFocused",
cannyLow: s(40, 120).low,
cannyHigh: s(40, 120).high,
areaThreshold: i(0.15),
// 15% -> adaptive
minAspectRatio: 0.4,
maxAspectRatio: 2.5,
approxEpsilon: 0.02,
useDocumentHeuristics: !0,
// Enable document-specific scoring
usePreprocessing: !0
},
{
name: "Enhanced",
cannyLow: s(25, 75).low,
cannyHigh: s(25, 75).high,
areaThreshold: i(0.08),
// 8% -> adaptive
minAspectRatio: 0.3,
maxAspectRatio: 3,
approxEpsilon: 0.025,
useDocumentHeuristics: !0,
usePreprocessing: !0
}
];
for (const v of c) {
const m = T * v.areaThreshold;
console.log(`[DEBUG] Trying ${v.name} strategy... (adaptive threshold: ${(v.areaThreshold * 100).toFixed(4)}%, min area: ${m.toFixed(0)} pixels)`);
let L = null, H = null, W = null;
try {
L = new cv.Mat();
let q = r;
if (v.usePreprocessing) {
console.log(`[DEBUG] ${v.name}: Applying preprocessing (CLAHE contrast enhancement)`), q = new cv.Mat();
const $ = new cv.CLAHE(2, new cv.Size(8, 8));
$.apply(r, q), $.delete();
}
if (cv.Canny(q, L, v.cannyLow, v.cannyHigh), H = new cv.MatVector(), W = new cv.Mat(), cv.findContours(L, H, W, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE), console.log(`[DEBUG] ${v.name}: Found ${H.size()} initial contours.`), H.size() === 0) {
v.usePreprocessing && q !== r && q.delete();
continue;
}
let C = 0, E = {
notFourSided: 0,
notConvex: 0,
tooSmall: 0,
badAspectRatio: 0,
passed: 0
}, x = null, N = -1;
for (let $ = 0; $ < H.size(); ++$) {
const ee = H.get($), J = cv.arcLength(ee, !0), _ = new cv.Mat();
if (cv.approxPolyDP(ee, _, v.approxEpsilon * J, !0), _.rows !== 4) {
E.notFourSided++, _.delete();
continue;
}
C++;
const K = cv.isContourConvex(_), Q = cv.contourArea(_), ne = cv.boundingRect(_), ae = ne.width / ne.height;
if (!K) {
E.notConvex++, C <= 10 && console.log(`[DEBUG] ${v.name} Contour ${$} (4-sided): REJECTED - Not convex. Area=${Q.toFixed(0)}, AR=${ae.toFixed(2)}`), _.delete();
continue;
}
if (Q < m) {
E.tooSmall++, C <= 10 && console.log(`[DEBUG] ${v.name} Contour ${$} (4-sided): REJECTED - Too small. Area=${Q.toFixed(0)} < ${m.toFixed(0)}, AR=${ae.toFixed(2)}`), _.delete();
continue;
}
if (ae < v.minAspectRatio || ae > v.maxAspectRatio) {
E.badAspectRatio++, C <= 10 && console.log(`[DEBUG] ${v.name} Contour ${$} (4-sided): REJECTED - Bad aspect ratio. Area=${Q.toFixed(0)}, AR=${ae.toFixed(2)} (Range: ${v.minAspectRatio}-${v.maxAspectRatio})`), _.delete();
continue;
}
let ce = Q;
v.useDocumentHeuristics && (ce = pt(_, Q, ae, T, K)), E.passed++;
const ye = K ? "CONVEX" : "NON-CONVEX", ve = v.useDocumentHeuristics ? `, Score=${ce.toFixed(0)}` : "";
console.log(`[DEBUG] ${v.name} Contour ${$} (4-sided): PASSED ALL FILTERS. Area=${Q.toFixed(0)}, AR=${ae.toFixed(2)}, W=${ne.width}, H=${ne.height}, ${ye}${ve}`), ce > N && (console.log(`[DEBUG] ${v.name} NEW BEST CONTOUR FOUND (Contour ${$}): Area=${Q.toFixed(0)}, AR=${ae.toFixed(2)}, W=${ne.width}, H=${ne.height}, ${ye}${ve}`), N = ce, x && x.delete(), x = _.clone()), _.delete();
}
if (console.log(`[DEBUG] ${v.name} Summary: 4-sided candidates=${C}, Rejections: notConvex=${E.notConvex}, tooSmall=${E.tooSmall}, badAR=${E.badAspectRatio}, passed=${E.passed}`), v.usePreprocessing && q !== r && q.delete(), x) {
console.log(`[DEBUG] ${v.name} strategy SUCCESS! Found suitable contour with score ${N.toFixed(0)}.`), n && n.delete(), n = x;
break;
} else
console.log(`[DEBUG] ${v.name} strategy failed, trying next...`);
} finally {
L && L.delete(), H && H.delete(), W && W.delete();
}
}
if (!n)
return console.log("[DEBUG] All strategies failed - no suitable 4-point contour found."), null;
const p = [];
for (let v = 0; v < n.rows; ++v) {
const m = n.data32S[v * 2], L = n.data32S[v * 2 + 1], H = y < 1 ? Math.round(m / y) : m, W = y < 1 ? Math.round(L / y) : L;
p.push({ x: H, y: W });
}
console.log(`[DEBUG] Scaling coordinates back to original size (factor: ${(1 / y).toFixed(3)})`), p.sort((v, m) => v.y - m.y);
const f = p.slice(0, 2).sort((v, m) => v.x - m.x), M = p.slice(2, 4).sort((v, m) => v.x - m.x);
return [f[0], f[1], M[1], M[0]];
} catch (l) {
return console.error("Error in detectDocumentCorners:", l), null;
} finally {
e && e.delete(), t && t.delete(), o && o.delete(), r && r.delete(), n && n.delete();
}
}
async function Xe(a, e, t) {
return new Promise((o, r) => {
const n = new Image();
n.onload = () => {
try {
console.log("[cvUtils] Image loaded for perspective transform. Input corners:", e, "Options:", t);
const [l, g, u, d] = e, w = Math.sqrt((g.x - l.x) ** 2 + (g.y - l.y) ** 2), y = Math.sqrt((u.x - d.x) ** 2 + (u.y - d.y) ** 2);
let P = Math.max(Math.floor(w), Math.floor(y));
const R = Math.sqrt((d.x - l.x) ** 2 + (d.y - l.y) ** 2), T = Math.sqrt((u.x - g.x) ** 2 + (u.y - g.y) ** 2);
let U = Math.max(Math.floor(R), Math.floor(T)), S = t != null && t.outputWidth && t.outputWidth > 0 ? t.outputWidth : P, i = t != null && t.outputHeight && t.outputHeight > 0 ? t.outputHeight : U;
if ((S <= 0 || i <= 0) && (console.warn("[cvUtils] Calculated or provided output dimensions are invalid, falling back to detected max dimensions."), S = P, i = U, S <= 0 || i <= 0)) {
console.error("[cvUtils] Fallback dimensions also invalid. Cannot process."), r(new Error("Invalid output dimensions for perspective transform."));
return;
}
console.log(`[cvUtils] Effective output dimensions for transform: ${S}x${i}`);
const s = cv.matFromArray(4, 1, cv.CV_32FC2, [
l.x,
l.y,
g.x,
g.y,
u.x,
u.y,
d.x,
d.y
]), c = cv.matFromArray(4, 1, cv.CV_32FC2, [
0,
0,
// Top-left
S - 1,
0,
// Top-right
S - 1,
i - 1,
// Bottom-right
0,
i - 1
// Bottom-left
]), p = cv.getPerspectiveTransform(s, c), f = cv.imread(n), M = new cv.Mat(), D = new cv.Size(S, i);
cv.warpPerspective(f, M, p, D, cv.INTER_LINEAR, cv.BORDER_CONSTANT, new cv.Scalar());
const v = document.createElement("canvas");
cv.imshow(v, M);
const m = v.toDataURL("image/jpeg");
f.delete(), M.delete(), p.delete(), s.delete(), c.delete(), o({
imageDataURL: m,
processedWidth: S,
processedHeight: i
});
} catch (l) {
console.error("[cvUtils] Error in applyPerspectiveTransform:", l), r(l);
}
}, n.onerror = (l) => {
console.error("[cvUtils] Failed to load image for perspective transform:", l), r(new Error("Image failed to load for processing."));
}, n.src = a;
});
}
async function ft(a, e) {
return !cv || !cv.rotate ? (console.error("OpenCV rotation functions not available"), a) : new Promise((t, o) => {
const r = new Image();
r.onload = () => {
let n = null, l = null;
try {
switch (n = gt(r), l = new cv.Mat(), (e % 360 + 360) % 360) {
case 0:
n.copyTo(l);
break;
case 90:
cv.rotate(n, l, cv.ROTATE_90_CLOCKWISE);
break;
case 180:
cv.rotate(n, l, cv.ROTATE_180);
break;
case 270:
cv.rotate(n, l, cv.ROTATE_90_COUNTERCLOCKWISE);
break;
default:
console.warn(`Unsupported rotation angle ${e}. Returning original image.`), n.copyTo(l);
break;
}
const u = mt(l);
t(u);
} catch (g) {
console.error("Error rotating image:", g), o(g);
} finally {
n && n.delete(), l && l.delete();
}
}, r.onerror = () => {
o(new Error("Failed to load image for rotation"));
}, r.src = a;
});
}
function vt(a) {
if (!a || a.length !== 4)
return console.warn("sortCornersForConsistentOrientation: Invalid corners provided."), a;
const e = [...a], t = e.reduce(
(u, d) => d.x + d.y < u.x + u.y ? d : u
), o = e.reduce(
(u, d) => d.x + d.y > u.x + u.y ? d : u
), r = e.filter(
(u) => u !== t && u !== o
), n = r[0].y < r[1].y ? r[0] : r[0].y > r[1].y ? r[1] : r[0].x > r[1].x ? r[0] : r[1], l = r.find((u) => u !== n), g = [t, n, o, l];
return console.log("[IP] Sorted corners for consistent orientation:", {
original: a,
sorted: g
}), g;
}
function Ee(a, e, t, o) {
if (!a || a.length !== 4)
return console.warn("transformCornersForRotation: Invalid corners provided."), null;
const r = (e % 360 + 360) % 360, n = a.map((l) => {
switch (r) {
case 0:
return { x: l.x, y: l.y };
case 90:
return { x: o - l.y, y: l.x };
case 180:
return { x: t - l.x, y: o - l.y };
case 270:
return { x: l.y, y: t - l.x };
default:
return console.warn(`transformCornersForRotation: Unsupported rotation angle ${e}`), { x: l.x, y: l.y };
}
});
return n.length === 4 ? [n[0], n[1], n[2], n[3]] : (console.error("transformCornersForRotation: Failed to produce 4 rotated coordinates."), null);
}
function fa(a, e, t, o) {
if (!a || a.length !== 4)
return console.warn("transformDisplayCornersToBase: Invalid displayCorners provided."), null;
const r = (e % 360 + 360) % 360;
let n, l;
r === 90 || r === 270 ? (n = o, l = t) : (n = t, l = o);
const g = a.map((u) => {
switch (r) {
case 0:
return { x: u.x, y: u.y };
case 90:
return { x: u.y, y: n - u.x };
case 180:
return { x: n - u.x, y: l - u.y };
case 270:
return { x: l - u.y, y: u.x };
default:
return console.warn(`transformDisplayCornersToBase: Unsupported rotation angle ${e}`), { x: u.x, y: u.y };
}
});
return g.length === 4 ? [g[0], g[1], g[2], g[3]] : (console.error("transformDisplayCornersToBase: Failed to produce 4 base coordinates."), null);
}
function ht(a) {
if (!a || a.length !== 4)
return 0;
const e = a;
return 0.5 * Math.abs(
e[0].x * e[1].y + e[1].x * e[2].y + e[2].x * e[3].y + e[3].x * e[0].y - (e[1].x * e[0].y + e[2].x * e[1].y + e[3].x * e[2].y + e[0].x * e[3].y)
);
}
function $e(a, e, t) {
return [
{ x: t, y: t },
{ x: a - t, y: t },
{ x: a - t, y: e - t },
{ x: t, y: e - t }
];
}
console.log("[UIP] opencvUtils imported:", typeof De, typeof Xe);
const va = [
{ name: "A4 Portrait", ratio: 1 / Math.sqrt(2) },
// ~0.7071
{ name: "A4 Landscape", ratio: Math.sqrt(2) },
// ~1.4142
{ name: "Letter Portrait", ratio: 8.5 / 11 },
// ~0.7727
{ name: "Letter Landscape", ratio: 11 / 8.5 },
// ~1.2941
{ name: "Legal Portrait", ratio: 8.5 / 14 },
// ~0.6071
{ name: "Legal Landscape", ratio: 14 / 8.5 },
// ~1.6471
{ name: "Square", ratio: 1 },
{ name: "ID Card/Credit Card", ratio: 85.6 / 53.98 },
// ~1.5857 (ISO/IEC 7810 ID-1)
{ name: "Business Card (US)", ratio: 3.5 / 2 },
// 1.75
{ name: "Business Card (EU)", ratio: 85 / 55 }
// ~1.545
];
const yt = !1;
function Ye(a) {
const e = A(null), t = A(null), o = A(0), r = A(!1), n = ue(e), l = ue(t), g = ue(o), u = ue(r);
async function d(i) {
if (!a.value || !i)
return console.warn("[ImgProc] OpenCV not ready or no image data URL for edge detection."), null;
r.value = !0;
try {
const s = await De(i);
return s && s.length === 4 ? (e.value = Object.freeze(s), t.value = Object.freeze(s), e.value) : (console.warn("[ImgProc] Edge detection did not return 4 corners."), e.value = null, t.value = null, null);
} catch (s) {
return console.error("[ImgProc] Error during edge detection:", s), e.value = null, t.value = null, null;
} finally {
r.value = !1;
}
}
async function w(i, s, c) {
if (!a.value || !i || !s || s.length !== 4)
return console.warn("[ImgProc] Prerequisites for perspective transform not met."), null;
r.value = !0;
try {
const p = vt([...s]);
let f, M;
if (!yt) {
if (c) {
const [v, m, L, H] = p, W = (J, _) => Math.sqrt((J.x - _.x) ** 2 + (J.y - _.y) ** 2), q = W(v, m), C = W(H, L), E = Math.max(Math.floor(q), Math.floor(C)), x = W(v, H), N = W(m, L), $ = Math.max(Math.floor(x), Math.floor(N)), ee = Math.max(E, $);
c.ratio < 1 ? (M = ee, f = Math.round(M * c.ratio)) : (f = ee, M = Math.round(f / c.ratio)), console.log(`[ImgProc] Using selected format: ${c.name}. Target output: ${f}x${M}`);
}
}
const D = await Xe(
i,
p,
{ outputWidth: f, outputHeight: M }
// Pass our calculated target dimensions
);
return D && D.imageDataURL ? D : null;
} catch (p) {
return console.error("[ImgProc] Error during perspective transform:", p), null;
} finally {
r.value = !1;
}
}
function y(i) {
i && i.length === 4 ? t.value = Object.freeze([...i]) : i === null ? t.value = null : console.warn("[ImgProc] Attempted to set invalid adjusted corners.");
}
function P() {
console.log("[ImgProc] resetActiveImageState called"), e.value = null, t.value = null, o.value = 0, r.value = !1;
}
function R(i) {
o.value = (i % 360 + 360) % 360;
}
function T(i) {
i ? (console.log("[ImgProc] Syncing state from page:", i.id), e.value = i.corners ? Object.freeze([...i.corners]) : null, t.value = i.corners ? Object.freeze([...i.corners]) : null, o.value = i.currentRotation) : (console.log("[ImgProc] No page to sync from, resetting active image state."), P());
}
async function U(i, s) {
if (!a.value || !i)
return console.warn("[ImgProc] OpenCV not ready or no image data URL for rotation."), i;
try {
return r.value = !0, await ft(i, s);
} catch (c) {
return console.error("[ImgProc] Error during image rotation:", c), i;
} finally {
r.value = !1;
}
}
function S(i, s, c, p) {
if (!i || i.length !== 4)
return null;
const f = Ee(
[...i],
// Convert ReadonlyArray to regular array
s,
c,
p
);
return Object.freeze(f);
}
return {
detectedCorners: n,
adjustedCorners: l,
currentRotation: g,
isProcessing: u,
detectEdges: d,
performPerspectiveTransform: w,
setAdjustedCorners: y,
resetActiveImageState: P,
setRotation: R,
syncStateFromPage: T,
rotateImageData: U,
transformCornersForRotationIncrement: S
};
}
function Pt(a) {
return !a || a.length !== 4 ? (console.warn("[calculateOriginalAspectRatio] Requires 4 corner points."), null) : wt(a);
}
function wt(a) {
const [e, t, o, r] = a, n = (P, R) => Math.sqrt(Math.pow(R.x - P.x, 2) + Math.pow(R.y - P.y, 2)), l = n(e, t), g = n(r, o), u = Math.max(l, g), d = n(e, r), w = n(t, o), y = Math.max(d, w);
return y === 0 ? (console.warn("[calculateSimpleAspectRatio] Calculated effective height is zero."), 1) : u / y;
}
const Rt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
calculateOriginalAspectRatio: Pt,
useImageProcessing: Ye
}, Symbol.toStringTag, { value: "Module" }));
let Ue = (a = 21) => crypto.getRandomValues(new Uint8Array(a)).reduce((e, t) => (t &= 63, t < 36 ? e += t.toString(36) : t < 62 ? e += (t - 26).toString(36).toUpperCase() : t > 62 ? e += "-" : e += "_", e), "");
function se(a) {
a && a.startsWith("blob:") ? URL.revokeObjectURL(a) : console.warn("Attempted to revoke a non-blob URL or an empty URL:", a);
}
function It() {
const a = A([]), e = A(null), t = X(() => e.value && a.value.find((i) => i.id === e.value) || null), o = (i) => a.value.find((s) => s.id === i), r = X(() => ue(a.value)), n = X(() => {
const i = e.value ? a.value.findIndex((p) => p.id === e.value) : -1, s = i !== -1 ? i + 1 : a.value.length > 0 ? 1 : 0, c = a.value.length;
return `${s}/${c}`;
}), l = X(() => a.value.length), g = async (i, s) => {
let c = null;
if (typeof window < "u" && !window.cv)
throw new Error("OpenCV is not loaded yet. Please wait for the scanner to initialize.");
try {
s("Loading image...", 0), c = URL.createObjectURL(i);
const p = new Image();
return await new Promise(async (M, D) => {
p.onload = async () => {
try {
console.log(`[usePageManager] Image loaded successfully for ${i.name}, dimensions: ${p.naturalWidth}x${p.naturalHeight}`), s("Analyzing document...", 20), console.log(`[usePageManager] Starting corner detection for ${i.name}...`);
const v = await De(c);
console.log(`[usePageManager] Corner detection completed for ${i.name}, found:`, (v == null ? void 0 : v.length) || 0, "corners"), s("Processing corners...", 40);
let m;
v && v.length === 4 ? m = [
v[0],
v[1],
v[2],
v[3]
] : (console.warn(`[usePageManager] Corners not detected or invalid for ${i.name}, using fallback.`), m = $e(p.naturalWidth, p.naturalHeight, 32)), s("Auto-processing document...", 60);
const L = Ue(), H = {
id: L,
originalFile: i,
originalFileName: i.name,
originalImageDataURL: c,
originalWidth: p.naturalWidth,
originalHeight: p.naturalHeight,
corners: m,
currentRotation: 0,
processedImageDataURL: null,
processedWidth: null,
processedHeight: null,
timestampProcessed: null,
mode: "preview",
// Start in preview mode since we'll auto-process
timestampAdded: Date.now(),
// Add default output format
outputFormat: {
name: "Letter Portrait",
ratio: 8.5 / 11,
dimensions: '8.5" × 11"',
category: "standard"
}
};
a.value.push(H);
try {
s("Processing document...", 80);
const { useImageProcessing: W } = await Promise.resolve().then(() => Rt), { ref: q } = await import("vue"), C = q(!0), { performPerspectiveTransform: E } = W(C), x = await E(
c,
m,
H.outputFormat
// Pass the paper format for proper sizing
);
if (x && x.imageDataURL) {
const N = a.value.findIndex(($) => $.id === L);
N !== -1 && (a.value[N] = {
...a.value[N],
processedImageDataURL: x.imageDataURL,
processedWidth: x.processedWidth,
processedHeight: x.processedHeight,
timestampProcessed: Date.now(),
mode: "preview"
}), console.log(`[usePageManager] Auto-processed page ${L} successfully`);
} else {
console.warn(`[usePageManager] Auto-processing failed for ${L}, keeping in edit mode`);
const N = a.value.findIndex(($) => $.id === L);
N !== -1 && (a.value[N] = {
...a.value[N],
mode: "edit"
});
}
} catch (W) {
console.warn(`[usePageManager] Auto-processing error for ${L}:`, W);
const q = a.value.findIndex((C) => C.id === L);
q !== -1 && (a.value[q] = {
...a.value[q],
mode: "edit"
});
}
s("Complete!", 100), M(L);
} catch (v) {
console.error(`[usePageManager] Error processing image ${i.name} after load:`, v), c && se(c), D(v);
}
}, p.onerror = (v) => {
console.error(`[usePageManager] Error loading image ${i.name} (img.onerror):`, v), c && se(c), D(new Error(`Failed to load image: ${i.name}`));
}, c ? p.src = c : D(new Error("Failed to create object URL for image"));
});
} catch (p) {
throw console.error(`[usePageManager] Failed to process file ${i.name} into a Page object:`, p), c && se(c), p;
}
}, u = async (i) => {
const s = [];
for (const c of i) {
let p = null;
try {
p = URL.createObjectURL(c);
const f = new Image(), M = new Promise(async (D, v) => {
f.onload = async () => {
try {
const m = await De(p);
let L;
m && m.length === 4 ? L = [
m[0],
m[1],
m[2],
m[3]
] : (console.warn(`[usePageManager] Corners not detected or invalid for ${c.name}, using fallback.`), L = $e(f.naturalWidth, f.naturalHeight, 32));
const H = {
id: Ue(),
originalFile: c,
originalFileName: c.name,
originalImageDataURL: p,
originalWidth: f.naturalWidth,
originalHeight: f.naturalHeight,
corners: L,
currentRotation: 0,
processedImageDataURL: null,
processedWidth: null,
processedHeight: null,
timestampProcessed: null,
mode: "edit",
timestampAdded: Date.now(),
// Add default output format
outputFormat: {
name: "Letter Portrait",
ratio: 8.5 / 11,
dimensions: '8.5" × 11"',
category: "standard"
}
};
a.value.push(H), s.push(H.id), D();
} catch (m) {
console.error(`[usePageManager] Error processing image ${c.name} after load:`, m), p && se(p), v(m);
}
}, f.onerror = (m) => {
console.error(`[usePageManager] Error loading image ${c.name} (img.onerror):`, m), p && se(p), v(new Error(`Failed to load image: ${c.name}`));
};
});
f.src = p, await M;
} catch (f) {
throw console.error(`[usePageManager] Failed to process file ${c.name} into a Page object:`, f), p && se(p), f;
}
}
return s.length > 0 && !e.value ? d(s[0]) : s.length > 0 && e.value, s;
}, d = (i) => {
if (console.log("[usePageManager] Selecting page:", i), i === null) {
e.value = null;
return;
}
a.value.some((c) => c.id === i) ? e.value = i : (console.warn(`[usePageManager] Attempted to select non-existent page: ${i}`), a.value.length > 0 ? e.value = a.value[0].id : e.value = null);
}, w = (i, s) => {
const c = a.value.findIndex((p) => p.id === i);
if (c !== -1) {
const p = a.value[c];
let f = { ...p }, M = !1;
const D = p.corners ? [...p.corners] : null;
if (s.currentRotation !== void 0 && s.currentRotation !== f.currentRotation)
if (console.log(`[usePageManager] Updating rotation from ${f.currentRotation} to ${s.currentRotation} for page ${i}`), f.currentRotation = s.currentRotation, M = !0, D) {
const v = Ee(
D,
// Corners relative to the *old* rotation
f.currentRotation,
// The new target rotation
f.originalWidth,
f.originalHeight
);
v ? (f.corners = v, console.log("[usePageManager] Corners transformed due to rotation change:", f.corners)) : (console.warn(`[usePageManager] Corner transformation returned null for rotation ${f.currentRotation}. Setting corners to null.`), f.corners = null);
} else
f.corners = null;
s.corners !== void 0 && (console.log(`[usePageManager] Explicitly updating corners for page ${i} to:`, s.corners, `(rotation: ${f.currentRotation})`), f.corners = s.corners ? [...s.corners] : null, M || (M = !0)), M && (console.log(`[usePageManager] Resetting processed image for page ${i} due to rotation or corner change.`), f.processedImageDataURL = null, f.processedWidth = null, f.processedHeight = null, f.timestampProcessed = null, f.mode === "preview" && (f.mode = "edit")), s.processedImageDataURL !== void 0 && !M && (f.processedImageDataURL = s.processedImageDataURL, f.processedWidth = s.processedWidth !== void 0 ? s.processedWidth : null, f.processedHeight = s.processedHeight !== void 0 ? s.processedHeight : null, s.processedImageDataURL ? (f.timestampProcessed = Date.now(), f.mode = s.mode !== void 0 ? s.mode : "preview") : (f.timestampProcessed = null, f.mode = "edit")), s.mode !== void 0 && s.mode !== f.mode && (f.mode = s.mode), s.outputFormat !== void 0 && (f.outputFormat = s.outputFormat, console.log(`[usePageManager] Updated outputFormat for page ${i}:`, s.outputFormat)), a.value.splice(c, 1, f), console.log("[usePageManager] Updated page data for:", i, JSON.parse(JSON.stringify(s)), "Resulting page:", JSON.parse(JSON.stringify(f)));
} else
console.warn(`[usePageManager] Cannot update page data: Page with ID ${i} not found.`);
}, y = (i) => {
var c, p;
const s = a.value.findIndex((f) => f.id === i);
if (s !== -1) {
const f = a.value[s];
if ((c = f.originalImageDataURL) != null && c.startsWith("blob:") && se(f.originalImageDataURL), (p = f.processedImageDataURL) != null && p.startsWith("blob:") && se(f.processedImageDataURL), a.value.splice(s, 1), console.log(`[usePageManager] Deleted page: ${i}`), e.value === i)
if (a.value.length > 0) {
const M = Math.min(s, a.value.length - 1);
d(a.value[M].id);
} else
d(null);
} else
console.warn(`[usePageManager] Cannot delete page: Page with ID ${i} not found.`);
}, P = () => {
a.value.forEach((i) => {
var s, c;
(s = i.originalImageDataURL) != null && s.startsWith("blob:") && se(i.originalImageDataURL), (c = i.processedImageDataURL) != null && c.startsWith("blob:") && se(i.processedImageDataURL);
}), a.value = [], e.value = null, console.log("[usePageManager] All pages cleared.");
}, R = (i, s) => {
if (i < 0 || i >= a.value.length || s < 0 || s >= a.value.length) {
console.warn(`[usePageManager] Invalid reorder indices: from ${i} to ${s}`);
return;
}
if (i === s)
return;
const c = [...a.value], [p] = c.splice(i, 1);
c.splice(s, 0, p), a.value = c, console.log(`[usePageManager] Reordered page from index ${i} to ${s}`);
}, T = () => {
if (a.value.length === 0) {
console.warn("[usePageManager] No pages available to navigate");
return;
}
const i = e.value ? a.value.findIndex((c) => c.id === e.value) : -1;
if (i === -1) {
d(a.value[0].id);
return;
}
const s = Math.min(i + 1, a.value.length - 1);
s !== i ? (d(a.value[s].id), console.log(`[usePageManager] Moved to next page: index ${s}`)) : console.log("[usePageManager] Already at last page");
}, U = () => {
if (a.value.length === 0) {
console.warn("[usePageManager] No pages available to navigate");
return;
}
const i = e.value ? a.value.findIndex((c) => c.id === e.value) : -1;
if (i === -1) {
d(a.value[0].id);
return;
}
const s = Math.max(i - 1, 0);
s !== i ? (d(a.value[s].id), console.log(`[usePageManager] Moved to previous page: index ${s}`)) : console.log("[usePageManager] Already at first page");
}, S = () => {
a.value.forEach((i) => {
var s, c;
if ((s = i.originalImageDataURL) != null && s.startsWith("blob:"))
try {
se(i.originalImageDataURL);
} catch (p) {
console.warn("Error revoking original URL", p);
}
if ((c = i.processedImageDataURL) != null && c.startsWith("blob:"))
try {
se(i.processedImageDataURL);
} catch (p) {
console.warn("Error revoking processed URL", p);
}
});
};
return {
pages: r,
activePageId: ue(e),
currentPage: t,
pageCountDisplay: n,
totalPages: l,
addFilesAsPages: u,
addFileAsPageWithProgress: g,
selectPage: d,
updatePageData: w,
deletePage: y,
getPageById: o,
clearAllPages: P,
reorderPages: R,
moveToNextPage: T,
moveToPrevPage: U,
cleanupAllObjectURLs: S
};
}
function Ct(a) {
const e = A(!1), t = A(""), o = A(0);
return {
// State
isLoading: e,
processingStatus: t,
processingProgress: o,
// Methods
handleFilesSelected: async (n) => {
if (console.log("[useDocumentProcessing] handleFilesSelected with files:", n.length), n.length !== 0) {
console.log("[useDocumentProcessing] Proceeding with file processing..."), console.log("[useDocumentProcessing] Setting loading state..."), e.value = !0, t.value = "Processing images...", o.value = 0;
try {
console.log("[useDocumentProcessing] Getting current page count...");
const l = a.pageManager.pages.value.length;
console.log("[useDocumentProcessing] Current page count:", l), console.log("[useDocumentProcessing] Phase 1: Setting initial status..."), t.value = "Loading images...", o.value = 20;
const g = n.length;
console.log("[useDocumentProcessing] Starting to process", g, "files...");
for (let d = 0; d < g; d++) {
const w = n[d];
console.log(`[useDocumentProcessing] Processing file ${d + 1}/${g}:`, w.name, "size:", w.size, "type:", w.type), t.value = `Processing image ${d + 1} of ${g}...`, o.value = 20 + d / g * 60;
try {
console.log(`[useDocumentProcessing] Calling addFileAsPageWithProgress for file ${d + 1}...`), await a.pageManager.addFileAsPageWithProgress(w, (y, P) => {
console.log(`[useDocumentProcessing] Progress callback - Status: ${y}, Progress: ${P}`), t.value = y, o.value = 20 + d / g * 60 + P / g * 60;
}), console.log(`[useDocumentProcessing] Successfully processed file ${d + 1}:`, w.name);
} catch (y) {
throw console.error(`[useDocumentProcessing] Error processing file ${d + 1} (${w.name}):`, y), y;
}
}
console.log("[useDocumentProcessing] All files processed, finalizing..."), t.value = "Finalizing...", o.value = 90;
const u = a.pageManager.pages.value;
if (console.log("[useDocumentProcessing] New pages count:", u.length, "vs previous:", l), u.length > l) {
const d = u[l].id;
console.log("[useDocumentProcessing] Selecting newly added page:", d), a.pageManager.selectPage(d);
}
o.value = 100, t.value = "Complete!", console.log("[useDocumentProcessing] Processing complete!"), setTimeout(() => {
console.log("[useDocumentProcessing] Clearing processing status..."), t.value = "", o.value = 0;
}, 500);
} catch (l) {
console.error("[useDocumentProcessing] Error processing files:", l), console.error("[useDocumentProcessing] Error stack:", l instanceof Error ? l.stack : "No stack trace"), t.value = "Error processing images", setTimeout(() => {
t.value = "", o.value = 0;
}, 2e3);
} finally {
console.log("[useDocumentProcessing] Setting loading to false..."), e.value = !1;
}
}
}
};
}
function bt(a) {
const e = A(!1), t = A(""), o = A(0), r = A(/* @__PURE__ */ new Map()), n = A(null), l = (i, s) => `${i}-${s}`, g = (i) => {
Array.from(r.value.keys()).filter(
(c) => c.startsWith(`${i}-`)
).forEach((c) => {
const p = r.value.get(c);
p && p.startsWith("blob:") && URL.revokeObjectURL(p), r.value.delete(c);
});
}, u = () => {
r.value.forEach((i) => {
i.startsWith("blob:") && URL.revokeObjectURL(i);
}), r.value.clear();
}, d = X(() => a.pageManager.currentPage.value), w = async (i, s) => {
if (s === 0)
return i.originalImageDataURL;
const c = l(i.id, s), p = r.value.get(c);
if (p)
return p;
if (!a.isOpenCVReady.value)
return console.warn("[useImageOperations] OpenCV not ready for rotation generation"), i.originalImageDataURL;
try {
console.log(`[useImageOperations] Generating ${s}° rotation for page ${i.id}`);
const f = await a.rotateImageData(i.originalImageDataURL, s);
return r.value.set(c, f), f;
} catch (f) {
return console.error(`[useImageOperations] Error generating ${s}° rotation:`, f), i.originalImageDataURL;
}
};
we(
() => d.value ? [d.value.id, d.value.currentRotation] : null,
async (i) => {
if (!i || !d.value) {
n.value = null;
return;
}
const [s, c] = i, p = d.value;
try {
const f = await w(p, c);
n.value = f;
} catch (f) {
console.error("[useImageOperations] Error updating rotated image:", f), n.value = p.originalImageDataURL;
}
},
{ immediate: !0 }
);
const y = X(() => n.value), P = X(() => d.value ? d.value.mode === "preview" && d.value.processedImageDataURL ? d.value.processedImageDataURL : y.value : null);
return {
// State
isLoading: e,
processingStatus: t,
processingProgress: o,
// Computed
currentDisplayPage: d,
rotatedImageDataURLByRotation: y,
imageSrcForPreviewComponent: P,
// Methods
processActivePage: async (i) => {
if (!d.value) {
console.warn("[useImageOperations] processActivePage: No current page.");
return;
}
const s = d.value, c = y.value;
if (!c) {
console.warn("[useImageOperations] processActivePage: No image data available for processing.");
return;
}
const p = s.corners;
if (!p || p.length !== 4) {
console.warn(`[useImageOperations] processActivePage: Valid corners not available for page '${s.id}'.`);
return;
}
e.value = !0, t.value = "Processing document...", o.value = 50;
try {
console.log(`[useImageOperations] Processing page '${s.id}' with image:`, c === y.value ? "rotated" : "original", "and corners:", p);
const f = await a.performPerspectiveTransform(
c,
// Use rotated image if available
p,
// Already checked length
i
// Pass the format parameter
);
if (!f || !f.imageDataURL) {
console.error(`[useImageOperations] Perspective transform failed for page '${s.id}'.`), t.value = "Processing failed", setTimeout(() => {
t.value = "", o.value = 0;
}, 2e3), e.value = !1;
return;
}
o.value = 90, t.value = "Finalizing...", a.pageManager.updatePageData(s.id, {
processedImageDataURL: f.imageDataURL,
processedWidth: f.processedWidth,
processedHeight: f.processedHeight,
mode: "preview"
// Switch to preview mode after successful processing
}), console.log(`[useImageOperations] Page '${s.id}' processed successfully.`), o.value = 100, t.value = "Complete!", setTimeout(() => {
t.value = "", o.value = 0;
}, 500);
} catch (f) {
console.error(`[useImageOperations] Error processing page '${s.id}':`, f), t.value = "Error processing document", setTimeout(() => {
t.value = "", o.value = 0;
}, 2e3);
} finally {
e.value = !1;
}
},
resetCornersForCurrentPage: () => {
if (d.value) {
const i = d.value;
if (!y.value) {
console.warn("[useImageOperations] Reset corners: No image data available.");
return;
}
let c = i.originalWidth, p = i.originalHeight;
(i.currentRotation === 90 || i.currentRotation === 270) && (c = i.originalHeight, p = i.originalWidth);
const f = 0.1, M = c * f, D = p * f, v = [
{ x: M, y: D },
{ x: c - M, y: D },
{ x: c - M, y: p - D },
{ x: M, y: p - D }
];
a.pageManager.updatePageData(i.id, {
corners: v
}), console.log(`[useImageOperations] Corners reset to default box for page ${i.id}:`, v);
} else
console.warn("[useImageOperations] Reset corners: No current page.");
},
rotateCurrentPage: async (i) => {
if (!d.value) {
console.warn("[useImageOperations] Rotate: No current page.");
return;
}
const s = d.value, c = i === "left" ? -90 : 90;
let p = (s.currentRotation + c + 360) % 360;
if (!s.originalImageDataURL) {
console.warn("[useImageOperations] Rotate: No original image data available.");
return;
}
console.log(`[useImageOperations] Rotating page ${s.id} by ${c}°...`), e.value = !0, t.value = `Rotating image ${c > 0 ? "right" : "left"}...`, o.value = 30;
try {
o.value = 60;
let f, M = s.originalWidth, D = s.originalHeight;
(s.currentRotation === 90 || s.currentRotation === 270) && (M = s.originalHeight, D = s.originalWidth), s.corners && (console.log(`[useImageOperations] Transforming current corners by ${c}° using dimensions ${M}x${D}`), f = a.transformCornersForRotationIncrement(
s.corners,
c,
M,
D
), console.log("[useImageOperations] Transformed corners:", f)), o.value = 90, a.pageManager.updatePageData(s.id, {
currentRotation: p,
// Clear processed version since rotation invalidates previous processing
processedImageDataURL: void 0,
processedWidth: void 0,
processedHeight: void 0,
// Use transformed corners or undefined to trigger re-detection
corners: f
}), o.value = 100, t.value = "Rotation complete!", console.log(`[useImageOperations] Successfully rotated page ${s.id} to ${p}°, corners ${f ? "transformed (adjusted)" : "reset for re-detection"}`), setTimeout(() => {
t.value = "", o.value = 0;
}, 500);
} catch (f) {
console.error(`[useImageOperations] Error rotating page ${s.id}:`, f), t.value = "Rotation failed", a.pageManager.updatePageData(s.id, { currentRotation: s.currentRotation }), setTimeout(() => {
t.value = "", o.value = 0;
}, 2e3);
} finally {
e.value = !1;
}
},
applyPerspectiveTransformAndGetDataURL: async (i) => {
const s = a.pageManager.getPageById(i);
if (!s)
return console.error("Cannot apply perspective transform: page not found for id", i), null;
if (!s.corners)
return console.error("Cannot apply perspective transform: corners are null for page", s.id), null;
try {
const c = await a.performPerspectiveTransform(s.originalImageDataURL, s.corners);
if (c) {
const p = new Image();
await new Promise((f, M) => {
p.onload = f, p.onerror = (D) => {
console.error("Error loading processed image to get dimensions:", D), M(D);
}, p.src = c.imageDataURL;
}), a.pageManager.updatePageData(s.id, {
processedImageDataURL: c.imageDataURL,
processedWidth: p.naturalWidth,
processedHeight: p.naturalHeight,
mode: "preview"
});
}
return (c == null ? void 0 : c.imageDataURL) || null;
} catch (c) {
return console.error("Error applying perspective transform for page:", s.id, c), a.pageManager.updatePageData(s.id, { mode: "edit" }), null;
}
},
// Cache management
clearPageCache: g,
clearAllCache: u
};
}
function xt(a) {
const {
showFullscreenScanner: e,
isProcessingPdf: t,
currentDisplayPage: o,
pageManager: r,
onCloseScanner: n,
onDiscardProcessedImage: l
} = a;
return Ae("Escape", (g) => {
var u;
g.preventDefault(), t.value ? ((u = o.value) == null ? void 0 : u.mode) === "preview" ? l() : n() : e.value && n();
}), Ae("ArrowLeft", (g) => {
if (t.value && (g.preventDefault(), r.currentPage.value && r.pages.value.length > 1)) {
const u = r.pages.value.findIndex(
(d) => d.id === r.currentPage.value.id
);
u > 0 && r.selectPage(r.pages.value[u - 1].id);
}
}), Ae("ArrowRight", (g) => {
if (t.value && (g.preventDefault(), r.currentPage.value && r.pages.value.length > 1)) {
const u = r.pages.value.findIndex(
(d) => d.id === r.currentPage.value.id
);
u < r.pages.value.length - 1 && r.selectPage(r.pages.value[u + 1].id);
}
}), {
// No return values needed - the composable sets up the keyboard listeners
};
}
function Dt({ currentDisplayPage: a, pageManager: e }) {
return we(a, (t) => {
if (t && t.id && t.mode === "edit") {
let o = !1, r = t.corners;
if (t.corners) {
const n = ht(t.corners), l = t.currentRotation === 90 || t.currentRotation === 270 ? t.originalHeight : t.originalWidth, g = t.currentRotation === 90 || t.currentRotation === 270 ? t.originalWidth : t.originalHeight, u = l * g, d = u > 8e6, w = u > 2e6;
let y = 0.05;
d ? y = 5e-3 : w && (y = 0.025);
const P = u * y;
if (n < P) {
console.warn(`[useCornerValidation] Watcher: corners area for page ${t.id} is too small (${n} < ${P}). Resetting to default. Image: ${d ? "High-res" : w ? "Medium-res" : "Low-res"} (${l}x${g})`);
const R = $e(t.originalWidth, t.originalHeight, 32);
r = Ee(R, t.currentRotation, t.originalWidth, t.originalHeight), o = !0;
}
} else {
console.log(`[useCornerValidation] Watcher: corners for page ${t.id} are null. Setting default.`);
const n = $e(t.originalWidth, t.originalHeight, 32);
r = Ee(n, t.currentRotation, t.originalWidth, t.originalHeight), o = !0;
}
o && e.currentPage.value && e.currentPage.value.id === t.id && e.updatePageData(t.id, {
corners: r
});
}
}, { immediate: !1, deep: !0 }), {
// This composable primarily sets up the watcher
// Could expose validation utilities if needed in the future
};
}
const Et = { class: "loading-spinner d-flex flex-column align-items-center justify-content-center p-4 bg-white rounded shadow-lg" }, $t = {
class: "spinner-border text-primary",
role: "status"
}, Mt = { class: "visually-hidden" }, St = { class: "h5 text-secondary mt-3 ds-loading-message" }, Lt = /* @__PURE__ */ ge({
__name: "LoadingSpinner",
props: {
message: {
type: String,
default: "Loading..."
}
},
setup(a) {
const e = a;
return (t, o) => (V(), Y("div", Et, [
b("div", $t, [
b("span", Mt, de(e.message), 1)
]),
b("p", St, de(e.message), 1)
]));
}
}), me = (a, e) => {
const t = a.__vccOpts || a;
for (const [o, r] of e)
t[o] = r;
return t;
}, At = /* @__PURE__ */ me(Lt, [["__scopeId", "data-v-936490dc"]]);
/**
* @license lucide-vue-next v0.511.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const We = (a) => a.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), Ft = (a) => a.replace(
/^([A-Z])|[\s-_]+(\w)/g,
(e, t, o) => o ? o.toUpperCase() : t.toLowerCase()
), Ot = (a) => {
const e = Ft(a);
return e.charAt(0).toUpperCase() + e.slice(1);
}, kt = (...a) => a.filter((e, t, o) => !!e && e.trim() !== "" && o.indexOf(e) === t).join(" ").trim();
/**
* @license lucide-vue-next v0.511.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
var be = {
xmlns: "http://www.w3.org/2000/svg",
width: 24,
height: 24,
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": 2,
"stroke-linecap": "round",
"stroke-linejoin": "round"
};
/**
* @license lucide-vue-next v0.511.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const Tt = ({ size: a, strokeWidth: e = 2, absoluteStrokeWidth: t, color: o, iconNode: r, name: n, class: l, ...g }, { slots: u }) => Oe(
"svg",
{
...be,
width: a || be.width,
height: a || be.height,
stroke: o || be.stroke,
"stroke-width": t ? Number(e) * 24 / Number(a) : e,
class: kt(
"lucide",
...n ? [`lucide-${We(Ot(n))}-icon`, `lucide-${We(n)}`] : ["lucide-icon"]
),
...g
},
[...r.map((d) => Oe(...d)), ...u.default ? [u.default()] : []]
);
/**
* @license lucide-vue-next v0.511.0 - ISC
*
* This sourc