@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.cjs CHANGED
@@ -5563,7 +5563,14 @@ var decisionCardSchema = zod.z.object({
5563
5563
  zod.z.object({
5564
5564
  id: zod.z.string().optional(),
5565
5565
  label: zod.z.string(),
5566
- 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()
5567
5574
  })
5568
5575
  ).min(1).max(5),
5569
5576
  source: zod.z.object({
@@ -5571,7 +5578,8 @@ var decisionCardSchema = zod.z.object({
5571
5578
  url: zod.z.string().optional()
5572
5579
  }).optional(),
5573
5580
  resolved: zod.z.object({
5574
- option: zod.z.string()
5581
+ option: zod.z.string(),
5582
+ value: zod.z.number().optional()
5575
5583
  }).optional()
5576
5584
  });
5577
5585
  var decisionCardTool = {
@@ -5614,13 +5622,28 @@ var decisionCardTool = {
5614
5622
  type: "array",
5615
5623
  minItems: 1,
5616
5624
  maxItems: 5,
5617
- 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.",
5618
5626
  items: {
5619
5627
  type: "object",
5620
5628
  properties: {
5621
5629
  id: { type: "string" },
5622
5630
  label: { type: "string" },
5623
- 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
+ }
5624
5647
  },
5625
5648
  required: ["label"]
5626
5649
  }
@@ -5637,7 +5660,8 @@ var decisionCardTool = {
5637
5660
  type: "object",
5638
5661
  description: "Pre-resolved state for transcript replay",
5639
5662
  properties: {
5640
- option: { type: "string" }
5663
+ option: { type: "string" },
5664
+ value: { type: "number", description: "Adjusted figure the user confirmed, when the option was adjustable" }
5641
5665
  },
5642
5666
  required: ["option"]
5643
5667
  }
@@ -5645,6 +5669,167 @@ var decisionCardTool = {
5645
5669
  required: ["type", "title", "question", "options"]
5646
5670
  }
5647
5671
  };
5672
+ var decisionQueueItemSchema = zod.z.object({
5673
+ id: zod.z.string().optional(),
5674
+ decision_type: zod.z.string().optional(),
5675
+ title: zod.z.string(),
5676
+ question: zod.z.string(),
5677
+ amount: zod.z.number().optional(),
5678
+ currency: zod.z.string().optional(),
5679
+ amount_label: zod.z.string().optional(),
5680
+ severity: zod.z.enum(["low", "medium", "high"]).optional(),
5681
+ flags: zod.z.array(
5682
+ zod.z.object({
5683
+ field: zod.z.string().optional(),
5684
+ issue: zod.z.string(),
5685
+ severity: zod.z.enum(["low", "medium", "high"]).optional()
5686
+ })
5687
+ ).max(6).optional(),
5688
+ options: zod.z.array(
5689
+ zod.z.object({
5690
+ id: zod.z.string().optional(),
5691
+ label: zod.z.string(),
5692
+ recommended: zod.z.boolean().optional(),
5693
+ value: zod.z.number().optional(),
5694
+ adjust: zod.z.object({
5695
+ min: zod.z.number(),
5696
+ max: zod.z.number(),
5697
+ step: zod.z.number().optional(),
5698
+ unit: zod.z.string().optional()
5699
+ }).optional()
5700
+ })
5701
+ ).min(1).max(5),
5702
+ source: zod.z.object({
5703
+ label: zod.z.string().optional(),
5704
+ url: zod.z.string().optional()
5705
+ }).optional()
5706
+ });
5707
+ var decisionQueueSchema = zod.z.object({
5708
+ type: zod.z.literal("decision-queue"),
5709
+ id: zod.z.string().optional(),
5710
+ title: zod.z.string().optional(),
5711
+ description: zod.z.string().optional(),
5712
+ submit_label: zod.z.string().optional(),
5713
+ items: zod.z.array(decisionQueueItemSchema).min(2).max(12),
5714
+ resolved: zod.z.object({
5715
+ decisions: zod.z.array(
5716
+ zod.z.object({
5717
+ id: zod.z.string().optional(),
5718
+ title: zod.z.string(),
5719
+ option: zod.z.string(),
5720
+ value: zod.z.number().optional()
5721
+ })
5722
+ )
5723
+ }).optional()
5724
+ });
5725
+ var OPTION_ITEM_JSON = {
5726
+ type: "object",
5727
+ properties: {
5728
+ id: { type: "string" },
5729
+ label: { type: "string" },
5730
+ recommended: { type: "boolean" },
5731
+ value: {
5732
+ type: "number",
5733
+ description: "Suggested numeric figure for this option (starting point of the adjuster)"
5734
+ },
5735
+ adjust: {
5736
+ type: "object",
5737
+ description: "Allow the user to tune `value` within this inclusive range before deciding",
5738
+ properties: {
5739
+ min: { type: "number" },
5740
+ max: { type: "number" },
5741
+ step: { type: "number" },
5742
+ unit: { type: "string", description: "Short unit suffix, e.g. 'units', '%', 'hrs'" }
5743
+ },
5744
+ required: ["min", "max"]
5745
+ }
5746
+ },
5747
+ required: ["label"]
5748
+ };
5749
+ var decisionQueueTool = {
5750
+ name: "render_decision_queue",
5751
+ 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.",
5752
+ input_schema: {
5753
+ type: "object",
5754
+ properties: {
5755
+ type: { type: "string", enum: ["decision-queue"] },
5756
+ id: { type: "string", description: "Stable id for update-in-place rendering" },
5757
+ title: {
5758
+ type: "string",
5759
+ description: "Batch headline shown in the header, e.g. 'Reconciliation exceptions'"
5760
+ },
5761
+ description: { type: "string", description: "One-line context above the queue" },
5762
+ submit_label: { type: "string", description: "CTA label; defaults to 'Submit N decisions'" },
5763
+ items: {
5764
+ type: "array",
5765
+ minItems: 2,
5766
+ maxItems: 12,
5767
+ description: "The pending judgments, in the order the user should take them. Each is a full decision-card body (no `type`).",
5768
+ items: {
5769
+ type: "object",
5770
+ properties: {
5771
+ id: { type: "string" },
5772
+ decision_type: {
5773
+ type: "string",
5774
+ description: "Short category eyebrow, e.g. 'Duplicate', 'Capitalization'"
5775
+ },
5776
+ title: { type: "string" },
5777
+ question: { type: "string" },
5778
+ amount: { type: "number" },
5779
+ currency: { type: "string" },
5780
+ amount_label: { type: "string" },
5781
+ severity: { type: "string", enum: ["low", "medium", "high"] },
5782
+ flags: {
5783
+ type: "array",
5784
+ maxItems: 6,
5785
+ items: {
5786
+ type: "object",
5787
+ properties: {
5788
+ field: { type: "string" },
5789
+ issue: { type: "string" },
5790
+ severity: { type: "string", enum: ["low", "medium", "high"] }
5791
+ },
5792
+ required: ["issue"]
5793
+ }
5794
+ },
5795
+ options: {
5796
+ type: "array",
5797
+ minItems: 1,
5798
+ maxItems: 5,
5799
+ items: OPTION_ITEM_JSON
5800
+ },
5801
+ source: {
5802
+ type: "object",
5803
+ properties: { label: { type: "string" }, url: { type: "string" } }
5804
+ }
5805
+ },
5806
+ required: ["title", "question", "options"]
5807
+ }
5808
+ },
5809
+ resolved: {
5810
+ type: "object",
5811
+ description: "Pre-resolved state for transcript replay",
5812
+ properties: {
5813
+ decisions: {
5814
+ type: "array",
5815
+ items: {
5816
+ type: "object",
5817
+ properties: {
5818
+ id: { type: "string" },
5819
+ title: { type: "string" },
5820
+ option: { type: "string" },
5821
+ value: { type: "number" }
5822
+ },
5823
+ required: ["title", "option"]
5824
+ }
5825
+ }
5826
+ },
5827
+ required: ["decisions"]
5828
+ }
5829
+ },
5830
+ required: ["type", "items"]
5831
+ }
5832
+ };
5648
5833
  var tabbyAuthSchema = zod.z.object({
5649
5834
  type: zod.z.literal("tabby-auth"),
5650
5835
  app: zod.z.string(),
@@ -5796,6 +5981,7 @@ var schemaRegistry = {
5796
5981
  "workflow-stepper": { schema: workflowStepperSchema, tool: workflowStepperTool },
5797
5982
  "document-field-extraction": { schema: documentFieldExtractionSchema, tool: documentFieldExtractionTool },
5798
5983
  "decision-card": { schema: decisionCardSchema, tool: decisionCardTool },
5984
+ "decision-queue": { schema: decisionQueueSchema, tool: decisionQueueTool },
5799
5985
  "tabby-auth": { schema: tabbyAuthSchema, tool: tabbyAuthTool }
5800
5986
  };
5801
5987
 
@@ -6509,17 +6695,17 @@ function SparklineTableResolver(p) {
6509
6695
  // src/composites/heatmap-table/resolver.tsx
6510
6696
  init_theme();
6511
6697
  init_ThemeContext();
6512
- function heatColor(z62) {
6513
- const clamped = Math.max(-3, Math.min(3, z62));
6698
+ function heatColor(z63) {
6699
+ const clamped = Math.max(-3, Math.min(3, z63));
6514
6700
  const abs = Math.abs(clamped);
6515
6701
  const lightness = 95 - abs * 8;
6516
6702
  const hue = clamped >= 0 ? 142 : 0;
6517
6703
  return `hsl(${hue} 60% ${lightness}%)`;
6518
6704
  }
6519
- function heatTextColor(z62) {
6520
- const abs = Math.abs(z62);
6521
- if (abs > 2) return z62 >= 0 ? "#14532d" : "#7f1d1d";
6522
- if (abs > 1) return z62 >= 0 ? "#166534" : "#991b1b";
6705
+ function heatTextColor(z63) {
6706
+ const abs = Math.abs(z63);
6707
+ if (abs > 2) return z63 >= 0 ? "#14532d" : "#7f1d1d";
6708
+ if (abs > 1) return z63 >= 0 ? "#166534" : "#991b1b";
6523
6709
  return "var(--foreground)";
6524
6710
  }
6525
6711
  var th2 = {
@@ -17570,7 +17756,8 @@ var DEFAULT_INTERACTION = {
17570
17756
  onStepSelect: void 0,
17571
17757
  resolvedDecisions: void 0,
17572
17758
  onDecisionResolve: void 0,
17573
- onDecisionSource: void 0
17759
+ onDecisionSource: void 0,
17760
+ onDecisionQueueSubmit: void 0
17574
17761
  };
17575
17762
  var GenUIInteractionContext = React45.createContext(DEFAULT_INTERACTION);
17576
17763
  function GenUIInteractionProvider({ value, children }) {
@@ -20079,8 +20266,15 @@ function useContainerWidth2(ref) {
20079
20266
  var KEYFRAMES2 = `
20080
20267
  @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
20081
20268
  .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
20269
+ .dc-range{-webkit-appearance:none;appearance:none;width:100%;height:4px;border-radius:9999px;outline:none;cursor:pointer;background:transparent}
20270
+ .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}
20271
+ .dc-range::-webkit-slider-thumb:hover{transform:scale(1.12)}
20272
+ .dc-range:active::-webkit-slider-thumb{cursor:grabbing}
20273
+ .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}
20274
+ .dc-range::-moz-range-track{height:4px;border-radius:9999px;background:transparent}
20082
20275
  @media (prefers-reduced-motion: reduce){
20083
20276
  .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
20277
+ .dc-range::-webkit-slider-thumb{transition:none}
20084
20278
  }`;
20085
20279
  function SparkCheck({ size, color }) {
20086
20280
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -20126,17 +20320,240 @@ function FlagPill({ flag }) {
20126
20320
  }
20127
20321
  );
20128
20322
  }
20323
+ function formatFigure(value, unit) {
20324
+ const body = Number.isInteger(value) ? `${value}` : `${Math.round(value * 100) / 100}`;
20325
+ if (!unit) return body;
20326
+ return unit === "%" ? `${body}%` : `${body} ${unit}`;
20327
+ }
20328
+ function clampToRange(raw, adjust) {
20329
+ var _a2;
20330
+ const step = (_a2 = adjust.step) != null ? _a2 : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
20331
+ const snapped = Math.round((raw - adjust.min) / step) * step + adjust.min;
20332
+ const fixed = Math.round(snapped * 1e6) / 1e6;
20333
+ return Math.min(adjust.max, Math.max(adjust.min, fixed));
20334
+ }
20335
+ function ValueAdjuster({
20336
+ option,
20337
+ accent,
20338
+ border,
20339
+ muted,
20340
+ onConfirm,
20341
+ onBack
20342
+ }) {
20343
+ var _a2, _b;
20344
+ const adjust = option.adjust;
20345
+ const suggested = clampToRange((_a2 = option.value) != null ? _a2 : adjust.min, adjust);
20346
+ const [value, setValue] = React45__default.default.useState(suggested);
20347
+ const [text, setText] = React45__default.default.useState(String(suggested));
20348
+ const step = (_b = adjust.step) != null ? _b : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
20349
+ const pct = adjust.max > adjust.min ? (value - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
20350
+ const suggestedPct = adjust.max > adjust.min ? (suggested - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
20351
+ const moved = value !== suggested;
20352
+ const commit = (raw) => {
20353
+ const v = clampToRange(raw, adjust);
20354
+ setValue(v);
20355
+ setText(String(v));
20356
+ };
20357
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20358
+ "div",
20359
+ {
20360
+ className: "dc-rise",
20361
+ "data-testid": "decision-card-adjuster",
20362
+ style: {
20363
+ display: "flex",
20364
+ flexDirection: "column",
20365
+ gap: 12,
20366
+ border: `1px solid ${border}`,
20367
+ borderRadius: 10,
20368
+ padding: "12px 14px",
20369
+ background: "#fafafa"
20370
+ },
20371
+ children: [
20372
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 8 }, children: [
20373
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.06em", color: muted }, children: [
20374
+ "Adjust \xB7 ",
20375
+ option.label
20376
+ ] }),
20377
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 } }),
20378
+ /* @__PURE__ */ jsxRuntime.jsx(
20379
+ "button",
20380
+ {
20381
+ type: "button",
20382
+ onClick: onBack,
20383
+ "data-testid": "decision-card-adjust-back",
20384
+ style: { border: "none", background: "none", padding: 0, cursor: "pointer", fontSize: 12, fontWeight: 600, color: muted },
20385
+ children: "Back"
20386
+ }
20387
+ )
20388
+ ] }),
20389
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 6 }, children: [
20390
+ /* @__PURE__ */ jsxRuntime.jsx(
20391
+ "input",
20392
+ {
20393
+ value: text,
20394
+ onChange: (e) => {
20395
+ setText(e.target.value);
20396
+ const n = Number(e.target.value);
20397
+ if (Number.isFinite(n)) setValue(clampToRange(n, adjust));
20398
+ },
20399
+ onBlur: () => commit(Number(text) || suggested),
20400
+ onKeyDown: (e) => {
20401
+ if (e.key === "Enter") {
20402
+ const v = clampToRange(Number(text) || suggested, adjust);
20403
+ commit(v);
20404
+ onConfirm(v);
20405
+ } else if (e.key === "ArrowUp") {
20406
+ e.preventDefault();
20407
+ commit(value + step);
20408
+ } else if (e.key === "ArrowDown") {
20409
+ e.preventDefault();
20410
+ commit(value - step);
20411
+ }
20412
+ },
20413
+ inputMode: "decimal",
20414
+ "aria-label": `${option.label} value`,
20415
+ "data-testid": "decision-card-adjust-input",
20416
+ style: {
20417
+ width: `${Math.max(3, String(text).length + 1)}ch`,
20418
+ fontSize: 26,
20419
+ fontWeight: 700,
20420
+ fontVariantNumeric: "tabular-nums",
20421
+ letterSpacing: "-0.02em",
20422
+ color: "var(--foreground)",
20423
+ border: "none",
20424
+ borderBottom: `2px solid ${accent}`,
20425
+ background: "transparent",
20426
+ outline: "none",
20427
+ padding: 0
20428
+ }
20429
+ }
20430
+ ),
20431
+ adjust.unit && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 13, fontWeight: 600, color: muted }, children: adjust.unit }),
20432
+ moved && /* @__PURE__ */ jsxRuntime.jsxs(
20433
+ "button",
20434
+ {
20435
+ type: "button",
20436
+ onClick: () => commit(suggested),
20437
+ "data-testid": "decision-card-adjust-reset",
20438
+ style: {
20439
+ marginLeft: 8,
20440
+ border: "none",
20441
+ background: "none",
20442
+ padding: 0,
20443
+ cursor: "pointer",
20444
+ fontSize: 11.5,
20445
+ fontWeight: 600,
20446
+ color: muted,
20447
+ textDecoration: "underline",
20448
+ textUnderlineOffset: 2
20449
+ },
20450
+ children: [
20451
+ "Reset to suggested (",
20452
+ formatFigure(suggested, adjust.unit),
20453
+ ")"
20454
+ ]
20455
+ }
20456
+ )
20457
+ ] }),
20458
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
20459
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", height: 16, display: "flex", alignItems: "center" }, children: [
20460
+ /* @__PURE__ */ jsxRuntime.jsx(
20461
+ "div",
20462
+ {
20463
+ "aria-hidden": "true",
20464
+ style: {
20465
+ position: "absolute",
20466
+ left: 0,
20467
+ right: 0,
20468
+ height: 4,
20469
+ borderRadius: 9999,
20470
+ background: `linear-gradient(to right, ${accent} ${pct}%, #e8e8e8 ${pct}%)`
20471
+ }
20472
+ }
20473
+ ),
20474
+ moved && /* @__PURE__ */ jsxRuntime.jsx(
20475
+ "div",
20476
+ {
20477
+ "aria-hidden": "true",
20478
+ title: `Suggested: ${formatFigure(suggested, adjust.unit)}`,
20479
+ style: {
20480
+ position: "absolute",
20481
+ left: `${suggestedPct}%`,
20482
+ transform: "translateX(-50%)",
20483
+ width: 2,
20484
+ height: 10,
20485
+ borderRadius: 1,
20486
+ background: muted,
20487
+ opacity: 0.55
20488
+ }
20489
+ }
20490
+ ),
20491
+ /* @__PURE__ */ jsxRuntime.jsx(
20492
+ "input",
20493
+ {
20494
+ type: "range",
20495
+ className: "dc-range",
20496
+ min: adjust.min,
20497
+ max: adjust.max,
20498
+ step,
20499
+ value,
20500
+ onChange: (e) => commit(Number(e.target.value)),
20501
+ "aria-label": `${option.label} slider`,
20502
+ "data-testid": "decision-card-adjust-slider",
20503
+ style: { position: "relative", ["--dc-thumb"]: accent }
20504
+ }
20505
+ )
20506
+ ] }),
20507
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 10.5, fontWeight: 600, color: muted, fontVariantNumeric: "tabular-nums" }, children: [
20508
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFigure(adjust.min, adjust.unit) }),
20509
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFigure(adjust.max, adjust.unit) })
20510
+ ] })
20511
+ ] }),
20512
+ /* @__PURE__ */ jsxRuntime.jsxs(
20513
+ "button",
20514
+ {
20515
+ type: "button",
20516
+ onClick: () => onConfirm(value),
20517
+ "data-testid": "decision-card-adjust-confirm",
20518
+ style: {
20519
+ alignSelf: "flex-start",
20520
+ border: `1px solid ${accent}`,
20521
+ background: accent,
20522
+ color: "white",
20523
+ borderRadius: 8,
20524
+ fontSize: 13,
20525
+ fontWeight: 600,
20526
+ padding: "9px 16px",
20527
+ cursor: "pointer",
20528
+ fontVariantNumeric: "tabular-nums",
20529
+ transition: "opacity 0.15s"
20530
+ },
20531
+ onMouseEnter: (e) => e.currentTarget.style.opacity = "0.88",
20532
+ onMouseLeave: (e) => e.currentTarget.style.opacity = "1",
20533
+ children: [
20534
+ option.label,
20535
+ " \xB7 ",
20536
+ formatFigure(value, adjust.unit)
20537
+ ]
20538
+ }
20539
+ )
20540
+ ]
20541
+ }
20542
+ );
20543
+ }
20129
20544
  function DecisionCardRenderer({
20130
20545
  data,
20131
20546
  resolved = null,
20132
20547
  onResolve,
20133
- onOpenSource
20548
+ onOpenSource,
20549
+ eyebrow
20134
20550
  }) {
20135
- var _a2, _b;
20551
+ var _a2, _b, _c;
20136
20552
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
20137
20553
  const rootRef = React45__default.default.useRef(null);
20138
20554
  const width = useContainerWidth2(rootRef);
20139
20555
  const stacked = width > 0 && width < STACK_BELOW;
20556
+ const [adjustingIdx, setAdjustingIdx] = React45__default.default.useState(null);
20140
20557
  const options = (_a2 = data.options) != null ? _a2 : [];
20141
20558
  const recommendedIdx = Math.max(
20142
20559
  0,
@@ -20235,7 +20652,7 @@ function DecisionCardRenderer({
20235
20652
  },
20236
20653
  children: [
20237
20654
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { minWidth: 0, display: "flex", flexDirection: "column", gap: 4 }, children: [
20238
- /* @__PURE__ */ jsxRuntime.jsx(
20655
+ eyebrow === null ? null : /* @__PURE__ */ jsxRuntime.jsx(
20239
20656
  "span",
20240
20657
  {
20241
20658
  style: {
@@ -20245,7 +20662,7 @@ function DecisionCardRenderer({
20245
20662
  fontWeight: 700,
20246
20663
  color: ACCENT2
20247
20664
  },
20248
- children: data.decision_type ? `Decision needs you \xB7 ${data.decision_type}` : "Decision needs you"
20665
+ children: eyebrow !== void 0 ? eyebrow : data.decision_type ? `Decision needs you \xB7 ${data.decision_type}` : "Decision needs you"
20249
20666
  }
20250
20667
  ),
20251
20668
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -20291,7 +20708,20 @@ function DecisionCardRenderer({
20291
20708
  ]
20292
20709
  }
20293
20710
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
20294
- /* @__PURE__ */ jsxRuntime.jsx(
20711
+ adjustingIdx != null && ((_b = options[adjustingIdx]) == null ? void 0 : _b.adjust) ? /* @__PURE__ */ jsxRuntime.jsx(
20712
+ ValueAdjuster,
20713
+ {
20714
+ option: options[adjustingIdx],
20715
+ accent: ACCENT2,
20716
+ border: BORDER4,
20717
+ muted: MUTED2,
20718
+ onBack: () => setAdjustingIdx(null),
20719
+ onConfirm: (value) => {
20720
+ setAdjustingIdx(null);
20721
+ onResolve == null ? void 0 : onResolve(options[adjustingIdx].label, value);
20722
+ }
20723
+ }
20724
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
20295
20725
  "div",
20296
20726
  {
20297
20727
  style: {
@@ -20301,15 +20731,21 @@ function DecisionCardRenderer({
20301
20731
  gap: 8
20302
20732
  },
20303
20733
  children: options.map((opt, idx) => {
20304
- var _a3;
20734
+ var _a3, _b2;
20305
20735
  const primary = idx === recommendedIdx;
20306
- return /* @__PURE__ */ jsxRuntime.jsx(
20736
+ const adjustable = Boolean(opt.adjust);
20737
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20307
20738
  "button",
20308
20739
  {
20309
20740
  type: "button",
20310
- onClick: () => onResolve == null ? void 0 : onResolve(opt.label),
20741
+ onClick: () => adjustable ? setAdjustingIdx(idx) : onResolve == null ? void 0 : onResolve(opt.label),
20742
+ "data-adjustable": adjustable || void 0,
20311
20743
  style: {
20312
20744
  width: stacked ? "100%" : "auto",
20745
+ display: "inline-flex",
20746
+ alignItems: "center",
20747
+ justifyContent: stacked ? "flex-start" : "center",
20748
+ gap: 7,
20313
20749
  textAlign: stacked ? "left" : "center",
20314
20750
  border: `1px solid ${primary ? ACCENT2 : BORDER4}`,
20315
20751
  background: primary ? ACCENT2 : "white",
@@ -20337,7 +20773,28 @@ function DecisionCardRenderer({
20337
20773
  e.currentTarget.style.background = "white";
20338
20774
  }
20339
20775
  },
20340
- children: opt.label
20776
+ children: [
20777
+ opt.label,
20778
+ adjustable && typeof opt.value === "number" && /* @__PURE__ */ jsxRuntime.jsxs(
20779
+ "span",
20780
+ {
20781
+ style: {
20782
+ fontSize: 11.5,
20783
+ fontWeight: 700,
20784
+ fontVariantNumeric: "tabular-nums",
20785
+ padding: "1px 7px",
20786
+ borderRadius: 9999,
20787
+ background: primary ? "rgba(255,255,255,0.22)" : "#f2f2f2",
20788
+ color: primary ? "white" : MUTED2,
20789
+ lineHeight: 1.5
20790
+ },
20791
+ children: [
20792
+ formatFigure(opt.value, (_b2 = opt.adjust) == null ? void 0 : _b2.unit),
20793
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { marginLeft: 4, opacity: 0.8 }, children: "\u270E" })
20794
+ ]
20795
+ }
20796
+ )
20797
+ ]
20341
20798
  },
20342
20799
  (_a3 = opt.id) != null ? _a3 : opt.label
20343
20800
  );
@@ -20376,7 +20833,7 @@ function DecisionCardRenderer({
20376
20833
  strokeLinejoin: "round"
20377
20834
  }
20378
20835
  ) }),
20379
- (_b = data.source.label) != null ? _b : "View source for this figure"
20836
+ (_c = data.source.label) != null ? _c : "View source for this figure"
20380
20837
  ]
20381
20838
  }
20382
20839
  )
@@ -20385,20 +20842,27 @@ function DecisionCardRenderer({
20385
20842
  }
20386
20843
  );
20387
20844
  }
20845
+ function composeResolution(p, option, value) {
20846
+ var _a2, _b, _c;
20847
+ if (value == null) return option;
20848
+ const unit = (_c = (_b = ((_a2 = p.options) != null ? _a2 : []).find((o) => o.label === option)) == null ? void 0 : _b.adjust) == null ? void 0 : _c.unit;
20849
+ return `${option} \xB7 ${formatFigure(value, unit)}`;
20850
+ }
20388
20851
  function DecisionCardResolver(p) {
20389
- var _a2, _b, _c, _d;
20852
+ var _a2, _b;
20390
20853
  const { resolvedDecisions, onDecisionResolve, onDecisionSource } = useGenUIInteraction();
20391
20854
  const decisionId = (_a2 = p.id) != null ? _a2 : p.title;
20392
20855
  const hostResolved = resolvedDecisions == null ? void 0 : resolvedDecisions[decisionId];
20393
- const initial = (_c = hostResolved != null ? hostResolved : (_b = p.resolved) == null ? void 0 : _b.option) != null ? _c : null;
20856
+ const initial = hostResolved != null ? hostResolved : p.resolved ? composeResolution(p, p.resolved.option, p.resolved.value) : null;
20394
20857
  const [localResolved, setLocalResolved] = React45__default.default.useState(initial);
20395
20858
  React45__default.default.useEffect(() => {
20396
20859
  if (hostResolved !== void 0) setLocalResolved(hostResolved);
20397
20860
  }, [hostResolved]);
20398
20861
  const resolved = hostResolved != null ? hostResolved : localResolved;
20399
- const handleResolve = (option) => {
20400
- setLocalResolved(option);
20401
- onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, option);
20862
+ const handleResolve = (option, value) => {
20863
+ const resolution = composeResolution(p, option, value);
20864
+ setLocalResolved(resolution);
20865
+ onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, resolution);
20402
20866
  };
20403
20867
  const handleSource = () => {
20404
20868
  var _a3;
@@ -20407,7 +20871,7 @@ function DecisionCardResolver(p) {
20407
20871
  window.open(p.source.url, "_blank", "noopener,noreferrer");
20408
20872
  }
20409
20873
  };
20410
- return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_d = p.title) != null ? _d : "decision-card", children: /* @__PURE__ */ jsxRuntime.jsx(
20874
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_b = p.title) != null ? _b : "decision-card", children: /* @__PURE__ */ jsxRuntime.jsx(
20411
20875
  DecisionCardRenderer,
20412
20876
  {
20413
20877
  data: p,
@@ -20418,6 +20882,302 @@ function DecisionCardResolver(p) {
20418
20882
  ) });
20419
20883
  }
20420
20884
  init_ThemeContext();
20885
+ var GREEN4 = "#15803d";
20886
+ var KEYFRAMES3 = `
20887
+ @keyframes dqSettle{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}
20888
+ .dq-settle{animation:dqSettle 0.24s cubic-bezier(0.22,1,0.36,1) both}
20889
+ @keyframes dqFocus{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:none}}
20890
+ .dq-focus{animation:dqFocus 0.28s cubic-bezier(0.22,1,0.36,1) both}
20891
+ @media (prefers-reduced-motion: reduce){
20892
+ .dq-settle,.dq-focus{animation:none !important;opacity:1 !important;transform:none !important}
20893
+ }`;
20894
+ function figureOf(item, decision) {
20895
+ var _a2, _b, _c;
20896
+ if (decision.value == null) return decision.option;
20897
+ 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;
20898
+ return `${decision.option} \xB7 ${formatFigure(decision.value, unit)}`;
20899
+ }
20900
+ function composeQueueMessage(items, decisions) {
20901
+ const lines = items.map((item, i) => {
20902
+ const d = decisions[i];
20903
+ return `${i + 1}. ${item.title} \u2192 ${d ? figureOf(item, d) : "(undecided)"}`;
20904
+ });
20905
+ const done = decisions.filter(Boolean).length;
20906
+ return `Decisions (${done}/${items.length}):
20907
+ ${lines.join("\n")}`;
20908
+ }
20909
+ function Check({ size, color }) {
20910
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 13l4 4L19 7", stroke: color, strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round" }) });
20911
+ }
20912
+ function amountChip(item) {
20913
+ if (typeof item.amount !== "number") return null;
20914
+ const abs = Math.abs(item.amount);
20915
+ const sign = item.amount < 0 ? "-" : "";
20916
+ if (abs >= 1e6) return `${sign}$${(abs / 1e6).toFixed(abs >= 1e7 ? 0 : 1)}M`;
20917
+ if (abs >= 1e3) return `${sign}$${(abs / 1e3).toFixed(abs >= 1e4 ? 0 : 1)}K`;
20918
+ return `${sign}$${abs}`;
20919
+ }
20920
+ function DecisionQueueRenderer({ data, submitted = null, onSubmit }) {
20921
+ var _a2;
20922
+ const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2 } = useTheme();
20923
+ const items = (_a2 = data.items) != null ? _a2 : [];
20924
+ const [decisions, setDecisions] = React45__default.default.useState(
20925
+ () => items.map(() => void 0)
20926
+ );
20927
+ const firstUndecided = decisions.findIndex((d) => !d);
20928
+ const [focusIdx, setFocusIdx] = React45__default.default.useState(firstUndecided >= 0 ? firstUndecided : null);
20929
+ const isSubmitted = submitted != null;
20930
+ const shown = isSubmitted ? items.map(
20931
+ (item, i) => {
20932
+ var _a3;
20933
+ return (_a3 = submitted.find((d) => d.id && d.id === item.id || d.title === item.title)) != null ? _a3 : submitted[i];
20934
+ }
20935
+ ) : decisions;
20936
+ const decidedCount = shown.filter(Boolean).length;
20937
+ const allDecided = decidedCount === items.length;
20938
+ const decide = (idx, option, value) => {
20939
+ const item = items[idx];
20940
+ const next = decisions.slice();
20941
+ next[idx] = { id: item.id, title: item.title, option, value };
20942
+ setDecisions(next);
20943
+ const order = [...Array(items.length).keys()];
20944
+ const after = order.slice(idx + 1).concat(order.slice(0, idx + 1));
20945
+ const target = after.find((j) => j !== idx && !next[j]);
20946
+ setFocusIdx(target != null ? target : null);
20947
+ };
20948
+ const handleSubmit = () => {
20949
+ if (!allDecided || isSubmitted) return;
20950
+ const final = decisions;
20951
+ onSubmit == null ? void 0 : onSubmit(final, composeQueueMessage(items, final));
20952
+ };
20953
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20954
+ "div",
20955
+ {
20956
+ "data-testid": "decision-queue",
20957
+ "data-submitted": isSubmitted || void 0,
20958
+ style: {
20959
+ position: "relative",
20960
+ width: "100%",
20961
+ minWidth: 0,
20962
+ boxSizing: "border-box",
20963
+ borderRadius: "0.75rem",
20964
+ border: `1px solid ${BORDER4}`,
20965
+ background: "white",
20966
+ boxShadow: "0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.04)",
20967
+ padding: "16px 18px",
20968
+ display: "flex",
20969
+ flexDirection: "column",
20970
+ gap: 12,
20971
+ overflow: "hidden"
20972
+ },
20973
+ children: [
20974
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: KEYFRAMES3 }),
20975
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 3 }, children: [
20976
+ /* @__PURE__ */ jsxRuntime.jsx(
20977
+ "span",
20978
+ {
20979
+ style: {
20980
+ fontSize: 10.5,
20981
+ textTransform: "uppercase",
20982
+ letterSpacing: "0.07em",
20983
+ fontWeight: 700,
20984
+ color: isSubmitted ? GREEN4 : ACCENT2
20985
+ },
20986
+ children: isSubmitted ? "Decisions submitted" : "Decisions need you"
20987
+ }
20988
+ ),
20989
+ data.title && /* @__PURE__ */ jsxRuntime.jsx(
20990
+ "p",
20991
+ {
20992
+ style: {
20993
+ fontFamily: "var(--font-serif)",
20994
+ fontSize: 16,
20995
+ fontWeight: 400,
20996
+ color: "var(--foreground)",
20997
+ letterSpacing: "-0.01em",
20998
+ margin: 0,
20999
+ lineHeight: 1.25
21000
+ },
21001
+ children: data.title
21002
+ }
21003
+ ),
21004
+ data.description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 12.5, color: MUTED2, margin: 0, lineHeight: 1.45 }, children: data.description })
21005
+ ] }),
21006
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: items.map((item, idx) => {
21007
+ var _a3, _b, _c;
21008
+ const decision = shown[idx];
21009
+ const focused = !isSubmitted && focusIdx === idx;
21010
+ if (focused) {
21011
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "dq-focus", "data-testid": `decision-queue-focus-${idx}`, children: /* @__PURE__ */ jsxRuntime.jsx(
21012
+ DecisionCardRenderer,
21013
+ {
21014
+ data: __spreadValues({ type: "decision-card" }, item),
21015
+ resolved: null,
21016
+ onResolve: (option, value) => decide(idx, option, value),
21017
+ eyebrow: `${idx + 1} of ${items.length}${item.decision_type ? ` \xB7 ${item.decision_type}` : ""}`
21018
+ }
21019
+ ) }, (_a3 = item.id) != null ? _a3 : `q-${idx}`);
21020
+ }
21021
+ if (decision) {
21022
+ return /* @__PURE__ */ jsxRuntime.jsxs(
21023
+ "button",
21024
+ {
21025
+ type: "button",
21026
+ className: "dq-settle",
21027
+ onClick: isSubmitted ? void 0 : () => setFocusIdx(idx),
21028
+ disabled: isSubmitted,
21029
+ title: isSubmitted ? void 0 : "Change this decision",
21030
+ "data-testid": `decision-queue-receipt-${idx}`,
21031
+ style: {
21032
+ display: "flex",
21033
+ alignItems: "center",
21034
+ gap: 8,
21035
+ width: "100%",
21036
+ textAlign: "left",
21037
+ border: "1px solid #dcfce7",
21038
+ background: "#f6fef9",
21039
+ borderRadius: 8,
21040
+ padding: "7px 11px",
21041
+ cursor: isSubmitted ? "default" : "pointer",
21042
+ font: "inherit"
21043
+ },
21044
+ children: [
21045
+ /* @__PURE__ */ jsxRuntime.jsx(Check, { size: 13, color: GREEN4 }),
21046
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12.5, fontWeight: 600, color: "var(--foreground)", minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: item.title }),
21047
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { color: MUTED2, fontSize: 12 }, children: "\u2192" }),
21048
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12.5, fontWeight: 600, color: GREEN4, fontVariantNumeric: "tabular-nums", whiteSpace: "nowrap" }, children: figureOf(item, decision) }),
21049
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 } }),
21050
+ !isSubmitted && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 11, fontWeight: 600, color: MUTED2 }, children: "Change" })
21051
+ ]
21052
+ },
21053
+ (_b = item.id) != null ? _b : `q-${idx}`
21054
+ );
21055
+ }
21056
+ return /* @__PURE__ */ jsxRuntime.jsxs(
21057
+ "button",
21058
+ {
21059
+ type: "button",
21060
+ onClick: isSubmitted ? void 0 : () => setFocusIdx(idx),
21061
+ disabled: isSubmitted,
21062
+ "data-testid": `decision-queue-upcoming-${idx}`,
21063
+ style: {
21064
+ display: "flex",
21065
+ alignItems: "center",
21066
+ gap: 8,
21067
+ width: "100%",
21068
+ textAlign: "left",
21069
+ border: `1px dashed ${BORDER4}`,
21070
+ background: "white",
21071
+ borderRadius: 8,
21072
+ padding: "7px 11px",
21073
+ cursor: isSubmitted ? "default" : "pointer",
21074
+ font: "inherit",
21075
+ opacity: 0.75
21076
+ },
21077
+ children: [
21078
+ /* @__PURE__ */ jsxRuntime.jsx(
21079
+ "span",
21080
+ {
21081
+ "aria-hidden": "true",
21082
+ style: { width: 13, height: 13, borderRadius: "50%", border: `1.5px solid ${MUTED2}`, flexShrink: 0, boxSizing: "border-box" }
21083
+ }
21084
+ ),
21085
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: 12.5, fontWeight: 600, color: MUTED2, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
21086
+ item.decision_type ? `${item.decision_type} \xB7 ` : "",
21087
+ item.title
21088
+ ] }),
21089
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 } }),
21090
+ amountChip(item) && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 11.5, fontWeight: 700, color: MUTED2, fontVariantNumeric: "tabular-nums" }, children: amountChip(item) })
21091
+ ]
21092
+ },
21093
+ (_c = item.id) != null ? _c : `q-${idx}`
21094
+ );
21095
+ }) }),
21096
+ /* @__PURE__ */ jsxRuntime.jsxs(
21097
+ "div",
21098
+ {
21099
+ style: {
21100
+ display: "flex",
21101
+ alignItems: "center",
21102
+ gap: 10,
21103
+ paddingTop: 10,
21104
+ borderTop: `1px solid #f0f0f0`
21105
+ },
21106
+ children: [
21107
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-flex", gap: 4 }, "aria-hidden": "true", children: items.map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
21108
+ "span",
21109
+ {
21110
+ style: {
21111
+ width: 7,
21112
+ height: 7,
21113
+ borderRadius: "50%",
21114
+ background: shown[i] ? isSubmitted ? GREEN4 : ACCENT2 : "#e8e8e8",
21115
+ transition: "background 0.2s"
21116
+ }
21117
+ },
21118
+ `dot-${i}`
21119
+ )) }),
21120
+ /* @__PURE__ */ jsxRuntime.jsxs(
21121
+ "span",
21122
+ {
21123
+ style: { fontSize: 11.5, fontWeight: 600, color: MUTED2, fontVariantNumeric: "tabular-nums" },
21124
+ "data-testid": "decision-queue-progress",
21125
+ children: [
21126
+ decidedCount,
21127
+ "/",
21128
+ items.length,
21129
+ " decided"
21130
+ ]
21131
+ }
21132
+ ),
21133
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 } }),
21134
+ isSubmitted ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 6, fontSize: 12.5, fontWeight: 600, color: GREEN4 }, children: [
21135
+ /* @__PURE__ */ jsxRuntime.jsx(Check, { size: 14, color: GREEN4 }),
21136
+ "Submitted"
21137
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
21138
+ "button",
21139
+ {
21140
+ type: "button",
21141
+ onClick: handleSubmit,
21142
+ disabled: !allDecided,
21143
+ "data-testid": "decision-queue-submit",
21144
+ style: {
21145
+ border: `1px solid ${allDecided ? ACCENT2 : BORDER4}`,
21146
+ background: allDecided ? ACCENT2 : "#f6f6f6",
21147
+ color: allDecided ? "white" : MUTED2,
21148
+ borderRadius: 8,
21149
+ fontSize: 13,
21150
+ fontWeight: 600,
21151
+ padding: "8px 16px",
21152
+ cursor: allDecided ? "pointer" : "default",
21153
+ fontVariantNumeric: "tabular-nums",
21154
+ transition: "background 0.15s, border-color 0.15s, color 0.15s"
21155
+ },
21156
+ children: data.submit_label || `Submit ${items.length} decision${items.length === 1 ? "" : "s"}`
21157
+ }
21158
+ )
21159
+ ]
21160
+ }
21161
+ )
21162
+ ]
21163
+ }
21164
+ );
21165
+ }
21166
+ function DecisionQueueResolver(p) {
21167
+ var _a2, _b, _c, _d, _e, _f;
21168
+ const { resolvedDecisions, onDecisionQueueSubmit } = useGenUIInteraction();
21169
+ const queueId = (_b = (_a2 = p.id) != null ? _a2 : p.title) != null ? _b : "decision-queue";
21170
+ const replayed = (_d = (_c = p.resolved) == null ? void 0 : _c.decisions) != null ? _d : null;
21171
+ const [localSubmitted, setLocalSubmitted] = React45__default.default.useState(null);
21172
+ const hostLocked = (resolvedDecisions == null ? void 0 : resolvedDecisions[queueId]) != null;
21173
+ const submitted = (_e = replayed != null ? replayed : localSubmitted) != null ? _e : hostLocked ? [] : null;
21174
+ const handleSubmit = (decisions, message) => {
21175
+ setLocalSubmitted(decisions);
21176
+ onDecisionQueueSubmit == null ? void 0 : onDecisionQueueSubmit(queueId, decisions, message);
21177
+ };
21178
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_f = p.title) != null ? _f : "decision-queue", children: /* @__PURE__ */ jsxRuntime.jsx(DecisionQueueRenderer, { data: p, submitted, onSubmit: handleSubmit }) });
21179
+ }
21180
+ init_ThemeContext();
20421
21181
  var CONNECTED_GREEN3 = "#15803d";
