executable-stories-react 0.10.1 → 0.11.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/ssr.cjs CHANGED
@@ -404,21 +404,29 @@ function DocLink({ entry }) {
404
404
  );
405
405
  }
406
406
 
407
- // src/components/doc/DocSection.tsx
407
+ // src/lib/markdown.ts
408
408
  var import_marked = require("marked");
409
409
 
410
410
  // src/lib/url.ts
411
411
  var import_url = require("executable-stories-core/utils/url");
412
412
 
413
- // src/components/doc/DocSection.tsx
414
- var import_jsx_runtime9 = require("react/jsx-runtime");
415
- function neutralizeUrl(value) {
416
- return (0, import_url.safeUrl)(value) ?? "#";
417
- }
413
+ // src/lib/markdown.ts
418
414
  function safeMarkdownHtml(markdown) {
419
415
  const raw = import_marked.marked.parse(markdown, { async: false });
420
416
  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)}'`);
421
417
  }
418
+ function dedent(text) {
419
+ const lines = text.replace(/\t/g, " ").split("\n");
420
+ const indents = lines.filter((line) => line.trim().length > 0).map((line) => line.length - line.trimStart().length);
421
+ const shortest = indents.length > 0 ? Math.min(...indents) : 0;
422
+ return lines.map((line) => line.slice(shortest)).join("\n").trim();
423
+ }
424
+ function neutralizeUrl(value) {
425
+ return (0, import_url.safeUrl)(value) ?? "#";
426
+ }
427
+
428
+ // src/components/doc/DocSection.tsx
429
+ var import_jsx_runtime9 = require("react/jsx-runtime");
422
430
  function DocSection({ entry }) {
423
431
  const renderers = useBuiltinRenderers();
424
432
  if (renderers.section) {
@@ -1295,8 +1303,35 @@ function ReportScenarioList({ feature }) {
1295
1303
  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)) });
1296
1304
  }
1297
1305
 
1298
- // src/components/ReportFeature.tsx
1306
+ // src/components/ReportFeatureIntro.tsx
1299
1307
  var import_jsx_runtime28 = require("react/jsx-runtime");
1308
+ function ReportFeatureIntro({ feature }) {
1309
+ const hasNarrative = Boolean(feature.narrative?.trim());
1310
+ const hasGlossary = Boolean(feature.glossary?.length);
1311
+ if (!hasNarrative && !hasGlossary) return null;
1312
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col gap-3 border-l-2 border-border pl-4 text-sm", children: [
1313
+ hasNarrative ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1314
+ "div",
1315
+ {
1316
+ className: "es-doc-prose prose prose-sm max-w-none text-muted-foreground",
1317
+ dangerouslySetInnerHTML: { __html: safeMarkdownHtml(dedent(feature.narrative)) }
1318
+ }
1319
+ ) : null,
1320
+ hasGlossary ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("dl", { className: "grid gap-1.5", "aria-label": "Glossary", children: feature.glossary.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-wrap gap-x-2 text-xs", children: [
1321
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("dt", { className: "font-medium text-foreground", children: entry.term }),
1322
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("dd", { className: "flex-1 text-muted-foreground", children: entry.definition })
1323
+ ] }, entry.term)) }) : null
1324
+ ] });
1325
+ }
1326
+ function featureKindLabel(kind) {
1327
+ if (kind === "ability") return "Ability";
1328
+ if (kind === "business-need") return "Business need";
1329
+ if (kind === "feature") return "Feature";
1330
+ return null;
1331
+ }
1332
+
1333
+ // src/components/ReportFeature.tsx
1334
+ var import_jsx_runtime29 = require("react/jsx-runtime");
1300
1335
  function ReportFeature({ feature }) {
1301
1336
  const titleId = `${feature.id}-title`;
1302
1337
  const bodyId = `${feature.id}-body`;
@@ -1304,10 +1339,11 @@ function ReportFeature({ feature }) {
1304
1339
  const skipped = s.skipped + s.pending;
1305
1340
  const collapse = useCollapse();
1306
1341
  const collapsed = collapse?.isCollapsed(feature.id) ?? false;
1342
+ const kindLabel = featureKindLabel(feature.kind);
1307
1343
  return (
1308
1344
  // Suite = a section heading + a divider, NOT another bordered card. Drops a
1309
1345
  // layer of nesting so the scenario cards below read as the primary unit.
1310
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
1346
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
1311
1347
  "section",
1312
1348
  {
1313
1349
  id: feature.id,
@@ -1315,9 +1351,9 @@ function ReportFeature({ feature }) {
1315
1351
  "aria-labelledby": titleId,
1316
1352
  className: "flex flex-col gap-3",
1317
1353
  children: [
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)(
1354
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
1355
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "min-w-0", children: [
1356
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
1321
1357
  "button",
1322
1358
  {
1323
1359
  type: "button",
@@ -1326,31 +1362,34 @@ function ReportFeature({ feature }) {
1326
1362
  "aria-controls": bodyId,
1327
1363
  className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
1328
1364
  children: [
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 })
1365
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
1366
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "truncate", children: feature.title })
1331
1367
  ]
1332
1368
  }
1333
1369
  ) : feature.title }),
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 })
1370
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("p", { className: cn("mt-0.5 flex items-center gap-2 text-xs text-muted-foreground", collapse && "pl-5"), children: [
1371
+ kindLabel ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "shrink-0 rounded-sm bg-muted px-1.5 py-0.5 font-medium text-foreground", children: kindLabel }) : null,
1372
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "truncate font-mono", children: feature.sourceFile })
1373
+ ] })
1335
1374
  ] }),
