import blockStyleVariations from '@launch/_data/block-style-variations.json'; import themeJSON from '@launch/_data/theme-processed.json'; import { usePreviewIframe } from '@launch/hooks/usePreviewIframe'; import { getFontOverrides } from '@launch/lib/preview-helpers'; import { hexTomatrixValues, lowerImageQuality } from '@launch/lib/util'; import { pageNames } from '@shared/lib/pages'; import { BlockPreview } from '@wordpress/block-editor'; import { rawHandler } from '@wordpress/blocks'; import { Spinner } from '@wordpress/components'; import { forwardRef, useCallback, useLayoutEffect, useMemo, useRef, useState, } from '@wordpress/element'; import classNames from 'classnames'; import { AnimatePresence, motion } from 'framer-motion'; export const PagePreview = forwardRef( ({ style, siteTitle, loading, showNav = true }, ref) => { const previewContainer = useRef(null); const blockRef = useRef(null); const [ready, setReady] = useState(false); const variation = style?.variation; const theme = variation?.settings?.color?.palette?.theme; const vibe = useMemo( () => style?.siteStyle?.vibe, [style?.siteStyle?.vibe], ); const blockVariationCSS = useMemo(() => { if (vibe && blockStyleVariations[vibe]) { return blockStyleVariations[vibe]; } return blockStyleVariations['natural-1'] || ''; }, [vibe]); const onLoad = useCallback( (frame) => { frame.contentDocument?.getElementById('ext-tj')?.remove(); // 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 variationTitle = variation?.slug ?.split('-') .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(' '); const variationStyles = themeJSON[variationTitle]; const { customFontLinks, fontOverrides } = getFontOverrides(variation); const primaryColor = theme?.find( ({ slug }) => slug === 'primary', )?.color; const [r, g, b] = hexTomatrixValues(primaryColor); const checkOnStyles = () => { if (counter >= 150) return; const now = performance.now(); if (now - lastRun < 100) return requestAnimationFrame(checkOnStyles); lastRun = now; const content = frame?.contentDocument; if (content) { content.querySelector('[href*=load-styles]')?.remove(); const siteTitleElement = content.querySelectorAll('[href*=site-title]'); siteTitleElement?.forEach((element) => { element.textContent = siteTitle; }); } // Add custom font links if not already present if ( customFontLinks && !frame.contentDocument?.querySelector('[id^="ext-custom-font"]') ) { frame.contentDocument?.head?.insertAdjacentHTML( 'beforeend', customFontLinks, ); } if (!frame.contentDocument?.getElementById('ext-tj')) { frame.contentDocument?.body?.insertAdjacentHTML( 'beforeend', ``, ); } // Look for any frames inside the iframe, like the html block const innerFrames = frame.contentDocument?.querySelectorAll('iframe'); innerFrames?.forEach((inner) => { inner?.contentDocument ?.querySelector('[href*=load-styles]') ?.remove(); inner?.contentDocument ?.querySelector('body') ?.classList.add('editor-styles-wrapper'); // Add custom font links to inner frames if not already present if ( customFontLinks && !inner.contentDocument?.querySelector('[id^="ext-custom-font"]') ) { inner.contentDocument?.head?.insertAdjacentHTML( 'beforeend', customFontLinks, ); } if (inner && !inner.contentDocument?.getElementById('ext-tj')) { inner.contentDocument?.body?.insertAdjacentHTML( 'beforeend', ``, ); } }); counter++; requestAnimationFrame(checkOnStyles); // recursive }; checkOnStyles(); }, [variation, theme, siteTitle, blockVariationCSS], ); const { ready: showPreview } = usePreviewIframe({ container: ref.current, ready, onLoad, loadDelay: 400, }); const blocks = useMemo(() => { const links = [ pageNames.about.title, pageNames.blog.title, pageNames.contact.title, ]; const code = [ style?.headerCode, style?.patterns?.flatMap(({ code }) => code).join(''), style?.footerCode, ] .filter(Boolean) .join('') .replace( // Replace natural-1 with dynamic vibe value /natural-1/g, vibe || 'natural-1', ) .replace( // //g, showNav ? `

${links.map((link) => `${link}`).join('')}

` : '', ) .replace( // //g, showNav ? `

${links.map((link) => `${link}`).join('')}

` : '', ) .replace( //gis, // dont replace if showNav is true (match) => (showNav ? match : ''), ) .replace( //g, '', ); return rawHandler({ HTML: lowerImageQuality(code) }); }, [style?.headerCode, style?.patterns, style?.footerCode, vibe, showNav]); useLayoutEffect(() => { setReady(false); const timer = setTimeout(() => setReady(true), 0); return () => clearTimeout(timer); }, [blocks]); const isLoading = !showPreview && loading; return ( <> {(isLoading || !showPreview) && (
)}
); }, );