executable-stories-react 0.14.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 +142 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +131 -52
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +518 -361
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +4 -0
- package/dist/interactive.d.ts +4 -0
- package/dist/interactive.js +471 -314
- package/dist/interactive.js.map +1 -1
- package/dist/report-island.global.js +53 -51
- package/dist/ssr.cjs +110 -26
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.d.cts +4 -0
- package/dist/ssr.d.ts +4 -0
- package/dist/ssr.js +97 -13
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +3 -3
package/dist/interactive.js
CHANGED
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
useCallback as useCallback5,
|
|
8
8
|
useDeferredValue,
|
|
9
9
|
useId as useId2,
|
|
10
|
-
useMemo as
|
|
11
|
-
useRef as
|
|
12
|
-
useState as
|
|
10
|
+
useMemo as useMemo4,
|
|
11
|
+
useRef as useRef7,
|
|
12
|
+
useState as useState12
|
|
13
13
|
} from "react";
|
|
14
14
|
|
|
15
15
|
// src/components/ui/empty.tsx
|
|
@@ -384,12 +384,29 @@ function DocVideo({ entry }) {
|
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
// src/components/doc/DocHtml.tsx
|
|
387
|
+
import { useEffect, useRef, useState } from "react";
|
|
387
388
|
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
389
|
+
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>";
|
|
390
|
+
var MAX_MEASURED_HEIGHT = 5e3;
|
|
388
391
|
function DocHtml({ entry }) {
|
|
389
|
-
const
|
|
392
|
+
const declaredHeight = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
390
393
|
const title = entry.title ?? "Embedded HTML";
|
|
391
394
|
const safeHref = safeUrl(entry.url ?? entry.path);
|
|
392
|
-
const
|
|
395
|
+
const frameRef = useRef(null);
|
|
396
|
+
const [measuredHeight, setMeasuredHeight] = useState();
|
|
397
|
+
useEffect(() => {
|
|
398
|
+
if (entry.content === void 0) return;
|
|
399
|
+
const onMessage = (event) => {
|
|
400
|
+
if (event.source !== frameRef.current?.contentWindow) return;
|
|
401
|
+
const reported = event.data?.__esHtmlHeight;
|
|
402
|
+
if (typeof reported !== "number" || !Number.isFinite(reported) || reported <= 0) return;
|
|
403
|
+
setMeasuredHeight(Math.min(reported, MAX_MEASURED_HEIGHT));
|
|
404
|
+
};
|
|
405
|
+
window.addEventListener("message", onMessage);
|
|
406
|
+
return () => window.removeEventListener("message", onMessage);
|
|
407
|
+
}, [entry.content]);
|
|
408
|
+
const height = measuredHeight === void 0 ? declaredHeight : `${measuredHeight}px`;
|
|
409
|
+
const frameProps = entry.content !== void 0 ? { srcDoc: entry.content + MEASURE_SCRIPT } : { src: safeHref ?? "" };
|
|
393
410
|
return /* @__PURE__ */ jsxs8("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
|
|
394
411
|
/* @__PURE__ */ jsxs8("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: [
|
|
395
412
|
/* @__PURE__ */ jsx14("span", { children: entry.title ?? "HTML" }),
|
|
@@ -409,6 +426,7 @@ function DocHtml({ entry }) {
|
|
|
409
426
|
/* @__PURE__ */ jsx14(
|
|
410
427
|
"iframe",
|
|
411
428
|
{
|
|
429
|
+
ref: frameRef,
|
|
412
430
|
...frameProps,
|
|
413
431
|
sandbox: "allow-scripts",
|
|
414
432
|
loading: "lazy",
|
|
@@ -975,7 +993,7 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
975
993
|
}
|
|
976
994
|
|
|
977
995
|
// src/components/ScenarioStaleness.tsx
|
|
978
|
-
import { useEffect, useState } from "react";
|
|
996
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
979
997
|
|
|
980
998
|
// src/lib/provenance.ts
|
|
981
999
|
function reportLastRunMs(report) {
|
|
@@ -1039,8 +1057,8 @@ import { jsxs as jsxs15 } from "react/jsx-runtime";
|
|
|
1039
1057
|
function ScenarioStaleness({ scenario }) {
|
|
1040
1058
|
const freshness = useScenarioFreshness();
|
|
1041
1059
|
const fixedNow = freshness?.nowMs;
|
|
1042
|
-
const [now, setNow] =
|
|
1043
|
-
|
|
1060
|
+
const [now, setNow] = useState2(fixedNow);
|
|
1061
|
+
useEffect2(() => {
|
|
1044
1062
|
if (fixedNow === void 0) setNow(Date.now());
|
|
1045
1063
|
}, [fixedNow]);
|
|
1046
1064
|
if (!freshness || now === void 0) return null;
|
|
@@ -1054,7 +1072,7 @@ function ScenarioStaleness({ scenario }) {
|
|
|
1054
1072
|
}
|
|
1055
1073
|
|
|
1056
1074
|
// src/interactive/collapse-context.ts
|
|
1057
|
-
import { createContext as createContext4, useCallback, useContext as useContext5, useState as
|
|
1075
|
+
import { createContext as createContext4, useCallback, useContext as useContext5, useState as useState3 } from "react";
|
|
1058
1076
|
var CollapseContext = createContext4(null);
|
|
1059
1077
|
var CollapseProvider = CollapseContext.Provider;
|
|
1060
1078
|
function useCollapse() {
|
|
@@ -1078,7 +1096,7 @@ function persist(ids) {
|
|
|
1078
1096
|
}
|
|
1079
1097
|
}
|
|
1080
1098
|
function useCollapseState(computeDefault) {
|
|
1081
|
-
const [collapsed, setCollapsed] =
|
|
1099
|
+
const [collapsed, setCollapsed] = useState3(
|
|
1082
1100
|
() => readPersisted() ?? computeDefault?.() ?? /* @__PURE__ */ new Set()
|
|
1083
1101
|
);
|
|
1084
1102
|
const isCollapsed = useCallback((id) => collapsed.has(id), [collapsed]);
|
|
@@ -1652,15 +1670,75 @@ function ReportErrorShell({
|
|
|
1652
1670
|
return /* @__PURE__ */ jsx34("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx34(ReportSchemaError, { error }) });
|
|
1653
1671
|
}
|
|
1654
1672
|
|
|
1673
|
+
// src/components/ReportSpanGraph.tsx
|
|
1674
|
+
import { deriveSpanGraph, spanGraphNodeMark, spanGraphToMermaid } from "executable-stories-core/span-graph";
|
|
1675
|
+
import { useMemo } from "react";
|
|
1676
|
+
import { jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1677
|
+
var LANE_LABEL = {
|
|
1678
|
+
edge: "Edge",
|
|
1679
|
+
service: "Service",
|
|
1680
|
+
queue: "Queue",
|
|
1681
|
+
datastore: "Data"
|
|
1682
|
+
};
|
|
1683
|
+
var MARK_LABEL = {
|
|
1684
|
+
failing: "Failing",
|
|
1685
|
+
added: "New",
|
|
1686
|
+
changed: "Changed"
|
|
1687
|
+
};
|
|
1688
|
+
var MARK_CLASS = {
|
|
1689
|
+
failing: "text-fail",
|
|
1690
|
+
added: "text-pass",
|
|
1691
|
+
changed: "text-pend"
|
|
1692
|
+
};
|
|
1693
|
+
function MarkBadge({ node }) {
|
|
1694
|
+
const mark = spanGraphNodeMark(node);
|
|
1695
|
+
if (!mark) return null;
|
|
1696
|
+
return /* @__PURE__ */ jsx35("span", { className: cn("ml-2 text-xs font-medium", MARK_CLASS[mark]), children: MARK_LABEL[mark] });
|
|
1697
|
+
}
|
|
1698
|
+
function ReportSpanGraph() {
|
|
1699
|
+
const report = useReport();
|
|
1700
|
+
const { code, graph, titleById } = useMemo(() => {
|
|
1701
|
+
const scenarios = report.features.flatMap((feature) => feature.scenarios);
|
|
1702
|
+
const derived = deriveSpanGraph(scenarios);
|
|
1703
|
+
return {
|
|
1704
|
+
graph: derived,
|
|
1705
|
+
code: spanGraphToMermaid(derived),
|
|
1706
|
+
titleById: new Map(scenarios.map((scenario) => [scenario.id, scenario.title]))
|
|
1707
|
+
};
|
|
1708
|
+
}, [report]);
|
|
1709
|
+
if (code === "") return null;
|
|
1710
|
+
return /* @__PURE__ */ jsxs24("section", { className: "es-span-graph mt-6", "aria-labelledby": "es-span-graph-heading", children: [
|
|
1711
|
+
/* @__PURE__ */ jsx35("h2", { id: "es-span-graph-heading", className: "text-base font-semibold text-foreground", children: "Architecture, as it ran" }),
|
|
1712
|
+
/* @__PURE__ */ jsx35("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." }),
|
|
1713
|
+
/* @__PURE__ */ jsx35(DocMermaid, { entry: { kind: "mermaid", phase: "static", code } }),
|
|
1714
|
+
/* @__PURE__ */ jsxs24("table", { className: "mt-2 w-full text-left text-sm", children: [
|
|
1715
|
+
/* @__PURE__ */ jsx35("caption", { className: "sr-only", children: "Each component and the scenarios that exercised it" }),
|
|
1716
|
+
/* @__PURE__ */ jsx35("thead", { children: /* @__PURE__ */ jsxs24("tr", { className: "text-xs text-muted-foreground", children: [
|
|
1717
|
+
/* @__PURE__ */ jsx35("th", { scope: "col", className: "py-1 pr-4 font-medium", children: "Component" }),
|
|
1718
|
+
/* @__PURE__ */ jsx35("th", { scope: "col", className: "py-1 pr-4 font-medium", children: "Lane" }),
|
|
1719
|
+
/* @__PURE__ */ jsx35("th", { scope: "col", className: "py-1 font-medium", children: "Covered by" })
|
|
1720
|
+
] }) }),
|
|
1721
|
+
/* @__PURE__ */ jsx35("tbody", { children: graph.nodes.map((node) => /* @__PURE__ */ jsxs24("tr", { className: "border-t border-border align-top", children: [
|
|
1722
|
+
/* @__PURE__ */ jsxs24("th", { scope: "row", className: "py-1.5 pr-4 font-mono text-xs font-normal", children: [
|
|
1723
|
+
node.id,
|
|
1724
|
+
/* @__PURE__ */ jsx35(MarkBadge, { node })
|
|
1725
|
+
] }),
|
|
1726
|
+
/* @__PURE__ */ jsx35("td", { className: "py-1.5 pr-4 text-xs text-muted-foreground", children: LANE_LABEL[node.kind] }),
|
|
1727
|
+
/* @__PURE__ */ jsx35("td", { className: "py-1.5", children: /* @__PURE__ */ jsx35("ul", { className: "flex flex-col gap-0.5", children: node.scenarioIds.map((id) => /* @__PURE__ */ jsx35("li", { children: /* @__PURE__ */ jsx35("a", { href: `#${id}`, className: "text-xs underline underline-offset-2", children: titleById.get(id) ?? id }) }, id)) }) })
|
|
1728
|
+
] }, node.id)) })
|
|
1729
|
+
] })
|
|
1730
|
+
] });
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1655
1733
|
// src/components/ui/switch.tsx
|
|
1656
1734
|
import "react";
|
|
1657
1735
|
import { Switch as SwitchPrimitive } from "@base-ui/react/switch";
|
|
1658
|
-
import { jsx as
|
|
1736
|
+
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
1659
1737
|
function Switch({
|
|
1660
1738
|
className,
|
|
1661
1739
|
...props
|
|
1662
1740
|
}) {
|
|
1663
|
-
return /* @__PURE__ */
|
|
1741
|
+
return /* @__PURE__ */ jsx36(
|
|
1664
1742
|
SwitchPrimitive.Root,
|
|
1665
1743
|
{
|
|
1666
1744
|
"data-slot": "switch",
|
|
@@ -1669,7 +1747,7 @@ function Switch({
|
|
|
1669
1747
|
className
|
|
1670
1748
|
),
|
|
1671
1749
|
...props,
|
|
1672
|
-
children: /* @__PURE__ */
|
|
1750
|
+
children: /* @__PURE__ */ jsx36(
|
|
1673
1751
|
SwitchPrimitive.Thumb,
|
|
1674
1752
|
{
|
|
1675
1753
|
"data-slot": "switch-thumb",
|
|
@@ -1685,7 +1763,7 @@ import * as React5 from "react";
|
|
|
1685
1763
|
import { ToggleGroup as ToggleGroupPrimitive } from "@base-ui/react/toggle-group";
|
|
1686
1764
|
import { Toggle as TogglePrimitive } from "@base-ui/react/toggle";
|
|
1687
1765
|
import { cva as cva3 } from "class-variance-authority";
|
|
1688
|
-
import { jsx as
|
|
1766
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
1689
1767
|
var toggleItemVariants = cva3(
|
|
1690
1768
|
"inline-flex items-center justify-center gap-1.5 rounded-md font-medium whitespace-nowrap text-muted-foreground transition-[color,background-color,box-shadow] outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 data-[pressed]:bg-background data-[pressed]:text-foreground data-[pressed]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1691
1769
|
{
|
|
@@ -1707,13 +1785,13 @@ function ToggleGroup({
|
|
|
1707
1785
|
children,
|
|
1708
1786
|
...props
|
|
1709
1787
|
}) {
|
|
1710
|
-
return /* @__PURE__ */
|
|
1788
|
+
return /* @__PURE__ */ jsx37(
|
|
1711
1789
|
ToggleGroupPrimitive,
|
|
1712
1790
|
{
|
|
1713
1791
|
"data-slot": "toggle-group",
|
|
1714
1792
|
className: cn("flex w-fit items-center gap-0.5 rounded-lg bg-muted p-0.5", className),
|
|
1715
1793
|
...props,
|
|
1716
|
-
children: /* @__PURE__ */
|
|
1794
|
+
children: /* @__PURE__ */ jsx37(ToggleGroupContext.Provider, { value: { size }, children })
|
|
1717
1795
|
}
|
|
1718
1796
|
);
|
|
1719
1797
|
}
|
|
@@ -1724,7 +1802,7 @@ function ToggleGroupItem({
|
|
|
1724
1802
|
...props
|
|
1725
1803
|
}) {
|
|
1726
1804
|
const context = React5.useContext(ToggleGroupContext);
|
|
1727
|
-
return /* @__PURE__ */
|
|
1805
|
+
return /* @__PURE__ */ jsx37(
|
|
1728
1806
|
TogglePrimitive,
|
|
1729
1807
|
{
|
|
1730
1808
|
"data-slot": "toggle-group-item",
|
|
@@ -1736,10 +1814,10 @@ function ToggleGroupItem({
|
|
|
1736
1814
|
}
|
|
1737
1815
|
|
|
1738
1816
|
// src/context/ReportRoot.tsx
|
|
1739
|
-
import { useMemo } from "react";
|
|
1817
|
+
import { useMemo as useMemo2 } from "react";
|
|
1740
1818
|
|
|
1741
1819
|
// src/components/doc/NarrativeBlocks.tsx
|
|
1742
|
-
import { jsx as
|
|
1820
|
+
import { jsx as jsx38, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1743
1821
|
var FILE_TREE_TYPE = "file-tree";
|
|
1744
1822
|
var DATA_MODEL_TYPE = "data-model";
|
|
1745
1823
|
function isChangeKind(value) {
|
|
@@ -1753,23 +1831,23 @@ function str(value) {
|
|
|
1753
1831
|
}
|
|
1754
1832
|
function AuthoredMarker({ authored }) {
|
|
1755
1833
|
if (authored !== "agent") return null;
|
|
1756
|
-
return /* @__PURE__ */
|
|
1834
|
+
return /* @__PURE__ */ jsx38(Badge, { variant: "outline", className: "border-border text-[10px] text-muted-foreground", children: "AI-authored, not verified by a run" });
|
|
1757
1835
|
}
|
|
1758
1836
|
function BlockFrame({
|
|
1759
1837
|
title,
|
|
1760
1838
|
authored,
|
|
1761
1839
|
children
|
|
1762
1840
|
}) {
|
|
1763
|
-
return /* @__PURE__ */
|
|
1764
|
-
title || authored === "agent" ? /* @__PURE__ */
|
|
1765
|
-
title ? /* @__PURE__ */
|
|
1766
|
-
/* @__PURE__ */
|
|
1841
|
+
return /* @__PURE__ */ jsxs25("figure", { className: "my-3", children: [
|
|
1842
|
+
title || authored === "agent" ? /* @__PURE__ */ jsxs25("figcaption", { className: "mb-1.5 flex flex-wrap items-center gap-2", children: [
|
|
1843
|
+
title ? /* @__PURE__ */ jsx38("span", { className: "text-xs font-medium text-muted-foreground", children: title }) : null,
|
|
1844
|
+
/* @__PURE__ */ jsx38(AuthoredMarker, { authored })
|
|
1767
1845
|
] }) : null,
|
|
1768
1846
|
children
|
|
1769
1847
|
] });
|
|
1770
1848
|
}
|
|
1771
1849
|
function ChangeBadge({ change }) {
|
|
1772
|
-
return /* @__PURE__ */
|
|
1850
|
+
return /* @__PURE__ */ jsx38(Badge, { variant: "tag", className: "text-[10px]", children: change });
|
|
1773
1851
|
}
|
|
1774
1852
|
function parseFileTree(data) {
|
|
1775
1853
|
if (!isRecord(data) || !Array.isArray(data.files)) return void 0;
|
|
@@ -1818,11 +1896,11 @@ function sortedChildren(node) {
|
|
|
1818
1896
|
}
|
|
1819
1897
|
function TreeBranch({ node, depth }) {
|
|
1820
1898
|
const children = sortedChildren(node);
|
|
1821
|
-
return /* @__PURE__ */
|
|
1899
|
+
return /* @__PURE__ */ jsx38("ul", { className: cn("space-y-0.5", depth > 0 && "ml-3 border-l border-border/60 pl-3"), children: children.map((child) => {
|
|
1822
1900
|
const isDir = child.children.size > 0;
|
|
1823
|
-
return /* @__PURE__ */
|
|
1824
|
-
/* @__PURE__ */
|
|
1825
|
-
/* @__PURE__ */
|
|
1901
|
+
return /* @__PURE__ */ jsxs25("li", { children: [
|
|
1902
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex flex-wrap items-baseline gap-2", children: [
|
|
1903
|
+
/* @__PURE__ */ jsx38(
|
|
1826
1904
|
"span",
|
|
1827
1905
|
{
|
|
1828
1906
|
className: cn(
|
|
@@ -1832,17 +1910,17 @@ function TreeBranch({ node, depth }) {
|
|
|
1832
1910
|
children: isDir ? `${child.name}/` : child.name
|
|
1833
1911
|
}
|
|
1834
1912
|
),
|
|
1835
|
-
child.file?.change ? /* @__PURE__ */
|
|
1836
|
-
child.file?.note ? /* @__PURE__ */
|
|
1913
|
+
child.file?.change ? /* @__PURE__ */ jsx38(ChangeBadge, { change: child.file.change }) : null,
|
|
1914
|
+
child.file?.note ? /* @__PURE__ */ jsx38("span", { className: "text-xs text-muted-foreground", children: child.file.note }) : null
|
|
1837
1915
|
] }),
|
|
1838
|
-
isDir ? /* @__PURE__ */
|
|
1916
|
+
isDir ? /* @__PURE__ */ jsx38(TreeBranch, { node: child, depth: depth + 1 }) : null
|
|
1839
1917
|
] }, child.name);
|
|
1840
1918
|
}) });
|
|
1841
1919
|
}
|
|
1842
1920
|
function FileTreeBlock({ entry }) {
|
|
1843
1921
|
const data = parseFileTree(entry.data);
|
|
1844
|
-
if (!data) return /* @__PURE__ */
|
|
1845
|
-
return /* @__PURE__ */
|
|
1922
|
+
if (!data) return /* @__PURE__ */ jsx38(UnreadableBlock, { entry });
|
|
1923
|
+
return /* @__PURE__ */ jsx38(BlockFrame, { title: data.title ?? "Files changed", authored: data.authored, children: /* @__PURE__ */ jsx38("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border bg-card p-3", children: /* @__PURE__ */ jsx38(TreeBranch, { node: buildTree(data.files), depth: 0 }) }) });
|
|
1846
1924
|
}
|
|
1847
1925
|
function parseDataModel(data) {
|
|
1848
1926
|
if (!isRecord(data) || !Array.isArray(data.fields)) return void 0;
|
|
@@ -1868,31 +1946,31 @@ function parseDataModel(data) {
|
|
|
1868
1946
|
}
|
|
1869
1947
|
function DataModelBlock({ entry }) {
|
|
1870
1948
|
const data = parseDataModel(entry.data);
|
|
1871
|
-
if (!data) return /* @__PURE__ */
|
|
1949
|
+
if (!data) return /* @__PURE__ */ jsx38(UnreadableBlock, { entry });
|
|
1872
1950
|
const hasNotes = data.fields.some((f) => f.note);
|
|
1873
|
-
return /* @__PURE__ */
|
|
1874
|
-
/* @__PURE__ */
|
|
1875
|
-
/* @__PURE__ */
|
|
1876
|
-
/* @__PURE__ */
|
|
1877
|
-
hasNotes ? /* @__PURE__ */
|
|
1951
|
+
return /* @__PURE__ */ jsx38(BlockFrame, { title: data.title ?? data.name ?? "Data model", authored: data.authored, children: /* @__PURE__ */ jsx38("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ jsxs25("table", { className: "w-full border-collapse text-sm", children: [
|
|
1952
|
+
/* @__PURE__ */ jsx38("thead", { children: /* @__PURE__ */ jsxs25("tr", { className: "bg-muted/50", children: [
|
|
1953
|
+
/* @__PURE__ */ jsx38("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Field" }),
|
|
1954
|
+
/* @__PURE__ */ jsx38("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Type" }),
|
|
1955
|
+
hasNotes ? /* @__PURE__ */ jsx38("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Note" }) : null
|
|
1878
1956
|
] }) }),
|
|
1879
|
-
/* @__PURE__ */
|
|
1880
|
-
/* @__PURE__ */
|
|
1881
|
-
/* @__PURE__ */
|
|
1882
|
-
field.change ? /* @__PURE__ */
|
|
1957
|
+
/* @__PURE__ */ jsx38("tbody", { children: data.fields.map((field) => /* @__PURE__ */ jsxs25("tr", { children: [
|
|
1958
|
+
/* @__PURE__ */ jsx38("td", { className: "border-b border-border px-3 py-2", children: /* @__PURE__ */ jsxs25("span", { className: "flex flex-wrap items-center gap-2", children: [
|
|
1959
|
+
/* @__PURE__ */ jsx38("span", { className: "font-mono text-xs text-foreground", children: field.name }),
|
|
1960
|
+
field.change ? /* @__PURE__ */ jsx38(ChangeBadge, { change: field.change }) : null
|
|
1883
1961
|
] }) }),
|
|
1884
|
-
/* @__PURE__ */
|
|
1885
|
-
hasNotes ? /* @__PURE__ */
|
|
1962
|
+
/* @__PURE__ */ jsx38("td", { className: "border-b border-border px-3 py-2 font-mono text-xs text-muted-foreground", children: field.type ?? "" }),
|
|
1963
|
+
hasNotes ? /* @__PURE__ */ jsx38("td", { className: "border-b border-border px-3 py-2 text-foreground", children: field.note ?? "" }) : null
|
|
1886
1964
|
] }, field.name)) })
|
|
1887
1965
|
] }) }) });
|
|
1888
1966
|
}
|
|
1889
1967
|
function UnreadableBlock({ entry }) {
|
|
1890
|
-
return /* @__PURE__ */
|
|
1891
|
-
/* @__PURE__ */
|
|
1968
|
+
return /* @__PURE__ */ jsxs25("div", { className: "my-2", "data-type": entry.type, children: [
|
|
1969
|
+
/* @__PURE__ */ jsxs25("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: [
|
|
1892
1970
|
entry.type,
|
|
1893
1971
|
" (unrecognised shape)"
|
|
1894
1972
|
] }),
|
|
1895
|
-
/* @__PURE__ */
|
|
1973
|
+
/* @__PURE__ */ jsx38(
|
|
1896
1974
|
"pre",
|
|
1897
1975
|
{
|
|
1898
1976
|
tabIndex: 0,
|
|
@@ -1910,12 +1988,12 @@ function safeStringify2(value) {
|
|
|
1910
1988
|
}
|
|
1911
1989
|
}
|
|
1912
1990
|
var narrativeBlockRenderers = {
|
|
1913
|
-
[FILE_TREE_TYPE]: (entry) => /* @__PURE__ */
|
|
1914
|
-
[DATA_MODEL_TYPE]: (entry) => /* @__PURE__ */
|
|
1991
|
+
[FILE_TREE_TYPE]: (entry) => /* @__PURE__ */ jsx38(FileTreeBlock, { entry }),
|
|
1992
|
+
[DATA_MODEL_TYPE]: (entry) => /* @__PURE__ */ jsx38(DataModelBlock, { entry })
|
|
1915
1993
|
};
|
|
1916
1994
|
|
|
1917
1995
|
// src/context/ReportRoot.tsx
|
|
1918
|
-
import { jsx as
|
|
1996
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
1919
1997
|
var EMPTY_RENDERERS2 = {};
|
|
1920
1998
|
function ReportRoot({
|
|
1921
1999
|
report,
|
|
@@ -1923,7 +2001,7 @@ function ReportRoot({
|
|
|
1923
2001
|
renderers,
|
|
1924
2002
|
children
|
|
1925
2003
|
}) {
|
|
1926
|
-
const value =
|
|
2004
|
+
const value = useMemo2(
|
|
1927
2005
|
() => ({
|
|
1928
2006
|
report,
|
|
1929
2007
|
// Narrative blocks render everywhere the report does (static SSR, the
|
|
@@ -1934,7 +2012,7 @@ function ReportRoot({
|
|
|
1934
2012
|
}),
|
|
1935
2013
|
[report, customRenderers, renderers]
|
|
1936
2014
|
);
|
|
1937
|
-
return /* @__PURE__ */
|
|
2015
|
+
return /* @__PURE__ */ jsx39(ReportContext.Provider, { value, children });
|
|
1938
2016
|
}
|
|
1939
2017
|
|
|
1940
2018
|
// src/lib/hash-state.ts
|
|
@@ -2120,7 +2198,7 @@ function listFailures(report) {
|
|
|
2120
2198
|
|
|
2121
2199
|
// src/interactive/ReportAgentFilterNotice.tsx
|
|
2122
2200
|
import { Bot, X } from "lucide-react";
|
|
2123
|
-
import { Fragment as Fragment11, jsx as
|
|
2201
|
+
import { Fragment as Fragment11, jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2124
2202
|
function ReportAgentFilterNotice({
|
|
2125
2203
|
applied,
|
|
2126
2204
|
onReset,
|
|
@@ -2130,23 +2208,23 @@ function ReportAgentFilterNotice({
|
|
|
2130
2208
|
if (applied.search) terms.push(`matching \u201C${applied.search}\u201D`);
|
|
2131
2209
|
if (applied.status !== "all") terms.push(applied.status);
|
|
2132
2210
|
if (applied.tags.length > 0) terms.push(applied.tags.join(", "));
|
|
2133
|
-
return /* @__PURE__ */
|
|
2211
|
+
return /* @__PURE__ */ jsxs26(
|
|
2134
2212
|
"div",
|
|
2135
2213
|
{
|
|
2136
2214
|
role: "status",
|
|
2137
2215
|
"aria-live": "polite",
|
|
2138
2216
|
className: "flex flex-wrap items-center gap-x-3 gap-y-1 rounded-md border border-primary/40 bg-primary/5 px-3 py-2 text-sm",
|
|
2139
2217
|
children: [
|
|
2140
|
-
/* @__PURE__ */
|
|
2141
|
-
/* @__PURE__ */
|
|
2218
|
+
/* @__PURE__ */ jsx40(Bot, { "aria-hidden": true, className: "size-4 shrink-0 text-primary" }),
|
|
2219
|
+
/* @__PURE__ */ jsxs26("span", { className: "min-w-0 flex-1", children: [
|
|
2142
2220
|
"An agent filtered this report",
|
|
2143
|
-
terms.length > 0 ? /* @__PURE__ */
|
|
2221
|
+
terms.length > 0 ? /* @__PURE__ */ jsxs26(Fragment11, { children: [
|
|
2144
2222
|
" to ",
|
|
2145
2223
|
terms.join(" \xB7 ")
|
|
2146
2224
|
] }) : null,
|
|
2147
2225
|
" \u2014",
|
|
2148
2226
|
" ",
|
|
2149
|
-
/* @__PURE__ */
|
|
2227
|
+
/* @__PURE__ */ jsxs26("span", { className: "tabular-nums", children: [
|
|
2150
2228
|
applied.matched,
|
|
2151
2229
|
" of ",
|
|
2152
2230
|
applied.total,
|
|
@@ -2154,7 +2232,7 @@ function ReportAgentFilterNotice({
|
|
|
2154
2232
|
] }),
|
|
2155
2233
|
"."
|
|
2156
2234
|
] }),
|
|
2157
|
-
/* @__PURE__ */
|
|
2235
|
+
/* @__PURE__ */ jsx40(
|
|
2158
2236
|
"button",
|
|
2159
2237
|
{
|
|
2160
2238
|
type: "button",
|
|
@@ -2163,14 +2241,14 @@ function ReportAgentFilterNotice({
|
|
|
2163
2241
|
children: "Show all"
|
|
2164
2242
|
}
|
|
2165
2243
|
),
|
|
2166
|
-
/* @__PURE__ */
|
|
2244
|
+
/* @__PURE__ */ jsx40(
|
|
2167
2245
|
"button",
|
|
2168
2246
|
{
|
|
2169
2247
|
type: "button",
|
|
2170
2248
|
onClick: onDismiss,
|
|
2171
2249
|
"aria-label": "Dismiss",
|
|
2172
2250
|
className: "cursor-pointer rounded-md p-1 text-muted-foreground hover:text-foreground",
|
|
2173
|
-
children: /* @__PURE__ */
|
|
2251
|
+
children: /* @__PURE__ */ jsx40(X, { "aria-hidden": true, className: "size-4" })
|
|
2174
2252
|
}
|
|
2175
2253
|
)
|
|
2176
2254
|
]
|
|
@@ -2180,7 +2258,7 @@ function ReportAgentFilterNotice({
|
|
|
2180
2258
|
|
|
2181
2259
|
// src/interactive/ReportFailureBanner.tsx
|
|
2182
2260
|
import { useCallback as useCallback2 } from "react";
|
|
2183
|
-
import { jsx as
|
|
2261
|
+
import { jsx as jsx41, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2184
2262
|
function ReportFailureBanner({ failures, onCopyAll }) {
|
|
2185
2263
|
const first = failures[0];
|
|
2186
2264
|
const jumpToFirst = useCallback2(() => {
|
|
@@ -2188,7 +2266,7 @@ function ReportFailureBanner({ failures, onCopyAll }) {
|
|
|
2188
2266
|
scrollToScenarioId(first.scenarioId);
|
|
2189
2267
|
}, [first]);
|
|
2190
2268
|
if (failures.length === 0) return null;
|
|
2191
|
-
return /* @__PURE__ */
|
|
2269
|
+
return /* @__PURE__ */ jsxs27(
|
|
2192
2270
|
"div",
|
|
2193
2271
|
{
|
|
2194
2272
|
className: "es-failure-banner",
|
|
@@ -2196,13 +2274,13 @@ function ReportFailureBanner({ failures, onCopyAll }) {
|
|
|
2196
2274
|
"aria-live": "polite",
|
|
2197
2275
|
"aria-label": "Failure summary",
|
|
2198
2276
|
children: [
|
|
2199
|
-
/* @__PURE__ */
|
|
2200
|
-
/* @__PURE__ */
|
|
2277
|
+
/* @__PURE__ */ jsxs27("span", { className: "es-failure-banner-text", children: [
|
|
2278
|
+
/* @__PURE__ */ jsx41("strong", { children: failures.length }),
|
|
2201
2279
|
" ",
|
|
2202
2280
|
"failure",
|
|
2203
2281
|
failures.length === 1 ? "" : "s"
|
|
2204
2282
|
] }),
|
|
2205
|
-
/* @__PURE__ */
|
|
2283
|
+
/* @__PURE__ */ jsx41(
|
|
2206
2284
|
"button",
|
|
2207
2285
|
{
|
|
2208
2286
|
type: "button",
|
|
@@ -2212,7 +2290,7 @@ function ReportFailureBanner({ failures, onCopyAll }) {
|
|
|
2212
2290
|
children: "View first failure \u2193"
|
|
2213
2291
|
}
|
|
2214
2292
|
),
|
|
2215
|
-
onCopyAll ? /* @__PURE__ */
|
|
2293
|
+
onCopyAll ? /* @__PURE__ */ jsxs27(
|
|
2216
2294
|
"button",
|
|
2217
2295
|
{
|
|
2218
2296
|
type: "button",
|
|
@@ -2234,8 +2312,8 @@ function ReportFailureBanner({ failures, onCopyAll }) {
|
|
|
2234
2312
|
}
|
|
2235
2313
|
|
|
2236
2314
|
// src/interactive/ReportFilters.tsx
|
|
2237
|
-
import { useState as
|
|
2238
|
-
import { jsx as
|
|
2315
|
+
import { useState as useState4 } from "react";
|
|
2316
|
+
import { jsx as jsx42, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2239
2317
|
var TAG_LIMIT = 12;
|
|
2240
2318
|
function ReportFilters({
|
|
2241
2319
|
statuses,
|
|
@@ -2245,14 +2323,14 @@ function ReportFilters({
|
|
|
2245
2323
|
activeTags,
|
|
2246
2324
|
onToggleTag
|
|
2247
2325
|
}) {
|
|
2248
|
-
const [showAllTags, setShowAllTags] =
|
|
2326
|
+
const [showAllTags, setShowAllTags] = useState4(false);
|
|
2249
2327
|
if (statuses.length === 0 && tags.length === 0) return null;
|
|
2250
2328
|
const tagsCollapsed = tags.length > TAG_LIMIT && !showAllTags;
|
|
2251
2329
|
const visibleTags = tagsCollapsed ? tags.slice(0, TAG_LIMIT) : tags;
|
|
2252
|
-
return /* @__PURE__ */
|
|
2253
|
-
statuses.length > 0 ? /* @__PURE__ */
|
|
2330
|
+
return /* @__PURE__ */ jsxs28("div", { className: "flex flex-col gap-2", children: [
|
|
2331
|
+
statuses.length > 0 ? /* @__PURE__ */ jsx42("div", { role: "group", "aria-label": "Filter by status", className: "flex flex-wrap gap-1", children: statuses.map((opt) => {
|
|
2254
2332
|
const active = status === opt.key;
|
|
2255
|
-
return /* @__PURE__ */
|
|
2333
|
+
return /* @__PURE__ */ jsxs28(
|
|
2256
2334
|
"button",
|
|
2257
2335
|
{
|
|
2258
2336
|
type: "button",
|
|
@@ -2264,23 +2342,23 @@ function ReportFilters({
|
|
|
2264
2342
|
),
|
|
2265
2343
|
children: [
|
|
2266
2344
|
opt.label,
|
|
2267
|
-
/* @__PURE__ */
|
|
2345
|
+
/* @__PURE__ */ jsx42("span", { className: "ml-1 font-mono opacity-70", children: opt.count })
|
|
2268
2346
|
]
|
|
2269
2347
|
},
|
|
2270
2348
|
opt.key
|
|
2271
2349
|
);
|
|
2272
2350
|
}) }) : null,
|
|
2273
|
-
tags.length > 0 ? /* @__PURE__ */
|
|
2351
|
+
tags.length > 0 ? /* @__PURE__ */ jsxs28("ul", { "aria-label": "Filter by tag", className: "flex flex-wrap items-center gap-1.5", children: [
|
|
2274
2352
|
visibleTags.map((tag) => {
|
|
2275
2353
|
const active = activeTags.includes(tag);
|
|
2276
|
-
return /* @__PURE__ */
|
|
2354
|
+
return /* @__PURE__ */ jsx42("li", { children: /* @__PURE__ */ jsx42(
|
|
2277
2355
|
"button",
|
|
2278
2356
|
{
|
|
2279
2357
|
type: "button",
|
|
2280
2358
|
"aria-pressed": active,
|
|
2281
2359
|
onClick: () => onToggleTag(tag),
|
|
2282
2360
|
className: "cursor-pointer",
|
|
2283
|
-
children: /* @__PURE__ */
|
|
2361
|
+
children: /* @__PURE__ */ jsx42(
|
|
2284
2362
|
Badge,
|
|
2285
2363
|
{
|
|
2286
2364
|
variant: "tag",
|
|
@@ -2293,7 +2371,7 @@ function ReportFilters({
|
|
|
2293
2371
|
}
|
|
2294
2372
|
) }, tag);
|
|
2295
2373
|
}),
|
|
2296
|
-
tags.length > TAG_LIMIT ? /* @__PURE__ */
|
|
2374
|
+
tags.length > TAG_LIMIT ? /* @__PURE__ */ jsx42("li", { children: /* @__PURE__ */ jsx42(
|
|
2297
2375
|
"button",
|
|
2298
2376
|
{
|
|
2299
2377
|
type: "button",
|
|
@@ -2308,16 +2386,16 @@ function ReportFilters({
|
|
|
2308
2386
|
}
|
|
2309
2387
|
|
|
2310
2388
|
// src/interactive/ReportFreshness.tsx
|
|
2311
|
-
import { useEffect as
|
|
2312
|
-
import { Fragment as Fragment12, jsx as
|
|
2389
|
+
import { useEffect as useEffect3, useState as useState5 } from "react";
|
|
2390
|
+
import { Fragment as Fragment12, jsx as jsx43, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2313
2391
|
function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
2314
|
-
const [now, setNow] =
|
|
2315
|
-
|
|
2392
|
+
const [now, setNow] = useState5(nowMs);
|
|
2393
|
+
useEffect3(() => {
|
|
2316
2394
|
if (nowMs === void 0) setNow(Date.now());
|
|
2317
2395
|
}, [nowMs]);
|
|
2318
2396
|
if (lastRunMs === void 0 || now === void 0) return null;
|
|
2319
2397
|
const age = formatRelativeAge(lastRunMs, now);
|
|
2320
|
-
const runLink = ciUrl ? /* @__PURE__ */
|
|
2398
|
+
const runLink = ciUrl ? /* @__PURE__ */ jsx43(
|
|
2321
2399
|
"a",
|
|
2322
2400
|
{
|
|
2323
2401
|
href: ciUrl,
|
|
@@ -2328,9 +2406,9 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2328
2406
|
}
|
|
2329
2407
|
) : null;
|
|
2330
2408
|
if (isReportStale(lastRunMs, staleAfterDays, now)) {
|
|
2331
|
-
return /* @__PURE__ */
|
|
2332
|
-
/* @__PURE__ */
|
|
2333
|
-
/* @__PURE__ */
|
|
2409
|
+
return /* @__PURE__ */ jsxs29("div", { className: "es-stale-banner", role: "status", "aria-label": "Report freshness", children: [
|
|
2410
|
+
/* @__PURE__ */ jsxs29("span", { children: [
|
|
2411
|
+
/* @__PURE__ */ jsxs29("strong", { children: [
|
|
2334
2412
|
"Last verified ",
|
|
2335
2413
|
age,
|
|
2336
2414
|
"."
|
|
@@ -2340,10 +2418,10 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2340
2418
|
runLink
|
|
2341
2419
|
] });
|
|
2342
2420
|
}
|
|
2343
|
-
return /* @__PURE__ */
|
|
2421
|
+
return /* @__PURE__ */ jsxs29("p", { className: "es-freshness", "aria-label": "Report freshness", children: [
|
|
2344
2422
|
"Verified ",
|
|
2345
2423
|
age,
|
|
2346
|
-
runLink ? /* @__PURE__ */
|
|
2424
|
+
runLink ? /* @__PURE__ */ jsxs29(Fragment12, { children: [
|
|
2347
2425
|
" \xB7 ",
|
|
2348
2426
|
runLink
|
|
2349
2427
|
] }) : null
|
|
@@ -2351,15 +2429,15 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2351
2429
|
}
|
|
2352
2430
|
|
|
2353
2431
|
// src/interactive/ReportLastRunDelta.tsx
|
|
2354
|
-
import { Fragment as Fragment13, jsx as
|
|
2432
|
+
import { Fragment as Fragment13, jsx as jsx44, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2355
2433
|
var MAX_LINKS = 5;
|
|
2356
2434
|
function ScenarioLinks({ scenarios, tone }) {
|
|
2357
|
-
return /* @__PURE__ */
|
|
2358
|
-
scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */
|
|
2435
|
+
return /* @__PURE__ */ jsxs30(Fragment13, { children: [
|
|
2436
|
+
scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ jsxs30("span", { children: [
|
|
2359
2437
|
i > 0 ? ", " : "",
|
|
2360
|
-
/* @__PURE__ */
|
|
2438
|
+
/* @__PURE__ */ jsx44("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
|
|
2361
2439
|
] }, s.id)),
|
|
2362
|
-
scenarios.length > MAX_LINKS ? /* @__PURE__ */
|
|
2440
|
+
scenarios.length > MAX_LINKS ? /* @__PURE__ */ jsxs30("span", { children: [
|
|
2363
2441
|
" and ",
|
|
2364
2442
|
scenarios.length - MAX_LINKS,
|
|
2365
2443
|
" more"
|
|
@@ -2376,23 +2454,23 @@ function ReportLastRunDelta({
|
|
|
2376
2454
|
if (!delta) return null;
|
|
2377
2455
|
const { newlyFailing, newlyPassing, added } = delta;
|
|
2378
2456
|
if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) {
|
|
2379
|
-
return /* @__PURE__ */
|
|
2457
|
+
return /* @__PURE__ */ jsx44("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: "Since last run: no behavior changes." });
|
|
2380
2458
|
}
|
|
2381
|
-
return /* @__PURE__ */
|
|
2382
|
-
/* @__PURE__ */
|
|
2383
|
-
newlyFailing.length > 0 ? /* @__PURE__ */
|
|
2459
|
+
return /* @__PURE__ */ jsxs30("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: [
|
|
2460
|
+
/* @__PURE__ */ jsx44("span", { className: "font-medium text-foreground", children: "Since last run:" }),
|
|
2461
|
+
newlyFailing.length > 0 ? /* @__PURE__ */ jsxs30("span", { className: "ml-2 text-fail", children: [
|
|
2384
2462
|
newlyFailing.length,
|
|
2385
2463
|
" newly failing (",
|
|
2386
|
-
/* @__PURE__ */
|
|
2464
|
+
/* @__PURE__ */ jsx44(ScenarioLinks, { scenarios: newlyFailing, tone: "text-fail" }),
|
|
2387
2465
|
")"
|
|
2388
2466
|
] }) : null,
|
|
2389
|
-
newlyPassing.length > 0 ? /* @__PURE__ */
|
|
2467
|
+
newlyPassing.length > 0 ? /* @__PURE__ */ jsxs30("span", { className: "ml-2 text-pass", children: [
|
|
2390
2468
|
newlyPassing.length,
|
|
2391
2469
|
" fixed (",
|
|
2392
|
-
/* @__PURE__ */
|
|
2470
|
+
/* @__PURE__ */ jsx44(ScenarioLinks, { scenarios: newlyPassing, tone: "text-pass" }),
|
|
2393
2471
|
")"
|
|
2394
2472
|
] }) : null,
|
|
2395
|
-
added.length > 0 ? /* @__PURE__ */
|
|
2473
|
+
added.length > 0 ? /* @__PURE__ */ jsxs30("span", { className: "ml-2", children: [
|
|
2396
2474
|
added.length,
|
|
2397
2475
|
" new"
|
|
2398
2476
|
] }) : null
|
|
@@ -2408,9 +2486,9 @@ import { Search } from "lucide-react";
|
|
|
2408
2486
|
|
|
2409
2487
|
// src/components/ui/input.tsx
|
|
2410
2488
|
import "react";
|
|
2411
|
-
import { jsx as
|
|
2489
|
+
import { jsx as jsx45 } from "react/jsx-runtime";
|
|
2412
2490
|
function Input({ className, type, ...props }) {
|
|
2413
|
-
return /* @__PURE__ */
|
|
2491
|
+
return /* @__PURE__ */ jsx45(
|
|
2414
2492
|
"input",
|
|
2415
2493
|
{
|
|
2416
2494
|
type,
|
|
@@ -2427,7 +2505,7 @@ function Input({ className, type, ...props }) {
|
|
|
2427
2505
|
}
|
|
2428
2506
|
|
|
2429
2507
|
// src/interactive/ReportSearch.tsx
|
|
2430
|
-
import { jsx as
|
|
2508
|
+
import { jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2431
2509
|
var ReportSearch = forwardRef(
|
|
2432
2510
|
function ReportSearch2(props, ref) {
|
|
2433
2511
|
const {
|
|
@@ -2449,17 +2527,17 @@ var ReportSearch = forwardRef(
|
|
|
2449
2527
|
e.preventDefault();
|
|
2450
2528
|
}
|
|
2451
2529
|
}
|
|
2452
|
-
return /* @__PURE__ */
|
|
2453
|
-
/* @__PURE__ */
|
|
2454
|
-
/* @__PURE__ */
|
|
2455
|
-
/* @__PURE__ */
|
|
2530
|
+
return /* @__PURE__ */ jsxs31("div", { className: cn("es-search flex flex-col gap-1", className), children: [
|
|
2531
|
+
/* @__PURE__ */ jsx46("label", { htmlFor: inputId, className: "sr-only", children: "Search" }),
|
|
2532
|
+
/* @__PURE__ */ jsxs31("div", { className: "relative w-full sm:w-72", children: [
|
|
2533
|
+
/* @__PURE__ */ jsx46(
|
|
2456
2534
|
Search,
|
|
2457
2535
|
{
|
|
2458
2536
|
"aria-hidden": true,
|
|
2459
2537
|
className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
|
|
2460
2538
|
}
|
|
2461
2539
|
),
|
|
2462
|
-
/* @__PURE__ */
|
|
2540
|
+
/* @__PURE__ */ jsx46(
|
|
2463
2541
|
Input,
|
|
2464
2542
|
{
|
|
2465
2543
|
ref,
|
|
@@ -2476,7 +2554,7 @@ var ReportSearch = forwardRef(
|
|
|
2476
2554
|
}
|
|
2477
2555
|
)
|
|
2478
2556
|
] }),
|
|
2479
|
-
showCounts ? /* @__PURE__ */
|
|
2557
|
+
showCounts ? /* @__PURE__ */ jsxs31(
|
|
2480
2558
|
"span",
|
|
2481
2559
|
{
|
|
2482
2560
|
className: "text-xs tabular-nums text-muted-foreground",
|
|
@@ -2493,8 +2571,138 @@ var ReportSearch = forwardRef(
|
|
|
2493
2571
|
}
|
|
2494
2572
|
);
|
|
2495
2573
|
|
|
2574
|
+
// src/interactive/ReportShare.tsx
|
|
2575
|
+
import { Share2 } from "lucide-react";
|
|
2576
|
+
import { useEffect as useEffect4, useRef as useRef2, useState as useState6 } from "react";
|
|
2577
|
+
|
|
2578
|
+
// src/components/ui/button.tsx
|
|
2579
|
+
import "react";
|
|
2580
|
+
import { cva as cva4 } from "class-variance-authority";
|
|
2581
|
+
import { useRender as useRender2 } from "@base-ui/react/use-render";
|
|
2582
|
+
var buttonVariants = cva4(
|
|
2583
|
+
"inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,background-color,border-color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
2584
|
+
{
|
|
2585
|
+
variants: {
|
|
2586
|
+
variant: {
|
|
2587
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
2588
|
+
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
|
|
2589
|
+
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
2590
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
2591
|
+
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
2592
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
2593
|
+
},
|
|
2594
|
+
size: {
|
|
2595
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
2596
|
+
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
2597
|
+
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
|
|
2598
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
2599
|
+
icon: "size-9",
|
|
2600
|
+
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
2601
|
+
"icon-sm": "size-8",
|
|
2602
|
+
"icon-lg": "size-10"
|
|
2603
|
+
}
|
|
2604
|
+
},
|
|
2605
|
+
defaultVariants: {
|
|
2606
|
+
variant: "default",
|
|
2607
|
+
size: "default"
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
);
|
|
2611
|
+
function Button({
|
|
2612
|
+
className,
|
|
2613
|
+
variant = "default",
|
|
2614
|
+
size = "default",
|
|
2615
|
+
render,
|
|
2616
|
+
...props
|
|
2617
|
+
}) {
|
|
2618
|
+
return useRender2({
|
|
2619
|
+
defaultTagName: "button",
|
|
2620
|
+
render,
|
|
2621
|
+
props: {
|
|
2622
|
+
"data-slot": "button",
|
|
2623
|
+
"data-variant": variant,
|
|
2624
|
+
"data-size": size,
|
|
2625
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
2626
|
+
...props
|
|
2627
|
+
}
|
|
2628
|
+
});
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
// src/interactive/ReportShare.tsx
|
|
2632
|
+
import { Fragment as Fragment14, jsx as jsx47, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2633
|
+
var DEFAULT_SHARE_COMMAND = "npx executable-stories share reports/";
|
|
2634
|
+
function ReportShare({
|
|
2635
|
+
command = DEFAULT_SHARE_COMMAND,
|
|
2636
|
+
onCopy
|
|
2637
|
+
}) {
|
|
2638
|
+
const [open, setOpen] = useState6(false);
|
|
2639
|
+
const dialogRef = useRef2(null);
|
|
2640
|
+
useEffect4(() => {
|
|
2641
|
+
const dialog = dialogRef.current;
|
|
2642
|
+
if (!dialog) return;
|
|
2643
|
+
if (open && !dialog.open) dialog.showModal();
|
|
2644
|
+
else if (!open && dialog.open) dialog.close();
|
|
2645
|
+
}, [open]);
|
|
2646
|
+
return /* @__PURE__ */ jsxs32(Fragment14, { children: [
|
|
2647
|
+
/* @__PURE__ */ jsxs32(
|
|
2648
|
+
Button,
|
|
2649
|
+
{
|
|
2650
|
+
type: "button",
|
|
2651
|
+
variant: "ghost",
|
|
2652
|
+
size: "sm",
|
|
2653
|
+
"aria-label": "Share this report",
|
|
2654
|
+
title: "Share this report",
|
|
2655
|
+
onClick: () => setOpen(true),
|
|
2656
|
+
children: [
|
|
2657
|
+
/* @__PURE__ */ jsx47(Share2, { "aria-hidden": "true", className: "size-4" }),
|
|
2658
|
+
/* @__PURE__ */ jsx47("span", { className: "sr-only sm:not-sr-only", children: "Share" })
|
|
2659
|
+
]
|
|
2660
|
+
}
|
|
2661
|
+
),
|
|
2662
|
+
/* @__PURE__ */ jsxs32(
|
|
2663
|
+
"dialog",
|
|
2664
|
+
{
|
|
2665
|
+
ref: dialogRef,
|
|
2666
|
+
className: "es-report-share m-auto w-[min(90vw,32rem)] rounded-lg border border-border bg-card p-6 text-card-foreground shadow-lg [overscroll-behavior:contain] backdrop:bg-black/40",
|
|
2667
|
+
"aria-label": "Share this report",
|
|
2668
|
+
onClose: () => setOpen(false),
|
|
2669
|
+
children: [
|
|
2670
|
+
/* @__PURE__ */ jsx47("h2", { className: "text-base font-semibold", children: "Share this report" }),
|
|
2671
|
+
/* @__PURE__ */ jsx47("p", { className: "mt-2 text-sm text-muted-foreground", children: "Publish it to Executable Stories Cloud and send a link. Screenshots and videos go with it. Run this from your project:" }),
|
|
2672
|
+
/* @__PURE__ */ jsxs32("div", { className: "mt-4 flex items-center gap-2", children: [
|
|
2673
|
+
/* @__PURE__ */ jsx47("code", { className: "min-w-0 flex-1 truncate rounded border border-border bg-muted px-3 py-2 font-mono text-xs", children: command }),
|
|
2674
|
+
/* @__PURE__ */ jsx47(
|
|
2675
|
+
Button,
|
|
2676
|
+
{
|
|
2677
|
+
type: "button",
|
|
2678
|
+
size: "sm",
|
|
2679
|
+
onClick: () => onCopy(command, "Command copied"),
|
|
2680
|
+
children: "Copy"
|
|
2681
|
+
}
|
|
2682
|
+
)
|
|
2683
|
+
] }),
|
|
2684
|
+
/* @__PURE__ */ jsx47("p", { className: "mt-3 text-xs text-muted-foreground", children: "The file you are reading cannot upload itself, so the command does it: only the CLI can read the assets this report links to." }),
|
|
2685
|
+
/* @__PURE__ */ jsxs32("div", { className: "mt-6 flex items-center justify-between gap-4", children: [
|
|
2686
|
+
/* @__PURE__ */ jsx47(
|
|
2687
|
+
"a",
|
|
2688
|
+
{
|
|
2689
|
+
className: "text-xs underline underline-offset-2",
|
|
2690
|
+
href: "https://executablestories.com/guides/sharing-reports/",
|
|
2691
|
+
target: "_blank",
|
|
2692
|
+
rel: "noreferrer",
|
|
2693
|
+
children: "How sharing works"
|
|
2694
|
+
}
|
|
2695
|
+
),
|
|
2696
|
+
/* @__PURE__ */ jsx47(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setOpen(false), children: "Close" })
|
|
2697
|
+
] })
|
|
2698
|
+
]
|
|
2699
|
+
}
|
|
2700
|
+
)
|
|
2701
|
+
] });
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2496
2704
|
// src/interactive/ReportSinceLastVisit.tsx
|
|
2497
|
-
import { useEffect as
|
|
2705
|
+
import { useEffect as useEffect5, useState as useState7 } from "react";
|
|
2498
2706
|
|
|
2499
2707
|
// src/interactive/last-visit.ts
|
|
2500
2708
|
function snapshotOf(report, atMs) {
|
|
@@ -2530,7 +2738,7 @@ function diffSinceVisit(previous, report) {
|
|
|
2530
2738
|
}
|
|
2531
2739
|
|
|
2532
2740
|
// src/interactive/ReportSinceLastVisit.tsx
|
|
2533
|
-
import { Fragment as
|
|
2741
|
+
import { Fragment as Fragment15, jsx as jsx48, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2534
2742
|
var KEY = "es-last-visit";
|
|
2535
2743
|
var MAX_LINKS2 = 5;
|
|
2536
2744
|
function readVisit() {
|
|
@@ -2555,12 +2763,12 @@ function writeVisit(snapshot) {
|
|
|
2555
2763
|
}
|
|
2556
2764
|
}
|
|
2557
2765
|
function ScenarioLinks2({ scenarios, tone }) {
|
|
2558
|
-
return /* @__PURE__ */
|
|
2559
|
-
scenarios.slice(0, MAX_LINKS2).map((s, i) => /* @__PURE__ */
|
|
2766
|
+
return /* @__PURE__ */ jsxs33(Fragment15, { children: [
|
|
2767
|
+
scenarios.slice(0, MAX_LINKS2).map((s, i) => /* @__PURE__ */ jsxs33("span", { children: [
|
|
2560
2768
|
i > 0 ? ", " : "",
|
|
2561
|
-
/* @__PURE__ */
|
|
2769
|
+
/* @__PURE__ */ jsx48("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
|
|
2562
2770
|
] }, s.id)),
|
|
2563
|
-
scenarios.length > MAX_LINKS2 ? /* @__PURE__ */
|
|
2771
|
+
scenarios.length > MAX_LINKS2 ? /* @__PURE__ */ jsxs33("span", { children: [
|
|
2564
2772
|
" and ",
|
|
2565
2773
|
scenarios.length - MAX_LINKS2,
|
|
2566
2774
|
" more"
|
|
@@ -2568,9 +2776,9 @@ function ScenarioLinks2({ scenarios, tone }) {
|
|
|
2568
2776
|
] });
|
|
2569
2777
|
}
|
|
2570
2778
|
function ReportSinceLastVisit({ report }) {
|
|
2571
|
-
const [delta, setDelta] =
|
|
2572
|
-
const [nowMs, setNowMs] =
|
|
2573
|
-
|
|
2779
|
+
const [delta, setDelta] = useState7(null);
|
|
2780
|
+
const [nowMs, setNowMs] = useState7(0);
|
|
2781
|
+
useEffect5(() => {
|
|
2574
2782
|
const now = Date.now();
|
|
2575
2783
|
setDelta(diffSinceVisit(readVisit(), report));
|
|
2576
2784
|
setNowMs(now);
|
|
@@ -2578,25 +2786,25 @@ function ReportSinceLastVisit({ report }) {
|
|
|
2578
2786
|
}, [report]);
|
|
2579
2787
|
if (!delta) return null;
|
|
2580
2788
|
const { newlyFailing, newlyPassing, added } = delta;
|
|
2581
|
-
return /* @__PURE__ */
|
|
2582
|
-
/* @__PURE__ */
|
|
2789
|
+
return /* @__PURE__ */ jsxs33("p", { className: "text-xs text-muted-foreground", "data-testid": "es-since-last-visit", children: [
|
|
2790
|
+
/* @__PURE__ */ jsxs33("span", { className: "font-medium text-foreground", children: [
|
|
2583
2791
|
"Since your last visit (",
|
|
2584
2792
|
formatRelativeAge(delta.sinceMs, nowMs),
|
|
2585
2793
|
"):"
|
|
2586
2794
|
] }),
|
|
2587
|
-
newlyFailing.length > 0 ? /* @__PURE__ */
|
|
2795
|
+
newlyFailing.length > 0 ? /* @__PURE__ */ jsxs33("span", { className: "ml-2 text-fail", children: [
|
|
2588
2796
|
newlyFailing.length,
|
|
2589
2797
|
" started failing (",
|
|
2590
|
-
/* @__PURE__ */
|
|
2798
|
+
/* @__PURE__ */ jsx48(ScenarioLinks2, { scenarios: newlyFailing, tone: "text-fail" }),
|
|
2591
2799
|
")"
|
|
2592
2800
|
] }) : null,
|
|
2593
|
-
newlyPassing.length > 0 ? /* @__PURE__ */
|
|
2801
|
+
newlyPassing.length > 0 ? /* @__PURE__ */ jsxs33("span", { className: "ml-2 text-pass", children: [
|
|
2594
2802
|
newlyPassing.length,
|
|
2595
2803
|
" fixed (",
|
|
2596
|
-
/* @__PURE__ */
|
|
2804
|
+
/* @__PURE__ */ jsx48(ScenarioLinks2, { scenarios: newlyPassing, tone: "text-pass" }),
|
|
2597
2805
|
")"
|
|
2598
2806
|
] }) : null,
|
|
2599
|
-
added.length > 0 ? /* @__PURE__ */
|
|
2807
|
+
added.length > 0 ? /* @__PURE__ */ jsxs33("span", { className: "ml-2", children: [
|
|
2600
2808
|
added.length,
|
|
2601
2809
|
" new"
|
|
2602
2810
|
] }) : null
|
|
@@ -2604,63 +2812,8 @@ function ReportSinceLastVisit({ report }) {
|
|
|
2604
2812
|
}
|
|
2605
2813
|
|
|
2606
2814
|
// src/interactive/ReportShortcutsHelp.tsx
|
|
2607
|
-
import { useEffect as
|
|
2608
|
-
|
|
2609
|
-
// src/components/ui/button.tsx
|
|
2610
|
-
import "react";
|
|
2611
|
-
import { cva as cva4 } from "class-variance-authority";
|
|
2612
|
-
import { useRender as useRender2 } from "@base-ui/react/use-render";
|
|
2613
|
-
var buttonVariants = cva4(
|
|
2614
|
-
"inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,background-color,border-color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
2615
|
-
{
|
|
2616
|
-
variants: {
|
|
2617
|
-
variant: {
|
|
2618
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
2619
|
-
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
|
|
2620
|
-
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
2621
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
2622
|
-
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
2623
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
2624
|
-
},
|
|
2625
|
-
size: {
|
|
2626
|
-
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
2627
|
-
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
2628
|
-
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
|
|
2629
|
-
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
2630
|
-
icon: "size-9",
|
|
2631
|
-
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
2632
|
-
"icon-sm": "size-8",
|
|
2633
|
-
"icon-lg": "size-10"
|
|
2634
|
-
}
|
|
2635
|
-
},
|
|
2636
|
-
defaultVariants: {
|
|
2637
|
-
variant: "default",
|
|
2638
|
-
size: "default"
|
|
2639
|
-
}
|
|
2640
|
-
}
|
|
2641
|
-
);
|
|
2642
|
-
function Button({
|
|
2643
|
-
className,
|
|
2644
|
-
variant = "default",
|
|
2645
|
-
size = "default",
|
|
2646
|
-
render,
|
|
2647
|
-
...props
|
|
2648
|
-
}) {
|
|
2649
|
-
return useRender2({
|
|
2650
|
-
defaultTagName: "button",
|
|
2651
|
-
render,
|
|
2652
|
-
props: {
|
|
2653
|
-
"data-slot": "button",
|
|
2654
|
-
"data-variant": variant,
|
|
2655
|
-
"data-size": size,
|
|
2656
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
2657
|
-
...props
|
|
2658
|
-
}
|
|
2659
|
-
});
|
|
2660
|
-
}
|
|
2661
|
-
|
|
2662
|
-
// src/interactive/ReportShortcutsHelp.tsx
|
|
2663
|
-
import { jsx as jsx47, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2815
|
+
import { useEffect as useEffect6, useRef as useRef3 } from "react";
|
|
2816
|
+
import { jsx as jsx49, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2664
2817
|
var SHORTCUTS = [
|
|
2665
2818
|
{ keys: "/", description: "Focus search" },
|
|
2666
2819
|
{ keys: "f", description: "Jump to next failure" },
|
|
@@ -2672,20 +2825,20 @@ var SHORTCUTS = [
|
|
|
2672
2825
|
];
|
|
2673
2826
|
function Keys({ keys }) {
|
|
2674
2827
|
const parts = keys.split(" ");
|
|
2675
|
-
return /* @__PURE__ */
|
|
2676
|
-
i > 0 ? /* @__PURE__ */
|
|
2677
|
-
/* @__PURE__ */
|
|
2828
|
+
return /* @__PURE__ */ jsx49("span", { className: "inline-flex items-center gap-1", children: parts.map((k, i) => /* @__PURE__ */ jsxs34("span", { className: "inline-flex items-center gap-1", children: [
|
|
2829
|
+
i > 0 ? /* @__PURE__ */ jsx49("span", { className: "text-xs text-muted-foreground", children: "+" }) : null,
|
|
2830
|
+
/* @__PURE__ */ jsx49("kbd", { className: "inline-flex h-6 min-w-6 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-xs font-medium text-muted-foreground", children: k })
|
|
2678
2831
|
] }, k)) });
|
|
2679
2832
|
}
|
|
2680
2833
|
function ReportShortcutsHelp({ open, onClose }) {
|
|
2681
|
-
const dialogRef =
|
|
2682
|
-
|
|
2834
|
+
const dialogRef = useRef3(null);
|
|
2835
|
+
useEffect6(() => {
|
|
2683
2836
|
const dialog = dialogRef.current;
|
|
2684
2837
|
if (!dialog) return;
|
|
2685
2838
|
if (open && !dialog.open) dialog.showModal();
|
|
2686
2839
|
else if (!open && dialog.open) dialog.close();
|
|
2687
2840
|
}, [open]);
|
|
2688
|
-
return /* @__PURE__ */
|
|
2841
|
+
return /* @__PURE__ */ jsxs34(
|
|
2689
2842
|
"dialog",
|
|
2690
2843
|
{
|
|
2691
2844
|
ref: dialogRef,
|
|
@@ -2693,20 +2846,20 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2693
2846
|
"aria-label": "Keyboard shortcuts",
|
|
2694
2847
|
onClose,
|
|
2695
2848
|
children: [
|
|
2696
|
-
/* @__PURE__ */
|
|
2697
|
-
/* @__PURE__ */
|
|
2698
|
-
/* @__PURE__ */
|
|
2699
|
-
/* @__PURE__ */
|
|
2849
|
+
/* @__PURE__ */ jsx49("h2", { className: "text-base font-semibold", children: "Keyboard shortcuts" }),
|
|
2850
|
+
/* @__PURE__ */ jsx49("dl", { className: "mt-4 grid grid-cols-[auto_1fr] items-center gap-x-4 gap-y-2.5", children: SHORTCUTS.map((s) => /* @__PURE__ */ jsxs34("div", { className: "col-span-2 grid grid-cols-subgrid items-center", children: [
|
|
2851
|
+
/* @__PURE__ */ jsx49("dt", { className: "justify-self-start", children: /* @__PURE__ */ jsx49(Keys, { keys: s.keys }) }),
|
|
2852
|
+
/* @__PURE__ */ jsx49("dd", { className: "text-sm text-muted-foreground", children: s.description })
|
|
2700
2853
|
] }, s.keys)) }),
|
|
2701
|
-
/* @__PURE__ */
|
|
2854
|
+
/* @__PURE__ */ jsx49("form", { method: "dialog", className: "mt-6", children: /* @__PURE__ */ jsx49(Button, { type: "submit", variant: "outline", size: "sm", children: "Close" }) })
|
|
2702
2855
|
]
|
|
2703
2856
|
}
|
|
2704
2857
|
);
|
|
2705
2858
|
}
|
|
2706
2859
|
|
|
2707
2860
|
// src/interactive/ReportToc.tsx
|
|
2708
|
-
import { useEffect as
|
|
2709
|
-
import { jsx as
|
|
2861
|
+
import { useEffect as useEffect7, useMemo as useMemo3, useState as useState8 } from "react";
|
|
2862
|
+
import { jsx as jsx50, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2710
2863
|
var DOT = {
|
|
2711
2864
|
passed: "bg-pass",
|
|
2712
2865
|
failed: "bg-fail",
|
|
@@ -2715,12 +2868,12 @@ var DOT = {
|
|
|
2715
2868
|
};
|
|
2716
2869
|
function TocContent({ onNavigate }) {
|
|
2717
2870
|
const report = useReport();
|
|
2718
|
-
const [activeId, setActiveId] =
|
|
2719
|
-
const scenarioIds =
|
|
2871
|
+
const [activeId, setActiveId] = useState8(null);
|
|
2872
|
+
const scenarioIds = useMemo3(
|
|
2720
2873
|
() => report.features.flatMap((f) => f.scenarios.map((s) => s.id)),
|
|
2721
2874
|
[report]
|
|
2722
2875
|
);
|
|
2723
|
-
|
|
2876
|
+
useEffect7(() => {
|
|
2724
2877
|
if (typeof IntersectionObserver === "undefined") return;
|
|
2725
2878
|
const els = scenarioIds.map((id) => document.getElementById(id)).filter((el) => el !== null);
|
|
2726
2879
|
if (els.length === 0) return;
|
|
@@ -2735,11 +2888,11 @@ function TocContent({ onNavigate }) {
|
|
|
2735
2888
|
return () => observer.disconnect();
|
|
2736
2889
|
}, [scenarioIds]);
|
|
2737
2890
|
if (report.features.length === 0) return null;
|
|
2738
|
-
return /* @__PURE__ */
|
|
2739
|
-
/* @__PURE__ */
|
|
2740
|
-
/* @__PURE__ */
|
|
2891
|
+
return /* @__PURE__ */ jsx50("ul", { className: "flex list-none flex-col gap-4 pl-0", children: report.features.map((feature) => /* @__PURE__ */ jsxs35("li", { children: [
|
|
2892
|
+
/* @__PURE__ */ jsx50("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
|
|
2893
|
+
/* @__PURE__ */ jsx50("ul", { className: "flex list-none flex-col gap-0.5 pl-0", children: feature.scenarios.map((scenario) => {
|
|
2741
2894
|
const active = activeId === scenario.id;
|
|
2742
|
-
return /* @__PURE__ */
|
|
2895
|
+
return /* @__PURE__ */ jsx50("li", { children: /* @__PURE__ */ jsxs35(
|
|
2743
2896
|
"a",
|
|
2744
2897
|
{
|
|
2745
2898
|
href: `#${scenario.id}`,
|
|
@@ -2754,14 +2907,14 @@ function TocContent({ onNavigate }) {
|
|
|
2754
2907
|
active ? "border-primary font-medium text-foreground" : "border-border text-muted-foreground"
|
|
2755
2908
|
),
|
|
2756
2909
|
children: [
|
|
2757
|
-
/* @__PURE__ */
|
|
2910
|
+
/* @__PURE__ */ jsx50(
|
|
2758
2911
|
"span",
|
|
2759
2912
|
{
|
|
2760
2913
|
"aria-hidden": true,
|
|
2761
2914
|
className: cn("mt-1 size-1.5 shrink-0 rounded-full", DOT[scenario.status])
|
|
2762
2915
|
}
|
|
2763
2916
|
),
|
|
2764
|
-
/* @__PURE__ */
|
|
2917
|
+
/* @__PURE__ */ jsx50("span", { className: "break-words", children: scenario.title })
|
|
2765
2918
|
]
|
|
2766
2919
|
}
|
|
2767
2920
|
) }, scenario.id);
|
|
@@ -2771,48 +2924,48 @@ function TocContent({ onNavigate }) {
|
|
|
2771
2924
|
function ReportToc() {
|
|
2772
2925
|
const report = useReport();
|
|
2773
2926
|
if (report.features.length === 0) return null;
|
|
2774
|
-
return /* @__PURE__ */
|
|
2927
|
+
return /* @__PURE__ */ jsxs35(
|
|
2775
2928
|
"nav",
|
|
2776
2929
|
{
|
|
2777
2930
|
"aria-label": "Table of contents",
|
|
2778
2931
|
className: "sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block",
|
|
2779
2932
|
children: [
|
|
2780
|
-
/* @__PURE__ */
|
|
2781
|
-
/* @__PURE__ */
|
|
2933
|
+
/* @__PURE__ */ jsx50("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
|
|
2934
|
+
/* @__PURE__ */ jsx50(TocContent, {})
|
|
2782
2935
|
]
|
|
2783
2936
|
}
|
|
2784
2937
|
);
|
|
2785
2938
|
}
|
|
2786
2939
|
|
|
2787
2940
|
// src/interactive/ReportTocDrawer.tsx
|
|
2788
|
-
import { useState as
|
|
2941
|
+
import { useState as useState9 } from "react";
|
|
2789
2942
|
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
|
|
2790
2943
|
import { ListIcon, XIcon } from "lucide-react";
|
|
2791
|
-
import { jsx as
|
|
2944
|
+
import { jsx as jsx51, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2792
2945
|
function ReportTocDrawer() {
|
|
2793
2946
|
const report = useReport();
|
|
2794
|
-
const [open, setOpen] =
|
|
2947
|
+
const [open, setOpen] = useState9(false);
|
|
2795
2948
|
if (report.features.length === 0) return null;
|
|
2796
|
-
return /* @__PURE__ */
|
|
2797
|
-
/* @__PURE__ */
|
|
2798
|
-
/* @__PURE__ */
|
|
2949
|
+
return /* @__PURE__ */ jsxs36(DialogPrimitive.Root, { open, onOpenChange: setOpen, children: [
|
|
2950
|
+
/* @__PURE__ */ jsxs36(DialogPrimitive.Trigger, { className: "flex cursor-pointer items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground lg:hidden [&_svg]:size-3.5", children: [
|
|
2951
|
+
/* @__PURE__ */ jsx51(ListIcon, { "aria-hidden": true }),
|
|
2799
2952
|
" Contents"
|
|
2800
2953
|
] }),
|
|
2801
|
-
/* @__PURE__ */
|
|
2802
|
-
/* @__PURE__ */
|
|
2803
|
-
/* @__PURE__ */
|
|
2804
|
-
/* @__PURE__ */
|
|
2805
|
-
/* @__PURE__ */
|
|
2806
|
-
/* @__PURE__ */
|
|
2954
|
+
/* @__PURE__ */ jsxs36(DialogPrimitive.Portal, { children: [
|
|
2955
|
+
/* @__PURE__ */ jsx51(DialogPrimitive.Backdrop, { className: "fixed inset-0 z-50 bg-black/50 transition-opacity duration-200 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0" }),
|
|
2956
|
+
/* @__PURE__ */ jsxs36(DialogPrimitive.Popup, { className: "fixed inset-y-0 left-0 z-50 flex w-72 max-w-[80vw] flex-col gap-3 overflow-y-auto border-r border-border bg-background p-4 font-sans text-xs shadow-lg outline-none transition-transform duration-200 data-[ending-style]:-translate-x-full data-[starting-style]:-translate-x-full", children: [
|
|
2957
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between", children: [
|
|
2958
|
+
/* @__PURE__ */ jsx51(DialogPrimitive.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
|
|
2959
|
+
/* @__PURE__ */ jsx51(
|
|
2807
2960
|
DialogPrimitive.Close,
|
|
2808
2961
|
{
|
|
2809
2962
|
"aria-label": "Close contents",
|
|
2810
2963
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
2811
|
-
children: /* @__PURE__ */
|
|
2964
|
+
children: /* @__PURE__ */ jsx51(XIcon, { "aria-hidden": true })
|
|
2812
2965
|
}
|
|
2813
2966
|
)
|
|
2814
2967
|
] }),
|
|
2815
|
-
/* @__PURE__ */
|
|
2968
|
+
/* @__PURE__ */ jsx51(TocContent, { onNavigate: () => setOpen(false) })
|
|
2816
2969
|
] })
|
|
2817
2970
|
] })
|
|
2818
2971
|
] });
|
|
@@ -2846,10 +2999,10 @@ function failuresFirst(report) {
|
|
|
2846
2999
|
}
|
|
2847
3000
|
|
|
2848
3001
|
// src/interactive/use-deep-link-scroll.ts
|
|
2849
|
-
import { useEffect as
|
|
3002
|
+
import { useEffect as useEffect8, useRef as useRef4 } from "react";
|
|
2850
3003
|
function useDeepLinkScroll() {
|
|
2851
|
-
const lastAnchor =
|
|
2852
|
-
|
|
3004
|
+
const lastAnchor = useRef4(null);
|
|
3005
|
+
useEffect8(() => {
|
|
2853
3006
|
function scrollToHash() {
|
|
2854
3007
|
const { anchor } = splitHash(window.location.hash);
|
|
2855
3008
|
if (!anchor || anchor === lastAnchor.current) return;
|
|
@@ -2865,7 +3018,7 @@ function useDeepLinkScroll() {
|
|
|
2865
3018
|
}
|
|
2866
3019
|
|
|
2867
3020
|
// src/interactive/use-keyboard-shortcuts.ts
|
|
2868
|
-
import { useEffect as
|
|
3021
|
+
import { useEffect as useEffect9, useRef as useRef5 } from "react";
|
|
2869
3022
|
function isEditableTarget(target) {
|
|
2870
3023
|
if (!(target instanceof HTMLElement)) return false;
|
|
2871
3024
|
const tag = target.tagName;
|
|
@@ -2874,9 +3027,9 @@ function isEditableTarget(target) {
|
|
|
2874
3027
|
return false;
|
|
2875
3028
|
}
|
|
2876
3029
|
function useKeyboardShortcuts(handlers) {
|
|
2877
|
-
const ref =
|
|
3030
|
+
const ref = useRef5(handlers);
|
|
2878
3031
|
ref.current = handlers;
|
|
2879
|
-
|
|
3032
|
+
useEffect9(() => {
|
|
2880
3033
|
function onKeyDown(e) {
|
|
2881
3034
|
const h = ref.current;
|
|
2882
3035
|
if (e.key === "Escape") {
|
|
@@ -2920,7 +3073,7 @@ function useKeyboardShortcuts(handlers) {
|
|
|
2920
3073
|
}
|
|
2921
3074
|
|
|
2922
3075
|
// src/interactive/use-theme.ts
|
|
2923
|
-
import { useCallback as useCallback3, useEffect as
|
|
3076
|
+
import { useCallback as useCallback3, useEffect as useEffect10, useState as useState10 } from "react";
|
|
2924
3077
|
var KEY2 = "es-theme";
|
|
2925
3078
|
function systemDark() {
|
|
2926
3079
|
return typeof matchMedia !== "undefined" && matchMedia("(prefers-color-scheme: dark)").matches;
|
|
@@ -2941,13 +3094,13 @@ function initialPref() {
|
|
|
2941
3094
|
return "system";
|
|
2942
3095
|
}
|
|
2943
3096
|
function useTheme() {
|
|
2944
|
-
const [pref, setPrefState] =
|
|
2945
|
-
|
|
3097
|
+
const [pref, setPrefState] = useState10("system");
|
|
3098
|
+
useEffect10(() => {
|
|
2946
3099
|
const p = initialPref();
|
|
2947
3100
|
setPrefState(p);
|
|
2948
3101
|
applyTheme(p);
|
|
2949
3102
|
}, []);
|
|
2950
|
-
|
|
3103
|
+
useEffect10(() => {
|
|
2951
3104
|
if (typeof matchMedia === "undefined") return;
|
|
2952
3105
|
const mq = matchMedia("(prefers-color-scheme: dark)");
|
|
2953
3106
|
const onChange = () => {
|
|
@@ -2968,19 +3121,19 @@ function useTheme() {
|
|
|
2968
3121
|
}
|
|
2969
3122
|
|
|
2970
3123
|
// src/interactive/use-url-state.ts
|
|
2971
|
-
import { useCallback as useCallback4, useEffect as
|
|
3124
|
+
import { useCallback as useCallback4, useEffect as useEffect11, useRef as useRef6, useState as useState11 } from "react";
|
|
2972
3125
|
var WRITE_DELAY_MS = 250;
|
|
2973
3126
|
function useUrlState() {
|
|
2974
|
-
const [state, setState] =
|
|
2975
|
-
const ready =
|
|
2976
|
-
|
|
3127
|
+
const [state, setState] = useState11(DEFAULT_URL_STATE);
|
|
3128
|
+
const ready = useRef6(false);
|
|
3129
|
+
useEffect11(() => {
|
|
2977
3130
|
const read = () => setState(decodeUrlState(splitHash(window.location.hash).params));
|
|
2978
3131
|
read();
|
|
2979
3132
|
ready.current = true;
|
|
2980
3133
|
window.addEventListener("hashchange", read);
|
|
2981
3134
|
return () => window.removeEventListener("hashchange", read);
|
|
2982
3135
|
}, []);
|
|
2983
|
-
|
|
3136
|
+
useEffect11(() => {
|
|
2984
3137
|
if (!ready.current) return;
|
|
2985
3138
|
const timer = setTimeout(
|
|
2986
3139
|
() => writeHash(splitHash(window.location.hash).anchor, encodeUrlState(state)),
|
|
@@ -3216,12 +3369,12 @@ function reportTools(deps) {
|
|
|
3216
3369
|
}
|
|
3217
3370
|
|
|
3218
3371
|
// src/interactive/ReportInteractive.tsx
|
|
3219
|
-
import { Fragment as
|
|
3372
|
+
import { Fragment as Fragment16, jsx as jsx52, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3220
3373
|
function ReportInteractive(props) {
|
|
3221
3374
|
const { report, className, title, dataTheme } = props;
|
|
3222
3375
|
const result = unwrapReport(report);
|
|
3223
3376
|
if (!result.ok) {
|
|
3224
|
-
return /* @__PURE__ */
|
|
3377
|
+
return /* @__PURE__ */ jsx52(
|
|
3225
3378
|
ReportErrorShell,
|
|
3226
3379
|
{
|
|
3227
3380
|
error: result.error,
|
|
@@ -3231,7 +3384,7 @@ function ReportInteractive(props) {
|
|
|
3231
3384
|
}
|
|
3232
3385
|
);
|
|
3233
3386
|
}
|
|
3234
|
-
return /* @__PURE__ */
|
|
3387
|
+
return /* @__PURE__ */ jsx52(ReportInteractiveView, { ...props, report: result.data });
|
|
3235
3388
|
}
|
|
3236
3389
|
var THEME_OPTIONS = [
|
|
3237
3390
|
{ value: "light", label: "Light", Icon: Sun },
|
|
@@ -3242,7 +3395,7 @@ function ThemeSegment({
|
|
|
3242
3395
|
pref,
|
|
3243
3396
|
onPref
|
|
3244
3397
|
}) {
|
|
3245
|
-
return /* @__PURE__ */
|
|
3398
|
+
return /* @__PURE__ */ jsx52(
|
|
3246
3399
|
ToggleGroup,
|
|
3247
3400
|
{
|
|
3248
3401
|
size: "sm",
|
|
@@ -3252,14 +3405,14 @@ function ThemeSegment({
|
|
|
3252
3405
|
if (next) onPref(next);
|
|
3253
3406
|
},
|
|
3254
3407
|
"aria-label": "Color theme",
|
|
3255
|
-
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */
|
|
3408
|
+
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ jsx52(
|
|
3256
3409
|
ToggleGroupItem,
|
|
3257
3410
|
{
|
|
3258
3411
|
value,
|
|
3259
3412
|
"aria-label": label,
|
|
3260
3413
|
title: label,
|
|
3261
3414
|
className: "px-2",
|
|
3262
|
-
children: /* @__PURE__ */
|
|
3415
|
+
children: /* @__PURE__ */ jsx52(Icon, {})
|
|
3263
3416
|
},
|
|
3264
3417
|
value
|
|
3265
3418
|
))
|
|
@@ -3276,7 +3429,9 @@ function ReportInteractiveView({
|
|
|
3276
3429
|
hideHeader = false,
|
|
3277
3430
|
hideToc = false,
|
|
3278
3431
|
staleAfterDays = 7,
|
|
3279
|
-
scenarioHistory
|
|
3432
|
+
scenarioHistory,
|
|
3433
|
+
share = false,
|
|
3434
|
+
shareCommand
|
|
3280
3435
|
}) {
|
|
3281
3436
|
const [urlState, setUrlState] = useUrlState();
|
|
3282
3437
|
const { query, status: statusFilter, tags: activeTags, detail } = urlState;
|
|
@@ -3292,14 +3447,14 @@ function ReportInteractiveView({
|
|
|
3292
3447
|
(next) => setUrlState({ detail: next }),
|
|
3293
3448
|
[setUrlState]
|
|
3294
3449
|
);
|
|
3295
|
-
const [helpOpen, setHelpOpen] =
|
|
3450
|
+
const [helpOpen, setHelpOpen] = useState12(false);
|
|
3296
3451
|
const { pref: themePref, setPref: setThemePref } = useTheme();
|
|
3297
|
-
const searchRef =
|
|
3452
|
+
const searchRef = useRef7(null);
|
|
3298
3453
|
const expandId = useId2();
|
|
3299
3454
|
const docsId = useId2();
|
|
3300
3455
|
const deferredQuery = useDeferredValue(query);
|
|
3301
|
-
const failures =
|
|
3302
|
-
const filtered =
|
|
3456
|
+
const failures = useMemo4(() => listFailures(report), [report]);
|
|
3457
|
+
const filtered = useMemo4(
|
|
3303
3458
|
// Features carrying failures float to the top so the first thing on screen
|
|
3304
3459
|
// is the thing that needs attention; an all-green run keeps source order.
|
|
3305
3460
|
() => failuresFirst(
|
|
@@ -3312,7 +3467,7 @@ function ReportInteractiveView({
|
|
|
3312
3467
|
[report, deferredQuery, statusFilter, activeTags]
|
|
3313
3468
|
);
|
|
3314
3469
|
const isFiltering = query !== deferredQuery;
|
|
3315
|
-
const statusOptions =
|
|
3470
|
+
const statusOptions = useMemo4(() => {
|
|
3316
3471
|
const s = report.summary;
|
|
3317
3472
|
const opts = [
|
|
3318
3473
|
{ key: "all", label: "All", count: s.total }
|
|
@@ -3327,15 +3482,15 @@ function ReportInteractiveView({
|
|
|
3327
3482
|
opts.push({ key: "pending", label: "Pending", count: s.pending });
|
|
3328
3483
|
return opts;
|
|
3329
3484
|
}, [report]);
|
|
3330
|
-
const tagOptions =
|
|
3485
|
+
const tagOptions = useMemo4(() => allTags(report), [report]);
|
|
3331
3486
|
const toggleTag = useCallback5(
|
|
3332
3487
|
(tag) => setUrlState({
|
|
3333
3488
|
tags: activeTags.includes(tag) ? activeTags.filter((t) => t !== tag) : [...activeTags, tag]
|
|
3334
3489
|
}),
|
|
3335
3490
|
[activeTags, setUrlState]
|
|
3336
3491
|
);
|
|
3337
|
-
const [toast, setToast] =
|
|
3338
|
-
const toastTimer =
|
|
3492
|
+
const [toast, setToast] = useState12(null);
|
|
3493
|
+
const toastTimer = useRef7(null);
|
|
3339
3494
|
const showToast = useCallback5((msg) => {
|
|
3340
3495
|
setToast(msg);
|
|
3341
3496
|
if (toastTimer.current) clearTimeout(toastTimer.current);
|
|
@@ -3352,7 +3507,7 @@ function ReportInteractiveView({
|
|
|
3352
3507
|
},
|
|
3353
3508
|
[showToast]
|
|
3354
3509
|
);
|
|
3355
|
-
const scenarioActions =
|
|
3510
|
+
const scenarioActions = useMemo4(
|
|
3356
3511
|
() => ({
|
|
3357
3512
|
copyLink: (s) => copy(scenarioPermalink(s), "Link copied"),
|
|
3358
3513
|
copyMarkdown: (s) => copy(scenarioToMarkdown(s), "Markdown copied"),
|
|
@@ -3364,8 +3519,8 @@ function ReportInteractiveView({
|
|
|
3364
3519
|
() => copy(failuresToPrompt(failedScenarios(filtered)), "Failures copied"),
|
|
3365
3520
|
[copy, filtered]
|
|
3366
3521
|
);
|
|
3367
|
-
const failureIndexRef =
|
|
3368
|
-
const allCollapsibleIds =
|
|
3522
|
+
const failureIndexRef = useRef7(0);
|
|
3523
|
+
const allCollapsibleIds = useMemo4(
|
|
3369
3524
|
() => report.features.flatMap((f) => [f.id, ...f.scenarios.map((s) => s.id)]),
|
|
3370
3525
|
[report]
|
|
3371
3526
|
);
|
|
@@ -3373,7 +3528,7 @@ function ReportInteractiveView({
|
|
|
3373
3528
|
useCallback5(() => defaultCollapsedIds(report), [report])
|
|
3374
3529
|
);
|
|
3375
3530
|
const revealFilteredResults = deferredQuery.trim() !== "" || statusFilter !== "all" || activeTags.length > 0;
|
|
3376
|
-
const visibleCollapse =
|
|
3531
|
+
const visibleCollapse = useMemo4(
|
|
3377
3532
|
() => revealFilteredResults ? { ...collapse.api, isCollapsed: () => false } : collapse.api,
|
|
3378
3533
|
[collapse.api, revealFilteredResults]
|
|
3379
3534
|
);
|
|
@@ -3381,7 +3536,7 @@ function ReportInteractiveView({
|
|
|
3381
3536
|
() => collapse.collapseAll(allCollapsibleIds),
|
|
3382
3537
|
[collapse, allCollapsibleIds]
|
|
3383
3538
|
);
|
|
3384
|
-
const [expandedAll, setExpandedAll] =
|
|
3539
|
+
const [expandedAll, setExpandedAll] = useState12(
|
|
3385
3540
|
() => report.summary.failed === 0
|
|
3386
3541
|
);
|
|
3387
3542
|
const setExpanded = useCallback5(
|
|
@@ -3392,7 +3547,7 @@ function ReportInteractiveView({
|
|
|
3392
3547
|
},
|
|
3393
3548
|
[collapse, collapseAll]
|
|
3394
3549
|
);
|
|
3395
|
-
const [agentFilter, setAgentFilter] =
|
|
3550
|
+
const [agentFilter, setAgentFilter] = useState12(null);
|
|
3396
3551
|
useTools(
|
|
3397
3552
|
reportTools({
|
|
3398
3553
|
report,
|
|
@@ -3439,13 +3594,13 @@ function ReportInteractiveView({
|
|
|
3439
3594
|
const totalScenarios = report.summary.total;
|
|
3440
3595
|
const matchedScenarios = filtered.summary.total;
|
|
3441
3596
|
const showToc = !hideToc && totalScenarios > 3;
|
|
3442
|
-
return /* @__PURE__ */
|
|
3597
|
+
return /* @__PURE__ */ jsx52(CollapseProvider, { value: visibleCollapse, children: /* @__PURE__ */ jsx52(ScenarioActionsProvider, { value: scenarioActions, children: /* @__PURE__ */ jsx52(ScenarioHistoryProvider, { value: scenarioHistory ?? null, children: /* @__PURE__ */ jsx52(ScenarioFreshnessProvider, { value: { staleAfterDays, report }, children: /* @__PURE__ */ jsx52(
|
|
3443
3598
|
ReportRoot,
|
|
3444
3599
|
{
|
|
3445
3600
|
report: filtered,
|
|
3446
3601
|
customRenderers,
|
|
3447
3602
|
renderers,
|
|
3448
|
-
children: /* @__PURE__ */
|
|
3603
|
+
children: /* @__PURE__ */ jsxs37(
|
|
3449
3604
|
"main",
|
|
3450
3605
|
{
|
|
3451
3606
|
className: cn("es-report", "es-report-interactive", className),
|
|
@@ -3454,8 +3609,8 @@ function ReportInteractiveView({
|
|
|
3454
3609
|
"data-theme": dataTheme,
|
|
3455
3610
|
"data-detail-level": detail,
|
|
3456
3611
|
children: [
|
|
3457
|
-
/* @__PURE__ */
|
|
3458
|
-
/* @__PURE__ */
|
|
3612
|
+
/* @__PURE__ */ jsxs37("header", { className: "es-report-header", children: [
|
|
3613
|
+
/* @__PURE__ */ jsxs37(
|
|
3459
3614
|
"div",
|
|
3460
3615
|
{
|
|
3461
3616
|
"data-es-navbar": true,
|
|
@@ -3464,9 +3619,9 @@ function ReportInteractiveView({
|
|
|
3464
3619
|
hideHeader ? "justify-end" : "justify-between"
|
|
3465
3620
|
),
|
|
3466
3621
|
children: [
|
|
3467
|
-
hideHeader ? null : /* @__PURE__ */
|
|
3468
|
-
/* @__PURE__ */
|
|
3469
|
-
/* @__PURE__ */
|
|
3622
|
+
hideHeader ? null : /* @__PURE__ */ jsx52("h1", { className: "min-w-0", children: title ?? "Story Report" }),
|
|
3623
|
+
/* @__PURE__ */ jsxs37("div", { className: "flex items-center gap-2", children: [
|
|
3624
|
+
/* @__PURE__ */ jsx52(
|
|
3470
3625
|
ReportSearch,
|
|
3471
3626
|
{
|
|
3472
3627
|
ref: searchRef,
|
|
@@ -3476,16 +3631,18 @@ function ReportInteractiveView({
|
|
|
3476
3631
|
totalCount: totalScenarios
|
|
3477
3632
|
}
|
|
3478
3633
|
),
|
|
3479
|
-
/* @__PURE__ */
|
|
3634
|
+
share ? /* @__PURE__ */ jsx52(ReportShare, { command: shareCommand, onCopy: copy }) : null,
|
|
3635
|
+
/* @__PURE__ */ jsx52(ThemeSegment, { pref: themePref, onPref: setThemePref })
|
|
3480
3636
|
] })
|
|
3481
3637
|
]
|
|
3482
3638
|
}
|
|
3483
3639
|
),
|
|
3484
|
-
hideHeader ? null : /* @__PURE__ */
|
|
3485
|
-
/* @__PURE__ */
|
|
3486
|
-
/* @__PURE__ */
|
|
3640
|
+
hideHeader ? null : /* @__PURE__ */ jsxs37(Fragment16, { children: [
|
|
3641
|
+
/* @__PURE__ */ jsx52(ReportSummary, {}),
|
|
3642
|
+
/* @__PURE__ */ jsx52(ReportMeta, {})
|
|
3487
3643
|
] }),
|
|
3488
|
-
/* @__PURE__ */
|
|
3644
|
+
/* @__PURE__ */ jsx52(ReportSpanGraph, {}),
|
|
3645
|
+
/* @__PURE__ */ jsx52(
|
|
3489
3646
|
ReportFreshness,
|
|
3490
3647
|
{
|
|
3491
3648
|
lastRunMs: reportLastRunMs(report),
|
|
@@ -3493,15 +3650,15 @@ function ReportInteractiveView({
|
|
|
3493
3650
|
staleAfterDays
|
|
3494
3651
|
}
|
|
3495
3652
|
),
|
|
3496
|
-
/* @__PURE__ */
|
|
3653
|
+
/* @__PURE__ */ jsx52(
|
|
3497
3654
|
ReportLastRunDelta,
|
|
3498
3655
|
{
|
|
3499
3656
|
history: scenarioHistory,
|
|
3500
3657
|
report
|
|
3501
3658
|
}
|
|
3502
3659
|
),
|
|
3503
|
-
/* @__PURE__ */
|
|
3504
|
-
/* @__PURE__ */
|
|
3660
|
+
/* @__PURE__ */ jsx52(ReportSinceLastVisit, { report }),
|
|
3661
|
+
/* @__PURE__ */ jsx52(
|
|
3505
3662
|
ReportFilters,
|
|
3506
3663
|
{
|
|
3507
3664
|
statuses: statusOptions,
|
|
@@ -3512,10 +3669,10 @@ function ReportInteractiveView({
|
|
|
3512
3669
|
onToggleTag: toggleTag
|
|
3513
3670
|
}
|
|
3514
3671
|
),
|
|
3515
|
-
/* @__PURE__ */
|
|
3516
|
-
showToc ? /* @__PURE__ */
|
|
3517
|
-
/* @__PURE__ */
|
|
3518
|
-
/* @__PURE__ */
|
|
3672
|
+
/* @__PURE__ */ jsxs37("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border/60 pt-3", children: [
|
|
3673
|
+
showToc ? /* @__PURE__ */ jsx52(ReportTocDrawer, {}) : null,
|
|
3674
|
+
/* @__PURE__ */ jsxs37("div", { className: "flex items-center gap-2", children: [
|
|
3675
|
+
/* @__PURE__ */ jsx52(
|
|
3519
3676
|
Switch,
|
|
3520
3677
|
{
|
|
3521
3678
|
id: expandId,
|
|
@@ -3523,7 +3680,7 @@ function ReportInteractiveView({
|
|
|
3523
3680
|
onCheckedChange: setExpanded
|
|
3524
3681
|
}
|
|
3525
3682
|
),
|
|
3526
|
-
/* @__PURE__ */
|
|
3683
|
+
/* @__PURE__ */ jsx52(
|
|
3527
3684
|
"label",
|
|
3528
3685
|
{
|
|
3529
3686
|
htmlFor: expandId,
|
|
@@ -3532,8 +3689,8 @@ function ReportInteractiveView({
|
|
|
3532
3689
|
}
|
|
3533
3690
|
)
|
|
3534
3691
|
] }),
|
|
3535
|
-
/* @__PURE__ */
|
|
3536
|
-
/* @__PURE__ */
|
|
3692
|
+
/* @__PURE__ */ jsxs37("div", { className: "flex items-center gap-2", children: [
|
|
3693
|
+
/* @__PURE__ */ jsx52(
|
|
3537
3694
|
Switch,
|
|
3538
3695
|
{
|
|
3539
3696
|
id: docsId,
|
|
@@ -3541,7 +3698,7 @@ function ReportInteractiveView({
|
|
|
3541
3698
|
onCheckedChange: (checked) => setDetail(checked ? "full" : "minimal")
|
|
3542
3699
|
}
|
|
3543
3700
|
),
|
|
3544
|
-
/* @__PURE__ */
|
|
3701
|
+
/* @__PURE__ */ jsx52(
|
|
3545
3702
|
"label",
|
|
3546
3703
|
{
|
|
3547
3704
|
htmlFor: docsId,
|
|
@@ -3552,7 +3709,7 @@ function ReportInteractiveView({
|
|
|
3552
3709
|
] })
|
|
3553
3710
|
] })
|
|
3554
3711
|
] }),
|
|
3555
|
-
showAgentFilter ? /* @__PURE__ */
|
|
3712
|
+
showAgentFilter ? /* @__PURE__ */ jsx52(
|
|
3556
3713
|
ReportAgentFilterNotice,
|
|
3557
3714
|
{
|
|
3558
3715
|
applied: agentFilter,
|
|
@@ -3560,17 +3717,17 @@ function ReportInteractiveView({
|
|
|
3560
3717
|
onDismiss: () => setAgentFilter(null)
|
|
3561
3718
|
}
|
|
3562
3719
|
) : null,
|
|
3563
|
-
/* @__PURE__ */
|
|
3564
|
-
hasContent ? showToc ? /* @__PURE__ */
|
|
3565
|
-
/* @__PURE__ */
|
|
3566
|
-
/* @__PURE__ */
|
|
3567
|
-
] }) : /* @__PURE__ */
|
|
3720
|
+
/* @__PURE__ */ jsx52(ReportFailureBanner, { failures, onCopyAll: copyAllFailures }),
|
|
3721
|
+
hasContent ? showToc ? /* @__PURE__ */ jsxs37("div", { className: "flex gap-6", children: [
|
|
3722
|
+
/* @__PURE__ */ jsx52(ReportToc, {}),
|
|
3723
|
+
/* @__PURE__ */ jsx52("div", { className: "flex min-w-0 flex-1 flex-col gap-4", children: /* @__PURE__ */ jsx52(ReportFeatureList, {}) })
|
|
3724
|
+
] }) : /* @__PURE__ */ jsx52("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsx52(ReportFeatureList, {}) }) : /* @__PURE__ */ jsx52(
|
|
3568
3725
|
ReportEmpty,
|
|
3569
3726
|
{
|
|
3570
3727
|
message: query ? "No scenarios match the search." : void 0
|
|
3571
3728
|
}
|
|
3572
3729
|
),
|
|
3573
|
-
/* @__PURE__ */
|
|
3730
|
+
/* @__PURE__ */ jsx52(
|
|
3574
3731
|
"button",
|
|
3575
3732
|
{
|
|
3576
3733
|
type: "button",
|
|
@@ -3581,14 +3738,14 @@ function ReportInteractiveView({
|
|
|
3581
3738
|
children: "?"
|
|
3582
3739
|
}
|
|
3583
3740
|
),
|
|
3584
|
-
/* @__PURE__ */
|
|
3741
|
+
/* @__PURE__ */ jsx52(
|
|
3585
3742
|
ReportShortcutsHelp,
|
|
3586
3743
|
{
|
|
3587
3744
|
open: helpOpen,
|
|
3588
3745
|
onClose: () => setHelpOpen(false)
|
|
3589
3746
|
}
|
|
3590
3747
|
),
|
|
3591
|
-
toast ? /* @__PURE__ */
|
|
3748
|
+
toast ? /* @__PURE__ */ jsx52(
|
|
3592
3749
|
"div",
|
|
3593
3750
|
{
|
|
3594
3751
|
role: "status",
|
|
@@ -3605,14 +3762,14 @@ function ReportInteractiveView({
|
|
|
3605
3762
|
}
|
|
3606
3763
|
|
|
3607
3764
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
3608
|
-
import { useMemo as
|
|
3765
|
+
import { useMemo as useMemo5 } from "react";
|
|
3609
3766
|
|
|
3610
3767
|
// src/interactive/island-renderers.tsx
|
|
3611
|
-
import { createElement, useEffect as
|
|
3768
|
+
import { createElement, useEffect as useEffect13, useState as useState14 } from "react";
|
|
3612
3769
|
|
|
3613
3770
|
// src/components/doc/MermaidView.tsx
|
|
3614
|
-
import { useEffect as
|
|
3615
|
-
import { Fragment as
|
|
3771
|
+
import { useEffect as useEffect12, useRef as useRef8, useState as useState13 } from "react";
|
|
3772
|
+
import { Fragment as Fragment17, jsx as jsx53, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
3616
3773
|
function prefersDark(el) {
|
|
3617
3774
|
const themed = el?.closest("[data-theme]");
|
|
3618
3775
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -3620,10 +3777,10 @@ function prefersDark(el) {
|
|
|
3620
3777
|
return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
|
|
3621
3778
|
}
|
|
3622
3779
|
function MermaidView({ entry, load }) {
|
|
3623
|
-
const ref =
|
|
3624
|
-
const [svg, setSvg] =
|
|
3625
|
-
const [error, setError] =
|
|
3626
|
-
|
|
3780
|
+
const ref = useRef8(null);
|
|
3781
|
+
const [svg, setSvg] = useState13(null);
|
|
3782
|
+
const [error, setError] = useState13(null);
|
|
3783
|
+
useEffect12(() => {
|
|
3627
3784
|
let cancelled = false;
|
|
3628
3785
|
const draw = async () => {
|
|
3629
3786
|
let mermaid;
|
|
@@ -3666,9 +3823,9 @@ function MermaidView({ entry, load }) {
|
|
|
3666
3823
|
};
|
|
3667
3824
|
}, [entry.code, load]);
|
|
3668
3825
|
if (svg) {
|
|
3669
|
-
return /* @__PURE__ */
|
|
3670
|
-
entry.title ? /* @__PURE__ */
|
|
3671
|
-
/* @__PURE__ */
|
|
3826
|
+
return /* @__PURE__ */ jsxs38("figure", { ref, className: "my-3", children: [
|
|
3827
|
+
entry.title ? /* @__PURE__ */ jsx53("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
3828
|
+
/* @__PURE__ */ jsx53(
|
|
3672
3829
|
"div",
|
|
3673
3830
|
{
|
|
3674
3831
|
role: "img",
|
|
@@ -3679,8 +3836,8 @@ function MermaidView({ entry, load }) {
|
|
|
3679
3836
|
)
|
|
3680
3837
|
] });
|
|
3681
3838
|
}
|
|
3682
|
-
return /* @__PURE__ */
|
|
3683
|
-
error ? /* @__PURE__ */
|
|
3839
|
+
return /* @__PURE__ */ jsxs38(Fragment17, { children: [
|
|
3840
|
+
error ? /* @__PURE__ */ jsxs38(
|
|
3684
3841
|
"p",
|
|
3685
3842
|
{
|
|
3686
3843
|
role: "alert",
|
|
@@ -3692,12 +3849,12 @@ function MermaidView({ entry, load }) {
|
|
|
3692
3849
|
]
|
|
3693
3850
|
}
|
|
3694
3851
|
) : null,
|
|
3695
|
-
/* @__PURE__ */
|
|
3852
|
+
/* @__PURE__ */ jsx53(MermaidSource, { entry, ref })
|
|
3696
3853
|
] });
|
|
3697
3854
|
}
|
|
3698
3855
|
|
|
3699
3856
|
// src/interactive/island-renderers.tsx
|
|
3700
|
-
import { jsx as
|
|
3857
|
+
import { jsx as jsx54 } from "react/jsx-runtime";
|
|
3701
3858
|
var HLJS_ESM = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
|
|
3702
3859
|
var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
|
|
3703
3860
|
function cachedCdnModule(url) {
|
|
@@ -3714,8 +3871,8 @@ function cachedCdnModule(url) {
|
|
|
3714
3871
|
var loadMermaidFromCdn = cachedCdnModule(MERMAID_ESM);
|
|
3715
3872
|
var loadHljs = cachedCdnModule(HLJS_ESM);
|
|
3716
3873
|
function CdnHighlightedCode({ entry }) {
|
|
3717
|
-
const [html, setHtml] =
|
|
3718
|
-
|
|
3874
|
+
const [html, setHtml] = useState14(null);
|
|
3875
|
+
useEffect13(() => {
|
|
3719
3876
|
let cancelled = false;
|
|
3720
3877
|
void (async () => {
|
|
3721
3878
|
try {
|
|
@@ -3731,13 +3888,13 @@ function CdnHighlightedCode({ entry }) {
|
|
|
3731
3888
|
cancelled = true;
|
|
3732
3889
|
};
|
|
3733
3890
|
}, [entry.content, entry.lang]);
|
|
3734
|
-
return /* @__PURE__ */
|
|
3891
|
+
return /* @__PURE__ */ jsx54(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ jsx54(
|
|
3735
3892
|
"code",
|
|
3736
3893
|
{
|
|
3737
3894
|
className: cn("hljs font-mono text-xs", entry.lang && `language-${entry.lang}`),
|
|
3738
3895
|
dangerouslySetInnerHTML: { __html: html }
|
|
3739
3896
|
}
|
|
3740
|
-
) : /* @__PURE__ */
|
|
3897
|
+
) : /* @__PURE__ */ jsx54("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
3741
3898
|
}
|
|
3742
3899
|
function buildIslandRenderers(opts) {
|
|
3743
3900
|
const renderers = {};
|
|
@@ -3751,7 +3908,7 @@ function buildIslandRenderers(opts) {
|
|
|
3751
3908
|
}
|
|
3752
3909
|
|
|
3753
3910
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
3754
|
-
import { jsx as
|
|
3911
|
+
import { jsx as jsx55 } from "react/jsx-runtime";
|
|
3755
3912
|
function ReportInteractiveIsland({
|
|
3756
3913
|
report,
|
|
3757
3914
|
title,
|
|
@@ -3761,11 +3918,11 @@ function ReportInteractiveIsland({
|
|
|
3761
3918
|
syntaxHighlighting = true,
|
|
3762
3919
|
mermaid = true
|
|
3763
3920
|
}) {
|
|
3764
|
-
const renderers =
|
|
3921
|
+
const renderers = useMemo5(
|
|
3765
3922
|
() => buildIslandRenderers({ syntaxHighlighting, mermaid }),
|
|
3766
3923
|
[syntaxHighlighting, mermaid]
|
|
3767
3924
|
);
|
|
3768
|
-
return /* @__PURE__ */
|
|
3925
|
+
return /* @__PURE__ */ jsx55(
|
|
3769
3926
|
ReportInteractive,
|
|
3770
3927
|
{
|
|
3771
3928
|
report,
|