@the-portland-company/shell 0.61.1 → 0.63.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/app-chrome.cjs +76 -16
- package/dist/app-chrome.cjs.map +1 -1
- package/dist/app-chrome.js +1 -1
- package/dist/{chunk-G5DXKB3R.js → chunk-2SF25TVU.js} +78 -18
- package/dist/chunk-2SF25TVU.js.map +1 -0
- package/dist/native.cjs +76 -16
- package/dist/native.cjs.map +1 -1
- package/dist/native.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-G5DXKB3R.js.map +0 -1
package/dist/app-chrome.cjs
CHANGED
|
@@ -1388,36 +1388,44 @@ function currentChromeTheme() {
|
|
|
1388
1388
|
}
|
|
1389
1389
|
var SPEC_OVERLAY_ROOT_ATTR = "data-spec-overlay-root";
|
|
1390
1390
|
async function captureMyView(status, orgId, orgName) {
|
|
1391
|
-
const {
|
|
1391
|
+
const { domToCanvas } = await import('modern-screenshot');
|
|
1392
1392
|
const w = window.innerWidth;
|
|
1393
1393
|
const h = window.innerHeight;
|
|
1394
1394
|
const theme = currentChromeTheme();
|
|
1395
1395
|
const bg = getComputedStyle(document.body).backgroundColor || (theme === "dark" ? "#0b0b0c" : "#ffffff");
|
|
1396
|
-
const
|
|
1396
|
+
const full = await domToCanvas(document.body, {
|
|
1397
1397
|
width: w,
|
|
1398
1398
|
height: h,
|
|
1399
1399
|
scale: 1,
|
|
1400
1400
|
backgroundColor: bg,
|
|
1401
|
-
type: "image/png",
|
|
1402
1401
|
// Cross-origin images that refuse CORS render blank instead of failing.
|
|
1403
1402
|
fetch: { requestInit: { mode: "cors", credentials: "omit" }, placeholderImage: "" },
|
|
1404
|
-
|
|
1403
|
+
// Drop the Spec drawer and everything fixed (sidebar, toasts, popovers):
|
|
1404
|
+
// the design is the page body only, so chrome would only add noise.
|
|
1405
|
+
filter: (node) => !(node instanceof Element) || !node.hasAttribute(SPEC_OVERLAY_ROOT_ATTR) && getComputedStyle(node).position !== "fixed",
|
|
1405
1406
|
style: { transform: `translate(${-window.scrollX}px, ${-window.scrollY}px)` }
|
|
1406
1407
|
});
|
|
1407
|
-
|
|
1408
|
-
let
|
|
1409
|
-
const el = status.live_selector ? document.querySelector(status.live_selector) : null;
|
|
1408
|
+
const el = (status.live_selector ? document.querySelector(status.live_selector) : null) ?? document.querySelector("[data-shell-content]");
|
|
1409
|
+
let region = { x: 0, y: 0, width: w, height: h };
|
|
1410
1410
|
if (el) {
|
|
1411
1411
|
const r = el.getBoundingClientRect();
|
|
1412
1412
|
const x = Math.max(0, Math.round(r.left));
|
|
1413
1413
|
const y = Math.max(0, Math.round(r.top));
|
|
1414
|
-
|
|
1414
|
+
region = { x, y, width: Math.min(w - x, Math.round(r.width)), height: Math.min(h - y, Math.round(r.height)) };
|
|
1415
1415
|
}
|
|
1416
|
+
const out = document.createElement("canvas");
|
|
1417
|
+
out.width = region.width;
|
|
1418
|
+
out.height = region.height;
|
|
1419
|
+
const ctx = out.getContext("2d");
|
|
1420
|
+
if (!ctx) throw new Error("page raster failed");
|
|
1421
|
+
ctx.drawImage(full, region.x, region.y, region.width, region.height, 0, 0, region.width, region.height);
|
|
1422
|
+
const blob = await new Promise((resolve) => out.toBlob(resolve, "image/png"));
|
|
1423
|
+
if (!blob) throw new Error("page raster failed");
|
|
1416
1424
|
const form = new FormData();
|
|
1417
1425
|
form.append("image", blob, "live.png");
|
|
1418
1426
|
form.append(
|
|
1419
1427
|
"meta",
|
|
1420
|
-
JSON.stringify({ url: window.location.href, theme, org_id: orgId ?? null, org_name: orgName ?? null, crop })
|
|
1428
|
+
JSON.stringify({ url: window.location.href, theme, org_id: orgId ?? null, org_name: orgName ?? null, crop: null })
|
|
1421
1429
|
);
|
|
1422
1430
|
const res = await fetch(status.capture_url ?? `${SPECS_ORIGIN}/api/overlay/capture`, {
|
|
1423
1431
|
method: "POST",
|
|
@@ -1427,6 +1435,24 @@ async function captureMyView(status, orgId, orgName) {
|
|
|
1427
1435
|
});
|
|
1428
1436
|
if (!res.ok) throw new Error(`capture ${res.status}: ${(await res.text()).slice(0, 160)}`);
|
|
1429
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
|
+
}
|
|
1430
1456
|
function specOverlayStatusPath() {
|
|
1431
1457
|
return `/api/overlay/status?url=${encodeURIComponent(window.location.href)}&theme=${currentChromeTheme()}`;
|
|
1432
1458
|
}
|
|
@@ -1436,6 +1462,7 @@ function SpecOverlayAction({ orgId, orgName } = {}) {
|
|
|
1436
1462
|
const [open, setOpen] = react.useState(false);
|
|
1437
1463
|
const [capture, setCapture] = react.useState({ state: "idle" });
|
|
1438
1464
|
const [frameKey, setFrameKey] = react.useState(0);
|
|
1465
|
+
const [copied, setCopied] = react.useState("idle");
|
|
1439
1466
|
const href = useLocationHref();
|
|
1440
1467
|
react.useEffect(() => {
|
|
1441
1468
|
if (access) return;
|
|
@@ -1589,16 +1616,49 @@ function SpecOverlayAction({ orgId, orgName } = {}) {
|
|
|
1589
1616
|
onClick: () => void runCapture(status),
|
|
1590
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",
|
|
1591
1618
|
title: "Your view is captured when the drawer opens. Recapture after changing the page.",
|
|
1592
|
-
children: capture.state === "busy" ? "Capturing
|
|
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"
|
|
1593
1636
|
}
|
|
1594
1637
|
)
|
|
1595
1638
|
] }),
|
|
1596
|
-
capture.state
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
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,
|
|
1600
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,
|
|
1601
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1661
|
+
capture.state === "busy" ? /* @__PURE__ */ jsxRuntime.jsx(SpecCaptureLoading, {}) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1602
1662
|
"iframe",
|
|
1603
1663
|
{
|
|
1604
1664
|
src: status.overlay_url,
|
|
@@ -3321,7 +3381,7 @@ function NavAppShell({
|
|
|
3321
3381
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lg:pl-[240px]", children: [
|
|
3322
3382
|
/* @__PURE__ */ jsxRuntime.jsx(NavTopBar, { ...topBar, onOpenNav: () => setNavOpen(true), navOpen }),
|
|
3323
3383
|
betaBanner ? /* @__PURE__ */ jsxRuntime.jsx(NavBetaBanner, { ...betaBanner }) : null,
|
|
3324
|
-
contentWrapper === "bare" ? children : /* @__PURE__ */ jsxRuntime.jsx("main", { className: "px-6 py-7", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto max-w-7xl", children }) })
|
|
3384
|
+
contentWrapper === "bare" ? /* @__PURE__ */ jsxRuntime.jsx("div", { "data-shell-content": "", children }) : /* @__PURE__ */ jsxRuntime.jsx("main", { "data-shell-content": "", className: "px-6 py-7", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto max-w-7xl", children }) })
|
|
3325
3385
|
] })
|
|
3326
3386
|
]
|
|
3327
3387
|
}
|