@adoptai/genui-components 0.1.58 → 0.1.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/builders/BlockForm.d.ts +5 -1
  2. package/dist/builders/BlockForm.d.ts.map +1 -1
  3. package/dist/builders/BuilderForm.d.ts +22 -1
  4. package/dist/builders/BuilderForm.d.ts.map +1 -1
  5. package/dist/builders/index.d.ts +1 -1
  6. package/dist/builders/index.d.ts.map +1 -1
  7. package/dist/composites/decision-card/resolver.cjs +289 -13
  8. package/dist/composites/decision-card/resolver.cjs.map +1 -1
  9. package/dist/composites/decision-card/resolver.d.ts +2 -1
  10. package/dist/composites/decision-card/resolver.d.ts.map +1 -1
  11. package/dist/composites/decision-card/resolver.js +289 -13
  12. package/dist/composites/decision-card/resolver.js.map +1 -1
  13. package/dist/composites/document-field-extraction/resolver.cjs +1920 -0
  14. package/dist/composites/document-field-extraction/resolver.cjs.map +1 -0
  15. package/dist/composites/document-field-extraction/resolver.js +1913 -0
  16. package/dist/composites/document-field-extraction/resolver.js.map +1 -0
  17. package/dist/composites/tabby-auth/resolver.cjs +597 -0
  18. package/dist/composites/tabby-auth/resolver.cjs.map +1 -0
  19. package/dist/composites/tabby-auth/resolver.d.ts +3 -0
  20. package/dist/composites/tabby-auth/resolver.d.ts.map +1 -0
  21. package/dist/composites/tabby-auth/resolver.js +595 -0
  22. package/dist/composites/tabby-auth/resolver.js.map +1 -0
  23. package/dist/composites/workflow-stepper/resolver.cjs +86 -18
  24. package/dist/composites/workflow-stepper/resolver.cjs.map +1 -1
  25. package/dist/composites/workflow-stepper/resolver.d.ts.map +1 -1
  26. package/dist/composites/workflow-stepper/resolver.js +86 -18
  27. package/dist/composites/workflow-stepper/resolver.js.map +1 -1
  28. package/dist/index.cjs +901 -63
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.js +901 -63
  31. package/dist/index.js.map +1 -1
  32. package/dist/renderer.cjs +810 -45
  33. package/dist/renderer.cjs.map +1 -1
  34. package/dist/renderer.js +810 -45
  35. package/dist/renderer.js.map +1 -1
  36. package/dist/resolver.cjs +810 -45
  37. package/dist/resolver.cjs.map +1 -1
  38. package/dist/resolver.d.ts.map +1 -1
  39. package/dist/resolver.js +810 -45
  40. package/dist/resolver.js.map +1 -1
  41. package/dist/schemas/decision-card.d.ts +37 -0
  42. package/dist/schemas/decision-card.d.ts.map +1 -1
  43. package/dist/schemas/index.cjs +113 -8
  44. package/dist/schemas/index.cjs.map +1 -1
  45. package/dist/schemas/index.d.ts +155 -0
  46. package/dist/schemas/index.d.ts.map +1 -1
  47. package/dist/schemas/index.js +113 -8
  48. package/dist/schemas/index.js.map +1 -1
  49. package/dist/schemas/tabby-auth.d.ts +58 -0
  50. package/dist/schemas/tabby-auth.d.ts.map +1 -0
  51. package/dist/schemas/workflow-stepper.d.ts +60 -0
  52. package/dist/schemas/workflow-stepper.d.ts.map +1 -1
  53. package/dist/tool-definitions.json +135 -4
  54. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -5255,7 +5255,32 @@ var workflowStepperSchema = zod.z.object({
5255
5255
  n: zod.z.number().int().positive().optional(),
5256
5256
  title: zod.z.string(),
5257
5257
  sub: zod.z.string().optional(),
5258
- status: zod.z.enum(["done", "active", "review", "pending", "blocked", "failed"]),
5258
+ status: zod.z.enum([
5259
+ "done",
5260
+ "active",
5261
+ "running",
5262
+ "review",
5263
+ "pending",
5264
+ "blocked",
5265
+ "failed"
5266
+ ]),
5267
+ // Optional quality-gate verdict for a step run by an executor (e.g. a
5268
+ // pipeline). Surfaces a subtle trust badge; flags hint at issues a human
5269
+ // should review (the full list lives in the escalation dock).
5270
+ eval: zod.z.object({
5271
+ score: zod.z.number().min(0).max(1).nullable().optional(),
5272
+ verdict: zod.z.enum(["good", "bad"]).optional(),
5273
+ reasoning: zod.z.string().optional(),
5274
+ judge_ok: zod.z.boolean().optional(),
5275
+ data_quality_flags: zod.z.array(
5276
+ zod.z.object({
5277
+ field: zod.z.string().optional(),
5278
+ issue: zod.z.string().optional(),
5279
+ severity: zod.z.enum(["low", "medium", "high"]).optional(),
5280
+ details: zod.z.string().optional()
5281
+ })
5282
+ ).optional()
5283
+ }).optional(),
5259
5284
  assignees: zod.z.array(
5260
5285
  zod.z.object({
5261
5286
  name: zod.z.string(),
@@ -5291,7 +5316,32 @@ var workflowStepperTool = {
5291
5316
  n: { type: "number", description: "Step number; defaults to index + 1" },
5292
5317
  title: { type: "string" },
5293
5318
  sub: { type: "string", description: "Short status caption, e.g. '7 accounts \xB7 2 exceptions'" },
5294
- status: { type: "string", enum: ["done", "active", "review", "pending", "blocked", "failed"] },
5319
+ status: {
5320
+ type: "string",
5321
+ enum: ["done", "active", "running", "review", "pending", "blocked", "failed"]
5322
+ },
5323
+ eval: {
5324
+ type: "object",
5325
+ description: "Optional quality-gate verdict for an executor-run step.",
5326
+ properties: {
5327
+ score: { type: "number" },
5328
+ verdict: { type: "string", enum: ["good", "bad"] },
5329
+ reasoning: { type: "string" },
5330
+ judge_ok: { type: "boolean" },
5331
+ data_quality_flags: {
5332
+ type: "array",
5333
+ items: {
5334
+ type: "object",
5335
+ properties: {
5336
+ field: { type: "string" },
5337
+ issue: { type: "string" },
5338
+ severity: { type: "string", enum: ["low", "medium", "high"] },
5339
+ details: { type: "string" }
5340
+ }
5341
+ }
5342
+ }
5343
+ }
5344
+ },
5295
5345
  assignees: {
5296
5346
  type: "array",
5297
5347
  maxItems: 6,
@@ -5513,7 +5563,14 @@ var decisionCardSchema = zod.z.object({
5513
5563
  zod.z.object({
5514
5564
  id: zod.z.string().optional(),
5515
5565
  label: zod.z.string(),
5516
- recommended: zod.z.boolean().optional()
5566
+ recommended: zod.z.boolean().optional(),
5567
+ value: zod.z.number().optional(),
5568
+ adjust: zod.z.object({
5569
+ min: zod.z.number(),
5570
+ max: zod.z.number(),
5571
+ step: zod.z.number().optional(),
5572
+ unit: zod.z.string().optional()
5573
+ }).optional()
5517
5574
  })
5518
5575
  ).min(1).max(5),
5519
5576
  source: zod.z.object({
@@ -5521,7 +5578,8 @@ var decisionCardSchema = zod.z.object({
5521
5578
  url: zod.z.string().optional()
5522
5579
  }).optional(),
5523
5580
  resolved: zod.z.object({
5524
- option: zod.z.string()
5581
+ option: zod.z.string(),
5582
+ value: zod.z.number().optional()
5525
5583
  }).optional()
5526
5584
  });
5527
5585
  var decisionCardTool = {
@@ -5564,13 +5622,28 @@ var decisionCardTool = {
5564
5622
  type: "array",
5565
5623
  minItems: 1,
5566
5624
  maxItems: 5,
5567
- description: "Mutually-exclusive resolution choices; mark one `recommended` to make it primary",
5625
+ description: "Mutually-exclusive resolution choices; mark one `recommended` to make it primary. An option that carries a numeric figure the user may want to tune (e.g. 'Book reserve' at 50 units) should set `value` (your suggested figure) and `adjust` ({min,max[,step,unit]}) \u2014 the card then lets the user fine-tune the number within that range before confirming.",
5568
5626
  items: {
5569
5627
  type: "object",
5570
5628
  properties: {
5571
5629
  id: { type: "string" },
5572
5630
  label: { type: "string" },
5573
- recommended: { type: "boolean" }
5631
+ recommended: { type: "boolean" },
5632
+ value: {
5633
+ type: "number",
5634
+ description: "Suggested numeric figure for this option (the starting point of the adjuster)"
5635
+ },
5636
+ adjust: {
5637
+ type: "object",
5638
+ description: "Allow the user to tune `value` within this inclusive range before resolving",
5639
+ properties: {
5640
+ min: { type: "number" },
5641
+ max: { type: "number" },
5642
+ step: { type: "number", description: "Increment granularity; defaults to a sensible step for the range" },
5643
+ unit: { type: "string", description: "Short unit suffix shown after the number, e.g. 'units', '%', 'hrs'" }
5644
+ },
5645
+ required: ["min", "max"]
5646
+ }
5574
5647
  },
5575
5648
  required: ["label"]
5576
5649
  }
@@ -5587,7 +5660,8 @@ var decisionCardTool = {
5587
5660
  type: "object",
5588
5661
  description: "Pre-resolved state for transcript replay",
5589
5662
  properties: {
5590
- option: { type: "string" }
5663
+ option: { type: "string" },
5664
+ value: { type: "number", description: "Adjusted figure the user confirmed, when the option was adjustable" }
5591
5665
  },
5592
5666
  required: ["option"]
5593
5667
  }
@@ -5595,6 +5669,36 @@ var decisionCardTool = {
5595
5669
  required: ["type", "title", "question", "options"]
5596
5670
  }
5597
5671
  };
5672
+ var tabbyAuthSchema = zod.z.object({
5673
+ type: zod.z.literal("tabby-auth"),
5674
+ app: zod.z.string(),
5675
+ url: zod.z.string(),
5676
+ workspace: zod.z.string().optional(),
5677
+ state: zod.z.enum(["pending", "connected"]).optional(),
5678
+ ctaLabel: zod.z.string().optional(),
5679
+ steps: zod.z.array(zod.z.string()).optional(),
5680
+ description: zod.z.string().optional(),
5681
+ iconUrl: zod.z.string().optional()
5682
+ });
5683
+ var tabbyAuthTool = {
5684
+ name: "render_tabby_auth",
5685
+ 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.",
5686
+ input_schema: {
5687
+ type: "object",
5688
+ properties: {
5689
+ type: { type: "string", enum: ["tabby-auth"] },
5690
+ app: { type: "string" },
5691
+ url: { type: "string" },
5692
+ workspace: { type: "string" },
5693
+ state: { type: "string", enum: ["pending", "connected"] },
5694
+ ctaLabel: { type: "string" },
5695
+ steps: { type: "array", items: { type: "string" } },
5696
+ description: { type: "string" },
5697
+ iconUrl: { type: "string" }
5698
+ },
5699
+ required: ["type", "app", "url"]
5700
+ }
5701
+ };
5598
5702
 
5599
5703
  // src/schemas/buildRenderUITool.ts
5600
5704
  function buildRenderUITool(selectedSchemas) {
@@ -5715,7 +5819,8 @@ var schemaRegistry = {
5715
5819
  "pipeline-preview": { schema: pipelinePreviewSchema, tool: pipelinePreviewTool },
5716
5820
  "workflow-stepper": { schema: workflowStepperSchema, tool: workflowStepperTool },
5717
5821
  "document-field-extraction": { schema: documentFieldExtractionSchema, tool: documentFieldExtractionTool },
5718
- "decision-card": { schema: decisionCardSchema, tool: decisionCardTool }
5822
+ "decision-card": { schema: decisionCardSchema, tool: decisionCardTool },
5823
+ "tabby-auth": { schema: tabbyAuthSchema, tool: tabbyAuthTool }
5719
5824
  };
5720
5825
 
5721
5826
  // src/shared/ColumnSettingsPanel.tsx
@@ -6428,17 +6533,17 @@ function SparklineTableResolver(p) {
6428
6533
  // src/composites/heatmap-table/resolver.tsx
6429
6534
  init_theme();
6430
6535
  init_ThemeContext();
6431
- function heatColor(z61) {
6432
- const clamped = Math.max(-3, Math.min(3, z61));
6536
+ function heatColor(z62) {
6537
+ const clamped = Math.max(-3, Math.min(3, z62));
6433
6538
  const abs = Math.abs(clamped);
6434
6539
  const lightness = 95 - abs * 8;
6435
6540
  const hue = clamped >= 0 ? 142 : 0;
6436
6541
  return `hsl(${hue} 60% ${lightness}%)`;
6437
6542
  }
6438
- function heatTextColor(z61) {
6439
- const abs = Math.abs(z61);
6440
- if (abs > 2) return z61 >= 0 ? "#14532d" : "#7f1d1d";
6441
- if (abs > 1) return z61 >= 0 ? "#166534" : "#991b1b";
6543
+ function heatTextColor(z62) {
6544
+ const abs = Math.abs(z62);
6545
+ if (abs > 2) return z62 >= 0 ? "#14532d" : "#7f1d1d";
6546
+ if (abs > 1) return z62 >= 0 ? "#166534" : "#991b1b";
6442
6547
  return "var(--foreground)";
6443
6548
  }
6444
6549
  var th2 = {
@@ -17502,6 +17607,8 @@ var STATUS_COLORS3 = {
17502
17607
  done: "#15803d",
17503
17608
  active: "",
17504
17609
  // filled from theme ACCENT at render time
17610
+ running: "",
17611
+ // filled from theme ACCENT at render time (executor in flight)
17505
17612
  review: "#f59e0b",
17506
17613
  pending: "#9ca3af",
17507
17614
  blocked: "#b45309",
@@ -17510,6 +17617,7 @@ var STATUS_COLORS3 = {
17510
17617
  var STATUS_LABELS = {
17511
17618
  done: "Complete",
17512
17619
  active: "In progress",
17620
+ running: "Running",
17513
17621
  review: "In review",
17514
17622
  pending: "Pending",
17515
17623
  blocked: "Blocked",
@@ -17613,6 +17721,26 @@ function IndexDot({ step, index, accent }) {
17613
17721
  if (step.status === "failed") {
17614
17722
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: "#dc2626", color: "white" }), children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 10 }, children: "!" }) });
17615
17723
  }
17724
+ if (step.status === "running") {
17725
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: __spreadProps(__spreadValues({}, base), { position: "relative", background: `${accent}1f`, color: accent }), children: [
17726
+ /* @__PURE__ */ jsxRuntime.jsx(
17727
+ "span",
17728
+ {
17729
+ className: "wfs-anim",
17730
+ "aria-hidden": "true",
17731
+ style: {
17732
+ position: "absolute",
17733
+ inset: 0,
17734
+ borderRadius: "50%",
17735
+ border: `1.5px solid ${accent}33`,
17736
+ borderTopColor: accent,
17737
+ animation: "wfsSpin 0.8s linear infinite"
17738
+ }
17739
+ }
17740
+ ),
17741
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 9 }, children: n })
17742
+ ] });
17743
+ }
17616
17744
  if (step.status === "active") {
17617
17745
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: accent, color: "white" }), children: n });
17618
17746
  }
@@ -17621,6 +17749,44 @@ function IndexDot({ step, index, accent }) {
17621
17749
  }
17622
17750
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style: __spreadProps(__spreadValues({}, base), { background: "#f2f2f2", color: "#9ca3af" }), children: n });
17623
17751
  }
