@@ -10,16 +10,20 @@ export const DeviceContainer: React.FC<{
10
10
const { children } = props
11
11
12
12
const deviceFrameRef = React . useRef < HTMLDivElement > ( null )
13
+ const outerFrameRef = React . useRef < HTMLDivElement > ( null )
13
14
14
- const { breakpoint, setMeasuredDeviceSize, size, zoom } = useLivePreviewContext ( )
15
+ const { breakpoint, setMeasuredDeviceSize, size : desiredSize , zoom } = useLivePreviewContext ( )
15
16
16
17
// Keep an accurate measurement of the actual device size as it is truly rendered
17
18
// This is helpful when `sizes` are non-number units like percentages, etc.
18
- const { size : measuredDeviceSize } = useResize ( deviceFrameRef )
19
+ const { size : measuredDeviceSize } = useResize ( deviceFrameRef . current )
20
+ const { size : outerFrameSize } = useResize ( outerFrameRef . current )
21
+
22
+ let deviceIsLargerThanFrame : boolean = false
19
23
20
24
// Sync the measured device size with the context so that other components can use it
21
25
// This happens from the bottom up so that as this component mounts and unmounts,
22
- // Its size is freshly populated again upon re-mounting, i.e. going from iframe->popup->iframe
26
+ // its size is freshly populated again upon re-mounting, i.e. going from iframe->popup->iframe
23
27
useEffect ( ( ) => {
24
28
if ( measuredDeviceSize ) {
25
29
setMeasuredDeviceSize ( measuredDeviceSize )
@@ -34,35 +38,64 @@ export const DeviceContainer: React.FC<{
34
38
35
39
if (
36
40
typeof zoom === 'number' &&
37
- typeof size . width === 'number' &&
38
- typeof size . height === 'number'
41
+ typeof desiredSize . width === 'number' &&
42
+ typeof desiredSize . height === 'number' &&
43
+ typeof measuredDeviceSize . width === 'number' &&
44
+ typeof measuredDeviceSize . height === 'number'
39
45
) {
40
- const scaledWidth = size . width / zoom
41
- const difference = scaledWidth - size . width
42
- x = `${ difference / 2 } px`
43
46
margin = '0 auto'
47
+ const scaledDesiredWidth = desiredSize . width / zoom
48
+ const scaledDeviceWidth = measuredDeviceSize . width * zoom
49
+ const scaledDeviceDifferencePixels = scaledDesiredWidth - desiredSize . width
50
+ deviceIsLargerThanFrame = scaledDeviceWidth > outerFrameSize . width
51
+
52
+ if ( deviceIsLargerThanFrame ) {
53
+ if ( zoom > 1 ) {
54
+ const differenceFromDeviceToFrame = measuredDeviceSize . width - outerFrameSize . width
55
+ if ( differenceFromDeviceToFrame < 0 ) x = `${ differenceFromDeviceToFrame / 2 } px`
56
+ else x = '0'
57
+ } else {
58
+ x = '0'
59
+ }
60
+ } else {
61
+ if ( zoom >= 1 ) {
62
+ x = `${ scaledDeviceDifferencePixels / 2 } px`
63
+ } else {
64
+ const differenceFromDeviceToFrame = outerFrameSize . width - scaledDeviceWidth
65
+ x = `${ differenceFromDeviceToFrame / 2 } px`
66
+ margin = '0'
67
+ }
68
+ }
44
69
}
45
70
}
46
71
47
72
let width = zoom ? `${ 100 / zoom } %` : '100%'
48
73
let height = zoom ? `${ 100 / zoom } %` : '100%'
49
74
50
75
if ( breakpoint !== 'responsive' ) {
51
- width = `${ size ?. width / ( typeof zoom === 'number' ? zoom : 1 ) } px`
52
- height = `${ size ?. height / ( typeof zoom === 'number' ? zoom : 1 ) } px`
76
+ width = `${ desiredSize ?. width / ( typeof zoom === 'number' ? zoom : 1 ) } px`
77
+ height = `${ desiredSize ?. height / ( typeof zoom === 'number' ? zoom : 1 ) } px`
53
78
}
54
79
55
80
return (
56
81
< div
57
- ref = { deviceFrameRef }
82
+ ref = { outerFrameRef }
58
83
style = { {
59
- height,
60
- margin,
61
- transform : `translate3d(${ x } , 0, 0)` ,
62
- width,
84
+ height : '100%' ,
85
+ width : '100%' ,
63
86
} }
64
87
>
65
- { children }
88
+ < div
89
+ ref = { deviceFrameRef }
90
+ style = { {
91
+ height,
92
+ margin,
93
+ transform : `translate3d(${ x } , 0, 0)` ,
94
+ width,
95
+ } }
96
+ >
97
+ { children }
98
+ </ div >
66
99
</ div >
67
100
)
68
101
}
0 commit comments