truecanvas 0.6.2 → 0.6.3

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.
@@ -3180,6 +3180,7 @@ function addVitePlugin(src) {
3180
3180
  export {
3181
3181
  listRoutes,
3182
3182
  layoutFiles,
3183
+ routeOf,
3183
3184
  componentsDir,
3184
3185
  DEVICES,
3185
3186
  findDevice,
@@ -294,6 +294,32 @@ button:focus-visible { outline: 2px solid #3b82f6; outline-offset: 1px; }
294
294
  : '<a class="who-btn" href="/signin?next=' + encodeURIComponent(here) + '">Sign in</a>'));
295
295
  }
296
296
 
297
+ // a page frame of a version with a live site shows the real site, on its own origin
298
+ function liveSrc(path) {
299
+ const home = new URL(manifest.live.url);
300
+ const url = new URL(path || "/", home);
301
+ const token = home.searchParams.get("tc_access");
302
+ if (token) url.searchParams.set("tc_access", token);
303
+ return url.href;
304
+ }
305
+ const showsLive = (f) => !!(manifest.live && f.route);
306
+ /**
307
+ * A frame outside a live session: the real site for page frames of a version
308
+ * that has one (animations and all), the frozen copy otherwise. The frozen
309
+ * image stays underneath until the iframe has loaded.
310
+ */
311
+ function restFrame(f, iframe, img) {
312
+ if (showsLive(f)) {
313
+ iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms");
314
+ iframe.setAttribute("referrerpolicy", "no-referrer");
315
+ iframe.src = liveSrc(f.route);
316
+ } else {
317
+ iframe.setAttribute("sandbox", "");
318
+ iframe.src = f.html;
319
+ }
320
+ iframe.addEventListener("load", () => { iframe.classList.add("ready"); if (showsLive(f) && img) img.style.visibility = "hidden"; });
321
+ }
322
+
297
323
  // layout: frames at their canvas positions
298
324
  const frames = manifest.frames;
299
325
  const minX = Math.min(...frames.map((f) => f.x)), minY = Math.min(...frames.map((f) => f.y));
