Skip to content

Commit f5782f6

Browse files
authored
fix (design library): preview fixes (#3606)
* fixes - add timeout to requestIdleCallback - scale on styles load * fix fallback logic * add/adjust timeout * adjust timeout * adjust fallback
1 parent ab1fd2a commit f5782f6

File tree

6 files changed

+83
-40
lines changed

6 files changed

+83
-40
lines changed

src/components/design-library-list/design-library-list-item.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { Tooltip } from '~stackable/components'
2020
*/
2121
import {
2222
useState, useRef, memo,
23+
useMemo,
2324
} from '@wordpress/element'
2425
import { Dashicon, Spinner } from '@wordpress/components'
2526
import { __ } from '@wordpress/i18n'
@@ -43,7 +44,9 @@ const DesignLibraryListItem = memo( props => {
4344
const [ isLoading, setIsLoading ] = useState( true )
4445
const [ selected, setSelected ] = useState( false )
4546

46-
const { hostRef, shadowRoot } = useShadowRoot( shouldRender )
47+
const {
48+
hostRef, shadowRoot, stylesLoaded,
49+
} = useShadowRoot( shouldRender )
4750

4851
const ref = useRef( null )
4952

@@ -53,13 +56,13 @@ const DesignLibraryListItem = memo( props => {
5356
previewSize, onClickDesign,
5457
updateShadowBodySize,
5558
} = usePreviewRenderer( previewProps, shouldRender, spacingSize,
56-
ref, hostRef, shadowRoot, setIsLoading )
59+
ref, hostRef, shadowRoot, setIsLoading, stylesLoaded )
5760

5861
const {
5962
onMouseOut, onMouseOver, onMouseDown,
6063
} = useAutoScroll( hostRef, shadowBodySizeRef, selectedTab )
6164

62-
const getDesignPreviewSize = () => {
65+
const designPreviewSize = useMemo( () => {
6366
const tempHeight = selectedTab === 'pages' ? 345 : 100
6467

6568
const previewHeight = selectedNum && selectedData ? selectedData.selectedPreviewSize.preview
@@ -70,7 +73,7 @@ const DesignLibraryListItem = memo( props => {
7073
}
7174

7275
return previewHeight
73-
}
76+
}, [ selectedTab, selectedNum, selectedData, previewSize, blocks, enableBackground ] )
7477

7578
const mainClasses = classnames( [
7679
'ugb-design-library-item',
@@ -99,7 +102,7 @@ const DesignLibraryListItem = memo( props => {
99102
onMouseOver={ onMouseOver }
100103
>
101104
{ ! isPro && plan !== 'free' && <span className="stk-pulsating-circle" role="presentation" /> }
102-
<div style={ { position: 'relative' } } className={ `stk-block-design__design-container ${ getDesignPreviewSize() > 100 ? 'stk--design-preview-large' : 'stk--design-preview-small' }` }>
105+
<div style={ { position: 'relative' } } className={ `stk-block-design__design-container ${ designPreviewSize > 100 ? 'stk--design-preview-large' : 'stk--design-preview-small' }` }>
103106
{ ! isPro && plan !== 'free' && (
104107
<ProControl
105108
type="design-library"
@@ -113,7 +116,7 @@ const DesignLibraryListItem = memo( props => {
113116
style={ {
114117
transform: `scale(${ selectedNum && selectedData ? selectedData.selectedPreviewSize.scale : previewSize?.scale })`,
115118
transformOrigin: 'top left',
116-
height: getDesignPreviewSize(),
119+
height: designPreviewSize,
117120
} }
118121
>
119122
<div className="stk-block-design__host" ref={ hostRef }>

src/components/design-library-list/design-preview.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,8 @@ export const DesignPreview = ( {
9090

9191
setIsLoading( true )
9292

93-
// Comment this since our requestIdleCallback is not called
94-
// const ric = window.requestIdleCallback || ( cb => setTimeout( cb, designIndex * 20 ) )
95-
const ric = cb => setTimeout( cb, designIndex * 20 )
93+
const ric = window.requestIdleCallback ? ( cb => window.requestIdleCallback( cb, { timeout: 5000 } ) )
94+
: ( cb => setTimeout( cb, designIndex * 20 ) )
9695
const sanitizedHTML = safeHTML( blocks )
9796

9897
if ( selectedTab !== 'pages' || designIndex < 9 ) {

src/components/design-library-list/editor.scss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,11 @@
246246
will-change: opacity;
247247
opacity: 1;
248248
display: flex;
249-
// background-color: #fff;
250-
// z-index: 1;
249+
background-color: #fff;
250+
z-index: 1;
251251
&.stk-hide-spinner {
252252
opacity: 0;
253-
// z-index: -1;
253+
z-index: -1;
254254
}
255255
.components-spinner {
256256
margin: auto;

src/components/design-library-list/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,10 @@ const DesignLibraryItem = memo( props => {
129129
}
130130
let id
131131
if ( typeof requestIdleCallback !== 'undefined' ) {
132-
id = requestIdleCallback( () => ! shouldRender ? setShouldRender( true ) : {} )
132+
id = requestIdleCallback( () => ! shouldRender ? setShouldRender( true ) : {}, { timeout: ( designIndex + 1 ) * 500 } )
133133
} else {
134-
// fallback
135-
id = setTimeout( () => setShouldRender( true ), designIndex * 20 )
134+
// fallback, always render immediately the first design
135+
id = setTimeout( () => setShouldRender( true ), designIndex * 500 )
136136
}
137137

138138
return () => {

src/components/design-library-list/use-preview-renderer.js

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const DEFAULT_CONTENT = { ...DEFAULT }
3636

3737
export const usePreviewRenderer = (
3838
props, shouldRender, spacingSize,
39-
ref, hostRef, shadowRoot, setIsLoading
39+
ref, hostRef, shadowRoot, setIsLoading, stylesLoaded
4040
) => {
4141
const {
4242
designId,
@@ -84,13 +84,13 @@ export const usePreviewRenderer = (
8484
}
8585
}
8686

87-
const adjustScale = ( force = true ) => {
87+
const adjustScale = ( force = 2, callCount = 0 ) => {
8888
const parentDiv = ref?.current?.querySelector( '.stk-block-design__design-container' )
8989
const shouldAdjust = ref.current && hostRef.current && shadowRoot && parentDiv &&
9090
( ! selectedNum || // adjust if design is not selected
9191
prevSelectedTabRef.current !== selectedTab ) // adjust if selected tab changed even if design is selected
9292

93-
if ( ! shouldAdjust ) {
93+
if ( ! shouldAdjust || ! force || callCount > 3 ) {
9494
return
9595
}
9696

@@ -103,17 +103,17 @@ export const usePreviewRenderer = (
103103

104104
// Consider heights equal if the difference is less than 1px
105105
const isEqualHeight = Math.abs( parentDivRect.height - hostRect.height ) < 1
106+
const isEqualWidth = Math.abs( cardWidth - hostWidth ) < 1
106107

107-
if ( ! force && cardWidth === hostWidth && isEqualHeight ) {
108-
if ( adjustAnimateFrameRef.current !== null ) {
109-
cancelAnimationFrame( adjustAnimateFrameRef.current )
110-
}
111-
adjustAnimateFrameRef.current = null
112-
return
108+
let recompute = true
109+
110+
if ( isEqualWidth && isEqualHeight ) {
111+
force -= 1
112+
recompute = false
113113
}
114114

115115
const shadowBody = shadowRoot.querySelector( 'body' )
116-
if ( shadowBody ) {
116+
if ( shadowBody && recompute ) {
117117
const scaleFactor = cardWidth > 0 ? cardWidth / 1300 : 1 // Divide by 1300, which is the width of preview in the shadow DOM
118118

119119
let _bodyHeight = 1200
@@ -144,7 +144,7 @@ export const usePreviewRenderer = (
144144
if ( adjustAnimateFrameRef.current !== null ) {
145145
cancelAnimationFrame( adjustAnimateFrameRef.current )
146146
}
147-
adjustAnimateFrameRef.current = requestAnimationFrame( () => adjustScale( false ) )
147+
adjustAnimateFrameRef.current = requestAnimationFrame( () => adjustScale( force, ++callCount ) )
148148
}
149149

150150
const renderPreview = ( blockContent = content ) => {
@@ -327,7 +327,7 @@ export const usePreviewRenderer = (
327327
if ( adjustAnimateFrameRef.current !== null ) {
328328
cancelAnimationFrame( adjustAnimateFrameRef.current )
329329
}
330-
adjustAnimateFrameRef.current = requestAnimationFrame( adjustScale )
330+
adjustAnimateFrameRef.current = requestAnimationFrame( () => adjustScale() )
331331
}, [ content, containerScheme, backgroundScheme, enableBackground, selectedNum, shouldRender, shadowRoot ] )
332332

333333
// Handle background changes separately to avoid unnecessary re-renders
@@ -342,10 +342,22 @@ export const usePreviewRenderer = (
342342
if ( adjustAnimateFrameRef.current !== null ) {
343343
cancelAnimationFrame( adjustAnimateFrameRef.current )
344344
}
345-
adjustAnimateFrameRef.current = requestAnimationFrame( adjustScale )
345+
adjustAnimateFrameRef.current = requestAnimationFrame( () => adjustScale() )
346346
}
347347
}, [ blocks, enableBackground ] )
348348

349+
useEffect( () => {
350+
if ( ! blocks.parsed || ! blocks.serialized || ! shouldRender ) {
351+
return
352+
}
353+
354+
if ( adjustAnimateFrameRef.current !== null ) {
355+
cancelAnimationFrame( adjustAnimateFrameRef.current )
356+
}
357+
358+
adjustAnimateFrameRef.current = requestAnimationFrame( () => adjustScale() )
359+
}, [ stylesLoaded ] )
360+
349361
// cleanup any pending animation on unmount
350362
useEffect( () => {
351363
return () => {

src/components/design-library-list/use-shadow-root.js

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { applyFilters } from '@wordpress/hooks'
1010
export const useShadowRoot = shouldRender => {
1111
const hostRef = useRef( null )
1212
const [ shadowRoot, setShadowRoot ] = useState( null )
13+
const [ stylesLoaded, setStylesLoaded ] = useState( 0 )
1314

1415
const { getEditorDom } = useSelect( 'stackable/editor-dom' )
1516
const editorDom = getEditorDom()
@@ -25,6 +26,12 @@ export const useShadowRoot = shouldRender => {
2526
useEffect( () => {
2627
if ( shouldRender && hostRef.current ) {
2728
const shadow = hostRef.current.shadowRoot || hostRef.current.attachShadow( { mode: 'open' } )
29+
setStylesLoaded( 0 )
30+
31+
// Track existing style/link nodes in the shadow root to avoid duplicates
32+
const existingIds = new Set(
33+
Array.from( shadow.querySelectorAll( 'style[id],link[id]' ) ).map( n => n.id )
34+
)
2835

2936
const styleNodes = STYLE_IDS.map( id => {
3037
let style = null
@@ -48,30 +55,52 @@ export const useShadowRoot = shouldRender => {
4855
} ).filter( node => node !== null )
4956

5057
// Add global and theme styles
51-
const globalStylesNode = document.createElement( 'style' )
52-
globalStylesNode.setAttribute( 'id', 'global-styles-inline-css' )
53-
globalStylesNode.innerHTML = wpGlobalStylesInlineCss
54-
styleNodes.push( globalStylesNode )
55-
56-
const hostStyles = document.createElement( 'style' )
57-
hostStyles.setAttribute( 'id', 'stk-design-library-styles' )
58+
if ( ! existingIds.has( 'global-styles-inline-css' ) ) {
59+
const globalStylesNode = document.createElement( 'style' )
60+
globalStylesNode.setAttribute( 'id', 'global-styles-inline-css' )
61+
globalStylesNode.innerHTML = wpGlobalStylesInlineCss
62+
styleNodes.push( globalStylesNode )
63+
}
64+
65+
if ( ! existingIds.has( 'stk-design-library-styles' ) ) {
66+
const hostStyles = document.createElement( 'style' )
67+
hostStyles.setAttribute( 'id', 'stk-design-library-styles' )
68+
69+
// Additional styles for blocks to render properly in the preview
70+
hostStyles.innerHTML += getAdditionalStylesForPreview()
71+
styleNodes.push( hostStyles )
72+
}
5873

59-
// Additional styles for blocks to render properly in the preview
60-
hostStyles.innerHTML += getAdditionalStylesForPreview()
74+
styleNodes.forEach( node => {
75+
if ( node.id && existingIds.has( node.id ) ) {
76+
return
77+
}
6178

62-
styleNodes.push( hostStyles )
79+
if ( node.href ) {
80+
node.onload = () => {
81+
setStylesLoaded( prev => prev + 1 )
82+
}
83+
node.onerror = () => {
84+
setStylesLoaded( prev => prev + 1 )
85+
}
86+
}
6387

64-
styleNodes.forEach( node => {
6588
if ( node.textContent ) {
6689
// we use :host in the shadow DOM to target the root
6790
node.textContent = node.textContent.replace( /:root/g, ':host' )
6891
}
6992
shadow.appendChild( node )
93+
94+
if ( node.id ) {
95+
existingIds.add( node.id )
96+
}
7097
} )
7198

7299
setShadowRoot( shadow )
73100
}
74101
}, [ shouldRender ] )
75102

76-
return { hostRef, shadowRoot }
103+
return {
104+
hostRef, shadowRoot, stylesLoaded,
105+
}
77106
}

0 commit comments

Comments
 (0)