executable-stories-react 0.4.1 → 0.5.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.js CHANGED
@@ -98,11 +98,15 @@ var badgeVariants = cva(
98
98
  outline: "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
99
99
  ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
100
100
  link: "text-primary underline-offset-4 [a&]:hover:underline",
101
- passed: "border-pass-border bg-pass-bg text-pass font-mono uppercase",
101
+ // Pass/skip/pending are the quiet states: outline + coloured text, no
102
+ // fill, so a green report reads calm. Only `failed` keeps a tinted
103
+ // fill, making it the single loud badge on the page, so red pops the
104
+ // instant something breaks. Colour-as-accent, matching the KPI cards.
105
+ passed: "border-pass-border text-pass font-mono uppercase",
102
106
  failed: "border-fail-border bg-fail-bg text-fail font-mono uppercase",
103
- skipped: "border-skip-border bg-skip-bg text-skip font-mono uppercase",
104
- pending: "border-pend-border bg-pend-bg text-pend font-mono uppercase",
105
- tag: "border-pass-border bg-pass-bg text-pass font-mono font-medium"
107
+ skipped: "border-skip-border text-skip font-mono uppercase",
108
+ pending: "border-pend-border text-pend font-mono uppercase",
109
+ tag: "border-border text-muted-foreground font-mono font-medium [a&]:hover:bg-muted"
106
110
  }
107
111
  },
