executable-stories-react 0.9.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +540 -483
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -235
- package/dist/index.d.ts +50 -235
- package/dist/index.js +525 -475
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +615 -689
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +1 -233
- package/dist/interactive.d.ts +1 -233
- package/dist/interactive.js +607 -681
- package/dist/interactive.js.map +1 -1
- package/dist/parse.d.cts +3 -234
- package/dist/parse.d.ts +3 -234
- package/dist/report-island.global.js +28 -28
- package/dist/ssr.cjs +492 -449
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.d.cts +1 -232
- package/dist/ssr.d.ts +1 -232
- package/dist/ssr.js +484 -441
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +4 -4
package/dist/ssr.cjs
CHANGED
|
@@ -42,63 +42,6 @@ var import_react2 = require("react");
|
|
|
42
42
|
var import_react = require("react");
|
|
43
43
|
var ReportContext = (0, import_react.createContext)(null);
|
|
44
44
|
|
|
45
|
-
// src/context/ReportRoot.tsx
|
|
46
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
47
|
-
var EMPTY_CUSTOM = {};
|
|
48
|
-
var EMPTY_RENDERERS = {};
|
|
49
|
-
function ReportRoot({
|
|
50
|
-
report,
|
|
51
|
-
customRenderers,
|
|
52
|
-
renderers,
|
|
53
|
-
children
|
|
54
|
-
}) {
|
|
55
|
-
const value = (0, import_react2.useMemo)(
|
|
56
|
-
() => ({
|
|
57
|
-
report,
|
|
58
|
-
customRenderers: customRenderers ?? EMPTY_CUSTOM,
|
|
59
|
-
renderers: renderers ?? EMPTY_RENDERERS
|
|
60
|
-
}),
|
|
61
|
-
[report, customRenderers, renderers]
|
|
62
|
-
);
|
|
63
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReportContext.Provider, { value, children });
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// src/hooks/useReport.ts
|
|
67
|
-
var import_react3 = require("react");
|
|
68
|
-
function useReport() {
|
|
69
|
-
const ctx = (0, import_react3.useContext)(ReportContext);
|
|
70
|
-
if (!ctx) {
|
|
71
|
-
throw new Error(
|
|
72
|
-
"useReport must be used inside <ReportRoot> or <Report>. Wrap your tree with one of those."
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
return ctx.report;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// ../executable-stories-core/dist/utils/duration.js
|
|
79
|
-
function formatDuration(ms) {
|
|
80
|
-
if (ms < 1e3) {
|
|
81
|
-
return `${Math.round(ms)} ms`;
|
|
82
|
-
}
|
|
83
|
-
if (ms < 6e4) {
|
|
84
|
-
return `${(ms / 1e3).toFixed(2)} s`;
|
|
85
|
-
}
|
|
86
|
-
const minutes = Math.floor(ms / 6e4);
|
|
87
|
-
const seconds = Math.floor(ms % 6e4 / 1e3);
|
|
88
|
-
if (minutes < 60) {
|
|
89
|
-
return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
90
|
-
}
|
|
91
|
-
const hours = Math.floor(minutes / 60);
|
|
92
|
-
const remainingMinutes = minutes % 60;
|
|
93
|
-
return `${hours}h ${remainingMinutes}m`;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// src/components/doc/DocNote.tsx
|
|
97
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
98
|
-
function DocNote({ entry }) {
|
|
99
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
|
|
100
|
-
}
|
|
101
|
-
|
|
102
45
|
// src/components/ui/badge.tsx
|
|
103
46
|
var React = require("react");
|
|
104
47
|
var import_class_variance_authority = require("class-variance-authority");
|
|
@@ -157,14 +100,237 @@ function Badge({
|
|
|
157
100
|
});
|
|
158
101
|
}
|
|
159
102
|
|
|
160
|
-
// src/components/doc/
|
|
103
|
+
// src/components/doc/NarrativeBlocks.tsx
|
|
104
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
105
|
+
var FILE_TREE_TYPE = "file-tree";
|
|
106
|
+
var DATA_MODEL_TYPE = "data-model";
|
|
107
|
+
function isChangeKind(value) {
|
|
108
|
+
return value === "added" || value === "modified" || value === "removed" || value === "renamed";
|
|
109
|
+
}
|
|
110
|
+
function isRecord(value) {
|
|
111
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
112
|
+
}
|
|
113
|
+
function str(value) {
|
|
114
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
115
|
+
}
|
|
116
|
+
function AuthoredMarker({ authored }) {
|
|
117
|
+
if (authored !== "agent") return null;
|
|
118
|
+
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" });
|
|
119
|
+
}
|
|
120
|
+
function BlockFrame({
|
|
121
|
+
title,
|
|
122
|
+
authored,
|
|
123
|
+
children
|
|
124
|
+
}) {
|
|
125
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("figure", { className: "my-3", children: [
|
|
126
|
+
title || authored === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("figcaption", { className: "mb-1.5 flex flex-wrap items-center gap-2", children: [
|
|
127
|
+
title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs font-medium text-muted-foreground", children: title }) : null,
|
|
128
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AuthoredMarker, { authored })
|
|
129
|
+
] }) : null,
|
|
130
|
+
children
|
|
131
|
+
] });
|
|
132
|
+
}
|
|
133
|
+
function ChangeBadge({ change }) {
|
|
134
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "tag", className: "text-[10px]", children: change });
|
|
135
|
+
}
|
|
136
|
+
function parseFileTree(data) {
|
|
137
|
+
if (!isRecord(data) || !Array.isArray(data.files)) return void 0;
|
|
138
|
+
const files = [];
|
|
139
|
+
for (const raw of data.files) {
|
|
140
|
+
if (typeof raw === "string") {
|
|
141
|
+
if (raw) files.push({ path: raw });
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (!isRecord(raw)) continue;
|
|
145
|
+
const path = str(raw.path);
|
|
146
|
+
if (!path) continue;
|
|
147
|
+
files.push({
|
|
148
|
+
path,
|
|
149
|
+
change: isChangeKind(raw.change) ? raw.change : void 0,
|
|
150
|
+
note: str(raw.note)
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (files.length === 0) return void 0;
|
|
154
|
+
return { title: str(data.title), authored: str(data.authored), files };
|
|
155
|
+
}
|
|
156
|
+
function buildTree(files) {
|
|
157
|
+
const root = { name: "", children: /* @__PURE__ */ new Map() };
|
|
158
|
+
for (const file of files) {
|
|
159
|
+
const segments = file.path.split("/").filter(Boolean);
|
|
160
|
+
let node = root;
|
|
161
|
+
segments.forEach((segment, index) => {
|
|
162
|
+
let child = node.children.get(segment);
|
|
163
|
+
if (!child) {
|
|
164
|
+
child = { name: segment, children: /* @__PURE__ */ new Map() };
|
|
165
|
+
node.children.set(segment, child);
|
|
166
|
+
}
|
|
167
|
+
if (index === segments.length - 1) child.file = file;
|
|
168
|
+
node = child;
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
return root;
|
|
172
|
+
}
|
|
173
|
+
function sortedChildren(node) {
|
|
174
|
+
return [...node.children.values()].sort((a, b) => {
|
|
175
|
+
const aDir = a.children.size > 0;
|
|
176
|
+
const bDir = b.children.size > 0;
|
|
177
|
+
if (aDir !== bDir) return aDir ? -1 : 1;
|
|
178
|
+
return a.name.localeCompare(b.name);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
function TreeBranch({ node, depth }) {
|
|
182
|
+
const children = sortedChildren(node);
|
|
183
|
+
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) => {
|
|
184
|
+
const isDir = child.children.size > 0;
|
|
185
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
|
|
186
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-baseline gap-2", children: [
|
|
187
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
188
|
+
"span",
|
|
189
|
+
{
|
|
190
|
+
className: cn(
|
|
191
|
+
"font-mono text-xs",
|
|
192
|
+
isDir ? "text-muted-foreground" : "text-foreground"
|
|
193
|
+
),
|
|
194
|
+
children: isDir ? `${child.name}/` : child.name
|
|
195
|
+
}
|
|
196
|
+
),
|
|
197
|
+
child.file?.change ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeBadge, { change: child.file.change }) : null,
|
|
198
|
+
child.file?.note ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs text-muted-foreground", children: child.file.note }) : null
|
|
199
|
+
] }),
|
|
200
|
+
isDir ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TreeBranch, { node: child, depth: depth + 1 }) : null
|
|
201
|
+
] }, child.name);
|
|
202
|
+
}) });
|
|
203
|
+
}
|
|
204
|
+
function FileTreeBlock({ entry }) {
|
|
205
|
+
const data = parseFileTree(entry.data);
|
|
206
|
+
if (!data) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UnreadableBlock, { entry });
|
|
207
|
+
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 }) }) });
|
|
208
|
+
}
|
|
209
|
+
function parseDataModel(data) {
|
|
210
|
+
if (!isRecord(data) || !Array.isArray(data.fields)) return void 0;
|
|
211
|
+
const fields = [];
|
|
212
|
+
for (const raw of data.fields) {
|
|
213
|
+
if (!isRecord(raw)) continue;
|
|
214
|
+
const name = str(raw.name);
|
|
215
|
+
if (!name) continue;
|
|
216
|
+
fields.push({
|
|
217
|
+
name,
|
|
218
|
+
type: str(raw.type),
|
|
219
|
+
note: str(raw.note),
|
|
220
|
+
change: isChangeKind(raw.change) ? raw.change : void 0
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
if (fields.length === 0) return void 0;
|
|
224
|
+
return {
|
|
225
|
+
title: str(data.title),
|
|
226
|
+
authored: str(data.authored),
|
|
227
|
+
name: str(data.name),
|
|
228
|
+
fields
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function DataModelBlock({ entry }) {
|
|
232
|
+
const data = parseDataModel(entry.data);
|
|
233
|
+
if (!data) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UnreadableBlock, { entry });
|
|
234
|
+
const hasNotes = data.fields.some((f) => f.note);
|
|
235
|
+
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: [
|
|
236
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: "bg-muted/50", children: [
|
|
237
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Field" }),
|
|
238
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Type" }),
|
|
239
|
+
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
|
|
240
|
+
] }) }),
|
|
241
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: data.fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
|
|
242
|
+
/* @__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: [
|
|
243
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-mono text-xs text-foreground", children: field.name }),
|
|
244
|
+
field.change ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeBadge, { change: field.change }) : null
|
|
245
|
+
] }) }),
|
|
246
|
+
/* @__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 ?? "" }),
|
|
247
|
+
hasNotes ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: field.note ?? "" }) : null
|
|
248
|
+
] }, field.name)) })
|
|
249
|
+
] }) }) });
|
|
250
|
+
}
|
|
251
|
+
function UnreadableBlock({ entry }) {
|
|
252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
|
|
253
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: [
|
|
254
|
+
entry.type,
|
|
255
|
+
" (unrecognised shape)"
|
|
256
|
+
] }),
|
|
257
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
258
|
+
"pre",
|
|
259
|
+
{
|
|
260
|
+
tabIndex: 0,
|
|
261
|
+
className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground",
|
|
262
|
+
children: safeStringify(entry.data)
|
|
263
|
+
}
|
|
264
|
+
)
|
|
265
|
+
] });
|
|
266
|
+
}
|
|
267
|
+
function safeStringify(value) {
|
|
268
|
+
try {
|
|
269
|
+
return JSON.stringify(value, null, 2);
|
|
270
|
+
} catch {
|
|
271
|
+
return String(value);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
var narrativeBlockRenderers = {
|
|
275
|
+
[FILE_TREE_TYPE]: (entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileTreeBlock, { entry }),
|
|
276
|
+
[DATA_MODEL_TYPE]: (entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DataModelBlock, { entry })
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// src/context/ReportRoot.tsx
|
|
280
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
281
|
+
var EMPTY_RENDERERS = {};
|
|
282
|
+
function ReportRoot({
|
|
283
|
+
report,
|
|
284
|
+
customRenderers,
|
|
285
|
+
renderers,
|
|
286
|
+
children
|
|
287
|
+
}) {
|
|
288
|
+
const value = (0, import_react2.useMemo)(
|
|
289
|
+
() => ({
|
|
290
|
+
report,
|
|
291
|
+
// Narrative blocks render everywhere the report does (static SSR, the
|
|
292
|
+
// island, Astro) without every host wiring them up. A host renderer for
|
|
293
|
+
// the same type still wins.
|
|
294
|
+
customRenderers: { ...narrativeBlockRenderers, ...customRenderers },
|
|
295
|
+
renderers: renderers ?? EMPTY_RENDERERS
|
|
296
|
+
}),
|
|
297
|
+
[report, customRenderers, renderers]
|
|
298
|
+
);
|
|
299
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReportContext.Provider, { value, children });
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// src/hooks/useReport.ts
|
|
303
|
+
var import_react3 = require("react");
|
|
304
|
+
function useReport() {
|
|
305
|
+
const ctx = (0, import_react3.useContext)(ReportContext);
|
|
306
|
+
if (!ctx) {
|
|
307
|
+
throw new Error(
|
|
308
|
+
"useReport must be used inside <ReportRoot> or <Report>. Wrap your tree with one of those."
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
return ctx.report;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// src/components/ReportScenario.tsx
|
|
315
|
+
var import_duration3 = require("executable-stories-core/utils/duration");
|
|
316
|
+
|
|
317
|
+
// src/components/ReportSteps.tsx
|
|
318
|
+
var import_duration = require("executable-stories-core/utils/duration");
|
|
319
|
+
|
|
320
|
+
// src/components/doc/DocNote.tsx
|
|
161
321
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
322
|
+
function DocNote({ entry }) {
|
|
323
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// src/components/doc/DocTag.tsx
|
|
327
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
162
328
|
function DocTag({ entry }) {
|
|
163
|
-
return /* @__PURE__ */ (0,
|
|
329
|
+
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)) });
|
|
164
330
|
}
|
|
165
331
|
|
|
166
332
|
// src/components/doc/DocKv.tsx
|
|
167
|
-
var
|
|
333
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
168
334
|
function formatValue(value) {
|
|
169
335
|
if (value === null) return "null";
|
|
170
336
|
if (typeof value === "string") return value;
|
|
@@ -176,19 +342,19 @@ function formatValue(value) {
|
|
|
176
342
|
}
|
|
177
343
|
}
|
|
178
344
|
function DocKv({ entry }) {
|
|
179
|
-
return /* @__PURE__ */ (0,
|
|
180
|
-
/* @__PURE__ */ (0,
|
|
181
|
-
/* @__PURE__ */ (0,
|
|
345
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
|
|
346
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { className: "font-semibold text-muted-foreground", children: entry.label }),
|
|
347
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { className: "font-mono text-foreground", children: formatValue(entry.value) })
|
|
182
348
|
] });
|
|
183
349
|
}
|
|
184
350
|
|
|
185
351
|
// src/hooks/useRenderers.ts
|
|
186
352
|
var import_react4 = require("react");
|
|
187
|
-
var
|
|
353
|
+
var EMPTY_CUSTOM = {};
|
|
188
354
|
var EMPTY_RENDERERS2 = {};
|
|
189
355
|
function useCustomRenderers() {
|
|
190
356
|
const ctx = (0, import_react4.useContext)(ReportContext);
|
|
191
|
-
return ctx?.customRenderers ??
|
|
357
|
+
return ctx?.customRenderers ?? EMPTY_CUSTOM;
|
|
192
358
|
}
|
|
193
359
|
function useBuiltinRenderers() {
|
|
194
360
|
const ctx = (0, import_react4.useContext)(ReportContext);
|
|
@@ -196,37 +362,37 @@ function useBuiltinRenderers() {
|
|
|
196
362
|
}
|
|
197
363
|
|
|
198
364
|
// src/components/doc/DocCode.tsx
|
|
199
|
-
var
|
|
365
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
200
366
|
function CodeFigure({ label, children }) {
|
|
201
|
-
return /* @__PURE__ */ (0,
|
|
202
|
-
label ? /* @__PURE__ */ (0,
|
|
203
|
-
/* @__PURE__ */ (0,
|
|
367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("figure", { className: "my-3", children: [
|
|
368
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: label }) : null,
|
|
369
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3", children })
|
|
204
370
|
] });
|
|
205
371
|
}
|
|
206
372
|
function DocCode({ entry }) {
|
|
207
373
|
const renderers = useBuiltinRenderers();
|
|
208
374
|
if (renderers.code) {
|
|
209
|
-
return /* @__PURE__ */ (0,
|
|
375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: renderers.code(entry) });
|
|
210
376
|
}
|
|
211
|
-
return /* @__PURE__ */ (0,
|
|
377
|
+
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 }) });
|
|
212
378
|
}
|
|
213
379
|
|
|
214
380
|
// src/components/doc/DocTable.tsx
|
|
215
|
-
var
|
|
381
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
216
382
|
function DocTable({ entry }) {
|
|
217
|
-
return /* @__PURE__ */ (0,
|
|
218
|
-
entry.label ? /* @__PURE__ */ (0,
|
|
219
|
-
/* @__PURE__ */ (0,
|
|
220
|
-
/* @__PURE__ */ (0,
|
|
221
|
-
/* @__PURE__ */ (0,
|
|
383
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("figure", { className: "my-3", children: [
|
|
384
|
+
entry.label ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.label }) : null,
|
|
385
|
+
/* @__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: [
|
|
386
|
+
/* @__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)) }) }),
|
|
387
|
+
/* @__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)) })
|
|
222
388
|
] }) })
|
|
223
389
|
] });
|
|
224
390
|
}
|
|
225
391
|
|
|
226
392
|
// src/components/doc/DocLink.tsx
|
|
227
|
-
var
|
|
393
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
228
394
|
function DocLink({ entry }) {
|
|
229
|
-
return /* @__PURE__ */ (0,
|
|
395
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
230
396
|
"a",
|
|
231
397
|
{
|
|
232
398
|
className: "text-sm font-medium text-primary underline underline-offset-2 hover:no-underline",
|
|
@@ -241,28 +407,13 @@ function DocLink({ entry }) {
|
|
|
241
407
|
// src/components/doc/DocSection.tsx
|
|
242
408
|
var import_marked = require("marked");
|
|
243
409
|
|
|
244
|
-
//
|
|
245
|
-
|
|
246
|
-
if (!value) return void 0;
|
|
247
|
-
const trimmed = value.trim();
|
|
248
|
-
const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(trimmed);
|
|
249
|
-
if (scheme && !/^https?$/i.test(scheme[1] ?? "")) return void 0;
|
|
250
|
-
return trimmed;
|
|
251
|
-
}
|
|
252
|
-
function safeImageUrl(value) {
|
|
253
|
-
if (!value) return void 0;
|
|
254
|
-
const trimmed = value.trim();
|
|
255
|
-
if (/^data:image\//i.test(trimmed)) return trimmed;
|
|
256
|
-
return safeUrl(trimmed);
|
|
257
|
-
}
|
|
258
|
-
function isLocalFsPath(value) {
|
|
259
|
-
return /^(?:[/\\]|[A-Za-z]:[/\\])/.test(value);
|
|
260
|
-
}
|
|
410
|
+
// src/lib/url.ts
|
|
411
|
+
var import_url = require("executable-stories-core/utils/url");
|
|
261
412
|
|
|
262
413
|
// src/components/doc/DocSection.tsx
|
|
263
|
-
var
|
|
414
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
264
415
|
function neutralizeUrl(value) {
|
|
265
|
-
return safeUrl(value) ?? "#";
|
|
416
|
+
return (0, import_url.safeUrl)(value) ?? "#";
|
|
266
417
|
}
|
|
267
418
|
function safeMarkdownHtml(markdown) {
|
|
268
419
|
const raw = import_marked.marked.parse(markdown, { async: false });
|
|
@@ -271,12 +422,12 @@ function safeMarkdownHtml(markdown) {
|
|
|
271
422
|
function DocSection({ entry }) {
|
|
272
423
|
const renderers = useBuiltinRenderers();
|
|
273
424
|
if (renderers.section) {
|
|
274
|
-
return /* @__PURE__ */ (0,
|
|
425
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: renderers.section(entry) });
|
|
275
426
|
}
|
|
276
427
|
const html = safeMarkdownHtml(entry.markdown);
|
|
277
|
-
return /* @__PURE__ */ (0,
|
|
278
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
279
|
-
/* @__PURE__ */ (0,
|
|
428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("section", { className: "my-3 text-sm", "aria-label": entry.title, children: [
|
|
429
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h4", { className: "mb-1 font-semibold text-foreground", children: entry.title }) : null,
|
|
430
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
280
431
|
"div",
|
|
281
432
|
{
|
|
282
433
|
className: "es-doc-prose prose prose-sm max-w-none",
|
|
@@ -287,11 +438,11 @@ function DocSection({ entry }) {
|
|
|
287
438
|
}
|
|
288
439
|
|
|
289
440
|
// src/components/doc/DocMermaid.tsx
|
|
290
|
-
var
|
|
441
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
291
442
|
function MermaidSource({ entry, ref }) {
|
|
292
|
-
return /* @__PURE__ */ (0,
|
|
293
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
294
|
-
/* @__PURE__ */ (0,
|
|
443
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("figure", { ref, className: "my-3", "aria-label": entry.title ?? "Diagram", children: [
|
|
444
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
445
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
295
446
|
"pre",
|
|
296
447
|
{
|
|
297
448
|
"data-mermaid": true,
|
|
@@ -305,24 +456,24 @@ function MermaidSource({ entry, ref }) {
|
|
|
305
456
|
function DocMermaid({ entry }) {
|
|
306
457
|
const renderers = useBuiltinRenderers();
|
|
307
458
|
if (renderers.mermaid) {
|
|
308
|
-
return /* @__PURE__ */ (0,
|
|
459
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: renderers.mermaid(entry) });
|
|
309
460
|
}
|
|
310
|
-
return /* @__PURE__ */ (0,
|
|
461
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MermaidSource, { entry });
|
|
311
462
|
}
|
|
312
463
|
|
|
313
464
|
// src/components/doc/DocScreenshot.tsx
|
|
314
|
-
var
|
|
465
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
315
466
|
function DocScreenshot({ entry }) {
|
|
316
|
-
const src = isLocalFsPath(entry.path) ? void 0 : safeImageUrl(entry.path);
|
|
467
|
+
const src = (0, import_url.isLocalFsPath)(entry.path) ? void 0 : (0, import_url.safeImageUrl)(entry.path);
|
|
317
468
|
if (!src) {
|
|
318
|
-
return /* @__PURE__ */ (0,
|
|
319
|
-
/* @__PURE__ */ (0,
|
|
320
|
-
/* @__PURE__ */ (0,
|
|
321
|
-
entry.alt ? /* @__PURE__ */ (0,
|
|
469
|
+
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: [
|
|
470
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "font-medium", children: "Screenshot unavailable" }),
|
|
471
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
472
|
+
entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.alt }) : null
|
|
322
473
|
] });
|
|
323
474
|
}
|
|
324
|
-
return /* @__PURE__ */ (0,
|
|
325
|
-
/* @__PURE__ */ (0,
|
|
475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("figure", { className: "my-3", children: [
|
|
476
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
326
477
|
"img",
|
|
327
478
|
{
|
|
328
479
|
src,
|
|
@@ -331,24 +482,24 @@ function DocScreenshot({ entry }) {
|
|
|
331
482
|
className: "max-w-full rounded-md border border-border"
|
|
332
483
|
}
|
|
333
484
|
),
|
|
334
|
-
entry.alt ? /* @__PURE__ */ (0,
|
|
485
|
+
entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("figcaption", { className: "mt-1.5 text-xs text-muted-foreground", children: entry.alt }) : null
|
|
335
486
|
] });
|
|
336
487
|
}
|
|
337
488
|
|
|
338
489
|
// src/components/doc/DocVideo.tsx
|
|
339
|
-
var
|
|
490
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
340
491
|
function DocVideo({ entry }) {
|
|
341
|
-
if (isLocalFsPath(entry.path)) {
|
|
342
|
-
return /* @__PURE__ */ (0,
|
|
343
|
-
/* @__PURE__ */ (0,
|
|
344
|
-
/* @__PURE__ */ (0,
|
|
345
|
-
entry.caption ? /* @__PURE__ */ (0,
|
|
492
|
+
if ((0, import_url.isLocalFsPath)(entry.path)) {
|
|
493
|
+
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: [
|
|
494
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "font-medium", children: "Video unavailable" }),
|
|
495
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
496
|
+
entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.caption }) : null
|
|
346
497
|
] });
|
|
347
498
|
}
|
|
348
|
-
const src = safeUrl(entry.path);
|
|
349
|
-
const poster = safeUrl(entry.poster);
|
|
350
|
-
return /* @__PURE__ */ (0,
|
|
351
|
-
/* @__PURE__ */ (0,
|
|
499
|
+
const src = (0, import_url.safeUrl)(entry.path);
|
|
500
|
+
const poster = (0, import_url.safeUrl)(entry.poster);
|
|
501
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "my-3", children: [
|
|
502
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
352
503
|
"video",
|
|
353
504
|
{
|
|
354
505
|
controls: true,
|
|
@@ -358,21 +509,21 @@ function DocVideo({ entry }) {
|
|
|
358
509
|
className: "max-w-full rounded-md border border-border"
|
|
359
510
|
}
|
|
360
511
|
),
|
|
361
|
-
entry.caption ? /* @__PURE__ */ (0,
|
|
512
|
+
entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: entry.caption }) : null
|
|
362
513
|
] });
|
|
363
514
|
}
|
|
364
515
|
|
|
365
516
|
// src/components/doc/DocHtml.tsx
|
|
366
|
-
var
|
|
517
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
367
518
|
function DocHtml({ entry }) {
|
|
368
519
|
const height = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
369
520
|
const title = entry.title ?? "Embedded HTML";
|
|
370
|
-
const safeHref = safeUrl(entry.url ?? entry.path);
|
|
521
|
+
const safeHref = (0, import_url.safeUrl)(entry.url ?? entry.path);
|
|
371
522
|
const frameProps = entry.content !== void 0 ? { srcDoc: entry.content } : { src: safeHref ?? "" };
|
|
372
|
-
return /* @__PURE__ */ (0,
|
|
373
|
-
/* @__PURE__ */ (0,
|
|
374
|
-
/* @__PURE__ */ (0,
|
|
375
|
-
safeHref ? /* @__PURE__ */ (0,
|
|
523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
|
|
524
|
+
/* @__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: [
|
|
525
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: entry.title ?? "HTML" }),
|
|
526
|
+
safeHref ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
376
527
|
"a",
|
|
377
528
|
{
|
|
378
529
|
href: safeHref,
|
|
@@ -385,7 +536,7 @@ function DocHtml({ entry }) {
|
|
|
385
536
|
}
|
|
386
537
|
) : null
|
|
387
538
|
] }),
|
|
388
|
-
/* @__PURE__ */ (0,
|
|
539
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
389
540
|
"iframe",
|
|
390
541
|
{
|
|
391
542
|
...frameProps,
|
|
@@ -400,7 +551,7 @@ function DocHtml({ entry }) {
|
|
|
400
551
|
}
|
|
401
552
|
|
|
402
553
|
// src/components/doc/DocState.tsx
|
|
403
|
-
var
|
|
554
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
404
555
|
function DocState({ entry }) {
|
|
405
556
|
let json;
|
|
406
557
|
try {
|
|
@@ -408,23 +559,23 @@ function DocState({ entry }) {
|
|
|
408
559
|
} catch {
|
|
409
560
|
json = String(entry.value);
|
|
410
561
|
}
|
|
411
|
-
return /* @__PURE__ */ (0,
|
|
562
|
+
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 }) });
|
|
412
563
|
}
|
|
413
564
|
|
|
414
565
|
// src/components/doc/DocCustom.tsx
|
|
415
|
-
var
|
|
566
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
416
567
|
function DocCustom({ entry }) {
|
|
417
568
|
const renderers = useCustomRenderers();
|
|
418
569
|
const renderer = renderers[entry.type];
|
|
419
570
|
if (renderer) {
|
|
420
|
-
return /* @__PURE__ */ (0,
|
|
571
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children: renderer(entry) });
|
|
421
572
|
}
|
|
422
|
-
return /* @__PURE__ */ (0,
|
|
423
|
-
/* @__PURE__ */ (0,
|
|
424
|
-
/* @__PURE__ */ (0,
|
|
573
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
|
|
574
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
|
|
575
|
+
/* @__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) })
|
|
425
576
|
] });
|
|
426
577
|
}
|
|
427
|
-
function
|
|
578
|
+
function safeStringify2(value) {
|
|
428
579
|
try {
|
|
429
580
|
return JSON.stringify(value, null, 2);
|
|
430
581
|
} catch {
|
|
@@ -433,47 +584,47 @@ function safeStringify(value) {
|
|
|
433
584
|
}
|
|
434
585
|
|
|
435
586
|
// src/components/doc/DocEntry.tsx
|
|
436
|
-
var
|
|
587
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
437
588
|
function DocEntry({ entry }) {
|
|
438
589
|
switch (entry.kind) {
|
|
439
590
|
case "note":
|
|
440
|
-
return /* @__PURE__ */ (0,
|
|
591
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocNote, { entry });
|
|
441
592
|
case "tag":
|
|
442
|
-
return /* @__PURE__ */ (0,
|
|
593
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocTag, { entry });
|
|
443
594
|
case "kv":
|
|
444
|
-
return /* @__PURE__ */ (0,
|
|
595
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocKv, { entry });
|
|
445
596
|
case "code":
|
|
446
|
-
return /* @__PURE__ */ (0,
|
|
597
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocCode, { entry });
|
|
447
598
|
case "table":
|
|
448
|
-
return /* @__PURE__ */ (0,
|
|
599
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocTable, { entry });
|
|
449
600
|
case "link":
|
|
450
|
-
return /* @__PURE__ */ (0,
|
|
601
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocLink, { entry });
|
|
451
602
|
case "section":
|
|
452
|
-
return /* @__PURE__ */ (0,
|
|
603
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocSection, { entry });
|
|
453
604
|
case "mermaid":
|
|
454
|
-
return /* @__PURE__ */ (0,
|
|
605
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocMermaid, { entry });
|
|
455
606
|
case "screenshot":
|
|
456
|
-
return /* @__PURE__ */ (0,
|
|
607
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocScreenshot, { entry });
|
|
457
608
|
case "video":
|
|
458
|
-
return /* @__PURE__ */ (0,
|
|
609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocVideo, { entry });
|
|
459
610
|
case "html":
|
|
460
|
-
return /* @__PURE__ */ (0,
|
|
611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocHtml, { entry });
|
|
461
612
|
case "state":
|
|
462
|
-
return /* @__PURE__ */ (0,
|
|
613
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocState, { entry });
|
|
463
614
|
case "custom":
|
|
464
|
-
return /* @__PURE__ */ (0,
|
|
615
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocCustom, { entry });
|
|
465
616
|
}
|
|
466
617
|
}
|
|
467
618
|
|
|
468
619
|
// src/components/ReportDocEntries.tsx
|
|
469
|
-
var
|
|
620
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
470
621
|
function ReportDocEntries({ entries }) {
|
|
471
622
|
if (entries.length === 0) return null;
|
|
472
|
-
return /* @__PURE__ */ (0,
|
|
623
|
+
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)) });
|
|
473
624
|
}
|
|
474
625
|
|
|
475
626
|
// src/lib/step-params.tsx
|
|
476
|
-
var
|
|
627
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
477
628
|
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
478
629
|
function highlightStepParams(text) {
|
|
479
630
|
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
@@ -485,7 +636,7 @@ function highlightStepParams(text) {
|
|
|
485
636
|
const end = start + match[0].length;
|
|
486
637
|
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
487
638
|
nodes.push(
|
|
488
|
-
/* @__PURE__ */ (0,
|
|
639
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
489
640
|
);
|
|
490
641
|
lastIndex = end;
|
|
491
642
|
});
|
|
@@ -494,7 +645,7 @@ function highlightStepParams(text) {
|
|
|
494
645
|
}
|
|
495
646
|
|
|
496
647
|
// src/components/ReportSteps.tsx
|
|
497
|
-
var
|
|
648
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
498
649
|
var STEP_GLYPH = {
|
|
499
650
|
passed: "\u2713",
|
|
500
651
|
failed: "\u2717",
|
|
@@ -509,21 +660,21 @@ var STEP_GLYPH_COLOR = {
|
|
|
509
660
|
};
|
|
510
661
|
function ReportSteps({ scenario }) {
|
|
511
662
|
if (scenario.steps.length === 0) return null;
|
|
512
|
-
return /* @__PURE__ */ (0,
|
|
663
|
+
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)) });
|
|
513
664
|
}
|
|
514
665
|
function ReportStepItem({ step }) {
|
|
515
666
|
const kw = step.keyword.toLowerCase();
|
|
516
667
|
const continuation = kw === "and" || kw === "but";
|
|
517
|
-
return /* @__PURE__ */ (0,
|
|
668
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
518
669
|
"li",
|
|
519
670
|
{
|
|
520
671
|
id: step.id,
|
|
521
672
|
"data-status": step.status,
|
|
522
673
|
className: cn("py-1.5 text-[0.8125rem] leading-normal", continuation && "pl-5"),
|
|
523
674
|
children: [
|
|
524
|
-
/* @__PURE__ */ (0,
|
|
525
|
-
/* @__PURE__ */ (0,
|
|
526
|
-
/* @__PURE__ */ (0,
|
|
675
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-baseline gap-2", children: [
|
|
676
|
+
/* @__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" }),
|
|
677
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
527
678
|
"span",
|
|
528
679
|
{
|
|
529
680
|
className: cn(
|
|
@@ -533,10 +684,10 @@ function ReportStepItem({ step }) {
|
|
|
533
684
|
children: step.keyword
|
|
534
685
|
}
|
|
535
686
|
),
|
|
536
|
-
/* @__PURE__ */ (0,
|
|
537
|
-
step.durationMs > 0 ? /* @__PURE__ */ (0,
|
|
687
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
|
|
688
|
+
step.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: (0, import_duration.formatDuration)(step.durationMs) }) : null
|
|
538
689
|
] }),
|
|
539
|
-
step.errorMessage ? /* @__PURE__ */ (0,
|
|
690
|
+
step.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
540
691
|
"pre",
|
|
541
692
|
{
|
|
542
693
|
role: "alert",
|
|
@@ -544,132 +695,17 @@ function ReportStepItem({ step }) {
|
|
|
544
695
|
children: step.errorMessage
|
|
545
696
|
}
|
|
546
697
|
) : null,
|
|
547
|
-
step.docEntries.length > 0 ? /* @__PURE__ */ (0,
|
|
698
|
+
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
|
|
548
699
|
]
|
|
549
700
|
}
|
|
550
701
|
);
|
|
551
702
|
}
|
|
552
703
|
|
|
553
|
-
// ../executable-stories-core/dist/state-diff.js
|
|
554
|
-
var isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
555
|
-
function deepEqual(a, b) {
|
|
556
|
-
if (Object.is(a, b)) return true;
|
|
557
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
558
|
-
return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
559
|
-
}
|
|
560
|
-
if (isPlainObject(a) && isPlainObject(b)) {
|
|
561
|
-
const ak = Object.keys(a);
|
|
562
|
-
const bk = Object.keys(b);
|
|
563
|
-
return ak.length === bk.length && ak.every((k) => k in b && deepEqual(a[k], b[k]));
|
|
564
|
-
}
|
|
565
|
-
return false;
|
|
566
|
-
}
|
|
567
|
-
var joinKey = (path, key) => path === "" ? key : `${path}.${key}`;
|
|
568
|
-
function walk(path, before, after, out) {
|
|
569
|
-
if (Object.is(before, after)) return;
|
|
570
|
-
if (Array.isArray(before) && Array.isArray(after)) {
|
|
571
|
-
const shared = Math.min(before.length, after.length);
|
|
572
|
-
for (let i = 0; i < shared; i++) walk(`${path}[${i}]`, before[i], after[i], out);
|
|
573
|
-
for (let i = shared; i < after.length; i++) out.push({ path: `${path}[${i}]`, kind: "added", after: after[i] });
|
|
574
|
-
for (let i = shared; i < before.length; i++) out.push({ path: `${path}[${i}]`, kind: "removed", before: before[i] });
|
|
575
|
-
return;
|
|
576
|
-
}
|
|
577
|
-
if (isPlainObject(before) && isPlainObject(after)) {
|
|
578
|
-
for (const key of Object.keys(after)) {
|
|
579
|
-
const p = joinKey(path, key);
|
|
580
|
-
if (key in before) walk(p, before[key], after[key], out);
|
|
581
|
-
else out.push({ path: p, kind: "added", after: after[key] });
|
|
582
|
-
}
|
|
583
|
-
for (const key of Object.keys(before)) {
|
|
584
|
-
if (!(key in after)) out.push({ path: joinKey(path, key), kind: "removed", before: before[key] });
|
|
585
|
-
}
|
|
586
|
-
return;
|
|
587
|
-
}
|
|
588
|
-
if (!deepEqual(before, after)) out.push({ path, kind: "changed", before, after });
|
|
589
|
-
}
|
|
590
|
-
function diffStateValues(before, after) {
|
|
591
|
-
const out = [];
|
|
592
|
-
walk("", before, after, out);
|
|
593
|
-
return out;
|
|
594
|
-
}
|
|
595
|
-
function formatStateValue(value, maxLen = 60) {
|
|
596
|
-
const s = value === void 0 ? "undefined" : JSON.stringify(value);
|
|
597
|
-
return s.length > maxLen ? `${s.slice(0, maxLen - 1)}\u2026` : s;
|
|
598
|
-
}
|
|
599
|
-
function summarizeStateChanges(changes) {
|
|
600
|
-
return changes.map((c) => {
|
|
601
|
-
const at = c.path === "" ? "(root)" : c.path;
|
|
602
|
-
switch (c.kind) {
|
|
603
|
-
case "added":
|
|
604
|
-
return `+ ${at}: ${formatStateValue(c.after)}`;
|
|
605
|
-
case "removed":
|
|
606
|
-
return `\u2212 ${at}`;
|
|
607
|
-
case "changed":
|
|
608
|
-
return `${at}: ${formatStateValue(c.before)} \u2192 ${formatStateValue(c.after)}`;
|
|
609
|
-
}
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// ../executable-stories-core/dist/storyboard.js
|
|
614
|
-
function findScreenshot(entries) {
|
|
615
|
-
for (const entry of entries) {
|
|
616
|
-
if (entry.kind === "screenshot") return entry;
|
|
617
|
-
if (entry.children) {
|
|
618
|
-
const nested = findScreenshot(entry.children);
|
|
619
|
-
if (nested) return nested;
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
return void 0;
|
|
623
|
-
}
|
|
624
|
-
function findStates(entries, out = []) {
|
|
625
|
-
for (const entry of entries) {
|
|
626
|
-
if (entry.kind === "state") out.push(entry);
|
|
627
|
-
if (entry.children) findStates(entry.children, out);
|
|
628
|
-
}
|
|
629
|
-
return out;
|
|
630
|
-
}
|
|
631
|
-
var laneOf = (label) => label ?? "";
|
|
632
|
-
function extractStoryboardFrames(scenario) {
|
|
633
|
-
const frames = [];
|
|
634
|
-
const laneOrder = [];
|
|
635
|
-
const previous = /* @__PURE__ */ new Map();
|
|
636
|
-
for (const step of scenario.steps) {
|
|
637
|
-
const shot = findScreenshot(step.docEntries);
|
|
638
|
-
const stateDocs = findStates(step.docEntries);
|
|
639
|
-
if (!shot && stateDocs.length === 0) continue;
|
|
640
|
-
const byLane = /* @__PURE__ */ new Map();
|
|
641
|
-
for (const doc of stateDocs) {
|
|
642
|
-
const lane = laneOf(doc.label);
|
|
643
|
-
if (!byLane.has(lane) && !laneOrder.includes(lane)) laneOrder.push(lane);
|
|
644
|
-
byLane.set(lane, doc);
|
|
645
|
-
}
|
|
646
|
-
const states = [];
|
|
647
|
-
for (const lane of laneOrder) {
|
|
648
|
-
const doc = byLane.get(lane);
|
|
649
|
-
if (!doc) continue;
|
|
650
|
-
const card = {
|
|
651
|
-
...doc.label !== void 0 && { label: doc.label },
|
|
652
|
-
value: doc.value
|
|
653
|
-
};
|
|
654
|
-
if (previous.has(lane)) card.changes = diffStateValues(previous.get(lane), doc.value);
|
|
655
|
-
previous.set(lane, doc.value);
|
|
656
|
-
states.push(card);
|
|
657
|
-
}
|
|
658
|
-
frames.push({
|
|
659
|
-
stepId: step.id,
|
|
660
|
-
stepIndex: step.index,
|
|
661
|
-
keyword: step.keyword,
|
|
662
|
-
text: step.text,
|
|
663
|
-
status: step.status,
|
|
664
|
-
...shot && { screenshot: { path: shot.path, ...shot.alt !== void 0 && { alt: shot.alt } } },
|
|
665
|
-
states
|
|
666
|
-
});
|
|
667
|
-
}
|
|
668
|
-
return frames;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
704
|
// src/components/ReportStoryboard.tsx
|
|
672
|
-
var
|
|
705
|
+
var import_storyboard = require("executable-stories-core/storyboard");
|
|
706
|
+
var import_state_diff = require("executable-stories-core/state-diff");
|
|
707
|
+
var import_url6 = require("executable-stories-core/utils/url");
|
|
708
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
673
709
|
var FRAME_GLYPH = {
|
|
674
710
|
passed: "\u2713",
|
|
675
711
|
failed: "\u2717",
|
|
@@ -683,48 +719,48 @@ var FRAME_GLYPH_COLOR = {
|
|
|
683
719
|
pending: "text-pend"
|
|
684
720
|
};
|
|
685
721
|
function ReportStoryboard({ scenario }) {
|
|
686
|
-
const frames = extractStoryboardFrames(scenario);
|
|
722
|
+
const frames = (0, import_storyboard.extractStoryboardFrames)(scenario);
|
|
687
723
|
if (frames.length < 2) return null;
|
|
688
|
-
return /* @__PURE__ */ (0,
|
|
689
|
-
/* @__PURE__ */ (0,
|
|
690
|
-
/* @__PURE__ */ (0,
|
|
724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
|
|
725
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
|
|
726
|
+
/* @__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)) })
|
|
691
727
|
] });
|
|
692
728
|
}
|
|
693
729
|
function StoryboardFrameItem({ frame }) {
|
|
694
730
|
const label = `${frame.keyword} ${frame.text}`;
|
|
695
731
|
const hasStates = frame.states.length > 0;
|
|
696
|
-
const caption = /* @__PURE__ */ (0,
|
|
697
|
-
/* @__PURE__ */ (0,
|
|
698
|
-
/* @__PURE__ */ (0,
|
|
699
|
-
/* @__PURE__ */ (0,
|
|
732
|
+
const caption = /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
|
|
733
|
+
/* @__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" }),
|
|
734
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "min-w-0", children: [
|
|
735
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
|
|
700
736
|
" ",
|
|
701
|
-
/* @__PURE__ */ (0,
|
|
737
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-muted-foreground", children: frame.screenshot?.alt ?? frame.text })
|
|
702
738
|
] })
|
|
703
739
|
] });
|
|
704
740
|
return (
|
|
705
741
|
// State cards need room for diff rows; screenshot-only frames keep the
|
|
706
742
|
// original narrow film-cell width (and DOM) unchanged.
|
|
707
|
-
/* @__PURE__ */ (0,
|
|
708
|
-
frame.screenshot ? /* @__PURE__ */ (0,
|
|
709
|
-
hasStates ? /* @__PURE__ */ (0,
|
|
743
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("li", { className: cn("shrink-0", hasStates ? "w-64" : "w-40"), children: [
|
|
744
|
+
frame.screenshot ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(FrameScreenshot, { frame, label }) : null,
|
|
745
|
+
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,
|
|
710
746
|
frame.screenshot ? caption : (
|
|
711
747
|
// No screenshot means no image anchor, so the caption carries the
|
|
712
748
|
// jump-to-step link instead.
|
|
713
|
-
/* @__PURE__ */ (0,
|
|
749
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("a", { href: `#${frame.stepId}`, "aria-label": `Jump to step: ${label}`, className: "block hover:underline", children: caption })
|
|
714
750
|
)
|
|
715
751
|
] })
|
|
716
752
|
);
|
|
717
753
|
}
|
|
718
754
|
function FrameScreenshot({ frame, label }) {
|
|
719
755
|
const path = frame.screenshot?.path ?? "";
|
|
720
|
-
const src = isLocalFsPath(path) ? void 0 : safeImageUrl(path);
|
|
721
|
-
return /* @__PURE__ */ (0,
|
|
756
|
+
const src = (0, import_url6.isLocalFsPath)(path) ? void 0 : (0, import_url6.safeImageUrl)(path);
|
|
757
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
722
758
|
"a",
|
|
723
759
|
{
|
|
724
760
|
href: `#${frame.stepId}`,
|
|
725
761
|
"aria-label": `Jump to step: ${label}`,
|
|
726
762
|
className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
|
|
727
|
-
children: src ? /* @__PURE__ */ (0,
|
|
763
|
+
children: src ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
728
764
|
"img",
|
|
729
765
|
{
|
|
730
766
|
src,
|
|
@@ -732,7 +768,7 @@ function FrameScreenshot({ frame, label }) {
|
|
|
732
768
|
loading: "lazy",
|
|
733
769
|
className: "h-24 w-full bg-muted object-cover object-top"
|
|
734
770
|
}
|
|
735
|
-
) : /* @__PURE__ */ (0,
|
|
771
|
+
) : /* @__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" })
|
|
736
772
|
}
|
|
737
773
|
);
|
|
738
774
|
}
|
|
@@ -751,30 +787,30 @@ function prettyJson(value) {
|
|
|
751
787
|
function StateCardView({ card }) {
|
|
752
788
|
const json = prettyJson(card.value);
|
|
753
789
|
const firstCapture = card.changes === void 0;
|
|
754
|
-
return /* @__PURE__ */ (0,
|
|
755
|
-
/* @__PURE__ */ (0,
|
|
756
|
-
/* @__PURE__ */ (0,
|
|
757
|
-
firstCapture ? /* @__PURE__ */ (0,
|
|
790
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { "data-slot": "state-card", className: "rounded-md border border-border bg-card p-2", children: [
|
|
791
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: "flex flex-wrap items-baseline gap-1.5", children: [
|
|
792
|
+
/* @__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" }),
|
|
793
|
+
firstCapture ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-[0.625rem] text-muted-foreground italic", children: "first capture" }) : null
|
|
758
794
|
] }),
|
|
759
|
-
!firstCapture && (card.changes && card.changes.length > 0 ? /* @__PURE__ */ (0,
|
|
795
|
+
!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)(
|
|
760
796
|
"li",
|
|
761
797
|
{
|
|
762
798
|
className: cn(
|
|
763
799
|
"rounded-sm px-1.5 py-0.5 font-mono text-[0.625rem] leading-snug break-all",
|
|
764
800
|
CHANGE_TONE[change.kind]
|
|
765
801
|
),
|
|
766
|
-
children: summarizeStateChanges([change])[0]
|
|
802
|
+
children: (0, import_state_diff.summarizeStateChanges)([change])[0]
|
|
767
803
|
},
|
|
768
804
|
i
|
|
769
|
-
)) }) : /* @__PURE__ */ (0,
|
|
770
|
-
/* @__PURE__ */ (0,
|
|
805
|
+
)) }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "mt-1.5 text-[0.625rem] text-muted-foreground", children: "No changes" })),
|
|
806
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
771
807
|
"details",
|
|
772
808
|
{
|
|
773
809
|
open: firstCapture && json.length <= 240,
|
|
774
810
|
className: cn(firstCapture ? "mt-1.5" : "mt-1"),
|
|
775
811
|
children: [
|
|
776
|
-
/* @__PURE__ */ (0,
|
|
777
|
-
/* @__PURE__ */ (0,
|
|
812
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("summary", { className: "cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground", children: "Snapshot" }),
|
|
813
|
+
/* @__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 })
|
|
778
814
|
]
|
|
779
815
|
}
|
|
780
816
|
)
|
|
@@ -782,17 +818,17 @@ function StateCardView({ card }) {
|
|
|
782
818
|
}
|
|
783
819
|
|
|
784
820
|
// src/components/ReportAttachments.tsx
|
|
785
|
-
var
|
|
821
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
786
822
|
function ReportAttachments({ attachments }) {
|
|
787
823
|
if (attachments.length === 0) return null;
|
|
788
824
|
return (
|
|
789
825
|
// role="group" (not a labelled <section>) so multiple scenarios' attachment
|
|
790
826
|
// blocks don't create duplicate "Attachments" region landmarks.
|
|
791
|
-
/* @__PURE__ */ (0,
|
|
827
|
+
/* @__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) => {
|
|
792
828
|
const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
|
|
793
829
|
const isImage = att.mediaType.startsWith("image/");
|
|
794
|
-
return /* @__PURE__ */ (0,
|
|
795
|
-
/* @__PURE__ */ (0,
|
|
830
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
831
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
796
832
|
"img",
|
|
797
833
|
{
|
|
798
834
|
src: dataUri,
|
|
@@ -801,8 +837,8 @@ function ReportAttachments({ attachments }) {
|
|
|
801
837
|
className: "max-w-full rounded-md border border-border"
|
|
802
838
|
}
|
|
803
839
|
),
|
|
804
|
-
/* @__PURE__ */ (0,
|
|
805
|
-
] }) : /* @__PURE__ */ (0,
|
|
840
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
|
|
841
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
806
842
|
"a",
|
|
807
843
|
{
|
|
808
844
|
href: dataUri,
|
|
@@ -811,7 +847,7 @@ function ReportAttachments({ attachments }) {
|
|
|
811
847
|
children: [
|
|
812
848
|
att.name,
|
|
813
849
|
" ",
|
|
814
|
-
/* @__PURE__ */ (0,
|
|
850
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
815
851
|
"(",
|
|
816
852
|
att.mediaType,
|
|
817
853
|
")"
|
|
@@ -823,6 +859,9 @@ function ReportAttachments({ attachments }) {
|
|
|
823
859
|
);
|
|
824
860
|
}
|
|
825
861
|
|
|
862
|
+
// src/components/ReportTrace.tsx
|
|
863
|
+
var import_duration2 = require("executable-stories-core/utils/duration");
|
|
864
|
+
|
|
826
865
|
// src/lib/trace.ts
|
|
827
866
|
var VALID = /* @__PURE__ */ new Set(["ok", "error", "unset"]);
|
|
828
867
|
var safeStatus = (s) => VALID.has(s) ? s : "unset";
|
|
@@ -875,15 +914,15 @@ function toTraceRows(spans) {
|
|
|
875
914
|
roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
876
915
|
const rows = [];
|
|
877
916
|
const seen = /* @__PURE__ */ new Set();
|
|
878
|
-
const
|
|
917
|
+
const walk = (node, depth) => {
|
|
879
918
|
if (seen.has(node.span.spanId)) return;
|
|
880
919
|
seen.add(node.span.spanId);
|
|
881
920
|
rows.push({ ...node.span, depth });
|
|
882
|
-
for (const child of node.children)
|
|
921
|
+
for (const child of node.children) walk(child, depth + 1);
|
|
883
922
|
};
|
|
884
|
-
for (const root of roots)
|
|
923
|
+
for (const root of roots) walk(root, 0);
|
|
885
924
|
for (const node of byId.values()) {
|
|
886
|
-
if (!seen.has(node.span.spanId))
|
|
925
|
+
if (!seen.has(node.span.spanId)) walk(node, 0);
|
|
887
926
|
}
|
|
888
927
|
return rows;
|
|
889
928
|
}
|
|
@@ -899,7 +938,7 @@ function traceWindow(rows) {
|
|
|
899
938
|
}
|
|
900
939
|
|
|
901
940
|
// src/components/ReportTrace.tsx
|
|
902
|
-
var
|
|
941
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
903
942
|
var BAR_COLOR = {
|
|
904
943
|
ok: "bg-pass",
|
|
905
944
|
error: "bg-fail",
|
|
@@ -910,21 +949,21 @@ function ReportTrace({ spans }) {
|
|
|
910
949
|
const rows = toTraceRows(spans);
|
|
911
950
|
if (rows.length === 0) return null;
|
|
912
951
|
const { minStartMs, totalMs } = traceWindow(rows);
|
|
913
|
-
return /* @__PURE__ */ (0,
|
|
914
|
-
/* @__PURE__ */ (0,
|
|
952
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
|
|
953
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
|
|
915
954
|
"Trace (",
|
|
916
955
|
rows.length,
|
|
917
956
|
" span",
|
|
918
957
|
rows.length === 1 ? "" : "s",
|
|
919
958
|
", ",
|
|
920
|
-
formatDuration(totalMs),
|
|
959
|
+
(0, import_duration2.formatDuration)(totalMs),
|
|
921
960
|
")"
|
|
922
961
|
] }),
|
|
923
|
-
/* @__PURE__ */ (0,
|
|
962
|
+
/* @__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) => {
|
|
924
963
|
const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
|
|
925
964
|
const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
|
|
926
|
-
return /* @__PURE__ */ (0,
|
|
927
|
-
/* @__PURE__ */ (0,
|
|
965
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("li", { className: "flex items-center gap-2", children: [
|
|
966
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
928
967
|
"span",
|
|
929
968
|
{
|
|
930
969
|
className: "min-w-0 flex-1 truncate text-foreground",
|
|
@@ -933,14 +972,14 @@ function ReportTrace({ spans }) {
|
|
|
933
972
|
children: row.name
|
|
934
973
|
}
|
|
935
974
|
),
|
|
936
|
-
/* @__PURE__ */ (0,
|
|
975
|
+
/* @__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)(
|
|
937
976
|
"span",
|
|
938
977
|
{
|
|
939
978
|
className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
|
|
940
979
|
style: { left: `${leftPct}%`, width: `${widthPct}%` }
|
|
941
980
|
}
|
|
942
981
|
) }),
|
|
943
|
-
/* @__PURE__ */ (0,
|
|
982
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: (0, import_duration2.formatDuration)(row.durationMs) })
|
|
944
983
|
] }, `${row.spanId}-${i}`);
|
|
945
984
|
}) })
|
|
946
985
|
] });
|
|
@@ -991,7 +1030,7 @@ function flakinessOf(entries) {
|
|
|
991
1030
|
}
|
|
992
1031
|
|
|
993
1032
|
// src/components/ScenarioRunHistory.tsx
|
|
994
|
-
var
|
|
1033
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
995
1034
|
var MAX_DOTS = 10;
|
|
996
1035
|
var DOT_COLOR = {
|
|
997
1036
|
passed: "bg-pass",
|
|
@@ -1011,16 +1050,16 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
1011
1050
|
const recent = entries.slice(-MAX_DOTS);
|
|
1012
1051
|
const flaky = flakinessOf(recent) === "flaky";
|
|
1013
1052
|
const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
|
|
1014
|
-
return /* @__PURE__ */ (0,
|
|
1015
|
-
flaky ? /* @__PURE__ */ (0,
|
|
1016
|
-
/* @__PURE__ */ (0,
|
|
1053
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
1054
|
+
flaky ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
|
|
1055
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1017
1056
|
"span",
|
|
1018
1057
|
{
|
|
1019
1058
|
role: "img",
|
|
1020
1059
|
"aria-label": `Run history: ${summary}`,
|
|
1021
1060
|
title: summary,
|
|
1022
1061
|
className: "flex shrink-0 items-center gap-[3px]",
|
|
1023
|
-
children: recent.map((e, i) => /* @__PURE__ */ (0,
|
|
1062
|
+
children: recent.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1024
1063
|
"span",
|
|
1025
1064
|
{
|
|
1026
1065
|
"aria-hidden": true,
|
|
@@ -1051,6 +1090,7 @@ function useCollapse() {
|
|
|
1051
1090
|
|
|
1052
1091
|
// src/interactive/scenario-actions.tsx
|
|
1053
1092
|
var import_react7 = require("react");
|
|
1093
|
+
var import_scenario_markdown = require("executable-stories-core/utils/scenario-markdown");
|
|
1054
1094
|
var ScenarioActionsContext = (0, import_react7.createContext)(null);
|
|
1055
1095
|
var ScenarioActionsProvider = ScenarioActionsContext.Provider;
|
|
1056
1096
|
function useScenarioActions() {
|
|
@@ -1059,9 +1099,9 @@ function useScenarioActions() {
|
|
|
1059
1099
|
|
|
1060
1100
|
// src/components/ui/card.tsx
|
|
1061
1101
|
var React2 = require("react");
|
|
1062
|
-
var
|
|
1102
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1063
1103
|
function Card({ className, ...props }) {
|
|
1064
|
-
return /* @__PURE__ */ (0,
|
|
1104
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1065
1105
|
"div",
|
|
1066
1106
|
{
|
|
1067
1107
|
"data-slot": "card",
|
|
@@ -1074,7 +1114,7 @@ function Card({ className, ...props }) {
|
|
|
1074
1114
|
);
|
|
1075
1115
|
}
|
|
1076
1116
|
function CardHeader({ className, ...props }) {
|
|
1077
|
-
return /* @__PURE__ */ (0,
|
|
1117
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1078
1118
|
"div",
|
|
1079
1119
|
{
|
|
1080
1120
|
"data-slot": "card-header",
|
|
@@ -1087,7 +1127,7 @@ function CardHeader({ className, ...props }) {
|
|
|
1087
1127
|
);
|
|
1088
1128
|
}
|
|
1089
1129
|
function CardContent({ className, ...props }) {
|
|
1090
|
-
return /* @__PURE__ */ (0,
|
|
1130
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1091
1131
|
"div",
|
|
1092
1132
|
{
|
|
1093
1133
|
"data-slot": "card-content",
|
|
@@ -1101,13 +1141,13 @@ function CardContent({ className, ...props }) {
|
|
|
1101
1141
|
var React3 = require("react");
|
|
1102
1142
|
var import_menu = require("@base-ui/react/menu");
|
|
1103
1143
|
var import_lucide_react = require("lucide-react");
|
|
1104
|
-
var
|
|
1144
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1105
1145
|
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";
|
|
1106
1146
|
function DropdownMenu(props) {
|
|
1107
|
-
return /* @__PURE__ */ (0,
|
|
1147
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1108
1148
|
}
|
|
1109
1149
|
function DropdownMenuTrigger(props) {
|
|
1110
|
-
return /* @__PURE__ */ (0,
|
|
1150
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
1111
1151
|
}
|
|
1112
1152
|
function DropdownMenuContent({
|
|
1113
1153
|
className,
|
|
@@ -1115,14 +1155,14 @@ function DropdownMenuContent({
|
|
|
1115
1155
|
sideOffset = 4,
|
|
1116
1156
|
...props
|
|
1117
1157
|
}) {
|
|
1118
|
-
return /* @__PURE__ */ (0,
|
|
1158
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1119
1159
|
import_menu.Menu.Positioner,
|
|
1120
1160
|
{
|
|
1121
1161
|
"data-slot": "dropdown-menu-positioner",
|
|
1122
1162
|
className: "z-50",
|
|
1123
1163
|
align,
|
|
1124
1164
|
sideOffset,
|
|
1125
|
-
children: /* @__PURE__ */ (0,
|
|
1165
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1126
1166
|
import_menu.Menu.Popup,
|
|
1127
1167
|
{
|
|
1128
1168
|
"data-slot": "dropdown-menu-content",
|
|
@@ -1140,7 +1180,7 @@ function DropdownMenuItem({
|
|
|
1140
1180
|
className,
|
|
1141
1181
|
...props
|
|
1142
1182
|
}) {
|
|
1143
|
-
return /* @__PURE__ */ (0,
|
|
1183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1144
1184
|
import_menu.Menu.Item,
|
|
1145
1185
|
{
|
|
1146
1186
|
"data-slot": "dropdown-menu-item",
|
|
@@ -1152,7 +1192,7 @@ function DropdownMenuItem({
|
|
|
1152
1192
|
|
|
1153
1193
|
// src/components/ReportScenario.tsx
|
|
1154
1194
|
var import_lucide_react2 = require("lucide-react");
|
|
1155
|
-
var
|
|
1195
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1156
1196
|
var STATUS_META = {
|
|
1157
1197
|
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
1158
1198
|
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
@@ -1168,7 +1208,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1168
1208
|
const collapsible = collapse !== null && !hideTitle;
|
|
1169
1209
|
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
1170
1210
|
const actions = useScenarioActions();
|
|
1171
|
-
return /* @__PURE__ */ (0,
|
|
1211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1172
1212
|
Card,
|
|
1173
1213
|
{
|
|
1174
1214
|
id: scenario.id,
|
|
@@ -1176,10 +1216,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1176
1216
|
...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
|
|
1177
1217
|
className: "gap-0 py-0",
|
|
1178
1218
|
children: [
|
|
1179
|
-
/* @__PURE__ */ (0,
|
|
1180
|
-
/* @__PURE__ */ (0,
|
|
1181
|
-
hideTitle ? null : /* @__PURE__ */ (0,
|
|
1182
|
-
collapsible ? /* @__PURE__ */ (0,
|
|
1219
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardHeader, { className: "px-4 py-3", children: [
|
|
1220
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
1221
|
+
hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
1222
|
+
collapsible ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1183
1223
|
"button",
|
|
1184
1224
|
{
|
|
1185
1225
|
type: "button",
|
|
@@ -1188,49 +1228,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1188
1228
|
"aria-controls": bodyId,
|
|
1189
1229
|
"aria-label": `Toggle ${scenario.title}`,
|
|
1190
1230
|
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
1191
|
-
children: /* @__PURE__ */ (0,
|
|
1231
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
1192
1232
|
}
|
|
1193
1233
|
) : null,
|
|
1194
|
-
/* @__PURE__ */ (0,
|
|
1195
|
-
/* @__PURE__ */ (0,
|
|
1234
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
1235
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: scenario.title })
|
|
1196
1236
|
] }),
|
|
1197
|
-
/* @__PURE__ */ (0,
|
|
1198
|
-
/* @__PURE__ */ (0,
|
|
1199
|
-
scenario.durationMs > 0 ? /* @__PURE__ */ (0,
|
|
1200
|
-
meta.showPill ? /* @__PURE__ */ (0,
|
|
1201
|
-
actions ? /* @__PURE__ */ (0,
|
|
1202
|
-
/* @__PURE__ */ (0,
|
|
1237
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1238
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1239
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: (0, import_duration3.formatDuration)(scenario.durationMs) }) : null,
|
|
1240
|
+
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}` }),
|
|
1241
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenu, { children: [
|
|
1242
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1203
1243
|
DropdownMenuTrigger,
|
|
1204
1244
|
{
|
|
1205
1245
|
"aria-label": `Actions for ${scenario.title}`,
|
|
1206
1246
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
1207
|
-
children: /* @__PURE__ */ (0,
|
|
1247
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
|
|
1208
1248
|
}
|
|
1209
1249
|
),
|
|
1210
|
-
/* @__PURE__ */ (0,
|
|
1211
|
-
/* @__PURE__ */ (0,
|
|
1212
|
-
/* @__PURE__ */ (0,
|
|
1250
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuContent, { align: "end", children: [
|
|
1251
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
1252
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.LinkIcon, {}),
|
|
1213
1253
|
" Copy link"
|
|
1214
1254
|
] }),
|
|
1215
|
-
/* @__PURE__ */ (0,
|
|
1216
|
-
/* @__PURE__ */ (0,
|
|
1255
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
1256
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.FileTextIcon, {}),
|
|
1217
1257
|
" Copy as Markdown"
|
|
1218
1258
|
] }),
|
|
1219
|
-
/* @__PURE__ */ (0,
|
|
1220
|
-
/* @__PURE__ */ (0,
|
|
1259
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
1260
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.SparklesIcon, {}),
|
|
1221
1261
|
" Explain with AI"
|
|
1222
1262
|
] })
|
|
1223
1263
|
] })
|
|
1224
1264
|
] }) : null
|
|
1225
1265
|
] })
|
|
1226
1266
|
] }),
|
|
1227
|
-
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0,
|
|
1228
|
-
scenario.tags.map((t) => /* @__PURE__ */ (0,
|
|
1229
|
-
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0,
|
|
1267
|
+
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: [
|
|
1268
|
+
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}`)),
|
|
1269
|
+
(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}`))
|
|
1230
1270
|
] }) : null
|
|
1231
1271
|
] }),
|
|
1232
|
-
/* @__PURE__ */ (0,
|
|
1233
|
-
scenario.errorMessage ? /* @__PURE__ */ (0,
|
|
1272
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
1273
|
+
scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1234
1274
|
"pre",
|
|
1235
1275
|
{
|
|
1236
1276
|
role: "alert",
|
|
@@ -1238,11 +1278,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1238
1278
|
children: scenario.errorMessage
|
|
1239
1279
|
}
|
|
1240
1280
|
) : null,
|
|
1241
|
-
/* @__PURE__ */ (0,
|
|
1242
|
-
/* @__PURE__ */ (0,
|
|
1243
|
-
scenario.docEntries.length > 0 ? /* @__PURE__ */ (0,
|
|
1244
|
-
/* @__PURE__ */ (0,
|
|
1245
|
-
/* @__PURE__ */ (0,
|
|
1281
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportStoryboard, { scenario }),
|
|
1282
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportSteps, { scenario }),
|
|
1283
|
+
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,
|
|
1284
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportAttachments, { attachments: scenario.attachments }),
|
|
1285
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportTrace, { spans: scenario.otelSpans })
|
|
1246
1286
|
] })
|
|
1247
1287
|
]
|
|
1248
1288
|
}
|
|
@@ -1250,13 +1290,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1250
1290
|
}
|
|
1251
1291
|
|
|
1252
1292
|
// src/components/ReportScenarioList.tsx
|
|
1253
|
-
var
|
|
1293
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1254
1294
|
function ReportScenarioList({ feature }) {
|
|
1255
|
-
return /* @__PURE__ */ (0,
|
|
1295
|
+
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)) });
|
|
1256
1296
|
}
|
|
1257
1297
|
|
|
1258
1298
|
// src/components/ReportFeature.tsx
|
|
1259
|
-
var
|
|
1299
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1260
1300
|
function ReportFeature({ feature }) {
|
|
1261
1301
|
const titleId = `${feature.id}-title`;
|
|
1262
1302
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1267,7 +1307,7 @@ function ReportFeature({ feature }) {
|
|
|
1267
1307
|
return (
|
|
1268
1308
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
1269
1309
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1270
|
-
/* @__PURE__ */ (0,
|
|
1310
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
1271
1311
|
"section",
|
|
1272
1312
|
{
|
|
1273
1313
|
id: feature.id,
|
|
@@ -1275,9 +1315,9 @@ function ReportFeature({ feature }) {
|
|
|
1275
1315
|
"aria-labelledby": titleId,
|
|
1276
1316
|
className: "flex flex-col gap-3",
|
|
1277
1317
|
children: [
|
|
1278
|
-
/* @__PURE__ */ (0,
|
|
1279
|
-
/* @__PURE__ */ (0,
|
|
1280
|
-
/* @__PURE__ */ (0,
|
|
1318
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1319
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "min-w-0", children: [
|
|
1320
|
+
/* @__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)(
|
|
1281
1321
|
"button",
|
|
1282
1322
|
{
|
|
1283
1323
|
type: "button",
|
|
@@ -1286,31 +1326,31 @@ function ReportFeature({ feature }) {
|
|
|
1286
1326
|
"aria-controls": bodyId,
|
|
1287
1327
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1288
1328
|
children: [
|
|
1289
|
-
/* @__PURE__ */ (0,
|
|
1290
|
-
/* @__PURE__ */ (0,
|
|
1329
|
+
/* @__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" }),
|
|
1330
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "truncate", children: feature.title })
|
|
1291
1331
|
]
|
|
1292
1332
|
}
|
|
1293
1333
|
) : feature.title }),
|
|
1294
|
-
/* @__PURE__ */ (0,
|
|
1334
|
+
/* @__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 })
|
|
1295
1335
|
] }),
|
|
1296
|
-
/* @__PURE__ */ (0,
|
|
1336
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
1297
1337
|
"p",
|
|
1298
1338
|
{
|
|
1299
1339
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1300
1340
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1301
1341
|
children: [
|
|
1302
|
-
/* @__PURE__ */ (0,
|
|
1342
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { children: [
|
|
1303
1343
|
s.passed,
|
|
1304
1344
|
" passed"
|
|
1305
1345
|
] }),
|
|
1306
|
-
/* @__PURE__ */ (0,
|
|
1307
|
-
/* @__PURE__ */ (0,
|
|
1346
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1347
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1308
1348
|
s.failed,
|
|
1309
1349
|
" failed"
|
|
1310
1350
|
] }),
|
|
1311
|
-
skipped > 0 ? /* @__PURE__ */ (0,
|
|
1312
|
-
/* @__PURE__ */ (0,
|
|
1313
|
-
/* @__PURE__ */ (0,
|
|
1351
|
+
skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
1352
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1353
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { children: [
|
|
1314
1354
|
skipped,
|
|
1315
1355
|
" skipped"
|
|
1316
1356
|
] })
|
|
@@ -1319,7 +1359,7 @@ function ReportFeature({ feature }) {
|
|
|
1319
1359
|
}
|
|
1320
1360
|
)
|
|
1321
1361
|
] }),
|
|
1322
|
-
/* @__PURE__ */ (0,
|
|
1362
|
+
/* @__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 }) })
|
|
1323
1363
|
]
|
|
1324
1364
|
}
|
|
1325
1365
|
)
|
|
@@ -1327,17 +1367,17 @@ function ReportFeature({ feature }) {
|
|
|
1327
1367
|
}
|
|
1328
1368
|
|
|
1329
1369
|
// src/components/ReportFeatureList.tsx
|
|
1330
|
-
var
|
|
1370
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1331
1371
|
function ReportFeatureList() {
|
|
1332
1372
|
const report = useReport();
|
|
1333
|
-
return /* @__PURE__ */ (0,
|
|
1373
|
+
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)) });
|
|
1334
1374
|
}
|
|
1335
1375
|
|
|
1336
1376
|
// src/components/ui/empty.tsx
|
|
1337
1377
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
1338
|
-
var
|
|
1378
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1339
1379
|
function Empty({ className, ...props }) {
|
|
1340
|
-
return /* @__PURE__ */ (0,
|
|
1380
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1341
1381
|
"div",
|
|
1342
1382
|
{
|
|
1343
1383
|
"data-slot": "empty",
|
|
@@ -1350,7 +1390,7 @@ function Empty({ className, ...props }) {
|
|
|
1350
1390
|
);
|
|
1351
1391
|
}
|
|
1352
1392
|
function EmptyHeader({ className, ...props }) {
|
|
1353
|
-
return /* @__PURE__ */ (0,
|
|
1393
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1354
1394
|
"div",
|
|
1355
1395
|
{
|
|
1356
1396
|
"data-slot": "empty-header",
|
|
@@ -1377,7 +1417,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
|
|
|
1377
1417
|
}
|
|
1378
1418
|
);
|
|
1379
1419
|
function EmptyTitle({ className, ...props }) {
|
|
1380
|
-
return /* @__PURE__ */ (0,
|
|
1420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1381
1421
|
"div",
|
|
1382
1422
|
{
|
|
1383
1423
|
"data-slot": "empty-title",
|
|
@@ -1388,16 +1428,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1388
1428
|
}
|
|
1389
1429
|
|
|
1390
1430
|
// src/components/ReportEmpty.tsx
|
|
1391
|
-
var
|
|
1431
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1392
1432
|
function ReportEmpty({ message }) {
|
|
1393
|
-
return /* @__PURE__ */ (0,
|
|
1433
|
+
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." }) }) });
|
|
1394
1434
|
}
|
|
1395
1435
|
|
|
1396
1436
|
// src/components/ReportSummary.tsx
|
|
1397
|
-
var
|
|
1437
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1398
1438
|
function ReportSummary({ className }) {
|
|
1399
1439
|
const report = useReport();
|
|
1400
|
-
return /* @__PURE__ */ (0,
|
|
1440
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1401
1441
|
ReportSummaryView,
|
|
1402
1442
|
{
|
|
1403
1443
|
summary: report.summary,
|
|
@@ -1423,7 +1463,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1423
1463
|
if (summary.pending > 0) {
|
|
1424
1464
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1425
1465
|
}
|
|
1426
|
-
return /* @__PURE__ */ (0,
|
|
1466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1427
1467
|
"dl",
|
|
1428
1468
|
{
|
|
1429
1469
|
className: cn(
|
|
@@ -1436,17 +1476,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1436
1476
|
"aria-label": ariaLabel,
|
|
1437
1477
|
children: cards.map((c) => {
|
|
1438
1478
|
const tone = TONE[c.status];
|
|
1439
|
-
return /* @__PURE__ */ (0,
|
|
1479
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
1440
1480
|
"div",
|
|
1441
1481
|
{
|
|
1442
1482
|
"data-status": c.status,
|
|
1443
1483
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1444
1484
|
children: [
|
|
1445
|
-
/* @__PURE__ */ (0,
|
|
1446
|
-
/* @__PURE__ */ (0,
|
|
1485
|
+
/* @__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: [
|
|
1486
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1447
1487
|
c.label
|
|
1448
1488
|
] }),
|
|
1449
|
-
/* @__PURE__ */ (0,
|
|
1489
|
+
/* @__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 })
|
|
1450
1490
|
]
|
|
1451
1491
|
},
|
|
1452
1492
|
c.status
|
|
@@ -1456,6 +1496,9 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1456
1496
|
);
|
|
1457
1497
|
}
|
|
1458
1498
|
|
|
1499
|
+
// src/components/ReportMeta.tsx
|
|
1500
|
+
var import_duration4 = require("executable-stories-core/utils/duration");
|
|
1501
|
+
|
|
1459
1502
|
// src/lib/provenance.ts
|
|
1460
1503
|
var CI_DISPLAY_NAMES = {
|
|
1461
1504
|
github: "GitHub Actions",
|
|
@@ -1487,7 +1530,7 @@ function prUrl(ci) {
|
|
|
1487
1530
|
}
|
|
1488
1531
|
|
|
1489
1532
|
// src/components/ReportMeta.tsx
|
|
1490
|
-
var
|
|
1533
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1491
1534
|
function ReportMeta() {
|
|
1492
1535
|
const report = useReport();
|
|
1493
1536
|
const items = [];
|
|
@@ -1496,7 +1539,7 @@ function ReportMeta() {
|
|
|
1496
1539
|
items.push({ label: "Started", value: new Date(report.startedAtMs).toLocaleString() });
|
|
1497
1540
|
}
|
|
1498
1541
|
if (report.durationMs) {
|
|
1499
|
-
items.push({ label: "Duration", value: formatDuration(report.durationMs) });
|
|
1542
|
+
items.push({ label: "Duration", value: (0, import_duration4.formatDuration)(report.durationMs) });
|
|
1500
1543
|
}
|
|
1501
1544
|
if (report.packageVersion) {
|
|
1502
1545
|
items.push({ label: "Version", value: report.packageVersion });
|
|
@@ -1510,13 +1553,13 @@ function ReportMeta() {
|
|
|
1510
1553
|
const short = sha.slice(0, 8);
|
|
1511
1554
|
items.push({
|
|
1512
1555
|
label: "Commit",
|
|
1513
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1556
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1514
1557
|
});
|
|
1515
1558
|
}
|
|
1516
1559
|
if (report.ci) {
|
|
1517
1560
|
items.push({
|
|
1518
1561
|
label: "CI",
|
|
1519
|
-
value: report.ci.url ? /* @__PURE__ */ (0,
|
|
1562
|
+
value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1520
1563
|
ciDisplayName(report.ci.name),
|
|
1521
1564
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1522
1565
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1527,7 +1570,7 @@ function ReportMeta() {
|
|
|
1527
1570
|
const label = `#${report.ci.prNumber}`;
|
|
1528
1571
|
items.push({
|
|
1529
1572
|
label: "PR",
|
|
1530
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1573
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1531
1574
|
});
|
|
1532
1575
|
}
|
|
1533
1576
|
if (items.length === 0) return null;
|
|
@@ -1535,48 +1578,48 @@ function ReportMeta() {
|
|
|
1535
1578
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1536
1579
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1537
1580
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1538
|
-
/* @__PURE__ */ (0,
|
|
1539
|
-
/* @__PURE__ */ (0,
|
|
1540
|
-
/* @__PURE__ */ (0,
|
|
1581
|
+
/* @__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: [
|
|
1582
|
+
/* @__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: [
|
|
1583
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1541
1584
|
"Run details"
|
|
1542
1585
|
] }),
|
|
1543
|
-
/* @__PURE__ */ (0,
|
|
1544
|
-
/* @__PURE__ */ (0,
|
|
1545
|
-
/* @__PURE__ */ (0,
|
|
1586
|
+
/* @__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: [
|
|
1587
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("dt", { className: "font-medium", children: item.label }),
|
|
1588
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1546
1589
|
] }, item.label)) })
|
|
1547
1590
|
] })
|
|
1548
1591
|
);
|
|
1549
1592
|
}
|
|
1550
1593
|
|
|
1551
1594
|
// src/components/ReportSchemaError.tsx
|
|
1552
|
-
var
|
|
1595
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1553
1596
|
function ReportSchemaError({ error }) {
|
|
1554
|
-
return /* @__PURE__ */ (0,
|
|
1555
|
-
/* @__PURE__ */ (0,
|
|
1556
|
-
/* @__PURE__ */ (0,
|
|
1557
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0,
|
|
1597
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1598
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("strong", { children: "Report could not be displayed." }) }),
|
|
1599
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { children: error.message }),
|
|
1600
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("p", { children: [
|
|
1558
1601
|
"The report bundle is newer than this version of ",
|
|
1559
|
-
/* @__PURE__ */ (0,
|
|
1602
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("code", { children: "executable-stories-react" }),
|
|
1560
1603
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1561
1604
|
] }) : null,
|
|
1562
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0,
|
|
1563
|
-
/* @__PURE__ */ (0,
|
|
1605
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("details", { children: [
|
|
1606
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("summary", { children: [
|
|
1564
1607
|
error.issues.length,
|
|
1565
1608
|
" validation issue",
|
|
1566
1609
|
error.issues.length === 1 ? "" : "s"
|
|
1567
1610
|
] }),
|
|
1568
|
-
/* @__PURE__ */ (0,
|
|
1611
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1569
1612
|
] }) : null
|
|
1570
1613
|
] });
|
|
1571
1614
|
}
|
|
1572
1615
|
|
|
1573
1616
|
// src/components/ReportShell.tsx
|
|
1574
|
-
var
|
|
1617
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
1575
1618
|
function ReportTitleBlock({ title }) {
|
|
1576
|
-
return /* @__PURE__ */ (0,
|
|
1577
|
-
/* @__PURE__ */ (0,
|
|
1578
|
-
/* @__PURE__ */ (0,
|
|
1579
|
-
/* @__PURE__ */ (0,
|
|
1619
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
|
|
1620
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h1", { children: title ?? "Story Report" }),
|
|
1621
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportSummary, {}),
|
|
1622
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportMeta, {})
|
|
1580
1623
|
] });
|
|
1581
1624
|
}
|
|
1582
1625
|
function ReportErrorShell({
|
|
@@ -1585,22 +1628,22 @@ function ReportErrorShell({
|
|
|
1585
1628
|
title,
|
|
1586
1629
|
dataTheme
|
|
1587
1630
|
}) {
|
|
1588
|
-
return /* @__PURE__ */ (0,
|
|
1631
|
+
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 }) });
|
|
1589
1632
|
}
|
|
1590
1633
|
|
|
1591
1634
|
// src/components/Report.tsx
|
|
1592
|
-
var
|
|
1635
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
1593
1636
|
function Report(props) {
|
|
1594
1637
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1595
1638
|
const result = unwrapReport(report);
|
|
1596
1639
|
if (!result.ok) {
|
|
1597
|
-
return /* @__PURE__ */ (0,
|
|
1640
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1598
1641
|
}
|
|
1599
1642
|
const data = result.data;
|
|
1600
1643
|
const hasContent = data.features.length > 0;
|
|
1601
|
-
return /* @__PURE__ */ (0,
|
|
1602
|
-
/* @__PURE__ */ (0,
|
|
1603
|
-
hasContent ? /* @__PURE__ */ (0,
|
|
1644
|
+
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: [
|
|
1645
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportTitleBlock, { title }) }),
|
|
1646
|
+
hasContent ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportEmpty, {})
|
|
1604
1647
|
] }) });
|
|
1605
1648
|
}
|
|
1606
1649
|
|