17752
+ function EvalBadge({ step }) {
17753
+ var _a2;
17754
+ const ev = step.eval;
17755
+ if (!ev || ev.judge_ok === false) return null;
17756
+ const score = typeof ev.score === "number" ? ev.score : null;
17757
+ const flags = (_a2 = ev.data_quality_flags) != null ? _a2 : [];
17758
+ const bad = ev.verdict === "bad" || score !== null && score < 0.8;
17759
+ const tip = flags.length > 0 ? flags.map((f) => {
17760
+ var _a3;
17761
+ return `${(_a3 = f.severity) != null ? _a3 : "?"}: ${f.details || f.issue || f.field || "issue"}`;
17762
+ }).join("\n") : ev.reasoning || void 0;
17763
+ const label = score !== null ? score.toFixed(2) : bad ? "flagged" : "ok";
17764
+ return /* @__PURE__ */ jsxRuntime.jsxs(
17765
+ "span",
17766
+ {
17767
+ title: tip,
17768
+ "data-testid": `workflow-stepper-eval-${step.id}`,
17769
+ style: {
17770
+ display: "inline-flex",
17771
+ alignItems: "center",
17772
+ gap: 3,
17773
+ fontSize: 9,
17774
+ fontWeight: 700,
17775
+ padding: "1px 6px",
17776
+ borderRadius: 9999,
17777
+ background: bad ? "#fff7ed" : "#dcfce7",
17778
+ color: bad ? "#b45309" : "#15803d",
17779
+ whiteSpace: "nowrap",
17780
+ flexShrink: 0
17781
+ },
17782
+ children: [
17783
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: bad ? "\u26A0" : "\u2713" }),
17784
+ label,
17785
+ flags.length > 0 ? ` \xB7 ${flags.length}` : ""
17786
+ ]
17787
+ }
17788
+ );
17789
+ }
17624
17790
  var CARD_MIN = 132;