108
112
  defaultVariants: {
@@ -655,7 +659,7 @@ function ReportTrace({ spans }) {
655
659
  {
656
660
  className: "min-w-0 flex-1 truncate text-foreground",
657
661
  style: { paddingLeft: `${row.depth * 12}px` },
658
- title: row.statusMessage ? `${row.name} \u2014 ${row.statusMessage}` : row.name,
662
+ title: row.statusMessage ? `${row.name}: ${row.statusMessage}` : row.name,
659
663
  children: row.name
660
664
  }
661
665
  ),
@@ -792,7 +796,7 @@ function Card({ className, ...props }) {
792
796
  {
793
797
  "data-slot": "card",
794
798
  className: cn(
795
- "flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm",
799
+ "flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-xs",
796
800
  className
797
801
  ),
798
802
  ...props
@@ -823,52 +827,89 @@ function CardContent({ className, ...props }) {
823
827
  );
824
828
  }
825
829
 
826
- // src/components/ReportScenario.tsx
830
+ // src/components/ui/dropdown-menu.tsx
831
+ import "react";
832
+ import { Menu as MenuPrimitive } from "@base-ui/react/menu";
833
+ import { CheckIcon } from "lucide-react";
827
834
  import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
828
- var STATUS_LABEL = {
829
- passed: "Passed",
830
- failed: "Failed",
831
- skipped: "Skipped",
832
- pending: "Pending"
833
- };
834
- var STATUS_GLYPH = {
835
- passed: "\u2713",
836
- failed: "\u2717",
837
- skipped: "\u25CB",
838
- pending: "\u25CB"
839
- };
840
- var STATUS_GLYPH_COLOR = {
841
- passed: "text-pass",
842
- failed: "text-fail",
843
- skipped: "text-skip",
844
- pending: "text-pend"
845
- };
846
- var STATUS_BADGE = {
847
- passed: "passed",
848
- failed: "failed",
849
- skipped: "skipped",
850
- pending: "pending"
835
+ 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";
836
+ function DropdownMenu(props) {
837
+ return /* @__PURE__ */ jsx22(MenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
838
+ }
839
+ function DropdownMenuTrigger(props) {
840
+ return /* @__PURE__ */ jsx22(MenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
841
+ }
842
+ function DropdownMenuContent({
843
+ className,
844
+ align = "end",
845
+ sideOffset = 4,
846
+ ...props
847
+ }) {
848
+ return /* @__PURE__ */ jsx22(MenuPrimitive.Portal, { children: /* @__PURE__ */ jsx22(
849
+ MenuPrimitive.Positioner,
850
+ {
851
+ "data-slot": "dropdown-menu-positioner",
852
+ className: "z-50",
853
+ align,
854
+ sideOffset,
855
+ children: /* @__PURE__ */ jsx22(
856
+ MenuPrimitive.Popup,
857
+ {
858
+ "data-slot": "dropdown-menu-content",
859
+ className: cn(
860
+ "z-50 min-w-[11rem] origin-[var(--transform-origin)] overflow-hidden rounded-md border border-border bg-popover p-1 font-sans text-sm text-popover-foreground shadow-md transition-[opacity,transform] data-[ending-style]:scale-95 data-[ending-style]:opacity-0 data-[starting-style]:scale-95 data-[starting-style]:opacity-0",
861
+ className
862
+ ),
863
+ ...props
864
+ }
865
+ )
866
+ }
867
+ ) });
868
+ }
869
+ function DropdownMenuItem({
870
+ className,
871
+ ...props
872
+ }) {
873
+ return /* @__PURE__ */ jsx22(
874
+ MenuPrimitive.Item,
875
+ {
876
+ "data-slot": "dropdown-menu-item",
877
+ className: cn(itemClasses, className),
878
+ ...props
879
+ }
880
+ );
881
+ }
882
+
883
+ // src/components/ReportScenario.tsx
884
+ import { LinkIcon, FileTextIcon, SparklesIcon, MoreHorizontalIcon } from "lucide-react";
885
+ import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
886
+ var STATUS_META = {
887
+ passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
888
+ failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
889
+ skipped: { label: "Skipped", glyph: "\u25CB", glyphColor: "text-skip", badgeVariant: "skipped", showPill: true },
890
+ pending: { label: "Pending", glyph: "\u25CB", glyphColor: "text-pend", badgeVariant: "pending", showPill: true }
851
891
  };
852
892
  function ReportScenario({ scenario, hideTitle = false }) {
853
893
  const titleId = `${scenario.id}-title`;
854
894
  const bodyId = `${scenario.id}-body`;
855
- const label = scenario.planned ? "Planned" : STATUS_LABEL[scenario.status];
895
+ const meta = STATUS_META[scenario.status];
896
+ const label = scenario.planned ? "Planned" : meta.label;
856
897
  const collapse = useCollapse();
857
898
  const collapsible = collapse !== null && !hideTitle;
858
899
  const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
859
900
  const actions = useScenarioActions();
860
- return /* @__PURE__ */ jsxs14(
901
+ return /* @__PURE__ */ jsxs15(
861
902
  Card,
862
903
  {
863
904
  id: scenario.id,
864
905
  "data-status": scenario.status,
865
- ...hideTitle ? { "aria-label": `${scenario.title} \u2014 ${label}` } : { "aria-labelledby": titleId },
906
+ ...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
866
907
  className: "gap-0 py-0",
867
908
  children: [
868
- /* @__PURE__ */ jsxs14(CardHeader, { className: "px-4 py-3", children: [
869
- /* @__PURE__ */ jsxs14("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
870
- hideTitle ? null : /* @__PURE__ */ jsxs14("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
871
- collapsible ? /* @__PURE__ */ jsx22(
909
+ /* @__PURE__ */ jsxs15(CardHeader, { className: "px-4 py-3", children: [
910
+ /* @__PURE__ */ jsxs15("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
911
+ hideTitle ? null : /* @__PURE__ */ jsxs15("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
912
+ collapsible ? /* @__PURE__ */ jsx23(
872
913
  "button",
873
914
  {
874
915
  type: "button",
@@ -877,60 +918,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
877
918
  "aria-controls": bodyId,
878
919
  "aria-label": `Toggle ${scenario.title}`,
879
920
  className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
880
- children: /* @__PURE__ */ jsx22("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
921
+ children: /* @__PURE__ */ jsx23("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
881
922
  }
882
923
  ) : null,
883
- /* @__PURE__ */ jsx22("span", { "aria-hidden": true, className: cn("text-sm leading-none", STATUS_GLYPH_COLOR[scenario.status]), children: STATUS_GLYPH[scenario.status] }),
884
- /* @__PURE__ */ jsx22("span", { children: scenario.title })
924
+ /* @__PURE__ */ jsx23("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
925
+ /* @__PURE__ */ jsx23("span", { children: scenario.title })
885
926
  ] }),
886
- /* @__PURE__ */ jsxs14("div", { className: "flex shrink-0 items-center gap-2", children: [
887
- /* @__PURE__ */ jsx22(ScenarioRunHistory, { scenarioId: scenario.id }),
888
- scenario.durationMs > 0 ? /* @__PURE__ */ jsx22("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
889
- /* @__PURE__ */ jsx22(Badge, { variant: STATUS_BADGE[scenario.status], "aria-label": `Status: ${label}`, children: label }),
890
- actions ? /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-0.5", children: [
891
- /* @__PURE__ */ jsx22(
892
- "button",
927
+ /* @__PURE__ */ jsxs15("div", { className: "flex shrink-0 items-center gap-2", children: [
928
+ /* @__PURE__ */ jsx23(ScenarioRunHistory, { scenarioId: scenario.id }),
929
+ scenario.durationMs > 0 ? /* @__PURE__ */ jsx23("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
930
+ meta.showPill ? /* @__PURE__ */ jsx23(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ jsx23("span", { className: "sr-only", children: `Status: ${label}` }),
931
+ actions ? /* @__PURE__ */ jsxs15(DropdownMenu, { children: [
932
+ /* @__PURE__ */ jsx23(
933
+ DropdownMenuTrigger,
893
934
  {
894
- type: "button",
895
- onClick: () => actions.copyLink(scenario),
896
- "aria-label": `Copy link to ${scenario.title}`,
897
- title: "Copy permalink",
898
- className: "cursor-pointer rounded px-1 py-0.5 font-mono text-[0.625rem] text-muted-foreground hover:bg-muted hover:text-foreground",
899
- children: "link"
935
+ "aria-label": `Actions for ${scenario.title}`,
936
+ className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
937
+ children: /* @__PURE__ */ jsx23(MoreHorizontalIcon, { "aria-hidden": true })
900
938
  }
901
939
  ),
902
- /* @__PURE__ */ jsx22(
903
- "button",
904
- {
905
- type: "button",
906
- onClick: () => actions.copyMarkdown(scenario),
907
- "aria-label": `Copy ${scenario.title} as Markdown`,
908
- title: "Copy as Markdown",
909
- className: "cursor-pointer rounded px-1 py-0.5 font-mono text-[0.625rem] text-muted-foreground hover:bg-muted hover:text-foreground",
910
- children: "md"
911
- }
912
- ),
913
- /* @__PURE__ */ jsx22(
914
- "button",
915
- {
916
- type: "button",
917
- onClick: () => actions.copyPrompt(scenario),
918
- "aria-label": `Copy ${scenario.title} as an AI investigation prompt`,
919
- title: "Copy as AI prompt",
920
- className: "cursor-pointer rounded px-1 py-0.5 font-mono text-[0.625rem] text-muted-foreground hover:bg-muted hover:text-foreground",
921
- children: "ai"
922
- }
923
- )
940
+ /* @__PURE__ */ jsxs15(DropdownMenuContent, { align: "end", children: [
941
+ /* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
942
+ /* @__PURE__ */ jsx23(LinkIcon, {}),
943
+ " Copy link"
944
+ ] }),
945
+ /* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
946
+ /* @__PURE__ */ jsx23(FileTextIcon, {}),
947
+ " Copy as Markdown"
948
+ ] }),
949
+ /* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
950
+ /* @__PURE__ */ jsx23(SparklesIcon, {}),
951
+ " Explain with AI"
952
+ ] })
953
+ ] })
924
954
  ] }) : null
925
955
  ] })
926
956
  ] }),
927
- scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs14("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
928
- scenario.tags.map((t) => /* @__PURE__ */ jsx22("li", { children: /* @__PURE__ */ jsx22(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
929
- (scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ jsx22("li", { children: ticket.url ? /* @__PURE__ */ jsx22("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ jsx22(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ jsx22(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
957
+ scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs15("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
958
+ scenario.tags.map((t) => /* @__PURE__ */ jsx23("li", { children: /* @__PURE__ */ jsx23(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
959
+ (scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ jsx23("li", { children: ticket.url ? /* @__PURE__ */ jsx23("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ jsx23(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ jsx23(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
930
960
  ] }) : null
931
961
  ] }),
932
- /* @__PURE__ */ jsxs14(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
933
- scenario.errorMessage ? /* @__PURE__ */ jsx22(
962
+ /* @__PURE__ */ jsxs15(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
963
+ scenario.errorMessage ? /* @__PURE__ */ jsx23(
934
964
  "pre",
935
965
  {
936
966
  role: "alert",
@@ -938,10 +968,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
938
968
  children: scenario.errorMessage
939
969
  }
940
970
  ) : null,
941
- /* @__PURE__ */ jsx22(ReportSteps, { scenario }),
942
- scenario.docEntries.length > 0 ? /* @__PURE__ */ jsx22("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ jsx22(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
943
- /* @__PURE__ */ jsx22(ReportAttachments, { attachments: scenario.attachments }),
944
- /* @__PURE__ */ jsx22(ReportTrace, { spans: scenario.otelSpans })
971
+ /* @__PURE__ */ jsx23(ReportSteps, { scenario }),
972
+ scenario.docEntries.length > 0 ? /* @__PURE__ */ jsx23("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ jsx23(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
973
+ /* @__PURE__ */ jsx23(ReportAttachments, { attachments: scenario.attachments }),
974
+ /* @__PURE__ */ jsx23(ReportTrace, { spans: scenario.otelSpans })
945
975
  ] })
946
976
  ]
947
977
  }
@@ -949,13 +979,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
949
979
  }
950
980
 
951
981
  // src/components/ReportScenarioList.tsx
952
- import { Fragment as Fragment8, jsx as jsx23 } from "react/jsx-runtime";
982
+ import { Fragment as Fragment8, jsx as jsx24 } from "react/jsx-runtime";
953
983
  function ReportScenarioList({ feature }) {
954
- return /* @__PURE__ */ jsx23(Fragment8, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ jsx23(ReportScenario, { scenario }, scenario.id)) });
984
+ return /* @__PURE__ */ jsx24(Fragment8, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ jsx24(ReportScenario, { scenario }, scenario.id)) });
955
985
  }
956
986
 
957
987
  // src/components/ReportFeature.tsx
958
- import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
988
+ import { Fragment as Fragment9, jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
959
989
  function ReportFeature({ feature }) {
960
990
  const titleId = `${feature.id}-title`;
961
991
  const bodyId = `${feature.id}-body`;
@@ -963,74 +993,80 @@ function ReportFeature({ feature }) {
963
993
  const skipped = s.skipped + s.pending;
964
994
  const collapse = useCollapse();
965
995
  const collapsed = collapse?.isCollapsed(feature.id) ?? false;
966
- return /* @__PURE__ */ jsxs15(
967
- "section",
968
- {
969
- id: feature.id,
970
- "data-slot": "feature",
971
- "aria-labelledby": titleId,
972
- className: "overflow-hidden rounded-xl border border-border bg-card shadow-sm",
973
- children: [
974
- /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between gap-4 border-b border-border bg-muted/40 px-4 py-3", children: [
975
- /* @__PURE__ */ jsxs15("div", { className: "flex min-w-0 items-center gap-2", children: [
976
- collapse ? /* @__PURE__ */ jsx24(
977
- "button",
996
+ return (
997
+ // Suite = a section heading + a divider, NOT another bordered card. Drops a
998
+ // layer of nesting so the scenario cards below read as the primary unit.
999
+ /* @__PURE__ */ jsxs16(
1000
+ "section",
1001
+ {
1002
+ id: feature.id,
1003
+ "data-slot": "feature",
1004
+ "aria-labelledby": titleId,
1005
+ className: "flex flex-col gap-3",
1006
+ children: [
1007
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
1008
+ /* @__PURE__ */ jsxs16("div", { className: "min-w-0", children: [
1009
+ /* @__PURE__ */ jsx25("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ jsxs16(
1010
+ "button",
1011
+ {
1012
+ type: "button",
1013
+ onClick: () => collapse.toggle(feature.id),
1014
+ "aria-expanded": !collapsed,
1015
+ "aria-controls": bodyId,
1016
+ className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
1017
+ children: [
1018
+ /* @__PURE__ */ jsx25("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
1019
+ /* @__PURE__ */ jsx25("span", { className: "truncate", children: feature.title })
1020
+ ]
1021
+ }
1022
+ ) : feature.title }),
1023
+ /* @__PURE__ */ jsx25("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
1024
+ ] }),
1025
+ /* @__PURE__ */ jsxs16(
1026
+ "p",
978
1027
  {
979
- type: "button",
980
- onClick: () => collapse.toggle(feature.id),
981
- "aria-expanded": !collapsed,
982
- "aria-controls": bodyId,
983
- "aria-label": `Toggle ${feature.title}`,
984
- className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
985
- children: /* @__PURE__ */ jsx24("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
1028
+ className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
1029
+ "aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
1030
+ children: [
1031
+ /* @__PURE__ */ jsxs16("span", { children: [
1032
+ s.passed,
1033
+ " passed"
1034
+ ] }),
1035
+ /* @__PURE__ */ jsx25("span", { "aria-hidden": true, children: "\xB7" }),
1036
+ /* @__PURE__ */ jsxs16("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
1037
+ s.failed,
1038
+ " failed"
1039
+ ] }),
1040
+ skipped > 0 ? /* @__PURE__ */ jsxs16(Fragment9, { children: [
1041
+ /* @__PURE__ */ jsx25("span", { "aria-hidden": true, children: "\xB7" }),
1042
+ /* @__PURE__ */ jsxs16("span", { children: [
1043
+ skipped,
1044
+ " skipped"
1045
+ ] })
1046
+ ] }) : null
1047
+ ]
986
1048
  }
987
- ) : null,
988
- /* @__PURE__ */ jsxs15("div", { className: "min-w-0", children: [
989
- /* @__PURE__ */ jsx24("h2", { id: titleId, className: "text-sm font-semibold tracking-tight text-foreground", children: feature.title }),
990
- /* @__PURE__ */ jsx24("p", { className: "mt-0.5 truncate font-mono text-xs text-muted-foreground", children: feature.sourceFile })
991
- ] })
1049
+ )
992
1050
  ] }),
993
- /* @__PURE__ */ jsxs15(
994
- "div",
995
- {
996
- role: "img",
997
- className: "flex shrink-0 items-center gap-2.5 font-mono text-xs font-medium",
998
- "aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
999
- children: [
1000
- /* @__PURE__ */ jsxs15("span", { "aria-hidden": true, className: "text-pass", children: [
1001
- "\u2713",
1002
- s.passed
1003
- ] }),
1004
- /* @__PURE__ */ jsxs15("span", { "aria-hidden": true, className: "text-fail", children: [
1005
- "\u2717",
1006
- s.failed
1007
- ] }),
1008
- /* @__PURE__ */ jsxs15("span", { "aria-hidden": true, className: "text-skip", children: [
1009
- "\u25CB",
1010
- skipped
1011
- ] })
1012
- ]
1013
- }
1014
- )
1015
- ] }),
1016
- /* @__PURE__ */ jsx24("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-2 p-3", children: /* @__PURE__ */ jsx24(ReportScenarioList, { feature }) })
1017
- ]
1018
- }
1051
+ /* @__PURE__ */ jsx25("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx25(ReportScenarioList, { feature }) })
1052
+ ]
1053
+ }
1054
+ )
1019
1055
  );
1020
1056
  }
1021
1057
 
1022
1058
  // src/components/ReportFeatureList.tsx
1023
- import { Fragment as Fragment9, jsx as jsx25 } from "react/jsx-runtime";
1059
+ import { jsx as jsx26 } from "react/jsx-runtime";
1024
1060
  function ReportFeatureList() {
1025
1061
  const report = useReport();
1026
- return /* @__PURE__ */ jsx25(Fragment9, { children: report.features.map((feature) => /* @__PURE__ */ jsx25(ReportFeature, { feature }, feature.id)) });
1062
+ return /* @__PURE__ */ jsx26("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ jsx26(ReportFeature, { feature }, feature.id)) });
1027
1063
  }
1028
1064
 
1029
1065
  // src/components/ui/empty.tsx
1030
1066
  import { cva as cva2 } from "class-variance-authority";
1031
- import { jsx as jsx26 } from "react/jsx-runtime";
1067
+ import { jsx as jsx27 } from "react/jsx-runtime";
1032
1068
  function Empty({ className, ...props }) {
1033
- return /* @__PURE__ */ jsx26(
1069
+ return /* @__PURE__ */ jsx27(
1034
1070
  "div",
1035
1071
  {
1036
1072
  "data-slot": "empty",
@@ -1043,7 +1079,7 @@ function Empty({ className, ...props }) {
1043
1079
  );
1044
1080
  }
1045
1081
  function EmptyHeader({ className, ...props }) {
1046
- return /* @__PURE__ */ jsx26(
1082
+ return /* @__PURE__ */ jsx27(
1047
1083
  "div",
1048
1084
  {
1049
1085
  "data-slot": "empty-header",
@@ -1070,7 +1106,7 @@ var emptyMediaVariants = cva2(
1070
1106
  }
1071
1107
  );
1072
1108
  function EmptyTitle({ className, ...props }) {
1073
- return /* @__PURE__ */ jsx26(
1109
+ return /* @__PURE__ */ jsx27(
1074
1110
  "div",
1075
1111
  {
1076
1112
  "data-slot": "empty-title",
@@ -1081,16 +1117,16 @@ function EmptyTitle({ className, ...props }) {
1081
1117
  }
1082
1118
 
1083
1119
  // src/components/ReportEmpty.tsx
1084
- import { jsx as jsx27 } from "react/jsx-runtime";
1120
+ import { jsx as jsx28 } from "react/jsx-runtime";
1085
1121
  function ReportEmpty({ message }) {
1086
- return /* @__PURE__ */ jsx27(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ jsx27(EmptyHeader, { children: /* @__PURE__ */ jsx27(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
1122
+ return /* @__PURE__ */ jsx28(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ jsx28(EmptyHeader, { children: /* @__PURE__ */ jsx28(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
1087
1123
  }
1088
1124
 
1089
1125
  // src/components/ReportSummary.tsx
1090
- import { Fragment as Fragment10, jsx as jsx28, jsxs as jsxs16 } from "react/jsx-runtime";
1126
+ import { jsx as jsx29, jsxs as jsxs17 } from "react/jsx-runtime";
1091
1127
  function ReportSummary({ className }) {
1092
1128
  const report = useReport();
1093
- return /* @__PURE__ */ jsx28(
1129
+ return /* @__PURE__ */ jsx29(
1094
1130
  ReportSummaryView,
1095
1131
  {
1096
1132
  summary: report.summary,
@@ -1099,38 +1135,54 @@ function ReportSummary({ className }) {
1099
1135
  }
1100
1136
  );
1101
1137
  }
1138
+ var TONE = {
1139
+ total: { num: "text-foreground", dot: "bg-muted-foreground/50" },
1140
+ passed: { num: "text-pass", dot: "bg-pass" },
1141
+ failed: { num: "text-fail", dot: "bg-fail" },
1142
+ skipped: { num: "text-skip", dot: "bg-skip" },
1143
+ pending: { num: "text-pend", dot: "bg-pend" }
1144
+ };
1102
1145
  function ReportSummaryView({ summary, className, ariaLabel }) {
1103
- return /* @__PURE__ */ jsxs16("p", { className: cn("text-sm text-muted-foreground", className), "aria-label": ariaLabel, children: [
1104
- /* @__PURE__ */ jsxs16("span", { children: [
1105
- /* @__PURE__ */ jsx28("strong", { className: "font-semibold text-foreground", children: summary.total }),
1106
- " scenario",
1107
- summary.total === 1 ? "" : "s"
1108
- ] }),
1109
- " \xB7 ",
1110
- /* @__PURE__ */ jsxs16("span", { "data-status": "passed", className: "text-pass", children: [
1111
- summary.passed,
1112
- " passed"
1113
- ] }),
1114
- " \xB7 ",
1115
- /* @__PURE__ */ jsxs16("span", { "data-status": "failed", className: "text-fail", children: [
1116
- summary.failed,
1117
- " failed"
1118
- ] }),
1119
- summary.skipped > 0 ? /* @__PURE__ */ jsxs16(Fragment10, { children: [
1120
- " \xB7 ",
1121
- /* @__PURE__ */ jsxs16("span", { "data-status": "skipped", className: "text-skip", children: [
1122
- summary.skipped,
1123
- " skipped"
1124
- ] })
1125
- ] }) : null,
1126
- summary.pending > 0 ? /* @__PURE__ */ jsxs16(Fragment10, { children: [
1127
- " \xB7 ",
1128
- /* @__PURE__ */ jsxs16("span", { "data-status": "pending", className: "text-pend", children: [
1129
- summary.pending,
1130
- " pending"
1131
- ] })
1132
- ] }) : null
1133
- ] });
1146
+ const cards = [
1147
+ { status: "total", label: "Total", value: summary.total },
1148
+ { status: "passed", label: "Passed", value: summary.passed },
1149
+ { status: "failed", label: "Failed", value: summary.failed },
1150
+ { status: "skipped", label: "Skipped", value: summary.skipped }
1151
+ ];
1152
+ if (summary.pending > 0) {
1153
+ cards.push({ status: "pending", label: "Pending", value: summary.pending });
1154
+ }
1155
+ return /* @__PURE__ */ jsx29(
1156
+ "dl",
1157
+ {
1158
+ className: cn(
1159
+ "grid grid-cols-2 gap-3",
1160
+ // Columns follow the card count so the row is always full — 5 statuses
1161
+ // (pending present) never leave a lone orphan card below a row of four.
1162
+ cards.length === 5 ? "sm:grid-cols-5" : "sm:grid-cols-4",
1163
+ className
1164
+ ),
1165
+ "aria-label": ariaLabel,
1166
+ children: cards.map((c) => {
1167
+ const tone = TONE[c.status];
1168
+ return /* @__PURE__ */ jsxs17(
1169
+ "div",
1170
+ {
1171
+ "data-status": c.status,
1172
+ className: "rounded-lg border bg-card px-4 py-3",
1173
+ children: [
1174
+ /* @__PURE__ */ jsxs17("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
1175
+ /* @__PURE__ */ jsx29("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
1176
+ c.label
1177
+ ] }),
1178
+ /* @__PURE__ */ jsx29("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
1179
+ ]
1180
+ },
1181
+ c.status
1182
+ );
1183
+ })
1184
+ }
1185
+ );
1134
1186
  }
1135
1187
 
1136
1188
  // src/lib/provenance.ts
@@ -1183,7 +1235,7 @@ function prUrl(ci) {
1183
1235
  }
1184
1236
 
1185
1237
  // src/components/ReportMeta.tsx
1186
- import { jsx as jsx29, jsxs as jsxs17 } from "react/jsx-runtime";
1238
+ import { jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
1187
1239
  function ReportMeta() {
1188
1240
  const report = useReport();
1189
1241
  const items = [];
@@ -1206,13 +1258,13 @@ function ReportMeta() {
1206
1258
  const short = sha.slice(0, 8);
1207
1259
  items.push({
1208
1260
  label: "Commit",
1209
- value: url ? /* @__PURE__ */ jsx29("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
1261
+ value: url ? /* @__PURE__ */ jsx30("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
1210
1262
  });
1211
1263
  }
1212
1264
  if (report.ci) {
1213
1265
  items.push({
1214
1266
  label: "CI",
1215
- value: report.ci.url ? /* @__PURE__ */ jsxs17("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
1267
+ value: report.ci.url ? /* @__PURE__ */ jsxs18("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
1216
1268
  ciDisplayName(report.ci.name),
1217
1269
  report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
1218
1270
  ] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
@@ -1223,45 +1275,56 @@ function ReportMeta() {
1223
1275
  const label = `#${report.ci.prNumber}`;
1224
1276
  items.push({
1225
1277
  label: "PR",
1226
- value: url ? /* @__PURE__ */ jsx29("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1278
+ value: url ? /* @__PURE__ */ jsx30("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1227
1279
  });
1228
1280
  }
1229
1281
  if (items.length === 0) return null;
1230
- return /* @__PURE__ */ jsx29("dl", { "aria-label": "Run metadata", className: "flex flex-wrap gap-x-6 gap-y-1 text-xs text-muted-foreground", children: items.map((item) => /* @__PURE__ */ jsxs17("div", { className: "flex gap-1.5", children: [
1231
- /* @__PURE__ */ jsx29("dt", { className: "font-medium", children: item.label }),
1232
- /* @__PURE__ */ jsx29("dd", { className: "font-mono text-foreground", children: item.value })
1233
- ] }, item.label)) });
1282
+ return (
1283
+ // Run metadata is useful but secondary to "what failed" — tuck it into a
1284
+ // collapsed disclosure so it doesn't push the result down. Native <details>
1285
+ // so it works with no JS (the SSR/no-hydration report still toggles).
1286
+ /* @__PURE__ */ jsxs18("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
1287
+ /* @__PURE__ */ jsxs18("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: [
1288
+ /* @__PURE__ */ jsx30("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
1289
+ "Run details"
1290
+ ] }),
1291
+ /* @__PURE__ */ jsx30("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__ */ jsxs18("div", { className: "flex items-baseline gap-1.5", children: [
1292
+ /* @__PURE__ */ jsx30("dt", { className: "font-medium", children: item.label }),
1293
+ /* @__PURE__ */ jsx30("dd", { className: "font-mono text-foreground", children: item.value })
1294
+ ] }, item.label)) })
1295
+ ] })
1296
+ );
1234
1297
  }
1235
1298
 
1236
1299
  // src/components/ReportSchemaError.tsx
1237
- import { jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
1300
+ import { jsx as jsx31, jsxs as jsxs19 } from "react/jsx-runtime";
1238
1301
  function ReportSchemaError({ error }) {
1239
- return /* @__PURE__ */ jsxs18("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
1240
- /* @__PURE__ */ jsx30("p", { children: /* @__PURE__ */ jsx30("strong", { children: "Report could not be displayed." }) }),
1241
- /* @__PURE__ */ jsx30("p", { children: error.message }),
1242
- error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ jsxs18("p", { children: [
1302
+ return /* @__PURE__ */ jsxs19("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
1303
+ /* @__PURE__ */ jsx31("p", { children: /* @__PURE__ */ jsx31("strong", { children: "Report could not be displayed." }) }),
1304
+ /* @__PURE__ */ jsx31("p", { children: error.message }),
1305
+ error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ jsxs19("p", { children: [
1243
1306
  "The report bundle is newer than this version of ",
1244
- /* @__PURE__ */ jsx30("code", { children: "executable-stories-react" }),
1307
+ /* @__PURE__ */ jsx31("code", { children: "executable-stories-react" }),
1245
1308
  ". Upgrade the package, or regenerate the report with an older formatters CLI."
1246
1309
  ] }) : null,
1247
- error.issues && error.issues.length > 0 ? /* @__PURE__ */ jsxs18("details", { children: [
1248
- /* @__PURE__ */ jsxs18("summary", { children: [
1310
+ error.issues && error.issues.length > 0 ? /* @__PURE__ */ jsxs19("details", { children: [
1311
+ /* @__PURE__ */ jsxs19("summary", { children: [
1249
1312
  error.issues.length,
1250
1313
  " validation issue",
1251
1314
  error.issues.length === 1 ? "" : "s"
1252
1315
  ] }),
1253
- /* @__PURE__ */ jsx30("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
1316
+ /* @__PURE__ */ jsx31("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
1254
1317
  ] }) : null
1255
1318
  ] });
1256
1319
  }
1257
1320
 
1258
1321
  // src/components/ReportShell.tsx
1259
- import { Fragment as Fragment11, jsx as jsx31, jsxs as jsxs19 } from "react/jsx-runtime";
1322
+ import { Fragment as Fragment10, jsx as jsx32, jsxs as jsxs20 } from "react/jsx-runtime";
1260
1323
  function ReportTitleBlock({ title }) {
1261
- return /* @__PURE__ */ jsxs19(Fragment11, { children: [
1262
- /* @__PURE__ */ jsx31("h1", { children: title ?? "Story Report" }),
1263
- /* @__PURE__ */ jsx31(ReportSummary, {}),
1264
- /* @__PURE__ */ jsx31(ReportMeta, {})
1324
+ return /* @__PURE__ */ jsxs20(Fragment10, { children: [
1325
+ /* @__PURE__ */ jsx32("h1", { children: title ?? "Story Report" }),
1326
+ /* @__PURE__ */ jsx32(ReportSummary, {}),
1327
+ /* @__PURE__ */ jsx32(ReportMeta, {})
1265
1328
  ] });
1266
1329
  }
1267
1330
  function ReportErrorShell({
@@ -1270,28 +1333,28 @@ function ReportErrorShell({
1270
1333
  title,
1271
1334
  dataTheme
1272
1335
  }) {
1273
- return /* @__PURE__ */ jsx31("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx31(ReportSchemaError, { error }) });
1336
+ return /* @__PURE__ */ jsx32("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx32(ReportSchemaError, { error }) });
1274
1337
  }
1275
1338
 
1276
1339
  // src/components/Report.tsx
1277
- import { jsx as jsx32, jsxs as jsxs20 } from "react/jsx-runtime";
1340
+ import { jsx as jsx33, jsxs as jsxs21 } from "react/jsx-runtime";
1278
1341
  function Report(props) {
1279
1342
  const { report, customRenderers, renderers, className, title, dataTheme } = props;
1280
1343
  const result = unwrapReport(report);
1281
1344
  if (!result.ok) {
1282
- return /* @__PURE__ */ jsx32(ReportErrorShell, { error: result.error, className, title, dataTheme });
1345
+ return /* @__PURE__ */ jsx33(ReportErrorShell, { error: result.error, className, title, dataTheme });
1283
1346
  }
1284
1347
  const data = result.data;
1285
1348
  const hasContent = data.features.length > 0;
1286
- return /* @__PURE__ */ jsx32(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ jsxs20("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
1287
- /* @__PURE__ */ jsx32("header", { className: "es-report-header", children: /* @__PURE__ */ jsx32(ReportTitleBlock, { title }) }),
1288
- hasContent ? /* @__PURE__ */ jsx32(ReportFeatureList, {}) : /* @__PURE__ */ jsx32(ReportEmpty, {})
1349
+ return /* @__PURE__ */ jsx33(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ jsxs21("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
1350
+ /* @__PURE__ */ jsx33("header", { className: "es-report-header", children: /* @__PURE__ */ jsx33(ReportTitleBlock, { title }) }),
1351
+ hasContent ? /* @__PURE__ */ jsx33(ReportFeatureList, {}) : /* @__PURE__ */ jsx33(ReportEmpty, {})
1289
1352
  ] }) });
1290
1353
  }
1291
1354
 
1292
1355
  // src/components/doc/MermaidView.tsx
1293
1356
  import { useEffect, useRef, useState as useState2 } from "react";
1294
- import { jsx as jsx33, jsxs as jsxs21 } from "react/jsx-runtime";
1357
+ import { jsx as jsx34, jsxs as jsxs22 } from "react/jsx-runtime";
1295
1358
  function prefersDark(el) {
1296
1359
  const themed = el?.closest("[data-theme]");
1297
1360
  if (themed?.dataset.theme === "dark") return true;
@@ -1328,9 +1391,9 @@ function MermaidView({ entry, load }) {
1328
1391
  };
1329
1392
  }, [entry.code, load]);
1330
1393
  if (svg) {
1331
- return /* @__PURE__ */ jsxs21("figure", { ref, className: "my-3", children: [
1332
- entry.title ? /* @__PURE__ */ jsx33("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
1333
- /* @__PURE__ */ jsx33(
1394
+ return /* @__PURE__ */ jsxs22("figure", { ref, className: "my-3", children: [
1395
+ entry.title ? /* @__PURE__ */ jsx34("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
1396
+ /* @__PURE__ */ jsx34(
1334
1397
  "div",
1335
1398
  {
1336
1399
  role: "img",
@@ -1341,18 +1404,18 @@ function MermaidView({ entry, load }) {
1341
1404
  )
1342
1405
  ] });
1343
1406
  }
1344
- return /* @__PURE__ */ jsx33(MermaidSource, { entry, ref });
1407
+ return /* @__PURE__ */ jsx34(MermaidSource, { entry, ref });
1345
1408
  }
1346
1409
 
1347
1410
  // src/components/doc/MermaidDiagram.tsx
1348
- import { jsx as jsx34 } from "react/jsx-runtime";
1411
+ import { jsx as jsx35 } from "react/jsx-runtime";
1349
1412
  var mermaidLoader;
1350
1413
  function loadMermaid() {
1351
1414
  mermaidLoader ??= import("mermaid").then((m) => m.default);
1352
1415
  return mermaidLoader;
1353
1416
  }
1354
1417
  function MermaidDiagram({ entry, load = loadMermaid }) {
1355
- return /* @__PURE__ */ jsx34(MermaidView, { entry, load });
1418
+ return /* @__PURE__ */ jsx35(MermaidView, { entry, load });
1356
1419
  }
1357
1420
 
1358
1421
  // src/components/ScenarioExplorer.tsx
@@ -1362,12 +1425,12 @@ import { useState as useState3 } from "react";
1362
1425
  import "react";
1363
1426
  import { Command as CommandPrimitive } from "cmdk";
1364
1427
  import { SearchIcon } from "lucide-react";
1365
- import { jsx as jsx35, jsxs as jsxs22 } from "react/jsx-runtime";
1428
+ import { jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
1366
1429
  function Command({
1367
1430
  className,
1368
1431
  ...props
1369
1432
  }) {
1370
- return /* @__PURE__ */ jsx35(
1433
+ return /* @__PURE__ */ jsx36(
1371
1434
  CommandPrimitive,
1372
1435
  {
1373
1436
  "data-slot": "command",
@@ -1383,14 +1446,14 @@ function CommandInput({
1383
1446
  className,
1384
1447
  ...props
1385
1448
  }) {
1386
- return /* @__PURE__ */ jsxs22(
1449
+ return /* @__PURE__ */ jsxs23(
1387
1450
  "div",
1388
1451
  {
1389
1452
  "data-slot": "command-input-wrapper",
1390
1453
  className: "flex h-9 items-center gap-2 border-b px-3",
1391
1454
  children: [
1392
- /* @__PURE__ */ jsx35(SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
1393
- /* @__PURE__ */ jsx35(
1455
+ /* @__PURE__ */ jsx36(SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
1456
+ /* @__PURE__ */ jsx36(
1394
1457
  CommandPrimitive.Input,
1395
1458
  {
1396
1459
  "data-slot": "command-input",
@@ -1409,7 +1472,7 @@ function CommandList({
1409
1472
  className,
1410
1473
  ...props
1411
1474
  }) {
1412
- return /* @__PURE__ */ jsx35(
1475
+ return /* @__PURE__ */ jsx36(
1413
1476
  CommandPrimitive.List,
1414
1477
  {
1415
1478
  "data-slot": "command-list",
@@ -1424,7 +1487,7 @@ function CommandList({
1424
1487
  function CommandEmpty({
1425
1488
  ...props
1426
1489
  }) {
1427
- return /* @__PURE__ */ jsx35(
1490
+ return /* @__PURE__ */ jsx36(
1428
1491
  CommandPrimitive.Empty,
1429
1492
  {
1430
1493
  "data-slot": "command-empty",
@@ -1437,7 +1500,7 @@ function CommandGroup({
1437
1500
  className,
1438
1501
  ...props
1439
1502
  }) {
1440
- return /* @__PURE__ */ jsx35(
1503
+ return /* @__PURE__ */ jsx36(
1441
1504
  CommandPrimitive.Group,
1442
1505
  {
1443
1506
  "data-slot": "command-group",
@@ -1453,7 +1516,7 @@ function CommandItem({
1453
1516
  className,
1454
1517
  ...props
1455
1518
  }) {
1456
- return /* @__PURE__ */ jsx35(
1519
+ return /* @__PURE__ */ jsx36(
1457
1520
  CommandPrimitive.Item,
1458
1521
  {
1459
1522
  "data-slot": "command-item",
@@ -1467,7 +1530,7 @@ function CommandItem({
1467
1530
  }
1468
1531
 
1469
1532
  // src/components/ScenarioExplorer.tsx
1470
- import { jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
1533
+ import { jsx as jsx37, jsxs as jsxs24 } from "react/jsx-runtime";
1471
1534
  var STATUS_FILTERS = [
1472
1535
  { value: "all", label: "All" },
1473
1536
  { value: "passed", label: "Passed" },
@@ -1478,22 +1541,22 @@ var STATUS_FILTERS = [
1478
1541
  function ScenarioExplorer({ scenarios, summary }) {
1479
1542
  const [status, setStatus] = useState3("all");
1480
1543
  const visible = status === "all" ? scenarios : scenarios.filter((s) => s.status === status);
1481
- return /* @__PURE__ */ jsxs23("div", { className: "font-sans text-foreground", children: [
1482
- summary ? /* @__PURE__ */ jsxs23("p", { className: "mb-3 text-sm text-muted-foreground", children: [
1544
+ return /* @__PURE__ */ jsxs24("div", { className: "font-sans text-foreground", children: [
1545
+ summary ? /* @__PURE__ */ jsxs24("p", { className: "mb-3 text-sm text-muted-foreground", children: [
1483
1546
  summary.total,
1484
1547
  " scenarios \xB7 ",
1485
- /* @__PURE__ */ jsxs23("span", { className: "text-pass", children: [
1548
+ /* @__PURE__ */ jsxs24("span", { className: "text-pass", children: [
1486
1549
  summary.passed,
1487
1550
  " passed"
1488
1551
  ] }),
1489
1552
  " \xB7",
1490
1553
  " ",
1491
- /* @__PURE__ */ jsxs23("span", { className: "text-fail", children: [
1554
+ /* @__PURE__ */ jsxs24("span", { className: "text-fail", children: [
1492
1555
  summary.failed,
1493
1556
  " failed"
1494
1557
  ] })
1495
1558
  ] }) : null,
1496
- /* @__PURE__ */ jsx36("div", { className: "mb-2 flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by status", children: STATUS_FILTERS.map((f) => /* @__PURE__ */ jsx36(
1559
+ /* @__PURE__ */ jsx37("div", { className: "mb-2 flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by status", children: STATUS_FILTERS.map((f) => /* @__PURE__ */ jsx37(
1497
1560
  "button",
1498
1561
  {
1499
1562
  type: "button",
@@ -1508,26 +1571,26 @@ function ScenarioExplorer({ scenarios, summary }) {
1508
1571
  },
1509
1572
  f.value
1510
1573
  )) }),
1511
- /* @__PURE__ */ jsxs23(
1574
+ /* @__PURE__ */ jsxs24(
1512
1575
  Command,
1513
1576
  {
1514
1577
  className: "rounded-lg border border-border bg-card",
1515
1578
  filter: (value, search) => value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0,
1516
1579
  children: [
1517
- /* @__PURE__ */ jsx36(CommandInput, { placeholder: "Search scenarios\u2026" }),
1518
- /* @__PURE__ */ jsxs23(CommandList, { className: "max-h-none", children: [
1519
- /* @__PURE__ */ jsx36(CommandEmpty, { children: "No scenarios match your filters." }),
1520
- /* @__PURE__ */ jsx36(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ jsx36(
1580
+ /* @__PURE__ */ jsx37(CommandInput, { placeholder: "Search scenarios\u2026" }),
1581
+ /* @__PURE__ */ jsxs24(CommandList, { className: "max-h-none", children: [
1582
+ /* @__PURE__ */ jsx37(CommandEmpty, { children: "No scenarios match your filters." }),
1583
+ /* @__PURE__ */ jsx37(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ jsx37(
1521
1584
  CommandItem,
1522
1585
  {
1523
1586
  value: `${s.title} ${s.feature} ${s.tags.join(" ")}`,
1524
1587
  asChild: true,
1525
1588
  className: "cursor-pointer",
1526
- children: /* @__PURE__ */ jsxs23("a", { href: s.href, className: "flex items-center gap-3", children: [
1527
- /* @__PURE__ */ jsx36(Badge, { variant: s.status, children: s.status }),
1528
- /* @__PURE__ */ jsx36("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
1529
- s.tags.slice(0, 3).map((t) => /* @__PURE__ */ jsx36(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
1530
- /* @__PURE__ */ jsx36("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
1589
+ children: /* @__PURE__ */ jsxs24("a", { href: s.href, className: "flex items-center gap-3", children: [
1590
+ /* @__PURE__ */ jsx37(Badge, { variant: s.status, children: s.status }),
1591
+ /* @__PURE__ */ jsx37("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
1592
+ s.tags.slice(0, 3).map((t) => /* @__PURE__ */ jsx37(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
1593
+ /* @__PURE__ */ jsx37("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
1531
1594
  ] })
1532
1595
  },
1533
1596
  s.id