@adoptai/genui-components 0.1.58 → 0.1.60

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.
Files changed (54) hide show
  1. package/dist/builders/BlockForm.d.ts +5 -1
  2. package/dist/builders/BlockForm.d.ts.map +1 -1
  3. package/dist/builders/BuilderForm.d.ts +22 -1
  4. package/dist/builders/BuilderForm.d.ts.map +1 -1
  5. package/dist/builders/index.d.ts +1 -1
  6. package/dist/builders/index.d.ts.map +1 -1
  7. package/dist/composites/decision-card/resolver.cjs +289 -13
  8. package/dist/composites/decision-card/resolver.cjs.map +1 -1
  9. package/dist/composites/decision-card/resolver.d.ts +2 -1
  10. package/dist/composites/decision-card/resolver.d.ts.map +1 -1
  11. package/dist/composites/decision-card/resolver.js +289 -13
  12. package/dist/composites/decision-card/resolver.js.map +1 -1
  13. package/dist/composites/document-field-extraction/resolver.cjs +1920 -0
  14. package/dist/composites/document-field-extraction/resolver.cjs.map +1 -0
  15. package/dist/composites/document-field-extraction/resolver.js +1913 -0
  16. package/dist/composites/document-field-extraction/resolver.js.map +1 -0
  17. package/dist/composites/tabby-auth/resolver.cjs +597 -0
  18. package/dist/composites/tabby-auth/resolver.cjs.map +1 -0
  19. package/dist/composites/tabby-auth/resolver.d.ts +3 -0
  20. package/dist/composites/tabby-auth/resolver.d.ts.map +1 -0
  21. package/dist/composites/tabby-auth/resolver.js +595 -0
  22. package/dist/composites/tabby-auth/resolver.js.map +1 -0
  23. package/dist/composites/workflow-stepper/resolver.cjs +86 -18
  24. package/dist/composites/workflow-stepper/resolver.cjs.map +1 -1
  25. package/dist/composites/workflow-stepper/resolver.d.ts.map +1 -1
  26. package/dist/composites/workflow-stepper/resolver.js +86 -18
  27. package/dist/composites/workflow-stepper/resolver.js.map +1 -1
  28. package/dist/index.cjs +901 -63
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.js +901 -63
  31. package/dist/index.js.map +1 -1
  32. package/dist/renderer.cjs +810 -45
  33. package/dist/renderer.cjs.map +1 -1
  34. package/dist/renderer.js +810 -45
  35. package/dist/renderer.js.map +1 -1
  36. package/dist/resolver.cjs +810 -45
  37. package/dist/resolver.cjs.map +1 -1
  38. package/dist/resolver.d.ts.map +1 -1
  39. package/dist/resolver.js +810 -45
  40. package/dist/resolver.js.map +1 -1
  41. package/dist/schemas/decision-card.d.ts +37 -0
  42. package/dist/schemas/decision-card.d.ts.map +1 -1
  43. package/dist/schemas/index.cjs +113 -8
  44. package/dist/schemas/index.cjs.map +1 -1
  45. package/dist/schemas/index.d.ts +155 -0
  46. package/dist/schemas/index.d.ts.map +1 -1
  47. package/dist/schemas/index.js +113 -8
  48. package/dist/schemas/index.js.map +1 -1
  49. package/dist/schemas/tabby-auth.d.ts +58 -0
  50. package/dist/schemas/tabby-auth.d.ts.map +1 -0
  51. package/dist/schemas/workflow-stepper.d.ts +60 -0
  52. package/dist/schemas/workflow-stepper.d.ts.map +1 -1
  53. package/dist/tool-definitions.json +135 -4
  54. package/package.json +1 -1
