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.cjs
CHANGED
|
@@ -47,9 +47,9 @@ __export(interactive_exports, {
|
|
|
47
47
|
module.exports = __toCommonJS(interactive_exports);
|
|
48
48
|
|
|
49
49
|
// src/interactive/ReportInteractive.tsx
|
|
50
|
-
var
|
|
51
|
-
var
|
|
52
|
-
var
|
|
50
|
+
var import_lucide_react7 = require("lucide-react");
|
|
51
|
+
var import_react25 = require("webmcpable/react");
|
|
52
|
+
var import_react26 = require("react");
|
|
53
53
|
|
|
54
54
|
// src/components/ui/empty.tsx
|
|
55
55
|
var import_class_variance_authority = require("class-variance-authority");
|
|
@@ -420,12 +420,29 @@ function DocVideo({ entry }) {
|
|
|
420
420
|
}
|
|
421
421
|
|
|
422
422
|
// src/components/doc/DocHtml.tsx
|
|
423
|
+
var import_react4 = require("react");
|
|
423
424
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
425
|
+
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>";
|
|
426
|
+
var MAX_MEASURED_HEIGHT = 5e3;
|
|
424
427
|
function DocHtml({ entry }) {
|
|
425
|
-
const
|
|
428
|
+
const declaredHeight = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
426
429
|
const title = entry.title ?? "Embedded HTML";
|
|
427
430
|
const safeHref = (0, import_url.safeUrl)(entry.url ?? entry.path);
|
|
428
|
-
const
|
|
431
|
+
const frameRef = (0, import_react4.useRef)(null);
|
|
432
|
+
const [measuredHeight, setMeasuredHeight] = (0, import_react4.useState)();
|
|
433
|
+
(0, import_react4.useEffect)(() => {
|
|
434
|
+
if (entry.content === void 0) return;
|
|
435
|
+
const onMessage = (event) => {
|
|
436
|
+
if (event.source !== frameRef.current?.contentWindow) return;
|
|
437
|
+
const reported = event.data?.__esHtmlHeight;
|
|
438
|
+
if (typeof reported !== "number" || !Number.isFinite(reported) || reported <= 0) return;
|
|
439
|
+
setMeasuredHeight(Math.min(reported, MAX_MEASURED_HEIGHT));
|
|
440
|
+
};
|
|
441
|
+
window.addEventListener("message", onMessage);
|
|
442
|
+
return () => window.removeEventListener("message", onMessage);
|
|
443
|
+
}, [entry.content]);
|
|
444
|
+
const height = measuredHeight === void 0 ? declaredHeight : `${measuredHeight}px`;
|
|
445
|
+
const frameProps = entry.content !== void 0 ? { srcDoc: entry.content + MEASURE_SCRIPT } : { src: safeHref ?? "" };
|
|
429
446
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
|
|
430
447
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("figcaption", { className: "flex items-center justify-between border-b border-border bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground", children: [
|
|
431
448
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: entry.title ?? "HTML" }),
|
|
@@ -445,6 +462,7 @@ function DocHtml({ entry }) {
|
|
|
445
462
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
446
463
|
"iframe",
|
|
447
464
|
{
|
|
465
|
+
ref: frameRef,
|
|
448
466
|
...frameProps,
|
|
449
467
|
sandbox: "allow-scripts",
|
|
450
468
|
loading: "lazy",
|
|
@@ -898,11 +916,11 @@ function ReportTrace({ spans }) {
|
|
|
898
916
|
}
|
|
899
917
|
|
|
900
918
|
// src/interactive/scenario-history-context.ts
|
|
901
|
-
var
|
|
902
|
-
var ScenarioHistoryContext = (0,
|
|
919
|
+
var import_react5 = require("react");
|
|
920
|
+
var ScenarioHistoryContext = (0, import_react5.createContext)(null);
|
|
903
921
|
var ScenarioHistoryProvider = ScenarioHistoryContext.Provider;
|
|
904
922
|
function useScenarioHistory() {
|
|
905
|
-
return (0,
|
|
923
|
+
return (0, import_react5.useContext)(ScenarioHistoryContext);
|
|
906
924
|
}
|
|
907
925
|
|
|
908
926
|
// src/lib/run-history.ts
|
|
@@ -1011,7 +1029,7 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
1011
1029
|
}
|
|
1012
1030
|
|
|
1013
1031
|
// src/components/ScenarioStaleness.tsx
|
|
1014
|
-
var
|
|
1032
|
+
var import_react7 = require("react");
|
|
1015
1033
|
|
|
1016
1034
|
// src/lib/provenance.ts
|
|
1017
1035
|
function reportLastRunMs(report) {
|
|
@@ -1063,11 +1081,11 @@ function prUrl(ci) {
|
|
|
1063
1081
|
}
|
|
1064
1082
|
|
|
1065
1083
|
// src/interactive/scenario-freshness-context.tsx
|
|
1066
|
-
var
|
|
1067
|
-
var ScenarioFreshnessContext = (0,
|
|
1084
|
+
var import_react6 = require("react");
|
|
1085
|
+
var ScenarioFreshnessContext = (0, import_react6.createContext)(null);
|
|
1068
1086
|
var ScenarioFreshnessProvider = ScenarioFreshnessContext.Provider;
|
|
1069
1087
|
function useScenarioFreshness() {
|
|
1070
|
-
return (0,
|
|
1088
|
+
return (0, import_react6.useContext)(ScenarioFreshnessContext);
|
|
1071
1089
|
}
|
|
1072
1090
|
|
|
1073
1091
|
// src/components/ScenarioStaleness.tsx
|
|
@@ -1075,8 +1093,8 @@ var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
|
1075
1093
|
function ScenarioStaleness({ scenario }) {
|
|
1076
1094
|
const freshness = useScenarioFreshness();
|
|
1077
1095
|
const fixedNow = freshness?.nowMs;
|
|
1078
|
-
const [now, setNow] = (0,
|
|
1079
|
-
(0,
|
|
1096
|
+
const [now, setNow] = (0, import_react7.useState)(fixedNow);
|
|
1097
|
+
(0, import_react7.useEffect)(() => {
|
|
1080
1098
|
if (fixedNow === void 0) setNow(Date.now());
|
|
1081
1099
|
}, [fixedNow]);
|
|
1082
1100
|
if (!freshness || now === void 0) return null;
|
|
@@ -1090,11 +1108,11 @@ function ScenarioStaleness({ scenario }) {
|
|
|
1090
1108
|
}
|
|
1091
1109
|
|
|
1092
1110
|
// src/interactive/collapse-context.ts
|
|
1093
|
-
var
|
|
1094
|
-
var CollapseContext = (0,
|
|
1111
|
+
var import_react8 = require("react");
|
|
1112
|
+
var CollapseContext = (0, import_react8.createContext)(null);
|
|
1095
1113
|
var CollapseProvider = CollapseContext.Provider;
|
|
1096
1114
|
function useCollapse() {
|
|
1097
|
-
return (0,
|
|
1115
|
+
return (0, import_react8.useContext)(CollapseContext);
|
|
1098
1116
|
}
|
|
1099
1117
|
var STORAGE_KEY = "es-collapsed-ids";
|
|
1100
1118
|
function readPersisted() {
|
|
@@ -1114,11 +1132,11 @@ function persist(ids) {
|
|
|
1114
1132
|
}
|
|
1115
1133
|
}
|
|
1116
1134
|
function useCollapseState(computeDefault) {
|
|
1117
|
-
const [collapsed, setCollapsed] = (0,
|
|
1135
|
+
const [collapsed, setCollapsed] = (0, import_react8.useState)(
|
|
1118
1136
|
() => readPersisted() ?? computeDefault?.() ?? /* @__PURE__ */ new Set()
|
|
1119
1137
|
);
|
|
1120
|
-
const isCollapsed = (0,
|
|
1121
|
-
const toggle = (0,
|
|
1138
|
+
const isCollapsed = (0, import_react8.useCallback)((id) => collapsed.has(id), [collapsed]);
|
|
1139
|
+
const toggle = (0, import_react8.useCallback)((id) => {
|
|
1122
1140
|
setCollapsed((prev) => {
|
|
1123
1141
|
const next = new Set(prev);
|
|
1124
1142
|
if (next.has(id)) next.delete(id);
|
|
@@ -1127,14 +1145,14 @@ function useCollapseState(computeDefault) {
|
|
|
1127
1145
|
return next;
|
|
1128
1146
|
});
|
|
1129
1147
|
}, []);
|
|
1130
|
-
const collapseAll = (0,
|
|
1148
|
+
const collapseAll = (0, import_react8.useCallback)((ids) => {
|
|
1131
1149
|
setCollapsed(() => {
|
|
1132
1150
|
const next = new Set(ids);
|
|
1133
1151
|
persist(next);
|
|
1134
1152
|
return next;
|
|
1135
1153
|
});
|
|
1136
1154
|
}, []);
|
|
1137
|
-
const expandAll = (0,
|
|
1155
|
+
const expandAll = (0, import_react8.useCallback)(() => {
|
|
1138
1156
|
setCollapsed(() => {
|
|
1139
1157
|
const next = /* @__PURE__ */ new Set();
|
|
1140
1158
|
persist(next);
|
|
@@ -1145,12 +1163,12 @@ function useCollapseState(computeDefault) {
|
|
|
1145
1163
|
}
|
|
1146
1164
|
|
|
1147
1165
|
// src/interactive/scenario-actions.tsx
|
|
1148
|
-
var
|
|
1166
|
+
var import_react9 = require("react");
|
|
1149
1167
|
var import_scenario_markdown = require("executable-stories-core/utils/scenario-markdown");
|
|
1150
|
-
var ScenarioActionsContext = (0,
|
|
1168
|
+
var ScenarioActionsContext = (0, import_react9.createContext)(null);
|
|
1151
1169
|
var ScenarioActionsProvider = ScenarioActionsContext.Provider;
|
|
1152
1170
|
function useScenarioActions() {
|
|
1153
|
-
return (0,
|
|
1171
|
+
return (0, import_react9.useContext)(ScenarioActionsContext);
|
|
1154
1172
|
}
|
|
1155
1173
|
function scenarioToMarkdown(scenario) {
|
|
1156
1174
|
return (0, import_scenario_markdown.scenarioToMarkdown)(scenario, { variant: "compact" });
|
|
@@ -1688,15 +1706,75 @@ function ReportErrorShell({
|
|
|
1688
1706
|
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportSchemaError, { error }) });
|
|
1689
1707
|
}
|
|
1690
1708
|
|
|
1709
|
+
// src/components/ReportSpanGraph.tsx
|
|
1710
|
+
var import_span_graph = require("executable-stories-core/span-graph");
|
|
1711
|
+
var import_react10 = require("react");
|
|
1712
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
1713
|
+
var LANE_LABEL = {
|
|
1714
|
+
edge: "Edge",
|
|
1715
|
+
service: "Service",
|
|
1716
|
+
queue: "Queue",
|
|
1717
|
+
datastore: "Data"
|
|
1718
|
+
};
|
|
1719
|
+
var MARK_LABEL = {
|
|
1720
|
+
failing: "Failing",
|
|
1721
|
+
added: "New",
|
|
1722
|
+
changed: "Changed"
|
|
1723
|
+
};
|
|
1724
|
+
var MARK_CLASS = {
|
|
1725
|
+
failing: "text-fail",
|
|
1726
|
+
added: "text-pass",
|
|
1727
|
+
changed: "text-pend"
|
|
1728
|
+
};
|
|
1729
|
+
function MarkBadge({ node }) {
|
|
1730
|
+
const mark = (0, import_span_graph.spanGraphNodeMark)(node);
|
|
1731
|
+
if (!mark) return null;
|
|
1732
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: cn("ml-2 text-xs font-medium", MARK_CLASS[mark]), children: MARK_LABEL[mark] });
|
|
1733
|
+
}
|
|
1734
|
+
function ReportSpanGraph() {
|
|
1735
|
+
const report = useReport();
|
|
1736
|
+
const { code, graph, titleById } = (0, import_react10.useMemo)(() => {
|
|
1737
|
+
const scenarios = report.features.flatMap((feature) => feature.scenarios);
|
|
1738
|
+
const derived = (0, import_span_graph.deriveSpanGraph)(scenarios);
|
|
1739
|
+
return {
|
|
1740
|
+
graph: derived,
|
|
1741
|
+
code: (0, import_span_graph.spanGraphToMermaid)(derived),
|
|
1742
|
+
titleById: new Map(scenarios.map((scenario) => [scenario.id, scenario.title]))
|
|
1743
|
+
};
|
|
1744
|
+
}, [report]);
|
|
1745
|
+
if (code === "") return null;
|
|
1746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("section", { className: "es-span-graph mt-6", "aria-labelledby": "es-span-graph-heading", children: [
|
|
1747
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h2", { id: "es-span-graph-heading", className: "text-base font-semibold text-foreground", children: "Architecture, as it ran" }),
|
|
1748
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: "Derived from this run\u2019s traces. Every component was named by a span while a scenario ran, so nothing here is inferred from the code. Instrumented, exercised paths only: a component no scenario reaches does not appear." }),
|
|
1749
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(DocMermaid, { entry: { kind: "mermaid", phase: "static", code } }),
|
|
1750
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("table", { className: "mt-2 w-full text-left text-sm", children: [
|
|
1751
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("caption", { className: "sr-only", children: "Each component and the scenarios that exercised it" }),
|
|
1752
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("tr", { className: "text-xs text-muted-foreground", children: [
|
|
1753
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("th", { scope: "col", className: "py-1 pr-4 font-medium", children: "Component" }),
|
|
1754
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("th", { scope: "col", className: "py-1 pr-4 font-medium", children: "Lane" }),
|
|
1755
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("th", { scope: "col", className: "py-1 font-medium", children: "Covered by" })
|
|
1756
|
+
] }) }),
|
|
1757
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("tbody", { children: graph.nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("tr", { className: "border-t border-border align-top", children: [
|
|
1758
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("th", { scope: "row", className: "py-1.5 pr-4 font-mono text-xs font-normal", children: [
|
|
1759
|
+
node.id,
|
|
1760
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MarkBadge, { node })
|
|
1761
|
+
] }),
|
|
1762
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("td", { className: "py-1.5 pr-4 text-xs text-muted-foreground", children: LANE_LABEL[node.kind] }),
|
|
1763
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("td", { className: "py-1.5", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("ul", { className: "flex flex-col gap-0.5", children: node.scenarioIds.map((id) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("a", { href: `#${id}`, className: "text-xs underline underline-offset-2", children: titleById.get(id) ?? id }) }, id)) }) })
|
|
1764
|
+
] }, node.id)) })
|
|
1765
|
+
] })
|
|
1766
|
+
] });
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1691
1769
|
// src/components/ui/switch.tsx
|
|
1692
1770
|
var React4 = require("react");
|
|
1693
1771
|
var import_switch = require("@base-ui/react/switch");
|
|
1694
|
-
var
|
|
1772
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
1695
1773
|
function Switch({
|
|
1696
1774
|
className,
|
|
1697
1775
|
...props
|
|
1698
1776
|
}) {
|
|
1699
|
-
return /* @__PURE__ */ (0,
|
|
1777
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
1700
1778
|
import_switch.Switch.Root,
|
|
1701
1779
|
{
|
|
1702
1780
|
"data-slot": "switch",
|
|
@@ -1705,7 +1783,7 @@ function Switch({
|
|
|
1705
1783
|
className
|
|
1706
1784
|
),
|
|
1707
1785
|
...props,
|
|
1708
|
-
children: /* @__PURE__ */ (0,
|
|
1786
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
1709
1787
|
import_switch.Switch.Thumb,
|
|
1710
1788
|
{
|
|
1711
1789
|
"data-slot": "switch-thumb",
|
|
@@ -1721,7 +1799,7 @@ var React5 = __toESM(require("react"), 1);
|
|
|
1721
1799
|
var import_toggle_group = require("@base-ui/react/toggle-group");
|
|
1722
1800
|
var import_toggle = require("@base-ui/react/toggle");
|
|
1723
1801
|
var import_class_variance_authority3 = require("class-variance-authority");
|
|
1724
|
-
var
|
|
1802
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
1725
1803
|
var toggleItemVariants = (0, import_class_variance_authority3.cva)(
|
|
1726
1804
|
"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",
|
|
1727
1805
|
{
|
|
@@ -1743,13 +1821,13 @@ function ToggleGroup({
|
|
|
1743
1821
|
children,
|
|
1744
1822
|
...props
|
|
1745
1823
|
}) {
|
|
1746
|
-
return /* @__PURE__ */ (0,
|
|
1824
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
1747
1825
|
import_toggle_group.ToggleGroup,
|
|
1748
1826
|
{
|
|
1749
1827
|
"data-slot": "toggle-group",
|
|
1750
1828
|
className: cn("flex w-fit items-center gap-0.5 rounded-lg bg-muted p-0.5", className),
|
|
1751
1829
|
...props,
|
|
1752
|
-
children: /* @__PURE__ */ (0,
|
|
1830
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ToggleGroupContext.Provider, { value: { size }, children })
|
|
1753
1831
|
}
|
|
1754
1832
|
);
|
|
1755
1833
|
}
|
|
@@ -1760,7 +1838,7 @@ function ToggleGroupItem({
|
|
|
1760
1838
|
...props
|
|
1761
1839
|
}) {
|
|
1762
1840
|
const context = React5.useContext(ToggleGroupContext);
|
|
1763
|
-
return /* @__PURE__ */ (0,
|
|
1841
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
1764
1842
|
import_toggle.Toggle,
|
|
1765
1843
|
{
|
|
1766
1844
|
"data-slot": "toggle-group-item",
|
|
@@ -1772,10 +1850,10 @@ function ToggleGroupItem({
|
|
|
1772
1850
|
}
|
|
1773
1851
|
|
|
1774
1852
|
// src/context/ReportRoot.tsx
|
|
1775
|
-
var
|
|
1853
|
+
var import_react11 = require("react");
|
|
1776
1854
|
|
|
1777
1855
|
// src/components/doc/NarrativeBlocks.tsx
|
|
1778
|
-
var
|
|
1856
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
1779
1857
|
var FILE_TREE_TYPE = "file-tree";
|
|
1780
1858
|
var DATA_MODEL_TYPE = "data-model";
|
|
1781
1859
|
function isChangeKind(value) {
|
|
@@ -1789,23 +1867,23 @@ function str(value) {
|
|
|
1789
1867
|
}
|
|
1790
1868
|
function AuthoredMarker({ authored }) {
|
|
1791
1869
|
if (authored !== "agent") return null;
|
|
1792
|
-
return /* @__PURE__ */ (0,
|
|
1870
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge, { variant: "outline", className: "border-border text-[10px] text-muted-foreground", children: "AI-authored, not verified by a run" });
|
|
1793
1871
|
}
|
|
1794
1872
|
function BlockFrame({
|
|
1795
1873
|
title,
|
|
1796
1874
|
authored,
|
|
1797
1875
|
children
|
|
1798
1876
|
}) {
|
|
1799
|
-
return /* @__PURE__ */ (0,
|
|
1800
|
-
title || authored === "agent" ? /* @__PURE__ */ (0,
|
|
1801
|
-
title ? /* @__PURE__ */ (0,
|
|
1802
|
-
/* @__PURE__ */ (0,
|
|
1877
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("figure", { className: "my-3", children: [
|
|
1878
|
+
title || authored === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("figcaption", { className: "mb-1.5 flex flex-wrap items-center gap-2", children: [
|
|
1879
|
+
title ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs font-medium text-muted-foreground", children: title }) : null,
|
|
1880
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(AuthoredMarker, { authored })
|
|
1803
1881
|
] }) : null,
|
|
1804
1882
|
children
|
|
1805
1883
|
] });
|
|
1806
1884
|
}
|
|
1807
1885
|
function ChangeBadge({ change }) {
|
|
1808
|
-
return /* @__PURE__ */ (0,
|
|
1886
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge, { variant: "tag", className: "text-[10px]", children: change });
|
|
1809
1887
|
}
|
|
1810
1888
|
function parseFileTree(data) {
|
|
1811
1889
|
if (!isRecord(data) || !Array.isArray(data.files)) return void 0;
|
|
@@ -1854,11 +1932,11 @@ function sortedChildren(node) {
|
|
|
1854
1932
|
}
|
|
1855
1933
|
function TreeBranch({ node, depth }) {
|
|
1856
1934
|
const children = sortedChildren(node);
|
|
1857
|
-
return /* @__PURE__ */ (0,
|
|
1935
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("ul", { className: cn("space-y-0.5", depth > 0 && "ml-3 border-l border-border/60 pl-3"), children: children.map((child) => {
|
|
1858
1936
|
const isDir = child.children.size > 0;
|
|
1859
|
-
return /* @__PURE__ */ (0,
|
|
1860
|
-
/* @__PURE__ */ (0,
|
|
1861
|
-
/* @__PURE__ */ (0,
|
|
1937
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("li", { children: [
|
|
1938
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-wrap items-baseline gap-2", children: [
|
|
1939
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1862
1940
|
"span",
|
|
1863
1941
|
{
|
|
1864
1942
|
className: cn(
|
|
@@ -1868,17 +1946,17 @@ function TreeBranch({ node, depth }) {
|
|
|
1868
1946
|
children: isDir ? `${child.name}/` : child.name
|
|
1869
1947
|
}
|
|
1870
1948
|
),
|
|
1871
|
-
child.file?.change ? /* @__PURE__ */ (0,
|
|
1872
|
-
child.file?.note ? /* @__PURE__ */ (0,
|
|
1949
|
+
child.file?.change ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ChangeBadge, { change: child.file.change }) : null,
|
|
1950
|
+
child.file?.note ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs text-muted-foreground", children: child.file.note }) : null
|
|
1873
1951
|
] }),
|
|
1874
|
-
isDir ? /* @__PURE__ */ (0,
|
|
1952
|
+
isDir ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(TreeBranch, { node: child, depth: depth + 1 }) : null
|
|
1875
1953
|
] }, child.name);
|
|
1876
1954
|
}) });
|
|
1877
1955
|
}
|
|
1878
1956
|
function FileTreeBlock({ entry }) {
|
|
1879
1957
|
const data = parseFileTree(entry.data);
|
|
1880
|
-
if (!data) return /* @__PURE__ */ (0,
|
|
1881
|
-
return /* @__PURE__ */ (0,
|
|
1958
|
+
if (!data) return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(UnreadableBlock, { entry });
|
|
1959
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(BlockFrame, { title: data.title ?? "Files changed", authored: data.authored, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border bg-card p-3", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(TreeBranch, { node: buildTree(data.files), depth: 0 }) }) });
|
|
1882
1960
|
}
|
|
1883
1961
|
function parseDataModel(data) {
|
|
1884
1962
|
if (!isRecord(data) || !Array.isArray(data.fields)) return void 0;
|
|
@@ -1904,31 +1982,31 @@ function parseDataModel(data) {
|
|
|
1904
1982
|
}
|
|
1905
1983
|
function DataModelBlock({ entry }) {
|
|
1906
1984
|
const data = parseDataModel(entry.data);
|
|
1907
|
-
if (!data) return /* @__PURE__ */ (0,
|
|
1985
|
+
if (!data) return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(UnreadableBlock, { entry });
|
|
1908
1986
|
const hasNotes = data.fields.some((f) => f.note);
|
|
1909
|
-
return /* @__PURE__ */ (0,
|
|
1910
|
-
/* @__PURE__ */ (0,
|
|
1911
|
-
/* @__PURE__ */ (0,
|
|
1912
|
-
/* @__PURE__ */ (0,
|
|
1913
|
-
hasNotes ? /* @__PURE__ */ (0,
|
|
1987
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(BlockFrame, { title: data.title ?? data.name ?? "Data model", authored: data.authored, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("table", { className: "w-full border-collapse text-sm", children: [
|
|
1988
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("tr", { className: "bg-muted/50", children: [
|
|
1989
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Field" }),
|
|
1990
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Type" }),
|
|
1991
|
+
hasNotes ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Note" }) : null
|
|
1914
1992
|
] }) }),
|
|
1915
|
-
/* @__PURE__ */ (0,
|
|
1916
|
-
/* @__PURE__ */ (0,
|
|
1917
|
-
/* @__PURE__ */ (0,
|
|
1918
|
-
field.change ? /* @__PURE__ */ (0,
|
|
1993
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("tbody", { children: data.fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("tr", { children: [
|
|
1994
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("td", { className: "border-b border-border px-3 py-2", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "flex flex-wrap items-center gap-2", children: [
|
|
1995
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "font-mono text-xs text-foreground", children: field.name }),
|
|
1996
|
+
field.change ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ChangeBadge, { change: field.change }) : null
|
|
1919
1997
|
] }) }),
|
|
1920
|
-
/* @__PURE__ */ (0,
|
|
1921
|
-
hasNotes ? /* @__PURE__ */ (0,
|
|
1998
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("td", { className: "border-b border-border px-3 py-2 font-mono text-xs text-muted-foreground", children: field.type ?? "" }),
|
|
1999
|
+
hasNotes ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: field.note ?? "" }) : null
|
|
1922
2000
|
] }, field.name)) })
|
|
1923
2001
|
] }) }) });
|
|
1924
2002
|
}
|
|
1925
2003
|
function UnreadableBlock({ entry }) {
|
|
1926
|
-
return /* @__PURE__ */ (0,
|
|
1927
|
-
/* @__PURE__ */ (0,
|
|
2004
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
|
|
2005
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: [
|
|
1928
2006
|
entry.type,
|
|
1929
2007
|
" (unrecognised shape)"
|
|
1930
2008
|
] }),
|
|
1931
|
-
/* @__PURE__ */ (0,
|
|
2009
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1932
2010
|
"pre",
|
|
1933
2011
|
{
|
|
1934
2012
|
tabIndex: 0,
|
|
@@ -1946,12 +2024,12 @@ function safeStringify2(value) {
|
|
|
1946
2024
|
}
|
|
1947
2025
|
}
|
|
1948
2026
|
var narrativeBlockRenderers = {
|
|
1949
|
-
[FILE_TREE_TYPE]: (entry) => /* @__PURE__ */ (0,
|
|
1950
|
-
[DATA_MODEL_TYPE]: (entry) => /* @__PURE__ */ (0,
|
|
2027
|
+
[FILE_TREE_TYPE]: (entry) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(FileTreeBlock, { entry }),
|
|
2028
|
+
[DATA_MODEL_TYPE]: (entry) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(DataModelBlock, { entry })
|
|
1951
2029
|
};
|
|
1952
2030
|
|
|
1953
2031
|
// src/context/ReportRoot.tsx
|
|
1954
|
-
var
|
|
2032
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
1955
2033
|
var EMPTY_RENDERERS2 = {};
|
|
1956
2034
|
function ReportRoot({
|
|
1957
2035
|
report,
|
|
@@ -1959,7 +2037,7 @@ function ReportRoot({
|
|
|
1959
2037
|
renderers,
|
|
1960
2038
|
children
|
|
1961
2039
|
}) {
|
|
1962
|
-
const value = (0,
|
|
2040
|
+
const value = (0, import_react11.useMemo)(
|
|
1963
2041
|
() => ({
|
|
1964
2042
|
report,
|
|
1965
2043
|
// Narrative blocks render everywhere the report does (static SSR, the
|
|
@@ -1970,7 +2048,7 @@ function ReportRoot({
|
|
|
1970
2048
|
}),
|
|
1971
2049
|
[report, customRenderers, renderers]
|
|
1972
2050
|
);
|
|
1973
|
-
return /* @__PURE__ */ (0,
|
|
2051
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ReportContext.Provider, { value, children });
|
|
1974
2052
|
}
|
|
1975
2053
|
|
|
1976
2054
|
// src/lib/hash-state.ts
|
|
@@ -2156,7 +2234,7 @@ function listFailures(report) {
|
|
|
2156
2234
|
|
|
2157
2235
|
// src/interactive/ReportAgentFilterNotice.tsx
|
|
2158
2236
|
var import_lucide_react3 = require("lucide-react");
|
|
2159
|
-
var
|
|
2237
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2160
2238
|
function ReportAgentFilterNotice({
|
|
2161
2239
|
applied,
|
|
2162
2240
|
onReset,
|
|
@@ -2166,23 +2244,23 @@ function ReportAgentFilterNotice({
|
|
|
2166
2244
|
if (applied.search) terms.push(`matching \u201C${applied.search}\u201D`);
|
|
2167
2245
|
if (applied.status !== "all") terms.push(applied.status);
|
|
2168
2246
|
if (applied.tags.length > 0) terms.push(applied.tags.join(", "));
|
|
2169
|
-
return /* @__PURE__ */ (0,
|
|
2247
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
|
|
2170
2248
|
"div",
|
|
2171
2249
|
{
|
|
2172
2250
|
role: "status",
|
|
2173
2251
|
"aria-live": "polite",
|
|
2174
2252
|
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",
|
|
2175
2253
|
children: [
|
|
2176
|
-
/* @__PURE__ */ (0,
|
|
2177
|
-
/* @__PURE__ */ (0,
|
|
2254
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react3.Bot, { "aria-hidden": true, className: "size-4 shrink-0 text-primary" }),
|
|
2255
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "min-w-0 flex-1", children: [
|
|
2178
2256
|
"An agent filtered this report",
|
|
2179
|
-
terms.length > 0 ? /* @__PURE__ */ (0,
|
|
2257
|
+
terms.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
|
|
2180
2258
|
" to ",
|
|
2181
2259
|
terms.join(" \xB7 ")
|
|
2182
2260
|
] }) : null,
|
|
2183
2261
|
" \u2014",
|
|
2184
2262
|
" ",
|
|
2185
|
-
/* @__PURE__ */ (0,
|
|
2263
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "tabular-nums", children: [
|
|
2186
2264
|
applied.matched,
|
|
2187
2265
|
" of ",
|
|
2188
2266
|
applied.total,
|
|
@@ -2190,7 +2268,7 @@ function ReportAgentFilterNotice({
|
|
|
2190
2268
|
] }),
|
|
2191
2269
|
"."
|
|
2192
2270
|
] }),
|
|
2193
|
-
/* @__PURE__ */ (0,
|
|
2271
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2194
2272
|
"button",
|
|
2195
2273
|
{
|
|
2196
2274
|
type: "button",
|
|
@@ -2199,14 +2277,14 @@ function ReportAgentFilterNotice({
|
|
|
2199
2277
|
children: "Show all"
|
|
2200
2278
|
}
|
|
2201
2279
|
),
|
|
2202
|
-
/* @__PURE__ */ (0,
|
|
2280
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2203
2281
|
"button",
|
|
2204
2282
|
{
|
|
2205
2283
|
type: "button",
|
|
2206
2284
|
onClick: onDismiss,
|
|
2207
2285
|
"aria-label": "Dismiss",
|
|
2208
2286
|
className: "cursor-pointer rounded-md p-1 text-muted-foreground hover:text-foreground",
|
|
2209
|
-
children: /* @__PURE__ */ (0,
|
|
2287
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react3.X, { "aria-hidden": true, className: "size-4" })
|
|
2210
2288
|
}
|
|
2211
2289
|
)
|
|
2212
2290
|
]
|
|
@@ -2215,16 +2293,16 @@ function ReportAgentFilterNotice({
|
|
|
2215
2293
|
}
|
|
2216
2294
|
|
|
2217
2295
|
// src/interactive/ReportFailureBanner.tsx
|
|
2218
|
-
var
|
|
2219
|
-
var
|
|
2296
|
+
var import_react12 = require("react");
|
|
2297
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2220
2298
|
function ReportFailureBanner({ failures, onCopyAll }) {
|
|
2221
2299
|
const first = failures[0];
|
|
2222
|
-
const jumpToFirst = (0,
|
|
2300
|
+
const jumpToFirst = (0, import_react12.useCallback)(() => {
|
|
2223
2301
|
if (!first) return;
|
|
2224
2302
|
scrollToScenarioId(first.scenarioId);
|
|
2225
2303
|
}, [first]);
|
|
2226
2304
|
if (failures.length === 0) return null;
|
|
2227
|
-
return /* @__PURE__ */ (0,
|
|
2305
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
2228
2306
|
"div",
|
|
2229
2307
|
{
|
|
2230
2308
|
className: "es-failure-banner",
|
|
@@ -2232,13 +2310,13 @@ function ReportFailureBanner({ failures, onCopyAll }) {
|
|
|
2232
2310
|
"aria-live": "polite",
|
|
2233
2311
|
"aria-label": "Failure summary",
|
|
2234
2312
|
children: [
|
|
2235
|
-
/* @__PURE__ */ (0,
|
|
2236
|
-
/* @__PURE__ */ (0,
|
|
2313
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "es-failure-banner-text", children: [
|
|
2314
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: failures.length }),
|
|
2237
2315
|
" ",
|
|
2238
2316
|
"failure",
|
|
2239
2317
|
failures.length === 1 ? "" : "s"
|
|
2240
2318
|
] }),
|
|
2241
|
-
/* @__PURE__ */ (0,
|
|
2319
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2242
2320
|
"button",
|
|
2243
2321
|
{
|
|
2244
2322
|
type: "button",
|
|
@@ -2248,7 +2326,7 @@ function ReportFailureBanner({ failures, onCopyAll }) {
|
|
|
2248
2326
|
children: "View first failure \u2193"
|
|
2249
2327
|
}
|
|
2250
2328
|
),
|
|
2251
|
-
onCopyAll ? /* @__PURE__ */ (0,
|
|
2329
|
+
onCopyAll ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
2252
2330
|
"button",
|
|
2253
2331
|
{
|
|
2254
2332
|
type: "button",
|
|
@@ -2270,8 +2348,8 @@ function ReportFailureBanner({ failures, onCopyAll }) {
|
|
|
2270
2348
|
}
|
|
2271
2349
|
|
|
2272
2350
|
// src/interactive/ReportFilters.tsx
|
|
2273
|
-
var
|
|
2274
|
-
var
|
|
2351
|
+
var import_react13 = require("react");
|
|
2352
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2275
2353
|
var TAG_LIMIT = 12;
|
|
2276
2354
|
function ReportFilters({
|
|
2277
2355
|
statuses,
|
|
@@ -2281,14 +2359,14 @@ function ReportFilters({
|
|
|
2281
2359
|
activeTags,
|
|
2282
2360
|
onToggleTag
|
|
2283
2361
|
}) {
|
|
2284
|
-
const [showAllTags, setShowAllTags] = (0,
|
|
2362
|
+
const [showAllTags, setShowAllTags] = (0, import_react13.useState)(false);
|
|
2285
2363
|
if (statuses.length === 0 && tags.length === 0) return null;
|
|
2286
2364
|
const tagsCollapsed = tags.length > TAG_LIMIT && !showAllTags;
|
|
2287
2365
|
const visibleTags = tagsCollapsed ? tags.slice(0, TAG_LIMIT) : tags;
|
|
2288
|
-
return /* @__PURE__ */ (0,
|
|
2289
|
-
statuses.length > 0 ? /* @__PURE__ */ (0,
|
|
2366
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
2367
|
+
statuses.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { role: "group", "aria-label": "Filter by status", className: "flex flex-wrap gap-1", children: statuses.map((opt) => {
|
|
2290
2368
|
const active = status === opt.key;
|
|
2291
|
-
return /* @__PURE__ */ (0,
|
|
2369
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
2292
2370
|
"button",
|
|
2293
2371
|
{
|
|
2294
2372
|
type: "button",
|
|
@@ -2300,23 +2378,23 @@ function ReportFilters({
|
|
|
2300
2378
|
),
|
|
2301
2379
|
children: [
|
|
2302
2380
|
opt.label,
|
|
2303
|
-
/* @__PURE__ */ (0,
|
|
2381
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "ml-1 font-mono opacity-70", children: opt.count })
|
|
2304
2382
|
]
|
|
2305
2383
|
},
|
|
2306
2384
|
opt.key
|
|
2307
2385
|
);
|
|
2308
2386
|
}) }) : null,
|
|
2309
|
-
tags.length > 0 ? /* @__PURE__ */ (0,
|
|
2387
|
+
tags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("ul", { "aria-label": "Filter by tag", className: "flex flex-wrap items-center gap-1.5", children: [
|
|
2310
2388
|
visibleTags.map((tag) => {
|
|
2311
2389
|
const active = activeTags.includes(tag);
|
|
2312
|
-
return /* @__PURE__ */ (0,
|
|
2390
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2313
2391
|
"button",
|
|
2314
2392
|
{
|
|
2315
2393
|
type: "button",
|
|
2316
2394
|
"aria-pressed": active,
|
|
2317
2395
|
onClick: () => onToggleTag(tag),
|
|
2318
2396
|
className: "cursor-pointer",
|
|
2319
|
-
children: /* @__PURE__ */ (0,
|
|
2397
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2320
2398
|
Badge,
|
|
2321
2399
|
{
|
|
2322
2400
|
variant: "tag",
|
|
@@ -2329,7 +2407,7 @@ function ReportFilters({
|
|
|
2329
2407
|
}
|
|
2330
2408
|
) }, tag);
|
|
2331
2409
|
}),
|
|
2332
|
-
tags.length > TAG_LIMIT ? /* @__PURE__ */ (0,
|
|
2410
|
+
tags.length > TAG_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2333
2411
|
"button",
|
|
2334
2412
|
{
|
|
2335
2413
|
type: "button",
|
|
@@ -2344,16 +2422,16 @@ function ReportFilters({
|
|
|
2344
2422
|
}
|
|
2345
2423
|
|
|
2346
2424
|
// src/interactive/ReportFreshness.tsx
|
|
2347
|
-
var
|
|
2348
|
-
var
|
|
2425
|
+
var import_react14 = require("react");
|
|
2426
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2349
2427
|
function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
2350
|
-
const [now, setNow] = (0,
|
|
2351
|
-
(0,
|
|
2428
|
+
const [now, setNow] = (0, import_react14.useState)(nowMs);
|
|
2429
|
+
(0, import_react14.useEffect)(() => {
|
|
2352
2430
|
if (nowMs === void 0) setNow(Date.now());
|
|
2353
2431
|
}, [nowMs]);
|
|
2354
2432
|
if (lastRunMs === void 0 || now === void 0) return null;
|
|
2355
2433
|
const age = formatRelativeAge(lastRunMs, now);
|
|
2356
|
-
const runLink = ciUrl ? /* @__PURE__ */ (0,
|
|
2434
|
+
const runLink = ciUrl ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2357
2435
|
"a",
|
|
2358
2436
|
{
|
|
2359
2437
|
href: ciUrl,
|
|
@@ -2364,9 +2442,9 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2364
2442
|
}
|
|
2365
2443
|
) : null;
|
|
2366
2444
|
if (isReportStale(lastRunMs, staleAfterDays, now)) {
|
|
2367
|
-
return /* @__PURE__ */ (0,
|
|
2368
|
-
/* @__PURE__ */ (0,
|
|
2369
|
-
/* @__PURE__ */ (0,
|
|
2445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "es-stale-banner", role: "status", "aria-label": "Report freshness", children: [
|
|
2446
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { children: [
|
|
2447
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("strong", { children: [
|
|
2370
2448
|
"Last verified ",
|
|
2371
2449
|
age,
|
|
2372
2450
|
"."
|
|
@@ -2376,10 +2454,10 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2376
2454
|
runLink
|
|
2377
2455
|
] });
|
|
2378
2456
|
}
|
|
2379
|
-
return /* @__PURE__ */ (0,
|
|
2457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("p", { className: "es-freshness", "aria-label": "Report freshness", children: [
|
|
2380
2458
|
"Verified ",
|
|
2381
2459
|
age,
|
|
2382
|
-
runLink ? /* @__PURE__ */ (0,
|
|
2460
|
+
runLink ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
|
|
2383
2461
|
" \xB7 ",
|
|
2384
2462
|
runLink
|
|
2385
2463
|
] }) : null
|
|
@@ -2387,15 +2465,15 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2387
2465
|
}
|
|
2388
2466
|
|
|
2389
2467
|
// src/interactive/ReportLastRunDelta.tsx
|
|
2390
|
-
var
|
|
2468
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2391
2469
|
var MAX_LINKS = 5;
|
|
2392
2470
|
function ScenarioLinks({ scenarios, tone }) {
|
|
2393
|
-
return /* @__PURE__ */ (0,
|
|
2394
|
-
scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ (0,
|
|
2471
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
|
|
2472
|
+
scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { children: [
|
|
2395
2473
|
i > 0 ? ", " : "",
|
|
2396
|
-
/* @__PURE__ */ (0,
|
|
2474
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
|
|
2397
2475
|
] }, s.id)),
|
|
2398
|
-
scenarios.length > MAX_LINKS ? /* @__PURE__ */ (0,
|
|
2476
|
+
scenarios.length > MAX_LINKS ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { children: [
|
|
2399
2477
|
" and ",
|
|
2400
2478
|
scenarios.length - MAX_LINKS,
|
|
2401
2479
|
" more"
|
|
@@ -2412,23 +2490,23 @@ function ReportLastRunDelta({
|
|
|
2412
2490
|
if (!delta) return null;
|
|
2413
2491
|
const { newlyFailing, newlyPassing, added } = delta;
|
|
2414
2492
|
if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) {
|
|
2415
|
-
return /* @__PURE__ */ (0,
|
|
2493
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: "Since last run: no behavior changes." });
|
|
2416
2494
|
}
|
|
2417
|
-
return /* @__PURE__ */ (0,
|
|
2418
|
-
/* @__PURE__ */ (0,
|
|
2419
|
-
newlyFailing.length > 0 ? /* @__PURE__ */ (0,
|
|
2495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: [
|
|
2496
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "font-medium text-foreground", children: "Since last run:" }),
|
|
2497
|
+
newlyFailing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "ml-2 text-fail", children: [
|
|
2420
2498
|
newlyFailing.length,
|
|
2421
2499
|
" newly failing (",
|
|
2422
|
-
/* @__PURE__ */ (0,
|
|
2500
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ScenarioLinks, { scenarios: newlyFailing, tone: "text-fail" }),
|
|
2423
2501
|
")"
|
|
2424
2502
|
] }) : null,
|
|
2425
|
-
newlyPassing.length > 0 ? /* @__PURE__ */ (0,
|
|
2503
|
+
newlyPassing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "ml-2 text-pass", children: [
|
|
2426
2504
|
newlyPassing.length,
|
|
2427
2505
|
" fixed (",
|
|
2428
|
-
/* @__PURE__ */ (0,
|
|
2506
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ScenarioLinks, { scenarios: newlyPassing, tone: "text-pass" }),
|
|
2429
2507
|
")"
|
|
2430
2508
|
] }) : null,
|
|
2431
|
-
added.length > 0 ? /* @__PURE__ */ (0,
|
|
2509
|
+
added.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "ml-2", children: [
|
|
2432
2510
|
added.length,
|
|
2433
2511
|
" new"
|
|
2434
2512
|
] }) : null
|
|
@@ -2436,14 +2514,14 @@ function ReportLastRunDelta({
|
|
|
2436
2514
|
}
|
|
2437
2515
|
|
|
2438
2516
|
// src/interactive/ReportSearch.tsx
|
|
2439
|
-
var
|
|
2517
|
+
var import_react15 = require("react");
|
|
2440
2518
|
var import_lucide_react4 = require("lucide-react");
|
|
2441
2519
|
|
|
2442
2520
|
// src/components/ui/input.tsx
|
|
2443
2521
|
var React6 = require("react");
|
|
2444
|
-
var
|
|
2522
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2445
2523
|
function Input({ className, type, ...props }) {
|
|
2446
|
-
return /* @__PURE__ */ (0,
|
|
2524
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2447
2525
|
"input",
|
|
2448
2526
|
{
|
|
2449
2527
|
type,
|
|
@@ -2460,8 +2538,8 @@ function Input({ className, type, ...props }) {
|
|
|
2460
2538
|
}
|
|
2461
2539
|
|
|
2462
2540
|
// src/interactive/ReportSearch.tsx
|
|
2463
|
-
var
|
|
2464
|
-
var ReportSearch = (0,
|
|
2541
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2542
|
+
var ReportSearch = (0, import_react15.forwardRef)(
|
|
2465
2543
|
function ReportSearch2(props, ref) {
|
|
2466
2544
|
const {
|
|
2467
2545
|
value,
|
|
@@ -2471,7 +2549,7 @@ var ReportSearch = (0, import_react13.forwardRef)(
|
|
|
2471
2549
|
placeholder = "Search scenarios, tags, tickets, errors\u2026",
|
|
2472
2550
|
className
|
|
2473
2551
|
} = props;
|
|
2474
|
-
const inputId = (0,
|
|
2552
|
+
const inputId = (0, import_react15.useId)();
|
|
2475
2553
|
const showCounts = value.trim().length > 0 && typeof matchedCount === "number" && typeof totalCount === "number";
|
|
2476
2554
|
function handleChange(e) {
|
|
2477
2555
|
onChange(e.target.value);
|
|
@@ -2482,17 +2560,17 @@ var ReportSearch = (0, import_react13.forwardRef)(
|
|
|
2482
2560
|
e.preventDefault();
|
|
2483
2561
|
}
|
|
2484
2562
|
}
|
|
2485
|
-
return /* @__PURE__ */ (0,
|
|
2486
|
-
/* @__PURE__ */ (0,
|
|
2487
|
-
/* @__PURE__ */ (0,
|
|
2488
|
-
/* @__PURE__ */ (0,
|
|
2563
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: cn("es-search flex flex-col gap-1", className), children: [
|
|
2564
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("label", { htmlFor: inputId, className: "sr-only", children: "Search" }),
|
|
2565
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "relative w-full sm:w-72", children: [
|
|
2566
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2489
2567
|
import_lucide_react4.Search,
|
|
2490
2568
|
{
|
|
2491
2569
|
"aria-hidden": true,
|
|
2492
2570
|
className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
|
|
2493
2571
|
}
|
|
2494
2572
|
),
|
|
2495
|
-
/* @__PURE__ */ (0,
|
|
2573
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2496
2574
|
Input,
|
|
2497
2575
|
{
|
|
2498
2576
|
ref,
|
|
@@ -2509,7 +2587,7 @@ var ReportSearch = (0, import_react13.forwardRef)(
|
|
|
2509
2587
|
}
|
|
2510
2588
|
)
|
|
2511
2589
|
] }),
|
|
2512
|
-
showCounts ? /* @__PURE__ */ (0,
|
|
2590
|
+
showCounts ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
2513
2591
|
"span",
|
|
2514
2592
|
{
|
|
2515
2593
|
className: "text-xs tabular-nums text-muted-foreground",
|
|
@@ -2526,8 +2604,138 @@ var ReportSearch = (0, import_react13.forwardRef)(
|
|
|
2526
2604
|
}
|
|
2527
2605
|
);
|
|
2528
2606
|
|
|
2607
|
+
// src/interactive/ReportShare.tsx
|
|
2608
|
+
var import_lucide_react5 = require("lucide-react");
|
|
2609
|
+
var import_react16 = require("react");
|
|
2610
|
+
|
|
2611
|
+
// src/components/ui/button.tsx
|
|
2612
|
+
var React7 = require("react");
|
|
2613
|
+
var import_class_variance_authority4 = require("class-variance-authority");
|
|
2614
|
+
var import_use_render2 = require("@base-ui/react/use-render");
|
|
2615
|
+
var buttonVariants = (0, import_class_variance_authority4.cva)(
|
|
2616
|
+
"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",
|
|
2617
|
+
{
|
|
2618
|
+
variants: {
|
|
2619
|
+
variant: {
|
|
2620
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
2621
|
+
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
|
|
2622
|
+
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",
|
|
2623
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
2624
|
+
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
2625
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
2626
|
+
},
|
|
2627
|
+
size: {
|
|
2628
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
2629
|
+
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
2630
|
+
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
|
|
2631
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
2632
|
+
icon: "size-9",
|
|
2633
|
+
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
2634
|
+
"icon-sm": "size-8",
|
|
2635
|
+
"icon-lg": "size-10"
|
|
2636
|
+
}
|
|
2637
|
+
},
|
|
2638
|
+
defaultVariants: {
|
|
2639
|
+
variant: "default",
|
|
2640
|
+
size: "default"
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
);
|
|
2644
|
+
function Button({
|
|
2645
|
+
className,
|
|
2646
|
+
variant = "default",
|
|
2647
|
+
size = "default",
|
|
2648
|
+
render,
|
|
2649
|
+
...props
|
|
2650
|
+
}) {
|
|
2651
|
+
return (0, import_use_render2.useRender)({
|
|
2652
|
+
defaultTagName: "button",
|
|
2653
|
+
render,
|
|
2654
|
+
props: {
|
|
2655
|
+
"data-slot": "button",
|
|
2656
|
+
"data-variant": variant,
|
|
2657
|
+
"data-size": size,
|
|
2658
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
2659
|
+
...props
|
|
2660
|
+
}
|
|
2661
|
+
});
|
|
2662
|
+
}
|
|
2663
|
+
|
|
2664
|
+
// src/interactive/ReportShare.tsx
|
|
2665
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2666
|
+
var DEFAULT_SHARE_COMMAND = "npx executable-stories share reports/";
|
|
2667
|
+
function ReportShare({
|
|
2668
|
+
command = DEFAULT_SHARE_COMMAND,
|
|
2669
|
+
onCopy
|
|
2670
|
+
}) {
|
|
2671
|
+
const [open, setOpen] = (0, import_react16.useState)(false);
|
|
2672
|
+
const dialogRef = (0, import_react16.useRef)(null);
|
|
2673
|
+
(0, import_react16.useEffect)(() => {
|
|
2674
|
+
const dialog = dialogRef.current;
|
|
2675
|
+
if (!dialog) return;
|
|
2676
|
+
if (open && !dialog.open) dialog.showModal();
|
|
2677
|
+
else if (!open && dialog.open) dialog.close();
|
|
2678
|
+
}, [open]);
|
|
2679
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
|
|
2680
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
2681
|
+
Button,
|
|
2682
|
+
{
|
|
2683
|
+
type: "button",
|
|
2684
|
+
variant: "ghost",
|
|
2685
|
+
size: "sm",
|
|
2686
|
+
"aria-label": "Share this report",
|
|
2687
|
+
title: "Share this report",
|
|
2688
|
+
onClick: () => setOpen(true),
|
|
2689
|
+
children: [
|
|
2690
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_lucide_react5.Share2, { "aria-hidden": "true", className: "size-4" }),
|
|
2691
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "sr-only sm:not-sr-only", children: "Share" })
|
|
2692
|
+
]
|
|
2693
|
+
}
|
|
2694
|
+
),
|
|
2695
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
2696
|
+
"dialog",
|
|
2697
|
+
{
|
|
2698
|
+
ref: dialogRef,
|
|
2699
|
+
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",
|
|
2700
|
+
"aria-label": "Share this report",
|
|
2701
|
+
onClose: () => setOpen(false),
|
|
2702
|
+
children: [
|
|
2703
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("h2", { className: "text-base font-semibold", children: "Share this report" }),
|
|
2704
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("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:" }),
|
|
2705
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "mt-4 flex items-center gap-2", children: [
|
|
2706
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("code", { className: "min-w-0 flex-1 truncate rounded border border-border bg-muted px-3 py-2 font-mono text-xs", children: command }),
|
|
2707
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2708
|
+
Button,
|
|
2709
|
+
{
|
|
2710
|
+
type: "button",
|
|
2711
|
+
size: "sm",
|
|
2712
|
+
onClick: () => onCopy(command, "Command copied"),
|
|
2713
|
+
children: "Copy"
|
|
2714
|
+
}
|
|
2715
|
+
)
|
|
2716
|
+
] }),
|
|
2717
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("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." }),
|
|
2718
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "mt-6 flex items-center justify-between gap-4", children: [
|
|
2719
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2720
|
+
"a",
|
|
2721
|
+
{
|
|
2722
|
+
className: "text-xs underline underline-offset-2",
|
|
2723
|
+
href: "https://executablestories.com/guides/sharing-reports/",
|
|
2724
|
+
target: "_blank",
|
|
2725
|
+
rel: "noreferrer",
|
|
2726
|
+
children: "How sharing works"
|
|
2727
|
+
}
|
|
2728
|
+
),
|
|
2729
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setOpen(false), children: "Close" })
|
|
2730
|
+
] })
|
|
2731
|
+
]
|
|
2732
|
+
}
|
|
2733
|
+
)
|
|
2734
|
+
] });
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2529
2737
|
// src/interactive/ReportSinceLastVisit.tsx
|
|
2530
|
-
var
|
|
2738
|
+
var import_react17 = require("react");
|
|
2531
2739
|
|
|
2532
2740
|
// src/interactive/last-visit.ts
|
|
2533
2741
|
function snapshotOf(report, atMs) {
|
|
@@ -2563,7 +2771,7 @@ function diffSinceVisit(previous, report) {
|
|
|
2563
2771
|
}
|
|
2564
2772
|
|
|
2565
2773
|
// src/interactive/ReportSinceLastVisit.tsx
|
|
2566
|
-
var
|
|
2774
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
2567
2775
|
var KEY = "es-last-visit";
|
|
2568
2776
|
var MAX_LINKS2 = 5;
|
|
2569
2777
|
function readVisit() {
|
|
@@ -2588,12 +2796,12 @@ function writeVisit(snapshot) {
|
|
|
2588
2796
|
}
|
|
2589
2797
|
}
|
|
2590
2798
|
function ScenarioLinks2({ scenarios, tone }) {
|
|
2591
|
-
return /* @__PURE__ */ (0,
|
|
2592
|
-
scenarios.slice(0, MAX_LINKS2).map((s, i) => /* @__PURE__ */ (0,
|
|
2799
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
|
|
2800
|
+
scenarios.slice(0, MAX_LINKS2).map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { children: [
|
|
2593
2801
|
i > 0 ? ", " : "",
|
|
2594
|
-
/* @__PURE__ */ (0,
|
|
2802
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
|
|
2595
2803
|
] }, s.id)),
|
|
2596
|
-
scenarios.length > MAX_LINKS2 ? /* @__PURE__ */ (0,
|
|
2804
|
+
scenarios.length > MAX_LINKS2 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { children: [
|
|
2597
2805
|
" and ",
|
|
2598
2806
|
scenarios.length - MAX_LINKS2,
|
|
2599
2807
|
" more"
|
|
@@ -2601,9 +2809,9 @@ function ScenarioLinks2({ scenarios, tone }) {
|
|
|
2601
2809
|
] });
|
|
2602
2810
|
}
|
|
2603
2811
|
function ReportSinceLastVisit({ report }) {
|
|
2604
|
-
const [delta, setDelta] = (0,
|
|
2605
|
-
const [nowMs, setNowMs] = (0,
|
|
2606
|
-
(0,
|
|
2812
|
+
const [delta, setDelta] = (0, import_react17.useState)(null);
|
|
2813
|
+
const [nowMs, setNowMs] = (0, import_react17.useState)(0);
|
|
2814
|
+
(0, import_react17.useEffect)(() => {
|
|
2607
2815
|
const now = Date.now();
|
|
2608
2816
|
setDelta(diffSinceVisit(readVisit(), report));
|
|
2609
2817
|
setNowMs(now);
|
|
@@ -2611,25 +2819,25 @@ function ReportSinceLastVisit({ report }) {
|
|
|
2611
2819
|
}, [report]);
|
|
2612
2820
|
if (!delta) return null;
|
|
2613
2821
|
const { newlyFailing, newlyPassing, added } = delta;
|
|
2614
|
-
return /* @__PURE__ */ (0,
|
|
2615
|
-
/* @__PURE__ */ (0,
|
|
2822
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-since-last-visit", children: [
|
|
2823
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "font-medium text-foreground", children: [
|
|
2616
2824
|
"Since your last visit (",
|
|
2617
2825
|
formatRelativeAge(delta.sinceMs, nowMs),
|
|
2618
2826
|
"):"
|
|
2619
2827
|
] }),
|
|
2620
|
-
newlyFailing.length > 0 ? /* @__PURE__ */ (0,
|
|
2828
|
+
newlyFailing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "ml-2 text-fail", children: [
|
|
2621
2829
|
newlyFailing.length,
|
|
2622
2830
|
" started failing (",
|
|
2623
|
-
/* @__PURE__ */ (0,
|
|
2831
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ScenarioLinks2, { scenarios: newlyFailing, tone: "text-fail" }),
|
|
2624
2832
|
")"
|
|
2625
2833
|
] }) : null,
|
|
2626
|
-
newlyPassing.length > 0 ? /* @__PURE__ */ (0,
|
|
2834
|
+
newlyPassing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "ml-2 text-pass", children: [
|
|
2627
2835
|
newlyPassing.length,
|
|
2628
2836
|
" fixed (",
|
|
2629
|
-
/* @__PURE__ */ (0,
|
|
2837
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ScenarioLinks2, { scenarios: newlyPassing, tone: "text-pass" }),
|
|
2630
2838
|
")"
|
|
2631
2839
|
] }) : null,
|
|
2632
|
-
added.length > 0 ? /* @__PURE__ */ (0,
|
|
2840
|
+
added.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "ml-2", children: [
|
|
2633
2841
|
added.length,
|
|
2634
2842
|
" new"
|
|
2635
2843
|
] }) : null
|
|
@@ -2637,63 +2845,8 @@ function ReportSinceLastVisit({ report }) {
|
|
|
2637
2845
|
}
|
|
2638
2846
|
|
|
2639
2847
|
// src/interactive/ReportShortcutsHelp.tsx
|
|
2640
|
-
var
|
|
2641
|
-
|
|
2642
|
-
// src/components/ui/button.tsx
|
|
2643
|
-
var React7 = require("react");
|
|
2644
|
-
var import_class_variance_authority4 = require("class-variance-authority");
|
|
2645
|
-
var import_use_render2 = require("@base-ui/react/use-render");
|
|
2646
|
-
var buttonVariants = (0, import_class_variance_authority4.cva)(
|
|
2647
|
-
"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",
|
|
2648
|
-
{
|
|
2649
|
-
variants: {
|
|
2650
|
-
variant: {
|
|
2651
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
2652
|
-
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
|
|
2653
|
-
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",
|
|
2654
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
2655
|
-
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
2656
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
2657
|
-
},
|
|
2658
|
-
size: {
|
|
2659
|
-
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
2660
|
-
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
2661
|
-
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
|
|
2662
|
-
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
2663
|
-
icon: "size-9",
|
|
2664
|
-
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
2665
|
-
"icon-sm": "size-8",
|
|
2666
|
-
"icon-lg": "size-10"
|
|
2667
|
-
}
|
|
2668
|
-
},
|
|
2669
|
-
defaultVariants: {
|
|
2670
|
-
variant: "default",
|
|
2671
|
-
size: "default"
|
|
2672
|
-
}
|
|
2673
|
-
}
|
|
2674
|
-
);
|
|
2675
|
-
function Button({
|
|
2676
|
-
className,
|
|
2677
|
-
variant = "default",
|
|
2678
|
-
size = "default",
|
|
2679
|
-
render,
|
|
2680
|
-
...props
|
|
2681
|
-
}) {
|
|
2682
|
-
return (0, import_use_render2.useRender)({
|
|
2683
|
-
defaultTagName: "button",
|
|
2684
|
-
render,
|
|
2685
|
-
props: {
|
|
2686
|
-
"data-slot": "button",
|
|
2687
|
-
"data-variant": variant,
|
|
2688
|
-
"data-size": size,
|
|
2689
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
2690
|
-
...props
|
|
2691
|
-
}
|
|
2692
|
-
});
|
|
2693
|
-
}
|
|
2694
|
-
|
|
2695
|
-
// src/interactive/ReportShortcutsHelp.tsx
|
|
2696
|
-
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2848
|
+
var import_react18 = require("react");
|
|
2849
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
2697
2850
|
var SHORTCUTS = [
|
|
2698
2851
|
{ keys: "/", description: "Focus search" },
|
|
2699
2852
|
{ keys: "f", description: "Jump to next failure" },
|
|
@@ -2705,20 +2858,20 @@ var SHORTCUTS = [
|
|
|
2705
2858
|
];
|
|
2706
2859
|
function Keys({ keys }) {
|
|
2707
2860
|
const parts = keys.split(" ");
|
|
2708
|
-
return /* @__PURE__ */ (0,
|
|
2709
|
-
i > 0 ? /* @__PURE__ */ (0,
|
|
2710
|
-
/* @__PURE__ */ (0,
|
|
2861
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "inline-flex items-center gap-1", children: parts.map((k, i) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "inline-flex items-center gap-1", children: [
|
|
2862
|
+
i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "text-xs text-muted-foreground", children: "+" }) : null,
|
|
2863
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("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 })
|
|
2711
2864
|
] }, k)) });
|
|
2712
2865
|
}
|
|
2713
2866
|
function ReportShortcutsHelp({ open, onClose }) {
|
|
2714
|
-
const dialogRef = (0,
|
|
2715
|
-
(0,
|
|
2867
|
+
const dialogRef = (0, import_react18.useRef)(null);
|
|
2868
|
+
(0, import_react18.useEffect)(() => {
|
|
2716
2869
|
const dialog = dialogRef.current;
|
|
2717
2870
|
if (!dialog) return;
|
|
2718
2871
|
if (open && !dialog.open) dialog.showModal();
|
|
2719
2872
|
else if (!open && dialog.open) dialog.close();
|
|
2720
2873
|
}, [open]);
|
|
2721
|
-
return /* @__PURE__ */ (0,
|
|
2874
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
2722
2875
|
"dialog",
|
|
2723
2876
|
{
|
|
2724
2877
|
ref: dialogRef,
|
|
@@ -2726,20 +2879,20 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2726
2879
|
"aria-label": "Keyboard shortcuts",
|
|
2727
2880
|
onClose,
|
|
2728
2881
|
children: [
|
|
2729
|
-
/* @__PURE__ */ (0,
|
|
2730
|
-
/* @__PURE__ */ (0,
|
|
2731
|
-
/* @__PURE__ */ (0,
|
|
2732
|
-
/* @__PURE__ */ (0,
|
|
2882
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("h2", { className: "text-base font-semibold", children: "Keyboard shortcuts" }),
|
|
2883
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("dl", { className: "mt-4 grid grid-cols-[auto_1fr] items-center gap-x-4 gap-y-2.5", children: SHORTCUTS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "col-span-2 grid grid-cols-subgrid items-center", children: [
|
|
2884
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("dt", { className: "justify-self-start", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Keys, { keys: s.keys }) }),
|
|
2885
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("dd", { className: "text-sm text-muted-foreground", children: s.description })
|
|
2733
2886
|
] }, s.keys)) }),
|
|
2734
|
-
/* @__PURE__ */ (0,
|
|
2887
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("form", { method: "dialog", className: "mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Button, { type: "submit", variant: "outline", size: "sm", children: "Close" }) })
|
|
2735
2888
|
]
|
|
2736
2889
|
}
|
|
2737
2890
|
);
|
|
2738
2891
|
}
|
|
2739
2892
|
|
|
2740
2893
|
// src/interactive/ReportToc.tsx
|
|
2741
|
-
var
|
|
2742
|
-
var
|
|
2894
|
+
var import_react19 = require("react");
|
|
2895
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
2743
2896
|
var DOT = {
|
|
2744
2897
|
passed: "bg-pass",
|
|
2745
2898
|
failed: "bg-fail",
|
|
@@ -2748,12 +2901,12 @@ var DOT = {
|
|
|
2748
2901
|
};
|
|
2749
2902
|
function TocContent({ onNavigate }) {
|
|
2750
2903
|
const report = useReport();
|
|
2751
|
-
const [activeId, setActiveId] = (0,
|
|
2752
|
-
const scenarioIds = (0,
|
|
2904
|
+
const [activeId, setActiveId] = (0, import_react19.useState)(null);
|
|
2905
|
+
const scenarioIds = (0, import_react19.useMemo)(
|
|
2753
2906
|
() => report.features.flatMap((f) => f.scenarios.map((s) => s.id)),
|
|
2754
2907
|
[report]
|
|
2755
2908
|
);
|
|
2756
|
-
(0,
|
|
2909
|
+
(0, import_react19.useEffect)(() => {
|
|
2757
2910
|
if (typeof IntersectionObserver === "undefined") return;
|
|
2758
2911
|
const els = scenarioIds.map((id) => document.getElementById(id)).filter((el) => el !== null);
|
|
2759
2912
|
if (els.length === 0) return;
|
|
@@ -2768,11 +2921,11 @@ function TocContent({ onNavigate }) {
|
|
|
2768
2921
|
return () => observer.disconnect();
|
|
2769
2922
|
}, [scenarioIds]);
|
|
2770
2923
|
if (report.features.length === 0) return null;
|
|
2771
|
-
return /* @__PURE__ */ (0,
|
|
2772
|
-
/* @__PURE__ */ (0,
|
|
2773
|
-
/* @__PURE__ */ (0,
|
|
2924
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("ul", { className: "flex list-none flex-col gap-4 pl-0", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("li", { children: [
|
|
2925
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
|
|
2926
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("ul", { className: "flex list-none flex-col gap-0.5 pl-0", children: feature.scenarios.map((scenario) => {
|
|
2774
2927
|
const active = activeId === scenario.id;
|
|
2775
|
-
return /* @__PURE__ */ (0,
|
|
2928
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
2776
2929
|
"a",
|
|
2777
2930
|
{
|
|
2778
2931
|
href: `#${scenario.id}`,
|
|
@@ -2787,14 +2940,14 @@ function TocContent({ onNavigate }) {
|
|
|
2787
2940
|
active ? "border-primary font-medium text-foreground" : "border-border text-muted-foreground"
|
|
2788
2941
|
),
|
|
2789
2942
|
children: [
|
|
2790
|
-
/* @__PURE__ */ (0,
|
|
2943
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
2791
2944
|
"span",
|
|
2792
2945
|
{
|
|
2793
2946
|
"aria-hidden": true,
|
|
2794
2947
|
className: cn("mt-1 size-1.5 shrink-0 rounded-full", DOT[scenario.status])
|
|
2795
2948
|
}
|
|
2796
2949
|
),
|
|
2797
|
-
/* @__PURE__ */ (0,
|
|
2950
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "break-words", children: scenario.title })
|
|
2798
2951
|
]
|
|
2799
2952
|
}
|
|
2800
2953
|
) }, scenario.id);
|
|
@@ -2804,48 +2957,48 @@ function TocContent({ onNavigate }) {
|
|
|
2804
2957
|
function ReportToc() {
|
|
2805
2958
|
const report = useReport();
|
|
2806
2959
|
if (report.features.length === 0) return null;
|
|
2807
|
-
return /* @__PURE__ */ (0,
|
|
2960
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
2808
2961
|
"nav",
|
|
2809
2962
|
{
|
|
2810
2963
|
"aria-label": "Table of contents",
|
|
2811
2964
|
className: "sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block",
|
|
2812
2965
|
children: [
|
|
2813
|
-
/* @__PURE__ */ (0,
|
|
2814
|
-
/* @__PURE__ */ (0,
|
|
2966
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
|
|
2967
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(TocContent, {})
|
|
2815
2968
|
]
|
|
2816
2969
|
}
|
|
2817
2970
|
);
|
|
2818
2971
|
}
|
|
2819
2972
|
|
|
2820
2973
|
// src/interactive/ReportTocDrawer.tsx
|
|
2821
|
-
var
|
|
2974
|
+
var import_react20 = require("react");
|
|
2822
2975
|
var import_dialog = require("@base-ui/react/dialog");
|
|
2823
|
-
var
|
|
2824
|
-
var
|
|
2976
|
+
var import_lucide_react6 = require("lucide-react");
|
|
2977
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
2825
2978
|
function ReportTocDrawer() {
|
|
2826
2979
|
const report = useReport();
|
|
2827
|
-
const [open, setOpen] = (0,
|
|
2980
|
+
const [open, setOpen] = (0, import_react20.useState)(false);
|
|
2828
2981
|
if (report.features.length === 0) return null;
|
|
2829
|
-
return /* @__PURE__ */ (0,
|
|
2830
|
-
/* @__PURE__ */ (0,
|
|
2831
|
-
/* @__PURE__ */ (0,
|
|
2982
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_dialog.Dialog.Root, { open, onOpenChange: setOpen, children: [
|
|
2983
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_dialog.Dialog.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: [
|
|
2984
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react6.ListIcon, { "aria-hidden": true }),
|
|
2832
2985
|
" Contents"
|
|
2833
2986
|
] }),
|
|
2834
|
-
/* @__PURE__ */ (0,
|
|
2835
|
-
/* @__PURE__ */ (0,
|
|
2836
|
-
/* @__PURE__ */ (0,
|
|
2837
|
-
/* @__PURE__ */ (0,
|
|
2838
|
-
/* @__PURE__ */ (0,
|
|
2839
|
-
/* @__PURE__ */ (0,
|
|
2987
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_dialog.Dialog.Portal, { children: [
|
|
2988
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_dialog.Dialog.Backdrop, { className: "fixed inset-0 z-50 bg-black/50 transition-opacity duration-200 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0" }),
|
|
2989
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_dialog.Dialog.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: [
|
|
2990
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2991
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_dialog.Dialog.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
|
|
2992
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
2840
2993
|
import_dialog.Dialog.Close,
|
|
2841
2994
|
{
|
|
2842
2995
|
"aria-label": "Close contents",
|
|
2843
2996
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
2844
|
-
children: /* @__PURE__ */ (0,
|
|
2997
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react6.XIcon, { "aria-hidden": true })
|
|
2845
2998
|
}
|
|
2846
2999
|
)
|
|
2847
3000
|
] }),
|
|
2848
|
-
/* @__PURE__ */ (0,
|
|
3001
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(TocContent, { onNavigate: () => setOpen(false) })
|
|
2849
3002
|
] })
|
|
2850
3003
|
] })
|
|
2851
3004
|
] });
|
|
@@ -2879,10 +3032,10 @@ function failuresFirst(report) {
|
|
|
2879
3032
|
}
|
|
2880
3033
|
|
|
2881
3034
|
// src/interactive/use-deep-link-scroll.ts
|
|
2882
|
-
var
|
|
3035
|
+
var import_react21 = require("react");
|
|
2883
3036
|
function useDeepLinkScroll() {
|
|
2884
|
-
const lastAnchor = (0,
|
|
2885
|
-
(0,
|
|
3037
|
+
const lastAnchor = (0, import_react21.useRef)(null);
|
|
3038
|
+
(0, import_react21.useEffect)(() => {
|
|
2886
3039
|
function scrollToHash() {
|
|
2887
3040
|
const { anchor } = splitHash(window.location.hash);
|
|
2888
3041
|
if (!anchor || anchor === lastAnchor.current) return;
|
|
@@ -2898,7 +3051,7 @@ function useDeepLinkScroll() {
|
|
|
2898
3051
|
}
|
|
2899
3052
|
|
|
2900
3053
|
// src/interactive/use-keyboard-shortcuts.ts
|
|
2901
|
-
var
|
|
3054
|
+
var import_react22 = require("react");
|
|
2902
3055
|
function isEditableTarget(target) {
|
|
2903
3056
|
if (!(target instanceof HTMLElement)) return false;
|
|
2904
3057
|
const tag = target.tagName;
|
|
@@ -2907,9 +3060,9 @@ function isEditableTarget(target) {
|
|
|
2907
3060
|
return false;
|
|
2908
3061
|
}
|
|
2909
3062
|
function useKeyboardShortcuts(handlers) {
|
|
2910
|
-
const ref = (0,
|
|
3063
|
+
const ref = (0, import_react22.useRef)(handlers);
|
|
2911
3064
|
ref.current = handlers;
|
|
2912
|
-
(0,
|
|
3065
|
+
(0, import_react22.useEffect)(() => {
|
|
2913
3066
|
function onKeyDown(e) {
|
|
2914
3067
|
const h = ref.current;
|
|
2915
3068
|
if (e.key === "Escape") {
|
|
@@ -2953,7 +3106,7 @@ function useKeyboardShortcuts(handlers) {
|
|
|
2953
3106
|
}
|
|
2954
3107
|
|
|
2955
3108
|
// src/interactive/use-theme.ts
|
|
2956
|
-
var
|
|
3109
|
+
var import_react23 = require("react");
|
|
2957
3110
|
var KEY2 = "es-theme";
|
|
2958
3111
|
function systemDark() {
|
|
2959
3112
|
return typeof matchMedia !== "undefined" && matchMedia("(prefers-color-scheme: dark)").matches;
|
|
@@ -2974,13 +3127,13 @@ function initialPref() {
|
|
|
2974
3127
|
return "system";
|
|
2975
3128
|
}
|
|
2976
3129
|
function useTheme() {
|
|
2977
|
-
const [pref, setPrefState] = (0,
|
|
2978
|
-
(0,
|
|
3130
|
+
const [pref, setPrefState] = (0, import_react23.useState)("system");
|
|
3131
|
+
(0, import_react23.useEffect)(() => {
|
|
2979
3132
|
const p = initialPref();
|
|
2980
3133
|
setPrefState(p);
|
|
2981
3134
|
applyTheme(p);
|
|
2982
3135
|
}, []);
|
|
2983
|
-
(0,
|
|
3136
|
+
(0, import_react23.useEffect)(() => {
|
|
2984
3137
|
if (typeof matchMedia === "undefined") return;
|
|
2985
3138
|
const mq = matchMedia("(prefers-color-scheme: dark)");
|
|
2986
3139
|
const onChange = () => {
|
|
@@ -2989,7 +3142,7 @@ function useTheme() {
|
|
|
2989
3142
|
mq.addEventListener("change", onChange);
|
|
2990
3143
|
return () => mq.removeEventListener("change", onChange);
|
|
2991
3144
|
}, [pref]);
|
|
2992
|
-
const setPref = (0,
|
|
3145
|
+
const setPref = (0, import_react23.useCallback)((p) => {
|
|
2993
3146
|
setPrefState(p);
|
|
2994
3147
|
applyTheme(p);
|
|
2995
3148
|
try {
|
|
@@ -3001,19 +3154,19 @@ function useTheme() {
|
|
|
3001
3154
|
}
|
|
3002
3155
|
|
|
3003
3156
|
// src/interactive/use-url-state.ts
|
|
3004
|
-
var
|
|
3157
|
+
var import_react24 = require("react");
|
|
3005
3158
|
var WRITE_DELAY_MS = 250;
|
|
3006
3159
|
function useUrlState() {
|
|
3007
|
-
const [state, setState] = (0,
|
|
3008
|
-
const ready = (0,
|
|
3009
|
-
(0,
|
|
3160
|
+
const [state, setState] = (0, import_react24.useState)(DEFAULT_URL_STATE);
|
|
3161
|
+
const ready = (0, import_react24.useRef)(false);
|
|
3162
|
+
(0, import_react24.useEffect)(() => {
|
|
3010
3163
|
const read = () => setState(decodeUrlState(splitHash(window.location.hash).params));
|
|
3011
3164
|
read();
|
|
3012
3165
|
ready.current = true;
|
|
3013
3166
|
window.addEventListener("hashchange", read);
|
|
3014
3167
|
return () => window.removeEventListener("hashchange", read);
|
|
3015
3168
|
}, []);
|
|
3016
|
-
(0,
|
|
3169
|
+
(0, import_react24.useEffect)(() => {
|
|
3017
3170
|
if (!ready.current) return;
|
|
3018
3171
|
const timer = setTimeout(
|
|
3019
3172
|
() => writeHash(splitHash(window.location.hash).anchor, encodeUrlState(state)),
|
|
@@ -3021,7 +3174,7 @@ function useUrlState() {
|
|
|
3021
3174
|
);
|
|
3022
3175
|
return () => clearTimeout(timer);
|
|
3023
3176
|
}, [state]);
|
|
3024
|
-
const update = (0,
|
|
3177
|
+
const update = (0, import_react24.useCallback)(
|
|
3025
3178
|
(patch) => setState((prev) => ({ ...prev, ...patch })),
|
|
3026
3179
|
[]
|
|
3027
3180
|
);
|
|
@@ -3243,12 +3396,12 @@ function reportTools(deps) {
|
|
|
3243
3396
|
}
|
|
3244
3397
|
|
|
3245
3398
|
// src/interactive/ReportInteractive.tsx
|
|
3246
|
-
var
|
|
3399
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
3247
3400
|
function ReportInteractive(props) {
|
|
3248
3401
|
const { report, className, title, dataTheme } = props;
|
|
3249
3402
|
const result = unwrapReport(report);
|
|
3250
3403
|
if (!result.ok) {
|
|
3251
|
-
return /* @__PURE__ */ (0,
|
|
3404
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3252
3405
|
ReportErrorShell,
|
|
3253
3406
|
{
|
|
3254
3407
|
error: result.error,
|
|
@@ -3258,18 +3411,18 @@ function ReportInteractive(props) {
|
|
|
3258
3411
|
}
|
|
3259
3412
|
);
|
|
3260
3413
|
}
|
|
3261
|
-
return /* @__PURE__ */ (0,
|
|
3414
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportInteractiveView, { ...props, report: result.data });
|
|
3262
3415
|
}
|
|
3263
3416
|
var THEME_OPTIONS = [
|
|
3264
|
-
{ value: "light", label: "Light", Icon:
|
|
3265
|
-
{ value: "system", label: "System", Icon:
|
|
3266
|
-
{ value: "dark", label: "Dark", Icon:
|
|
3417
|
+
{ value: "light", label: "Light", Icon: import_lucide_react7.Sun },
|
|
3418
|
+
{ value: "system", label: "System", Icon: import_lucide_react7.Monitor },
|
|
3419
|
+
{ value: "dark", label: "Dark", Icon: import_lucide_react7.Moon }
|
|
3267
3420
|
];
|
|
3268
3421
|
function ThemeSegment({
|
|
3269
3422
|
pref,
|
|
3270
3423
|
onPref
|
|
3271
3424
|
}) {
|
|
3272
|
-
return /* @__PURE__ */ (0,
|
|
3425
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3273
3426
|
ToggleGroup,
|
|
3274
3427
|
{
|
|
3275
3428
|
size: "sm",
|
|
@@ -3279,14 +3432,14 @@ function ThemeSegment({
|
|
|
3279
3432
|
if (next) onPref(next);
|
|
3280
3433
|
},
|
|
3281
3434
|
"aria-label": "Color theme",
|
|
3282
|
-
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ (0,
|
|
3435
|
+
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3283
3436
|
ToggleGroupItem,
|
|
3284
3437
|
{
|
|
3285
3438
|
value,
|
|
3286
3439
|
"aria-label": label,
|
|
3287
3440
|
title: label,
|
|
3288
3441
|
className: "px-2",
|
|
3289
|
-
children: /* @__PURE__ */ (0,
|
|
3442
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Icon, {})
|
|
3290
3443
|
},
|
|
3291
3444
|
value
|
|
3292
3445
|
))
|
|
@@ -3303,30 +3456,32 @@ function ReportInteractiveView({
|
|
|
3303
3456
|
hideHeader = false,
|
|
3304
3457
|
hideToc = false,
|
|
3305
3458
|
staleAfterDays = 7,
|
|
3306
|
-
scenarioHistory
|
|
3459
|
+
scenarioHistory,
|
|
3460
|
+
share = false,
|
|
3461
|
+
shareCommand
|
|
3307
3462
|
}) {
|
|
3308
3463
|
const [urlState, setUrlState] = useUrlState();
|
|
3309
3464
|
const { query, status: statusFilter, tags: activeTags, detail } = urlState;
|
|
3310
|
-
const setQuery = (0,
|
|
3465
|
+
const setQuery = (0, import_react26.useCallback)(
|
|
3311
3466
|
(next) => setUrlState({ query: next }),
|
|
3312
3467
|
[setUrlState]
|
|
3313
3468
|
);
|
|
3314
|
-
const setStatusFilter = (0,
|
|
3469
|
+
const setStatusFilter = (0, import_react26.useCallback)(
|
|
3315
3470
|
(next) => setUrlState({ status: next }),
|
|
3316
3471
|
[setUrlState]
|
|
3317
3472
|
);
|
|
3318
|
-
const setDetail = (0,
|
|
3473
|
+
const setDetail = (0, import_react26.useCallback)(
|
|
3319
3474
|
(next) => setUrlState({ detail: next }),
|
|
3320
3475
|
[setUrlState]
|
|
3321
3476
|
);
|
|
3322
|
-
const [helpOpen, setHelpOpen] = (0,
|
|
3477
|
+
const [helpOpen, setHelpOpen] = (0, import_react26.useState)(false);
|
|
3323
3478
|
const { pref: themePref, setPref: setThemePref } = useTheme();
|
|
3324
|
-
const searchRef = (0,
|
|
3325
|
-
const expandId = (0,
|
|
3326
|
-
const docsId = (0,
|
|
3327
|
-
const deferredQuery = (0,
|
|
3328
|
-
const failures = (0,
|
|
3329
|
-
const filtered = (0,
|
|
3479
|
+
const searchRef = (0, import_react26.useRef)(null);
|
|
3480
|
+
const expandId = (0, import_react26.useId)();
|
|
3481
|
+
const docsId = (0, import_react26.useId)();
|
|
3482
|
+
const deferredQuery = (0, import_react26.useDeferredValue)(query);
|
|
3483
|
+
const failures = (0, import_react26.useMemo)(() => listFailures(report), [report]);
|
|
3484
|
+
const filtered = (0, import_react26.useMemo)(
|
|
3330
3485
|
// Features carrying failures float to the top so the first thing on screen
|
|
3331
3486
|
// is the thing that needs attention; an all-green run keeps source order.
|
|
3332
3487
|
() => failuresFirst(
|
|
@@ -3339,7 +3494,7 @@ function ReportInteractiveView({
|
|
|
3339
3494
|
[report, deferredQuery, statusFilter, activeTags]
|
|
3340
3495
|
);
|
|
3341
3496
|
const isFiltering = query !== deferredQuery;
|
|
3342
|
-
const statusOptions = (0,
|
|
3497
|
+
const statusOptions = (0, import_react26.useMemo)(() => {
|
|
3343
3498
|
const s = report.summary;
|
|
3344
3499
|
const opts = [
|
|
3345
3500
|
{ key: "all", label: "All", count: s.total }
|
|
@@ -3354,21 +3509,21 @@ function ReportInteractiveView({
|
|
|
3354
3509
|
opts.push({ key: "pending", label: "Pending", count: s.pending });
|
|
3355
3510
|
return opts;
|
|
3356
3511
|
}, [report]);
|
|
3357
|
-
const tagOptions = (0,
|
|
3358
|
-
const toggleTag = (0,
|
|
3512
|
+
const tagOptions = (0, import_react26.useMemo)(() => allTags(report), [report]);
|
|
3513
|
+
const toggleTag = (0, import_react26.useCallback)(
|
|
3359
3514
|
(tag) => setUrlState({
|
|
3360
3515
|
tags: activeTags.includes(tag) ? activeTags.filter((t) => t !== tag) : [...activeTags, tag]
|
|
3361
3516
|
}),
|
|
3362
3517
|
[activeTags, setUrlState]
|
|
3363
3518
|
);
|
|
3364
|
-
const [toast, setToast] = (0,
|
|
3365
|
-
const toastTimer = (0,
|
|
3366
|
-
const showToast = (0,
|
|
3519
|
+
const [toast, setToast] = (0, import_react26.useState)(null);
|
|
3520
|
+
const toastTimer = (0, import_react26.useRef)(null);
|
|
3521
|
+
const showToast = (0, import_react26.useCallback)((msg) => {
|
|
3367
3522
|
setToast(msg);
|
|
3368
3523
|
if (toastTimer.current) clearTimeout(toastTimer.current);
|
|
3369
3524
|
toastTimer.current = setTimeout(() => setToast(null), 1800);
|
|
3370
3525
|
}, []);
|
|
3371
|
-
const copy = (0,
|
|
3526
|
+
const copy = (0, import_react26.useCallback)(
|
|
3372
3527
|
(text, msg) => {
|
|
3373
3528
|
if (typeof navigator !== "undefined" && navigator.clipboard) {
|
|
3374
3529
|
navigator.clipboard.writeText(text).then(
|
|
@@ -3379,7 +3534,7 @@ function ReportInteractiveView({
|
|
|
3379
3534
|
},
|
|
3380
3535
|
[showToast]
|
|
3381
3536
|
);
|
|
3382
|
-
const scenarioActions = (0,
|
|
3537
|
+
const scenarioActions = (0, import_react26.useMemo)(
|
|
3383
3538
|
() => ({
|
|
3384
3539
|
copyLink: (s) => copy(scenarioPermalink(s), "Link copied"),
|
|
3385
3540
|
copyMarkdown: (s) => copy(scenarioToMarkdown(s), "Markdown copied"),
|
|
@@ -3387,31 +3542,31 @@ function ReportInteractiveView({
|
|
|
3387
3542
|
}),
|
|
3388
3543
|
[copy]
|
|
3389
3544
|
);
|
|
3390
|
-
const copyAllFailures = (0,
|
|
3545
|
+
const copyAllFailures = (0, import_react26.useCallback)(
|
|
3391
3546
|
() => copy(failuresToPrompt(failedScenarios(filtered)), "Failures copied"),
|
|
3392
3547
|
[copy, filtered]
|
|
3393
3548
|
);
|
|
3394
|
-
const failureIndexRef = (0,
|
|
3395
|
-
const allCollapsibleIds = (0,
|
|
3549
|
+
const failureIndexRef = (0, import_react26.useRef)(0);
|
|
3550
|
+
const allCollapsibleIds = (0, import_react26.useMemo)(
|
|
3396
3551
|
() => report.features.flatMap((f) => [f.id, ...f.scenarios.map((s) => s.id)]),
|
|
3397
3552
|
[report]
|
|
3398
3553
|
);
|
|
3399
3554
|
const collapse = useCollapseState(
|
|
3400
|
-
(0,
|
|
3555
|
+
(0, import_react26.useCallback)(() => defaultCollapsedIds(report), [report])
|
|
3401
3556
|
);
|
|
3402
3557
|
const revealFilteredResults = deferredQuery.trim() !== "" || statusFilter !== "all" || activeTags.length > 0;
|
|
3403
|
-
const visibleCollapse = (0,
|
|
3558
|
+
const visibleCollapse = (0, import_react26.useMemo)(
|
|
3404
3559
|
() => revealFilteredResults ? { ...collapse.api, isCollapsed: () => false } : collapse.api,
|
|
3405
3560
|
[collapse.api, revealFilteredResults]
|
|
3406
3561
|
);
|
|
3407
|
-
const collapseAll = (0,
|
|
3562
|
+
const collapseAll = (0, import_react26.useCallback)(
|
|
3408
3563
|
() => collapse.collapseAll(allCollapsibleIds),
|
|
3409
3564
|
[collapse, allCollapsibleIds]
|
|
3410
3565
|
);
|
|
3411
|
-
const [expandedAll, setExpandedAll] = (0,
|
|
3566
|
+
const [expandedAll, setExpandedAll] = (0, import_react26.useState)(
|
|
3412
3567
|
() => report.summary.failed === 0
|
|
3413
3568
|
);
|
|
3414
|
-
const setExpanded = (0,
|
|
3569
|
+
const setExpanded = (0, import_react26.useCallback)(
|
|
3415
3570
|
(expanded) => {
|
|
3416
3571
|
if (expanded) collapse.expandAll();
|
|
3417
3572
|
else collapseAll();
|
|
@@ -3419,8 +3574,8 @@ function ReportInteractiveView({
|
|
|
3419
3574
|
},
|
|
3420
3575
|
[collapse, collapseAll]
|
|
3421
3576
|
);
|
|
3422
|
-
const [agentFilter, setAgentFilter] = (0,
|
|
3423
|
-
(0,
|
|
3577
|
+
const [agentFilter, setAgentFilter] = (0, import_react26.useState)(null);
|
|
3578
|
+
(0, import_react25.useTools)(
|
|
3424
3579
|
reportTools({
|
|
3425
3580
|
report,
|
|
3426
3581
|
view: urlState,
|
|
@@ -3429,14 +3584,14 @@ function ReportInteractiveView({
|
|
|
3429
3584
|
})
|
|
3430
3585
|
);
|
|
3431
3586
|
const showAgentFilter = agentFilter !== null && agentFilter.search === query && agentFilter.status === statusFilter && agentFilter.tags.length === activeTags.length && agentFilter.tags.every((tag) => activeTags.includes(tag));
|
|
3432
|
-
const clearFilters = (0,
|
|
3587
|
+
const clearFilters = (0, import_react26.useCallback)(
|
|
3433
3588
|
() => setUrlState({ query: "", status: "all", tags: [] }),
|
|
3434
3589
|
[setUrlState]
|
|
3435
3590
|
);
|
|
3436
|
-
const focusSearch = (0,
|
|
3591
|
+
const focusSearch = (0, import_react26.useCallback)(() => {
|
|
3437
3592
|
searchRef.current?.focus();
|
|
3438
3593
|
}, []);
|
|
3439
|
-
const stepFailure = (0,
|
|
3594
|
+
const stepFailure = (0, import_react26.useCallback)(
|
|
3440
3595
|
(direction) => {
|
|
3441
3596
|
if (failures.length === 0) return;
|
|
3442
3597
|
failureIndexRef.current = (failureIndexRef.current + direction + failures.length) % failures.length;
|
|
@@ -3445,10 +3600,10 @@ function ReportInteractiveView({
|
|
|
3445
3600
|
},
|
|
3446
3601
|
[failures]
|
|
3447
3602
|
);
|
|
3448
|
-
const toggleHelp = (0,
|
|
3603
|
+
const toggleHelp = (0, import_react26.useCallback)(() => {
|
|
3449
3604
|
setHelpOpen((v) => !v);
|
|
3450
3605
|
}, []);
|
|
3451
|
-
const escape = (0,
|
|
3606
|
+
const escape = (0, import_react26.useCallback)(() => {
|
|
3452
3607
|
if (helpOpen) setHelpOpen(false);
|
|
3453
3608
|
else if (query !== "") setQuery("");
|
|
3454
3609
|
}, [helpOpen, query, setQuery]);
|
|
@@ -3466,13 +3621,13 @@ function ReportInteractiveView({
|
|
|
3466
3621
|
const totalScenarios = report.summary.total;
|
|
3467
3622
|
const matchedScenarios = filtered.summary.total;
|
|
3468
3623
|
const showToc = !hideToc && totalScenarios > 3;
|
|
3469
|
-
return /* @__PURE__ */ (0,
|
|
3624
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(CollapseProvider, { value: visibleCollapse, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ScenarioActionsProvider, { value: scenarioActions, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ScenarioHistoryProvider, { value: scenarioHistory ?? null, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ScenarioFreshnessProvider, { value: { staleAfterDays, report }, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3470
3625
|
ReportRoot,
|
|
3471
3626
|
{
|
|
3472
3627
|
report: filtered,
|
|
3473
3628
|
customRenderers,
|
|
3474
3629
|
renderers,
|
|
3475
|
-
children: /* @__PURE__ */ (0,
|
|
3630
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3476
3631
|
"main",
|
|
3477
3632
|
{
|
|
3478
3633
|
className: cn("es-report", "es-report-interactive", className),
|
|
@@ -3481,8 +3636,8 @@ function ReportInteractiveView({
|
|
|
3481
3636
|
"data-theme": dataTheme,
|
|
3482
3637
|
"data-detail-level": detail,
|
|
3483
3638
|
children: [
|
|
3484
|
-
/* @__PURE__ */ (0,
|
|
3485
|
-
/* @__PURE__ */ (0,
|
|
3639
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("header", { className: "es-report-header", children: [
|
|
3640
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3486
3641
|
"div",
|
|
3487
3642
|
{
|
|
3488
3643
|
"data-es-navbar": true,
|
|
@@ -3491,9 +3646,9 @@ function ReportInteractiveView({
|
|
|
3491
3646
|
hideHeader ? "justify-end" : "justify-between"
|
|
3492
3647
|
),
|
|
3493
3648
|
children: [
|
|
3494
|
-
hideHeader ? null : /* @__PURE__ */ (0,
|
|
3495
|
-
/* @__PURE__ */ (0,
|
|
3496
|
-
/* @__PURE__ */ (0,
|
|
3649
|
+
hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("h1", { className: "min-w-0", children: title ?? "Story Report" }),
|
|
3650
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3651
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3497
3652
|
ReportSearch,
|
|
3498
3653
|
{
|
|
3499
3654
|
ref: searchRef,
|
|
@@ -3503,16 +3658,18 @@ function ReportInteractiveView({
|
|
|
3503
3658
|
totalCount: totalScenarios
|
|
3504
3659
|
}
|
|
3505
3660
|
),
|
|
3506
|
-
/* @__PURE__ */ (0,
|
|
3661
|
+
share ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportShare, { command: shareCommand, onCopy: copy }) : null,
|
|
3662
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ThemeSegment, { pref: themePref, onPref: setThemePref })
|
|
3507
3663
|
] })
|
|
3508
3664
|
]
|
|
3509
3665
|
}
|
|
3510
3666
|
),
|
|
3511
|
-
hideHeader ? null : /* @__PURE__ */ (0,
|
|
3512
|
-
/* @__PURE__ */ (0,
|
|
3513
|
-
/* @__PURE__ */ (0,
|
|
3667
|
+
hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
|
|
3668
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportSummary, {}),
|
|
3669
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportMeta, {})
|
|
3514
3670
|
] }),
|
|
3515
|
-
/* @__PURE__ */ (0,
|
|
3671
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportSpanGraph, {}),
|
|
3672
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3516
3673
|
ReportFreshness,
|
|
3517
3674
|
{
|
|
3518
3675
|
lastRunMs: reportLastRunMs(report),
|
|
@@ -3520,15 +3677,15 @@ function ReportInteractiveView({
|
|
|
3520
3677
|
staleAfterDays
|
|
3521
3678
|
}
|
|
3522
3679
|
),
|
|
3523
|
-
/* @__PURE__ */ (0,
|
|
3680
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3524
3681
|
ReportLastRunDelta,
|
|
3525
3682
|
{
|
|
3526
3683
|
history: scenarioHistory,
|
|
3527
3684
|
report
|
|
3528
3685
|
}
|
|
3529
3686
|
),
|
|
3530
|
-
/* @__PURE__ */ (0,
|
|
3531
|
-
/* @__PURE__ */ (0,
|
|
3687
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportSinceLastVisit, { report }),
|
|
3688
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3532
3689
|
ReportFilters,
|
|
3533
3690
|
{
|
|
3534
3691
|
statuses: statusOptions,
|
|
@@ -3539,10 +3696,10 @@ function ReportInteractiveView({
|
|
|
3539
3696
|
onToggleTag: toggleTag
|
|
3540
3697
|
}
|
|
3541
3698
|
),
|
|
3542
|
-
/* @__PURE__ */ (0,
|
|
3543
|
-
showToc ? /* @__PURE__ */ (0,
|
|
3544
|
-
/* @__PURE__ */ (0,
|
|
3545
|
-
/* @__PURE__ */ (0,
|
|
3699
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border/60 pt-3", children: [
|
|
3700
|
+
showToc ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportTocDrawer, {}) : null,
|
|
3701
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3702
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3546
3703
|
Switch,
|
|
3547
3704
|
{
|
|
3548
3705
|
id: expandId,
|
|
@@ -3550,7 +3707,7 @@ function ReportInteractiveView({
|
|
|
3550
3707
|
onCheckedChange: setExpanded
|
|
3551
3708
|
}
|
|
3552
3709
|
),
|
|
3553
|
-
/* @__PURE__ */ (0,
|
|
3710
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3554
3711
|
"label",
|
|
3555
3712
|
{
|
|
3556
3713
|
htmlFor: expandId,
|
|
@@ -3559,8 +3716,8 @@ function ReportInteractiveView({
|
|
|
3559
3716
|
}
|
|
3560
3717
|
)
|
|
3561
3718
|
] }),
|
|
3562
|
-
/* @__PURE__ */ (0,
|
|
3563
|
-
/* @__PURE__ */ (0,
|
|
3719
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3720
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3564
3721
|
Switch,
|
|
3565
3722
|
{
|
|
3566
3723
|
id: docsId,
|
|
@@ -3568,7 +3725,7 @@ function ReportInteractiveView({
|
|
|
3568
3725
|
onCheckedChange: (checked) => setDetail(checked ? "full" : "minimal")
|
|
3569
3726
|
}
|
|
3570
3727
|
),
|
|
3571
|
-
/* @__PURE__ */ (0,
|
|
3728
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3572
3729
|
"label",
|
|
3573
3730
|
{
|
|
3574
3731
|
htmlFor: docsId,
|
|
@@ -3579,7 +3736,7 @@ function ReportInteractiveView({
|
|
|
3579
3736
|
] })
|
|
3580
3737
|
] })
|
|
3581
3738
|
] }),
|
|
3582
|
-
showAgentFilter ? /* @__PURE__ */ (0,
|
|
3739
|
+
showAgentFilter ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3583
3740
|
ReportAgentFilterNotice,
|
|
3584
3741
|
{
|
|
3585
3742
|
applied: agentFilter,
|
|
@@ -3587,17 +3744,17 @@ function ReportInteractiveView({
|
|
|
3587
3744
|
onDismiss: () => setAgentFilter(null)
|
|
3588
3745
|
}
|
|
3589
3746
|
) : null,
|
|
3590
|
-
/* @__PURE__ */ (0,
|
|
3591
|
-
hasContent ? showToc ? /* @__PURE__ */ (0,
|
|
3592
|
-
/* @__PURE__ */ (0,
|
|
3593
|
-
/* @__PURE__ */ (0,
|
|
3594
|
-
] }) : /* @__PURE__ */ (0,
|
|
3747
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportFailureBanner, { failures, onCopyAll: copyAllFailures }),
|
|
3748
|
+
hasContent ? showToc ? /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex gap-6", children: [
|
|
3749
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportToc, {}),
|
|
3750
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "flex min-w-0 flex-1 flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportFeatureList, {}) })
|
|
3751
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportFeatureList, {}) }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3595
3752
|
ReportEmpty,
|
|
3596
3753
|
{
|
|
3597
3754
|
message: query ? "No scenarios match the search." : void 0
|
|
3598
3755
|
}
|
|
3599
3756
|
),
|
|
3600
|
-
/* @__PURE__ */ (0,
|
|
3757
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3601
3758
|
"button",
|
|
3602
3759
|
{
|
|
3603
3760
|
type: "button",
|
|
@@ -3608,14 +3765,14 @@ function ReportInteractiveView({
|
|
|
3608
3765
|
children: "?"
|
|
3609
3766
|
}
|
|
3610
3767
|
),
|
|
3611
|
-
/* @__PURE__ */ (0,
|
|
3768
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3612
3769
|
ReportShortcutsHelp,
|
|
3613
3770
|
{
|
|
3614
3771
|
open: helpOpen,
|
|
3615
3772
|
onClose: () => setHelpOpen(false)
|
|
3616
3773
|
}
|
|
3617
3774
|
),
|
|
3618
|
-
toast ? /* @__PURE__ */ (0,
|
|
3775
|
+
toast ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3619
3776
|
"div",
|
|
3620
3777
|
{
|
|
3621
3778
|
role: "status",
|
|
@@ -3632,14 +3789,14 @@ function ReportInteractiveView({
|
|
|
3632
3789
|
}
|
|
3633
3790
|
|
|
3634
3791
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
3635
|
-
var
|
|
3792
|
+
var import_react29 = require("react");
|
|
3636
3793
|
|
|
3637
3794
|
// src/interactive/island-renderers.tsx
|
|
3638
|
-
var
|
|
3795
|
+
var import_react28 = require("react");
|
|
3639
3796
|
|
|
3640
3797
|
// src/components/doc/MermaidView.tsx
|
|
3641
|
-
var
|
|
3642
|
-
var
|
|
3798
|
+
var import_react27 = require("react");
|
|
3799
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
3643
3800
|
function prefersDark(el) {
|
|
3644
3801
|
const themed = el?.closest("[data-theme]");
|
|
3645
3802
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -3647,10 +3804,10 @@ function prefersDark(el) {
|
|
|
3647
3804
|
return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
|
|
3648
3805
|
}
|
|
3649
3806
|
function MermaidView({ entry, load }) {
|
|
3650
|
-
const ref = (0,
|
|
3651
|
-
const [svg, setSvg] = (0,
|
|
3652
|
-
const [error, setError] = (0,
|
|
3653
|
-
(0,
|
|
3807
|
+
const ref = (0, import_react27.useRef)(null);
|
|
3808
|
+
const [svg, setSvg] = (0, import_react27.useState)(null);
|
|
3809
|
+
const [error, setError] = (0, import_react27.useState)(null);
|
|
3810
|
+
(0, import_react27.useEffect)(() => {
|
|
3654
3811
|
let cancelled = false;
|
|
3655
3812
|
const draw = async () => {
|
|
3656
3813
|
let mermaid;
|
|
@@ -3693,9 +3850,9 @@ function MermaidView({ entry, load }) {
|
|
|
3693
3850
|
};
|
|
3694
3851
|
}, [entry.code, load]);
|
|
3695
3852
|
if (svg) {
|
|
3696
|
-
return /* @__PURE__ */ (0,
|
|
3697
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
3698
|
-
/* @__PURE__ */ (0,
|
|
3853
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("figure", { ref, className: "my-3", children: [
|
|
3854
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
3855
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3699
3856
|
"div",
|
|
3700
3857
|
{
|
|
3701
3858
|
role: "img",
|
|
@@ -3706,8 +3863,8 @@ function MermaidView({ entry, load }) {
|
|
|
3706
3863
|
)
|
|
3707
3864
|
] });
|
|
3708
3865
|
}
|
|
3709
|
-
return /* @__PURE__ */ (0,
|
|
3710
|
-
error ? /* @__PURE__ */ (0,
|
|
3866
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
|
|
3867
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
3711
3868
|
"p",
|
|
3712
3869
|
{
|
|
3713
3870
|
role: "alert",
|
|
@@ -3719,12 +3876,12 @@ function MermaidView({ entry, load }) {
|
|
|
3719
3876
|
]
|
|
3720
3877
|
}
|
|
3721
3878
|
) : null,
|
|
3722
|
-
/* @__PURE__ */ (0,
|
|
3879
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(MermaidSource, { entry, ref })
|
|
3723
3880
|
] });
|
|
3724
3881
|
}
|
|
3725
3882
|
|
|
3726
3883
|
// src/interactive/island-renderers.tsx
|
|
3727
|
-
var
|
|
3884
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
3728
3885
|
var HLJS_ESM = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
|
|
3729
3886
|
var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
|
|
3730
3887
|
function cachedCdnModule(url) {
|
|
@@ -3741,8 +3898,8 @@ function cachedCdnModule(url) {
|
|
|
3741
3898
|
var loadMermaidFromCdn = cachedCdnModule(MERMAID_ESM);
|
|
3742
3899
|
var loadHljs = cachedCdnModule(HLJS_ESM);
|
|
3743
3900
|
function CdnHighlightedCode({ entry }) {
|
|
3744
|
-
const [html, setHtml] = (0,
|
|
3745
|
-
(0,
|
|
3901
|
+
const [html, setHtml] = (0, import_react28.useState)(null);
|
|
3902
|
+
(0, import_react28.useEffect)(() => {
|
|
3746
3903
|
let cancelled = false;
|
|
3747
3904
|
void (async () => {
|
|
3748
3905
|
try {
|
|
@@ -3758,27 +3915,27 @@ function CdnHighlightedCode({ entry }) {
|
|
|
3758
3915
|
cancelled = true;
|
|
3759
3916
|
};
|
|
3760
3917
|
}, [entry.content, entry.lang]);
|
|
3761
|
-
return /* @__PURE__ */ (0,
|
|
3918
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
3762
3919
|
"code",
|
|
3763
3920
|
{
|
|
3764
3921
|
className: cn("hljs font-mono text-xs", entry.lang && `language-${entry.lang}`),
|
|
3765
3922
|
dangerouslySetInnerHTML: { __html: html }
|
|
3766
3923
|
}
|
|
3767
|
-
) : /* @__PURE__ */ (0,
|
|
3924
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
3768
3925
|
}
|
|
3769
3926
|
function buildIslandRenderers(opts) {
|
|
3770
3927
|
const renderers = {};
|
|
3771
3928
|
if (opts.mermaid) {
|
|
3772
|
-
renderers.mermaid = (entry) => (0,
|
|
3929
|
+
renderers.mermaid = (entry) => (0, import_react28.createElement)(MermaidView, { entry, load: loadMermaidFromCdn });
|
|
3773
3930
|
}
|
|
3774
3931
|
if (opts.syntaxHighlighting) {
|
|
3775
|
-
renderers.code = (entry) => (0,
|
|
3932
|
+
renderers.code = (entry) => (0, import_react28.createElement)(CdnHighlightedCode, { entry });
|
|
3776
3933
|
}
|
|
3777
3934
|
return renderers;
|
|
3778
3935
|
}
|
|
3779
3936
|
|
|
3780
3937
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
3781
|
-
var
|
|
3938
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
3782
3939
|
function ReportInteractiveIsland({
|
|
3783
3940
|
report,
|
|
3784
3941
|
title,
|
|
@@ -3788,11 +3945,11 @@ function ReportInteractiveIsland({
|
|
|
3788
3945
|
syntaxHighlighting = true,
|
|
3789
3946
|
mermaid = true
|
|
3790
3947
|
}) {
|
|
3791
|
-
const renderers = (0,
|
|
3948
|
+
const renderers = (0, import_react29.useMemo)(
|
|
3792
3949
|
() => buildIslandRenderers({ syntaxHighlighting, mermaid }),
|
|
3793
3950
|
[syntaxHighlighting, mermaid]
|
|
3794
3951
|
);
|
|
3795
|
-
return /* @__PURE__ */ (0,
|
|
3952
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
3796
3953
|
ReportInteractive,
|
|
3797
3954
|
{
|
|
3798
3955
|
report,
|