@adoptai/genui-components 0.1.58 → 0.1.59

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