@@ -0,0 +1,1913 @@
1
+ "use client";
2
+ import React6, { createContext, useContext, useState, useRef, useCallback, useEffect } from 'react';
3
+ import { createPortal } from 'react-dom';
4
+ import { toPng } from 'html-to-image';
5
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
+
7
+ // src/shared/theme.ts
8
+ var BORDER = "#dedede";
9
+ var MUTED = "#777777";
10
+ var PAPER = "#f6f6f6";
11
+ var ACCENT = "#ff5000";
12
+ var ACCENT_SOFT = "#cc4000";
13
+ var SECONDARY = "#0364ff";
14
+ var CHART_PALETTE = [
15
+ "#ff5000",
16
+ "#0364ff",
17
+ "#16a34a",
18
+ "#dc2626",
19
+ "#7c3aed",
20
+ "#0891b2",
21
+ "#f59e0b",
22
+ "#6366f1",
23
+ "#ec4899",
24
+ "#84cc16",
25
+ "#e11d48",
26
+ "#0ea5e9"
27
+ ];
28
+ function ColumnSettingsPanel({ columns, hidden, onToggle, onShowAll, onHideAll }) {
29
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "6px", minWidth: "180px" }, children: [
30
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", paddingBottom: "4px", borderBottom: `1px solid ${BORDER}` }, children: [
31
+ /* @__PURE__ */ jsx(
32
+ "button",
33
+ {
34
+ onClick: onShowAll,
35
+ style: { background: "none", border: "none", cursor: "pointer", fontSize: "11px", color: ACCENT, fontWeight: 500, padding: 0 },
36
+ children: "Show all"
37
+ }
38
+ ),
39
+ /* @__PURE__ */ jsx(
40
+ "button",
41
+ {
42
+ onClick: onHideAll,
43
+ style: { background: "none", border: "none", cursor: "pointer", fontSize: "11px", color: MUTED, fontWeight: 500, padding: 0 },
44
+ children: "Hide all"
45
+ }
46
+ )
47
+ ] }),
48
+ columns.map((col) => /* @__PURE__ */ jsxs(
49
+ "label",
50
+ {
51
+ style: { display: "flex", alignItems: "center", gap: "8px", cursor: "pointer", fontSize: "12px", color: "var(--foreground)" },
52
+ children: [
53
+ /* @__PURE__ */ jsx(
54
+ "input",
55
+ {
56
+ type: "checkbox",
57
+ checked: !hidden.has(col.key),
58
+ onChange: () => onToggle(col.key),
59
+ style: { accentColor: ACCENT, width: "14px", height: "14px", margin: 0, cursor: "pointer" }
60
+ }
61
+ ),
62
+ col.label
63
+ ]
64
+ },
65
+ col.key
66
+ ))
67
+ ] });
68
+ }
69
+ var DOT_COLOR = "#aaaaaa";
70
+ var DOT_HOVER = "#555555";
71
+ function ComponentActions({ children, onDownloadCSV, columnConfig, filename = "component" }) {
72
+ const [open, setOpen] = useState(false);
73
+ const [view, setView] = useState("main");
74
+ const contentRef = useRef(null);
75
+ const menuRef = useRef(null);
76
+ const btnRef = useRef(null);
77
+ const close = useCallback(() => {
78
+ setOpen(false);
79
+ setView("main");
80
+ }, []);
81
+ useEffect(() => {
82
+ if (!open) return;
83
+ const handler = (e) => {
84
+ var _a, _b;
85
+ if ((_a = menuRef.current) == null ? void 0 : _a.contains(e.target)) return;
86
+ if ((_b = btnRef.current) == null ? void 0 : _b.contains(e.target)) return;
87
+ close();
88
+ };
89
+ document.addEventListener("mousedown", handler);
90
+ return () => document.removeEventListener("mousedown", handler);
91
+ }, [open, close]);
92
+ const handleDownloadPNG = useCallback(async () => {
93
+ if (!contentRef.current) return;
94
+ try {
95
+ const url = await toPng(contentRef.current, { backgroundColor: "white", pixelRatio: 2 });
96
+ const a = document.createElement("a");
97
+ a.href = url;
98
+ a.download = `${filename}.png`;
99
+ a.click();
100
+ } catch (e) {
101
+ }
102
+ close();
103
+ }, [filename, close]);
104
+ const handleCSV = useCallback(() => {
105
+ onDownloadCSV == null ? void 0 : onDownloadCSV();
106
+ close();
107
+ }, [onDownloadCSV, close]);
108
+ return /* @__PURE__ */ jsxs("div", { style: { width: "100%", display: "flex", flexDirection: "column" }, children: [
109
+ /* @__PURE__ */ jsx("div", { ref: contentRef, style: { width: "100%" }, children }),
110
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: "4px", position: "relative", zIndex: 10, flexShrink: 0 }, children: [
111
+ /* @__PURE__ */ jsx(
112
+ "button",
113
+ {
114
+ ref: btnRef,
115
+ onClick: () => {
116
+ setOpen((o) => !o);
117
+ setView("main");
118
+ },
119
+ "aria-label": "Component actions",
120
+ style: {
121
+ background: "none",
122
+ border: "none",
123
+ cursor: "pointer",
124
+ padding: "4px 8px",
125
+ display: "flex",
126
+ gap: "3px",
127
+ alignItems: "center",
128
+ borderRadius: "6px",
129
+ transition: "background 0.15s"
130
+ },
131
+ onMouseEnter: (e) => {
132
+ e.currentTarget.style.background = "#f2f2f2";
133
+ e.currentTarget.querySelectorAll("circle").forEach((c) => c.style.fill = DOT_HOVER);
134
+ },
135
+ onMouseLeave: (e) => {
136
+ e.currentTarget.style.background = "none";
137
+ e.currentTarget.querySelectorAll("circle").forEach((c) => c.style.fill = DOT_COLOR);
138
+ },
139
+ children: /* @__PURE__ */ jsxs("svg", { width: "20", height: "6", viewBox: "0 0 20 6", children: [
140
+ /* @__PURE__ */ jsx("circle", { cx: "3", cy: "3", r: "2", style: { fill: DOT_COLOR, transition: "fill 0.15s" } }),
141
+ /* @__PURE__ */ jsx("circle", { cx: "10", cy: "3", r: "2", style: { fill: DOT_COLOR, transition: "fill 0.15s" } }),
142
+ /* @__PURE__ */ jsx("circle", { cx: "17", cy: "3", r: "2", style: { fill: DOT_COLOR, transition: "fill 0.15s" } })
143
+ ] })
144
+ }
145
+ ),
146
+ open && /* @__PURE__ */ jsx(
147
+ "div",
148
+ {
149
+ ref: menuRef,
150
+ style: {
151
+ position: "absolute",
152
+ bottom: "100%",
153
+ right: 0,
154
+ marginBottom: "4px",
155
+ background: "white",
156
+ border: `1px solid ${BORDER}`,
157
+ borderRadius: "0.75rem",
158
+ boxShadow: "0 4px 12px rgba(0,0,0,0.06)",
159
+ zIndex: 50,
160
+ padding: view === "columns" ? "10px" : "4px",
161
+ minWidth: view === "columns" ? "200px" : "160px"
162
+ },
163
+ children: view === "main" ? /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column" }, children: [
164
+ columnConfig && /* @__PURE__ */ jsx(MenuButton, { label: "Customize columns", onClick: () => setView("columns") }),
165
+ onDownloadCSV && /* @__PURE__ */ jsx(MenuButton, { label: "Download CSV", onClick: handleCSV }),
166
+ /* @__PURE__ */ jsx(MenuButton, { label: "Download PNG", onClick: handleDownloadPNG })
167
+ ] }) : /* @__PURE__ */ jsxs("div", { children: [
168
+ /* @__PURE__ */ jsx(
169
+ "button",
170
+ {
171
+ onClick: () => setView("main"),
172
+ style: { background: "none", border: "none", cursor: "pointer", fontSize: "11px", color: MUTED, marginBottom: "6px", padding: 0 },
173
+ children: "\u2190 Back"
174
+ }
175
+ ),
176
+ /* @__PURE__ */ jsx(
177
+ ColumnSettingsPanel,
178
+ {
179
+ columns: columnConfig.columns,
180
+ hidden: columnConfig.hidden,
181
+ onToggle: columnConfig.onToggle,
182
+ onShowAll: columnConfig.onShowAll,
183
+ onHideAll: columnConfig.onHideAll
184
+ }
185
+ )
186
+ ] })
187
+ }
188
+ )
189
+ ] })
190
+ ] });
191
+ }
192
+ function MenuButton({ label, onClick }) {
193
+ return /* @__PURE__ */ jsx(
194
+ "button",
195
+ {
196
+ onClick,
197
+ style: {
198
+ background: "none",
199
+ border: "none",
200
+ cursor: "pointer",
201
+ padding: "8px 12px",
202
+ fontSize: "12.5px",
203
+ color: "var(--foreground)",
204
+ textAlign: "left",
205
+ borderRadius: "8px",
206
+ transition: "background 0.15s",
207
+ whiteSpace: "nowrap"
208
+ },
209
+ onMouseEnter: (e) => e.currentTarget.style.background = "#f2f2f2",
210
+ onMouseLeave: (e) => e.currentTarget.style.background = "none",
211
+ children: label
212
+ }
213
+ );
214
+ }
215
+
216
+ // src/shared/downloadCSV.ts
217
+ function escapeCSV(value) {
218
+ const str = value == null ? "" : String(value);
219
+ if (str.includes(",") || str.includes('"') || str.includes("\n")) {
220
+ return `"${str.replace(/"/g, '""')}"`;
221
+ }
222
+ return str;
223
+ }
224
+ function downloadCSV(columns, rows, filename) {
225
+ const header = columns.map((c) => escapeCSV(c.label)).join(",");
226
+ const body = rows.map((row) => columns.map((c) => escapeCSV(row[c.key])).join(",")).join("\n");
227
+ const csv = `${header}
228
+ ${body}`;
229
+ const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
230
+ const url = URL.createObjectURL(blob);
231
+ const a = document.createElement("a");
232
+ a.href = url;
233
+ a.download = filename.endsWith(".csv") ? filename : `${filename}.csv`;
234
+ a.click();
235
+ URL.revokeObjectURL(url);
236
+ }
237
+ var DEFAULT_TOKENS = {
238
+ BORDER,
239
+ MUTED,
240
+ PAPER,
241
+ ACCENT,
242
+ ACCENT_SOFT,
243
+ SECONDARY,
244
+ CHART_PALETTE: [...CHART_PALETTE]
245
+ };
246
+ var GenUIThemeContext = createContext(DEFAULT_TOKENS);
247
+ function useTheme() {
248
+ return useContext(GenUIThemeContext);
249
+ }
250
+
251
+ // src/composites/document-field-extraction/bboxTransform.ts
252
+ function bboxToRect(bbox, page, px) {
253
+ if (!bbox || bbox.length !== 4) return null;
254
+ const { wPts, hPts } = page;
255
+ const { wPx, hPx } = px;
256
+ if (!wPts || !hPts || !wPx || !hPx) return null;
257
+ const [x0, y0, x1, y1] = bbox;
258
+ const sx = wPx / wPts;
259
+ const sy = hPx / hPts;
260
+ return {
261
+ left: x0 * sx,
262
+ width: (x1 - x0) * sx,
263
+ // Flip Y: the box's TOP in screen space is the page height minus its upper
264
+ // PDF-point edge (y1), because PDF y grows upward from the bottom.
265
+ top: (hPts - y1) * sy,
266
+ height: (y1 - y0) * sy
267
+ };
268
+ }
269
+
270
+ // src/composites/document-field-extraction/fieldLabels.ts
271
+ var LABEL_DISPLAY = {
272
+ "employer identification number": "Employer ID (EIN)",
273
+ "company or business name": "Company Name",
274
+ "total revenue": "Total Revenue",
275
+ "net income": "Net Income",
276
+ "tax year": "Tax Year",
277
+ "invoice number": "Invoice Number",
278
+ "invoice date": "Invoice Date",
279
+ "total amount due": "Total Amount Due",
280
+ "vendor name": "Vendor Name",
281
+ "receipt total": "Receipt Total",
282
+ "transaction date": "Transaction Date",
283
+ "merchant name": "Merchant Name"
284
+ };
285
+ function prettyLabel(label) {
286
+ var _a;
287
+ return (_a = LABEL_DISPLAY[label]) != null ? _a : label.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
288
+ }
289
+ var TIER_COLORS = {
290
+ green: "#15803d",
291
+ amber: "#f59e0b",
292
+ red: "#dc2626"
293
+ };
294
+ var BADGE_TITLE = {
295
+ SC: "High confidence",
296
+ CN: "Medium confidence",
297
+ AB: "Low confidence",
298
+ SW: "Very low confidence"
299
+ };
300
+ var BADGE_STYLE = {
301
+ SC: { bg: "#dcfce7", fg: "#15803d" },
302
+ CN: { bg: "#eff6ff", fg: "#0364ff" },
303
+ // theme-ok (SECONDARY)
304
+ AB: { bg: "#fff7ed", fg: "#92400e" },
305
+ SW: { bg: "#fef2f2", fg: "#dc2626" }
306
+ };
307
+ var STATE_DOT = {
308
+ ok: "#15803d",
309
+ corrected: "#0364ff",
310
+ // theme-ok (SECONDARY)
311
+ missing: "#dc2626",
312
+ warn: "#f59e0b"
313
+ };
314
+ function hexToRgba(hex, alpha) {
315
+ const h = hex.replace("#", "");
316
+ const r = parseInt(h.slice(0, 2), 16);
317
+ const g = parseInt(h.slice(2, 4), 16);
318
+ const b = parseInt(h.slice(4, 6), 16);
319
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
320
+ }
321
+ function badgeStyle(f) {
322
+ var _a, _b;
323
+ return (_b = BADGE_STYLE[(_a = f.badge) != null ? _a : ""]) != null ? _b : { bg: "#f6f6f6", fg: "#777777" };
324
+ }
325
+ function dotColor(f) {
326
+ var _a, _b;
327
+ return (_b = STATE_DOT[(_a = f.state) != null ? _a : "ok"]) != null ? _b : "#15803d";
328
+ }
329
+ function fieldColor(f, secondary) {
330
+ var _a, _b;
331
+ if (f.state === "corrected") return secondary;
332
+ return (_b = TIER_COLORS[(_a = f.confidence_tier) != null ? _a : "amber"]) != null ? _b : TIER_COLORS.amber;
333
+ }
334
+ function confidenceLabel(f) {
335
+ var _a;
336
+ if (typeof f.confidence === "number" && !Number.isNaN(f.confidence)) {
337
+ return `${Math.round(f.confidence * 100)}%`;
338
+ }
339
+ return (_a = f.badge) != null ? _a : "\u2014";
340
+ }
341
+ function FieldDetail({
342
+ field,
343
+ selected,
344
+ onSelect,
345
+ onSave,
346
+ correctionCount = 0,
347
+ cardRef
348
+ }) {
349
+ var _a, _b, _c, _d;
350
+ const { BORDER: BORDER2, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
351
+ const [editing, setEditing] = React6.useState(false);
352
+ const [draft, setDraft] = React6.useState("");
353
+ const [saving, setSaving] = React6.useState(false);
354
+ const [saveError, setSaveError] = React6.useState(null);
355
+ const textareaRef = React6.useRef(null);
356
+ const color = fieldColor(field, SECONDARY2);
357
+ const corrected = field.state === "corrected";
358
+ const startEdit = (e) => {
359
+ e.stopPropagation();
360
+ setDraft(field.value || "");
361
+ setSaveError(null);
362
+ setEditing(true);
363
+ setTimeout(() => {
364
+ var _a2, _b2;
365
+ (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
366
+ (_b2 = textareaRef.current) == null ? void 0 : _b2.select();
367
+ }, 0);
368
+ };
369
+ const cancelEdit = (e) => {
370
+ e.stopPropagation();
371
+ setEditing(false);
372
+ setSaveError(null);
373
+ };
374
+ const save = async (e) => {
375
+ var _a2, _b2;
376
+ e.stopPropagation();
377
+ if (!onSave || draft === field.value) {
378
+ setEditing(false);
379
+ return;
380
+ }
381
+ setSaving(true);
382
+ setSaveError(null);
383
+ try {
384
+ await onSave(field.field_key, draft);
385
+ setEditing(false);
386
+ } catch (err) {
387
+ const msg = ((_b2 = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b2.detail) || "Save failed. Try again.";
388
+ setSaveError(msg);
389
+ } finally {
390
+ setSaving(false);
391
+ }
392
+ };
393
+ const handleKeyDown = (e) => {
394
+ if (e.key === "Escape") cancelEdit(e);
395
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) void save(e);
396
+ };
397
+ return /* @__PURE__ */ jsxs(
398
+ "div",
399
+ {
400
+ ref: cardRef,
401
+ "data-testid": "field-card",
402
+ "data-field-key": field.field_key,
403
+ "data-selected": selected ? "true" : "false",
404
+ role: "button",
405
+ tabIndex: 0,
406
+ onClick: () => !editing && onSelect(selected ? null : field.field_key),
407
+ onKeyDown: (e) => {
408
+ if (!editing && e.key === "Enter") onSelect(selected ? null : field.field_key);
409
+ },
410
+ style: {
411
+ display: "flex",
412
+ flexDirection: "column",
413
+ gap: "4px",
414
+ padding: "8px 10px",
415
+ borderRadius: "0.5rem",
416
+ border: `1px solid ${selected ? color : BORDER2}`,
417
+ background: selected ? hexToRgba(color, 0.06) : "white",
418
+ cursor: editing ? "default" : "pointer",
419
+ transition: "background 0.15s, border-color 0.15s"
420
+ },
421
+ children: [
422
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", minWidth: 0 }, children: [
423
+ /* @__PURE__ */ jsx(
424
+ "span",
425
+ {
426
+ title: (_c = (_b = BADGE_TITLE[(_a = field.badge) != null ? _a : ""]) != null ? _b : field.badge) != null ? _c : "",
427
+ style: {
428
+ fontSize: "10px",
429
+ fontWeight: 700,
430
+ padding: "2px 6px",
431
+ borderRadius: "4px",
432
+ flexShrink: 0,
433
+ letterSpacing: "0.02em",
434
+ minWidth: "34px",
435
+ textAlign: "center",
436
+ fontVariantNumeric: "tabular-nums",
437
+ background: badgeStyle(field).bg,
438
+ color: badgeStyle(field).fg
439
+ },
440
+ children: confidenceLabel(field)
441
+ }
442
+ ),
443
+ /* @__PURE__ */ jsx(
444
+ "span",
445
+ {
446
+ title: prettyLabel(field.label),
447
+ style: {
448
+ fontSize: "12.5px",
449
+ fontWeight: 600,
450
+ color: "var(--foreground)",
451
+ flex: 1,
452
+ minWidth: 0,
453
+ whiteSpace: "nowrap",
454
+ overflow: "hidden",
455
+ textOverflow: "ellipsis"
456
+ },
457
+ children: prettyLabel(field.label)
458
+ }
459
+ ),
460
+ field.is_primary && /* @__PURE__ */ jsx(
461
+ "span",
462
+ {
463
+ style: {
464
+ fontSize: "9px",
465
+ fontWeight: 600,
466
+ textTransform: "uppercase",
467
+ letterSpacing: "0.04em",
468
+ color: MUTED2,
469
+ flexShrink: 0
470
+ },
471
+ children: "Primary"
472
+ }
473
+ ),
474
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: "11px", color: MUTED2, flexShrink: 0 }, children: [
475
+ "p.",
476
+ field.page + 1
477
+ ] }),
478
+ !editing && onSave && /* @__PURE__ */ jsx(
479
+ "button",
480
+ {
481
+ type: "button",
482
+ onClick: startEdit,
483
+ title: "Edit value",
484
+ "aria-label": "Edit value",
485
+ style: {
486
+ border: `1px solid ${BORDER2}`,
487
+ borderRadius: "6px",
488
+ background: "white",
489
+ cursor: "pointer",
490
+ padding: "3px 5px",
491
+ lineHeight: 1,
492
+ flexShrink: 0,
493
+ display: "inline-flex",
494
+ alignItems: "center",
495
+ justifyContent: "center"
496
+ },
497
+ children: /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: MUTED2, strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
498
+ /* @__PURE__ */ jsx("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
499
+ /* @__PURE__ */ jsx("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
500
+ ] })
501
+ }
502
+ )
503
+ ] }),
504
+ editing ? /* @__PURE__ */ jsxs("div", { onClick: (e) => e.stopPropagation(), style: { display: "flex", flexDirection: "column", gap: "5px" }, children: [
505
+ /* @__PURE__ */ jsx(
506
+ "textarea",
507
+ {
508
+ ref: textareaRef,
509
+ value: draft,
510
+ onChange: (e) => setDraft(e.target.value),
511
+ onKeyDown: handleKeyDown,
512
+ rows: 3,
513
+ placeholder: "Enter value\u2026",
514
+ style: {
515
+ width: "100%",
516
+ boxSizing: "border-box",
517
+ resize: "vertical",
518
+ fontSize: "13px",
519
+ fontFamily: "var(--font-sans)",
520
+ color: "var(--foreground)",
521
+ padding: "6px 8px",
522
+ borderRadius: "0.4rem",
523
+ border: `1px solid ${BORDER2}`
524
+ }
525
+ }
526
+ ),
527
+ saveError && /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: TIER_COLORS.red }, children: saveError }),
528
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "6px" }, children: [
529
+ /* @__PURE__ */ jsx(
530
+ "button",
531
+ {
532
+ type: "button",
533
+ onClick: save,
534
+ disabled: saving,
535
+ title: "Save (\u2318\u21B5)",
536
+ style: {
537
+ display: "inline-flex",
538
+ alignItems: "center",
539
+ gap: "4px",
540
+ fontSize: "11px",
541
+ fontWeight: 600,
542
+ padding: "4px 10px",
543
+ borderRadius: "0.4rem",
544
+ border: "none",
545
+ background: "var(--foreground)",
546
+ color: "white",
547
+ cursor: saving ? "default" : "pointer",
548
+ opacity: saving ? 0.7 : 1
549
+ },
550
+ children: saving ? "Saving\u2026" : "Save"
551
+ }
552
+ ),
553
+ /* @__PURE__ */ jsx(
554
+ "button",
555
+ {
556
+ type: "button",
557
+ onClick: cancelEdit,
558
+ disabled: saving,
559
+ title: "Cancel (Esc)",
560
+ style: {
561
+ fontSize: "11px",
562
+ fontWeight: 600,
563
+ padding: "4px 10px",
564
+ borderRadius: "0.4rem",
565
+ border: `1px solid ${BORDER2}`,
566
+ background: "white",
567
+ color: MUTED2,
568
+ cursor: saving ? "default" : "pointer"
569
+ },
570
+ children: "Cancel"
571
+ }
572
+ )
573
+ ] })
574
+ ] }) : corrected ? /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "2px", paddingLeft: "2px" }, children: [
575
+ field.previous_value != null && field.previous_value !== "" && /* @__PURE__ */ jsx(
576
+ "span",
577
+ {
578
+ style: {
579
+ fontSize: "11.5px",
580
+ color: MUTED2,
581
+ textDecoration: "line-through",
582
+ fontFamily: "ui-monospace, 'Cascadia Code', monospace",
583
+ wordBreak: "break-word"
584
+ },
585
+ children: field.previous_value
586
+ }
587
+ ),
588
+ /* @__PURE__ */ jsx(
589
+ "span",
590
+ {
591
+ style: {
592
+ fontSize: "12.5px",
593
+ fontWeight: 600,
594
+ color: "var(--foreground)",
595
+ fontFamily: "ui-monospace, 'Cascadia Code', monospace",
596
+ wordBreak: "break-word"
597
+ },
598
+ children: field.value || "\u2014"
599
+ }
600
+ ),
601
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
602
+ field.corrected_by && /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: SECONDARY2 }, title: `Corrected by ${field.corrected_by}`, children: field.corrected_by }),
603
+ correctionCount > 0 && /* @__PURE__ */ jsxs(
604
+ "span",
605
+ {
606
+ style: {
607
+ fontSize: "10.5px",
608
+ fontWeight: 600,
609
+ color: MUTED2,
610
+ background: PAPER2,
611
+ borderRadius: "9999px",
612
+ padding: "1px 7px"
613
+ },
614
+ children: [
615
+ correctionCount,
616
+ " ",
617
+ correctionCount === 1 ? "event" : "events"
618
+ ]
619
+ }
620
+ )
621
+ ] })
622
+ ] }) : (
623
+ // Bottom row: monospace value + right-edge validation dot (file explorer).
624
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", paddingLeft: "2px" }, children: [
625
+ /* @__PURE__ */ jsx(
626
+ "span",
627
+ {
628
+ style: {
629
+ fontSize: "12.5px",
630
+ color: MUTED2,
631
+ fontFamily: "ui-monospace, 'Cascadia Code', monospace",
632
+ flex: 1,
633
+ minWidth: 0,
634
+ whiteSpace: "nowrap",
635
+ overflow: "hidden",
636
+ textOverflow: "ellipsis"
637
+ },
638
+ title: field.value || "\u2014",
639
+ children: field.value || "\u2014"
640
+ }
641
+ ),
642
+ /* @__PURE__ */ jsx(
643
+ "span",
644
+ {
645
+ title: (_d = field.state) != null ? _d : "ok",
646
+ style: {
647
+ width: "8px",
648
+ height: "8px",
649
+ borderRadius: "9999px",
650
+ flexShrink: 0,
651
+ background: dotColor(field)
652
+ }
653
+ }
654
+ )
655
+ ] })
656
+ )
657
+ ]
658
+ }
659
+ );
660
+ }
661
+ var BADGE_DOT = {
662
+ // gen-ui semantic dot colors
663
+ ok: "#15803d",
664
+ green: "#15803d",
665
+ warn: "#f59e0b",
666
+ amber: "#f59e0b",
667
+ missing: "#dc2626",
668
+ red: "#dc2626",
669
+ corrected: "#0364ff"
670
+ // theme-ok (SECONDARY)
671
+ };
672
+ function FieldDetails({
673
+ summary,
674
+ fileName,
675
+ pageCount,
676
+ pagesProcessed
677
+ }) {
678
+ var _a, _b, _c, _d, _e, _f;
679
+ const { BORDER: BORDER2, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
680
+ if (!summary) {
681
+ return /* @__PURE__ */ jsxs(
682
+ "div",
683
+ {
684
+ style: {
685
+ height: "100%",
686
+ display: "flex",
687
+ flexDirection: "column",
688
+ alignItems: "center",
689
+ justifyContent: "center",
690
+ gap: "6px",
691
+ color: MUTED2,
692
+ textAlign: "center",
693
+ padding: "24px"
694
+ },
695
+ children: [
696
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "26px", lineHeight: 1 }, children: "\u{1F4C4}" }),
697
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "14px", fontWeight: 600, color: "var(--foreground)" }, children: "No summary yet" }),
698
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", maxWidth: "280px" }, children: "This document has no extracted summary." })
699
+ ]
700
+ }
701
+ );
702
+ }
703
+ const header = buildHeader(summary);
704
+ const crumb = buildCrumbLine(summary);
705
+ const facts = buildFacts(summary, fileName, pageCount, pagesProcessed);
706
+ return /* @__PURE__ */ jsx("div", { style: { height: "100%", overflowY: "auto", paddingRight: "4px" }, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "14px" }, children: [
707
+ /* @__PURE__ */ jsxs("header", { style: { display: "flex", flexDirection: "column", gap: "3px" }, children: [
708
+ /* @__PURE__ */ jsx(
709
+ "h2",
710
+ {
711
+ title: header.title,
712
+ style: {
713
+ margin: 0,
714
+ fontFamily: "var(--font-serif)",
715
+ fontSize: "20px",
716
+ fontWeight: 400,
717
+ letterSpacing: "-0.01em",
718
+ color: "var(--foreground)",
719
+ overflow: "hidden",
720
+ textOverflow: "ellipsis",
721
+ whiteSpace: "nowrap"
722
+ },
723
+ children: header.title
724
+ }
725
+ ),
726
+ header.subtitle && /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", color: MUTED2 }, children: header.subtitle })
727
+ ] }),
728
+ (summary.domain || summary.display_name || summary.domain_group || ((_b = (_a = summary.tags) == null ? void 0 : _a.length) != null ? _b : 0) > 0) && /* @__PURE__ */ jsxs(
729
+ "section",
730
+ {
731
+ style: {
732
+ display: "flex",
733
+ flexDirection: "column",
734
+ gap: "6px",
735
+ padding: "12px 14px",
736
+ borderRadius: "0.75rem",
737
+ border: `1px solid ${BORDER2}`,
738
+ background: PAPER2
739
+ },
740
+ children: [
741
+ summary.domain_group && /* @__PURE__ */ jsx(
742
+ "span",
743
+ {
744
+ style: {
745
+ fontSize: "10px",
746
+ fontWeight: 600,
747
+ textTransform: "uppercase",
748
+ letterSpacing: "0.06em",
749
+ color: MUTED2
750
+ },
751
+ children: summary.domain_group
752
+ }
753
+ ),
754
+ /* @__PURE__ */ jsx(
755
+ "h3",
756
+ {
757
+ style: {
758
+ margin: 0,
759
+ fontSize: "14px",
760
+ fontWeight: 600,
761
+ color: "var(--foreground)"
762
+ },
763
+ children: summary.domain || summary.display_name
764
+ }
765
+ ),
766
+ crumb && /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", color: MUTED2 }, children: crumb }),
767
+ ((_d = (_c = summary.tags) == null ? void 0 : _c.length) != null ? _d : 0) > 0 && /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "5px", marginTop: "2px" }, children: summary.tags.map((t) => /* @__PURE__ */ jsx(
768
+ "span",
769
+ {
770
+ style: {
771
+ fontSize: "10px",
772
+ fontWeight: 600,
773
+ padding: "2px 8px",
774
+ borderRadius: "9999px",
775
+ background: "white",
776
+ border: `1px solid ${BORDER2}`,
777
+ color: MUTED2
778
+ },
779
+ children: t
780
+ },
781
+ t
782
+ )) })
783
+ ]
784
+ }
785
+ ),
786
+ ((_f = (_e = summary.stats) == null ? void 0 : _e.length) != null ? _f : 0) > 0 && /* @__PURE__ */ jsx(
787
+ "div",
788
+ {
789
+ style: {
790
+ display: "grid",
791
+ gridTemplateColumns: "repeat(auto-fit, minmax(130px, 1fr))",
792
+ gap: "8px"
793
+ },
794
+ children: summary.stats.map((s) => /* @__PURE__ */ jsxs(
795
+ "div",
796
+ {
797
+ style: {
798
+ display: "flex",
799
+ flexDirection: "column",
800
+ gap: "2px",
801
+ padding: "10px 12px",
802
+ borderRadius: "0.6rem",
803
+ border: `1px solid ${BORDER2}`,
804
+ background: "white"
805
+ },
806
+ children: [
807
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: MUTED2 }, children: s.label }),
808
+ /* @__PURE__ */ jsx(
809
+ "span",
810
+ {
811
+ title: s.value,
812
+ style: {
813
+ fontSize: "15px",
814
+ fontWeight: 600,
815
+ color: "var(--foreground)",
816
+ overflow: "hidden",
817
+ textOverflow: "ellipsis",
818
+ whiteSpace: "nowrap"
819
+ },
820
+ children: s.value
821
+ }
822
+ ),
823
+ s.caption && /* @__PURE__ */ jsx("span", { style: { fontSize: "10px", color: MUTED2 }, children: s.caption })
824
+ ]
825
+ },
826
+ s.field_key
827
+ ))
828
+ }
829
+ ),
830
+ facts.length > 0 && /* @__PURE__ */ jsxs("section", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
831
+ /* @__PURE__ */ jsxs(
832
+ "div",
833
+ {
834
+ style: {
835
+ display: "flex",
836
+ alignItems: "center",
837
+ gap: "6px",
838
+ fontSize: "11px",
839
+ fontWeight: 600,
840
+ textTransform: "uppercase",
841
+ letterSpacing: "0.04em",
842
+ color: MUTED2
843
+ },
844
+ children: [
845
+ /* @__PURE__ */ jsx("span", { children: "\u25A4" }),
846
+ /* @__PURE__ */ jsx("span", { children: "Document details" })
847
+ ]
848
+ }
849
+ ),
850
+ /* @__PURE__ */ jsx(
851
+ "dl",
852
+ {
853
+ style: {
854
+ margin: 0,
855
+ display: "grid",
856
+ gridTemplateColumns: "minmax(110px, auto) 1fr",
857
+ rowGap: "6px",
858
+ columnGap: "14px"
859
+ },
860
+ children: facts.map((f) => {
861
+ var _a2;
862
+ return /* @__PURE__ */ jsxs(React6.Fragment, { children: [
863
+ /* @__PURE__ */ jsx("dt", { style: { fontSize: "12px", color: MUTED2 }, children: f.label }),
864
+ /* @__PURE__ */ jsxs(
865
+ "dd",
866
+ {
867
+ title: typeof f.value === "string" ? f.value : void 0,
868
+ style: {
869
+ margin: 0,
870
+ fontSize: "12px",
871
+ color: "var(--foreground)",
872
+ display: "flex",
873
+ alignItems: "center",
874
+ gap: "6px",
875
+ wordBreak: "break-word"
876
+ },
877
+ children: [
878
+ f.badge && /* @__PURE__ */ jsx(
879
+ "span",
880
+ {
881
+ style: {
882
+ width: "7px",
883
+ height: "7px",
884
+ borderRadius: "9999px",
885
+ flexShrink: 0,
886
+ background: (_a2 = BADGE_DOT[f.badge]) != null ? _a2 : SECONDARY2
887
+ }
888
+ }
889
+ ),
890
+ f.value
891
+ ]
892
+ }
893
+ )
894
+ ] }, f.key);
895
+ })
896
+ }
897
+ )
898
+ ] })
899
+ ] }) });
900
+ }
901
+ function buildHeader(summary) {
902
+ const form = [summary.short_name, summary.display_name].filter(Boolean);
903
+ const title = summary.organization || form.shift() || summary.domain || "Document";
904
+ const parts = summary.organization ? [...form] : form;
905
+ if (summary.tax_year) parts.push(`TY ${summary.tax_year}`);
906
+ return { title, subtitle: parts.join(" \xB7 ") };
907
+ }
908
+ function buildCrumbLine(summary) {
909
+ const parts = [...summary.crumbs || [], summary.short_name].filter(Boolean);
910
+ if (parts.length > 0) return parts.join(" \xB7 ");
911
+ return summary.domain && summary.display_name ? summary.display_name : "";
912
+ }
913
+ function buildFacts(summary, fileName, pageCount, pagesProcessed) {
914
+ const rows = [];
915
+ if (fileName) rows.push({ key: "file", label: "File", value: fileName });
916
+ if (summary.display_name) {
917
+ rows.push({ key: "doctype", label: "Document type", value: summary.display_name });
918
+ }
919
+ if (summary.tax_year != null && summary.tax_year !== "") {
920
+ rows.push({ key: "year", label: "Tax year", value: String(summary.tax_year) });
921
+ }
922
+ for (const f of summary.facts || []) {
923
+ rows.push({ key: f.field_key, label: f.label, value: f.value, badge: f.badge });
924
+ }
925
+ if (pageCount) {
926
+ rows.push({
927
+ key: "pages",
928
+ label: "Pages processed",
929
+ value: `${pagesProcessed != null ? pagesProcessed : pageCount} / ${pageCount}`
930
+ });
931
+ }
932
+ return rows;
933
+ }
934
+ function initials(name) {
935
+ return name.trim().split(/\s+/).slice(0, 2).map((w) => {
936
+ var _a;
937
+ return ((_a = w[0]) != null ? _a : "").toUpperCase();
938
+ }).join("");
939
+ }
940
+ function formatTs(ts) {
941
+ if (!ts) return "\u2014";
942
+ const d = new Date(ts);
943
+ if (Number.isNaN(d.getTime())) return ts;
944
+ return d.toLocaleString(void 0, {
945
+ month: "short",
946
+ day: "numeric",
947
+ hour: "2-digit",
948
+ minute: "2-digit"
949
+ });
950
+ }
951
+ function FieldAuditLog({
952
+ events = [],
953
+ loading = false,
954
+ fields = []
955
+ }) {
956
+ const { BORDER: BORDER2, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
957
+ const fieldLabelMap = React6.useMemo(() => {
958
+ var _a;
959
+ const map = {};
960
+ for (const f of fields) map[f.field_key] = (_a = f.label) != null ? _a : f.field_key;
961
+ return map;
962
+ }, [fields]);
963
+ if (loading) {
964
+ return /* @__PURE__ */ jsx(
965
+ "div",
966
+ {
967
+ style: {
968
+ flex: 1,
969
+ display: "flex",
970
+ alignItems: "center",
971
+ justifyContent: "center",
972
+ padding: "32px 20px",
973
+ fontSize: "13px",
974
+ color: MUTED2
975
+ },
976
+ children: "Loading audit trail\u2026"
977
+ }
978
+ );
979
+ }
980
+ if (events.length === 0) {
981
+ return /* @__PURE__ */ jsxs(
982
+ "div",
983
+ {
984
+ style: {
985
+ flex: 1,
986
+ display: "flex",
987
+ flexDirection: "column",
988
+ alignItems: "center",
989
+ justifyContent: "center",
990
+ gap: "6px",
991
+ padding: "32px 20px",
992
+ textAlign: "center"
993
+ },
994
+ children: [
995
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "13.5px", fontWeight: 600, color: "var(--foreground)" }, children: "No changes yet" }),
996
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", color: MUTED2, maxWidth: "240px", lineHeight: 1.5 }, children: "Field corrections will appear here." })
997
+ ]
998
+ }
999
+ );
1000
+ }
1001
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", flex: 1, minHeight: 0, overflow: "hidden" }, children: [
1002
+ /* @__PURE__ */ jsx("div", { style: { padding: "8px 14px 6px", flexShrink: 0 }, children: /* @__PURE__ */ jsxs(
1003
+ "span",
1004
+ {
1005
+ style: {
1006
+ fontSize: "11.5px",
1007
+ fontWeight: 600,
1008
+ color: MUTED2,
1009
+ textTransform: "uppercase",
1010
+ letterSpacing: "0.04em"
1011
+ },
1012
+ children: [
1013
+ events.length,
1014
+ " ",
1015
+ events.length === 1 ? "change" : "changes"
1016
+ ]
1017
+ }
1018
+ ) }),
1019
+ /* @__PURE__ */ jsx("ol", { style: { listStyle: "none", margin: 0, padding: "0 0 16px", overflowY: "auto", flex: 1, minHeight: 0 }, children: events.map((ev) => {
1020
+ var _a, _b;
1021
+ const rawLabel = (_a = fieldLabelMap[ev.field_key]) != null ? _a : ev.field_key;
1022
+ const label = prettyLabel(rawLabel);
1023
+ const isAI = ev.actor_type === "system" || ev.event_type === "ai_corrected" || ev.event_type === "ai_extracted";
1024
+ const actor = isAI ? "AI" : ev.actor_name || "Unknown";
1025
+ const eventLabel = isAI ? "Re-extracted" : "Corrected";
1026
+ return /* @__PURE__ */ jsxs(
1027
+ "li",
1028
+ {
1029
+ "data-testid": "audit-row",
1030
+ style: { display: "flex", gap: "10px", padding: "10px 14px", borderBottom: `1px solid ${BORDER2}` },
1031
+ children: [
1032
+ /* @__PURE__ */ jsx(
1033
+ "div",
1034
+ {
1035
+ title: isAI ? "AI extraction" : actor,
1036
+ style: {
1037
+ flexShrink: 0,
1038
+ width: "28px",
1039
+ height: "28px",
1040
+ borderRadius: "50%",
1041
+ background: isAI ? "#dcfce7" : "#eff6ff",
1042
+ color: isAI ? "#15803d" : SECONDARY2,
1043
+ fontSize: "10.5px",
1044
+ fontWeight: 700,
1045
+ display: "flex",
1046
+ alignItems: "center",
1047
+ justifyContent: "center",
1048
+ marginTop: "1px"
1049
+ },
1050
+ children: isAI ? "\u2728" : initials(actor)
1051
+ }
1052
+ ),
1053
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "3px", flex: 1, minWidth: 0 }, children: [
1054
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: "6px", flexWrap: "wrap" }, children: [
1055
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "12.5px", fontWeight: 600, color: isAI ? "#15803d" : "var(--foreground)" }, children: actor }),
1056
+ /* @__PURE__ */ jsx(
1057
+ "span",
1058
+ {
1059
+ style: {
1060
+ fontSize: "10.5px",
1061
+ fontWeight: 600,
1062
+ color: MUTED2,
1063
+ background: PAPER2,
1064
+ borderRadius: "4px",
1065
+ padding: "1px 6px",
1066
+ whiteSpace: "nowrap",
1067
+ flexShrink: 0
1068
+ },
1069
+ children: eventLabel
1070
+ }
1071
+ ),
1072
+ /* @__PURE__ */ jsx(
1073
+ "span",
1074
+ {
1075
+ style: {
1076
+ fontSize: "12px",
1077
+ color: MUTED2,
1078
+ flex: 1,
1079
+ minWidth: 0,
1080
+ whiteSpace: "nowrap",
1081
+ overflow: "hidden",
1082
+ textOverflow: "ellipsis"
1083
+ },
1084
+ children: label
1085
+ }
1086
+ ),
1087
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: MUTED2, flexShrink: 0 }, children: formatTs(ev.created_at) })
1088
+ ] }),
1089
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
1090
+ ev.previous_value != null && /* @__PURE__ */ jsxs(Fragment, { children: [
1091
+ /* @__PURE__ */ jsx(
1092
+ "span",
1093
+ {
1094
+ style: {
1095
+ fontSize: "12px",
1096
+ fontFamily: "ui-monospace, monospace",
1097
+ color: MUTED2,
1098
+ textDecoration: "line-through"
1099
+ },
1100
+ children: ev.previous_value
1101
+ }
1102
+ ),
1103
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: BORDER2 }, children: "\u2192" })
1104
+ ] }),
1105
+ /* @__PURE__ */ jsx(
1106
+ "span",
1107
+ {
1108
+ style: {
1109
+ fontSize: "12px",
1110
+ fontFamily: "ui-monospace, monospace",
1111
+ fontWeight: 600,
1112
+ color: "var(--foreground)"
1113
+ },
1114
+ children: (_b = ev.new_value) != null ? _b : "\u2014"
1115
+ }
1116
+ )
1117
+ ] }),
1118
+ ev.reason && /* @__PURE__ */ jsxs("p", { style: { margin: "2px 0 0", fontSize: "11.5px", color: MUTED2, fontStyle: "italic" }, children: [
1119
+ "\u201C",
1120
+ ev.reason,
1121
+ "\u201D"
1122
+ ] })
1123
+ ] })
1124
+ ]
1125
+ },
1126
+ ev.id
1127
+ );
1128
+ }) })
1129
+ ] });
1130
+ }
1131
+ var TIER_COLORS2 = {
1132
+ green: "#15803d",
1133
+ amber: "#f59e0b",
1134
+ red: "#dc2626"
1135
+ };
1136
+ function fieldColor2(f, secondary) {
1137
+ var _a, _b;
1138
+ if (f.state === "corrected") return secondary;
1139
+ return (_b = TIER_COLORS2[(_a = f.confidence_tier) != null ? _a : "amber"]) != null ? _b : TIER_COLORS2.amber;
1140
+ }
1141
+ function hexToRgba2(hex, alpha) {
1142
+ const h = hex.replace("#", "");
1143
+ const r = parseInt(h.slice(0, 2), 16);
1144
+ const g = parseInt(h.slice(2, 4), 16);
1145
+ const b = parseInt(h.slice(4, 6), 16);
1146
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
1147
+ }
1148
+ function PageOverlay({
1149
+ page,
1150
+ fields,
1151
+ selectedKey,
1152
+ onSelect,
1153
+ secondary
1154
+ }) {
1155
+ const { PAPER: PAPER2, MUTED: MUTED2 } = useTheme();
1156
+ const imgRef = React6.useRef(null);
1157
+ const selectedBoxRef = React6.useRef(null);
1158
+ const [px, setPx] = React6.useState(null);
1159
+ React6.useEffect(() => {
1160
+ const el = imgRef.current;
1161
+ if (!el) return;
1162
+ const measure = () => {
1163
+ if (el.clientWidth && el.clientHeight) {
1164
+ setPx({ wPx: el.clientWidth, hPx: el.clientHeight });
1165
+ }
1166
+ };
1167
+ measure();
1168
+ if (typeof ResizeObserver === "undefined") return;
1169
+ const ro = new ResizeObserver(measure);
1170
+ ro.observe(el);
1171
+ return () => ro.disconnect();
1172
+ }, [page.imageUrl]);
1173
+ React6.useEffect(() => {
1174
+ if (!selectedKey) return;
1175
+ if (!fields.some((f) => f.field_key === selectedKey && f.bbox)) return;
1176
+ const el = selectedBoxRef.current;
1177
+ if (el && typeof el.scrollIntoView === "function") {
1178
+ el.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
1179
+ }
1180
+ }, [selectedKey, fields, px]);
1181
+ const pagePts = { wPts: page.width_pt, hPts: page.height_pt };
1182
+ return /* @__PURE__ */ jsxs("div", { style: { position: "relative", width: "100%", lineHeight: 0 }, children: [
1183
+ page.imageUrl ? /* @__PURE__ */ jsx(
1184
+ "img",
1185
+ {
1186
+ ref: imgRef,
1187
+ src: page.imageUrl,
1188
+ alt: `Page ${page.page + 1}`,
1189
+ onLoad: () => {
1190
+ const el = imgRef.current;
1191
+ if (el && el.clientWidth && el.clientHeight) {
1192
+ setPx({ wPx: el.clientWidth, hPx: el.clientHeight });
1193
+ }
1194
+ },
1195
+ style: { display: "block", width: "100%", height: "auto" }
1196
+ }
1197
+ ) : (
1198
+ // No resolved image (host couldn't resolve the raster) — keep the
1199
+ // aspect box so cards still make sense, but show nothing to overlay on.
1200
+ /* @__PURE__ */ jsxs(
1201
+ "div",
1202
+ {
1203
+ style: {
1204
+ width: "100%",
1205
+ aspectRatio: `${page.width_pt} / ${page.height_pt}`,
1206
+ background: PAPER2,
1207
+ display: "flex",
1208
+ alignItems: "center",
1209
+ justifyContent: "center",
1210
+ fontSize: "12px",
1211
+ color: MUTED2,
1212
+ lineHeight: 1.4
1213
+ },
1214
+ children: [
1215
+ "Page ",
1216
+ page.page + 1,
1217
+ " image unavailable"
1218
+ ]
1219
+ }
1220
+ )
1221
+ ),
1222
+ px && page.imageUrl && fields.map((f) => {
1223
+ var _a;
1224
+ const rect = bboxToRect((_a = f.bbox) != null ? _a : null, pagePts, px);
1225
+ if (!rect) return null;
1226
+ const color = fieldColor2(f, secondary);
1227
+ const selected = selectedKey === f.field_key;
1228
+ return /* @__PURE__ */ jsx(
1229
+ "div",
1230
+ {
1231
+ ref: selected ? selectedBoxRef : null,
1232
+ "data-testid": "bbox-rect",
1233
+ "data-field-key": f.field_key,
1234
+ "data-selected": selected ? "true" : "false",
1235
+ onClick: () => onSelect(selected ? null : f.field_key),
1236
+ title: `${f.label}: ${f.value}`,
1237
+ style: {
1238
+ position: "absolute",
1239
+ left: `${rect.left}px`,
1240
+ top: `${rect.top}px`,
1241
+ width: `${rect.width}px`,
1242
+ height: `${rect.height}px`,
1243
+ border: `1px solid ${color}`,
1244
+ background: hexToRgba2(color, selected ? 0.28 : 0.12),
1245
+ boxShadow: selected ? `0 0 0 2px ${hexToRgba2(color, 0.5)}` : "none",
1246
+ borderRadius: "2px",
1247
+ cursor: "pointer",
1248
+ transition: "background 0.15s, box-shadow 0.15s"
1249
+ }
1250
+ },
1251
+ f.field_key
1252
+ );
1253
+ })
1254
+ ] });
1255
+ }
1256
+ function ExtractionDetail({
1257
+ pages,
1258
+ orderedFields,
1259
+ fieldsByPage,
1260
+ selectedKey,
1261
+ setSelectedKey,
1262
+ onFieldSave,
1263
+ correctionCounts,
1264
+ tab,
1265
+ setTab,
1266
+ editable,
1267
+ summary,
1268
+ fileName,
1269
+ pageCount,
1270
+ pagesProcessed,
1271
+ auditEvents,
1272
+ auditLoading
1273
+ }) {
1274
+ const { BORDER: BORDER2, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
1275
+ const selectedCardRef = React6.useRef(null);
1276
+ React6.useEffect(() => {
1277
+ if (!selectedKey || tab !== "fields") return;
1278
+ const el = selectedCardRef.current;
1279
+ if (el && typeof el.scrollIntoView === "function") {
1280
+ el.scrollIntoView({ behavior: "smooth", block: "nearest" });
1281
+ }
1282
+ }, [selectedKey, tab]);
1283
+ const tabs = [
1284
+ { key: "details", label: "Details" },
1285
+ { key: "fields", label: "Fields", count: orderedFields.length }
1286
+ ];
1287
+ if (editable) tabs.push({ key: "audit", label: "Audit Trails", count: (auditEvents == null ? void 0 : auditEvents.length) || void 0 });
1288
+ return /* @__PURE__ */ jsxs(
1289
+ "div",
1290
+ {
1291
+ style: {
1292
+ display: "grid",
1293
+ gridTemplateColumns: "minmax(0, 3fr) minmax(260px, 1fr)",
1294
+ gap: "12px",
1295
+ height: "100%",
1296
+ minHeight: 0
1297
+ },
1298
+ children: [
1299
+ /* @__PURE__ */ jsx(
1300
+ "div",
1301
+ {
1302
+ style: {
1303
+ display: "flex",
1304
+ flexDirection: "column",
1305
+ gap: "10px",
1306
+ borderRadius: "0.75rem",
1307
+ border: `1px solid ${BORDER2}`,
1308
+ overflowY: "auto",
1309
+ minHeight: 0
1310
+ },
1311
+ children: pages.map((pg) => /* @__PURE__ */ jsx(
1312
+ PageOverlay,
1313
+ {
1314
+ page: pg,
1315
+ fields: fieldsByPage(pg.page),
1316
+ selectedKey,
1317
+ onSelect: (key) => {
1318
+ setSelectedKey(key);
1319
+ if (key) setTab("fields");
1320
+ },
1321
+ secondary: SECONDARY2
1322
+ },
1323
+ pg.page
1324
+ ))
1325
+ }
1326
+ ),
1327
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", minWidth: 0, minHeight: 0 }, children: [
1328
+ /* @__PURE__ */ jsx(
1329
+ "div",
1330
+ {
1331
+ style: {
1332
+ display: "flex",
1333
+ gap: "16px",
1334
+ borderBottom: `1px solid ${BORDER2}`,
1335
+ flexShrink: 0,
1336
+ marginBottom: "10px"
1337
+ },
1338
+ children: tabs.map((t) => {
1339
+ const active = tab === t.key;
1340
+ return /* @__PURE__ */ jsxs(
1341
+ "button",
1342
+ {
1343
+ type: "button",
1344
+ onClick: () => setTab(t.key),
1345
+ "data-testid": `tab-${t.key}`,
1346
+ style: {
1347
+ appearance: "none",
1348
+ background: "transparent",
1349
+ borderTop: "none",
1350
+ borderLeft: "none",
1351
+ borderRight: "none",
1352
+ borderBottom: `2px solid ${active ? SECONDARY2 : "transparent"}`,
1353
+ padding: "6px 2px",
1354
+ marginBottom: "-1px",
1355
+ cursor: "pointer",
1356
+ fontSize: "13px",
1357
+ fontWeight: 600,
1358
+ color: active ? SECONDARY2 : MUTED2,
1359
+ display: "inline-flex",
1360
+ alignItems: "center",
1361
+ gap: "6px"
1362
+ },
1363
+ children: [
1364
+ t.label,
1365
+ typeof t.count === "number" && /* @__PURE__ */ jsx(
1366
+ "span",
1367
+ {
1368
+ style: {
1369
+ fontSize: "11px",
1370
+ fontWeight: 600,
1371
+ padding: "1px 7px",
1372
+ borderRadius: "9999px",
1373
+ background: active ? "#eff6ff" : PAPER2,
1374
+ color: active ? SECONDARY2 : MUTED2
1375
+ },
1376
+ children: t.count
1377
+ }
1378
+ )
1379
+ ]
1380
+ },
1381
+ t.key
1382
+ );
1383
+ })
1384
+ }
1385
+ ),
1386
+ tab === "details" ? /* @__PURE__ */ jsx(
1387
+ FieldDetails,
1388
+ {
1389
+ summary,
1390
+ fileName,
1391
+ pageCount,
1392
+ pagesProcessed
1393
+ }
1394
+ ) : tab === "audit" ? /* @__PURE__ */ jsx("div", { style: { minHeight: 0, overflowY: "auto" }, children: /* @__PURE__ */ jsx(
1395
+ FieldAuditLog,
1396
+ {
1397
+ events: auditEvents != null ? auditEvents : [],
1398
+ loading: auditLoading != null ? auditLoading : false,
1399
+ fields: orderedFields.map((f) => ({ field_key: f.field_key, label: f.label }))
1400
+ }
1401
+ ) }) : /* @__PURE__ */ jsxs(
1402
+ "div",
1403
+ {
1404
+ style: {
1405
+ display: "flex",
1406
+ flexDirection: "column",
1407
+ minHeight: 0,
1408
+ overflowY: "auto",
1409
+ paddingRight: "4px"
1410
+ },
1411
+ children: [
1412
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: "12px", color: MUTED2, padding: "0 0 8px 2px", flexShrink: 0 }, children: [
1413
+ orderedFields.length,
1414
+ " extracted"
1415
+ ] }),
1416
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: orderedFields.map((f) => {
1417
+ var _a;
1418
+ const selected = selectedKey === f.field_key;
1419
+ return /* @__PURE__ */ jsx(
1420
+ FieldDetail,
1421
+ {
1422
+ field: f,
1423
+ selected,
1424
+ onSelect: setSelectedKey,
1425
+ onSave: onFieldSave,
1426
+ correctionCount: (_a = correctionCounts == null ? void 0 : correctionCounts[f.field_key]) != null ? _a : 0,
1427
+ cardRef: selected ? selectedCardRef : void 0
1428
+ },
1429
+ f.field_key
1430
+ );
1431
+ }) })
1432
+ ]
1433
+ }
1434
+ )
1435
+ ] })
1436
+ ]
1437
+ }
1438
+ );
1439
+ }
1440
+ function ExtractionModal({
1441
+ open,
1442
+ onClose,
1443
+ title,
1444
+ children
1445
+ }) {
1446
+ const { BORDER: BORDER2, MUTED: MUTED2 } = useTheme();
1447
+ React6.useEffect(() => {
1448
+ if (!open) return;
1449
+ const onKey = (e) => {
1450
+ if (e.key === "Escape") onClose();
1451
+ };
1452
+ window.addEventListener("keydown", onKey);
1453
+ const prev = document.body.style.overflow;
1454
+ document.body.style.overflow = "hidden";
1455
+ return () => {
1456
+ window.removeEventListener("keydown", onKey);
1457
+ document.body.style.overflow = prev;
1458
+ };
1459
+ }, [open, onClose]);
1460
+ if (!open || typeof document === "undefined") return null;
1461
+ return createPortal(
1462
+ /* @__PURE__ */ jsx(
1463
+ "div",
1464
+ {
1465
+ role: "dialog",
1466
+ "aria-modal": "true",
1467
+ "aria-label": title,
1468
+ onClick: onClose,
1469
+ style: {
1470
+ position: "fixed",
1471
+ inset: 0,
1472
+ zIndex: 2147483e3,
1473
+ background: "rgba(0,0,0,0.5)",
1474
+ display: "flex",
1475
+ alignItems: "center",
1476
+ justifyContent: "center",
1477
+ padding: "4vh 4vw",
1478
+ backdropFilter: "blur(2px)"
1479
+ },
1480
+ children: /* @__PURE__ */ jsxs(
1481
+ "div",
1482
+ {
1483
+ onClick: (e) => e.stopPropagation(),
1484
+ style: {
1485
+ width: "90vw",
1486
+ height: "90vh",
1487
+ background: "white",
1488
+ borderRadius: "0.875rem",
1489
+ border: `1px solid ${BORDER2}`,
1490
+ boxShadow: "0 20px 60px rgba(0,0,0,0.30)",
1491
+ display: "flex",
1492
+ flexDirection: "column",
1493
+ overflow: "hidden"
1494
+ },
1495
+ children: [
1496
+ /* @__PURE__ */ jsxs(
1497
+ "div",
1498
+ {
1499
+ style: {
1500
+ display: "flex",
1501
+ alignItems: "center",
1502
+ gap: "10px",
1503
+ padding: "11px 16px",
1504
+ borderBottom: `1px solid ${BORDER2}`,
1505
+ flexShrink: 0
1506
+ },
1507
+ children: [
1508
+ /* @__PURE__ */ jsx(
1509
+ "span",
1510
+ {
1511
+ style: {
1512
+ flex: 1,
1513
+ minWidth: 0,
1514
+ fontFamily: "var(--font-serif)",
1515
+ fontSize: "16px",
1516
+ fontWeight: 400,
1517
+ letterSpacing: "-0.01em",
1518
+ color: "var(--foreground)",
1519
+ overflow: "hidden",
1520
+ textOverflow: "ellipsis",
1521
+ whiteSpace: "nowrap"
1522
+ },
1523
+ children: title
1524
+ }
1525
+ ),
1526
+ /* @__PURE__ */ jsx(
1527
+ "button",
1528
+ {
1529
+ type: "button",
1530
+ "aria-label": "Close",
1531
+ onClick: onClose,
1532
+ style: {
1533
+ border: `1px solid ${BORDER2}`,
1534
+ borderRadius: "8px",
1535
+ background: "white",
1536
+ cursor: "pointer",
1537
+ padding: "5px 9px",
1538
+ fontSize: "13px",
1539
+ color: MUTED2,
1540
+ lineHeight: 1
1541
+ },
1542
+ children: "\u2715"
1543
+ }
1544
+ )
1545
+ ]
1546
+ }
1547
+ ),
1548
+ /* @__PURE__ */ jsx(
1549
+ "div",
1550
+ {
1551
+ style: {
1552
+ flex: 1,
1553
+ minHeight: 0,
1554
+ overflow: "hidden",
1555
+ display: "flex",
1556
+ flexDirection: "column",
1557
+ padding: "14px 16px"
1558
+ },
1559
+ children
1560
+ }
1561
+ )
1562
+ ]
1563
+ }
1564
+ )
1565
+ }
1566
+ ),
1567
+ document.body
1568
+ );
1569
+ }
1570
+ function DocumentFieldExtractionResolver(p) {
1571
+ var _a, _b;
1572
+ const { BORDER: BORDER2, MUTED: MUTED2, PAPER: PAPER2 } = useTheme();
1573
+ const [selectedKey, setSelectedKey] = React6.useState(null);
1574
+ const [open, setOpen] = React6.useState(false);
1575
+ const [tab, setTab] = React6.useState("fields");
1576
+ const pages = (_a = p.pages) != null ? _a : [];
1577
+ const fields = (_b = p.fields) != null ? _b : [];
1578
+ const editable = typeof p.onFieldSave === "function";
1579
+ const onLoadAudit = p.onLoadAudit;
1580
+ React6.useEffect(() => {
1581
+ if (tab === "audit" && onLoadAudit) {
1582
+ onLoadAudit();
1583
+ }
1584
+ }, [tab, onLoadAudit]);
1585
+ const correctionCounts = React6.useMemo(() => {
1586
+ var _a2, _b2;
1587
+ const counts = {};
1588
+ for (const ev of (_a2 = p.auditEvents) != null ? _a2 : []) {
1589
+ const human = ev.actor_type !== "system" && ev.event_type !== "ai_extracted";
1590
+ if (human) counts[ev.field_key] = ((_b2 = counts[ev.field_key]) != null ? _b2 : 0) + 1;
1591
+ }
1592
+ return counts;
1593
+ }, [p.auditEvents]);
1594
+ const orderedFields = [...fields].sort((a, b) => {
1595
+ var _a2, _b2;
1596
+ if (!!a.is_primary !== !!b.is_primary) return a.is_primary ? -1 : 1;
1597
+ return ((_a2 = b.confidence) != null ? _a2 : 0) - ((_b2 = a.confidence) != null ? _b2 : 0);
1598
+ });
1599
+ const fieldsByPage = (pageNo) => fields.filter((f) => f.page === pageNo);
1600
+ const csvCols = [
1601
+ { key: "label", label: "Field" },
1602
+ { key: "value", label: "Value" },
1603
+ { key: "page", label: "Page" },
1604
+ { key: "confidence", label: "Confidence" },
1605
+ { key: "badge", label: "Badge" },
1606
+ { key: "state", label: "State" }
1607
+ ];
1608
+ const csvRows = orderedFields.map((f) => {
1609
+ var _a2, _b2, _c;
1610
+ return {
1611
+ label: f.label,
1612
+ value: f.value,
1613
+ page: f.page + 1,
1614
+ confidence: (_a2 = f.confidence) != null ? _a2 : "",
1615
+ badge: (_b2 = f.badge) != null ? _b2 : "",
1616
+ state: (_c = f.state) != null ? _c : ""
1617
+ };
1618
+ });
1619
+ const title = p.file_name || (p.doc_type ? `${p.doc_type} \u2014 extracted fields` : "Extracted fields");
1620
+ const tierCounts = fields.reduce(
1621
+ (acc, f) => {
1622
+ var _a2;
1623
+ const t = (_a2 = f.confidence_tier) != null ? _a2 : "amber";
1624
+ if (t === "green") acc.high += 1;
1625
+ else if (t === "red") acc.low += 1;
1626
+ else acc.med += 1;
1627
+ return acc;
1628
+ },
1629
+ { high: 0, med: 0, low: 0 }
1630
+ );
1631
+ const chips = [
1632
+ { n: tierCounts.high, label: "high", color: TIER_COLORS2.green },
1633
+ { n: tierCounts.med, label: "medium", color: TIER_COLORS2.amber },
1634
+ { n: tierCounts.low, label: "low", color: TIER_COLORS2.red }
1635
+ ].filter((c) => c.n > 0);
1636
+ const thumb = pages.find((pg) => pg.imageUrl);
1637
+ return /* @__PURE__ */ jsxs(
1638
+ ComponentActions,
1639
+ {
1640
+ filename: "document-fields",
1641
+ onDownloadCSV: () => downloadCSV(csvCols, csvRows, "document-fields"),
1642
+ children: [
1643
+ /* @__PURE__ */ jsxs(
1644
+ "div",
1645
+ {
1646
+ role: "button",
1647
+ tabIndex: 0,
1648
+ onClick: () => setOpen(true),
1649
+ onKeyDown: (e) => {
1650
+ if (e.key === "Enter" || e.key === " ") {
1651
+ e.preventDefault();
1652
+ setOpen(true);
1653
+ }
1654
+ },
1655
+ style: {
1656
+ display: "flex",
1657
+ alignItems: "stretch",
1658
+ gap: "12px",
1659
+ padding: "12px",
1660
+ width: "100%",
1661
+ maxWidth: "440px",
1662
+ borderRadius: "0.75rem",
1663
+ border: `1px solid ${BORDER2}`,
1664
+ background: "white",
1665
+ cursor: "pointer",
1666
+ textAlign: "left",
1667
+ boxShadow: "0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.05)"
1668
+ },
1669
+ children: [
1670
+ /* @__PURE__ */ jsx(
1671
+ "div",
1672
+ {
1673
+ style: {
1674
+ width: "64px",
1675
+ flexShrink: 0,
1676
+ borderRadius: "0.5rem",
1677
+ border: `1px solid ${BORDER2}`,
1678
+ background: PAPER2,
1679
+ overflow: "hidden",
1680
+ display: "flex",
1681
+ alignItems: "center",
1682
+ justifyContent: "center"
1683
+ },
1684
+ children: (thumb == null ? void 0 : thumb.imageUrl) ? /* @__PURE__ */ jsx(
1685
+ "img",
1686
+ {
1687
+ src: thumb.imageUrl,
1688
+ alt: "Document preview",
1689
+ style: { width: "100%", height: "auto", display: "block" }
1690
+ }
1691
+ ) : /* @__PURE__ */ jsx("span", { style: { fontSize: "22px", lineHeight: 1, padding: "16px 0" }, children: "\u{1F4C4}" })
1692
+ }
1693
+ ),
1694
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "6px" }, children: [
1695
+ /* @__PURE__ */ jsx(
1696
+ "p",
1697
+ {
1698
+ style: {
1699
+ fontFamily: "var(--font-serif)",
1700
+ fontSize: "15px",
1701
+ fontWeight: 400,
1702
+ color: "var(--foreground)",
1703
+ letterSpacing: "-0.01em",
1704
+ margin: 0,
1705
+ overflow: "hidden",
1706
+ textOverflow: "ellipsis",
1707
+ whiteSpace: "nowrap"
1708
+ },
1709
+ children: p.file_name || p.doc_type || "Document"
1710
+ }
1711
+ ),
1712
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: "12px", color: MUTED2 }, children: [
1713
+ fields.length,
1714
+ " field",
1715
+ fields.length === 1 ? "" : "s",
1716
+ " extracted \xB7 ",
1717
+ pages.length,
1718
+ " page",
1719
+ pages.length === 1 ? "" : "s"
1720
+ ] }),
1721
+ chips.length > 0 && /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "5px" }, children: chips.map((c) => /* @__PURE__ */ jsxs(
1722
+ "span",
1723
+ {
1724
+ style: {
1725
+ display: "inline-flex",
1726
+ alignItems: "center",
1727
+ gap: "4px",
1728
+ fontSize: "10px",
1729
+ fontWeight: 600,
1730
+ padding: "2px 7px",
1731
+ borderRadius: "9999px",
1732
+ background: hexToRgba2(c.color, 0.12),
1733
+ color: c.color
1734
+ },
1735
+ children: [
1736
+ /* @__PURE__ */ jsx(
1737
+ "span",
1738
+ {
1739
+ style: {
1740
+ width: "6px",
1741
+ height: "6px",
1742
+ borderRadius: "9999px",
1743
+ background: c.color
1744
+ }
1745
+ }
1746
+ ),
1747
+ c.n,
1748
+ " ",
1749
+ c.label
1750
+ ]
1751
+ },
1752
+ c.label
1753
+ )) }),
1754
+ /* @__PURE__ */ jsx(
1755
+ "span",
1756
+ {
1757
+ style: {
1758
+ marginTop: "2px",
1759
+ alignSelf: "flex-start",
1760
+ fontSize: "12px",
1761
+ fontWeight: 600,
1762
+ padding: "6px 12px",
1763
+ borderRadius: "0.5rem",
1764
+ background: "var(--foreground)",
1765
+ color: "white"
1766
+ },
1767
+ children: "View & edit fields"
1768
+ }
1769
+ )
1770
+ ] })
1771
+ ]
1772
+ }
1773
+ ),
1774
+ /* @__PURE__ */ jsx(ExtractionModal, { open, onClose: () => setOpen(false), title, children: /* @__PURE__ */ jsx(
1775
+ ExtractionDetail,
1776
+ {
1777
+ pages,
1778
+ orderedFields,
1779
+ fieldsByPage,
1780
+ selectedKey,
1781
+ setSelectedKey,
1782
+ onFieldSave: p.onFieldSave,
1783
+ correctionCounts,
1784
+ tab,
1785
+ setTab,
1786
+ editable,
1787
+ summary: p.summary,
1788
+ fileName: p.file_name,
1789
+ pageCount: p.page_count,
1790
+ pagesProcessed: p.pages_processed,
1791
+ auditEvents: p.auditEvents,
1792
+ auditLoading: p.auditLoading
1793
+ }
1794
+ ) })
1795
+ ]
1796
+ }
1797
+ );
1798
+ }
1799
+ function DocumentFieldExtractionSkeleton() {
1800
+ const { BORDER: BORDER2, PAPER: PAPER2 } = useTheme();
1801
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1802
+ /* @__PURE__ */ jsx("style", { children: `
1803
+ @keyframes dfeSkeletonPulse {
1804
+ 0%, 100% { opacity: 1; }
1805
+ 50% { opacity: 0.45; }
1806
+ }
1807
+ ` }),
1808
+ /* @__PURE__ */ jsxs(
1809
+ "div",
1810
+ {
1811
+ "aria-busy": "true",
1812
+ "aria-label": "Loading extracted document",
1813
+ style: {
1814
+ display: "flex",
1815
+ alignItems: "stretch",
1816
+ gap: "12px",
1817
+ padding: "12px",
1818
+ width: "100%",
1819
+ maxWidth: "440px",
1820
+ borderRadius: "0.75rem",
1821
+ border: `1px solid ${BORDER2}`,
1822
+ background: "white",
1823
+ boxShadow: "0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.05)"
1824
+ },
1825
+ children: [
1826
+ /* @__PURE__ */ jsx(
1827
+ "div",
1828
+ {
1829
+ style: {
1830
+ width: "64px",
1831
+ flexShrink: 0,
1832
+ borderRadius: "0.5rem",
1833
+ border: `1px solid ${BORDER2}`,
1834
+ background: PAPER2,
1835
+ minHeight: "82px",
1836
+ animation: "dfeSkeletonPulse 1.6s ease-in-out infinite"
1837
+ }
1838
+ }
1839
+ ),
1840
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "8px", paddingTop: "2px" }, children: [
1841
+ /* @__PURE__ */ jsx(
1842
+ "div",
1843
+ {
1844
+ style: {
1845
+ height: "14px",
1846
+ width: "65%",
1847
+ borderRadius: "4px",
1848
+ background: PAPER2,
1849
+ animation: "dfeSkeletonPulse 1.6s ease-in-out 0.08s infinite"
1850
+ }
1851
+ }
1852
+ ),
1853
+ /* @__PURE__ */ jsx(
1854
+ "div",
1855
+ {
1856
+ style: {
1857
+ height: "11px",
1858
+ width: "45%",
1859
+ borderRadius: "4px",
1860
+ background: PAPER2,
1861
+ animation: "dfeSkeletonPulse 1.6s ease-in-out 0.14s infinite"
1862
+ }
1863
+ }
1864
+ ),
1865
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "5px" }, children: [
1866
+ /* @__PURE__ */ jsx(
1867
+ "div",
1868
+ {
1869
+ style: {
1870
+ height: "18px",
1871
+ width: "66px",
1872
+ borderRadius: "9999px",
1873
+ background: PAPER2,
1874
+ animation: "dfeSkeletonPulse 1.6s ease-in-out 0.2s infinite"
1875
+ }
1876
+ }
1877
+ ),
1878
+ /* @__PURE__ */ jsx(
1879
+ "div",
1880
+ {
1881
+ style: {
1882
+ height: "18px",
1883
+ width: "56px",
1884
+ borderRadius: "9999px",
1885
+ background: PAPER2,
1886
+ animation: "dfeSkeletonPulse 1.6s ease-in-out 0.25s infinite"
1887
+ }
1888
+ }
1889
+ )
1890
+ ] }),
1891
+ /* @__PURE__ */ jsx(
1892
+ "div",
1893
+ {
1894
+ style: {
1895
+ height: "28px",
1896
+ width: "122px",
1897
+ borderRadius: "0.5rem",
1898
+ background: PAPER2,
1899
+ marginTop: "2px",
1900
+ animation: "dfeSkeletonPulse 1.6s ease-in-out 0.3s infinite"
1901
+ }
1902
+ }
1903
+ )
1904
+ ] })
1905
+ ]
1906
+ }
1907
+ )
1908
+ ] });
1909
+ }
1910
+
1911
+ export { DocumentFieldExtractionResolver, DocumentFieldExtractionSkeleton };
1912
+ //# sourceMappingURL=resolver.js.map
1913
+ //# sourceMappingURL=resolver.js.map