| 1 |
import { refreshBlockHighlight } from '@agent/lib/block-highlight'; |
| 2 |
import { isInEditor } from '@agent/lib/util'; |
| 3 |
import { useCallback, useEffect, useRef, useState } from '@wordpress/element'; |
| 4 |
|
| 5 |
const styleId = 'block-style-variation-styles-inline-css'; |
| 6 |
const editorIframeSelector = 'iframe[name="editor-canvas"]'; |
| 7 |
const editorStylesWrapper = '.editor-styles-wrapper'; |
| 8 |
|
| 9 |
const getEditorDocument = () => { |
| 10 |
const iframe = document.querySelector(editorIframeSelector); |
| 11 |
return iframe?.contentDocument || document; |
| 12 |
}; |
| 13 |
|
| 14 |
// update the CSS so that it won't affect the switcher preview area |
| 15 |
const transformVibeCSS = (css, slug) => css.replaceAll(slug, 'natural-1'); |
| 16 |
|
| 17 |
export const useSiteVibesOverride = ({ css, slug }) => { |
| 18 |
const blockStyles = useRef(null); |
| 19 |
const [theDocument, setDocument] = useState(null); |
| 20 |
const onEditor = isInEditor(); |
| 21 |
|
| 22 |
useEffect(() => { |
| 23 |
if (!css || onEditor || !slug) return; |
| 24 |
const style = document.getElementById(styleId); |
| 25 |
if (!style) return; |
| 26 |
if (!blockStyles.current) { |
| 27 |
blockStyles.current = style.innerHTML; |
| 28 |
} |
| 29 |
style.innerHTML = transformVibeCSS(css, slug); |
| 30 |
refreshBlockHighlight(); |
| 31 |
}, [css, slug, onEditor]); |
| 32 |
|
| 33 |
useEffect(() => { |
| 34 |
if (!css || !theDocument || !onEditor) return; |
| 35 |
const style = theDocument.getElementById(styleId); |
| 36 |
const hasIframe = document.querySelector(editorIframeSelector); |
| 37 |
|
| 38 |
let modifiedCss = css |
| 39 |
.replaceAll(':root', hasIframe ? ':root' : editorStylesWrapper) |
| 40 |
.replaceAll(slug, 'natural-1') |
| 41 |
.replace( |
| 42 |
/:where\(([^)]+)\)/g, |
| 43 |
':where($1):not(.ext-vibe-container, .ext-vibe-container *)', |
| 44 |
); |
| 45 |
|
| 46 |
if (!hasIframe) { |
| 47 |
modifiedCss = modifiedCss |
| 48 |
.replace('body{', `${editorStylesWrapper}{`) |
| 49 |
.replace( |
| 50 |
/(h[1-6](?:\s*,\s*h[1-6])*)\s*\{/g, |
| 51 |
`${editorStylesWrapper} $1{`, |
| 52 |
); |
| 53 |
} |
| 54 |
|
| 55 |
style.innerHTML = modifiedCss; |
| 56 |
}, [css, slug, theDocument, onEditor]); |
| 57 |
|
| 58 |
useEffect(() => { |
| 59 |
if (theDocument) return; |
| 60 |
const timer = setTimeout(() => { |
| 61 |
if (theDocument) return; |
| 62 |
const doc = getEditorDocument(); |
| 63 |
if (!doc || !doc.body) return; |
| 64 |
const newStyle = doc.createElement('style'); |
| 65 |
newStyle.id = styleId; |
| 66 |
doc.body.appendChild(newStyle); |
| 67 |
setDocument(doc); |
| 68 |
}, 300); |
| 69 |
return () => clearTimeout(timer); |
| 70 |
}, [theDocument]); |
| 71 |
|
| 72 |
const undoChange = useCallback(() => { |
| 73 |
const style = document.getElementById(styleId); |
| 74 |
if (style && blockStyles.current) { |
| 75 |
style.innerHTML = blockStyles.current; |
| 76 |
} |
| 77 |
|
| 78 |
if (!onEditor) return; |
| 79 |
const doc = getEditorDocument(); |
| 80 |
doc?.getElementById(styleId)?.remove(); |
| 81 |
}, [onEditor]); |
| 82 |
|
| 83 |
return { undoChange }; |
| 84 |
}; |
| 85 |
|