1336
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
1375
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
1337
1376
  "p",
1338
1377
  {
1339
1378
  className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
1340
1379
  "aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
1341
1380
  children: [
1342
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { children: [
1381
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { children: [
1343
1382
  s.passed,
1344
1383
  " passed"
1345
1384
  ] }),
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: [
1385
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1386
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
1348
1387
  s.failed,
1349
1388
  " failed"
1350
1389
  ] }),
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: [
1390
+ skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
1391
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1392
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { children: [
1354
1393
  skipped,
1355
1394
  " skipped"
1356
1395
  ] })
@@ -1359,7 +1398,10 @@ function ReportFeature({ feature }) {
1359
1398
  }
1360
1399
  )
1361
1400
  ] }),
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 }) })
1401
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: [
1402
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ReportFeatureIntro, { feature }),
1403
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ReportScenarioList, { feature })
1404
+ ] })
1363
1405
  ]
1364
1406
  }
1365
1407
  )
@@ -1367,17 +1409,17 @@ function ReportFeature({ feature }) {
1367
1409
  }
1368
1410
 
1369
1411
  // src/components/ReportFeatureList.tsx
1370
- var import_jsx_runtime29 = require("react/jsx-runtime");
1412
+ var import_jsx_runtime30 = require("react/jsx-runtime");
1371
1413
  function ReportFeatureList() {
1372
1414
  const report = useReport();
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)) });
1415
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ReportFeature, { feature }, feature.id)) });
1374
1416
  }
1375
1417
 
1376
1418
  // src/components/ui/empty.tsx
1377
1419
  var import_class_variance_authority2 = require("class-variance-authority");
1378
- var import_jsx_runtime30 = require("react/jsx-runtime");
1420
+ var import_jsx_runtime31 = require("react/jsx-runtime");
1379
1421
  function Empty({ className, ...props }) {
1380
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1422
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
1381
1423
  "div",
1382
1424
  {
1383
1425
  "data-slot": "empty",
@@ -1390,7 +1432,7 @@ function Empty({ className, ...props }) {
1390
1432
  );
1391
1433
  }
1392
1434
  function EmptyHeader({ className, ...props }) {
1393
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1435
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
1394
1436
  "div",
1395
1437
  {
1396
1438
  "data-slot": "empty-header",
@@ -1417,7 +1459,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
1417
1459
  }
1418
1460
  );
1419
1461
  function EmptyTitle({ className, ...props }) {
1420
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1462
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
1421
1463
  "div",
1422
1464
  {
1423
1465
  "data-slot": "empty-title",
@@ -1428,16 +1470,16 @@ function EmptyTitle({ className, ...props }) {
1428
1470
  }
1429
1471
 
1430
1472
  // src/components/ReportEmpty.tsx
1431
- var import_jsx_runtime31 = require("react/jsx-runtime");
1473
+ var import_jsx_runtime32 = require("react/jsx-runtime");
1432
1474
  function ReportEmpty({ message }) {
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." }) }) });
1475
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(EmptyHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
1434
1476
  }
1435
1477
 
1436
1478
  // src/components/ReportSummary.tsx
1437
- var import_jsx_runtime32 = require("react/jsx-runtime");
1479
+ var import_jsx_runtime33 = require("react/jsx-runtime");
1438
1480
  function ReportSummary({ className }) {
1439
1481
  const report = useReport();
1440
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1482
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
1441
1483
  ReportSummaryView,
1442
1484
  {
1443
1485
  summary: report.summary,
@@ -1463,7 +1505,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1463
1505
  if (summary.pending > 0) {
1464
1506
  cards.push({ status: "pending", label: "Pending", value: summary.pending });
1465
1507
  }
1466
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1508
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
1467
1509
  "dl",
1468
1510
  {
1469
1511
  className: cn(
@@ -1476,17 +1518,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1476
1518
  "aria-label": ariaLabel,
1477
1519
  children: cards.map((c) => {
1478
1520
  const tone = TONE[c.status];
1479
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
1521
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
1480
1522
  "div",
1481
1523
  {
1482
1524
  "data-status": c.status,
1483
1525
  className: "rounded-lg border bg-card px-4 py-3",
1484
1526
  children: [
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" }),
1527
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
1528
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
1487
1529
  c.label
1488
1530
  ] }),
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 })
1531
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
1490
1532
  ]
1491
1533
  },
1492
1534
  c.status
@@ -1530,7 +1572,7 @@ function prUrl(ci) {
1530
1572
  }
1531
1573
 
1532
1574
  // src/components/ReportMeta.tsx
1533
- var import_jsx_runtime33 = require("react/jsx-runtime");
1575
+ var import_jsx_runtime34 = require("react/jsx-runtime");
1534
1576
  function ReportMeta() {
1535
1577
  const report = useReport();
1536
1578
  const items = [];
@@ -1553,13 +1595,13 @@ function ReportMeta() {
1553
1595
  const short = sha.slice(0, 8);
1554
1596
  items.push({
1555
1597
  label: "Commit",
1556
- value: url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
1598
+ value: url ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
1557
1599
  });
1558
1600
  }
1559
1601
  if (report.ci) {
1560
1602
  items.push({
1561
1603
  label: "CI",
1562
- value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
1604
+ value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
1563
1605
  ciDisplayName(report.ci.name),
1564
1606
  report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
1565
1607
  ] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
@@ -1570,7 +1612,7 @@ function ReportMeta() {
1570
1612
  const label = `#${report.ci.prNumber}`;
1571
1613
  items.push({
1572
1614
  label: "PR",
1573
- value: url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1615
+ value: url ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1574
1616
  });
1575
1617
  }
1576
1618
  if (items.length === 0) return null;
@@ -1578,48 +1620,48 @@ function ReportMeta() {
1578
1620
  // Run metadata is useful but secondary to "what failed" — tuck it into a
1579
1621
  // collapsed disclosure so it doesn't push the result down. Native <details>
1580
1622
  // so it works with no JS (the SSR/no-hydration report still toggles).
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" }),
1623
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
1624
+ /* @__PURE__ */ (0, import_jsx_runtime34.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: [
1625
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
1584
1626
  "Run details"
1585
1627
  ] }),
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 })
1628
+ /* @__PURE__ */ (0, import_jsx_runtime34.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_runtime34.jsxs)("div", { className: "flex items-baseline gap-1.5", children: [
1629
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("dt", { className: "font-medium", children: item.label }),
1630
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
1589
1631
  ] }, item.label)) })
1590
1632
  ] })