20422
21182
  var CONNECTED_GREEN_BG = "#dcfce7";
20423
21183
  var PENDING_AMBER = "#92400e";
@@ -20849,6 +21609,8 @@ function resolveUI(rawPayload) {
20849
21609
  return /* @__PURE__ */ jsxRuntime.jsx(DocumentFieldExtractionResolver, __spreadValues({}, payload));
20850
21610
  case "decision-card":
20851
21611
  return /* @__PURE__ */ jsxRuntime.jsx(DecisionCardResolver, __spreadValues({}, payload));
21612
+ case "decision-queue":
21613
+ return /* @__PURE__ */ jsxRuntime.jsx(DecisionQueueResolver, __spreadValues({}, payload));
20852
21614
  case "tabby-auth":
20853
21615
  return /* @__PURE__ */ jsxRuntime.jsx(TabbyAuthResolver, __spreadValues({}, payload));
20854
21616
  default: {
@@ -22204,7 +22966,9 @@ function BlockForm({
22204
22966
  onEntityCreate,
22205
22967
  hideActions,
22206
22968
  dense,
22207
- variant = "form"
22969
+ variant = "form",
22970
+ fieldSuggestions,
22971
+ onApplySuggestion
22208
22972
  }) {
22209
22973
  var _a2;
22210
22974
  const t = useTheme();
@@ -22235,20 +22999,85 @@ function BlockForm({
22235
22999
  }
22236
23000
  ),
22237
23001
  ((_a2 = block.context) == null ? void 0 : _a2.type) && /* @__PURE__ */ jsxRuntime.jsx(ContextSlot, { payload: block.context }),
22238
- /* @__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(
22239
- FieldRenderer,
22240
- {
22241
- field,
22242
- value: state.getValue(block.id, field.name),
22243
- onChange: (v) => state.setFieldValue(block.id, field.name, v),
22244
- disabled,
22245
- error: state.getError(block.id, field.name),
22246
- dense,
22247
- onFileUpload,
22248
- onEntitySearch,
22249
- onEntityCreate
22250
- }
22251
- ) }, `${block.id}:${field.name}`)) }),
23002
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: dense ? "8px" : isEscalation ? "10px" : "12px" }, children: (block.fields || []).map((field) => {
23003
+ var _a3;
23004
+ const suggestion = (fieldSuggestions || []).filter((sg) => {
23005
+ var _a4;
23006
+ return sg.field === field.name && ((_a4 = sg.block_id) != null ? _a4 : block.id) === block.id;
23007
+ }).slice(-1)[0];
23008
+ const current = state.getValue(block.id, field.name);
23009
+ const showSuggestion = suggestion != null && current !== suggestion.value;
23010
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-field-key": fieldKey(block.id, field.name), children: [
23011
+ /* @__PURE__ */ jsxRuntime.jsx(
23012
+ FieldRenderer,
23013
+ {
23014
+ field,
23015
+ value: current,
23016
+ onChange: (v) => state.setFieldValue(block.id, field.name, v),
23017
+ disabled,
23018
+ error: state.getError(block.id, field.name),
23019
+ dense,
23020
+ onFileUpload,
23021
+ onEntitySearch,
23022
+ onEntityCreate
23023
+ }
23024
+ ),
23025
+ showSuggestion && !disabled ? /* @__PURE__ */ jsxRuntime.jsxs(
23026
+ "div",
23027
+ {
23028
+ "data-testid": `builder-suggestion-${field.name}`,
23029
+ style: {
23030
+ display: "flex",
23031
+ alignItems: "center",
23032
+ flexWrap: "wrap",
23033
+ gap: "6px",
23034
+ marginTop: "5px",
23035
+ padding: "5px 9px",
23036
+ borderRadius: "8px",
23037
+ border: `1px dashed ${t.BORDER}`,
23038
+ background: "#fafafa",
23039
+ fontSize: "11.5px",
23040
+ lineHeight: 1.4
23041
+ },
23042
+ children: [
23043
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { color: t.ACCENT, fontSize: "11px" }, children: "\u2726" }),
23044
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: t.MUTED, fontWeight: 600 }, children: [
23045
+ "Suggested:",
23046
+ " ",
23047
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--foreground)", fontVariantNumeric: "tabular-nums" }, children: (_a3 = suggestion.label) != null ? _a3 : String(suggestion.value) })
23048
+ ] }),
23049
+ suggestion.note ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: t.MUTED }, children: [
23050
+ "\xB7 ",
23051
+ suggestion.note
23052
+ ] }) : null,
23053
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 } }),
23054
+ /* @__PURE__ */ jsxRuntime.jsx(
23055
+ "button",
23056
+ {
23057
+ type: "button",
23058
+ "data-testid": `builder-suggestion-apply-${field.name}`,
23059
+ onClick: () => {
23060
+ state.setFieldValue(block.id, field.name, suggestion.value);
23061
+ onApplySuggestion == null ? void 0 : onApplySuggestion(suggestion);
23062
+ },
23063
+ style: {
23064
+ font: "inherit",
23065
+ fontSize: "11.5px",
23066
+ fontWeight: 700,
23067
+ color: t.ACCENT,
23068
+ background: "transparent",
23069
+ border: "none",
23070
+ padding: 0,
23071
+ cursor: "pointer"
23072
+ },
23073
+ children: "Apply"
23074
+ }
23075
+ )
23076
+ ]
23077
+ }
23078
+ ) : null
23079
+ ] }, `${block.id}:${field.name}`);
23080
+ }) }),
22252
23081
  hideActions ? null : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "6px", paddingTop: isEscalation ? "2px" : "4px" }, children: [
22253
23082
  errorCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: "11px", fontWeight: 600, color: "#dc2626" }, children: [
22254
23083
  errorCount,
@@ -22536,7 +23365,9 @@ function BuilderFormResolver({
22536
23365
  submitRef,
22537
23366
  hideActions,
22538
23367
  dense,
22539
- onValidationError
23368
+ onValidationError,
23369
+ fieldSuggestions,
23370
+ onApplySuggestion
22540
23371
  }) {
22541
23372
  var _a2;
22542
23373
  const state = useBuilderState(builder.blocks);
@@ -22613,7 +23444,9 @@ function BuilderFormResolver({
22613
23444
  onEntitySearch,
22614
23445
  onEntityCreate,
22615
23446
  hideActions,
22616
- dense
23447
+ dense,
23448
+ fieldSuggestions,
23449
+ onApplySuggestion
22617
23450
  }
22618
23451
  );
22619
23452
  default:
@@ -22630,7 +23463,9 @@ function BuilderFormResolver({
22630
23463
  onEntitySearch,
22631
23464
  onEntityCreate,
22632
23465
  dense,
22633
- hideActions
23466
+ hideActions,
23467
+ fieldSuggestions,
23468
+ onApplySuggestion
22634
23469
  }
22635
23470
  );
22636
23471
  }