17625
17791
  var CARD_GAP = 16;
17626
17792
  var AUTO_COMPACT_BELOW = 360;
@@ -17645,6 +17811,7 @@ var KEYFRAMES = `
17645
17811
  @keyframes wfsLampPulse{0%,100%{box-shadow:0 0 0 0 var(--wfs-accent,#6366f1)73}50%{box-shadow:0 0 0 4px transparent}}
17646
17812
  @keyframes wfsRise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
17647
17813
  @keyframes wfsShimmer{0%{background-position:-200px 0}100%{background-position:calc(200px + 100%) 0}}
17814
+ @keyframes wfsSpin{to{transform:rotate(360deg)}}
17648
17815
  .wfs-rise{animation:wfsRise 0.32s cubic-bezier(0.22,1,0.36,1) both}
17649
17816
  @media (prefers-reduced-motion: reduce){
17650
17817
  .wfs-anim,.wfs-rise,.wfs-shim{animation:none !important}
@@ -17725,7 +17892,7 @@ function WorkflowStepperRenderer({
17725
17892
  const steps = (_a2 = data.steps) != null ? _a2 : [];
17726
17893
  const activeStepId = (_d = (_c = data.active_step) != null ? _c : (_b = steps.find((s) => s.status === "active")) == null ? void 0 : _b.id) != null ? _d : null;
17727
17894
  const interactive = typeof onSelectStep === "function";
17728
- const statusColor3 = (s) => s === "active" ? ACCENT2 : STATUS_COLORS3[s];
17895
+ const statusColor3 = (s) => s === "active" || s === "running" ? ACCENT2 : STATUS_COLORS3[s];
17729
17896
  const doneCount = steps.filter((s) => s.status === "done").length;
17730
17897
  const rootRef = React45__default.default.useRef(null);
17731
17898
  const containerW = useContainerWidth(rootRef);
@@ -17953,6 +18120,7 @@ function WorkflowStepperRenderer({
17953
18120
  var _a3;
17954
18121
  const isSelected = selectedStep === step.id;
17955
18122
  const isActive = step.status === "active";
18123
+ const isRunning = step.status === "running";
17956
18124
  const reached = step.status !== "pending";
17957
18125
  const clickable = interactive && reached;
17958
18126
  const color = statusColor3(step.status);
@@ -18049,36 +18217,41 @@ function WorkflowStepperRenderer({
18049
18217
  }
18050
18218
  }
18051
18219
  ),
18052
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
18053
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
18220
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 4 }, children: [
18221
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, minWidth: 0 }, children: [
18054
18222
  /* @__PURE__ */ jsxRuntime.jsx(IndexDot, { step, index: i, accent: ACCENT2 }),
18055
18223
  /* @__PURE__ */ jsxRuntime.jsx(
18056
18224
  "span",
18057
18225
  {
18058
- className: isActive ? "wfs-anim" : void 0,
18226
+ className: isActive || isRunning ? "wfs-anim" : void 0,
18059
18227
  style: {
18060
18228
  width: 6,
18061
18229
  height: 6,
18062
18230
  borderRadius: "50%",
18063
18231
  background: color,
18064
- animation: isActive ? "wfsLampPulse 1.8s ease-in-out infinite" : "none"
18232
+ flexShrink: 0,
18233
+ animation: isActive || isRunning ? "wfsLampPulse 1.8s ease-in-out infinite" : "none"
18065
18234
  }
18066
18235
  }
18067
18236
  )
18068
18237
  ] }),
18069
- /* @__PURE__ */ jsxRuntime.jsx(
18070
- "span",
18071
- {
18072
- style: {
18073
- fontSize: 9,
18074
- fontWeight: 600,
18075
- letterSpacing: "0.05em",
18076
- textTransform: "uppercase",
18077
- color
18078
- },
18079
- children: STATUS_LABELS[step.status]
18080
- }
18081
- )
18238
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4, minWidth: 0 }, children: [
18239
+ /* @__PURE__ */ jsxRuntime.jsx(EvalBadge, { step }),
18240
+ /* @__PURE__ */ jsxRuntime.jsx(
18241
+ "span",
18242
+ {
18243
+ style: {
18244
+ fontSize: 9,
18245
+ fontWeight: 600,
18246
+ letterSpacing: "0.05em",
18247
+ textTransform: "uppercase",
18248
+ color,
18249
+ whiteSpace: "nowrap"
18250
+ },
18251
+ children: STATUS_LABELS[step.status]
18252
+ }
18253
+ )
18254
+ ] })
18082
18255
  ] }),
18083
18256
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { minWidth: 0 }, children: [
18084
18257
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -18268,12 +18441,14 @@ var BADGE_TITLE = {
18268
18441
  var BADGE_STYLE = {
18269
18442
  SC: { bg: "#dcfce7", fg: "#15803d" },
18270
18443
  CN: { bg: "#eff6ff", fg: "#0364ff" },
18444
+ // theme-ok (SECONDARY)
18271
18445
  AB: { bg: "#fff7ed", fg: "#92400e" },
18272
18446
  SW: { bg: "#fef2f2", fg: "#dc2626" }
18273
18447
  };
18274
18448
  var STATE_DOT = {
18275
18449
  ok: "#15803d",
18276
18450
  corrected: "#0364ff",
18451
+ // theme-ok (SECONDARY)
18277
18452
  missing: "#dc2626",
18278
18453
  warn: "#f59e0b"
18279
18454
  };
@@ -18636,6 +18811,7 @@ var BADGE_DOT = {
18636
18811
  missing: "#dc2626",
18637
18812
  red: "#dc2626",
18638
18813
  corrected: "#0364ff"
18814
+ // theme-ok (SECONDARY)
18639
18815
  };
18640
18816
  function FieldDetails({
18641
18817
  summary,
@@ -19927,8 +20103,15 @@ function useContainerWidth2(ref) {
19927
20103
  var KEYFRAMES2 = `
