executable-stories-react 0.15.0 → 0.17.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 +147 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +136 -54
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +439 -332
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +6 -0
- package/dist/interactive.d.ts +6 -0
- package/dist/interactive.js +397 -290
- package/dist/interactive.js.map +1 -1
- package/dist/report-island.global.js +55 -54
- package/dist/ssr.cjs +111 -28
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.d.cts +2 -0
- package/dist/ssr.d.ts +2 -0
- package/dist/ssr.js +99 -16
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -63,6 +63,12 @@ interface ReportProps {
|
|
|
63
63
|
title?: string;
|
|
64
64
|
/** Optional theme attribute scope. Use to force "light" or "dark". */
|
|
65
65
|
dataTheme?: "light" | "dark";
|
|
66
|
+
/**
|
|
67
|
+
* Draw the "Architecture, as it ran" section above the features. Off by
|
|
68
|
+
* default — only an instrumented run has anything to draw, and the span
|
|
69
|
+
* picture is a specialist view. `--html-architecture` turns it on.
|
|
70
|
+
*/
|
|
71
|
+
architecture?: boolean;
|
|
66
72
|
}
|
|
67
73
|
declare function Report(props: ReportProps): react.JSX.Element;
|
|
68
74
|
|
package/dist/index.d.ts
CHANGED
|
@@ -63,6 +63,12 @@ interface ReportProps {
|
|
|
63
63
|
title?: string;
|
|
64
64
|
/** Optional theme attribute scope. Use to force "light" or "dark". */
|
|
65
65
|
dataTheme?: "light" | "dark";
|
|
66
|
+
/**
|
|
67
|
+
* Draw the "Architecture, as it ran" section above the features. Off by
|
|
68
|
+
* default — only an instrumented run has anything to draw, and the span
|
|
69
|
+
* picture is a specialist view. `--html-architecture` turns it on.
|
|
70
|
+
*/
|
|
71
|
+
architecture?: boolean;
|
|
66
72
|
}
|
|
67
73
|
declare function Report(props: ReportProps): react.JSX.Element;
|
|
68
74
|
|
package/dist/index.js
CHANGED
|
@@ -522,12 +522,29 @@ function DocVideo({ entry }) {
|
|
|
522
522
|
}
|
|
523
523
|
|
|
524
524
|
// src/components/doc/DocHtml.tsx
|
|
525
|
+
import { useEffect, useRef, useState } from "react";
|
|
525
526
|
import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
527
|
+
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>";
|
|
528
|
+
var MAX_MEASURED_HEIGHT = 5e3;
|
|
526
529
|
function DocHtml({ entry }) {
|
|
527
|
-
const
|
|
530
|
+
const declaredHeight = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
528
531
|
const title = entry.title ?? "Embedded HTML";
|
|
529
532
|
const safeHref = safeUrl(entry.url ?? entry.path);
|
|
530
|
-
const
|
|
533
|
+
const frameRef = useRef(null);
|
|
534
|
+
const [measuredHeight, setMeasuredHeight] = useState();
|
|
535
|
+
useEffect(() => {
|
|
536
|
+
if (entry.content === void 0) return;
|
|
537
|
+
const onMessage = (event) => {
|
|
538
|
+
if (event.source !== frameRef.current?.contentWindow) return;
|
|
539
|
+
const reported = event.data?.__esHtmlHeight;
|
|
540
|
+
if (typeof reported !== "number" || !Number.isFinite(reported) || reported <= 0) return;
|
|
541
|
+
setMeasuredHeight(Math.min(reported, MAX_MEASURED_HEIGHT));
|
|
542
|
+
};
|
|
543
|
+
window.addEventListener("message", onMessage);
|
|
544
|
+
return () => window.removeEventListener("message", onMessage);
|
|
545
|
+
}, [entry.content]);
|
|
546
|
+
const height = measuredHeight === void 0 ? declaredHeight : `${measuredHeight}px`;
|
|
547
|
+
const frameProps = entry.content !== void 0 ? { srcDoc: entry.content + MEASURE_SCRIPT } : { src: safeHref ?? "" };
|
|
531
548
|
return /* @__PURE__ */ jsxs9("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
|
|
532
549
|
/* @__PURE__ */ jsxs9("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: [
|
|
533
550
|
/* @__PURE__ */ jsx14("span", { children: entry.title ?? "HTML" }),
|
|
@@ -547,6 +564,7 @@ function DocHtml({ entry }) {
|
|
|
547
564
|
/* @__PURE__ */ jsx14(
|
|
548
565
|
"iframe",
|
|
549
566
|
{
|
|
567
|
+
ref: frameRef,
|
|
550
568
|
...frameProps,
|
|
551
569
|
sandbox: "allow-scripts",
|
|
552
570
|
loading: "lazy",
|
|
@@ -1095,7 +1113,7 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
1095
1113
|
}
|
|
1096
1114
|
|
|
1097
1115
|
// src/components/ScenarioStaleness.tsx
|
|
1098
|
-
import { useEffect, useState } from "react";
|
|
1116
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
1099
1117
|
|
|
1100
1118
|
// src/lib/provenance.ts
|
|
1101
1119
|
function reportLastRunMs(report) {
|
|
@@ -1163,8 +1181,8 @@ import { jsxs as jsxs16 } from "react/jsx-runtime";
|
|
|
1163
1181
|
function ScenarioStaleness({ scenario }) {
|
|
1164
1182
|
const freshness = useScenarioFreshness();
|
|
1165
1183
|
const fixedNow = freshness?.nowMs;
|
|
1166
|
-
const [now, setNow] =
|
|
1167
|
-
|
|
1184
|
+
const [now, setNow] = useState2(fixedNow);
|
|
1185
|
+
useEffect2(() => {
|
|
1168
1186
|
if (fixedNow === void 0) setNow(Date.now());
|
|
1169
1187
|
}, [fixedNow]);
|
|
1170
1188
|
if (!freshness || now === void 0) return null;
|
|
@@ -1178,7 +1196,7 @@ function ScenarioStaleness({ scenario }) {
|
|
|
1178
1196
|
}
|
|
1179
1197
|
|
|
1180
1198
|
// src/interactive/collapse-context.ts
|
|
1181
|
-
import { createContext as createContext4, useCallback, useContext as useContext5, useState as
|
|
1199
|
+
import { createContext as createContext4, useCallback, useContext as useContext5, useState as useState3 } from "react";
|
|
1182
1200
|
var CollapseContext = createContext4(null);
|
|
1183
1201
|
var CollapseProvider = CollapseContext.Provider;
|
|
1184
1202
|
function useCollapse() {
|
|
@@ -1752,25 +1770,86 @@ function ReportErrorShell({
|
|
|
1752
1770
|
return /* @__PURE__ */ jsx36("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx36(ReportSchemaError, { error }) });
|
|
1753
1771
|
}
|
|
1754
1772
|
|
|
1755
|
-
// src/components/
|
|
1773
|
+
// src/components/ReportSpanGraph.tsx
|
|
1774
|
+
import { deriveSpanGraph, spanGraphNodeMark, spanGraphToMermaid } from "executable-stories-core/span-graph";
|
|
1775
|
+
import { useMemo as useMemo2 } from "react";
|
|
1756
1776
|
import { jsx as jsx37, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1777
|
+
var LANE_LABEL = {
|
|
1778
|
+
edge: "Edge",
|
|
1779
|
+
service: "Service",
|
|
1780
|
+
queue: "Queue",
|
|
1781
|
+
datastore: "Data"
|
|
1782
|
+
};
|
|
1783
|
+
var MARK_LABEL = {
|
|
1784
|
+
failing: "Failing",
|
|
1785
|
+
added: "New",
|
|
1786
|
+
changed: "Changed"
|
|
1787
|
+
};
|
|
1788
|
+
var MARK_CLASS = {
|
|
1789
|
+
failing: "text-fail",
|
|
1790
|
+
added: "text-pass",
|
|
1791
|
+
changed: "text-pend"
|
|
1792
|
+
};
|
|
1793
|
+
function MarkBadge({ node }) {
|
|
1794
|
+
const mark = spanGraphNodeMark(node);
|
|
1795
|
+
if (!mark) return null;
|
|
1796
|
+
return /* @__PURE__ */ jsx37("span", { className: cn("ml-2 text-xs font-medium", MARK_CLASS[mark]), children: MARK_LABEL[mark] });
|
|
1797
|
+
}
|
|
1798
|
+
function ReportSpanGraph() {
|
|
1799
|
+
const report = useReport();
|
|
1800
|
+
const { code, graph, titleById } = useMemo2(() => {
|
|
1801
|
+
const scenarios = report.features.flatMap((feature) => feature.scenarios);
|
|
1802
|
+
const derived = deriveSpanGraph(scenarios);
|
|
1803
|
+
return {
|
|
1804
|
+
graph: derived,
|
|
1805
|
+
code: spanGraphToMermaid(derived),
|
|
1806
|
+
titleById: new Map(scenarios.map((scenario) => [scenario.id, scenario.title]))
|
|
1807
|
+
};
|
|
1808
|
+
}, [report]);
|
|
1809
|
+
if (code === "") return null;
|
|
1810
|
+
return /* @__PURE__ */ jsxs25("section", { className: "es-span-graph mt-6", "aria-labelledby": "es-span-graph-heading", children: [
|
|
1811
|
+
/* @__PURE__ */ jsx37("h2", { id: "es-span-graph-heading", className: "text-base font-semibold text-foreground", children: "Architecture, as it ran" }),
|
|
1812
|
+
/* @__PURE__ */ jsx37("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." }),
|
|
1813
|
+
/* @__PURE__ */ jsx37(DocMermaid, { entry: { kind: "mermaid", phase: "static", code } }),
|
|
1814
|
+
/* @__PURE__ */ jsxs25("table", { className: "mt-2 w-full border-collapse text-left text-sm", children: [
|
|
1815
|
+
/* @__PURE__ */ jsx37("caption", { className: "sr-only", children: "Each component and the scenarios that exercised it" }),
|
|
1816
|
+
/* @__PURE__ */ jsx37("thead", { children: /* @__PURE__ */ jsxs25("tr", { className: "text-xs text-muted-foreground", children: [
|
|
1817
|
+
/* @__PURE__ */ jsx37("th", { scope: "col", className: "py-1 pr-4 font-medium", children: "Component" }),
|
|
1818
|
+
/* @__PURE__ */ jsx37("th", { scope: "col", className: "py-1 pr-4 font-medium", children: "Lane" }),
|
|
1819
|
+
/* @__PURE__ */ jsx37("th", { scope: "col", className: "py-1 font-medium", children: "Covered by" })
|
|
1820
|
+
] }) }),
|
|
1821
|
+
/* @__PURE__ */ jsx37("tbody", { children: graph.nodes.map((node) => /* @__PURE__ */ jsxs25("tr", { className: "border-t border-border align-top", children: [
|
|
1822
|
+
/* @__PURE__ */ jsxs25("th", { scope: "row", className: "py-1.5 pr-4 font-mono text-xs font-normal", children: [
|
|
1823
|
+
node.id,
|
|
1824
|
+
/* @__PURE__ */ jsx37(MarkBadge, { node })
|
|
1825
|
+
] }),
|
|
1826
|
+
/* @__PURE__ */ jsx37("td", { className: "py-1.5 pr-4 text-xs text-muted-foreground", children: LANE_LABEL[node.kind] }),
|
|
1827
|
+
/* @__PURE__ */ jsx37("td", { className: "py-1.5", children: /* @__PURE__ */ jsx37("ul", { className: "flex flex-col gap-0.5", children: node.scenarioIds.map((id) => /* @__PURE__ */ jsx37("li", { children: /* @__PURE__ */ jsx37("a", { href: `#${id}`, className: "text-xs text-link underline underline-offset-2 hover:text-foreground", children: titleById.get(id) ?? id }) }, id)) }) })
|
|
1828
|
+
] }, node.id)) })
|
|
1829
|
+
] })
|
|
1830
|
+
] });
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
// src/components/Report.tsx
|
|
1834
|
+
import { jsx as jsx38, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1757
1835
|
function Report(props) {
|
|
1758
|
-
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1836
|
+
const { report, customRenderers, renderers, className, title, dataTheme, architecture = false } = props;
|
|
1759
1837
|
const result = unwrapReport(report);
|
|
1760
1838
|
if (!result.ok) {
|
|
1761
|
-
return /* @__PURE__ */
|
|
1839
|
+
return /* @__PURE__ */ jsx38(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1762
1840
|
}
|
|
1763
1841
|
const data = result.data;
|
|
1764
1842
|
const hasContent = data.features.length > 0;
|
|
1765
|
-
return /* @__PURE__ */
|
|
1766
|
-
/* @__PURE__ */
|
|
1767
|
-
|
|
1843
|
+
return /* @__PURE__ */ jsx38(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ jsxs26("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1844
|
+
/* @__PURE__ */ jsx38("header", { className: "es-report-header", children: /* @__PURE__ */ jsx38(ReportTitleBlock, { title }) }),
|
|
1845
|
+
architecture ? /* @__PURE__ */ jsx38(ReportSpanGraph, {}) : null,
|
|
1846
|
+
hasContent ? /* @__PURE__ */ jsx38(ReportFeatureList, {}) : /* @__PURE__ */ jsx38(ReportEmpty, {})
|
|
1768
1847
|
] }) });
|
|
1769
1848
|
}
|
|
1770
1849
|
|
|
1771
1850
|
// src/components/doc/MermaidView.tsx
|
|
1772
|
-
import { useEffect as
|
|
1773
|
-
import { Fragment as Fragment11, jsx as
|
|
1851
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
|
|
1852
|
+
import { Fragment as Fragment11, jsx as jsx39, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1774
1853
|
function prefersDark(el) {
|
|
1775
1854
|
const themed = el?.closest("[data-theme]");
|
|
1776
1855
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -1778,10 +1857,10 @@ function prefersDark(el) {
|
|
|
1778
1857
|
return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
|
|
1779
1858
|
}
|
|
1780
1859
|
function MermaidView({ entry, load }) {
|
|
1781
|
-
const ref =
|
|
1782
|
-
const [svg, setSvg] =
|
|
1783
|
-
const [error, setError] =
|
|
1784
|
-
|
|
1860
|
+
const ref = useRef2(null);
|
|
1861
|
+
const [svg, setSvg] = useState4(null);
|
|
1862
|
+
const [error, setError] = useState4(null);
|
|
1863
|
+
useEffect3(() => {
|
|
1785
1864
|
let cancelled = false;
|
|
1786
1865
|
const draw = async () => {
|
|
1787
1866
|
let mermaid;
|
|
@@ -1798,7 +1877,10 @@ function MermaidView({ entry, load }) {
|
|
|
1798
1877
|
mermaid.initialize({
|
|
1799
1878
|
startOnLoad: false,
|
|
1800
1879
|
securityLevel: "strict",
|
|
1801
|
-
|
|
1880
|
+
// "neutral" in light: the same theme the static, no-JS render uses
|
|
1881
|
+
// in ssr-entry, so a diagram keeps its colours when the island takes
|
|
1882
|
+
// over.
|
|
1883
|
+
theme: prefersDark(ref.current) ? "dark" : "neutral"
|
|
1802
1884
|
});
|
|
1803
1885
|
await mermaid.parse(entry.code);
|
|
1804
1886
|
const id = `es-mermaid-${Math.random().toString(36).slice(2)}`;
|
|
@@ -1824,9 +1906,9 @@ function MermaidView({ entry, load }) {
|
|
|
1824
1906
|
};
|
|
1825
1907
|
}, [entry.code, load]);
|
|
1826
1908
|
if (svg) {
|
|
1827
|
-
return /* @__PURE__ */
|
|
1828
|
-
entry.title ? /* @__PURE__ */
|
|
1829
|
-
/* @__PURE__ */
|
|
1909
|
+
return /* @__PURE__ */ jsxs27("figure", { ref, className: "my-3", children: [
|
|
1910
|
+
entry.title ? /* @__PURE__ */ jsx39("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
1911
|
+
/* @__PURE__ */ jsx39(
|
|
1830
1912
|
"div",
|
|
1831
1913
|
{
|
|
1832
1914
|
role: "img",
|
|
@@ -1837,8 +1919,8 @@ function MermaidView({ entry, load }) {
|
|
|
1837
1919
|
)
|
|
1838
1920
|
] });
|
|
1839
1921
|
}
|
|
1840
|
-
return /* @__PURE__ */
|
|
1841
|
-
error ? /* @__PURE__ */
|
|
1922
|
+
return /* @__PURE__ */ jsxs27(Fragment11, { children: [
|
|
1923
|
+
error ? /* @__PURE__ */ jsxs27(
|
|
1842
1924
|
"p",
|
|
1843
1925
|
{
|
|
1844
1926
|
role: "alert",
|
|
@@ -1850,34 +1932,34 @@ function MermaidView({ entry, load }) {
|
|
|
1850
1932
|
]
|
|
1851
1933
|
}
|
|
1852
1934
|
) : null,
|
|
1853
|
-
/* @__PURE__ */
|
|
1935
|
+
/* @__PURE__ */ jsx39(MermaidSource, { entry, ref })
|
|
1854
1936
|
] });
|
|
1855
1937
|
}
|
|
1856
1938
|
|
|
1857
1939
|
// src/components/doc/MermaidDiagram.tsx
|
|
1858
|
-
import { jsx as
|
|
1940
|
+
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
1859
1941
|
var mermaidLoader;
|
|
1860
1942
|
function loadMermaid() {
|
|
1861
1943
|
mermaidLoader ??= import("mermaid").then((m) => m.default);
|
|
1862
1944
|
return mermaidLoader;
|
|
1863
1945
|
}
|
|
1864
1946
|
function MermaidDiagram({ entry, load = loadMermaid }) {
|
|
1865
|
-
return /* @__PURE__ */
|
|
1947
|
+
return /* @__PURE__ */ jsx40(MermaidView, { entry, load });
|
|
1866
1948
|
}
|
|
1867
1949
|
|
|
1868
1950
|
// src/components/ScenarioExplorer.tsx
|
|
1869
|
-
import { useState as
|
|
1951
|
+
import { useState as useState5 } from "react";
|
|
1870
1952
|
|
|
1871
1953
|
// src/components/ui/command.tsx
|
|
1872
1954
|
import "react";
|
|
1873
1955
|
import { Command as CommandPrimitive } from "cmdk";
|
|
1874
1956
|
import { SearchIcon } from "lucide-react";
|
|
1875
|
-
import { jsx as
|
|
1957
|
+
import { jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
1876
1958
|
function Command({
|
|
1877
1959
|
className,
|
|
1878
1960
|
...props
|
|
1879
1961
|
}) {
|
|
1880
|
-
return /* @__PURE__ */
|
|
1962
|
+
return /* @__PURE__ */ jsx41(
|
|
1881
1963
|
CommandPrimitive,
|
|
1882
1964
|
{
|
|
1883
1965
|
"data-slot": "command",
|
|
@@ -1893,14 +1975,14 @@ function CommandInput({
|
|
|
1893
1975
|
className,
|
|
1894
1976
|
...props
|
|
1895
1977
|
}) {
|
|
1896
|
-
return /* @__PURE__ */
|
|
1978
|
+
return /* @__PURE__ */ jsxs28(
|
|
1897
1979
|
"div",
|
|
1898
1980
|
{
|
|
1899
1981
|
"data-slot": "command-input-wrapper",
|
|
1900
1982
|
className: "flex h-9 items-center gap-2 border-b px-3",
|
|
1901
1983
|
children: [
|
|
1902
|
-
/* @__PURE__ */
|
|
1903
|
-
/* @__PURE__ */
|
|
1984
|
+
/* @__PURE__ */ jsx41(SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
|
|
1985
|
+
/* @__PURE__ */ jsx41(
|
|
1904
1986
|
CommandPrimitive.Input,
|
|
1905
1987
|
{
|
|
1906
1988
|
"data-slot": "command-input",
|
|
@@ -1919,7 +2001,7 @@ function CommandList({
|
|
|
1919
2001
|
className,
|
|
1920
2002
|
...props
|
|
1921
2003
|
}) {
|
|
1922
|
-
return /* @__PURE__ */
|
|
2004
|
+
return /* @__PURE__ */ jsx41(
|
|
1923
2005
|
CommandPrimitive.List,
|
|
1924
2006
|
{
|
|
1925
2007
|
"data-slot": "command-list",
|
|
@@ -1934,7 +2016,7 @@ function CommandList({
|
|
|
1934
2016
|
function CommandEmpty({
|
|
1935
2017
|
...props
|
|
1936
2018
|
}) {
|
|
1937
|
-
return /* @__PURE__ */
|
|
2019
|
+
return /* @__PURE__ */ jsx41(
|
|
1938
2020
|
CommandPrimitive.Empty,
|
|
1939
2021
|
{
|
|
1940
2022
|
"data-slot": "command-empty",
|
|
@@ -1947,7 +2029,7 @@ function CommandGroup({
|
|
|
1947
2029
|
className,
|
|
1948
2030
|
...props
|
|
1949
2031
|
}) {
|
|
1950
|
-
return /* @__PURE__ */
|
|
2032
|
+
return /* @__PURE__ */ jsx41(
|
|
1951
2033
|
CommandPrimitive.Group,
|
|
1952
2034
|
{
|
|
1953
2035
|
"data-slot": "command-group",
|
|
@@ -1963,7 +2045,7 @@ function CommandItem({
|
|
|
1963
2045
|
className,
|
|
1964
2046
|
...props
|
|
1965
2047
|
}) {
|
|
1966
|
-
return /* @__PURE__ */
|
|
2048
|
+
return /* @__PURE__ */ jsx41(
|
|
1967
2049
|
CommandPrimitive.Item,
|
|
1968
2050
|
{
|
|
1969
2051
|
"data-slot": "command-item",
|
|
@@ -1977,7 +2059,7 @@ function CommandItem({
|
|
|
1977
2059
|
}
|
|
1978
2060
|
|
|
1979
2061
|
// src/components/ScenarioExplorer.tsx
|
|
1980
|
-
import { jsx as
|
|
2062
|
+
import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
1981
2063
|
var STATUS_FILTERS = [
|
|
1982
2064
|
{ value: "all", label: "All" },
|
|
1983
2065
|
{ value: "passed", label: "Passed" },
|
|
@@ -1986,24 +2068,24 @@ var STATUS_FILTERS = [
|
|
|
1986
2068
|
{ value: "pending", label: "Pending" }
|
|
1987
2069
|
];
|
|
1988
2070
|
function ScenarioExplorer({ scenarios, summary }) {
|
|
1989
|
-
const [status, setStatus] =
|
|
2071
|
+
const [status, setStatus] = useState5("all");
|
|
1990
2072
|
const visible = status === "all" ? scenarios : scenarios.filter((s) => s.status === status);
|
|
1991
|
-
return /* @__PURE__ */
|
|
1992
|
-
summary ? /* @__PURE__ */
|
|
2073
|
+
return /* @__PURE__ */ jsxs29("div", { className: "font-sans text-foreground", children: [
|
|
2074
|
+
summary ? /* @__PURE__ */ jsxs29("p", { className: "mb-3 text-sm text-muted-foreground", children: [
|
|
1993
2075
|
summary.total,
|
|
1994
2076
|
" scenarios \xB7 ",
|
|
1995
|
-
/* @__PURE__ */
|
|
2077
|
+
/* @__PURE__ */ jsxs29("span", { className: "text-pass", children: [
|
|
1996
2078
|
summary.passed,
|
|
1997
2079
|
" passed"
|
|
1998
2080
|
] }),
|
|
1999
2081
|
" \xB7",
|
|
2000
2082
|
" ",
|
|
2001
|
-
/* @__PURE__ */
|
|
2083
|
+
/* @__PURE__ */ jsxs29("span", { className: "text-fail", children: [
|
|
2002
2084
|
summary.failed,
|
|
2003
2085
|
" failed"
|
|
2004
2086
|
] })
|
|
2005
2087
|
] }) : null,
|
|
2006
|
-
/* @__PURE__ */
|
|
2088
|
+
/* @__PURE__ */ jsx42("div", { className: "mb-2 flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by status", children: STATUS_FILTERS.map((f) => /* @__PURE__ */ jsx42(
|
|
2007
2089
|
"button",
|
|
2008
2090
|
{
|
|
2009
2091
|
type: "button",
|
|
@@ -2018,26 +2100,26 @@ function ScenarioExplorer({ scenarios, summary }) {
|
|
|
2018
2100
|
},
|
|
2019
2101
|
f.value
|
|
2020
2102
|
)) }),
|
|
2021
|
-
/* @__PURE__ */
|
|
2103
|
+
/* @__PURE__ */ jsxs29(
|
|
2022
2104
|
Command,
|
|
2023
2105
|
{
|
|
2024
2106
|
className: "rounded-lg border border-border bg-card",
|
|
2025
2107
|
filter: (value, search) => value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0,
|
|
2026
2108
|
children: [
|
|
2027
|
-
/* @__PURE__ */
|
|
2028
|
-
/* @__PURE__ */
|
|
2029
|
-
/* @__PURE__ */
|
|
2030
|
-
/* @__PURE__ */
|
|
2109
|
+
/* @__PURE__ */ jsx42(CommandInput, { placeholder: "Search scenarios\u2026" }),
|
|
2110
|
+
/* @__PURE__ */ jsxs29(CommandList, { className: "max-h-none", children: [
|
|
2111
|
+
/* @__PURE__ */ jsx42(CommandEmpty, { children: "No scenarios match your filters." }),
|
|
2112
|
+
/* @__PURE__ */ jsx42(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ jsx42(
|
|
2031
2113
|
CommandItem,
|
|
2032
2114
|
{
|
|
2033
2115
|
value: `${s.title} ${s.feature} ${s.tags.join(" ")}`,
|
|
2034
2116
|
asChild: true,
|
|
2035
2117
|
className: "cursor-pointer",
|
|
2036
|
-
children: /* @__PURE__ */
|
|
2037
|
-
/* @__PURE__ */
|
|
2038
|
-
/* @__PURE__ */
|
|
2039
|
-
s.tags.slice(0, 3).map((t) => /* @__PURE__ */
|
|
2040
|
-
/* @__PURE__ */
|
|
2118
|
+
children: /* @__PURE__ */ jsxs29("a", { href: s.href, className: "flex items-center gap-3", children: [
|
|
2119
|
+
/* @__PURE__ */ jsx42(Badge, { variant: s.status, children: s.status }),
|
|
2120
|
+
/* @__PURE__ */ jsx42("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
|
|
2121
|
+
s.tags.slice(0, 3).map((t) => /* @__PURE__ */ jsx42(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
|
|
2122
|
+
/* @__PURE__ */ jsx42("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
|
|
2041
2123
|
] })
|
|
2042
2124
|
},
|
|
2043
2125
|
s.id
|