@adoptai/genui-components 0.1.55 → 0.1.57

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 (38) hide show
  1. package/dist/builders/BuilderForm.d.ts.map +1 -1
  2. package/dist/composites/decision-card/resolver.cjs +634 -0
  3. package/dist/composites/decision-card/resolver.cjs.map +1 -0
  4. package/dist/composites/decision-card/resolver.d.ts +13 -0
  5. package/dist/composites/decision-card/resolver.d.ts.map +1 -0
  6. package/dist/composites/decision-card/resolver.js +627 -0
  7. package/dist/composites/decision-card/resolver.js.map +1 -0
  8. package/dist/composites/workflow-stepper/resolver.cjs +4 -1
  9. package/dist/composites/workflow-stepper/resolver.cjs.map +1 -1
  10. package/dist/composites/workflow-stepper/resolver.js +4 -1
  11. package/dist/composites/workflow-stepper/resolver.js.map +1 -1
  12. package/dist/index.cjs +522 -12
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +521 -13
  17. package/dist/index.js.map +1 -1
  18. package/dist/renderer.cjs +504 -8
  19. package/dist/renderer.cjs.map +1 -1
  20. package/dist/renderer.js +504 -8
  21. package/dist/renderer.js.map +1 -1
  22. package/dist/resolver.cjs +504 -8
  23. package/dist/resolver.cjs.map +1 -1
  24. package/dist/resolver.d.ts.map +1 -1
  25. package/dist/resolver.js +504 -8
  26. package/dist/resolver.js.map +1 -1
  27. package/dist/schemas/decision-card.d.ts +149 -0
  28. package/dist/schemas/decision-card.d.ts.map +1 -0
  29. package/dist/schemas/index.cjs +105 -1
  30. package/dist/schemas/index.cjs.map +1 -1
  31. package/dist/schemas/index.d.ts +149 -0
  32. package/dist/schemas/index.d.ts.map +1 -1
  33. package/dist/schemas/index.js +105 -1
  34. package/dist/schemas/index.js.map +1 -1
  35. package/dist/shared/InteractionContext.d.ts +10 -0
  36. package/dist/shared/InteractionContext.d.ts.map +1 -1
  37. package/dist/tool-definitions.json +135 -3
  38. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -5315,6 +5315,109 @@ var workflowStepperTool = {
5315
5315
  required: ["type", "title", "steps"]
5316
5316
  }
5317
5317
  };
