executable-stories-react 0.6.0 → 0.7.0

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.
package/dist/index.cjs CHANGED
@@ -59,6 +59,7 @@ __export(src_exports, {
59
59
  ReportSchemaError: () => ReportSchemaError,
60
60
  ReportStepItem: () => ReportStepItem,
61
61
  ReportSteps: () => ReportSteps,
62
+ ReportStoryboard: () => ReportStoryboard,
62
63
  ReportSummary: () => ReportSummary,
63
64
  ReportSummaryView: () => ReportSummaryView,
64
65
  ReportTrace: () => ReportTrace,
@@ -299,7 +300,7 @@ function DocLink({ entry }) {
299
300
  // src/components/doc/DocSection.tsx
300
301
  var import_marked = require("marked");
301
302
 
302
- // src/lib/url.ts
303
+ // ../executable-stories-core/dist/utils/url.js
303
304
  function safeUrl(value) {
304
305
  if (!value) return void 0;
305
306
  const trimmed = value.trim();
@@ -594,18 +595,101 @@ function ReportStepItem({ step }) {
594
595
  );
595
596
  }
596
597
 
597
- // src/components/ReportAttachments.tsx
598
+ // ../executable-stories-core/dist/storyboard.js
599
+ function findScreenshot(entries) {
600
+ for (const entry of entries) {
601
+ if (entry.kind === "screenshot") return entry;
602
+ if (entry.children) {
603
+ const nested = findScreenshot(entry.children);
604
+ if (nested) return nested;
605
+ }
606
+ }
607
+ return void 0;
608
+ }
609
+ function extractStoryboardFrames(scenario) {
610
+ const frames = [];
611
+ for (const step of scenario.steps) {
612
+ const shot = findScreenshot(step.docEntries);
613
+ if (!shot) continue;
614
+ frames.push({
615
+ stepId: step.id,
616
+ stepIndex: step.index,
617
+ keyword: step.keyword,
618
+ text: step.text,
619
+ status: step.status,
620
+ path: shot.path,
621
+ ...shot.alt !== void 0 && { alt: shot.alt }
622
+ });
623
+ }
624
+ return frames;
625
+ }
626
+
627
+ // src/components/ReportStoryboard.tsx
598
628
  var import_jsx_runtime18 = require("react/jsx-runtime");
629
+ var FRAME_GLYPH = {
630
+ passed: "\u2713",
631
+ failed: "\u2717",
632
+ skipped: "\u25CB",
633
+ pending: "\u25CB"
634
+ };
635
+ var FRAME_GLYPH_COLOR = {
636
+ passed: "text-pass",
637
+ failed: "text-fail",
638
+ skipped: "text-skip",
639
+ pending: "text-pend"
640
+ };
641
+ function ReportStoryboard({ scenario }) {
642
+ const frames = extractStoryboardFrames(scenario);
643
+ if (frames.length < 2) return null;
644
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
645
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
646
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("ol", { className: "flex gap-3 overflow-x-auto pb-2", children: frames.map((frame) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(StoryboardFrameItem, { frame }, frame.stepId)) })
647
+ ] });
648
+ }
649
+ function StoryboardFrameItem({ frame }) {
650
+ const src = isLocalFsPath(frame.path) ? void 0 : safeImageUrl(frame.path);
651
+ const label = `${frame.keyword} ${frame.text}`;
652
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("li", { className: "w-40 shrink-0", children: [
653
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
654
+ "a",
655
+ {
656
+ href: `#${frame.stepId}`,
657
+ "aria-label": `Jump to step: ${label}`,
658
+ className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
659
+ children: src ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
660
+ "img",
661
+ {
662
+ src,
663
+ alt: frame.alt ?? label,
664
+ loading: "lazy",
665
+ className: "h-24 w-full bg-muted object-cover object-top"
666
+ }
667
+ ) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "flex h-24 w-full items-center justify-center border-b border-dashed border-border bg-muted px-2 text-center text-[0.6875rem] text-muted-foreground", children: "Screenshot unavailable" })
668
+ }
669
+ ),
670
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
671
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
672
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "min-w-0", children: [
673
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
674
+ " ",
675
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-muted-foreground", children: frame.alt ?? frame.text })
676
+ ] })
677
+ ] })
678
+ ] });
679
+ }
680
+
681
+ // src/components/ReportAttachments.tsx
682
+ var import_jsx_runtime19 = require("react/jsx-runtime");
599
683
  function ReportAttachments({ attachments }) {
600
684
  if (attachments.length === 0) return null;
601
685
  return (
602
686
  // role="group" (not a labelled <section>) so multiple scenarios' attachment
603
687
  // blocks don't create duplicate "Attachments" region landmarks.
604
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
688
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
605
689
  const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
606
690
  const isImage = att.mediaType.startsWith("image/");
607
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
608
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
691
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
692
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
609
693
  "img",
610
694
  {
611
695
  src: dataUri,
@@ -614,8 +698,8 @@ function ReportAttachments({ attachments }) {
614
698
  className: "max-w-full rounded-md border border-border"
615
699
  }
616
700
  ),
617
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
618
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
701
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
702
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
619
703
  "a",
620
704
  {
621
705
  href: dataUri,
@@ -624,7 +708,7 @@ function ReportAttachments({ attachments }) {
624
708
  children: [
625
709
  att.name,
626
710
  " ",
627
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "text-muted-foreground", children: [
711
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "text-muted-foreground", children: [
628
712
  "(",
629
713
  att.mediaType,
630
714
  ")"
@@ -712,7 +796,7 @@ function traceWindow(rows) {
712
796
  }
713
797
 
714
798
  // src/components/ReportTrace.tsx
715
- var import_jsx_runtime19 = require("react/jsx-runtime");
799
+ var import_jsx_runtime20 = require("react/jsx-runtime");
716
800
  var BAR_COLOR = {
717
801
  ok: "bg-pass",
718
802
  error: "bg-fail",
@@ -723,8 +807,8 @@ function ReportTrace({ spans }) {
723
807
  const rows = toTraceRows(spans);
724
808
  if (rows.length === 0) return null;
725
809
  const { minStartMs, totalMs } = traceWindow(rows);
726
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
727
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
810
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
811
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
728
812
  "Trace (",
729
813
  rows.length,
730
814
  " span",
@@ -733,11 +817,11 @@ function ReportTrace({ spans }) {
733
817
  formatDuration(totalMs),
734
818
  ")"
735
819
  ] }),
736
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
820
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
737
821
  const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
738
822
  const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
739
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("li", { className: "flex items-center gap-2", children: [
740
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
823
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("li", { className: "flex items-center gap-2", children: [
824
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
741
825
  "span",
742
826
  {
743
827
  className: "min-w-0 flex-1 truncate text-foreground",
@@ -746,14 +830,14 @@ function ReportTrace({ spans }) {
746
830
  children: row.name
747
831
  }
748
832
  ),
749
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
833
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
750
834
  "span",
751
835
  {
752
836
  className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
753
837
  style: { left: `${leftPct}%`, width: `${widthPct}%` }
754
838
  }
755
839
  ) }),
756
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
840
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
757
841
  ] }, `${row.spanId}-${i}`);
758
842
  }) })
759
843
  ] });
