-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathdesign-preview.js
More file actions
132 lines (110 loc) · 3.33 KB
/
design-preview.js
File metadata and controls
132 lines (110 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import classnames from 'classnames'
import {
useEffect, createPortal, useRef,
} from '@wordpress/element'
import { applyFilters } from '@wordpress/hooks'
import { safeHTML } from '@wordpress/dom'
const NOOP = () => {}
export const DesignPreview = ( {
blocks = '',
shadowRoot,
selectedTab,
designIndex,
onMouseDown = NOOP,
updateShadowBodySize = NOOP,
setIsLoading,
} ) => {
const ref = useRef( null )
const wrapperRef = useRef( null )
const isDragging = useRef( false )
const lastY = useRef( 0 )
const lastScrollTop = useRef( 0 )
const handleMouseDown = e => {
// Disable the auto scroll
onMouseDown()
isDragging.current = true
lastY.current = e.clientY
const container = ref.current
if ( container ) {
lastScrollTop.current = container.scrollTop
}
}
const handleMouseMove = e => {
if ( ! isDragging.current ) {
return
}
const container = ref.current
if ( container ) {
const deltaY = e.clientY - lastY.current
container.scrollTop = lastScrollTop.current - ( deltaY * 4 )
}
}
const handleMouseUp = () => {
isDragging.current = false
}
useEffect( () => {
const container = ref.current
if ( ! container || selectedTab !== 'pages' ) {
return
}
container.addEventListener( 'mousedown', handleMouseDown )
// eslint-disable-next-line @wordpress/no-global-event-listener
window.addEventListener( 'mousemove', handleMouseMove )
// eslint-disable-next-line @wordpress/no-global-event-listener
window.addEventListener( 'mouseup', handleMouseUp )
// Clean up the event listeners when the component unmounts.
return () => {
container.removeEventListener( 'mousedown', handleMouseDown )
// eslint-disable-next-line @wordpress/no-global-event-listener
window.removeEventListener( 'mousemove', handleMouseMove )
// eslint-disable-next-line @wordpress/no-global-event-listener
window.removeEventListener( 'mouseup', handleMouseUp )
}
}, [ selectedTab ] )
const shadowBodyClasses = classnames( applyFilters( 'stackable.global-styles.classnames', [
'entry-content',
] ), {
'preview-pages': selectedTab === 'pages',
} )
useEffect( () => {
const wrapper = wrapperRef.current
if ( ! wrapper || ! blocks ) {
return
}
setIsLoading( true )
// Prevent interaction and focus within the preview content
wrapper.setAttribute( 'inert', '' )
const ric = window.requestIdleCallback ? ( cb => window.requestIdleCallback( cb, { timeout: 5000 } ) )
: ( cb => setTimeout( cb, designIndex * 20 ) )
const sanitizedHTML = safeHTML( blocks )
if ( selectedTab !== 'pages' || designIndex < 9 ) {
// insert HTML for patterns and for the first 9 pages
wrapper.innerHTML = sanitizedHTML
requestAnimationFrame( () => {
ric( () => setIsLoading( false ) )
} )
return
}
requestAnimationFrame( () => {
ric( () => {
wrapper.innerHTML = sanitizedHTML
updateShadowBodySize()
requestAnimationFrame( () => {
ric( () => setIsLoading( false ) )
} )
} )
} )
}, [ blocks, shadowRoot ] ) // Only depend on blocks and shadowRoot; selectedTab and designIndex changes will cause blocks to update
return createPortal( <>
<body
ref={ ref }
className={ shadowBodyClasses }
>
<div
ref={ wrapperRef }
className="is-layout-constrained"
style={ { pointerEvents: 'none' } } // prevent blocks from being clicked
/>
</body>
</>, shadowRoot )
}