executable-stories-react 0.17.1 → 0.19.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.
@@ -239,11 +239,11 @@ function formatValue(value) {
239
239
  return String(value);
240
240
  }
241
241
  }
242
- function DocKv({ entry }) {
243
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
242
+ function DocKv({ entries }) {
243
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dl", { className: "my-2 grid grid-cols-[max-content_1fr] gap-x-3 gap-y-1 text-sm", children: entries.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "contents", children: [
244
244
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dt", { className: "font-semibold text-muted-foreground", children: entry.label }),
245
245
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dd", { className: "min-w-0 break-words font-mono text-foreground", children: formatValue(entry.value) })
246
- ] });
246
+ ] }, i)) });
247
247
  }
248
248
 
249
249
  // src/hooks/useRenderers.ts
@@ -330,7 +330,7 @@ function DocSection({ entry }) {
330
330
  if (renderers.section) {
331
331
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: renderers.section(entry) });
332
332
  }
333
- const html = safeMarkdownHtml(entry.markdown);
333
+ const html = safeMarkdownHtml(dedent(entry.markdown));
334
334
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("section", { className: "my-3 text-sm", "aria-label": entry.title, children: [
335
335
  entry.title ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h4", { className: "mb-1 font-semibold text-foreground", children: entry.title }) : null,
336
336
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
@@ -516,7 +516,7 @@ function DocEntry({ entry }) {
516
516
  case "tag":
517
517
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocTag, { entry });
518
518
  case "kv":
519
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocKv, { entry });
519
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocKv, { entries: [entry] });
520
520
  case "code":
521
521
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocCode, { entry });
522
522
  case "table":
@@ -544,7 +544,15 @@ function DocEntry({ entry }) {
544
544
  var import_jsx_runtime18 = require("react/jsx-runtime");
545
545
  function ReportDocEntries({ entries }) {
546
546
  if (entries.length === 0) return null;
547
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children: entries.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DocEntry, { entry }, i)) });
547
+ const groups = [];
548
+ for (const entry of entries) {
549
+ const last = groups[groups.length - 1];
550
+ if (entry.kind === "kv" && Array.isArray(last)) last.push(entry);
551
+ else groups.push(entry.kind === "kv" ? [entry] : entry);
552
+ }
553
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children: groups.map(
554
+ (g, i) => Array.isArray(g) ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DocKv, { entries: g }, i) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DocEntry, { entry: g }, i)
555
+ ) });
548
556
  }
549
557
 
550
558
  // src/components/ReportSteps.tsx
