diff --git a/changelog.txt b/changelog.txt index 9505059dd3b706..f88f39e5968db0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,257 @@ == Changelog == += 17.8.0-rc.1 = + +## Changelog + +### Features + +- Patterns: add bulk export patterns action. ([58897](https://github.com/WordPress/gutenberg/pull/58897)) +- Template editor/inspector: show and select related patterns. ([55091](https://github.com/WordPress/gutenberg/pull/55091)) + +#### Layout +- Add toggle for grid types and stabilise Grid block variation. ([59051](https://github.com/WordPress/gutenberg/pull/59051) and [59116](https://github.com/WordPress/gutenberg/pull/59116)) +- Add support for column and row span in grid children. ([58539](https://github.com/WordPress/gutenberg/pull/58539)) + + +### Enhancements + +- Patterns Page: Make category action button compact. ([59203](https://github.com/WordPress/gutenberg/pull/59203)) +- Block Editor: Use hooks instead of HoC in 'SkipToSelectedBlock'. ([59202](https://github.com/WordPress/gutenberg/pull/59202)) +- Font Library: Adds the ability to use generic() in font family names. ([59103](https://github.com/WordPress/gutenberg/pull/59103) and [59037](https://github.com/WordPress/gutenberg/pull/59037)) +- REST API Global Styles Revisions Controller: Return single revision only when it matches the parent id. ([59049](https://github.com/WordPress/gutenberg/pull/59049)) +- CSS & Styling: Tweak link focus outline styles in HTML anchor and custom CSS. ([59048](https://github.com/WordPress/gutenberg/pull/59048)) +- Data Views: Make 'All pages' view label consistent with template and patterns. ([59009](https://github.com/WordPress/gutenberg/pull/59009)) +- Script Modules API: Script Modules add deregister option. ([58830](https://github.com/WordPress/gutenberg/pull/58830)) + +#### Custom Fields +- Block Bindings: Lock editing of blocks by default. ([58787](https://github.com/WordPress/gutenberg/pull/58787)) +- Style engine: Rename at_rule to rules_groups and update test/docs. ([58922](https://github.com/WordPress/gutenberg/pull/58922)) + +#### Block Library +- Gallery: Set the 'defaultBlock' setting for inner blocks. ([59168](https://github.com/WordPress/gutenberg/pull/59168)) +- Remove the navigation edit button because it leads to a useless screen. ([59211](https://github.com/WordPress/gutenberg/pull/59211)) +- Set the 'defaultBlock' setting for Columns & List blocks. ([59196](https://github.com/WordPress/gutenberg/pull/59196)) +- Update: Increase footnotes meta priority and separate footnotes meta registration. ([58882](https://github.com/WordPress/gutenberg/pull/58882)) + +#### Site Editor +- Editor: Hide template part and post content blocks in some site editor contexts. ([58928](https://github.com/WordPress/gutenberg/pull/58928)) +- Tweak save hub button. ([58917](https://github.com/WordPress/gutenberg/pull/58917) and [59200](https://github.com/WordPress/gutenberg/pull/59200)) + +#### Components +- CustomSelect: Adapt component for legacy props. ([57902](https://github.com/WordPress/gutenberg/pull/57902)) +- Use `Element.scrollIntoView()` instead of `dom-scroll-into-view`. ([59085](https://github.com/WordPress/gutenberg/pull/59085)) + +#### Global Styles +- Global style changes: Refactor output for a more flexible UI and grouping. ([59055](https://github.com/WordPress/gutenberg/pull/59055)) +- Style theme variations: Add property extraction and merge utils. ([58803](https://github.com/WordPress/gutenberg/pull/58803)) + + +### Bug Fixes + +- Distraction Free Mode: fix ui toggling bugs. ([59061](https://github.com/WordPress/gutenberg/pull/59061)) +- Layout: Refactor responsive logic for grid column spans. ([59057](https://github.com/WordPress/gutenberg/pull/59057)) +- Interactivity API: Only add proxies to plain objects inside the store. ([59039](https://github.com/WordPress/gutenberg/pull/59039)) +- Block Hooks: Fix in Navigation block. ([59021](https://github.com/WordPress/gutenberg/pull/59021)) + +#### List View +- Editor: Do not open list view by default on mobile. ([59016](https://github.com/WordPress/gutenberg/pull/59016)) +- Create Block: Add missing `viewScriptModule` field. ([59140](https://github.com/WordPress/gutenberg/pull/59140)) +- Ignore the 'twentytwentyfour' test theme dir created by wp-env. ([59072](https://github.com/WordPress/gutenberg/pull/59072)) +- useEntityBlockEditor: Update 'content' type check. ([59058](https://github.com/WordPress/gutenberg/pull/59058)) + +#### Block Library +- Author, Author Bio, Author Name: Add a fallback for Author Archive Template. ([55451](https://github.com/WordPress/gutenberg/pull/55451)) +- Fix Spacer orientation when inside a block with default flex layout. ([58921](https://github.com/WordPress/gutenberg/pull/58921)) +- Fix WP 6.4/6.3 compat for navigation link variations. ([59126](https://github.com/WordPress/gutenberg/pull/59126)) +- Interactivity API: Fix server side rendering for Search block. ([59029](https://github.com/WordPress/gutenberg/pull/59029)) +- Navigation: Avoid using embedded record from fallback API. ([59076](https://github.com/WordPress/gutenberg/pull/59076)) +- Pagination Numbers: Add `data-wp-key` to pagination numbers if enhanced pagination is enabled. ([58189](https://github.com/WordPress/gutenberg/pull/58189)) +- Revert "Navigation: Refactor mobile overlay breakpoints to JS (#57520)". ([59149](https://github.com/WordPress/gutenberg/pull/59149)) +- Spacer block: Fix `null` label in tooltip when horizontal layout. ([58909](https://github.com/WordPress/gutenberg/pull/58909)) + +#### Data Views +- DataViews: Add loading/no results message in grid view. ([59002](https://github.com/WordPress/gutenberg/pull/59002)) +- DataViews: Correctly display featured image that don't have image sizes. ([59111](https://github.com/WordPress/gutenberg/pull/59111)) +- DataViews: Fix pages list back path. ([59201](https://github.com/WordPress/gutenberg/pull/59201)) +- DataViews: Fix patterns, templates and template parts pagination `z-index`. ([58965](https://github.com/WordPress/gutenberg/pull/58965)) +- DataViews: Fix storybook. ([58842](https://github.com/WordPress/gutenberg/pull/58842)) +- DataViews: Remove second `reset filter` button in filter dialog. ([58960](https://github.com/WordPress/gutenberg/pull/58960)) +- Revert footer in pages list with DataViews. ([59151](https://github.com/WordPress/gutenberg/pull/59151)) + +#### Block Editor +- After Enter transform, skip other onEnter actions like splitting. ([59064](https://github.com/WordPress/gutenberg/pull/59064)) +- Close link preview if collapsed selection when creating link. ([58896](https://github.com/WordPress/gutenberg/pull/58896)) +- Editor: Limit spotlight mode to the editor. ([58817](https://github.com/WordPress/gutenberg/pull/58817)) +- Fix incorrect useAnchor positioning when switching from virtual to rich text elements. ([58900](https://github.com/WordPress/gutenberg/pull/58900)) +- Inserter: Don't select the closest block with 'disabled' editing mode. ([58971](https://github.com/WordPress/gutenberg/pull/58971)) +- Inserter: Fix title condition for media tab previews. ([58993](https://github.com/WordPress/gutenberg/pull/58993)) + +#### Site Editor +- Fix navigation on mobile web. ([59014](https://github.com/WordPress/gutenberg/pull/59014)) +- Fix: Don't render the Transform Into panel if there are no patterns. ([59217](https://github.com/WordPress/gutenberg/pull/59217)) +- Fix: Logical error in filterPatterns on template-panel/hooks.js. ([59218](https://github.com/WordPress/gutenberg/pull/59218)) +- Make command palette string transatables. ([59133](https://github.com/WordPress/gutenberg/pull/59133)) +- Remove left margin on Status help text. ([58775](https://github.com/WordPress/gutenberg/pull/58775)) + +#### Patterns +- Allow editing of image block alt and title attributes in content only mode. ([58998](https://github.com/WordPress/gutenberg/pull/58998)) +- Avoid showing block removal warning when deleting a pattern instance that has overrides. ([59044](https://github.com/WordPress/gutenberg/pull/59044)) +- Block editor: Pass patterns selector as setting. ([58661](https://github.com/WordPress/gutenberg/pull/58661)) +- Fix pattern categories on import. ([58926](https://github.com/WordPress/gutenberg/pull/58926)) +- Site editor: Fix start patterns store selector. ([58813](https://github.com/WordPress/gutenberg/pull/58813)) + +#### Global Styles +- Fix console error in block preview. ([59112](https://github.com/WordPress/gutenberg/pull/59112)) +- Revert "Use all the settings origins for a block that consumes paths with merge #55219" ([58951](https://github.com/WordPress/gutenberg/pull/58951) and [59101](https://github.com/WordPress/gutenberg/pull/59101)) +- Shadows: Don't assume that core provides default shadows. ([58973](https://github.com/WordPress/gutenberg/pull/58973)) + +#### Font Library +- Fixes installed font families not rendering in the editor or frontend. ([59019](https://github.com/WordPress/gutenberg/pull/59019)) +- Font Libary: Add missing translation functions. ([58104](https://github.com/WordPress/gutenberg/pull/58104)) +- Show error message when no fonts found to install. ([58914](https://github.com/WordPress/gutenberg/pull/58914)) + +#### Synced Patterns +- Fix missing source for binding attributes. ([59194](https://github.com/WordPress/gutenberg/pull/59194)) +- Fix resetting individual blocks to empty optional values for Pattern Overrides. ([59170](https://github.com/WordPress/gutenberg/pull/59170)) +- Fix upload button on overridden empty image block in patterns. ([59169](https://github.com/WordPress/gutenberg/pull/59169)) + +#### Design Tools +- Background image support: Fix issue with background position keyboard entry. ([59050](https://github.com/WordPress/gutenberg/pull/59050)) +- Cover block: Clear the min height field when aspect ratio is set. ([59191](https://github.com/WordPress/gutenberg/pull/59191)) +- Elements: Fix block instance element styles for links applying to buttons. ([59114](https://github.com/WordPress/gutenberg/pull/59114)) + +#### Components +- Modal: Add `box-sizing` reset style. ([58905](https://github.com/WordPress/gutenberg/pull/58905)) +- ToolbarButton: Fix text centering for short labels. ([59117](https://github.com/WordPress/gutenberg/pull/59117)) +- Upgrade Floating UI packages, fix nested iframe positioning bug. ([58932](https://github.com/WordPress/gutenberg/pull/58932)) + +#### Post Editor +- Editor: Fix 'useHideBlocksFromInserter' hook filename. ([59150](https://github.com/WordPress/gutenberg/pull/59150)) +- Fix layout for non viewable post types. ([58962](https://github.com/WordPress/gutenberg/pull/58962)) + +#### Rich Text +- Fix link paste for internal paste. ([59063](https://github.com/WordPress/gutenberg/pull/59063)) +- Revert "Rich text: Pad multiple spaces through en/em replacement". ([58792](https://github.com/WordPress/gutenberg/pull/58792)) + +#### Custom Fields +- Block Bindings: Add block context needed for bindings in PHP. ([58554](https://github.com/WordPress/gutenberg/pull/58554)) +- Block Bindings: Fix disable bindings editing when source is undefined. ([58961](https://github.com/WordPress/gutenberg/pull/58961)) + + +### Accessibility + +- Enter editing mode via Enter or Spacebar. ([58795](https://github.com/WordPress/gutenberg/pull/58795)) +- Block Bindings > Image Block:Mark connected controls as 'readonly'. ([59059](https://github.com/WordPress/gutenberg/pull/59059)) +- Details Block: Try double enter to escape inner blocks. ([58903](https://github.com/WordPress/gutenberg/pull/58903)) +- Font Library: Replace infinite scroll by pagination. ([58794](https://github.com/WordPress/gutenberg/pull/58794)) +- Global Styles: Remove menubar role and improve complementary area header semantics. ([58740](https://github.com/WordPress/gutenberg/pull/58740)) + +#### Block Editor +- Block Mover: Unify visual separator when show button label is on. ([59158](https://github.com/WordPress/gutenberg/pull/59158)) +- Make the custom CSS validation error message accessible. ([56690](https://github.com/WordPress/gutenberg/pull/56690)) +- Restore default border and focus style on image URL input field. ([58505](https://github.com/WordPress/gutenberg/pull/58505)) + +### Performance + +- Pattern Block: Batch replacing actions. ([59075](https://github.com/WordPress/gutenberg/pull/59075)) +- Block Editor: Move StopEditingAsBlocksOnOutsideSelect to Root. ([58412](https://github.com/WordPress/gutenberg/pull/58412)) + + +### Documentation + +- Add contributing guidlines around Component versioning. ([58789](https://github.com/WordPress/gutenberg/pull/58789)) +- Clarify the performance reference commit and how to pick it. ([58927](https://github.com/WordPress/gutenberg/pull/58927)) +- DataViews: Update documentation. ([58847](https://github.com/WordPress/gutenberg/pull/58847)) +- Docs: Clarify the status of the wp-block-styles theme support, and its intent. ([58915](https://github.com/WordPress/gutenberg/pull/58915)) +- Fix move interactivity schema to supports property instead of selectors property. ([59166](https://github.com/WordPress/gutenberg/pull/59166)) +- Storybook: Show badges in sidebar. ([58518](https://github.com/WordPress/gutenberg/pull/58518)) +- Theme docs: Update appearance-tools documentation to reflect opt-in for backgroundSize and aspectRatio. ([59165](https://github.com/WordPress/gutenberg/pull/59165)) +- Update richtext.md. ([59089](https://github.com/WordPress/gutenberg/pull/59089)) + +#### Interactivity API +- Interactivity API: Fix WP version, update new store documentation. ([59107](https://github.com/WordPress/gutenberg/pull/59107)) +- Interactivity API: Update documentation guide with new `wp-interactivity` directive implementation. ([59018](https://github.com/WordPress/gutenberg/pull/59018)) +- Add interactivity property to block supports reference documentation. ([59152](https://github.com/WordPress/gutenberg/pull/59152)) + +#### Schemas +- Block JSON schema: Add `viewScriptModule` field. ([59060](https://github.com/WordPress/gutenberg/pull/59060)) +- Block JSON schema: Update `shadow` definition. ([58910](https://github.com/WordPress/gutenberg/pull/58910)) +- JSON schema: Update schema for background support. ([59127](https://github.com/WordPress/gutenberg/pull/59127)) + +### Code Quality + +- Create Block: Remove deprecated viewModule field. ([59198](https://github.com/WordPress/gutenberg/pull/59198)) +- Editor: Remove the 'all' rendering mode. ([58935](https://github.com/WordPress/gutenberg/pull/58935)) +- Editor: Unify the editor commands between post and site editors. ([59005](https://github.com/WordPress/gutenberg/pull/59005)) +- Relocate 'ErrorBoundary' component unit test folders. ([59031](https://github.com/WordPress/gutenberg/pull/59031)) +- Remove obsolete wp-env configuration from package.json (#58877). ([58899](https://github.com/WordPress/gutenberg/pull/58899)) +- Design Tools > Elements: Make editor selector match theme.json and frontend. ([59167](https://github.com/WordPress/gutenberg/pull/59167)) +- Global Styles: Update sprintf calls using `_n`. ([59160](https://github.com/WordPress/gutenberg/pull/59160)) +- Block API: Revert "Block Hooks: Set ignoredHookedBlocks metada attr upon insertion". ([58969](https://github.com/WordPress/gutenberg/pull/58969)) +- Editor > Rich Text: Remove inline toolbar preference. ([58945](https://github.com/WordPress/gutenberg/pull/58945)) +- Style Variations: Remove preferred style variations legacy support. ([58930](https://github.com/WordPress/gutenberg/pull/58930)) +- REST API > Template Revisions: Move from experimental to compat/6.4. ([58920](https://github.com/WordPress/gutenberg/pull/58920)) + +#### Block Editor +- Block-editor: Auto-register block commands. ([59079](https://github.com/WordPress/gutenberg/pull/59079)) +- BlockSettingsMenu: Combine 'block-editor' store selectors. ([59153](https://github.com/WordPress/gutenberg/pull/59153)) +- Clean up link control CSS. ([58934](https://github.com/WordPress/gutenberg/pull/58934)) +- HeadingLevelDropdown: Remove unnecessary isPressed prop. ([56636](https://github.com/WordPress/gutenberg/pull/56636)) +- Move 'ParentSelectorMenuItem' into a separate file. ([59146](https://github.com/WordPress/gutenberg/pull/59146)) +- Remove 'BlockSettingsMenu' styles. ([59147](https://github.com/WordPress/gutenberg/pull/59147)) + +#### Components +- Add Higher Order Function to ignore Input Method Editor (IME) keydowns. ([59081](https://github.com/WordPress/gutenberg/pull/59081)) +- Add lint rules for theme color CSS var usage. ([59022](https://github.com/WordPress/gutenberg/pull/59022)) +- ColorPicker: Style without accessing InputControl internals. ([59069](https://github.com/WordPress/gutenberg/pull/59069)) +- CustomSelectControl (v1 & v2): Fix errors in unit test setup. ([59038](https://github.com/WordPress/gutenberg/pull/59038)) +- CustomSelectControl: Hard deprecate constrained width. ([58974](https://github.com/WordPress/gutenberg/pull/58974)) + +#### Post Editor +- DocumentBar: Fix browser warning error. ([59193](https://github.com/WordPress/gutenberg/pull/59193)) +- DocumentBar: Simplify component, use framer for animation. ([58656](https://github.com/WordPress/gutenberg/pull/58656)) +- Editor: Remove unused selector value from 'PostTitle'. ([59204](https://github.com/WordPress/gutenberg/pull/59204)) +- Editor: Unify Mode Switcher component between post and site editor. ([59100](https://github.com/WordPress/gutenberg/pull/59100)) + +#### Interactivity API +- Refactor to use string instead of an object on `wp-data-interactive`. ([59034](https://github.com/WordPress/gutenberg/pull/59034)) +- Remove `data-wp-interactive` object for core/router. ([59030](https://github.com/WordPress/gutenberg/pull/59030)) +- Use `data_wp_context` helper in core blocks and remove `data-wp-interactive` object. ([58943](https://github.com/WordPress/gutenberg/pull/58943)) + +#### Site Editor +- Add stylelint rule to prevent theme CSS vars outside of wp-components. ([59020](https://github.com/WordPress/gutenberg/pull/59020)) +- Don't memoize the canvas container title. ([59000](https://github.com/WordPress/gutenberg/pull/59000)) +- Remove old patterns list code and styles. ([58966](https://github.com/WordPress/gutenberg/pull/58966)) + + +### Tools + +- Remove reference to CODE_OF_CONDUCT.md in documentation. ([59206](https://github.com/WordPress/gutenberg/pull/59206)) +- Remove repository specific Code of Conduct. ([59027](https://github.com/WordPress/gutenberg/pull/59027)) +- env: Fix mariadb version to LTS. ([59237](https://github.com/WordPress/gutenberg/pull/59237)) + +#### Testing +- Components: Add sleep() before all Tab() to fix flaky tests. ([59012](https://github.com/WordPress/gutenberg/pull/59012)) +- Components: Try fixing some flaky `Composite` and `Tabs` tests. ([58968](https://github.com/WordPress/gutenberg/pull/58968)) +- Migrate `change-detection` to Playwright. ([58767](https://github.com/WordPress/gutenberg/pull/58767)) +- Tabs: Fix flaky unit tests. ([58629](https://github.com/WordPress/gutenberg/pull/58629)) +- Update test environment default theme versions to latest. ([58955](https://github.com/WordPress/gutenberg/pull/58955)) + +#### Build Tooling +- Add test:e2e:playwright:debug command to debug Playwright tests. ([58808](https://github.com/WordPress/gutenberg/pull/58808)) +- Updating Storybook to v7.6.15 (latest). ([59074](https://github.com/WordPress/gutenberg/pull/59074)) + + + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @afercia @ajlende @alexstine @andrewhayward @andrewserong @brookewp @c4rl0sbr4v0 @chad1008 @ciampo @DAreRodz @derekblank @desrosj @draganescu @ellatrix @fabiankaegy @gaambo @glendaviesnz @jameskoster @janboddez @jasmussen @jeryj @jorgefilipecosta @jsnajdr @juanfra @kevin940726 @Mamaduka @MarieComet @matiasbenedetto @mirka @noisysocks @ntsekouras @oandregal @ockham @pbking @ramonjd @SantosGuillamot @scruffian @shreyash3087 @t-hamano @talldan @tellthemachines @tyxla @youknowriad + + = 17.7.0 = ## Changelog diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index eaffc0a875ca3b..9e9c1ef140c76a 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -1263,7 +1263,7 @@ Action that hides the insertion point. ### insertAfterBlock -Action that inserts an empty block after a given block. +Action that inserts a default block after a given block. _Parameters_ @@ -1271,7 +1271,7 @@ _Parameters_ ### insertBeforeBlock -Action that inserts an empty block before a given block. +Action that inserts a default block before a given block. _Parameters_ diff --git a/gutenberg.php b/gutenberg.php index c9edbb32024c8c..a6b4577d10a2d7 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.3 * Requires PHP: 7.0 - * Version: 17.7.0 + * Version: 17.8.0-rc.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 0d2520ff9682a4..82e5503a6b225d 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -3807,12 +3807,18 @@ private static function resolve_custom_css_format( $tree ) { * Replaces CSS variables with their values in place. * * @since 6.3.0 + * @since 6.6.0 Check for empty style before processing. + * * @param array $styles CSS declarations to convert. * @param array $values key => value pairs to use for replacement. * @return array */ private static function convert_variables_to_value( $styles, $values ) { foreach ( $styles as $key => $style ) { + if ( empty( $style ) ) { + continue; + } + if ( is_array( $style ) ) { $styles[ $key ] = self::convert_variables_to_value( $style, $values ); continue; diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php index cd402a8e545003..3ccbed6ed275e9 100644 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php +++ b/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php @@ -48,12 +48,11 @@ final class WP_Font_Collection { * * @since 6.5.0 * - * @param string $slug Font collection slug. - * @param array|string $data_or_file Font collection data array or a path/URL to a JSON file - * containing the font collection. - * See {@see wp_register_font_collection()} for the supported fields. + * @param string $slug Font collection slug. May only contain alphanumeric characters, dashes, + * and underscores. See sanitize_title(). + * @param array $args Font collection data. See wp_register_font_collection() for information on accepted arguments. */ - public function __construct( $slug, $data_or_file ) { + public function __construct( string $slug, array $args ) { $this->slug = sanitize_title( $slug ); if ( $this->slug !== $slug ) { _doing_it_wrong( @@ -64,12 +63,17 @@ public function __construct( $slug, $data_or_file ) { ); } - if ( is_array( $data_or_file ) ) { - $this->data = $this->sanitize_and_validate_data( $data_or_file ); - } else { + $required_properties = array( 'name', 'font_families' ); + + if ( isset( $args['font_families'] ) && is_string( $args['font_families'] ) ) { // JSON data is lazy loaded by ::get_data(). - $this->src = $data_or_file; + $this->src = $args['font_families']; + unset( $args['font_families'] ); + + $required_properties = array( 'name' ); } + + $this->data = $this->sanitize_and_validate_data( $args, $required_properties ); } /** @@ -80,8 +84,12 @@ public function __construct( $slug, $data_or_file ) { * @return array|WP_Error An array containing the font collection data, or a WP_Error on failure. */ public function get_data() { + if ( is_wp_error( $this->data ) ) { + return $this->data; + } + // If the collection uses JSON data, load it and cache the data/error. - if ( $this->src && empty( $this->data ) ) { + if ( isset( $this->src ) ) { $this->data = $this->load_from_json( $this->src ); } @@ -118,7 +126,26 @@ private function load_from_json( $file_or_url ) { return new WP_Error( 'font_collection_json_missing', $message ); } - return $url ? $this->load_from_url( $url ) : $this->load_from_file( $file ); + $data = $url ? $this->load_from_url( $url ) : $this->load_from_file( $file ); + + if ( is_wp_error( $data ) ) { + return $data; + } + + $data = array( + 'name' => $this->data['name'], + 'font_families' => $data['font_families'], + ); + + if ( isset( $this->data['description'] ) ) { + $data['description'] = $this->data['description']; + } + + if ( isset( $this->data['categories'] ) ) { + $data['categories'] = $this->data['categories']; + } + + return $data; } /** @@ -136,7 +163,7 @@ private function load_from_file( $file ) { return new WP_Error( 'font_collection_decode_error', __( 'Error decoding the font collection JSON file contents.', 'gutenberg' ) ); } - return $this->sanitize_and_validate_data( $data ); + return $this->sanitize_and_validate_data( $data, array( 'font_families' ) ); } /** @@ -156,8 +183,14 @@ private function load_from_url( $url ) { if ( false === $data ) { $response = wp_safe_remote_get( $url ); if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { - // translators: %s: Font collection URL. - return new WP_Error( 'font_collection_request_error', sprintf( __( 'Error fetching the font collection data from "%s".', 'gutenberg' ), $url ) ); + return new WP_Error( + 'font_collection_request_error', + sprintf( + // translators: %s: Font collection URL. + __( 'Error fetching the font collection data from "%s".', 'gutenberg' ), + $url + ) + ); } $data = json_decode( wp_remote_retrieve_body( $response ), true ); @@ -166,7 +199,7 @@ private function load_from_url( $url ) { } // Make sure the data is valid before storing it in a transient. - $data = $this->sanitize_and_validate_data( $data ); + $data = $this->sanitize_and_validate_data( $data, array( 'font_families' ) ); if ( is_wp_error( $data ) ) { return $data; } @@ -182,18 +215,18 @@ private function load_from_url( $url ) { * * @since 6.5.0 * - * @param array $data Font collection data to sanitize and validate. + * @param array $data Font collection data to sanitize and validate. + * @param array $required_properties Required properties that must exist in the passed data. * @return array|WP_Error Sanitized data if valid, otherwise a WP_Error instance. */ - private function sanitize_and_validate_data( $data ) { + private function sanitize_and_validate_data( $data, $required_properties = array() ) { $schema = self::get_sanitization_schema(); $data = WP_Font_Utils::sanitize_from_schema( $data, $schema ); - $required_properties = array( 'name', 'font_families' ); foreach ( $required_properties as $property ) { if ( empty( $data[ $property ] ) ) { $message = sprintf( - // translators: 1: Font collection slug, 2: Missing property name, e.g. "font_families". + // translators: 1: Font collection slug, 2: Missing property name, e.g. "font_families". __( 'Font collection "%1$s" has missing or empty property: "%2$s".', 'gutenberg' ), $this->slug, $property diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-library.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-library.php index 141dff730a15fc..eb4a269b3a8068 100644 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-library.php +++ b/lib/compat/wordpress-6.5/fonts/class-wp-font-library.php @@ -39,20 +39,19 @@ class WP_Font_Library { * * @since 6.5.0 * - * @param string $slug Font collection slug. - * @param array $data_or_file Font collection data array or a path/URL to a JSON file - * containing the font collection. - * See {@see wp_register_font_collection()} for the supported fields. + * @param string $slug Font collection slug. May only contain alphanumeric characters, dashes, + * and underscores. See sanitize_title(). + * @param array $args Font collection data. See wp_register_font_collection() for information on accepted arguments. * @return WP_Font_Collection|WP_Error A font collection if it was registered successfully, * or WP_Error object on failure. */ - public function register_font_collection( $slug, $data_or_file ) { - $new_collection = new WP_Font_Collection( $slug, $data_or_file ); + public function register_font_collection( string $slug, array $args ) { + $new_collection = new WP_Font_Collection( $slug, $args ); if ( $this->is_collection_registered( $new_collection->slug ) ) { $error_message = sprintf( /* translators: %s: Font collection slug. */ - __( 'Font collection with slug "%s" is already registered.', 'gutenberg' ), + __( 'Font collection with slug: "%s" is already registered.', 'gutenberg' ), $new_collection->slug ); _doing_it_wrong( @@ -74,7 +73,7 @@ public function register_font_collection( $slug, $data_or_file ) { * @param string $slug Font collection slug. * @return bool True if the font collection was unregistered successfully and false otherwise. */ - public function unregister_font_collection( $slug ) { + public function unregister_font_collection( string $slug ) { if ( ! $this->is_collection_registered( $slug ) ) { _doing_it_wrong( __METHOD__, @@ -96,7 +95,7 @@ public function unregister_font_collection( $slug ) { * @param string $slug Font collection slug. * @return bool True if the font collection is registered and false otherwise. */ - private function is_collection_registered( $slug ) { + private function is_collection_registered( string $slug ) { return array_key_exists( $slug, $this->collections ); } @@ -119,7 +118,7 @@ public function get_font_collections() { * @param string $slug Font collection slug. * @return WP_Font_Collection|null Font collection object, or null if the font collection doesn't exist. */ - public function get_font_collection( $slug ) { + public function get_font_collection( string $slug ) { if ( $this->is_collection_registered( $slug ) ) { return $this->collections[ $slug ]; } diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-collections-controller.php b/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-collections-controller.php index 97aba89a8b24e9..2433a8d4ff9553 100644 --- a/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-collections-controller.php +++ b/lib/compat/wordpress-6.5/fonts/class-wp-rest-font-collections-controller.php @@ -106,7 +106,7 @@ public function get_items( $request ) { $response = rest_ensure_response( $items ); $response->header( 'X-WP-Total', (int) $total_items ); - $response->header( 'X-WP-TotalPages', (int) $max_pages ); + $response->header( 'X-WP-TotalPages', $max_pages ); $request_params = $request->get_query_params(); $collection_url = rest_url( $this->namespace . '/' . $this->rest_base ); diff --git a/lib/compat/wordpress-6.5/fonts/fonts.php b/lib/compat/wordpress-6.5/fonts/fonts.php index 1f29645a9c2b90..8307d5217ad426 100644 --- a/lib/compat/wordpress-6.5/fonts/fonts.php +++ b/lib/compat/wordpress-6.5/fonts/fonts.php @@ -114,28 +114,30 @@ function gutenberg_init_font_library() { if ( ! function_exists( 'wp_register_font_collection' ) ) { /** - * Registers a new Font Collection in the Font Library. + * Registers a new font collection in the font library. + * + * See {@link https://schemas.wp.org/trunk/font-collection.json} for the schema + * the font collection data must adhere to. * * @since 6.5.0 * - * @param string $slug Font collection slug. May only contain alphanumeric characters, dashes, + * @param string $slug Font collection slug. May only contain alphanumeric characters, dashes, * and underscores. See sanitize_title(). - * @param array|string $data_or_file { - * Font collection data array or a path/URL to a JSON file containing the font collection. - * - * @link https://schemas.wp.org/trunk/font-collection.json + * @param array $args { + * Font collection data. * - * @type string $name Required. Name of the font collection shown in the Font Library. - * @type string $description Optional. A short descriptive summary of the font collection. Default empty. - * @type array $font_families Required. Array of font family definitions that are in the collection. - * @type array $categories Optional. Array of categories, each with a name and slug, that are used by the - * fonts in the collection. Default empty. + * @type string $name Required. Name of the font collection shown in the Font Library. + * @type string $description Optional. A short descriptive summary of the font collection. Default empty. + * @type array|string $font_families Required. Array of font family definitions that are in the collection, + * or a string containing the path or URL to a JSON file containing the font collection. + * @type array $categories Optional. Array of categories, each with a name and slug, that are used by the + * fonts in the collection. Default empty. * } * @return WP_Font_Collection|WP_Error A font collection if it was registered * successfully, or WP_Error object on failure. */ - function wp_register_font_collection( $slug, $data_or_file ) { - return WP_Font_Library::get_instance()->register_font_collection( $slug, $data_or_file ); + function wp_register_font_collection( string $slug, array $args ) { + return WP_Font_Library::get_instance()->register_font_collection( $slug, $args ); } } @@ -148,7 +150,7 @@ function wp_register_font_collection( $slug, $data_or_file ) { * @param string $slug Font collection slug. * @return bool True if the font collection was unregistered successfully, else false. */ - function wp_unregister_font_collection( $slug ) { + function wp_unregister_font_collection( string $slug ) { return WP_Font_Library::get_instance()->unregister_font_collection( $slug ); } } @@ -157,7 +159,36 @@ function gutenberg_register_font_collections() { if ( null !== WP_Font_Library::get_instance()->get_font_collection( 'google-fonts' ) ) { return; } - wp_register_font_collection( 'google-fonts', 'https://s.w.org/images/fonts/17.7/collections/google-fonts-with-preview.json' ); + wp_register_font_collection( + 'google-fonts', + array( + 'name' => _x( 'Google Fonts', 'font collection name', 'gutenberg' ), + 'description' => __( 'Install from Google Fonts. Fonts are copied to and served from your site.', 'gutenberg' ), + 'font_families' => 'https://s.w.org/images/fonts/17.7/collections/google-fonts-with-preview.json', + 'categories' => array( + array( + 'name' => _x( 'Sans Serif', 'font category', 'gutenberg' ), + 'slug' => 'sans-serif', + ), + array( + 'name' => _x( 'Display', 'font category', 'gutenberg' ), + 'slug' => 'display', + ), + array( + 'name' => _x( 'Serif', 'font category', 'gutenberg' ), + 'slug' => 'serif', + ), + array( + 'name' => _x( 'Handwriting', 'font category', 'gutenberg' ), + 'slug' => 'handwriting', + ), + array( + 'name' => _x( 'Monospace', 'font category', 'gutenberg' ), + 'slug' => 'monospace', + ), + ), + ) + ); } add_action( 'init', 'gutenberg_register_font_collections', 11 ); diff --git a/package-lock.json b/package-lock.json index 9ca357997a7f5a..eb752483cecfd7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "17.7.0", + "version": "17.8.0-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "17.7.0", + "version": "17.8.0-rc.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54176,7 +54176,7 @@ }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "3.51.0", + "version": "3.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54189,7 +54189,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "2.51.1", + "version": "2.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54217,7 +54217,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "6.48.0", + "version": "6.49.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54230,7 +54230,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "3.51.0", + "version": "3.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54241,7 +54241,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "4.34.0", + "version": "4.35.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54253,7 +54253,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "5.35.0", + "version": "5.36.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54270,7 +54270,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "7.35.0", + "version": "7.36.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54293,13 +54293,13 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "4.42.0", + "version": "4.43.0", "dev": true, "license": "GPL-2.0-or-later" }, "packages/blob": { "name": "@wordpress/blob", - "version": "3.51.0", + "version": "3.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54310,7 +54310,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "4.28.1", + "version": "4.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54345,7 +54345,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "12.19.1", + "version": "12.20.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54441,7 +54441,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "8.28.1", + "version": "8.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54505,7 +54505,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "4.51.0", + "version": "4.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54516,7 +54516,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "4.51.0", + "version": "4.52.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -54528,7 +54528,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "12.28.1", + "version": "12.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54582,7 +54582,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "5.34.0", + "version": "5.35.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54591,7 +54591,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "0.22.1", + "version": "0.23.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54616,7 +54616,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "26.0.1", + "version": "27.0.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.3.12", @@ -54707,7 +54707,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "6.28.0", + "version": "6.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54743,7 +54743,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "0.20.1", + "version": "0.21.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54769,7 +54769,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "6.28.1", + "version": "6.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54813,7 +54813,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.35.0", + "version": "4.36.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54841,13 +54841,13 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "3.5.0", + "version": "3.6.0", "dev": true, "license": "GPL-2.0-or-later" }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "4.28.1", + "version": "4.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54884,7 +54884,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "9.21.0", + "version": "9.22.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54912,7 +54912,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "3.20.0", + "version": "3.21.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54929,7 +54929,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "0.5.1", + "version": "0.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.3.12", @@ -54990,7 +54990,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "4.51.0", + "version": "4.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55004,7 +55004,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "5.2.0", + "version": "5.3.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55019,7 +55019,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "3.51.0", + "version": "3.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55031,7 +55031,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "1.60.0", + "version": "1.61.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55049,7 +55049,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "3.51.0", + "version": "3.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55061,7 +55061,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "3.51.0", + "version": "3.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55072,7 +55072,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "10.22.0", + "version": "10.23.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55094,7 +55094,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "0.19.0", + "version": "0.20.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55117,7 +55117,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "7.22.0", + "version": "7.23.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55156,7 +55156,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "7.28.1", + "version": "7.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55204,7 +55204,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "5.28.1", + "version": "5.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55270,7 +55270,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "5.28.1", + "version": "5.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55313,7 +55313,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "13.28.1", + "version": "13.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55364,7 +55364,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "5.28.0", + "version": "5.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55382,7 +55382,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "9.3.0", + "version": "9.4.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55516,7 +55516,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "2.51.0", + "version": "2.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55527,7 +55527,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "17.8.0", + "version": "17.9.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55570,7 +55570,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "4.28.1", + "version": "4.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55597,7 +55597,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "3.51.0", + "version": "3.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55608,7 +55608,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "3.51.0", + "version": "3.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55619,7 +55619,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "4.51.0", + "version": "4.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55638,7 +55638,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "9.42.0", + "version": "9.43.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55651,7 +55651,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "5.0.0", + "version": "5.1.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.2.2", @@ -55664,7 +55664,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "1.1.0", + "version": "1.2.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/interactivity": "file:../interactivity" @@ -55724,7 +55724,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "5.28.1", + "version": "5.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55752,7 +55752,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "4.51.0", + "version": "4.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55763,7 +55763,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "7.22.0", + "version": "7.23.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55779,7 +55779,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "11.22.0", + "version": "11.23.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55796,7 +55796,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "6.22.0", + "version": "6.23.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55818,7 +55818,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "4.28.0", + "version": "4.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55836,7 +55836,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "3.51.0", + "version": "3.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55848,7 +55848,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "1.38.0", + "version": "1.39.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55862,7 +55862,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "4.28.1", + "version": "4.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55884,7 +55884,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "4.42.0", + "version": "4.43.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55899,7 +55899,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "4.19.0", + "version": "4.20.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55915,7 +55915,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "4.36.0", + "version": "4.37.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -55927,7 +55927,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "8.13.1", + "version": "8.14.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55950,7 +55950,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "1.12.1", + "version": "1.13.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55980,7 +55980,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "6.19.1", + "version": "6.20.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56002,7 +56002,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "4.35.0", + "version": "4.36.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -56018,7 +56018,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "5.34.0", + "version": "5.35.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -56030,7 +56030,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "3.28.1", + "version": "3.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56055,7 +56055,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "1.43.0", + "version": "1.44.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56067,7 +56067,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "3.8.0", + "version": "3.9.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -56079,7 +56079,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "3.49.0", + "version": "3.50.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56092,7 +56092,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "2.51.0", + "version": "2.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56104,7 +56104,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "0.33.0", + "version": "0.34.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -56115,7 +56115,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "1.50.0", + "version": "1.51.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -56128,7 +56128,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "3.49.0", + "version": "3.50.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56276,7 +56276,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "2.34.0", + "version": "2.35.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -56288,7 +56288,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "4.51.0", + "version": "4.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56332,7 +56332,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "4.28.1", + "version": "4.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56358,7 +56358,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "6.28.1", + "version": "6.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56382,7 +56382,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "0.20.0", + "version": "0.21.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56400,7 +56400,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "27.2.0", + "version": "27.3.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -56622,7 +56622,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "4.28.1", + "version": "4.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56647,7 +56647,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "3.51.0", + "version": "3.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56659,7 +56659,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "1.34.0", + "version": "1.35.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56671,7 +56671,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "21.34.0", + "version": "21.35.0", "dev": true, "license": "MIT", "dependencies": { @@ -56687,7 +56687,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "0.13.0", + "version": "0.14.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56707,7 +56707,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "2.51.0", + "version": "2.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -56718,7 +56718,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "0.11.0", + "version": "0.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56730,7 +56730,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "3.52.0", + "version": "3.53.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56742,7 +56742,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "5.28.0", + "version": "5.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56759,7 +56759,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "2.51.0", + "version": "2.52.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=12" @@ -56767,7 +56767,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "3.28.1", + "version": "3.29.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -56791,7 +56791,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "3.51.0", + "version": "3.52.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" diff --git a/package.json b/package.json index b54be23041128f..467d5b44a5d5f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "17.7.0", + "version": "17.8.0-rc.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 21ff2989058194..b55b3424c5c47b 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.52.0 (2024-02-21) + ## 3.51.0 (2024-02-09) ## 3.50.0 (2024-01-24) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index c93ceb7ae55e7e..18622e22ad8c28 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "3.51.0", + "version": "3.52.0", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md index e475705c4dc561..3da67470f7677d 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.52.0 (2024-02-21) + ## 2.51.0 (2024-02-09) ## 2.50.0 (2024-01-24) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 1257778703aa18..b92beeb7f99d59 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "2.51.1", + "version": "2.52.0", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md index 7746db7508cee1..317daffd26fa8e 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.49.0 (2024-02-21) + ## 6.48.0 (2024-02-09) ## 6.47.0 (2024-01-24) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 65ba4fc9897514..0b5da9906e6327 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "6.48.0", + "version": "6.49.0", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index e5fd1e245d2846..521bab1f64f2a2 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.52.0 (2024-02-21) + ## 3.51.0 (2024-02-09) ## 3.50.0 (2024-01-24) diff --git a/packages/autop/package.json b/packages/autop/package.json index 102e20235fd96d..44c9f8585ee3d8 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "3.51.0", + "version": "3.52.0", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index 046380922e9662..c0e414b2158408 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.35.0 (2024-02-21) + ## 4.34.0 (2024-02-09) ## 4.33.0 (2024-01-24) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index 0a066c01db3987..399732060884e2 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "4.34.0", + "version": "4.35.0", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md index f27508610e1325..700ae9d80c6a5d 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.36.0 (2024-02-21) + ## 5.35.0 (2024-02-09) ## 5.34.0 (2024-01-24) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index d467854c25f0ca..61ff6931337908 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "5.35.0", + "version": "5.36.0", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index 0f472e67287302..344222a17330db 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.36.0 (2024-02-21) + ## 7.35.0 (2024-02-09) ## 7.34.0 (2024-01-24) diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 44fbed125a7a12..4cdb41058f60a3 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "7.35.0", + "version": "7.36.0", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md index 56b393a140851c..488a598d7df5b0 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.43.0 (2024-02-21) + ## 4.42.0 (2024-02-09) ## 4.41.0 (2024-01-24) diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 93df4497445423..17bb579e4c8c9f 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "4.42.0", + "version": "4.43.0", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index 5cb62e3734bfa4..2dccf51fe6cde3 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.52.0 (2024-02-21) + ## 3.51.0 (2024-02-09) ## 3.50.0 (2024-01-24) diff --git a/packages/blob/package.json b/packages/blob/package.json index b8f073003d1be8..333ed8ab3f6ed2 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "3.51.0", + "version": "3.52.0", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md index 547bc80bee02b2..0e7476075781cc 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.29.0 (2024-02-21) + ## 4.28.0 (2024-02-09) ## 4.27.0 (2024-01-24) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index d892e359511938..24112ce327346b 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "4.28.1", + "version": "4.29.0", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index c19c025bf17ae2..2ce86bdec8e1db 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.20.0 (2024-02-21) + ## 12.19.0 (2024-02-09) - `FontSizePicker`: Remove deprecated `__nextHasNoMarginBottom` prop and promote to default behavior ([#58702](https://github.com/WordPress/gutenberg/pull/58702)). diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index fcc36c14a09d06..971613a0586b75 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "12.19.1", + "version": "12.20.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/src/components/block-actions/index.js b/packages/block-editor/src/components/block-actions/index.js index 5d942d2b25c708..760f0f4daabde9 100644 --- a/packages/block-editor/src/components/block-actions/index.js +++ b/packages/block-editor/src/components/block-actions/index.js @@ -20,42 +20,55 @@ export default function BlockActions( { children, __experimentalUpdateSelection: updateSelection, } ) { - const { - canInsertBlockType, - getBlockRootClientId, - getBlocksByClientId, - canMoveBlocks, - canRemoveBlocks, - } = useSelect( blockEditorStore ); const { getDefaultBlockName, getGroupingBlockName } = useSelect( blocksStore ); - - const blocks = getBlocksByClientId( clientIds ); - const rootClientId = getBlockRootClientId( clientIds[ 0 ] ); - - const canCopyStyles = blocks.every( ( block ) => { - return ( - !! block && - ( hasBlockSupport( block.name, 'color' ) || - hasBlockSupport( block.name, 'typography' ) ) - ); - } ); - - const canDuplicate = blocks.every( ( block ) => { - return ( - !! block && - hasBlockSupport( block.name, 'multiple', true ) && - canInsertBlockType( block.name, rootClientId ) - ); - } ); - - const canInsertDefaultBlock = canInsertBlockType( - getDefaultBlockName(), - rootClientId + const selected = useSelect( + ( select ) => { + const { + canInsertBlockType, + getBlockRootClientId, + getBlocksByClientId, + getDirectInsertBlock, + canMoveBlocks, + canRemoveBlocks, + } = select( blockEditorStore ); + + const blocks = getBlocksByClientId( clientIds ); + const rootClientId = getBlockRootClientId( clientIds[ 0 ] ); + const canInsertDefaultBlock = canInsertBlockType( + getDefaultBlockName(), + rootClientId + ); + const directInsertBlock = rootClientId + ? getDirectInsertBlock( rootClientId ) + : null; + + return { + canMove: canMoveBlocks( clientIds, rootClientId ), + canRemove: canRemoveBlocks( clientIds, rootClientId ), + canInsertBlock: canInsertDefaultBlock || !! directInsertBlock, + canCopyStyles: blocks.every( ( block ) => { + return ( + !! block && + ( hasBlockSupport( block.name, 'color' ) || + hasBlockSupport( block.name, 'typography' ) ) + ); + } ), + canDuplicate: blocks.every( ( block ) => { + return ( + !! block && + hasBlockSupport( block.name, 'multiple', true ) && + canInsertBlockType( block.name, rootClientId ) + ); + } ), + }; + }, + [ clientIds, getDefaultBlockName ] ); + const { getBlocksByClientId, getBlocks } = useSelect( blockEditorStore ); - const canMove = canMoveBlocks( clientIds, rootClientId ); - const canRemove = canRemoveBlocks( clientIds, rootClientId ); + const { canMove, canRemove, canInsertBlock, canCopyStyles, canDuplicate } = + selected; const { removeBlocks, @@ -75,11 +88,9 @@ export default function BlockActions( { return children( { canCopyStyles, canDuplicate, - canInsertDefaultBlock, + canInsertBlock, canMove, canRemove, - rootClientId, - blocks, onDuplicate() { return duplicateBlocks( clientIds, updateSelection ); }, @@ -104,14 +115,17 @@ export default function BlockActions( { setBlockMovingClientId( clientIds[ 0 ] ); }, onGroup() { - if ( ! blocks.length ) { + if ( ! clientIds.length ) { return; } const groupingBlockName = getGroupingBlockName(); // Activate the `transform` on `core/group` which does the conversion. - const newBlocks = switchToBlockType( blocks, groupingBlockName ); + const newBlocks = switchToBlockType( + getBlocksByClientId( clientIds ), + groupingBlockName + ); if ( ! newBlocks ) { return; @@ -119,12 +133,11 @@ export default function BlockActions( { replaceBlocks( clientIds, newBlocks ); }, onUngroup() { - if ( ! blocks.length ) { + if ( ! clientIds.length ) { return; } - const innerBlocks = blocks[ 0 ].innerBlocks; - + const innerBlocks = getBlocks( clientIds[ 0 ] ); if ( ! innerBlocks.length ) { return; } @@ -132,16 +145,13 @@ export default function BlockActions( { replaceBlocks( clientIds, innerBlocks ); }, onCopy() { - const selectedBlockClientIds = blocks.map( - ( { clientId } ) => clientId - ); - if ( blocks.length === 1 ) { - flashBlock( selectedBlockClientIds[ 0 ] ); + if ( clientIds.length === 1 ) { + flashBlock( clientIds[ 0 ] ); } - notifyCopy( 'copy', selectedBlockClientIds ); + notifyCopy( 'copy', clientIds ); }, async onPasteStyles() { - await pasteStyles( blocks ); + await pasteStyles( getBlocksByClientId( clientIds ) ); }, } ); } diff --git a/packages/block-editor/src/components/block-popover/cover.js b/packages/block-editor/src/components/block-popover/cover.js new file mode 100644 index 00000000000000..6d2d5b8ce1ac03 --- /dev/null +++ b/packages/block-editor/src/components/block-popover/cover.js @@ -0,0 +1,63 @@ +/** + * WordPress dependencies + */ +import { useEffect, useState, useMemo, forwardRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs'; +import BlockPopover from '.'; + +function BlockPopoverCover( + { clientId, bottomClientId, children, shift = false, ...props }, + ref +) { + bottomClientId ??= clientId; + + const selectedElement = useBlockElement( clientId ); + + return ( + + { selectedElement && clientId === bottomClientId ? ( + + { children } + + ) : ( + children + ) } + + ); +} + +function CoverContainer( { selectedElement, children } ) { + const [ width, setWidth ] = useState( selectedElement.offsetWidth ); + const [ height, setHeight ] = useState( selectedElement.offsetHeight ); + + useEffect( () => { + const observer = new window.ResizeObserver( () => { + setWidth( selectedElement.offsetWidth ); + setHeight( selectedElement.offsetHeight ); + } ); + observer.observe( selectedElement, { box: 'border-box' } ); + return () => observer.disconnect(); + }, [ selectedElement ] ); + + const style = useMemo( () => { + return { + position: 'absolute', + width, + height, + }; + }, [ width, height ] ); + + return
{ children }
; +} + +export default forwardRef( BlockPopoverCover ); diff --git a/packages/block-editor/src/components/block-popover/drop-zone.js b/packages/block-editor/src/components/block-popover/drop-zone.js index c26f28127022d6..1174c619cb3f43 100644 --- a/packages/block-editor/src/components/block-popover/drop-zone.js +++ b/packages/block-editor/src/components/block-popover/drop-zone.js @@ -9,7 +9,7 @@ import { __unstableMotion as motion } from '@wordpress/components'; * Internal dependencies */ import { store as blockEditorStore } from '../../store'; -import BlockPopover from './index'; +import BlockPopoverCover from './cover'; const animateVariants = { hide: { opacity: 0, scaleY: 0.75 }, @@ -38,9 +38,8 @@ function BlockDropZonePopover( { const reducedMotion = useReducedMotion(); return ( - - + ); } diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 13e6ba4d9e7f81..d5ac90c68745ec 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -28,8 +28,6 @@ function BlockPopover( clientId, bottomClientId, children, - __unstableRefreshSize, - __unstableCoverTarget = false, __unstablePopoverSlot, __unstableContentRef, shift = true, @@ -75,30 +73,6 @@ function BlockPopover( }; }, [ selectedElement ] ); - const style = useMemo( () => { - if ( - // popoverDimensionsRecomputeCounter is by definition always equal or greater - // than 0. This check is only there to satisfy the correctness of the - // exhaustive-deps rule for the `useMemo` hook. - popoverDimensionsRecomputeCounter < 0 || - ! selectedElement || - lastSelectedElement !== selectedElement - ) { - return {}; - } - - return { - position: 'absolute', - width: selectedElement.offsetWidth, - height: selectedElement.offsetHeight, - }; - }, [ - selectedElement, - lastSelectedElement, - __unstableRefreshSize, - popoverDimensionsRecomputeCounter, - ] ); - const popoverAnchor = useMemo( () => { if ( // popoverDimensionsRecomputeCounter is by definition always equal or greater @@ -176,8 +150,7 @@ function BlockPopover( ) } variant="unstyled" > - { __unstableCoverTarget &&
{ children }
} - { ! __unstableCoverTarget && children } + { children } ); } diff --git a/packages/block-editor/src/components/block-removal-warning-modal/index.js b/packages/block-editor/src/components/block-removal-warning-modal/index.js index 167f87654259f8..fca8098c4cd398 100644 --- a/packages/block-editor/src/components/block-removal-warning-modal/index.js +++ b/packages/block-editor/src/components/block-removal-warning-modal/index.js @@ -8,7 +8,7 @@ import { Button, __experimentalHStack as HStack, } from '@wordpress/components'; -import { __, _n } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -17,10 +17,9 @@ import { store as blockEditorStore } from '../../store'; import { unlock } from '../../lock-unlock'; export function BlockRemovalWarningModal( { rules } ) { - const { clientIds, selectPrevious, blockNamesForPrompt, messageType } = - useSelect( ( select ) => - unlock( select( blockEditorStore ) ).getRemovalPromptData() - ); + const { clientIds, selectPrevious, message } = useSelect( ( select ) => + unlock( select( blockEditorStore ) ).getRemovalPromptData() + ); const { clearBlockRemovalPrompt, @@ -37,23 +36,10 @@ export function BlockRemovalWarningModal( { rules } ) { }; }, [ rules, setBlockRemovalRules ] ); - if ( ! blockNamesForPrompt ) { + if ( ! message ) { return; } - const message = - messageType === 'templates' - ? _n( - 'Deleting this block will stop your post or page content from displaying on this template. It is not recommended.', - 'Deleting these blocks will stop your post or page content from displaying on this template. It is not recommended.', - blockNamesForPrompt.length - ) - : _n( - 'Deleting this block could break patterns on your site that have content linked to it. Are you sure you want to delete it?', - 'Deleting these blocks could break patterns on your site that have content linked to them. Are you sure you want to delete them?', - blockNamesForPrompt.length - ); - const onConfirmRemoval = () => { privateRemoveBlocks( clientIds, selectPrevious, /* force */ true ); clearBlockRemovalPrompt(); diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index ae28ca6e5bad97..f3d22e6557a674 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -33,8 +33,12 @@ const POPOVER_PROPS = { placement: 'bottom-start', }; -function CopyMenuItem( { blocks, onCopy, label } ) { - const ref = useCopyToClipboard( () => serialize( blocks ), onCopy ); +function CopyMenuItem( { clientIds, onCopy, label } ) { + const { getBlocksByClientId } = useSelect( blockEditorStore ); + const ref = useCopyToClipboard( + () => serialize( getBlocksByClientId( clientIds ) ), + onCopy + ); const copyMenuItemLabel = label ? label : __( 'Copy' ); return { copyMenuItemLabel }; } @@ -198,7 +202,7 @@ export function BlockSettingsDropdown( { { ( { canCopyStyles, canDuplicate, - canInsertDefaultBlock, + canInsertBlock, canMove, canRemove, onDuplicate, @@ -208,7 +212,6 @@ export function BlockSettingsDropdown( { onCopy, onPasteStyles, onMoveTo, - blocks, } ) => ( ) } { canDuplicate && ( @@ -301,7 +304,7 @@ export function BlockSettingsDropdown( { { __( 'Duplicate' ) } ) } - { canInsertDefaultBlock && ( + { canInsertBlock && ( <> diff --git a/packages/block-editor/src/components/block-tools/empty-block-inserter.js b/packages/block-editor/src/components/block-tools/empty-block-inserter.js index 1d520ed72b1c69..bf708c686363ff 100644 --- a/packages/block-editor/src/components/block-tools/empty-block-inserter.js +++ b/packages/block-editor/src/components/block-tools/empty-block-inserter.js @@ -6,7 +6,7 @@ import classnames from 'classnames'; /** * Internal dependencies */ -import BlockPopover from '../block-popover'; +import BlockPopoverCover from '../block-popover/cover'; import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; import Inserter from '../inserter'; import useSelectedBlockToolProps from './use-selected-block-tool-props'; @@ -28,9 +28,8 @@ export default function EmptyBlockInserter( { } ); return ( -
@@ -51,6 +48,6 @@ export default function EmptyBlockInserter( { __experimentalIsQuick />
-
+ ); } diff --git a/packages/block-editor/src/components/colors-gradients/control.js b/packages/block-editor/src/components/colors-gradients/control.js index 5a1cda78f86683..946b5dd486b042 100644 --- a/packages/block-editor/src/components/colors-gradients/control.js +++ b/packages/block-editor/src/components/colors-gradients/control.js @@ -133,7 +133,7 @@ function ColorGradientControlInner( { { canChooseAColor && canChooseAGradient && (
) } { tabs.length > 1 && ( - + { tabs.map( ( tab ) => ( - + { tabs.map( ( tab ) => ( + select( preferencesStore ).get( 'core', 'showIconLabels' ), + [] + ); + // Avoid fetching if rich previews are not desired. const showRichPreviews = hasRichPreviews ? value?.url : null; @@ -139,7 +146,7 @@ export default function LinkPreview( { label={ sprintf( // Translators: %s is a placeholder for the link URL and an optional colon, (if a Link URL is present). __( 'Copy link%s' ), // Ends up looking like "Copy link: https://example.com". - isEmptyURL ? '' : ': ' + value.url + isEmptyURL || showIconLabels ? '' : ': ' + value.url ) } ref={ ref } disabled={ isEmptyURL } diff --git a/packages/block-editor/src/components/link-control/style.scss b/packages/block-editor/src/components/link-control/style.scss index 425df96ab31fa6..9531ad6f0c7a09 100644 --- a/packages/block-editor/src/components/link-control/style.scss +++ b/packages/block-editor/src/components/link-control/style.scss @@ -34,6 +34,15 @@ $block-editor-link-control-number-of-actions: 1; content: attr(aria-label); } } + + .block-editor-link-control__search-item-top { + gap: $grid-unit-10; + + .components-button.has-icon { + min-width: inherit; + width: min-content; + } + } } } diff --git a/packages/block-editor/src/components/resizable-box-popover/index.js b/packages/block-editor/src/components/resizable-box-popover/index.js index 12a61aceaaf38e..8a49c1631287a1 100644 --- a/packages/block-editor/src/components/resizable-box-popover/index.js +++ b/packages/block-editor/src/components/resizable-box-popover/index.js @@ -6,7 +6,7 @@ import { ResizableBox } from '@wordpress/components'; /** * Internal dependencies */ -import BlockPopover from '../block-popover'; +import BlockPopoverCover from '../block-popover/cover'; export default function ResizableBoxPopover( { clientId, @@ -14,14 +14,12 @@ export default function ResizableBoxPopover( { ...props } ) { return ( - - + ); } diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index deafde69b35c37..01753ceda4728e 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -109,6 +109,7 @@ export function RichTextWrapper( __unstableDisableFormats: disableFormats, disableLineBreaks, __unstableAllowPrefixTransformations, + disableEditing, ...props }, forwardedRef @@ -147,7 +148,7 @@ export function RichTextWrapper( } // Disable Rich Text editing if block bindings specify that. - let shouldDisableEditing = false; + let disableBoundBlocks = false; if ( blockBindings && blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS ) { const blockTypeAttributes = getBlockType( blockName ).attributes; const { getBlockBindingsSource } = unlock( @@ -170,7 +171,7 @@ export function RichTextWrapper( ! blockBindingsSource || blockBindingsSource.lockAttributesEditing ) { - shouldDisableEditing = true; + disableBoundBlocks = true; break; } } @@ -180,16 +181,19 @@ export function RichTextWrapper( selectionStart: isSelected ? selectionStart.offset : undefined, selectionEnd: isSelected ? selectionEnd.offset : undefined, isSelected, - shouldDisableEditing, + disableBoundBlocks, }; }; - const { selectionStart, selectionEnd, isSelected, shouldDisableEditing } = + const { selectionStart, selectionEnd, isSelected, disableBoundBlocks } = useSelect( selector, [ clientId, identifier, originalIsSelected, isBlockSelected, ] ); + + const shouldDisableEditing = disableEditing || disableBoundBlocks; + const { getSelectionStart, getSelectionEnd, getBlockRootClientId } = useSelect( blockEditorStore ); const { selectionChange } = useDispatch( blockEditorStore ); @@ -441,19 +445,34 @@ export function RichTextWrapper( ); } -const ForwardedRichTextContainer = withDeprecations( +// This is the private API for the RichText component. +// It allows access to all props, not just the public ones. +export const PrivateRichText = withDeprecations( forwardRef( RichTextWrapper ) ); -ForwardedRichTextContainer.Content = Content; -ForwardedRichTextContainer.isEmpty = ( value ) => { +PrivateRichText.Content = Content; +PrivateRichText.isEmpty = ( value ) => { return ! value || value.length === 0; }; +// This is the public API for the RichText component. +// We wrap the PrivateRichText component to hide some props from the public API. /** * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/rich-text/README.md */ -export default ForwardedRichTextContainer; +const PublicForwardedRichTextContainer = forwardRef( ( props, ref ) => { + return ( + + ); +} ); + +PublicForwardedRichTextContainer.Content = Content; +PublicForwardedRichTextContainer.isEmpty = ( value ) => { + return ! value || value.length === 0; +}; + +export default PublicForwardedRichTextContainer; export { RichTextShortcut } from './shortcut'; export { RichTextToolbarButton } from './toolbar-button'; export { __unstableRichTextInputEvent } from './input-event'; diff --git a/packages/block-editor/src/hooks/margin.js b/packages/block-editor/src/hooks/margin.js index 8f723b3f8c97de..7be1179d295100 100644 --- a/packages/block-editor/src/hooks/margin.js +++ b/packages/block-editor/src/hooks/margin.js @@ -7,7 +7,7 @@ import isShallowEqual from '@wordpress/is-shallow-equal'; /** * Internal dependencies */ -import BlockPopover from '../components/block-popover'; +import BlockPopoverCover from '../components/block-popover/cover'; import { __unstableUseBlockElement as useBlockElement } from '../components/block-list/use-block-props/use-block-refs'; function getComputedCSS( element, property ) { @@ -78,14 +78,11 @@ export function MarginVisualizer( { clientId, attributes, forceShow } ) { } return ( -
- + ); } diff --git a/packages/block-editor/src/hooks/padding.js b/packages/block-editor/src/hooks/padding.js index ca4436153d122c..50eed7ac05d5e9 100644 --- a/packages/block-editor/src/hooks/padding.js +++ b/packages/block-editor/src/hooks/padding.js @@ -7,7 +7,7 @@ import isShallowEqual from '@wordpress/is-shallow-equal'; /** * Internal dependencies */ -import BlockPopover from '../components/block-popover'; +import BlockPopoverCover from '../components/block-popover/cover'; import { __unstableUseBlockElement as useBlockElement } from '../components/block-list/use-block-props/use-block-refs'; function getComputedCSS( element, property ) { @@ -69,14 +69,11 @@ export function PaddingVisualizer( { clientId, value, forceShow } ) { } return ( -
- + ); } diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 220aa5f4127270..ec6843ead24895 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -27,6 +27,7 @@ import { ExperimentalBlockCanvas } from './components/block-canvas'; import { getDuotoneFilter } from './components/duotone/utils'; import { useFlashEditableBlocks } from './components/use-flash-editable-blocks'; import { selectBlockPatternsKey } from './store/private-keys'; +import { PrivateRichText } from './components/rich-text/'; /** * Private @wordpress/block-editor APIs. @@ -58,4 +59,5 @@ lock( privateApis, { usesContextKey, useFlashEditableBlocks, selectBlockPatternsKey, + PrivateRichText, } ); diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 33c76bd2f6e4cf..018c9ff9115185 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1539,7 +1539,7 @@ export const duplicateBlocks = }; /** - * Action that inserts an empty block before a given block. + * Action that inserts a default block before a given block. * * @param {string} clientId */ @@ -1555,16 +1555,34 @@ export const insertBeforeBlock = return; } - const firstSelectedIndex = select.getBlockIndex( clientId ); - return dispatch.insertDefaultBlock( - {}, - rootClientId, - firstSelectedIndex - ); + const blockIndex = select.getBlockIndex( clientId ); + const directInsertBlock = rootClientId + ? select.getDirectInsertBlock( rootClientId ) + : null; + + if ( ! directInsertBlock ) { + return dispatch.insertDefaultBlock( {}, rootClientId, blockIndex ); + } + + const copiedAttributes = {}; + if ( directInsertBlock.attributesToCopy ) { + const attributes = select.getBlockAttributes( clientId ); + directInsertBlock.attributesToCopy.forEach( ( key ) => { + if ( attributes[ key ] ) { + copiedAttributes[ key ] = attributes[ key ]; + } + } ); + } + + const block = createBlock( directInsertBlock.name, { + ...directInsertBlock.attributes, + ...copiedAttributes, + } ); + return dispatch.insertBlock( block, blockIndex, rootClientId ); }; /** - * Action that inserts an empty block after a given block. + * Action that inserts a default block after a given block. * * @param {string} clientId */ @@ -1580,12 +1598,34 @@ export const insertAfterBlock = return; } - const firstSelectedIndex = select.getBlockIndex( clientId ); - return dispatch.insertDefaultBlock( - {}, - rootClientId, - firstSelectedIndex + 1 - ); + const blockIndex = select.getBlockIndex( clientId ); + const directInsertBlock = rootClientId + ? select.getDirectInsertBlock( rootClientId ) + : null; + + if ( ! directInsertBlock ) { + return dispatch.insertDefaultBlock( + {}, + rootClientId, + blockIndex + 1 + ); + } + + const copiedAttributes = {}; + if ( directInsertBlock.attributesToCopy ) { + const attributes = select.getBlockAttributes( clientId ); + directInsertBlock.attributesToCopy.forEach( ( key ) => { + if ( attributes[ key ] ) { + copiedAttributes[ key ] = attributes[ key ]; + } + } ); + } + + const block = createBlock( directInsertBlock.name, { + ...directInsertBlock.attributes, + ...copiedAttributes, + } ); + return dispatch.insertBlock( block, blockIndex + 1, rootClientId ); }; /** diff --git a/packages/block-editor/src/store/private-actions.js b/packages/block-editor/src/store/private-actions.js index ae0a06152fb933..606cd01228204f 100644 --- a/packages/block-editor/src/store/private-actions.js +++ b/packages/block-editor/src/store/private-actions.js @@ -123,61 +123,36 @@ export const privateRemoveBlocks = // // @see https://github.com/WordPress/gutenberg/pull/51145 const rules = ! forceRemove && select.getBlockRemovalRules(); - if ( rules ) { - const blockNamesForPrompt = new Set(); - - // Given a list of client IDs of blocks that the user intended to - // remove, perform a tree search (BFS) to find all block names - // corresponding to "important" blocks, i.e. blocks that require a - // removal prompt. - const queue = [ ...clientIds ]; - let messageType = 'templates'; - while ( queue.length ) { - const clientId = queue.shift(); - const blockName = select.getBlockName( clientId ); - if ( rules[ blockName ] ) { - blockNamesForPrompt.add( blockName ); - } - if ( rules[ 'bindings/core/pattern-overrides' ] ) { - const parentPatternBlocks = - select.getBlockParentsByBlockName( - clientId, - 'core/block' - ); - // We only need to run this check when editing the original pattern, not pattern instances. - if ( parentPatternBlocks?.length > 0 ) { - continue; - } - const blockAttributes = - select.getBlockAttributes( clientId ); - if ( - blockAttributes?.metadata?.bindings && - JSON.stringify( - blockAttributes.metadata.bindings - ).includes( 'core/pattern-overrides' ) - ) { - blockNamesForPrompt.add( blockName ); - messageType = 'patternOverrides'; - } + if ( rules ) { + function flattenBlocks( blocks ) { + const result = []; + const stack = [ ...blocks ]; + while ( stack.length ) { + const { innerBlocks, ...block } = stack.shift(); + stack.push( ...innerBlocks ); + result.push( block ); } - - const innerBlocks = select.getBlockOrder( clientId ); - queue.push( ...innerBlocks ); + return result; } - // If any such blocks were found, trigger the removal prompt and - // skip any other steps (thus postponing actual removal). - if ( blockNamesForPrompt.size ) { - dispatch( - displayBlockRemovalPrompt( - clientIds, - selectPrevious, - Array.from( blockNamesForPrompt ), - messageType - ) - ); - return; + const blockList = clientIds.map( select.getBlock ); + const flattenedBlocks = flattenBlocks( blockList ); + + // Find the first message and use it. + let message; + for ( const rule of rules ) { + message = rule.callback( flattenedBlocks ); + if ( message ) { + dispatch( + displayBlockRemovalPrompt( + clientIds, + selectPrevious, + message + ) + ); + return; + } } } @@ -228,31 +203,21 @@ export const ensureDefaultBlock = * * Contrast with `setBlockRemovalRules`. * - * @param {string|string[]} clientIds Client IDs of blocks to remove. - * @param {boolean} selectPrevious True if the previous block - * or the immediate parent - * (if no previous block exists) - * should be selected - * when a block is removed. - * @param {string[]} blockNamesForPrompt Names of the blocks that - * triggered the need for - * confirmation before removal. - * @param {string} messageType The type of message to display. + * @param {string|string[]} clientIds Client IDs of blocks to remove. + * @param {boolean} selectPrevious True if the previous block or the + * immediate parent (if no previous + * block exists) should be selected + * when a block is removed. + * @param {string} message Message to display in the prompt. * * @return {Object} Action object. */ -function displayBlockRemovalPrompt( - clientIds, - selectPrevious, - blockNamesForPrompt, - messageType -) { +function displayBlockRemovalPrompt( clientIds, selectPrevious, message ) { return { type: 'DISPLAY_BLOCK_REMOVAL_PROMPT', clientIds, selectPrevious, - blockNamesForPrompt, - messageType, + message, }; } diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 1b535e51950164..33678f64905d69 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1521,17 +1521,11 @@ export function isSelectionEnabled( state = true, action ) { function removalPromptData( state = false, action ) { switch ( action.type ) { case 'DISPLAY_BLOCK_REMOVAL_PROMPT': - const { - clientIds, - selectPrevious, - blockNamesForPrompt, - messageType, - } = action; + const { clientIds, selectPrevious, message } = action; return { clientIds, selectPrevious, - blockNamesForPrompt, - messageType, + message, }; case 'CLEAR_BLOCK_REMOVAL_PROMPT': return false; diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index 53b6aa54f5b1d6..5daeff9249064f 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.29.0 (2024-02-21) + ## 8.28.0 (2024-02-09) ## 8.27.0 (2024-01-24) diff --git a/packages/block-library/package.json b/packages/block-library/package.json index b27704fcd52fb7..c899051ca4e694 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "8.28.1", + "version": "8.29.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/src/buttons/transforms.js b/packages/block-library/src/buttons/transforms.js index 3e89b4973e3728..9848299f3a99f9 100644 --- a/packages/block-library/src/buttons/transforms.js +++ b/packages/block-library/src/buttons/transforms.js @@ -4,6 +4,11 @@ import { createBlock } from '@wordpress/blocks'; import { __unstableCreateElement as createElement } from '@wordpress/rich-text'; +/** + * Internal dependencies + */ +import { getTransformedMetadata } from '../utils/get-transformed-metadata'; + const transforms = { from: [ { @@ -33,10 +38,8 @@ const transforms = { {}, // Loop the selected buttons. buttons.map( ( attributes ) => { - const element = createElement( - document, - attributes.content - ); + const { content, metadata } = attributes; + const element = createElement( document, content ); // Remove any HTML tags. const text = element.innerText || ''; // Get first url. @@ -46,6 +49,13 @@ const transforms = { return createBlock( 'core/button', { text, url, + metadata: getTransformedMetadata( + metadata, + 'core/button', + ( { content: contentBinding } ) => ( { + text: contentBinding, + } ) + ), } ); } ) ), diff --git a/packages/block-library/src/code/transforms.js b/packages/block-library/src/code/transforms.js index af6d4686af8122..e537db342b8d5c 100644 --- a/packages/block-library/src/code/transforms.js +++ b/packages/block-library/src/code/transforms.js @@ -4,6 +4,11 @@ import { createBlock } from '@wordpress/blocks'; import { create, toHTMLString } from '@wordpress/rich-text'; +/** + * Internal dependencies + */ +import { getTransformedMetadata } from '../utils/get-transformed-metadata'; + const transforms = { from: [ { @@ -14,17 +19,21 @@ const transforms = { { type: 'block', blocks: [ 'core/paragraph' ], - transform: ( { content } ) => - createBlock( 'core/code', { content } ), + transform: ( { content, metadata } ) => + createBlock( 'core/code', { + content, + metadata: getTransformedMetadata( metadata, 'core/code' ), + } ), }, { type: 'block', blocks: [ 'core/html' ], - transform: ( { content: text } ) => { + transform: ( { content: text, metadata } ) => { return createBlock( 'core/code', { // The HTML is plain text (with plain line breaks), so // convert it to rich text. content: toHTMLString( { value: create( { text } ) } ), + metadata: getTransformedMetadata( metadata, 'core/code' ), } ); }, }, @@ -51,8 +60,14 @@ const transforms = { { type: 'block', blocks: [ 'core/paragraph' ], - transform: ( { content } ) => - createBlock( 'core/paragraph', { content } ), + transform: ( { content, metadata } ) => + createBlock( 'core/paragraph', { + content, + metadata: getTransformedMetadata( + metadata, + 'core/paragraph' + ), + } ), }, ], }; diff --git a/packages/block-library/src/cover/edit/resizable-cover-popover.js b/packages/block-library/src/cover/edit/resizable-cover-popover.js index 7db8b0cc50b883..64d1bf106c3bc9 100644 --- a/packages/block-library/src/cover/edit/resizable-cover-popover.js +++ b/packages/block-library/src/cover/edit/resizable-cover-popover.js @@ -6,7 +6,7 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { useMemo, useState } from '@wordpress/element'; +import { useState } from '@wordpress/element'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; /** @@ -40,10 +40,6 @@ export default function ResizableCoverPopover( { ...props } ) { const [ isResizing, setIsResizing ] = useState( false ); - const dimensions = useMemo( - () => ( { height, minHeight, width } ), - [ minHeight, height, width ] - ); const resizableBoxProps = { className: classnames( className, { 'is-resizing': isResizing } ), @@ -75,7 +71,6 @@ export default function ResizableCoverPopover( { return ( diff --git a/packages/block-library/src/heading/transforms.js b/packages/block-library/src/heading/transforms.js index a4db7884620963..f040ff06e37e86 100644 --- a/packages/block-library/src/heading/transforms.js +++ b/packages/block-library/src/heading/transforms.js @@ -7,6 +7,7 @@ import { createBlock, getBlockAttributes } from '@wordpress/blocks'; * Internal dependencies */ import { getLevelFromHeadingNodeName } from './shared'; +import { getTransformedMetadata } from '../utils/get-transformed-metadata'; const transforms = { from: [ @@ -15,12 +16,20 @@ const transforms = { isMultiBlock: true, blocks: [ 'core/paragraph' ], transform: ( attributes ) => - attributes.map( ( { content, anchor, align: textAlign } ) => - createBlock( 'core/heading', { - content, - anchor, - textAlign, - } ) + attributes.map( + ( { content, anchor, align: textAlign, metadata } ) => + createBlock( 'core/heading', { + content, + anchor, + textAlign, + metadata: getTransformedMetadata( + metadata, + 'core/heading', + ( { content: contentBinding } ) => ( { + content: contentBinding, + } ) + ), + } ) ), }, { @@ -82,8 +91,18 @@ const transforms = { isMultiBlock: true, blocks: [ 'core/paragraph' ], transform: ( attributes ) => - attributes.map( ( { content, textAlign: align } ) => - createBlock( 'core/paragraph', { content, align } ) + attributes.map( ( { content, textAlign: align, metadata } ) => + createBlock( 'core/paragraph', { + content, + align, + metadata: getTransformedMetadata( + metadata, + 'core/paragraph', + ( { content: contentBinding } ) => ( { + content: contentBinding, + } ) + ), + } ) ), }, ], diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index a0d481681ee934..eecb4da72b9ce6 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -411,6 +411,7 @@ export default function Image( { lockHrefControls = false, lockAltControls = false, lockTitleControls = false, + lockCaption = false, } = useSelect( ( select ) => { if ( ! isSingleSelected ) { @@ -444,6 +445,10 @@ export default function Image( { // Disable editing the link of the URL if the image is inside a pattern instance. // This is a temporary solution until we support overriding the link on the frontend. hasParentPattern, + lockCaption: + // Disable editing the caption if the image is inside a pattern instance. + // This is a temporary solution until we support overriding the caption on the frontend. + hasParentPattern, lockAltControls: !! altBinding && ( ! altBindingSource || @@ -907,6 +912,7 @@ export default function Image( { which causes duplicated image upload. */ } { ! temporaryURL && controls } { img } + ); diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index 5dcada62f6feb5..e45591661abfe4 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -554,7 +554,11 @@ private static function get_nav_element_directives( $is_interactive ) { // When adding to this array be mindful of security concerns. $nav_element_context = data_wp_context( array( - 'overlayOpenedBy' => array(), + 'overlayOpenedBy' => array( + 'click' => false, + 'hover' => false, + 'focus' => false, + ), 'type' => 'overlay', 'roleAttribute' => '', 'ariaLabel' => __( 'Menu' ), @@ -764,7 +768,7 @@ function block_core_navigation_add_directives_to_submenu( $tags, $block_attribut ) ) { // Add directives to the parent `
  • `. $tags->set_attribute( 'data-wp-interactive', 'core/navigation' ); - $tags->set_attribute( 'data-wp-context', '{ "submenuOpenedBy": {}, "type": "submenu" }' ); + $tags->set_attribute( 'data-wp-context', '{ "submenuOpenedBy": { "click": false, "hover": false, "focus": false }, "type": "submenu" }' ); $tags->set_attribute( 'data-wp-watch', 'callbacks.initMenu' ); $tags->set_attribute( 'data-wp-on--focusout', 'actions.handleMenuFocusout' ); $tags->set_attribute( 'data-wp-on--keydown', 'actions.handleMenuKeydown' ); diff --git a/packages/block-library/src/search/style.scss b/packages/block-library/src/search/style.scss index 4e283530a0e277..1434f29de76810 100644 --- a/packages/block-library/src/search/style.scss +++ b/packages/block-library/src/search/style.scss @@ -12,6 +12,8 @@ $button-spacing-y: math.div($grid-unit-15, 2); // 6px svg { min-width: $grid-unit-30; min-height: $grid-unit-30; + width: 1.25em; + height: 1.25em; fill: currentColor; vertical-align: text-bottom; } diff --git a/packages/block-library/src/utils/caption.js b/packages/block-library/src/utils/caption.js index e9055cc29df02c..57f034c76c6ed9 100644 --- a/packages/block-library/src/utils/caption.js +++ b/packages/block-library/src/utils/caption.js @@ -10,14 +10,21 @@ import { useState, useEffect, useCallback } from '@wordpress/element'; import { usePrevious } from '@wordpress/compose'; import { __ } from '@wordpress/i18n'; import { - RichText, BlockControls, __experimentalGetElementClassName, + privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; import { ToolbarButton } from '@wordpress/components'; import { caption as captionIcon } from '@wordpress/icons'; import { createBlock, getDefaultBlockName } from '@wordpress/blocks'; +/** + * Internal dependencies + */ +import { unlock } from '../lock-unlock'; + +const { PrivateRichText: RichText } = unlock( blockEditorPrivateApis ); + export function Caption( { key = 'caption', attributes, @@ -28,6 +35,7 @@ export function Caption( { label = __( 'Caption text' ), showToolbarButton = true, className, + disableEditing, } ) { const caption = attributes[ key ]; const prevCaption = usePrevious( caption ); @@ -101,6 +109,7 @@ export function Caption( { createBlock( getDefaultBlockName() ) ) } + disableEditing={ disableEditing } /> ) } diff --git a/packages/block-library/src/utils/get-transformed-metadata.js b/packages/block-library/src/utils/get-transformed-metadata.js new file mode 100644 index 00000000000000..53d79d3c1e42ac --- /dev/null +++ b/packages/block-library/src/utils/get-transformed-metadata.js @@ -0,0 +1,65 @@ +/** + * WordPress dependencies + */ +import { getBlockType } from '@wordpress/blocks'; + +/** + * Transform the metadata attribute with only the values and bindings specified by each transform. + * Returns `undefined` if the input metadata is falsy. + * + * @param {Object} metadata Original metadata attribute from the block that is being transformed. + * @param {Object} newBlockName Name of the final block after the transformation. + * @param {Function} bindingsCallback Optional callback to transform the `bindings` property object. + * @return {Object|undefined} New metadata object only with the relevant properties. + */ +export function getTransformedMetadata( + metadata, + newBlockName, + bindingsCallback +) { + if ( ! metadata ) { + return; + } + const { supports } = getBlockType( newBlockName ); + // Fixed until an opt-in mechanism is implemented. + const BLOCK_BINDINGS_SUPPORTED_BLOCKS = [ + 'core/paragraph', + 'core/heading', + 'core/image', + 'core/button', + ]; + // The metadata properties that should be preserved after the transform. + const transformSupportedProps = []; + // If it support bindings, and there is a transform bindings callback, add the `id` and `bindings` properties. + if ( + BLOCK_BINDINGS_SUPPORTED_BLOCKS.includes( newBlockName ) && + bindingsCallback + ) { + transformSupportedProps.push( 'id', 'bindings' ); + } + // If it support block naming (true by default), add the `name` property. + if ( supports.renaming !== false ) { + transformSupportedProps.push( 'name' ); + } + + // Return early if no supported properties. + if ( ! transformSupportedProps.length ) { + return; + } + + const newMetadata = Object.entries( metadata ).reduce( + ( obj, [ prop, value ] ) => { + // If prop is not supported, don't add it to the new metadata object. + if ( ! transformSupportedProps.includes( prop ) ) { + return obj; + } + obj[ prop ] = + prop === 'bindings' ? bindingsCallback( value ) : value; + return obj; + }, + {} + ); + + // Return undefined if object is empty. + return Object.keys( newMetadata ).length ? newMetadata : undefined; +} diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md index fe782b5e416f27..daed2cf19cec9e 100644 --- a/packages/block-serialization-default-parser/CHANGELOG.md +++ b/packages/block-serialization-default-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.52.0 (2024-02-21) + ## 4.51.0 (2024-02-09) ## 4.50.0 (2024-01-24) diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 097b38f9d939b1..eedbaeaa04356b 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "4.51.0", + "version": "4.52.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md index 027c0561350c9e..cf6dcfe865991a 100644 --- a/packages/block-serialization-spec-parser/CHANGELOG.md +++ b/packages/block-serialization-spec-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.52.0 (2024-02-21) + ## 4.51.0 (2024-02-09) ## 4.50.0 (2024-01-24) diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index 109396cc017e6c..ed78b6c3741c4a 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "4.51.0", + "version": "4.52.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index c9f5df50de4650..ea1a6cbcad58af 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.29.0 (2024-02-21) + ## 12.28.0 (2024-02-09) ## 12.27.0 (2024-01-24) diff --git a/packages/blocks/package.json b/packages/blocks/package.json index aca9b8bf061c6b..adcaeb3d0fa605 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "12.28.1", + "version": "12.29.0", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index ba41f6fc886c68..625c1de258fed4 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.35.0 (2024-02-21) + ## 5.34.0 (2024-02-09) ## 5.33.0 (2024-01-24) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 15a85eeb8f2a44..30a59b04a1fa8b 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "5.34.0", + "version": "5.35.0", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md index 56d307f5709a18..12f26101fd65ba 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.23.0 (2024-02-21) + ## 0.22.0 (2024-02-09) ## 0.21.0 (2024-01-24) diff --git a/packages/commands/package.json b/packages/commands/package.json index 3f259f5af2570e..dd2fa58ec24fcc 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "0.22.1", + "version": "0.23.0", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index b3bd5bfcf70f2f..b37a6775079e8b 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 27.0.0 (2024-02-21) + ### Breaking Changes - `CustomSelectControl`: Remove deprecated `__nextUnconstrainedWidth` prop and promote to default behavior ([#58974](https://github.com/WordPress/gutenberg/pull/58974)). @@ -18,6 +20,10 @@ - Removing `dom-scroll-into-view` as a dependency of the components package ([#59085](https://github.com/WordPress/gutenberg/pull/59085)). - Add higher-order function to ignore IME keydowns ([#59081](https://github.com/WordPress/gutenberg/pull/59081)). +### Experimental + +- `Tabs`: rename `initialTabId` prop to `defaultTabId` ([#59035](https://github.com/WordPress/gutenberg/pull/59035)). + ## 26.0.1 (2024-02-13) ### Bug Fix diff --git a/packages/components/package.json b/packages/components/package.json index 4f7d68bc9a0593..fc2cd46cc8e1bc 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "26.0.1", + "version": "27.0.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/src/tabs/README.md b/packages/components/src/tabs/README.md index 732dec9dba7df0..6eaadc0ae0b19d 100644 --- a/packages/components/src/tabs/README.md +++ b/packages/components/src/tabs/README.md @@ -14,7 +14,7 @@ Tabs organizes content across different screens, data sets, and interactions. It #### Uncontrolled Mode -Tabs can be used in an uncontrolled mode, where the component manages its own state. In this mode, the `initialTabId` prop can be used to set the initially selected tab. If this prop is not set, the first tab will be selected by default. In addition, in most cases where the currently active tab becomes disabled or otherwise unavailable, uncontrolled mode will automatically fall back to selecting the first available tab. +Tabs can be used in an uncontrolled mode, where the component manages its own state. In this mode, the `defaultTabId` prop can be used to set the initially selected tab. If this prop is not set, the first tab will be selected by default. In addition, in most cases where the currently active tab becomes disabled or otherwise unavailable, uncontrolled mode will automatically fall back to selecting the first available tab. ```jsx import { Tabs } from '@wordpress/components'; @@ -24,25 +24,25 @@ const onSelect = ( tabName ) => { }; const MyUncontrolledTabs = () => ( - - - + + + Tab 1 - + Tab 2 - + Tab 3 - +

    Selected tab: Tab 1

    - +

    Selected tab: Tab 2

    - +

    Selected tab: Tab 3

    @@ -51,7 +51,7 @@ const MyUncontrolledTabs = () => ( #### Controlled Mode -Tabs can also be used in a controlled mode, where the parent component specifies the `selectedTabId` and the `onSelect` props to control tab selection. In this mode, the `initialTabId` prop will be ignored if it is provided. If the `selectedTabId` is `null`, no tab is selected. In this mode, if the currently selected tab becomes disabled or otherwise unavailable, the component will _not_ fall back to another available tab, leaving the controlling component in charge of implementing the desired logic. +Tabs can also be used in a controlled mode, where the parent component specifies the `selectedTabId` and the `onSelect` props to control tab selection. In this mode, the `defaultTabId` prop will be ignored if it is provided. If the `selectedTabId` is `null`, no tab is selected. In this mode, if the currently selected tab becomes disabled or otherwise unavailable, the component will _not_ fall back to another available tab, leaving the controlling component in charge of implementing the desired logic. ```jsx import { Tabs } from '@wordpress/components'; @@ -71,24 +71,24 @@ const MyControlledTabs = () => ( onSelect( selectedId ); } } > - - + + Tab 1 - + Tab 2 - + Tab 3 - +

    Selected tab: Tab 1

    - +

    Selected tab: Tab 2

    - +

    Selected tab: Tab 3

    @@ -120,7 +120,7 @@ When `true`, the tab will be selected when receiving focus (automatic tab activa - Required: No - Default: `true` -###### `initialTabId`: `string` +###### `defaultTabId`: `string` The id of the tab to be selected upon mounting of component. If this prop is not set, the first tab will be selected by default. The id provided will be internally prefixed with a unique instance ID to avoid collisions. diff --git a/packages/components/src/tabs/index.tsx b/packages/components/src/tabs/index.tsx index 685c5cb32bd05a..5ffa8e97a651b0 100644 --- a/packages/components/src/tabs/index.tsx +++ b/packages/components/src/tabs/index.tsx @@ -26,7 +26,7 @@ import { TabPanel } from './tabpanel'; function Tabs( { selectOnMove = true, - initialTabId, + defaultTabId, orientation = 'horizontal', onSelect, children, @@ -36,7 +36,7 @@ function Tabs( { const store = Ariakit.useTabStore( { selectOnMove, orientation, - defaultSelectedId: initialTabId && `${ instanceId }-${ initialTabId }`, + defaultSelectedId: defaultTabId && `${ instanceId }-${ defaultTabId }`, setSelectedId: ( selectedId ) => { const strippedDownId = typeof selectedId === 'string' @@ -66,7 +66,7 @@ function Tabs( { return ! item.dimmed; } ); const initialTab = items.find( - ( item ) => item.id === `${ instanceId }-${ initialTabId }` + ( item ) => item.id === `${ instanceId }-${ defaultTabId }` ); // Handle selecting the initial tab. @@ -78,8 +78,8 @@ function Tabs( { // Wait for the denoted initial tab to be declared before making a // selection. This ensures that if a tab is declared lazily it can // still receive initial selection, as well as ensuring no tab is - // selected if an invalid `initialTabId` is provided. - if ( initialTabId && ! initialTab ) { + // selected if an invalid `defaultTabId` is provided. + if ( defaultTabId && ! initialTab ) { return; } @@ -101,7 +101,7 @@ function Tabs( { }, [ firstEnabledTab, initialTab, - initialTabId, + defaultTabId, isControlled, items, selectedId, @@ -122,7 +122,7 @@ function Tabs( { } // If the currently selected tab becomes disabled, fall back to the - // `initialTabId` if possible. Otherwise select the first + // `defaultTabId` if possible. Otherwise select the first // enabled tab (if there is one). if ( initialTab && ! initialTab.dimmed ) { setSelectedId( initialTab.id ); diff --git a/packages/components/src/tabs/test/index.tsx b/packages/components/src/tabs/test/index.tsx index 96d17f59df99e8..39c860de62c144 100644 --- a/packages/components/src/tabs/test/index.tsx +++ b/packages/components/src/tabs/test/index.tsx @@ -598,7 +598,7 @@ describe( 'Tabs', () => { } ); } ); describe( 'Uncontrolled mode', () => { - describe( 'Without `initialTabId` prop', () => { + describe( 'Without `defaultTabId` prop', () => { it( 'should render first tab', async () => { render( ); @@ -655,20 +655,20 @@ describe( 'Tabs', () => { } ); } ); - describe( 'With `initialTabId`', () => { - it( 'should render the tab set by `initialTabId` prop', async () => { + describe( 'With `defaultTabId`', () => { + it( 'should render the tab set by `defaultTabId` prop', async () => { render( - + ); expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); } ); - it( 'should not select a tab when `initialTabId` does not match any known tab', () => { + it( 'should not select a tab when `defaultTabId` does not match any known tab', () => { render( ); @@ -682,25 +682,25 @@ describe( 'Tabs', () => { screen.queryByRole( 'tabpanel' ) ).not.toBeInTheDocument(); } ); - it( 'should not change tabs when initialTabId is changed', async () => { + it( 'should not change tabs when defaultTabId is changed', async () => { const { rerender } = render( - + ); rerender( - + ); expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); } ); - it( 'should fall back to the tab associated to `initialTabId` if the currently active tab is removed', async () => { + it( 'should fall back to the tab associated to `defaultTabId` if the currently active tab is removed', async () => { const mockOnSelect = jest.fn(); const { rerender } = render( ); @@ -714,7 +714,7 @@ describe( 'Tabs', () => { rerender( ); @@ -722,13 +722,13 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); } ); - it( 'should fall back to the tab associated to `initialTabId` if the currently active tab becomes disabled', async () => { + it( 'should fall back to the tab associated to `defaultTabId` if the currently active tab becomes disabled', async () => { const mockOnSelect = jest.fn(); const { rerender } = render( ); @@ -754,7 +754,7 @@ describe( 'Tabs', () => { rerender( ); @@ -762,9 +762,9 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); } ); - it( 'should have no active tabs when the tab associated to `initialTabId` is removed while being the active tab', async () => { + it( 'should have no active tabs when the tab associated to `defaultTabId` is removed while being the active tab', async () => { const { rerender } = render( - + ); expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); @@ -773,7 +773,7 @@ describe( 'Tabs', () => { rerender( ); @@ -788,9 +788,9 @@ describe( 'Tabs', () => { ).not.toBeInTheDocument(); } ); - it( 'waits for the tab with the `initialTabId` to be present in the `tabs` array before selecting it', async () => { + it( 'waits for the tab with the `defaultTabId` to be present in the `tabs` array before selecting it', async () => { const { rerender } = render( - + ); // There should be no selected tab yet. @@ -801,7 +801,7 @@ describe( 'Tabs', () => { rerender( ); @@ -891,7 +891,7 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); } ); - it( 'should select first enabled tab when the tab associated to `initialTabId` is disabled', async () => { + it( 'should select first enabled tab when the tab associated to `defaultTabId` is disabled', async () => { const TABS_ONLY_GAMMA_ENABLED = TABS.map( ( tabObj ) => tabObj.tabId !== 'gamma' ? { @@ -906,7 +906,7 @@ describe( 'Tabs', () => { const { rerender } = render( ); @@ -916,7 +916,7 @@ describe( 'Tabs', () => { // Re-enable all tabs rerender( - + ); // Even if the initial tab becomes enabled again, the selected tab doesn't @@ -968,14 +968,14 @@ describe( 'Tabs', () => { expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' ); } ); - it( 'should select the first enabled tab when the tab associated to `initialTabId` becomes disabled while being the active tab', async () => { + it( 'should select the first enabled tab when the tab associated to `defaultTabId` becomes disabled while being the active tab', async () => { const mockOnSelect = jest.fn(); const { rerender } = render( ); @@ -998,7 +998,7 @@ describe( 'Tabs', () => { ); @@ -1011,7 +1011,7 @@ describe( 'Tabs', () => { ); @@ -1032,12 +1032,12 @@ describe( 'Tabs', () => { await screen.findByRole( 'tabpanel', { name: 'Beta' } ) ).toBeInTheDocument(); } ); - it( 'should render the specified `selectedTabId`, and ignore the `initialTabId` prop', async () => { + it( 'should render the specified `selectedTabId`, and ignore the `defaultTabId` prop', async () => { render( ); diff --git a/packages/components/src/tabs/types.ts b/packages/components/src/tabs/types.ts index 389665b13357fe..1a9e6477385f67 100644 --- a/packages/components/src/tabs/types.ts +++ b/packages/components/src/tabs/types.ts @@ -43,7 +43,7 @@ export type TabsProps = { * Note: this prop will be overridden by the `selectedTabId` prop if it is * provided. (Controlled Mode) */ - initialTabId?: string; + defaultTabId?: string; /** * The function called when a tab has been selected. * It is passed the id of the newly selected tab as an argument. diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index d9a8069db3ad7f..9add5200edc13c 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.29.0 (2024-02-21) + ## 6.28.0 (2024-02-09) ## 6.27.0 (2024-01-24) diff --git a/packages/compose/package.json b/packages/compose/package.json index 1745f2f1abb344..8ebd0946647082 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "6.28.0", + "version": "6.29.0", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md index 19a95017acf910..c6e29c5ed03386 100644 --- a/packages/core-commands/CHANGELOG.md +++ b/packages/core-commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.21.0 (2024-02-21) + ## 0.20.0 (2024-02-09) ## 0.19.0 (2024-01-24) diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index afaec5b550dc96..4a72bd74c7eec5 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "0.20.1", + "version": "0.21.0", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index 3b1c7792068dc1..16cb9b709365be 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.29.0 (2024-02-21) + ## 6.28.0 (2024-02-09) ## 6.27.0 (2024-01-24) diff --git a/packages/core-data/package.json b/packages/core-data/package.json index 89cc98a22e2f48..23c829326f2dde 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-data", - "version": "6.28.1", + "version": "6.29.0", "description": "Access to and manipulation of core WordPress entities.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-interactive-template/CHANGELOG.md b/packages/create-block-interactive-template/CHANGELOG.md index 0c4efafb083488..d5b67b2718653c 100644 --- a/packages/create-block-interactive-template/CHANGELOG.md +++ b/packages/create-block-interactive-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.15.0 (2024-02-21) + ## 1.14.0 (2024-02-09) ## 1.13.0 (2024-01-24) diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index 6fa540ebffb0d3..c9320ba39d1f30 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "1.14.0", + "version": "1.15.0", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index 4f20092a7eca87..61a6ba24b37d4b 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.6.0 (2024-02-21) + ## 3.5.0 (2024-02-09) ## 3.4.0 (2024-01-24) diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index 5dc5afc2ab5072..37b2541b3b17a1 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "3.5.0", + "version": "3.6.0", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index 99347a28b887e5..5c1392cbf01284 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.36.0 (2024-02-21) + ### Bug Fix - Add missing `viewScriptModule` field ([#59140](https://github.com/WordPress/gutenberg/pull/59140)). diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 92b75299c52fea..11725574e4916c 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.35.0", + "version": "4.36.0", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index 8c7bc3cd9e5067..bd71cf8e84af8c 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.29.0 (2024-02-21) + ## 4.28.0 (2024-02-09) ## 4.27.0 (2024-01-24) diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index c0c07964f88abd..5e61641a4d1c66 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "4.28.1", + "version": "4.29.0", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md index 72a4f1c9ed0c8a..2107ebddbb868a 100644 --- a/packages/data-controls/CHANGELOG.md +++ b/packages/data-controls/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.21.0 (2024-02-21) + ## 3.20.0 (2024-02-09) ## 3.19.0 (2024-01-24) diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index 72cc3dc5758d1f..3974021b65563e 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "3.20.0", + "version": "3.21.0", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index b70c383f372589..4bf434d282f171 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.22.0 (2024-02-21) + ## 9.21.0 (2024-02-09) ## 9.20.0 (2024-01-24) diff --git a/packages/data/package.json b/packages/data/package.json index 26c300b2a85f86..8ae2cb6986ab24 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "9.21.0", + "version": "9.22.0", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 63b8739881f366..e525ab0eb4f28d 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.6.0 (2024-02-21) + ## 0.5.0 (2024-02-09) ## 0.4.0 (2024-01-24) diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index d1a0f5285634b4..5af3d1f92a93f0 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "0.5.1", + "version": "0.6.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index fcf4bfb34c08e7..95072f509e618b 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.52.0 (2024-02-21) + ## 4.51.0 (2024-02-09) ## 4.50.0 (2024-01-24) diff --git a/packages/date/package.json b/packages/date/package.json index 407e6704ab72e3..50495e1215c3d8 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "4.51.0", + "version": "4.52.0", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 3a87aa24561de9..1c466ba89363e7 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.3.0 (2024-02-21) + ## 5.2.0 (2024-02-09) ### Bug fixes diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index 99f7acb6c020bc..f53e4afa071d8b 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "5.2.0", + "version": "5.3.0", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md index 1ae7ee7cff78bb..1ce181ec48f9a2 100644 --- a/packages/deprecated/CHANGELOG.md +++ b/packages/deprecated/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.52.0 (2024-02-21) + ## 3.51.0 (2024-02-09) ## 3.50.0 (2024-01-24) diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 21589b17f0fc61..8cf9fa4d17f03d 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "3.51.0", + "version": "3.52.0", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index e266a45d17d606..031c7999fb3af4 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.61.0 (2024-02-21) + ## 1.60.0 (2024-02-09) ## 1.59.0 (2024-01-24) diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 9cb73a378aa61f..6a252be94b44b2 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "1.60.0", + "version": "1.61.0", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index d6f380971e264c..4fd66a3d4a8279 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.52.0 (2024-02-21) + ## 3.51.0 (2024-02-09) ## 3.50.0 (2024-01-24) diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index ccf5c26d58f438..21eb54ed0c7ea0 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "3.51.0", + "version": "3.52.0", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index 390186d9be6457..fa0a98701a5404 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.52.0 (2024-02-21) + ## 3.51.0 (2024-02-09) ## 3.50.0 (2024-01-24) diff --git a/packages/dom/package.json b/packages/dom/package.json index 36007d0fb4472f..0a827c134c41ef 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "3.51.0", + "version": "3.52.0", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md index f5aaa56d434d82..0afec7fffeb7e1 100644 --- a/packages/e2e-test-utils-playwright/CHANGELOG.md +++ b/packages/e2e-test-utils-playwright/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.20.0 (2024-02-21) + ## 0.19.0 (2024-02-09) ## 0.18.0 (2024-01-24) diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 3e6751afff5d77..606040b874c9f9 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "0.19.0", + "version": "0.20.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index 8f9a7afb72bf71..25cd29fc0267e7 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 10.23.0 (2024-02-21) + ## 10.22.0 (2024-02-09) ## 10.21.0 (2024-01-24) diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index ea3486a4c78a74..c5ef99227875cb 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "10.22.0", + "version": "10.23.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index 2357a952b7497b..f82bc48d2a4bbc 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.23.0 (2024-02-21) + ## 7.22.0 (2024-02-09) ## 7.21.0 (2024-01-24) diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 5cf58d68f6d72e..96a14211b8cd85 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "7.22.0", + "version": "7.23.0", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-context/render.php b/packages/e2e-tests/plugins/interactive-blocks/directive-context/render.php index 428d47ec397957..25d2bbc692efdf 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-context/render.php +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-context/render.php @@ -18,6 +18,7 @@ > + +
    @@ -59,6 +68,7 @@ > + +
    @@ -143,3 +158,15 @@
  • + +
    + + +
    +
    diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-context/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-context/view.js index aed4a3fefed07d..2267868713c41b 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-context/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-context/view.js @@ -9,6 +9,10 @@ store( 'directive-context', { const ctx = getContext(); return JSON.stringify( ctx, undefined, 2 ); }, + get selected() { + const { list, selected } = getContext(); + return list.find( ( obj ) => obj === selected )?.text; + } }, actions: { updateContext( event ) { @@ -22,6 +26,15 @@ store( 'directive-context', { const ctx = getContext(); ctx.text = ctx.text === 'Text 1' ? 'Text 2' : 'Text 1'; }, + selectItem( event ) { + const ctx = getContext(); + const value = parseInt( event.target.value ); + ctx.selected = ctx.list.find( ( { id } ) => id === value ); + }, + replaceObj() { + const ctx = getContext(); + ctx.obj = { overwritten: true }; + } }, } ); @@ -29,12 +42,17 @@ const html = `
    +
    +
    +
    +
    - + +
    `; @@ -49,13 +67,17 @@ const { actions } = store( 'directive-context-navigate', { const ctx = getContext(); ctx.newText = 'some new text'; }, + addText2() { + const ctx = getContext(); + ctx.text2 = 'some new text'; + }, navigate() { return import( '@wordpress/interactivity-router' ).then( - ( { actions: routerActions } ) => - routerActions.navigate( - window.location, - { force: true, html }, - ) + ( { actions: routerActions } ) => { + const url = new URL( window.location.href ); + url.searchParams.set( 'next_page', 'true' ); + return routerActions.navigate( url, { force: true, html } ); + } ); }, diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index a70b0623b49898..9fab74a295aac8 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.29.0 (2024-02-21) + ## 7.28.0 (2024-02-09) ## 7.27.0 (2024-01-24) diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index a4a7a210418e43..8b4b22a3850cea 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "7.28.1", + "version": "7.29.0", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/src/components/header/index.js b/packages/edit-post/src/components/header/index.js index b7e42d0217eefc..62a6a462d8dd18 100644 --- a/packages/edit-post/src/components/header/index.js +++ b/packages/edit-post/src/components/header/index.js @@ -61,7 +61,7 @@ function Header( { setEntitiesSavedStatesCallback, initialPost } ) { const blockToolbarRef = useRef(); const { isTextEditor, - hasBlockSelection, + blockSelectionStart, hasActiveMetaboxes, hasFixedToolbar, isPublishSidebarOpened, @@ -73,8 +73,8 @@ function Header( { setEntitiesSavedStatesCallback, initialPost } ) { return { isTextEditor: getEditorMode() === 'text', - hasBlockSelection: - !! select( blockEditorStore ).getBlockSelectionStart(), + blockSelectionStart: + select( blockEditorStore ).getBlockSelectionStart(), hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(), hasHistory: !! select( editorStore ).getEditorSettings() @@ -88,13 +88,14 @@ function Header( { setEntitiesSavedStatesCallback, initialPost } ) { const [ isBlockToolsCollapsed, setIsBlockToolsCollapsed ] = useState( true ); + const hasBlockSelection = !! blockSelectionStart; useEffect( () => { // If we have a new block selection, show the block tools - if ( hasBlockSelection ) { + if ( blockSelectionStart ) { setIsBlockToolsCollapsed( false ); } - }, [ hasBlockSelection ] ); + }, [ blockSelectionStart ] ); return (
    @@ -121,7 +122,9 @@ function Header( { setEntitiesSavedStatesCallback, initialPost } ) { className={ classnames( 'selected-block-tools-wrapper', { - 'is-collapsed': isBlockToolsCollapsed, + 'is-collapsed': + isBlockToolsCollapsed || + ! hasBlockSelection, } ) } > diff --git a/packages/edit-post/src/editor.js b/packages/edit-post/src/editor.js index 6aa8c2e9a62394..f179ee6156e63e 100644 --- a/packages/edit-post/src/editor.js +++ b/packages/edit-post/src/editor.js @@ -12,8 +12,6 @@ import { useMemo } from '@wordpress/element'; import { SlotFillProvider } from '@wordpress/components'; import { store as coreStore } from '@wordpress/core-data'; import { CommandMenu } from '@wordpress/commands'; -import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; -import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -25,14 +23,6 @@ import { unlock } from './lock-unlock'; import useNavigateToEntityRecord from './hooks/use-navigate-to-entity-record'; const { ExperimentalEditorProvider } = unlock( editorPrivateApis ); -const { BlockRemovalWarningModal } = unlock( blockEditorPrivateApis ); -// Prevent accidental removal of certain blocks, asking the user for -// confirmation. -const blockRemovalRules = { - 'bindings/core/pattern-overrides': __( - 'Blocks from synced patterns that can have overriden content.' - ), -}; function Editor( { postId: initialPostId, @@ -108,7 +98,6 @@ function Editor( { - diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index ea79dd79e61659..1c6e885a5b70b2 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.29.0 (2024-02-21) + ## 5.28.0 (2024-02-09) ## 5.27.0 (2024-01-24) diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index f62faf0b8cd8f1..4820539c10ed63 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "5.28.1", + "version": "5.29.0", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index d3f61ea7dfb1f4..1512ea5ba3bcd5 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -14,7 +14,6 @@ import { BlockBreadcrumb, BlockToolbar, store as blockEditorStore, - privateApis as blockEditorPrivateApis, BlockInspector, } from '@wordpress/block-editor'; import { @@ -56,7 +55,6 @@ import SiteEditorCanvas from '../block-editor/site-editor-canvas'; import TemplatePartConverter from '../template-part-converter'; import { useSpecificEditorSettings } from '../block-editor/use-site-editor-settings'; -const { BlockRemovalWarningModal } = unlock( blockEditorPrivateApis ); const { ExperimentalEditorProvider: EditorProvider, InserterSidebar, @@ -74,21 +72,6 @@ const interfaceLabels = { footer: __( 'Editor footer' ), }; -// Prevent accidental removal of certain blocks, asking the user for -// confirmation. -const blockRemovalRules = { - 'core/query': __( 'Query Loop displays a list of posts or pages.' ), - 'core/post-content': __( - 'Post Content displays the content of a post or page.' - ), - 'core/post-template': __( - 'Post Template displays each post or page in a Query Loop.' - ), - 'bindings/core/pattern-overrides': __( - 'Blocks from synced patterns that can have overriden content.' - ), -}; - export default function Editor( { isLoading } ) { const { record: editedPost, @@ -243,9 +226,6 @@ export default function Editor( { isLoading } ) { ) } - ) } diff --git a/packages/edit-site/src/components/global-styles/font-families.js b/packages/edit-site/src/components/global-styles/font-families.js index 5e66f705334c8e..55ca6d0b5222c9 100644 --- a/packages/edit-site/src/components/global-styles/font-families.js +++ b/packages/edit-site/src/components/global-styles/font-families.js @@ -33,7 +33,7 @@ function FontFamilies() { { !! modalTabOpen && ( toggleModal() } - initialTabId={ modalTabOpen } + defaultTabId={ modalTabOpen } /> ) } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/index.js b/packages/edit-site/src/components/global-styles/font-library-modal/index.js index 71966449eb616d..dc0fcd7ea373b0 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/index.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/index.js @@ -41,7 +41,7 @@ const tabsFromCollections = ( collections ) => function FontLibraryModal( { onRequestClose, - initialTabId = 'installed-fonts', + defaultTabId = 'installed-fonts', } ) { const { collections, setNotice } = useContext( FontLibraryContext ); @@ -63,7 +63,7 @@ function FontLibraryModal( { className="font-library-modal" >
    - + { tabs.map( ( { id, title } ) => ( diff --git a/packages/edit-site/src/components/header-edit-mode/index.js b/packages/edit-site/src/components/header-edit-mode/index.js index 5b8b44f63efe74..daacf7b4df21ea 100644 --- a/packages/edit-site/src/components/header-edit-mode/index.js +++ b/packages/edit-site/src/components/header-edit-mode/index.js @@ -134,7 +134,9 @@ export default function HeaderEditMode() { className={ classnames( 'selected-block-tools-wrapper', { - 'is-collapsed': isBlockToolsCollapsed, + 'is-collapsed': + isBlockToolsCollapsed || + ! hasBlockSelected, } ) } > diff --git a/packages/edit-widgets/CHANGELOG.md b/packages/edit-widgets/CHANGELOG.md index a3cf159c3c37b2..15bc28138449db 100644 --- a/packages/edit-widgets/CHANGELOG.md +++ b/packages/edit-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.29.0 (2024-02-21) + ## 5.28.0 (2024-02-09) ## 5.27.0 (2024-01-24) diff --git a/packages/edit-widgets/package.json b/packages/edit-widgets/package.json index dacfe0f79d1bdc..ebe39e64df12f9 100644 --- a/packages/edit-widgets/package.json +++ b/packages/edit-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-widgets", - "version": "5.28.1", + "version": "5.29.0", "description": "Widgets Page module for WordPress..", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index f06ec7ce7505f3..e09c3766e2e628 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 13.29.0 (2024-02-21) + ## 13.28.0 (2024-02-09) ## 13.27.0 (2024-01-24) diff --git a/packages/editor/package.json b/packages/editor/package.json index 11c8b600b21959..fbbfdaa6e26119 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/editor", - "version": "13.28.1", + "version": "13.29.0", "description": "Enhanced block editor for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/editor/src/components/block-removal-warnings/index.js b/packages/editor/src/components/block-removal-warnings/index.js new file mode 100644 index 00000000000000..aa6dad0bc44d33 --- /dev/null +++ b/packages/editor/src/components/block-removal-warnings/index.js @@ -0,0 +1,92 @@ +/** + * WordPress dependencies + */ + +import { _n } from '@wordpress/i18n'; +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; +import { useSelect } from '@wordpress/data'; +import { useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; +import { store as editorStore } from '../../store'; + +const { BlockRemovalWarningModal } = unlock( blockEditorPrivateApis ); + +// Prevent accidental removal of certain blocks, asking the user for confirmation first. +const TEMPLATE_BLOCKS = [ + 'core/post-content', + 'core/post-template', + 'core/query', +]; +const BLOCK_REMOVAL_RULES = [ + { + // Template blocks. + // The warning is only shown when a user manipulates templates or template parts. + postTypes: [ 'wp_template', 'wp_template_part' ], + callback( removedBlocks ) { + const removedTemplateBlocks = removedBlocks.filter( ( { name } ) => + TEMPLATE_BLOCKS.includes( name ) + ); + if ( removedTemplateBlocks.length ) { + return _n( + 'Deleting this block will stop your post or page content from displaying on this template. It is not recommended.', + 'Some of the deleted blocks will stop your post or page content from displaying on this template. It is not recommended.', + removedBlocks.length + ); + } + }, + }, + { + // Pattern overrides. + // The warning is only shown when the user edits a pattern. + postTypes: [ 'wp_block' ], + callback( removedBlocks ) { + const removedBlocksWithOverrides = removedBlocks.filter( + ( { attributes } ) => + attributes?.metadata?.bindings && + Object.values( attributes.metadata.bindings ).some( + ( binding ) => + binding.source === 'core/pattern-overrides' + ) + ); + if ( removedBlocksWithOverrides.length ) { + return _n( + 'The deleted block allows instance overrides. Removing it may result in content not displaying where this pattern is used. Are you sure you want to proceed?', + 'Some of the deleted blocks allow instance overrides. Removing them may result in content not displaying where this pattern is used. Are you sure you want to proceed?', + removedBlocks.length + ); + } + }, + }, +]; + +export default function BlockRemovalWarnings() { + const currentPostType = useSelect( + ( select ) => select( editorStore ).getCurrentPostType(), + [] + ); + + const removalRulesForPostType = useMemo( + () => + BLOCK_REMOVAL_RULES.filter( ( rule ) => + rule.postTypes.includes( currentPostType ) + ), + [ currentPostType ] + ); + + // `BlockRemovalWarnings` is rendered in the editor provider, a shared component + // across react native and web. However, `BlockRemovalWarningModal` is web only. + // Check it exists before trying to render it. + if ( ! BlockRemovalWarningModal ) { + return null; + } + + if ( ! removalRulesForPostType ) { + return null; + } + + return ; +} diff --git a/packages/editor/src/components/document-outline/check.js b/packages/editor/src/components/document-outline/check.js index 0ae0b3435e1e46..9338ac6d5cf419 100644 --- a/packages/editor/src/components/document-outline/check.js +++ b/packages/editor/src/components/document-outline/check.js @@ -1,21 +1,19 @@ /** * WordPress dependencies */ -import { withSelect } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; import { store as blockEditorStore } from '@wordpress/block-editor'; -function DocumentOutlineCheck( { blocks, children } ) { - const headings = blocks.filter( - ( block ) => block.name === 'core/heading' - ); +export default function DocumentOutlineCheck( { children } ) { + const hasHeadings = useSelect( ( select ) => { + const { getGlobalBlockCount } = select( blockEditorStore ); - if ( headings.length < 1 ) { + return getGlobalBlockCount( 'core/heading' ) > 0; + } ); + + if ( hasHeadings ) { return null; } return children; } - -export default withSelect( ( select ) => ( { - blocks: select( blockEditorStore ).getBlocks(), -} ) )( DocumentOutlineCheck ); diff --git a/packages/editor/src/components/document-outline/index.js b/packages/editor/src/components/document-outline/index.js index bbddf220115406..20410959a17210 100644 --- a/packages/editor/src/components/document-outline/index.js +++ b/packages/editor/src/components/document-outline/index.js @@ -2,8 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { compose } from '@wordpress/compose'; -import { withSelect, useDispatch } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { create, getTextContent } from '@wordpress/rich-text'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { store as coreStore } from '@wordpress/core-data'; @@ -98,15 +97,26 @@ const computeOutlineHeadings = ( blocks = [] ) => { const isEmptyHeading = ( heading ) => ! heading.attributes.content || heading.attributes.content.length === 0; -export const DocumentOutline = ( { - blocks = [], - title, +export default function DocumentOutline( { onSelect, isTitleSupported, hasOutlineItemsDisabled, -} ) => { - const headings = computeOutlineHeadings( blocks ); +} ) { const { selectBlock } = useDispatch( blockEditorStore ); + const { blocks, title } = useSelect( ( select ) => { + const { getBlocks } = select( blockEditorStore ); + const { getEditedPostAttribute } = select( editorStore ); + const { getPostType } = select( coreStore ); + const postType = getPostType( getEditedPostAttribute( 'type' ) ); + + return { + title: getEditedPostAttribute( 'title' ), + blocks: getBlocks(), + isTitleSupported: postType?.supports?.title ?? false, + }; + } ); + + const headings = computeOutlineHeadings( blocks ); if ( headings.length < 1 ) { return (
    @@ -194,19 +204,4 @@ export const DocumentOutline = ( {
    ); -}; - -export default compose( - withSelect( ( select ) => { - const { getBlocks } = select( blockEditorStore ); - const { getEditedPostAttribute } = select( editorStore ); - const { getPostType } = select( coreStore ); - const postType = getPostType( getEditedPostAttribute( 'type' ) ); - - return { - title: getEditedPostAttribute( 'title' ), - blocks: getBlocks(), - isTitleSupported: postType?.supports?.title ?? false, - }; - } ) -)( DocumentOutline ); +} diff --git a/packages/editor/src/components/document-outline/test/index.js b/packages/editor/src/components/document-outline/test/index.js index 21c258c9a65df7..b396d7cc78349f 100644 --- a/packages/editor/src/components/document-outline/test/index.js +++ b/packages/editor/src/components/document-outline/test/index.js @@ -11,15 +11,27 @@ import { registerBlockType, unregisterBlockType, } from '@wordpress/blocks'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ -import { DocumentOutline } from '../'; +import DocumentOutline from '../'; jest.mock( '@wordpress/block-editor', () => ( { BlockTitle: () => 'Block Title', } ) ); +jest.mock( '@wordpress/data/src/components/use-select', () => jest.fn() ); + +function setupMockSelect( blocks ) { + useSelect.mockImplementation( ( mapSelect ) => { + return mapSelect( () => ( { + getBlocks: () => blocks, + getEditedPostAttribute: () => null, + getPostType: () => null, + } ) ); + } ); +} describe( 'DocumentOutline', () => { let paragraph, headingH1, headingH2, headingH3, nestedHeading; @@ -77,6 +89,7 @@ describe( 'DocumentOutline', () => { describe( 'no header blocks present', () => { it( 'should not render when no blocks provided', () => { + setupMockSelect( [] ); render( ); expect( screen.queryByRole( 'list' ) ).not.toBeInTheDocument(); @@ -87,7 +100,8 @@ describe( 'DocumentOutline', () => { // Set client IDs to a predictable value. return { ...block, clientId: `clientId_${ index }` }; } ); - render( ); + setupMockSelect( blocks ); + render( ); expect( screen.queryByRole( 'list' ) ).not.toBeInTheDocument(); } ); @@ -99,14 +113,16 @@ describe( 'DocumentOutline', () => { // Set client IDs to a predictable value. return { ...block, clientId: `clientId_${ index }` }; } ); - render( ); + setupMockSelect( blocks ); + render( ); expect( screen.getByRole( 'list' ) ).toMatchSnapshot(); } ); it( 'should render an item when only one heading provided', () => { const blocks = [ headingH2 ]; - render( ); + setupMockSelect( blocks ); + render( ); const tableOfContentItem = within( screen.getByRole( 'list' ) @@ -123,7 +139,8 @@ describe( 'DocumentOutline', () => { headingH3, paragraph, ]; - render( ); + setupMockSelect( blocks ); + render( ); expect( within( screen.getByRole( 'list' ) ).getAllByRole( 'listitem' ) @@ -137,7 +154,8 @@ describe( 'DocumentOutline', () => { return { ...block, clientId: `clientId_${ index }` }; } ); - render( ); + setupMockSelect( blocks ); + render( ); expect( screen.getByRole( 'list' ) ).toMatchSnapshot(); } ); @@ -146,7 +164,8 @@ describe( 'DocumentOutline', () => { describe( 'nested headings', () => { it( 'should render even if the heading is nested', () => { const blocks = [ headingH2, nestedHeading ]; - render( ); + setupMockSelect( blocks ); + render( ); // Unnested heading and nested heading should appear as items. const tableOfContentItems = within( diff --git a/packages/editor/src/components/list-view-sidebar/index.js b/packages/editor/src/components/list-view-sidebar/index.js index 9484ddcf3943dd..a08b9a73c3c982 100644 --- a/packages/editor/src/components/list-view-sidebar/index.js +++ b/packages/editor/src/components/list-view-sidebar/index.js @@ -127,7 +127,7 @@ export default function ListViewSidebar() { // render where no tab is selected. This ensures that the // tabpanel height is correct so the relevant scroll container // can be rendered internally. - initialTabId="list-view" + defaultTabId="list-view" >