diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2773fa8ea7581a..2832c860de002a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -12,7 +12,7 @@ # Blocks /packages/block-library @Soean @ajitbohra @talldan -/packages/block-library/src/gallery @mkevins @pinarol +/packages/block-library/src/gallery @mkevins /packages/block-library/src/social-links @mkaz /packages/block-library/src/social-link @mkaz /packages/block-library/src/image @ajlende diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index 7a7a69a14d564c..840e49a55ee078 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -30,7 +30,7 @@ jobs: - name: Restore build cache uses: actions/cache@v2 with: - path: packages/react-native-editor/ios/build/gutenberg/Build/Products/Release-iphonesimulator/GutenbergDemo.app + path: packages/react-native-editor/ios/build/gutenberg/Build/Products/Release-iphonesimulator/gutenberg.app key: ${{ runner.os }}-ios-build-${{ hashFiles('ios-checksums.txt') }} - name: Restore pods cache @@ -55,13 +55,13 @@ jobs: run: sudo xcode-select --switch /Applications/Xcode_11.4.1.app - name: Build (if needed) - run: test -e packages/react-native-editor/ios/build/gutenberg/Build/Products/Release-iphonesimulator/GutenbergDemo.app/GutenbergDemo || SKIP_BUNDLING=true npm run native test:e2e:build-app:ios + run: test -e packages/react-native-editor/ios/build/gutenberg/Build/Products/Release-iphonesimulator/gutenberg.app/gutenberg || SKIP_BUNDLING=true npm run native test:e2e:build-app:ios - name: Run iOS Device Tests run: TEST_RN_PLATFORM=ios npm run native device-tests:local ${{ matrix.native-test-name }} - name: Prepare build cache - run: rm packages/react-native-editor/ios/build/gutenberg/Build/Products/Release-iphonesimulator/GutenbergDemo.app/main.jsbundle + run: rm packages/react-native-editor/ios/build/gutenberg/Build/Products/Release-iphonesimulator/gutenberg.app/main.jsbundle - uses: actions/upload-artifact@v2 if: always() diff --git a/changelog.txt b/changelog.txt index 3ac19d9866268a..9bc39db2a4630f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,168 @@ == Changelog == += 9.1.0 = + +### Features + +- Add "open in new tab" feature to Social Links Block. ([25468](https://github.com/WordPress/gutenberg/pull/25468)) +- Add Image Size control to the Media & Text block. ([24795](https://github.com/WordPress/gutenberg/pull/24795)) + +### Enhancements + +- Inserter: Add block pattern category selection. ([24954](https://github.com/WordPress/gutenberg/pull/24954)) +- Reduce minimum height to 1px for the Spacer block. ([25528](https://github.com/WordPress/gutenberg/pull/25528)) +- Show the Fullscreen keyboard shortcut. ([25395](https://github.com/WordPress/gutenberg/pull/25395)) +- Improve the Audio block shortcode transform to account for all sources. ([25114](https://github.com/WordPress/gutenberg/pull/25114)) +- Code block: Allow HTML editing & rich text content. ([24689](https://github.com/WordPress/gutenberg/pull/24689)) +- Remove appender from unselected Buttons and Social Icons block. ([25518](https://github.com/WordPress/gutenberg/pull/25518)) +- Widgets Screen: + - Register legacy widgets as block variations. ([24905](https://github.com/WordPress/gutenberg/pull/24905)) + - Use the default block list appender for the widget areas. ([25635](https://github.com/WordPress/gutenberg/pull/25635)) + - Add titles to Legacy Widgets. ([25638](https://github.com/WordPress/gutenberg/pull/25638)) +- Buttons block: Lighten editor DOM. ([23222](https://github.com/WordPress/gutenberg/pull/23222)) +- Copy: Reword block settings menu item labels. ([22955](https://github.com/WordPress/gutenberg/pull/22955)) +- Add a tooltip to the Drag & Drop handle. ([25606](https://github.com/WordPress/gutenberg/pull/25606)) ([25614](https://github.com/WordPress/gutenberg/pull/25614)) +- A11y: + - Add aria-haspopup property to the BlockNavigation component. ([25605](https://github.com/WordPress/gutenberg/pull/25605)) + - Add aria-haspopup property to the TableOfContents component. ([25603](https://github.com/WordPress/gutenberg/pull/25603)) + - Add aria-haspopup to the ToolSelector. ([25600](https://github.com/WordPress/gutenberg/pull/25600)) + - Add aria-haspopup to the MediaReplaceFlow button. ([25597](https://github.com/WordPress/gutenberg/pull/25597)) + - Add aria-haspopup attribute to CustomGradientBar component. ([25571](https://github.com/WordPress/gutenberg/pull/25571)) + - Add aria-haspopup to CircularOptionPicker component. ([25564](https://github.com/WordPress/gutenberg/pull/25564)) + - Add aria-describedby to featured-image button. ([24888](https://github.com/WordPress/gutenberg/pull/24888)) +- Don't show heading ancestor blocks in Document Outline. ([25599](https://github.com/WordPress/gutenberg/pull/25599)) +- Support the default link config for the Gallery and Image blocks (`image_default_link_type`). ([25578](https://github.com/WordPress/gutenberg/pull/25578)) ([25582](https://github.com/WordPress/gutenberg/pull/25582)) +- Social Icons Block: Let icons wrap. ([25334](https://github.com/WordPress/gutenberg/pull/25334)) + +### New APIs + +- Add new ComboboxControl. ([25442](https://github.com/WordPress/gutenberg/pull/25442)) +- Data Controls: Add new syncSelect control. ([25336](https://github.com/WordPress/gutenberg/pull/25336)) +- DateTimePicker: Add support for highlighting days. ([22032](https://github.com/WordPress/gutenberg/pull/22032)) + +### Bug Fixes + +- Widgets Screen: + - Auto expand the last selected widget area when opening the inserter. ([25669](https://github.com/WordPress/gutenberg/pull/25669)) + - Ensure all widgets are properly initialized when they're added, do not unmount widgets once they're mounted. ([25645](https://github.com/WordPress/gutenberg/pull/25645)) + - Fix Legacy widget block previews and use iFrames. ([25443](https://github.com/WordPress/gutenberg/pull/25443)) ([14643](https://github.com/WordPress/gutenberg/pull/14643)) + - Report save errors. ([25408](https://github.com/WordPress/gutenberg/pull/25408)) + - Fix global inserter. ([24908](https://github.com/WordPress/gutenberg/pull/24908)) +- Fix RangeControl direct entry in input field. ([25609](https://github.com/WordPress/gutenberg/pull/25609)) +- A11y: + - Fix the color contrast in the code editor. ([25593](https://github.com/WordPress/gutenberg/pull/25593)) + - Fix Publish sidebar Cancel button not usable through screen readers. ([25441](https://github.com/WordPress/gutenberg/pull/25441)) + - Fix keyboard navigation on the Image block toolbar. ([25127](https://github.com/WordPress/gutenberg/pull/25127)) + - More block: Use an actual placeholder for input text. ([23836](https://github.com/WordPress/gutenberg/pull/23836)) +- Fix nested container smart margins. ([25527](https://github.com/WordPress/gutenberg/pull/25527)) +- Fix add_filter instead of apply_filters. ([25512](https://github.com/WordPress/gutenberg/pull/25512)) +- Fix the WordPress embed preview in the editor. ([25370](https://github.com/WordPress/gutenberg/pull/25370)) +- Remove Embed block aspect ratio classes on url change. ([25295](https://github.com/WordPress/gutenberg/pull/25295)) +- Remove duplicate help item. ([25283](https://github.com/WordPress/gutenberg/pull/25283)) +- Fix Block Directory author average rating formating. ([24732](https://github.com/WordPress/gutenberg/pull/24732)) +- @wordpress/api-fetch: + - Fix preloading middleware referencing stale data. ([25550](https://github.com/WordPress/gutenberg/pull/25550)) + - Check nonce header value before skipping adding it. ([25458](https://github.com/WordPress/gutenberg/pull/25458)) +- Use esc_html instead of esc_attr in the Archives block. ([25476](https://github.com/WordPress/gutenberg/pull/25476)) +- Fix Canceling Drag and Drop using ESC key. ([25317](https://github.com/WordPress/gutenberg/pull/25317)) +- Cover block: Add explilcit box-sizing style. ([25115](https://github.com/WordPress/gutenberg/pull/25115)) +- Use a ComboboxControl for the post author selector to fix loading issues for sites with a big number of authors. ([23237](https://github.com/WordPress/gutenberg/pull/23237)) + +### Performance + +- Avoid relying on DOM events to measure the loading time. ([25288](https://github.com/WordPress/gutenberg/pull/25288)) + +### Experiments + +- Site Editor Screen: + - Fix wrong close label in the block inspector. ([25424](https://github.com/WordPress/gutenberg/pull/25424)) + - Add basic template information to editor header. ([25320](https://github.com/WordPress/gutenberg/pull/25320)) + - Fix the footer styling. ([25152](https://github.com/WordPress/gutenberg/pull/25152)) + - Add a reset button to global styles sidebar. ([25426](https://github.com/WordPress/gutenberg/pull/25426)) + - Show document subtext if template part child is selected. ([25544](https://github.com/WordPress/gutenberg/pull/25544)) + - Add navigation panel. ([25506](https://github.com/WordPress/gutenberg/pull/25506)) + - Fix site base URL. ([25409](https://github.com/WordPress/gutenberg/pull/25409)) +- Post and Site Blocks: + - Add link option in PostTitle block. ([25341](https://github.com/WordPress/gutenberg/pull/25341)) ([25397](https://github.com/WordPress/gutenberg/pull/25397)) + - Register the Site Logo block using `register_block_type_from_metadata`. ([25289](https://github.com/WordPress/gutenberg/pull/25289)) +- Themes and global styles: + - Support defining colors and gradients config from theme.json. ([25419](https://github.com/WordPress/gutenberg/pull/25419)) + - Support defining font sizes config from theme.json. ([25516](https://github.com/WordPress/gutenberg/pull/25516)) + - Support custom units on theme.json. ([25217](https://github.com/WordPress/gutenberg/pull/25217)) + - Add separate support keys for color and background color. ([25314](https://github.com/WordPress/gutenberg/pull/25314)) + - Allow themes to enqueue custom CSS variables via theme.json. ([25446](https://github.com/WordPress/gutenberg/pull/25446)) ([25619](https://github.com/WordPress/gutenberg/pull/25619)) + - Refactor theme.json format. ([25301](https://github.com/WordPress/gutenberg/pull/25301)) ([25407](https://github.com/WordPress/gutenberg/pull/25407)) + - Update theme json documentation to account for latest changes. ([25369](https://github.com/WordPress/gutenberg/pull/25369)) +- Block API: Introduce useBlockWrapperProps hook to use light block DOM in the editor. ([23034](https://github.com/WordPress/gutenberg/pull/23034)) ([25679](https://github.com/WordPress/gutenberg/pull/25679)) ([25554](https://github.com/WordPress/gutenberg/pull/25554)) ([25515](https://github.com/WordPress/gutenberg/pull/25515)) +- Navigation block and screen: + - Handle block menu items. ([24846](https://github.com/WordPress/gutenberg/pull/24846)) + - Avoid auto-focusing Navigation block in Navigation screen. ([25592](https://github.com/WordPress/gutenberg/pull/25592)) + - Change the block description. ([25531](https://github.com/WordPress/gutenberg/pull/25531)) ([25555](https://github.com/WordPress/gutenberg/pull/25555)) + - Allow Social Links within Navigation Block. ([25357](https://github.com/WordPress/gutenberg/pull/25357)) + - Wrap navigation editing features with filters. ([25329](https://github.com/WordPress/gutenberg/pull/25329)) + - Add move markers to list view. ([25205](https://github.com/WordPress/gutenberg/pull/25205)) +- Iterating on the Navigation Component ([25608](https://github.com/WordPress/gutenberg/pull/25608)) ([25495](https://github.com/WordPress/gutenberg/pull/25495)) ([25572](https://github.com/WordPress/gutenberg/pull/25572)) ([25540](https://github.com/WordPress/gutenberg/pull/25540)) ([25520](https://github.com/WordPress/gutenberg/pull/25520)) ([25507](https://github.com/WordPress/gutenberg/pull/25507)) ([25367](https://github.com/WordPress/gutenberg/pull/25367)) ([25364](https://github.com/WordPress/gutenberg/pull/25364)) ([25340](https://github.com/WordPress/gutenberg/pull/25340)) ([25327](https://github.com/WordPress/gutenberg/pull/25327)) ([25281](https://github.com/WordPress/gutenberg/pull/25281)) ([25280](https://github.com/WordPress/gutenberg/pull/25280)) + + +### Documentation + +- Add a data format and flow architecture document. ([25299](https://github.com/WordPress/gutenberg/pull/25299)) +- @wordpress/env: Add documentation for inspecting the docker compose file. ([25666](https://github.com/WordPress/gutenberg/pull/25666)) +- Add new block supports page to the handbook. ([25647](https://github.com/WordPress/gutenberg/pull/25647)) +- Block Directory: Add developer documentation. ([25591](https://github.com/WordPress/gutenberg/pull/25591)) +- Move custom-fields note to the 'Register Meta Field' documentation. ([25584](https://github.com/WordPress/gutenberg/pull/25584)) +- Add Block Editor Components documentation: + - Warning ([25574](https://github.com/WordPress/gutenberg/pull/25574)) + - FontSizePicker ([25568](https://github.com/WordPress/gutenberg/pull/25568)) + - UnitControl ([25565](https://github.com/WordPress/gutenberg/pull/25565)) + - CopyHandler ([25342](https://github.com/WordPress/gutenberg/pull/25342)) + - MultiSelection ([25306](https://github.com/WordPress/gutenberg/pull/25306)) + - LineHeightControl ([25303](https://github.com/WordPress/gutenberg/pull/25303)) + - BlockAlignmentToolbar ([25212](https://github.com/WordPress/gutenberg/pull/25212)) + - AlignmentToolbar ([25210](https://github.com/WordPress/gutenberg/pull/25210)) + - BlockFormatControls ([25573](https://github.com/WordPress/gutenberg/pull/25573)) +- Add Caveats section for MAMP. ([25444](https://github.com/WordPress/gutenberg/pull/25444)) +- Add FormTokenField story. ([25439](https://github.com/WordPress/gutenberg/pull/25439)) +- Improve documentation for the data registry control and selector creators. ([25335](https://github.com/WordPress/gutenberg/pull/25335)) +- Update git workflow documentation. ([25164](https://github.com/WordPress/gutenberg/pull/25164)) +- Refresh the Getting Started guide. ([25090](https://github.com/WordPress/gutenberg/pull/25090)) +- Update JavaScript troubleshooting guide. ([24105](https://github.com/WordPress/gutenberg/pull/24105)) +- Enhance the Block Context documentation. ([25272](https://github.com/WordPress/gutenberg/pull/25272)) +- Typos: ([25359](https://github.com/WordPress/gutenberg/pull/25359)) ([25653](https://github.com/WordPress/gutenberg/pull/25653)) + +### Code Quality + +- Update the Dashicon component to rely on the font that ships with WordPress. ([20003](https://github.com/WordPress/gutenberg/pull/20003)) +- Add new $gray-200 SASS variable and use for skeleton borders. ([25491](https://github.com/WordPress/gutenberg/pull/25491)) +- Block Editor: Remove empty module focus-detector. ([25561](https://github.com/WordPress/gutenberg/pull/25561)) +- Image block: Avoid remounting to focus caption. ([25493](https://github.com/WordPress/gutenberg/pull/25493)) +- Add explicit boxSizing style to Placeholder component. ([25463](https://github.com/WordPress/gutenberg/pull/25463)) +- Remove classic block code used to support WP 4.9. ([25365](https://github.com/WordPress/gutenberg/pull/25365)) +- Add RichText value type definition. ([25363](https://github.com/WordPress/gutenberg/pull/25363)) +- Avoid global DOM dependencies. ([25332](https://github.com/WordPress/gutenberg/pull/25332)) +- Use controls from the Data Controls package instead of local ones. ([25235](https://github.com/WordPress/gutenberg/pull/25235)) +- RichText: Simplify withFormatTypes as hook. ([23145](https://github.com/WordPress/gutenberg/pull/23145)) +- Video block: Use hooks. ([25513](https://github.com/WordPress/gutenberg/pull/25513)) +- Remove wp_area custom post type. ([25497](https://github.com/WordPress/gutenberg/pull/25497)) +- Post Featured Image: Remove redundant condition. ([25490](https://github.com/WordPress/gutenberg/pull/25490)) +- Move legacy-widget block over to edit-widgets package. ([25371](https://github.com/WordPress/gutenberg/pull/25371)) ([25404](https://github.com/WordPress/gutenberg/pull/25404)) +- Don't use percent units for line-height. ([25398](https://github.com/WordPress/gutenberg/pull/25398)) +- Change wording and names to not include "whitelist". ([25396](https://github.com/WordPress/gutenberg/pull/25396)) +- Don't discard all promises results when one of them rejects. ([25302](https://github.com/WordPress/gutenberg/pull/25302)) +- Block Directory: Switch to `blocks.registerBlockType` filter. ([25264](https://github.com/WordPress/gutenberg/pull/25264)) +- Fix some javascript warnings. ([24996](https://github.com/WordPress/gutenberg/pull/24996)) + +### Various + +- Remove the Block-based widgets editor from the customizer. ([25626](https://github.com/WordPress/gutenberg/pull/25626)) +- Cover block: Remove default position (center/center) className from rendering. ([25346](https://github.com/WordPress/gutenberg/pull/25346)) +- Fix the default label position in SelectControl. ([25427](https://github.com/WordPress/gutenberg/pull/25427)) +- DropdownMenu tooltip default to true. ([25391](https://github.com/WordPress/gutenberg/pull/25391)) +- Pass block pattern name when using replaceBlocks and insertBlocks. ([25165](https://github.com/WordPress/gutenberg/pull/25165)). ([25433](https://github.com/WordPress/gutenberg/pull/25433)) +- Babel Preset: Update Babel version to 7.11.x. ([25351](https://github.com/WordPress/gutenberg/pull/25351)) +- InputControl: Remove floating label variant. ([25308](https://github.com/WordPress/gutenberg/pull/25308)) + + = 9.0.0 = ### Features diff --git a/docs/contributors/git-workflow.md b/docs/contributors/git-workflow.md index 3acfd27a36f0c8..0894945e8a2850 100644 --- a/docs/contributors/git-workflow.md +++ b/docs/contributors/git-workflow.md @@ -51,7 +51,7 @@ git switch -c update/my-branch **Step 4**: Make the code changes. Build, confirm, and test your change thoroughly. See [coding guidelines](/docs/contributors/coding-guidelines.md) and [testing overview](/docs/contributors/testing-overview.md) for guidance. -**Step 5**: Commit your change with a [good commmit message](https://make.wordpress.org/core/handbook/best-practices/commit-messages/). This will commit your change to your local copy of the repository. +**Step 5**: Commit your change with a [good commit message](https://make.wordpress.org/core/handbook/best-practices/commit-messages/). This will commit your change to your local copy of the repository. ```bash git commit -m "Your Good Commit Message" path/to/FILE diff --git a/docs/designers-developers/developers/block-api/README.md b/docs/designers-developers/developers/block-api/README.md index a388e05d9f76c7..dd8c6468882935 100644 --- a/docs/designers-developers/developers/block-api/README.md +++ b/docs/designers-developers/developers/block-api/README.md @@ -8,6 +8,7 @@ The following sections will walk you through the existing block APIs: - [Edit and Save](/docs/designers-developers/developers/block-api/block-edit-save.md) - [Attributes](/docs/designers-developers/developers/block-api/block-attributes.md) - [Deprecated blocks](/docs/designers-developers/developers/block-api/block-deprecation.md) +- [Supports](/docs/designers-developers/developers/block-api/block-supports.md) - [Transformations](/docs/designers-developers/developers/block-api/block-transforms.md) - [Templates](/docs/designers-developers/developers/block-api/block-templates.md) - [Annotations](/docs/designers-developers/developers/block-api/block-annotations.md) diff --git a/docs/designers-developers/developers/block-api/block-metadata.md b/docs/designers-developers/developers/block-api/block-metadata.md index 4613b3f2fa96ee..24d1468121ba29 100644 --- a/docs/designers-developers/developers/block-api/block-metadata.md +++ b/docs/designers-developers/developers/block-api/block-metadata.md @@ -11,6 +11,7 @@ To register a new block type using metadata that can be shared between codebase ```json { + "apiVersion": 2, "name": "my-plugin/notice", "title": "Notice", "category": "text", @@ -32,7 +33,6 @@ To register a new block type using metadata that can be shared between codebase "usesContext": [ "groupId" ], "supports": { "align": true, - "lightBlockWrapper": true }, "styles": [ { "name": "default", "label": "Default", "isDefault": true }, @@ -255,9 +255,7 @@ See [the block context documentation](/docs/designers-developers/developers/bloc - Property: `supports` - Default: `{}` -It contains as set of options to control features used in the editor. - -See the [the supports documentation](/docs/designers-developers/developers/block-api/block-registration.md#supports-optional) for more details. +It contains as set of options to control features used in the editor. See the [the supports documentation](/docs/designers-developers/developers/block-api/block-supports.md) for more details. ### Style Variations diff --git a/docs/designers-developers/developers/block-api/block-registration.md b/docs/designers-developers/developers/block-api/block-registration.md index e6987e1cfed369..711ca1acef0c38 100644 --- a/docs/designers-developers/developers/block-api/block-registration.md +++ b/docs/designers-developers/developers/block-api/block-registration.md @@ -270,6 +270,12 @@ variations: [ ], ``` +#### supports (optional) + +- ***Type:*** `Object` + +Supports contains as set of options to control features used in the editor. See the [the supports documentation](/docs/designers-developers/developers/block-api/block-supports.md) for more details. + #### transforms (optional) - **Type:** `Object` @@ -289,103 +295,6 @@ Setting `parent` lets a block require that it is only available when nested with parent: [ 'core/columns' ], ``` -#### supports (optional) - -_Some [block supports](#supports-optional) — for example, `anchor` or `className` — apply their attributes by adding additional props on the element returned by `save`. This will work automatically for default HTML tag elements (`div`, etc). However, if the return value of your `save` is a custom component element, you will need to ensure that your custom component handles these props in order for the attributes to be persisted._ - -- **Type:** `Object` - -Optional block extended support features. The following options are supported: - -- `align` (default `false`): This property adds block controls which allow to change block's alignment. _Important: It doesn't work with dynamic blocks yet._ - -```js -// Add the support for block's alignment (left, center, right, wide, full). -align: true, -// Pick which alignment options to display. -align: [ 'left', 'right', 'full' ], -``` - -When supports align is used the block attributes definition is extended to include an align attribute with a string type. -By default, no alignment is assigned to the block. -The block can apply a default alignment by specifying its own align attribute with a default e.g.: - -``` -attributes: { - ... - align: { - type: 'string', - default: 'right' - }, - ... -} -``` - -- `alignWide` (default `true`): This property allows to enable [wide alignment](/docs/designers-developers/developers/themes/theme-support.md#wide-alignment) for your theme. To disable this behavior for a single block, set this flag to `false`. - -```js -// Remove the support for wide alignment. -alignWide: false, -``` - -- `defaultStylePicker` (default `true`): When the style picker is shown, a dropdown is displayed so the user can select a default style for this block type. If you prefer not to show the dropdown, set this property to `false`. - -```js -// Remove the Default Style picker. -defaultStylePicker: false, -``` - - -- `anchor` (default `false`): Anchors let you link directly to a specific block on a page. This property adds a field to define an id for the block and a button to copy the direct link. - -```js -// Add the support for an anchor link. -anchor: true, -``` - -- `customClassName` (default `true`): This property adds a field to define a custom className for the block's wrapper. - -```js -// Remove the support for the custom className. -customClassName: false, -``` - -- `className` (default `true`): By default, the class `.wp-block-your-block-name` is added to the root element of your saved markup. This helps having a consistent mechanism for styling blocks that themes and plugins can rely on. If for whatever reason a class is not desired on the markup, this functionality can be disabled. - -```js -// Remove the support for the generated className. -className: false, -``` - -- `html` (default `true`): By default, a block's markup can be edited individually. To disable this behavior, set `html` to `false`. - -```js -// Remove support for an HTML mode. -html: false, -``` - -- `inserter` (default `true`): By default, all blocks will appear in the inserter. To hide a block so that it can only be inserted programmatically, set `inserter` to `false`. - -```js -// Hide this block from the inserter. -inserter: false, -``` - -- `multiple` (default `true`): A non-multiple block can be inserted into each post, one time only. For example, the built-in 'More' block cannot be inserted again if it already exists in the post being edited. A non-multiple block's icon is automatically dimmed (unclickable) to prevent multiple instances. - -```js -// Use the block just once per post -multiple: false, -``` - -- `reusable` (default `true`): A block may want to disable the ability of being converted into a reusable block. - By default all blocks can be converted to a reusable block. If supports reusable is set to false, the option to convert the block into a reusable block will not appear. - -```js -// Don't allow the block to be converted into a reusable block. -reusable: false, -``` - ## Block Collections ## `registerBlockCollection` diff --git a/docs/designers-developers/developers/block-api/block-supports.md b/docs/designers-developers/developers/block-api/block-supports.md new file mode 100644 index 00000000000000..d0e459257d933b --- /dev/null +++ b/docs/designers-developers/developers/block-api/block-supports.md @@ -0,0 +1,165 @@ +# Block Supports + +Block Supports is the API that allows a block to declare features used in the editor. + +Some block supports — for example, `anchor` or `className` — apply their attributes by adding additional props on the element returned by `save`. This will work automatically for default HTML tag elements (`div`, etc). However, if the return value of your `save` is a custom component element, you will need to ensure that your custom component handles these props in order for the attributes to be persisted. + +## anchor + +- Type: `boolean` +- Default value: `false` + +Anchors let you link directly to a specific block on a page. This property adds a field to define an id for the block and a button to copy the direct link. + +```js +// Declare support for anchor links. +supports: { + anchor: true +} +``` + +## align + +- Type: `boolean` or `array` +- Default value: `false` + +This property adds block controls which allow to change block's alignment. _Important: It doesn't work with dynamic blocks yet._ + +```js +supports: { + // Declare support for block's alignment. + // This adds support for all the options: + // left, center, right, wide, and full. + align: true +} +``` + +```js +supports: { + // Declare support for specific alignment options. + align: [ 'left', 'right', 'full' ] +} +``` + +When the block declares support for `align`, the attributes definition is extended to include an align attribute with a `string` type. By default, no alignment is assigned. The block can apply a default alignment by specifying its own `align` attribute with a default e.g.: + +```js +attributes: { + align: { + type: 'string', + default: 'right' + } +} +``` + +## alignWide + +- Type: `boolean` +- Default value: `true` + +This property allows to enable [wide alignment](/docs/designers-developers/developers/themes/theme-support.md#wide-alignment) for your theme. To disable this behavior for a single block, set this flag to `false`. + +```js +supports: { + // Remove the support for wide alignment. + alignWide: false +} +``` + +## className + +- Type: `boolean` +- Default value: `true` + +By default, the class `.wp-block-your-block-name` is added to the root element of your saved markup. This helps having a consistent mechanism for styling blocks that themes and plugins can rely on. If, for whatever reason, a class is not desired on the markup, this functionality can be disabled. + +```js +supports: { + // Remove the support for the generated className. + className: false +} +``` + +## customClassName + +- Type: `boolean` +- Default value: `true` + +This property adds a field to define a custom className for the block's wrapper. + +```js +supports: { + // Remove the support for the custom className. + customClassName: false +} +``` + +## defaultStylePicker + +- Type: `boolean` +- Default value: `true` + +When the style picker is shown, a dropdown is displayed so the user can select a default style for this block type. If you prefer not to show the dropdown, set this property to `false`. + +```js +supports: { + // Remove the Default Style picker. + defaultStylePicker: false +} +``` + +## html + +- Type: `boolean` +- Default value: `true` + +By default, a block's markup can be edited individually. To disable this behavior, set `html` to `false`. + +```js +supports: { + // Remove support for an HTML mode. + html: false +} +``` + +## inserter + +- Type: `boolean` +- Default value: `true` + +By default, all blocks will appear in the inserter. To hide a block so that it can only be inserted programmatically, set `inserter` to `false`. + +```js +supports: { + // Hide this block from the inserter. + inserter: false +} +``` + +## multiple + +- Type: `boolean` +- Default value: `true` + +A non-multiple block can be inserted into each post, one time only. For example, the built-in 'More' block cannot be inserted again if it already exists in the post being edited. A non-multiple block's icon is automatically dimmed (unclickable) to prevent multiple instances. + +```js +supports: { + // Use the block just once per post + multiple: false +} +``` + +## reusable + +- Type: `boolean` +- Default value: `true` + +A block may want to disable the ability of being converted into a reusable block. By default all blocks can be converted to a reusable block. If supports reusable is set to false, the option to convert the block into a reusable block will not appear. + +```js +supports: { + // Don't allow the block to be converted into a reusable block. + reusable: false +} +``` diff --git a/docs/designers-developers/developers/themes/block-based-themes.md b/docs/designers-developers/developers/themes/block-based-themes.md index 4889a36580bd48..03f4f278b9a256 100644 --- a/docs/designers-developers/developers/themes/block-based-themes.md +++ b/docs/designers-developers/developers/themes/block-based-themes.md @@ -17,6 +17,7 @@ A very simple block-based theme is structured like so: ``` theme |__ style.css +|__ experimental-theme.json |__ functions.php |__ block-templates |__ index.html @@ -30,7 +31,7 @@ theme |__ ... ``` -The difference with existing WordPress themes is that the different templates in the template hierarchy, and template parts, are block templates instead of php files. +The difference with existing WordPress themes is that the different templates in the template hierarchy, and template parts, are block templates instead of php files. In addition, this example includes an [`experimental-theme.json`](/docs/designers-developers/developers/themes/theme-json.md) file for some styles. ## What is a block template? @@ -111,17 +112,21 @@ As we're still early in the process, the number of blocks specifically dedicated - Post Title - Post Content - Post Author +- Post Comment +- Post Comment Author +- Post Comment Date - Post Comments -- Post CommentsCount -- Post CommentsForm +- Post Comments Count +- Post Comments Form - Post Date - Post Excerpt - Post Featured Image +- Post Hierarchical Terms - Post Tags ## Styling -One of the most important aspects of themes (if not the most important) is the styling. While initially you'll be able to provide styles and enqueue them using the same hooks themes have always used, this is an area that is still [being explored](https://github.com/WordPress/gutenberg/issues/9534). +One of the most important aspects of themes (if not the most important) is the styling. While initially you'll be able to provide styles and enqueue them using the same hooks themes have always used, the [Global Styles](/docs/designers-developers/developers/themes/theme-json.md) effort will provide a scaffolding for adding many theme styles in the future. ## Resources diff --git a/docs/designers-developers/developers/tutorials/block-based-themes/README.md b/docs/designers-developers/developers/tutorials/block-based-themes/README.md index 820403bdbc656a..6d819840ac8987 100644 --- a/docs/designers-developers/developers/tutorials/block-based-themes/README.md +++ b/docs/designers-developers/developers/tutorials/block-based-themes/README.md @@ -238,9 +238,10 @@ Add the following global presets to the experimental-theme.json file: "slug": "large", "value": "2.5" } - ], - }, - }, + ] + } + } +} ``` This code generates the following variables: diff --git a/docs/designers-developers/developers/tutorials/create-block/wp-plugin.md b/docs/designers-developers/developers/tutorials/create-block/wp-plugin.md index 8a1eaf87ff53f3..e97313bddf6fb6 100644 --- a/docs/designers-developers/developers/tutorials/create-block/wp-plugin.md +++ b/docs/designers-developers/developers/tutorials/create-block/wp-plugin.md @@ -55,7 +55,7 @@ Let's confirm the plugin is loaded and working. wp-env start ``` -This will start your local WordPress site and use the current directory as your plugin directory. In your browser, go to https://localhost:8888/wp-admin/ and login, the default username is "admin" and password is "password", no quotes. +This will start your local WordPress site and use the current directory as your plugin directory. In your browser, go to http://localhost:8888/wp-admin/ and login, the default username is "admin" and password is "password", no quotes. ### Confirm Plugin Installed diff --git a/docs/manifest.json b/docs/manifest.json index c51b32e20f9442..4983d6c4b34804 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -119,6 +119,12 @@ "markdown_source": "../docs/designers-developers/developers/block-api/block-deprecation.md", "parent": "block-api" }, + { + "title": "Block Supports", + "slug": "block-supports", + "markdown_source": "../docs/designers-developers/developers/block-api/block-supports.md", + "parent": "block-api" + }, { "title": "Block Transforms", "slug": "block-transforms", diff --git a/docs/toc.json b/docs/toc.json index 47dfa25425ceb3..7013a98ccc2ca6 100644 --- a/docs/toc.json +++ b/docs/toc.json @@ -21,6 +21,7 @@ { "docs/designers-developers/developers/block-api/block-attributes.md": [] }, { "docs/designers-developers/developers/block-api/block-context.md": [] }, { "docs/designers-developers/developers/block-api/block-deprecation.md": [] }, + { "docs/designers-developers/developers/block-api/block-supports.md": [] }, { "docs/designers-developers/developers/block-api/block-transforms.md": [] }, { "docs/designers-developers/developers/block-api/block-templates.md": [] }, { "docs/designers-developers/developers/block-api/block-patterns.md": [] }, diff --git a/gutenberg.php b/gutenberg.php index 2cda8621d0e063..4cf9aacec6ce6a 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the new block editor in core. * Requires at least: 5.3 * Requires PHP: 5.6 - * Version: 9.0.0 + * Version: 9.1.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/lib/block-supports/colors.php b/lib/block-supports/colors.php index 8649b14d6d6095..b0bb4e1e22ada9 100644 --- a/lib/block-supports/colors.php +++ b/lib/block-supports/colors.php @@ -13,7 +13,7 @@ function gutenberg_register_colors_support( $block_type ) { $color_support = false; if ( property_exists( $block_type, 'supports' ) ) { - $color_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalColor' ), false ); + $color_support = gutenberg_experimental_get( $block_type->supports, array( 'color' ), false ); } $has_text_colors_support = true === $color_support || ( is_array( $color_support ) && gutenberg_experimental_get( $color_support, array( 'text' ), true ) ); $has_background_colors_support = true === $color_support || ( is_array( $color_support ) && gutenberg_experimental_get( $color_support, array( 'background' ), true ) ); @@ -60,10 +60,10 @@ function gutenberg_register_colors_support( $block_type ) { * @return array Colors CSS classes and inline styles. */ function gutenberg_apply_colors_support( $attributes, $block_attributes, $block_type ) { - $color_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalColor' ), false ); + $color_support = gutenberg_experimental_get( $block_type->supports, array( 'color' ), false ); $has_text_colors_support = true === $color_support || ( is_array( $color_support ) && gutenberg_experimental_get( $color_support, array( 'text' ), true ) ); $has_background_colors_support = true === $color_support || ( is_array( $color_support ) && gutenberg_experimental_get( $color_support, array( 'background' ), true ) ); - $has_link_colors_support = gutenberg_experimental_get( $color_support, array( 'linkColor' ), false ); + $has_link_colors_support = gutenberg_experimental_get( $color_support, array( 'link' ), false ); $has_gradients_support = gutenberg_experimental_get( $color_support, array( 'gradients' ), false ); // Text Colors. diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index 083a6ee477b900..ef33c3249ade17 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -13,12 +13,12 @@ function gutenberg_register_typography_support( $block_type ) { $has_font_size_support = false; if ( property_exists( $block_type, 'supports' ) ) { - $has_font_size_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalFontSize' ), false ); + $has_font_size_support = gutenberg_experimental_get( $block_type->supports, array( 'fontSize' ), false ); } $has_line_height_support = false; if ( property_exists( $block_type, 'supports' ) ) { - $has_line_height_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalLineHeight' ), false ); + $has_line_height_support = gutenberg_experimental_get( $block_type->supports, array( 'lineHeight' ), false ); } if ( ! $block_type->attributes ) { @@ -51,12 +51,12 @@ function gutenberg_register_typography_support( $block_type ) { function gutenberg_apply_typography_support( $attributes, $block_attributes, $block_type ) { $has_font_size_support = false; if ( property_exists( $block_type, 'supports' ) ) { - $has_font_size_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalFontSize' ), false ); + $has_font_size_support = gutenberg_experimental_get( $block_type->supports, array( 'fontSize' ), false ); } $has_line_height_support = false; if ( property_exists( $block_type, 'supports' ) ) { - $has_line_height_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalLineHeight' ), false ); + $has_line_height_support = gutenberg_experimental_get( $block_type->supports, array( 'lineHeight' ), false ); } // Font Size. diff --git a/lib/blocks.php b/lib/blocks.php index 0aa7c62e725b9d..a35f6a659bd294 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -45,7 +45,6 @@ function gutenberg_reregister_core_block_types() { 'text-columns', 'verse', 'video', - 'widget-area', ), 'block_names' => array_merge( array( @@ -96,9 +95,11 @@ function gutenberg_reregister_core_block_types() { dirname( __FILE__ ) . '/../build/edit-widgets/blocks/' => array( 'block_folders' => array( 'legacy-widget', + 'widget-area', ), 'block_names' => array( 'legacy-widget.php' => 'core/legacy-widget', + 'widget-area.php' => 'core/widget-area', ), ), ); diff --git a/lib/class-wp-customize-widget-blocks-control.php b/lib/class-wp-customize-widget-blocks-control.php deleted file mode 100644 index e92fef67c1577d..00000000000000 --- a/lib/class-wp-customize-widget-blocks-control.php +++ /dev/null @@ -1,40 +0,0 @@ - - link(); ?> - /> - 350, ); parent::__construct( 'block', __( 'Block', 'gutenberg' ), $widget_ops, $control_ops ); + add_action( 'is_wide_widget_in_customizer', array( $this, 'set_is_wide_widget_in_customizer' ), 10, 2 ); } /** * Outputs the content for the current Block widget instance. * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Block widget instance. + * * @since 4.8.1 * * @global WP_Post $post Global post object. - * - * @param array $args Display arguments including 'before_title', 'after_title', - * 'before_widget', and 'after_widget'. - * @param array $instance Settings for the current Block widget instance. */ public function widget( $args, $instance ) { + echo $args['before_widget']; echo do_blocks( $instance['content'] ); + echo $args['after_widget']; } /** * Handles updating settings for the current Block widget instance. * - * @since 4.8.1 - * * @param array $new_instance New settings for this instance as input by the user via * WP_Widget::form(). * @param array $old_instance Old settings for this instance. + * * @return array Settings to save or bool false to cancel saving. + * @since 4.8.1 */ public function update( $new_instance, $old_instance ) { $instance = array_merge( $this->default_instance, $old_instance ); $instance['content'] = $new_instance['content']; + return $instance; } /** * Outputs the Block widget settings form. * - * @see WP_Widget_Custom_HTML::render_control_template_scripts() - * * @param array $instance Current instance. + * + * @see WP_Widget_Custom_HTML::render_control_template_scripts() */ public function form( $instance ) { $instance = wp_parse_args( (array) $instance, $this->default_instance ); echo do_blocks( $instance['content'] ); + $textarea_id = $this->get_field_id( 'content' ); ?> - +
+ + add_setting( - 'gutenberg_widget_blocks', - array( - 'default' => '{}', - 'type' => 'gutenberg_widget_blocks', - 'capability' => 'edit_theme_options', - 'transport' => 'postMessage', - 'sanitize_callback' => 'gutenberg_customize_sanitize', - ) - ); - - if ( gutenberg_use_widgets_block_editor() ) { - $wp_customize->add_section( - 'gutenberg_widget_blocks', - array( 'title' => __( 'Widget Blocks', 'gutenberg' ) ) - ); - $wp_customize->add_control( - new WP_Customize_Widget_Blocks_Control( - $wp_customize, - 'gutenberg_widget_blocks', - array( - 'section' => 'gutenberg_widget_blocks', - 'settings' => 'gutenberg_widget_blocks', - ) - ) - ); - } -} -add_action( 'customize_register', 'gutenberg_customize_register' ); - -/** - * Removes the core 'Widgets' panel from the Customizer if block based widgets are enabled. - * - * @param array $components Core Customizer components list. - * @return array (Maybe) modified components list. - */ -function gutenberg_remove_widgets_panel( $components ) { - if ( ! gutenberg_use_widgets_block_editor() ) { - return $components; - } - - $i = array_search( 'widgets', $components, true ); - if ( false !== $i ) { - unset( $components[ $i ] ); - } - return $components; -} -add_filter( 'customize_loaded_components', 'gutenberg_remove_widgets_panel' ); - -/** - * Filters the Customizer widget settings arguments. - * This is needed because the Customizer registers settings for the raw registered widgets, without going through the `sidebars_widgets` filter. - * The `WP_Customize_Widgets` class expects sidebars to have an array of widgets registered, not a post ID. - * This results in the value passed to `sanitize_js_callback` being `null` and throwing an error. - * - * TODO: Figure out why core is not running the `sidebars_widgets` filter for the relevant part of the code. - * Then, either fix it or change this filter to parse the post IDs and then pass them to the original `sanitize_js_callback`. - * - * @param array $args Array of Customizer setting arguments. - * @param string $id Widget setting ID. - * @return array Maybe modified array of Customizer setting arguments. - */ -function filter_widget_customizer_setting_args( $args, $id = null ) { - // Posts won't have a settings ID like widgets. We can use that to remove the sanitization callback. - if ( ! isset( $id ) ) { - unset( $args['sanitize_js_callback'] ); - } - - return $args; -} -add_filter( 'widget_customizer_setting_args', 'filter_widget_customizer_setting_args' ); diff --git a/lib/edit-site-page.php b/lib/edit-site-page.php index 689e628c6eeae7..83089981f59756 100644 --- a/lib/edit-site-page.php +++ b/lib/edit-site-page.php @@ -131,6 +131,7 @@ function gutenberg_edit_site_init( $hook ) { 'isRTL' => is_rtl(), 'maxUploadFileSize' => $max_upload_size, 'siteUrl' => site_url(), + 'postsPerPage' => get_option( 'posts_per_page' ), ); $settings['styles'] = gutenberg_get_editor_styles(); diff --git a/lib/global-styles.php b/lib/global-styles.php index 1fbdf36f00d95c..e4ec344af7738e 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -417,12 +417,12 @@ function gutenberg_experimental_global_styles_get_style_property() { */ function gutenberg_experimental_global_styles_get_support_keys() { return array( - '--wp--style--color--link' => array( '__experimentalColor', 'linkColor' ), - 'background' => array( '__experimentalColor', 'gradients' ), - 'backgroundColor' => array( '__experimentalColor' ), - 'color' => array( '__experimentalColor' ), - 'fontSize' => array( '__experimentalFontSize' ), - 'lineHeight' => array( '__experimentalLineHeight' ), + '--wp--style--color--link' => array( 'color', 'linkColor' ), + 'background' => array( 'color', 'gradients' ), + 'backgroundColor' => array( 'color' ), + 'color' => array( 'color' ), + 'fontSize' => array( 'fontSize' ), + 'lineHeight' => array( 'lineHeight' ), ); } @@ -484,8 +484,8 @@ function gutenberg_experimental_global_styles_get_block_data() { array( 'supports' => array( '__experimentalSelector' => ':root', - '__experimentalFontSize' => true, - '__experimentalColor' => array( + 'fontSize' => true, + 'color' => array( 'linkColor' => true, 'gradients' => true, ), diff --git a/lib/load.php b/lib/load.php index 540539f56ba59a..435941c323d0dc 100644 --- a/lib/load.php +++ b/lib/load.php @@ -113,7 +113,6 @@ function gutenberg_is_experiment_enabled( $name ) { require dirname( __FILE__ ) . '/navigation.php'; require dirname( __FILE__ ) . '/navigation-page.php'; require dirname( __FILE__ ) . '/experiments-page.php'; -require dirname( __FILE__ ) . '/customizer.php'; require dirname( __FILE__ ) . '/global-styles.php'; require dirname( __FILE__ ) . '/block-supports/index.php'; require dirname( __FILE__ ) . '/block-supports/align.php'; diff --git a/lib/widgets-page.php b/lib/widgets-page.php index 4a12f51e550e31..f620d27865b68a 100644 --- a/lib/widgets-page.php +++ b/lib/widgets-page.php @@ -9,20 +9,12 @@ * The main entry point for the Gutenberg widgets page. * * @since 5.2.0 - * - * @param string $page The page name the function is being called for, `'gutenberg_customizer'` for the Customizer. */ -function the_gutenberg_widgets( $page = 'appearance_page_gutenberg-widgets' ) { +function the_gutenberg_widgets() { ?>
+ +# **addInstalledBlockType** + +Returns an action object used to add a block type to the "newly installed" +tracking list. + +_Parameters_ + +- _item_ `Object`: The block item with the block id and name. + +_Returns_ + +- `Object`: Action object. + +# **clearErrorNotice** + +Sets the error notice to empty for specific block. + +_Parameters_ + +- _blockId_ `string`: The ID of the block plugin. eg: my-block + +_Returns_ + +- `Object`: Action object. + +# **fetchDownloadableBlocks** + +Returns an action object used in signalling that the downloadable blocks +have been requested and are loading. + +_Parameters_ + +- _filterValue_ `string`: Search string. + +_Returns_ + +- `Object`: Action object. + +# **installBlockType** + +Action triggered to install a block plugin. + +_Parameters_ + +- _block_ `Object`: The block item returned by search. + +_Returns_ + +- `boolean`: Whether the block was successfully installed & loaded. + +# **receiveDownloadableBlocks** + +Returns an action object used in signalling that the downloadable blocks +have been updated. + +_Parameters_ + +- _downloadableBlocks_ `Array`: Downloadable blocks. +- _filterValue_ `string`: Search string. + +_Returns_ + +- `Object`: Action object. + +# **removeInstalledBlockType** + +Returns an action object used to remove a block type from the "newly installed" +tracking list. + +_Parameters_ + +- _item_ `string`: The block item with the block id and name. + +_Returns_ + +- `Object`: Action object. + +# **setErrorNotice** + +Sets an error notice to be displayed to the user for a given block. + +_Parameters_ + +- _blockId_ `string`: The ID of the block plugin. eg: my-block +- _message_ `string`: The message shown in the notice. +- _isFatal_ `boolean`: Whether the user can recover from the error. + +_Returns_ + +- `Object`: Action object. + +# **setIsInstalling** + +Returns an action object used to indicate install in progress. + +_Parameters_ + +- _blockId_ `string`: +- _isInstalling_ `boolean`: + +_Returns_ + +- `Object`: Action object. + +# **uninstallBlockType** + +Action triggered to uninstall a block plugin. + +_Parameters_ + +- _block_ `Object`: The blockType object. + + + +## Selectors + +The following selectors are available on the object returned by `wp.data.select( 'core/block-directory' )`: + + + +# **getDownloadableBlocks** + +Returns the available uninstalled blocks. + +_Parameters_ + +- _state_ `Object`: Global application state. +- _filterValue_ `string`: Search string. + +_Returns_ + +- `Array`: Downloadable blocks. + +# **getErrorNoticeForBlock** + +Returns the error notice for a given block. + +_Parameters_ + +- _state_ `Object`: Global application state. +- _blockId_ `string`: The ID of the block plugin. eg: my-block + +_Returns_ + +- `(string|boolean)`: The error text, or false if no error. + +# **getErrorNotices** + +Returns all block error notices. + +_Parameters_ + +- _state_ `Object`: Global application state. + +_Returns_ + +- `Object`: Object with error notices. + +# **getInstalledBlockTypes** + +Returns the block types that have been installed on the server in this +session. + +_Parameters_ + +- _state_ `Object`: Global application state. + +_Returns_ + +- `Array`: Block type items + +# **getNewBlockTypes** + +Returns block types that have been installed on the server and used in the +current post. + +_Parameters_ + +- _state_ `Object`: Global application state. + +_Returns_ + +- `Array`: Block type items. + +# **getUnusedBlockTypes** + +Returns the block types that have been installed on the server but are not +used in the current post. + +_Parameters_ + +- _state_ `Object`: Global application state. + +_Returns_ + +- `Array`: Block type items. + +# **isInstalling** + +Returns true if a block plugin install is in progress. + +_Parameters_ + +- _state_ `Object`: Global application state. +- _blockId_ `string`: Id of the block. + +_Returns_ + +- `boolean`: Whether this block is currently being installed. + +# **isRequestingDownloadableBlocks** + +Returns true if application is requesting for downloadable blocks. + +_Parameters_ + +- _state_ `Object`: Global application state. +- _filterValue_ `string`: Search string. + +_Returns_ + +- `boolean`: Whether a request is in progress for the blocks list. + + + +

Code is Poetry.

diff --git a/packages/block-directory/src/plugins/filter-missing/index.js b/packages/block-directory/src/plugins/filter-missing/index.js deleted file mode 100644 index 2b958ad54eb51a..00000000000000 --- a/packages/block-directory/src/plugins/filter-missing/index.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * WordPress dependencies - */ -import { __, sprintf } from '@wordpress/i18n'; -import { Button } from '@wordpress/components'; -import { RawHTML } from '@wordpress/element'; -import { useSelect } from '@wordpress/data'; -import { Warning } from '@wordpress/block-editor'; - -/** - * Internal dependencies - */ -import InstallButton from './install-button'; - -const filterMissing = ( OriginalComponent ) => ( props ) => { - const { originalName, originalUndelimitedContent } = props.attributes; - const { block, hasPermission } = useSelect( - ( select ) => { - const { getDownloadableBlocks } = select( 'core/block-directory' ); - const blocks = getDownloadableBlocks( - 'block:' + originalName - ).filter( ( { name } ) => originalName === name ); - return { - hasPermission: select( 'core' ).canUser( - 'read', - 'block-directory/search' - ), - block: blocks.length && blocks[ 0 ], - }; - }, - [ originalName ] - ); - - if ( ! hasPermission || ! block ) { - return ; - } - - const actions = [ - , - , - ]; - - return ( - <> - - { sprintf( - /* translators: %s: block name */ - __( - 'Your site doesn’t include support for the %s block. You can try installing the block, convert it to a Custom HTML block, or remove it entirely.' - ), - block.title || originalName - ) } - - { originalUndelimitedContent } - - ); -}; - -export default filterMissing; diff --git a/packages/block-directory/src/plugins/get-install-missing/index.js b/packages/block-directory/src/plugins/get-install-missing/index.js new file mode 100644 index 00000000000000..da4337e69249c0 --- /dev/null +++ b/packages/block-directory/src/plugins/get-install-missing/index.js @@ -0,0 +1,93 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { Button } from '@wordpress/components'; +import { createBlock, getBlockType } from '@wordpress/blocks'; +import { RawHTML } from '@wordpress/element'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { Warning } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import InstallButton from './install-button'; + +const getInstallMissing = ( OriginalComponent ) => ( props ) => { + const { originalName, originalUndelimitedContent } = props.attributes; + // Disable reason: This is a valid component, but it's mistaken for a callback. + // eslint-disable-next-line react-hooks/rules-of-hooks + const { block, hasPermission } = useSelect( + ( select ) => { + const { getDownloadableBlocks } = select( 'core/block-directory' ); + const blocks = getDownloadableBlocks( + 'block:' + originalName + ).filter( ( { name } ) => originalName === name ); + return { + hasPermission: select( 'core' ).canUser( + 'read', + 'block-directory/search' + ), + block: blocks.length && blocks[ 0 ], + }; + }, + [ originalName ] + ); + + const { replaceBlock } = useDispatch( 'core/block-editor' ); + const convertToHTML = () => { + replaceBlock( + props.clientId, + createBlock( 'core/html', { + content: originalUndelimitedContent, + } ) + ); + }; + + if ( ! hasPermission || ! block ) { + return ; + } + + const hasContent = !! originalUndelimitedContent; + const hasHTMLBlock = getBlockType( 'core/html' ); + + let messageHTML = sprintf( + /* translators: %s: block name */ + __( + 'Your site doesn’t include support for the %s block. You can try installing the block or remove it entirely.' + ), + block.title || originalName + ); + const actions = [ + , + ]; + + if ( hasContent && hasHTMLBlock ) { + messageHTML = sprintf( + /* translators: %s: block name */ + __( + 'Your site doesn’t include support for the %s block. You can try installing the block, convert it to a Custom HTML block, or remove it entirely.' + ), + block.title || originalName + ); + actions.push( + + ); + } + + return ( + <> + { messageHTML } + { originalUndelimitedContent } + + ); +}; + +export default getInstallMissing; diff --git a/packages/block-directory/src/plugins/filter-missing/install-button.js b/packages/block-directory/src/plugins/get-install-missing/install-button.js similarity index 100% rename from packages/block-directory/src/plugins/filter-missing/install-button.js rename to packages/block-directory/src/plugins/get-install-missing/install-button.js diff --git a/packages/block-directory/src/plugins/index.js b/packages/block-directory/src/plugins/index.js index beb9aac416e31a..283ff0ea4d2715 100644 --- a/packages/block-directory/src/plugins/index.js +++ b/packages/block-directory/src/plugins/index.js @@ -10,7 +10,7 @@ import { addFilter } from '@wordpress/hooks'; import AutoBlockUninstaller from '../components/auto-block-uninstaller'; import InserterMenuDownloadableBlocksPanel from './inserter-menu-downloadable-blocks-panel'; import InstalledBlocksPrePublishPanel from './installed-blocks-pre-publish-panel'; -import filterMissing from './filter-missing'; +import getInstallMissing from './get-install-missing'; registerPlugin( 'block-directory', { render() { @@ -25,7 +25,14 @@ registerPlugin( 'block-directory', { } ); addFilter( - 'editor.missingEdit', - 'block-directory/install-missing', - filterMissing + 'blocks.registerBlockType', + 'block-directory/fallback', + ( settings, name ) => { + if ( name !== 'core/missing' ) { + return settings; + } + settings.edit = getInstallMissing( settings.edit ); + + return settings; + } ); diff --git a/packages/block-directory/src/store/actions.js b/packages/block-directory/src/store/actions.js index 9f1e96d5db26ba..905c46590a654a 100644 --- a/packages/block-directory/src/store/actions.js +++ b/packages/block-directory/src/store/actions.js @@ -12,7 +12,7 @@ import getPluginUrl from './utils/get-plugin-url'; /** * Returns an action object used in signalling that the downloadable blocks - * have been requested and is loading. + * have been requested and are loading. * * @param {string} filterValue Search string. * @@ -150,7 +150,8 @@ export function* uninstallBlockType( block ) { } /** - * Returns an action object used to add a newly installed block type. + * Returns an action object used to add a block type to the "newly installed" + * tracking list. * * @param {Object} item The block item with the block id and name. * @@ -164,7 +165,8 @@ export function addInstalledBlockType( item ) { } /** - * Returns an action object used to remove a newly installed block type. + * Returns an action object used to remove a block type from the "newly installed" + * tracking list. * * @param {string} item The block item with the block id and name. * @@ -178,7 +180,7 @@ export function removeInstalledBlockType( item ) { } /** - * Returns an action object used to indicate install in progress + * Returns an action object used to indicate install in progress. * * @param {string} blockId * @param {boolean} isInstalling @@ -194,11 +196,11 @@ export function setIsInstalling( blockId, isInstalling ) { } /** - * Sets an error notice string to be displayed to the user + * Sets an error notice to be displayed to the user for a given block. * - * @param {string} blockId The ID of the block plugin. eg: my-block + * @param {string} blockId The ID of the block plugin. eg: my-block * @param {string} message The message shown in the notice. - * @param {boolean} isFatal Whether the user can recover from the error + * @param {boolean} isFatal Whether the user can recover from the error. * * @return {Object} Action object. */ @@ -212,7 +214,7 @@ export function setErrorNotice( blockId, message, isFatal = false ) { } /** - * Sets the error notice to empty for specific block + * Sets the error notice to empty for specific block. * * @param {string} blockId The ID of the block plugin. eg: my-block * diff --git a/packages/block-directory/src/store/selectors.js b/packages/block-directory/src/store/selectors.js index 2d14bb029467fd..dbf94678436e82 100644 --- a/packages/block-directory/src/store/selectors.js +++ b/packages/block-directory/src/store/selectors.js @@ -11,11 +11,10 @@ import hasBlockType from './utils/has-block-type'; /** * Returns true if application is requesting for downloadable blocks. * - * @param {Object} state Global application state. + * @param {Object} state Global application state. * @param {string} filterValue Search string. * - * - * @return {Array} Downloadable blocks + * @return {boolean} Whether a request is in progress for the blocks list. */ export function isRequestingDownloadableBlocks( state, filterValue ) { if ( @@ -28,12 +27,12 @@ export function isRequestingDownloadableBlocks( state, filterValue ) { } /** - * Returns the available uninstalled blocks + * Returns the available uninstalled blocks. * * @param {Object} state Global application state. * @param {string} filterValue Search string. * - * @return {Array} Downloadable blocks + * @return {Array} Downloadable blocks. */ export function getDownloadableBlocks( state, filterValue ) { if ( @@ -46,11 +45,12 @@ export function getDownloadableBlocks( state, filterValue ) { } /** - * Returns the block types that have been installed on the server. + * Returns the block types that have been installed on the server in this + * session. * * @param {Object} state Global application state. * - * @return {Array} Block type items. + * @return {Array} Block type items */ export function getInstalledBlockTypes( state ) { return state.blockManagement.installedBlockTypes; @@ -95,19 +95,19 @@ export const getUnusedBlockTypes = createRegistrySelector( ); /** - * Returns true if application is calling install endpoint. + * Returns true if a block plugin install is in progress. * - * @param {Object} state Global application state. + * @param {Object} state Global application state. * @param {string} blockId Id of the block. * - * @return {boolean} Whether its currently installing + * @return {boolean} Whether this block is currently being installed. */ export function isInstalling( state, blockId ) { return state.blockManagement.isInstalling[ blockId ] || false; } /** - * Returns the error notices + * Returns all block error notices. * * @param {Object} state Global application state. * diff --git a/packages/block-directory/src/store/test/actions.js b/packages/block-directory/src/store/test/actions.js index b74f7f1a657725..516f6deef3fe1d 100644 --- a/packages/block-directory/src/store/test/actions.js +++ b/packages/block-directory/src/store/test/actions.js @@ -81,7 +81,7 @@ describe( 'actions', () => { args: [], selectorName: 'getBlockTypes', storeKey: 'core/blocks', - type: 'SELECT', + type: '@@data/RESOLVE_SELECT', } ); expect( generator.next( [ block ] ).value ).toEqual( { @@ -143,7 +143,7 @@ describe( 'actions', () => { args: [], selectorName: 'getBlockTypes', storeKey: 'core/blocks', - type: 'SELECT', + type: '@@data/RESOLVE_SELECT', } ); expect( generator.next( [ inactiveBlock ] ).value ).toEqual( { @@ -274,7 +274,7 @@ describe( 'actions', () => { data: null, }; expect( generator.throw( apiError ).value ).toMatchObject( { - type: 'DISPATCH', + type: '@@data/DISPATCH', actionName: 'createErrorNotice', storeKey: 'core/notices', } ); diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 57a4d5c88a9b90..40d148d1fe5130 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -400,6 +400,10 @@ _Related_ - +# **LineHeightControl** + +Undocumented declaration. + # **MediaPlaceholder** _Related_ @@ -558,6 +562,50 @@ _Related_ Undocumented declaration. +# **useBlockProps** + +This hook is used to lightly mark an element as a block element. The element +should be the outermost element of a block. Call this hook and pass the +returned props to the element to mark as a block. If you define a ref for the +element, it is important to pass the ref to this hook, which the hook in turn +will pass to the component through the props it returns. Optionally, you can +also pass any other props through this hook, and they will be merged and +returned. + +_Parameters_ + +- _props_ `Object`: Optional. Props to pass to the element. Must contain the ref if one is defined. +- _options_ `Object`: Options for internal use only. +- _options.\_\_unstableIsHtml_ `boolean`: + +_Returns_ + +- `Object`: Props to pass to the element to mark as a block. + +# **validateThemeColors** + +Given an array of theme colors checks colors for validity + +_Parameters_ + +- _colors_ `Array`: The array of theme colors + +_Returns_ + +- `Array`: The array of valid theme colors or the default colors + +# **validateThemeGradients** + +Given an array of theme gradients checks gradients for validity + +_Parameters_ + +- _gradients_ `Array`: The array of theme gradients + +_Returns_ + +- `Array`: The array of valid theme gradients or the default gradients + # **Warning** _Related_ diff --git a/packages/block-editor/src/components/alignment-toolbar/README.md b/packages/block-editor/src/components/alignment-toolbar/README.md new file mode 100644 index 00000000000000..81697e70667723 --- /dev/null +++ b/packages/block-editor/src/components/alignment-toolbar/README.md @@ -0,0 +1,53 @@ +## Alignment Toolbar + +The `AlignmentToolbar` component renders a toolbar that displays alignment options for the selected block. + +This component is mostly used for blocks that display text, such as Heading, Paragraph, Post Author, Post Comments, Verse, Quote, Post Title, etc... And the available alignment options are `left`, `center` or `right` alignment. + +![Post Title block alignment options](https://make.wordpress.org/core/files/2020/09/post-title-block-alignment-options.png) + +## Table of contents + +1. [Development guidelines](#development-guidelines) +2. [Related components](#related-components) + +## Development guidelines + +### Usage + +Renders an alignment toolbar with alignments options. + +```jsx +import { AlignmentToolbar } from '@wordpress/block-editor'; + +const MyAlignmentToolbar = () => ( + + { + setAttributes( { textAlign: nextAlign } ); + } } + /> + +); +``` +_Note:_ In this example that we render `AlignmentToolbar` as a child of the `BlockControls` component. + +### Props + +### `value` +* **Type:** `String` +* **Default:** `undefined` +* **Options:**: `left`, `center`, `right` + +The current value of the alignment setting. You may only choose from the `Options` listed above. + +### `onChange` +* **Type:** `Function` + +A callback function invoked when the toolbar's alignment value is changed via an interaction with any of the toolbar's buttons. Called with the new alignment value (ie: `left`, `center`, `right`, `undefined`) as the only argument. + + +## Related components + +Block Editor components are components that can be used to compose the UI of your block editor. Thus, they can only be used under a [`BlockEditorProvider`](https://github.com/WordPress/gutenberg/blob/master/packages/block-editor/src/components/provider/README.md) in the components tree. diff --git a/packages/block-editor/src/components/block-actions/index.js b/packages/block-editor/src/components/block-actions/index.js index 9f5e6593eb3e3d..e7de0fa5c40f32 100644 --- a/packages/block-editor/src/components/block-actions/index.js +++ b/packages/block-editor/src/components/block-actions/index.js @@ -54,6 +54,7 @@ export default function BlockActions( { flashBlock, setBlockMovingClientId, setNavigationMode, + selectBlock, } = useDispatch( 'core/block-editor' ); const notifyCopy = useNotifyCopy(); @@ -78,6 +79,7 @@ export default function BlockActions( { }, onMoveTo() { setNavigationMode( true ); + selectBlock( clientIds[ 0 ] ); setBlockMovingClientId( clientIds[ 0 ] ); }, onGroup() { diff --git a/packages/block-editor/src/components/block-alignment-toolbar/README.md b/packages/block-editor/src/components/block-alignment-toolbar/README.md new file mode 100644 index 00000000000000..4288a68b49c1f5 --- /dev/null +++ b/packages/block-editor/src/components/block-alignment-toolbar/README.md @@ -0,0 +1,51 @@ +# Block Alignment Toolbar + +The `BlockAlignmentToolbar` component is used to render block alignment options in the editor. The different alignment options it provides are `left`, `center`, `right`, `wide` and `full`. + +![Image block alignment options](https://make.wordpress.org/core/files/2020/09/image-block-alignment-options.png) + +## Table of contents + +1. [Development guidelines](#development-guidelines) +2. [Related components](#related-components) + +## Development guidelines + +### Usage + +Renders a block alignment toolbar with alignments options. + +```jsx +import { BlockAlignmentToolbar } from '@wordpress/block-editor'; + +const MyBlockAlignmentToolbar = () => ( + + + +); +``` + +_Note:_ In this example that we render `BlockAlignmentToolbar` as a child of the `BlockControls` component. + +### Props + +### `value` + +- **Type:** `String` +- **Default:** `undefined` +- **Options:**: `left`, `center`, `right`, `wide`, `full` + +The current value of the alignment setting. You may only choose from the `Options` listed above. + +### `onChange` + +- **Type:** `Function` + +A callback function invoked when the toolbar's alignment value is changed via an interaction with any of the toolbar's buttons. Called with the new alignment value (ie: `left`, `center`, `right`, `wide`, `full`) as the only argument. + +## Related components + +Block Editor components are components that can be used to compose the UI of your block editor. Thus, they can only be used under a [`BlockEditorProvider`](https://github.com/WordPress/gutenberg/blob/master/packages/block-editor/src/components/provider/README.md) in the components tree. diff --git a/packages/block-editor/src/components/block-edit/edit.js b/packages/block-editor/src/components/block-edit/edit.js index 84044be7cc60db..0746699eb145dc 100644 --- a/packages/block-editor/src/components/block-edit/edit.js +++ b/packages/block-editor/src/components/block-edit/edit.js @@ -50,13 +50,11 @@ export const Edit = ( props ) => { // with which a block is displayed. If `blockType` is valid, assign // them preferentially as the render value for the block. const Component = blockType.edit || blockType.save; - const lightBlockWrapper = hasBlockSupport( - blockType, - 'lightBlockWrapper', - false - ); - if ( lightBlockWrapper ) { + if ( + blockType.apiVersion > 1 || + hasBlockSupport( blockType, 'lightBlockWrapper', false ) + ) { return ; } diff --git a/packages/block-editor/src/components/block-edit/test/edit.js b/packages/block-editor/src/components/block-edit/test/edit.js index 3e89608bb096e5..5525bcf30aaab0 100644 --- a/packages/block-editor/src/components/block-edit/test/edit.js +++ b/packages/block-editor/src/components/block-edit/test/edit.js @@ -104,12 +104,10 @@ describe( 'Edit', () => { it( 'should assign context', () => { const edit = ( { context } ) => context.value; registerBlockType( 'core/test-block', { + apiVersion: 2, category: 'text', title: 'block title', usesContext: [ 'value' ], - supports: { - lightBlockWrapper: true, - }, edit, save: noop, } ); diff --git a/packages/block-editor/src/components/block-icon/index.js b/packages/block-editor/src/components/block-icon/index.js index 5c43846229ad25..f605e7f375d5d9 100644 --- a/packages/block-editor/src/components/block-icon/index.js +++ b/packages/block-editor/src/components/block-icon/index.js @@ -2,7 +2,6 @@ * External dependencies */ import classnames from 'classnames'; -import { get } from 'lodash'; /** * WordPress dependencies @@ -11,7 +10,7 @@ import { Icon } from '@wordpress/components'; import { blockDefault } from '@wordpress/icons'; export default function BlockIcon( { icon, showColors = false, className } ) { - if ( get( icon, [ 'src' ] ) === 'block-default' ) { + if ( icon?.src === 'block-default' ) { icon = { src: blockDefault, }; diff --git a/packages/block-editor/src/components/block-icon/index.native.js b/packages/block-editor/src/components/block-icon/index.native.js index fcb66f8f3d1e3e..f0845e6b74f8ad 100644 --- a/packages/block-editor/src/components/block-icon/index.native.js +++ b/packages/block-editor/src/components/block-icon/index.native.js @@ -1,7 +1,6 @@ /** * External dependencies */ -import { get } from 'lodash'; import { View } from 'react-native'; /** @@ -11,7 +10,7 @@ import { Icon } from '@wordpress/components'; import { blockDefault } from '@wordpress/icons'; export default function BlockIcon( { icon, showColors = false } ) { - if ( get( icon, [ 'src' ] ) === 'block-default' ) { + if ( icon?.src === 'block-default' ) { icon = { src: blockDefault, }; diff --git a/packages/block-editor/src/components/block-list/block-wrapper.js b/packages/block-editor/src/components/block-list/block-wrapper.js index b4a2885524fb4d..bca876163cc28f 100644 --- a/packages/block-editor/src/components/block-list/block-wrapper.js +++ b/packages/block-editor/src/components/block-list/block-wrapper.js @@ -18,6 +18,8 @@ import { focus, isTextField, placeCaretAtHorizontalEdge } from '@wordpress/dom'; import { ENTER, BACKSPACE, DELETE } from '@wordpress/keycodes'; import { __, sprintf } from '@wordpress/i18n'; import { useSelect, useDispatch } from '@wordpress/data'; +import deprecated from '@wordpress/deprecated'; +import { __unstableGetBlockProps as getBlockProps } from '@wordpress/blocks'; /** * Internal dependencies @@ -29,12 +31,13 @@ import { BlockListBlockContext } from './block'; import ELEMENTS from './block-wrapper-elements'; /** - * This hook is used to lighly mark an element as a block element. Call this - * hook and pass the returned props to the element to mark as a block. If you - * define a ref for the element, it is important to pass the ref to this hook, - * which the hooks in turn will pass to the component through the props it - * returns. Optionally, you can also pass any other props through this hook, and - * they will be merged and returned. + * This hook is used to lightly mark an element as a block element. The element + * should be the outermost element of a block. Call this hook and pass the + * returned props to the element to mark as a block. If you define a ref for the + * element, it is important to pass the ref to this hook, which the hook in turn + * will pass to the component through the props it returns. Optionally, you can + * also pass any other props through this hook, and they will be merged and + * returned. * * @param {Object} props Optional. Props to pass to the element. Must contain * the ref if one is defined. @@ -43,7 +46,7 @@ import ELEMENTS from './block-wrapper-elements'; * * @return {Object} Props to pass to the element to mark as a block. */ -export function useBlockWrapperProps( props = {}, { __unstableIsHtml } = {} ) { +export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { const fallbackRef = useRef(); const ref = props.ref || fallbackRef; const onSelectionStart = useContext( Context ); @@ -110,6 +113,20 @@ export function useBlockWrapperProps( props = {}, { __unstableIsHtml } = {} ) { } }, [ isSelected, isFirstMultiSelected, isLastMultiSelected ] ); + // Set new block node if it changes. + // This effect should happen on every render, so no dependencies should be + // added. + useEffect( () => { + const node = ref.current; + setBlockNodes( ( nodes ) => { + if ( ! nodes[ clientId ] || nodes[ clientId ] === node ) { + return nodes; + } + + return { ...nodes, [ clientId ]: node }; + } ); + } ); + // translators: %s: Type of block (i.e. Text, Image etc) const blockLabel = sprintf( __( 'Block: %s' ), blockTitle ); @@ -285,16 +302,20 @@ export function useBlockWrapperProps( props = {}, { __unstableIsHtml } = {} ) { }; } +/** + * Call within a save function to get the props for the block wrapper. + * + * @param {Object} props Optional. Props to pass to the element. + */ +useBlockProps.save = getBlockProps; + const BlockComponent = forwardRef( - ( - { children, tagName: TagName = 'div', __unstableIsHtml, ...props }, - ref - ) => { - const blockWrapperProps = useBlockWrapperProps( - { ...props, ref }, - { __unstableIsHtml } - ); - return { children }; + ( { children, tagName: TagName = 'div', ...props }, ref ) => { + deprecated( 'wp.blockEditor.__experimentalBlock', { + alternative: 'wp.blockEditor.useBlockProps', + } ); + const blockProps = useBlockProps( { ...props, ref } ); + return { children }; } ); diff --git a/packages/block-editor/src/components/block-list/block-wrapper.native.js b/packages/block-editor/src/components/block-list/block-wrapper.native.js index 10aea4bb9edd71..122ff1e4f514c5 100644 --- a/packages/block-editor/src/components/block-list/block-wrapper.native.js +++ b/packages/block-editor/src/components/block-list/block-wrapper.native.js @@ -1,12 +1,19 @@ +/** + * WordPress dependencies + */ +import { __unstableGetBlockProps as getBlockProps } from '@wordpress/blocks'; + /** * Internal dependencies */ import ELEMENTS from './block-wrapper-elements'; -export function useBlockWrapperProps( props = {} ) { +export function useBlockProps( props = {} ) { return props; } +useBlockProps.save = getBlockProps; + const ExtendedBlockComponent = ELEMENTS.reduce( ( acc, element ) => { acc[ element ] = element; return acc; diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 06c54b09bfddb0..9d151b9793d3cf 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -40,7 +40,7 @@ import BlockInvalidWarning from './block-invalid-warning'; import BlockCrashWarning from './block-crash-warning'; import BlockCrashBoundary from './block-crash-boundary'; import BlockHtml from './block-html'; -import { Block } from './block-wrapper'; +import { useBlockProps } from './block-wrapper'; export const BlockListBlockContext = createContext(); @@ -68,6 +68,14 @@ function mergeWrapperProps( propsA, propsB ) { return newProps; } +function Block( { children, isHtml, ...props } ) { + return ( +
+ { children } +
+ ); +} + function BlockListBlock( { mode, isFocusMode, @@ -118,11 +126,9 @@ function BlockListBlock( { const onBlockError = () => setErrorState( true ); const blockType = getBlockType( name ); - const lightBlockWrapper = hasBlockSupport( - blockType, - 'lightBlockWrapper', - false - ); + const lightBlockWrapper = + blockType.apiVersion > 1 || + hasBlockSupport( blockType, 'lightBlockWrapper', false ); const isUnregisteredBlock = name === getUnregisteredTypeHandlerName(); // Determine whether the block has props to apply to the wrapper. @@ -219,10 +225,10 @@ function BlockListBlock( { if ( ! isValid ) { block = ( - +
{ getSaveElement( blockType, attributes ) }
-
+ ); } else if ( mode === 'html' ) { // Render blockEdit so the inspector controls don't disappear. @@ -230,15 +236,15 @@ function BlockListBlock( { block = ( <>
{ blockEdit }
- + - + ); } else if ( lightBlockWrapper ) { block = blockEdit; } else { - block = { blockEdit }; + block = { blockEdit }; } return ( @@ -247,9 +253,9 @@ function BlockListBlock( { { block } { !! hasError && ( - + - + ) } ); diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index b1ce89ab83e9dc..22ede3bc48e677 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -69,9 +69,12 @@ function BlockList( isDraggingBlocks, } = useSelect( selector, [ rootClientId ] ); + const fallbackRef = useRef(); + const element = __experimentalPassedProps.ref || ref || fallbackRef; + const Container = rootClientId ? __experimentalTagName : RootContainer; const dropTargetIndex = useBlockDropZone( { - element: ref, + element, rootClientId, } ); @@ -81,7 +84,7 @@ function BlockList( return ( { - const fallbackRef = useRef(); return ( - + ); } ); diff --git a/packages/block-editor/src/components/block-list/style.scss b/packages/block-editor/src/components/block-list/style.scss index 25e06ce7f00bab..ad60dd086b12ca 100644 --- a/packages/block-editor/src/components/block-list/style.scss +++ b/packages/block-editor/src/components/block-list/style.scss @@ -495,10 +495,12 @@ .block-editor-block-list__block .block-editor-block-list__block-html-textarea { display: block; margin: 0; + padding: $grid-unit-15; width: 100%; border: none; outline: none; - box-shadow: none; + border-radius: 2px; + box-shadow: inset 0 0 0 $border-width $gray-900; resize: none; overflow: hidden; font-family: $editor-html-font; @@ -508,7 +510,7 @@ @include reduce-motion("transition"); &:focus { - box-shadow: none; + box-shadow: inset 0 0 0 $border-width-focus var(--wp-admin-theme-color); } } @@ -536,63 +538,20 @@ .block-editor-block-mover.is-horizontal .block-editor-block-mover-button.block-editor-block-mover-button { min-width: $block-toolbar-height/2; width: $block-toolbar-height/2; - - // Animate buttons on hover. - &.is-up-button { - svg { - transition: ease-in-out transform 0.1s; - @include reduce-motion("transition"); - } - &:focus, - &:hover { - svg { - transform: translateX(-2px); - } - } - } - - &.is-down-button { - svg { - transition: ease-in-out transform 0.1s; - @include reduce-motion("transition"); - } - &:focus, - &:hover { - svg { - transform: translateX(2px); - } - } - } } .block-editor-block-mover:not(.is-horizontal) { - // Position SVGs. Animate buttons on hover. + // Position SVGs. .block-editor-block-mover-button { &.is-up-button { svg { margin-top: 2px; - transition: ease-in-out transform 0.1s; - @include reduce-motion("transition"); - } - &:focus, - &:hover { - svg { - transform: translateY(-2px); - } } } &.is-down-button { svg { margin-bottom: 3px; - transition: ease-in-out transform 0.1s; - @include reduce-motion("transition"); - } - &:focus, - &:hover { - svg { - transform: translateY(2px); - } } } diff --git a/packages/block-editor/src/components/block-list/use-multi-selection.js b/packages/block-editor/src/components/block-list/use-multi-selection.js index 3e1b86564eff76..696ed2f55c5396 100644 --- a/packages/block-editor/src/components/block-list/use-multi-selection.js +++ b/packages/block-editor/src/components/block-list/use-multi-selection.js @@ -229,19 +229,19 @@ export default function useMultiSelection( ref ) { }, [ onSelectionChange, stopMultiSelect ] ); // Only clean up when unmounting, these are added and cleaned up elsewhere. - useEffect( - () => () => { - const { ownerDocument } = ref.current; - const { defaultView } = ownerDocument; + useEffect( () => { + const { ownerDocument } = ref.current; + const { defaultView } = ownerDocument; + + return () => { ownerDocument.removeEventListener( 'selectionchange', onSelectionChange ); defaultView.removeEventListener( 'mouseup', onSelectionEnd ); defaultView.cancelAnimationFrame( rafId.current ); - }, - [ onSelectionChange, onSelectionEnd ] - ); + }; + }, [ onSelectionChange, onSelectionEnd ] ); /** * Binds event handlers to the document for tracking a pending multi-select diff --git a/packages/block-editor/src/components/block-navigation/block-contents.js b/packages/block-editor/src/components/block-navigation/block-contents.js index 8bf5baea7985b5..dc215cd461b189 100644 --- a/packages/block-editor/src/components/block-navigation/block-contents.js +++ b/packages/block-editor/src/components/block-navigation/block-contents.js @@ -37,14 +37,29 @@ const BlockNavigationBlockContents = forwardRef( const { clientId } = block; - const rootClientId = useSelect( - ( select ) => - select( 'core/block-editor' ).getBlockRootClientId( - clientId - ) || '', + const { + rootClientId, + blockMovingClientId, + selectedBlockInBlockEditor, + } = useSelect( + ( select ) => { + const { + getBlockRootClientId, + hasBlockMovingClientId, + getSelectedBlockClientId, + } = select( 'core/block-editor' ); + return { + rootClientId: getBlockRootClientId( clientId ) || '', + blockMovingClientId: hasBlockMovingClientId(), + selectedBlockInBlockEditor: getSelectedBlockClientId(), + }; + }, [ clientId ] ); + const isBlockMoveTarget = + blockMovingClientId && selectedBlockInBlockEditor === clientId; + const { rootClientId: dropTargetRootClientId, clientId: dropTargetClientId, @@ -65,7 +80,7 @@ const BlockNavigationBlockContents = forwardRef( const className = classnames( 'block-editor-block-navigation-block-contents', { - 'is-dropping-before': isDroppingBefore, + 'is-dropping-before': isDroppingBefore || isBlockMoveTarget, 'is-dropping-after': isDroppingAfter, 'is-dropping-to-inner-blocks': isDroppingToInnerBlocks, } diff --git a/packages/block-editor/src/components/block-variation-picker/index.native.js b/packages/block-editor/src/components/block-variation-picker/index.native.js index 0884b5aebdaed2..9ad927c0b4796a 100644 --- a/packages/block-editor/src/components/block-variation-picker/index.native.js +++ b/packages/block-editor/src/components/block-variation-picker/index.native.js @@ -21,6 +21,7 @@ import { PanelBody, BottomSheet, FooterMessageControl, + InserterButton, } from '@wordpress/components'; import { Icon, close } from '@wordpress/icons'; import { useMemo } from '@wordpress/element'; @@ -28,7 +29,6 @@ import { useMemo } from '@wordpress/element'; /** * Internal dependencies */ -import MenuItem from '../inserter/menu-item'; import styles from './style.scss'; const hitSlop = { top: 22, bottom: 22, left: 22, right: 22 }; @@ -103,7 +103,7 @@ function BlockVariationPicker( { isVisible, onClose, clientId, variations } ) { > { variations.map( ( v ) => { return ( - onVariationSelect( v ) } diff --git a/packages/block-editor/src/components/colors/with-colors.js b/packages/block-editor/src/components/colors/with-colors.js index b152047fa94b96..324c31b72a4812 100644 --- a/packages/block-editor/src/components/colors/with-colors.js +++ b/packages/block-editor/src/components/colors/with-colors.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { get, isString, kebabCase, reduce, upperFirst } from 'lodash'; +import { isString, kebabCase, reduce, upperFirst } from 'lodash'; /** * WordPress dependencies @@ -161,9 +161,7 @@ function createColorHOC( colorTypes, withColorPalette ) { const previousColorObject = previousState[ colorAttributeName ]; - const previousColor = get( previousColorObject, [ - 'color', - ] ); + const previousColor = previousColorObject?.color; /** * The "and previousColorObject" condition checks that a previous color object was already computed. * At the start previousColorObject and colorValue are both equal to undefined diff --git a/packages/block-editor/src/components/default-style-picker/index.js b/packages/block-editor/src/components/default-style-picker/index.js index 5880d8bd5850b3..5dc15cc4a9e6b5 100644 --- a/packages/block-editor/src/components/default-style-picker/index.js +++ b/packages/block-editor/src/components/default-style-picker/index.js @@ -1,8 +1,3 @@ -/** - * External dependencies - */ -import { get } from 'lodash'; - /** * WordPress dependencies */ @@ -22,15 +17,9 @@ export default function DefaultStylePicker( { blockName } ) { const preferredStyleVariations = settings.__experimentalPreferredStyleVariations; return { - preferredStyle: get( preferredStyleVariations, [ - 'value', - blockName, - ] ), - onUpdatePreferredStyleVariations: get( - preferredStyleVariations, - [ 'onChange' ], - null - ), + preferredStyle: preferredStyleVariations?.value?.[ blockName ], + onUpdatePreferredStyleVariations: + preferredStyleVariations?.onChange ?? null, styles: select( 'core/blocks' ).getBlockStyles( blockName ), }; }, diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index ab75507f8a1714..7719bfff230e89 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -36,7 +36,7 @@ export { default as InnerBlocks } from './inner-blocks'; export { default as InspectorAdvancedControls } from './inspector-advanced-controls'; export { default as InspectorControls } from './inspector-controls'; export { default as __experimentalLinkControl } from './link-control'; -export { default as __experimentalLineHeightControl } from './line-height-control'; +export { default as LineHeightControl } from './line-height-control'; export { default as MediaReplaceFlow } from './media-replace-flow'; export { default as MediaPlaceholder } from './media-placeholder'; export { default as MediaUpload } from './media-upload'; @@ -70,7 +70,7 @@ export { default as BlockInspector } from './block-inspector'; export { default as BlockList } from './block-list'; export { Block as __experimentalBlock, - useBlockWrapperProps as __experimentalUseBlockWrapperProps, + useBlockProps, } from './block-list/block-wrapper'; export { default as BlockMover } from './block-mover'; export { default as BlockPreview } from './block-preview'; diff --git a/packages/block-editor/src/components/index.native.js b/packages/block-editor/src/components/index.native.js index e15f4b6c252e01..8fa8e93b903040 100644 --- a/packages/block-editor/src/components/index.native.js +++ b/packages/block-editor/src/components/index.native.js @@ -13,7 +13,7 @@ export { default as AlignmentToolbar } from './alignment-toolbar'; export { default as InnerBlocks } from './inner-blocks'; export { default as InspectorAdvancedControls } from './inspector-advanced-controls'; export { default as InspectorControls } from './inspector-controls'; -export { default as __experimentalLineHeightControl } from './line-height-control'; +export { default as LineHeightControl } from './line-height-control'; export { default as PlainText } from './plain-text'; export { default as RichText, @@ -59,7 +59,7 @@ export { default as __unstableEditorStyles } from './editor-styles'; export { default as Inserter } from './inserter'; export { Block as __experimentalBlock, - useBlockWrapperProps as __experimentalUseBlockWrapperProps, + useBlockProps, } from './block-list/block-wrapper'; export { default as FloatingToolbar } from './floating-toolbar'; diff --git a/packages/block-editor/src/components/inserter/menu.native.js b/packages/block-editor/src/components/inserter/menu.native.js index 76b1557ddfd68e..c05ae07048b676 100644 --- a/packages/block-editor/src/components/inserter/menu.native.js +++ b/packages/block-editor/src/components/inserter/menu.native.js @@ -17,13 +17,16 @@ import { Component } from '@wordpress/element'; import { createBlock, rawHandler } from '@wordpress/blocks'; import { withDispatch, withSelect } from '@wordpress/data'; import { withInstanceId, compose } from '@wordpress/compose'; -import { BottomSheet, BottomSheetConsumer } from '@wordpress/components'; +import { + BottomSheet, + BottomSheetConsumer, + InserterButton, +} from '@wordpress/components'; /** * Internal dependencies */ import styles from './style.scss'; -import MenuItem from './menu-item.native'; const MIN_COL_NUM = 3; @@ -62,8 +65,8 @@ export class InserterMenu extends Component { const { paddingLeft: itemPaddingLeft, paddingRight: itemPaddingRight, - } = styles.modalItem; - const { width: itemWidth } = styles.modalIconWrapper; + } = InserterButton.Styles.modalItem; + const { width: itemWidth } = InserterButton.Styles.modalIconWrapper; return itemWidth + itemPaddingLeft + itemPaddingRight; } @@ -112,7 +115,7 @@ export class InserterMenu extends Component { const { itemWidth, maxWidth } = this.state; const { onSelect } = this.props; return ( - ( + +); +``` + +### Props + +#### `value` + +- **Type:** `String` or `Number` or `Undefined` + +The value of the line height. + +#### `onChange` + +- **Type:** `Function` + +A callback function that handles the application of the line height value. + + +## Related components + +Block Editor components are components that can be used to compose the UI of your block editor. Thus, they can only be used under a [`BlockEditorProvider`](https://github.com/WordPress/gutenberg/blob/master/packages/block-editor/src/components/provider/README.md) in the components tree. diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index 1e9c5415580310..d413171cd114be 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -160,7 +160,7 @@ export class MediaUpload extends React.Component { } render() { - const { allowedTypes = [], isReplacingMedia } = this.props; + const { allowedTypes = [], isReplacingMedia, multiple } = this.props; const isOneType = allowedTypes.length === 1; const isImage = isOneType && allowedTypes.includes( MEDIA_TYPE_IMAGE ); const isVideo = isOneType && allowedTypes.includes( MEDIA_TYPE_VIDEO ); @@ -174,7 +174,9 @@ export class MediaUpload extends React.Component { if ( isReplacingMedia ) { pickerTitle = __( 'Replace image' ); } else { - pickerTitle = __( 'Choose image' ); + pickerTitle = multiple + ? __( 'Choose images' ) + : __( 'Choose image' ); } } else if ( isVideo ) { if ( isReplacingMedia ) { diff --git a/packages/block-editor/src/components/navigable-toolbar/index.js b/packages/block-editor/src/components/navigable-toolbar/index.js index 931932b7ab6da7..5b3fad6e09138e 100644 --- a/packages/block-editor/src/components/navigable-toolbar/index.js +++ b/packages/block-editor/src/components/navigable-toolbar/index.js @@ -13,16 +13,6 @@ import deprecated from '@wordpress/deprecated'; import { focus } from '@wordpress/dom'; import { useShortcut } from '@wordpress/keyboard-shortcuts'; -function useUpdateLayoutEffect( effect, deps ) { - const mounted = useRef( false ); - useLayoutEffect( () => { - if ( mounted.current ) { - return effect(); - } - mounted.current = true; - }, deps ); -} - function hasOnlyToolbarItem( elements ) { const dataProp = 'toolbarItem'; return ! elements.some( ( element ) => ! ( dataProp in element.dataset ) ); @@ -71,9 +61,7 @@ function useIsAccessibleToolbar( ref ) { setIsAccessibleToolbar( onlyToolbarItem ); }, [] ); - useLayoutEffect( determineIsAccessibleToolbar, [] ); - - useUpdateLayoutEffect( () => { + useLayoutEffect( () => { // Toolbar buttons may be rendered asynchronously, so we use // MutationObserver to check if the toolbar subtree has been modified const observer = new window.MutationObserver( diff --git a/packages/block-editor/src/components/responsive-block-control/test/__snapshots__/index.js.snap b/packages/block-editor/src/components/responsive-block-control/test/__snapshots__/index.js.snap index e0233344f6352d..c885154f55d763 100644 --- a/packages/block-editor/src/components/responsive-block-control/test/__snapshots__/index.js.snap +++ b/packages/block-editor/src/components/responsive-block-control/test/__snapshots__/index.js.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Basic rendering should render with required props 1`] = `"
Padding

Toggle between using the same value for all screen sizes or using a unique value per screen size.

All is used here for testing purposes to ensure we have access to details about the device.

"`; +exports[`Basic rendering should render with required props 1`] = `"
Padding

Toggle between using the same value for all screen sizes or using a unique value per screen size.

All is used here for testing purposes to ensure we have access to details about the device.

"`; diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 0b36ed4e9754bb..faf3f79140ab8e 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -106,7 +106,6 @@ function RichTextWrapper( multiline, inlineToolbar, wrapperClassName, - className, autocompleters, onReplace, placeholder, @@ -120,10 +119,6 @@ function RichTextWrapper( __unstableOnSplitAtEnd: onSplitAtEnd, __unstableOnSplitMiddle: onSplitMiddle, identifier, - // To do: find a better way to implicitly inherit props. - start: startAttr, - reversed, - style, preserveWhiteSpace, __unstableEmbedURLOnPaste, __unstableDisableFormats: disableFormats, @@ -144,6 +139,10 @@ function RichTextWrapper( fontFamily, fontWeight, fontStyle, + minWidth, + maxWidth, + onBlur, + setRef, ...props }, forwardedRef @@ -553,9 +552,6 @@ function RichTextWrapper( selectionEnd={ selectionEnd } onSelectionChange={ onSelectionChange } tagName={ tagName } - className={ classnames( classes, className, { - 'keep-placeholder-on-focus': keepPlaceholderOnFocus, - } ) } placeholder={ placeholder } allowedFormats={ adjustedAllowedFormats } withoutInteractiveFormatting={ withoutInteractiveFormatting } @@ -573,11 +569,8 @@ function RichTextWrapper( __unstableDidAutomaticChange={ didAutomaticChange } __unstableUndo={ undo } __unstableDisableFormats={ disableFormats } - style={ style } preserveWhiteSpace={ preserveWhiteSpace } disabled={ disabled } - start={ startAttr } - reversed={ reversed } unstableOnFocus={ unstableOnFocus } __unstableAllowPrefixTransformations={ __unstableAllowPrefixTransformations @@ -603,6 +596,15 @@ function RichTextWrapper( fontFamily={ fontFamily } fontWeight={ fontWeight } fontStyle={ fontStyle } + minWidth={ minWidth } + maxWidth={ maxWidth } + onBlur={ onBlur } + setRef={ setRef } + // Props to be set on the editable container are destructured on the + // element itself for web (see below), but passed through rich text + // for native. + id={ props.id } + style={ props.style } > { ( { isSelected: nestedIsSelected, @@ -632,13 +634,27 @@ function RichTextWrapper( { onKeyDown( event ); editableProps.onKeyDown( event ); diff --git a/packages/block-editor/src/components/unit-control/README.md b/packages/block-editor/src/components/unit-control/README.md new file mode 100644 index 00000000000000..4d99d85254decb --- /dev/null +++ b/packages/block-editor/src/components/unit-control/README.md @@ -0,0 +1,141 @@ +# UnitControl + +UnitControl component allows the user to set a value as well as a unit (e.g. `px`). The allowed units are derived from the (experimental) `theme.json` settings file . + +```js +// theme.json +{ + "global": { + "settings": { + "spacing": { + "units": [ "px", "em", "rem", "vh", "vw" ] + } + } + } +} +``` + +## Table of contents + +1. [Development guidelines](#development-guidelines) + +## Developer guidelines + +### Usage + +Renders a control (`input` and `select`) with the values `10` and `px` parsed from `10px`. + +```jsx +import { __experimentalUnitControl as UnitControl } from '@wordpress/block-editor/'; +import { useState } from '@wordpress/element'; + +const Example = () => { + const [ value, setValue ] = useState( '10px' ); + + return ; +}; +``` + +### Props + +#### disabledUnits + +If true, the unit `` is tabbable. + +- Type: `Boolean` +- Required: No +- Default: `true` + +#### label + +If this property is added, a label will be generated using label property as the content. + +- Type: `String` +- Required: No + +#### labelPosition + +The position of the label (`top`, `side`, `bottom`, or `edge`). + +- Type: `String` +- Required: No + +#### onChange + +Callback when the `value` changes. + +- Type: `Function` +- Required: No +- Default: `noop` + +#### onUnitChange + +Callback when the `unit` changes. + +- Type: `Function` +- Required: No +- Default: `noop` + +#### size + +Adjusts the size of the input. +Sizes include: `default`, `small` + +- Type: `String` +- Required: No +- Default: `default` + +#### units + +Collection of available units. These units must be one of the units defined in the `theme.json` settings file. + +- Type: `Array` +- Required: No + +Example: + +```jsx +import { __experimentalUnitControl as UnitControl } from '@wordpress/block-editor/'; + +const Example = () => { + const [ value, setValue ] = useState( '10px' ); + const units = [ + { value: 'px', label: 'px', default: 0 }, + { value: '%', label: '%', default: 10 }, + { value: 'em', label: 'em', default: 0 }, + ]; + + return ; +}; +``` + +A `default` value for (in the example above, `10` for `%`), if defined, is set as the new `value` when a unit changes. This is helpful in scenarios where changing a unit may cause drastic results, such as changing from `px` to `vh`. + +#### value + +Current value. To set a unit, provide a unit with a value through the `value` prop. + +Example: + +```jsx + +``` + +- Type: `Number`|`String` +- Required: No diff --git a/packages/block-editor/src/components/use-simulated-media-query/index.js b/packages/block-editor/src/components/use-simulated-media-query/index.js index 52ab33e24f8bf4..b5ef9a2a519fe0 100644 --- a/packages/block-editor/src/components/use-simulated-media-query/index.js +++ b/packages/block-editor/src/components/use-simulated-media-query/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { filter, get } from 'lodash'; +import { filter } from 'lodash'; import { match } from 'css-mediaquery'; /** @@ -20,18 +20,15 @@ function getStyleSheetsThatMatchHostname() { return []; } - return filter( - get( window, [ 'document', 'styleSheets' ], [] ), - ( styleSheet ) => { - if ( ! styleSheet.href ) { - return false; - } - return ( - getProtocol( styleSheet.href ) === window.location.protocol && - getAuthority( styleSheet.href ) === window.location.host - ); + return filter( window?.document?.styleSheets ?? [], ( styleSheet ) => { + if ( ! styleSheet.href ) { + return false; } - ); + return ( + getProtocol( styleSheet.href ) === window.location.protocol && + getAuthority( styleSheet.href ) === window.location.host + ); + } ); } function isReplaceableMediaRule( rule ) { diff --git a/packages/block-editor/src/components/warning/style.scss b/packages/block-editor/src/components/warning/style.scss index 1fdb061d2af34b..cc082b0ea4e69c 100644 --- a/packages/block-editor/src/components/warning/style.scss +++ b/packages/block-editor/src/components/warning/style.scss @@ -14,6 +14,7 @@ line-height: $default-line-height; font-family: $default-font; font-size: $default-font-size; + color: $gray-900; margin: 0 0 1em; } diff --git a/packages/block-editor/src/hooks/align.js b/packages/block-editor/src/hooks/align.js index f46b7fc029bc24..9d4e66d6556c06 100644 --- a/packages/block-editor/src/hooks/align.js +++ b/packages/block-editor/src/hooks/align.js @@ -2,7 +2,7 @@ * External dependencies */ import classnames from 'classnames'; -import { get, has, without } from 'lodash'; +import { has, without } from 'lodash'; /** * WordPress dependencies @@ -135,11 +135,7 @@ export const withToolbarControls = createHigherOrderComponent( const updateAlignment = ( nextAlign ) => { if ( ! nextAlign ) { const blockType = getBlockType( props.name ); - const blockDefaultAlign = get( blockType, [ - 'attributes', - 'align', - 'default', - ] ); + const blockDefaultAlign = blockType.attributes?.align?.default; if ( blockDefaultAlign ) { nextAlign = ''; } diff --git a/packages/block-editor/src/hooks/color.js b/packages/block-editor/src/hooks/color.js index d1962e7011cb2f..2f083d9af2f942 100644 --- a/packages/block-editor/src/hooks/color.js +++ b/packages/block-editor/src/hooks/color.js @@ -30,7 +30,7 @@ import { cleanEmptyObject } from './utils'; import ColorPanel from './color-panel'; import useEditorFeature from '../components/use-editor-feature'; -export const COLOR_SUPPORT_KEY = '__experimentalColor'; +export const COLOR_SUPPORT_KEY = 'color'; const EMPTY_ARRAY = []; const hasColorSupport = ( blockType ) => { @@ -40,7 +40,7 @@ const hasColorSupport = ( blockType ) => { const colorSupport = getBlockSupport( blockType, COLOR_SUPPORT_KEY ); return ( colorSupport && - ( colorSupport.linkColor === true || + ( colorSupport.link === true || colorSupport.gradient === true || colorSupport.background !== false || colorSupport.text !== false ) @@ -54,7 +54,7 @@ const hasLinkColorSupport = ( blockType ) => { const colorSupport = getBlockSupport( blockType, COLOR_SUPPORT_KEY ); - return isObject( colorSupport ) && !! colorSupport.linkColor; + return isObject( colorSupport ) && !! colorSupport.link; }; const hasGradientSupport = ( blockType ) => { diff --git a/packages/block-editor/src/hooks/font-size.js b/packages/block-editor/src/hooks/font-size.js index f993da5c8e0d76..c82855de332ca7 100644 --- a/packages/block-editor/src/hooks/font-size.js +++ b/packages/block-editor/src/hooks/font-size.js @@ -18,7 +18,7 @@ import { import { cleanEmptyObject } from './utils'; import useEditorFeature from '../components/use-editor-feature'; -export const FONT_SIZE_SUPPORT_KEY = '__experimentalFontSize'; +export const FONT_SIZE_SUPPORT_KEY = 'fontSize'; /** * Filters registered block settings, extending attributes to include diff --git a/packages/block-editor/src/hooks/line-height.js b/packages/block-editor/src/hooks/line-height.js index b1390192608b79..d47e5eadf0788f 100644 --- a/packages/block-editor/src/hooks/line-height.js +++ b/packages/block-editor/src/hooks/line-height.js @@ -10,7 +10,7 @@ import LineHeightControl from '../components/line-height-control'; import { cleanEmptyObject } from './utils'; import useEditorFeature from '../components/use-editor-feature'; -export const LINE_HEIGHT_SUPPORT_KEY = '__experimentalLineHeight'; +export const LINE_HEIGHT_SUPPORT_KEY = 'lineHeight'; /** * Inspector control panel containing the line height related configuration diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 9465f5b764d0f6..e506e3271028e8 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { castArray, first, get, last, some } from 'lodash'; +import { castArray, first, last, some } from 'lodash'; /** * WordPress dependencies @@ -14,10 +14,7 @@ import { } from '@wordpress/blocks'; import { speak } from '@wordpress/a11y'; import { __ } from '@wordpress/i18n'; -/** - * Internal dependencies - */ -import { select } from './controls'; +import { controls } from '@wordpress/data'; /** * Generator which will yield a default block insert action if there @@ -26,7 +23,7 @@ import { select } from './controls'; * replacement, etc). */ function* ensureDefaultBlock() { - const count = yield select( 'core/block-editor', 'getBlockCount' ); + const count = yield controls.select( 'core/block-editor', 'getBlockCount' ); // To avoid a focus loss when removing the last block, assure there is // always a default block if the last of the blocks have been removed. @@ -156,7 +153,7 @@ export function selectBlock( clientId, initialPosition = null ) { * @param {string} clientId Block client ID. */ export function* selectPreviousBlock( clientId ) { - const previousBlockClientId = yield select( + const previousBlockClientId = yield controls.select( 'core/block-editor', 'getPreviousBlockClientId', clientId @@ -175,7 +172,7 @@ export function* selectPreviousBlock( clientId ) { * @param {string} clientId Block client ID. */ export function* selectNextBlock( clientId ) { - const nextBlockClientId = yield select( + const nextBlockClientId = yield controls.select( 'core/block-editor', 'getNextBlockClientId', clientId @@ -252,11 +249,9 @@ export function toggleSelection( isSelectionEnabled = true ) { } function getBlocksWithDefaultStylesApplied( blocks, blockEditorSettings ) { - const preferredStyleVariations = get( - blockEditorSettings, - [ '__experimentalPreferredStyleVariations', 'value' ], - {} - ); + const preferredStyleVariations = + blockEditorSettings?.__experimentalPreferredStyleVariations?.value ?? + {}; return blocks.map( ( block ) => { const blockName = block.name; if ( ! hasBlockSupport( blockName, 'defaultStylePicker', true ) ) { @@ -265,7 +260,7 @@ function getBlocksWithDefaultStylesApplied( blocks, blockEditorSettings ) { if ( ! preferredStyleVariations[ blockName ] ) { return block; } - const className = get( block, [ 'attributes', 'className' ] ); + const className = block.attributes?.className; if ( className?.includes( 'is-style-' ) ) { return block; } @@ -305,9 +300,9 @@ export function* replaceBlocks( clientIds = castArray( clientIds ); blocks = getBlocksWithDefaultStylesApplied( castArray( blocks ), - yield select( 'core/block-editor', 'getSettings' ) + yield controls.select( 'core/block-editor', 'getSettings' ) ); - const rootClientId = yield select( + const rootClientId = yield controls.select( 'core/block-editor', 'getBlockRootClientId', first( clientIds ) @@ -315,7 +310,7 @@ export function* replaceBlocks( // Replace is valid if the new blocks can be inserted in the root block. for ( let index = 0; index < blocks.length; index++ ) { const block = blocks[ index ]; - const canInsertBlock = yield select( + const canInsertBlock = yield controls.select( 'core/block-editor', 'canInsertBlockType', block.name, @@ -388,7 +383,7 @@ export function* moveBlocksToPosition( toRootClientId = '', index ) { - const templateLock = yield select( + const templateLock = yield controls.select( 'core/block-editor', 'getTemplateLock', fromRootClientId @@ -421,7 +416,7 @@ export function* moveBlocksToPosition( return; } - const canInsertBlocks = yield select( + const canInsertBlocks = yield controls.select( 'core/block-editor', 'canInsertBlocks', clientIds, @@ -500,11 +495,11 @@ export function* insertBlocks( ) { blocks = getBlocksWithDefaultStylesApplied( castArray( blocks ), - yield select( 'core/block-editor', 'getSettings' ) + yield controls.select( 'core/block-editor', 'getSettings' ) ); const allowedBlocks = []; for ( const block of blocks ) { - const isValid = yield select( + const isValid = yield controls.select( 'core/block-editor', 'canInsertBlockType', block.name, @@ -610,12 +605,12 @@ export function* removeBlocks( clientIds, selectPrevious = true ) { } clientIds = castArray( clientIds ); - const rootClientId = yield select( + const rootClientId = yield controls.select( 'core/block-editor', 'getBlockRootClientId', clientIds[ 0 ] ); - const isLocked = yield select( + const isLocked = yield controls.select( 'core/block-editor', 'getTemplateLock', rootClientId @@ -628,7 +623,7 @@ export function* removeBlocks( clientIds, selectPrevious = true ) { if ( selectPrevious ) { previousBlockId = yield selectPreviousBlock( clientIds[ 0 ] ); } else { - previousBlockId = yield select( + previousBlockId = yield controls.select( 'core/block-editor', 'getPreviousBlockClientId', clientIds[ 0 ] @@ -953,12 +948,12 @@ export function* duplicateBlocks( clientIds, updateSelection = true ) { if ( ! clientIds && ! clientIds.length ) { return; } - const blocks = yield select( + const blocks = yield controls.select( 'core/block-editor', 'getBlocksByClientId', clientIds ); - const rootClientId = yield select( + const rootClientId = yield controls.select( 'core/block-editor', 'getBlockRootClientId', clientIds[ 0 ] @@ -978,7 +973,7 @@ export function* duplicateBlocks( clientIds, updateSelection = true ) { return; } - const lastSelectedIndex = yield select( + const lastSelectedIndex = yield controls.select( 'core/block-editor', 'getBlockIndex', last( castArray( clientIds ) ), @@ -1009,12 +1004,12 @@ export function* insertBeforeBlock( clientId ) { if ( ! clientId ) { return; } - const rootClientId = yield select( + const rootClientId = yield controls.select( 'core/block-editor', 'getBlockRootClientId', clientId ); - const isLocked = yield select( + const isLocked = yield controls.select( 'core/block-editor', 'getTemplateLock', rootClientId @@ -1023,7 +1018,7 @@ export function* insertBeforeBlock( clientId ) { return; } - const firstSelectedIndex = yield select( + const firstSelectedIndex = yield controls.select( 'core/block-editor', 'getBlockIndex', clientId, @@ -1041,12 +1036,12 @@ export function* insertAfterBlock( clientId ) { if ( ! clientId ) { return; } - const rootClientId = yield select( + const rootClientId = yield controls.select( 'core/block-editor', 'getBlockRootClientId', clientId ); - const isLocked = yield select( + const isLocked = yield controls.select( 'core/block-editor', 'getTemplateLock', rootClientId @@ -1055,7 +1050,7 @@ export function* insertAfterBlock( clientId ) { return; } - const firstSelectedIndex = yield select( + const firstSelectedIndex = yield controls.select( 'core/block-editor', 'getBlockIndex', clientId, diff --git a/packages/block-editor/src/store/controls.js b/packages/block-editor/src/store/controls.js index f0cbed509f3131..83b4f453425462 100644 --- a/packages/block-editor/src/store/controls.js +++ b/packages/block-editor/src/store/controls.js @@ -1,32 +1,4 @@ -/** - * WordPress dependencies - */ -import { createRegistryControl } from '@wordpress/data'; - -/** - * Calls a selector using the current state. - * - * @param {string} storeName Store name. - * @param {string} selectorName Selector name. - * @param {Array} args Selector arguments. - * - * @return {Object} control descriptor. - */ -export function select( storeName, selectorName, ...args ) { - return { - type: 'SELECT', - storeName, - selectorName, - args, - }; -} - const controls = { - SELECT: createRegistryControl( - ( registry ) => ( { storeName, selectorName, args } ) => { - return registry.select( storeName )[ selectorName ]( ...args ); - } - ), SLEEP( { duration } ) { return new Promise( ( resolve ) => { setTimeout( resolve, duration ); diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 058f0794ab2d13..85898175da7dac 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -12,7 +12,6 @@ import { keys, isEqual, isEmpty, - get, identity, difference, omitBy, @@ -411,11 +410,7 @@ function withPersistentBlockChange( reducer ) { markNextChangeAsNotPersistent = action.type === 'MARK_NEXT_CHANGE_AS_NOT_PERSISTENT'; - const nextIsPersistentChange = get( - state, - [ 'isPersistentChange' ], - true - ); + const nextIsPersistentChange = state?.isPersistentChange ?? true; if ( state.isPersistentChange === nextIsPersistentChange ) { return state; } diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 85c4a17d94bd4e..b84a7ff24aed79 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -5,7 +5,6 @@ import { castArray, flatMap, first, - get, isArray, isBoolean, last, @@ -1273,9 +1272,7 @@ const canInsertBlockTypeUnmemoized = ( return false; } - const parentAllowedBlocks = get( parentBlockListSettings, [ - 'allowedBlocks', - ] ); + const parentAllowedBlocks = parentBlockListSettings?.allowedBlocks; const hasParentAllowedBlock = checkAllowList( parentAllowedBlocks, blockName @@ -1345,7 +1342,7 @@ export function canInsertBlocks( state, clientIds, rootClientId = null ) { * the number of inserts that have occurred. */ function getInsertUsage( state, id ) { - return get( state.preferences.insertUsage, [ id ], null ); + return state.preferences.insertUsage?.[ id ] ?? null; } /** @@ -1735,11 +1732,7 @@ export function __experimentalGetLastBlockAttributeChanges( state ) { * @return {Array} Reusable blocks */ function getReusableBlocks( state ) { - return get( - state, - [ 'settings', '__experimentalReusableBlocks' ], - EMPTY_ARRAY - ); + return state?.settings?.__experimentalReusableBlocks ?? EMPTY_ARRAY; } /** diff --git a/packages/block-editor/src/store/test/actions.js b/packages/block-editor/src/store/test/actions.js index 772afcefda5081..dc7ad96e3261a7 100644 --- a/packages/block-editor/src/store/test/actions.js +++ b/packages/block-editor/src/store/test/actions.js @@ -1,3 +1,8 @@ +/** + * WordPress dependencies + */ +import { controls } from '@wordpress/data'; + /** * Internal dependencies */ @@ -32,7 +37,6 @@ import { updateBlockAttributes, updateBlockListSettings, } from '../actions'; -import { select } from '../controls'; describe( 'actions', () => { describe( 'resetBlocks', () => { @@ -142,19 +146,22 @@ describe( 'actions', () => { // Skip getSettings select. replaceBlockGenerator.next(); - expect( replaceBlockGenerator.next().value ).toEqual( { - args: [ 'chicken' ], - selectorName: 'getBlockRootClientId', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( replaceBlockGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'getBlockRootClientId', + 'chicken' + ) + ); - expect( replaceBlockGenerator.next().value ).toEqual( { - args: [ 'core/test-block', undefined ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( replaceBlockGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-block', + undefined + ) + ); expect( replaceBlockGenerator.next( true ).value ).toEqual( { type: 'REPLACE_BLOCKS', @@ -163,12 +170,9 @@ describe( 'actions', () => { time: expect.any( Number ), } ); - expect( replaceBlockGenerator.next().value ).toEqual( { - args: [], - selectorName: 'getBlockCount', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( replaceBlockGenerator.next().value ).toEqual( + controls.select( 'core/block-editor', 'getBlockCount' ) + ); expect( replaceBlockGenerator.next( 1 ) ).toEqual( { value: undefined, @@ -195,33 +199,35 @@ describe( 'actions', () => { blocks ); - expect( replaceBlockGenerator.next().value ).toEqual( { - args: [], - selectorName: 'getSettings', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( replaceBlockGenerator.next().value ).toEqual( + controls.select( 'core/block-editor', 'getSettings' ) + ); - expect( replaceBlockGenerator.next().value ).toEqual( { - args: [ 'chicken' ], - selectorName: 'getBlockRootClientId', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( replaceBlockGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'getBlockRootClientId', + 'chicken' + ) + ); - expect( replaceBlockGenerator.next().value ).toEqual( { - args: [ 'core/test-ribs', undefined ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( replaceBlockGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-ribs', + undefined + ) + ); - expect( replaceBlockGenerator.next( true ).value ).toEqual( { - args: [ 'core/test-chicken', undefined ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( replaceBlockGenerator.next( true ).value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-chicken', + undefined + ) + ); expect( replaceBlockGenerator.next( false ) ).toEqual( { value: undefined, @@ -249,26 +255,31 @@ describe( 'actions', () => { // Skip getSettings select. replaceBlockGenerator.next(); - expect( replaceBlockGenerator.next().value ).toEqual( { - args: [ 'chicken' ], - selectorName: 'getBlockRootClientId', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( replaceBlockGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'getBlockRootClientId', + 'chicken' + ) + ); - expect( replaceBlockGenerator.next().value ).toEqual( { - args: [ 'core/test-ribs', undefined ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( replaceBlockGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-ribs', + undefined + ) + ); - expect( replaceBlockGenerator.next( true ).value ).toEqual( { - args: [ 'core/test-chicken', undefined ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( replaceBlockGenerator.next( true ).value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-chicken', + undefined + ) + ); expect( replaceBlockGenerator.next( true ).value ).toEqual( { type: 'REPLACE_BLOCKS', @@ -277,12 +288,9 @@ describe( 'actions', () => { time: expect.any( Number ), } ); - expect( replaceBlockGenerator.next().value ).toEqual( { - args: [], - selectorName: 'getBlockCount', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( replaceBlockGenerator.next().value ).toEqual( + controls.select( 'core/block-editor', 'getBlockCount' ) + ); expect( replaceBlockGenerator.next( 1 ) ).toEqual( { value: undefined, @@ -348,12 +356,14 @@ describe( 'actions', () => { // Skip getSettings select. insertBlockGenerator.next(); - expect( insertBlockGenerator.next().value ).toEqual( { - args: [ 'core/test-block', 'testclientid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlockGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-block', + 'testclientid' + ) + ); expect( insertBlockGenerator.next( true ) ).toEqual( { done: true, @@ -392,12 +402,9 @@ describe( 'actions', () => { false ); - expect( insertBlocksGenerator.next().value ).toEqual( { - args: [], - selectorName: 'getSettings', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlocksGenerator.next().value ).toEqual( + controls.select( 'core/block-editor', 'getSettings' ) + ); expect( insertBlocksGenerator.next( { @@ -408,26 +415,32 @@ describe( 'actions', () => { }, }, } ).value - ).toEqual( { - args: [ 'core/test-ribs', 'testrootid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-ribs', + 'testrootid' + ) + ); - expect( insertBlocksGenerator.next( true ).value ).toEqual( { - args: [ 'core/test-chicken', 'testrootid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlocksGenerator.next( true ).value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-chicken', + 'testrootid' + ) + ); - expect( insertBlocksGenerator.next( true ).value ).toEqual( { - args: [ 'core/test-chicken-ribs', 'testrootid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlocksGenerator.next( true ).value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-chicken-ribs', + 'testrootid' + ) + ); expect( insertBlocksGenerator.next( true ) ).toEqual( { done: true, @@ -469,12 +482,9 @@ describe( 'actions', () => { false ); - expect( insertBlocksGenerator.next().value ).toEqual( { - args: [], - selectorName: 'getSettings', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlocksGenerator.next().value ).toEqual( + controls.select( 'core/block-editor', 'getSettings' ) + ); expect( insertBlocksGenerator.next( { @@ -484,12 +494,14 @@ describe( 'actions', () => { }, }, } ).value - ).toEqual( { - args: [ 'core/test-ribs', 'testrootid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-ribs', + 'testrootid' + ) + ); expect( insertBlocksGenerator.next( true ) ).toEqual( { done: true, @@ -533,26 +545,32 @@ describe( 'actions', () => { // Skip getSettings select. insertBlocksGenerator.next(); - expect( insertBlocksGenerator.next().value ).toEqual( { - args: [ 'core/test-ribs', 'testrootid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlocksGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-ribs', + 'testrootid' + ) + ); - expect( insertBlocksGenerator.next( true ).value ).toEqual( { - args: [ 'core/test-chicken', 'testrootid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlocksGenerator.next( true ).value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-chicken', + 'testrootid' + ) + ); - expect( insertBlocksGenerator.next( false ).value ).toEqual( { - args: [ 'core/test-chicken-ribs', 'testrootid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlocksGenerator.next( false ).value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-chicken-ribs', + 'testrootid' + ) + ); expect( insertBlocksGenerator.next( true ) ).toEqual( { done: true, @@ -588,19 +606,23 @@ describe( 'actions', () => { // Skip getSettings select. insertBlocksGenerator.next(); - expect( insertBlocksGenerator.next().value ).toEqual( { - args: [ 'core/test-ribs', 'testrootid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlocksGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-ribs', + 'testrootid' + ) + ); - expect( insertBlocksGenerator.next( false ).value ).toEqual( { - args: [ 'core/test-chicken', 'testrootid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlocksGenerator.next( false ).value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-chicken', + 'testrootid' + ) + ); expect( insertBlocksGenerator.next( false ) ).toEqual( { done: true, @@ -635,26 +657,32 @@ describe( 'actions', () => { // Skip getSettings select. insertBlocksGenerator.next(); - expect( insertBlocksGenerator.next().value ).toEqual( { - args: [ 'core/test-ribs', 'testrootid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlocksGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-ribs', + 'testrootid' + ) + ); - expect( insertBlocksGenerator.next( true ).value ).toEqual( { - args: [ 'core/test-chicken', 'testrootid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlocksGenerator.next( true ).value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-chicken', + 'testrootid' + ) + ); - expect( insertBlocksGenerator.next( false ).value ).toEqual( { - args: [ 'core/test-chicken-ribs', 'testrootid' ], - selectorName: 'canInsertBlockType', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( insertBlocksGenerator.next( false ).value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlockType', + 'core/test-chicken-ribs', + 'testrootid' + ) + ); expect( insertBlocksGenerator.next( true ) ).toEqual( { done: true, @@ -708,14 +736,22 @@ describe( 'actions', () => { const actions = Array.from( removeBlocks( clientIds ) ); expect( actions ).toEqual( [ - select( 'core/block-editor', 'getBlockRootClientId', clientId ), - select( 'core/block-editor', 'getTemplateLock', undefined ), + controls.select( + 'core/block-editor', + 'getBlockRootClientId', + clientId + ), + controls.select( + 'core/block-editor', + 'getTemplateLock', + undefined + ), selectPreviousBlock( clientId ), { type: 'REMOVE_BLOCKS', clientIds, }, - select( 'core/block-editor', 'getBlockCount' ), + controls.select( 'core/block-editor', 'getBlockCount' ), ] ); } ); } ); @@ -729,12 +765,13 @@ describe( 'actions', () => { 5 ); - expect( moveBlockToPositionGenerator.next().value ).toEqual( { - args: [ 'ribs' ], - selectorName: 'getTemplateLock', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( moveBlockToPositionGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'getTemplateLock', + 'ribs' + ) + ); expect( moveBlockToPositionGenerator.next( 'insert' ).value @@ -757,12 +794,13 @@ describe( 'actions', () => { 5 ); - expect( moveBlockToPositionGenerator.next().value ).toEqual( { - args: [ 'ribs' ], - selectorName: 'getTemplateLock', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( moveBlockToPositionGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'getTemplateLock', + 'ribs' + ) + ); expect( moveBlockToPositionGenerator.next( 'all' ) ).toEqual( { done: true, @@ -778,12 +816,13 @@ describe( 'actions', () => { 5 ); - expect( moveBlockToPositionGenerator.next().value ).toEqual( { - args: [ 'ribs' ], - selectorName: 'getTemplateLock', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( moveBlockToPositionGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'getTemplateLock', + 'ribs' + ) + ); expect( moveBlockToPositionGenerator.next( 'insert' ) ).toEqual( { done: true, @@ -799,19 +838,22 @@ describe( 'actions', () => { 5 ); - expect( moveBlockToPositionGenerator.next().value ).toEqual( { - args: [ 'ribs' ], - selectorName: 'getTemplateLock', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( moveBlockToPositionGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'getTemplateLock', + 'ribs' + ) + ); - expect( moveBlockToPositionGenerator.next().value ).toEqual( { - args: [ [ 'chicken' ], 'chicken-ribs' ], - selectorName: 'canInsertBlocks', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( moveBlockToPositionGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlocks', + [ 'chicken' ], + 'chicken-ribs' + ) + ); expect( moveBlockToPositionGenerator.next( true ).value ).toEqual( { type: 'MOVE_BLOCKS_TO_POSITION', @@ -835,19 +877,22 @@ describe( 'actions', () => { 5 ); - expect( moveBlockToPositionGenerator.next().value ).toEqual( { - args: [ 'ribs' ], - selectorName: 'getTemplateLock', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( moveBlockToPositionGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'getTemplateLock', + 'ribs' + ) + ); - expect( moveBlockToPositionGenerator.next().value ).toEqual( { - args: [ [ 'chicken' ], 'chicken-ribs' ], - selectorName: 'canInsertBlocks', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( moveBlockToPositionGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'canInsertBlocks', + [ 'chicken' ], + 'chicken-ribs' + ) + ); expect( moveBlockToPositionGenerator.next( false ) ).toEqual( { done: true, @@ -865,12 +910,13 @@ describe( 'actions', () => { 5 ); - expect( moveBlockToPositionGenerator.next().value ).toEqual( { - args: [ 'ribs' ], - selectorName: 'getTemplateLock', - storeName: 'core/block-editor', - type: 'SELECT', - } ); + expect( moveBlockToPositionGenerator.next().value ).toEqual( + controls.select( + 'core/block-editor', + 'getTemplateLock', + 'ribs' + ) + ); expect( moveBlockToPositionGenerator.next().value ).toEqual( { type: 'MOVE_BLOCKS_TO_POSITION', @@ -891,14 +937,22 @@ describe( 'actions', () => { const actions = Array.from( removeBlock( clientId ) ); expect( actions ).toEqual( [ - select( 'core/block-editor', 'getBlockRootClientId', clientId ), - select( 'core/block-editor', 'getTemplateLock', undefined ), + controls.select( + 'core/block-editor', + 'getBlockRootClientId', + clientId + ), + controls.select( + 'core/block-editor', + 'getTemplateLock', + undefined + ), selectPreviousBlock( clientId ), { type: 'REMOVE_BLOCKS', clientIds: [ clientId ], }, - select( 'core/block-editor', 'getBlockCount' ), + controls.select( 'core/block-editor', 'getBlockCount' ), ] ); } ); @@ -908,9 +962,17 @@ describe( 'actions', () => { const actions = Array.from( removeBlock( clientId, false ) ); expect( actions ).toEqual( [ - select( 'core/block-editor', 'getBlockRootClientId', clientId ), - select( 'core/block-editor', 'getTemplateLock', undefined ), - select( + controls.select( + 'core/block-editor', + 'getBlockRootClientId', + clientId + ), + controls.select( + 'core/block-editor', + 'getTemplateLock', + undefined + ), + controls.select( 'core/block-editor', 'getPreviousBlockClientId', 'myclientid' @@ -919,7 +981,7 @@ describe( 'actions', () => { type: 'REMOVE_BLOCKS', clientIds: [ clientId ], }, - select( 'core/block-editor', 'getBlockCount' ), + controls.select( 'core/block-editor', 'getBlockCount' ), ] ); } ); } ); diff --git a/packages/block-editor/src/utils/index.js b/packages/block-editor/src/utils/index.js index 95241bd4fa7673..c1ba2027f62065 100644 --- a/packages/block-editor/src/utils/index.js +++ b/packages/block-editor/src/utils/index.js @@ -1 +1,2 @@ export { default as transformStyles } from './transform-styles'; +export * from './theme'; diff --git a/packages/block-editor/src/utils/theme.js b/packages/block-editor/src/utils/theme.js new file mode 100644 index 00000000000000..beb8bd8629fe14 --- /dev/null +++ b/packages/block-editor/src/utils/theme.js @@ -0,0 +1,48 @@ +/** + * Internal dependencies + */ +import { SETTINGS_DEFAULTS } from '../store/defaults'; + +/** + * Given an array of theme colors checks colors for validity + * + * @param {Array} colors The array of theme colors + * + * @return {Array} The array of valid theme colors or the default colors + */ +export function validateThemeColors( colors ) { + if ( colors === undefined ) { + colors = SETTINGS_DEFAULTS.colors; + } else { + const validColors = colors.filter( ( c ) => c.color ); + if ( validColors.length === 0 ) { + colors = SETTINGS_DEFAULTS.colors; + } else if ( validColors.length < colors.length ) { + // Filter out invalid colors + colors = validColors; + } + } + return colors; +} + +/** + * Given an array of theme gradients checks gradients for validity + * + * @param {Array} gradients The array of theme gradients + * + * @return {Array} The array of valid theme gradients or the default gradients + */ +export function validateThemeGradients( gradients ) { + if ( gradients === undefined ) { + gradients = SETTINGS_DEFAULTS.gradients; + } else { + const validGradients = gradients.filter( ( c ) => c.gradient ); + if ( validGradients.length === 0 ) { + gradients = SETTINGS_DEFAULTS.gradients; + } else if ( validGradients.length < gradients.length ) { + // Filter out invalid gradients + gradients = validGradients; + } + } + return gradients; +} diff --git a/packages/block-library/src/audio/block.json b/packages/block-library/src/audio/block.json index 30b165e51cfa0c..a077767932e73c 100644 --- a/packages/block-library/src/audio/block.json +++ b/packages/block-library/src/audio/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/audio", "category": "media", "attributes": { @@ -37,7 +38,6 @@ }, "supports": { "anchor": true, - "align": true, - "lightBlockWrapper": true + "align": true } } diff --git a/packages/block-library/src/audio/edit.js b/packages/block-library/src/audio/edit.js index 0c9bfd882abcf6..96a52d3f9d4a28 100644 --- a/packages/block-library/src/audio/edit.js +++ b/packages/block-library/src/audio/edit.js @@ -16,7 +16,7 @@ import { MediaPlaceholder, MediaReplaceFlow, RichText, - __experimentalUseBlockWrapperProps as useBlockWrapperProps, + useBlockProps, } from '@wordpress/block-editor'; import { useEffect } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; @@ -41,7 +41,7 @@ function AudioEdit( { insertBlocksAfter, } ) { const { id, autoplay, caption, loop, preload, src } = attributes; - const blockWrapperProps = useBlockWrapperProps(); + const blockProps = useBlockProps(); const mediaUpload = useSelect( ( select ) => { const { getSettings } = select( 'core/block-editor' ); return getSettings().mediaUpload; @@ -116,7 +116,7 @@ function AudioEdit( { } if ( ! src ) { return ( -
+
} onSelect={ onSelectAudio } @@ -175,7 +175,7 @@ function AudioEdit( { /> -
+
{ /* Disable the audio tag so the user clicking on it won't play the file or change the position slider when the controls are enabled. diff --git a/packages/block-library/src/audio/save.js b/packages/block-library/src/audio/save.js index f88eb0bba52e0c..14dc6d57047f53 100644 --- a/packages/block-library/src/audio/save.js +++ b/packages/block-library/src/audio/save.js @@ -1,14 +1,14 @@ /** * WordPress dependencies */ -import { RichText } from '@wordpress/block-editor'; +import { RichText, useBlockProps } from '@wordpress/block-editor'; export default function save( { attributes } ) { const { autoplay, caption, loop, preload, src } = attributes; return ( src && ( -
+
+ ); + }, + }, { attributes: { images: { diff --git a/packages/block-library/src/gallery/save.js b/packages/block-library/src/gallery/save.js index 87478c82fbf625..335f5884167fa3 100644 --- a/packages/block-library/src/gallery/save.js +++ b/packages/block-library/src/gallery/save.js @@ -39,6 +39,11 @@ export default function save( { attributes } ) { href = image.link; break; } + // The image should only have an aria-label if it's within a link and has no alt text. + const imageLabel = + ! image.alt && image.caption && href + ? image.caption + : null; const img = ( ); diff --git a/packages/block-library/src/group/block.json b/packages/block-library/src/group/block.json index a2d0cc083a9f6d..8bcbb631f4360b 100644 --- a/packages/block-library/src/group/block.json +++ b/packages/block-library/src/group/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/group", "category": "design", "attributes": { @@ -14,10 +15,9 @@ ], "anchor": true, "html": false, - "lightBlockWrapper": true, - "__experimentalColor": { + "color": { "gradients": true, - "linkColor": true + "link": true }, "__experimentalPadding": true } diff --git a/packages/block-library/src/group/edit.js b/packages/block-library/src/group/edit.js index 9397662e67d77b..fd8f6e0466c03e 100644 --- a/packages/block-library/src/group/edit.js +++ b/packages/block-library/src/group/edit.js @@ -2,14 +2,11 @@ * WordPress dependencies */ import { useSelect } from '@wordpress/data'; -import { - InnerBlocks, - __experimentalBlock as Block, -} from '@wordpress/block-editor'; +import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; import { __experimentalBoxControl as BoxControl } from '@wordpress/components'; const { __Visualizer: BoxControlVisualizer } = BoxControl; -function GroupEdit( { attributes, className, clientId } ) { +function GroupEdit( { attributes, clientId } ) { const hasInnerBlocks = useSelect( ( select ) => { const { getBlock } = select( 'core/block-editor' ); @@ -18,26 +15,25 @@ function GroupEdit( { attributes, className, clientId } ) { }, [ clientId ] ); - const BlockWrapper = Block[ attributes.tagName ]; + const blockProps = useBlockProps(); + const { tagName: TagName = 'div' } = attributes; return ( - + + hasInnerBlocks ? undefined : InnerBlocks.ButtonBlockAppender } __experimentalTagName="div" __experimentalPassedProps={ { className: 'wp-block-group__inner-container', } } /> - + ); } diff --git a/packages/block-library/src/group/save.js b/packages/block-library/src/group/save.js index f24c9f37cdf409..0a5f4b87ec7085 100644 --- a/packages/block-library/src/group/save.js +++ b/packages/block-library/src/group/save.js @@ -1,13 +1,13 @@ /** * WordPress dependencies */ -import { InnerBlocks } from '@wordpress/block-editor'; +import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; export default function save( { attributes } ) { const { tagName: Tag } = attributes; return ( - +
diff --git a/packages/block-library/src/heading/block.json b/packages/block-library/src/heading/block.json index fd03a4487ee5aa..7780c4ed5f2484 100644 --- a/packages/block-library/src/heading/block.json +++ b/packages/block-library/src/heading/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/heading", "category": "text", "attributes": { @@ -22,12 +23,11 @@ "supports": { "anchor": true, "className": false, - "lightBlockWrapper": true, - "__experimentalColor": { - "linkColor": true + "color": { + "link": true }, - "__experimentalFontSize": true, - "__experimentalLineHeight": true, + "fontSize": true, + "lineHeight": true, "__experimentalSelector": { "core/heading/h1": "h1", "core/heading/h2": "h2", diff --git a/packages/block-library/src/heading/edit.js b/packages/block-library/src/heading/edit.js index d4a353c1b0ead4..b40f5333da87c3 100644 --- a/packages/block-library/src/heading/edit.js +++ b/packages/block-library/src/heading/edit.js @@ -12,7 +12,7 @@ import { AlignmentToolbar, BlockControls, RichText, - __experimentalBlock as Block, + useBlockProps, } from '@wordpress/block-editor'; import { ToolbarGroup } from '@wordpress/components'; @@ -30,6 +30,12 @@ function HeadingEdit( { } ) { const { align, content, level, placeholder } = attributes; const tagName = 'h' + level; + const blockProps = useBlockProps( { + className: classnames( { + [ `has-text-align-${ align }` ]: align, + } ), + style: mergedStyle, + } ); return ( <> @@ -51,7 +57,7 @@ function HeadingEdit( { setAttributes( { content: value } ) } onMerge={ mergeBlocks } @@ -67,12 +73,9 @@ function HeadingEdit( { } } onReplace={ onReplace } onRemove={ () => onReplace( [] ) } - className={ classnames( { - [ `has-text-align-${ align }` ]: align, - } ) } placeholder={ placeholder || __( 'Write heading…' ) } textAlign={ align } - style={ mergedStyle } + { ...blockProps } /> ); diff --git a/packages/block-library/src/heading/save.js b/packages/block-library/src/heading/save.js index 00ecf40e1c27ce..e2eae91f823eb1 100644 --- a/packages/block-library/src/heading/save.js +++ b/packages/block-library/src/heading/save.js @@ -6,21 +6,19 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { RichText } from '@wordpress/block-editor'; +import { RichText, useBlockProps } from '@wordpress/block-editor'; export default function save( { attributes } ) { const { align, content, level } = attributes; - const tagName = 'h' + level; + const TagName = 'h' + level; const className = classnames( { [ `has-text-align-${ align }` ]: align, } ); return ( - + + + ); } diff --git a/packages/block-library/src/image/block.json b/packages/block-library/src/image/block.json index 798210cbd5c2f8..ec80dc4c9ed250 100644 --- a/packages/block-library/src/image/block.json +++ b/packages/block-library/src/image/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/image", "category": "media", "attributes": { @@ -70,7 +71,6 @@ } }, "supports": { - "anchor": true, - "lightBlockWrapper": true + "anchor": true } } diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 5d5478b4db3394..17109a02f4a3b2 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -15,7 +15,7 @@ import { BlockControls, BlockIcon, MediaPlaceholder, - __experimentalUseBlockWrapperProps as useBlockWrapperProps, + useBlockProps, } from '@wordpress/block-editor'; import { useEffect, useRef } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; @@ -303,7 +303,7 @@ export function ImageEdit( { [ `size-${ sizeSlug }` ]: sizeSlug, } ); - const blockWrapperProps = useBlockWrapperProps( { + const blockProps = useBlockProps( { ref, className: classes, } ); @@ -311,7 +311,7 @@ export function ImageEdit( { return ( <> { controls } -
+
{ url && ( { ( { onClose } ) => ( diff --git a/packages/block-library/src/image/save.js b/packages/block-library/src/image/save.js index 4124e9c951e382..ccf816c121e909 100644 --- a/packages/block-library/src/image/save.js +++ b/packages/block-library/src/image/save.js @@ -7,7 +7,7 @@ import { isEmpty } from 'lodash'; /** * WordPress dependencies */ -import { RichText } from '@wordpress/block-editor'; +import { RichText, useBlockProps } from '@wordpress/block-editor'; export default function save( { attributes } ) { const { @@ -67,11 +67,15 @@ export default function save( { attributes } ) { if ( 'left' === align || 'right' === align || 'center' === align ) { return ( -
+
{ figure }
); } - return
{ figure }
; + return ( +
+ { figure } +
+ ); } diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index d92cde6ca38d5a..e99a917ec839b0 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -61,7 +61,6 @@ import * as tagCloud from './tag-cloud'; import * as classic from './classic'; import * as socialLinks from './social-links'; import * as socialLink from './social-link'; -import * as widgetArea from './widget-area'; // Full Site Editing Blocks import * as siteLogo from './site-logo'; @@ -191,7 +190,6 @@ export const __experimentalRegisterExperimentalCoreBlocks = const { __experimentalEnableFullSiteEditing } = settings; [ - widgetArea, navigation, navigationLink, diff --git a/packages/block-library/src/latest-posts/style.scss b/packages/block-library/src/latest-posts/style.scss index e3a34c1387529c..cee628dbb20d38 100644 --- a/packages/block-library/src/latest-posts/style.scss +++ b/packages/block-library/src/latest-posts/style.scss @@ -28,7 +28,11 @@ @include break-small { @for $i from 2 through 6 { &.columns-#{ $i } li { - width: calc((100% / #{ $i }) - 1.25em); + width: calc((100% / #{ $i }) - 1.25em + (1.25em / #{ $i })); + + &:nth-child( #{ $i }n ) { + margin-right: 0; + } } } } diff --git a/packages/block-library/src/list/block.json b/packages/block-library/src/list/block.json index 3fa10c51a1f859..848c017842d392 100644 --- a/packages/block-library/src/list/block.json +++ b/packages/block-library/src/list/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/list", "category": "text", "attributes": { @@ -27,10 +28,9 @@ "supports": { "anchor": true, "className": false, - "__experimentalColor": { + "color": { "gradients": true }, - "__unstablePasteTextInline": true, - "lightBlockWrapper": true + "__unstablePasteTextInline": true } } diff --git a/packages/block-library/src/list/edit.js b/packages/block-library/src/list/edit.js index 9a8e6659566ab9..5ca9052dbf6ecb 100644 --- a/packages/block-library/src/list/edit.js +++ b/packages/block-library/src/list/edit.js @@ -7,7 +7,7 @@ import { RichText, BlockControls, RichTextShortcut, - __experimentalUseBlockWrapperProps as useBlockWrapperProps, + useBlockProps, } from '@wordpress/block-editor'; import { ToolbarGroup } from '@wordpress/components'; import { @@ -154,7 +154,7 @@ export default function ListEdit( { ); - const blockWrapperProps = useBlockWrapperProps(); + const blockProps = useBlockProps(); return ( <> @@ -180,7 +180,7 @@ export default function ListEdit( { start={ start } reversed={ reversed } type={ type } - { ...blockWrapperProps } + { ...blockProps } > { controls } diff --git a/packages/block-library/src/list/save.js b/packages/block-library/src/list/save.js index 8cd1d3870148ba..7d4f8a37fc86a5 100644 --- a/packages/block-library/src/list/save.js +++ b/packages/block-library/src/list/save.js @@ -1,20 +1,15 @@ /** * WordPress dependencies */ -import { RichText } from '@wordpress/block-editor'; +import { RichText, useBlockProps } from '@wordpress/block-editor'; export default function save( { attributes } ) { const { ordered, values, type, reversed, start } = attributes; - const tagName = ordered ? 'ol' : 'ul'; + const TagName = ordered ? 'ol' : 'ul'; return ( - + + + ); } diff --git a/packages/block-library/src/media-text/block.json b/packages/block-library/src/media-text/block.json index 9911c4d35edc1b..e88b1b1d1b8182 100644 --- a/packages/block-library/src/media-text/block.json +++ b/packages/block-library/src/media-text/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/media-text", "category": "media", "attributes": { @@ -84,10 +85,9 @@ "anchor": true, "align": [ "wide", "full" ], "html": false, - "lightBlockWrapper": true, - "__experimentalColor": { + "color": { "gradients": true, - "linkColor": true + "link": true } } } diff --git a/packages/block-library/src/media-text/edit.js b/packages/block-library/src/media-text/edit.js index 52914136a42b2f..fd83c4d830e7eb 100644 --- a/packages/block-library/src/media-text/edit.js +++ b/packages/block-library/src/media-text/edit.js @@ -15,7 +15,7 @@ import { BlockVerticalAlignmentToolbar, InnerBlocks, InspectorControls, - __experimentalUseBlockWrapperProps as useBlockWrapperProps, + useBlockProps, __experimentalImageURLInputUI as ImageURLInputUI, __experimentalImageSizeControl as ImageSizeControl, } from '@wordpress/block-editor'; @@ -280,7 +280,7 @@ function MediaTextEdit( { attributes, isSelected, setAttributes } ) { ); - const blockWrapperProps = useBlockWrapperProps( { + const blockProps = useBlockProps( { className: classNames, style, } ); @@ -310,7 +310,7 @@ function MediaTextEdit( { attributes, isSelected, setAttributes } ) { ) } -
+
+
{ - const { replaceBlock } = dispatch( 'core/block-editor' ); - return { - convertToHTML() { - replaceBlock( - clientId, - createBlock( 'core/html', { - content: attributes.originalUndelimitedContent, - } ) - ); - }, - }; - } ), - withFilters( 'editor.missingEdit' ) -)( MissingBlockWarning ); +const MissingEdit = withDispatch( ( dispatch, { clientId, attributes } ) => { + const { replaceBlock } = dispatch( 'core/block-editor' ); + return { + convertToHTML() { + replaceBlock( + clientId, + createBlock( 'core/html', { + content: attributes.originalUndelimitedContent, + } ) + ); + }, + }; +} )( MissingBlockWarning ); export default MissingEdit; diff --git a/packages/block-library/src/missing/edit.native.js b/packages/block-library/src/missing/edit.native.js index b0f97d48a41c5a..b6fa3a4415e4ca 100644 --- a/packages/block-library/src/missing/edit.native.js +++ b/packages/block-library/src/missing/edit.native.js @@ -1,13 +1,17 @@ /** * External dependencies */ -import { Platform, View, Text, TouchableWithoutFeedback } from 'react-native'; +import { View, Text, TouchableWithoutFeedback } from 'react-native'; /** * WordPress dependencies */ -import { requestUnsupportedBlockFallback } from '@wordpress/react-native-bridge'; -import { BottomSheet, Icon } from '@wordpress/components'; +import { + requestUnsupportedBlockFallback, + sendActionButtonPressedAction, + actionButtons, +} from '@wordpress/react-native-bridge'; +import { BottomSheet, Icon, withUIStrings } from '@wordpress/components'; import { compose, withPreferredColorScheme } from '@wordpress/compose'; import { coreBlocks } from '@wordpress/block-library'; import { normalizeIconObject } from '@wordpress/blocks'; @@ -60,8 +64,16 @@ export class UnsupportedBlockEdit extends Component { } requestFallback() { - this.toggleSheet(); - this.setState( { sendFallbackMessage: true } ); + if ( + this.props.canEnableUnsupportedBlockEditor && + this.props.isUnsupportedBlockEditorSupported === false + ) { + this.toggleSheet(); + this.setState( { sendButtonPressMessage: true } ); + } else { + this.toggleSheet(); + this.setState( { sendFallbackMessage: true } ); + } } renderSheet( blockTitle, blockName ) { @@ -70,6 +82,7 @@ export class UnsupportedBlockEdit extends Component { attributes, clientId, isUnsupportedBlockEditorSupported, + canEnableUnsupportedBlockEditor, } = this.props; const infoTextStyle = getStylesFromColorScheme( styles.infoText, @@ -88,12 +101,8 @@ export class UnsupportedBlockEdit extends Component { styles.infoSheetIconDark ); - const titleFormat = - Platform.OS === 'android' - ? // translators: %s: Name of the block - __( "'%s' isn't yet supported on WordPress for Android" ) - : // translators: %s: Name of the block - __( "'%s' isn't yet supported on WordPress for iOS" ); + /* translators: Missing block alert title. %s: The localized block name */ + const titleFormat = __( "'%s' is not fully-supported" ); const infoTitle = sprintf( titleFormat, blockTitle ); const actionButtonStyle = getStylesFromColorScheme( @@ -124,6 +133,13 @@ export class UnsupportedBlockEdit extends Component { ); }, 100 ); this.setState( { sendFallbackMessage: false } ); + } else if ( this.state.sendButtonPressMessage ) { + this.timeout = setTimeout( () => { + sendActionButtonPressedAction( + actionButtons.missingBlockAlertActionButton + ); + }, 100 ); + this.setState( { sendButtonPressMessage: false } ); } } } > @@ -137,19 +153,21 @@ export class UnsupportedBlockEdit extends Component { { infoTitle } - { isUnsupportedBlockEditorSupported - ? __( - "We are working hard to add more blocks with each release. In the meantime, you can also edit this block using your device's web browser." - ) - : __( - 'We are working hard to add more blocks with each release. In the meantime, you can also edit this post on the web.' - ) } + { this.props.uiStrings[ 'missing-block-detail' ] ?? + __( + 'We are working hard to add more blocks with each release.' + ) } - { isUnsupportedBlockEditorSupported && ( + { ( isUnsupportedBlockEditorSupported || + canEnableUnsupportedBlockEditor ) && ( <> { const testInstance = component.root; const bottomSheet = testInstance.findByType( BottomSheet ); const children = bottomSheet.props.children[ 0 ].props.children; - const expectedOSString = Platform.OS === 'ios' ? 'iOS' : 'Android'; expect( children[ 1 ].props.children ).toBe( "'" + defaultAttributes.originalName + - "' isn't yet supported on WordPress for " + - expectedOSString + "' is not fully-supported" ); } ); } ); diff --git a/packages/block-library/src/navigation-link/block.json b/packages/block-library/src/navigation-link/block.json index edad7abb6cda7f..689707fc5ba77e 100644 --- a/packages/block-library/src/navigation-link/block.json +++ b/packages/block-library/src/navigation-link/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/navigation-link", "category": "design", "parent": [ "core/navigation" ], @@ -40,7 +41,6 @@ ], "supports": { "reusable": false, - "html": false, - "lightBlockWrapper": true + "html": false } } diff --git a/packages/block-library/src/navigation-link/edit.js b/packages/block-library/src/navigation-link/edit.js index 6094494cf80ba7..2b6d2339ea3346 100644 --- a/packages/block-library/src/navigation-link/edit.js +++ b/packages/block-library/src/navigation-link/edit.js @@ -32,7 +32,7 @@ import { InspectorControls, RichText, __experimentalLinkControl as LinkControl, - __experimentalUseBlockWrapperProps as useBlockWrapperProps, + useBlockProps, } from '@wordpress/block-editor'; import { isURL, prependHTTP } from '@wordpress/url'; import { @@ -239,7 +239,7 @@ function NavigationLinkEdit( { }; } - const blockWrapperProps = useBlockWrapperProps( { + const blockProps = useBlockProps( { ref: listItemRef, className: classnames( { 'is-editing': @@ -318,7 +318,7 @@ function NavigationLinkEdit( { /> -
  • +
  • ( - - - -); - -/** - * Color Selector Icon component. - * - * @param {Object} props Component properties. - * @param {Object} props.style Style object. - * @param {string} props.className Class name for component. - * - * @return {*} React Icon component. - */ -const ColorSelectorIcon = ( { style, className } ) => { - return ( -
    -
    - -
    -
    - ); -}; - -/** - * Renders the Colors Selector Toolbar with the icon button. - * - * @param {Object} props Component properties. - * @param {Object} props.TextColor Text color component that wraps icon. - * @param {Object} props.BackgroundColor Background color component that wraps icon. - * - * @return {*} React toggle button component. - */ -const renderToggleComponent = ( { TextColor, BackgroundColor } ) => ( { - onToggle, - isOpen, -} ) => { - const openOnArrowDown = ( event ) => { - if ( ! isOpen && event.keyCode === DOWN ) { - event.preventDefault(); - event.stopPropagation(); - onToggle(); - } - }; - - return ( - - - - - - - } - /> - - ); -}; - -const BlockColorsStyleSelector = ( { children, ...other } ) => ( - children } - /> -); - -export default BlockColorsStyleSelector; diff --git a/packages/block-library/src/navigation/block.json b/packages/block-library/src/navigation/block.json index bd93c30bc91010..b22fdfad89a77a 100644 --- a/packages/block-library/src/navigation/block.json +++ b/packages/block-library/src/navigation/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/navigation", "category": "design", "attributes": { @@ -41,11 +42,17 @@ "showSubmenuIcon": "showSubmenuIcon" }, "supports": { - "align": [ "wide", "full" ], + "align": [ + "wide", + "full" + ], "anchor": true, "html": false, "inserter": true, - "lightBlockWrapper": true, - "__experimentalFontSize": true + "fontSize": true, + "color": { + "textColor": true, + "backgroundColor": true + } } } diff --git a/packages/block-library/src/navigation/edit.js b/packages/block-library/src/navigation/edit.js index 6dbf24663abab9..64564b70cc7f02 100644 --- a/packages/block-library/src/navigation/edit.js +++ b/packages/block-library/src/navigation/edit.js @@ -7,21 +7,15 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { useRef, useState } from '@wordpress/element'; +import { useState } from '@wordpress/element'; import { InnerBlocks, InspectorControls, BlockControls, - __experimentalUseColors, - __experimentalUseBlockWrapperProps as useBlockWrapperProps, + useBlockProps, } from '@wordpress/block-editor'; import { useDispatch, withSelect, withDispatch } from '@wordpress/data'; -import { - PanelBody, - ToggleControl, - Toolbar, - ToolbarGroup, -} from '@wordpress/components'; +import { PanelBody, ToggleControl, ToolbarGroup } from '@wordpress/components'; import { compose } from '@wordpress/compose'; import { __ } from '@wordpress/i18n'; @@ -29,79 +23,38 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import useBlockNavigator from './use-block-navigator'; -import BlockColorsStyleSelector from './block-colors-selector'; import * as navIcons from './icons'; import NavigationPlaceholder from './placeholder'; function Navigation( { selectedBlockHasDescendants, attributes, + setAttributes, clientId, hasExistingNavItems, isImmediateParentOfSelectedBlock, isSelected, - setAttributes, updateInnerBlocks, className, + hasSubmenuIndicatorSetting = true, + hasItemJustificationControls = true, + hasListViewModal = true, } ) { - // - // HOOKS - // - const ref = useRef(); - const [ isPlaceholderShown, setIsPlaceholderShown ] = useState( ! hasExistingNavItems ); const { selectBlock } = useDispatch( 'core/block-editor' ); - const blockProps = useBlockWrapperProps(); - - const { TextColor, BackgroundColor, ColorPanel } = __experimentalUseColors( - [ - { name: 'textColor', property: 'color' }, - { name: 'backgroundColor', className: 'has-background' }, - ], - { - contrastCheckers: [ - { - backgroundColor: true, - textColor: true, - }, - ], - colorDetector: { targetRef: ref }, - colorPanelProps: { - initialOpen: true, - }, - } - ); - + const blockProps = useBlockProps(); const { navigatorToolbarButton, navigatorModal } = useBlockNavigator( clientId ); - // - // HANDLERS - // - function handleItemsAlignment( align ) { - return () => { - const itemsJustification = - attributes.itemsJustification === align ? undefined : align; - setAttributes( { - itemsJustification, - } ); - }; - } - - // - // RENDER - // - if ( isPlaceholderShown ) { return (
    { setIsPlaceholderShown( false ); updateInnerBlocks( blocks ); @@ -114,6 +67,16 @@ function Navigation( { ); } + function handleItemsAlignment( align ) { + return () => { + const itemsJustification = + attributes.itemsJustification === align ? undefined : align; + setAttributes( { + itemsJustification, + } ); + }; + } + const blockClassNames = classnames( className, { [ `items-justified-${ attributes.itemsJustification }` ]: attributes.itemsJustification, 'is-vertical': attributes.orientation === 'vertical', @@ -122,101 +85,98 @@ function Navigation( { return ( <> - - { navigatorToolbarButton } - - { ColorPanel } - + { hasItemJustificationControls && ( + + ) } + { hasListViewModal && ( + { navigatorToolbarButton } + ) } - { navigatorModal } + { hasListViewModal && navigatorModal } - - { - setAttributes( { showSubmenuIcon: value } ); - } } - label={ __( 'Show submenu indicator icons' ) } - /> - - - - - - - + + ) } + + ); } diff --git a/packages/block-library/src/navigation/placeholder.js b/packages/block-library/src/navigation/placeholder.js index 0e50078babbb85..79739656ba9e1d 100644 --- a/packages/block-library/src/navigation/placeholder.js +++ b/packages/block-library/src/navigation/placeholder.js @@ -1,12 +1,13 @@ /** * External dependencies */ +import { some } from 'lodash'; import classnames from 'classnames'; /** * WordPress dependencies */ -import { createBlock } from '@wordpress/blocks'; +import { createBlock, parse } from '@wordpress/blocks'; import { Button, CustomSelectControl, @@ -76,26 +77,51 @@ function getSelectedMenu( selectedCreateOption ) { /** * A recursive function that maps menu item nodes to blocks. * - * @param {Object[]} nodes An array of menu items. - * + * @param {Object[]} menuItems An array of menu items. * @return {WPBlock[]} An array of blocks. */ -function mapMenuItemsToBlocks( nodes ) { - return nodes.map( ( { title, type, link: url, id, children } ) => { - const innerBlocks = - children && children.length ? mapMenuItemsToBlocks( children ) : []; +function mapMenuItemsToBlocks( menuItems ) { + return menuItems.map( ( menuItem ) => { + if ( menuItem.type === 'block' ) { + const [ block ] = parse( menuItem.content.raw ); - return createBlock( - 'core/navigation-link', - { - type, - id, - url, - label: ! title.rendered ? __( '(no title)' ) : title.rendered, - opensInNewTab: false, - }, - innerBlocks - ); + if ( ! block ) { + return createBlock( 'core/freeform', { + content: menuItem.content, + } ); + } + + return block; + } + + const attributes = { + label: ! menuItem.title.rendered + ? __( '(no title)' ) + : menuItem.title.rendered, + opensInNewTab: menuItem.target === '_blank', + }; + + if ( menuItem.url ) { + attributes.url = menuItem.url; + } + + if ( menuItem.description ) { + attributes.description = menuItem.description; + } + + if ( menuItem.xfn?.length && some( menuItem.xfn ) ) { + attributes.rel = menuItem.xfn.join( ' ' ); + } + + if ( menuItem.classes?.length && some( menuItem.classes ) ) { + attributes.className = menuItem.classes.join( ' ' ); + } + + const innerBlocks = menuItem.children?.length + ? mapMenuItemsToBlocks( menuItem.children ) + : []; + + return createBlock( 'core/navigation-link', attributes, innerBlocks ); } ); } @@ -168,6 +194,7 @@ function NavigationPlaceholder( { onCreate }, ref ) { parent: 0, order: 'asc', orderby: 'id', + per_page: -1, }, ]; const menusParameters = [ { per_page: -1 } ]; diff --git a/packages/block-library/src/paragraph/block.json b/packages/block-library/src/paragraph/block.json index 91d8ad357f7ebf..44118c165c2770 100644 --- a/packages/block-library/src/paragraph/block.json +++ b/packages/block-library/src/paragraph/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/paragraph", "category": "text", "attributes": { @@ -29,12 +30,11 @@ "supports": { "anchor": true, "className": false, - "lightBlockWrapper": true, - "__experimentalColor": { - "linkColor": true + "color": { + "link": true }, - "__experimentalFontSize": true, - "__experimentalLineHeight": true, + "fontSize": true, + "lineHeight": true, "__experimentalSelector": "p", "__unstablePasteTextInline": true } diff --git a/packages/block-library/src/paragraph/edit.js b/packages/block-library/src/paragraph/edit.js index dd2b439d5b8ac0..53a27030f5a7ed 100644 --- a/packages/block-library/src/paragraph/edit.js +++ b/packages/block-library/src/paragraph/edit.js @@ -13,7 +13,7 @@ import { BlockControls, InspectorControls, RichText, - __experimentalUseBlockWrapperProps as useBlockWrapperProps, + useBlockProps, getFontSize, __experimentalUseEditorFeature as useEditorFeature, } from '@wordpress/block-editor'; @@ -117,7 +117,7 @@ function ParagraphBlock( { minHeight: dropCapMinimumHeight, }; - const blockWrapperProps = useBlockWrapperProps( { + const blockProps = useBlockProps( { className: classnames( { 'has-drop-cap': dropCap, [ `has-text-align-${ align }` ]: align, @@ -164,7 +164,7 @@ function ParagraphBlock( { setAttributes( { content: newContent } ) diff --git a/packages/block-library/src/paragraph/save.js b/packages/block-library/src/paragraph/save.js index 434cc022295588..9bc9921e31334a 100644 --- a/packages/block-library/src/paragraph/save.js +++ b/packages/block-library/src/paragraph/save.js @@ -6,22 +6,18 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { RichText } from '@wordpress/block-editor'; +import { RichText, useBlockProps } from '@wordpress/block-editor'; export default function save( { attributes } ) { const { align, content, dropCap, direction } = attributes; - const className = classnames( { 'has-drop-cap': dropCap, [ `has-text-align-${ align }` ]: align, } ); return ( - +

    + +

    ); } diff --git a/packages/block-library/src/post-author/block.json b/packages/block-library/src/post-author/block.json index 3e788777dec81d..99f1cd2c8a8163 100644 --- a/packages/block-library/src/post-author/block.json +++ b/packages/block-library/src/post-author/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/post-author", "category": "design", "attributes": { @@ -26,12 +27,11 @@ ], "supports": { "html": false, - "lightBlockWrapper": true, - "__experimentalFontSize": true, - "__experimentalColor": { + "fontSize": true, + "color": { "gradients": true, - "linkColor": true + "link": true }, - "__experimentalLineHeight": true + "lineHeight": true } } diff --git a/packages/block-library/src/post-author/edit.js b/packages/block-library/src/post-author/edit.js index 3a159fbf76be3e..120fb0da34616a 100644 --- a/packages/block-library/src/post-author/edit.js +++ b/packages/block-library/src/post-author/edit.js @@ -12,7 +12,7 @@ import { BlockControls, InspectorControls, RichText, - __experimentalUseBlockWrapperProps as useBlockWrapperProps, + useBlockProps, } from '@wordpress/block-editor'; import { PanelBody, SelectControl, ToggleControl } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; @@ -23,7 +23,7 @@ function PostAuthorEdit( { isSelected, context, attributes, setAttributes } ) { const { authorId, authorDetails, authors } = useSelect( ( select ) => { - const { getEditedEntityRecord, getUser, getAuthors } = select( + const { getEditedEntityRecord, getUser, getUsers } = select( 'core' ); const _authorId = getEditedEntityRecord( @@ -35,7 +35,7 @@ function PostAuthorEdit( { isSelected, context, attributes, setAttributes } ) { return { authorId: _authorId, authorDetails: _authorId ? getUser( _authorId ) : null, - authors: getAuthors(), + authors: getUsers( { who: 'authors' } ), }; }, [ postType, postId ] @@ -55,7 +55,7 @@ function PostAuthorEdit( { isSelected, context, attributes, setAttributes } ) { } ); } - const blockWrapperProps = useBlockWrapperProps( { + const blockProps = useBlockProps( { className: classnames( { [ `has-text-align-${ textAlign }` ]: textAlign, } ), @@ -118,7 +118,7 @@ function PostAuthorEdit( { isSelected, context, attributes, setAttributes } ) { /> -
    +
    { showAvatar && authorDetails && (
    @@ -47,7 +44,7 @@ export default function Edit( { attributes, context, setAttributes } ) { -
    +
    diff --git a/packages/block-library/src/post-comments-count/block.json b/packages/block-library/src/post-comments-count/block.json index 5908f13b721c76..85d4005651da6e 100644 --- a/packages/block-library/src/post-comments-count/block.json +++ b/packages/block-library/src/post-comments-count/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/post-comments-count", "category": "design", "attributes": { @@ -11,11 +12,10 @@ ], "supports": { "html": false, - "lightBlockWrapper": true, - "__experimentalColor": { + "color": { "gradients": true }, - "__experimentalFontSize": true, - "__experimentalLineHeight": true + "fontSize": true, + "lineHeight": true } } diff --git a/packages/block-library/src/post-comments-count/edit.js b/packages/block-library/src/post-comments-count/edit.js index ddc33fe26192f0..9f9f87939bfa70 100644 --- a/packages/block-library/src/post-comments-count/edit.js +++ b/packages/block-library/src/post-comments-count/edit.js @@ -10,7 +10,7 @@ import { AlignmentToolbar, BlockControls, Warning, - __experimentalUseBlockWrapperProps as useBlockWrapperProps, + useBlockProps, } from '@wordpress/block-editor'; import { useState, useEffect } from '@wordpress/element'; import apiFetch from '@wordpress/api-fetch'; @@ -25,7 +25,7 @@ export default function PostCommentsCountEdit( { const { textAlign } = attributes; const { postId } = context; const [ commentsCount, setCommentsCount ] = useState(); - const blockWrapperProps = useBlockWrapperProps( { + const blockProps = useBlockProps( { className: classnames( { [ `has-text-align-${ textAlign }` ]: textAlign, } ), @@ -59,7 +59,7 @@ export default function PostCommentsCountEdit( { } } /> -
    +
    { postId && commentsCount !== undefined ? ( commentsCount ) : ( diff --git a/packages/block-library/src/post-comments-form/block.json b/packages/block-library/src/post-comments-form/block.json index c0e131b83b231b..64cdcbba8f95fd 100644 --- a/packages/block-library/src/post-comments-form/block.json +++ b/packages/block-library/src/post-comments-form/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/post-comments-form", "category": "design", "attributes": { @@ -12,12 +13,11 @@ ], "supports": { "html": false, - "lightBlockWrapper": true, - "__experimentalColor": { + "color": { "gradients": true, - "linkColor": true + "link": true }, - "__experimentalFontSize": true, - "__experimentalLineHeight": true + "fontSize": true, + "lineHeight": true } } diff --git a/packages/block-library/src/post-comments-form/edit.js b/packages/block-library/src/post-comments-form/edit.js index 49d5362360ea18..da6751e0e30dbe 100644 --- a/packages/block-library/src/post-comments-form/edit.js +++ b/packages/block-library/src/post-comments-form/edit.js @@ -10,7 +10,7 @@ import { AlignmentToolbar, BlockControls, Warning, - __experimentalUseBlockWrapperProps as useBlockWrapperProps, + useBlockProps, } from '@wordpress/block-editor'; import { useEntityProp } from '@wordpress/core-data'; import { __ } from '@wordpress/i18n'; @@ -28,7 +28,7 @@ export default function PostCommentsFormEdit( { 'comment_status', postId ); - const blockWrapperProps = useBlockWrapperProps( { + const blockProps = useBlockProps( { className: classnames( { [ `has-text-align-${ textAlign }` ]: textAlign, } ), @@ -44,7 +44,7 @@ export default function PostCommentsFormEdit( { } } /> -
    +
    { ! commentStatus && ( { __( diff --git a/packages/block-library/src/post-comments/block.json b/packages/block-library/src/post-comments/block.json index 51dbb5c22dcbcc..ee1e3d4c03f717 100644 --- a/packages/block-library/src/post-comments/block.json +++ b/packages/block-library/src/post-comments/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/post-comments", "category": "design", "attributes": { @@ -12,16 +13,15 @@ ], "supports": { "html": false, - "lightBlockWrapper": true, "align": [ "wide", "full" ], - "__experimentalFontSize": true, - "__experimentalColor": { + "fontSize": true, + "color": { "gradients": true, - "linkColor": true + "link": true }, - "__experimentalLineHeight": true + "lineHeight": true } } diff --git a/packages/block-library/src/post-comments/edit.js b/packages/block-library/src/post-comments/edit.js index 79109cb2629f9b..e79a8b8760c03d 100644 --- a/packages/block-library/src/post-comments/edit.js +++ b/packages/block-library/src/post-comments/edit.js @@ -11,7 +11,7 @@ import { AlignmentToolbar, BlockControls, Warning, - __experimentalUseBlockWrapperProps as useBlockWrapperProps, + useBlockProps, } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; import { RawHTML } from '@wordpress/element'; @@ -49,7 +49,7 @@ export default function PostCommentsEdit( { } ) { const { postType, postId } = context; const { textAlign } = attributes; - const blockWrapperProps = useBlockWrapperProps( { + const blockProps = useBlockProps( { className: classnames( { [ `has-text-align-${ textAlign }` ]: textAlign, } ), @@ -72,7 +72,7 @@ export default function PostCommentsEdit( { /> -
    +
    diff --git a/packages/block-library/src/post-date/block.json b/packages/block-library/src/post-date/block.json index 872bf705c01162..94fc7dd67d9f98 100644 --- a/packages/block-library/src/post-date/block.json +++ b/packages/block-library/src/post-date/block.json @@ -1,4 +1,5 @@ { + "apiVersion": 2, "name": "core/post-date", "category": "design", "attributes": { @@ -15,11 +16,10 @@ ], "supports": { "html": false, - "lightBlockWrapper": true, - "__experimentalColor": { + "color": { "gradients": true }, - "__experimentalFontSize": true, - "__experimentalLineHeight": true + "fontSize": true, + "lineHeight": true } } diff --git a/packages/block-library/src/post-date/edit.js b/packages/block-library/src/post-date/edit.js index 664e59a6899027..4b75b93a648d31 100644 --- a/packages/block-library/src/post-date/edit.js +++ b/packages/block-library/src/post-date/edit.js @@ -13,7 +13,7 @@ import { AlignmentToolbar, BlockControls, InspectorControls, - __experimentalUseBlockWrapperProps as useBlockWrapperProps, + useBlockProps, } from '@wordpress/block-editor'; import { ToolbarGroup, @@ -56,7 +56,7 @@ export default function PostDateEdit( { attributes, context, setAttributes } ) { } ) ); const resolvedFormat = format || siteFormat || settings.formats.date; - const blockWrapperProps = useBlockWrapperProps( { + const blockProps = useBlockProps( { className: classnames( { [ `has-text-align-${ textAlign }` ]: textAlign, } ), @@ -105,7 +105,7 @@ export default function PostDateEdit( { attributes, context, setAttributes } ) { -
    +
    { date && (