executable-stories-react 0.12.0 → 0.14.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.js CHANGED
@@ -345,7 +345,7 @@ function formatValue(value) {
345
345
  function DocKv({ entry }) {
346
346
  return /* @__PURE__ */ jsxs2("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
347
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) })
348
+ /* @__PURE__ */ jsx6("dd", { className: "min-w-0 break-words font-mono text-foreground", children: formatValue(entry.value) })
349
349
  ] });
350
350
  }
351
351
 
@@ -553,7 +553,7 @@ function DocHtml({ entry }) {
553
553
  loading: "lazy",
554
554
  title,
555
555
  className: "block w-full border-0",
556
- style: { height }
556
+ style: { height, colorScheme: "light", background: "#fff" }
557
557
  }
558
558
  )
559
559
  ] });
@@ -1306,57 +1306,68 @@ function ReportScenario({ scenario, hideTitle = false }) {
1306
1306
  className: "gap-0 py-0",
1307
1307
  children: [
1308
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: [
1311
- collapsible ? /* @__PURE__ */ jsx26(
1312
- "button",
1313
- {
1314
- type: "button",
1315
- onClick: () => collapse.toggle(scenario.id),
1316
- "aria-expanded": !collapsed,
1317
- "aria-controls": bodyId,
1318
- "aria-label": `Toggle ${scenario.title}`,
1319
- className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
1320
- children: /* @__PURE__ */ jsx26("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
1321
- }
1322
- ) : null,
1323
- /* @__PURE__ */ jsx26("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
1324
- /* @__PURE__ */ jsx26("span", { children: scenario.title })
1325
- ] }),
1326
- /* @__PURE__ */ jsxs18("div", { className: "flex shrink-0 items-center gap-2", children: [
1327
- /* @__PURE__ */ jsx26(ScenarioRunHistory, { scenarioId: scenario.id }),
1328
- /* @__PURE__ */ jsx26(ScenarioStaleness, { scenario }),
1329
- scenario.durationMs > 0 ? /* @__PURE__ */ jsx26("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration3(scenario.durationMs) }) : null,
1330
- meta.showPill ? /* @__PURE__ */ jsx26(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ jsx26("span", { className: "sr-only", children: `Status: ${label}` }),
1331
- actions ? /* @__PURE__ */ jsxs18(DropdownMenu, { children: [
1332
- /* @__PURE__ */ jsx26(
1333
- DropdownMenuTrigger,
1334
- {
1335
- "aria-label": `Actions for ${scenario.title}`,
1336
- className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
1337
- children: /* @__PURE__ */ jsx26(MoreHorizontalIcon, { "aria-hidden": true })
1338
- }
1339
- ),
1340
- /* @__PURE__ */ jsxs18(DropdownMenuContent, { align: "end", children: [
1341
- /* @__PURE__ */ jsxs18(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
1342
- /* @__PURE__ */ jsx26(LinkIcon, {}),
1343
- " Copy link"
1344
- ] }),
1345
- /* @__PURE__ */ jsxs18(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
1346
- /* @__PURE__ */ jsx26(FileTextIcon, {}),
1347
- " Copy as Markdown"
1348
- ] }),
1349
- /* @__PURE__ */ jsxs18(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
1350
- /* @__PURE__ */ jsx26(SparklesIcon, {}),
1351
- " Explain with AI"
1352
- ] })
1309
+ /* @__PURE__ */ jsxs18(
1310
+ "div",
1311
+ {
1312
+ className: cn(
1313
+ // Wraps rather than squeezing: on a phone the status/duration group
1314
+ // is ~160px, which leaves a title column a few characters wide.
1315
+ "flex flex-wrap items-start gap-x-4 gap-y-1",
1316
+ hideTitle ? "justify-end" : "justify-between"
1317
+ ),
1318
+ children: [
1319
+ hideTitle ? null : /* @__PURE__ */ jsxs18("h3", { id: titleId, className: "flex min-w-0 flex-1 basis-48 items-center gap-2 text-sm font-medium text-foreground", children: [
1320
+ collapsible ? /* @__PURE__ */ jsx26(
1321
+ "button",
1322
+ {
1323
+ type: "button",
1324
+ onClick: () => collapse.toggle(scenario.id),
1325
+ "aria-expanded": !collapsed,
1326
+ "aria-controls": bodyId,
1327
+ "aria-label": `Toggle ${scenario.title}`,
1328
+ className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
1329
+ children: /* @__PURE__ */ jsx26("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
1330
+ }
1331
+ ) : null,
1332
+ /* @__PURE__ */ jsx26("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
1333
+ /* @__PURE__ */ jsx26("span", { children: scenario.title })
1334
+ ] }),
1335
+ /* @__PURE__ */ jsxs18("div", { className: "flex shrink-0 items-center gap-2", children: [
1336
+ /* @__PURE__ */ jsx26(ScenarioRunHistory, { scenarioId: scenario.id }),
1337
+ /* @__PURE__ */ jsx26(ScenarioStaleness, { scenario }),
1338
+ scenario.durationMs > 0 ? /* @__PURE__ */ jsx26("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration3(scenario.durationMs) }) : null,
1339
+ meta.showPill ? /* @__PURE__ */ jsx26(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ jsx26("span", { className: "sr-only", children: `Status: ${label}` }),
1340
+ actions ? /* @__PURE__ */ jsxs18(DropdownMenu, { children: [
1341
+ /* @__PURE__ */ jsx26(
1342
+ DropdownMenuTrigger,
1343
+ {
1344
+ "aria-label": `Actions for ${scenario.title}`,
1345
+ className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
1346
+ children: /* @__PURE__ */ jsx26(MoreHorizontalIcon, { "aria-hidden": true })
1347
+ }
1348
+ ),
1349
+ /* @__PURE__ */ jsxs18(DropdownMenuContent, { align: "end", children: [
1350
+ /* @__PURE__ */ jsxs18(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
1351
+ /* @__PURE__ */ jsx26(LinkIcon, {}),
1352
+ " Copy link"
1353
+ ] }),
1354
+ /* @__PURE__ */ jsxs18(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
1355
+ /* @__PURE__ */ jsx26(FileTextIcon, {}),
1356
+ " Copy as Markdown"
1357
+ ] }),
1358
+ /* @__PURE__ */ jsxs18(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
1359
+ /* @__PURE__ */ jsx26(SparklesIcon, {}),
1360
+ " Explain with AI"
1361
+ ] })
1362
+ ] })
1363
+ ] }) : null
1353
1364
  ] })
1354
- ] }) : null
1355
- ] })
1356
- ] }),
1365
+ ]
1366
+ }
1367
+ ),
1357
1368
  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: [
1358
1369
  scenario.tags.map((t) => /* @__PURE__ */ jsx26("li", { children: /* @__PURE__ */ jsx26(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
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}`))
1370
+ (scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ jsx26("li", { children: ticket.url ? /* @__PURE__ */ jsx26("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", className: "inline-flex min-h-6 items-center", children: /* @__PURE__ */ jsx26(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ jsx26(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
1360
1371
  ] }) : null
1361
1372
  ] }),
1362
1373
  /* @__PURE__ */ jsxs18(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
@@ -1622,6 +1633,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1622
1633
 
1623
1634
  // src/components/ReportMeta.tsx
1624
1635
  import { formatDuration as formatDuration4 } from "executable-stories-core/utils/duration";
1636
+ import { slowestScenarios } from "executable-stories-core/report-queries";
1625
1637
  import { jsx as jsx34, jsxs as jsxs22 } from "react/jsx-runtime";
1626
1638
  function ReportMeta() {
1627
1639
  const report = useReport();
@@ -1665,7 +1677,9 @@ function ReportMeta() {
1665
1677
  value: url ? /* @__PURE__ */ jsx34("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1666
1678
  });
1667
1679
  }
1668
- if (items.length === 0) return null;
1680
+ const slowest = slowestScenarios(report, 5);
1681
+ const showSlowest = slowest.length >= 3;
1682
+ if (items.length === 0 && !showSlowest) return null;
1669
1683
  return (
1670
1684
  // Run metadata is useful but secondary to "what failed" — tuck it into a
1671
1685
  // collapsed disclosure so it doesn't push the result down. Native <details>
@@ -1678,7 +1692,14 @@ function ReportMeta() {
1678
1692
  /* @__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
1693
  /* @__PURE__ */ jsx34("dt", { className: "font-medium", children: item.label }),
1680
1694
  /* @__PURE__ */ jsx34("dd", { className: "font-mono text-foreground", children: item.value })
1681
- ] }, item.label)) })
1695
+ ] }, item.label)) }),
1696
+ showSlowest ? /* @__PURE__ */ jsxs22("div", { className: "border-t border-border px-4 py-3", children: [
1697
+ /* @__PURE__ */ jsx34("div", { className: "mb-1.5 font-medium text-muted-foreground", children: "Slowest scenarios" }),
1698
+ /* @__PURE__ */ jsx34("ol", { className: "flex flex-col gap-1", "aria-label": "Slowest scenarios", children: slowest.map((s) => /* @__PURE__ */ jsxs22("li", { className: "flex items-baseline justify-between gap-4", children: [
1699
+ /* @__PURE__ */ jsx34("a", { href: `#${s.id}`, className: "min-w-0 text-primary underline underline-offset-2", children: s.title }),
1700
+ /* @__PURE__ */ jsx34("span", { className: "shrink-0 font-mono tabular-nums text-muted-foreground", children: formatDuration4(s.durationMs) })
1701
+ ] }, s.id)) })
1702
+ ] }) : null
1682
1703
  ] })
1683
1704
  );
1684
1705
  }
@@ -1802,7 +1823,7 @@ function renderReportToHtml(report, options = {}) {
1802
1823
  const parsed = unwrapReport(report);
1803
1824
  const rawReport = parsed.ok ? parsed.data : void 0;
1804
1825
  const interactive = islandScript.length > 0 && rawReport !== void 0;
1805
- const dataScript = interactive ? `<script type="application/json" id="${DATA_ID}">${escapeJsonForScript(JSON.stringify(rawReport))}</script>` : "";
1826
+ const dataScript = rawReport !== void 0 ? `<script type="application/json" id="${DATA_ID}">${escapeJsonForScript(JSON.stringify(rawReport))}</script>` : "";
1806
1827
  const historyScript = interactive && scenarioHistory && Object.keys(scenarioHistory).length > 0 ? `<script type="application/json" id="${HISTORY_ID}">${escapeJsonForScript(JSON.stringify(scenarioHistory))}</script>` : "";
1807
1828
  const islandTag = interactive ? `<script>${islandScript}</script>` : "";
1808
1829
  const cdnBody = interactive ? "" : cdn.body;