diff --git a/.eslintrc.js b/.eslintrc.js
index a9ce5392e2f2e..4bb1966dde375 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -104,7 +104,7 @@ module.exports = {
{
name: '@emotion/css',
message:
- 'Please use `@emotion/react` and `@emotion/styled` in order to maintain iframe support',
+ 'Please use `@emotion/react` and `@emotion/styled` in order to maintain iframe support. As a replacement for the `cx` function, please use the `useCx` hook defined in `@wordpress/components` instead.',
},
],
},
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 934b853ba6c61..b22eec7c45d40 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -40,9 +40,11 @@
# Widgets
/packages/edit-widgets @draganescu @talldan @noisysocks @tellthemachines @adamziel @kevin940726
+/packages/customize-widgets @noisysocks
+/packages/widgets @noisysocks
# Navigation
-/packages/edit-navigation @draganescu @talldan @noisysocks @tellthemachines @adamziel @kevin940726 @getdave
+/packages/edit-navigation @draganescu @talldan @tellthemachines @adamziel @kevin940726 @getdave
# Full Site Editing
/packages/edit-site
@@ -125,6 +127,7 @@
/lib/theme.json @timothybjabocs @spacedmonkey @nosolosw
/lib/class-wp-theme-json-gutenberg.php @timothybjabocs @spacedmonkey @nosolosw
/lib/class-wp-theme-json-resolver-gutenberg.php @timothybjabocs @spacedmonkey @nosolosw
+/lib/full-site-editing @janw-me
/phpunit/class-wp-theme-json-test.php @nosolosw
# Web App
diff --git a/.github/ISSUE_TEMPLATE/Bug_report.yml b/.github/ISSUE_TEMPLATE/Bug_report.yml
index a104c70d1072f..50944218a52b8 100644
--- a/.github/ISSUE_TEMPLATE/Bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/Bug_report.yml
@@ -1,6 +1,5 @@
name: Bug report
description: Report a bug with the WordPress block editor or Gutenberg plugin
-title: '
'
body:
- type: markdown
attributes:
@@ -49,10 +48,25 @@ body:
validations:
required: false
- - type: checkboxes
+ - type: dropdown
+ id: existing
attributes:
- label: Pre-checks
- description: Please check if the bug has already been reported by searching https://github.com/WordPress/gutenberg/issues and make sure the bug is not related to another plugin.
+ label: Please confirm that you have searched existing issues in the repo.
+ description: You can do this by searching https://github.com/WordPress/gutenberg/issues and making sure the bug is not related to another plugin.
+ multiple: true
options:
- - label: I have searched the existing issues.
- - label: I have tested with all plugins deactivated except Gutenberg.
+ - 'Yes'
+ - 'No'
+ validations:
+ required: true
+
+ - type: dropdown
+ id: plugins
+ attributes:
+ label: Please confirm that you have tested with all plugins deactivated except Gutenberg.
+ multiple: true
+ options:
+ - 'Yes'
+ - 'No'
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/Bug_report_mobile.md b/.github/ISSUE_TEMPLATE/Bug_report_mobile.md
index 06b6fad1bb6bc..8347a6649ea8d 100644
--- a/.github/ISSUE_TEMPLATE/Bug_report_mobile.md
+++ b/.github/ISSUE_TEMPLATE/Bug_report_mobile.md
@@ -44,7 +44,7 @@ the bug.
-->
## WordPress information
-- WordPress version:
+- WordPress version:
- Gutenberg version:
- Are all plugins except Gutenberg deactivated?
- Are you using a default theme (e.g. Twenty Twenty-One)?
diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml
index 18eda2ad1ef5a..8bb83dfd7b6ec 100644
--- a/.github/workflows/rnmobile-android-runner.yml
+++ b/.github/workflows/rnmobile-android-runner.yml
@@ -15,9 +15,7 @@ concurrency:
jobs:
test:
runs-on: macos-latest
- # The false value below disables the test while we investigate a
- # foundational error causing failures
- if: ${{ false && (github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request') }}
+ if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }}
strategy:
matrix:
native-test-name: [gutenberg-editor-initial-html]
@@ -41,9 +39,10 @@ jobs:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
- - uses: reactivecircus/android-emulator-runner@d2799957d660add41c61a5103e2fbb9e2889eb73 # v2.15.0
+ - uses: reactivecircus/android-emulator-runner@5de26e4bd23bf523e8a4b7f077df8bfb8e52b50e # v2.19.1
with:
api-level: 28
+ emulator-build: 7425822 # https://git.io/JE3jX
profile: pixel_xl
script: npm run native test:e2e:android:local ${{ matrix.native-test-name }}
diff --git a/.github/workflows/upload-release-to-plugin-repo.yml b/.github/workflows/upload-release-to-plugin-repo.yml
index d7561fe3b296f..59cfed85c1b8f 100644
--- a/.github/workflows/upload-release-to-plugin-repo.yml
+++ b/.github/workflows/upload-release-to-plugin-repo.yml
@@ -79,8 +79,14 @@ jobs:
- name: Commit the Changelog update
run: |
git add changelog.txt
- git commit -m "Update Changelog for ${TAG#v}"
- git push --set-upstream origin "${{ matrix.branch }}"
+ # Remove files that are not meant to be commited
+ # ie. release_notes.txt created on the previous step.
+ git clean -fd
+ # Only attempt to commit changelog if it has been modified.
+ if ! git diff-index --quiet HEAD --; then
+ git commit -m "Update Changelog for ${TAG#v}"
+ git push --set-upstream origin "${{ matrix.branch }}"
+ fi
- name: Upload Changelog artifact
uses: actions/upload-artifact@e448a9b857ee2131e752b06002bf0e093c65e571 # v2.2.2
diff --git a/.vscode/launch-example.json b/.vscode/launch-example.json
index 3e333f450a001..67b7a8859eb20 100644
--- a/.vscode/launch-example.json
+++ b/.vscode/launch-example.json
@@ -9,6 +9,23 @@
"pathMappings": {
"/var/www/html/wp-content/plugins/gutenberg": "${workspaceRoot}/"
}
+ },
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Debug current e2e test",
+ "program": "${workspaceRoot}/node_modules/@wordpress/scripts/bin/wp-scripts.js",
+ "args": [
+ "test-e2e",
+ "--config=${workspaceRoot}/packages/e2e-tests/jest.config.js",
+ "--verbose=true",
+ "--runInBand",
+ "--watch",
+ "${file}"
+ ],
+ "console": "integratedTerminal",
+ "internalConsoleOptions": "neverOpen",
+ "trace": "all"
}
]
-}
\ No newline at end of file
+}
diff --git a/bin/packages/build.js b/bin/packages/build.js
index eff2fcd732020..250492506ae7d 100755
--- a/bin/packages/build.js
+++ b/bin/packages/build.js
@@ -263,7 +263,8 @@ stream
console.error( error );
}
- if ( ended && ++complete === files.length ) {
+ ++complete;
+ if ( ended && complete === files.length ) {
workerFarm.end( worker );
}
} )
diff --git a/bin/plugin/commands/changelog.js b/bin/plugin/commands/changelog.js
index 73d8afdae4edf..dca2ce62406e7 100644
--- a/bin/plugin/commands/changelog.js
+++ b/bin/plugin/commands/changelog.js
@@ -780,7 +780,9 @@ async function createChangelog( settings ) {
try {
changelog = await getChangelog( settings );
} catch ( error ) {
- changelog = formats.error( error.stack );
+ if ( error instanceof Error ) {
+ changelog = formats.error( error.stack );
+ }
}
log( changelog );
diff --git a/changelog.txt b/changelog.txt
index a25a0c2a499fd..ffc9af781783f 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,5 +1,442 @@
== Changelog ==
+= 11.5.0-rc.1 =
+
+### Features
+
+- Add Dark Mode-specific help section images. ([34361](https://github.com/WordPress/gutenberg/pull/34361))
+
+#### Block Library
+- Group block: Add a row variation. ([34535](https://github.com/WordPress/gutenberg/pull/34535))
+
+#### Design Tools
+- Block Support: Add gap block support feature. ([33991](https://github.com/WordPress/gutenberg/pull/33991))
+
+
+### Enhancements
+
+- Add isRawAttribute to entity configuration. ([34388](https://github.com/WordPress/gutenberg/pull/34388))
+- Consolidate the PATHS_WITH_MERGE constant to one instance. ([34407](https://github.com/WordPress/gutenberg/pull/34407))
+- Fix title missing in bug report form. ([34504](https://github.com/WordPress/gutenberg/pull/34504))
+- General Interface: Make permalinks documentation URL translatable. ([34282](https://github.com/WordPress/gutenberg/pull/34282))
+- Update bug form to use drop downs. ([34458](https://github.com/WordPress/gutenberg/pull/34458))
+
+#### Block Library
+- Update Site Logo block description to be concise. ([34471](https://github.com/WordPress/gutenberg/pull/34471))
+- Update the Table block description to be concise. ([34475](https://github.com/WordPress/gutenberg/pull/34475))
+- Use blockGap between Columns blocks. ([34456](https://github.com/WordPress/gutenberg/pull/34456))
+- Video Block: Use existing video poster image on insert. ([34415](https://github.com/WordPress/gutenberg/pull/34415))
+- [Query Pagination Next/Previous]: Add an arrow attribute and sync next/previous block's arrow. ([33656](https://github.com/WordPress/gutenberg/pull/33656))
+
+#### Design Tools
+- Add wide alignment control only if theme provides `layout.wideSize`. ([34586](https://github.com/WordPress/gutenberg/pull/34586))
+- Gap block support: Force gap change to cause the block to re-render (fix Safari issue). ([34567](https://github.com/WordPress/gutenberg/pull/34567))
+- Post Author Block: Add duotone suport. ([34408](https://github.com/WordPress/gutenberg/pull/34408))
+- ToolsPanel: Change icon from horizontal to vertical ellipsis. ([34369](https://github.com/WordPress/gutenberg/pull/34369))
+
+#### Navigation Screen
+- Add undo redo buttons in navigation editor. ([34533](https://github.com/WordPress/gutenberg/pull/34533))
+- Disable "block-nav-menus" feature for the purposes of removing the "experimental" status on the Navigation Editor. ([34444](https://github.com/WordPress/gutenberg/pull/34444))
+- Preload menu REST API requests on new navigation editor. ([34364](https://github.com/WordPress/gutenberg/pull/34364))
+- Update navigation editor placeholder. ([34568](https://github.com/WordPress/gutenberg/pull/34568))
+
+#### Widgets Editor
+- Add 'Widget Group' block to widgets screens. ([34484](https://github.com/WordPress/gutenberg/pull/34484))
+- Legacy widget rendering endpoint. ([34230](https://github.com/WordPress/gutenberg/pull/34230))
+
+#### Global Styles
+- Allow disabling `text` and `background` color via `theme.json`. ([34420](https://github.com/WordPress/gutenberg/pull/34420))
+- Make global styles available to all themes. ([34334](https://github.com/WordPress/gutenberg/pull/34334))
+
+#### Block Editor
+- Media Placeholder: Change media URL input type to allow a local URL path. ([29138](https://github.com/WordPress/gutenberg/pull/29138))
+
+#### Block Variations
+- Remove horizontal and vertical navigation block variations from inserter. ([34614](https://github.com/WordPress/gutenberg/pull/34614))
+
+#### Post Editor
+- Try: Title block gap. ([34570](https://github.com/WordPress/gutenberg/pull/34570))
+
+#### Themes
+- Add default editor styles applied to themes without theme.json and without editor styles. ([34439](https://github.com/WordPress/gutenberg/pull/34439))
+
+#### Components
+- MenuItem: Add right padding for unchecked radio and checkbox items. ([34406](https://github.com/WordPress/gutenberg/pull/34406))
+
+#### Full Site Editing
+- Limit FSE admin notices to the Themes screen. ([34353](https://github.com/WordPress/gutenberg/pull/34353))
+
+#### List View
+- Block Navigation List: Do not show appender and avoid closing the modal on block select. ([34337](https://github.com/WordPress/gutenberg/pull/34337))
+
+#### CSS & Styling
+- Block Styles: Fix long strings of text without spaces overflow the block. ([34222](https://github.com/WordPress/gutenberg/pull/34222))
+
+#### Testing
+- Debug e2e-tests in vscode. ([29788](https://github.com/WordPress/gutenberg/pull/29788))
+
+
+### New APIs
+
+#### Design Tools
+- Allow themes with theme.json to opt-out of block gap styles. ([34491](https://github.com/WordPress/gutenberg/pull/34491))
+
+
+### Bug Fixes
+
+- Block Toolbar & Popover component - Prevent sticky position from causing permanently obscured areas of the selected block. ([33981](https://github.com/WordPress/gutenberg/pull/33981))
+- Core Data: Adds 'include' to the query key. ([34583](https://github.com/WordPress/gutenberg/pull/34583))
+- ESLint: Add useSelect to direct function calls list. ([34301](https://github.com/WordPress/gutenberg/pull/34301))
+- Fix menu item padding regression. ([34435](https://github.com/WordPress/gutenberg/pull/34435))
+- Fix text-menu min widths. ([34532](https://github.com/WordPress/gutenberg/pull/34532))
+- Scripts: Only use svgr/webpack in js files. ([34394](https://github.com/WordPress/gutenberg/pull/34394))
+- Use resolveSelect instead of select in saveEntityRecord. ([34584](https://github.com/WordPress/gutenberg/pull/34584))
+
+#### Block Library
+- Fix Column bottom sheet Android close button. ([34332](https://github.com/WordPress/gutenberg/pull/34332))
+- Fix Page List styles inside responsive Navigation. ([34517](https://github.com/WordPress/gutenberg/pull/34517))
+- Fix navigation block classname issues. ([34344](https://github.com/WordPress/gutenberg/pull/34344))
+- Fix responsive menu height regression. ([34488](https://github.com/WordPress/gutenberg/pull/34488))
+- Fix submenu layout in navigation page list. ([34342](https://github.com/WordPress/gutenberg/pull/34342))
+- Fix undo/redo 'trap' in navigation link block. ([34565](https://github.com/WordPress/gutenberg/pull/34565))
+- Fix various React warnings in development log. ([34428](https://github.com/WordPress/gutenberg/pull/34428))
+- Gallery block: Fix bug with stalled upload when image size too large. ([34371](https://github.com/WordPress/gutenberg/pull/34371))
+- Gallery block: Fix media placeholder height in site editor. ([34629](https://github.com/WordPress/gutenberg/pull/34629))
+- Gallery block: Fix problem with overflowing captions on new gallery block format. ([34402](https://github.com/WordPress/gutenberg/pull/34402))
+- Site title: Allow empty title in edit mode. ([34274](https://github.com/WordPress/gutenberg/pull/34274))
+- Try: Fix so submenus only take up space when visible. ([34382](https://github.com/WordPress/gutenberg/pull/34382))
+- Video Block: Fix TypeError when removing poster. ([34411](https://github.com/WordPress/gutenberg/pull/34411))
+
+#### Components
+- Align labels on focal point picker position controls above the inputs. ([34209](https://github.com/WordPress/gutenberg/pull/34209))
+- Check if in browser env before calling `CSS.supports`. ([34572](https://github.com/WordPress/gutenberg/pull/34572))
+- CustomSelectControl: Add describedBy fallback. ([34385](https://github.com/WordPress/gutenberg/pull/34385))
+- DateTime Component: Fix sizing of help info. ([34370](https://github.com/WordPress/gutenberg/pull/34370))
+- Fix `ToggleGroupControlBackdrop` not updating size when `isAdaptiveWidth` prop changes. ([34595](https://github.com/WordPress/gutenberg/pull/34595))
+- Fix selected value computation in `CustomSelectControl` when no initial `value` is set. ([34490](https://github.com/WordPress/gutenberg/pull/34490))
+- Fix subheadings from wrapping. ([34319](https://github.com/WordPress/gutenberg/pull/34319))
+
+#### Design Tools
+- Border Controls: Display color indicator and check selected color. ([34467](https://github.com/WordPress/gutenberg/pull/34467))
+- Border Support: Fix check for displaying border support panel. ([34516](https://github.com/WordPress/gutenberg/pull/34516))
+- Letter Spacing: Group letter spacing correctly under typography supports. ([34515](https://github.com/WordPress/gutenberg/pull/34515))
+
+#### Widgets Editor
+- Fix Block Settings sidebar unexpectedly collapsing. ([34543](https://github.com/WordPress/gutenberg/pull/34543))
+- Legacy widget's preview functionality is broken when the page is moved. ([34384](https://github.com/WordPress/gutenberg/pull/34384))
+
+#### Global Styles
+- Fix block-level global styles color panels. ([34293](https://github.com/WordPress/gutenberg/pull/34293))
+- Font Appearance Control: Fix error in global styles for Site Title in TT1-Blocks. ([34520](https://github.com/WordPress/gutenberg/pull/34520))
+
+#### Testing
+- Jest Preset: Restore the default setting for the `verbose` option. ([34327](https://github.com/WordPress/gutenberg/pull/34327))
+- Make Test_Widget compatible with WP_Widget. ([34355](https://github.com/WordPress/gutenberg/pull/34355))
+
+#### Meta Boxes
+- Change default value of enableCustomFields to undefined. ([33931](https://github.com/WordPress/gutenberg/pull/33931))
+- Fix metabox reordering. ([30617](https://github.com/WordPress/gutenberg/pull/30617))
+
+#### Block API
+- Blocks: Register block when invalid value provided for the icon. ([34350](https://github.com/WordPress/gutenberg/pull/34350))
+
+#### Accessibility
+- Fix button block focus trap after a URL has been added. ([34314](https://github.com/WordPress/gutenberg/pull/34314))
+
+#### REST API
+- Default batch processor: Respect the batch endpoint's maxItems. ([34280](https://github.com/WordPress/gutenberg/pull/34280))
+
+#### Navigation Screen
+- Decode entities in the menu names. ([34263](https://github.com/WordPress/gutenberg/pull/34263))
+
+#### Rich Text
+- [Block Editor]: Fix caret position on block merging. ([34169](https://github.com/WordPress/gutenberg/pull/34169))
+
+#### Block Editor
+- Keep id on paste if internal link points to it. ([31107](https://github.com/WordPress/gutenberg/pull/31107))
+
+#### Build Tooling
+- Fix build hang on Windows 10. ([23589](https://github.com/WordPress/gutenberg/pull/23589))
+
+
+### Performance
+
+- Improve the getBlock and getBlocks performance. ([34241](https://github.com/WordPress/gutenberg/pull/34241))
+- Remove duplicated `useValidAlignment` hook. ([34593](https://github.com/WordPress/gutenberg/pull/34593))
+- core-data: Move locks state from store to local variable. ([34374](https://github.com/WordPress/gutenberg/pull/34374))
+
+#### Global Styles
+- Remove colors classes from the packages that are already provided by global styles. ([34510](https://github.com/WordPress/gutenberg/pull/34510))
+
+
+### Experiments
+
+#### Block Library
+- Allow Site Title and Logo inside Navigation block. ([33316](https://github.com/WordPress/gutenberg/pull/33316))
+- [Social Links]: Use the new `flex` layout. ([34493](https://github.com/WordPress/gutenberg/pull/34493))
+
+#### Global Styles
+- Add unit tests for edit site editor utils. ([34401](https://github.com/WordPress/gutenberg/pull/34401))
+
+
+### Documentation
+
+- Correct typo in Blocks Documentation. ([34396](https://github.com/WordPress/gutenberg/pull/34396))
+- Eslint: Add no-unsafe-wp-apis to rules list in the documentation. ([34416](https://github.com/WordPress/gutenberg/pull/34416))
+- RNMobile: Fix links, images, and formatting in documentation. ([34300](https://github.com/WordPress/gutenberg/pull/34300))
+- Replace withSelect references with useSelect. ([34549](https://github.com/WordPress/gutenberg/pull/34549))
+- Update DuotonePicker documentation for accuracy. ([34494](https://github.com/WordPress/gutenberg/pull/34494))
+- Updated Template section copy. ([34383](https://github.com/WordPress/gutenberg/pull/34383))
+- [Docs]: Update block variations documentation about `block` scope. ([34455](https://github.com/WordPress/gutenberg/pull/34455))
+- [Prettier] Updated README.md file with the correct syntax. ([34600](https://github.com/WordPress/gutenberg/pull/34600))
+
+#### Components
+- Fix/update documentation alignment matrix control. ([34624](https://github.com/WordPress/gutenberg/pull/34624))
+
+
+### Code Quality
+
+- Add getFilename method to the URL package. ([34313](https://github.com/WordPress/gutenberg/pull/34313))
+- Block Editor: Ensure that `blockType` is defined when accessing `apiVersion`. ([34346](https://github.com/WordPress/gutenberg/pull/34346))
+- Block Editor: Migrate `lightBlockWrapper` support to `apiVersion` for blocks. ([34459](https://github.com/WordPress/gutenberg/pull/34459))
+- Code cleanup to the getBlock refactoring. ([34326](https://github.com/WordPress/gutenberg/pull/34326))
+- Fix linting error in trunk. ([34464](https://github.com/WordPress/gutenberg/pull/34464))
+- Fix linting errors. ([34596](https://github.com/WordPress/gutenberg/pull/34596))
+- Linting: Remove global event listener warning. ([34528](https://github.com/WordPress/gutenberg/pull/34528))
+- Migrate canUser resolver to thunks. ([34580](https://github.com/WordPress/gutenberg/pull/34580))
+- Migrate entities.js to thunks. ([34582](https://github.com/WordPress/gutenberg/pull/34582))
+- Migrate getAutosaves resolver to thunks. ([34581](https://github.com/WordPress/gutenberg/pull/34581))
+- Migrate getEntityRecord resolver to thunks. ([34576](https://github.com/WordPress/gutenberg/pull/34576))
+- Migrate getEntityRecords resolver to thunks. ([34578](https://github.com/WordPress/gutenberg/pull/34578))
+- Migrate resolvers to thunks: GetAuthors,_getCurrentUser,__getCurrentTheme,__getThemeSupports. ([34579](https://github.com/WordPress/gutenberg/pull/34579))
+- Refactor deleteEntityRecord to use thunks instead of generators. ([34386](https://github.com/WordPress/gutenberg/pull/34386))
+- Refactor editEntityRecord, undo, and redo to be thunks instead of generators. ([34387](https://github.com/WordPress/gutenberg/pull/34387))
+- Refactor saveEntityRecord from redux-rungen to async thunks. ([33201](https://github.com/WordPress/gutenberg/pull/33201))
+- Remove confusing punctuation. ([34322](https://github.com/WordPress/gutenberg/pull/34322))
+- Remove extraction of raw values in saveEntityRecords. ([34502](https://github.com/WordPress/gutenberg/pull/34502))
+- Rich text: Replace global event handlers with local ones. ([34492](https://github.com/WordPress/gutenberg/pull/34492))
+- core-data: Remove the PROCESS_PENDING_LOCK_REQUESTS action. ([34343](https://github.com/WordPress/gutenberg/pull/34343))
+- i18n: Add context to 'none' strings for better translations. ([34341](https://github.com/WordPress/gutenberg/pull/34341))
+- useDropZone: Ensure drag event targets HTMLElement. ([34272](https://github.com/WordPress/gutenberg/pull/34272))
+
+#### Block Library
+- Button block: Replace global shortcut event handlers with local ones. ([34498](https://github.com/WordPress/gutenberg/pull/34498))
+- Gallery Block : Remove IE specific CSS hacks. ([34372](https://github.com/WordPress/gutenberg/pull/34372))
+- Gallery block: Add docblock comments to the new gallery hooks. ([34562](https://github.com/WordPress/gutenberg/pull/34562))
+- Navigation link block: Replace global shortcut event handlers with local ones. ([34500](https://github.com/WordPress/gutenberg/pull/34500))
+- Refactor navigation block to use generic classnames. ([34171](https://github.com/WordPress/gutenberg/pull/34171))
+- Remove redundant css selector. ([34277](https://github.com/WordPress/gutenberg/pull/34277))
+
+#### Components
+- CustomGradientBar: Replace global shortcut event handlers with local ones. ([34505](https://github.com/WordPress/gutenberg/pull/34505))
+- Guide: Replace global shortcut event handlers with local ones. ([34503](https://github.com/WordPress/gutenberg/pull/34503))
+- Navigate regions: Use React events for shortcuts (portal bubbles & contextual). ([33633](https://github.com/WordPress/gutenberg/pull/33633))
+- Rename `PolymorphicComponent*` types to `WordPressComponent*`. ([34330](https://github.com/WordPress/gutenberg/pull/34330))
+- Simplify Modal with hooks. ([34412](https://github.com/WordPress/gutenberg/pull/34412))
+- Try: Simplify & polish heading levels. ([34378](https://github.com/WordPress/gutenberg/pull/34378))
+
+#### Post Editor
+- Editor package: Replace hardcoded store key. ([34296](https://github.com/WordPress/gutenberg/pull/34296))
+- Fix gray W menu color. ([34318](https://github.com/WordPress/gutenberg/pull/34318))
+
+#### Block Editor
+- Fix Animated warning log. ([34197](https://github.com/WordPress/gutenberg/pull/34197))
+- Rich text (core): OnFocus method can be replaced with HTMLElement.focus. ([32054](https://github.com/WordPress/gutenberg/pull/32054))
+
+#### CSS & Styling
+- Navigation: Use gap instead of margin. ([32367](https://github.com/WordPress/gutenberg/pull/32367))
+
+
+### Tools
+
+- Added janw-me to the Codeowners for the PHP FSE folder. ([32990](https://github.com/WordPress/gutenberg/pull/32990))
+
+#### Build Tooling
+- ESLint: Update error message for `@emotion/css` with info about the `useCx` hook. ([34418](https://github.com/WordPress/gutenberg/pull/34418))
+- More work on the stability of the performance metrics. ([34229](https://github.com/WordPress/gutenberg/pull/34229))
+
+
+### Various
+
+- Upgrade gradle to 7.1.1 agp to 4.2.2. ([34048](https://github.com/WordPress/gutenberg/pull/34048))
+
+#### Components
+- Combobox Component: Only force expanded state if the input has focus. ([34090](https://github.com/WordPress/gutenberg/pull/34090))
+- Try: Vertical heading levels menu. ([32926](https://github.com/WordPress/gutenberg/pull/32926))
+- [ToggleGroupControl]: Update stories to use knobs. ([34497](https://github.com/WordPress/gutenberg/pull/34497))
+
+#### Plugin
+- Update the minimum supported WordPress version to 5.7. ([34536](https://github.com/WordPress/gutenberg/pull/34536))
+
+#### Accessibility
+- Accessibility improvement for font weight screen reader description. ([34312](https://github.com/WordPress/gutenberg/pull/34312))
+
+#### Widgets Editor
+- Prevent focus trap in Legacy Widget block’s preview iframe. ([33614](https://github.com/WordPress/gutenberg/pull/33614))
+
+#### Post Editor
+- Expose ThemeSupportCheck component. ([20506](https://github.com/WordPress/gutenberg/pull/20506))
+
+
+
+
+
+= 11.4.1 =
+
+### Bug Fixes
+
+- Post title: Remove class from old div to fix alignment. ([34489](https://github.com/WordPress/gutenberg/pull/34489))
+
+
+= 11.4.0 =
+
+### Enhancements
+- Accessibility
+ - Cover Block: Allow alt text in Cover blocks. ([33226](https://github.com/WordPress/gutenberg/pull/33226))
+ - Add `aria-describedby` to custom select control component to describe currently-selected font size. ([33941](https://github.com/WordPress/gutenberg/pull/33941))
+- Block Editor
+ - Block Lists: improve iframe block, pattern and template previews. ([28165](https://github.com/WordPress/gutenberg/pull/28165))
+- Block Library
+ - Query Loop: update Post Template sub-block icon. ([34204](https://github.com/WordPress/gutenberg/pull/34204))
+ - Convert Gallery block to use Image blocks. ([25940](https://github.com/WordPress/gutenberg/pull/25940))
+ - Post Featured Image: add duotone block supports. ([34113](https://github.com/WordPress/gutenberg/pull/34113))
+ - Post Featured Image: add contextual help text to the `scale`property. ([34158](https://github.com/WordPress/gutenberg/pull/34158))
+ - File block: update transform from image to use image filename if caption is empty. ([34256](https://github.com/WordPress/gutenberg/pull/34256))
+ - Post date Block: add font weight support to the block. ([34070](https://github.com/WordPress/gutenberg/pull/34070))
+ - Post terms: add font weight support to the block. ([34142](https://github.com/WordPress/gutenberg/pull/34142))
+ - Site Tagline: add font weight support. ([33983](https://github.com/WordPress/gutenberg/pull/33983))
+ - Button: update spacing support to use axial padding. ([33859](https://github.com/WordPress/gutenberg/pull/33859))
+- Components
+ - Add deprecated props adapter for ColorPicker. ([34014](https://github.com/WordPress/gutenberg/pull/34014))
+ - Wrap SegmentedControl in a BaseControl with an added `help` property. ([34017](https://github.com/WordPress/gutenberg/pull/34017))
+ - Combobox: update the current selection if the list of suggestions is filtered. ([33928](https://github.com/WordPress/gutenberg/pull/33928))
+ - Post Title: use rich text hook and updating tag to `h1` ([31569](https://github.com/WordPress/gutenberg/pull/31569))
+- Design Tools
+ - Add layout default value support for blocks. ([34194](https://github.com/WordPress/gutenberg/pull/34194))
+ - Dimensions Panel: add padding tool as default for blocks where this is a common setting. ([34026](https://github.com/WordPress/gutenberg/pull/34026))
+- Navigation Screen
+ - Update navigation screen topbar. ([34166](https://github.com/WordPress/gutenberg/pull/34166))
+- Packages
+ - Updates the "settings" icon, which toggles the display of additional controls in an interface. ([34165](https://github.com/WordPress/gutenberg/pull/34165))
+- Post Editor
+ - Migrate post editor feature preferences to the interface package. ([34154](https://github.com/WordPress/gutenberg/pull/34154))
+- Widgets Editor
+ - Migrate customize widgets feature preferences to interface package. ([34135](https://github.com/WordPress/gutenberg/pull/34135))
+ - Refactor editor 'feature' preferences to interface package. ([33774](https://github.com/WordPress/gutenberg/pull/33774))
+
+### Bug Fixes
+- Block API
+ - Spacing/Dimensions Supports: separate spacing from dimensions for compatibility purposes. ([34059](https://github.com/WordPress/gutenberg/pull/34059))
+- Block Editor
+ - Font-size adjustment for tablet and mobile device previews. ([33342](https://github.com/WordPress/gutenberg/pull/33342))
+ - Fix single block selection by holding `shift` key. ([34137](https://github.com/WordPress/gutenberg/pull/34137))
+ - Fix unwanted additional spaces added around pasted text on Windows. ([33607](https://github.com/WordPress/gutenberg/pull/33607))
+ - Inserter: prevent non-deterministic order of inserter items. ([34078](https://github.com/WordPress/gutenberg/pull/34078))
+ - Try: Fix multiselect toolbar indent and reformat `BlockContextualToolbar()`. ([34038](https://github.com/WordPress/gutenberg/pull/34038)) ([34173](https://github.com/WordPress/gutenberg/pull/34173))
+- Block Library
+ - Latest Comments: use site locale in the editor. ([33944](https://github.com/WordPress/gutenberg/pull/33944))
+ - Navigation: fix vertical layout on the frontend. ([34226](https://github.com/WordPress/gutenberg/pull/34226))
+ - Navigation: add z-index value to responsive menu overlay. ([34228](https://github.com/WordPress/gutenberg/pull/34228))
+ - Navigation: enable flex on container to fix space between. ([34258](https://github.com/WordPress/gutenberg/pull/34258))
+ - Navigation: fix submenu icon positioning. ([34168](https://github.com/WordPress/gutenberg/pull/34168))
+ - Navigation block: add missing `` closing tag. ([34077](https://github.com/WordPress/gutenberg/pull/34077))
+ - Post Excerpt: remove interactive formatting. ([34083](https://github.com/WordPress/gutenberg/pull/34083))
+ - RichText: fix `space` key for button and summary elements. ([30244](https://github.com/WordPress/gutenberg/pull/30244))
+ - Search Block: add space between generated border class names. ([34025](https://github.com/WordPress/gutenberg/pull/34025))
+- Build Tooling
+ - Webpack: Fix watch on `.json` and `.php` files. ([34024](https://github.com/WordPress/gutenberg/pull/34024))
+ - Pin TypeScript dependency to a specific version to avoid pulling in breaking changes. ([34422](https://github.com/WordPress/gutenberg/pull/34422))
+- Components
+ - Fix RTL on `Flex` component. ([33729](https://github.com/WordPress/gutenberg/pull/33729))
+ - NavigationSidebar: fix template content for content-navigation-item preview. ([34203](https://github.com/WordPress/gutenberg/pull/34203))
+ - Remove deprecated import style for storybook/addon-docs. ([34095](https://github.com/WordPress/gutenberg/pull/34095))
+ - ToolsPanel: add tools panel item deregistration. ([34085](https://github.com/WordPress/gutenberg/pull/34085))
+ - Post Title: remove wrapper div and fix border style. ([34167](https://github.com/WordPress/gutenberg/pull/34167))
+- Core Data
+ - `GetEntityRecords` returns items even if some included IDs don't exist. ([34034](https://github.com/WordPress/gutenberg/pull/34034))
+- Design Tools
+ - Allow zero values for `theme.json` styles. ([34251](https://github.com/WordPress/gutenberg/pull/34251))
+- Global Styles
+ - Site editor: fix for how CSS custom properties are generated. ([33932](https://github.com/WordPress/gutenberg/pull/33932))
+- Packages
+ - Rich Text: add check to `toTree()` in replacements before accessing its type. ([34020](https://github.com/WordPress/gutenberg/pull/34020))
+- Post Editor
+ - Fix selector params in `isPluginItemPinned()` selector. ([34155](https://github.com/WordPress/gutenberg/pull/34155))
+
+
+### Performance
+- Data Layer
+ - Data: Add a batch function to the data module to batch actions. ([34046](https://github.com/WordPress/gutenberg/pull/34046))
+
+### Experiments
+- Block API
+ - Block Editor: absorb parent block toolbar controls. ([33955](https://github.com/WordPress/gutenberg/pull/33955))
+ - Block Editor: use groups for InspectorControls. ([34069](https://github.com/WordPress/gutenberg/pull/34069))
+- Block Library
+ - Add generic classnames to children of Navigation. ([33918](https://github.com/WordPress/gutenberg/pull/33918))
+- Global Styles
+ - Add slashes back to the Theme JSON. ([33919](https://github.com/WordPress/gutenberg/pull/33919))
+ - Add block spacing gap configuration to `theme.json` and add support for this CSS variable to the "flow/default" layout. ([33812](https://github.com/WordPress/gutenberg/pull/33812))
+
+
+### Documentation
+- Handbook
+ - Alphabetize glossary entries. ([34058](https://github.com/WordPress/gutenberg/pull/34058))
+ - Correct minor typos in `wp-plugin.md` ([34185](https://github.com/WordPress/gutenberg/pull/34185))
+ - Remove extraneous params from `block_type_metadata` hook. ([34151](https://github.com/WordPress/gutenberg/pull/34151))
+ - Update incorrect settings examples in "Global Settings & Styles". ([34084](https://github.com/WordPress/gutenberg/pull/34084))
+ - Use `block.json` to add attributes in create block tutorial. ([33978](https://github.com/WordPress/gutenberg/pull/33978))
+ - Fix typo in block gap documentation in `theme-json.md`. ([34231](https://github.com/WordPress/gutenberg/pull/34231))
+ - Fix broken mobile testing documentation link in `testing-overview.md`. ([34187](https://github.com/WordPress/gutenberg/pull/34187))
+ - Fix typo in `legacy-widget-block.md`. ([34103](https://github.com/WordPress/gutenberg/pull/34103))
+ - Update spelling and `fontSize` examples in `create-block-theme.md`. ([34152](https://github.com/WordPress/gutenberg/pull/34152))
+- Library
+ - Bump mobile version in experiments page for Gallery. ([34220](https://github.com/WordPress/gutenberg/pull/34220))
+- Packages
+ - Add documentation for mobile components directory. ([33872](https://github.com/WordPress/gutenberg/pull/33872))
+
+### Code Quality
+- Block Editor
+ - Render head and body with single portal for block previews. ([34208](https://github.com/WordPress/gutenberg/pull/34208))
+ - BlockList: refactor element context for style/svg appending. ([34183](https://github.com/WordPress/gutenberg/pull/34183))
+ - BlockList: use InnerBlocks internally. ([29895](https://github.com/WordPress/gutenberg/pull/29895))
+- Components
+ - Unit Control: add unit tests for `getValidParsedUnit` utility method. ([34029](https://github.com/WordPress/gutenberg/pull/34029))
+ - Rename `SegmentedControl` to `ToggleGroupControl`. ([34111](https://github.com/WordPress/gutenberg/pull/34111))
+ - Dropdown Menu: remove min-width from the dropdown component and add whitespace rule to avoid wrapping ([33995](https://github.com/WordPress/gutenberg/pull/33995))
+- Core Data
+ - Allow passing store definitions to controls. ([34170](https://github.com/WordPress/gutenberg/pull/34170))
+- Site Editor
+ - Remove extra DOM element used for template part overlay. ([34012](https://github.com/WordPress/gutenberg/pull/34012))
+
+### Tools
+- Build Tooling
+ - Automated Changelog: force group all documentation tasks under `Documentation`. ([34042](https://github.com/WordPress/gutenberg/pull/34042))
+ - Automated Changelog: rename "Editor" grouping to "Post Editor" to avoid ambiguity with other editors. ([34093](https://github.com/WordPress/gutenberg/pull/34093))
+ - Automated Changelog: sort feature groups by issue name. ([34071](https://github.com/WordPress/gutenberg/pull/34071))
+ - Automated Changelog: use nested headings for feature groups instead of indenting lists. ([34040](https://github.com/WordPress/gutenberg/pull/34040))
+ - Automated Changelog: remove `Uncategorized` header in output and place items at top. ([34037](https://github.com/WordPress/gutenberg/pull/34037))
+ - Add Typescript extensions to watched files. ([34094](https://github.com/WordPress/gutenberg/pull/34094))
+ - Remove obsolete step that pushes tags in NPM publishing flow. ([34114](https://github.com/WordPress/gutenberg/pull/34114))
+ - Release workflow: only commit modified changelogs. ([34211](https://github.com/WordPress/gutenberg/pull/34211))
+- ESLint
+ - Eslint plugin: use `@typescript-eslint/no-duplicate-imports` in TS projects. ([34055](https://github.com/WordPress/gutenberg/pull/34055))
+- GitHub Contributor Templates
+ - Issue Forms: simplify the bug report form template. ([34007](https://github.com/WordPress/gutenberg/pull/34007))
+- Logs
+ - Hide deprecation logs under a console group. ([34163](https://github.com/WordPress/gutenberg/pull/34163))
+- Testing
+ - Emulate reduced-motion in end-to-end tests. ([34132](https://github.com/WordPress/gutenberg/pull/34132))
+ - Re-enable Android end-to-end tests. ([34243](https://github.com/WordPress/gutenberg/pull/34243))
+ - Remove extra props from Cover deprecations. ([34066](https://github.com/WordPress/gutenberg/pull/34066))
+ - Remove the `ENVIRONMENT_DIRECTORY` env variable that was added to the performance jobs. ([34086](https://github.com/WordPress/gutenberg/pull/34086))
+ - Add snapshot test for changelog formatting. ([34049](https://github.com/WordPress/gutenberg/pull/34049))
+ - Experiment with using REST API in end-to-end tests to build up states. ([33414](https://github.com/WordPress/gutenberg/pull/33414))
+
+
+
+
+
= 11.3.0 =
### Enhancements
diff --git a/docs/contributors/code/getting-started-native-mobile.md b/docs/contributors/code/getting-started-native-mobile.md
index a3dbeedcd98a3..dbdeba751aa50 100644
--- a/docs/contributors/code/getting-started-native-mobile.md
+++ b/docs/contributors/code/getting-started-native-mobile.md
@@ -9,15 +9,15 @@ For a developer experience closer to the one the project maintainers current hav
- git
- [nvm](https://github.com/creationix/nvm)
- Node.js and npm (use nvm to install them)
-- [AndroidStudio](https://developer.android.com/studio/) to be able to compile the Android version of the app
+- [Android Studio](https://developer.android.com/studio/) to be able to compile the Android version of the app
- [Xcode](https://developer.apple.com/xcode/) to be able to compile the iOS app
-- CocoaPods(`sudo gem install cocoapods`) needed to fetch React and third-party dependencies.
+- CocoaPods (`sudo gem install cocoapods`) needed to fetch React and third-party dependencies.
Note that the OS platform used by the maintainers is macOS but the tools and setup should be usable in other platforms too.
## Clone the project
-```
+```sh
git clone https://github.com/WordPress/gutenberg.git
```
@@ -25,14 +25,14 @@ git clone https://github.com/WordPress/gutenberg.git
Note that the commands described here should be run in the top-level directory of the cloned project. Before running the demo app, you need to download and install the project dependencies. This is done via the following command:
-```
+```sh
nvm install
npm ci
```
## Run
-```
+```sh
npm run native start:reset
```
@@ -40,7 +40,7 @@ Runs the packager (Metro) in development mode. The packager stays running to ser
With the packager running, open another terminal window and use the following command to compile and run the Android app:
-```
+```sh
npm run native android
```
@@ -48,7 +48,7 @@ The app should now open in a connected device or a running emulator and fetch th
To compile and run the iOS variant of the app using the _default_ simulator device, use:
-```
+```sh
npm run native ios
```
@@ -58,13 +58,13 @@ which will attempt to open your app in the iOS Simulator if you're on a Mac and
To compile and run the app using a different device simulator, use the following, noting the double sets of `--` to pass the simulator option down to the `react-native` CLI.
-```
+```sh
npm run native ios -- -- --simulator="DEVICE_NAME"
```
For example, if you'd like to run in an iPhone Xs Max, try:
-```
+```sh
npm run native ios -- -- --simulator="iPhone Xs Max"
```
@@ -86,7 +86,7 @@ One of the extensions we are using is the [React Native Tools](https://marketpla
Use the following command to run the test suite:
-```
+```sh
npm run native test
```
@@ -94,7 +94,7 @@ It will run the [jest](https://github.com/facebook/jest) test runner on your tes
To run the tests with debugger support, start it with the following CLI command:
-```
+```sh
npm run native test:debug
```
@@ -114,15 +114,21 @@ This repository uses Appium to run UI tests. The tests live in `__device-tests__
Then, to run the UI tests on iOS:
-`npm run native test:e2e:ios:local`
+```sh
+npm run native test:e2e:ios:local
+```
and for Android:
-`npm run native test:e2e:android:local`
+```sh
+npm run native test:e2e:android:local
+```
To run a single test instead of the entire suite, use `npm run native device-tests:local`. Here's an example that runs only `gutenberg-editor-gallery.test.js`:
-`npm run native test:e2e:android:local gutenberg-editor-gallery.test.js`
+```sh
+npm run native test:e2e:android:local gutenberg-editor-gallery.test.js
+```
Note: You might experience problems that seem to be related to the tests starting the Appium server, e.g. errors that say `Connection Refused`, `Connection Reset` or `The requested environment is not available`. For now, you can manually start the Appium server via [appium desktop](https://github.com/appium/appium-desktop) or the CLI, then change the port number in the tests while (optionally) commenting out related code in the `beforeAll` and `afterAll` block.
diff --git a/docs/contributors/code/native-mobile-integration-test-guide.md b/docs/contributors/code/native-mobile-integration-test-guide.md
index 46bcd271094b2..14cb479dae194 100644
--- a/docs/contributors/code/native-mobile-integration-test-guide.md
+++ b/docs/contributors/code/native-mobile-integration-test-guide.md
@@ -27,7 +27,7 @@ This part usually is covered by using the Jest callbacks `beforeAll` and `before
Here is an example of a common pattern if we expect all core blocks to be available:
-```
+```js
beforeAll( () => {
// Register all core blocks
registerCoreBlocks();
@@ -42,7 +42,7 @@ Before introducing the testing logic, we have to render the components that we w
Here is an example of rendering the Cover block (extracted from [this code](https://github.com/WordPress/gutenberg/blob/86cd187873984f80ddeeec3e82454b486dd1860f/packages/block-library/src/cover/test/edit.native.js#L82-L91)):
-```
+```js
// This import points to the index file of the block
import { metadata, settings, name } from '../index';
@@ -83,7 +83,7 @@ const { getByText, findByText } = render(
Here is an example of rendering the Buttons block (extracted from [this code](https://github.com/WordPress/gutenberg/blob/9201906891a68ca305daf7f8b6cd006e2b26291e/packages/block-library/src/buttons/test/edit.native.js#L32-L39)):
-```
+```js
const initialHtml = `
@@ -106,15 +106,15 @@ When querying we should follow this priority order:
Here are some examples:
-```
+```js
const mediaLibraryButton = getByText( 'WordPress Media Library' );
```
-```
+```js
const missingBlock = getByA11yLabel( /Unsupported Block\. Row 1/ );
```
-```
+```js
const radiusSlider = getByTestId( 'Slider Border Radius' );
```
@@ -126,19 +126,19 @@ After rendering the components or firing an event, side effects might happen due
Here are some examples:
-```
+```js
const mediaLibraryButton = await waitFor( () =>
getByText( 'WordPress Media Library' )
);
```
-```
+```js
const missingBlock = await waitFor( () =>
getByA11yLabel( /Unsupported Block\. Row 1/ )
);
```
-```
+```js
const radiusSlider = await waitFor( () =>
getByTestId( 'Slider Border Radius' )
);
@@ -152,13 +152,11 @@ NOTE: The `react-native-testing-library` package provides the `query*` and `find
It’s also possible to query elements contained in other elements via the `within` function, here is an example:
-```
+```js
const missingBlock = await waitFor( () =>
getByA11yLabel( /Unsupported Block\. Row 1/ )
);
-const translatedTableTitle = within( missingBlock ).getByText(
- 'Tabla'
-);
+const translatedTableTitle = within( missingBlock ).getByText( 'Tabla' );
```
## Fire events
@@ -169,7 +167,7 @@ Here is an example of a press event:
**Press event:**
-```
+```js
fireEvent.press( settingsButton );
```
@@ -177,7 +175,7 @@ We can also trigger any type of event, including custom events, in the following
**Custom event – onValueChange:**
-```
+```js
fireEvent( heightSlider, 'valueChange', '50' );
```
@@ -187,18 +185,16 @@ After querying elements and firing events, we have to verify that the logic work
Here is an example:
-```
-const translatedTableTitle = within( missingBlock ).getByText(
- 'Tabla'
-);
+```js
+const translatedTableTitle = within( missingBlock ).getByText( 'Tabla' );
expect( translatedTableTitle ).toBeDefined();
```
Additionally when rendering the entire editor, we can also verify if the HTML output is what we expect:
-```
+```js
expect( getEditorHtml() ).toBe(
-'\n\n'
+ '\n\n'
);
```
@@ -206,7 +202,7 @@ expect( getEditorHtml() ).toBe(
And finally, we have to clean up any potential modifications we’ve made that could affect the following tests. Here is an example of a typical cleanup after registering blocks that implies unregistering all blocks:
-```
+```js
afterAll( () => {
// Clean up registered blocks
getBlockTypes().forEach( ( block ) => {
@@ -221,9 +217,9 @@ afterAll( () => {
A common way to query a block is by its accessibility label, here is an example:
-```
+```js
const spacerBlock = await waitFor( () =>
-getByA11yLabel( /Spacer Block\. Row 1/ )
+ getByA11yLabel( /Spacer Block\. Row 1/ )
);
```
@@ -233,7 +229,7 @@ For further information about the accessibility label of a block, you can check
Here is an example of how to insert a Paragraph block:
-```
+```js
// Open the inserter menu
fireEvent.press( await waitFor( () => getByA11yLabel( 'Add block' ) ) );
@@ -255,12 +251,10 @@ fireEvent.press( await waitFor( () => getByText( `Paragraph` ) ) );
The block settings can be accessed by tapping the "Open Settings" button after selecting the block, here is an example:
-```
+```js
fireEvent.press( block );
-const settingsButton = await waitFor( () =>
- getByA11yLabel( 'Open Settings' )
-);
+const settingsButton = await waitFor( () => getByA11yLabel( 'Open Settings' ) );
fireEvent.press( settingsButton );
```
@@ -268,10 +262,10 @@ fireEvent.press( settingsButton );
When using the scoped component approach, we need first to render the `SlotFillProvider` and the `BottomSheetSettings` (note that we’re passing the `isVisible` prop to force the bottom sheet to be displayed) along with the block:
-```
+```js
-
-
+
+
```
@@ -285,7 +279,7 @@ The `FlatList` component renders its items depending on the scroll position, the
Here is an example of the FlatList used for rendering the block list in the inserter menu:
-```
+```js
const blockList = getByTestId( 'InserterUI-Blocks' );
// onScroll event used to force the FlatList to render all items
fireEvent.scroll( blockList, {
@@ -301,7 +295,7 @@ fireEvent.scroll( blockList, {
Sliders found in bottom sheets should be queried using their `testID`:
-```
+```js
const radiusSlider = await waitFor( () =>
getByTestId( 'Slider Border Radius' )
);
@@ -314,7 +308,7 @@ Note that a slider’s `testID` is "Slider " + label. So for a slider with a lab
One caveat when adding blocks is that if they contain inner blocks, these inner blocks are not rendered. The following example shows how we can make a Buttons block render its inner Button blocks (assumes we’ve already obtained a reference to the Buttons block as `buttonsBlock`):
-```
+```js
const innerBlockListWrapper = await waitFor( () =>
within( buttonsBlock ).getByTestId( 'block-list-wrapper' )
);
@@ -338,7 +332,7 @@ fireEvent.press( buttonInnerBlock );
If you have trouble locating an element’s identifier, you may wish to use Xcode’s Accessibility Inspector. Most identifiers are cross-platform, so even though the tests are run on Android by default, the Accessibility Inspector can be used to find the right identifier.
-
+
## Common pitfalls and caveats
@@ -362,7 +356,7 @@ By default, all tests run in Jest use the Android platform, so in case we need t
In case we only need to test logic controlled by the Platform object, we can mock the module with the following code (in this case it’s changing the platform to iOS):
-```
+```js
jest.mock( 'Platform', () => {
const Platform = jest.requireActual( 'Platform' );
Platform.OS = 'ios';
diff --git a/docs/contributors/code/native-mobile.md b/docs/contributors/code/native-mobile.md
index d216720eda4c3..2db44df33fef3 100644
--- a/docs/contributors/code/native-mobile.md
+++ b/docs/contributors/code/native-mobile.md
@@ -21,7 +21,7 @@ Also, the mobile client is packaged and released via the [official WordPress app
If you encounter a failed Android/iOS test on your pull request, we recommend the following steps:
1. Re-running the failed GitHub Action job ([guide for how to re-run](https://docs.github.com/en/actions/configuring-and-managing-workflows/managing-a-workflow-run#viewing-your-workflow-history)) - This should fix failed tests the majority of the time. Cases where you need to re-run tests for a pass should go down in the near future as flakiness in tests is actively being worked on. See the following GitHub issue for updated info on known failures: https://github.com/WordPress/gutenberg/issues/23949
-2. You can check if the test is failing locally by following the steps to run the E2E test on your machine from the [mobile getting started guide](/docs/contributors/code/getting-started-with-code-contribution-native-mobile.md#ui-tests), with even more relevant info in the [relevant directory README.md](https://github.com/WordPress/gutenberg/tree/HEAD/packages/react-native-editor/__device-tests__#running-the-tests-locally)
+2. You can check if the test is failing locally by following the steps to run the E2E test on your machine from the [mobile getting started guide](/docs/contributors/code/getting-started-native-mobile.md#ui-tests), with even more relevant info in the [relevant directory README.md](https://github.com/WordPress/gutenberg/tree/HEAD/packages/react-native-editor/__device-tests__#running-the-tests-locally)
3. In addition to reading the logs from the E2E test, you can download a video recording from the Artifacts section of the GitHub job that may have additional useful information.
4. Check if any changes in your PR would require corresponding changes to `.native.js` versions of files.
5. Lastly, if you're stuck on a failing mobile test, feel free to reach out to contributors on Slack in the #mobile or #core-editor chats in the WordPress Core Slack, [free to join](https://make.wordpress.org/chat/).
diff --git a/docs/contributors/code/testing-overview.md b/docs/contributors/code/testing-overview.md
index b4b9e06270181..5f288d618233f 100644
--- a/docs/contributors/code/testing-overview.md
+++ b/docs/contributors/code/testing-overview.md
@@ -21,7 +21,7 @@ When writing tests consider the following:
Tests for JavaScript use [Jest](https://jestjs.io/) as the test runner and its API for [globals](https://jestjs.io/docs/en/api.html) (`describe`, `test`, `beforeEach` and so on) [assertions](https://jestjs.io/docs/en/expect.html), [mocks](https://jestjs.io/docs/en/mock-functions.html), [spies](https://jestjs.io/docs/en/jest-object.html#jestspyonobject-methodname) and [mock functions](https://jestjs.io/docs/en/mock-function-api.html). If needed, you can also use [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) for React component testing.
-It should be noted that in the past, React components were unit tested with [Enzyme](https://github.com/airbnb/enzyme). However, for new tests, it is preferred to use React Testing Library (RTL) and over time old tests should be refactored to use RTL too (typically when working on code that touches an old test).
+_It should be noted that in the past, React components were unit tested with [Enzyme](https://github.com/airbnb/enzyme). However, React Testing Library (RTL) should be used for new tests instead, and over time old tests should be refactored to use RTL too (typically when working on code that touches an old test)._
Assuming you've followed the [instructions](/docs/contributors/code/getting-started-with-code-contribution.md) to install Node and project dependencies, tests can be run from the command-line with NPM:
@@ -273,23 +273,22 @@ You should never create or modify a snapshot directly, they are generated and up
Snapshot are mostly targeted at component testing. They make us conscious of changes to a component's structure which makes them _ideal_ for refactoring. If a snapshot is kept up to date over the course of a series of commits, the snapshot diffs record the evolution of a component's structure. Pretty cool 😎
-```js
-import { shallow } from 'enzyme';
+```jsx
+import { render, screen } from '@testing-library/react';
import SolarSystem from 'solar-system';
-import { Mars } from 'planets';
describe( 'SolarSystem', () => {
test( 'should render', () => {
- const wrapper = shallow( );
+ const { container } = render( );
- expect( wrapper ).toMatchSnapshot();
+ expect( container.firstChild ).toMatchSnapshot();
} );
test( 'should contain mars if planets is true', () => {
- const wrapper = shallow( );
+ const { container } = render( );
- expect( wrapper ).toMatchSnapshot();
- expect( wrapper.find( Mars ) ).toHaveLength( 1 );
+ expect( container.firstChild ).toMatchSnapshot();
+ expect( screen.getByText( /mars/i ) ).toBeInTheDocument();
} );
} );
```
@@ -332,23 +331,41 @@ If you're starting a refactor, snapshots are quite nice, you can add them as the
Snapshots themselves don't express anything about what we expect. Snapshots are best used in conjunction with other tests that describe our expectations, like in the example above:
-```js
+```jsx
test( 'should contain mars if planets is true', () => {
- const wrapper = shallow( );
+ const { container } = render( );
// Snapshot will catch unintended changes
- expect( wrapper ).toMatchSnapshot();
+ expect( container.firstChild ).toMatchSnapshot();
// This is what we actually expect to find in our test
- expect( wrapper.find( Mars ) ).toHaveLength( 1 );
+ expect( screen.getByText( /mars/i ) ).toBeInTheDocument();
} );
```
-[`shallow`](http://airbnb.io/enzyme/docs/api/shallow.html) rendering is your friend:
+Another good technique is to use the `toMatchDiffSnapshot` function (provided by the [`snapshot-diff` package](https://github.com/jest-community/snapshot-diff)), which allows to snapshot only the difference between two different states of the DOM. This approach is useful to test the effects of a prop change on the resulting DOM while generating a much smaller snapshot, like in this example:
-> Shallow rendering is useful to constrain yourself to testing a component as a unit, and to ensure that your tests aren't indirectly asserting on behavior of child components.
+```jsx
+test( 'should render a darker background when isShady is true', () => {
+ const { container } = render( Body );
+ const { container: containerShady } = render(
+ Body
+ );
+ expect( container ).toMatchDiffSnapshot( containerShady );
+} );
+```
-It's tempting to snapshot deep renders, but that makes for huge snapshots. Additionally, deep renders no longer test a single component, but an entire tree. With `shallow`, we snapshot just the components that are directly rendered by the component we want to test.
+Similarly, the `toMatchStyleDiffSnapshot` function allows to snapshot only the difference between the _styles_ associated to two different states of a component, like in this example:
+
+```jsx
+test( 'should render margin', () => {
+ const { container: spacer } = render( );
+ const { container: spacerWithMargin } = render( );
+ expect( spacerWithMargin.firstChild ).toMatchStyleDiffSnapshot(
+ spacer.firstChild
+ );
+} );
+```
#### Troubleshooting
@@ -380,11 +397,11 @@ To locally run the tests in debug mode, follow these steps:
### Native mobile end-to-end tests
-Contributors to Gutenberg will note that PRs include continuous integration E2E tests running the native mobile E2E tests on Android and iOS. For troubleshooting failed tests, check our guide on [native mobile tests in continious integration](docs/contributors/native-mobile.md#native-mobile-e2e-tests-in-continuous-integration). More information on running these tests locally can be found in the [relevant directory README.md](https://github.com/WordPress/gutenberg/tree/HEAD/packages/react-native-editor/__device-tests__).
+Contributors to Gutenberg will note that PRs include continuous integration E2E tests running the native mobile E2E tests on Android and iOS. For troubleshooting failed tests, check our guide on [native mobile tests in continuous integration](/docs/contributors/code/native-mobile.md#native-mobile-e2e-tests-in-continuous-integration). More information on running these tests locally can be found in [here](/packages/react-native-editor/__device-tests__/README.md).
### Native mobile integration tests
-There is an ongoing effort to add integration tests to the native mobile project using the [`react-native-testing-library`](https://testing-library.com/docs/react-native-testing-library/intro/) library. A guide to writing integration tests can be found [here](native-mobile-integration-test-guide.md).
+There is an ongoing effort to add integration tests to the native mobile project using the [`react-native-testing-library`](https://testing-library.com/docs/react-native-testing-library/intro/) library. A guide to writing integration tests can be found [here](/docs/contributors/code/native-mobile-integration-test-guide.md).
## End-to-end Testing
diff --git a/docs/getting-started/tutorials/create-block/wp-plugin.md b/docs/getting-started/tutorials/create-block/wp-plugin.md
index b3d4a4a636e8c..ff1d1db7f455c 100644
--- a/docs/getting-started/tutorials/create-block/wp-plugin.md
+++ b/docs/getting-started/tutorials/create-block/wp-plugin.md
@@ -59,7 +59,7 @@ This will start your local WordPress site and use the current directory as your
### Confirm Plugin Installed
-The generated plugin should now be listed on the Plugins admin page in your WordPress install. Switch WorPress to the plugins page and activate.
+The generated plugin should now be listed on the Plugins admin page in your WordPress install. Switch WordPress to the plugins page and activate.
For more on creating a WordPress plugin see [Plugin Basics](https://developer.wordpress.org/plugins/plugin-basics/), and [Plugin Header requirements](https://developer.wordpress.org/plugins/plugin-basics/header-requirements/) for explanation and additional fields you can include in your plugin header.
@@ -67,7 +67,7 @@ For more on creating a WordPress plugin see [Plugin Basics](https://developer.wo
The `package.json` file defines the JavaScript properties for your project. This is a standard file used by NPM for defining properties and scripts it can run, the file and process is not specific to WordPress.
-A `package.json` file was created with the create script, this defines the dependecies and scripts needed. You can install dependencies. The only initial dependency is the `@wordpress/scripts` package that bundles the tools and configurations needed to build blocks.
+A `package.json` file was created with the create script, this defines the dependencies and scripts needed. You can install dependencies. The only initial dependency is the `@wordpress/scripts` package that bundles the tools and configurations needed to build blocks.
In `package.json`, there is a `scripts` property that defines what command to run when using `npm run (cmd)`. In our generated `package.json` file, the two main scripts point to the commands in the `wp-scripts` package:
diff --git a/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md b/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md
index bf86d303fc643..770fa53ec7c15 100644
--- a/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md
+++ b/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md
@@ -22,7 +22,7 @@ The following code example shows how to create a dynamic block that shows only t
```jsx
import { registerBlockType } from '@wordpress/blocks';
-import { withSelect } from '@wordpress/data';
+import { useSelect } from '@wordpress/data';
import { useBlockProps } from '@wordpress/block-editor';
registerBlockType( 'gutenberg-examples/example-dynamic', {
@@ -31,12 +31,11 @@ registerBlockType( 'gutenberg-examples/example-dynamic', {
icon: 'megaphone',
category: 'widgets',
- edit: withSelect( ( select ) => {
- return {
- posts: select( 'core' ).getEntityRecords( 'postType', 'post' ),
- };
- } )( ( { posts } ) => {
+ edit: () => {
const blockProps = useBlockProps();
+ const posts = useSelect( ( select ) => {
+ return select( 'core' ).getEntityRecords( 'postType', 'post' );
+ }, [] );
return (
);
- } ),
+ },
} );
```
@@ -59,7 +58,7 @@ registerBlockType( 'gutenberg-examples/example-dynamic', {
( function ( blocks, element, data, blockEditor ) {
var el = element.createElement,
registerBlockType = blocks.registerBlockType,
- withSelect = data.withSelect,
+ useSelect = data.useSelect,
useBlockProps = blockEditor.useBlockProps;
registerBlockType( 'gutenberg-examples/example-dynamic', {
@@ -67,24 +66,23 @@ registerBlockType( 'gutenberg-examples/example-dynamic', {
title: 'Example: last post',
icon: 'megaphone',
category: 'widgets',
- edit: withSelect( function ( select ) {
- return {
- posts: select( 'core' ).getEntityRecords( 'postType', 'post' ),
- };
- } )( function ( props ) {
- var blockProps = useBlockProps();
+ edit: function () {
var content;
- if ( ! props.posts ) {
+ var blockProps = useBlockProps();
+ var posts = useSelect( function ( select ) {
+ return select( 'core' ).getEntityRecords( 'postType', 'post' );
+ }, [] );
+ if ( ! posts ) {
content = 'Loading...';
- } else if ( props.posts.length === 0 ) {
+ } else if ( posts.length === 0 ) {
content = 'No posts';
} else {
- var post = props.posts[ 0 ];
+ var post = posts[ 0 ];
content = el( 'a', { href: post.link }, post.title.rendered );
}
return el( 'div', blockProps, content );
- } ),
+ },
} );
} )(
window.wp.blocks,
diff --git a/docs/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md b/docs/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md
index 3c6e8cb2418aa..c7e2805767170 100644
--- a/docs/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md
+++ b/docs/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md
@@ -137,7 +137,7 @@ const MY_TEMPLATE = [
{% end %}
-Use the `templateLock` property to lock down the template. Using `all` locks the template complete, no changes can be made. Using `insert` prevents additional blocks to be inserted, but existing blocks can be reordered. See [templateLock documentation](https://github.com/WordPress/gutenberg/tree/HEAD/packages/block-editor/src/components/inner-blocks/README.md#templatelock) for additional information.
+Use the `templateLock` property to lock down the template. Using `all` locks the template completely so no changes can be made. Using `insert` prevents additional blocks from being inserted, but existing blocks can be reordered. See [templateLock documentation](https://github.com/WordPress/gutenberg/tree/HEAD/packages/block-editor/src/components/inner-blocks/README.md#templatelock) for additional information.
### Post Template
diff --git a/docs/how-to-guides/format-api/2-toolbar-button.md b/docs/how-to-guides/format-api/2-toolbar-button.md
index ddc10df8c9877..5cbfabbdec05e 100644
--- a/docs/how-to-guides/format-api/2-toolbar-button.md
+++ b/docs/how-to-guides/format-api/2-toolbar-button.md
@@ -74,31 +74,26 @@ The following sample code renders the previously shown button only on Paragraph
```js
( function ( wp ) {
- var withSelect = wp.data.withSelect;
- var ifCondition = wp.compose.ifCondition;
- var compose = wp.compose.compose;
- var MyCustomButton = function ( props ) {
- return wp.element.createElement( wp.editor.RichTextToolbarButton, {
+ var el = wp.element.createElement;
+ var useSelect = wp.data.useSelect;
+
+ function ConditionalButton( props ) {
+ var selectedBlock = useSelect( function ( select ) {
+ return select( 'core/block-editor' ).getSelectedBlock();
+ }, [] );
+
+ if ( selectedBlock && selectedBlock.name !== 'core/paragraph' ) {
+ return null;
+ }
+
+ return el( wp.blockEditor.RichTextToolbarButton, {
icon: 'editor-code',
title: 'Sample output',
onClick: function () {
- console.log( 'toggle format' );
+ console.log( 'toggle format!' );
},
} );
};
- var ConditionalButton = compose(
- withSelect( function ( select ) {
- return {
- selectedBlock: select( 'core/editor' ).getSelectedBlock(),
- };
- } ),
- ifCondition( function ( props ) {
- return (
- props.selectedBlock &&
- props.selectedBlock.name === 'core/paragraph'
- );
- } )
- )( MyCustomButton );
wp.richText.registerFormatType( 'my-custom-format/sample-output', {
title: 'Sample output',
@@ -112,12 +107,19 @@ The following sample code renders the previously shown button only on Paragraph
{% ESNext %}
```js
-import { compose, ifCondition } from '@wordpress/compose';
import { registerFormatType } from '@wordpress/rich-text';
import { RichTextToolbarButton } from '@wordpress/block-editor';
-import { withSelect } from '@wordpress/data';
+import { useSelect } from '@wordpress/data';
+
+function ConditionalButton( props ) {
+ const selectedBlock = useSelect( ( select ) => {
+ return select( 'core/block-editor' ).getSelectedBlock();
+ }, [] );
+
+ if ( selectedBlock && selectedBlock.name !== 'core/paragraph' ) {
+ return null;
+ }
-const MyCustomButton = ( props ) => {
return (
{
} }
/>
);
-};
-
-const ConditionalButton = compose(
- withSelect( function ( select ) {
- return {
- selectedBlock: select( 'core/editor' ).getSelectedBlock(),
- };
- } ),
- ifCondition( function ( props ) {
- return (
- props.selectedBlock && props.selectedBlock.name === 'core/paragraph'
- );
- } )
-)( MyCustomButton );
+}
registerFormatType( 'my-custom-format/sample-output', {
title: 'Sample output',
@@ -152,6 +141,6 @@ registerFormatType( 'my-custom-format/sample-output', {
{% end %}
-Don't forget adding `wp-compose` and `wp-data` to the dependencies array in the PHP script.
+Don't forget adding `wp-data` to the dependencies array in the PHP script.
More advanced conditions can be used, e.g., only render the button depending on specific attributes of the block.
diff --git a/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-0.md b/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-0.md
index 750a12236d660..3a6d87c7a50b8 100644
--- a/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-0.md
+++ b/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-0.md
@@ -9,4 +9,3 @@ In the next sections, you're going to create a custom sidebar for a plugin that
3. [Register a new meta field](/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-3-register-meta.md)
4. [Initialize the input control with the meta field value](/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-4-initialize-input.md)
5. [Update the meta field value when input's content changes](/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-5-update-meta.md)
-6. [Finishing touches](/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-6-finishing-touches.md)
diff --git a/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-4-initialize-input.md b/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-4-initialize-input.md
index 106bd31925e44..1df2b7bfb3675 100644
--- a/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-4-initialize-input.md
+++ b/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-4-initialize-input.md
@@ -41,17 +41,9 @@ Now that the field is available in the editor store, it can be surfaced to the U
Now you can focus solely on the `MetaBlockField` component. The goal is to initialize it with the value of `sidebar_plugin_meta_block_field`, but also to keep it updated when that value changes.
-WordPress has [some utilities to work with data](/packages/data/README.md) from the stores. The first you're going to use is [withSelect](/packages/data/README.md#withselect-mapselecttoprops-function-function), whose signature is:
+WordPress has [some utilities to work with data](/packages/data/README.md) from the stores. The first you're going to use is [useSelect](/packages/data/README.md#useselect).
-```js
-withSelect()();
-// a function that takes `select` as input
-// and returns an object containing data
-// a function that takes the previous data as input
-// and returns a component
-```
-
-`withSelect` is used to pass data to other components, and update them when the original data changes. Let's update the code to use it:
+The `useSelect` is used to fetch data for the current component and update it when the original data changes. Let's update the code to use it:
```js
( function ( wp ) {
@@ -59,30 +51,22 @@ withSelect()();
var PluginSidebar = wp.editPost.PluginSidebar;
var el = wp.element.createElement;
var Text = wp.components.TextControl;
- var withSelect = wp.data.withSelect;
-
- var mapSelectToProps = function ( select ) {
- return {
- metaFieldValue: select( 'core/editor' ).getEditedPostAttribute(
- 'meta'
- )[ 'sidebar_plugin_meta_block_field' ],
- };
- };
+ var useSelect = wp.data.useSelect;
+
+ var MetaBlockField = function () {
+ var metaFieldValue = useSelect( function ( select ) {
+ return select( 'core/editor' ).getEditedPostAttribute( 'meta' )[ 'sidebar_plugin_meta_block_field' ];
+ }, [] );
- var MetaBlockField = function ( props ) {
return el( Text, {
label: 'Meta Block Field',
- value: props.metaFieldValue,
+ value: metaFieldValue,
onChange: function ( content ) {
console.log( 'content has changed to ', content );
},
} );
};
- var MetaBlockFieldWithData = withSelect( mapSelectToProps )(
- MetaBlockField
- );
-
registerPlugin( 'my-plugin-sidebar', {
render: function () {
return el(
@@ -95,7 +79,7 @@ withSelect()();
el(
'div',
{ className: 'plugin-sidebar-content' },
- el( MetaBlockFieldWithData )
+ el( MetaBlockField )
)
);
},
@@ -103,12 +87,11 @@ withSelect()();
} )( window.wp );
```
-Copy this code to the JavaScript file. Note that it now uses the `wp.data.withSelect` utility to be found in the `@wordpress/data` package. Go ahead and add `wp-data` as a dependency in the PHP script.
+Copy this code to the JavaScript file. Note that it now uses the `wp.data.useSelect` utility to be found in the `@wordpress/data` package. Go ahead and add `wp-data` as a dependency in the PHP script.
This is how the code changes from the previous section:
-- The `MetaBlockField` function has now a `props` argument as input. It contains the data object returned by the `mapSelectToProps` function, which it uses to initialize its value property.
-- The component rendered within the `div` element was also updated, the plugin now uses `MetaBlockFieldWithData`. This will be updated every time the original data changes.
+- The `MetaBlockField` component will be updated every time the original data changes.
- [getEditedPostAttribute](/docs/reference-guides/data/data-core-editor.md#geteditedpostattribute) is used to retrieve data instead of [getCurrentPost](/docs/reference-guides/data/data-core-editor.md#getcurrentpost) because it returns the most recent values of the post, including user editions that haven't been yet saved.
Update the code and open the sidebar. The input's content is no longer `Initial value` but a void string. Users can't type values yet, but let's check that the component is updated if the value in the store changes. Open the browser's console, execute
diff --git a/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-5-update-meta.md b/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-5-update-meta.md
index 4fadd285f6942..9a5a8c8be78df 100644
--- a/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-5-update-meta.md
+++ b/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-5-update-meta.md
@@ -1,8 +1,8 @@
# Update the Meta Field When the Input's Content Changes
-The last step in the journey is to update the meta field when the input content changes. To do that, you'll use another utility from the `@wordpress/data` package, [withDispatch](/packages/data/README.md#withdispatch-mapdispatchtoprops-function-function).
+The last step in the journey is to update the meta field when the input content changes. To do that, you'll use another utility from the `@wordpress/data` package, [useDispatch](/packages/data/README.md#usedispatch). These utilities are also known as _hooks_.
-`withDispatch` works similarly to `withSelect`. It takes two functions, the first returns an object with data, and the second takes that data object as input and returns a new UI component. Let's see how to use it:
+The `useDispatch` takes store name as its only argument and returns methods that you can use to update the store.
```js
( function ( wp ) {
@@ -10,44 +10,27 @@ The last step in the journey is to update the meta field when the input content
var PluginSidebar = wp.editPost.PluginSidebar;
var el = wp.element.createElement;
var Text = wp.components.TextControl;
- var withSelect = wp.data.withSelect;
- var withDispatch = wp.data.withDispatch;
-
- var mapSelectToProps = function ( select ) {
- return {
- metaFieldValue: select( 'core/editor' ).getEditedPostAttribute(
- 'meta'
- )[ 'sidebar_plugin_meta_block_field' ],
- };
- };
-
- var mapDispatchToProps = function ( dispatch ) {
- return {
- setMetaFieldValue: function ( value ) {
- dispatch( 'core/editor' ).editPost( {
- meta: { sidebar_plugin_meta_block_field: value },
- } );
- },
- };
- };
+ var useSelect = wp.data.useSelect;
+ var useDispatch = wp.data.useDispatch;
var MetaBlockField = function ( props ) {
+ var metaFieldValue = useSelect( function ( select ) {
+ return select( 'core/editor' ).getEditedPostAttribute( 'meta' )[ 'sidebar_plugin_meta_block_field' ];
+ }, [] );
+
+ var editPost = useDispatch( 'core/editor' ).editPost;
+
return el( Text, {
label: 'Meta Block Field',
- value: props.metaFieldValue,
+ value: metaFieldValue,
onChange: function ( content ) {
- props.setMetaFieldValue( content );
+ editPost( {
+ meta: { sidebar_plugin_meta_block_field: content },
+ } );
},
} );
};
- var MetaBlockFieldWithData = withSelect( mapSelectToProps )(
- MetaBlockField
- );
- var MetaBlockFieldWithDataAndActions = withDispatch( mapDispatchToProps )(
- MetaBlockFieldWithData
- );
-
registerPlugin( 'my-plugin-sidebar', {
render: function () {
return el(
@@ -60,7 +43,7 @@ The last step in the journey is to update the meta field when the input content
el(
'div',
{ className: 'plugin-sidebar-content' },
- el( MetaBlockFieldWithDataAndActions )
+ el( MetaBlockField )
)
);
},
@@ -70,9 +53,8 @@ The last step in the journey is to update the meta field when the input content
Here's how it changed from the previous section:
-- Added a new `mapDispatchToProps` function that will be passed to `withDispatch`. It takes `dispatch` as input and returns an object containing functions to update the internal data structures of the editor. These functions are also known as _actions_.
-- By calling `setMetaFieldValue` every time the user types something within the input control, we're effectively updating the editor store on each key stroke.
-- The `props` argument to the `MetaBlockField` component contains now the data passed by `mapSelectToProps` and the actions passed by `mapDispatchToProps`.
+- The component now use `editPost` function returned by `useDispatch` hook. These functions are also known as _actions_.
+- By calling `editPost` every time the user types something within the input control, we're effectively updating the editor store on each key stroke.
Copy this new code to the JavaScript file, load the sidebar and see how the input value gets updated as you type. You may want to check that the internal data structures are updated as well. Type something in the input control, and execute the following instruction in your browser's console:
diff --git a/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-6-finishing-touches.md b/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-6-finishing-touches.md
deleted file mode 100644
index cd2d2f2d45c01..0000000000000
--- a/docs/how-to-guides/sidebar-tutorial/plugin-sidebar-6-finishing-touches.md
+++ /dev/null
@@ -1,199 +0,0 @@
-# Finishing Touches
-
-Your JavaScript code now works as expected, here are a few ways to simplify and make it easier to change in the future.
-
-The first step is to convert the functions `mapSelectToProps` and `mapDispatchToProps` to anonymous functions that get passed directly to `withSelect` and `withData`, respectively:
-
-```js
-( function ( wp ) {
- var registerPlugin = wp.plugins.registerPlugin;
- var PluginSidebar = wp.editPost.PluginSidebar;
- var el = wp.element.createElement;
- var Text = wp.components.TextControl;
- var withSelect = wp.data.withSelect;
- var withDispatch = wp.data.withDispatch;
-
- var MetaBlockField = function ( props ) {
- return el( Text, {
- label: 'Meta Block Field',
- value: props.metaFieldValue,
- onChange: function ( content ) {
- props.setMetaFieldValue( content );
- },
- } );
- };
-
- var MetaBlockFieldWithData = withSelect( function ( select ) {
- return {
- metaFieldValue: select( 'core/editor' ).getEditedPostAttribute(
- 'meta'
- )[ 'sidebar_plugin_meta_block_field' ],
- };
- } )( MetaBlockField );
-
- var MetaBlockFieldWithDataAndActions = withDispatch( function ( dispatch ) {
- return {
- setMetaFieldValue: function ( value ) {
- dispatch( 'core/editor' ).editPost( {
- meta: { sidebar_plugin_meta_block_field: value },
- } );
- },
- };
- } )( MetaBlockFieldWithData );
-
- registerPlugin( 'my-plugin-sidebar', {
- render: function () {
- return el(
- PluginSidebar,
- {
- name: 'my-plugin-sidebar',
- icon: 'admin-post',
- title: 'My plugin sidebar',
- },
- el(
- 'div',
- { className: 'plugin-sidebar-content' },
- el( MetaBlockFieldWithDataAndActions )
- )
- );
- },
- } );
-} )( window.wp );
-```
-
-Next, merge `MetaBlockField`, `MetaBlockFieldWithData`, and `MetaBlockFieldWithDataAndActions` into one function called `MetaBlockField` that gets passed to the `div` element. The `@wordpress/compose` package offers an utility to concatenate functions called `compose`. Don't forget adding `wp-compose` to the dependencies array in the PHP script.
-
-```js
-( function ( wp ) {
- var registerPlugin = wp.plugins.registerPlugin;
- var PluginSidebar = wp.editPost.PluginSidebar;
- var el = wp.element.createElement;
- var Text = wp.components.TextControl;
- var withSelect = wp.data.withSelect;
- var withDispatch = wp.data.withDispatch;
- var compose = wp.compose.compose;
-
- var MetaBlockField = compose(
- withDispatch( function ( dispatch ) {
- return {
- setMetaFieldValue: function ( value ) {
- dispatch( 'core/editor' ).editPost( {
- meta: { sidebar_plugin_meta_block_field: value },
- } );
- },
- };
- } ),
- withSelect( function ( select ) {
- return {
- metaFieldValue: select( 'core/editor' ).getEditedPostAttribute(
- 'meta'
- )[ 'sidebar_plugin_meta_block_field' ],
- };
- } )
- )( function ( props ) {
- return el( Text, {
- label: 'Meta Block Field',
- value: props.metaFieldValue,
- onChange: function ( content ) {
- props.setMetaFieldValue( content );
- },
- } );
- } );
-
- registerPlugin( 'my-plugin-sidebar', {
- render: function () {
- return el(
- PluginSidebar,
- {
- name: 'my-plugin-sidebar',
- icon: 'admin-post',
- title: 'My plugin sidebar',
- },
- el(
- 'div',
- { className: 'plugin-sidebar-content' },
- el( MetaBlockField )
- )
- );
- },
- } );
-} )( window.wp );
-```
-
-Finally, extract the meta field name (`sidebar_plugin_meta_block_field`) from the `withSelect` and `withDispatch` functions to a single place, so it's easier to change in the future. You can leverage the fact that `withSelect` and `withDispatch` first functions can take the props of the UI component they wrap as a second argument. For example:
-
-```js
-// ...
-var MetaBlockFieldWithData = withSelect( function ( select, props ) {
- console.log( props.metaFieldName );
-} )( MetaBlockField );
-
-// ...
-el( MetaBlockFieldWithData, {
- metaFieldName: 'sidebar_plugin_meta_block_field',
-} );
-// ...
-```
-
-Notice how the `metaFieldName` can be accessed within `withSelect`. Let's change the code to take advantage of that:
-
-```js
-( function ( wp ) {
- var registerPlugin = wp.plugins.registerPlugin;
- var PluginSidebar = wp.editPost.PluginSidebar;
- var el = wp.element.createElement;
- var Text = wp.components.TextControl;
- var withSelect = wp.data.withSelect;
- var withDispatch = wp.data.withDispatch;
- var compose = wp.compose.compose;
-
- var MetaBlockField = compose(
- withDispatch( function ( dispatch, props ) {
- return {
- setMetaFieldValue: function ( value ) {
- dispatch( 'core/editor' ).editPost( {
- meta: { [ props.fieldName ]: value },
- } );
- },
- };
- } ),
- withSelect( function ( select, props ) {
- return {
- metaFieldValue: select( 'core/editor' ).getEditedPostAttribute(
- 'meta'
- )[ props.fieldName ],
- };
- } )
- )( function ( props ) {
- return el( Text, {
- label: 'Meta Block Field',
- value: props.metaFieldValue,
- onChange: function ( content ) {
- props.setMetaFieldValue( content );
- },
- } );
- } );
-
- registerPlugin( 'my-plugin-sidebar', {
- render: function () {
- return el(
- PluginSidebar,
- {
- name: 'my-plugin-sidebar',
- icon: 'admin-post',
- title: 'My plugin sidebar',
- },
- el(
- 'div',
- { className: 'plugin-sidebar-content' },
- el( MetaBlockField, {
- fieldName: 'sidebar_plugin_meta_block_field',
- } )
- )
- );
- },
- } );
-} )( window.wp );
-```
-
-That's it. You have now a compact version of the original code. Go ahead and add more functionality to your plugin, review other tutorials, or create your next gig!
diff --git a/docs/how-to-guides/themes/create-block-theme.md b/docs/how-to-guides/themes/create-block-theme.md
index 72fea1cb8ec97..45df340c1e19d 100644
--- a/docs/how-to-guides/themes/create-block-theme.md
+++ b/docs/how-to-guides/themes/create-block-theme.md
@@ -628,7 +628,7 @@ To add custom font sizes, create a new section called `typography` under `settin
`fontSizes` is the equivalent of `add_theme_support( 'editor-font-sizes' )`.
```json
-"typograhy": {
+"typography": {
"fontSizes": [
]
}
@@ -641,7 +641,7 @@ The keys used by `fontSizes` are:
- `name` The visible name in the editor.
```json
-"typograhy": {
+"typography": {
"fontSizes": [
{
"slug": "normal",
diff --git a/docs/how-to-guides/themes/theme-json.md b/docs/how-to-guides/themes/theme-json.md
index 460a43ba9161e..6335a614f9b3c 100644
--- a/docs/how-to-guides/themes/theme-json.md
+++ b/docs/how-to-guides/themes/theme-json.md
@@ -222,13 +222,15 @@ The settings section has the following structure:
"customWidth": false
},
"color": {
+ "background": true,
"custom": true,
"customDuotone": true,
"customGradient": true,
"duotone": [],
"gradients": [],
"link": false,
- "palette": []
+ "palette": [],
+ "text": true
},
"custom": {},
"layout": {
@@ -615,7 +617,6 @@ Each block declares which style properties it exposes via the [block supports me
"text": "value"
},
"spacing": {
- "blockGap": "value",
"margin": {
"top": "value",
"right": "value",
diff --git a/docs/how-to-guides/widgets/legacy-widget-block.md b/docs/how-to-guides/widgets/legacy-widget-block.md
index 7e629d482688c..e349829acb25c 100644
--- a/docs/how-to-guides/widgets/legacy-widget-block.md
+++ b/docs/how-to-guides/widgets/legacy-widget-block.md
@@ -33,7 +33,7 @@ Note that all of the widget's event handlers are added in the `widget-added` cal
The Legacy Widget block will display a preview of the widget when the Legacy Widget block is not selected.
-A "No preview available." message is automatically shown by the Legacy Widget block when the widget's `widget()` function does not render anytihng or only renders empty HTML elements.
+A "No preview available." message is automatically shown by the Legacy Widget block when the widget's `widget()` function does not render anything or only renders empty HTML elements.
Widgets may take advantage of this by returning early from `widget()` when a preview should not be displayed.
diff --git a/docs/manifest.json b/docs/manifest.json
index e424b1381a3c6..a07a780786517 100644
--- a/docs/manifest.json
+++ b/docs/manifest.json
@@ -239,12 +239,6 @@
"markdown_source": "../docs/how-to-guides/sidebar-tutorial/plugin-sidebar-5-update-meta.md",
"parent": "plugin-sidebar-0"
},
- {
- "title": "Finishing Touches",
- "slug": "plugin-sidebar-6-finishing-touches",
- "markdown_source": "../docs/how-to-guides/sidebar-tutorial/plugin-sidebar-6-finishing-touches.md",
- "parent": "plugin-sidebar-0"
- },
{
"title": "Blocks",
"slug": "block-tutorial",
@@ -2021,6 +2015,12 @@
"markdown_source": "../docs/contributors/code/native-mobile.md",
"parent": "code"
},
+ {
+ "title": "React Native Integration Test Guide",
+ "slug": "native-mobile-integration-test-guide",
+ "markdown_source": "../docs/contributors/code/native-mobile-integration-test-guide.md",
+ "parent": "code"
+ },
{
"title": "Getting Started for the React Native based Mobile Gutenberg",
"slug": "getting-started-native-mobile",
diff --git a/docs/reference-guides/block-api/block-transforms.md b/docs/reference-guides/block-api/block-transforms.md
index 1078608345e52..d1de0e98fa12a 100644
--- a/docs/reference-guides/block-api/block-transforms.md
+++ b/docs/reference-guides/block-api/block-transforms.md
@@ -42,7 +42,7 @@ A transformation of type `block` is an object that takes the following parameter
- **type** _(string)_: the value `block`.
- **blocks** _(array)_: a list of known block types. It also accepts the wildcard value (`"*"`), meaning that the transform is available to _all_ block types (eg: all blocks can transform into `core/group`).
- **transform** _(function)_: a callback that receives the attributes and inner blocks of the block being processed. It should return a block object or an array of block objects.
-- **isMatch** _(function, optional)_: a callback that receives the block attributes and should return a boolean. Returning `false` from this function will prevent the transform from being available and displayed as an option to the user.
+- **isMatch** _(function, optional)_: a callback that receives the block attributes as the first argument and the block object as the second argument and should return a boolean. Returning `false` from this function will prevent the transform from being available and displayed as an option to the user.
- **isMultiBlock** _(boolean, optional)_: whether the transformation can be applied when multiple blocks are selected. If true, the `transform` function's first parameter will be an array containing each selected block's attributes, and the second an array of each selected block's inner blocks. False by default.
- **priority** _(number, optional)_: controls the priority with which a transformation is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://codex.wordpress.org/Plugin_API#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
diff --git a/docs/reference-guides/block-api/block-variations.md b/docs/reference-guides/block-api/block-variations.md
index 2c9e6b3bc6520..4aa2122dcfd76 100644
--- a/docs/reference-guides/block-api/block-variations.md
+++ b/docs/reference-guides/block-api/block-variations.md
@@ -45,7 +45,7 @@ An object describing a variation defined for the block type can contain the foll
- `example` (optional, type `Object`) – Example provides structured data for the block preview. You can set to `undefined` to disable the preview shown for the block type.
- `scope` (optional, type `WPBlockVariationScope[]`) - the list of scopes where the variation is applicable. When not provided, it defaults to `block` and `inserter`. Available options:
- `inserter` - Block Variation is shown on the inserter.
- - `block` - Used by blocks to filter specific block variations. Mostly used in Placeholder patterns like `Columns` block.
+ - `block` - Used by blocks to filter specific block variations. `Columns` and `Query Loop` blocks have such variations and are passed to the [experimental BlockVariationPicker](/packages/block-editor/src/components/block-variation-picker/README.md) component, which is handling the displaying of variations and the ability to select one from them.
- `transform` - Block Variation will be shown in the component for Block Variations transformations.
- `keywords` (optional, type `string[]`) - An array of terms (which can be translated) that help users discover the variation while searching.
- `isActive` (optional, type `Function|string[]`) - This can be a function or an array of block attributes. Function that accepts a block's attributes and the variation's attributes and determines if a variation is active. This function doesn't try to find a match dynamically based on all block's attributes, as in many cases some attributes are irrelevant. An example would be for `embed` block where we only care about `providerNameSlug` attribute's value. We can also use a `string[]` to tell which attributes should be compared as a shorthand. Each attributes will be matched and the variation will be active if all of them are matching.
diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md
index 3cc75b5048168..9f07302f001a8 100644
--- a/docs/reference-guides/data/data-core-block-editor.md
+++ b/docs/reference-guides/data/data-core-block-editor.md
@@ -281,12 +281,6 @@ Returns all block objects for the current post being edited as an array in
the order they appear in the post. Note that this will exclude child blocks
of nested inner block controllers.
-Note: It's important to memoize this selector to avoid return a new instance
-on each call. We use the block cache state for each top-level block of the
-given clientID. This way, the selector only refreshes on changes to blocks
-associated with the given entity, and does not refresh when changes are made
-to blocks which are part of different inner block controllers.
-
_Parameters_
- _state_ `Object`: Editor state.
@@ -1221,6 +1215,8 @@ _Parameters_
### receiveBlocks
+> **Deprecated**
+
Returns an action object used in signalling that blocks have been received.
Unlike resetBlocks, these should be appended to the existing known set, not
replacing.
diff --git a/docs/reference-guides/data/data-core-edit-post.md b/docs/reference-guides/data/data-core-edit-post.md
index 2348d6544020d..72a76d56fad15 100644
--- a/docs/reference-guides/data/data-core-edit-post.md
+++ b/docs/reference-guides/data/data-core-edit-post.md
@@ -6,6 +6,18 @@ Namespace: `core/edit-post`.
+### areMetaBoxesInitialized
+
+Returns true if meta boxes are initialized.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `boolean`: Whether meta boxes are initialized.
+
### getActiveGeneralSidebarName
Returns the current active general sidebar name, or null if there is no
@@ -351,6 +363,10 @@ _Returns_
- `Object`: Action object.
+### initializeMetaBoxes
+
+Initializes WordPress `postboxes` script and the logic for saving meta boxes.
+
### metaBoxUpdatesFailure
Returns an action object used to signal a failed meta box update.
@@ -502,16 +518,12 @@ _Returns_
### toggleFeature
-Returns an action object used to toggle a feature flag.
+Triggers an action used to toggle a feature flag.
_Parameters_
- _feature_ `string`: Feature name.
-_Returns_
-
-- `Object`: Action object.
-
### togglePinnedPluginItem
Triggers an action object used to toggle a plugin name flag.
diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md
index 7ad08fa7f9ff2..16f4d6305fecf 100644
--- a/docs/reference-guides/data/data-core.md
+++ b/docs/reference-guides/data/data-core.md
@@ -535,7 +535,7 @@ _Parameters_
- _recordId_ `string`: Record ID of the deleted entity.
- _query_ `?Object`: Special query parameters for the DELETE API call.
- _options_ `[Object]`: Delete options.
-- _options.\_\_unstableFetch_ `[Function]`: Internal use only. Function to call instead of `apiFetch()`. Must return a control descriptor.
+- _options.\_\_unstableFetch_ `[Function]`: Internal use only. Function to call instead of `apiFetch()`. Must return a promise.
### editEntityRecord
@@ -680,6 +680,10 @@ _Returns_
Action triggered to redo the last undoed
edit to an entity record, if any.
+_Returns_
+
+- `undefined`:
+
### saveEditedEntityRecord
Action triggered to save an entity record's edits.
@@ -702,11 +706,15 @@ _Parameters_
- _record_ `Object`: Record to be saved.
- _options_ `Object`: Saving options.
- _options.isAutosave_ `[boolean]`: Whether this is an autosave.
-- _options.\_\_unstableFetch_ `[Function]`: Internal use only. Function to call instead of `apiFetch()`. Must return a control descriptor.
+- _options.\_\_unstableFetch_ `[Function]`: Internal use only. Function to call instead of `apiFetch()`. Must return a promise.
### undo
Action triggered to undo the last edit to
an entity record, if any.
+_Returns_
+
+- `undefined`:
+
diff --git a/docs/toc.json b/docs/toc.json
index c8ce6140ef94f..875e514901517 100644
--- a/docs/toc.json
+++ b/docs/toc.json
@@ -98,9 +98,6 @@
},
{
"docs/how-to-guides/sidebar-tutorial/plugin-sidebar-5-update-meta.md": []
- },
- {
- "docs/how-to-guides/sidebar-tutorial/plugin-sidebar-6-finishing-touches.md": []
}
]
},
@@ -178,11 +175,13 @@
},
{ "docs/how-to-guides/accessibility.md": [] },
{ "docs/how-to-guides/internationalization.md": [] },
- { "docs/how-to-guides/widgets/README.md": [
- { "docs/how-to-guides/widgets/overview.md": [] },
- { "docs/how-to-guides/widgets/opting-out.md": [] },
- { "docs/how-to-guides/widgets/legacy-widget-block.md": [] }
- ] }
+ {
+ "docs/how-to-guides/widgets/README.md": [
+ { "docs/how-to-guides/widgets/overview.md": [] },
+ { "docs/how-to-guides/widgets/opting-out.md": [] },
+ { "docs/how-to-guides/widgets/legacy-widget-block.md": [] }
+ ]
+ }
]
},
{
@@ -318,6 +317,9 @@
{ "docs/contributors/code/managing-packages.md": [] },
{ "docs/contributors/code/release.md": [] },
{ "docs/contributors/code/native-mobile.md": [] },
+ {
+ "docs/contributors/code/native-mobile-integration-test-guide.md": []
+ },
{
"docs/contributors/code/getting-started-native-mobile.md": []
}
diff --git a/gutenberg.php b/gutenberg.php
index 63d4d1c4eb095..5e8552586f685 100644
--- a/gutenberg.php
+++ b/gutenberg.php
@@ -3,9 +3,9 @@
* Plugin Name: Gutenberg
* Plugin URI: https://github.com/WordPress/gutenberg
* Description: Printing since 1440. This is the development plugin for the new block editor in core.
- * Requires at least: 5.6
+ * Requires at least: 5.7
* Requires PHP: 5.6
- * Version: 11.3.0
+ * Version: 11.5.0-rc.1
* Author: Gutenberg Team
* Text Domain: gutenberg
*
@@ -26,7 +26,7 @@
function gutenberg_wordpress_version_notice() {
echo '
';
/* translators: %s: Minimum required version */
- printf( __( 'Gutenberg requires WordPress %s or later to function properly. Please upgrade WordPress before activating Gutenberg.', 'gutenberg' ), '5.6' );
+ printf( __( 'Gutenberg requires WordPress %s or later to function properly. Please upgrade WordPress before activating Gutenberg.', 'gutenberg' ), '5.7' );
echo '
-This component is currently used by the "Columns" block to display and choose the number and structure of columns. It is also used by the "Post Hierarchical Terms Block" block.
+The `BlockVariationPicker` component allows certain types of blocks to display their different variations, and to choose one of them. Variations provided are usually filtered by their inclusion of the `block` value in their `scope` attribute.
+
+This component is currently used by "Columns" and "Query Loop" blocks.
![Columns block variations](https://make.wordpress.org/core/files/2020/09/colums-block-variations.png)
@@ -18,33 +22,62 @@ This component is currently used by the "Columns" block to display and choose th
Renders the variations of a block.
```jsx
-import { BlockVariationPicker } from '@wordpress/block-editor';
-
-const MyBlockVariationPicker = () => (
-
-);
+import { useSelect } from '@wordpress/data';
+import {
+ __experimentalBlockVariationPicker as BlockVariationPicker,
+ store as blockEditorStore,
+} from '@wordpress/block-editor';
+
+const MyBlockVariationPicker = ( { blockName } ) => {
+ const variations = useSelect(
+ ( select ) => {
+ const { getBlockVariations } = select( blocksStore );
+ return getBlockVariations( blockName, 'block' );
+ },
+ [ blockName ]
+ );
+ return ;
+};
```
### Props
-#### label
-
-The label of each variation of the block.
+#### `label`
- Type: `String`
+- Required: No
+- Default: `Choose variation`
-#### instructions
+The label of each variation of the block.
-The instructions to choose a block variation.
+#### `instructions`
- Type: `String`
+- Required: No
+- Default: `Select a variation to start with.`
+
+The instructions to choose a block variation.
-#### variations
+#### `variations`
-- Type: `Array`
+- Type: `Array`
The different variations of the block.
+#### `onSelect`
+
+- Type: `Function`
+
+Callback called when a block variation is selected. It recieves the selected variation as a parameter.
+
+#### `icon`
+
+- Type: `Icon component`
+- Required: No
+- Default: `layout`
+
+Icon to be displayed at the top of the component before the `label`.
+
## 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/HEAD/packages/block-editor/src/components/provider/README.md) in the components tree.
diff --git a/packages/block-editor/src/components/block-variation-picker/style.native.scss b/packages/block-editor/src/components/block-variation-picker/style.native.scss
index cfee074a24a98..20b1297a593b1 100644
--- a/packages/block-editor/src/components/block-variation-picker/style.native.scss
+++ b/packages/block-editor/src/components/block-variation-picker/style.native.scss
@@ -17,6 +17,8 @@
.cancelButton {
color: $blue-wordpress;
font-size: 16px;
+ padding-left: $grid-unit-20;
+ padding-right: $grid-unit-20;
}
.cancelButtonDark {
@@ -25,4 +27,6 @@
.closeIcon {
color: $gray;
+ margin-left: $grid-unit-20;
+ padding: $grid-unit-20;
}
diff --git a/packages/block-editor/src/components/editor-styles/index.js b/packages/block-editor/src/components/editor-styles/index.js
index 4b0286d8eba71..c2c5f77ff600b 100644
--- a/packages/block-editor/src/components/editor-styles/index.js
+++ b/packages/block-editor/src/components/editor-styles/index.js
@@ -68,6 +68,7 @@ export default function EditorStyles( { styles } ) {
() => transformStyles( styles, EDITOR_STYLES_SELECTOR ),
[ styles ]
);
+
return (
<>
{ /* Use an empty style element to have a document reference,
diff --git a/packages/block-editor/src/components/font-appearance-control/index.js b/packages/block-editor/src/components/font-appearance-control/index.js
index 224f9361d32f2..711ded6b70835 100644
--- a/packages/block-editor/src/components/font-appearance-control/index.js
+++ b/packages/block-editor/src/components/font-appearance-control/index.js
@@ -163,12 +163,42 @@ export default function FontAppearanceControl( props ) {
return __( 'Appearance' );
};
+ // Adjusts screen reader description based on styles or weights.
+ const getDescribedBy = () => {
+ if ( ! currentSelection ) {
+ return __( 'No selected font appearance' );
+ }
+
+ if ( ! hasFontStyles ) {
+ return sprintf(
+ // translators: %s: Currently selected font weight.
+ __( 'Currently selected font weight: %s' ),
+ currentSelection.name
+ );
+ }
+
+ if ( ! hasFontWeights ) {
+ return sprintf(
+ // translators: %s: Currently selected font style.
+ __( 'Currently selected font style: %s' ),
+ currentSelection.name
+ );
+ }
+
+ return sprintf(
+ // translators: %s: Currently selected font appearance.
+ __( 'Currently selected font appearance: %s' ),
+ currentSelection.name
+ );
+ };
+
return (
-
+
+ { ! isURLSet && (
+
+ ) }
+ { isURLSet && (
+
+ ) }
+
+ { isSelected && ( isEditingURL || isURLSet ) && (
+ {
+ setIsEditingURL( false );
+ richTextRef.current?.focus();
+ } }
+ anchorRef={ ref?.current }
+ focusOnMount={ isEditingURL ? 'firstElement' : false }
+ >
+ {
+ setAttributes( { url: newURL } );
+
+ if ( opensInNewTab !== newOpensInNewTab ) {
+ onToggleOpenInNewTab( newOpensInNewTab );
+ }
+ } }
+ onRemove={ () => {
+ unlink();
+ richTextRef.current?.focus();
+ } }
+ forceIsEditingLink={ isEditingURL }
+ />
+
+ ) }
-
+
-
+
>
);
}
diff --git a/packages/block-library/src/button/edit.native.js b/packages/block-library/src/button/edit.native.js
index a06f5d06adccb..ec9741fe5add4 100644
--- a/packages/block-library/src/button/edit.native.js
+++ b/packages/block-library/src/button/edit.native.js
@@ -6,7 +6,7 @@ import { View, AccessibilityInfo, Platform, Text } from 'react-native';
* WordPress dependencies
*/
import { withInstanceId, compose } from '@wordpress/compose';
-import { __ } from '@wordpress/i18n';
+import { __, _x } from '@wordpress/i18n';
import {
RichText,
InspectorControls,
@@ -136,7 +136,10 @@ class ButtonEdit extends Component {
},
linkRel: {
label: __( 'Link Rel' ),
- placeholder: __( 'None' ),
+ placeholder: _x(
+ 'None',
+ 'Link rel attribute value placeholder'
+ ),
},
};
diff --git a/packages/block-library/src/button/style.scss b/packages/block-library/src/button/style.scss
index fb85a6cdd6ce2..4b778ed3be541 100644
--- a/packages/block-library/src/button/style.scss
+++ b/packages/block-library/src/button/style.scss
@@ -14,7 +14,7 @@ $blocks-block__margin: 0.5em;
padding: calc(0.667em + 2px) calc(1.333em + 2px); // The extra 2px are added to size solids the same as the outline versions.
text-align: center;
text-decoration: none;
- overflow-wrap: break-word;
+ word-break: break-word; // overflow-wrap doesn't work well if a link is wrapped in the div, so use word-break here.
box-sizing: border-box;
&:hover,
diff --git a/packages/block-library/src/buttons/block.json b/packages/block-library/src/buttons/block.json
index 74eed0a4a0a54..dcd9519af1a10 100644
--- a/packages/block-library/src/buttons/block.json
+++ b/packages/block-library/src/buttons/block.json
@@ -17,7 +17,8 @@
},
"supports": {
"anchor": true,
- "align": [ "wide", "full" ]
+ "align": [ "wide", "full" ],
+ "__experimentalExposeControlsToChildren": true
},
"editorStyle": "wp-block-buttons-editor",
"style": "wp-block-buttons"
diff --git a/packages/block-library/src/buttons/edit.js b/packages/block-library/src/buttons/edit.js
index 424e305bd585e..8cf3c31db5062 100644
--- a/packages/block-library/src/buttons/edit.js
+++ b/packages/block-library/src/buttons/edit.js
@@ -70,7 +70,7 @@ function ButtonsEdit( {
return (
<>
-
+ 1 ? 'horizontal' : undefined
}
- horizontal={ true }
+ horizontal={ columnsInRow > 1 }
allowedBlocks={ ALLOWED_BLOCKS }
contentResizeMode="stretch"
onAddBlock={ onAddBlock }
diff --git a/packages/block-library/src/columns/editor.scss b/packages/block-library/src/columns/editor.scss
index bb84ad88a6623..de64661b46b4b 100644
--- a/packages/block-library/src/columns/editor.scss
+++ b/packages/block-library/src/columns/editor.scss
@@ -12,14 +12,14 @@
@include break-small() {
.editor-styles-wrapper
.block-editor-block-list__block.wp-block-column:nth-child(even) {
- margin-left: $grid-unit-20 * 2;
+ margin-left: var(--wp--style--block-gap, 2em);
}
}
@include break-medium() {
.editor-styles-wrapper
.block-editor-block-list__block.wp-block-column:not(:first-child) {
- margin-left: $grid-unit-20 * 2;
+ margin-left: var(--wp--style--block-gap, 2em);
}
}
diff --git a/packages/block-library/src/columns/style.scss b/packages/block-library/src/columns/style.scss
index aba4c99297a19..acd1d713385bd 100644
--- a/packages/block-library/src/columns/style.scss
+++ b/packages/block-library/src/columns/style.scss
@@ -43,14 +43,14 @@
// As with mobile styles, this must be important since the Column
// assigns its own width as an inline style, which should take effect
// starting at `break-medium`.
- flex-basis: calc(50% - 1em) !important;
+ flex-basis: calc(50% - calc(var(--wp--style--block-gap, 2em) / 2)) !important;
flex-grow: 0;
}
// Add space between the multiple columns. Themes can customize this if they wish to work differently.
// Only apply this beyond the mobile breakpoint, as there's only a single column on mobile.
&:nth-child(even) {
- margin-left: 2em;
+ margin-left: var(--wp--style--block-gap, 2em);
}
}
@@ -74,7 +74,7 @@
// When columns are in a single row, add space before all except the first.
&:not(:first-child) {
- margin-left: 2em;
+ margin-left: var(--wp--style--block-gap, 2em);
}
}
}
@@ -95,7 +95,7 @@
// When columns are in a single row, add space before all except the first.
&:not(:first-child) {
- margin-left: 2em;
+ margin-left: var(--wp--style--block-gap, 2em);
}
}
}
diff --git a/packages/block-library/src/common.scss b/packages/block-library/src/common.scss
index 6cf9854943376..de0dacc67815e 100644
--- a/packages/block-library/src/common.scss
+++ b/packages/block-library/src/common.scss
@@ -3,15 +3,9 @@
// the colors override the added specificity by link states such as :hover.
:root {
- // Background colors.
- @include background-colors();
-
- // Foreground colors.
- @include foreground-colors();
-
- // Gradients
- @include gradient-colors();
-
+ @include background-colors-deprecated();
+ @include foreground-colors-deprecated();
+ @include gradient-colors-deprecated();
}
// Font sizes.
diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss
index 0870f1b38b0fe..b1919397804a2 100644
--- a/packages/block-library/src/editor.scss
+++ b/packages/block-library/src/editor.scss
@@ -11,7 +11,6 @@
@import "./freeform/editor.scss";
@import "./gallery/editor.scss";
@import "./group/editor.scss";
-@import "./heading/editor.scss";
@import "./html/editor.scss";
@import "./image/editor.scss";
@import "./latest-posts/editor.scss";
@@ -49,14 +48,9 @@
@import "./term-description/editor.scss";
:root .editor-styles-wrapper {
- // Background colors.
- @include background-colors();
-
- // Foreground colors.
- @include foreground-colors();
-
- // Gradients
- @include gradient-colors();
+ @include background-colors-deprecated();
+ @include foreground-colors-deprecated();
+ @include gradient-colors-deprecated();
}
// Font sizes.
diff --git a/packages/block-library/src/embed/edit.native.js b/packages/block-library/src/embed/edit.native.js
index 623f08752e56d..ac9e1f372be02 100644
--- a/packages/block-library/src/embed/edit.native.js
+++ b/packages/block-library/src/embed/edit.native.js
@@ -32,9 +32,13 @@ import {
import { store as coreStore } from '@wordpress/core-data';
import { View } from '@wordpress/primitives';
+// The inline preview feature will be released progressible, for this reason
+// the embed will only be considered previewable for the following providers list.
+const PREVIEWABLE_PROVIDERS = [ 'youtube', 'twitter' ];
+
const EmbedEdit = ( props ) => {
const {
- attributes: { providerNameSlug, previewable, responsive, url },
+ attributes: { align, providerNameSlug, previewable, responsive, url },
attributes,
isSelected,
onReplace,
@@ -207,6 +211,11 @@ const EmbedEdit = ( props ) => {
} = getMergedAttributes();
const className = classnames( classFromPreview, props.className );
+ const isProviderPreviewable =
+ PREVIEWABLE_PROVIDERS.includes( providerNameSlug ) ||
+ // For WordPress embeds, we enable the inline preview for all its providers.
+ 'wp-embed' === type;
+
return (
<>
{ showEmbedPlaceholder ? (
@@ -234,6 +243,7 @@ const EmbedEdit = ( props ) => {
/>
{
label={ title }
onFocus={ onFocus }
preview={ preview }
- previewable={ previewable }
+ previewable={ previewable && isProviderPreviewable }
type={ type }
url={ url }
/>
diff --git a/packages/block-library/src/embed/embed-no-preview.native.js b/packages/block-library/src/embed/embed-no-preview.native.js
index cd0af7b730851..c76ea855eff5f 100644
--- a/packages/block-library/src/embed/embed-no-preview.native.js
+++ b/packages/block-library/src/embed/embed-no-preview.native.js
@@ -8,7 +8,7 @@ import { TouchableOpacity, TouchableWithoutFeedback, Text } from 'react-native';
*/
import { View } from '@wordpress/primitives';
-import { __ } from '@wordpress/i18n';
+import { __, sprintf } from '@wordpress/i18n';
import { useRef, useState } from '@wordpress/element';
import { usePreferredColorSchemeStyle } from '@wordpress/compose';
import { requestPreview } from '@wordpress/react-native-bridge';
@@ -73,11 +73,19 @@ const EmbedNoPreview = ( { label, icon, isSelected, onPress } ) => {
postType === 'page' ? __( 'Preview page' ) : __( 'Preview post' );
const comingSoonDescription =
postType === 'page'
- ? __(
- 'We’re working hard on adding support for embed previews. In the meantime, you can preview the embedded content on the page.'
+ ? sprintf(
+ // translators: %s: embed block variant's label e.g: "Twitter".
+ __(
+ 'We’re working hard on adding support for %s previews. In the meantime, you can preview the embedded content on the page.'
+ ),
+ label
)
- : __(
- 'We’re working hard on adding support for embed previews. In the meantime, you can preview the embedded content on the post.'
+ : sprintf(
+ // translators: %s: embed block variant's label e.g: "Twitter".
+ __(
+ 'We’re working hard on adding support for %s previews. In the meantime, you can preview the embedded content on the post.'
+ ),
+ label
);
function onOpenSheet() {
@@ -118,7 +126,11 @@ const EmbedNoPreview = ( { label, icon, isSelected, onPress } ) => {
{ label }
- { __( 'Embed previews not yet available' ) }
+ { sprintf(
+ // translators: %s: embed block variant's label e.g: "Twitter".
+ __( '%s previews not yet available' ),
+ label
+ ) }
{ previewButtonText.toUpperCase() }
@@ -154,7 +166,11 @@ const EmbedNoPreview = ( { label, icon, isSelected, onPress } ) => {
/>
- { __( 'Embed block previews are coming soon' ) }
+ { sprintf(
+ // translators: %s: embed block variant's label e.g: "Twitter".
+ __( '%s block previews are coming soon' ),
+ label
+ ) }
{ comingSoonDescription }
diff --git a/packages/block-library/src/embed/embed-preview.native.js b/packages/block-library/src/embed/embed-preview.native.js
index 2f0cf949d4d0f..0beafe458ccca 100644
--- a/packages/block-library/src/embed/embed-preview.native.js
+++ b/packages/block-library/src/embed/embed-preview.native.js
@@ -20,8 +20,11 @@ import { SandBox } from '@wordpress/components';
*/
import { getPhotoHtml } from './util';
import EmbedNoPreview from './embed-no-preview';
+import WpEmbedPreview from './wp-embed-preview';
+import styles from './styles.scss';
const EmbedPreview = ( {
+ align,
className,
clientId,
icon,
@@ -36,6 +39,12 @@ const EmbedPreview = ( {
} ) => {
const [ isCaptionSelected, setIsCaptionSelected ] = useState( false );
+ const wrapperStyle = styles[ 'embed-preview__wrapper' ];
+ const wrapperAlignStyle =
+ styles[ `embed-preview__wrapper--align-${ align }` ];
+ const sandboxAlignStyle =
+ styles[ `embed-preview__sandbox--align-${ align }` ];
+
function accessibilityLabelCreator( caption ) {
return isEmpty( caption )
? /* translators: accessibility text. Empty Embed caption. */
@@ -77,33 +86,35 @@ const EmbedPreview = ( {
'wp-block-embed__wrapper'
);
- const embedWrapper =
- /* We should render here: */
- 'wp-embed' === type ? null : (
- <>
- {
- if ( onFocus ) {
- onFocus();
- }
- if ( isCaptionSelected ) {
- setIsCaptionSelected( false );
- }
- } }
+ const PreviewContent = 'wp-embed' === type ? WpEmbedPreview : SandBox;
+ const embedWrapper = (
+ <>
+ {
+ if ( onFocus ) {
+ onFocus();
+ }
+ if ( isCaptionSelected ) {
+ setIsCaptionSelected( false );
+ }
+ } }
+ >
+
-
-
-
-
- >
- );
-
+
+
+
+ >
+ );
return (
- {
- // eslint-disable-next-line no-undef
- __DEV__ && previewable ? (
- embedWrapper
- ) : (
- setIsCaptionSelected( false ) }
- />
- )
- }
+ { previewable ? (
+ embedWrapper
+ ) : (
+ setIsCaptionSelected( false ) }
+ />
+ ) }
! attribute
+ ) ||
+ message !== 'height'
+ ) {
+ return;
+ }
+
+ document
+ .querySelectorAll( 'iframe[data-secret="' + secret + '"' )
+ .forEach( ( iframe ) => {
+ if ( +iframe.height !== value ) {
+ iframe.height = value;
+ }
+ } );
+
+ // The function postMessage is exposed by the react-native-webview library
+ // to communicate between React Native and the WebView, in this case,
+ // we use it for notifying resize changes.
+ window.ReactNativeWebView.postMessage(JSON.stringify( {
+ action: 'resize',
+ height: value,
+ }));
+ }
+
+ window.addEventListener( 'message', sendResize );
+} )();`;
+
+function WpEmbedPreview( { html, ...rest } ) {
+ const wpEmbedHtml = useMemo( () => {
+ const doc = new window.DOMParser().parseFromString( html, 'text/html' );
+ const iframe = doc.querySelector( 'iframe' );
+
+ if ( iframe ) {
+ iframe.removeAttribute( 'style' );
+ }
+
+ const blockQuote = doc.querySelector( 'blockquote' );
+
+ if ( blockQuote ) {
+ blockQuote.innerHTML = '';
+ }
+
+ return doc.body.innerHTML;
+ }, [ html ] );
+
+ return (
+
+ );
+}
+
+export default memo( WpEmbedPreview );
diff --git a/packages/block-library/src/file/test/__snapshots__/edit.native.js.snap b/packages/block-library/src/file/test/__snapshots__/edit.native.js.snap
index 36a2e8b87915d..440d991192d16 100644
--- a/packages/block-library/src/file/test/__snapshots__/edit.native.js.snap
+++ b/packages/block-library/src/file/test/__snapshots__/edit.native.js.snap
@@ -61,6 +61,7 @@ exports[`File block renders file error state without crashing 1`] = `
disableEditingMenu={false}
focusable={true}
fontFamily="serif"
+ fontSize={16}
isMultiline={false}
maxImagesWidth={200}
onBackspace={[Function]}
@@ -150,6 +151,7 @@ exports[`File block renders file error state without crashing 1`] = `
disableEditingMenu={false}
focusable={true}
fontFamily="serif"
+ fontSize={16}
isMultiline={false}
maxImagesWidth={200}
minWidth={40}
@@ -259,6 +261,7 @@ exports[`File block renders file without crashing 1`] = `
disableEditingMenu={false}
focusable={true}
fontFamily="serif"
+ fontSize={16}
isMultiline={false}
maxImagesWidth={200}
onBackspace={[Function]}
@@ -330,6 +333,7 @@ exports[`File block renders file without crashing 1`] = `
disableEditingMenu={false}
focusable={true}
fontFamily="serif"
+ fontSize={16}
isMultiline={false}
maxImagesWidth={200}
minWidth={40}
diff --git a/packages/block-library/src/file/transforms.js b/packages/block-library/src/file/transforms.js
index 30e9808cb2525..3f96667b14745 100644
--- a/packages/block-library/src/file/transforms.js
+++ b/packages/block-library/src/file/transforms.js
@@ -10,6 +10,7 @@ import { createBlobURL } from '@wordpress/blob';
import { createBlock } from '@wordpress/blocks';
import { select } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
+import { getFilename } from '@wordpress/url';
const transforms = {
from: [
@@ -72,7 +73,8 @@ const transforms = {
transform: ( attributes ) => {
return createBlock( 'core/file', {
href: attributes.url,
- fileName: attributes.caption,
+ fileName:
+ attributes.caption || getFilename( attributes.url ),
textLinkHref: attributes.url,
id: attributes.id,
anchor: attributes.anchor,
diff --git a/packages/block-library/src/gallery/deprecated.scss b/packages/block-library/src/gallery/deprecated.scss
index c72fecd994fde..e0503e991e2b3 100644
--- a/packages/block-library/src/gallery/deprecated.scss
+++ b/packages/block-library/src/gallery/deprecated.scss
@@ -29,27 +29,16 @@
figure {
margin: 0;
height: 100%;
-
- // IE doesn't support flex so omit that.
- @supports (position: sticky) {
- display: flex;
- align-items: flex-end;
- justify-content: flex-start;
- }
+ display: flex;
+ align-items: flex-end;
+ justify-content: flex-start;
}
img {
display: block;
max-width: 100%;
height: auto;
-
- // IE doesn't handle cropping, so we need an explicit width here.
- width: 100%;
-
- // IE11 doesn't read rules inside this query. They are applied only to modern browsers.
- @supports (position: sticky) {
- width: auto;
- }
+ width: auto;
}
figcaption {
@@ -81,16 +70,9 @@
&.is-cropped .blocks-gallery-item {
a,
img {
- // IE11 doesn't support object-fit, so just make sure images aren't skewed.
- // The following rules are for all browsers.
- width: 100%;
-
- // IE11 doesn't read rules inside this query. They are applied only to modern browsers.
- @supports (position: sticky) {
- height: 100%;
- flex: 1;
- object-fit: cover;
- }
+ height: 100%;
+ flex: 1;
+ object-fit: cover;
}
}
diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js
index 3a1fa9c990b95..ec4f274751580 100644
--- a/packages/block-library/src/gallery/edit.js
+++ b/packages/block-library/src/gallery/edit.js
@@ -24,7 +24,7 @@ import {
useBlockProps,
} from '@wordpress/block-editor';
import { Platform, useEffect, useMemo } from '@wordpress/element';
-import { __, sprintf } from '@wordpress/i18n';
+import { __, _x, sprintf } from '@wordpress/i18n';
import { useSelect, useDispatch } from '@wordpress/data';
import { withViewportMatch } from '@wordpress/viewport';
import { View } from '@wordpress/primitives';
@@ -57,7 +57,10 @@ const MAX_COLUMNS = 8;
const linkOptions = [
{ value: LINK_DESTINATION_ATTACHMENT, label: __( 'Attachment Page' ) },
{ value: LINK_DESTINATION_MEDIA, label: __( 'Media File' ) },
- { value: LINK_DESTINATION_NONE, label: __( 'None' ) },
+ {
+ value: LINK_DESTINATION_NONE,
+ label: _x( 'None', 'Media item link option' ),
+ },
];
const ALLOWED_MEDIA_TYPES = [ 'image' ];
diff --git a/packages/block-library/src/gallery/editor.scss b/packages/block-library/src/gallery/editor.scss
index 32b2b39405cf8..47ebb1bdaa1e8 100644
--- a/packages/block-library/src/gallery/editor.scss
+++ b/packages/block-library/src/gallery/editor.scss
@@ -16,9 +16,24 @@ figure.wp-block-gallery {
flex: 0 0 100%;
}
- .components-form-file-upload {
+ > .components-form-file-upload {
flex-basis: 100%;
}
+
+ .wp-block-image {
+ .components-notice.is-error {
+ display: block;
+ }
+ .components-notice__content {
+ margin: 4px 0;
+ }
+ .components-notice__dismiss {
+ position: absolute;
+ top: 0;
+ right: 5px;
+ }
+ }
+
// @todo: this deserves a refactor, by being moved to the toolbar.
.block-editor-media-placeholder.is-appender {
.components-placeholder__label {
@@ -30,7 +45,6 @@ figure.wp-block-gallery {
}
.block-editor-media-placeholder {
margin: 0;
- height: 100%;
&::before {
box-shadow: 0 0 0 $border-width $white inset, 0 0 0 3px var(--wp-admin-theme-color) inset;
diff --git a/packages/block-library/src/gallery/save.js b/packages/block-library/src/gallery/save.js
index bb1fa63a1ba59..77afff7f27984 100644
--- a/packages/block-library/src/gallery/save.js
+++ b/packages/block-library/src/gallery/save.js
@@ -20,7 +20,7 @@ export default function saveWithInnerBlocks( { attributes } ) {
const { caption, columns, imageCrop } = attributes;
- const className = classnames( 'blocks-gallery-grid', 'has-nested-images', {
+ const className = classnames( 'has-nested-images', {
[ `columns-${ columns }` ]: columns !== undefined,
[ `columns-default` ]: columns === undefined,
'is-cropped': imageCrop,
diff --git a/packages/block-library/src/gallery/style.scss b/packages/block-library/src/gallery/style.scss
index e1e8300936b60..df7cf0634405e 100644
--- a/packages/block-library/src/gallery/style.scss
+++ b/packages/block-library/src/gallery/style.scss
@@ -2,7 +2,7 @@
@import "./deprecated.scss";
// Styles for current version of gallery block.
-.wp-block-gallery.blocks-gallery-grid.has-nested-images {
+.wp-block-gallery.has-nested-images {
display: flex;
flex-wrap: wrap;
// Need bogus :not(#individual-image) to override long :not()
@@ -29,33 +29,20 @@
position: relative;
margin-top: auto;
margin-bottom: auto;
- // IE11 doesn't like the "flex-direction: column;" here.
- @supports ( position: sticky ) {
- flex-direction: column;
- }
+ flex-direction: column;
> div,
> a {
margin: 0;
-
- // Avoid applying flex styles to IE11.
- @supports ( position: sticky ) {
- flex-direction: column;
- flex-grow: 1;
- }
+ flex-direction: column;
+ flex-grow: 1;
}
img {
display: block;
height: auto;
max-width: 100%;
- width: 100%;
-
- // IE doesn't handle cropping, so we need an explicit width here.
- // IE11 doesn't read rules inside this query. They are applied only to modern browsers.
- @supports ( position: sticky ) {
- width: auto;
- }
+ width: auto;
}
figcaption {
@@ -65,12 +52,13 @@
font-size: $default-font-size;
left: 0;
margin-bottom: 0;
- max-height: 100%;
+ max-height: 60%;
overflow: auto;
- padding: 40px 10px 9px;
+ padding: 0 8px 8px;
position: absolute;
text-align: center;
width: 100%;
+ box-sizing: border-box;
img {
display: inline;
@@ -80,22 +68,15 @@
&.is-style-rounded {
> div,
> a {
- // Not supported in IE11.
- @supports ( position: sticky ) {
- flex: 1 1 auto;
- }
+ flex: 1 1 auto;
}
figcaption {
+ flex: initial;
background: none;
- // Not supported in IE11.
- @supports ( position: sticky ) {
- flex: initial;
- background: none;
- color: inherit;
- margin: 0;
- padding: 10px 10px 9px;
- position: relative;
- }
+ color: inherit;
+ margin: 0;
+ padding: 10px 10px 9px;
+ position: relative;
}
}
}
@@ -127,24 +108,15 @@
align-self: inherit;
> div:not(.components-drop-zone),
> a {
- display: block; // Thanks to IE11 not supporting object-fit fall back to display: block.
-
- // Without IE11 object-fit support "display: flex;" here causes distortion of aspect ratio.
- @supports ( position: sticky ) {
- display: flex;
- }
+ display: flex;
}
a,
img {
width: 100%;
-
- // IE11 doesn't read rules inside this query. They are applied only to modern browsers.
- @supports ( position: sticky ) {
- flex: 1 0 0%;
- height: 100%;
- object-fit: cover;
- }
+ flex: 1 0 0%;
+ height: 100%;
+ object-fit: cover;
}
}
diff --git a/packages/block-library/src/gallery/use-get-media.js b/packages/block-library/src/gallery/use-get-media.js
index 597b112a8af3d..2d70119e4aa22 100644
--- a/packages/block-library/src/gallery/use-get-media.js
+++ b/packages/block-library/src/gallery/use-get-media.js
@@ -5,23 +5,26 @@ import { useState } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
+/**
+ * Retrieves the extended media info for each gallery image from the store. This is used to
+ * determine which image size options are available for the current gallery.
+ *
+ * @param {Array} innerBlockImages An array of the innerBlock images currently in the gallery.
+ *
+ * @return {Array} An array of media info options for each gallery image.
+ */
export default function useGetMedia( innerBlockImages ) {
const [ currentImageMedia, setCurrentImageMedia ] = useState( [] );
const imageMedia = useSelect(
( select ) => {
- if (
- ! innerBlockImages?.length ||
- innerBlockImages.some(
- ( imageBlock ) => ! imageBlock.attributes.id
- )
- ) {
+ if ( ! innerBlockImages?.length ) {
return currentImageMedia;
}
- const imageIds = innerBlockImages.map(
- ( imageBlock ) => imageBlock.attributes.id
- );
+ const imageIds = innerBlockImages
+ .map( ( imageBlock ) => imageBlock.attributes.id )
+ .filter( ( id ) => id !== undefined );
if ( imageIds.length === 0 ) {
return currentImageMedia;
diff --git a/packages/block-library/src/gallery/use-get-new-images.js b/packages/block-library/src/gallery/use-get-new-images.js
index 67578a5cb9941..056cf1d2ff6ba 100644
--- a/packages/block-library/src/gallery/use-get-new-images.js
+++ b/packages/block-library/src/gallery/use-get-new-images.js
@@ -3,6 +3,16 @@
*/
import { useMemo, useState } from '@wordpress/element';
+/**
+ * Keeps track of images already in the gallery to allow new innerBlocks to be identified. This
+ * is required so default gallery attributes can be applied without overwriting any custom
+ * attributes applied to existing images.
+ *
+ * @param {Array} images Basic image block data taken from current gallery innerBlock
+ * @param {Array} imageData The related image data for each of the current gallery images.
+ *
+ * @return {Array} An array of any new images that have been added to the gallery.
+ */
export default function useGetNewImages( images, imageData ) {
const [ currentImages, setCurrentImages ] = useState( [] );
diff --git a/packages/block-library/src/gallery/use-image-sizes.js b/packages/block-library/src/gallery/use-image-sizes.js
index 5b406adab4cc9..877bacb67dd13 100644
--- a/packages/block-library/src/gallery/use-image-sizes.js
+++ b/packages/block-library/src/gallery/use-image-sizes.js
@@ -8,6 +8,16 @@ import { get, some } from 'lodash';
*/
import { useMemo } from '@wordpress/element';
+/**
+ * Calculates the image sizes that are avaible for the current gallery images in order to
+ * populate the 'Image size' selector.
+ *
+ * @param {Array} images Basic image block data taken from current gallery innerBlock
+ * @param {boolean} isSelected Is the block currently selected in the editor.
+ * @param {Function} getSettings Block editor store selector.
+ *
+ * @return {Array} An array of image size options.
+ */
export default function useImageSizes( images, isSelected, getSettings ) {
return useMemo( () => getImageSizing(), [ images, isSelected ] );
diff --git a/packages/block-library/src/gallery/use-short-code-transform.js b/packages/block-library/src/gallery/use-short-code-transform.js
index 3843df9d5a642..bc25111910408 100644
--- a/packages/block-library/src/gallery/use-short-code-transform.js
+++ b/packages/block-library/src/gallery/use-short-code-transform.js
@@ -9,6 +9,14 @@ import { every } from 'lodash';
import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
+/**
+ * Shortcode transforms don't currently have a tranform method and so can't use a selector to
+ * retrieve the data for each image being transformer, so this selector handle this post transformation.
+ *
+ * @param {Array} shortCodeTransforms An array of image data passed from the shortcode transform.
+ *
+ * @return {Array} An array of extended image data objects for each of the shortcode transform images.
+ */
export default function useShortCodeTransform( shortCodeTransforms ) {
const newImageData = useSelect(
( select ) => {
diff --git a/packages/block-library/src/gallery/v1/tiles.native.js b/packages/block-library/src/gallery/v1/tiles.native.js
index c5ce52b4ba24b..30126ce872593 100644
--- a/packages/block-library/src/gallery/v1/tiles.native.js
+++ b/packages/block-library/src/gallery/v1/tiles.native.js
@@ -23,7 +23,8 @@ function Tiles( props ) {
const lastRow = Math.floor( lastTile / columns );
const wrappedChildren = Children.map( children, ( child, index ) => {
- /** Since we don't have `calc()`, we must calculate our spacings here in
+ /**
+ * Since we don't have `calc()`, we must calculate our spacings here in
* order to preserve even spacing between tiles and equal width for tiles
* in a given row.
*
diff --git a/packages/block-library/src/group/edit.js b/packages/block-library/src/group/edit.js
index 5628ea0105ce8..f30a7482bc3d8 100644
--- a/packages/block-library/src/group/edit.js
+++ b/packages/block-library/src/group/edit.js
@@ -5,7 +5,7 @@ import { useSelect } from '@wordpress/data';
import {
InnerBlocks,
useBlockProps,
- InspectorAdvancedControls,
+ InspectorControls,
__experimentalUseInnerBlocksProps as useInnerBlocksProps,
useSetting,
store as blockEditorStore,
@@ -28,10 +28,12 @@ function GroupEdit( { attributes, setAttributes, clientId } ) {
const defaultLayout = useSetting( 'layout' ) || {};
const { tagName: TagName = 'div', templateLock, layout = {} } = attributes;
const usedLayout = !! layout && layout.inherit ? defaultLayout : layout;
+ const { type = 'default' } = usedLayout;
+ const layoutSupportEnabled = themeSupportsLayout || type !== 'default';
const blockProps = useBlockProps();
const innerBlocksProps = useInnerBlocksProps(
- themeSupportsLayout
+ layoutSupportEnabled
? blockProps
: { className: 'wp-block-group__inner-container' },
{
@@ -39,13 +41,13 @@ function GroupEdit( { attributes, setAttributes, clientId } ) {
renderAppender: hasInnerBlocks
? undefined
: InnerBlocks.ButtonBlockAppender,
- __experimentalLayout: themeSupportsLayout ? usedLayout : undefined,
+ __experimentalLayout: layoutSupportEnabled ? usedLayout : undefined,
}
);
return (
<>
-
+
-
- { themeSupportsLayout && }
+
+ { layoutSupportEnabled && }
{ /* Ideally this is not needed but it's there for backward compatibility reason
to keep this div for themes that might rely on its presence */ }
- { ! themeSupportsLayout && (
+ { ! layoutSupportEnabled && (
diff --git a/packages/block-library/src/group/index.js b/packages/block-library/src/group/index.js
index dac9a09b3cb1f..e3b9d887d95f8 100644
--- a/packages/block-library/src/group/index.js
+++ b/packages/block-library/src/group/index.js
@@ -12,6 +12,7 @@ import deprecated from './deprecated';
import edit from './edit';
import metadata from './block.json';
import save from './save';
+import variations from './variations';
const { name } = metadata;
@@ -135,4 +136,5 @@ export const settings = {
edit,
save,
deprecated,
+ variations,
};
diff --git a/packages/block-library/src/group/variations.js b/packages/block-library/src/group/variations.js
new file mode 100644
index 0000000000000..76de042661f38
--- /dev/null
+++ b/packages/block-library/src/group/variations.js
@@ -0,0 +1,18 @@
+/**
+ * WordPress dependencies
+ */
+import { __ } from '@wordpress/i18n';
+
+const variations = [
+ {
+ name: 'group-row',
+ title: __( 'Row' ),
+ description: __( 'Blocks shown in a row.' ),
+ attributes: { layout: { type: 'flex' } },
+ scope: [ 'inserter' ],
+ isActive: ( blockAttributes ) =>
+ blockAttributes.layout?.type === 'flex',
+ },
+];
+
+export default variations;
diff --git a/packages/block-library/src/heading/editor.scss b/packages/block-library/src/heading/editor.scss
deleted file mode 100644
index a1af2ba370244..0000000000000
--- a/packages/block-library/src/heading/editor.scss
+++ /dev/null
@@ -1,20 +0,0 @@
-// Remove padding in heading level control popover since the toolbar buttons already have padding.
-.block-library-heading-level-dropdown .components-popover__content {
- // TODO: Find a less hardcoded way of doing this. `max-content` works on
- // Chromium, but it results in a scrollbar on Safari, and isn't supported
- // at all in IE11.
- min-width: 230px;
-
- > div {
- padding: 0;
- }
-}
-
-// The dropdown already has a border, so we can remove the one on the heading
-// level toolbar.
-.block-library-heading-level-toolbar {
- border: none;
- .components-toolbar-group {
- flex-wrap: nowrap;
- }
-}
diff --git a/packages/block-library/src/heading/heading-level-dropdown.js b/packages/block-library/src/heading/heading-level-dropdown.js
index 84d00181b7129..592787b5fa9dd 100644
--- a/packages/block-library/src/heading/heading-level-dropdown.js
+++ b/packages/block-library/src/heading/heading-level-dropdown.js
@@ -1,14 +1,8 @@
/**
* WordPress dependencies
*/
-import {
- Dropdown,
- Toolbar,
- ToolbarButton,
- ToolbarGroup,
-} from '@wordpress/components';
+import { ToolbarDropdownMenu } from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
-import { DOWN } from '@wordpress/keycodes';
/**
* Internal dependencies
@@ -19,7 +13,6 @@ const HEADING_LEVELS = [ 1, 2, 3, 4, 5, 6 ];
const POPOVER_PROPS = {
className: 'block-library-heading-level-dropdown',
- isAlternate: true,
};
/** @typedef {import('@wordpress/element').WPComponent} WPComponent */
@@ -43,58 +36,33 @@ const POPOVER_PROPS = {
*/
export default function HeadingLevelDropdown( { selectedLevel, onChange } ) {
return (
- {
- const openOnArrowDown = ( event ) => {
- if ( ! isOpen && event.keyCode === DOWN ) {
- event.preventDefault();
- onToggle();
- }
- };
+ icon={ }
+ label={ __( 'Change heading level' ) }
+ controls={ HEADING_LEVELS.map( ( targetLevel ) => {
+ {
+ const isActive = targetLevel === selectedLevel;
- return (
- }
- label={ __( 'Change heading level' ) }
- onClick={ onToggle }
- onKeyDown={ openOnArrowDown }
- showTooltip
- />
- );
- } }
- renderContent={ () => (
-
- {
- const isActive = targetLevel === selectedLevel;
- return {
- icon: (
-
- ),
- title: sprintf(
- // translators: %s: heading level e.g: "1", "2", "3"
- __( 'Heading %d' ),
- targetLevel
- ),
- isActive,
- onClick() {
- onChange( targetLevel );
- },
- };
- } ) }
- />
-
- ) }
+ return {
+ icon: (
+
+ ),
+ label: sprintf(
+ // translators: %s: heading level e.g: "1", "2", "3"
+ __( 'Heading %d' ),
+ targetLevel
+ ),
+ isActive,
+ onClick() {
+ onChange( targetLevel );
+ },
+ };
+ }
+ } ) }
/>
);
}
diff --git a/packages/block-library/src/heading/style.scss b/packages/block-library/src/heading/style.scss
index 31a6989c39c81..e07cdb2f11193 100644
--- a/packages/block-library/src/heading/style.scss
+++ b/packages/block-library/src/heading/style.scss
@@ -4,6 +4,9 @@ h3,
h4,
h5,
h6 {
+ // Break long strings of text without spaces so they don't overflow the block.
+ overflow-wrap: break-word;
+
&.has-background {
padding: $block-bg-padding--v $block-bg-padding--h;
}
diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js
index 3a02291ea0c95..7f29a8d1078c5 100644
--- a/packages/block-library/src/image/edit.js
+++ b/packages/block-library/src/image/edit.js
@@ -246,7 +246,7 @@ export function ImageEdit( {
} );
}
- const isTemp = isTemporaryImage( id, url );
+ let isTemp = isTemporaryImage( id, url );
// Upload a temporary image on mount.
useEffect( () => {
@@ -264,6 +264,7 @@ export function ImageEdit( {
},
allowedTypes: ALLOWED_MEDIA_TYPES,
onError: ( message ) => {
+ isTemp = false;
noticeOperations.createErrorNotice( message );
setAttributes( {
src: undefined,
diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js
index 54174c3607a74..1233abbcdca60 100644
--- a/packages/block-library/src/image/edit.native.js
+++ b/packages/block-library/src/image/edit.native.js
@@ -42,7 +42,7 @@ import {
BlockStyles,
store as blockEditorStore,
} from '@wordpress/block-editor';
-import { __, sprintf } from '@wordpress/i18n';
+import { __, _x, sprintf } from '@wordpress/i18n';
import { getProtocol, hasQueryArg } from '@wordpress/url';
import { doAction, hasAction } from '@wordpress/hooks';
import { compose, withPreferredColorScheme } from '@wordpress/compose';
@@ -121,7 +121,10 @@ export class ImageEdit extends Component {
},
linkRel: {
label: __( 'Link Rel' ),
- placeholder: __( 'None' ),
+ placeholder: _x(
+ 'None',
+ 'Link rel attribute value placeholder'
+ ),
},
};
}
diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js
index 54b552186e7ff..dedd8786534be 100644
--- a/packages/block-library/src/image/image.js
+++ b/packages/block-library/src/image/image.js
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
-import { get, filter, map, last, pick, includes } from 'lodash';
+import { get, filter, map, pick, includes } from 'lodash';
/**
* WordPress dependencies
@@ -21,7 +21,6 @@ import { useSelect, useDispatch } from '@wordpress/data';
import {
BlockControls,
InspectorControls,
- InspectorAdvancedControls,
RichText,
__experimentalImageSizeControl as ImageSizeControl,
__experimentalImageURLInputUI as ImageURLInputUI,
@@ -31,7 +30,7 @@ import {
} from '@wordpress/block-editor';
import { useEffect, useState, useRef } from '@wordpress/element';
import { __, sprintf, isRTL } from '@wordpress/i18n';
-import { getPath } from '@wordpress/url';
+import { getFilename } from '@wordpress/url';
import { createBlock, switchToBlockType } from '@wordpress/blocks';
import { crop, overlayText, upload } from '@wordpress/icons';
import { store as noticesStore } from '@wordpress/notices';
@@ -50,13 +49,6 @@ import { isExternalImage } from './edit';
*/
import { MIN_SIZE, ALLOWED_MEDIA_TYPES } from './constants';
-function getFilename( url ) {
- const path = getPath( url );
- if ( path ) {
- return last( path.split( '/' ) );
- }
-}
-
export default function Image( {
temporaryURL,
attributes: {
@@ -371,7 +363,7 @@ export default function Image( {
/>
-
+
}
/>
-
+
>
);
diff --git a/packages/block-library/src/list/style.scss b/packages/block-library/src/list/style.scss
index 04f579042196f..2bc29a349e4f4 100644
--- a/packages/block-library/src/list/style.scss
+++ b/packages/block-library/src/list/style.scss
@@ -1,4 +1,9 @@
-ol.has-background,
-ul.has-background {
- padding: $block-bg-padding--v $block-bg-padding--h;
+ol,
+ul {
+ // Break long strings of text without spaces so they don't overflow the block.
+ overflow-wrap: break-word;
+
+ &.has-background {
+ padding: $block-bg-padding--v $block-bg-padding--h;
+ }
}
diff --git a/packages/block-library/src/navigation-link/edit.js b/packages/block-library/src/navigation-link/edit.js
index 9df12f2681bc5..fce0a339b2e25 100644
--- a/packages/block-library/src/navigation-link/edit.js
+++ b/packages/block-library/src/navigation-link/edit.js
@@ -10,7 +10,6 @@ import { escape } from 'lodash';
import { createBlock } from '@wordpress/blocks';
import { useSelect, useDispatch } from '@wordpress/data';
import {
- KeyboardShortcuts,
PanelBody,
Popover,
TextControl,
@@ -18,7 +17,7 @@ import {
ToolbarButton,
ToolbarGroup,
} from '@wordpress/components';
-import { rawShortcut, displayShortcut } from '@wordpress/keycodes';
+import { displayShortcut, isKeyboardEvent, ENTER } from '@wordpress/keycodes';
import { __, sprintf } from '@wordpress/i18n';
import {
BlockControls,
@@ -292,7 +291,10 @@ export default function NavigationLinkEdit( {
};
const { showSubmenuIcon } = context;
const { saveEntityRecord } = useDispatch( coreStore );
- const { insertBlock } = useDispatch( blockEditorStore );
+ const {
+ insertBlock,
+ __unstableMarkNextChangeAsNotPersistent,
+ } = useDispatch( blockEditorStore );
const [ isLinkOpen, setIsLinkOpen ] = useState( false );
const listItemRef = useRef( null );
const isDraggingWithin = useIsDraggingWithin( listItemRef );
@@ -355,8 +357,14 @@ export default function NavigationLinkEdit( {
[ clientId ]
);
- // Store the colors from context as attributes for rendering
- useEffect( () => setAttributes( { isTopLevelLink } ), [ isTopLevelLink ] );
+ useEffect( () => {
+ // This side-effect should not create an undo level as those should
+ // only be created via user interactions. Mark this change as
+ // not persistent to avoid undo level creation.
+ // See https://github.com/WordPress/gutenberg/issues/34564.
+ __unstableMarkNextChangeAsNotPersistent();
+ setAttributes( { isTopLevelLink } );
+ }, [ isTopLevelLink ] );
/**
* Insert a link block when submenu is added.
@@ -467,6 +475,15 @@ export default function NavigationLinkEdit( {
customBackgroundColor,
} = getColors( context, ! isTopLevelLink );
+ function onKeyDown( event ) {
+ if (
+ isKeyboardEvent.primary( event, 'k' ) ||
+ ( ! url && event.keyCode === ENTER )
+ ) {
+ setIsLinkOpen( true );
+ }
+ }
+
const blockProps = useBlockProps( {
ref: listItemRef,
className: classnames( 'wp-block-navigation-item', {
@@ -486,6 +503,7 @@ export default function NavigationLinkEdit( {
color: ! textColor && customTextColor,
backgroundColor: ! backgroundColor && customBackgroundColor,
},
+ onKeyDown,
} );
if ( ! url ) {
@@ -566,13 +584,6 @@ export default function NavigationLinkEdit( {
-
- setIsLinkOpen( true ),
- } }
- />
-
- isSelected && setIsLinkOpen( true ),
- } }
- />
{ missingText }
) : (
@@ -672,12 +677,6 @@ export default function NavigationLinkEdit( {
onClose={ () => setIsLinkOpen( false ) }
anchorRef={ listItemRef.current }
>
- setIsLinkOpen( false ),
- } }
- />
.wp-block-navigation-link__container {
+ > .wp-block-navigation__submenu-container {
// We use important here because if the parent block is selected and submenus are present, they should always be visible.
visibility: visible !important;
opacity: 1 !important;
+ min-width: 200px !important;
+ height: auto !important;
+ width: auto !important;
}
}
}
@@ -43,12 +44,12 @@
* Navigation Items.
*/
-.wp-block-navigation-link {
- .wp-block-navigation-link__container {
+.wp-block-navigation-item {
+ .wp-block-navigation__submenu-container {
display: block;
}
- .wp-block-navigation-link__content {
+ .wp-block-navigation-item__content {
cursor: text;
}
@@ -96,7 +97,7 @@
}
// This needs extra specificity.
- &.wp-block-navigation-link__content {
+ &.wp-block-navigation-item__content {
cursor: pointer;
}
}
diff --git a/packages/block-library/src/navigation/block-navigation-list.js b/packages/block-library/src/navigation/block-navigation-list.js
index 2aee258574605..814a56b20f4fd 100644
--- a/packages/block-library/src/navigation/block-navigation-list.js
+++ b/packages/block-library/src/navigation/block-navigation-list.js
@@ -6,6 +6,7 @@ import {
store as blockEditorStore,
} from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';
+import { useRef, useEffect, useState } from '@wordpress/element';
export default function BlockNavigationList( {
clientId,
@@ -17,13 +18,21 @@ export default function BlockNavigationList( {
[ clientId ]
);
+ const listViewRef = useRef();
+ const [ minHeight, setMinHeight ] = useState( 300 );
+ useEffect( () => {
+ setMinHeight( listViewRef?.current?.clientHeight ?? 300 );
+ }, [] );
+
return (
-
+
+
+
);
}
diff --git a/packages/block-library/src/navigation/block.json b/packages/block-library/src/navigation/block.json
index 79da72eb86a2f..98663a8075b23 100644
--- a/packages/block-library/src/navigation/block.json
+++ b/packages/block-library/src/navigation/block.json
@@ -8,7 +8,8 @@
"textdomain": "default",
"attributes": {
"orientation": {
- "type": "string"
+ "type": "string",
+ "default": "horizontal"
},
"textColor": {
"type": "string"
diff --git a/packages/block-library/src/navigation/edit.js b/packages/block-library/src/navigation/edit.js
index 0f55e958e5b97..bdab02b4b7c80 100644
--- a/packages/block-library/src/navigation/edit.js
+++ b/packages/block-library/src/navigation/edit.js
@@ -46,6 +46,8 @@ const ALLOWED_BLOCKS = [
'core/page-list',
'core/spacer',
'core/home-link',
+ 'core/site-title',
+ 'core/site-logo',
];
const LAYOUT = {
@@ -101,6 +103,7 @@ function Navigation( {
hasSubmenuIndicatorSetting = true,
hasItemJustificationControls = true,
hasColorSettings = true,
+ customPlaceholder: CustomPlaceholder = null,
} ) {
const [ isPlaceholderShown, setIsPlaceholderShown ] = useState(
! hasExistingNavItems
@@ -148,20 +151,24 @@ function Navigation( {
},
{
allowedBlocks: ALLOWED_BLOCKS,
- orientation: attributes.orientation || 'horizontal',
+ orientation: attributes.orientation,
renderAppender:
( isImmediateParentOfSelectedBlock &&
! selectedBlockHasDescendants ) ||
isSelected
? InnerBlocks.DefaultAppender
: false,
- __experimentalCaptureToolbars: true,
+ // Ensure block toolbar is not too far removed from item
+ // being edited when in vertical mode.
+ // see: https://github.com/WordPress/gutenberg/pull/34615.
+ __experimentalCaptureToolbars:
+ attributes.orientation !== 'vertical',
// Template lock set to false here so that the Nav
// Block on the experimental menus screen does not
// inherit templateLock={ 'all' }.
templateLock: false,
__experimentalLayout: LAYOUT,
- placeholder,
+ placeholder: ! CustomPlaceholder ? placeholder : undefined,
}
);
@@ -198,9 +205,13 @@ function Navigation( {
} );
if ( isPlaceholderShown ) {
+ const PlaceholderComponent = CustomPlaceholder
+ ? CustomPlaceholder
+ : NavigationPlaceholder;
+
return (
- {
setIsPlaceholderShown( false );
updateInnerBlocks( blocks );
diff --git a/packages/block-library/src/navigation/editor.scss b/packages/block-library/src/navigation/editor.scss
index fff28e42151ab..ba4212cf67777 100644
--- a/packages/block-library/src/navigation/editor.scss
+++ b/packages/block-library/src/navigation/editor.scss
@@ -11,6 +11,13 @@
margin-left: 0;
padding-left: 0;
}
+
+ // Revert any left/right margins.
+ // This also makes it work with classic theme auto margins.
+ .wp-block-navigation-item.wp-block {
+ margin-left: revert;
+ margin-right: revert;
+ }
}
// This element is inline on the frontend but needs to be editable, therefore inline-block, in the editor.
@@ -31,13 +38,13 @@
// Low specificity default to ensure background color applies to submenus.
.wp-block-navigation__container,
-.wp-block-navigation-link {
+.wp-block-navigation-item {
background-color: inherit;
}
// Only show the flyout on hover if the parent menu item is selected.
.wp-block-navigation:not(.is-selected):not(.has-child-selected) .has-child:hover {
- > .wp-block-navigation-link__container {
+ > .wp-block-navigation__submenu-container {
opacity: 0;
visibility: hidden;
}
@@ -47,7 +54,7 @@
.has-child {
&.is-selected,
&.has-child-selected {
- > .wp-block-navigation-link__container {
+ > .wp-block-navigation__submenu-container {
display: flex;
opacity: 1;
visibility: visible;
@@ -58,7 +65,7 @@
// Show a submenu when generally dragging (is-dragging-components-draggable) if that
// submenu has children (has-child) and is being dragged within (is-dragging-within).
.is-dragging-components-draggable .has-child.is-dragging-within {
- > .wp-block-navigation-link__container {
+ > .wp-block-navigation__submenu-container {
opacity: 1;
visibility: visible;
}
@@ -215,7 +222,7 @@ $color-control-label-height: 20px;
// Style skeleton elements to mostly match the metrics of actual menu items.
// Needs specificity.
- .wp-block-navigation-link.wp-block-navigation-link {
+ .wp-block-navigation-item.wp-block-navigation-item {
position: relative;
min-width: 72px;
@@ -237,7 +244,7 @@ $color-control-label-height: 20px;
}
- .wp-block-navigation-link.wp-block-navigation-link,
+ .wp-block-navigation-item.wp-block-navigation-item,
.wp-block-navigation-placeholder__preview-search-icon {
opacity: 0.3;
}
@@ -250,6 +257,7 @@ $color-control-label-height: 20px;
width: 0;
overflow: hidden;
flex-wrap: nowrap;
+ flex: 0;
}
// Hide entirely when vertical.
diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php
index df93471feecbc..68246111ffe0e 100644
--- a/packages/block-library/src/navigation/index.php
+++ b/packages/block-library/src/navigation/index.php
@@ -256,15 +256,19 @@ function render_block_core_navigation( $attributes, $content, $block ) {
$inner_blocks_html = '';
$is_list_open = false;
foreach ( $inner_blocks as $inner_block ) {
- if ( ( 'core/navigation-link' === $inner_block->name || 'core/home-link' === $inner_block->name ) && ! $is_list_open ) {
+ if ( ( 'core/navigation-link' === $inner_block->name || 'core/home-link' === $inner_block->name || 'core/site-title' === $inner_block->name || 'core/site-logo' === $inner_block->name ) && ! $is_list_open ) {
$is_list_open = true;
$inner_blocks_html .= '
- );
-};
-
-export default ModalHeader;
diff --git a/packages/components/src/modal/index.js b/packages/components/src/modal/index.js
index e689b77171486..90acee41efa5c 100644
--- a/packages/components/src/modal/index.js
+++ b/packages/components/src/modal/index.js
@@ -1,175 +1,168 @@
//@ts-nocheck
+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
/**
* WordPress dependencies
*/
-import { Component, createPortal } from '@wordpress/element';
-import { withInstanceId } from '@wordpress/compose';
+import { createPortal, useEffect, useRef } from '@wordpress/element';
+import {
+ useInstanceId,
+ useFocusReturn,
+ useFocusOnMount,
+ __experimentalUseFocusOutside as useFocusOutside,
+ useConstrainedTabbing,
+ useMergeRefs,
+} from '@wordpress/compose';
import deprecated from '@wordpress/deprecated';
+import { ESCAPE } from '@wordpress/keycodes';
+import { __ } from '@wordpress/i18n';
+import { closeSmall } from '@wordpress/icons';
/**
* Internal dependencies
*/
-import ModalFrame from './frame';
-import ModalHeader from './header';
import * as ariaHelper from './aria-helper';
+import Button from '../button';
// Used to count the number of open modals.
-let parentElement,
- openModalCount = 0;
-
-class Modal extends Component {
- constructor( props ) {
- super( props );
- this.prepareDOM();
- }
-
- /**
- * Appends the modal's node to the DOM, so the portal can render the
- * modal in it. Also calls the openFirstModal when this is the first modal to be
- * opened.
- */
- componentDidMount() {
+let openModalCount = 0;
+
+export default function Modal( {
+ bodyOpenClassName = 'modal-open',
+ role = 'dialog',
+ title = null,
+ focusOnMount = true,
+ shouldCloseOnEsc = true,
+ shouldCloseOnClickOutside = true,
+ isDismissable, // Deprecated
+ isDismissible = isDismissable || true,
+ /* accessibility */
+ aria = {
+ labelledby: null,
+ describedby: null,
+ },
+ onRequestClose,
+ icon,
+ closeButtonLabel,
+ children,
+ style,
+ overlayClassName,
+ className,
+ contentLabel,
+ onKeyDown,
+} ) {
+ const ref = useRef();
+ const instanceId = useInstanceId( Modal );
+ const headingId = title
+ ? `components-modal-header-${ instanceId }`
+ : aria.labelledby;
+ const focusOnMountRef = useFocusOnMount( focusOnMount );
+ const constrainedTabbingRef = useConstrainedTabbing();
+ const focusReturnRef = useFocusReturn();
+ const focusOutsideProps = useFocusOutside( onRequestClose );
+
+ useEffect( () => {
openModalCount++;
if ( openModalCount === 1 ) {
- this.openFirstModal();
+ ariaHelper.hideApp( ref.current );
+ document.body.classList.add( bodyOpenClassName );
}
- }
-
- /**
- * Removes the modal's node from the DOM. Also calls closeLastModal when this is
- * the last modal to be closed.
- */
- componentWillUnmount() {
- openModalCount--;
- if ( openModalCount === 0 ) {
- this.closeLastModal();
- }
-
- this.cleanDOM();
+ return () => {
+ openModalCount--;
+
+ if ( openModalCount === 0 ) {
+ document.body.classList.remove( bodyOpenClassName );
+ ariaHelper.showApp();
+ }
+ };
+ }, [] );
+
+ if ( isDismissable ) {
+ deprecated( 'isDismissable prop of the Modal component', {
+ since: '5.4',
+ alternative: 'isDismissible prop (renamed) of the Modal component',
+ } );
}
- /**
- * Prepares the DOM for the modals to be rendered.
- *
- * Every modal is mounted in a separate div appended to a parent div
- * that is appended to the document body.
- *
- * The parent div will be created if it does not yet exist, and the
- * separate div for this specific modal will be appended to that.
- */
- prepareDOM() {
- if ( ! parentElement ) {
- parentElement = document.createElement( 'div' );
- document.body.appendChild( parentElement );
+ function handleEscapeKeyDown( event ) {
+ if (
+ shouldCloseOnEsc &&
+ event.keyCode === ESCAPE &&
+ ! event.defaultPrevented
+ ) {
+ event.preventDefault();
+ if ( onRequestClose ) {
+ onRequestClose( event );
+ }
}
- this.node = document.createElement( 'div' );
- parentElement.appendChild( this.node );
- }
-
- /**
- * Removes the specific mounting point for this modal from the DOM.
- */
- cleanDOM() {
- parentElement.removeChild( this.node );
- }
-
- /**
- * Prepares the DOM for this modal and any additional modal to be mounted.
- *
- * It appends an additional div to the body for the modals to be rendered in,
- * it hides any other elements from screen-readers and adds an additional class
- * to the body to prevent scrolling while the modal is open.
- */
- openFirstModal() {
- ariaHelper.hideApp( parentElement );
- document.body.classList.add( this.props.bodyOpenClassName );
- }
-
- /**
- * Cleans up the DOM after the last modal is closed and makes the app available
- * for screen-readers again.
- */
- closeLastModal() {
- document.body.classList.remove( this.props.bodyOpenClassName );
- ariaHelper.showApp();
}
- /**
- * Renders the modal.
- *
- * @return {WPElement} The modal element.
- */
- render() {
- const {
- onRequestClose,
- title,
- icon,
- closeButtonLabel,
- children,
- aria,
- instanceId,
- isDismissible,
- isDismissable, //Deprecated
- // Many of the documented props for Modal are passed straight through
- // to the ModalFrame component and handled there.
- ...otherProps
- } = this.props;
-
- const headingId = title
- ? `components-modal-header-${ instanceId }`
- : aria.labelledby;
-
- if ( isDismissable ) {
- deprecated( 'isDismissable prop of the Modal component', {
- since: '5.4',
- alternative:
- 'isDismissible prop (renamed) of the Modal component',
- } );
- }
- // Disable reason: this stops mouse events from triggering tooltips and
- // other elements underneath the modal overlay.
- return createPortal(
-
+