@@ -804,7 +888,7 @@ function flakinessOf(entries) {
804
888
  }
805
889
 
806
890
  // src/components/ScenarioRunHistory.tsx
807
- var import_jsx_runtime20 = require("react/jsx-runtime");
891
+ var import_jsx_runtime21 = require("react/jsx-runtime");
808
892
  var MAX_DOTS = 10;
809
893
  var DOT_COLOR = {
810
894
  passed: "bg-pass",
@@ -824,16 +908,16 @@ function ScenarioRunHistory({ scenarioId }) {
824
908
  const recent = entries.slice(-MAX_DOTS);
825
909
  const flaky = flakinessOf(recent) === "flaky";
826
910
  const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
827
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
828
- flaky ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
829
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
911
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
912
+ flaky ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
913
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
830
914
  "span",
831
915
  {
832
916
  role: "img",
833
917
  "aria-label": `Run history: ${summary}`,
834
918
  title: summary,
835
919
  className: "flex shrink-0 items-center gap-[3px]",
836
- children: recent.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
920
+ children: recent.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
837
921
  "span",
838
922
  {
839
923
  "aria-hidden": true,
@@ -872,9 +956,9 @@ function useScenarioActions() {
872
956
 
873
957
  // src/components/ui/card.tsx
874
958
  var React2 = require("react");
875
- var import_jsx_runtime21 = require("react/jsx-runtime");
959
+ var import_jsx_runtime22 = require("react/jsx-runtime");
876
960
  function Card({ className, ...props }) {
877
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
961
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
878
962
  "div",
879
963
  {
880
964
  "data-slot": "card",
@@ -887,7 +971,7 @@ function Card({ className, ...props }) {
887
971
  );
888
972
  }
889
973
  function CardHeader({ className, ...props }) {
890
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
974
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
891
975
  "div",
892
976
  {
893
977
  "data-slot": "card-header",
@@ -900,7 +984,7 @@ function CardHeader({ className, ...props }) {
900
984
  );
901
985
  }
902
986
  function CardContent({ className, ...props }) {
903
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
987
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
904
988
  "div",
905
989
  {
906
990
  "data-slot": "card-content",
@@ -914,13 +998,13 @@ function CardContent({ className, ...props }) {
914
998
  var React3 = require("react");
915
999
  var import_menu = require("@base-ui/react/menu");
916
1000
  var import_lucide_react = require("lucide-react");
917
- var import_jsx_runtime22 = require("react/jsx-runtime");
1001
+ var import_jsx_runtime23 = require("react/jsx-runtime");
918
1002
  var itemClasses = "relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 [&_svg:not([class*='text-'])]:text-muted-foreground";
919
1003
  function DropdownMenu(props) {
920
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
1004
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
921
1005
  }
922
1006
  function DropdownMenuTrigger(props) {
923
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
1007
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
924
1008
  }
925
1009
  function DropdownMenuContent({
926
1010
  className,
@@ -928,14 +1012,14 @@ function DropdownMenuContent({
928
1012
  sideOffset = 4,
929
1013
  ...props
930
1014
  }) {
931
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1015
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
932
1016
  import_menu.Menu.Positioner,
933
1017
  {
934
1018
  "data-slot": "dropdown-menu-positioner",
935
1019
  className: "z-50",
936
1020
  align,
937
1021
  sideOffset,
938
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1022
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
939
1023
  import_menu.Menu.Popup,
940
1024
  {
941
1025
  "data-slot": "dropdown-menu-content",
@@ -953,7 +1037,7 @@ function DropdownMenuItem({
953
1037
  className,
954
1038
  ...props
955
1039
  }) {
956
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1040
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
957
1041
  import_menu.Menu.Item,
958
1042
  {
959
1043
  "data-slot": "dropdown-menu-item",
@@ -965,7 +1049,7 @@ function DropdownMenuItem({
965
1049
 
966
1050
  // src/components/ReportScenario.tsx
967
1051
  var import_lucide_react2 = require("lucide-react");
968
- var import_jsx_runtime23 = require("react/jsx-runtime");
1052
+ var import_jsx_runtime24 = require("react/jsx-runtime");
969
1053
  var STATUS_META = {
970
1054
  passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
971
1055
  failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
@@ -981,7 +1065,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
981
1065
  const collapsible = collapse !== null && !hideTitle;
982
1066
  const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
983
1067
  const actions = useScenarioActions();
984
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
1068
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
985
1069
  Card,
986
1070
  {
987
1071
  id: scenario.id,
@@ -989,10 +1073,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
989
1073
  ...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
990
1074
  className: "gap-0 py-0",
991
1075
  children: [
992
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(CardHeader, { className: "px-4 py-3", children: [
993
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
994
- hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
995
- collapsible ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1076
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(CardHeader, { className: "px-4 py-3", children: [
1077
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
1078
+ hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
1079
+ collapsible ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
996
1080
  "button",
997
1081
  {
998
1082
  type: "button",
@@ -1001,49 +1085,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
1001
1085
  "aria-controls": bodyId,
1002
1086
  "aria-label": `Toggle ${scenario.title}`,
1003
1087
  className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
1004
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
1088
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
1005
1089
  }
1006
1090
  ) : null,
1007
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
1008
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: scenario.title })
1091
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
1092
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: scenario.title })
1009
1093
  ] }),
1010
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
1011
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
1012
- scenario.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
1013
- meta.showPill ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "sr-only", children: `Status: ${label}` }),
1014
- actions ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenu, { children: [
1015
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1094
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
1095
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
1096
+ scenario.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
1097
+ meta.showPill ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "sr-only", children: `Status: ${label}` }),
1098
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DropdownMenu, { children: [
1099
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1016
1100
  DropdownMenuTrigger,
1017
1101
  {
1018
1102
  "aria-label": `Actions for ${scenario.title}`,
1019
1103
  className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
1020
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
1104
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
1021
1105
  }
1022
1106
  ),
1023
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenuContent, { align: "end", children: [
1024
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
1025
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react2.LinkIcon, {}),
1107
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DropdownMenuContent, { align: "end", children: [
1108
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
1109
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react2.LinkIcon, {}),
1026
1110
  " Copy link"
1027
1111
  ] }),
1028
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
1029
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react2.FileTextIcon, {}),
1112
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
1113
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react2.FileTextIcon, {}),
1030
1114
  " Copy as Markdown"
1031
1115
  ] }),
1032
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
1033
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react2.SparklesIcon, {}),
1116
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
1117
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react2.SparklesIcon, {}),
1034
1118
  " Explain with AI"
1035
1119
  ] })
1036
1120
  ] })
1037
1121
  ] }) : null
1038
1122
  ] })
