@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/renderer.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import React41, { lazy, createContext, useState, useCallback, useEffect, useRef, Suspense, useMemo, useContext, useLayoutEffect } from 'react';
2
+ import React45, { lazy, createContext, useState, useCallback, useEffect, useRef, Suspense, useMemo, useContext, useLayoutEffect } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import dagre from '@dagrejs/dagre';
5
5
  import { createPortal } from 'react-dom';
@@ -5217,7 +5217,32 @@ var workflowStepperSchema = z.object({
5217
5217
  n: z.number().int().positive().optional(),
5218
5218
  title: z.string(),
5219
5219
  sub: z.string().optional(),
5220
- status: z.enum(["done", "active", "review", "pending", "blocked", "failed"]),
5220
+ status: z.enum([
5221
+ "done",
5222
+ "active",
5223
+ "running",
5224
+ "review",
5225
+ "pending",
5226
+ "blocked",
5227
+ "failed"
5228
+ ]),
5229
+ // Optional quality-gate verdict for a step run by an executor (e.g. a
5230
+ // pipeline). Surfaces a subtle trust badge; flags hint at issues a human
5231
+ // should review (the full list lives in the escalation dock).
5232
+ eval: z.object({
5233
+ score: z.number().min(0).max(1).nullable().optional(),
5234
+ verdict: z.enum(["good", "bad"]).optional(),
5235
+ reasoning: z.string().optional(),
5236
+ judge_ok: z.boolean().optional(),
5237
+ data_quality_flags: z.array(
5238
+ z.object({
5239
+ field: z.string().optional(),
5240
+ issue: z.string().optional(),
5241
+ severity: z.enum(["low", "medium", "high"]).optional(),
5242
+ details: z.string().optional()
5243
+ })
5244
+ ).optional()
5245
+ }).optional(),
5221
5246
  assignees: z.array(
5222
5247
  z.object({
5223
5248
  name: z.string(),
@@ -5253,7 +5278,32 @@ var workflowStepperTool = {
5253
5278
  n: { type: "number", description: "Step number; defaults to index + 1" },
5254
5279
  title: { type: "string" },
5255
5280
  sub: { type: "string", description: "Short status caption, e.g. '7 accounts \xB7 2 exceptions'" },
5256
- status: { type: "string", enum: ["done", "active", "review", "pending", "blocked", "failed"] },
5281
+ status: {
5282
+ type: "string",
5283
+ enum: ["done", "active", "running", "review", "pending", "blocked", "failed"]
5284
+ },
5285
+ eval: {
5286
+ type: "object",
5287
+ description: "Optional quality-gate verdict for an executor-run step.",
5288
+ properties: {
5289
+ score: { type: "number" },
5290
+ verdict: { type: "string", enum: ["good", "bad"] },
5291
+ reasoning: { type: "string" },
5292
+ judge_ok: { type: "boolean" },
5293
+ data_quality_flags: {
5294
+ type: "array",
5295
+ items: {
5296
+ type: "object",
5297
+ properties: {
5298
+ field: { type: "string" },
5299
+ issue: { type: "string" },
5300
+ severity: { type: "string", enum: ["low", "medium", "high"] },
5301
+ details: { type: "string" }
5302
+ }
5303
+ }
5304
+ }
5305
+ }
5306
+ },
5257
5307
  assignees: {
5258
5308
  type: "array",
5259
5309
  maxItems: 6,
@@ -5277,6 +5327,183 @@ var workflowStepperTool = {
5277
5327
  required: ["type", "title", "steps"]
5278
5328
  }
5279
5329
  };
5330
+ var bbox = z.tuple([z.number(), z.number(), z.number(), z.number()]);
5331
+ var fieldSchema = z.object({
5332
+ field_key: z.string(),
5333
+ label: z.string(),
5334
+ value: z.string(),
5335
+ page: z.number(),
5336
+ // 0-indexed, matches PageDimension.page
5337
+ bbox: bbox.nullable().optional(),
5338
+ confidence: z.number().optional(),
5339
+ confidence_tier: z.enum(["green", "amber", "red"]).optional(),
5340
+ badge: z.enum(["SC", "CN", "AB", "SW"]).optional(),
5341
+ state: z.enum(["ok", "corrected", "missing", "warn"]).optional(),
5342
+ entity_type: z.string().optional(),
5343
+ is_primary: z.boolean().optional(),
5344
+ // Set after a human correction (extractor output, or an optimistic in-card
5345
+ // edit) so the editable field card can show old → new and who changed it.
5346
+ previous_value: z.string().nullable().optional(),
5347
+ corrected_by: z.string().nullable().optional()
5348
+ });
5349
+ var pageSchema = z.object({
5350
+ page: z.number(),
5351
+ // 0-indexed
5352
+ imageUrl: z.string().optional(),
5353
+ // host-resolved from the durable image_ref
5354
+ width_pt: z.number(),
5355
+ height_pt: z.number()
5356
+ });
5357
+ var summaryStatSchema = z.object({
5358
+ field_key: z.string(),
5359
+ label: z.string(),
5360
+ value: z.string(),
5361
+ caption: z.string().nullable().optional()
5362
+ });
5363
+ var summaryFactSchema = z.object({
5364
+ field_key: z.string(),
5365
+ label: z.string(),
5366
+ value: z.string(),
5367
+ badge: z.string().nullable().optional()
5368
+ });
5369
+ var summarySchema = z.object({
5370
+ display_name: z.string().nullable().optional(),
5371
+ short_name: z.string().nullable().optional(),
5372
+ organization: z.string().nullable().optional(),
5373
+ domain: z.string().nullable().optional(),
5374
+ domain_group: z.string().nullable().optional(),
5375
+ tax_year: z.union([z.string(), z.number()]).nullable().optional(),
5376
+ crumbs: z.array(z.string()).optional(),
5377
+ tags: z.array(z.string()).optional(),
5378
+ stats: z.array(summaryStatSchema).optional(),
5379
+ facts: z.array(summaryFactSchema).optional()
5380
+ });
5381
+ var documentFieldExtractionSchema = z.object({
5382
+ type: z.literal("document-field-extraction"),
5383
+ doc_type: z.string().optional(),
5384
+ // Original uploaded filename (e.g. "2024_gl.pdf"); preferred over doc_type for
5385
+ // the card title since doc_type is often the "generic_fallback" schema name.
5386
+ file_name: z.string().optional(),
5387
+ // Server-side token; resolved by the host into pages/fields before render.
5388
+ payload_ref: z.string().optional(),
5389
+ // Present for persisted workstream docs; absent for pre-existing cards.
5390
+ store_id: z.string().optional(),
5391
+ doc_id: z.string().optional(),
5392
+ pages: z.array(pageSchema).max(100).optional(),
5393
+ fields: z.array(fieldSchema).max(1e3).optional(),
5394
+ // Page-count metadata for the Details tab ("N of M pages extracted").
5395
+ page_count: z.number().optional(),
5396
+ pages_processed: z.number().optional(),
5397
+ // Deterministic document summary for the Details tab.
5398
+ summary: summarySchema.nullable().optional()
5399
+ });
5400
+ var documentFieldExtractionTool = {
5401
+ name: "render_document_field_extraction",
5402
+ 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.",
5403
+ input_schema: {
5404
+ type: "object",
5405
+ properties: {
5406
+ type: { type: "string", enum: ["document-field-extraction"] },
5407
+ doc_type: { type: "string" },
5408
+ file_name: {
5409
+ type: "string",
5410
+ description: "Original uploaded filename; shown as the card title."
5411
+ },
5412
+ payload_ref: {
5413
+ type: "string",
5414
+ 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."
5415
+ },
5416
+ store_id: {
5417
+ type: "string",
5418
+ description: "Docstore store id; present for persisted workstream docs. The host uses this to open the editable viewer."
5419
+ },
5420
+ doc_id: {
5421
+ type: "string",
5422
+ description: "Docstore document id; present for persisted workstream docs. Required for the editable viewer."
5423
+ },
5424
+ pages: {
5425
+ type: "array",
5426
+ items: {
5427
+ type: "object",
5428
+ properties: {
5429
+ page: { type: "number", description: "0-indexed page number" },
5430
+ imageUrl: { type: "string" },
5431
+ width_pt: { type: "number" },
5432
+ height_pt: { type: "number" }
5433
+ },
5434
+ required: ["page", "width_pt", "height_pt"]
5435
+ }
5436
+ },
5437
+ fields: {
5438
+ type: "array",
5439
+ items: {
5440
+ type: "object",
5441
+ properties: {
5442
+ field_key: { type: "string" },
5443
+ label: { type: "string" },
5444
+ value: { type: "string" },
5445
+ page: { type: "number", description: "0-indexed page number" },
5446
+ bbox: {
5447
+ type: "array",
5448
+ items: { type: "number" },
5449
+ description: "[x0,y0,x1,y1] PDF points, origin bottom-left; null if unlocated"
5450
+ },
5451
+ confidence: { type: "number" },
5452
+ confidence_tier: { type: "string", enum: ["green", "amber", "red"] },
5453
+ badge: { type: "string", enum: ["SC", "CN", "AB", "SW"] },
5454
+ state: { type: "string", enum: ["ok", "corrected", "missing", "warn"] },
5455
+ entity_type: { type: "string" },
5456
+ is_primary: { type: "boolean" }
5457
+ },
5458
+ required: ["field_key", "label", "value", "page"]
5459
+ }
5460
+ },
5461
+ page_count: { type: "number" },
5462
+ pages_processed: { type: "number" },
5463
+ summary: {
5464
+ type: "object",
5465
+ description: "Deterministic document summary for the Details tab (display_name, organization, domain, stats, facts, tags). Produced by the extractor \u2014 pass through verbatim.",
5466
+ properties: {
5467
+ display_name: { type: "string" },
5468
+ short_name: { type: "string" },
5469
+ organization: { type: "string" },
5470
+ domain: { type: "string" },
5471
+ domain_group: { type: "string" },
5472
+ tax_year: { type: "string" },
5473
+ crumbs: { type: "array", items: { type: "string" } },
5474
+ tags: { type: "array", items: { type: "string" } },
5475
+ stats: {
5476
+ type: "array",
5477
+ items: {
5478
+ type: "object",
5479
+ properties: {
5480
+ field_key: { type: "string" },
5481
+ label: { type: "string" },
5482
+ value: { type: "string" },
5483
+ caption: { type: "string" }
5484
+ },
5485
+ required: ["field_key", "label", "value"]
5486
+ }
5487
+ },
5488
+ facts: {
5489
+ type: "array",
5490
+ items: {
5491
+ type: "object",
5492
+ properties: {
5493
+ field_key: { type: "string" },
5494
+ label: { type: "string" },
5495
+ value: { type: "string" },
5496
+ badge: { type: "string" }
5497
+ },
5498
+ required: ["field_key", "label", "value"]
5499
+ }
5500
+ }
5501
+ }
5502
+ }
5503
+ },
5504
+ required: ["type"]
5505
+ }
5506
+ };
5280
5507
  var decisionCardSchema = z.object({
5281
5508
  type: z.literal("decision-card"),
5282
5509
  id: z.string().optional(),
@@ -5380,6 +5607,36 @@ var decisionCardTool = {
5380
5607
  required: ["type", "title", "question", "options"]
5381
5608
  }
5382
5609
  };
5610
+ var tabbyAuthSchema = z.object({
5611
+ type: z.literal("tabby-auth"),
5612
+ app: z.string(),
5613
+ url: z.string(),
5614
+ workspace: z.string().optional(),
5615
+ state: z.enum(["pending", "connected"]).optional(),
5616
+ ctaLabel: z.string().optional(),
5617
+ steps: z.array(z.string()).optional(),
5618
+ description: z.string().optional(),
5619
+ iconUrl: z.string().optional()
5620
+ });
5621
+ var tabbyAuthTool = {
5622
+ name: "render_tabby_auth",
5623
+ 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.",
5624
+ input_schema: {
5625
+ type: "object",
5626
+ properties: {
5627
+ type: { type: "string", enum: ["tabby-auth"] },
5628
+ app: { type: "string" },
5629
+ url: { type: "string" },
5630
+ workspace: { type: "string" },
5631
+ state: { type: "string", enum: ["pending", "connected"] },
5632
+ ctaLabel: { type: "string" },
5633
+ steps: { type: "array", items: { type: "string" } },
5634
+ description: { type: "string" },
5635
+ iconUrl: { type: "string" }
5636
+ },
5637
+ required: ["type", "app", "url"]
5638
+ }
5639
+ };
5383
5640
 
5384
5641
  // src/schemas/index.ts
5385
5642
  var schemaRegistry = {
@@ -5440,7 +5697,9 @@ var schemaRegistry = {
5440
5697
  "integrations-list": { schema: integrationsListSchema, tool: integrationsListTool },
5441
5698
  "pipeline-preview": { schema: pipelinePreviewSchema, tool: pipelinePreviewTool },
5442
5699
  "workflow-stepper": { schema: workflowStepperSchema, tool: workflowStepperTool },
5443
- "decision-card": { schema: decisionCardSchema, tool: decisionCardTool }
5700
+ "document-field-extraction": { schema: documentFieldExtractionSchema, tool: documentFieldExtractionTool },
5701
+ "decision-card": { schema: decisionCardSchema, tool: decisionCardTool },
5702
+ "tabby-auth": { schema: tabbyAuthSchema, tool: tabbyAuthTool }
5444
5703
  };
5445
5704
 
5446
5705
  // src/schemas/coercePayload.ts
@@ -6178,17 +6437,17 @@ function SparklineTableResolver(p) {
6178
6437
  // src/composites/heatmap-table/resolver.tsx
6179
6438
  init_theme();
6180
6439
  init_ThemeContext();
6181
- function heatColor(z59) {
6182
- const clamped = Math.max(-3, Math.min(3, z59));
6440
+ function heatColor(z61) {
6441
+ const clamped = Math.max(-3, Math.min(3, z61));
6183
6442
  const abs = Math.abs(clamped);
6184
6443
  const lightness = 95 - abs * 8;
6185
6444
  const hue = clamped >= 0 ? 142 : 0;
6186
6445
  return `hsl(${hue} 60% ${lightness}%)`;
6187
6446
  }
6188
- function heatTextColor(z59) {
6189
- const abs = Math.abs(z59);
6190
- if (abs > 2) return z59 >= 0 ? "#14532d" : "#7f1d1d";
6191
- if (abs > 1) return z59 >= 0 ? "#166534" : "#991b1b";
6447
+ function heatTextColor(z61) {
6448
+ const abs = Math.abs(z61);
6449
+ if (abs > 2) return z61 >= 0 ? "#14532d" : "#7f1d1d";
6450
+ if (abs > 1) return z61 >= 0 ? "#166534" : "#991b1b";
6192
6451
  return "var(--foreground)";
6193
6452
  }
6194
6453
  var th2 = {
@@ -6822,7 +7081,7 @@ function WaterfallChartResolver(p) {
6822
7081
  ] }) });
6823
7082
  }
6824
7083
  init_ThemeContext();
6825
- var FlowGraph2 = React41.lazy(
7084
+ var FlowGraph2 = React45.lazy(
6826
7085
  () => Promise.resolve().then(() => (init_FlowGraph(), FlowGraph_exports)).then((m) => ({ default: m.FlowGraph }))
6827
7086
  );
6828
7087
  function FlowCanvasRenderer({
@@ -7096,7 +7355,7 @@ function TrialBalanceResolver(p) {
7096
7355
  gDebit += a.debit;
7097
7356
  gCredit += a.credit;
7098
7357
  });
7099
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
7358
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
7100
7359
  /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: 4, style: {
7101
7360
  padding: "8px 12px",
7102
7361
  fontSize: "12px",
@@ -8482,10 +8741,10 @@ function useFullscreen(ref) {
8482
8741
  // src/composites/document-preview/resolver.tsx
8483
8742
  init_theme();
8484
8743
  init_ThemeContext();
8485
- var PdfViewer2 = React41.lazy(
8744
+ var PdfViewer2 = React45.lazy(
8486
8745
  () => Promise.resolve().then(() => (init_PdfViewer(), PdfViewer_exports)).then((m) => ({ default: m.PdfViewer }))
8487
8746
  );
8488
- var ExcelViewer2 = React41.lazy(
8747
+ var ExcelViewer2 = React45.lazy(
8489
8748
  () => Promise.resolve().then(() => (init_ExcelViewer(), ExcelViewer_exports)).then((m) => ({ default: m.ExcelViewer }))
8490
8749
  );
8491
8750
  var highlightColors = {
@@ -9441,7 +9700,7 @@ function EngagementPipelineResolver(p) {
9441
9700
  const color = (_a2 = statusColor2[phase.status]) != null ? _a2 : "#d6d3d1";
9442
9701
  const isCurrent = i === activeIdx;
9443
9702
  const size = isCurrent ? 28 : 20;
9444
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
9703
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
9445
9704
  i > 0 && /* @__PURE__ */ jsx(
9446
9705
  "div",
9447
9706
  {
@@ -11604,7 +11863,7 @@ function FileCard({
11604
11863
  whiteSpace: "nowrap"
11605
11864
  },
11606
11865
  children: [
11607
- metaTokens.map((t, i) => /* @__PURE__ */ jsxs(React41.Fragment, { children: [
11866
+ metaTokens.map((t, i) => /* @__PURE__ */ jsxs(React45.Fragment, { children: [
11608
11867
  i > 0 && /* @__PURE__ */ jsx("span", { style: { color: "#c4c4c4" }, children: "\xB7" }),
11609
11868
  /* @__PURE__ */ jsx("span", { children: t })
11610
11869
  ] }, i)),
@@ -12179,7 +12438,7 @@ function KeyValueListResolver(p) {
12179
12438
  var _a3;
12180
12439
  return sum + ((_a3 = g.items) != null ? _a3 : []).length;
12181
12440
  }, 0);
12182
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12441
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12183
12442
  /* @__PURE__ */ jsxs(
12184
12443
  "div",
12185
12444
  {
@@ -12357,7 +12616,7 @@ function BalanceSheetResolver(p) {
12357
12616
  /* @__PURE__ */ jsxs("tbody", { children: [
12358
12617
  ((_p = p.sections) != null ? _p : []).map((section) => {
12359
12618
  var _a2;
12360
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12619
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12361
12620
  /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan, style: {
12362
12621
  padding: "8px 12px",
12363
12622
  fontSize: "12px",
@@ -12370,7 +12629,7 @@ function BalanceSheetResolver(p) {
12370
12629
  }, children: (_a2 = categoryLabels2[section.category]) != null ? _a2 : section.category }) }),
12371
12630
  section.subsections.map((sub, si) => {
12372
12631
  var _a3;
12373
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12632
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12374
12633
  /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan, style: {
12375
12634
  padding: "6px 10px 6px 24px",
12376
12635
  fontSize: "12px",
@@ -12546,7 +12805,7 @@ function IncomeStatementResolver(p) {
12546
12805
  textAlign: "left",
12547
12806
  whiteSpace: "nowrap"
12548
12807
  }, children: "\xA0" }),
12549
- periods.map((period) => /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12808
+ periods.map((period) => /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12550
12809
  /* @__PURE__ */ jsx("th", { style: {
12551
12810
  fontSize: "11px",
12552
12811
  fontWeight: 500,
@@ -12577,7 +12836,7 @@ function IncomeStatementResolver(p) {
12577
12836
  sections.map((section, si) => {
12578
12837
  var _a2;
12579
12838
  const isSubtotal = section.sectionType === "subtotal";
12580
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12839
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12581
12840
  /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: colCount, style: {
12582
12841
  padding: "8px 12px",
12583
12842
  fontSize: "12px",
@@ -12608,7 +12867,7 @@ function IncomeStatementResolver(p) {
12608
12867
  var _a4;
12609
12868
  const val = (_a4 = amounts[pi]) != null ? _a4 : 0;
12610
12869
  const isNeg = val < 0;
12611
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12870
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12612
12871
  /* @__PURE__ */ jsx("td", { style: {
12613
12872
  padding: "6px 10px",
12614
12873
  fontSize: "13px",
@@ -12643,7 +12902,7 @@ function IncomeStatementResolver(p) {
12643
12902
  var _a2;
12644
12903
  const val = (_a2 = grossProfit[pi]) != null ? _a2 : 0;
12645
12904
  const isNeg = val < 0;
12646
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12905
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12647
12906
  /* @__PURE__ */ jsx("td", { style: {
12648
12907
  padding: "8px 10px",
12649
12908
  fontSize: "12px",
@@ -12678,7 +12937,7 @@ function IncomeStatementResolver(p) {
12678
12937
  var _a2;
12679
12938
  const val = (_a2 = operatingIncome[pi]) != null ? _a2 : 0;
12680
12939
  const isNeg = val < 0;
12681
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12940
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12682
12941
  /* @__PURE__ */ jsx("td", { style: {
12683
12942
  padding: "8px 10px",
12684
12943
  fontSize: "12px",
@@ -12712,7 +12971,7 @@ function IncomeStatementResolver(p) {
12712
12971
  var _a2;
12713
12972
  const val = (_a2 = netIncome[pi]) != null ? _a2 : 0;
12714
12973
  const isNeg = val < 0;
12715
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12974
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12716
12975
  /* @__PURE__ */ jsx("td", { style: {
12717
12976
  padding: "10px 10px",
12718
12977
  fontSize: "13px",
@@ -12932,7 +13191,7 @@ function CashFlowStatementResolver(p) {
12932
13191
  /* @__PURE__ */ jsxs("tbody", { children: [
12933
13192
  activities.map((activity, ai) => {
12934
13193
  var _a2, _b2, _c2;
12935
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
13194
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12936
13195
  ai > 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
12937
13196
  "td",
12938
13197
  {
@@ -17246,6 +17505,8 @@ var STATUS_COLORS3 = {
17246
17505
  done: "#15803d",
17247
17506
  active: "",
17248
17507
  // filled from theme ACCENT at render time
17508
+ running: "",
17509
+ // filled from theme ACCENT at render time (executor in flight)
17249
17510
  review: "#f59e0b",
17250
17511
  pending: "#9ca3af",
17251
17512
  blocked: "#b45309",
@@ -17254,6 +17515,7 @@ var STATUS_COLORS3 = {
17254
17515
  var STATUS_LABELS = {
17255
17516
  done: "Complete",
17256
17517
  active: "In progress",
17518
+ running: "Running",
17257
17519
  review: "In review",
17258
17520
  pending: "Pending",
17259
17521
  blocked: "Blocked",
@@ -17357,6 +17619,26 @@ function IndexDot({ step, index, accent }) {
17357
17619
  if (step.status === "failed") {
17358
17620
  return /* @__PURE__ */ jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: "#dc2626", color: "white" }), children: /* @__PURE__ */ jsx("span", { style: { fontSize: 10 }, children: "!" }) });
17359
17621
  }
17622
+ if (step.status === "running") {
17623
+ return /* @__PURE__ */ jsxs("div", { style: __spreadProps(__spreadValues({}, base), { position: "relative", background: `${accent}1f`, color: accent }), children: [
17624
+ /* @__PURE__ */ jsx(
17625
+ "span",
17626
+ {
17627
+ className: "wfs-anim",
17628
+ "aria-hidden": "true",
17629
+ style: {
17630
+ position: "absolute",
17631
+ inset: 0,
17632
+ borderRadius: "50%",
17633
+ border: `1.5px solid ${accent}33`,
17634
+ borderTopColor: accent,
17635
+ animation: "wfsSpin 0.8s linear infinite"
17636
+ }
17637
+ }
17638
+ ),
17639
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 9 }, children: n })
17640
+ ] });
17641
+ }
17360
17642
  if (step.status === "active") {
17361
17643
  return /* @__PURE__ */ jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: accent, color: "white" }), children: n });
17362
17644
  }
@@ -17365,12 +17647,50 @@ function IndexDot({ step, index, accent }) {
17365
17647
  }
17366
17648
  return /* @__PURE__ */ jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: "#f2f2f2", color: "#9ca3af" }), children: n });
17367
17649
  }
17650
+ function EvalBadge({ step }) {
17651
+ var _a;
17652
+ const ev = step.eval;
17653
+ if (!ev || ev.judge_ok === false) return null;
17654
+ const score = typeof ev.score === "number" ? ev.score : null;
17655
+ const flags = (_a = ev.data_quality_flags) != null ? _a : [];
17656
+ const bad = ev.verdict === "bad" || score !== null && score < 0.8;
17657
+ const tip = flags.length > 0 ? flags.map((f) => {
17658
+ var _a2;
17659
+ return `${(_a2 = f.severity) != null ? _a2 : "?"}: ${f.details || f.issue || f.field || "issue"}`;
17660
+ }).join("\n") : ev.reasoning || void 0;
17661
+ const label = score !== null ? score.toFixed(2) : bad ? "flagged" : "ok";
17662
+ return /* @__PURE__ */ jsxs(
17663
+ "span",
17664
+ {
17665
+ title: tip,
17666
+ "data-testid": `workflow-stepper-eval-${step.id}`,
17667
+ style: {
17668
+ display: "inline-flex",
17669
+ alignItems: "center",
17670
+ gap: 3,
17671
+ fontSize: 9,
17672
+ fontWeight: 700,
17673
+ padding: "1px 6px",
17674
+ borderRadius: 9999,
17675
+ background: bad ? "#fff7ed" : "#dcfce7",
17676
+ color: bad ? "#b45309" : "#15803d",
17677
+ whiteSpace: "nowrap",
17678
+ flexShrink: 0
17679
+ },
17680
+ children: [
17681
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: bad ? "\u26A0" : "\u2713" }),
17682
+ label,
17683
+ flags.length > 0 ? ` \xB7 ${flags.length}` : ""
17684
+ ]
17685
+ }
17686
+ );
17687
+ }
17368
17688
  var CARD_MIN = 132;
17369
17689
  var CARD_GAP = 16;
17370
17690
  var AUTO_COMPACT_BELOW = 360;
17371
17691
  function useContainerWidth(ref) {
17372
- const [w, setW] = React41.useState(0);
17373
- React41.useLayoutEffect(() => {
17692
+ const [w, setW] = React45.useState(0);
17693
+ React45.useLayoutEffect(() => {
17374
17694
  const el = ref.current;
17375
17695
  if (!el || typeof ResizeObserver === "undefined") return;
17376
17696
  const ro = new ResizeObserver((entries) => {
@@ -17389,6 +17709,7 @@ var KEYFRAMES = `
17389
17709
  @keyframes wfsLampPulse{0%,100%{box-shadow:0 0 0 0 var(--wfs-accent,#6366f1)73}50%{box-shadow:0 0 0 4px transparent}}
17390
17710
  @keyframes wfsRise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
17391
17711
  @keyframes wfsShimmer{0%{background-position:-200px 0}100%{background-position:calc(200px + 100%) 0}}
17712
+ @keyframes wfsSpin{to{transform:rotate(360deg)}}
17392
17713
  .wfs-rise{animation:wfsRise 0.32s cubic-bezier(0.22,1,0.36,1) both}
17393
17714
  @media (prefers-reduced-motion: reduce){
17394
17715
  .wfs-anim,.wfs-rise,.wfs-shim{animation:none !important}
@@ -17469,17 +17790,17 @@ function WorkflowStepperRenderer({
17469
17790
  const steps = (_a = data.steps) != null ? _a : [];
17470
17791
  const activeStepId = (_d = (_c = data.active_step) != null ? _c : (_b = steps.find((s) => s.status === "active")) == null ? void 0 : _b.id) != null ? _d : null;
17471
17792
  const interactive = typeof onSelectStep === "function";
17472
- const statusColor3 = (s) => s === "active" ? ACCENT2 : STATUS_COLORS3[s];
17793
+ const statusColor3 = (s) => s === "active" || s === "running" ? ACCENT2 : STATUS_COLORS3[s];
17473
17794
  const doneCount = steps.filter((s) => s.status === "done").length;
17474
- const rootRef = React41.useRef(null);
17795
+ const rootRef = React45.useRef(null);
17475
17796
  const containerW = useContainerWidth(rootRef);
17476
17797
  let resolved = density === "auto" ? "full" : density;
17477
17798
  if (density === "auto" && containerW > 0) {
17478
17799
  const needed = steps.length * CARD_MIN + Math.max(0, steps.length - 1) * CARD_GAP;
17479
17800
  resolved = containerW < AUTO_COMPACT_BELOW || needed > containerW * 1.6 ? "compact" : "full";
17480
17801
  }
17481
- const scrollerRef = React41.useRef(null);
17482
- React41.useEffect(() => {
17802
+ const scrollerRef = React45.useRef(null);
17803
+ React45.useEffect(() => {
17483
17804
  if (resolved !== "full" || loading) return;
17484
17805
  const sc = scrollerRef.current;
17485
17806
  if (!sc) return;
@@ -17490,11 +17811,11 @@ function WorkflowStepperRenderer({
17490
17811
  el.scrollIntoView({ inline: "center", block: "nearest", behavior: "smooth" });
17491
17812
  }
17492
17813
  }, [resolved, loading, selectedStep, activeStepId]);
17493
- const [edges, setEdges] = React41.useState({
17814
+ const [edges, setEdges] = React45.useState({
17494
17815
  left: false,
17495
17816
  right: false
17496
17817
  });
17497
- const updateEdges = React41.useCallback(() => {
17818
+ const updateEdges = React45.useCallback(() => {
17498
17819
  const sc = scrollerRef.current;
17499
17820
  if (!sc) return;
17500
17821
  const max = sc.scrollWidth - sc.clientWidth;
@@ -17503,7 +17824,7 @@ function WorkflowStepperRenderer({
17503
17824
  const right = sl < max - 1;
17504
17825
  setEdges((prev) => prev.left === left && prev.right === right ? prev : { left, right });
17505
17826
  }, []);
17506
- React41.useLayoutEffect(() => {
17827
+ React45.useLayoutEffect(() => {
17507
17828
  if (resolved !== "full" || loading) return;
17508
17829
  updateEdges();
17509
17830
  const sc = scrollerRef.current;
@@ -17559,7 +17880,7 @@ function WorkflowStepperRenderer({
17559
17880
  const reached = s.status !== "pending";
17560
17881
  const clickable = interactive && reached;
17561
17882
  const size = act ? 11 : done ? 9 : 8;
17562
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
17883
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
17563
17884
  i > 0 && /* @__PURE__ */ jsx(
17564
17885
  "span",
17565
17886
  {
@@ -17697,12 +18018,13 @@ function WorkflowStepperRenderer({
17697
18018
  var _a2;
17698
18019
  const isSelected = selectedStep === step.id;
17699
18020
  const isActive = step.status === "active";
18021
+ const isRunning = step.status === "running";
17700
18022
  const reached = step.status !== "pending";
17701
18023
  const clickable = interactive && reached;
17702
18024
  const color = statusColor3(step.status);
17703
18025
  const humans = ((_a2 = step.assignees) != null ? _a2 : []).filter((a) => a.kind === "human");
17704
18026
  const roleCaption = humans.map((h) => h.role).filter(Boolean).slice(0, 2).join(" \xB7 ");
17705
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
18027
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
17706
18028
  i > 0 && /* @__PURE__ */ jsx(
17707
18029
  "div",
17708
18030
  {
@@ -17793,36 +18115,41 @@ function WorkflowStepperRenderer({
17793
18115
  }
17794
18116
  }
17795
18117
  ),
17796
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
17797
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
18118
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 4 }, children: [
18119
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, minWidth: 0 }, children: [
17798
18120
  /* @__PURE__ */ jsx(IndexDot, { step, index: i, accent: ACCENT2 }),
17799
18121
  /* @__PURE__ */ jsx(
17800
18122
  "span",
17801
18123
  {
17802
- className: isActive ? "wfs-anim" : void 0,
18124
+ className: isActive || isRunning ? "wfs-anim" : void 0,
17803
18125
  style: {
17804
18126
  width: 6,
17805
18127
  height: 6,
17806
18128
  borderRadius: "50%",
17807
18129
  background: color,
17808
- animation: isActive ? "wfsLampPulse 1.8s ease-in-out infinite" : "none"
18130
+ flexShrink: 0,
18131
+ animation: isActive || isRunning ? "wfsLampPulse 1.8s ease-in-out infinite" : "none"
17809
18132
  }
17810
18133
  }
17811
18134
  )
17812
18135
  ] }),
17813
- /* @__PURE__ */ jsx(
17814
- "span",
17815
- {
17816
- style: {
17817
- fontSize: 9,
17818
- fontWeight: 600,
17819
- letterSpacing: "0.05em",
17820
- textTransform: "uppercase",
17821
- color
17822
- },
17823
- children: STATUS_LABELS[step.status]
17824
- }
17825
- )
18136
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4, minWidth: 0 }, children: [
18137
+ /* @__PURE__ */ jsx(EvalBadge, { step }),
18138
+ /* @__PURE__ */ jsx(
18139
+ "span",
18140
+ {
18141
+ style: {
18142
+ fontSize: 9,
18143
+ fontWeight: 600,
18144
+ letterSpacing: "0.05em",
18145
+ textTransform: "uppercase",
18146
+ color,
18147
+ whiteSpace: "nowrap"
18148
+ },
18149
+ children: STATUS_LABELS[step.status]
18150
+ }
18151
+ )
18152
+ ] })
17826
18153
  ] }),
17827
18154
  /* @__PURE__ */ jsxs("div", { style: { minWidth: 0 }, children: [
17828
18155
  /* @__PURE__ */ jsx(
@@ -17956,98 +18283,1657 @@ function WorkflowStepperResolver(p) {
17956
18283
  ] }) });
17957
18284
  }
17958
18285
  init_ThemeContext();
17959
- var SEVERITY_COLORS = {
17960
- high: { color: "#dc2626", bg: "#fef2f2" },
17961
- medium: { color: "#f59e0b", bg: "#fff7ed" },
17962
- low: { color: "#777777", bg: "#f2f2f2" }
18286
+
18287
+ // src/composites/document-field-extraction/bboxTransform.ts
18288
+ function bboxToRect(bbox2, page, px) {
18289
+ if (!bbox2 || bbox2.length !== 4) return null;
18290
+ const { wPts, hPts } = page;
18291
+ const { wPx, hPx } = px;
18292
+ if (!wPts || !hPts || !wPx || !hPx) return null;
18293
+ const [x0, y0, x1, y1] = bbox2;
18294
+ const sx = wPx / wPts;
18295
+ const sy = hPx / hPts;
18296
+ return {
18297
+ left: x0 * sx,
18298
+ width: (x1 - x0) * sx,
18299
+ // Flip Y: the box's TOP in screen space is the page height minus its upper
18300
+ // PDF-point edge (y1), because PDF y grows upward from the bottom.
18301
+ top: (hPts - y1) * sy,
18302
+ height: (y1 - y0) * sy
18303
+ };
18304
+ }
18305
+
18306
+ // src/composites/document-field-extraction/FieldDetail.tsx
18307
+ init_ThemeContext();
18308
+
18309
+ // src/composites/document-field-extraction/fieldLabels.ts
18310
+ var LABEL_DISPLAY = {
18311
+ "employer identification number": "Employer ID (EIN)",
18312
+ "company or business name": "Company Name",
18313
+ "total revenue": "Total Revenue",
18314
+ "net income": "Net Income",
18315
+ "tax year": "Tax Year",
18316
+ "invoice number": "Invoice Number",
18317
+ "invoice date": "Invoice Date",
18318
+ "total amount due": "Total Amount Due",
18319
+ "vendor name": "Vendor Name",
18320
+ "receipt total": "Receipt Total",
18321
+ "transaction date": "Transaction Date",
18322
+ "merchant name": "Merchant Name"
17963
18323
  };
17964
- var GREEN3 = "#15803d";
17965
- var GREEN_SOFT = "#dcfce7";
17966
- var STACK_BELOW = 380;
17967
- function formatAmount2(amount, currency = "USD") {
18324
+ function prettyLabel(label) {
18325
+ var _a;
18326
+ return (_a = LABEL_DISPLAY[label]) != null ? _a : label.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
18327
+ }
18328
+ var TIER_COLORS = {
18329
+ green: "#15803d",
18330
+ amber: "#f59e0b",
18331
+ red: "#dc2626"
18332
+ };
18333
+ var BADGE_TITLE = {
18334
+ SC: "High confidence",
18335
+ CN: "Medium confidence",
18336
+ AB: "Low confidence",
18337
+ SW: "Very low confidence"
18338
+ };
18339
+ var BADGE_STYLE = {
18340
+ SC: { bg: "#dcfce7", fg: "#15803d" },
18341
+ CN: { bg: "#eff6ff", fg: "#0364ff" },
18342
+ // theme-ok (SECONDARY)
18343
+ AB: { bg: "#fff7ed", fg: "#92400e" },
18344
+ SW: { bg: "#fef2f2", fg: "#dc2626" }
18345
+ };
18346
+ var STATE_DOT = {
18347
+ ok: "#15803d",
18348
+ corrected: "#0364ff",
18349
+ // theme-ok (SECONDARY)
18350
+ missing: "#dc2626",
18351
+ warn: "#f59e0b"
18352
+ };
18353
+ function hexToRgba(hex, alpha) {
18354
+ const h = hex.replace("#", "");
18355
+ const r = parseInt(h.slice(0, 2), 16);
18356
+ const g = parseInt(h.slice(2, 4), 16);
18357
+ const b = parseInt(h.slice(4, 6), 16);
18358
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
18359
+ }
18360
+ function badgeStyle(f) {
17968
18361
  var _a, _b;
17969
- const abs = Math.abs(amount);
17970
- const sign = amount < 0 ? "-" : "";
17971
- let body;
17972
- if (abs >= 1e6) body = `${(abs / 1e6).toFixed(abs >= 1e7 ? 0 : 1)}M`;
17973
- else if (abs >= 1e3) body = `${(abs / 1e3).toFixed(abs >= 1e4 ? 0 : 1)}K`;
17974
- else body = `${abs}`;
17975
- let symbol = "$";
17976
- try {
17977
- const parts = new Intl.NumberFormat("en-US", {
17978
- style: "currency",
17979
- currency,
17980
- maximumFractionDigits: 0
17981
- }).formatToParts(0);
17982
- symbol = (_b = (_a = parts.find((p) => p.type === "currency")) == null ? void 0 : _a.value) != null ? _b : "$";
17983
- } catch (e) {
17984
- symbol = "$";
17985
- }
17986
- return `${sign}${symbol}${body}`;
18362
+ return (_b = BADGE_STYLE[(_a = f.badge) != null ? _a : ""]) != null ? _b : { bg: "#f6f6f6", fg: "#777777" };
17987
18363
  }
17988
- function useContainerWidth2(ref) {
17989
- const [w, setW] = React41.useState(0);
17990
- React41.useLayoutEffect(() => {
17991
- const el = ref.current;
17992
- if (!el || typeof ResizeObserver === "undefined") return;
17993
- const ro = new ResizeObserver((entries) => {
17994
- var _a;
17995
- const cr = (_a = entries[0]) == null ? void 0 : _a.contentRect;
17996
- if (cr) setW(cr.width);
17997
- });
17998
- ro.observe(el);
17999
- setW(el.getBoundingClientRect().width);
18000
- return () => ro.disconnect();
18001
- }, [ref]);
18002
- return w;
18364
+ function dotColor2(f) {
18365
+ var _a, _b;
18366
+ return (_b = STATE_DOT[(_a = f.state) != null ? _a : "ok"]) != null ? _b : "#15803d";
18003
18367
  }
18004
- var KEYFRAMES2 = `
18005
- @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
18006
- .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
18007
- @media (prefers-reduced-motion: reduce){
18008
- .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
18009
- }`;
18010
- function SparkCheck({ size, color }) {
18011
- return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
18012
- "path",
18013
- {
18014
- d: "M5 13l4 4L19 7",
18015
- stroke: color,
18016
- strokeWidth: 2.5,
18017
- strokeLinecap: "round",
18018
- strokeLinejoin: "round"
18019
- }
18020
- ) });
18368
+ function fieldColor(f, secondary) {
18369
+ var _a, _b;
18370
+ if (f.state === "corrected") return secondary;
18371
+ return (_b = TIER_COLORS[(_a = f.confidence_tier) != null ? _a : "amber"]) != null ? _b : TIER_COLORS.amber;
18021
18372
  }
18022
- function FlagPill({ flag }) {
18373
+ function confidenceLabel(f) {
18023
18374
  var _a;
18024
- const sev = (_a = flag.severity) != null ? _a : "medium";
18025
- const { color, bg } = SEVERITY_COLORS[sev];
18375
+ if (typeof f.confidence === "number" && !Number.isNaN(f.confidence)) {
18376
+ return `${Math.round(f.confidence * 100)}%`;
18377
+ }
18378
+ return (_a = f.badge) != null ? _a : "\u2014";
18379
+ }
18380
+ function FieldDetail({
18381
+ field,
18382
+ selected,
18383
+ onSelect,
18384
+ onSave,
18385
+ correctionCount = 0,
18386
+ cardRef
18387
+ }) {
18388
+ var _a, _b, _c, _d;
18389
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
18390
+ const [editing, setEditing] = React45.useState(false);
18391
+ const [draft, setDraft] = React45.useState("");
18392
+ const [saving, setSaving] = React45.useState(false);
18393
+ const [saveError, setSaveError] = React45.useState(null);
18394
+ const textareaRef = React45.useRef(null);
18395
+ const color = fieldColor(field, SECONDARY2);
18396
+ const corrected = field.state === "corrected";
18397
+ const startEdit = (e) => {
18398
+ e.stopPropagation();
18399
+ setDraft(field.value || "");
18400
+ setSaveError(null);
18401
+ setEditing(true);
18402
+ setTimeout(() => {
18403
+ var _a2, _b2;
18404
+ (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
18405
+ (_b2 = textareaRef.current) == null ? void 0 : _b2.select();
18406
+ }, 0);
18407
+ };
18408
+ const cancelEdit = (e) => {
18409
+ e.stopPropagation();
18410
+ setEditing(false);
18411
+ setSaveError(null);
18412
+ };
18413
+ const save = async (e) => {
18414
+ var _a2, _b2;
18415
+ e.stopPropagation();
18416
+ if (!onSave || draft === field.value) {
18417
+ setEditing(false);
18418
+ return;
18419
+ }
18420
+ setSaving(true);
18421
+ setSaveError(null);
18422
+ try {
18423
+ await onSave(field.field_key, draft);
18424
+ setEditing(false);
18425
+ } catch (err) {
18426
+ const msg = ((_b2 = (_a2 = err == null ? void 0 : err.response) == null ? void 0 : _a2.data) == null ? void 0 : _b2.detail) || "Save failed. Try again.";
18427
+ setSaveError(msg);
18428
+ } finally {
18429
+ setSaving(false);
18430
+ }
18431
+ };
18432
+ const handleKeyDown = (e) => {
18433
+ if (e.key === "Escape") cancelEdit(e);
18434
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) void save(e);
18435
+ };
18026
18436
  return /* @__PURE__ */ jsxs(
18027
- "span",
18437
+ "div",
18028
18438
  {
18439
+ ref: cardRef,
18440
+ "data-testid": "field-card",
18441
+ "data-field-key": field.field_key,
18442
+ "data-selected": selected ? "true" : "false",
18443
+ role: "button",
18444
+ tabIndex: 0,
18445
+ onClick: () => !editing && onSelect(selected ? null : field.field_key),
18446
+ onKeyDown: (e) => {
18447
+ if (!editing && e.key === "Enter") onSelect(selected ? null : field.field_key);
18448
+ },
18029
18449
  style: {
18030
- display: "inline-flex",
18031
- alignItems: "center",
18032
- gap: 5,
18033
- fontSize: 11,
18034
- fontWeight: 600,
18035
- padding: "3px 9px",
18036
- borderRadius: 9999,
18037
- background: bg,
18038
- color,
18039
- lineHeight: 1.2
18450
+ display: "flex",
18451
+ flexDirection: "column",
18452
+ gap: "4px",
18453
+ padding: "8px 10px",
18454
+ borderRadius: "0.5rem",
18455
+ border: `1px solid ${selected ? color : BORDER4}`,
18456
+ background: selected ? hexToRgba(color, 0.06) : "white",
18457
+ cursor: editing ? "default" : "pointer",
18458
+ transition: "background 0.15s, border-color 0.15s"
18040
18459
  },
18041
18460
  children: [
18042
- /* @__PURE__ */ jsx(
18043
- "span",
18044
- {
18045
- "aria-hidden": "true",
18046
- style: { width: 6, height: 6, borderRadius: "50%", background: color, flexShrink: 0 }
18047
- }
18048
- ),
18049
- flag.field ? `${flag.field}: ${flag.issue}` : flag.issue
18050
- ]
18461
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", minWidth: 0 }, children: [
18462
+ /* @__PURE__ */ jsx(
18463
+ "span",
18464
+ {
18465
+ title: (_c = (_b = BADGE_TITLE[(_a = field.badge) != null ? _a : ""]) != null ? _b : field.badge) != null ? _c : "",
18466
+ style: {
18467
+ fontSize: "10px",
18468
+ fontWeight: 700,
18469
+ padding: "2px 6px",
18470
+ borderRadius: "4px",
18471
+ flexShrink: 0,
18472
+ letterSpacing: "0.02em",
18473
+ minWidth: "34px",
18474
+ textAlign: "center",
18475
+ fontVariantNumeric: "tabular-nums",
18476
+ background: badgeStyle(field).bg,
18477
+ color: badgeStyle(field).fg
18478
+ },
18479
+ children: confidenceLabel(field)
18480
+ }
18481
+ ),
18482
+ /* @__PURE__ */ jsx(
18483
+ "span",
18484
+ {
18485
+ title: prettyLabel(field.label),
18486
+ style: {
18487
+ fontSize: "12.5px",
18488
+ fontWeight: 600,
18489
+ color: "var(--foreground)",
18490
+ flex: 1,
18491
+ minWidth: 0,
18492
+ whiteSpace: "nowrap",
18493
+ overflow: "hidden",
18494
+ textOverflow: "ellipsis"
18495
+ },
18496
+ children: prettyLabel(field.label)
18497
+ }
18498
+ ),
18499
+ field.is_primary && /* @__PURE__ */ jsx(
18500
+ "span",
18501
+ {
18502
+ style: {
18503
+ fontSize: "9px",
18504
+ fontWeight: 600,
18505
+ textTransform: "uppercase",
18506
+ letterSpacing: "0.04em",
18507
+ color: MUTED2,
18508
+ flexShrink: 0
18509
+ },
18510
+ children: "Primary"
18511
+ }
18512
+ ),
18513
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: "11px", color: MUTED2, flexShrink: 0 }, children: [
18514
+ "p.",
18515
+ field.page + 1
18516
+ ] }),
18517
+ !editing && onSave && /* @__PURE__ */ jsx(
18518
+ "button",
18519
+ {
18520
+ type: "button",
18521
+ onClick: startEdit,
18522
+ title: "Edit value",
18523
+ "aria-label": "Edit value",
18524
+ style: {
18525
+ border: `1px solid ${BORDER4}`,
18526
+ borderRadius: "6px",
18527
+ background: "white",
18528
+ cursor: "pointer",
18529
+ padding: "3px 5px",
18530
+ lineHeight: 1,
18531
+ flexShrink: 0,
18532
+ display: "inline-flex",
18533
+ alignItems: "center",
18534
+ justifyContent: "center"
18535
+ },
18536
+ children: /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: MUTED2, strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
18537
+ /* @__PURE__ */ jsx("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
18538
+ /* @__PURE__ */ jsx("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
18539
+ ] })
18540
+ }
18541
+ )
18542
+ ] }),
18543
+ editing ? /* @__PURE__ */ jsxs("div", { onClick: (e) => e.stopPropagation(), style: { display: "flex", flexDirection: "column", gap: "5px" }, children: [
18544
+ /* @__PURE__ */ jsx(
18545
+ "textarea",
18546
+ {
18547
+ ref: textareaRef,
18548
+ value: draft,
18549
+ onChange: (e) => setDraft(e.target.value),
18550
+ onKeyDown: handleKeyDown,
18551
+ rows: 3,
18552
+ placeholder: "Enter value\u2026",
18553
+ style: {
18554
+ width: "100%",
18555
+ boxSizing: "border-box",
18556
+ resize: "vertical",
18557
+ fontSize: "13px",
18558
+ fontFamily: "var(--font-sans)",
18559
+ color: "var(--foreground)",
18560
+ padding: "6px 8px",
18561
+ borderRadius: "0.4rem",
18562
+ border: `1px solid ${BORDER4}`
18563
+ }
18564
+ }
18565
+ ),
18566
+ saveError && /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: TIER_COLORS.red }, children: saveError }),
18567
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "6px" }, children: [
18568
+ /* @__PURE__ */ jsx(
18569
+ "button",
18570
+ {
18571
+ type: "button",
18572
+ onClick: save,
18573
+ disabled: saving,
18574
+ title: "Save (\u2318\u21B5)",
18575
+ style: {
18576
+ display: "inline-flex",
18577
+ alignItems: "center",
18578
+ gap: "4px",
18579
+ fontSize: "11px",
18580
+ fontWeight: 600,
18581
+ padding: "4px 10px",
18582
+ borderRadius: "0.4rem",
18583
+ border: "none",
18584
+ background: "var(--foreground)",
18585
+ color: "white",
18586
+ cursor: saving ? "default" : "pointer",
18587
+ opacity: saving ? 0.7 : 1
18588
+ },
18589
+ children: saving ? "Saving\u2026" : "Save"
18590
+ }
18591
+ ),
18592
+ /* @__PURE__ */ jsx(
18593
+ "button",
18594
+ {
18595
+ type: "button",
18596
+ onClick: cancelEdit,
18597
+ disabled: saving,
18598
+ title: "Cancel (Esc)",
18599
+ style: {
18600
+ fontSize: "11px",
18601
+ fontWeight: 600,
18602
+ padding: "4px 10px",
18603
+ borderRadius: "0.4rem",
18604
+ border: `1px solid ${BORDER4}`,
18605
+ background: "white",
18606
+ color: MUTED2,
18607
+ cursor: saving ? "default" : "pointer"
18608
+ },
18609
+ children: "Cancel"
18610
+ }
18611
+ )
18612
+ ] })
18613
+ ] }) : corrected ? /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "2px", paddingLeft: "2px" }, children: [
18614
+ field.previous_value != null && field.previous_value !== "" && /* @__PURE__ */ jsx(
18615
+ "span",
18616
+ {
18617
+ style: {
18618
+ fontSize: "11.5px",
18619
+ color: MUTED2,
18620
+ textDecoration: "line-through",
18621
+ fontFamily: "ui-monospace, 'Cascadia Code', monospace",
18622
+ wordBreak: "break-word"
18623
+ },
18624
+ children: field.previous_value
18625
+ }
18626
+ ),
18627
+ /* @__PURE__ */ jsx(
18628
+ "span",
18629
+ {
18630
+ style: {
18631
+ fontSize: "12.5px",
18632
+ fontWeight: 600,
18633
+ color: "var(--foreground)",
18634
+ fontFamily: "ui-monospace, 'Cascadia Code', monospace",
18635
+ wordBreak: "break-word"
18636
+ },
18637
+ children: field.value || "\u2014"
18638
+ }
18639
+ ),
18640
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
18641
+ field.corrected_by && /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: SECONDARY2 }, title: `Corrected by ${field.corrected_by}`, children: field.corrected_by }),
18642
+ correctionCount > 0 && /* @__PURE__ */ jsxs(
18643
+ "span",
18644
+ {
18645
+ style: {
18646
+ fontSize: "10.5px",
18647
+ fontWeight: 600,
18648
+ color: MUTED2,
18649
+ background: PAPER2,
18650
+ borderRadius: "9999px",
18651
+ padding: "1px 7px"
18652
+ },
18653
+ children: [
18654
+ correctionCount,
18655
+ " ",
18656
+ correctionCount === 1 ? "event" : "events"
18657
+ ]
18658
+ }
18659
+ )
18660
+ ] })
18661
+ ] }) : (
18662
+ // Bottom row: monospace value + right-edge validation dot (file explorer).
18663
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", paddingLeft: "2px" }, children: [
18664
+ /* @__PURE__ */ jsx(
18665
+ "span",
18666
+ {
18667
+ style: {
18668
+ fontSize: "12.5px",
18669
+ color: MUTED2,
18670
+ fontFamily: "ui-monospace, 'Cascadia Code', monospace",
18671
+ flex: 1,
18672
+ minWidth: 0,
18673
+ whiteSpace: "nowrap",
18674
+ overflow: "hidden",
18675
+ textOverflow: "ellipsis"
18676
+ },
18677
+ title: field.value || "\u2014",
18678
+ children: field.value || "\u2014"
18679
+ }
18680
+ ),
18681
+ /* @__PURE__ */ jsx(
18682
+ "span",
18683
+ {
18684
+ title: (_d = field.state) != null ? _d : "ok",
18685
+ style: {
18686
+ width: "8px",
18687
+ height: "8px",
18688
+ borderRadius: "9999px",
18689
+ flexShrink: 0,
18690
+ background: dotColor2(field)
18691
+ }
18692
+ }
18693
+ )
18694
+ ] })
18695
+ )
18696
+ ]
18697
+ }
18698
+ );
18699
+ }
18700
+
18701
+ // src/composites/document-field-extraction/FieldDetails.tsx
18702
+ init_ThemeContext();
18703
+ var BADGE_DOT = {
18704
+ // gen-ui semantic dot colors
18705
+ ok: "#15803d",
18706
+ green: "#15803d",
18707
+ warn: "#f59e0b",
18708
+ amber: "#f59e0b",
18709
+ missing: "#dc2626",
18710
+ red: "#dc2626",
18711
+ corrected: "#0364ff"
18712
+ // theme-ok (SECONDARY)
18713
+ };
18714
+ function FieldDetails({
18715
+ summary,
18716
+ fileName,
18717
+ pageCount,
18718
+ pagesProcessed
18719
+ }) {
18720
+ var _a, _b, _c, _d, _e, _f;
18721
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
18722
+ if (!summary) {
18723
+ return /* @__PURE__ */ jsxs(
18724
+ "div",
18725
+ {
18726
+ style: {
18727
+ height: "100%",
18728
+ display: "flex",
18729
+ flexDirection: "column",
18730
+ alignItems: "center",
18731
+ justifyContent: "center",
18732
+ gap: "6px",
18733
+ color: MUTED2,
18734
+ textAlign: "center",
18735
+ padding: "24px"
18736
+ },
18737
+ children: [
18738
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "26px", lineHeight: 1 }, children: "\u{1F4C4}" }),
18739
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "14px", fontWeight: 600, color: "var(--foreground)" }, children: "No summary yet" }),
18740
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", maxWidth: "280px" }, children: "This document has no extracted summary." })
18741
+ ]
18742
+ }
18743
+ );
18744
+ }
18745
+ const header = buildHeader(summary);
18746
+ const crumb = buildCrumbLine(summary);
18747
+ const facts = buildFacts(summary, fileName, pageCount, pagesProcessed);
18748
+ return /* @__PURE__ */ jsx("div", { style: { height: "100%", overflowY: "auto", paddingRight: "4px" }, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "14px" }, children: [
18749
+ /* @__PURE__ */ jsxs("header", { style: { display: "flex", flexDirection: "column", gap: "3px" }, children: [
18750
+ /* @__PURE__ */ jsx(
18751
+ "h2",
18752
+ {
18753
+ title: header.title,
18754
+ style: {
18755
+ margin: 0,
18756
+ fontFamily: "var(--font-serif)",
18757
+ fontSize: "20px",
18758
+ fontWeight: 400,
18759
+ letterSpacing: "-0.01em",
18760
+ color: "var(--foreground)",
18761
+ overflow: "hidden",
18762
+ textOverflow: "ellipsis",
18763
+ whiteSpace: "nowrap"
18764
+ },
18765
+ children: header.title
18766
+ }
18767
+ ),
18768
+ header.subtitle && /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", color: MUTED2 }, children: header.subtitle })
18769
+ ] }),
18770
+ (summary.domain || summary.display_name || summary.domain_group || ((_b = (_a = summary.tags) == null ? void 0 : _a.length) != null ? _b : 0) > 0) && /* @__PURE__ */ jsxs(
18771
+ "section",
18772
+ {
18773
+ style: {
18774
+ display: "flex",
18775
+ flexDirection: "column",
18776
+ gap: "6px",
18777
+ padding: "12px 14px",
18778
+ borderRadius: "0.75rem",
18779
+ border: `1px solid ${BORDER4}`,
18780
+ background: PAPER2
18781
+ },
18782
+ children: [
18783
+ summary.domain_group && /* @__PURE__ */ jsx(
18784
+ "span",
18785
+ {
18786
+ style: {
18787
+ fontSize: "10px",
18788
+ fontWeight: 600,
18789
+ textTransform: "uppercase",
18790
+ letterSpacing: "0.06em",
18791
+ color: MUTED2
18792
+ },
18793
+ children: summary.domain_group
18794
+ }
18795
+ ),
18796
+ /* @__PURE__ */ jsx(
18797
+ "h3",
18798
+ {
18799
+ style: {
18800
+ margin: 0,
18801
+ fontSize: "14px",
18802
+ fontWeight: 600,
18803
+ color: "var(--foreground)"
18804
+ },
18805
+ children: summary.domain || summary.display_name
18806
+ }
18807
+ ),
18808
+ crumb && /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", color: MUTED2 }, children: crumb }),
18809
+ ((_d = (_c = summary.tags) == null ? void 0 : _c.length) != null ? _d : 0) > 0 && /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "5px", marginTop: "2px" }, children: summary.tags.map((t) => /* @__PURE__ */ jsx(
18810
+ "span",
18811
+ {
18812
+ style: {
18813
+ fontSize: "10px",
18814
+ fontWeight: 600,
18815
+ padding: "2px 8px",
18816
+ borderRadius: "9999px",
18817
+ background: "white",
18818
+ border: `1px solid ${BORDER4}`,
18819
+ color: MUTED2
18820
+ },
18821
+ children: t
18822
+ },
18823
+ t
18824
+ )) })
18825
+ ]
18826
+ }
18827
+ ),
18828
+ ((_f = (_e = summary.stats) == null ? void 0 : _e.length) != null ? _f : 0) > 0 && /* @__PURE__ */ jsx(
18829
+ "div",
18830
+ {
18831
+ style: {
18832
+ display: "grid",
18833
+ gridTemplateColumns: "repeat(auto-fit, minmax(130px, 1fr))",
18834
+ gap: "8px"
18835
+ },
18836
+ children: summary.stats.map((s) => /* @__PURE__ */ jsxs(
18837
+ "div",
18838
+ {
18839
+ style: {
18840
+ display: "flex",
18841
+ flexDirection: "column",
18842
+ gap: "2px",
18843
+ padding: "10px 12px",
18844
+ borderRadius: "0.6rem",
18845
+ border: `1px solid ${BORDER4}`,
18846
+ background: "white"
18847
+ },
18848
+ children: [
18849
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: MUTED2 }, children: s.label }),
18850
+ /* @__PURE__ */ jsx(
18851
+ "span",
18852
+ {
18853
+ title: s.value,
18854
+ style: {
18855
+ fontSize: "15px",
18856
+ fontWeight: 600,
18857
+ color: "var(--foreground)",
18858
+ overflow: "hidden",
18859
+ textOverflow: "ellipsis",
18860
+ whiteSpace: "nowrap"
18861
+ },
18862
+ children: s.value
18863
+ }
18864
+ ),
18865
+ s.caption && /* @__PURE__ */ jsx("span", { style: { fontSize: "10px", color: MUTED2 }, children: s.caption })
18866
+ ]
18867
+ },
18868
+ s.field_key
18869
+ ))
18870
+ }
18871
+ ),
18872
+ facts.length > 0 && /* @__PURE__ */ jsxs("section", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
18873
+ /* @__PURE__ */ jsxs(
18874
+ "div",
18875
+ {
18876
+ style: {
18877
+ display: "flex",
18878
+ alignItems: "center",
18879
+ gap: "6px",
18880
+ fontSize: "11px",
18881
+ fontWeight: 600,
18882
+ textTransform: "uppercase",
18883
+ letterSpacing: "0.04em",
18884
+ color: MUTED2
18885
+ },
18886
+ children: [
18887
+ /* @__PURE__ */ jsx("span", { children: "\u25A4" }),
18888
+ /* @__PURE__ */ jsx("span", { children: "Document details" })
18889
+ ]
18890
+ }
18891
+ ),
18892
+ /* @__PURE__ */ jsx(
18893
+ "dl",
18894
+ {
18895
+ style: {
18896
+ margin: 0,
18897
+ display: "grid",
18898
+ gridTemplateColumns: "minmax(110px, auto) 1fr",
18899
+ rowGap: "6px",
18900
+ columnGap: "14px"
18901
+ },
18902
+ children: facts.map((f) => {
18903
+ var _a2;
18904
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
18905
+ /* @__PURE__ */ jsx("dt", { style: { fontSize: "12px", color: MUTED2 }, children: f.label }),
18906
+ /* @__PURE__ */ jsxs(
18907
+ "dd",
18908
+ {
18909
+ title: typeof f.value === "string" ? f.value : void 0,
18910
+ style: {
18911
+ margin: 0,
18912
+ fontSize: "12px",
18913
+ color: "var(--foreground)",
18914
+ display: "flex",
18915
+ alignItems: "center",
18916
+ gap: "6px",
18917
+ wordBreak: "break-word"
18918
+ },
18919
+ children: [
18920
+ f.badge && /* @__PURE__ */ jsx(
18921
+ "span",
18922
+ {
18923
+ style: {
18924
+ width: "7px",
18925
+ height: "7px",
18926
+ borderRadius: "9999px",
18927
+ flexShrink: 0,
18928
+ background: (_a2 = BADGE_DOT[f.badge]) != null ? _a2 : SECONDARY2
18929
+ }
18930
+ }
18931
+ ),
18932
+ f.value
18933
+ ]
18934
+ }
18935
+ )
18936
+ ] }, f.key);
18937
+ })
18938
+ }
18939
+ )
18940
+ ] })
18941
+ ] }) });
18942
+ }
18943
+ function buildHeader(summary) {
18944
+ const form = [summary.short_name, summary.display_name].filter(Boolean);
18945
+ const title = summary.organization || form.shift() || summary.domain || "Document";
18946
+ const parts = summary.organization ? [...form] : form;
18947
+ if (summary.tax_year) parts.push(`TY ${summary.tax_year}`);
18948
+ return { title, subtitle: parts.join(" \xB7 ") };
18949
+ }
18950
+ function buildCrumbLine(summary) {
18951
+ const parts = [...summary.crumbs || [], summary.short_name].filter(Boolean);
18952
+ if (parts.length > 0) return parts.join(" \xB7 ");
18953
+ return summary.domain && summary.display_name ? summary.display_name : "";
18954
+ }
18955
+ function buildFacts(summary, fileName, pageCount, pagesProcessed) {
18956
+ const rows = [];
18957
+ if (fileName) rows.push({ key: "file", label: "File", value: fileName });
18958
+ if (summary.display_name) {
18959
+ rows.push({ key: "doctype", label: "Document type", value: summary.display_name });
18960
+ }
18961
+ if (summary.tax_year != null && summary.tax_year !== "") {
18962
+ rows.push({ key: "year", label: "Tax year", value: String(summary.tax_year) });
18963
+ }
18964
+ for (const f of summary.facts || []) {
18965
+ rows.push({ key: f.field_key, label: f.label, value: f.value, badge: f.badge });
18966
+ }
18967
+ if (pageCount) {
18968
+ rows.push({
18969
+ key: "pages",
18970
+ label: "Pages processed",
18971
+ value: `${pagesProcessed != null ? pagesProcessed : pageCount} / ${pageCount}`
18972
+ });
18973
+ }
18974
+ return rows;
18975
+ }
18976
+
18977
+ // src/composites/document-field-extraction/FieldAuditLog.tsx
18978
+ init_ThemeContext();
18979
+ function initials(name) {
18980
+ return name.trim().split(/\s+/).slice(0, 2).map((w) => {
18981
+ var _a;
18982
+ return ((_a = w[0]) != null ? _a : "").toUpperCase();
18983
+ }).join("");
18984
+ }
18985
+ function formatTs(ts) {
18986
+ if (!ts) return "\u2014";
18987
+ const d = new Date(ts);
18988
+ if (Number.isNaN(d.getTime())) return ts;
18989
+ return d.toLocaleString(void 0, {
18990
+ month: "short",
18991
+ day: "numeric",
18992
+ hour: "2-digit",
18993
+ minute: "2-digit"
18994
+ });
18995
+ }
18996
+ function FieldAuditLog({
18997
+ events = [],
18998
+ loading = false,
18999
+ fields = []
19000
+ }) {
19001
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
19002
+ const fieldLabelMap = React45.useMemo(() => {
19003
+ var _a;
19004
+ const map = {};
19005
+ for (const f of fields) map[f.field_key] = (_a = f.label) != null ? _a : f.field_key;
19006
+ return map;
19007
+ }, [fields]);
19008
+ if (loading) {
19009
+ return /* @__PURE__ */ jsx(
19010
+ "div",
19011
+ {
19012
+ style: {
19013
+ flex: 1,
19014
+ display: "flex",
19015
+ alignItems: "center",
19016
+ justifyContent: "center",
19017
+ padding: "32px 20px",
19018
+ fontSize: "13px",
19019
+ color: MUTED2
19020
+ },
19021
+ children: "Loading audit trail\u2026"
19022
+ }
19023
+ );
19024
+ }
19025
+ if (events.length === 0) {
19026
+ return /* @__PURE__ */ jsxs(
19027
+ "div",
19028
+ {
19029
+ style: {
19030
+ flex: 1,
19031
+ display: "flex",
19032
+ flexDirection: "column",
19033
+ alignItems: "center",
19034
+ justifyContent: "center",
19035
+ gap: "6px",
19036
+ padding: "32px 20px",
19037
+ textAlign: "center"
19038
+ },
19039
+ children: [
19040
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "13.5px", fontWeight: 600, color: "var(--foreground)" }, children: "No changes yet" }),
19041
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", color: MUTED2, maxWidth: "240px", lineHeight: 1.5 }, children: "Field corrections will appear here." })
19042
+ ]
19043
+ }
19044
+ );
19045
+ }
19046
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", flex: 1, minHeight: 0, overflow: "hidden" }, children: [
19047
+ /* @__PURE__ */ jsx("div", { style: { padding: "8px 14px 6px", flexShrink: 0 }, children: /* @__PURE__ */ jsxs(
19048
+ "span",
19049
+ {
19050
+ style: {
19051
+ fontSize: "11.5px",
19052
+ fontWeight: 600,
19053
+ color: MUTED2,
19054
+ textTransform: "uppercase",
19055
+ letterSpacing: "0.04em"
19056
+ },
19057
+ children: [
19058
+ events.length,
19059
+ " ",
19060
+ events.length === 1 ? "change" : "changes"
19061
+ ]
19062
+ }
19063
+ ) }),
19064
+ /* @__PURE__ */ jsx("ol", { style: { listStyle: "none", margin: 0, padding: "0 0 16px", overflowY: "auto", flex: 1, minHeight: 0 }, children: events.map((ev) => {
19065
+ var _a, _b;
19066
+ const rawLabel = (_a = fieldLabelMap[ev.field_key]) != null ? _a : ev.field_key;
19067
+ const label = prettyLabel(rawLabel);
19068
+ const isAI = ev.actor_type === "system" || ev.event_type === "ai_corrected" || ev.event_type === "ai_extracted";
19069
+ const actor = isAI ? "AI" : ev.actor_name || "Unknown";
19070
+ const eventLabel = isAI ? "Re-extracted" : "Corrected";
19071
+ return /* @__PURE__ */ jsxs(
19072
+ "li",
19073
+ {
19074
+ "data-testid": "audit-row",
19075
+ style: { display: "flex", gap: "10px", padding: "10px 14px", borderBottom: `1px solid ${BORDER4}` },
19076
+ children: [
19077
+ /* @__PURE__ */ jsx(
19078
+ "div",
19079
+ {
19080
+ title: isAI ? "AI extraction" : actor,
19081
+ style: {
19082
+ flexShrink: 0,
19083
+ width: "28px",
19084
+ height: "28px",
19085
+ borderRadius: "50%",
19086
+ background: isAI ? "#dcfce7" : "#eff6ff",
19087
+ color: isAI ? "#15803d" : SECONDARY2,
19088
+ fontSize: "10.5px",
19089
+ fontWeight: 700,
19090
+ display: "flex",
19091
+ alignItems: "center",
19092
+ justifyContent: "center",
19093
+ marginTop: "1px"
19094
+ },
19095
+ children: isAI ? "\u2728" : initials(actor)
19096
+ }
19097
+ ),
19098
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "3px", flex: 1, minWidth: 0 }, children: [
19099
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: "6px", flexWrap: "wrap" }, children: [
19100
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "12.5px", fontWeight: 600, color: isAI ? "#15803d" : "var(--foreground)" }, children: actor }),
19101
+ /* @__PURE__ */ jsx(
19102
+ "span",
19103
+ {
19104
+ style: {
19105
+ fontSize: "10.5px",
19106
+ fontWeight: 600,
19107
+ color: MUTED2,
19108
+ background: PAPER2,
19109
+ borderRadius: "4px",
19110
+ padding: "1px 6px",
19111
+ whiteSpace: "nowrap",
19112
+ flexShrink: 0
19113
+ },
19114
+ children: eventLabel
19115
+ }
19116
+ ),
19117
+ /* @__PURE__ */ jsx(
19118
+ "span",
19119
+ {
19120
+ style: {
19121
+ fontSize: "12px",
19122
+ color: MUTED2,
19123
+ flex: 1,
19124
+ minWidth: 0,
19125
+ whiteSpace: "nowrap",
19126
+ overflow: "hidden",
19127
+ textOverflow: "ellipsis"
19128
+ },
19129
+ children: label
19130
+ }
19131
+ ),
19132
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: MUTED2, flexShrink: 0 }, children: formatTs(ev.created_at) })
19133
+ ] }),
19134
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
19135
+ ev.previous_value != null && /* @__PURE__ */ jsxs(Fragment, { children: [
19136
+ /* @__PURE__ */ jsx(
19137
+ "span",
19138
+ {
19139
+ style: {
19140
+ fontSize: "12px",
19141
+ fontFamily: "ui-monospace, monospace",
19142
+ color: MUTED2,
19143
+ textDecoration: "line-through"
19144
+ },
19145
+ children: ev.previous_value
19146
+ }
19147
+ ),
19148
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: BORDER4 }, children: "\u2192" })
19149
+ ] }),
19150
+ /* @__PURE__ */ jsx(
19151
+ "span",
19152
+ {
19153
+ style: {
19154
+ fontSize: "12px",
19155
+ fontFamily: "ui-monospace, monospace",
19156
+ fontWeight: 600,
19157
+ color: "var(--foreground)"
19158
+ },
19159
+ children: (_b = ev.new_value) != null ? _b : "\u2014"
19160
+ }
19161
+ )
19162
+ ] }),
19163
+ ev.reason && /* @__PURE__ */ jsxs("p", { style: { margin: "2px 0 0", fontSize: "11.5px", color: MUTED2, fontStyle: "italic" }, children: [
19164
+ "\u201C",
19165
+ ev.reason,
19166
+ "\u201D"
19167
+ ] })
19168
+ ] })
19169
+ ]
19170
+ },
19171
+ ev.id
19172
+ );
19173
+ }) })
19174
+ ] });
19175
+ }
19176
+ var TIER_COLORS2 = {
19177
+ green: "#15803d",
19178
+ amber: "#f59e0b",
19179
+ red: "#dc2626"
19180
+ };
19181
+ function fieldColor2(f, secondary) {
19182
+ var _a, _b;
19183
+ if (f.state === "corrected") return secondary;
19184
+ return (_b = TIER_COLORS2[(_a = f.confidence_tier) != null ? _a : "amber"]) != null ? _b : TIER_COLORS2.amber;
19185
+ }
19186
+ function hexToRgba2(hex, alpha) {
19187
+ const h = hex.replace("#", "");
19188
+ const r = parseInt(h.slice(0, 2), 16);
19189
+ const g = parseInt(h.slice(2, 4), 16);
19190
+ const b = parseInt(h.slice(4, 6), 16);
19191
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
19192
+ }
19193
+ function PageOverlay({
19194
+ page,
19195
+ fields,
19196
+ selectedKey,
19197
+ onSelect,
19198
+ secondary
19199
+ }) {
19200
+ const { PAPER: PAPER2, MUTED: MUTED2 } = useTheme();
19201
+ const imgRef = React45.useRef(null);
19202
+ const selectedBoxRef = React45.useRef(null);
19203
+ const [px, setPx] = React45.useState(null);
19204
+ React45.useEffect(() => {
19205
+ const el = imgRef.current;
19206
+ if (!el) return;
19207
+ const measure = () => {
19208
+ if (el.clientWidth && el.clientHeight) {
19209
+ setPx({ wPx: el.clientWidth, hPx: el.clientHeight });
19210
+ }
19211
+ };
19212
+ measure();
19213
+ if (typeof ResizeObserver === "undefined") return;
19214
+ const ro = new ResizeObserver(measure);
19215
+ ro.observe(el);
19216
+ return () => ro.disconnect();
19217
+ }, [page.imageUrl]);
19218
+ React45.useEffect(() => {
19219
+ if (!selectedKey) return;
19220
+ if (!fields.some((f) => f.field_key === selectedKey && f.bbox)) return;
19221
+ const el = selectedBoxRef.current;
19222
+ if (el && typeof el.scrollIntoView === "function") {
19223
+ el.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
19224
+ }
19225
+ }, [selectedKey, fields, px]);
19226
+ const pagePts = { wPts: page.width_pt, hPts: page.height_pt };
19227
+ return /* @__PURE__ */ jsxs("div", { style: { position: "relative", width: "100%", lineHeight: 0 }, children: [
19228
+ page.imageUrl ? /* @__PURE__ */ jsx(
19229
+ "img",
19230
+ {
19231
+ ref: imgRef,
19232
+ src: page.imageUrl,
19233
+ alt: `Page ${page.page + 1}`,
19234
+ onLoad: () => {
19235
+ const el = imgRef.current;
19236
+ if (el && el.clientWidth && el.clientHeight) {
19237
+ setPx({ wPx: el.clientWidth, hPx: el.clientHeight });
19238
+ }
19239
+ },
19240
+ style: { display: "block", width: "100%", height: "auto" }
19241
+ }
19242
+ ) : (
19243
+ // No resolved image (host couldn't resolve the raster) — keep the
19244
+ // aspect box so cards still make sense, but show nothing to overlay on.
19245
+ /* @__PURE__ */ jsxs(
19246
+ "div",
19247
+ {
19248
+ style: {
19249
+ width: "100%",
19250
+ aspectRatio: `${page.width_pt} / ${page.height_pt}`,
19251
+ background: PAPER2,
19252
+ display: "flex",
19253
+ alignItems: "center",
19254
+ justifyContent: "center",
19255
+ fontSize: "12px",
19256
+ color: MUTED2,
19257
+ lineHeight: 1.4
19258
+ },
19259
+ children: [
19260
+ "Page ",
19261
+ page.page + 1,
19262
+ " image unavailable"
19263
+ ]
19264
+ }
19265
+ )
19266
+ ),
19267
+ px && page.imageUrl && fields.map((f) => {
19268
+ var _a;
19269
+ const rect = bboxToRect((_a = f.bbox) != null ? _a : null, pagePts, px);
19270
+ if (!rect) return null;
19271
+ const color = fieldColor2(f, secondary);
19272
+ const selected = selectedKey === f.field_key;
19273
+ return /* @__PURE__ */ jsx(
19274
+ "div",
19275
+ {
19276
+ ref: selected ? selectedBoxRef : null,
19277
+ "data-testid": "bbox-rect",
19278
+ "data-field-key": f.field_key,
19279
+ "data-selected": selected ? "true" : "false",
19280
+ onClick: () => onSelect(selected ? null : f.field_key),
19281
+ title: `${f.label}: ${f.value}`,
19282
+ style: {
19283
+ position: "absolute",
19284
+ left: `${rect.left}px`,
19285
+ top: `${rect.top}px`,
19286
+ width: `${rect.width}px`,
19287
+ height: `${rect.height}px`,
19288
+ border: `1px solid ${color}`,
19289
+ background: hexToRgba2(color, selected ? 0.28 : 0.12),
19290
+ boxShadow: selected ? `0 0 0 2px ${hexToRgba2(color, 0.5)}` : "none",
19291
+ borderRadius: "2px",
19292
+ cursor: "pointer",
19293
+ transition: "background 0.15s, box-shadow 0.15s"
19294
+ }
19295
+ },
19296
+ f.field_key
19297
+ );
19298
+ })
19299
+ ] });
19300
+ }
19301
+ function ExtractionDetail({
19302
+ pages,
19303
+ orderedFields,
19304
+ fieldsByPage,
19305
+ selectedKey,
19306
+ setSelectedKey,
19307
+ onFieldSave,
19308
+ correctionCounts,
19309
+ tab,
19310
+ setTab,
19311
+ editable,
19312
+ summary,
19313
+ fileName,
19314
+ pageCount,
19315
+ pagesProcessed,
19316
+ auditEvents,
19317
+ auditLoading
19318
+ }) {
19319
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
19320
+ const selectedCardRef = React45.useRef(null);
19321
+ React45.useEffect(() => {
19322
+ if (!selectedKey || tab !== "fields") return;
19323
+ const el = selectedCardRef.current;
19324
+ if (el && typeof el.scrollIntoView === "function") {
19325
+ el.scrollIntoView({ behavior: "smooth", block: "nearest" });
19326
+ }
19327
+ }, [selectedKey, tab]);
19328
+ const tabs = [
19329
+ { key: "details", label: "Details" },
19330
+ { key: "fields", label: "Fields", count: orderedFields.length }
19331
+ ];
19332
+ if (editable) tabs.push({ key: "audit", label: "Audit Trails", count: (auditEvents == null ? void 0 : auditEvents.length) || void 0 });
19333
+ return /* @__PURE__ */ jsxs(
19334
+ "div",
19335
+ {
19336
+ style: {
19337
+ display: "grid",
19338
+ gridTemplateColumns: "minmax(0, 3fr) minmax(260px, 1fr)",
19339
+ gap: "12px",
19340
+ height: "100%",
19341
+ minHeight: 0
19342
+ },
19343
+ children: [
19344
+ /* @__PURE__ */ jsx(
19345
+ "div",
19346
+ {
19347
+ style: {
19348
+ display: "flex",
19349
+ flexDirection: "column",
19350
+ gap: "10px",
19351
+ borderRadius: "0.75rem",
19352
+ border: `1px solid ${BORDER4}`,
19353
+ overflowY: "auto",
19354
+ minHeight: 0
19355
+ },
19356
+ children: pages.map((pg) => /* @__PURE__ */ jsx(
19357
+ PageOverlay,
19358
+ {
19359
+ page: pg,
19360
+ fields: fieldsByPage(pg.page),
19361
+ selectedKey,
19362
+ onSelect: (key) => {
19363
+ setSelectedKey(key);
19364
+ if (key) setTab("fields");
19365
+ },
19366
+ secondary: SECONDARY2
19367
+ },
19368
+ pg.page
19369
+ ))
19370
+ }
19371
+ ),
19372
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", minWidth: 0, minHeight: 0 }, children: [
19373
+ /* @__PURE__ */ jsx(
19374
+ "div",
19375
+ {
19376
+ style: {
19377
+ display: "flex",
19378
+ gap: "16px",
19379
+ borderBottom: `1px solid ${BORDER4}`,
19380
+ flexShrink: 0,
19381
+ marginBottom: "10px"
19382
+ },
19383
+ children: tabs.map((t) => {
19384
+ const active = tab === t.key;
19385
+ return /* @__PURE__ */ jsxs(
19386
+ "button",
19387
+ {
19388
+ type: "button",
19389
+ onClick: () => setTab(t.key),
19390
+ "data-testid": `tab-${t.key}`,
19391
+ style: {
19392
+ appearance: "none",
19393
+ background: "transparent",
19394
+ borderTop: "none",
19395
+ borderLeft: "none",
19396
+ borderRight: "none",
19397
+ borderBottom: `2px solid ${active ? SECONDARY2 : "transparent"}`,
19398
+ padding: "6px 2px",
19399
+ marginBottom: "-1px",
19400
+ cursor: "pointer",
19401
+ fontSize: "13px",
19402
+ fontWeight: 600,
19403
+ color: active ? SECONDARY2 : MUTED2,
19404
+ display: "inline-flex",
19405
+ alignItems: "center",
19406
+ gap: "6px"
19407
+ },
19408
+ children: [
19409
+ t.label,
19410
+ typeof t.count === "number" && /* @__PURE__ */ jsx(
19411
+ "span",
19412
+ {
19413
+ style: {
19414
+ fontSize: "11px",
19415
+ fontWeight: 600,
19416
+ padding: "1px 7px",
19417
+ borderRadius: "9999px",
19418
+ background: active ? "#eff6ff" : PAPER2,
19419
+ color: active ? SECONDARY2 : MUTED2
19420
+ },
19421
+ children: t.count
19422
+ }
19423
+ )
19424
+ ]
19425
+ },
19426
+ t.key
19427
+ );
19428
+ })
19429
+ }
19430
+ ),
19431
+ tab === "details" ? /* @__PURE__ */ jsx(
19432
+ FieldDetails,
19433
+ {
19434
+ summary,
19435
+ fileName,
19436
+ pageCount,
19437
+ pagesProcessed
19438
+ }
19439
+ ) : tab === "audit" ? /* @__PURE__ */ jsx("div", { style: { minHeight: 0, overflowY: "auto" }, children: /* @__PURE__ */ jsx(
19440
+ FieldAuditLog,
19441
+ {
19442
+ events: auditEvents != null ? auditEvents : [],
19443
+ loading: auditLoading != null ? auditLoading : false,
19444
+ fields: orderedFields.map((f) => ({ field_key: f.field_key, label: f.label }))
19445
+ }
19446
+ ) }) : /* @__PURE__ */ jsxs(
19447
+ "div",
19448
+ {
19449
+ style: {
19450
+ display: "flex",
19451
+ flexDirection: "column",
19452
+ minHeight: 0,
19453
+ overflowY: "auto",
19454
+ paddingRight: "4px"
19455
+ },
19456
+ children: [
19457
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: "12px", color: MUTED2, padding: "0 0 8px 2px", flexShrink: 0 }, children: [
19458
+ orderedFields.length,
19459
+ " extracted"
19460
+ ] }),
19461
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: orderedFields.map((f) => {
19462
+ var _a;
19463
+ const selected = selectedKey === f.field_key;
19464
+ return /* @__PURE__ */ jsx(
19465
+ FieldDetail,
19466
+ {
19467
+ field: f,
19468
+ selected,
19469
+ onSelect: setSelectedKey,
19470
+ onSave: onFieldSave,
19471
+ correctionCount: (_a = correctionCounts == null ? void 0 : correctionCounts[f.field_key]) != null ? _a : 0,
19472
+ cardRef: selected ? selectedCardRef : void 0
19473
+ },
19474
+ f.field_key
19475
+ );
19476
+ }) })
19477
+ ]
19478
+ }
19479
+ )
19480
+ ] })
19481
+ ]
19482
+ }
19483
+ );
19484
+ }
19485
+ function ExtractionModal({
19486
+ open,
19487
+ onClose,
19488
+ title,
19489
+ children
19490
+ }) {
19491
+ const { BORDER: BORDER4, MUTED: MUTED2 } = useTheme();
19492
+ React45.useEffect(() => {
19493
+ if (!open) return;
19494
+ const onKey = (e) => {
19495
+ if (e.key === "Escape") onClose();
19496
+ };
19497
+ window.addEventListener("keydown", onKey);
19498
+ const prev = document.body.style.overflow;
19499
+ document.body.style.overflow = "hidden";
19500
+ return () => {
19501
+ window.removeEventListener("keydown", onKey);
19502
+ document.body.style.overflow = prev;
19503
+ };
19504
+ }, [open, onClose]);
19505
+ if (!open || typeof document === "undefined") return null;
19506
+ return createPortal(
19507
+ /* @__PURE__ */ jsx(
19508
+ "div",
19509
+ {
19510
+ role: "dialog",
19511
+ "aria-modal": "true",
19512
+ "aria-label": title,
19513
+ onClick: onClose,
19514
+ style: {
19515
+ position: "fixed",
19516
+ inset: 0,
19517
+ zIndex: 2147483e3,
19518
+ background: "rgba(0,0,0,0.5)",
19519
+ display: "flex",
19520
+ alignItems: "center",
19521
+ justifyContent: "center",
19522
+ padding: "4vh 4vw",
19523
+ backdropFilter: "blur(2px)"
19524
+ },
19525
+ children: /* @__PURE__ */ jsxs(
19526
+ "div",
19527
+ {
19528
+ onClick: (e) => e.stopPropagation(),
19529
+ style: {
19530
+ width: "90vw",
19531
+ height: "90vh",
19532
+ background: "white",
19533
+ borderRadius: "0.875rem",
19534
+ border: `1px solid ${BORDER4}`,
19535
+ boxShadow: "0 20px 60px rgba(0,0,0,0.30)",
19536
+ display: "flex",
19537
+ flexDirection: "column",
19538
+ overflow: "hidden"
19539
+ },
19540
+ children: [
19541
+ /* @__PURE__ */ jsxs(
19542
+ "div",
19543
+ {
19544
+ style: {
19545
+ display: "flex",
19546
+ alignItems: "center",
19547
+ gap: "10px",
19548
+ padding: "11px 16px",
19549
+ borderBottom: `1px solid ${BORDER4}`,
19550
+ flexShrink: 0
19551
+ },
19552
+ children: [
19553
+ /* @__PURE__ */ jsx(
19554
+ "span",
19555
+ {
19556
+ style: {
19557
+ flex: 1,
19558
+ minWidth: 0,
19559
+ fontFamily: "var(--font-serif)",
19560
+ fontSize: "16px",
19561
+ fontWeight: 400,
19562
+ letterSpacing: "-0.01em",
19563
+ color: "var(--foreground)",
19564
+ overflow: "hidden",
19565
+ textOverflow: "ellipsis",
19566
+ whiteSpace: "nowrap"
19567
+ },
19568
+ children: title
19569
+ }
19570
+ ),
19571
+ /* @__PURE__ */ jsx(
19572
+ "button",
19573
+ {
19574
+ type: "button",
19575
+ "aria-label": "Close",
19576
+ onClick: onClose,
19577
+ style: {
19578
+ border: `1px solid ${BORDER4}`,
19579
+ borderRadius: "8px",
19580
+ background: "white",
19581
+ cursor: "pointer",
19582
+ padding: "5px 9px",
19583
+ fontSize: "13px",
19584
+ color: MUTED2,
19585
+ lineHeight: 1
19586
+ },
19587
+ children: "\u2715"
19588
+ }
19589
+ )
19590
+ ]
19591
+ }
19592
+ ),
19593
+ /* @__PURE__ */ jsx(
19594
+ "div",
19595
+ {
19596
+ style: {
19597
+ flex: 1,
19598
+ minHeight: 0,
19599
+ overflow: "hidden",
19600
+ display: "flex",
19601
+ flexDirection: "column",
19602
+ padding: "14px 16px"
19603
+ },
19604
+ children
19605
+ }
19606
+ )
19607
+ ]
19608
+ }
19609
+ )
19610
+ }
19611
+ ),
19612
+ document.body
19613
+ );
19614
+ }
19615
+ function DocumentFieldExtractionResolver(p) {
19616
+ var _a, _b;
19617
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2 } = useTheme();
19618
+ const [selectedKey, setSelectedKey] = React45.useState(null);
19619
+ const [open, setOpen] = React45.useState(false);
19620
+ const [tab, setTab] = React45.useState("fields");
19621
+ const pages = (_a = p.pages) != null ? _a : [];
19622
+ const fields = (_b = p.fields) != null ? _b : [];
19623
+ const editable = typeof p.onFieldSave === "function";
19624
+ const onLoadAudit = p.onLoadAudit;
19625
+ React45.useEffect(() => {
19626
+ if (tab === "audit" && onLoadAudit) {
19627
+ onLoadAudit();
19628
+ }
19629
+ }, [tab, onLoadAudit]);
19630
+ const correctionCounts = React45.useMemo(() => {
19631
+ var _a2, _b2;
19632
+ const counts = {};
19633
+ for (const ev of (_a2 = p.auditEvents) != null ? _a2 : []) {
19634
+ const human = ev.actor_type !== "system" && ev.event_type !== "ai_extracted";
19635
+ if (human) counts[ev.field_key] = ((_b2 = counts[ev.field_key]) != null ? _b2 : 0) + 1;
19636
+ }
19637
+ return counts;
19638
+ }, [p.auditEvents]);
19639
+ const orderedFields = [...fields].sort((a, b) => {
19640
+ var _a2, _b2;
19641
+ if (!!a.is_primary !== !!b.is_primary) return a.is_primary ? -1 : 1;
19642
+ return ((_a2 = b.confidence) != null ? _a2 : 0) - ((_b2 = a.confidence) != null ? _b2 : 0);
19643
+ });
19644
+ const fieldsByPage = (pageNo) => fields.filter((f) => f.page === pageNo);
19645
+ const csvCols = [
19646
+ { key: "label", label: "Field" },
19647
+ { key: "value", label: "Value" },
19648
+ { key: "page", label: "Page" },
19649
+ { key: "confidence", label: "Confidence" },
19650
+ { key: "badge", label: "Badge" },
19651
+ { key: "state", label: "State" }
19652
+ ];
19653
+ const csvRows = orderedFields.map((f) => {
19654
+ var _a2, _b2, _c;
19655
+ return {
19656
+ label: f.label,
19657
+ value: f.value,
19658
+ page: f.page + 1,
19659
+ confidence: (_a2 = f.confidence) != null ? _a2 : "",
19660
+ badge: (_b2 = f.badge) != null ? _b2 : "",
19661
+ state: (_c = f.state) != null ? _c : ""
19662
+ };
19663
+ });
19664
+ const title = p.file_name || (p.doc_type ? `${p.doc_type} \u2014 extracted fields` : "Extracted fields");
19665
+ const tierCounts = fields.reduce(
19666
+ (acc, f) => {
19667
+ var _a2;
19668
+ const t = (_a2 = f.confidence_tier) != null ? _a2 : "amber";
19669
+ if (t === "green") acc.high += 1;
19670
+ else if (t === "red") acc.low += 1;
19671
+ else acc.med += 1;
19672
+ return acc;
19673
+ },
19674
+ { high: 0, med: 0, low: 0 }
19675
+ );
19676
+ const chips = [
19677
+ { n: tierCounts.high, label: "high", color: TIER_COLORS2.green },
19678
+ { n: tierCounts.med, label: "medium", color: TIER_COLORS2.amber },
19679
+ { n: tierCounts.low, label: "low", color: TIER_COLORS2.red }
19680
+ ].filter((c) => c.n > 0);
19681
+ const thumb = pages.find((pg) => pg.imageUrl);
19682
+ return /* @__PURE__ */ jsxs(
19683
+ ComponentActions,
19684
+ {
19685
+ filename: "document-fields",
19686
+ onDownloadCSV: () => downloadCSV(csvCols, csvRows, "document-fields"),
19687
+ children: [
19688
+ /* @__PURE__ */ jsxs(
19689
+ "div",
19690
+ {
19691
+ role: "button",
19692
+ tabIndex: 0,
19693
+ onClick: () => setOpen(true),
19694
+ onKeyDown: (e) => {
19695
+ if (e.key === "Enter" || e.key === " ") {
19696
+ e.preventDefault();
19697
+ setOpen(true);
19698
+ }
19699
+ },
19700
+ style: {
19701
+ display: "flex",
19702
+ alignItems: "stretch",
19703
+ gap: "12px",
19704
+ padding: "12px",
19705
+ width: "100%",
19706
+ maxWidth: "440px",
19707
+ borderRadius: "0.75rem",
19708
+ border: `1px solid ${BORDER4}`,
19709
+ background: "white",
19710
+ cursor: "pointer",
19711
+ textAlign: "left",
19712
+ boxShadow: "0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.05)"
19713
+ },
19714
+ children: [
19715
+ /* @__PURE__ */ jsx(
19716
+ "div",
19717
+ {
19718
+ style: {
19719
+ width: "64px",
19720
+ flexShrink: 0,
19721
+ borderRadius: "0.5rem",
19722
+ border: `1px solid ${BORDER4}`,
19723
+ background: PAPER2,
19724
+ overflow: "hidden",
19725
+ display: "flex",
19726
+ alignItems: "center",
19727
+ justifyContent: "center"
19728
+ },
19729
+ children: (thumb == null ? void 0 : thumb.imageUrl) ? /* @__PURE__ */ jsx(
19730
+ "img",
19731
+ {
19732
+ src: thumb.imageUrl,
19733
+ alt: "Document preview",
19734
+ style: { width: "100%", height: "auto", display: "block" }
19735
+ }
19736
+ ) : /* @__PURE__ */ jsx("span", { style: { fontSize: "22px", lineHeight: 1, padding: "16px 0" }, children: "\u{1F4C4}" })
19737
+ }
19738
+ ),
19739
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "6px" }, children: [
19740
+ /* @__PURE__ */ jsx(
19741
+ "p",
19742
+ {
19743
+ style: {
19744
+ fontFamily: "var(--font-serif)",
19745
+ fontSize: "15px",
19746
+ fontWeight: 400,
19747
+ color: "var(--foreground)",
19748
+ letterSpacing: "-0.01em",
19749
+ margin: 0,
19750
+ overflow: "hidden",
19751
+ textOverflow: "ellipsis",
19752
+ whiteSpace: "nowrap"
19753
+ },
19754
+ children: p.file_name || p.doc_type || "Document"
19755
+ }
19756
+ ),
19757
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: "12px", color: MUTED2 }, children: [
19758
+ fields.length,
19759
+ " field",
19760
+ fields.length === 1 ? "" : "s",
19761
+ " extracted \xB7 ",
19762
+ pages.length,
19763
+ " page",
19764
+ pages.length === 1 ? "" : "s"
19765
+ ] }),
19766
+ chips.length > 0 && /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "5px" }, children: chips.map((c) => /* @__PURE__ */ jsxs(
19767
+ "span",
19768
+ {
19769
+ style: {
19770
+ display: "inline-flex",
19771
+ alignItems: "center",
19772
+ gap: "4px",
19773
+ fontSize: "10px",
19774
+ fontWeight: 600,
19775
+ padding: "2px 7px",
19776
+ borderRadius: "9999px",
19777
+ background: hexToRgba2(c.color, 0.12),
19778
+ color: c.color
19779
+ },
19780
+ children: [
19781
+ /* @__PURE__ */ jsx(
19782
+ "span",
19783
+ {
19784
+ style: {
19785
+ width: "6px",
19786
+ height: "6px",
19787
+ borderRadius: "9999px",
19788
+ background: c.color
19789
+ }
19790
+ }
19791
+ ),
19792
+ c.n,
19793
+ " ",
19794
+ c.label
19795
+ ]
19796
+ },
19797
+ c.label
19798
+ )) }),
19799
+ /* @__PURE__ */ jsx(
19800
+ "span",
19801
+ {
19802
+ style: {
19803
+ marginTop: "2px",
19804
+ alignSelf: "flex-start",
19805
+ fontSize: "12px",
19806
+ fontWeight: 600,
19807
+ padding: "6px 12px",
19808
+ borderRadius: "0.5rem",
19809
+ background: "var(--foreground)",
19810
+ color: "white"
19811
+ },
19812
+ children: "View & edit fields"
19813
+ }
19814
+ )
19815
+ ] })
19816
+ ]
19817
+ }
19818
+ ),
19819
+ /* @__PURE__ */ jsx(ExtractionModal, { open, onClose: () => setOpen(false), title, children: /* @__PURE__ */ jsx(
19820
+ ExtractionDetail,
19821
+ {
19822
+ pages,
19823
+ orderedFields,
19824
+ fieldsByPage,
19825
+ selectedKey,
19826
+ setSelectedKey,
19827
+ onFieldSave: p.onFieldSave,
19828
+ correctionCounts,
19829
+ tab,
19830
+ setTab,
19831
+ editable,
19832
+ summary: p.summary,
19833
+ fileName: p.file_name,
19834
+ pageCount: p.page_count,
19835
+ pagesProcessed: p.pages_processed,
19836
+ auditEvents: p.auditEvents,
19837
+ auditLoading: p.auditLoading
19838
+ }
19839
+ ) })
19840
+ ]
19841
+ }
19842
+ );
19843
+ }
19844
+ init_ThemeContext();
19845
+ var SEVERITY_COLORS = {
19846
+ high: { color: "#dc2626", bg: "#fef2f2" },
19847
+ medium: { color: "#f59e0b", bg: "#fff7ed" },
19848
+ low: { color: "#777777", bg: "#f2f2f2" }
19849
+ };
19850
+ var GREEN3 = "#15803d";
19851
+ var GREEN_SOFT = "#dcfce7";
19852
+ var STACK_BELOW = 380;
19853
+ function formatAmount2(amount, currency = "USD") {
19854
+ var _a, _b;
19855
+ const abs = Math.abs(amount);
19856
+ const sign = amount < 0 ? "-" : "";
19857
+ let body;
19858
+ if (abs >= 1e6) body = `${(abs / 1e6).toFixed(abs >= 1e7 ? 0 : 1)}M`;
19859
+ else if (abs >= 1e3) body = `${(abs / 1e3).toFixed(abs >= 1e4 ? 0 : 1)}K`;
19860
+ else body = `${abs}`;
19861
+ let symbol = "$";
19862
+ try {
19863
+ const parts = new Intl.NumberFormat("en-US", {
19864
+ style: "currency",
19865
+ currency,
19866
+ maximumFractionDigits: 0
19867
+ }).formatToParts(0);
19868
+ symbol = (_b = (_a = parts.find((p) => p.type === "currency")) == null ? void 0 : _a.value) != null ? _b : "$";
19869
+ } catch (e) {
19870
+ symbol = "$";
19871
+ }
19872
+ return `${sign}${symbol}${body}`;
19873
+ }
19874
+ function useContainerWidth2(ref) {
19875
+ const [w, setW] = React45.useState(0);
19876
+ React45.useLayoutEffect(() => {
19877
+ const el = ref.current;
19878
+ if (!el || typeof ResizeObserver === "undefined") return;
19879
+ const ro = new ResizeObserver((entries) => {
19880
+ var _a;
19881
+ const cr = (_a = entries[0]) == null ? void 0 : _a.contentRect;
19882
+ if (cr) setW(cr.width);
19883
+ });
19884
+ ro.observe(el);
19885
+ setW(el.getBoundingClientRect().width);
19886
+ return () => ro.disconnect();
19887
+ }, [ref]);
19888
+ return w;
19889
+ }
19890
+ var KEYFRAMES2 = `
19891
+ @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
19892
+ .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
19893
+ @media (prefers-reduced-motion: reduce){
19894
+ .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
19895
+ }`;
19896
+ function SparkCheck({ size, color }) {
19897
+ return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
19898
+ "path",
19899
+ {
19900
+ d: "M5 13l4 4L19 7",
19901
+ stroke: color,
19902
+ strokeWidth: 2.5,
19903
+ strokeLinecap: "round",
19904
+ strokeLinejoin: "round"
19905
+ }
19906
+ ) });
19907
+ }
19908
+ function FlagPill({ flag }) {
19909
+ var _a;
19910
+ const sev = (_a = flag.severity) != null ? _a : "medium";
19911
+ const { color, bg } = SEVERITY_COLORS[sev];
19912
+ return /* @__PURE__ */ jsxs(
19913
+ "span",
19914
+ {
19915
+ style: {
19916
+ display: "inline-flex",
19917
+ alignItems: "center",
19918
+ gap: 5,
19919
+ fontSize: 11,
19920
+ fontWeight: 600,
19921
+ padding: "3px 9px",
19922
+ borderRadius: 9999,
19923
+ background: bg,
19924
+ color,
19925
+ lineHeight: 1.2
19926
+ },
19927
+ children: [
19928
+ /* @__PURE__ */ jsx(
19929
+ "span",
19930
+ {
19931
+ "aria-hidden": "true",
19932
+ style: { width: 6, height: 6, borderRadius: "50%", background: color, flexShrink: 0 }
19933
+ }
19934
+ ),
19935
+ flag.field ? `${flag.field}: ${flag.issue}` : flag.issue
19936
+ ]
18051
19937
  }
18052
19938
  );
18053
19939
  }
@@ -18059,7 +19945,7 @@ function DecisionCardRenderer({
18059
19945
  }) {
18060
19946
  var _a, _b;
18061
19947
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
18062
- const rootRef = React41.useRef(null);
19948
+ const rootRef = React45.useRef(null);
18063
19949
  const width = useContainerWidth2(rootRef);
18064
19950
  const stacked = width > 0 && width < STACK_BELOW;
18065
19951
  const options = (_a = data.options) != null ? _a : [];
@@ -18316,8 +20202,8 @@ function DecisionCardResolver(p) {
18316
20202
  const decisionId = (_a = p.id) != null ? _a : p.title;
18317
20203
  const hostResolved = resolvedDecisions == null ? void 0 : resolvedDecisions[decisionId];
18318
20204
  const initial = (_c = hostResolved != null ? hostResolved : (_b = p.resolved) == null ? void 0 : _b.option) != null ? _c : null;
18319
- const [localResolved, setLocalResolved] = React41.useState(initial);
18320
- React41.useEffect(() => {
20205
+ const [localResolved, setLocalResolved] = React45.useState(initial);
20206
+ React45.useEffect(() => {
18321
20207
  if (hostResolved !== void 0) setLocalResolved(hostResolved);
18322
20208
  }, [hostResolved]);
18323
20209
  const resolved = hostResolved != null ? hostResolved : localResolved;
@@ -18342,6 +20228,317 @@ function DecisionCardResolver(p) {
18342
20228
  }
18343
20229
  ) });
18344
20230
  }
20231
+ init_ThemeContext();
20232
+ var CONNECTED_GREEN3 = "#15803d";
20233
+ var CONNECTED_GREEN_BG = "#dcfce7";
20234
+ var PENDING_AMBER = "#92400e";
20235
+ var PENDING_AMBER_BG = "#fff7ed";
20236
+ var CARD_TITLE = "Authentication required";
20237
+ var TRUST_FOOTER = "Credentials not stored by Adopt";
20238
+ var DEFAULT_STEPS = (app, ctaLabel, connected) => connected ? [
20239
+ `Click ${ctaLabel} below to open ${app} in a new tab.`,
20240
+ "Confirm you are signed in \u2014 re-authenticate if prompted.",
20241
+ "Return here \u2014 the request continues automatically."
20242
+ ] : [
20243
+ `Click ${ctaLabel} below to open the sign-in page.`,
20244
+ `Sign in with your ${app} credentials \u2014 SSO is supported.`,
20245
+ "Return here \u2014 the request resumes automatically."
20246
+ ];
20247
+ function humanizeApp(raw) {
20248
+ const v = raw.trim();
20249
+ if (!v) return v;
20250
+ const looksLikeSlug = /^[a-z0-9]+([_-][a-z0-9]+)*$/.test(v);
20251
+ if (!looksLikeSlug) return v;
20252
+ return v.split(/[_-]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
20253
+ }
20254
+ function ShieldIcon({ color }) {
20255
+ return /* @__PURE__ */ jsxs(
20256
+ "svg",
20257
+ {
20258
+ width: "13",
20259
+ height: "13",
20260
+ viewBox: "0 0 24 24",
20261
+ fill: "none",
20262
+ stroke: color,
20263
+ strokeWidth: "2",
20264
+ strokeLinecap: "round",
20265
+ strokeLinejoin: "round",
20266
+ "aria-hidden": "true",
20267
+ style: { flexShrink: 0 },
20268
+ children: [
20269
+ /* @__PURE__ */ jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }),
20270
+ /* @__PURE__ */ jsx("path", { d: "m9 12 2 2 4-4" })
20271
+ ]
20272
+ }
20273
+ );
20274
+ }
20275
+ function ExternalIcon() {
20276
+ return /* @__PURE__ */ jsxs(
20277
+ "svg",
20278
+ {
20279
+ width: "13",
20280
+ height: "13",
20281
+ viewBox: "0 0 24 24",
20282
+ fill: "none",
20283
+ stroke: "currentColor",
20284
+ strokeWidth: "2",
20285
+ strokeLinecap: "round",
20286
+ strokeLinejoin: "round",
20287
+ "aria-hidden": "true",
20288
+ style: { flexShrink: 0 },
20289
+ children: [
20290
+ /* @__PURE__ */ jsx("path", { d: "M15 3h6v6" }),
20291
+ /* @__PURE__ */ jsx("path", { d: "M10 14 21 3" }),
20292
+ /* @__PURE__ */ jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
20293
+ ]
20294
+ }
20295
+ );
20296
+ }
20297
+ function TabbyAuthResolver(p) {
20298
+ var _a, _b, _c;
20299
+ const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
20300
+ const [cardHovered, setCardHovered] = useState(false);
20301
+ const [btnHovered, setBtnHovered] = useState(false);
20302
+ const [imgFailed, setImgFailed] = useState(false);
20303
+ const app = humanizeApp(p.app || "the app");
20304
+ const connected = p.state === "connected";
20305
+ const accent = connected ? CONNECTED_GREEN3 : ACCENT2;
20306
+ const ctaLabel = (_a = p.ctaLabel) != null ? _a : connected ? `Open ${app}` : `Connect ${app}`;
20307
+ const subtitle = p.workspace ? `${app} \xB7 ${p.workspace} workspace` : app;
20308
+ const steps = ((_b = p.steps) == null ? void 0 : _b.length) ? p.steps : DEFAULT_STEPS(app, ctaLabel, connected);
20309
+ 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.`;
20310
+ const iconSrc = p.iconUrl || brandIconUrl(app);
20311
+ const showImg = Boolean(iconSrc) && !imgFailed;
20312
+ const initial = app.charAt(0).toUpperCase();
20313
+ const badge = connected ? { label: "Connected", bg: CONNECTED_GREEN_BG, color: CONNECTED_GREEN3 } : { label: "Pending sign-in", bg: PENDING_AMBER_BG, color: PENDING_AMBER };
20314
+ const sectionPad = "13px 16px";
20315
+ return /* @__PURE__ */ jsx(ComponentActions, { filename: `${app} authentication`, children: /* @__PURE__ */ jsx("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: "10px" }, children: /* @__PURE__ */ jsxs(
20316
+ "div",
20317
+ {
20318
+ onMouseEnter: () => setCardHovered(true),
20319
+ onMouseLeave: () => setCardHovered(false),
20320
+ style: {
20321
+ display: "flex",
20322
+ flexDirection: "row",
20323
+ alignItems: "stretch",
20324
+ borderRadius: "0.75rem",
20325
+ border: `1px solid ${cardHovered ? "#d2d2d2" : BORDER4}`,
20326
+ background: "white",
20327
+ overflow: "hidden",
20328
+ 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)",
20329
+ transition: "box-shadow 0.18s ease, border-color 0.18s ease"
20330
+ },
20331
+ children: [
20332
+ /* @__PURE__ */ jsx("div", { style: { width: "3px", flexShrink: 0, background: accent } }),
20333
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column" }, children: [
20334
+ /* @__PURE__ */ jsxs(
20335
+ "div",
20336
+ {
20337
+ style: {
20338
+ display: "flex",
20339
+ alignItems: "flex-start",
20340
+ gap: "12px",
20341
+ padding: sectionPad
20342
+ },
20343
+ children: [
20344
+ /* @__PURE__ */ jsx(
20345
+ "div",
20346
+ {
20347
+ style: {
20348
+ position: "relative",
20349
+ width: "34px",
20350
+ height: "34px",
20351
+ borderRadius: "9px",
20352
+ flexShrink: 0,
20353
+ display: "flex",
20354
+ alignItems: "center",
20355
+ justifyContent: "center",
20356
+ background: showImg ? "white" : "#fff3ee",
20357
+ boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.06)",
20358
+ overflow: "hidden"
20359
+ },
20360
+ children: showImg ? /* @__PURE__ */ jsx(
20361
+ "img",
20362
+ {
20363
+ src: iconSrc,
20364
+ alt: app,
20365
+ onError: () => setImgFailed(true),
20366
+ style: { width: "22px", height: "22px", objectFit: "contain" }
20367
+ }
20368
+ ) : /* @__PURE__ */ jsx(
20369
+ "span",
20370
+ {
20371
+ style: {
20372
+ fontFamily: "var(--font-serif)",
20373
+ fontSize: "17px",
20374
+ fontWeight: 400,
20375
+ color: ACCENT2,
20376
+ lineHeight: 1
20377
+ },
20378
+ children: initial
20379
+ }
20380
+ )
20381
+ }
20382
+ ),
20383
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "2px" }, children: [
20384
+ /* @__PURE__ */ jsx(
20385
+ "span",
20386
+ {
20387
+ style: {
20388
+ fontFamily: "var(--font-serif)",
20389
+ fontSize: "15px",
20390
+ fontWeight: 400,
20391
+ color: "var(--foreground)",
20392
+ letterSpacing: "-0.01em",
20393
+ lineHeight: 1.2
20394
+ },
20395
+ children: CARD_TITLE
20396
+ }
20397
+ ),
20398
+ /* @__PURE__ */ jsx(
20399
+ "span",
20400
+ {
20401
+ style: {
20402
+ fontSize: "12px",
20403
+ color: MUTED2,
20404
+ whiteSpace: "nowrap",
20405
+ overflow: "hidden",
20406
+ textOverflow: "ellipsis"
20407
+ },
20408
+ children: subtitle
20409
+ }
20410
+ )
20411
+ ] }),
20412
+ /* @__PURE__ */ jsxs(
20413
+ "span",
20414
+ {
20415
+ style: {
20416
+ display: "inline-flex",
20417
+ alignItems: "center",
20418
+ gap: "5px",
20419
+ flexShrink: 0,
20420
+ fontSize: "10.5px",
20421
+ fontWeight: 600,
20422
+ padding: "3px 9px",
20423
+ borderRadius: "9999px",
20424
+ background: badge.bg,
20425
+ color: badge.color,
20426
+ whiteSpace: "nowrap"
20427
+ },
20428
+ children: [
20429
+ /* @__PURE__ */ jsx(
20430
+ "span",
20431
+ {
20432
+ style: {
20433
+ width: "6px",
20434
+ height: "6px",
20435
+ borderRadius: "9999px",
20436
+ background: badge.color
20437
+ }
20438
+ }
20439
+ ),
20440
+ badge.label
20441
+ ]
20442
+ }
20443
+ )
20444
+ ]
20445
+ }
20446
+ ),
20447
+ /* @__PURE__ */ jsxs(
20448
+ "div",
20449
+ {
20450
+ style: {
20451
+ borderTop: `1px solid ${BORDER4}`,
20452
+ padding: sectionPad,
20453
+ display: "flex",
20454
+ flexDirection: "column",
20455
+ gap: "12px"
20456
+ },
20457
+ children: [
20458
+ description && /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12.5px", lineHeight: 1.5, color: "var(--foreground)" }, children: description }),
20459
+ /* @__PURE__ */ jsx("ol", { style: { margin: 0, padding: 0, listStyle: "none", display: "flex", flexDirection: "column", gap: "8px" }, children: steps.map((step, i) => /* @__PURE__ */ jsxs("li", { style: { display: "flex", alignItems: "flex-start", gap: "10px" }, children: [
20460
+ /* @__PURE__ */ jsx(
20461
+ "span",
20462
+ {
20463
+ style: {
20464
+ flexShrink: 0,
20465
+ width: "18px",
20466
+ height: "18px",
20467
+ borderRadius: "9999px",
20468
+ background: accent,
20469
+ color: "white",
20470
+ fontSize: "10.5px",
20471
+ fontWeight: 600,
20472
+ display: "flex",
20473
+ alignItems: "center",
20474
+ justifyContent: "center",
20475
+ marginTop: "1px"
20476
+ },
20477
+ children: i + 1
20478
+ }
20479
+ ),
20480
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "12.5px", lineHeight: 1.45, color: "var(--foreground)" }, children: step })
20481
+ ] }, i)) })
20482
+ ]
20483
+ }
20484
+ ),
20485
+ /* @__PURE__ */ jsxs(
20486
+ "div",
20487
+ {
20488
+ style: {
20489
+ borderTop: `1px solid ${BORDER4}`,
20490
+ padding: sectionPad,
20491
+ background: "#fbfbfb",
20492
+ display: "flex",
20493
+ alignItems: "center",
20494
+ justifyContent: "space-between",
20495
+ gap: "12px",
20496
+ flexWrap: "wrap"
20497
+ },
20498
+ children: [
20499
+ /* @__PURE__ */ jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: "6px", color: MUTED2, fontSize: "11.5px" }, children: [
20500
+ /* @__PURE__ */ jsx(ShieldIcon, { color: CONNECTED_GREEN3 }),
20501
+ TRUST_FOOTER
20502
+ ] }),
20503
+ /* @__PURE__ */ jsxs(
20504
+ "a",
20505
+ {
20506
+ href: p.url,
20507
+ target: "_blank",
20508
+ rel: "noopener noreferrer",
20509
+ onMouseEnter: () => setBtnHovered(true),
20510
+ onMouseLeave: () => setBtnHovered(false),
20511
+ style: {
20512
+ display: "inline-flex",
20513
+ alignItems: "center",
20514
+ gap: "7px",
20515
+ flexShrink: 0,
20516
+ borderRadius: "8px",
20517
+ padding: "8px 15px",
20518
+ fontSize: "12.5px",
20519
+ fontWeight: 600,
20520
+ textDecoration: "none",
20521
+ whiteSpace: "nowrap",
20522
+ cursor: "pointer",
20523
+ color: "white",
20524
+ border: "1px solid transparent",
20525
+ background: btnHovered ? connected ? "#126a33" : ACCENT_SOFT2 : accent,
20526
+ transition: "background 0.15s ease"
20527
+ },
20528
+ children: [
20529
+ /* @__PURE__ */ jsx(ExternalIcon, {}),
20530
+ ctaLabel
20531
+ ]
20532
+ }
20533
+ )
20534
+ ]
20535
+ }
20536
+ )
20537
+ ] })
20538
+ ]
20539
+ }
20540
+ ) }) });
20541
+ }
18345
20542
  function resolveUI(rawPayload) {
18346
20543
  const payload = coercePayload(rawPayload);
18347
20544
  switch (payload.type) {
@@ -18459,8 +20656,12 @@ function resolveUI(rawPayload) {
18459
20656
  return /* @__PURE__ */ jsx(PipelinePreviewResolver, __spreadValues({}, payload));
18460
20657
  case "workflow-stepper":
18461
20658
  return /* @__PURE__ */ jsx(WorkflowStepperResolver, __spreadValues({}, payload));
20659
+ case "document-field-extraction":
20660
+ return /* @__PURE__ */ jsx(DocumentFieldExtractionResolver, __spreadValues({}, payload));
18462
20661
  case "decision-card":
18463
20662
  return /* @__PURE__ */ jsx(DecisionCardResolver, __spreadValues({}, payload));
20663
+ case "tabby-auth":
20664
+ return /* @__PURE__ */ jsx(TabbyAuthResolver, __spreadValues({}, payload));
18464
20665
  default: {
18465
20666
  return /* @__PURE__ */ jsx(
18466
20667
  "div",