@the-portland-company/shell 0.62.1 → 0.64.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.
@@ -1435,6 +1435,24 @@ async function captureMyView(status, orgId, orgName) {
1435
1435
  });
1436
1436
  if (!res.ok) throw new Error(`capture ${res.status}: ${(await res.text()).slice(0, 160)}`);
1437
1437
  }
1438
+ function SpecCaptureLoading() {
1439
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-spec-capture-loading": "", role: "status", "aria-live": "polite", className: "flex-1 overflow-hidden px-4 py-4", children: [
1440
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 flex items-center gap-3 text-sm text-[color:var(--foreground)]", children: [
1441
+ /* @__PURE__ */ jsxRuntime.jsx(
1442
+ "span",
1443
+ {
1444
+ "aria-hidden": "true",
1445
+ className: "inline-block h-5 w-5 animate-spin rounded-full border-2 border-[color:var(--line)] border-t-[color:var(--color-accent)] motion-reduce:animate-none"
1446
+ }
1447
+ ),
1448
+ "Capturing your view and comparing\u2026"
1449
+ ] }),
1450
+ ["Live \u2014 your view", "Diff"].map((label) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4", children: [
1451
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-[color:var(--muted)]", children: label }),
1452
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", className: "h-40 w-full animate-pulse rounded border border-[color:var(--line)] bg-[color:var(--panel)] motion-reduce:animate-none" })
1453
+ ] }, label))
1454
+ ] });
1455
+ }
1438
1456
  function specOverlayStatusPath() {
1439
1457
  return `/api/overlay/status?url=${encodeURIComponent(window.location.href)}&theme=${currentChromeTheme()}`;
1440
1458
  }
@@ -1444,6 +1462,7 @@ function SpecOverlayAction({ orgId, orgName } = {}) {
1444
1462
  const [open, setOpen] = react.useState(false);
1445
1463
  const [capture, setCapture] = react.useState({ state: "idle" });
1446
1464
  const [frameKey, setFrameKey] = react.useState(0);
1465
+ const [copied, setCopied] = react.useState("idle");
1447
1466
  const href = useLocationHref();
1448
1467
  react.useEffect(() => {
1449
1468
  if (access) return;
@@ -1597,16 +1616,49 @@ function SpecOverlayAction({ orgId, orgName } = {}) {
1597
1616
  onClick: () => void runCapture(status),
1598
1617
  className: "ml-auto rounded-md border border-[color:var(--line)] px-2 py-1 text-[color:var(--foreground)] hover:bg-[color:var(--panel)] disabled:opacity-60",
1599
1618
  title: "Your view is captured when the drawer opens. Recapture after changing the page.",
1600
- children: capture.state === "busy" ? "Capturing your view\u2026" : "Recapture"
1619
+ children: capture.state === "busy" ? "Capturing\u2026" : "Recapture"
1620
+ }
1621
+ ),
1622
+ /* @__PURE__ */ jsxRuntime.jsx(
1623
+ "button",
1624
+ {
1625
+ type: "button",
1626
+ "data-spec-copy-prompt": "",
1627
+ disabled: capture.state === "busy" || !status.prompt,
1628
+ onClick: () => {
1629
+ const text = status.prompt;
1630
+ if (!text) return;
1631
+ navigator.clipboard.writeText(text).then(() => setCopied("copied")).catch(() => setCopied("failed")).finally(() => window.setTimeout(() => setCopied("idle"), 2e3));
1632
+ },
1633
+ className: "rounded-md border border-[color:var(--line)] px-2 py-1 text-[color:var(--foreground)] hover:bg-[color:var(--panel)] disabled:opacity-60",
1634
+ title: "Copy a repair prompt for an AI agent: spec, score, image links, top mismatched regions and instructions.",
1635
+ children: copied === "copied" ? "Copied \u2713" : copied === "failed" ? "Copy failed" : "Copy prompt"
1601
1636
  }
1602
1637
  )
1603
1638
  ] }),
