@adoptai/genui-components 0.1.57 → 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 (56) hide show
  1. package/dist/composites/document-field-extraction/FieldAuditLog.d.ts +27 -0
  2. package/dist/composites/document-field-extraction/FieldAuditLog.d.ts.map +1 -0
  3. package/dist/composites/document-field-extraction/FieldDetail.d.ts +22 -0
  4. package/dist/composites/document-field-extraction/FieldDetail.d.ts.map +1 -0
  5. package/dist/composites/document-field-extraction/FieldDetails.d.ts +18 -0
  6. package/dist/composites/document-field-extraction/FieldDetails.d.ts.map +1 -0
  7. package/dist/composites/document-field-extraction/bboxTransform.d.ts +25 -0
  8. package/dist/composites/document-field-extraction/bboxTransform.d.ts.map +1 -0
  9. package/dist/composites/document-field-extraction/fieldLabels.d.ts +2 -0
  10. package/dist/composites/document-field-extraction/fieldLabels.d.ts.map +1 -0
  11. package/dist/composites/document-field-extraction/resolver.cjs +1920 -0
  12. package/dist/composites/document-field-extraction/resolver.cjs.map +1 -0
  13. package/dist/composites/document-field-extraction/resolver.d.ts +16 -0
  14. package/dist/composites/document-field-extraction/resolver.d.ts.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 +2661 -345
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.ts +5 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +2456 -144
  33. package/dist/index.js.map +1 -1
  34. package/dist/renderer.cjs +2482 -281
  35. package/dist/renderer.cjs.map +1 -1
  36. package/dist/renderer.js +2339 -138
  37. package/dist/renderer.js.map +1 -1
  38. package/dist/resolver.cjs +2481 -280
  39. package/dist/resolver.cjs.map +1 -1
  40. package/dist/resolver.d.ts.map +1 -1
  41. package/dist/resolver.js +2339 -138
  42. package/dist/resolver.js.map +1 -1
  43. package/dist/schemas/document-field-extraction.d.ts +258 -0
  44. package/dist/schemas/document-field-extraction.d.ts.map +1 -0
  45. package/dist/schemas/index.cjs +262 -3
  46. package/dist/schemas/index.cjs.map +1 -1
  47. package/dist/schemas/index.d.ts +376 -0
  48. package/dist/schemas/index.d.ts.map +1 -1
  49. package/dist/schemas/index.js +262 -3
  50. package/dist/schemas/index.js.map +1 -1
  51. package/dist/schemas/tabby-auth.d.ts +58 -0
  52. package/dist/schemas/tabby-auth.d.ts.map +1 -0
  53. package/dist/schemas/workflow-stepper.d.ts +60 -0
  54. package/dist/schemas/workflow-stepper.d.ts.map +1 -1
  55. package/dist/tool-definitions.json +326 -3
  56. package/package.json +1 -1
package/dist/resolver.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var React41 = require('react');
4
+ var React45 = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var dagre = require('@dagrejs/dagre');
7
7
  var reactDom = require('react-dom');
@@ -37,7 +37,7 @@ function _interopNamespace(e) {
37
37
  return Object.freeze(n);
38
38
  }
39
39
 
40
- var React41__default = /*#__PURE__*/_interopDefault(React41);
40
+ var React45__default = /*#__PURE__*/_interopDefault(React45);
41
41
  var dagre__default = /*#__PURE__*/_interopDefault(dagre);
42
42
  var XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
43
43
  var Papa__default = /*#__PURE__*/_interopDefault(Papa);
@@ -111,7 +111,7 @@ var init_theme = __esm({
111
111
  }
112
112
  });
113
113
  function useTheme() {
114
- return React41.useContext(GenUIThemeContext);
114
+ return React45.useContext(GenUIThemeContext);
115
115
  }
116
116
  var DEFAULT_TOKENS, GenUIThemeContext;
117
117
  var init_ThemeContext = __esm({
@@ -127,7 +127,7 @@ var init_ThemeContext = __esm({
127
127
  SECONDARY,
128
128
  CHART_PALETTE: [...CHART_PALETTE]
129
129
  };
130
- GenUIThemeContext = React41.createContext(DEFAULT_TOKENS);
130
+ GenUIThemeContext = React45.createContext(DEFAULT_TOKENS);
131
131
  }
132
132
  });
