@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
@@ -229,7 +229,8 @@ var DEFAULT_INTERACTION = {
229
229
  onStepSelect: void 0,
230
230
  resolvedDecisions: void 0,
231
231
  onDecisionResolve: void 0,
232
- onDecisionSource: void 0
232
+ onDecisionSource: void 0,
233
+ onDecisionQueueSubmit: void 0
233
234
  };
234
235
  var GenUIInteractionContext = createContext(DEFAULT_INTERACTION);
235
236
  function useGenUIInteraction() {
@@ -283,8 +284,15 @@ function useContainerWidth(ref) {
283
284
  var KEYFRAMES = `
284
285
  @keyframes dcRise{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
285
286
  .dc-rise{animation:dcRise 0.28s cubic-bezier(0.22,1,0.36,1) both}
287
+ .dc-range{-webkit-appearance:none;appearance:none;width:100%;height:4px;border-radius:9999px;outline:none;cursor:pointer;background:transparent}
288
+ .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}
289
+ .dc-range::-webkit-slider-thumb:hover{transform:scale(1.12)}
290
+ .dc-range:active::-webkit-slider-thumb{cursor:grabbing}
291
+ .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}
292
+ .dc-range::-moz-range-track{height:4px;border-radius:9999px;background:transparent}
286
293
  @media (prefers-reduced-motion: reduce){
287
294
  .dc-rise{animation:none !important;opacity:1 !important;transform:none !important}
295
+ .dc-range::-webkit-slider-thumb{transition:none}
288
296
  }`;
289
297
  function SparkCheck({ size, color }) {
290
298
  return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
@@ -330,17 +338,240 @@ function FlagPill({ flag }) {
330
338
  }
331
339
  );
332
340
  }
341
+ function formatFigure(value, unit) {
342
+ const body = Number.isInteger(value) ? `${value}` : `${Math.round(value * 100) / 100}`;
343
+ if (!unit) return body;
344
+ return unit === "%" ? `${body}%` : `${body} ${unit}`;
345
+ }
346
+ function clampToRange(raw, adjust) {
347
+ var _a;
348
+ const step = (_a = adjust.step) != null ? _a : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
349
+ const snapped = Math.round((raw - adjust.min) / step) * step + adjust.min;
350
+ const fixed = Math.round(snapped * 1e6) / 1e6;
351
+ return Math.min(adjust.max, Math.max(adjust.min, fixed));
352
+ }
353
+ function ValueAdjuster({
354
+ option,
355
+ accent,
356
+ border,
357
+ muted,
358
+ onConfirm,
359
+ onBack
360
+ }) {
361
+ var _a, _b;
362
+ const adjust = option.adjust;
363
+ const suggested = clampToRange((_a = option.value) != null ? _a : adjust.min, adjust);
364
+ const [value, setValue] = React4.useState(suggested);
365
+ const [text, setText] = React4.useState(String(suggested));
366
+ const step = (_b = adjust.step) != null ? _b : Number.isInteger(adjust.min) && Number.isInteger(adjust.max) ? 1 : (adjust.max - adjust.min) / 100;
367
+ const pct = adjust.max > adjust.min ? (value - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
368
+ const suggestedPct = adjust.max > adjust.min ? (suggested - adjust.min) / (adjust.max - adjust.min) * 100 : 0;
369
+ const moved = value !== suggested;
370
+ const commit = (raw) => {
371
+ const v = clampToRange(raw, adjust);
372
+ setValue(v);
373
+ setText(String(v));
374
+ };
375
+ return /* @__PURE__ */ jsxs(
376
+ "div",
377
+ {
378
+ className: "dc-rise",
379
+ "data-testid": "decision-card-adjuster",
380
+ style: {
381
+ display: "flex",
382
+ flexDirection: "column",
383
+ gap: 12,
384
+ border: `1px solid ${border}`,
385
+ borderRadius: 10,
386
+ padding: "12px 14px",
387
+ background: "#fafafa"
388
+ },
389
+ children: [
390
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 8 }, children: [
391
+ /* @__PURE__ */ jsxs("span", { style: { fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.06em", color: muted }, children: [
392
+ "Adjust \xB7 ",
393
+ option.label
394
+ ] }),
395
+ /* @__PURE__ */ jsx("span", { style: { flex: 1 } }),
396
+ /* @__PURE__ */ jsx(
397
+ "button",
398
+ {
399
+ type: "button",
400
+ onClick: onBack,
401
+ "data-testid": "decision-card-adjust-back",
402
+ style: { border: "none", background: "none", padding: 0, cursor: "pointer", fontSize: 12, fontWeight: 600, color: muted },
403
+ children: "Back"
404
+ }
405
+ )
406
+ ] }),
407
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 6 }, children: [
408
+ /* @__PURE__ */ jsx(
409
+ "input",
410
+ {
411
+ value: text,
412
+ onChange: (e) => {
413
+ setText(e.target.value);
414
+ const n = Number(e.target.value);
415
+ if (Number.isFinite(n)) setValue(clampToRange(n, adjust));
416
+ },
417
+ onBlur: () => commit(Number(text) || suggested),
418
+ onKeyDown: (e) => {
419
+ if (e.key === "Enter") {
420
+ const v = clampToRange(Number(text) || suggested, adjust);
421
+ commit(v);
422
+ onConfirm(v);
423
+ } else if (e.key === "ArrowUp") {
424
+ e.preventDefault();
425
+ commit(value + step);
426
+ } else if (e.key === "ArrowDown") {
427
+ e.preventDefault();
428
+ commit(value - step);
429
+ }
430
+ },
431
+ inputMode: "decimal",
432
+ "aria-label": `${option.label} value`,
433
+ "data-testid": "decision-card-adjust-input",
434
+ style: {
435
+ width: `${Math.max(3, String(text).length + 1)}ch`,
436
+ fontSize: 26,
437
+ fontWeight: 700,
438
+ fontVariantNumeric: "tabular-nums",
439
+ letterSpacing: "-0.02em",
440
+ color: "var(--foreground)",
441
+ border: "none",
442
+ borderBottom: `2px solid ${accent}`,
443
+ background: "transparent",
444
+ outline: "none",
445
+ padding: 0
446
+ }
447
+ }
448
+ ),
449
+ adjust.unit && /* @__PURE__ */ jsx("span", { style: { fontSize: 13, fontWeight: 600, color: muted }, children: adjust.unit }),
450
+ moved && /* @__PURE__ */ jsxs(
451
+ "button",
452
+ {
453
+ type: "button",
454
+ onClick: () => commit(suggested),
455
+ "data-testid": "decision-card-adjust-reset",
456
+ style: {
457
+ marginLeft: 8,
458
+ border: "none",
459
+ background: "none",
460
+ padding: 0,
461
+ cursor: "pointer",
462
+ fontSize: 11.5,
463
+ fontWeight: 600,
464
+ color: muted,
465
+ textDecoration: "underline",
466
+ textUnderlineOffset: 2
467
+ },
468
+ children: [
469
+ "Reset to suggested (",
470
+ formatFigure(suggested, adjust.unit),
471
+ ")"
472
+ ]
473
+ }
474
+ )
475
+ ] }),
476
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
477
+ /* @__PURE__ */ jsxs("div", { style: { position: "relative", height: 16, display: "flex", alignItems: "center" }, children: [
478
+ /* @__PURE__ */ jsx(
479
+ "div",
480
+ {
481
+ "aria-hidden": "true",
482
+ style: {
483
+ position: "absolute",
484
+ left: 0,
485
+ right: 0,
486
+ height: 4,
487
+ borderRadius: 9999,
488
+ background: `linear-gradient(to right, ${accent} ${pct}%, #e8e8e8 ${pct}%)`
489
+ }
490
+ }
491
+ ),
492
+ moved && /* @__PURE__ */ jsx(
493
+ "div",
494
+ {
495
+ "aria-hidden": "true",
496
+ title: `Suggested: ${formatFigure(suggested, adjust.unit)}`,
497
+ style: {
498
+ position: "absolute",
499
+ left: `${suggestedPct}%`,
500
+ transform: "translateX(-50%)",
501
+ width: 2,
502
+ height: 10,
503
+ borderRadius: 1,
504
+ background: muted,
505
+ opacity: 0.55
506
+ }
507
+ }
508
+ ),
509
+ /* @__PURE__ */ jsx(
510
+ "input",
511
+ {
512
+ type: "range",
513
+ className: "dc-range",
514
+ min: adjust.min,
515
+ max: adjust.max,
516
+ step,
517
+ value,
518
+ onChange: (e) => commit(Number(e.target.value)),
519
+ "aria-label": `${option.label} slider`,
520
+ "data-testid": "decision-card-adjust-slider",
521
+ style: { position: "relative", ["--dc-thumb"]: accent }
522
+ }
523
+ )
524
+ ] }),
525
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 10.5, fontWeight: 600, color: muted, fontVariantNumeric: "tabular-nums" }, children: [
526
+ /* @__PURE__ */ jsx("span", { children: formatFigure(adjust.min, adjust.unit) }),
527
+ /* @__PURE__ */ jsx("span", { children: formatFigure(adjust.max, adjust.unit) })
528
+ ] })
529
+ ] }),
530
+ /* @__PURE__ */ jsxs(
531
+ "button",
532
+ {
533
+ type: "button",
534
+ onClick: () => onConfirm(value),
535
+ "data-testid": "decision-card-adjust-confirm",
536
+ style: {
537
+ alignSelf: "flex-start",
538
+ border: `1px solid ${accent}`,
539
+ background: accent,
540
+ color: "white",
541
+ borderRadius: 8,
542
+ fontSize: 13,
543
+ fontWeight: 600,
544
+ padding: "9px 16px",
545
+ cursor: "pointer",
546
+ fontVariantNumeric: "tabular-nums",
547
+ transition: "opacity 0.15s"
548
+ },
549
+ onMouseEnter: (e) => e.currentTarget.style.opacity = "0.88",
550
+ onMouseLeave: (e) => e.currentTarget.style.opacity = "1",
551
+ children: [
552
+ option.label,
553
+ " \xB7 ",
554
+ formatFigure(value, adjust.unit)
555
+ ]
556
+ }
557
+ )
558
+ ]
559
+ }
560
+ );
561
+ }
333
562
  function DecisionCardRenderer({
334
563
  data,
335
564
  resolved = null,
336
565
  onResolve,
337
- onOpenSource
566
+ onOpenSource,
567
+ eyebrow
338
568
  }) {
339
- var _a, _b;
569
+ var _a, _b, _c;
340
570
  const { BORDER: BORDER2, MUTED: MUTED2, ACCENT: ACCENT2, ACCENT_SOFT: ACCENT_SOFT2 } = useTheme();
341
571
  const rootRef = React4.useRef(null);
342
572
  const width = useContainerWidth(rootRef);
343
573
  const stacked = width > 0 && width < STACK_BELOW;
574
+ const [adjustingIdx, setAdjustingIdx] = React4.useState(null);
344
575
  const options = (_a = data.options) != null ? _a : [];
345
576
  const recommendedIdx = Math.max(
346
577
  0,
@@ -439,7 +670,7 @@ function DecisionCardRenderer({
439
670
  },
440
671
  children: [
441
672
  /* @__PURE__ */ jsxs("div", { style: { minWidth: 0, display: "flex", flexDirection: "column", gap: 4 }, children: [
442
- /* @__PURE__ */ jsx(
673
+ eyebrow === null ? null : /* @__PURE__ */ jsx(
443
674
  "span",
444
675
  {
445
676
  style: {
@@ -449,7 +680,7 @@ function DecisionCardRenderer({
449
680
  fontWeight: 700,
450
681
  color: ACCENT2
451
682
  },
452
- children: data.decision_type ? `Decision needs you \xB7 ${data.decision_type}` : "Decision needs you"
683
+ children: eyebrow !== void 0 ? eyebrow : data.decision_type ? `Decision needs you \xB7 ${data.decision_type}` : "Decision needs you"
453
684
  }
454
685
  ),
455
686
  /* @__PURE__ */ jsx(
@@ -495,7 +726,20 @@ function DecisionCardRenderer({
495
726
  ]
496
727
  }
497
728
  ) : /* @__PURE__ */ jsxs(Fragment, { children: [
498
- /* @__PURE__ */ jsx(
729
+ adjustingIdx != null && ((_b = options[adjustingIdx]) == null ? void 0 : _b.adjust) ? /* @__PURE__ */ jsx(
730
+ ValueAdjuster,
731
+ {
732
+ option: options[adjustingIdx],
733
+ accent: ACCENT2,
734
+ border: BORDER2,
735
+ muted: MUTED2,
736
+ onBack: () => setAdjustingIdx(null),
737
+ onConfirm: (value) => {
738
+ setAdjustingIdx(null);
739
+ onResolve == null ? void 0 : onResolve(options[adjustingIdx].label, value);
740
+ }
741
+ }
742
+ ) : /* @__PURE__ */ jsx(
499
743
  "div",
500
744
  {
501
745
  style: {
@@ -505,15 +749,21 @@ function DecisionCardRenderer({
505
749
  gap: 8
506
750
  },
507
751
  children: options.map((opt, idx) => {
508
- var _a2;
752
+ var _a2, _b2;
509
753
  const primary = idx === recommendedIdx;
510
- return /* @__PURE__ */ jsx(
754
+ const adjustable = Boolean(opt.adjust);
755
+ return /* @__PURE__ */ jsxs(
511
756
  "button",
512
757
  {
513
758
  type: "button",
514
- onClick: () => onResolve == null ? void 0 : onResolve(opt.label),
759
+ onClick: () => adjustable ? setAdjustingIdx(idx) : onResolve == null ? void 0 : onResolve(opt.label),
760
+ "data-adjustable": adjustable || void 0,
515
761
  style: {
516
762
  width: stacked ? "100%" : "auto",
763
+ display: "inline-flex",
764
+ alignItems: "center",
765
+ justifyContent: stacked ? "flex-start" : "center",
766
+ gap: 7,
517
767
  textAlign: stacked ? "left" : "center",
518
768
  border: `1px solid ${primary ? ACCENT2 : BORDER2}`,
519
769
  background: primary ? ACCENT2 : "white",
@@ -541,7 +791,28 @@ function DecisionCardRenderer({
541
791
  e.currentTarget.style.background = "white";
542
792
  }
543
793
  },
544
- children: opt.label
794
+ children: [
795
+ opt.label,
796
+ adjustable && typeof opt.value === "number" && /* @__PURE__ */ jsxs(
797
+ "span",
798
+ {
799
+ style: {
800
+ fontSize: 11.5,
801
+ fontWeight: 700,
802
+ fontVariantNumeric: "tabular-nums",
803
+ padding: "1px 7px",
804
+ borderRadius: 9999,
805
+ background: primary ? "rgba(255,255,255,0.22)" : "#f2f2f2",
806
+ color: primary ? "white" : MUTED2,
807
+ lineHeight: 1.5
808
+ },
809
+ children: [
810
+ formatFigure(opt.value, (_b2 = opt.adjust) == null ? void 0 : _b2.unit),
811
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { marginLeft: 4, opacity: 0.8 }, children: "\u270E" })
812
+ ]
813
+ }
814
+ )
815
+ ]
545
816
  },
546
817
  (_a2 = opt.id) != null ? _a2 : opt.label
547
818
  );
@@ -580,7 +851,7 @@ function DecisionCardRenderer({
580
851
  strokeLinejoin: "round"
581
852
  }
582
853
  ) }),
583
- (_b = data.source.label) != null ? _b : "View source for this figure"
854
+ (_c = data.source.label) != null ? _c : "View source for this figure"
584
855
  ]
585
856
  }
586
857
  )
@@ -589,20 +860,27 @@ function DecisionCardRenderer({
589
860
  }
590
861
  );
591
862
  }
863
+ function composeResolution(p, option, value) {
864
+ var _a, _b, _c;
865
+ if (value == null) return option;
866
+ const unit = (_c = (_b = ((_a = p.options) != null ? _a : []).find((o) => o.label === option)) == null ? void 0 : _b.adjust) == null ? void 0 : _c.unit;
867
+ return `${option} \xB7 ${formatFigure(value, unit)}`;
868
+ }
592
869
  function DecisionCardResolver(p) {
593
- var _a, _b, _c, _d;
870
+ var _a, _b;
594
871
  const { resolvedDecisions, onDecisionResolve, onDecisionSource } = useGenUIInteraction();
595
872
  const decisionId = (_a = p.id) != null ? _a : p.title;
596
873
  const hostResolved = resolvedDecisions == null ? void 0 : resolvedDecisions[decisionId];
597
- const initial = (_c = hostResolved != null ? hostResolved : (_b = p.resolved) == null ? void 0 : _b.option) != null ? _c : null;
874
+ const initial = hostResolved != null ? hostResolved : p.resolved ? composeResolution(p, p.resolved.option, p.resolved.value) : null;
598
875
  const [localResolved, setLocalResolved] = React4.useState(initial);
599
876
  React4.useEffect(() => {
600
877
  if (hostResolved !== void 0) setLocalResolved(hostResolved);
601
878
  }, [hostResolved]);
602
879
  const resolved = hostResolved != null ? hostResolved : localResolved;
603
- const handleResolve = (option) => {
604
- setLocalResolved(option);
605
- onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, option);
880
+ const handleResolve = (option, value) => {
881
+ const resolution = composeResolution(p, option, value);
882
+ setLocalResolved(resolution);
883
+ onDecisionResolve == null ? void 0 : onDecisionResolve(decisionId, resolution);
606
884
  };
607
885
  const handleSource = () => {
608
886
  var _a2;
@@ -611,7 +889,7 @@ function DecisionCardResolver(p) {
611
889
  window.open(p.source.url, "_blank", "noopener,noreferrer");
612
890
  }
613
891
  };
614
- return /* @__PURE__ */ jsx(ComponentActions, { filename: (_d = p.title) != null ? _d : "decision-card", children: /* @__PURE__ */ jsx(
892
+ return /* @__PURE__ */ jsx(ComponentActions, { filename: (_b = p.title) != null ? _b : "decision-card", children: /* @__PURE__ */ jsx(
615
893
  DecisionCardRenderer,
616
894
  {
617
895
  data: p,
@@ -622,6 +900,6 @@ function DecisionCardResolver(p) {
622
900
  ) });
623
901
  }
624
902
 
625
- export { DecisionCardRenderer, DecisionCardResolver };
903
+ export { DecisionCardRenderer, DecisionCardResolver, formatFigure };
626
904
  //# sourceMappingURL=resolver.js.map
627
905
  //# sourceMappingURL=resolver.js.map