5318
+ var decisionCardSchema = zod.z.object({
5319
+ type: zod.z.literal("decision-card"),
5320
+ id: zod.z.string().optional(),
5321
+ decision_type: zod.z.string().optional(),
5322
+ title: zod.z.string(),
5323
+ question: zod.z.string(),
5324
+ amount: zod.z.number().optional(),
5325
+ currency: zod.z.string().optional(),
5326
+ amount_label: zod.z.string().optional(),
5327
+ severity: zod.z.enum(["low", "medium", "high"]).optional(),
5328
+ flags: zod.z.array(
5329
+ zod.z.object({
5330
+ field: zod.z.string().optional(),
5331
+ issue: zod.z.string(),
5332
+ severity: zod.z.enum(["low", "medium", "high"]).optional()
5333
+ })
5334
+ ).max(6).optional(),
5335
+ options: zod.z.array(
5336
+ zod.z.object({
5337
+ id: zod.z.string().optional(),
5338
+ label: zod.z.string(),
5339
+ recommended: zod.z.boolean().optional()
5340
+ })
5341
+ ).min(1).max(5),
5342
+ source: zod.z.object({
5343
+ label: zod.z.string().optional(),
5344
+ url: zod.z.string().optional()
5345
+ }).optional(),
5346
+ resolved: zod.z.object({
5347
+ option: zod.z.string()
5348
+ }).optional()
5349
+ });
5350
+ var decisionCardTool = {
5351
+ name: "render_decision_card",
5352
+ description: "Render an inline human-in-the-loop (HITL) decision card \u2014 a single judgment the agent needs from the user, resolved in-thread. Shows a titled question with an optional dollar amount at stake, optional data-quality flags, and 2-5 mutually-exclusive resolution options (the first or `recommended` one renders as the primary action), plus an optional 'view source' link. Use for inline approve/choose decisions the user resolves directly in the conversation. NOT for handing off to an external review portal (use escalation-card) and NOT for collecting multiple typed fields (use render_builder).",
5353
+ input_schema: {
5354
+ type: "object",
5355
+ properties: {
5356
+ type: { type: "string", enum: ["decision-card"] },
5357
+ id: { type: "string", description: "Stable id for update-in-place rendering" },
5358
+ decision_type: {
5359
+ type: "string",
5360
+ description: "Short category shown in the eyebrow, e.g. 'Cross-check', 'Allocation', 'Reserve'"
5361
+ },
5362
+ title: { type: "string", description: "The decision headline, e.g. 'AR reserve adequacy'" },
5363
+ question: { type: "string", description: "The full question / context the user must judge" },
5364
+ amount: { type: "number", description: "Dollar value at stake, e.g. 27100" },
5365
+ currency: { type: "string", description: "ISO currency code; defaults to USD" },
5366
+ amount_label: { type: "string", description: "Caption above the amount, e.g. 'At stake'" },
5367
+ severity: {
5368
+ type: "string",
5369
+ enum: ["low", "medium", "high"],
5370
+ description: "Severity of the decision; tints the accent rail"
5371
+ },
5372
+ flags: {
5373
+ type: "array",
5374
+ maxItems: 6,
5375
+ description: "Optional data-quality flags surfaced on the card",
5376
+ items: {
5377
+ type: "object",
5378
+ properties: {
5379
+ field: { type: "string" },
5380
+ issue: { type: "string" },
5381
+ severity: { type: "string", enum: ["low", "medium", "high"] }
5382
+ },
5383
+ required: ["issue"]
5384
+ }
5385
+ },
5386
+ options: {
5387
+ type: "array",
5388
+ minItems: 1,
5389
+ maxItems: 5,
5390
+ description: "Mutually-exclusive resolution choices; mark one `recommended` to make it primary",
5391
+ items: {
5392
+ type: "object",
5393
+ properties: {
5394
+ id: { type: "string" },
5395
+ label: { type: "string" },
5396
+ recommended: { type: "boolean" }
5397
+ },
5398
+ required: ["label"]
5399
+ }
5400
+ },
5401
+ source: {
5402
+ type: "object",
5403
+ description: "Optional provenance link for the figure",
5404
+ properties: {
5405
+ label: { type: "string" },
5406
+ url: { type: "string" }
5407
+ }
5408
+ },
5409
+ resolved: {
5410
+ type: "object",
5411
+ description: "Pre-resolved state for transcript replay",
5412
+ properties: {
5413
+ option: { type: "string" }
5414
+ },
5415
+ required: ["option"]
5416
+ }
5417
+ },
5418
+ required: ["type", "title", "question", "options"]
5419
+ }
5420
+ };
5318
5421
 
5319
5422
  // src/schemas/buildRenderUITool.ts