19928
20104
  @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
19929
20105
  .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
20106
+ .dc-range{-webkit-appearance:none;appearance:none;width:100%;height:4px;border-radius:9999px;outline:none;cursor:pointer;background:transparent}
20107
+ .dc-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background:white;border:2px solid var(--dc-thumb,#ff5000);box-shadow:0 1px 3px rgba(0,0,0,0.18);cursor:grab;transition:transform 0.12s}
20108
+ .dc-range::-webkit-slider-thumb:hover{transform:scale(1.12)}
20109
+ .dc-range:active::-webkit-slider-thumb{cursor:grabbing}
20110
+ .dc-range::-moz-range-thumb{width:12px;height:12px;border-radius:50%;background:white;border:2px solid var(--dc-thumb,#ff5000);box-shadow:0 1px 3px rgba(0,0,0,0.18);cursor:grab}
20111
+ .dc-range::-moz-range-track{height:4px;border-radius:9999px;background:transparent}
19930
20112
  @media (prefers-reduced-motion: reduce){
19931
20113
  .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
20114
+ .dc-range::-webkit-slider-thumb{transition:none}
19932
20115
  }`;
19933
20116
  function SparkCheck({ size, color }) {
19934
20117
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -19974,17 +20157,239 @@ function FlagPill({ flag }) {
19974
20157
  }
19975
20158
  );
19976
20159
  }
20160
+ function formatFigure(value, unit) {
20161
+ const body = Number.isInteger(value) ? `${value}` : `${Math.round(value * 100) / 100}`;
20162
+ if (!unit) return body;
20163
+ return unit === "%" ? `${body}%` : `${body} ${unit}`;
20164
+ }
20165
+ function clampToRange(raw, adjust) {
20166
+ var _a2;
20167
+ const step = (_a2 = adjust.step) != null ? _a2 : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
20168
+ const snapped = Math.round((raw - adjust.min) / step) * step + adjust.min;
20169
+ const fixed = Math.round(snapped * 1e6) / 1e6;
20170
+ return Math.min(adjust.max, Math.max(adjust.min, fixed));
20171
+ }
20172
+ function ValueAdjuster({
20173
+ option,
20174
+ accent,
20175
+ border,
20176
+ muted,
20177
+ onConfirm,
20178
+ onBack
20179
+ }) {
20180
+ var _a2, _b;
20181
+ const adjust = option.adjust;
20182
+ const suggested = clampToRange((_a2 = option.value) != null ? _a2 : adjust.min, adjust);
20183
+ const [value, setValue] = React45__default.default.useState(suggested);
20184
+ const [text, setText] = React45__default.default.useState(String(suggested));
20185
+ const step = (_b = adjust.step) != null ? _b : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
20186
+ const pct = adjust.max > adjust.min ? (value - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
20187
+ const suggestedPct = adjust.max > adjust.min ? (suggested - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
20188
+ const moved = value !== suggested;
20189
+ const commit = (raw) => {
20190
+ const v = clampToRange(raw, adjust);
20191
+ setValue(v);
20192
+ setText(String(v));
20193
+ };
20194
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20195
+ "div",
20196
+ {
20197
+ className: "dc-rise",
20198
+ "data-testid": "decision-card-adjuster",
20199
+ style: {
20200
+ display: "flex",
20201
+ flexDirection: "column",
20202
+ gap: 12,
20203
+ border: `1px solid ${border}`,
20204
+ borderRadius: 10,
20205
+ padding: "12px 14px",
20206
+ background: "#fafafa"
20207
+ },
20208
+ children: [
20209
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 8 }, children: [
20210
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.06em", color: muted }, children: [
20211
+ "Adjust \xB7 ",
20212
+ option.label
20213
+ ] }),
20214
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 } }),
20215
+ /* @__PURE__ */ jsxRuntime.jsx(
20216
+ "button",
20217
+ {
20218
+ type: "button",
20219
+ onClick: onBack,
20220
+ "data-testid": "decision-card-adjust-back",
20221
+ style: { border: "none", background: "none", padding: 0, cursor: "pointer", fontSize: 12, fontWeight: 600, color: muted },
20222
+ children: "Back"
20223
+ }
20224
+ )
20225
+ ] }),
20226
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 6 }, children: [
20227
+ /* @__PURE__ */ jsxRuntime.jsx(
20228
+ "input",
20229
+ {
20230
+ value: text,
20231
+ onChange: (e) => {
20232
+ setText(e.target.value);
20233
+ const n = Number(e.target.value);
20234
+ if (Number.isFinite(n)) setValue(clampToRange(n, adjust));
20235
+ },
20236
+ onBlur: () => commit(Number(text) || suggested),
20237
+ onKeyDown: (e) => {
20238
+ if (e.key === "Enter") {
20239
+ const v = clampToRange(Number(text) || suggested, adjust);
20240
+ commit(v);
20241
+ onConfirm(v);
20242
+ } else if (e.key === "ArrowUp") {
20243
+ e.preventDefault();
20244
+ commit(value + step);
20245
+ } else if (e.key === "ArrowDown") {
20246
+ e.preventDefault();
20247
+ commit(value - step);
20248
+ }
20249
+ },
20250
+ inputMode: "decimal",
20251
+ "aria-label": `${option.label} value`,
20252
+ "data-testid": "decision-card-adjust-input",
20253
+ style: {
20254
+ width: `${Math.max(3, String(text).length + 1)}ch`,
20255
+ fontSize: 26,
20256
+ fontWeight: 700,
20257
+ fontVariantNumeric: "tabular-nums",
20258
+ letterSpacing: "-0.02em",
20259
+ color: "var(--foreground)",
20260
+ border: "none",
20261
+ borderBottom: `2px solid ${accent}`,
20262
+ background: "transparent",
20263
+ outline: "none",
20264
+ padding: 0
20265
+ }
20266
+ }
20267
+ ),
20268
+ adjust.unit && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 13, fontWeight: 600, color: muted }, children: adjust.unit }),
20269
+ moved && /* @__PURE__ */ jsxRuntime.jsxs(
20270
+ "button",
20271
+ {
20272
+ type: "button",
20273
+ onClick: () => commit(suggested),
20274
+ "data-testid": "decision-card-adjust-reset",
20275
+ style: {
20276
+ marginLeft: 8,
20277
+ border: "none",
20278
+ background: "none",
20279
+ padding: 0,
20280
+ cursor: "pointer",
20281
+ fontSize: 11.5,
20282
+ fontWeight: 600,
20283
+ color: muted,
20284
+ textDecoration: "underline",
20285
+ textUnderlineOffset: 2
20286
+ },
20287
+ children: [
20288
+ "Reset to suggested (",
20289
+ formatFigure(suggested, adjust.unit),
20290
+ ")"
20291
+ ]
20292
+ }
20293
+ )
20294
+ ] }),
20295
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
20296
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", height: 16, display: "flex", alignItems: "center" }, children: [
20297
+ /* @__PURE__ */ jsxRuntime.jsx(
20298
+ "div",
20299
+ {
20300
+ "aria-hidden": "true",
20301
+ style: {
20302
+ position: "absolute",
20303
+ left: 0,
20304
+ right: 0,
20305
+ height: 4,
20306
+ borderRadius: 9999,
20307
+ background: `linear-gradient(to right, ${accent} ${pct}%, #e8e8e8 ${pct}%)`
20308
+ }
20309
+ }
20310
+ ),
20311
+ moved && /* @__PURE__ */ jsxRuntime.jsx(
20312
+ "div",
20313
+ {
20314
+ "aria-hidden": "true",
20315
+ title: `Suggested: ${formatFigure(suggested, adjust.unit)}`,
20316
+ style: {
20317
+ position: "absolute",
20318
+ left: `${suggestedPct}%`,
20319
+ transform: "translateX(-50%)",
20320
+ width: 2,
20321
+ height: 10,
20322
+ borderRadius: 1,
20323
+ background: muted,
20324
+ opacity: 0.55
20325
+ }
20326
+ }
20327
+ ),
20328
+ /* @__PURE__ */ jsxRuntime.jsx(
20329
+ "input",
20330
+ {
20331
+ type: "range",
20332
+ className: "dc-range",
20333
+ min: adjust.min,
20334
+ max: adjust.max,
20335
+ step,
20336
+ value,
20337
+ onChange: (e) => commit(Number(e.target.value)),
20338
+ "aria-label": `${option.label} slider`,
20339
+ "data-testid": "decision-card-adjust-slider",
20340
+ style: { position: "relative", ["--dc-thumb"]: accent }
20341
+ }
20342
+ )
20343
+ ] }),
20344
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 10.5, fontWeight: 600, color: muted, fontVariantNumeric: "tabular-nums" }, children: [
20345
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFigure(adjust.min, adjust.unit) }),
20346
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFigure(adjust.max, adjust.unit) })
20347
+ ] })
20348
+ ] }),
20349
+ /* @__PURE__ */ jsxRuntime.jsxs(
20350
+ "button",
20351
+ {
20352
+ type: "button",
20353
+ onClick: () => onConfirm(value),
20354
+ "data-testid": "decision-card-adjust-confirm",
20355
+ style: {
20356
+ alignSelf: "flex-start",
20357
+ border: `1px solid ${accent}`,
20358
+ background: accent,
20359
+ color: "white",
20360
+ borderRadius: 8,
20361
+ fontSize: 13,
20362
+ fontWeight: 600,
20363
+ padding: "9px 16px",
20364
+ cursor: "pointer",
20365
+ fontVariantNumeric: "tabular-nums",
20366
+ transition: "opacity 0.15s"
20367
+ },
20368
+ onMouseEnter: (e) => e.currentTarget.style.opacity = "0.88",
20369
+ onMouseLeave: (e) => e.currentTarget.style.opacity = "1",
20370
+ children: [
20371
+ option.label,
20372
+ " \xB7 ",
20373
+ formatFigure(value, adjust.unit)
20374
+ ]
20375
+ }
20376
+ )
20377
+ ]
20378
+ }
20379
+ );
20380
+ }
19977
20381
  function DecisionCardRenderer({
19978
20382
  data,
19979
20383
  resolved = null,
19980
20384
  onResolve,
19981
20385
  onOpenSource
19982
20386
  }) {
19983
- var _a2, _b;
20387
+ var _a2, _b, _c;
19984
20388
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
19985
20389
  const rootRef = React45__default.default.useRef(null);
19986
20390
  const width = useContainerWidth2(rootRef);
19987
20391
  const stacked = width > 0 && width < STACK_BELOW;
20392
+ const [adjustingIdx, setAdjustingIdx] = React45__default.default.useState(null);
19988
20393
  const options = (_a2 = data.options) != null ? _a2 : [];
19989
20394
  const recommendedIdx = Math.max(
19990
20395
  0,
@@ -20139,7 +20544,20 @@ function DecisionCardRenderer({
20139
20544
  ]
20140
20545
  }
20141
20546
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
20142
- /* @__PURE__ */ jsxRuntime.jsx(
20547
+ adjustingIdx != null && ((_b = options[adjustingIdx]) == null ? void 0 : _b.adjust) ? /* @__PURE__ */ jsxRuntime.jsx(
20548
+ ValueAdjuster,
20549
+ {
20550
+ option: options[adjustingIdx],
20551
+ accent: ACCENT2,
20552
+ border: BORDER4,
20553
+ muted: MUTED2,
20554
+ onBack: () => setAdjustingIdx(null),
20555
+ onConfirm: (value) => {
20556
+ setAdjustingIdx(null);
20557
+ onResolve == null ? void 0 : onResolve(options[adjustingIdx].label, value);
20558
+ }
20559
+ }
20560
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
20143
20561
  "div",
20144
20562
  {
20145
20563
  style: {
@@ -20149,15 +20567,21 @@ function DecisionCardRenderer({
20149
20567
  gap: 8
20150
20568
  },
20151
20569
  children: options.map((opt, idx) => {
20152
- var _a3;
20570
+ var _a3, _b2;
20153
20571
  const primary = idx === recommendedIdx;
20154
- return /* @__PURE__ */ jsxRuntime.jsx(
20572
+ const adjustable = Boolean(opt.adjust);
20573
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20155
20574
  "button",
20156
20575
  {
20157
20576
  type: "button",
20158
- onClick: () => onResolve == null ? void 0 : onResolve(opt.label),
20577
+ onClick: () => adjustable ? setAdjustingIdx(idx) : onResolve == null ? void 0 : onResolve(opt.label),
20578
+ "data-adjustable": adjustable || void 0,
20159
20579
  style: {
20160
20580
  width: stacked ? "100%" : "auto",
20581
+ display: "inline-flex",
20582
+ alignItems: "center",
20583
+ justifyContent: stacked ? "flex-start" : "center",
20584
+ gap: 7,
20161
20585
  textAlign: stacked ? "left" : "center",
20162
20586
  border: `1px solid ${primary ? ACCENT2 : BORDER4}`,
20163
20587
  background: primary ? ACCENT2 : "white",
@@ -20185,7 +20609,28 @@ function DecisionCardRenderer({
20185
20609
  e.currentTarget.style.background = "white";
20186
20610
  }
20187
20611
  },
20188
- children: opt.label
20612
+ children: [
20613
+ opt.label,
20614
+ adjustable && typeof opt.value === "number" && /* @__PURE__ */ jsxRuntime.jsxs(
20615
+ "span",
20616
+ {
20617
+ style: {
20618
+ fontSize: 11.5,
20619
+ fontWeight: 700,
20620
+ fontVariantNumeric: "tabular-nums",
20621
+ padding: "1px 7px",
20622
+ borderRadius: 9999,
20623
+ background: primary ? "rgba(255,255,255,0.22)" : "#f2f2f2",
20624
+ color: primary ? "white" : MUTED2,
20625
+ lineHeight: 1.5
20626
+ },
20627
+ children: [
20628
+ formatFigure(opt.value, (_b2 = opt.adjust) == null ? void 0 : _b2.unit),
20629
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { marginLeft: 4, opacity: 0.8 }, children: "\u270E" })
20630
+ ]
20631
+ }
20632
+ )
20633
+ ]
20189
20634
  },
20190
20635
  (_a3 = opt.id) != null ? _a3 : opt.label
20191
20636
  );
@@ -20224,7 +20669,7 @@ function DecisionCardRenderer({
20224
20669
  strokeLinejoin: "round"
20225
20670
  }
20226
20671
  ) }),
20227
- (_b = data.source.label) != null ? _b : "View source for this figure"
20672
+ (_c = data.source.label) != null ? _c : "View source for this figure"
20228
20673
  ]
20229
20674
  }
20230
20675
  )
@@ -20233,20 +20678,27 @@ function DecisionCardRenderer({
20233
20678
  }
20234
20679
  );
20235
20680
  }
20681
+ function composeResolution(p, option, value) {
20682
+ var _a2, _b, _c;
20683
+ if (value == null) return option;
20684
+ const unit = (_c = (_b = ((_a2 = p.options) != null ? _a2 : []).find((o) => o.label === option)) == null ? void 0 : _b.adjust) == null ? void 0 : _c.unit;
20685
+ return `${option} \xB7 ${formatFigure(value, unit)}`;
20686
+ }
20236
20687
  function DecisionCardResolver(p) {
20237
- var _a2, _b, _c, _d;
20688
+ var _a2, _b;
20238
20689
  const { resolvedDecisions, onDecisionResolve, onDecisionSource } = useGenUIInteraction();
20239
20690
  const decisionId = (_a2 = p.id) != null ? _a2 : p.title;
20240
20691
  const hostResolved = resolvedDecisions == null ? void 0 : resolvedDecisions[decisionId];
20241
- const initial = (_c = hostResolved != null ? hostResolved : (_b = p.resolved) == null ? void 0 : _b.option) != null ? _c : null;
20692
+ const initial = hostResolved != null ? hostResolved : p.resolved ? composeResolution(p, p.resolved.option, p.resolved.value) : null;
20242
20693
  const [localResolved, setLocalResolved] = React45__default.default.useState(initial);
20243
20694
  React45__default.default.useEffect(() => {
20244
20695
  if (hostResolved !== void 0) setLocalResolved(hostResolved);
20245
20696
  }, [hostResolved]);
20246
20697
  const resolved = hostResolved != null ? hostResolved : localResolved;
20247
- const handleResolve = (option) => {
20248
- setLocalResolved(option);
20249
- onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, option);
20698
+ const handleResolve = (option, value) => {
20699
+ const resolution = composeResolution(p, option, value);
20700
+ setLocalResolved(resolution);
20701
+ onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, resolution);
20250
20702
  };
20251
20703
  const handleSource = () => {
20252
20704
  var _a3;
@@ -20255,7 +20707,7 @@ function DecisionCardResolver(p) {
20255
20707
  window.open(p.source.url, "_blank", "noopener,noreferrer");
20256
20708
  }
20257
20709
  };
20258
- return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_d = p.title) != null ? _d : "decision-card", children: /* @__PURE__ */ jsxRuntime.jsx(
20710
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_b = p.title) != null ? _b : "decision-card", children: /* @__PURE__ */ jsxRuntime.jsx(
20259
20711
  DecisionCardRenderer,
20260
20712
  {
20261
20713
  data: p,
@@ -20265,6 +20717,317 @@ function DecisionCardResolver(p) {
20265
20717
  }
20266
20718
  ) });
