executable-stories-react 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +558 -335
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -1
- package/dist/index.d.ts +45 -1
- package/dist/index.js +551 -335
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +772 -476
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +25 -3
- package/dist/interactive.d.ts +25 -3
- package/dist/interactive.js +762 -466
- package/dist/interactive.js.map +1 -1
- package/dist/report-island.global.js +28 -28
- package/dist/ssr.cjs +477 -299
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.js +477 -299
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -31,6 +31,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
// src/index.ts
|
|
32
32
|
var src_exports = {};
|
|
33
33
|
__export(src_exports, {
|
|
34
|
+
DATA_MODEL_TYPE: () => DATA_MODEL_TYPE,
|
|
35
|
+
DataModelBlock: () => DataModelBlock,
|
|
34
36
|
DocCode: () => DocCode,
|
|
35
37
|
DocCustom: () => DocCustom,
|
|
36
38
|
DocEntry: () => DocEntry,
|
|
@@ -44,6 +46,8 @@ __export(src_exports, {
|
|
|
44
46
|
DocTable: () => DocTable,
|
|
45
47
|
DocTag: () => DocTag,
|
|
46
48
|
DocVideo: () => DocVideo,
|
|
49
|
+
FILE_TREE_TYPE: () => FILE_TREE_TYPE,
|
|
50
|
+
FileTreeBlock: () => FileTreeBlock,
|
|
47
51
|
MermaidDiagram: () => MermaidDiagram,
|
|
48
52
|
MermaidSource: () => MermaidSource,
|
|
49
53
|
Report: () => Report,
|
|
@@ -73,7 +77,10 @@ __export(src_exports, {
|
|
|
73
77
|
err: () => err,
|
|
74
78
|
formatRelativeAge: () => formatRelativeAge,
|
|
75
79
|
isReportStale: () => isReportStale,
|
|
80
|
+
narrativeBlockRenderers: () => narrativeBlockRenderers,
|
|
76
81
|
ok: () => ok,
|
|
82
|
+
parseDataModel: () => parseDataModel,
|
|
83
|
+
parseFileTree: () => parseFileTree,
|
|
77
84
|
parseStoryReport: () => parseStoryReport,
|
|
78
85
|
prUrl: () => prUrl,
|
|
79
86
|
reportLastRunMs: () => reportLastRunMs,
|
|
@@ -101,63 +108,6 @@ var import_react2 = require("react");
|
|
|
101
108
|
var import_react = require("react");
|
|
102
109
|
var ReportContext = (0, import_react.createContext)(null);
|
|
103
110
|
|
|
104
|
-
// src/context/ReportRoot.tsx
|
|
105
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
106
|
-
var EMPTY_CUSTOM = {};
|
|
107
|
-
var EMPTY_RENDERERS = {};
|
|
108
|
-
function ReportRoot({
|
|
109
|
-
report,
|
|
110
|
-
customRenderers,
|
|
111
|
-
renderers,
|
|
112
|
-
children
|
|
113
|
-
}) {
|
|
114
|
-
const value = (0, import_react2.useMemo)(
|
|
115
|
-
() => ({
|
|
116
|
-
report,
|
|
117
|
-
customRenderers: customRenderers ?? EMPTY_CUSTOM,
|
|
118
|
-
renderers: renderers ?? EMPTY_RENDERERS
|
|
119
|
-
}),
|
|
120
|
-
[report, customRenderers, renderers]
|
|
121
|
-
);
|
|
122
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReportContext.Provider, { value, children });
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// src/hooks/useReport.ts
|
|
126
|
-
var import_react3 = require("react");
|
|
127
|
-
function useReport() {
|
|
128
|
-
const ctx = (0, import_react3.useContext)(ReportContext);
|
|
129
|
-
if (!ctx) {
|
|
130
|
-
throw new Error(
|
|
131
|
-
"useReport must be used inside <ReportRoot> or <Report>. Wrap your tree with one of those."
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
return ctx.report;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// ../executable-stories-core/dist/utils/duration.js
|
|
138
|
-
function formatDuration(ms) {
|
|
139
|
-
if (ms < 1e3) {
|
|
140
|
-
return `${Math.round(ms)} ms`;
|
|
141
|
-
}
|
|
142
|
-
if (ms < 6e4) {
|
|
143
|
-
return `${(ms / 1e3).toFixed(2)} s`;
|
|
144
|
-
}
|
|
145
|
-
const minutes = Math.floor(ms / 6e4);
|
|
146
|
-
const seconds = Math.floor(ms % 6e4 / 1e3);
|
|
147
|
-
if (minutes < 60) {
|
|
148
|
-
return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
149
|
-
}
|
|
150
|
-
const hours = Math.floor(minutes / 60);
|
|
151
|
-
const remainingMinutes = minutes % 60;
|
|
152
|
-
return `${hours}h ${remainingMinutes}m`;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// src/components/doc/DocNote.tsx
|
|
156
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
157
|
-
function DocNote({ entry }) {
|
|
158
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
|
|
159
|
-
}
|
|
160
|
-
|
|
161
111
|
// src/components/ui/badge.tsx
|
|
162
112
|
var React = require("react");
|
|
163
113
|
var import_class_variance_authority = require("class-variance-authority");
|
|
@@ -216,14 +166,249 @@ function Badge({
|
|
|
216
166
|
});
|
|
217
167
|
}
|
|
218
168
|
|
|
219
|
-
// src/components/doc/
|
|
169
|
+
// src/components/doc/NarrativeBlocks.tsx
|
|
170
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
171
|
+
var FILE_TREE_TYPE = "file-tree";
|
|
172
|
+
var DATA_MODEL_TYPE = "data-model";
|
|
173
|
+
function isChangeKind(value) {
|
|
174
|
+
return value === "added" || value === "modified" || value === "removed" || value === "renamed";
|
|
175
|
+
}
|
|
176
|
+
function isRecord(value) {
|
|
177
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
178
|
+
}
|
|
179
|
+
function str(value) {
|
|
180
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
181
|
+
}
|
|
182
|
+
function AuthoredMarker({ authored }) {
|
|
183
|
+
if (authored !== "agent") return null;
|
|
184
|
+
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" });
|
|
185
|
+
}
|
|
186
|
+
function BlockFrame({
|
|
187
|
+
title,
|
|
188
|
+
authored,
|
|
189
|
+
children
|
|
190
|
+
}) {
|
|
191
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("figure", { className: "my-3", children: [
|
|
192
|
+
title || authored === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("figcaption", { className: "mb-1.5 flex flex-wrap items-center gap-2", children: [
|
|
193
|
+
title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs font-medium text-muted-foreground", children: title }) : null,
|
|
194
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AuthoredMarker, { authored })
|
|
195
|
+
] }) : null,
|
|
196
|
+
children
|
|
197
|
+
] });
|
|
198
|
+
}
|
|
199
|
+
function ChangeBadge({ change }) {
|
|
200
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "tag", className: "text-[10px]", children: change });
|
|
201
|
+
}
|
|
202
|
+
function parseFileTree(data) {
|
|
203
|
+
if (!isRecord(data) || !Array.isArray(data.files)) return void 0;
|
|
204
|
+
const files = [];
|
|
205
|
+
for (const raw of data.files) {
|
|
206
|
+
if (typeof raw === "string") {
|
|
207
|
+
if (raw) files.push({ path: raw });
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (!isRecord(raw)) continue;
|
|
211
|
+
const path = str(raw.path);
|
|
212
|
+
if (!path) continue;
|
|
213
|
+
files.push({
|
|
214
|
+
path,
|
|
215
|
+
change: isChangeKind(raw.change) ? raw.change : void 0,
|
|
216
|
+
note: str(raw.note)
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
if (files.length === 0) return void 0;
|
|
220
|
+
return { title: str(data.title), authored: str(data.authored), files };
|
|
221
|
+
}
|
|
222
|
+
function buildTree(files) {
|
|
223
|
+
const root = { name: "", children: /* @__PURE__ */ new Map() };
|
|
224
|
+
for (const file of files) {
|
|
225
|
+
const segments = file.path.split("/").filter(Boolean);
|
|
226
|
+
let node = root;
|
|
227
|
+
segments.forEach((segment, index) => {
|
|
228
|
+
let child = node.children.get(segment);
|
|
229
|
+
if (!child) {
|
|
230
|
+
child = { name: segment, children: /* @__PURE__ */ new Map() };
|
|
231
|
+
node.children.set(segment, child);
|
|
232
|
+
}
|
|
233
|
+
if (index === segments.length - 1) child.file = file;
|
|
234
|
+
node = child;
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
return root;
|
|
238
|
+
}
|
|
239
|
+
function sortedChildren(node) {
|
|
240
|
+
return [...node.children.values()].sort((a, b) => {
|
|
241
|
+
const aDir = a.children.size > 0;
|
|
242
|
+
const bDir = b.children.size > 0;
|
|
243
|
+
if (aDir !== bDir) return aDir ? -1 : 1;
|
|
244
|
+
return a.name.localeCompare(b.name);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
function TreeBranch({ node, depth }) {
|
|
248
|
+
const children = sortedChildren(node);
|
|
249
|
+
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) => {
|
|
250
|
+
const isDir = child.children.size > 0;
|
|
251
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
|
|
252
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-baseline gap-2", children: [
|
|
253
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
254
|
+
"span",
|
|
255
|
+
{
|
|
256
|
+
className: cn(
|
|
257
|
+
"font-mono text-xs",
|
|
258
|
+
isDir ? "text-muted-foreground" : "text-foreground"
|
|
259
|
+
),
|
|
260
|
+
children: isDir ? `${child.name}/` : child.name
|
|
261
|
+
}
|
|
262
|
+
),
|
|
263
|
+
child.file?.change ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeBadge, { change: child.file.change }) : null,
|
|
264
|
+
child.file?.note ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs text-muted-foreground", children: child.file.note }) : null
|
|
265
|
+
] }),
|
|
266
|
+
isDir ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TreeBranch, { node: child, depth: depth + 1 }) : null
|
|
267
|
+
] }, child.name);
|
|
268
|
+
}) });
|
|
269
|
+
}
|
|
270
|
+
function FileTreeBlock({ entry }) {
|
|
271
|
+
const data = parseFileTree(entry.data);
|
|
272
|
+
if (!data) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UnreadableBlock, { entry });
|
|
273
|
+
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 }) }) });
|
|
274
|
+
}
|
|
275
|
+
function parseDataModel(data) {
|
|
276
|
+
if (!isRecord(data) || !Array.isArray(data.fields)) return void 0;
|
|
277
|
+
const fields = [];
|
|
278
|
+
for (const raw of data.fields) {
|
|
279
|
+
if (!isRecord(raw)) continue;
|
|
280
|
+
const name = str(raw.name);
|
|
281
|
+
if (!name) continue;
|
|
282
|
+
fields.push({
|
|
283
|
+
name,
|
|
284
|
+
type: str(raw.type),
|
|
285
|
+
note: str(raw.note),
|
|
286
|
+
change: isChangeKind(raw.change) ? raw.change : void 0
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
if (fields.length === 0) return void 0;
|
|
290
|
+
return {
|
|
291
|
+
title: str(data.title),
|
|
292
|
+
authored: str(data.authored),
|
|
293
|
+
name: str(data.name),
|
|
294
|
+
fields
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function DataModelBlock({ entry }) {
|
|
298
|
+
const data = parseDataModel(entry.data);
|
|
299
|
+
if (!data) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UnreadableBlock, { entry });
|
|
300
|
+
const hasNotes = data.fields.some((f) => f.note);
|
|
301
|
+
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: [
|
|
302
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: "bg-muted/50", children: [
|
|
303
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Field" }),
|
|
304
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Type" }),
|
|
305
|
+
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
|
|
306
|
+
] }) }),
|
|
307
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: data.fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
|
|
308
|
+
/* @__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: [
|
|
309
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-mono text-xs text-foreground", children: field.name }),
|
|
310
|
+
field.change ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeBadge, { change: field.change }) : null
|
|
311
|
+
] }) }),
|
|
312
|
+
/* @__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 ?? "" }),
|
|
313
|
+
hasNotes ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: field.note ?? "" }) : null
|
|
314
|
+
] }, field.name)) })
|
|
315
|
+
] }) }) });
|
|
316
|
+
}
|
|
317
|
+
function UnreadableBlock({ entry }) {
|
|
318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
|
|
319
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: [
|
|
320
|
+
entry.type,
|
|
321
|
+
" (unrecognised shape)"
|
|
322
|
+
] }),
|
|
323
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
324
|
+
"pre",
|
|
325
|
+
{
|
|
326
|
+
tabIndex: 0,
|
|
327
|
+
className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground",
|
|
328
|
+
children: safeStringify(entry.data)
|
|
329
|
+
}
|
|
330
|
+
)
|
|
331
|
+
] });
|
|
332
|
+
}
|
|
333
|
+
function safeStringify(value) {
|
|
334
|
+
try {
|
|
335
|
+
return JSON.stringify(value, null, 2);
|
|
336
|
+
} catch {
|
|
337
|
+
return String(value);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
var narrativeBlockRenderers = {
|
|
341
|
+
[FILE_TREE_TYPE]: (entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileTreeBlock, { entry }),
|
|
342
|
+
[DATA_MODEL_TYPE]: (entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DataModelBlock, { entry })
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
// src/context/ReportRoot.tsx
|
|
346
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
347
|
+
var EMPTY_RENDERERS = {};
|
|
348
|
+
function ReportRoot({
|
|
349
|
+
report,
|
|
350
|
+
customRenderers,
|
|
351
|
+
renderers,
|
|
352
|
+
children
|
|
353
|
+
}) {
|
|
354
|
+
const value = (0, import_react2.useMemo)(
|
|
355
|
+
() => ({
|
|
356
|
+
report,
|
|
357
|
+
// Narrative blocks render everywhere the report does (static SSR, the
|
|
358
|
+
// island, Astro) without every host wiring them up. A host renderer for
|
|
359
|
+
// the same type still wins.
|
|
360
|
+
customRenderers: { ...narrativeBlockRenderers, ...customRenderers },
|
|
361
|
+
renderers: renderers ?? EMPTY_RENDERERS
|
|
362
|
+
}),
|
|
363
|
+
[report, customRenderers, renderers]
|
|
364
|
+
);
|
|
365
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReportContext.Provider, { value, children });
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// src/hooks/useReport.ts
|
|
369
|
+
var import_react3 = require("react");
|
|
370
|
+
function useReport() {
|
|
371
|
+
const ctx = (0, import_react3.useContext)(ReportContext);
|
|
372
|
+
if (!ctx) {
|
|
373
|
+
throw new Error(
|
|
374
|
+
"useReport must be used inside <ReportRoot> or <Report>. Wrap your tree with one of those."
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
return ctx.report;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// ../executable-stories-core/dist/utils/duration.js
|
|
381
|
+
function formatDuration(ms) {
|
|
382
|
+
if (ms < 1e3) {
|
|
383
|
+
return `${Math.round(ms)} ms`;
|
|
384
|
+
}
|
|
385
|
+
if (ms < 6e4) {
|
|
386
|
+
return `${(ms / 1e3).toFixed(2)} s`;
|
|
387
|
+
}
|
|
388
|
+
const minutes = Math.floor(ms / 6e4);
|
|
389
|
+
const seconds = Math.floor(ms % 6e4 / 1e3);
|
|
390
|
+
if (minutes < 60) {
|
|
391
|
+
return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
392
|
+
}
|
|
393
|
+
const hours = Math.floor(minutes / 60);
|
|
394
|
+
const remainingMinutes = minutes % 60;
|
|
395
|
+
return `${hours}h ${remainingMinutes}m`;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// src/components/doc/DocNote.tsx
|
|
220
399
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
400
|
+
function DocNote({ entry }) {
|
|
401
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// src/components/doc/DocTag.tsx
|
|
405
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
221
406
|
function DocTag({ entry }) {
|
|
222
|
-
return /* @__PURE__ */ (0,
|
|
407
|
+
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)) });
|
|
223
408
|
}
|
|
224
409
|
|
|
225
410
|
// src/components/doc/DocKv.tsx
|
|
226
|
-
var
|
|
411
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
227
412
|
function formatValue(value) {
|
|
228
413
|
if (value === null) return "null";
|
|
229
414
|
if (typeof value === "string") return value;
|
|
@@ -235,19 +420,19 @@ function formatValue(value) {
|
|
|
235
420
|
}
|
|
236
421
|
}
|
|
237
422
|
function DocKv({ entry }) {
|
|
238
|
-
return /* @__PURE__ */ (0,
|
|
239
|
-
/* @__PURE__ */ (0,
|
|
240
|
-
/* @__PURE__ */ (0,
|
|
423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
|
|
424
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { className: "font-semibold text-muted-foreground", children: entry.label }),
|
|
425
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { className: "font-mono text-foreground", children: formatValue(entry.value) })
|
|
241
426
|
] });
|
|
242
427
|
}
|
|
243
428
|
|
|
244
429
|
// src/hooks/useRenderers.ts
|
|
245
430
|
var import_react4 = require("react");
|
|
246
|
-
var
|
|
431
|
+
var EMPTY_CUSTOM = {};
|
|
247
432
|
var EMPTY_RENDERERS2 = {};
|
|
248
433
|
function useCustomRenderers() {
|
|
249
434
|
const ctx = (0, import_react4.useContext)(ReportContext);
|
|
250
|
-
return ctx?.customRenderers ??
|
|
435
|
+
return ctx?.customRenderers ?? EMPTY_CUSTOM;
|
|
251
436
|
}
|
|
252
437
|
function useBuiltinRenderers() {
|
|
253
438
|
const ctx = (0, import_react4.useContext)(ReportContext);
|
|
@@ -255,37 +440,37 @@ function useBuiltinRenderers() {
|
|
|
255
440
|
}
|
|
256
441
|
|
|
257
442
|
// src/components/doc/DocCode.tsx
|
|
258
|
-
var
|
|
443
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
259
444
|
function CodeFigure({ label, children }) {
|
|
260
|
-
return /* @__PURE__ */ (0,
|
|
261
|
-
label ? /* @__PURE__ */ (0,
|
|
262
|
-
/* @__PURE__ */ (0,
|
|
445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("figure", { className: "my-3", children: [
|
|
446
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: label }) : null,
|
|
447
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3", children })
|
|
263
448
|
] });
|
|
264
449
|
}
|
|
265
450
|
function DocCode({ entry }) {
|
|
266
451
|
const renderers = useBuiltinRenderers();
|
|
267
452
|
if (renderers.code) {
|
|
268
|
-
return /* @__PURE__ */ (0,
|
|
453
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: renderers.code(entry) });
|
|
269
454
|
}
|
|
270
|
-
return /* @__PURE__ */ (0,
|
|
455
|
+
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 }) });
|
|
271
456
|
}
|
|
272
457
|
|
|
273
458
|
// src/components/doc/DocTable.tsx
|
|
274
|
-
var
|
|
459
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
275
460
|
function DocTable({ entry }) {
|
|
276
|
-
return /* @__PURE__ */ (0,
|
|
277
|
-
entry.label ? /* @__PURE__ */ (0,
|
|
278
|
-
/* @__PURE__ */ (0,
|
|
279
|
-
/* @__PURE__ */ (0,
|
|
280
|
-
/* @__PURE__ */ (0,
|
|
461
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("figure", { className: "my-3", children: [
|
|
462
|
+
entry.label ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.label }) : null,
|
|
463
|
+
/* @__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: [
|
|
464
|
+
/* @__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)) }) }),
|
|
465
|
+
/* @__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)) })
|
|
281
466
|
] }) })
|
|
282
467
|
] });
|
|
283
468
|
}
|
|
284
469
|
|
|
285
470
|
// src/components/doc/DocLink.tsx
|
|
286
|
-
var
|
|
471
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
287
472
|
function DocLink({ entry }) {
|
|
288
|
-
return /* @__PURE__ */ (0,
|
|
473
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
289
474
|
"a",
|
|
290
475
|
{
|
|
291
476
|
className: "text-sm font-medium text-primary underline underline-offset-2 hover:no-underline",
|
|
@@ -319,7 +504,7 @@ function isLocalFsPath(value) {
|
|
|
319
504
|
}
|
|
320
505
|
|
|
321
506
|
// src/components/doc/DocSection.tsx
|
|
322
|
-
var
|
|
507
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
323
508
|
function neutralizeUrl(value) {
|
|
324
509
|
return safeUrl(value) ?? "#";
|
|
325
510
|
}
|
|
@@ -330,12 +515,12 @@ function safeMarkdownHtml(markdown) {
|
|
|
330
515
|
function DocSection({ entry }) {
|
|
331
516
|
const renderers = useBuiltinRenderers();
|
|
332
517
|
if (renderers.section) {
|
|
333
|
-
return /* @__PURE__ */ (0,
|
|
518
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: renderers.section(entry) });
|
|
334
519
|
}
|
|
335
520
|
const html = safeMarkdownHtml(entry.markdown);
|
|
336
|
-
return /* @__PURE__ */ (0,
|
|
337
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
338
|
-
/* @__PURE__ */ (0,
|
|
521
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("section", { className: "my-3 text-sm", "aria-label": entry.title, children: [
|
|
522
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h4", { className: "mb-1 font-semibold text-foreground", children: entry.title }) : null,
|
|
523
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
339
524
|
"div",
|
|
340
525
|
{
|
|
341
526
|
className: "es-doc-prose prose prose-sm max-w-none",
|
|
@@ -346,11 +531,11 @@ function DocSection({ entry }) {
|
|
|
346
531
|
}
|
|
347
532
|
|
|
348
533
|
// src/components/doc/DocMermaid.tsx
|
|
349
|
-
var
|
|
534
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
350
535
|
function MermaidSource({ entry, ref }) {
|
|
351
|
-
return /* @__PURE__ */ (0,
|
|
352
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
353
|
-
/* @__PURE__ */ (0,
|
|
536
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("figure", { ref, className: "my-3", "aria-label": entry.title ?? "Diagram", children: [
|
|
537
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
538
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
354
539
|
"pre",
|
|
355
540
|
{
|
|
356
541
|
"data-mermaid": true,
|
|
@@ -364,24 +549,24 @@ function MermaidSource({ entry, ref }) {
|
|
|
364
549
|
function DocMermaid({ entry }) {
|
|
365
550
|
const renderers = useBuiltinRenderers();
|
|
366
551
|
if (renderers.mermaid) {
|
|
367
|
-
return /* @__PURE__ */ (0,
|
|
552
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: renderers.mermaid(entry) });
|
|
368
553
|
}
|
|
369
|
-
return /* @__PURE__ */ (0,
|
|
554
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MermaidSource, { entry });
|
|
370
555
|
}
|
|
371
556
|
|
|
372
557
|
// src/components/doc/DocScreenshot.tsx
|
|
373
|
-
var
|
|
558
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
374
559
|
function DocScreenshot({ entry }) {
|
|
375
560
|
const src = isLocalFsPath(entry.path) ? void 0 : safeImageUrl(entry.path);
|
|
376
561
|
if (!src) {
|
|
377
|
-
return /* @__PURE__ */ (0,
|
|
378
|
-
/* @__PURE__ */ (0,
|
|
379
|
-
/* @__PURE__ */ (0,
|
|
380
|
-
entry.alt ? /* @__PURE__ */ (0,
|
|
562
|
+
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: [
|
|
563
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "font-medium", children: "Screenshot unavailable" }),
|
|
564
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
565
|
+
entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.alt }) : null
|
|
381
566
|
] });
|
|
382
567
|
}
|
|
383
|
-
return /* @__PURE__ */ (0,
|
|
384
|
-
/* @__PURE__ */ (0,
|
|
568
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("figure", { className: "my-3", children: [
|
|
569
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
385
570
|
"img",
|
|
386
571
|
{
|
|
387
572
|
src,
|
|
@@ -390,24 +575,24 @@ function DocScreenshot({ entry }) {
|
|
|
390
575
|
className: "max-w-full rounded-md border border-border"
|
|
391
576
|
}
|
|
392
577
|
),
|
|
393
|
-
entry.alt ? /* @__PURE__ */ (0,
|
|
578
|
+
entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("figcaption", { className: "mt-1.5 text-xs text-muted-foreground", children: entry.alt }) : null
|
|
394
579
|
] });
|
|
395
580
|
}
|
|
396
581
|
|
|
397
582
|
// src/components/doc/DocVideo.tsx
|
|
398
|
-
var
|
|
583
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
399
584
|
function DocVideo({ entry }) {
|
|
400
585
|
if (isLocalFsPath(entry.path)) {
|
|
401
|
-
return /* @__PURE__ */ (0,
|
|
402
|
-
/* @__PURE__ */ (0,
|
|
403
|
-
/* @__PURE__ */ (0,
|
|
404
|
-
entry.caption ? /* @__PURE__ */ (0,
|
|
586
|
+
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: [
|
|
587
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "font-medium", children: "Video unavailable" }),
|
|
588
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
589
|
+
entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.caption }) : null
|
|
405
590
|
] });
|
|
406
591
|
}
|
|
407
592
|
const src = safeUrl(entry.path);
|
|
408
593
|
const poster = safeUrl(entry.poster);
|
|
409
|
-
return /* @__PURE__ */ (0,
|
|
410
|
-
/* @__PURE__ */ (0,
|
|
594
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "my-3", children: [
|
|
595
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
411
596
|
"video",
|
|
412
597
|
{
|
|
413
598
|
controls: true,
|
|
@@ -417,21 +602,21 @@ function DocVideo({ entry }) {
|
|
|
417
602
|
className: "max-w-full rounded-md border border-border"
|
|
418
603
|
}
|
|
419
604
|
),
|
|
420
|
-
entry.caption ? /* @__PURE__ */ (0,
|
|
605
|
+
entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: entry.caption }) : null
|
|
421
606
|
] });
|
|
422
607
|
}
|
|
423
608
|
|
|
424
609
|
// src/components/doc/DocHtml.tsx
|
|
425
|
-
var
|
|
610
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
426
611
|
function DocHtml({ entry }) {
|
|
427
612
|
const height = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
428
613
|
const title = entry.title ?? "Embedded HTML";
|
|
429
614
|
const safeHref = safeUrl(entry.url ?? entry.path);
|
|
430
615
|
const frameProps = entry.content !== void 0 ? { srcDoc: entry.content } : { src: safeHref ?? "" };
|
|
431
|
-
return /* @__PURE__ */ (0,
|
|
432
|
-
/* @__PURE__ */ (0,
|
|
433
|
-
/* @__PURE__ */ (0,
|
|
434
|
-
safeHref ? /* @__PURE__ */ (0,
|
|
616
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
|
|
617
|
+
/* @__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: [
|
|
618
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: entry.title ?? "HTML" }),
|
|
619
|
+
safeHref ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
435
620
|
"a",
|
|
436
621
|
{
|
|
437
622
|
href: safeHref,
|
|
@@ -444,7 +629,7 @@ function DocHtml({ entry }) {
|
|
|
444
629
|
}
|
|
445
630
|
) : null
|
|
446
631
|
] }),
|
|
447
|
-
/* @__PURE__ */ (0,
|
|
632
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
448
633
|
"iframe",
|
|
449
634
|
{
|
|
450
635
|
...frameProps,
|
|
@@ -459,7 +644,7 @@ function DocHtml({ entry }) {
|
|
|
459
644
|
}
|
|
460
645
|
|
|
461
646
|
// src/components/doc/DocState.tsx
|
|
462
|
-
var
|
|
647
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
463
648
|
function DocState({ entry }) {
|
|
464
649
|
let json;
|
|
465
650
|
try {
|
|
@@ -467,23 +652,23 @@ function DocState({ entry }) {
|
|
|
467
652
|
} catch {
|
|
468
653
|
json = String(entry.value);
|
|
469
654
|
}
|
|
470
|
-
return /* @__PURE__ */ (0,
|
|
655
|
+
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 }) });
|
|
471
656
|
}
|
|
472
657
|
|
|
473
658
|
// src/components/doc/DocCustom.tsx
|
|
474
|
-
var
|
|
659
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
475
660
|
function DocCustom({ entry }) {
|
|
476
661
|
const renderers = useCustomRenderers();
|
|
477
662
|
const renderer = renderers[entry.type];
|
|
478
663
|
if (renderer) {
|
|
479
|
-
return /* @__PURE__ */ (0,
|
|
664
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children: renderer(entry) });
|
|
480
665
|
}
|
|
481
|
-
return /* @__PURE__ */ (0,
|
|
482
|
-
/* @__PURE__ */ (0,
|
|
483
|
-
/* @__PURE__ */ (0,
|
|
666
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
|
|
667
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
|
|
668
|
+
/* @__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) })
|
|
484
669
|
] });
|
|
485
670
|
}
|
|
486
|
-
function
|
|
671
|
+
function safeStringify2(value) {
|
|
487
672
|
try {
|
|
488
673
|
return JSON.stringify(value, null, 2);
|
|
489
674
|
} catch {
|
|
@@ -492,47 +677,47 @@ function safeStringify(value) {
|
|
|
492
677
|
}
|
|
493
678
|
|
|
494
679
|
// src/components/doc/DocEntry.tsx
|
|
495
|
-
var
|
|
680
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
496
681
|
function DocEntry({ entry }) {
|
|
497
682
|
switch (entry.kind) {
|
|
498
683
|
case "note":
|
|
499
|
-
return /* @__PURE__ */ (0,
|
|
684
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocNote, { entry });
|
|
500
685
|
case "tag":
|
|
501
|
-
return /* @__PURE__ */ (0,
|
|
686
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocTag, { entry });
|
|
502
687
|
case "kv":
|
|
503
|
-
return /* @__PURE__ */ (0,
|
|
688
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocKv, { entry });
|
|
504
689
|
case "code":
|
|
505
|
-
return /* @__PURE__ */ (0,
|
|
690
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocCode, { entry });
|
|
506
691
|
case "table":
|
|
507
|
-
return /* @__PURE__ */ (0,
|
|
692
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocTable, { entry });
|
|
508
693
|
case "link":
|
|
509
|
-
return /* @__PURE__ */ (0,
|
|
694
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocLink, { entry });
|
|
510
695
|
case "section":
|
|
511
|
-
return /* @__PURE__ */ (0,
|
|
696
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocSection, { entry });
|
|
512
697
|
case "mermaid":
|
|
513
|
-
return /* @__PURE__ */ (0,
|
|
698
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocMermaid, { entry });
|
|
514
699
|
case "screenshot":
|
|
515
|
-
return /* @__PURE__ */ (0,
|
|
700
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocScreenshot, { entry });
|
|
516
701
|
case "video":
|
|
517
|
-
return /* @__PURE__ */ (0,
|
|
702
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocVideo, { entry });
|
|
518
703
|
case "html":
|
|
519
|
-
return /* @__PURE__ */ (0,
|
|
704
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocHtml, { entry });
|
|
520
705
|
case "state":
|
|
521
|
-
return /* @__PURE__ */ (0,
|
|
706
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocState, { entry });
|
|
522
707
|
case "custom":
|
|
523
|
-
return /* @__PURE__ */ (0,
|
|
708
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocCustom, { entry });
|
|
524
709
|
}
|
|
525
710
|
}
|
|
526
711
|
|
|
527
712
|
// src/components/ReportDocEntries.tsx
|
|
528
|
-
var
|
|
713
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
529
714
|
function ReportDocEntries({ entries }) {
|
|
530
715
|
if (entries.length === 0) return null;
|
|
531
|
-
return /* @__PURE__ */ (0,
|
|
716
|
+
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)) });
|
|
532
717
|
}
|
|
533
718
|
|
|
534
719
|
// src/lib/step-params.tsx
|
|
535
|
-
var
|
|
720
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
536
721
|
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
537
722
|
function highlightStepParams(text) {
|
|
538
723
|
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
@@ -544,7 +729,7 @@ function highlightStepParams(text) {
|
|
|
544
729
|
const end = start + match[0].length;
|
|
545
730
|
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
546
731
|
nodes.push(
|
|
547
|
-
/* @__PURE__ */ (0,
|
|
732
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
548
733
|
);
|
|
549
734
|
lastIndex = end;
|
|
550
735
|
});
|
|
@@ -553,7 +738,7 @@ function highlightStepParams(text) {
|
|
|
553
738
|
}
|
|
554
739
|
|
|
555
740
|
// src/components/ReportSteps.tsx
|
|
556
|
-
var
|
|
741
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
557
742
|
var STEP_GLYPH = {
|
|
558
743
|
passed: "\u2713",
|
|
559
744
|
failed: "\u2717",
|
|
@@ -568,21 +753,21 @@ var STEP_GLYPH_COLOR = {
|
|
|
568
753
|
};
|
|
569
754
|
function ReportSteps({ scenario }) {
|
|
570
755
|
if (scenario.steps.length === 0) return null;
|
|
571
|
-
return /* @__PURE__ */ (0,
|
|
756
|
+
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)) });
|
|
572
757
|
}
|
|
573
758
|
function ReportStepItem({ step }) {
|
|
574
759
|
const kw = step.keyword.toLowerCase();
|
|
575
760
|
const continuation = kw === "and" || kw === "but";
|
|
576
|
-
return /* @__PURE__ */ (0,
|
|
761
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
577
762
|
"li",
|
|
578
763
|
{
|
|
579
764
|
id: step.id,
|
|
580
765
|
"data-status": step.status,
|
|
581
766
|
className: cn("py-1.5 text-[0.8125rem] leading-normal", continuation && "pl-5"),
|
|
582
767
|
children: [
|
|
583
|
-
/* @__PURE__ */ (0,
|
|
584
|
-
/* @__PURE__ */ (0,
|
|
585
|
-
/* @__PURE__ */ (0,
|
|
768
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-baseline gap-2", children: [
|
|
769
|
+
/* @__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" }),
|
|
770
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
586
771
|
"span",
|
|
587
772
|
{
|
|
588
773
|
className: cn(
|
|
@@ -592,10 +777,10 @@ function ReportStepItem({ step }) {
|
|
|
592
777
|
children: step.keyword
|
|
593
778
|
}
|
|
594
779
|
),
|
|
595
|
-
/* @__PURE__ */ (0,
|
|
596
|
-
step.durationMs > 0 ? /* @__PURE__ */ (0,
|
|
780
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
|
|
781
|
+
step.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(step.durationMs) }) : null
|
|
597
782
|
] }),
|
|
598
|
-
step.errorMessage ? /* @__PURE__ */ (0,
|
|
783
|
+
step.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
599
784
|
"pre",
|
|
600
785
|
{
|
|
601
786
|
role: "alert",
|
|
@@ -603,7 +788,7 @@ function ReportStepItem({ step }) {
|
|
|
603
788
|
children: step.errorMessage
|
|
604
789
|
}
|
|
605
790
|
) : null,
|
|
606
|
-
step.docEntries.length > 0 ? /* @__PURE__ */ (0,
|
|
791
|
+
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
|
|
607
792
|
]
|
|
608
793
|
}
|
|
609
794
|
);
|
|
@@ -728,7 +913,7 @@ function extractStoryboardFrames(scenario) {
|
|
|
728
913
|
}
|
|
729
914
|
|
|
730
915
|
// src/components/ReportStoryboard.tsx
|
|
731
|
-
var
|
|
916
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
732
917
|
var FRAME_GLYPH = {
|
|
733
918
|
passed: "\u2713",
|
|
734
919
|
failed: "\u2717",
|
|
@@ -744,32 +929,32 @@ var FRAME_GLYPH_COLOR = {
|
|
|
744
929
|
function ReportStoryboard({ scenario }) {
|
|
745
930
|
const frames = extractStoryboardFrames(scenario);
|
|
746
931
|
if (frames.length < 2) return null;
|
|
747
|
-
return /* @__PURE__ */ (0,
|
|
748
|
-
/* @__PURE__ */ (0,
|
|
749
|
-
/* @__PURE__ */ (0,
|
|
932
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
|
|
933
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
|
|
934
|
+
/* @__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)) })
|
|
750
935
|
] });
|
|
751
936
|
}
|
|
752
937
|
function StoryboardFrameItem({ frame }) {
|
|
753
938
|
const label = `${frame.keyword} ${frame.text}`;
|
|
754
939
|
const hasStates = frame.states.length > 0;
|
|
755
|
-
const caption = /* @__PURE__ */ (0,
|
|
756
|
-
/* @__PURE__ */ (0,
|
|
757
|
-
/* @__PURE__ */ (0,
|
|
758
|
-
/* @__PURE__ */ (0,
|
|
940
|
+
const caption = /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
|
|
941
|
+
/* @__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" }),
|
|
942
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "min-w-0", children: [
|
|
943
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
|
|
759
944
|
" ",
|
|
760
|
-
/* @__PURE__ */ (0,
|
|
945
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-muted-foreground", children: frame.screenshot?.alt ?? frame.text })
|
|
761
946
|
] })
|
|
762
947
|
] });
|
|
763
948
|
return (
|
|
764
949
|
// State cards need room for diff rows; screenshot-only frames keep the
|
|
765
950
|
// original narrow film-cell width (and DOM) unchanged.
|
|
766
|
-
/* @__PURE__ */ (0,
|
|
767
|
-
frame.screenshot ? /* @__PURE__ */ (0,
|
|
768
|
-
hasStates ? /* @__PURE__ */ (0,
|
|
951
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("li", { className: cn("shrink-0", hasStates ? "w-64" : "w-40"), children: [
|
|
952
|
+
frame.screenshot ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(FrameScreenshot, { frame, label }) : null,
|
|
953
|
+
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,
|
|
769
954
|
frame.screenshot ? caption : (
|
|
770
955
|
// No screenshot means no image anchor, so the caption carries the
|
|
771
956
|
// jump-to-step link instead.
|
|
772
|
-
/* @__PURE__ */ (0,
|
|
957
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("a", { href: `#${frame.stepId}`, "aria-label": `Jump to step: ${label}`, className: "block hover:underline", children: caption })
|
|
773
958
|
)
|
|
774
959
|
] })
|
|
775
960
|
);
|
|
@@ -777,13 +962,13 @@ function StoryboardFrameItem({ frame }) {
|
|
|
777
962
|
function FrameScreenshot({ frame, label }) {
|
|
778
963
|
const path = frame.screenshot?.path ?? "";
|
|
779
964
|
const src = isLocalFsPath(path) ? void 0 : safeImageUrl(path);
|
|
780
|
-
return /* @__PURE__ */ (0,
|
|
965
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
781
966
|
"a",
|
|
782
967
|
{
|
|
783
968
|
href: `#${frame.stepId}`,
|
|
784
969
|
"aria-label": `Jump to step: ${label}`,
|
|
785
970
|
className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
|
|
786
|
-
children: src ? /* @__PURE__ */ (0,
|
|
971
|
+
children: src ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
787
972
|
"img",
|
|
788
973
|
{
|
|
789
974
|
src,
|
|
@@ -791,7 +976,7 @@ function FrameScreenshot({ frame, label }) {
|
|
|
791
976
|
loading: "lazy",
|
|
792
977
|
className: "h-24 w-full bg-muted object-cover object-top"
|
|
793
978
|
}
|
|
794
|
-
) : /* @__PURE__ */ (0,
|
|
979
|
+
) : /* @__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" })
|
|
795
980
|
}
|
|
796
981
|
);
|
|
797
982
|
}
|
|
@@ -810,12 +995,12 @@ function prettyJson(value) {
|
|
|
810
995
|
function StateCardView({ card }) {
|
|
811
996
|
const json = prettyJson(card.value);
|
|
812
997
|
const firstCapture = card.changes === void 0;
|
|
813
|
-
return /* @__PURE__ */ (0,
|
|
814
|
-
/* @__PURE__ */ (0,
|
|
815
|
-
/* @__PURE__ */ (0,
|
|
816
|
-
firstCapture ? /* @__PURE__ */ (0,
|
|
998
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { "data-slot": "state-card", className: "rounded-md border border-border bg-card p-2", children: [
|
|
999
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: "flex flex-wrap items-baseline gap-1.5", children: [
|
|
1000
|
+
/* @__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" }),
|
|
1001
|
+
firstCapture ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-[0.625rem] text-muted-foreground italic", children: "first capture" }) : null
|
|
817
1002
|
] }),
|
|
818
|
-
!firstCapture && (card.changes && card.changes.length > 0 ? /* @__PURE__ */ (0,
|
|
1003
|
+
!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)(
|
|
819
1004
|
"li",
|
|
820
1005
|
{
|
|
821
1006
|
className: cn(
|
|
@@ -825,15 +1010,15 @@ function StateCardView({ card }) {
|
|
|
825
1010
|
children: summarizeStateChanges([change])[0]
|
|
826
1011
|
},
|
|
827
1012
|
i
|
|
828
|
-
)) }) : /* @__PURE__ */ (0,
|
|
829
|
-
/* @__PURE__ */ (0,
|
|
1013
|
+
)) }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "mt-1.5 text-[0.625rem] text-muted-foreground", children: "No changes" })),
|
|
1014
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
830
1015
|
"details",
|
|
831
1016
|
{
|
|
832
1017
|
open: firstCapture && json.length <= 240,
|
|
833
1018
|
className: cn(firstCapture ? "mt-1.5" : "mt-1"),
|
|
834
1019
|
children: [
|
|
835
|
-
/* @__PURE__ */ (0,
|
|
836
|
-
/* @__PURE__ */ (0,
|
|
1020
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("summary", { className: "cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground", children: "Snapshot" }),
|
|
1021
|
+
/* @__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 })
|
|
837
1022
|
]
|
|
838
1023
|
}
|
|
839
1024
|
)
|
|
@@ -841,17 +1026,17 @@ function StateCardView({ card }) {
|
|
|
841
1026
|
}
|
|
842
1027
|
|
|
843
1028
|
// src/components/ReportAttachments.tsx
|
|
844
|
-
var
|
|
1029
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
845
1030
|
function ReportAttachments({ attachments }) {
|
|
846
1031
|
if (attachments.length === 0) return null;
|
|
847
1032
|
return (
|
|
848
1033
|
// role="group" (not a labelled <section>) so multiple scenarios' attachment
|
|
849
1034
|
// blocks don't create duplicate "Attachments" region landmarks.
|
|
850
|
-
/* @__PURE__ */ (0,
|
|
1035
|
+
/* @__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) => {
|
|
851
1036
|
const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
|
|
852
1037
|
const isImage = att.mediaType.startsWith("image/");
|
|
853
|
-
return /* @__PURE__ */ (0,
|
|
854
|
-
/* @__PURE__ */ (0,
|
|
1038
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
1039
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
855
1040
|
"img",
|
|
856
1041
|
{
|
|
857
1042
|
src: dataUri,
|
|
@@ -860,8 +1045,8 @@ function ReportAttachments({ attachments }) {
|
|
|
860
1045
|
className: "max-w-full rounded-md border border-border"
|
|
861
1046
|
}
|
|
862
1047
|
),
|
|
863
|
-
/* @__PURE__ */ (0,
|
|
864
|
-
] }) : /* @__PURE__ */ (0,
|
|
1048
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
|
|
1049
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
865
1050
|
"a",
|
|
866
1051
|
{
|
|
867
1052
|
href: dataUri,
|
|
@@ -870,7 +1055,7 @@ function ReportAttachments({ attachments }) {
|
|
|
870
1055
|
children: [
|
|
871
1056
|
att.name,
|
|
872
1057
|
" ",
|
|
873
|
-
/* @__PURE__ */ (0,
|
|
1058
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
874
1059
|
"(",
|
|
875
1060
|
att.mediaType,
|
|
876
1061
|
")"
|
|
@@ -958,7 +1143,7 @@ function traceWindow(rows) {
|
|
|
958
1143
|
}
|
|
959
1144
|
|
|
960
1145
|
// src/components/ReportTrace.tsx
|
|
961
|
-
var
|
|
1146
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
962
1147
|
var BAR_COLOR = {
|
|
963
1148
|
ok: "bg-pass",
|
|
964
1149
|
error: "bg-fail",
|
|
@@ -969,8 +1154,8 @@ function ReportTrace({ spans }) {
|
|
|
969
1154
|
const rows = toTraceRows(spans);
|
|
970
1155
|
if (rows.length === 0) return null;
|
|
971
1156
|
const { minStartMs, totalMs } = traceWindow(rows);
|
|
972
|
-
return /* @__PURE__ */ (0,
|
|
973
|
-
/* @__PURE__ */ (0,
|
|
1157
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
|
|
1158
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
|
|
974
1159
|
"Trace (",
|
|
975
1160
|
rows.length,
|
|
976
1161
|
" span",
|
|
@@ -979,11 +1164,11 @@ function ReportTrace({ spans }) {
|
|
|
979
1164
|
formatDuration(totalMs),
|
|
980
1165
|
")"
|
|
981
1166
|
] }),
|
|
982
|
-
/* @__PURE__ */ (0,
|
|
1167
|
+
/* @__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) => {
|
|
983
1168
|
const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
|
|
984
1169
|
const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
|
|
985
|
-
return /* @__PURE__ */ (0,
|
|
986
|
-
/* @__PURE__ */ (0,
|
|
1170
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("li", { className: "flex items-center gap-2", children: [
|
|
1171
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
987
1172
|
"span",
|
|
988
1173
|
{
|
|
989
1174
|
className: "min-w-0 flex-1 truncate text-foreground",
|
|
@@ -992,14 +1177,14 @@ function ReportTrace({ spans }) {
|
|
|
992
1177
|
children: row.name
|
|
993
1178
|
}
|
|
994
1179
|
),
|
|
995
|
-
/* @__PURE__ */ (0,
|
|
1180
|
+
/* @__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)(
|
|
996
1181
|
"span",
|
|
997
1182
|
{
|
|
998
1183
|
className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
|
|
999
1184
|
style: { left: `${leftPct}%`, width: `${widthPct}%` }
|
|
1000
1185
|
}
|
|
1001
1186
|
) }),
|
|
1002
|
-
/* @__PURE__ */ (0,
|
|
1187
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
|
|
1003
1188
|
] }, `${row.spanId}-${i}`);
|
|
1004
1189
|
}) })
|
|
1005
1190
|
] });
|
|
@@ -1050,7 +1235,7 @@ function flakinessOf(entries) {
|
|
|
1050
1235
|
}
|
|
1051
1236
|
|
|
1052
1237
|
// src/components/ScenarioRunHistory.tsx
|
|
1053
|
-
var
|
|
1238
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1054
1239
|
var MAX_DOTS = 10;
|
|
1055
1240
|
var DOT_COLOR = {
|
|
1056
1241
|
passed: "bg-pass",
|
|
@@ -1070,16 +1255,16 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
1070
1255
|
const recent = entries.slice(-MAX_DOTS);
|
|
1071
1256
|
const flaky = flakinessOf(recent) === "flaky";
|
|
1072
1257
|
const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
|
|
1073
|
-
return /* @__PURE__ */ (0,
|
|
1074
|
-
flaky ? /* @__PURE__ */ (0,
|
|
1075
|
-
/* @__PURE__ */ (0,
|
|
1258
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
1259
|
+
flaky ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
|
|
1260
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1076
1261
|
"span",
|
|
1077
1262
|
{
|
|
1078
1263
|
role: "img",
|
|
1079
1264
|
"aria-label": `Run history: ${summary}`,
|
|
1080
1265
|
title: summary,
|
|
1081
1266
|
className: "flex shrink-0 items-center gap-[3px]",
|
|
1082
|
-
children: recent.map((e, i) => /* @__PURE__ */ (0,
|
|
1267
|
+
children: recent.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1083
1268
|
"span",
|
|
1084
1269
|
{
|
|
1085
1270
|
"aria-hidden": true,
|
|
@@ -1118,9 +1303,9 @@ function useScenarioActions() {
|
|
|
1118
1303
|
|
|
1119
1304
|
// src/components/ui/card.tsx
|
|
1120
1305
|
var React2 = require("react");
|
|
1121
|
-
var
|
|
1306
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1122
1307
|
function Card({ className, ...props }) {
|
|
1123
|
-
return /* @__PURE__ */ (0,
|
|
1308
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1124
1309
|
"div",
|
|
1125
1310
|
{
|
|
1126
1311
|
"data-slot": "card",
|
|
@@ -1133,7 +1318,7 @@ function Card({ className, ...props }) {
|
|
|
1133
1318
|
);
|
|
1134
1319
|
}
|
|
1135
1320
|
function CardHeader({ className, ...props }) {
|
|
1136
|
-
return /* @__PURE__ */ (0,
|
|
1321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1137
1322
|
"div",
|
|
1138
1323
|
{
|
|
1139
1324
|
"data-slot": "card-header",
|
|
@@ -1146,7 +1331,7 @@ function CardHeader({ className, ...props }) {
|
|
|
1146
1331
|
);
|
|
1147
1332
|
}
|
|
1148
1333
|
function CardContent({ className, ...props }) {
|
|
1149
|
-
return /* @__PURE__ */ (0,
|
|
1334
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1150
1335
|
"div",
|
|
1151
1336
|
{
|
|
1152
1337
|
"data-slot": "card-content",
|
|
@@ -1160,13 +1345,13 @@ function CardContent({ className, ...props }) {
|
|
|
1160
1345
|
var React3 = require("react");
|
|
1161
1346
|
var import_menu = require("@base-ui/react/menu");
|
|
1162
1347
|
var import_lucide_react = require("lucide-react");
|
|
1163
|
-
var
|
|
1348
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1164
1349
|
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";
|
|
1165
1350
|
function DropdownMenu(props) {
|
|
1166
|
-
return /* @__PURE__ */ (0,
|
|
1351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1167
1352
|
}
|
|
1168
1353
|
function DropdownMenuTrigger(props) {
|
|
1169
|
-
return /* @__PURE__ */ (0,
|
|
1354
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
1170
1355
|
}
|
|
1171
1356
|
function DropdownMenuContent({
|
|
1172
1357
|
className,
|
|
@@ -1174,14 +1359,14 @@ function DropdownMenuContent({
|
|
|
1174
1359
|
sideOffset = 4,
|
|
1175
1360
|
...props
|
|
1176
1361
|
}) {
|
|
1177
|
-
return /* @__PURE__ */ (0,
|
|
1362
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1178
1363
|
import_menu.Menu.Positioner,
|
|
1179
1364
|
{
|
|
1180
1365
|
"data-slot": "dropdown-menu-positioner",
|
|
1181
1366
|
className: "z-50",
|
|
1182
1367
|
align,
|
|
1183
1368
|
sideOffset,
|
|
1184
|
-
children: /* @__PURE__ */ (0,
|
|
1369
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1185
1370
|
import_menu.Menu.Popup,
|
|
1186
1371
|
{
|
|
1187
1372
|
"data-slot": "dropdown-menu-content",
|
|
@@ -1199,7 +1384,7 @@ function DropdownMenuItem({
|
|
|
1199
1384
|
className,
|
|
1200
1385
|
...props
|
|
1201
1386
|
}) {
|
|
1202
|
-
return /* @__PURE__ */ (0,
|
|
1387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1203
1388
|
import_menu.Menu.Item,
|
|
1204
1389
|
{
|
|
1205
1390
|
"data-slot": "dropdown-menu-item",
|
|
@@ -1211,7 +1396,7 @@ function DropdownMenuItem({
|
|
|
1211
1396
|
|
|
1212
1397
|
// src/components/ReportScenario.tsx
|
|
1213
1398
|
var import_lucide_react2 = require("lucide-react");
|
|
1214
|
-
var
|
|
1399
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1215
1400
|
var STATUS_META = {
|
|
1216
1401
|
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
1217
1402
|
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
@@ -1227,7 +1412,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1227
1412
|
const collapsible = collapse !== null && !hideTitle;
|
|
1228
1413
|
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
1229
1414
|
const actions = useScenarioActions();
|
|
1230
|
-
return /* @__PURE__ */ (0,
|
|
1415
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1231
1416
|
Card,
|
|
1232
1417
|
{
|
|
1233
1418
|
id: scenario.id,
|
|
@@ -1235,10 +1420,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1235
1420
|
...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
|
|
1236
1421
|
className: "gap-0 py-0",
|
|
1237
1422
|
children: [
|
|
1238
|
-
/* @__PURE__ */ (0,
|
|
1239
|
-
/* @__PURE__ */ (0,
|
|
1240
|
-
hideTitle ? null : /* @__PURE__ */ (0,
|
|
1241
|
-
collapsible ? /* @__PURE__ */ (0,
|
|
1423
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardHeader, { className: "px-4 py-3", children: [
|
|
1424
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
1425
|
+
hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
1426
|
+
collapsible ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1242
1427
|
"button",
|
|
1243
1428
|
{
|
|
1244
1429
|
type: "button",
|
|
@@ -1247,49 +1432,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1247
1432
|
"aria-controls": bodyId,
|
|
1248
1433
|
"aria-label": `Toggle ${scenario.title}`,
|
|
1249
1434
|
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
1250
|
-
children: /* @__PURE__ */ (0,
|
|
1435
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
1251
1436
|
}
|
|
1252
1437
|
) : null,
|
|
1253
|
-
/* @__PURE__ */ (0,
|
|
1254
|
-
/* @__PURE__ */ (0,
|
|
1438
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
1439
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: scenario.title })
|
|
1255
1440
|
] }),
|
|
1256
|
-
/* @__PURE__ */ (0,
|
|
1257
|
-
/* @__PURE__ */ (0,
|
|
1258
|
-
scenario.durationMs > 0 ? /* @__PURE__ */ (0,
|
|
1259
|
-
meta.showPill ? /* @__PURE__ */ (0,
|
|
1260
|
-
actions ? /* @__PURE__ */ (0,
|
|
1261
|
-
/* @__PURE__ */ (0,
|
|
1441
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1442
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1443
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
|
|
1444
|
+
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}` }),
|
|
1445
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenu, { children: [
|
|
1446
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1262
1447
|
DropdownMenuTrigger,
|
|
1263
1448
|
{
|
|
1264
1449
|
"aria-label": `Actions for ${scenario.title}`,
|
|
1265
1450
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
1266
|
-
children: /* @__PURE__ */ (0,
|
|
1451
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
|
|
1267
1452
|
}
|
|
1268
1453
|
),
|
|
1269
|
-
/* @__PURE__ */ (0,
|
|
1270
|
-
/* @__PURE__ */ (0,
|
|
1271
|
-
/* @__PURE__ */ (0,
|
|
1454
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuContent, { align: "end", children: [
|
|
1455
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
1456
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.LinkIcon, {}),
|
|
1272
1457
|
" Copy link"
|
|
1273
1458
|
] }),
|
|
1274
|
-
/* @__PURE__ */ (0,
|
|
1275
|
-
/* @__PURE__ */ (0,
|
|
1459
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
1460
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.FileTextIcon, {}),
|
|
1276
1461
|
" Copy as Markdown"
|
|
1277
1462
|
] }),
|
|
1278
|
-
/* @__PURE__ */ (0,
|
|
1279
|
-
/* @__PURE__ */ (0,
|
|
1463
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
1464
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.SparklesIcon, {}),
|
|
1280
1465
|
" Explain with AI"
|
|
1281
1466
|
] })
|
|
1282
1467
|
] })
|
|
1283
1468
|
] }) : null
|
|
1284
1469
|
] })
|
|
1285
1470
|
] }),
|
|
1286
|
-
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0,
|
|
1287
|
-
scenario.tags.map((t) => /* @__PURE__ */ (0,
|
|
1288
|
-
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0,
|
|
1471
|
+
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: [
|
|
1472
|
+
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}`)),
|
|
1473
|
+
(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}`))
|
|
1289
1474
|
] }) : null
|
|
1290
1475
|
] }),
|
|
1291
|
-
/* @__PURE__ */ (0,
|
|
1292
|
-
scenario.errorMessage ? /* @__PURE__ */ (0,
|
|
1476
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
1477
|
+
scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1293
1478
|
"pre",
|
|
1294
1479
|
{
|
|
1295
1480
|
role: "alert",
|
|
@@ -1297,11 +1482,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1297
1482
|
children: scenario.errorMessage
|
|
1298
1483
|
}
|
|
1299
1484
|
) : null,
|
|
1300
|
-
/* @__PURE__ */ (0,
|
|
1301
|
-
/* @__PURE__ */ (0,
|
|
1302
|
-
scenario.docEntries.length > 0 ? /* @__PURE__ */ (0,
|
|
1303
|
-
/* @__PURE__ */ (0,
|
|
1304
|
-
/* @__PURE__ */ (0,
|
|
1485
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportStoryboard, { scenario }),
|
|
1486
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportSteps, { scenario }),
|
|
1487
|
+
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,
|
|
1488
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportAttachments, { attachments: scenario.attachments }),
|
|
1489
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportTrace, { spans: scenario.otelSpans })
|
|
1305
1490
|
] })
|
|
1306
1491
|
]
|
|
1307
1492
|
}
|
|
@@ -1309,13 +1494,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1309
1494
|
}
|
|
1310
1495
|
|
|
1311
1496
|
// src/components/ReportScenarioList.tsx
|
|
1312
|
-
var
|
|
1497
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1313
1498
|
function ReportScenarioList({ feature }) {
|
|
1314
|
-
return /* @__PURE__ */ (0,
|
|
1499
|
+
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)) });
|
|
1315
1500
|
}
|
|
1316
1501
|
|
|
1317
1502
|
// src/components/ReportFeature.tsx
|
|
1318
|
-
var
|
|
1503
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1319
1504
|
function ReportFeature({ feature }) {
|
|
1320
1505
|
const titleId = `${feature.id}-title`;
|
|
1321
1506
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1326,7 +1511,7 @@ function ReportFeature({ feature }) {
|
|
|
1326
1511
|
return (
|
|
1327
1512
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
1328
1513
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1329
|
-
/* @__PURE__ */ (0,
|
|
1514
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
1330
1515
|
"section",
|
|
1331
1516
|
{
|
|
1332
1517
|
id: feature.id,
|
|
@@ -1334,9 +1519,9 @@ function ReportFeature({ feature }) {
|
|
|
1334
1519
|
"aria-labelledby": titleId,
|
|
1335
1520
|
className: "flex flex-col gap-3",
|
|
1336
1521
|
children: [
|
|
1337
|
-
/* @__PURE__ */ (0,
|
|
1338
|
-
/* @__PURE__ */ (0,
|
|
1339
|
-
/* @__PURE__ */ (0,
|
|
1522
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1523
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "min-w-0", children: [
|
|
1524
|
+
/* @__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)(
|
|
1340
1525
|
"button",
|
|
1341
1526
|
{
|
|
1342
1527
|
type: "button",
|
|
@@ -1345,31 +1530,31 @@ function ReportFeature({ feature }) {
|
|
|
1345
1530
|
"aria-controls": bodyId,
|
|
1346
1531
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1347
1532
|
children: [
|
|
1348
|
-
/* @__PURE__ */ (0,
|
|
1349
|
-
/* @__PURE__ */ (0,
|
|
1533
|
+
/* @__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" }),
|
|
1534
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "truncate", children: feature.title })
|
|
1350
1535
|
]
|
|
1351
1536
|
}
|
|
1352
1537
|
) : feature.title }),
|
|
1353
|
-
/* @__PURE__ */ (0,
|
|
1538
|
+
/* @__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 })
|
|
1354
1539
|
] }),
|
|
1355
|
-
/* @__PURE__ */ (0,
|
|
1540
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
1356
1541
|
"p",
|
|
1357
1542
|
{
|
|
1358
1543
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1359
1544
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1360
1545
|
children: [
|
|
1361
|
-
/* @__PURE__ */ (0,
|
|
1546
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { children: [
|
|
1362
1547
|
s.passed,
|
|
1363
1548
|
" passed"
|
|
1364
1549
|
] }),
|
|
1365
|
-
/* @__PURE__ */ (0,
|
|
1366
|
-
/* @__PURE__ */ (0,
|
|
1550
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1551
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1367
1552
|
s.failed,
|
|
1368
1553
|
" failed"
|
|
1369
1554
|
] }),
|
|
1370
|
-
skipped > 0 ? /* @__PURE__ */ (0,
|
|
1371
|
-
/* @__PURE__ */ (0,
|
|
1372
|
-
/* @__PURE__ */ (0,
|
|
1555
|
+
skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
1556
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1557
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { children: [
|
|
1373
1558
|
skipped,
|
|
1374
1559
|
" skipped"
|
|
1375
1560
|
] })
|
|
@@ -1378,7 +1563,7 @@ function ReportFeature({ feature }) {
|
|
|
1378
1563
|
}
|
|
1379
1564
|
)
|
|
1380
1565
|
] }),
|
|
1381
|
-
/* @__PURE__ */ (0,
|
|
1566
|
+
/* @__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 }) })
|
|
1382
1567
|
]
|
|
1383
1568
|
}
|
|
1384
1569
|
)
|
|
@@ -1386,17 +1571,17 @@ function ReportFeature({ feature }) {
|
|
|
1386
1571
|
}
|
|
1387
1572
|
|
|
1388
1573
|
// src/components/ReportFeatureList.tsx
|
|
1389
|
-
var
|
|
1574
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1390
1575
|
function ReportFeatureList() {
|
|
1391
1576
|
const report = useReport();
|
|
1392
|
-
return /* @__PURE__ */ (0,
|
|
1577
|
+
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)) });
|
|
1393
1578
|
}
|
|
1394
1579
|
|
|
1395
1580
|
// src/components/ui/empty.tsx
|
|
1396
1581
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
1397
|
-
var
|
|
1582
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1398
1583
|
function Empty({ className, ...props }) {
|
|
1399
|
-
return /* @__PURE__ */ (0,
|
|
1584
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1400
1585
|
"div",
|
|
1401
1586
|
{
|
|
1402
1587
|
"data-slot": "empty",
|
|
@@ -1409,7 +1594,7 @@ function Empty({ className, ...props }) {
|
|
|
1409
1594
|
);
|
|
1410
1595
|
}
|
|
1411
1596
|
function EmptyHeader({ className, ...props }) {
|
|
1412
|
-
return /* @__PURE__ */ (0,
|
|
1597
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1413
1598
|
"div",
|
|
1414
1599
|
{
|
|
1415
1600
|
"data-slot": "empty-header",
|
|
@@ -1436,7 +1621,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
|
|
|
1436
1621
|
}
|
|
1437
1622
|
);
|
|
1438
1623
|
function EmptyTitle({ className, ...props }) {
|
|
1439
|
-
return /* @__PURE__ */ (0,
|
|
1624
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1440
1625
|
"div",
|
|
1441
1626
|
{
|
|
1442
1627
|
"data-slot": "empty-title",
|
|
@@ -1447,16 +1632,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1447
1632
|
}
|
|
1448
1633
|
|
|
1449
1634
|
// src/components/ReportEmpty.tsx
|
|
1450
|
-
var
|
|
1635
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1451
1636
|
function ReportEmpty({ message }) {
|
|
1452
|
-
return /* @__PURE__ */ (0,
|
|
1637
|
+
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." }) }) });
|
|
1453
1638
|
}
|
|
1454
1639
|
|
|
1455
1640
|
// src/components/ReportSummary.tsx
|
|
1456
|
-
var
|
|
1641
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1457
1642
|
function ReportSummary({ className }) {
|
|
1458
1643
|
const report = useReport();
|
|
1459
|
-
return /* @__PURE__ */ (0,
|
|
1644
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1460
1645
|
ReportSummaryView,
|
|
1461
1646
|
{
|
|
1462
1647
|
summary: report.summary,
|
|
@@ -1482,7 +1667,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1482
1667
|
if (summary.pending > 0) {
|
|
1483
1668
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1484
1669
|
}
|
|
1485
|
-
return /* @__PURE__ */ (0,
|
|
1670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1486
1671
|
"dl",
|
|
1487
1672
|
{
|
|
1488
1673
|
className: cn(
|
|
@@ -1495,17 +1680,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1495
1680
|
"aria-label": ariaLabel,
|
|
1496
1681
|
children: cards.map((c) => {
|
|
1497
1682
|
const tone = TONE[c.status];
|
|
1498
|
-
return /* @__PURE__ */ (0,
|
|
1683
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
1499
1684
|
"div",
|
|
1500
1685
|
{
|
|
1501
1686
|
"data-status": c.status,
|
|
1502
1687
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1503
1688
|
children: [
|
|
1504
|
-
/* @__PURE__ */ (0,
|
|
1505
|
-
/* @__PURE__ */ (0,
|
|
1689
|
+
/* @__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: [
|
|
1690
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1506
1691
|
c.label
|
|
1507
1692
|
] }),
|
|
1508
|
-
/* @__PURE__ */ (0,
|
|
1693
|
+
/* @__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 })
|
|
1509
1694
|
]
|
|
1510
1695
|
},
|
|
1511
1696
|
c.status
|
|
@@ -1565,7 +1750,7 @@ function prUrl(ci) {
|
|
|
1565
1750
|
}
|
|
1566
1751
|
|
|
1567
1752
|
// src/components/ReportMeta.tsx
|
|
1568
|
-
var
|
|
1753
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1569
1754
|
function ReportMeta() {
|
|
1570
1755
|
const report = useReport();
|
|
1571
1756
|
const items = [];
|
|
@@ -1588,13 +1773,13 @@ function ReportMeta() {
|
|
|
1588
1773
|
const short = sha.slice(0, 8);
|
|
1589
1774
|
items.push({
|
|
1590
1775
|
label: "Commit",
|
|
1591
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1776
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1592
1777
|
});
|
|
1593
1778
|
}
|
|
1594
1779
|
if (report.ci) {
|
|
1595
1780
|
items.push({
|
|
1596
1781
|
label: "CI",
|
|
1597
|
-
value: report.ci.url ? /* @__PURE__ */ (0,
|
|
1782
|
+
value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1598
1783
|
ciDisplayName(report.ci.name),
|
|
1599
1784
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1600
1785
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1605,7 +1790,7 @@ function ReportMeta() {
|
|
|
1605
1790
|
const label = `#${report.ci.prNumber}`;
|
|
1606
1791
|
items.push({
|
|
1607
1792
|
label: "PR",
|
|
1608
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1793
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1609
1794
|
});
|
|
1610
1795
|
}
|
|
1611
1796
|
if (items.length === 0) return null;
|
|
@@ -1613,48 +1798,48 @@ function ReportMeta() {
|
|
|
1613
1798
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1614
1799
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1615
1800
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1616
|
-
/* @__PURE__ */ (0,
|
|
1617
|
-
/* @__PURE__ */ (0,
|
|
1618
|
-
/* @__PURE__ */ (0,
|
|
1801
|
+
/* @__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: [
|
|
1802
|
+
/* @__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: [
|
|
1803
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1619
1804
|
"Run details"
|
|
1620
1805
|
] }),
|
|
1621
|
-
/* @__PURE__ */ (0,
|
|
1622
|
-
/* @__PURE__ */ (0,
|
|
1623
|
-
/* @__PURE__ */ (0,
|
|
1806
|
+
/* @__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: [
|
|
1807
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("dt", { className: "font-medium", children: item.label }),
|
|
1808
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1624
1809
|
] }, item.label)) })
|
|
1625
1810
|
] })
|
|
1626
1811
|
);
|
|
1627
1812
|
}
|
|
1628
1813
|
|
|
1629
1814
|
// src/components/ReportSchemaError.tsx
|
|
1630
|
-
var
|
|
1815
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1631
1816
|
function ReportSchemaError({ error }) {
|
|
1632
|
-
return /* @__PURE__ */ (0,
|
|
1633
|
-
/* @__PURE__ */ (0,
|
|
1634
|
-
/* @__PURE__ */ (0,
|
|
1635
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0,
|
|
1817
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1818
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("strong", { children: "Report could not be displayed." }) }),
|
|
1819
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { children: error.message }),
|
|
1820
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("p", { children: [
|
|
1636
1821
|
"The report bundle is newer than this version of ",
|
|
1637
|
-
/* @__PURE__ */ (0,
|
|
1822
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("code", { children: "executable-stories-react" }),
|
|
1638
1823
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1639
1824
|
] }) : null,
|
|
1640
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0,
|
|
1641
|
-
/* @__PURE__ */ (0,
|
|
1825
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("details", { children: [
|
|
1826
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("summary", { children: [
|
|
1642
1827
|
error.issues.length,
|
|
1643
1828
|
" validation issue",
|
|
1644
1829
|
error.issues.length === 1 ? "" : "s"
|
|
1645
1830
|
] }),
|
|
1646
|
-
/* @__PURE__ */ (0,
|
|
1831
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1647
1832
|
] }) : null
|
|
1648
1833
|
] });
|
|
1649
1834
|
}
|
|
1650
1835
|
|
|
1651
1836
|
// src/components/ReportShell.tsx
|
|
1652
|
-
var
|
|
1837
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
1653
1838
|
function ReportTitleBlock({ title }) {
|
|
1654
|
-
return /* @__PURE__ */ (0,
|
|
1655
|
-
/* @__PURE__ */ (0,
|
|
1656
|
-
/* @__PURE__ */ (0,
|
|
1657
|
-
/* @__PURE__ */ (0,
|
|
1839
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
|
|
1840
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h1", { children: title ?? "Story Report" }),
|
|
1841
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportSummary, {}),
|
|
1842
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportMeta, {})
|
|
1658
1843
|
] });
|
|
1659
1844
|
}
|
|
1660
1845
|
function ReportErrorShell({
|
|
@@ -1663,28 +1848,28 @@ function ReportErrorShell({
|
|
|
1663
1848
|
title,
|
|
1664
1849
|
dataTheme
|
|
1665
1850
|
}) {
|
|
1666
|
-
return /* @__PURE__ */ (0,
|
|
1851
|
+
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 }) });
|
|
1667
1852
|
}
|
|
1668
1853
|
|
|
1669
1854
|
// src/components/Report.tsx
|
|
1670
|
-
var
|
|
1855
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
1671
1856
|
function Report(props) {
|
|
1672
1857
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1673
1858
|
const result = unwrapReport(report);
|
|
1674
1859
|
if (!result.ok) {
|
|
1675
|
-
return /* @__PURE__ */ (0,
|
|
1860
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1676
1861
|
}
|
|
1677
1862
|
const data = result.data;
|
|
1678
1863
|
const hasContent = data.features.length > 0;
|
|
1679
|
-
return /* @__PURE__ */ (0,
|
|
1680
|
-
/* @__PURE__ */ (0,
|
|
1681
|
-
hasContent ? /* @__PURE__ */ (0,
|
|
1864
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1865
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportTitleBlock, { title }) }),
|
|
1866
|
+
hasContent ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportEmpty, {})
|
|
1682
1867
|
] }) });
|
|
1683
1868
|
}
|
|
1684
1869
|
|
|
1685
1870
|
// src/components/doc/MermaidView.tsx
|
|
1686
1871
|
var import_react8 = require("react");
|
|
1687
|
-
var
|
|
1872
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
1688
1873
|
function prefersDark(el) {
|
|
1689
1874
|
const themed = el?.closest("[data-theme]");
|
|
1690
1875
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -1694,21 +1879,38 @@ function prefersDark(el) {
|
|
|
1694
1879
|
function MermaidView({ entry, load }) {
|
|
1695
1880
|
const ref = (0, import_react8.useRef)(null);
|
|
1696
1881
|
const [svg, setSvg] = (0, import_react8.useState)(null);
|
|
1882
|
+
const [error, setError] = (0, import_react8.useState)(null);
|
|
1697
1883
|
(0, import_react8.useEffect)(() => {
|
|
1698
1884
|
let cancelled = false;
|
|
1699
1885
|
const draw = async () => {
|
|
1886
|
+
let mermaid;
|
|
1887
|
+
try {
|
|
1888
|
+
mermaid = await load();
|
|
1889
|
+
} catch {
|
|
1890
|
+
if (!cancelled) {
|
|
1891
|
+
setSvg(null);
|
|
1892
|
+
setError(null);
|
|
1893
|
+
}
|
|
1894
|
+
return;
|
|
1895
|
+
}
|
|
1700
1896
|
try {
|
|
1701
|
-
const mermaid = await load();
|
|
1702
1897
|
mermaid.initialize({
|
|
1703
1898
|
startOnLoad: false,
|
|
1704
1899
|
securityLevel: "strict",
|
|
1705
1900
|
theme: prefersDark(ref.current) ? "dark" : "default"
|
|
1706
1901
|
});
|
|
1902
|
+
await mermaid.parse(entry.code);
|
|
1707
1903
|
const id = `es-mermaid-${Math.random().toString(36).slice(2)}`;
|
|
1708
1904
|
const { svg: rendered } = await mermaid.render(id, entry.code);
|
|
1709
|
-
if (!cancelled)
|
|
1710
|
-
|
|
1711
|
-
|
|
1905
|
+
if (!cancelled) {
|
|
1906
|
+
setSvg(rendered);
|
|
1907
|
+
setError(null);
|
|
1908
|
+
}
|
|
1909
|
+
} catch (err2) {
|
|
1910
|
+
if (!cancelled) {
|
|
1911
|
+
setSvg(null);
|
|
1912
|
+
setError(err2 instanceof Error ? err2.message : String(err2));
|
|
1913
|
+
}
|
|
1712
1914
|
}
|
|
1713
1915
|
};
|
|
1714
1916
|
void draw();
|
|
@@ -1721,9 +1923,9 @@ function MermaidView({ entry, load }) {
|
|
|
1721
1923
|
};
|
|
1722
1924
|
}, [entry.code, load]);
|
|
1723
1925
|
if (svg) {
|
|
1724
|
-
return /* @__PURE__ */ (0,
|
|
1725
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
1726
|
-
/* @__PURE__ */ (0,
|
|
1926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("figure", { ref, className: "my-3", children: [
|
|
1927
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
1928
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
1727
1929
|
"div",
|
|
1728
1930
|
{
|
|
1729
1931
|
role: "img",
|
|
@@ -1734,18 +1936,32 @@ function MermaidView({ entry, load }) {
|
|
|
1734
1936
|
)
|
|
1735
1937
|
] });
|
|
1736
1938
|
}
|
|
1737
|
-
return /* @__PURE__ */ (0,
|
|
1939
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
|
|
1940
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
1941
|
+
"p",
|
|
1942
|
+
{
|
|
1943
|
+
role: "alert",
|
|
1944
|
+
"data-es-mermaid-error": true,
|
|
1945
|
+
className: "mt-3 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",
|
|
1946
|
+
children: [
|
|
1947
|
+
"Diagram failed to render: ",
|
|
1948
|
+
error
|
|
1949
|
+
]
|
|
1950
|
+
}
|
|
1951
|
+
) : null,
|
|
1952
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(MermaidSource, { entry, ref })
|
|
1953
|
+
] });
|
|
1738
1954
|
}
|
|
1739
1955
|
|
|
1740
1956
|
// src/components/doc/MermaidDiagram.tsx
|
|
1741
|
-
var
|
|
1957
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
1742
1958
|
var mermaidLoader;
|
|
1743
1959
|
function loadMermaid() {
|
|
1744
1960
|
mermaidLoader ??= import("mermaid").then((m) => m.default);
|
|
1745
1961
|
return mermaidLoader;
|
|
1746
1962
|
}
|
|
1747
1963
|
function MermaidDiagram({ entry, load = loadMermaid }) {
|
|
1748
|
-
return /* @__PURE__ */ (0,
|
|
1964
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(MermaidView, { entry, load });
|
|
1749
1965
|
}
|
|
1750
1966
|
|
|
1751
1967
|
// src/components/ScenarioExplorer.tsx
|
|
@@ -1755,12 +1971,12 @@ var import_react9 = require("react");
|
|
|
1755
1971
|
var React4 = require("react");
|
|
1756
1972
|
var import_cmdk = require("cmdk");
|
|
1757
1973
|
var import_lucide_react3 = require("lucide-react");
|
|
1758
|
-
var
|
|
1974
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
1759
1975
|
function Command({
|
|
1760
1976
|
className,
|
|
1761
1977
|
...props
|
|
1762
1978
|
}) {
|
|
1763
|
-
return /* @__PURE__ */ (0,
|
|
1979
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1764
1980
|
import_cmdk.Command,
|
|
1765
1981
|
{
|
|
1766
1982
|
"data-slot": "command",
|
|
@@ -1776,14 +1992,14 @@ function CommandInput({
|
|
|
1776
1992
|
className,
|
|
1777
1993
|
...props
|
|
1778
1994
|
}) {
|
|
1779
|
-
return /* @__PURE__ */ (0,
|
|
1995
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
1780
1996
|
"div",
|
|
1781
1997
|
{
|
|
1782
1998
|
"data-slot": "command-input-wrapper",
|
|
1783
1999
|
className: "flex h-9 items-center gap-2 border-b px-3",
|
|
1784
2000
|
children: [
|
|
1785
|
-
/* @__PURE__ */ (0,
|
|
1786
|
-
/* @__PURE__ */ (0,
|
|
2001
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react3.SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
|
|
2002
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1787
2003
|
import_cmdk.Command.Input,
|
|
1788
2004
|
{
|
|
1789
2005
|
"data-slot": "command-input",
|
|
@@ -1802,7 +2018,7 @@ function CommandList({
|
|
|
1802
2018
|
className,
|
|
1803
2019
|
...props
|
|
1804
2020
|
}) {
|
|
1805
|
-
return /* @__PURE__ */ (0,
|
|
2021
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1806
2022
|
import_cmdk.Command.List,
|
|
1807
2023
|
{
|
|
1808
2024
|
"data-slot": "command-list",
|
|
@@ -1817,7 +2033,7 @@ function CommandList({
|
|
|
1817
2033
|
function CommandEmpty({
|
|
1818
2034
|
...props
|
|
1819
2035
|
}) {
|
|
1820
|
-
return /* @__PURE__ */ (0,
|
|
2036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1821
2037
|
import_cmdk.Command.Empty,
|
|
1822
2038
|
{
|
|
1823
2039
|
"data-slot": "command-empty",
|
|
@@ -1830,7 +2046,7 @@ function CommandGroup({
|
|
|
1830
2046
|
className,
|
|
1831
2047
|
...props
|
|
1832
2048
|
}) {
|
|
1833
|
-
return /* @__PURE__ */ (0,
|
|
2049
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1834
2050
|
import_cmdk.Command.Group,
|
|
1835
2051
|
{
|
|
1836
2052
|
"data-slot": "command-group",
|
|
@@ -1846,7 +2062,7 @@ function CommandItem({
|
|
|
1846
2062
|
className,
|
|
1847
2063
|
...props
|
|
1848
2064
|
}) {
|
|
1849
|
-
return /* @__PURE__ */ (0,
|
|
2065
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1850
2066
|
import_cmdk.Command.Item,
|
|
1851
2067
|
{
|
|
1852
2068
|
"data-slot": "command-item",
|
|
@@ -1860,7 +2076,7 @@ function CommandItem({
|
|
|
1860
2076
|
}
|
|
1861
2077
|
|
|
1862
2078
|
// src/components/ScenarioExplorer.tsx
|
|
1863
|
-
var
|
|
2079
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
1864
2080
|
var STATUS_FILTERS = [
|
|
1865
2081
|
{ value: "all", label: "All" },
|
|
1866
2082
|
{ value: "passed", label: "Passed" },
|
|
@@ -1871,22 +2087,22 @@ var STATUS_FILTERS = [
|
|
|
1871
2087
|
function ScenarioExplorer({ scenarios, summary }) {
|
|
1872
2088
|
const [status, setStatus] = (0, import_react9.useState)("all");
|
|
1873
2089
|
const visible = status === "all" ? scenarios : scenarios.filter((s) => s.status === status);
|
|
1874
|
-
return /* @__PURE__ */ (0,
|
|
1875
|
-
summary ? /* @__PURE__ */ (0,
|
|
2090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "font-sans text-foreground", children: [
|
|
2091
|
+
summary ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("p", { className: "mb-3 text-sm text-muted-foreground", children: [
|
|
1876
2092
|
summary.total,
|
|
1877
2093
|
" scenarios \xB7 ",
|
|
1878
|
-
/* @__PURE__ */ (0,
|
|
2094
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "text-pass", children: [
|
|
1879
2095
|
summary.passed,
|
|
1880
2096
|
" passed"
|
|
1881
2097
|
] }),
|
|
1882
2098
|
" \xB7",
|
|
1883
2099
|
" ",
|
|
1884
|
-
/* @__PURE__ */ (0,
|
|
2100
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "text-fail", children: [
|
|
1885
2101
|
summary.failed,
|
|
1886
2102
|
" failed"
|
|
1887
2103
|
] })
|
|
1888
2104
|
] }) : null,
|
|
1889
|
-
/* @__PURE__ */ (0,
|
|
2105
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "mb-2 flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by status", children: STATUS_FILTERS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
1890
2106
|
"button",
|
|
1891
2107
|
{
|
|
1892
2108
|
type: "button",
|
|
@@ -1901,26 +2117,26 @@ function ScenarioExplorer({ scenarios, summary }) {
|
|
|
1901
2117
|
},
|
|
1902
2118
|
f.value
|
|
1903
2119
|
)) }),
|
|
1904
|
-
/* @__PURE__ */ (0,
|
|
2120
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
1905
2121
|
Command,
|
|
1906
2122
|
{
|
|
1907
2123
|
className: "rounded-lg border border-border bg-card",
|
|
1908
2124
|
filter: (value, search) => value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0,
|
|
1909
2125
|
children: [
|
|
1910
|
-
/* @__PURE__ */ (0,
|
|
1911
|
-
/* @__PURE__ */ (0,
|
|
1912
|
-
/* @__PURE__ */ (0,
|
|
1913
|
-
/* @__PURE__ */ (0,
|
|
2126
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(CommandInput, { placeholder: "Search scenarios\u2026" }),
|
|
2127
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(CommandList, { className: "max-h-none", children: [
|
|
2128
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(CommandEmpty, { children: "No scenarios match your filters." }),
|
|
2129
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
1914
2130
|
CommandItem,
|
|
1915
2131
|
{
|
|
1916
2132
|
value: `${s.title} ${s.feature} ${s.tags.join(" ")}`,
|
|
1917
2133
|
asChild: true,
|
|
1918
2134
|
className: "cursor-pointer",
|
|
1919
|
-
children: /* @__PURE__ */ (0,
|
|
1920
|
-
/* @__PURE__ */ (0,
|
|
1921
|
-
/* @__PURE__ */ (0,
|
|
1922
|
-
s.tags.slice(0, 3).map((t) => /* @__PURE__ */ (0,
|
|
1923
|
-
/* @__PURE__ */ (0,
|
|
2135
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("a", { href: s.href, className: "flex items-center gap-3", children: [
|
|
2136
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Badge, { variant: s.status, children: s.status }),
|
|
2137
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
|
|
2138
|
+
s.tags.slice(0, 3).map((t) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
|
|
2139
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
|
|
1924
2140
|
] })
|
|
1925
2141
|
},
|
|
1926
2142
|
s.id
|
|
@@ -2943,6 +3159,8 @@ function parseStoryReport(input) {
|
|
|
2943
3159
|
}
|
|
2944
3160
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2945
3161
|
0 && (module.exports = {
|
|
3162
|
+
DATA_MODEL_TYPE,
|
|
3163
|
+
DataModelBlock,
|
|
2946
3164
|
DocCode,
|
|
2947
3165
|
DocCustom,
|
|
2948
3166
|
DocEntry,
|
|
@@ -2956,6 +3174,8 @@ function parseStoryReport(input) {
|
|
|
2956
3174
|
DocTable,
|
|
2957
3175
|
DocTag,
|
|
2958
3176
|
DocVideo,
|
|
3177
|
+
FILE_TREE_TYPE,
|
|
3178
|
+
FileTreeBlock,
|
|
2959
3179
|
MermaidDiagram,
|
|
2960
3180
|
MermaidSource,
|
|
2961
3181
|
Report,
|
|
@@ -2985,7 +3205,10 @@ function parseStoryReport(input) {
|
|
|
2985
3205
|
err,
|
|
2986
3206
|
formatRelativeAge,
|
|
2987
3207
|
isReportStale,
|
|
3208
|
+
narrativeBlockRenderers,
|
|
2988
3209
|
ok,
|
|
3210
|
+
parseDataModel,
|
|
3211
|
+
parseFileTree,
|
|
2989
3212
|
parseStoryReport,
|
|
2990
3213
|
prUrl,
|
|
2991
3214
|
reportLastRunMs,
|