From 98c65eaf268b86175d51cbb91c35e4111a7950ef Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:02:49 +1000 Subject: [PATCH 01/19] Drag and Drop: When dragging a mix of video, audio, and image blocks, create individual blocks as appropriate (#65144) * Drag and Drop: When dragging a mix of video, audio, and image blocks, create individual blocks as appropriate * Consolidate into the fallback transform for the File block Co-authored-by: andrewserong Co-authored-by: ramonjd Co-authored-by: kevin940726 Co-authored-by: swissspidy --- packages/block-library/src/file/transforms.js | 32 +++++++++++++++---- .../block-library/src/image/transforms.js | 23 ------------- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/packages/block-library/src/file/transforms.js b/packages/block-library/src/file/transforms.js index b925e80e595033..c381a62f783866 100644 --- a/packages/block-library/src/file/transforms.js +++ b/packages/block-library/src/file/transforms.js @@ -24,12 +24,32 @@ const transforms = { const blobURL = createBlobURL( file ); // File will be uploaded in componentDidMount() - blocks.push( - createBlock( 'core/file', { - blob: blobURL, - fileName: file.name, - } ) - ); + if ( file.type.startsWith( 'video/' ) ) { + blocks.push( + createBlock( 'core/video', { + blob: createBlobURL( file ), + } ) + ); + } else if ( file.type.startsWith( 'image/' ) ) { + blocks.push( + createBlock( 'core/image', { + blob: createBlobURL( file ), + } ) + ); + } else if ( file.type.startsWith( 'audio/' ) ) { + blocks.push( + createBlock( 'core/audio', { + blob: createBlobURL( file ), + } ) + ); + } else { + blocks.push( + createBlock( 'core/file', { + blob: blobURL, + fileName: file.name, + } ) + ); + } } ); return blocks; diff --git a/packages/block-library/src/image/transforms.js b/packages/block-library/src/image/transforms.js index 0e1dfb6ee9da44..347d2408280170 100644 --- a/packages/block-library/src/image/transforms.js +++ b/packages/block-library/src/image/transforms.js @@ -3,9 +3,6 @@ */ import { createBlobURL, isBlobURL } from '@wordpress/blob'; import { createBlock, getBlockAttributes } from '@wordpress/blocks'; -import { dispatch } from '@wordpress/data'; -import { store as noticesStore } from '@wordpress/notices'; -import { __ } from '@wordpress/i18n'; export function stripFirstImage( attributes, { shortcode } ) { const { body } = document.implementation.createHTMLDocument( '' ); @@ -138,26 +135,6 @@ const transforms = { // creating a new gallery. type: 'files', isMatch( files ) { - // The following check is intended to catch non-image files when dropped together with images. - if ( - files.some( - ( file ) => file.type.indexOf( 'image/' ) === 0 - ) && - files.some( - ( file ) => file.type.indexOf( 'image/' ) !== 0 - ) - ) { - const { createErrorNotice } = dispatch( noticesStore ); - createErrorNotice( - __( - 'If uploading to a gallery all files need to be image formats' - ), - { - id: 'gallery-transform-invalid-file', - type: 'snackbar', - } - ); - } return files.every( ( file ) => file.type.indexOf( 'image/' ) === 0 ); From da8f8743c22bd9b188a742886367b0a6a25746ed Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Wed, 11 Sep 2024 10:40:44 +0800 Subject: [PATCH 02/19] Disallow setting grid block rows/columns to zero (#65217) * Disallow setting grid block rows/columns to zero * Prevent issues with grid block column/row count by ensuring a proper minimum Co-authored-by: talldan Co-authored-by: andrewserong Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/block-editor/src/layouts/grid.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/layouts/grid.js b/packages/block-editor/src/layouts/grid.js index 7ab5c7ebbc8c3d..d1f6fdd785089b 100644 --- a/packages/block-editor/src/layouts/grid.js +++ b/packages/block-editor/src/layouts/grid.js @@ -74,7 +74,8 @@ export default { // In the experiment we want to also show column control in Auto mode, and // the minimum width control in Manual mode. const showColumnsControl = - window.__experimentalEnableGridInteractivity || layout?.columnCount; + window.__experimentalEnableGridInteractivity || + !! layout?.columnCount; const showMinWidthControl = window.__experimentalEnableGridInteractivity || ! layout?.columnCount; @@ -317,7 +318,7 @@ function GridLayoutColumnsAndRowsControl( { const defaultNewColumnCount = isManualPlacement ? 1 : undefined; const newColumnCount = - value === '' + value === '' || value === '0' ? defaultNewColumnCount : parseInt( value, 10 ); onChange( { @@ -327,7 +328,7 @@ function GridLayoutColumnsAndRowsControl( { } else { // Don't allow unsetting the column count. const newColumnCount = - value === '' + value === '' || value === '0' ? 1 : parseInt( value, 10 ); onChange( { @@ -337,7 +338,7 @@ function GridLayoutColumnsAndRowsControl( { } } } value={ columnCount } - min={ 0 } + min={ 1 } label={ __( 'Columns' ) } hideLabelFromVision={ ! window.__experimentalEnableGridInteractivity || @@ -355,7 +356,7 @@ function GridLayoutColumnsAndRowsControl( { onChange={ ( value ) => { // Don't allow unsetting the row count. const newRowCount = - value === '' + value === '' || value === '0' ? 1 : parseInt( value, 10 ); onChange( { @@ -364,21 +365,24 @@ function GridLayoutColumnsAndRowsControl( { } ); } } value={ rowCount } - min={ 0 } + min={ 1 } label={ __( 'Rows' ) } /> ) : ( onChange( { ...layout, - columnCount: value, + columnCount: + value === '' || value === '0' + ? 1 + : value, } ) } - min={ 0 } + min={ 1 } max={ 16 } withInputField={ false } label={ __( 'Columns' ) } From ec58c51108f03e4a03046d763d4c830347da91bf Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Wed, 11 Sep 2024 08:18:32 +0530 Subject: [PATCH 03/19] Image: Adds the block controls for uploading image. (#64320) * feat: Adds the block controls for uploading image. * feat: Adds the size based placeholder logic. * fix: The layout design for small images and adds grid support. * refactor: Remove resize observer and add lockURLControls support. * refactor: Make use of the existing MediaReplaceFlow component. * fix: The mediaPlaceholder location after merge. * fix: The initial flash in small size. * feat: Removes the redundant css and redefine the placeholder logic. * fix: Adressed the PR feedbacks. * fix: Removes the effective width logic and moves observer inside of placeholder. * fix: The e2e test failures * Update packages/block-library/src/image/edit.js Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> --------- Co-authored-by: vipul0425 Co-authored-by: jasmussen Co-authored-by: t-hamano Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo Co-authored-by: tyxla Co-authored-by: richtabor Co-authored-by: annezazu Co-authored-by: fabiankaegy --- packages/block-library/src/image/edit.js | 31 ++++++++++----- packages/block-library/src/image/editor.scss | 40 +------------------ packages/block-library/src/image/image.js | 42 ++++++++++++-------- 3 files changed, 48 insertions(+), 65 deletions(-) diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index f9aed8d93f95a0..660d99bc748ab0 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -12,8 +12,8 @@ import { Placeholder } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { BlockIcon, - MediaPlaceholder, useBlockProps, + MediaPlaceholder, store as blockEditorStore, __experimentalUseBorderProps as useBorderProps, __experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles, @@ -109,12 +109,18 @@ export function ImageEdit( { align, metadata, } = attributes; + const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob ); const figureRef = useRef(); const [ contentResizeListener, { width: containerWidth } ] = useResizeObserver(); + const [ placeholderResizeListener, { width: placeholderWidth } ] = + useResizeObserver(); + + const isSmallContainer = placeholderWidth && placeholderWidth < 160; + const altRef = useRef(); useEffect( () => { altRef.current = alt; @@ -387,11 +393,15 @@ export function ImageEdit( { [ borderProps.className ]: !! borderProps.className && ! isSingleSelected, } ) } - withIllustration - icon={ lockUrlControls ? pluginsIcon : icon } - label={ __( 'Image' ) } + icon={ + ! isSmallContainer && + ( lockUrlControls ? pluginsIcon : icon ) + } + withIllustration={ ! isSingleSelected || isSmallContainer } + label={ ! isSmallContainer && __( 'Image' ) } instructions={ ! lockUrlControls && + ! isSmallContainer && __( 'Upload or drag an image file here, or pick one from your library.' ) @@ -408,13 +418,12 @@ export function ImageEdit( { ...shadowProps.style, } } > - { lockUrlControls ? ( - - { lockUrlControlsMessage } - - ) : ( - content - ) } + { lockUrlControls && + ! isSmallContainer && + lockUrlControlsMessage } + + { ! lockUrlControls && ! isSmallContainer && content } + { placeholderResizeListener } ); }; diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index 636741c7d9ddbb..d143e6604d1e73 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -1,44 +1,8 @@ // Provide special styling for the placeholder. // @todo this particular minimal style of placeholder could be componentized further. .wp-block-image.wp-block-image { - - // Show Placeholder style on-select. - &.is-selected .block-editor-media-placeholder { - // Block UI appearance. - color: $gray-900; - background-color: $white; - box-shadow: inset 0 0 0 $border-width $gray-900; - border: none; - - // Disable any duotone filter applied in the selected state. - filter: none !important; - - > svg { - opacity: 0; - } - - .components-placeholder__illustration { - display: none; - } - - &::before { - opacity: 0; - } - } - .block-bindings-media-placeholder-message { - opacity: 0; - } - &.is-selected .block-bindings-media-placeholder-message { - opacity: 1; - } - - // Remove the transition while we still have a legacy placeholder style. - // Otherwise the content jumps between the 1px placeholder border, and any inherited custom - // parent border that may get applied when you deselect. - .components-placeholder__label, - .components-placeholder__instructions, - .components-button { - transition: none; + .block-editor-media-placeholder.is-small { + min-height: 60px; } } diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 2de316f78ba5d8..f79f078b1eef82 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -556,6 +556,24 @@ export default function Image( { const showBlockControls = showUrlInput || allowCrop || showCoverControls; + const mediaReplaceFlow = isSingleSelected && + ! isEditingImage && + ! lockUrlControls && ( + + onSelectImage( undefined ) } + /> + + ); + const controls = ( <> { showBlockControls && ( @@ -592,20 +610,6 @@ export default function Image( { ) } ) } - { isSingleSelected && ! isEditingImage && ! lockUrlControls && ( - - onSelectImage( undefined ) } - /> - - ) } { isSingleSelected && externalBlob && ( @@ -1029,12 +1033,18 @@ export default function Image( { } if ( ! url && ! temporaryURL ) { - // Add all controls if the image attributes are connected. - return metadata?.bindings ? controls : sizeControls; + return ( + <> + { mediaReplaceFlow } + { /* Add all controls if the image attributes are connected. */ } + { metadata?.bindings ? controls : sizeControls } + + ); } return ( <> + { mediaReplaceFlow } { controls } { img } From 6a60081909d1dfbbb608e7b069dec3eb6881e37e Mon Sep 17 00:00:00 2001 From: Kai Hao Date: Wed, 11 Sep 2024 10:51:28 +0800 Subject: [PATCH 04/19] Fix resizing to max width in classic themes (#64819) co-authored-by: kevin940726 Co-authored-by: aaronrobertshaw Co-authored-by: andrewserong Co-authored-by: ramonjd * Fix resizing to max width in classic themes * Fix padding and max-width * Reverse the condition * Try ignoring if layout doesn't exist --- packages/block-library/src/image/edit.js | 24 +++++++++----- packages/block-library/src/image/editor.scss | 5 +++ packages/block-library/src/image/image.js | 9 +++--- .../src/image/use-max-width-observer.js | 32 +++++++++++++++++++ 4 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 packages/block-library/src/image/use-max-width-observer.js diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 660d99bc748ab0..16ec296554d743 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -23,7 +23,6 @@ import { useEffect, useRef, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { image as icon, plugins as pluginsIcon } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; -import { useResizeObserver } from '@wordpress/compose'; /** * Internal dependencies @@ -32,6 +31,7 @@ import { unlock } from '../lock-unlock'; import { useUploadMediaFromBlobURL } from '../utils/hooks'; import Image from './image'; import { isValidFileType } from './utils'; +import { useMaxWidthObserver } from './use-max-width-observer'; /** * Module constants @@ -111,10 +111,15 @@ export function ImageEdit( { } = attributes; const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob ); - const figureRef = useRef(); - const [ contentResizeListener, { width: containerWidth } ] = - useResizeObserver(); + const containerRef = useRef(); + // Only observe the max width from the parent container when the parent layout is not flex nor grid. + // This won't work for them because the container width changes with the image. + // TODO: Find a way to observe the container width for flex and grid layouts. + const isMaxWidthContainerWidth = + ! parentLayout || + ( parentLayout.type !== 'flex' && parentLayout.type !== 'grid' ); + const [ maxWidthObserver, maxContentWidth ] = useMaxWidthObserver(); const [ placeholderResizeListener, { width: placeholderWidth } ] = useResizeObserver(); @@ -166,7 +171,7 @@ export function ImageEdit( { } function onSelectImagesList( images ) { - const win = figureRef.current?.ownerDocument.defaultView; + const win = containerRef.current?.ownerDocument.defaultView; if ( images.every( ( file ) => file instanceof win.File ) ) { /** @type {File[]} */ @@ -354,7 +359,10 @@ export function ImageEdit( { Object.keys( borderProps.style ).length > 0 ), } ); - const blockProps = useBlockProps( { ref: figureRef, className: classes } ); + const blockProps = useBlockProps( { + ref: containerRef, + className: classes, + } ); // Much of this description is duplicated from MediaPlaceholder. const { lockUrlControls = false, lockUrlControlsMessage } = useSelect( @@ -445,7 +453,7 @@ export function ImageEdit( { clientId={ clientId } blockEditingMode={ blockEditingMode } parentLayoutType={ parentLayout?.type } - containerWidth={ containerWidth } + maxContentWidth={ maxContentWidth } /> } @@ -464,7 +472,7 @@ export function ImageEdit( { { // The listener cannot be placed as the first element as it will break the in-between inserter. // See https://github.com/WordPress/gutenberg/blob/71134165868298fc15e22896d0c28b41b3755ff7/packages/block-editor/src/components/block-list/use-in-between-inserter.js#L120 - contentResizeListener + isSingleSelected && isMaxWidthContainerWidth && maxWidthObserver } ); diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index d143e6604d1e73..34f65d690d3d74 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -113,6 +113,11 @@ figure.wp-block-image:not(.wp-block) { text-align: center; } +// Relatively position the alignment container to support the content resizer. +.wp-block[data-align]:has(> .wp-block-image) { + position: relative; +} + .wp-block-image__crop-area { position: relative; max-width: 100%; diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index f79f078b1eef82..60d83f89129070 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -108,7 +108,7 @@ export default function Image( { clientId, blockEditingMode, parentLayoutType, - containerWidth, + maxContentWidth, } ) { const { url = '', @@ -938,7 +938,7 @@ export default function Image( { // @todo It would be good to revisit this once a content-width variable // becomes available. const maxWidthBuffer = maxWidth * 2.5; - const maxContentWidth = containerWidth || maxWidthBuffer; + const maxResizeWidth = maxContentWidth || maxWidthBuffer; let showRightHandle = false; let showLeftHandle = false; @@ -984,9 +984,9 @@ export default function Image( { } } showHandle={ isSingleSelected } minWidth={ minWidth } - maxWidth={ maxContentWidth } + maxWidth={ maxResizeWidth } minHeight={ minHeight } - maxHeight={ maxContentWidth / ratio } + maxHeight={ maxResizeWidth / ratio } lockAspectRatio={ ratio } enable={ { top: false, @@ -1000,6 +1000,7 @@ export default function Image( { // Clear hardcoded width if the resized width is close to the max-content width. if ( + maxContentWidth && // Only do this if the image is bigger than the container to prevent it from being squished. // TODO: Remove this check if the image support setting 100% width. naturalWidth >= maxContentWidth && diff --git a/packages/block-library/src/image/use-max-width-observer.js b/packages/block-library/src/image/use-max-width-observer.js new file mode 100644 index 00000000000000..684392537fac7a --- /dev/null +++ b/packages/block-library/src/image/use-max-width-observer.js @@ -0,0 +1,32 @@ +/** + * WordPress dependencies + */ +import { useRef } from '@wordpress/element'; +import { useResizeObserver } from '@wordpress/compose'; + +function useMaxWidthObserver() { + const [ contentResizeListener, { width } ] = useResizeObserver(); + const observerRef = useRef(); + + const maxWidthObserver = ( + + ); + + return [ maxWidthObserver, width ]; +} + +export { useMaxWidthObserver }; From 2f939a7f9047ed9b632ac4fb0d593d0cf9588ce9 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:44:22 +0900 Subject: [PATCH 05/19] Fix image block crash (#65222) Co-authored-by: t-hamano Co-authored-by: kevin940726 Co-authored-by: ramonjd --- packages/block-library/src/image/edit.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 16ec296554d743..d44dc73abfd855 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -23,6 +23,7 @@ import { useEffect, useRef, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { image as icon, plugins as pluginsIcon } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; +import { useResizeObserver } from '@wordpress/compose'; /** * Internal dependencies From 20ca80f48c1b022305164cdbb16baf1329d785f4 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Wed, 11 Sep 2024 10:24:18 +0200 Subject: [PATCH 06/19] DatePicker: better hover/focus styles (#65117) * DatePicker: better hover/focus styles * CHANGELOG * Use after pseudo-element to avoid conflict with calendar event dot * Make event dots compatible with high contrast mode * Apply box sizing utility * Use themed colors * Use translate to prevent event dot from jumping --- Co-authored-by: ciampo Co-authored-by: tyxla Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: t-hamano --- packages/components/CHANGELOG.md | 4 ++ .../components/src/date-time/date/styles.ts | 42 ++++++++++++++----- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8c656f4adb48bb..8a9151e3fdc05e 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -14,6 +14,10 @@ - `Modal`: Decrease close button size and remove horizontal offset ([#65131](https://github.com/WordPress/gutenberg/pull/65131)). +### Bug Fixes + +- `DatePicker`: better hover/focus styles ([#65117](https://github.com/WordPress/gutenberg/pull/65117)). + ### Internal - `Composite`: Remove from private APIs ([#63569](https://github.com/WordPress/gutenberg/pull/63569)). diff --git a/packages/components/src/date-time/date/styles.ts b/packages/components/src/date-time/date/styles.ts index bffc8ae35d2a64..84405854827ec9 100644 --- a/packages/components/src/date-time/date/styles.ts +++ b/packages/components/src/date-time/date/styles.ts @@ -7,13 +7,13 @@ import styled from '@emotion/styled'; * Internal dependencies */ import Button from '../../button'; -import { COLORS, CONFIG } from '../../utils'; +import { boxSizingReset, COLORS, CONFIG } from '../../utils'; import { HStack } from '../../h-stack'; import { Heading } from '../../heading'; import { space } from '../../utils/space'; export const Wrapper = styled.div` - box-sizing: border-box; + ${ boxSizingReset } `; export const Navigator = styled( HStack )` @@ -38,7 +38,7 @@ export const Calendar = styled.div` `; export const DayOfWeek = styled.div` - color: ${ COLORS.gray[ 700 ] }; + color: ${ COLORS.theme.gray[ 700 ] }; font-size: ${ CONFIG.fontSize }; line-height: ${ CONFIG.fontLineHeightBase }; @@ -90,15 +90,34 @@ export const DayButton = styled( Button, { ${ ( props ) => props.isSelected && ` - background: ${ COLORS.theme.accent }; - color: ${ COLORS.white }; + background: ${ COLORS.theme.accent }; + + &, + &:hover:not(:disabled, [aria-disabled=true]) { + color: ${ COLORS.theme.accentInverted }; + } + + &:focus:not(:disabled), + &:focus:not(:disabled) { + border: ${ CONFIG.borderWidthFocus } solid currentColor; + } + + /* Highlight the selected day for high-contrast mode */ + &::after { + content: ''; + position: absolute; + pointer-events: none; + inset: 0; + border-radius: inherit; + border: 1px solid transparent; + } ` } ${ ( props ) => ! props.isSelected && props.isToday && ` - background: ${ COLORS.gray[ 200 ] }; + background: ${ COLORS.theme.gray[ 200 ] }; ` } } @@ -106,15 +125,16 @@ export const DayButton = styled( Button, { props.hasEvents && ` ::before { - background: ${ props.isSelected ? COLORS.white : COLORS.theme.accent }; + border: 2px solid ${ + props.isSelected + ? COLORS.theme.accentInverted + : COLORS.theme.accent + }; border-radius: ${ CONFIG.radiusRound }; - bottom: 2px; content: " "; - height: 4px; left: 50%; - margin-left: -2px; position: absolute; - width: 4px; + transform: translate(-50%, 9px); } ` } `; From 5daa582f7fa20f28daabf546e1686c016432b04f Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Wed, 11 Sep 2024 11:05:07 +0200 Subject: [PATCH 07/19] Navigator Screen: warn if path doesn't follow a URL-like scheme (#65231) * Navigator Screen: warn if path doesn't follow the expected scheme * Add test * CHANGELOG --- Co-authored-by: ciampo Co-authored-by: Mamaduka Co-authored-by: ramonjd --- packages/components/CHANGELOG.md | 1 + .../src/navigator/navigator-screen/component.tsx | 7 +++++++ packages/components/src/navigator/test/index.tsx | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 8a9151e3fdc05e..55c85565f522aa 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -12,6 +12,7 @@ ### Enhancements +- `Navigator`: warn if a screen's `path` doesn't follow a URL-like scheme ([#65231](https://github.com/WordPress/gutenberg/pull/65231)). - `Modal`: Decrease close button size and remove horizontal offset ([#65131](https://github.com/WordPress/gutenberg/pull/65131)). ### Bug Fixes diff --git a/packages/components/src/navigator/navigator-screen/component.tsx b/packages/components/src/navigator/navigator-screen/component.tsx index be5c4bfaf41ec4..5882f271d4518f 100644 --- a/packages/components/src/navigator/navigator-screen/component.tsx +++ b/packages/components/src/navigator/navigator-screen/component.tsx @@ -17,6 +17,7 @@ import { import { useMergeRefs } from '@wordpress/compose'; import { isRTL as isRTLFn } from '@wordpress/i18n'; import { escapeAttribute } from '@wordpress/escape-html'; +import warning from '@wordpress/warning'; /** * Internal dependencies @@ -33,6 +34,12 @@ function UnconnectedNavigatorScreen( props: WordPressComponentProps< NavigatorScreenProps, 'div', false >, forwardedRef: ForwardedRef< any > ) { + if ( ! /^\//.test( props.path ) ) { + warning( + 'wp.components.NavigatorScreen: the `path` should follow a URL-like scheme; it should start with and be separated by the `/` character.' + ); + } + const screenId = useId(); const { children, className, path, ...otherProps } = useContextSystem( props, diff --git a/packages/components/src/navigator/test/index.tsx b/packages/components/src/navigator/test/index.tsx index 9b9b257ea09681..820942a22644ba 100644 --- a/packages/components/src/navigator/test/index.tsx +++ b/packages/components/src/navigator/test/index.tsx @@ -642,6 +642,14 @@ describe( 'Navigator', () => { ).toHaveAttribute( 'id', INVALID_HTML_ATTRIBUTE.escaped ); } ); + it( 'should warn if the `path` prop does not follow the required format', () => { + render( Test ); + + expect( console ).toHaveWarnedWith( + 'wp.components.NavigatorScreen: the `path` should follow a URL-like scheme; it should start with and be separated by the `/` character.' + ); + } ); + it( 'should match correctly paths with named arguments', async () => { const user = userEvent.setup(); From 3d5dacd3ed50fb2cba64cf62781a8859716e3738 Mon Sep 17 00:00:00 2001 From: Mario Santos <34552881+SantosGuillamot@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:45:50 +0200 Subject: [PATCH 08/19] Populate block context with inherited post type from template slug (#65062) * Inherit post type from template slug * Move map outside of `useSelect` Co-authored-by: SantosGuillamot Co-authored-by: Mamaduka Co-authored-by: artemiomorales Co-authored-by: cbravobernal --- .../editor/src/components/provider/index.js | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index aaf25621d3324b..11b1478d58434a 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -4,7 +4,11 @@ import { useEffect, useLayoutEffect, useMemo } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; -import { EntityProvider, useEntityBlockEditor } from '@wordpress/core-data'; +import { + EntityProvider, + useEntityBlockEditor, + store as coreStore, +} from '@wordpress/core-data'; import { BlockEditorProvider, BlockContextProvider, @@ -48,7 +52,6 @@ const noop = () => {}; */ const NON_CONTEXTUAL_POST_TYPES = [ 'wp_block', - 'wp_template', 'wp_navigation', 'wp_template_part', ]; @@ -161,31 +164,59 @@ export const ExperimentalEditorProvider = withRegistryProvider( BlockEditorProviderComponent = ExperimentalBlockEditorProvider, __unstableTemplate: template, } ) => { - const { editorSettings, selection, isReady, mode } = useSelect( - ( select ) => { + const { editorSettings, selection, isReady, mode, postTypes } = + useSelect( ( select ) => { const { getEditorSettings, getEditorSelection, getRenderingMode, __unstableIsEditorReady, } = select( editorStore ); + const { getPostTypes } = select( coreStore ); + return { editorSettings: getEditorSettings(), isReady: __unstableIsEditorReady(), mode: getRenderingMode(), selection: getEditorSelection(), + postTypes: getPostTypes( { per_page: -1 } ), }; - }, - [] - ); + }, [] ); const shouldRenderTemplate = !! template && mode !== 'post-only'; const rootLevelPost = shouldRenderTemplate ? template : post; const defaultBlockContext = useMemo( () => { - const postContext = + const postContext = {}; + // If it is a template, try to inherit the post type from the slug. + if ( post.type === 'wp_template' ) { + if ( ! post.is_custom ) { + const [ kind ] = post.slug.split( '-' ); + switch ( kind ) { + case 'page': + postContext.postType = 'page'; + break; + case 'single': + // Infer the post type from the slug. + const postTypesSlugs = + postTypes?.map( ( entity ) => entity.slug ) || + []; + const match = post.slug.match( + `^single-(${ postTypesSlugs.join( + '|' + ) })(?:-.+)?$` + ); + if ( match ) { + postContext.postType = match[ 1 ]; + } + break; + } + } + } else if ( ! NON_CONTEXTUAL_POST_TYPES.includes( rootLevelPost.type ) || shouldRenderTemplate - ? { postId: post.id, postType: post.type } - : {}; + ) { + postContext.postId = post.id; + postContext.postType = post.type; + } return { ...postContext, @@ -200,6 +231,7 @@ export const ExperimentalEditorProvider = withRegistryProvider( post.type, rootLevelPost.type, rootLevelPost.slug, + postTypes, ] ); const { id, type } = rootLevelPost; const blockEditorSettings = useBlockEditorSettings( From b2766478255b83b9a44be72bceaa843734778be2 Mon Sep 17 00:00:00 2001 From: Akshat Kakkad <87222220+AKSHAT2802@users.noreply.github.com> Date: Wed, 11 Sep 2024 15:48:58 +0530 Subject: [PATCH 09/19] Remove Warning and add notice for Navigation (#63921) Co-authored-by: AKSHAT2802 Co-authored-by: Mamaduka Co-authored-by: afercia --- .../edit/deleted-navigation-warning.js | 42 ++++++++++--------- .../edit/menu-inspector-controls.js | 4 +- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/packages/block-library/src/navigation/edit/deleted-navigation-warning.js b/packages/block-library/src/navigation/edit/deleted-navigation-warning.js index b0521f16cfb5d5..22d1e339c5c004 100644 --- a/packages/block-library/src/navigation/edit/deleted-navigation-warning.js +++ b/packages/block-library/src/navigation/edit/deleted-navigation-warning.js @@ -2,28 +2,32 @@ * WordPress dependencies */ import { Warning } from '@wordpress/block-editor'; -import { Button } from '@wordpress/components'; +import { Button, Notice } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { createInterpolateElement } from '@wordpress/element'; -function DeletedNavigationWarning( { onCreateNew } ) { - return ( - - { createInterpolateElement( - __( - 'Navigation Menu has been deleted or is unavailable. ' - ), - { - button: ( - ' + ), + { + button: ( +