1604
- capture.state === "busy" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 border-b border-[color:var(--line)] px-4 py-2 text-xs text-[color:var(--muted)]", children: [
1605
- /* @__PURE__ */ jsxRuntime.jsx(ValueSkeleton, { className: "h-3 w-3 rounded-full" }),
1606
- "Capturing your view and comparing\u2026"
1607
- ] }) : null,
1639
+ status.live_size && status.design_size && capture.state !== "busy" ? /* @__PURE__ */ jsxRuntime.jsxs(
1640
+ "p",
1641
+ {
1642
+ "data-spec-sizes": "",
1643
+ className: [
1644
+ "border-b border-[color:var(--line)] px-4 py-1.5 text-xs",
1645
+ status.live_size.width === status.design_size.width && status.live_size.height === status.design_size.height ? "text-[color:var(--muted)]" : "font-semibold text-[color:var(--chrome-danger)]"
1646
+ ].join(" "),
1647
+ children: [
1648
+ "Live ",
1649
+ status.live_size.width,
1650
+ "\xD7",
1651
+ status.live_size.height,
1652
+ " \xB7 Design ",
1653
+ status.design_size.width,
1654
+ "\xD7",
1655
+ status.design_size.height,
1656
+ status.live_size.width === status.design_size.width && status.live_size.height === status.design_size.height ? " \xB7 sizes match" : " \xB7 SIZE MISMATCH"
1657
+ ]
1658
+ }
1659
+ ) : null,
1608
1660
  capture.state === "error" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "border-b border-[color:var(--line)] px-4 py-2 text-xs text-[color:var(--chrome-danger)]", children: capture.message }) : null,
1609
- /* @__PURE__ */ jsxRuntime.jsx(
1661
+ capture.state === "busy" ? /* @__PURE__ */ jsxRuntime.jsx(SpecCaptureLoading, {}) : /* @__PURE__ */ jsxRuntime.jsx(
1610
1662
  "iframe",
1611
1663
  {
1612
1664
  src: status.overlay_url,
@@ -2243,10 +2295,7 @@ function NavSidebar({
2243
2295
  ),
2244
2296
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col overflow-y-auto px-4 pb-2", children: [
2245
2297
  org ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-3", children: [
2246
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex items-center justify-between px-1", children: [
2247
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--sidebar-text-muted,var(--muted))]", children: "Organization" }),
2248
- org.id && !org.loading ? /* @__PURE__ */ jsxRuntime.jsx(OrgIdCopyButton, { id: org.id }) : null
2249
- ] }),
2298
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 flex items-center justify-between px-1", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--sidebar-text-muted,var(--muted))]", children: "Organization" }) }),
2250
2299
  org.loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2.5 rounded-md border border-[color:var(--line)] bg-[color:var(--panel-elevated)] px-2.5 py-2 shadow-sm", children: [
2251
2300
  /* @__PURE__ */ jsxRuntime.jsx(
2252
2301
  "span",
@@ -2274,14 +2323,17 @@ function NavSidebar({
2274
2323
  children: orgLogoSrc ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: orgLogoSrc, alt: "", className: "h-full w-full object-cover" }) : (org.name ?? "Org").slice(0, 2).toUpperCase()
2275
2324
  }
2276
2325
  ),
2277
- /* @__PURE__ */ jsxRuntime.jsx(
2278
- "span",
2279
- {
2280
- title: org.name ?? void 0,
2281
- className: "truncate text-sm font-semibold",
2282
- children: org.name ?? "No organizations"
2283
- }
2284
- )
2326
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
2327
+ /* @__PURE__ */ jsxRuntime.jsx(
2328
+ "span",
2329
+ {
2330
+ title: org.name ?? void 0,
2331
+ className: "truncate text-sm font-semibold",
2332
+ children: org.name ?? "No organizations"
2333
+ }
2334
+ ),
2335
+ org.id && !org.loading ? /* @__PURE__ */ jsxRuntime.jsx(OrgIdCopyButton, { id: org.id }) : null
2336
+ ] })
2285
2337
  ] }),
2286
2338
  /* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {})
2287
2339
  ] }),
@@ -2364,7 +2416,17 @@ function NavSidebar({
2364
2416
  children: orgLogoSrc ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: orgLogoSrc, alt: "", className: "h-full w-full object-cover" }) : (org.name ?? "Org").slice(0, 2).toUpperCase()
2365
2417
  }
2366
2418
  ),
2367
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-semibold", children: org.name ?? "No organizations" })
2419
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
2420
+ /* @__PURE__ */ jsxRuntime.jsx(
2421
+ "span",
2422
+ {
2423
+ title: org.name ?? void 0,
2424
+ className: "truncate text-sm font-semibold",
2425
+ children: org.name ?? "No organizations"
2426
+ }
2427
+ ),
2428
+ org.id && !org.loading ? /* @__PURE__ */ jsxRuntime.jsx(OrgIdCopyButton, { id: org.id }) : null
2429
+ ] })
2368
2430
  ] }),
2369
2431
  /* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {})
2370
2432
  ]
@@ -2497,7 +2559,7 @@ function NavSidebar({
2497
2559
  }
2498
2560
  )
2499
2561
  ] }, l.label)) }) : null,
2500
- footer.envLabel ? /* @__PURE__ */ jsxRuntime.jsxs(
2562
+ footer.envLabel && footer.envLabel.trim().toLowerCase() !== "production" ? /* @__PURE__ */ jsxRuntime.jsxs(
2501
2563
  "div",
2502
2564
  {
2503
2565
  "data-shell-meta": true,