1039
1123
  ] }),
1040
- scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
1041
- scenario.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
1042
- (scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("li", { children: ticket.url ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
1124
+ scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
1125
+ scenario.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
1126
+ (scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { children: ticket.url ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
1043
1127
  ] }) : null
1044
1128
  ] }),
1045
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
1046
- scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1129
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
1130
+ scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1047
1131
  "pre",
1048
1132
  {
1049
1133
  role: "alert",
@@ -1051,10 +1135,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
1051
1135
  children: scenario.errorMessage
1052
1136
  }
1053
1137
  ) : null,
1054
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ReportSteps, { scenario }),
1055
- scenario.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
1056
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ReportAttachments, { attachments: scenario.attachments }),
1057
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ReportTrace, { spans: scenario.otelSpans })
1138
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ReportStoryboard, { scenario }),
1139
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ReportSteps, { scenario }),
1140
+ scenario.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
1141
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ReportAttachments, { attachments: scenario.attachments }),
1142
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ReportTrace, { spans: scenario.otelSpans })
1058
1143
  ] })
1059
1144
  ]
1060
1145
  }
@@ -1062,13 +1147,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
1062
1147
  }
1063
1148
 
1064
1149
  // src/components/ReportScenarioList.tsx
1065
- var import_jsx_runtime24 = require("react/jsx-runtime");
1150
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1066
1151
  function ReportScenarioList({ feature }) {
1067
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_jsx_runtime24.Fragment, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ReportScenario, { scenario }, scenario.id)) });
1152
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_jsx_runtime25.Fragment, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportScenario, { scenario }, scenario.id)) });
1068
1153
  }
