PluginProbe
Extendify / 3.0.6
Extendify v3.0.6
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / src / Agent / hooks / useFontVariationOverride.js

useFontVariationOverride.js in Extendify 3.0.6, at src/Agent/hooks/useFontVariationOverride.js

134 lines 3.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { getDynamicDuotoneMap } from '@agent/lib/svg-blocks-scanner';
2 import { replaceDuotoneSVG } from '@agent/lib/svg-helpers';
3 import apiFetch from '@wordpress/api-fetch';
4 import { parse } from '@wordpress/blocks';
5 import { useSelect } from '@wordpress/data';
6 import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
7
8 const id = 'global-styles-inline-css';
9 const path = window.location.pathname;
10 const s = new URLSearchParams(window.location.search);
11 const onEditor =
12 path.includes('/wp-admin/post.php') && s.get('action') === 'edit';
13 const { globalStylesPostID } = window.extSharedData;
14
15 export const useFontVariationOverride = ({ css }) => {
16 const frontStyles = useRef(null);
17 const duotoneCleanup = useRef(null);
18 const [theDocument, setDocument] = useState(null);
19 const [duotoneTheme, setDuotoneTheme] = useState(null);
20
21 useEffect(() => {
22 apiFetch({
23 path: `/wp/v2/global-styles/${globalStylesPostID}?context=edit`,
24 }).then((stylesResponse) => {
25 const duotone = stylesResponse?.settings?.color?.duotone?.theme;
26 setDuotoneTheme(duotone);
27 });
28 }, [css]);
29
30 useEffect(() => {
31 if (!css || onEditor) return;
32 const style = document.getElementById(id);
33 if (!style) return;
34 if (!frontStyles.current) {
35 frontStyles.current = style.innerHTML;
36 }
37 style.innerHTML = css;
38 }, [css]);
39
40 // Handle the editor
41 useEffect(() => {
42 if (!css || !theDocument || !onEditor) return;
43 const style = theDocument.getElementById(id);
44 const hasIframe = document.querySelector('iframe[name="editor-canvas"]');
45 style.innerHTML = css.replaceAll(
46 ':root',
47 // If the iframe was removed, target the editor the old way
48 hasIframe ? ':root' : '.editor-styles-wrapper',
49 );
50
51 // Since these effects should not affect the whole editor, only the text
52 if (!hasIframe) {
53 // we need to replace the individual elements with the style wrapper
54 style.innerHTML = style.innerHTML
55 .replace('body{', '.editor-styles-wrapper{')
56 // or prefix them with the editor class
57 .replace(
58 /(h[1-6](?:\s*,\s*h[1-6])*)\s*\{/g,
59 '.editor-styles-wrapper $1{',
60 );
61 }
62 }, [css, theDocument]);
63
64 useEffect(() => {
65 if (theDocument) return;
66 const timer = setTimeout(() => {
67 if (theDocument) return;
68 const frame = document.querySelector('iframe[name="editor-canvas"]');
69 const doc = frame?.contentDocument || document;
70 if (!doc || !doc.body) return;
71 // Add a tag to the body
72 const newStyle = doc.createElement('style');
73 newStyle.id = id;
74 doc.body.appendChild(newStyle);
75 setDocument(doc);
76 }, 300); // wait for iframe
77 return () => clearTimeout(timer);
78 }, [theDocument]);
79
80 const dynamicDuotone = useSelect((select) => {
81 let blocks = select('core/block-editor')?.getBlocks?.() ?? [];
82
83 const hasShowTemplateOn = blocks.find(
84 (block) => block.name === 'core/template-part',
85 );
86
87 if (hasShowTemplateOn) {
88 const { getEditedPostContent } = select('core/editor');
89 blocks = parse(getEditedPostContent(), {});
90 }
91
92 return getDynamicDuotoneMap(blocks);
93 }, []);
94
95 // Handle duotone changes
96 useEffect(() => {
97 if (!duotoneTheme) return;
98
99 // Clean up previous duotone changes
100 if (duotoneCleanup.current) {
101 duotoneCleanup.current();
102 duotoneCleanup.current = null;
103 }
104
105 // Apply new duotone changes and store cleanup
106 duotoneCleanup.current = replaceDuotoneSVG({
107 duotoneTheme,
108 dynamicDuotone,
109 });
110 }, [css, duotoneTheme, dynamicDuotone]);
111
112 const undoChange = useCallback(() => {
113 // Revert duotone changes
114 if (duotoneCleanup.current) {
115 duotoneCleanup.current();
116 duotoneCleanup.current = null;
117 }
118
119 // Revert CSS changes
120 const style = document.getElementById(id);
121 if (style && frontStyles.current) {
122 style.innerHTML = frontStyles.current;
123 }
124
125 // Remove editor CSS
126 if (!onEditor) return;
127 const iframe = document.querySelector('iframe[name="editor-canvas"]');
128 const doc = iframe?.contentDocument || document;
129 doc?.getElementById(id)?.remove();
130 }, []);
131
132 return { undoChange };
133 };
134