@littlepartytime/dev-kit 1.18.2 → 1.18.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.
@@ -11,48 +11,51 @@ const CAPTURE_H = 751; // 844 - 59 - 34
11
11
  * Also exposed on window.__devkit__.captureScreen() for LLM/Playwright callers:
12
12
  * await page.evaluate(() => window.__devkit__.captureScreen())
13
13
  *
14
- * ## Why onclone?
15
- * html2canvas clones the entire document before rendering. The PhoneFrame DOM
16
- * has three CSS properties that break the capture:
14
+ * ## Strategy: clone into a mobile-viewport-sized container
17
15
  *
18
- * - `contain: paint` on Screen div and safe-area div html2canvas uses
19
- * getBoundingClientRect() to compute clip rects, which returns the *visual*
20
- * (post-transform) size, clipping the output to ~half height.
21
- * - `transform: scale(x)` on the phone body same getBoundingClientRect
22
- * mismatch; intrinsic size is 390×751 but visual rect is smaller.
23
- * - `overflow: hidden` on ancestors — once transform is removed, the full-size
24
- * phone body overflows its scaled wrapper and gets clipped.
16
+ * All LPT games are designed for full-screen mobile. In the dev-kit, the game
17
+ * renders inside PhoneFrame which wraps it in transform:scale + contain:paint.
18
+ * html2canvas cannot correctly capture elements inside this hierarchy because
19
+ * getBoundingClientRect() returns the scaled visual size, not the natural size.
25
20
  *
26
- * Fix: in the `onclone` callback, neutralise all three properties on ancestor
27
- * elements of the *cloned* document. The original DOM is never touched.
21
+ * Instead of fighting html2canvas, we deep-clone the game DOM subtree into a
22
+ * standalone 390×751 container appended to <body> no transforms, no contain,
23
+ * no overflow clipping from ancestors. The game content is designed for exactly
24
+ * this size, so it renders correctly. html2canvas captures the clean container
25
+ * with no coordinate mismatches.
28
26
  */
29
27
  export async function captureScreen(): Promise<string> {
30
28
  const el = document.getElementById('devkit-game-screen');
31
29
  if (!el) throw new Error('[devkit] #devkit-game-screen not found — is the Preview page active?');
32
30
 
33
- const canvas = await html2canvas(el, {
34
- width: CAPTURE_W,
35
- height: CAPTURE_H,
36
- scale: 2,
37
- logging: false,
38
- backgroundColor: null,
39
- useCORS: true,
40
- allowTaint: true,
41
- onclone: (clonedDoc: Document) => {
42
- const clonedEl = clonedDoc.getElementById('devkit-game-screen');
43
- if (!clonedEl) return;
31
+ // Deep-clone the safe-area subtree into a standalone mobile-sized container.
32
+ const clone = el.cloneNode(true) as HTMLElement;
33
+ clone.removeAttribute('id');
34
+ clone.removeAttribute('data-testid');
35
+ clone.style.cssText = `
36
+ position: absolute;
37
+ left: -9999px;
38
+ top: 0;
39
+ width: ${CAPTURE_W}px;
40
+ height: ${CAPTURE_H}px;
41
+ overflow: hidden;
42
+ `;
43
+ document.body.appendChild(clone);
44
44
 
45
- let node: HTMLElement | null = clonedEl;
46
- while (node && node !== clonedDoc.body) {
47
- node.style.contain = '';
48
- node.style.transform = 'none';
49
- node.style.overflow = 'visible';
50
- node = node.parentElement;
51
- }
52
- },
53
- });
54
-
55
- return canvas.toDataURL('image/png');
45
+ try {
46
+ const canvas = await html2canvas(clone, {
47
+ width: CAPTURE_W,
48
+ height: CAPTURE_H,
49
+ scale: 2,
50
+ logging: false,
51
+ backgroundColor: null,
52
+ useCORS: true,
53
+ allowTaint: true,
54
+ });
55
+ return canvas.toDataURL('image/png');
56
+ } finally {
57
+ document.body.removeChild(clone);
58
+ }
56
59
  }
57
60
 
58
61
  export function downloadScreenshot(dataUrl: string): void {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@littlepartytime/dev-kit",
3
- "version": "1.18.2",
3
+ "version": "1.18.3",
4
4
  "description": "Development toolkit CLI for Little Party Time game developers",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",