1069
1154
 
1070
1155
  // src/components/ReportFeature.tsx
1071
- var import_jsx_runtime25 = require("react/jsx-runtime");
1156
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1072
1157
  function ReportFeature({ feature }) {
1073
1158
  const titleId = `${feature.id}-title`;
1074
1159
  const bodyId = `${feature.id}-body`;
@@ -1079,7 +1164,7 @@ function ReportFeature({ feature }) {
1079
1164
  return (
1080
1165
  // Suite = a section heading + a divider, NOT another bordered card. Drops a
1081
1166
  // layer of nesting so the scenario cards below read as the primary unit.
1082
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1167
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
1083
1168
  "section",
1084
1169
  {
1085
1170
  id: feature.id,
@@ -1087,9 +1172,9 @@ function ReportFeature({ feature }) {
1087
1172
  "aria-labelledby": titleId,
1088
1173
  className: "flex flex-col gap-3",
1089
1174
  children: [
1090
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
1091
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "min-w-0", children: [
1092
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1175
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
1176
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "min-w-0", children: [
1177
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
1093
1178
  "button",
1094
1179
  {
1095
1180
  type: "button",
@@ -1098,31 +1183,31 @@ function ReportFeature({ feature }) {
1098
1183
  "aria-controls": bodyId,
1099
1184
  className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
1100
1185
  children: [
1101
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
1102
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "truncate", children: feature.title })
1186
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
1187
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "truncate", children: feature.title })
1103
1188
  ]
1104
1189
  }
1105
1190
  ) : feature.title }),
1106
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
1191
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
1107
1192
  ] }),
1108
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1193
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
1109
1194
  "p",
1110
1195
  {
1111
1196
  className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
1112
1197
  "aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
1113
1198
  children: [
1114
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { children: [
1199
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { children: [
1115
1200
  s.passed,
1116
1201
  " passed"
1117
1202
  ] }),
1118
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1119
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
1203
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1204
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
1120
1205
  s.failed,
1121
1206
  " failed"
1122
1207
  ] }),
1123
- skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
1124
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1125
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { children: [
1208
+ skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
1209
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1210
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { children: [
1126
1211
  skipped,
1127
1212
  " skipped"
1128
1213
  ] })
@@ -1131,7 +1216,7 @@ function ReportFeature({ feature }) {
1131
1216
  }
1132
1217
  )
