@littlepartytime/dev-kit 1.18.2 → 1.18.4
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.
|
@@ -46,6 +46,7 @@ export default function PhoneFrame({ children }: { children: React.ReactNode })
|
|
|
46
46
|
<div style={{ width: BODY_W * scale, height: BODY_H * scale, flexShrink: 0 }}>
|
|
47
47
|
{/* Phone body at original pixel size, visually scaled */}
|
|
48
48
|
<div
|
|
49
|
+
id="devkit-phone"
|
|
49
50
|
style={{
|
|
50
51
|
position: 'relative',
|
|
51
52
|
width: BODY_W,
|
|
@@ -1,55 +1,50 @@
|
|
|
1
1
|
import html2canvas from 'html2canvas';
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
const
|
|
5
|
-
const CAPTURE_H = 751; // 844 - 59 - 34
|
|
3
|
+
// PhoneFrame body width (bezel included): 390 + 8*2
|
|
4
|
+
const PHONE_W = 406;
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
|
-
* Captures the game content
|
|
9
|
-
* Returns a base64-encoded
|
|
7
|
+
* Captures the phone model (game content + bezel frame) as a PNG.
|
|
8
|
+
* Returns a base64-encoded data URL.
|
|
10
9
|
*
|
|
11
10
|
* Also exposed on window.__devkit__.captureScreen() for LLM/Playwright callers:
|
|
12
11
|
* await page.evaluate(() => window.__devkit__.captureScreen())
|
|
13
12
|
*
|
|
14
|
-
* ##
|
|
15
|
-
* html2canvas clones the entire document before rendering. The PhoneFrame DOM
|
|
16
|
-
* has three CSS properties that break the capture:
|
|
13
|
+
* ## Strategy: capture from documentElement with visual crop
|
|
17
14
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* - `overflow: hidden` on ancestors — once transform is removed, the full-size
|
|
24
|
-
* phone body overflows its scaled wrapper and gets clipped.
|
|
15
|
+
* The phone body lives inside transform:scale(x) + contain:paint, which makes
|
|
16
|
+
* its getBoundingClientRect() return the *visual* (scaled) size. Previous
|
|
17
|
+
* attempts to target the game element directly all failed because html2canvas
|
|
18
|
+
* reads the target's bounding rect first, then clones — the crop coordinates
|
|
19
|
+
* never agree with the clone's layout.
|
|
25
20
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
21
|
+
* By targeting document.documentElement and passing the phone body's visual
|
|
22
|
+
* bounding rect as an explicit crop, html2canvas renders the full page as-is
|
|
23
|
+
* (all CSS respected) and simply cuts out the phone region. Crop coordinates
|
|
24
|
+
* equal visual coordinates — no mismatch possible.
|
|
28
25
|
*/
|
|
29
26
|
export async function captureScreen(): Promise<string> {
|
|
30
|
-
const
|
|
31
|
-
if (!
|
|
27
|
+
const phone = document.getElementById('devkit-phone');
|
|
28
|
+
if (!phone) throw new Error('[devkit] #devkit-phone not found — is the Preview page active?');
|
|
32
29
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
const rect = phone.getBoundingClientRect();
|
|
31
|
+
if (rect.width === 0 || rect.height === 0) {
|
|
32
|
+
throw new Error('[devkit] phone frame has zero dimensions');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Upsample so the output matches the phone's natural size at 2× retina.
|
|
36
|
+
const outputScale = (PHONE_W * 2) / rect.width;
|
|
37
|
+
|
|
38
|
+
const canvas = await html2canvas(document.documentElement, {
|
|
39
|
+
x: rect.left + window.scrollX,
|
|
40
|
+
y: rect.top + window.scrollY,
|
|
41
|
+
width: rect.width,
|
|
42
|
+
height: rect.height,
|
|
43
|
+
scale: outputScale,
|
|
37
44
|
logging: false,
|
|
38
45
|
backgroundColor: null,
|
|
39
46
|
useCORS: true,
|
|
40
47
|
allowTaint: true,
|
|
41
|
-
onclone: (clonedDoc: Document) => {
|
|
42
|
-
const clonedEl = clonedDoc.getElementById('devkit-game-screen');
|
|
43
|
-
if (!clonedEl) return;
|
|
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
48
|
});
|
|
54
49
|
|
|
55
50
|
return canvas.toDataURL('image/png');
|