executable-stories-react 0.13.0 → 0.15.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 +73 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +73 -52
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +485 -227
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +7 -1
- package/dist/interactive.d.ts +7 -1
- package/dist/interactive.js +443 -185
- package/dist/interactive.js.map +1 -1
- package/dist/report-island.global.js +43 -41
- package/dist/ssr.cjs +78 -54
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.d.cts +4 -0
- package/dist/ssr.d.ts +4 -0
- package/dist/ssr.js +78 -54
- package/dist/ssr.js.map +1 -1
- package/dist/styles.css +1 -3
- package/dist/tailwind.css +1 -1
- package/package.json +2 -2
package/dist/interactive.js
CHANGED
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
useDeferredValue,
|
|
9
9
|
useId as useId2,
|
|
10
10
|
useMemo as useMemo3,
|
|
11
|
-
useRef as
|
|
12
|
-
useState as
|
|
11
|
+
useRef as useRef6,
|
|
12
|
+
useState as useState11
|
|
13
13
|
} from "react";
|
|
14
14
|
|
|
15
15
|
// src/components/ui/empty.tsx
|
|
@@ -206,7 +206,7 @@ function formatValue(value) {
|
|
|
206
206
|
function DocKv({ entry }) {
|
|
207
207
|
return /* @__PURE__ */ jsxs("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
|
|
208
208
|
/* @__PURE__ */ jsx6("dt", { className: "font-semibold text-muted-foreground", children: entry.label }),
|
|
209
|
-
/* @__PURE__ */ jsx6("dd", { className: "font-mono text-foreground", children: formatValue(entry.value) })
|
|
209
|
+
/* @__PURE__ */ jsx6("dd", { className: "min-w-0 break-words font-mono text-foreground", children: formatValue(entry.value) })
|
|
210
210
|
] });
|
|
211
211
|
}
|
|
212
212
|
|
|
@@ -414,7 +414,7 @@ function DocHtml({ entry }) {
|
|
|
414
414
|
loading: "lazy",
|
|
415
415
|
title,
|
|
416
416
|
className: "block w-full border-0",
|
|
417
|
-
style: { height }
|
|
417
|
+
style: { height, colorScheme: "light", background: "#fff" }
|
|
418
418
|
}
|
|
419
419
|
)
|
|
420
420
|
] });
|
|
@@ -1138,6 +1138,24 @@ function scenarioToPrompt(scenario) {
|
|
|
1138
1138
|
}
|
|
1139
1139
|
return lines.join("\n");
|
|
1140
1140
|
}
|
|
1141
|
+
function failuresToPrompt(scenarios) {
|
|
1142
|
+
if (scenarios.length === 0) return "";
|
|
1143
|
+
const noun = scenarios.length === 1 ? "test scenario is" : "test scenarios are";
|
|
1144
|
+
const lines = [
|
|
1145
|
+
`${scenarios.length} ${noun} failing. Investigate the likely cause (they may share one) and propose a fix.`
|
|
1146
|
+
];
|
|
1147
|
+
scenarios.forEach((scenario, i) => {
|
|
1148
|
+
lines.push("", `${i + 1}. ${scenario.title}`, "Steps:");
|
|
1149
|
+
for (const step of scenario.steps) {
|
|
1150
|
+
const mark = step.status === "failed" ? " \u27F5 failed here" : "";
|
|
1151
|
+
lines.push(` ${step.keyword} ${step.text}${mark}`);
|
|
1152
|
+
}
|
|
1153
|
+
if (scenario.errorMessage) {
|
|
1154
|
+
lines.push("Error:", scenario.errorMessage.trim());
|
|
1155
|
+
}
|
|
1156
|
+
});
|
|
1157
|
+
return lines.join("\n");
|
|
1158
|
+
}
|
|
1141
1159
|
function scenarioPermalink(scenario) {
|
|
1142
1160
|
if (typeof location === "undefined") return `#${scenario.id}`;
|
|
1143
1161
|
return `${location.href.split("#")[0]}#${scenario.id}`;
|
|
@@ -1263,57 +1281,68 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1263
1281
|
className: "gap-0 py-0",
|
|
1264
1282
|
children: [
|
|
1265
1283
|
/* @__PURE__ */ jsxs17(CardHeader, { className: "px-4 py-3", children: [
|
|
1266
|
-
/* @__PURE__ */ jsxs17(
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1284
|
+
/* @__PURE__ */ jsxs17(
|
|
1285
|
+
"div",
|
|
1286
|
+
{
|
|
1287
|
+
className: cn(
|
|
1288
|
+
// Wraps rather than squeezing: on a phone the status/duration group
|
|
1289
|
+
// is ~160px, which leaves a title column a few characters wide.
|
|
1290
|
+
"flex flex-wrap items-start gap-x-4 gap-y-1",
|
|
1291
|
+
hideTitle ? "justify-end" : "justify-between"
|
|
1292
|
+
),
|
|
1293
|
+
children: [
|
|
1294
|
+
hideTitle ? null : /* @__PURE__ */ jsxs17("h3", { id: titleId, className: "flex min-w-0 flex-1 basis-48 items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
1295
|
+
collapsible ? /* @__PURE__ */ jsx26(
|
|
1296
|
+
"button",
|
|
1297
|
+
{
|
|
1298
|
+
type: "button",
|
|
1299
|
+
onClick: () => collapse.toggle(scenario.id),
|
|
1300
|
+
"aria-expanded": !collapsed,
|
|
1301
|
+
"aria-controls": bodyId,
|
|
1302
|
+
"aria-label": `Toggle ${scenario.title}`,
|
|
1303
|
+
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
1304
|
+
children: /* @__PURE__ */ jsx26("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
1305
|
+
}
|
|
1306
|
+
) : null,
|
|
1307
|
+
/* @__PURE__ */ jsx26("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
1308
|
+
/* @__PURE__ */ jsx26("span", { children: scenario.title })
|
|
1309
|
+
] }),
|
|
1310
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1311
|
+
/* @__PURE__ */ jsx26(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1312
|
+
/* @__PURE__ */ jsx26(ScenarioStaleness, { scenario }),
|
|
1313
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ jsx26("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration3(scenario.durationMs) }) : null,
|
|
1314
|
+
meta.showPill ? /* @__PURE__ */ jsx26(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ jsx26("span", { className: "sr-only", children: `Status: ${label}` }),
|
|
1315
|
+
actions ? /* @__PURE__ */ jsxs17(DropdownMenu, { children: [
|
|
1316
|
+
/* @__PURE__ */ jsx26(
|
|
1317
|
+
DropdownMenuTrigger,
|
|
1318
|
+
{
|
|
1319
|
+
"aria-label": `Actions for ${scenario.title}`,
|
|
1320
|
+
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
1321
|
+
children: /* @__PURE__ */ jsx26(MoreHorizontalIcon, { "aria-hidden": true })
|
|
1322
|
+
}
|
|
1323
|
+
),
|
|
1324
|
+
/* @__PURE__ */ jsxs17(DropdownMenuContent, { align: "end", children: [
|
|
1325
|
+
/* @__PURE__ */ jsxs17(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
1326
|
+
/* @__PURE__ */ jsx26(LinkIcon, {}),
|
|
1327
|
+
" Copy link"
|
|
1328
|
+
] }),
|
|
1329
|
+
/* @__PURE__ */ jsxs17(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
1330
|
+
/* @__PURE__ */ jsx26(FileTextIcon, {}),
|
|
1331
|
+
" Copy as Markdown"
|
|
1332
|
+
] }),
|
|
1333
|
+
/* @__PURE__ */ jsxs17(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
1334
|
+
/* @__PURE__ */ jsx26(SparklesIcon, {}),
|
|
1335
|
+
" Explain with AI"
|
|
1336
|
+
] })
|
|
1337
|
+
] })
|
|
1338
|
+
] }) : null
|
|
1310
1339
|
] })
|
|
1311
|
-
]
|
|
1312
|
-
|
|
1313
|
-
|
|
1340
|
+
]
|
|
1341
|
+
}
|
|
1342
|
+
),
|
|
1314
1343
|
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs17("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
|
|
1315
1344
|
scenario.tags.map((t) => /* @__PURE__ */ jsx26("li", { children: /* @__PURE__ */ jsx26(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
|
|
1316
|
-
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ jsx26("li", { children: ticket.url ? /* @__PURE__ */ jsx26("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ jsx26(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ jsx26(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
|
|
1345
|
+
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ jsx26("li", { children: ticket.url ? /* @__PURE__ */ jsx26("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", className: "inline-flex min-h-6 items-center", children: /* @__PURE__ */ jsx26(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ jsx26(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
|
|
1317
1346
|
] }) : null
|
|
1318
1347
|
] }),
|
|
1319
1348
|
/* @__PURE__ */ jsxs17(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
@@ -1456,6 +1485,7 @@ function ReportFeatureList() {
|
|
|
1456
1485
|
|
|
1457
1486
|
// src/components/ReportMeta.tsx
|
|
1458
1487
|
import { formatDuration as formatDuration4 } from "executable-stories-core/utils/duration";
|
|
1488
|
+
import { slowestScenarios } from "executable-stories-core/report-queries";
|
|
1459
1489
|
import { jsx as jsx31, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1460
1490
|
function ReportMeta() {
|
|
1461
1491
|
const report = useReport();
|
|
@@ -1499,7 +1529,9 @@ function ReportMeta() {
|
|
|
1499
1529
|
value: url ? /* @__PURE__ */ jsx31("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1500
1530
|
});
|
|
1501
1531
|
}
|
|
1502
|
-
|
|
1532
|
+
const slowest = slowestScenarios(report, 5);
|
|
1533
|
+
const showSlowest = slowest.length >= 3;
|
|
1534
|
+
if (items.length === 0 && !showSlowest) return null;
|
|
1503
1535
|
return (
|
|
1504
1536
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1505
1537
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
@@ -1512,7 +1544,14 @@ function ReportMeta() {
|
|
|
1512
1544
|
/* @__PURE__ */ jsx31("dl", { className: "flex flex-wrap gap-x-5 gap-y-2 border-t border-border px-4 py-3 text-muted-foreground", "aria-label": "Run metadata", children: items.map((item) => /* @__PURE__ */ jsxs20("div", { className: "flex items-baseline gap-1.5", children: [
|
|
1513
1545
|
/* @__PURE__ */ jsx31("dt", { className: "font-medium", children: item.label }),
|
|
1514
1546
|
/* @__PURE__ */ jsx31("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1515
|
-
] }, item.label)) })
|
|
1547
|
+
] }, item.label)) }),
|
|
1548
|
+
showSlowest ? /* @__PURE__ */ jsxs20("div", { className: "border-t border-border px-4 py-3", children: [
|
|
1549
|
+
/* @__PURE__ */ jsx31("div", { className: "mb-1.5 font-medium text-muted-foreground", children: "Slowest scenarios" }),
|
|
1550
|
+
/* @__PURE__ */ jsx31("ol", { className: "flex flex-col gap-1", "aria-label": "Slowest scenarios", children: slowest.map((s) => /* @__PURE__ */ jsxs20("li", { className: "flex items-baseline justify-between gap-4", children: [
|
|
1551
|
+
/* @__PURE__ */ jsx31("a", { href: `#${s.id}`, className: "min-w-0 text-primary underline underline-offset-2", children: s.title }),
|
|
1552
|
+
/* @__PURE__ */ jsx31("span", { className: "shrink-0 font-mono tabular-nums text-muted-foreground", children: formatDuration4(s.durationMs) })
|
|
1553
|
+
] }, s.id)) })
|
|
1554
|
+
] }) : null
|
|
1516
1555
|
] })
|
|
1517
1556
|
);
|
|
1518
1557
|
}
|
|
@@ -1988,21 +2027,26 @@ function allTags(report) {
|
|
|
1988
2027
|
}
|
|
1989
2028
|
return [...seen];
|
|
1990
2029
|
}
|
|
1991
|
-
function queryMatches(scenario, q) {
|
|
2030
|
+
function queryMatches(scenario, q, sourceFile) {
|
|
1992
2031
|
if (q === "") return true;
|
|
1993
2032
|
if (scenario.title.toLowerCase().includes(q)) return true;
|
|
2033
|
+
if (sourceFile?.toLowerCase().includes(q)) return true;
|
|
2034
|
+
if (scenario.errorMessage?.toLowerCase().includes(q)) return true;
|
|
1994
2035
|
for (const tag of scenario.tags) {
|
|
1995
2036
|
if (tag.toLowerCase().includes(q)) return true;
|
|
1996
2037
|
}
|
|
2038
|
+
for (const ticket of scenario.tickets ?? []) {
|
|
2039
|
+
if (ticket.id.toLowerCase().includes(q)) return true;
|
|
2040
|
+
}
|
|
1997
2041
|
for (const step of scenario.steps) {
|
|
1998
2042
|
if (step.text.toLowerCase().includes(q)) return true;
|
|
1999
2043
|
}
|
|
2000
2044
|
return false;
|
|
2001
2045
|
}
|
|
2002
|
-
function scenarioMatches(scenario, q, status, tags) {
|
|
2046
|
+
function scenarioMatches(scenario, q, status, tags, sourceFile) {
|
|
2003
2047
|
if (status !== "all" && scenario.status !== status) return false;
|
|
2004
2048
|
if (tags.length > 0 && !tags.some((t) => scenario.tags.includes(t))) return false;
|
|
2005
|
-
return queryMatches(scenario, q);
|
|
2049
|
+
return queryMatches(scenario, q, sourceFile);
|
|
2006
2050
|
}
|
|
2007
2051
|
function summarizeScenarios(scenarios) {
|
|
2008
2052
|
let total = 0, passed = 0, failed = 0, skipped = 0, pending = 0, durationMs = 0;
|
|
@@ -2025,7 +2069,9 @@ function filterReport(report, criteria) {
|
|
|
2025
2069
|
const features = [];
|
|
2026
2070
|
let topTotal = 0, topPassed = 0, topFailed = 0, topSkipped = 0, topPending = 0, topDuration = 0;
|
|
2027
2071
|
for (const feature of report.features) {
|
|
2028
|
-
const matched = feature.scenarios.filter(
|
|
2072
|
+
const matched = feature.scenarios.filter(
|
|
2073
|
+
(s) => scenarioMatches(s, q, status, tags, feature.sourceFile)
|
|
2074
|
+
);
|
|
2029
2075
|
if (matched.length === 0) continue;
|
|
2030
2076
|
const summary = summarizeScenarios(matched);
|
|
2031
2077
|
features.push({ ...feature, summary, scenarios: matched });
|
|
@@ -2049,6 +2095,9 @@ function filterReport(report, criteria) {
|
|
|
2049
2095
|
features
|
|
2050
2096
|
};
|
|
2051
2097
|
}
|
|
2098
|
+
function failedScenarios(report) {
|
|
2099
|
+
return report.features.flatMap((f) => f.scenarios.filter((s) => s.status === "failed"));
|
|
2100
|
+
}
|
|
2052
2101
|
function listFailures(report) {
|
|
2053
2102
|
const out = [];
|
|
2054
2103
|
for (const feature of report.features) {
|
|
@@ -2132,7 +2181,7 @@ function ReportAgentFilterNotice({
|
|
|
2132
2181
|
// src/interactive/ReportFailureBanner.tsx
|
|
2133
2182
|
import { useCallback as useCallback2 } from "react";
|
|
2134
2183
|
import { jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2135
|
-
function ReportFailureBanner({ failures }) {
|
|
2184
|
+
function ReportFailureBanner({ failures, onCopyAll }) {
|
|
2136
2185
|
const first = failures[0];
|
|
2137
2186
|
const jumpToFirst = useCallback2(() => {
|
|
2138
2187
|
if (!first) return;
|
|
@@ -2162,7 +2211,23 @@ function ReportFailureBanner({ failures }) {
|
|
|
2162
2211
|
"aria-label": "View first failure",
|
|
2163
2212
|
children: "View first failure \u2193"
|
|
2164
2213
|
}
|
|
2165
|
-
)
|
|
2214
|
+
),
|
|
2215
|
+
onCopyAll ? /* @__PURE__ */ jsxs26(
|
|
2216
|
+
"button",
|
|
2217
|
+
{
|
|
2218
|
+
type: "button",
|
|
2219
|
+
className: "es-failure-banner-jump",
|
|
2220
|
+
onClick: onCopyAll,
|
|
2221
|
+
"aria-label": "Copy failures for an agent",
|
|
2222
|
+
children: [
|
|
2223
|
+
"Copy ",
|
|
2224
|
+
failures.length,
|
|
2225
|
+
" failure",
|
|
2226
|
+
failures.length === 1 ? "" : "s",
|
|
2227
|
+
" for an agent"
|
|
2228
|
+
]
|
|
2229
|
+
}
|
|
2230
|
+
) : null
|
|
2166
2231
|
]
|
|
2167
2232
|
}
|
|
2168
2233
|
);
|
|
@@ -2370,7 +2435,7 @@ var ReportSearch = forwardRef(
|
|
|
2370
2435
|
onChange,
|
|
2371
2436
|
matchedCount,
|
|
2372
2437
|
totalCount,
|
|
2373
|
-
placeholder = "Search scenarios
|
|
2438
|
+
placeholder = "Search scenarios, tags, tickets, errors\u2026",
|
|
2374
2439
|
className
|
|
2375
2440
|
} = props;
|
|
2376
2441
|
const inputId = useId();
|
|
@@ -2428,8 +2493,9 @@ var ReportSearch = forwardRef(
|
|
|
2428
2493
|
}
|
|
2429
2494
|
);
|
|
2430
2495
|
|
|
2431
|
-
// src/interactive/
|
|
2432
|
-
import {
|
|
2496
|
+
// src/interactive/ReportShare.tsx
|
|
2497
|
+
import { Share2 } from "lucide-react";
|
|
2498
|
+
import { useEffect as useEffect3, useRef, useState as useState5 } from "react";
|
|
2433
2499
|
|
|
2434
2500
|
// src/components/ui/button.tsx
|
|
2435
2501
|
import "react";
|
|
@@ -2484,8 +2550,192 @@ function Button({
|
|
|
2484
2550
|
});
|
|
2485
2551
|
}
|
|
2486
2552
|
|
|
2553
|
+
// src/interactive/ReportShare.tsx
|
|
2554
|
+
import { Fragment as Fragment14, jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2555
|
+
var DEFAULT_SHARE_COMMAND = "npx executable-stories share reports/";
|
|
2556
|
+
function ReportShare({
|
|
2557
|
+
command = DEFAULT_SHARE_COMMAND,
|
|
2558
|
+
onCopy
|
|
2559
|
+
}) {
|
|
2560
|
+
const [open, setOpen] = useState5(false);
|
|
2561
|
+
const dialogRef = useRef(null);
|
|
2562
|
+
useEffect3(() => {
|
|
2563
|
+
const dialog = dialogRef.current;
|
|
2564
|
+
if (!dialog) return;
|
|
2565
|
+
if (open && !dialog.open) dialog.showModal();
|
|
2566
|
+
else if (!open && dialog.open) dialog.close();
|
|
2567
|
+
}, [open]);
|
|
2568
|
+
return /* @__PURE__ */ jsxs31(Fragment14, { children: [
|
|
2569
|
+
/* @__PURE__ */ jsxs31(
|
|
2570
|
+
Button,
|
|
2571
|
+
{
|
|
2572
|
+
type: "button",
|
|
2573
|
+
variant: "ghost",
|
|
2574
|
+
size: "sm",
|
|
2575
|
+
"aria-label": "Share this report",
|
|
2576
|
+
title: "Share this report",
|
|
2577
|
+
onClick: () => setOpen(true),
|
|
2578
|
+
children: [
|
|
2579
|
+
/* @__PURE__ */ jsx46(Share2, { "aria-hidden": "true", className: "size-4" }),
|
|
2580
|
+
/* @__PURE__ */ jsx46("span", { className: "sr-only sm:not-sr-only", children: "Share" })
|
|
2581
|
+
]
|
|
2582
|
+
}
|
|
2583
|
+
),
|
|
2584
|
+
/* @__PURE__ */ jsxs31(
|
|
2585
|
+
"dialog",
|
|
2586
|
+
{
|
|
2587
|
+
ref: dialogRef,
|
|
2588
|
+
className: "es-report-share m-auto w-[min(90vw,32rem)] rounded-lg border border-border bg-card p-6 text-card-foreground shadow-lg [overscroll-behavior:contain] backdrop:bg-black/40",
|
|
2589
|
+
"aria-label": "Share this report",
|
|
2590
|
+
onClose: () => setOpen(false),
|
|
2591
|
+
children: [
|
|
2592
|
+
/* @__PURE__ */ jsx46("h2", { className: "text-base font-semibold", children: "Share this report" }),
|
|
2593
|
+
/* @__PURE__ */ jsx46("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:" }),
|
|
2594
|
+
/* @__PURE__ */ jsxs31("div", { className: "mt-4 flex items-center gap-2", children: [
|
|
2595
|
+
/* @__PURE__ */ jsx46("code", { className: "min-w-0 flex-1 truncate rounded border border-border bg-muted px-3 py-2 font-mono text-xs", children: command }),
|
|
2596
|
+
/* @__PURE__ */ jsx46(
|
|
2597
|
+
Button,
|
|
2598
|
+
{
|
|
2599
|
+
type: "button",
|
|
2600
|
+
size: "sm",
|
|
2601
|
+
onClick: () => onCopy(command, "Command copied"),
|
|
2602
|
+
children: "Copy"
|
|
2603
|
+
}
|
|
2604
|
+
)
|
|
2605
|
+
] }),
|
|
2606
|
+
/* @__PURE__ */ jsx46("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." }),
|
|
2607
|
+
/* @__PURE__ */ jsxs31("div", { className: "mt-6 flex items-center justify-between gap-4", children: [
|
|
2608
|
+
/* @__PURE__ */ jsx46(
|
|
2609
|
+
"a",
|
|
2610
|
+
{
|
|
2611
|
+
className: "text-xs underline underline-offset-2",
|
|
2612
|
+
href: "https://executablestories.com/guides/sharing-reports/",
|
|
2613
|
+
target: "_blank",
|
|
2614
|
+
rel: "noreferrer",
|
|
2615
|
+
children: "How sharing works"
|
|
2616
|
+
}
|
|
2617
|
+
),
|
|
2618
|
+
/* @__PURE__ */ jsx46(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setOpen(false), children: "Close" })
|
|
2619
|
+
] })
|
|
2620
|
+
]
|
|
2621
|
+
}
|
|
2622
|
+
)
|
|
2623
|
+
] });
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2626
|
+
// src/interactive/ReportSinceLastVisit.tsx
|
|
2627
|
+
import { useEffect as useEffect4, useState as useState6 } from "react";
|
|
2628
|
+
|
|
2629
|
+
// src/interactive/last-visit.ts
|
|
2630
|
+
function snapshotOf(report, atMs) {
|
|
2631
|
+
const statuses = {};
|
|
2632
|
+
for (const feature of report.features) {
|
|
2633
|
+
for (const scenario of feature.scenarios) {
|
|
2634
|
+
statuses[scenario.id] = scenario.status;
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
return { runId: report.runId, atMs, statuses };
|
|
2638
|
+
}
|
|
2639
|
+
function diffSinceVisit(previous, report) {
|
|
2640
|
+
if (!previous) return null;
|
|
2641
|
+
if (previous.runId === report.runId) return null;
|
|
2642
|
+
const newlyFailing = [];
|
|
2643
|
+
const newlyPassing = [];
|
|
2644
|
+
const added = [];
|
|
2645
|
+
for (const feature of report.features) {
|
|
2646
|
+
for (const scenario of feature.scenarios) {
|
|
2647
|
+
const ref = { id: scenario.id, title: scenario.title };
|
|
2648
|
+
const before = previous.statuses[scenario.id];
|
|
2649
|
+
if (before === void 0) {
|
|
2650
|
+
added.push(ref);
|
|
2651
|
+
} else if (before !== "failed" && scenario.status === "failed") {
|
|
2652
|
+
newlyFailing.push(ref);
|
|
2653
|
+
} else if (before === "failed" && scenario.status === "passed") {
|
|
2654
|
+
newlyPassing.push(ref);
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) return null;
|
|
2659
|
+
return { sinceMs: previous.atMs, newlyFailing, newlyPassing, added };
|
|
2660
|
+
}
|
|
2661
|
+
|
|
2662
|
+
// src/interactive/ReportSinceLastVisit.tsx
|
|
2663
|
+
import { Fragment as Fragment15, jsx as jsx47, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2664
|
+
var KEY = "es-last-visit";
|
|
2665
|
+
var MAX_LINKS2 = 5;
|
|
2666
|
+
function readVisit() {
|
|
2667
|
+
try {
|
|
2668
|
+
const raw = localStorage.getItem(KEY);
|
|
2669
|
+
if (!raw) return null;
|
|
2670
|
+
const parsed = JSON.parse(raw);
|
|
2671
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
2672
|
+
const v = parsed;
|
|
2673
|
+
if (typeof v.runId !== "string" || typeof v.atMs !== "number" || typeof v.statuses !== "object") {
|
|
2674
|
+
return null;
|
|
2675
|
+
}
|
|
2676
|
+
return { runId: v.runId, atMs: v.atMs, statuses: v.statuses };
|
|
2677
|
+
} catch {
|
|
2678
|
+
return null;
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
function writeVisit(snapshot) {
|
|
2682
|
+
try {
|
|
2683
|
+
localStorage.setItem(KEY, JSON.stringify(snapshot));
|
|
2684
|
+
} catch {
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2687
|
+
function ScenarioLinks2({ scenarios, tone }) {
|
|
2688
|
+
return /* @__PURE__ */ jsxs32(Fragment15, { children: [
|
|
2689
|
+
scenarios.slice(0, MAX_LINKS2).map((s, i) => /* @__PURE__ */ jsxs32("span", { children: [
|
|
2690
|
+
i > 0 ? ", " : "",
|
|
2691
|
+
/* @__PURE__ */ jsx47("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
|
|
2692
|
+
] }, s.id)),
|
|
2693
|
+
scenarios.length > MAX_LINKS2 ? /* @__PURE__ */ jsxs32("span", { children: [
|
|
2694
|
+
" and ",
|
|
2695
|
+
scenarios.length - MAX_LINKS2,
|
|
2696
|
+
" more"
|
|
2697
|
+
] }) : null
|
|
2698
|
+
] });
|
|
2699
|
+
}
|
|
2700
|
+
function ReportSinceLastVisit({ report }) {
|
|
2701
|
+
const [delta, setDelta] = useState6(null);
|
|
2702
|
+
const [nowMs, setNowMs] = useState6(0);
|
|
2703
|
+
useEffect4(() => {
|
|
2704
|
+
const now = Date.now();
|
|
2705
|
+
setDelta(diffSinceVisit(readVisit(), report));
|
|
2706
|
+
setNowMs(now);
|
|
2707
|
+
writeVisit(snapshotOf(report, now));
|
|
2708
|
+
}, [report]);
|
|
2709
|
+
if (!delta) return null;
|
|
2710
|
+
const { newlyFailing, newlyPassing, added } = delta;
|
|
2711
|
+
return /* @__PURE__ */ jsxs32("p", { className: "text-xs text-muted-foreground", "data-testid": "es-since-last-visit", children: [
|
|
2712
|
+
/* @__PURE__ */ jsxs32("span", { className: "font-medium text-foreground", children: [
|
|
2713
|
+
"Since your last visit (",
|
|
2714
|
+
formatRelativeAge(delta.sinceMs, nowMs),
|
|
2715
|
+
"):"
|
|
2716
|
+
] }),
|
|
2717
|
+
newlyFailing.length > 0 ? /* @__PURE__ */ jsxs32("span", { className: "ml-2 text-fail", children: [
|
|
2718
|
+
newlyFailing.length,
|
|
2719
|
+
" started failing (",
|
|
2720
|
+
/* @__PURE__ */ jsx47(ScenarioLinks2, { scenarios: newlyFailing, tone: "text-fail" }),
|
|
2721
|
+
")"
|
|
2722
|
+
] }) : null,
|
|
2723
|
+
newlyPassing.length > 0 ? /* @__PURE__ */ jsxs32("span", { className: "ml-2 text-pass", children: [
|
|
2724
|
+
newlyPassing.length,
|
|
2725
|
+
" fixed (",
|
|
2726
|
+
/* @__PURE__ */ jsx47(ScenarioLinks2, { scenarios: newlyPassing, tone: "text-pass" }),
|
|
2727
|
+
")"
|
|
2728
|
+
] }) : null,
|
|
2729
|
+
added.length > 0 ? /* @__PURE__ */ jsxs32("span", { className: "ml-2", children: [
|
|
2730
|
+
added.length,
|
|
2731
|
+
" new"
|
|
2732
|
+
] }) : null
|
|
2733
|
+
] });
|
|
2734
|
+
}
|
|
2735
|
+
|
|
2487
2736
|
// src/interactive/ReportShortcutsHelp.tsx
|
|
2488
|
-
import {
|
|
2737
|
+
import { useEffect as useEffect5, useRef as useRef2 } from "react";
|
|
2738
|
+
import { jsx as jsx48, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2489
2739
|
var SHORTCUTS = [
|
|
2490
2740
|
{ keys: "/", description: "Focus search" },
|
|
2491
2741
|
{ keys: "f", description: "Jump to next failure" },
|
|
@@ -2497,20 +2747,20 @@ var SHORTCUTS = [
|
|
|
2497
2747
|
];
|
|
2498
2748
|
function Keys({ keys }) {
|
|
2499
2749
|
const parts = keys.split(" ");
|
|
2500
|
-
return /* @__PURE__ */
|
|
2501
|
-
i > 0 ? /* @__PURE__ */
|
|
2502
|
-
/* @__PURE__ */
|
|
2750
|
+
return /* @__PURE__ */ jsx48("span", { className: "inline-flex items-center gap-1", children: parts.map((k, i) => /* @__PURE__ */ jsxs33("span", { className: "inline-flex items-center gap-1", children: [
|
|
2751
|
+
i > 0 ? /* @__PURE__ */ jsx48("span", { className: "text-xs text-muted-foreground", children: "+" }) : null,
|
|
2752
|
+
/* @__PURE__ */ jsx48("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 })
|
|
2503
2753
|
] }, k)) });
|
|
2504
2754
|
}
|
|
2505
2755
|
function ReportShortcutsHelp({ open, onClose }) {
|
|
2506
|
-
const dialogRef =
|
|
2507
|
-
|
|
2756
|
+
const dialogRef = useRef2(null);
|
|
2757
|
+
useEffect5(() => {
|
|
2508
2758
|
const dialog = dialogRef.current;
|
|
2509
2759
|
if (!dialog) return;
|
|
2510
2760
|
if (open && !dialog.open) dialog.showModal();
|
|
2511
2761
|
else if (!open && dialog.open) dialog.close();
|
|
2512
2762
|
}, [open]);
|
|
2513
|
-
return /* @__PURE__ */
|
|
2763
|
+
return /* @__PURE__ */ jsxs33(
|
|
2514
2764
|
"dialog",
|
|
2515
2765
|
{
|
|
2516
2766
|
ref: dialogRef,
|
|
@@ -2518,20 +2768,20 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2518
2768
|
"aria-label": "Keyboard shortcuts",
|
|
2519
2769
|
onClose,
|
|
2520
2770
|
children: [
|
|
2521
|
-
/* @__PURE__ */
|
|
2522
|
-
/* @__PURE__ */
|
|
2523
|
-
/* @__PURE__ */
|
|
2524
|
-
/* @__PURE__ */
|
|
2771
|
+
/* @__PURE__ */ jsx48("h2", { className: "text-base font-semibold", children: "Keyboard shortcuts" }),
|
|
2772
|
+
/* @__PURE__ */ jsx48("dl", { className: "mt-4 grid grid-cols-[auto_1fr] items-center gap-x-4 gap-y-2.5", children: SHORTCUTS.map((s) => /* @__PURE__ */ jsxs33("div", { className: "col-span-2 grid grid-cols-subgrid items-center", children: [
|
|
2773
|
+
/* @__PURE__ */ jsx48("dt", { className: "justify-self-start", children: /* @__PURE__ */ jsx48(Keys, { keys: s.keys }) }),
|
|
2774
|
+
/* @__PURE__ */ jsx48("dd", { className: "text-sm text-muted-foreground", children: s.description })
|
|
2525
2775
|
] }, s.keys)) }),
|
|
2526
|
-
/* @__PURE__ */
|
|
2776
|
+
/* @__PURE__ */ jsx48("form", { method: "dialog", className: "mt-6", children: /* @__PURE__ */ jsx48(Button, { type: "submit", variant: "outline", size: "sm", children: "Close" }) })
|
|
2527
2777
|
]
|
|
2528
2778
|
}
|
|
2529
2779
|
);
|
|
2530
2780
|
}
|
|
2531
2781
|
|
|
2532
2782
|
// src/interactive/ReportToc.tsx
|
|
2533
|
-
import { useEffect as
|
|
2534
|
-
import { jsx as
|
|
2783
|
+
import { useEffect as useEffect6, useMemo as useMemo2, useState as useState7 } from "react";
|
|
2784
|
+
import { jsx as jsx49, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2535
2785
|
var DOT = {
|
|
2536
2786
|
passed: "bg-pass",
|
|
2537
2787
|
failed: "bg-fail",
|
|
@@ -2540,12 +2790,12 @@ var DOT = {
|
|
|
2540
2790
|
};
|
|
2541
2791
|
function TocContent({ onNavigate }) {
|
|
2542
2792
|
const report = useReport();
|
|
2543
|
-
const [activeId, setActiveId] =
|
|
2793
|
+
const [activeId, setActiveId] = useState7(null);
|
|
2544
2794
|
const scenarioIds = useMemo2(
|
|
2545
2795
|
() => report.features.flatMap((f) => f.scenarios.map((s) => s.id)),
|
|
2546
2796
|
[report]
|
|
2547
2797
|
);
|
|
2548
|
-
|
|
2798
|
+
useEffect6(() => {
|
|
2549
2799
|
if (typeof IntersectionObserver === "undefined") return;
|
|
2550
2800
|
const els = scenarioIds.map((id) => document.getElementById(id)).filter((el) => el !== null);
|
|
2551
2801
|
if (els.length === 0) return;
|
|
@@ -2560,11 +2810,11 @@ function TocContent({ onNavigate }) {
|
|
|
2560
2810
|
return () => observer.disconnect();
|
|
2561
2811
|
}, [scenarioIds]);
|
|
2562
2812
|
if (report.features.length === 0) return null;
|
|
2563
|
-
return /* @__PURE__ */
|
|
2564
|
-
/* @__PURE__ */
|
|
2565
|
-
/* @__PURE__ */
|
|
2813
|
+
return /* @__PURE__ */ jsx49("ul", { className: "flex list-none flex-col gap-4 pl-0", children: report.features.map((feature) => /* @__PURE__ */ jsxs34("li", { children: [
|
|
2814
|
+
/* @__PURE__ */ jsx49("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
|
|
2815
|
+
/* @__PURE__ */ jsx49("ul", { className: "flex list-none flex-col gap-0.5 pl-0", children: feature.scenarios.map((scenario) => {
|
|
2566
2816
|
const active = activeId === scenario.id;
|
|
2567
|
-
return /* @__PURE__ */
|
|
2817
|
+
return /* @__PURE__ */ jsx49("li", { children: /* @__PURE__ */ jsxs34(
|
|
2568
2818
|
"a",
|
|
2569
2819
|
{
|
|
2570
2820
|
href: `#${scenario.id}`,
|
|
@@ -2579,14 +2829,14 @@ function TocContent({ onNavigate }) {
|
|
|
2579
2829
|
active ? "border-primary font-medium text-foreground" : "border-border text-muted-foreground"
|
|
2580
2830
|
),
|
|
2581
2831
|
children: [
|
|
2582
|
-
/* @__PURE__ */
|
|
2832
|
+
/* @__PURE__ */ jsx49(
|
|
2583
2833
|
"span",
|
|
2584
2834
|
{
|
|
2585
2835
|
"aria-hidden": true,
|
|
2586
2836
|
className: cn("mt-1 size-1.5 shrink-0 rounded-full", DOT[scenario.status])
|
|
2587
2837
|
}
|
|
2588
2838
|
),
|
|
2589
|
-
/* @__PURE__ */
|
|
2839
|
+
/* @__PURE__ */ jsx49("span", { className: "break-words", children: scenario.title })
|
|
2590
2840
|
]
|
|
2591
2841
|
}
|
|
2592
2842
|
) }, scenario.id);
|
|
@@ -2596,48 +2846,48 @@ function TocContent({ onNavigate }) {
|
|
|
2596
2846
|
function ReportToc() {
|
|
2597
2847
|
const report = useReport();
|
|
2598
2848
|
if (report.features.length === 0) return null;
|
|
2599
|
-
return /* @__PURE__ */
|
|
2849
|
+
return /* @__PURE__ */ jsxs34(
|
|
2600
2850
|
"nav",
|
|
2601
2851
|
{
|
|
2602
2852
|
"aria-label": "Table of contents",
|
|
2603
2853
|
className: "sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block",
|
|
2604
2854
|
children: [
|
|
2605
|
-
/* @__PURE__ */
|
|
2606
|
-
/* @__PURE__ */
|
|
2855
|
+
/* @__PURE__ */ jsx49("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
|
|
2856
|
+
/* @__PURE__ */ jsx49(TocContent, {})
|
|
2607
2857
|
]
|
|
2608
2858
|
}
|
|
2609
2859
|
);
|
|
2610
2860
|
}
|
|
2611
2861
|
|
|
2612
2862
|
// src/interactive/ReportTocDrawer.tsx
|
|
2613
|
-
import { useState as
|
|
2863
|
+
import { useState as useState8 } from "react";
|
|
2614
2864
|
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
|
|
2615
2865
|
import { ListIcon, XIcon } from "lucide-react";
|
|
2616
|
-
import { jsx as
|
|
2866
|
+
import { jsx as jsx50, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2617
2867
|
function ReportTocDrawer() {
|
|
2618
2868
|
const report = useReport();
|
|
2619
|
-
const [open, setOpen] =
|
|
2869
|
+
const [open, setOpen] = useState8(false);
|
|
2620
2870
|
if (report.features.length === 0) return null;
|
|
2621
|
-
return /* @__PURE__ */
|
|
2622
|
-
/* @__PURE__ */
|
|
2623
|
-
/* @__PURE__ */
|
|
2871
|
+
return /* @__PURE__ */ jsxs35(DialogPrimitive.Root, { open, onOpenChange: setOpen, children: [
|
|
2872
|
+
/* @__PURE__ */ jsxs35(DialogPrimitive.Trigger, { className: "flex cursor-pointer items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground lg:hidden [&_svg]:size-3.5", children: [
|
|
2873
|
+
/* @__PURE__ */ jsx50(ListIcon, { "aria-hidden": true }),
|
|
2624
2874
|
" Contents"
|
|
2625
2875
|
] }),
|
|
2626
|
-
/* @__PURE__ */
|
|
2627
|
-
/* @__PURE__ */
|
|
2628
|
-
/* @__PURE__ */
|
|
2629
|
-
/* @__PURE__ */
|
|
2630
|
-
/* @__PURE__ */
|
|
2631
|
-
/* @__PURE__ */
|
|
2876
|
+
/* @__PURE__ */ jsxs35(DialogPrimitive.Portal, { children: [
|
|
2877
|
+
/* @__PURE__ */ jsx50(DialogPrimitive.Backdrop, { className: "fixed inset-0 z-50 bg-black/50 transition-opacity duration-200 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0" }),
|
|
2878
|
+
/* @__PURE__ */ jsxs35(DialogPrimitive.Popup, { className: "fixed inset-y-0 left-0 z-50 flex w-72 max-w-[80vw] flex-col gap-3 overflow-y-auto border-r border-border bg-background p-4 font-sans text-xs shadow-lg outline-none transition-transform duration-200 data-[ending-style]:-translate-x-full data-[starting-style]:-translate-x-full", children: [
|
|
2879
|
+
/* @__PURE__ */ jsxs35("div", { className: "flex items-center justify-between", children: [
|
|
2880
|
+
/* @__PURE__ */ jsx50(DialogPrimitive.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
|
|
2881
|
+
/* @__PURE__ */ jsx50(
|
|
2632
2882
|
DialogPrimitive.Close,
|
|
2633
2883
|
{
|
|
2634
2884
|
"aria-label": "Close contents",
|
|
2635
2885
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
2636
|
-
children: /* @__PURE__ */
|
|
2886
|
+
children: /* @__PURE__ */ jsx50(XIcon, { "aria-hidden": true })
|
|
2637
2887
|
}
|
|
2638
2888
|
)
|
|
2639
2889
|
] }),
|
|
2640
|
-
/* @__PURE__ */
|
|
2890
|
+
/* @__PURE__ */ jsx50(TocContent, { onNavigate: () => setOpen(false) })
|
|
2641
2891
|
] })
|
|
2642
2892
|
] })
|
|
2643
2893
|
] });
|
|
@@ -2671,10 +2921,10 @@ function failuresFirst(report) {
|
|
|
2671
2921
|
}
|
|
2672
2922
|
|
|
2673
2923
|
// src/interactive/use-deep-link-scroll.ts
|
|
2674
|
-
import { useEffect as
|
|
2924
|
+
import { useEffect as useEffect7, useRef as useRef3 } from "react";
|
|
2675
2925
|
function useDeepLinkScroll() {
|
|
2676
|
-
const lastAnchor =
|
|
2677
|
-
|
|
2926
|
+
const lastAnchor = useRef3(null);
|
|
2927
|
+
useEffect7(() => {
|
|
2678
2928
|
function scrollToHash() {
|
|
2679
2929
|
const { anchor } = splitHash(window.location.hash);
|
|
2680
2930
|
if (!anchor || anchor === lastAnchor.current) return;
|
|
@@ -2690,7 +2940,7 @@ function useDeepLinkScroll() {
|
|
|
2690
2940
|
}
|
|
2691
2941
|
|
|
2692
2942
|
// src/interactive/use-keyboard-shortcuts.ts
|
|
2693
|
-
import { useEffect as
|
|
2943
|
+
import { useEffect as useEffect8, useRef as useRef4 } from "react";
|
|
2694
2944
|
function isEditableTarget(target) {
|
|
2695
2945
|
if (!(target instanceof HTMLElement)) return false;
|
|
2696
2946
|
const tag = target.tagName;
|
|
@@ -2699,9 +2949,9 @@ function isEditableTarget(target) {
|
|
|
2699
2949
|
return false;
|
|
2700
2950
|
}
|
|
2701
2951
|
function useKeyboardShortcuts(handlers) {
|
|
2702
|
-
const ref =
|
|
2952
|
+
const ref = useRef4(handlers);
|
|
2703
2953
|
ref.current = handlers;
|
|
2704
|
-
|
|
2954
|
+
useEffect8(() => {
|
|
2705
2955
|
function onKeyDown(e) {
|
|
2706
2956
|
const h = ref.current;
|
|
2707
2957
|
if (e.key === "Escape") {
|
|
@@ -2745,8 +2995,8 @@ function useKeyboardShortcuts(handlers) {
|
|
|
2745
2995
|
}
|
|
2746
2996
|
|
|
2747
2997
|
// src/interactive/use-theme.ts
|
|
2748
|
-
import { useCallback as useCallback3, useEffect as
|
|
2749
|
-
var
|
|
2998
|
+
import { useCallback as useCallback3, useEffect as useEffect9, useState as useState9 } from "react";
|
|
2999
|
+
var KEY2 = "es-theme";
|
|
2750
3000
|
function systemDark() {
|
|
2751
3001
|
return typeof matchMedia !== "undefined" && matchMedia("(prefers-color-scheme: dark)").matches;
|
|
2752
3002
|
}
|
|
@@ -2760,19 +3010,19 @@ function applyTheme(pref) {
|
|
|
2760
3010
|
}
|
|
2761
3011
|
function initialPref() {
|
|
2762
3012
|
if (typeof localStorage !== "undefined") {
|
|
2763
|
-
const stored = localStorage.getItem(
|
|
3013
|
+
const stored = localStorage.getItem(KEY2);
|
|
2764
3014
|
if (stored === "light" || stored === "dark" || stored === "system") return stored;
|
|
2765
3015
|
}
|
|
2766
3016
|
return "system";
|
|
2767
3017
|
}
|
|
2768
3018
|
function useTheme() {
|
|
2769
|
-
const [pref, setPrefState] =
|
|
2770
|
-
|
|
3019
|
+
const [pref, setPrefState] = useState9("system");
|
|
3020
|
+
useEffect9(() => {
|
|
2771
3021
|
const p = initialPref();
|
|
2772
3022
|
setPrefState(p);
|
|
2773
3023
|
applyTheme(p);
|
|
2774
3024
|
}, []);
|
|
2775
|
-
|
|
3025
|
+
useEffect9(() => {
|
|
2776
3026
|
if (typeof matchMedia === "undefined") return;
|
|
2777
3027
|
const mq = matchMedia("(prefers-color-scheme: dark)");
|
|
2778
3028
|
const onChange = () => {
|
|
@@ -2785,7 +3035,7 @@ function useTheme() {
|
|
|
2785
3035
|
setPrefState(p);
|
|
2786
3036
|
applyTheme(p);
|
|
2787
3037
|
try {
|
|
2788
|
-
localStorage.setItem(
|
|
3038
|
+
localStorage.setItem(KEY2, p);
|
|
2789
3039
|
} catch {
|
|
2790
3040
|
}
|
|
2791
3041
|
}, []);
|
|
@@ -2793,19 +3043,19 @@ function useTheme() {
|
|
|
2793
3043
|
}
|
|
2794
3044
|
|
|
2795
3045
|
// src/interactive/use-url-state.ts
|
|
2796
|
-
import { useCallback as useCallback4, useEffect as
|
|
3046
|
+
import { useCallback as useCallback4, useEffect as useEffect10, useRef as useRef5, useState as useState10 } from "react";
|
|
2797
3047
|
var WRITE_DELAY_MS = 250;
|
|
2798
3048
|
function useUrlState() {
|
|
2799
|
-
const [state, setState] =
|
|
2800
|
-
const ready =
|
|
2801
|
-
|
|
3049
|
+
const [state, setState] = useState10(DEFAULT_URL_STATE);
|
|
3050
|
+
const ready = useRef5(false);
|
|
3051
|
+
useEffect10(() => {
|
|
2802
3052
|
const read = () => setState(decodeUrlState(splitHash(window.location.hash).params));
|
|
2803
3053
|
read();
|
|
2804
3054
|
ready.current = true;
|
|
2805
3055
|
window.addEventListener("hashchange", read);
|
|
2806
3056
|
return () => window.removeEventListener("hashchange", read);
|
|
2807
3057
|
}, []);
|
|
2808
|
-
|
|
3058
|
+
useEffect10(() => {
|
|
2809
3059
|
if (!ready.current) return;
|
|
2810
3060
|
const timer = setTimeout(
|
|
2811
3061
|
() => writeHash(splitHash(window.location.hash).anchor, encodeUrlState(state)),
|
|
@@ -3041,12 +3291,12 @@ function reportTools(deps) {
|
|
|
3041
3291
|
}
|
|
3042
3292
|
|
|
3043
3293
|
// src/interactive/ReportInteractive.tsx
|
|
3044
|
-
import { Fragment as
|
|
3294
|
+
import { Fragment as Fragment16, jsx as jsx51, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
3045
3295
|
function ReportInteractive(props) {
|
|
3046
3296
|
const { report, className, title, dataTheme } = props;
|
|
3047
3297
|
const result = unwrapReport(report);
|
|
3048
3298
|
if (!result.ok) {
|
|
3049
|
-
return /* @__PURE__ */
|
|
3299
|
+
return /* @__PURE__ */ jsx51(
|
|
3050
3300
|
ReportErrorShell,
|
|
3051
3301
|
{
|
|
3052
3302
|
error: result.error,
|
|
@@ -3056,7 +3306,7 @@ function ReportInteractive(props) {
|
|
|
3056
3306
|
}
|
|
3057
3307
|
);
|
|
3058
3308
|
}
|
|
3059
|
-
return /* @__PURE__ */
|
|
3309
|
+
return /* @__PURE__ */ jsx51(ReportInteractiveView, { ...props, report: result.data });
|
|
3060
3310
|
}
|
|
3061
3311
|
var THEME_OPTIONS = [
|
|
3062
3312
|
{ value: "light", label: "Light", Icon: Sun },
|
|
@@ -3067,7 +3317,7 @@ function ThemeSegment({
|
|
|
3067
3317
|
pref,
|
|
3068
3318
|
onPref
|
|
3069
3319
|
}) {
|
|
3070
|
-
return /* @__PURE__ */
|
|
3320
|
+
return /* @__PURE__ */ jsx51(
|
|
3071
3321
|
ToggleGroup,
|
|
3072
3322
|
{
|
|
3073
3323
|
size: "sm",
|
|
@@ -3077,14 +3327,14 @@ function ThemeSegment({
|
|
|
3077
3327
|
if (next) onPref(next);
|
|
3078
3328
|
},
|
|
3079
3329
|
"aria-label": "Color theme",
|
|
3080
|
-
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */
|
|
3330
|
+
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ jsx51(
|
|
3081
3331
|
ToggleGroupItem,
|
|
3082
3332
|
{
|
|
3083
3333
|
value,
|
|
3084
3334
|
"aria-label": label,
|
|
3085
3335
|
title: label,
|
|
3086
3336
|
className: "px-2",
|
|
3087
|
-
children: /* @__PURE__ */
|
|
3337
|
+
children: /* @__PURE__ */ jsx51(Icon, {})
|
|
3088
3338
|
},
|
|
3089
3339
|
value
|
|
3090
3340
|
))
|
|
@@ -3101,7 +3351,9 @@ function ReportInteractiveView({
|
|
|
3101
3351
|
hideHeader = false,
|
|
3102
3352
|
hideToc = false,
|
|
3103
3353
|
staleAfterDays = 7,
|
|
3104
|
-
scenarioHistory
|
|
3354
|
+
scenarioHistory,
|
|
3355
|
+
share = false,
|
|
3356
|
+
shareCommand
|
|
3105
3357
|
}) {
|
|
3106
3358
|
const [urlState, setUrlState] = useUrlState();
|
|
3107
3359
|
const { query, status: statusFilter, tags: activeTags, detail } = urlState;
|
|
@@ -3117,9 +3369,9 @@ function ReportInteractiveView({
|
|
|
3117
3369
|
(next) => setUrlState({ detail: next }),
|
|
3118
3370
|
[setUrlState]
|
|
3119
3371
|
);
|
|
3120
|
-
const [helpOpen, setHelpOpen] =
|
|
3372
|
+
const [helpOpen, setHelpOpen] = useState11(false);
|
|
3121
3373
|
const { pref: themePref, setPref: setThemePref } = useTheme();
|
|
3122
|
-
const searchRef =
|
|
3374
|
+
const searchRef = useRef6(null);
|
|
3123
3375
|
const expandId = useId2();
|
|
3124
3376
|
const docsId = useId2();
|
|
3125
3377
|
const deferredQuery = useDeferredValue(query);
|
|
@@ -3159,8 +3411,8 @@ function ReportInteractiveView({
|
|
|
3159
3411
|
}),
|
|
3160
3412
|
[activeTags, setUrlState]
|
|
3161
3413
|
);
|
|
3162
|
-
const [toast, setToast] =
|
|
3163
|
-
const toastTimer =
|
|
3414
|
+
const [toast, setToast] = useState11(null);
|
|
3415
|
+
const toastTimer = useRef6(null);
|
|
3164
3416
|
const showToast = useCallback5((msg) => {
|
|
3165
3417
|
setToast(msg);
|
|
3166
3418
|
if (toastTimer.current) clearTimeout(toastTimer.current);
|
|
@@ -3185,7 +3437,11 @@ function ReportInteractiveView({
|
|
|
3185
3437
|
}),
|
|
3186
3438
|
[copy]
|
|
3187
3439
|
);
|
|
3188
|
-
const
|
|
3440
|
+
const copyAllFailures = useCallback5(
|
|
3441
|
+
() => copy(failuresToPrompt(failedScenarios(filtered)), "Failures copied"),
|
|
3442
|
+
[copy, filtered]
|
|
3443
|
+
);
|
|
3444
|
+
const failureIndexRef = useRef6(0);
|
|
3189
3445
|
const allCollapsibleIds = useMemo3(
|
|
3190
3446
|
() => report.features.flatMap((f) => [f.id, ...f.scenarios.map((s) => s.id)]),
|
|
3191
3447
|
[report]
|
|
@@ -3202,7 +3458,7 @@ function ReportInteractiveView({
|
|
|
3202
3458
|
() => collapse.collapseAll(allCollapsibleIds),
|
|
3203
3459
|
[collapse, allCollapsibleIds]
|
|
3204
3460
|
);
|
|
3205
|
-
const [expandedAll, setExpandedAll] =
|
|
3461
|
+
const [expandedAll, setExpandedAll] = useState11(
|
|
3206
3462
|
() => report.summary.failed === 0
|
|
3207
3463
|
);
|
|
3208
3464
|
const setExpanded = useCallback5(
|
|
@@ -3213,7 +3469,7 @@ function ReportInteractiveView({
|
|
|
3213
3469
|
},
|
|
3214
3470
|
[collapse, collapseAll]
|
|
3215
3471
|
);
|
|
3216
|
-
const [agentFilter, setAgentFilter] =
|
|
3472
|
+
const [agentFilter, setAgentFilter] = useState11(null);
|
|
3217
3473
|
useTools(
|
|
3218
3474
|
reportTools({
|
|
3219
3475
|
report,
|
|
@@ -3260,13 +3516,13 @@ function ReportInteractiveView({
|
|
|
3260
3516
|
const totalScenarios = report.summary.total;
|
|
3261
3517
|
const matchedScenarios = filtered.summary.total;
|
|
3262
3518
|
const showToc = !hideToc && totalScenarios > 3;
|
|
3263
|
-
return /* @__PURE__ */
|
|
3519
|
+
return /* @__PURE__ */ jsx51(CollapseProvider, { value: visibleCollapse, children: /* @__PURE__ */ jsx51(ScenarioActionsProvider, { value: scenarioActions, children: /* @__PURE__ */ jsx51(ScenarioHistoryProvider, { value: scenarioHistory ?? null, children: /* @__PURE__ */ jsx51(ScenarioFreshnessProvider, { value: { staleAfterDays, report }, children: /* @__PURE__ */ jsx51(
|
|
3264
3520
|
ReportRoot,
|
|
3265
3521
|
{
|
|
3266
3522
|
report: filtered,
|
|
3267
3523
|
customRenderers,
|
|
3268
3524
|
renderers,
|
|
3269
|
-
children: /* @__PURE__ */
|
|
3525
|
+
children: /* @__PURE__ */ jsxs36(
|
|
3270
3526
|
"main",
|
|
3271
3527
|
{
|
|
3272
3528
|
className: cn("es-report", "es-report-interactive", className),
|
|
@@ -3275,8 +3531,8 @@ function ReportInteractiveView({
|
|
|
3275
3531
|
"data-theme": dataTheme,
|
|
3276
3532
|
"data-detail-level": detail,
|
|
3277
3533
|
children: [
|
|
3278
|
-
/* @__PURE__ */
|
|
3279
|
-
/* @__PURE__ */
|
|
3534
|
+
/* @__PURE__ */ jsxs36("header", { className: "es-report-header", children: [
|
|
3535
|
+
/* @__PURE__ */ jsxs36(
|
|
3280
3536
|
"div",
|
|
3281
3537
|
{
|
|
3282
3538
|
"data-es-navbar": true,
|
|
@@ -3285,9 +3541,9 @@ function ReportInteractiveView({
|
|
|
3285
3541
|
hideHeader ? "justify-end" : "justify-between"
|
|
3286
3542
|
),
|
|
3287
3543
|
children: [
|
|
3288
|
-
hideHeader ? null : /* @__PURE__ */
|
|
3289
|
-
/* @__PURE__ */
|
|
3290
|
-
/* @__PURE__ */
|
|
3544
|
+
hideHeader ? null : /* @__PURE__ */ jsx51("h1", { className: "min-w-0", children: title ?? "Story Report" }),
|
|
3545
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex items-center gap-2", children: [
|
|
3546
|
+
/* @__PURE__ */ jsx51(
|
|
3291
3547
|
ReportSearch,
|
|
3292
3548
|
{
|
|
3293
3549
|
ref: searchRef,
|
|
@@ -3297,16 +3553,17 @@ function ReportInteractiveView({
|
|
|
3297
3553
|
totalCount: totalScenarios
|
|
3298
3554
|
}
|
|
3299
3555
|
),
|
|
3300
|
-
/* @__PURE__ */
|
|
3556
|
+
share ? /* @__PURE__ */ jsx51(ReportShare, { command: shareCommand, onCopy: copy }) : null,
|
|
3557
|
+
/* @__PURE__ */ jsx51(ThemeSegment, { pref: themePref, onPref: setThemePref })
|
|
3301
3558
|
] })
|
|
3302
3559
|
]
|
|
3303
3560
|
}
|
|
3304
3561
|
),
|
|
3305
|
-
hideHeader ? null : /* @__PURE__ */
|
|
3306
|
-
/* @__PURE__ */
|
|
3307
|
-
/* @__PURE__ */
|
|
3562
|
+
hideHeader ? null : /* @__PURE__ */ jsxs36(Fragment16, { children: [
|
|
3563
|
+
/* @__PURE__ */ jsx51(ReportSummary, {}),
|
|
3564
|
+
/* @__PURE__ */ jsx51(ReportMeta, {})
|
|
3308
3565
|
] }),
|
|
3309
|
-
/* @__PURE__ */
|
|
3566
|
+
/* @__PURE__ */ jsx51(
|
|
3310
3567
|
ReportFreshness,
|
|
3311
3568
|
{
|
|
3312
3569
|
lastRunMs: reportLastRunMs(report),
|
|
@@ -3314,14 +3571,15 @@ function ReportInteractiveView({
|
|
|
3314
3571
|
staleAfterDays
|
|
3315
3572
|
}
|
|
3316
3573
|
),
|
|
3317
|
-
/* @__PURE__ */
|
|
3574
|
+
/* @__PURE__ */ jsx51(
|
|
3318
3575
|
ReportLastRunDelta,
|
|
3319
3576
|
{
|
|
3320
3577
|
history: scenarioHistory,
|
|
3321
3578
|
report
|
|
3322
3579
|
}
|
|
3323
3580
|
),
|
|
3324
|
-
/* @__PURE__ */
|
|
3581
|
+
/* @__PURE__ */ jsx51(ReportSinceLastVisit, { report }),
|
|
3582
|
+
/* @__PURE__ */ jsx51(
|
|
3325
3583
|
ReportFilters,
|
|
3326
3584
|
{
|
|
3327
3585
|
statuses: statusOptions,
|
|
@@ -3332,10 +3590,10 @@ function ReportInteractiveView({
|
|
|
3332
3590
|
onToggleTag: toggleTag
|
|
3333
3591
|
}
|
|
3334
3592
|
),
|
|
3335
|
-
/* @__PURE__ */
|
|
3336
|
-
showToc ? /* @__PURE__ */
|
|
3337
|
-
/* @__PURE__ */
|
|
3338
|
-
/* @__PURE__ */
|
|
3593
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border/60 pt-3", children: [
|
|
3594
|
+
showToc ? /* @__PURE__ */ jsx51(ReportTocDrawer, {}) : null,
|
|
3595
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex items-center gap-2", children: [
|
|
3596
|
+
/* @__PURE__ */ jsx51(
|
|
3339
3597
|
Switch,
|
|
3340
3598
|
{
|
|
3341
3599
|
id: expandId,
|
|
@@ -3343,7 +3601,7 @@ function ReportInteractiveView({
|
|
|
3343
3601
|
onCheckedChange: setExpanded
|
|
3344
3602
|
}
|
|
3345
3603
|
),
|
|
3346
|
-
/* @__PURE__ */
|
|
3604
|
+
/* @__PURE__ */ jsx51(
|
|
3347
3605
|
"label",
|
|
3348
3606
|
{
|
|
3349
3607
|
htmlFor: expandId,
|
|
@@ -3352,8 +3610,8 @@ function ReportInteractiveView({
|
|
|
3352
3610
|
}
|
|
3353
3611
|
)
|
|
3354
3612
|
] }),
|
|
3355
|
-
/* @__PURE__ */
|
|
3356
|
-
/* @__PURE__ */
|
|
3613
|
+
/* @__PURE__ */ jsxs36("div", { className: "flex items-center gap-2", children: [
|
|
3614
|
+
/* @__PURE__ */ jsx51(
|
|
3357
3615
|
Switch,
|
|
3358
3616
|
{
|
|
3359
3617
|
id: docsId,
|
|
@@ -3361,7 +3619,7 @@ function ReportInteractiveView({
|
|
|
3361
3619
|
onCheckedChange: (checked) => setDetail(checked ? "full" : "minimal")
|
|
3362
3620
|
}
|
|
3363
3621
|
),
|
|
3364
|
-
/* @__PURE__ */
|
|
3622
|
+
/* @__PURE__ */ jsx51(
|
|
3365
3623
|
"label",
|
|
3366
3624
|
{
|
|
3367
3625
|
htmlFor: docsId,
|
|
@@ -3372,7 +3630,7 @@ function ReportInteractiveView({
|
|
|
3372
3630
|
] })
|
|
3373
3631
|
] })
|
|
3374
3632
|
] }),
|
|
3375
|
-
showAgentFilter ? /* @__PURE__ */
|
|
3633
|
+
showAgentFilter ? /* @__PURE__ */ jsx51(
|
|
3376
3634
|
ReportAgentFilterNotice,
|
|
3377
3635
|
{
|
|
3378
3636
|
applied: agentFilter,
|
|
@@ -3380,17 +3638,17 @@ function ReportInteractiveView({
|
|
|
3380
3638
|
onDismiss: () => setAgentFilter(null)
|
|
3381
3639
|
}
|
|
3382
3640
|
) : null,
|
|
3383
|
-
/* @__PURE__ */
|
|
3384
|
-
hasContent ? showToc ? /* @__PURE__ */
|
|
3385
|
-
/* @__PURE__ */
|
|
3386
|
-
/* @__PURE__ */
|
|
3387
|
-
] }) : /* @__PURE__ */
|
|
3641
|
+
/* @__PURE__ */ jsx51(ReportFailureBanner, { failures, onCopyAll: copyAllFailures }),
|
|
3642
|
+
hasContent ? showToc ? /* @__PURE__ */ jsxs36("div", { className: "flex gap-6", children: [
|
|
3643
|
+
/* @__PURE__ */ jsx51(ReportToc, {}),
|
|
3644
|
+
/* @__PURE__ */ jsx51("div", { className: "flex min-w-0 flex-1 flex-col gap-4", children: /* @__PURE__ */ jsx51(ReportFeatureList, {}) })
|
|
3645
|
+
] }) : /* @__PURE__ */ jsx51("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsx51(ReportFeatureList, {}) }) : /* @__PURE__ */ jsx51(
|
|
3388
3646
|
ReportEmpty,
|
|
3389
3647
|
{
|
|
3390
3648
|
message: query ? "No scenarios match the search." : void 0
|
|
3391
3649
|
}
|
|
3392
3650
|
),
|
|
3393
|
-
/* @__PURE__ */
|
|
3651
|
+
/* @__PURE__ */ jsx51(
|
|
3394
3652
|
"button",
|
|
3395
3653
|
{
|
|
3396
3654
|
type: "button",
|
|
@@ -3401,14 +3659,14 @@ function ReportInteractiveView({
|
|
|
3401
3659
|
children: "?"
|
|
3402
3660
|
}
|
|
3403
3661
|
),
|
|
3404
|
-
/* @__PURE__ */
|
|
3662
|
+
/* @__PURE__ */ jsx51(
|
|
3405
3663
|
ReportShortcutsHelp,
|
|
3406
3664
|
{
|
|
3407
3665
|
open: helpOpen,
|
|
3408
3666
|
onClose: () => setHelpOpen(false)
|
|
3409
3667
|
}
|
|
3410
3668
|
),
|
|
3411
|
-
toast ? /* @__PURE__ */
|
|
3669
|
+
toast ? /* @__PURE__ */ jsx51(
|
|
3412
3670
|
"div",
|
|
3413
3671
|
{
|
|
3414
3672
|
role: "status",
|
|
@@ -3428,11 +3686,11 @@ function ReportInteractiveView({
|
|
|
3428
3686
|
import { useMemo as useMemo4 } from "react";
|
|
3429
3687
|
|
|
3430
3688
|
// src/interactive/island-renderers.tsx
|
|
3431
|
-
import { createElement, useEffect as
|
|
3689
|
+
import { createElement, useEffect as useEffect12, useState as useState13 } from "react";
|
|
3432
3690
|
|
|
3433
3691
|
// src/components/doc/MermaidView.tsx
|
|
3434
|
-
import { useEffect as
|
|
3435
|
-
import { Fragment as
|
|
3692
|
+
import { useEffect as useEffect11, useRef as useRef7, useState as useState12 } from "react";
|
|
3693
|
+
import { Fragment as Fragment17, jsx as jsx52, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3436
3694
|
function prefersDark(el) {
|
|
3437
3695
|
const themed = el?.closest("[data-theme]");
|
|
3438
3696
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -3440,10 +3698,10 @@ function prefersDark(el) {
|
|
|
3440
3698
|
return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
|
|
3441
3699
|
}
|
|
3442
3700
|
function MermaidView({ entry, load }) {
|
|
3443
|
-
const ref =
|
|
3444
|
-
const [svg, setSvg] =
|
|
3445
|
-
const [error, setError] =
|
|
3446
|
-
|
|
3701
|
+
const ref = useRef7(null);
|
|
3702
|
+
const [svg, setSvg] = useState12(null);
|
|
3703
|
+
const [error, setError] = useState12(null);
|
|
3704
|
+
useEffect11(() => {
|
|
3447
3705
|
let cancelled = false;
|
|
3448
3706
|
const draw = async () => {
|
|
3449
3707
|
let mermaid;
|
|
@@ -3486,9 +3744,9 @@ function MermaidView({ entry, load }) {
|
|
|
3486
3744
|
};
|
|
3487
3745
|
}, [entry.code, load]);
|
|
3488
3746
|
if (svg) {
|
|
3489
|
-
return /* @__PURE__ */
|
|
3490
|
-
entry.title ? /* @__PURE__ */
|
|
3491
|
-
/* @__PURE__ */
|
|
3747
|
+
return /* @__PURE__ */ jsxs37("figure", { ref, className: "my-3", children: [
|
|
3748
|
+
entry.title ? /* @__PURE__ */ jsx52("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
3749
|
+
/* @__PURE__ */ jsx52(
|
|
3492
3750
|
"div",
|
|
3493
3751
|
{
|
|
3494
3752
|
role: "img",
|
|
@@ -3499,8 +3757,8 @@ function MermaidView({ entry, load }) {
|
|
|
3499
3757
|
)
|
|
3500
3758
|
] });
|
|
3501
3759
|
}
|
|
3502
|
-
return /* @__PURE__ */
|
|
3503
|
-
error ? /* @__PURE__ */
|
|
3760
|
+
return /* @__PURE__ */ jsxs37(Fragment17, { children: [
|
|
3761
|
+
error ? /* @__PURE__ */ jsxs37(
|
|
3504
3762
|
"p",
|
|
3505
3763
|
{
|
|
3506
3764
|
role: "alert",
|
|
@@ -3512,12 +3770,12 @@ function MermaidView({ entry, load }) {
|
|
|
3512
3770
|
]
|
|
3513
3771
|
}
|
|
3514
3772
|
) : null,
|
|
3515
|
-
/* @__PURE__ */
|
|
3773
|
+
/* @__PURE__ */ jsx52(MermaidSource, { entry, ref })
|
|
3516
3774
|
] });
|
|
3517
3775
|
}
|
|
3518
3776
|
|
|
3519
3777
|
// src/interactive/island-renderers.tsx
|
|
3520
|
-
import { jsx as
|
|
3778
|
+
import { jsx as jsx53 } from "react/jsx-runtime";
|
|
3521
3779
|
var HLJS_ESM = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
|
|
3522
3780
|
var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
|
|
3523
3781
|
function cachedCdnModule(url) {
|
|
@@ -3534,8 +3792,8 @@ function cachedCdnModule(url) {
|
|
|
3534
3792
|
var loadMermaidFromCdn = cachedCdnModule(MERMAID_ESM);
|
|
3535
3793
|
var loadHljs = cachedCdnModule(HLJS_ESM);
|
|
3536
3794
|
function CdnHighlightedCode({ entry }) {
|
|
3537
|
-
const [html, setHtml] =
|
|
3538
|
-
|
|
3795
|
+
const [html, setHtml] = useState13(null);
|
|
3796
|
+
useEffect12(() => {
|
|
3539
3797
|
let cancelled = false;
|
|
3540
3798
|
void (async () => {
|
|
3541
3799
|
try {
|
|
@@ -3551,13 +3809,13 @@ function CdnHighlightedCode({ entry }) {
|
|
|
3551
3809
|
cancelled = true;
|
|
3552
3810
|
};
|
|
3553
3811
|
}, [entry.content, entry.lang]);
|
|
3554
|
-
return /* @__PURE__ */
|
|
3812
|
+
return /* @__PURE__ */ jsx53(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ jsx53(
|
|
3555
3813
|
"code",
|
|
3556
3814
|
{
|
|
3557
3815
|
className: cn("hljs font-mono text-xs", entry.lang && `language-${entry.lang}`),
|
|
3558
3816
|
dangerouslySetInnerHTML: { __html: html }
|
|
3559
3817
|
}
|
|
3560
|
-
) : /* @__PURE__ */
|
|
3818
|
+
) : /* @__PURE__ */ jsx53("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
3561
3819
|
}
|
|
3562
3820
|
function buildIslandRenderers(opts) {
|
|
3563
3821
|
const renderers = {};
|
|
@@ -3571,7 +3829,7 @@ function buildIslandRenderers(opts) {
|
|
|
3571
3829
|
}
|
|
3572
3830
|
|
|
3573
3831
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
3574
|
-
import { jsx as
|
|
3832
|
+
import { jsx as jsx54 } from "react/jsx-runtime";
|
|
3575
3833
|
function ReportInteractiveIsland({
|
|
3576
3834
|
report,
|
|
3577
3835
|
title,
|
|
@@ -3585,7 +3843,7 @@ function ReportInteractiveIsland({
|
|
|
3585
3843
|
() => buildIslandRenderers({ syntaxHighlighting, mermaid }),
|
|
3586
3844
|
[syntaxHighlighting, mermaid]
|
|
3587
3845
|
);
|
|
3588
|
-
return /* @__PURE__ */
|
|
3846
|
+
return /* @__PURE__ */ jsx54(
|
|
3589
3847
|
ReportInteractive,
|
|
3590
3848
|
{
|
|
3591
3849
|
report,
|