executable-stories-react 0.12.0 → 0.13.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/interactive.cjs +469 -172
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.js +426 -123
- package/dist/interactive.js.map +1 -1
- package/dist/report-island.global.js +64 -54
- package/dist/ssr.cjs +1 -1
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.js +1 -1
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +2 -2
- package/package.json +24 -23
package/dist/interactive.cjs
CHANGED
|
@@ -47,8 +47,9 @@ __export(interactive_exports, {
|
|
|
47
47
|
module.exports = __toCommonJS(interactive_exports);
|
|
48
48
|
|
|
49
49
|
// src/interactive/ReportInteractive.tsx
|
|
50
|
-
var
|
|
51
|
-
var import_react21 = require("react");
|
|
50
|
+
var import_lucide_react6 = require("lucide-react");
|
|
51
|
+
var import_react21 = require("webmcpable/react");
|
|
52
|
+
var import_react22 = require("react");
|
|
52
53
|
|
|
53
54
|
// src/components/ui/empty.tsx
|
|
54
55
|
var import_class_variance_authority = require("class-variance-authority");
|
|
@@ -2104,9 +2105,69 @@ function listFailures(report) {
|
|
|
2104
2105
|
return out;
|
|
2105
2106
|
}
|
|
2106
2107
|
|
|
2108
|
+
// src/interactive/ReportAgentFilterNotice.tsx
|
|
2109
|
+
var import_lucide_react3 = require("lucide-react");
|
|
2110
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2111
|
+
function ReportAgentFilterNotice({
|
|
2112
|
+
applied,
|
|
2113
|
+
onReset,
|
|
2114
|
+
onDismiss
|
|
2115
|
+
}) {
|
|
2116
|
+
const terms = [];
|
|
2117
|
+
if (applied.search) terms.push(`matching \u201C${applied.search}\u201D`);
|
|
2118
|
+
if (applied.status !== "all") terms.push(applied.status);
|
|
2119
|
+
if (applied.tags.length > 0) terms.push(applied.tags.join(", "));
|
|
2120
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
2121
|
+
"div",
|
|
2122
|
+
{
|
|
2123
|
+
role: "status",
|
|
2124
|
+
"aria-live": "polite",
|
|
2125
|
+
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",
|
|
2126
|
+
children: [
|
|
2127
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react3.Bot, { "aria-hidden": true, className: "size-4 shrink-0 text-primary" }),
|
|
2128
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "min-w-0 flex-1", children: [
|
|
2129
|
+
"An agent filtered this report",
|
|
2130
|
+
terms.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
|
|
2131
|
+
" to ",
|
|
2132
|
+
terms.join(" \xB7 ")
|
|
2133
|
+
] }) : null,
|
|
2134
|
+
" \u2014",
|
|
2135
|
+
" ",
|
|
2136
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "tabular-nums", children: [
|
|
2137
|
+
applied.matched,
|
|
2138
|
+
" of ",
|
|
2139
|
+
applied.total,
|
|
2140
|
+
" scenarios"
|
|
2141
|
+
] }),
|
|
2142
|
+
"."
|
|
2143
|
+
] }),
|
|
2144
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
2145
|
+
"button",
|
|
2146
|
+
{
|
|
2147
|
+
type: "button",
|
|
2148
|
+
onClick: onReset,
|
|
2149
|
+
className: "cursor-pointer rounded-md border border-border px-2 py-1 text-xs hover:bg-muted",
|
|
2150
|
+
children: "Show all"
|
|
2151
|
+
}
|
|
2152
|
+
),
|
|
2153
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
2154
|
+
"button",
|
|
2155
|
+
{
|
|
2156
|
+
type: "button",
|
|
2157
|
+
onClick: onDismiss,
|
|
2158
|
+
"aria-label": "Dismiss",
|
|
2159
|
+
className: "cursor-pointer rounded-md p-1 text-muted-foreground hover:text-foreground",
|
|
2160
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react3.X, { "aria-hidden": true, className: "size-4" })
|
|
2161
|
+
}
|
|
2162
|
+
)
|
|
2163
|
+
]
|
|
2164
|
+
}
|
|
2165
|
+
);
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2107
2168
|
// src/interactive/ReportFailureBanner.tsx
|
|
2108
2169
|
var import_react10 = require("react");
|
|
2109
|
-
var
|
|
2170
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2110
2171
|
function ReportFailureBanner({ failures }) {
|
|
2111
2172
|
const first = failures[0];
|
|
2112
2173
|
const jumpToFirst = (0, import_react10.useCallback)(() => {
|
|
@@ -2114,7 +2175,7 @@ function ReportFailureBanner({ failures }) {
|
|
|
2114
2175
|
scrollToScenarioId(first.scenarioId);
|
|
2115
2176
|
}, [first]);
|
|
2116
2177
|
if (failures.length === 0) return null;
|
|
2117
|
-
return /* @__PURE__ */ (0,
|
|
2178
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
|
|
2118
2179
|
"div",
|
|
2119
2180
|
{
|
|
2120
2181
|
className: "es-failure-banner",
|
|
@@ -2122,13 +2183,13 @@ function ReportFailureBanner({ failures }) {
|
|
|
2122
2183
|
"aria-live": "polite",
|
|
2123
2184
|
"aria-label": "Failure summary",
|
|
2124
2185
|
children: [
|
|
2125
|
-
/* @__PURE__ */ (0,
|
|
2126
|
-
/* @__PURE__ */ (0,
|
|
2186
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "es-failure-banner-text", children: [
|
|
2187
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: failures.length }),
|
|
2127
2188
|
" ",
|
|
2128
2189
|
"failure",
|
|
2129
2190
|
failures.length === 1 ? "" : "s"
|
|
2130
2191
|
] }),
|
|
2131
|
-
/* @__PURE__ */ (0,
|
|
2192
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2132
2193
|
"button",
|
|
2133
2194
|
{
|
|
2134
2195
|
type: "button",
|
|
@@ -2145,7 +2206,7 @@ function ReportFailureBanner({ failures }) {
|
|
|
2145
2206
|
|
|
2146
2207
|
// src/interactive/ReportFilters.tsx
|
|
2147
2208
|
var import_react11 = require("react");
|
|
2148
|
-
var
|
|
2209
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2149
2210
|
var TAG_LIMIT = 12;
|
|
2150
2211
|
function ReportFilters({
|
|
2151
2212
|
statuses,
|
|
@@ -2159,10 +2220,10 @@ function ReportFilters({
|
|
|
2159
2220
|
if (statuses.length === 0 && tags.length === 0) return null;
|
|
2160
2221
|
const tagsCollapsed = tags.length > TAG_LIMIT && !showAllTags;
|
|
2161
2222
|
const visibleTags = tagsCollapsed ? tags.slice(0, TAG_LIMIT) : tags;
|
|
2162
|
-
return /* @__PURE__ */ (0,
|
|
2163
|
-
statuses.length > 0 ? /* @__PURE__ */ (0,
|
|
2223
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
2224
|
+
statuses.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { role: "group", "aria-label": "Filter by status", className: "flex flex-wrap gap-1", children: statuses.map((opt) => {
|
|
2164
2225
|
const active = status === opt.key;
|
|
2165
|
-
return /* @__PURE__ */ (0,
|
|
2226
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
2166
2227
|
"button",
|
|
2167
2228
|
{
|
|
2168
2229
|
type: "button",
|
|
@@ -2174,23 +2235,23 @@ function ReportFilters({
|
|
|
2174
2235
|
),
|
|
2175
2236
|
children: [
|
|
2176
2237
|
opt.label,
|
|
2177
|
-
/* @__PURE__ */ (0,
|
|
2238
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "ml-1 font-mono opacity-70", children: opt.count })
|
|
2178
2239
|
]
|
|
2179
2240
|
},
|
|
2180
2241
|
opt.key
|
|
2181
2242
|
);
|
|
2182
2243
|
}) }) : null,
|
|
2183
|
-
tags.length > 0 ? /* @__PURE__ */ (0,
|
|
2244
|
+
tags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("ul", { "aria-label": "Filter by tag", className: "flex flex-wrap items-center gap-1.5", children: [
|
|
2184
2245
|
visibleTags.map((tag) => {
|
|
2185
2246
|
const active = activeTags.includes(tag);
|
|
2186
|
-
return /* @__PURE__ */ (0,
|
|
2247
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2187
2248
|
"button",
|
|
2188
2249
|
{
|
|
2189
2250
|
type: "button",
|
|
2190
2251
|
"aria-pressed": active,
|
|
2191
2252
|
onClick: () => onToggleTag(tag),
|
|
2192
2253
|
className: "cursor-pointer",
|
|
2193
|
-
children: /* @__PURE__ */ (0,
|
|
2254
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2194
2255
|
Badge,
|
|
2195
2256
|
{
|
|
2196
2257
|
variant: "tag",
|
|
@@ -2203,7 +2264,7 @@ function ReportFilters({
|
|
|
2203
2264
|
}
|
|
2204
2265
|
) }, tag);
|
|
2205
2266
|
}),
|
|
2206
|
-
tags.length > TAG_LIMIT ? /* @__PURE__ */ (0,
|
|
2267
|
+
tags.length > TAG_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2207
2268
|
"button",
|
|
2208
2269
|
{
|
|
2209
2270
|
type: "button",
|
|
@@ -2219,7 +2280,7 @@ function ReportFilters({
|
|
|
2219
2280
|
|
|
2220
2281
|
// src/interactive/ReportFreshness.tsx
|
|
2221
2282
|
var import_react12 = require("react");
|
|
2222
|
-
var
|
|
2283
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2223
2284
|
function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
2224
2285
|
const [now, setNow] = (0, import_react12.useState)(nowMs);
|
|
2225
2286
|
(0, import_react12.useEffect)(() => {
|
|
@@ -2227,7 +2288,7 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2227
2288
|
}, [nowMs]);
|
|
2228
2289
|
if (lastRunMs === void 0 || now === void 0) return null;
|
|
2229
2290
|
const age = formatRelativeAge(lastRunMs, now);
|
|
2230
|
-
const runLink = ciUrl ? /* @__PURE__ */ (0,
|
|
2291
|
+
const runLink = ciUrl ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2231
2292
|
"a",
|
|
2232
2293
|
{
|
|
2233
2294
|
href: ciUrl,
|
|
@@ -2238,9 +2299,9 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2238
2299
|
}
|
|
2239
2300
|
) : null;
|
|
2240
2301
|
if (isReportStale(lastRunMs, staleAfterDays, now)) {
|
|
2241
|
-
return /* @__PURE__ */ (0,
|
|
2242
|
-
/* @__PURE__ */ (0,
|
|
2243
|
-
/* @__PURE__ */ (0,
|
|
2302
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "es-stale-banner", role: "status", "aria-label": "Report freshness", children: [
|
|
2303
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { children: [
|
|
2304
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("strong", { children: [
|
|
2244
2305
|
"Last verified ",
|
|
2245
2306
|
age,
|
|
2246
2307
|
"."
|
|
@@ -2250,10 +2311,10 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2250
2311
|
runLink
|
|
2251
2312
|
] });
|
|
2252
2313
|
}
|
|
2253
|
-
return /* @__PURE__ */ (0,
|
|
2314
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("p", { className: "es-freshness", "aria-label": "Report freshness", children: [
|
|
2254
2315
|
"Verified ",
|
|
2255
2316
|
age,
|
|
2256
|
-
runLink ? /* @__PURE__ */ (0,
|
|
2317
|
+
runLink ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
|
|
2257
2318
|
" \xB7 ",
|
|
2258
2319
|
runLink
|
|
2259
2320
|
] }) : null
|
|
@@ -2261,15 +2322,15 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2261
2322
|
}
|
|
2262
2323
|
|
|
2263
2324
|
// src/interactive/ReportLastRunDelta.tsx
|
|
2264
|
-
var
|
|
2325
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2265
2326
|
var MAX_LINKS = 5;
|
|
2266
2327
|
function ScenarioLinks({ scenarios, tone }) {
|
|
2267
|
-
return /* @__PURE__ */ (0,
|
|
2268
|
-
scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ (0,
|
|
2328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
|
|
2329
|
+
scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { children: [
|
|
2269
2330
|
i > 0 ? ", " : "",
|
|
2270
|
-
/* @__PURE__ */ (0,
|
|
2331
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
|
|
2271
2332
|
] }, s.id)),
|
|
2272
|
-
scenarios.length > MAX_LINKS ? /* @__PURE__ */ (0,
|
|
2333
|
+
scenarios.length > MAX_LINKS ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { children: [
|
|
2273
2334
|
" and ",
|
|
2274
2335
|
scenarios.length - MAX_LINKS,
|
|
2275
2336
|
" more"
|
|
@@ -2286,23 +2347,23 @@ function ReportLastRunDelta({
|
|
|
2286
2347
|
if (!delta) return null;
|
|
2287
2348
|
const { newlyFailing, newlyPassing, added } = delta;
|
|
2288
2349
|
if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) {
|
|
2289
|
-
return /* @__PURE__ */ (0,
|
|
2350
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: "Since last run: no behavior changes." });
|
|
2290
2351
|
}
|
|
2291
|
-
return /* @__PURE__ */ (0,
|
|
2292
|
-
/* @__PURE__ */ (0,
|
|
2293
|
-
newlyFailing.length > 0 ? /* @__PURE__ */ (0,
|
|
2352
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: [
|
|
2353
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "font-medium text-foreground", children: "Since last run:" }),
|
|
2354
|
+
newlyFailing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "ml-2 text-fail", children: [
|
|
2294
2355
|
newlyFailing.length,
|
|
2295
2356
|
" newly failing (",
|
|
2296
|
-
/* @__PURE__ */ (0,
|
|
2357
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ScenarioLinks, { scenarios: newlyFailing, tone: "text-fail" }),
|
|
2297
2358
|
")"
|
|
2298
2359
|
] }) : null,
|
|
2299
|
-
newlyPassing.length > 0 ? /* @__PURE__ */ (0,
|
|
2360
|
+
newlyPassing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "ml-2 text-pass", children: [
|
|
2300
2361
|
newlyPassing.length,
|
|
2301
2362
|
" fixed (",
|
|
2302
|
-
/* @__PURE__ */ (0,
|
|
2363
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ScenarioLinks, { scenarios: newlyPassing, tone: "text-pass" }),
|
|
2303
2364
|
")"
|
|
2304
2365
|
] }) : null,
|
|
2305
|
-
added.length > 0 ? /* @__PURE__ */ (0,
|
|
2366
|
+
added.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "ml-2", children: [
|
|
2306
2367
|
added.length,
|
|
2307
2368
|
" new"
|
|
2308
2369
|
] }) : null
|
|
@@ -2311,13 +2372,13 @@ function ReportLastRunDelta({
|
|
|
2311
2372
|
|
|
2312
2373
|
// src/interactive/ReportSearch.tsx
|
|
2313
2374
|
var import_react13 = require("react");
|
|
2314
|
-
var
|
|
2375
|
+
var import_lucide_react4 = require("lucide-react");
|
|
2315
2376
|
|
|
2316
2377
|
// src/components/ui/input.tsx
|
|
2317
2378
|
var React6 = require("react");
|
|
2318
|
-
var
|
|
2379
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2319
2380
|
function Input({ className, type, ...props }) {
|
|
2320
|
-
return /* @__PURE__ */ (0,
|
|
2381
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2321
2382
|
"input",
|
|
2322
2383
|
{
|
|
2323
2384
|
type,
|
|
@@ -2334,7 +2395,7 @@ function Input({ className, type, ...props }) {
|
|
|
2334
2395
|
}
|
|
2335
2396
|
|
|
2336
2397
|
// src/interactive/ReportSearch.tsx
|
|
2337
|
-
var
|
|
2398
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2338
2399
|
var ReportSearch = (0, import_react13.forwardRef)(
|
|
2339
2400
|
function ReportSearch2(props, ref) {
|
|
2340
2401
|
const {
|
|
@@ -2356,17 +2417,17 @@ var ReportSearch = (0, import_react13.forwardRef)(
|
|
|
2356
2417
|
e.preventDefault();
|
|
2357
2418
|
}
|
|
2358
2419
|
}
|
|
2359
|
-
return /* @__PURE__ */ (0,
|
|
2360
|
-
/* @__PURE__ */ (0,
|
|
2361
|
-
/* @__PURE__ */ (0,
|
|
2362
|
-
/* @__PURE__ */ (0,
|
|
2363
|
-
|
|
2420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: cn("es-search flex flex-col gap-1", className), children: [
|
|
2421
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("label", { htmlFor: inputId, className: "sr-only", children: "Search" }),
|
|
2422
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "relative w-full sm:w-72", children: [
|
|
2423
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2424
|
+
import_lucide_react4.Search,
|
|
2364
2425
|
{
|
|
2365
2426
|
"aria-hidden": true,
|
|
2366
2427
|
className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
|
|
2367
2428
|
}
|
|
2368
2429
|
),
|
|
2369
|
-
/* @__PURE__ */ (0,
|
|
2430
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2370
2431
|
Input,
|
|
2371
2432
|
{
|
|
2372
2433
|
ref,
|
|
@@ -2383,7 +2444,7 @@ var ReportSearch = (0, import_react13.forwardRef)(
|
|
|
2383
2444
|
}
|
|
2384
2445
|
)
|
|
2385
2446
|
] }),
|
|
2386
|
-
showCounts ? /* @__PURE__ */ (0,
|
|
2447
|
+
showCounts ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
2387
2448
|
"span",
|
|
2388
2449
|
{
|
|
2389
2450
|
className: "text-xs tabular-nums text-muted-foreground",
|
|
@@ -2457,7 +2518,7 @@ function Button({
|
|
|
2457
2518
|
}
|
|
2458
2519
|
|
|
2459
2520
|
// src/interactive/ReportShortcutsHelp.tsx
|
|
2460
|
-
var
|
|
2521
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2461
2522
|
var SHORTCUTS = [
|
|
2462
2523
|
{ keys: "/", description: "Focus search" },
|
|
2463
2524
|
{ keys: "f", description: "Jump to next failure" },
|
|
@@ -2469,9 +2530,9 @@ var SHORTCUTS = [
|
|
|
2469
2530
|
];
|
|
2470
2531
|
function Keys({ keys }) {
|
|
2471
2532
|
const parts = keys.split(" ");
|
|
2472
|
-
return /* @__PURE__ */ (0,
|
|
2473
|
-
i > 0 ? /* @__PURE__ */ (0,
|
|
2474
|
-
/* @__PURE__ */ (0,
|
|
2533
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "inline-flex items-center gap-1", children: parts.map((k, i) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "inline-flex items-center gap-1", children: [
|
|
2534
|
+
i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "text-xs text-muted-foreground", children: "+" }) : null,
|
|
2535
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.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 })
|
|
2475
2536
|
] }, k)) });
|
|
2476
2537
|
}
|
|
2477
2538
|
function ReportShortcutsHelp({ open, onClose }) {
|
|
@@ -2482,7 +2543,7 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2482
2543
|
if (open && !dialog.open) dialog.showModal();
|
|
2483
2544
|
else if (!open && dialog.open) dialog.close();
|
|
2484
2545
|
}, [open]);
|
|
2485
|
-
return /* @__PURE__ */ (0,
|
|
2546
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
2486
2547
|
"dialog",
|
|
2487
2548
|
{
|
|
2488
2549
|
ref: dialogRef,
|
|
@@ -2490,12 +2551,12 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2490
2551
|
"aria-label": "Keyboard shortcuts",
|
|
2491
2552
|
onClose,
|
|
2492
2553
|
children: [
|
|
2493
|
-
/* @__PURE__ */ (0,
|
|
2494
|
-
/* @__PURE__ */ (0,
|
|
2495
|
-
/* @__PURE__ */ (0,
|
|
2496
|
-
/* @__PURE__ */ (0,
|
|
2554
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h2", { className: "text-base font-semibold", children: "Keyboard shortcuts" }),
|
|
2555
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.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_runtime47.jsxs)("div", { className: "col-span-2 grid grid-cols-subgrid items-center", children: [
|
|
2556
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("dt", { className: "justify-self-start", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Keys, { keys: s.keys }) }),
|
|
2557
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("dd", { className: "text-sm text-muted-foreground", children: s.description })
|
|
2497
2558
|
] }, s.keys)) }),
|
|
2498
|
-
/* @__PURE__ */ (0,
|
|
2559
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("form", { method: "dialog", className: "mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Button, { type: "submit", variant: "outline", size: "sm", children: "Close" }) })
|
|
2499
2560
|
]
|
|
2500
2561
|
}
|
|
2501
2562
|
);
|
|
@@ -2503,7 +2564,7 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2503
2564
|
|
|
2504
2565
|
// src/interactive/ReportToc.tsx
|
|
2505
2566
|
var import_react15 = require("react");
|
|
2506
|
-
var
|
|
2567
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2507
2568
|
var DOT = {
|
|
2508
2569
|
passed: "bg-pass",
|
|
2509
2570
|
failed: "bg-fail",
|
|
@@ -2532,11 +2593,11 @@ function TocContent({ onNavigate }) {
|
|
|
2532
2593
|
return () => observer.disconnect();
|
|
2533
2594
|
}, [scenarioIds]);
|
|
2534
2595
|
if (report.features.length === 0) return null;
|
|
2535
|
-
return /* @__PURE__ */ (0,
|
|
2536
|
-
/* @__PURE__ */ (0,
|
|
2537
|
-
/* @__PURE__ */ (0,
|
|
2596
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("ul", { className: "flex list-none flex-col gap-4 pl-0", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("li", { children: [
|
|
2597
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
|
|
2598
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("ul", { className: "flex list-none flex-col gap-0.5 pl-0", children: feature.scenarios.map((scenario) => {
|
|
2538
2599
|
const active = activeId === scenario.id;
|
|
2539
|
-
return /* @__PURE__ */ (0,
|
|
2600
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
2540
2601
|
"a",
|
|
2541
2602
|
{
|
|
2542
2603
|
href: `#${scenario.id}`,
|
|
@@ -2551,14 +2612,14 @@ function TocContent({ onNavigate }) {
|
|
|
2551
2612
|
active ? "border-primary font-medium text-foreground" : "border-border text-muted-foreground"
|
|
2552
2613
|
),
|
|
2553
2614
|
children: [
|
|
2554
|
-
/* @__PURE__ */ (0,
|
|
2615
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2555
2616
|
"span",
|
|
2556
2617
|
{
|
|
2557
2618
|
"aria-hidden": true,
|
|
2558
2619
|
className: cn("mt-1 size-1.5 shrink-0 rounded-full", DOT[scenario.status])
|
|
2559
2620
|
}
|
|
2560
2621
|
),
|
|
2561
|
-
/* @__PURE__ */ (0,
|
|
2622
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "break-words", children: scenario.title })
|
|
2562
2623
|
]
|
|
2563
2624
|
}
|
|
2564
2625
|
) }, scenario.id);
|
|
@@ -2568,14 +2629,14 @@ function TocContent({ onNavigate }) {
|
|
|
2568
2629
|
function ReportToc() {
|
|
2569
2630
|
const report = useReport();
|
|
2570
2631
|
if (report.features.length === 0) return null;
|
|
2571
|
-
return /* @__PURE__ */ (0,
|
|
2632
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
2572
2633
|
"nav",
|
|
2573
2634
|
{
|
|
2574
2635
|
"aria-label": "Table of contents",
|
|
2575
2636
|
className: "sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block",
|
|
2576
2637
|
children: [
|
|
2577
|
-
/* @__PURE__ */ (0,
|
|
2578
|
-
/* @__PURE__ */ (0,
|
|
2638
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
|
|
2639
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(TocContent, {})
|
|
2579
2640
|
]
|
|
2580
2641
|
}
|
|
2581
2642
|
);
|
|
@@ -2584,32 +2645,32 @@ function ReportToc() {
|
|
|
2584
2645
|
// src/interactive/ReportTocDrawer.tsx
|
|
2585
2646
|
var import_react16 = require("react");
|
|
2586
2647
|
var import_dialog = require("@base-ui/react/dialog");
|
|
2587
|
-
var
|
|
2588
|
-
var
|
|
2648
|
+
var import_lucide_react5 = require("lucide-react");
|
|
2649
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
2589
2650
|
function ReportTocDrawer() {
|
|
2590
2651
|
const report = useReport();
|
|
2591
2652
|
const [open, setOpen] = (0, import_react16.useState)(false);
|
|
2592
2653
|
if (report.features.length === 0) return null;
|
|
2593
|
-
return /* @__PURE__ */ (0,
|
|
2594
|
-
/* @__PURE__ */ (0,
|
|
2595
|
-
/* @__PURE__ */ (0,
|
|
2654
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_dialog.Dialog.Root, { open, onOpenChange: setOpen, children: [
|
|
2655
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.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: [
|
|
2656
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react5.ListIcon, { "aria-hidden": true }),
|
|
2596
2657
|
" Contents"
|
|
2597
2658
|
] }),
|
|
2598
|
-
/* @__PURE__ */ (0,
|
|
2599
|
-
/* @__PURE__ */ (0,
|
|
2600
|
-
/* @__PURE__ */ (0,
|
|
2601
|
-
/* @__PURE__ */ (0,
|
|
2602
|
-
/* @__PURE__ */ (0,
|
|
2603
|
-
/* @__PURE__ */ (0,
|
|
2659
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_dialog.Dialog.Portal, { children: [
|
|
2660
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.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" }),
|
|
2661
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.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: [
|
|
2662
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2663
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_dialog.Dialog.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
|
|
2664
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2604
2665
|
import_dialog.Dialog.Close,
|
|
2605
2666
|
{
|
|
2606
2667
|
"aria-label": "Close contents",
|
|
2607
2668
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
2608
|
-
children: /* @__PURE__ */ (0,
|
|
2669
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react5.XIcon, { "aria-hidden": true })
|
|
2609
2670
|
}
|
|
2610
2671
|
)
|
|
2611
2672
|
] }),
|
|
2612
|
-
/* @__PURE__ */ (0,
|
|
2673
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(TocContent, { onNavigate: () => setOpen(false) })
|
|
2613
2674
|
] })
|
|
2614
2675
|
] })
|
|
2615
2676
|
] });
|
|
@@ -2792,13 +2853,227 @@ function useUrlState() {
|
|
|
2792
2853
|
return [state, update];
|
|
2793
2854
|
}
|
|
2794
2855
|
|
|
2856
|
+
// src/interactive/webmcp-tools.ts
|
|
2857
|
+
var import_report_queries = require("executable-stories-core/report-queries");
|
|
2858
|
+
var STATUSES2 = [
|
|
2859
|
+
"passed",
|
|
2860
|
+
"failed",
|
|
2861
|
+
"skipped",
|
|
2862
|
+
"pending"
|
|
2863
|
+
];
|
|
2864
|
+
var VIEW_STATUSES = ["all", ...STATUSES2];
|
|
2865
|
+
var ToolArgumentError = class extends Error {
|
|
2866
|
+
};
|
|
2867
|
+
function asRecord(input) {
|
|
2868
|
+
return typeof input === "object" && input !== null ? input : {};
|
|
2869
|
+
}
|
|
2870
|
+
function readString(input, key) {
|
|
2871
|
+
const value = input[key];
|
|
2872
|
+
if (value === void 0 || value === null) return void 0;
|
|
2873
|
+
if (typeof value !== "string") {
|
|
2874
|
+
throw new ToolArgumentError(`"${key}" must be a string, received ${typeof value}.`);
|
|
2875
|
+
}
|
|
2876
|
+
return value;
|
|
2877
|
+
}
|
|
2878
|
+
function readStringArray(input, key) {
|
|
2879
|
+
const value = input[key];
|
|
2880
|
+
if (value === void 0 || value === null) return void 0;
|
|
2881
|
+
if (typeof value === "string") return [value];
|
|
2882
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
2883
|
+
throw new ToolArgumentError(`"${key}" must be an array of strings.`);
|
|
2884
|
+
}
|
|
2885
|
+
return value;
|
|
2886
|
+
}
|
|
2887
|
+
function readEnum(input, key, allowed) {
|
|
2888
|
+
const value = readString(input, key);
|
|
2889
|
+
if (value === void 0) return void 0;
|
|
2890
|
+
if (!allowed.includes(value)) {
|
|
2891
|
+
throw new ToolArgumentError(
|
|
2892
|
+
`"${key}" must be one of: ${allowed.join(", ")}. Received "${value}".`
|
|
2893
|
+
);
|
|
2894
|
+
}
|
|
2895
|
+
return value;
|
|
2896
|
+
}
|
|
2897
|
+
function readStatuses(input) {
|
|
2898
|
+
const values = readStringArray(input, "statuses");
|
|
2899
|
+
if (values === void 0) return void 0;
|
|
2900
|
+
const invalid = values.filter((v) => !STATUSES2.includes(v));
|
|
2901
|
+
if (invalid.length > 0) {
|
|
2902
|
+
throw new ToolArgumentError(
|
|
2903
|
+
`"statuses" must contain only: ${STATUSES2.join(", ")}. Received "${invalid.join('", "')}".`
|
|
2904
|
+
);
|
|
2905
|
+
}
|
|
2906
|
+
return values;
|
|
2907
|
+
}
|
|
2908
|
+
function guarded(run) {
|
|
2909
|
+
try {
|
|
2910
|
+
return run();
|
|
2911
|
+
} catch (error) {
|
|
2912
|
+
if (error instanceof ToolArgumentError) return `Invalid input \u2014 ${error.message}`;
|
|
2913
|
+
throw error;
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2916
|
+
var scenarioListSchema = {
|
|
2917
|
+
type: "object",
|
|
2918
|
+
properties: {
|
|
2919
|
+
statuses: {
|
|
2920
|
+
type: "array",
|
|
2921
|
+
items: { type: "string", enum: [...STATUSES2] },
|
|
2922
|
+
description: "Keep only scenarios with any of these statuses."
|
|
2923
|
+
},
|
|
2924
|
+
tags: {
|
|
2925
|
+
type: "array",
|
|
2926
|
+
items: { type: "string" },
|
|
2927
|
+
description: "Keep only scenarios carrying any of these tags."
|
|
2928
|
+
},
|
|
2929
|
+
sourceFiles: {
|
|
2930
|
+
type: "array",
|
|
2931
|
+
items: { type: "string" },
|
|
2932
|
+
description: "Keep only scenarios whose source file path contains any of these."
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
};
|
|
2936
|
+
var READ_ONLY = { readOnlyHint: true, untrustedContentHint: true };
|
|
2937
|
+
function reportTools(deps) {
|
|
2938
|
+
const { report, setView, onAgentFilter } = deps;
|
|
2939
|
+
const now = deps.now ?? Date.now;
|
|
2940
|
+
const provenance = () => ({ run: (0, import_report_queries.runProvenance)(report, now()) });
|
|
2941
|
+
const list = (filters) => {
|
|
2942
|
+
const scenarios = (0, import_report_queries.listScenarioSummaries)(report, filters);
|
|
2943
|
+
return { ...provenance(), total: scenarios.length, scenarios };
|
|
2944
|
+
};
|
|
2945
|
+
return {
|
|
2946
|
+
list_scenarios: {
|
|
2947
|
+
title: "List scenarios",
|
|
2948
|
+
description: "List the behaviour scenarios in this report, optionally filtered by status, tag, or source file. Returns each scenario with its steps, tags, timing and failure message.",
|
|
2949
|
+
annotations: READ_ONLY,
|
|
2950
|
+
input: scenarioListSchema,
|
|
2951
|
+
execute: (input) => guarded(() => {
|
|
2952
|
+
const args = asRecord(input);
|
|
2953
|
+
const filters = {};
|
|
2954
|
+
const statuses = readStatuses(args);
|
|
2955
|
+
const tags = readStringArray(args, "tags");
|
|
2956
|
+
const sourceFiles = readStringArray(args, "sourceFiles");
|
|
2957
|
+
if (statuses) filters.statuses = statuses;
|
|
2958
|
+
if (tags) filters.tags = tags;
|
|
2959
|
+
if (sourceFiles) filters.sourceFiles = sourceFiles;
|
|
2960
|
+
return list(filters);
|
|
2961
|
+
})
|
|
2962
|
+
},
|
|
2963
|
+
get_failing_scenarios: {
|
|
2964
|
+
title: "Get failing scenarios",
|
|
2965
|
+
description: "List only the scenarios that failed in this run, each with the step that failed and its error message. Use this first when asked what is broken.",
|
|
2966
|
+
annotations: READ_ONLY,
|
|
2967
|
+
execute: () => list({ statuses: ["failed"] })
|
|
2968
|
+
},
|
|
2969
|
+
get_feature_summary: {
|
|
2970
|
+
title: "Get feature summary",
|
|
2971
|
+
description: 'Summarise each feature in the report with its scenario counts by status. Use this for "how are we doing" questions rather than listing every scenario.',
|
|
2972
|
+
annotations: READ_ONLY,
|
|
2973
|
+
execute: () => ({
|
|
2974
|
+
...provenance(),
|
|
2975
|
+
summary: report.summary,
|
|
2976
|
+
features: (0, import_report_queries.getFeatureSummary)(report)
|
|
2977
|
+
})
|
|
2978
|
+
},
|
|
2979
|
+
get_scenario: {
|
|
2980
|
+
title: "Get scenario",
|
|
2981
|
+
description: "Get one scenario by its id or its exact title, with every step and any failure detail. Attachment and document bodies are omitted \u2014 `docKinds` names what the page shows.",
|
|
2982
|
+
annotations: READ_ONLY,
|
|
2983
|
+
input: {
|
|
2984
|
+
type: "object",
|
|
2985
|
+
properties: {
|
|
2986
|
+
idOrTitle: {
|
|
2987
|
+
type: "string",
|
|
2988
|
+
description: "The scenario id, or its exact title as shown in the report."
|
|
2989
|
+
}
|
|
2990
|
+
},
|
|
2991
|
+
required: ["idOrTitle"]
|
|
2992
|
+
},
|
|
2993
|
+
execute: (input) => guarded(() => {
|
|
2994
|
+
const idOrTitle = readString(asRecord(input), "idOrTitle") ?? "";
|
|
2995
|
+
const found = (0, import_report_queries.getScenario)(report, idOrTitle);
|
|
2996
|
+
if (!found) {
|
|
2997
|
+
return {
|
|
2998
|
+
...provenance(),
|
|
2999
|
+
error: `No scenario found with id or title "${idOrTitle}". Call list_scenarios to see what this report contains.`
|
|
3000
|
+
};
|
|
3001
|
+
}
|
|
3002
|
+
return {
|
|
3003
|
+
...provenance(),
|
|
3004
|
+
feature: {
|
|
3005
|
+
id: found.feature.id,
|
|
3006
|
+
title: found.feature.title,
|
|
3007
|
+
sourceFile: found.feature.sourceFile
|
|
3008
|
+
},
|
|
3009
|
+
// The summary projection, not the raw scenario: doc entry bodies and
|
|
3010
|
+
// base64 attachments are unbounded, and this payload goes straight
|
|
3011
|
+
// into a model's context window.
|
|
3012
|
+
scenario: (0, import_report_queries.toScenarioSummary)(found.feature, found.scenario)
|
|
3013
|
+
};
|
|
3014
|
+
})
|
|
3015
|
+
},
|
|
3016
|
+
filter_scenarios: {
|
|
3017
|
+
title: "Filter the report",
|
|
3018
|
+
description: `Change what the reader is looking at: set the report's search text, status filter and tag filter. Omitted fields are left as they are; pass an empty string, "all", or an empty array to clear one.`,
|
|
3019
|
+
input: {
|
|
3020
|
+
type: "object",
|
|
3021
|
+
properties: {
|
|
3022
|
+
search: {
|
|
3023
|
+
type: "string",
|
|
3024
|
+
description: "Free text matched against scenario titles, tags and step text. Empty string clears it."
|
|
3025
|
+
},
|
|
3026
|
+
status: {
|
|
3027
|
+
type: "string",
|
|
3028
|
+
enum: [...VIEW_STATUSES],
|
|
3029
|
+
description: 'Show only scenarios with this status. "all" clears the filter.'
|
|
3030
|
+
},
|
|
3031
|
+
tags: {
|
|
3032
|
+
type: "array",
|
|
3033
|
+
items: { type: "string" },
|
|
3034
|
+
description: "Show only scenarios carrying any of these tags. Empty array clears the filter."
|
|
3035
|
+
}
|
|
3036
|
+
}
|
|
3037
|
+
},
|
|
3038
|
+
execute: (input) => guarded(() => {
|
|
3039
|
+
const args = asRecord(input);
|
|
3040
|
+
const search = readString(args, "search");
|
|
3041
|
+
const status = readEnum(args, "status", VIEW_STATUSES);
|
|
3042
|
+
const tags = readStringArray(args, "tags");
|
|
3043
|
+
const applied = {
|
|
3044
|
+
search: search ?? deps.view.query,
|
|
3045
|
+
status: status ?? deps.view.status,
|
|
3046
|
+
tags: tags ?? deps.view.tags
|
|
3047
|
+
};
|
|
3048
|
+
const patch = {};
|
|
3049
|
+
if (search !== void 0) patch.query = search;
|
|
3050
|
+
if (status !== void 0) patch.status = status;
|
|
3051
|
+
if (tags !== void 0) patch.tags = tags;
|
|
3052
|
+
setView(patch);
|
|
3053
|
+
const matched = filterReport(report, {
|
|
3054
|
+
query: applied.search,
|
|
3055
|
+
status: applied.status,
|
|
3056
|
+
tags: applied.tags
|
|
3057
|
+
}).summary.total;
|
|
3058
|
+
const result = {
|
|
3059
|
+
...applied,
|
|
3060
|
+
matched,
|
|
3061
|
+
total: report.summary.total
|
|
3062
|
+
};
|
|
3063
|
+
onAgentFilter?.(result);
|
|
3064
|
+
return { ...provenance(), applied: result };
|
|
3065
|
+
})
|
|
3066
|
+
}
|
|
3067
|
+
};
|
|
3068
|
+
}
|
|
3069
|
+
|
|
2795
3070
|
// src/interactive/ReportInteractive.tsx
|
|
2796
|
-
var
|
|
3071
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
2797
3072
|
function ReportInteractive(props) {
|
|
2798
3073
|
const { report, className, title, dataTheme } = props;
|
|
2799
3074
|
const result = unwrapReport(report);
|
|
2800
3075
|
if (!result.ok) {
|
|
2801
|
-
return /* @__PURE__ */ (0,
|
|
3076
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
2802
3077
|
ReportErrorShell,
|
|
2803
3078
|
{
|
|
2804
3079
|
error: result.error,
|
|
@@ -2808,18 +3083,18 @@ function ReportInteractive(props) {
|
|
|
2808
3083
|
}
|
|
2809
3084
|
);
|
|
2810
3085
|
}
|
|
2811
|
-
return /* @__PURE__ */ (0,
|
|
3086
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ReportInteractiveView, { ...props, report: result.data });
|
|
2812
3087
|
}
|
|
2813
3088
|
var THEME_OPTIONS = [
|
|
2814
|
-
{ value: "light", label: "Light", Icon:
|
|
2815
|
-
{ value: "system", label: "System", Icon:
|
|
2816
|
-
{ value: "dark", label: "Dark", Icon:
|
|
3089
|
+
{ value: "light", label: "Light", Icon: import_lucide_react6.Sun },
|
|
3090
|
+
{ value: "system", label: "System", Icon: import_lucide_react6.Monitor },
|
|
3091
|
+
{ value: "dark", label: "Dark", Icon: import_lucide_react6.Moon }
|
|
2817
3092
|
];
|
|
2818
3093
|
function ThemeSegment({
|
|
2819
3094
|
pref,
|
|
2820
3095
|
onPref
|
|
2821
3096
|
}) {
|
|
2822
|
-
return /* @__PURE__ */ (0,
|
|
3097
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
2823
3098
|
ToggleGroup,
|
|
2824
3099
|
{
|
|
2825
3100
|
size: "sm",
|
|
@@ -2829,14 +3104,14 @@ function ThemeSegment({
|
|
|
2829
3104
|
if (next) onPref(next);
|
|
2830
3105
|
},
|
|
2831
3106
|
"aria-label": "Color theme",
|
|
2832
|
-
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ (0,
|
|
3107
|
+
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
2833
3108
|
ToggleGroupItem,
|
|
2834
3109
|
{
|
|
2835
3110
|
value,
|
|
2836
3111
|
"aria-label": label,
|
|
2837
3112
|
title: label,
|
|
2838
3113
|
className: "px-2",
|
|
2839
|
-
children: /* @__PURE__ */ (0,
|
|
3114
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Icon, {})
|
|
2840
3115
|
},
|
|
2841
3116
|
value
|
|
2842
3117
|
))
|
|
@@ -2857,26 +3132,26 @@ function ReportInteractiveView({
|
|
|
2857
3132
|
}) {
|
|
2858
3133
|
const [urlState, setUrlState] = useUrlState();
|
|
2859
3134
|
const { query, status: statusFilter, tags: activeTags, detail } = urlState;
|
|
2860
|
-
const setQuery = (0,
|
|
3135
|
+
const setQuery = (0, import_react22.useCallback)(
|
|
2861
3136
|
(next) => setUrlState({ query: next }),
|
|
2862
3137
|
[setUrlState]
|
|
2863
3138
|
);
|
|
2864
|
-
const setStatusFilter = (0,
|
|
3139
|
+
const setStatusFilter = (0, import_react22.useCallback)(
|
|
2865
3140
|
(next) => setUrlState({ status: next }),
|
|
2866
3141
|
[setUrlState]
|
|
2867
3142
|
);
|
|
2868
|
-
const setDetail = (0,
|
|
3143
|
+
const setDetail = (0, import_react22.useCallback)(
|
|
2869
3144
|
(next) => setUrlState({ detail: next }),
|
|
2870
3145
|
[setUrlState]
|
|
2871
3146
|
);
|
|
2872
|
-
const [helpOpen, setHelpOpen] = (0,
|
|
3147
|
+
const [helpOpen, setHelpOpen] = (0, import_react22.useState)(false);
|
|
2873
3148
|
const { pref: themePref, setPref: setThemePref } = useTheme();
|
|
2874
|
-
const searchRef = (0,
|
|
2875
|
-
const expandId = (0,
|
|
2876
|
-
const docsId = (0,
|
|
2877
|
-
const deferredQuery = (0,
|
|
2878
|
-
const failures = (0,
|
|
2879
|
-
const filtered = (0,
|
|
3149
|
+
const searchRef = (0, import_react22.useRef)(null);
|
|
3150
|
+
const expandId = (0, import_react22.useId)();
|
|
3151
|
+
const docsId = (0, import_react22.useId)();
|
|
3152
|
+
const deferredQuery = (0, import_react22.useDeferredValue)(query);
|
|
3153
|
+
const failures = (0, import_react22.useMemo)(() => listFailures(report), [report]);
|
|
3154
|
+
const filtered = (0, import_react22.useMemo)(
|
|
2880
3155
|
// Features carrying failures float to the top so the first thing on screen
|
|
2881
3156
|
// is the thing that needs attention; an all-green run keeps source order.
|
|
2882
3157
|
() => failuresFirst(
|
|
@@ -2889,7 +3164,7 @@ function ReportInteractiveView({
|
|
|
2889
3164
|
[report, deferredQuery, statusFilter, activeTags]
|
|
2890
3165
|
);
|
|
2891
3166
|
const isFiltering = query !== deferredQuery;
|
|
2892
|
-
const statusOptions = (0,
|
|
3167
|
+
const statusOptions = (0, import_react22.useMemo)(() => {
|
|
2893
3168
|
const s = report.summary;
|
|
2894
3169
|
const opts = [
|
|
2895
3170
|
{ key: "all", label: "All", count: s.total }
|
|
@@ -2904,21 +3179,21 @@ function ReportInteractiveView({
|
|
|
2904
3179
|
opts.push({ key: "pending", label: "Pending", count: s.pending });
|
|
2905
3180
|
return opts;
|
|
2906
3181
|
}, [report]);
|
|
2907
|
-
const tagOptions = (0,
|
|
2908
|
-
const toggleTag = (0,
|
|
3182
|
+
const tagOptions = (0, import_react22.useMemo)(() => allTags(report), [report]);
|
|
3183
|
+
const toggleTag = (0, import_react22.useCallback)(
|
|
2909
3184
|
(tag) => setUrlState({
|
|
2910
3185
|
tags: activeTags.includes(tag) ? activeTags.filter((t) => t !== tag) : [...activeTags, tag]
|
|
2911
3186
|
}),
|
|
2912
3187
|
[activeTags, setUrlState]
|
|
2913
3188
|
);
|
|
2914
|
-
const [toast, setToast] = (0,
|
|
2915
|
-
const toastTimer = (0,
|
|
2916
|
-
const showToast = (0,
|
|
3189
|
+
const [toast, setToast] = (0, import_react22.useState)(null);
|
|
3190
|
+
const toastTimer = (0, import_react22.useRef)(null);
|
|
3191
|
+
const showToast = (0, import_react22.useCallback)((msg) => {
|
|
2917
3192
|
setToast(msg);
|
|
2918
3193
|
if (toastTimer.current) clearTimeout(toastTimer.current);
|
|
2919
3194
|
toastTimer.current = setTimeout(() => setToast(null), 1800);
|
|
2920
3195
|
}, []);
|
|
2921
|
-
const copy = (0,
|
|
3196
|
+
const copy = (0, import_react22.useCallback)(
|
|
2922
3197
|
(text, msg) => {
|
|
2923
3198
|
if (typeof navigator !== "undefined" && navigator.clipboard) {
|
|
2924
3199
|
navigator.clipboard.writeText(text).then(
|
|
@@ -2929,7 +3204,7 @@ function ReportInteractiveView({
|
|
|
2929
3204
|
},
|
|
2930
3205
|
[showToast]
|
|
2931
3206
|
);
|
|
2932
|
-
const scenarioActions = (0,
|
|
3207
|
+
const scenarioActions = (0, import_react22.useMemo)(
|
|
2933
3208
|
() => ({
|
|
2934
3209
|
copyLink: (s) => copy(scenarioPermalink(s), "Link copied"),
|
|
2935
3210
|
copyMarkdown: (s) => copy(scenarioToMarkdown(s), "Markdown copied"),
|
|
@@ -2937,27 +3212,27 @@ function ReportInteractiveView({
|
|
|
2937
3212
|
}),
|
|
2938
3213
|
[copy]
|
|
2939
3214
|
);
|
|
2940
|
-
const failureIndexRef = (0,
|
|
2941
|
-
const allCollapsibleIds = (0,
|
|
3215
|
+
const failureIndexRef = (0, import_react22.useRef)(0);
|
|
3216
|
+
const allCollapsibleIds = (0, import_react22.useMemo)(
|
|
2942
3217
|
() => report.features.flatMap((f) => [f.id, ...f.scenarios.map((s) => s.id)]),
|
|
2943
3218
|
[report]
|
|
2944
3219
|
);
|
|
2945
3220
|
const collapse = useCollapseState(
|
|
2946
|
-
(0,
|
|
3221
|
+
(0, import_react22.useCallback)(() => defaultCollapsedIds(report), [report])
|
|
2947
3222
|
);
|
|
2948
3223
|
const revealFilteredResults = deferredQuery.trim() !== "" || statusFilter !== "all" || activeTags.length > 0;
|
|
2949
|
-
const visibleCollapse = (0,
|
|
3224
|
+
const visibleCollapse = (0, import_react22.useMemo)(
|
|
2950
3225
|
() => revealFilteredResults ? { ...collapse.api, isCollapsed: () => false } : collapse.api,
|
|
2951
3226
|
[collapse.api, revealFilteredResults]
|
|
2952
3227
|
);
|
|
2953
|
-
const collapseAll = (0,
|
|
3228
|
+
const collapseAll = (0, import_react22.useCallback)(
|
|
2954
3229
|
() => collapse.collapseAll(allCollapsibleIds),
|
|
2955
3230
|
[collapse, allCollapsibleIds]
|
|
2956
3231
|
);
|
|
2957
|
-
const [expandedAll, setExpandedAll] = (0,
|
|
3232
|
+
const [expandedAll, setExpandedAll] = (0, import_react22.useState)(
|
|
2958
3233
|
() => report.summary.failed === 0
|
|
2959
3234
|
);
|
|
2960
|
-
const setExpanded = (0,
|
|
3235
|
+
const setExpanded = (0, import_react22.useCallback)(
|
|
2961
3236
|
(expanded) => {
|
|
2962
3237
|
if (expanded) collapse.expandAll();
|
|
2963
3238
|
else collapseAll();
|
|
@@ -2965,10 +3240,24 @@ function ReportInteractiveView({
|
|
|
2965
3240
|
},
|
|
2966
3241
|
[collapse, collapseAll]
|
|
2967
3242
|
);
|
|
2968
|
-
const
|
|
3243
|
+
const [agentFilter, setAgentFilter] = (0, import_react22.useState)(null);
|
|
3244
|
+
(0, import_react21.useTools)(
|
|
3245
|
+
reportTools({
|
|
3246
|
+
report,
|
|
3247
|
+
view: urlState,
|
|
3248
|
+
setView: setUrlState,
|
|
3249
|
+
onAgentFilter: setAgentFilter
|
|
3250
|
+
})
|
|
3251
|
+
);
|
|
3252
|
+
const showAgentFilter = agentFilter !== null && agentFilter.search === query && agentFilter.status === statusFilter && agentFilter.tags.length === activeTags.length && agentFilter.tags.every((tag) => activeTags.includes(tag));
|
|
3253
|
+
const clearFilters = (0, import_react22.useCallback)(
|
|
3254
|
+
() => setUrlState({ query: "", status: "all", tags: [] }),
|
|
3255
|
+
[setUrlState]
|
|
3256
|
+
);
|
|
3257
|
+
const focusSearch = (0, import_react22.useCallback)(() => {
|
|
2969
3258
|
searchRef.current?.focus();
|
|
2970
3259
|
}, []);
|
|
2971
|
-
const stepFailure = (0,
|
|
3260
|
+
const stepFailure = (0, import_react22.useCallback)(
|
|
2972
3261
|
(direction) => {
|
|
2973
3262
|
if (failures.length === 0) return;
|
|
2974
3263
|
failureIndexRef.current = (failureIndexRef.current + direction + failures.length) % failures.length;
|
|
@@ -2977,10 +3266,10 @@ function ReportInteractiveView({
|
|
|
2977
3266
|
},
|
|
2978
3267
|
[failures]
|
|
2979
3268
|
);
|
|
2980
|
-
const toggleHelp = (0,
|
|
3269
|
+
const toggleHelp = (0, import_react22.useCallback)(() => {
|
|
2981
3270
|
setHelpOpen((v) => !v);
|
|
2982
3271
|
}, []);
|
|
2983
|
-
const escape = (0,
|
|
3272
|
+
const escape = (0, import_react22.useCallback)(() => {
|
|
2984
3273
|
if (helpOpen) setHelpOpen(false);
|
|
2985
3274
|
else if (query !== "") setQuery("");
|
|
2986
3275
|
}, [helpOpen, query, setQuery]);
|
|
@@ -2998,13 +3287,13 @@ function ReportInteractiveView({
|
|
|
2998
3287
|
const totalScenarios = report.summary.total;
|
|
2999
3288
|
const matchedScenarios = filtered.summary.total;
|
|
3000
3289
|
const showToc = !hideToc && totalScenarios > 3;
|
|
3001
|
-
return /* @__PURE__ */ (0,
|
|
3290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(CollapseProvider, { value: visibleCollapse, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ScenarioActionsProvider, { value: scenarioActions, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ScenarioHistoryProvider, { value: scenarioHistory ?? null, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ScenarioFreshnessProvider, { value: { staleAfterDays, report }, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3002
3291
|
ReportRoot,
|
|
3003
3292
|
{
|
|
3004
3293
|
report: filtered,
|
|
3005
3294
|
customRenderers,
|
|
3006
3295
|
renderers,
|
|
3007
|
-
children: /* @__PURE__ */ (0,
|
|
3296
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
3008
3297
|
"main",
|
|
3009
3298
|
{
|
|
3010
3299
|
className: cn("es-report", "es-report-interactive", className),
|
|
@@ -3013,8 +3302,8 @@ function ReportInteractiveView({
|
|
|
3013
3302
|
"data-theme": dataTheme,
|
|
3014
3303
|
"data-detail-level": detail,
|
|
3015
3304
|
children: [
|
|
3016
|
-
/* @__PURE__ */ (0,
|
|
3017
|
-
/* @__PURE__ */ (0,
|
|
3305
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("header", { className: "es-report-header", children: [
|
|
3306
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
3018
3307
|
"div",
|
|
3019
3308
|
{
|
|
3020
3309
|
"data-es-navbar": true,
|
|
@@ -3023,9 +3312,9 @@ function ReportInteractiveView({
|
|
|
3023
3312
|
hideHeader ? "justify-end" : "justify-between"
|
|
3024
3313
|
),
|
|
3025
3314
|
children: [
|
|
3026
|
-
hideHeader ? null : /* @__PURE__ */ (0,
|
|
3027
|
-
/* @__PURE__ */ (0,
|
|
3028
|
-
/* @__PURE__ */ (0,
|
|
3315
|
+
hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("h1", { className: "min-w-0", children: title ?? "Story Report" }),
|
|
3316
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3317
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3029
3318
|
ReportSearch,
|
|
3030
3319
|
{
|
|
3031
3320
|
ref: searchRef,
|
|
@@ -3035,16 +3324,16 @@ function ReportInteractiveView({
|
|
|
3035
3324
|
totalCount: totalScenarios
|
|
3036
3325
|
}
|
|
3037
3326
|
),
|
|
3038
|
-
/* @__PURE__ */ (0,
|
|
3327
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ThemeSegment, { pref: themePref, onPref: setThemePref })
|
|
3039
3328
|
] })
|
|
3040
3329
|
]
|
|
3041
3330
|
}
|
|
3042
3331
|
),
|
|
3043
|
-
hideHeader ? null : /* @__PURE__ */ (0,
|
|
3044
|
-
/* @__PURE__ */ (0,
|
|
3045
|
-
/* @__PURE__ */ (0,
|
|
3332
|
+
hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, { children: [
|
|
3333
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ReportSummary, {}),
|
|
3334
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ReportMeta, {})
|
|
3046
3335
|
] }),
|
|
3047
|
-
/* @__PURE__ */ (0,
|
|
3336
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3048
3337
|
ReportFreshness,
|
|
3049
3338
|
{
|
|
3050
3339
|
lastRunMs: reportLastRunMs(report),
|
|
@@ -3052,14 +3341,14 @@ function ReportInteractiveView({
|
|
|
3052
3341
|
staleAfterDays
|
|
3053
3342
|
}
|
|
3054
3343
|
),
|
|
3055
|
-
/* @__PURE__ */ (0,
|
|
3344
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3056
3345
|
ReportLastRunDelta,
|
|
3057
3346
|
{
|
|
3058
3347
|
history: scenarioHistory,
|
|
3059
3348
|
report
|
|
3060
3349
|
}
|
|
3061
3350
|
),
|
|
3062
|
-
/* @__PURE__ */ (0,
|
|
3351
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3063
3352
|
ReportFilters,
|
|
3064
3353
|
{
|
|
3065
3354
|
statuses: statusOptions,
|
|
@@ -3070,10 +3359,10 @@ function ReportInteractiveView({
|
|
|
3070
3359
|
onToggleTag: toggleTag
|
|
3071
3360
|
}
|
|
3072
3361
|
),
|
|
3073
|
-
/* @__PURE__ */ (0,
|
|
3074
|
-
showToc ? /* @__PURE__ */ (0,
|
|
3075
|
-
/* @__PURE__ */ (0,
|
|
3076
|
-
/* @__PURE__ */ (0,
|
|
3362
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border/60 pt-3", children: [
|
|
3363
|
+
showToc ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ReportTocDrawer, {}) : null,
|
|
3364
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3365
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3077
3366
|
Switch,
|
|
3078
3367
|
{
|
|
3079
3368
|
id: expandId,
|
|
@@ -3081,7 +3370,7 @@ function ReportInteractiveView({
|
|
|
3081
3370
|
onCheckedChange: setExpanded
|
|
3082
3371
|
}
|
|
3083
3372
|
),
|
|
3084
|
-
/* @__PURE__ */ (0,
|
|
3373
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3085
3374
|
"label",
|
|
3086
3375
|
{
|
|
3087
3376
|
htmlFor: expandId,
|
|
@@ -3090,8 +3379,8 @@ function ReportInteractiveView({
|
|
|
3090
3379
|
}
|
|
3091
3380
|
)
|
|
3092
3381
|
] }),
|
|
3093
|
-
/* @__PURE__ */ (0,
|
|
3094
|
-
/* @__PURE__ */ (0,
|
|
3382
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3383
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3095
3384
|
Switch,
|
|
3096
3385
|
{
|
|
3097
3386
|
id: docsId,
|
|
@@ -3099,7 +3388,7 @@ function ReportInteractiveView({
|
|
|
3099
3388
|
onCheckedChange: (checked) => setDetail(checked ? "full" : "minimal")
|
|
3100
3389
|
}
|
|
3101
3390
|
),
|
|
3102
|
-
/* @__PURE__ */ (0,
|
|
3391
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3103
3392
|
"label",
|
|
3104
3393
|
{
|
|
3105
3394
|
htmlFor: docsId,
|
|
@@ -3110,17 +3399,25 @@ function ReportInteractiveView({
|
|
|
3110
3399
|
] })
|
|
3111
3400
|
] })
|
|
3112
3401
|
] }),
|
|
3113
|
-
/* @__PURE__ */ (0,
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3402
|
+
showAgentFilter ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3403
|
+
ReportAgentFilterNotice,
|
|
3404
|
+
{
|
|
3405
|
+
applied: agentFilter,
|
|
3406
|
+
onReset: clearFilters,
|
|
3407
|
+
onDismiss: () => setAgentFilter(null)
|
|
3408
|
+
}
|
|
3409
|
+
) : null,
|
|
3410
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ReportFailureBanner, { failures }),
|
|
3411
|
+
hasContent ? showToc ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex gap-6", children: [
|
|
3412
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ReportToc, {}),
|
|
3413
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "flex min-w-0 flex-1 flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ReportFeatureList, {}) })
|
|
3414
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ReportFeatureList, {}) }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3118
3415
|
ReportEmpty,
|
|
3119
3416
|
{
|
|
3120
3417
|
message: query ? "No scenarios match the search." : void 0
|
|
3121
3418
|
}
|
|
3122
3419
|
),
|
|
3123
|
-
/* @__PURE__ */ (0,
|
|
3420
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3124
3421
|
"button",
|
|
3125
3422
|
{
|
|
3126
3423
|
type: "button",
|
|
@@ -3131,14 +3428,14 @@ function ReportInteractiveView({
|
|
|
3131
3428
|
children: "?"
|
|
3132
3429
|
}
|
|
3133
3430
|
),
|
|
3134
|
-
/* @__PURE__ */ (0,
|
|
3431
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3135
3432
|
ReportShortcutsHelp,
|
|
3136
3433
|
{
|
|
3137
3434
|
open: helpOpen,
|
|
3138
3435
|
onClose: () => setHelpOpen(false)
|
|
3139
3436
|
}
|
|
3140
3437
|
),
|
|
3141
|
-
toast ? /* @__PURE__ */ (0,
|
|
3438
|
+
toast ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3142
3439
|
"div",
|
|
3143
3440
|
{
|
|
3144
3441
|
role: "status",
|
|
@@ -3155,14 +3452,14 @@ function ReportInteractiveView({
|
|
|
3155
3452
|
}
|
|
3156
3453
|
|
|
3157
3454
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
3158
|
-
var
|
|
3455
|
+
var import_react25 = require("react");
|
|
3159
3456
|
|
|
3160
3457
|
// src/interactive/island-renderers.tsx
|
|
3161
|
-
var
|
|
3458
|
+
var import_react24 = require("react");
|
|
3162
3459
|
|
|
3163
3460
|
// src/components/doc/MermaidView.tsx
|
|
3164
|
-
var
|
|
3165
|
-
var
|
|
3461
|
+
var import_react23 = require("react");
|
|
3462
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
3166
3463
|
function prefersDark(el) {
|
|
3167
3464
|
const themed = el?.closest("[data-theme]");
|
|
3168
3465
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -3170,10 +3467,10 @@ function prefersDark(el) {
|
|
|
3170
3467
|
return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
|
|
3171
3468
|
}
|
|
3172
3469
|
function MermaidView({ entry, load }) {
|
|
3173
|
-
const ref = (0,
|
|
3174
|
-
const [svg, setSvg] = (0,
|
|
3175
|
-
const [error, setError] = (0,
|
|
3176
|
-
(0,
|
|
3470
|
+
const ref = (0, import_react23.useRef)(null);
|
|
3471
|
+
const [svg, setSvg] = (0, import_react23.useState)(null);
|
|
3472
|
+
const [error, setError] = (0, import_react23.useState)(null);
|
|
3473
|
+
(0, import_react23.useEffect)(() => {
|
|
3177
3474
|
let cancelled = false;
|
|
3178
3475
|
const draw = async () => {
|
|
3179
3476
|
let mermaid;
|
|
@@ -3216,9 +3513,9 @@ function MermaidView({ entry, load }) {
|
|
|
3216
3513
|
};
|
|
3217
3514
|
}, [entry.code, load]);
|
|
3218
3515
|
if (svg) {
|
|
3219
|
-
return /* @__PURE__ */ (0,
|
|
3220
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
3221
|
-
/* @__PURE__ */ (0,
|
|
3516
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("figure", { ref, className: "my-3", children: [
|
|
3517
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
3518
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3222
3519
|
"div",
|
|
3223
3520
|
{
|
|
3224
3521
|
role: "img",
|
|
@@ -3229,8 +3526,8 @@ function MermaidView({ entry, load }) {
|
|
|
3229
3526
|
)
|
|
3230
3527
|
] });
|
|
3231
3528
|
}
|
|
3232
|
-
return /* @__PURE__ */ (0,
|
|
3233
|
-
error ? /* @__PURE__ */ (0,
|
|
3529
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
|
|
3530
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
3234
3531
|
"p",
|
|
3235
3532
|
{
|
|
3236
3533
|
role: "alert",
|
|
@@ -3242,12 +3539,12 @@ function MermaidView({ entry, load }) {
|
|
|
3242
3539
|
]
|
|
3243
3540
|
}
|
|
3244
3541
|
) : null,
|
|
3245
|
-
/* @__PURE__ */ (0,
|
|
3542
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(MermaidSource, { entry, ref })
|
|
3246
3543
|
] });
|
|
3247
3544
|
}
|
|
3248
3545
|
|
|
3249
3546
|
// src/interactive/island-renderers.tsx
|
|
3250
|
-
var
|
|
3547
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
3251
3548
|
var HLJS_ESM = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
|
|
3252
3549
|
var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
|
|
3253
3550
|
function cachedCdnModule(url) {
|
|
@@ -3264,8 +3561,8 @@ function cachedCdnModule(url) {
|
|
|
3264
3561
|
var loadMermaidFromCdn = cachedCdnModule(MERMAID_ESM);
|
|
3265
3562
|
var loadHljs = cachedCdnModule(HLJS_ESM);
|
|
3266
3563
|
function CdnHighlightedCode({ entry }) {
|
|
3267
|
-
const [html, setHtml] = (0,
|
|
3268
|
-
(0,
|
|
3564
|
+
const [html, setHtml] = (0, import_react24.useState)(null);
|
|
3565
|
+
(0, import_react24.useEffect)(() => {
|
|
3269
3566
|
let cancelled = false;
|
|
3270
3567
|
void (async () => {
|
|
3271
3568
|
try {
|
|
@@ -3281,27 +3578,27 @@ function CdnHighlightedCode({ entry }) {
|
|
|
3281
3578
|
cancelled = true;
|
|
3282
3579
|
};
|
|
3283
3580
|
}, [entry.content, entry.lang]);
|
|
3284
|
-
return /* @__PURE__ */ (0,
|
|
3581
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3285
3582
|
"code",
|
|
3286
3583
|
{
|
|
3287
3584
|
className: cn("hljs font-mono text-xs", entry.lang && `language-${entry.lang}`),
|
|
3288
3585
|
dangerouslySetInnerHTML: { __html: html }
|
|
3289
3586
|
}
|
|
3290
|
-
) : /* @__PURE__ */ (0,
|
|
3587
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
3291
3588
|
}
|
|
3292
3589
|
function buildIslandRenderers(opts) {
|
|
3293
3590
|
const renderers = {};
|
|
3294
3591
|
if (opts.mermaid) {
|
|
3295
|
-
renderers.mermaid = (entry) => (0,
|
|
3592
|
+
renderers.mermaid = (entry) => (0, import_react24.createElement)(MermaidView, { entry, load: loadMermaidFromCdn });
|
|
3296
3593
|
}
|
|
3297
3594
|
if (opts.syntaxHighlighting) {
|
|
3298
|
-
renderers.code = (entry) => (0,
|
|
3595
|
+
renderers.code = (entry) => (0, import_react24.createElement)(CdnHighlightedCode, { entry });
|
|
3299
3596
|
}
|
|
3300
3597
|
return renderers;
|
|
3301
3598
|
}
|
|
3302
3599
|
|
|
3303
3600
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
3304
|
-
var
|
|
3601
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
3305
3602
|
function ReportInteractiveIsland({
|
|
3306
3603
|
report,
|
|
3307
3604
|
title,
|
|
@@ -3311,11 +3608,11 @@ function ReportInteractiveIsland({
|
|
|
3311
3608
|
syntaxHighlighting = true,
|
|
3312
3609
|
mermaid = true
|
|
3313
3610
|
}) {
|
|
3314
|
-
const renderers = (0,
|
|
3611
|
+
const renderers = (0, import_react25.useMemo)(
|
|
3315
3612
|
() => buildIslandRenderers({ syntaxHighlighting, mermaid }),
|
|
3316
3613
|
[syntaxHighlighting, mermaid]
|
|
3317
3614
|
);
|
|
3318
|
-
return /* @__PURE__ */ (0,
|
|
3615
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3319
3616
|
ReportInteractive,
|
|
3320
3617
|
{
|
|
3321
3618
|
report,
|