diff --git a/backport-changelog/6.7/6668.md b/backport-changelog/6.7/6668.md
new file mode 100644
index 0000000000000..7653dd8d8294e
--- /dev/null
+++ b/backport-changelog/6.7/6668.md
@@ -0,0 +1,3 @@
+https://github.com/WordPress/wordpress-develop/pull/6668
+
+* https://github.com/WordPress/gutenberg/pull/62092
diff --git a/backport-changelog/6.7/6910.md b/backport-changelog/6.7/6910.md
index 8e6be0dc8e7a5..962f54be672ad 100644
--- a/backport-changelog/6.7/6910.md
+++ b/backport-changelog/6.7/6910.md
@@ -2,4 +2,5 @@ https://github.com/WordPress/wordpress-develop/pull/6910
* https://github.com/WordPress/gutenberg/pull/59483
* https://github.com/WordPress/gutenberg/pull/60652
-* https://github.com/WordPress/gutenberg/pull/62777
\ No newline at end of file
+* https://github.com/WordPress/gutenberg/pull/62777
+* https://github.com/WordPress/gutenberg/pull/63108
\ No newline at end of file
diff --git a/docs/reference-guides/block-api/block-metadata.md b/docs/reference-guides/block-api/block-metadata.md
index 2d4a93a080654..d79f1cdb6c56b 100644
--- a/docs/reference-guides/block-api/block-metadata.md
+++ b/docs/reference-guides/block-api/block-metadata.md
@@ -427,7 +427,7 @@ See the [Example documentation](/docs/reference-guides/block-api/block-registrat
### Variations
-- Type: `object[]`
+- Type: `object[]|WPDefinedPath` ([learn more](#wpdefinedpath))
- Optional
- Localized: Yes (`title`, `description`, and `keywords` of each variation only)
- Property: `variations`
@@ -454,6 +454,48 @@ Block Variations is the API that allows a block to have similar versions of it,
_Note: In JavaScript you can provide a function for the `isActive` property, and a React element for the `icon`. In the `block.json` file both only support strings_
+Starting with version 6.7, it is possible to specify a PHP file in `block.json` that generates the list of block variations on the server side:
+
+```json
+{ "variations": "file:./variations.php" }
+```
+
+That PHP file is expected to `return` an array that contains the block variations. Strings found in the variations returned from the PHP file will not be localized automatically; instead, use the `__()` function as usual.
+
+For example:
+
+```php
+ true,
+ 'name' => 'wordpress',
+ 'title' => 'WordPress',
+ 'icon' => 'wordpress',
+ 'attributes' => array(
+ 'service' => 'wordpress',
+ ),
+ 'isActive' => array( 'service' )
+ ),
+ array(
+ 'name' => 'mail',
+ 'title' => __( 'Mail' ),
+ 'keywords' => array(
+ __( 'email' ),
+ __( 'e-mail' )
+ ),
+ 'icon' => 'mail',
+ 'attributes' => array(
+ 'service' => 'mail',
+ ),
+ 'isActive' => array( 'mail' )
+ ),
+);
+
+```
+
See [the variations documentation](/docs/reference-guides/block-api/block-variations.md) for more details.
### Block Hooks
diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md
index d81a46cd727a1..4bfe230f6df03 100644
--- a/docs/reference-guides/core-blocks.md
+++ b/docs/reference-guides/core-blocks.md
@@ -24,7 +24,7 @@ Embed a simple audio player. ([Source](https://github.com/WordPress/gutenberg/tr
- **Name:** core/audio
- **Category:** media
- **Supports:** align, anchor, interactivity (clientNavigation), spacing (margin, padding)
-- **Attributes:** autoplay, caption, id, loop, preload, src
+- **Attributes:** autoplay, blob, caption, id, loop, preload, src
## Avatar
@@ -273,7 +273,7 @@ Add a link to a downloadable file. ([Source](https://github.com/WordPress/gutenb
- **Name:** core/file
- **Category:** media
- **Supports:** align, anchor, color (background, gradients, link, ~~text~~), interactivity, spacing (margin, padding)
-- **Attributes:** displayPreview, downloadButtonText, fileId, fileName, href, id, previewHeight, showDownloadButton, textLinkHref, textLinkTarget
+- **Attributes:** blob, displayPreview, downloadButtonText, fileId, fileName, href, id, previewHeight, showDownloadButton, textLinkHref, textLinkTarget
## Footnotes
diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index b5e2fe37faecd..a8cc85dd304e7 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -501,7 +501,7 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
if ( ! empty( $layout['rowCount'] ) ) {
$layout_styles[] = array(
'selector' => $selector,
- 'declarations' => array( 'grid-template-rows' => 'repeat(' . $layout['rowCount'] . ', minmax(8px, auto))' ),
+ 'declarations' => array( 'grid-template-rows' => 'repeat(' . $layout['rowCount'] . ', minmax(1rem, auto))' ),
);
}
} elseif ( ! empty( $layout['columnCount'] ) ) {
@@ -512,7 +512,7 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
if ( ! empty( $layout['rowCount'] ) ) {
$layout_styles[] = array(
'selector' => $selector,
- 'declarations' => array( 'grid-template-rows' => 'repeat(' . $layout['rowCount'] . ', minmax(8px, auto))' ),
+ 'declarations' => array( 'grid-template-rows' => 'repeat(' . $layout['rowCount'] . ', minmax(1rem, auto))' ),
);
}
} else {
diff --git a/lib/compat/wordpress-6.7/blocks.php b/lib/compat/wordpress-6.7/blocks.php
new file mode 100644
index 0000000000000..18d21621be719
--- /dev/null
+++ b/lib/compat/wordpress-6.7/blocks.php
@@ -0,0 +1,45 @@
+ {
+ ( { gridClientId, gridElement, isManualGrid }, ref ) => {
const [ gridInfo, setGridInfo ] = useState( () =>
getGridInfo( gridElement )
);
const [ isDroppingAllowed, setIsDroppingAllowed ] = useState( false );
- const [ highlightedRect, setHighlightedRect ] = useState( null );
useEffect( () => {
const observers = [];
@@ -88,7 +88,7 @@ const GridVisualizerGrid = forwardRef(
className={ clsx( 'block-editor-grid-visualizer', {
'is-dropping-allowed': isDroppingAllowed,
} ) }
- clientId={ clientId }
+ clientId={ gridClientId }
__unstablePopoverSlot="block-toolbar"
>
- { isManualGrid
- ? range( 1, gridInfo.numRows ).map( ( row ) =>
- range( 1, gridInfo.numColumns ).map(
- ( column ) => (
-
-
-
- )
- )
- )
- : Array.from(
- { length: gridInfo.numItems },
- ( _, i ) => (
-
- )
- ) }
+ { isManualGrid ? (
+
+ ) : (
+ Array.from( { length: gridInfo.numItems }, ( _, i ) => (
+
+ ) )
+ ) }
);
}
);
-function GridVisualizerCell( { color, children } ) {
+function ManualGridVisualizer( { gridClientId, gridInfo } ) {
+ const [ highlightedRect, setHighlightedRect ] = useState( null );
+
+ const gridItems = useSelect(
+ ( select ) => select( blockEditorStore ).getBlocks( gridClientId ),
+ [ gridClientId ]
+ );
+ const occupiedRects = useMemo( () => {
+ const rects = [];
+ for ( const block of gridItems ) {
+ const {
+ columnStart,
+ rowStart,
+ columnSpan = 1,
+ rowSpan = 1,
+ } = block.attributes.style?.layout || {};
+ if ( ! columnStart || ! rowStart ) {
+ continue;
+ }
+ rects.push(
+ new GridRect( {
+ columnStart,
+ rowStart,
+ columnSpan,
+ rowSpan,
+ } )
+ );
+ }
+ return rects;
+ }, [ gridItems ] );
+
+ return range( 1, gridInfo.numRows ).map( ( row ) =>
+ range( 1, gridInfo.numColumns ).map( ( column ) => {
+ const isCellOccupied = occupiedRects.some( ( rect ) =>
+ rect.contains( column, row )
+ );
+ const isHighlighted =
+ highlightedRect?.contains( column, row ) ?? false;
+ return (
+
+ { isCellOccupied ? (
+
+ ) : (
+
+ ) }
+
+ );
+ } )
+ );
+}
+
+function GridVisualizerCell( { color, children, className } ) {
return (
{ children }
@@ -148,15 +199,15 @@ function GridVisualizerCell( { color, children } ) {
);
}
-function GridVisualizerDropZone( {
+function useGridVisualizerDropZone(
column,
row,
gridClientId,
gridInfo,
- highlightedRect,
- setHighlightedRect,
-} ) {
- const { getBlockAttributes } = useSelect( blockEditorStore );
+ setHighlightedRect
+) {
+ const { getBlockAttributes, getBlockRootClientId } =
+ useSelect( blockEditorStore );
const {
updateBlockAttributes,
moveBlocksToPosition,
@@ -168,7 +219,7 @@ function GridVisualizerDropZone( {
gridInfo.numColumns
);
- const ref = useDropZoneWithValidation( {
+ return useDropZoneWithValidation( {
validateDrag( srcClientId ) {
const attributes = getBlockAttributes( srcClientId );
const rect = new GridRect( {
@@ -221,21 +272,87 @@ function GridVisualizerDropZone( {
__unstableMarkNextChangeAsNotPersistent();
moveBlocksToPosition(
[ srcClientId ],
- gridClientId,
+ getBlockRootClientId( srcClientId ),
gridClientId,
getNumberOfBlocksBeforeCell( column, row )
);
},
} );
+}
- const isHighlighted = highlightedRect?.contains( column, row ) ?? false;
-
+function GridVisualizerDropZone( {
+ column,
+ row,
+ gridClientId,
+ gridInfo,
+ setHighlightedRect,
+} ) {
return (
+ );
+}
+
+function GridVisualizerAppender( {
+ column,
+ row,
+ gridClientId,
+ gridInfo,
+ setHighlightedRect,
+} ) {
+ const {
+ updateBlockAttributes,
+ moveBlocksToPosition,
+ __unstableMarkNextChangeAsNotPersistent,
+ } = useDispatch( blockEditorStore );
+
+ const getNumberOfBlocksBeforeCell = useGetNumberOfBlocksBeforeCell(
+ gridClientId,
+ gridInfo.numColumns
+ );
+
+ return (
+
{
+ if ( ! block ) {
+ return;
+ }
+ updateBlockAttributes( block.clientId, {
+ style: {
+ layout: {
+ columnStart: column,
+ rowStart: row,
+ },
+ },
+ } );
+ __unstableMarkNextChangeAsNotPersistent();
+ moveBlocksToPosition(
+ [ block.clientId ],
+ gridClientId,
+ gridClientId,
+ getNumberOfBlocksBeforeCell( column, row )
+ );
+ } }
/>
);
}
diff --git a/packages/block-editor/src/components/grid/style.scss b/packages/block-editor/src/components/grid/style.scss
index 17513fa6496b2..a4d2c58895932 100644
--- a/packages/block-editor/src/components/grid/style.scss
+++ b/packages/block-editor/src/components/grid/style.scss
@@ -12,6 +12,9 @@
pointer-events: all;
}
}
+ .block-editor-inserter * {
+ pointer-events: auto;
+ }
}
}
@@ -20,23 +23,55 @@
}
.block-editor-grid-visualizer__cell {
- align-items: center;
- display: flex;
- justify-content: center;
+ display: grid;
+ position: relative;
+
+ .block-editor-inserter {
+ color: inherit;
+ z-index: 32;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ overflow: hidden;
+
+ .block-editor-grid-visualizer__appender {
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 20%, #0000);
+ color: inherit;
+ overflow: hidden;
+ height: 100%;
+ width: 100%;
+ padding: 0 !important;
+ opacity: 0;
+ }
+
+ }
+
+ &.is-highlighted {
+ .block-editor-inserter,
+ .block-editor-grid-visualizer__drop-zone {
+ background: var(--wp-admin-theme-color);
+ }
+ }
+
+ &:hover .block-editor-grid-visualizer__appender,
+ .block-editor-grid-visualizer__appender:focus {
+ opacity: 1;
+ background-color: color-mix(in srgb, currentColor 20%, #0000);
+ }
}
.block-editor-grid-visualizer__drop-zone {
background: rgba($gray-400, 0.1);
width: 100%;
height: 100%;
+ grid-column: 1;
+ grid-row: 1;
// Make drop zone 8x8 at minimum so that it's easier to drag into. This will overflow the parent.
min-width: $grid-unit-10;
min-height: $grid-unit-10;
-
- &.is-highlighted {
- background: var(--wp-admin-theme-color);
- }
}
.block-editor-grid-item-resizer {
@@ -60,3 +95,4 @@
}
}
}
+
diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js
index bcd60a687a36f..ef741a9b6ac61 100644
--- a/packages/block-editor/src/components/inserter/menu.js
+++ b/packages/block-editor/src/components/inserter/menu.js
@@ -88,7 +88,7 @@ function InserterMenu(
shouldForceFocusBlock,
_rootClientId
);
- onSelect();
+ onSelect( blocks );
// Check for focus loss due to filtering blocks by selected block type
window.requestAnimationFrame( () => {
diff --git a/packages/block-editor/src/components/inserter/quick-inserter.js b/packages/block-editor/src/components/inserter/quick-inserter.js
index 022957df952ce..aa3d54e87a7fd 100644
--- a/packages/block-editor/src/components/inserter/quick-inserter.js
+++ b/packages/block-editor/src/components/inserter/quick-inserter.js
@@ -85,7 +85,12 @@ export default function QuickInserter( {
// When clicking Browse All select the appropriate block so as
// the insertion point can work as expected.
const onBrowseAll = () => {
- setInserterIsOpened( { rootClientId, insertionIndex, filterValue } );
+ setInserterIsOpened( {
+ rootClientId,
+ insertionIndex,
+ filterValue,
+ onSelect,
+ } );
};
let maxBlockPatterns = 0;
diff --git a/packages/block-editor/src/hooks/grid-visualizer.js b/packages/block-editor/src/hooks/grid-visualizer.js
new file mode 100644
index 0000000000000..42b45952d45d1
--- /dev/null
+++ b/packages/block-editor/src/hooks/grid-visualizer.js
@@ -0,0 +1,64 @@
+/**
+ * WordPress dependencies
+ */
+import { createHigherOrderComponent } from '@wordpress/compose';
+import { addFilter } from '@wordpress/hooks';
+import { useSelect } from '@wordpress/data';
+
+/**
+ * Internal dependencies
+ */
+import { GridVisualizer, useGridLayoutSync } from '../components/grid';
+import { store as blockEditorStore } from '../store';
+
+function GridLayoutSync( props ) {
+ useGridLayoutSync( props );
+}
+
+function GridTools( { clientId, layout } ) {
+ const { isSelected, isDragging } = useSelect( ( select ) => {
+ const { isBlockSelected, isDraggingBlocks } =
+ select( blockEditorStore );
+
+ return {
+ isSelected: isBlockSelected( clientId ),
+ isDragging: isDraggingBlocks(),
+ };
+ } );
+
+ if ( ! isSelected && ! isDragging ) {
+ return null;
+ }
+
+ return (
+ <>
+
+
+ >
+ );
+}
+
+const addGridVisualizerToBlockEdit = createHigherOrderComponent(
+ ( BlockEdit ) => ( props ) => {
+ if ( props.attributes.layout?.type !== 'grid' ) {
+ return ;
+ }
+
+ return (
+ <>
+
+
+ >
+ );
+ },
+ 'addGridVisualizerToBlockEdit'
+);
+
+addFilter(
+ 'editor.BlockEdit',
+ 'core/editor/grid-visualizer',
+ addGridVisualizerToBlockEdit
+);
diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js
index 423e1f6f0bc32..b58ede2e9d389 100644
--- a/packages/block-editor/src/hooks/index.js
+++ b/packages/block-editor/src/hooks/index.js
@@ -33,6 +33,7 @@ import blockHooks from './block-hooks';
import blockBindingsPanel from './block-bindings';
import './block-renaming';
import './use-bindings-attributes';
+import './grid-visualizer';
createBlockEditFilter(
[
diff --git a/packages/block-editor/src/layouts/constrained.js b/packages/block-editor/src/layouts/constrained.js
index f86791391176f..03d2c642d02bd 100644
--- a/packages/block-editor/src/layouts/constrained.js
+++ b/packages/block-editor/src/layouts/constrained.js
@@ -24,6 +24,7 @@ import { getCSSRules } from '@wordpress/style-engine';
import { useSettings } from '../components/use-settings';
import { appendSelectors, getBlockGapCSS, getAlignmentsInfo } from './utils';
import { getGapCSSValue } from '../hooks/gap';
+import { BlockControls, JustifyContentControl } from '../components';
import { shouldSkipSerialization } from '../hooks/utils';
import { LAYOUT_DEFINITIONS } from './definitions';
@@ -146,8 +147,24 @@ export default {
>
);
},
- toolBarControls: function DefaultLayoutToolbarControls() {
- return null;
+ toolBarControls: function DefaultLayoutToolbarControls( {
+ layout = {},
+ onChange,
+ layoutBlockSupport,
+ } ) {
+ const { allowJustification = true } = layoutBlockSupport;
+
+ if ( ! allowJustification ) {
+ return null;
+ }
+ return (
+
+
+
+ );
},
getLayoutStyle: function getLayoutStyle( {
selector,
@@ -278,3 +295,27 @@ export default {
return alignments;
},
};
+
+const POPOVER_PROPS = {
+ placement: 'bottom-start',
+};
+
+function DefaultLayoutJustifyContentControl( { layout, onChange } ) {
+ const { justifyContent = 'center' } = layout;
+ const onJustificationChange = ( value ) => {
+ onChange( {
+ ...layout,
+ justifyContent: value,
+ } );
+ };
+ const allowedControls = [ 'left', 'center', 'right' ];
+
+ return (
+
+ );
+}
diff --git a/packages/block-editor/src/layouts/grid.js b/packages/block-editor/src/layouts/grid.js
index 21870fc182093..975b79f4ba570 100644
--- a/packages/block-editor/src/layouts/grid.js
+++ b/packages/block-editor/src/layouts/grid.js
@@ -23,7 +23,6 @@ import { appendSelectors, getBlockGapCSS } from './utils';
import { getGapCSSValue } from '../hooks/gap';
import { shouldSkipSerialization } from '../hooks/utils';
import { LAYOUT_DEFINITIONS } from './definitions';
-import { GridVisualizer, useGridLayoutSync } from '../components/grid';
const RANGE_CONTROL_MAX_VALUES = {
px: 600,
@@ -101,15 +100,8 @@ export default {
>
);
},
- toolBarControls: function GridLayoutToolbarControls( { clientId } ) {
- return (
- <>
- { window.__experimentalEnableGridInteractivity && (
-
- ) }
-
- >
- );
+ toolBarControls: function GridLayoutToolbarControls() {
+ return null;
},
getLayoutStyle: function getLayoutStyle( {
selector,
@@ -163,7 +155,7 @@ export default {
);
if ( rowCount ) {
rules.push(
- `grid-template-rows: repeat(${ rowCount }, minmax(8px, auto))`
+ `grid-template-rows: repeat(${ rowCount }, minmax(1rem, auto))`
);
}
} else if ( columnCount ) {
@@ -172,7 +164,7 @@ export default {
);
if ( rowCount ) {
rules.push(
- `grid-template-rows: repeat(${ rowCount }, minmax(8px, auto))`
+ `grid-template-rows: repeat(${ rowCount }, minmax(1rem, auto))`
);
}
} else {
@@ -479,7 +471,3 @@ function GridLayoutTypeControl( { layout, onChange } ) {
);
}
-
-function GridLayoutSync( props ) {
- useGridLayoutSync( props );
-}
diff --git a/packages/block-library/src/audio/block.json b/packages/block-library/src/audio/block.json
index 14b44704fb7e8..bee2ff6d534a7 100644
--- a/packages/block-library/src/audio/block.json
+++ b/packages/block-library/src/audio/block.json
@@ -8,6 +8,10 @@
"keywords": [ "music", "sound", "podcast", "recording" ],
"textdomain": "default",
"attributes": {
+ "blob": {
+ "type": "string",
+ "__experimentalRole": "local"
+ },
"src": {
"type": "string",
"source": "attribute",
diff --git a/packages/block-library/src/audio/edit.js b/packages/block-library/src/audio/edit.js
index 0db2552b8ac26..97d3c9c5a1ae3 100644
--- a/packages/block-library/src/audio/edit.js
+++ b/packages/block-library/src/audio/edit.js
@@ -26,6 +26,7 @@ import { __, _x } from '@wordpress/i18n';
import { useDispatch } from '@wordpress/data';
import { audio as icon } from '@wordpress/icons';
import { store as noticesStore } from '@wordpress/notices';
+import { useState } from '@wordpress/element';
/**
* Internal dependencies
@@ -45,10 +46,10 @@ function AudioEdit( {
insertBlocksAfter,
} ) {
const { id, autoplay, loop, preload, src } = attributes;
- const isTemporaryAudio = ! id && isBlobURL( src );
+ const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob );
useUploadMediaFromBlobURL( {
- url: src,
+ url: temporaryURL,
allowedTypes: ALLOWED_MEDIA_TYPES,
onChange: onSelectAudio,
onError: onUploadError,
@@ -72,7 +73,8 @@ function AudioEdit( {
onReplace( embedBlock );
return;
}
- setAttributes( { src: newSrc, id: undefined } );
+ setAttributes( { src: newSrc, id: undefined, blob: undefined } );
+ setTemporaryURL();
}
}
@@ -95,27 +97,37 @@ function AudioEdit( {
src: undefined,
id: undefined,
caption: undefined,
+ blob: undefined,
} );
+ setTemporaryURL();
return;
}
+
+ if ( isBlobURL( media.url ) ) {
+ setTemporaryURL( media.url );
+ return;
+ }
+
// Sets the block's attribute and updates the edit component from the
// selected media, then switches off the editing UI.
setAttributes( {
+ blob: undefined,
src: media.url,
id: media.id,
caption: media.caption,
} );
+ setTemporaryURL();
}
const classes = clsx( className, {
- 'is-transient': isTemporaryAudio,
+ 'is-transient': !! temporaryURL,
} );
const blockProps = useBlockProps( {
className: classes,
} );
- if ( ! src ) {
+ if ( ! src && ! temporaryURL ) {
return (
-
+
- { isTemporaryAudio && }
+ { !! temporaryURL && }
( {
media:
@@ -88,7 +89,7 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) {
useDispatch( blockEditorStore );
useUploadMediaFromBlobURL( {
- url: href,
+ url: temporaryURL,
onChange: onSelectFile,
onError: onUploadError,
} );
@@ -108,6 +109,12 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) {
function onSelectFile( newMedia ) {
if ( ! newMedia || ! newMedia.url ) {
+ setTemporaryURL();
+ return;
+ }
+
+ if ( isBlobURL( newMedia.url ) ) {
+ setTemporaryURL( newMedia.url );
return;
}
@@ -120,7 +127,9 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) {
displayPreview: isPdf ? true : undefined,
previewHeight: isPdf ? 600 : undefined,
fileId: `wp-block-file--media-${ clientId }`,
+ blob: undefined,
} );
+ setTemporaryURL();
}
function onUploadError( message ) {
@@ -166,16 +175,16 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) {
const blockProps = useBlockProps( {
className: clsx(
- isBlobURL( href ) && getAnimateClassName( { type: 'loading' } ),
+ !! temporaryURL && getAnimateClassName( { type: 'loading' } ),
{
- 'is-transient': isBlobURL( href ),
+ 'is-transient': !! temporaryURL,
}
),
} );
const displayPreviewInEditor = browserSupportsPdfs() && displayPreview;
- if ( ! href ) {
+ if ( ! href && ! temporaryURL ) {
return (
null,
...bootstrappedBlockType,
...blockSettings,
+ // blockType.variations can be defined as a filePath.
variations: mergeBlockVariations(
- bootstrappedBlockType?.variations,
- blockSettings?.variations
+ Array.isArray( bootstrappedBlockType?.variations )
+ ? bootstrappedBlockType.variations
+ : [],
+ Array.isArray( blockSettings?.variations )
+ ? blockSettings.variations
+ : []
),
};
diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md
index 01218a30c36e0..211a4f66f4803 100644
--- a/packages/components/CHANGELOG.md
+++ b/packages/components/CHANGELOG.md
@@ -16,11 +16,14 @@
### Bug Fixes
+- `Tabs`: Make Tabs have a fluid height ([#62027](https://github.com/WordPress/gutenberg/pull/62027)).
- `UnitControl`: Fix colors when disabled. ([#62970](https://github.com/WordPress/gutenberg/pull/62970))
- `useUpdateEffect`: Correctly track mounted state in strict mode. ([#62974](https://github.com/WordPress/gutenberg/pull/62974))
- `UnitControl`: Fix an issue where keyboard shortcuts unintentionally shift focus on Windows OS. ([#62988](https://github.com/WordPress/gutenberg/pull/62988))
- Fix inaccessibly disabled `Button`s ([#62306](https://github.com/WordPress/gutenberg/pull/62306)).
- `TimePicker`: Fix time zone overflow ([#63209](https://github.com/WordPress/gutenberg/pull/63209)).
+- `SelectControl`: Fix disabled styles ([#63266](https://github.com/WordPress/gutenberg/pull/63266)).
+- `Tabs`: Fix text-align when text wraps in vertical mode ([#63272](https://github.com/WordPress/gutenberg/pull/63272)).
### Internal
diff --git a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap
index 608cadbcf544f..1d3cd12a2aa31 100644
--- a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap
+++ b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap
@@ -21,7 +21,7 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
margin-bottom: inherit;
}
-.emotion-5 {
+.emotion-6 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -41,20 +41,22 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
position: relative;
border-radius: 2px;
padding-top: 0;
+ color: var(--wp-components-color-foreground, #1e1e1e);
+ cursor: pointer;
}
-.emotion-5>* {
+.emotion-6>* {
min-height: 0;
}
-.emotion-5:focus-within:not( :has( :is( .em5sgkm7, .emotion-18 ):focus-within ) ) .emotion-25 {
+.emotion-6:focus-within:not( :has( :is( .em5sgkm7, .emotion-19 ):focus-within ) ) .emotion-26 {
border-color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9));
box-shadow: 0 0 0 0.5px var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9));
outline: 2px solid transparent;
outline-offset: -2px;
}
-.emotion-8 {
+.emotion-9 {
display: block;
max-height: 100%;
max-width: 100%;
@@ -64,7 +66,7 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
max-width: calc( 100% - 10px );
}
-.emotion-11 {
+.emotion-12 {
color: #1e1e1e;
line-height: 1.4;
margin: 0;
@@ -74,7 +76,7 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
font-weight: normal;
}
-.emotion-11.emotion-11.emotion-11 {
+.emotion-12.emotion-12.emotion-12 {
font-size: 11px;
font-weight: 500;
line-height: 1.4;
@@ -90,7 +92,7 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
white-space: nowrap;
}
-.emotion-13 {
+.emotion-14 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
@@ -109,7 +111,7 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
width: 100%;
}
-.emotion-15.emotion-15.emotion-15 {
+.emotion-16.emotion-16.emotion-16 {
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
@@ -118,13 +120,12 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
box-sizing: border-box;
border: none;
box-shadow: none!important;
- color: #1e1e1e;
+ cursor: inherit;
display: block;
font-family: inherit;
margin: 0;
width: 100%;
max-width: none;
- cursor: pointer;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 16px;
@@ -138,12 +139,12 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
}
@media ( min-width: 600px ) {
- .emotion-15.emotion-15.emotion-15 {
+ .emotion-16.emotion-16.emotion-16 {
font-size: 13px;
}
}
-.emotion-17 {
+.emotion-18 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
@@ -158,7 +159,7 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
display: flex;
}
-.emotion-20 {
+.emotion-21 {
margin-bottom: 0;
padding-right: calc(4px * 2);
position: absolute;
@@ -166,13 +167,17 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
right: 0;
}
-.emotion-22 {
+.emotion-23 {
-webkit-margin-end: calc(4px * -1);
margin-inline-end: calc(4px * -1);
line-height: 0;
}
-.emotion-24.emotion-24.emotion-24 {
+.emotion-23 path {
+ fill: currentColor;
+}
+
+.emotion-25.emotion-25.emotion-25 {
box-sizing: border-box;
border-color: var(--wp-components-color-gray-600, #949494);
border-radius: inherit;
@@ -197,17 +202,17 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
class="components-base-control__field emotion-2 emotion-3"
>