20267
20719
  }
20720
+ init_ThemeContext();
20721
+ var CONNECTED_GREEN3 = "#15803d";
20722
+ var CONNECTED_GREEN_BG = "#dcfce7";
20723
+ var PENDING_AMBER = "#92400e";
20724
+ var PENDING_AMBER_BG = "#fff7ed";
20725
+ var CARD_TITLE = "Authentication required";
20726
+ var TRUST_FOOTER = "Credentials not stored by Adopt";
20727
+ var DEFAULT_STEPS = (app, ctaLabel, connected) => connected ? [
20728
+ `Click ${ctaLabel} below to open ${app} in a new tab.`,
20729
+ "Confirm you are signed in \u2014 re-authenticate if prompted.",
20730
+ "Return here \u2014 the request continues automatically."
20731
+ ] : [
20732
+ `Click ${ctaLabel} below to open the sign-in page.`,
20733
+ `Sign in with your ${app} credentials \u2014 SSO is supported.`,
20734
+ "Return here \u2014 the request resumes automatically."
20735
+ ];
20736
+ function humanizeApp(raw) {
20737
+ const v = raw.trim();
20738
+ if (!v) return v;
20739
+ const looksLikeSlug = /^[a-z0-9]+([_-][a-z0-9]+)*$/.test(v);
20740
+ if (!looksLikeSlug) return v;
20741
+ return v.split(/[_-]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
20742
+ }
20743
+ function ShieldIcon({ color }) {
20744
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20745
+ "svg",
20746
+ {
20747
+ width: "13",
20748
+ height: "13",
20749
+ viewBox: "0 0 24 24",
20750
+ fill: "none",
20751
+ stroke: color,
20752
+ strokeWidth: "2",
20753
+ strokeLinecap: "round",
20754
+ strokeLinejoin: "round",
20755
+ "aria-hidden": "true",
20756
+ style: { flexShrink: 0 },
20757
+ children: [
20758
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }),
20759
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 12 2 2 4-4" })
20760
+ ]
20761
+ }
20762
+ );
20763
+ }
20764
+ function ExternalIcon() {
20765
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20766
+ "svg",
20767
+ {
20768
+ width: "13",
20769
+ height: "13",
20770
+ viewBox: "0 0 24 24",
20771
+ fill: "none",
20772
+ stroke: "currentColor",
20773
+ strokeWidth: "2",
20774
+ strokeLinecap: "round",
20775
+ strokeLinejoin: "round",
20776
+ "aria-hidden": "true",
20777
+ style: { flexShrink: 0 },
20778
+ children: [
20779
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 3h6v6" }),
20780
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 14 21 3" }),
20781
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
20782
+ ]
20783
+ }
20784
+ );
20785
+ }
20786
+ function TabbyAuthResolver(p) {
20787
+ var _a2, _b, _c;
20788
+ const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
20789
+ const [cardHovered, setCardHovered] = React45.useState(false);
20790
+ const [btnHovered, setBtnHovered] = React45.useState(false);
20791
+ const [imgFailed, setImgFailed] = React45.useState(false);
20792
+ const app = humanizeApp(p.app || "the app");
20793
+ const connected = p.state === "connected";
20794
+ const accent = connected ? CONNECTED_GREEN3 : ACCENT2;
20795
+ const ctaLabel = (_a2 = p.ctaLabel) != null ? _a2 : connected ? `Open ${app}` : `Connect ${app}`;
20796
+ const subtitle = p.workspace ? `${app} \xB7 ${p.workspace} workspace` : app;
20797
+ const steps = ((_b = p.steps) == null ? void 0 : _b.length) ? p.steps : DEFAULT_STEPS(app, ctaLabel, connected);
20798
+ 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.`;
20799
+ const iconSrc = p.iconUrl || brandIconUrl(app);
20800
+ const showImg = Boolean(iconSrc) && !imgFailed;
20801
+ const initial = app.charAt(0).toUpperCase();
20802
+ const badge = connected ? { label: "Connected", bg: CONNECTED_GREEN_BG, color: CONNECTED_GREEN3 } : { label: "Pending sign-in", bg: PENDING_AMBER_BG, color: PENDING_AMBER };
20803
+ const sectionPad = "13px 16px";
20804
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: `${app} authentication`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: "10px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(
20805
+ "div",
20806
+ {
20807
+ onMouseEnter: () => setCardHovered(true),
20808
+ onMouseLeave: () => setCardHovered(false),
20809
+ style: {
20810
+ display: "flex",
20811
+ flexDirection: "row",
20812
+ alignItems: "stretch",
20813
+ borderRadius: "0.75rem",
20814
+ border: `1px solid ${cardHovered ? "#d2d2d2" : BORDER4}`,
20815
+ background: "white",
20816
+ overflow: "hidden",
20817
+ 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)",
20818
+ transition: "box-shadow 0.18s ease, border-color 0.18s ease"
20819
+ },
20820
+ children: [
20821
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "3px", flexShrink: 0, background: accent } }),
20822
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column" }, children: [
20823
+ /* @__PURE__ */ jsxRuntime.jsxs(
20824
+ "div",
20825
+ {
20826
+ style: {
20827
+ display: "flex",
20828
+ alignItems: "flex-start",
20829
+ gap: "12px",
20830
+ padding: sectionPad
20831
+ },
20832
+ children: [
20833
+ /* @__PURE__ */ jsxRuntime.jsx(
20834
+ "div",
20835
+ {
20836
+ style: {
20837
+ position: "relative",
20838
+ width: "34px",
20839
+ height: "34px",
20840
+ borderRadius: "9px",
20841
+ flexShrink: 0,
20842
+ display: "flex",
20843
+ alignItems: "center",
20844
+ justifyContent: "center",
20845
+ background: showImg ? "white" : "#fff3ee",
20846
+ boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.06)",
20847
+ overflow: "hidden"
20848
+ },
20849
+ children: showImg ? /* @__PURE__ */ jsxRuntime.jsx(
20850
+ "img",
20851
+ {
20852
+ src: iconSrc,
20853
+ alt: app,
20854
+ onError: () => setImgFailed(true),
20855
+ style: { width: "22px", height: "22px", objectFit: "contain" }
20856
+ }
20857
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
20858
+ "span",
20859
+ {
20860
+ style: {
20861
+ fontFamily: "var(--font-serif)",
20862
+ fontSize: "17px",
20863
+ fontWeight: 400,
20864
+ color: ACCENT2,
20865
+ lineHeight: 1
20866
+ },
20867
+ children: initial
20868
+ }
20869
+ )
20870
+ }
20871
+ ),
20872
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "2px" }, children: [
20873
+ /* @__PURE__ */ jsxRuntime.jsx(
20874
+ "span",
20875
+ {
20876
+ style: {
20877
+ fontFamily: "var(--font-serif)",
20878
+ fontSize: "15px",
20879
+ fontWeight: 400,
20880
+ color: "var(--foreground)",
20881
+ letterSpacing: "-0.01em",
20882
+ lineHeight: 1.2
20883
+ },
20884
+ children: CARD_TITLE
20885
+ }
20886
+ ),
20887
+ /* @__PURE__ */ jsxRuntime.jsx(
20888
+ "span",
20889
+ {
20890
+ style: {
20891
+ fontSize: "12px",
20892
+ color: MUTED2,
20893
+ whiteSpace: "nowrap",
20894
+ overflow: "hidden",
20895
+ textOverflow: "ellipsis"
20896
+ },
20897
+ children: subtitle
20898
+ }
20899
+ )
20900
+ ] }),
20901
+ /* @__PURE__ */ jsxRuntime.jsxs(
20902
+ "span",
20903
+ {
20904
+ style: {
20905
+ display: "inline-flex",
20906
+ alignItems: "center",
20907
+ gap: "5px",
20908
+ flexShrink: 0,
20909
+ fontSize: "10.5px",
20910
+ fontWeight: 600,
20911
+ padding: "3px 9px",
20912
+ borderRadius: "9999px",
20913
+ background: badge.bg,
20914
+ color: badge.color,
20915
+ whiteSpace: "nowrap"
20916
+ },
20917
+ children: [
20918
+ /* @__PURE__ */ jsxRuntime.jsx(
20919
+ "span",
20920
+ {
20921
+ style: {
20922
+ width: "6px",
20923
+ height: "6px",
20924
+ borderRadius: "9999px",
20925
+ background: badge.color
20926
+ }
20927
+ }
20928
+ ),
20929
+ badge.label
20930
+ ]
20931
+ }
20932
+ )
20933
+ ]
20934
+ }
20935
+ ),
20936
+ /* @__PURE__ */ jsxRuntime.jsxs(
20937
+ "div",
20938
+ {
20939
+ style: {
20940
+ borderTop: `1px solid ${BORDER4}`,
20941
+ padding: sectionPad,
20942
+ display: "flex",
20943
+ flexDirection: "column",
20944
+ gap: "12px"
20945
+ },
20946
+ children: [
20947
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "12.5px", lineHeight: 1.5, color: "var(--foreground)" }, children: description }),
20948
+ /* @__PURE__ */ jsxRuntime.jsx("ol", { style: { margin: 0, padding: 0, listStyle: "none", display: "flex", flexDirection: "column", gap: "8px" }, children: steps.map((step, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { style: { display: "flex", alignItems: "flex-start", gap: "10px" }, children: [
20949
+ /* @__PURE__ */ jsxRuntime.jsx(
20950
+ "span",
20951
+ {
20952
+ style: {
20953
+ flexShrink: 0,
20954
+ width: "18px",
20955
+ height: "18px",
20956
+ borderRadius: "9999px",
20957
+ background: accent,
20958
+ color: "white",
20959
+ fontSize: "10.5px",
20960
+ fontWeight: 600,
20961
+ display: "flex",
20962
+ alignItems: "center",
20963
+ justifyContent: "center",
20964
+ marginTop: "1px"
20965
+ },
20966
+ children: i + 1
20967
+ }
20968
+ ),
20969
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "12.5px", lineHeight: 1.45, color: "var(--foreground)" }, children: step })
20970
+ ] }, i)) })
20971
+ ]
20972
+ }
20973
+ ),
20974
+ /* @__PURE__ */ jsxRuntime.jsxs(
20975
+ "div",
20976
+ {
20977
+ style: {
20978
+ borderTop: `1px solid ${BORDER4}`,
20979
+ padding: sectionPad,
20980
+ background: "#fbfbfb",
20981
+ display: "flex",
20982
+ alignItems: "center",
20983
+ justifyContent: "space-between",
20984
+ gap: "12px",
20985
+ flexWrap: "wrap"
20986
+ },
20987
+ children: [
20988
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: "6px", color: MUTED2, fontSize: "11.5px" }, children: [
20989
+ /* @__PURE__ */ jsxRuntime.jsx(ShieldIcon, { color: CONNECTED_GREEN3 }),
20990
+ TRUST_FOOTER
20991
+ ] }),
20992
+ /* @__PURE__ */ jsxRuntime.jsxs(
20993
+ "a",
20994
+ {
20995
+ href: p.url,
20996
+ target: "_blank",
20997
+ rel: "noopener noreferrer",
20998
+ onMouseEnter: () => setBtnHovered(true),
20999
+ onMouseLeave: () => setBtnHovered(false),
21000
+ style: {
21001
+ display: "inline-flex",
21002
+ alignItems: "center",
21003
+ gap: "7px",
21004
+ flexShrink: 0,
21005
+ borderRadius: "8px",
21006
+ padding: "8px 15px",
21007
+ fontSize: "12.5px",
21008
+ fontWeight: 600,
21009
+ textDecoration: "none",
21010
+ whiteSpace: "nowrap",
21011
+ cursor: "pointer",
21012
+ color: "white",
21013
+ border: "1px solid transparent",
21014
+ background: btnHovered ? connected ? "#126a33" : ACCENT_SOFT2 : accent,
21015
+ transition: "background 0.15s ease"
21016
+ },
21017
+ children: [
21018
+ /* @__PURE__ */ jsxRuntime.jsx(ExternalIcon, {}),
21019
+ ctaLabel
21020
+ ]
21021
+ }
21022
+ )
21023
+ ]
21024
+ }
21025
+ )
21026
+ ] })
21027
+ ]
21028
+ }
21029
+ ) }) });
21030
+ }
20268
21031
  function resolveUI(rawPayload) {
20269
21032
  const payload = coercePayload(rawPayload);
20270
21033
  switch (payload.type) {
@@ -20386,6 +21149,8 @@ function resolveUI(rawPayload) {
20386
21149
  return /* @__PURE__ */ jsxRuntime.jsx(DocumentFieldExtractionResolver, __spreadValues({}, payload));
20387
21150
  case "decision-card":
20388
21151
  return /* @__PURE__ */ jsxRuntime.jsx(DecisionCardResolver, __spreadValues({}, payload));
21152
+ case "tabby-auth":
21153
+ return /* @__PURE__ */ jsxRuntime.jsx(TabbyAuthResolver, __spreadValues({}, payload));
20389
21154
  default: {
20390
21155
  return /* @__PURE__ */ jsxRuntime.jsx(
20391
21156
  "div",
@@ -21739,7 +22504,9 @@ function BlockForm({
21739
22504
  onEntityCreate,
21740
22505
  hideActions,
21741
22506
  dense,
21742
- variant = "form"
22507
+ variant = "form",
22508
+ fieldSuggestions,
22509
+ onApplySuggestion
21743
22510
  }) {
21744
22511
  var _a2;
21745
22512
  const t = useTheme();
@@ -21770,20 +22537,85 @@ function BlockForm({
21770
22537
  }
21771
22538
  ),
21772
22539
  ((_a2 = block.context) == null ? void 0 : _a2.type) && /* @__PURE__ */ jsxRuntime.jsx(ContextSlot, { payload: block.context }),
21773
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: dense ? "8px" : isEscalation ? "10px" : "12px" }, children: (block.fields || []).map((field) => /* @__PURE__ */ jsxRuntime.jsx("div", { "data-field-key": fieldKey(block.id, field.name), children: /* @__PURE__ */ jsxRuntime.jsx(
21774
- FieldRenderer,
21775
- {
21776
- field,
21777
- value: state.getValue(block.id, field.name),
21778
- onChange: (v) => state.setFieldValue(block.id, field.name, v),
21779
- disabled,
21780
- error: state.getError(block.id, field.name),
21781
- dense,
21782
- onFileUpload,
21783
- onEntitySearch,
21784
- onEntityCreate
21785
- }
21786
- ) }, `${block.id}:${field.name}`)) }),
22540
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: dense ? "8px" : isEscalation ? "10px" : "12px" }, children: (block.fields || []).map((field) => {
22541
+ var _a3;
22542
+ const suggestion = (fieldSuggestions || []).filter((sg) => {
22543
+ var _a4;
22544
+ return sg.field === field.name && ((_a4 = sg.block_id) != null ? _a4 : block.id) === block.id;
22545
+ }).slice(-1)[0];
22546
+ const current = state.getValue(block.id, field.name);
22547
+ const showSuggestion = suggestion != null && current !== suggestion.value;
22548
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-field-key": fieldKey(block.id, field.name), children: [
22549
+ /* @__PURE__ */ jsxRuntime.jsx(
22550
+ FieldRenderer,
22551
+ {
22552
+ field,
22553
+ value: current,
22554
+ onChange: (v) => state.setFieldValue(block.id, field.name, v),
22555
+ disabled,
22556
+ error: state.getError(block.id, field.name),
22557
+ dense,
22558
+ onFileUpload,
22559
+ onEntitySearch,
22560
+ onEntityCreate
22561
+ }
22562
+ ),
22563
+ showSuggestion && !disabled ? /* @__PURE__ */ jsxRuntime.jsxs(
22564
+ "div",
22565
+ {
22566
+ "data-testid": `builder-suggestion-${field.name}`,
22567
+ style: {
22568
+ display: "flex",
22569
+ alignItems: "center",
22570
+ flexWrap: "wrap",
22571
+ gap: "6px",
22572
+ marginTop: "5px",
22573
+ padding: "5px 9px",
22574
+ borderRadius: "8px",
22575
+ border: `1px dashed ${t.BORDER}`,
22576
+ background: "#fafafa",
22577
+ fontSize: "11.5px",
22578
+ lineHeight: 1.4
22579
+ },
22580
+ children: [
22581
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { color: t.ACCENT, fontSize: "11px" }, children: "\u2726" }),
22582
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: t.MUTED, fontWeight: 600 }, children: [
22583
+ "Suggested:",
22584
+ " ",
22585
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--foreground)", fontVariantNumeric: "tabular-nums" }, children: (_a3 = suggestion.label) != null ? _a3 : String(suggestion.value) })
22586
+ ] }),
22587
+ suggestion.note ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: t.MUTED }, children: [
22588
+ "\xB7 ",
22589
+ suggestion.note
22590
+ ] }) : null,
22591
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 } }),
22592
+ /* @__PURE__ */ jsxRuntime.jsx(
22593
+ "button",
22594
+ {
22595
+ type: "button",
22596
+ "data-testid": `builder-suggestion-apply-${field.name}`,
22597
+ onClick: () => {
22598
+ state.setFieldValue(block.id, field.name, suggestion.value);
22599
+ onApplySuggestion == null ? void 0 : onApplySuggestion(suggestion);
22600
+ },
22601
+ style: {
22602
+ font: "inherit",
22603
+ fontSize: "11.5px",
22604
+ fontWeight: 700,
22605
+ color: t.ACCENT,
22606
+ background: "transparent",
22607
+ border: "none",
22608
+ padding: 0,
22609
+ cursor: "pointer"
22610
+ },
22611
+ children: "Apply"
22612
+ }
22613
+ )
22614
+ ]
22615
+ }
22616
+ ) : null
22617
+ ] }, `${block.id}:${field.name}`);
22618
+ }) }),
21787
22619
  hideActions ? null : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "6px", paddingTop: isEscalation ? "2px" : "4px" }, children: [
21788
22620
  errorCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: "11px", fontWeight: 600, color: "#dc2626" }, children: [
21789
22621
  errorCount,
@@ -22071,7 +22903,9 @@ function BuilderFormResolver({
22071
22903
  submitRef,
22072
22904
  hideActions,
22073
22905
  dense,
22074
- onValidationError
22906
+ onValidationError,
22907
+ fieldSuggestions,
22908
+ onApplySuggestion
22075
22909
  }) {
22076
22910
  var _a2;
22077
22911
  const state = useBuilderState(builder.blocks);
@@ -22148,7 +22982,9 @@ function BuilderFormResolver({
22148
22982
  onEntitySearch,
22149
22983
  onEntityCreate,
22150
22984
  hideActions,
22151
- dense
22985
+ dense,
22986
+ fieldSuggestions,
22987
+ onApplySuggestion
22152
22988
  }
22153
22989
  );
22154
22990
  default:
@@ -22165,7 +23001,9 @@ function BuilderFormResolver({
22165
23001
  onEntitySearch,
22166
23002
  onEntityCreate,
22167
23003
  dense,
22168
- hideActions
23004
+ hideActions,
23005
+ fieldSuggestions,
23006
+ onApplySuggestion
22169
23007
  }
22170
23008
  );
22171
23009
  }