meticulous-ui 3.11.8 → 3.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,182 @@
1
+ import { jsx as a, jsxs as u } from "react/jsx-runtime";
2
+ import { useState as v } from "react";
3
+ import r from "prop-types";
4
+ import t, { keyframes as w } from "styled-components";
5
+ import c from "../../colors/grey.js";
6
+ import { black as l } from "../../colors/black.js";
7
+ import B from "../Icons/ChevronDown.js";
8
+ const O = w`
9
+ from { opacity: 0; transform: translateY(-6px); }
10
+ to { opacity: 1; transform: translateY(0); }
11
+ `, S = t.div`
12
+ width: 100%;
13
+ display: flex;
14
+ flex-direction: column;
15
+ gap: 12px;
16
+ `, T = t.div`
17
+ border: 1.5px solid
18
+ ${({ $isOpen: o, $activeBackground: n, $itemBorderColor: s }) => o && n ? "transparent" : s || c.m200};
19
+ border-radius: 12px;
20
+ overflow: hidden;
21
+ background: ${({ $isOpen: o, $activeBackground: n, $itemBackground: s }) => o && n ? n : s};
22
+ transition:
23
+ background 0.22s ease,
24
+ border-color 0.22s ease;
25
+ `, I = t.button`
26
+ width: 100%;
27
+ display: flex;
28
+ align-items: center;
29
+ gap: 16px;
30
+ padding: 18px 20px;
31
+ background: none;
32
+ border: none;
33
+ cursor: pointer;
34
+ text-align: left;
35
+
36
+ &:focus-visible {
37
+ outline: 2px solid ${l.m700};
38
+ outline-offset: -2px;
39
+ border-radius: 12px;
40
+ }
41
+ `, R = t.div`
42
+ flex-shrink: 0;
43
+ width: 40px;
44
+ height: 40px;
45
+ border: 1.5px solid
46
+ ${({ $iconBackground: o, $borderColor: n }) => o ? "transparent" : n || c.m200};
47
+ border-radius: 10px;
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: center;
51
+ color: ${({ $iconColor: o }) => o};
52
+ background: ${({ $iconBackground: o }) => o || "none"};
53
+ `, j = t.span`
54
+ flex: 1;
55
+ font-size: 15px;
56
+ font-weight: 600;
57
+ color: ${({ $titleColor: o }) => o || l.m700};
58
+ line-height: 1.4;
59
+ `, q = t.div`
60
+ flex-shrink: 0;
61
+ display: flex;
62
+ align-items: center;
63
+ color: ${({ $chevronColor: o }) => o || c.m600};
64
+ transform: rotate(${({ $isOpen: o }) => o ? "180deg" : "0deg"});
65
+ transition: transform 0.22s ease;
66
+ `, z = t.div`
67
+ padding: 0 20px 18px calc(20px + 40px + 16px);
68
+ font-size: 14px;
69
+ line-height: 1.65;
70
+ color: ${({ $bodyColor: o }) => o || c.m700};
71
+ animation: ${O} 0.22s ease both;
72
+
73
+ a {
74
+ color: ${({ $bodyColor: o }) => o || l.m700};
75
+ text-decoration: underline;
76
+ }
77
+ `, A = l.m700, D = ({
78
+ items: o = [],
79
+ allowMultiple: n = !1,
80
+ activeBackground: s,
81
+ iconColor: h,
82
+ iconBackground: m,
83
+ itemBackground: $ = "#fff",
84
+ itemBorderColor: p,
85
+ titleColor: g,
86
+ bodyColor: b
87
+ }) => {
88
+ const [y, k] = v(/* @__PURE__ */ new Set()), C = (e) => {
89
+ k((i) => {
90
+ const d = n ? new Set(i) : /* @__PURE__ */ new Set();
91
+ return i.has(e) ? d.delete(e) : d.add(e), d;
92
+ });
93
+ };
94
+ return /* @__PURE__ */ a(S, { children: o.map((e) => {
95
+ var d, f, x;
96
+ const i = y.has(e.id);
97
+ return /* @__PURE__ */ u(
98
+ T,
99
+ {
100
+ $isOpen: i,
101
+ $activeBackground: s,
102
+ $itemBackground: $,
103
+ $itemBorderColor: p,
104
+ children: [
105
+ /* @__PURE__ */ u(
106
+ I,
107
+ {
108
+ type: "button",
109
+ "aria-expanded": i,
110
+ "aria-controls": `accordion-body-${e.id}`,
111
+ id: `accordion-header-${e.id}`,
112
+ onClick: () => C(e.id),
113
+ children: [
114
+ e.icon && /* @__PURE__ */ a(
115
+ R,
116
+ {
117
+ "aria-hidden": "true",
118
+ $iconColor: (f = (d = e.iconColor) != null ? d : h) != null ? f : A,
119
+ $iconBackground: (x = e.iconBackground) != null ? x : m,
120
+ $borderColor: p,
121
+ children: e.icon
122
+ }
123
+ ),
124
+ /* @__PURE__ */ a(j, { $titleColor: g, children: e.title }),
125
+ /* @__PURE__ */ a(q, { "aria-hidden": "true", $isOpen: i, $chevronColor: g, children: /* @__PURE__ */ a(B, { size: 18 }) })
126
+ ]
127
+ }
128
+ ),
129
+ i && /* @__PURE__ */ a(
130
+ z,
131
+ {
132
+ id: `accordion-body-${e.id}`,
133
+ role: "region",
134
+ "aria-labelledby": `accordion-header-${e.id}`,
135
+ $bodyColor: b,
136
+ children: e.content
137
+ }
138
+ )
139
+ ]
140
+ },
141
+ e.id
142
+ );
143
+ }) });
144
+ };
145
+ D.propTypes = {
146
+ /** Array of accordion items */
147
+ items: r.arrayOf(
148
+ r.shape({
149
+ /** Unique identifier for the item */
150
+ id: r.oneOfType([r.string, r.number]).isRequired,
151
+ /** Question / heading text */
152
+ title: r.node.isRequired,
153
+ /** Answer / expanded content (string or JSX) */
154
+ content: r.node.isRequired,
155
+ /** Optional icon node rendered in the icon box */
156
+ icon: r.node,
157
+ /** Color applied to the icon — defaults to black.m700 */
158
+ iconColor: r.string,
159
+ /** Background color of the icon box for this item — overrides accordion-level iconBackground */
160
+ iconBackground: r.string
161
+ })
162
+ ),
163
+ /** When true, multiple items can be open simultaneously */
164
+ allowMultiple: r.bool,
165
+ /** Background color applied to the expanded item — use a token from the colors palette e.g. blue.m50 */
166
+ activeBackground: r.string,
167
+ /** Default icon color for all items — overridden per-item via item.iconColor. Defaults to black.m700 */
168
+ iconColor: r.string,
169
+ /** Default icon box background for all items — overridden per-item via item.iconBackground */
170
+ iconBackground: r.string,
171
+ /** Background color for resting (closed) items. Defaults to '#fff' — use a palette token e.g. blueGray.m800 for dark mode */
172
+ itemBackground: r.string,
173
+ /** Border color for all items — use a palette token e.g. blueGray.m600 for dark mode */
174
+ itemBorderColor: r.string,
175
+ /** Title and chevron text color — use a light palette token e.g. blueGray.m100 for dark mode */
176
+ titleColor: r.string,
177
+ /** Body content text color — use a muted light token e.g. blueGray.m300 for dark mode */
178
+ bodyColor: r.string
179
+ };
180
+ export {
181
+ D as default
182
+ };
@@ -0,0 +1,4 @@
1
+ import r from "./Accordion.js";
2
+ export {
3
+ r as default
4
+ };
package/index.d.ts CHANGED
@@ -49,6 +49,42 @@ export type ThemeColor =
49
49
 