1591
1633
  );
1592
1634
  }
1593
1635
 
1594
1636
  // src/components/ReportSchemaError.tsx
1595
- var import_jsx_runtime34 = require("react/jsx-runtime");
1637
+ var import_jsx_runtime35 = require("react/jsx-runtime");
1596
1638
  function ReportSchemaError({ error }) {
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: [
1639
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
1640
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("strong", { children: "Report could not be displayed." }) }),
1641
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { children: error.message }),
1642
+ error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("p", { children: [
1601
1643
  "The report bundle is newer than this version of ",
1602
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("code", { children: "executable-stories-react" }),
1644
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("code", { children: "executable-stories-react" }),
1603
1645
  ". Upgrade the package, or regenerate the report with an older formatters CLI."
1604
1646
  ] }) : null,
1605
- error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("details", { children: [
1606
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("summary", { children: [
1647
+ error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("details", { children: [
1648
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("summary", { children: [
1607
1649
  error.issues.length,
1608
1650
  " validation issue",
1609
1651
  error.issues.length === 1 ? "" : "s"
1610
1652
  ] }),
1611
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
1653
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
1612
1654
  ] }) : null
1613
1655
  ] });
1614
1656
  }
1615
1657
 
1616
1658
  // src/components/ReportShell.tsx
1617
- var import_jsx_runtime35 = require("react/jsx-runtime");
1659
+ var import_jsx_runtime36 = require("react/jsx-runtime");
1618
1660
  function ReportTitleBlock({ title }) {
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, {})
1661
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
1662
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h1", { children: title ?? "Story Report" }),
1663
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportSummary, {}),
1664
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportMeta, {})
1623
1665
  ] });
1624
1666
  }
1625
1667
  function ReportErrorShell({
@@ -1628,22 +1670,22 @@ function ReportErrorShell({
1628
1670
  title,
1629
1671
  dataTheme
1630
1672
  }) {
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 }) });
1673
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportSchemaError, { error }) });
1632
1674
  }
1633
1675
 
1634
1676
  // src/components/Report.tsx
1635
- var import_jsx_runtime36 = require("react/jsx-runtime");
1677
+ var import_jsx_runtime37 = require("react/jsx-runtime");
1636
1678
  function Report(props) {
1637
1679
  const { report, customRenderers, renderers, className, title, dataTheme } = props;
1638
1680
  const result = unwrapReport(report);
1639
1681
  if (!result.ok) {
1640
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
1682
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
1641
1683
  }
1642
1684
  const data = result.data;
1643
1685
  const hasContent = data.features.length > 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, {})
1686
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
1687
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportTitleBlock, { title }) }),
1688
+ hasContent ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportEmpty, {})
1647
1689
  ] }) });
1648
1690
  }
1649
1691