@@ -304,9 +330,8 @@ button:focus-visible { outline: 2px solid #3b82f6; outline-offset: 1px; }
304
330
  el.className = "frame";
305
331
  el.style.cssText = "left:" + (f.x - minX) + "px;top:" + (f.y - minY) + "px;width:" + f.width + "px;height:" + f.height + "px";
306
332
  el.innerHTML = '<div class="frame-label"><b>' + esc(f.name) + "</b>" + f.width + " \xD7 " + Math.round(f.height) + (manifest.live ? '<button class="live-btn" title="Open the live site at this width"><svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><path d="M7 4.5v15l13-7.5z"/></svg>View live</button>' : "") + "</div>" +
307
- '<div class="frame-box" style="width:' + f.width + "px;height:" + f.height + 'px"><img alt="" src="' + esc(f.image) + '"><iframe sandbox title="' + esc(f.name) + '" scrolling="no" loading="lazy" src="' + esc(f.html) + '"></iframe></div>';
308
- const iframe = el.querySelector("iframe");
309
- iframe.addEventListener("load", () => iframe.classList.add("ready"));
333
+ '<div class="frame-box" style="width:' + f.width + "px;height:" + f.height + 'px"><img alt="" src="' + esc(f.image) + '"><iframe title="' + esc(f.name) + '" scrolling="no" loading="lazy"></iframe></div>';
334
+ restFrame(f, el.querySelector("iframe"), el.querySelector("img"));
310
335
  const liveBtn = el.querySelector(".live-btn");
311
336
  if (liveBtn) liveBtn.onclick = (e) => { e.stopPropagation(); openLive(f); };
312
337
  el.dataset.name = f.name;
@@ -465,7 +490,7 @@ button:focus-visible { outline: 2px solid #3b82f6; outline-offset: 1px; }
465
490
  iframe.title = "Live site: " + f.name;
466
491
  iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox");
467
492
  iframe.setAttribute("referrerpolicy", "no-referrer");
468
- iframe.src = manifest.live.url;
493
+ iframe.src = f.route ? liveSrc(f.route) : manifest.live.url;
469
494
  liveDevice.appendChild(iframe);
470
495
  document.getElementById("live-name").textContent = f.name;
471
496
  document.getElementById("live-tab").href = manifest.live.url;
@@ -819,13 +844,12 @@ button:focus-visible { outline: 2px solid #3b82f6; outline-offset: 1px; }
819
844
  next.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms");
820
845
  next.setAttribute("referrerpolicy", "no-referrer");
821
846
  next.src = sessionFrame(f);
847
+ next.addEventListener("load", () => { next.classList.add("ready"); if (img) img.style.visibility = "hidden"; });
822
848
  } else {
823
- next.setAttribute("sandbox", "");
824
849
  next.loading = "lazy";
825
- next.src = f.html;
826
850
  if (img) img.style.visibility = "";
851
+ restFrame(f, next, img);
827
852
  }
828
- next.addEventListener("load", () => { next.classList.add("ready"); if (on && img) img.style.visibility = "hidden"; });
829
853
  old.replaceWith(next);
830
854
  }
831
855
  renderRoom();
package/dist/cli.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  responseHeaders,
23
23
  safePath,
24
24
  viewerHtml
25
- } from "./chunk-OPKROZI2.js";
25
+ } from "./chunk-S5P2CHHZ.js";
26
26
  import {
27
27
  DEVICES,
28
28
  Workspace,
@@ -39,12 +39,13 @@ import {
39
39
  outlineDoc,
40
40
  readDesignTokens,
41
41
  readTokenData,
42
+ routeOf,
42
43
  shadcnAdd,
43
44
  shadcnRegistry,
44
45
  shadcnStatus,
45
46
  syncComponentRegistry,
46
47
  writeCompare
47
- } from "./chunk-QJ5M3G4E.js";
48
+ } from "./chunk-PLJRUWCS.js";
48
49
  import {
49
50
  EditError,
50
51
  addArgs,
@@ -144,7 +145,8 @@ async function createSnapshot(ws, shots, canvas, opts = {}) {
144
145
  used.add(slug);
145
146
  fs.writeFileSync(path.join(dir, "frames", `${slug}.html`), await freeze(raw, assets));
146
147
  fs.writeFileSync(path.join(dir, "frames", `${slug}.png`), raw.png);
147
- out.push({ name: f.frameName, x: f.x, y: f.y, width: raw.width, height: f.height ?? raw.height, theme: f.theme, device: f.device, html: `frames/${slug}.html`, image: `frames/${slug}.png` });
148
+ const route = f.page && ws.config.framework === "next" ? routeOf(ws.config, f.page) : void 0;
149
+ out.push({ name: f.frameName, x: f.x, y: f.y, width: raw.width, height: f.height ?? raw.height, theme: f.theme, device: f.device, html: `frames/${slug}.html`, image: `frames/${slug}.png`, ...route ? { route } : {} });
148
150
  }
149
151
  const manifest = {
150
152
  format: 1,
@@ -20,7 +20,7 @@ import {
20
20
  viteStylesheets,
21
21
  wrapConfigExport,
22
22
  writeCompare
23
- } from "../chunk-QJ5M3G4E.js";
23
+ } from "../chunk-PLJRUWCS.js";
24
24
  import {
25
25
  CanvasEditor,
26
26
  EditError,
@@ -22,6 +22,8 @@ interface ShareFrame {
22
22
  /** paths inside the snapshot */
23
23
  html: string;
24
24
  image: string;
25
+ /** a frame linked to a page: its URL in the app (e.g. "/pricing"), so the live site can show it */
26
+ route?: string;
25
27
  }
26
28
  interface ShareManifest {
27
29
  format: 1;
@@ -6,7 +6,7 @@ import {
6
6
  responseHeaders,
7
7
  safePath,
8
8
  viewerHtml
9
- } from "../chunk-OPKROZI2.js";
9
+ } from "../chunk-S5P2CHHZ.js";
10
10
  export {
11
11
  CHUNK,
12
12
  decodeFrame,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "truecanvas",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "Design with your real React components: a Figma-like canvas for Next.js and Vite where layers are your .tsx and agents edit through MCP.",
5
5
  "license": "MIT",
6
6
  "type": "module",