@adoptai/genui-components 0.1.59 → 0.1.61

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 (45) 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 +296 -17
  8. package/dist/composites/decision-card/resolver.cjs.map +1 -1
  9. package/dist/composites/decision-card/resolver.d.ts +9 -2
  10. package/dist/composites/decision-card/resolver.d.ts.map +1 -1
  11. package/dist/composites/decision-card/resolver.js +296 -18
  12. package/dist/composites/decision-card/resolver.js.map +1 -1
  13. package/dist/composites/decision-queue/resolver.d.ts +22 -0
  14. package/dist/composites/decision-queue/resolver.d.ts.map +1 -0
  15. package/dist/composites/workflow-stepper/resolver.cjs +2 -1
  16. package/dist/composites/workflow-stepper/resolver.cjs.map +1 -1
  17. package/dist/composites/workflow-stepper/resolver.js +2 -1
  18. package/dist/composites/workflow-stepper/resolver.js.map +1 -1
  19. package/dist/index.cjs +881 -46
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.js +881 -46
  22. package/dist/index.js.map +1 -1
  23. package/dist/renderer.cjs +790 -28
  24. package/dist/renderer.cjs.map +1 -1
  25. package/dist/renderer.js +790 -28
  26. package/dist/renderer.js.map +1 -1
  27. package/dist/resolver.cjs +790 -28
  28. package/dist/resolver.cjs.map +1 -1
  29. package/dist/resolver.d.ts.map +1 -1
  30. package/dist/resolver.js +790 -28
  31. package/dist/resolver.js.map +1 -1
  32. package/dist/schemas/decision-card.d.ts +37 -0
  33. package/dist/schemas/decision-card.d.ts.map +1 -1
  34. package/dist/schemas/decision-queue.d.ts +227 -0
  35. package/dist/schemas/decision-queue.d.ts.map +1 -0
  36. package/dist/schemas/index.cjs +191 -5
  37. package/dist/schemas/index.cjs.map +1 -1
  38. package/dist/schemas/index.d.ts +264 -0
  39. package/dist/schemas/index.d.ts.map +1 -1
  40. package/dist/schemas/index.js +191 -5
  41. package/dist/schemas/index.js.map +1 -1
  42. package/dist/shared/InteractionContext.d.ts +10 -0
  43. package/dist/shared/InteractionContext.d.ts.map +1 -1
  44. package/dist/tool-definitions.json +236 -4
  45. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5535,7 +5535,14 @@ var decisionCardSchema = z.object({
5535
5535
  z.object({
5536
5536
  id: z.string().optional(),
5537
5537
  label: z.string(),
5538
- recommended: z.boolean().optional()
5538
+ recommended: z.boolean().optional(),
5539
+ value: z.number().optional(),
5540
+ adjust: z.object({
5541
+ min: z.number(),
5542
+ max: z.number(),
5543
+ step: z.number().optional(),
5544
+ unit: z.string().optional()
5545
+ }).optional()
5539
5546
  })
5540
5547
  ).min(1).max(5),
5541
5548
  source: z.object({
@@ -5543,7 +5550,8 @@ var decisionCardSchema = z.object({
5543
5550
  url: z.string().optional()
5544
5551
  }).optional(),
5545
5552
  resolved: z.object({
5546
- option: z.string()
5553
+ option: z.string(),
5554
+ value: z.number().optional()
5547
5555
  }).optional()
5548
5556
  });
5549
5557
  var decisionCardTool = {
@@ -5586,13 +5594,28 @@ var decisionCardTool = {
5586
5594
  type: "array",
5587
5595
  minItems: 1,
5588
5596
  maxItems: 5,
5589
- description: "Mutually-exclusive resolution choices; mark one `recommended` to make it primary",
5597
+ 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.",
5590
5598
  items: {
5591
5599
  type: "object",
5592
5600
  properties: {
5593
5601
  id: { type: "string" },
5594
5602
  label: { type: "string" },
5595
- recommended: { type: "boolean" }
5603
+ recommended: { type: "boolean" },
5604
+ value: {
5605
+ type: "number",
5606
+ description: "Suggested numeric figure for this option (the starting point of the adjuster)"
5607
+ },
5608
+ adjust: {
5609
+ type: "object",
5610
+ description: "Allow the user to tune `value` within this inclusive range before resolving",
5611
+ properties: {
5612
+ min: { type: "number" },
5613
+ max: { type: "number" },
5614
+ step: { type: "number", description: "Increment granularity; defaults to a sensible step for the range" },
5615
+ unit: { type: "string", description: "Short unit suffix shown after the number, e.g. 'units', '%', 'hrs'" }
5616
+ },
5617
+ required: ["min", "max"]
5618
+ }
5596
5619
  },
5597
5620
  required: ["label"]
5598
5621
  }
@@ -5609,7 +5632,8 @@ var decisionCardTool = {
5609
5632
  type: "object",
5610
5633
  description: "Pre-resolved state for transcript replay",
5611
5634
  properties: {
5612
- option: { type: "string" }
5635
+ option: { type: "string" },
5636
+ value: { type: "number", description: "Adjusted figure the user confirmed, when the option was adjustable" }
5613
5637
  },
5614
5638
  required: ["option"]
5615
5639
  }
@@ -5617,6 +5641,167 @@ var decisionCardTool = {
5617
5641
  required: ["type", "title", "question", "options"]
5618
5642
  }
5619
5643
  };
5644
+ var decisionQueueItemSchema = z.object({
5645
+ id: z.string().optional(),
5646
+ decision_type: z.string().optional(),
5647
+ title: z.string(),
5648
+ question: z.string(),
5649
+ amount: z.number().optional(),
5650
+ currency: z.string().optional(),
5651
+ amount_label: z.string().optional(),
5652
+ severity: z.enum(["low", "medium", "high"]).optional(),
5653
+ flags: z.array(
5654
+ z.object({
5655
+ field: z.string().optional(),
5656
+ issue: z.string(),
5657
+ severity: z.enum(["low", "medium", "high"]).optional()
5658
+ })
5659
+ ).max(6).optional(),
5660
+ options: z.array(
5661
+ z.object({
5662
+ id: z.string().optional(),
5663
+ label: z.string(),
5664
+ recommended: z.boolean().optional(),
5665
+ value: z.number().optional(),
5666
+ adjust: z.object({
5667
+ min: z.number(),
5668
+ max: z.number(),
5669
+ step: z.number().optional(),
5670
+ unit: z.string().optional()
5671
+ }).optional()
5672
+ })
5673
+ ).min(1).max(5),
5674
+ source: z.object({
5675
+ label: z.string().optional(),
5676
+ url: z.string().optional()
5677
+ }).optional()
5678
+ });
5679
+ var decisionQueueSchema = z.object({
5680
+ type: z.literal("decision-queue"),
5681
+ id: z.string().optional(),
5682
+ title: z.string().optional(),
5683
+ description: z.string().optional(),
5684
+ submit_label: z.string().optional(),
5685
+ items: z.array(decisionQueueItemSchema).min(2).max(12),
5686
+ resolved: z.object({
5687
+ decisions: z.array(
5688
+ z.object({
5689
+ id: z.string().optional(),
5690
+ title: z.string(),
5691
+ option: z.string(),
5692
+ value: z.number().optional()
5693
+ })
5694
+ )
5695
+ }).optional()
5696
+ });
5697
+ var OPTION_ITEM_JSON = {
5698
+ type: "object",
5699
+ properties: {
5700
+ id: { type: "string" },
5701
+ label: { type: "string" },
5702
+ recommended: { type: "boolean" },
5703
+ value: {
5704
+ type: "number",
5705
+ description: "Suggested numeric figure for this option (starting point of the adjuster)"
5706
+ },
5707
+ adjust: {
5708
+ type: "object",
5709
+ description: "Allow the user to tune `value` within this inclusive range before deciding",
5710
+ properties: {
5711
+ min: { type: "number" },
5712
+ max: { type: "number" },
5713
+ step: { type: "number" },
5714
+ unit: { type: "string", description: "Short unit suffix, e.g. 'units', '%', 'hrs'" }
5715
+ },
5716
+ required: ["min", "max"]
5717
+ }
5718
+ },
5719
+ required: ["label"]
5720
+ };
5721
+ var decisionQueueTool = {
5722
+ name: "render_decision_queue",
5723
+ description: "Render a SEQUENTIAL QUEUE of 2-12 related human-in-the-loop judgments, decided one at a time at full decision-card richness (amount at stake, data-quality flags, adjustable figures, source links) and submitted TOGETHER as one reply. Use whenever MORE THAN ONE decision is pending in the same turn \u2014 never emit multiple loose decision-cards. Give deferrable items an explicit 'leave open'-style option so the user can always complete the queue. For a single judgment use decision-card; for typed field input (names, dates, uploads) use render_builder.",
5724
+ input_schema: {
5725
+ type: "object",
5726
+ properties: {
5727
+ type: { type: "string", enum: ["decision-queue"] },
5728
+ id: { type: "string", description: "Stable id for update-in-place rendering" },
5729
+ title: {
5730
+ type: "string",
5731
+ description: "Batch headline shown in the header, e.g. 'Reconciliation exceptions'"
5732
+ },
5733
+ description: { type: "string", description: "One-line context above the queue" },
5734
+ submit_label: { type: "string", description: "CTA label; defaults to 'Submit N decisions'" },
5735
+ items: {
5736
+ type: "array",
5737
+ minItems: 2,
5738
+ maxItems: 12,
5739
+ description: "The pending judgments, in the order the user should take them. Each is a full decision-card body (no `type`).",
5740
+ items: {
5741
+ type: "object",
5742
+ properties: {
5743
+ id: { type: "string" },
5744
+ decision_type: {
5745
+ type: "string",
5746
+ description: "Short category eyebrow, e.g. 'Duplicate', 'Capitalization'"
5747
+ },
5748
+ title: { type: "string" },
5749
+ question: { type: "string" },
5750
+ amount: { type: "number" },
5751
+ currency: { type: "string" },
5752
+ amount_label: { type: "string" },
5753
+ severity: { type: "string", enum: ["low", "medium", "high"] },
5754
+ flags: {
5755
+ type: "array",
5756
+ maxItems: 6,
5757
+ items: {
5758
+ type: "object",
5759
+ properties: {
5760
+ field: { type: "string" },
5761
+ issue: { type: "string" },
5762
+ severity: { type: "string", enum: ["low", "medium", "high"] }
5763
+ },
5764
+ required: ["issue"]
5765
+ }
5766
+ },
5767
+ options: {
5768
+ type: "array",
5769
+ minItems: 1,
5770
+ maxItems: 5,
5771
+ items: OPTION_ITEM_JSON
5772
+ },
5773
+ source: {
5774
+ type: "object",
5775
+ properties: { label: { type: "string" }, url: { type: "string" } }
5776
+ }
5777
+ },
5778
+ required: ["title", "question", "options"]
5779
+ }
5780
+ },
5781
+ resolved: {
5782
+ type: "object",
5783
+ description: "Pre-resolved state for transcript replay",
5784
+ properties: {
5785
+ decisions: {
5786
+ type: "array",
5787
+ items: {
5788
+ type: "object",
5789
+ properties: {
5790
+ id: { type: "string" },
5791
+ title: { type: "string" },
5792
+ option: { type: "string" },
5793
+ value: { type: "number" }
5794
+ },
5795
+ required: ["title", "option"]
5796
+ }
5797
+ }
5798
+ },
5799
+ required: ["decisions"]
5800
+ }
5801
+ },
5802
+ required: ["type", "items"]
5803
+ }
5804
+ };
5620
5805
  var tabbyAuthSchema = z.object({
5621
5806
  type: z.literal("tabby-auth"),
5622
5807
  app: z.string(),
@@ -5768,6 +5953,7 @@ var schemaRegistry = {
5768
5953
  "workflow-stepper": { schema: workflowStepperSchema, tool: workflowStepperTool },
5769
5954
  "document-field-extraction": { schema: documentFieldExtractionSchema, tool: documentFieldExtractionTool },
5770
5955
  "decision-card": { schema: decisionCardSchema, tool: decisionCardTool },
5956
+ "decision-queue": { schema: decisionQueueSchema, tool: decisionQueueTool },
5771
5957
  "tabby-auth": { schema: tabbyAuthSchema, tool: tabbyAuthTool }
5772
5958
  };
5773
5959
 
@@ -6481,17 +6667,17 @@ function SparklineTableResolver(p) {
6481
6667
  // src/composites/heatmap-table/resolver.tsx
6482
6668
  init_theme();
6483
6669
  init_ThemeContext();
6484
- function heatColor(z62) {
6485
- const clamped = Math.max(-3, Math.min(3, z62));
6670
+ function heatColor(z63) {
6671
+ const clamped = Math.max(-3, Math.min(3, z63));
6486
6672
  const abs = Math.abs(clamped);
6487
6673
  const lightness = 95 - abs * 8;
6488
6674
  const hue = clamped >= 0 ? 142 : 0;
6489
6675
  return `hsl(${hue} 60% ${lightness}%)`;
6490
6676
  }
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";
6677
+ function heatTextColor(z63) {
6678
+ const abs = Math.abs(z63);
6679
+ if (abs > 2) return z63 >= 0 ? "#14532d" : "#7f1d1d";
6680
+ if (abs > 1) return z63 >= 0 ? "#166534" : "#991b1b";
6495
6681
  return "var(--foreground)";
6496
6682
  }
6497
6683
  var th2 = {
@@ -17542,7 +17728,8 @@ var DEFAULT_INTERACTION = {
17542
17728
  onStepSelect: void 0,
17543
17729
  resolvedDecisions: void 0,
17544
17730
  onDecisionResolve: void 0,
17545
- onDecisionSource: void 0
17731
+ onDecisionSource: void 0,
17732
+ onDecisionQueueSubmit: void 0
17546
17733
  };
17547
17734
  var GenUIInteractionContext = createContext(DEFAULT_INTERACTION);
17548
17735
  function GenUIInteractionProvider({ value, children }) {
@@ -20051,8 +20238,15 @@ function useContainerWidth2(ref) {
20051
20238
  var KEYFRAMES2 = `
20052
20239
  @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
20053
20240
  .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
20241
+ .dc-range{-webkit-appearance:none;appearance:none;width:100%;height:4px;border-radius:9999px;outline:none;cursor:pointer;background:transparent}
20242
+ .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}
20243
+ .dc-range::-webkit-slider-thumb:hover{transform:scale(1.12)}
20244
+ .dc-range:active::-webkit-slider-thumb{cursor:grabbing}
20245
+ .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}
20246
+ .dc-range::-moz-range-track{height:4px;border-radius:9999px;background:transparent}
20054
20247
  @media (prefers-reduced-motion: reduce){
20055
20248
  .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
20249
+ .dc-range::-webkit-slider-thumb{transition:none}
20056
20250
  }`;
20057
20251
  function SparkCheck({ size, color }) {
20058
20252
  return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
@@ -20098,17 +20292,240 @@ function FlagPill({ flag }) {
20098
20292
  }
20099
20293
  );
20100
20294
  }
20295
+ function formatFigure(value, unit) {
20296
+ const body = Number.isInteger(value) ? `${value}` : `${Math.round(value * 100) / 100}`;
20297
+ if (!unit) return body;
20298
+ return unit === "%" ? `${body}%` : `${body} ${unit}`;
20299
+ }
20300
+ function clampToRange(raw, adjust) {
20301
+ var _a2;
20302
+ const step = (_a2 = adjust.step) != null ? _a2 : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
20303
+ const snapped = Math.round((raw - adjust.min) / step) * step + adjust.min;
20304
+ const fixed = Math.round(snapped * 1e6) / 1e6;
20305
+ return Math.min(adjust.max, Math.max(adjust.min, fixed));
20306
+ }
20307
+ function ValueAdjuster({
20308
+ option,
20309
+ accent,
20310
+ border,
20311
+ muted,
20312
+ onConfirm,
20313
+ onBack
20314
+ }) {
20315
+ var _a2, _b;
20316
+ const adjust = option.adjust;
20317
+ const suggested = clampToRange((_a2 = option.value) != null ? _a2 : adjust.min, adjust);
20318
+ const [value, setValue] = React45.useState(suggested);
20319
+ const [text, setText] = React45.useState(String(suggested));
20320
+ const step = (_b = adjust.step) != null ? _b : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
20321
+ const pct = adjust.max > adjust.min ? (value - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
20322
+ const suggestedPct = adjust.max > adjust.min ? (suggested - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
20323
+ const moved = value !== suggested;
20324
+ const commit = (raw) => {
20325
+ const v = clampToRange(raw, adjust);
20326
+ setValue(v);
20327
+ setText(String(v));
20328
+ };
20329
+ return /* @__PURE__ */ jsxs(
20330
+ "div",
20331
+ {
20332
+ className: "dc-rise",
20333
+ "data-testid": "decision-card-adjuster",
20334
+ style: {
20335
+ display: "flex",
20336
+ flexDirection: "column",
20337
+ gap: 12,
20338
+ border: `1px solid ${border}`,
20339
+ borderRadius: 10,
20340
+ padding: "12px 14px",
20341
+ background: "#fafafa"
20342
+ },
20343
+ children: [
20344
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 8 }, children: [
20345
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.06em", color: muted }, children: [
20346
+ "Adjust \xB7 ",
20347
+ option.label
20348
+ ] }),
20349
+ /* @__PURE__ */ jsx("span", { style: { flex: 1 } }),
20350
+ /* @__PURE__ */ jsx(
20351
+ "button",
20352
+ {
20353
+ type: "button",
20354
+ onClick: onBack,
20355
+ "data-testid": "decision-card-adjust-back",
20356
+ style: { border: "none", background: "none", padding: 0, cursor: "pointer", fontSize: 12, fontWeight: 600, color: muted },
20357
+ children: "Back"
20358
+ }
20359
+ )
20360
+ ] }),
20361
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 6 }, children: [
20362
+ /* @__PURE__ */ jsx(
20363
+ "input",
20364
+ {
20365
+ value: text,
20366
+ onChange: (e) => {
20367
+ setText(e.target.value);
20368
+ const n = Number(e.target.value);
20369
+ if (Number.isFinite(n)) setValue(clampToRange(n, adjust));
20370
+ },
20371
+ onBlur: () => commit(Number(text) || suggested),
20372
+ onKeyDown: (e) => {
20373
+ if (e.key === "Enter") {
20374
+ const v = clampToRange(Number(text) || suggested, adjust);
20375
+ commit(v);
20376
+ onConfirm(v);
20377
+ } else if (e.key === "ArrowUp") {
20378
+ e.preventDefault();
20379
+ commit(value + step);
20380
+ } else if (e.key === "ArrowDown") {
20381
+ e.preventDefault();
20382
+ commit(value - step);
20383
+ }
20384
+ },
20385
+ inputMode: "decimal",
20386
+ "aria-label": `${option.label} value`,
20387
+ "data-testid": "decision-card-adjust-input",
20388
+ style: {
20389
+ width: `${Math.max(3, String(text).length + 1)}ch`,
20390
+ fontSize: 26,
20391
+ fontWeight: 700,
20392
+ fontVariantNumeric: "tabular-nums",
20393
+ letterSpacing: "-0.02em",
20394
+ color: "var(--foreground)",
20395
+ border: "none",
20396
+ borderBottom: `2px solid ${accent}`,
20397
+ background: "transparent",
20398
+ outline: "none",
20399
+ padding: 0
20400
+ }
20401
+ }
20402
+ ),
20403
+ adjust.unit && /* @__PURE__ */ jsx("span", { style: { fontSize: 13, fontWeight: 600, color: muted }, children: adjust.unit }),
20404
+ moved && /* @__PURE__ */ jsxs(
20405
+ "button",
20406
+ {
20407
+ type: "button",
20408
+ onClick: () => commit(suggested),
20409
+ "data-testid": "decision-card-adjust-reset",
20410
+ style: {
20411
+ marginLeft: 8,
20412
+ border: "none",
20413
+ background: "none",
20414
+ padding: 0,
20415
+ cursor: "pointer",
20416
+ fontSize: 11.5,
20417
+ fontWeight: 600,
20418
+ color: muted,
20419
+ textDecoration: "underline",
20420
+ textUnderlineOffset: 2
20421
+ },
20422
+ children: [
20423
+ "Reset to suggested (",
20424
+ formatFigure(suggested, adjust.unit),
20425
+ ")"
20426
+ ]
20427
+ }
20428
+ )
20429
+ ] }),
20430
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
20431
+ /* @__PURE__ */ jsxs("div", { style: { position: "relative", height: 16, display: "flex", alignItems: "center" }, children: [
20432
+ /* @__PURE__ */ jsx(
20433
+ "div",
20434
+ {
20435
+ "aria-hidden": "true",
20436
+ style: {
20437
+ position: "absolute",
20438
+ left: 0,
20439
+ right: 0,
20440
+ height: 4,
20441
+ borderRadius: 9999,
20442
+ background: `linear-gradient(to right, ${accent} ${pct}%, #e8e8e8 ${pct}%)`
20443
+ }
20444
+ }
20445
+ ),
20446
+ moved && /* @__PURE__ */ jsx(
20447
+ "div",
20448
+ {
20449
+ "aria-hidden": "true",
20450
+ title: `Suggested: ${formatFigure(suggested, adjust.unit)}`,
20451
+ style: {
20452
+ position: "absolute",
20453
+ left: `${suggestedPct}%`,
20454
+ transform: "translateX(-50%)",
20455
+ width: 2,
20456
+ height: 10,
20457
+ borderRadius: 1,
20458
+ background: muted,
20459
+ opacity: 0.55
20460
+ }
20461
+ }
20462
+ ),
20463
+ /* @__PURE__ */ jsx(
20464
+ "input",
20465
+ {
20466
+ type: "range",
20467
+ className: "dc-range",
20468
+ min: adjust.min,
20469
+ max: adjust.max,
20470
+ step,
20471
+ value,
20472
+ onChange: (e) => commit(Number(e.target.value)),
20473
+ "aria-label": `${option.label} slider`,
20474
+ "data-testid": "decision-card-adjust-slider",
20475
+ style: { position: "relative", ["--dc-thumb"]: accent }
20476
+ }
20477
+ )
20478
+ ] }),
20479
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 10.5, fontWeight: 600, color: muted, fontVariantNumeric: "tabular-nums" }, children: [
20480
+ /* @__PURE__ */ jsx("span", { children: formatFigure(adjust.min, adjust.unit) }),
20481
+ /* @__PURE__ */ jsx("span", { children: formatFigure(adjust.max, adjust.unit) })
20482
+ ] })
20483
+ ] }),
20484
+ /* @__PURE__ */ jsxs(
20485
+ "button",
20486
+ {
20487
+ type: "button",
20488
+ onClick: () => onConfirm(value),
20489
+ "data-testid": "decision-card-adjust-confirm",
20490
+ style: {
20491
+ alignSelf: "flex-start",
20492
+ border: `1px solid ${accent}`,
20493
+ background: accent,
20494
+ color: "white",
20495
+ borderRadius: 8,
20496
+ fontSize: 13,
20497
+ fontWeight: 600,
20498
+ padding: "9px 16px",
20499
+ cursor: "pointer",
20500
+ fontVariantNumeric: "tabular-nums",
20501
+ transition: "opacity 0.15s"
20502
+ },
20503
+ onMouseEnter: (e) => e.currentTarget.style.opacity = "0.88",
20504
+ onMouseLeave: (e) => e.currentTarget.style.opacity = "1",
20505
+ children: [
20506
+ option.label,
20507
+ " \xB7 ",
20508
+ formatFigure(value, adjust.unit)
20509
+ ]
20510
+ }
20511
+ )
20512
+ ]
20513
+ }
20514
+ );
20515
+ }
20101
20516
  function DecisionCardRenderer({
20102
20517
  data,
20103
20518
  resolved = null,
20104
20519
  onResolve,
20105
- onOpenSource
20520
+ onOpenSource,
20521
+ eyebrow
20106
20522
  }) {
20107
- var _a2, _b;
20523
+ var _a2, _b, _c;
20108
20524
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
20109
20525
  const rootRef = React45.useRef(null);
20110
20526
  const width = useContainerWidth2(rootRef);
20111
20527
  const stacked = width > 0 && width < STACK_BELOW;
20528
+ const [adjustingIdx, setAdjustingIdx] = React45.useState(null);
20112
20529
  const options = (_a2 = data.options) != null ? _a2 : [];
20113
20530
  const recommendedIdx = Math.max(
20114
20531
  0,
@@ -20207,7 +20624,7 @@ function DecisionCardRenderer({
20207
20624
  },
20208
20625
  children: [
20209
20626
  /* @__PURE__ */ jsxs("div", { style: { minWidth: 0, display: "flex", flexDirection: "column", gap: 4 }, children: [
20210
- /* @__PURE__ */ jsx(
20627
+ eyebrow === null ? null : /* @__PURE__ */ jsx(
20211
20628
  "span",
20212
20629
  {
20213
20630
  style: {
@@ -20217,7 +20634,7 @@ function DecisionCardRenderer({
20217
20634
  fontWeight: 700,
20218
20635
  color: ACCENT2
20219
20636
  },
20220
- children: data.decision_type ? `Decision needs you \xB7 ${data.decision_type}` : "Decision needs you"
20637
+ children: eyebrow !== void 0 ? eyebrow : data.decision_type ? `Decision needs you \xB7 ${data.decision_type}` : "Decision needs you"
20221
20638
  }
20222
20639
  ),
20223
20640
  /* @__PURE__ */ jsx(
@@ -20263,7 +20680,20 @@ function DecisionCardRenderer({
20263
20680
  ]
20264
20681
  }
20265
20682
  ) : /* @__PURE__ */ jsxs(Fragment, { children: [
20266
- /* @__PURE__ */ jsx(
20683
+ adjustingIdx != null && ((_b = options[adjustingIdx]) == null ? void 0 : _b.adjust) ? /* @__PURE__ */ jsx(
20684
+ ValueAdjuster,
20685
+ {
20686
+ option: options[adjustingIdx],
20687
+ accent: ACCENT2,
20688
+ border: BORDER4,
20689
+ muted: MUTED2,
20690
+ onBack: () => setAdjustingIdx(null),
20691
+ onConfirm: (value) => {
20692
+ setAdjustingIdx(null);
20693
+ onResolve == null ? void 0 : onResolve(options[adjustingIdx].label, value);
20694
+ }
20695
+ }
20696
+ ) : /* @__PURE__ */ jsx(
20267
20697
  "div",
20268
20698
  {
20269
20699
  style: {
@@ -20273,15 +20703,21 @@ function DecisionCardRenderer({
20273
20703
  gap: 8
20274
20704
  },
20275
20705
  children: options.map((opt, idx) => {
20276
- var _a3;
20706
+ var _a3, _b2;
20277
20707
  const primary = idx === recommendedIdx;
20278
- return /* @__PURE__ */ jsx(
20708
+ const adjustable = Boolean(opt.adjust);
20709
+ return /* @__PURE__ */ jsxs(
20279
20710
  "button",
20280
20711
  {
20281
20712
  type: "button",
20282
- onClick: () => onResolve == null ? void 0 : onResolve(opt.label),
20713
+ onClick: () => adjustable ? setAdjustingIdx(idx) : onResolve == null ? void 0 : onResolve(opt.label),
20714
+ "data-adjustable": adjustable || void 0,
20283
20715
  style: {
20284
20716
  width: stacked ? "100%" : "auto",
20717
+ display: "inline-flex",
20718
+ alignItems: "center",
20719
+ justifyContent: stacked ? "flex-start" : "center",
20720
+ gap: 7,
20285
20721
  textAlign: stacked ? "left" : "center",
20286
20722
  border: `1px solid ${primary ? ACCENT2 : BORDER4}`,
20287
20723
  background: primary ? ACCENT2 : "white",
@@ -20309,7 +20745,28 @@ function DecisionCardRenderer({
20309
20745
  e.currentTarget.style.background = "white";
20310
20746
  }
20311
20747
  },
20312
- children: opt.label
20748
+ children: [
20749
+ opt.label,
20750
+ adjustable && typeof opt.value === "number" && /* @__PURE__ */ jsxs(
20751
+ "span",
20752
+ {
20753
+ style: {
20754
+ fontSize: 11.5,
20755
+ fontWeight: 700,
20756
+ fontVariantNumeric: "tabular-nums",
20757
+ padding: "1px 7px",
20758
+ borderRadius: 9999,
20759
+ background: primary ? "rgba(255,255,255,0.22)" : "#f2f2f2",
20760
+ color: primary ? "white" : MUTED2,
20761
+ lineHeight: 1.5
20762
+ },
20763
+ children: [
20764
+ formatFigure(opt.value, (_b2 = opt.adjust) == null ? void 0 : _b2.unit),
20765
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { marginLeft: 4, opacity: 0.8 }, children: "\u270E" })
20766
+ ]
20767
+ }
20768
+ )
20769
+ ]
20313
20770
  },
20314
20771
  (_a3 = opt.id) != null ? _a3 : opt.label
20315
20772
  );
@@ -20348,7 +20805,7 @@ function DecisionCardRenderer({
20348
20805
  strokeLinejoin: "round"
20349
20806
  }
20350
20807
  ) }),
20351
- (_b = data.source.label) != null ? _b : "View source for this figure"
20808
+ (_c = data.source.label) != null ? _c : "View source for this figure"
20352
20809
  ]
20353
20810
  }
20354
20811
  )
@@ -20357,20 +20814,27 @@ function DecisionCardRenderer({
20357
20814
  }
20358
20815
  );
20359
20816
  }
20817
+ function composeResolution(p, option, value) {
20818
+ var _a2, _b, _c;
20819
+ if (value == null) return option;
20820
+ const unit = (_c = (_b = ((_a2 = p.options) != null ? _a2 : []).find((o) => o.label === option)) == null ? void 0 : _b.adjust) == null ? void 0 : _c.unit;
20821
+ return `${option} \xB7 ${formatFigure(value, unit)}`;
20822
+ }
20360
20823
  function DecisionCardResolver(p) {
20361
- var _a2, _b, _c, _d;
20824
+ var _a2, _b;
20362
20825
  const { resolvedDecisions, onDecisionResolve, onDecisionSource } = useGenUIInteraction();
20363
20826
  const decisionId = (_a2 = p.id) != null ? _a2 : p.title;
20364
20827
  const hostResolved = resolvedDecisions == null ? void 0 : resolvedDecisions[decisionId];
20365
- const initial = (_c = hostResolved != null ? hostResolved : (_b = p.resolved) == null ? void 0 : _b.option) != null ? _c : null;
20828
+ const initial = hostResolved != null ? hostResolved : p.resolved ? composeResolution(p, p.resolved.option, p.resolved.value) : null;
20366
20829
  const [localResolved, setLocalResolved] = React45.useState(initial);
20367
20830
  React45.useEffect(() => {
20368
20831
  if (hostResolved !== void 0) setLocalResolved(hostResolved);
20369
20832
  }, [hostResolved]);
20370
20833
  const resolved = hostResolved != null ? hostResolved : localResolved;
20371
- const handleResolve = (option) => {
20372
- setLocalResolved(option);
20373
- onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, option);
20834
+ const handleResolve = (option, value) => {
20835
+ const resolution = composeResolution(p, option, value);
20836
+ setLocalResolved(resolution);
20837
+ onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, resolution);
20374
20838
  };
20375
20839
  const handleSource = () => {
20376
20840
  var _a3;
@@ -20379,7 +20843,7 @@ function DecisionCardResolver(p) {
20379
20843
  window.open(p.source.url, "_blank", "noopener,noreferrer");
20380
20844
  }
20381
20845
  };
20382
- return /* @__PURE__ */ jsx(ComponentActions, { filename: (_d = p.title) != null ? _d : "decision-card", children: /* @__PURE__ */ jsx(
20846
+ return /* @__PURE__ */ jsx(ComponentActions, { filename: (_b = p.title) != null ? _b : "decision-card", children: /* @__PURE__ */ jsx(
20383
20847
  DecisionCardRenderer,
20384
20848
  {
20385
20849
  data: p,
@@ -20390,6 +20854,302 @@ function DecisionCardResolver(p) {
20390
20854
  ) });
20391
20855
  }
20392
20856
  init_ThemeContext();
20857
+ var GREEN4 = "#15803d";
20858
+ var KEYFRAMES3 = `
20859
+ @keyframes dqSettle{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}
20860
+ .dq-settle{animation:dqSettle 0.24s cubic-bezier(0.22,1,0.36,1) both}
20861
+ @keyframes dqFocus{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:none}}
20862
+ .dq-focus{animation:dqFocus 0.28s cubic-bezier(0.22,1,0.36,1) both}
20863
+ @media (prefers-reduced-motion: reduce){
20864
+ .dq-settle,.dq-focus{animation:none !important;opacity:1 !important;transform:none !important}
20865
+ }`;
20866
+ function figureOf(item, decision) {
20867
+ var _a2, _b, _c;
20868
+ if (decision.value == null) return decision.option;
20869
+ const unit = (_c = (_b = ((_a2 = item.options) != null ? _a2 : []).find((o) => o.label === decision.option)) == null ? void 0 : _b.adjust) == null ? void 0 : _c.unit;
20870
+ return `${decision.option} \xB7 ${formatFigure(decision.value, unit)}`;
20871
+ }
20872
+ function composeQueueMessage(items, decisions) {
20873
+ const lines = items.map((item, i) => {
20874
+ const d = decisions[i];
20875
+ return `${i + 1}. ${item.title} \u2192 ${d ? figureOf(item, d) : "(undecided)"}`;
20876
+ });
20877
+ const done = decisions.filter(Boolean).length;
20878
+ return `Decisions (${done}/${items.length}):
20879
+ ${lines.join("\n")}`;
20880
+ }
20881
+ function Check({ size, color }) {
20882
+ return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7", stroke: color, strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round" }) });
20883
+ }
20884
+ function amountChip(item) {
20885
+ if (typeof item.amount !== "number") return null;
20886
+ const abs = Math.abs(item.amount);
20887
+ const sign = item.amount < 0 ? "-" : "";
20888
+ if (abs >= 1e6) return `${sign}$${(abs / 1e6).toFixed(abs >= 1e7 ? 0 : 1)}M`;
20889
+ if (abs >= 1e3) return `${sign}$${(abs / 1e3).toFixed(abs >= 1e4 ? 0 : 1)}K`;
20890
+ return `${sign}$${abs}`;
20891
+ }
20892
+ function DecisionQueueRenderer({ data, submitted = null, onSubmit }) {
20893
+ var _a2;
20894
+ const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2 } = useTheme();
20895
+ const items = (_a2 = data.items) != null ? _a2 : [];
20896
+ const [decisions, setDecisions] = React45.useState(
20897
+ () => items.map(() => void 0)
20898
+ );
20899
+ const firstUndecided = decisions.findIndex((d) => !d);
20900
+ const [focusIdx, setFocusIdx] = React45.useState(firstUndecided >= 0 ? firstUndecided : null);
20901
+ const isSubmitted = submitted != null;
20902
+ const shown = isSubmitted ? items.map(
20903
+ (item, i) => {
20904
+ var _a3;
20905
+ return (_a3 = submitted.find((d) => d.id && d.id === item.id || d.title === item.title)) != null ? _a3 : submitted[i];
20906
+ }
20907
+ ) : decisions;
20908
+ const decidedCount = shown.filter(Boolean).length;
20909
+ const allDecided = decidedCount === items.length;
20910
+ const decide = (idx, option, value) => {
20911
+ const item = items[idx];
20912
+ const next = decisions.slice();
20913
+ next[idx] = { id: item.id, title: item.title, option, value };
20914
+ setDecisions(next);
20915
+ const order = [...Array(items.length).keys()];
20916
+ const after = order.slice(idx + 1).concat(order.slice(0, idx + 1));
20917
+ const target = after.find((j) => j !== idx && !next[j]);
20918
+ setFocusIdx(target != null ? target : null);
20919
+ };
20920
+ const handleSubmit = () => {
20921
+ if (!allDecided || isSubmitted) return;
20922
+ const final = decisions;
20923
+ onSubmit == null ? void 0 : onSubmit(final, composeQueueMessage(items, final));
20924
+ };
20925
+ return /* @__PURE__ */ jsxs(
20926
+ "div",
20927
+ {
20928
+ "data-testid": "decision-queue",
20929
+ "data-submitted": isSubmitted || void 0,
20930
+ style: {
20931
+ position: "relative",
20932
+ width: "100%",
20933
+ minWidth: 0,
20934
+ boxSizing: "border-box",
20935
+ borderRadius: "0.75rem",
20936
+ border: `1px solid ${BORDER4}`,
20937
+ background: "white",
20938
+ boxShadow: "0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.04)",
20939
+ padding: "16px 18px",
20940
+ display: "flex",
20941
+ flexDirection: "column",
20942
+ gap: 12,
20943
+ overflow: "hidden"
20944
+ },
20945
+ children: [
20946
+ /* @__PURE__ */ jsx("style", { children: KEYFRAMES3 }),
20947
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 3 }, children: [
20948
+ /* @__PURE__ */ jsx(
20949
+ "span",
20950
+ {
20951
+ style: {
20952
+ fontSize: 10.5,
20953
+ textTransform: "uppercase",
20954
+ letterSpacing: "0.07em",
20955
+ fontWeight: 700,
20956
+ color: isSubmitted ? GREEN4 : ACCENT2
20957
+ },
20958
+ children: isSubmitted ? "Decisions submitted" : "Decisions need you"
20959
+ }
20960
+ ),
20961
+ data.title && /* @__PURE__ */ jsx(
20962
+ "p",
20963
+ {
20964
+ style: {
20965
+ fontFamily: "var(--font-serif)",
20966
+ fontSize: 16,
20967
+ fontWeight: 400,
20968
+ color: "var(--foreground)",
20969
+ letterSpacing: "-0.01em",
20970
+ margin: 0,
20971
+ lineHeight: 1.25
20972
+ },
20973
+ children: data.title
20974
+ }
20975
+ ),
20976
+ data.description && /* @__PURE__ */ jsx("p", { style: { fontSize: 12.5, color: MUTED2, margin: 0, lineHeight: 1.45 }, children: data.description })
20977
+ ] }),
20978
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: items.map((item, idx) => {
20979
+ var _a3, _b, _c;
20980
+ const decision = shown[idx];
20981
+ const focused = !isSubmitted && focusIdx === idx;
20982
+ if (focused) {
20983
+ return /* @__PURE__ */ jsx("div", { className: "dq-focus", "data-testid": `decision-queue-focus-${idx}`, children: /* @__PURE__ */ jsx(
20984
+ DecisionCardRenderer,
20985
+ {
20986
+ data: __spreadValues({ type: "decision-card" }, item),
20987
+ resolved: null,
20988
+ onResolve: (option, value) => decide(idx, option, value),
20989
+ eyebrow: `${idx + 1} of ${items.length}${item.decision_type ? ` \xB7 ${item.decision_type}` : ""}`
20990
+ }
20991
+ ) }, (_a3 = item.id) != null ? _a3 : `q-${idx}`);
20992
+ }
20993
+ if (decision) {
20994
+ return /* @__PURE__ */ jsxs(
20995
+ "button",
20996
+ {
20997
+ type: "button",
20998
+ className: "dq-settle",
20999
+ onClick: isSubmitted ? void 0 : () => setFocusIdx(idx),
21000
+ disabled: isSubmitted,
21001
+ title: isSubmitted ? void 0 : "Change this decision",
21002
+ "data-testid": `decision-queue-receipt-${idx}`,
21003
+ style: {
21004
+ display: "flex",
21005
+ alignItems: "center",
21006
+ gap: 8,
21007
+ width: "100%",
21008
+ textAlign: "left",
21009
+ border: "1px solid #dcfce7",
21010
+ background: "#f6fef9",
21011
+ borderRadius: 8,
21012
+ padding: "7px 11px",
21013
+ cursor: isSubmitted ? "default" : "pointer",
21014
+ font: "inherit"
21015
+ },
21016
+ children: [
21017
+ /* @__PURE__ */ jsx(Check, { size: 13, color: GREEN4 }),
21018
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 12.5, fontWeight: 600, color: "var(--foreground)", minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: item.title }),
21019
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { color: MUTED2, fontSize: 12 }, children: "\u2192" }),
21020
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 12.5, fontWeight: 600, color: GREEN4, fontVariantNumeric: "tabular-nums", whiteSpace: "nowrap" }, children: figureOf(item, decision) }),
21021
+ /* @__PURE__ */ jsx("span", { style: { flex: 1 } }),
21022
+ !isSubmitted && /* @__PURE__ */ jsx("span", { style: { fontSize: 11, fontWeight: 600, color: MUTED2 }, children: "Change" })
21023
+ ]
21024
+ },
21025
+ (_b = item.id) != null ? _b : `q-${idx}`
21026
+ );
21027
+ }
21028
+ return /* @__PURE__ */ jsxs(
21029
+ "button",
21030
+ {
21031
+ type: "button",
21032
+ onClick: isSubmitted ? void 0 : () => setFocusIdx(idx),
21033
+ disabled: isSubmitted,
21034
+ "data-testid": `decision-queue-upcoming-${idx}`,
21035
+ style: {
21036
+ display: "flex",
21037
+ alignItems: "center",
21038
+ gap: 8,
21039
+ width: "100%",
21040
+ textAlign: "left",
21041
+ border: `1px dashed ${BORDER4}`,
21042
+ background: "white",
21043
+ borderRadius: 8,
21044
+ padding: "7px 11px",
21045
+ cursor: isSubmitted ? "default" : "pointer",
21046
+ font: "inherit",
21047
+ opacity: 0.75
21048
+ },
21049
+ children: [
21050
+ /* @__PURE__ */ jsx(
21051
+ "span",
21052
+ {
21053
+ "aria-hidden": "true",
21054
+ style: { width: 13, height: 13, borderRadius: "50%", border: `1.5px solid ${MUTED2}`, flexShrink: 0, boxSizing: "border-box" }
21055
+ }
21056
+ ),
21057
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: 12.5, fontWeight: 600, color: MUTED2, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
21058
+ item.decision_type ? `${item.decision_type} \xB7 ` : "",
21059
+ item.title
21060
+ ] }),
21061
+ /* @__PURE__ */ jsx("span", { style: { flex: 1 } }),
21062
+ amountChip(item) && /* @__PURE__ */ jsx("span", { style: { fontSize: 11.5, fontWeight: 700, color: MUTED2, fontVariantNumeric: "tabular-nums" }, children: amountChip(item) })
21063
+ ]
21064
+ },
21065
+ (_c = item.id) != null ? _c : `q-${idx}`
21066
+ );
21067
+ }) }),
21068
+ /* @__PURE__ */ jsxs(
21069
+ "div",
21070
+ {
21071
+ style: {
21072
+ display: "flex",
21073
+ alignItems: "center",
21074
+ gap: 10,
21075
+ paddingTop: 10,
21076
+ borderTop: `1px solid #f0f0f0`
21077
+ },
21078
+ children: [
21079
+ /* @__PURE__ */ jsx("span", { style: { display: "inline-flex", gap: 4 }, "aria-hidden": "true", children: items.map((_, i) => /* @__PURE__ */ jsx(
21080
+ "span",
21081
+ {
21082
+ style: {
21083
+ width: 7,
21084
+ height: 7,
21085
+ borderRadius: "50%",
21086
+ background: shown[i] ? isSubmitted ? GREEN4 : ACCENT2 : "#e8e8e8",
21087
+ transition: "background 0.2s"
21088
+ }
21089
+ },
21090
+ `dot-${i}`
21091
+ )) }),
21092
+ /* @__PURE__ */ jsxs(
21093
+ "span",
21094
+ {
21095
+ style: { fontSize: 11.5, fontWeight: 600, color: MUTED2, fontVariantNumeric: "tabular-nums" },
21096
+ "data-testid": "decision-queue-progress",
21097
+ children: [
21098
+ decidedCount,
21099
+ "/",
21100
+ items.length,
21101
+ " decided"
21102
+ ]
21103
+ }
21104
+ ),
21105
+ /* @__PURE__ */ jsx("span", { style: { flex: 1 } }),
21106
+ isSubmitted ? /* @__PURE__ */ jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 6, fontSize: 12.5, fontWeight: 600, color: GREEN4 }, children: [
21107
+ /* @__PURE__ */ jsx(Check, { size: 14, color: GREEN4 }),
21108
+ "Submitted"
21109
+ ] }) : /* @__PURE__ */ jsx(
21110
+ "button",
21111
+ {
21112
+ type: "button",
21113
+ onClick: handleSubmit,
21114
+ disabled: !allDecided,
21115
+ "data-testid": "decision-queue-submit",
21116
+ style: {
21117
+ border: `1px solid ${allDecided ? ACCENT2 : BORDER4}`,
21118
+ background: allDecided ? ACCENT2 : "#f6f6f6",
21119
+ color: allDecided ? "white" : MUTED2,
21120
+ borderRadius: 8,
21121
+ fontSize: 13,
21122
+ fontWeight: 600,
21123
+ padding: "8px 16px",
21124
+ cursor: allDecided ? "pointer" : "default",
21125
+ fontVariantNumeric: "tabular-nums",
21126
+ transition: "background 0.15s, border-color 0.15s, color 0.15s"
21127
+ },
21128
+ children: data.submit_label || `Submit ${items.length} decision${items.length === 1 ? "" : "s"}`
21129
+ }
21130
+ )
21131
+ ]
21132
+ }
21133
+ )
21134
+ ]
21135
+ }
21136
+ );
21137
+ }
21138
+ function DecisionQueueResolver(p) {
21139
+ var _a2, _b, _c, _d, _e, _f;
21140
+ const { resolvedDecisions, onDecisionQueueSubmit } = useGenUIInteraction();
21141
+ const queueId = (_b = (_a2 = p.id) != null ? _a2 : p.title) != null ? _b : "decision-queue";
21142
+ const replayed = (_d = (_c = p.resolved) == null ? void 0 : _c.decisions) != null ? _d : null;
21143
+ const [localSubmitted, setLocalSubmitted] = React45.useState(null);
21144
+ const hostLocked = (resolvedDecisions == null ? void 0 : resolvedDecisions[queueId]) != null;
21145
+ const submitted = (_e = replayed != null ? replayed : localSubmitted) != null ? _e : hostLocked ? [] : null;
21146
+ const handleSubmit = (decisions, message) => {
21147
+ setLocalSubmitted(decisions);
21148
+ onDecisionQueueSubmit == null ? void 0 : onDecisionQueueSubmit(queueId, decisions, message);
21149
+ };
21150
+ return /* @__PURE__ */ jsx(ComponentActions, { filename: (_f = p.title) != null ? _f : "decision-queue", children: /* @__PURE__ */ jsx(DecisionQueueRenderer, { data: p, submitted, onSubmit: handleSubmit }) });
21151
+ }
21152
+ init_ThemeContext();
20393
21153
  var CONNECTED_GREEN3 = "#15803d";