1133
1218
  ] }),
1134
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportScenarioList, { feature }) })
1219
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportScenarioList, { feature }) })
1135
1220
  ]
1136
1221
  }
1137
1222
  )
@@ -1139,17 +1224,17 @@ function ReportFeature({ feature }) {
1139
1224
  }
1140
1225
 
1141
1226
  // src/components/ReportFeatureList.tsx
1142
- var import_jsx_runtime26 = require("react/jsx-runtime");
1227
+ var import_jsx_runtime27 = require("react/jsx-runtime");
1143
1228
  function ReportFeatureList() {
1144
1229
  const report = useReport();
1145
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportFeature, { feature }, feature.id)) });
1230
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportFeature, { feature }, feature.id)) });
1146
1231
  }
1147
1232
 
1148
1233
  // src/components/ui/empty.tsx
1149
1234
  var import_class_variance_authority2 = require("class-variance-authority");
1150
- var import_jsx_runtime27 = require("react/jsx-runtime");
1235
+ var import_jsx_runtime28 = require("react/jsx-runtime");
1151
1236
  function Empty({ className, ...props }) {
1152
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1237
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1153
1238
  "div",
1154
1239
  {
1155
1240
  "data-slot": "empty",
@@ -1162,7 +1247,7 @@ function Empty({ className, ...props }) {
1162
1247
  );
1163
1248
  }
1164
1249
  function EmptyHeader({ className, ...props }) {
1165
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1250
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1166
1251
  "div",
1167
1252
  {
1168
1253
  "data-slot": "empty-header",
@@ -1189,7 +1274,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
1189
1274
  }
1190
1275
  );
1191
1276
  function EmptyTitle({ className, ...props }) {
1192
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1277
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1193
1278
  "div",
1194
1279
  {
1195
1280
  "data-slot": "empty-title",
@@ -1200,16 +1285,16 @@ function EmptyTitle({ className, ...props }) {
1200
1285
  }
1201
1286
 
1202
1287
  // src/components/ReportEmpty.tsx
1203
- var import_jsx_runtime28 = require("react/jsx-runtime");
1288
+ var import_jsx_runtime29 = require("react/jsx-runtime");
1204
1289
  function ReportEmpty({ message }) {
1205
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(EmptyHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
1290
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(EmptyHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
1206
1291
  }
1207
1292
 
1208
1293
  // src/components/ReportSummary.tsx
1209
- var import_jsx_runtime29 = require("react/jsx-runtime");
1294
+ var import_jsx_runtime30 = require("react/jsx-runtime");
1210
1295
  function ReportSummary({ className }) {
1211
1296
  const report = useReport();
1212
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1297
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1213
1298
  ReportSummaryView,
1214
1299
  {
1215
1300
  summary: report.summary,
@@ -1235,7 +1320,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1235
1320
  if (summary.pending > 0) {
1236
1321
  cards.push({ status: "pending", label: "Pending", value: summary.pending });
1237
1322
  }
1238
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1323
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1239
1324
  "dl",
1240
1325
  {
1241
1326
  className: cn(
@@ -1248,17 +1333,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1248
1333
  "aria-label": ariaLabel,
1249
1334
  children: cards.map((c) => {
1250
1335
  const tone = TONE[c.status];
1251
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
1336
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
1252
1337
  "div",
1253
1338
  {
1254
1339
  "data-status": c.status,
1255
1340
  className: "rounded-lg border bg-card px-4 py-3",
1256
1341
  children: [
1257
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
1258
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
1342
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
1343
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
1259
1344
  c.label
1260
1345
  ] }),
1261
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
1346
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
1262
1347
  ]
1263
1348
  },
1264
1349
  c.status
@@ -1318,7 +1403,7 @@ function prUrl(ci) {
1318
1403
  }
1319
1404
 
1320
1405
  // src/components/ReportMeta.tsx
1321
- var import_jsx_runtime30 = require("react/jsx-runtime");
1406
+ var import_jsx_runtime31 = require("react/jsx-runtime");
1322
1407
  function ReportMeta() {
1323
1408
  const report = useReport();
1324
1409
  const items = [];
@@ -1341,13 +1426,13 @@ function ReportMeta() {
1341
1426
  const short = sha.slice(0, 8);
1342
1427
  items.push({
1343
1428
  label: "Commit",
1344
- value: url ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
1429
+ value: url ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
1345
1430
  });
1346
1431
  }
1347
1432
  if (report.ci) {
1348
1433
  items.push({
1349
1434
  label: "CI",
1350
- value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
1435
+ value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
1351
1436
  ciDisplayName(report.ci.name),
1352
1437
  report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
1353
1438
  ] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
@@ -1358,7 +1443,7 @@ function ReportMeta() {
1358
1443
  const label = `#${report.ci.prNumber}`;
1359
1444
  items.push({
1360
1445
  label: "PR",
1361
- value: url ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1446
+ value: url ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1362
1447
  });
1363
1448
  }
1364
1449
  if (items.length === 0) return null;
@@ -1366,48 +1451,48 @@ function ReportMeta() {
1366
1451
  // Run metadata is useful but secondary to "what failed" — tuck it into a
1367
1452
  // collapsed disclosure so it doesn't push the result down. Native <details>
1368
1453
  // so it works with no JS (the SSR/no-hydration report still toggles).
1369
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
1370
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("summary", { className: "flex cursor-pointer list-none select-none items-center gap-1.5 px-4 py-2 font-medium text-muted-foreground [&::-webkit-details-marker]:hidden", children: [
1371
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
1454
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
1455
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("summary", { className: "flex cursor-pointer list-none select-none items-center gap-1.5 px-4 py-2 font-medium text-muted-foreground [&::-webkit-details-marker]:hidden", children: [
1456
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
1372
1457
  "Run details"
1373
1458
  ] }),
1374
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("dl", { className: "flex flex-wrap gap-x-5 gap-y-2 border-t border-border px-4 py-3 text-muted-foreground", "aria-label": "Run metadata", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-baseline gap-1.5", children: [
1375
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("dt", { className: "font-medium", children: item.label }),
1376
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
1459
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("dl", { className: "flex flex-wrap gap-x-5 gap-y-2 border-t border-border px-4 py-3 text-muted-foreground", "aria-label": "Run metadata", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-baseline gap-1.5", children: [
1460
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("dt", { className: "font-medium", children: item.label }),
1461
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
1377
1462
  ] }, item.label)) })
1378
1463
  ] })
1379
1464
  );
1380
1465
  }
1381
1466
 
1382
1467
  // src/components/ReportSchemaError.tsx
1383
- var import_jsx_runtime31 = require("react/jsx-runtime");
1468
+ var import_jsx_runtime32 = require("react/jsx-runtime");
1384
1469
  function ReportSchemaError({ error }) {
1385
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
1386
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("strong", { children: "Report could not be displayed." }) }),
1387
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { children: error.message }),
1388
- error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("p", { children: [
1470
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
1471
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("strong", { children: "Report could not be displayed." }) }),
1472
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { children: error.message }),
1473
+ error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("p", { children: [
1389
1474
  "The report bundle is newer than this version of ",
1390
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("code", { children: "executable-stories-react" }),
1475
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("code", { children: "executable-stories-react" }),
1391
1476
  ". Upgrade the package, or regenerate the report with an older formatters CLI."
1392
1477
  ] }) : null,
1393
- error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("details", { children: [
1394
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("summary", { children: [
1478
+ error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("details", { children: [
1479
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("summary", { children: [
1395
1480
  error.issues.length,
1396
1481
  " validation issue",
1397
1482
  error.issues.length === 1 ? "" : "s"
1398
1483
  ] }),
1399
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
1484
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
1400
1485
  ] }) : null
1401
1486
  ] });
1402
1487
  }
1403
1488
 
1404
1489
  // src/components/ReportShell.tsx
1405
- var import_jsx_runtime32 = require("react/jsx-runtime");
1490
+ var import_jsx_runtime33 = require("react/jsx-runtime");
1406
1491
  function ReportTitleBlock({ title }) {
1407
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
1408
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("h1", { children: title ?? "Story Report" }),
1409
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ReportSummary, {}),
1410
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ReportMeta, {})
1492
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
1493
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("h1", { children: title ?? "Story Report" }),
1494
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ReportSummary, {}),
1495
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ReportMeta, {})
1411
1496
  ] });
1412
1497
  }
1413
1498
  function ReportErrorShell({
@@ -1416,28 +1501,28 @@ function ReportErrorShell({
1416
1501
  title,
1417
1502
  dataTheme
1418
1503
  }) {
1419
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ReportSchemaError, { error }) });
1504
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ReportSchemaError, { error }) });
1420
1505
  }
