From e7f2d01e449b105fdc8dbe6799370070573201d7 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 25 Oct 2024 07:10:27 -0500 Subject: [PATCH 1/5] Remove viewport check from useZoomOut hook (#66341) The useZoomOut hook should not be responsible for checking viewport width. It should respect the desired zoom out level passed by the condition. We should decide if we want to enter zoom out or not where we implement the useZoomOut hook (the inserter menu). --------- Co-authored-by: jeryj Co-authored-by: t-hamano Co-authored-by: kevin940726 Co-authored-by: PARTHVATALIYA Co-authored-by: getdave --- packages/block-editor/src/components/inserter/menu.js | 6 ++++-- packages/block-editor/src/hooks/use-zoom-out.js | 8 +++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index 915a36d242ba26..8dc2f64063c8e3 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -16,7 +16,7 @@ import { } from '@wordpress/element'; import { VisuallyHidden, SearchControl, Popover } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useDebouncedInput } from '@wordpress/compose'; +import { useDebouncedInput, useViewportMatch } from '@wordpress/compose'; import { useSelect } from '@wordpress/data'; /** @@ -67,6 +67,8 @@ function InserterMenu( const [ patternFilter, setPatternFilter ] = useState( 'all' ); const [ selectedMediaCategory, setSelectedMediaCategory ] = useState( null ); + const isLargeViewport = useViewportMatch( 'large' ); + function getInitialTab() { if ( __experimentalInitialTab ) { return __experimentalInitialTab; @@ -80,7 +82,7 @@ function InserterMenu( const shouldUseZoomOut = selectedTab === 'patterns' || selectedTab === 'media'; - useZoomOut( shouldUseZoomOut ); + useZoomOut( shouldUseZoomOut && isLargeViewport ); const [ destinationRootClientId, onInsertBlocks, onToggleInsertionPoint ] = useInsertionPoint( { diff --git a/packages/block-editor/src/hooks/use-zoom-out.js b/packages/block-editor/src/hooks/use-zoom-out.js index bc2d325e81d61a..bcf5d9ff882f7b 100644 --- a/packages/block-editor/src/hooks/use-zoom-out.js +++ b/packages/block-editor/src/hooks/use-zoom-out.js @@ -9,7 +9,6 @@ import { useEffect } from '@wordpress/element'; */ import { store as blockEditorStore } from '../store'; import { unlock } from '../lock-unlock'; -import { useViewportMatch } from '@wordpress/compose'; /** * A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. @@ -21,13 +20,12 @@ export function useZoomOut( zoomOut = true ) { useDispatch( blockEditorStore ) ); const { isZoomOut } = unlock( useSelect( blockEditorStore ) ); - const isWideViewport = useViewportMatch( 'large' ); useEffect( () => { const isZoomOutOnMount = isZoomOut(); return () => { - if ( isZoomOutOnMount && isWideViewport ) { + if ( isZoomOutOnMount ) { setZoomLevel( 'auto-scaled' ); } else { resetZoomLevel(); @@ -36,10 +34,10 @@ export function useZoomOut( zoomOut = true ) { }, [] ); useEffect( () => { - if ( zoomOut && isWideViewport ) { + if ( zoomOut ) { setZoomLevel( 'auto-scaled' ); } else { resetZoomLevel(); } - }, [ zoomOut, setZoomLevel, resetZoomLevel, isWideViewport ] ); + }, [ zoomOut, setZoomLevel, resetZoomLevel ] ); } From 029716e11c2d5e9a824aa26c9e7f6f30e9ee62c1 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Fri, 25 Oct 2024 16:14:32 +0400 Subject: [PATCH 2/5] Rich Text: Fix React Complier error for 'useEventListeners' (#66460) * Rich Text: Fix React Complier error for 'useEventListeners' * Try 'useInsertionEffect' hook Co-authored-by: Mamaduka Co-authored-by: tyxla --- packages/rich-text/src/component/event-listeners/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/rich-text/src/component/event-listeners/index.js b/packages/rich-text/src/component/event-listeners/index.js index a6327fe6637c37..4f69db36db06a0 100644 --- a/packages/rich-text/src/component/event-listeners/index.js +++ b/packages/rich-text/src/component/event-listeners/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useMemo, useRef } from '@wordpress/element'; +import { useMemo, useRef, useInsertionEffect } from '@wordpress/element'; import { useRefEffect } from '@wordpress/compose'; /** @@ -25,7 +25,9 @@ const allEventListeners = [ export function useEventListeners( props ) { const propsRef = useRef( props ); - propsRef.current = props; + useInsertionEffect( () => { + propsRef.current = props; + } ); const refEffects = useMemo( () => allEventListeners.map( ( refEffect ) => refEffect( propsRef ) ), [ propsRef ] From 7941d47a582ea621c4a1f782eddab1f273d15884 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Fri, 25 Oct 2024 15:15:27 +0300 Subject: [PATCH 3/5] Iterate zoom out shuffle into a more visual control (#66194) Co-authored-by: ntsekouras Co-authored-by: richtabor Co-authored-by: youknowriad Co-authored-by: jasmussen Co-authored-by: jameskoster Co-authored-by: ellatrix Co-authored-by: afercia --- .../components/block-toolbar/change-design.js | 133 ++++++++++++++++++ .../src/components/block-toolbar/index.js | 11 +- .../src/components/block-toolbar/shuffle.js | 111 --------------- .../src/components/block-toolbar/style.scss | 16 +++ 4 files changed, 152 insertions(+), 119 deletions(-) create mode 100644 packages/block-editor/src/components/block-toolbar/change-design.js delete mode 100644 packages/block-editor/src/components/block-toolbar/shuffle.js diff --git a/packages/block-editor/src/components/block-toolbar/change-design.js b/packages/block-editor/src/components/block-toolbar/change-design.js new file mode 100644 index 00000000000000..ecfeff6cb1ed3e --- /dev/null +++ b/packages/block-editor/src/components/block-toolbar/change-design.js @@ -0,0 +1,133 @@ +/** + * WordPress dependencies + */ +import { + ToolbarButton, + ToolbarGroup, + Dropdown, + __experimentalDropdownContentWrapper as DropdownContentWrapper, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { cloneBlock } from '@wordpress/blocks'; +import { useMemo } from '@wordpress/element'; +import { useAsyncList } from '@wordpress/compose'; +import { useSelect, useDispatch } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../store'; +import BlockPatternsList from '../block-patterns-list'; + +const EMPTY_ARRAY = []; +const MAX_PATTERNS_TO_SHOW = 6; +const POPOVER_PROPS = { + placement: 'bottom-start', +}; + +export default function ChangeDesign( { clientId } ) { + const { categories, currentPatternName, patterns } = useSelect( + ( select ) => { + const { + getBlockAttributes, + getBlockRootClientId, + __experimentalGetAllowedPatterns, + } = select( blockEditorStore ); + const attributes = getBlockAttributes( clientId ); + const _categories = attributes?.metadata?.categories || EMPTY_ARRAY; + const rootBlock = getBlockRootClientId( clientId ); + + // Calling `__experimentalGetAllowedPatterns` is expensive. + // Checking if the block can be changed prevents unnecessary selector calls. + // See: https://github.com/WordPress/gutenberg/pull/64736. + const _patterns = + _categories.length > 0 + ? __experimentalGetAllowedPatterns( rootBlock ) + : EMPTY_ARRAY; + return { + categories: _categories, + currentPatternName: attributes?.metadata?.patternName, + patterns: _patterns, + }; + }, + [ clientId ] + ); + const { replaceBlocks } = useDispatch( blockEditorStore ); + const sameCategoryPatternsWithSingleWrapper = useMemo( () => { + if ( categories.length === 0 || ! patterns || patterns.length === 0 ) { + return EMPTY_ARRAY; + } + return patterns + .filter( ( pattern ) => { + const isCorePattern = + pattern.source === 'core' || + ( pattern.source?.startsWith( 'pattern-directory' ) && + pattern.source !== 'pattern-directory/theme' ); + return ( + // Check if the pattern has only one top level block, + // otherwise we may switch to a pattern that doesn't have replacement suggestions. + pattern.blocks.length === 1 && + // We exclude the core patterns and pattern directory patterns that are not theme patterns. + ! isCorePattern && + // Exclude current pattern. + currentPatternName !== pattern.name && + pattern.categories?.some( ( category ) => { + return categories.includes( category ); + } ) && + // Check if the pattern is not a synced pattern. + ( pattern.syncStatus === 'unsynced' || ! pattern.id ) + ); + } ) + .slice( 0, MAX_PATTERNS_TO_SHOW ); + }, [ categories, currentPatternName, patterns ] ); + + const currentShownPatterns = useAsyncList( + sameCategoryPatternsWithSingleWrapper + ); + + if ( sameCategoryPatternsWithSingleWrapper.length < 2 ) { + return null; + } + + const onClickPattern = ( pattern ) => { + const newBlocks = ( pattern.blocks ?? [] ).map( ( block ) => { + return cloneBlock( block ); + } ); + newBlocks[ 0 ].attributes.metadata = { + ...newBlocks[ 0 ].attributes.metadata, + categories, + }; + replaceBlocks( clientId, newBlocks ); + }; + + return ( + { + return ( + + onToggle( ! isOpen ) } + aria-expanded={ isOpen } + > + { __( 'Change design' ) } + + + ); + } } + renderContent={ () => ( + + + + ) } + /> + ); +} diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 77b10149aaf226..b3bf7e94accb08 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -16,7 +16,7 @@ import { isReusableBlock, isTemplatePart, } from '@wordpress/blocks'; -import { ToolbarGroup, ToolbarButton } from '@wordpress/components'; +import { ToolbarGroup } from '@wordpress/components'; /** * Internal dependencies @@ -35,7 +35,7 @@ import { store as blockEditorStore } from '../../store'; import __unstableBlockNameContext from './block-name-context'; import NavigableToolbar from '../navigable-toolbar'; import { useHasBlockToolbar } from './use-has-block-toolbar'; -import Shuffle from './shuffle'; +import ChangeDesign from './change-design'; import { unlock } from '../../lock-unlock'; /** @@ -220,12 +220,7 @@ export function PrivateBlockToolbar( { isMultiToolbar && showGroupButtons && } { showShuffleButton && ( - - - + ) } { shouldShowVisualToolbar && showSlots && ( <> diff --git a/packages/block-editor/src/components/block-toolbar/shuffle.js b/packages/block-editor/src/components/block-toolbar/shuffle.js deleted file mode 100644 index 954c7ff22d68ce..00000000000000 --- a/packages/block-editor/src/components/block-toolbar/shuffle.js +++ /dev/null @@ -1,111 +0,0 @@ -/** - * WordPress dependencies - */ -import { shuffle } from '@wordpress/icons'; -import { ToolbarButton, ToolbarGroup } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { useMemo } from '@wordpress/element'; -import { useSelect, useDispatch } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import { store as blockEditorStore } from '../../store'; - -const EMPTY_ARRAY = []; - -function Container( props ) { - return ( - - - - ); -} - -export default function Shuffle( { clientId, as = Container } ) { - const { categories, patterns, patternName } = useSelect( - ( select ) => { - const { - getBlockAttributes, - getBlockRootClientId, - __experimentalGetAllowedPatterns, - } = select( blockEditorStore ); - const attributes = getBlockAttributes( clientId ); - const _categories = attributes?.metadata?.categories || EMPTY_ARRAY; - const _patternName = attributes?.metadata?.patternName; - const rootBlock = getBlockRootClientId( clientId ); - - // Calling `__experimentalGetAllowedPatterns` is expensive. - // Checking if the block can be shuffled prevents unnecessary selector calls. - // See: https://github.com/WordPress/gutenberg/pull/64736. - const _patterns = - _categories.length > 0 - ? __experimentalGetAllowedPatterns( rootBlock ) - : EMPTY_ARRAY; - return { - categories: _categories, - patterns: _patterns, - patternName: _patternName, - }; - }, - [ clientId ] - ); - const { replaceBlocks } = useDispatch( blockEditorStore ); - const sameCategoryPatternsWithSingleWrapper = useMemo( () => { - if ( categories.length === 0 || ! patterns || patterns.length === 0 ) { - return EMPTY_ARRAY; - } - return patterns.filter( ( pattern ) => { - const isCorePattern = - pattern.source === 'core' || - ( pattern.source?.startsWith( 'pattern-directory' ) && - pattern.source !== 'pattern-directory/theme' ); - return ( - // Check if the pattern has only one top level block, - // otherwise we may shuffle to pattern that will not allow to continue shuffling. - pattern.blocks.length === 1 && - // We exclude the core patterns and pattern directory patterns that are not theme patterns. - ! isCorePattern && - pattern.categories?.some( ( category ) => { - return categories.includes( category ); - } ) && - // Check if the pattern is not a synced pattern. - ( pattern.syncStatus === 'unsynced' || ! pattern.id ) - ); - } ); - }, [ categories, patterns ] ); - - if ( sameCategoryPatternsWithSingleWrapper.length < 2 ) { - return null; - } - - function getNextPattern() { - const numberOfPatterns = sameCategoryPatternsWithSingleWrapper.length; - const patternIndex = sameCategoryPatternsWithSingleWrapper.findIndex( - ( { name } ) => name === patternName - ); - const nextPatternIndex = - patternIndex + 1 < numberOfPatterns ? patternIndex + 1 : 0; - return sameCategoryPatternsWithSingleWrapper[ nextPatternIndex ]; - } - - const ComponentToUse = as; - return ( - { - const nextPattern = getNextPattern(); - nextPattern.blocks[ 0 ].attributes = { - ...nextPattern.blocks[ 0 ].attributes, - metadata: { - ...nextPattern.blocks[ 0 ].attributes.metadata, - categories, - }, - }; - replaceBlocks( clientId, nextPattern.blocks ); - } } - /> - ); -} diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index ae03eeed1a817c..26bf71356925e9 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -285,3 +285,19 @@ } } } + +.block-editor-block-toolbar-change-design-content-wrapper { + padding: $grid-unit-15; + width: 320px; + .block-editor-block-patterns-list { + display: grid; + grid-template-columns: 1fr 1fr; + grid-gap: $grid-unit-15; + .block-editor-block-patterns-list__list-item { + margin-bottom: 0; + } + .block-editor-inserter__media-list__list-item { + min-height: 100px; + } + } +} From 8a2480a88e0bac2685b279ea377ae18d2523022f Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:23:36 +0200 Subject: [PATCH 4/5] Site Editor: remove content styles outside canvas (#66432) --- backport-changelog/6.8/7643.md | 3 +++ lib/client-assets.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 backport-changelog/6.8/7643.md diff --git a/backport-changelog/6.8/7643.md b/backport-changelog/6.8/7643.md new file mode 100644 index 00000000000000..e3c923a487be06 --- /dev/null +++ b/backport-changelog/6.8/7643.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7643 + +* https://github.com/WordPress/gutenberg/pull/66432 diff --git a/lib/client-assets.php b/lib/client-assets.php index 9cdee4753f43b7..f6b17ffcce68be 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -410,7 +410,7 @@ function gutenberg_register_packages_styles( $styles ) { $styles, 'wp-edit-site', gutenberg_url( 'build/edit-site/style.css' ), - array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-commands', 'wp-preferences' ), + array( 'wp-components', 'wp-block-editor', 'wp-editor', 'common', 'forms', 'wp-commands', 'wp-preferences' ), $version ); $styles->add_data( 'wp-edit-site', 'rtl', 'replace' ); From 6347583a290531b9c7ae8ffde62f51368843f998 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Fri, 25 Oct 2024 16:21:18 +0300 Subject: [PATCH 5/5] Follow up of 66451 - leftovers from removed styles (#66472) Co-authored-by: ntsekouras Co-authored-by: Mamaduka --- .../src/components/document-bar/index.js | 6 +--- .../src/components/post-card-panel/index.js | 29 ++----------------- 2 files changed, 3 insertions(+), 32 deletions(-) diff --git a/packages/editor/src/components/document-bar/index.js b/packages/editor/src/components/document-bar/index.js index 904a877734cef9..3c522189a2632f 100644 --- a/packages/editor/src/components/document-bar/index.js +++ b/packages/editor/src/components/document-bar/index.js @@ -26,7 +26,7 @@ import { decodeEntities } from '@wordpress/html-entities'; /** * Internal dependencies */ -import { TEMPLATE_POST_TYPES, GLOBAL_POST_TYPES } from '../../store/constants'; +import { TEMPLATE_POST_TYPES } from '../../store/constants'; import { store as editorStore } from '../../store'; /** @typedef {import("@wordpress/components").IconType} IconType */ @@ -56,7 +56,6 @@ export default function DocumentBar( props ) { postTypeLabel, documentTitle, isNotFound, - isUnsyncedPattern, templateTitle, onNavigateToPreviousEntityRecord, } = useSelect( ( select ) => { @@ -93,7 +92,6 @@ export default function DocumentBar( props ) { _postType, _postId ), - isUnsyncedPattern: _document?.wp_pattern_sync_status === 'unsynced', templateTitle: _templateInfo.title, onNavigateToPreviousEntityRecord: getEditorSettings().onNavigateToPreviousEntityRecord, @@ -104,7 +102,6 @@ export default function DocumentBar( props ) { const isReducedMotion = useReducedMotion(); const isTemplate = TEMPLATE_POST_TYPES.includes( postType ); - const isGlobalEntity = GLOBAL_POST_TYPES.includes( postType ); const hasBackButton = !! onNavigateToPreviousEntityRecord; const entityTitle = isTemplate ? templateTitle : documentTitle; const title = props.title || entityTitle; @@ -119,7 +116,6 @@ export default function DocumentBar( props ) {
diff --git a/packages/editor/src/components/post-card-panel/index.js b/packages/editor/src/components/post-card-panel/index.js index ed13af9b55a4aa..1365659f708147 100644 --- a/packages/editor/src/components/post-card-panel/index.js +++ b/packages/editor/src/components/post-card-panel/index.js @@ -1,7 +1,3 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; /** * WordPress dependencies */ @@ -22,8 +18,6 @@ import { store as editorStore } from '../../store'; import { TEMPLATE_POST_TYPE, TEMPLATE_PART_POST_TYPE, - PATTERN_POST_TYPE, - GLOBAL_POST_TYPES, } from '../../store/constants'; import { unlock } from '../../lock-unlock'; import PostActions from '../post-actions'; @@ -33,7 +27,7 @@ export default function PostCardPanel( { postId, onActionPerformed, } ) { - const { isFrontPage, isPostsPage, title, icon, isSync } = useSelect( + const { isFrontPage, isPostsPage, title, icon } = useSelect( ( select ) => { const { __experimentalGetTemplateInfo } = select( editorStore ); const { canUser, getEditedEntityRecord } = select( coreStore ); @@ -52,25 +46,11 @@ export default function PostCardPanel( { [ TEMPLATE_POST_TYPE, TEMPLATE_PART_POST_TYPE ].includes( postType ) && __experimentalGetTemplateInfo( _record ); - let _isSync = false; - if ( GLOBAL_POST_TYPES.includes( postType ) ) { - if ( PATTERN_POST_TYPE === postType ) { - // When the post is first created, the top level wp_pattern_sync_status is not set so get meta value instead. - const currentSyncStatus = - _record?.meta?.wp_pattern_sync_status === 'unsynced' - ? 'unsynced' - : _record?.wp_pattern_sync_status; - _isSync = currentSyncStatus !== 'unsynced'; - } else { - _isSync = true; - } - } return { title: _templateInfo?.title || _record?.title, icon: unlock( select( editorStore ) ).getPostIcon( postType, { area: _record?.area, } ), - isSync: _isSync, isFrontPage: siteSettings?.page_on_front === postId, isPostsPage: siteSettings?.page_for_posts === postId, }; @@ -84,12 +64,7 @@ export default function PostCardPanel( { className="editor-post-card-panel__header" align="flex-start" > - +