133
133
  function renderInline(text) {
@@ -857,11 +857,11 @@ async function getMermaid(t) {
857
857
  }
858
858
  function MermaidFallback({ diagram, title }) {
859
859
  const tokens = useTheme();
860
- const [svg, setSvg] = React41.useState("");
861
- const [err, setErr] = React41.useState(false);
862
- const [full, setFull] = React41.useState(false);
863
- const idRef = React41.useRef(0);
864
- React41.useEffect(() => {
860
+ const [svg, setSvg] = React45.useState("");
861
+ const [err, setErr] = React45.useState(false);
862
+ const [full, setFull] = React45.useState(false);
863
+ const idRef = React45.useRef(0);
864
+ React45.useEffect(() => {
865
865
  const id = ++renderSeq;
866
866
  idRef.current = id;
867
867
  setErr(false);
@@ -930,7 +930,7 @@ function FullscreenModalInner({ nodes, edges, title, onClose }) {
930
930
  ] }) });
931
931
  }
932
932
  function FullscreenModal({ nodes, edges, title, onClose }) {
933
- React41.useEffect(() => {
933
+ React45.useEffect(() => {
934
934
  const h = (e) => {
935
935
  if (e.key === "Escape") onClose();
936
936
  };
@@ -943,8 +943,8 @@ function FullscreenModal({ nodes, edges, title, onClose }) {
943
943
  );
944
944
  }
945
945
  function usePrefersReducedMotion() {
946
- const [reduced, setReduced] = React41.useState(false);
947
- React41.useEffect(() => {
946
+ const [reduced, setReduced] = React45.useState(false);
947
+ React45.useEffect(() => {
948
948
  var _a;
949
949
  if (typeof matchMedia === "undefined") return;
950
950
  const mq = matchMedia("(prefers-reduced-motion: reduce)");
@@ -988,9 +988,9 @@ function topoOrder(nodeIds, edges) {
988
988
  }
989
989
  function useAutoplay(order, enabled) {
990
990
  const reduced = usePrefersReducedMotion();
991
- const [step, setStep] = React41.useState(0);
991
+ const [step, setStep] = React45.useState(0);
992
992
  const key = order.join("|");
993
- React41.useEffect(() => {
993
+ React45.useEffect(() => {
994
994
  if (!enabled || reduced || order.length === 0) {
995
995
  setStep(0);
996
996
  return;
@@ -1012,7 +1012,7 @@ function useAutoplay(order, enabled) {
1012
1012
  timer = setTimeout(tick, 850);
1013
1013
  return () => clearTimeout(timer);
1014
1014
  }, [enabled, reduced, key]);
1015
- return React41.useMemo(() => {
1015
+ return React45.useMemo(() => {
1016
1016
  const m = {};
1017
1017
  order.forEach((id, i) => {
1018
1018
  m[id] = i < step ? "done" : i === step ? "active" : "pending";
@@ -1034,13 +1034,13 @@ function resolveStates(nodes, nodeStates) {
1034
1034
  }
1035
1035
  function Inner({ diagram, title, autoplay, nodeStates }) {
1036
1036
  const tokens = useTheme();
1037
- const [full, setFull] = React41.useState(false);
1038
- const [focused, setFocused] = React41.useState(false);
1039
- const [boxW, setBoxW] = React41.useState(640);
1040
- const containerRef = React41.useRef(null);
1041
- const parsed = React41.useMemo(() => parseMermaidFlow(diagram), [diagram]);
1042
- const layout = React41.useMemo(() => parsed ? computeLayout(parsed) : null, [parsed]);
1043
- const themedEdges = React41.useMemo(
1037
+ const [full, setFull] = React45.useState(false);
1038
+ const [focused, setFocused] = React45.useState(false);
1039
+ const [boxW, setBoxW] = React45.useState(640);
1040
+ const containerRef = React45.useRef(null);
1041
+ const parsed = React45.useMemo(() => parseMermaidFlow(diagram), [diagram]);
1042
+ const layout = React45.useMemo(() => parsed ? computeLayout(parsed) : null, [parsed]);
1043
+ const themedEdges = React45.useMemo(
1044
1044
  () => {
1045
1045
  var _a;
1046
1046
  return ((_a = layout == null ? void 0 : layout.edges) != null ? _a : []).map((e) => __spreadProps(__spreadValues({}, e), {
@@ -1052,7 +1052,7 @@ function Inner({ diagram, title, autoplay, nodeStates }) {
1052
1052
  },
1053
1053
  [layout, tokens.ACCENT, tokens.MUTED]
1054
1054
  );
1055
- const order = React41.useMemo(
1055
+ const order = React45.useMemo(
1056
1056
  () => {
1057
1057
  var _a, _b;
1058
1058
  return topoOrder(((_a = layout == null ? void 0 : layout.nodes) != null ? _a : []).map((n) => n.id), (_b = layout == null ? void 0 : layout.edges) != null ? _b : []);
@@ -1060,19 +1060,19 @@ function Inner({ diagram, title, autoplay, nodeStates }) {
1060
1060
  [layout]
1061
1061
  );
1062
1062
  const autoStatus = useAutoplay(order, !!autoplay);
1063
- const staticStatus = React41.useMemo(() => {
1063
+ const staticStatus = React45.useMemo(() => {
1064
1064
  var _a;
1065
1065
  return resolveStates((_a = layout == null ? void 0 : layout.nodes) != null ? _a : [], nodeStates);
1066
1066
  }, [layout, nodeStates]);
1067
1067
  const statusMap = autoplay ? autoStatus : staticStatus;
1068
- const displayNodes = React41.useMemo(
1068
+ const displayNodes = React45.useMemo(
1069
1069
  () => {
1070
1070
  var _a;
1071
1071
  return ((_a = layout == null ? void 0 : layout.nodes) != null ? _a : []).map((n) => __spreadProps(__spreadValues({}, n), { data: __spreadProps(__spreadValues({}, n.data), { status: statusMap[n.id] }) }));
1072
1072
  },
1073
1073
  [layout, statusMap]
1074
1074
  );
1075
- const displayEdges = React41.useMemo(
1075
+ const displayEdges = React45.useMemo(
1076
1076
  () => themedEdges.map((e) => {
1077
1077
  const ss = statusMap[e.source];
1078
1078
  const ts = statusMap[e.target];
@@ -1092,13 +1092,13 @@ function Inner({ diagram, title, autoplay, nodeStates }) {
1092
1092
  const [nodes, setNodes, onNC] = react.useNodesState(displayNodes);
1093
1093
  const [edges, setEdges, onEC] = react.useEdgesState(displayEdges);
1094
1094
  const rf = react.useReactFlow();
1095
- React41.useEffect(() => {
1095
+ React45.useEffect(() => {
1096
1096
  setNodes(displayNodes);
1097
1097
  }, [displayNodes, setNodes]);
1098
- React41.useEffect(() => {
1098
+ React45.useEffect(() => {
1099
1099
  setEdges(displayEdges);
1100
1100
  }, [displayEdges, setEdges]);
1101
- React41.useEffect(() => {
1101
+ React45.useEffect(() => {
1102
1102
  const id = requestAnimationFrame(() => {
1103
1103
  try {
1104
1104
  rf.fitView({ padding: 0.1 });
@@ -1107,14 +1107,14 @@ function Inner({ diagram, title, autoplay, nodeStates }) {
1107
1107
  });
1108
1108
  return () => cancelAnimationFrame(id);
1109
1109
  }, [layout, rf]);
1110
- const handleClickOutside = React41.useCallback((e) => {
1110
+ const handleClickOutside = React45.useCallback((e) => {
1111
1111
  if (containerRef.current && !containerRef.current.contains(e.target)) setFocused(false);
1112
1112
  }, []);
1113
- React41.useEffect(() => {
1113
+ React45.useEffect(() => {
1114
1114
  document.addEventListener("mousedown", handleClickOutside);
1115
1115
  return () => document.removeEventListener("mousedown", handleClickOutside);
1116
1116
  }, [handleClickOutside]);
1117
- React41.useEffect(() => {
1117
+ React45.useEffect(() => {
1118
1118
  const el = containerRef.current;
1119
1119
  if (!el) return;
1120
1120
  let raf = 0;
@@ -1273,15 +1273,15 @@ __export(PdfViewer_exports, {
1273
1273
  PdfViewer: () => PdfViewer
1274
1274
  });
1275
1275
  function PdfViewer({ url, base64, onLoadSuccess }) {
1276
- const [numPages, setNumPages] = React41.useState(0);
1277
- const [currentPage, setCurrentPage] = React41.useState(1);
1278
- const [loading, setLoading] = React41.useState(true);
1279
- const handleLoad = React41.useCallback(({ numPages: n }) => {
1276
+ const [numPages, setNumPages] = React45.useState(0);
1277
+ const [currentPage, setCurrentPage] = React45.useState(1);
1278
+ const [loading, setLoading] = React45.useState(true);
1279
+ const handleLoad = React45.useCallback(({ numPages: n }) => {
1280
1280
  setNumPages(n);
1281
1281
  setLoading(false);
1282
1282
  onLoadSuccess == null ? void 0 : onLoadSuccess(n);
1283
1283
  }, [onLoadSuccess]);
1284
- React41.useEffect(() => {
1284
+ React45.useEffect(() => {
1285
1285
  if (numPages <= 1) return;
1286
1286
  const handler = (e) => {
1287
1287
  var _a;
@@ -1377,13 +1377,13 @@ __export(ExcelViewer_exports, {
1377
1377
  ExcelViewer: () => ExcelViewer
1378
1378
  });
1379
1379
  function ExcelViewer({ url, base64, onLoadSuccess }) {
1380
- const [sheetNames, setSheetNames] = React41.useState([]);
1381
- const [activeSheet, setActiveSheet] = React41.useState(0);
1382
- const [data, setData] = React41.useState([]);
1383
- const [loading, setLoading] = React41.useState(true);
1384
- const [error, setError] = React41.useState(null);
1385
- const wbRef = React41.useRef(null);
1386
- React41.useEffect(() => {
1380
+ const [sheetNames, setSheetNames] = React45.useState([]);
1381
+ const [activeSheet, setActiveSheet] = React45.useState(0);
1382
+ const [data, setData] = React45.useState([]);
1383
+ const [loading, setLoading] = React45.useState(true);
1384
+ const [error, setError] = React45.useState(null);
1385
+ const wbRef = React45.useRef(null);
1386
+ React45.useEffect(() => {
1387
1387
  let cancelled = false;
1388
1388
  setLoading(true);
1389
1389
  setError(null);
@@ -1441,7 +1441,7 @@ function ExcelViewer({ url, base64, onLoadSuccess }) {
1441
1441
  const rows = XLSX__namespace.utils.sheet_to_json(wbRef.current.Sheets[wbRef.current.SheetNames[idx]], { header: 1 });
1442
1442
  setData(rows);
1443
1443
  };
1444
- React41.useEffect(() => {
1444
+ React45.useEffect(() => {
1445
1445
  if (sheetNames.length <= 1) return;
1446
1446
  const handler = (e) => {
1447
1447
  var _a;
@@ -1566,10 +1566,10 @@ __export(CsvViewer_exports, {
1566
1566
  });
1567
1567
  function CsvViewer({ url, base64, delimiter, maxRows }) {
1568
1568
  const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2 } = useTheme();
1569
- const [rows, setRows] = React41.useState([]);
1570
- const [loading, setLoading] = React41.useState(true);
1571
- const [error, setError] = React41.useState(null);
1572
- React41.useEffect(() => {
1569
+ const [rows, setRows] = React45.useState([]);
1570
+ const [loading, setLoading] = React45.useState(true);
1571
+ const [error, setError] = React45.useState(null);
1572
+ React45.useEffect(() => {
1573
1573
  let cancelled = false;
1574
1574
  setLoading(true);
1575
1575
  setError(null);
@@ -1688,10 +1688,10 @@ __export(TextViewer_exports, {
1688
1688
  });
1689
1689
  function TextViewer({ url, base64, markdown = false, maxLines }) {
1690
1690
  const { MUTED: MUTED2 } = useTheme();
1691
- const [text, setText] = React41.useState("");
1692
- const [loading, setLoading] = React41.useState(true);
1693
- const [error, setError] = React41.useState(null);
1694
- React41.useEffect(() => {
1691
+ const [text, setText] = React45.useState("");
1692
+ const [loading, setLoading] = React45.useState(true);
1693
+ const [error, setError] = React45.useState(null);
1694
+ React45.useEffect(() => {
1695
1695
  let cancelled = false;
1696
1696
  setLoading(true);
1697
1697
  setError(null);
@@ -1789,10 +1789,10 @@ function sanitize(html) {
1789
1789
  }
1790
1790
  function DocxViewer({ url, base64 }) {
1791
1791
  const { MUTED: MUTED2, BORDER: BORDER4 } = useTheme();
1792
- const [html, setHtml] = React41.useState("");
1793
- const [loading, setLoading] = React41.useState(true);
1794
- const [error, setError] = React41.useState(null);
1795
- React41.useEffect(() => {
1792
+ const [html, setHtml] = React45.useState("");
1793
+ const [loading, setLoading] = React45.useState(true);
1794
+ const [error, setError] = React45.useState(null);
1795
+ React45.useEffect(() => {
1796
1796
  let cancelled = false;
1797
1797
  setLoading(true);
1798
1798
  setError(null);
@@ -5245,7 +5245,32 @@ var workflowStepperSchema = zod.z.object({
5245
5245
  n: zod.z.number().int().positive().optional(),
5246
5246
  title: zod.z.string(),
5247
5247
  sub: zod.z.string().optional(),
5248
- status: zod.z.enum(["done", "active", "review", "pending", "blocked", "failed"]),
5248
+ status: zod.z.enum([
5249
+ "done",
5250
+ "active",
5251
+ "running",
5252
+ "review",
5253
+ "pending",
5254
+ "blocked",
5255
+ "failed"
5256
+ ]),
5257
+ // Optional quality-gate verdict for a step run by an executor (e.g. a
5258
+ // pipeline). Surfaces a subtle trust badge; flags hint at issues a human
5259
+ // should review (the full list lives in the escalation dock).
5260
+ eval: zod.z.object({
5261
+ score: zod.z.number().min(0).max(1).nullable().optional(),
5262
+ verdict: zod.z.enum(["good", "bad"]).optional(),
5263
+ reasoning: zod.z.string().optional(),
5264
+ judge_ok: zod.z.boolean().optional(),
5265
+ data_quality_flags: zod.z.array(
5266
+ zod.z.object({
5267
+ field: zod.z.string().optional(),
5268
+ issue: zod.z.string().optional(),
5269
+ severity: zod.z.enum(["low", "medium", "high"]).optional(),
5270
+ details: zod.z.string().optional()
5271
+ })
5272
+ ).optional()
5273
+ }).optional(),
5249
5274
  assignees: zod.z.array(
5250
5275
  zod.z.object({
5251
5276
  name: zod.z.string(),
@@ -5281,7 +5306,32 @@ var workflowStepperTool = {
5281
5306
  n: { type: "number", description: "Step number; defaults to index + 1" },
5282
5307
  title: { type: "string" },
5283
5308
  sub: { type: "string", description: "Short status caption, e.g. '7 accounts \xB7 2 exceptions'" },
5284
- status: { type: "string", enum: ["done", "active", "review", "pending", "blocked", "failed"] },
5309
+ status: {
5310
+ type: "string",
5311
+ enum: ["done", "active", "running", "review", "pending", "blocked", "failed"]
5312
+ },
5313
+ eval: {
5314
+ type: "object",
5315
+ description: "Optional quality-gate verdict for an executor-run step.",
5316
+ properties: {
5317
+ score: { type: "number" },
5318
+ verdict: { type: "string", enum: ["good", "bad"] },
5319
+ reasoning: { type: "string" },
5320
+ judge_ok: { type: "boolean" },
5321
+ data_quality_flags: {
5322
+ type: "array",
5323
+ items: {
5324
+ type: "object",
5325
+ properties: {
5326
+ field: { type: "string" },
5327
+ issue: { type: "string" },
5328
+ severity: { type: "string", enum: ["low", "medium", "high"] },
5329
+ details: { type: "string" }
5330
+ }
5331
+ }
5332
+ }
5333
+ }
5334
+ },
5285
5335
  assignees: {
5286
5336
  type: "array",
5287
5337
  maxItems: 6,
@@ -5305,6 +5355,183 @@ var workflowStepperTool = {
5305
5355
  required: ["type", "title", "steps"]
5306
5356
  }
5307
5357
  };
5358
+ var bbox = zod.z.tuple([zod.z.number(), zod.z.number(), zod.z.number(), zod.z.number()]);
5359
+ var fieldSchema = zod.z.object({
5360
+ field_key: zod.z.string(),
5361
+ label: zod.z.string(),
5362
+ value: zod.z.string(),
5363
+ page: zod.z.number(),
5364
+ // 0-indexed, matches PageDimension.page
5365
+ bbox: bbox.nullable().optional(),
5366
+ confidence: zod.z.number().optional(),
5367
+ confidence_tier: zod.z.enum(["green", "amber", "red"]).optional(),
5368
+ badge: zod.z.enum(["SC", "CN", "AB", "SW"]).optional(),
5369
+ state: zod.z.enum(["ok", "corrected", "missing", "warn"]).optional(),
5370
+ entity_type: zod.z.string().optional(),
5371
+ is_primary: zod.z.boolean().optional(),
5372
+ // Set after a human correction (extractor output, or an optimistic in-card
5373
+ // edit) so the editable field card can show old → new and who changed it.
5374
+ previous_value: zod.z.string().nullable().optional(),
5375
+ corrected_by: zod.z.string().nullable().optional()
5376
+ });
5377
+ var pageSchema = zod.z.object({
5378
+ page: zod.z.number(),
5379
+ // 0-indexed
5380
+ imageUrl: zod.z.string().optional(),
5381
+ // host-resolved from the durable image_ref
5382
+ width_pt: zod.z.number(),
5383
+ height_pt: zod.z.number()
5384
+ });
5385
+ var summaryStatSchema = zod.z.object({
5386
+ field_key: zod.z.string(),
5387
+ label: zod.z.string(),
5388
+ value: zod.z.string(),
5389
+ caption: zod.z.string().nullable().optional()
5390
+ });
5391
+ var summaryFactSchema = zod.z.object({
5392
+ field_key: zod.z.string(),
5393
+ label: zod.z.string(),
5394
+ value: zod.z.string(),
5395
+ badge: zod.z.string().nullable().optional()
5396
+ });
5397
+ var summarySchema = zod.z.object({
5398
+ display_name: zod.z.string().nullable().optional(),
5399
+ short_name: zod.z.string().nullable().optional(),
5400
+ organization: zod.z.string().nullable().optional(),
5401
+ domain: zod.z.string().nullable().optional(),
5402
+ domain_group: zod.z.string().nullable().optional(),
5403
+ tax_year: zod.z.union([zod.z.string(), zod.z.number()]).nullable().optional(),
5404
+ crumbs: zod.z.array(zod.z.string()).optional(),
5405
+ tags: zod.z.array(zod.z.string()).optional(),
5406
+ stats: zod.z.array(summaryStatSchema).optional(),
5407
+ facts: zod.z.array(summaryFactSchema).optional()
5408
+ });
5409
+ var documentFieldExtractionSchema = zod.z.object({
5410
+ type: zod.z.literal("document-field-extraction"),
5411
+ doc_type: zod.z.string().optional(),
5412
+ // Original uploaded filename (e.g. "2024_gl.pdf"); preferred over doc_type for
5413
+ // the card title since doc_type is often the "generic_fallback" schema name.
5414
+ file_name: zod.z.string().optional(),
5415
+ // Server-side token; resolved by the host into pages/fields before render.
5416
+ payload_ref: zod.z.string().optional(),
5417
+ // Present for persisted workstream docs; absent for pre-existing cards.
5418
+ store_id: zod.z.string().optional(),
5419
+ doc_id: zod.z.string().optional(),
5420
+ pages: zod.z.array(pageSchema).max(100).optional(),
5421
+ fields: zod.z.array(fieldSchema).max(1e3).optional(),
5422
+ // Page-count metadata for the Details tab ("N of M pages extracted").
5423
+ page_count: zod.z.number().optional(),
5424
+ pages_processed: zod.z.number().optional(),
5425
+ // Deterministic document summary for the Details tab.
5426
+ summary: summarySchema.nullable().optional()
5427
+ });
5428
+ var documentFieldExtractionTool = {
5429
+ name: "render_document_field_extraction",
5430
+ description: "Render extracted document fields as an interactive overlay on the page image(s) \u2014 colored bounding boxes per field plus a synced field-card list. Use after the extract_document tool returns; pass the returned payload_ref (the host expands it). For invoices, statements, tax forms, receipts, KYC/loan docs, POs where the user wants to SEE where each value sits on the page.",
5431
+ input_schema: {
5432
+ type: "object",
5433
+ properties: {
5434
+ type: { type: "string", enum: ["document-field-extraction"] },
5435
+ doc_type: { type: "string" },
5436
+ file_name: {
5437
+ type: "string",
5438
+ description: "Original uploaded filename; shown as the card title."
5439
+ },
5440
+ payload_ref: {
5441
+ type: "string",
5442
+ description: "Durable store key returned by extract_document; the GenUI host expands it into pages/fields at render time. Pass this verbatim \u2014 do NOT hand-build pages/fields."
5443
+ },
5444
+ store_id: {
5445
+ type: "string",
5446
+ description: "Docstore store id; present for persisted workstream docs. The host uses this to open the editable viewer."
5447
+ },
5448
+ doc_id: {
5449
+ type: "string",
5450
+ description: "Docstore document id; present for persisted workstream docs. Required for the editable viewer."
5451
+ },
5452
+ pages: {
5453
+ type: "array",
5454
+ items: {
5455
+ type: "object",
5456
+ properties: {
5457
+ page: { type: "number", description: "0-indexed page number" },
5458
+ imageUrl: { type: "string" },
5459
+ width_pt: { type: "number" },
5460
+ height_pt: { type: "number" }
5461
+ },
5462
+ required: ["page", "width_pt", "height_pt"]
5463
+ }
5464
+ },
5465
+ fields: {
5466
+ type: "array",
5467
+ items: {
5468
+ type: "object",
5469
+ properties: {
5470
+ field_key: { type: "string" },
5471
+ label: { type: "string" },
5472
+ value: { type: "string" },
5473
+ page: { type: "number", description: "0-indexed page number" },
5474
+ bbox: {
5475
+ type: "array",
5476
+ items: { type: "number" },
5477
+ description: "[x0,y0,x1,y1] PDF points, origin bottom-left; null if unlocated"
5478
+ },
5479
+ confidence: { type: "number" },
5480
+ confidence_tier: { type: "string", enum: ["green", "amber", "red"] },
5481
+ badge: { type: "string", enum: ["SC", "CN", "AB", "SW"] },
5482
+ state: { type: "string", enum: ["ok", "corrected", "missing", "warn"] },
5483
+ entity_type: { type: "string" },
5484
+ is_primary: { type: "boolean" }
5485
+ },
5486
+ required: ["field_key", "label", "value", "page"]
5487
+ }
5488
+ },
5489
+ page_count: { type: "number" },
5490
+ pages_processed: { type: "number" },
5491
+ summary: {
5492
+ type: "object",
5493
+ description: "Deterministic document summary for the Details tab (display_name, organization, domain, stats, facts, tags). Produced by the extractor \u2014 pass through verbatim.",
5494
+ properties: {
5495
+ display_name: { type: "string" },
5496
+ short_name: { type: "string" },
5497
+ organization: { type: "string" },
5498
+ domain: { type: "string" },
5499
+ domain_group: { type: "string" },
5500
+ tax_year: { type: "string" },
5501
+ crumbs: { type: "array", items: { type: "string" } },
5502
+ tags: { type: "array", items: { type: "string" } },
5503
+ stats: {
5504
+ type: "array",
5505
+ items: {
5506
+ type: "object",
5507
+ properties: {
5508
+ field_key: { type: "string" },
5509
+ label: { type: "string" },
5510
+ value: { type: "string" },
5511
+ caption: { type: "string" }
5512
+ },
5513
+ required: ["field_key", "label", "value"]
5514
+ }
5515
+ },
5516
+ facts: {
5517
+ type: "array",
5518
+ items: {
5519
+ type: "object",
5520
+ properties: {
5521
+ field_key: { type: "string" },
5522
+ label: { type: "string" },
5523
+ value: { type: "string" },
5524
+ badge: { type: "string" }
5525
+ },
5526
+ required: ["field_key", "label", "value"]
5527
+ }
5528
+ }
5529
+ }
5530
+ }
5531
+ },
5532
+ required: ["type"]
5533
+ }
5534
+ };
5308
5535
  var decisionCardSchema = zod.z.object({
5309
5536
  type: zod.z.literal("decision-card"),
5310
5537
  id: zod.z.string().optional(),
@@ -5408,6 +5635,36 @@ var decisionCardTool = {
5408
5635
  required: ["type", "title", "question", "options"]
5409
5636
  }
5410
5637
  };
5638
+ var tabbyAuthSchema = zod.z.object({
5639
+ type: zod.z.literal("tabby-auth"),
5640
+ app: zod.z.string(),
5641
+ url: zod.z.string(),
5642
+ workspace: zod.z.string().optional(),
5643
+ state: zod.z.enum(["pending", "connected"]).optional(),
5644
+ ctaLabel: zod.z.string().optional(),
5645
+ steps: zod.z.array(zod.z.string()).optional(),
5646
+ description: zod.z.string().optional(),
5647
+ iconUrl: zod.z.string().optional()
5648
+ });
5649
+ var tabbyAuthTool = {
5650
+ name: "render_tabby_auth",
5651
+ description: "Render a dedicated, trustworthy sign-in card when a harness skill needs the member to authenticate with a third-party app (e.g. Sage Intacct, Airbnb, an ERP) before a `call_web_api` request can proceed. Use this for the `login_required` path instead of a raw markdown link or a connect-integration card. `app` is the human display name (drives the title context, subtitle, and CTA). `url` is the login/short-link the prominent CTA opens in a new tab. `workspace` adds a subtitle suffix ('{app} \xB7 {workspace} workspace'). `state='pending'` (default) is the first-time connect; `state='connected'` is the verify/re-auth case (session already live) with a green badge and an Open deep-link. `steps` overrides the default numbered instructions; `description` is a one-line intro. The card title ('Authentication required') and the 'Credentials not stored by Adopt' trust footer are hardcoded brand constants \u2014 never supplied here.",
5652
+ input_schema: {
5653
+ type: "object",
5654
+ properties: {
5655
+ type: { type: "string", enum: ["tabby-auth"] },
5656
+ app: { type: "string" },
5657
+ url: { type: "string" },
5658
+ workspace: { type: "string" },
5659
+ state: { type: "string", enum: ["pending", "connected"] },
5660
+ ctaLabel: { type: "string" },
5661
+ steps: { type: "array", items: { type: "string" } },
5662
+ description: { type: "string" },
5663
+ iconUrl: { type: "string" }
5664
+ },
5665
+ required: ["type", "app", "url"]
5666
+ }
5667
+ };
5411
5668
 
5412
5669
  // src/schemas/index.ts
5413
5670
  var schemaRegistry = {
@@ -5468,7 +5725,9 @@ var schemaRegistry = {
5468
5725
  "integrations-list": { schema: integrationsListSchema, tool: integrationsListTool },
5469
5726
  "pipeline-preview": { schema: pipelinePreviewSchema, tool: pipelinePreviewTool },
5470
5727
  "workflow-stepper": { schema: workflowStepperSchema, tool: workflowStepperTool },
5471
- "decision-card": { schema: decisionCardSchema, tool: decisionCardTool }
5728
+ "document-field-extraction": { schema: documentFieldExtractionSchema, tool: documentFieldExtractionTool },
5729
+ "decision-card": { schema: decisionCardSchema, tool: decisionCardTool },
5730
+ "tabby-auth": { schema: tabbyAuthSchema, tool: tabbyAuthTool }
5472
5731
  };
5473
5732
 
5474
5733
  // src/schemas/coercePayload.ts
@@ -5550,16 +5809,16 @@ init_theme();
5550
5809
  var DOT_COLOR = "#aaaaaa";
5551
5810
  var DOT_HOVER = "#555555";
5552
5811
  function ComponentActions({ children, onDownloadCSV, columnConfig, filename = "component" }) {
5553
- const [open, setOpen] = React41.useState(false);
5554
- const [view, setView] = React41.useState("main");
5555
- const contentRef = React41.useRef(null);
5556
- const menuRef = React41.useRef(null);
5557
- const btnRef = React41.useRef(null);
5558
- const close = React41.useCallback(() => {
5812
+ const [open, setOpen] = React45.useState(false);
5813
+ const [view, setView] = React45.useState("main");
5814
+ const contentRef = React45.useRef(null);
5815
+ const menuRef = React45.useRef(null);
5816
+ const btnRef = React45.useRef(null);
5817
+ const close = React45.useCallback(() => {
5559
5818
  setOpen(false);
5560
5819
  setView("main");
5561
5820
  }, []);
5562
- React41.useEffect(() => {
5821
+ React45.useEffect(() => {
5563
5822
  if (!open) return;
5564
5823
  const handler = (e) => {
5565
5824
  var _a, _b;
@@ -5570,7 +5829,7 @@ function ComponentActions({ children, onDownloadCSV, columnConfig, filename = "c
5570
5829
  document.addEventListener("mousedown", handler);
5571
5830
  return () => document.removeEventListener("mousedown", handler);
5572
5831
  }, [open, close]);
5573
- const handleDownloadPNG = React41.useCallback(async () => {
5832
+ const handleDownloadPNG = React45.useCallback(async () => {
5574
5833
  if (!contentRef.current) return;
5575
5834
  try {
5576
5835
  const url = await htmlToImage.toPng(contentRef.current, { backgroundColor: "white", pixelRatio: 2 });
@@ -5582,7 +5841,7 @@ function ComponentActions({ children, onDownloadCSV, columnConfig, filename = "c
5582
5841
  }
5583
5842
  close();
5584
5843
  }, [filename, close]);
5585
- const handleCSV = React41.useCallback(() => {
5844
+ const handleCSV = React45.useCallback(() => {
5586
5845
  onDownloadCSV == null ? void 0 : onDownloadCSV();
5587
5846
  close();
5588
5847
  }, [onDownloadCSV, close]);
@@ -5694,12 +5953,12 @@ function MenuButton({ label, onClick }) {
5694
5953
  );
5695
5954
  }
5696
5955
  function useColumnVisibility(columns) {
5697
- const [hidden, setHidden] = React41.useState(/* @__PURE__ */ new Set());
5698
- const visibleColumns = React41.useMemo(
5956
+ const [hidden, setHidden] = React45.useState(/* @__PURE__ */ new Set());
5957
+ const visibleColumns = React45.useMemo(
5699
5958
  () => columns.filter((c) => !hidden.has(c.key)),
5700
5959
  [columns, hidden]
5701
5960
  );
5702
- const toggle = React41.useCallback((key) => {
5961
+ const toggle = React45.useCallback((key) => {
5703
5962
  setHidden((prev) => {
5704
5963
  const next = new Set(prev);
5705
5964
  if (next.has(key)) next.delete(key);
@@ -5707,8 +5966,8 @@ function useColumnVisibility(columns) {
5707
5966
  return next;
5708
5967
  });
5709
5968
  }, []);
5710
- const showAll = React41.useCallback(() => setHidden(/* @__PURE__ */ new Set()), []);
5711
- const hideAll = React41.useCallback(
5969
+ const showAll = React45.useCallback(() => setHidden(/* @__PURE__ */ new Set()), []);
5970
+ const hideAll = React45.useCallback(
5712
5971
  () => setHidden(new Set(columns.map((c) => c.key))),
5713
5972
  [columns]
5714
5973
  );
@@ -5959,9 +6218,9 @@ function AlertResolver(p) {
5959
6218
  // src/composites/stat-grid/resolver.tsx
5960
6219
  init_Markdown();
5961
6220
  function FitText({ children, max = 22, min = 13, title, className, style }) {
5962
- const ref = React41.useRef(null);
5963
- const [size, setSize] = React41.useState(max);
5964
- React41.useLayoutEffect(() => {
6221
+ const ref = React45.useRef(null);
6222
+ const [size, setSize] = React45.useState(max);
6223
+ React45.useLayoutEffect(() => {
5965
6224
  const el = ref.current;
5966
6225
  if (!el) return void 0;
5967
6226
  const fit = () => {
@@ -6048,7 +6307,7 @@ init_ThemeContext();
6048
6307
  function TabsPanelResolver(p) {
6049
6308
  var _a;
6050
6309
  const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, ACCENT: ACCENT2 } = useTheme();
6051
- const [activeIdx, setActiveIdx] = React41.useState(0);
6310
+ const [activeIdx, setActiveIdx] = React45.useState(0);
6052
6311
  const activeTab = p.tabs[activeIdx];
6053
6312
  return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: "tabs-panel", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: "0" }, children: [
6054
6313
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -6206,17 +6465,17 @@ function SparklineTableResolver(p) {
6206
6465
  // src/composites/heatmap-table/resolver.tsx
6207
6466
  init_theme();
6208
6467
  init_ThemeContext();
6209
- function heatColor(z59) {
6210
- const clamped = Math.max(-3, Math.min(3, z59));
6468
+ function heatColor(z61) {
6469
+ const clamped = Math.max(-3, Math.min(3, z61));
6211
6470
  const abs = Math.abs(clamped);
6212
6471
  const lightness = 95 - abs * 8;
6213
6472
  const hue = clamped >= 0 ? 142 : 0;
6214
6473
  return `hsl(${hue} 60% ${lightness}%)`;
6215
6474
  }
6216
- function heatTextColor(z59) {
6217
- const abs = Math.abs(z59);
6218
- if (abs > 2) return z59 >= 0 ? "#14532d" : "#7f1d1d";
6219
- if (abs > 1) return z59 >= 0 ? "#166534" : "#991b1b";
6475
+ function heatTextColor(z61) {
6476
+ const abs = Math.abs(z61);
6477
+ if (abs > 2) return z61 >= 0 ? "#14532d" : "#7f1d1d";
6478
+ if (abs > 1) return z61 >= 0 ? "#166534" : "#991b1b";
6220
6479
  return "var(--foreground)";
6221
6480
  }
6222
6481
  var th2 = {
@@ -6314,7 +6573,7 @@ var thStyle2 = {
6314
6573
  function ScreenerTableResolver(p) {
6315
6574
  var _a, _b, _c, _d, _e, _f;
6316
6575
  const { ACCENT: ACCENT2, BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2 } = useTheme();
6317
- const [activeFilters, setActiveFilters] = React41.useState(new Set((_a = p.activeFilters) != null ? _a : []));
6576
+ const [activeFilters, setActiveFilters] = React45.useState(new Set((_a = p.activeFilters) != null ? _a : []));
6318
6577
  const { visibleColumns, hidden, toggle, showAll, hideAll, allColumns } = useColumnVisibility((_b = p.columns) != null ? _b : []);
6319
6578
  const toggleFilter = (f) => setActiveFilters((prev) => {
6320
6579
  const next = new Set(prev);
@@ -6384,7 +6643,7 @@ var th3 = {
6384
6643
  };
6385
6644
  function GroupRows({ group, columns, depth }) {
6386
6645
  var _a, _b;
6387
- const [open, setOpen] = React41.useState(true);
6646
+ const [open, setOpen] = React45.useState(true);
6388
6647
  const indent = depth * 14;
6389
6648
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6390
6649
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -6489,7 +6748,7 @@ var dotColor = {
6489
6748
  function NewsFeedResolver(p) {
6490
6749
  var _a, _b;
6491
6750
  const { ACCENT: ACCENT2, MUTED: MUTED2 } = useTheme();
6492
- const [filter, setFilter] = React41.useState(null);
6751
+ const [filter, setFilter] = React45.useState(null);
6493
6752
  const sentiments = ["positive", "neutral", "negative"].filter(
6494
6753
  (s) => {
6495
6754
  var _a2;
@@ -6531,9 +6790,9 @@ function NewsFeedResolver(p) {
6531
6790
  ] }) });
6532
6791
  }
6533
6792
  function useSeriesToggle(seriesKeys) {
6534
- const [hidden, setHidden] = React41.useState(/* @__PURE__ */ new Set());
6535
- const isVisible = React41.useCallback((key) => !hidden.has(key), [hidden]);
6536
- const toggle = React41.useCallback((key) => {
6793
+ const [hidden, setHidden] = React45.useState(/* @__PURE__ */ new Set());
6794
+ const isVisible = React45.useCallback((key) => !hidden.has(key), [hidden]);
6795
+ const toggle = React45.useCallback((key) => {
6537
6796
  setHidden((prev) => {
6538
6797
  const next = new Set(prev);
6539
6798
  if (next.has(key)) next.delete(key);
@@ -6541,7 +6800,7 @@ function useSeriesToggle(seriesKeys) {
6541
6800
  return next;
6542
6801
  });
6543
6802
  }, []);
6544
- const showAll = React41.useCallback(() => setHidden(/* @__PURE__ */ new Set()), []);
6803
+ const showAll = React45.useCallback(() => setHidden(/* @__PURE__ */ new Set()), []);
6545
6804
  return { hidden, isVisible, toggle, showAll, allKeys: seriesKeys };
6546
6805
  }
6547
6806
 
@@ -6850,7 +7109,7 @@ function WaterfallChartResolver(p) {
6850
7109
  ] }) });
6851
7110
  }
6852
7111
  init_ThemeContext();
6853
- var FlowGraph2 = React41__default.default.lazy(
7112
+ var FlowGraph2 = React45__default.default.lazy(
6854
7113
  () => Promise.resolve().then(() => (init_FlowGraph(), FlowGraph_exports)).then((m) => ({ default: m.FlowGraph }))
6855
7114
  );
6856
7115
  function FlowCanvasRenderer({
@@ -6891,7 +7150,7 @@ function FlowCanvasRenderer({
6891
7150
  overflow: "hidden",
6892
7151
  background: "#ffffff",
6893
7152
  position: "relative"
6894
- }, diagram ? {} : { height: "320px" }), children: diagram ? /* @__PURE__ */ jsxRuntime.jsx(React41.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(FlowGraph2, { diagram, title, autoplay, nodeStates }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
7153
+ }, diagram ? {} : { height: "320px" }), children: diagram ? /* @__PURE__ */ jsxRuntime.jsx(React45.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(FlowGraph2, { diagram, title, autoplay, nodeStates }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
6895
7154
  position: "absolute",
6896
7155
  inset: 0,
6897
7156
  display: "flex",
@@ -7124,7 +7383,7 @@ function TrialBalanceResolver(p) {
7124
7383
  gDebit += a.debit;
7125
7384
  gCredit += a.credit;
7126
7385
  });
7127
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
7386
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
7128
7387
  /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: 4, style: {
7129
7388
  padding: "8px 12px",
7130
7389
  fontSize: "12px",
@@ -7661,7 +7920,7 @@ function ItemRow({ item }) {
7661
7920
  ] });
7662
7921
  }
7663
7922
  function Section({ section }) {
7664
- const [open, setOpen] = React41.useState(true);
7923
+ const [open, setOpen] = React45.useState(true);
7665
7924
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
7666
7925
  /* @__PURE__ */ jsxRuntime.jsxs(
7667
7926
  "button",
@@ -7783,7 +8042,7 @@ function ReconciliationViewResolver(p) {
7783
8042
  const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, ACCENT: ACCENT2 } = useTheme();
7784
8043
  const sourceA = (_a = p.sourceA) != null ? _a : { label: "Source A" };
7785
8044
  const sourceB = (_b = p.sourceB) != null ? _b : { label: "Source B" };
7786
- const [activeTab, setActiveTab] = React41.useState("matched");
8045
+ const [activeTab, setActiveTab] = React45.useState("matched");
7787
8046
  const balanceA = (_d = (_c = p.summary) == null ? void 0 : _c.balanceA) != null ? _d : 0;
7788
8047
  const balanceB = (_f = (_e = p.summary) == null ? void 0 : _e.balanceB) != null ? _f : 0;
7789
8048
  const difference = (_h = (_g = p.summary) == null ? void 0 : _g.difference) != null ? _h : balanceA - balanceB;
@@ -8426,7 +8685,7 @@ function ChangesView({ changes }) {
8426
8685
  }
8427
8686
  function EventCard({ event }) {
8428
8687
  var _a;
8429
- const [showChanges, setShowChanges] = React41.useState(false);
8688
+ const [showChanges, setShowChanges] = React45.useState(false);
8430
8689
  const ac = (_a = actionConfig[event.action]) != null ? _a : actionConfig.commented;
8431
8690
  const hasChanges = event.changes && event.changes.length > 0;
8432
8691
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "12px", position: "relative" }, children: [
@@ -8484,23 +8743,23 @@ function AuditTrailResolver(p) {
8484
8743
  }
8485
8744
  init_Markdown();
8486
8745
  function useFullscreen(ref) {
8487
- const [isFullscreen, setIsFullscreen] = React41.useState(false);
8488
- React41.useEffect(() => {
8746
+ const [isFullscreen, setIsFullscreen] = React45.useState(false);
8747
+ React45.useEffect(() => {
8489
8748
  const handler = () => {
8490
8749
  setIsFullscreen(!!document.fullscreenElement);
8491
8750
  };
8492
8751
  document.addEventListener("fullscreenchange", handler);
8493
8752
  return () => document.removeEventListener("fullscreenchange", handler);
8494
8753
  }, []);
8495
- const enter = React41.useCallback(() => {
8754
+ const enter = React45.useCallback(() => {
8496
8755
  var _a, _b;
8497
8756
  (_b = (_a = ref.current) == null ? void 0 : _a.requestFullscreen) == null ? void 0 : _b.call(_a);
8498
8757
  }, [ref]);
8499
- const exit = React41.useCallback(() => {
8758
+ const exit = React45.useCallback(() => {
8500
8759
  var _a;
8501
8760
  if (document.fullscreenElement) (_a = document.exitFullscreen) == null ? void 0 : _a.call(document);
8502
8761
  }, []);
8503
- const toggle = React41.useCallback(() => {
8762
+ const toggle = React45.useCallback(() => {
8504
8763
  if (isFullscreen) exit();
8505
8764
  else enter();
8506
8765
  }, [isFullscreen, enter, exit]);
@@ -8510,10 +8769,10 @@ function useFullscreen(ref) {
8510
8769
  // src/composites/document-preview/resolver.tsx
8511
8770
  init_theme();
8512
8771
  init_ThemeContext();
8513
- var PdfViewer2 = React41__default.default.lazy(
8772
+ var PdfViewer2 = React45__default.default.lazy(
8514
8773
  () => Promise.resolve().then(() => (init_PdfViewer(), PdfViewer_exports)).then((m) => ({ default: m.PdfViewer }))
8515
8774
  );
8516
- var ExcelViewer2 = React41__default.default.lazy(
8775
+ var ExcelViewer2 = React45__default.default.lazy(
8517
8776
  () => Promise.resolve().then(() => (init_ExcelViewer(), ExcelViewer_exports)).then((m) => ({ default: m.ExcelViewer }))
8518
8777
  );
8519
8778
  var highlightColors = {
@@ -8563,8 +8822,8 @@ function DownloadIcon() {
8563
8822
  function DocumentPreviewResolver(p) {
8564
8823
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
8565
8824
  const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, ACCENT: ACCENT2 } = useTheme();
8566
- const [currentPage, setCurrentPage] = React41.useState(0);
8567
- const containerRef = React41.useRef(null);
8825
+ const [currentPage, setCurrentPage] = React45.useState(0);
8826
+ const containerRef = React45.useRef(null);
8568
8827
  const { isFullscreen, toggle } = useFullscreen(containerRef);
8569
8828
  const hasRealFile = !!(((_a = p.source) == null ? void 0 : _a.url) || ((_b = p.source) == null ? void 0 : _b.base64));
8570
8829
  const isPdf = p.documentType === "pdf";
@@ -8572,9 +8831,9 @@ function DocumentPreviewResolver(p) {
8572
8831
  const totalPages = ((_c = p.pages) != null ? _c : []).length;
8573
8832
  const page = p.pages[currentPage];
8574
8833
  const pageHighlights = ((_d = p.highlights) != null ? _d : []).filter((h) => h.pageIndex === currentPage);
8575
- const handlePdfLoad = React41.useCallback(() => {
8834
+ const handlePdfLoad = React45.useCallback(() => {
8576
8835
  }, []);
8577
- const handleExcelLoad = React41.useCallback(() => {
8836
+ const handleExcelLoad = React45.useCallback(() => {
8578
8837
  }, []);
8579
8838
  return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_e = p.title) != null ? _e : "document-preview", children: /* @__PURE__ */ jsxRuntime.jsxs(
8580
8839
  "div",
@@ -8687,7 +8946,7 @@ function DocumentPreviewResolver(p) {
8687
8946
  display: "flex",
8688
8947
  flexDirection: "column"
8689
8948
  }, children: [
8690
- hasRealFile && isPdf ? /* @__PURE__ */ jsxRuntime.jsx(React41.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(PdfViewer2, { url: (_q = p.source) == null ? void 0 : _q.url, base64: (_r = p.source) == null ? void 0 : _r.base64, onLoadSuccess: handlePdfLoad }) }) : hasRealFile && isExcel ? /* @__PURE__ */ jsxRuntime.jsx(React41.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(ExcelViewer2, { url: (_s = p.source) == null ? void 0 : _s.url, base64: (_t = p.source) == null ? void 0 : _t.base64, onLoadSuccess: handleExcelLoad }) }) : (page == null ? void 0 : page.imageUrl) ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "20px" }, children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: page.imageUrl, alt: page.label, style: { maxWidth: "100%", borderRadius: "4px" } }) }) : (page == null ? void 0 : page.content) ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontFamily: "var(--font-sans, system-ui)", fontSize: "13px", color: "var(--foreground)", lineHeight: 1.6, margin: 0, padding: "20px" }, children: /* @__PURE__ */ jsxRuntime.jsx(Markdown, { content: page.content }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "120px", color: MUTED2, fontSize: "13px" }, children: [
8949
+ hasRealFile && isPdf ? /* @__PURE__ */ jsxRuntime.jsx(React45.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(PdfViewer2, { url: (_q = p.source) == null ? void 0 : _q.url, base64: (_r = p.source) == null ? void 0 : _r.base64, onLoadSuccess: handlePdfLoad }) }) : hasRealFile && isExcel ? /* @__PURE__ */ jsxRuntime.jsx(React45.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(ExcelViewer2, { url: (_s = p.source) == null ? void 0 : _s.url, base64: (_t = p.source) == null ? void 0 : _t.base64, onLoadSuccess: handleExcelLoad }) }) : (page == null ? void 0 : page.imageUrl) ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "20px" }, children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: page.imageUrl, alt: page.label, style: { maxWidth: "100%", borderRadius: "4px" } }) }) : (page == null ? void 0 : page.content) ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontFamily: "var(--font-sans, system-ui)", fontSize: "13px", color: "var(--foreground)", lineHeight: 1.6, margin: 0, padding: "20px" }, children: /* @__PURE__ */ jsxRuntime.jsx(Markdown, { content: page.content }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "120px", color: MUTED2, fontSize: "13px" }, children: [
8691
8950
  "No content available for ",
8692
8951
  (_u = page == null ? void 0 : page.label) != null ? _u : "this page"
8693
8952
  ] }),
@@ -8750,7 +9009,7 @@ function ConfidenceBar({ confidence, height = 6 }) {
8750
9009
  }
8751
9010
  function StepCard({ step, isLast }) {
8752
9011
  var _a;
8753
- const [expanded, setExpanded] = React41.useState(false);
9012
+ const [expanded, setExpanded] = React45.useState(false);
8754
9013
  const cfg = stepTypeConfig[step.stepType];
8755
9014
  const detail = (_a = step.detail) != null ? _a : "";
8756
9015
  const isLong = detail.length > 100;
@@ -9255,7 +9514,7 @@ function ExampleRow({ example }) {
9255
9514
  );
9256
9515
  }
9257
9516
  function PartSection({ part, defaultOpen }) {
9258
- const [open, setOpen] = React41.useState(defaultOpen);
9517
+ const [open, setOpen] = React45.useState(defaultOpen);
9259
9518
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9260
9519
  /* @__PURE__ */ jsxRuntime.jsxs(
9261
9520
  "button",
@@ -9385,7 +9644,7 @@ function EngagementPipelineResolver(p) {
9385
9644
  const defaultActive = phases.findIndex(
9386
9645
  (ph) => ph.status === "in-progress" || ph.status === "blocked"
9387
9646
  );
9388
- const [activeIdx, setActiveIdx] = React41.useState(defaultActive >= 0 ? defaultActive : 0);
9647
+ const [activeIdx, setActiveIdx] = React45.useState(defaultActive >= 0 ? defaultActive : 0);
9389
9648
  const activePhase = phases[activeIdx];
9390
9649
  return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_b = p.title) != null ? _b : "engagement-pipeline", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: "12px" }, children: [
9391
9650
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "4px" }, children: [
@@ -9469,7 +9728,7 @@ function EngagementPipelineResolver(p) {
9469
9728
  const color = (_a2 = statusColor2[phase.status]) != null ? _a2 : "#d6d3d1";
9470
9729
  const isCurrent = i === activeIdx;
9471
9730
  const size = isCurrent ? 28 : 20;
9472
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
9731
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
9473
9732
  i > 0 && /* @__PURE__ */ jsxRuntime.jsx(
9474
9733
  "div",
9475
9734
  {
@@ -9776,7 +10035,7 @@ function Avatar({ name, avatar, hovered }) {
9776
10035
  function EntityCardGridResolver(p) {
9777
10036
  var _a, _b;
9778
10037
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2 } = useTheme();
9779
- const [hoveredId, setHoveredId] = React41.useState(null);
10038
+ const [hoveredId, setHoveredId] = React45.useState(null);
9780
10039
  return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_a = p.title) != null ? _a : "entity-card-grid", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: "10px" }, children: [
9781
10040
  p.title && /* @__PURE__ */ jsxRuntime.jsx(
9782
10041
  "p",
@@ -10032,7 +10291,7 @@ function StepRow({ step }) {
10032
10291
  function JobTrackerResolver(p) {
10033
10292
  var _a, _b, _c, _d, _e, _f, _g;
10034
10293
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, PAPER: PAPER2 } = useTheme();
10035
- const [stepsOpen, setStepsOpen] = React41.useState(true);
10294
+ const [stepsOpen, setStepsOpen] = React45.useState(true);
10036
10295
  const barColor = (_a = statusColors2[p.status]) != null ? _a : MUTED2;
10037
10296
  const badge = (_b = statusBadgeConfig[p.status]) != null ? _b : statusBadgeConfig.queued;
10038
10297
  const progress = (_c = p.progress) != null ? _c : p.status === "completed" ? 100 : 0;
@@ -10472,7 +10731,7 @@ function CitationCard({
10472
10731
  );
10473
10732
  }
10474
10733
  function FollowUpItem({ text }) {
10475
- const [hovered, setHovered] = React41.useState(false);
10734
+ const [hovered, setHovered] = React45.useState(false);
10476
10735
  return /* @__PURE__ */ jsxRuntime.jsxs(
10477
10736
  "span",
10478
10737
  {
@@ -10497,7 +10756,7 @@ function CitationMarker({
10497
10756
  index,
10498
10757
  onClick
10499
10758
  }) {
10500
- const [hovered, setHovered] = React41.useState(false);
10759
+ const [hovered, setHovered] = React45.useState(false);
10501
10760
  return /* @__PURE__ */ jsxRuntime.jsx(
10502
10761
  "sup",
10503
10762
  {
@@ -10526,7 +10785,7 @@ function CitationMarker({
10526
10785
  function CitedAnswerResolver(p) {
10527
10786
  var _a, _b, _c, _d, _e;
10528
10787
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, SECONDARY: SECONDARY2 } = useTheme();
10529
- const [expandedIds, setExpandedIds] = React41.useState(/* @__PURE__ */ new Set());
10788
+ const [expandedIds, setExpandedIds] = React45.useState(/* @__PURE__ */ new Set());
10530
10789
  const toggleCitation = (id) => {
10531
10790
  setExpandedIds((prev) => {
10532
10791
  const next = new Set(prev);
@@ -10830,7 +11089,7 @@ function TransactionFeedResolver(p) {
10830
11089
  var _a, _b, _c, _d, _e;
10831
11090
  const { BORDER: BORDER4, MUTED: MUTED2 } = useTheme();
10832
11091
  const currency = (_a = p.currency) != null ? _a : "USD";
10833
- const [hoveredIndex, setHoveredIndex] = React41.useState(null);
11092
+ const [hoveredIndex, setHoveredIndex] = React45.useState(null);
10834
11093
  const hasBalance = ((_b = p.transactions) != null ? _b : []).some((tx) => tx.balance != null);
10835
11094
  const totalInflows = p.transactions.filter((tx) => tx.amount > 0 && tx.status !== "reversed").reduce((sum, tx) => sum + tx.amount, 0);
10836
11095
  const totalOutflows = p.transactions.filter((tx) => tx.amount < 0 && tx.status !== "reversed").reduce((sum, tx) => sum + tx.amount, 0);
@@ -10987,7 +11246,7 @@ function formatDate2(dateStr) {
10987
11246
  }
10988
11247
  function FileRow({ item }) {
10989
11248
  var _a;
10990
- const [hovered, setHovered] = React41.useState(false);
11249
+ const [hovered, setHovered] = React45.useState(false);
10991
11250
  const cfg = getDocConfig(item.docType);
10992
11251
  return /* @__PURE__ */ jsxRuntime.jsxs(
10993
11252
  "div",
@@ -11063,8 +11322,8 @@ function FileRow({ item }) {
11063
11322
  );
11064
11323
  }
11065
11324
  function GroupSection({ groupName, items }) {
11066
- const [open, setOpen] = React41.useState(true);
11067
- const [headerHovered, setHeaderHovered] = React41.useState(false);
11325
+ const [open, setOpen] = React45.useState(true);
11326
+ const [headerHovered, setHeaderHovered] = React45.useState(false);
11068
11327
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11069
11328
  /* @__PURE__ */ jsxRuntime.jsxs(
11070
11329
  "button",
@@ -11250,15 +11509,15 @@ function isExpirySoon(expiresAt) {
11250
11509
 
11251
11510
  // src/shared/viewers/PreviewHost.tsx
11252
11511
  init_ThemeContext();
11253
- var PdfViewer3 = React41.lazy(
11512
+ var PdfViewer3 = React45.lazy(
11254
11513
  () => Promise.resolve().then(() => (init_PdfViewer(), PdfViewer_exports)).then((m) => ({ default: m.PdfViewer }))
11255
11514
  );
11256
- var ExcelViewer3 = React41.lazy(
11515
+ var ExcelViewer3 = React45.lazy(
11257
11516
  () => Promise.resolve().then(() => (init_ExcelViewer(), ExcelViewer_exports)).then((m) => ({ default: m.ExcelViewer }))
11258
11517
  );
11259
- var CsvViewer2 = React41.lazy(() => Promise.resolve().then(() => (init_CsvViewer(), CsvViewer_exports)).then((m) => ({ default: m.CsvViewer })));
11260
- var TextViewer2 = React41.lazy(() => Promise.resolve().then(() => (init_TextViewer(), TextViewer_exports)).then((m) => ({ default: m.TextViewer })));
11261
- var DocxViewer2 = React41.lazy(() => Promise.resolve().then(() => (init_DocxViewer(), DocxViewer_exports)).then((m) => ({ default: m.DocxViewer })));
11518
+ var CsvViewer2 = React45.lazy(() => Promise.resolve().then(() => (init_CsvViewer(), CsvViewer_exports)).then((m) => ({ default: m.CsvViewer })));
11519
+ var TextViewer2 = React45.lazy(() => Promise.resolve().then(() => (init_TextViewer(), TextViewer_exports)).then((m) => ({ default: m.TextViewer })));
11520
+ var DocxViewer2 = React45.lazy(() => Promise.resolve().then(() => (init_DocxViewer(), DocxViewer_exports)).then((m) => ({ default: m.DocxViewer })));
11262
11521
  var PEEK_ROWS = 20;
11263
11522
  var PEEK_LINES = 40;
11264
11523
  function PreviewHost({ kind, source, mode = "full" }) {
@@ -11288,7 +11547,7 @@ function PreviewHost({ kind, source, mode = "full" }) {
11288
11547
  default:
11289
11548
  return null;
11290
11549
  }
11291
- return /* @__PURE__ */ jsxRuntime.jsx(React41.Suspense, { fallback, children: viewer });
11550
+ return /* @__PURE__ */ jsxRuntime.jsx(React45.Suspense, { fallback, children: viewer });
11292
11551
  }
11293
11552
 
11294
11553
  // src/shared/PreviewModal.tsx
@@ -11304,7 +11563,7 @@ function PreviewModal({
11304
11563
  onDownload
11305
11564
  }) {
11306
11565
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2 } = useTheme();
11307
- React41.useEffect(() => {
11566
+ React45.useEffect(() => {
11308
11567
  if (!open) return;
11309
11568
  const onKey = (e) => {
11310
11569
  if (e.key === "Escape") onClose();
@@ -11477,17 +11736,17 @@ function FileCard({
11477
11736
  previewDisabled = false
11478
11737
  }) {
11479
11738
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2 } = useTheme();
11480
- const [cardHover, setCardHover] = React41.useState(false);
11481
- const [btnHover, setBtnHover] = React41.useState(false);
11482
- const [pvHover, setPvHover] = React41.useState(false);
11739
+ const [cardHover, setCardHover] = React45.useState(false);
11740
+ const [btnHover, setBtnHover] = React45.useState(false);
11741
+ const [pvHover, setPvHover] = React45.useState(false);
11483
11742
  const previewKind = previewKindFor(fileType, filename);
11484
11743
  const canPreview = !previewDisabled && previewKind !== null && (!!previewUrl || !!fetchPreviewBlob);
11485
- const [peekOpen, setPeekOpen] = React41.useState(false);
11486
- const [modalOpen, setModalOpen] = React41.useState(false);
11487
- const [source, setSource] = React41.useState(previewUrl ? { url: previewUrl } : null);
11488
- const [pvLoading, setPvLoading] = React41.useState(false);
11489
- const [pvError, setPvError] = React41.useState(null);
11490
- const ensureSource = React41.useCallback(async () => {
11744
+ const [peekOpen, setPeekOpen] = React45.useState(false);
11745
+ const [modalOpen, setModalOpen] = React45.useState(false);
11746
+ const [source, setSource] = React45.useState(previewUrl ? { url: previewUrl } : null);
11747
+ const [pvLoading, setPvLoading] = React45.useState(false);
11748
+ const [pvError, setPvError] = React45.useState(null);
11749
+ const ensureSource = React45.useCallback(async () => {
11491
11750
  if (source) return source;
11492
11751
  if (previewUrl) {
11493
11752
  const s = { url: previewUrl };
@@ -11509,7 +11768,7 @@ function FileCard({
11509
11768
  setPvLoading(false);
11510
11769
  }
11511
11770
  }, [source, previewUrl, fetchPreviewBlob]);
11512
- const togglePeek = React41.useCallback(async () => {
11771
+ const togglePeek = React45.useCallback(async () => {
11513
11772
  if (peekOpen) {
11514
11773
  setPeekOpen(false);
11515
11774
  return;
@@ -11517,7 +11776,7 @@ function FileCard({
11517
11776
  setPeekOpen(true);
11518
11777
  await ensureSource();
11519
11778
  }, [peekOpen, ensureSource]);
11520
- const openModal = React41.useCallback(async () => {
11779
+ const openModal = React45.useCallback(async () => {
11521
11780
  const s = await ensureSource();
11522
11781
  if (s) setModalOpen(true);
11523
11782
  }, [ensureSource]);
@@ -11632,7 +11891,7 @@ function FileCard({
11632
11891
  whiteSpace: "nowrap"
11633
11892
  },
11634
11893
  children: [
11635
- metaTokens.map((t, i) => /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
11894
+ metaTokens.map((t, i) => /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
11636
11895
  i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#c4c4c4" }, children: "\xB7" }),
11637
11896
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: t })
11638
11897
  ] }, i)),
@@ -11976,7 +12235,7 @@ function ServiceCard({ item, isHovered, onHover, onLeave: onLeave2 }) {
11976
12235
  function OpsDashboardResolver(p) {
11977
12236
  var _a, _b, _c;
11978
12237
  const { BORDER: BORDER4, MUTED: MUTED2 } = useTheme();
11979
- const [hoveredId, setHoveredId] = React41.useState(null);
12238
+ const [hoveredId, setHoveredId] = React45.useState(null);
11980
12239
  const hasRunning = ((_a = p.items) != null ? _a : []).some((item) => item.state === "running");
11981
12240
  return /* @__PURE__ */ jsxRuntime.jsxs(ComponentActions, { filename: (_b = p.title) != null ? _b : "ops-dashboard", children: [
11982
12241
  hasRunning && /* @__PURE__ */ jsxRuntime.jsx("style", { children: PULSE_KEYFRAMES }),
@@ -12029,8 +12288,8 @@ function formatDate3(value) {
12029
12288
  }
12030
12289
  }
12031
12290
  function CopyButton({ value, rowHovered }) {
12032
- const [copied, setCopied] = React41.useState(false);
12033
- const [btnHovered, setBtnHovered] = React41.useState(false);
12291
+ const [copied, setCopied] = React45.useState(false);
12292
+ const [btnHovered, setBtnHovered] = React45.useState(false);
12034
12293
  const handleCopy = () => {
12035
12294
  navigator.clipboard.writeText(value).then(() => {
12036
12295
  setCopied(true);
@@ -12122,7 +12381,7 @@ function ValueCell({ item }) {
12122
12381
  }
12123
12382
  }
12124
12383
  function KVRow({ item, isLast, index }) {
12125
- const [hovered, setHovered] = React41.useState(false);
12384
+ const [hovered, setHovered] = React45.useState(false);
12126
12385
  const altBg = index % 2 === 1 ? "#fcfcfc" : "white";
12127
12386
  return /* @__PURE__ */ jsxRuntime.jsxs(
12128
12387
  "div",
@@ -12207,7 +12466,7 @@ function KeyValueListResolver(p) {
12207
12466
  var _a3;
12208
12467
  return sum + ((_a3 = g.items) != null ? _a3 : []).length;
12209
12468
  }, 0);
12210
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
12469
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
12211
12470
  /* @__PURE__ */ jsxRuntime.jsxs(
12212
12471
  "div",
12213
12472
  {
@@ -12385,7 +12644,7 @@ function BalanceSheetResolver(p) {
12385
12644
  /* @__PURE__ */ jsxRuntime.jsxs("tbody", { children: [
12386
12645
  ((_p = p.sections) != null ? _p : []).map((section) => {
12387
12646
  var _a2;
12388
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
12647
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
12389
12648
  /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan, style: {
12390
12649
  padding: "8px 12px",
12391
12650
  fontSize: "12px",
@@ -12398,7 +12657,7 @@ function BalanceSheetResolver(p) {
12398
12657
  }, children: (_a2 = categoryLabels2[section.category]) != null ? _a2 : section.category }) }),
12399
12658
  section.subsections.map((sub, si) => {
12400
12659
  var _a3;
12401
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
12660
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
12402
12661
  /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan, style: {
12403
12662
  padding: "6px 10px 6px 24px",
12404
12663
  fontSize: "12px",
@@ -12574,7 +12833,7 @@ function IncomeStatementResolver(p) {
12574
12833
  textAlign: "left",
12575
12834
  whiteSpace: "nowrap"
12576
12835
  }, children: "\xA0" }),
12577
- periods.map((period) => /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
12836
+ periods.map((period) => /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
12578
12837
  /* @__PURE__ */ jsxRuntime.jsx("th", { style: {
12579
12838
  fontSize: "11px",
12580
12839
  fontWeight: 500,
@@ -12605,7 +12864,7 @@ function IncomeStatementResolver(p) {
12605
12864
  sections.map((section, si) => {
12606
12865
  var _a2;
12607
12866
  const isSubtotal = section.sectionType === "subtotal";
12608
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
12867
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
12609
12868
  /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: colCount, style: {
12610
12869
  padding: "8px 12px",
12611
12870
  fontSize: "12px",
@@ -12636,7 +12895,7 @@ function IncomeStatementResolver(p) {
12636
12895
  var _a4;
12637
12896
  const val = (_a4 = amounts[pi]) != null ? _a4 : 0;
12638
12897
  const isNeg = val < 0;
12639
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
12898
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
12640
12899
  /* @__PURE__ */ jsxRuntime.jsx("td", { style: {
12641
12900
  padding: "6px 10px",
12642
12901
  fontSize: "13px",
@@ -12671,7 +12930,7 @@ function IncomeStatementResolver(p) {
12671
12930
  var _a2;
12672
12931
  const val = (_a2 = grossProfit[pi]) != null ? _a2 : 0;
12673
12932
  const isNeg = val < 0;
12674
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
12933
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
12675
12934
  /* @__PURE__ */ jsxRuntime.jsx("td", { style: {
12676
12935
  padding: "8px 10px",
12677
12936
  fontSize: "12px",
@@ -12706,7 +12965,7 @@ function IncomeStatementResolver(p) {
12706
12965
  var _a2;
12707
12966
  const val = (_a2 = operatingIncome[pi]) != null ? _a2 : 0;
12708
12967
  const isNeg = val < 0;
12709
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
12968
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
12710
12969
  /* @__PURE__ */ jsxRuntime.jsx("td", { style: {
12711
12970
  padding: "8px 10px",
12712
12971
  fontSize: "12px",
@@ -12740,7 +12999,7 @@ function IncomeStatementResolver(p) {
12740
12999
  var _a2;
12741
13000
  const val = (_a2 = netIncome[pi]) != null ? _a2 : 0;
12742
13001
  const isNeg = val < 0;
12743
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
13002
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
12744
13003
  /* @__PURE__ */ jsxRuntime.jsx("td", { style: {
12745
13004
  padding: "10px 10px",
12746
13005
  fontSize: "13px",
@@ -12960,7 +13219,7 @@ function CashFlowStatementResolver(p) {
12960
13219
  /* @__PURE__ */ jsxRuntime.jsxs("tbody", { children: [
12961
13220
  activities.map((activity, ai) => {
12962
13221
  var _a2, _b2, _c2;
12963
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
13222
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
12964
13223
  ai > 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
12965
13224
  "td",
12966
13225
  {
@@ -15373,8 +15632,8 @@ var PRIORITY_STYLES = {
15373
15632
  function EscalationCardResolver(p) {
15374
15633
  var _a, _b, _c, _d;
15375
15634
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
15376
- const [cardHovered, setCardHovered] = React41.useState(false);
15377
- const [btnHovered, setBtnHovered] = React41.useState(false);
15635
+ const [cardHovered, setCardHovered] = React45.useState(false);
15636
+ const [btnHovered, setBtnHovered] = React45.useState(false);
15378
15637
  const priorityStyle = p.priority ? PRIORITY_STYLES[p.priority] : null;
15379
15638
  const railColor = (_a = priorityStyle == null ? void 0 : priorityStyle.color) != null ? _a : ACCENT2;
15380
15639
  const iconBg = (_b = priorityStyle == null ? void 0 : priorityStyle.bg) != null ? _b : "#fff2ec";
@@ -16221,9 +16480,9 @@ var CONNECTED_GREEN = "#15803d";
16221
16480
  function ConnectIntegrationResolver(p) {
16222
16481
  var _a;
16223
16482
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
16224
- const [cardHovered, setCardHovered] = React41.useState(false);
16225
- const [btnHovered, setBtnHovered] = React41.useState(false);
16226
- const [imgFailed, setImgFailed] = React41.useState(false);
16483
+ const [cardHovered, setCardHovered] = React45.useState(false);
16484
+ const [btnHovered, setBtnHovered] = React45.useState(false);
16485
+ const [imgFailed, setImgFailed] = React45.useState(false);
16227
16486
  const name = (p.integrationName || "Integration").trim();
16228
16487
  const initial = name.charAt(0).toUpperCase();
16229
16488
  const iconSrc = p.iconUrl || brandIconUrl(name);
@@ -16385,9 +16644,9 @@ function IntegrationsListResolver(p) {
16385
16644
  var _a, _b;
16386
16645
  const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
16387
16646
  const integrations = Array.isArray(p.integrations) ? p.integrations : [];
16388
- const [rowHover, setRowHover] = React41.useState(null);
16389
- const [btnHover, setBtnHover] = React41.useState(null);
16390
- const [failed, setFailed] = React41.useState({});
16647
+ const [rowHover, setRowHover] = React45.useState(null);
16648
+ const [btnHover, setBtnHover] = React45.useState(null);
16649
+ const [failed, setFailed] = React45.useState({});
16391
16650
  const connectedCount = integrations.filter((i) => i.status === "connected").length;
16392
16651
  return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_a = p.title) != null ? _a : "integrations", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: "11px" }, children: [
16393
16652
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "2px" }, children: [
@@ -16870,13 +17129,13 @@ var ellipsis = {
16870
17129
  function PipelinePreviewResolver(p) {
16871
17130
  var _a, _b, _c, _d, _e, _f, _g;
16872
17131
  const { MUTED: MUTED2, PAPER: PAPER2, BORDER: BORDER4, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
16873
- const [btnHovered, setBtnHovered] = React41.useState(false);
17132
+ const [btnHovered, setBtnHovered] = React45.useState(false);
16874
17133
  const stateCfg = STATE_CONFIG[(_a = p.state) != null ? _a : "draft"];
16875
17134
  const destinations = (_b = p.destinations) != null ? _b : [];
16876
17135
  const steps = (_c = p.steps) != null ? _c : [];
16877
17136
  const workstreams = (_d = p.workstreams) != null ? _d : [];
16878
17137
  const scheduleLabel = p.schedule ? p.schedule.type === "manual" ? "Manual" : (_f = (_e = p.schedule.label) != null ? _e : p.schedule.cron) != null ? _f : "Scheduled" : null;
16879
- const { nodes, edges, viewBox, vbW, vbH } = React41.useMemo(() => {
17138
+ const { nodes, edges, viewBox, vbW, vbH } = React45.useMemo(() => {
16880
17139
  const res = layoutGraph(steps);
16881
17140
  const b = layoutBounds(res.nodes);
16882
17141
  const pad = 24;
@@ -16890,7 +17149,7 @@ function PipelinePreviewResolver(p) {
16890
17149
  vbH: h
16891
17150
  };
16892
17151
  }, [steps]);
16893
- const nodeMap = React41.useMemo(() => {
17152
+ const nodeMap = React45.useMemo(() => {
16894
17153
  const m = {};
16895
17154
  nodes.forEach((n) => m[n.id] = n);
16896
17155
  return m;
@@ -17266,14 +17525,16 @@ var DEFAULT_INTERACTION = {
17266
17525
  onDecisionResolve: void 0,
17267
17526
  onDecisionSource: void 0
17268
17527
  };
17269
- var GenUIInteractionContext = React41.createContext(DEFAULT_INTERACTION);
17528
+ var GenUIInteractionContext = React45.createContext(DEFAULT_INTERACTION);
17270
17529
  function useGenUIInteraction() {
17271
- return React41.useContext(GenUIInteractionContext);
17530
+ return React45.useContext(GenUIInteractionContext);
17272
17531
  }
17273
17532
  var STATUS_COLORS3 = {
17274
17533
  done: "#15803d",
17275
17534
  active: "",
17276
17535
  // filled from theme ACCENT at render time
17536
+ running: "",
17537
+ // filled from theme ACCENT at render time (executor in flight)
17277
17538
  review: "#f59e0b",
17278
17539
  pending: "#9ca3af",
17279
17540
  blocked: "#b45309",
@@ -17282,6 +17543,7 @@ var STATUS_COLORS3 = {
17282
17543
  var STATUS_LABELS = {
17283
17544
  done: "Complete",
17284
17545
  active: "In progress",
17546
+ running: "Running",
17285
17547
  review: "In review",
17286
17548
  pending: "Pending",
17287
17549
  blocked: "Blocked",
@@ -17385,6 +17647,26 @@ function IndexDot({ step, index, accent }) {
17385
17647
  if (step.status === "failed") {
17386
17648
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: "#dc2626", color: "white" }), children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 10 }, children: "!" }) });
17387
17649
  }
17650
+ if (step.status === "running") {
17651
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: __spreadProps(__spreadValues({}, base), { position: "relative", background: `${accent}1f`, color: accent }), children: [
17652
+ /* @__PURE__ */ jsxRuntime.jsx(
17653
+ "span",
17654
+ {
17655
+ className: "wfs-anim",
17656
+ "aria-hidden": "true",
17657
+ style: {
17658
+ position: "absolute",
17659
+ inset: 0,
17660
+ borderRadius: "50%",
17661
+ border: `1.5px solid ${accent}33`,
17662
+ borderTopColor: accent,
17663
+ animation: "wfsSpin 0.8s linear infinite"
17664
+ }
17665
+ }
17666
+ ),
17667
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 9 }, children: n })
17668
+ ] });
17669
+ }
17388
17670
  if (step.status === "active") {
17389
17671
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: accent, color: "white" }), children: n });
17390
17672
  }
@@ -17393,12 +17675,50 @@ function IndexDot({ step, index, accent }) {
17393
17675
  }
17394
17676
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: "#f2f2f2", color: "#9ca3af" }), children: n });
17395
17677
  }
17678
+ function EvalBadge({ step }) {
17679
+ var _a;
17680
+ const ev = step.eval;
17681
+ if (!ev || ev.judge_ok === false) return null;
17682
+ const score = typeof ev.score === "number" ? ev.score : null;
17683
+ const flags = (_a = ev.data_quality_flags) != null ? _a : [];
17684
+ const bad = ev.verdict === "bad" || score !== null && score < 0.8;
17685
+ const tip = flags.length > 0 ? flags.map((f) => {
17686
+ var _a2;
17687
+ return `${(_a2 = f.severity) != null ? _a2 : "?"}: ${f.details || f.issue || f.field || "issue"}`;
17688
+ }).join("\n") : ev.reasoning || void 0;
17689
+ const label = score !== null ? score.toFixed(2) : bad ? "flagged" : "ok";
17690
+ return /* @__PURE__ */ jsxRuntime.jsxs(
17691
+ "span",
17692
+ {
17693
+ title: tip,
17694
+ "data-testid": `workflow-stepper-eval-${step.id}`,
17695
+ style: {
17696
+ display: "inline-flex",
17697
+ alignItems: "center",
17698
+ gap: 3,
17699
+ fontSize: 9,
17700
+ fontWeight: 700,
17701
+ padding: "1px 6px",
17702
+ borderRadius: 9999,
17703
+ background: bad ? "#fff7ed" : "#dcfce7",
17704
+ color: bad ? "#b45309" : "#15803d",
17705
+ whiteSpace: "nowrap",
17706
+ flexShrink: 0
17707
+ },
17708
+ children: [
17709
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: bad ? "\u26A0" : "\u2713" }),
17710
+ label,
17711
+ flags.length > 0 ? ` \xB7 ${flags.length}` : ""
17712
+ ]
17713
+ }
17714
+ );
17715
+ }
17396
17716
  var CARD_MIN = 132;
17397
17717
  var CARD_GAP = 16;
17398
17718
  var AUTO_COMPACT_BELOW = 360;
17399
17719
  function useContainerWidth(ref) {
17400
- const [w, setW] = React41__default.default.useState(0);
17401
- React41__default.default.useLayoutEffect(() => {
17720
+ const [w, setW] = React45__default.default.useState(0);
17721
+ React45__default.default.useLayoutEffect(() => {
17402
17722
  const el = ref.current;
17403
17723
  if (!el || typeof ResizeObserver === "undefined") return;
17404
17724
  const ro = new ResizeObserver((entries) => {
@@ -17417,6 +17737,7 @@ var KEYFRAMES = `
17417
17737
  @keyframes wfsLampPulse{0%,100%{box-shadow:0 0 0 0 var(--wfs-accent,#6366f1)73}50%{box-shadow:0 0 0 4px transparent}}
17418
17738
  @keyframes wfsRise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
17419
17739
  @keyframes wfsShimmer{0%{background-position:-200px 0}100%{background-position:calc(200px + 100%) 0}}
17740
+ @keyframes wfsSpin{to{transform:rotate(360deg)}}
17420
17741
  .wfs-rise{animation:wfsRise 0.32s cubic-bezier(0.22,1,0.36,1) both}
17421
17742
  @media (prefers-reduced-motion: reduce){
17422
17743
  .wfs-anim,.wfs-rise,.wfs-shim{animation:none !important}
@@ -17497,17 +17818,17 @@ function WorkflowStepperRenderer({
17497
17818
  const steps = (_a = data.steps) != null ? _a : [];
17498
17819
  const activeStepId = (_d = (_c = data.active_step) != null ? _c : (_b = steps.find((s) => s.status === "active")) == null ? void 0 : _b.id) != null ? _d : null;
17499
17820
  const interactive = typeof onSelectStep === "function";
17500
- const statusColor3 = (s) => s === "active" ? ACCENT2 : STATUS_COLORS3[s];
17821
+ const statusColor3 = (s) => s === "active" || s === "running" ? ACCENT2 : STATUS_COLORS3[s];
17501
17822
  const doneCount = steps.filter((s) => s.status === "done").length;
17502
- const rootRef = React41__default.default.useRef(null);
17823
+ const rootRef = React45__default.default.useRef(null);
17503
17824
  const containerW = useContainerWidth(rootRef);
17504
17825
  let resolved = density === "auto" ? "full" : density;
17505
17826
  if (density === "auto" && containerW > 0) {
17506
17827
  const needed = steps.length * CARD_MIN + Math.max(0, steps.length - 1) * CARD_GAP;
17507
17828
  resolved = containerW < AUTO_COMPACT_BELOW || needed > containerW * 1.6 ? "compact" : "full";
17508
17829
  }
17509
- const scrollerRef = React41__default.default.useRef(null);
17510
- React41__default.default.useEffect(() => {
17830
+ const scrollerRef = React45__default.default.useRef(null);
17831
+ React45__default.default.useEffect(() => {
17511
17832
  if (resolved !== "full" || loading) return;
17512
17833
  const sc = scrollerRef.current;
17513
17834
  if (!sc) return;
@@ -17518,11 +17839,11 @@ function WorkflowStepperRenderer({
17518
17839
  el.scrollIntoView({ inline: "center", block: "nearest", behavior: "smooth" });
17519
17840
  }
17520
17841
  }, [resolved, loading, selectedStep, activeStepId]);
17521
- const [edges, setEdges] = React41__default.default.useState({
17842
+ const [edges, setEdges] = React45__default.default.useState({
17522
17843
  left: false,
17523
17844
  right: false
17524
17845
  });
17525
- const updateEdges = React41__default.default.useCallback(() => {
17846
+ const updateEdges = React45__default.default.useCallback(() => {
17526
17847
  const sc = scrollerRef.current;
17527
17848
  if (!sc) return;
17528
17849
  const max = sc.scrollWidth - sc.clientWidth;
@@ -17531,7 +17852,7 @@ function WorkflowStepperRenderer({
17531
17852
  const right = sl < max - 1;
17532
17853
  setEdges((prev) => prev.left === left && prev.right === right ? prev : { left, right });
17533
17854
  }, []);
17534
- React41__default.default.useLayoutEffect(() => {
17855
+ React45__default.default.useLayoutEffect(() => {
17535
17856
  if (resolved !== "full" || loading) return;
17536
17857
  updateEdges();
17537
17858
  const sc = scrollerRef.current;
@@ -17587,7 +17908,7 @@ function WorkflowStepperRenderer({
17587
17908
  const reached = s.status !== "pending";
17588
17909
  const clickable = interactive && reached;
17589
17910
  const size = act ? 11 : done ? 9 : 8;
17590
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
17911
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
17591
17912
  i > 0 && /* @__PURE__ */ jsxRuntime.jsx(
17592
17913
  "span",
17593
17914
  {
@@ -17725,12 +18046,13 @@ function WorkflowStepperRenderer({
17725
18046
  var _a2;
17726
18047
  const isSelected = selectedStep === step.id;
17727
18048
  const isActive = step.status === "active";
18049
+ const isRunning = step.status === "running";
17728
18050
  const reached = step.status !== "pending";
17729
18051
  const clickable = interactive && reached;
17730
18052
  const color = statusColor3(step.status);
17731
18053
  const humans = ((_a2 = step.assignees) != null ? _a2 : []).filter((a) => a.kind === "human");
17732
18054
  const roleCaption = humans.map((h) => h.role).filter(Boolean).slice(0, 2).join(" \xB7 ");
17733
- return /* @__PURE__ */ jsxRuntime.jsxs(React41__default.default.Fragment, { children: [
18055
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
17734
18056
  i > 0 && /* @__PURE__ */ jsxRuntime.jsx(
17735
18057
  "div",
17736
18058
  {
@@ -17821,36 +18143,41 @@ function WorkflowStepperRenderer({
17821
18143
  }
17822
18144
  }
17823
18145
  ),
17824
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
17825
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
18146
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 4 }, children: [
18147
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, minWidth: 0 }, children: [
17826
18148
  /* @__PURE__ */ jsxRuntime.jsx(IndexDot, { step, index: i, accent: ACCENT2 }),
17827
18149
  /* @__PURE__ */ jsxRuntime.jsx(
17828
18150
  "span",
17829
18151
  {
17830
- className: isActive ? "wfs-anim" : void 0,
18152
+ className: isActive || isRunning ? "wfs-anim" : void 0,
17831
18153
  style: {
17832
18154
  width: 6,
17833
18155
  height: 6,
17834
18156
  borderRadius: "50%",
17835
18157
  background: color,
17836
- animation: isActive ? "wfsLampPulse 1.8s ease-in-out infinite" : "none"
18158
+ flexShrink: 0,
18159
+ animation: isActive || isRunning ? "wfsLampPulse 1.8s ease-in-out infinite" : "none"
17837
18160
  }
17838
18161
  }
17839
18162
  )
17840
18163
  ] }),
17841
- /* @__PURE__ */ jsxRuntime.jsx(
17842
- "span",
17843
- {
17844
- style: {
17845
- fontSize: 9,
17846
- fontWeight: 600,
17847
- letterSpacing: "0.05em",
17848
- textTransform: "uppercase",
17849
- color
17850
- },
17851
- children: STATUS_LABELS[step.status]
17852
- }
17853
- )
18164
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4, minWidth: 0 }, children: [
18165
+ /* @__PURE__ */ jsxRuntime.jsx(EvalBadge, { step }),
18166
+ /* @__PURE__ */ jsxRuntime.jsx(
18167
+ "span",
18168
+ {
18169
+ style: {
18170
+ fontSize: 9,
18171
+ fontWeight: 600,
18172
+ letterSpacing: "0.05em",
18173
+ textTransform: "uppercase",
18174
+ color,
18175
+ whiteSpace: "nowrap"
18176
+ },
18177
+ children: STATUS_LABELS[step.status]
18178
+ }
18179
+ )
18180
+ ] })
17854
18181
  ] }),
17855
18182
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { minWidth: 0 }, children: [
17856
18183
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -17984,98 +18311,1657 @@ function WorkflowStepperResolver(p) {
17984
18311
  ] }) });
17985
18312
  }
17986
18313
  init_ThemeContext();
17987
- var SEVERITY_COLORS = {
17988
- high: { color: "#dc2626", bg: "#fef2f2" },
17989
- medium: { color: "#f59e0b", bg: "#fff7ed" },
17990
- low: { color: "#777777", bg: "#f2f2f2" }
18314
+
18315
+ // src/composites/document-field-extraction/bboxTransform.ts
18316
+ function bboxToRect(bbox2, page, px) {
18317
+ if (!bbox2 || bbox2.length !== 4) return null;
18318
+ const { wPts, hPts } = page;
18319
+ const { wPx, hPx } = px;
18320
+ if (!wPts || !hPts || !wPx || !hPx) return null;
18321
+ const [x0, y0, x1, y1] = bbox2;
18322
+ const sx = wPx / wPts;
18323
+ const sy = hPx / hPts;
18324
+ return {
18325
+ left: x0 * sx,
18326
+ width: (x1 - x0) * sx,
18327
+ // Flip Y: the box's TOP in screen space is the page height minus its upper
18328
+ // PDF-point edge (y1), because PDF y grows upward from the bottom.
18329
+ top: (hPts - y1) * sy,
18330
+ height: (y1 - y0) * sy
18331
+ };
18332
+ }
18333
+
18334
+ // src/composites/document-field-extraction/FieldDetail.tsx
18335
+ init_ThemeContext();
18336
+
18337
+ // src/composites/document-field-extraction/fieldLabels.ts
18338
+ var LABEL_DISPLAY = {
18339
+ "employer identification number": "Employer ID (EIN)",
18340
+ "company or business name": "Company Name",
18341
+ "total revenue": "Total Revenue",
18342
+ "net income": "Net Income",
18343
+ "tax year": "Tax Year",
18344
+ "invoice number": "Invoice Number",
18345
+ "invoice date": "Invoice Date",
18346
+ "total amount due": "Total Amount Due",
18347
+ "vendor name": "Vendor Name",
18348
+ "receipt total": "Receipt Total",
18349
+ "transaction date": "Transaction Date",
18350
+ "merchant name": "Merchant Name"
17991
18351
  };
17992
- var GREEN3 = "#15803d";
17993
- var GREEN_SOFT = "#dcfce7";
17994
- var STACK_BELOW = 380;
17995
- function formatAmount2(amount, currency = "USD") {
18352
+ function prettyLabel(label) {
18353
+ var _a;
18354
+ return (_a = LABEL_DISPLAY[label]) != null ? _a : label.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
18355
+ }
18356
+ var TIER_COLORS = {
18357
+ green: "#15803d",
18358
+ amber: "#f59e0b",
18359
+ red: "#dc2626"
18360
+ };
18361
+ var BADGE_TITLE = {
18362
+ SC: "High confidence",
18363
+ CN: "Medium confidence",
18364
+ AB: "Low confidence",
18365
+ SW: "Very low confidence"
18366
+ };
18367
+ var BADGE_STYLE = {
18368
+ SC: { bg: "#dcfce7", fg: "#15803d" },
18369
+ CN: { bg: "#eff6ff", fg: "#0364ff" },
18370
+ // theme-ok (SECONDARY)
18371
+ AB: { bg: "#fff7ed", fg: "#92400e" },
18372
+ SW: { bg: "#fef2f2", fg: "#dc2626" }
18373
+ };
18374
+ var STATE_DOT = {
18375
+ ok: "#15803d",
18376
+ corrected: "#0364ff",
18377
+ // theme-ok (SECONDARY)
18378
+ missing: "#dc2626",
18379
+ warn: "#f59e0b"
18380
+ };
18381
+ function hexToRgba(hex, alpha) {
18382
+ const h = hex.replace("#", "");
18383
+ const r = parseInt(h.slice(0, 2), 16);
18384
+ const g = parseInt(h.slice(2, 4), 16);
18385
+ const b = parseInt(h.slice(4, 6), 16);
18386
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
18387
+ }
18388
+ function badgeStyle(f) {
17996
18389
  var _a, _b;
17997
- const abs = Math.abs(amount);
17998
- const sign = amount < 0 ? "-" : "";
17999
- let body;
18000
- if (abs >= 1e6) body = `${(abs / 1e6).toFixed(abs >= 1e7 ? 0 : 1)}M`;
18001
- else if (abs >= 1e3) body = `${(abs / 1e3).toFixed(abs >= 1e4 ? 0 : 1)}K`;
18002
- else body = `${abs}`;
18003
- let symbol = "$";
18004
- try {
18005
- const parts = new Intl.NumberFormat("en-US", {
18006
- style: "currency",
18007
- currency,
18008
- maximumFractionDigits: 0
18009
- }).formatToParts(0);
18010
- symbol = (_b = (_a = parts.find((p) => p.type === "currency")) == null ? void 0 : _a.value) != null ? _b : "$";
18011
- } catch (e) {
18012
- symbol = "$";
18013
- }
18014
- return `${sign}${symbol}${body}`;
18390
+ return (_b = BADGE_STYLE[(_a = f.badge) != null ? _a : ""]) != null ? _b : { bg: "#f6f6f6", fg: "#777777" };
18015
18391
  }
18016
- function useContainerWidth2(ref) {
18017
- const [w, setW] = React41__default.default.useState(0);
18018
- React41__default.default.useLayoutEffect(() => {
18019
- const el = ref.current;
18020
- if (!el || typeof ResizeObserver === "undefined") return;
18021
- const ro = new ResizeObserver((entries) => {
18022
- var _a;
18023
- const cr = (_a = entries[0]) == null ? void 0 : _a.contentRect;
18024
- if (cr) setW(cr.width);
18025
- });
18026
- ro.observe(el);
18027
- setW(el.getBoundingClientRect().width);
18028
- return () => ro.disconnect();
18029
- }, [ref]);
18030
- return w;
18392
+ function dotColor2(f) {
18393
+ var _a, _b;
18394
+ return (_b = STATE_DOT[(_a = f.state) != null ? _a : "ok"]) != null ? _b : "#15803d";
18031
18395
  }
18032
- var KEYFRAMES2 = `
18033
- @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
18034
- .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
18035
- @media (prefers-reduced-motion: reduce){
18036
- .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
18037
- }`;
18038
- function SparkCheck({ size, color }) {
18039
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
18040
- "path",
18041
- {
18042
- d: "M5 13l4 4L19 7",
18043
- stroke: color,
18044
- strokeWidth: 2.5,
18045
- strokeLinecap: "round",
18046
- strokeLinejoin: "round"
18047
- }
18048
- ) });
18396
+ function fieldColor(f, secondary) {
18397
+ var _a, _b;
18398
+ if (f.state === "corrected") return secondary;
18399
+ return (_b = TIER_COLORS[(_a = f.confidence_tier) != null ? _a : "amber"]) != null ? _b : TIER_COLORS.amber;
18049
18400
  }
18050
- function FlagPill({ flag }) {
18401
+ function confidenceLabel(f) {
18051
18402
  var _a;
18052
- const sev = (_a = flag.severity) != null ? _a : "medium";
18053
- const { color, bg } = SEVERITY_COLORS[sev];
18403
+ if (typeof f.confidence === "number" && !Number.isNaN(f.confidence)) {
18404
+ return `${Math.round(f.confidence * 100)}%`;
18405
+ }
18406
+ return (_a = f.badge) != null ? _a : "\u2014";
18407
+ }
18408
+ function FieldDetail({
18409
+ field,
18410
+ selected,
18411
+ onSelect,
18412
+ onSave,
18413
+ correctionCount = 0,
18414
+ cardRef
18415
+ }) {
18416
+ var _a, _b, _c, _d;
18417
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
18418
+ const [editing, setEditing] = React45__default.default.useState(false);
18419
+ const [draft, setDraft] = React45__default.default.useState("");
18420
+ const [saving, setSaving] = React45__default.default.useState(false);
18421
+ const [saveError, setSaveError] = React45__default.default.useState(null);
18422
+ const textareaRef = React45__default.default.useRef(null);
18423
+ const color = fieldColor(field, SECONDARY2);
18424
+ const corrected = field.state === "corrected";
18425
+ const startEdit = (e) => {
18426
+ e.stopPropagation();
18427
+ setDraft(field.value || "");
18428
+ setSaveError(null);
18429
+ setEditing(true);
18430
+ setTimeout(() => {
18431
+ var _a2, _b2;
18432
+ (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
18433
+ (_b2 = textareaRef.current) == null ? void 0 : _b2.select();
18434
+ }, 0);
18435
+ };
18436
+ const cancelEdit = (e) => {
18437
+ e.stopPropagation();
18438
+ setEditing(false);
18439
+ setSaveError(null);
18440
+ };
18441
+ const save = async (e) => {
18442
+ var _a2, _b2;
18443
+ e.stopPropagation();
18444
+ if (!onSave || draft === field.value) {
18445
+ setEditing(false);
18446
+ return;
18447
+ }
18448
+ setSaving(true);
18449
+ setSaveError(null);
18450
+ try {
18451
+ await onSave(field.field_key, draft);
18452
+ setEditing(false);
18453
+ } catch (err) {
18454
+ const msg = ((_b2 = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b2.detail) || "Save failed. Try again.";
18455
+ setSaveError(msg);
18456
+ } finally {
18457
+ setSaving(false);
18458
+ }
18459
+ };
18460
+ const handleKeyDown = (e) => {
18461
+ if (e.key === "Escape") cancelEdit(e);
18462
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) void save(e);
18463
+ };
18054
18464
  return /* @__PURE__ */ jsxRuntime.jsxs(
18055
- "span",
18465
+ "div",
18056
18466
  {
18467
+ ref: cardRef,
18468
+ "data-testid": "field-card",
18469
+ "data-field-key": field.field_key,
18470
+ "data-selected": selected ? "true" : "false",
18471
+ role: "button",
18472
+ tabIndex: 0,
18473
+ onClick: () => !editing && onSelect(selected ? null : field.field_key),
18474
+ onKeyDown: (e) => {
18475
+ if (!editing && e.key === "Enter") onSelect(selected ? null : field.field_key);
18476
+ },
18057
18477
  style: {
18058
- display: "inline-flex",
18059
- alignItems: "center",
18060
- gap: 5,
18061
- fontSize: 11,
18062
- fontWeight: 600,
18063
- padding: "3px 9px",
18064
- borderRadius: 9999,
18065
- background: bg,
18066
- color,
18067
- lineHeight: 1.2
18478
+ display: "flex",
18479
+ flexDirection: "column",
18480
+ gap: "4px",
18481
+ padding: "8px 10px",
18482
+ borderRadius: "0.5rem",
18483
+ border: `1px solid ${selected ? color : BORDER4}`,
18484
+ background: selected ? hexToRgba(color, 0.06) : "white",
18485
+ cursor: editing ? "default" : "pointer",
18486
+ transition: "background 0.15s, border-color 0.15s"
18068
18487
  },
18069
18488
  children: [
18070
- /* @__PURE__ */ jsxRuntime.jsx(
18071
- "span",
18072
- {
18073
- "aria-hidden": "true",
18074
- style: { width: 6, height: 6, borderRadius: "50%", background: color, flexShrink: 0 }
18075
- }
18076
- ),
18077
- flag.field ? `${flag.field}: ${flag.issue}` : flag.issue
18078
- ]
18489
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", minWidth: 0 }, children: [
18490
+ /* @__PURE__ */ jsxRuntime.jsx(
18491
+ "span",
18492
+ {
18493
+ title: (_c = (_b = BADGE_TITLE[(_a = field.badge) != null ? _a : ""]) != null ? _b : field.badge) != null ? _c : "",
18494
+ style: {
18495
+ fontSize: "10px",
18496
+ fontWeight: 700,
18497
+ padding: "2px 6px",
18498
+ borderRadius: "4px",
18499
+ flexShrink: 0,
18500
+ letterSpacing: "0.02em",
18501
+ minWidth: "34px",
18502
+ textAlign: "center",
18503
+ fontVariantNumeric: "tabular-nums",
18504
+ background: badgeStyle(field).bg,
18505
+ color: badgeStyle(field).fg
18506
+ },
18507
+ children: confidenceLabel(field)
18508
+ }
18509
+ ),
18510
+ /* @__PURE__ */ jsxRuntime.jsx(
18511
+ "span",
18512
+ {
18513
+ title: prettyLabel(field.label),
18514
+ style: {
18515
+ fontSize: "12.5px",
18516
+ fontWeight: 600,
18517
+ color: "var(--foreground)",
18518
+ flex: 1,
18519
+ minWidth: 0,
18520
+ whiteSpace: "nowrap",
18521
+ overflow: "hidden",
18522
+ textOverflow: "ellipsis"
18523
+ },
18524
+ children: prettyLabel(field.label)
18525
+ }
18526
+ ),
18527
+ field.is_primary && /* @__PURE__ */ jsxRuntime.jsx(
18528
+ "span",
18529
+ {
18530
+ style: {
18531
+ fontSize: "9px",
18532
+ fontWeight: 600,
18533
+ textTransform: "uppercase",
18534
+ letterSpacing: "0.04em",
18535
+ color: MUTED2,
18536
+ flexShrink: 0
18537
+ },
18538
+ children: "Primary"
18539
+ }
18540
+ ),
18541
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "11px", color: MUTED2, flexShrink: 0 }, children: [
18542
+ "p.",
18543
+ field.page + 1
18544
+ ] }),
18545
+ !editing && onSave && /* @__PURE__ */ jsxRuntime.jsx(
18546
+ "button",
18547
+ {
18548
+ type: "button",
18549
+ onClick: startEdit,
18550
+ title: "Edit value",
18551
+ "aria-label": "Edit value",
18552
+ style: {
18553
+ border: `1px solid ${BORDER4}`,
18554
+ borderRadius: "6px",
18555
+ background: "white",
18556
+ cursor: "pointer",
18557
+ padding: "3px 5px",
18558
+ lineHeight: 1,
18559
+ flexShrink: 0,
18560
+ display: "inline-flex",
18561
+ alignItems: "center",
18562
+ justifyContent: "center"
18563
+ },
18564
+ 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: [
18565
+ /* @__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" }),
18566
+ /* @__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" })
18567
+ ] })
18568
+ }
18569
+ )
18570
+ ] }),
18571
+ editing ? /* @__PURE__ */ jsxRuntime.jsxs("div", { onClick: (e) => e.stopPropagation(), style: { display: "flex", flexDirection: "column", gap: "5px" }, children: [
18572
+ /* @__PURE__ */ jsxRuntime.jsx(
18573
+ "textarea",
18574
+ {
18575
+ ref: textareaRef,
18576
+ value: draft,
18577
+ onChange: (e) => setDraft(e.target.value),
18578
+ onKeyDown: handleKeyDown,
18579
+ rows: 3,
18580
+ placeholder: "Enter value\u2026",
18581
+ style: {
18582
+ width: "100%",
18583
+ boxSizing: "border-box",
18584
+ resize: "vertical",
18585
+ fontSize: "13px",
18586
+ fontFamily: "var(--font-sans)",
18587
+ color: "var(--foreground)",
18588
+ padding: "6px 8px",
18589
+ borderRadius: "0.4rem",
18590
+ border: `1px solid ${BORDER4}`
18591
+ }
18592
+ }
18593
+ ),
18594
+ saveError && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "11px", color: TIER_COLORS.red }, children: saveError }),
18595
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "6px" }, children: [
18596
+ /* @__PURE__ */ jsxRuntime.jsx(
18597
+ "button",
18598
+ {
18599
+ type: "button",
18600
+ onClick: save,
18601
+ disabled: saving,
18602
+ title: "Save (\u2318\u21B5)",
18603
+ style: {
18604
+ display: "inline-flex",
18605
+ alignItems: "center",
18606
+ gap: "4px",
18607
+ fontSize: "11px",
18608
+ fontWeight: 600,
18609
+ padding: "4px 10px",
18610
+ borderRadius: "0.4rem",
18611
+ border: "none",
18612
+ background: "var(--foreground)",
18613
+ color: "white",
18614
+ cursor: saving ? "default" : "pointer",
18615
+ opacity: saving ? 0.7 : 1
18616
+ },
18617
+ children: saving ? "Saving\u2026" : "Save"
18618
+ }
18619
+ ),
18620
+ /* @__PURE__ */ jsxRuntime.jsx(
18621
+ "button",
18622
+ {
18623
+ type: "button",
18624
+ onClick: cancelEdit,
18625
+ disabled: saving,
18626
+ title: "Cancel (Esc)",
18627
+ style: {
18628
+ fontSize: "11px",
18629
+ fontWeight: 600,
18630
+ padding: "4px 10px",
18631
+ borderRadius: "0.4rem",
18632
+ border: `1px solid ${BORDER4}`,
18633
+ background: "white",
18634
+ color: MUTED2,
18635
+ cursor: saving ? "default" : "pointer"
18636
+ },
18637
+ children: "Cancel"
18638
+ }
18639
+ )
18640
+ ] })
18641
+ ] }) : corrected ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "2px", paddingLeft: "2px" }, children: [
18642
+ field.previous_value != null && field.previous_value !== "" && /* @__PURE__ */ jsxRuntime.jsx(
18643
+ "span",
18644
+ {
18645
+ style: {
18646
+ fontSize: "11.5px",
18647
+ color: MUTED2,
18648
+ textDecoration: "line-through",
18649
+ fontFamily: "ui-monospace, 'Cascadia Code', monospace",
18650
+ wordBreak: "break-word"
18651
+ },
18652
+ children: field.previous_value
18653
+ }
18654
+ ),
18655
+ /* @__PURE__ */ jsxRuntime.jsx(
18656
+ "span",
18657
+ {
18658
+ style: {
18659
+ fontSize: "12.5px",
18660
+ fontWeight: 600,
18661
+ color: "var(--foreground)",
18662
+ fontFamily: "ui-monospace, 'Cascadia Code', monospace",
18663
+ wordBreak: "break-word"
18664
+ },
18665
+ children: field.value || "\u2014"
18666
+ }
18667
+ ),
18668
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
18669
+ field.corrected_by && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "11px", color: SECONDARY2 }, title: `Corrected by ${field.corrected_by}`, children: field.corrected_by }),
18670
+ correctionCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
18671
+ "span",
18672
+ {
18673
+ style: {
18674
+ fontSize: "10.5px",
18675
+ fontWeight: 600,
18676
+ color: MUTED2,
18677
+ background: PAPER2,
18678
+ borderRadius: "9999px",
18679
+ padding: "1px 7px"
18680
+ },
18681
+ children: [
18682
+ correctionCount,
18683
+ " ",
18684
+ correctionCount === 1 ? "event" : "events"
18685
+ ]
18686
+ }
18687
+ )
18688
+ ] })
18689
+ ] }) : (
18690
+ // Bottom row: monospace value + right-edge validation dot (file explorer).
18691
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", paddingLeft: "2px" }, children: [
18692
+ /* @__PURE__ */ jsxRuntime.jsx(
18693
+ "span",
18694
+ {
18695
+ style: {
18696
+ fontSize: "12.5px",
18697
+ color: MUTED2,
18698
+ fontFamily: "ui-monospace, 'Cascadia Code', monospace",
18699
+ flex: 1,
18700
+ minWidth: 0,
18701
+ whiteSpace: "nowrap",
18702
+ overflow: "hidden",
18703
+ textOverflow: "ellipsis"
18704
+ },
18705
+ title: field.value || "\u2014",
18706
+ children: field.value || "\u2014"
18707
+ }
18708
+ ),
18709
+ /* @__PURE__ */ jsxRuntime.jsx(
18710
+ "span",
18711
+ {
18712
+ title: (_d = field.state) != null ? _d : "ok",
18713
+ style: {
18714
+ width: "8px",
18715
+ height: "8px",
18716
+ borderRadius: "9999px",
18717
+ flexShrink: 0,
18718
+ background: dotColor2(field)
18719
+ }
18720
+ }
18721
+ )
18722
+ ] })
18723
+ )
18724
+ ]
18725
+ }
18726
+ );
18727
+ }
18728
+
18729
+ // src/composites/document-field-extraction/FieldDetails.tsx
18730
+ init_ThemeContext();
18731
+ var BADGE_DOT = {
18732
+ // gen-ui semantic dot colors
18733
+ ok: "#15803d",
18734
+ green: "#15803d",
18735
+ warn: "#f59e0b",
18736
+ amber: "#f59e0b",
18737
+ missing: "#dc2626",
18738
+ red: "#dc2626",
18739
+ corrected: "#0364ff"
18740
+ // theme-ok (SECONDARY)
18741
+ };
18742
+ function FieldDetails({
18743
+ summary,
18744
+ fileName,
18745
+ pageCount,
18746
+ pagesProcessed
18747
+ }) {
18748
+ var _a, _b, _c, _d, _e, _f;
18749
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
18750
+ if (!summary) {
18751
+ return /* @__PURE__ */ jsxRuntime.jsxs(
18752
+ "div",
18753
+ {
18754
+ style: {
18755
+ height: "100%",
18756
+ display: "flex",
18757
+ flexDirection: "column",
18758
+ alignItems: "center",
18759
+ justifyContent: "center",
18760
+ gap: "6px",
18761
+ color: MUTED2,
18762
+ textAlign: "center",
18763
+ padding: "24px"
18764
+ },
18765
+ children: [
18766
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "26px", lineHeight: 1 }, children: "\u{1F4C4}" }),
18767
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "14px", fontWeight: 600, color: "var(--foreground)" }, children: "No summary yet" }),
18768
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "12px", maxWidth: "280px" }, children: "This document has no extracted summary." })
18769
+ ]
18770
+ }
18771
+ );
18772
+ }
18773
+ const header = buildHeader(summary);
18774
+ const crumb = buildCrumbLine(summary);
18775
+ const facts = buildFacts(summary, fileName, pageCount, pagesProcessed);
18776
+ 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: [
18777
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { style: { display: "flex", flexDirection: "column", gap: "3px" }, children: [
18778
+ /* @__PURE__ */ jsxRuntime.jsx(
18779
+ "h2",
18780
+ {
18781
+ title: header.title,
18782
+ style: {
18783
+ margin: 0,
18784
+ fontFamily: "var(--font-serif)",
18785
+ fontSize: "20px",
18786
+ fontWeight: 400,
18787
+ letterSpacing: "-0.01em",
18788
+ color: "var(--foreground)",
18789
+ overflow: "hidden",
18790
+ textOverflow: "ellipsis",
18791
+ whiteSpace: "nowrap"
18792
+ },
18793
+ children: header.title
18794
+ }
18795
+ ),
18796
+ header.subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "12px", color: MUTED2 }, children: header.subtitle })
18797
+ ] }),
18798
+ (summary.domain || summary.display_name || summary.domain_group || ((_b = (_a = summary.tags) == null ? void 0 : _a.length) != null ? _b : 0) > 0) && /* @__PURE__ */ jsxRuntime.jsxs(
18799
+ "section",
18800
+ {
18801
+ style: {
18802
+ display: "flex",
18803
+ flexDirection: "column",
18804
+ gap: "6px",
18805
+ padding: "12px 14px",
18806
+ borderRadius: "0.75rem",
18807
+ border: `1px solid ${BORDER4}`,
18808
+ background: PAPER2
18809
+ },
18810
+ children: [
18811
+ summary.domain_group && /* @__PURE__ */ jsxRuntime.jsx(
18812
+ "span",
18813
+ {
18814
+ style: {
18815
+ fontSize: "10px",
18816
+ fontWeight: 600,
18817
+ textTransform: "uppercase",
18818
+ letterSpacing: "0.06em",
18819
+ color: MUTED2
18820
+ },
18821
+ children: summary.domain_group
18822
+ }
18823
+ ),
18824
+ /* @__PURE__ */ jsxRuntime.jsx(
18825
+ "h3",
18826
+ {
18827
+ style: {
18828
+ margin: 0,
18829
+ fontSize: "14px",
18830
+ fontWeight: 600,
18831
+ color: "var(--foreground)"
18832
+ },
18833
+ children: summary.domain || summary.display_name
18834
+ }
18835
+ ),
18836
+ crumb && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "12px", color: MUTED2 }, children: crumb }),
18837
+ ((_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(
18838
+ "span",
18839
+ {
18840
+ style: {
18841
+ fontSize: "10px",
18842
+ fontWeight: 600,
18843
+ padding: "2px 8px",
18844
+ borderRadius: "9999px",
18845
+ background: "white",
18846
+ border: `1px solid ${BORDER4}`,
18847
+ color: MUTED2
18848
+ },
18849
+ children: t
18850
+ },
18851
+ t
18852
+ )) })
18853
+ ]
18854
+ }
18855
+ ),
18856
+ ((_f = (_e = summary.stats) == null ? void 0 : _e.length) != null ? _f : 0) > 0 && /* @__PURE__ */ jsxRuntime.jsx(
18857
+ "div",
18858
+ {
18859
+ style: {
18860
+ display: "grid",
18861
+ gridTemplateColumns: "repeat(auto-fit, minmax(130px, 1fr))",
18862
+ gap: "8px"
18863
+ },
18864
+ children: summary.stats.map((s) => /* @__PURE__ */ jsxRuntime.jsxs(
18865
+ "div",
18866
+ {
18867
+ style: {
18868
+ display: "flex",
18869
+ flexDirection: "column",
18870
+ gap: "2px",
18871
+ padding: "10px 12px",
18872
+ borderRadius: "0.6rem",
18873
+ border: `1px solid ${BORDER4}`,
18874
+ background: "white"
18875
+ },
18876
+ children: [
18877
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "11px", color: MUTED2 }, children: s.label }),
18878
+ /* @__PURE__ */ jsxRuntime.jsx(
18879
+ "span",
18880
+ {
18881
+ title: s.value,
18882
+ style: {
18883
+ fontSize: "15px",
18884
+ fontWeight: 600,
18885
+ color: "var(--foreground)",
18886
+ overflow: "hidden",
18887
+ textOverflow: "ellipsis",
18888
+ whiteSpace: "nowrap"
18889
+ },
18890
+ children: s.value
18891
+ }
18892
+ ),
18893
+ s.caption && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "10px", color: MUTED2 }, children: s.caption })
18894
+ ]
18895
+ },
18896
+ s.field_key
18897
+ ))
18898
+ }
18899
+ ),
18900
+ facts.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("section", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
18901
+ /* @__PURE__ */ jsxRuntime.jsxs(
18902
+ "div",
18903
+ {
18904
+ style: {
18905
+ display: "flex",
18906
+ alignItems: "center",
18907
+ gap: "6px",
18908
+ fontSize: "11px",
18909
+ fontWeight: 600,
18910
+ textTransform: "uppercase",
18911
+ letterSpacing: "0.04em",
18912
+ color: MUTED2
18913
+ },
18914
+ children: [
18915
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u25A4" }),
18916
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Document details" })
18917
+ ]
18918
+ }
18919
+ ),
18920
+ /* @__PURE__ */ jsxRuntime.jsx(
18921
+ "dl",
18922
+ {
18923
+ style: {
18924
+ margin: 0,
18925
+ display: "grid",
18926
+ gridTemplateColumns: "minmax(110px, auto) 1fr",
18927
+ rowGap: "6px",
18928
+ columnGap: "14px"
18929
+ },
18930
+ children: facts.map((f) => {
18931
+ var _a2;
18932
+ return /* @__PURE__ */ jsxRuntime.jsxs(React45__default.default.Fragment, { children: [
18933
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { style: { fontSize: "12px", color: MUTED2 }, children: f.label }),
18934
+ /* @__PURE__ */ jsxRuntime.jsxs(
18935
+ "dd",
18936
+ {
18937
+ title: typeof f.value === "string" ? f.value : void 0,
18938
+ style: {
18939
+ margin: 0,
18940
+ fontSize: "12px",
18941
+ color: "var(--foreground)",
18942
+ display: "flex",
18943
+ alignItems: "center",
18944
+ gap: "6px",
18945
+ wordBreak: "break-word"
18946
+ },
18947
+ children: [
18948
+ f.badge && /* @__PURE__ */ jsxRuntime.jsx(
18949
+ "span",
18950
+ {
18951
+ style: {
18952
+ width: "7px",
18953
+ height: "7px",
18954
+ borderRadius: "9999px",
18955
+ flexShrink: 0,
18956
+ background: (_a2 = BADGE_DOT[f.badge]) != null ? _a2 : SECONDARY2
18957
+ }
18958
+ }
18959
+ ),
18960
+ f.value
18961
+ ]
18962
+ }
18963
+ )
18964
+ ] }, f.key);
18965
+ })
18966
+ }
18967
+ )
18968
+ ] })
18969
+ ] }) });
18970
+ }
18971
+ function buildHeader(summary) {
18972
+ const form = [summary.short_name, summary.display_name].filter(Boolean);
18973
+ const title = summary.organization || form.shift() || summary.domain || "Document";
18974
+ const parts = summary.organization ? [...form] : form;
18975
+ if (summary.tax_year) parts.push(`TY ${summary.tax_year}`);
18976
+ return { title, subtitle: parts.join(" \xB7 ") };
18977
+ }
18978
+ function buildCrumbLine(summary) {
18979
+ const parts = [...summary.crumbs || [], summary.short_name].filter(Boolean);
18980
+ if (parts.length > 0) return parts.join(" \xB7 ");
18981
+ return summary.domain && summary.display_name ? summary.display_name : "";
18982
+ }
18983
+ function buildFacts(summary, fileName, pageCount, pagesProcessed) {
18984
+ const rows = [];
18985
+ if (fileName) rows.push({ key: "file", label: "File", value: fileName });
18986
+ if (summary.display_name) {
18987
+ rows.push({ key: "doctype", label: "Document type", value: summary.display_name });
18988
+ }
18989
+ if (summary.tax_year != null && summary.tax_year !== "") {
18990
+ rows.push({ key: "year", label: "Tax year", value: String(summary.tax_year) });
18991
+ }
18992
+ for (const f of summary.facts || []) {
18993
+ rows.push({ key: f.field_key, label: f.label, value: f.value, badge: f.badge });
18994
+ }
18995
+ if (pageCount) {
18996
+ rows.push({
18997
+ key: "pages",
18998
+ label: "Pages processed",
18999
+ value: `${pagesProcessed != null ? pagesProcessed : pageCount} / ${pageCount}`
19000
+ });
19001
+ }
19002
+ return rows;
19003
+ }
19004
+
19005
+ // src/composites/document-field-extraction/FieldAuditLog.tsx
19006
+ init_ThemeContext();
19007
+ function initials(name) {
19008
+ return name.trim().split(/\s+/).slice(0, 2).map((w) => {
19009
+ var _a;
19010
+ return ((_a = w[0]) != null ? _a : "").toUpperCase();
19011
+ }).join("");
19012
+ }
19013
+ function formatTs(ts) {
19014
+ if (!ts) return "\u2014";
19015
+ const d = new Date(ts);
19016
+ if (Number.isNaN(d.getTime())) return ts;
19017
+ return d.toLocaleString(void 0, {
19018
+ month: "short",
19019
+ day: "numeric",
19020
+ hour: "2-digit",
19021
+ minute: "2-digit"
19022
+ });
19023
+ }
19024
+ function FieldAuditLog({
19025
+ events = [],
19026
+ loading = false,
19027
+ fields = []
19028
+ }) {
19029
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
19030
+ const fieldLabelMap = React45__default.default.useMemo(() => {
19031
+ var _a;
19032
+ const map = {};
19033
+ for (const f of fields) map[f.field_key] = (_a = f.label) != null ? _a : f.field_key;
19034
+ return map;
19035
+ }, [fields]);
19036
+ if (loading) {
19037
+ return /* @__PURE__ */ jsxRuntime.jsx(
19038
+ "div",
19039
+ {
19040
+ style: {
19041
+ flex: 1,
19042
+ display: "flex",
19043
+ alignItems: "center",
19044
+ justifyContent: "center",
19045
+ padding: "32px 20px",
19046
+ fontSize: "13px",
19047
+ color: MUTED2
19048
+ },
19049
+ children: "Loading audit trail\u2026"
19050
+ }
19051
+ );
19052
+ }
19053
+ if (events.length === 0) {
19054
+ return /* @__PURE__ */ jsxRuntime.jsxs(
19055
+ "div",
19056
+ {
19057
+ style: {
19058
+ flex: 1,
19059
+ display: "flex",
19060
+ flexDirection: "column",
19061
+ alignItems: "center",
19062
+ justifyContent: "center",
19063
+ gap: "6px",
19064
+ padding: "32px 20px",
19065
+ textAlign: "center"
19066
+ },
19067
+ children: [
19068
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "13.5px", fontWeight: 600, color: "var(--foreground)" }, children: "No changes yet" }),
19069
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "12px", color: MUTED2, maxWidth: "240px", lineHeight: 1.5 }, children: "Field corrections will appear here." })
19070
+ ]
19071
+ }
19072
+ );
19073
+ }
19074
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", flex: 1, minHeight: 0, overflow: "hidden" }, children: [
19075
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "8px 14px 6px", flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
19076
+ "span",
19077
+ {
19078
+ style: {
19079
+ fontSize: "11.5px",
19080
+ fontWeight: 600,
19081
+ color: MUTED2,
19082
+ textTransform: "uppercase",
19083
+ letterSpacing: "0.04em"
19084
+ },
19085
+ children: [
19086
+ events.length,
19087
+ " ",
19088
+ events.length === 1 ? "change" : "changes"
19089
+ ]
19090
+ }
19091
+ ) }),
19092
+ /* @__PURE__ */ jsxRuntime.jsx("ol", { style: { listStyle: "none", margin: 0, padding: "0 0 16px", overflowY: "auto", flex: 1, minHeight: 0 }, children: events.map((ev) => {
19093
+ var _a, _b;
19094
+ const rawLabel = (_a = fieldLabelMap[ev.field_key]) != null ? _a : ev.field_key;
19095
+ const label = prettyLabel(rawLabel);
19096
+ const isAI = ev.actor_type === "system" || ev.event_type === "ai_corrected" || ev.event_type === "ai_extracted";
19097
+ const actor = isAI ? "AI" : ev.actor_name || "Unknown";
19098
+ const eventLabel = isAI ? "Re-extracted" : "Corrected";
19099
+ return /* @__PURE__ */ jsxRuntime.jsxs(
19100
+ "li",
19101
+ {
19102
+ "data-testid": "audit-row",
19103
+ style: { display: "flex", gap: "10px", padding: "10px 14px", borderBottom: `1px solid ${BORDER4}` },
19104
+ children: [
19105
+ /* @__PURE__ */ jsxRuntime.jsx(
19106
+ "div",
19107
+ {
19108
+ title: isAI ? "AI extraction" : actor,
19109
+ style: {
19110
+ flexShrink: 0,
19111
+ width: "28px",
19112
+ height: "28px",
19113
+ borderRadius: "50%",
19114
+ background: isAI ? "#dcfce7" : "#eff6ff",
19115
+ color: isAI ? "#15803d" : SECONDARY2,
19116
+ fontSize: "10.5px",
19117
+ fontWeight: 700,
19118
+ display: "flex",
19119
+ alignItems: "center",
19120
+ justifyContent: "center",
19121
+ marginTop: "1px"
19122
+ },
19123
+ children: isAI ? "\u2728" : initials(actor)
19124
+ }
19125
+ ),
19126
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "3px", flex: 1, minWidth: 0 }, children: [
19127
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: "6px", flexWrap: "wrap" }, children: [
19128
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "12.5px", fontWeight: 600, color: isAI ? "#15803d" : "var(--foreground)" }, children: actor }),
19129
+ /* @__PURE__ */ jsxRuntime.jsx(
19130
+ "span",
19131
+ {
19132
+ style: {
19133
+ fontSize: "10.5px",
19134
+ fontWeight: 600,
19135
+ color: MUTED2,
19136
+ background: PAPER2,
19137
+ borderRadius: "4px",
19138
+ padding: "1px 6px",
19139
+ whiteSpace: "nowrap",
19140
+ flexShrink: 0
19141
+ },
19142
+ children: eventLabel
19143
+ }
19144
+ ),
19145
+ /* @__PURE__ */ jsxRuntime.jsx(
19146
+ "span",
19147
+ {
19148
+ style: {
19149
+ fontSize: "12px",
19150
+ color: MUTED2,
19151
+ flex: 1,
19152
+ minWidth: 0,
19153
+ whiteSpace: "nowrap",
19154
+ overflow: "hidden",
19155
+ textOverflow: "ellipsis"
19156
+ },
19157
+ children: label
19158
+ }
19159
+ ),
19160
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "11px", color: MUTED2, flexShrink: 0 }, children: formatTs(ev.created_at) })
19161
+ ] }),
19162
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
19163
+ ev.previous_value != null && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
19164
+ /* @__PURE__ */ jsxRuntime.jsx(
19165
+ "span",
19166
+ {
19167
+ style: {
19168
+ fontSize: "12px",
19169
+ fontFamily: "ui-monospace, monospace",
19170
+ color: MUTED2,
19171
+ textDecoration: "line-through"
19172
+ },
19173
+ children: ev.previous_value
19174
+ }
19175
+ ),
19176
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "11px", color: BORDER4 }, children: "\u2192" })
19177
+ ] }),
19178
+ /* @__PURE__ */ jsxRuntime.jsx(
19179
+ "span",
19180
+ {
19181
+ style: {
19182
+ fontSize: "12px",
19183
+ fontFamily: "ui-monospace, monospace",
19184
+ fontWeight: 600,
19185
+ color: "var(--foreground)"
19186
+ },
19187
+ children: (_b = ev.new_value) != null ? _b : "\u2014"
19188
+ }
19189
+ )
19190
+ ] }),
19191
+ ev.reason && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { margin: "2px 0 0", fontSize: "11.5px", color: MUTED2, fontStyle: "italic" }, children: [
19192
+ "\u201C",
19193
+ ev.reason,
19194
+ "\u201D"
19195
+ ] })
19196
+ ] })
19197
+ ]
19198
+ },
19199
+ ev.id
19200
+ );
19201
+ }) })
19202
+ ] });
19203
+ }
19204
+ var TIER_COLORS2 = {
19205
+ green: "#15803d",
19206
+ amber: "#f59e0b",
19207
+ red: "#dc2626"
19208
+ };
19209
+ function fieldColor2(f, secondary) {
19210
+ var _a, _b;
19211
+ if (f.state === "corrected") return secondary;
19212
+ return (_b = TIER_COLORS2[(_a = f.confidence_tier) != null ? _a : "amber"]) != null ? _b : TIER_COLORS2.amber;
19213
+ }
19214
+ function hexToRgba2(hex, alpha) {
19215
+ const h = hex.replace("#", "");
19216
+ const r = parseInt(h.slice(0, 2), 16);
19217
+ const g = parseInt(h.slice(2, 4), 16);
19218
+ const b = parseInt(h.slice(4, 6), 16);
19219
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
19220
+ }
19221
+ function PageOverlay({
19222
+ page,
19223
+ fields,
19224
+ selectedKey,
19225
+ onSelect,
19226
+ secondary
19227
+ }) {
19228
+ const { PAPER: PAPER2, MUTED: MUTED2 } = useTheme();
19229
+ const imgRef = React45__default.default.useRef(null);
19230
+ const selectedBoxRef = React45__default.default.useRef(null);
19231
+ const [px, setPx] = React45__default.default.useState(null);
19232
+ React45__default.default.useEffect(() => {
19233
+ const el = imgRef.current;
19234
+ if (!el) return;
19235
+ const measure = () => {
19236
+ if (el.clientWidth && el.clientHeight) {
19237
+ setPx({ wPx: el.clientWidth, hPx: el.clientHeight });
19238
+ }
19239
+ };
19240
+ measure();
19241
+ if (typeof ResizeObserver === "undefined") return;
19242
+ const ro = new ResizeObserver(measure);
19243
+ ro.observe(el);
19244
+ return () => ro.disconnect();
19245
+ }, [page.imageUrl]);
19246
+ React45__default.default.useEffect(() => {
19247
+ if (!selectedKey) return;
19248
+ if (!fields.some((f) => f.field_key === selectedKey && f.bbox)) return;
19249
+ const el = selectedBoxRef.current;
19250
+ if (el && typeof el.scrollIntoView === "function") {
19251
+ el.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
19252
+ }
19253
+ }, [selectedKey, fields, px]);
19254
+ const pagePts = { wPts: page.width_pt, hPts: page.height_pt };
19255
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", width: "100%", lineHeight: 0 }, children: [
19256
+ page.imageUrl ? /* @__PURE__ */ jsxRuntime.jsx(
19257
+ "img",
19258
+ {
19259
+ ref: imgRef,
19260
+ src: page.imageUrl,
19261
+ alt: `Page ${page.page + 1}`,
19262
+ onLoad: () => {
19263
+ const el = imgRef.current;
19264
+ if (el && el.clientWidth && el.clientHeight) {
19265
+ setPx({ wPx: el.clientWidth, hPx: el.clientHeight });
19266
+ }
19267
+ },
19268
+ style: { display: "block", width: "100%", height: "auto" }
19269
+ }
19270
+ ) : (
19271
+ // No resolved image (host couldn't resolve the raster) — keep the
19272
+ // aspect box so cards still make sense, but show nothing to overlay on.
19273
+ /* @__PURE__ */ jsxRuntime.jsxs(
19274
+ "div",
19275
+ {
19276
+ style: {
19277
+ width: "100%",
19278
+ aspectRatio: `${page.width_pt} / ${page.height_pt}`,
19279
+ background: PAPER2,
19280
+ display: "flex",
19281
+ alignItems: "center",
19282
+ justifyContent: "center",
19283
+ fontSize: "12px",
19284
+ color: MUTED2,
19285
+ lineHeight: 1.4
19286
+ },
19287
+ children: [
19288
+ "Page ",
19289
+ page.page + 1,
19290
+ " image unavailable"
19291
+ ]
19292
+ }
19293
+ )
19294
+ ),
19295
+ px && page.imageUrl && fields.map((f) => {
19296
+ var _a;
19297
+ const rect = bboxToRect((_a = f.bbox) != null ? _a : null, pagePts, px);
19298
+ if (!rect) return null;
19299
+ const color = fieldColor2(f, secondary);
19300
+ const selected = selectedKey === f.field_key;
19301
+ return /* @__PURE__ */ jsxRuntime.jsx(
19302
+ "div",
19303
+ {
19304
+ ref: selected ? selectedBoxRef : null,
19305
+ "data-testid": "bbox-rect",
19306
+ "data-field-key": f.field_key,
19307
+ "data-selected": selected ? "true" : "false",
19308
+ onClick: () => onSelect(selected ? null : f.field_key),
19309
+ title: `${f.label}: ${f.value}`,
19310
+ style: {
19311
+ position: "absolute",
19312
+ left: `${rect.left}px`,
19313
+ top: `${rect.top}px`,
19314
+ width: `${rect.width}px`,
19315
+ height: `${rect.height}px`,
19316
+ border: `1px solid ${color}`,
19317
+ background: hexToRgba2(color, selected ? 0.28 : 0.12),
19318
+ boxShadow: selected ? `0 0 0 2px ${hexToRgba2(color, 0.5)}` : "none",
19319
+ borderRadius: "2px",
19320
+ cursor: "pointer",
19321
+ transition: "background 0.15s, box-shadow 0.15s"
19322
+ }
19323
+ },
19324
+ f.field_key
19325
+ );
19326
+ })
19327
+ ] });
19328
+ }
19329
+ function ExtractionDetail({
19330
+ pages,
19331
+ orderedFields,
19332
+ fieldsByPage,
19333
+ selectedKey,
19334
+ setSelectedKey,
19335
+ onFieldSave,
19336
+ correctionCounts,
19337
+ tab,
19338
+ setTab,
19339
+ editable,
19340
+ summary,
19341
+ fileName,
19342
+ pageCount,
19343
+ pagesProcessed,
19344
+ auditEvents,
19345
+ auditLoading
19346
+ }) {
19347
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
19348
+ const selectedCardRef = React45__default.default.useRef(null);
19349
+ React45__default.default.useEffect(() => {
19350
+ if (!selectedKey || tab !== "fields") return;
19351
+ const el = selectedCardRef.current;
19352
+ if (el && typeof el.scrollIntoView === "function") {
19353
+ el.scrollIntoView({ behavior: "smooth", block: "nearest" });
19354
+ }
19355
+ }, [selectedKey, tab]);
19356
+ const tabs = [
19357
+ { key: "details", label: "Details" },
19358
+ { key: "fields", label: "Fields", count: orderedFields.length }
19359
+ ];
19360
+ if (editable) tabs.push({ key: "audit", label: "Audit Trails", count: (auditEvents == null ? void 0 : auditEvents.length) || void 0 });
19361
+ return /* @__PURE__ */ jsxRuntime.jsxs(
19362
+ "div",
19363
+ {
19364
+ style: {
19365
+ display: "grid",
19366
+ gridTemplateColumns: "minmax(0, 3fr) minmax(260px, 1fr)",
19367
+ gap: "12px",
19368
+ height: "100%",
19369
+ minHeight: 0
19370
+ },
19371
+ children: [
19372
+ /* @__PURE__ */ jsxRuntime.jsx(
19373
+ "div",
19374
+ {
19375
+ style: {
19376
+ display: "flex",
19377
+ flexDirection: "column",
19378
+ gap: "10px",
19379
+ borderRadius: "0.75rem",
19380
+ border: `1px solid ${BORDER4}`,
19381
+ overflowY: "auto",
19382
+ minHeight: 0
19383
+ },
19384
+ children: pages.map((pg) => /* @__PURE__ */ jsxRuntime.jsx(
19385
+ PageOverlay,
19386
+ {
19387
+ page: pg,
19388
+ fields: fieldsByPage(pg.page),
19389
+ selectedKey,
19390
+ onSelect: (key) => {
19391
+ setSelectedKey(key);
19392
+ if (key) setTab("fields");
19393
+ },
19394
+ secondary: SECONDARY2
19395
+ },
19396
+ pg.page
19397
+ ))
19398
+ }
19399
+ ),
19400
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", minWidth: 0, minHeight: 0 }, children: [
19401
+ /* @__PURE__ */ jsxRuntime.jsx(
19402
+ "div",
19403
+ {
19404
+ style: {
19405
+ display: "flex",
19406
+ gap: "16px",
19407
+ borderBottom: `1px solid ${BORDER4}`,
19408
+ flexShrink: 0,
19409
+ marginBottom: "10px"
19410
+ },
19411
+ children: tabs.map((t) => {
19412
+ const active = tab === t.key;
19413
+ return /* @__PURE__ */ jsxRuntime.jsxs(
19414
+ "button",
19415
+ {
19416
+ type: "button",
19417
+ onClick: () => setTab(t.key),
19418
+ "data-testid": `tab-${t.key}`,
19419
+ style: {
19420
+ appearance: "none",
19421
+ background: "transparent",
19422
+ borderTop: "none",
19423
+ borderLeft: "none",
19424
+ borderRight: "none",
19425
+ borderBottom: `2px solid ${active ? SECONDARY2 : "transparent"}`,
19426
+ padding: "6px 2px",
19427
+ marginBottom: "-1px",
19428
+ cursor: "pointer",
19429
+ fontSize: "13px",
19430
+ fontWeight: 600,
19431
+ color: active ? SECONDARY2 : MUTED2,
19432
+ display: "inline-flex",
19433
+ alignItems: "center",
19434
+ gap: "6px"
19435
+ },
19436
+ children: [
19437
+ t.label,
19438
+ typeof t.count === "number" && /* @__PURE__ */ jsxRuntime.jsx(
19439
+ "span",
19440
+ {
19441
+ style: {
19442
+ fontSize: "11px",
19443
+ fontWeight: 600,
19444
+ padding: "1px 7px",
19445
+ borderRadius: "9999px",
19446
+ background: active ? "#eff6ff" : PAPER2,
19447
+ color: active ? SECONDARY2 : MUTED2
19448
+ },
19449
+ children: t.count
19450
+ }
19451
+ )
19452
+ ]
19453
+ },
19454
+ t.key
19455
+ );
19456
+ })
19457
+ }
19458
+ ),
19459
+ tab === "details" ? /* @__PURE__ */ jsxRuntime.jsx(
19460
+ FieldDetails,
19461
+ {
19462
+ summary,
19463
+ fileName,
19464
+ pageCount,
19465
+ pagesProcessed
19466
+ }
19467
+ ) : tab === "audit" ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minHeight: 0, overflowY: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsx(
19468
+ FieldAuditLog,
19469
+ {
19470
+ events: auditEvents != null ? auditEvents : [],
19471
+ loading: auditLoading != null ? auditLoading : false,
19472
+ fields: orderedFields.map((f) => ({ field_key: f.field_key, label: f.label }))
19473
+ }
19474
+ ) }) : /* @__PURE__ */ jsxRuntime.jsxs(
19475
+ "div",
19476
+ {
19477
+ style: {
19478
+ display: "flex",
19479
+ flexDirection: "column",
19480
+ minHeight: 0,
19481
+ overflowY: "auto",
19482
+ paddingRight: "4px"
19483
+ },
19484
+ children: [
19485
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "12px", color: MUTED2, padding: "0 0 8px 2px", flexShrink: 0 }, children: [
19486
+ orderedFields.length,
19487
+ " extracted"
19488
+ ] }),
19489
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: orderedFields.map((f) => {
19490
+ var _a;
19491
+ const selected = selectedKey === f.field_key;
19492
+ return /* @__PURE__ */ jsxRuntime.jsx(
19493
+ FieldDetail,
19494
+ {
19495
+ field: f,
19496
+ selected,
19497
+ onSelect: setSelectedKey,
19498
+ onSave: onFieldSave,
19499
+ correctionCount: (_a = correctionCounts == null ? void 0 : correctionCounts[f.field_key]) != null ? _a : 0,
19500
+ cardRef: selected ? selectedCardRef : void 0
19501
+ },
19502
+ f.field_key
19503
+ );
19504
+ }) })
19505
+ ]
19506
+ }
19507
+ )
19508
+ ] })
19509
+ ]
19510
+ }
19511
+ );
19512
+ }
19513
+ function ExtractionModal({
19514
+ open,
19515
+ onClose,
19516
+ title,
19517
+ children
19518
+ }) {
19519
+ const { BORDER: BORDER4, MUTED: MUTED2 } = useTheme();
19520
+ React45__default.default.useEffect(() => {
19521
+ if (!open) return;
19522
+ const onKey = (e) => {
19523
+ if (e.key === "Escape") onClose();
19524
+ };
19525
+ window.addEventListener("keydown", onKey);
19526
+ const prev = document.body.style.overflow;
19527
+ document.body.style.overflow = "hidden";
19528
+ return () => {
19529
+ window.removeEventListener("keydown", onKey);
19530
+ document.body.style.overflow = prev;
19531
+ };
19532
+ }, [open, onClose]);
19533
+ if (!open || typeof document === "undefined") return null;
19534
+ return reactDom.createPortal(
19535
+ /* @__PURE__ */ jsxRuntime.jsx(
19536
+ "div",
19537
+ {
19538
+ role: "dialog",
19539
+ "aria-modal": "true",
19540
+ "aria-label": title,
19541
+ onClick: onClose,
19542
+ style: {
19543
+ position: "fixed",
19544
+ inset: 0,
19545
+ zIndex: 2147483e3,
19546
+ background: "rgba(0,0,0,0.5)",
19547
+ display: "flex",
19548
+ alignItems: "center",
19549
+ justifyContent: "center",
19550
+ padding: "4vh 4vw",
19551
+ backdropFilter: "blur(2px)"
19552
+ },
19553
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
19554
+ "div",
19555
+ {
19556
+ onClick: (e) => e.stopPropagation(),
19557
+ style: {
19558
+ width: "90vw",
19559
+ height: "90vh",
19560
+ background: "white",
19561
+ borderRadius: "0.875rem",
19562
+ border: `1px solid ${BORDER4}`,
19563
+ boxShadow: "0 20px 60px rgba(0,0,0,0.30)",
19564
+ display: "flex",
19565
+ flexDirection: "column",
19566
+ overflow: "hidden"
19567
+ },
19568
+ children: [
19569
+ /* @__PURE__ */ jsxRuntime.jsxs(
19570
+ "div",
19571
+ {
19572
+ style: {
19573
+ display: "flex",
19574
+ alignItems: "center",
19575
+ gap: "10px",
19576
+ padding: "11px 16px",
19577
+ borderBottom: `1px solid ${BORDER4}`,
19578
+ flexShrink: 0
19579
+ },
19580
+ children: [
19581
+ /* @__PURE__ */ jsxRuntime.jsx(
19582
+ "span",
19583
+ {
19584
+ style: {
19585
+ flex: 1,
19586
+ minWidth: 0,
19587
+ fontFamily: "var(--font-serif)",
19588
+ fontSize: "16px",
19589
+ fontWeight: 400,
19590
+ letterSpacing: "-0.01em",
19591
+ color: "var(--foreground)",
19592
+ overflow: "hidden",
19593
+ textOverflow: "ellipsis",
19594
+ whiteSpace: "nowrap"
19595
+ },
19596
+ children: title
19597
+ }
19598
+ ),
19599
+ /* @__PURE__ */ jsxRuntime.jsx(
19600
+ "button",
19601
+ {
19602
+ type: "button",
19603
+ "aria-label": "Close",
19604
+ onClick: onClose,
19605
+ style: {
19606
+ border: `1px solid ${BORDER4}`,
19607
+ borderRadius: "8px",
19608
+ background: "white",
19609
+ cursor: "pointer",
19610
+ padding: "5px 9px",
19611
+ fontSize: "13px",
19612
+ color: MUTED2,
19613
+ lineHeight: 1
19614
+ },
19615
+ children: "\u2715"
19616
+ }
19617
+ )
19618
+ ]
19619
+ }
19620
+ ),
19621
+ /* @__PURE__ */ jsxRuntime.jsx(
19622
+ "div",
19623
+ {
19624
+ style: {
19625
+ flex: 1,
19626
+ minHeight: 0,
19627
+ overflow: "hidden",
19628
+ display: "flex",
19629
+ flexDirection: "column",
19630
+ padding: "14px 16px"
19631
+ },
19632
+ children
19633
+ }
19634
+ )
19635
+ ]
19636
+ }
19637
+ )
19638
+ }
19639
+ ),
19640
+ document.body
19641
+ );
19642
+ }
19643
+ function DocumentFieldExtractionResolver(p) {
19644
+ var _a, _b;
19645
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2 } = useTheme();
19646
+ const [selectedKey, setSelectedKey] = React45__default.default.useState(null);
19647
+ const [open, setOpen] = React45__default.default.useState(false);
19648
+ const [tab, setTab] = React45__default.default.useState("fields");
19649
+ const pages = (_a = p.pages) != null ? _a : [];
19650
+ const fields = (_b = p.fields) != null ? _b : [];
19651
+ const editable = typeof p.onFieldSave === "function";
19652
+ const onLoadAudit = p.onLoadAudit;
19653
+ React45__default.default.useEffect(() => {
19654
+ if (tab === "audit" && onLoadAudit) {
19655
+ onLoadAudit();
19656
+ }
19657
+ }, [tab, onLoadAudit]);
19658
+ const correctionCounts = React45__default.default.useMemo(() => {
19659
+ var _a2, _b2;
19660
+ const counts = {};
19661
+ for (const ev of (_a2 = p.auditEvents) != null ? _a2 : []) {
19662
+ const human = ev.actor_type !== "system" && ev.event_type !== "ai_extracted";
19663
+ if (human) counts[ev.field_key] = ((_b2 = counts[ev.field_key]) != null ? _b2 : 0) + 1;
19664
+ }
19665
+ return counts;
19666
+ }, [p.auditEvents]);
19667
+ const orderedFields = [...fields].sort((a, b) => {
19668
+ var _a2, _b2;
19669
+ if (!!a.is_primary !== !!b.is_primary) return a.is_primary ? -1 : 1;
19670
+ return ((_a2 = b.confidence) != null ? _a2 : 0) - ((_b2 = a.confidence) != null ? _b2 : 0);
19671
+ });
19672
+ const fieldsByPage = (pageNo) => fields.filter((f) => f.page === pageNo);
19673
+ const csvCols = [
19674
+ { key: "label", label: "Field" },
19675
+ { key: "value", label: "Value" },
19676
+ { key: "page", label: "Page" },
19677
+ { key: "confidence", label: "Confidence" },
19678
+ { key: "badge", label: "Badge" },
19679
+ { key: "state", label: "State" }
19680
+ ];
19681
+ const csvRows = orderedFields.map((f) => {
19682
+ var _a2, _b2, _c;
19683
+ return {
19684
+ label: f.label,
19685
+ value: f.value,
19686
+ page: f.page + 1,
19687
+ confidence: (_a2 = f.confidence) != null ? _a2 : "",
19688
+ badge: (_b2 = f.badge) != null ? _b2 : "",
19689
+ state: (_c = f.state) != null ? _c : ""
19690
+ };
19691
+ });
19692
+ const title = p.file_name || (p.doc_type ? `${p.doc_type} \u2014 extracted fields` : "Extracted fields");
19693
+ const tierCounts = fields.reduce(
19694
+ (acc, f) => {
19695
+ var _a2;
19696
+ const t = (_a2 = f.confidence_tier) != null ? _a2 : "amber";
19697
+ if (t === "green") acc.high += 1;
19698
+ else if (t === "red") acc.low += 1;
19699
+ else acc.med += 1;
19700
+ return acc;
19701
+ },
19702
+ { high: 0, med: 0, low: 0 }
19703
+ );
19704
+ const chips = [
19705
+ { n: tierCounts.high, label: "high", color: TIER_COLORS2.green },
19706
+ { n: tierCounts.med, label: "medium", color: TIER_COLORS2.amber },
19707
+ { n: tierCounts.low, label: "low", color: TIER_COLORS2.red }
19708
+ ].filter((c) => c.n > 0);
19709
+ const thumb = pages.find((pg) => pg.imageUrl);
19710
+ return /* @__PURE__ */ jsxRuntime.jsxs(
19711
+ ComponentActions,
19712
+ {
19713
+ filename: "document-fields",
19714
+ onDownloadCSV: () => downloadCSV(csvCols, csvRows, "document-fields"),
19715
+ children: [
19716
+ /* @__PURE__ */ jsxRuntime.jsxs(
19717
+ "div",
19718
+ {
19719
+ role: "button",
19720
+ tabIndex: 0,
19721
+ onClick: () => setOpen(true),
19722
+ onKeyDown: (e) => {
19723
+ if (e.key === "Enter" || e.key === " ") {
19724
+ e.preventDefault();
19725
+ setOpen(true);
19726
+ }
19727
+ },
19728
+ style: {
19729
+ display: "flex",
19730
+ alignItems: "stretch",
19731
+ gap: "12px",
19732
+ padding: "12px",
19733
+ width: "100%",
19734
+ maxWidth: "440px",
19735
+ borderRadius: "0.75rem",
19736
+ border: `1px solid ${BORDER4}`,
19737
+ background: "white",
19738
+ cursor: "pointer",
19739
+ textAlign: "left",
19740
+ boxShadow: "0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.05)"
19741
+ },
19742
+ children: [
19743
+ /* @__PURE__ */ jsxRuntime.jsx(
19744
+ "div",
19745
+ {
19746
+ style: {
19747
+ width: "64px",
19748
+ flexShrink: 0,
19749
+ borderRadius: "0.5rem",
19750
+ border: `1px solid ${BORDER4}`,
19751
+ background: PAPER2,
19752
+ overflow: "hidden",
19753
+ display: "flex",
19754
+ alignItems: "center",
19755
+ justifyContent: "center"
19756
+ },
19757
+ children: (thumb == null ? void 0 : thumb.imageUrl) ? /* @__PURE__ */ jsxRuntime.jsx(
19758
+ "img",
19759
+ {
19760
+ src: thumb.imageUrl,
19761
+ alt: "Document preview",
19762
+ style: { width: "100%", height: "auto", display: "block" }
19763
+ }
19764
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "22px", lineHeight: 1, padding: "16px 0" }, children: "\u{1F4C4}" })
19765
+ }
19766
+ ),
19767
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "6px" }, children: [
19768
+ /* @__PURE__ */ jsxRuntime.jsx(
19769
+ "p",
19770
+ {
19771
+ style: {
19772
+ fontFamily: "var(--font-serif)",
19773
+ fontSize: "15px",
19774
+ fontWeight: 400,
19775
+ color: "var(--foreground)",
19776
+ letterSpacing: "-0.01em",
19777
+ margin: 0,
19778
+ overflow: "hidden",
19779
+ textOverflow: "ellipsis",
19780
+ whiteSpace: "nowrap"
19781
+ },
19782
+ children: p.file_name || p.doc_type || "Document"
19783
+ }
19784
+ ),
19785
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "12px", color: MUTED2 }, children: [
19786
+ fields.length,
19787
+ " field",
19788
+ fields.length === 1 ? "" : "s",
19789
+ " extracted \xB7 ",
19790
+ pages.length,
19791
+ " page",
19792
+ pages.length === 1 ? "" : "s"
19793
+ ] }),
19794
+ chips.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "5px" }, children: chips.map((c) => /* @__PURE__ */ jsxRuntime.jsxs(
19795
+ "span",
19796
+ {
19797
+ style: {
19798
+ display: "inline-flex",
19799
+ alignItems: "center",
19800
+ gap: "4px",
19801
+ fontSize: "10px",
19802
+ fontWeight: 600,
19803
+ padding: "2px 7px",
19804
+ borderRadius: "9999px",
19805
+ background: hexToRgba2(c.color, 0.12),
19806
+ color: c.color
19807
+ },
19808
+ children: [
19809
+ /* @__PURE__ */ jsxRuntime.jsx(
19810
+ "span",
19811
+ {
19812
+ style: {
19813
+ width: "6px",
19814
+ height: "6px",
19815
+ borderRadius: "9999px",
19816
+ background: c.color
19817
+ }
19818
+ }
19819
+ ),
19820
+ c.n,
19821
+ " ",
19822
+ c.label
19823
+ ]
19824
+ },
19825
+ c.label
19826
+ )) }),
19827
+ /* @__PURE__ */ jsxRuntime.jsx(
19828
+ "span",
19829
+ {
19830
+ style: {
19831
+ marginTop: "2px",
19832
+ alignSelf: "flex-start",
19833
+ fontSize: "12px",
19834
+ fontWeight: 600,
19835
+ padding: "6px 12px",
19836
+ borderRadius: "0.5rem",
19837
+ background: "var(--foreground)",
19838
+ color: "white"
19839
+ },
19840
+ children: "View & edit fields"
19841
+ }
19842
+ )
19843
+ ] })
19844
+ ]
19845
+ }
19846
+ ),
19847
+ /* @__PURE__ */ jsxRuntime.jsx(ExtractionModal, { open, onClose: () => setOpen(false), title, children: /* @__PURE__ */ jsxRuntime.jsx(
19848
+ ExtractionDetail,
19849
+ {
19850
+ pages,
19851
+ orderedFields,
19852
+ fieldsByPage,
19853
+ selectedKey,
19854
+ setSelectedKey,
19855
+ onFieldSave: p.onFieldSave,
19856
+ correctionCounts,
19857
+ tab,
19858
+ setTab,
19859
+ editable,
19860
+ summary: p.summary,
19861
+ fileName: p.file_name,
19862
+ pageCount: p.page_count,
19863
+ pagesProcessed: p.pages_processed,
19864
+ auditEvents: p.auditEvents,
19865
+ auditLoading: p.auditLoading
19866
+ }
19867
+ ) })
19868
+ ]
19869
+ }
19870
+ );
19871
+ }
19872
+ init_ThemeContext();
19873
+ var SEVERITY_COLORS = {
19874
+ high: { color: "#dc2626", bg: "#fef2f2" },
19875
+ medium: { color: "#f59e0b", bg: "#fff7ed" },
19876
+ low: { color: "#777777", bg: "#f2f2f2" }
19877
+ };
19878
+ var GREEN3 = "#15803d";
19879
+ var GREEN_SOFT = "#dcfce7";
19880
+ var STACK_BELOW = 380;
19881
+ function formatAmount2(amount, currency = "USD") {
19882
+ var _a, _b;
19883
+ const abs = Math.abs(amount);
19884
+ const sign = amount < 0 ? "-" : "";
19885
+ let body;
19886
+ if (abs >= 1e6) body = `${(abs / 1e6).toFixed(abs >= 1e7 ? 0 : 1)}M`;
19887
+ else if (abs >= 1e3) body = `${(abs / 1e3).toFixed(abs >= 1e4 ? 0 : 1)}K`;
19888
+ else body = `${abs}`;
19889
+ let symbol = "$";
19890
+ try {
19891
+ const parts = new Intl.NumberFormat("en-US", {
19892
+ style: "currency",
19893
+ currency,
19894
+ maximumFractionDigits: 0
19895
+ }).formatToParts(0);
19896
+ symbol = (_b = (_a = parts.find((p) => p.type === "currency")) == null ? void 0 : _a.value) != null ? _b : "$";
19897
+ } catch (e) {
19898
+ symbol = "$";
19899
+ }
19900
+ return `${sign}${symbol}${body}`;
19901
+ }
19902
+ function useContainerWidth2(ref) {
19903
+ const [w, setW] = React45__default.default.useState(0);
19904
+ React45__default.default.useLayoutEffect(() => {
19905
+ const el = ref.current;
19906
+ if (!el || typeof ResizeObserver === "undefined") return;
19907
+ const ro = new ResizeObserver((entries) => {
19908
+ var _a;
19909
+ const cr = (_a = entries[0]) == null ? void 0 : _a.contentRect;
19910
+ if (cr) setW(cr.width);
19911
+ });
19912
+ ro.observe(el);
19913
+ setW(el.getBoundingClientRect().width);
19914
+ return () => ro.disconnect();
19915
+ }, [ref]);
19916
+ return w;
19917
+ }
19918
+ var KEYFRAMES2 = `
19919
+ @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
19920
+ .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
19921
+ @media (prefers-reduced-motion: reduce){
19922
+ .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
19923
+ }`;
19924
+ function SparkCheck({ size, color }) {
19925
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
19926
+ "path",
19927
+ {
19928
+ d: "M5 13l4 4L19 7",
19929
+ stroke: color,
19930
+ strokeWidth: 2.5,
19931
+ strokeLinecap: "round",
19932
+ strokeLinejoin: "round"
19933
+ }
19934
+ ) });
19935
+ }
19936
+ function FlagPill({ flag }) {
19937
+ var _a;
19938
+ const sev = (_a = flag.severity) != null ? _a : "medium";
19939
+ const { color, bg } = SEVERITY_COLORS[sev];
19940
+ return /* @__PURE__ */ jsxRuntime.jsxs(
19941
+ "span",
19942
+ {
19943
+ style: {
19944
+ display: "inline-flex",
19945
+ alignItems: "center",
19946
+ gap: 5,
19947
+ fontSize: 11,
19948
+ fontWeight: 600,
19949
+ padding: "3px 9px",
19950
+ borderRadius: 9999,
19951
+ background: bg,
19952
+ color,
19953
+ lineHeight: 1.2
19954
+ },
19955
+ children: [
19956
+ /* @__PURE__ */ jsxRuntime.jsx(
19957
+ "span",
19958
+ {
19959
+ "aria-hidden": "true",
19960
+ style: { width: 6, height: 6, borderRadius: "50%", background: color, flexShrink: 0 }
19961
+ }
19962
+ ),
19963
+ flag.field ? `${flag.field}: ${flag.issue}` : flag.issue
19964
+ ]
18079
19965
  }
18080
19966
  );
18081
19967
  }
@@ -18087,7 +19973,7 @@ function DecisionCardRenderer({
18087
19973
  }) {
18088
19974
  var _a, _b;
18089
19975
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
18090
- const rootRef = React41__default.default.useRef(null);
19976
+ const rootRef = React45__default.default.useRef(null);
18091
19977
  const width = useContainerWidth2(rootRef);
18092
19978
  const stacked = width > 0 && width < STACK_BELOW;
18093
19979
  const options = (_a = data.options) != null ? _a : [];
@@ -18344,8 +20230,8 @@ function DecisionCardResolver(p) {
18344
20230
  const decisionId = (_a = p.id) != null ? _a : p.title;
18345
20231
  const hostResolved = resolvedDecisions == null ? void 0 : resolvedDecisions[decisionId];
18346
20232
  const initial = (_c = hostResolved != null ? hostResolved : (_b = p.resolved) == null ? void 0 : _b.option) != null ? _c : null;
18347
- const [localResolved, setLocalResolved] = React41__default.default.useState(initial);
18348
- React41__default.default.useEffect(() => {
20233
+ const [localResolved, setLocalResolved] = React45__default.default.useState(initial);
20234
+ React45__default.default.useEffect(() => {
18349
20235
  if (hostResolved !== void 0) setLocalResolved(hostResolved);
18350
20236
  }, [hostResolved]);
18351
20237
  const resolved = hostResolved != null ? hostResolved : localResolved;
@@ -18370,6 +20256,317 @@ function DecisionCardResolver(p) {
18370
20256
  }
18371
20257
  ) });
18372
20258
  }
20259
+ init_ThemeContext();
20260
+ var CONNECTED_GREEN3 = "#15803d";
20261
+ var CONNECTED_GREEN_BG = "#dcfce7";
20262
+ var PENDING_AMBER = "#92400e";
20263
+ var PENDING_AMBER_BG = "#fff7ed";
20264
+ var CARD_TITLE = "Authentication required";
20265
+ var TRUST_FOOTER = "Credentials not stored by Adopt";
20266
+ var DEFAULT_STEPS = (app, ctaLabel, connected) => connected ? [
20267
+ `Click ${ctaLabel} below to open ${app} in a new tab.`,
20268
+ "Confirm you are signed in \u2014 re-authenticate if prompted.",
20269
+ "Return here \u2014 the request continues automatically."
20270
+ ] : [
20271
+ `Click ${ctaLabel} below to open the sign-in page.`,
20272
+ `Sign in with your ${app} credentials \u2014 SSO is supported.`,
20273
+ "Return here \u2014 the request resumes automatically."
20274
+ ];
20275
+ function humanizeApp(raw) {
20276
+ const v = raw.trim();
20277
+ if (!v) return v;
20278
+ const looksLikeSlug = /^[a-z0-9]+([_-][a-z0-9]+)*$/.test(v);
20279
+ if (!looksLikeSlug) return v;
20280
+ return v.split(/[_-]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
20281
+ }
20282
+ function ShieldIcon({ color }) {
20283
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20284
+ "svg",
20285
+ {
20286
+ width: "13",
20287
+ height: "13",
20288
+ viewBox: "0 0 24 24",
20289
+ fill: "none",
20290
+ stroke: color,
20291
+ strokeWidth: "2",
20292
+ strokeLinecap: "round",
20293
+ strokeLinejoin: "round",
20294
+ "aria-hidden": "true",
20295
+ style: { flexShrink: 0 },
20296
+ children: [
20297
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }),
20298
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 12 2 2 4-4" })
20299
+ ]
20300
+ }
20301
+ );
20302
+ }
20303
+ function ExternalIcon() {
20304
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20305
+ "svg",
20306
+ {
20307
+ width: "13",
20308
+ height: "13",
20309
+ viewBox: "0 0 24 24",
20310
+ fill: "none",
20311
+ stroke: "currentColor",
20312
+ strokeWidth: "2",
20313
+ strokeLinecap: "round",
20314
+ strokeLinejoin: "round",
20315
+ "aria-hidden": "true",
20316
+ style: { flexShrink: 0 },
20317
+ children: [
20318
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 3h6v6" }),
20319
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 14 21 3" }),
20320
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
20321
+ ]
20322
+ }
20323
+ );
20324
+ }
20325
+ function TabbyAuthResolver(p) {
20326
+ var _a, _b, _c;
20327
+ const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
20328
+ const [cardHovered, setCardHovered] = React45.useState(false);
20329
+ const [btnHovered, setBtnHovered] = React45.useState(false);
20330
+ const [imgFailed, setImgFailed] = React45.useState(false);
20331
+ const app = humanizeApp(p.app || "the app");
20332
+ const connected = p.state === "connected";
20333
+ const accent = connected ? CONNECTED_GREEN3 : ACCENT2;
20334
+ const ctaLabel = (_a = p.ctaLabel) != null ? _a : connected ? `Open ${app}` : `Connect ${app}`;
20335
+ const subtitle = p.workspace ? `${app} \xB7 ${p.workspace} workspace` : app;
20336
+ const steps = ((_b = p.steps) == null ? void 0 : _b.length) ? p.steps : DEFAULT_STEPS(app, ctaLabel, connected);
20337
+ const description = (_c = p.description) != null ? _c : connected ? `Your ${app} session is active. Open ${app} to continue, or re-authenticate if prompted.` : `Your ${app} account is not yet connected to this workspace. Complete sign-in once to enable automatic access.`;
20338
+ const iconSrc = p.iconUrl || brandIconUrl(app);
20339
+ const showImg = Boolean(iconSrc) && !imgFailed;
20340
+ const initial = app.charAt(0).toUpperCase();
20341
+ const badge = connected ? { label: "Connected", bg: CONNECTED_GREEN_BG, color: CONNECTED_GREEN3 } : { label: "Pending sign-in", bg: PENDING_AMBER_BG, color: PENDING_AMBER };
20342
+ const sectionPad = "13px 16px";
20343
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: `${app} authentication`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: "10px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(
20344
+ "div",
20345
+ {
20346
+ onMouseEnter: () => setCardHovered(true),
20347
+ onMouseLeave: () => setCardHovered(false),
20348
+ style: {
20349
+ display: "flex",
20350
+ flexDirection: "row",
20351
+ alignItems: "stretch",
20352
+ borderRadius: "0.75rem",
20353
+ border: `1px solid ${cardHovered ? "#d2d2d2" : BORDER4}`,
20354
+ background: "white",
20355
+ overflow: "hidden",
20356
+ boxShadow: cardHovered ? "0 1px 3px rgba(0,0,0,0.05), 0 6px 18px rgba(0,0,0,0.06)" : "0 1px 2px rgba(0,0,0,0.03)",
20357
+ transition: "box-shadow 0.18s ease, border-color 0.18s ease"
20358
+ },
20359
+ children: [
20360
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "3px", flexShrink: 0, background: accent } }),
20361
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column" }, children: [
20362
+ /* @__PURE__ */ jsxRuntime.jsxs(
20363
+ "div",
20364
+ {
20365
+ style: {
20366
+ display: "flex",
20367
+ alignItems: "flex-start",
20368
+ gap: "12px",
20369
+ padding: sectionPad
20370
+ },
20371
+ children: [
20372
+ /* @__PURE__ */ jsxRuntime.jsx(
20373
+ "div",
20374
+ {
20375
+ style: {
20376
+ position: "relative",
20377
+ width: "34px",
20378
+ height: "34px",
20379
+ borderRadius: "9px",
20380
+ flexShrink: 0,
20381
+ display: "flex",
20382
+ alignItems: "center",
20383
+ justifyContent: "center",
20384
+ background: showImg ? "white" : "#fff3ee",
20385
+ boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.06)",
20386
+ overflow: "hidden"
20387
+ },
20388
+ children: showImg ? /* @__PURE__ */ jsxRuntime.jsx(
20389
+ "img",
20390
+ {
20391
+ src: iconSrc,
20392
+ alt: app,
20393
+ onError: () => setImgFailed(true),
20394
+ style: { width: "22px", height: "22px", objectFit: "contain" }
20395
+ }
20396
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
20397
+ "span",
20398
+ {
20399
+ style: {
20400
+ fontFamily: "var(--font-serif)",
20401
+ fontSize: "17px",
20402
+ fontWeight: 400,
20403
+ color: ACCENT2,
20404
+ lineHeight: 1
20405
+ },
20406
+ children: initial
20407
+ }
20408
+ )
20409
+ }
20410
+ ),
20411
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "2px" }, children: [
20412
+ /* @__PURE__ */ jsxRuntime.jsx(
20413
+ "span",
20414
+ {
20415
+ style: {
20416
+ fontFamily: "var(--font-serif)",
20417
+ fontSize: "15px",
20418
+ fontWeight: 400,
20419
+ color: "var(--foreground)",
20420
+ letterSpacing: "-0.01em",
20421
+ lineHeight: 1.2
20422
+ },
20423
+ children: CARD_TITLE
20424
+ }
20425
+ ),
20426
+ /* @__PURE__ */ jsxRuntime.jsx(
20427
+ "span",
20428
+ {
20429
+ style: {
20430
+ fontSize: "12px",
20431
+ color: MUTED2,
20432
+ whiteSpace: "nowrap",
20433
+ overflow: "hidden",
20434
+ textOverflow: "ellipsis"
20435
+ },
20436
+ children: subtitle
20437
+ }
20438
+ )
20439
+ ] }),
20440
+ /* @__PURE__ */ jsxRuntime.jsxs(
20441
+ "span",
20442
+ {
20443
+ style: {
20444
+ display: "inline-flex",
20445
+ alignItems: "center",
20446
+ gap: "5px",
20447
+ flexShrink: 0,
20448
+ fontSize: "10.5px",
20449
+ fontWeight: 600,
20450
+ padding: "3px 9px",
20451
+ borderRadius: "9999px",
20452
+ background: badge.bg,
20453
+ color: badge.color,
20454
+ whiteSpace: "nowrap"
20455
+ },
20456
+ children: [
20457
+ /* @__PURE__ */ jsxRuntime.jsx(
20458
+ "span",
20459
+ {
20460
+ style: {
20461
+ width: "6px",
20462
+ height: "6px",
20463
+ borderRadius: "9999px",
20464
+ background: badge.color
20465
+ }
20466
+ }
20467
+ ),
20468
+ badge.label
20469
+ ]
20470
+ }
20471
+ )
20472
+ ]
20473
+ }
20474
+ ),
20475
+ /* @__PURE__ */ jsxRuntime.jsxs(
20476
+ "div",
20477
+ {
20478
+ style: {
20479
+ borderTop: `1px solid ${BORDER4}`,
20480
+ padding: sectionPad,
20481
+ display: "flex",
20482
+ flexDirection: "column",
20483
+ gap: "12px"
20484
+ },
20485
+ children: [
20486
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "12.5px", lineHeight: 1.5, color: "var(--foreground)" }, children: description }),
20487
+ /* @__PURE__ */ jsxRuntime.jsx("ol", { style: { margin: 0, padding: 0, listStyle: "none", display: "flex", flexDirection: "column", gap: "8px" }, children: steps.map((step, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { style: { display: "flex", alignItems: "flex-start", gap: "10px" }, children: [
20488
+ /* @__PURE__ */ jsxRuntime.jsx(
20489
+ "span",
20490
+ {
20491
+ style: {
20492
+ flexShrink: 0,
20493
+ width: "18px",
20494
+ height: "18px",
20495
+ borderRadius: "9999px",
20496
+ background: accent,
20497
+ color: "white",
20498
+ fontSize: "10.5px",
20499
+ fontWeight: 600,
20500
+ display: "flex",
20501
+ alignItems: "center",
20502
+ justifyContent: "center",
20503
+ marginTop: "1px"
20504
+ },
20505
+ children: i + 1
20506
+ }
20507
+ ),
20508
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "12.5px", lineHeight: 1.45, color: "var(--foreground)" }, children: step })
20509
+ ] }, i)) })
20510
+ ]
20511
+ }
20512
+ ),
20513
+ /* @__PURE__ */ jsxRuntime.jsxs(
20514
+ "div",
20515
+ {
20516
+ style: {
20517
+ borderTop: `1px solid ${BORDER4}`,
20518
+ padding: sectionPad,
20519
+ background: "#fbfbfb",
20520
+ display: "flex",
20521
+ alignItems: "center",
20522
+ justifyContent: "space-between",
20523
+ gap: "12px",
20524
+ flexWrap: "wrap"
20525
+ },
20526
+ children: [
20527
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: "6px", color: MUTED2, fontSize: "11.5px" }, children: [
20528
+ /* @__PURE__ */ jsxRuntime.jsx(ShieldIcon, { color: CONNECTED_GREEN3 }),
20529
+ TRUST_FOOTER
20530
+ ] }),
20531
+ /* @__PURE__ */ jsxRuntime.jsxs(
20532
+ "a",
20533
+ {
20534
+ href: p.url,
20535
+ target: "_blank",
20536
+ rel: "noopener noreferrer",
20537
+ onMouseEnter: () => setBtnHovered(true),
20538
+ onMouseLeave: () => setBtnHovered(false),
20539
+ style: {
20540
+ display: "inline-flex",
20541
+ alignItems: "center",
20542
+ gap: "7px",
20543
+ flexShrink: 0,
20544
+ borderRadius: "8px",
20545
+ padding: "8px 15px",
20546
+ fontSize: "12.5px",
20547
+ fontWeight: 600,
20548
+ textDecoration: "none",
20549
+ whiteSpace: "nowrap",
20550
+ cursor: "pointer",
20551
+ color: "white",
20552
+ border: "1px solid transparent",
20553
+ background: btnHovered ? connected ? "#126a33" : ACCENT_SOFT2 : accent,
20554
+ transition: "background 0.15s ease"
20555
+ },
20556
+ children: [
20557
+ /* @__PURE__ */ jsxRuntime.jsx(ExternalIcon, {}),
20558
+ ctaLabel
20559
+ ]
20560
+ }
20561
+ )
20562
+ ]
20563
+ }
20564
+ )
20565
+ ] })
20566
+ ]
20567
+ }
20568
+ ) }) });
20569
+ }
18373
20570
  function resolveUI(rawPayload) {
18374
20571
  const payload = coercePayload(rawPayload);
18375
20572
  switch (payload.type) {
@@ -18487,8 +20684,12 @@ function resolveUI(rawPayload) {
18487
20684
  return /* @__PURE__ */ jsxRuntime.jsx(PipelinePreviewResolver, __spreadValues({}, payload));
18488
20685
  case "workflow-stepper":
18489
20686
  return /* @__PURE__ */ jsxRuntime.jsx(WorkflowStepperResolver, __spreadValues({}, payload));
20687
+ case "document-field-extraction":
20688
+ return /* @__PURE__ */ jsxRuntime.jsx(DocumentFieldExtractionResolver, __spreadValues({}, payload));
18490
20689
  case "decision-card":
18491
20690
  return /* @__PURE__ */ jsxRuntime.jsx(DecisionCardResolver, __spreadValues({}, payload));
20691
+ case "tabby-auth":
20692
+ return /* @__PURE__ */ jsxRuntime.jsx(TabbyAuthResolver, __spreadValues({}, payload));
18492
20693
  default: {
18493
20694
  return /* @__PURE__ */ jsxRuntime.jsx(
18494
20695
  "div",