executable-stories-react 0.15.0 → 0.16.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
@@ -611,12 +611,29 @@ function DocVideo({ entry }) {
611
611
  }
612
612
 
613
613
  // src/components/doc/DocHtml.tsx
614
+ var import_react5 = require("react");
614
615
  var import_jsx_runtime14 = require("react/jsx-runtime");
616
+ var MEASURE_SCRIPT = "<script>(function(){if(parent===window)return;var last=0,queued=false;var measure=function(){var kids=document.body.children,h=0;for(var i=0;i<kids.length;i++)h=Math.max(h,kids[i].getBoundingClientRect().bottom);return Math.ceil(h||document.body.getBoundingClientRect().bottom)};var post=function(){queued=false;var h=measure();if(h===last)return;last=h;parent.postMessage({__esHtmlHeight:h},'*')};var schedule=function(){if(queued)return;queued=true;requestAnimationFrame(post)};var start=function(){new ResizeObserver(schedule).observe(document.body);new MutationObserver(schedule).observe(document.body,{subtree:true,childList:true,attributes:true,characterData:true});addEventListener('load',schedule);post()};if(document.body)start();else addEventListener('DOMContentLoaded',start)})();</script>";
617
+ var MAX_MEASURED_HEIGHT = 5e3;
615
618
  function DocHtml({ entry }) {
616
- const height = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
619
+ const declaredHeight = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
617
620
  const title = entry.title ?? "Embedded HTML";
618
621
  const safeHref = (0, import_url.safeUrl)(entry.url ?? entry.path);
619
- const frameProps = entry.content !== void 0 ? { srcDoc: entry.content } : { src: safeHref ?? "" };
622
+ const frameRef = (0, import_react5.useRef)(null);
623
+ const [measuredHeight, setMeasuredHeight] = (0, import_react5.useState)();
624
+ (0, import_react5.useEffect)(() => {
625
+ if (entry.content === void 0) return;
626
+ const onMessage = (event) => {
627
+ if (event.source !== frameRef.current?.contentWindow) return;
628
+ const reported = event.data?.__esHtmlHeight;
629
+ if (typeof reported !== "number" || !Number.isFinite(reported) || reported <= 0) return;
630
+ setMeasuredHeight(Math.min(reported, MAX_MEASURED_HEIGHT));
631
+ };
632
+ window.addEventListener("message", onMessage);
633
+ return () => window.removeEventListener("message", onMessage);
634
+ }, [entry.content]);
635
+ const height = measuredHeight === void 0 ? declaredHeight : `${measuredHeight}px`;
636
+ const frameProps = entry.content !== void 0 ? { srcDoc: entry.content + MEASURE_SCRIPT } : { src: safeHref ?? "" };
620
637
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
621
638
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("figcaption", { className: "flex items-center justify-between border-b border-border bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground", children: [
622
639
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: entry.title ?? "HTML" }),
@@ -636,6 +653,7 @@ function DocHtml({ entry }) {
636
653
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
637
654
  "iframe",
638
655
  {
656
+ ref: frameRef,
639
657
  ...frameProps,
640
658
  sandbox: "allow-scripts",
641
659
  loading: "lazy",
@@ -1089,11 +1107,11 @@ function ReportTrace({ spans }) {
1089
1107
  }
1090
1108
 
1091
1109
  // src/interactive/scenario-history-context.ts
1092
- var import_react5 = require("react");
1093
- var ScenarioHistoryContext = (0, import_react5.createContext)(null);
1110
+ var import_react6 = require("react");
1111
+ var ScenarioHistoryContext = (0, import_react6.createContext)(null);
1094
1112
  var ScenarioHistoryProvider = ScenarioHistoryContext.Provider;
1095
1113
  function useScenarioHistory() {
1096
- return (0, import_react5.useContext)(ScenarioHistoryContext);
1114
+ return (0, import_react6.useContext)(ScenarioHistoryContext);
1097
1115
  }
1098
1116
 
1099
1117
  // src/lib/run-history.ts
@@ -1184,7 +1202,7 @@ function ScenarioRunHistory({ scenarioId }) {
1184
1202
  }
1185
1203
 
1186
1204
  // src/components/ScenarioStaleness.tsx
1187
- var import_react7 = require("react");
1205
+ var import_react8 = require("react");
1188
1206
 
1189
1207
  // src/lib/provenance.ts
1190
1208
  function reportLastRunMs(report) {
@@ -1240,11 +1258,11 @@ function prUrl(ci) {
1240
1258
  }
1241
1259
 
1242
1260
  // src/interactive/scenario-freshness-context.tsx
1243
- var import_react6 = require("react");
1244
- var ScenarioFreshnessContext = (0, import_react6.createContext)(null);
1261
+ var import_react7 = require("react");
1262
+ var ScenarioFreshnessContext = (0, import_react7.createContext)(null);
1245
1263
  var ScenarioFreshnessProvider = ScenarioFreshnessContext.Provider;
1246
1264
  function useScenarioFreshness() {
1247
- return (0, import_react6.useContext)(ScenarioFreshnessContext);
1265
+ return (0, import_react7.useContext)(ScenarioFreshnessContext);
1248
1266
  }
1249
1267
 
1250
1268
  // src/components/ScenarioStaleness.tsx
@@ -1252,8 +1270,8 @@ var import_jsx_runtime24 = require("react/jsx-runtime");
1252
1270
  function ScenarioStaleness({ scenario }) {
1253
1271
  const freshness = useScenarioFreshness();
1254
1272
  const fixedNow = freshness?.nowMs;
1255
- const [now, setNow] = (0, import_react7.useState)(fixedNow);
1256
- (0, import_react7.useEffect)(() => {
1273
+ const [now, setNow] = (0, import_react8.useState)(fixedNow);
1274
+ (0, import_react8.useEffect)(() => {
1257
1275
  if (fixedNow === void 0) setNow(Date.now());
1258
1276
  }, [fixedNow]);
1259
1277
  if (!freshness || now === void 0) return null;
@@ -1267,20 +1285,20 @@ function ScenarioStaleness({ scenario }) {
1267
1285
  }
1268
1286
 
1269
1287
  // src/interactive/collapse-context.ts
1270
- var import_react8 = require("react");
1271
- var CollapseContext = (0, import_react8.createContext)(null);
1288
+ var import_react9 = require("react");
1289
+ var CollapseContext = (0, import_react9.createContext)(null);
1272
1290
  var CollapseProvider = CollapseContext.Provider;
1273
1291
  function useCollapse() {
1274
- return (0, import_react8.useContext)(CollapseContext);
1292
+ return (0, import_react9.useContext)(CollapseContext);
1275
1293
  }
1276
1294
 
1277
1295
  // src/interactive/scenario-actions.tsx
1278
- var import_react9 = require("react");
1296
+ var import_react10 = require("react");
1279
1297
  var import_scenario_markdown = require("executable-stories-core/utils/scenario-markdown");
1280
- var ScenarioActionsContext = (0, import_react9.createContext)(null);
1298
+ var ScenarioActionsContext = (0, import_react10.createContext)(null);
1281
1299
  var ScenarioActionsProvider = ScenarioActionsContext.Provider;
1282
1300
  function useScenarioActions() {
1283
- return (0, import_react9.useContext)(ScenarioActionsContext);
1301
+ return (0, import_react10.useContext)(ScenarioActionsContext);
1284
1302
  }
1285
1303
 
1286
1304
  // src/components/ui/card.tsx
@@ -1841,25 +1859,86 @@ function ReportErrorShell({
1841
1859
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportSchemaError, { error }) });
1842
1860
  }
1843
1861
 
1844
- // src/components/Report.tsx
1862
+ // src/components/ReportSpanGraph.tsx
1863
+ var import_span_graph = require("executable-stories-core/span-graph");
1864
+ var import_react11 = require("react");
1845
1865
  var import_jsx_runtime38 = require("react/jsx-runtime");
1866
+ var LANE_LABEL = {
1867
+ edge: "Edge",
1868
+ service: "Service",
1869
+ queue: "Queue",
1870
+ datastore: "Data"
1871
+ };
1872
+ var MARK_LABEL = {
1873
+ failing: "Failing",
1874
+ added: "New",
1875
+ changed: "Changed"
1876
+ };
1877
+ var MARK_CLASS = {
1878
+ failing: "text-fail",
1879
+ added: "text-pass",
1880
+ changed: "text-pend"
1881
+ };
1882
+ function MarkBadge({ node }) {
1883
+ const mark = (0, import_span_graph.spanGraphNodeMark)(node);
1884
+ if (!mark) return null;
1885
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: cn("ml-2 text-xs font-medium", MARK_CLASS[mark]), children: MARK_LABEL[mark] });
1886
+ }
1887
+ function ReportSpanGraph() {
1888
+ const report = useReport();
1889
+ const { code, graph, titleById } = (0, import_react11.useMemo)(() => {
1890
+ const scenarios = report.features.flatMap((feature) => feature.scenarios);
1891
+ const derived = (0, import_span_graph.deriveSpanGraph)(scenarios);
1892
+ return {
1893
+ graph: derived,
1894
+ code: (0, import_span_graph.spanGraphToMermaid)(derived),
1895
+ titleById: new Map(scenarios.map((scenario) => [scenario.id, scenario.title]))
1896
+ };
1897
+ }, [report]);
1898
+ if (code === "") return null;
1899
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("section", { className: "es-span-graph mt-6", "aria-labelledby": "es-span-graph-heading", children: [
1900
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("h2", { id: "es-span-graph-heading", className: "text-base font-semibold text-foreground", children: "Architecture, as it ran" }),
1901
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: "Derived from this run\u2019s traces. Every component was named by a span while a scenario ran, so nothing here is inferred from the code. Instrumented, exercised paths only: a component no scenario reaches does not appear." }),
1902
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(DocMermaid, { entry: { kind: "mermaid", phase: "static", code } }),
1903
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("table", { className: "mt-2 w-full text-left text-sm", children: [
1904
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("caption", { className: "sr-only", children: "Each component and the scenarios that exercised it" }),
1905
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("tr", { className: "text-xs text-muted-foreground", children: [
1906
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("th", { scope: "col", className: "py-1 pr-4 font-medium", children: "Component" }),
1907
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("th", { scope: "col", className: "py-1 pr-4 font-medium", children: "Lane" }),
1908
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("th", { scope: "col", className: "py-1 font-medium", children: "Covered by" })
1909
+ ] }) }),
1910
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("tbody", { children: graph.nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("tr", { className: "border-t border-border align-top", children: [
1911
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("th", { scope: "row", className: "py-1.5 pr-4 font-mono text-xs font-normal", children: [
1912
+ node.id,
1913
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(MarkBadge, { node })
1914
+ ] }),
1915
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("td", { className: "py-1.5 pr-4 text-xs text-muted-foreground", children: LANE_LABEL[node.kind] }),
1916
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("td", { className: "py-1.5", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("ul", { className: "flex flex-col gap-0.5", children: node.scenarioIds.map((id) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("a", { href: `#${id}`, className: "text-xs underline underline-offset-2", children: titleById.get(id) ?? id }) }, id)) }) })
1917
+ ] }, node.id)) })
1918
+ ] })
1919
+ ] });
1920
+ }
1921
+
1922
+ // src/components/Report.tsx
1923
+ var import_jsx_runtime39 = require("react/jsx-runtime");
1846
1924
  function Report(props) {
1847
1925
  const { report, customRenderers, renderers, className, title, dataTheme } = props;
1848
1926
  const result = unwrapReport(report);
1849
1927
  if (!result.ok) {
1850
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
1928
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
1851
1929
  }
1852
1930
  const data = result.data;
1853
1931
  const hasContent = data.features.length > 0;
1854
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
1855
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportTitleBlock, { title }) }),
1856
- hasContent ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportEmpty, {})
1932
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
1933
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ReportTitleBlock, { title }) }),
1934
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ReportSpanGraph, {}),
1935
+ hasContent ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ReportEmpty, {})
1857
1936
  ] }) });
