executable-stories-react 0.9.0 → 0.10.1
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 +540 -483
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -235
- package/dist/index.d.ts +50 -235
- package/dist/index.js +525 -475
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +615 -689
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +1 -233
- package/dist/interactive.d.ts +1 -233
- package/dist/interactive.js +607 -681
- package/dist/interactive.js.map +1 -1
- package/dist/parse.d.cts +3 -234
- package/dist/parse.d.ts +3 -234
- package/dist/report-island.global.js +28 -28
- package/dist/ssr.cjs +492 -449
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.d.cts +1 -232
- package/dist/ssr.d.ts +1 -232
- package/dist/ssr.js +484 -441
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +4 -4
package/dist/interactive.cjs
CHANGED
|
@@ -65,63 +65,6 @@ var import_react2 = require("react");
|
|
|
65
65
|
var import_react = require("react");
|
|
66
66
|
var ReportContext = (0, import_react.createContext)(null);
|
|
67
67
|
|
|
68
|
-
// src/context/ReportRoot.tsx
|
|
69
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
70
|
-
var EMPTY_CUSTOM = {};
|
|
71
|
-
var EMPTY_RENDERERS = {};
|
|
72
|
-
function ReportRoot({
|
|
73
|
-
report,
|
|
74
|
-
customRenderers,
|
|
75
|
-
renderers,
|
|
76
|
-
children
|
|
77
|
-
}) {
|
|
78
|
-
const value = (0, import_react2.useMemo)(
|
|
79
|
-
() => ({
|
|
80
|
-
report,
|
|
81
|
-
customRenderers: customRenderers ?? EMPTY_CUSTOM,
|
|
82
|
-
renderers: renderers ?? EMPTY_RENDERERS
|
|
83
|
-
}),
|
|
84
|
-
[report, customRenderers, renderers]
|
|
85
|
-
);
|
|
86
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReportContext.Provider, { value, children });
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// src/hooks/useReport.ts
|
|
90
|
-
var import_react3 = require("react");
|
|
91
|
-
function useReport() {
|
|
92
|
-
const ctx = (0, import_react3.useContext)(ReportContext);
|
|
93
|
-
if (!ctx) {
|
|
94
|
-
throw new Error(
|
|
95
|
-
"useReport must be used inside <ReportRoot> or <Report>. Wrap your tree with one of those."
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
return ctx.report;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// ../executable-stories-core/dist/utils/duration.js
|
|
102
|
-
function formatDuration(ms) {
|
|
103
|
-
if (ms < 1e3) {
|
|
104
|
-
return `${Math.round(ms)} ms`;
|
|
105
|
-
}
|
|
106
|
-
if (ms < 6e4) {
|
|
107
|
-
return `${(ms / 1e3).toFixed(2)} s`;
|
|
108
|
-
}
|
|
109
|
-
const minutes = Math.floor(ms / 6e4);
|
|
110
|
-
const seconds = Math.floor(ms % 6e4 / 1e3);
|
|
111
|
-
if (minutes < 60) {
|
|
112
|
-
return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
113
|
-
}
|
|
114
|
-
const hours = Math.floor(minutes / 60);
|
|
115
|
-
const remainingMinutes = minutes % 60;
|
|
116
|
-
return `${hours}h ${remainingMinutes}m`;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// src/components/doc/DocNote.tsx
|
|
120
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
121
|
-
function DocNote({ entry }) {
|
|
122
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
|
|
123
|
-
}
|
|
124
|
-
|
|
125
68
|
// src/components/ui/badge.tsx
|
|
126
69
|
var React = require("react");
|
|
127
70
|
var import_class_variance_authority = require("class-variance-authority");
|
|
@@ -180,14 +123,237 @@ function Badge({
|
|
|
180
123
|
});
|
|
181
124
|
}
|
|
182
125
|
|
|
183
|
-
// src/components/doc/
|
|
126
|
+
// src/components/doc/NarrativeBlocks.tsx
|
|
127
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
128
|
+
var FILE_TREE_TYPE = "file-tree";
|
|
129
|
+
var DATA_MODEL_TYPE = "data-model";
|
|
130
|
+
function isChangeKind(value) {
|
|
131
|
+
return value === "added" || value === "modified" || value === "removed" || value === "renamed";
|
|
132
|
+
}
|
|
133
|
+
function isRecord(value) {
|
|
134
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
135
|
+
}
|
|
136
|
+
function str(value) {
|
|
137
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
138
|
+
}
|
|
139
|
+
function AuthoredMarker({ authored }) {
|
|
140
|
+
if (authored !== "agent") return null;
|
|
141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "outline", className: "border-border text-[10px] text-muted-foreground", children: "AI-authored, not verified by a run" });
|
|
142
|
+
}
|
|
143
|
+
function BlockFrame({
|
|
144
|
+
title,
|
|
145
|
+
authored,
|
|
146
|
+
children
|
|
147
|
+
}) {
|
|
148
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("figure", { className: "my-3", children: [
|
|
149
|
+
title || authored === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("figcaption", { className: "mb-1.5 flex flex-wrap items-center gap-2", children: [
|
|
150
|
+
title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs font-medium text-muted-foreground", children: title }) : null,
|
|
151
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AuthoredMarker, { authored })
|
|
152
|
+
] }) : null,
|
|
153
|
+
children
|
|
154
|
+
] });
|
|
155
|
+
}
|
|
156
|
+
function ChangeBadge({ change }) {
|
|
157
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "tag", className: "text-[10px]", children: change });
|
|
158
|
+
}
|
|
159
|
+
function parseFileTree(data) {
|
|
160
|
+
if (!isRecord(data) || !Array.isArray(data.files)) return void 0;
|
|
161
|
+
const files = [];
|
|
162
|
+
for (const raw of data.files) {
|
|
163
|
+
if (typeof raw === "string") {
|
|
164
|
+
if (raw) files.push({ path: raw });
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (!isRecord(raw)) continue;
|
|
168
|
+
const path = str(raw.path);
|
|
169
|
+
if (!path) continue;
|
|
170
|
+
files.push({
|
|
171
|
+
path,
|
|
172
|
+
change: isChangeKind(raw.change) ? raw.change : void 0,
|
|
173
|
+
note: str(raw.note)
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
if (files.length === 0) return void 0;
|
|
177
|
+
return { title: str(data.title), authored: str(data.authored), files };
|
|
178
|
+
}
|
|
179
|
+
function buildTree(files) {
|
|
180
|
+
const root = { name: "", children: /* @__PURE__ */ new Map() };
|
|
181
|
+
for (const file of files) {
|
|
182
|
+
const segments = file.path.split("/").filter(Boolean);
|
|
183
|
+
let node = root;
|
|
184
|
+
segments.forEach((segment, index) => {
|
|
185
|
+
let child = node.children.get(segment);
|
|
186
|
+
if (!child) {
|
|
187
|
+
child = { name: segment, children: /* @__PURE__ */ new Map() };
|
|
188
|
+
node.children.set(segment, child);
|
|
189
|
+
}
|
|
190
|
+
if (index === segments.length - 1) child.file = file;
|
|
191
|
+
node = child;
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
return root;
|
|
195
|
+
}
|
|
196
|
+
function sortedChildren(node) {
|
|
197
|
+
return [...node.children.values()].sort((a, b) => {
|
|
198
|
+
const aDir = a.children.size > 0;
|
|
199
|
+
const bDir = b.children.size > 0;
|
|
200
|
+
if (aDir !== bDir) return aDir ? -1 : 1;
|
|
201
|
+
return a.name.localeCompare(b.name);
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function TreeBranch({ node, depth }) {
|
|
205
|
+
const children = sortedChildren(node);
|
|
206
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: cn("space-y-0.5", depth > 0 && "ml-3 border-l border-border/60 pl-3"), children: children.map((child) => {
|
|
207
|
+
const isDir = child.children.size > 0;
|
|
208
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
|
|
209
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-baseline gap-2", children: [
|
|
210
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
211
|
+
"span",
|
|
212
|
+
{
|
|
213
|
+
className: cn(
|
|
214
|
+
"font-mono text-xs",
|
|
215
|
+
isDir ? "text-muted-foreground" : "text-foreground"
|
|
216
|
+
),
|
|
217
|
+
children: isDir ? `${child.name}/` : child.name
|
|
218
|
+
}
|
|
219
|
+
),
|
|
220
|
+
child.file?.change ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeBadge, { change: child.file.change }) : null,
|
|
221
|
+
child.file?.note ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs text-muted-foreground", children: child.file.note }) : null
|
|
222
|
+
] }),
|
|
223
|
+
isDir ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TreeBranch, { node: child, depth: depth + 1 }) : null
|
|
224
|
+
] }, child.name);
|
|
225
|
+
}) });
|
|
226
|
+
}
|
|
227
|
+
function FileTreeBlock({ entry }) {
|
|
228
|
+
const data = parseFileTree(entry.data);
|
|
229
|
+
if (!data) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UnreadableBlock, { entry });
|
|
230
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BlockFrame, { title: data.title ?? "Files changed", authored: data.authored, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border bg-card p-3", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TreeBranch, { node: buildTree(data.files), depth: 0 }) }) });
|
|
231
|
+
}
|
|
232
|
+
function parseDataModel(data) {
|
|
233
|
+
if (!isRecord(data) || !Array.isArray(data.fields)) return void 0;
|
|
234
|
+
const fields = [];
|
|
235
|
+
for (const raw of data.fields) {
|
|
236
|
+
if (!isRecord(raw)) continue;
|
|
237
|
+
const name = str(raw.name);
|
|
238
|
+
if (!name) continue;
|
|
239
|
+
fields.push({
|
|
240
|
+
name,
|
|
241
|
+
type: str(raw.type),
|
|
242
|
+
note: str(raw.note),
|
|
243
|
+
change: isChangeKind(raw.change) ? raw.change : void 0
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
if (fields.length === 0) return void 0;
|
|
247
|
+
return {
|
|
248
|
+
title: str(data.title),
|
|
249
|
+
authored: str(data.authored),
|
|
250
|
+
name: str(data.name),
|
|
251
|
+
fields
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function DataModelBlock({ entry }) {
|
|
255
|
+
const data = parseDataModel(entry.data);
|
|
256
|
+
if (!data) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UnreadableBlock, { entry });
|
|
257
|
+
const hasNotes = data.fields.some((f) => f.note);
|
|
258
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BlockFrame, { title: data.title ?? data.name ?? "Data model", authored: data.authored, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "w-full border-collapse text-sm", children: [
|
|
259
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: "bg-muted/50", children: [
|
|
260
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Field" }),
|
|
261
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Type" }),
|
|
262
|
+
hasNotes ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Note" }) : null
|
|
263
|
+
] }) }),
|
|
264
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: data.fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
|
|
265
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "border-b border-border px-3 py-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex flex-wrap items-center gap-2", children: [
|
|
266
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-mono text-xs text-foreground", children: field.name }),
|
|
267
|
+
field.change ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeBadge, { change: field.change }) : null
|
|
268
|
+
] }) }),
|
|
269
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "border-b border-border px-3 py-2 font-mono text-xs text-muted-foreground", children: field.type ?? "" }),
|
|
270
|
+
hasNotes ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: field.note ?? "" }) : null
|
|
271
|
+
] }, field.name)) })
|
|
272
|
+
] }) }) });
|
|
273
|
+
}
|
|
274
|
+
function UnreadableBlock({ entry }) {
|
|
275
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
|
|
276
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: [
|
|
277
|
+
entry.type,
|
|
278
|
+
" (unrecognised shape)"
|
|
279
|
+
] }),
|
|
280
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
281
|
+
"pre",
|
|
282
|
+
{
|
|
283
|
+
tabIndex: 0,
|
|
284
|
+
className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground",
|
|
285
|
+
children: safeStringify(entry.data)
|
|
286
|
+
}
|
|
287
|
+
)
|
|
288
|
+
] });
|
|
289
|
+
}
|
|
290
|
+
function safeStringify(value) {
|
|
291
|
+
try {
|
|
292
|
+
return JSON.stringify(value, null, 2);
|
|
293
|
+
} catch {
|
|
294
|
+
return String(value);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
var narrativeBlockRenderers = {
|
|
298
|
+
[FILE_TREE_TYPE]: (entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileTreeBlock, { entry }),
|
|
299
|
+
[DATA_MODEL_TYPE]: (entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DataModelBlock, { entry })
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// src/context/ReportRoot.tsx
|
|
303
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
304
|
+
var EMPTY_RENDERERS = {};
|
|
305
|
+
function ReportRoot({
|
|
306
|
+
report,
|
|
307
|
+
customRenderers,
|
|
308
|
+
renderers,
|
|
309
|
+
children
|
|
310
|
+
}) {
|
|
311
|
+
const value = (0, import_react2.useMemo)(
|
|
312
|
+
() => ({
|
|
313
|
+
report,
|
|
314
|
+
// Narrative blocks render everywhere the report does (static SSR, the
|
|
315
|
+
// island, Astro) without every host wiring them up. A host renderer for
|
|
316
|
+
// the same type still wins.
|
|
317
|
+
customRenderers: { ...narrativeBlockRenderers, ...customRenderers },
|
|
318
|
+
renderers: renderers ?? EMPTY_RENDERERS
|
|
319
|
+
}),
|
|
320
|
+
[report, customRenderers, renderers]
|
|
321
|
+
);
|
|
322
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReportContext.Provider, { value, children });
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// src/hooks/useReport.ts
|
|
326
|
+
var import_react3 = require("react");
|
|
327
|
+
function useReport() {
|
|
328
|
+
const ctx = (0, import_react3.useContext)(ReportContext);
|
|
329
|
+
if (!ctx) {
|
|
330
|
+
throw new Error(
|
|
331
|
+
"useReport must be used inside <ReportRoot> or <Report>. Wrap your tree with one of those."
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
return ctx.report;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// src/components/ReportScenario.tsx
|
|
338
|
+
var import_duration3 = require("executable-stories-core/utils/duration");
|
|
339
|
+
|
|
340
|
+
// src/components/ReportSteps.tsx
|
|
341
|
+
var import_duration = require("executable-stories-core/utils/duration");
|
|
342
|
+
|
|
343
|
+
// src/components/doc/DocNote.tsx
|
|
184
344
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
345
|
+
function DocNote({ entry }) {
|
|
346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// src/components/doc/DocTag.tsx
|
|
350
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
185
351
|
function DocTag({ entry }) {
|
|
186
|
-
return /* @__PURE__ */ (0,
|
|
352
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "my-2 flex flex-wrap gap-1.5", "aria-label": "Tags", children: entry.names.map((n) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Badge, { variant: "tag", children: n }) }, n)) });
|
|
187
353
|
}
|
|
188
354
|
|
|
189
355
|
// src/components/doc/DocKv.tsx
|
|
190
|
-
var
|
|
356
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
191
357
|
function formatValue(value) {
|
|
192
358
|
if (value === null) return "null";
|
|
193
359
|
if (typeof value === "string") return value;
|
|
@@ -199,19 +365,19 @@ function formatValue(value) {
|
|
|
199
365
|
}
|
|
200
366
|
}
|
|
201
367
|
function DocKv({ entry }) {
|
|
202
|
-
return /* @__PURE__ */ (0,
|
|
203
|
-
/* @__PURE__ */ (0,
|
|
204
|
-
/* @__PURE__ */ (0,
|
|
368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
|
|
369
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { className: "font-semibold text-muted-foreground", children: entry.label }),
|
|
370
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { className: "font-mono text-foreground", children: formatValue(entry.value) })
|
|
205
371
|
] });
|
|
206
372
|
}
|
|
207
373
|
|
|
208
374
|
// src/hooks/useRenderers.ts
|
|
209
375
|
var import_react4 = require("react");
|
|
210
|
-
var
|
|
376
|
+
var EMPTY_CUSTOM = {};
|
|
211
377
|
var EMPTY_RENDERERS2 = {};
|
|
212
378
|
function useCustomRenderers() {
|
|
213
379
|
const ctx = (0, import_react4.useContext)(ReportContext);
|
|
214
|
-
return ctx?.customRenderers ??
|
|
380
|
+
return ctx?.customRenderers ?? EMPTY_CUSTOM;
|
|
215
381
|
}
|
|
216
382
|
function useBuiltinRenderers() {
|
|
217
383
|
const ctx = (0, import_react4.useContext)(ReportContext);
|
|
@@ -219,37 +385,37 @@ function useBuiltinRenderers() {
|
|
|
219
385
|
}
|
|
220
386
|
|
|
221
387
|
// src/components/doc/DocCode.tsx
|
|
222
|
-
var
|
|
388
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
223
389
|
function CodeFigure({ label, children }) {
|
|
224
|
-
return /* @__PURE__ */ (0,
|
|
225
|
-
label ? /* @__PURE__ */ (0,
|
|
226
|
-
/* @__PURE__ */ (0,
|
|
390
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("figure", { className: "my-3", children: [
|
|
391
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: label }) : null,
|
|
392
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3", children })
|
|
227
393
|
] });
|
|
228
394
|
}
|
|
229
395
|
function DocCode({ entry }) {
|
|
230
396
|
const renderers = useBuiltinRenderers();
|
|
231
397
|
if (renderers.code) {
|
|
232
|
-
return /* @__PURE__ */ (0,
|
|
398
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: renderers.code(entry) });
|
|
233
399
|
}
|
|
234
|
-
return /* @__PURE__ */ (0,
|
|
400
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CodeFigure, { label: entry.label, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
235
401
|
}
|
|
236
402
|
|
|
237
403
|
// src/components/doc/DocTable.tsx
|
|
238
|
-
var
|
|
404
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
239
405
|
function DocTable({ entry }) {
|
|
240
|
-
return /* @__PURE__ */ (0,
|
|
241
|
-
entry.label ? /* @__PURE__ */ (0,
|
|
242
|
-
/* @__PURE__ */ (0,
|
|
243
|
-
/* @__PURE__ */ (0,
|
|
244
|
-
/* @__PURE__ */ (0,
|
|
406
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("figure", { className: "my-3", children: [
|
|
407
|
+
entry.label ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.label }) : null,
|
|
408
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("table", { className: "w-full border-collapse text-sm", children: [
|
|
409
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tr", { className: "bg-muted/50", children: entry.columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: c }, c)) }) }),
|
|
410
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tbody", { children: entry.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tr", { children: row.map((cell, j) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: cell }, j)) }, i)) })
|
|
245
411
|
] }) })
|
|
246
412
|
] });
|
|
247
413
|
}
|
|
248
414
|
|
|
249
415
|
// src/components/doc/DocLink.tsx
|
|
250
|
-
var
|
|
416
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
251
417
|
function DocLink({ entry }) {
|
|
252
|
-
return /* @__PURE__ */ (0,
|
|
418
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
253
419
|
"a",
|
|
254
420
|
{
|
|
255
421
|
className: "text-sm font-medium text-primary underline underline-offset-2 hover:no-underline",
|
|
@@ -264,28 +430,13 @@ function DocLink({ entry }) {
|
|
|
264
430
|
// src/components/doc/DocSection.tsx
|
|
265
431
|
var import_marked = require("marked");
|
|
266
432
|
|
|
267
|
-
//
|
|
268
|
-
|
|
269
|
-
if (!value) return void 0;
|
|
270
|
-
const trimmed = value.trim();
|
|
271
|
-
const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(trimmed);
|
|
272
|
-
if (scheme && !/^https?$/i.test(scheme[1] ?? "")) return void 0;
|
|
273
|
-
return trimmed;
|
|
274
|
-
}
|
|
275
|
-
function safeImageUrl(value) {
|
|
276
|
-
if (!value) return void 0;
|
|
277
|
-
const trimmed = value.trim();
|
|
278
|
-
if (/^data:image\//i.test(trimmed)) return trimmed;
|
|
279
|
-
return safeUrl(trimmed);
|
|
280
|
-
}
|
|
281
|
-
function isLocalFsPath(value) {
|
|
282
|
-
return /^(?:[/\\]|[A-Za-z]:[/\\])/.test(value);
|
|
283
|
-
}
|
|
433
|
+
// src/lib/url.ts
|
|
434
|
+
var import_url = require("executable-stories-core/utils/url");
|
|
284
435
|
|
|
285
436
|
// src/components/doc/DocSection.tsx
|
|
286
|
-
var
|
|
437
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
287
438
|
function neutralizeUrl(value) {
|
|
288
|
-
return safeUrl(value) ?? "#";
|
|
439
|
+
return (0, import_url.safeUrl)(value) ?? "#";
|
|
289
440
|
}
|
|
290
441
|
function safeMarkdownHtml(markdown) {
|
|
291
442
|
const raw = import_marked.marked.parse(markdown, { async: false });
|
|
@@ -294,12 +445,12 @@ function safeMarkdownHtml(markdown) {
|
|
|
294
445
|
function DocSection({ entry }) {
|
|
295
446
|
const renderers = useBuiltinRenderers();
|
|
296
447
|
if (renderers.section) {
|
|
297
|
-
return /* @__PURE__ */ (0,
|
|
448
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: renderers.section(entry) });
|
|
298
449
|
}
|
|
299
450
|
const html = safeMarkdownHtml(entry.markdown);
|
|
300
|
-
return /* @__PURE__ */ (0,
|
|
301
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
302
|
-
/* @__PURE__ */ (0,
|
|
451
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("section", { className: "my-3 text-sm", "aria-label": entry.title, children: [
|
|
452
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h4", { className: "mb-1 font-semibold text-foreground", children: entry.title }) : null,
|
|
453
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
303
454
|
"div",
|
|
304
455
|
{
|
|
305
456
|
className: "es-doc-prose prose prose-sm max-w-none",
|
|
@@ -310,11 +461,11 @@ function DocSection({ entry }) {
|
|
|
310
461
|
}
|
|
311
462
|
|
|
312
463
|
// src/components/doc/DocMermaid.tsx
|
|
313
|
-
var
|
|
464
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
314
465
|
function MermaidSource({ entry, ref }) {
|
|
315
|
-
return /* @__PURE__ */ (0,
|
|
316
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
317
|
-
/* @__PURE__ */ (0,
|
|
466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("figure", { ref, className: "my-3", "aria-label": entry.title ?? "Diagram", children: [
|
|
467
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
468
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
318
469
|
"pre",
|
|
319
470
|
{
|
|
320
471
|
"data-mermaid": true,
|
|
@@ -328,24 +479,24 @@ function MermaidSource({ entry, ref }) {
|
|
|
328
479
|
function DocMermaid({ entry }) {
|
|
329
480
|
const renderers = useBuiltinRenderers();
|
|
330
481
|
if (renderers.mermaid) {
|
|
331
|
-
return /* @__PURE__ */ (0,
|
|
482
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: renderers.mermaid(entry) });
|
|
332
483
|
}
|
|
333
|
-
return /* @__PURE__ */ (0,
|
|
484
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MermaidSource, { entry });
|
|
334
485
|
}
|
|
335
486
|
|
|
336
487
|
// src/components/doc/DocScreenshot.tsx
|
|
337
|
-
var
|
|
488
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
338
489
|
function DocScreenshot({ entry }) {
|
|
339
|
-
const src = isLocalFsPath(entry.path) ? void 0 : safeImageUrl(entry.path);
|
|
490
|
+
const src = (0, import_url.isLocalFsPath)(entry.path) ? void 0 : (0, import_url.safeImageUrl)(entry.path);
|
|
340
491
|
if (!src) {
|
|
341
|
-
return /* @__PURE__ */ (0,
|
|
342
|
-
/* @__PURE__ */ (0,
|
|
343
|
-
/* @__PURE__ */ (0,
|
|
344
|
-
entry.alt ? /* @__PURE__ */ (0,
|
|
492
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
|
|
493
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "font-medium", children: "Screenshot unavailable" }),
|
|
494
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
495
|
+
entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.alt }) : null
|
|
345
496
|
] });
|
|
346
497
|
}
|
|
347
|
-
return /* @__PURE__ */ (0,
|
|
348
|
-
/* @__PURE__ */ (0,
|
|
498
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("figure", { className: "my-3", children: [
|
|
499
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
349
500
|
"img",
|
|
350
501
|
{
|
|
351
502
|
src,
|
|
@@ -354,24 +505,24 @@ function DocScreenshot({ entry }) {
|
|
|
354
505
|
className: "max-w-full rounded-md border border-border"
|
|
355
506
|
}
|
|
356
507
|
),
|
|
357
|
-
entry.alt ? /* @__PURE__ */ (0,
|
|
508
|
+
entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("figcaption", { className: "mt-1.5 text-xs text-muted-foreground", children: entry.alt }) : null
|
|
358
509
|
] });
|
|
359
510
|
}
|
|
360
511
|
|
|
361
512
|
// src/components/doc/DocVideo.tsx
|
|
362
|
-
var
|
|
513
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
363
514
|
function DocVideo({ entry }) {
|
|
364
|
-
if (isLocalFsPath(entry.path)) {
|
|
365
|
-
return /* @__PURE__ */ (0,
|
|
366
|
-
/* @__PURE__ */ (0,
|
|
367
|
-
/* @__PURE__ */ (0,
|
|
368
|
-
entry.caption ? /* @__PURE__ */ (0,
|
|
515
|
+
if ((0, import_url.isLocalFsPath)(entry.path)) {
|
|
516
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
|
|
517
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "font-medium", children: "Video unavailable" }),
|
|
518
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
519
|
+
entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.caption }) : null
|
|
369
520
|
] });
|
|
370
521
|
}
|
|
371
|
-
const src = safeUrl(entry.path);
|
|
372
|
-
const poster = safeUrl(entry.poster);
|
|
373
|
-
return /* @__PURE__ */ (0,
|
|
374
|
-
/* @__PURE__ */ (0,
|
|
522
|
+
const src = (0, import_url.safeUrl)(entry.path);
|
|
523
|
+
const poster = (0, import_url.safeUrl)(entry.poster);
|
|
524
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "my-3", children: [
|
|
525
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
375
526
|
"video",
|
|
376
527
|
{
|
|
377
528
|
controls: true,
|
|
@@ -381,21 +532,21 @@ function DocVideo({ entry }) {
|
|
|
381
532
|
className: "max-w-full rounded-md border border-border"
|
|
382
533
|
}
|
|
383
534
|
),
|
|
384
|
-
entry.caption ? /* @__PURE__ */ (0,
|
|
535
|
+
entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: entry.caption }) : null
|
|
385
536
|
] });
|
|
386
537
|
}
|
|
387
538
|
|
|
388
539
|
// src/components/doc/DocHtml.tsx
|
|
389
|
-
var
|
|
540
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
390
541
|
function DocHtml({ entry }) {
|
|
391
542
|
const height = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
392
543
|
const title = entry.title ?? "Embedded HTML";
|
|
393
|
-
const safeHref = safeUrl(entry.url ?? entry.path);
|
|
544
|
+
const safeHref = (0, import_url.safeUrl)(entry.url ?? entry.path);
|
|
394
545
|
const frameProps = entry.content !== void 0 ? { srcDoc: entry.content } : { src: safeHref ?? "" };
|
|
395
|
-
return /* @__PURE__ */ (0,
|
|
396
|
-
/* @__PURE__ */ (0,
|
|
397
|
-
/* @__PURE__ */ (0,
|
|
398
|
-
safeHref ? /* @__PURE__ */ (0,
|
|
546
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
|
|
547
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("figcaption", { className: "flex items-center justify-between border-b border-border bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground", children: [
|
|
548
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: entry.title ?? "HTML" }),
|
|
549
|
+
safeHref ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
399
550
|
"a",
|
|
400
551
|
{
|
|
401
552
|
href: safeHref,
|
|
@@ -408,7 +559,7 @@ function DocHtml({ entry }) {
|
|
|
408
559
|
}
|
|
409
560
|
) : null
|
|
410
561
|
] }),
|
|
411
|
-
/* @__PURE__ */ (0,
|
|
562
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
412
563
|
"iframe",
|
|
413
564
|
{
|
|
414
565
|
...frameProps,
|
|
@@ -423,7 +574,7 @@ function DocHtml({ entry }) {
|
|
|
423
574
|
}
|
|
424
575
|
|
|
425
576
|
// src/components/doc/DocState.tsx
|
|
426
|
-
var
|
|
577
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
427
578
|
function DocState({ entry }) {
|
|
428
579
|
let json;
|
|
429
580
|
try {
|
|
@@ -431,23 +582,23 @@ function DocState({ entry }) {
|
|
|
431
582
|
} catch {
|
|
432
583
|
json = String(entry.value);
|
|
433
584
|
}
|
|
434
|
-
return /* @__PURE__ */ (0,
|
|
585
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CodeFigure, { label: entry.label ?? "State", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("code", { className: "font-mono text-xs language-json", children: json }) });
|
|
435
586
|
}
|
|
436
587
|
|
|
437
588
|
// src/components/doc/DocCustom.tsx
|
|
438
|
-
var
|
|
589
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
439
590
|
function DocCustom({ entry }) {
|
|
440
591
|
const renderers = useCustomRenderers();
|
|
441
592
|
const renderer = renderers[entry.type];
|
|
442
593
|
if (renderer) {
|
|
443
|
-
return /* @__PURE__ */ (0,
|
|
594
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children: renderer(entry) });
|
|
444
595
|
}
|
|
445
|
-
return /* @__PURE__ */ (0,
|
|
446
|
-
/* @__PURE__ */ (0,
|
|
447
|
-
/* @__PURE__ */ (0,
|
|
596
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
|
|
597
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
|
|
598
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground", children: safeStringify2(entry.data) })
|
|
448
599
|
] });
|
|
449
600
|
}
|
|
450
|
-
function
|
|
601
|
+
function safeStringify2(value) {
|
|
451
602
|
try {
|
|
452
603
|
return JSON.stringify(value, null, 2);
|
|
453
604
|
} catch {
|
|
@@ -456,47 +607,47 @@ function safeStringify(value) {
|
|
|
456
607
|
}
|
|
457
608
|
|
|
458
609
|
// src/components/doc/DocEntry.tsx
|
|
459
|
-
var
|
|
610
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
460
611
|
function DocEntry({ entry }) {
|
|
461
612
|
switch (entry.kind) {
|
|
462
613
|
case "note":
|
|
463
|
-
return /* @__PURE__ */ (0,
|
|
614
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocNote, { entry });
|
|
464
615
|
case "tag":
|
|
465
|
-
return /* @__PURE__ */ (0,
|
|
616
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocTag, { entry });
|
|
466
617
|
case "kv":
|
|
467
|
-
return /* @__PURE__ */ (0,
|
|
618
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocKv, { entry });
|
|
468
619
|
case "code":
|
|
469
|
-
return /* @__PURE__ */ (0,
|
|
620
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocCode, { entry });
|
|
470
621
|
case "table":
|
|
471
|
-
return /* @__PURE__ */ (0,
|
|
622
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocTable, { entry });
|
|
472
623
|
case "link":
|
|
473
|
-
return /* @__PURE__ */ (0,
|
|
624
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocLink, { entry });
|
|
474
625
|
case "section":
|
|
475
|
-
return /* @__PURE__ */ (0,
|
|
626
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocSection, { entry });
|
|
476
627
|
case "mermaid":
|
|
477
|
-
return /* @__PURE__ */ (0,
|
|
628
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocMermaid, { entry });
|
|
478
629
|
case "screenshot":
|
|
479
|
-
return /* @__PURE__ */ (0,
|
|
630
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocScreenshot, { entry });
|
|
480
631
|
case "video":
|
|
481
|
-
return /* @__PURE__ */ (0,
|
|
632
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocVideo, { entry });
|
|
482
633
|
case "html":
|
|
483
|
-
return /* @__PURE__ */ (0,
|
|
634
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocHtml, { entry });
|
|
484
635
|
case "state":
|
|
485
|
-
return /* @__PURE__ */ (0,
|
|
636
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocState, { entry });
|
|
486
637
|
case "custom":
|
|
487
|
-
return /* @__PURE__ */ (0,
|
|
638
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocCustom, { entry });
|
|
488
639
|
}
|
|
489
640
|
}
|
|
490
641
|
|
|
491
642
|
// src/components/ReportDocEntries.tsx
|
|
492
|
-
var
|
|
643
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
493
644
|
function ReportDocEntries({ entries }) {
|
|
494
645
|
if (entries.length === 0) return null;
|
|
495
|
-
return /* @__PURE__ */ (0,
|
|
646
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_jsx_runtime17.Fragment, { children: entries.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocEntry, { entry }, i)) });
|
|
496
647
|
}
|
|
497
648
|
|
|
498
649
|
// src/lib/step-params.tsx
|
|
499
|
-
var
|
|
650
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
500
651
|
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
501
652
|
function highlightStepParams(text) {
|
|
502
653
|
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
@@ -508,7 +659,7 @@ function highlightStepParams(text) {
|
|
|
508
659
|
const end = start + match[0].length;
|
|
509
660
|
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
510
661
|
nodes.push(
|
|
511
|
-
/* @__PURE__ */ (0,
|
|
662
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
512
663
|
);
|
|
513
664
|
lastIndex = end;
|
|
514
665
|
});
|
|
@@ -517,7 +668,7 @@ function highlightStepParams(text) {
|
|
|
517
668
|
}
|
|
518
669
|
|
|
519
670
|
// src/components/ReportSteps.tsx
|
|
520
|
-
var
|
|
671
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
521
672
|
var STEP_GLYPH = {
|
|
522
673
|
passed: "\u2713",
|
|
523
674
|
failed: "\u2717",
|
|
@@ -532,21 +683,21 @@ var STEP_GLYPH_COLOR = {
|
|
|
532
683
|
};
|
|
533
684
|
function ReportSteps({ scenario }) {
|
|
534
685
|
if (scenario.steps.length === 0) return null;
|
|
535
|
-
return /* @__PURE__ */ (0,
|
|
686
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ReportStepItem, { step }, step.id)) });
|
|
536
687
|
}
|
|
537
688
|
function ReportStepItem({ step }) {
|
|
538
689
|
const kw = step.keyword.toLowerCase();
|
|
539
690
|
const continuation = kw === "and" || kw === "but";
|
|
540
|
-
return /* @__PURE__ */ (0,
|
|
691
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
541
692
|
"li",
|
|
542
693
|
{
|
|
543
694
|
id: step.id,
|
|
544
695
|
"data-status": step.status,
|
|
545
696
|
className: cn("py-1.5 text-[0.8125rem] leading-normal", continuation && "pl-5"),
|
|
546
697
|
children: [
|
|
547
|
-
/* @__PURE__ */ (0,
|
|
548
|
-
/* @__PURE__ */ (0,
|
|
549
|
-
/* @__PURE__ */ (0,
|
|
698
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-baseline gap-2", children: [
|
|
699
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { "aria-hidden": true, className: cn("w-4 shrink-0 text-center text-xs", STEP_GLYPH_COLOR[step.status]), children: STEP_GLYPH[step.status] ?? "\u25CB" }),
|
|
700
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
550
701
|
"span",
|
|
551
702
|
{
|
|
552
703
|
className: cn(
|
|
@@ -556,10 +707,10 @@ function ReportStepItem({ step }) {
|
|
|
556
707
|
children: step.keyword
|
|
557
708
|
}
|
|
558
709
|
),
|
|
559
|
-
/* @__PURE__ */ (0,
|
|
560
|
-
step.durationMs > 0 ? /* @__PURE__ */ (0,
|
|
710
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
|
|
711
|
+
step.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: (0, import_duration.formatDuration)(step.durationMs) }) : null
|
|
561
712
|
] }),
|
|
562
|
-
step.errorMessage ? /* @__PURE__ */ (0,
|
|
713
|
+
step.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
563
714
|
"pre",
|
|
564
715
|
{
|
|
565
716
|
role: "alert",
|
|
@@ -567,132 +718,17 @@ function ReportStepItem({ step }) {
|
|
|
567
718
|
children: step.errorMessage
|
|
568
719
|
}
|
|
569
720
|
) : null,
|
|
570
|
-
step.docEntries.length > 0 ? /* @__PURE__ */ (0,
|
|
721
|
+
step.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { "data-es-docs": true, className: "mt-2 ml-6", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ReportDocEntries, { entries: step.docEntries }) }) : null
|
|
571
722
|
]
|
|
572
723
|
}
|
|
573
724
|
);
|
|
574
725
|
}
|
|
575
726
|
|
|
576
|
-
// ../executable-stories-core/dist/state-diff.js
|
|
577
|
-
var isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
578
|
-
function deepEqual(a, b) {
|
|
579
|
-
if (Object.is(a, b)) return true;
|
|
580
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
581
|
-
return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
582
|
-
}
|
|
583
|
-
if (isPlainObject(a) && isPlainObject(b)) {
|
|
584
|
-
const ak = Object.keys(a);
|
|
585
|
-
const bk = Object.keys(b);
|
|
586
|
-
return ak.length === bk.length && ak.every((k) => k in b && deepEqual(a[k], b[k]));
|
|
587
|
-
}
|
|
588
|
-
return false;
|
|
589
|
-
}
|
|
590
|
-
var joinKey = (path, key) => path === "" ? key : `${path}.${key}`;
|
|
591
|
-
function walk(path, before, after, out) {
|
|
592
|
-
if (Object.is(before, after)) return;
|
|
593
|
-
if (Array.isArray(before) && Array.isArray(after)) {
|
|
594
|
-
const shared = Math.min(before.length, after.length);
|
|
595
|
-
for (let i = 0; i < shared; i++) walk(`${path}[${i}]`, before[i], after[i], out);
|
|
596
|
-
for (let i = shared; i < after.length; i++) out.push({ path: `${path}[${i}]`, kind: "added", after: after[i] });
|
|
597
|
-
for (let i = shared; i < before.length; i++) out.push({ path: `${path}[${i}]`, kind: "removed", before: before[i] });
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
if (isPlainObject(before) && isPlainObject(after)) {
|
|
601
|
-
for (const key of Object.keys(after)) {
|
|
602
|
-
const p = joinKey(path, key);
|
|
603
|
-
if (key in before) walk(p, before[key], after[key], out);
|
|
604
|
-
else out.push({ path: p, kind: "added", after: after[key] });
|
|
605
|
-
}
|
|
606
|
-
for (const key of Object.keys(before)) {
|
|
607
|
-
if (!(key in after)) out.push({ path: joinKey(path, key), kind: "removed", before: before[key] });
|
|
608
|
-
}
|
|
609
|
-
return;
|
|
610
|
-
}
|
|
611
|
-
if (!deepEqual(before, after)) out.push({ path, kind: "changed", before, after });
|
|
612
|
-
}
|
|
613
|
-
function diffStateValues(before, after) {
|
|
614
|
-
const out = [];
|
|
615
|
-
walk("", before, after, out);
|
|
616
|
-
return out;
|
|
617
|
-
}
|
|
618
|
-
function formatStateValue(value, maxLen = 60) {
|
|
619
|
-
const s = value === void 0 ? "undefined" : JSON.stringify(value);
|
|
620
|
-
return s.length > maxLen ? `${s.slice(0, maxLen - 1)}\u2026` : s;
|
|
621
|
-
}
|
|
622
|
-
function summarizeStateChanges(changes) {
|
|
623
|
-
return changes.map((c) => {
|
|
624
|
-
const at = c.path === "" ? "(root)" : c.path;
|
|
625
|
-
switch (c.kind) {
|
|
626
|
-
case "added":
|
|
627
|
-
return `+ ${at}: ${formatStateValue(c.after)}`;
|
|
628
|
-
case "removed":
|
|
629
|
-
return `\u2212 ${at}`;
|
|
630
|
-
case "changed":
|
|
631
|
-
return `${at}: ${formatStateValue(c.before)} \u2192 ${formatStateValue(c.after)}`;
|
|
632
|
-
}
|
|
633
|
-
});
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
// ../executable-stories-core/dist/storyboard.js
|
|
637
|
-
function findScreenshot(entries) {
|
|
638
|
-
for (const entry of entries) {
|
|
639
|
-
if (entry.kind === "screenshot") return entry;
|
|
640
|
-
if (entry.children) {
|
|
641
|
-
const nested = findScreenshot(entry.children);
|
|
642
|
-
if (nested) return nested;
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
return void 0;
|
|
646
|
-
}
|
|
647
|
-
function findStates(entries, out = []) {
|
|
648
|
-
for (const entry of entries) {
|
|
649
|
-
if (entry.kind === "state") out.push(entry);
|
|
650
|
-
if (entry.children) findStates(entry.children, out);
|
|
651
|
-
}
|
|
652
|
-
return out;
|
|
653
|
-
}
|
|
654
|
-
var laneOf = (label) => label ?? "";
|
|
655
|
-
function extractStoryboardFrames(scenario) {
|
|
656
|
-
const frames = [];
|
|
657
|
-
const laneOrder = [];
|
|
658
|
-
const previous = /* @__PURE__ */ new Map();
|
|
659
|
-
for (const step of scenario.steps) {
|
|
660
|
-
const shot = findScreenshot(step.docEntries);
|
|
661
|
-
const stateDocs = findStates(step.docEntries);
|
|
662
|
-
if (!shot && stateDocs.length === 0) continue;
|
|
663
|
-
const byLane = /* @__PURE__ */ new Map();
|
|
664
|
-
for (const doc of stateDocs) {
|
|
665
|
-
const lane = laneOf(doc.label);
|
|
666
|
-
if (!byLane.has(lane) && !laneOrder.includes(lane)) laneOrder.push(lane);
|
|
667
|
-
byLane.set(lane, doc);
|
|
668
|
-
}
|
|
669
|
-
const states = [];
|
|
670
|
-
for (const lane of laneOrder) {
|
|
671
|
-
const doc = byLane.get(lane);
|
|
672
|
-
if (!doc) continue;
|
|
673
|
-
const card = {
|
|
674
|
-
...doc.label !== void 0 && { label: doc.label },
|
|
675
|
-
value: doc.value
|
|
676
|
-
};
|
|
677
|
-
if (previous.has(lane)) card.changes = diffStateValues(previous.get(lane), doc.value);
|
|
678
|
-
previous.set(lane, doc.value);
|
|
679
|
-
states.push(card);
|
|
680
|
-
}
|
|
681
|
-
frames.push({
|
|
682
|
-
stepId: step.id,
|
|
683
|
-
stepIndex: step.index,
|
|
684
|
-
keyword: step.keyword,
|
|
685
|
-
text: step.text,
|
|
686
|
-
status: step.status,
|
|
687
|
-
...shot && { screenshot: { path: shot.path, ...shot.alt !== void 0 && { alt: shot.alt } } },
|
|
688
|
-
states
|
|
689
|
-
});
|
|
690
|
-
}
|
|
691
|
-
return frames;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
727
|
// src/components/ReportStoryboard.tsx
|
|
695
|
-
var
|
|
728
|
+
var import_storyboard = require("executable-stories-core/storyboard");
|
|
729
|
+
var import_state_diff = require("executable-stories-core/state-diff");
|
|
730
|
+
var import_url6 = require("executable-stories-core/utils/url");
|
|
731
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
696
732
|
var FRAME_GLYPH = {
|
|
697
733
|
passed: "\u2713",
|
|
698
734
|
failed: "\u2717",
|
|
@@ -706,48 +742,48 @@ var FRAME_GLYPH_COLOR = {
|
|
|
706
742
|
pending: "text-pend"
|
|
707
743
|
};
|
|
708
744
|
function ReportStoryboard({ scenario }) {
|
|
709
|
-
const frames = extractStoryboardFrames(scenario);
|
|
745
|
+
const frames = (0, import_storyboard.extractStoryboardFrames)(scenario);
|
|
710
746
|
if (frames.length < 2) return null;
|
|
711
|
-
return /* @__PURE__ */ (0,
|
|
712
|
-
/* @__PURE__ */ (0,
|
|
713
|
-
/* @__PURE__ */ (0,
|
|
747
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
|
|
748
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
|
|
749
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ol", { className: "flex items-start gap-3 overflow-x-auto pb-2", children: frames.map((frame) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StoryboardFrameItem, { frame }, frame.stepId)) })
|
|
714
750
|
] });
|
|
715
751
|
}
|
|
716
752
|
function StoryboardFrameItem({ frame }) {
|
|
717
753
|
const label = `${frame.keyword} ${frame.text}`;
|
|
718
754
|
const hasStates = frame.states.length > 0;
|
|
719
|
-
const caption = /* @__PURE__ */ (0,
|
|
720
|
-
/* @__PURE__ */ (0,
|
|
721
|
-
/* @__PURE__ */ (0,
|
|
722
|
-
/* @__PURE__ */ (0,
|
|
755
|
+
const caption = /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
|
|
756
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
|
|
757
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "min-w-0", children: [
|
|
758
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
|
|
723
759
|
" ",
|
|
724
|
-
/* @__PURE__ */ (0,
|
|
760
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-muted-foreground", children: frame.screenshot?.alt ?? frame.text })
|
|
725
761
|
] })
|
|
726
762
|
] });
|
|
727
763
|
return (
|
|
728
764
|
// State cards need room for diff rows; screenshot-only frames keep the
|
|
729
765
|
// original narrow film-cell width (and DOM) unchanged.
|
|
730
|
-
/* @__PURE__ */ (0,
|
|
731
|
-
frame.screenshot ? /* @__PURE__ */ (0,
|
|
732
|
-
hasStates ? /* @__PURE__ */ (0,
|
|
766
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("li", { className: cn("shrink-0", hasStates ? "w-64" : "w-40"), children: [
|
|
767
|
+
frame.screenshot ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(FrameScreenshot, { frame, label }) : null,
|
|
768
|
+
hasStates ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: cn("flex flex-col gap-1.5", frame.screenshot && "mt-1.5"), children: frame.states.map((card, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StateCardView, { card }, card.label ?? i)) }) : null,
|
|
733
769
|
frame.screenshot ? caption : (
|
|
734
770
|
// No screenshot means no image anchor, so the caption carries the
|
|
735
771
|
// jump-to-step link instead.
|
|
736
|
-
/* @__PURE__ */ (0,
|
|
772
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("a", { href: `#${frame.stepId}`, "aria-label": `Jump to step: ${label}`, className: "block hover:underline", children: caption })
|
|
737
773
|
)
|
|
738
774
|
] })
|
|
739
775
|
);
|
|
740
776
|
}
|
|
741
777
|
function FrameScreenshot({ frame, label }) {
|
|
742
778
|
const path = frame.screenshot?.path ?? "";
|
|
743
|
-
const src = isLocalFsPath(path) ? void 0 : safeImageUrl(path);
|
|
744
|
-
return /* @__PURE__ */ (0,
|
|
779
|
+
const src = (0, import_url6.isLocalFsPath)(path) ? void 0 : (0, import_url6.safeImageUrl)(path);
|
|
780
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
745
781
|
"a",
|
|
746
782
|
{
|
|
747
783
|
href: `#${frame.stepId}`,
|
|
748
784
|
"aria-label": `Jump to step: ${label}`,
|
|
749
785
|
className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
|
|
750
|
-
children: src ? /* @__PURE__ */ (0,
|
|
786
|
+
children: src ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
751
787
|
"img",
|
|
752
788
|
{
|
|
753
789
|
src,
|
|
@@ -755,7 +791,7 @@ function FrameScreenshot({ frame, label }) {
|
|
|
755
791
|
loading: "lazy",
|
|
756
792
|
className: "h-24 w-full bg-muted object-cover object-top"
|
|
757
793
|
}
|
|
758
|
-
) : /* @__PURE__ */ (0,
|
|
794
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "flex h-24 w-full items-center justify-center border-b border-dashed border-border bg-muted px-2 text-center text-[0.6875rem] text-muted-foreground", children: "Screenshot unavailable" })
|
|
759
795
|
}
|
|
760
796
|
);
|
|
761
797
|
}
|
|
@@ -774,30 +810,30 @@ function prettyJson(value) {
|
|
|
774
810
|
function StateCardView({ card }) {
|
|
775
811
|
const json = prettyJson(card.value);
|
|
776
812
|
const firstCapture = card.changes === void 0;
|
|
777
|
-
return /* @__PURE__ */ (0,
|
|
778
|
-
/* @__PURE__ */ (0,
|
|
779
|
-
/* @__PURE__ */ (0,
|
|
780
|
-
firstCapture ? /* @__PURE__ */ (0,
|
|
813
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { "data-slot": "state-card", className: "rounded-md border border-border bg-card p-2", children: [
|
|
814
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: "flex flex-wrap items-baseline gap-1.5", children: [
|
|
815
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "inline-flex rounded-full border border-border px-1.5 font-mono text-[0.625rem] font-medium text-muted-foreground", children: card.label ?? "State" }),
|
|
816
|
+
firstCapture ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-[0.625rem] text-muted-foreground italic", children: "first capture" }) : null
|
|
781
817
|
] }),
|
|
782
|
-
!firstCapture && (card.changes && card.changes.length > 0 ? /* @__PURE__ */ (0,
|
|
818
|
+
!firstCapture && (card.changes && card.changes.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { className: "mt-1.5 flex flex-col gap-0.5", children: card.changes.map((change, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
783
819
|
"li",
|
|
784
820
|
{
|
|
785
821
|
className: cn(
|
|
786
822
|
"rounded-sm px-1.5 py-0.5 font-mono text-[0.625rem] leading-snug break-all",
|
|
787
823
|
CHANGE_TONE[change.kind]
|
|
788
824
|
),
|
|
789
|
-
children: summarizeStateChanges([change])[0]
|
|
825
|
+
children: (0, import_state_diff.summarizeStateChanges)([change])[0]
|
|
790
826
|
},
|
|
791
827
|
i
|
|
792
|
-
)) }) : /* @__PURE__ */ (0,
|
|
793
|
-
/* @__PURE__ */ (0,
|
|
828
|
+
)) }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "mt-1.5 text-[0.625rem] text-muted-foreground", children: "No changes" })),
|
|
829
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
794
830
|
"details",
|
|
795
831
|
{
|
|
796
832
|
open: firstCapture && json.length <= 240,
|
|
797
833
|
className: cn(firstCapture ? "mt-1.5" : "mt-1"),
|
|
798
834
|
children: [
|
|
799
|
-
/* @__PURE__ */ (0,
|
|
800
|
-
/* @__PURE__ */ (0,
|
|
835
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("summary", { className: "cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground", children: "Snapshot" }),
|
|
836
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { tabIndex: 0, className: "mt-1 max-h-48 overflow-auto rounded-sm bg-muted p-1.5 font-mono text-[0.625rem] leading-snug", children: json })
|
|
801
837
|
]
|
|
802
838
|
}
|
|
803
839
|
)
|
|
@@ -805,17 +841,17 @@ function StateCardView({ card }) {
|
|
|
805
841
|
}
|
|
806
842
|
|
|
807
843
|
// src/components/ReportAttachments.tsx
|
|
808
|
-
var
|
|
844
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
809
845
|
function ReportAttachments({ attachments }) {
|
|
810
846
|
if (attachments.length === 0) return null;
|
|
811
847
|
return (
|
|
812
848
|
// role="group" (not a labelled <section>) so multiple scenarios' attachment
|
|
813
849
|
// blocks don't create duplicate "Attachments" region landmarks.
|
|
814
|
-
/* @__PURE__ */ (0,
|
|
850
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
|
|
815
851
|
const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
|
|
816
852
|
const isImage = att.mediaType.startsWith("image/");
|
|
817
|
-
return /* @__PURE__ */ (0,
|
|
818
|
-
/* @__PURE__ */ (0,
|
|
853
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
854
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
819
855
|
"img",
|
|
820
856
|
{
|
|
821
857
|
src: dataUri,
|
|
@@ -824,8 +860,8 @@ function ReportAttachments({ attachments }) {
|
|
|
824
860
|
className: "max-w-full rounded-md border border-border"
|
|
825
861
|
}
|
|
826
862
|
),
|
|
827
|
-
/* @__PURE__ */ (0,
|
|
828
|
-
] }) : /* @__PURE__ */ (0,
|
|
863
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
|
|
864
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
829
865
|
"a",
|
|
830
866
|
{
|
|
831
867
|
href: dataUri,
|
|
@@ -834,7 +870,7 @@ function ReportAttachments({ attachments }) {
|
|
|
834
870
|
children: [
|
|
835
871
|
att.name,
|
|
836
872
|
" ",
|
|
837
|
-
/* @__PURE__ */ (0,
|
|
873
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
838
874
|
"(",
|
|
839
875
|
att.mediaType,
|
|
840
876
|
")"
|
|
@@ -846,6 +882,9 @@ function ReportAttachments({ attachments }) {
|
|
|
846
882
|
);
|
|
847
883
|
}
|
|
848
884
|
|
|
885
|
+
// src/components/ReportTrace.tsx
|
|
886
|
+
var import_duration2 = require("executable-stories-core/utils/duration");
|
|
887
|
+
|
|
849
888
|
// src/lib/trace.ts
|
|
850
889
|
var VALID = /* @__PURE__ */ new Set(["ok", "error", "unset"]);
|
|
851
890
|
var safeStatus = (s) => VALID.has(s) ? s : "unset";
|
|
@@ -898,15 +937,15 @@ function toTraceRows(spans) {
|
|
|
898
937
|
roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
899
938
|
const rows = [];
|
|
900
939
|
const seen = /* @__PURE__ */ new Set();
|
|
901
|
-
const
|
|
940
|
+
const walk = (node, depth) => {
|
|
902
941
|
if (seen.has(node.span.spanId)) return;
|
|
903
942
|
seen.add(node.span.spanId);
|
|
904
943
|
rows.push({ ...node.span, depth });
|
|
905
|
-
for (const child of node.children)
|
|
944
|
+
for (const child of node.children) walk(child, depth + 1);
|
|
906
945
|
};
|
|
907
|
-
for (const root of roots)
|
|
946
|
+
for (const root of roots) walk(root, 0);
|
|
908
947
|
for (const node of byId.values()) {
|
|
909
|
-
if (!seen.has(node.span.spanId))
|
|
948
|
+
if (!seen.has(node.span.spanId)) walk(node, 0);
|
|
910
949
|
}
|
|
911
950
|
return rows;
|
|
912
951
|
}
|
|
@@ -922,7 +961,7 @@ function traceWindow(rows) {
|
|
|
922
961
|
}
|
|
923
962
|
|
|
924
963
|
// src/components/ReportTrace.tsx
|
|
925
|
-
var
|
|
964
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
926
965
|
var BAR_COLOR = {
|
|
927
966
|
ok: "bg-pass",
|
|
928
967
|
error: "bg-fail",
|
|
@@ -933,21 +972,21 @@ function ReportTrace({ spans }) {
|
|
|
933
972
|
const rows = toTraceRows(spans);
|
|
934
973
|
if (rows.length === 0) return null;
|
|
935
974
|
const { minStartMs, totalMs } = traceWindow(rows);
|
|
936
|
-
return /* @__PURE__ */ (0,
|
|
937
|
-
/* @__PURE__ */ (0,
|
|
975
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
|
|
976
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
|
|
938
977
|
"Trace (",
|
|
939
978
|
rows.length,
|
|
940
979
|
" span",
|
|
941
980
|
rows.length === 1 ? "" : "s",
|
|
942
981
|
", ",
|
|
943
|
-
formatDuration(totalMs),
|
|
982
|
+
(0, import_duration2.formatDuration)(totalMs),
|
|
944
983
|
")"
|
|
945
984
|
] }),
|
|
946
|
-
/* @__PURE__ */ (0,
|
|
985
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
|
|
947
986
|
const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
|
|
948
987
|
const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
|
|
949
|
-
return /* @__PURE__ */ (0,
|
|
950
|
-
/* @__PURE__ */ (0,
|
|
988
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("li", { className: "flex items-center gap-2", children: [
|
|
989
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
951
990
|
"span",
|
|
952
991
|
{
|
|
953
992
|
className: "min-w-0 flex-1 truncate text-foreground",
|
|
@@ -956,14 +995,14 @@ function ReportTrace({ spans }) {
|
|
|
956
995
|
children: row.name
|
|
957
996
|
}
|
|
958
997
|
),
|
|
959
|
-
/* @__PURE__ */ (0,
|
|
998
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
960
999
|
"span",
|
|
961
1000
|
{
|
|
962
1001
|
className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
|
|
963
1002
|
style: { left: `${leftPct}%`, width: `${widthPct}%` }
|
|
964
1003
|
}
|
|
965
1004
|
) }),
|
|
966
|
-
/* @__PURE__ */ (0,
|
|
1005
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: (0, import_duration2.formatDuration)(row.durationMs) })
|
|
967
1006
|
] }, `${row.spanId}-${i}`);
|
|
968
1007
|
}) })
|
|
969
1008
|
] });
|
|
@@ -1032,7 +1071,7 @@ function diffSinceLastRun(history, scenarios) {
|
|
|
1032
1071
|
}
|
|
1033
1072
|
|
|
1034
1073
|
// src/components/ScenarioRunHistory.tsx
|
|
1035
|
-
var
|
|
1074
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1036
1075
|
var MAX_DOTS = 10;
|
|
1037
1076
|
var DOT_COLOR = {
|
|
1038
1077
|
passed: "bg-pass",
|
|
@@ -1052,16 +1091,16 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
1052
1091
|
const recent = entries.slice(-MAX_DOTS);
|
|
1053
1092
|
const flaky = flakinessOf(recent) === "flaky";
|
|
1054
1093
|
const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
|
|
1055
|
-
return /* @__PURE__ */ (0,
|
|
1056
|
-
flaky ? /* @__PURE__ */ (0,
|
|
1057
|
-
/* @__PURE__ */ (0,
|
|
1094
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
1095
|
+
flaky ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
|
|
1096
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1058
1097
|
"span",
|
|
1059
1098
|
{
|
|
1060
1099
|
role: "img",
|
|
1061
1100
|
"aria-label": `Run history: ${summary}`,
|
|
1062
1101
|
title: summary,
|
|
1063
1102
|
className: "flex shrink-0 items-center gap-[3px]",
|
|
1064
|
-
children: recent.map((e, i) => /* @__PURE__ */ (0,
|
|
1103
|
+
children: recent.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1065
1104
|
"span",
|
|
1066
1105
|
{
|
|
1067
1106
|
"aria-hidden": true,
|
|
@@ -1139,130 +1178,14 @@ function useCollapseState(computeDefault) {
|
|
|
1139
1178
|
|
|
1140
1179
|
// src/interactive/scenario-actions.tsx
|
|
1141
1180
|
var import_react7 = require("react");
|
|
1142
|
-
|
|
1143
|
-
// ../executable-stories-core/dist/utils/scenario-markdown.js
|
|
1144
|
-
function cell(value) {
|
|
1145
|
-
return value.replaceAll("|", "\\|").replaceAll("\n", " ");
|
|
1146
|
-
}
|
|
1147
|
-
function stringify(value) {
|
|
1148
|
-
if (typeof value === "string") return value;
|
|
1149
|
-
try {
|
|
1150
|
-
return JSON.stringify(value, null, 2) ?? String(value);
|
|
1151
|
-
} catch {
|
|
1152
|
-
return String(value);
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
function docEntryToMarkdown(entry, stateLanes) {
|
|
1156
|
-
const lines = [];
|
|
1157
|
-
switch (entry.kind) {
|
|
1158
|
-
case "note":
|
|
1159
|
-
lines.push(entry.text);
|
|
1160
|
-
break;
|
|
1161
|
-
case "tag":
|
|
1162
|
-
lines.push(entry.names.map((n) => `\`@${n}\``).join(" "));
|
|
1163
|
-
break;
|
|
1164
|
-
case "kv":
|
|
1165
|
-
lines.push(`**${entry.label}:** ${stringify(entry.value)}`);
|
|
1166
|
-
break;
|
|
1167
|
-
case "code":
|
|
1168
|
-
lines.push(`**${entry.label}**`, "", "```" + (entry.lang ?? ""), entry.content, "```");
|
|
1169
|
-
break;
|
|
1170
|
-
case "table": {
|
|
1171
|
-
lines.push(`**${entry.label}**`, "");
|
|
1172
|
-
lines.push(`| ${entry.columns.map(cell).join(" | ")} |`);
|
|
1173
|
-
lines.push(`| ${entry.columns.map(() => "---").join(" | ")} |`);
|
|
1174
|
-
for (const row of entry.rows) lines.push(`| ${row.map(cell).join(" | ")} |`);
|
|
1175
|
-
break;
|
|
1176
|
-
}
|
|
1177
|
-
case "link":
|
|
1178
|
-
lines.push(`[${entry.label}](${entry.url})`);
|
|
1179
|
-
break;
|
|
1180
|
-
case "section":
|
|
1181
|
-
lines.push(`### ${entry.title}`, "", entry.markdown);
|
|
1182
|
-
break;
|
|
1183
|
-
case "mermaid":
|
|
1184
|
-
if (entry.title) lines.push(`**${entry.title}**`, "");
|
|
1185
|
-
lines.push("```mermaid", entry.code, "```");
|
|
1186
|
-
break;
|
|
1187
|
-
case "screenshot":
|
|
1188
|
-
lines.push(``);
|
|
1189
|
-
break;
|
|
1190
|
-
case "video":
|
|
1191
|
-
lines.push(`Video: ${entry.path}${entry.caption ? ` \u2014 ${entry.caption}` : ""}`);
|
|
1192
|
-
break;
|
|
1193
|
-
case "html": {
|
|
1194
|
-
const htmlTitle = entry.title ?? "Embedded HTML";
|
|
1195
|
-
if (entry.content) {
|
|
1196
|
-
lines.push(`**${htmlTitle}**`, "", "```html", entry.content, "```");
|
|
1197
|
-
} else if (entry.url) {
|
|
1198
|
-
lines.push(`[${htmlTitle}](${entry.url})`);
|
|
1199
|
-
} else {
|
|
1200
|
-
lines.push(`Embedded HTML: ${entry.path ?? "(inline)"}`);
|
|
1201
|
-
}
|
|
1202
|
-
break;
|
|
1203
|
-
}
|
|
1204
|
-
case "custom":
|
|
1205
|
-
lines.push(`**${entry.type}**`, "", "```json", stringify(entry.data), "```");
|
|
1206
|
-
break;
|
|
1207
|
-
case "state": {
|
|
1208
|
-
const lane = entry.label ?? "";
|
|
1209
|
-
lines.push(`**${entry.label ?? "State"}**`);
|
|
1210
|
-
if (stateLanes?.has(lane)) {
|
|
1211
|
-
const summary = summarizeStateChanges(diffStateValues(stateLanes.get(lane), entry.value));
|
|
1212
|
-
if (summary.length > 0) lines.push("", ...summary.map((l) => `- ${l}`));
|
|
1213
|
-
}
|
|
1214
|
-
stateLanes?.set(lane, entry.value);
|
|
1215
|
-
lines.push("", "<details>", "<summary>snapshot</summary>", "", "```json", stringify(entry.value ?? null), "```", "", "</details>");
|
|
1216
|
-
break;
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
for (const child of entry.children ?? []) {
|
|
1220
|
-
lines.push("", ...docEntryToMarkdown(child, stateLanes));
|
|
1221
|
-
}
|
|
1222
|
-
return lines;
|
|
1223
|
-
}
|
|
1224
|
-
function stepLines(step, ordinal, full, stateLanes) {
|
|
1225
|
-
const status = step.status === "passed" ? "" : ` \u2014 **${step.status}**`;
|
|
1226
|
-
const lines = [`${ordinal}. **${step.keyword}** ${step.text}${status}`];
|
|
1227
|
-
if (!full) return lines;
|
|
1228
|
-
if (step.errorMessage) {
|
|
1229
|
-
lines.push(...step.errorMessage.split("\n").map((l) => ` > ${l}`));
|
|
1230
|
-
}
|
|
1231
|
-
for (const entry of step.docEntries) {
|
|
1232
|
-
lines.push("", ...docEntryToMarkdown(entry, stateLanes).map((l) => l === "" ? l : ` ${l}`));
|
|
1233
|
-
}
|
|
1234
|
-
return lines;
|
|
1235
|
-
}
|
|
1236
|
-
function scenarioToMarkdown(scenario, options = {}) {
|
|
1237
|
-
const { variant = "full", meta = [] } = options;
|
|
1238
|
-
const full = variant === "full";
|
|
1239
|
-
const lines = full ? [`# ${scenario.title}`, ""] : [`## ${scenario.title} _(${scenario.status})_`, ""];
|
|
1240
|
-
if (full && meta.length > 0) lines.push(...meta);
|
|
1241
|
-
const stateLanes = /* @__PURE__ */ new Map();
|
|
1242
|
-
if (scenario.steps.length > 0) {
|
|
1243
|
-
if (full) lines.push("", "## Steps", "");
|
|
1244
|
-
scenario.steps.forEach((step, i) => lines.push(...stepLines(step, i + 1, full, stateLanes)));
|
|
1245
|
-
}
|
|
1246
|
-
if (scenario.errorMessage) {
|
|
1247
|
-
if (full) lines.push("", "## Failure", "");
|
|
1248
|
-
else lines.push("");
|
|
1249
|
-
lines.push("```", scenario.errorMessage.trim(), "```");
|
|
1250
|
-
}
|
|
1251
|
-
if (full && scenario.docEntries.length > 0) {
|
|
1252
|
-
lines.push("", "## Docs", "");
|
|
1253
|
-
for (const entry of scenario.docEntries) lines.push(...docEntryToMarkdown(entry, stateLanes), "");
|
|
1254
|
-
}
|
|
1255
|
-
return lines.join("\n").replaceAll(/\n{3,}/g, "\n\n").trimEnd() + (full ? "\n" : "");
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
// src/interactive/scenario-actions.tsx
|
|
1181
|
+
var import_scenario_markdown = require("executable-stories-core/utils/scenario-markdown");
|
|
1259
1182
|
var ScenarioActionsContext = (0, import_react7.createContext)(null);
|
|
1260
1183
|
var ScenarioActionsProvider = ScenarioActionsContext.Provider;
|
|
1261
1184
|
function useScenarioActions() {
|
|
1262
1185
|
return (0, import_react7.useContext)(ScenarioActionsContext);
|
|
1263
1186
|
}
|
|
1264
|
-
function
|
|
1265
|
-
return scenarioToMarkdown(scenario, { variant: "compact" });
|
|
1187
|
+
function scenarioToMarkdown(scenario) {
|
|
1188
|
+
return (0, import_scenario_markdown.scenarioToMarkdown)(scenario, { variant: "compact" });
|
|
1266
1189
|
}
|
|
1267
1190
|
function scenarioToPrompt(scenario) {
|
|
1268
1191
|
const lines = [
|
|
@@ -1290,9 +1213,9 @@ function scenarioPermalink(scenario) {
|
|
|
1290
1213
|
|
|
1291
1214
|
// src/components/ui/card.tsx
|
|
1292
1215
|
var React2 = require("react");
|
|
1293
|
-
var
|
|
1216
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1294
1217
|
function Card({ className, ...props }) {
|
|
1295
|
-
return /* @__PURE__ */ (0,
|
|
1218
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1296
1219
|
"div",
|
|
1297
1220
|
{
|
|
1298
1221
|
"data-slot": "card",
|
|
@@ -1305,7 +1228,7 @@ function Card({ className, ...props }) {
|
|
|
1305
1228
|
);
|
|
1306
1229
|
}
|
|
1307
1230
|
function CardHeader({ className, ...props }) {
|
|
1308
|
-
return /* @__PURE__ */ (0,
|
|
1231
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1309
1232
|
"div",
|
|
1310
1233
|
{
|
|
1311
1234
|
"data-slot": "card-header",
|
|
@@ -1318,7 +1241,7 @@ function CardHeader({ className, ...props }) {
|
|
|
1318
1241
|
);
|
|
1319
1242
|
}
|
|
1320
1243
|
function CardContent({ className, ...props }) {
|
|
1321
|
-
return /* @__PURE__ */ (0,
|
|
1244
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1322
1245
|
"div",
|
|
1323
1246
|
{
|
|
1324
1247
|
"data-slot": "card-content",
|
|
@@ -1332,13 +1255,13 @@ function CardContent({ className, ...props }) {
|
|
|
1332
1255
|
var React3 = require("react");
|
|
1333
1256
|
var import_menu = require("@base-ui/react/menu");
|
|
1334
1257
|
var import_lucide_react = require("lucide-react");
|
|
1335
|
-
var
|
|
1258
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1336
1259
|
var itemClasses = "relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 [&_svg:not([class*='text-'])]:text-muted-foreground";
|
|
1337
1260
|
function DropdownMenu(props) {
|
|
1338
|
-
return /* @__PURE__ */ (0,
|
|
1261
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1339
1262
|
}
|
|
1340
1263
|
function DropdownMenuTrigger(props) {
|
|
1341
|
-
return /* @__PURE__ */ (0,
|
|
1264
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
1342
1265
|
}
|
|
1343
1266
|
function DropdownMenuContent({
|
|
1344
1267
|
className,
|
|
@@ -1346,14 +1269,14 @@ function DropdownMenuContent({
|
|
|
1346
1269
|
sideOffset = 4,
|
|
1347
1270
|
...props
|
|
1348
1271
|
}) {
|
|
1349
|
-
return /* @__PURE__ */ (0,
|
|
1272
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1350
1273
|
import_menu.Menu.Positioner,
|
|
1351
1274
|
{
|
|
1352
1275
|
"data-slot": "dropdown-menu-positioner",
|
|
1353
1276
|
className: "z-50",
|
|
1354
1277
|
align,
|
|
1355
1278
|
sideOffset,
|
|
1356
|
-
children: /* @__PURE__ */ (0,
|
|
1279
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1357
1280
|
import_menu.Menu.Popup,
|
|
1358
1281
|
{
|
|
1359
1282
|
"data-slot": "dropdown-menu-content",
|
|
@@ -1371,7 +1294,7 @@ function DropdownMenuItem({
|
|
|
1371
1294
|
className,
|
|
1372
1295
|
...props
|
|
1373
1296
|
}) {
|
|
1374
|
-
return /* @__PURE__ */ (0,
|
|
1297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1375
1298
|
import_menu.Menu.Item,
|
|
1376
1299
|
{
|
|
1377
1300
|
"data-slot": "dropdown-menu-item",
|
|
@@ -1383,7 +1306,7 @@ function DropdownMenuItem({
|
|
|
1383
1306
|
|
|
1384
1307
|
// src/components/ReportScenario.tsx
|
|
1385
1308
|
var import_lucide_react2 = require("lucide-react");
|
|
1386
|
-
var
|
|
1309
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1387
1310
|
var STATUS_META = {
|
|
1388
1311
|
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
1389
1312
|
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
@@ -1399,7 +1322,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1399
1322
|
const collapsible = collapse !== null && !hideTitle;
|
|
1400
1323
|
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
1401
1324
|
const actions = useScenarioActions();
|
|
1402
|
-
return /* @__PURE__ */ (0,
|
|
1325
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1403
1326
|
Card,
|
|
1404
1327
|
{
|
|
1405
1328
|
id: scenario.id,
|
|
@@ -1407,10 +1330,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1407
1330
|
...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
|
|
1408
1331
|
className: "gap-0 py-0",
|
|
1409
1332
|
children: [
|
|
1410
|
-
/* @__PURE__ */ (0,
|
|
1411
|
-
/* @__PURE__ */ (0,
|
|
1412
|
-
hideTitle ? null : /* @__PURE__ */ (0,
|
|
1413
|
-
collapsible ? /* @__PURE__ */ (0,
|
|
1333
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardHeader, { className: "px-4 py-3", children: [
|
|
1334
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
1335
|
+
hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
1336
|
+
collapsible ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1414
1337
|
"button",
|
|
1415
1338
|
{
|
|
1416
1339
|
type: "button",
|
|
@@ -1419,49 +1342,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1419
1342
|
"aria-controls": bodyId,
|
|
1420
1343
|
"aria-label": `Toggle ${scenario.title}`,
|
|
1421
1344
|
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
1422
|
-
children: /* @__PURE__ */ (0,
|
|
1345
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
1423
1346
|
}
|
|
1424
1347
|
) : null,
|
|
1425
|
-
/* @__PURE__ */ (0,
|
|
1426
|
-
/* @__PURE__ */ (0,
|
|
1348
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
1349
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: scenario.title })
|
|
1427
1350
|
] }),
|
|
1428
|
-
/* @__PURE__ */ (0,
|
|
1429
|
-
/* @__PURE__ */ (0,
|
|
1430
|
-
scenario.durationMs > 0 ? /* @__PURE__ */ (0,
|
|
1431
|
-
meta.showPill ? /* @__PURE__ */ (0,
|
|
1432
|
-
actions ? /* @__PURE__ */ (0,
|
|
1433
|
-
/* @__PURE__ */ (0,
|
|
1351
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1352
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1353
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: (0, import_duration3.formatDuration)(scenario.durationMs) }) : null,
|
|
1354
|
+
meta.showPill ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "sr-only", children: `Status: ${label}` }),
|
|
1355
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenu, { children: [
|
|
1356
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1434
1357
|
DropdownMenuTrigger,
|
|
1435
1358
|
{
|
|
1436
1359
|
"aria-label": `Actions for ${scenario.title}`,
|
|
1437
1360
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
1438
|
-
children: /* @__PURE__ */ (0,
|
|
1361
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
|
|
1439
1362
|
}
|
|
1440
1363
|
),
|
|
1441
|
-
/* @__PURE__ */ (0,
|
|
1442
|
-
/* @__PURE__ */ (0,
|
|
1443
|
-
/* @__PURE__ */ (0,
|
|
1364
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuContent, { align: "end", children: [
|
|
1365
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
1366
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.LinkIcon, {}),
|
|
1444
1367
|
" Copy link"
|
|
1445
1368
|
] }),
|
|
1446
|
-
/* @__PURE__ */ (0,
|
|
1447
|
-
/* @__PURE__ */ (0,
|
|
1369
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
1370
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.FileTextIcon, {}),
|
|
1448
1371
|
" Copy as Markdown"
|
|
1449
1372
|
] }),
|
|
1450
|
-
/* @__PURE__ */ (0,
|
|
1451
|
-
/* @__PURE__ */ (0,
|
|
1373
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
1374
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.SparklesIcon, {}),
|
|
1452
1375
|
" Explain with AI"
|
|
1453
1376
|
] })
|
|
1454
1377
|
] })
|
|
1455
1378
|
] }) : null
|
|
1456
1379
|
] })
|
|
1457
1380
|
] }),
|
|
1458
|
-
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0,
|
|
1459
|
-
scenario.tags.map((t) => /* @__PURE__ */ (0,
|
|
1460
|
-
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0,
|
|
1381
|
+
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
|
|
1382
|
+
scenario.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
|
|
1383
|
+
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("li", { children: ticket.url ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
|
|
1461
1384
|
] }) : null
|
|
1462
1385
|
] }),
|
|
1463
|
-
/* @__PURE__ */ (0,
|
|
1464
|
-
scenario.errorMessage ? /* @__PURE__ */ (0,
|
|
1386
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
1387
|
+
scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1465
1388
|
"pre",
|
|
1466
1389
|
{
|
|
1467
1390
|
role: "alert",
|
|
@@ -1469,11 +1392,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1469
1392
|
children: scenario.errorMessage
|
|
1470
1393
|
}
|
|
1471
1394
|
) : null,
|
|
1472
|
-
/* @__PURE__ */ (0,
|
|
1473
|
-
/* @__PURE__ */ (0,
|
|
1474
|
-
scenario.docEntries.length > 0 ? /* @__PURE__ */ (0,
|
|
1475
|
-
/* @__PURE__ */ (0,
|
|
1476
|
-
/* @__PURE__ */ (0,
|
|
1395
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportStoryboard, { scenario }),
|
|
1396
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportSteps, { scenario }),
|
|
1397
|
+
scenario.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
|
|
1398
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportAttachments, { attachments: scenario.attachments }),
|
|
1399
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportTrace, { spans: scenario.otelSpans })
|
|
1477
1400
|
] })
|
|
1478
1401
|
]
|
|
1479
1402
|
}
|
|
@@ -1481,13 +1404,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1481
1404
|
}
|
|
1482
1405
|
|
|
1483
1406
|
// src/components/ReportScenarioList.tsx
|
|
1484
|
-
var
|
|
1407
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1485
1408
|
function ReportScenarioList({ feature }) {
|
|
1486
|
-
return /* @__PURE__ */ (0,
|
|
1409
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_jsx_runtime27.Fragment, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportScenario, { scenario }, scenario.id)) });
|
|
1487
1410
|
}
|
|
1488
1411
|
|
|
1489
1412
|
// src/components/ReportFeature.tsx
|
|
1490
|
-
var
|
|
1413
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1491
1414
|
function ReportFeature({ feature }) {
|
|
1492
1415
|
const titleId = `${feature.id}-title`;
|
|
1493
1416
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1498,7 +1421,7 @@ function ReportFeature({ feature }) {
|
|
|
1498
1421
|
return (
|
|
1499
1422
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
1500
1423
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1501
|
-
/* @__PURE__ */ (0,
|
|
1424
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
1502
1425
|
"section",
|
|
1503
1426
|
{
|
|
1504
1427
|
id: feature.id,
|
|
@@ -1506,9 +1429,9 @@ function ReportFeature({ feature }) {
|
|
|
1506
1429
|
"aria-labelledby": titleId,
|
|
1507
1430
|
className: "flex flex-col gap-3",
|
|
1508
1431
|
children: [
|
|
1509
|
-
/* @__PURE__ */ (0,
|
|
1510
|
-
/* @__PURE__ */ (0,
|
|
1511
|
-
/* @__PURE__ */ (0,
|
|
1432
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1433
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "min-w-0", children: [
|
|
1434
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
1512
1435
|
"button",
|
|
1513
1436
|
{
|
|
1514
1437
|
type: "button",
|
|
@@ -1517,31 +1440,31 @@ function ReportFeature({ feature }) {
|
|
|
1517
1440
|
"aria-controls": bodyId,
|
|
1518
1441
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1519
1442
|
children: [
|
|
1520
|
-
/* @__PURE__ */ (0,
|
|
1521
|
-
/* @__PURE__ */ (0,
|
|
1443
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
|
|
1444
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "truncate", children: feature.title })
|
|
1522
1445
|
]
|
|
1523
1446
|
}
|
|
1524
1447
|
) : feature.title }),
|
|
1525
|
-
/* @__PURE__ */ (0,
|
|
1448
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
|
|
1526
1449
|
] }),
|
|
1527
|
-
/* @__PURE__ */ (0,
|
|
1450
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
1528
1451
|
"p",
|
|
1529
1452
|
{
|
|
1530
1453
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1531
1454
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1532
1455
|
children: [
|
|
1533
|
-
/* @__PURE__ */ (0,
|
|
1456
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { children: [
|
|
1534
1457
|
s.passed,
|
|
1535
1458
|
" passed"
|
|
1536
1459
|
] }),
|
|
1537
|
-
/* @__PURE__ */ (0,
|
|
1538
|
-
/* @__PURE__ */ (0,
|
|
1460
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1461
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1539
1462
|
s.failed,
|
|
1540
1463
|
" failed"
|
|
1541
1464
|
] }),
|
|
1542
|
-
skipped > 0 ? /* @__PURE__ */ (0,
|
|
1543
|
-
/* @__PURE__ */ (0,
|
|
1544
|
-
/* @__PURE__ */ (0,
|
|
1465
|
+
skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
1466
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1467
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { children: [
|
|
1545
1468
|
skipped,
|
|
1546
1469
|
" skipped"
|
|
1547
1470
|
] })
|
|
@@ -1550,7 +1473,7 @@ function ReportFeature({ feature }) {
|
|
|
1550
1473
|
}
|
|
1551
1474
|
)
|
|
1552
1475
|
] }),
|
|
1553
|
-
/* @__PURE__ */ (0,
|
|
1476
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ReportScenarioList, { feature }) })
|
|
1554
1477
|
]
|
|
1555
1478
|
}
|
|
1556
1479
|
)
|
|
@@ -1558,17 +1481,17 @@ function ReportFeature({ feature }) {
|
|
|
1558
1481
|
}
|
|
1559
1482
|
|
|
1560
1483
|
// src/components/ReportFeatureList.tsx
|
|
1561
|
-
var
|
|
1484
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1562
1485
|
function ReportFeatureList() {
|
|
1563
1486
|
const report = useReport();
|
|
1564
|
-
return /* @__PURE__ */ (0,
|
|
1487
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ReportFeature, { feature }, feature.id)) });
|
|
1565
1488
|
}
|
|
1566
1489
|
|
|
1567
1490
|
// src/components/ui/empty.tsx
|
|
1568
1491
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
1569
|
-
var
|
|
1492
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1570
1493
|
function Empty({ className, ...props }) {
|
|
1571
|
-
return /* @__PURE__ */ (0,
|
|
1494
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1572
1495
|
"div",
|
|
1573
1496
|
{
|
|
1574
1497
|
"data-slot": "empty",
|
|
@@ -1581,7 +1504,7 @@ function Empty({ className, ...props }) {
|
|
|
1581
1504
|
);
|
|
1582
1505
|
}
|
|
1583
1506
|
function EmptyHeader({ className, ...props }) {
|
|
1584
|
-
return /* @__PURE__ */ (0,
|
|
1507
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1585
1508
|
"div",
|
|
1586
1509
|
{
|
|
1587
1510
|
"data-slot": "empty-header",
|
|
@@ -1608,7 +1531,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
|
|
|
1608
1531
|
}
|
|
1609
1532
|
);
|
|
1610
1533
|
function EmptyTitle({ className, ...props }) {
|
|
1611
|
-
return /* @__PURE__ */ (0,
|
|
1534
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1612
1535
|
"div",
|
|
1613
1536
|
{
|
|
1614
1537
|
"data-slot": "empty-title",
|
|
@@ -1619,16 +1542,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1619
1542
|
}
|
|
1620
1543
|
|
|
1621
1544
|
// src/components/ReportEmpty.tsx
|
|
1622
|
-
var
|
|
1545
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1623
1546
|
function ReportEmpty({ message }) {
|
|
1624
|
-
return /* @__PURE__ */ (0,
|
|
1547
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(EmptyHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
|
|
1625
1548
|
}
|
|
1626
1549
|
|
|
1627
1550
|
// src/components/ReportSummary.tsx
|
|
1628
|
-
var
|
|
1551
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1629
1552
|
function ReportSummary({ className }) {
|
|
1630
1553
|
const report = useReport();
|
|
1631
|
-
return /* @__PURE__ */ (0,
|
|
1554
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1632
1555
|
ReportSummaryView,
|
|
1633
1556
|
{
|
|
1634
1557
|
summary: report.summary,
|
|
@@ -1654,7 +1577,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1654
1577
|
if (summary.pending > 0) {
|
|
1655
1578
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1656
1579
|
}
|
|
1657
|
-
return /* @__PURE__ */ (0,
|
|
1580
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1658
1581
|
"dl",
|
|
1659
1582
|
{
|
|
1660
1583
|
className: cn(
|
|
@@ -1667,17 +1590,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1667
1590
|
"aria-label": ariaLabel,
|
|
1668
1591
|
children: cards.map((c) => {
|
|
1669
1592
|
const tone = TONE[c.status];
|
|
1670
|
-
return /* @__PURE__ */ (0,
|
|
1593
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
1671
1594
|
"div",
|
|
1672
1595
|
{
|
|
1673
1596
|
"data-status": c.status,
|
|
1674
1597
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1675
1598
|
children: [
|
|
1676
|
-
/* @__PURE__ */ (0,
|
|
1677
|
-
/* @__PURE__ */ (0,
|
|
1599
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
|
|
1600
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1678
1601
|
c.label
|
|
1679
1602
|
] }),
|
|
1680
|
-
/* @__PURE__ */ (0,
|
|
1603
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
|
|
1681
1604
|
]
|
|
1682
1605
|
},
|
|
1683
1606
|
c.status
|
|
@@ -1687,6 +1610,9 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1687
1610
|
);
|
|
1688
1611
|
}
|
|
1689
1612
|
|
|
1613
|
+
// src/components/ReportMeta.tsx
|
|
1614
|
+
var import_duration4 = require("executable-stories-core/utils/duration");
|
|
1615
|
+
|
|
1690
1616
|
// src/lib/provenance.ts
|
|
1691
1617
|
function reportLastRunMs(report) {
|
|
1692
1618
|
if (report.finishedAtMs && report.finishedAtMs > 0) return report.finishedAtMs;
|
|
@@ -1737,7 +1663,7 @@ function prUrl(ci) {
|
|
|
1737
1663
|
}
|
|
1738
1664
|
|
|
1739
1665
|
// src/components/ReportMeta.tsx
|
|
1740
|
-
var
|
|
1666
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1741
1667
|
function ReportMeta() {
|
|
1742
1668
|
const report = useReport();
|
|
1743
1669
|
const items = [];
|
|
@@ -1746,7 +1672,7 @@ function ReportMeta() {
|
|
|
1746
1672
|
items.push({ label: "Started", value: new Date(report.startedAtMs).toLocaleString() });
|
|
1747
1673
|
}
|
|
1748
1674
|
if (report.durationMs) {
|
|
1749
|
-
items.push({ label: "Duration", value: formatDuration(report.durationMs) });
|
|
1675
|
+
items.push({ label: "Duration", value: (0, import_duration4.formatDuration)(report.durationMs) });
|
|
1750
1676
|
}
|
|
1751
1677
|
if (report.packageVersion) {
|
|
1752
1678
|
items.push({ label: "Version", value: report.packageVersion });
|
|
@@ -1760,13 +1686,13 @@ function ReportMeta() {
|
|
|
1760
1686
|
const short = sha.slice(0, 8);
|
|
1761
1687
|
items.push({
|
|
1762
1688
|
label: "Commit",
|
|
1763
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1689
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1764
1690
|
});
|
|
1765
1691
|
}
|
|
1766
1692
|
if (report.ci) {
|
|
1767
1693
|
items.push({
|
|
1768
1694
|
label: "CI",
|
|
1769
|
-
value: report.ci.url ? /* @__PURE__ */ (0,
|
|
1695
|
+
value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1770
1696
|
ciDisplayName(report.ci.name),
|
|
1771
1697
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1772
1698
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1777,7 +1703,7 @@ function ReportMeta() {
|
|
|
1777
1703
|
const label = `#${report.ci.prNumber}`;
|
|
1778
1704
|
items.push({
|
|
1779
1705
|
label: "PR",
|
|
1780
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1706
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1781
1707
|
});
|
|
1782
1708
|
}
|
|
1783
1709
|
if (items.length === 0) return null;
|
|
@@ -1785,50 +1711,50 @@ function ReportMeta() {
|
|
|
1785
1711
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1786
1712
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1787
1713
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1788
|
-
/* @__PURE__ */ (0,
|
|
1789
|
-
/* @__PURE__ */ (0,
|
|
1790
|
-
/* @__PURE__ */ (0,
|
|
1714
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
|
|
1715
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("summary", { className: "flex cursor-pointer list-none select-none items-center gap-1.5 px-4 py-2 font-medium text-muted-foreground [&::-webkit-details-marker]:hidden", children: [
|
|
1716
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1791
1717
|
"Run details"
|
|
1792
1718
|
] }),
|
|
1793
|
-
/* @__PURE__ */ (0,
|
|
1794
|
-
/* @__PURE__ */ (0,
|
|
1795
|
-
/* @__PURE__ */ (0,
|
|
1719
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("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__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-baseline gap-1.5", children: [
|
|
1720
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("dt", { className: "font-medium", children: item.label }),
|
|
1721
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1796
1722
|
] }, item.label)) })
|
|
1797
1723
|
] })
|
|
1798
1724
|
);
|
|
1799
1725
|
}
|
|
1800
1726
|
|
|
1801
1727
|
// src/components/ReportSchemaError.tsx
|
|
1802
|
-
var
|
|
1728
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1803
1729
|
function ReportSchemaError({ error }) {
|
|
1804
|
-
return /* @__PURE__ */ (0,
|
|
1805
|
-
/* @__PURE__ */ (0,
|
|
1806
|
-
/* @__PURE__ */ (0,
|
|
1807
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0,
|
|
1730
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1731
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("strong", { children: "Report could not be displayed." }) }),
|
|
1732
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { children: error.message }),
|
|
1733
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("p", { children: [
|
|
1808
1734
|
"The report bundle is newer than this version of ",
|
|
1809
|
-
/* @__PURE__ */ (0,
|
|
1735
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("code", { children: "executable-stories-react" }),
|
|
1810
1736
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1811
1737
|
] }) : null,
|
|
1812
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0,
|
|
1813
|
-
/* @__PURE__ */ (0,
|
|
1738
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("details", { children: [
|
|
1739
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("summary", { children: [
|
|
1814
1740
|
error.issues.length,
|
|
1815
1741
|
" validation issue",
|
|
1816
1742
|
error.issues.length === 1 ? "" : "s"
|
|
1817
1743
|
] }),
|
|
1818
|
-
/* @__PURE__ */ (0,
|
|
1744
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1819
1745
|
] }) : null
|
|
1820
1746
|
] });
|
|
1821
1747
|
}
|
|
1822
1748
|
|
|
1823
1749
|
// src/components/ReportShell.tsx
|
|
1824
|
-
var
|
|
1750
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
1825
1751
|
function ReportErrorShell({
|
|
1826
1752
|
error,
|
|
1827
1753
|
className,
|
|
1828
1754
|
title,
|
|
1829
1755
|
dataTheme
|
|
1830
1756
|
}) {
|
|
1831
|
-
return /* @__PURE__ */ (0,
|
|
1757
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportSchemaError, { error }) });
|
|
1832
1758
|
}
|
|
1833
1759
|
|
|
1834
1760
|
// src/interactive/ReportInteractive.tsx
|
|
@@ -1837,12 +1763,12 @@ var import_lucide_react5 = require("lucide-react");
|
|
|
1837
1763
|
// src/components/ui/switch.tsx
|
|
1838
1764
|
var React4 = require("react");
|
|
1839
1765
|
var import_switch = require("@base-ui/react/switch");
|
|
1840
|
-
var
|
|
1766
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
1841
1767
|
function Switch({
|
|
1842
1768
|
className,
|
|
1843
1769
|
...props
|
|
1844
1770
|
}) {
|
|
1845
|
-
return /* @__PURE__ */ (0,
|
|
1771
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
1846
1772
|
import_switch.Switch.Root,
|
|
1847
1773
|
{
|
|
1848
1774
|
"data-slot": "switch",
|
|
@@ -1851,7 +1777,7 @@ function Switch({
|
|
|
1851
1777
|
className
|
|
1852
1778
|
),
|
|
1853
1779
|
...props,
|
|
1854
|
-
children: /* @__PURE__ */ (0,
|
|
1780
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
1855
1781
|
import_switch.Switch.Thumb,
|
|
1856
1782
|
{
|
|
1857
1783
|
"data-slot": "switch-thumb",
|
|
@@ -1867,7 +1793,7 @@ var React5 = __toESM(require("react"), 1);
|
|
|
1867
1793
|
var import_toggle_group = require("@base-ui/react/toggle-group");
|
|
1868
1794
|
var import_toggle = require("@base-ui/react/toggle");
|
|
1869
1795
|
var import_class_variance_authority3 = require("class-variance-authority");
|
|
1870
|
-
var
|
|
1796
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
1871
1797
|
var toggleItemVariants = (0, import_class_variance_authority3.cva)(
|
|
1872
1798
|
"inline-flex items-center justify-center gap-1.5 rounded-md font-medium whitespace-nowrap text-muted-foreground transition-[color,background-color,box-shadow] outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 data-[pressed]:bg-background data-[pressed]:text-foreground data-[pressed]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1873
1799
|
{
|
|
@@ -1889,13 +1815,13 @@ function ToggleGroup({
|
|
|
1889
1815
|
children,
|
|
1890
1816
|
...props
|
|
1891
1817
|
}) {
|
|
1892
|
-
return /* @__PURE__ */ (0,
|
|
1818
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
1893
1819
|
import_toggle_group.ToggleGroup,
|
|
1894
1820
|
{
|
|
1895
1821
|
"data-slot": "toggle-group",
|
|
1896
1822
|
className: cn("flex w-fit items-center gap-0.5 rounded-lg bg-muted p-0.5", className),
|
|
1897
1823
|
...props,
|
|
1898
|
-
children: /* @__PURE__ */ (0,
|
|
1824
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ToggleGroupContext.Provider, { value: { size }, children })
|
|
1899
1825
|
}
|
|
1900
1826
|
);
|
|
1901
1827
|
}
|
|
@@ -1906,7 +1832,7 @@ function ToggleGroupItem({
|
|
|
1906
1832
|
...props
|
|
1907
1833
|
}) {
|
|
1908
1834
|
const context = React5.useContext(ToggleGroupContext);
|
|
1909
|
-
return /* @__PURE__ */ (0,
|
|
1835
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
1910
1836
|
import_toggle.Toggle,
|
|
1911
1837
|
{
|
|
1912
1838
|
"data-slot": "toggle-group-item",
|
|
@@ -1923,9 +1849,9 @@ var import_lucide_react3 = require("lucide-react");
|
|
|
1923
1849
|
|
|
1924
1850
|
// src/components/ui/input.tsx
|
|
1925
1851
|
var React6 = require("react");
|
|
1926
|
-
var
|
|
1852
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
1927
1853
|
function Input({ className, type, ...props }) {
|
|
1928
|
-
return /* @__PURE__ */ (0,
|
|
1854
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
1929
1855
|
"input",
|
|
1930
1856
|
{
|
|
1931
1857
|
type,
|
|
@@ -1942,7 +1868,7 @@ function Input({ className, type, ...props }) {
|
|
|
1942
1868
|
}
|
|
1943
1869
|
|
|
1944
1870
|
// src/interactive/ReportSearch.tsx
|
|
1945
|
-
var
|
|
1871
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
1946
1872
|
var ReportSearch = (0, import_react8.forwardRef)(
|
|
1947
1873
|
function ReportSearch2(props, ref) {
|
|
1948
1874
|
const {
|
|
@@ -1964,17 +1890,17 @@ var ReportSearch = (0, import_react8.forwardRef)(
|
|
|
1964
1890
|
e.preventDefault();
|
|
1965
1891
|
}
|
|
1966
1892
|
}
|
|
1967
|
-
return /* @__PURE__ */ (0,
|
|
1968
|
-
/* @__PURE__ */ (0,
|
|
1969
|
-
/* @__PURE__ */ (0,
|
|
1970
|
-
/* @__PURE__ */ (0,
|
|
1893
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: cn("es-search flex flex-col gap-1", className), children: [
|
|
1894
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { htmlFor: inputId, className: "sr-only", children: "Search" }),
|
|
1895
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "relative w-full sm:w-72", children: [
|
|
1896
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1971
1897
|
import_lucide_react3.Search,
|
|
1972
1898
|
{
|
|
1973
1899
|
"aria-hidden": true,
|
|
1974
1900
|
className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
|
|
1975
1901
|
}
|
|
1976
1902
|
),
|
|
1977
|
-
/* @__PURE__ */ (0,
|
|
1903
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1978
1904
|
Input,
|
|
1979
1905
|
{
|
|
1980
1906
|
ref,
|
|
@@ -1991,7 +1917,7 @@ var ReportSearch = (0, import_react8.forwardRef)(
|
|
|
1991
1917
|
}
|
|
1992
1918
|
)
|
|
1993
1919
|
] }),
|
|
1994
|
-
showCounts ? /* @__PURE__ */ (0,
|
|
1920
|
+
showCounts ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
1995
1921
|
"span",
|
|
1996
1922
|
{
|
|
1997
1923
|
className: "text-xs tabular-nums text-muted-foreground",
|
|
@@ -2080,7 +2006,7 @@ function scrollToScenarioId(scenarioId, options = {}) {
|
|
|
2080
2006
|
}
|
|
2081
2007
|
|
|
2082
2008
|
// src/interactive/ReportFailureBanner.tsx
|
|
2083
|
-
var
|
|
2009
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2084
2010
|
function ReportFailureBanner({ failures }) {
|
|
2085
2011
|
const first = failures[0];
|
|
2086
2012
|
const jumpToFirst = (0, import_react9.useCallback)(() => {
|
|
@@ -2088,7 +2014,7 @@ function ReportFailureBanner({ failures }) {
|
|
|
2088
2014
|
scrollToScenarioId(first.scenarioId);
|
|
2089
2015
|
}, [first]);
|
|
2090
2016
|
if (failures.length === 0) return null;
|
|
2091
|
-
return /* @__PURE__ */ (0,
|
|
2017
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
2092
2018
|
"div",
|
|
2093
2019
|
{
|
|
2094
2020
|
className: "es-failure-banner",
|
|
@@ -2096,13 +2022,13 @@ function ReportFailureBanner({ failures }) {
|
|
|
2096
2022
|
"aria-live": "polite",
|
|
2097
2023
|
"aria-label": "Failure summary",
|
|
2098
2024
|
children: [
|
|
2099
|
-
/* @__PURE__ */ (0,
|
|
2100
|
-
/* @__PURE__ */ (0,
|
|
2025
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "es-failure-banner-text", children: [
|
|
2026
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("strong", { children: failures.length }),
|
|
2101
2027
|
" ",
|
|
2102
2028
|
"failure",
|
|
2103
2029
|
failures.length === 1 ? "" : "s"
|
|
2104
2030
|
] }),
|
|
2105
|
-
/* @__PURE__ */ (0,
|
|
2031
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
2106
2032
|
"button",
|
|
2107
2033
|
{
|
|
2108
2034
|
type: "button",
|
|
@@ -2119,7 +2045,7 @@ function ReportFailureBanner({ failures }) {
|
|
|
2119
2045
|
|
|
2120
2046
|
// src/interactive/ReportFreshness.tsx
|
|
2121
2047
|
var import_react10 = require("react");
|
|
2122
|
-
var
|
|
2048
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2123
2049
|
function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
2124
2050
|
const [now, setNow] = (0, import_react10.useState)(nowMs);
|
|
2125
2051
|
(0, import_react10.useEffect)(() => {
|
|
@@ -2127,7 +2053,7 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2127
2053
|
}, [nowMs]);
|
|
2128
2054
|
if (lastRunMs === void 0 || now === void 0) return null;
|
|
2129
2055
|
const age = formatRelativeAge(lastRunMs, now);
|
|
2130
|
-
const runLink = ciUrl ? /* @__PURE__ */ (0,
|
|
2056
|
+
const runLink = ciUrl ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2131
2057
|
"a",
|
|
2132
2058
|
{
|
|
2133
2059
|
href: ciUrl,
|
|
@@ -2138,9 +2064,9 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2138
2064
|
}
|
|
2139
2065
|
) : null;
|
|
2140
2066
|
if (isReportStale(lastRunMs, staleAfterDays, now)) {
|
|
2141
|
-
return /* @__PURE__ */ (0,
|
|
2142
|
-
/* @__PURE__ */ (0,
|
|
2143
|
-
/* @__PURE__ */ (0,
|
|
2067
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "es-stale-banner", role: "status", "aria-label": "Report freshness", children: [
|
|
2068
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { children: [
|
|
2069
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("strong", { children: [
|
|
2144
2070
|
"Last verified ",
|
|
2145
2071
|
age,
|
|
2146
2072
|
"."
|
|
@@ -2150,10 +2076,10 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2150
2076
|
runLink
|
|
2151
2077
|
] });
|
|
2152
2078
|
}
|
|
2153
|
-
return /* @__PURE__ */ (0,
|
|
2079
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("p", { className: "es-freshness", "aria-label": "Report freshness", children: [
|
|
2154
2080
|
"Verified ",
|
|
2155
2081
|
age,
|
|
2156
|
-
runLink ? /* @__PURE__ */ (0,
|
|
2082
|
+
runLink ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
|
|
2157
2083
|
" \xB7 ",
|
|
2158
2084
|
runLink
|
|
2159
2085
|
] }) : null
|
|
@@ -2161,15 +2087,15 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2161
2087
|
}
|
|
2162
2088
|
|
|
2163
2089
|
// src/interactive/ReportLastRunDelta.tsx
|
|
2164
|
-
var
|
|
2090
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2165
2091
|
var MAX_LINKS = 5;
|
|
2166
2092
|
function ScenarioLinks({ scenarios, tone }) {
|
|
2167
|
-
return /* @__PURE__ */ (0,
|
|
2168
|
-
scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ (0,
|
|
2093
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
|
|
2094
|
+
scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { children: [
|
|
2169
2095
|
i > 0 ? ", " : "",
|
|
2170
|
-
/* @__PURE__ */ (0,
|
|
2096
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
|
|
2171
2097
|
] }, s.id)),
|
|
2172
|
-
scenarios.length > MAX_LINKS ? /* @__PURE__ */ (0,
|
|
2098
|
+
scenarios.length > MAX_LINKS ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { children: [
|
|
2173
2099
|
" and ",
|
|
2174
2100
|
scenarios.length - MAX_LINKS,
|
|
2175
2101
|
" more"
|
|
@@ -2186,23 +2112,23 @@ function ReportLastRunDelta({
|
|
|
2186
2112
|
if (!delta) return null;
|
|
2187
2113
|
const { newlyFailing, newlyPassing, added } = delta;
|
|
2188
2114
|
if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) {
|
|
2189
|
-
return /* @__PURE__ */ (0,
|
|
2115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: "Since last run: no behavior changes." });
|
|
2190
2116
|
}
|
|
2191
|
-
return /* @__PURE__ */ (0,
|
|
2192
|
-
/* @__PURE__ */ (0,
|
|
2193
|
-
newlyFailing.length > 0 ? /* @__PURE__ */ (0,
|
|
2117
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: [
|
|
2118
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "font-medium text-foreground", children: "Since last run:" }),
|
|
2119
|
+
newlyFailing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "ml-2 text-fail", children: [
|
|
2194
2120
|
newlyFailing.length,
|
|
2195
2121
|
" newly failing (",
|
|
2196
|
-
/* @__PURE__ */ (0,
|
|
2122
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ScenarioLinks, { scenarios: newlyFailing, tone: "text-fail" }),
|
|
2197
2123
|
")"
|
|
2198
2124
|
] }) : null,
|
|
2199
|
-
newlyPassing.length > 0 ? /* @__PURE__ */ (0,
|
|
2125
|
+
newlyPassing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "ml-2 text-pass", children: [
|
|
2200
2126
|
newlyPassing.length,
|
|
2201
2127
|
" fixed (",
|
|
2202
|
-
/* @__PURE__ */ (0,
|
|
2128
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ScenarioLinks, { scenarios: newlyPassing, tone: "text-pass" }),
|
|
2203
2129
|
")"
|
|
2204
2130
|
] }) : null,
|
|
2205
|
-
added.length > 0 ? /* @__PURE__ */ (0,
|
|
2131
|
+
added.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "ml-2", children: [
|
|
2206
2132
|
added.length,
|
|
2207
2133
|
" new"
|
|
2208
2134
|
] }) : null
|
|
@@ -2266,7 +2192,7 @@ function Button({
|
|
|
2266
2192
|
}
|
|
2267
2193
|
|
|
2268
2194
|
// src/interactive/ReportShortcutsHelp.tsx
|
|
2269
|
-
var
|
|
2195
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2270
2196
|
var SHORTCUTS = [
|
|
2271
2197
|
{ keys: "/", description: "Focus search" },
|
|
2272
2198
|
{ keys: "f", description: "Jump to next failure" },
|
|
@@ -2278,9 +2204,9 @@ var SHORTCUTS = [
|
|
|
2278
2204
|
];
|
|
2279
2205
|
function Keys({ keys }) {
|
|
2280
2206
|
const parts = keys.split(" ");
|
|
2281
|
-
return /* @__PURE__ */ (0,
|
|
2282
|
-
i > 0 ? /* @__PURE__ */ (0,
|
|
2283
|
-
/* @__PURE__ */ (0,
|
|
2207
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "inline-flex items-center gap-1", children: parts.map((k, i) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "inline-flex items-center gap-1", children: [
|
|
2208
|
+
i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-xs text-muted-foreground", children: "+" }) : null,
|
|
2209
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.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 })
|
|
2284
2210
|
] }, k)) });
|
|
2285
2211
|
}
|
|
2286
2212
|
function ReportShortcutsHelp({ open, onClose }) {
|
|
@@ -2291,7 +2217,7 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2291
2217
|
if (open && !dialog.open) dialog.showModal();
|
|
2292
2218
|
else if (!open && dialog.open) dialog.close();
|
|
2293
2219
|
}, [open]);
|
|
2294
|
-
return /* @__PURE__ */ (0,
|
|
2220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
2295
2221
|
"dialog",
|
|
2296
2222
|
{
|
|
2297
2223
|
ref: dialogRef,
|
|
@@ -2299,12 +2225,12 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2299
2225
|
"aria-label": "Keyboard shortcuts",
|
|
2300
2226
|
onClose,
|
|
2301
2227
|
children: [
|
|
2302
|
-
/* @__PURE__ */ (0,
|
|
2303
|
-
/* @__PURE__ */ (0,
|
|
2304
|
-
/* @__PURE__ */ (0,
|
|
2305
|
-
/* @__PURE__ */ (0,
|
|
2228
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("h2", { className: "text-base font-semibold", children: "Keyboard shortcuts" }),
|
|
2229
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.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_runtime43.jsxs)("div", { className: "col-span-2 grid grid-cols-subgrid items-center", children: [
|
|
2230
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("dt", { className: "justify-self-start", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Keys, { keys: s.keys }) }),
|
|
2231
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("dd", { className: "text-sm text-muted-foreground", children: s.description })
|
|
2306
2232
|
] }, s.keys)) }),
|
|
2307
|
-
/* @__PURE__ */ (0,
|
|
2233
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("form", { method: "dialog", className: "mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Button, { type: "submit", variant: "outline", size: "sm", children: "Close" }) })
|
|
2308
2234
|
]
|
|
2309
2235
|
}
|
|
2310
2236
|
);
|
|
@@ -2507,7 +2433,7 @@ function failuresFirst(report) {
|
|
|
2507
2433
|
|
|
2508
2434
|
// src/interactive/ReportFilters.tsx
|
|
2509
2435
|
var import_react14 = require("react");
|
|
2510
|
-
var
|
|
2436
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2511
2437
|
var TAG_LIMIT = 12;
|
|
2512
2438
|
function ReportFilters({
|
|
2513
2439
|
statuses,
|
|
@@ -2521,10 +2447,10 @@ function ReportFilters({
|
|
|
2521
2447
|
if (statuses.length === 0 && tags.length === 0) return null;
|
|
2522
2448
|
const tagsCollapsed = tags.length > TAG_LIMIT && !showAllTags;
|
|
2523
2449
|
const visibleTags = tagsCollapsed ? tags.slice(0, TAG_LIMIT) : tags;
|
|
2524
|
-
return /* @__PURE__ */ (0,
|
|
2525
|
-
statuses.length > 0 ? /* @__PURE__ */ (0,
|
|
2450
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
2451
|
+
statuses.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { role: "group", "aria-label": "Filter by status", className: "flex flex-wrap gap-1", children: statuses.map((opt) => {
|
|
2526
2452
|
const active = status === opt.key;
|
|
2527
|
-
return /* @__PURE__ */ (0,
|
|
2453
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
2528
2454
|
"button",
|
|
2529
2455
|
{
|
|
2530
2456
|
type: "button",
|
|
@@ -2536,23 +2462,23 @@ function ReportFilters({
|
|
|
2536
2462
|
),
|
|
2537
2463
|
children: [
|
|
2538
2464
|
opt.label,
|
|
2539
|
-
/* @__PURE__ */ (0,
|
|
2465
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "ml-1 font-mono opacity-70", children: opt.count })
|
|
2540
2466
|
]
|
|
2541
2467
|
},
|
|
2542
2468
|
opt.key
|
|
2543
2469
|
);
|
|
2544
2470
|
}) }) : null,
|
|
2545
|
-
tags.length > 0 ? /* @__PURE__ */ (0,
|
|
2471
|
+
tags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("ul", { "aria-label": "Filter by tag", className: "flex flex-wrap items-center gap-1.5", children: [
|
|
2546
2472
|
visibleTags.map((tag) => {
|
|
2547
2473
|
const active = activeTags.includes(tag);
|
|
2548
|
-
return /* @__PURE__ */ (0,
|
|
2474
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2549
2475
|
"button",
|
|
2550
2476
|
{
|
|
2551
2477
|
type: "button",
|
|
2552
2478
|
"aria-pressed": active,
|
|
2553
2479
|
onClick: () => onToggleTag(tag),
|
|
2554
2480
|
className: "cursor-pointer",
|
|
2555
|
-
children: /* @__PURE__ */ (0,
|
|
2481
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2556
2482
|
Badge,
|
|
2557
2483
|
{
|
|
2558
2484
|
variant: "tag",
|
|
@@ -2565,7 +2491,7 @@ function ReportFilters({
|
|
|
2565
2491
|
}
|
|
2566
2492
|
) }, tag);
|
|
2567
2493
|
}),
|
|
2568
|
-
tags.length > TAG_LIMIT ? /* @__PURE__ */ (0,
|
|
2494
|
+
tags.length > TAG_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2569
2495
|
"button",
|
|
2570
2496
|
{
|
|
2571
2497
|
type: "button",
|
|
@@ -2581,7 +2507,7 @@ function ReportFilters({
|
|
|
2581
2507
|
|
|
2582
2508
|
// src/interactive/ReportToc.tsx
|
|
2583
2509
|
var import_react15 = require("react");
|
|
2584
|
-
var
|
|
2510
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2585
2511
|
var DOT = {
|
|
2586
2512
|
passed: "bg-pass",
|
|
2587
2513
|
failed: "bg-fail",
|
|
@@ -2610,11 +2536,11 @@ function TocContent({ onNavigate }) {
|
|
|
2610
2536
|
return () => observer.disconnect();
|
|
2611
2537
|
}, [scenarioIds]);
|
|
2612
2538
|
if (report.features.length === 0) return null;
|
|
2613
|
-
return /* @__PURE__ */ (0,
|
|
2614
|
-
/* @__PURE__ */ (0,
|
|
2615
|
-
/* @__PURE__ */ (0,
|
|
2539
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("ul", { className: "flex list-none flex-col gap-4 pl-0", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("li", { children: [
|
|
2540
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
|
|
2541
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("ul", { className: "flex list-none flex-col gap-0.5 pl-0", children: feature.scenarios.map((scenario) => {
|
|
2616
2542
|
const active = activeId === scenario.id;
|
|
2617
|
-
return /* @__PURE__ */ (0,
|
|
2543
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
2618
2544
|
"a",
|
|
2619
2545
|
{
|
|
2620
2546
|
href: `#${scenario.id}`,
|
|
@@ -2629,14 +2555,14 @@ function TocContent({ onNavigate }) {
|
|
|
2629
2555
|
active ? "border-primary font-medium text-foreground" : "border-border text-muted-foreground"
|
|
2630
2556
|
),
|
|
2631
2557
|
children: [
|
|
2632
|
-
/* @__PURE__ */ (0,
|
|
2558
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2633
2559
|
"span",
|
|
2634
2560
|
{
|
|
2635
2561
|
"aria-hidden": true,
|
|
2636
2562
|
className: cn("mt-1 size-1.5 shrink-0 rounded-full", DOT[scenario.status])
|
|
2637
2563
|
}
|
|
2638
2564
|
),
|
|
2639
|
-
/* @__PURE__ */ (0,
|
|
2565
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "break-words", children: scenario.title })
|
|
2640
2566
|
]
|
|
2641
2567
|
}
|
|
2642
2568
|
) }, scenario.id);
|
|
@@ -2646,14 +2572,14 @@ function TocContent({ onNavigate }) {
|
|
|
2646
2572
|
function ReportToc() {
|
|
2647
2573
|
const report = useReport();
|
|
2648
2574
|
if (report.features.length === 0) return null;
|
|
2649
|
-
return /* @__PURE__ */ (0,
|
|
2575
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
2650
2576
|
"nav",
|
|
2651
2577
|
{
|
|
2652
2578
|
"aria-label": "Table of contents",
|
|
2653
2579
|
className: "sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block",
|
|
2654
2580
|
children: [
|
|
2655
|
-
/* @__PURE__ */ (0,
|
|
2656
|
-
/* @__PURE__ */ (0,
|
|
2581
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
|
|
2582
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TocContent, {})
|
|
2657
2583
|
]
|
|
2658
2584
|
}
|
|
2659
2585
|
);
|
|
@@ -2663,31 +2589,31 @@ function ReportToc() {
|
|
|
2663
2589
|
var import_react16 = require("react");
|
|
2664
2590
|
var import_dialog = require("@base-ui/react/dialog");
|
|
2665
2591
|
var import_lucide_react4 = require("lucide-react");
|
|
2666
|
-
var
|
|
2592
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2667
2593
|
function ReportTocDrawer() {
|
|
2668
2594
|
const report = useReport();
|
|
2669
2595
|
const [open, setOpen] = (0, import_react16.useState)(false);
|
|
2670
2596
|
if (report.features.length === 0) return null;
|
|
2671
|
-
return /* @__PURE__ */ (0,
|
|
2672
|
-
/* @__PURE__ */ (0,
|
|
2673
|
-
/* @__PURE__ */ (0,
|
|
2597
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_dialog.Dialog.Root, { open, onOpenChange: setOpen, children: [
|
|
2598
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.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: [
|
|
2599
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react4.ListIcon, { "aria-hidden": true }),
|
|
2674
2600
|
" Contents"
|
|
2675
2601
|
] }),
|
|
2676
|
-
/* @__PURE__ */ (0,
|
|
2677
|
-
/* @__PURE__ */ (0,
|
|
2678
|
-
/* @__PURE__ */ (0,
|
|
2679
|
-
/* @__PURE__ */ (0,
|
|
2680
|
-
/* @__PURE__ */ (0,
|
|
2681
|
-
/* @__PURE__ */ (0,
|
|
2602
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_dialog.Dialog.Portal, { children: [
|
|
2603
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.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" }),
|
|
2604
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.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: [
|
|
2605
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2606
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_dialog.Dialog.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
|
|
2607
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2682
2608
|
import_dialog.Dialog.Close,
|
|
2683
2609
|
{
|
|
2684
2610
|
"aria-label": "Close contents",
|
|
2685
2611
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
2686
|
-
children: /* @__PURE__ */ (0,
|
|
2612
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react4.XIcon, { "aria-hidden": true })
|
|
2687
2613
|
}
|
|
2688
2614
|
)
|
|
2689
2615
|
] }),
|
|
2690
|
-
/* @__PURE__ */ (0,
|
|
2616
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(TocContent, { onNavigate: () => setOpen(false) })
|
|
2691
2617
|
] })
|
|
2692
2618
|
] })
|
|
2693
2619
|
] });
|
|
@@ -2770,14 +2696,14 @@ function useUrlState() {
|
|
|
2770
2696
|
}
|
|
2771
2697
|
|
|
2772
2698
|
// src/interactive/ReportInteractive.tsx
|
|
2773
|
-
var
|
|
2699
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2774
2700
|
function ReportInteractive(props) {
|
|
2775
2701
|
const { report, className, title, dataTheme } = props;
|
|
2776
2702
|
const result = unwrapReport(report);
|
|
2777
2703
|
if (!result.ok) {
|
|
2778
|
-
return /* @__PURE__ */ (0,
|
|
2704
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
2779
2705
|
}
|
|
2780
|
-
return /* @__PURE__ */ (0,
|
|
2706
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ReportInteractiveView, { ...props, report: result.data });
|
|
2781
2707
|
}
|
|
2782
2708
|
var THEME_OPTIONS = [
|
|
2783
2709
|
{ value: "light", label: "Light", Icon: import_lucide_react5.Sun },
|
|
@@ -2785,7 +2711,7 @@ var THEME_OPTIONS = [
|
|
|
2785
2711
|
{ value: "dark", label: "Dark", Icon: import_lucide_react5.Moon }
|
|
2786
2712
|
];
|
|
2787
2713
|
function ThemeSegment({ pref, onPref }) {
|
|
2788
|
-
return /* @__PURE__ */ (0,
|
|
2714
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2789
2715
|
ToggleGroup,
|
|
2790
2716
|
{
|
|
2791
2717
|
size: "sm",
|
|
@@ -2795,7 +2721,7 @@ function ThemeSegment({ pref, onPref }) {
|
|
|
2795
2721
|
if (next) onPref(next);
|
|
2796
2722
|
},
|
|
2797
2723
|
"aria-label": "Color theme",
|
|
2798
|
-
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ (0,
|
|
2724
|
+
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ToggleGroupItem, { value, "aria-label": label, title: label, className: "px-2", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Icon, {}) }, value))
|
|
2799
2725
|
}
|
|
2800
2726
|
);
|
|
2801
2727
|
}
|
|
@@ -2872,7 +2798,7 @@ function ReportInteractiveView({
|
|
|
2872
2798
|
const scenarioActions = (0, import_react19.useMemo)(
|
|
2873
2799
|
() => ({
|
|
2874
2800
|
copyLink: (s) => copy(scenarioPermalink(s), "Link copied"),
|
|
2875
|
-
copyMarkdown: (s) => copy(
|
|
2801
|
+
copyMarkdown: (s) => copy(scenarioToMarkdown(s), "Markdown copied"),
|
|
2876
2802
|
copyPrompt: (s) => copy(scenarioToPrompt(s), "Prompt copied")
|
|
2877
2803
|
}),
|
|
2878
2804
|
[copy]
|
|
@@ -2926,13 +2852,13 @@ function ReportInteractiveView({
|
|
|
2926
2852
|
const totalScenarios = report.summary.total;
|
|
2927
2853
|
const matchedScenarios = filtered.summary.total;
|
|
2928
2854
|
const showToc = !hideToc && totalScenarios > 3;
|
|
2929
|
-
return /* @__PURE__ */ (0,
|
|
2855
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(CollapseProvider, { value: collapse.api, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ScenarioActionsProvider, { value: scenarioActions, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ScenarioHistoryProvider, { value: scenarioHistory ?? null, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2930
2856
|
ReportRoot,
|
|
2931
2857
|
{
|
|
2932
2858
|
report: filtered,
|
|
2933
2859
|
customRenderers,
|
|
2934
2860
|
renderers,
|
|
2935
|
-
children: /* @__PURE__ */ (0,
|
|
2861
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
2936
2862
|
"main",
|
|
2937
2863
|
{
|
|
2938
2864
|
className: cn("es-report", "es-report-interactive", className),
|
|
@@ -2941,8 +2867,8 @@ function ReportInteractiveView({
|
|
|
2941
2867
|
"data-theme": dataTheme,
|
|
2942
2868
|
"data-detail-level": detail,
|
|
2943
2869
|
children: [
|
|
2944
|
-
/* @__PURE__ */ (0,
|
|
2945
|
-
/* @__PURE__ */ (0,
|
|
2870
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("header", { className: "es-report-header", children: [
|
|
2871
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
2946
2872
|
"div",
|
|
2947
2873
|
{
|
|
2948
2874
|
"data-es-navbar": true,
|
|
@@ -2951,9 +2877,9 @@ function ReportInteractiveView({
|
|
|
2951
2877
|
hideHeader ? "justify-end" : "justify-between"
|
|
2952
2878
|
),
|
|
2953
2879
|
children: [
|
|
2954
|
-
hideHeader ? null : /* @__PURE__ */ (0,
|
|
2955
|
-
/* @__PURE__ */ (0,
|
|
2956
|
-
/* @__PURE__ */ (0,
|
|
2880
|
+
hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h1", { className: "min-w-0", children: title ?? "Story Report" }),
|
|
2881
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2882
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2957
2883
|
ReportSearch,
|
|
2958
2884
|
{
|
|
2959
2885
|
ref: searchRef,
|
|
@@ -2963,16 +2889,16 @@ function ReportInteractiveView({
|
|
|
2963
2889
|
totalCount: totalScenarios
|
|
2964
2890
|
}
|
|
2965
2891
|
),
|
|
2966
|
-
/* @__PURE__ */ (0,
|
|
2892
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ThemeSegment, { pref: themePref, onPref: setThemePref })
|
|
2967
2893
|
] })
|
|
2968
2894
|
]
|
|
2969
2895
|
}
|
|
2970
2896
|
),
|
|
2971
|
-
hideHeader ? null : /* @__PURE__ */ (0,
|
|
2972
|
-
/* @__PURE__ */ (0,
|
|
2973
|
-
/* @__PURE__ */ (0,
|
|
2897
|
+
hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
|
|
2898
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ReportSummary, {}),
|
|
2899
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ReportMeta, {})
|
|
2974
2900
|
] }),
|
|
2975
|
-
/* @__PURE__ */ (0,
|
|
2901
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2976
2902
|
ReportFreshness,
|
|
2977
2903
|
{
|
|
2978
2904
|
lastRunMs: reportLastRunMs(report),
|
|
@@ -2980,8 +2906,8 @@ function ReportInteractiveView({
|
|
|
2980
2906
|
staleAfterDays
|
|
2981
2907
|
}
|
|
2982
2908
|
),
|
|
2983
|
-
/* @__PURE__ */ (0,
|
|
2984
|
-
/* @__PURE__ */ (0,
|
|
2909
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ReportLastRunDelta, { history: scenarioHistory, report }),
|
|
2910
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2985
2911
|
ReportFilters,
|
|
2986
2912
|
{
|
|
2987
2913
|
statuses: statusOptions,
|
|
@@ -2992,14 +2918,14 @@ function ReportInteractiveView({
|
|
|
2992
2918
|
onToggleTag: toggleTag
|
|
2993
2919
|
}
|
|
2994
2920
|
),
|
|
2995
|
-
/* @__PURE__ */ (0,
|
|
2996
|
-
showToc ? /* @__PURE__ */ (0,
|
|
2997
|
-
/* @__PURE__ */ (0,
|
|
2998
|
-
/* @__PURE__ */ (0,
|
|
2999
|
-
/* @__PURE__ */ (0,
|
|
2921
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border/60 pt-3", children: [
|
|
2922
|
+
showToc ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ReportTocDrawer, {}) : null,
|
|
2923
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2924
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Switch, { id: expandId, checked: expandedAll, onCheckedChange: setExpanded }),
|
|
2925
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("label", { htmlFor: expandId, className: "cursor-pointer text-sm text-muted-foreground select-none", children: "Expand all" })
|
|
3000
2926
|
] }),
|
|
3001
|
-
/* @__PURE__ */ (0,
|
|
3002
|
-
/* @__PURE__ */ (0,
|
|
2927
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2928
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
3003
2929
|
Switch,
|
|
3004
2930
|
{
|
|
3005
2931
|
id: docsId,
|
|
@@ -3007,16 +2933,16 @@ function ReportInteractiveView({
|
|
|
3007
2933
|
onCheckedChange: (checked) => setDetail(checked ? "full" : "minimal")
|
|
3008
2934
|
}
|
|
3009
2935
|
),
|
|
3010
|
-
/* @__PURE__ */ (0,
|
|
2936
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("label", { htmlFor: docsId, className: "cursor-pointer text-sm text-muted-foreground select-none", children: "Show documentation" })
|
|
3011
2937
|
] })
|
|
3012
2938
|
] })
|
|
3013
2939
|
] }),
|
|
3014
|
-
/* @__PURE__ */ (0,
|
|
3015
|
-
hasContent ? showToc ? /* @__PURE__ */ (0,
|
|
3016
|
-
/* @__PURE__ */ (0,
|
|
3017
|
-
/* @__PURE__ */ (0,
|
|
3018
|
-
] }) : /* @__PURE__ */ (0,
|
|
3019
|
-
/* @__PURE__ */ (0,
|
|
2940
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ReportFailureBanner, { failures }),
|
|
2941
|
+
hasContent ? showToc ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex gap-6", children: [
|
|
2942
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ReportToc, {}),
|
|
2943
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex min-w-0 flex-1 flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ReportFeatureList, {}) })
|
|
2944
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ReportFeatureList, {}) }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ReportEmpty, { message: query ? "No scenarios match the search." : void 0 }),
|
|
2945
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
3020
2946
|
"button",
|
|
3021
2947
|
{
|
|
3022
2948
|
type: "button",
|
|
@@ -3027,8 +2953,8 @@ function ReportInteractiveView({
|
|
|
3027
2953
|
children: "?"
|
|
3028
2954
|
}
|
|
3029
2955
|
),
|
|
3030
|
-
/* @__PURE__ */ (0,
|
|
3031
|
-
toast ? /* @__PURE__ */ (0,
|
|
2956
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ReportShortcutsHelp, { open: helpOpen, onClose: () => setHelpOpen(false) }),
|
|
2957
|
+
toast ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
3032
2958
|
"div",
|
|
3033
2959
|
{
|
|
3034
2960
|
role: "status",
|
|
@@ -3052,7 +2978,7 @@ var import_react21 = require("react");
|
|
|
3052
2978
|
|
|
3053
2979
|
// src/components/doc/MermaidView.tsx
|
|
3054
2980
|
var import_react20 = require("react");
|
|
3055
|
-
var
|
|
2981
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
3056
2982
|
function prefersDark(el) {
|
|
3057
2983
|
const themed = el?.closest("[data-theme]");
|
|
3058
2984
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -3106,9 +3032,9 @@ function MermaidView({ entry, load }) {
|
|
|
3106
3032
|
};
|
|
3107
3033
|
}, [entry.code, load]);
|
|
3108
3034
|
if (svg) {
|
|
3109
|
-
return /* @__PURE__ */ (0,
|
|
3110
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
3111
|
-
/* @__PURE__ */ (0,
|
|
3035
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("figure", { ref, className: "my-3", children: [
|
|
3036
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
3037
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3112
3038
|
"div",
|
|
3113
3039
|
{
|
|
3114
3040
|
role: "img",
|
|
@@ -3119,8 +3045,8 @@ function MermaidView({ entry, load }) {
|
|
|
3119
3045
|
)
|
|
3120
3046
|
] });
|
|
3121
3047
|
}
|
|
3122
|
-
return /* @__PURE__ */ (0,
|
|
3123
|
-
error ? /* @__PURE__ */ (0,
|
|
3048
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
|
|
3049
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
3124
3050
|
"p",
|
|
3125
3051
|
{
|
|
3126
3052
|
role: "alert",
|
|
@@ -3132,12 +3058,12 @@ function MermaidView({ entry, load }) {
|
|
|
3132
3058
|
]
|
|
3133
3059
|
}
|
|
3134
3060
|
) : null,
|
|
3135
|
-
/* @__PURE__ */ (0,
|
|
3061
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(MermaidSource, { entry, ref })
|
|
3136
3062
|
] });
|
|
3137
3063
|
}
|
|
3138
3064
|
|
|
3139
3065
|
// src/interactive/island-renderers.tsx
|
|
3140
|
-
var
|
|
3066
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
3141
3067
|
var HLJS_ESM = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
|
|
3142
3068
|
var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
|
|
3143
3069
|
function cachedCdnModule(url) {
|
|
@@ -3171,13 +3097,13 @@ function CdnHighlightedCode({ entry }) {
|
|
|
3171
3097
|
cancelled = true;
|
|
3172
3098
|
};
|
|
3173
3099
|
}, [entry.content, entry.lang]);
|
|
3174
|
-
return /* @__PURE__ */ (0,
|
|
3100
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3175
3101
|
"code",
|
|
3176
3102
|
{
|
|
3177
3103
|
className: cn("hljs font-mono text-xs", entry.lang && `language-${entry.lang}`),
|
|
3178
3104
|
dangerouslySetInnerHTML: { __html: html }
|
|
3179
3105
|
}
|
|
3180
|
-
) : /* @__PURE__ */ (0,
|
|
3106
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
3181
3107
|
}
|
|
3182
3108
|
function buildIslandRenderers(opts) {
|
|
3183
3109
|
const renderers = {};
|
|
@@ -3191,7 +3117,7 @@ function buildIslandRenderers(opts) {
|
|
|
3191
3117
|
}
|
|
3192
3118
|
|
|
3193
3119
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
3194
|
-
var
|
|
3120
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
3195
3121
|
function ReportInteractiveIsland({
|
|
3196
3122
|
report,
|
|
3197
3123
|
title,
|
|
@@ -3205,7 +3131,7 @@ function ReportInteractiveIsland({
|
|
|
3205
3131
|
() => buildIslandRenderers({ syntaxHighlighting, mermaid }),
|
|
3206
3132
|
[syntaxHighlighting, mermaid]
|
|
3207
3133
|
);
|
|
3208
|
-
return /* @__PURE__ */ (0,
|
|
3134
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3209
3135
|
ReportInteractive,
|
|
3210
3136
|
{
|
|
3211
3137
|
report,
|