diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d356c6113543ea..c90179f0e80943 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -47,7 +47,7 @@ /packages/block-editor/src/components/link-control @getdave # Widgets -/packages/edit-widgets @draganescu @talldan @adamziel @kevin940726 +/packages/edit-widgets @draganescu @adamziel @kevin940726 /packages/customize-widgets /packages/widgets diff --git a/.github/setup-node/action.yml b/.github/setup-node/action.yml index fccce2e4e93bcf..f52f5fb2e3ebf0 100644 --- a/.github/setup-node/action.yml +++ b/.github/setup-node/action.yml @@ -28,7 +28,7 @@ runs: uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 with: path: '**/node_modules' - key: node_modules-${{ runner.os }}-${{ steps.node-version.outputs.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} + key: node_modules-${{ runner.os }}-${{ runner.arch }}-${{ steps.node-version.outputs.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} - name: Install npm dependencies if: ${{ steps.cache-node_modules.outputs.cache-hit != 'true' }} diff --git a/.github/workflows/build-plugin-zip.yml b/.github/workflows/build-plugin-zip.yml index 7facf92e00dd4f..dab26f66aa5263 100644 --- a/.github/workflows/build-plugin-zip.yml +++ b/.github/workflows/build-plugin-zip.yml @@ -69,7 +69,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: token: ${{ secrets.GUTENBERG_TOKEN }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -165,7 +165,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: ref: ${{ needs.bump-version.outputs.release_branch || github.ref }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -183,7 +183,7 @@ jobs: NO_CHECKS: 'true' - name: Upload artifact - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 with: name: gutenberg-plugin path: ./gutenberg.zip @@ -206,7 +206,7 @@ jobs: - name: Upload release notes artifact if: ${{ needs.bump-version.outputs.new_version }} - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 with: name: release-notes path: ./release-notes.txt @@ -222,7 +222,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: fetch-depth: 2 ref: ${{ needs.bump-version.outputs.release_branch }} @@ -270,12 +270,12 @@ jobs: run: echo "version=$(echo $VERSION | cut -d / -f 3 | sed 's/-rc./ RC/' )" >> $GITHUB_OUTPUT - name: Download Plugin Zip Artifact - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4.1.5 with: name: gutenberg-plugin - name: Download Release Notes Artifact - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4.1.5 with: name: release-notes @@ -311,14 +311,14 @@ jobs: if: ${{ endsWith( needs.bump-version.outputs.new_version, '-rc.1' ) }} steps: - name: Checkout (for CLI) - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: path: main ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Checkout (for publishing) - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: path: publish # Later, we switch this branch in the script that publishes packages. diff --git a/.github/workflows/bundle-size.yml b/.github/workflows/bundle-size.yml index a1c66221a76aff..de59da57ead8b1 100644 --- a/.github/workflows/bundle-size.yml +++ b/.github/workflows/bundle-size.yml @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: fetch-depth: 1 show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/check-components-changelog.yml b/.github/workflows/check-components-changelog.yml index 8af0dc05f41087..8f20e3d22aedb9 100644 --- a/.github/workflows/check-components-changelog.yml +++ b/.github/workflows/check-components-changelog.yml @@ -20,7 +20,7 @@ jobs: - name: 'Get PR commit count' run: echo "PR_COMMIT_COUNT=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> "${GITHUB_ENV}" - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: ref: ${{ github.event.pull_request.head.ref }} repository: ${{ github.event.pull_request.head.repo.full_name }} diff --git a/.github/workflows/create-block.yml b/.github/workflows/create-block.yml index 5fec67935cdf0c..00ff266aa63ec7 100644 --- a/.github/workflows/create-block.yml +++ b/.github/workflows/create-block.yml @@ -24,7 +24,7 @@ jobs: os: ['macos-latest', 'ubuntu-latest', 'windows-latest'] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/end2end-test.yml b/.github/workflows/end2end-test.yml index 23545c70f512ec..34c9b7275c64a0 100644 --- a/.github/workflows/end2end-test.yml +++ b/.github/workflows/end2end-test.yml @@ -27,7 +27,7 @@ jobs: totalParts: [8] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -52,7 +52,7 @@ jobs: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test:e2e -- --shard=${{ matrix.part }}/${{ matrix.totalParts }} - name: Archive debug artifacts (screenshots, traces) - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 if: always() with: name: failures-artifacts @@ -60,7 +60,7 @@ jobs: if-no-files-found: ignore - name: Archive flaky tests report - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 if: always() with: name: flaky-tests-report @@ -75,12 +75,12 @@ jobs: steps: # Checkout defaults to using the branch which triggered the event, which # isn't necessarily `trunk` (e.g. in the case of a merge). - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: actions/download-artifact@v4.1.4 + - uses: actions/download-artifact@v4.1.5 id: download_artifact # Don't fail the job if there isn't any flaky tests report. continue-on-error: true diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 12f8517e2a5f5c..ea6564a5dde398 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -6,7 +6,7 @@ jobs: name: 'Validation' runs-on: ubuntu-latest steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: gradle/wrapper-validation-action@v2 + - uses: gradle/wrapper-validation-action@v3 diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 143bf71ab2e3af..02bdef381ce84b 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -32,7 +32,7 @@ jobs: WP_ARTIFACTS_PATH: ${{ github.workspace }}/artifacts steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -86,7 +86,7 @@ jobs: - name: Archive performance results if: success() - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 with: name: performance-results path: ${{ env.WP_ARTIFACTS_PATH }}/*.performance-results*.json @@ -100,7 +100,7 @@ jobs: ./bin/log-performance-results.js $CODEHEALTH_PROJECT_TOKEN trunk $GITHUB_SHA 9bb75b35ec0daa46e8cd60c46619f522c7edd453 $COMMITTED_AT - name: Archive debug artifacts (screenshots, HTML snapshots) - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 if: failure() with: name: failures-artifacts diff --git a/.github/workflows/php-changes-detection.yml b/.github/workflows/php-changes-detection.yml index f2529e873816ae..dec97de5e87255 100644 --- a/.github/workflows/php-changes-detection.yml +++ b/.github/workflows/php-changes-detection.yml @@ -10,14 +10,14 @@ jobs: if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} steps: - name: Check out code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: fetch-depth: 0 show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Get changed PHP files id: changed-files-php - uses: tj-actions/changed-files@2d756ea4c53f7f6b397767d8723b3a10a9f35bf2 # v44.0.0 + uses: tj-actions/changed-files@0874344d6ebbaa00a27da73276ae7162fadcaf69 # v44.3.0 with: files: | **.{php} diff --git a/.github/workflows/publish-npm-packages.yml b/.github/workflows/publish-npm-packages.yml index 038d8de8ed2e18..2276136190bb27 100644 --- a/.github/workflows/publish-npm-packages.yml +++ b/.github/workflows/publish-npm-packages.yml @@ -31,7 +31,7 @@ jobs: steps: - name: Checkout (for CLI) if: ${{ github.event.inputs.release_type != 'wp' }} - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: path: cli ref: trunk @@ -39,7 +39,7 @@ jobs: - name: Checkout (for publishing) if: ${{ github.event.inputs.release_type != 'wp' }} - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: path: publish # Later, we switch this branch in the script that publishes packages. @@ -49,7 +49,7 @@ jobs: - name: Checkout (for publishing WP major version) if: ${{ github.event.inputs.release_type == 'wp' && github.event.inputs.wp_version }} - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: path: publish ref: wp/${{ github.event.inputs.wp_version }} diff --git a/.github/workflows/pull-request-automation.yml b/.github/workflows/pull-request-automation.yml index 73fc2866848856..bc002f0ca0890e 100644 --- a/.github/workflows/pull-request-automation.yml +++ b/.github/workflows/pull-request-automation.yml @@ -12,7 +12,7 @@ jobs: steps: # Checkout defaults to using the branch which triggered the event, which # isn't necessarily `trunk` (e.g. in the case of a merge). - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index d9bc76e4772d0f..873853cab39f56 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -23,7 +23,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -47,7 +47,7 @@ jobs: run: npm run native test:e2e:setup - name: Gradle cache - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + uses: gradle/actions/setup-gradle@6cec5d49d4d6d4bb982fbed7047db31ea6d38f11 # v3.3.0 - name: AVD cache uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 @@ -81,13 +81,13 @@ jobs: profile: Nexus 6 script: npm run native test:e2e:android:local ${{ matrix.native-test-name }} - - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 if: always() with: name: android-screen-recordings path: packages/react-native-editor/android-screen-recordings - - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 if: always() with: name: appium-logs diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index 0484faa9cdfe74..1823107f30aafc 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -23,11 +23,11 @@ jobs: native-test-name: [gutenberg-editor-rendering] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: ruby/setup-ruby@5f19ec79cedfadb78ab837f95b87734d0003c899 # v1.173.0 + - uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0 with: # `.ruby-version` file location working-directory: packages/react-native-editor/ios @@ -89,13 +89,13 @@ jobs: rm packages/react-native-editor/ios/build/GutenbergDemo/Build/Products/Release-iphonesimulator/GutenbergDemo.app/main.jsbundle rm -rf packages/react-native-editor/ios/build/GutenbergDemo/Build/Products/Release-iphonesimulator/GutenbergDemo.app/assets - - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 if: always() with: name: ios-screen-recordings path: packages/react-native-editor/ios-screen-recordings - - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 if: always() with: name: appium-logs diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index fb8f33a103293d..933873f71720ea 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -22,7 +22,7 @@ jobs: if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/storybook-pages.yml b/.github/workflows/storybook-pages.yml index 1f79fb208094c2..f70263e49dc317 100644 --- a/.github/workflows/storybook-pages.yml +++ b/.github/workflows/storybook-pages.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -24,7 +24,7 @@ jobs: run: npm run storybook:build - name: Deploy - uses: peaceiris/actions-gh-pages@373f7f263a76c20808c831209c920827a82a2847 # v3.9.3 + uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./storybook/build diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 551a77f8bed6d1..a873a53fb9c133 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -70,7 +70,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -121,7 +121,7 @@ jobs: name: Build JavaScript assets for PHP unit tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -132,7 +132,7 @@ jobs: run: npm run build - name: Upload built JavaScript assets - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 with: name: build-assets path: ./build/ @@ -157,7 +157,7 @@ jobs: wordpress: [''] # Latest WordPress version. include: # Test with the previous WP version. - - php: '7.0' + - php: '7.2' wordpress: ${{ needs.compute-previous-wordpress-version.outputs.previous-wordpress-version }} - php: '7.4' wordpress: ${{ needs.compute-previous-wordpress-version.outputs.previous-wordpress-version }} @@ -170,7 +170,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} @@ -185,7 +185,7 @@ jobs: # dependency versions are installed and cached. ## - name: Set up PHP - uses: shivammathur/setup-php@8872c784b04a1420e81191df5d64fbd59d3d3033 # v2.30.2 + uses: shivammathur/setup-php@efffd0e4f2504f936fcfe3b69293d31ce0e2fd7a # v2.30.3 with: php-version: '${{ matrix.php }}' ini-file: development @@ -209,7 +209,7 @@ jobs: custom-cache-suffix: $(/bin/date -u --date='last Mon' "+%F") - name: Download built JavaScript assets - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4.1.5 with: name: build-assets path: ./build @@ -281,12 +281,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Set up PHP - uses: shivammathur/setup-php@8872c784b04a1420e81191df5d64fbd59d3d3033 # v2.30.2 + uses: shivammathur/setup-php@efffd0e4f2504f936fcfe3b69293d31ce0e2fd7a # v2.30.3 with: php-version: '7.4' coverage: none @@ -351,7 +351,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} diff --git a/.github/workflows/upload-release-to-plugin-repo.yml b/.github/workflows/upload-release-to-plugin-repo.yml index 7ca7283f9cfdec..dfbbf1ede7e306 100644 --- a/.github/workflows/upload-release-to-plugin-repo.yml +++ b/.github/workflows/upload-release-to-plugin-repo.yml @@ -96,7 +96,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: ref: ${{ matrix.branch }} token: ${{ secrets.GUTENBERG_TOKEN }} @@ -147,7 +147,7 @@ jobs: fi - name: Upload Changelog artifact - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 with: name: changelog ${{ matrix.label }} path: ./changelog.txt @@ -189,7 +189,7 @@ jobs: sed -i "s/$STABLE_TAG_PLACEHOLDER/Stable tag: $VERSION/g" ./trunk/readme.txt - name: Download Changelog Artifact - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4.1.5 with: name: changelog trunk path: trunk @@ -247,7 +247,7 @@ jobs: sed -i "s/$STABLE_TAG_PLACEHOLDER/Stable tag: $VERSION/g" "$VERSION/readme.txt" - name: Download Changelog Artifact - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4.1.5 with: name: changelog trunk path: ${{ github.event.release.name }} diff --git a/README.md b/README.md index 33f76716470751..360b2851be092b 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,13 @@ Welcome to the development hub for the WordPress Gutenberg project! -"Gutenberg" is a codename for a whole new paradigm in WordPress site building and publishing, that aims to revolutionize the entire publishing experience as much as Gutenberg did the printed word. Right now, the project is in the second phase of a four-phase process that will touch every piece of WordPress -- Editing, **Customization** (which includes Full Site Editing, Block Patterns, Block Directory and Block based themes), Collaboration, and Multilingual -- and is focused on a new editing experience, the block editor. +"Gutenberg" is a codename for a whole new paradigm in WordPress site building and publishing, that aims to revolutionize the entire publishing experience as much as Gutenberg did the printed word. Right now, the project is in the second phase of a four-phase process that will touch every piece of WordPress -- Editing, Customization, **Collaboration** (which includes [Real-time collaboration](https://make.wordpress.org/core/2023/07/03/real-time-collaboration/), [Asynchronous collaboration](https://make.wordpress.org/core/2023/07/04/workflows/), [Publishing flows](https://make.wordpress.org/core/2023/07/04/workflows/), [Post revisions interface](https://make.wordpress.org/core/2023/07/05/revisions/), [Admin design](https://make.wordpress.org/core/2023/07/12/admin-design/), [Library](https://make.wordpress.org/core/2023/07/10/block-library/)), and Multilingual -- and is focused on a new editing experience, the block editor. The block editor introduces a modular approach to pages and posts: each piece of content in the editor, from a paragraph to an image gallery to a headline, is its own block. And just like physical blocks, WordPress blocks can be added, arranged, and rearranged, allowing WordPress users to create media-rich pages in a visually intuitive way -- and without work-arounds like shortcodes or custom HTML. The block editor first became available in December 2018, and we're still hard at work refining the experience, creating more and better blocks, and laying the groundwork for the next three phases of work. The Gutenberg plugin gives you the latest version of the block editor, so you can join us in testing bleeding-edge features, start playing with blocks, and maybe get inspired to build your own. -Check out the [Ways to keep up with Gutenberg & Full Site Editing (FSE)](https://make.wordpress.org/core/2020/05/20/ways-to-keep-up-with-full-site-editing-fse/) +Check out the [Keeping up with Gutenberg Index](https://make.wordpress.org/core/handbook/references/keeping-up-with-gutenberg-index/) ## Getting Started @@ -55,8 +55,6 @@ As with all WordPress projects, we want to ensure a welcoming environment for ev You can join us in the `#core-editor` channel in Slack, see the [WordPress Slack page](https://make.wordpress.org/chat/) for signup information; it is free to join. -**Weekly meetings** The Editor Team meets weekly on Wednesdays at 14:00 UTC in Slack. If you can not join the meeting, [agenda](https://make.wordpress.org/core/tag/core-editor-agenda/) and [notes](https://make.wordpress.org/core/tag/core-editor-summary/) are posted to the [Make WordPress Blog](https://make.wordpress.org/core/). - ## License WordPress is free software, and is released under the terms of the GNU General Public License version 2 or (at your option) any later version. See [LICENSE.md](LICENSE.md) for complete license. diff --git a/bin/api-docs/gen-theme-reference.js b/bin/api-docs/gen-theme-reference.js index 0ea9e282e5463e..6bb0e5d5b4ce2d 100644 --- a/bin/api-docs/gen-theme-reference.js +++ b/bin/api-docs/gen-theme-reference.js @@ -127,16 +127,44 @@ const getSettingsPropertiesMarkup = ( struct ) => { } let markup = '| Property | Type | Default | Props |\n'; - markup += '| --- | --- | --- |--- |\n'; + markup += '| --- | --- | --- |--- |\n'; ks.forEach( ( key ) => { const def = 'default' in props[ key ] ? props[ key ].default : ''; - const ps = + let type = props[ key ].type || ''; + let ps = props[ key ].type === 'array' ? keys( getPropertiesFromArray( props[ key ].items ) ) .sort() .join( ', ' ) : ''; - markup += `| ${ key } | ${ props[ key ].type } | ${ def } | ${ ps } |\n`; + + /* + * Handle`oneOf` type definitions - extract the type and properties. + * See: https://json-schema.org/understanding-json-schema/reference/combining#oneOf + */ + if ( props[ key ].oneOf && Array.isArray( props[ key ].oneOf ) ) { + if ( ! type ) { + type = props[ key ].oneOf + .map( ( item ) => item.type ) + .join( ', ' ); + } + + if ( ! ps ) { + ps = props[ key ].oneOf + .map( ( item ) => + item?.type === 'object' && item?.properties + ? '_{' + + keys( getPropertiesFromArray( item ) ) + .sort() + .join( ', ' ) + + '}_' + : '' + ) + .join( ' ' ); + } + } + + markup += `| ${ key } | ${ type } | ${ def } | ${ ps } |\n`; } ); return markup; diff --git a/bin/packages/lint-staged-typecheck.js b/bin/packages/lint-staged-typecheck.js index 7b7eb7b846bfb0..8e656755134f18 100644 --- a/bin/packages/lint-staged-typecheck.js +++ b/bin/packages/lint-staged-typecheck.js @@ -28,9 +28,11 @@ const changedPackages = [ fs.existsSync( path.join( packageRoot, 'tsconfig.json' ) ) ); -try { - execa.sync( tscPath, [ '--build', ...changedPackages ] ); -} catch ( err ) { - console.error( err.stdout ); - process.exitCode = 1; +if ( changedPackages.length > 0 ) { + try { + execa.sync( tscPath, [ '--build', ...changedPackages ] ); + } catch ( err ) { + console.error( err.stdout ); + process.exitCode = 1; + } } diff --git a/changelog.txt b/changelog.txt index 02864f4ea4bf25..75bde44254aecc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,378 @@ == Changelog == += 18.2.0 = + +## Changelog + +- Bump minimum required PHP version to 7.2 ([60714](https://github.com/WordPress/gutenberg/pull/60714)) + +### Enhancements + +#### Site Editor +- Add rename and trash actions to page panel. ([60232](https://github.com/WordPress/gutenberg/pull/60232)) +- Adjust frame animation profile. ([60589](https://github.com/WordPress/gutenberg/pull/60589)) +- Animate the radius of the frame. ([60415](https://github.com/WordPress/gutenberg/pull/60415)) +- Create router adapter for sidebar. ([60466](https://github.com/WordPress/gutenberg/pull/60466)) +- Improve the header animation. ([60408](https://github.com/WordPress/gutenberg/pull/60408)) +- Index view for Templates & Parts: Use `grid` layout as default. ([60069](https://github.com/WordPress/gutenberg/pull/60069)) +- Pages: Display content frame in mobile when canvas is not edit. ([60409](https://github.com/WordPress/gutenberg/pull/60409)) +- Simplify template reset language. ([60256](https://github.com/WordPress/gutenberg/pull/60256)) +- Template parts in patterns page: Add author field. ([60372](https://github.com/WordPress/gutenberg/pull/60372)) +- Template parts: Set backpath to patterns page. ([60667](https://github.com/WordPress/gutenberg/pull/60667)) +- Update hub markup and animation. ([60410](https://github.com/WordPress/gutenberg/pull/60410)) +- Update site hub action positioning. ([60511](https://github.com/WordPress/gutenberg/pull/60511)) + +#### Components +- CustomSelectControlV2: Support disabled in item types. ([60896](https://github.com/WordPress/gutenberg/pull/60896)) +- ExternalLink: Replace icon with unicode arrow. ([60255](https://github.com/WordPress/gutenberg/pull/60255)) +- InputBase: Simplify focus styles. ([60226](https://github.com/WordPress/gutenberg/pull/60226)) +- ProgressBar: Moved width to css var for perf. ([60388](https://github.com/WordPress/gutenberg/pull/60388)) +- SlotFill: Replace valtio with custom ObservableMap. ([60879](https://github.com/WordPress/gutenberg/pull/60879)) +- Tabs: Fallback to first enabled tab if no active tab Id. ([60681](https://github.com/WordPress/gutenberg/pull/60681)) +- Text: Add text-wrap: Pretty. ([60164](https://github.com/WordPress/gutenberg/pull/60164)) +- Try: Reduce checkbox size in data views. ([60475](https://github.com/WordPress/gutenberg/pull/60475)) + +#### Post Editor +- Confirm dialog: Use more descriptive text for the confirm button. ([60364](https://github.com/WordPress/gutenberg/pull/60364)) +- Editor: Add wordcount and reading time info in post card. ([60672](https://github.com/WordPress/gutenberg/pull/60672)) +- Editor: Animate opening and closing editor right sidebar. ([60561](https://github.com/WordPress/gutenberg/pull/60561)) +- Editor: Animate the inserter and list view panels. ([60665](https://github.com/WordPress/gutenberg/pull/60665)) +- Editor: Update post URL component. ([60632](https://github.com/WordPress/gutenberg/pull/60632)) +- Editor: Use the 'ConfirmDialog' component in template validation notice. ([60385](https://github.com/WordPress/gutenberg/pull/60385)) +- Enable template preview in post editor for non administrators. ([60447](https://github.com/WordPress/gutenberg/pull/60447)) +- Support insert before/after keyboard shortcuts when focus is within the list view. ([60651](https://github.com/WordPress/gutenberg/pull/60651)) +- Update publish flow. ([60456](https://github.com/WordPress/gutenberg/pull/60456)) + +#### Patterns +- Add a "All Template Parts" section. ([60775](https://github.com/WordPress/gutenberg/pull/60775)) +- Back Compat: Add Patterns submenu for WordPress 6.4. ([60804](https://github.com/WordPress/gutenberg/pull/60804)) +- Patterns page: Add edit & view revision actions to parts. ([60659](https://github.com/WordPress/gutenberg/pull/60659)) +- Remove "Template parts" sidebar group. ([60359](https://github.com/WordPress/gutenberg/pull/60359)) +- Site Editor: Support starter patterns. ([60745](https://github.com/WordPress/gutenberg/pull/60745)) + +#### Synced Patterns +- Adjust allow pattern overrides UX flow. ([60769](https://github.com/WordPress/gutenberg/pull/60769)) +- Consolidate "bound block" color and "synced" colors. ([60617](https://github.com/WordPress/gutenberg/pull/60617)) +- Improve override indication for editable blocks in synced patterns. ([60599](https://github.com/WordPress/gutenberg/pull/60599)) +- Refine rename flow for blocks with overrides. ([60234](https://github.com/WordPress/gutenberg/pull/60234)) + +#### Zoom Out +- Adjust block selection button. ([60348](https://github.com/WordPress/gutenberg/pull/60348)) +- Animation: Avoid fixed width when animating the secondary sidebar. ([60693](https://github.com/WordPress/gutenberg/pull/60693)) +- Introduce section container selection when assembling patterns (zoom out mode). ([59249](https://github.com/WordPress/gutenberg/pull/59249)) +- Update zoom out scale. ([60618](https://github.com/WordPress/gutenberg/pull/60618)) + +#### Block Library +- Add loading state on image upload in featured image, Site logo and Cover blocks. ([59519](https://github.com/WordPress/gutenberg/pull/59519)) +- File: Use HTML API to update the PDF preview label. ([60494](https://github.com/WordPress/gutenberg/pull/60494)) +- Navigation block: Add current-menu-item class for post type archive. ([57808](https://github.com/WordPress/gutenberg/pull/57808)) +- Remove block renaming control from advanced inspector controls group. ([60453](https://github.com/WordPress/gutenberg/pull/60453)) + +#### Data Views +- Add ability to display fields as a badge in grid layout. ([60284](https://github.com/WordPress/gutenberg/pull/60284)) +- Data views table row: Make checkboxes and actions visible on touch devices. ([60829](https://github.com/WordPress/gutenberg/pull/60829)) +- DataViews: Make the experiment about custom views. ([60813](https://github.com/WordPress/gutenberg/pull/60813)) + +#### Layout +- Add a Row control to grid layout in manual mode. ([60652](https://github.com/WordPress/gutenberg/pull/60652)) +- Apply negative margins for alignfull children of blocks with custom padding set. ([60716](https://github.com/WordPress/gutenberg/pull/60716)) +- Try reducing specificity of layout style selectors. ([60228](https://github.com/WordPress/gutenberg/pull/60228)) + +#### Block Editor +- Remove animation from InlineLinkUI. ([60575](https://github.com/WordPress/gutenberg/pull/60575)) +- Remove root appender. ([60697](https://github.com/WordPress/gutenberg/pull/60697)) +- Try: Add new `textAlign` block support. ([59531](https://github.com/WordPress/gutenberg/pull/59531)) + +#### Global Styles +- Background image: Display default background size value in global styles. ([60490](https://github.com/WordPress/gutenberg/pull/60490)) +- Background UI control labels. ([60264](https://github.com/WordPress/gutenberg/pull/60264)) +- Use text and button background color for color indicators. ([59514](https://github.com/WordPress/gutenberg/pull/59514)) + +#### Font Library +- Change Spinner to ProgressBar component. ([60570](https://github.com/WordPress/gutenberg/pull/60570)) + +#### Interactivity API +- Include `preact/debug` when `SCRIPT_DEBUG` is enabled. ([60514](https://github.com/WordPress/gutenberg/pull/60514)) + + +### New APIs + +#### Extensibility +- Editor: Support PluginPostStatusInfo Slot in the site editor. ([60814](https://github.com/WordPress/gutenberg/pull/60814)) +- Editor: Unify PluginMoreMenuItem API between post and site editors. ([60778](https://github.com/WordPress/gutenberg/pull/60778)) + - Fix: Use core instead of core/editor on normalizeComplementaryAreaScope. ([60821](https://github.com/WordPress/gutenberg/pull/60821)) +- Editor: Unify PluginSidebarMoreMenuItem. ([60853](https://github.com/WordPress/gutenberg/pull/60853)) +- Editor: Unify the PluginSidebar slot between post and site editors. ([60815](https://github.com/WordPress/gutenberg/pull/60815)) + + +### Bug Fixes + +- Fix: Add types to useSuspenseSelect. ([60733](https://github.com/WordPress/gutenberg/pull/60733)) +- Fix experimental useHasRecursion deprecation. ([60451](https://github.com/WordPress/gutenberg/pull/60451)) +- Fix translatable string in pagination modal. ([60742](https://github.com/WordPress/gutenberg/pull/60742)) +- Interactivity: Return useMemo and useCallback hooks. ([60474](https://github.com/WordPress/gutenberg/pull/60474)) +- Only show block icon in toolbar for contentOnly blocks when block is a synced block. ([60647](https://github.com/WordPress/gutenberg/pull/60647)) +- Patterns: Guard for unknown pattern in server-side resolver. ([60464](https://github.com/WordPress/gutenberg/pull/60464)) +- Snackbar: Make the `explicitDismiss` string translatable. ([60368](https://github.com/WordPress/gutenberg/pull/60368)) +- Update standardisation of 'Navigation Menu' to have both words capitalised in user-facing menus. ([60262](https://github.com/WordPress/gutenberg/pull/60262)) + - Standardise capitalisation of Navigation Menu in sidebar. ([60527](https://github.com/WordPress/gutenberg/pull/60527)) + +#### Block Library +- Embed: Avoid retrying valid URLs. ([60655](https://github.com/WordPress/gutenberg/pull/60655)) +- File: Mark update for setting default label as non-persistent. ([60492](https://github.com/WordPress/gutenberg/pull/60492)) +- Fix don't close overlay menu when focus leaves submenu. ([60406](https://github.com/WordPress/gutenberg/pull/60406)) +- Fix pattern block recursion handling. ([60452](https://github.com/WordPress/gutenberg/pull/60452)) +- Image: Fix cropper resize on align change (react-easy-crop upgrade). ([60581](https://github.com/WordPress/gutenberg/pull/60581)) +- Latest Posts: Remove wrapper div and apply consistent class. ([60728](https://github.com/WordPress/gutenberg/pull/60728)) +- List: Disable edit as HTML support. ([55656](https://github.com/WordPress/gutenberg/pull/55656)) +- Media & Text: Hide the alt text option for featured images. ([60496](https://github.com/WordPress/gutenberg/pull/60496)) +- Post title: Re-add the paragraph level (without UI). ([60548](https://github.com/WordPress/gutenberg/pull/60548)) +- Pullquote: Reduce specificity of padding rule to avoid conflicts with global styles. ([60649](https://github.com/WordPress/gutenberg/pull/60649)) +- Separator block: Reduce default border styles to avoid conflicts with global styles. ([60740](https://github.com/WordPress/gutenberg/pull/60740)) + +#### Site Editor +- Chore: Fix missing comma on welcome guide styles. ([60596](https://github.com/WordPress/gutenberg/pull/60596)) +- Fallback to URL when site title is empty. ([60885](https://github.com/WordPress/gutenberg/pull/60885)) +- Fix activating a theme in site editor when previewing. ([60699](https://github.com/WordPress/gutenberg/pull/60699)) +- Fix site icon animation. ([60419](https://github.com/WordPress/gutenberg/pull/60419)) +- Fix small regression on the resize handle. ([60427](https://github.com/WordPress/gutenberg/pull/60427)) +- Fix the removePropertyFromObject function throws an error if the object is null. ([60831](https://github.com/WordPress/gutenberg/pull/60831)) +- Fix: Style issue on page actions button. ([60592](https://github.com/WordPress/gutenberg/pull/60592)) +- Pattern page: Fix deps for `onActionPerformed` useCallback. ([60784](https://github.com/WordPress/gutenberg/pull/60784)) +- Remove outdated border radius animation. ([60454](https://github.com/WordPress/gutenberg/pull/60454)) +- Router: Load proper sidebar for `/wp_template`. ([60850](https://github.com/WordPress/gutenberg/pull/60850)) +- [Site Editor]: Fix ability to edit trashed pages. ([60236](https://github.com/WordPress/gutenberg/pull/60236)) + +#### Post Editor +- Editor: Do not render publish time and post status panels in design post types. ([60857](https://github.com/WordPress/gutenberg/pull/60857)) +- Editor: Fix post status label styles for low-capability users. ([60854](https://github.com/WordPress/gutenberg/pull/60854)) +- Fix display of shortcut to add non breaking space in the post editor. ([60625](https://github.com/WordPress/gutenberg/pull/60625)) +- Fix: Action button alignment on details panel. ([60773](https://github.com/WordPress/gutenberg/pull/60773)) +- Fix: Action order is different from inspector and dataviews. ([60877](https://github.com/WordPress/gutenberg/pull/60877)) +- Fix: Do not show pattern and template actions on the post editor. ([60568](https://github.com/WordPress/gutenberg/pull/60568)) +- Fix: Missing items parameter and or missing onActionPerformed calls. ([60753](https://github.com/WordPress/gutenberg/pull/60753)) +- Fix: Trash Post action and permanently delete post action do not show errors on single item. ([60597](https://github.com/WordPress/gutenberg/pull/60597)) +- Post Editor Header: Make block toolbar toggle button focus visible. ([59781](https://github.com/WordPress/gutenberg/pull/59781)) + +#### Block Editor +- Avoid errors when a block variation icon is an object. ([60766](https://github.com/WordPress/gutenberg/pull/60766)) +- Fix external link indicator in Link Control. ([60439](https://github.com/WordPress/gutenberg/pull/60439)) +- Fix for isPossibleTransformForSource handling selecting inexistent block. ([59410](https://github.com/WordPress/gutenberg/pull/59410)) +- Fix stuck dragging mode in UI in Firefox when dealing with deeply nested lists. ([60845](https://github.com/WordPress/gutenberg/pull/60845)) +- Prevents delete key from undoing automatic changes. ([60858](https://github.com/WordPress/gutenberg/pull/60858)) +- Raw Handling - msListIgnore - Check attributes are valid. ([60375](https://github.com/WordPress/gutenberg/pull/60375)) + +#### Data Views +- DataViews: Fix typing in combobox filter. ([60819](https://github.com/WordPress/gutenberg/pull/60819)) +- Fix default layout configuration in pages list. ([60407](https://github.com/WordPress/gutenberg/pull/60407)) +- Fix pattern titles. ([60640](https://github.com/WordPress/gutenberg/pull/60640)) + +#### Zoom Out +- Don't allow shuffle for locked patterns. ([60381](https://github.com/WordPress/gutenberg/pull/60381)) +- Prevent exiting Zoom Out mode from stealing focus. ([60441](https://github.com/WordPress/gutenberg/pull/60441)) +- Respect reduced motion when engaging zoom out mode. ([60808](https://github.com/WordPress/gutenberg/pull/60808)) + +#### Font Library +- Avoid overriding custom settings on font library save. ([60438](https://github.com/WordPress/gutenberg/pull/60438)) +- Fix modal scrollbar. ([60641](https://github.com/WordPress/gutenberg/pull/60641)) +- I18N: Add context to 'Library' string. ([60520](https://github.com/WordPress/gutenberg/pull/60520)) + +#### Components +- Fix link control link preview when it displays long URLs. ([60890](https://github.com/WordPress/gutenberg/pull/60890)) +- ProgressBar: Fix CSS variable with invalid value. ([60576](https://github.com/WordPress/gutenberg/pull/60576)) + +#### Layout +- Always add semantic classes. ([60668](https://github.com/WordPress/gutenberg/pull/60668)) +- Don't output base flow and constrained layout rules on themes without theme.json. ([60764](https://github.com/WordPress/gutenberg/pull/60764)) +- Fix responsive column span logic on the front end. ([60976](https://github.com/WordPress/gutenberg/pull/60976)) +- Restore classic auto margin rule to its previous specificity. ([60802](https://github.com/WordPress/gutenberg/pull/60802)) + +#### Interactivity API +- Allow multiple event handlers for the same type with `data-wp-on`. ([60661](https://github.com/WordPress/gutenberg/pull/60661)) +- Update the query block to permit non-core interactive blocks. ([60006](https://github.com/WordPress/gutenberg/pull/60006)) + +#### Templates API +- Fix static posts page setting resolved template. ([60608](https://github.com/WordPress/gutenberg/pull/60608)) +- Fix: Honor 'template_hierarchy' filters on template fallbacks. ([60377](https://github.com/WordPress/gutenberg/pull/60377)) + +#### Distraction Free +- Only show inserter in document tools if DFM is off. ([60426](https://github.com/WordPress/gutenberg/pull/60426)) +- Remove alpha from edit post header. ([60431](https://github.com/WordPress/gutenberg/pull/60431)) + +#### REST API +- Fix PHP notice triggered by 'gutenberg_update_initial_settings'. ([60862](https://github.com/WordPress/gutenberg/pull/60862)) + +#### Global Styles +- Editor styles: Delete duplicate backwards compat CSS custom properties. ([60400](https://github.com/WordPress/gutenberg/pull/60400)) +- Fix browser warning regarding highlight colors. ([60555](https://github.com/WordPress/gutenberg/pull/60555)) + +### Accessibility + +- Details Block: remove `overflow:Hidden` style. ([60270](https://github.com/WordPress/gutenberg/pull/60270)) +- Do not render pattern aria description if not button is rendered. ([60653](https://github.com/WordPress/gutenberg/pull/60653)) +- Fix inserter pattern pagination focus loss. ([60620](https://github.com/WordPress/gutenberg/pull/60620)) +- Make sure Social icons links aren't empty and improve UI clarity. ([60047](https://github.com/WordPress/gutenberg/pull/60047)) + +### Performance + +- Add null check to prevent errors in `get_block_template` filter. ([60491](https://github.com/WordPress/gutenberg/pull/60491)) +- Block preview: Build in async rendering. ([60425](https://github.com/WordPress/gutenberg/pull/60425)) +- Editor canvas: Reduces resize listeners. ([60682](https://github.com/WordPress/gutenberg/pull/60682)) +- Layout support: Avoid two block editor store subs. ([60612](https://github.com/WordPress/gutenberg/pull/60612)) +- Optimize the rendering of the EditorStyles component. ([60493](https://github.com/WordPress/gutenberg/pull/60493)) +- Post Title: Avoid accidental types requests. ([60531](https://github.com/WordPress/gutenberg/pull/60531)) +- Preview: Skip rendering rich text. ([60544](https://github.com/WordPress/gutenberg/pull/60544)) +- Previews: Avoid unneeded block selectors. ([60543](https://github.com/WordPress/gutenberg/pull/60543)) +- Site Editor: Close the editor sidebar by default. ([60820](https://github.com/WordPress/gutenberg/pull/60820)) +- Zoom-out: Scale should be stable function. ([60580](https://github.com/WordPress/gutenberg/pull/60580)) +- getEntityRecords: Batch actions. ([60591](https://github.com/WordPress/gutenberg/pull/60591)) + +#### Block Library +- Avoid calling getBlocks selector for navigation link blocks. ([60458](https://github.com/WordPress/gutenberg/pull/60458)) +- Image cropper: Remove clientWidth prop with useResizeObserver. ([60674](https://github.com/WordPress/gutenberg/pull/60674)) +- Navigation block: Avoid selector + style recalc on mount. ([60572](https://github.com/WordPress/gutenberg/pull/60572)) +- Pattern block: Avoid fetching all reusable blocks on mount. ([60310](https://github.com/WordPress/gutenberg/pull/60310)) +- Post Featured Image: Optimize store subscriptions. ([60770](https://github.com/WordPress/gutenberg/pull/60770)) + +#### Site Editor +- Optimize the AddTemplate component used in data views pages. ([60586](https://github.com/WordPress/gutenberg/pull/60586)) +- Sidebar slide animation: Replace motion.div with CSS animation. ([60849](https://github.com/WordPress/gutenberg/pull/60849)) + +### Documentation + +- Add `AutosaveMonitor` component JSDoc and populate `README` with auto-gen documentation. ([60882](https://github.com/WordPress/gutenberg/pull/60882)) +- Add documentation for `disableLineBreaks` property of `RichText`. ([56284](https://github.com/WordPress/gutenberg/pull/56284)) +- Added Documentation for PostExcerptCheck. ([60864](https://github.com/WordPress/gutenberg/pull/60864)) +- Added links to related components. ([60726](https://github.com/WordPress/gutenberg/pull/60726)) +- Correct link to the theme json reference. ([60517](https://github.com/WordPress/gutenberg/pull/60517)) +- DimensionControl: Fix story configuration. ([60703](https://github.com/WordPress/gutenberg/pull/60703)) +- Docs: Fix typos in interactivity API reference. ([60870](https://github.com/WordPress/gutenberg/pull/60870)) +- Docs: Update wording in Block Editor Handbook to reflect that all examples now use JSX. ([56315](https://github.com/WordPress/gutenberg/pull/56315)) +- Fix: Grammar typo on packages/dataviews/src/search-widget.js. ([60588](https://github.com/WordPress/gutenberg/pull/60588)) +- Fix: Link to the block building tutorial. ([60518](https://github.com/WordPress/gutenberg/pull/60518)) +- Fixes a link to the getEntityRecord documentation. ([60823](https://github.com/WordPress/gutenberg/pull/60823)) +- Improve documentation for block variation `isActive` property. ([60801](https://github.com/WordPress/gutenberg/pull/60801)) +- Update: Hardcoded documentation link to a branch that does not exist. ([60671](https://github.com/WordPress/gutenberg/pull/60671)) +- Update: Reference editor scope instead of edit-site, edit-post on interface package documentation. ([60818](https://github.com/WordPress/gutenberg/pull/60818)) +- [Create Block] Adding documentation for the transformer property. ([60445](https://github.com/WordPress/gutenberg/pull/60445)) + + +### Code Quality + +- Added @return after @global in php doc. ([60611](https://github.com/WordPress/gutenberg/pull/60611)) +- Blocks: Remove client-side polyfill for 'selectors'. ([60846](https://github.com/WordPress/gutenberg/pull/60846)) +- [Block Bindings] Don't use hooks. ([60724](https://github.com/WordPress/gutenberg/pull/60724)) +- Chore: Fix: Wrong JSDOC for an action return. ([60786](https://github.com/WordPress/gutenberg/pull/60786)) +- Chore: Simplify some CSS margin rules. ([60816](https://github.com/WordPress/gutenberg/pull/60816)) +- Editor: Serve as a proxy for the interface package. ([60748](https://github.com/WordPress/gutenberg/pull/60748)) +- Editor: Unify the auto-switch sidebars behavior. ([60869](https://github.com/WordPress/gutenberg/pull/60869)) +- Editor: Unify the keyboard shortcuts modal. ([60866](https://github.com/WordPress/gutenberg/pull/60866)) +- Editor: Unify the names of the sidebars between edit post and edit site. ([60856](https://github.com/WordPress/gutenberg/pull/60856)) +- Editor: Unify the preferences modal name. ([60871](https://github.com/WordPress/gutenberg/pull/60871)) +- Fix: Remove unused CSS for TemplatePartHint. ([60852](https://github.com/WordPress/gutenberg/pull/60852)) +- Fix: Remove unused css from page panels styles. ([60774](https://github.com/WordPress/gutenberg/pull/60774)) +- Fix: Font Library typo. ([60751](https://github.com/WordPress/gutenberg/pull/60751)) +- Fix: Remove unused CSS code from the site editor. ([60662](https://github.com/WordPress/gutenberg/pull/60662)) +- Interactivity API refactor to TypeScript (utils & kebabToCamelCase). ([60149](https://github.com/WordPress/gutenberg/pull/60149)) +- Reexport createSelector from data package. ([60370](https://github.com/WordPress/gutenberg/pull/60370)) +- Refactor: UseBlockTools cleanup. ([59450](https://github.com/WordPress/gutenberg/pull/59450)) +- Remove comment that no longer applies about appearance-tools support. ([60844](https://github.com/WordPress/gutenberg/pull/60844)) +- Reuse and unify post and page actions, accross the different use cases. ([60486](https://github.com/WordPress/gutenberg/pull/60486)) +- Test: Validate block & theme json. ([57374](https://github.com/WordPress/gutenberg/pull/57374)) +- Tests: Shard JS unit tests. ([60045](https://github.com/WordPress/gutenberg/pull/60045)) +- Tests: Share JavaScript build assets across PHP workflows. ([60428](https://github.com/WordPress/gutenberg/pull/60428)) +- Update: Avoid two useSelect calls on PostActions. ([60752](https://github.com/WordPress/gutenberg/pull/60752)) +- Update: Make content locking related selectors private. ([60827](https://github.com/WordPress/gutenberg/pull/60827)) +- Update: Move template actions to the editor store. ([60395](https://github.com/WordPress/gutenberg/pull/60395)) +- Update: Remove keyCode usage from dataviews package. ([60585](https://github.com/WordPress/gutenberg/pull/60585)) +- Update: Use util getVariationClassName instead of computing the variation inline. ([60664](https://github.com/WordPress/gutenberg/pull/60664)) + +#### Components +- Deprecate `reduceMotion` util. ([60839](https://github.com/WordPress/gutenberg/pull/60839)) +- Navigation: Soft deprecate component. ([59182](https://github.com/WordPress/gutenberg/pull/59182)) +- NavigatorProvider: Move the same-location check to the goTo function. ([60767](https://github.com/WordPress/gutenberg/pull/60767)) +- ObservableMap: Optimize unsubscribe and add unit tests. ([60892](https://github.com/WordPress/gutenberg/pull/60892)) +- Remove CSS hack for Internet Explorer 11. ([60727](https://github.com/WordPress/gutenberg/pull/60727)) + +#### Post Editor +- Editor: Optimize the 'PostSlug' component. ([60422](https://github.com/WordPress/gutenberg/pull/60422)) +- Editor: Use hook instead of HoC in 'ThemeSupportCheck'. ([60807](https://github.com/WordPress/gutenberg/pull/60807)) +- Editor: Use hooks instead of HoCs in 'PostTrashCheck'. ([60380](https://github.com/WordPress/gutenberg/pull/60380)) +- [Editor]:Get post content in PostContentInfo component. ([60743](https://github.com/WordPress/gutenberg/pull/60743)) + +#### Data Views +- DataViews: Remove `onDetailsChange` event. ([60387](https://github.com/WordPress/gutenberg/pull/60387)) +- Rename displayAsColumnFields to columnFields API. ([60504](https://github.com/WordPress/gutenberg/pull/60504)) +- Simplify visually hidden label. ([60835](https://github.com/WordPress/gutenberg/pull/60835)) + +#### Block Editor +- Refactor Link UI States. ([59762](https://github.com/WordPress/gutenberg/pull/59762)) +- Switching pattern categories inserter to Tabs component with arrow key navigation. ([60257](https://github.com/WordPress/gutenberg/pull/60257)) + +### Tools + +- Update @talldan in codeowners file, remove from edit-widgets package. ([60800](https://github.com/WordPress/gutenberg/pull/60800)) + +#### Testing +- Add end-to-end test for activating themes in site editor. ([60707](https://github.com/WordPress/gutenberg/pull/60707)) +- Automated Testing: Update end-to-end test npm commands. ([60376](https://github.com/WordPress/gutenberg/pull/60376)) +- Fix flaky Site Editor URL navigation end-to-end test. ([60675](https://github.com/WordPress/gutenberg/pull/60675)) +- PHP unit test workflow: Try removing 7.0 and 7.1. ([60686](https://github.com/WordPress/gutenberg/pull/60686)) +- Perf: Improve way we measure template loading by adding posts. ([60516](https://github.com/WordPress/gutenberg/pull/60516)) +- Performance Tests: I'm tired of doing head math 😊. ([60509](https://github.com/WordPress/gutenberg/pull/60509)) +- Upgrade Playwright to v1.43. ([60635](https://github.com/WordPress/gutenberg/pull/60635)) +- tip: Remove unecessary delay in tests except where needed. ([60897](https://github.com/WordPress/gutenberg/pull/60897)) + +#### Build Tooling +- Dependencies: Upgrade babel. ([57311](https://github.com/WordPress/gutenberg/pull/57311)) +- Upgrade simple-git dependency. ([59915](https://github.com/WordPress/gutenberg/pull/59915)) +- Update Typescript to 5.4.5. ([60793](https://github.com/WordPress/gutenberg/pull/60793)) + +## First time contributors + +The following PRs were merged by first time contributors: + +- @asheshmagar: Font library: Fix typo. ([60751](https://github.com/WordPress/gutenberg/pull/60751)) +- @DaniGuardiola: ProgressBar: Moved width to CSS var for performance. ([60388](https://github.com/WordPress/gutenberg/pull/60388)) +- @garridinsi: Interactivity API refactor to TypeScript (utils & kebabToCamelCase). ([60149](https://github.com/WordPress/gutenberg/pull/60149)) +- @xhemals: Update standardization of the 'Navigation Menu' to have both words capitalized in user-facing menus. ([60262](https://github.com/WordPress/gutenberg/pull/60262)), Standardise capitalization of the Navigation Menu in the sidebar. ([60527](https://github.com/WordPress/gutenberg/pull/60527)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @afercia @andrewserong @arthur791004 @artpi @asheshmagar @atachibana @carolinan @colinduwe @colorful-tones @DaniGuardiola @DAreRodz @draganescu @ellatrix @fabiankaegy @flexseth @garridinsi @geriux @getdave @ixkaito @jameskoster @jasmussen @jeryj @johnhooks @jorgefilipecosta @jsnajdr @kevin940726 @Mamaduka @matiasbenedetto @mhkuu @mikachan @mirka @noisysocks @ntsekouras @oandregal @ocean90 @okmttdhr @prajapatisagar @ramonjd @richtabor @ryanwelcher @scruffian @shail-mehta @shimotmk @simonhammes @sirreal @Soean @sunil25393 @t-hamano @talldan @tellthemachines @tyxla @xhemals @youknowriad + + += 18.1.2 = + +## Bug Fixes + +- Restore classic auto margin rule to its previous specificity ([60802](https://github.com/WordPress/gutenberg/pull/60802)) +- Fix the removePropertyFromObject function throws an error if the object is null ([60831](https://github.com/WordPress/gutenberg/pull/60831)) + +## Contributors + +The following contributors merged PRs in this release: + +@tellthemachines @arthur791004 + + += 18.1.1 = + +## Bug Fixes + +- Add null check to prevent errors in `get_block_template` filter ([60491](https://github.com/WordPress/gutenberg/pull/60491)) +- Fix activating a theme in site editor when previewing ([60699](https://github.com/WordPress/gutenberg/pull/60699)) + +## Contributors + +The following contributors merged PRs in this release: + +@okmttdhr @ntsekouras + + = 18.1.0 = ## Changelog diff --git a/docs/contributors/folder-structure.md b/docs/contributors/folder-structure.md index 98eccf1b2029ba..cbad182a58f447 100644 --- a/docs/contributors/folder-structure.md +++ b/docs/contributors/folder-structure.md @@ -75,9 +75,19 @@ The following snippet explains how the Gutenberg repository is structured omitti β”œβ”€β”€ docs/*.md β”‚ Set of documentation pages composing the [Block editor handbook](https://developer.wordpress.org/block-editor/). β”‚ + β”œβ”€β”€ platform-docs + β”‚ Documentation website targetted to non WordPress developpers + β”‚ using Gutenberg in their own applications. + β”‚ Deployed on [https://wordpress.org/gutenberg-framework/](https://wordpress.org/gutenberg-framework/). + β”‚ + β”‚ β”œβ”€β”€ lib β”‚ PHP Source code of the Gutenberg plugin. β”‚ + β”œβ”€β”€ lib/compact/wordpress-x.x + β”‚ PHP code that was include in WordPress ont the WordPrexx X.X version. + β”‚ It is kept to ensure plugin compatibility with older WordPress versions. + β”‚ β”œβ”€β”€ packages β”‚ Source code of the WordPress packages. β”‚ Packages can be: @@ -107,10 +117,6 @@ The following snippet explains how the Gutenberg repository is structured omitti β”œβ”€β”€ packages/{packageName}/src/**/{ComponentName}/stories/*.js β”‚ Component Stories to load on the Gutenberg storybook. β”‚ - β”œβ”€β”€ packages/e2e-tests - β”‚ End-2-end tests of the Gutenberg plugin. - β”‚ Distributed as a package for potential reuse in Core and other plugins. - β”‚ β”œβ”€β”€ phpunit β”‚ Unit tests for the PHP code of the Gutenberg plugin. β”‚ @@ -123,11 +129,17 @@ The following snippet explains how the Gutenberg repository is structured omitti β”œβ”€β”€ test/native β”‚ Configuration for the Gutenberg Mobile unit tests. β”‚ - └── test/unit + β”œβ”€β”€ test/unit β”‚ Configuration for the Packages unit tests. β”‚ - └── tools/eslint + β”œβ”€β”€ test/e2e + β”‚ End-2-end tests of the Gutenberg plugin. + β”‚ + β”œβ”€β”€ test/performance + β”‚ Performance metrics. Results are tracked on the [Gutenberg performance dashboard](https://codevitals.run/project/gutenberg). + β”‚ + β”œβ”€β”€ tools/eslint β”‚ Configuration files for the ESLint linter. β”‚ - └── tools/webpack + β”œβ”€β”€ tools/webpack β”‚ Configuration files for the webpack build. diff --git a/docs/getting-started/devenv/get-started-with-wp-scripts.md b/docs/getting-started/devenv/get-started-with-wp-scripts.md index b6271620514df4..16f1bbc6015b5b 100644 --- a/docs/getting-started/devenv/get-started-with-wp-scripts.md +++ b/docs/getting-started/devenv/get-started-with-wp-scripts.md @@ -4,7 +4,7 @@ The [`@wordpress/scripts`](https://developer.wordpress.org/block-editor/referenc A JavaScript build step refers to the process of transforming, bundling, and optimizing JavaScript source code and related assets into a format suitable for production environments. These build steps often take modern JavaScript (ESNext and JSX) and convert it to a version compatible with most browsers. They can also bundle multiple files into one, minify the code to reduce file size and perform various other tasks to optimize the code. -You will typically be working with ESNext and JSX when building for the Block Editor, and most examples in the Block Editor Handbook are written in these syntaxes. Learning how to set up a build step is essential. However, configuring the necessary tools like [webpack](https://webpack.js.org/), [Babel](https://babeljs.io/), and [ESLint](https://eslint.org/) can become complex. This is where `wp-scripts` comes in. +You will typically be working with ESNext and JSX when building for the Block Editor, and all examples in the Block Editor Handbook are written in these syntaxes. Learning how to set up a build step is essential. However, configuring the necessary tools like [webpack](https://webpack.js.org/), [Babel](https://babeljs.io/), and [ESLint](https://eslint.org/) can become complex. This is where `wp-scripts` comes in. Here are a few things that `wp-scripts` can do: diff --git a/docs/getting-started/fundamentals/block-in-the-editor.md b/docs/getting-started/fundamentals/block-in-the-editor.md index 85a6dfe506db3e..f7357def5ec2df 100644 --- a/docs/getting-started/fundamentals/block-in-the-editor.md +++ b/docs/getting-started/fundamentals/block-in-the-editor.md @@ -1,6 +1,6 @@ # The block in the Editor -The Block Editor is a React Single Page Application (SPA). Every block in the Editor is displayed through a React component defined in the `edit` property of the settings object used to [register the block](https://developer.wordpress.org/block-editor/getting-started/fundamentals/registration-of-a-block/#registration-of-the-block-with-javascript-client-side) on the client. +The Block Editor is a React Single Page Application (SPA). Every block in the Editor is displayed through a React component defined in the `edit` property of the settings object used to [register the block](https://developer.wordpress.org/block-editor/getting-started/fundamentals/registration-of-a-block/#registering-a-block-with-javascript-client-side) on the client. The `props` object received by the block's `Edit` React component includes: @@ -164,4 +164,4 @@ Block controls rendered in both the toolbar and sidebar will also be available w - [@wordpress/block-editor](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/) - [@wordpress/components](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-components/) - [`InspectorControls`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inspector-controls/README.md) -- [`BlockControls`](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-editor/src/components/block-controls) \ No newline at end of file +- [`BlockControls`](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-editor/src/components/block-controls) diff --git a/docs/how-to-guides/data-basics/3-building-an-edit-form.md b/docs/how-to-guides/data-basics/3-building-an-edit-form.md index 68c87381701515..34136ff4080800 100644 --- a/docs/how-to-guides/data-basics/3-building-an-edit-form.md +++ b/docs/how-to-guides/data-basics/3-building-an-edit-form.md @@ -120,7 +120,7 @@ Great! We now have a basic user interface to work with. We want the `EditPageForm` to display the title of the currently edited page. You may have noticed that it doesn't receive a `page` prop, only `pageId`. That's okay. Gutenberg Data allows us to easily access entity records from any component. -In this case, we need to use the [`getEntityRecord`](/docs/reference-guides/data/data-core/#getentityrecord) selector. The list of records is already available thanks to the `getEntityRecords` call in `MyFirstApp`, so there won't even be any additional HTTP requests involved – we'll get the cached record right away. +In this case, we need to use the [`getEntityRecord`](/docs/reference-guides/data/data-core.md#getentityrecord) selector. The list of records is already available thanks to the `getEntityRecords` call in `MyFirstApp`, so there won't even be any additional HTTP requests involved – we'll get the cached record right away. Here's how you can try it in your browser's dev tools: diff --git a/docs/how-to-guides/platform/custom-block-editor.md b/docs/how-to-guides/platform/custom-block-editor.md index 65f8c412c45d33..a7abb00adacec6 100644 --- a/docs/how-to-guides/platform/custom-block-editor.md +++ b/docs/how-to-guides/platform/custom-block-editor.md @@ -24,7 +24,7 @@ By the end of this article, you will have a solid understanding of the block edi ## Code syntax -The code snippets in this guide use JSX syntax. However, you could use plain JavaScript if you prefer. However, once familiar with JSX, many developers find it easier to read and write, so most code examples in the Block Editor Handbook use this syntax. +The code snippets in this guide use JSX syntax. However, you could use plain JavaScript if you prefer. However, once familiar with JSX, many developers find it easier to read and write, so all code examples in the Block Editor Handbook use this syntax. ## What you're going to be building diff --git a/docs/how-to-guides/plugin-sidebar-0.md b/docs/how-to-guides/plugin-sidebar-0.md index 5a6a1efe84f80d..76ef54bb9d3082 100644 --- a/docs/how-to-guides/plugin-sidebar-0.md +++ b/docs/how-to-guides/plugin-sidebar-0.md @@ -16,7 +16,7 @@ The tutorial assumes you have an existing plugin setup and are ready to add PHP ### Step 1: Get a sidebar up and running -The first step is to tell the editor that there is a new plugin that will have its own sidebar. Use the [registerPlugin](/packages/plugins/README.md), [PluginSidebar](/packages/edit-post/README.md#pluginsidebar), and [createElement](/packages/element/README.md) utilities provided by the `@wordpress/plugins`, `@wordpress/edit-post`, and `react` packages, respectively. +The first step is to tell the editor that there is a new plugin that will have its own sidebar. Use the [registerPlugin](/packages/plugins/README.md), [PluginSidebar](/packages/editor/README.md#pluginsidebar), and [createElement](/packages/element/README.md) utilities provided by the `@wordpress/plugins`, `@wordpress/editor`, and `react` packages, respectively. Add the following code to a JavaScript file called `plugin-sidebar.js` and save it within your plugin's directory: @@ -24,7 +24,7 @@ Add the following code to a JavaScript file called `plugin-sidebar.js` and save ( function ( wp, React ) { var el = React.createElement; var registerPlugin = wp.plugins.registerPlugin; - var PluginSidebar = wp.editPost.PluginSidebar; + var PluginSidebar = wp.editor.PluginSidebar; registerPlugin( 'my-plugin-sidebar', { render: function () { @@ -57,7 +57,7 @@ function sidebar_plugin_register() { wp_register_script( 'plugin-sidebar-js', plugins_url( 'plugin-sidebar.js', __FILE__ ), - array( 'wp-plugins', 'wp-edit-post', 'react' ) + array( 'wp-plugins', 'wp-editor', 'react' ) ); } add_action( 'init', 'sidebar_plugin_register' ); @@ -82,7 +82,7 @@ To visualize and edit the meta field value you'll use an input component. The `@ ( function ( wp ) { var el = React.createElement; var registerPlugin = wp.plugins.registerPlugin; - var PluginSidebar = wp.editPost.PluginSidebar; + var PluginSidebar = wp.editor.PluginSidebar; var TextControl = wp.components.TextControl; registerPlugin( 'my-plugin-sidebar', { @@ -144,7 +144,7 @@ function sidebar_plugin_register() { array( 'react', 'wp-plugins', - 'wp-edit-post', + 'wp-editor', 'wp-components' ) ); @@ -202,7 +202,7 @@ With the field available in the editor store, it can now be surfaced to the UI. ( function ( wp ) { var el = React.createElement; var registerPlugin = wp.plugins.registerPlugin; - var PluginSidebar = wp.editPost.PluginSidebar; + var PluginSidebar = wp.editor.PluginSidebar; var TextControl = wp.components.TextControl; var MetaBlockField = function () { @@ -243,7 +243,7 @@ The `useSelect` function is used to fetch data when the component loads and will ( function ( wp ) { var el = React.createElement; var registerPlugin = wp.plugins.registerPlugin; - var PluginSidebar = wp.editPost.PluginSidebar; + var PluginSidebar = wp.editor.PluginSidebar; var Text = wp.components.TextControl; var useSelect = wp.data.useSelect; @@ -306,7 +306,7 @@ The `useDispatch` function takes a store name as its only argument and returns m ( function ( wp ) { var el = React.createElement; var registerPlugin = wp.plugins.registerPlugin; - var PluginSidebar = wp.editPost.PluginSidebar; + var PluginSidebar = wp.editor.PluginSidebar; var TextControl = wp.components.TextControl; var useSelect = wp.data.useSelect; var useDispatch = wp.data.useDispatch; diff --git a/docs/reference-guides/block-api/block-attributes.md b/docs/reference-guides/block-api/block-attributes.md index 935b38155f1e72..52a325ff9253de 100644 --- a/docs/reference-guides/block-api/block-attributes.md +++ b/docs/reference-guides/block-api/block-attributes.md @@ -375,9 +375,6 @@ Attribute definition: From here, meta attributes can be read and written by a block using the same interface as any attribute: - -{% JSX %} - ```js edit( { attributes, setAttributes } ) { function onChange( event ) { diff --git a/docs/reference-guides/block-api/block-deprecation.md b/docs/reference-guides/block-api/block-deprecation.md index 4d69d9d46843cd..0da85ee02d1ec0 100644 --- a/docs/reference-guides/block-api/block-deprecation.md +++ b/docs/reference-guides/block-api/block-deprecation.md @@ -23,7 +23,7 @@ It is also important to note that if a deprecation's `save` method imports addit For blocks with multiple deprecations, it may be easier to save each deprecation to a constant with the version of the block it applies to, and then add each of these to the block's `deprecated` array. The deprecations in the array should be in reverse chronological order. This allows the block editor to attempt to apply the most recent and likely deprecations first, avoiding unnecessary and expensive processing. -### Example: +**Example** ```js const v1 = {}; @@ -59,7 +59,7 @@ Deprecations are defined on a block type as its `deprecated` property, an array It's important to note that attributes, supports, and save are not automatically inherited from the current version, since they can impact parsing and serialization of a block, so they must be defined on the deprecated object in order to be processed during a migration. -### Example: +**Example** ```js const { registerBlockType } = wp.blocks; @@ -104,7 +104,7 @@ In the example above we updated the markup of the block to use a `div` instead o Sometimes, you need to update the attributes set to rename or modify old attributes. -### Example: +**Example** ```js @@ -155,7 +155,7 @@ In the example above we updated the markup of the block to use a `div` instead o Situations may exist where when migrating the block we may need to add or remove innerBlocks. E.g: a block wants to migrate a title attribute to a paragraph innerBlock. -### Example: +**Example** ```js const { registerBlockType } = wp.blocks; diff --git a/docs/reference-guides/block-api/block-variations.md b/docs/reference-guides/block-api/block-variations.md index 96930dc6b9b625..0440858810b65a 100644 --- a/docs/reference-guides/block-api/block-variations.md +++ b/docs/reference-guides/block-api/block-variations.md @@ -1,6 +1,6 @@ # Variations -The Block Variations API allows you to define multiple versions (variations) of a block. A block variation differs from the original block by a set of initial attributes or inner blocks. When you insert the block variation into the Editor, these attributes and/or inner blocks are applied. +The Block Variations API allows you to define multiple versions (variations) of a block. A block variation differs from the original block by a set of initial attributes or inner blocks. When you insert the block variation into the Editor, these attributes and/or inner blocks are applied. Variations are an excellent way to create iterations of existing blocks without building entirely new blocks from scratch. @@ -55,8 +55,8 @@ Block variations can be declared during a block's registration by providing the To create a variation for an existing block, such as a Core block, use `wp.blocks.registerBlockVariation()`. This function accepts the name of the block and the object defining the variation. ```js -wp.blocks.registerBlockVariation( - 'core/embed', +wp.blocks.registerBlockVariation( + 'core/embed', { name: 'custom-embed', attributes: { providerNameSlug: 'custom' }, @@ -66,7 +66,7 @@ wp.blocks.registerBlockVariation( ## Removing a block variation -Block variations can also be easily removed. To do so, use `wp.blocks.unregisterBlockVariation()`. This function accepts the name of the block and the `name` of the variation that should be unregistered. +Block variations can also be easily removed. To do so, use `wp.blocks.unregisterBlockVariation()`. This function accepts the name of the block and the `name` of the variation that should be unregistered. ```js wp.blocks.unregisterBlockVariation( 'core/embed', 'youtube' ); @@ -84,9 +84,9 @@ variations: [ name: 'blue', title: __( 'Blue Quote' ), isDefault: true, - attributes: { - color: 'blue', - className: 'is-style-blue-quote' + attributes: { + color: 'blue', + className: 'is-style-blue-quote' }, icon: 'format-quote', isActive: ( blockAttributes, variationAttributes ) => @@ -99,16 +99,16 @@ variations: [ By default, all variations will show up in the Inserter in addition to the original block type item. However, setting the `isDefault` flag for any variations listed will override the regular block type in the Inserter. This is a great tool for curating the Editor experience to your specific needs. -For example, if you want Media & Text block to display the image on the right by default, you could create a variation like this: +For example, if you want Media & Text block to display the image on the right by default, you could create a variation like this: ```js wp.blocks.registerBlockVariation( - 'core/media-text', + 'core/media-text', { name: 'media-text-media-right', title: __( 'Media & Text' ), isDefault: true, - attributes: { + attributes: { mediaPosition: 'right' } } @@ -125,20 +125,53 @@ The solution is to unregister the other variation before registering your variat ## Using `isActive` -While the `isActive` property is optional, you will often want to use it to display information about the block variation after the block has been inserted. For example, this API is used in `useBlockDisplayInformation` hook to fetch and display proper information in places like the `BlockCard` or `Breadcrumbs` components. +While the `isActive` property is optional, it's recommended. This API is used by the block editor to check which variation is active, and display the correct variation's title, icon and description when an instance of the variation is selected in the editor. + +If `isActive` is not set, the Editor cannot distinguish between an instance of the original block and your variation, so the original block information will be displayed. + +The property can be set to either a function or an array of strings (`string[]`). -If `isActive` is not set, the Editor cannot distinguish between the original block and your variation, so the original block information will be displayed. +The function version of this property accepts a block instance's `blockAttributes` as the first argument, and the `variationAttributes` declared for a variation as the second argument. These arguments can be used to determine if a variation is active by comparing them and returning a `true` or `false` (indicating whether this variation is inactive for this block instance). -The property can use either a function or an array of strings (`string[]`). The function accepts `blockAttributes` and `variationAttributes`, which can be used to determine if a variation is active. In the Embed block, the primary differentiator is the `providerNameSlug` attribute, so if you wanted to determine if the YouTube Embed variation was active, you could do something like this: +As an example, in the core Embed block, the `providerNameSlug` attribute is used to determine the embed provider (e.g. 'youtube' or 'twitter'). The variations may be declared like this: +```js +const variations = [ + { + name: 'twitter', + title: 'Twitter', + icon: embedTwitterIcon, + keywords: [ 'tweet', __( 'social' ) ], + description: __( 'Embed a tweet.' ), + patterns: [ /^https?:\/\/(www\.)?twitter\.com\/.+/i ], + attributes: { providerNameSlug: 'twitter', responsive: true }, + }, + { + name: 'youtube', + title: 'YouTube', + icon: embedYouTubeIcon, + keywords: [ __( 'music' ), __( 'video' ) ], + description: __( 'Embed a YouTube video.' ), + patterns: [ + /^https?:\/\/((m|www)\.)?youtube\.com\/.+/i, + /^https?:\/\/youtu\.be\/.+/i, + ], + attributes: { providerNameSlug: 'youtube', responsive: true }, + }, + // ... +] ``` + + The `isActive` function can compare the block instance value for `providerNameSlug` to the value declared in the variation's declaration (the values in the code snippet above) to determine which embed variation is active: + +```js isActive: ( blockAttributes, variationAttributes ) => blockAttributes.providerNameSlug === variationAttributes.providerNameSlug, ``` -You can also use a `string[]` to tell which attributes should be compared as a shorthand. Each attribute will be checked and the variation will be active if all of them match. Using the same example of the YouTube Embed variation, the string version would look like this: +The `string[]` version is used to declare which attributes should be compared as a shorthand. Each attribute will be checked and the variation will be active if all of them match. Using the same example for the embed block, the string version would look like this: -``` +```js isActive: [ 'providerNameSlug' ] ``` @@ -175,4 +208,4 @@ wp.blocks.registerBlockVariation( The `isActive` check on both variations tests the `textColor`, but each variations uses `vivid-red`. Since the `paragraph-red` variation is registered first, once the `paragraph-red-grey` variation is inserted into the Editor, it will have the title `Red Paragraph` instead of `Red/Grey Paragraph`. As soon as the Editor finds a match, it stops checking. -There have been [discussions](https://github.com/WordPress/gutenberg/issues/41303#issuecomment-1526193087) around how the API can be improved, but as of WordPress 6.3, this remains an issue to watch out for. \ No newline at end of file +There have been [discussions](https://github.com/WordPress/gutenberg/issues/41303#issuecomment-1526193087) around how the API can be improved, but as of WordPress 6.3, this remains an issue to watch out for. diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index d0eb25b807e6d7..3c8ee800d31aa4 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -860,7 +860,7 @@ Displays the name of this site. Update the block, and the changes apply everywhe ## Social Icon -Display an icon linking to a social media profile or site. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/social-link)) +Display an icon linking to a social profile or site. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/social-link)) - **Name:** core/social-link - **Category:** widgets @@ -870,7 +870,7 @@ Display an icon linking to a social media profile or site. ([Source](https://git ## Social Icons -Display icons linking to your social media profiles or sites. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/social-links)) +Display icons linking to your social profiles or sites. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/social-links)) - **Name:** core/social-links - **Category:** widgets diff --git a/docs/reference-guides/data/data-core-edit-site.md b/docs/reference-guides/data/data-core-edit-site.md index a2bc9ea1bfb968..1f050ca98576a3 100644 --- a/docs/reference-guides/data/data-core-edit-site.md +++ b/docs/reference-guides/data/data-core-edit-site.md @@ -371,7 +371,7 @@ Resolves the template for a page and displays both. If no path is given, attempt _Returns_ -- `number`: The resolved template ID for the page route. +- `Object`: Action object. ### setTemplate diff --git a/docs/reference-guides/data/data-core-keyboard-shortcuts.md b/docs/reference-guides/data/data-core-keyboard-shortcuts.md index 613c5e009e8b07..d7d5cf853f7865 100644 --- a/docs/reference-guides/data/data-core-keyboard-shortcuts.md +++ b/docs/reference-guides/data/data-core-keyboard-shortcuts.md @@ -22,7 +22,7 @@ const ExampleComponent = () => { const allShortcutKeyCombinations = useSelect( ( select ) => select( keyboardShortcutsStore ).getAllShortcutKeyCombinations( - 'core/edit-post/next-region' + 'core/editor/next-region' ), [] ); @@ -77,7 +77,7 @@ const ExampleComponent = () => { const allShortcutRawKeyCombinations = useSelect( ( select ) => select( keyboardShortcutsStore ).getAllShortcutRawKeyCombinations( - 'core/edit-post/next-region' + 'core/editor/next-region' ), [] ); @@ -168,7 +168,7 @@ const ExampleComponent = () => { const shortcutAliases = useSelect( ( select ) => select( keyboardShortcutsStore ).getShortcutAliases( - 'core/edit-post/next-region' + 'core/editor/next-region' ), [] ); @@ -219,7 +219,7 @@ const ExampleComponent = () => { const shortcutDescription = useSelect( ( select ) => select( keyboardShortcutsStore ).getShortcutDescription( - 'core/edit-post/next-region' + 'core/editor/next-region' ), [] ); @@ -256,7 +256,7 @@ const ExampleComponent = () => { const { character, modifier } = useSelect( ( select ) => select( keyboardShortcutsStore ).getShortcutKeyCombination( - 'core/edit-post/next-region' + 'core/editor/next-region' ), [] ); @@ -302,16 +302,16 @@ const ExampleComponent = () => { const { display, raw, ariaLabel } = useSelect( ( select ) => { return { display: select( keyboardShortcutsStore ).getShortcutRepresentation( - 'core/edit-post/next-region' + 'core/editor/next-region' ), raw: select( keyboardShortcutsStore ).getShortcutRepresentation( - 'core/edit-post/next-region', + 'core/editor/next-region', 'raw' ), ariaLabel: select( keyboardShortcutsStore ).getShortcutRepresentation( - 'core/edit-post/next-region', + 'core/editor/next-region', 'ariaLabel' ), }; @@ -410,13 +410,13 @@ const ExampleComponent = () => { const { unregisterShortcut } = useDispatch( keyboardShortcutsStore ); useEffect( () => { - unregisterShortcut( 'core/edit-post/next-region' ); + unregisterShortcut( 'core/editor/next-region' ); }, [] ); const shortcut = useSelect( ( select ) => select( keyboardShortcutsStore ).getShortcutKeyCombination( - 'core/edit-post/next-region' + 'core/editor/next-region' ), [] ); diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md index b80703dcc67b18..88db705f23f122 100644 --- a/docs/reference-guides/data/data-core.md +++ b/docs/reference-guides/data/data-core.md @@ -150,7 +150,7 @@ _Parameters_ _Returns_ -- `undefined< 'edit' >`: Current user object. +- `ET.User< 'edit' >`: Current user object. ### getDefaultTemplateId @@ -178,7 +178,7 @@ _Parameters_ _Returns_ -- `undefined< EntityRecord > | undefined`: The entity record, merged with its edits. +- `ET.Updatable< EntityRecord > | false`: The entity record, merged with its edits. ### getEmbedPreview @@ -504,7 +504,7 @@ _Parameters_ _Returns_ -- `undefined< 'edit' >[]`: Users list. +- `ET.User< 'edit' >[]`: Users list. ### hasEditsForEntityRecord diff --git a/docs/reference-guides/slotfills/README.md b/docs/reference-guides/slotfills/README.md index c41e6da0d8eb9f..043a50cb5186e6 100644 --- a/docs/reference-guides/slotfills/README.md +++ b/docs/reference-guides/slotfills/README.md @@ -10,7 +10,7 @@ In order to use them, we must leverage the [@wordpress/plugins](/packages/plugin In order to access the SlotFills, we need to do four things: 1. Import the `registerPlugin` method from `wp.plugins`. -2. Import the SlotFill we want from `wp.editPost`. +2. Import the SlotFill we want from `wp.editor`. 3. Define a method to render our changes. Our changes/additions will be wrapped in the SlotFill component we imported. 4. Register the plugin. @@ -18,7 +18,7 @@ Here is an example using the `PluginPostStatusInfo` slotFill: ```js import { registerPlugin } from '@wordpress/plugins'; -import { PluginPostStatusInfo } from '@wordpress/edit-post'; +import { PluginPostStatusInfo } from '@wordpress/editor'; const PluginPostStatusInfoTest = () => ( @@ -93,7 +93,7 @@ const PostStatus = ( { isOpened, onTogglePanel } ) => ( ## Currently available SlotFills and examples -The following SlotFills are available in the `edit-post` package. Please refer to the individual items below for usage and example details: +The following SlotFills are available in the `edit-post` or `editor` packages. Please refer to the individual items below for usage and example details: - [MainDashboardButton](/docs/reference-guides/slotfills/main-dashboard-button.md) - [PluginBlockSettingsMenuItem](/docs/reference-guides/slotfills/plugin-block-settings-menu-item.md) diff --git a/docs/reference-guides/slotfills/plugin-more-menu-item.md b/docs/reference-guides/slotfills/plugin-more-menu-item.md index 6a53c029b10dda..b5dd211b60f3e1 100644 --- a/docs/reference-guides/slotfills/plugin-more-menu-item.md +++ b/docs/reference-guides/slotfills/plugin-more-menu-item.md @@ -6,7 +6,7 @@ This slot will add a new item to the More Tools & Options section. ```js import { registerPlugin } from '@wordpress/plugins'; -import { PluginMoreMenuItem } from '@wordpress/edit-post'; +import { PluginMoreMenuItem } from '@wordpress/editor'; import { image } from '@wordpress/icons'; const MyButtonMoreMenuItemTest = () => ( diff --git a/docs/reference-guides/slotfills/plugin-post-status-info.md b/docs/reference-guides/slotfills/plugin-post-status-info.md index 2fc0d50050ee7a..03e6d3bfe3a17a 100644 --- a/docs/reference-guides/slotfills/plugin-post-status-info.md +++ b/docs/reference-guides/slotfills/plugin-post-status-info.md @@ -6,7 +6,7 @@ This slots allows for the insertion of items in the Summary panel of the documen ```js import { registerPlugin } from '@wordpress/plugins'; -import { PluginPostStatusInfo } from '@wordpress/edit-post'; +import { PluginPostStatusInfo } from '@wordpress/editor'; const PluginPostStatusInfoTest = () => ( diff --git a/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md b/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md index 4d32d754578cc4..76fb3018de7b68 100644 --- a/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md +++ b/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md @@ -7,7 +7,7 @@ This is done by setting the `target` on `` to match t ```js import { registerPlugin } from '@wordpress/plugins'; -import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/edit-post'; +import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/editor'; import { image } from '@wordpress/icons'; const PluginSidebarMoreMenuItemTest = () => ( diff --git a/docs/reference-guides/slotfills/plugin-sidebar.md b/docs/reference-guides/slotfills/plugin-sidebar.md index 56d87ea1fc1be4..8fe274414905b7 100644 --- a/docs/reference-guides/slotfills/plugin-sidebar.md +++ b/docs/reference-guides/slotfills/plugin-sidebar.md @@ -7,7 +7,7 @@ Using this slot will add an icon to the bar that, when clicked, will open a side ```js import { registerPlugin } from '@wordpress/plugins'; -import { PluginSidebar } from '@wordpress/edit-post'; +import { PluginSidebar } from '@wordpress/editor'; import { image } from '@wordpress/icons'; const PluginSidebarTest = () => ( diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md index 39fc3d61b3cb4e..bea655e61af827 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-living.md +++ b/docs/reference-guides/theme-json-reference/theme-json-living.md @@ -59,7 +59,7 @@ Please note that when using this setting, `styles.spacing.padding` should always Settings related to borders. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | color | boolean | false | | | radius | boolean | false | | | style | boolean | false | | @@ -72,7 +72,7 @@ Settings related to borders. Settings related to shadows. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | defaultPresets | boolean | true | | | presets | array | | name, shadow, slug | @@ -83,7 +83,7 @@ Settings related to shadows. Settings related to colors. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | background | boolean | true | | | custom | boolean | true | | | customDuotone | boolean | true | | @@ -107,7 +107,7 @@ Settings related to colors. Settings related to background. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | backgroundImage | boolean | false | | | backgroundSize | boolean | false | | @@ -118,7 +118,7 @@ Settings related to background. Settings related to dimensions. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | aspectRatio | boolean | false | | | minHeight | boolean | false | | @@ -129,7 +129,7 @@ Settings related to dimensions. Settings related to layout. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | contentSize | string | | | | wideSize | string | | | | allowEditing | boolean | true | | @@ -142,7 +142,7 @@ Settings related to layout. Settings related to the lightbox. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | enabled | boolean | | | | allowEditing | boolean | | | @@ -153,7 +153,7 @@ Settings related to the lightbox. Settings related to position. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | sticky | boolean | false | | --- @@ -163,8 +163,8 @@ Settings related to position. Settings related to spacing. | Property | Type | Default | Props | -| --- | --- | --- |--- | -| blockGap | undefined | null | | +| --- | --- | --- |--- | +| blockGap | boolean, null | null | | | margin | boolean | false | | | padding | boolean | false | | | units | array | px,em,rem,vh,vw,% | | @@ -179,12 +179,12 @@ Settings related to spacing. Settings related to typography. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | defaultFontSizes | boolean | true | | | customFontSize | boolean | true | | | fontStyle | boolean | true | | | fontWeight | boolean | true | | -| fluid | undefined | false | | +| fluid | object, boolean | false | _{maxViewportWidth, minFontSize, minViewportWidth}_ | | letterSpacing | boolean | true | | | lineHeight | boolean | false | | | textAlign | boolean | true | | diff --git a/docs/reference-guides/theme-json-reference/theme-json-v2.md b/docs/reference-guides/theme-json-reference/theme-json-v2.md index ea68eb0eb5772e..56cdff1c3bb863 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-v2.md +++ b/docs/reference-guides/theme-json-reference/theme-json-v2.md @@ -28,9 +28,9 @@ Code editors can pick up the schema and can provide helpful hints and suggestion Setting that enables the following UI tools: -- background: backgroundImage +- background: backgroundImage, backgroundSize - border: color, radius, style, width -- color: link +- color: link, heading, button, caption - dimensions: aspectRatio, minHeight - position: sticky - spacing: blockGap, margin, padding @@ -53,7 +53,7 @@ Please note that when using this setting, `styles.spacing.padding` should always Settings related to borders. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | color | boolean | false | | | radius | boolean | false | | | style | boolean | false | | @@ -66,7 +66,7 @@ Settings related to borders. Settings related to shadows. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | defaultPresets | boolean | true | | | presets | array | | name, shadow, slug | @@ -77,7 +77,7 @@ Settings related to shadows. Settings related to colors. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | background | boolean | true | | | custom | boolean | true | | | customDuotone | boolean | true | | @@ -92,6 +92,7 @@ Settings related to colors. | text | boolean | true | | | heading | boolean | true | | | button | boolean | true | | +| caption | boolean | true | | --- @@ -100,8 +101,9 @@ Settings related to colors. Settings related to background. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | backgroundImage | boolean | false | | +| backgroundSize | boolean | false | | --- @@ -110,7 +112,7 @@ Settings related to background. Settings related to dimensions. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | aspectRatio | boolean | false | | | minHeight | boolean | false | | @@ -121,7 +123,7 @@ Settings related to dimensions. Settings related to layout. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | contentSize | string | | | | wideSize | string | | | | allowEditing | boolean | true | | @@ -134,7 +136,7 @@ Settings related to layout. Settings related to the lightbox. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | enabled | boolean | | | | allowEditing | boolean | | | @@ -145,7 +147,7 @@ Settings related to the lightbox. Settings related to position. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | sticky | boolean | false | | --- @@ -155,8 +157,8 @@ Settings related to position. Settings related to spacing. | Property | Type | Default | Props | -| --- | --- | --- |--- | -| blockGap | undefined | null | | +| --- | --- | --- |--- | +| blockGap | boolean, null | null | | | margin | boolean | false | | | padding | boolean | false | | | units | array | px,em,rem,vh,vw,% | | @@ -171,11 +173,11 @@ Settings related to spacing. Settings related to typography. | Property | Type | Default | Props | -| --- | --- | --- |--- | +| --- | --- | --- |--- | | customFontSize | boolean | true | | | fontStyle | boolean | true | | | fontWeight | boolean | true | | -| fluid | undefined | false | | +| fluid | object, boolean | false | _{maxViewportWidth, minFontSize, minViewportWidth}_ | | letterSpacing | boolean | true | | | lineHeight | boolean | false | | | textAlign | boolean | true | | @@ -261,6 +263,7 @@ Typography styles. | fontWeight | string, object | | | letterSpacing | string, object | | | lineHeight | string, object | | +| textAlign | string | | | textColumns | string | | | textDecoration | string, object | | | writingMode | string, object | | diff --git a/gutenberg.php b/gutenberg.php index 8e7889224566ca..06faf9a84df5fb 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -4,8 +4,8 @@ * Plugin URI: https://github.com/WordPress/gutenberg * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.3 - * Requires PHP: 7.0 - * Version: 18.1.0 + * Requires PHP: 7.2 + * Version: 18.2.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/lib/block-supports/elements.php b/lib/block-supports/elements.php index eefab9ceffbafd..35a41270a19800 100644 --- a/lib/block-supports/elements.php +++ b/lib/block-supports/elements.php @@ -5,6 +5,19 @@ * @package gutenberg */ +/** + * Update the block content with elements class names. + * + * @deprecated 6.6.0 Use `gutenberg_render_elements_class_name` instead. + * + * @param string $block_content Rendered block content. + * @return string Filtered block content. + */ +function gutenberg_render_elements_support( $block_content ) { + _deprecated_function( __FUNCTION__, '6.6.0', 'gutenberg_render_elements_class_name' ); + return $block_content; +} + /** * Determines whether an elements class name should be added to the block. * @@ -86,11 +99,31 @@ function gutenberg_should_add_elements_class_name( $block, $options ) { * This solves the issue of an element (e.g.: link color) being styled in both the parent and a descendant: * we want the descendant style to take priority, and this is done by loading it after, in DOM order. * + * @since 6.6.0 Element block support class and styles are generated via the `render_block_data` filter instead of `pre_render_block` + * * @param array $parsed_block The parsed block. * * @return array The same parsed block with elements classname added if appropriate. */ function gutenberg_render_elements_support_styles( $parsed_block ) { + /* + * The generation of element styles and classname were moved to the + * `render_block_data` filter in 6.6.0 to avoid filtered attributes + * breaking the application of the elements CSS class. + * + * @see https://github.com/WordPress/gutenberg/pull/59535. + * + * The change in filter means, the argument types for this function + * have changed and require deprecating. + */ + if ( is_string( $parsed_block ) ) { + _deprecated_argument( + __FUNCTION__, + '6.6.0', + __( 'Use as a `pre_render_block` filter is deprecated. Use with `render_block_data` instead.', 'gutenberg' ) + ); + } + $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $parsed_block['blockName'] ); $element_block_styles = $parsed_block['attrs']['style']['elements'] ?? null; @@ -193,8 +226,8 @@ function gutenberg_render_elements_support_styles( $parsed_block ) { } /** - * Ensure the elements block support class name generated and added to - * block attributes in the `render_block_data` filter gets applied to the + * Ensure the elements block support class name generated, and added to + * block attributes, in the `render_block_data` filter gets applied to the * block's markup. * * @see gutenberg_render_elements_support_styles @@ -215,17 +248,19 @@ function gutenberg_render_elements_class_name( $block_content, $block ) { $tags = new WP_HTML_Tag_Processor( $block_content ); if ( $tags->next_tag() ) { - // Ensure the elements class name set in render_block_data filter is applied in markup. - // See `gutenberg_render_elements_support_styles`. $tags->add_class( $matches[0] ); } return $tags->get_updated_html(); } -// Remove WordPress core filters to avoid rendering duplicate elements stylesheet & attaching classes twice. +// Remove deprecated WordPress core filters. remove_filter( 'render_block', 'wp_render_elements_support', 10, 2 ); remove_filter( 'pre_render_block', 'wp_render_elements_support_styles', 10, 2 ); + +// Remove WordPress core filters to avoid rendering duplicate elements stylesheet & attaching classes twice. remove_filter( 'render_block', 'wp_render_elements_class_name', 10, 2 ); +remove_filter( 'render_block_data', 'wp_render_elements_support_styles', 10, 1 ); + add_filter( 'render_block', 'gutenberg_render_elements_class_name', 10, 2 ); -add_filter( 'render_block_data', 'gutenberg_render_elements_support_styles', 10, 2 ); +add_filter( 'render_block_data', 'gutenberg_render_elements_support_styles', 10, 1 ); diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php index 554a88b4eeec3f..e18dcba462a5ea 100644 --- a/lib/block-supports/layout.php +++ b/lib/block-supports/layout.php @@ -47,13 +47,13 @@ function gutenberg_get_layout_definitions() { ), 'spacingStyles' => array( array( - 'selector' => ' > :first-child:first-child', + 'selector' => ' > :first-child', 'rules' => array( 'margin-block-start' => '0', ), ), array( - 'selector' => ' > :last-child:last-child', + 'selector' => ' > :last-child', 'rules' => array( 'margin-block-end' => '0', ), @@ -112,13 +112,13 @@ function gutenberg_get_layout_definitions() { ), 'spacingStyles' => array( array( - 'selector' => ' > :first-child:first-child', + 'selector' => ' > :first-child', 'rules' => array( 'margin-block-start' => '0', ), ), array( - 'selector' => ' > :last-child:last-child', + 'selector' => ' > :last-child', 'rules' => array( 'margin-block-end' => '0', ), @@ -146,7 +146,7 @@ function gutenberg_get_layout_definitions() { ), ), array( - 'selector' => ' > *', + 'selector' => ' > :is(*, div)', // :is(*, div) instead of just * increases the specificity by 001. 'rules' => array( 'margin' => '0', ), @@ -168,7 +168,7 @@ function gutenberg_get_layout_definitions() { 'displayMode' => 'grid', 'baseStyles' => array( array( - 'selector' => ' > *', + 'selector' => ' > :is(*, div)', // :is(*, div) instead of just * increases the specificity by 001. 'rules' => array( 'margin' => '0', ), @@ -248,7 +248,7 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support ), ), array( - 'selector' => "$selector$selector > * + *", + 'selector' => "$selector > * + *", 'declarations' => array( 'margin-block-start' => $gap_value, 'margin-block-end' => '0', @@ -357,7 +357,7 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support ), ), array( - 'selector' => "$selector$selector > * + *", + 'selector' => "$selector > * + *", 'declarations' => array( 'margin-block-start' => $gap_value, 'margin-block-end' => '0', @@ -612,8 +612,8 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { 'declarations' => $child_layout_declarations, ); - $minimum_column_width = isset( $block['attrs']['style']['layout']['minimumColumnWidth'] ) ? $block['attrs']['style']['layout']['minimumColumnWidth'] : null; - $column_count = isset( $block['attrs']['style']['layout']['columnCount'] ) ? $block['attrs']['style']['layout']['columnCount'] : null; + $minimum_column_width = isset( $block['parentLayout']['minimumColumnWidth'] ) ? $block['parentLayout']['minimumColumnWidth'] : null; + $column_count = isset( $block['parentLayout']['columnCount'] ) ? $block['parentLayout']['columnCount'] : null; /* * If columnSpan or columnStart is set, and the parent grid is responsive, i.e. if it has a minimumColumnWidth set, @@ -799,7 +799,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { $has_block_gap_support = isset( $block_gap ); $style = gutenberg_get_layout_style( - ".$container_class.$container_class", + ".$container_class", $used_layout, $has_block_gap_support, $gap_value, diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index f1bcab53ed7760..d685c7bdc846dd 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1259,7 +1259,7 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' ); foreach ( $base_styles_nodes as $base_style_node ) { - $stylesheet .= $this->get_layout_styles( $base_style_node ); + $stylesheet .= $this->get_layout_styles( $base_style_node, $types ); } } @@ -1467,7 +1467,7 @@ protected function get_block_classes( $style_nodes ) { * @param array $block_metadata Metadata about the block to get styles for. * @return string Layout styles for the block. */ - protected function get_layout_styles( $block_metadata ) { + protected function get_layout_styles( $block_metadata, $types = array() ) { $block_rules = ''; $block_type = null; @@ -1488,7 +1488,7 @@ protected function get_layout_styles( $block_metadata ) { $has_fallback_gap_support = ! $has_block_gap_support; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback gap styles support. $node = _wp_array_get( $this->theme_json, $block_metadata['path'], array() ); $layout_definitions = gutenberg_get_layout_definitions(); - $layout_selector_pattern = '/^[a-zA-Z0-9\-\.\ *+>:\(\)]*$/'; // Allow alphanumeric classnames, spaces, wildcard, sibling, child combinator and pseudo class selectors. + $layout_selector_pattern = '/^[a-zA-Z0-9\-\.\,\ *+>:\(\)]*$/'; // Allow alphanumeric classnames, spaces, wildcard, sibling, child combinator and pseudo class selectors. // Gap styles will only be output if the theme has block gap support, or supports a fallback gap. // Default layout gap styles will be skipped for themes that do not explicitly opt-in to blockGap with a `true` or `false` value. @@ -1559,7 +1559,7 @@ protected function get_layout_styles( $block_metadata ) { $spacing_rule['selector'] ); } else { - $format = static::ROOT_BLOCK_SELECTOR === $selector ? ':where(%s .%s) %s' : '%s-%s%s'; + $format = static::ROOT_BLOCK_SELECTOR === $selector ? ':where(.%2$s) %3$s' : ':where(%1$s-%2$s) %3$s'; $layout_selector = sprintf( $format, $selector, @@ -1613,6 +1613,11 @@ protected function get_layout_styles( $block_metadata ) { foreach ( $base_style_rules as $base_style_rule ) { $declarations = array(); + // Skip outputting base styles for flow and constrained layout types if theme doesn't support theme.json. The 'base-layout-styles' type flags this. + if ( in_array( 'base-layout-styles', $types, true ) && ( 'default' === $layout_definition['name'] || 'constrained' === $layout_definition['name'] ) ) { + continue; + } + if ( isset( $base_style_rule['selector'] ) && preg_match( $layout_selector_pattern, $base_style_rule['selector'] ) && @@ -1638,8 +1643,7 @@ protected function get_layout_styles( $block_metadata ) { } $layout_selector = sprintf( - '%s .%s%s', - $selector, + '.%s%s', $class_name, $base_style_rule['selector'] ); @@ -2789,8 +2793,8 @@ public function get_root_layout_rules( $selector, $block_metadata ) { if ( isset( $this->theme_json['settings']['spacing']['blockGap'] ) ) { $block_gap_value = static::get_property_value( $this->theme_json, array( 'styles', 'spacing', 'blockGap' ) ); $css .= ":where(.wp-site-blocks) > * { margin-block-start: $block_gap_value; margin-block-end: 0; }"; - $css .= ':where(.wp-site-blocks) > :first-child:first-child { margin-block-start: 0; }'; - $css .= ':where(.wp-site-blocks) > :last-child:last-child { margin-block-end: 0; }'; + $css .= ':where(.wp-site-blocks) > :first-child { margin-block-start: 0; }'; + $css .= ':where(.wp-site-blocks) > :last-child { margin-block-end: 0; }'; // For backwards compatibility, ensure the legacy block gap CSS variable is still available. $css .= static::ROOT_CSS_PROPERTIES_SELECTOR . " { --wp--style--block-gap: $block_gap_value; }"; diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index 1d27353b70a89b..dcc0bf8b099c3b 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -350,15 +350,10 @@ public static function get_theme_data( $deprecated = array(), $options = array() ); } - // BEGIN EXPERIMENTAL. // Allow themes to enable appearance tools via theme_support. - // This feature was backported for WordPress 6.2 as of https://core.trac.wordpress.org/ticket/56487 - // and then reverted as of https://core.trac.wordpress.org/ticket/57649 - // Not to backport until the issues are resolved. if ( current_theme_supports( 'appearance-tools' ) ) { $theme_support_data['settings']['appearanceTools'] = true; } - // END EXPERIMENTAL. } $with_theme_supports = new WP_Theme_JSON_Gutenberg( $theme_support_data ); $with_theme_supports->merge( static::$theme ); diff --git a/lib/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-registry.php b/lib/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-registry.php index 7f04820050a913..8eb6f5271adf69 100644 --- a/lib/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-registry.php +++ b/lib/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-registry.php @@ -12,7 +12,7 @@ /** * Class used for interacting with block bindings sources. * - * @since 6.5.0 + * @since 6.5.0 */ if ( ! class_exists( 'WP_Block_Bindings_Registry' ) ) { final class WP_Block_Bindings_Registry { diff --git a/lib/compat/wordpress-6.5/compat.php b/lib/compat/wordpress-6.5/compat.php index 39edaef83e5cc8..c41203e5d27b4e 100644 --- a/lib/compat/wordpress-6.5/compat.php +++ b/lib/compat/wordpress-6.5/compat.php @@ -51,3 +51,42 @@ function gutenberg_add_use_customizer_site_logo_url_flag() { } add_action( 'admin_init', 'gutenberg_add_use_customizer_site_logo_url_flag' ); + +/** + * Add a Patterns submenu (wp-admin/edit.php?post_type=wp_block) under the Appearance menu + * for the Classic theme. This function should not be backported to core, and should be + * removed when the required WP core version for Gutenberg is >= 6.5.0. + * + * @global array $submenu + */ +function gutenberg_add_patterns_page_submenu_item() { + if ( ! is_wp_version_compatible( '6.5' ) && ! wp_is_block_theme() ) { + // Move the Themes submenu forward and inject a Patterns submenu. + global $submenu; + $submenu['themes.php'][4] = $submenu['themes.php'][5]; + $submenu['themes.php'][5] = array( __( 'Patterns', 'gutenberg' ), 'edit_theme_options', 'edit.php?post_type=wp_block' ); + ksort( $submenu['themes.php'], SORT_NUMERIC ); + } +} +add_action( 'admin_init', 'gutenberg_add_patterns_page_submenu_item' ); + +/** + * Filter the `wp_die_handler` to allow access to the Site Editor's Patterns page + * (wp-admin/site-editor.php?path=%2Fpatterns) internally for the Classic theme. This + * function should not be backported to core, and should be removed when the required + * WP core version for Gutenberg is >= 6.5.0. + * + * @param callable $default_handler The default handler. + * @return callable The default handler or a custom handler. + */ +function gutenberg_patterns_page_wp_die_handler( $default_handler ) { + if ( ! is_wp_version_compatible( '6.5' ) && ! wp_is_block_theme() && str_contains( $_SERVER['REQUEST_URI'], 'site-editor.php' ) ) { + $is_patterns = isset( $_GET['postType'] ) && 'wp_block' === sanitize_key( $_GET['postType'] ); + $is_patterns_path = isset( $_GET['path'] ) && 'patterns' === sanitize_key( $_GET['path'] ); + if ( $is_patterns || $is_patterns_path ) { + return '__return_false'; + } + } + return $default_handler; +} +add_filter( 'wp_die_handler', 'gutenberg_patterns_page_wp_die_handler' ); diff --git a/lib/compat/wordpress-6.6/option.php b/lib/compat/wordpress-6.6/option.php index 71907fa62dd09c..c471be6b240314 100644 --- a/lib/compat/wordpress-6.6/option.php +++ b/lib/compat/wordpress-6.6/option.php @@ -26,6 +26,11 @@ function gutenberg_update_initial_settings( $args, $defaults, $option_group, $op $args['label'] = $settings_label_map[ $option_name ]; } + // Don't update schema when a setting isn't exposed via REST API. + if ( ! isset( $args['show_in_rest'] ) ) { + return $args; + } + // Don't update schema when label isn't provided. if ( ! isset( $args['label'] ) ) { return $args; diff --git a/lib/compat/wordpress-6.6/post.php b/lib/compat/wordpress-6.6/post.php new file mode 100644 index 00000000000000..42707989fc0828 --- /dev/null +++ b/lib/compat/wordpress-6.6/post.php @@ -0,0 +1,15 @@ + 'fullPage' ) ); + wp_enqueue_script_module( '@wordpress/interactivity-router' ); +} + +add_action( 'wp_enqueue_scripts', '_gutenberg_enqueue_interactivity_router' ); + +/** + * Set enhancedPagination attribute for query loop when the experiment is enabled. + * + * @param array $parsed_block The parsed block. + * + * @return array The same parsed block with the modified attribute. + */ +function _gutenberg_add_enhanced_pagination_to_query_block( $parsed_block ) { + if ( 'core/query' !== $parsed_block['blockName'] ) { + return $parsed_block; + } + + $parsed_block['attrs']['enhancedPagination'] = true; + return $parsed_block; +} + +add_filter( 'render_block_data', '_gutenberg_add_enhanced_pagination_to_query_block' ); + +/** + * Add directives to all links. + * + * Note: This should probably be done per site, not by default when this option is enabled. + * + * @param array $content The block content. + * + * @return array The same block content with the directives needed. + */ +function _gutenberg_add_client_side_navigation_directives( $content ) { + $p = new WP_HTML_Tag_Processor( $content ); + // Hack to add the necessary directives to the body tag. + // TODO: Find a proper way to add directives to the body tag. + static $body_interactive_added; + if ( ! $body_interactive_added ) { + $body_interactive_added = true; + return (string) $p . ''; + } + return (string) $p; +} + +// TODO: Explore moving this to the server directive processing. +add_filter( 'render_block', '_gutenberg_add_client_side_navigation_directives' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 08bfc283dac2e2..7dfe6fbe5bb90c 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -68,14 +68,14 @@ function gutenberg_initialize_experiments_settings() { ); add_settings_field( - 'gutenberg-dataviews', - __( 'New admin views', 'gutenberg' ), + 'gutenberg-custom-dataviews', + __( 'Custom dataviews', 'gutenberg' ), 'gutenberg_display_experiment_field', 'gutenberg-experiments', 'gutenberg_experiments_section', array( - 'label' => __( 'Test the new views for different entities like pages.', 'gutenberg' ), - 'id' => 'gutenberg-dataviews', + 'label' => __( 'Test the custom dataviews in the pages page.', 'gutenberg' ), + 'id' => 'gutenberg-custom-dataviews', ) ); @@ -127,6 +127,18 @@ function gutenberg_initialize_experiments_settings() { ) ); + add_settings_field( + 'gutenberg-full-page-client-side-navigation', + __( 'Enable full page client-side navigation', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Enable full page client-side navigation using the Interactivity API', 'gutenberg' ), + 'id' => 'gutenberg-full-page-client-side-navigation', + ) + ); + register_setting( 'gutenberg-experiments', 'gutenberg-experiments' diff --git a/lib/load.php b/lib/load.php index ead9a1b9743fb8..2ae1be2c9011ed 100644 --- a/lib/load.php +++ b/lib/load.php @@ -131,6 +131,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.6/option.php'; require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php'; require __DIR__ . '/compat/wordpress-6.6/rest-api.php'; +require __DIR__ . '/compat/wordpress-6.6/post.php'; // Experimental features. require __DIR__ . '/experimental/block-editor-settings-mobile.php'; @@ -199,6 +200,9 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/demo.php'; require __DIR__ . '/experiments-page.php'; require __DIR__ . '/interactivity-api.php'; +if ( gutenberg_is_experiment_enabled( 'gutenberg-full-page-client-side-navigation' ) ) { + require __DIR__ . '/experimental/full-page-client-side-navigation.php'; +} // Copied package PHP files. if ( is_dir( __DIR__ . '/../build/style-engine' ) ) { diff --git a/package-lock.json b/package-lock.json index 55f2e0ad541189..131b3ae8124daf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "18.1.0", + "version": "18.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "18.1.0", + "version": "18.2.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -118,8 +118,8 @@ "@testing-library/react": "14.0.0", "@testing-library/react-native": "12.4.3", "@testing-library/user-event": "14.4.3", - "@types/eslint": "7.28.0", - "@types/estree": "0.0.50", + "@types/eslint": "8.56.9", + "@types/estree": "1.0.5", "@types/istanbul-lib-report": "3.0.0", "@types/mime": "2.0.3", "@types/npm-package-arg": "6.1.1", @@ -242,7 +242,7 @@ "strip-json-comments": "5.0.0", "style-loader": "3.2.1", "terser-webpack-plugin": "5.3.9", - "typescript": "5.1.6", + "typescript": "5.4.5", "uglify-js": "3.13.7", "uuid": "9.0.1", "webdriverio": "8.16.20", @@ -15602,9 +15602,9 @@ "dev": true }, "node_modules/@types/eslint": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.0.tgz", - "integrity": "sha512-07XlgzX0YJUn4iG1ocY4IX9DzKSmMGUs6ESKlxWhZRaa0fatIWaHWUVapcuGa8r5HFnTqzj+4OCjd5f7EZ/i/A==", + "version": "8.56.9", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.9.tgz", + "integrity": "sha512-W4W3KcqzjJ0sHg2vAq9vfml6OhsJ53TcUjUqfzzZf/EChUtwspszj/S0pzMxnfRcO55/iGq47dscXw71Fxc4Zg==", "dev": true, "dependencies": { "@types/estree": "*", @@ -15622,9 +15622,9 @@ } }, "node_modules/@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@types/events": { @@ -43340,11 +43340,6 @@ "node": ">= 14" } }, - "node_modules/proxy-compare": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.3.0.tgz", - "integrity": "sha512-c3L2CcAi7f7pvlD0D7xsF+2CQIW8C3HaYx2Pfgq8eA4HAl3GAH6/dVYsyBbYF/0XJs2ziGLrzmz5fmzPm6A0pQ==" - }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -49698,9 +49693,9 @@ } }, "node_modules/typescript": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", - "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -50511,46 +50506,6 @@ "integrity": "sha512-PnFM3xiZ+kYmLyTiMgTYmU7ZHkjBZz2/+F0DaALc/uUtVzdCt1wAosvYJ5hFQi/hz8O4zb52FQhHZRC+uVkJ+g==", "dev": true }, - "node_modules/valtio": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/valtio/-/valtio-1.7.0.tgz", - "integrity": "sha512-3Tnix66EERwMcrl1rfB3ylcewOcL5L/GiPmC3FlVNreQzqf2jufEeqlNmgnLgSGchkEmH3WYVtS+x6Qw4r+yzQ==", - "dependencies": { - "proxy-compare": "2.3.0", - "use-sync-external-store": "1.2.0" - }, - "engines": { - "node": ">=12.7.0" - }, - "peerDependencies": { - "@babel/helper-module-imports": ">=7.12", - "@babel/types": ">=7.13", - "aslemammad-vite-plugin-macro": ">=1.0.0-alpha.1", - "babel-plugin-macros": ">=3.0", - "react": ">=16.8", - "vite": ">=2.8.6" - }, - "peerDependenciesMeta": { - "@babel/helper-module-imports": { - "optional": true - }, - "@babel/types": { - "optional": true - }, - "aslemammad-vite-plugin-macro": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - }, - "react": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -51996,12 +51951,6 @@ "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", "dev": true }, - "node_modules/webpack/node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, "node_modules/webpack/node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -53061,7 +53010,7 @@ }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "3.55.0", + "version": "3.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53074,7 +53023,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "2.55.0", + "version": "2.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53101,7 +53050,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "6.52.0", + "version": "6.53.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53114,7 +53063,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "3.55.0", + "version": "3.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53125,7 +53074,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "4.38.0", + "version": "4.39.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -53137,7 +53086,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "5.39.0", + "version": "5.40.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53154,7 +53103,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "7.39.0", + "version": "7.40.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53177,13 +53126,13 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "4.46.0", + "version": "4.47.0", "dev": true, "license": "GPL-2.0-or-later" }, "packages/blob": { "name": "@wordpress/blob", - "version": "3.55.0", + "version": "3.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53194,7 +53143,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "4.32.0", + "version": "4.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53229,7 +53178,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "12.23.0", + "version": "12.24.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53342,7 +53291,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "8.32.0", + "version": "8.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53367,6 +53316,7 @@ "@wordpress/icons": "file:../icons", "@wordpress/interactivity": "file:../interactivity", "@wordpress/interactivity-router": "file:../interactivity-router", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", "@wordpress/keycodes": "file:../keycodes", "@wordpress/notices": "file:../notices", "@wordpress/patterns": "file:../patterns", @@ -53406,7 +53356,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "4.55.0", + "version": "4.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53417,7 +53367,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "4.55.0", + "version": "4.56.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -53429,7 +53379,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "12.32.0", + "version": "12.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53482,7 +53432,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "5.38.0", + "version": "5.39.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -53491,7 +53441,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "0.26.0", + "version": "0.27.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53515,7 +53465,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "27.3.0", + "version": "27.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.3.12", @@ -53564,8 +53514,7 @@ "react-colorful": "^5.3.1", "remove-accents": "^0.5.0", "use-lilius": "^2.0.5", - "uuid": "^9.0.1", - "valtio": "1.7.0" + "uuid": "^9.0.1" }, "engines": { "node": ">=12" @@ -53618,7 +53567,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "6.32.0", + "version": "6.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53654,7 +53603,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "0.24.0", + "version": "0.25.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53680,7 +53629,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "6.32.0", + "version": "6.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53723,7 +53672,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.39.0", + "version": "4.40.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53751,13 +53700,13 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "3.9.0", + "version": "3.10.0", "dev": true, "license": "GPL-2.0-or-later" }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "4.32.0", + "version": "4.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53794,7 +53743,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "9.25.0", + "version": "9.26.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53822,7 +53771,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "3.24.0", + "version": "3.25.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53839,7 +53788,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "0.9.0", + "version": "1.0.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.3.12", @@ -53900,7 +53849,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "4.55.0", + "version": "4.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53914,7 +53863,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "5.6.0", + "version": "5.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53929,7 +53878,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "3.55.0", + "version": "3.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53941,7 +53890,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "1.64.0", + "version": "1.65.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -53959,7 +53908,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "3.55.0", + "version": "3.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -53971,7 +53920,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "3.55.0", + "version": "3.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -53982,7 +53931,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "10.26.0", + "version": "10.27.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54004,7 +53953,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "0.23.0", + "version": "0.24.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54027,7 +53976,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "7.26.0", + "version": "7.27.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54066,7 +54015,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "7.32.0", + "version": "7.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54112,7 +54061,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "5.32.0", + "version": "5.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54177,7 +54126,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "5.32.0", + "version": "5.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54219,7 +54168,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "13.32.0", + "version": "13.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54272,7 +54221,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "5.32.0", + "version": "5.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54290,7 +54239,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "9.7.0", + "version": "9.8.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54427,7 +54376,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "2.55.0", + "version": "2.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54438,7 +54387,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "17.12.0", + "version": "17.13.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54481,7 +54430,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "4.32.0", + "version": "4.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54508,7 +54457,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "3.55.0", + "version": "3.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54519,7 +54468,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "3.55.0", + "version": "3.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54530,7 +54479,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "4.55.0", + "version": "4.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54549,7 +54498,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "9.46.0", + "version": "9.47.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54562,7 +54511,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "5.4.0", + "version": "5.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.2.2", @@ -54575,7 +54524,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "1.5.0", + "version": "1.6.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/interactivity": "file:../interactivity" @@ -54635,7 +54584,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "5.32.0", + "version": "5.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54663,7 +54612,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "4.55.0", + "version": "4.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -54674,7 +54623,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "7.26.0", + "version": "7.27.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54690,7 +54639,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "11.26.0", + "version": "11.27.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54707,7 +54656,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "6.26.0", + "version": "6.27.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54729,7 +54678,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "4.32.0", + "version": "4.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54746,7 +54695,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "3.55.0", + "version": "3.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54758,7 +54707,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "1.42.0", + "version": "1.43.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54772,7 +54721,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "4.32.0", + "version": "4.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54794,7 +54743,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "4.46.0", + "version": "4.47.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54809,7 +54758,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "4.23.0", + "version": "4.24.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54825,7 +54774,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "4.40.0", + "version": "4.41.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54837,7 +54786,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "8.17.0", + "version": "8.18.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54859,7 +54808,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "1.16.0", + "version": "1.17.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54888,7 +54837,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "6.23.0", + "version": "6.24.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54910,7 +54859,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "4.39.0", + "version": "4.40.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -54926,7 +54875,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "5.38.0", + "version": "5.39.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54938,7 +54887,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "3.32.0", + "version": "3.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54963,7 +54912,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "1.47.0", + "version": "1.48.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -54975,7 +54924,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "3.12.0", + "version": "3.13.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -54987,7 +54936,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "3.53.0", + "version": "3.54.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55000,7 +54949,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "2.55.0", + "version": "2.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55012,7 +54961,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "0.37.0", + "version": "0.38.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55023,7 +54972,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "1.54.0", + "version": "1.55.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55036,7 +54985,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "3.53.0", + "version": "3.54.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55183,7 +55132,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "2.38.0", + "version": "2.39.0", "dev": true, "license": "GPL-2.0-or-later", "engines": { @@ -55195,7 +55144,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "4.55.0", + "version": "4.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55239,7 +55188,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "4.32.0", + "version": "4.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55265,7 +55214,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "6.32.0", + "version": "6.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55288,7 +55237,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "0.24.0", + "version": "0.25.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55306,7 +55255,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "27.6.0", + "version": "27.7.0", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -55691,7 +55640,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "4.32.0", + "version": "4.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55716,7 +55665,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "3.55.0", + "version": "3.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55728,7 +55677,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "1.38.0", + "version": "1.39.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55740,7 +55689,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "21.38.0", + "version": "21.39.0", "dev": true, "license": "MIT", "dependencies": { @@ -55756,7 +55705,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "0.17.0", + "version": "0.18.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55776,7 +55725,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "2.55.0", + "version": "2.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -55787,7 +55736,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "0.15.0", + "version": "0.16.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55799,7 +55748,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "3.56.0", + "version": "3.57.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55811,7 +55760,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "5.32.0", + "version": "5.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55828,7 +55777,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "2.55.0", + "version": "2.56.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=12" @@ -55836,7 +55785,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "3.32.0", + "version": "3.33.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0", @@ -55860,7 +55809,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "3.55.0", + "version": "3.56.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "^7.16.0" @@ -66607,9 +66556,9 @@ "dev": true }, "@types/eslint": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.0.tgz", - "integrity": "sha512-07XlgzX0YJUn4iG1ocY4IX9DzKSmMGUs6ESKlxWhZRaa0fatIWaHWUVapcuGa8r5HFnTqzj+4OCjd5f7EZ/i/A==", + "version": "8.56.9", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.9.tgz", + "integrity": "sha512-W4W3KcqzjJ0sHg2vAq9vfml6OhsJ53TcUjUqfzzZf/EChUtwspszj/S0pzMxnfRcO55/iGq47dscXw71Fxc4Zg==", "dev": true, "requires": { "@types/estree": "*", @@ -66627,9 +66576,9 @@ } }, "@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "@types/events": { @@ -68686,6 +68635,7 @@ "@wordpress/icons": "file:../icons", "@wordpress/interactivity": "file:../interactivity", "@wordpress/interactivity-router": "file:../interactivity-router", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", "@wordpress/keycodes": "file:../keycodes", "@wordpress/notices": "file:../notices", "@wordpress/patterns": "file:../patterns", @@ -68837,8 +68787,7 @@ "react-colorful": "^5.3.1", "remove-accents": "^0.5.0", "use-lilius": "^2.0.5", - "uuid": "^9.0.1", - "valtio": "1.7.0" + "uuid": "^9.0.1" }, "dependencies": { "@floating-ui/react-dom": { @@ -89427,11 +89376,6 @@ } } }, - "proxy-compare": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.3.0.tgz", - "integrity": "sha512-c3L2CcAi7f7pvlD0D7xsF+2CQIW8C3HaYx2Pfgq8eA4HAl3GAH6/dVYsyBbYF/0XJs2ziGLrzmz5fmzPm6A0pQ==" - }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -94313,9 +94257,9 @@ "dev": true }, "typescript": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", - "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true }, "uc.micro": { @@ -94930,15 +94874,6 @@ "integrity": "sha512-PnFM3xiZ+kYmLyTiMgTYmU7ZHkjBZz2/+F0DaALc/uUtVzdCt1wAosvYJ5hFQi/hz8O4zb52FQhHZRC+uVkJ+g==", "dev": true }, - "valtio": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/valtio/-/valtio-1.7.0.tgz", - "integrity": "sha512-3Tnix66EERwMcrl1rfB3ylcewOcL5L/GiPmC3FlVNreQzqf2jufEeqlNmgnLgSGchkEmH3WYVtS+x6Qw4r+yzQ==", - "requires": { - "proxy-compare": "2.3.0", - "use-sync-external-store": "1.2.0" - } - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -95610,12 +95545,6 @@ "webpack-sources": "^3.2.3" }, "dependencies": { - "@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, "@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", diff --git a/package.json b/package.json index c7043fa9cc06e6..fc9b52821918d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "18.1.0", + "version": "18.2.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", @@ -130,8 +130,8 @@ "@testing-library/react": "14.0.0", "@testing-library/react-native": "12.4.3", "@testing-library/user-event": "14.4.3", - "@types/eslint": "7.28.0", - "@types/estree": "0.0.50", + "@types/eslint": "8.56.9", + "@types/estree": "1.0.5", "@types/istanbul-lib-report": "3.0.0", "@types/mime": "2.0.3", "@types/npm-package-arg": "6.1.1", @@ -254,7 +254,7 @@ "strip-json-comments": "5.0.0", "style-loader": "3.2.1", "terser-webpack-plugin": "5.3.9", - "typescript": "5.1.6", + "typescript": "5.4.5", "uglify-js": "3.13.7", "uuid": "9.0.1", "webdriverio": "8.16.20", diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index f9eb9aedf15b4a..74317b9e5d577c 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.56.0 (2024-04-19) + ## 3.55.0 (2024-04-03) ## 3.54.0 (2024-03-21) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 80375c5519f7e1..b65307cc490a25 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "3.55.0", + "version": "3.56.0", "description": "Accessibility (a11y) utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/annotations/CHANGELOG.md b/packages/annotations/CHANGELOG.md index 21117c194d2a5f..9af8f3ef1f58cb 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.56.0 (2024-04-19) + ## 2.55.0 (2024-04-03) ## 2.54.0 (2024-03-21) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index 571be01d55046f..3e9e4da7d20806 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "2.55.0", + "version": "2.56.0", "description": "Annotate content in the Gutenberg editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/api-fetch/CHANGELOG.md b/packages/api-fetch/CHANGELOG.md index 048023e03d9a17..edcdcf33ad5091 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.53.0 (2024-04-19) + ## 6.52.0 (2024-04-03) ## 6.51.0 (2024-03-21) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 09431da66bbe0a..a2744d1fb955a5 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "6.52.0", + "version": "6.53.0", "description": "Utility to make WordPress REST API requests.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/autop/CHANGELOG.md b/packages/autop/CHANGELOG.md index 8459618c4df4f6..66b81a85a73f6d 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.56.0 (2024-04-19) + ## 3.55.0 (2024-04-03) ## 3.54.0 (2024-03-21) diff --git a/packages/autop/package.json b/packages/autop/package.json index de808d270ff367..761c2ea92d2e78 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "3.55.0", + "version": "3.56.0", "description": "WordPress's automatic paragraph functions `autop` and `removep`.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md index 4a0d59cf95bd56..b188b86a9722ff 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.39.0 (2024-04-19) + ## 4.38.0 (2024-04-03) ## 4.37.0 (2024-03-21) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index efa45964304e3f..a5ede8247a3918 100644 --- a/packages/babel-plugin-import-jsx-pragma/package.json +++ b/packages/babel-plugin-import-jsx-pragma/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "4.38.0", + "version": "4.39.0", "description": "Babel transform plugin for automatically injecting an import to be used as the pragma for the React JSX Transform plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-plugin-makepot/CHANGELOG.md b/packages/babel-plugin-makepot/CHANGELOG.md index 66b8bdf881e227..361414c736d1db 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.40.0 (2024-04-19) + ## 5.39.0 (2024-04-03) ## 5.38.0 (2024-03-21) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index 78256f730ba495..584e6e1ee07c5b 100644 --- a/packages/babel-plugin-makepot/package.json +++ b/packages/babel-plugin-makepot/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-plugin-makepot", - "version": "5.39.0", + "version": "5.40.0", "description": "WordPress Babel internationalization (i18n) plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/babel-preset-default/CHANGELOG.md b/packages/babel-preset-default/CHANGELOG.md index 586ea36a9f341f..ea63bf2e2e5194 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.40.0 (2024-04-19) + ## 7.39.0 (2024-04-03) ## 7.38.0 (2024-03-21) diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index ffd759abfcd48c..077d0284613e73 100644 --- a/packages/babel-preset-default/package.json +++ b/packages/babel-preset-default/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/babel-preset-default", - "version": "7.39.0", + "version": "7.40.0", "description": "Default Babel preset for WordPress development.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/base-styles/CHANGELOG.md b/packages/base-styles/CHANGELOG.md index 193e8781b6cc6c..e056a6041fdbb9 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.47.0 (2024-04-19) + ## 4.46.0 (2024-04-03) ## 4.45.0 (2024-03-21) diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index b5d6beabb4f604..d995ccb31bbf5f 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -4,6 +4,7 @@ $z-layers: ( ".block-editor-block-list__block::before": 0, + ".block-editor-block-list__block.is-selected": 20, ".block-editor-block-switcher__arrow": 1, ".block-editor-block-list__block {core/image aligned wide or fullwide}": 20, ".block-library-classic__toolbar": 31, // When scrolled to top this toolbar needs to sit over block-editor-block-toolbar diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index e333ec49de511f..8bf9eb809fd95a 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "4.46.0", + "version": "4.47.0", "description": "Base SCSS utilities and variables for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md index fd1bf5a5ad127f..3e50e3f4cf349f 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.56.0 (2024-04-19) + ## 3.55.0 (2024-04-03) ## 3.54.0 (2024-03-21) diff --git a/packages/blob/package.json b/packages/blob/package.json index 28a33bd18fac41..833fa2c6ad90f0 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "3.55.0", + "version": "3.56.0", "description": "Blob utilities for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-directory/CHANGELOG.md b/packages/block-directory/CHANGELOG.md index 2d15643bbb32af..1373124b74262c 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.33.0 (2024-04-19) + ## 4.32.0 (2024-04-03) ## 4.31.0 (2024-03-21) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 5f50ec3ebe6673..841265ecfaa6e9 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "4.32.0", + "version": "4.33.0", "description": "Extend editor with block directory features to search, download and install blocks.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index c471eb84ace9a4..b5b9253db3aa04 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 12.24.0 (2024-04-19) + ## 12.23.0 (2024-04-03) ## 12.22.0 (2024-03-21) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 75f4d1143895ec..154ea248ae6518 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -1032,6 +1032,10 @@ _Returns_ A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. +_Parameters_ + +- _zoomOut_ `boolean`: If we should enter into zoomOut mode or not + ### Warning _Related_ diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index 5a99129760d3c5..674d4058d64bdc 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "12.23.0", + "version": "12.24.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index 5c52ca62e01d69..6da035a883ffb1 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -30,6 +30,8 @@ import BlockInfo from '../block-info-slot-fill'; import BlockQuickNavigation from '../block-quick-navigation'; import { useBorderPanelLabel } from '../../hooks/border'; +import { unlock } from '../../lock-unlock'; + function BlockInspectorLockedBlocks( { topLevelLockedBlock } ) { const contentClientIds = useSelect( ( select ) => { @@ -76,9 +78,9 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { getSelectedBlockClientId, getSelectedBlockCount, getBlockName, - __unstableGetContentLockingParent, + getContentLockingParent, getTemplateLock, - } = select( blockEditorStore ); + } = unlock( select( blockEditorStore ) ); const _selectedBlockClientId = getSelectedBlockClientId(); const _selectedBlockName = @@ -92,7 +94,7 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { selectedBlockName: _selectedBlockName, blockType: _blockType, topLevelLockedBlock: - __unstableGetContentLockingParent( _selectedBlockClientId ) || + getContentLockingParent( _selectedBlockClientId ) || ( getTemplateLock( _selectedBlockClientId ) === 'contentOnly' || _selectedBlockName === 'core/block' ? _selectedBlockClientId diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 82d6aac18cb6a2..290d2f05414828 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -526,7 +526,7 @@ function BlockListBlockProvider( props ) { canMoveBlock, getSettings, - __unstableGetTemporarilyEditingAsBlocks, + getTemporarilyEditingAsBlocks, getBlockEditingMode, getBlockName, isFirstMultiSelectedBlock, @@ -620,7 +620,7 @@ function BlockListBlockProvider( props ) { canMove, isSelected: _isSelected, isTemporarilyEditingAsBlocks: - __unstableGetTemporarilyEditingAsBlocks() === clientId, + getTemporarilyEditingAsBlocks() === clientId, blockEditingMode, mayDisplayControls: _isSelected || diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index 9184f3d9355ec7..3971df611c277e 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -183,6 +183,14 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b user-select: none; } + &.has-negative-margin { + &.is-selected, + &.has-child-selected { + // Bring the selected block forward so we can see it. + z-index: z-index(".block-editor-block-list__block.is-selected"); + } + } + .reusable-block-edit-panel * { z-index: z-index(".block-editor-block-list__block .reusable-block-edit-panel *"); } @@ -487,8 +495,9 @@ body.is-zoomed-out { } .block-editor-iframe__html { - transition: all 0.3s; transform-origin: top center; + transition: all 0.3s; + @include reduce-motion("transition"); } .block-editor-iframe__html[style*="scale"] { diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index 825deb9f5b4368..1faffef6ba3941 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -55,15 +55,14 @@ function Root( { className, ...settings } ) { const { getSettings, __unstableGetEditorMode, - __unstableGetTemporarilyEditingAsBlocks, - } = select( blockEditorStore ); + getTemporarilyEditingAsBlocks, + } = unlock( select( blockEditorStore ) ); const { outlineMode, focusMode } = getSettings(); return { isOutlineMode: outlineMode, isFocusMode: focusMode, editorMode: __unstableGetEditorMode(), - temporarilyEditingAsBlocks: - __unstableGetTemporarilyEditingAsBlocks(), + temporarilyEditingAsBlocks: getTemporarilyEditingAsBlocks(), }; }, [] ); const registry = useRegistry(); @@ -205,11 +204,10 @@ function Items( { visibleBlocks: __unstableGetVisibleBlocks(), shouldRenderAppender: hasAppender && + __unstableGetEditorMode() !== 'zoom-out' && ( hasCustomAppender ? ! getTemplateLock( rootClientId ) && - getBlockEditingMode( rootClientId ) !== - 'disabled' && - __unstableGetEditorMode() !== 'zoom-out' + getBlockEditingMode( rootClientId ) !== 'disabled' : rootClientId === selectedBlockClientId || ( ! rootClientId && ! selectedBlockClientId && diff --git a/packages/block-editor/src/components/block-list/index.native.js b/packages/block-editor/src/components/block-list/index.native.js index c531ea8db4893d..830b7ffec02f4d 100644 --- a/packages/block-editor/src/components/block-list/index.native.js +++ b/packages/block-editor/src/components/block-list/index.native.js @@ -211,7 +211,7 @@ export default function BlockList( { ); }; - const { blockToolbar, headerToolbar, floatingToolbar } = styles; + const { blockToolbar, floatingToolbar } = styles; const containerStyle = { flex: isRootList ? 1 : 0, @@ -224,7 +224,6 @@ export default function BlockList( { const isMultiBlocks = blockClientIds.length > 1; const { isWider } = alignmentHelpers; const extraScrollHeight = - headerToolbar.height + blockToolbar.height + ( isFloatingToolbarVisible ? floatingToolbar.height : 0 ); @@ -245,14 +244,10 @@ export default function BlockList( { { ( { onScroll } ) => ( { const { getBlockEditingMode, @@ -28,24 +27,30 @@ export function useHasBlockToolbar() { // for the toolbar, so we use getBlockSelectionStart // instead of getSelectedBlockClientIds const selectedBlockClientId = getBlockSelectionStart(); - const isDefaultEditingMode = - getBlockEditingMode( selectedBlockClientId ) === 'default'; + const blockType = selectedBlockClientId && getBlockType( getBlockName( selectedBlockClientId ) ); - const isToolbarEnabled = - blockType && - hasBlockSupport( blockType, '__experimentalToolbar', true ); - if ( - ! isToolbarEnabled || - ( ! isDefaultEditingMode && ! hasAnyBlockControls ) - ) { - return false; - } - - return true; + return { + isToolbarEnabled: + blockType && + hasBlockSupport( blockType, '__experimentalToolbar', true ), + isDefaultEditingMode: + getBlockEditingMode( selectedBlockClientId ) === 'default', + }; }, - [ hasAnyBlockControls ] + [] ); + + const hasAnyBlockControls = useHasAnyBlockControls(); + + if ( + ! isToolbarEnabled || + ( ! isDefaultEditingMode && ! hasAnyBlockControls ) + ) { + return false; + } + + return true; } diff --git a/packages/block-editor/src/components/block-tools/use-show-block-tools.js b/packages/block-editor/src/components/block-tools/use-show-block-tools.js index 633a0272b23e4e..a6af89388b497f 100644 --- a/packages/block-editor/src/components/block-tools/use-show-block-tools.js +++ b/packages/block-editor/src/components/block-tools/use-show-block-tools.js @@ -8,7 +8,6 @@ import { isUnmodifiedDefaultBlock } from '@wordpress/blocks'; * Internal dependencies */ import { store as blockEditorStore } from '../../store'; -import { useHasBlockToolbar } from '../block-toolbar/use-has-block-toolbar'; /** * Source of truth for which block tools are showing in the block editor. @@ -16,55 +15,44 @@ import { useHasBlockToolbar } from '../block-toolbar/use-has-block-toolbar'; * @return {Object} Object of which block tools will be shown. */ export function useShowBlockTools() { - const hasBlockToolbar = useHasBlockToolbar(); + return useSelect( ( select ) => { + const { + getSelectedBlockClientId, + getFirstMultiSelectedBlockClientId, + getBlock, + getSettings, + hasMultiSelection, + __unstableGetEditorMode, + isTyping, + } = select( blockEditorStore ); - return useSelect( - ( select ) => { - const { - getSelectedBlockClientId, - getFirstMultiSelectedBlockClientId, - getBlock, - getSettings, - hasMultiSelection, - __unstableGetEditorMode, - isTyping, - } = select( blockEditorStore ); + const clientId = + getSelectedBlockClientId() || getFirstMultiSelectedBlockClientId(); - const clientId = - getSelectedBlockClientId() || - getFirstMultiSelectedBlockClientId(); + const block = getBlock( clientId ) || { name: '', attributes: {} }; + const editorMode = __unstableGetEditorMode(); + const hasSelectedBlock = clientId && block?.name; + const isEmptyDefaultBlock = isUnmodifiedDefaultBlock( block ); + const _showEmptyBlockSideInserter = + clientId && + ! isTyping() && + editorMode === 'edit' && + isEmptyDefaultBlock; + const maybeShowBreadcrumb = + hasSelectedBlock && + ! hasMultiSelection() && + ( editorMode === 'navigation' || editorMode === 'zoom-out' ); - const block = getBlock( clientId ) || { name: '', attributes: {} }; - const editorMode = __unstableGetEditorMode(); - const hasSelectedBlock = clientId && block?.name; - const isEmptyDefaultBlock = isUnmodifiedDefaultBlock( block ); - const _showEmptyBlockSideInserter = - clientId && - ! isTyping() && - editorMode === 'edit' && - isEmptyDefaultBlock; - const maybeShowBreadcrumb = + return { + showEmptyBlockSideInserter: _showEmptyBlockSideInserter, + showBreadcrumb: + ! _showEmptyBlockSideInserter && maybeShowBreadcrumb, + showBlockToolbarPopover: + ! getSettings().hasFixedToolbar && + ! _showEmptyBlockSideInserter && hasSelectedBlock && - ! hasMultiSelection() && - ( editorMode === 'navigation' || editorMode === 'zoom-out' ); - - return { - showEmptyBlockSideInserter: _showEmptyBlockSideInserter, - showBreadcrumb: - ! _showEmptyBlockSideInserter && maybeShowBreadcrumb, - showBlockToolbarPopover: - hasBlockToolbar && - ! getSettings().hasFixedToolbar && - ! _showEmptyBlockSideInserter && - hasSelectedBlock && - ! isEmptyDefaultBlock && - ! maybeShowBreadcrumb, - showFixedToolbar: - editorMode !== 'zoom-out' && - hasBlockToolbar && - getSettings().hasFixedToolbar, - }; - }, - [ hasBlockToolbar ] - ); + ! isEmptyDefaultBlock && + ! maybeShowBreadcrumb, + }; + }, [] ); } diff --git a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js index 3c42bdcdb4a48d..e3d411d07f7260 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-mode-inserters.js @@ -10,11 +10,15 @@ import { useEffect, useState } from '@wordpress/element'; import BlockPopoverInbetween from '../block-popover/inbetween'; import { store as blockEditorStore } from '../../store'; import Inserter from '../inserter'; +import { unlock } from '../../lock-unlock'; function ZoomOutModeInserters( { __unstableContentRef } ) { const [ isReady, setIsReady ] = useState( false ); const blockOrder = useSelect( ( select ) => { - return select( blockEditorStore ).getBlockOrder(); + const { sectionRootClientId } = unlock( + select( blockEditorStore ).getSettings() + ); + return select( blockEditorStore ).getBlockOrder( sectionRootClientId ); }, [] ); // Defer the initial rendering to avoid the jumps due to the animation. diff --git a/packages/block-editor/src/components/default-block-appender/content.scss b/packages/block-editor/src/components/default-block-appender/content.scss index a09de4ab36f0ce..77725d2508ec5e 100644 --- a/packages/block-editor/src/components/default-block-appender/content.scss +++ b/packages/block-editor/src/components/default-block-appender/content.scss @@ -31,7 +31,7 @@ // Such shifts happen when the bottom margin of the Title block has been set to less than the default 1em margin of paragraphs. :where(body .is-layout-constrained) &, :where(.wp-site-blocks) & { - > :first-child:first-child { + > :first-child { margin-block-start: 0; margin-block-end: 0; } diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js index 94e53eec163721..6e5c46d85b9008 100644 --- a/packages/block-editor/src/components/global-styles/dimensions-panel.js +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -17,7 +17,7 @@ import { __experimentalView as View, } from '@wordpress/components'; import { Icon, positionCenter, stretchWide } from '@wordpress/icons'; -import { useCallback, Platform } from '@wordpress/element'; +import { useCallback, useState, Platform } from '@wordpress/element'; /** * Internal dependencies @@ -248,6 +248,10 @@ export default function DimensionsPanel( { ], } ); + //Minimum Margin Value + const minimumMargin = -Infinity; + const [ minMarginValue, setMinMarginValue ] = useState( minimumMargin ); + // Content Size const showContentSizeControl = useHasContentSize( settings ) && includeLayoutControls; @@ -435,6 +439,17 @@ export default function DimensionsPanel( { const onMouseLeaveControls = () => onVisualize( false ); + const inputProps = { + min: minMarginValue, + onDragStart: () => { + //Reset to 0 in case the value was negative. + setMinMarginValue( 0 ); + }, + onDragEnd: () => { + setMinMarginValue( minimumMargin ); + }, + }; + return ( { }; expect( toStyles( tree, blockSelectors ) ).toEqual( - 'body {margin: 0;}body .is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }body .is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }body .is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }body .is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }body .is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }body .is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }body .is-layout-flex { flex-wrap: wrap; align-items: center; }body .is-layout-flex > * { margin: 0; }body .is-layout-grid { display:grid; }body .is-layout-grid > * { margin: 0; }' + - ':where(body){background-color: red;margin: 10px;padding: 10px;}:where(a:where(:not(.wp-element-button))){color: blue;}a:where(:not(.wp-element-button)):hover{color: orange;}a:where(:not(.wp-element-button)):focus{color: orange;}:where(h1){font-size: 42px;}:where(.wp-block-group){margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}:where(h1,h2,h3,h4,h5,h6){color: orange;}:where(h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button))){color: hotpink;}h1 a:where(:not(.wp-element-button)):hover,h2 a:where(:not(.wp-element-button)):hover,h3 a:where(:not(.wp-element-button)):hover,h4 a:where(:not(.wp-element-button)):hover,h5 a:where(:not(.wp-element-button)):hover,h6 a:where(:not(.wp-element-button)):hover{color: red;}h1 a:where(:not(.wp-element-button)):focus,h2 a:where(:not(.wp-element-button)):focus,h3 a:where(:not(.wp-element-button)):focus,h4 a:where(:not(.wp-element-button)):focus,h5 a:where(:not(.wp-element-button)):focus,h6 a:where(:not(.wp-element-button)):focus{color: red;}' + - ':where(.wp-block-image img, .wp-block-image .wp-crop-area){border-radius: 9999px;}:where(.wp-block-image){color: red;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' + - '.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}' + 'body {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }:where(body){background-color: red;margin: 10px;padding: 10px;}:where(a:where(:not(.wp-element-button))){color: blue;}a:where(:not(.wp-element-button)):hover{color: orange;}a:where(:not(.wp-element-button)):focus{color: orange;}:where(h1){font-size: 42px;}:where(.wp-block-group){margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}:where(h1,h2,h3,h4,h5,h6){color: orange;}:where(h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button))){color: hotpink;}h1 a:where(:not(.wp-element-button)):hover,h2 a:where(:not(.wp-element-button)):hover,h3 a:where(:not(.wp-element-button)):hover,h4 a:where(:not(.wp-element-button)):hover,h5 a:where(:not(.wp-element-button)):hover,h6 a:where(:not(.wp-element-button)):hover{color: red;}h1 a:where(:not(.wp-element-button)):focus,h2 a:where(:not(.wp-element-button)):focus,h3 a:where(:not(.wp-element-button)):focus,h4 a:where(:not(.wp-element-button)):focus,h5 a:where(:not(.wp-element-button)):focus,h6 a:where(:not(.wp-element-button)):focus{color: red;}:where(.wp-block-image img, .wp-block-image .wp-crop-area){border-radius: 9999px;}:where(.wp-block-image){color: red;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}' ); } ); @@ -523,9 +520,7 @@ describe( 'global styles renderer', () => { }; expect( toStyles( Object.freeze( tree ), blockSelectors ) ).toEqual( - 'body {margin: 0;}body .is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }body .is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }body .is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }body .is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }body .is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }body .is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }body .is-layout-flex { flex-wrap: wrap; align-items: center; }body .is-layout-flex > * { margin: 0; }body .is-layout-grid { display:grid; }body .is-layout-grid > * { margin: 0; }' + - ':where(.wp-image-spacing){padding-top: 1px;}:where(.wp-image-border-color){border-color: red;}:where(.wp-image-border){border-radius: 9999px;}:where(.wp-image){color: red;}' + - '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' + 'body {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }:where(.wp-image-spacing){padding-top: 1px;}:where(.wp-image-border-color){border-color: red;}:where(.wp-image-border){border-radius: 9999px;}:where(.wp-image){color: red;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' ); } ); @@ -571,9 +566,7 @@ describe( 'global styles renderer', () => { }; expect( toStyles( Object.freeze( tree ), blockSelectors ) ).toEqual( - 'body {margin: 0;}body .is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }body .is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }body .is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }body .is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }body .is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }body .is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }body .is-layout-flex { flex-wrap: wrap; align-items: center; }body .is-layout-flex > * { margin: 0; }body .is-layout-grid { display:grid; }body .is-layout-grid > * { margin: 0; }' + - '.is-style-foo.wp-image.wp-image-spacing{padding-top: 2px;}.is-style-foo.wp-image.wp-image-border-color{border-color: blue;}.is-style-foo.wp-image{color: blue;}' + - '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' + 'body {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }.is-style-foo.wp-image.wp-image-spacing{padding-top: 2px;}.is-style-foo.wp-image.wp-image-border-color{border-color: blue;}.is-style-foo.wp-image{color: blue;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' ); } ); @@ -598,9 +591,7 @@ describe( 'global styles renderer', () => { }; expect( toStyles( Object.freeze( tree ), blockSelectors ) ).toEqual( - 'body {margin: 0;}body .is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }body .is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }body .is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }body .is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }body .is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }body .is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }body .is-layout-flex { flex-wrap: wrap; align-items: center; }body .is-layout-flex > * { margin: 0; }body .is-layout-grid { display:grid; }body .is-layout-grid > * { margin: 0; }' + - '.wp-image img{filter: blur(5px);}' + - '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' + 'body {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }.wp-image img{filter: blur(5px);}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' ); } ); @@ -717,7 +708,7 @@ describe( 'global styles renderer', () => { } ); expect( layoutStyles ).toEqual( - ':where(.is-layout-flex) { gap: 0.5em; }body .is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }body .is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }body .is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }body .is-layout-flex { flex-wrap: wrap; align-items: center; }body .is-layout-flex > * { margin: 0; }' + ':where(.is-layout-flex) { gap: 0.5em; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }' ); } ); @@ -734,7 +725,7 @@ describe( 'global styles renderer', () => { } ); expect( layoutStyles ).toEqual( - ':where(body .is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:where(body .is-layout-flow) > * + * { margin-block-start: 0.5em; margin-block-end: 0; }:where(body .is-layout-flex) { gap: 0.5em; }:root { --wp--style--block-gap: 0.5em; }body .is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }body .is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }body .is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }body .is-layout-flex { flex-wrap: wrap; align-items: center; }body .is-layout-flex > * { margin: 0; }' + ':where(.is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:where(.is-layout-flow) > * + * { margin-block-start: 0.5em; margin-block-end: 0; }:where(.is-layout-flex) { gap: 0.5em; }:root { --wp--style--block-gap: 0.5em; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }' ); } ); @@ -751,7 +742,7 @@ describe( 'global styles renderer', () => { } ); expect( layoutStyles ).toEqual( - ':where(body .is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:where(body .is-layout-flow) > * + * { margin-block-start: 12px; margin-block-end: 0; }:where(body .is-layout-flex) { gap: 12px; }:root { --wp--style--block-gap: 12px; }body .is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }body .is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }body .is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }body .is-layout-flex { flex-wrap: wrap; align-items: center; }body .is-layout-flex > * { margin: 0; }' + ':where(.is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:where(.is-layout-flow) > * + * { margin-block-start: 12px; margin-block-end: 0; }:where(.is-layout-flex) { gap: 12px; }:root { --wp--style--block-gap: 12px; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }' ); } ); @@ -768,7 +759,7 @@ describe( 'global styles renderer', () => { } ); expect( layoutStyles ).toEqual( - '.wp-block-group-is-layout-flow > * { margin-block-start: 0; margin-block-end: 0; }.wp-block-group-is-layout-flow > * + * { margin-block-start: 12px; margin-block-end: 0; }.wp-block-group-is-layout-flex { gap: 12px; }' + ':where(.wp-block-group-is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:where(.wp-block-group-is-layout-flow) > * + * { margin-block-start: 12px; margin-block-end: 0; }:where(.wp-block-group-is-layout-flex) { gap: 12px; }' ); } ); diff --git a/packages/block-editor/src/components/global-styles/typography-panel.js b/packages/block-editor/src/components/global-styles/typography-panel.js index 40fc692bae2dc4..76836c775bb807 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -350,7 +350,7 @@ export default function TypographyPanel( { > { hasFontFamilyEnabled && ( * { margin-block-start: ${ gapValue }; margin-block-end: 0; }`; ruleset = ruleset + - ':where(.wp-site-blocks) > :first-child:first-child { margin-block-start: 0; }'; + ':where(.wp-site-blocks) > :first-child { margin-block-start: 0; }'; ruleset = ruleset + - ':where(.wp-site-blocks) > :last-child:last-child { margin-block-end: 0; }'; + ':where(.wp-site-blocks) > :last-child { margin-block-end: 0; }'; } nodesWithSettings.forEach( ( { selector, presets } ) => { diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js index deb4328212b105..1dd3005b99d62d 100644 --- a/packages/block-editor/src/components/inner-blocks/index.js +++ b/packages/block-editor/src/components/inner-blocks/index.js @@ -204,6 +204,8 @@ export function useInnerBlocksProps( props = {}, options = {} ) { getBlockEditingMode, getBlockSettings, isDragging, + getSettings, + getBlockOrder, } = unlock( select( blockEditorStore ) ); const { hasBlockSupport, getBlockType } = select( blocksStore ); const blockName = getBlockName( clientId ); @@ -212,6 +214,17 @@ export function useInnerBlocksProps( props = {}, options = {} ) { const blockEditingMode = getBlockEditingMode( clientId ); const parentClientId = getBlockRootClientId( clientId ); const [ defaultLayout ] = getBlockSettings( clientId, 'layout' ); + + // In zoom out mode, we want to disable the drop zone for the sections. + // The inner blocks belonging to the section drop zone is + // already disabled by the blocks themselves being disabled. + let _isDropZoneDisabled = blockEditingMode === 'disabled'; + if ( __unstableGetEditorMode() === 'zoom-out' ) { + const { sectionRootClientId } = unlock( getSettings() ); + const sectionsClientIds = getBlockOrder( sectionRootClientId ); + _isDropZoneDisabled = sectionsClientIds?.includes( clientId ); + } + return { __experimentalCaptureToolbars: hasBlockSupport( blockName, @@ -228,7 +241,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) { blockType: getBlockType( blockName ), parentLock: getTemplateLock( parentClientId ), parentClientId, - isDropZoneDisabled: blockEditingMode === 'disabled', + isDropZoneDisabled: _isDropZoneDisabled, defaultLayout, }; }, diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/index.js b/packages/block-editor/src/components/inserter/block-patterns-tab/index.js index 378bd996bf93bf..d2f302683ed2da 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/index.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/index.js @@ -2,16 +2,9 @@ * WordPress dependencies */ import { useState } from '@wordpress/element'; -import { __, isRTL } from '@wordpress/i18n'; import { useViewportMatch } from '@wordpress/compose'; -import { - __experimentalItemGroup as ItemGroup, - __experimentalItem as Item, - __experimentalHStack as HStack, - FlexBlock, - Button, -} from '@wordpress/components'; -import { Icon, chevronRight, chevronLeft } from '@wordpress/icons'; +import { Button } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -20,93 +13,59 @@ import PatternsExplorerModal from '../block-patterns-explorer'; import MobileTabNavigation from '../mobile-tab-navigation'; import { PatternCategoryPreviews } from './pattern-category-previews'; import { usePatternCategories } from './use-pattern-categories'; +import CategoryTabs from '../category-tabs'; function BlockPatternsTab( { onSelectCategory, selectedCategory, onInsert, rootClientId, + children, } ) { const [ showPatternsExplorer, setShowPatternsExplorer ] = useState( false ); const categories = usePatternCategories( rootClientId ); - const initialCategory = selectedCategory || categories[ 0 ]; const isMobile = useViewportMatch( 'medium', '<' ); return ( <> { ! isMobile && (
- + { children } + +
) } { isMobile && ( { ( category ) => ( - +
+ +
) }
) } { showPatternsExplorer && ( setShowPatternsExplorer( false ) } rootClientId={ rootClientId } diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-preview-panel.js b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-preview-panel.js index 7a5a9eb8d989e6..04f25ade4880d5 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-preview-panel.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-preview-panel.js @@ -1,16 +1,8 @@ -/** - * WordPress dependencies - */ -import { useRef, useEffect } from '@wordpress/element'; - -import { focus } from '@wordpress/dom'; - /** * Internal dependencies */ import { PatternCategoryPreviews } from './pattern-category-previews'; -import { useZoomOut } from '../../../hooks/use-zoom-out'; export function PatternCategoryPreviewPanel( { rootClientId, @@ -20,34 +12,15 @@ export function PatternCategoryPreviewPanel( { showTitlesAsTooltip, patternFilter, } ) { - const container = useRef(); - - useEffect( () => { - const timeout = setTimeout( () => { - const [ firstTabbable ] = focus.tabbable.find( container.current ); - firstTabbable?.focus(); - } ); - return () => clearTimeout( timeout ); - }, [ category ] ); - - // Move to zoom out mode when this component is mounted - // and back to the previous mode when unmounted. - useZoomOut(); - return ( -
- -
+ ); } diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js index 7b8fd8e76202a2..8a4bedbb4a5fc6 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js @@ -128,7 +128,7 @@ export function PatternCategoryPreviews( { ); return ( -
+ <> ) } -
+ ); } diff --git a/packages/block-editor/src/components/inserter/category-tabs/index.js b/packages/block-editor/src/components/inserter/category-tabs/index.js new file mode 100644 index 00000000000000..47c9f0e051a66e --- /dev/null +++ b/packages/block-editor/src/components/inserter/category-tabs/index.js @@ -0,0 +1,74 @@ +/** + * WordPress dependencies + */ +import { isRTL } from '@wordpress/i18n'; +import { + __experimentalHStack as HStack, + FlexBlock, + privateApis as componentsPrivateApis, +} from '@wordpress/components'; +import { Icon, chevronRight, chevronLeft } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import { unlock } from '../../../lock-unlock'; + +const { Tabs } = unlock( componentsPrivateApis ); + +function CategoryTabs( { + categories, + selectedCategory, + onSelectCategory, + children, +} ) { + return ( + { + // Pass the full category object + onSelectCategory( + categories.find( + ( category ) => category.name === categoryId + ) + ); + } } + > + + { categories.map( ( category ) => ( + + + { category.label } + + + + ) ) } + + { categories.map( ( category ) => ( + + { children } + + ) ) } + + ); +} + +export default CategoryTabs; diff --git a/packages/block-editor/src/components/inserter/media-tab/index.js b/packages/block-editor/src/components/inserter/media-tab/index.js index 6e4c518ff63b5e..2a44fd922f5239 100644 --- a/packages/block-editor/src/components/inserter/media-tab/index.js +++ b/packages/block-editor/src/components/inserter/media-tab/index.js @@ -1,3 +1,3 @@ export { default as MediaTab } from './media-tab'; -export { MediaCategoryDialog } from './media-panel'; +export { MediaCategoryPanel } from './media-panel'; export { useMediaCategories } from './hooks'; diff --git a/packages/block-editor/src/components/inserter/media-tab/media-panel.js b/packages/block-editor/src/components/inserter/media-tab/media-panel.js index 49601c9c8ad1bc..9a55bd5ef99cef 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-panel.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-panel.js @@ -1,9 +1,7 @@ /** * WordPress dependencies */ -import { useRef, useEffect } from '@wordpress/element'; import { Spinner, SearchControl } from '@wordpress/components'; -import { focus } from '@wordpress/dom'; import { __ } from '@wordpress/i18n'; import { useDebouncedInput } from '@wordpress/compose'; @@ -16,26 +14,6 @@ import InserterNoResults from '../no-results'; const INITIAL_MEDIA_ITEMS_PER_PAGE = 10; -export function MediaCategoryDialog( { rootClientId, onInsert, category } ) { - const container = useRef(); - useEffect( () => { - const timeout = setTimeout( () => { - const [ firstTabbable ] = focus.tabbable.find( container.current ); - firstTabbable?.focus(); - } ); - return () => clearTimeout( timeout ); - }, [ category ] ); - return ( -
- -
- ); -} - export function MediaCategoryPanel( { rootClientId, onInsert, category } ) { const [ search, setSearch, debouncedSearch ] = useDebouncedInput(); const { mediaList, isLoading } = useMediaResults( category, { diff --git a/packages/block-editor/src/components/inserter/media-tab/media-preview.js b/packages/block-editor/src/components/inserter/media-tab/media-preview.js index ad6239c61d2f7b..807123f327664c 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-preview.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-preview.js @@ -127,23 +127,31 @@ export function MediaPreview( { media, onClick, category } ) { ); const { createErrorNotice, createSuccessNotice } = useDispatch( noticesStore ); - const mediaUpload = useSelect( - ( select ) => select( blockEditorStore ).getSettings().mediaUpload, - [] - ); + const { getSettings } = useSelect( blockEditorStore ); + const onMediaInsert = useCallback( ( previewBlock ) => { // Prevent multiple uploads when we're in the process of inserting. if ( isInserting ) { return; } + + const settings = getSettings(); const clonedBlock = cloneBlock( previewBlock ); const { id, url, caption } = clonedBlock.attributes; + + // User has no permission to upload media. + if ( ! id && ! settings.mediaUpload ) { + setShowExternalUploadModal( true ); + return; + } + // Media item already exists in library, so just insert it. if ( !! id ) { onClick( clonedBlock ); return; } + setIsInserting( true ); // Media item does not exist in library, so try to upload it. // Fist fetch the image data. This may fail if the image host @@ -154,7 +162,7 @@ export function MediaPreview( { media, onClick, category } ) { .fetch( url ) .then( ( response ) => response.blob() ) .then( ( blob ) => { - mediaUpload( { + settings.mediaUpload( { filesList: [ blob ], additionalData: { caption }, onFileChange( [ img ] ) { @@ -189,10 +197,10 @@ export function MediaPreview( { media, onClick, category } ) { }, [ isInserting, + getSettings, onClick, - mediaUpload, - createErrorNotice, createSuccessNotice, + createErrorNotice, ] ); diff --git a/packages/block-editor/src/components/inserter/media-tab/media-tab.js b/packages/block-editor/src/components/inserter/media-tab/media-tab.js index b448ae2a406499..c5f462210fa4a4 100644 --- a/packages/block-editor/src/components/inserter/media-tab/media-tab.js +++ b/packages/block-editor/src/components/inserter/media-tab/media-tab.js @@ -1,22 +1,10 @@ -/** - * External dependencies - */ -import classNames from 'classnames'; - /** * WordPress dependencies */ -import { __, isRTL } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; import { useViewportMatch } from '@wordpress/compose'; -import { - __experimentalItemGroup as ItemGroup, - __experimentalItem as Item, - __experimentalHStack as HStack, - FlexBlock, - Button, -} from '@wordpress/components'; +import { Button } from '@wordpress/components'; import { useCallback, useMemo } from '@wordpress/element'; -import { Icon, chevronRight, chevronLeft } from '@wordpress/icons'; /** * Internal dependencies @@ -27,6 +15,7 @@ import MediaUpload from '../../media-upload'; import { useMediaCategories } from './hooks'; import { getBlockAndPreviewFromMedia } from './utils'; import MobileTabNavigation from '../mobile-tab-navigation'; +import CategoryTabs from '../category-tabs'; const ALLOWED_MEDIA_TYPES = [ 'image', 'video', 'audio' ]; @@ -35,6 +24,7 @@ function MediaTab( { selectedCategory, onSelectCategory, onInsert, + children, } ) { const mediaCategories = useMediaCategories( rootClientId ); const isMobile = useViewportMatch( 'medium', '<' ); @@ -49,7 +39,7 @@ function MediaTab( { }, [ onInsert ] ); - const mobileMediaCategories = useMemo( + const categories = useMemo( () => mediaCategories.map( ( mediaCategory ) => ( { ...mediaCategory, @@ -57,82 +47,48 @@ function MediaTab( { } ) ), [ mediaCategories ] ); + return ( <> { ! isMobile && (
-
- - + { __( 'Open Media Library' ) } + + ) } + /> + ) } { isMobile && ( - + { ( category ) => ( {}; function InserterMenu( @@ -122,9 +123,23 @@ function InserterMenu( __experimentalOnPatternCategorySelection(); } }, - [ setSelectedPatternCategory, __experimentalOnPatternCategorySelection ] + [ + setSelectedPatternCategory, + __experimentalOnPatternCategorySelection, + isZoomedOutViewExperimentEnabled, + ] ); + const showPatternPanel = + selectedTab === 'patterns' && + ! delayedFilterValue && + selectedPatternCategory; + + const showMediaPanel = + selectedTab === 'media' && + ! delayedFilterValue && + selectedMediaCategory; + const blocksTab = useMemo( () => ( <> @@ -162,13 +177,27 @@ function InserterMenu( onInsert={ onInsertPattern } onSelectCategory={ onClickPatternCategory } selectedCategory={ selectedPatternCategory } - /> + > + { showPatternPanel && ( + + ) } + ), [ destinationRootClientId, + onHoverPattern, onInsertPattern, onClickPatternCategory, + patternFilter, selectedPatternCategory, + showPatternPanel, ] ); @@ -179,13 +208,22 @@ function InserterMenu( selectedCategory={ selectedMediaCategory } onSelectCategory={ setSelectedMediaCategory } onInsert={ onInsert } - /> + > + { showMediaPanel && ( + + ) } + ), [ destinationRootClientId, onInsert, selectedMediaCategory, setSelectedMediaCategory, + showMediaPanel, ] ); @@ -205,15 +243,10 @@ function InserterMenu( }, } ) ); - const showPatternPanel = - selectedTab === 'patterns' && - ! delayedFilterValue && - selectedPatternCategory; const showAsTabs = ! delayedFilterValue && ( showPatterns || showMedia ); - const showMediaPanel = - selectedTab === 'media' && - ! delayedFilterValue && - selectedMediaCategory; + + // When the pattern panel is showing, we want to use zoom out mode + useZoomOut( showPatternPanel ); const handleSetSelectedTab = ( value ) => { // If no longer on patterns tab remove the category setting. @@ -224,7 +257,11 @@ function InserterMenu( }; return ( -
+
) }
- { showMediaPanel && ( - - ) } { showInserterHelpPanel && hoveredItem && ( ) } - { showPatternPanel && ( - - ) }
); } diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index 580e4ec0e21f26..5e35180ae7c45c 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -62,7 +62,7 @@ $block-inserter-tabs-height: 44px; .block-editor-inserter__popover .block-editor-inserter__menu { margin: -$grid-unit-15; - .block-editor-inserter__tabs div[role="tablist"] { + .block-editor-inserter__tablist { top: $grid-unit-10 + $grid-unit-20 + $grid-unit-60 - $grid-unit-15; } @@ -115,7 +115,7 @@ $block-inserter-tabs-height: 44px; flex-direction: column; overflow: hidden; - div[role="tablist"] { + .block-editor-inserter__tablist { border-bottom: $border-width solid $gray-300; button[role="tab"] { @@ -130,7 +130,7 @@ $block-inserter-tabs-height: 44px; } } - div[role="tabpanel"] { + .block-editor-inserter__tabpanel { display: flex; flex-grow: 1; flex-direction: column; @@ -228,7 +228,7 @@ $block-inserter-tabs-height: 44px; display: block; } - .block-editor-block-preview__container { + .block-editor-inserter__media-list__list-item { height: 100%; } @@ -239,63 +239,81 @@ $block-inserter-tabs-height: 44px; } } -.block-editor-inserter__patterns-explore-button.components-button { - padding: $grid-unit-20; - justify-content: center; - margin-top: $grid-unit-20; - width: 100%; -} - -.block-editor-inserter__patterns-selected-category.block-editor-inserter__patterns-selected-category { - color: var(--wp-admin-theme-color); - position: relative; - - .components-flex-item { - filter: brightness(0.95); - } - - svg { - fill: var(--wp-admin-theme-color); - } - - &::after { - content: ""; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - border-radius: $radius-block-ui; - opacity: 0.04; - background: var(--wp-admin-theme-color); - } -} - +.block-editor-inserter__media-tabs-container, .block-editor-inserter__block-patterns-tabs-container { + padding: $grid-unit-20; height: 100%; - nav { - height: 100%; - } + display: flex; + flex-direction: column; + justify-content: space-between; } -.block-editor-inserter__block-patterns-tabs { +.block-editor-inserter__category-tablist { display: flex; flex-direction: column; - padding: $grid-unit-20; - overflow-y: auto; - height: 100%; + border: none; + margin-bottom: $grid-unit-10; // Push the listitem wrapping the "explore" button to the bottom of the panel. div[role="listitem"]:last-child { margin-top: auto; } - .block-editor-inserter__patterns-category { + .block-editor-inserter__category-tab { // Account for the icon on the right so that it's visually balanced. - padding-right: $grid-unit-05; + padding: $grid-unit-10 $grid-unit-05 $grid-unit-10 $grid-unit-15; + text-align: left; + font-weight: inherit; + display: block; + position: relative; + height: auto; + + &[aria-selected="true"] { + color: var(--wp-admin-theme-color); + + .components-flex-item { + filter: brightness(0.95); + } + + svg { + fill: var(--wp-admin-theme-color); + } + + &::after { + content: ""; + display: block; + outline: none; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + border-radius: $radius-block-ui; + opacity: 0.04; + background: var(--wp-admin-theme-color); + height: 100%; + } + } + + &:focus-visible, + &:focus:not(:disabled) { + border-radius: 2px; + box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + // Windows high contrast mode. + outline: 2px solid transparent; + outline-offset: 0; + } + + &::before { + display: none; + } + + &::after { + display: none; + } } } -.block-editor-inserter__patterns-category-dialog { +.block-editor-inserter__category-panel { background: $gray-100; border-left: $border-width solid $gray-200; border-right: $border-width solid $gray-200; @@ -304,35 +322,30 @@ $block-inserter-tabs-height: 44px; left: 0; height: 100%; width: 100%; + padding: 0 $grid-unit-20; + display: flex; + flex-direction: column; @include break-medium { + padding: 0; left: 100%; - display: block; width: 300px; } +} - .block-editor-block-patterns-list { - overflow-y: auto; - flex-grow: 1; - height: 100%; - padding: $grid-unit-20 $grid-unit-30; - } +.block-editor-inserter__patterns-category-panel-header { + padding: 16px $grid-unit-30; +} +.block-editor-inserter__patterns-category-no-results { + margin-top: $grid-unit-30; } -.block-editor-inserter__patterns-category-panel { - padding: 0 $grid-unit-20; - display: flex; - flex-direction: column; +.block-editor-inserter__media-list, +.block-editor-block-patterns-list { + overflow-y: auto; + flex-grow: 1; height: 100%; - @include break-medium { - padding: 0; - } - .block-editor-inserter__patterns-category-panel-header { - padding: 16px $grid-unit-30; - } - .block-editor-inserter__patterns-category-no-results { - margin-top: $grid-unit-30; - } + padding: $grid-unit-20 $grid-unit-30; } .block-editor-inserter__preview-content { @@ -392,7 +405,7 @@ $block-inserter-tabs-height: 44px; .block-editor-block-patterns-list__list-item { margin-bottom: 0; } - .block-editor-block-preview__container { + .block-editor-inserter__media-list__list-item { min-height: 100px; } } @@ -485,7 +498,7 @@ $block-inserter-tabs-height: 44px; min-height: 240px; } - .block-editor-block-preview__container { + .block-editor-inserter__media-list__list-item { height: inherit; min-height: 100px; max-height: 800px; @@ -497,14 +510,9 @@ $block-inserter-tabs-height: 44px; font-size: calc(1.25 * 13px); } -.block-editor-inserter__media-tabs-container { - height: 100%; - - nav { - height: 100%; - } - - .block-editor-inserter__media-library-button { +.block-editor-inserter__patterns-explore-button, +.block-editor-inserter__media-library-button { + &.components-button { padding: $grid-unit-20; justify-content: center; margin-top: $grid-unit-20; @@ -512,76 +520,6 @@ $block-inserter-tabs-height: 44px; } } -.block-editor-inserter__media-tabs { - display: flex; - flex-direction: column; - padding: $grid-unit-20; - overflow-y: auto; - height: 100%; - - // Push the listitem wrapping the "open media library" button to the bottom of the panel. - div[role="listitem"]:last-child { - margin-top: auto; - } - - .block-editor-inserter__media-tabs__media-category { - // Account for the icon on the right so that it's visually balanced. - padding-right: $grid-unit-05; - - &.is-selected { - color: var(--wp-admin-theme-color); - position: relative; - - .components-flex-item { - filter: brightness(0.95); - } - - svg { - fill: var(--wp-admin-theme-color); - } - - &::after { - content: ""; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - border-radius: $radius-block-ui; - opacity: 0.04; - background: var(--wp-admin-theme-color); - } - } - } -} - -.block-editor-inserter__media-dialog { - background: $gray-100; - border-left: $border-width solid $gray-200; - border-right: $border-width solid $gray-200; - position: absolute; - padding: $grid-unit-20 $grid-unit-30; - top: 0; - left: 0; - height: 100%; - width: 100%; - overflow-y: auto; - scrollbar-gutter: stable both-edges; - - @include break-medium { - left: 100%; - display: block; - width: 300px; - } - - .block-editor-block-preview__container { - box-shadow: 0 15px 25px rgb(0 0 0 / 7%); - &:hover { - box-shadow: 0 0 0 2px $gray-900, 0 15px 25px rgb(0 0 0 / 7%); - } - } -} - .block-editor-inserter__media-panel { min-height: 100%; padding: 0 $grid-unit-20; @@ -601,6 +539,7 @@ $block-inserter-tabs-height: 44px; } .block-editor-inserter__media-panel-search { + padding: $grid-unit-20 $grid-unit-30 0; // TODO: Consider using the Theme component to automatically adapt to a gray background. &:not(:focus-within) { --wp-components-color-background: #{$white}; @@ -608,90 +547,88 @@ $block-inserter-tabs-height: 44px; } } -.block-editor-inserter__media-list { - margin-top: $grid-unit-20; - .block-editor-inserter__media-list__list-item { - position: relative; - cursor: pointer; - margin-bottom: $grid-unit-30; +.block-editor-inserter__media-list__list-item { + position: relative; + cursor: pointer; + margin-bottom: $grid-unit-30; + box-shadow: 0 15px 25px rgb(0 0 0 / 7%); - &.is-placeholder { - min-height: 100px; - } + &.is-placeholder { + min-height: 100px; + } - &[draggable="true"] .block-editor-block-preview__container { - cursor: grab; + &[draggable="true"] .block-editor-inserter__media-list__list-item { + cursor: grab; + } + + &.is-hovered { + .block-editor-inserter__media-list__item-preview { + box-shadow: 0 0 0 2px $gray-900, 0 15px 25px rgb(0 0 0 / 7%); } - &.is-hovered { - .block-editor-inserter__media-list__item-preview { - box-shadow: 0 0 0 2px $gray-900, 0 15px 25px rgb(0 0 0 / 7%); - } + .block-editor-inserter__media-list__item-preview-options > button { + display: block; + } + } - .block-editor-inserter__media-list__item-preview-options > button { + .block-editor-inserter__media-list__item-preview-options { + position: absolute; + right: $grid-unit-10; + top: $grid-unit-10; + + > button { + background: $white; + border-radius: $radius-block-ui; + display: none; + + // These styles are important so as focus isn't lost + // when the button is focused and we hover away. + &.is-opened, + &:focus { display: block; } - } - - .block-editor-inserter__media-list__item-preview-options { - position: absolute; - right: $grid-unit-10; - top: $grid-unit-10; - > button { - background: $white; - border-radius: $radius-block-ui; - display: none; - - // These styles are important so as focus isn't lost - // when the button is focused and we hover away. - &.is-opened, - &:focus { - display: block; - } - - &:hover { - box-shadow: inset 0 0 0 2px $white, 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + &:hover { + box-shadow: inset 0 0 0 2px $white, 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - // Windows High Contrast mode will show this outline, but not the box-shadow. - outline: 2px solid transparent; - } + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; } } } +} - .block-editor-inserter__media-list__item { - height: 100%; +.block-editor-inserter__media-list__item { + height: 100%; - .block-editor-inserter__media-list__item-preview { - display: flex; - align-items: center; - overflow: hidden; - border-radius: 2px; + .block-editor-inserter__media-list__item-preview { + display: flex; + align-items: center; + overflow: hidden; + border-radius: 2px; - > * { - margin: 0 auto; - max-width: 100%; - } + > * { + margin: 0 auto; + max-width: 100%; + } - .block-editor-inserter__media-list__item-preview-spinner { - display: flex; - height: 100%; - width: 100%; - position: absolute; - justify-content: center; - background: rgba($white, 0.7); - align-items: center; - pointer-events: none; - } + .block-editor-inserter__media-list__item-preview-spinner { + display: flex; + height: 100%; + width: 100%; + position: absolute; + justify-content: center; + background: rgba($white, 0.7); + align-items: center; + pointer-events: none; } + } - &:focus .block-editor-inserter__media-list__item-preview { - box-shadow: inset 0 0 0 2px $white, 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + &:focus .block-editor-inserter__media-list__item-preview { + box-shadow: inset 0 0 0 2px $white, 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - // Windows High Contrast mode will show this outline, but not the box-shadow. - outline: 2px solid transparent; - } + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; } } @@ -758,16 +695,23 @@ $block-inserter-tabs-height: 44px; } } +// Only relevant in zoom-out-mode +.block-editor-inserter__pattern-panel-placeholder { + display: none; +} + .is-zoom-out { .block-editor-inserter__menu { display: flex; } - .block-editor-inserter__patterns-category-dialog { - position: static; - } - - .block-editor-inserter__media-dialog { - position: static; + .show-panel::after { + // Makes space for the inserter flyout panel + @include break-medium { + content: ""; + display: block; + width: 300px; + height: 100%; + } } } diff --git a/packages/block-editor/src/components/inserter/tabs.js b/packages/block-editor/src/components/inserter/tabs.js index 4795c3ce4fdc24..ad9cd4888bd947 100644 --- a/packages/block-editor/src/components/inserter/tabs.js +++ b/packages/block-editor/src/components/inserter/tabs.js @@ -43,9 +43,13 @@ function InserterTabs( { return (
- + { tabs.map( ( tab ) => ( - + { tab.title } ) ) } @@ -55,6 +59,7 @@ function InserterTabs( { key={ tab.name } tabId={ tab.name } focusable={ false } + className="block-editor-inserter__tabpanel" > { tabsContents[ tab.name ] } diff --git a/packages/block-editor/src/components/list-view/block.js b/packages/block-editor/src/components/list-view/block.js index 930d0a0f80ef66..658188dbd0fc70 100644 --- a/packages/block-editor/src/components/list-view/block.js +++ b/packages/block-editor/src/components/list-view/block.js @@ -82,25 +82,26 @@ function ListViewBlock( { const blockInformation = useBlockDisplayInformation( clientId ); - const { block, blockName, blockEditingMode } = useSelect( - ( select ) => { - const { getBlock, getBlockName, getBlockEditingMode } = - select( blockEditorStore ); - - return { - block: getBlock( clientId ), - blockName: getBlockName( clientId ), - blockEditingMode: getBlockEditingMode( clientId ), - }; - }, - [ clientId ] - ); - - const allowRightClickOverrides = useSelect( - ( select ) => - select( blockEditorStore ).getSettings().allowRightClickOverrides, - [] - ); + const { block, blockName, blockEditingMode, allowRightClickOverrides } = + useSelect( + ( select ) => { + const { + getBlock, + getBlockName, + getBlockEditingMode, + getSettings, + } = select( blockEditorStore ); + + return { + block: getBlock( clientId ), + blockName: getBlockName( clientId ), + blockEditingMode: getBlockEditingMode( clientId ), + allowRightClickOverrides: + getSettings().allowRightClickOverrides, + }; + }, + [ clientId ] + ); const showBlockActions = // When a block hides its toolbar it also hides the block settings menu, diff --git a/packages/block-editor/src/components/list-view/index.js b/packages/block-editor/src/components/list-view/index.js index 8a696c6f56c241..7ef5d270f50a27 100644 --- a/packages/block-editor/src/components/list-view/index.js +++ b/packages/block-editor/src/components/list-view/index.js @@ -64,7 +64,7 @@ const expanded = ( state, action ) => { return state; }; -export const BLOCK_LIST_ITEM_HEIGHT = 36; +export const BLOCK_LIST_ITEM_HEIGHT = 32; /** @typedef {import('react').ComponentType} ComponentType */ /** @typedef {import('react').Ref} Ref */ diff --git a/packages/block-editor/src/components/list-view/style.scss b/packages/block-editor/src/components/list-view/style.scss index 7a9abb7a6b4814..ea3cc5bb78cdf3 100644 --- a/packages/block-editor/src/components/list-view/style.scss +++ b/packages/block-editor/src/components/list-view/style.scss @@ -156,13 +156,13 @@ &.is-displacement-up { transition: transform 0.2s; - transform: translateY(-36px); + transform: translateY(-32px); @include reduce-motion("transition"); } &.is-displacement-down { transition: transform 0.2s; - transform: translateY(36px); + transform: translateY(32px); @include reduce-motion("transition"); } @@ -172,20 +172,20 @@ // worth of space for the visual indicator of where a block will be placed when dropped. &.is-after-dragged-blocks { transition: transform 0.2s; - transform: translateY(calc(var(--wp-admin--list-view-dragged-items-height, 36px) * -1)); + transform: translateY(calc(var(--wp-admin--list-view-dragged-items-height, 32px) * -1)); @include reduce-motion("transition"); } &.is-after-dragged-blocks.is-displacement-up { transition: transform 0.2s; - transform: translateY(calc(-36px + var(--wp-admin--list-view-dragged-items-height, 36px) * -1)); + transform: translateY(calc(-32px + var(--wp-admin--list-view-dragged-items-height, 32px) * -1)); @include reduce-motion("transition"); } &.is-after-dragged-blocks.is-displacement-down { transition: transform 0.2s; transform: - translateY(calc(36px + var(--wp-admin--list-view-dragged-items-height, 36px) * + translateY(calc(32px + var(--wp-admin--list-view-dragged-items-height, 32px) * -1)); @include reduce-motion("transition"); } @@ -204,15 +204,15 @@ z-index: -9999; } - // List View renders a fixed number of items and relies on each item having a fixed height of 36px. + // List View renders a fixed number of items and relies on each item having a fixed height of 32px. // If this value changes, we should also change the itemHeight value set in useFixedWindowList. // See: https://github.com/WordPress/gutenberg/pull/35230 for additional context. .block-editor-list-view-block-contents { display: flex; align-items: center; width: 100%; - height: auto; - padding: ($grid-unit-15 * 0.5) ($grid-unit-15 * 0.5) ($grid-unit-15 * 0.5) 0; + height: $grid-unit-40; + padding: ($grid-unit-15 * 0.5) $grid-unit-05 ($grid-unit-15 * 0.5) 0; text-align: left; border-radius: $radius-block-ui; position: relative; @@ -277,15 +277,14 @@ } .block-editor-block-icon { - margin-right: $grid-unit-10; + margin-right: $grid-unit-10 * 0.5; // 6px. flex: 0 0 $icon-size; } .block-editor-list-view-block__menu-cell, .block-editor-list-view-block__mover-cell, .block-editor-list-view-block__contents-cell { - padding-top: 0; - padding-bottom: 0; + padding: 0; } .block-editor-list-view-block__menu-cell, @@ -316,7 +315,7 @@ } .block-editor-list-view-block__menu-cell { - padding-right: $grid-unit-15 * 0.5; // 6px. + padding-right: $grid-unit-05; .components-button.has-icon { height: 24px; @@ -379,8 +378,10 @@ } } - .block-editor-list-view-block-select-button__label-wrapper { - min-width: 120px; + // Style lock and position icons in line with image previews. + .block-editor-list-view-block-select-button__label-wrapper svg { + left: $grid-unit-05 * 0.5; // 2px. + position: relative; } .block-editor-list-view-block-select-button__title { @@ -464,21 +465,12 @@ $block-navigation-max-indent: 8; // Chevron container metrics. .block-editor-list-view__expander { height: $icon-size; - margin-left: $grid-unit-05; width: $icon-size; cursor: pointer; } .block-editor-list-view-leaf[aria-level] .block-editor-list-view__expander { - margin-left: - ($icon-size) * $block-navigation-max-indent + 4 * - ($block-navigation-max-indent - 1); -} - -.block-editor-list-view-leaf:not([aria-level="1"]) { - .block-editor-list-view__expander { - margin-right: 4px; - } + margin-left: ($grid-unit-30 * $block-navigation-max-indent); } // When updating the margin for each indentation level, the corresponding @@ -488,9 +480,9 @@ $block-navigation-max-indent: 8; .block-editor-list-view-leaf[aria-level="#{ $i + 1 }"] .block-editor-list-view__expander { @if $i - 1 >= 0 { - margin-left: ($icon-size * $i) + 4 * ($i - 1); + margin-left: ($grid-unit-30 * $i); // Effectivly centers the expander below the parent's icon. } @else { - margin-left: ($icon-size * $i); + margin-left: 0; } } } @@ -540,7 +532,7 @@ svg { .block-editor-list-view-drop-indicator__line { background: rgba(var(--wp-admin-theme-color--rgb), 0.04); - height: 36px; + height: 32px; border-radius: 4px; overflow: hidden; } @@ -553,7 +545,7 @@ svg { .block-editor-list-view-placeholder { padding: 0; margin: 0; - height: 36px; + height: 32px; } .list-view-appender .block-editor-inserter__toggle { diff --git a/packages/block-editor/src/components/list-view/use-list-view-drop-zone.js b/packages/block-editor/src/components/list-view/use-list-view-drop-zone.js index 3354b3f41d391c..64730be6156df9 100644 --- a/packages/block-editor/src/components/list-view/use-list-view-drop-zone.js +++ b/packages/block-editor/src/components/list-view/use-list-view-drop-zone.js @@ -62,7 +62,7 @@ import { store as blockEditorStore } from '../../store'; // When the indentation level, the corresponding left margin in `style.scss` // must be updated as well to ensure the drop zone is aligned with the indentation. -export const NESTING_LEVEL_INDENTATION = 28; +export const NESTING_LEVEL_INDENTATION = 24; /** * Determines whether the user is positioning the dragged block to be @@ -556,9 +556,14 @@ export default function useListViewDropZone( { const ref = useDropZone( { dropZoneElement, onDrop( event ) { + throttled.cancel(); if ( target ) { onBlockDrop( event ); } + // Use `undefined` value to indicate that the drag has concluded. + // This allows styling rules that are active only when a user is + // dragging to be removed. + setTarget( undefined ); }, onDragLeave() { throttled.cancel(); diff --git a/packages/block-editor/src/components/provider/test/use-block-sync.js b/packages/block-editor/src/components/provider/test/use-block-sync.js index 9b16e966249fa7..aae5e517c63029 100644 --- a/packages/block-editor/src/components/provider/test/use-block-sync.js +++ b/packages/block-editor/src/components/provider/test/use-block-sync.js @@ -71,6 +71,7 @@ describe( 'useBlockSync hook', () => { expect( onInput ).not.toHaveBeenCalled(); expect( replaceInnerBlocks ).not.toHaveBeenCalled(); expect( resetBlocks ).toHaveBeenCalledWith( fakeBlocks ); + expect( resetBlocks ).toHaveBeenCalledTimes( 1 ); const testBlocks = [ { clientId: 'a', innerBlocks: [], attributes: { foo: 1 } }, @@ -88,6 +89,7 @@ describe( 'useBlockSync hook', () => { expect( onInput ).not.toHaveBeenCalled(); expect( replaceInnerBlocks ).not.toHaveBeenCalled(); expect( resetBlocks ).toHaveBeenCalledWith( testBlocks ); + expect( resetBlocks ).toHaveBeenCalledTimes( 2 ); unmount(); @@ -95,6 +97,7 @@ describe( 'useBlockSync hook', () => { expect( onInput ).not.toHaveBeenCalled(); expect( replaceInnerBlocks ).not.toHaveBeenCalled(); expect( resetBlocks ).toHaveBeenCalledWith( [] ); + expect( resetBlocks ).toHaveBeenCalledTimes( 3 ); } ); it( 'replaces the inner blocks of a block when the controlled value changes if a clientId is passed', async () => { @@ -123,6 +126,7 @@ describe( 'useBlockSync hook', () => { 'test', // It should use the given client ID. fakeBlocks // It should use the controlled blocks value. ); + expect( replaceInnerBlocks ).toHaveBeenCalledTimes( 1 ); const testBlocks = [ { @@ -148,6 +152,7 @@ describe( 'useBlockSync hook', () => { expect( replaceInnerBlocks ).toHaveBeenCalledWith( 'test', [ expect.objectContaining( { name: 'test/test-block' } ), ] ); + expect( replaceInnerBlocks ).toHaveBeenCalledTimes( 2 ); unmount(); @@ -155,6 +160,7 @@ describe( 'useBlockSync hook', () => { expect( onInput ).not.toHaveBeenCalled(); expect( resetBlocks ).not.toHaveBeenCalled(); expect( replaceInnerBlocks ).toHaveBeenCalledWith( 'test', [] ); + expect( replaceInnerBlocks ).toHaveBeenCalledTimes( 3 ); } ); it( 'does not add the controlled blocks to the block-editor store if the store already contains them', async () => { @@ -354,6 +360,7 @@ describe( 'useBlockSync hook', () => { ); expect( replaceInnerBlocks ).toHaveBeenCalledWith( 'test', [] ); + expect( replaceInnerBlocks ).toHaveBeenCalledTimes( 1 ); expect( onChange ).not.toHaveBeenCalled(); expect( onInput ).not.toHaveBeenCalled(); } ); diff --git a/packages/block-editor/src/components/provider/use-block-sync.js b/packages/block-editor/src/components/provider/use-block-sync.js index 969c0f1e4d1c5e..7dfbd6a8f320e9 100644 --- a/packages/block-editor/src/components/provider/use-block-sync.js +++ b/packages/block-editor/src/components/provider/use-block-sync.js @@ -186,7 +186,15 @@ export default function useBlockSync( { } }, [ controlledBlocks, clientId ] ); + const isMounted = useRef( false ); + useEffect( () => { + // On mount, controlled blocks are already set in the effect above. + if ( ! isMounted.current ) { + isMounted.current = true; + return; + } + // When the block becomes uncontrolled, it means its inner state has been reset // we need to take the blocks again from the external value property. if ( ! isControlled ) { diff --git a/packages/block-editor/src/components/rich-text/README.md b/packages/block-editor/src/components/rich-text/README.md index d6469bf098145b..a4c9b932e87905 100644 --- a/packages/block-editor/src/components/rich-text/README.md +++ b/packages/block-editor/src/components/rich-text/README.md @@ -25,6 +25,10 @@ _Default: `div`._ The [tag name](https://www.w3.org/TR/html51/syntax.html#tag-na _Optional._ Placeholder text to show when the field is empty, similar to the [`input` and `textarea` attribute of the same name](https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/HTML5_updates#The_placeholder_attribute). +### `disableLineBreaks: Boolean` + +_Optional._ Disables inserting line breaks on `Enter` when it is set to `true` + ### `multiline: Boolean | String` _Optional._ By default, a line break will be inserted on Enter. If the editable field can contain multiple paragraphs, this property can be set to create new paragraphs on Enter. diff --git a/packages/block-editor/src/components/rich-text/index.native.js b/packages/block-editor/src/components/rich-text/index.native.js index 8371460862fa55..5729aa2d4bf27f 100644 --- a/packages/block-editor/src/components/rich-text/index.native.js +++ b/packages/block-editor/src/components/rich-text/index.native.js @@ -118,6 +118,7 @@ export function RichTextWrapper( getBlock, isMultiSelecting, hasMultiSelection, + getSelectedBlockClientId, } = select( blockEditorStore ); const selectionStart = getSelectionStart(); @@ -154,6 +155,7 @@ export function RichTextWrapper( didAutomaticChange: didAutomaticChange(), disabled: isMultiSelecting() || hasMultiSelection(), undo, + getSelectedBlockClientId, ...extraProps, }; }; @@ -164,6 +166,7 @@ export function RichTextWrapper( selectionStart, selectionEnd, isSelected, + getSelectedBlockClientId, didAutomaticChange, disabled, undo, @@ -175,6 +178,7 @@ export function RichTextWrapper( exitFormattedText, selectionChange, __unstableMarkAutomaticChange, + clearSelectedBlock, } = useDispatch( blockEditorStore ); const adjustedAllowedFormats = getAllowedFormats( { allowedFormats, @@ -209,6 +213,12 @@ export function RichTextWrapper( [ clientId, identifier ] ); + const clearCurrentSelectionOnUnmount = useCallback( () => { + if ( getSelectedBlockClientId() === clientId ) { + clearSelectedBlock(); + } + }, [ clearSelectedBlock, clientId, getSelectedBlockClientId ] ); + const onDelete = useCallback( ( { value, isReverse } ) => { if ( onMerge ) { @@ -590,6 +600,7 @@ export function RichTextWrapper( disableSuggestions={ disableSuggestions } disableAutocorrection={ disableAutocorrection } containerWidth={ containerWidth } + clearCurrentSelectionOnUnmount={ clearCurrentSelectionOnUnmount } // Props to be set on the editable container are destructured on the // element itself for web (see below), but passed through rich text // for native. diff --git a/packages/block-editor/src/components/rich-text/native/index.native.js b/packages/block-editor/src/components/rich-text/native/index.native.js index 8b4c871bda7bbf..26d39a0c6058b4 100644 --- a/packages/block-editor/src/components/rich-text/native/index.native.js +++ b/packages/block-editor/src/components/rich-text/native/index.native.js @@ -873,6 +873,17 @@ export class RichText extends Component { } } + componentWillUnmount() { + const { clearCurrentSelectionOnUnmount } = this.props; + + // There are cases when the component is unmounted e.g. scrolling in a + // long post due to virtualization, so the block selection needs to be cleared + // so it doesn't auto-focus when it's added back. + if ( this._editor?.isFocused() ) { + clearCurrentSelectionOnUnmount?.(); + } + } + getHtmlToRender( record, tagName ) { // Save back to HTML from React tree. let value = this.valueToFormat( record ); diff --git a/packages/block-editor/src/components/rich-text/use-undo-automatic-change.js b/packages/block-editor/src/components/rich-text/use-undo-automatic-change.js index 819f2935806263..9094633186ebdd 100644 --- a/packages/block-editor/src/components/rich-text/use-undo-automatic-change.js +++ b/packages/block-editor/src/components/rich-text/use-undo-automatic-change.js @@ -3,7 +3,7 @@ */ import { useSelect } from '@wordpress/data'; import { useRefEffect } from '@wordpress/compose'; -import { BACKSPACE, DELETE, ESCAPE } from '@wordpress/keycodes'; +import { BACKSPACE, ESCAPE } from '@wordpress/keycodes'; /** * Internal dependencies @@ -20,11 +20,7 @@ export function useUndoAutomaticChange() { return; } - if ( - keyCode !== DELETE && - keyCode !== BACKSPACE && - keyCode !== ESCAPE - ) { + if ( keyCode !== BACKSPACE && keyCode !== ESCAPE ) { return; } diff --git a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js index 3a549bd8e15cc3..6feb583c29cdb2 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js @@ -92,6 +92,8 @@ export default function SpacingInputControl( { ! isValueSpacingPreset( value ) ); + const [ minValue, setMinValue ] = useState( minimumCustomValue ); + const previousValue = usePrevious( value ); if ( !! value && @@ -222,13 +224,26 @@ export default function SpacingInputControl( { } value={ currentValue } units={ units } - min={ minimumCustomValue } + min={ minValue } placeholder={ allPlaceholder } disableUnits={ isMixed } label={ ariaLabel } hideLabelFromVision className="spacing-sizes-control__custom-value-input" size={ '__unstable-large' } + onDragStart={ () => { + if ( value?.charAt( 0 ) === '-' ) { + setMinValue( 0 ); + } + } } + onDrag={ () => { + if ( value?.charAt( 0 ) === '-' ) { + setMinValue( 0 ); + } + } } + onDragEnd={ () => { + setMinValue( minimumCustomValue ); + } } /> { const { - __unstableGetContentLockingParent, + getContentLockingParent, getTemplateLock, - __unstableGetTemporarilyEditingAsBlocks, - } = select( blockEditorStore ); + getTemporarilyEditingAsBlocks, + } = unlock( select( blockEditorStore ) ); return { templateLock: getTemplateLock( clientId ), - isLockedByParent: - !! __unstableGetContentLockingParent( clientId ), - isEditingAsBlocks: - __unstableGetTemporarilyEditingAsBlocks() === clientId, + isLockedByParent: !! getContentLockingParent( clientId ), + isEditingAsBlocks: getTemporarilyEditingAsBlocks() === clientId, }; }, [ clientId ] diff --git a/packages/block-editor/src/hooks/layout.js b/packages/block-editor/src/hooks/layout.js index 5f07c9e843f4bf..ac6a381742c814 100644 --- a/packages/block-editor/src/hooks/layout.js +++ b/packages/block-editor/src/hooks/layout.js @@ -374,7 +374,7 @@ function BlockWithLayoutStyles( { const { kebabCase } = unlock( componentsPrivateApis ); const selectorPrefix = `wp-container-${ kebabCase( name ) }-is-layout-`; // Higher specificity to override defaults from theme.json. - const selector = `.${ selectorPrefix }${ id }.${ selectorPrefix }${ id }`; + const selector = `.${ selectorPrefix }${ id }`; const hasBlockGapSupport = blockGapSupport !== null; // Get CSS string for the current layout type. diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index 5cd8cb46b3b7e7..5ca526b5749b74 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -1,12 +1,11 @@ /** * WordPress dependencies */ -import { getBlockType, store as blocksStore } from '@wordpress/blocks'; +import { store as blocksStore } from '@wordpress/blocks'; import { createHigherOrderComponent } from '@wordpress/compose'; -import { useSelect } from '@wordpress/data'; -import { useLayoutEffect, useCallback, useState } from '@wordpress/element'; +import { useRegistry, useSelect } from '@wordpress/data'; +import { useCallback } from '@wordpress/element'; import { addFilter } from '@wordpress/hooks'; -import { RichTextData } from '@wordpress/rich-text'; /** * Internal dependencies @@ -56,181 +55,111 @@ export function canBindAttribute( blockName, attributeName ) { ); } -/** - * This component is responsible for detecting and - * propagating data changes from the source to the block. - * - * @param {Object} props - The component props. - * @param {string} props.attrName - The attribute name. - * @param {Object} props.blockProps - The block props with bound attribute. - * @param {Object} props.source - Source handler. - * @param {Object} props.args - The arguments to pass to the source. - * @param {Function} props.onPropValueChange - The function to call when the attribute value changes. - * @return {null} Data-handling component. Render nothing. - */ -const BindingConnector = ( { - args, - attrName, - blockProps, - source, - onPropValueChange, -} ) => { - const { placeholder, value: propValue } = source.useSource( - blockProps, - args - ); - - const { name: blockName } = blockProps; - const attrValue = blockProps.attributes[ attrName ]; - - const updateBoundAttibute = useCallback( - ( newAttrValue, prevAttrValue ) => { - /* - * If the attribute is a RichTextData instance, - * (core/paragraph, core/heading, core/button, etc.) - * compare its HTML representation with the new value. - * - * To do: it looks like a workaround. - * Consider improving the attribute and metadata fields types. - */ - if ( prevAttrValue instanceof RichTextData ) { - // Bail early if the Rich Text value is the same. - if ( prevAttrValue.toHTMLString() === newAttrValue ) { - return; - } - - /* - * To preserve the value type, - * convert the new value to a RichTextData instance. - */ - newAttrValue = RichTextData.fromHTMLString( newAttrValue ); - } - - if ( prevAttrValue === newAttrValue ) { +export const withBlockBindingSupport = createHigherOrderComponent( + ( BlockEdit ) => ( props ) => { + const registry = useRegistry(); + const sources = useSelect( ( select ) => + unlock( select( blocksStore ) ).getAllBlockBindingsSources() + ); + const bindings = props.attributes.metadata?.bindings; + const { name, clientId, context } = props; + const boundAttributes = useSelect( () => { + if ( ! bindings ) { return; } - onPropValueChange( { [ attrName ]: newAttrValue } ); - }, - [ attrName, onPropValueChange ] - ); - - useLayoutEffect( () => { - if ( typeof propValue !== 'undefined' ) { - updateBoundAttibute( propValue, attrValue ); - } else if ( placeholder ) { - /* - * Placeholder fallback. - * If the attribute is `src` or `href`, - * a placeholder can't be used because it is not a valid url. - * Adding this workaround until - * attributes and metadata fields types are improved and include `url`. - */ - const htmlAttribute = - getBlockType( blockName ).attributes[ attrName ].attribute; + const attributes = {}; + + for ( const [ attributeName, boundAttribute ] of Object.entries( + bindings + ) ) { + const source = sources[ boundAttribute.source ]; + if ( + ! source?.getValue || + ! canBindAttribute( name, attributeName ) + ) { + continue; + } - if ( htmlAttribute === 'src' || htmlAttribute === 'href' ) { - updateBoundAttibute( null ); - return; + const args = { + registry, + context, + clientId, + attributeName, + args: boundAttribute.args, + }; + + attributes[ attributeName ] = source.getValue( args ); + + if ( attributes[ attributeName ] === undefined ) { + if ( attributeName === 'url' ) { + attributes[ attributeName ] = null; + } else { + attributes[ attributeName ] = + source.getPlaceholder?.( args ); + } + } } - updateBoundAttibute( placeholder ); - } - }, [ - updateBoundAttibute, - propValue, - attrValue, - placeholder, - blockName, - attrName, - ] ); - - return null; -}; + return attributes; + }, [ bindings, name, clientId, context, registry, sources ] ); -/** - * BlockBindingBridge acts like a component wrapper - * that connects the bound attributes of a block - * to the source handlers. - * For this, it creates a BindingConnector for each bound attribute. - * - * @param {Object} props - The component props. - * @param {Object} props.blockProps - The BlockEdit props object. - * @param {Object} props.bindings - The block bindings settings. - * @param {Function} props.onPropValueChange - The function to call when the attribute value changes. - * @return {null} Data-handling component. Render nothing. - */ -function BlockBindingBridge( { blockProps, bindings, onPropValueChange } ) { - const blockBindingsSources = unlock( - useSelect( blocksStore ) - ).getAllBlockBindingsSources(); + const { setAttributes } = props; - return ( - <> - { Object.entries( bindings ).map( - ( [ attrName, boundAttribute ] ) => { - // Bail early if the block doesn't have a valid source handler. - const source = - blockBindingsSources[ boundAttribute.source ]; - if ( ! source?.useSource ) { - return null; + const _setAttributes = useCallback( + ( nextAttributes ) => { + registry.batch( () => { + if ( ! bindings ) { + return setAttributes( nextAttributes ); } - return ( - - ); - } - ) } - - ); -} - -const withBlockBindingSupport = createHigherOrderComponent( - ( BlockEdit ) => ( props ) => { - /* - * Collect and update the bound attributes - * in a separate state. - */ - const [ boundAttributes, setBoundAttributes ] = useState( {} ); - const updateBoundAttributes = useCallback( - ( newAttributes ) => - setBoundAttributes( ( prev ) => ( { - ...prev, - ...newAttributes, - } ) ), - [] - ); + const keptAttributes = { ...nextAttributes }; + + for ( const [ + attributeName, + boundAttribute, + ] of Object.entries( bindings ) ) { + const source = sources[ boundAttribute.source ]; + if ( + ! source?.setValue || + ! canBindAttribute( name, attributeName ) + ) { + continue; + } + + source.setValue( { + registry, + context, + clientId, + attributeName, + args: boundAttribute.args, + value: nextAttributes[ attributeName ], + } ); + delete keptAttributes[ attributeName ]; + } - /* - * Create binding object filtering - * only the attributes that can be bound. - */ - const bindings = Object.fromEntries( - Object.entries( props.attributes.metadata?.bindings || {} ).filter( - ( [ attrName ] ) => canBindAttribute( props.name, attrName ) - ) + if ( Object.keys( keptAttributes ).length ) { + setAttributes( keptAttributes ); + } + } ); + }, + [ + registry, + bindings, + name, + clientId, + context, + setAttributes, + sources, + ] ); return ( <> - { Object.keys( bindings ).length > 0 && ( - - ) } - ); diff --git a/packages/block-editor/src/hooks/use-zoom-out.js b/packages/block-editor/src/hooks/use-zoom-out.js index 84603c0161dd43..ce20cb5bd7a179 100644 --- a/packages/block-editor/src/hooks/use-zoom-out.js +++ b/packages/block-editor/src/hooks/use-zoom-out.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { useSelect, useDispatch } from '@wordpress/data'; -import { useEffect } from '@wordpress/element'; +import { useEffect, useRef } from '@wordpress/element'; /** * Internal dependencies @@ -11,26 +11,36 @@ import { store as blockEditorStore } from '../store'; /** * A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode. + * + * @param {boolean} zoomOut If we should enter into zoomOut mode or not */ -export function useZoomOut() { +export function useZoomOut( zoomOut = true ) { const { __unstableSetEditorMode } = useDispatch( blockEditorStore ); - const { mode } = useSelect( ( select ) => { - return { - mode: select( blockEditorStore ).__unstableGetEditorMode(), + const { __unstableGetEditorMode } = useSelect( blockEditorStore ); + + const originalEditingMode = useRef( null ); + const mode = __unstableGetEditorMode(); + + useEffect( () => { + // Only set this on mount so we know what to return to when we unmount. + if ( ! originalEditingMode.current ) { + originalEditingMode.current = mode; + } + + return () => { + // We need to use __unstableGetEditorMode() here and not `mode`, as mode may not update on unmount + if ( __unstableGetEditorMode() !== originalEditingMode.current ) { + __unstableSetEditorMode( originalEditingMode.current ); + } }; }, [] ); - // Intentionality left without any dependency. - // This effect should only run when the component is rendered and unmounted. - // The effect opens the zoom-out view if it is not open before when applying a style variation. + // The effect opens the zoom-out view if we want it open and it's not currently in zoom-out mode. useEffect( () => { - if ( mode !== 'zoom-out' ) { + if ( zoomOut && mode !== 'zoom-out' ) { __unstableSetEditorMode( 'zoom-out' ); - return () => { - // Revert to original mode - __unstableSetEditorMode( mode ); - }; + } else if ( ! zoomOut && originalEditingMode.current !== mode ) { + __unstableSetEditorMode( originalEditingMode.current ); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [] ); + }, [ __unstableSetEditorMode, zoomOut, mode ] ); } diff --git a/packages/block-editor/src/layouts/definitions.js b/packages/block-editor/src/layouts/definitions.js index 3b1e5c7ab5896a..a5c6d431c50f20 100644 --- a/packages/block-editor/src/layouts/definitions.js +++ b/packages/block-editor/src/layouts/definitions.js @@ -34,13 +34,13 @@ export const LAYOUT_DEFINITIONS = { ], spacingStyles: [ { - selector: ' > :first-child:first-child', + selector: ' > :first-child', rules: { 'margin-block-start': '0', }, }, { - selector: ' > :last-child:last-child', + selector: ' > :last-child', rules: { 'margin-block-end': '0', }, @@ -100,13 +100,13 @@ export const LAYOUT_DEFINITIONS = { ], spacingStyles: [ { - selector: ' > :first-child:first-child', + selector: ' > :first-child', rules: { 'margin-block-start': '0', }, }, { - selector: ' > :last-child:last-child', + selector: ' > :last-child', rules: { 'margin-block-end': '0', }, @@ -134,7 +134,7 @@ export const LAYOUT_DEFINITIONS = { }, }, { - selector: ' > *', + selector: ' > :is(*, div)', // :is(*, div) instead of just * increases the specificity by 001. rules: { margin: '0', }, @@ -156,7 +156,7 @@ export const LAYOUT_DEFINITIONS = { displayMode: 'grid', baseStyles: [ { - selector: ' > *', + selector: ' > :is(*, div)', // :is(*, div) instead of just * increases the specificity by 001. rules: { margin: '0', }, diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index b51c019e791788..e81a5eed39d5bc 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -15,7 +15,7 @@ import { } from './components/inserter/search-items'; import { PrivateListView } from './components/list-view'; import BlockInfo from './components/block-info-slot-fill'; -import { useShowBlockTools } from './components/block-tools/use-show-block-tools'; +import { useHasBlockToolbar } from './components/block-toolbar/use-has-block-toolbar'; import { cleanEmptyObject, useStyleOverride } from './hooks/utils'; import BlockQuickNavigation from './components/block-quick-navigation'; import { LayoutStyle } from './components/block-list/layout'; @@ -56,7 +56,7 @@ lock( privateApis, { PrivateListView, ResizableBoxPopover, BlockInfo, - useShowBlockTools, + useHasBlockToolbar, cleanEmptyObject, useStyleOverride, BlockQuickNavigation, diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index f98e4845e91f2f..faa36a286e046a 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1438,26 +1438,42 @@ export const __unstableSetEditorMode = // When switching to zoom-out mode, we need to select the parent section if ( mode === 'zoom-out' ) { const firstSelectedClientId = select.getBlockSelectionStart(); + const allBlocks = select.getBlocks(); + const { sectionRootClientId } = unlock( registry.select( STORE_NAME ).getSettings() ); if ( sectionRootClientId ) { const sectionClientIds = select.getBlockOrder( sectionRootClientId ); + const lastSectionClientId = + sectionClientIds[ sectionClientIds.length - 1 ]; if ( sectionClientIds ) { - const parents = select.getBlockParents( - firstSelectedClientId - ); - const firstSectionClientId = parents.find( ( parent ) => - sectionClientIds.includes( parent ) - ); - dispatch.selectBlock( firstSectionClientId ); + if ( firstSelectedClientId ) { + const parents = select.getBlockParents( + firstSelectedClientId + ); + const firstSectionClientId = parents.find( ( parent ) => + sectionClientIds.includes( parent ) + ); + if ( firstSectionClientId ) { + dispatch.selectBlock( firstSectionClientId ); + } else { + dispatch.selectBlock( lastSectionClientId ); + } + } else { + dispatch.selectBlock( lastSectionClientId ); + } } } else if ( firstSelectedClientId ) { const rootClientId = select.getBlockHierarchyRootClientId( firstSelectedClientId ); dispatch.selectBlock( rootClientId ); + } else { + // If there's no block selected and no sectionRootClientId, select the last root block. + const lastRootBlock = allBlocks[ allBlocks.length - 1 ]; + dispatch.selectBlock( lastRootBlock?.clientId ); } } diff --git a/packages/block-editor/src/store/private-actions.js b/packages/block-editor/src/store/private-actions.js index 85d624e048318f..6cfccb17287ff9 100644 --- a/packages/block-editor/src/store/private-actions.js +++ b/packages/block-editor/src/store/private-actions.js @@ -7,6 +7,8 @@ import { Platform } from '@wordpress/element'; * Internal dependencies */ import { undoIgnoreBlocks } from './undo-ignore'; +import { store as blockEditorStore } from './index'; +import { unlock } from '../lock-unlock'; const castArray = ( maybeArray ) => Array.isArray( maybeArray ) ? maybeArray : [ maybeArray ]; @@ -339,9 +341,10 @@ export function setLastFocus( lastFocus = null ) { * @param {string} clientId The block's clientId. */ export function stopEditingAsBlocks( clientId ) { - return ( { select, dispatch } ) => { - const focusModeToRevert = - select.__unstableGetTemporarilyEditingFocusModeToRevert(); + return ( { select, dispatch, registry } ) => { + const focusModeToRevert = unlock( + registry.select( blockEditorStore ) + ).getTemporarilyEditingFocusModeToRevert(); dispatch.__unstableMarkNextChangeAsNotPersistent(); dispatch.updateBlockAttributes( clientId, { templateLock: 'contentOnly', diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 126c116ac97f84..94de85cbabe70e 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -12,6 +12,8 @@ import { getBlockEditingMode, getSettings, canInsertBlockType, + getBlockName, + getTemplateLock, } from './selectors'; import { checkAllowListRecursive, @@ -420,3 +422,53 @@ export function isDragging( state ) { export function getExpandedBlock( state ) { return state.expandedBlock; } + +/** + * Retrieves the client ID of the ancestor block that is content locking the block + * with the provided client ID. + * + * @param {Object} state Global application state. + * @param {Object} clientId Client Id of the block. + * + * @return {?string} Client ID of the ancestor block that is content locking the block. + */ +export const getContentLockingParent = createSelector( + ( state, clientId ) => { + let current = clientId; + let result; + while ( ( current = state.blocks.parents.get( current ) ) ) { + if ( + getBlockName( state, current ) === 'core/block' || + getTemplateLock( state, current ) === 'contentOnly' + ) { + result = current; + } + } + return result; + }, + ( state ) => [ state.blocks.parents, state.blockListSettings ] +); + +/** + * Retrieves the client ID of the block that is content locked but is + * currently being temporarily edited as a non-locked block. + * + * @param {Object} state Global application state. + * + * @return {?string} The client ID of the block being temporarily edited as a non-locked block. + */ +export function getTemporarilyEditingAsBlocks( state ) { + return state.temporarilyEditingAsBlocks; +} + +/** + * Returns the focus mode that should be reapplied when the user stops editing + * a content locked blocks as a block without locking. + * + * @param {Object} state Global application state. + * + * @return {?string} The focus mode that should be re-set when temporarily editing as blocks stops. + */ +export function getTemporarilyEditingFocusModeToRevert( state ) { + return state.temporarilyEditingFocusModeRevert; +} diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 43b1990e3f17b4..19c609e848732c 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -31,6 +31,12 @@ import { orderBy } from '../utils/sorting'; import { STORE_NAME } from './constants'; import { unlock } from '../lock-unlock'; +import { + getContentLockingParent, + getTemporarilyEditingAsBlocks, + getTemporarilyEditingFocusModeToRevert, +} from './private-selectors'; + /** * A block selection object. * @@ -2756,50 +2762,6 @@ export const __unstableGetVisibleBlocks = createSelector( ( state ) => [ state.blockVisibility ] ); -/** - * DO-NOT-USE in production. - * This selector is created for internal/experimental only usage and may be - * removed anytime without any warning, causing breakage on any plugin or theme invoking it. - */ -export const __unstableGetContentLockingParent = createSelector( - ( state, clientId ) => { - let current = clientId; - let result; - while ( ( current = state.blocks.parents.get( current ) ) ) { - if ( - getBlockName( state, current ) === 'core/block' || - getTemplateLock( state, current ) === 'contentOnly' - ) { - result = current; - } - } - return result; - }, - ( state ) => [ state.blocks.parents, state.blockListSettings ] -); - -/** - * DO-NOT-USE in production. - * This selector is created for internal/experimental only usage and may be - * removed anytime without any warning, causing breakage on any plugin or theme invoking it. - * - * @param {Object} state Global application state. - */ -export function __unstableGetTemporarilyEditingAsBlocks( state ) { - return state.temporarilyEditingAsBlocks; -} - -/** - * DO-NOT-USE in production. - * This selector is created for internal/experimental only usage and may be - * removed anytime without any warning, causing breakage on any plugin or theme invoking it. - * - * @param {Object} state Global application state. - */ -export function __unstableGetTemporarilyEditingFocusModeToRevert( state ) { - return state.temporarilyEditingFocusModeRevert; -} - export function __unstableHasActiveBlockOverlayActive( state, clientId ) { // Prevent overlay on blocks with a non-default editing mode. If the mdoe is // 'disabled' then the overlay is redundant since the block can't be @@ -3013,3 +2975,66 @@ export const isGroupable = createRegistrySelector( ); } ); + +/** + * DO-NOT-USE in production. + * This selector is created for internal/experimental only usage and may be + * removed anytime without any warning, causing breakage on any plugin or theme invoking it. + * + * @deprecated + * + * @param {Object} state Global application state. + * @param {Object} clientId Client Id of the block. + * + * @return {?string} Client ID of the ancestor block that is content locking the block. + */ +export const __unstableGetContentLockingParent = ( state, clientId ) => { + deprecated( + "wp.data.select( 'core/block-editor' ).__unstableGetContentLockingParent", + { + since: '6.1', + version: '6.7', + } + ); + return getContentLockingParent( state, clientId ); +}; + +/** + * DO-NOT-USE in production. + * This selector is created for internal/experimental only usage and may be + * removed anytime without any warning, causing breakage on any plugin or theme invoking it. + * + * @deprecated + * + * @param {Object} state Global application state. + */ +export function __unstableGetTemporarilyEditingAsBlocks( state ) { + deprecated( + "wp.data.select( 'core/block-editor' ).__unstableGetTemporarilyEditingAsBlocks", + { + since: '6.1', + version: '6.7', + } + ); + return getTemporarilyEditingAsBlocks( state ); +} + +/** + * DO-NOT-USE in production. + * This selector is created for internal/experimental only usage and may be + * removed anytime without any warning, causing breakage on any plugin or theme invoking it. + * + * @deprecated + * + * @param {Object} state Global application state. + */ +export function __unstableGetTemporarilyEditingFocusModeToRevert( state ) { + deprecated( + "wp.data.select( 'core/block-editor' ).__unstableGetTemporarilyEditingFocusModeToRevert", + { + since: '6.5', + version: '6.7', + } + ); + return getTemporarilyEditingFocusModeToRevert( state ); +} diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index c3153990e2f0ea..91741cf70413f9 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.33.0 (2024-04-19) + ## 8.32.0 (2024-04-03) ## 8.31.0 (2024-03-21) diff --git a/packages/block-library/package.json b/packages/block-library/package.json index d9bb73400d79cd..c4cded1866a731 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "8.32.0", + "version": "8.33.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", @@ -52,6 +52,7 @@ "@wordpress/icons": "file:../icons", "@wordpress/interactivity": "file:../interactivity", "@wordpress/interactivity-router": "file:../interactivity-router", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", "@wordpress/keycodes": "file:../keycodes", "@wordpress/notices": "file:../notices", "@wordpress/patterns": "file:../patterns", diff --git a/packages/block-library/src/block-keyboard-shortcuts/index.js b/packages/block-library/src/block-keyboard-shortcuts/index.js new file mode 100644 index 00000000000000..6d9cde8364001f --- /dev/null +++ b/packages/block-library/src/block-keyboard-shortcuts/index.js @@ -0,0 +1,113 @@ +/** + * WordPress dependencies + */ +import { useEffect } from '@wordpress/element'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { + useShortcut, + store as keyboardShortcutsStore, +} from '@wordpress/keyboard-shortcuts'; +import { __ } from '@wordpress/i18n'; +import { createBlock } from '@wordpress/blocks'; +import { store as blockEditorStore } from '@wordpress/block-editor'; + +function BlockKeyboardShortcuts() { + const { registerShortcut } = useDispatch( keyboardShortcutsStore ); + const { replaceBlocks } = useDispatch( blockEditorStore ); + const { getBlockName, getSelectedBlockClientId, getBlockAttributes } = + useSelect( blockEditorStore ); + + const handleTransformHeadingAndParagraph = ( event, level ) => { + event.preventDefault(); + + const currentClientId = getSelectedBlockClientId(); + if ( currentClientId === null ) { + return; + } + + const blockName = getBlockName( currentClientId ); + const isParagraph = blockName === 'core/paragraph'; + const isHeading = blockName === 'core/heading'; + + if ( ! isParagraph && ! isHeading ) { + return; + } + + const destinationBlockName = + level === 0 ? 'core/paragraph' : 'core/heading'; + + const attributes = getBlockAttributes( currentClientId ); + + // Avoid unnecessary block transform when attempting to transform to + // the same block type and/or same level. + if ( + ( isParagraph && level === 0 ) || + ( isHeading && attributes.level === level ) + ) { + return; + } + + const textAlign = + blockName === 'core/paragraph' ? 'align' : 'textAlign'; + const destinationTextAlign = + destinationBlockName === 'core/paragraph' ? 'align' : 'textAlign'; + + replaceBlocks( + currentClientId, + createBlock( destinationBlockName, { + level, + content: attributes.content, + ...{ [ destinationTextAlign ]: attributes[ textAlign ] }, + } ) + ); + }; + + useEffect( () => { + registerShortcut( { + name: 'core/block-editor/transform-heading-to-paragraph', + category: 'block-library', + description: __( 'Transform heading to paragraph.' ), + keyCombination: { + modifier: 'access', + character: '0', + }, + aliases: [ + { + modifier: 'access', + character: '7', + }, + ], + } ); + + [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { + registerShortcut( { + name: `core/block-editor/transform-paragraph-to-heading-${ level }`, + category: 'block-library', + description: __( 'Transform paragraph to heading.' ), + keyCombination: { + modifier: 'access', + character: `${ level }`, + }, + } ); + } ); + }, [] ); + + useShortcut( + 'core/block-editor/transform-heading-to-paragraph', + ( event ) => handleTransformHeadingAndParagraph( event, 0 ) + ); + + [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { + //the loop is based off on a constant therefore + //the hook will execute the same way every time + //eslint-disable-next-line react-hooks/rules-of-hooks + useShortcut( + `core/block-editor/transform-paragraph-to-heading-${ level }`, + ( event ) => handleTransformHeadingAndParagraph( event, level ) + ); + } ); + + return null; +} + +export default BlockKeyboardShortcuts; diff --git a/packages/block-library/src/gallery/editor.scss b/packages/block-library/src/gallery/editor.scss index 76cff33bbf00cd..ea6fa8836a3a4b 100644 --- a/packages/block-library/src/gallery/editor.scss +++ b/packages/block-library/src/gallery/editor.scss @@ -1,4 +1,4 @@ -figure.wp-block-gallery { +:where(figure.wp-block-gallery) { // Override the default list style type _only in the editor_ // to avoid :not() selector specificity issues. // See https://github.com/WordPress/gutenberg/pull/10358 diff --git a/packages/block-library/src/group/index.js b/packages/block-library/src/group/index.js index 2d06f1a965c521..1ccfa4fa89c1aa 100644 --- a/packages/block-library/src/group/index.js +++ b/packages/block-library/src/group/index.js @@ -22,14 +22,6 @@ export { metadata, name }; export const settings = { icon, example: { - attributes: { - style: { - color: { - text: '#000000', - background: '#ffffff', - }, - }, - }, innerBlocks: [ { name: 'core/paragraph', diff --git a/packages/block-library/src/group/style.scss b/packages/block-library/src/group/style.scss index 3457a12adb6221..018091ffd45644 100644 --- a/packages/block-library/src/group/style.scss +++ b/packages/block-library/src/group/style.scss @@ -2,3 +2,8 @@ // This block has customizable padding, border-box makes that more predictable. box-sizing: border-box; } + +// We need this so groups with negative margins overlap as expected. +:where(.wp-block-group.wp-block-group-is-layout-constrained) { + position: relative; +} diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index e2e0fd9e414ef3..9cb2f44d05eb9b 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -330,3 +330,5 @@ export const __experimentalRegisterExperimentalCoreBlocks = process.env .forEach( ( { init } ) => init() ); } : undefined; + +export { privateApis } from './private-apis'; diff --git a/packages/block-library/src/latest-posts/edit.js b/packages/block-library/src/latest-posts/edit.js index 0efe538b01f629..1ef7bd5e5fed7b 100644 --- a/packages/block-library/src/latest-posts/edit.js +++ b/packages/block-library/src/latest-posts/edit.js @@ -431,7 +431,7 @@ export default function LatestPostsEdit( { attributes, setAttributes } ) { const dateFormat = getSettings().formats.date; return ( -
+ <> { inspectorControls } @@ -518,7 +518,6 @@ export default function LatestPostsEdit( { attributes, setAttributes } ) {
{ addLinkToFeaturedImage ? ( ) } -
+ ); } diff --git a/packages/block-library/src/latest-posts/index.php b/packages/block-library/src/latest-posts/index.php index 6bff971beef576..913a9ae2d430e1 100644 --- a/packages/block-library/src/latest-posts/index.php +++ b/packages/block-library/src/latest-posts/index.php @@ -157,7 +157,7 @@ function render_block_core_latest_posts( $attributes ) { $trimmed_excerpt = substr( $trimmed_excerpt, 0, -11 ); $trimmed_excerpt .= sprintf( /* translators: 1: A URL to a post, 2: Hidden accessibility text: Post title */ - __( '… Read more: %2$s' ), + __( '… Read more: %2$s' ), esc_url( $post_link ), esc_html( $title ) ); diff --git a/packages/block-library/src/navigation-link/edit.js b/packages/block-library/src/navigation-link/edit.js index d71a49aef969c0..e8370242b7870c 100644 --- a/packages/block-library/src/navigation-link/edit.js +++ b/packages/block-library/src/navigation-link/edit.js @@ -153,6 +153,82 @@ function getMissingText( type ) { return missingText; } +/* + * Warning, this duplicated in + * packages/block-library/src/navigation-submenu/edit.js + * Consider reuseing this components for both blocks. + */ +function Controls( { attributes, setAttributes, setIsLabelFieldFocused } ) { + const { label, url, description, title, rel } = attributes; + return ( + + { + setAttributes( { label: labelValue } ); + } } + label={ __( 'Text' ) } + autoComplete="off" + onFocus={ () => setIsLabelFieldFocused( true ) } + onBlur={ () => setIsLabelFieldFocused( false ) } + /> + { + updateAttributes( + { url: urlValue }, + setAttributes, + attributes + ); + } } + label={ __( 'Link' ) } + autoComplete="off" + /> + { + setAttributes( { description: descriptionValue } ); + } } + label={ __( 'Description' ) } + help={ __( + 'The description will be displayed in the menu if the current theme supports it.' + ) } + /> + { + setAttributes( { title: titleValue } ); + } } + label={ __( 'Title attribute' ) } + autoComplete="off" + help={ __( + 'Additional information to help clarify the purpose of the link.' + ) } + /> + { + setAttributes( { rel: relValue } ); + } } + label={ __( 'Rel attribute' ) } + autoComplete="off" + help={ __( + 'The relationship of the linked URL as space-separated link types.' + ) } + /> + + ); +} + export default function NavigationLinkEdit( { attributes, isSelected, @@ -163,7 +239,7 @@ export default function NavigationLinkEdit( { context, clientId, } ) { - const { id, label, type, url, description, rel, title, kind } = attributes; + const { id, label, type, url, description, kind } = attributes; const [ isInvalid, isDraft ] = useIsInvalidLink( kind, type, id ); const { maxNestingLevel } = context; @@ -420,71 +496,11 @@ export default function NavigationLinkEdit( {
{ /* Warning, this duplicated in packages/block-library/src/navigation-submenu/edit.js */ } - - { - setAttributes( { label: labelValue } ); - } } - label={ __( 'Text' ) } - autoComplete="off" - onFocus={ () => setIsLabelFieldFocused( true ) } - onBlur={ () => setIsLabelFieldFocused( false ) } - /> - { - updateAttributes( - { url: urlValue }, - setAttributes, - attributes - ); - } } - label={ __( 'Link' ) } - autoComplete="off" - /> - { - setAttributes( { description: descriptionValue } ); - } } - label={ __( 'Description' ) } - help={ __( - 'The description will be displayed in the menu if the current theme supports it.' - ) } - /> - { - setAttributes( { title: titleValue } ); - } } - label={ __( 'Title attribute' ) } - autoComplete="off" - help={ __( - 'Additional information to help clarify the purpose of the link.' - ) } - /> - { - setAttributes( { rel: relValue } ); - } } - label={ __( 'Rel attribute' ) } - autoComplete="off" - help={ __( - 'The relationship of the linked URL as space-separated link types.' - ) } - /> - +
{ /* eslint-disable jsx-a11y/anchor-is-valid */ } diff --git a/packages/block-library/src/navigation-link/index.php b/packages/block-library/src/navigation-link/index.php index ffeea51996a02c..5653e04fca88a3 100644 --- a/packages/block-library/src/navigation-link/index.php +++ b/packages/block-library/src/navigation-link/index.php @@ -198,6 +198,13 @@ function render_block_core_navigation_link( $attributes, $content, $block ) { $kind = empty( $attributes['kind'] ) ? 'post_type' : str_replace( '-', '_', $attributes['kind'] ); $is_active = ! empty( $attributes['id'] ) && get_queried_object_id() === (int) $attributes['id'] && ! empty( get_queried_object()->$kind ); + if ( is_post_type_archive() ) { + $queried_archive_link = get_post_type_archive_link( get_queried_object()->name ); + if ( $attributes['url'] === $queried_archive_link ) { + $is_active = true; + } + } + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $css_classes . ' wp-block-navigation-item' . ( $has_submenu ? ' has-child' : '' ) . diff --git a/packages/block-library/src/navigation-submenu/index.php b/packages/block-library/src/navigation-submenu/index.php index b67f5ead8651ee..92b55e291606e8 100644 --- a/packages/block-library/src/navigation-submenu/index.php +++ b/packages/block-library/src/navigation-submenu/index.php @@ -87,6 +87,13 @@ function render_block_core_navigation_submenu( $attributes, $content, $block ) { $kind = empty( $attributes['kind'] ) ? 'post_type' : str_replace( '-', '_', $attributes['kind'] ); $is_active = ! empty( $attributes['id'] ) && get_queried_object_id() === (int) $attributes['id'] && ! empty( get_queried_object()->$kind ); + if ( is_post_type_archive() ) { + $queried_archive_link = get_post_type_archive_link( get_queried_object()->name ); + if ( $attributes['url'] === $queried_archive_link ) { + $is_active = true; + } + } + $show_submenu_indicators = isset( $block->context['showSubmenuIcon'] ) && $block->context['showSubmenuIcon']; $open_on_click = isset( $block->context['openSubmenusOnClick'] ) && $block->context['openSubmenusOnClick']; $open_on_hover_and_click = isset( $block->context['openSubmenusOnClick'] ) && ! $block->context['openSubmenusOnClick'] && diff --git a/packages/block-library/src/navigation/block.json b/packages/block-library/src/navigation/block.json index eef6af390de78a..c65e0c6224616e 100644 --- a/packages/block-library/src/navigation/block.json +++ b/packages/block-library/src/navigation/block.json @@ -137,15 +137,6 @@ "type": "flex" } }, - "__experimentalStyle": { - "elements": { - "link": { - "color": { - "text": "inherit" - } - } - } - }, "interactivity": true, "renaming": false }, diff --git a/packages/block-library/src/navigation/edit/deleted-navigation-warning.js b/packages/block-library/src/navigation/edit/deleted-navigation-warning.js index 143bf8a3a2ce33..915e19694085de 100644 --- a/packages/block-library/src/navigation/edit/deleted-navigation-warning.js +++ b/packages/block-library/src/navigation/edit/deleted-navigation-warning.js @@ -11,7 +11,7 @@ function DeletedNavigationWarning( { onCreateNew } ) { { createInterpolateElement( __( - 'Navigation Menu has been deleted or is unavailable. ' + 'Navigation Menu has been deleted or is unavailable. ' ), { button: + { isSelected && showURLPopover && ( + + ) } ); diff --git a/packages/block-library/src/social-link/index.php b/packages/block-library/src/social-link/index.php index 69a145c0ff6028..5e2bc616d0e5ac 100644 --- a/packages/block-library/src/social-link/index.php +++ b/packages/block-library/src/social-link/index.php @@ -19,9 +19,11 @@ function render_block_core_social_link( $attributes, $content, $block ) { $open_in_new_tab = isset( $block->context['openInNewTab'] ) ? $block->context['openInNewTab'] : false; + $text = ! empty( $attributes['label'] ) ? trim( $attributes['label'] ) : ''; + $service = isset( $attributes['service'] ) ? $attributes['service'] : 'Icon'; $url = isset( $attributes['url'] ) ? $attributes['url'] : false; - $label = ! empty( $attributes['label'] ) ? $attributes['label'] : block_core_social_link_get_name( $service ); + $text = $text ? $text : block_core_social_link_get_name( $service ); $rel = isset( $attributes['rel'] ) ? $attributes['rel'] : ''; $show_labels = array_key_exists( 'showLabels', $block->context ) ? $block->context['showLabels'] : false; @@ -57,7 +59,7 @@ function render_block_core_social_link( $attributes, $content, $block ) { $link = '
  • '; $link .= ''; $link .= $icon; - $link .= '' . esc_html( $label ) . ''; + $link .= '' . esc_html( $text ) . ''; $link .= '
  • '; $processor = new WP_HTML_Tag_Processor( $link ); diff --git a/packages/block-library/src/social-links/block.json b/packages/block-library/src/social-links/block.json index 0c8c7be1eba9a5..45dbd9d698953f 100644 --- a/packages/block-library/src/social-links/block.json +++ b/packages/block-library/src/social-links/block.json @@ -5,7 +5,7 @@ "title": "Social Icons", "category": "widgets", "allowedBlocks": [ "core/social-link" ], - "description": "Display icons linking to your social media profiles or sites.", + "description": "Display icons linking to your social profiles or sites.", "keywords": [ "links" ], "textdomain": "default", "attributes": { diff --git a/packages/block-library/src/social-links/edit.js b/packages/block-library/src/social-links/edit.js index 38a68e7f2dab2c..52d26be50a6c9e 100644 --- a/packages/block-library/src/social-links/edit.js +++ b/packages/block-library/src/social-links/edit.js @@ -203,7 +203,7 @@ export function SocialLinksEdit( props ) { /> setAttributes( { showLabels: ! showLabels } ) diff --git a/packages/block-library/src/template-part/edit/index.js b/packages/block-library/src/template-part/edit/index.js index 5af3ede02b677e..52d740735eaf61 100644 --- a/packages/block-library/src/template-part/edit/index.js +++ b/packages/block-library/src/template-part/edit/index.js @@ -128,6 +128,7 @@ export default function TemplatePartEdit( { area, onNavigateToEntityRecord, title, + canEditTemplate, } = useSelect( ( select ) => { const { getEditedEntityRecord, hasFinishedResolution } = @@ -150,6 +151,9 @@ export default function TemplatePartEdit( { ) : false; + const _canEditTemplate = + select( coreStore ).canUser( 'create', 'templates' ) ?? false; + return { hasInnerBlocks: getBlockCount( clientId ) > 0, isResolved: hasResolvedEntity, @@ -161,6 +165,7 @@ export default function TemplatePartEdit( { onNavigateToEntityRecord: getSettings().onNavigateToEntityRecord, title: entityRecord?.title, + canEditTemplate: _canEditTemplate, }; }, [ templatePartId, attributes.area, clientId ] @@ -228,20 +233,22 @@ export default function TemplatePartEdit( { return ( <> - { isEntityAvailable && onNavigateToEntityRecord && ( - - - onNavigateToEntityRecord( { - postId: templatePartId, - postType: 'wp_template_part', - } ) - } - > - { __( 'Edit' ) } - - - ) } + { isEntityAvailable && + onNavigateToEntityRecord && + canEditTemplate && ( + + + onNavigateToEntityRecord( { + postId: templatePartId, + postType: 'wp_template_part', + } ) + } + > + { __( 'Edit' ) } + + + ) } { * ``` */ export const registerBlockVariation = ( blockName, variation ) => { + if ( typeof variation.name !== 'string' ) { + console.warn( 'Variation names must be unique strings.' ); + } + dispatch( blocksStore ).addBlockVariations( blockName, variation ); }; diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index 8433bbcb04ca38..81f45f1999803e 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -13,6 +13,7 @@ import { select, dispatch } from '@wordpress/data'; import { registerBlockType, registerBlockCollection, + registerBlockVariation, unregisterBlockCollection, unregisterBlockType, setFreeformContentHandlerName, @@ -26,6 +27,7 @@ import { getBlockType, getBlockTypes, getBlockSupport, + getBlockVariations, hasBlockSupport, isReusableBlock, unstable__bootstrapServerSideBlockDefinitions, // eslint-disable-line camelcase @@ -398,39 +400,47 @@ describe( 'blocks', () => { } ); } ); - // This can be removed once polyfill adding selectors has been removed. - it( 'should apply selectors on the client when not set on the server', () => { - const blockName = 'core/test-block-with-selectors'; + it( 'should merge settings provided by server and client', () => { + const blockName = 'core/test-block-with-merged-settings'; unstable__bootstrapServerSideBlockDefinitions( { [ blockName ]: { - category: 'widgets', - }, - } ); - unstable__bootstrapServerSideBlockDefinitions( { - [ blockName ]: { - selectors: { root: '.wp-block-custom-selector' }, - category: 'ignored', + variations: [ + { name: 'foo', label: 'Foo' }, + { name: 'baz', label: 'Baz', description: 'Testing' }, + ], }, } ); const blockType = { - title: 'block title', + title: 'block settings merge', + variations: [ + { name: 'bar', label: 'Bar' }, + { name: 'baz', label: 'Baz', icon: 'layout' }, + ], }; registerBlockType( blockName, blockType ); expect( getBlockType( blockName ) ).toEqual( { name: blockName, save: expect.any( Function ), - title: 'block title', - category: 'widgets', + title: 'block settings merge', icon: { src: BLOCK_ICON_DEFAULT }, attributes: {}, providesContext: {}, usesContext: [], keywords: [], - selectors: { root: '.wp-block-custom-selector' }, + selectors: {}, supports: {}, styles: [], - variations: [], + variations: [ + { name: 'foo', label: 'Foo' }, + { + description: 'Testing', + name: 'baz', + label: 'Baz', + icon: 'layout', + }, + { name: 'bar', label: 'Bar' }, + ], blockHooks: {}, } ); } ); @@ -1402,6 +1412,26 @@ describe( 'blocks', () => { expect( isReusableBlock( block ) ).toBe( false ); } ); } ); + + describe( 'registerBlockVariation', () => { + it( 'should warn when registering block variation without a name', () => { + registerBlockType( 'core/variation-block', defaultBlockSettings ); + registerBlockVariation( 'core/variation-block', { + title: 'Variation Title', + description: 'Variation description', + } ); + + expect( console ).toHaveWarnedWith( + 'Variation names must be unique strings.' + ); + expect( getBlockVariations( 'core/variation-block' ) ).toEqual( [ + { + title: 'Variation Title', + description: 'Variation description', + }, + ] ); + } ); + } ); } ); /* eslint-enable react/forbid-elements */ diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index d609f70b91b55d..1ef9c3614922e0 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -51,7 +51,9 @@ export function registerBlockBindingsSource( source ) { type: 'REGISTER_BLOCK_BINDINGS_SOURCE', sourceName: source.name, sourceLabel: source.label, - useSource: source.useSource, + getValue: source.getValue, + setValue: source.setValue, + getPlaceholder: source.getPlaceholder, lockAttributesEditing: source.lockAttributesEditing, }; } diff --git a/packages/blocks/src/store/process-block-type.js b/packages/blocks/src/store/process-block-type.js index 889f59b55e392e..154f74c6ab7296 100644 --- a/packages/blocks/src/store/process-block-type.js +++ b/packages/blocks/src/store/process-block-type.js @@ -33,6 +33,37 @@ const LEGACY_CATEGORY_MAPPING = { layout: 'design', }; +/** + * Merge block variations bootstrapped from the server and client. + * + * When a variation is registered in both places, its properties are merged. + * + * @param {Array} bootstrappedVariations - A block type variations from the server. + * @param {Array} clientVariations - A block type variations from the client. + * @return {Array} The merged array of block variations. + */ +function mergeBlockVariations( + bootstrappedVariations = [], + clientVariations = [] +) { + const result = [ ...bootstrappedVariations ]; + + clientVariations.forEach( ( clientVariation ) => { + const index = result.findIndex( + ( bootstrappedVariation ) => + bootstrappedVariation.name === clientVariation.name + ); + + if ( index !== -1 ) { + result[ index ] = { ...result[ index ], ...clientVariation }; + } else { + result.push( clientVariation ); + } + } ); + + return result; +} + /** * Takes the unprocessed block type settings, merges them with block type metadata * and applies all the existing filters for the registered block type. @@ -46,6 +77,8 @@ const LEGACY_CATEGORY_MAPPING = { export const processBlockType = ( name, blockSettings ) => ( { select } ) => { + const bootstrappedBlockType = select.getBootstrappedBlockType( name ); + const blockType = { name, icon: BLOCK_ICON_DEFAULT, @@ -56,11 +89,14 @@ export const processBlockType = selectors: {}, supports: {}, styles: [], - variations: [], blockHooks: {}, save: () => null, - ...select.getBootstrappedBlockType( name ), + ...bootstrappedBlockType, ...blockSettings, + variations: mergeBlockVariations( + bootstrappedBlockType?.variations, + blockSettings?.variations + ), }; const settings = applyFilters( diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index f92fb376b530a7..7a3a866485e4a9 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -66,19 +66,6 @@ function bootstrappedBlockTypes( state = {}, action ) { // Don't overwrite if already set. It covers the case when metadata // was initialized from the server. if ( serverDefinition ) { - // The `selectors` prop is not yet included in the server provided - // definitions and needs to be polyfilled. This can be removed when the - // minimum supported WordPress is >= 6.3. - if ( - serverDefinition.selectors === undefined && - blockType.selectors - ) { - newDefinition = { - ...serverDefinition, - selectors: blockType.selectors, - }; - } - // The `blockHooks` prop is not yet included in the server provided // definitions and needs to be polyfilled. This can be removed when the // minimum supported WordPress is >= 6.4. @@ -389,7 +376,9 @@ export function blockBindingsSources( state = {}, action ) { ...state, [ action.sourceName ]: { label: action.sourceLabel, - useSource: action.useSource, + getValue: action.getValue, + setValue: action.setValue, + getPlaceholder: action.getPlaceholder, lockAttributesEditing: action.lockAttributesEditing ?? true, }, }; diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index 6aa4230ab920a3..437c17c02caa32 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.39.0 (2024-04-19) + ## 5.38.0 (2024-04-03) ## 5.37.0 (2024-03-21) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 979d09608d5c7b..e04b70fb534bb9 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "5.38.0", + "version": "5.39.0", "description": "WordPress Browserslist shared configuration.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/commands/CHANGELOG.md b/packages/commands/CHANGELOG.md index 97fb8999300b8b..aee350fa5e99c4 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.27.0 (2024-04-19) + ## 0.26.0 (2024-04-03) ## 0.25.0 (2024-03-21) diff --git a/packages/commands/package.json b/packages/commands/package.json index c3f7d3ead0f460..2dbcc5cf43d7e9 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "0.26.0", + "version": "0.27.0", "description": "Handles the commands menu.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index c6a32b22cdd6c9..612f2d4546655d 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,22 +2,47 @@ ## Unreleased +### Enhancements + +- `InputControl`: Add a password visibility toggle story ([#60898](https://github.com/WordPress/gutenberg/pull/60898)). +- `View`: Fix prop types ([#60919](https://github.com/WordPress/gutenberg/pull/60919)). + +### Bug Fix + +- `SlotFill`: fixed missing `getServerSnapshot` parameter in slot map ([#60943](https://github.com/WordPress/gutenberg/pull/60943)). + +### Enhancements + +- `DropZone`: Avoid a media query on mount [#60546](https://github.com/WordPress/gutenberg/pull/60546)). +- `ComboboxControl`: Simplify string normalization ([#60893](https://github.com/WordPress/gutenberg/pull/60893)). + +### Internal + +- `FontSizerPicker`: Improve docs for default units ([#60996](https://github.com/WordPress/gutenberg/pull/60996)). + +## 27.4.0 (2024-04-19) + ### Deprecation - `Navigation`: Soft deprecate component ([#59182](https://github.com/WordPress/gutenberg/pull/59182)). ### Enhancements +- `Tooltip`: Make tests faster ([#60897](https://github.com/WordPress/gutenberg/pull/60897)). - `ExternalLink`: Use unicode arrow instead of svg icon ([#60255](https://github.com/WordPress/gutenberg/pull/60255)). - `ProgressBar`: Move the indicator width styles from emotion to a CSS variable ([#60388](https://github.com/WordPress/gutenberg/pull/60388)). -- `Text`: Add `text-wrap: pretty;` to improve wrapping. ([#60164](https://github.com/WordPress/gutenberg/pull/60164)). -- `Navigator`: Navigation to the active path doesn't create a new location history. ([#60561](https://github.com/WordPress/gutenberg/pull/60561)) -- `FormToggle`: Forwards ref to input. ([#60234](https://github.com/WordPress/gutenberg/pull/60234)). -- `ToggleControl`: Forwards ref to FormToggle. ([#60234](https://github.com/WordPress/gutenberg/pull/60234)). +- `Text`: Add `text-wrap: pretty;` to improve wrapping ([#60164](https://github.com/WordPress/gutenberg/pull/60164)). +- `Navigator`: Navigation to the active path doesn't create a new location history ([#60561](https://github.com/WordPress/gutenberg/pull/60561)). +- `FormToggle`: Forwards ref to input ([#60234](https://github.com/WordPress/gutenberg/pull/60234)). +- `ToggleControl`: Forwards ref to FormToggle ([#60234](https://github.com/WordPress/gutenberg/pull/60234)). +- `CheckboxControl`: Update help text alignment ([#60787](https://github.com/WordPress/gutenberg/pull/60787)). ### Bug Fix +- `Truncate`: Fix link control link preview when it displays long URLs ([#60890](https://github.com/WordPress/gutenberg/pull/60890)). + - `ProgressBar`: Fix CSS variable with invalid value ([#60576](https://github.com/WordPress/gutenberg/pull/60576)). +- `CheckboxControl`: Fix label text wrap ([#60787](https://github.com/WordPress/gutenberg/pull/60787)). ### Experimental @@ -25,7 +50,12 @@ ### Internal +- Remove CSS hack for Internet Explorer 11 ([#60727](https://github.com/WordPress/gutenberg/pull/60727)). - `CheckboxControl`: Streamline size styles ([#60475](https://github.com/WordPress/gutenberg/pull/60475)). +- Deprecate `reduceMotion` util ([#60839](https://github.com/WordPress/gutenberg/pull/60839)). +- `InputBase`: Simplify management of focus styles. Affects all components based on `InputControl` (e.g. `SearchControl`, `NumberControl`, `UnitControl`), as well as `SelectControl`, `CustomSelectControl`, and `TreeSelect` ([#60226](https://github.com/WordPress/gutenberg/pull/60226)). +- Removed dependency on `valtio`, replaced its usage in `SlotFill` with a custom object [#60879](https://github.com/WordPress/gutenberg/pull/60879)). +- `CustomSelectControlV2`: Support disabled in item types ([#60896](https://github.com/WordPress/gutenberg/pull/60896)). ## 27.3.0 (2024-04-03) @@ -60,6 +90,7 @@ - `TextControl`: Add typings for `date`, `time` and `datetime-local` ([#59666](https://github.com/WordPress/gutenberg/pull/59666)). - `Text`, `Heading`, `ItemGroup` : Update the line height from 1.2 to 1.4 ([#60041](https://github.com/WordPress/gutenberg/pull/60041)). +- `Autocomplete` : match the autocomplete styling to that of List View and Command Palette([#60131](https://github.com/WordPress/gutenberg/pull/60131)). ### Deprecation diff --git a/packages/components/package.json b/packages/components/package.json index 188e214e79bd45..a2768c887c37ab 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "27.3.0", + "version": "27.4.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", @@ -76,8 +76,7 @@ "react-colorful": "^5.3.1", "remove-accents": "^0.5.0", "use-lilius": "^2.0.5", - "uuid": "^9.0.1", - "valtio": "1.7.0" + "uuid": "^9.0.1" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/components/src/autocomplete/style.scss b/packages/components/src/autocomplete/style.scss index 4d04b3b8b52cf2..fdb29fe577f206 100644 --- a/packages/components/src/autocomplete/style.scss +++ b/packages/components/src/autocomplete/style.scss @@ -1,6 +1,6 @@ .components-autocomplete__popover .components-popover__content { - padding: $grid-unit-20; - min-width: 220px; + padding: $grid-unit-10; + min-width: 200px; } .components-autocomplete__result.components-button { @@ -10,7 +10,13 @@ text-align: left; width: 100%; - &.is-selected { - box-shadow: 0 0 0 var(--wp-admin-border-width-focus) $components-color-accent; + &:focus:not(:disabled) { + @include block-toolbar-button-style__focus(); + } + + &.is-selected, + &:not(:disabled,[aria-disabled="true"]):active { + background: $components-color-accent; + color: $white; } } diff --git a/packages/components/src/box-control/test/index.tsx b/packages/components/src/box-control/test/index.tsx index 1ea3c84aae9225..681e7721d0c13a 100644 --- a/packages/components/src/box-control/test/index.tsx +++ b/packages/components/src/box-control/test/index.tsx @@ -80,6 +80,28 @@ describe( 'BoxControl', () => { expect( input ).toHaveValue( '50' ); expect( screen.getByRole( 'slider' ) ).toHaveValue( '50' ); } ); + + it( 'should render the number input with a default min value of 0', () => { + render( {} } /> ); + + const input = screen.getByRole( 'textbox', { name: 'All sides' } ); + + expect( input ).toHaveAttribute( 'min', '0' ); + } ); + + it( 'should pass down `inputProps` to the underlying number input', () => { + render( + {} } + inputProps={ { min: 10, max: 50 } } + /> + ); + + const input = screen.getByRole( 'textbox', { name: 'All sides' } ); + + expect( input ).toHaveAttribute( 'min', '10' ); + expect( input ).toHaveAttribute( 'max', '50' ); + } ); } ); describe( 'Reset', () => { diff --git a/packages/components/src/card/test/__snapshots__/index.tsx.snap b/packages/components/src/card/test/__snapshots__/index.tsx.snap index 0b723732e3dbaf..60dcd306f3f526 100644 --- a/packages/components/src/card/test/__snapshots__/index.tsx.snap +++ b/packages/components/src/card/test/__snapshots__/index.tsx.snap @@ -8,8 +8,8 @@ Snapshot Diff: @@ -1,8 +1,8 @@
    @@ -25,8 +25,8 @@ Snapshot Diff: @@ -1,8 +1,8 @@
    @@ -42,8 +42,8 @@ Snapshot Diff: @@ -1,8 +1,8 @@