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.js
CHANGED
|
@@ -17,63 +17,6 @@ import { useMemo } from "react";
|
|
|
17
17
|
import { createContext } from "react";
|
|
18
18
|
var ReportContext = createContext(null);
|
|
19
19
|
|
|
20
|
-
// src/context/ReportRoot.tsx
|
|
21
|
-
import { jsx } from "react/jsx-runtime";
|
|
22
|
-
var EMPTY_CUSTOM = {};
|
|
23
|
-
var EMPTY_RENDERERS = {};
|
|
24
|
-
function ReportRoot({
|
|
25
|
-
report,
|
|
26
|
-
customRenderers,
|
|
27
|
-
renderers,
|
|
28
|
-
children
|
|
29
|
-
}) {
|
|
30
|
-
const value = useMemo(
|
|
31
|
-
() => ({
|
|
32
|
-
report,
|
|
33
|
-
customRenderers: customRenderers ?? EMPTY_CUSTOM,
|
|
34
|
-
renderers: renderers ?? EMPTY_RENDERERS
|
|
35
|
-
}),
|
|
36
|
-
[report, customRenderers, renderers]
|
|
37
|
-
);
|
|
38
|
-
return /* @__PURE__ */ jsx(ReportContext.Provider, { value, children });
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// src/hooks/useReport.ts
|
|
42
|
-
import { useContext } from "react";
|
|
43
|
-
function useReport() {
|
|
44
|
-
const ctx = useContext(ReportContext);
|
|
45
|
-
if (!ctx) {
|
|
46
|
-
throw new Error(
|
|
47
|
-
"useReport must be used inside <ReportRoot> or <Report>. Wrap your tree with one of those."
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
return ctx.report;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// ../executable-stories-core/dist/utils/duration.js
|
|
54
|
-
function formatDuration(ms) {
|
|
55
|
-
if (ms < 1e3) {
|
|
56
|
-
return `${Math.round(ms)} ms`;
|
|
57
|
-
}
|
|
58
|
-
if (ms < 6e4) {
|
|
59
|
-
return `${(ms / 1e3).toFixed(2)} s`;
|
|
60
|
-
}
|
|
61
|
-
const minutes = Math.floor(ms / 6e4);
|
|
62
|
-
const seconds = Math.floor(ms % 6e4 / 1e3);
|
|
63
|
-
if (minutes < 60) {
|
|
64
|
-
return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
65
|
-
}
|
|
66
|
-
const hours = Math.floor(minutes / 60);
|
|
67
|
-
const remainingMinutes = minutes % 60;
|
|
68
|
-
return `${hours}h ${remainingMinutes}m`;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// src/components/doc/DocNote.tsx
|
|
72
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
73
|
-
function DocNote({ entry }) {
|
|
74
|
-
return /* @__PURE__ */ jsx2("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
|
|
75
|
-
}
|
|
76
|
-
|
|
77
20
|
// src/components/ui/badge.tsx
|
|
78
21
|
import "react";
|
|
79
22
|
import { cva } from "class-variance-authority";
|
|
@@ -132,14 +75,249 @@ function Badge({
|
|
|
132
75
|
});
|
|
133
76
|
}
|
|
134
77
|
|
|
135
|
-
// src/components/doc/
|
|
78
|
+
// src/components/doc/NarrativeBlocks.tsx
|
|
79
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
80
|
+
var FILE_TREE_TYPE = "file-tree";
|
|
81
|
+
var DATA_MODEL_TYPE = "data-model";
|
|
82
|
+
function isChangeKind(value) {
|
|
83
|
+
return value === "added" || value === "modified" || value === "removed" || value === "renamed";
|
|
84
|
+
}
|
|
85
|
+
function isRecord(value) {
|
|
86
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
87
|
+
}
|
|
88
|
+
function str(value) {
|
|
89
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
90
|
+
}
|
|
91
|
+
function AuthoredMarker({ authored }) {
|
|
92
|
+
if (authored !== "agent") return null;
|
|
93
|
+
return /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "border-border text-[10px] text-muted-foreground", children: "AI-authored, not verified by a run" });
|
|
94
|
+
}
|
|
95
|
+
function BlockFrame({
|
|
96
|
+
title,
|
|
97
|
+
authored,
|
|
98
|
+
children
|
|
99
|
+
}) {
|
|
100
|
+
return /* @__PURE__ */ jsxs("figure", { className: "my-3", children: [
|
|
101
|
+
title || authored === "agent" ? /* @__PURE__ */ jsxs("figcaption", { className: "mb-1.5 flex flex-wrap items-center gap-2", children: [
|
|
102
|
+
title ? /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground", children: title }) : null,
|
|
103
|
+
/* @__PURE__ */ jsx(AuthoredMarker, { authored })
|
|
104
|
+
] }) : null,
|
|
105
|
+
children
|
|
106
|
+
] });
|
|
107
|
+
}
|
|
108
|
+
function ChangeBadge({ change }) {
|
|
109
|
+
return /* @__PURE__ */ jsx(Badge, { variant: "tag", className: "text-[10px]", children: change });
|
|
110
|
+
}
|
|
111
|
+
function parseFileTree(data) {
|
|
112
|
+
if (!isRecord(data) || !Array.isArray(data.files)) return void 0;
|
|
113
|
+
const files = [];
|
|
114
|
+
for (const raw of data.files) {
|
|
115
|
+
if (typeof raw === "string") {
|
|
116
|
+
if (raw) files.push({ path: raw });
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (!isRecord(raw)) continue;
|
|
120
|
+
const path = str(raw.path);
|
|
121
|
+
if (!path) continue;
|
|
122
|
+
files.push({
|
|
123
|
+
path,
|
|
124
|
+
change: isChangeKind(raw.change) ? raw.change : void 0,
|
|
125
|
+
note: str(raw.note)
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
if (files.length === 0) return void 0;
|
|
129
|
+
return { title: str(data.title), authored: str(data.authored), files };
|
|
130
|
+
}
|
|
131
|
+
function buildTree(files) {
|
|
132
|
+
const root = { name: "", children: /* @__PURE__ */ new Map() };
|
|
133
|
+
for (const file of files) {
|
|
134
|
+
const segments = file.path.split("/").filter(Boolean);
|
|
135
|
+
let node = root;
|
|
136
|
+
segments.forEach((segment, index) => {
|
|
137
|
+
let child = node.children.get(segment);
|
|
138
|
+
if (!child) {
|
|
139
|
+
child = { name: segment, children: /* @__PURE__ */ new Map() };
|
|
140
|
+
node.children.set(segment, child);
|
|
141
|
+
}
|
|
142
|
+
if (index === segments.length - 1) child.file = file;
|
|
143
|
+
node = child;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return root;
|
|
147
|
+
}
|
|
148
|
+
function sortedChildren(node) {
|
|
149
|
+
return [...node.children.values()].sort((a, b) => {
|
|
150
|
+
const aDir = a.children.size > 0;
|
|
151
|
+
const bDir = b.children.size > 0;
|
|
152
|
+
if (aDir !== bDir) return aDir ? -1 : 1;
|
|
153
|
+
return a.name.localeCompare(b.name);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function TreeBranch({ node, depth }) {
|
|
157
|
+
const children = sortedChildren(node);
|
|
158
|
+
return /* @__PURE__ */ jsx("ul", { className: cn("space-y-0.5", depth > 0 && "ml-3 border-l border-border/60 pl-3"), children: children.map((child) => {
|
|
159
|
+
const isDir = child.children.size > 0;
|
|
160
|
+
return /* @__PURE__ */ jsxs("li", { children: [
|
|
161
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-2", children: [
|
|
162
|
+
/* @__PURE__ */ jsx(
|
|
163
|
+
"span",
|
|
164
|
+
{
|
|
165
|
+
className: cn(
|
|
166
|
+
"font-mono text-xs",
|
|
167
|
+
isDir ? "text-muted-foreground" : "text-foreground"
|
|
168
|
+
),
|
|
169
|
+
children: isDir ? `${child.name}/` : child.name
|
|
170
|
+
}
|
|
171
|
+
),
|
|
172
|
+
child.file?.change ? /* @__PURE__ */ jsx(ChangeBadge, { change: child.file.change }) : null,
|
|
173
|
+
child.file?.note ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: child.file.note }) : null
|
|
174
|
+
] }),
|
|
175
|
+
isDir ? /* @__PURE__ */ jsx(TreeBranch, { node: child, depth: depth + 1 }) : null
|
|
176
|
+
] }, child.name);
|
|
177
|
+
}) });
|
|
178
|
+
}
|
|
179
|
+
function FileTreeBlock({ entry }) {
|
|
180
|
+
const data = parseFileTree(entry.data);
|
|
181
|
+
if (!data) return /* @__PURE__ */ jsx(UnreadableBlock, { entry });
|
|
182
|
+
return /* @__PURE__ */ jsx(BlockFrame, { title: data.title ?? "Files changed", authored: data.authored, children: /* @__PURE__ */ jsx("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border bg-card p-3", children: /* @__PURE__ */ jsx(TreeBranch, { node: buildTree(data.files), depth: 0 }) }) });
|
|
183
|
+
}
|
|
184
|
+
function parseDataModel(data) {
|
|
185
|
+
if (!isRecord(data) || !Array.isArray(data.fields)) return void 0;
|
|
186
|
+
const fields = [];
|
|
187
|
+
for (const raw of data.fields) {
|
|
188
|
+
if (!isRecord(raw)) continue;
|
|
189
|
+
const name = str(raw.name);
|
|
190
|
+
if (!name) continue;
|
|
191
|
+
fields.push({
|
|
192
|
+
name,
|
|
193
|
+
type: str(raw.type),
|
|
194
|
+
note: str(raw.note),
|
|
195
|
+
change: isChangeKind(raw.change) ? raw.change : void 0
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
if (fields.length === 0) return void 0;
|
|
199
|
+
return {
|
|
200
|
+
title: str(data.title),
|
|
201
|
+
authored: str(data.authored),
|
|
202
|
+
name: str(data.name),
|
|
203
|
+
fields
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function DataModelBlock({ entry }) {
|
|
207
|
+
const data = parseDataModel(entry.data);
|
|
208
|
+
if (!data) return /* @__PURE__ */ jsx(UnreadableBlock, { entry });
|
|
209
|
+
const hasNotes = data.fields.some((f) => f.note);
|
|
210
|
+
return /* @__PURE__ */ jsx(BlockFrame, { title: data.title ?? data.name ?? "Data model", authored: data.authored, children: /* @__PURE__ */ jsx("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-sm", children: [
|
|
211
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "bg-muted/50", children: [
|
|
212
|
+
/* @__PURE__ */ jsx("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Field" }),
|
|
213
|
+
/* @__PURE__ */ jsx("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Type" }),
|
|
214
|
+
hasNotes ? /* @__PURE__ */ jsx("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Note" }) : null
|
|
215
|
+
] }) }),
|
|
216
|
+
/* @__PURE__ */ jsx("tbody", { children: data.fields.map((field) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
217
|
+
/* @__PURE__ */ jsx("td", { className: "border-b border-border px-3 py-2", children: /* @__PURE__ */ jsxs("span", { className: "flex flex-wrap items-center gap-2", children: [
|
|
218
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono text-xs text-foreground", children: field.name }),
|
|
219
|
+
field.change ? /* @__PURE__ */ jsx(ChangeBadge, { change: field.change }) : null
|
|
220
|
+
] }) }),
|
|
221
|
+
/* @__PURE__ */ jsx("td", { className: "border-b border-border px-3 py-2 font-mono text-xs text-muted-foreground", children: field.type ?? "" }),
|
|
222
|
+
hasNotes ? /* @__PURE__ */ jsx("td", { className: "border-b border-border px-3 py-2 text-foreground", children: field.note ?? "" }) : null
|
|
223
|
+
] }, field.name)) })
|
|
224
|
+
] }) }) });
|
|
225
|
+
}
|
|
226
|
+
function UnreadableBlock({ entry }) {
|
|
227
|
+
return /* @__PURE__ */ jsxs("div", { className: "my-2", "data-type": entry.type, children: [
|
|
228
|
+
/* @__PURE__ */ jsxs("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: [
|
|
229
|
+
entry.type,
|
|
230
|
+
" (unrecognised shape)"
|
|
231
|
+
] }),
|
|
232
|
+
/* @__PURE__ */ jsx(
|
|
233
|
+
"pre",
|
|
234
|
+
{
|
|
235
|
+
tabIndex: 0,
|
|
236
|
+
className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground",
|
|
237
|
+
children: safeStringify(entry.data)
|
|
238
|
+
}
|
|
239
|
+
)
|
|
240
|
+
] });
|
|
241
|
+
}
|
|
242
|
+
function safeStringify(value) {
|
|
243
|
+
try {
|
|
244
|
+
return JSON.stringify(value, null, 2);
|
|
245
|
+
} catch {
|
|
246
|
+
return String(value);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
var narrativeBlockRenderers = {
|
|
250
|
+
[FILE_TREE_TYPE]: (entry) => /* @__PURE__ */ jsx(FileTreeBlock, { entry }),
|
|
251
|
+
[DATA_MODEL_TYPE]: (entry) => /* @__PURE__ */ jsx(DataModelBlock, { entry })
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// src/context/ReportRoot.tsx
|
|
255
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
256
|
+
var EMPTY_RENDERERS = {};
|
|
257
|
+
function ReportRoot({
|
|
258
|
+
report,
|
|
259
|
+
customRenderers,
|
|
260
|
+
renderers,
|
|
261
|
+
children
|
|
262
|
+
}) {
|
|
263
|
+
const value = useMemo(
|
|
264
|
+
() => ({
|
|
265
|
+
report,
|
|
266
|
+
// Narrative blocks render everywhere the report does (static SSR, the
|
|
267
|
+
// island, Astro) without every host wiring them up. A host renderer for
|
|
268
|
+
// the same type still wins.
|
|
269
|
+
customRenderers: { ...narrativeBlockRenderers, ...customRenderers },
|
|
270
|
+
renderers: renderers ?? EMPTY_RENDERERS
|
|
271
|
+
}),
|
|
272
|
+
[report, customRenderers, renderers]
|
|
273
|
+
);
|
|
274
|
+
return /* @__PURE__ */ jsx2(ReportContext.Provider, { value, children });
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// src/hooks/useReport.ts
|
|
278
|
+
import { useContext } from "react";
|
|
279
|
+
function useReport() {
|
|
280
|
+
const ctx = useContext(ReportContext);
|
|
281
|
+
if (!ctx) {
|
|
282
|
+
throw new Error(
|
|
283
|
+
"useReport must be used inside <ReportRoot> or <Report>. Wrap your tree with one of those."
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
return ctx.report;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ../executable-stories-core/dist/utils/duration.js
|
|
290
|
+
function formatDuration(ms) {
|
|
291
|
+
if (ms < 1e3) {
|
|
292
|
+
return `${Math.round(ms)} ms`;
|
|
293
|
+
}
|
|
294
|
+
if (ms < 6e4) {
|
|
295
|
+
return `${(ms / 1e3).toFixed(2)} s`;
|
|
296
|
+
}
|
|
297
|
+
const minutes = Math.floor(ms / 6e4);
|
|
298
|
+
const seconds = Math.floor(ms % 6e4 / 1e3);
|
|
299
|
+
if (minutes < 60) {
|
|
300
|
+
return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
301
|
+
}
|
|
302
|
+
const hours = Math.floor(minutes / 60);
|
|
303
|
+
const remainingMinutes = minutes % 60;
|
|
304
|
+
return `${hours}h ${remainingMinutes}m`;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// src/components/doc/DocNote.tsx
|
|
136
308
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
309
|
+
function DocNote({ entry }) {
|
|
310
|
+
return /* @__PURE__ */ jsx3("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// src/components/doc/DocTag.tsx
|
|
314
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
137
315
|
function DocTag({ entry }) {
|
|
138
|
-
return /* @__PURE__ */
|
|
316
|
+
return /* @__PURE__ */ jsx4("ul", { className: "my-2 flex flex-wrap gap-1.5", "aria-label": "Tags", children: entry.names.map((n) => /* @__PURE__ */ jsx4("li", { children: /* @__PURE__ */ jsx4(Badge, { variant: "tag", children: n }) }, n)) });
|
|
139
317
|
}
|
|
140
318
|
|
|
141
319
|
// src/components/doc/DocKv.tsx
|
|
142
|
-
import { jsx as
|
|
320
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
143
321
|
function formatValue(value) {
|
|
144
322
|
if (value === null) return "null";
|
|
145
323
|
if (typeof value === "string") return value;
|
|
@@ -151,19 +329,19 @@ function formatValue(value) {
|
|
|
151
329
|
}
|
|
152
330
|
}
|
|
153
331
|
function DocKv({ entry }) {
|
|
154
|
-
return /* @__PURE__ */
|
|
155
|
-
/* @__PURE__ */
|
|
156
|
-
/* @__PURE__ */
|
|
332
|
+
return /* @__PURE__ */ jsxs2("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
|
|
333
|
+
/* @__PURE__ */ jsx5("dt", { className: "font-semibold text-muted-foreground", children: entry.label }),
|
|
334
|
+
/* @__PURE__ */ jsx5("dd", { className: "font-mono text-foreground", children: formatValue(entry.value) })
|
|
157
335
|
] });
|
|
158
336
|
}
|
|
159
337
|
|
|
160
338
|
// src/hooks/useRenderers.ts
|
|
161
339
|
import { useContext as useContext2 } from "react";
|
|
162
|
-
var
|
|
340
|
+
var EMPTY_CUSTOM = {};
|
|
163
341
|
var EMPTY_RENDERERS2 = {};
|
|
164
342
|
function useCustomRenderers() {
|
|
165
343
|
const ctx = useContext2(ReportContext);
|
|
166
|
-
return ctx?.customRenderers ??
|
|
344
|
+
return ctx?.customRenderers ?? EMPTY_CUSTOM;
|
|
167
345
|
}
|
|
168
346
|
function useBuiltinRenderers() {
|
|
169
347
|
const ctx = useContext2(ReportContext);
|
|
@@ -171,37 +349,37 @@ function useBuiltinRenderers() {
|
|
|
171
349
|
}
|
|
172
350
|
|
|
173
351
|
// src/components/doc/DocCode.tsx
|
|
174
|
-
import { Fragment, jsx as
|
|
352
|
+
import { Fragment, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
175
353
|
function CodeFigure({ label, children }) {
|
|
176
|
-
return /* @__PURE__ */
|
|
177
|
-
label ? /* @__PURE__ */
|
|
178
|
-
/* @__PURE__ */
|
|
354
|
+
return /* @__PURE__ */ jsxs3("figure", { className: "my-3", children: [
|
|
355
|
+
label ? /* @__PURE__ */ jsx6("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: label }) : null,
|
|
356
|
+
/* @__PURE__ */ jsx6("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3", children })
|
|
179
357
|
] });
|
|
180
358
|
}
|
|
181
359
|
function DocCode({ entry }) {
|
|
182
360
|
const renderers = useBuiltinRenderers();
|
|
183
361
|
if (renderers.code) {
|
|
184
|
-
return /* @__PURE__ */
|
|
362
|
+
return /* @__PURE__ */ jsx6(Fragment, { children: renderers.code(entry) });
|
|
185
363
|
}
|
|
186
|
-
return /* @__PURE__ */
|
|
364
|
+
return /* @__PURE__ */ jsx6(CodeFigure, { label: entry.label, children: /* @__PURE__ */ jsx6("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
187
365
|
}
|
|
188
366
|
|
|
189
367
|
// src/components/doc/DocTable.tsx
|
|
190
|
-
import { jsx as
|
|
368
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
191
369
|
function DocTable({ entry }) {
|
|
192
|
-
return /* @__PURE__ */
|
|
193
|
-
entry.label ? /* @__PURE__ */
|
|
194
|
-
/* @__PURE__ */
|
|
195
|
-
/* @__PURE__ */
|
|
196
|
-
/* @__PURE__ */
|
|
370
|
+
return /* @__PURE__ */ jsxs4("figure", { className: "my-3", children: [
|
|
371
|
+
entry.label ? /* @__PURE__ */ jsx7("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.label }) : null,
|
|
372
|
+
/* @__PURE__ */ jsx7("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ jsxs4("table", { className: "w-full border-collapse text-sm", children: [
|
|
373
|
+
/* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsx7("tr", { className: "bg-muted/50", children: entry.columns.map((c) => /* @__PURE__ */ jsx7("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: c }, c)) }) }),
|
|
374
|
+
/* @__PURE__ */ jsx7("tbody", { children: entry.rows.map((row, i) => /* @__PURE__ */ jsx7("tr", { children: row.map((cell, j) => /* @__PURE__ */ jsx7("td", { className: "border-b border-border px-3 py-2 text-foreground", children: cell }, j)) }, i)) })
|
|
197
375
|
] }) })
|
|
198
376
|
] });
|
|
199
377
|
}
|
|
200
378
|
|
|
201
379
|
// src/components/doc/DocLink.tsx
|
|
202
|
-
import { jsx as
|
|
380
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
203
381
|
function DocLink({ entry }) {
|
|
204
|
-
return /* @__PURE__ */
|
|
382
|
+
return /* @__PURE__ */ jsx8(
|
|
205
383
|
"a",
|
|
206
384
|
{
|
|
207
385
|
className: "text-sm font-medium text-primary underline underline-offset-2 hover:no-underline",
|
|
@@ -235,7 +413,7 @@ function isLocalFsPath(value) {
|
|
|
235
413
|
}
|
|
236
414
|
|
|
237
415
|
// src/components/doc/DocSection.tsx
|
|
238
|
-
import { Fragment as Fragment2, jsx as
|
|
416
|
+
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
239
417
|
function neutralizeUrl(value) {
|
|
240
418
|
return safeUrl(value) ?? "#";
|
|
241
419
|
}
|
|
@@ -246,12 +424,12 @@ function safeMarkdownHtml(markdown) {
|
|
|
246
424
|
function DocSection({ entry }) {
|
|
247
425
|
const renderers = useBuiltinRenderers();
|
|
248
426
|
if (renderers.section) {
|
|
249
|
-
return /* @__PURE__ */
|
|
427
|
+
return /* @__PURE__ */ jsx9(Fragment2, { children: renderers.section(entry) });
|
|
250
428
|
}
|
|
251
429
|
const html = safeMarkdownHtml(entry.markdown);
|
|
252
|
-
return /* @__PURE__ */
|
|
253
|
-
entry.title ? /* @__PURE__ */
|
|
254
|
-
/* @__PURE__ */
|
|
430
|
+
return /* @__PURE__ */ jsxs5("section", { className: "my-3 text-sm", "aria-label": entry.title, children: [
|
|
431
|
+
entry.title ? /* @__PURE__ */ jsx9("h4", { className: "mb-1 font-semibold text-foreground", children: entry.title }) : null,
|
|
432
|
+
/* @__PURE__ */ jsx9(
|
|
255
433
|
"div",
|
|
256
434
|
{
|
|
257
435
|
className: "es-doc-prose prose prose-sm max-w-none",
|
|
@@ -262,11 +440,11 @@ function DocSection({ entry }) {
|
|
|
262
440
|
}
|
|
263
441
|
|
|
264
442
|
// src/components/doc/DocMermaid.tsx
|
|
265
|
-
import { Fragment as Fragment3, jsx as
|
|
443
|
+
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
266
444
|
function MermaidSource({ entry, ref }) {
|
|
267
|
-
return /* @__PURE__ */
|
|
268
|
-
entry.title ? /* @__PURE__ */
|
|
269
|
-
/* @__PURE__ */
|
|
445
|
+
return /* @__PURE__ */ jsxs6("figure", { ref, className: "my-3", "aria-label": entry.title ?? "Diagram", children: [
|
|
446
|
+
entry.title ? /* @__PURE__ */ jsx10("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
447
|
+
/* @__PURE__ */ jsx10(
|
|
270
448
|
"pre",
|
|
271
449
|
{
|
|
272
450
|
"data-mermaid": true,
|
|
@@ -280,24 +458,24 @@ function MermaidSource({ entry, ref }) {
|
|
|
280
458
|
function DocMermaid({ entry }) {
|
|
281
459
|
const renderers = useBuiltinRenderers();
|
|
282
460
|
if (renderers.mermaid) {
|
|
283
|
-
return /* @__PURE__ */
|
|
461
|
+
return /* @__PURE__ */ jsx10(Fragment3, { children: renderers.mermaid(entry) });
|
|
284
462
|
}
|
|
285
|
-
return /* @__PURE__ */
|
|
463
|
+
return /* @__PURE__ */ jsx10(MermaidSource, { entry });
|
|
286
464
|
}
|
|
287
465
|
|
|
288
466
|
// src/components/doc/DocScreenshot.tsx
|
|
289
|
-
import { jsx as
|
|
467
|
+
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
290
468
|
function DocScreenshot({ entry }) {
|
|
291
469
|
const src = isLocalFsPath(entry.path) ? void 0 : safeImageUrl(entry.path);
|
|
292
470
|
if (!src) {
|
|
293
|
-
return /* @__PURE__ */
|
|
294
|
-
/* @__PURE__ */
|
|
295
|
-
/* @__PURE__ */
|
|
296
|
-
entry.alt ? /* @__PURE__ */
|
|
471
|
+
return /* @__PURE__ */ jsxs7("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
|
|
472
|
+
/* @__PURE__ */ jsx11("div", { className: "font-medium", children: "Screenshot unavailable" }),
|
|
473
|
+
/* @__PURE__ */ jsx11("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
474
|
+
entry.alt ? /* @__PURE__ */ jsx11("figcaption", { className: "mt-1.5 text-xs", children: entry.alt }) : null
|
|
297
475
|
] });
|
|
298
476
|
}
|
|
299
|
-
return /* @__PURE__ */
|
|
300
|
-
/* @__PURE__ */
|
|
477
|
+
return /* @__PURE__ */ jsxs7("figure", { className: "my-3", children: [
|
|
478
|
+
/* @__PURE__ */ jsx11(
|
|
301
479
|
"img",
|
|
302
480
|
{
|
|
303
481
|
src,
|
|
@@ -306,24 +484,24 @@ function DocScreenshot({ entry }) {
|
|
|
306
484
|
className: "max-w-full rounded-md border border-border"
|
|
307
485
|
}
|
|
308
486
|
),
|
|
309
|
-
entry.alt ? /* @__PURE__ */
|
|
487
|
+
entry.alt ? /* @__PURE__ */ jsx11("figcaption", { className: "mt-1.5 text-xs text-muted-foreground", children: entry.alt }) : null
|
|
310
488
|
] });
|
|
311
489
|
}
|
|
312
490
|
|
|
313
491
|
// src/components/doc/DocVideo.tsx
|
|
314
|
-
import { jsx as
|
|
492
|
+
import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
315
493
|
function DocVideo({ entry }) {
|
|
316
494
|
if (isLocalFsPath(entry.path)) {
|
|
317
|
-
return /* @__PURE__ */
|
|
318
|
-
/* @__PURE__ */
|
|
319
|
-
/* @__PURE__ */
|
|
320
|
-
entry.caption ? /* @__PURE__ */
|
|
495
|
+
return /* @__PURE__ */ jsxs8("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
|
|
496
|
+
/* @__PURE__ */ jsx12("div", { className: "font-medium", children: "Video unavailable" }),
|
|
497
|
+
/* @__PURE__ */ jsx12("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
498
|
+
entry.caption ? /* @__PURE__ */ jsx12("figcaption", { className: "mt-1.5 text-xs", children: entry.caption }) : null
|
|
321
499
|
] });
|
|
322
500
|
}
|
|
323
501
|
const src = safeUrl(entry.path);
|
|
324
502
|
const poster = safeUrl(entry.poster);
|
|
325
|
-
return /* @__PURE__ */
|
|
326
|
-
/* @__PURE__ */
|
|
503
|
+
return /* @__PURE__ */ jsxs8("figure", { className: "my-3", children: [
|
|
504
|
+
/* @__PURE__ */ jsx12(
|
|
327
505
|
"video",
|
|
328
506
|
{
|
|
329
507
|
controls: true,
|
|
@@ -333,21 +511,21 @@ function DocVideo({ entry }) {
|
|
|
333
511
|
className: "max-w-full rounded-md border border-border"
|
|
334
512
|
}
|
|
335
513
|
),
|
|
336
|
-
entry.caption ? /* @__PURE__ */
|
|
514
|
+
entry.caption ? /* @__PURE__ */ jsx12("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: entry.caption }) : null
|
|
337
515
|
] });
|
|
338
516
|
}
|
|
339
517
|
|
|
340
518
|
// src/components/doc/DocHtml.tsx
|
|
341
|
-
import { jsx as
|
|
519
|
+
import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
342
520
|
function DocHtml({ entry }) {
|
|
343
521
|
const height = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
344
522
|
const title = entry.title ?? "Embedded HTML";
|
|
345
523
|
const safeHref = safeUrl(entry.url ?? entry.path);
|
|
346
524
|
const frameProps = entry.content !== void 0 ? { srcDoc: entry.content } : { src: safeHref ?? "" };
|
|
347
|
-
return /* @__PURE__ */
|
|
348
|
-
/* @__PURE__ */
|
|
349
|
-
/* @__PURE__ */
|
|
350
|
-
safeHref ? /* @__PURE__ */
|
|
525
|
+
return /* @__PURE__ */ jsxs9("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
|
|
526
|
+
/* @__PURE__ */ jsxs9("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: [
|
|
527
|
+
/* @__PURE__ */ jsx13("span", { children: entry.title ?? "HTML" }),
|
|
528
|
+
safeHref ? /* @__PURE__ */ jsx13(
|
|
351
529
|
"a",
|
|
352
530
|
{
|
|
353
531
|
href: safeHref,
|
|
@@ -360,7 +538,7 @@ function DocHtml({ entry }) {
|
|
|
360
538
|
}
|
|
361
539
|
) : null
|
|
362
540
|
] }),
|
|
363
|
-
/* @__PURE__ */
|
|
541
|
+
/* @__PURE__ */ jsx13(
|
|
364
542
|
"iframe",
|
|
365
543
|
{
|
|
366
544
|
...frameProps,
|
|
@@ -375,7 +553,7 @@ function DocHtml({ entry }) {
|
|
|
375
553
|
}
|
|
376
554
|
|
|
377
555
|
// src/components/doc/DocState.tsx
|
|
378
|
-
import { jsx as
|
|
556
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
379
557
|
function DocState({ entry }) {
|
|
380
558
|
let json;
|
|
381
559
|
try {
|
|
@@ -383,23 +561,23 @@ function DocState({ entry }) {
|
|
|
383
561
|
} catch {
|
|
384
562
|
json = String(entry.value);
|
|
385
563
|
}
|
|
386
|
-
return /* @__PURE__ */
|
|
564
|
+
return /* @__PURE__ */ jsx14(CodeFigure, { label: entry.label ?? "State", children: /* @__PURE__ */ jsx14("code", { className: "font-mono text-xs language-json", children: json }) });
|
|
387
565
|
}
|
|
388
566
|
|
|
389
567
|
// src/components/doc/DocCustom.tsx
|
|
390
|
-
import { Fragment as Fragment4, jsx as
|
|
568
|
+
import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
391
569
|
function DocCustom({ entry }) {
|
|
392
570
|
const renderers = useCustomRenderers();
|
|
393
571
|
const renderer = renderers[entry.type];
|
|
394
572
|
if (renderer) {
|
|
395
|
-
return /* @__PURE__ */
|
|
573
|
+
return /* @__PURE__ */ jsx15(Fragment4, { children: renderer(entry) });
|
|
396
574
|
}
|
|
397
|
-
return /* @__PURE__ */
|
|
398
|
-
/* @__PURE__ */
|
|
399
|
-
/* @__PURE__ */
|
|
575
|
+
return /* @__PURE__ */ jsxs10("div", { className: "my-2", "data-type": entry.type, children: [
|
|
576
|
+
/* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
|
|
577
|
+
/* @__PURE__ */ jsx15("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground", children: safeStringify2(entry.data) })
|
|
400
578
|
] });
|
|
401
579
|
}
|
|
402
|
-
function
|
|
580
|
+
function safeStringify2(value) {
|
|
403
581
|
try {
|
|
404
582
|
return JSON.stringify(value, null, 2);
|
|
405
583
|
} catch {
|
|
@@ -408,47 +586,47 @@ function safeStringify(value) {
|
|
|
408
586
|
}
|
|
409
587
|
|
|
410
588
|
// src/components/doc/DocEntry.tsx
|
|
411
|
-
import { jsx as
|
|
589
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
412
590
|
function DocEntry({ entry }) {
|
|
413
591
|
switch (entry.kind) {
|
|
414
592
|
case "note":
|
|
415
|
-
return /* @__PURE__ */
|
|
593
|
+
return /* @__PURE__ */ jsx16(DocNote, { entry });
|
|
416
594
|
case "tag":
|
|
417
|
-
return /* @__PURE__ */
|
|
595
|
+
return /* @__PURE__ */ jsx16(DocTag, { entry });
|
|
418
596
|
case "kv":
|
|
419
|
-
return /* @__PURE__ */
|
|
597
|
+
return /* @__PURE__ */ jsx16(DocKv, { entry });
|
|
420
598
|
case "code":
|
|
421
|
-
return /* @__PURE__ */
|
|
599
|
+
return /* @__PURE__ */ jsx16(DocCode, { entry });
|
|
422
600
|
case "table":
|
|
423
|
-
return /* @__PURE__ */
|
|
601
|
+
return /* @__PURE__ */ jsx16(DocTable, { entry });
|
|
424
602
|
case "link":
|
|
425
|
-
return /* @__PURE__ */
|
|
603
|
+
return /* @__PURE__ */ jsx16(DocLink, { entry });
|
|
426
604
|
case "section":
|
|
427
|
-
return /* @__PURE__ */
|
|
605
|
+
return /* @__PURE__ */ jsx16(DocSection, { entry });
|
|
428
606
|
case "mermaid":
|
|
429
|
-
return /* @__PURE__ */
|
|
607
|
+
return /* @__PURE__ */ jsx16(DocMermaid, { entry });
|
|
430
608
|
case "screenshot":
|
|
431
|
-
return /* @__PURE__ */
|
|
609
|
+
return /* @__PURE__ */ jsx16(DocScreenshot, { entry });
|
|
432
610
|
case "video":
|
|
433
|
-
return /* @__PURE__ */
|
|
611
|
+
return /* @__PURE__ */ jsx16(DocVideo, { entry });
|
|
434
612
|
case "html":
|
|
435
|
-
return /* @__PURE__ */
|
|
613
|
+
return /* @__PURE__ */ jsx16(DocHtml, { entry });
|
|
436
614
|
case "state":
|
|
437
|
-
return /* @__PURE__ */
|
|
615
|
+
return /* @__PURE__ */ jsx16(DocState, { entry });
|
|
438
616
|
case "custom":
|
|
439
|
-
return /* @__PURE__ */
|
|
617
|
+
return /* @__PURE__ */ jsx16(DocCustom, { entry });
|
|
440
618
|
}
|
|
441
619
|
}
|
|
442
620
|
|
|
443
621
|
// src/components/ReportDocEntries.tsx
|
|
444
|
-
import { Fragment as Fragment5, jsx as
|
|
622
|
+
import { Fragment as Fragment5, jsx as jsx17 } from "react/jsx-runtime";
|
|
445
623
|
function ReportDocEntries({ entries }) {
|
|
446
624
|
if (entries.length === 0) return null;
|
|
447
|
-
return /* @__PURE__ */
|
|
625
|
+
return /* @__PURE__ */ jsx17(Fragment5, { children: entries.map((entry, i) => /* @__PURE__ */ jsx17(DocEntry, { entry }, i)) });
|
|
448
626
|
}
|
|
449
627
|
|
|
450
628
|
// src/lib/step-params.tsx
|
|
451
|
-
import { jsx as
|
|
629
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
452
630
|
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
453
631
|
function highlightStepParams(text) {
|
|
454
632
|
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
@@ -460,7 +638,7 @@ function highlightStepParams(text) {
|
|
|
460
638
|
const end = start + match[0].length;
|
|
461
639
|
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
462
640
|
nodes.push(
|
|
463
|
-
/* @__PURE__ */
|
|
641
|
+
/* @__PURE__ */ jsx18("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
464
642
|
);
|
|
465
643
|
lastIndex = end;
|
|
466
644
|
});
|
|
@@ -469,7 +647,7 @@ function highlightStepParams(text) {
|
|
|
469
647
|
}
|
|
470
648
|
|
|
471
649
|
// src/components/ReportSteps.tsx
|
|
472
|
-
import { jsx as
|
|
650
|
+
import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
473
651
|
var STEP_GLYPH = {
|
|
474
652
|
passed: "\u2713",
|
|
475
653
|
failed: "\u2717",
|
|
@@ -484,21 +662,21 @@ var STEP_GLYPH_COLOR = {
|
|
|
484
662
|
};
|
|
485
663
|
function ReportSteps({ scenario }) {
|
|
486
664
|
if (scenario.steps.length === 0) return null;
|
|
487
|
-
return /* @__PURE__ */
|
|
665
|
+
return /* @__PURE__ */ jsx19("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ jsx19(ReportStepItem, { step }, step.id)) });
|
|
488
666
|
}
|
|
489
667
|
function ReportStepItem({ step }) {
|
|
490
668
|
const kw = step.keyword.toLowerCase();
|
|
491
669
|
const continuation = kw === "and" || kw === "but";
|
|
492
|
-
return /* @__PURE__ */
|
|
670
|
+
return /* @__PURE__ */ jsxs11(
|
|
493
671
|
"li",
|
|
494
672
|
{
|
|
495
673
|
id: step.id,
|
|
496
674
|
"data-status": step.status,
|
|
497
675
|
className: cn("py-1.5 text-[0.8125rem] leading-normal", continuation && "pl-5"),
|
|
498
676
|
children: [
|
|
499
|
-
/* @__PURE__ */
|
|
500
|
-
/* @__PURE__ */
|
|
501
|
-
/* @__PURE__ */
|
|
677
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-baseline gap-2", children: [
|
|
678
|
+
/* @__PURE__ */ jsx19("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" }),
|
|
679
|
+
/* @__PURE__ */ jsx19(
|
|
502
680
|
"span",
|
|
503
681
|
{
|
|
504
682
|
className: cn(
|
|
@@ -508,10 +686,10 @@ function ReportStepItem({ step }) {
|
|
|
508
686
|
children: step.keyword
|
|
509
687
|
}
|
|
510
688
|
),
|
|
511
|
-
/* @__PURE__ */
|
|
512
|
-
step.durationMs > 0 ? /* @__PURE__ */
|
|
689
|
+
/* @__PURE__ */ jsx19("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
|
|
690
|
+
step.durationMs > 0 ? /* @__PURE__ */ jsx19("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(step.durationMs) }) : null
|
|
513
691
|
] }),
|
|
514
|
-
step.errorMessage ? /* @__PURE__ */
|
|
692
|
+
step.errorMessage ? /* @__PURE__ */ jsx19(
|
|
515
693
|
"pre",
|
|
516
694
|
{
|
|
517
695
|
role: "alert",
|
|
@@ -519,7 +697,7 @@ function ReportStepItem({ step }) {
|
|
|
519
697
|
children: step.errorMessage
|
|
520
698
|
}
|
|
521
699
|
) : null,
|
|
522
|
-
step.docEntries.length > 0 ? /* @__PURE__ */
|
|
700
|
+
step.docEntries.length > 0 ? /* @__PURE__ */ jsx19("div", { "data-es-docs": true, className: "mt-2 ml-6", children: /* @__PURE__ */ jsx19(ReportDocEntries, { entries: step.docEntries }) }) : null
|
|
523
701
|
]
|
|
524
702
|
}
|
|
525
703
|
);
|
|
@@ -644,7 +822,7 @@ function extractStoryboardFrames(scenario) {
|
|
|
644
822
|
}
|
|
645
823
|
|
|
646
824
|
// src/components/ReportStoryboard.tsx
|
|
647
|
-
import { jsx as
|
|
825
|
+
import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
648
826
|
var FRAME_GLYPH = {
|
|
649
827
|
passed: "\u2713",
|
|
650
828
|
failed: "\u2717",
|
|
@@ -660,32 +838,32 @@ var FRAME_GLYPH_COLOR = {
|
|
|
660
838
|
function ReportStoryboard({ scenario }) {
|
|
661
839
|
const frames = extractStoryboardFrames(scenario);
|
|
662
840
|
if (frames.length < 2) return null;
|
|
663
|
-
return /* @__PURE__ */
|
|
664
|
-
/* @__PURE__ */
|
|
665
|
-
/* @__PURE__ */
|
|
841
|
+
return /* @__PURE__ */ jsxs12("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
|
|
842
|
+
/* @__PURE__ */ jsx20("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
|
|
843
|
+
/* @__PURE__ */ jsx20("ol", { className: "flex items-start gap-3 overflow-x-auto pb-2", children: frames.map((frame) => /* @__PURE__ */ jsx20(StoryboardFrameItem, { frame }, frame.stepId)) })
|
|
666
844
|
] });
|
|
667
845
|
}
|
|
668
846
|
function StoryboardFrameItem({ frame }) {
|
|
669
847
|
const label = `${frame.keyword} ${frame.text}`;
|
|
670
848
|
const hasStates = frame.states.length > 0;
|
|
671
|
-
const caption = /* @__PURE__ */
|
|
672
|
-
/* @__PURE__ */
|
|
673
|
-
/* @__PURE__ */
|
|
674
|
-
/* @__PURE__ */
|
|
849
|
+
const caption = /* @__PURE__ */ jsxs12("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
|
|
850
|
+
/* @__PURE__ */ jsx20("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
|
|
851
|
+
/* @__PURE__ */ jsxs12("span", { className: "min-w-0", children: [
|
|
852
|
+
/* @__PURE__ */ jsx20("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
|
|
675
853
|
" ",
|
|
676
|
-
/* @__PURE__ */
|
|
854
|
+
/* @__PURE__ */ jsx20("span", { className: "text-muted-foreground", children: frame.screenshot?.alt ?? frame.text })
|
|
677
855
|
] })
|
|
678
856
|
] });
|
|
679
857
|
return (
|
|
680
858
|
// State cards need room for diff rows; screenshot-only frames keep the
|
|
681
859
|
// original narrow film-cell width (and DOM) unchanged.
|
|
682
|
-
/* @__PURE__ */
|
|
683
|
-
frame.screenshot ? /* @__PURE__ */
|
|
684
|
-
hasStates ? /* @__PURE__ */
|
|
860
|
+
/* @__PURE__ */ jsxs12("li", { className: cn("shrink-0", hasStates ? "w-64" : "w-40"), children: [
|
|
861
|
+
frame.screenshot ? /* @__PURE__ */ jsx20(FrameScreenshot, { frame, label }) : null,
|
|
862
|
+
hasStates ? /* @__PURE__ */ jsx20("div", { className: cn("flex flex-col gap-1.5", frame.screenshot && "mt-1.5"), children: frame.states.map((card, i) => /* @__PURE__ */ jsx20(StateCardView, { card }, card.label ?? i)) }) : null,
|
|
685
863
|
frame.screenshot ? caption : (
|
|
686
864
|
// No screenshot means no image anchor, so the caption carries the
|
|
687
865
|
// jump-to-step link instead.
|
|
688
|
-
/* @__PURE__ */
|
|
866
|
+
/* @__PURE__ */ jsx20("a", { href: `#${frame.stepId}`, "aria-label": `Jump to step: ${label}`, className: "block hover:underline", children: caption })
|
|
689
867
|
)
|
|
690
868
|
] })
|
|
691
869
|
);
|
|
@@ -693,13 +871,13 @@ function StoryboardFrameItem({ frame }) {
|
|
|
693
871
|
function FrameScreenshot({ frame, label }) {
|
|
694
872
|
const path = frame.screenshot?.path ?? "";
|
|
695
873
|
const src = isLocalFsPath(path) ? void 0 : safeImageUrl(path);
|
|
696
|
-
return /* @__PURE__ */
|
|
874
|
+
return /* @__PURE__ */ jsx20(
|
|
697
875
|
"a",
|
|
698
876
|
{
|
|
699
877
|
href: `#${frame.stepId}`,
|
|
700
878
|
"aria-label": `Jump to step: ${label}`,
|
|
701
879
|
className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
|
|
702
|
-
children: src ? /* @__PURE__ */
|
|
880
|
+
children: src ? /* @__PURE__ */ jsx20(
|
|
703
881
|
"img",
|
|
704
882
|
{
|
|
705
883
|
src,
|
|
@@ -707,7 +885,7 @@ function FrameScreenshot({ frame, label }) {
|
|
|
707
885
|
loading: "lazy",
|
|
708
886
|
className: "h-24 w-full bg-muted object-cover object-top"
|
|
709
887
|
}
|
|
710
|
-
) : /* @__PURE__ */
|
|
888
|
+
) : /* @__PURE__ */ jsx20("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" })
|
|
711
889
|
}
|
|
712
890
|
);
|
|
713
891
|
}
|
|
@@ -726,12 +904,12 @@ function prettyJson(value) {
|
|
|
726
904
|
function StateCardView({ card }) {
|
|
727
905
|
const json = prettyJson(card.value);
|
|
728
906
|
const firstCapture = card.changes === void 0;
|
|
729
|
-
return /* @__PURE__ */
|
|
730
|
-
/* @__PURE__ */
|
|
731
|
-
/* @__PURE__ */
|
|
732
|
-
firstCapture ? /* @__PURE__ */
|
|
907
|
+
return /* @__PURE__ */ jsxs12("div", { "data-slot": "state-card", className: "rounded-md border border-border bg-card p-2", children: [
|
|
908
|
+
/* @__PURE__ */ jsxs12("p", { className: "flex flex-wrap items-baseline gap-1.5", children: [
|
|
909
|
+
/* @__PURE__ */ jsx20("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" }),
|
|
910
|
+
firstCapture ? /* @__PURE__ */ jsx20("span", { className: "text-[0.625rem] text-muted-foreground italic", children: "first capture" }) : null
|
|
733
911
|
] }),
|
|
734
|
-
!firstCapture && (card.changes && card.changes.length > 0 ? /* @__PURE__ */
|
|
912
|
+
!firstCapture && (card.changes && card.changes.length > 0 ? /* @__PURE__ */ jsx20("ul", { className: "mt-1.5 flex flex-col gap-0.5", children: card.changes.map((change, i) => /* @__PURE__ */ jsx20(
|
|
735
913
|
"li",
|
|
736
914
|
{
|
|
737
915
|
className: cn(
|
|
@@ -741,15 +919,15 @@ function StateCardView({ card }) {
|
|
|
741
919
|
children: summarizeStateChanges([change])[0]
|
|
742
920
|
},
|
|
743
921
|
i
|
|
744
|
-
)) }) : /* @__PURE__ */
|
|
745
|
-
/* @__PURE__ */
|
|
922
|
+
)) }) : /* @__PURE__ */ jsx20("p", { className: "mt-1.5 text-[0.625rem] text-muted-foreground", children: "No changes" })),
|
|
923
|
+
/* @__PURE__ */ jsxs12(
|
|
746
924
|
"details",
|
|
747
925
|
{
|
|
748
926
|
open: firstCapture && json.length <= 240,
|
|
749
927
|
className: cn(firstCapture ? "mt-1.5" : "mt-1"),
|
|
750
928
|
children: [
|
|
751
|
-
/* @__PURE__ */
|
|
752
|
-
/* @__PURE__ */
|
|
929
|
+
/* @__PURE__ */ jsx20("summary", { className: "cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground", children: "Snapshot" }),
|
|
930
|
+
/* @__PURE__ */ jsx20("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 })
|
|
753
931
|
]
|
|
754
932
|
}
|
|
755
933
|
)
|
|
@@ -757,17 +935,17 @@ function StateCardView({ card }) {
|
|
|
757
935
|
}
|
|
758
936
|
|
|
759
937
|
// src/components/ReportAttachments.tsx
|
|
760
|
-
import { Fragment as Fragment6, jsx as
|
|
938
|
+
import { Fragment as Fragment6, jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
761
939
|
function ReportAttachments({ attachments }) {
|
|
762
940
|
if (attachments.length === 0) return null;
|
|
763
941
|
return (
|
|
764
942
|
// role="group" (not a labelled <section>) so multiple scenarios' attachment
|
|
765
943
|
// blocks don't create duplicate "Attachments" region landmarks.
|
|
766
|
-
/* @__PURE__ */
|
|
944
|
+
/* @__PURE__ */ jsx21("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
|
|
767
945
|
const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
|
|
768
946
|
const isImage = att.mediaType.startsWith("image/");
|
|
769
|
-
return /* @__PURE__ */
|
|
770
|
-
/* @__PURE__ */
|
|
947
|
+
return /* @__PURE__ */ jsx21("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ jsxs13(Fragment6, { children: [
|
|
948
|
+
/* @__PURE__ */ jsx21(
|
|
771
949
|
"img",
|
|
772
950
|
{
|
|
773
951
|
src: dataUri,
|
|
@@ -776,8 +954,8 @@ function ReportAttachments({ attachments }) {
|
|
|
776
954
|
className: "max-w-full rounded-md border border-border"
|
|
777
955
|
}
|
|
778
956
|
),
|
|
779
|
-
/* @__PURE__ */
|
|
780
|
-
] }) : /* @__PURE__ */
|
|
957
|
+
/* @__PURE__ */ jsx21("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
|
|
958
|
+
] }) : /* @__PURE__ */ jsxs13(
|
|
781
959
|
"a",
|
|
782
960
|
{
|
|
783
961
|
href: dataUri,
|
|
@@ -786,7 +964,7 @@ function ReportAttachments({ attachments }) {
|
|
|
786
964
|
children: [
|
|
787
965
|
att.name,
|
|
788
966
|
" ",
|
|
789
|
-
/* @__PURE__ */
|
|
967
|
+
/* @__PURE__ */ jsxs13("span", { className: "text-muted-foreground", children: [
|
|
790
968
|
"(",
|
|
791
969
|
att.mediaType,
|
|
792
970
|
")"
|
|
@@ -874,7 +1052,7 @@ function traceWindow(rows) {
|
|
|
874
1052
|
}
|
|
875
1053
|
|
|
876
1054
|
// src/components/ReportTrace.tsx
|
|
877
|
-
import { jsx as
|
|
1055
|
+
import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
878
1056
|
var BAR_COLOR = {
|
|
879
1057
|
ok: "bg-pass",
|
|
880
1058
|
error: "bg-fail",
|
|
@@ -885,8 +1063,8 @@ function ReportTrace({ spans }) {
|
|
|
885
1063
|
const rows = toTraceRows(spans);
|
|
886
1064
|
if (rows.length === 0) return null;
|
|
887
1065
|
const { minStartMs, totalMs } = traceWindow(rows);
|
|
888
|
-
return /* @__PURE__ */
|
|
889
|
-
/* @__PURE__ */
|
|
1066
|
+
return /* @__PURE__ */ jsxs14("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
|
|
1067
|
+
/* @__PURE__ */ jsxs14("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
|
|
890
1068
|
"Trace (",
|
|
891
1069
|
rows.length,
|
|
892
1070
|
" span",
|
|
@@ -895,11 +1073,11 @@ function ReportTrace({ spans }) {
|
|
|
895
1073
|
formatDuration(totalMs),
|
|
896
1074
|
")"
|
|
897
1075
|
] }),
|
|
898
|
-
/* @__PURE__ */
|
|
1076
|
+
/* @__PURE__ */ jsx22("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
|
|
899
1077
|
const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
|
|
900
1078
|
const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
|
|
901
|
-
return /* @__PURE__ */
|
|
902
|
-
/* @__PURE__ */
|
|
1079
|
+
return /* @__PURE__ */ jsxs14("li", { className: "flex items-center gap-2", children: [
|
|
1080
|
+
/* @__PURE__ */ jsx22(
|
|
903
1081
|
"span",
|
|
904
1082
|
{
|
|
905
1083
|
className: "min-w-0 flex-1 truncate text-foreground",
|
|
@@ -908,14 +1086,14 @@ function ReportTrace({ spans }) {
|
|
|
908
1086
|
children: row.name
|
|
909
1087
|
}
|
|
910
1088
|
),
|
|
911
|
-
/* @__PURE__ */
|
|
1089
|
+
/* @__PURE__ */ jsx22("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ jsx22(
|
|
912
1090
|
"span",
|
|
913
1091
|
{
|
|
914
1092
|
className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
|
|
915
1093
|
style: { left: `${leftPct}%`, width: `${widthPct}%` }
|
|
916
1094
|
}
|
|
917
1095
|
) }),
|
|
918
|
-
/* @__PURE__ */
|
|
1096
|
+
/* @__PURE__ */ jsx22("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
|
|
919
1097
|
] }, `${row.spanId}-${i}`);
|
|
920
1098
|
}) })
|
|
921
1099
|
] });
|
|
@@ -966,7 +1144,7 @@ function flakinessOf(entries) {
|
|
|
966
1144
|
}
|
|
967
1145
|
|
|
968
1146
|
// src/components/ScenarioRunHistory.tsx
|
|
969
|
-
import { Fragment as Fragment7, jsx as
|
|
1147
|
+
import { Fragment as Fragment7, jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
970
1148
|
var MAX_DOTS = 10;
|
|
971
1149
|
var DOT_COLOR = {
|
|
972
1150
|
passed: "bg-pass",
|
|
@@ -986,16 +1164,16 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
986
1164
|
const recent = entries.slice(-MAX_DOTS);
|
|
987
1165
|
const flaky = flakinessOf(recent) === "flaky";
|
|
988
1166
|
const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
|
|
989
|
-
return /* @__PURE__ */
|
|
990
|
-
flaky ? /* @__PURE__ */
|
|
991
|
-
/* @__PURE__ */
|
|
1167
|
+
return /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
1168
|
+
flaky ? /* @__PURE__ */ jsx23(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
|
|
1169
|
+
/* @__PURE__ */ jsx23(
|
|
992
1170
|
"span",
|
|
993
1171
|
{
|
|
994
1172
|
role: "img",
|
|
995
1173
|
"aria-label": `Run history: ${summary}`,
|
|
996
1174
|
title: summary,
|
|
997
1175
|
className: "flex shrink-0 items-center gap-[3px]",
|
|
998
|
-
children: recent.map((e, i) => /* @__PURE__ */
|
|
1176
|
+
children: recent.map((e, i) => /* @__PURE__ */ jsx23(
|
|
999
1177
|
"span",
|
|
1000
1178
|
{
|
|
1001
1179
|
"aria-hidden": true,
|
|
@@ -1034,9 +1212,9 @@ function useScenarioActions() {
|
|
|
1034
1212
|
|
|
1035
1213
|
// src/components/ui/card.tsx
|
|
1036
1214
|
import "react";
|
|
1037
|
-
import { jsx as
|
|
1215
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
1038
1216
|
function Card({ className, ...props }) {
|
|
1039
|
-
return /* @__PURE__ */
|
|
1217
|
+
return /* @__PURE__ */ jsx24(
|
|
1040
1218
|
"div",
|
|
1041
1219
|
{
|
|
1042
1220
|
"data-slot": "card",
|
|
@@ -1049,7 +1227,7 @@ function Card({ className, ...props }) {
|
|
|
1049
1227
|
);
|
|
1050
1228
|
}
|
|
1051
1229
|
function CardHeader({ className, ...props }) {
|
|
1052
|
-
return /* @__PURE__ */
|
|
1230
|
+
return /* @__PURE__ */ jsx24(
|
|
1053
1231
|
"div",
|
|
1054
1232
|
{
|
|
1055
1233
|
"data-slot": "card-header",
|
|
@@ -1062,7 +1240,7 @@ function CardHeader({ className, ...props }) {
|
|
|
1062
1240
|
);
|
|
1063
1241
|
}
|
|
1064
1242
|
function CardContent({ className, ...props }) {
|
|
1065
|
-
return /* @__PURE__ */
|
|
1243
|
+
return /* @__PURE__ */ jsx24(
|
|
1066
1244
|
"div",
|
|
1067
1245
|
{
|
|
1068
1246
|
"data-slot": "card-content",
|
|
@@ -1076,13 +1254,13 @@ function CardContent({ className, ...props }) {
|
|
|
1076
1254
|
import "react";
|
|
1077
1255
|
import { Menu as MenuPrimitive } from "@base-ui/react/menu";
|
|
1078
1256
|
import { CheckIcon } from "lucide-react";
|
|
1079
|
-
import { jsx as
|
|
1257
|
+
import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1080
1258
|
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";
|
|
1081
1259
|
function DropdownMenu(props) {
|
|
1082
|
-
return /* @__PURE__ */
|
|
1260
|
+
return /* @__PURE__ */ jsx25(MenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1083
1261
|
}
|
|
1084
1262
|
function DropdownMenuTrigger(props) {
|
|
1085
|
-
return /* @__PURE__ */
|
|
1263
|
+
return /* @__PURE__ */ jsx25(MenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
1086
1264
|
}
|
|
1087
1265
|
function DropdownMenuContent({
|
|
1088
1266
|
className,
|
|
@@ -1090,14 +1268,14 @@ function DropdownMenuContent({
|
|
|
1090
1268
|
sideOffset = 4,
|
|
1091
1269
|
...props
|
|
1092
1270
|
}) {
|
|
1093
|
-
return /* @__PURE__ */
|
|
1271
|
+
return /* @__PURE__ */ jsx25(MenuPrimitive.Portal, { children: /* @__PURE__ */ jsx25(
|
|
1094
1272
|
MenuPrimitive.Positioner,
|
|
1095
1273
|
{
|
|
1096
1274
|
"data-slot": "dropdown-menu-positioner",
|
|
1097
1275
|
className: "z-50",
|
|
1098
1276
|
align,
|
|
1099
1277
|
sideOffset,
|
|
1100
|
-
children: /* @__PURE__ */
|
|
1278
|
+
children: /* @__PURE__ */ jsx25(
|
|
1101
1279
|
MenuPrimitive.Popup,
|
|
1102
1280
|
{
|
|
1103
1281
|
"data-slot": "dropdown-menu-content",
|
|
@@ -1115,7 +1293,7 @@ function DropdownMenuItem({
|
|
|
1115
1293
|
className,
|
|
1116
1294
|
...props
|
|
1117
1295
|
}) {
|
|
1118
|
-
return /* @__PURE__ */
|
|
1296
|
+
return /* @__PURE__ */ jsx25(
|
|
1119
1297
|
MenuPrimitive.Item,
|
|
1120
1298
|
{
|
|
1121
1299
|
"data-slot": "dropdown-menu-item",
|
|
@@ -1127,7 +1305,7 @@ function DropdownMenuItem({
|
|
|
1127
1305
|
|
|
1128
1306
|
// src/components/ReportScenario.tsx
|
|
1129
1307
|
import { LinkIcon, FileTextIcon, SparklesIcon, MoreHorizontalIcon } from "lucide-react";
|
|
1130
|
-
import { jsx as
|
|
1308
|
+
import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1131
1309
|
var STATUS_META = {
|
|
1132
1310
|
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
1133
1311
|
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
@@ -1143,7 +1321,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1143
1321
|
const collapsible = collapse !== null && !hideTitle;
|
|
1144
1322
|
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
1145
1323
|
const actions = useScenarioActions();
|
|
1146
|
-
return /* @__PURE__ */
|
|
1324
|
+
return /* @__PURE__ */ jsxs17(
|
|
1147
1325
|
Card,
|
|
1148
1326
|
{
|
|
1149
1327
|
id: scenario.id,
|
|
@@ -1151,10 +1329,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1151
1329
|
...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
|
|
1152
1330
|
className: "gap-0 py-0",
|
|
1153
1331
|
children: [
|
|
1154
|
-
/* @__PURE__ */
|
|
1155
|
-
/* @__PURE__ */
|
|
1156
|
-
hideTitle ? null : /* @__PURE__ */
|
|
1157
|
-
collapsible ? /* @__PURE__ */
|
|
1332
|
+
/* @__PURE__ */ jsxs17(CardHeader, { className: "px-4 py-3", children: [
|
|
1333
|
+
/* @__PURE__ */ jsxs17("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
1334
|
+
hideTitle ? null : /* @__PURE__ */ jsxs17("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
1335
|
+
collapsible ? /* @__PURE__ */ jsx26(
|
|
1158
1336
|
"button",
|
|
1159
1337
|
{
|
|
1160
1338
|
type: "button",
|
|
@@ -1163,49 +1341,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1163
1341
|
"aria-controls": bodyId,
|
|
1164
1342
|
"aria-label": `Toggle ${scenario.title}`,
|
|
1165
1343
|
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
1166
|
-
children: /* @__PURE__ */
|
|
1344
|
+
children: /* @__PURE__ */ jsx26("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
1167
1345
|
}
|
|
1168
1346
|
) : null,
|
|
1169
|
-
/* @__PURE__ */
|
|
1170
|
-
/* @__PURE__ */
|
|
1347
|
+
/* @__PURE__ */ jsx26("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
1348
|
+
/* @__PURE__ */ jsx26("span", { children: scenario.title })
|
|
1171
1349
|
] }),
|
|
1172
|
-
/* @__PURE__ */
|
|
1173
|
-
/* @__PURE__ */
|
|
1174
|
-
scenario.durationMs > 0 ? /* @__PURE__ */
|
|
1175
|
-
meta.showPill ? /* @__PURE__ */
|
|
1176
|
-
actions ? /* @__PURE__ */
|
|
1177
|
-
/* @__PURE__ */
|
|
1350
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1351
|
+
/* @__PURE__ */ jsx26(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1352
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ jsx26("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
|
|
1353
|
+
meta.showPill ? /* @__PURE__ */ jsx26(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ jsx26("span", { className: "sr-only", children: `Status: ${label}` }),
|
|
1354
|
+
actions ? /* @__PURE__ */ jsxs17(DropdownMenu, { children: [
|
|
1355
|
+
/* @__PURE__ */ jsx26(
|
|
1178
1356
|
DropdownMenuTrigger,
|
|
1179
1357
|
{
|
|
1180
1358
|
"aria-label": `Actions for ${scenario.title}`,
|
|
1181
1359
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
1182
|
-
children: /* @__PURE__ */
|
|
1360
|
+
children: /* @__PURE__ */ jsx26(MoreHorizontalIcon, { "aria-hidden": true })
|
|
1183
1361
|
}
|
|
1184
1362
|
),
|
|
1185
|
-
/* @__PURE__ */
|
|
1186
|
-
/* @__PURE__ */
|
|
1187
|
-
/* @__PURE__ */
|
|
1363
|
+
/* @__PURE__ */ jsxs17(DropdownMenuContent, { align: "end", children: [
|
|
1364
|
+
/* @__PURE__ */ jsxs17(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
1365
|
+
/* @__PURE__ */ jsx26(LinkIcon, {}),
|
|
1188
1366
|
" Copy link"
|
|
1189
1367
|
] }),
|
|
1190
|
-
/* @__PURE__ */
|
|
1191
|
-
/* @__PURE__ */
|
|
1368
|
+
/* @__PURE__ */ jsxs17(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
1369
|
+
/* @__PURE__ */ jsx26(FileTextIcon, {}),
|
|
1192
1370
|
" Copy as Markdown"
|
|
1193
1371
|
] }),
|
|
1194
|
-
/* @__PURE__ */
|
|
1195
|
-
/* @__PURE__ */
|
|
1372
|
+
/* @__PURE__ */ jsxs17(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
1373
|
+
/* @__PURE__ */ jsx26(SparklesIcon, {}),
|
|
1196
1374
|
" Explain with AI"
|
|
1197
1375
|
] })
|
|
1198
1376
|
] })
|
|
1199
1377
|
] }) : null
|
|
1200
1378
|
] })
|
|
1201
1379
|
] }),
|
|
1202
|
-
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */
|
|
1203
|
-
scenario.tags.map((t) => /* @__PURE__ */
|
|
1204
|
-
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */
|
|
1380
|
+
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs17("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
|
|
1381
|
+
scenario.tags.map((t) => /* @__PURE__ */ jsx26("li", { children: /* @__PURE__ */ jsx26(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
|
|
1382
|
+
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ jsx26("li", { children: ticket.url ? /* @__PURE__ */ jsx26("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ jsx26(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ jsx26(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
|
|
1205
1383
|
] }) : null
|
|
1206
1384
|
] }),
|
|
1207
|
-
/* @__PURE__ */
|
|
1208
|
-
scenario.errorMessage ? /* @__PURE__ */
|
|
1385
|
+
/* @__PURE__ */ jsxs17(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
1386
|
+
scenario.errorMessage ? /* @__PURE__ */ jsx26(
|
|
1209
1387
|
"pre",
|
|
1210
1388
|
{
|
|
1211
1389
|
role: "alert",
|
|
@@ -1213,11 +1391,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1213
1391
|
children: scenario.errorMessage
|
|
1214
1392
|
}
|
|
1215
1393
|
) : null,
|
|
1216
|
-
/* @__PURE__ */
|
|
1217
|
-
/* @__PURE__ */
|
|
1218
|
-
scenario.docEntries.length > 0 ? /* @__PURE__ */
|
|
1219
|
-
/* @__PURE__ */
|
|
1220
|
-
/* @__PURE__ */
|
|
1394
|
+
/* @__PURE__ */ jsx26(ReportStoryboard, { scenario }),
|
|
1395
|
+
/* @__PURE__ */ jsx26(ReportSteps, { scenario }),
|
|
1396
|
+
scenario.docEntries.length > 0 ? /* @__PURE__ */ jsx26("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ jsx26(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
|
|
1397
|
+
/* @__PURE__ */ jsx26(ReportAttachments, { attachments: scenario.attachments }),
|
|
1398
|
+
/* @__PURE__ */ jsx26(ReportTrace, { spans: scenario.otelSpans })
|
|
1221
1399
|
] })
|
|
1222
1400
|
]
|
|
1223
1401
|
}
|
|
@@ -1225,13 +1403,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1225
1403
|
}
|
|
1226
1404
|
|
|
1227
1405
|
// src/components/ReportScenarioList.tsx
|
|
1228
|
-
import { Fragment as Fragment8, jsx as
|
|
1406
|
+
import { Fragment as Fragment8, jsx as jsx27 } from "react/jsx-runtime";
|
|
1229
1407
|
function ReportScenarioList({ feature }) {
|
|
1230
|
-
return /* @__PURE__ */
|
|
1408
|
+
return /* @__PURE__ */ jsx27(Fragment8, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ jsx27(ReportScenario, { scenario }, scenario.id)) });
|
|
1231
1409
|
}
|
|
1232
1410
|
|
|
1233
1411
|
// src/components/ReportFeature.tsx
|
|
1234
|
-
import { Fragment as Fragment9, jsx as
|
|
1412
|
+
import { Fragment as Fragment9, jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1235
1413
|
function ReportFeature({ feature }) {
|
|
1236
1414
|
const titleId = `${feature.id}-title`;
|
|
1237
1415
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1242,7 +1420,7 @@ function ReportFeature({ feature }) {
|
|
|
1242
1420
|
return (
|
|
1243
1421
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
1244
1422
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1245
|
-
/* @__PURE__ */
|
|
1423
|
+
/* @__PURE__ */ jsxs18(
|
|
1246
1424
|
"section",
|
|
1247
1425
|
{
|
|
1248
1426
|
id: feature.id,
|
|
@@ -1250,9 +1428,9 @@ function ReportFeature({ feature }) {
|
|
|
1250
1428
|
"aria-labelledby": titleId,
|
|
1251
1429
|
className: "flex flex-col gap-3",
|
|
1252
1430
|
children: [
|
|
1253
|
-
/* @__PURE__ */
|
|
1254
|
-
/* @__PURE__ */
|
|
1255
|
-
/* @__PURE__ */
|
|
1431
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1432
|
+
/* @__PURE__ */ jsxs18("div", { className: "min-w-0", children: [
|
|
1433
|
+
/* @__PURE__ */ jsx28("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ jsxs18(
|
|
1256
1434
|
"button",
|
|
1257
1435
|
{
|
|
1258
1436
|
type: "button",
|
|
@@ -1261,31 +1439,31 @@ function ReportFeature({ feature }) {
|
|
|
1261
1439
|
"aria-controls": bodyId,
|
|
1262
1440
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1263
1441
|
children: [
|
|
1264
|
-
/* @__PURE__ */
|
|
1265
|
-
/* @__PURE__ */
|
|
1442
|
+
/* @__PURE__ */ jsx28("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
|
|
1443
|
+
/* @__PURE__ */ jsx28("span", { className: "truncate", children: feature.title })
|
|
1266
1444
|
]
|
|
1267
1445
|
}
|
|
1268
1446
|
) : feature.title }),
|
|
1269
|
-
/* @__PURE__ */
|
|
1447
|
+
/* @__PURE__ */ jsx28("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
|
|
1270
1448
|
] }),
|
|
1271
|
-
/* @__PURE__ */
|
|
1449
|
+
/* @__PURE__ */ jsxs18(
|
|
1272
1450
|
"p",
|
|
1273
1451
|
{
|
|
1274
1452
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1275
1453
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1276
1454
|
children: [
|
|
1277
|
-
/* @__PURE__ */
|
|
1455
|
+
/* @__PURE__ */ jsxs18("span", { children: [
|
|
1278
1456
|
s.passed,
|
|
1279
1457
|
" passed"
|
|
1280
1458
|
] }),
|
|
1281
|
-
/* @__PURE__ */
|
|
1282
|
-
/* @__PURE__ */
|
|
1459
|
+
/* @__PURE__ */ jsx28("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1460
|
+
/* @__PURE__ */ jsxs18("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1283
1461
|
s.failed,
|
|
1284
1462
|
" failed"
|
|
1285
1463
|
] }),
|
|
1286
|
-
skipped > 0 ? /* @__PURE__ */
|
|
1287
|
-
/* @__PURE__ */
|
|
1288
|
-
/* @__PURE__ */
|
|
1464
|
+
skipped > 0 ? /* @__PURE__ */ jsxs18(Fragment9, { children: [
|
|
1465
|
+
/* @__PURE__ */ jsx28("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1466
|
+
/* @__PURE__ */ jsxs18("span", { children: [
|
|
1289
1467
|
skipped,
|
|
1290
1468
|
" skipped"
|
|
1291
1469
|
] })
|
|
@@ -1294,7 +1472,7 @@ function ReportFeature({ feature }) {
|
|
|
1294
1472
|
}
|
|
1295
1473
|
)
|
|
1296
1474
|
] }),
|
|
1297
|
-
/* @__PURE__ */
|
|
1475
|
+
/* @__PURE__ */ jsx28("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx28(ReportScenarioList, { feature }) })
|
|
1298
1476
|
]
|
|
1299
1477
|
}
|
|
1300
1478
|
)
|
|
@@ -1302,17 +1480,17 @@ function ReportFeature({ feature }) {
|
|
|
1302
1480
|
}
|
|
1303
1481
|
|
|
1304
1482
|
// src/components/ReportFeatureList.tsx
|
|
1305
|
-
import { jsx as
|
|
1483
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
1306
1484
|
function ReportFeatureList() {
|
|
1307
1485
|
const report = useReport();
|
|
1308
|
-
return /* @__PURE__ */
|
|
1486
|
+
return /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ jsx29(ReportFeature, { feature }, feature.id)) });
|
|
1309
1487
|
}
|
|
1310
1488
|
|
|
1311
1489
|
// src/components/ui/empty.tsx
|
|
1312
1490
|
import { cva as cva2 } from "class-variance-authority";
|
|
1313
|
-
import { jsx as
|
|
1491
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
1314
1492
|
function Empty({ className, ...props }) {
|
|
1315
|
-
return /* @__PURE__ */
|
|
1493
|
+
return /* @__PURE__ */ jsx30(
|
|
1316
1494
|
"div",
|
|
1317
1495
|
{
|
|
1318
1496
|
"data-slot": "empty",
|
|
@@ -1325,7 +1503,7 @@ function Empty({ className, ...props }) {
|
|
|
1325
1503
|
);
|
|
1326
1504
|
}
|
|
1327
1505
|
function EmptyHeader({ className, ...props }) {
|
|
1328
|
-
return /* @__PURE__ */
|
|
1506
|
+
return /* @__PURE__ */ jsx30(
|
|
1329
1507
|
"div",
|
|
1330
1508
|
{
|
|
1331
1509
|
"data-slot": "empty-header",
|
|
@@ -1352,7 +1530,7 @@ var emptyMediaVariants = cva2(
|
|
|
1352
1530
|
}
|
|
1353
1531
|
);
|
|
1354
1532
|
function EmptyTitle({ className, ...props }) {
|
|
1355
|
-
return /* @__PURE__ */
|
|
1533
|
+
return /* @__PURE__ */ jsx30(
|
|
1356
1534
|
"div",
|
|
1357
1535
|
{
|
|
1358
1536
|
"data-slot": "empty-title",
|
|
@@ -1363,16 +1541,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1363
1541
|
}
|
|
1364
1542
|
|
|
1365
1543
|
// src/components/ReportEmpty.tsx
|
|
1366
|
-
import { jsx as
|
|
1544
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
1367
1545
|
function ReportEmpty({ message }) {
|
|
1368
|
-
return /* @__PURE__ */
|
|
1546
|
+
return /* @__PURE__ */ jsx31(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ jsx31(EmptyHeader, { children: /* @__PURE__ */ jsx31(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
|
|
1369
1547
|
}
|
|
1370
1548
|
|
|
1371
1549
|
// src/components/ReportSummary.tsx
|
|
1372
|
-
import { jsx as
|
|
1550
|
+
import { jsx as jsx32, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1373
1551
|
function ReportSummary({ className }) {
|
|
1374
1552
|
const report = useReport();
|
|
1375
|
-
return /* @__PURE__ */
|
|
1553
|
+
return /* @__PURE__ */ jsx32(
|
|
1376
1554
|
ReportSummaryView,
|
|
1377
1555
|
{
|
|
1378
1556
|
summary: report.summary,
|
|
@@ -1398,7 +1576,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1398
1576
|
if (summary.pending > 0) {
|
|
1399
1577
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1400
1578
|
}
|
|
1401
|
-
return /* @__PURE__ */
|
|
1579
|
+
return /* @__PURE__ */ jsx32(
|
|
1402
1580
|
"dl",
|
|
1403
1581
|
{
|
|
1404
1582
|
className: cn(
|
|
@@ -1411,17 +1589,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1411
1589
|
"aria-label": ariaLabel,
|
|
1412
1590
|
children: cards.map((c) => {
|
|
1413
1591
|
const tone = TONE[c.status];
|
|
1414
|
-
return /* @__PURE__ */
|
|
1592
|
+
return /* @__PURE__ */ jsxs19(
|
|
1415
1593
|
"div",
|
|
1416
1594
|
{
|
|
1417
1595
|
"data-status": c.status,
|
|
1418
1596
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1419
1597
|
children: [
|
|
1420
|
-
/* @__PURE__ */
|
|
1421
|
-
/* @__PURE__ */
|
|
1598
|
+
/* @__PURE__ */ jsxs19("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
|
|
1599
|
+
/* @__PURE__ */ jsx32("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1422
1600
|
c.label
|
|
1423
1601
|
] }),
|
|
1424
|
-
/* @__PURE__ */
|
|
1602
|
+
/* @__PURE__ */ jsx32("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
|
|
1425
1603
|
]
|
|
1426
1604
|
},
|
|
1427
1605
|
c.status
|
|
@@ -1481,7 +1659,7 @@ function prUrl(ci) {
|
|
|
1481
1659
|
}
|
|
1482
1660
|
|
|
1483
1661
|
// src/components/ReportMeta.tsx
|
|
1484
|
-
import { jsx as
|
|
1662
|
+
import { jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1485
1663
|
function ReportMeta() {
|
|
1486
1664
|
const report = useReport();
|
|
1487
1665
|
const items = [];
|
|
@@ -1504,13 +1682,13 @@ function ReportMeta() {
|
|
|
1504
1682
|
const short = sha.slice(0, 8);
|
|
1505
1683
|
items.push({
|
|
1506
1684
|
label: "Commit",
|
|
1507
|
-
value: url ? /* @__PURE__ */
|
|
1685
|
+
value: url ? /* @__PURE__ */ jsx33("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1508
1686
|
});
|
|
1509
1687
|
}
|
|
1510
1688
|
if (report.ci) {
|
|
1511
1689
|
items.push({
|
|
1512
1690
|
label: "CI",
|
|
1513
|
-
value: report.ci.url ? /* @__PURE__ */
|
|
1691
|
+
value: report.ci.url ? /* @__PURE__ */ jsxs20("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1514
1692
|
ciDisplayName(report.ci.name),
|
|
1515
1693
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1516
1694
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1521,7 +1699,7 @@ function ReportMeta() {
|
|
|
1521
1699
|
const label = `#${report.ci.prNumber}`;
|
|
1522
1700
|
items.push({
|
|
1523
1701
|
label: "PR",
|
|
1524
|
-
value: url ? /* @__PURE__ */
|
|
1702
|
+
value: url ? /* @__PURE__ */ jsx33("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1525
1703
|
});
|
|
1526
1704
|
}
|
|
1527
1705
|
if (items.length === 0) return null;
|
|
@@ -1529,48 +1707,48 @@ function ReportMeta() {
|
|
|
1529
1707
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1530
1708
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1531
1709
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1532
|
-
/* @__PURE__ */
|
|
1533
|
-
/* @__PURE__ */
|
|
1534
|
-
/* @__PURE__ */
|
|
1710
|
+
/* @__PURE__ */ jsxs20("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
|
|
1711
|
+
/* @__PURE__ */ jsxs20("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: [
|
|
1712
|
+
/* @__PURE__ */ jsx33("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1535
1713
|
"Run details"
|
|
1536
1714
|
] }),
|
|
1537
|
-
/* @__PURE__ */
|
|
1538
|
-
/* @__PURE__ */
|
|
1539
|
-
/* @__PURE__ */
|
|
1715
|
+
/* @__PURE__ */ jsx33("dl", { className: "flex flex-wrap gap-x-5 gap-y-2 border-t border-border px-4 py-3 text-muted-foreground", "aria-label": "Run metadata", children: items.map((item) => /* @__PURE__ */ jsxs20("div", { className: "flex items-baseline gap-1.5", children: [
|
|
1716
|
+
/* @__PURE__ */ jsx33("dt", { className: "font-medium", children: item.label }),
|
|
1717
|
+
/* @__PURE__ */ jsx33("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1540
1718
|
] }, item.label)) })
|
|
1541
1719
|
] })
|
|
1542
1720
|
);
|
|
1543
1721
|
}
|
|
1544
1722
|
|
|
1545
1723
|
// src/components/ReportSchemaError.tsx
|
|
1546
|
-
import { jsx as
|
|
1724
|
+
import { jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1547
1725
|
function ReportSchemaError({ error }) {
|
|
1548
|
-
return /* @__PURE__ */
|
|
1549
|
-
/* @__PURE__ */
|
|
1550
|
-
/* @__PURE__ */
|
|
1551
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */
|
|
1726
|
+
return /* @__PURE__ */ jsxs21("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1727
|
+
/* @__PURE__ */ jsx34("p", { children: /* @__PURE__ */ jsx34("strong", { children: "Report could not be displayed." }) }),
|
|
1728
|
+
/* @__PURE__ */ jsx34("p", { children: error.message }),
|
|
1729
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ jsxs21("p", { children: [
|
|
1552
1730
|
"The report bundle is newer than this version of ",
|
|
1553
|
-
/* @__PURE__ */
|
|
1731
|
+
/* @__PURE__ */ jsx34("code", { children: "executable-stories-react" }),
|
|
1554
1732
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1555
1733
|
] }) : null,
|
|
1556
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */
|
|
1557
|
-
/* @__PURE__ */
|
|
1734
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ jsxs21("details", { children: [
|
|
1735
|
+
/* @__PURE__ */ jsxs21("summary", { children: [
|
|
1558
1736
|
error.issues.length,
|
|
1559
1737
|
" validation issue",
|
|
1560
1738
|
error.issues.length === 1 ? "" : "s"
|
|
1561
1739
|
] }),
|
|
1562
|
-
/* @__PURE__ */
|
|
1740
|
+
/* @__PURE__ */ jsx34("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1563
1741
|
] }) : null
|
|
1564
1742
|
] });
|
|
1565
1743
|
}
|
|
1566
1744
|
|
|
1567
1745
|
// src/components/ReportShell.tsx
|
|
1568
|
-
import { Fragment as Fragment10, jsx as
|
|
1746
|
+
import { Fragment as Fragment10, jsx as jsx35, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1569
1747
|
function ReportTitleBlock({ title }) {
|
|
1570
|
-
return /* @__PURE__ */
|
|
1571
|
-
/* @__PURE__ */
|
|
1572
|
-
/* @__PURE__ */
|
|
1573
|
-
/* @__PURE__ */
|
|
1748
|
+
return /* @__PURE__ */ jsxs22(Fragment10, { children: [
|
|
1749
|
+
/* @__PURE__ */ jsx35("h1", { children: title ?? "Story Report" }),
|
|
1750
|
+
/* @__PURE__ */ jsx35(ReportSummary, {}),
|
|
1751
|
+
/* @__PURE__ */ jsx35(ReportMeta, {})
|
|
1574
1752
|
] });
|
|
1575
1753
|
}
|
|
1576
1754
|
function ReportErrorShell({
|
|
@@ -1579,28 +1757,28 @@ function ReportErrorShell({
|
|
|
1579
1757
|
title,
|
|
1580
1758
|
dataTheme
|
|
1581
1759
|
}) {
|
|
1582
|
-
return /* @__PURE__ */
|
|
1760
|
+
return /* @__PURE__ */ jsx35("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx35(ReportSchemaError, { error }) });
|
|
1583
1761
|
}
|
|
1584
1762
|
|
|
1585
1763
|
// src/components/Report.tsx
|
|
1586
|
-
import { jsx as
|
|
1764
|
+
import { jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1587
1765
|
function Report(props) {
|
|
1588
1766
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1589
1767
|
const result = unwrapReport(report);
|
|
1590
1768
|
if (!result.ok) {
|
|
1591
|
-
return /* @__PURE__ */
|
|
1769
|
+
return /* @__PURE__ */ jsx36(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1592
1770
|
}
|
|
1593
1771
|
const data = result.data;
|
|
1594
1772
|
const hasContent = data.features.length > 0;
|
|
1595
|
-
return /* @__PURE__ */
|
|
1596
|
-
/* @__PURE__ */
|
|
1597
|
-
hasContent ? /* @__PURE__ */
|
|
1773
|
+
return /* @__PURE__ */ jsx36(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ jsxs23("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1774
|
+
/* @__PURE__ */ jsx36("header", { className: "es-report-header", children: /* @__PURE__ */ jsx36(ReportTitleBlock, { title }) }),
|
|
1775
|
+
hasContent ? /* @__PURE__ */ jsx36(ReportFeatureList, {}) : /* @__PURE__ */ jsx36(ReportEmpty, {})
|
|
1598
1776
|
] }) });
|
|
1599
1777
|
}
|
|
1600
1778
|
|
|
1601
1779
|
// src/components/doc/MermaidView.tsx
|
|
1602
1780
|
import { useEffect, useRef, useState as useState2 } from "react";
|
|
1603
|
-
import { jsx as
|
|
1781
|
+
import { Fragment as Fragment11, jsx as jsx37, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1604
1782
|
function prefersDark(el) {
|
|
1605
1783
|
const themed = el?.closest("[data-theme]");
|
|
1606
1784
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -1610,21 +1788,38 @@ function prefersDark(el) {
|
|
|
1610
1788
|
function MermaidView({ entry, load }) {
|
|
1611
1789
|
const ref = useRef(null);
|
|
1612
1790
|
const [svg, setSvg] = useState2(null);
|
|
1791
|
+
const [error, setError] = useState2(null);
|
|
1613
1792
|
useEffect(() => {
|
|
1614
1793
|
let cancelled = false;
|
|
1615
1794
|
const draw = async () => {
|
|
1795
|
+
let mermaid;
|
|
1796
|
+
try {
|
|
1797
|
+
mermaid = await load();
|
|
1798
|
+
} catch {
|
|
1799
|
+
if (!cancelled) {
|
|
1800
|
+
setSvg(null);
|
|
1801
|
+
setError(null);
|
|
1802
|
+
}
|
|
1803
|
+
return;
|
|
1804
|
+
}
|
|
1616
1805
|
try {
|
|
1617
|
-
const mermaid = await load();
|
|
1618
1806
|
mermaid.initialize({
|
|
1619
1807
|
startOnLoad: false,
|
|
1620
1808
|
securityLevel: "strict",
|
|
1621
1809
|
theme: prefersDark(ref.current) ? "dark" : "default"
|
|
1622
1810
|
});
|
|
1811
|
+
await mermaid.parse(entry.code);
|
|
1623
1812
|
const id = `es-mermaid-${Math.random().toString(36).slice(2)}`;
|
|
1624
1813
|
const { svg: rendered } = await mermaid.render(id, entry.code);
|
|
1625
|
-
if (!cancelled)
|
|
1626
|
-
|
|
1627
|
-
|
|
1814
|
+
if (!cancelled) {
|
|
1815
|
+
setSvg(rendered);
|
|
1816
|
+
setError(null);
|
|
1817
|
+
}
|
|
1818
|
+
} catch (err2) {
|
|
1819
|
+
if (!cancelled) {
|
|
1820
|
+
setSvg(null);
|
|
1821
|
+
setError(err2 instanceof Error ? err2.message : String(err2));
|
|
1822
|
+
}
|
|
1628
1823
|
}
|
|
1629
1824
|
};
|
|
1630
1825
|
void draw();
|
|
@@ -1637,9 +1832,9 @@ function MermaidView({ entry, load }) {
|
|
|
1637
1832
|
};
|
|
1638
1833
|
}, [entry.code, load]);
|
|
1639
1834
|
if (svg) {
|
|
1640
|
-
return /* @__PURE__ */
|
|
1641
|
-
entry.title ? /* @__PURE__ */
|
|
1642
|
-
/* @__PURE__ */
|
|
1835
|
+
return /* @__PURE__ */ jsxs24("figure", { ref, className: "my-3", children: [
|
|
1836
|
+
entry.title ? /* @__PURE__ */ jsx37("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
1837
|
+
/* @__PURE__ */ jsx37(
|
|
1643
1838
|
"div",
|
|
1644
1839
|
{
|
|
1645
1840
|
role: "img",
|
|
@@ -1650,18 +1845,32 @@ function MermaidView({ entry, load }) {
|
|
|
1650
1845
|
)
|
|
1651
1846
|
] });
|
|
1652
1847
|
}
|
|
1653
|
-
return /* @__PURE__ */
|
|
1848
|
+
return /* @__PURE__ */ jsxs24(Fragment11, { children: [
|
|
1849
|
+
error ? /* @__PURE__ */ jsxs24(
|
|
1850
|
+
"p",
|
|
1851
|
+
{
|
|
1852
|
+
role: "alert",
|
|
1853
|
+
"data-es-mermaid-error": true,
|
|
1854
|
+
className: "mt-3 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",
|
|
1855
|
+
children: [
|
|
1856
|
+
"Diagram failed to render: ",
|
|
1857
|
+
error
|
|
1858
|
+
]
|
|
1859
|
+
}
|
|
1860
|
+
) : null,
|
|
1861
|
+
/* @__PURE__ */ jsx37(MermaidSource, { entry, ref })
|
|
1862
|
+
] });
|
|
1654
1863
|
}
|
|
1655
1864
|
|
|
1656
1865
|
// src/components/doc/MermaidDiagram.tsx
|
|
1657
|
-
import { jsx as
|
|
1866
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
1658
1867
|
var mermaidLoader;
|
|
1659
1868
|
function loadMermaid() {
|
|
1660
1869
|
mermaidLoader ??= import("mermaid").then((m) => m.default);
|
|
1661
1870
|
return mermaidLoader;
|
|
1662
1871
|
}
|
|
1663
1872
|
function MermaidDiagram({ entry, load = loadMermaid }) {
|
|
1664
|
-
return /* @__PURE__ */
|
|
1873
|
+
return /* @__PURE__ */ jsx38(MermaidView, { entry, load });
|
|
1665
1874
|
}
|
|
1666
1875
|
|
|
1667
1876
|
// src/components/ScenarioExplorer.tsx
|
|
@@ -1671,12 +1880,12 @@ import { useState as useState3 } from "react";
|
|
|
1671
1880
|
import "react";
|
|
1672
1881
|
import { Command as CommandPrimitive } from "cmdk";
|
|
1673
1882
|
import { SearchIcon } from "lucide-react";
|
|
1674
|
-
import { jsx as
|
|
1883
|
+
import { jsx as jsx39, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1675
1884
|
function Command({
|
|
1676
1885
|
className,
|
|
1677
1886
|
...props
|
|
1678
1887
|
}) {
|
|
1679
|
-
return /* @__PURE__ */
|
|
1888
|
+
return /* @__PURE__ */ jsx39(
|
|
1680
1889
|
CommandPrimitive,
|
|
1681
1890
|
{
|
|
1682
1891
|
"data-slot": "command",
|
|
@@ -1692,14 +1901,14 @@ function CommandInput({
|
|
|
1692
1901
|
className,
|
|
1693
1902
|
...props
|
|
1694
1903
|
}) {
|
|
1695
|
-
return /* @__PURE__ */
|
|
1904
|
+
return /* @__PURE__ */ jsxs25(
|
|
1696
1905
|
"div",
|
|
1697
1906
|
{
|
|
1698
1907
|
"data-slot": "command-input-wrapper",
|
|
1699
1908
|
className: "flex h-9 items-center gap-2 border-b px-3",
|
|
1700
1909
|
children: [
|
|
1701
|
-
/* @__PURE__ */
|
|
1702
|
-
/* @__PURE__ */
|
|
1910
|
+
/* @__PURE__ */ jsx39(SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
|
|
1911
|
+
/* @__PURE__ */ jsx39(
|
|
1703
1912
|
CommandPrimitive.Input,
|
|
1704
1913
|
{
|
|
1705
1914
|
"data-slot": "command-input",
|
|
@@ -1718,7 +1927,7 @@ function CommandList({
|
|
|
1718
1927
|
className,
|
|
1719
1928
|
...props
|
|
1720
1929
|
}) {
|
|
1721
|
-
return /* @__PURE__ */
|
|
1930
|
+
return /* @__PURE__ */ jsx39(
|
|
1722
1931
|
CommandPrimitive.List,
|
|
1723
1932
|
{
|
|
1724
1933
|
"data-slot": "command-list",
|
|
@@ -1733,7 +1942,7 @@ function CommandList({
|
|
|
1733
1942
|
function CommandEmpty({
|
|
1734
1943
|
...props
|
|
1735
1944
|
}) {
|
|
1736
|
-
return /* @__PURE__ */
|
|
1945
|
+
return /* @__PURE__ */ jsx39(
|
|
1737
1946
|
CommandPrimitive.Empty,
|
|
1738
1947
|
{
|
|
1739
1948
|
"data-slot": "command-empty",
|
|
@@ -1746,7 +1955,7 @@ function CommandGroup({
|
|
|
1746
1955
|
className,
|
|
1747
1956
|
...props
|
|
1748
1957
|
}) {
|
|
1749
|
-
return /* @__PURE__ */
|
|
1958
|
+
return /* @__PURE__ */ jsx39(
|
|
1750
1959
|
CommandPrimitive.Group,
|
|
1751
1960
|
{
|
|
1752
1961
|
"data-slot": "command-group",
|
|
@@ -1762,7 +1971,7 @@ function CommandItem({
|
|
|
1762
1971
|
className,
|
|
1763
1972
|
...props
|
|
1764
1973
|
}) {
|
|
1765
|
-
return /* @__PURE__ */
|
|
1974
|
+
return /* @__PURE__ */ jsx39(
|
|
1766
1975
|
CommandPrimitive.Item,
|
|
1767
1976
|
{
|
|
1768
1977
|
"data-slot": "command-item",
|
|
@@ -1776,7 +1985,7 @@ function CommandItem({
|
|
|
1776
1985
|
}
|
|
1777
1986
|
|
|
1778
1987
|
// src/components/ScenarioExplorer.tsx
|
|
1779
|
-
import { jsx as
|
|
1988
|
+
import { jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1780
1989
|
var STATUS_FILTERS = [
|
|
1781
1990
|
{ value: "all", label: "All" },
|
|
1782
1991
|
{ value: "passed", label: "Passed" },
|
|
@@ -1787,22 +1996,22 @@ var STATUS_FILTERS = [
|
|
|
1787
1996
|
function ScenarioExplorer({ scenarios, summary }) {
|
|
1788
1997
|
const [status, setStatus] = useState3("all");
|
|
1789
1998
|
const visible = status === "all" ? scenarios : scenarios.filter((s) => s.status === status);
|
|
1790
|
-
return /* @__PURE__ */
|
|
1791
|
-
summary ? /* @__PURE__ */
|
|
1999
|
+
return /* @__PURE__ */ jsxs26("div", { className: "font-sans text-foreground", children: [
|
|
2000
|
+
summary ? /* @__PURE__ */ jsxs26("p", { className: "mb-3 text-sm text-muted-foreground", children: [
|
|
1792
2001
|
summary.total,
|
|
1793
2002
|
" scenarios \xB7 ",
|
|
1794
|
-
/* @__PURE__ */
|
|
2003
|
+
/* @__PURE__ */ jsxs26("span", { className: "text-pass", children: [
|
|
1795
2004
|
summary.passed,
|
|
1796
2005
|
" passed"
|
|
1797
2006
|
] }),
|
|
1798
2007
|
" \xB7",
|
|
1799
2008
|
" ",
|
|
1800
|
-
/* @__PURE__ */
|
|
2009
|
+
/* @__PURE__ */ jsxs26("span", { className: "text-fail", children: [
|
|
1801
2010
|
summary.failed,
|
|
1802
2011
|
" failed"
|
|
1803
2012
|
] })
|
|
1804
2013
|
] }) : null,
|
|
1805
|
-
/* @__PURE__ */
|
|
2014
|
+
/* @__PURE__ */ jsx40("div", { className: "mb-2 flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by status", children: STATUS_FILTERS.map((f) => /* @__PURE__ */ jsx40(
|
|
1806
2015
|
"button",
|
|
1807
2016
|
{
|
|
1808
2017
|
type: "button",
|
|
@@ -1817,26 +2026,26 @@ function ScenarioExplorer({ scenarios, summary }) {
|
|
|
1817
2026
|
},
|
|
1818
2027
|
f.value
|
|
1819
2028
|
)) }),
|
|
1820
|
-
/* @__PURE__ */
|
|
2029
|
+
/* @__PURE__ */ jsxs26(
|
|
1821
2030
|
Command,
|
|
1822
2031
|
{
|
|
1823
2032
|
className: "rounded-lg border border-border bg-card",
|
|
1824
2033
|
filter: (value, search) => value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0,
|
|
1825
2034
|
children: [
|
|
1826
|
-
/* @__PURE__ */
|
|
1827
|
-
/* @__PURE__ */
|
|
1828
|
-
/* @__PURE__ */
|
|
1829
|
-
/* @__PURE__ */
|
|
2035
|
+
/* @__PURE__ */ jsx40(CommandInput, { placeholder: "Search scenarios\u2026" }),
|
|
2036
|
+
/* @__PURE__ */ jsxs26(CommandList, { className: "max-h-none", children: [
|
|
2037
|
+
/* @__PURE__ */ jsx40(CommandEmpty, { children: "No scenarios match your filters." }),
|
|
2038
|
+
/* @__PURE__ */ jsx40(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ jsx40(
|
|
1830
2039
|
CommandItem,
|
|
1831
2040
|
{
|
|
1832
2041
|
value: `${s.title} ${s.feature} ${s.tags.join(" ")}`,
|
|
1833
2042
|
asChild: true,
|
|
1834
2043
|
className: "cursor-pointer",
|
|
1835
|
-
children: /* @__PURE__ */
|
|
1836
|
-
/* @__PURE__ */
|
|
1837
|
-
/* @__PURE__ */
|
|
1838
|
-
s.tags.slice(0, 3).map((t) => /* @__PURE__ */
|
|
1839
|
-
/* @__PURE__ */
|
|
2044
|
+
children: /* @__PURE__ */ jsxs26("a", { href: s.href, className: "flex items-center gap-3", children: [
|
|
2045
|
+
/* @__PURE__ */ jsx40(Badge, { variant: s.status, children: s.status }),
|
|
2046
|
+
/* @__PURE__ */ jsx40("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
|
|
2047
|
+
s.tags.slice(0, 3).map((t) => /* @__PURE__ */ jsx40(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
|
|
2048
|
+
/* @__PURE__ */ jsx40("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
|
|
1840
2049
|
] })
|
|
1841
2050
|
},
|
|
1842
2051
|
s.id
|
|
@@ -2858,6 +3067,8 @@ function parseStoryReport(input) {
|
|
|
2858
3067
|
});
|
|
2859
3068
|
}
|
|
2860
3069
|
export {
|
|
3070
|
+
DATA_MODEL_TYPE,
|
|
3071
|
+
DataModelBlock,
|
|
2861
3072
|
DocCode,
|
|
2862
3073
|
DocCustom,
|
|
2863
3074
|
DocEntry,
|
|
@@ -2871,6 +3082,8 @@ export {
|
|
|
2871
3082
|
DocTable,
|
|
2872
3083
|
DocTag,
|
|
2873
3084
|
DocVideo,
|
|
3085
|
+
FILE_TREE_TYPE,
|
|
3086
|
+
FileTreeBlock,
|
|
2874
3087
|
MermaidDiagram,
|
|
2875
3088
|
MermaidSource,
|
|
2876
3089
|
Report,
|
|
@@ -2900,7 +3113,10 @@ export {
|
|
|
2900
3113
|
err,
|
|
2901
3114
|
formatRelativeAge,
|
|
2902
3115
|
isReportStale,
|
|
3116
|
+
narrativeBlockRenderers,
|
|
2903
3117
|
ok,
|
|
3118
|
+
parseDataModel,
|
|
3119
|
+
parseFileTree,
|
|
2904
3120
|
parseStoryReport,
|
|
2905
3121
|
prUrl,
|
|
2906
3122
|
reportLastRunMs,
|