@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/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import React41, { lazy, createContext, useMemo, useContext, useState, useCallback, useEffect, useRef, useLayoutEffect, Suspense } from 'react';
2
+ import React45, { lazy, createContext, useMemo, useContext, useState, useCallback, useEffect, useRef, useLayoutEffect, Suspense } 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';
@@ -5227,7 +5227,32 @@ var workflowStepperSchema = z.object({
5227
5227
  n: z.number().int().positive().optional(),
5228
5228
  title: z.string(),
5229
5229
  sub: z.string().optional(),
5230
- status: z.enum(["done", "active", "review", "pending", "blocked", "failed"]),
5230
+ status: z.enum([
5231
+ "done",
5232
+ "active",
5233
+ "running",
5234
+ "review",
5235
+ "pending",
5236
+ "blocked",
5237
+ "failed"
5238
+ ]),
5239
+ // Optional quality-gate verdict for a step run by an executor (e.g. a
5240
+ // pipeline). Surfaces a subtle trust badge; flags hint at issues a human
5241
+ // should review (the full list lives in the escalation dock).
5242
+ eval: z.object({
5243
+ score: z.number().min(0).max(1).nullable().optional(),
5244
+ verdict: z.enum(["good", "bad"]).optional(),
5245
+ reasoning: z.string().optional(),
5246
+ judge_ok: z.boolean().optional(),
5247
+ data_quality_flags: z.array(
5248
+ z.object({
5249
+ field: z.string().optional(),
5250
+ issue: z.string().optional(),
5251
+ severity: z.enum(["low", "medium", "high"]).optional(),
5252
+ details: z.string().optional()
5253
+ })
5254
+ ).optional()
5255
+ }).optional(),
5231
5256
  assignees: z.array(
5232
5257
  z.object({
5233
5258
  name: z.string(),
@@ -5263,7 +5288,32 @@ var workflowStepperTool = {
5263
5288
  n: { type: "number", description: "Step number; defaults to index + 1" },
5264
5289
  title: { type: "string" },
5265
5290
  sub: { type: "string", description: "Short status caption, e.g. '7 accounts \xB7 2 exceptions'" },
5266
- status: { type: "string", enum: ["done", "active", "review", "pending", "blocked", "failed"] },
5291
+ status: {
5292
+ type: "string",
5293
+ enum: ["done", "active", "running", "review", "pending", "blocked", "failed"]
5294
+ },
5295
+ eval: {
5296
+ type: "object",
5297
+ description: "Optional quality-gate verdict for an executor-run step.",
5298
+ properties: {
5299
+ score: { type: "number" },
5300
+ verdict: { type: "string", enum: ["good", "bad"] },
5301
+ reasoning: { type: "string" },
5302
+ judge_ok: { type: "boolean" },
5303
+ data_quality_flags: {
5304
+ type: "array",
5305
+ items: {
5306
+ type: "object",
5307
+ properties: {
5308
+ field: { type: "string" },
5309
+ issue: { type: "string" },
5310
+ severity: { type: "string", enum: ["low", "medium", "high"] },
5311
+ details: { type: "string" }
5312
+ }
5313
+ }
5314
+ }
5315
+ }
5316
+ },
5267
5317
  assignees: {
5268
5318
  type: "array",
5269
5319
  maxItems: 6,
@@ -5287,6 +5337,183 @@ var workflowStepperTool = {
5287
5337
  required: ["type", "title", "steps"]
5288
5338
  }
5289
5339
  };
5340
+ var bbox = z.tuple([z.number(), z.number(), z.number(), z.number()]);
5341
+ var fieldSchema = z.object({
5342
+ field_key: z.string(),
5343
+ label: z.string(),
5344
+ value: z.string(),
5345
+ page: z.number(),
5346
+ // 0-indexed, matches PageDimension.page
5347
+ bbox: bbox.nullable().optional(),
5348
+ confidence: z.number().optional(),
5349
+ confidence_tier: z.enum(["green", "amber", "red"]).optional(),
5350
+ badge: z.enum(["SC", "CN", "AB", "SW"]).optional(),
5351
+ state: z.enum(["ok", "corrected", "missing", "warn"]).optional(),
5352
+ entity_type: z.string().optional(),
5353
+ is_primary: z.boolean().optional(),
5354
+ // Set after a human correction (extractor output, or an optimistic in-card
5355
+ // edit) so the editable field card can show old → new and who changed it.
5356
+ previous_value: z.string().nullable().optional(),
5357
+ corrected_by: z.string().nullable().optional()
5358
+ });
5359
+ var pageSchema = z.object({
5360
+ page: z.number(),
5361
+ // 0-indexed
5362
+ imageUrl: z.string().optional(),
5363
+ // host-resolved from the durable image_ref
5364
+ width_pt: z.number(),
5365
+ height_pt: z.number()
5366
+ });
5367
+ var summaryStatSchema = z.object({
5368
+ field_key: z.string(),
5369
+ label: z.string(),
5370
+ value: z.string(),
5371
+ caption: z.string().nullable().optional()
5372
+ });
5373
+ var summaryFactSchema = z.object({
5374
+ field_key: z.string(),
5375
+ label: z.string(),
5376
+ value: z.string(),
5377
+ badge: z.string().nullable().optional()
5378
+ });
5379
+ var summarySchema = z.object({
5380
+ display_name: z.string().nullable().optional(),
5381
+ short_name: z.string().nullable().optional(),
5382
+ organization: z.string().nullable().optional(),
5383
+ domain: z.string().nullable().optional(),
5384
+ domain_group: z.string().nullable().optional(),
5385
+ tax_year: z.union([z.string(), z.number()]).nullable().optional(),
5386
+ crumbs: z.array(z.string()).optional(),
5387
+ tags: z.array(z.string()).optional(),
5388
+ stats: z.array(summaryStatSchema).optional(),
5389
+ facts: z.array(summaryFactSchema).optional()
5390
+ });
5391
+ var documentFieldExtractionSchema = z.object({
5392
+ type: z.literal("document-field-extraction"),
5393
+ doc_type: z.string().optional(),
5394
+ // Original uploaded filename (e.g. "2024_gl.pdf"); preferred over doc_type for
5395
+ // the card title since doc_type is often the "generic_fallback" schema name.
5396
+ file_name: z.string().optional(),
5397
+ // Server-side token; resolved by the host into pages/fields before render.
5398
+ payload_ref: z.string().optional(),
5399
+ // Present for persisted workstream docs; absent for pre-existing cards.
5400
+ store_id: z.string().optional(),
5401
+ doc_id: z.string().optional(),
5402
+ pages: z.array(pageSchema).max(100).optional(),
5403
+ fields: z.array(fieldSchema).max(1e3).optional(),
5404
+ // Page-count metadata for the Details tab ("N of M pages extracted").
5405
+ page_count: z.number().optional(),
5406
+ pages_processed: z.number().optional(),
5407
+ // Deterministic document summary for the Details tab.
5408
+ summary: summarySchema.nullable().optional()
5409
+ });
5410
+ var documentFieldExtractionTool = {
5411
+ name: "render_document_field_extraction",
5412
+ 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.",
5413
+ input_schema: {
5414
+ type: "object",
5415
+ properties: {
5416
+ type: { type: "string", enum: ["document-field-extraction"] },
5417
+ doc_type: { type: "string" },
5418
+ file_name: {
5419
+ type: "string",
5420
+ description: "Original uploaded filename; shown as the card title."
5421
+ },
5422
+ payload_ref: {
5423
+ type: "string",
5424
+ 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."
5425
+ },
5426
+ store_id: {
5427
+ type: "string",
5428
+ description: "Docstore store id; present for persisted workstream docs. The host uses this to open the editable viewer."
5429
+ },
5430
+ doc_id: {
5431
+ type: "string",
5432
+ description: "Docstore document id; present for persisted workstream docs. Required for the editable viewer."
5433
+ },
5434
+ pages: {
5435
+ type: "array",
5436
+ items: {
5437
+ type: "object",
5438
+ properties: {
5439
+ page: { type: "number", description: "0-indexed page number" },
5440
+ imageUrl: { type: "string" },
5441
+ width_pt: { type: "number" },
5442
+ height_pt: { type: "number" }
5443
+ },
5444
+ required: ["page", "width_pt", "height_pt"]
5445
+ }
5446
+ },
5447
+ fields: {
5448
+ type: "array",
5449
+ items: {
5450
+ type: "object",
5451
+ properties: {
5452
+ field_key: { type: "string" },
5453
+ label: { type: "string" },
5454
+ value: { type: "string" },
5455
+ page: { type: "number", description: "0-indexed page number" },
5456
+ bbox: {
5457
+ type: "array",
5458
+ items: { type: "number" },
5459
+ description: "[x0,y0,x1,y1] PDF points, origin bottom-left; null if unlocated"
5460
+ },
5461
+ confidence: { type: "number" },
5462
+ confidence_tier: { type: "string", enum: ["green", "amber", "red"] },
5463
+ badge: { type: "string", enum: ["SC", "CN", "AB", "SW"] },
5464
+ state: { type: "string", enum: ["ok", "corrected", "missing", "warn"] },
5465
+ entity_type: { type: "string" },
5466
+ is_primary: { type: "boolean" }
5467
+ },
5468
+ required: ["field_key", "label", "value", "page"]
5469
+ }
5470
+ },
5471
+ page_count: { type: "number" },
5472
+ pages_processed: { type: "number" },
5473
+ summary: {
5474
+ type: "object",
5475
+ description: "Deterministic document summary for the Details tab (display_name, organization, domain, stats, facts, tags). Produced by the extractor \u2014 pass through verbatim.",
5476
+ properties: {
5477
+ display_name: { type: "string" },
5478
+ short_name: { type: "string" },
5479
+ organization: { type: "string" },
5480
+ domain: { type: "string" },
5481
+ domain_group: { type: "string" },
5482
+ tax_year: { type: "string" },
5483
+ crumbs: { type: "array", items: { type: "string" } },
5484
+ tags: { type: "array", items: { type: "string" } },
5485
+ stats: {
5486
+ type: "array",
5487
+ items: {
5488
+ type: "object",
5489
+ properties: {
5490
+ field_key: { type: "string" },
5491
+ label: { type: "string" },
5492
+ value: { type: "string" },
5493
+ caption: { type: "string" }
5494
+ },
5495
+ required: ["field_key", "label", "value"]
5496
+ }
5497
+ },
5498
+ facts: {
5499
+ type: "array",
5500
+ items: {
5501
+ type: "object",
5502
+ properties: {
5503
+ field_key: { type: "string" },
5504
+ label: { type: "string" },
5505
+ value: { type: "string" },
5506
+ badge: { type: "string" }
5507
+ },
5508
+ required: ["field_key", "label", "value"]
5509
+ }
5510
+ }
5511
+ }
5512
+ }
5513
+ },
5514
+ required: ["type"]
5515
+ }
5516
+ };
5290
5517
  var decisionCardSchema = z.object({
5291
5518
  type: z.literal("decision-card"),
5292
5519
  id: z.string().optional(),
@@ -5390,6 +5617,36 @@ var decisionCardTool = {
5390
5617
  required: ["type", "title", "question", "options"]
5391
5618
  }
5392
5619
  };
5620
+ var tabbyAuthSchema = z.object({
5621
+ type: z.literal("tabby-auth"),
5622
+ app: z.string(),
5623
+ url: z.string(),
5624
+ workspace: z.string().optional(),
5625
+ state: z.enum(["pending", "connected"]).optional(),
5626
+ ctaLabel: z.string().optional(),
5627
+ steps: z.array(z.string()).optional(),
5628
+ description: z.string().optional(),
5629
+ iconUrl: z.string().optional()
5630
+ });
5631
+ var tabbyAuthTool = {
5632
+ name: "render_tabby_auth",
5633
+ 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.",
5634
+ input_schema: {
5635
+ type: "object",
5636
+ properties: {
5637
+ type: { type: "string", enum: ["tabby-auth"] },
5638
+ app: { type: "string" },
5639
+ url: { type: "string" },
5640
+ workspace: { type: "string" },
5641
+ state: { type: "string", enum: ["pending", "connected"] },
5642
+ ctaLabel: { type: "string" },
5643
+ steps: { type: "array", items: { type: "string" } },
5644
+ description: { type: "string" },
5645
+ iconUrl: { type: "string" }
5646
+ },
5647
+ required: ["type", "app", "url"]
5648
+ }
5649
+ };
5393
5650
 
5394
5651
  // src/schemas/buildRenderUITool.ts
5395
5652
  function buildRenderUITool(selectedSchemas) {
@@ -5509,7 +5766,9 @@ var schemaRegistry = {
5509
5766
  "integrations-list": { schema: integrationsListSchema, tool: integrationsListTool },
5510
5767
  "pipeline-preview": { schema: pipelinePreviewSchema, tool: pipelinePreviewTool },
5511
5768
  "workflow-stepper": { schema: workflowStepperSchema, tool: workflowStepperTool },
5512
- "decision-card": { schema: decisionCardSchema, tool: decisionCardTool }
5769
+ "document-field-extraction": { schema: documentFieldExtractionSchema, tool: documentFieldExtractionTool },
5770
+ "decision-card": { schema: decisionCardSchema, tool: decisionCardTool },
5771
+ "tabby-auth": { schema: tabbyAuthSchema, tool: tabbyAuthTool }
5513
5772
  };
5514
5773
 
5515
5774
  // src/shared/ColumnSettingsPanel.tsx
@@ -6222,17 +6481,17 @@ function SparklineTableResolver(p) {
6222
6481
  // src/composites/heatmap-table/resolver.tsx
6223
6482
  init_theme();
6224
6483
  init_ThemeContext();
6225
- function heatColor(z60) {
6226
- const clamped = Math.max(-3, Math.min(3, z60));
6484
+ function heatColor(z62) {
6485
+ const clamped = Math.max(-3, Math.min(3, z62));
6227
6486
  const abs = Math.abs(clamped);
6228
6487
  const lightness = 95 - abs * 8;
6229
6488
  const hue = clamped >= 0 ? 142 : 0;
6230
6489
  return `hsl(${hue} 60% ${lightness}%)`;
6231
6490
  }
6232
- function heatTextColor(z60) {
6233
- const abs = Math.abs(z60);
6234
- if (abs > 2) return z60 >= 0 ? "#14532d" : "#7f1d1d";
6235
- if (abs > 1) return z60 >= 0 ? "#166534" : "#991b1b";
6491
+ function heatTextColor(z62) {
6492
+ const abs = Math.abs(z62);
6493
+ if (abs > 2) return z62 >= 0 ? "#14532d" : "#7f1d1d";
6494
+ if (abs > 1) return z62 >= 0 ? "#166534" : "#991b1b";
6236
6495
  return "var(--foreground)";
6237
6496
  }
6238
6497
  var th2 = {
@@ -6866,7 +7125,7 @@ function WaterfallChartResolver(p) {
6866
7125
  ] }) });
6867
7126
  }
6868
7127
  init_ThemeContext();
6869
- var FlowGraph2 = React41.lazy(
7128
+ var FlowGraph2 = React45.lazy(
6870
7129
  () => Promise.resolve().then(() => (init_FlowGraph(), FlowGraph_exports)).then((m) => ({ default: m.FlowGraph }))
6871
7130
  );
6872
7131
  function FlowCanvasRenderer({
@@ -7140,7 +7399,7 @@ function TrialBalanceResolver(p) {
7140
7399
  gDebit += a.debit;
7141
7400
  gCredit += a.credit;
7142
7401
  });
7143
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
7402
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
7144
7403
  /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: 4, style: {
7145
7404
  padding: "8px 12px",
7146
7405
  fontSize: "12px",
@@ -8526,10 +8785,10 @@ function useFullscreen(ref) {
8526
8785
  // src/composites/document-preview/resolver.tsx
8527
8786
  init_theme();
8528
8787
  init_ThemeContext();
8529
- var PdfViewer2 = React41.lazy(
8788
+ var PdfViewer2 = React45.lazy(
8530
8789
  () => Promise.resolve().then(() => (init_PdfViewer(), PdfViewer_exports)).then((m) => ({ default: m.PdfViewer }))
8531
8790
  );
8532
- var ExcelViewer2 = React41.lazy(
8791
+ var ExcelViewer2 = React45.lazy(
8533
8792
  () => Promise.resolve().then(() => (init_ExcelViewer(), ExcelViewer_exports)).then((m) => ({ default: m.ExcelViewer }))
8534
8793
  );
8535
8794
  var highlightColors = {
@@ -9485,7 +9744,7 @@ function EngagementPipelineResolver(p) {
9485
9744
  const color = (_a3 = statusColor2[phase.status]) != null ? _a3 : "#d6d3d1";
9486
9745
  const isCurrent = i === activeIdx;
9487
9746
  const size = isCurrent ? 28 : 20;
9488
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
9747
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
9489
9748
  i > 0 && /* @__PURE__ */ jsx(
9490
9749
  "div",
9491
9750
  {
@@ -11651,7 +11910,7 @@ function FileCard({
11651
11910
  whiteSpace: "nowrap"
11652
11911
  },
11653
11912
  children: [
11654
- metaTokens.map((t, i) => /* @__PURE__ */ jsxs(React41.Fragment, { children: [
11913
+ metaTokens.map((t, i) => /* @__PURE__ */ jsxs(React45.Fragment, { children: [
11655
11914
  i > 0 && /* @__PURE__ */ jsx("span", { style: { color: "#c4c4c4" }, children: "\xB7" }),
11656
11915
  /* @__PURE__ */ jsx("span", { children: t })
11657
11916
  ] }, i)),
@@ -12226,7 +12485,7 @@ function KeyValueListResolver(p) {
12226
12485
  var _a4;
12227
12486
  return sum + ((_a4 = g.items) != null ? _a4 : []).length;
12228
12487
  }, 0);
12229
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12488
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12230
12489
  /* @__PURE__ */ jsxs(
12231
12490
  "div",
12232
12491
  {
@@ -12404,7 +12663,7 @@ function BalanceSheetResolver(p) {
12404
12663
  /* @__PURE__ */ jsxs("tbody", { children: [
12405
12664
  ((_p = p.sections) != null ? _p : []).map((section) => {
12406
12665
  var _a3;
12407
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12666
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12408
12667
  /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan, style: {
12409
12668
  padding: "8px 12px",
12410
12669
  fontSize: "12px",
@@ -12417,7 +12676,7 @@ function BalanceSheetResolver(p) {
12417
12676
  }, children: (_a3 = categoryLabels2[section.category]) != null ? _a3 : section.category }) }),
12418
12677
  section.subsections.map((sub, si) => {
12419
12678
  var _a4;
12420
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12679
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12421
12680
  /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan, style: {
12422
12681
  padding: "6px 10px 6px 24px",
12423
12682
  fontSize: "12px",
@@ -12593,7 +12852,7 @@ function IncomeStatementResolver(p) {
12593
12852
  textAlign: "left",
12594
12853
  whiteSpace: "nowrap"
12595
12854
  }, children: "\xA0" }),
12596
- periods.map((period) => /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12855
+ periods.map((period) => /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12597
12856
  /* @__PURE__ */ jsx("th", { style: {
12598
12857
  fontSize: "11px",
12599
12858
  fontWeight: 500,
@@ -12624,7 +12883,7 @@ function IncomeStatementResolver(p) {
12624
12883
  sections.map((section, si) => {
12625
12884
  var _a3;
12626
12885
  const isSubtotal = section.sectionType === "subtotal";
12627
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12886
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12628
12887
  /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: colCount, style: {
12629
12888
  padding: "8px 12px",
12630
12889
  fontSize: "12px",
@@ -12655,7 +12914,7 @@ function IncomeStatementResolver(p) {
12655
12914
  var _a5;
12656
12915
  const val = (_a5 = amounts[pi]) != null ? _a5 : 0;
12657
12916
  const isNeg = val < 0;
12658
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12917
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12659
12918
  /* @__PURE__ */ jsx("td", { style: {
12660
12919
  padding: "6px 10px",
12661
12920
  fontSize: "13px",
@@ -12690,7 +12949,7 @@ function IncomeStatementResolver(p) {
12690
12949
  var _a3;
12691
12950
  const val = (_a3 = grossProfit[pi]) != null ? _a3 : 0;
12692
12951
  const isNeg = val < 0;
12693
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12952
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12694
12953
  /* @__PURE__ */ jsx("td", { style: {
12695
12954
  padding: "8px 10px",
12696
12955
  fontSize: "12px",
@@ -12725,7 +12984,7 @@ function IncomeStatementResolver(p) {
12725
12984
  var _a3;
12726
12985
  const val = (_a3 = operatingIncome[pi]) != null ? _a3 : 0;
12727
12986
  const isNeg = val < 0;
12728
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
12987
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12729
12988
  /* @__PURE__ */ jsx("td", { style: {
12730
12989
  padding: "8px 10px",
12731
12990
  fontSize: "12px",
@@ -12759,7 +13018,7 @@ function IncomeStatementResolver(p) {
12759
13018
  var _a3;
12760
13019
  const val = (_a3 = netIncome[pi]) != null ? _a3 : 0;
12761
13020
  const isNeg = val < 0;
12762
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
13021
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12763
13022
  /* @__PURE__ */ jsx("td", { style: {
12764
13023
  padding: "10px 10px",
12765
13024
  fontSize: "13px",
@@ -12979,7 +13238,7 @@ function CashFlowStatementResolver(p) {
12979
13238
  /* @__PURE__ */ jsxs("tbody", { children: [
12980
13239
  activities.map((activity, ai) => {
12981
13240
  var _a3, _b2, _c2;
12982
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
13241
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
12983
13242
  ai > 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
12984
13243
  "td",
12985
13244
  {
@@ -17296,6 +17555,8 @@ var STATUS_COLORS3 = {
17296
17555
  done: "#15803d",
17297
17556
  active: "",
17298
17557
  // filled from theme ACCENT at render time
17558
+ running: "",
17559
+ // filled from theme ACCENT at render time (executor in flight)
17299
17560
  review: "#f59e0b",
17300
17561
  pending: "#9ca3af",
17301
17562
  blocked: "#b45309",
@@ -17304,6 +17565,7 @@ var STATUS_COLORS3 = {
17304
17565
  var STATUS_LABELS = {
17305
17566
  done: "Complete",
17306
17567
  active: "In progress",
17568
+ running: "Running",
17307
17569
  review: "In review",
17308
17570
  pending: "Pending",
17309
17571
  blocked: "Blocked",
@@ -17407,6 +17669,26 @@ function IndexDot({ step, index, accent }) {
17407
17669
  if (step.status === "failed") {
17408
17670
  return /* @__PURE__ */ jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: "#dc2626", color: "white" }), children: /* @__PURE__ */ jsx("span", { style: { fontSize: 10 }, children: "!" }) });
17409
17671
  }
17672
+ if (step.status === "running") {
17673
+ return /* @__PURE__ */ jsxs("div", { style: __spreadProps(__spreadValues({}, base), { position: "relative", background: `${accent}1f`, color: accent }), children: [
17674
+ /* @__PURE__ */ jsx(
17675
+ "span",
17676
+ {
17677
+ className: "wfs-anim",
17678
+ "aria-hidden": "true",
17679
+ style: {
17680
+ position: "absolute",
17681
+ inset: 0,
17682
+ borderRadius: "50%",
17683
+ border: `1.5px solid ${accent}33`,
17684
+ borderTopColor: accent,
17685
+ animation: "wfsSpin 0.8s linear infinite"
17686
+ }
17687
+ }
17688
+ ),
17689
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 9 }, children: n })
17690
+ ] });
17691
+ }
17410
17692
  if (step.status === "active") {
17411
17693
  return /* @__PURE__ */ jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: accent, color: "white" }), children: n });
17412
17694
  }
@@ -17415,12 +17697,50 @@ function IndexDot({ step, index, accent }) {
17415
17697
  }
17416
17698
  return /* @__PURE__ */ jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: "#f2f2f2", color: "#9ca3af" }), children: n });
17417
17699
  }
17700
+ function EvalBadge({ step }) {
17701
+ var _a2;
17702
+ const ev = step.eval;
17703
+ if (!ev || ev.judge_ok === false) return null;
17704
+ const score = typeof ev.score === "number" ? ev.score : null;
17705
+ const flags = (_a2 = ev.data_quality_flags) != null ? _a2 : [];
17706
+ const bad = ev.verdict === "bad" || score !== null && score < 0.8;
17707
+ const tip = flags.length > 0 ? flags.map((f) => {
17708
+ var _a3;
17709
+ return `${(_a3 = f.severity) != null ? _a3 : "?"}: ${f.details || f.issue || f.field || "issue"}`;
17710
+ }).join("\n") : ev.reasoning || void 0;
17711
+ const label = score !== null ? score.toFixed(2) : bad ? "flagged" : "ok";
17712
+ return /* @__PURE__ */ jsxs(
17713
+ "span",
17714
+ {
17715
+ title: tip,
17716
+ "data-testid": `workflow-stepper-eval-${step.id}`,
17717
+ style: {
17718
+ display: "inline-flex",
17719
+ alignItems: "center",
17720
+ gap: 3,
17721
+ fontSize: 9,
17722
+ fontWeight: 700,
17723
+ padding: "1px 6px",
17724
+ borderRadius: 9999,
17725
+ background: bad ? "#fff7ed" : "#dcfce7",
17726
+ color: bad ? "#b45309" : "#15803d",
17727
+ whiteSpace: "nowrap",
17728
+ flexShrink: 0
17729
+ },
17730
+ children: [
17731
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: bad ? "\u26A0" : "\u2713" }),
17732
+ label,
17733
+ flags.length > 0 ? ` \xB7 ${flags.length}` : ""
17734
+ ]
17735
+ }
17736
+ );
17737
+ }
17418
17738
  var CARD_MIN = 132;
17419
17739
  var CARD_GAP = 16;
17420
17740
  var AUTO_COMPACT_BELOW = 360;
17421
17741
  function useContainerWidth(ref) {
17422
- const [w, setW] = React41.useState(0);
17423
- React41.useLayoutEffect(() => {
17742
+ const [w, setW] = React45.useState(0);
17743
+ React45.useLayoutEffect(() => {
17424
17744
  const el = ref.current;
17425
17745
  if (!el || typeof ResizeObserver === "undefined") return;
17426
17746
  const ro = new ResizeObserver((entries) => {
@@ -17439,6 +17759,7 @@ var KEYFRAMES = `
17439
17759
  @keyframes wfsLampPulse{0%,100%{box-shadow:0 0 0 0 var(--wfs-accent,#6366f1)73}50%{box-shadow:0 0 0 4px transparent}}
17440
17760
  @keyframes wfsRise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
17441
17761
  @keyframes wfsShimmer{0%{background-position:-200px 0}100%{background-position:calc(200px + 100%) 0}}
17762
+ @keyframes wfsSpin{to{transform:rotate(360deg)}}
17442
17763
  .wfs-rise{animation:wfsRise 0.32s cubic-bezier(0.22,1,0.36,1) both}
17443
17764
  @media (prefers-reduced-motion: reduce){
17444
17765
  .wfs-anim,.wfs-rise,.wfs-shim{animation:none !important}
@@ -17519,17 +17840,17 @@ function WorkflowStepperRenderer({
17519
17840
  const steps = (_a2 = data.steps) != null ? _a2 : [];
17520
17841
  const activeStepId = (_d = (_c = data.active_step) != null ? _c : (_b = steps.find((s) => s.status === "active")) == null ? void 0 : _b.id) != null ? _d : null;
17521
17842
  const interactive = typeof onSelectStep === "function";
17522
- const statusColor3 = (s) => s === "active" ? ACCENT2 : STATUS_COLORS3[s];
17843
+ const statusColor3 = (s) => s === "active" || s === "running" ? ACCENT2 : STATUS_COLORS3[s];
17523
17844
  const doneCount = steps.filter((s) => s.status === "done").length;
17524
- const rootRef = React41.useRef(null);
17845
+ const rootRef = React45.useRef(null);
17525
17846
  const containerW = useContainerWidth(rootRef);
17526
17847
  let resolved = density === "auto" ? "full" : density;
17527
17848
  if (density === "auto" && containerW > 0) {
17528
17849
  const needed = steps.length * CARD_MIN + Math.max(0, steps.length - 1) * CARD_GAP;
17529
17850
  resolved = containerW < AUTO_COMPACT_BELOW || needed > containerW * 1.6 ? "compact" : "full";
17530
17851
  }
17531
- const scrollerRef = React41.useRef(null);
17532
- React41.useEffect(() => {
17852
+ const scrollerRef = React45.useRef(null);
17853
+ React45.useEffect(() => {
17533
17854
  if (resolved !== "full" || loading) return;
17534
17855
  const sc = scrollerRef.current;
17535
17856
  if (!sc) return;
@@ -17540,11 +17861,11 @@ function WorkflowStepperRenderer({
17540
17861
  el.scrollIntoView({ inline: "center", block: "nearest", behavior: "smooth" });
17541
17862
  }
17542
17863
  }, [resolved, loading, selectedStep, activeStepId]);
17543
- const [edges, setEdges] = React41.useState({
17864
+ const [edges, setEdges] = React45.useState({
17544
17865
  left: false,
17545
17866
  right: false
17546
17867
  });
17547
- const updateEdges = React41.useCallback(() => {
17868
+ const updateEdges = React45.useCallback(() => {
17548
17869
  const sc = scrollerRef.current;
17549
17870
  if (!sc) return;
17550
17871
  const max = sc.scrollWidth - sc.clientWidth;
@@ -17553,7 +17874,7 @@ function WorkflowStepperRenderer({
17553
17874
  const right = sl < max - 1;
17554
17875
  setEdges((prev) => prev.left === left && prev.right === right ? prev : { left, right });
17555
17876
  }, []);
17556
- React41.useLayoutEffect(() => {
17877
+ React45.useLayoutEffect(() => {
17557
17878
  if (resolved !== "full" || loading) return;
17558
17879
  updateEdges();
17559
17880
  const sc = scrollerRef.current;
@@ -17609,7 +17930,7 @@ function WorkflowStepperRenderer({
17609
17930
  const reached = s.status !== "pending";
17610
17931
  const clickable = interactive && reached;
17611
17932
  const size = act ? 11 : done ? 9 : 8;
17612
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
17933
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
17613
17934
  i > 0 && /* @__PURE__ */ jsx(
17614
17935
  "span",
17615
17936
  {
@@ -17747,12 +18068,13 @@ function WorkflowStepperRenderer({
17747
18068
  var _a3;
17748
18069
  const isSelected = selectedStep === step.id;
17749
18070
  const isActive = step.status === "active";
18071
+ const isRunning = step.status === "running";
17750
18072
  const reached = step.status !== "pending";
17751
18073
  const clickable = interactive && reached;
17752
18074
  const color = statusColor3(step.status);
17753
18075
  const humans = ((_a3 = step.assignees) != null ? _a3 : []).filter((a) => a.kind === "human");
17754
18076
  const roleCaption = humans.map((h) => h.role).filter(Boolean).slice(0, 2).join(" \xB7 ");
17755
- return /* @__PURE__ */ jsxs(React41.Fragment, { children: [
18077
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
17756
18078
  i > 0 && /* @__PURE__ */ jsx(
17757
18079
  "div",
17758
18080
  {
@@ -17843,36 +18165,41 @@ function WorkflowStepperRenderer({
17843
18165
  }
17844
18166
  }
17845
18167
  ),
17846
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
17847
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
18168
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 4 }, children: [
18169
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, minWidth: 0 }, children: [
17848
18170
  /* @__PURE__ */ jsx(IndexDot, { step, index: i, accent: ACCENT2 }),
17849
18171
  /* @__PURE__ */ jsx(
17850
18172
  "span",
17851
18173
  {
17852
- className: isActive ? "wfs-anim" : void 0,
18174
+ className: isActive || isRunning ? "wfs-anim" : void 0,
17853
18175
  style: {
17854
18176
  width: 6,
17855
18177
  height: 6,
17856
18178
  borderRadius: "50%",
17857
18179
  background: color,
17858
- animation: isActive ? "wfsLampPulse 1.8s ease-in-out infinite" : "none"
18180
+ flexShrink: 0,
18181
+ animation: isActive || isRunning ? "wfsLampPulse 1.8s ease-in-out infinite" : "none"
17859
18182
  }
17860
18183
  }
17861
18184
  )
17862
18185
  ] }),
17863
- /* @__PURE__ */ jsx(
17864
- "span",
17865
- {
17866
- style: {
17867
- fontSize: 9,
17868
- fontWeight: 600,
17869
- letterSpacing: "0.05em",
17870
- textTransform: "uppercase",
17871
- color
17872
- },
17873
- children: STATUS_LABELS[step.status]
17874
- }
17875
- )
18186
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4, minWidth: 0 }, children: [
18187
+ /* @__PURE__ */ jsx(EvalBadge, { step }),
18188
+ /* @__PURE__ */ jsx(
18189
+ "span",
18190
+ {
18191
+ style: {
18192
+ fontSize: 9,
18193
+ fontWeight: 600,
18194
+ letterSpacing: "0.05em",
18195
+ textTransform: "uppercase",
18196
+ color,
18197
+ whiteSpace: "nowrap"
18198
+ },
18199
+ children: STATUS_LABELS[step.status]
18200
+ }
18201
+ )
18202
+ ] })
17876
18203
  ] }),
17877
18204
  /* @__PURE__ */ jsxs("div", { style: { minWidth: 0 }, children: [
17878
18205
  /* @__PURE__ */ jsx(
@@ -18006,97 +18333,1767 @@ function WorkflowStepperResolver(p) {
18006
18333
  ] }) });
18007
18334
  }
18008
18335
  init_ThemeContext();
18009
- var SEVERITY_COLORS = {
18010
- high: { color: "#dc2626", bg: "#fef2f2" },
18011
- medium: { color: "#f59e0b", bg: "#fff7ed" },
18012
- low: { color: "#777777", bg: "#f2f2f2" }
18336
+
18337
+ // src/composites/document-field-extraction/bboxTransform.ts
18338
+ function bboxToRect(bbox2, page, px) {
18339
+ if (!bbox2 || bbox2.length !== 4) return null;
18340
+ const { wPts, hPts } = page;
18341
+ const { wPx, hPx } = px;
18342
+ if (!wPts || !hPts || !wPx || !hPx) return null;
18343
+ const [x0, y0, x1, y1] = bbox2;
18344
+ const sx = wPx / wPts;
18345
+ const sy = hPx / hPts;
18346
+ return {
18347
+ left: x0 * sx,
18348
+ width: (x1 - x0) * sx,
18349
+ // Flip Y: the box's TOP in screen space is the page height minus its upper
18350
+ // PDF-point edge (y1), because PDF y grows upward from the bottom.
18351
+ top: (hPts - y1) * sy,
18352
+ height: (y1 - y0) * sy
18353
+ };
18354
+ }
18355
+
18356
+ // src/composites/document-field-extraction/FieldDetail.tsx
18357
+ init_ThemeContext();
18358
+
18359
+ // src/composites/document-field-extraction/fieldLabels.ts
18360
+ var LABEL_DISPLAY = {
18361
+ "employer identification number": "Employer ID (EIN)",
18362
+ "company or business name": "Company Name",
18363
+ "total revenue": "Total Revenue",
18364
+ "net income": "Net Income",
18365
+ "tax year": "Tax Year",
18366
+ "invoice number": "Invoice Number",
18367
+ "invoice date": "Invoice Date",
18368
+ "total amount due": "Total Amount Due",
18369
+ "vendor name": "Vendor Name",
18370
+ "receipt total": "Receipt Total",
18371
+ "transaction date": "Transaction Date",
18372
+ "merchant name": "Merchant Name"
18013
18373
  };
18014
- var GREEN3 = "#15803d";
18015
- var GREEN_SOFT = "#dcfce7";
18016
- var STACK_BELOW = 380;
18017
- function formatAmount2(amount, currency = "USD") {
18374
+ function prettyLabel(label) {
18375
+ var _a2;
18376
+ return (_a2 = LABEL_DISPLAY[label]) != null ? _a2 : label.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
18377
+ }
18378
+ var TIER_COLORS = {
18379
+ green: "#15803d",
18380
+ amber: "#f59e0b",
18381
+ red: "#dc2626"
18382
+ };
18383
+ var BADGE_TITLE = {
18384
+ SC: "High confidence",
18385
+ CN: "Medium confidence",
18386
+ AB: "Low confidence",
18387
+ SW: "Very low confidence"
18388
+ };
18389
+ var BADGE_STYLE = {
18390
+ SC: { bg: "#dcfce7", fg: "#15803d" },
18391
+ CN: { bg: "#eff6ff", fg: "#0364ff" },
18392
+ // theme-ok (SECONDARY)
18393
+ AB: { bg: "#fff7ed", fg: "#92400e" },
18394
+ SW: { bg: "#fef2f2", fg: "#dc2626" }
18395
+ };
18396
+ var STATE_DOT = {
18397
+ ok: "#15803d",
18398
+ corrected: "#0364ff",
18399
+ // theme-ok (SECONDARY)
18400
+ missing: "#dc2626",
18401
+ warn: "#f59e0b"
18402
+ };
18403
+ function hexToRgba(hex, alpha) {
18404
+ const h = hex.replace("#", "");
18405
+ const r = parseInt(h.slice(0, 2), 16);
18406
+ const g = parseInt(h.slice(2, 4), 16);
18407
+ const b = parseInt(h.slice(4, 6), 16);
18408
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
18409
+ }
18410
+ function badgeStyle(f) {
18018
18411
  var _a2, _b;
18019
- const abs = Math.abs(amount);
18020
- const sign = amount < 0 ? "-" : "";
18021
- let body;
18022
- if (abs >= 1e6) body = `${(abs / 1e6).toFixed(abs >= 1e7 ? 0 : 1)}M`;
18023
- else if (abs >= 1e3) body = `${(abs / 1e3).toFixed(abs >= 1e4 ? 0 : 1)}K`;
18024
- else body = `${abs}`;
18025
- let symbol = "$";
18026
- try {
18027
- const parts = new Intl.NumberFormat("en-US", {
18028
- style: "currency",
18029
- currency,
18030
- maximumFractionDigits: 0
18031
- }).formatToParts(0);
18032
- symbol = (_b = (_a2 = parts.find((p) => p.type === "currency")) == null ? void 0 : _a2.value) != null ? _b : "$";
18033
- } catch (e) {
18034
- symbol = "$";
18035
- }
18036
- return `${sign}${symbol}${body}`;
18412
+ return (_b = BADGE_STYLE[(_a2 = f.badge) != null ? _a2 : ""]) != null ? _b : { bg: "#f6f6f6", fg: "#777777" };
18037
18413
  }
18038
- function useContainerWidth2(ref) {
18039
- const [w, setW] = React41.useState(0);
18040
- React41.useLayoutEffect(() => {
18041
- const el = ref.current;
18042
- if (!el || typeof ResizeObserver === "undefined") return;
18043
- const ro = new ResizeObserver((entries) => {
18044
- var _a2;
18045
- const cr = (_a2 = entries[0]) == null ? void 0 : _a2.contentRect;
18046
- if (cr) setW(cr.width);
18047
- });
18048
- ro.observe(el);
18049
- setW(el.getBoundingClientRect().width);
18050
- return () => ro.disconnect();
18051
- }, [ref]);
18052
- return w;
18414
+ function dotColor2(f) {
18415
+ var _a2, _b;
18416
+ return (_b = STATE_DOT[(_a2 = f.state) != null ? _a2 : "ok"]) != null ? _b : "#15803d";
18053
18417
  }
18054
- var KEYFRAMES2 = `
18055
- @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
18056
- .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
18057
- @media (prefers-reduced-motion: reduce){
18058
- .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
18059
- }`;
18060
- function SparkCheck({ size, color }) {
18061
- return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
18062
- "path",
18063
- {
18064
- d: "M5 13l4 4L19 7",
18065
- stroke: color,
18066
- strokeWidth: 2.5,
18067
- strokeLinecap: "round",
18068
- strokeLinejoin: "round"
18069
- }
18070
- ) });
18418
+ function fieldColor(f, secondary) {
18419
+ var _a2, _b;
18420
+ if (f.state === "corrected") return secondary;
18421
+ return (_b = TIER_COLORS[(_a2 = f.confidence_tier) != null ? _a2 : "amber"]) != null ? _b : TIER_COLORS.amber;
18071
18422
  }
18072
- function FlagPill({ flag }) {
18423
+ function confidenceLabel(f) {
18073
18424
  var _a2;
18074
- const sev = (_a2 = flag.severity) != null ? _a2 : "medium";
18075
- const { color, bg } = SEVERITY_COLORS[sev];
18425
+ if (typeof f.confidence === "number" && !Number.isNaN(f.confidence)) {
18426
+ return `${Math.round(f.confidence * 100)}%`;
18427
+ }
18428
+ return (_a2 = f.badge) != null ? _a2 : "\u2014";
18429
+ }
18430
+ function FieldDetail({
18431
+ field,
18432
+ selected,
18433
+ onSelect,
18434
+ onSave,
18435
+ correctionCount = 0,
18436
+ cardRef
18437
+ }) {
18438
+ var _a2, _b, _c, _d;
18439
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
18440
+ const [editing, setEditing] = React45.useState(false);
18441
+ const [draft, setDraft] = React45.useState("");
18442
+ const [saving, setSaving] = React45.useState(false);
18443
+ const [saveError, setSaveError] = React45.useState(null);
18444
+ const textareaRef = React45.useRef(null);
18445
+ const color = fieldColor(field, SECONDARY2);
18446
+ const corrected = field.state === "corrected";
18447
+ const startEdit = (e) => {
18448
+ e.stopPropagation();
18449
+ setDraft(field.value || "");
18450
+ setSaveError(null);
18451
+ setEditing(true);
18452
+ setTimeout(() => {
18453
+ var _a3, _b2;
18454
+ (_a3 = textareaRef.current) == null ? void 0 : _a3.focus();
18455
+ (_b2 = textareaRef.current) == null ? void 0 : _b2.select();
18456
+ }, 0);
18457
+ };
18458
+ const cancelEdit = (e) => {
18459
+ e.stopPropagation();
18460
+ setEditing(false);
18461
+ setSaveError(null);
18462
+ };
18463
+ const save = async (e) => {
18464
+ var _a3, _b2;
18465
+ e.stopPropagation();
18466
+ if (!onSave || draft === field.value) {
18467
+ setEditing(false);
18468
+ return;
18469
+ }
18470
+ setSaving(true);
18471
+ setSaveError(null);
18472
+ try {
18473
+ await onSave(field.field_key, draft);
18474
+ setEditing(false);
18475
+ } catch (err) {
18476
+ const msg = ((_b2 = (_a3 = err == null ? void 0 : err.response) == null ? void 0 : _a3.data) == null ? void 0 : _b2.detail) || "Save failed. Try again.";
18477
+ setSaveError(msg);
18478
+ } finally {
18479
+ setSaving(false);
18480
+ }
18481
+ };
18482
+ const handleKeyDown = (e) => {
18483
+ if (e.key === "Escape") cancelEdit(e);
18484
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) void save(e);
18485
+ };
18076
18486
  return /* @__PURE__ */ jsxs(
18077
- "span",
18487
+ "div",
18078
18488
  {
18489
+ ref: cardRef,
18490
+ "data-testid": "field-card",
18491
+ "data-field-key": field.field_key,
18492
+ "data-selected": selected ? "true" : "false",
18493
+ role: "button",
18494
+ tabIndex: 0,
18495
+ onClick: () => !editing && onSelect(selected ? null : field.field_key),
18496
+ onKeyDown: (e) => {
18497
+ if (!editing && e.key === "Enter") onSelect(selected ? null : field.field_key);
18498
+ },
18079
18499
  style: {
18080
- display: "inline-flex",
18081
- alignItems: "center",
18082
- gap: 5,
18083
- fontSize: 11,
18084
- fontWeight: 600,
18085
- padding: "3px 9px",
18086
- borderRadius: 9999,
18087
- background: bg,
18088
- color,
18089
- lineHeight: 1.2
18500
+ display: "flex",
18501
+ flexDirection: "column",
18502
+ gap: "4px",
18503
+ padding: "8px 10px",
18504
+ borderRadius: "0.5rem",
18505
+ border: `1px solid ${selected ? color : BORDER4}`,
18506
+ background: selected ? hexToRgba(color, 0.06) : "white",
18507
+ cursor: editing ? "default" : "pointer",
18508
+ transition: "background 0.15s, border-color 0.15s"
18090
18509
  },
18091
18510
  children: [
18092
- /* @__PURE__ */ jsx(
18093
- "span",
18094
- {
18095
- "aria-hidden": "true",
18096
- style: { width: 6, height: 6, borderRadius: "50%", background: color, flexShrink: 0 }
18097
- }
18098
- ),
18099
- flag.field ? `${flag.field}: ${flag.issue}` : flag.issue
18511
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", minWidth: 0 }, children: [
18512
+ /* @__PURE__ */ jsx(
18513
+ "span",
18514
+ {
18515
+ title: (_c = (_b = BADGE_TITLE[(_a2 = field.badge) != null ? _a2 : ""]) != null ? _b : field.badge) != null ? _c : "",
18516
+ style: {
18517
+ fontSize: "10px",
18518
+ fontWeight: 700,
18519
+ padding: "2px 6px",
18520
+ borderRadius: "4px",
18521
+ flexShrink: 0,
18522
+ letterSpacing: "0.02em",
18523
+ minWidth: "34px",
18524
+ textAlign: "center",
18525
+ fontVariantNumeric: "tabular-nums",
18526
+ background: badgeStyle(field).bg,
18527
+ color: badgeStyle(field).fg
18528
+ },
18529
+ children: confidenceLabel(field)
18530
+ }
18531
+ ),
18532
+ /* @__PURE__ */ jsx(
18533
+ "span",
18534
+ {
18535
+ title: prettyLabel(field.label),
18536
+ style: {
18537
+ fontSize: "12.5px",
18538
+ fontWeight: 600,
18539
+ color: "var(--foreground)",
18540
+ flex: 1,
18541
+ minWidth: 0,
18542
+ whiteSpace: "nowrap",
18543
+ overflow: "hidden",
18544
+ textOverflow: "ellipsis"
18545
+ },
18546
+ children: prettyLabel(field.label)
18547
+ }
18548
+ ),
18549
+ field.is_primary && /* @__PURE__ */ jsx(
18550
+ "span",
18551
+ {
18552
+ style: {
18553
+ fontSize: "9px",
18554
+ fontWeight: 600,
18555
+ textTransform: "uppercase",
18556
+ letterSpacing: "0.04em",
18557
+ color: MUTED2,
18558
+ flexShrink: 0
18559
+ },
18560
+ children: "Primary"
18561
+ }
18562
+ ),
18563
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: "11px", color: MUTED2, flexShrink: 0 }, children: [
18564
+ "p.",
18565
+ field.page + 1
18566
+ ] }),
18567
+ !editing && onSave && /* @__PURE__ */ jsx(
18568
+ "button",
18569
+ {
18570
+ type: "button",
18571
+ onClick: startEdit,
18572
+ title: "Edit value",
18573
+ "aria-label": "Edit value",
18574
+ style: {
18575
+ border: `1px solid ${BORDER4}`,
18576
+ borderRadius: "6px",
18577
+ background: "white",
18578
+ cursor: "pointer",
18579
+ padding: "3px 5px",
18580
+ lineHeight: 1,
18581
+ flexShrink: 0,
18582
+ display: "inline-flex",
18583
+ alignItems: "center",
18584
+ justifyContent: "center"
18585
+ },
18586
+ 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: [
18587
+ /* @__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" }),
18588
+ /* @__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" })
18589
+ ] })
18590
+ }
18591
+ )
18592
+ ] }),
18593
+ editing ? /* @__PURE__ */ jsxs("div", { onClick: (e) => e.stopPropagation(), style: { display: "flex", flexDirection: "column", gap: "5px" }, children: [
18594
+ /* @__PURE__ */ jsx(
18595
+ "textarea",
18596
+ {
18597
+ ref: textareaRef,
18598
+ value: draft,
18599
+ onChange: (e) => setDraft(e.target.value),
18600
+ onKeyDown: handleKeyDown,
18601
+ rows: 3,
18602
+ placeholder: "Enter value\u2026",
18603
+ style: {
18604
+ width: "100%",
18605
+ boxSizing: "border-box",
18606
+ resize: "vertical",
18607
+ fontSize: "13px",
18608
+ fontFamily: "var(--font-sans)",
18609
+ color: "var(--foreground)",
18610
+ padding: "6px 8px",
18611
+ borderRadius: "0.4rem",
18612
+ border: `1px solid ${BORDER4}`
18613
+ }
18614
+ }
18615
+ ),
18616
+ saveError && /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: TIER_COLORS.red }, children: saveError }),
18617
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "6px" }, children: [
18618
+ /* @__PURE__ */ jsx(
18619
+ "button",
18620
+ {
18621
+ type: "button",
18622
+ onClick: save,
18623
+ disabled: saving,
18624
+ title: "Save (\u2318\u21B5)",
18625
+ style: {
18626
+ display: "inline-flex",
18627
+ alignItems: "center",
18628
+ gap: "4px",
18629
+ fontSize: "11px",
18630
+ fontWeight: 600,
18631
+ padding: "4px 10px",
18632
+ borderRadius: "0.4rem",
18633
+ border: "none",
18634
+ background: "var(--foreground)",
18635
+ color: "white",
18636
+ cursor: saving ? "default" : "pointer",
18637
+ opacity: saving ? 0.7 : 1
18638
+ },
18639
+ children: saving ? "Saving\u2026" : "Save"
18640
+ }
18641
+ ),
18642
+ /* @__PURE__ */ jsx(
18643
+ "button",
18644
+ {
18645
+ type: "button",
18646
+ onClick: cancelEdit,
18647
+ disabled: saving,
18648
+ title: "Cancel (Esc)",
18649
+ style: {
18650
+ fontSize: "11px",
18651
+ fontWeight: 600,
18652
+ padding: "4px 10px",
18653
+ borderRadius: "0.4rem",
18654
+ border: `1px solid ${BORDER4}`,
18655
+ background: "white",
18656
+ color: MUTED2,
18657
+ cursor: saving ? "default" : "pointer"
18658
+ },
18659
+ children: "Cancel"
18660
+ }
18661
+ )
18662
+ ] })
18663
+ ] }) : corrected ? /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "2px", paddingLeft: "2px" }, children: [
18664
+ field.previous_value != null && field.previous_value !== "" && /* @__PURE__ */ jsx(
18665
+ "span",
18666
+ {
18667
+ style: {
18668
+ fontSize: "11.5px",
18669
+ color: MUTED2,
18670
+ textDecoration: "line-through",
18671
+ fontFamily: "ui-monospace, 'Cascadia Code', monospace",
18672
+ wordBreak: "break-word"
18673
+ },
18674
+ children: field.previous_value
18675
+ }
18676
+ ),
18677
+ /* @__PURE__ */ jsx(
18678
+ "span",
18679
+ {
18680
+ style: {
18681
+ fontSize: "12.5px",
18682
+ fontWeight: 600,
18683
+ color: "var(--foreground)",
18684
+ fontFamily: "ui-monospace, 'Cascadia Code', monospace",
18685
+ wordBreak: "break-word"
18686
+ },
18687
+ children: field.value || "\u2014"
18688
+ }
18689
+ ),
18690
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
18691
+ field.corrected_by && /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: SECONDARY2 }, title: `Corrected by ${field.corrected_by}`, children: field.corrected_by }),
18692
+ correctionCount > 0 && /* @__PURE__ */ jsxs(
18693
+ "span",
18694
+ {
18695
+ style: {
18696
+ fontSize: "10.5px",
18697
+ fontWeight: 600,
18698
+ color: MUTED2,
18699
+ background: PAPER2,
18700
+ borderRadius: "9999px",
18701
+ padding: "1px 7px"
18702
+ },
18703
+ children: [
18704
+ correctionCount,
18705
+ " ",
18706
+ correctionCount === 1 ? "event" : "events"
18707
+ ]
18708
+ }
18709
+ )
18710
+ ] })
18711
+ ] }) : (
18712
+ // Bottom row: monospace value + right-edge validation dot (file explorer).
18713
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", paddingLeft: "2px" }, children: [
18714
+ /* @__PURE__ */ jsx(
18715
+ "span",
18716
+ {
18717
+ style: {
18718
+ fontSize: "12.5px",
18719
+ color: MUTED2,
18720
+ fontFamily: "ui-monospace, 'Cascadia Code', monospace",
18721
+ flex: 1,
18722
+ minWidth: 0,
18723
+ whiteSpace: "nowrap",
18724
+ overflow: "hidden",
18725
+ textOverflow: "ellipsis"
18726
+ },
18727
+ title: field.value || "\u2014",
18728
+ children: field.value || "\u2014"
18729
+ }
18730
+ ),
18731
+ /* @__PURE__ */ jsx(
18732
+ "span",
18733
+ {
18734
+ title: (_d = field.state) != null ? _d : "ok",
18735
+ style: {
18736
+ width: "8px",
18737
+ height: "8px",
18738
+ borderRadius: "9999px",
18739
+ flexShrink: 0,
18740
+ background: dotColor2(field)
18741
+ }
18742
+ }
18743
+ )
18744
+ ] })
18745
+ )
18746
+ ]
18747
+ }
18748
+ );
18749
+ }
18750
+
18751
+ // src/composites/document-field-extraction/FieldDetails.tsx
18752
+ init_ThemeContext();
18753
+ var BADGE_DOT = {
18754
+ // gen-ui semantic dot colors
18755
+ ok: "#15803d",
18756
+ green: "#15803d",
18757
+ warn: "#f59e0b",
18758
+ amber: "#f59e0b",
18759
+ missing: "#dc2626",
18760
+ red: "#dc2626",
18761
+ corrected: "#0364ff"
18762
+ // theme-ok (SECONDARY)
18763
+ };
18764
+ function FieldDetails({
18765
+ summary,
18766
+ fileName,
18767
+ pageCount,
18768
+ pagesProcessed
18769
+ }) {
18770
+ var _a2, _b, _c, _d, _e, _f;
18771
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
18772
+ if (!summary) {
18773
+ return /* @__PURE__ */ jsxs(
18774
+ "div",
18775
+ {
18776
+ style: {
18777
+ height: "100%",
18778
+ display: "flex",
18779
+ flexDirection: "column",
18780
+ alignItems: "center",
18781
+ justifyContent: "center",
18782
+ gap: "6px",
18783
+ color: MUTED2,
18784
+ textAlign: "center",
18785
+ padding: "24px"
18786
+ },
18787
+ children: [
18788
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "26px", lineHeight: 1 }, children: "\u{1F4C4}" }),
18789
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "14px", fontWeight: 600, color: "var(--foreground)" }, children: "No summary yet" }),
18790
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", maxWidth: "280px" }, children: "This document has no extracted summary." })
18791
+ ]
18792
+ }
18793
+ );
18794
+ }
18795
+ const header = buildHeader(summary);
18796
+ const crumb = buildCrumbLine(summary);
18797
+ const facts = buildFacts(summary, fileName, pageCount, pagesProcessed);
18798
+ return /* @__PURE__ */ jsx("div", { style: { height: "100%", overflowY: "auto", paddingRight: "4px" }, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "14px" }, children: [
18799
+ /* @__PURE__ */ jsxs("header", { style: { display: "flex", flexDirection: "column", gap: "3px" }, children: [
18800
+ /* @__PURE__ */ jsx(
18801
+ "h2",
18802
+ {
18803
+ title: header.title,
18804
+ style: {
18805
+ margin: 0,
18806
+ fontFamily: "var(--font-serif)",
18807
+ fontSize: "20px",
18808
+ fontWeight: 400,
18809
+ letterSpacing: "-0.01em",
18810
+ color: "var(--foreground)",
18811
+ overflow: "hidden",
18812
+ textOverflow: "ellipsis",
18813
+ whiteSpace: "nowrap"
18814
+ },
18815
+ children: header.title
18816
+ }
18817
+ ),
18818
+ header.subtitle && /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", color: MUTED2 }, children: header.subtitle })
18819
+ ] }),
18820
+ (summary.domain || summary.display_name || summary.domain_group || ((_b = (_a2 = summary.tags) == null ? void 0 : _a2.length) != null ? _b : 0) > 0) && /* @__PURE__ */ jsxs(
18821
+ "section",
18822
+ {
18823
+ style: {
18824
+ display: "flex",
18825
+ flexDirection: "column",
18826
+ gap: "6px",
18827
+ padding: "12px 14px",
18828
+ borderRadius: "0.75rem",
18829
+ border: `1px solid ${BORDER4}`,
18830
+ background: PAPER2
18831
+ },
18832
+ children: [
18833
+ summary.domain_group && /* @__PURE__ */ jsx(
18834
+ "span",
18835
+ {
18836
+ style: {
18837
+ fontSize: "10px",
18838
+ fontWeight: 600,
18839
+ textTransform: "uppercase",
18840
+ letterSpacing: "0.06em",
18841
+ color: MUTED2
18842
+ },
18843
+ children: summary.domain_group
18844
+ }
18845
+ ),
18846
+ /* @__PURE__ */ jsx(
18847
+ "h3",
18848
+ {
18849
+ style: {
18850
+ margin: 0,
18851
+ fontSize: "14px",
18852
+ fontWeight: 600,
18853
+ color: "var(--foreground)"
18854
+ },
18855
+ children: summary.domain || summary.display_name
18856
+ }
18857
+ ),
18858
+ crumb && /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", color: MUTED2 }, children: crumb }),
18859
+ ((_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(
18860
+ "span",
18861
+ {
18862
+ style: {
18863
+ fontSize: "10px",
18864
+ fontWeight: 600,
18865
+ padding: "2px 8px",
18866
+ borderRadius: "9999px",
18867
+ background: "white",
18868
+ border: `1px solid ${BORDER4}`,
18869
+ color: MUTED2
18870
+ },
18871
+ children: t
18872
+ },
18873
+ t
18874
+ )) })
18875
+ ]
18876
+ }
18877
+ ),
18878
+ ((_f = (_e = summary.stats) == null ? void 0 : _e.length) != null ? _f : 0) > 0 && /* @__PURE__ */ jsx(
18879
+ "div",
18880
+ {
18881
+ style: {
18882
+ display: "grid",
18883
+ gridTemplateColumns: "repeat(auto-fit, minmax(130px, 1fr))",
18884
+ gap: "8px"
18885
+ },
18886
+ children: summary.stats.map((s) => /* @__PURE__ */ jsxs(
18887
+ "div",
18888
+ {
18889
+ style: {
18890
+ display: "flex",
18891
+ flexDirection: "column",
18892
+ gap: "2px",
18893
+ padding: "10px 12px",
18894
+ borderRadius: "0.6rem",
18895
+ border: `1px solid ${BORDER4}`,
18896
+ background: "white"
18897
+ },
18898
+ children: [
18899
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: MUTED2 }, children: s.label }),
18900
+ /* @__PURE__ */ jsx(
18901
+ "span",
18902
+ {
18903
+ title: s.value,
18904
+ style: {
18905
+ fontSize: "15px",
18906
+ fontWeight: 600,
18907
+ color: "var(--foreground)",
18908
+ overflow: "hidden",
18909
+ textOverflow: "ellipsis",
18910
+ whiteSpace: "nowrap"
18911
+ },
18912
+ children: s.value
18913
+ }
18914
+ ),
18915
+ s.caption && /* @__PURE__ */ jsx("span", { style: { fontSize: "10px", color: MUTED2 }, children: s.caption })
18916
+ ]
18917
+ },
18918
+ s.field_key
18919
+ ))
18920
+ }
18921
+ ),
18922
+ facts.length > 0 && /* @__PURE__ */ jsxs("section", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
18923
+ /* @__PURE__ */ jsxs(
18924
+ "div",
18925
+ {
18926
+ style: {
18927
+ display: "flex",
18928
+ alignItems: "center",
18929
+ gap: "6px",
18930
+ fontSize: "11px",
18931
+ fontWeight: 600,
18932
+ textTransform: "uppercase",
18933
+ letterSpacing: "0.04em",
18934
+ color: MUTED2
18935
+ },
18936
+ children: [
18937
+ /* @__PURE__ */ jsx("span", { children: "\u25A4" }),
18938
+ /* @__PURE__ */ jsx("span", { children: "Document details" })
18939
+ ]
18940
+ }
18941
+ ),
18942
+ /* @__PURE__ */ jsx(
18943
+ "dl",
18944
+ {
18945
+ style: {
18946
+ margin: 0,
18947
+ display: "grid",
18948
+ gridTemplateColumns: "minmax(110px, auto) 1fr",
18949
+ rowGap: "6px",
18950
+ columnGap: "14px"
18951
+ },
18952
+ children: facts.map((f) => {
18953
+ var _a3;
18954
+ return /* @__PURE__ */ jsxs(React45.Fragment, { children: [
18955
+ /* @__PURE__ */ jsx("dt", { style: { fontSize: "12px", color: MUTED2 }, children: f.label }),
18956
+ /* @__PURE__ */ jsxs(
18957
+ "dd",
18958
+ {
18959
+ title: typeof f.value === "string" ? f.value : void 0,
18960
+ style: {
18961
+ margin: 0,
18962
+ fontSize: "12px",
18963
+ color: "var(--foreground)",
18964
+ display: "flex",
18965
+ alignItems: "center",
18966
+ gap: "6px",
18967
+ wordBreak: "break-word"
18968
+ },
18969
+ children: [
18970
+ f.badge && /* @__PURE__ */ jsx(
18971
+ "span",
18972
+ {
18973
+ style: {
18974
+ width: "7px",
18975
+ height: "7px",
18976
+ borderRadius: "9999px",
18977
+ flexShrink: 0,
18978
+ background: (_a3 = BADGE_DOT[f.badge]) != null ? _a3 : SECONDARY2
18979
+ }
18980
+ }
18981
+ ),
18982
+ f.value
18983
+ ]
18984
+ }
18985
+ )
18986
+ ] }, f.key);
18987
+ })
18988
+ }
18989
+ )
18990
+ ] })
18991
+ ] }) });
18992
+ }
18993
+ function buildHeader(summary) {
18994
+ const form = [summary.short_name, summary.display_name].filter(Boolean);
18995
+ const title = summary.organization || form.shift() || summary.domain || "Document";
18996
+ const parts = summary.organization ? [...form] : form;
18997
+ if (summary.tax_year) parts.push(`TY ${summary.tax_year}`);
18998
+ return { title, subtitle: parts.join(" \xB7 ") };
18999
+ }
19000
+ function buildCrumbLine(summary) {
19001
+ const parts = [...summary.crumbs || [], summary.short_name].filter(Boolean);
19002
+ if (parts.length > 0) return parts.join(" \xB7 ");
19003
+ return summary.domain && summary.display_name ? summary.display_name : "";
19004
+ }
19005
+ function buildFacts(summary, fileName, pageCount, pagesProcessed) {
19006
+ const rows = [];
19007
+ if (fileName) rows.push({ key: "file", label: "File", value: fileName });
19008
+ if (summary.display_name) {
19009
+ rows.push({ key: "doctype", label: "Document type", value: summary.display_name });
19010
+ }
19011
+ if (summary.tax_year != null && summary.tax_year !== "") {
19012
+ rows.push({ key: "year", label: "Tax year", value: String(summary.tax_year) });
19013
+ }
19014
+ for (const f of summary.facts || []) {
19015
+ rows.push({ key: f.field_key, label: f.label, value: f.value, badge: f.badge });
19016
+ }
19017
+ if (pageCount) {
19018
+ rows.push({
19019
+ key: "pages",
19020
+ label: "Pages processed",
19021
+ value: `${pagesProcessed != null ? pagesProcessed : pageCount} / ${pageCount}`
19022
+ });
19023
+ }
19024
+ return rows;
19025
+ }
19026
+
19027
+ // src/composites/document-field-extraction/FieldAuditLog.tsx
19028
+ init_ThemeContext();
19029
+ function initials(name) {
19030
+ return name.trim().split(/\s+/).slice(0, 2).map((w) => {
19031
+ var _a2;
19032
+ return ((_a2 = w[0]) != null ? _a2 : "").toUpperCase();
19033
+ }).join("");
19034
+ }
19035
+ function formatTs(ts) {
19036
+ if (!ts) return "\u2014";
19037
+ const d = new Date(ts);
19038
+ if (Number.isNaN(d.getTime())) return ts;
19039
+ return d.toLocaleString(void 0, {
19040
+ month: "short",
19041
+ day: "numeric",
19042
+ hour: "2-digit",
19043
+ minute: "2-digit"
19044
+ });
19045
+ }
19046
+ function FieldAuditLog({
19047
+ events = [],
19048
+ loading = false,
19049
+ fields = []
19050
+ }) {
19051
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
19052
+ const fieldLabelMap = React45.useMemo(() => {
19053
+ var _a2;
19054
+ const map = {};
19055
+ for (const f of fields) map[f.field_key] = (_a2 = f.label) != null ? _a2 : f.field_key;
19056
+ return map;
19057
+ }, [fields]);
19058
+ if (loading) {
19059
+ return /* @__PURE__ */ jsx(
19060
+ "div",
19061
+ {
19062
+ style: {
19063
+ flex: 1,
19064
+ display: "flex",
19065
+ alignItems: "center",
19066
+ justifyContent: "center",
19067
+ padding: "32px 20px",
19068
+ fontSize: "13px",
19069
+ color: MUTED2
19070
+ },
19071
+ children: "Loading audit trail\u2026"
19072
+ }
19073
+ );
19074
+ }
19075
+ if (events.length === 0) {
19076
+ return /* @__PURE__ */ jsxs(
19077
+ "div",
19078
+ {
19079
+ style: {
19080
+ flex: 1,
19081
+ display: "flex",
19082
+ flexDirection: "column",
19083
+ alignItems: "center",
19084
+ justifyContent: "center",
19085
+ gap: "6px",
19086
+ padding: "32px 20px",
19087
+ textAlign: "center"
19088
+ },
19089
+ children: [
19090
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "13.5px", fontWeight: 600, color: "var(--foreground)" }, children: "No changes yet" }),
19091
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", color: MUTED2, maxWidth: "240px", lineHeight: 1.5 }, children: "Field corrections will appear here." })
19092
+ ]
19093
+ }
19094
+ );
19095
+ }
19096
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", flex: 1, minHeight: 0, overflow: "hidden" }, children: [
19097
+ /* @__PURE__ */ jsx("div", { style: { padding: "8px 14px 6px", flexShrink: 0 }, children: /* @__PURE__ */ jsxs(
19098
+ "span",
19099
+ {
19100
+ style: {
19101
+ fontSize: "11.5px",
19102
+ fontWeight: 600,
19103
+ color: MUTED2,
19104
+ textTransform: "uppercase",
19105
+ letterSpacing: "0.04em"
19106
+ },
19107
+ children: [
19108
+ events.length,
19109
+ " ",
19110
+ events.length === 1 ? "change" : "changes"
19111
+ ]
19112
+ }
19113
+ ) }),
19114
+ /* @__PURE__ */ jsx("ol", { style: { listStyle: "none", margin: 0, padding: "0 0 16px", overflowY: "auto", flex: 1, minHeight: 0 }, children: events.map((ev) => {
19115
+ var _a2, _b;
19116
+ const rawLabel = (_a2 = fieldLabelMap[ev.field_key]) != null ? _a2 : ev.field_key;
19117
+ const label = prettyLabel(rawLabel);
19118
+ const isAI = ev.actor_type === "system" || ev.event_type === "ai_corrected" || ev.event_type === "ai_extracted";
19119
+ const actor = isAI ? "AI" : ev.actor_name || "Unknown";
19120
+ const eventLabel = isAI ? "Re-extracted" : "Corrected";
19121
+ return /* @__PURE__ */ jsxs(
19122
+ "li",
19123
+ {
19124
+ "data-testid": "audit-row",
19125
+ style: { display: "flex", gap: "10px", padding: "10px 14px", borderBottom: `1px solid ${BORDER4}` },
19126
+ children: [
19127
+ /* @__PURE__ */ jsx(
19128
+ "div",
19129
+ {
19130
+ title: isAI ? "AI extraction" : actor,
19131
+ style: {
19132
+ flexShrink: 0,
19133
+ width: "28px",
19134
+ height: "28px",
19135
+ borderRadius: "50%",
19136
+ background: isAI ? "#dcfce7" : "#eff6ff",
19137
+ color: isAI ? "#15803d" : SECONDARY2,
19138
+ fontSize: "10.5px",
19139
+ fontWeight: 700,
19140
+ display: "flex",
19141
+ alignItems: "center",
19142
+ justifyContent: "center",
19143
+ marginTop: "1px"
19144
+ },
19145
+ children: isAI ? "\u2728" : initials(actor)
19146
+ }
19147
+ ),
19148
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "3px", flex: 1, minWidth: 0 }, children: [
19149
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: "6px", flexWrap: "wrap" }, children: [
19150
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "12.5px", fontWeight: 600, color: isAI ? "#15803d" : "var(--foreground)" }, children: actor }),
19151
+ /* @__PURE__ */ jsx(
19152
+ "span",
19153
+ {
19154
+ style: {
19155
+ fontSize: "10.5px",
19156
+ fontWeight: 600,
19157
+ color: MUTED2,
19158
+ background: PAPER2,
19159
+ borderRadius: "4px",
19160
+ padding: "1px 6px",
19161
+ whiteSpace: "nowrap",
19162
+ flexShrink: 0
19163
+ },
19164
+ children: eventLabel
19165
+ }
19166
+ ),
19167
+ /* @__PURE__ */ jsx(
19168
+ "span",
19169
+ {
19170
+ style: {
19171
+ fontSize: "12px",
19172
+ color: MUTED2,
19173
+ flex: 1,
19174
+ minWidth: 0,
19175
+ whiteSpace: "nowrap",
19176
+ overflow: "hidden",
19177
+ textOverflow: "ellipsis"
19178
+ },
19179
+ children: label
19180
+ }
19181
+ ),
19182
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: MUTED2, flexShrink: 0 }, children: formatTs(ev.created_at) })
19183
+ ] }),
19184
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
19185
+ ev.previous_value != null && /* @__PURE__ */ jsxs(Fragment, { children: [
19186
+ /* @__PURE__ */ jsx(
19187
+ "span",
19188
+ {
19189
+ style: {
19190
+ fontSize: "12px",
19191
+ fontFamily: "ui-monospace, monospace",
19192
+ color: MUTED2,
19193
+ textDecoration: "line-through"
19194
+ },
19195
+ children: ev.previous_value
19196
+ }
19197
+ ),
19198
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: BORDER4 }, children: "\u2192" })
19199
+ ] }),
19200
+ /* @__PURE__ */ jsx(
19201
+ "span",
19202
+ {
19203
+ style: {
19204
+ fontSize: "12px",
19205
+ fontFamily: "ui-monospace, monospace",
19206
+ fontWeight: 600,
19207
+ color: "var(--foreground)"
19208
+ },
19209
+ children: (_b = ev.new_value) != null ? _b : "\u2014"
19210
+ }
19211
+ )
19212
+ ] }),
19213
+ ev.reason && /* @__PURE__ */ jsxs("p", { style: { margin: "2px 0 0", fontSize: "11.5px", color: MUTED2, fontStyle: "italic" }, children: [
19214
+ "\u201C",
19215
+ ev.reason,
19216
+ "\u201D"
19217
+ ] })
19218
+ ] })
19219
+ ]
19220
+ },
19221
+ ev.id
19222
+ );
19223
+ }) })
19224
+ ] });
19225
+ }
19226
+ var TIER_COLORS2 = {
19227
+ green: "#15803d",
19228
+ amber: "#f59e0b",
19229
+ red: "#dc2626"
19230
+ };
19231
+ function fieldColor2(f, secondary) {
19232
+ var _a2, _b;
19233
+ if (f.state === "corrected") return secondary;
19234
+ return (_b = TIER_COLORS2[(_a2 = f.confidence_tier) != null ? _a2 : "amber"]) != null ? _b : TIER_COLORS2.amber;
19235
+ }
19236
+ function hexToRgba2(hex, alpha) {
19237
+ const h = hex.replace("#", "");
19238
+ const r = parseInt(h.slice(0, 2), 16);
19239
+ const g = parseInt(h.slice(2, 4), 16);
19240
+ const b = parseInt(h.slice(4, 6), 16);
19241
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
19242
+ }
19243
+ function PageOverlay({
19244
+ page,
19245
+ fields,
19246
+ selectedKey,
19247
+ onSelect,
19248
+ secondary
19249
+ }) {
19250
+ const { PAPER: PAPER2, MUTED: MUTED2 } = useTheme();
19251
+ const imgRef = React45.useRef(null);
19252
+ const selectedBoxRef = React45.useRef(null);
19253
+ const [px, setPx] = React45.useState(null);
19254
+ React45.useEffect(() => {
19255
+ const el = imgRef.current;
19256
+ if (!el) return;
19257
+ const measure = () => {
19258
+ if (el.clientWidth && el.clientHeight) {
19259
+ setPx({ wPx: el.clientWidth, hPx: el.clientHeight });
19260
+ }
19261
+ };
19262
+ measure();
19263
+ if (typeof ResizeObserver === "undefined") return;
19264
+ const ro = new ResizeObserver(measure);
19265
+ ro.observe(el);
19266
+ return () => ro.disconnect();
19267
+ }, [page.imageUrl]);
19268
+ React45.useEffect(() => {
19269
+ if (!selectedKey) return;
19270
+ if (!fields.some((f) => f.field_key === selectedKey && f.bbox)) return;
19271
+ const el = selectedBoxRef.current;
19272
+ if (el && typeof el.scrollIntoView === "function") {
19273
+ el.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
19274
+ }
19275
+ }, [selectedKey, fields, px]);
19276
+ const pagePts = { wPts: page.width_pt, hPts: page.height_pt };
19277
+ return /* @__PURE__ */ jsxs("div", { style: { position: "relative", width: "100%", lineHeight: 0 }, children: [
19278
+ page.imageUrl ? /* @__PURE__ */ jsx(
19279
+ "img",
19280
+ {
19281
+ ref: imgRef,
19282
+ src: page.imageUrl,
19283
+ alt: `Page ${page.page + 1}`,
19284
+ onLoad: () => {
19285
+ const el = imgRef.current;
19286
+ if (el && el.clientWidth && el.clientHeight) {
19287
+ setPx({ wPx: el.clientWidth, hPx: el.clientHeight });
19288
+ }
19289
+ },
19290
+ style: { display: "block", width: "100%", height: "auto" }
19291
+ }
19292
+ ) : (
19293
+ // No resolved image (host couldn't resolve the raster) — keep the
19294
+ // aspect box so cards still make sense, but show nothing to overlay on.
19295
+ /* @__PURE__ */ jsxs(
19296
+ "div",
19297
+ {
19298
+ style: {
19299
+ width: "100%",
19300
+ aspectRatio: `${page.width_pt} / ${page.height_pt}`,
19301
+ background: PAPER2,
19302
+ display: "flex",
19303
+ alignItems: "center",
19304
+ justifyContent: "center",
19305
+ fontSize: "12px",
19306
+ color: MUTED2,
19307
+ lineHeight: 1.4
19308
+ },
19309
+ children: [
19310
+ "Page ",
19311
+ page.page + 1,
19312
+ " image unavailable"
19313
+ ]
19314
+ }
19315
+ )
19316
+ ),
19317
+ px && page.imageUrl && fields.map((f) => {
19318
+ var _a2;
19319
+ const rect = bboxToRect((_a2 = f.bbox) != null ? _a2 : null, pagePts, px);
19320
+ if (!rect) return null;
19321
+ const color = fieldColor2(f, secondary);
19322
+ const selected = selectedKey === f.field_key;
19323
+ return /* @__PURE__ */ jsx(
19324
+ "div",
19325
+ {
19326
+ ref: selected ? selectedBoxRef : null,
19327
+ "data-testid": "bbox-rect",
19328
+ "data-field-key": f.field_key,
19329
+ "data-selected": selected ? "true" : "false",
19330
+ onClick: () => onSelect(selected ? null : f.field_key),
19331
+ title: `${f.label}: ${f.value}`,
19332
+ style: {
19333
+ position: "absolute",
19334
+ left: `${rect.left}px`,
19335
+ top: `${rect.top}px`,
19336
+ width: `${rect.width}px`,
19337
+ height: `${rect.height}px`,
19338
+ border: `1px solid ${color}`,
19339
+ background: hexToRgba2(color, selected ? 0.28 : 0.12),
19340
+ boxShadow: selected ? `0 0 0 2px ${hexToRgba2(color, 0.5)}` : "none",
19341
+ borderRadius: "2px",
19342
+ cursor: "pointer",
19343
+ transition: "background 0.15s, box-shadow 0.15s"
19344
+ }
19345
+ },
19346
+ f.field_key
19347
+ );
19348
+ })
19349
+ ] });
19350
+ }
19351
+ function ExtractionDetail({
19352
+ pages,
19353
+ orderedFields,
19354
+ fieldsByPage,
19355
+ selectedKey,
19356
+ setSelectedKey,
19357
+ onFieldSave,
19358
+ correctionCounts,
19359
+ tab,
19360
+ setTab,
19361
+ editable,
19362
+ summary,
19363
+ fileName,
19364
+ pageCount,
19365
+ pagesProcessed,
19366
+ auditEvents,
19367
+ auditLoading
19368
+ }) {
19369
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2, SECONDARY: SECONDARY2 } = useTheme();
19370
+ const selectedCardRef = React45.useRef(null);
19371
+ React45.useEffect(() => {
19372
+ if (!selectedKey || tab !== "fields") return;
19373
+ const el = selectedCardRef.current;
19374
+ if (el && typeof el.scrollIntoView === "function") {
19375
+ el.scrollIntoView({ behavior: "smooth", block: "nearest" });
19376
+ }
19377
+ }, [selectedKey, tab]);
19378
+ const tabs = [
19379
+ { key: "details", label: "Details" },
19380
+ { key: "fields", label: "Fields", count: orderedFields.length }
19381
+ ];
19382
+ if (editable) tabs.push({ key: "audit", label: "Audit Trails", count: (auditEvents == null ? void 0 : auditEvents.length) || void 0 });
19383
+ return /* @__PURE__ */ jsxs(
19384
+ "div",
19385
+ {
19386
+ style: {
19387
+ display: "grid",
19388
+ gridTemplateColumns: "minmax(0, 3fr) minmax(260px, 1fr)",
19389
+ gap: "12px",
19390
+ height: "100%",
19391
+ minHeight: 0
19392
+ },
19393
+ children: [
19394
+ /* @__PURE__ */ jsx(
19395
+ "div",
19396
+ {
19397
+ style: {
19398
+ display: "flex",
19399
+ flexDirection: "column",
19400
+ gap: "10px",
19401
+ borderRadius: "0.75rem",
19402
+ border: `1px solid ${BORDER4}`,
19403
+ overflowY: "auto",
19404
+ minHeight: 0
19405
+ },
19406
+ children: pages.map((pg) => /* @__PURE__ */ jsx(
19407
+ PageOverlay,
19408
+ {
19409
+ page: pg,
19410
+ fields: fieldsByPage(pg.page),
19411
+ selectedKey,
19412
+ onSelect: (key) => {
19413
+ setSelectedKey(key);
19414
+ if (key) setTab("fields");
19415
+ },
19416
+ secondary: SECONDARY2
19417
+ },
19418
+ pg.page
19419
+ ))
19420
+ }
19421
+ ),
19422
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", minWidth: 0, minHeight: 0 }, children: [
19423
+ /* @__PURE__ */ jsx(
19424
+ "div",
19425
+ {
19426
+ style: {
19427
+ display: "flex",
19428
+ gap: "16px",
19429
+ borderBottom: `1px solid ${BORDER4}`,
19430
+ flexShrink: 0,
19431
+ marginBottom: "10px"
19432
+ },
19433
+ children: tabs.map((t) => {
19434
+ const active = tab === t.key;
19435
+ return /* @__PURE__ */ jsxs(
19436
+ "button",
19437
+ {
19438
+ type: "button",
19439
+ onClick: () => setTab(t.key),
19440
+ "data-testid": `tab-${t.key}`,
19441
+ style: {
19442
+ appearance: "none",
19443
+ background: "transparent",
19444
+ borderTop: "none",
19445
+ borderLeft: "none",
19446
+ borderRight: "none",
19447
+ borderBottom: `2px solid ${active ? SECONDARY2 : "transparent"}`,
19448
+ padding: "6px 2px",
19449
+ marginBottom: "-1px",
19450
+ cursor: "pointer",
19451
+ fontSize: "13px",
19452
+ fontWeight: 600,
19453
+ color: active ? SECONDARY2 : MUTED2,
19454
+ display: "inline-flex",
19455
+ alignItems: "center",
19456
+ gap: "6px"
19457
+ },
19458
+ children: [
19459
+ t.label,
19460
+ typeof t.count === "number" && /* @__PURE__ */ jsx(
19461
+ "span",
19462
+ {
19463
+ style: {
19464
+ fontSize: "11px",
19465
+ fontWeight: 600,
19466
+ padding: "1px 7px",
19467
+ borderRadius: "9999px",
19468
+ background: active ? "#eff6ff" : PAPER2,
19469
+ color: active ? SECONDARY2 : MUTED2
19470
+ },
19471
+ children: t.count
19472
+ }
19473
+ )
19474
+ ]
19475
+ },
19476
+ t.key
19477
+ );
19478
+ })
19479
+ }
19480
+ ),
19481
+ tab === "details" ? /* @__PURE__ */ jsx(
19482
+ FieldDetails,
19483
+ {
19484
+ summary,
19485
+ fileName,
19486
+ pageCount,
19487
+ pagesProcessed
19488
+ }
19489
+ ) : tab === "audit" ? /* @__PURE__ */ jsx("div", { style: { minHeight: 0, overflowY: "auto" }, children: /* @__PURE__ */ jsx(
19490
+ FieldAuditLog,
19491
+ {
19492
+ events: auditEvents != null ? auditEvents : [],
19493
+ loading: auditLoading != null ? auditLoading : false,
19494
+ fields: orderedFields.map((f) => ({ field_key: f.field_key, label: f.label }))
19495
+ }
19496
+ ) }) : /* @__PURE__ */ jsxs(
19497
+ "div",
19498
+ {
19499
+ style: {
19500
+ display: "flex",
19501
+ flexDirection: "column",
19502
+ minHeight: 0,
19503
+ overflowY: "auto",
19504
+ paddingRight: "4px"
19505
+ },
19506
+ children: [
19507
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: "12px", color: MUTED2, padding: "0 0 8px 2px", flexShrink: 0 }, children: [
19508
+ orderedFields.length,
19509
+ " extracted"
19510
+ ] }),
19511
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: orderedFields.map((f) => {
19512
+ var _a2;
19513
+ const selected = selectedKey === f.field_key;
19514
+ return /* @__PURE__ */ jsx(
19515
+ FieldDetail,
19516
+ {
19517
+ field: f,
19518
+ selected,
19519
+ onSelect: setSelectedKey,
19520
+ onSave: onFieldSave,
19521
+ correctionCount: (_a2 = correctionCounts == null ? void 0 : correctionCounts[f.field_key]) != null ? _a2 : 0,
19522
+ cardRef: selected ? selectedCardRef : void 0
19523
+ },
19524
+ f.field_key
19525
+ );
19526
+ }) })
19527
+ ]
19528
+ }
19529
+ )
19530
+ ] })
19531
+ ]
19532
+ }
19533
+ );
19534
+ }
19535
+ function ExtractionModal({
19536
+ open,
19537
+ onClose,
19538
+ title,
19539
+ children
19540
+ }) {
19541
+ const { BORDER: BORDER4, MUTED: MUTED2 } = useTheme();
19542
+ React45.useEffect(() => {
19543
+ if (!open) return;
19544
+ const onKey = (e) => {
19545
+ if (e.key === "Escape") onClose();
19546
+ };
19547
+ window.addEventListener("keydown", onKey);
19548
+ const prev = document.body.style.overflow;
19549
+ document.body.style.overflow = "hidden";
19550
+ return () => {
19551
+ window.removeEventListener("keydown", onKey);
19552
+ document.body.style.overflow = prev;
19553
+ };
19554
+ }, [open, onClose]);
19555
+ if (!open || typeof document === "undefined") return null;
19556
+ return createPortal(
19557
+ /* @__PURE__ */ jsx(
19558
+ "div",
19559
+ {
19560
+ role: "dialog",
19561
+ "aria-modal": "true",
19562
+ "aria-label": title,
19563
+ onClick: onClose,
19564
+ style: {
19565
+ position: "fixed",
19566
+ inset: 0,
19567
+ zIndex: 2147483e3,
19568
+ background: "rgba(0,0,0,0.5)",
19569
+ display: "flex",
19570
+ alignItems: "center",
19571
+ justifyContent: "center",
19572
+ padding: "4vh 4vw",
19573
+ backdropFilter: "blur(2px)"
19574
+ },
19575
+ children: /* @__PURE__ */ jsxs(
19576
+ "div",
19577
+ {
19578
+ onClick: (e) => e.stopPropagation(),
19579
+ style: {
19580
+ width: "90vw",
19581
+ height: "90vh",
19582
+ background: "white",
19583
+ borderRadius: "0.875rem",
19584
+ border: `1px solid ${BORDER4}`,
19585
+ boxShadow: "0 20px 60px rgba(0,0,0,0.30)",
19586
+ display: "flex",
19587
+ flexDirection: "column",
19588
+ overflow: "hidden"
19589
+ },
19590
+ children: [
19591
+ /* @__PURE__ */ jsxs(
19592
+ "div",
19593
+ {
19594
+ style: {
19595
+ display: "flex",
19596
+ alignItems: "center",
19597
+ gap: "10px",
19598
+ padding: "11px 16px",
19599
+ borderBottom: `1px solid ${BORDER4}`,
19600
+ flexShrink: 0
19601
+ },
19602
+ children: [
19603
+ /* @__PURE__ */ jsx(
19604
+ "span",
19605
+ {
19606
+ style: {
19607
+ flex: 1,
19608
+ minWidth: 0,
19609
+ fontFamily: "var(--font-serif)",
19610
+ fontSize: "16px",
19611
+ fontWeight: 400,
19612
+ letterSpacing: "-0.01em",
19613
+ color: "var(--foreground)",
19614
+ overflow: "hidden",
19615
+ textOverflow: "ellipsis",
19616
+ whiteSpace: "nowrap"
19617
+ },
19618
+ children: title
19619
+ }
19620
+ ),
19621
+ /* @__PURE__ */ jsx(
19622
+ "button",
19623
+ {
19624
+ type: "button",
19625
+ "aria-label": "Close",
19626
+ onClick: onClose,
19627
+ style: {
19628
+ border: `1px solid ${BORDER4}`,
19629
+ borderRadius: "8px",
19630
+ background: "white",
19631
+ cursor: "pointer",
19632
+ padding: "5px 9px",
19633
+ fontSize: "13px",
19634
+ color: MUTED2,
19635
+ lineHeight: 1
19636
+ },
19637
+ children: "\u2715"
19638
+ }
19639
+ )
19640
+ ]
19641
+ }
19642
+ ),
19643
+ /* @__PURE__ */ jsx(
19644
+ "div",
19645
+ {
19646
+ style: {
19647
+ flex: 1,
19648
+ minHeight: 0,
19649
+ overflow: "hidden",
19650
+ display: "flex",
19651
+ flexDirection: "column",
19652
+ padding: "14px 16px"
19653
+ },
19654
+ children
19655
+ }
19656
+ )
19657
+ ]
19658
+ }
19659
+ )
19660
+ }
19661
+ ),
19662
+ document.body
19663
+ );
19664
+ }
19665
+ function DocumentFieldExtractionResolver(p) {
19666
+ var _a2, _b;
19667
+ const { BORDER: BORDER4, MUTED: MUTED2, PAPER: PAPER2 } = useTheme();
19668
+ const [selectedKey, setSelectedKey] = React45.useState(null);
19669
+ const [open, setOpen] = React45.useState(false);
19670
+ const [tab, setTab] = React45.useState("fields");
19671
+ const pages = (_a2 = p.pages) != null ? _a2 : [];
19672
+ const fields = (_b = p.fields) != null ? _b : [];
19673
+ const editable = typeof p.onFieldSave === "function";
19674
+ const onLoadAudit = p.onLoadAudit;
19675
+ React45.useEffect(() => {
19676
+ if (tab === "audit" && onLoadAudit) {
19677
+ onLoadAudit();
19678
+ }
19679
+ }, [tab, onLoadAudit]);
19680
+ const correctionCounts = React45.useMemo(() => {
19681
+ var _a3, _b2;
19682
+ const counts = {};
19683
+ for (const ev of (_a3 = p.auditEvents) != null ? _a3 : []) {
19684
+ const human = ev.actor_type !== "system" && ev.event_type !== "ai_extracted";
19685
+ if (human) counts[ev.field_key] = ((_b2 = counts[ev.field_key]) != null ? _b2 : 0) + 1;
19686
+ }
19687
+ return counts;
19688
+ }, [p.auditEvents]);
19689
+ const orderedFields = [...fields].sort((a, b) => {
19690
+ var _a3, _b2;
19691
+ if (!!a.is_primary !== !!b.is_primary) return a.is_primary ? -1 : 1;
19692
+ return ((_a3 = b.confidence) != null ? _a3 : 0) - ((_b2 = a.confidence) != null ? _b2 : 0);
19693
+ });
19694
+ const fieldsByPage = (pageNo) => fields.filter((f) => f.page === pageNo);
19695
+ const csvCols = [
19696
+ { key: "label", label: "Field" },
19697
+ { key: "value", label: "Value" },
19698
+ { key: "page", label: "Page" },
19699
+ { key: "confidence", label: "Confidence" },
19700
+ { key: "badge", label: "Badge" },
19701
+ { key: "state", label: "State" }
19702
+ ];
19703
+ const csvRows = orderedFields.map((f) => {
19704
+ var _a3, _b2, _c;
19705
+ return {
19706
+ label: f.label,
19707
+ value: f.value,
19708
+ page: f.page + 1,
19709
+ confidence: (_a3 = f.confidence) != null ? _a3 : "",
19710
+ badge: (_b2 = f.badge) != null ? _b2 : "",
19711
+ state: (_c = f.state) != null ? _c : ""
19712
+ };
19713
+ });
19714
+ const title = p.file_name || (p.doc_type ? `${p.doc_type} \u2014 extracted fields` : "Extracted fields");
19715
+ const tierCounts = fields.reduce(
19716
+ (acc, f) => {
19717
+ var _a3;
19718
+ const t = (_a3 = f.confidence_tier) != null ? _a3 : "amber";
19719
+ if (t === "green") acc.high += 1;
19720
+ else if (t === "red") acc.low += 1;
19721
+ else acc.med += 1;
19722
+ return acc;
19723
+ },
19724
+ { high: 0, med: 0, low: 0 }
19725
+ );
19726
+ const chips = [
19727
+ { n: tierCounts.high, label: "high", color: TIER_COLORS2.green },
19728
+ { n: tierCounts.med, label: "medium", color: TIER_COLORS2.amber },
19729
+ { n: tierCounts.low, label: "low", color: TIER_COLORS2.red }
19730
+ ].filter((c) => c.n > 0);
19731
+ const thumb = pages.find((pg) => pg.imageUrl);
19732
+ return /* @__PURE__ */ jsxs(
19733
+ ComponentActions,
19734
+ {
19735
+ filename: "document-fields",
19736
+ onDownloadCSV: () => downloadCSV(csvCols, csvRows, "document-fields"),
19737
+ children: [
19738
+ /* @__PURE__ */ jsxs(
19739
+ "div",
19740
+ {
19741
+ role: "button",
19742
+ tabIndex: 0,
19743
+ onClick: () => setOpen(true),
19744
+ onKeyDown: (e) => {
19745
+ if (e.key === "Enter" || e.key === " ") {
19746
+ e.preventDefault();
19747
+ setOpen(true);
19748
+ }
19749
+ },
19750
+ style: {
19751
+ display: "flex",
19752
+ alignItems: "stretch",
19753
+ gap: "12px",
19754
+ padding: "12px",
19755
+ width: "100%",
19756
+ maxWidth: "440px",
19757
+ borderRadius: "0.75rem",
19758
+ border: `1px solid ${BORDER4}`,
19759
+ background: "white",
19760
+ cursor: "pointer",
19761
+ textAlign: "left",
19762
+ boxShadow: "0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.05)"
19763
+ },
19764
+ children: [
19765
+ /* @__PURE__ */ jsx(
19766
+ "div",
19767
+ {
19768
+ style: {
19769
+ width: "64px",
19770
+ flexShrink: 0,
19771
+ borderRadius: "0.5rem",
19772
+ border: `1px solid ${BORDER4}`,
19773
+ background: PAPER2,
19774
+ overflow: "hidden",
19775
+ display: "flex",
19776
+ alignItems: "center",
19777
+ justifyContent: "center"
19778
+ },
19779
+ children: (thumb == null ? void 0 : thumb.imageUrl) ? /* @__PURE__ */ jsx(
19780
+ "img",
19781
+ {
19782
+ src: thumb.imageUrl,
19783
+ alt: "Document preview",
19784
+ style: { width: "100%", height: "auto", display: "block" }
19785
+ }
19786
+ ) : /* @__PURE__ */ jsx("span", { style: { fontSize: "22px", lineHeight: 1, padding: "16px 0" }, children: "\u{1F4C4}" })
19787
+ }
19788
+ ),
19789
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "6px" }, children: [
19790
+ /* @__PURE__ */ jsx(
19791
+ "p",
19792
+ {
19793
+ style: {
19794
+ fontFamily: "var(--font-serif)",
19795
+ fontSize: "15px",
19796
+ fontWeight: 400,
19797
+ color: "var(--foreground)",
19798
+ letterSpacing: "-0.01em",
19799
+ margin: 0,
19800
+ overflow: "hidden",
19801
+ textOverflow: "ellipsis",
19802
+ whiteSpace: "nowrap"
19803
+ },
19804
+ children: p.file_name || p.doc_type || "Document"
19805
+ }
19806
+ ),
19807
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: "12px", color: MUTED2 }, children: [
19808
+ fields.length,
19809
+ " field",
19810
+ fields.length === 1 ? "" : "s",
19811
+ " extracted \xB7 ",
19812
+ pages.length,
19813
+ " page",
19814
+ pages.length === 1 ? "" : "s"
19815
+ ] }),
19816
+ chips.length > 0 && /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "5px" }, children: chips.map((c) => /* @__PURE__ */ jsxs(
19817
+ "span",
19818
+ {
19819
+ style: {
19820
+ display: "inline-flex",
19821
+ alignItems: "center",
19822
+ gap: "4px",
19823
+ fontSize: "10px",
19824
+ fontWeight: 600,
19825
+ padding: "2px 7px",
19826
+ borderRadius: "9999px",
19827
+ background: hexToRgba2(c.color, 0.12),
19828
+ color: c.color
19829
+ },
19830
+ children: [
19831
+ /* @__PURE__ */ jsx(
19832
+ "span",
19833
+ {
19834
+ style: {
19835
+ width: "6px",
19836
+ height: "6px",
19837
+ borderRadius: "9999px",
19838
+ background: c.color
19839
+ }
19840
+ }
19841
+ ),
19842
+ c.n,
19843
+ " ",
19844
+ c.label
19845
+ ]
19846
+ },
19847
+ c.label
19848
+ )) }),
19849
+ /* @__PURE__ */ jsx(
19850
+ "span",
19851
+ {
19852
+ style: {
19853
+ marginTop: "2px",
19854
+ alignSelf: "flex-start",
19855
+ fontSize: "12px",
19856
+ fontWeight: 600,
19857
+ padding: "6px 12px",
19858
+ borderRadius: "0.5rem",
19859
+ background: "var(--foreground)",
19860
+ color: "white"
19861
+ },
19862
+ children: "View & edit fields"
19863
+ }
19864
+ )
19865
+ ] })
19866
+ ]
19867
+ }
19868
+ ),
19869
+ /* @__PURE__ */ jsx(ExtractionModal, { open, onClose: () => setOpen(false), title, children: /* @__PURE__ */ jsx(
19870
+ ExtractionDetail,
19871
+ {
19872
+ pages,
19873
+ orderedFields,
19874
+ fieldsByPage,
19875
+ selectedKey,
19876
+ setSelectedKey,
19877
+ onFieldSave: p.onFieldSave,
19878
+ correctionCounts,
19879
+ tab,
19880
+ setTab,
19881
+ editable,
19882
+ summary: p.summary,
19883
+ fileName: p.file_name,
19884
+ pageCount: p.page_count,
19885
+ pagesProcessed: p.pages_processed,
19886
+ auditEvents: p.auditEvents,
19887
+ auditLoading: p.auditLoading
19888
+ }
19889
+ ) })
19890
+ ]
19891
+ }
19892
+ );
19893
+ }
19894
+ function DocumentFieldExtractionSkeleton() {
19895
+ const { BORDER: BORDER4, PAPER: PAPER2 } = useTheme();
19896
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
19897
+ /* @__PURE__ */ jsx("style", { children: `
19898
+ @keyframes dfeSkeletonPulse {
19899
+ 0%, 100% { opacity: 1; }
19900
+ 50% { opacity: 0.45; }
19901
+ }
19902
+ ` }),
19903
+ /* @__PURE__ */ jsxs(
19904
+ "div",
19905
+ {
19906
+ "aria-busy": "true",
19907
+ "aria-label": "Loading extracted document",
19908
+ style: {
19909
+ display: "flex",
19910
+ alignItems: "stretch",
19911
+ gap: "12px",
19912
+ padding: "12px",
19913
+ width: "100%",
19914
+ maxWidth: "440px",
19915
+ borderRadius: "0.75rem",
19916
+ border: `1px solid ${BORDER4}`,
19917
+ background: "white",
19918
+ boxShadow: "0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.05)"
19919
+ },
19920
+ children: [
19921
+ /* @__PURE__ */ jsx(
19922
+ "div",
19923
+ {
19924
+ style: {
19925
+ width: "64px",
19926
+ flexShrink: 0,
19927
+ borderRadius: "0.5rem",
19928
+ border: `1px solid ${BORDER4}`,
19929
+ background: PAPER2,
19930
+ minHeight: "82px",
19931
+ animation: "dfeSkeletonPulse 1.6s ease-in-out infinite"
19932
+ }
19933
+ }
19934
+ ),
19935
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "8px", paddingTop: "2px" }, children: [
19936
+ /* @__PURE__ */ jsx(
19937
+ "div",
19938
+ {
19939
+ style: {
19940
+ height: "14px",
19941
+ width: "65%",
19942
+ borderRadius: "4px",
19943
+ background: PAPER2,
19944
+ animation: "dfeSkeletonPulse 1.6s ease-in-out 0.08s infinite"
19945
+ }
19946
+ }
19947
+ ),
19948
+ /* @__PURE__ */ jsx(
19949
+ "div",
19950
+ {
19951
+ style: {
19952
+ height: "11px",
19953
+ width: "45%",
19954
+ borderRadius: "4px",
19955
+ background: PAPER2,
19956
+ animation: "dfeSkeletonPulse 1.6s ease-in-out 0.14s infinite"
19957
+ }
19958
+ }
19959
+ ),
19960
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "5px" }, children: [
19961
+ /* @__PURE__ */ jsx(
19962
+ "div",
19963
+ {
19964
+ style: {
19965
+ height: "18px",
19966
+ width: "66px",
19967
+ borderRadius: "9999px",
19968
+ background: PAPER2,
19969
+ animation: "dfeSkeletonPulse 1.6s ease-in-out 0.2s infinite"
19970
+ }
19971
+ }
19972
+ ),
19973
+ /* @__PURE__ */ jsx(
19974
+ "div",
19975
+ {
19976
+ style: {
19977
+ height: "18px",
19978
+ width: "56px",
19979
+ borderRadius: "9999px",
19980
+ background: PAPER2,
19981
+ animation: "dfeSkeletonPulse 1.6s ease-in-out 0.25s infinite"
19982
+ }
19983
+ }
19984
+ )
19985
+ ] }),
19986
+ /* @__PURE__ */ jsx(
19987
+ "div",
19988
+ {
19989
+ style: {
19990
+ height: "28px",
19991
+ width: "122px",
19992
+ borderRadius: "0.5rem",
19993
+ background: PAPER2,
19994
+ marginTop: "2px",
19995
+ animation: "dfeSkeletonPulse 1.6s ease-in-out 0.3s infinite"
19996
+ }
19997
+ }
19998
+ )
19999
+ ] })
20000
+ ]
20001
+ }
20002
+ )
20003
+ ] });
20004
+ }
20005
+ init_ThemeContext();
20006
+ var SEVERITY_COLORS = {
20007
+ high: { color: "#dc2626", bg: "#fef2f2" },
20008
+ medium: { color: "#f59e0b", bg: "#fff7ed" },
20009
+ low: { color: "#777777", bg: "#f2f2f2" }
20010
+ };
20011
+ var GREEN3 = "#15803d";
20012
+ var GREEN_SOFT = "#dcfce7";
20013
+ var STACK_BELOW = 380;
20014
+ function formatAmount2(amount, currency = "USD") {
20015
+ var _a2, _b;
20016
+ const abs = Math.abs(amount);
20017
+ const sign = amount < 0 ? "-" : "";
20018
+ let body;
20019
+ if (abs >= 1e6) body = `${(abs / 1e6).toFixed(abs >= 1e7 ? 0 : 1)}M`;
20020
+ else if (abs >= 1e3) body = `${(abs / 1e3).toFixed(abs >= 1e4 ? 0 : 1)}K`;
20021
+ else body = `${abs}`;
20022
+ let symbol = "$";
20023
+ try {
20024
+ const parts = new Intl.NumberFormat("en-US", {
20025
+ style: "currency",
20026
+ currency,
20027
+ maximumFractionDigits: 0
20028
+ }).formatToParts(0);
20029
+ symbol = (_b = (_a2 = parts.find((p) => p.type === "currency")) == null ? void 0 : _a2.value) != null ? _b : "$";
20030
+ } catch (e) {
20031
+ symbol = "$";
20032
+ }
20033
+ return `${sign}${symbol}${body}`;
20034
+ }
20035
+ function useContainerWidth2(ref) {
20036
+ const [w, setW] = React45.useState(0);
20037
+ React45.useLayoutEffect(() => {
20038
+ const el = ref.current;
20039
+ if (!el || typeof ResizeObserver === "undefined") return;
20040
+ const ro = new ResizeObserver((entries) => {
20041
+ var _a2;
20042
+ const cr = (_a2 = entries[0]) == null ? void 0 : _a2.contentRect;
20043
+ if (cr) setW(cr.width);
20044
+ });
20045
+ ro.observe(el);
20046
+ setW(el.getBoundingClientRect().width);
20047
+ return () => ro.disconnect();
20048
+ }, [ref]);
20049
+ return w;
20050
+ }
20051
+ var KEYFRAMES2 = `
20052
+ @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
20053
+ .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
20054
+ @media (prefers-reduced-motion: reduce){
20055
+ .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
20056
+ }`;
20057
+ function SparkCheck({ size, color }) {
20058
+ return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
20059
+ "path",
20060
+ {
20061
+ d: "M5 13l4 4L19 7",
20062
+ stroke: color,
20063
+ strokeWidth: 2.5,
20064
+ strokeLinecap: "round",
20065
+ strokeLinejoin: "round"
20066
+ }
20067
+ ) });
20068
+ }
20069
+ function FlagPill({ flag }) {
20070
+ var _a2;
20071
+ const sev = (_a2 = flag.severity) != null ? _a2 : "medium";
20072
+ const { color, bg } = SEVERITY_COLORS[sev];
20073
+ return /* @__PURE__ */ jsxs(
20074
+ "span",
20075
+ {
20076
+ style: {
20077
+ display: "inline-flex",
20078
+ alignItems: "center",
20079
+ gap: 5,
20080
+ fontSize: 11,
20081
+ fontWeight: 600,
20082
+ padding: "3px 9px",
20083
+ borderRadius: 9999,
20084
+ background: bg,
20085
+ color,
20086
+ lineHeight: 1.2
20087
+ },
20088
+ children: [
20089
+ /* @__PURE__ */ jsx(
20090
+ "span",
20091
+ {
20092
+ "aria-hidden": "true",
20093
+ style: { width: 6, height: 6, borderRadius: "50%", background: color, flexShrink: 0 }
20094
+ }
20095
+ ),
20096
+ flag.field ? `${flag.field}: ${flag.issue}` : flag.issue
18100
20097
  ]
18101
20098
  }
18102
20099
  );
@@ -18109,7 +20106,7 @@ function DecisionCardRenderer({
18109
20106
  }) {
18110
20107
  var _a2, _b;
18111
20108
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
18112
- const rootRef = React41.useRef(null);
20109
+ const rootRef = React45.useRef(null);
18113
20110
  const width = useContainerWidth2(rootRef);
18114
20111
  const stacked = width > 0 && width < STACK_BELOW;
18115
20112
  const options = (_a2 = data.options) != null ? _a2 : [];
@@ -18366,8 +20363,8 @@ function DecisionCardResolver(p) {
18366
20363
  const decisionId = (_a2 = p.id) != null ? _a2 : p.title;
18367
20364
  const hostResolved = resolvedDecisions == null ? void 0 : resolvedDecisions[decisionId];
18368
20365
  const initial = (_c = hostResolved != null ? hostResolved : (_b = p.resolved) == null ? void 0 : _b.option) != null ? _c : null;
18369
- const [localResolved, setLocalResolved] = React41.useState(initial);
18370
- React41.useEffect(() => {
20366
+ const [localResolved, setLocalResolved] = React45.useState(initial);
20367
+ React45.useEffect(() => {
18371
20368
  if (hostResolved !== void 0) setLocalResolved(hostResolved);
18372
20369
  }, [hostResolved]);
18373
20370
  const resolved = hostResolved != null ? hostResolved : localResolved;
@@ -18392,6 +20389,317 @@ function DecisionCardResolver(p) {
18392
20389
  }
18393
20390
  ) });
18394
20391
  }
20392
+ init_ThemeContext();
20393
+ var CONNECTED_GREEN3 = "#15803d";
20394
+ var CONNECTED_GREEN_BG = "#dcfce7";
20395
+ var PENDING_AMBER = "#92400e";
20396
+ var PENDING_AMBER_BG = "#fff7ed";
20397
+ var CARD_TITLE = "Authentication required";
20398
+ var TRUST_FOOTER = "Credentials not stored by Adopt";
20399
+ var DEFAULT_STEPS = (app, ctaLabel, connected) => connected ? [
20400
+ `Click ${ctaLabel} below to open ${app} in a new tab.`,
20401
+ "Confirm you are signed in \u2014 re-authenticate if prompted.",
20402
+ "Return here \u2014 the request continues automatically."
20403
+ ] : [
20404
+ `Click ${ctaLabel} below to open the sign-in page.`,
20405
+ `Sign in with your ${app} credentials \u2014 SSO is supported.`,
20406
+ "Return here \u2014 the request resumes automatically."
20407
+ ];
20408
+ function humanizeApp(raw) {
20409
+ const v = raw.trim();
20410
+ if (!v) return v;
20411
+ const looksLikeSlug = /^[a-z0-9]+([_-][a-z0-9]+)*$/.test(v);
20412
+ if (!looksLikeSlug) return v;
20413
+ return v.split(/[_-]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
20414
+ }
20415
+ function ShieldIcon({ color }) {
20416
+ return /* @__PURE__ */ jsxs(
20417
+ "svg",
20418
+ {
20419
+ width: "13",
20420
+ height: "13",
20421
+ viewBox: "0 0 24 24",
20422
+ fill: "none",
20423
+ stroke: color,
20424
+ strokeWidth: "2",
20425
+ strokeLinecap: "round",
20426
+ strokeLinejoin: "round",
20427
+ "aria-hidden": "true",
20428
+ style: { flexShrink: 0 },
20429
+ children: [
20430
+ /* @__PURE__ */ jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }),
20431
+ /* @__PURE__ */ jsx("path", { d: "m9 12 2 2 4-4" })
20432
+ ]
20433
+ }
20434
+ );
20435
+ }
20436
+ function ExternalIcon() {
20437
+ return /* @__PURE__ */ jsxs(
20438
+ "svg",
20439
+ {
20440
+ width: "13",
20441
+ height: "13",
20442
+ viewBox: "0 0 24 24",
20443
+ fill: "none",
20444
+ stroke: "currentColor",
20445
+ strokeWidth: "2",
20446
+ strokeLinecap: "round",
20447
+ strokeLinejoin: "round",
20448
+ "aria-hidden": "true",
20449
+ style: { flexShrink: 0 },
20450
+ children: [
20451
+ /* @__PURE__ */ jsx("path", { d: "M15 3h6v6" }),
20452
+ /* @__PURE__ */ jsx("path", { d: "M10 14 21 3" }),
20453
+ /* @__PURE__ */ jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
20454
+ ]
20455
+ }
20456
+ );
20457
+ }
20458
+ function TabbyAuthResolver(p) {
20459
+ var _a2, _b, _c;
20460
+ const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
20461
+ const [cardHovered, setCardHovered] = useState(false);
20462
+ const [btnHovered, setBtnHovered] = useState(false);
20463
+ const [imgFailed, setImgFailed] = useState(false);
20464
+ const app = humanizeApp(p.app || "the app");
20465
+ const connected = p.state === "connected";
20466
+ const accent = connected ? CONNECTED_GREEN3 : ACCENT2;
20467
+ const ctaLabel = (_a2 = p.ctaLabel) != null ? _a2 : connected ? `Open ${app}` : `Connect ${app}`;
20468
+ const subtitle = p.workspace ? `${app} \xB7 ${p.workspace} workspace` : app;
20469
+ const steps = ((_b = p.steps) == null ? void 0 : _b.length) ? p.steps : DEFAULT_STEPS(app, ctaLabel, connected);
20470
+ 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.`;
20471
+ const iconSrc = p.iconUrl || brandIconUrl(app);
20472
+ const showImg = Boolean(iconSrc) && !imgFailed;
20473
+ const initial = app.charAt(0).toUpperCase();
20474
+ const badge = connected ? { label: "Connected", bg: CONNECTED_GREEN_BG, color: CONNECTED_GREEN3 } : { label: "Pending sign-in", bg: PENDING_AMBER_BG, color: PENDING_AMBER };
20475
+ const sectionPad = "13px 16px";
20476
+ return /* @__PURE__ */ jsx(ComponentActions, { filename: `${app} authentication`, children: /* @__PURE__ */ jsx("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: "10px" }, children: /* @__PURE__ */ jsxs(
20477
+ "div",
20478
+ {
20479
+ onMouseEnter: () => setCardHovered(true),
20480
+ onMouseLeave: () => setCardHovered(false),
20481
+ style: {
20482
+ display: "flex",
20483
+ flexDirection: "row",
20484
+ alignItems: "stretch",
20485
+ borderRadius: "0.75rem",
20486
+ border: `1px solid ${cardHovered ? "#d2d2d2" : BORDER4}`,
20487
+ background: "white",
20488
+ overflow: "hidden",
20489
+ 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)",
20490
+ transition: "box-shadow 0.18s ease, border-color 0.18s ease"
20491
+ },
20492
+ children: [
20493
+ /* @__PURE__ */ jsx("div", { style: { width: "3px", flexShrink: 0, background: accent } }),
20494
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column" }, children: [
20495
+ /* @__PURE__ */ jsxs(
20496
+ "div",
20497
+ {
20498
+ style: {
20499
+ display: "flex",
20500
+ alignItems: "flex-start",
20501
+ gap: "12px",
20502
+ padding: sectionPad
20503
+ },
20504
+ children: [
20505
+ /* @__PURE__ */ jsx(
20506
+ "div",
20507
+ {
20508
+ style: {
20509
+ position: "relative",
20510
+ width: "34px",
20511
+ height: "34px",
20512
+ borderRadius: "9px",
20513
+ flexShrink: 0,
20514
+ display: "flex",
20515
+ alignItems: "center",
20516
+ justifyContent: "center",
20517
+ background: showImg ? "white" : "#fff3ee",
20518
+ boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.06)",
20519
+ overflow: "hidden"
20520
+ },
20521
+ children: showImg ? /* @__PURE__ */ jsx(
20522
+ "img",
20523
+ {
20524
+ src: iconSrc,
20525
+ alt: app,
20526
+ onError: () => setImgFailed(true),
20527
+ style: { width: "22px", height: "22px", objectFit: "contain" }
20528
+ }
20529
+ ) : /* @__PURE__ */ jsx(
20530
+ "span",
20531
+ {
20532
+ style: {
20533
+ fontFamily: "var(--font-serif)",
20534
+ fontSize: "17px",
20535
+ fontWeight: 400,
20536
+ color: ACCENT2,
20537
+ lineHeight: 1
20538
+ },
20539
+ children: initial
20540
+ }
20541
+ )
20542
+ }
20543
+ ),
20544
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "2px" }, children: [
20545
+ /* @__PURE__ */ jsx(
20546
+ "span",
20547
+ {
20548
+ style: {
20549
+ fontFamily: "var(--font-serif)",
20550
+ fontSize: "15px",
20551
+ fontWeight: 400,
20552
+ color: "var(--foreground)",
20553
+ letterSpacing: "-0.01em",
20554
+ lineHeight: 1.2
20555
+ },
20556
+ children: CARD_TITLE
20557
+ }
20558
+ ),
20559
+ /* @__PURE__ */ jsx(
20560
+ "span",
20561
+ {
20562
+ style: {
20563
+ fontSize: "12px",
20564
+ color: MUTED2,
20565
+ whiteSpace: "nowrap",
20566
+ overflow: "hidden",
20567
+ textOverflow: "ellipsis"
20568
+ },
20569
+ children: subtitle
20570
+ }
20571
+ )
20572
+ ] }),
20573
+ /* @__PURE__ */ jsxs(
20574
+ "span",
20575
+ {
20576
+ style: {
20577
+ display: "inline-flex",
20578
+ alignItems: "center",
20579
+ gap: "5px",
20580
+ flexShrink: 0,
20581
+ fontSize: "10.5px",
20582
+ fontWeight: 600,
20583
+ padding: "3px 9px",
20584
+ borderRadius: "9999px",
20585
+ background: badge.bg,
20586
+ color: badge.color,
20587
+ whiteSpace: "nowrap"
20588
+ },
20589
+ children: [
20590
+ /* @__PURE__ */ jsx(
20591
+ "span",
20592
+ {
20593
+ style: {
20594
+ width: "6px",
20595
+ height: "6px",
20596
+ borderRadius: "9999px",
20597
+ background: badge.color
20598
+ }
20599
+ }
20600
+ ),
20601
+ badge.label
20602
+ ]
20603
+ }
20604
+ )
20605
+ ]
20606
+ }
20607
+ ),
20608
+ /* @__PURE__ */ jsxs(
20609
+ "div",
20610
+ {
20611
+ style: {
20612
+ borderTop: `1px solid ${BORDER4}`,
20613
+ padding: sectionPad,
20614
+ display: "flex",
20615
+ flexDirection: "column",
20616
+ gap: "12px"
20617
+ },
20618
+ children: [
20619
+ description && /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12.5px", lineHeight: 1.5, color: "var(--foreground)" }, children: description }),
20620
+ /* @__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: [
20621
+ /* @__PURE__ */ jsx(
20622
+ "span",
20623
+ {
20624
+ style: {
20625
+ flexShrink: 0,
20626
+ width: "18px",
20627
+ height: "18px",
20628
+ borderRadius: "9999px",
20629
+ background: accent,
20630
+ color: "white",
20631
+ fontSize: "10.5px",
20632
+ fontWeight: 600,
20633
+ display: "flex",
20634
+ alignItems: "center",
20635
+ justifyContent: "center",
20636
+ marginTop: "1px"
20637
+ },
20638
+ children: i + 1
20639
+ }
20640
+ ),
20641
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "12.5px", lineHeight: 1.45, color: "var(--foreground)" }, children: step })
20642
+ ] }, i)) })
20643
+ ]
20644
+ }
20645
+ ),
20646
+ /* @__PURE__ */ jsxs(
20647
+ "div",
20648
+ {
20649
+ style: {
20650
+ borderTop: `1px solid ${BORDER4}`,
20651
+ padding: sectionPad,
20652
+ background: "#fbfbfb",
20653
+ display: "flex",
20654
+ alignItems: "center",
20655
+ justifyContent: "space-between",
20656
+ gap: "12px",
20657
+ flexWrap: "wrap"
20658
+ },
20659
+ children: [
20660
+ /* @__PURE__ */ jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: "6px", color: MUTED2, fontSize: "11.5px" }, children: [
20661
+ /* @__PURE__ */ jsx(ShieldIcon, { color: CONNECTED_GREEN3 }),
20662
+ TRUST_FOOTER
20663
+ ] }),
20664
+ /* @__PURE__ */ jsxs(
20665
+ "a",
20666
+ {
20667
+ href: p.url,
20668
+ target: "_blank",
20669
+ rel: "noopener noreferrer",
20670
+ onMouseEnter: () => setBtnHovered(true),
20671
+ onMouseLeave: () => setBtnHovered(false),
20672
+ style: {
20673
+ display: "inline-flex",
20674
+ alignItems: "center",
20675
+ gap: "7px",
20676
+ flexShrink: 0,
20677
+ borderRadius: "8px",
20678
+ padding: "8px 15px",
20679
+ fontSize: "12.5px",
20680
+ fontWeight: 600,
20681
+ textDecoration: "none",
20682
+ whiteSpace: "nowrap",
20683
+ cursor: "pointer",
20684
+ color: "white",
20685
+ border: "1px solid transparent",
20686
+ background: btnHovered ? connected ? "#126a33" : ACCENT_SOFT2 : accent,
20687
+ transition: "background 0.15s ease"
20688
+ },
20689
+ children: [
20690
+ /* @__PURE__ */ jsx(ExternalIcon, {}),
20691
+ ctaLabel
20692
+ ]
20693
+ }
20694
+ )
20695
+ ]
20696
+ }
20697
+ )
20698
+ ] })
20699
+ ]
20700
+ }
20701
+ ) }) });
20702
+ }
18395
20703
  function resolveUI(rawPayload) {
18396
20704
  const payload = coercePayload(rawPayload);
18397
20705
  switch (payload.type) {
@@ -18509,8 +20817,12 @@ function resolveUI(rawPayload) {
18509
20817
  return /* @__PURE__ */ jsx(PipelinePreviewResolver, __spreadValues({}, payload));
18510
20818
  case "workflow-stepper":
18511
20819
  return /* @__PURE__ */ jsx(WorkflowStepperResolver, __spreadValues({}, payload));
20820
+ case "document-field-extraction":
20821
+ return /* @__PURE__ */ jsx(DocumentFieldExtractionResolver, __spreadValues({}, payload));
18512
20822
  case "decision-card":
18513
20823
  return /* @__PURE__ */ jsx(DecisionCardResolver, __spreadValues({}, payload));
20824
+ case "tabby-auth":
20825
+ return /* @__PURE__ */ jsx(TabbyAuthResolver, __spreadValues({}, payload));
18514
20826
  default: {
18515
20827
  return /* @__PURE__ */ jsx(
18516
20828
  "div",
@@ -18891,7 +21203,7 @@ function DocGlyph({ color }) {
18891
21203
  }
18892
21204
  function FileUploadField({ field, value, onChange, disabled, onFileUpload, error, dense }) {
18893
21205
  const { MUTED: MUTED2, ACCENT: ACCENT2, BORDER: BORDER4, PAPER: PAPER2 } = useTheme();
18894
- const keyRef = React41.useRef(0);
21206
+ const keyRef = React45.useRef(0);
18895
21207
  const [entries, setEntries] = useState(() => {
18896
21208
  const arr = Array.isArray(value) ? value : value && typeof value === "object" ? [value] : [];
18897
21209
  return arr.map((item) => {
@@ -18900,11 +21212,11 @@ function FileUploadField({ field, value, onChange, disabled, onFileUpload, error
18900
21212
  return { key: keyRef.current += 1, name: (_b = (_a2 = r.filename) != null ? _a2 : r.name) != null ? _b : "file", size: r.size, status: "done", result: r };
18901
21213
  });
18902
21214
  });
18903
- const entriesRef = React41.useRef(entries);
21215
+ const entriesRef = React45.useRef(entries);
18904
21216
  entriesRef.current = entries;
18905
21217
  const [dragOver, setDragOver] = useState(false);
18906
- const inputRef = React41.useRef(null);
18907
- React41.useEffect(() => {
21218
+ const inputRef = React45.useRef(null);
21219
+ React45.useEffect(() => {
18908
21220
  ensureFileUploadKeyframes();
18909
21221
  }, []);
18910
21222
  const interactive = !disabled;
@@ -19511,7 +21823,7 @@ function FieldRenderer({ field, value, onChange, disabled, error, onFileUpload,
19511
21823
  ] });
19512
21824
  }
19513
21825
  init_ThemeContext();
19514
- var SlotErrorBoundary = class extends React41.Component {
21826
+ var SlotErrorBoundary = class extends React45.Component {
19515
21827
  constructor(props) {
19516
21828
  super(props);
19517
21829
  this.state = { hasError: false };
@@ -20296,7 +22608,7 @@ function BuilderFormResolver({
20296
22608
  }
20297
22609
  }
20298
22610
  function resolveBuilder(payload, callbacks) {
20299
- return React41.createElement(BuilderFormResolver, __spreadValues({
22611
+ return React45.createElement(BuilderFormResolver, __spreadValues({
20300
22612
  builder: payload
20301
22613
  }, callbacks));
20302
22614
  }
@@ -20304,6 +22616,6 @@ function resolveBuilder(payload, callbacks) {
20304
22616
  // src/index.ts
20305
22617
  init_Markdown();
20306
22618
 
20307
- export { ACCENT, ACCENT_SOFT, AgingReportResolver, AlertResolver, AllocationDonutResolver, AreaChartResolver, AuditTrailResolver, BORDER, BUILDER_FIELD_TYPES, BuilderFormResolver, BuilderRecap, CHART_PALETTE, ComparativeBarChartResolver, ComplianceChecklistResolver, ComponentActions, ContextSlot, DEFAULT_INTERACTION, DEFAULT_TOKENS, DataTableResolver, DecisionCardRenderer, DecisionCardResolver, DocumentPreviewResolver, EngagementPipelineResolver, FIELD_REGISTRY, FieldRenderer, FileCard, FitText, FlowCanvasRenderer, FlowCanvasResolver, GenUIInteractionProvider, GenUIRenderer, GenUIThemeProvider, GroupedTableResolver, HeatmapTableResolver, JournalEntryResolver, LegalTestResultResolver, MUTED, Markdown, NUMERIC_CELL, NewsFeedResolver, PAPER, PreviewHost, PreviewModal, ProvenanceChainResolver, ReconciliationViewResolver, SECONDARY, ScreenerTableResolver, SearchResultsResolver, SparklineTableResolver, StackedBreakdownResolver, StatGridResolver, StatusCardResolver, TRUNCATE, TabsPanelResolver, TrialBalanceResolver, VarianceAnalysisResolver, WaterfallChartResolver, WorkflowStepperRenderer, WorkflowStepperResolver, buildRenderUITool, builderBlockSchema, builderFieldSchema, builderSchema, coercePayload, downloadCSV, fileTypeMeta, formatExpiry, isExpirySoon, isPreviewable, previewKindFor, resolveBuilder, resolveUI, schemaRegistry, useBuilderState, useGenUIInteraction, useTheme, validateBuilderPayload, validatePayload };
22619
+ export { ACCENT, ACCENT_SOFT, AgingReportResolver, AlertResolver, AllocationDonutResolver, AreaChartResolver, AuditTrailResolver, BORDER, BUILDER_FIELD_TYPES, BuilderFormResolver, BuilderRecap, CHART_PALETTE, ComparativeBarChartResolver, ComplianceChecklistResolver, ComponentActions, ContextSlot, DEFAULT_INTERACTION, DEFAULT_TOKENS, DataTableResolver, DecisionCardRenderer, DecisionCardResolver, DocumentFieldExtractionResolver, DocumentFieldExtractionSkeleton, DocumentPreviewResolver, EngagementPipelineResolver, FIELD_REGISTRY, FieldAuditLog, FieldDetails, FieldRenderer, FileCard, FitText, FlowCanvasRenderer, FlowCanvasResolver, GenUIInteractionProvider, GenUIRenderer, GenUIThemeProvider, GroupedTableResolver, HeatmapTableResolver, JournalEntryResolver, LegalTestResultResolver, MUTED, Markdown, NUMERIC_CELL, NewsFeedResolver, PAPER, PreviewHost, PreviewModal, ProvenanceChainResolver, ReconciliationViewResolver, SECONDARY, ScreenerTableResolver, SearchResultsResolver, SparklineTableResolver, StackedBreakdownResolver, StatGridResolver, StatusCardResolver, TRUNCATE, TabsPanelResolver, TrialBalanceResolver, VarianceAnalysisResolver, WaterfallChartResolver, WorkflowStepperRenderer, WorkflowStepperResolver, buildRenderUITool, builderBlockSchema, builderFieldSchema, builderSchema, coercePayload, downloadCSV, fileTypeMeta, formatExpiry, isExpirySoon, isPreviewable, previewKindFor, resolveBuilder, resolveUI, schemaRegistry, useBuilderState, useGenUIInteraction, useTheme, validateBuilderPayload, validatePayload };
20308
22620
  //# sourceMappingURL=index.js.map
20309
22621
  //# sourceMappingURL=index.js.map