50
50
  export type ComponentSize = 'small' | 'medium' | 'large';
51
51
 
52
+ // ---------------------------------------------------------------------------
53
+ // Accordion
54
+ // ---------------------------------------------------------------------------
55
+
56
+ export interface AccordionItem {
57
+ id: string | number;
58
+ title: React.ReactNode;
59
+ content: React.ReactNode;
60
+ icon?: React.ReactNode;
61
+ /** Color applied to the icon — defaults to black.m700 */
62
+ iconColor?: string;
63
+ /** Background color of the icon box for this item — overrides accordion-level iconBackground */
64
+ iconBackground?: string;
65
+ }
66
+
67
+ export interface AccordionProps {
68
+ items?: AccordionItem[];
69
+ allowMultiple?: boolean;
70
+ /** Background color applied to the expanded item — use a palette token e.g. blue.m50 */
71
+ activeBackground?: string;
72
+ /** Default icon color for all items — overridden per-item via item.iconColor. Defaults to black.m700 */
73
+ iconColor?: string;
74
+ /** Default icon box background for all items — overridden per-item via item.iconBackground */
75
+ iconBackground?: string;
76
+ /** Background color for resting (closed) items. Defaults to '#fff' — use a palette token e.g. blueGray.m800 for dark mode */
77
+ itemBackground?: string;
78
+ /** Border color for all items — use a palette token e.g. blueGray.m600 for dark mode */
79
+ itemBorderColor?: string;
80
+ /** Title and chevron text color — use a light palette token e.g. blueGray.m100 for dark mode */
81
+ titleColor?: string;
82
+ /** Body content text color — use a muted light token e.g. blueGray.m300 for dark mode */
83
+ bodyColor?: string;
84
+ }
85
+
86
+ export declare const Accordion: React.FC<AccordionProps>;
87
+
52
88
  // ---------------------------------------------------------------------------