1858
1937
  }
1859
1938
 
1860
1939
  // src/components/doc/MermaidView.tsx
1861
- var import_react10 = require("react");
1862
- var import_jsx_runtime39 = require("react/jsx-runtime");
1940
+ var import_react12 = require("react");
1941
+ var import_jsx_runtime40 = require("react/jsx-runtime");
1863
1942
  function prefersDark(el) {
1864
1943
  const themed = el?.closest("[data-theme]");
1865
1944
  if (themed?.dataset.theme === "dark") return true;
@@ -1867,10 +1946,10 @@ function prefersDark(el) {
1867
1946
  return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
1868
1947
  }
1869
1948
  function MermaidView({ entry, load }) {
1870
- const ref = (0, import_react10.useRef)(null);
1871
- const [svg, setSvg] = (0, import_react10.useState)(null);
1872
- const [error, setError] = (0, import_react10.useState)(null);
1873
- (0, import_react10.useEffect)(() => {
1949
+ const ref = (0, import_react12.useRef)(null);
1950
+ const [svg, setSvg] = (0, import_react12.useState)(null);
1951
+ const [error, setError] = (0, import_react12.useState)(null);
1952
+ (0, import_react12.useEffect)(() => {
1874
1953
  let cancelled = false;
1875
1954
  const draw = async () => {
1876
1955
  let mermaid;
@@ -1913,9 +1992,9 @@ function MermaidView({ entry, load }) {
1913
1992
  };
1914
1993
  }, [entry.code, load]);
1915
1994
  if (svg) {
1916
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("figure", { ref, className: "my-3", children: [
1917
- entry.title ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
1918
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
1995
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("figure", { ref, className: "my-3", children: [
1996
+ entry.title ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
1997
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
1919
1998
  "div",
1920
1999
  {
1921
2000
  role: "img",
@@ -1926,8 +2005,8 @@ function MermaidView({ entry, load }) {
1926
2005
  )
1927
2006
  ] });
1928
2007
  }
1929
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
1930
- error ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
2008
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
2009
+ error ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
1931
2010
  "p",
1932
2011
  {
1933
2012
  role: "alert",
@@ -1939,34 +2018,34 @@ function MermaidView({ entry, load }) {
1939
2018
  ]
1940
2019
  }
1941
2020
  ) : null,
1942
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(MermaidSource, { entry, ref })
2021
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(MermaidSource, { entry, ref })
1943
2022
  ] });
1944
2023
  }
1945
2024
 
1946
2025
  // src/components/doc/MermaidDiagram.tsx
1947
- var import_jsx_runtime40 = require("react/jsx-runtime");
2026
+ var import_jsx_runtime41 = require("react/jsx-runtime");
1948
2027
  var mermaidLoader;
1949
2028
  function loadMermaid() {
1950
2029
  mermaidLoader ??= import("mermaid").then((m) => m.default);
1951
2030
  return mermaidLoader;
1952
2031
  }
1953
2032
  function MermaidDiagram({ entry, load = loadMermaid }) {
1954
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(MermaidView, { entry, load });
2033
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(MermaidView, { entry, load });
1955
2034
  }
1956
2035
 
1957
2036
  // src/components/ScenarioExplorer.tsx
1958
- var import_react11 = require("react");
2037
+ var import_react13 = require("react");
1959
2038
 
1960
2039
  // src/components/ui/command.tsx
1961
2040
  var React4 = require("react");
1962
2041
  var import_cmdk = require("cmdk");
1963
2042
  var import_lucide_react3 = require("lucide-react");
1964
- var import_jsx_runtime41 = require("react/jsx-runtime");
2043
+ var import_jsx_runtime42 = require("react/jsx-runtime");
1965
2044
  function Command({
1966
2045
  className,
1967
2046
  ...props
1968
2047
  }) {
1969
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2048
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
1970
2049
  import_cmdk.Command,
1971
2050
  {
1972
2051
  "data-slot": "command",
@@ -1982,14 +2061,14 @@ function CommandInput({
1982
2061
  className,
1983
2062
  ...props
1984
2063
  }) {
1985
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
2064
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
1986
2065
  "div",
1987
2066
  {
1988
2067
  "data-slot": "command-input-wrapper",
1989
2068
  className: "flex h-9 items-center gap-2 border-b px-3",
1990
2069
  children: [
1991
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react3.SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
1992
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2070
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react3.SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
2071
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
1993
2072
  import_cmdk.Command.Input,
1994
2073
  {
1995
2074
  "data-slot": "command-input",
@@ -2008,7 +2087,7 @@ function CommandList({
2008
2087
  className,
2009
2088
  ...props
2010
2089
  }) {
2011
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2090
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2012
2091
  import_cmdk.Command.List,
2013
2092
  {
2014
2093
  "data-slot": "command-list",
@@ -2023,7 +2102,7 @@ function CommandList({
2023
2102
  function CommandEmpty({
2024
2103
  ...props
2025
2104
  }) {
2026
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2105
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2027
2106
  import_cmdk.Command.Empty,
2028
2107
  {
2029
2108
  "data-slot": "command-empty",
@@ -2036,7 +2115,7 @@ function CommandGroup({
2036
2115
  className,
2037
2116
  ...props
2038
2117
  }) {
2039
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2118
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2040
2119
  import_cmdk.Command.Group,
2041
2120
  {
2042
2121
  "data-slot": "command-group",
@@ -2052,7 +2131,7 @@ function CommandItem({
2052
2131
  className,
2053
2132
  ...props
2054
2133
  }) {
2055
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2134
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2056
2135
  import_cmdk.Command.Item,
2057
2136
  {
2058
2137
  "data-slot": "command-item",
@@ -2066,7 +2145,7 @@ function CommandItem({
2066
2145
  }
2067
2146
 
2068
2147
  // src/components/ScenarioExplorer.tsx
2069
- var import_jsx_runtime42 = require("react/jsx-runtime");
2148
+ var import_jsx_runtime43 = require("react/jsx-runtime");
2070
2149
  var STATUS_FILTERS = [
2071
2150
  { value: "all", label: "All" },
2072
2151
  { value: "passed", label: "Passed" },
@@ -2075,24 +2154,24 @@ var STATUS_FILTERS = [
2075
2154
  { value: "pending", label: "Pending" }
2076
2155
  ];
2077
2156
  function ScenarioExplorer({ scenarios, summary }) {
2078
- const [status, setStatus] = (0, import_react11.useState)("all");
2157
+ const [status, setStatus] = (0, import_react13.useState)("all");
2079
2158
  const visible = status === "all" ? scenarios : scenarios.filter((s) => s.status === status);
2080
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "font-sans text-foreground", children: [
2081
- summary ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("p", { className: "mb-3 text-sm text-muted-foreground", children: [
2159
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "font-sans text-foreground", children: [
2160
+ summary ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("p", { className: "mb-3 text-sm text-muted-foreground", children: [
2082
2161
  summary.total,
2083
2162
  " scenarios \xB7 ",
2084
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "text-pass", children: [
2163
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "text-pass", children: [
2085
2164
  summary.passed,
2086
2165
  " passed"
2087
2166
  ] }),
2088
2167
  " \xB7",
2089
2168
  " ",
2090
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "text-fail", children: [
2169
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "text-fail", children: [
2091
2170
  summary.failed,
2092
2171
  " failed"
2093
2172
  ] })
2094
2173
  ] }) : null,
2095
- /* @__PURE__ */ (0, import_jsx_runtime42.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_runtime42.jsx)(
2174
+ /* @__PURE__ */ (0, import_jsx_runtime43.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_runtime43.jsx)(
2096
2175
  "button",
2097
2176
  {
2098
2177
  type: "button",
@@ -2107,26 +2186,26 @@ function ScenarioExplorer({ scenarios, summary }) {
2107
2186
  },
2108
2187
  f.value
2109
2188
  )) }),
2110
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
2189
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
2111
2190
  Command,
2112
2191
  {
2113
2192
  className: "rounded-lg border border-border bg-card",
2114
2193
  filter: (value, search) => value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0,
2115
2194
  children: [
2116
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(CommandInput, { placeholder: "Search scenarios\u2026" }),
2117
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(CommandList, { className: "max-h-none", children: [
2118
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(CommandEmpty, { children: "No scenarios match your filters." }),
2119
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2195
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(CommandInput, { placeholder: "Search scenarios\u2026" }),
2196
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(CommandList, { className: "max-h-none", children: [
2197
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(CommandEmpty, { children: "No scenarios match your filters." }),
2198
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
2120
2199
  CommandItem,
2121
2200
  {
2122
2201
  value: `${s.title} ${s.feature} ${s.tags.join(" ")}`,
2123
2202
  asChild: true,
2124
2203
  className: "cursor-pointer",
2125
- children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("a", { href: s.href, className: "flex items-center gap-3", children: [
2126
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Badge, { variant: s.status, children: s.status }),
2127
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
2128
- s.tags.slice(0, 3).map((t) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
2129
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
2204
+ children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("a", { href: s.href, className: "flex items-center gap-3", children: [
2205
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Badge, { variant: s.status, children: s.status }),
2206
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
2207
+ s.tags.slice(0, 3).map((t) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
2208
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
2130
2209
  ] })
2131
2210
  },
2132
2211
  s.id