import { BlockPreview } from '@wordpress/block-editor'; import { rawHandler } from '@wordpress/blocks'; import { useState, useRef, useCallback, useEffect, useMemo, } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { pageNames } from '@shared/lib/pages'; import classNames from 'classnames'; import { colord } from 'colord'; import { AnimatePresence, motion } from 'framer-motion'; import { usePreviewIframe } from '@launch/hooks/usePreviewIframe'; import { lowerImageQuality } from '@launch/lib/util'; import themeJSON from '../_data/theme-processed.json'; export const SmallPreview = ({ style, onSelect, selected }) => { const previewContainer = useRef(null); const blockRef = useRef(null); const observer = useRef(null); const [ready, setReady] = useState(false); const variation = style?.variation; const theme = variation?.settings?.color?.palette?.theme; const onLoad = useCallback( (frame) => { // Run this 150 times at an interval of 100ms (15s) // This is a brute force check that the styles are there let lastRun = performance.now(); let counter = 0; const checkOnStyles = () => { if (counter >= 150) return; const now = performance.now(); if (now - lastRun < 100) return requestAnimationFrame(checkOnStyles); lastRun = now; frame?.contentDocument?.querySelector('[href*=load-styles]')?.remove(); const stylesToInject = ``; if (!frame.contentDocument?.getElementById('ext-tj')) { frame.contentDocument?.body?.insertAdjacentHTML( 'beforeend', stylesToInject, ); } counter++; requestAnimationFrame(checkOnStyles); // recursive }; checkOnStyles(); }, [style?.variation?.title], ); const { loading, ready: show } = usePreviewIframe({ container: blockRef.current, ready, onLoad, loadDelay: 2000, }); const blocks = useMemo(() => { const links = [ pageNames.about.title, pageNames.blog.title, pageNames.contact.title, ]; const code = [ style?.headerCode, style?.patterns .map(({ code }) => code) .flat() .slice(0, 3) .join('\n'), style?.footerCode, ] .filter(Boolean) .join('') .replace( // //g, `

${links.join(' | ')}

`, ) .replace( // //g, `

${links.join(' | ')}

`, ) .replace( //g, '', ); return rawHandler({ HTML: lowerImageQuality(code) }); }, [style]); useEffect(() => { if (observer.current) return; observer.current = new IntersectionObserver((entries) => { entries[0].isIntersecting && setReady(true); }); observer.current.observe(blockRef.current); return () => observer.current.disconnect(); }, []); return ( <>
{ if (['Enter', 'Space', ' '].includes(e.key)) { onSelect && onSelect({ ...style, variation }); } }} onClick={onSelect ? () => onSelect({ ...style, variation }) : () => {}}> {ready ? ( ) : null} {show || ( slug === 'primary')?.color ?? '#ccc', ) .alpha(0.25) .toRgbString(), backgroundImage: 'linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.5) 50%, rgba(255,255,255,0) 100%)', backgroundSize: '600% 600%', animation: 'extendify-loading-skeleton 10s ease-in-out infinite', }} /> )}
); };