1421
1506
 
1422
1507
  // src/components/Report.tsx
1423
- var import_jsx_runtime33 = require("react/jsx-runtime");
1508
+ var import_jsx_runtime34 = require("react/jsx-runtime");
1424
1509
  function Report(props) {
1425
1510
  const { report, customRenderers, renderers, className, title, dataTheme } = props;
1426
1511
  const result = unwrapReport(report);
1427
1512
  if (!result.ok) {
1428
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
1513
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
1429
1514
  }
1430
1515
  const data = result.data;
1431
1516
  const hasContent = data.features.length > 0;
1432
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
1433
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ReportTitleBlock, { title }) }),
1434
- hasContent ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ReportEmpty, {})
1517
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
1518
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ReportTitleBlock, { title }) }),
1519
+ hasContent ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ReportEmpty, {})
1435
1520
  ] }) });
1436
1521
  }
1437
1522
 
1438
1523
  // src/components/doc/MermaidView.tsx
1439
1524
  var import_react8 = require("react");
1440
- var import_jsx_runtime34 = require("react/jsx-runtime");
1525
+ var import_jsx_runtime35 = require("react/jsx-runtime");
1441
1526
  function prefersDark(el) {
1442
1527
  const themed = el?.closest("[data-theme]");
1443
1528
  if (themed?.dataset.theme === "dark") return true;
@@ -1474,9 +1559,9 @@ function MermaidView({ entry, load }) {
1474
1559
  };
1475
1560
  }, [entry.code, load]);
