executable-stories-react 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +147 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +136 -54
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +439 -332
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +6 -0
- package/dist/interactive.d.ts +6 -0
- package/dist/interactive.js +397 -290
- package/dist/interactive.js.map +1 -1
- package/dist/report-island.global.js +55 -54
- package/dist/ssr.cjs +111 -28
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.d.cts +2 -0
- package/dist/ssr.d.ts +2 -0
- package/dist/ssr.js +99 -16
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +3 -3
package/dist/interactive.cjs
CHANGED
|
@@ -48,8 +48,8 @@ module.exports = __toCommonJS(interactive_exports);
|
|
|
48
48
|
|
|
49
49
|
// src/interactive/ReportInteractive.tsx
|
|
50
50
|
var import_lucide_react7 = require("lucide-react");
|
|
51
|
-
var
|
|
52
|
-
var
|
|
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 border-collapse 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 text-link underline underline-offset-2 hover:text-foreground", 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",
|
|
@@ -2528,7 +2606,7 @@ var ReportSearch = (0, import_react13.forwardRef)(
|
|
|
2528
2606
|
|
|
2529
2607
|
// src/interactive/ReportShare.tsx
|
|
2530
2608
|
var import_lucide_react5 = require("lucide-react");
|
|
2531
|
-
var
|
|
2609
|
+
var import_react16 = require("react");
|
|
2532
2610
|
|
|
2533
2611
|
// src/components/ui/button.tsx
|
|
2534
2612
|
var React7 = require("react");
|
|
@@ -2584,22 +2662,22 @@ function Button({
|
|
|
2584
2662
|
}
|
|
2585
2663
|
|
|
2586
2664
|
// src/interactive/ReportShare.tsx
|
|
2587
|
-
var
|
|
2665
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2588
2666
|
var DEFAULT_SHARE_COMMAND = "npx executable-stories share reports/";
|
|
2589
2667
|
function ReportShare({
|
|
2590
2668
|
command = DEFAULT_SHARE_COMMAND,
|
|
2591
2669
|
onCopy
|
|
2592
2670
|
}) {
|
|
2593
|
-
const [open, setOpen] = (0,
|
|
2594
|
-
const dialogRef = (0,
|
|
2595
|
-
(0,
|
|
2671
|
+
const [open, setOpen] = (0, import_react16.useState)(false);
|
|
2672
|
+
const dialogRef = (0, import_react16.useRef)(null);
|
|
2673
|
+
(0, import_react16.useEffect)(() => {
|
|
2596
2674
|
const dialog = dialogRef.current;
|
|
2597
2675
|
if (!dialog) return;
|
|
2598
2676
|
if (open && !dialog.open) dialog.showModal();
|
|
2599
2677
|
else if (!open && dialog.open) dialog.close();
|
|
2600
2678
|
}, [open]);
|
|
2601
|
-
return /* @__PURE__ */ (0,
|
|
2602
|
-
/* @__PURE__ */ (0,
|
|
2679
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
|
|
2680
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
2603
2681
|
Button,
|
|
2604
2682
|
{
|
|
2605
2683
|
type: "button",
|
|
@@ -2609,12 +2687,12 @@ function ReportShare({
|
|
|
2609
2687
|
title: "Share this report",
|
|
2610
2688
|
onClick: () => setOpen(true),
|
|
2611
2689
|
children: [
|
|
2612
|
-
/* @__PURE__ */ (0,
|
|
2613
|
-
/* @__PURE__ */ (0,
|
|
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" })
|
|
2614
2692
|
]
|
|
2615
2693
|
}
|
|
2616
2694
|
),
|
|
2617
|
-
/* @__PURE__ */ (0,
|
|
2695
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
2618
2696
|
"dialog",
|
|
2619
2697
|
{
|
|
2620
2698
|
ref: dialogRef,
|
|
@@ -2622,11 +2700,11 @@ function ReportShare({
|
|
|
2622
2700
|
"aria-label": "Share this report",
|
|
2623
2701
|
onClose: () => setOpen(false),
|
|
2624
2702
|
children: [
|
|
2625
|
-
/* @__PURE__ */ (0,
|
|
2626
|
-
/* @__PURE__ */ (0,
|
|
2627
|
-
/* @__PURE__ */ (0,
|
|
2628
|
-
/* @__PURE__ */ (0,
|
|
2629
|
-
/* @__PURE__ */ (0,
|
|
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)(
|
|
2630
2708
|
Button,
|
|
2631
2709
|
{
|
|
2632
2710
|
type: "button",
|
|
@@ -2636,9 +2714,9 @@ function ReportShare({
|
|
|
2636
2714
|
}
|
|
2637
2715
|
)
|
|
2638
2716
|
] }),
|
|
2639
|
-
/* @__PURE__ */ (0,
|
|
2640
|
-
/* @__PURE__ */ (0,
|
|
2641
|
-
/* @__PURE__ */ (0,
|
|
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)(
|
|
2642
2720
|
"a",
|
|
2643
2721
|
{
|
|
2644
2722
|
className: "text-xs underline underline-offset-2",
|
|
@@ -2648,7 +2726,7 @@ function ReportShare({
|
|
|
2648
2726
|
children: "How sharing works"
|
|
2649
2727
|
}
|
|
2650
2728
|
),
|
|
2651
|
-
/* @__PURE__ */ (0,
|
|
2729
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setOpen(false), children: "Close" })
|
|
2652
2730
|
] })
|
|
2653
2731
|
]
|
|
2654
2732
|
}
|
|
@@ -2657,7 +2735,7 @@ function ReportShare({
|
|
|
2657
2735
|
}
|
|
2658
2736
|
|
|
2659
2737
|
// src/interactive/ReportSinceLastVisit.tsx
|
|
2660
|
-
var
|
|
2738
|
+
var import_react17 = require("react");
|
|
2661
2739
|
|
|
2662
2740
|
// src/interactive/last-visit.ts
|
|
2663
2741
|
function snapshotOf(report, atMs) {
|
|
@@ -2693,7 +2771,7 @@ function diffSinceVisit(previous, report) {
|
|
|
2693
2771
|
}
|
|
2694
2772
|
|
|
2695
2773
|
// src/interactive/ReportSinceLastVisit.tsx
|
|
2696
|
-
var
|
|
2774
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
2697
2775
|
var KEY = "es-last-visit";
|
|
2698
2776
|
var MAX_LINKS2 = 5;
|
|
2699
2777
|
function readVisit() {
|
|
@@ -2718,12 +2796,12 @@ function writeVisit(snapshot) {
|
|
|
2718
2796
|
}
|
|
2719
2797
|
}
|
|
2720
2798
|
function ScenarioLinks2({ scenarios, tone }) {
|
|
2721
|
-
return /* @__PURE__ */ (0,
|
|
2722
|
-
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: [
|
|
2723
2801
|
i > 0 ? ", " : "",
|
|
2724
|
-
/* @__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 })
|
|
2725
2803
|
] }, s.id)),
|
|
2726
|
-
scenarios.length > MAX_LINKS2 ? /* @__PURE__ */ (0,
|
|
2804
|
+
scenarios.length > MAX_LINKS2 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { children: [
|
|
2727
2805
|
" and ",
|
|
2728
2806
|
scenarios.length - MAX_LINKS2,
|
|
2729
2807
|
" more"
|
|
@@ -2731,9 +2809,9 @@ function ScenarioLinks2({ scenarios, tone }) {
|
|
|
2731
2809
|
] });
|
|
2732
2810
|
}
|
|
2733
2811
|
function ReportSinceLastVisit({ report }) {
|
|
2734
|
-
const [delta, setDelta] = (0,
|
|
2735
|
-
const [nowMs, setNowMs] = (0,
|
|
2736
|
-
(0,
|
|
2812
|
+
const [delta, setDelta] = (0, import_react17.useState)(null);
|
|
2813
|
+
const [nowMs, setNowMs] = (0, import_react17.useState)(0);
|
|
2814
|
+
(0, import_react17.useEffect)(() => {
|
|
2737
2815
|
const now = Date.now();
|
|
2738
2816
|
setDelta(diffSinceVisit(readVisit(), report));
|
|
2739
2817
|
setNowMs(now);
|
|
@@ -2741,25 +2819,25 @@ function ReportSinceLastVisit({ report }) {
|
|
|
2741
2819
|
}, [report]);
|
|
2742
2820
|
if (!delta) return null;
|
|
2743
2821
|
const { newlyFailing, newlyPassing, added } = delta;
|
|
2744
|
-
return /* @__PURE__ */ (0,
|
|
2745
|
-
/* @__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: [
|
|
2746
2824
|
"Since your last visit (",
|
|
2747
2825
|
formatRelativeAge(delta.sinceMs, nowMs),
|
|
2748
2826
|
"):"
|
|
2749
2827
|
] }),
|
|
2750
|
-
newlyFailing.length > 0 ? /* @__PURE__ */ (0,
|
|
2828
|
+
newlyFailing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "ml-2 text-fail", children: [
|
|
2751
2829
|
newlyFailing.length,
|
|
2752
2830
|
" started failing (",
|
|
2753
|
-
/* @__PURE__ */ (0,
|
|
2831
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ScenarioLinks2, { scenarios: newlyFailing, tone: "text-fail" }),
|
|
2754
2832
|
")"
|
|
2755
2833
|
] }) : null,
|
|
2756
|
-
newlyPassing.length > 0 ? /* @__PURE__ */ (0,
|
|
2834
|
+
newlyPassing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "ml-2 text-pass", children: [
|
|
2757
2835
|
newlyPassing.length,
|
|
2758
2836
|
" fixed (",
|
|
2759
|
-
/* @__PURE__ */ (0,
|
|
2837
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ScenarioLinks2, { scenarios: newlyPassing, tone: "text-pass" }),
|
|
2760
2838
|
")"
|
|
2761
2839
|
] }) : null,
|
|
2762
|
-
added.length > 0 ? /* @__PURE__ */ (0,
|
|
2840
|
+
added.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "ml-2", children: [
|
|
2763
2841
|
added.length,
|
|
2764
2842
|
" new"
|
|
2765
2843
|
] }) : null
|
|
@@ -2767,8 +2845,8 @@ function ReportSinceLastVisit({ report }) {
|
|
|
2767
2845
|
}
|
|
2768
2846
|
|
|
2769
2847
|
// src/interactive/ReportShortcutsHelp.tsx
|
|
2770
|
-
var
|
|
2771
|
-
var
|
|
2848
|
+
var import_react18 = require("react");
|
|
2849
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
2772
2850
|
var SHORTCUTS = [
|
|
2773
2851
|
{ keys: "/", description: "Focus search" },
|
|
2774
2852
|
{ keys: "f", description: "Jump to next failure" },
|
|
@@ -2780,20 +2858,20 @@ var SHORTCUTS = [
|
|
|
2780
2858
|
];
|
|
2781
2859
|
function Keys({ keys }) {
|
|
2782
2860
|
const parts = keys.split(" ");
|
|
2783
|
-
return /* @__PURE__ */ (0,
|
|
2784
|
-
i > 0 ? /* @__PURE__ */ (0,
|
|
2785
|
-
/* @__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 })
|
|
2786
2864
|
] }, k)) });
|
|
2787
2865
|
}
|
|
2788
2866
|
function ReportShortcutsHelp({ open, onClose }) {
|
|
2789
|
-
const dialogRef = (0,
|
|
2790
|
-
(0,
|
|
2867
|
+
const dialogRef = (0, import_react18.useRef)(null);
|
|
2868
|
+
(0, import_react18.useEffect)(() => {
|
|
2791
2869
|
const dialog = dialogRef.current;
|
|
2792
2870
|
if (!dialog) return;
|
|
2793
2871
|
if (open && !dialog.open) dialog.showModal();
|
|
2794
2872
|
else if (!open && dialog.open) dialog.close();
|
|
2795
2873
|
}, [open]);
|
|
2796
|
-
return /* @__PURE__ */ (0,
|
|
2874
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
2797
2875
|
"dialog",
|
|
2798
2876
|
{
|
|
2799
2877
|
ref: dialogRef,
|
|
@@ -2801,20 +2879,20 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2801
2879
|
"aria-label": "Keyboard shortcuts",
|
|
2802
2880
|
onClose,
|
|
2803
2881
|
children: [
|
|
2804
|
-
/* @__PURE__ */ (0,
|
|
2805
|
-
/* @__PURE__ */ (0,
|
|
2806
|
-
/* @__PURE__ */ (0,
|
|
2807
|
-
/* @__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 })
|
|
2808
2886
|
] }, s.keys)) }),
|
|
2809
|
-
/* @__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" }) })
|
|
2810
2888
|
]
|
|
2811
2889
|
}
|
|
2812
2890
|
);
|
|
2813
2891
|
}
|
|
2814
2892
|
|
|
2815
2893
|
// src/interactive/ReportToc.tsx
|
|
2816
|
-
var
|
|
2817
|
-
var
|
|
2894
|
+
var import_react19 = require("react");
|
|
2895
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
2818
2896
|
var DOT = {
|
|
2819
2897
|
passed: "bg-pass",
|
|
2820
2898
|
failed: "bg-fail",
|
|
@@ -2823,31 +2901,55 @@ var DOT = {
|
|
|
2823
2901
|
};
|
|
2824
2902
|
function TocContent({ onNavigate }) {
|
|
2825
2903
|
const report = useReport();
|
|
2826
|
-
const [activeId, setActiveId] = (0,
|
|
2827
|
-
const scenarioIds = (0,
|
|
2904
|
+
const [activeId, setActiveId] = (0, import_react19.useState)(null);
|
|
2905
|
+
const scenarioIds = (0, import_react19.useMemo)(
|
|
2828
2906
|
() => report.features.flatMap((f) => f.scenarios.map((s) => s.id)),
|
|
2829
2907
|
[report]
|
|
2830
2908
|
);
|
|
2831
|
-
(0,
|
|
2832
|
-
if (typeof
|
|
2909
|
+
(0, import_react19.useEffect)(() => {
|
|
2910
|
+
if (typeof window === "undefined") return;
|
|
2833
2911
|
const els = scenarioIds.map((id) => document.getElementById(id)).filter((el) => el !== null);
|
|
2834
2912
|
if (els.length === 0) return;
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2913
|
+
let frame = 0;
|
|
2914
|
+
const update = () => {
|
|
2915
|
+
frame = 0;
|
|
2916
|
+
const atBottom = window.scrollY + window.innerHeight >= document.documentElement.scrollHeight - 2;
|
|
2917
|
+
const line = atBottom ? window.innerHeight : window.innerHeight * 0.2;
|
|
2918
|
+
let active = els[0];
|
|
2919
|
+
let best = -Infinity;
|
|
2920
|
+
let firstId = null;
|
|
2921
|
+
let firstTop = Infinity;
|
|
2922
|
+
for (const el of els) {
|
|
2923
|
+
const top = el.getBoundingClientRect().top;
|
|
2924
|
+
if (top <= line && top > best) {
|
|
2925
|
+
best = top;
|
|
2926
|
+
active = el;
|
|
2927
|
+
}
|
|
2928
|
+
if (top < firstTop) {
|
|
2929
|
+
firstTop = top;
|
|
2930
|
+
firstId = el.id;
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
setActiveId(best === -Infinity ? firstId : active.id);
|
|
2934
|
+
};
|
|
2935
|
+
const onScroll = () => {
|
|
2936
|
+
if (frame === 0) frame = requestAnimationFrame(update);
|
|
2937
|
+
};
|
|
2938
|
+
update();
|
|
2939
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
2940
|
+
window.addEventListener("resize", onScroll);
|
|
2941
|
+
return () => {
|
|
2942
|
+
window.removeEventListener("scroll", onScroll);
|
|
2943
|
+
window.removeEventListener("resize", onScroll);
|
|
2944
|
+
if (frame !== 0) cancelAnimationFrame(frame);
|
|
2945
|
+
};
|
|
2844
2946
|
}, [scenarioIds]);
|
|
2845
2947
|
if (report.features.length === 0) return null;
|
|
2846
|
-
return /* @__PURE__ */ (0,
|
|
2847
|
-
/* @__PURE__ */ (0,
|
|
2848
|
-
/* @__PURE__ */ (0,
|
|
2948
|
+
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: [
|
|
2949
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
|
|
2950
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("ul", { className: "flex list-none flex-col gap-0.5 pl-0", children: feature.scenarios.map((scenario) => {
|
|
2849
2951
|
const active = activeId === scenario.id;
|
|
2850
|
-
return /* @__PURE__ */ (0,
|
|
2952
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
2851
2953
|
"a",
|
|
2852
2954
|
{
|
|
2853
2955
|
href: `#${scenario.id}`,
|
|
@@ -2862,14 +2964,14 @@ function TocContent({ onNavigate }) {
|
|
|
2862
2964
|
active ? "border-primary font-medium text-foreground" : "border-border text-muted-foreground"
|
|
2863
2965
|
),
|
|
2864
2966
|
children: [
|
|
2865
|
-
/* @__PURE__ */ (0,
|
|
2967
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
2866
2968
|
"span",
|
|
2867
2969
|
{
|
|
2868
2970
|
"aria-hidden": true,
|
|
2869
2971
|
className: cn("mt-1 size-1.5 shrink-0 rounded-full", DOT[scenario.status])
|
|
2870
2972
|
}
|
|
2871
2973
|
),
|
|
2872
|
-
/* @__PURE__ */ (0,
|
|
2974
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "break-words", children: scenario.title })
|
|
2873
2975
|
]
|
|
2874
2976
|
}
|
|
2875
2977
|
) }, scenario.id);
|
|
@@ -2879,48 +2981,48 @@ function TocContent({ onNavigate }) {
|
|
|
2879
2981
|
function ReportToc() {
|
|
2880
2982
|
const report = useReport();
|
|
2881
2983
|
if (report.features.length === 0) return null;
|
|
2882
|
-
return /* @__PURE__ */ (0,
|
|
2984
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
2883
2985
|
"nav",
|
|
2884
2986
|
{
|
|
2885
2987
|
"aria-label": "Table of contents",
|
|
2886
2988
|
className: "sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block",
|
|
2887
2989
|
children: [
|
|
2888
|
-
/* @__PURE__ */ (0,
|
|
2889
|
-
/* @__PURE__ */ (0,
|
|
2990
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
|
|
2991
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(TocContent, {})
|
|
2890
2992
|
]
|
|
2891
2993
|
}
|
|
2892
2994
|
);
|
|
2893
2995
|
}
|
|
2894
2996
|
|
|
2895
2997
|
// src/interactive/ReportTocDrawer.tsx
|
|
2896
|
-
var
|
|
2998
|
+
var import_react20 = require("react");
|
|
2897
2999
|
var import_dialog = require("@base-ui/react/dialog");
|
|
2898
3000
|
var import_lucide_react6 = require("lucide-react");
|
|
2899
|
-
var
|
|
3001
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
2900
3002
|
function ReportTocDrawer() {
|
|
2901
3003
|
const report = useReport();
|
|
2902
|
-
const [open, setOpen] = (0,
|
|
3004
|
+
const [open, setOpen] = (0, import_react20.useState)(false);
|
|
2903
3005
|
if (report.features.length === 0) return null;
|
|
2904
|
-
return /* @__PURE__ */ (0,
|
|
2905
|
-
/* @__PURE__ */ (0,
|
|
2906
|
-
/* @__PURE__ */ (0,
|
|
3006
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_dialog.Dialog.Root, { open, onOpenChange: setOpen, children: [
|
|
3007
|
+
/* @__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: [
|
|
3008
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react6.ListIcon, { "aria-hidden": true }),
|
|
2907
3009
|
" Contents"
|
|
2908
3010
|
] }),
|
|
2909
|
-
/* @__PURE__ */ (0,
|
|
2910
|
-
/* @__PURE__ */ (0,
|
|
2911
|
-
/* @__PURE__ */ (0,
|
|
2912
|
-
/* @__PURE__ */ (0,
|
|
2913
|
-
/* @__PURE__ */ (0,
|
|
2914
|
-
/* @__PURE__ */ (0,
|
|
3011
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_dialog.Dialog.Portal, { children: [
|
|
3012
|
+
/* @__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" }),
|
|
3013
|
+
/* @__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: [
|
|
3014
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
3015
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_dialog.Dialog.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
|
|
3016
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
2915
3017
|
import_dialog.Dialog.Close,
|
|
2916
3018
|
{
|
|
2917
3019
|
"aria-label": "Close contents",
|
|
2918
3020
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
2919
|
-
children: /* @__PURE__ */ (0,
|
|
3021
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react6.XIcon, { "aria-hidden": true })
|
|
2920
3022
|
}
|
|
2921
3023
|
)
|
|
2922
3024
|
] }),
|
|
2923
|
-
/* @__PURE__ */ (0,
|
|
3025
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(TocContent, { onNavigate: () => setOpen(false) })
|
|
2924
3026
|
] })
|
|
2925
3027
|
] })
|
|
2926
3028
|
] });
|
|
@@ -2954,10 +3056,10 @@ function failuresFirst(report) {
|
|
|
2954
3056
|
}
|
|
2955
3057
|
|
|
2956
3058
|
// src/interactive/use-deep-link-scroll.ts
|
|
2957
|
-
var
|
|
3059
|
+
var import_react21 = require("react");
|
|
2958
3060
|
function useDeepLinkScroll() {
|
|
2959
|
-
const lastAnchor = (0,
|
|
2960
|
-
(0,
|
|
3061
|
+
const lastAnchor = (0, import_react21.useRef)(null);
|
|
3062
|
+
(0, import_react21.useEffect)(() => {
|
|
2961
3063
|
function scrollToHash() {
|
|
2962
3064
|
const { anchor } = splitHash(window.location.hash);
|
|
2963
3065
|
if (!anchor || anchor === lastAnchor.current) return;
|
|
@@ -2973,7 +3075,7 @@ function useDeepLinkScroll() {
|
|
|
2973
3075
|
}
|
|
2974
3076
|
|
|
2975
3077
|
// src/interactive/use-keyboard-shortcuts.ts
|
|
2976
|
-
var
|
|
3078
|
+
var import_react22 = require("react");
|
|
2977
3079
|
function isEditableTarget(target) {
|
|
2978
3080
|
if (!(target instanceof HTMLElement)) return false;
|
|
2979
3081
|
const tag = target.tagName;
|
|
@@ -2982,9 +3084,9 @@ function isEditableTarget(target) {
|
|
|
2982
3084
|
return false;
|
|
2983
3085
|
}
|
|
2984
3086
|
function useKeyboardShortcuts(handlers) {
|
|
2985
|
-
const ref = (0,
|
|
3087
|
+
const ref = (0, import_react22.useRef)(handlers);
|
|
2986
3088
|
ref.current = handlers;
|
|
2987
|
-
(0,
|
|
3089
|
+
(0, import_react22.useEffect)(() => {
|
|
2988
3090
|
function onKeyDown(e) {
|
|
2989
3091
|
const h = ref.current;
|
|
2990
3092
|
if (e.key === "Escape") {
|
|
@@ -3028,7 +3130,7 @@ function useKeyboardShortcuts(handlers) {
|
|
|
3028
3130
|
}
|
|
3029
3131
|
|
|
3030
3132
|
// src/interactive/use-theme.ts
|
|
3031
|
-
var
|
|
3133
|
+
var import_react23 = require("react");
|
|
3032
3134
|
var KEY2 = "es-theme";
|
|
3033
3135
|
function systemDark() {
|
|
3034
3136
|
return typeof matchMedia !== "undefined" && matchMedia("(prefers-color-scheme: dark)").matches;
|
|
@@ -3049,13 +3151,13 @@ function initialPref() {
|
|
|
3049
3151
|
return "system";
|
|
3050
3152
|
}
|
|
3051
3153
|
function useTheme() {
|
|
3052
|
-
const [pref, setPrefState] = (0,
|
|
3053
|
-
(0,
|
|
3154
|
+
const [pref, setPrefState] = (0, import_react23.useState)("system");
|
|
3155
|
+
(0, import_react23.useEffect)(() => {
|
|
3054
3156
|
const p = initialPref();
|
|
3055
3157
|
setPrefState(p);
|
|
3056
3158
|
applyTheme(p);
|
|
3057
3159
|
}, []);
|
|
3058
|
-
(0,
|
|
3160
|
+
(0, import_react23.useEffect)(() => {
|
|
3059
3161
|
if (typeof matchMedia === "undefined") return;
|
|
3060
3162
|
const mq = matchMedia("(prefers-color-scheme: dark)");
|
|
3061
3163
|
const onChange = () => {
|
|
@@ -3064,7 +3166,7 @@ function useTheme() {
|
|
|
3064
3166
|
mq.addEventListener("change", onChange);
|
|
3065
3167
|
return () => mq.removeEventListener("change", onChange);
|
|
3066
3168
|
}, [pref]);
|
|
3067
|
-
const setPref = (0,
|
|
3169
|
+
const setPref = (0, import_react23.useCallback)((p) => {
|
|
3068
3170
|
setPrefState(p);
|
|
3069
3171
|
applyTheme(p);
|
|
3070
3172
|
try {
|
|
@@ -3076,19 +3178,19 @@ function useTheme() {
|
|
|
3076
3178
|
}
|
|
3077
3179
|
|
|
3078
3180
|
// src/interactive/use-url-state.ts
|
|
3079
|
-
var
|
|
3181
|
+
var import_react24 = require("react");
|
|
3080
3182
|
var WRITE_DELAY_MS = 250;
|
|
3081
3183
|
function useUrlState() {
|
|
3082
|
-
const [state, setState] = (0,
|
|
3083
|
-
const ready = (0,
|
|
3084
|
-
(0,
|
|
3184
|
+
const [state, setState] = (0, import_react24.useState)(DEFAULT_URL_STATE);
|
|
3185
|
+
const ready = (0, import_react24.useRef)(false);
|
|
3186
|
+
(0, import_react24.useEffect)(() => {
|
|
3085
3187
|
const read = () => setState(decodeUrlState(splitHash(window.location.hash).params));
|
|
3086
3188
|
read();
|
|
3087
3189
|
ready.current = true;
|
|
3088
3190
|
window.addEventListener("hashchange", read);
|
|
3089
3191
|
return () => window.removeEventListener("hashchange", read);
|
|
3090
3192
|
}, []);
|
|
3091
|
-
(0,
|
|
3193
|
+
(0, import_react24.useEffect)(() => {
|
|
3092
3194
|
if (!ready.current) return;
|
|
3093
3195
|
const timer = setTimeout(
|
|
3094
3196
|
() => writeHash(splitHash(window.location.hash).anchor, encodeUrlState(state)),
|
|
@@ -3096,7 +3198,7 @@ function useUrlState() {
|
|
|
3096
3198
|
);
|
|
3097
3199
|
return () => clearTimeout(timer);
|
|
3098
3200
|
}, [state]);
|
|
3099
|
-
const update = (0,
|
|
3201
|
+
const update = (0, import_react24.useCallback)(
|
|
3100
3202
|
(patch) => setState((prev) => ({ ...prev, ...patch })),
|
|
3101
3203
|
[]
|
|
3102
3204
|
);
|
|
@@ -3318,12 +3420,12 @@ function reportTools(deps) {
|
|
|
3318
3420
|
}
|
|
3319
3421
|
|
|
3320
3422
|
// src/interactive/ReportInteractive.tsx
|
|
3321
|
-
var
|
|
3423
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
3322
3424
|
function ReportInteractive(props) {
|
|
3323
3425
|
const { report, className, title, dataTheme } = props;
|
|
3324
3426
|
const result = unwrapReport(report);
|
|
3325
3427
|
if (!result.ok) {
|
|
3326
|
-
return /* @__PURE__ */ (0,
|
|
3428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3327
3429
|
ReportErrorShell,
|
|
3328
3430
|
{
|
|
3329
3431
|
error: result.error,
|
|
@@ -3333,7 +3435,7 @@ function ReportInteractive(props) {
|
|
|
3333
3435
|
}
|
|
3334
3436
|
);
|
|
3335
3437
|
}
|
|
3336
|
-
return /* @__PURE__ */ (0,
|
|
3438
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportInteractiveView, { ...props, report: result.data });
|
|
3337
3439
|
}
|
|
3338
3440
|
var THEME_OPTIONS = [
|
|
3339
3441
|
{ value: "light", label: "Light", Icon: import_lucide_react7.Sun },
|
|
@@ -3344,7 +3446,7 @@ function ThemeSegment({
|
|
|
3344
3446
|
pref,
|
|
3345
3447
|
onPref
|
|
3346
3448
|
}) {
|
|
3347
|
-
return /* @__PURE__ */ (0,
|
|
3449
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3348
3450
|
ToggleGroup,
|
|
3349
3451
|
{
|
|
3350
3452
|
size: "sm",
|
|
@@ -3354,14 +3456,14 @@ function ThemeSegment({
|
|
|
3354
3456
|
if (next) onPref(next);
|
|
3355
3457
|
},
|
|
3356
3458
|
"aria-label": "Color theme",
|
|
3357
|
-
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ (0,
|
|
3459
|
+
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3358
3460
|
ToggleGroupItem,
|
|
3359
3461
|
{
|
|
3360
3462
|
value,
|
|
3361
3463
|
"aria-label": label,
|
|
3362
3464
|
title: label,
|
|
3363
3465
|
className: "px-2",
|
|
3364
|
-
children: /* @__PURE__ */ (0,
|
|
3466
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Icon, {})
|
|
3365
3467
|
},
|
|
3366
3468
|
value
|
|
3367
3469
|
))
|
|
@@ -3380,30 +3482,31 @@ function ReportInteractiveView({
|
|
|
3380
3482
|
staleAfterDays = 7,
|
|
3381
3483
|
scenarioHistory,
|
|
3382
3484
|
share = false,
|
|
3485
|
+
architecture = false,
|
|
3383
3486
|
shareCommand
|
|
3384
3487
|
}) {
|
|
3385
3488
|
const [urlState, setUrlState] = useUrlState();
|
|
3386
3489
|
const { query, status: statusFilter, tags: activeTags, detail } = urlState;
|
|
3387
|
-
const setQuery = (0,
|
|
3490
|
+
const setQuery = (0, import_react26.useCallback)(
|
|
3388
3491
|
(next) => setUrlState({ query: next }),
|
|
3389
3492
|
[setUrlState]
|
|
3390
3493
|
);
|
|
3391
|
-
const setStatusFilter = (0,
|
|
3494
|
+
const setStatusFilter = (0, import_react26.useCallback)(
|
|
3392
3495
|
(next) => setUrlState({ status: next }),
|
|
3393
3496
|
[setUrlState]
|
|
3394
3497
|
);
|
|
3395
|
-
const setDetail = (0,
|
|
3498
|
+
const setDetail = (0, import_react26.useCallback)(
|
|
3396
3499
|
(next) => setUrlState({ detail: next }),
|
|
3397
3500
|
[setUrlState]
|
|
3398
3501
|
);
|
|
3399
|
-
const [helpOpen, setHelpOpen] = (0,
|
|
3502
|
+
const [helpOpen, setHelpOpen] = (0, import_react26.useState)(false);
|
|
3400
3503
|
const { pref: themePref, setPref: setThemePref } = useTheme();
|
|
3401
|
-
const searchRef = (0,
|
|
3402
|
-
const expandId = (0,
|
|
3403
|
-
const docsId = (0,
|
|
3404
|
-
const deferredQuery = (0,
|
|
3405
|
-
const failures = (0,
|
|
3406
|
-
const filtered = (0,
|
|
3504
|
+
const searchRef = (0, import_react26.useRef)(null);
|
|
3505
|
+
const expandId = (0, import_react26.useId)();
|
|
3506
|
+
const docsId = (0, import_react26.useId)();
|
|
3507
|
+
const deferredQuery = (0, import_react26.useDeferredValue)(query);
|
|
3508
|
+
const failures = (0, import_react26.useMemo)(() => listFailures(report), [report]);
|
|
3509
|
+
const filtered = (0, import_react26.useMemo)(
|
|
3407
3510
|
// Features carrying failures float to the top so the first thing on screen
|
|
3408
3511
|
// is the thing that needs attention; an all-green run keeps source order.
|
|
3409
3512
|
() => failuresFirst(
|
|
@@ -3416,7 +3519,7 @@ function ReportInteractiveView({
|
|
|
3416
3519
|
[report, deferredQuery, statusFilter, activeTags]
|
|
3417
3520
|
);
|
|
3418
3521
|
const isFiltering = query !== deferredQuery;
|
|
3419
|
-
const statusOptions = (0,
|
|
3522
|
+
const statusOptions = (0, import_react26.useMemo)(() => {
|
|
3420
3523
|
const s = report.summary;
|
|
3421
3524
|
const opts = [
|
|
3422
3525
|
{ key: "all", label: "All", count: s.total }
|
|
@@ -3431,21 +3534,21 @@ function ReportInteractiveView({
|
|
|
3431
3534
|
opts.push({ key: "pending", label: "Pending", count: s.pending });
|
|
3432
3535
|
return opts;
|
|
3433
3536
|
}, [report]);
|
|
3434
|
-
const tagOptions = (0,
|
|
3435
|
-
const toggleTag = (0,
|
|
3537
|
+
const tagOptions = (0, import_react26.useMemo)(() => allTags(report), [report]);
|
|
3538
|
+
const toggleTag = (0, import_react26.useCallback)(
|
|
3436
3539
|
(tag) => setUrlState({
|
|
3437
3540
|
tags: activeTags.includes(tag) ? activeTags.filter((t) => t !== tag) : [...activeTags, tag]
|
|
3438
3541
|
}),
|
|
3439
3542
|
[activeTags, setUrlState]
|
|
3440
3543
|
);
|
|
3441
|
-
const [toast, setToast] = (0,
|
|
3442
|
-
const toastTimer = (0,
|
|
3443
|
-
const showToast = (0,
|
|
3544
|
+
const [toast, setToast] = (0, import_react26.useState)(null);
|
|
3545
|
+
const toastTimer = (0, import_react26.useRef)(null);
|
|
3546
|
+
const showToast = (0, import_react26.useCallback)((msg) => {
|
|
3444
3547
|
setToast(msg);
|
|
3445
3548
|
if (toastTimer.current) clearTimeout(toastTimer.current);
|
|
3446
3549
|
toastTimer.current = setTimeout(() => setToast(null), 1800);
|
|
3447
3550
|
}, []);
|
|
3448
|
-
const copy = (0,
|
|
3551
|
+
const copy = (0, import_react26.useCallback)(
|
|
3449
3552
|
(text, msg) => {
|
|
3450
3553
|
if (typeof navigator !== "undefined" && navigator.clipboard) {
|
|
3451
3554
|
navigator.clipboard.writeText(text).then(
|
|
@@ -3456,7 +3559,7 @@ function ReportInteractiveView({
|
|
|
3456
3559
|
},
|
|
3457
3560
|
[showToast]
|
|
3458
3561
|
);
|
|
3459
|
-
const scenarioActions = (0,
|
|
3562
|
+
const scenarioActions = (0, import_react26.useMemo)(
|
|
3460
3563
|
() => ({
|
|
3461
3564
|
copyLink: (s) => copy(scenarioPermalink(s), "Link copied"),
|
|
3462
3565
|
copyMarkdown: (s) => copy(scenarioToMarkdown(s), "Markdown copied"),
|
|
@@ -3464,31 +3567,31 @@ function ReportInteractiveView({
|
|
|
3464
3567
|
}),
|
|
3465
3568
|
[copy]
|
|
3466
3569
|
);
|
|
3467
|
-
const copyAllFailures = (0,
|
|
3570
|
+
const copyAllFailures = (0, import_react26.useCallback)(
|
|
3468
3571
|
() => copy(failuresToPrompt(failedScenarios(filtered)), "Failures copied"),
|
|
3469
3572
|
[copy, filtered]
|
|
3470
3573
|
);
|
|
3471
|
-
const failureIndexRef = (0,
|
|
3472
|
-
const allCollapsibleIds = (0,
|
|
3574
|
+
const failureIndexRef = (0, import_react26.useRef)(0);
|
|
3575
|
+
const allCollapsibleIds = (0, import_react26.useMemo)(
|
|
3473
3576
|
() => report.features.flatMap((f) => [f.id, ...f.scenarios.map((s) => s.id)]),
|
|
3474
3577
|
[report]
|
|
3475
3578
|
);
|
|
3476
3579
|
const collapse = useCollapseState(
|
|
3477
|
-
(0,
|
|
3580
|
+
(0, import_react26.useCallback)(() => defaultCollapsedIds(report), [report])
|
|
3478
3581
|
);
|
|
3479
3582
|
const revealFilteredResults = deferredQuery.trim() !== "" || statusFilter !== "all" || activeTags.length > 0;
|
|
3480
|
-
const visibleCollapse = (0,
|
|
3583
|
+
const visibleCollapse = (0, import_react26.useMemo)(
|
|
3481
3584
|
() => revealFilteredResults ? { ...collapse.api, isCollapsed: () => false } : collapse.api,
|
|
3482
3585
|
[collapse.api, revealFilteredResults]
|
|
3483
3586
|
);
|
|
3484
|
-
const collapseAll = (0,
|
|
3587
|
+
const collapseAll = (0, import_react26.useCallback)(
|
|
3485
3588
|
() => collapse.collapseAll(allCollapsibleIds),
|
|
3486
3589
|
[collapse, allCollapsibleIds]
|
|
3487
3590
|
);
|
|
3488
|
-
const [expandedAll, setExpandedAll] = (0,
|
|
3591
|
+
const [expandedAll, setExpandedAll] = (0, import_react26.useState)(
|
|
3489
3592
|
() => report.summary.failed === 0
|
|
3490
3593
|
);
|
|
3491
|
-
const setExpanded = (0,
|
|
3594
|
+
const setExpanded = (0, import_react26.useCallback)(
|
|
3492
3595
|
(expanded) => {
|
|
3493
3596
|
if (expanded) collapse.expandAll();
|
|
3494
3597
|
else collapseAll();
|
|
@@ -3496,8 +3599,8 @@ function ReportInteractiveView({
|
|
|
3496
3599
|
},
|
|
3497
3600
|
[collapse, collapseAll]
|
|
3498
3601
|
);
|
|
3499
|
-
const [agentFilter, setAgentFilter] = (0,
|
|
3500
|
-
(0,
|
|
3602
|
+
const [agentFilter, setAgentFilter] = (0, import_react26.useState)(null);
|
|
3603
|
+
(0, import_react25.useTools)(
|
|
3501
3604
|
reportTools({
|
|
3502
3605
|
report,
|
|
3503
3606
|
view: urlState,
|
|
@@ -3506,14 +3609,14 @@ function ReportInteractiveView({
|
|
|
3506
3609
|
})
|
|
3507
3610
|
);
|
|
3508
3611
|
const showAgentFilter = agentFilter !== null && agentFilter.search === query && agentFilter.status === statusFilter && agentFilter.tags.length === activeTags.length && agentFilter.tags.every((tag) => activeTags.includes(tag));
|
|
3509
|
-
const clearFilters = (0,
|
|
3612
|
+
const clearFilters = (0, import_react26.useCallback)(
|
|
3510
3613
|
() => setUrlState({ query: "", status: "all", tags: [] }),
|
|
3511
3614
|
[setUrlState]
|
|
3512
3615
|
);
|
|
3513
|
-
const focusSearch = (0,
|
|
3616
|
+
const focusSearch = (0, import_react26.useCallback)(() => {
|
|
3514
3617
|
searchRef.current?.focus();
|
|
3515
3618
|
}, []);
|
|
3516
|
-
const stepFailure = (0,
|
|
3619
|
+
const stepFailure = (0, import_react26.useCallback)(
|
|
3517
3620
|
(direction) => {
|
|
3518
3621
|
if (failures.length === 0) return;
|
|
3519
3622
|
failureIndexRef.current = (failureIndexRef.current + direction + failures.length) % failures.length;
|
|
@@ -3522,10 +3625,10 @@ function ReportInteractiveView({
|
|
|
3522
3625
|
},
|
|
3523
3626
|
[failures]
|
|
3524
3627
|
);
|
|
3525
|
-
const toggleHelp = (0,
|
|
3628
|
+
const toggleHelp = (0, import_react26.useCallback)(() => {
|
|
3526
3629
|
setHelpOpen((v) => !v);
|
|
3527
3630
|
}, []);
|
|
3528
|
-
const escape = (0,
|
|
3631
|
+
const escape = (0, import_react26.useCallback)(() => {
|
|
3529
3632
|
if (helpOpen) setHelpOpen(false);
|
|
3530
3633
|
else if (query !== "") setQuery("");
|
|
3531
3634
|
}, [helpOpen, query, setQuery]);
|
|
@@ -3543,13 +3646,13 @@ function ReportInteractiveView({
|
|
|
3543
3646
|
const totalScenarios = report.summary.total;
|
|
3544
3647
|
const matchedScenarios = filtered.summary.total;
|
|
3545
3648
|
const showToc = !hideToc && totalScenarios > 3;
|
|
3546
|
-
return /* @__PURE__ */ (0,
|
|
3649
|
+
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)(
|
|
3547
3650
|
ReportRoot,
|
|
3548
3651
|
{
|
|
3549
3652
|
report: filtered,
|
|
3550
3653
|
customRenderers,
|
|
3551
3654
|
renderers,
|
|
3552
|
-
children: /* @__PURE__ */ (0,
|
|
3655
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3553
3656
|
"main",
|
|
3554
3657
|
{
|
|
3555
3658
|
className: cn("es-report", "es-report-interactive", className),
|
|
@@ -3558,8 +3661,8 @@ function ReportInteractiveView({
|
|
|
3558
3661
|
"data-theme": dataTheme,
|
|
3559
3662
|
"data-detail-level": detail,
|
|
3560
3663
|
children: [
|
|
3561
|
-
/* @__PURE__ */ (0,
|
|
3562
|
-
/* @__PURE__ */ (0,
|
|
3664
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("header", { className: "es-report-header", children: [
|
|
3665
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3563
3666
|
"div",
|
|
3564
3667
|
{
|
|
3565
3668
|
"data-es-navbar": true,
|
|
@@ -3568,9 +3671,9 @@ function ReportInteractiveView({
|
|
|
3568
3671
|
hideHeader ? "justify-end" : "justify-between"
|
|
3569
3672
|
),
|
|
3570
3673
|
children: [
|
|
3571
|
-
hideHeader ? null : /* @__PURE__ */ (0,
|
|
3572
|
-
/* @__PURE__ */ (0,
|
|
3573
|
-
/* @__PURE__ */ (0,
|
|
3674
|
+
hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("h1", { className: "min-w-0", children: title ?? "Story Report" }),
|
|
3675
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3676
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3574
3677
|
ReportSearch,
|
|
3575
3678
|
{
|
|
3576
3679
|
ref: searchRef,
|
|
@@ -3580,17 +3683,18 @@ function ReportInteractiveView({
|
|
|
3580
3683
|
totalCount: totalScenarios
|
|
3581
3684
|
}
|
|
3582
3685
|
),
|
|
3583
|
-
share ? /* @__PURE__ */ (0,
|
|
3584
|
-
/* @__PURE__ */ (0,
|
|
3686
|
+
share ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportShare, { command: shareCommand, onCopy: copy }) : null,
|
|
3687
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ThemeSegment, { pref: themePref, onPref: setThemePref })
|
|
3585
3688
|
] })
|
|
3586
3689
|
]
|
|
3587
3690
|
}
|
|
3588
3691
|
),
|
|
3589
|
-
hideHeader ? null : /* @__PURE__ */ (0,
|
|
3590
|
-
/* @__PURE__ */ (0,
|
|
3591
|
-
/* @__PURE__ */ (0,
|
|
3692
|
+
hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
|
|
3693
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportSummary, {}),
|
|
3694
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportMeta, {})
|
|
3592
3695
|
] }),
|
|
3593
|
-
/* @__PURE__ */ (0,
|
|
3696
|
+
architecture ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportSpanGraph, {}) : null,
|
|
3697
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3594
3698
|
ReportFreshness,
|
|
3595
3699
|
{
|
|
3596
3700
|
lastRunMs: reportLastRunMs(report),
|
|
@@ -3598,15 +3702,15 @@ function ReportInteractiveView({
|
|
|
3598
3702
|
staleAfterDays
|
|
3599
3703
|
}
|
|
3600
3704
|
),
|
|
3601
|
-
/* @__PURE__ */ (0,
|
|
3705
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3602
3706
|
ReportLastRunDelta,
|
|
3603
3707
|
{
|
|
3604
3708
|
history: scenarioHistory,
|
|
3605
3709
|
report
|
|
3606
3710
|
}
|
|
3607
3711
|
),
|
|
3608
|
-
/* @__PURE__ */ (0,
|
|
3609
|
-
/* @__PURE__ */ (0,
|
|
3712
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportSinceLastVisit, { report }),
|
|
3713
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3610
3714
|
ReportFilters,
|
|
3611
3715
|
{
|
|
3612
3716
|
statuses: statusOptions,
|
|
@@ -3617,10 +3721,10 @@ function ReportInteractiveView({
|
|
|
3617
3721
|
onToggleTag: toggleTag
|
|
3618
3722
|
}
|
|
3619
3723
|
),
|
|
3620
|
-
/* @__PURE__ */ (0,
|
|
3621
|
-
showToc ? /* @__PURE__ */ (0,
|
|
3622
|
-
/* @__PURE__ */ (0,
|
|
3623
|
-
/* @__PURE__ */ (0,
|
|
3724
|
+
/* @__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: [
|
|
3725
|
+
showToc ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportTocDrawer, {}) : null,
|
|
3726
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3727
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3624
3728
|
Switch,
|
|
3625
3729
|
{
|
|
3626
3730
|
id: expandId,
|
|
@@ -3628,7 +3732,7 @@ function ReportInteractiveView({
|
|
|
3628
3732
|
onCheckedChange: setExpanded
|
|
3629
3733
|
}
|
|
3630
3734
|
),
|
|
3631
|
-
/* @__PURE__ */ (0,
|
|
3735
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3632
3736
|
"label",
|
|
3633
3737
|
{
|
|
3634
3738
|
htmlFor: expandId,
|
|
@@ -3637,8 +3741,8 @@ function ReportInteractiveView({
|
|
|
3637
3741
|
}
|
|
3638
3742
|
)
|
|
3639
3743
|
] }),
|
|
3640
|
-
/* @__PURE__ */ (0,
|
|
3641
|
-
/* @__PURE__ */ (0,
|
|
3744
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3745
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3642
3746
|
Switch,
|
|
3643
3747
|
{
|
|
3644
3748
|
id: docsId,
|
|
@@ -3646,7 +3750,7 @@ function ReportInteractiveView({
|
|
|
3646
3750
|
onCheckedChange: (checked) => setDetail(checked ? "full" : "minimal")
|
|
3647
3751
|
}
|
|
3648
3752
|
),
|
|
3649
|
-
/* @__PURE__ */ (0,
|
|
3753
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3650
3754
|
"label",
|
|
3651
3755
|
{
|
|
3652
3756
|
htmlFor: docsId,
|
|
@@ -3657,7 +3761,7 @@ function ReportInteractiveView({
|
|
|
3657
3761
|
] })
|
|
3658
3762
|
] })
|
|
3659
3763
|
] }),
|
|
3660
|
-
showAgentFilter ? /* @__PURE__ */ (0,
|
|
3764
|
+
showAgentFilter ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3661
3765
|
ReportAgentFilterNotice,
|
|
3662
3766
|
{
|
|
3663
3767
|
applied: agentFilter,
|
|
@@ -3665,17 +3769,17 @@ function ReportInteractiveView({
|
|
|
3665
3769
|
onDismiss: () => setAgentFilter(null)
|
|
3666
3770
|
}
|
|
3667
3771
|
) : null,
|
|
3668
|
-
/* @__PURE__ */ (0,
|
|
3669
|
-
hasContent ? showToc ? /* @__PURE__ */ (0,
|
|
3670
|
-
/* @__PURE__ */ (0,
|
|
3671
|
-
/* @__PURE__ */ (0,
|
|
3672
|
-
] }) : /* @__PURE__ */ (0,
|
|
3772
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportFailureBanner, { failures, onCopyAll: copyAllFailures }),
|
|
3773
|
+
hasContent ? showToc ? /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex gap-6", children: [
|
|
3774
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ReportToc, {}),
|
|
3775
|
+
/* @__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, {}) })
|
|
3776
|
+
] }) : /* @__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)(
|
|
3673
3777
|
ReportEmpty,
|
|
3674
3778
|
{
|
|
3675
3779
|
message: query ? "No scenarios match the search." : void 0
|
|
3676
3780
|
}
|
|
3677
3781
|
),
|
|
3678
|
-
/* @__PURE__ */ (0,
|
|
3782
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3679
3783
|
"button",
|
|
3680
3784
|
{
|
|
3681
3785
|
type: "button",
|
|
@@ -3686,14 +3790,14 @@ function ReportInteractiveView({
|
|
|
3686
3790
|
children: "?"
|
|
3687
3791
|
}
|
|
3688
3792
|
),
|
|
3689
|
-
/* @__PURE__ */ (0,
|
|
3793
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3690
3794
|
ReportShortcutsHelp,
|
|
3691
3795
|
{
|
|
3692
3796
|
open: helpOpen,
|
|
3693
3797
|
onClose: () => setHelpOpen(false)
|
|
3694
3798
|
}
|
|
3695
3799
|
),
|
|
3696
|
-
toast ? /* @__PURE__ */ (0,
|
|
3800
|
+
toast ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3697
3801
|
"div",
|
|
3698
3802
|
{
|
|
3699
3803
|
role: "status",
|
|
@@ -3710,14 +3814,14 @@ function ReportInteractiveView({
|
|
|
3710
3814
|
}
|
|
3711
3815
|
|
|
3712
3816
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
3713
|
-
var
|
|
3817
|
+
var import_react29 = require("react");
|
|
3714
3818
|
|
|
3715
3819
|
// src/interactive/island-renderers.tsx
|
|
3716
|
-
var
|
|
3820
|
+
var import_react28 = require("react");
|
|
3717
3821
|
|
|
3718
3822
|
// src/components/doc/MermaidView.tsx
|
|
3719
|
-
var
|
|
3720
|
-
var
|
|
3823
|
+
var import_react27 = require("react");
|
|
3824
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
3721
3825
|
function prefersDark(el) {
|
|
3722
3826
|
const themed = el?.closest("[data-theme]");
|
|
3723
3827
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -3725,10 +3829,10 @@ function prefersDark(el) {
|
|
|
3725
3829
|
return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
|
|
3726
3830
|
}
|
|
3727
3831
|
function MermaidView({ entry, load }) {
|
|
3728
|
-
const ref = (0,
|
|
3729
|
-
const [svg, setSvg] = (0,
|
|
3730
|
-
const [error, setError] = (0,
|
|
3731
|
-
(0,
|
|
3832
|
+
const ref = (0, import_react27.useRef)(null);
|
|
3833
|
+
const [svg, setSvg] = (0, import_react27.useState)(null);
|
|
3834
|
+
const [error, setError] = (0, import_react27.useState)(null);
|
|
3835
|
+
(0, import_react27.useEffect)(() => {
|
|
3732
3836
|
let cancelled = false;
|
|
3733
3837
|
const draw = async () => {
|
|
3734
3838
|
let mermaid;
|
|
@@ -3745,7 +3849,10 @@ function MermaidView({ entry, load }) {
|
|
|
3745
3849
|
mermaid.initialize({
|
|
3746
3850
|
startOnLoad: false,
|
|
3747
3851
|
securityLevel: "strict",
|
|
3748
|
-
|
|
3852
|
+
// "neutral" in light: the same theme the static, no-JS render uses
|
|
3853
|
+
// in ssr-entry, so a diagram keeps its colours when the island takes
|
|
3854
|
+
// over.
|
|
3855
|
+
theme: prefersDark(ref.current) ? "dark" : "neutral"
|
|
3749
3856
|
});
|
|
3750
3857
|
await mermaid.parse(entry.code);
|
|
3751
3858
|
const id = `es-mermaid-${Math.random().toString(36).slice(2)}`;
|
|
@@ -3771,9 +3878,9 @@ function MermaidView({ entry, load }) {
|
|
|
3771
3878
|
};
|
|
3772
3879
|
}, [entry.code, load]);
|
|
3773
3880
|
if (svg) {
|
|
3774
|
-
return /* @__PURE__ */ (0,
|
|
3775
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
3776
|
-
/* @__PURE__ */ (0,
|
|
3881
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("figure", { ref, className: "my-3", children: [
|
|
3882
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
3883
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3777
3884
|
"div",
|
|
3778
3885
|
{
|
|
3779
3886
|
role: "img",
|
|
@@ -3784,8 +3891,8 @@ function MermaidView({ entry, load }) {
|
|
|
3784
3891
|
)
|
|
3785
3892
|
] });
|
|
3786
3893
|
}
|
|
3787
|
-
return /* @__PURE__ */ (0,
|
|
3788
|
-
error ? /* @__PURE__ */ (0,
|
|
3894
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
|
|
3895
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
3789
3896
|
"p",
|
|
3790
3897
|
{
|
|
3791
3898
|
role: "alert",
|
|
@@ -3797,14 +3904,14 @@ function MermaidView({ entry, load }) {
|
|
|
3797
3904
|
]
|
|
3798
3905
|
}
|
|
3799
3906
|
) : null,
|
|
3800
|
-
/* @__PURE__ */ (0,
|
|
3907
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(MermaidSource, { entry, ref })
|
|
3801
3908
|
] });
|
|
3802
3909
|
}
|
|
3803
3910
|
|
|
3804
3911
|
// src/interactive/island-renderers.tsx
|
|
3805
|
-
var
|
|
3912
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
3806
3913
|
var HLJS_ESM = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
|
|
3807
|
-
var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@
|
|
3914
|
+
var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs";
|
|
3808
3915
|
function cachedCdnModule(url) {
|
|
3809
3916
|
let loader;
|
|
3810
3917
|
return () => {
|
|
@@ -3819,8 +3926,8 @@ function cachedCdnModule(url) {
|
|
|
3819
3926
|
var loadMermaidFromCdn = cachedCdnModule(MERMAID_ESM);
|
|
3820
3927
|
var loadHljs = cachedCdnModule(HLJS_ESM);
|
|
3821
3928
|
function CdnHighlightedCode({ entry }) {
|
|
3822
|
-
const [html, setHtml] = (0,
|
|
3823
|
-
(0,
|
|
3929
|
+
const [html, setHtml] = (0, import_react28.useState)(null);
|
|
3930
|
+
(0, import_react28.useEffect)(() => {
|
|
3824
3931
|
let cancelled = false;
|
|
3825
3932
|
void (async () => {
|
|
3826
3933
|
try {
|
|
@@ -3836,27 +3943,27 @@ function CdnHighlightedCode({ entry }) {
|
|
|
3836
3943
|
cancelled = true;
|
|
3837
3944
|
};
|
|
3838
3945
|
}, [entry.content, entry.lang]);
|
|
3839
|
-
return /* @__PURE__ */ (0,
|
|
3946
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
3840
3947
|
"code",
|
|
3841
3948
|
{
|
|
3842
3949
|
className: cn("hljs font-mono text-xs", entry.lang && `language-${entry.lang}`),
|
|
3843
3950
|
dangerouslySetInnerHTML: { __html: html }
|
|
3844
3951
|
}
|
|
3845
|
-
) : /* @__PURE__ */ (0,
|
|
3952
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
3846
3953
|
}
|
|
3847
3954
|
function buildIslandRenderers(opts) {
|
|
3848
3955
|
const renderers = {};
|
|
3849
3956
|
if (opts.mermaid) {
|
|
3850
|
-
renderers.mermaid = (entry) => (0,
|
|
3957
|
+
renderers.mermaid = (entry) => (0, import_react28.createElement)(MermaidView, { entry, load: loadMermaidFromCdn });
|
|
3851
3958
|
}
|
|
3852
3959
|
if (opts.syntaxHighlighting) {
|
|
3853
|
-
renderers.code = (entry) => (0,
|
|
3960
|
+
renderers.code = (entry) => (0, import_react28.createElement)(CdnHighlightedCode, { entry });
|
|
3854
3961
|
}
|
|
3855
3962
|
return renderers;
|
|
3856
3963
|
}
|
|
3857
3964
|
|
|
3858
3965
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
3859
|
-
var
|
|
3966
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
3860
3967
|
function ReportInteractiveIsland({
|
|
3861
3968
|
report,
|
|
3862
3969
|
title,
|
|
@@ -3866,11 +3973,11 @@ function ReportInteractiveIsland({
|
|
|
3866
3973
|
syntaxHighlighting = true,
|
|
3867
3974
|
mermaid = true
|
|
3868
3975
|
}) {
|
|
3869
|
-
const renderers = (0,
|
|
3976
|
+
const renderers = (0, import_react29.useMemo)(
|
|
3870
3977
|
() => buildIslandRenderers({ syntaxHighlighting, mermaid }),
|
|
3871
3978
|
[syntaxHighlighting, mermaid]
|
|
3872
3979
|
);
|
|
3873
|
-
return /* @__PURE__ */ (0,
|
|
3980
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
3874
3981
|
ReportInteractive,
|
|
3875
3982
|
{
|
|
3876
3983
|
report,
|