diff --git a/packages/edit-site/src/components/global-styles/highlighted-colors.js b/packages/edit-site/src/components/global-styles/highlighted-colors.js new file mode 100644 index 00000000000000..35f5574f185a5a --- /dev/null +++ b/packages/edit-site/src/components/global-styles/highlighted-colors.js @@ -0,0 +1,39 @@ +/** + * WordPress dependencies + */ +import { __unstableMotion as motion } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import { useStylesPreviewColors } from './hooks'; + +export default function HighlightedColors( { + normalizedColorSwatchSize, + ratio, +} ) { + const { highlightedColors } = useStylesPreviewColors(); + const scaledSwatchSize = normalizedColorSwatchSize * ratio; + return highlightedColors.map( ( { slug, color }, index ) => ( + + ) ); +} diff --git a/packages/edit-site/src/components/global-styles/preview-colors.js b/packages/edit-site/src/components/global-styles/preview-colors.js index 88885baf300626..08a372ed83cf90 100644 --- a/packages/edit-site/src/components/global-styles/preview-colors.js +++ b/packages/edit-site/src/components/global-styles/preview-colors.js @@ -2,32 +2,17 @@ * WordPress dependencies */ import { - __unstableIframe as Iframe, - __unstableEditorStyles as EditorStyles, - privateApis as blockEditorPrivateApis, -} from '@wordpress/block-editor'; -import { - __unstableMotion as motion, __experimentalHStack as HStack, + __unstableMotion as motion, } from '@wordpress/components'; -import { - useThrottle, - useReducedMotion, - useResizeObserver, -} from '@wordpress/compose'; -import { useLayoutEffect, useState, useMemo } from '@wordpress/element'; /** * Internal dependencies */ -import { unlock } from '../../lock-unlock'; -import { useStylesPreviewColors } from './hooks'; - -const { useGlobalStyle, useGlobalStylesOutput } = unlock( - blockEditorPrivateApis -); +import HighlightedColors from './highlighted-colors'; +import PreviewIframe from './preview-iframe'; -const firstFrame = { +const firstFrameVariants = { start: { scale: 1, opacity: 1, @@ -38,178 +23,38 @@ const firstFrame = { }, }; -const normalizedWidth = 248; -const normalizedHeight = 152; - -const normalizedColorSwatchSize = 66; - -// Throttle options for useThrottle. Must be defined outside of the component, -// so that the object reference is the same on each render. -const THROTTLE_OPTIONS = { - leading: true, - trailing: true, -}; - const StylesPreviewColors = ( { label, isFocused, withHoverView } ) => { - const [ backgroundColor = 'white' ] = useGlobalStyle( 'color.background' ); - const [ gradientValue ] = useGlobalStyle( 'color.gradient' ); - const [ styles ] = useGlobalStylesOutput(); - const disableMotion = useReducedMotion(); - const [ isHovered, setIsHovered ] = useState( false ); - const [ containerResizeListener, { width } ] = useResizeObserver(); - const [ throttledWidth, setThrottledWidthState ] = useState( width ); - const [ ratioState, setRatioState ] = useState(); - - const setThrottledWidth = useThrottle( - setThrottledWidthState, - 250, - THROTTLE_OPTIONS - ); - - // Must use useLayoutEffect to avoid a flash of the iframe at the wrong - // size before the width is set. - useLayoutEffect( () => { - if ( width ) { - setThrottledWidth( width ); - } - }, [ width, setThrottledWidth ] ); - - // Must use useLayoutEffect to avoid a flash of the iframe at the wrong - // size before the width is set. - useLayoutEffect( () => { - const newRatio = throttledWidth ? throttledWidth / normalizedWidth : 1; - const ratioDiff = newRatio - ( ratioState || 0 ); - - // Only update the ratio state if the difference is big enough - // or if the ratio state is not yet set. This is to avoid an - // endless loop of updates at particular viewport heights when the - // presence of a scrollbar causes the width to change slightly. - const isRatioDiffBigEnough = Math.abs( ratioDiff ) > 0.1; - - if ( isRatioDiffBigEnough || ! ratioState ) { - setRatioState( newRatio ); - } - }, [ throttledWidth, ratioState ] ); - - // Set a fallbackRatio to use before the throttled ratio has been set. - const fallbackRatio = width ? width / normalizedWidth : 1; - /* - * Use the throttled ratio if it has been calculated, otherwise - * use the fallback ratio. The throttled ratio is used to avoid - * an endless loop of updates at particular viewport heights. - * See: https://github.com/WordPress/gutenberg/issues/55112 - */ - const ratio = ratioState ? ratioState : fallbackRatio; - - const { highlightedColors } = useStylesPreviewColors(); - - /* - * Reset leaked styles from WP common.css and remove main content layout padding and border. - * Add pointer cursor to the body to indicate the iframe is interactive, - * similar to Typography variation previews. - */ - const editorStyles = useMemo( () => { - if ( styles ) { - return [ - ...styles, - { - css: 'html{overflow:hidden}body{min-width: 0;padding: 0;border: none;cursor: pointer;}', - isGlobalStyles: true, - }, - ]; - } - - return styles; - }, [ styles ] ); - const isReady = !! width; - return ( - <> -
- { containerResizeListener } -
- { isReady && ( - + + +
) } - + ); }; diff --git a/packages/edit-site/src/components/global-styles/preview-iframe.js b/packages/edit-site/src/components/global-styles/preview-iframe.js new file mode 100644 index 00000000000000..ea4207e35a113d --- /dev/null +++ b/packages/edit-site/src/components/global-styles/preview-iframe.js @@ -0,0 +1,153 @@ +/** + * WordPress dependencies + */ +import { + __unstableIframe as Iframe, + __unstableEditorStyles as EditorStyles, + privateApis as blockEditorPrivateApis, +} from '@wordpress/block-editor'; +import { __unstableMotion as motion } from '@wordpress/components'; +import { + useThrottle, + useReducedMotion, + useResizeObserver, +} from '@wordpress/compose'; +import { useLayoutEffect, useState, useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; + +const { useGlobalStyle, useGlobalStylesOutput } = unlock( + blockEditorPrivateApis +); + +const normalizedWidth = 248; +const normalizedHeight = 152; + +// Throttle options for useThrottle. Must be defined outside of the component, +// so that the object reference is the same on each render. +const THROTTLE_OPTIONS = { + leading: true, + trailing: true, +}; + +export default function PreviewIframe( { + children, + label, + isFocused, + withHoverView, +} ) { + const [ backgroundColor = 'white' ] = useGlobalStyle( 'color.background' ); + const [ gradientValue ] = useGlobalStyle( 'color.gradient' ); + const [ styles ] = useGlobalStylesOutput(); + const disableMotion = useReducedMotion(); + const [ isHovered, setIsHovered ] = useState( false ); + const [ containerResizeListener, { width } ] = useResizeObserver(); + const [ throttledWidth, setThrottledWidthState ] = useState( width ); + const [ ratioState, setRatioState ] = useState(); + + const setThrottledWidth = useThrottle( + setThrottledWidthState, + 250, + THROTTLE_OPTIONS + ); + + // Must use useLayoutEffect to avoid a flash of the iframe at the wrong + // size before the width is set. + useLayoutEffect( () => { + if ( width ) { + setThrottledWidth( width ); + } + }, [ width, setThrottledWidth ] ); + + // Must use useLayoutEffect to avoid a flash of the iframe at the wrong + // size before the width is set. + useLayoutEffect( () => { + const newRatio = throttledWidth ? throttledWidth / normalizedWidth : 1; + const ratioDiff = newRatio - ( ratioState || 0 ); + + // Only update the ratio state if the difference is big enough + // or if the ratio state is not yet set. This is to avoid an + // endless loop of updates at particular viewport heights when the + // presence of a scrollbar causes the width to change slightly. + const isRatioDiffBigEnough = Math.abs( ratioDiff ) > 0.1; + + if ( isRatioDiffBigEnough || ! ratioState ) { + setRatioState( newRatio ); + } + }, [ throttledWidth, ratioState ] ); + + // Set a fallbackRatio to use before the throttled ratio has been set. + const fallbackRatio = width ? width / normalizedWidth : 1; + /* + * Use the throttled ratio if it has been calculated, otherwise + * use the fallback ratio. The throttled ratio is used to avoid + * an endless loop of updates at particular viewport heights. + * See: https://github.com/WordPress/gutenberg/issues/55112 + */ + const ratio = ratioState ? ratioState : fallbackRatio; + + /* + * Reset leaked styles from WP common.css and remove main content layout padding and border. + * Add pointer cursor to the body to indicate the iframe is interactive, + * similar to Typography variation previews. + */ + const editorStyles = useMemo( () => { + if ( styles ) { + return [ + ...styles, + { + css: 'html{overflow:hidden}body{min-width: 0;padding: 0;border: none;cursor: pointer;}', + isGlobalStyles: true, + }, + ]; + } + + return styles; + }, [ styles ] ); + const isReady = !! width; + + return ( + <> +
+ { containerResizeListener } +
+ { isReady && ( + + ) } + + ); +} diff --git a/packages/edit-site/src/components/global-styles/preview-styles.js b/packages/edit-site/src/components/global-styles/preview-styles.js new file mode 100644 index 00000000000000..f4566ca32d6784 --- /dev/null +++ b/packages/edit-site/src/components/global-styles/preview-styles.js @@ -0,0 +1,185 @@ +/** + * WordPress dependencies + */ +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; +import { + __experimentalHStack as HStack, + __experimentalVStack as VStack, + __unstableMotion as motion, +} from '@wordpress/components'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; +import { useStylesPreviewColors } from './hooks'; +import PreviewTypography from './preview-typography'; +import HighlightedColors from './highlighted-colors'; +import PreviewIframe from './preview-iframe'; + +const { useGlobalStyle } = unlock( blockEditorPrivateApis ); + +const firstFrameVariants = { + start: { + scale: 1, + opacity: 1, + }, + hover: { + scale: 0, + opacity: 0, + }, +}; + +const midFrameVariants = { + hover: { + opacity: 1, + }, + start: { + opacity: 0.5, + }, +}; + +const secondFrameVariants = { + hover: { + scale: 1, + opacity: 1, + }, + start: { + scale: 0, + opacity: 0, + }, +}; + +const PreviewStyles = ( { label, isFocused, withHoverView, variation } ) => { + const [ fontWeight ] = useGlobalStyle( 'typography.fontWeight' ); + const [ fontFamily = 'serif' ] = useGlobalStyle( 'typography.fontFamily' ); + const [ headingFontFamily = fontFamily ] = useGlobalStyle( + 'elements.h1.typography.fontFamily' + ); + const [ headingFontWeight = fontWeight ] = useGlobalStyle( + 'elements.h1.typography.fontWeight' + ); + const [ textColor = 'black' ] = useGlobalStyle( 'color.text' ); + const [ headingColor = textColor ] = useGlobalStyle( + 'elements.h1.color.text' + ); + + const { paletteColors } = useStylesPreviewColors(); + + return ( + + { ( { ratio, key } ) => ( + + + + + + + + + ) } + { ( { key } ) => ( + + + { paletteColors + .slice( 0, 4 ) + .map( ( { color }, index ) => ( +
+ ) ) } + + + ) } + { ( { ratio, key } ) => ( + + + { label && ( +
+ { label } +
+ ) } +
+
+ ) } + + ); +}; + +export default PreviewStyles; diff --git a/packages/edit-site/src/components/global-styles/preview.js b/packages/edit-site/src/components/global-styles/preview.js deleted file mode 100644 index eb58419ccec6bf..00000000000000 --- a/packages/edit-site/src/components/global-styles/preview.js +++ /dev/null @@ -1,319 +0,0 @@ -/** - * WordPress dependencies - */ -import { - __unstableIframe as Iframe, - __unstableEditorStyles as EditorStyles, - privateApis as blockEditorPrivateApis, -} from '@wordpress/block-editor'; -import { - __unstableMotion as motion, - __experimentalHStack as HStack, - __experimentalVStack as VStack, -} from '@wordpress/components'; -import { - useThrottle, - useReducedMotion, - useResizeObserver, -} from '@wordpress/compose'; -import { useLayoutEffect, useState, useMemo } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import { unlock } from '../../lock-unlock'; -import { useStylesPreviewColors } from './hooks'; -import PreviewTypography from './preview-typography'; - -const { useGlobalStyle, useGlobalStylesOutput } = unlock( - blockEditorPrivateApis -); - -const firstFrame = { - start: { - scale: 1, - opacity: 1, - }, - hover: { - scale: 0, - opacity: 0, - }, -}; - -const midFrame = { - hover: { - opacity: 1, - }, - start: { - opacity: 0.5, - }, -}; - -const secondFrame = { - hover: { - scale: 1, - opacity: 1, - }, - start: { - scale: 0, - opacity: 0, - }, -}; - -const normalizedWidth = 248; -const normalizedHeight = 152; - -const normalizedColorSwatchSize = 32; - -// Throttle options for useThrottle. Must be defined outside of the component, -// so that the object reference is the same on each render. -const THROTTLE_OPTIONS = { - leading: true, - trailing: true, -}; - -const StylesPreview = ( { label, isFocused, withHoverView, variation } ) => { - const [ fontWeight ] = useGlobalStyle( 'typography.fontWeight' ); - const [ fontFamily = 'serif' ] = useGlobalStyle( 'typography.fontFamily' ); - const [ headingFontFamily = fontFamily ] = useGlobalStyle( - 'elements.h1.typography.fontFamily' - ); - const [ headingFontWeight = fontWeight ] = useGlobalStyle( - 'elements.h1.typography.fontWeight' - ); - const [ textColor = 'black' ] = useGlobalStyle( 'color.text' ); - const [ headingColor = textColor ] = useGlobalStyle( - 'elements.h1.color.text' - ); - const [ backgroundColor = 'white' ] = useGlobalStyle( 'color.background' ); - const [ gradientValue ] = useGlobalStyle( 'color.gradient' ); - const [ styles ] = useGlobalStylesOutput(); - const disableMotion = useReducedMotion(); - const [ isHovered, setIsHovered ] = useState( false ); - const [ containerResizeListener, { width } ] = useResizeObserver(); - const [ throttledWidth, setThrottledWidthState ] = useState( width ); - const [ ratioState, setRatioState ] = useState(); - - const setThrottledWidth = useThrottle( - setThrottledWidthState, - 250, - THROTTLE_OPTIONS - ); - - // Must use useLayoutEffect to avoid a flash of the iframe at the wrong - // size before the width is set. - useLayoutEffect( () => { - if ( width ) { - setThrottledWidth( width ); - } - }, [ width, setThrottledWidth ] ); - - // Must use useLayoutEffect to avoid a flash of the iframe at the wrong - // size before the width is set. - useLayoutEffect( () => { - const newRatio = throttledWidth ? throttledWidth / normalizedWidth : 1; - const ratioDiff = newRatio - ( ratioState || 0 ); - - // Only update the ratio state if the difference is big enough - // or if the ratio state is not yet set. This is to avoid an - // endless loop of updates at particular viewport heights when the - // presence of a scrollbar causes the width to change slightly. - const isRatioDiffBigEnough = Math.abs( ratioDiff ) > 0.1; - - if ( isRatioDiffBigEnough || ! ratioState ) { - setRatioState( newRatio ); - } - }, [ throttledWidth, ratioState ] ); - - // Set a fallbackRatio to use before the throttled ratio has been set. - const fallbackRatio = width ? width / normalizedWidth : 1; - // Use the throttled ratio if it has been calculated, otherwise - // use the fallback ratio. The throttled ratio is used to avoid - // an endless loop of updates at particular viewport heights. - // See: https://github.com/WordPress/gutenberg/issues/55112 - const ratio = ratioState ? ratioState : fallbackRatio; - - const { paletteColors, highlightedColors } = useStylesPreviewColors(); - - // Reset leaked styles from WP common.css and remove main content layout padding and border. - const editorStyles = useMemo( () => { - if ( styles ) { - return [ - ...styles, - { - css: 'html{overflow:hidden}body{min-width: 0;padding: 0;border: none;}', - isGlobalStyles: true, - }, - ]; - } - - return styles; - }, [ styles ] ); - const isReady = !! width; - - return ( - <> -
- { containerResizeListener } -
- { isReady && ( - - ) } - - ); -}; - -export default StylesPreview; diff --git a/packages/edit-site/src/components/global-styles/screen-root.js b/packages/edit-site/src/components/global-styles/screen-root.js index 28b3642ac09b45..4146b32b57e3db 100644 --- a/packages/edit-site/src/components/global-styles/screen-root.js +++ b/packages/edit-site/src/components/global-styles/screen-root.js @@ -24,7 +24,7 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { IconWithCurrentColor } from './icon-with-current-color'; import { NavigationButtonAsItem } from './navigation-button'; import RootMenu from './root-menu'; -import StylesPreview from './preview'; +import PreviewStyles from './preview-styles'; import { unlock } from '../../lock-unlock'; const { useGlobalStyle } = unlock( blockEditorPrivateApis ); @@ -58,7 +58,7 @@ function ScreenRoot() { - + { hasVariations && ( diff --git a/packages/edit-site/src/components/global-styles/style-variations-container.js b/packages/edit-site/src/components/global-styles/style-variations-container.js index bcc0b940de4b26..69aff3e5be415a 100644 --- a/packages/edit-site/src/components/global-styles/style-variations-container.js +++ b/packages/edit-site/src/components/global-styles/style-variations-container.js @@ -10,7 +10,7 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import StylesPreview from './preview'; +import PreviewStyles from './preview-styles'; import Variation from './variations/variation'; export default function StyleVariationsContainer() { @@ -43,7 +43,7 @@ export default function StyleVariationsContainer() { { withEmptyVariation.map( ( variation, index ) => ( { ( isFocused ) => ( -