1476
1561
  if (svg) {
1477
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("figure", { ref, className: "my-3", children: [
1478
- entry.title ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
1479
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1562
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("figure", { ref, className: "my-3", children: [
1563
+ entry.title ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
1564
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
1480
1565
  "div",
1481
1566
  {
1482
1567
  role: "img",
@@ -1487,18 +1572,18 @@ function MermaidView({ entry, load }) {
1487
1572
  )
1488
1573
  ] });
1489
1574
  }
1490
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(MermaidSource, { entry, ref });
1575
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(MermaidSource, { entry, ref });
1491
1576
  }
1492
1577
 
1493
1578
  // src/components/doc/MermaidDiagram.tsx
1494
- var import_jsx_runtime35 = require("react/jsx-runtime");
1579
+ var import_jsx_runtime36 = require("react/jsx-runtime");
1495
1580
  var mermaidLoader;
1496
1581
  function loadMermaid() {
1497
1582
  mermaidLoader ??= import("mermaid").then((m) => m.default);
1498
1583
  return mermaidLoader;
1499
1584
  }
1500
1585
  function MermaidDiagram({ entry, load = loadMermaid }) {
1501
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(MermaidView, { entry, load });
1586
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MermaidView, { entry, load });
1502
1587
  }
1503
1588
 
1504
1589
  // src/components/ScenarioExplorer.tsx
@@ -1508,12 +1593,12 @@ var import_react9 = require("react");
1508
1593
  var React4 = require("react");
1509
1594
  var import_cmdk = require("cmdk");
1510
1595
  var import_lucide_react3 = require("lucide-react");
1511
- var import_jsx_runtime36 = require("react/jsx-runtime");
1596
+ var import_jsx_runtime37 = require("react/jsx-runtime");
1512
1597
  function Command({
1513
1598
  className,
1514
1599
  ...props
1515
1600
  }) {
1516
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
1601
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1517
1602
  import_cmdk.Command,
1518
1603
  {
1519
1604
  "data-slot": "command",
@@ -1529,14 +1614,14 @@ function CommandInput({
1529
1614
  className,
1530
1615
  ...props
1531
1616
  }) {
1532
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
1617
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
1533
1618
  "div",
1534
1619
  {
1535
1620
  "data-slot": "command-input-wrapper",
1536
1621
  className: "flex h-9 items-center gap-2 border-b px-3",
1537
1622
  children: [
1538
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react3.SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
1539
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
1623
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react3.SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
1624
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1540
1625
  import_cmdk.Command.Input,
1541
1626
  {
1542
1627
  "data-slot": "command-input",
@@ -1555,7 +1640,7 @@ function CommandList({
1555
1640
  className,
1556
1641
  ...props
1557
1642
  }) {
1558
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
1643
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1559
1644
  import_cmdk.Command.List,
1560
1645
  {
1561
1646
  "data-slot": "command-list",
@@ -1570,7 +1655,7 @@ function CommandList({
1570
1655
  function CommandEmpty({
1571
1656
  ...props
1572
1657
  }) {
1573
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
1658
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1574
1659
  import_cmdk.Command.Empty,
1575
1660
  {
1576
1661
  "data-slot": "command-empty",
@@ -1583,7 +1668,7 @@ function CommandGroup({
1583
1668
  className,
1584
1669
  ...props
1585
1670
  }) {
1586
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
1671
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1587
1672
  import_cmdk.Command.Group,
1588
1673
  {
1589
1674
  "data-slot": "command-group",
@@ -1599,7 +1684,7 @@ function CommandItem({
1599
1684
  className,
1600
1685
  ...props
1601
1686
  }) {
1602
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
1687
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1603
1688
  import_cmdk.Command.Item,
1604
1689
  {
1605
1690
  "data-slot": "command-item",
@@ -1613,7 +1698,7 @@ function CommandItem({
1613
1698
  }
1614
1699
 
1615
1700
  // src/components/ScenarioExplorer.tsx
1616
- var import_jsx_runtime37 = require("react/jsx-runtime");
1701
+ var import_jsx_runtime38 = require("react/jsx-runtime");
1617
1702
  var STATUS_FILTERS = [
1618
1703
  { value: "all", label: "All" },
1619
1704
  { value: "passed", label: "Passed" },
@@ -1624,22 +1709,22 @@ var STATUS_FILTERS = [
1624
1709
  function ScenarioExplorer({ scenarios, summary }) {
1625
1710
  const [status, setStatus] = (0, import_react9.useState)("all");
1626
1711
  const visible = status === "all" ? scenarios : scenarios.filter((s) => s.status === status);
1627
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "font-sans text-foreground", children: [
1628
- summary ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("p", { className: "mb-3 text-sm text-muted-foreground", children: [
1712
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "font-sans text-foreground", children: [
1713
+ summary ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("p", { className: "mb-3 text-sm text-muted-foreground", children: [
1629
1714
  summary.total,
1630
1715
  " scenarios \xB7 ",
1631
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "text-pass", children: [
1716
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "text-pass", children: [
1632
1717
  summary.passed,
1633
1718
  " passed"
1634
1719
  ] }),
1635
1720
  " \xB7",
1636
1721
  " ",
1637
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "text-fail", children: [
1722
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "text-fail", children: [
1638
1723
  summary.failed,
1639
1724
  " failed"
1640
1725
  ] })
1641
1726
  ] }) : null,
1642
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "mb-2 flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by status", children: STATUS_FILTERS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1727
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "mb-2 flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by status", children: STATUS_FILTERS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
1643
1728
  "button",
1644
1729
  {
1645
1730
  type: "button",
@@ -1654,26 +1739,26 @@ function ScenarioExplorer({ scenarios, summary }) {
1654
1739
  },
1655
1740
  f.value
1656
1741
  )) }),
1657
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
1742
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
1658
1743
  Command,
1659
1744
  {
1660
1745
  className: "rounded-lg border border-border bg-card",
1661
1746
  filter: (value, search) => value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0,
1662
1747
  children: [
1663
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(CommandInput, { placeholder: "Search scenarios\u2026" }),
1664
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(CommandList, { className: "max-h-none", children: [
1665
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(CommandEmpty, { children: "No scenarios match your filters." }),
1666
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1748
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(CommandInput, { placeholder: "Search scenarios\u2026" }),
1749
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(CommandList, { className: "max-h-none", children: [
1750
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(CommandEmpty, { children: "No scenarios match your filters." }),
1751
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
1667
1752
  CommandItem,
1668
1753
  {
1669
1754
  value: `${s.title} ${s.feature} ${s.tags.join(" ")}`,
1670
1755
  asChild: true,
1671
1756
  className: "cursor-pointer",
1672
- children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("a", { href: s.href, className: "flex items-center gap-3", children: [
1673
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Badge, { variant: s.status, children: s.status }),
1674
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
1675
- s.tags.slice(0, 3).map((t) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
1676
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
1757
+ children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("a", { href: s.href, className: "flex items-center gap-3", children: [
1758
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Badge, { variant: s.status, children: s.status }),
1759
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
1760
+ s.tags.slice(0, 3).map((t) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
1761
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
1677
1762
  ] })
1678
1763
  },
1679
1764
  s.id
@@ -2694,6 +2779,7 @@ function parseStoryReport(input) {
2694
2779
  ReportSchemaError,
2695
2780
  ReportStepItem,
2696
2781
  ReportSteps,
2782
+ ReportStoryboard,
2697
2783
  ReportSummary,
2698
2784
  ReportSummaryView,
2699
2785
  ReportTrace,