@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/renderer.cjs CHANGED
@@ -5553,7 +5553,14 @@ var decisionCardSchema = zod.z.object({
5553
5553
  zod.z.object({
5554
5554
  id: zod.z.string().optional(),
5555
5555
  label: zod.z.string(),
5556
- recommended: zod.z.boolean().optional()
5556
+ recommended: zod.z.boolean().optional(),
5557
+ value: zod.z.number().optional(),
5558
+ adjust: zod.z.object({
5559
+ min: zod.z.number(),
5560
+ max: zod.z.number(),
5561
+ step: zod.z.number().optional(),
5562
+ unit: zod.z.string().optional()
5563
+ }).optional()
5557
5564
  })
5558
5565
  ).min(1).max(5),
5559
5566
  source: zod.z.object({
@@ -5561,7 +5568,8 @@ var decisionCardSchema = zod.z.object({
5561
5568
  url: zod.z.string().optional()
5562
5569
  }).optional(),
5563
5570
  resolved: zod.z.object({
5564
- option: zod.z.string()
5571
+ option: zod.z.string(),
5572
+ value: zod.z.number().optional()
5565
5573
  }).optional()
5566
5574
  });
5567
5575
  var decisionCardTool = {
@@ -5604,13 +5612,28 @@ var decisionCardTool = {
5604
5612
  type: "array",
5605
5613
  minItems: 1,
5606
5614
  maxItems: 5,
5607
- description: "Mutually-exclusive resolution choices; mark one `recommended` to make it primary",
5615
+ 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.",
5608
5616
  items: {
5609
5617
  type: "object",
5610
5618
  properties: {
5611
5619
  id: { type: "string" },
5612
5620
  label: { type: "string" },
5613
- recommended: { type: "boolean" }
5621
+ recommended: { type: "boolean" },
5622
+ value: {
5623
+ type: "number",
5624
+ description: "Suggested numeric figure for this option (the starting point of the adjuster)"
5625
+ },
5626
+ adjust: {
5627
+ type: "object",
5628
+ description: "Allow the user to tune `value` within this inclusive range before resolving",
5629
+ properties: {
5630
+ min: { type: "number" },
5631
+ max: { type: "number" },
5632
+ step: { type: "number", description: "Increment granularity; defaults to a sensible step for the range" },
5633
+ unit: { type: "string", description: "Short unit suffix shown after the number, e.g. 'units', '%', 'hrs'" }
5634
+ },
5635
+ required: ["min", "max"]
5636
+ }
5614
5637
  },
5615
5638
  required: ["label"]
5616
5639
  }
@@ -5627,7 +5650,8 @@ var decisionCardTool = {
5627
5650
  type: "object",
5628
5651
  description: "Pre-resolved state for transcript replay",
5629
5652
  properties: {
5630
- option: { type: "string" }
5653
+ option: { type: "string" },
5654
+ value: { type: "number", description: "Adjusted figure the user confirmed, when the option was adjustable" }
5631
5655
  },
5632
5656
  required: ["option"]
5633
5657
  }
@@ -5635,6 +5659,167 @@ var decisionCardTool = {
5635
5659
  required: ["type", "title", "question", "options"]
5636
5660
  }
5637
5661
  };
5662
+ var decisionQueueItemSchema = zod.z.object({
5663
+ id: zod.z.string().optional(),
5664
+ decision_type: zod.z.string().optional(),
5665
+ title: zod.z.string(),
5666
+ question: zod.z.string(),
5667
+ amount: zod.z.number().optional(),
5668
+ currency: zod.z.string().optional(),
5669
+ amount_label: zod.z.string().optional(),
5670
+ severity: zod.z.enum(["low", "medium", "high"]).optional(),
5671
+ flags: zod.z.array(
5672
+ zod.z.object({
5673
+ field: zod.z.string().optional(),
5674
+ issue: zod.z.string(),
5675
+ severity: zod.z.enum(["low", "medium", "high"]).optional()
5676
+ })
5677
+ ).max(6).optional(),
5678
+ options: zod.z.array(
5679
+ zod.z.object({
5680
+ id: zod.z.string().optional(),
5681
+ label: zod.z.string(),
5682
+ recommended: zod.z.boolean().optional(),
5683
+ value: zod.z.number().optional(),
5684
+ adjust: zod.z.object({
5685
+ min: zod.z.number(),
5686
+ max: zod.z.number(),
5687
+ step: zod.z.number().optional(),
5688
+ unit: zod.z.string().optional()
5689
+ }).optional()
5690
+ })
5691
+ ).min(1).max(5),
5692
+ source: zod.z.object({
5693
+ label: zod.z.string().optional(),
5694
+ url: zod.z.string().optional()
5695
+ }).optional()
5696
+ });
5697
+ var decisionQueueSchema = zod.z.object({
5698
+ type: zod.z.literal("decision-queue"),
5699
+ id: zod.z.string().optional(),
5700
+ title: zod.z.string().optional(),
5701
+ description: zod.z.string().optional(),
5702
+ submit_label: zod.z.string().optional(),
5703
+ items: zod.z.array(decisionQueueItemSchema).min(2).max(12),
5704
+ resolved: zod.z.object({
5705
+ decisions: zod.z.array(
5706
+ zod.z.object({
5707
+ id: zod.z.string().optional(),
5708
+ title: zod.z.string(),
5709
+ option: zod.z.string(),
5710
+ value: zod.z.number().optional()
5711
+ })
5712
+ )
5713
+ }).optional()
5714
+ });
5715
+ var OPTION_ITEM_JSON = {
5716
+ type: "object",
5717
+ properties: {
5718
+ id: { type: "string" },
5719
+ label: { type: "string" },
5720
+ recommended: { type: "boolean" },
5721
+ value: {
5722
+ type: "number",
5723
+ description: "Suggested numeric figure for this option (starting point of the adjuster)"
5724
+ },
5725
+ adjust: {
5726
+ type: "object",
5727
+ description: "Allow the user to tune `value` within this inclusive range before deciding",
5728
+ properties: {
5729
+ min: { type: "number" },
5730
+ max: { type: "number" },
5731
+ step: { type: "number" },
5732
+ unit: { type: "string", description: "Short unit suffix, e.g. 'units', '%', 'hrs'" }
5733
+ },
5734
+ required: ["min", "max"]
5735
+ }
5736
+ },
5737
+ required: ["label"]
5738
+ };
5739
+ var decisionQueueTool = {
5740
+ name: "render_decision_queue",
5741
+ 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.",
5742
+ input_schema: {
5743
+ type: "object",
5744
+ properties: {
5745
+ type: { type: "string", enum: ["decision-queue"] },
5746
+ id: { type: "string", description: "Stable id for update-in-place rendering" },
5747
+ title: {
5748
+ type: "string",
5749
+ description: "Batch headline shown in the header, e.g. 'Reconciliation exceptions'"
5750
+ },
5751
+ description: { type: "string", description: "One-line context above the queue" },
5752
+ submit_label: { type: "string", description: "CTA label; defaults to 'Submit N decisions'" },
5753
+ items: {
5754
+ type: "array",
5755
+ minItems: 2,
5756
+ maxItems: 12,
5757
+ description: "The pending judgments, in the order the user should take them. Each is a full decision-card body (no `type`).",
5758
+ items: {
5759
+ type: "object",
5760
+ properties: {
5761
+ id: { type: "string" },
5762
+ decision_type: {
5763
+ type: "string",
5764
+ description: "Short category eyebrow, e.g. 'Duplicate', 'Capitalization'"
5765
+ },
5766
+ title: { type: "string" },
5767
+ question: { type: "string" },
5768
+ amount: { type: "number" },
5769
+ currency: { type: "string" },
5770
+ amount_label: { type: "string" },
5771
+ severity: { type: "string", enum: ["low", "medium", "high"] },
5772
+ flags: {
5773
+ type: "array",
5774
+ maxItems: 6,
5775
+ items: {
5776
+ type: "object",
5777
+ properties: {
5778
+ field: { type: "string" },
5779
+ issue: { type: "string" },
5780
+ severity: { type: "string", enum: ["low", "medium", "high"] }
5781
+ },
5782
+ required: ["issue"]
5783
+ }
5784
+ },
5785
+ options: {
5786
+ type: "array",
5787
+ minItems: 1,
5788
+ maxItems: 5,
5789
+ items: OPTION_ITEM_JSON
5790
+ },
5791
+ source: {
5792
+ type: "object",
5793
+ properties: { label: { type: "string" }, url: { type: "string" } }
5794
+ }
5795
+ },
5796
+ required: ["title", "question", "options"]
5797
+ }
5798
+ },
5799
+ resolved: {
5800
+ type: "object",
5801
+ description: "Pre-resolved state for transcript replay",
5802
+ properties: {
5803
+ decisions: {
5804
+ type: "array",
5805
+ items: {
5806
+ type: "object",
5807
+ properties: {
5808
+ id: { type: "string" },
5809
+ title: { type: "string" },
5810
+ option: { type: "string" },
5811
+ value: { type: "number" }
5812
+ },
5813
+ required: ["title", "option"]
5814
+ }
5815
+ }
5816
+ },
5817
+ required: ["decisions"]
5818
+ }
5819
+ },
5820
+ required: ["type", "items"]
5821
+ }
5822
+ };
5638
5823
  var tabbyAuthSchema = zod.z.object({
5639
5824
  type: zod.z.literal("tabby-auth"),
5640
5825
  app: zod.z.string(),
@@ -5727,6 +5912,7 @@ var schemaRegistry = {
5727
5912
  "workflow-stepper": { schema: workflowStepperSchema, tool: workflowStepperTool },
5728
5913
  "document-field-extraction": { schema: documentFieldExtractionSchema, tool: documentFieldExtractionTool },
5729
5914
  "decision-card": { schema: decisionCardSchema, tool: decisionCardTool },
5915
+ "decision-queue": { schema: decisionQueueSchema, tool: decisionQueueTool },
5730
5916
  "tabby-auth": { schema: tabbyAuthSchema, tool: tabbyAuthTool }
5731
5917
  };
5732
5918
 
@@ -6465,17 +6651,17 @@ function SparklineTableResolver(p) {
6465
6651
  // src/composites/heatmap-table/resolver.tsx
6466
6652
  init_theme();
6467
6653
  init_ThemeContext();
6468
- function heatColor(z61) {
6469
- const clamped = Math.max(-3, Math.min(3, z61));
6654
+ function heatColor(z62) {
6655
+ const clamped = Math.max(-3, Math.min(3, z62));
6470
6656
  const abs = Math.abs(clamped);
6471
6657
  const lightness = 95 - abs * 8;
6472
6658
  const hue = clamped >= 0 ? 142 : 0;
6473
6659
  return `hsl(${hue} 60% ${lightness}%)`;
6474
6660
  }
6475
- function heatTextColor(z61) {
6476
- const abs = Math.abs(z61);
6477
- if (abs > 2) return z61 >= 0 ? "#14532d" : "#7f1d1d";
6478
- if (abs > 1) return z61 >= 0 ? "#166534" : "#991b1b";
6661
+ function heatTextColor(z62) {
6662
+ const abs = Math.abs(z62);
6663
+ if (abs > 2) return z62 >= 0 ? "#14532d" : "#7f1d1d";
6664
+ if (abs > 1) return z62 >= 0 ? "#166534" : "#991b1b";
6479
6665
  return "var(--foreground)";
6480
6666
  }
6481
6667
  var th2 = {
@@ -17523,7 +17709,8 @@ var DEFAULT_INTERACTION = {
17523
17709
  onStepSelect: void 0,
17524
17710
  resolvedDecisions: void 0,
17525
17711
  onDecisionResolve: void 0,
17526
- onDecisionSource: void 0
17712
+ onDecisionSource: void 0,
17713
+ onDecisionQueueSubmit: void 0
17527
17714
  };
17528
17715
  var GenUIInteractionContext = React45.createContext(DEFAULT_INTERACTION);
17529
17716
  function useGenUIInteraction() {
@@ -19918,8 +20105,15 @@ function useContainerWidth2(ref) {
19918
20105
  var KEYFRAMES2 = `
19919
20106
  @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
19920
20107
  .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
20108
+ .dc-range{-webkit-appearance:none;appearance:none;width:100%;height:4px;border-radius:9999px;outline:none;cursor:pointer;background:transparent}
20109
+ .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}
20110
+ .dc-range::-webkit-slider-thumb:hover{transform:scale(1.12)}
20111
+ .dc-range:active::-webkit-slider-thumb{cursor:grabbing}
20112
+ .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}
20113
+ .dc-range::-moz-range-track{height:4px;border-radius:9999px;background:transparent}
19921
20114
  @media (prefers-reduced-motion: reduce){
19922
20115
  .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
20116
+ .dc-range::-webkit-slider-thumb{transition:none}
19923
20117
  }`;
19924
20118
  function SparkCheck({ size, color }) {
19925
20119
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -19965,17 +20159,240 @@ function FlagPill({ flag }) {
19965
20159
  }
19966
20160
  );
19967
20161
  }
20162
+ function formatFigure(value, unit) {
20163
+ const body = Number.isInteger(value) ? `${value}` : `${Math.round(value * 100) / 100}`;
20164
+ if (!unit) return body;
20165
+ return unit === "%" ? `${body}%` : `${body} ${unit}`;
20166
+ }
20167
+ function clampToRange(raw, adjust) {
20168
+ var _a;
20169
+ const step = (_a = adjust.step) != null ? _a : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
20170
+ const snapped = Math.round((raw - adjust.min) / step) * step + adjust.min;
20171
+ const fixed = Math.round(snapped * 1e6) / 1e6;
20172
+ return Math.min(adjust.max, Math.max(adjust.min, fixed));
20173
+ }
20174
+ function ValueAdjuster({
20175
+ option,
20176
+ accent,
20177
+ border,
20178
+ muted,
20179
+ onConfirm,
20180
+ onBack
20181
+ }) {
20182
+ var _a, _b;
20183
+ const adjust = option.adjust;
20184
+ const suggested = clampToRange((_a = option.value) != null ? _a : adjust.min, adjust);
20185
+ const [value, setValue] = React45__default.default.useState(suggested);
20186
+ const [text, setText] = React45__default.default.useState(String(suggested));
20187
+ const step = (_b = adjust.step) != null ? _b : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
20188
+ const pct = adjust.max > adjust.min ? (value - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
20189
+ const suggestedPct = adjust.max > adjust.min ? (suggested - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
20190
+ const moved = value !== suggested;
20191
+ const commit = (raw) => {
20192
+ const v = clampToRange(raw, adjust);
20193
+ setValue(v);
20194
+ setText(String(v));
20195
+ };
20196
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20197
+ "div",
20198
+ {
20199
+ className: "dc-rise",
20200
+ "data-testid": "decision-card-adjuster",
20201
+ style: {
20202
+ display: "flex",
20203
+ flexDirection: "column",
20204
+ gap: 12,
20205
+ border: `1px solid ${border}`,
20206
+ borderRadius: 10,
20207
+ padding: "12px 14px",
20208
+ background: "#fafafa"
20209
+ },
20210
+ children: [
20211
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 8 }, children: [
20212
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.06em", color: muted }, children: [
20213
+ "Adjust \xB7 ",
20214
+ option.label
20215
+ ] }),
20216
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 } }),
20217
+ /* @__PURE__ */ jsxRuntime.jsx(
20218
+ "button",
20219
+ {
20220
+ type: "button",
20221
+ onClick: onBack,
20222
+ "data-testid": "decision-card-adjust-back",
20223
+ style: { border: "none", background: "none", padding: 0, cursor: "pointer", fontSize: 12, fontWeight: 600, color: muted },
20224
+ children: "Back"
20225
+ }
20226
+ )
20227
+ ] }),
20228
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 6 }, children: [
20229
+ /* @__PURE__ */ jsxRuntime.jsx(
20230
+ "input",
20231
+ {
20232
+ value: text,
20233
+ onChange: (e) => {
20234
+ setText(e.target.value);
20235
+ const n = Number(e.target.value);
20236
+ if (Number.isFinite(n)) setValue(clampToRange(n, adjust));
20237
+ },
20238
+ onBlur: () => commit(Number(text) || suggested),
20239
+ onKeyDown: (e) => {
20240
+ if (e.key === "Enter") {
20241
+ const v = clampToRange(Number(text) || suggested, adjust);
20242
+ commit(v);
20243
+ onConfirm(v);
20244
+ } else if (e.key === "ArrowUp") {
20245
+ e.preventDefault();
20246
+ commit(value + step);
20247
+ } else if (e.key === "ArrowDown") {
20248
+ e.preventDefault();
20249
+ commit(value - step);
20250
+ }
20251
+ },
20252
+ inputMode: "decimal",
20253
+ "aria-label": `${option.label} value`,
20254
+ "data-testid": "decision-card-adjust-input",
20255
+ style: {
20256
+ width: `${Math.max(3, String(text).length + 1)}ch`,
20257
+ fontSize: 26,
20258
+ fontWeight: 700,
20259
+ fontVariantNumeric: "tabular-nums",
20260
+ letterSpacing: "-0.02em",
20261
+ color: "var(--foreground)",
20262
+ border: "none",
20263
+ borderBottom: `2px solid ${accent}`,
20264
+ background: "transparent",
20265
+ outline: "none",
20266
+ padding: 0
20267
+ }
20268
+ }
20269
+ ),
20270
+ adjust.unit && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 13, fontWeight: 600, color: muted }, children: adjust.unit }),
20271
+ moved && /* @__PURE__ */ jsxRuntime.jsxs(
20272
+ "button",
20273
+ {
20274
+ type: "button",
20275
+ onClick: () => commit(suggested),
20276
+ "data-testid": "decision-card-adjust-reset",
20277
+ style: {
20278
+ marginLeft: 8,
20279
+ border: "none",
20280
+ background: "none",
20281
+ padding: 0,
20282
+ cursor: "pointer",
20283
+ fontSize: 11.5,
20284
+ fontWeight: 600,
20285
+ color: muted,
20286
+ textDecoration: "underline",
20287
+ textUnderlineOffset: 2
20288
+ },
20289
+ children: [
20290
+ "Reset to suggested (",
20291
+ formatFigure(suggested, adjust.unit),
20292
+ ")"
20293
+ ]
20294
+ }
20295
+ )
20296
+ ] }),
20297
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
20298
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", height: 16, display: "flex", alignItems: "center" }, children: [
20299
+ /* @__PURE__ */ jsxRuntime.jsx(
20300
+ "div",
20301
+ {
20302
+ "aria-hidden": "true",
20303
+ style: {
20304
+ position: "absolute",
20305
+ left: 0,
20306
+ right: 0,
20307
+ height: 4,
20308
+ borderRadius: 9999,
20309
+ background: `linear-gradient(to right, ${accent} ${pct}%, #e8e8e8 ${pct}%)`
20310
+ }
20311
+ }
20312
+ ),
20313
+ moved && /* @__PURE__ */ jsxRuntime.jsx(
20314
+ "div",
20315
+ {
20316
+ "aria-hidden": "true",
20317
+ title: `Suggested: ${formatFigure(suggested, adjust.unit)}`,
20318
+ style: {
20319
+ position: "absolute",
20320
+ left: `${suggestedPct}%`,
20321
+ transform: "translateX(-50%)",
20322
+ width: 2,
20323
+ height: 10,
20324
+ borderRadius: 1,
20325
+ background: muted,
20326
+ opacity: 0.55
20327
+ }
20328
+ }
20329
+ ),
20330
+ /* @__PURE__ */ jsxRuntime.jsx(
20331
+ "input",
20332
+ {
20333
+ type: "range",
20334
+ className: "dc-range",
20335
+ min: adjust.min,
20336
+ max: adjust.max,
20337
+ step,
20338
+ value,
20339
+ onChange: (e) => commit(Number(e.target.value)),
20340
+ "aria-label": `${option.label} slider`,
20341
+ "data-testid": "decision-card-adjust-slider",
20342
+ style: { position: "relative", ["--dc-thumb"]: accent }
20343
+ }
20344
+ )
20345
+ ] }),
20346
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 10.5, fontWeight: 600, color: muted, fontVariantNumeric: "tabular-nums" }, children: [
20347
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFigure(adjust.min, adjust.unit) }),
20348
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatFigure(adjust.max, adjust.unit) })
20349
+ ] })
20350
+ ] }),
20351
+ /* @__PURE__ */ jsxRuntime.jsxs(
20352
+ "button",
20353
+ {
20354
+ type: "button",
20355
+ onClick: () => onConfirm(value),
20356
+ "data-testid": "decision-card-adjust-confirm",
20357
+ style: {
20358
+ alignSelf: "flex-start",
20359
+ border: `1px solid ${accent}`,
20360
+ background: accent,
20361
+ color: "white",
20362
+ borderRadius: 8,
20363
+ fontSize: 13,
20364
+ fontWeight: 600,
20365
+ padding: "9px 16px",
20366
+ cursor: "pointer",
20367
+ fontVariantNumeric: "tabular-nums",
20368
+ transition: "opacity 0.15s"
20369
+ },
20370
+ onMouseEnter: (e) => e.currentTarget.style.opacity = "0.88",
20371
+ onMouseLeave: (e) => e.currentTarget.style.opacity = "1",
20372
+ children: [
20373
+ option.label,
20374
+ " \xB7 ",
20375
+ formatFigure(value, adjust.unit)
20376
+ ]
20377
+ }
20378
+ )
20379
+ ]
20380
+ }
20381
+ );
20382
+ }
19968
20383
  function DecisionCardRenderer({
19969
20384
  data,
19970
20385
  resolved = null,
19971
20386
  onResolve,
19972
- onOpenSource
20387
+ onOpenSource,
20388
+ eyebrow
19973
20389
  }) {
19974
- var _a, _b;
20390
+ var _a, _b, _c;
19975
20391
  const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
19976
20392
  const rootRef = React45__default.default.useRef(null);
19977
20393
  const width = useContainerWidth2(rootRef);
19978
20394
  const stacked = width > 0 && width < STACK_BELOW;
20395
+ const [adjustingIdx, setAdjustingIdx] = React45__default.default.useState(null);
19979
20396
  const options = (_a = data.options) != null ? _a : [];
19980
20397
  const recommendedIdx = Math.max(
19981
20398
  0,
@@ -20074,7 +20491,7 @@ function DecisionCardRenderer({
20074
20491
  },
20075
20492
  children: [
20076
20493
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { minWidth: 0, display: "flex", flexDirection: "column", gap: 4 }, children: [
20077
- /* @__PURE__ */ jsxRuntime.jsx(
20494
+ eyebrow === null ? null : /* @__PURE__ */ jsxRuntime.jsx(
20078
20495
  "span",
20079
20496
  {
20080
20497
  style: {
@@ -20084,7 +20501,7 @@ function DecisionCardRenderer({
20084
20501
  fontWeight: 700,
20085
20502
  color: ACCENT2
20086
20503
  },
20087
- children: data.decision_type ? `Decision needs you \xB7 ${data.decision_type}` : "Decision needs you"
20504
+ children: eyebrow !== void 0 ? eyebrow : data.decision_type ? `Decision needs you \xB7 ${data.decision_type}` : "Decision needs you"
20088
20505
  }
20089
20506
  ),
20090
20507
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -20130,7 +20547,20 @@ function DecisionCardRenderer({
20130
20547
  ]
20131
20548
  }
20132
20549
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
20133
- /* @__PURE__ */ jsxRuntime.jsx(
20550
+ adjustingIdx != null && ((_b = options[adjustingIdx]) == null ? void 0 : _b.adjust) ? /* @__PURE__ */ jsxRuntime.jsx(
20551
+ ValueAdjuster,
20552
+ {
20553
+ option: options[adjustingIdx],
20554
+ accent: ACCENT2,
20555
+ border: BORDER4,
20556
+ muted: MUTED2,
20557
+ onBack: () => setAdjustingIdx(null),
20558
+ onConfirm: (value) => {
20559
+ setAdjustingIdx(null);
20560
+ onResolve == null ? void 0 : onResolve(options[adjustingIdx].label, value);
20561
+ }
20562
+ }
20563
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
20134
20564
  "div",
20135
20565
  {
20136
20566
  style: {
@@ -20140,15 +20570,21 @@ function DecisionCardRenderer({
20140
20570
  gap: 8
20141
20571
  },
20142
20572
  children: options.map((opt, idx) => {
20143
- var _a2;
20573
+ var _a2, _b2;
20144
20574
  const primary = idx === recommendedIdx;
20145
- return /* @__PURE__ */ jsxRuntime.jsx(
20575
+ const adjustable = Boolean(opt.adjust);
20576
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20146
20577
  "button",
20147
20578
  {
20148
20579
  type: "button",
20149
- onClick: () => onResolve == null ? void 0 : onResolve(opt.label),
20580
+ onClick: () => adjustable ? setAdjustingIdx(idx) : onResolve == null ? void 0 : onResolve(opt.label),
20581
+ "data-adjustable": adjustable || void 0,
20150
20582
  style: {
20151
20583
  width: stacked ? "100%" : "auto",
20584
+ display: "inline-flex",
20585
+ alignItems: "center",
20586
+ justifyContent: stacked ? "flex-start" : "center",
20587
+ gap: 7,
20152
20588
  textAlign: stacked ? "left" : "center",
20153
20589
  border: `1px solid ${primary ? ACCENT2 : BORDER4}`,
20154
20590
  background: primary ? ACCENT2 : "white",
@@ -20176,7 +20612,28 @@ function DecisionCardRenderer({
20176
20612
  e.currentTarget.style.background = "white";
20177
20613
  }
20178
20614
  },
20179
- children: opt.label
20615
+ children: [
20616
+ opt.label,
20617
+ adjustable && typeof opt.value === "number" && /* @__PURE__ */ jsxRuntime.jsxs(
20618
+ "span",
20619
+ {
20620
+ style: {
20621
+ fontSize: 11.5,
20622
+ fontWeight: 700,
20623
+ fontVariantNumeric: "tabular-nums",
20624
+ padding: "1px 7px",
20625
+ borderRadius: 9999,
20626
+ background: primary ? "rgba(255,255,255,0.22)" : "#f2f2f2",
20627
+ color: primary ? "white" : MUTED2,
20628
+ lineHeight: 1.5
20629
+ },
20630
+ children: [
20631
+ formatFigure(opt.value, (_b2 = opt.adjust) == null ? void 0 : _b2.unit),
20632
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { marginLeft: 4, opacity: 0.8 }, children: "\u270E" })
20633
+ ]
20634
+ }
20635
+ )
20636
+ ]
20180
20637
  },
20181
20638
  (_a2 = opt.id) != null ? _a2 : opt.label
20182
20639
  );
@@ -20215,7 +20672,7 @@ function DecisionCardRenderer({
20215
20672
  strokeLinejoin: "round"
20216
20673
  }
20217
20674
  ) }),
20218
- (_b = data.source.label) != null ? _b : "View source for this figure"
20675
+ (_c = data.source.label) != null ? _c : "View source for this figure"
20219
20676
  ]
20220
20677
  }
20221
20678
  )
@@ -20224,20 +20681,27 @@ function DecisionCardRenderer({
20224
20681
  }
20225
20682
  );
20226
20683
  }
20684
+ function composeResolution(p, option, value) {
20685
+ var _a, _b, _c;
20686
+ if (value == null) return option;
20687
+ const unit = (_c = (_b = ((_a = p.options) != null ? _a : []).find((o) => o.label === option)) == null ? void 0 : _b.adjust) == null ? void 0 : _c.unit;
20688
+ return `${option} \xB7 ${formatFigure(value, unit)}`;
20689
+ }
20227
20690
  function DecisionCardResolver(p) {
20228
- var _a, _b, _c, _d;
20691
+ var _a, _b;
20229
20692
  const { resolvedDecisions, onDecisionResolve, onDecisionSource } = useGenUIInteraction();
20230
20693
  const decisionId = (_a = p.id) != null ? _a : p.title;
20231
20694
  const hostResolved = resolvedDecisions == null ? void 0 : resolvedDecisions[decisionId];
20232
- const initial = (_c = hostResolved != null ? hostResolved : (_b = p.resolved) == null ? void 0 : _b.option) != null ? _c : null;
20695
+ const initial = hostResolved != null ? hostResolved : p.resolved ? composeResolution(p, p.resolved.option, p.resolved.value) : null;
20233
20696
  const [localResolved, setLocalResolved] = React45__default.default.useState(initial);
20234
20697
  React45__default.default.useEffect(() => {
20235
20698
  if (hostResolved !== void 0) setLocalResolved(hostResolved);
20236
20699
  }, [hostResolved]);
20237
20700
  const resolved = hostResolved != null ? hostResolved : localResolved;
20238
- const handleResolve = (option) => {
20239
- setLocalResolved(option);
20240
- onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, option);
20701
+ const handleResolve = (option, value) => {
20702
+ const resolution = composeResolution(p, option, value);
20703
+ setLocalResolved(resolution);
20704
+ onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, resolution);
20241
20705
  };
20242
20706
  const handleSource = () => {
20243
20707
  var _a2;
@@ -20246,7 +20710,7 @@ function DecisionCardResolver(p) {
20246
20710
  window.open(p.source.url, "_blank", "noopener,noreferrer");
20247
20711
  }
20248
20712
  };
20249
- return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_d = p.title) != null ? _d : "decision-card", children: /* @__PURE__ */ jsxRuntime.jsx(
20713
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_b = p.title) != null ? _b : "decision-card", children: /* @__PURE__ */ jsxRuntime.jsx(
20250
20714
  DecisionCardRenderer,
20251
20715
  {
20252
20716
  data: p,
@@ -20257,6 +20721,302 @@ function DecisionCardResolver(p) {
20257
20721
  ) });
20258
20722
  }
20259
20723
  init_ThemeContext();
20724
+ var GREEN4 = "#15803d";
20725
+ var KEYFRAMES3 = `
20726
+ @keyframes dqSettle{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}
20727
+ .dq-settle{animation:dqSettle 0.24s cubic-bezier(0.22,1,0.36,1) both}
20728
+ @keyframes dqFocus{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:none}}
20729
+ .dq-focus{animation:dqFocus 0.28s cubic-bezier(0.22,1,0.36,1) both}
20730
+ @media (prefers-reduced-motion: reduce){
20731
+ .dq-settle,.dq-focus{animation:none !important;opacity:1 !important;transform:none !important}
20732
+ }`;
20733
+ function figureOf(item, decision) {
20734
+ var _a, _b, _c;
20735
+ if (decision.value == null) return decision.option;
20736
+ const unit = (_c = (_b = ((_a = item.options) != null ? _a : []).find((o) => o.label === decision.option)) == null ? void 0 : _b.adjust) == null ? void 0 : _c.unit;
20737
+ return `${decision.option} \xB7 ${formatFigure(decision.value, unit)}`;
20738
+ }
20739
+ function composeQueueMessage(items, decisions) {
20740
+ const lines = items.map((item, i) => {
20741
+ const d = decisions[i];
20742
+ return `${i + 1}. ${item.title} \u2192 ${d ? figureOf(item, d) : "(undecided)"}`;
20743
+ });
20744
+ const done = decisions.filter(Boolean).length;
20745
+ return `Decisions (${done}/${items.length}):
20746
+ ${lines.join("\n")}`;
20747
+ }
20748
+ function Check({ size, color }) {
20749
+ 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" }) });
20750
+ }
20751
+ function amountChip(item) {
20752
+ if (typeof item.amount !== "number") return null;
20753
+ const abs = Math.abs(item.amount);
20754
+ const sign = item.amount < 0 ? "-" : "";
20755
+ if (abs >= 1e6) return `${sign}$${(abs / 1e6).toFixed(abs >= 1e7 ? 0 : 1)}M`;
20756
+ if (abs >= 1e3) return `${sign}$${(abs / 1e3).toFixed(abs >= 1e4 ? 0 : 1)}K`;
20757
+ return `${sign}$${abs}`;
20758
+ }
20759
+ function DecisionQueueRenderer({ data, submitted = null, onSubmit }) {
20760
+ var _a;
20761
+ const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2 } = useTheme();
20762
+ const items = (_a = data.items) != null ? _a : [];
20763
+ const [decisions, setDecisions] = React45__default.default.useState(
20764
+ () => items.map(() => void 0)
20765
+ );
20766
+ const firstUndecided = decisions.findIndex((d) => !d);
20767
+ const [focusIdx, setFocusIdx] = React45__default.default.useState(firstUndecided >= 0 ? firstUndecided : null);
20768
+ const isSubmitted = submitted != null;
20769
+ const shown = isSubmitted ? items.map(
20770
+ (item, i) => {
20771
+ var _a2;
20772
+ return (_a2 = submitted.find((d) => d.id && d.id === item.id || d.title === item.title)) != null ? _a2 : submitted[i];
20773
+ }
20774
+ ) : decisions;
20775
+ const decidedCount = shown.filter(Boolean).length;
20776
+ const allDecided = decidedCount === items.length;
20777
+ const decide = (idx, option, value) => {
20778
+ const item = items[idx];
20779
+ const next = decisions.slice();
20780
+ next[idx] = { id: item.id, title: item.title, option, value };
20781
+ setDecisions(next);
20782
+ const order = [...Array(items.length).keys()];
20783
+ const after = order.slice(idx + 1).concat(order.slice(0, idx + 1));
20784
+ const target = after.find((j) => j !== idx && !next[j]);
20785
+ setFocusIdx(target != null ? target : null);
20786
+ };
20787
+ const handleSubmit = () => {
20788
+ if (!allDecided || isSubmitted) return;
20789
+ const final = decisions;
20790
+ onSubmit == null ? void 0 : onSubmit(final, composeQueueMessage(items, final));
20791
+ };
20792
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20793
+ "div",
20794
+ {
20795
+ "data-testid": "decision-queue",
20796
+ "data-submitted": isSubmitted || void 0,
20797
+ style: {
20798
+ position: "relative",
20799
+ width: "100%",
20800
+ minWidth: 0,
20801
+ boxSizing: "border-box",
20802
+ borderRadius: "0.75rem",
20803
+ border: `1px solid ${BORDER4}`,
20804
+ background: "white",
20805
+ boxShadow: "0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.04)",
20806
+ padding: "16px 18px",
20807
+ display: "flex",
20808
+ flexDirection: "column",
20809
+ gap: 12,
20810
+ overflow: "hidden"
20811
+ },
20812
+ children: [
20813
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: KEYFRAMES3 }),
20814
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 3 }, children: [
20815
+ /* @__PURE__ */ jsxRuntime.jsx(
20816
+ "span",
20817
+ {
20818
+ style: {
20819
+ fontSize: 10.5,
20820
+ textTransform: "uppercase",
20821
+ letterSpacing: "0.07em",
20822
+ fontWeight: 700,
20823
+ color: isSubmitted ? GREEN4 : ACCENT2
20824
+ },
20825
+ children: isSubmitted ? "Decisions submitted" : "Decisions need you"
20826
+ }
20827
+ ),
20828
+ data.title && /* @__PURE__ */ jsxRuntime.jsx(
20829
+ "p",
20830
+ {
20831
+ style: {
20832
+ fontFamily: "var(--font-serif)",
20833
+ fontSize: 16,
20834
+ fontWeight: 400,
20835
+ color: "var(--foreground)",
20836
+ letterSpacing: "-0.01em",
20837
+ margin: 0,
20838
+ lineHeight: 1.25
20839
+ },
20840
+ children: data.title
20841
+ }
20842
+ ),
20843
+ data.description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 12.5, color: MUTED2, margin: 0, lineHeight: 1.45 }, children: data.description })
20844
+ ] }),
20845
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: items.map((item, idx) => {
20846
+ var _a2, _b, _c;
20847
+ const decision = shown[idx];
20848
+ const focused = !isSubmitted && focusIdx === idx;
20849
+ if (focused) {
20850
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "dq-focus", "data-testid": `decision-queue-focus-${idx}`, children: /* @__PURE__ */ jsxRuntime.jsx(
20851
+ DecisionCardRenderer,
20852
+ {
20853
+ data: __spreadValues({ type: "decision-card" }, item),
20854
+ resolved: null,
20855
+ onResolve: (option, value) => decide(idx, option, value),
20856
+ eyebrow: `${idx + 1} of ${items.length}${item.decision_type ? ` \xB7 ${item.decision_type}` : ""}`
20857
+ }
20858
+ ) }, (_a2 = item.id) != null ? _a2 : `q-${idx}`);
20859
+ }
20860
+ if (decision) {
20861
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20862
+ "button",
20863
+ {
20864
+ type: "button",
20865
+ className: "dq-settle",
20866
+ onClick: isSubmitted ? void 0 : () => setFocusIdx(idx),
20867
+ disabled: isSubmitted,
20868
+ title: isSubmitted ? void 0 : "Change this decision",
20869
+ "data-testid": `decision-queue-receipt-${idx}`,
20870
+ style: {
20871
+ display: "flex",
20872
+ alignItems: "center",
20873
+ gap: 8,
20874
+ width: "100%",
20875
+ textAlign: "left",
20876
+ border: "1px solid #dcfce7",
20877
+ background: "#f6fef9",
20878
+ borderRadius: 8,
20879
+ padding: "7px 11px",
20880
+ cursor: isSubmitted ? "default" : "pointer",
20881
+ font: "inherit"
20882
+ },
20883
+ children: [
20884
+ /* @__PURE__ */ jsxRuntime.jsx(Check, { size: 13, color: GREEN4 }),
20885
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12.5, fontWeight: 600, color: "var(--foreground)", minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: item.title }),
20886
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { color: MUTED2, fontSize: 12 }, children: "\u2192" }),
20887
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12.5, fontWeight: 600, color: GREEN4, fontVariantNumeric: "tabular-nums", whiteSpace: "nowrap" }, children: figureOf(item, decision) }),
20888
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 } }),
20889
+ !isSubmitted && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 11, fontWeight: 600, color: MUTED2 }, children: "Change" })
20890
+ ]
20891
+ },
20892
+ (_b = item.id) != null ? _b : `q-${idx}`
20893
+ );
20894
+ }
20895
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20896
+ "button",
20897
+ {
20898
+ type: "button",
20899
+ onClick: isSubmitted ? void 0 : () => setFocusIdx(idx),
20900
+ disabled: isSubmitted,
20901
+ "data-testid": `decision-queue-upcoming-${idx}`,
20902
+ style: {
20903
+ display: "flex",
20904
+ alignItems: "center",
20905
+ gap: 8,
20906
+ width: "100%",
20907
+ textAlign: "left",
20908
+ border: `1px dashed ${BORDER4}`,
20909
+ background: "white",
20910
+ borderRadius: 8,
20911
+ padding: "7px 11px",
20912
+ cursor: isSubmitted ? "default" : "pointer",
20913
+ font: "inherit",
20914
+ opacity: 0.75
20915
+ },
20916
+ children: [
20917
+ /* @__PURE__ */ jsxRuntime.jsx(
20918
+ "span",
20919
+ {
20920
+ "aria-hidden": "true",
20921
+ style: { width: 13, height: 13, borderRadius: "50%", border: `1.5px solid ${MUTED2}`, flexShrink: 0, boxSizing: "border-box" }
20922
+ }
20923
+ ),
20924
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: 12.5, fontWeight: 600, color: MUTED2, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
20925
+ item.decision_type ? `${item.decision_type} \xB7 ` : "",
20926
+ item.title
20927
+ ] }),
20928
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 } }),
20929
+ amountChip(item) && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 11.5, fontWeight: 700, color: MUTED2, fontVariantNumeric: "tabular-nums" }, children: amountChip(item) })
20930
+ ]
20931
+ },
20932
+ (_c = item.id) != null ? _c : `q-${idx}`
20933
+ );
20934
+ }) }),
20935
+ /* @__PURE__ */ jsxRuntime.jsxs(
20936
+ "div",
20937
+ {
20938
+ style: {
20939
+ display: "flex",
20940
+ alignItems: "center",
20941
+ gap: 10,
20942
+ paddingTop: 10,
20943
+ borderTop: `1px solid #f0f0f0`
20944
+ },
20945
+ children: [
20946
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-flex", gap: 4 }, "aria-hidden": "true", children: items.map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
20947
+ "span",
20948
+ {
20949
+ style: {
20950
+ width: 7,
20951
+ height: 7,
20952
+ borderRadius: "50%",
20953
+ background: shown[i] ? isSubmitted ? GREEN4 : ACCENT2 : "#e8e8e8",
20954
+ transition: "background 0.2s"
20955
+ }
20956
+ },
20957
+ `dot-${i}`
20958
+ )) }),
20959
+ /* @__PURE__ */ jsxRuntime.jsxs(
20960
+ "span",
20961
+ {
20962
+ style: { fontSize: 11.5, fontWeight: 600, color: MUTED2, fontVariantNumeric: "tabular-nums" },
20963
+ "data-testid": "decision-queue-progress",
20964
+ children: [
20965
+ decidedCount,
20966
+ "/",
20967
+ items.length,
20968
+ " decided"
20969
+ ]
20970
+ }
20971
+ ),
20972
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1 } }),
20973
+ isSubmitted ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 6, fontSize: 12.5, fontWeight: 600, color: GREEN4 }, children: [
20974
+ /* @__PURE__ */ jsxRuntime.jsx(Check, { size: 14, color: GREEN4 }),
20975
+ "Submitted"
20976
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
20977
+ "button",
20978
+ {
20979
+ type: "button",
20980
+ onClick: handleSubmit,
20981
+ disabled: !allDecided,
20982
+ "data-testid": "decision-queue-submit",
20983
+ style: {
20984
+ border: `1px solid ${allDecided ? ACCENT2 : BORDER4}`,
20985
+ background: allDecided ? ACCENT2 : "#f6f6f6",
20986
+ color: allDecided ? "white" : MUTED2,
20987
+ borderRadius: 8,
20988
+ fontSize: 13,
20989
+ fontWeight: 600,
20990
+ padding: "8px 16px",
20991
+ cursor: allDecided ? "pointer" : "default",
20992
+ fontVariantNumeric: "tabular-nums",
20993
+ transition: "background 0.15s, border-color 0.15s, color 0.15s"
20994
+ },
20995
+ children: data.submit_label || `Submit ${items.length} decision${items.length === 1 ? "" : "s"}`
20996
+ }
20997
+ )
20998
+ ]
20999
+ }
21000
+ )
21001
+ ]
21002
+ }
21003
+ );
21004
+ }
21005
+ function DecisionQueueResolver(p) {
21006
+ var _a, _b, _c, _d, _e, _f;
21007
+ const { resolvedDecisions, onDecisionQueueSubmit } = useGenUIInteraction();
21008
+ const queueId = (_b = (_a = p.id) != null ? _a : p.title) != null ? _b : "decision-queue";
21009
+ const replayed = (_d = (_c = p.resolved) == null ? void 0 : _c.decisions) != null ? _d : null;
21010
+ const [localSubmitted, setLocalSubmitted] = React45__default.default.useState(null);
21011
+ const hostLocked = (resolvedDecisions == null ? void 0 : resolvedDecisions[queueId]) != null;
21012
+ const submitted = (_e = replayed != null ? replayed : localSubmitted) != null ? _e : hostLocked ? [] : null;
21013
+ const handleSubmit = (decisions, message) => {
21014
+ setLocalSubmitted(decisions);
21015
+ onDecisionQueueSubmit == null ? void 0 : onDecisionQueueSubmit(queueId, decisions, message);
21016
+ };
21017
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_f = p.title) != null ? _f : "decision-queue", children: /* @__PURE__ */ jsxRuntime.jsx(DecisionQueueRenderer, { data: p, submitted, onSubmit: handleSubmit }) });
21018
+ }
21019
+ init_ThemeContext();
20260
21020
  var CONNECTED_GREEN3 = "#15803d";
20261
21021
  var CONNECTED_GREEN_BG = "#dcfce7";
20262
21022
  var PENDING_AMBER = "#92400e";
@@ -20688,6 +21448,8 @@ function resolveUI(rawPayload) {
20688
21448
  return /* @__PURE__ */ jsxRuntime.jsx(DocumentFieldExtractionResolver, __spreadValues({}, payload));
20689
21449
  case "decision-card":
20690
21450
  return /* @__PURE__ */ jsxRuntime.jsx(DecisionCardResolver, __spreadValues({}, payload));
21451
+ case "decision-queue":
21452
+ return /* @__PURE__ */ jsxRuntime.jsx(DecisionQueueResolver, __spreadValues({}, payload));
20691
21453
  case "tabby-auth":
20692
21454
  return /* @__PURE__ */ jsxRuntime.jsx(TabbyAuthResolver, __spreadValues({}, payload));
20693
21455
  default: {