5320
5423
  function buildRenderUITool(selectedSchemas) {
@@ -5433,7 +5536,8 @@ var schemaRegistry = {
5433
5536
  "connect-integration": { schema: connectIntegrationSchema, tool: connectIntegrationTool },
5434
5537
  "integrations-list": { schema: integrationsListSchema, tool: integrationsListTool },
5435
5538
  "pipeline-preview": { schema: pipelinePreviewSchema, tool: pipelinePreviewTool },
5436
- "workflow-stepper": { schema: workflowStepperSchema, tool: workflowStepperTool }
5539
+ "workflow-stepper": { schema: workflowStepperSchema, tool: workflowStepperTool },
5540
+ "decision-card": { schema: decisionCardSchema, tool: decisionCardTool }
5437
5541
  };
5438
5542
 
5439
5543
  // src/shared/ColumnSettingsPanel.tsx
@@ -6146,17 +6250,17 @@ function SparklineTableResolver(p) {
6146
6250
  // src/composites/heatmap-table/resolver.tsx
6147
6251
  init_theme();
6148
6252
  init_ThemeContext();
6149
- function heatColor(z59) {
6150
- const clamped = Math.max(-3, Math.min(3, z59));
6253
+ function heatColor(z60) {
6254
+ const clamped = Math.max(-3, Math.min(3, z60));
6151
6255
  const abs = Math.abs(clamped);
6152
6256
  const lightness = 95 - abs * 8;
6153
6257
  const hue = clamped >= 0 ? 142 : 0;
6154
6258
  return `hsl(${hue} 60% ${lightness}%)`;
6155
6259
  }
6156
- function heatTextColor(z59) {
6157
- const abs = Math.abs(z59);
6158
- if (abs > 2) return z59 >= 0 ? "#14532d" : "#7f1d1d";
6159
- if (abs > 1) return z59 >= 0 ? "#166534" : "#991b1b";
6260
+ function heatTextColor(z60) {
6261
+ const abs = Math.abs(z60);
6262
+ if (abs > 2) return z60 >= 0 ? "#14532d" : "#7f1d1d";
6263
+ if (abs > 1) return z60 >= 0 ? "#166534" : "#991b1b";
6160
6264
  return "var(--foreground)";
6161
6265
  }
6162
6266
  var th2 = {
@@ -17204,7 +17308,10 @@ function PipelinePreviewResolver(p) {
17204
17308
  init_ThemeContext();
17205
17309
  var DEFAULT_INTERACTION = {
17206
17310
  selectedStepId: null,
17207
- onStepSelect: void 0
17311
+ onStepSelect: void 0,
17312
+ resolvedDecisions: void 0,
17313
+ onDecisionResolve: void 0,
17314
+ onDecisionSource: void 0
17208
17315
  };
17209
17316
  var GenUIInteractionContext = React41.createContext(DEFAULT_INTERACTION);
17210
17317
  function GenUIInteractionProvider({ value, children }) {
@@ -17926,6 +18033,393 @@ function WorkflowStepperResolver(p) {
17926
18033
  )
17927
18034
  ] }) });
17928
18035
  }
18036
+ init_ThemeContext();
18037
+ var SEVERITY_COLORS = {
18038
+ high: { color: "#dc2626", bg: "#fef2f2" },
18039
+ medium: { color: "#f59e0b", bg: "#fff7ed" },
18040
+ low: { color: "#777777", bg: "#f2f2f2" }
18041
+ };
18042
+ var GREEN3 = "#15803d";
18043
+ var GREEN_SOFT = "#dcfce7";
18044
+ var STACK_BELOW = 380;
18045
+ function formatAmount2(amount, currency = "USD") {
18046
+ var _a2, _b;
18047
+ const abs = Math.abs(amount);
18048
+ const sign = amount < 0 ? "-" : "";
18049
+ let body;
18050
+ if (abs >= 1e6) body = `${(abs / 1e6).toFixed(abs >= 1e7 ? 0 : 1)}M`;
18051
+ else if (abs >= 1e3) body = `${(abs / 1e3).toFixed(abs >= 1e4 ? 0 : 1)}K`;
18052
+ else body = `${abs}`;
18053
+ let symbol = "$";
18054
+ try {
18055
+ const parts = new Intl.NumberFormat("en-US", {
18056
+ style: "currency",
18057
+ currency,
18058
+ maximumFractionDigits: 0
18059
+ }).formatToParts(0);
18060
+ symbol = (_b = (_a2 = parts.find((p) => p.type === "currency")) == null ? void 0 : _a2.value) != null ? _b : "$";
18061
+ } catch (e) {
18062
+ symbol = "$";
18063
+ }
18064
+ return `${sign}${symbol}${body}`;
18065
+ }
18066
+ function useContainerWidth2(ref) {
18067
+ const [w, setW] = React41__default.default.useState(0);
18068
+ React41__default.default.useLayoutEffect(() => {
18069
+ const el = ref.current;
18070
+ if (!el || typeof ResizeObserver === "undefined") return;
18071
+ const ro = new ResizeObserver((entries) => {
18072
+ var _a2;
18073
+ const cr = (_a2 = entries[0]) == null ? void 0 : _a2.contentRect;
18074
+ if (cr) setW(cr.width);
18075
+ });
18076
+ ro.observe(el);
18077
+ setW(el.getBoundingClientRect().width);
18078
+ return () => ro.disconnect();
18079
+ }, [ref]);
18080
+ return w;
18081
+ }
18082
+ var KEYFRAMES2 = `
18083
+ @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
18084
+ .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
18085
+ @media (prefers-reduced-motion: reduce){
18086
+ .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
18087
+ }`;
18088
+ function SparkCheck({ size, color }) {
18089
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
18090
+ "path",
18091
+ {
18092
+ d: "M5 13l4 4L19 7",
18093
+ stroke: color,
18094
+ strokeWidth: 2.5,
18095
+ strokeLinecap: "round",
18096
+ strokeLinejoin: "round"
18097
+ }
18098
+ ) });
18099
+ }
18100
+ function FlagPill({ flag }) {
18101
+ var _a2;
18102
+ const sev = (_a2 = flag.severity) != null ? _a2 : "medium";
18103
+ const { color, bg } = SEVERITY_COLORS[sev];
18104
+ return /* @__PURE__ */ jsxRuntime.jsxs(
18105
+ "span",
18106
+ {
18107
+ style: {
18108
+ display: "inline-flex",
18109
+ alignItems: "center",
18110
+ gap: 5,
18111
+ fontSize: 11,
18112
+ fontWeight: 600,
18113
+ padding: "3px 9px",
18114
+ borderRadius: 9999,
18115
+ background: bg,
18116
+ color,
18117
+ lineHeight: 1.2
18118
+ },
18119
+ children: [
18120
+ /* @__PURE__ */ jsxRuntime.jsx(
18121
+ "span",
18122
+ {
18123
+ "aria-hidden": "true",
18124
+ style: { width: 6, height: 6, borderRadius: "50%", background: color, flexShrink: 0 }
18125
+ }
18126
+ ),
18127
+ flag.field ? `${flag.field}: ${flag.issue}` : flag.issue
18128
+ ]
18129
+ }
18130
+ );
18131
+ }
18132
+ function DecisionCardRenderer({
18133
+ data,
18134
+ resolved = null,
18135
+ onResolve,
18136
+ onOpenSource
18137
+ }) {
18138
+ var _a2, _b;
18139
+ const { BORDER: BORDER4, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
18140
+ const rootRef = React41__default.default.useRef(null);
18141
+ const width = useContainerWidth2(rootRef);
18142
+ const stacked = width > 0 && width < STACK_BELOW;
18143
+ const options = (_a2 = data.options) != null ? _a2 : [];
18144
+ const recommendedIdx = Math.max(
18145
+ 0,
18146
+ options.findIndex((o) => o.recommended)
18147
+ );
18148
+ const railColor = data.severity ? SEVERITY_COLORS[data.severity].color : ACCENT2;
18149
+ const isResolved = Boolean(resolved);
18150
+ const amountNode = typeof data.amount === "number" ? /* @__PURE__ */ jsxRuntime.jsxs(
18151
+ "div",
18152
+ {
18153
+ style: {
18154
+ display: "flex",
18155
+ flexDirection: "column",
18156
+ alignItems: stacked ? "flex-start" : "flex-end",
18157
+ gap: 1,
18158
+ flexShrink: 0
18159
+ },
18160
+ children: [
18161
+ data.amount_label && /* @__PURE__ */ jsxRuntime.jsx(
18162
+ "span",
18163
+ {
18164
+ style: {
18165
+ fontSize: 10,
18166
+ textTransform: "uppercase",
18167
+ letterSpacing: "0.07em",
18168
+ fontWeight: 700,
18169
+ color: MUTED2
18170
+ },
18171
+ children: data.amount_label
18172
+ }
18173
+ ),
18174
+ /* @__PURE__ */ jsxRuntime.jsx(
18175
+ "span",
18176
+ {
18177
+ style: {
18178
+ fontSize: 18,
18179
+ fontWeight: 700,
18180
+ color: "var(--foreground)",
18181
+ fontVariantNumeric: "tabular-nums",
18182
+ letterSpacing: "-0.01em",
18183
+ lineHeight: 1.1
18184
+ },
18185
+ children: formatAmount2(data.amount, data.currency)
18186
+ }
18187
+ )
18188
+ ]
18189
+ }
18190
+ ) : null;
18191
+ return /* @__PURE__ */ jsxRuntime.jsxs(
18192
+ "div",
18193
+ {
18194
+ ref: rootRef,
18195
+ className: "dc-rise",
18196
+ "data-testid": "decision-card",
18197
+ "data-resolved": isResolved || void 0,
18198
+ style: {
18199
+ position: "relative",
18200
+ width: "100%",
18201
+ minWidth: 0,
18202
+ boxSizing: "border-box",
18203
+ borderRadius: "0.75rem",
18204
+ border: `1px solid ${isResolved ? GREEN_SOFT : BORDER4}`,
18205
+ background: isResolved ? "#f6fef9" : "white",
18206
+ boxShadow: "0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.04)",
18207
+ padding: "16px 18px 16px 20px",
18208
+ display: "flex",
18209
+ flexDirection: "column",
18210
+ gap: 12,
18211
+ overflow: "hidden"
18212
+ },
18213
+ children: [
18214
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: KEYFRAMES2 }),
18215
+ /* @__PURE__ */ jsxRuntime.jsx(
18216
+ "div",
18217
+ {
18218
+ "aria-hidden": "true",
18219
+ style: {
18220
+ position: "absolute",
18221
+ top: 0,
18222
+ left: 0,
18223
+ bottom: 0,
18224
+ width: 4,
18225
+ background: isResolved ? GREEN3 : railColor
18226
+ }
18227
+ }
18228
+ ),
18229
+ /* @__PURE__ */ jsxRuntime.jsxs(
18230
+ "div",
18231
+ {
18232
+ style: {
18233
+ display: "flex",
18234
+ flexDirection: stacked ? "column" : "row",
18235
+ alignItems: stacked ? "flex-start" : "flex-start",
18236
+ justifyContent: "space-between",
18237
+ gap: stacked ? 6 : 12
18238
+ },
18239
+ children: [
18240
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { minWidth: 0, display: "flex", flexDirection: "column", gap: 4 }, children: [
18241
+ /* @__PURE__ */ jsxRuntime.jsx(
18242
+ "span",
18243
+ {
18244
+ style: {
18245
+ fontSize: 10.5,
18246
+ textTransform: "uppercase",
18247
+ letterSpacing: "0.07em",
18248
+ fontWeight: 700,
18249
+ color: ACCENT2
18250
+ },
18251
+ children: data.decision_type ? `Decision needs you \xB7 ${data.decision_type}` : "Decision needs you"
18252
+ }
18253
+ ),
18254
+ /* @__PURE__ */ jsxRuntime.jsx(
18255
+ "p",
18256
+ {
18257
+ style: {
18258
+ fontFamily: "var(--font-serif)",
18259
+ fontSize: 17,
18260
+ fontWeight: 400,
18261
+ color: "var(--foreground)",
18262
+ letterSpacing: "-0.01em",
18263
+ margin: 0,
18264
+ lineHeight: 1.2
18265
+ },
18266
+ children: data.title
18267
+ }
18268
+ )
18269
+ ] }),
18270
+ amountNode
18271
+ ]
18272
+ }
18273
+ ),
18274
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 13, lineHeight: 1.5, color: MUTED2, margin: 0 }, children: data.question }),
18275
+ data.flags && data.flags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: data.flags.map((flag, i) => {
18276
+ var _a3;
18277
+ return /* @__PURE__ */ jsxRuntime.jsx(FlagPill, { flag }, `${(_a3 = flag.field) != null ? _a3 : "flag"}-${i}`);
18278
+ }) }),
18279
+ isResolved ? /* @__PURE__ */ jsxRuntime.jsxs(
18280
+ "div",
18281
+ {
18282
+ style: {
18283
+ display: "inline-flex",
18284
+ alignItems: "center",
18285
+ gap: 7,
18286
+ fontSize: 13,
18287
+ fontWeight: 600,
18288
+ color: GREEN3
18289
+ },
18290
+ children: [
18291
+ /* @__PURE__ */ jsxRuntime.jsx(SparkCheck, { size: 16, color: GREEN3 }),
18292
+ "Resolved \xB7 ",
18293
+ resolved
18294
+ ]
18295
+ }
18296
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18297
+ /* @__PURE__ */ jsxRuntime.jsx(
18298
+ "div",
18299
+ {
18300
+ style: {
18301
+ display: "flex",
18302
+ flexDirection: stacked ? "column" : "row",
18303
+ flexWrap: stacked ? "nowrap" : "wrap",
18304
+ gap: 8
18305
+ },
18306
+ children: options.map((opt, idx) => {
18307
+ var _a3;
18308
+ const primary = idx === recommendedIdx;
18309
+ return /* @__PURE__ */ jsxRuntime.jsx(
18310
+ "button",
18311
+ {
18312
+ type: "button",
18313
+ onClick: () => onResolve == null ? void 0 : onResolve(opt.label),
18314
+ style: {
18315
+ width: stacked ? "100%" : "auto",
18316
+ textAlign: stacked ? "left" : "center",
18317
+ border: `1px solid ${primary ? ACCENT2 : BORDER4}`,
18318
+ background: primary ? ACCENT2 : "white",
18319
+ color: primary ? "white" : "var(--foreground)",
18320
+ borderRadius: 8,
18321
+ fontSize: 13,
18322
+ fontWeight: 600,
18323
+ padding: "9px 14px",
18324
+ cursor: "pointer",
18325
+ transition: "background 0.15s, border-color 0.15s, color 0.15s"
18326
+ },
18327
+ onMouseEnter: (e) => {
18328
+ if (primary) {
18329
+ e.currentTarget.style.background = ACCENT_SOFT2;
18330
+ } else {
18331
+ e.currentTarget.style.borderColor = ACCENT2;
18332
+ e.currentTarget.style.background = "#fafafa";
18333
+ }
18334
+ },
18335
+ onMouseLeave: (e) => {
18336
+ if (primary) {
18337
+ e.currentTarget.style.background = ACCENT2;
18338
+ } else {
18339
+ e.currentTarget.style.borderColor = BORDER4;
18340
+ e.currentTarget.style.background = "white";
18341
+ }
18342
+ },
18343
+ children: opt.label
18344
+ },
18345
+ (_a3 = opt.id) != null ? _a3 : opt.label
18346
+ );
18347
+ })
18348
+ }
18349
+ ),
18350
+ data.source && /* @__PURE__ */ jsxRuntime.jsxs(
18351
+ "button",
18352
+ {
18353
+ type: "button",
18354
+ onClick: onOpenSource,
18355
+ style: {
18356
+ alignSelf: "flex-start",
18357
+ display: "inline-flex",
18358
+ alignItems: "center",
18359
+ gap: 5,
18360
+ border: "none",
18361
+ background: "none",
18362
+ padding: 0,
18363
+ cursor: "pointer",
18364
+ fontSize: 12,
18365
+ fontWeight: 600,
18366
+ color: MUTED2,
18367
+ transition: "color 0.15s"
18368
+ },
18369
+ onMouseEnter: (e) => e.currentTarget.style.color = ACCENT2,
18370
+ onMouseLeave: (e) => e.currentTarget.style.color = MUTED2,
18371
+ children: [
18372
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 13, height: 13, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
18373
+ "path",
18374
+ {
18375
+ d: "M14 3v4a1 1 0 001 1h4M5 4a1 1 0 011-1h8l5 5v11a1 1 0 01-1 1H6a1 1 0 01-1-1V4z",
18376
+ stroke: "currentColor",
18377
+ strokeWidth: 1.8,
18378
+ strokeLinecap: "round",
18379
+ strokeLinejoin: "round"
18380
+ }
18381
+ ) }),
18382
+ (_b = data.source.label) != null ? _b : "View source for this figure"
18383
+ ]
18384
+ }
18385
+ )
18386
+ ] })
18387
+ ]
18388
+ }
18389
+ );
18390
+ }
18391
+ function DecisionCardResolver(p) {
18392
+ var _a2, _b, _c, _d;
18393
+ const { resolvedDecisions, onDecisionResolve, onDecisionSource } = useGenUIInteraction();
18394
+ const decisionId = (_a2 = p.id) != null ? _a2 : p.title;
18395
+ const hostResolved = resolvedDecisions == null ? void 0 : resolvedDecisions[decisionId];
18396
+ const initial = (_c = hostResolved != null ? hostResolved : (_b = p.resolved) == null ? void 0 : _b.option) != null ? _c : null;
18397
+ const [localResolved, setLocalResolved] = React41__default.default.useState(initial);
18398
+ React41__default.default.useEffect(() => {
18399
+ if (hostResolved !== void 0) setLocalResolved(hostResolved);
18400
+ }, [hostResolved]);
18401
+ const resolved = hostResolved != null ? hostResolved : localResolved;
18402
+ const handleResolve = (option) => {
18403
+ setLocalResolved(option);
18404
+ onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, option);
18405
+ };
18406
+ const handleSource = () => {
18407
+ var _a3;
18408
+ onDecisionSource == null ? void 0 : onDecisionSource(decisionId, p.source);
18409
+ if (!onDecisionSource && ((_a3 = p.source) == null ? void 0 : _a3.url) && typeof window !== "undefined") {
18410
+ window.open(p.source.url, "_blank", "noopener,noreferrer");
18411
+ }
18412
+ };
18413
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentActions, { filename: (_d = p.title) != null ? _d : "decision-card", children: /* @__PURE__ */ jsxRuntime.jsx(
18414
+ DecisionCardRenderer,
18415
+ {
18416
+ data: p,
18417
+ resolved,
18418
+ onResolve: handleResolve,
18419
+ onOpenSource: handleSource
18420
+ }
18421
+ ) });
18422
+ }
17929
18423
  function resolveUI(rawPayload) {
17930
18424
  const payload = coercePayload(rawPayload);
17931
18425
  switch (payload.type) {
@@ -18043,6 +18537,8 @@ function resolveUI(rawPayload) {
18043
18537
  return /* @__PURE__ */ jsxRuntime.jsx(PipelinePreviewResolver, __spreadValues({}, payload));
18044
18538
  case "workflow-stepper":
18045
18539
  return /* @__PURE__ */ jsxRuntime.jsx(WorkflowStepperResolver, __spreadValues({}, payload));
18540
+ case "decision-card":
18541
+ return /* @__PURE__ */ jsxRuntime.jsx(DecisionCardResolver, __spreadValues({}, payload));
18046
18542
  default: {
18047
18543
  return /* @__PURE__ */ jsxRuntime.jsx(
18048
18544
  "div",
@@ -19730,8 +20226,16 @@ function BuilderFormResolver({
19730
20226
  dense,
19731
20227
  onValidationError
19732
20228
  }) {
20229
+ var _a2;
19733
20230
  const state = useBuilderState(builder.blocks);
19734
- const kind = builder.builder_kind || "form";
20231
+ const declaredKind = builder.builder_kind || "form";
20232
+ const blockCount = (builder.blocks || []).length;
20233
+ const kind = blockCount > 1 && declaredKind !== "stepper" ? "stepper" : declaredKind;
20234
+ if (kind !== declaredKind && typeof process !== "undefined" && ((_a2 = process.env) == null ? void 0 : _a2.NODE_ENV) !== "production") {
20235
+ console.warn(
20236
+ `[BuilderForm] builder "${builder.builder_id}" declared builder_kind="${declaredKind}" with ${blockCount} blocks; rendering as stepper to avoid dropping blocks.`
20237
+ );
20238
+ }
19735
20239
  const buildSubmission = React41.useCallback(() => {
19736
20240
  const blocks = (builder.blocks || []).map((b) => ({
19737
20241
  id: b.id,
@@ -19753,10 +20257,14 @@ function BuilderFormResolver({
19753
20257
  }
19754
20258
  onSubmit(buildSubmission());
19755
20259
  }, [disabled, state.validateAllDetailed, onSubmit, buildSubmission, onValidationError]);
20260
+ const onChangeRef = React41.useRef(onChange);
20261
+ React41.useEffect(() => {
20262
+ onChangeRef.current = onChange;
20263
+ });
19756
20264
  React41.useEffect(() => {
19757
- if (!onChange) return;
19758
- onChange(buildSubmission());
19759
- }, [onChange, state.values]);
20265
+ var _a3;
20266
+ (_a3 = onChangeRef.current) == null ? void 0 : _a3.call(onChangeRef, buildSubmission());
20267
+ }, [state.values]);
19760
20268
  React41.useEffect(() => {
19761
20269
  if (!submitRef) return;
19762
20270
  submitRef.current = handleSubmit;
@@ -19838,6 +20346,8 @@ exports.ComponentActions = ComponentActions;
19838
20346
  exports.ContextSlot = ContextSlot;
19839
20347
  exports.DEFAULT_INTERACTION = DEFAULT_INTERACTION;
19840
20348
  exports.DataTableResolver = DataTableResolver;
20349
+ exports.DecisionCardRenderer = DecisionCardRenderer;
20350
+ exports.DecisionCardResolver = DecisionCardResolver;
19841
20351
  exports.DocumentPreviewResolver = DocumentPreviewResolver;
19842
20352
  exports.EngagementPipelineResolver = EngagementPipelineResolver;
19843
20353
  exports.FIELD_REGISTRY = FIELD_REGISTRY;