20394
21154
  var CONNECTED_GREEN_BG = "#dcfce7";
20395
21155
  var PENDING_AMBER = "#92400e";
@@ -20821,6 +21581,8 @@ function resolveUI(rawPayload) {
20821
21581
  return /* @__PURE__ */ jsx(DocumentFieldExtractionResolver, __spreadValues({}, payload));
20822
21582
  case "decision-card":
20823
21583
  return /* @__PURE__ */ jsx(DecisionCardResolver, __spreadValues({}, payload));
21584
+ case "decision-queue":
21585
+ return /* @__PURE__ */ jsx(DecisionQueueResolver, __spreadValues({}, payload));
20824
21586
  case "tabby-auth":
20825
21587
  return /* @__PURE__ */ jsx(TabbyAuthResolver, __spreadValues({}, payload));
20826
21588
  default: {
@@ -22176,7 +22938,9 @@ function BlockForm({
22176
22938
  onEntityCreate,
22177
22939
  hideActions,
22178
22940
  dense,
22179
- variant = "form"
22941
+ variant = "form",
22942
+ fieldSuggestions,
22943
+ onApplySuggestion
22180
22944
  }) {
22181
22945
  var _a2;
22182
22946
  const t = useTheme();
@@ -22207,20 +22971,85 @@ function BlockForm({
22207
22971
  }
22208
22972
  ),
22209
22973
  ((_a2 = block.context) == null ? void 0 : _a2.type) && /* @__PURE__ */ jsx(ContextSlot, { payload: block.context }),
22210
- /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: dense ? "8px" : isEscalation ? "10px" : "12px" }, children: (block.fields || []).map((field) => /* @__PURE__ */ jsx("div", { "data-field-key": fieldKey(block.id, field.name), children: /* @__PURE__ */ jsx(
22211
- FieldRenderer,
22212
- {
22213
- field,
22214
- value: state.getValue(block.id, field.name),
22215
- onChange: (v) => state.setFieldValue(block.id, field.name, v),
22216
- disabled,
22217
- error: state.getError(block.id, field.name),
22218
- dense,
22219
- onFileUpload,
22220
- onEntitySearch,
22221
- onEntityCreate
22222
- }
22223
- ) }, `${block.id}:${field.name}`)) }),
22974
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: dense ? "8px" : isEscalation ? "10px" : "12px" }, children: (block.fields || []).map((field) => {
22975
+ var _a3;
22976
+ const suggestion = (fieldSuggestions || []).filter((sg) => {
22977
+ var _a4;
22978
+ return sg.field === field.name && ((_a4 = sg.block_id) != null ? _a4 : block.id) === block.id;
22979
+ }).slice(-1)[0];
22980
+ const current = state.getValue(block.id, field.name);
22981
+ const showSuggestion = suggestion != null && current !== suggestion.value;
22982
+ return /* @__PURE__ */ jsxs("div", { "data-field-key": fieldKey(block.id, field.name), children: [
22983
+ /* @__PURE__ */ jsx(
22984
+ FieldRenderer,
22985
+ {
22986
+ field,
22987
+ value: current,
22988
+ onChange: (v) => state.setFieldValue(block.id, field.name, v),
22989
+ disabled,
22990
+ error: state.getError(block.id, field.name),
22991
+ dense,
22992
+ onFileUpload,
22993
+ onEntitySearch,
22994
+ onEntityCreate
22995
+ }
22996
+ ),
22997
+ showSuggestion && !disabled ? /* @__PURE__ */ jsxs(
22998
+ "div",
22999
+ {
23000
+ "data-testid": `builder-suggestion-${field.name}`,
23001
+ style: {
23002
+ display: "flex",
23003
+ alignItems: "center",
23004
+ flexWrap: "wrap",
23005
+ gap: "6px",
23006
+ marginTop: "5px",
23007
+ padding: "5px 9px",
23008
+ borderRadius: "8px",
23009
+ border: `1px dashed ${t.BORDER}`,
23010
+ background: "#fafafa",
23011
+ fontSize: "11.5px",
23012
+ lineHeight: 1.4
23013
+ },
23014
+ children: [
23015
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { color: t.ACCENT, fontSize: "11px" }, children: "\u2726" }),
23016
+ /* @__PURE__ */ jsxs("span", { style: { color: t.MUTED, fontWeight: 600 }, children: [
23017
+ "Suggested:",
23018
+ " ",
23019
+ /* @__PURE__ */ jsx("span", { style: { color: "var(--foreground)", fontVariantNumeric: "tabular-nums" }, children: (_a3 = suggestion.label) != null ? _a3 : String(suggestion.value) })
23020
+ ] }),
23021
+ suggestion.note ? /* @__PURE__ */ jsxs("span", { style: { color: t.MUTED }, children: [
23022
+ "\xB7 ",
23023
+ suggestion.note
23024
+ ] }) : null,
23025
+ /* @__PURE__ */ jsx("span", { style: { flex: 1 } }),
23026
+ /* @__PURE__ */ jsx(
23027
+ "button",
23028
+ {
23029
+ type: "button",
23030
+ "data-testid": `builder-suggestion-apply-${field.name}`,
23031
+ onClick: () => {
23032
+ state.setFieldValue(block.id, field.name, suggestion.value);
23033
+ onApplySuggestion == null ? void 0 : onApplySuggestion(suggestion);
23034
+ },
23035
+ style: {
23036
+ font: "inherit",
23037
+ fontSize: "11.5px",
23038
+ fontWeight: 700,
23039
+ color: t.ACCENT,
23040
+ background: "transparent",
23041
+ border: "none",
23042
+ padding: 0,
23043
+ cursor: "pointer"
23044
+ },
23045
+ children: "Apply"
23046
+ }
23047
+ )
23048
+ ]
23049
+ }
23050
+ ) : null
23051
+ ] }, `${block.id}:${field.name}`);
23052
+ }) }),
22224
23053
  hideActions ? null : /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "6px", paddingTop: isEscalation ? "2px" : "4px" }, children: [
22225
23054
  errorCount > 0 ? /* @__PURE__ */ jsxs("div", { style: { fontSize: "11px", fontWeight: 600, color: "#dc2626" }, children: [
22226
23055
  errorCount,
@@ -22508,7 +23337,9 @@ function BuilderFormResolver({
22508
23337
  submitRef,
22509
23338
  hideActions,
22510
23339
  dense,
22511
- onValidationError
23340
+ onValidationError,
23341
+ fieldSuggestions,
23342
+ onApplySuggestion
22512
23343
  }) {
22513
23344
  var _a2;
22514
23345
  const state = useBuilderState(builder.blocks);
@@ -22585,7 +23416,9 @@ function BuilderFormResolver({
22585
23416
  onEntitySearch,
22586
23417
  onEntityCreate,
22587
23418
  hideActions,
22588
- dense
23419
+ dense,
23420
+ fieldSuggestions,
23421
+ onApplySuggestion
22589
23422
  }
22590
23423
  );
22591
23424
  default:
@@ -22602,7 +23435,9 @@ function BuilderFormResolver({
22602
23435
  onEntitySearch,
22603
23436
  onEntityCreate,
22604
23437
  dense,
22605
- hideActions
23438
+ hideActions,
23439
+ fieldSuggestions,
23440
+ onApplySuggestion
22606
23441
  }
22607
23442
  );
22608
23443
  }