Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions src/components/design-library-list/design-library-list-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Tooltip } from '~stackable/components'
*/
import {
useState, useRef, memo,
useMemo,
} from '@wordpress/element'
import { Dashicon, Spinner } from '@wordpress/components'
import { __ } from '@wordpress/i18n'
Expand All @@ -43,7 +44,9 @@ const DesignLibraryListItem = memo( props => {
const [ isLoading, setIsLoading ] = useState( true )
const [ selected, setSelected ] = useState( false )

const { hostRef, shadowRoot } = useShadowRoot( shouldRender )
const {
hostRef, shadowRoot, stylesLoaded,
} = useShadowRoot( shouldRender )

const ref = useRef( null )

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

const {
onMouseOut, onMouseOver, onMouseDown,
} = useAutoScroll( hostRef, shadowBodySizeRef, selectedTab )

const getDesignPreviewSize = () => {
const designPreviewSize = useMemo( () => {
const tempHeight = selectedTab === 'pages' ? 345 : 100

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

return previewHeight
}
}, [ selectedTab, selectedNum, selectedData, previewSize, blocks, enableBackground ] )

const mainClasses = classnames( [
'ugb-design-library-item',
Expand Down Expand Up @@ -99,7 +102,7 @@ const DesignLibraryListItem = memo( props => {
onMouseOver={ onMouseOver }
>
{ ! isPro && plan !== 'free' && <span className="stk-pulsating-circle" role="presentation" /> }
<div style={ { position: 'relative' } } className={ `stk-block-design__design-container ${ getDesignPreviewSize() > 100 ? 'stk--design-preview-large' : 'stk--design-preview-small' }` }>
<div style={ { position: 'relative' } } className={ `stk-block-design__design-container ${ designPreviewSize > 100 ? 'stk--design-preview-large' : 'stk--design-preview-small' }` }>
{ ! isPro && plan !== 'free' && (
<ProControl
type="design-library"
Expand All @@ -113,7 +116,7 @@ const DesignLibraryListItem = memo( props => {
style={ {
transform: `scale(${ selectedNum && selectedData ? selectedData.selectedPreviewSize.scale : previewSize?.scale })`,
transformOrigin: 'top left',
height: getDesignPreviewSize(),
height: designPreviewSize,
} }
>
<div className="stk-block-design__host" ref={ hostRef }>
Expand Down
5 changes: 2 additions & 3 deletions src/components/design-library-list/design-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,8 @@ export const DesignPreview = ( {

setIsLoading( true )

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

if ( selectedTab !== 'pages' || designIndex < 9 ) {
Expand Down
6 changes: 3 additions & 3 deletions src/components/design-library-list/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -246,11 +246,11 @@
will-change: opacity;
opacity: 1;
display: flex;
// background-color: #fff;
// z-index: 1;
background-color: #fff;
z-index: 1;
&.stk-hide-spinner {
opacity: 0;
// z-index: -1;
z-index: -1;
}
.components-spinner {
margin: auto;
Expand Down
6 changes: 3 additions & 3 deletions src/components/design-library-list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,10 @@ const DesignLibraryItem = memo( props => {
}
let id
if ( typeof requestIdleCallback !== 'undefined' ) {
id = requestIdleCallback( () => ! shouldRender ? setShouldRender( true ) : {} )
id = requestIdleCallback( () => ! shouldRender ? setShouldRender( true ) : {}, { timeout: ( designIndex + 1 ) * 500 } )
} else {
// fallback
id = setTimeout( () => setShouldRender( true ), designIndex * 20 )
// fallback, always render immediately the first design
id = setTimeout( () => setShouldRender( true ), designIndex * 500 )
}

return () => {
Expand Down
38 changes: 25 additions & 13 deletions src/components/design-library-list/use-preview-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const DEFAULT_CONTENT = { ...DEFAULT }

export const usePreviewRenderer = (
props, shouldRender, spacingSize,
ref, hostRef, shadowRoot, setIsLoading
ref, hostRef, shadowRoot, setIsLoading, stylesLoaded
) => {
const {
designId,
Expand Down Expand Up @@ -84,13 +84,13 @@ export const usePreviewRenderer = (
}
}

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

if ( ! shouldAdjust ) {
if ( ! shouldAdjust || ! force || callCount > 3 ) {
return
}

Expand All @@ -103,17 +103,17 @@ export const usePreviewRenderer = (

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

if ( ! force && cardWidth === hostWidth && isEqualHeight ) {
if ( adjustAnimateFrameRef.current !== null ) {
cancelAnimationFrame( adjustAnimateFrameRef.current )
}
adjustAnimateFrameRef.current = null
return
let recompute = true

if ( isEqualWidth && isEqualHeight ) {
force -= 1
recompute = false
}

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

let _bodyHeight = 1200
Expand Down Expand Up @@ -144,7 +144,7 @@ export const usePreviewRenderer = (
if ( adjustAnimateFrameRef.current !== null ) {
cancelAnimationFrame( adjustAnimateFrameRef.current )
}
adjustAnimateFrameRef.current = requestAnimationFrame( () => adjustScale( false ) )
adjustAnimateFrameRef.current = requestAnimationFrame( () => adjustScale( force, ++callCount ) )
}

const renderPreview = ( blockContent = content ) => {
Expand Down Expand Up @@ -327,7 +327,7 @@ export const usePreviewRenderer = (
if ( adjustAnimateFrameRef.current !== null ) {
cancelAnimationFrame( adjustAnimateFrameRef.current )
}
adjustAnimateFrameRef.current = requestAnimationFrame( adjustScale )
adjustAnimateFrameRef.current = requestAnimationFrame( () => adjustScale() )
}, [ content, containerScheme, backgroundScheme, enableBackground, selectedNum, shouldRender, shadowRoot ] )

// Handle background changes separately to avoid unnecessary re-renders
Expand All @@ -342,10 +342,22 @@ export const usePreviewRenderer = (
if ( adjustAnimateFrameRef.current !== null ) {
cancelAnimationFrame( adjustAnimateFrameRef.current )
}
adjustAnimateFrameRef.current = requestAnimationFrame( adjustScale )
adjustAnimateFrameRef.current = requestAnimationFrame( () => adjustScale() )
}
}, [ blocks, enableBackground ] )

useEffect( () => {
if ( ! blocks.parsed || ! blocks.serialized || ! shouldRender ) {
return
}

if ( adjustAnimateFrameRef.current !== null ) {
cancelAnimationFrame( adjustAnimateFrameRef.current )
}

adjustAnimateFrameRef.current = requestAnimationFrame( () => adjustScale() )
}, [ stylesLoaded ] )

// cleanup any pending animation on unmount
useEffect( () => {
return () => {
Expand Down
53 changes: 41 additions & 12 deletions src/components/design-library-list/use-shadow-root.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { applyFilters } from '@wordpress/hooks'
export const useShadowRoot = shouldRender => {
const hostRef = useRef( null )
const [ shadowRoot, setShadowRoot ] = useState( null )
const [ stylesLoaded, setStylesLoaded ] = useState( 0 )

const { getEditorDom } = useSelect( 'stackable/editor-dom' )
const editorDom = getEditorDom()
Expand All @@ -25,6 +26,12 @@ export const useShadowRoot = shouldRender => {
useEffect( () => {
if ( shouldRender && hostRef.current ) {
const shadow = hostRef.current.shadowRoot || hostRef.current.attachShadow( { mode: 'open' } )
setStylesLoaded( 0 )

// Track existing style/link nodes in the shadow root to avoid duplicates
const existingIds = new Set(
Array.from( shadow.querySelectorAll( 'style[id],link[id]' ) ).map( n => n.id )
)

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

// Add global and theme styles
const globalStylesNode = document.createElement( 'style' )
globalStylesNode.setAttribute( 'id', 'global-styles-inline-css' )
globalStylesNode.innerHTML = wpGlobalStylesInlineCss
styleNodes.push( globalStylesNode )

const hostStyles = document.createElement( 'style' )
hostStyles.setAttribute( 'id', 'stk-design-library-styles' )
if ( ! existingIds.has( 'global-styles-inline-css' ) ) {
const globalStylesNode = document.createElement( 'style' )
globalStylesNode.setAttribute( 'id', 'global-styles-inline-css' )
globalStylesNode.innerHTML = wpGlobalStylesInlineCss
styleNodes.push( globalStylesNode )
}

if ( ! existingIds.has( 'stk-design-library-styles' ) ) {
const hostStyles = document.createElement( 'style' )
hostStyles.setAttribute( 'id', 'stk-design-library-styles' )

// Additional styles for blocks to render properly in the preview
hostStyles.innerHTML += getAdditionalStylesForPreview()
styleNodes.push( hostStyles )
}

// Additional styles for blocks to render properly in the preview
hostStyles.innerHTML += getAdditionalStylesForPreview()
styleNodes.forEach( node => {
if ( node.id && existingIds.has( node.id ) ) {
return
}

styleNodes.push( hostStyles )
if ( node.href ) {
node.onload = () => {
setStylesLoaded( prev => prev + 1 )
}
node.onerror = () => {
setStylesLoaded( prev => prev + 1 )
}
}

styleNodes.forEach( node => {
if ( node.textContent ) {
// we use :host in the shadow DOM to target the root
node.textContent = node.textContent.replace( /:root/g, ':host' )
}
shadow.appendChild( node )

if ( node.id ) {
existingIds.add( node.id )
}
} )

setShadowRoot( shadow )
}
}, [ shouldRender ] )

return { hostRef, shadowRoot }
return {
hostRef, shadowRoot, stylesLoaded,
}
}
Loading