@@ -749,42 +757,76 @@ function StateCardView({ card }) {
749
757
 
750
758
  // src/components/ReportAttachments.tsx
751
759
  var import_jsx_runtime21 = require("react/jsx-runtime");
760
+ function attachmentText(att) {
761
+ if (att.contentEncoding !== "BASE64") return att.body;
762
+ try {
763
+ return new TextDecoder().decode(Uint8Array.from(atob(att.body), (c) => c.charCodeAt(0)));
764
+ } catch {
765
+ return void 0;
766
+ }
767
+ }
768
+ function preview(att) {
769
+ const type = att.mediaType.split(";")[0].trim().toLowerCase();
770
+ const text = attachmentText(att);
771
+ if (text === void 0) return null;
772
+ if (type === "text/plain") {
773
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "max-h-96 overflow-auto rounded-md border border-border bg-muted/40 p-3 text-xs whitespace-pre-wrap", children: text });
774
+ }
775
+ if (type === "text/markdown") {
776
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
777
+ "div",
778
+ {
779
+ className: "es-doc-prose prose prose-sm max-w-none rounded-md border border-border p-3",
780
+ dangerouslySetInnerHTML: { __html: safeMarkdownHtml(text) }
781
+ }
782
+ );
783
+ }
784
+ if (type === "text/html") {
785
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DocHtml, { entry: { kind: "html", content: text, title: att.name, phase: "runtime" } });
786
+ }
787
+ return null;
788
+ }
752
789
  function ReportAttachments({ attachments }) {
753
790
  if (attachments.length === 0) return null;
754
791
  return (
755
792
  // role="group" (not a labelled <section>) so multiple scenarios' attachment
756
793
  // blocks don't create duplicate "Attachments" region landmarks.
757
794
  /* @__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) => {
758
- const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
759
- const isImage = att.mediaType.startsWith("image/");
795
+ const dataUri = att.external ? void 0 : att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
796
+ const href = dataUri ?? (0, import_url.safeUrl)(att.body);
797
+ const imageSrc = dataUri ?? (0, import_url.safeImageUrl)(att.body);
798
+ const isImage = att.mediaType.startsWith("image/") && imageSrc !== void 0;
760
799
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
761
800
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
762
801
  "img",
763
802
  {
764
- src: dataUri,
803
+ src: imageSrc,
765
804
  alt: att.name,
766
805
  loading: "lazy",
767
806
  className: "max-w-full rounded-md border border-border"
768
807
  }
769
808
  ),
770
809
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
771
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
772
- "a",
773
- {
774
- href: dataUri,
775
- download: att.name,
776
- className: "text-xs text-link underline underline-offset-2",
777
- children: [
778
- att.name,
779
- " ",
780
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-muted-foreground", children: [
781
- "(",
782
- att.mediaType,
783
- ")"
784
- ] })
785
- ]
786
- }
787
- ) }, `${att.name}-${i}`);
810
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
811
+ att.external ? null : preview(att),
812
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
813
+ "a",
814
+ {
815
+ href,
816
+ download: att.name,
817
+ className: "text-xs text-link underline underline-offset-2",
818
+ children: [
819
+ att.name,
820
+ " ",
821
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-muted-foreground", children: [
822
+ "(",
823
+ att.mediaType,
824
+ ")"
825
+ ] })
826
+ ]
827
+ }
828
+ )
829
+ ] }) }, `${att.name}-${i}`);
788
830
  }) })
789
831
  );
790
832
  }
@@ -1439,10 +1481,17 @@ function ReportFeatureIntro({ feature }) {
1439
1481
  dangerouslySetInnerHTML: { __html: safeMarkdownHtml(dedent(feature.narrative)) }
1440
1482
  }
1441
1483
  ) : null,
1442
- hasGlossary ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dl", { className: "grid gap-1.5", "aria-label": "Glossary", children: feature.glossary.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-wrap gap-x-2 text-xs", children: [
1443
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dt", { className: "font-medium text-foreground", children: entry.term }),
1444
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dd", { className: "flex-1 text-muted-foreground", children: entry.definition })
1445
- ] }, entry.term)) }) : null
1484
+ hasGlossary ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1485
+ "dl",
1486
+ {
1487
+ className: "grid grid-cols-[max-content_1fr] gap-x-4 gap-y-1.5 text-xs",
1488
+ "aria-label": "Glossary",
1489
+ children: feature.glossary.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "contents", children: [
1490
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dt", { className: "font-medium text-foreground", children: entry.term }),
1491
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dd", { className: "text-muted-foreground", children: entry.definition })
1492
+ ] }, entry.term))
1493
+ }
1494
+ ) : null
1446
1495
  ] });
1447
1496
  }
1448
1497
  function featureKindLabel(kind) {
@@ -1458,7 +1507,6 @@ function ReportFeature({ feature }) {
1458
1507
  const titleId = `${feature.id}-title`;
1459
1508
  const bodyId = `${feature.id}-body`;
1460
1509
  const s = feature.summary;
1461
- const skipped = s.skipped + s.pending;
1462
1510
  const collapse = useCollapse();
1463
1511
  const collapsed = collapse?.isCollapsed(feature.id) ?? false;
1464
1512
  const kindLabel = featureKindLabel(feature.kind);
@@ -1498,7 +1546,12 @@ function ReportFeature({ feature }) {
1498
1546
  "p",
1499
1547
  {
1500
1548
  className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
1501
- "aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
1549
+ "aria-label": [
1550
+ `${s.passed} passed`,
1551
+ `${s.failed} failed`,
1552
+ s.skipped > 0 && `${s.skipped} skipped`,
1553
+ s.pending > 0 && `${s.pending} pending`
1554
+ ].filter(Boolean).join(", "),
1502
1555
  children: [
1503
1556
  /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { children: [
1504
1557
  s.passed,
@@ -1509,12 +1562,19 @@ function ReportFeature({ feature }) {
1509
1562
  s.failed,
1510
1563
  " failed"
1511
1564
  ] }),
1512
- skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
1565
+ s.skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
1513
1566
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1514
1567
  /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { children: [
1515
- skipped,
1568
+ s.skipped,
1516
1569
  " skipped"
1517
1570
  ] })
1571
+ ] }) : null,
1572
+ s.pending > 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
1573
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1574
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { children: [
1575
+ s.pending,
1576
+ " pending"
1577
+ ] })
1518
1578
  ] }) : null
1519
1579
  ]
1520
1580
  }