53
89
  // Link
54
90
  // ---------------------------------------------------------------------------
@@ -1452,28 +1488,32 @@ export declare function getQrAsJsonContent(source: QrSource): Promise<QrJsonResu
1452
1488
 
1453
1489
  export interface RecognizeImageResult {
1454
1490
  success: boolean;
1455
- /** Whether the TextDetector API is available in this browser. */
1456
- supported?: boolean;
1457
1491
  /** BCP-47 code of the primary language used for recognition. */
1458
1492
  detectedLanguage?: string;
1459
- /** Full extracted text, newline-separated by detected region. */
1493
+ /** Full extracted text from OCR, newline-separated by detected region. */
1460
1494
  text?: string;
1461
- /** OCR confidence score 0–100, or null when not available. */
1495
+ /** OCR confidence score 0–100. */
1462
1496
  confidence?: number | null;
1463
- /** Raw per-region data including bounding boxes and corner points. */
1464
- rawJson?: Array<{
1465
- rawValue: string;
1466
- boundingBox: { x: number; y: number; width: number; height: number };
1467
- cornerPoints: Array<{ x: number; y: number }>;
1468
- }>;
1497
+ /**
1498
+ * All readable lines from the OCR output as a key-value object.
1499
+ * Lines matching `ALL-CAPS KEY : value` use the label as the key.
1500
+ * Lines without a recognisable label are assigned generic keys (`param_1`, `param_2`, …).
1501
+ * Continuation lines (e.g. a wrapped address) are appended to the previous key.
1502
+ */
1503
+ fields?: Record<string, string>;
1504
+ /** Raw Tesseract output including per-word bounding boxes and metadata. */
1505
+ rawJson?: object;
1469
1506
  /** Human-readable error when success is false. */
1470
1507
  error?: string;
1471
1508
  }
1472
1509
 
