executable-stories-react 0.10.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +482 -451
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +440 -407
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +1430 -1246
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +32 -32
- package/dist/interactive.d.ts +32 -32
- package/dist/interactive.js +1473 -1286
- package/dist/interactive.js.map +1 -1
- package/dist/parse.cjs +65 -139
- package/dist/parse.cjs.map +1 -1
- package/dist/parse.js +65 -139
- package/dist/parse.js.map +1 -1
- package/dist/report-island.global.js +30 -28
- package/dist/ssr.cjs +367 -254
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.js +325 -209
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +2 -2
package/dist/ssr.js
CHANGED
|
@@ -290,23 +290,48 @@ function useReport() {
|
|
|
290
290
|
// src/components/ReportScenario.tsx
|
|
291
291
|
import { formatDuration as formatDuration3 } from "executable-stories-core/utils/duration";
|
|
292
292
|
|
|
293
|
+
// src/lib/step-params.tsx
|
|
294
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
295
|
+
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
296
|
+
function highlightStepParams(text) {
|
|
297
|
+
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
298
|
+
if (matches.length === 0) return text;
|
|
299
|
+
const nodes = [];
|
|
300
|
+
let lastIndex = 0;
|
|
301
|
+
matches.forEach((match, i) => {
|
|
302
|
+
const start = match.index;
|
|
303
|
+
const end = start + match[0].length;
|
|
304
|
+
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
305
|
+
nodes.push(
|
|
306
|
+
/* @__PURE__ */ jsx3("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
307
|
+
);
|
|
308
|
+
lastIndex = end;
|
|
309
|
+
});
|
|
310
|
+
if (lastIndex < text.length) nodes.push(text.slice(lastIndex));
|
|
311
|
+
return nodes;
|
|
312
|
+
}
|
|
313
|
+
|
|
293
314
|
// src/components/ReportSteps.tsx
|
|
315
|
+
import {
|
|
316
|
+
assertionState,
|
|
317
|
+
assertiveSteps
|
|
318
|
+
} from "executable-stories-core/utils/assertive-steps";
|
|
294
319
|
import { formatDuration } from "executable-stories-core/utils/duration";
|
|
295
320
|
|
|
296
321
|
// src/components/doc/DocNote.tsx
|
|
297
|
-
import { jsx as
|
|
322
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
298
323
|
function DocNote({ entry }) {
|
|
299
|
-
return /* @__PURE__ */
|
|
324
|
+
return /* @__PURE__ */ jsx4("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
|
|
300
325
|
}
|
|
301
326
|
|
|
302
327
|
// src/components/doc/DocTag.tsx
|
|
303
|
-
import { jsx as
|
|
328
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
304
329
|
function DocTag({ entry }) {
|
|
305
|
-
return /* @__PURE__ */
|
|
330
|
+
return /* @__PURE__ */ jsx5("ul", { className: "my-2 flex flex-wrap gap-1.5", "aria-label": "Tags", children: entry.names.map((n) => /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsx5(Badge, { variant: "tag", children: n }) }, n)) });
|
|
306
331
|
}
|
|
307
332
|
|
|
308
333
|
// src/components/doc/DocKv.tsx
|
|
309
|
-
import { jsx as
|
|
334
|
+
import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
310
335
|
function formatValue(value) {
|
|
311
336
|
if (value === null) return "null";
|
|
312
337
|
if (typeof value === "string") return value;
|
|
@@ -319,8 +344,8 @@ function formatValue(value) {
|
|
|
319
344
|
}
|
|
320
345
|
function DocKv({ entry }) {
|
|
321
346
|
return /* @__PURE__ */ jsxs2("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
|
|
322
|
-
/* @__PURE__ */
|
|
323
|
-
/* @__PURE__ */
|
|
347
|
+
/* @__PURE__ */ jsx6("dt", { className: "font-semibold text-muted-foreground", children: entry.label }),
|
|
348
|
+
/* @__PURE__ */ jsx6("dd", { className: "font-mono text-foreground", children: formatValue(entry.value) })
|
|
324
349
|
] });
|
|
325
350
|
}
|
|
326
351
|
|
|
@@ -338,37 +363,37 @@ function useBuiltinRenderers() {
|
|
|
338
363
|
}
|
|
339
364
|
|
|
340
365
|
// src/components/doc/DocCode.tsx
|
|
341
|
-
import { Fragment, jsx as
|
|
366
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
342
367
|
function CodeFigure({ label, children }) {
|
|
343
368
|
return /* @__PURE__ */ jsxs3("figure", { className: "my-3", children: [
|
|
344
|
-
label ? /* @__PURE__ */
|
|
345
|
-
/* @__PURE__ */
|
|
369
|
+
label ? /* @__PURE__ */ jsx7("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: label }) : null,
|
|
370
|
+
/* @__PURE__ */ jsx7("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3", children })
|
|
346
371
|
] });
|
|
347
372
|
}
|
|
348
373
|
function DocCode({ entry }) {
|
|
349
374
|
const renderers = useBuiltinRenderers();
|
|
350
375
|
if (renderers.code) {
|
|
351
|
-
return /* @__PURE__ */
|
|
376
|
+
return /* @__PURE__ */ jsx7(Fragment, { children: renderers.code(entry) });
|
|
352
377
|
}
|
|
353
|
-
return /* @__PURE__ */
|
|
378
|
+
return /* @__PURE__ */ jsx7(CodeFigure, { label: entry.label, children: /* @__PURE__ */ jsx7("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
354
379
|
}
|
|
355
380
|
|
|
356
381
|
// src/components/doc/DocTable.tsx
|
|
357
|
-
import { jsx as
|
|
382
|
+
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
358
383
|
function DocTable({ entry }) {
|
|
359
384
|
return /* @__PURE__ */ jsxs4("figure", { className: "my-3", children: [
|
|
360
|
-
entry.label ? /* @__PURE__ */
|
|
361
|
-
/* @__PURE__ */
|
|
362
|
-
/* @__PURE__ */
|
|
363
|
-
/* @__PURE__ */
|
|
385
|
+
entry.label ? /* @__PURE__ */ jsx8("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.label }) : null,
|
|
386
|
+
/* @__PURE__ */ jsx8("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ jsxs4("table", { className: "w-full border-collapse text-sm", children: [
|
|
387
|
+
/* @__PURE__ */ jsx8("thead", { children: /* @__PURE__ */ jsx8("tr", { className: "bg-muted/50", children: entry.columns.map((c) => /* @__PURE__ */ jsx8("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: c }, c)) }) }),
|
|
388
|
+
/* @__PURE__ */ jsx8("tbody", { children: entry.rows.map((row, i) => /* @__PURE__ */ jsx8("tr", { children: row.map((cell, j) => /* @__PURE__ */ jsx8("td", { className: "border-b border-border px-3 py-2 text-foreground", children: cell }, j)) }, i)) })
|
|
364
389
|
] }) })
|
|
365
390
|
] });
|
|
366
391
|
}
|
|
367
392
|
|
|
368
393
|
// src/components/doc/DocLink.tsx
|
|
369
|
-
import { jsx as
|
|
394
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
370
395
|
function DocLink({ entry }) {
|
|
371
|
-
return /* @__PURE__ */
|
|
396
|
+
return /* @__PURE__ */ jsx9(
|
|
372
397
|
"a",
|
|
373
398
|
{
|
|
374
399
|
className: "text-sm font-medium text-primary underline underline-offset-2 hover:no-underline",
|
|
@@ -380,30 +405,38 @@ function DocLink({ entry }) {
|
|
|
380
405
|
);
|
|
381
406
|
}
|
|
382
407
|
|
|
383
|
-
// src/
|
|
408
|
+
// src/lib/markdown.ts
|
|
384
409
|
import { marked } from "marked";
|
|
385
410
|
|
|
386
411
|
// src/lib/url.ts
|
|
387
412
|
import { safeUrl, safeImageUrl, isLocalFsPath } from "executable-stories-core/utils/url";
|
|
388
413
|
|
|
389
|
-
// src/
|
|
390
|
-
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
391
|
-
function neutralizeUrl(value) {
|
|
392
|
-
return safeUrl(value) ?? "#";
|
|
393
|
-
}
|
|
414
|
+
// src/lib/markdown.ts
|
|
394
415
|
function safeMarkdownHtml(markdown) {
|
|
395
416
|
const raw = marked.parse(markdown, { async: false });
|
|
396
417
|
return raw.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<\/?(?:iframe|object|embed|form|base)\b[^>]*>/gi, "").replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, "").replace(/\son[a-z]+\s*=\s*'[^']*'/gi, "").replace(/\son[a-z]+\s*=\s*[^\s>]+/gi, "").replace(/(href|src)\s*=\s*"([^"]*)"/gi, (_m, attr, val) => `${attr}="${neutralizeUrl(val)}"`).replace(/(href|src)\s*=\s*'([^']*)'/gi, (_m, attr, val) => `${attr}='${neutralizeUrl(val)}'`);
|
|
397
418
|
}
|
|
419
|
+
function dedent(text) {
|
|
420
|
+
const lines = text.replace(/\t/g, " ").split("\n");
|
|
421
|
+
const indents = lines.filter((line) => line.trim().length > 0).map((line) => line.length - line.trimStart().length);
|
|
422
|
+
const shortest = indents.length > 0 ? Math.min(...indents) : 0;
|
|
423
|
+
return lines.map((line) => line.slice(shortest)).join("\n").trim();
|
|
424
|
+
}
|
|
425
|
+
function neutralizeUrl(value) {
|
|
426
|
+
return safeUrl(value) ?? "#";
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// src/components/doc/DocSection.tsx
|
|
430
|
+
import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
398
431
|
function DocSection({ entry }) {
|
|
399
432
|
const renderers = useBuiltinRenderers();
|
|
400
433
|
if (renderers.section) {
|
|
401
|
-
return /* @__PURE__ */
|
|
434
|
+
return /* @__PURE__ */ jsx10(Fragment2, { children: renderers.section(entry) });
|
|
402
435
|
}
|
|
403
436
|
const html = safeMarkdownHtml(entry.markdown);
|
|
404
437
|
return /* @__PURE__ */ jsxs5("section", { className: "my-3 text-sm", "aria-label": entry.title, children: [
|
|
405
|
-
entry.title ? /* @__PURE__ */
|
|
406
|
-
/* @__PURE__ */
|
|
438
|
+
entry.title ? /* @__PURE__ */ jsx10("h4", { className: "mb-1 font-semibold text-foreground", children: entry.title }) : null,
|
|
439
|
+
/* @__PURE__ */ jsx10(
|
|
407
440
|
"div",
|
|
408
441
|
{
|
|
409
442
|
className: "es-doc-prose prose prose-sm max-w-none",
|
|
@@ -414,11 +447,11 @@ function DocSection({ entry }) {
|
|
|
414
447
|
}
|
|
415
448
|
|
|
416
449
|
// src/components/doc/DocMermaid.tsx
|
|
417
|
-
import { Fragment as Fragment3, jsx as
|
|
450
|
+
import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
418
451
|
function MermaidSource({ entry, ref }) {
|
|
419
452
|
return /* @__PURE__ */ jsxs6("figure", { ref, className: "my-3", "aria-label": entry.title ?? "Diagram", children: [
|
|
420
|
-
entry.title ? /* @__PURE__ */
|
|
421
|
-
/* @__PURE__ */
|
|
453
|
+
entry.title ? /* @__PURE__ */ jsx11("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
454
|
+
/* @__PURE__ */ jsx11(
|
|
422
455
|
"pre",
|
|
423
456
|
{
|
|
424
457
|
"data-mermaid": true,
|
|
@@ -432,24 +465,24 @@ function MermaidSource({ entry, ref }) {
|
|
|
432
465
|
function DocMermaid({ entry }) {
|
|
433
466
|
const renderers = useBuiltinRenderers();
|
|
434
467
|
if (renderers.mermaid) {
|
|
435
|
-
return /* @__PURE__ */
|
|
468
|
+
return /* @__PURE__ */ jsx11(Fragment3, { children: renderers.mermaid(entry) });
|
|
436
469
|
}
|
|
437
|
-
return /* @__PURE__ */
|
|
470
|
+
return /* @__PURE__ */ jsx11(MermaidSource, { entry });
|
|
438
471
|
}
|
|
439
472
|
|
|
440
473
|
// src/components/doc/DocScreenshot.tsx
|
|
441
|
-
import { jsx as
|
|
474
|
+
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
442
475
|
function DocScreenshot({ entry }) {
|
|
443
476
|
const src = isLocalFsPath(entry.path) ? void 0 : safeImageUrl(entry.path);
|
|
444
477
|
if (!src) {
|
|
445
478
|
return /* @__PURE__ */ jsxs7("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
|
|
446
|
-
/* @__PURE__ */
|
|
447
|
-
/* @__PURE__ */
|
|
448
|
-
entry.alt ? /* @__PURE__ */
|
|
479
|
+
/* @__PURE__ */ jsx12("div", { className: "font-medium", children: "Screenshot unavailable" }),
|
|
480
|
+
/* @__PURE__ */ jsx12("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
481
|
+
entry.alt ? /* @__PURE__ */ jsx12("figcaption", { className: "mt-1.5 text-xs", children: entry.alt }) : null
|
|
449
482
|
] });
|
|
450
483
|
}
|
|
451
484
|
return /* @__PURE__ */ jsxs7("figure", { className: "my-3", children: [
|
|
452
|
-
/* @__PURE__ */
|
|
485
|
+
/* @__PURE__ */ jsx12(
|
|
453
486
|
"img",
|
|
454
487
|
{
|
|
455
488
|
src,
|
|
@@ -458,24 +491,24 @@ function DocScreenshot({ entry }) {
|
|
|
458
491
|
className: "max-w-full rounded-md border border-border"
|
|
459
492
|
}
|
|
460
493
|
),
|
|
461
|
-
entry.alt ? /* @__PURE__ */
|
|
494
|
+
entry.alt ? /* @__PURE__ */ jsx12("figcaption", { className: "mt-1.5 text-xs text-muted-foreground", children: entry.alt }) : null
|
|
462
495
|
] });
|
|
463
496
|
}
|
|
464
497
|
|
|
465
498
|
// src/components/doc/DocVideo.tsx
|
|
466
|
-
import { jsx as
|
|
499
|
+
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
467
500
|
function DocVideo({ entry }) {
|
|
468
501
|
if (isLocalFsPath(entry.path)) {
|
|
469
502
|
return /* @__PURE__ */ jsxs8("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
|
|
470
|
-
/* @__PURE__ */
|
|
471
|
-
/* @__PURE__ */
|
|
472
|
-
entry.caption ? /* @__PURE__ */
|
|
503
|
+
/* @__PURE__ */ jsx13("div", { className: "font-medium", children: "Video unavailable" }),
|
|
504
|
+
/* @__PURE__ */ jsx13("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
505
|
+
entry.caption ? /* @__PURE__ */ jsx13("figcaption", { className: "mt-1.5 text-xs", children: entry.caption }) : null
|
|
473
506
|
] });
|
|
474
507
|
}
|
|
475
508
|
const src = safeUrl(entry.path);
|
|
476
509
|
const poster = safeUrl(entry.poster);
|
|
477
510
|
return /* @__PURE__ */ jsxs8("figure", { className: "my-3", children: [
|
|
478
|
-
/* @__PURE__ */
|
|
511
|
+
/* @__PURE__ */ jsx13(
|
|
479
512
|
"video",
|
|
480
513
|
{
|
|
481
514
|
controls: true,
|
|
@@ -485,12 +518,12 @@ function DocVideo({ entry }) {
|
|
|
485
518
|
className: "max-w-full rounded-md border border-border"
|
|
486
519
|
}
|
|
487
520
|
),
|
|
488
|
-
entry.caption ? /* @__PURE__ */
|
|
521
|
+
entry.caption ? /* @__PURE__ */ jsx13("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: entry.caption }) : null
|
|
489
522
|
] });
|
|
490
523
|
}
|
|
491
524
|
|
|
492
525
|
// src/components/doc/DocHtml.tsx
|
|
493
|
-
import { jsx as
|
|
526
|
+
import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
494
527
|
function DocHtml({ entry }) {
|
|
495
528
|
const height = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
496
529
|
const title = entry.title ?? "Embedded HTML";
|
|
@@ -498,8 +531,8 @@ function DocHtml({ entry }) {
|
|
|
498
531
|
const frameProps = entry.content !== void 0 ? { srcDoc: entry.content } : { src: safeHref ?? "" };
|
|
499
532
|
return /* @__PURE__ */ jsxs9("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
|
|
500
533
|
/* @__PURE__ */ jsxs9("figcaption", { className: "flex items-center justify-between border-b border-border bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground", children: [
|
|
501
|
-
/* @__PURE__ */
|
|
502
|
-
safeHref ? /* @__PURE__ */
|
|
534
|
+
/* @__PURE__ */ jsx14("span", { children: entry.title ?? "HTML" }),
|
|
535
|
+
safeHref ? /* @__PURE__ */ jsx14(
|
|
503
536
|
"a",
|
|
504
537
|
{
|
|
505
538
|
href: safeHref,
|
|
@@ -512,7 +545,7 @@ function DocHtml({ entry }) {
|
|
|
512
545
|
}
|
|
513
546
|
) : null
|
|
514
547
|
] }),
|
|
515
|
-
/* @__PURE__ */
|
|
548
|
+
/* @__PURE__ */ jsx14(
|
|
516
549
|
"iframe",
|
|
517
550
|
{
|
|
518
551
|
...frameProps,
|
|
@@ -527,7 +560,7 @@ function DocHtml({ entry }) {
|
|
|
527
560
|
}
|
|
528
561
|
|
|
529
562
|
// src/components/doc/DocState.tsx
|
|
530
|
-
import { jsx as
|
|
563
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
531
564
|
function DocState({ entry }) {
|
|
532
565
|
let json;
|
|
533
566
|
try {
|
|
@@ -535,20 +568,20 @@ function DocState({ entry }) {
|
|
|
535
568
|
} catch {
|
|
536
569
|
json = String(entry.value);
|
|
537
570
|
}
|
|
538
|
-
return /* @__PURE__ */
|
|
571
|
+
return /* @__PURE__ */ jsx15(CodeFigure, { label: entry.label ?? "State", children: /* @__PURE__ */ jsx15("code", { className: "font-mono text-xs language-json", children: json }) });
|
|
539
572
|
}
|
|
540
573
|
|
|
541
574
|
// src/components/doc/DocCustom.tsx
|
|
542
|
-
import { Fragment as Fragment4, jsx as
|
|
575
|
+
import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
543
576
|
function DocCustom({ entry }) {
|
|
544
577
|
const renderers = useCustomRenderers();
|
|
545
578
|
const renderer = renderers[entry.type];
|
|
546
579
|
if (renderer) {
|
|
547
|
-
return /* @__PURE__ */
|
|
580
|
+
return /* @__PURE__ */ jsx16(Fragment4, { children: renderer(entry) });
|
|
548
581
|
}
|
|
549
582
|
return /* @__PURE__ */ jsxs10("div", { className: "my-2", "data-type": entry.type, children: [
|
|
550
|
-
/* @__PURE__ */
|
|
551
|
-
/* @__PURE__ */
|
|
583
|
+
/* @__PURE__ */ jsx16("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
|
|
584
|
+
/* @__PURE__ */ jsx16("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground", children: safeStringify2(entry.data) })
|
|
552
585
|
] });
|
|
553
586
|
}
|
|
554
587
|
function safeStringify2(value) {
|
|
@@ -560,64 +593,43 @@ function safeStringify2(value) {
|
|
|
560
593
|
}
|
|
561
594
|
|
|
562
595
|
// src/components/doc/DocEntry.tsx
|
|
563
|
-
import { jsx as
|
|
596
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
564
597
|
function DocEntry({ entry }) {
|
|
565
598
|
switch (entry.kind) {
|
|
566
599
|
case "note":
|
|
567
|
-
return /* @__PURE__ */
|
|
600
|
+
return /* @__PURE__ */ jsx17(DocNote, { entry });
|
|
568
601
|
case "tag":
|
|
569
|
-
return /* @__PURE__ */
|
|
602
|
+
return /* @__PURE__ */ jsx17(DocTag, { entry });
|
|
570
603
|
case "kv":
|
|
571
|
-
return /* @__PURE__ */
|
|
604
|
+
return /* @__PURE__ */ jsx17(DocKv, { entry });
|
|
572
605
|
case "code":
|
|
573
|
-
return /* @__PURE__ */
|
|
606
|
+
return /* @__PURE__ */ jsx17(DocCode, { entry });
|
|
574
607
|
case "table":
|
|
575
|
-
return /* @__PURE__ */
|
|
608
|
+
return /* @__PURE__ */ jsx17(DocTable, { entry });
|
|
576
609
|
case "link":
|
|
577
|
-
return /* @__PURE__ */
|
|
610
|
+
return /* @__PURE__ */ jsx17(DocLink, { entry });
|
|
578
611
|
case "section":
|
|
579
|
-
return /* @__PURE__ */
|
|
612
|
+
return /* @__PURE__ */ jsx17(DocSection, { entry });
|
|
580
613
|
case "mermaid":
|
|
581
|
-
return /* @__PURE__ */
|
|
614
|
+
return /* @__PURE__ */ jsx17(DocMermaid, { entry });
|
|
582
615
|
case "screenshot":
|
|
583
|
-
return /* @__PURE__ */
|
|
616
|
+
return /* @__PURE__ */ jsx17(DocScreenshot, { entry });
|
|
584
617
|
case "video":
|
|
585
|
-
return /* @__PURE__ */
|
|
618
|
+
return /* @__PURE__ */ jsx17(DocVideo, { entry });
|
|
586
619
|
case "html":
|
|
587
|
-
return /* @__PURE__ */
|
|
620
|
+
return /* @__PURE__ */ jsx17(DocHtml, { entry });
|
|
588
621
|
case "state":
|
|
589
|
-
return /* @__PURE__ */
|
|
622
|
+
return /* @__PURE__ */ jsx17(DocState, { entry });
|
|
590
623
|
case "custom":
|
|
591
|
-
return /* @__PURE__ */
|
|
624
|
+
return /* @__PURE__ */ jsx17(DocCustom, { entry });
|
|
592
625
|
}
|
|
593
626
|
}
|
|
594
627
|
|
|
595
628
|
// src/components/ReportDocEntries.tsx
|
|
596
|
-
import { Fragment as Fragment5, jsx as
|
|
629
|
+
import { Fragment as Fragment5, jsx as jsx18 } from "react/jsx-runtime";
|
|
597
630
|
function ReportDocEntries({ entries }) {
|
|
598
631
|
if (entries.length === 0) return null;
|
|
599
|
-
return /* @__PURE__ */
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
// src/lib/step-params.tsx
|
|
603
|
-
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
604
|
-
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
605
|
-
function highlightStepParams(text) {
|
|
606
|
-
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
607
|
-
if (matches.length === 0) return text;
|
|
608
|
-
const nodes = [];
|
|
609
|
-
let lastIndex = 0;
|
|
610
|
-
matches.forEach((match, i) => {
|
|
611
|
-
const start = match.index;
|
|
612
|
-
const end = start + match[0].length;
|
|
613
|
-
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
614
|
-
nodes.push(
|
|
615
|
-
/* @__PURE__ */ jsx18("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
616
|
-
);
|
|
617
|
-
lastIndex = end;
|
|
618
|
-
});
|
|
619
|
-
if (lastIndex < text.length) nodes.push(text.slice(lastIndex));
|
|
620
|
-
return nodes;
|
|
632
|
+
return /* @__PURE__ */ jsx18(Fragment5, { children: entries.map((entry, i) => /* @__PURE__ */ jsx18(DocEntry, { entry }, i)) });
|
|
621
633
|
}
|
|
622
634
|
|
|
623
635
|
// src/components/ReportSteps.tsx
|
|
@@ -636,9 +648,22 @@ var STEP_GLYPH_COLOR = {
|
|
|
636
648
|
};
|
|
637
649
|
function ReportSteps({ scenario }) {
|
|
638
650
|
if (scenario.steps.length === 0) return null;
|
|
639
|
-
|
|
651
|
+
const unasserted = new Set(
|
|
652
|
+
assertionState(scenario.steps) === "unasserted" ? assertiveSteps(scenario.steps).map((step) => step.id) : []
|
|
653
|
+
);
|
|
654
|
+
return /* @__PURE__ */ jsx19("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ jsx19(
|
|
655
|
+
ReportStepItem,
|
|
656
|
+
{
|
|
657
|
+
step,
|
|
658
|
+
unasserted: unasserted.has(step.id)
|
|
659
|
+
},
|
|
660
|
+
step.id
|
|
661
|
+
)) });
|
|
640
662
|
}
|
|
641
|
-
function ReportStepItem({
|
|
663
|
+
function ReportStepItem({
|
|
664
|
+
step,
|
|
665
|
+
unasserted = false
|
|
666
|
+
}) {
|
|
642
667
|
const kw = step.keyword.toLowerCase();
|
|
643
668
|
const continuation = kw === "and" || kw === "but";
|
|
644
669
|
return /* @__PURE__ */ jsxs11(
|
|
@@ -646,10 +671,23 @@ function ReportStepItem({ step }) {
|
|
|
646
671
|
{
|
|
647
672
|
id: step.id,
|
|
648
673
|
"data-status": step.status,
|
|
649
|
-
className: cn(
|
|
674
|
+
className: cn(
|
|
675
|
+
"py-1.5 text-[0.8125rem] leading-normal",
|
|
676
|
+
continuation && "pl-5"
|
|
677
|
+
),
|
|
650
678
|
children: [
|
|
651
679
|
/* @__PURE__ */ jsxs11("div", { className: "flex items-baseline gap-2", children: [
|
|
652
|
-
/* @__PURE__ */ jsx19(
|
|
680
|
+
/* @__PURE__ */ jsx19(
|
|
681
|
+
"span",
|
|
682
|
+
{
|
|
683
|
+
"aria-hidden": true,
|
|
684
|
+
className: cn(
|
|
685
|
+
"w-4 shrink-0 text-center text-xs",
|
|
686
|
+
STEP_GLYPH_COLOR[step.status]
|
|
687
|
+
),
|
|
688
|
+
children: STEP_GLYPH[step.status] ?? "\u25CB"
|
|
689
|
+
}
|
|
690
|
+
),
|
|
653
691
|
/* @__PURE__ */ jsx19(
|
|
654
692
|
"span",
|
|
655
693
|
{
|
|
@@ -661,6 +699,7 @@ function ReportStepItem({ step }) {
|
|
|
661
699
|
}
|
|
662
700
|
),
|
|
663
701
|
/* @__PURE__ */ jsx19("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
|
|
702
|
+
unasserted ? /* @__PURE__ */ jsx19("span", { className: "shrink-0 rounded-full border border-pend-border bg-pend-bg px-2 py-0.5 text-[0.6875rem] font-medium text-pend", children: "No assertion" }) : null,
|
|
664
703
|
step.durationMs > 0 ? /* @__PURE__ */ jsx19("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(step.durationMs) }) : null
|
|
665
704
|
] }),
|
|
666
705
|
step.errorMessage ? /* @__PURE__ */ jsx19(
|
|
@@ -1056,21 +1095,95 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
1056
1095
|
] });
|
|
1057
1096
|
}
|
|
1058
1097
|
|
|
1098
|
+
// src/components/ScenarioStaleness.tsx
|
|
1099
|
+
import { useEffect, useState } from "react";
|
|
1100
|
+
|
|
1101
|
+
// src/lib/provenance.ts
|
|
1102
|
+
function formatRelativeAge(thenMs, nowMs) {
|
|
1103
|
+
const deltaMs = Math.max(0, nowMs - thenMs);
|
|
1104
|
+
const minutes = Math.floor(deltaMs / 6e4);
|
|
1105
|
+
if (minutes < 1) return "just now";
|
|
1106
|
+
if (minutes < 60) return `${minutes} minute${minutes === 1 ? "" : "s"} ago`;
|
|
1107
|
+
const hours = Math.floor(minutes / 60);
|
|
1108
|
+
if (hours < 24) return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
|
1109
|
+
const days = Math.floor(hours / 24);
|
|
1110
|
+
return `${days} day${days === 1 ? "" : "s"} ago`;
|
|
1111
|
+
}
|
|
1112
|
+
function isReportStale(lastRunMs, staleAfterDays, nowMs) {
|
|
1113
|
+
if (lastRunMs === void 0 || staleAfterDays <= 0) return false;
|
|
1114
|
+
return nowMs - lastRunMs >= staleAfterDays * 864e5;
|
|
1115
|
+
}
|
|
1116
|
+
var CI_DISPLAY_NAMES = {
|
|
1117
|
+
github: "GitHub Actions",
|
|
1118
|
+
gitlab: "GitLab CI",
|
|
1119
|
+
circleci: "CircleCI",
|
|
1120
|
+
jenkins: "Jenkins",
|
|
1121
|
+
azure: "Azure DevOps",
|
|
1122
|
+
buildkite: "Buildkite",
|
|
1123
|
+
travis: "Travis CI",
|
|
1124
|
+
ci: "CI"
|
|
1125
|
+
};
|
|
1126
|
+
function ciDisplayName(name) {
|
|
1127
|
+
return CI_DISPLAY_NAMES[name] ?? name;
|
|
1128
|
+
}
|
|
1129
|
+
function commitUrl(ci, sha) {
|
|
1130
|
+
const commitSha = ci?.commitSha ?? sha;
|
|
1131
|
+
if (!ci?.url || !commitSha) return void 0;
|
|
1132
|
+
const github = ci.url.match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)\/actions\/runs\//);
|
|
1133
|
+
if (github) return `${github[1]}/commit/${commitSha}`;
|
|
1134
|
+
const gitlab = ci.url.match(/^(https?:\/\/.+)\/-\/pipelines\//);
|
|
1135
|
+
if (gitlab) return `${gitlab[1]}/-/commit/${commitSha}`;
|
|
1136
|
+
return void 0;
|
|
1137
|
+
}
|
|
1138
|
+
function prUrl(ci) {
|
|
1139
|
+
if (!ci?.url || !ci.prNumber) return void 0;
|
|
1140
|
+
const github = ci.url.match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)\/actions\/runs\//);
|
|
1141
|
+
if (github) return `${github[1]}/pull/${ci.prNumber}`;
|
|
1142
|
+
return void 0;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
// src/interactive/scenario-freshness-context.tsx
|
|
1146
|
+
import { createContext as createContext3, useContext as useContext4 } from "react";
|
|
1147
|
+
var ScenarioFreshnessContext = createContext3(null);
|
|
1148
|
+
var ScenarioFreshnessProvider = ScenarioFreshnessContext.Provider;
|
|
1149
|
+
function useScenarioFreshness() {
|
|
1150
|
+
return useContext4(ScenarioFreshnessContext);
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
// src/components/ScenarioStaleness.tsx
|
|
1154
|
+
import { jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1155
|
+
function ScenarioStaleness({ scenario }) {
|
|
1156
|
+
const freshness = useScenarioFreshness();
|
|
1157
|
+
const fixedNow = freshness?.nowMs;
|
|
1158
|
+
const [now, setNow] = useState(fixedNow);
|
|
1159
|
+
useEffect(() => {
|
|
1160
|
+
if (fixedNow === void 0) setNow(Date.now());
|
|
1161
|
+
}, [fixedNow]);
|
|
1162
|
+
if (!freshness || now === void 0) return null;
|
|
1163
|
+
const lastRunAtMs = scenario.lastRunAtMs;
|
|
1164
|
+
if (!lastRunAtMs || lastRunAtMs <= 0) return null;
|
|
1165
|
+
if (!isReportStale(lastRunAtMs, freshness.staleAfterDays, now)) return null;
|
|
1166
|
+
return /* @__PURE__ */ jsxs16(Badge, { variant: "outline", "aria-label": "Scenario freshness", children: [
|
|
1167
|
+
"Last ran ",
|
|
1168
|
+
formatRelativeAge(lastRunAtMs, now)
|
|
1169
|
+
] });
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1059
1172
|
// src/interactive/collapse-context.ts
|
|
1060
|
-
import { createContext as
|
|
1061
|
-
var CollapseContext =
|
|
1173
|
+
import { createContext as createContext4, useCallback, useContext as useContext5, useState as useState2 } from "react";
|
|
1174
|
+
var CollapseContext = createContext4(null);
|
|
1062
1175
|
var CollapseProvider = CollapseContext.Provider;
|
|
1063
1176
|
function useCollapse() {
|
|
1064
|
-
return
|
|
1177
|
+
return useContext5(CollapseContext);
|
|
1065
1178
|
}
|
|
1066
1179
|
|
|
1067
1180
|
// src/interactive/scenario-actions.tsx
|
|
1068
|
-
import { createContext as
|
|
1181
|
+
import { createContext as createContext5, useContext as useContext6 } from "react";
|
|
1069
1182
|
import { scenarioToMarkdown as coreScenarioToMarkdown } from "executable-stories-core/utils/scenario-markdown";
|
|
1070
|
-
var ScenarioActionsContext =
|
|
1183
|
+
var ScenarioActionsContext = createContext5(null);
|
|
1071
1184
|
var ScenarioActionsProvider = ScenarioActionsContext.Provider;
|
|
1072
1185
|
function useScenarioActions() {
|
|
1073
|
-
return
|
|
1186
|
+
return useContext6(ScenarioActionsContext);
|
|
1074
1187
|
}
|
|
1075
1188
|
|
|
1076
1189
|
// src/components/ui/card.tsx
|
|
@@ -1117,7 +1230,7 @@ function CardContent({ className, ...props }) {
|
|
|
1117
1230
|
import "react";
|
|
1118
1231
|
import { Menu as MenuPrimitive } from "@base-ui/react/menu";
|
|
1119
1232
|
import { CheckIcon } from "lucide-react";
|
|
1120
|
-
import { jsx as jsx25, jsxs as
|
|
1233
|
+
import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1121
1234
|
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";
|
|
1122
1235
|
function DropdownMenu(props) {
|
|
1123
1236
|
return /* @__PURE__ */ jsx25(MenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
@@ -1168,7 +1281,7 @@ function DropdownMenuItem({
|
|
|
1168
1281
|
|
|
1169
1282
|
// src/components/ReportScenario.tsx
|
|
1170
1283
|
import { LinkIcon, FileTextIcon, SparklesIcon, MoreHorizontalIcon } from "lucide-react";
|
|
1171
|
-
import { jsx as jsx26, jsxs as
|
|
1284
|
+
import { jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1172
1285
|
var STATUS_META = {
|
|
1173
1286
|
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
1174
1287
|
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
@@ -1184,7 +1297,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1184
1297
|
const collapsible = collapse !== null && !hideTitle;
|
|
1185
1298
|
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
1186
1299
|
const actions = useScenarioActions();
|
|
1187
|
-
return /* @__PURE__ */
|
|
1300
|
+
return /* @__PURE__ */ jsxs18(
|
|
1188
1301
|
Card,
|
|
1189
1302
|
{
|
|
1190
1303
|
id: scenario.id,
|
|
@@ -1192,9 +1305,9 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1192
1305
|
...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
|
|
1193
1306
|
className: "gap-0 py-0",
|
|
1194
1307
|
children: [
|
|
1195
|
-
/* @__PURE__ */
|
|
1196
|
-
/* @__PURE__ */
|
|
1197
|
-
hideTitle ? null : /* @__PURE__ */
|
|
1308
|
+
/* @__PURE__ */ jsxs18(CardHeader, { className: "px-4 py-3", children: [
|
|
1309
|
+
/* @__PURE__ */ jsxs18("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
1310
|
+
hideTitle ? null : /* @__PURE__ */ jsxs18("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
1198
1311
|
collapsible ? /* @__PURE__ */ jsx26(
|
|
1199
1312
|
"button",
|
|
1200
1313
|
{
|
|
@@ -1210,11 +1323,12 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1210
1323
|
/* @__PURE__ */ jsx26("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
1211
1324
|
/* @__PURE__ */ jsx26("span", { children: scenario.title })
|
|
1212
1325
|
] }),
|
|
1213
|
-
/* @__PURE__ */
|
|
1326
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1214
1327
|
/* @__PURE__ */ jsx26(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1328
|
+
/* @__PURE__ */ jsx26(ScenarioStaleness, { scenario }),
|
|
1215
1329
|
scenario.durationMs > 0 ? /* @__PURE__ */ jsx26("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration3(scenario.durationMs) }) : null,
|
|
1216
1330
|
meta.showPill ? /* @__PURE__ */ jsx26(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ jsx26("span", { className: "sr-only", children: `Status: ${label}` }),
|
|
1217
|
-
actions ? /* @__PURE__ */
|
|
1331
|
+
actions ? /* @__PURE__ */ jsxs18(DropdownMenu, { children: [
|
|
1218
1332
|
/* @__PURE__ */ jsx26(
|
|
1219
1333
|
DropdownMenuTrigger,
|
|
1220
1334
|
{
|
|
@@ -1223,16 +1337,16 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1223
1337
|
children: /* @__PURE__ */ jsx26(MoreHorizontalIcon, { "aria-hidden": true })
|
|
1224
1338
|
}
|
|
1225
1339
|
),
|
|
1226
|
-
/* @__PURE__ */
|
|
1227
|
-
/* @__PURE__ */
|
|
1340
|
+
/* @__PURE__ */ jsxs18(DropdownMenuContent, { align: "end", children: [
|
|
1341
|
+
/* @__PURE__ */ jsxs18(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
1228
1342
|
/* @__PURE__ */ jsx26(LinkIcon, {}),
|
|
1229
1343
|
" Copy link"
|
|
1230
1344
|
] }),
|
|
1231
|
-
/* @__PURE__ */
|
|
1345
|
+
/* @__PURE__ */ jsxs18(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
1232
1346
|
/* @__PURE__ */ jsx26(FileTextIcon, {}),
|
|
1233
1347
|
" Copy as Markdown"
|
|
1234
1348
|
] }),
|
|
1235
|
-
/* @__PURE__ */
|
|
1349
|
+
/* @__PURE__ */ jsxs18(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
1236
1350
|
/* @__PURE__ */ jsx26(SparklesIcon, {}),
|
|
1237
1351
|
" Explain with AI"
|
|
1238
1352
|
] })
|
|
@@ -1240,12 +1354,12 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1240
1354
|
] }) : null
|
|
1241
1355
|
] })
|
|
1242
1356
|
] }),
|
|
1243
|
-
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */
|
|
1357
|
+
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs18("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
|
|
1244
1358
|
scenario.tags.map((t) => /* @__PURE__ */ jsx26("li", { children: /* @__PURE__ */ jsx26(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
|
|
1245
1359
|
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ jsx26("li", { children: ticket.url ? /* @__PURE__ */ jsx26("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ jsx26(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ jsx26(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
|
|
1246
1360
|
] }) : null
|
|
1247
1361
|
] }),
|
|
1248
|
-
/* @__PURE__ */
|
|
1362
|
+
/* @__PURE__ */ jsxs18(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
1249
1363
|
scenario.errorMessage ? /* @__PURE__ */ jsx26(
|
|
1250
1364
|
"pre",
|
|
1251
1365
|
{
|
|
@@ -1271,8 +1385,35 @@ function ReportScenarioList({ feature }) {
|
|
|
1271
1385
|
return /* @__PURE__ */ jsx27(Fragment8, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ jsx27(ReportScenario, { scenario }, scenario.id)) });
|
|
1272
1386
|
}
|
|
1273
1387
|
|
|
1388
|
+
// src/components/ReportFeatureIntro.tsx
|
|
1389
|
+
import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1390
|
+
function ReportFeatureIntro({ feature }) {
|
|
1391
|
+
const hasNarrative = Boolean(feature.narrative?.trim());
|
|
1392
|
+
const hasGlossary = Boolean(feature.glossary?.length);
|
|
1393
|
+
if (!hasNarrative && !hasGlossary) return null;
|
|
1394
|
+
return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-3 border-l-2 border-border pl-4 text-sm", children: [
|
|
1395
|
+
hasNarrative ? /* @__PURE__ */ jsx28(
|
|
1396
|
+
"div",
|
|
1397
|
+
{
|
|
1398
|
+
className: "es-doc-prose prose prose-sm max-w-none text-muted-foreground",
|
|
1399
|
+
dangerouslySetInnerHTML: { __html: safeMarkdownHtml(dedent(feature.narrative)) }
|
|
1400
|
+
}
|
|
1401
|
+
) : null,
|
|
1402
|
+
hasGlossary ? /* @__PURE__ */ jsx28("dl", { className: "grid gap-1.5", "aria-label": "Glossary", children: feature.glossary.map((entry) => /* @__PURE__ */ jsxs19("div", { className: "flex flex-wrap gap-x-2 text-xs", children: [
|
|
1403
|
+
/* @__PURE__ */ jsx28("dt", { className: "font-medium text-foreground", children: entry.term }),
|
|
1404
|
+
/* @__PURE__ */ jsx28("dd", { className: "flex-1 text-muted-foreground", children: entry.definition })
|
|
1405
|
+
] }, entry.term)) }) : null
|
|
1406
|
+
] });
|
|
1407
|
+
}
|
|
1408
|
+
function featureKindLabel(kind) {
|
|
1409
|
+
if (kind === "ability") return "Ability";
|
|
1410
|
+
if (kind === "business-need") return "Business need";
|
|
1411
|
+
if (kind === "feature") return "Feature";
|
|
1412
|
+
return null;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1274
1415
|
// src/components/ReportFeature.tsx
|
|
1275
|
-
import { Fragment as Fragment9, jsx as
|
|
1416
|
+
import { Fragment as Fragment9, jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1276
1417
|
function ReportFeature({ feature }) {
|
|
1277
1418
|
const titleId = `${feature.id}-title`;
|
|
1278
1419
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1280,10 +1421,11 @@ function ReportFeature({ feature }) {
|
|
|
1280
1421
|
const skipped = s.skipped + s.pending;
|
|
1281
1422
|
const collapse = useCollapse();
|
|
1282
1423
|
const collapsed = collapse?.isCollapsed(feature.id) ?? false;
|
|
1424
|
+
const kindLabel = featureKindLabel(feature.kind);
|
|
1283
1425
|
return (
|
|
1284
1426
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
1285
1427
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1286
|
-
/* @__PURE__ */
|
|
1428
|
+
/* @__PURE__ */ jsxs20(
|
|
1287
1429
|
"section",
|
|
1288
1430
|
{
|
|
1289
1431
|
id: feature.id,
|
|
@@ -1291,9 +1433,9 @@ function ReportFeature({ feature }) {
|
|
|
1291
1433
|
"aria-labelledby": titleId,
|
|
1292
1434
|
className: "flex flex-col gap-3",
|
|
1293
1435
|
children: [
|
|
1294
|
-
/* @__PURE__ */
|
|
1295
|
-
/* @__PURE__ */
|
|
1296
|
-
/* @__PURE__ */
|
|
1436
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1437
|
+
/* @__PURE__ */ jsxs20("div", { className: "min-w-0", children: [
|
|
1438
|
+
/* @__PURE__ */ jsx29("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ jsxs20(
|
|
1297
1439
|
"button",
|
|
1298
1440
|
{
|
|
1299
1441
|
type: "button",
|
|
@@ -1302,31 +1444,34 @@ function ReportFeature({ feature }) {
|
|
|
1302
1444
|
"aria-controls": bodyId,
|
|
1303
1445
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1304
1446
|
children: [
|
|
1305
|
-
/* @__PURE__ */
|
|
1306
|
-
/* @__PURE__ */
|
|
1447
|
+
/* @__PURE__ */ jsx29("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
|
|
1448
|
+
/* @__PURE__ */ jsx29("span", { className: "truncate", children: feature.title })
|
|
1307
1449
|
]
|
|
1308
1450
|
}
|
|
1309
1451
|
) : feature.title }),
|
|
1310
|
-
/* @__PURE__ */
|
|
1452
|
+
/* @__PURE__ */ jsxs20("p", { className: cn("mt-0.5 flex items-center gap-2 text-xs text-muted-foreground", collapse && "pl-5"), children: [
|
|
1453
|
+
kindLabel ? /* @__PURE__ */ jsx29("span", { className: "shrink-0 rounded-sm bg-muted px-1.5 py-0.5 font-medium text-foreground", children: kindLabel }) : null,
|
|
1454
|
+
/* @__PURE__ */ jsx29("span", { className: "truncate font-mono", children: feature.sourceFile })
|
|
1455
|
+
] })
|
|
1311
1456
|
] }),
|
|
1312
|
-
/* @__PURE__ */
|
|
1457
|
+
/* @__PURE__ */ jsxs20(
|
|
1313
1458
|
"p",
|
|
1314
1459
|
{
|
|
1315
1460
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1316
1461
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1317
1462
|
children: [
|
|
1318
|
-
/* @__PURE__ */
|
|
1463
|
+
/* @__PURE__ */ jsxs20("span", { children: [
|
|
1319
1464
|
s.passed,
|
|
1320
1465
|
" passed"
|
|
1321
1466
|
] }),
|
|
1322
|
-
/* @__PURE__ */
|
|
1323
|
-
/* @__PURE__ */
|
|
1467
|
+
/* @__PURE__ */ jsx29("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1468
|
+
/* @__PURE__ */ jsxs20("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1324
1469
|
s.failed,
|
|
1325
1470
|
" failed"
|
|
1326
1471
|
] }),
|
|
1327
|
-
skipped > 0 ? /* @__PURE__ */
|
|
1328
|
-
/* @__PURE__ */
|
|
1329
|
-
/* @__PURE__ */
|
|
1472
|
+
skipped > 0 ? /* @__PURE__ */ jsxs20(Fragment9, { children: [
|
|
1473
|
+
/* @__PURE__ */ jsx29("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1474
|
+
/* @__PURE__ */ jsxs20("span", { children: [
|
|
1330
1475
|
skipped,
|
|
1331
1476
|
" skipped"
|
|
1332
1477
|
] })
|
|
@@ -1335,7 +1480,10 @@ function ReportFeature({ feature }) {
|
|
|
1335
1480
|
}
|
|
1336
1481
|
)
|
|
1337
1482
|
] }),
|
|
1338
|
-
/* @__PURE__ */
|
|
1483
|
+
/* @__PURE__ */ jsxs20("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: [
|
|
1484
|
+
/* @__PURE__ */ jsx29(ReportFeatureIntro, { feature }),
|
|
1485
|
+
/* @__PURE__ */ jsx29(ReportScenarioList, { feature })
|
|
1486
|
+
] })
|
|
1339
1487
|
]
|
|
1340
1488
|
}
|
|
1341
1489
|
)
|
|
@@ -1343,17 +1491,17 @@ function ReportFeature({ feature }) {
|
|
|
1343
1491
|
}
|
|
1344
1492
|
|
|
1345
1493
|
// src/components/ReportFeatureList.tsx
|
|
1346
|
-
import { jsx as
|
|
1494
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
1347
1495
|
function ReportFeatureList() {
|
|
1348
1496
|
const report = useReport();
|
|
1349
|
-
return /* @__PURE__ */
|
|
1497
|
+
return /* @__PURE__ */ jsx30("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ jsx30(ReportFeature, { feature }, feature.id)) });
|
|
1350
1498
|
}
|
|
1351
1499
|
|
|
1352
1500
|
// src/components/ui/empty.tsx
|
|
1353
1501
|
import { cva as cva2 } from "class-variance-authority";
|
|
1354
|
-
import { jsx as
|
|
1502
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
1355
1503
|
function Empty({ className, ...props }) {
|
|
1356
|
-
return /* @__PURE__ */
|
|
1504
|
+
return /* @__PURE__ */ jsx31(
|
|
1357
1505
|
"div",
|
|
1358
1506
|
{
|
|
1359
1507
|
"data-slot": "empty",
|
|
@@ -1366,7 +1514,7 @@ function Empty({ className, ...props }) {
|
|
|
1366
1514
|
);
|
|
1367
1515
|
}
|
|
1368
1516
|
function EmptyHeader({ className, ...props }) {
|
|
1369
|
-
return /* @__PURE__ */
|
|
1517
|
+
return /* @__PURE__ */ jsx31(
|
|
1370
1518
|
"div",
|
|
1371
1519
|
{
|
|
1372
1520
|
"data-slot": "empty-header",
|
|
@@ -1393,7 +1541,7 @@ var emptyMediaVariants = cva2(
|
|
|
1393
1541
|
}
|
|
1394
1542
|
);
|
|
1395
1543
|
function EmptyTitle({ className, ...props }) {
|
|
1396
|
-
return /* @__PURE__ */
|
|
1544
|
+
return /* @__PURE__ */ jsx31(
|
|
1397
1545
|
"div",
|
|
1398
1546
|
{
|
|
1399
1547
|
"data-slot": "empty-title",
|
|
@@ -1404,16 +1552,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1404
1552
|
}
|
|
1405
1553
|
|
|
1406
1554
|
// src/components/ReportEmpty.tsx
|
|
1407
|
-
import { jsx as
|
|
1555
|
+
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
1408
1556
|
function ReportEmpty({ message }) {
|
|
1409
|
-
return /* @__PURE__ */
|
|
1557
|
+
return /* @__PURE__ */ jsx32(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ jsx32(EmptyHeader, { children: /* @__PURE__ */ jsx32(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
|
|
1410
1558
|
}
|
|
1411
1559
|
|
|
1412
1560
|
// src/components/ReportSummary.tsx
|
|
1413
|
-
import { jsx as
|
|
1561
|
+
import { jsx as jsx33, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1414
1562
|
function ReportSummary({ className }) {
|
|
1415
1563
|
const report = useReport();
|
|
1416
|
-
return /* @__PURE__ */
|
|
1564
|
+
return /* @__PURE__ */ jsx33(
|
|
1417
1565
|
ReportSummaryView,
|
|
1418
1566
|
{
|
|
1419
1567
|
summary: report.summary,
|
|
@@ -1439,7 +1587,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1439
1587
|
if (summary.pending > 0) {
|
|
1440
1588
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1441
1589
|
}
|
|
1442
|
-
return /* @__PURE__ */
|
|
1590
|
+
return /* @__PURE__ */ jsx33(
|
|
1443
1591
|
"dl",
|
|
1444
1592
|
{
|
|
1445
1593
|
className: cn(
|
|
@@ -1452,17 +1600,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1452
1600
|
"aria-label": ariaLabel,
|
|
1453
1601
|
children: cards.map((c) => {
|
|
1454
1602
|
const tone = TONE[c.status];
|
|
1455
|
-
return /* @__PURE__ */
|
|
1603
|
+
return /* @__PURE__ */ jsxs21(
|
|
1456
1604
|
"div",
|
|
1457
1605
|
{
|
|
1458
1606
|
"data-status": c.status,
|
|
1459
1607
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1460
1608
|
children: [
|
|
1461
|
-
/* @__PURE__ */
|
|
1462
|
-
/* @__PURE__ */
|
|
1609
|
+
/* @__PURE__ */ jsxs21("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
|
|
1610
|
+
/* @__PURE__ */ jsx33("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1463
1611
|
c.label
|
|
1464
1612
|
] }),
|
|
1465
|
-
/* @__PURE__ */
|
|
1613
|
+
/* @__PURE__ */ jsx33("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
|
|
1466
1614
|
]
|
|
1467
1615
|
},
|
|
1468
1616
|
c.status
|
|
@@ -1474,39 +1622,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1474
1622
|
|
|
1475
1623
|
// src/components/ReportMeta.tsx
|
|
1476
1624
|
import { formatDuration as formatDuration4 } from "executable-stories-core/utils/duration";
|
|
1477
|
-
|
|
1478
|
-
// src/lib/provenance.ts
|
|
1479
|
-
var CI_DISPLAY_NAMES = {
|
|
1480
|
-
github: "GitHub Actions",
|
|
1481
|
-
gitlab: "GitLab CI",
|
|
1482
|
-
circleci: "CircleCI",
|
|
1483
|
-
jenkins: "Jenkins",
|
|
1484
|
-
azure: "Azure DevOps",
|
|
1485
|
-
buildkite: "Buildkite",
|
|
1486
|
-
travis: "Travis CI",
|
|
1487
|
-
ci: "CI"
|
|
1488
|
-
};
|
|
1489
|
-
function ciDisplayName(name) {
|
|
1490
|
-
return CI_DISPLAY_NAMES[name] ?? name;
|
|
1491
|
-
}
|
|
1492
|
-
function commitUrl(ci, sha) {
|
|
1493
|
-
const commitSha = ci?.commitSha ?? sha;
|
|
1494
|
-
if (!ci?.url || !commitSha) return void 0;
|
|
1495
|
-
const github = ci.url.match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)\/actions\/runs\//);
|
|
1496
|
-
if (github) return `${github[1]}/commit/${commitSha}`;
|
|
1497
|
-
const gitlab = ci.url.match(/^(https?:\/\/.+)\/-\/pipelines\//);
|
|
1498
|
-
if (gitlab) return `${gitlab[1]}/-/commit/${commitSha}`;
|
|
1499
|
-
return void 0;
|
|
1500
|
-
}
|
|
1501
|
-
function prUrl(ci) {
|
|
1502
|
-
if (!ci?.url || !ci.prNumber) return void 0;
|
|
1503
|
-
const github = ci.url.match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)\/actions\/runs\//);
|
|
1504
|
-
if (github) return `${github[1]}/pull/${ci.prNumber}`;
|
|
1505
|
-
return void 0;
|
|
1506
|
-
}
|
|
1507
|
-
|
|
1508
|
-
// src/components/ReportMeta.tsx
|
|
1509
|
-
import { jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1625
|
+
import { jsx as jsx34, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1510
1626
|
function ReportMeta() {
|
|
1511
1627
|
const report = useReport();
|
|
1512
1628
|
const items = [];
|
|
@@ -1529,13 +1645,13 @@ function ReportMeta() {
|
|
|
1529
1645
|
const short = sha.slice(0, 8);
|
|
1530
1646
|
items.push({
|
|
1531
1647
|
label: "Commit",
|
|
1532
|
-
value: url ? /* @__PURE__ */
|
|
1648
|
+
value: url ? /* @__PURE__ */ jsx34("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1533
1649
|
});
|
|
1534
1650
|
}
|
|
1535
1651
|
if (report.ci) {
|
|
1536
1652
|
items.push({
|
|
1537
1653
|
label: "CI",
|
|
1538
|
-
value: report.ci.url ? /* @__PURE__ */
|
|
1654
|
+
value: report.ci.url ? /* @__PURE__ */ jsxs22("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1539
1655
|
ciDisplayName(report.ci.name),
|
|
1540
1656
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1541
1657
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1546,7 +1662,7 @@ function ReportMeta() {
|
|
|
1546
1662
|
const label = `#${report.ci.prNumber}`;
|
|
1547
1663
|
items.push({
|
|
1548
1664
|
label: "PR",
|
|
1549
|
-
value: url ? /* @__PURE__ */
|
|
1665
|
+
value: url ? /* @__PURE__ */ jsx34("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1550
1666
|
});
|
|
1551
1667
|
}
|
|
1552
1668
|
if (items.length === 0) return null;
|
|
@@ -1554,48 +1670,48 @@ function ReportMeta() {
|
|
|
1554
1670
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1555
1671
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1556
1672
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1557
|
-
/* @__PURE__ */
|
|
1558
|
-
/* @__PURE__ */
|
|
1559
|
-
/* @__PURE__ */
|
|
1673
|
+
/* @__PURE__ */ jsxs22("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
|
|
1674
|
+
/* @__PURE__ */ jsxs22("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: [
|
|
1675
|
+
/* @__PURE__ */ jsx34("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1560
1676
|
"Run details"
|
|
1561
1677
|
] }),
|
|
1562
|
-
/* @__PURE__ */
|
|
1563
|
-
/* @__PURE__ */
|
|
1564
|
-
/* @__PURE__ */
|
|
1678
|
+
/* @__PURE__ */ jsx34("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__ */ jsxs22("div", { className: "flex items-baseline gap-1.5", children: [
|
|
1679
|
+
/* @__PURE__ */ jsx34("dt", { className: "font-medium", children: item.label }),
|
|
1680
|
+
/* @__PURE__ */ jsx34("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1565
1681
|
] }, item.label)) })
|
|
1566
1682
|
] })
|
|
1567
1683
|
);
|
|
1568
1684
|
}
|
|
1569
1685
|
|
|
1570
1686
|
// src/components/ReportSchemaError.tsx
|
|
1571
|
-
import { jsx as
|
|
1687
|
+
import { jsx as jsx35, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1572
1688
|
function ReportSchemaError({ error }) {
|
|
1573
|
-
return /* @__PURE__ */
|
|
1574
|
-
/* @__PURE__ */
|
|
1575
|
-
/* @__PURE__ */
|
|
1576
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */
|
|
1689
|
+
return /* @__PURE__ */ jsxs23("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1690
|
+
/* @__PURE__ */ jsx35("p", { children: /* @__PURE__ */ jsx35("strong", { children: "Report could not be displayed." }) }),
|
|
1691
|
+
/* @__PURE__ */ jsx35("p", { children: error.message }),
|
|
1692
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ jsxs23("p", { children: [
|
|
1577
1693
|
"The report bundle is newer than this version of ",
|
|
1578
|
-
/* @__PURE__ */
|
|
1694
|
+
/* @__PURE__ */ jsx35("code", { children: "executable-stories-react" }),
|
|
1579
1695
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1580
1696
|
] }) : null,
|
|
1581
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */
|
|
1582
|
-
/* @__PURE__ */
|
|
1697
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ jsxs23("details", { children: [
|
|
1698
|
+
/* @__PURE__ */ jsxs23("summary", { children: [
|
|
1583
1699
|
error.issues.length,
|
|
1584
1700
|
" validation issue",
|
|
1585
1701
|
error.issues.length === 1 ? "" : "s"
|
|
1586
1702
|
] }),
|
|
1587
|
-
/* @__PURE__ */
|
|
1703
|
+
/* @__PURE__ */ jsx35("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1588
1704
|
] }) : null
|
|
1589
1705
|
] });
|
|
1590
1706
|
}
|
|
1591
1707
|
|
|
1592
1708
|
// src/components/ReportShell.tsx
|
|
1593
|
-
import { Fragment as Fragment10, jsx as
|
|
1709
|
+
import { Fragment as Fragment10, jsx as jsx36, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1594
1710
|
function ReportTitleBlock({ title }) {
|
|
1595
|
-
return /* @__PURE__ */
|
|
1596
|
-
/* @__PURE__ */
|
|
1597
|
-
/* @__PURE__ */
|
|
1598
|
-
/* @__PURE__ */
|
|
1711
|
+
return /* @__PURE__ */ jsxs24(Fragment10, { children: [
|
|
1712
|
+
/* @__PURE__ */ jsx36("h1", { children: title ?? "Story Report" }),
|
|
1713
|
+
/* @__PURE__ */ jsx36(ReportSummary, {}),
|
|
1714
|
+
/* @__PURE__ */ jsx36(ReportMeta, {})
|
|
1599
1715
|
] });
|
|
1600
1716
|
}
|
|
1601
1717
|
function ReportErrorShell({
|
|
@@ -1604,22 +1720,22 @@ function ReportErrorShell({
|
|
|
1604
1720
|
title,
|
|
1605
1721
|
dataTheme
|
|
1606
1722
|
}) {
|
|
1607
|
-
return /* @__PURE__ */
|
|
1723
|
+
return /* @__PURE__ */ jsx36("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx36(ReportSchemaError, { error }) });
|
|
1608
1724
|
}
|
|
1609
1725
|
|
|
1610
1726
|
// src/components/Report.tsx
|
|
1611
|
-
import { jsx as
|
|
1727
|
+
import { jsx as jsx37, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1612
1728
|
function Report(props) {
|
|
1613
1729
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1614
1730
|
const result = unwrapReport(report);
|
|
1615
1731
|
if (!result.ok) {
|
|
1616
|
-
return /* @__PURE__ */
|
|
1732
|
+
return /* @__PURE__ */ jsx37(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1617
1733
|
}
|
|
1618
1734
|
const data = result.data;
|
|
1619
1735
|
const hasContent = data.features.length > 0;
|
|
1620
|
-
return /* @__PURE__ */
|
|
1621
|
-
/* @__PURE__ */
|
|
1622
|
-
hasContent ? /* @__PURE__ */
|
|
1736
|
+
return /* @__PURE__ */ jsx37(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ jsxs25("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1737
|
+
/* @__PURE__ */ jsx37("header", { className: "es-report-header", children: /* @__PURE__ */ jsx37(ReportTitleBlock, { title }) }),
|
|
1738
|
+
hasContent ? /* @__PURE__ */ jsx37(ReportFeatureList, {}) : /* @__PURE__ */ jsx37(ReportEmpty, {})
|
|
1623
1739
|
] }) });
|
|
1624
1740
|
}
|
|
1625
1741
|
|