1473
1510
  /**
1474
- * Detect text in a base64 image using the browser-native TextDetector API.
1475
- * No external dependencies or network requests.
1476
- * Supported in Chrome 70+ and Edge 79+; returns supported:false on other browsers.
1511
+ * Runs OCR on a base64 image in all browsers with no npm dependency.
1512
+ * Powered by Tesseract.js loaded on demand from a CDN (fetched once, then
1513
+ * browser-cached). Preprocesses the image (grayscale + upscale + contrast
1514
+ * boost) before recognition for higher accuracy. Returns structured `fields`
1515
+ * with extracted key-value pairs alongside the raw `text`, `confidence` score,
1516
+ * and `rawJson` with full word-level bounding-box metadata.
1477
1517
  */
1478
1518
  export declare function recognizeImageContent(
1479
1519
  base64Image: string,
package/index.js CHANGED
@@ -12,8 +12,8 @@ import { default as h } from "./components/Link/Link.js";
12
12
  import { default as E } from "./components/Modal/Modal.js";
13
13
  import { default as L } from "./components/Timer/Timer.js";
14
14
  import { default as v } from "./components/Shimmer/Shimmer.js";
15
- import { default as O } from "./components/VideoPlayer/VideoPlayer.js";
16
- import { default as A } from "./components/Image/Image.js";
15
+ import { default as A } from "./components/VideoPlayer/VideoPlayer.js";
16
+ import { default as z } from "./components/Image/Image.js";
17
17
  import { default as N } from "./components/Carousel/Carousel.js";
18
18
  import { default as R } from "./components/Typography/Headings/index.js";
19
19
  import { default as G } from "./components/Typography/P/P.js";
@@ -39,8 +39,8 @@ import { default as he } from "./utils/groupBy.js";
39
39
  import { default as Ee } from "./utils/hasEqualProps.js";
40
40
  import { default as Le } from "./utils/addDays.js";
41
41
  import { default as ve } from "./utils/countdown.js";
42
- import { default as Oe } from "./utils/differenceInDays.js";
43
- import { default as Ae } from "./utils/isEmpty.js";
42
+ import { default as Ae } from "./utils/differenceInDays.js";
43
+ import { default as ze } from "./utils/isEmpty.js";
44
44
  import { default as Ne } from "./utils/isEqual.js";
45
45
  import { default as Re } from "./utils/isNonEmptyArray.js";
46
46
  import { default as Ge } from "./utils/isPast.js";
@@ -66,7 +66,7 @@ import { default as Co } from "./utils/titleCase.js";
66
66
  import { default as Io } from "./utils/truncate.js";
67
67
  import { default as wo } from "./utils/uniqueBy.js";
68
68
  import { default as Bo } from "./utils/isEmail.js";
69
- import { default as zo } from "./utils/isPhone.js";
69
+ import { default as Oo } from "./utils/isPhone.js";
70
70
  import { default as Fo } from "./utils/isURL.js";
71
71
  import { default as Do } from "./utils/isPasswordStrong.js";
72
72
  import { default as qo } from "./utils/isPAN.js";
@@ -93,7 +93,7 @@ import { default as Ca } from "./utils/setQueryParam.js";
93
93
  import { default as Ia } from "./utils/removeQueryParam.js";
94
94
  import { default as wa } from "./utils/buildURL.js";
95
95
  import { default as Ba } from "./utils/redirectTo.js";
96
- import { default as za } from "./utils/getCurrentPath.js";
96
+ import { default as Oa } from "./utils/getCurrentPath.js";
97
97
  import { default as Fa } from "./utils/isActiveRoute.js";
98
98
  import { default as Da } from "./utils/setLocalStorage.js";
99
99
  import { default as qa } from "./utils/getLocalStorage.js";
@@ -120,7 +120,7 @@ import { default as Ct } from "./utils/trapFocus.js";
120
120
  import { default as It } from "./utils/generateAriaId.js";
121
121
  import { default as wt } from "./utils/handleKeyboardNavigation.js";
122
122
  import { default as Bt } from "./utils/logError.js";
123
- import { default as zt } from "./utils/captureException.js";
123
+ import { default as Ot } from "./utils/captureException.js";
124
124
  import { default as Ft } from "./utils/safeJSONParse.js";
125
125
  import { default as Dt } from "./utils/safeJSONStringify.js";
126
126
  import { default as qt } from "./utils/fallback.js";
@@ -147,7 +147,7 @@ import { default as Cr } from "./utils/fadeIn.js";
147
147
  import { default as Ir } from "./utils/fadeOut.js";
148
148
  import { default as wr } from "./utils/smoothScroll.js";
149
149
  import { default as Br } from "./utils/waitForTransitionEnd.js";
150
- import { default as zr } from "./utils/trackEvent.js";
150
+ import { default as Or } from "./utils/trackEvent.js";
151
151
  import { default as Fr } from "./utils/trackPageView.js";
152
152
  import { default as Dr } from "./utils/measurePerformance.js";
153
153
  import { default as qr } from "./utils/featureGate.js";
@@ -173,8 +173,8 @@ import { default as hf } from "./hooks/useLocalStorage.js";
173
173
  import { default as Ef } from "./hooks/useSessionStorage.js";
174
174
  import { default as Lf } from "./hooks/useOutsideClick.js";
175
175
  import { default as vf } from "./hooks/useWindowSize.js";
176
- import { default as Of } from "./hooks/useOnlineStatus.js";
177
- import { default as Af } from "./hooks/useCopyToClipboard.js";
176
+ import { default as Af } from "./hooks/useOnlineStatus.js";
177
+ import { default as zf } from "./hooks/useCopyToClipboard.js";
178
178
  import { default as Nf } from "./hooks/useToggle.js";
179
179
  import { default as Rf } from "./hooks/useTimeout.js";
180
180
  import { default as Gf } from "./hooks/useInterval.js";
@@ -193,7 +193,9 @@ import { default as ms } from "./components/Input/Checkbox/Checkbox.js";
193
193
  import { default as ps } from "./components/Input/RadioGroup/RadioGroup.js";
194
194
  import { default as ns } from "./components/Input/FileUploader/FileUploader.js";
195
195
  import { default as cs } from "./components/Switch/Switch.js";
196
+ import { default as Ss } from "./components/Accordion/Accordion.js";
196
197
  export {
198
+ Ss as Accordion,
197
199
  k as Button,
198
200
  N as Carousel,
199
201
  ms as Checkbox,
@@ -202,7 +204,7 @@ export {
202
204
  ns as FileUploader,
203
205
  U as Form,
204
206
  R as Headings,
205
- A as Image,
207
+ z as Image,
206
208
  fs as Input,
207
209
  h as Link,
208
210
  m as Loader,
@@ -222,7 +224,7 @@ export {
222
224
  L as Timer,
223
225
  r as Toast,
224
226
  f as ToastContainer,
225
- O as VideoPlayer,
227
+ A as VideoPlayer,
226
228
  Le as addDays,
227
229
  bt as announceToScreenReader,
228
230
  Jr as auditLog,
@@ -231,7 +233,7 @@ export {
231
233
  ir as cancelablePromise,
232
234
  K as capFirstLetter,
233
235
  X as capitalize,
234
- zt as captureException,
236
+ Ot as captureException,
235
237
  $ as chunk,
236
238
  oe as clamp,
237
239
  Ha as clearStorage,
@@ -247,7 +249,7 @@ export {
247
249
  fe as deepClone,
248
250
  sf as deepFreeze,
249
251
  yt as detectOutsideClick,
250
- Oe as differenceInDays,
252
+ Ae as differenceInDays,
251
253
  da as downloadFile,
252
254
  Cr as fadeIn,
253
255
  Ir as fadeOut,
@@ -265,7 +267,7 @@ export {
265
267
  gr as fuzzySearch,
266
268
  It as generateAriaId,
267
269
  Te as generateInitials,
268
- za as getCurrentPath,
270
+ Oa as getCurrentPath,
269
271
  ke as getGreetingByTime,
270
272
  ga as getJsonContentAsQr,
271
273
  qa as getLocalStorage,
@@ -285,7 +287,7 @@ export {
285
287
  Mt as isAuthenticated,
286
288
  ra as isDarkMode,
287
289
  Bo as isEmail,
288
- Ae as isEmpty,
290
+ ze as isEmpty,
289
291
  Ne as isEqual,
290
292
  _t as isFeatureEnabled,
291
293
  Jo as isGST,
@@ -296,7 +298,7 @@ export {
296
298
  qo as isPAN,
297
299
  Do as isPasswordStrong,
298
300
  Ge as isPast,
299
- zo as isPhone,
301
+ Oo as isPhone,
300
302
  Vo as isRequired,
301
303
  aa as isSafari,
302
304
  Qe as isToday,
@@ -362,13 +364,13 @@ export {
362
364
  bo as timeAgo,
363
365
  Co as titleCase,
364
366
  it as toggleFullscreen,
365
- zr as trackEvent,
367
+ Or as trackEvent,
366
368
  Fr as trackPageView,
367
369
  Ct as trapFocus,
368
370
  Io as truncate,
369
371
  wo as uniqueBy,
370
372
  xt as unlockBodyScroll,
371
- Af as useCopyToClipboard,
373
+ zf as useCopyToClipboard,
372
374
  df as useDebounce,
373
375
  Sf as useEventListener,
374
376
  Uf as useFirstRender,
@@ -377,7 +379,7 @@ export {
377
379
  cf as useIsMounted,
378
380
  hf as useLocalStorage,
379
381
  kf as useMediaQuery,
380
- Of as useOnlineStatus,
382
+ Af as useOnlineStatus,
381
383
  Lf as useOutsideClick,
382
384
  uf as usePrevious,
383
385
  Ef as useSessionStorage,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meticulous-ui",
3
- "version": "3.11.8",
3
+ "version": "3.12.1",
4
4
  "license": "ISC",
5
5
  "description": "A comprehensive React UI component library with a wide range of customizable components, icons, colors, and utilities for building modern web applications.",
6
6
  "types": "./index.d.ts",
@@ -1,4 +1,62 @@
1
- const l = {
1
+ const b = (l) => new Promise((n, s) => {
2
+ const o = new Image();
3
+ o.onload = () => {
4
+ const r = document.createElement("canvas");
5
+ r.width = o.width * 2, r.height = o.height * 2;
6
+ const e = r.getContext("2d");
7
+ e.filter = "grayscale(1) contrast(1.8)", e.drawImage(o, 0, 0, r.width, r.height), n(r.toDataURL("image/png"));
8
+ }, o.onerror = s, o.src = l;
9
+ }), u = (l) => {
10
+ var r;
11
+ const n = ((r = l.words) != null ? r : []).map((e) => {
12
+ var t;
13
+ return { text: (t = e.text) == null ? void 0 : t.trim(), bbox: e.bbox };
14
+ }).filter((e) => e.text && e.bbox);
15
+ if (!n.length) return [];
16
+ const s = [];
17
+ for (const e of n) {
18
+ const t = (e.bbox.y0 + e.bbox.y1) / 2, c = (e.bbox.y1 - e.bbox.y0) / 2;
19
+ let a = s.find((m) => Math.abs(m.cy - t) < c);
20
+ a || (a = { cy: t, words: [] }, s.push(a)), a.words.push(e);
21
+ }
22
+ const o = [];
23
+ for (const e of s) {
24
+ const t = e.words.slice().sort((i, x) => i.bbox.x0 - x.bbox.x0), c = t.slice(1).map((i, x) => i.bbox.x0 - t[x].bbox.x1), a = c.length ? c.reduce((i, x) => i + x, 0) / c.length : 0, m = Math.max(a * 3, (t[0].bbox.y1 - t[0].bbox.y0) * 1.5);
25
+ let d = [t[0]];
26
+ for (let i = 1; i < t.length; i++)
27
+ t[i].bbox.x0 - t[i - 1].bbox.x1 > m && (o.push({
28
+ text: d.map((x) => x.text).join(" "),
29
+ y: e.cy,
30
+ x: d[0].bbox.x0
31
+ }), d = []), d.push(t[i]);
32
+ o.push({
33
+ text: d.map((i) => i.text).join(" "),
34
+ y: e.cy,
35
+ x: d[0].bbox.x0
36
+ });
37
+ }
38
+ return o.sort((e, t) => e.y - t.y || e.x - t.x), o.map((e) => e.text);
39
+ }, h = (l) => {
40
+ const n = {};
41
+ let s = null, o = 0;
42
+ const r = (e) => {
43
+ let t = e.replace(/^[^A-Za-z0-9"'(]+/, "").trim();
44
+ return t = t.replace(/[^A-Za-z0-9"')]+$/, "").trim(), t = t.replace(/^[A-Za-z]{1,3}\s+(?=\d)/, ""), t;
45
+ };
46
+ for (const e of l) {
47
+ const t = r(e.trim());
48
+ if (!t) {
49
+ s = null;
50
+ continue;
51
+ }
52
+ const c = t.match(/\b([A-Z][A-Z.]{0,}(?:\s+[A-Z.]+){0,2})\s*[:©]\s*(.+)/);
53
+ if (c) {
54
+ const a = c[1].trim();
55
+ n[a] = c[2].trim(), s = a;
56
+ } else s && /^[A-Z0-9][A-Z0-9\s.,'\-]+$/.test(t) ? (n[s] += " " + t, s = null) : (/\w{3,}/.test(t) && (n[`param_${++o}`] = t), s = null);
57
+ }
58
+ return n;
59
+ }, g = {
2
60
  en: "eng",
3
61
  hi: "hin",
4
62
  fr: "fra",
@@ -17,37 +75,40 @@ const l = {
17
75
  vi: "vie",
18
76
  th: "tha",
19
77
  id: "ind"
20
- }, d = (t) => t.map((r) => {
21
- var e;
22
- return (e = l[r]) != null ? e : r;
78
+ }, f = (l) => l.map((n) => {
79
+ var s;
80
+ return (s = g[n]) != null ? s : n;
23
81
  }).join("+");
24
- let s = null;
25
- const u = () => (s || (s = import(
82
+ let p = null;
83
+ const y = () => (p || (p = import(
26
84
  /* webpackIgnore: true */
27
85
  /* @vite-ignore */
28
86
  "https://esm.sh/tesseract.js@5"
29
- )), s), p = async (t, r = "en") => {
30
- var e;
87
+ )), p), w = async (l, n = "en") => {
88
+ var s;
31
89
  try {
32
- const a = t.startsWith("data:") ? t : `data:image/png;base64,${t}`, o = r.split("+").filter(Boolean), { createWorker: i } = await u(), c = await i(d(o));
90
+ const o = l.startsWith("data:") ? l : `data:image/png;base64,${l}`, r = n.split("+").filter(Boolean), e = await b(o), { createWorker: t } = await y(), c = await t(f(r));
33
91
  try {
34
- const { data: n } = await c.recognize(a);
92
+ await c.setParameters({ tessedit_pageseg_mode: "3" });
93
+ const { data: a } = await c.recognize(e), m = a.text.trim();
35
94
  return {
36
95
  success: !0,
37
- detectedLanguage: (e = o[0]) != null ? e : "en",
38
- text: n.text.trim(),
39
- confidence: n.confidence,
96
+ detectedLanguage: (s = r[0]) != null ? s : "en",
97
+ text: m,
98
+ confidence: a.confidence,
40
99
  // 0–100
41
- rawJson: n
100
+ fields: h(u(a)),
101
+ // structured key-value extraction, split on bbox gaps
102
+ rawJson: a
42
103
  // full metadata: words, blocks, bounding boxes
43
104
  };
44
105
  } finally {
45
106
  await c.terminate();
46
107
  }
47
- } catch (a) {
48
- return { success: !1, error: a.message };
108
+ } catch (o) {
109
+ return { success: !1, error: o.message };
49
110
  }
50
111
  };
51
112
  export {
52
- p as default
113
+ w as default
53
114
  };