From 8bc81ac032c5f2d829acecf18806bdee687fd11e Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Thu, 2 Nov 2023 11:05:04 +0000 Subject: [PATCH] Merge changes published in the Gutenberg plugin "release/17.0" branch --- .github/workflows/rnmobile-android-runner.yml | 10 + .github/workflows/rnmobile-ios-runner.yml | 26 +- .../upload-release-to-plugin-repo.yml | 6 +- bin/log-performance-results.js | 4 + changelog.txt | 540 + docs/contributors/code/react-native/README.md | 6 +- .../getting-started-react-native.md | 34 +- docs/explanations/architecture/entities.md | 2 +- docs/getting-started/devenv/README.md | 2 +- .../extending-the-query-loop-block.md | 2 +- .../enqueueing-assets-in-the-editor.md | 2 +- .../platform/custom-block-editor.md | 4 +- docs/manifest.json | 18 +- .../block-api/block-registration.md | 8 +- .../block-api/block-templates.md | 2 +- .../block-api/block-transforms.md | 6 +- docs/reference-guides/core-blocks.md | 8 +- .../filters/editor-filters.md | 2 +- docs/toc.json | 4 +- gutenberg.php | 2 +- lib/README.md | 2 +- lib/block-supports/layout.php | 31 +- lib/class-wp-duotone-gutenberg.php | 1 - ...class-gutenberg-html-tag-processor-6-3.php | 2413 - lib/compat/wordpress-6.4/block-patterns.php | 2 +- ...class-gutenberg-html-tag-processor-6-4.php | 32 +- lib/experimental/data-views.php | 57 + lib/experimental/disable-tinymce.php | 2 +- .../font-library/class-wp-font-family.php | 2 +- .../directives/wp-context.php | 15 +- lib/experimental/sync/README.md | 183 + .../class-gutenberg-http-signaling-server.php | 380 + lib/experimental/synchronization.php | 2 +- lib/load.php | 19 +- package-lock.json | 51919 +++++++--------- package.json | 6 +- packages/base-styles/_mixins.scss | 2 +- packages/block-editor/CHANGELOG.md | 20 +- packages/block-editor/README.md | 38 +- packages/block-editor/package.json | 8 +- .../use-available-alignments.js | 83 +- .../src/components/block-list/block.native.js | 8 +- .../src/components/block-list/layout.js | 4 +- .../src/components/block-styles/style.scss | 2 +- .../components/border-radius-control/index.js | 5 +- .../color-palette/with-color-context.js | 18 +- .../components/colors-gradients/control.js | 17 +- ...se-multiple-origin-colors-and-gradients.js | 44 +- .../src/components/colors/with-colors.js | 13 +- .../src/components/font-family/index.js | 4 +- .../components/font-sizes/font-size-picker.js | 10 +- .../components/font-sizes/with-font-sizes.js | 8 +- .../components/global-styles/filters-panel.js | 24 +- .../global-styles/image-settings-panel.js | 4 +- .../global-styles/typography-panel.js | 2 +- .../src/components/gradients/use-gradient.js | 14 +- .../src/components/height-control/index.js | 5 +- packages/block-editor/src/components/index.js | 2 +- .../src/components/index.native.js | 2 +- .../src/components/inner-blocks/index.js | 4 +- .../src/components/inserter/style.scss | 10 +- .../letter-spacing-control/index.js | 5 +- .../components/link-control/search-item.js | 14 + .../components/link-control/search-results.js | 1 + .../link-control/use-search-handler.js | 37 +- .../components/resizable-box-popover/index.js | 2 +- .../src/components/rich-text/index.js | 2 +- .../hooks/use-spacing-sizes.js | 12 +- .../input-controls/spacing-input-control.js | 5 +- .../src/components/unit-control/index.js | 11 +- .../components/use-block-commands/index.js | 3 +- .../src/components/use-setting/index.js | 218 - .../{use-setting => use-settings}/README.md | 19 +- .../src/components/use-settings/index.js | 272 + .../test/index.js | 52 +- packages/block-editor/src/hooks/align.js | 133 +- packages/block-editor/src/hooks/anchor.js | 140 +- packages/block-editor/src/hooks/background.js | 16 +- packages/block-editor/src/hooks/color.js | 11 +- packages/block-editor/src/hooks/duotone.js | 43 +- packages/block-editor/src/hooks/font-size.js | 8 +- packages/block-editor/src/hooks/layout.js | 22 +- .../block-editor/src/hooks/line-height.js | 6 +- packages/block-editor/src/hooks/position.js | 8 +- .../block-editor/src/hooks/use-color-props.js | 35 +- packages/block-editor/src/hooks/utils.js | 131 +- .../block-editor/src/layouts/constrained.js | 11 +- packages/block-editor/src/utils/object.js | 5 +- .../__snapshots__/transform-styles.js.snap | 103 + .../src/utils/test/transform-styles.js | 217 + .../src/utils/transform-styles/ast/index.js | 5 - .../src/utils/transform-styles/ast/parse.js | 732 - .../ast/stringify/compiler.js | 50 - .../ast/stringify/compress.js | 238 - .../ast/stringify/identity.js | 286 - .../transform-styles/ast/stringify/index.js | 32 - .../src/utils/transform-styles/index.js | 50 +- .../test/__snapshots__/traverse.js.snap | 7 - .../utils/transform-styles/test/traverse.js | 24 - .../test/__snapshots__/url-rewrite.js.snap | 25 - .../test/__snapshots__/wrap.js.snap | 64 - .../transforms/test/url-rewrite.js | 39 - .../transform-styles/transforms/test/wrap.js | 95 - .../transforms/url-rewrite.js | 139 - .../utils/transform-styles/transforms/wrap.js | 56 - .../src/utils/transform-styles/traverse.js | 32 - packages/block-library/src/avatar/block.json | 6 +- .../src/block/edit-title.native.js | 29 +- packages/block-library/src/block/edit.js | 2 +- packages/block-library/src/calendar/index.php | 8 +- packages/block-library/src/column/edit.js | 11 +- .../block-library/src/column/edit.native.js | 11 +- .../block-library/src/columns/edit.native.js | 11 +- .../src/comment-author-avatar/index.php | 2 +- .../src/cover/controls.native.js | 11 +- .../block-library/src/cover/edit/index.js | 5 +- .../src/cover/edit/inspector-controls.js | 11 +- packages/block-library/src/file/index.php | 3 +- packages/block-library/src/file/style.scss | 6 - packages/block-library/src/file/view.js | 4 +- .../block-library/src/form-input/block.json | 4 +- .../src/form-input/variations.js | 14 +- .../form-submission-notification/block.json | 2 +- .../variations.js | 8 +- .../src/form-submit-button/block.json | 4 +- packages/block-library/src/form/edit.js | 4 +- packages/block-library/src/form/index.js | 39 +- packages/block-library/src/form/variations.js | 2 +- .../test/__snapshots__/index.native.js.snap | 7 + .../src/freeform/test/index.native.js | 57 + packages/block-library/src/group/edit.js | 9 +- packages/block-library/src/html/preview.js | 13 +- packages/block-library/src/image/image.js | 23 +- packages/block-library/src/image/index.php | 11 +- packages/block-library/src/image/view.js | 32 +- .../block-library/src/missing/edit.native.js | 49 +- .../block-library/src/navigation/index.php | 2 +- .../block-library/src/navigation/style.scss | 7 +- packages/block-library/src/paragraph/edit.js | 4 +- .../post-featured-image/dimension-controls.js | 6 +- packages/block-library/src/post-terms/edit.js | 4 +- .../src/query-pagination-next/index.php | 2 +- .../src/query-pagination-previous/index.php | 2 +- .../query/edit/enhanced-pagination-modal.js | 58 +- .../enhanced-pagination-control.js | 40 +- packages/block-library/src/query/index.php | 105 +- packages/block-library/src/query/utils.js | 37 +- packages/block-library/src/query/view.js | 13 +- packages/block-library/src/search/edit.js | 8 +- .../src/social-link/edit.native.js | 38 +- .../src/social-link/editor.native.scss | 9 - .../block-library/src/social-link/index.php | 4 +- packages/block-library/src/spacer/controls.js | 21 +- .../src/spacer/controls.native.js | 11 +- packages/block-library/src/spacer/edit.js | 4 +- .../block-library/src/spacer/edit.native.js | 11 +- packages/block-library/src/tag-cloud/edit.js | 10 +- .../src/template-part/edit/inner-blocks.js | 6 +- .../src/term-description/block.json | 1 - packages/blocks/src/api/factory.js | 22 +- packages/blocks/src/api/test/factory.js | 30 + packages/components/CHANGELOG.md | 14 + packages/components/package.json | 3 +- .../components/src/autocomplete/index.tsx | 213 +- .../test/__snapshots__/index.test.js.snap | 16 +- .../src/dropdown-menu-v2-ariakit/README.md | 324 + .../src/dropdown-menu-v2-ariakit/index.tsx | 318 + .../stories/index.story.tsx | 506 + .../src/dropdown-menu-v2-ariakit/styles.ts | 297 + .../dropdown-menu-v2-ariakit/test/index.tsx | 1139 + .../src/dropdown-menu-v2-ariakit/types.ts | 186 + .../styles/input-control-styles.tsx | 4 +- .../global-styles-context/utils.native.js | 4 +- packages/components/src/private-apis.ts | 16 + .../styles/select-control-styles.ts | 4 +- .../bubbles-virtually/slot-fill-provider.tsx | 2 +- packages/components/src/tabs/index.tsx | 6 +- packages/components/src/tabs/test/index.tsx | 15 +- .../test/__snapshots__/index.tsx.snap | 8 + packages/components/src/tooltip/index.tsx | 5 +- packages/core-data/src/resolvers.js | 1 + packages/core-data/src/sync.js | 13 +- .../plugin-templates/$slug.php.mustache | 4 + .../plugin-templates/$slug.php.mustache | 4 + .../lib/templates/es5/$slug.php.mustache | 4 + .../lib/templates/plugin/$slug.php.mustache | 4 + packages/e2e-tests/plugins/block-context.php | 2 +- .../interactive-blocks/directive-init/view.js | 1 - .../specs/editor/blocks/site-title.test.js | 87 - .../editor/plugins/block-context.test.js | 84 - .../src/components/block-manager/style.scss | 4 +- .../sidebar/last-revision/style.scss | 3 +- .../src/components/visual-editor/index.js | 4 +- .../edit-site/src/components/actions/index.js | 123 + .../src/components/actions/trash-post.js | 55 - .../block-editor/use-site-editor-settings.js | 34 +- .../src/components/dataviews/README.md | 181 +- .../src/components/dataviews/dataviews.js | 12 +- .../src/components/dataviews/field-actions.js | 28 - .../src/components/dataviews/filters.js | 52 +- .../src/components/dataviews/in-filter.js | 12 +- .../src/components/dataviews/item-actions.js | 69 + .../src/components/dataviews/pagination.js | 127 +- .../dataviews/{text-filter.js => search.js} | 14 +- .../src/components/dataviews/style.scss | 15 +- .../src/components/dataviews/view-grid.js | 9 +- .../src/components/dataviews/view-list.js | 4 +- .../font-library-modal/font-collection.js | 2 +- .../components/global-styles/screen-block.js | 8 +- .../components/page-pages/default-views.js | 60 + .../src/components/page-pages/index.js | 145 +- .../rename-category-menu-item.js | 41 +- .../src/components/save-button/index.js | 15 +- .../src/components/sidebar-dataviews/index.js | 66 + .../page-details.js | 4 +- .../edit-site/src/components/sidebar/index.js | 2 + .../hooks/commands/use-edit-mode-commands.js | 4 +- .../edit-site/src/utils/use-activate-theme.js | 5 + .../index.js | 56 +- .../src/components/post-author/select.js | 1 + .../provider/use-block-editor-settings.js | 4 + packages/env/CHANGELOG.md | 4 + packages/env/lib/cache.js | 3 + packages/env/lib/commands/start.js | 17 +- packages/env/lib/config/parse-config.js | 2 +- .../env/lib/config/test/config-integration.js | 2 + packages/env/lib/test/cache.js | 1 + packages/env/lib/wordpress.js | 45 +- .../format-library/src/text-color/index.js | 8 +- .../src/text-color/index.native.js | 4 +- packages/interactivity/CHANGELOG.md | 4 + packages/interactivity/src/router.js | 7 +- packages/patterns/package.json | 1 + .../rename-pattern-category-modal.js | 78 +- packages/patterns/src/components/style.scss | 9 + packages/react-native-aztec/package.json | 2 +- packages/react-native-bridge/package.json | 2 +- packages/react-native-editor/.gitignore | 5 + packages/react-native-editor/CHANGELOG.md | 6 + .../__device-tests__/CONTRIBUTING.md | 44 - .../__device-tests__/README.md | 136 +- ...erg-editor-block-insertion-@canary.test.js | 31 +- .../gutenberg-editor-device-actions.test.js | 107 +- .../gutenberg-editor-drag-and-drop.test.js | 78 +- ...enberg-editor-media-blocks-@canary.test.js | 13 +- ...berg-editor-rendering-media-blocks.test.js | 2 +- .../gutenberg-editor-search.test.js | 2 +- .../__device-tests__/helpers/caps.js | 54 +- .../helpers/device-config.json | 29 + .../helpers/get-android-emulator-id.js | 30 + .../__device-tests__/helpers/serverConfigs.js | 8 +- .../__device-tests__/helpers/test-data.js | 4 +- .../__device-tests__/helpers/utils.js | 454 +- .../__device-tests__/pages/editor-page.js | 212 +- .../react-native-editor/bin/build-e2e-wda.sh | 10 + .../react-native-editor/bin/build_e2e_ios_app | 7 +- .../react-native-editor/bin/test-e2e-setup.sh | 30 + packages/react-native-editor/bin/test-e2e.sh | 20 + packages/react-native-editor/ios/Podfile.lock | 8 +- .../jest_ui_setup_after_env.js | 71 +- packages/react-native-editor/package.json | 7 +- .../react-native-editor/src/jsdom-patches.js | 24 +- packages/scripts/README.md | 2 +- packages/scripts/config/playwright.config.js | 5 +- .../scripts/config/playwright/global-setup.js | 4 +- packages/scripts/scripts/test-playwright.js | 4 +- packages/sync/README.md | 22 +- packages/sync/package.json | 6 + packages/sync/src/connect-webrtc.js | 28 - packages/sync/src/create-webrtc-connection.js | 39 + packages/sync/src/index.js | 2 +- .../sync/src/webrtc-http-stream-signaling.js | 401 + packages/sync/src/y-webrtc/crypto.js | 127 + packages/sync/src/y-webrtc/y-webrtc.js | 858 + packages/sync/tsconfig.json | 3 +- phpunit/blocks/render-query-test.php | 263 + .../directives/wp-context-test.php | 102 + ...g-html-tag-processor-6-3-bookmark-test.php | 45 - schemas/json/block.json | 10 + .../specs/editor/blocks/site-title.spec.js | 46 + .../editor/plugins/block-context.spec.js | 78 + .../various/autocomplete-and-mentions.spec.js | 9 +- test/e2e/specs/editor/various/preview.spec.js | 1 + .../fixtures/interactivity-utils.ts | 1 + .../interactivity/router-regions.spec.ts | 14 + test/native/jest.config.js | 17 + test/performance/fixtures/perf-utils.ts | 53 +- test/performance/playwright.config.ts | 1 + test/performance/specs/post-editor.spec.js | 4 +- test/performance/specs/site-editor.spec.js | 6 +- 290 files changed, 33588 insertions(+), 34961 deletions(-) delete mode 100644 lib/compat/wordpress-6.3/html-api/class-gutenberg-html-tag-processor-6-3.php create mode 100644 lib/experimental/data-views.php create mode 100644 lib/experimental/sync/README.md create mode 100644 lib/experimental/sync/class-gutenberg-http-signaling-server.php delete mode 100644 packages/block-editor/src/components/use-setting/index.js rename packages/block-editor/src/components/{use-setting => use-settings}/README.md (67%) create mode 100644 packages/block-editor/src/components/use-settings/index.js rename packages/block-editor/src/components/{use-setting => use-settings}/test/index.js (58%) create mode 100644 packages/block-editor/src/utils/test/__snapshots__/transform-styles.js.snap create mode 100644 packages/block-editor/src/utils/test/transform-styles.js delete mode 100644 packages/block-editor/src/utils/transform-styles/ast/index.js delete mode 100644 packages/block-editor/src/utils/transform-styles/ast/parse.js delete mode 100644 packages/block-editor/src/utils/transform-styles/ast/stringify/compiler.js delete mode 100644 packages/block-editor/src/utils/transform-styles/ast/stringify/compress.js delete mode 100644 packages/block-editor/src/utils/transform-styles/ast/stringify/identity.js delete mode 100644 packages/block-editor/src/utils/transform-styles/ast/stringify/index.js delete mode 100644 packages/block-editor/src/utils/transform-styles/test/__snapshots__/traverse.js.snap delete mode 100644 packages/block-editor/src/utils/transform-styles/test/traverse.js delete mode 100644 packages/block-editor/src/utils/transform-styles/transforms/test/__snapshots__/url-rewrite.js.snap delete mode 100644 packages/block-editor/src/utils/transform-styles/transforms/test/__snapshots__/wrap.js.snap delete mode 100644 packages/block-editor/src/utils/transform-styles/transforms/test/url-rewrite.js delete mode 100644 packages/block-editor/src/utils/transform-styles/transforms/test/wrap.js delete mode 100644 packages/block-editor/src/utils/transform-styles/transforms/url-rewrite.js delete mode 100644 packages/block-editor/src/utils/transform-styles/transforms/wrap.js delete mode 100644 packages/block-editor/src/utils/transform-styles/traverse.js create mode 100644 packages/block-library/src/freeform/test/__snapshots__/index.native.js.snap create mode 100644 packages/block-library/src/freeform/test/index.native.js create mode 100644 packages/components/src/dropdown-menu-v2-ariakit/README.md create mode 100644 packages/components/src/dropdown-menu-v2-ariakit/index.tsx create mode 100644 packages/components/src/dropdown-menu-v2-ariakit/stories/index.story.tsx create mode 100644 packages/components/src/dropdown-menu-v2-ariakit/styles.ts create mode 100644 packages/components/src/dropdown-menu-v2-ariakit/test/index.tsx create mode 100644 packages/components/src/dropdown-menu-v2-ariakit/types.ts delete mode 100644 packages/e2e-tests/specs/editor/blocks/site-title.test.js delete mode 100644 packages/e2e-tests/specs/editor/plugins/block-context.test.js create mode 100644 packages/edit-site/src/components/actions/index.js delete mode 100644 packages/edit-site/src/components/actions/trash-post.js delete mode 100644 packages/edit-site/src/components/dataviews/field-actions.js create mode 100644 packages/edit-site/src/components/dataviews/item-actions.js rename packages/edit-site/src/components/dataviews/{text-filter.js => search.js} (77%) create mode 100644 packages/edit-site/src/components/page-pages/default-views.js create mode 100644 packages/edit-site/src/components/sidebar-dataviews/index.js delete mode 100644 packages/react-native-editor/__device-tests__/CONTRIBUTING.md create mode 100644 packages/react-native-editor/__device-tests__/helpers/device-config.json create mode 100644 packages/react-native-editor/__device-tests__/helpers/get-android-emulator-id.js create mode 100755 packages/react-native-editor/bin/build-e2e-wda.sh create mode 100755 packages/react-native-editor/bin/test-e2e-setup.sh create mode 100755 packages/react-native-editor/bin/test-e2e.sh delete mode 100644 packages/sync/src/connect-webrtc.js create mode 100644 packages/sync/src/create-webrtc-connection.js create mode 100644 packages/sync/src/webrtc-http-stream-signaling.js create mode 100644 packages/sync/src/y-webrtc/crypto.js create mode 100644 packages/sync/src/y-webrtc/y-webrtc.js create mode 100644 phpunit/blocks/render-query-test.php delete mode 100644 phpunit/html-api/class-gutenberg-html-tag-processor-6-3-bookmark-test.php create mode 100644 test/e2e/specs/editor/blocks/site-title.spec.js create mode 100644 test/e2e/specs/editor/plugins/block-context.spec.js diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index 8a51df3faade2..5f33870be6879 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -36,6 +36,16 @@ jobs: - name: Setup Node.js and install dependencies uses: ./.github/setup-node + - name: Restore tests setup cache + uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + with: + path: | + ~/.appium + key: ${{ runner.os }}-tests-setup-${{ hashFiles('package-lock.json') }} + + - name: Prepare tests setup + run: npm run native test:e2e:setup + - name: Gradle cache uses: gradle/gradle-build-action@b5126f31dbc19dd434c3269bf8c28c315e121da2 # v2.8.1 diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index 60eb439d1e1c2..8f32a9ee9d9dc 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -18,8 +18,8 @@ jobs: if: ${{ github.repository == 'WordPress/gutenberg' || github.event_name == 'pull_request' }} strategy: matrix: - xcode: ['13.3.1'] - device: ['iPhone 13'] + xcode: ['14.2'] + device: ['iPhone 14'] native-test-name: [gutenberg-editor-rendering] steps: @@ -27,9 +27,25 @@ jobs: with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + - name: Switch Xcode version to ${{ matrix.xcode }} + run: sudo xcode-select --switch /Applications/Xcode_${{ matrix.xcode }}.app + + - name: Launch simulator + run: (open -a Simulator && xcrun simctl boot '${{ matrix.device }}') & + - name: Setup Node.js and install dependencies uses: ./.github/setup-node + - name: Restore tests setup cache + uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + with: + path: | + ~/.appium + key: ${{ runner.os }}-tests-setup-${{ hashFiles('package-lock.json') }} + + - name: Prepare tests setup + run: npm run native test:e2e:setup + - name: Prepare build cache key run: find package-lock.json packages/react-native-editor/ios packages/react-native-aztec/ios packages/react-native-bridge/ios -type f -print0 | sort -z | xargs -0 shasum | tee ios-checksums.txt @@ -54,18 +70,12 @@ jobs: - name: Bundle iOS run: npm run native test:e2e:bundle:ios - - name: Switch Xcode version to ${{ matrix.xcode }} - run: sudo xcode-select --switch /Applications/Xcode_${{ matrix.xcode }}.app - - name: Build (if needed) run: test -e packages/react-native-editor/ios/build/GutenbergDemo/Build/Products/Release-iphonesimulator/GutenbergDemo.app/GutenbergDemo || npm run native test:e2e:build-app:ios - name: Build Web Driver Agent (if needed) run: test -d packages/react-native-editor/ios/build/WDA || npm run native test:e2e:build-wda - - name: Launch simulator - run: open -a Simulator && xcrun simctl boot '${{ matrix.device }}' - - name: Run iOS Device Tests run: TEST_RN_PLATFORM=ios npm run native device-tests:local ${{ matrix.native-test-name }} diff --git a/.github/workflows/upload-release-to-plugin-repo.yml b/.github/workflows/upload-release-to-plugin-repo.yml index 2b5ca0e5a8593..11ba57b439b59 100644 --- a/.github/workflows/upload-release-to-plugin-repo.yml +++ b/.github/workflows/upload-release-to-plugin-repo.yml @@ -200,7 +200,8 @@ jobs: svn st | grep '^?' | awk '{print $2}' | xargs -r svn add svn st | grep '^!' | awk '{print $2}' | xargs -r svn rm svn commit -m "Committing version $VERSION" \ - --no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD" + --no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD" \ + --config-option=servers:global:http-timeout=300 - name: Create the SVN tag working-directory: ./trunk @@ -254,4 +255,5 @@ jobs: - name: Add the new version directory and commit changes to the SVN repository run: | svn import "$VERSION" "$PLUGIN_REPO_URL/tags/$VERSION" -m "Committing version $VERSION" \ - --no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD" + --no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD" \ + --config-option=servers:global:http-timeout=300 diff --git a/bin/log-performance-results.js b/bin/log-performance-results.js index 861e09bbc6c4d..f18e40fea3d2f 100755 --- a/bin/log-performance-results.js +++ b/bin/log-performance-results.js @@ -13,6 +13,10 @@ const resultsFiles = [ file: 'post-editor.performance-results.json', metricsPrefix: '', }, + { + file: 'site-editor.performance-results.json', + metricsPrefix: 'site-editor-', + }, { file: 'front-end-block-theme.performance-results.json', metricsPrefix: 'block-theme-', diff --git a/changelog.txt b/changelog.txt index f681205d6b98e..4789d83da9768 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,545 @@ == Changelog == += 17.0.0-rc.1 = + + + +## Changelog + +### Features + +#### Data Views +- Add: Ability to persist dataviews on the database. ([55465](https://github.com/WordPress/gutenberg/pull/55465)) +- DataViews: Extract `search` from filters. ([55722](https://github.com/WordPress/gutenberg/pull/55722)) +- DataViews: Limit users to those who have published pages. ([55455](https://github.com/WordPress/gutenberg/pull/55455)) +- Dataviews: List all pages, not only those with publish and draft statuses. ([55476](https://github.com/WordPress/gutenberg/pull/55476)) + +#### Patterns +- Revert "Patterns: Fix capabilities settings for pattern categories. ([55532](https://github.com/WordPress/gutenberg/pull/55532)) + + +### Enhancements + +- Add blog icon to the blog home page in LinkControl search results. ([55610](https://github.com/WordPress/gutenberg/pull/55610)) +- Add: Default readonly views to dataviews. ([55740](https://github.com/WordPress/gutenberg/pull/55740)) +- Add: Possibility to tree shake DataViewsProvider. ([55641](https://github.com/WordPress/gutenberg/pull/55641)) +- Block Theme Preview: Display loading state when activating. ([55658](https://github.com/WordPress/gutenberg/pull/55658)) +- Improve toolbar button focus visual. ([55523](https://github.com/WordPress/gutenberg/pull/55523)) + +#### Components +- Add new ariakit-based `DropdownMenu` component. ([54939](https://github.com/WordPress/gutenberg/pull/54939)) +- Update InputControl and SelectControl default heights. ([55490](https://github.com/WordPress/gutenberg/pull/55490)) +- Update ariakit to version 0.3.5. ([55365](https://github.com/WordPress/gutenberg/pull/55365)) + +#### Block Library +- Allow using groups and columns inside the experimental form block. ([55758](https://github.com/WordPress/gutenberg/pull/55758)) + +#### Block Editor +- Adjust the padding of the category item to make it visually balanced. ([55598](https://github.com/WordPress/gutenberg/pull/55598)) + +#### Data Views +- [Data views]: Update icons and design tweaks. ([55391](https://github.com/WordPress/gutenberg/pull/55391)) + +#### Patterns +- Suggest commands when editing pattern in site editor. ([55332](https://github.com/WordPress/gutenberg/pull/55332)) + + +### Bug Fixes + +- Block Editor: Avoid rendering empty Slot for block alignments. ([55689](https://github.com/WordPress/gutenberg/pull/55689)) +- Block Example: Avoid a crash when block is not registered. ([55686](https://github.com/WordPress/gutenberg/pull/55686)) +- Command Palette: Fix a crash when transform to a block without icon. ([55676](https://github.com/WordPress/gutenberg/pull/55676)) +- Ensure Term Description block is registered in core. ([55669](https://github.com/WordPress/gutenberg/pull/55669)) +- Fix autocomplete trigger character detection. ([55301](https://github.com/WordPress/gutenberg/pull/55301)) +- Fix typo in `FontCollection`. ([55439](https://github.com/WordPress/gutenberg/pull/55439)) +- Fix: Add __next40pxDefaultSize to author select in PostAuthor. ([55597](https://github.com/WordPress/gutenberg/pull/55597)) +- Fix: Add home icon to the front page in LinkControl results. ([55606](https://github.com/WordPress/gutenberg/pull/55606)) +- Fix: Don't register dataviews postype and taxonomy if experiment is disabled. ([55743](https://github.com/WordPress/gutenberg/pull/55743)) +- Fix: LinkControl on site editor does not show font page and post page indication. ([55694](https://github.com/WordPress/gutenberg/pull/55694)) +- Fix: LinkControl on widgets editor does not show font page and post page indication. ([55732](https://github.com/WordPress/gutenberg/pull/55732)) +- Fix: Post terms block: Missing options for prefix and suffix when the…. ([55726](https://github.com/WordPress/gutenberg/pull/55726)) +- Fix: Update page title when using enhanced pagination in query loop. ([55446](https://github.com/WordPress/gutenberg/pull/55446)) +- Use PostCSS + PostCSS plugins for style transformation. ([49521](https://github.com/WordPress/gutenberg/pull/49521)) + +#### Block Library +- Fix #55679 missing space in the string. ([55682](https://github.com/WordPress/gutenberg/pull/55682)) +- Image block: Wrap images with hrefs in an A tag. ([55470](https://github.com/WordPress/gutenberg/pull/55470)) +- Image: Improve focus management in lightbox. ([55428](https://github.com/WordPress/gutenberg/pull/55428)) +- Image: Update default fullscreen icon for lightbox trigger. ([55463](https://github.com/WordPress/gutenberg/pull/55463)) +- Navigation block: Remove browser default padding from the two submenu buttons. ([50943](https://github.com/WordPress/gutenberg/pull/50943)) +- Query Loop: Disallow "enhanced pagination" with core blocks that may contain third-party blocks. ([55539](https://github.com/WordPress/gutenberg/pull/55539)) +- Query block enhanced pagination: Detect inner plugin blocks during render. ([55714](https://github.com/WordPress/gutenberg/pull/55714)) +- Query: Require queryId for enhanced pagination to prevent PHP notices. ([55720](https://github.com/WordPress/gutenberg/pull/55720)) +- Update label for lightbox editor UI. ([55724](https://github.com/WordPress/gutenberg/pull/55724)) +- [Block] File: Fix embedded PDF files in Safari. ([55667](https://github.com/WordPress/gutenberg/pull/55667)) + +#### Patterns +- Fix bug with authors and contributors not seeing user pattern categories. ([55553](https://github.com/WordPress/gutenberg/pull/55553)) +- Fix capabilities settings for pattern categories. ([55379](https://github.com/WordPress/gutenberg/pull/55379)) +- Fix pattern category renaming causing potential duplicate categories. ([55607](https://github.com/WordPress/gutenberg/pull/55607)) + +#### Post Editor +- Edit Post: Fix revision button misalignment. ([55659](https://github.com/WordPress/gutenberg/pull/55659)) +- Preferences modal: Fix the position of sticky heading when blocks are hidden. ([55456](https://github.com/WordPress/gutenberg/pull/55456)) + +#### Site Editor +- Fix the 'Slug' display for draft pages. ([55774](https://github.com/WordPress/gutenberg/pull/55774)) + +#### Data Views +- DataViews: List all users in author filter. ([55723](https://github.com/WordPress/gutenberg/pull/55723)) + +#### Design Tools +- Fix: Remove default dimensions controls from core/avatar. ([55596](https://github.com/WordPress/gutenberg/pull/55596)) + +#### Collaborative Editing +- Remove dangling comma causing PHPUnit failures. ([55494](https://github.com/WordPress/gutenberg/pull/55494)) + +#### Interactivity API +- Fix server processing of an empty `data-wp-context` directive. ([55482](https://github.com/WordPress/gutenberg/pull/55482)) + +#### Layout +- Make layout support compatible with enhanced pagination. ([55416](https://github.com/WordPress/gutenberg/pull/55416)) + +#### Colors +- Make duotone support compatible with enhanced pagination. ([55415](https://github.com/WordPress/gutenberg/pull/55415)) + +#### Global Styles +- Fix duotone not showing in site editor style block level styles. ([55361](https://github.com/WordPress/gutenberg/pull/55361)) + + +### Accessibility + +#### Block Library +- Navigation block: Change aria-haspopup to dialog. ([55466](https://github.com/WordPress/gutenberg/pull/55466)) + +#### Components +- Autocomplete: Fix Voiceover not announcing suggestions. ([54902](https://github.com/WordPress/gutenberg/pull/54902)) + +#### Interactivity API +- Query Loop: Update modal role and focus first element. ([54507](https://github.com/WordPress/gutenberg/pull/54507)) + + +### Performance + +- Add useSettings hook for reading multiple settings at once. ([55337](https://github.com/WordPress/gutenberg/pull/55337)) +- Block Editor: Optimize 'Layout' controls. ([55754](https://github.com/WordPress/gutenberg/pull/55754)) +- Block Editor: Optimize 'anchor' inspector controls. ([55721](https://github.com/WordPress/gutenberg/pull/55721)) +- Block Editor: Optimize 'duotone' controls. ([55753](https://github.com/WordPress/gutenberg/pull/55753)) +- Block Editor: Optimize alignment toolbar controls. ([55692](https://github.com/WordPress/gutenberg/pull/55692)) +- Start logging site editor metrics in codevitals. ([55759](https://github.com/WordPress/gutenberg/pull/55759)) +- useAvailableAlignments: Avoid useSelect subscription when alignments array is empty. ([55449](https://github.com/WordPress/gutenberg/pull/55449)) + + +### Experiments + +#### Data Views +- Trash Data View: Use trash icon. ([55771](https://github.com/WordPress/gutenberg/pull/55771)) +- [Data views]: Add quick actions. ([55488](https://github.com/WordPress/gutenberg/pull/55488)) + +#### Block Library +- Form Blocks: Capitalize title and end the description with a period. ([55728](https://github.com/WordPress/gutenberg/pull/55728)) + + +### Documentation + +- Adds a few grammar fixes to `block-registration` documentation. ([55663](https://github.com/WordPress/gutenberg/pull/55663)) +- Block JSON schema: Add heading/button key to color definition. ([55675](https://github.com/WordPress/gutenberg/pull/55675)) +- DataViews: Document `data` and `filters`. ([55504](https://github.com/WordPress/gutenberg/pull/55504)) +- Docs: Fix some typos. ([55654](https://github.com/WordPress/gutenberg/pull/55654)) +- Docs: Sidebar Block editor handbook - create-block before wp-scripts. ([55534](https://github.com/WordPress/gutenberg/pull/55534)) +- Fix: Typos inside /docs. ([55472](https://github.com/WordPress/gutenberg/pull/55472)) +- Scripts: Fix typo in readme. ([55531](https://github.com/WordPress/gutenberg/pull/55531)) +- Update links to point to getting started guides. ([55479](https://github.com/WordPress/gutenberg/pull/55479)) +- docs: Fix end-to-end test documentation formatting. ([55631](https://github.com/WordPress/gutenberg/pull/55631)) + + +### Code Quality + +- CS: Remove redundant ignore annotations. ([55615](https://github.com/WordPress/gutenberg/pull/55615)) +- Chore: Fix: Potential access to properties of undefined object. ([55697](https://github.com/WordPress/gutenberg/pull/55697)) +- Fix: Add missing defaultStatuses on PagePages. ([55761](https://github.com/WordPress/gutenberg/pull/55761)) +- Resizeable box (for resizing cover block) should use after block popover slot. ([55784](https://github.com/WordPress/gutenberg/pull/55784)) +- Update: Code quality: Use for each instead of map. ([55798](https://github.com/WordPress/gutenberg/pull/55798)) +- Update: Remove path awareness from data-views specific code. ([55695](https://github.com/WordPress/gutenberg/pull/55695)) +- Update: Remove useless self assignment. ([55696](https://github.com/WordPress/gutenberg/pull/55696)) +- chore: Fix: Remove unused file dataview context. ([55775](https://github.com/WordPress/gutenberg/pull/55775)) + +#### Data Views +- DataViews: Iterate on filter's API. ([55440](https://github.com/WordPress/gutenberg/pull/55440)) +- DataViews: Pass `search` filter as global, unattached from fields. ([55475](https://github.com/WordPress/gutenberg/pull/55475)) +- DataViews: Remove string from pages sidebar. ([55510](https://github.com/WordPress/gutenberg/pull/55510)) +- Rename `TextFilter` to `Search`. ([55731](https://github.com/WordPress/gutenberg/pull/55731)) + +#### Block Library +- Pattern: Unlock the private hook outside the component. ([55792](https://github.com/WordPress/gutenberg/pull/55792)) + +#### Patterns +- Change pattern category taxonomy public param to false. ([55748](https://github.com/WordPress/gutenberg/pull/55748)) + + +### Tools + +- Replace 'npx' with 'node' on test-playwright.js file'. ([55616](https://github.com/WordPress/gutenberg/pull/55616)) +- wp-env: Fix errors which prevent it from working without internet. ([53547](https://github.com/WordPress/gutenberg/pull/53547)) + +#### Testing +- E2E: Revert typing delay on the autocomplete mentions test. ([55132](https://github.com/WordPress/gutenberg/pull/55132)) +- Fix flaky 'Switch to Draft' action in Preview end-to-end tests. ([55772](https://github.com/WordPress/gutenberg/pull/55772)) +- Migrate 'Site Title block' end-to-end tests to Playwright. ([55704](https://github.com/WordPress/gutenberg/pull/55704)) +- Migrate 'block context' end-to-end tests to Playwright. ([55793](https://github.com/WordPress/gutenberg/pull/55793)) +- Performance tests: Fix canvas locator timeout. ([55441](https://github.com/WordPress/gutenberg/pull/55441)) +- Scripts: Fix default Playwright configuration. ([55453](https://github.com/WordPress/gutenberg/pull/55453)) + + +### Various + +- Form: Update copy. ([55468](https://github.com/WordPress/gutenberg/pull/55468)) +- [create-block] Add ABSPATH check. ([55533](https://github.com/WordPress/gutenberg/pull/55533)) + +#### HTML API +- Backport updates from Core during the 6.4 release cycle. ([55703](https://github.com/WordPress/gutenberg/pull/55703)) + +#### Collaborative Editing +- [Try] HTTP based PHP signaling server for colaborative editing. ([53922](https://github.com/WordPress/gutenberg/pull/53922)) + + +## First time contributors + +The following PRs were merged by first time contributors: + +- @garibiza: Fix #55679 missing space in the string. ([55682](https://github.com/WordPress/gutenberg/pull/55682)) +- @iamsadi22: Replace 'npx' with 'node' on test-playwright.js file'. ([55616](https://github.com/WordPress/gutenberg/pull/55616)) +- @parikshit-adhikari: Fix: Typos inside /docs. ([55472](https://github.com/WordPress/gutenberg/pull/55472)) +- @strarsis: Use PostCSS + PostCSS plugins for style transformation. ([49521](https://github.com/WordPress/gutenberg/pull/49521)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @ajlende @alexstine @aristath @artemiomorales @arthur791004 @aurooba @c4rl0sbr4v0 @carolinan @ciampo @DAreRodz @dcalhoun @derekblank @dmsnell @fluiddot @garibiza @geriux @glendaviesnz @iamsadi22 @jameskoster @jeryj @jorgefilipecosta @jsnajdr @juanmaguitar @kevin940726 @KevinBatdorf @luisherranz @MaggieCabrera @Mamaduka @noahtallen @ntsekouras @oandregal @parikshit-adhikari @peterwilsoncc @ramonjd @richtabor @SergeyBiryukov @SiobhyB @Soean @strarsis @swissspidy @t-hamano @talldan @WunderBart @youknowriad + + += 16.9.0 = + +## Changelog + +### Features + +#### Create Block +- Introduce the transformer property. ([55423](https://github.com/WordPress/gutenberg/pull/55423)) + +#### Data Views +- Enable users to sort by `date`. ([55388](https://github.com/WordPress/gutenberg/pull/55388)) + +#### Block Library +- Enable Block Renaming support for (almost) all blocks. ([54426](https://github.com/WordPress/gutenberg/pull/54426)) + + +### Enhancements + +#### Command API +- Add block-specific commands as contextual suggestions [#53539]. ([53974](https://github.com/WordPress/gutenberg/pull/53974)) + +#### Components +- Add `Tabs` (a composable `TabPanel` v2). ([53960](https://github.com/WordPress/gutenberg/pull/53960)) +- Add `type="button"` to vanilla `'; @@ -322,12 +320,13 @@ function block_core_image_render_lightbox( $block_content, $block ) { data-wp-on--touchmove="actions.core.image.handleTouchMove" data-wp-on--touchend="actions.core.image.handleTouchEnd" data-wp-on--click="actions.core.image.hideLightbox" + tabindex="-1" > - + HTML; diff --git a/packages/block-library/src/image/view.js b/packages/block-library/src/image/view.js index 30d1259637e3d..331c0e79c731f 100644 --- a/packages/block-library/src/image/view.js +++ b/packages/block-library/src/image/view.js @@ -135,7 +135,7 @@ store( false ); }, - hideLightbox: async ( { context, event } ) => { + hideLightbox: async ( { context } ) => { context.core.image.hideAnimationEnabled = true; if ( context.core.image.lightboxEnabled ) { // We want to wait until the close animation is completed @@ -149,19 +149,15 @@ store( 'scroll', scrollCallback ); + // If we don't delay before changing the focus, + // the focus ring will appear on Firefox before + // the image has finished animating, which looks broken. + context.core.image.lightboxTriggerRef.focus( { + preventScroll: true, + } ); }, 450 ); context.core.image.lightboxEnabled = false; - - // We want to avoid drawing attention to the button - // after the lightbox closes for mouse and touch users. - // Note that the `event.pointerType` property returns - // as an empty string if a keyboard fired the event. - if ( event.pointerType === '' ) { - context.core.image.lastFocusedElement.focus( { - preventScroll: true, - } ); - } } }, handleKeydown: ( { context, actions, event } ) => { @@ -266,6 +262,10 @@ store( image: { initOriginImage: ( { context, ref } ) => { context.core.image.imageRef = ref; + context.core.image.lightboxTriggerRef = + ref.parentElement.querySelector( + '.lightbox-trigger' + ); if ( ref.complete ) { context.core.image.imageLoaded = true; context.core.image.imageCurrentSrc = ref.currentSrc; @@ -282,14 +282,8 @@ store( focusableElements.length - 1 ]; - // We want to avoid drawing unnecessary attention to the close - // button for mouse and touch users. Note that even if opening - // the lightbox via keyboard, the event fired is of type - // `pointerEvent`, so we need to rely on the `event.pointerType` - // property, which returns an empty string for keyboard events. - if ( context.core.image.pointerType === '' ) { - ref.querySelector( '.close-button' ).focus(); - } + // Move focus to the dialog when opening it. + ref.focus(); } }, setButtonStyles: ( { context, ref } ) => { diff --git a/packages/block-library/src/missing/edit.native.js b/packages/block-library/src/missing/edit.native.js index 8aa4738aeea85..a6164f590ca21 100644 --- a/packages/block-library/src/missing/edit.native.js +++ b/packages/block-library/src/missing/edit.native.js @@ -14,7 +14,7 @@ import { import { Icon } from '@wordpress/components'; import { compose, withPreferredColorScheme } from '@wordpress/compose'; import { coreBlocks } from '@wordpress/block-library'; -import { normalizeIconObject } from '@wordpress/blocks'; +import { normalizeIconObject, rawHandler, serialize } from '@wordpress/blocks'; import { Component } from '@wordpress/element'; import { __, _x, sprintf } from '@wordpress/i18n'; import { help, plugins } from '@wordpress/icons'; @@ -24,6 +24,7 @@ import { UnsupportedBlockDetails, store as blockEditorStore, } from '@wordpress/block-editor'; +import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies @@ -34,6 +35,8 @@ import styles from './style.scss'; const UBE_INCOMPATIBLE_BLOCKS = [ 'core/block' ]; const I18N_BLOCK_SCHEMA_TITLE = 'block title'; +const EMPTY_ARRAY = []; + export class UnsupportedBlockEdit extends Component { constructor( props ) { super( props ); @@ -119,16 +122,39 @@ export class UnsupportedBlockEdit extends Component { } renderSheet( blockTitle, blockName ) { - const { clientId } = this.props; + const { block, clientId, createSuccessNotice, replaceBlocks } = + this.props; const { showHelp } = this.state; + /* translators: Missing block alert title. %s: The localized block name */ const titleFormat = __( "'%s' is not fully-supported" ); const title = sprintf( titleFormat, blockTitle ); - const description = applyFilters( + let description = applyFilters( 'native.missing_block_detail', __( 'We are working hard to add more blocks with each release.' ), blockName ); + let customActions = EMPTY_ARRAY; + + // For Classic blocks, we offer the alternative to convert the content to blocks. + if ( blockName === 'core/freeform' ) { + description += + ' ' + + __( 'Alternatively, you can convert the content to blocks.' ); + /* translators: displayed right after the classic block is converted to blocks. %s: The localized classic block name */ + const successNotice = __( "'%s' block converted to blocks" ); + customActions = [ + { + label: __( 'Convert to blocks' ), + onPress: () => { + createSuccessNotice( + sprintf( successNotice, blockTitle ) + ); + replaceBlocks( block ); + }, + }, + ]; + } return ( ); } @@ -202,8 +229,9 @@ export class UnsupportedBlockEdit extends Component { } export default compose( [ - withSelect( ( select, { attributes } ) => { - const { capabilities } = select( blockEditorStore ).getSettings(); + withSelect( ( select, { attributes, clientId } ) => { + const { getBlock, getSettings } = select( blockEditorStore ); + const { capabilities } = getSettings(); return { isUnsupportedBlockEditorSupported: capabilities?.unsupportedBlockEditor === true, @@ -211,14 +239,23 @@ export default compose( [ capabilities?.canEnableUnsupportedBlockEditor === true, isEditableInUnsupportedBlockEditor: ! UBE_INCOMPATIBLE_BLOCKS.includes( attributes.originalName ), + block: getBlock( clientId ), }; } ), withDispatch( ( dispatch, ownProps ) => { - const { selectBlock } = dispatch( blockEditorStore ); + const { selectBlock, replaceBlocks } = dispatch( blockEditorStore ); + const { createSuccessNotice } = dispatch( noticesStore ); return { selectBlock() { selectBlock( ownProps.clientId ); }, + replaceBlocks( block ) { + replaceBlocks( + ownProps.clientId, + rawHandler( { HTML: serialize( block ) } ) + ); + }, + createSuccessNotice, }; } ), withPreferredColorScheme, diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index 592d188e22ae7..209a8b1c17c16 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -744,7 +744,7 @@ function render_block_core_navigation( $attributes, $content, $block ) { } $responsive_container_markup = sprintf( - ' + '
diff --git a/packages/block-library/src/navigation/style.scss b/packages/block-library/src/navigation/style.scss index eb8ef7683e198..0b70ebb656cfa 100644 --- a/packages/block-library/src/navigation/style.scss +++ b/packages/block-library/src/navigation/style.scss @@ -317,7 +317,9 @@ button.wp-block-navigation-item__content { // When set to open on click, a button element is used. // We pad it to include the arrow icon in the clickable area. // The padding can be blanket for click, since you can't set click and hide the icon. +// This is only applied to the submenu in the page list block. .wp-block-navigation-item.open-on-click .wp-block-navigation-submenu__toggle { + padding-left: 0; // Remove the browser default padding. padding-right: 0.6em + 0.25em; // Same size as icon plus margin. + .wp-block-navigation__submenu-icon { @@ -325,7 +327,10 @@ button.wp-block-navigation-item__content { pointer-events: none; // Make the icon inert to allow click on the button. } } - +// Remove the browser default padding on the button element used in the navigation link submenu. +.wp-block-navigation-item.open-on-click button.wp-block-navigation-item__content:not(.wp-block-navigation-submenu__toggle) { + padding: 0; +} /** * Margins diff --git a/packages/block-library/src/paragraph/edit.js b/packages/block-library/src/paragraph/edit.js index 21f692bd25b26..37a9c2ab9b10a 100644 --- a/packages/block-library/src/paragraph/edit.js +++ b/packages/block-library/src/paragraph/edit.js @@ -18,7 +18,7 @@ import { InspectorControls, RichText, useBlockProps, - useSetting, + useSettings, } from '@wordpress/block-editor'; import { createBlock } from '@wordpress/blocks'; import { formatLtr } from '@wordpress/icons'; @@ -58,7 +58,7 @@ function ParagraphBlock( { clientId, } ) { const { align, content, direction, dropCap, placeholder } = attributes; - const isDropCapFeatureEnabled = useSetting( 'typography.dropCap' ); + const [ isDropCapFeatureEnabled ] = useSettings( 'typography.dropCap' ); const blockProps = useBlockProps( { ref: useOnEnter( { clientId, content } ), className: classnames( { diff --git a/packages/block-library/src/post-featured-image/dimension-controls.js b/packages/block-library/src/post-featured-image/dimension-controls.js index 5e1204922880c..03a2d2849dae3 100644 --- a/packages/block-library/src/post-featured-image/dimension-controls.js +++ b/packages/block-library/src/post-featured-image/dimension-controls.js @@ -10,7 +10,7 @@ import { __experimentalUseCustomUnits as useCustomUnits, __experimentalToolsPanelItem as ToolsPanelItem, } from '@wordpress/components'; -import { InspectorControls, useSetting } from '@wordpress/block-editor'; +import { InspectorControls, useSettings } from '@wordpress/block-editor'; const SCALE_OPTIONS = ( <> @@ -53,9 +53,9 @@ const DimensionControls = ( { setAttributes, imageSizeOptions = [], } ) => { - const defaultUnits = [ 'px', '%', 'vw', 'em', 'rem' ]; + const [ availableUnits ] = useSettings( 'spacing.units' ); const units = useCustomUnits( { - availableUnits: useSetting( 'spacing.units' ) || defaultUnits, + availableUnits: availableUnits || [ 'px', '%', 'vw', 'em', 'rem' ], } ); const onDimensionChange = ( dimension, nextValue ) => { const parsedValue = parseFloat( nextValue ); diff --git a/packages/block-library/src/post-terms/edit.js b/packages/block-library/src/post-terms/edit.js index 49e3a4ce801f4..188a8d22f2f8e 100644 --- a/packages/block-library/src/post-terms/edit.js +++ b/packages/block-library/src/post-terms/edit.js @@ -93,7 +93,7 @@ export default function PostTermsEdit( {
{ isLoading && hasPost && } - { ! isLoading && hasPostTerms && ( isSelected || prefix ) && ( + { ! isLoading && ( isSelected || prefix ) && ( next_tag( array( diff --git a/packages/block-library/src/query-pagination-previous/index.php b/packages/block-library/src/query-pagination-previous/index.php index dc61f5d38b282..fc1fee08e8214 100644 --- a/packages/block-library/src/query-pagination-previous/index.php +++ b/packages/block-library/src/query-pagination-previous/index.php @@ -51,7 +51,7 @@ function render_block_core_query_pagination_previous( $attributes, $content, $bl ); } - if ( $enhanced_pagination ) { + if ( $enhanced_pagination && isset( $content ) ) { $p = new WP_HTML_Tag_Processor( $content ); if ( $p->next_tag( array( diff --git a/packages/block-library/src/query/edit/enhanced-pagination-modal.js b/packages/block-library/src/query/edit/enhanced-pagination-modal.js index 04423116ac92e..6009881c7bd86 100644 --- a/packages/block-library/src/query/edit/enhanced-pagination-modal.js +++ b/packages/block-library/src/query/edit/enhanced-pagination-modal.js @@ -12,11 +12,7 @@ import { useState, useEffect } from '@wordpress/element'; /** * Internal dependencies */ -import { useContainsThirdPartyBlocks } from '../utils'; - -const disableEnhancedPaginationDescription = __( - 'Plugin blocks are not supported yet. For the enhanced pagination to work, remove the plugin block, then re-enable "Enhanced pagination" in the Query Block settings.' -); +import { useUnsupportedBlocks } from '../utils'; const modalDescriptionId = 'wp-block-query-enhanced-pagination-modal__description'; @@ -27,35 +23,55 @@ export default function EnhancedPaginationModal( { setAttributes, } ) { const [ isOpen, setOpen ] = useState( false ); - - const containsThirdPartyBlocks = useContainsThirdPartyBlocks( clientId ); + const { hasBlocksFromPlugins, hasPostContentBlock, hasUnsupportedBlocks } = + useUnsupportedBlocks( clientId ); useEffect( () => { - setOpen( containsThirdPartyBlocks && enhancedPagination ); - }, [ containsThirdPartyBlocks, enhancedPagination, setOpen ] ); + if ( enhancedPagination && hasUnsupportedBlocks ) { + setAttributes( { enhancedPagination: false } ); + setOpen( true ); + } + }, [ enhancedPagination, hasUnsupportedBlocks, setAttributes ] ); + + const closeModal = () => { + setOpen( false ); + }; + + let notice = __( + 'If you still want to prevent full page reloads, remove that block, then disable "Force page reload" again in the Query Block settings.' + ); + if ( hasBlocksFromPlugins ) { + notice = + __( + 'Currently, avoiding full page reloads is not possible when blocks from plugins are present inside the Query block.' + ) + + ' ' + + notice; + } else if ( hasPostContentBlock ) { + notice = + __( + 'Currently, avoiding full page reloads is not possible when a Content block is present inside the Query block.' + ) + + ' ' + + notice; + } return ( isOpen && ( - - { disableEnhancedPaginationDescription } - - diff --git a/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js b/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js index 042c9f1e75930..de889c0715c07 100644 --- a/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/enhanced-pagination-control.js @@ -1,49 +1,45 @@ /** * WordPress dependencies */ -import { ToggleControl, Notice } from '@wordpress/components'; +import { ToggleControl } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import { useContainsThirdPartyBlocks } from '../../utils'; +import { useUnsupportedBlocks } from '../../utils'; export default function EnhancedPaginationControl( { enhancedPagination, setAttributes, clientId, } ) { - const enhancedPaginationNotice = __( - "Enhanced pagination doesn't support plugin blocks yet. If you want to enable it, you have to remove all plugin blocks from the Query Loop." - ); + const { hasUnsupportedBlocks } = useUnsupportedBlocks( clientId ); - const containsThirdPartyBlocks = useContainsThirdPartyBlocks( clientId ); + let help = __( 'Browsing between pages requires a full page reload.' ); + if ( enhancedPagination ) { + help = __( + "Browsing between pages won't require a full page reload, unless non-compatible blocks are detected." + ); + } else if ( hasUnsupportedBlocks ) { + help = __( + "Force page reload can't be disabled because there are non-compatible blocks inside the Query block." + ); + } return ( <> { setAttributes( { - enhancedPagination: !! value, + enhancedPagination: ! value, } ); } } /> - { containsThirdPartyBlocks && ( - - { enhancedPaginationNotice } - - ) } ); } diff --git a/packages/block-library/src/query/index.php b/packages/block-library/src/query/index.php index 5e89f21fc3028..201ceed737a12 100644 --- a/packages/block-library/src/query/index.php +++ b/packages/block-library/src/query/index.php @@ -10,14 +10,14 @@ * * @since 6.4.0 * - * @param array $attributes Block attributes. - * @param string $content Block default content. - * @param string $block Block instance. + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block The block instance. * * @return string Returns the modified output of the query block. */ function render_block_core_query( $attributes, $content, $block ) { - if ( $attributes['enhancedPagination'] ) { + if ( $attributes['enhancedPagination'] && isset( $attributes['queryId'] ) ) { $p = new WP_HTML_Tag_Processor( $content ); if ( $p->next_tag() ) { // Add the necessary directives. @@ -67,11 +67,14 @@ class="wp-block-query__enhanced-pagination-animation" if ( ! wp_script_is( $view_asset ) ) { $script_handles = $block->block_type->view_script_handles; // If the script is not needed, and it is still in the `view_script_handles`, remove it. - if ( ! $attributes['enhancedPagination'] && in_array( $view_asset, $script_handles, true ) ) { + if ( + ( ! $attributes['enhancedPagination'] || ! isset( $attributes['queryId'] ) ) + && in_array( $view_asset, $script_handles, true ) + ) { $block->block_type->view_script_handles = array_diff( $script_handles, array( $view_asset ) ); } // If the script is needed, but it was previously removed, add it again. - if ( $attributes['enhancedPagination'] && ! in_array( $view_asset, $script_handles, true ) ) { + if ( $attributes['enhancedPagination'] && isset( $attributes['queryId'] ) && ! in_array( $view_asset, $script_handles, true ) ) { $block->block_type->view_script_handles = array_merge( $script_handles, array( $view_asset ) ); } } @@ -80,11 +83,14 @@ class="wp-block-query__enhanced-pagination-animation" if ( ! wp_style_is( $style_asset ) ) { $style_handles = $block->block_type->style_handles; // If the styles are not needed, and they are still in the `style_handles`, remove them. - if ( ! $attributes['enhancedPagination'] && in_array( $style_asset, $style_handles, true ) ) { + if ( + ( ! $attributes['enhancedPagination'] || ! isset( $attributes['queryId'] ) ) + && in_array( $style_asset, $style_handles, true ) + ) { $block->block_type->style_handles = array_diff( $style_handles, array( $style_asset ) ); } // If the styles are needed, but they were previously removed, add them again. - if ( $attributes['enhancedPagination'] && ! in_array( $style_asset, $style_handles, true ) ) { + if ( $attributes['enhancedPagination'] && isset( $attributes['queryId'] ) && ! in_array( $style_asset, $style_handles, true ) ) { $block->block_type->style_handles = array_merge( $style_handles, array( $style_asset ) ); } } @@ -123,3 +129,86 @@ function register_block_core_query() { ); } add_action( 'init', 'register_block_core_query' ); + +/** + * Traverse the tree of blocks looking for any plugin block (i.e., a block from + * an installed plugin) inside a Query block with the enhanced pagination + * enabled. If at least one is found, the enhanced pagination is effectively + * disabled to prevent any potential incompatibilities. + * + * @since 6.4.0 + * + * @param array $parsed_block The block being rendered. + * @return string Returns the parsed block, unmodified. + */ +function block_core_query_disable_enhanced_pagination( $parsed_block ) { + static $enhanced_query_stack = array(); + static $dirty_enhanced_queries = array(); + static $render_query_callback = null; + + $block_name = $parsed_block['blockName']; + + if ( + 'core/query' === $block_name && + isset( $parsed_block['attrs']['enhancedPagination'] ) && + true === $parsed_block['attrs']['enhancedPagination'] && + isset( $parsed_block['attrs']['queryId'] ) + ) { + $enhanced_query_stack[] = $parsed_block['attrs']['queryId']; + + if ( ! isset( $render_query_callback ) ) { + /** + * Filter that disables the enhanced pagination feature during block + * rendering when a plugin block has been found inside. It does so + * by adding an attribute called `data-wp-navigation-disabled` which + * is later handled by the front-end logic. + * + * @param string $content The block content. + * @param array $block The full block, including name and attributes. + * @return string Returns the modified output of the query block. + */ + $render_query_callback = static function ( $content, $block ) use ( &$enhanced_query_stack, &$dirty_enhanced_queries, &$render_query_callback ) { + $has_enhanced_pagination = + isset( $block['attrs']['enhancedPagination'] ) && + true === $block['attrs']['enhancedPagination'] && + isset( $block['attrs']['queryId'] ); + + if ( ! $has_enhanced_pagination ) { + return $content; + } + + if ( isset( $dirty_enhanced_queries[ $block['attrs']['queryId'] ] ) ) { + $p = new WP_HTML_Tag_Processor( $content ); + if ( $p->next_tag() ) { + $p->set_attribute( 'data-wp-navigation-disabled', 'true' ); + } + $content = $p->get_updated_html(); + $dirty_enhanced_queries[ $block['attrs']['queryId'] ] = null; + } + + array_pop( $enhanced_query_stack ); + + if ( empty( $enhanced_query_stack ) ) { + remove_filter( 'render_block_core/query', $render_query_callback ); + $render_query_callback = null; + } + + return $content; + }; + + add_filter( 'render_block_core/query', $render_query_callback, 10, 2 ); + } + } elseif ( + ! empty( $enhanced_query_stack ) && + isset( $block_name ) && + ( ! str_starts_with( $block_name, 'core/' ) || 'core/post-content' === $block_name ) + ) { + foreach ( $enhanced_query_stack as $query_id ) { + $dirty_enhanced_queries[ $query_id ] = true; + } + } + + return $parsed_block; +} + +add_filter( 'render_block_data', 'block_core_query_disable_enhanced_pagination', 10, 1 ); diff --git a/packages/block-library/src/query/utils.js b/packages/block-library/src/query/utils.js index dd68ee38af916..2ce4acd4a782c 100644 --- a/packages/block-library/src/query/utils.js +++ b/packages/block-library/src/query/utils.js @@ -346,22 +346,43 @@ export const usePatterns = ( clientId, name ) => { }; /** - * Hook that returns whether the Query Loop with the given `clientId` contains - * any third-party block. + * The object returned by useUnsupportedBlocks with info about the type of + * unsupported blocks present inside the Query block. + * + * @typedef {Object} UnsupportedBlocksInfo + * @property {boolean} hasBlocksFromPlugins True if blocks from plugins are present. + * @property {boolean} hasPostContentBlock True if a 'core/post-content' block is present. + * @property {boolean} hasUnsupportedBlocks True if there are any unsupported blocks. + */ + +/** + * Hook that returns an object with information about the unsupported blocks + * present inside a Query Loop with the given `clientId`. The returned object + * contains props that are true when a certain type of unsupported block is + * present. * * @param {string} clientId The block's client ID. - * @return {boolean} True if it contains third-party blocks. + * @return {UnsupportedBlocksInfo} The object containing the information. */ -export const useContainsThirdPartyBlocks = ( clientId ) => { +export const useUnsupportedBlocks = ( clientId ) => { return useSelect( ( select ) => { const { getClientIdsOfDescendants, getBlockName } = select( blockEditorStore ); - - return getClientIdsOfDescendants( clientId ).some( - ( descendantClientId ) => - ! getBlockName( descendantClientId ).startsWith( 'core/' ) + const blocks = {}; + getClientIdsOfDescendants( clientId ).forEach( + ( descendantClientId ) => { + const blockName = getBlockName( descendantClientId ); + if ( ! blockName.startsWith( 'core/' ) ) { + blocks.hasBlocksFromPlugins = true; + } else if ( blockName === 'core/post-content' ) { + blocks.hasPostContentBlock = true; + } + } ); + blocks.hasUnsupportedBlocks = + blocks.hasBlocksFromPlugins || blocks.hasPostContentBlock; + return blocks; }, [ clientId ] ); diff --git a/packages/block-library/src/query/view.js b/packages/block-library/src/query/view.js index 96be4ee513fce..1dac448952b11 100644 --- a/packages/block-library/src/query/view.js +++ b/packages/block-library/src/query/view.js @@ -33,7 +33,14 @@ store( { core: { query: { navigate: async ( { event, ref, context } ) => { - if ( isValidLink( ref ) && isValidEvent( event ) ) { + const isDisabled = ref.closest( '[data-wp-navigation-id]' ) + ?.dataset.wpNavigationDisabled; + + if ( + isValidLink( ref ) && + isValidEvent( event ) && + ! isDisabled + ) { event.preventDefault(); const id = ref.closest( '[data-wp-navigation-id]' ) @@ -70,7 +77,9 @@ store( { } }, prefetch: async ( { ref } ) => { - if ( isValidLink( ref ) ) { + const isDisabled = ref.closest( '[data-wp-navigation-id]' ) + ?.dataset.wpNavigationDisabled; + if ( isValidLink( ref ) && ! isDisabled ) { await prefetch( ref.href ); } }, diff --git a/packages/block-library/src/search/edit.js b/packages/block-library/src/search/edit.js index 616478d8013f7..52f89d344cdf0 100644 --- a/packages/block-library/src/search/edit.js +++ b/packages/block-library/src/search/edit.js @@ -16,7 +16,7 @@ import { getTypographyClassesAndStyles as useTypographyProps, store as blockEditorStore, __experimentalGetElementClassName, - useSetting, + useSettings, } from '@wordpress/block-editor'; import { useDispatch, useSelect } from '@wordpress/data'; import { useEffect, useRef } from '@wordpress/element'; @@ -125,8 +125,10 @@ export default function SearchEdit( { } const colorProps = useColorProps( attributes ); - const fluidTypographySettings = useSetting( 'typography.fluid' ); - const layout = useSetting( 'layout' ); + const [ fluidTypographySettings, layout ] = useSettings( + 'typography.fluid', + 'layout' + ); const typographyProps = useTypographyProps( attributes, { typography: { fluid: fluidTypographySettings, diff --git a/packages/block-library/src/social-link/edit.native.js b/packages/block-library/src/social-link/edit.native.js index 856c6aa704a4e..3ea794a9b8c20 100644 --- a/packages/block-library/src/social-link/edit.native.js +++ b/packages/block-library/src/social-link/edit.native.js @@ -16,7 +16,7 @@ import { ToolbarButton, LinkSettingsNavigation, } from '@wordpress/components'; -import { compose, usePreferredColorSchemeStyle } from '@wordpress/compose'; +import { compose } from '@wordpress/compose'; import { __, sprintf } from '@wordpress/i18n'; import { link, Icon } from '@wordpress/icons'; import { withSelect } from '@wordpress/data'; @@ -30,10 +30,6 @@ const DEFAULT_ACTIVE_ICON_STYLES = { backgroundColor: '#f0f0f0', color: '#444', }; -const DEFAULT_INACTIVE_ICON_STYLES = { - backgroundColor: '#0000003f', - color: '#fff', -}; const ANIMATION_DELAY = 300; const ANIMATION_DURATION = 400; @@ -66,12 +62,6 @@ const SocialLinkEdit = ( { styles[ `wp-social-link-${ service }` ] || styles[ `wp-social-link` ] || DEFAULT_ACTIVE_ICON_STYLES; - const inactiveIcon = - usePreferredColorSchemeStyle( - styles.inactiveIcon, - styles.inactiveIconDark - ) || DEFAULT_INACTIVE_ICON_STYLES; - const animatedValue = useRef( new Animated.Value( 0 ) ).current; const IconComponent = getIconBySite( service )(); @@ -94,23 +84,13 @@ const SocialLinkEdit = ( { }, [ url ] ); const interpolationColors = { - backgroundColor: animatedValue.interpolate( { - inputRange: [ 0, 1 ], - outputRange: [ - inactiveIcon.backgroundColor, - activeIcon.backgroundColor, - ], - } ), - color: animatedValue.interpolate( { + opacity: animatedValue.interpolate( { inputRange: [ 0, 1 ], - outputRange: [ inactiveIcon.color, activeIcon.color ], + outputRange: [ 0.3, 1 ], } ), - stroke: '', }; - const { backgroundColor, color, stroke } = hasUrl - ? activeIcon - : interpolationColors; + const { opacity } = hasUrl ? activeIcon : interpolationColors; function animateColors() { Animated.sequence( [ @@ -200,12 +180,18 @@ const SocialLinkEdit = ( { accessibilityHint={ accessibilityHint } > diff --git a/packages/block-library/src/social-link/editor.native.scss b/packages/block-library/src/social-link/editor.native.scss index 91b69de77de64..fbbc8eb09e6a8 100644 --- a/packages/block-library/src/social-link/editor.native.scss +++ b/packages/block-library/src/social-link/editor.native.scss @@ -13,15 +13,6 @@ justify-content: center; } -.inactiveIcon { - background-color: $light-quaternary; - color: $white; -} - -.inactiveIconDark { - background-color: $dark-quaternary; -} - .container { margin: $block-selected-margin; } diff --git a/packages/block-library/src/social-link/index.php b/packages/block-library/src/social-link/index.php index cda8e125097a5..b84c7338cf31f 100644 --- a/packages/block-library/src/social-link/index.php +++ b/packages/block-library/src/social-link/index.php @@ -62,10 +62,10 @@ function render_block_core_social_link( $attributes, $content, $block ) { $processor = new WP_HTML_Tag_Processor( $link ); $processor->next_tag( 'a' ); if ( $open_in_new_tab ) { - $processor->set_attribute( 'rel', esc_attr( $rel ) . ' noopener nofollow' ); + $processor->set_attribute( 'rel', trim( $rel . ' noopener nofollow' ) ); $processor->set_attribute( 'target', '_blank' ); } elseif ( '' !== $rel ) { - $processor->set_attribute( 'rel', esc_attr( $rel ) ); + $processor->set_attribute( 'rel', trim( $rel ) ); } return $processor->get_updated_html(); } diff --git a/packages/block-library/src/spacer/controls.js b/packages/block-library/src/spacer/controls.js index d999550f16f33..91a1e79be173e 100644 --- a/packages/block-library/src/spacer/controls.js +++ b/packages/block-library/src/spacer/controls.js @@ -4,7 +4,7 @@ import { __ } from '@wordpress/i18n'; import { InspectorControls, - useSetting, + useSettings, __experimentalSpacingSizesControl as SpacingSizesControl, isValueSpacingPreset, } from '@wordpress/block-editor'; @@ -25,22 +25,19 @@ import { MIN_SPACER_SIZE } from './constants'; function DimensionInput( { label, onChange, isResizing, value = '' } ) { const inputId = useInstanceId( UnitControl, 'block-spacer-height-input' ); - const spacingSizes = useSetting( 'spacing.spacingSizes' ); + const [ spacingSizes, spacingUnits ] = useSettings( + 'spacing.spacingSizes', + 'spacing.units' + ); // In most contexts the spacer size cannot meaningfully be set to a // percentage, since this is relative to the parent container. This // unit is disabled from the UI. - const availableUnitSettings = ( - useSetting( 'spacing.units' ) || undefined - )?.filter( ( availableUnit ) => availableUnit !== '%' ); + const availableUnits = spacingUnits + ? spacingUnits.filter( ( unit ) => unit !== '%' ) + : [ 'px', 'em', 'rem', 'vw', 'vh' ]; const units = useCustomUnits( { - availableUnits: availableUnitSettings || [ - 'px', - 'em', - 'rem', - 'vw', - 'vh', - ], + availableUnits, defaultValues: { px: 100, em: 10, rem: 10, vw: 10, vh: 25 }, } ); diff --git a/packages/block-library/src/spacer/controls.native.js b/packages/block-library/src/spacer/controls.native.js index 644359b107275..6aacfae19fa82 100644 --- a/packages/block-library/src/spacer/controls.native.js +++ b/packages/block-library/src/spacer/controls.native.js @@ -8,7 +8,7 @@ import { __experimentalUseCustomUnits as useCustomUnits, } from '@wordpress/components'; import { useCallback } from '@wordpress/element'; -import { useSetting } from '@wordpress/block-editor'; +import { useSettings } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; /** @@ -59,14 +59,9 @@ function Controls( { [ height, width ] ); + const [ availableUnits ] = useSettings( 'spacing.units' ); const units = useCustomUnits( { - availableUnits: useSetting( 'spacing.units' ) || [ - 'px', - 'em', - 'rem', - 'vw', - 'vh', - ], + availableUnits: availableUnits || [ 'px', 'em', 'rem', 'vw', 'vh' ], defaultValues: DEFAULT_VALUES, } ); diff --git a/packages/block-library/src/spacer/edit.js b/packages/block-library/src/spacer/edit.js index 1786c435ebbf2..11133732042d3 100644 --- a/packages/block-library/src/spacer/edit.js +++ b/packages/block-library/src/spacer/edit.js @@ -8,7 +8,7 @@ import classnames from 'classnames'; */ import { useBlockProps, - useSetting, + useSettings, getCustomValueFromPreset, getSpacingPresetCssVar, store as blockEditorStore, @@ -107,7 +107,7 @@ const SpacerEdit = ( { const { layout = {} } = blockStyle; const { selfStretch, flexSize } = layout; - const spacingSizes = useSetting( 'spacing.spacingSizes' ); + const [ spacingSizes ] = useSettings( 'spacing.spacingSizes' ); const [ isResizing, setIsResizing ] = useState( false ); const [ temporaryHeight, setTemporaryHeight ] = useState( null ); diff --git a/packages/block-library/src/spacer/edit.native.js b/packages/block-library/src/spacer/edit.native.js index ca5cfa409939b..614624570a6d9 100644 --- a/packages/block-library/src/spacer/edit.native.js +++ b/packages/block-library/src/spacer/edit.native.js @@ -11,7 +11,7 @@ import { withPreferredColorScheme } from '@wordpress/compose'; import { InspectorControls, isValueSpacingPreset, - useSetting, + useSettings, getCustomValueFromPreset, getPxFromCssUnit, } from '@wordpress/block-editor'; @@ -39,10 +39,11 @@ const Spacer = ( { fontSize: DEFAULT_FONT_SIZE, }; const { height, width } = attributes; - const spacingSizes = [ - { name: 0, slug: '0', size: 0 }, - ...( useSetting( 'spacing.spacingSizes' ) || [] ), - ]; + const spacingSizes = [ { name: 0, slug: '0', size: 0 } ]; + const [ settingsSizes ] = useSettings( 'spacing.spacingSizes' ); + if ( settingsSizes ) { + spacingSizes.push( ...settingsSizes ); + } const { orientation } = context; const defaultStyle = getStylesFromColorScheme( styles.staticSpacer, diff --git a/packages/block-library/src/tag-cloud/edit.js b/packages/block-library/src/tag-cloud/edit.js index 4dbec86fff520..a52c68bc6a739 100644 --- a/packages/block-library/src/tag-cloud/edit.js +++ b/packages/block-library/src/tag-cloud/edit.js @@ -18,7 +18,7 @@ import { __ } from '@wordpress/i18n'; import { InspectorControls, useBlockProps, - useSetting, + useSettings, } from '@wordpress/block-editor'; import ServerSideRender from '@wordpress/server-side-render'; import { store as coreStore } from '@wordpress/core-data'; @@ -49,13 +49,9 @@ function TagCloudEdit( { attributes, setAttributes, taxonomies } ) { largestFontSize, } = attributes; + const [ availableUnits ] = useSettings( 'spacing.units' ); const units = useCustomUnits( { - availableUnits: useSetting( 'spacing.units' ) || [ - '%', - 'px', - 'em', - 'rem', - ], + availableUnits: availableUnits || [ '%', 'px', 'em', 'rem' ], } ); const getTaxonomyOptions = () => { diff --git a/packages/block-library/src/template-part/edit/inner-blocks.js b/packages/block-library/src/template-part/edit/inner-blocks.js index b17428bbdbb40..146877ee0287c 100644 --- a/packages/block-library/src/template-part/edit/inner-blocks.js +++ b/packages/block-library/src/template-part/edit/inner-blocks.js @@ -5,7 +5,7 @@ import { useEntityBlockEditor } from '@wordpress/core-data'; import { InnerBlocks, useInnerBlocksProps, - useSetting, + useSettings, store as blockEditorStore, } from '@wordpress/block-editor'; import { useSelect } from '@wordpress/data'; @@ -21,8 +21,8 @@ export default function TemplatePartInnerBlocks( { const { getSettings } = select( blockEditorStore ); return getSettings()?.supportsLayout; }, [] ); - const defaultLayout = useSetting( 'layout' ) || {}; - const usedLayout = !! layout && layout.inherit ? defaultLayout : layout; + const [ defaultLayout ] = useSettings( 'layout' ); + const usedLayout = layout?.inherit ? defaultLayout || {} : layout; const [ blocks, onInput, onChange ] = useEntityBlockEditor( 'postType', diff --git a/packages/block-library/src/term-description/block.json b/packages/block-library/src/term-description/block.json index beee12eb674b0..fc91a4aff4c48 100644 --- a/packages/block-library/src/term-description/block.json +++ b/packages/block-library/src/term-description/block.json @@ -1,7 +1,6 @@ { "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 3, - "__experimental": "fse", "name": "core/term-description", "title": "Term Description", "category": "theme", diff --git a/packages/blocks/src/api/factory.js b/packages/blocks/src/api/factory.js index 7112ae25ccdde..53333ef688085 100644 --- a/packages/blocks/src/api/factory.js +++ b/packages/blocks/src/api/factory.js @@ -580,11 +580,19 @@ export function switchToBlockType( blocks, name ) { * @return {Object} block. */ export const getBlockFromExample = ( name, example ) => { - return createBlock( - name, - example.attributes, - ( example.innerBlocks ?? [] ).map( ( innerBlock ) => - getBlockFromExample( innerBlock.name, innerBlock ) - ) - ); + try { + return createBlock( + name, + example.attributes, + ( example.innerBlocks ?? [] ).map( ( innerBlock ) => + getBlockFromExample( innerBlock.name, innerBlock ) + ) + ); + } catch { + return createBlock( 'core/missing', { + originalName: name, + originalContent: '', + originalUndelimitedContent: '', + } ); + } }; diff --git a/packages/blocks/src/api/test/factory.js b/packages/blocks/src/api/test/factory.js index 84d7161659928..22d069205113b 100644 --- a/packages/blocks/src/api/test/factory.js +++ b/packages/blocks/src/api/test/factory.js @@ -17,6 +17,7 @@ import { findTransform, isWildcardBlockTransform, isContainerGroupBlock, + getBlockFromExample, } from '../factory'; import { getBlockType, @@ -2276,4 +2277,33 @@ describe( 'block factory', () => { expect( isContainerGroupBlock( 'core/group' ) ).toBe( false ); } ); } ); + + describe( 'getBlockFromExample', () => { + it( 'should replace unregistered block with core/missing block', () => { + registerBlockType( 'core/missing', { + title: 'Unsupported', + } ); + registerBlockType( 'core/paragraph', { + title: 'Paragraph', + } ); + registerBlockType( 'core/group', { + title: 'A block that groups other blocks.', + } ); + const example = { + innerBlocks: [ + { name: 'core/paragraph' }, + { name: 'core/image' }, + ], + }; + expect( + getBlockFromExample( 'core/group', example ) + ).toMatchObject( { + name: 'core/group', + innerBlocks: [ + { name: 'core/paragraph' }, + { name: 'core/missing' }, + ], + } ); + } ); + } ); } ); diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 3b467cf083e3f..59a535447bf0d 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,18 @@ ## Unreleased +### Enhancements + +- `InputControl`/`SelectControl`: update `height`/`min-height` to `32px` instead of `30px` to align with modern sizing scale ([#55490](https://github.com/WordPress/gutenberg/pull/55490)). + +### Bug Fix + +- `Autocomplete`: Add `aria-live` announcements for Mac and IOS Voiceover to fix lack of support for `aria-owns` ([#54902](https://github.com/WordPress/gutenberg/pull/54902)). + +### Internal + +- Introduce experimental new version of `DropdownMenu` based on `ariakit` ([#54939](https://github.com/WordPress/gutenberg/pull/54939)) + ## 25.10.0 (2023-10-18) ### Enhancements @@ -18,9 +30,11 @@ - Render a "mouse event trap" when using a `ColorPicker` inside a `Popover` to prevent issues when rendering on top of `iframes` ([#55149](https://github.com/WordPress/gutenberg/pull/55149)). - `Modal`: fix closing when contained iframe is focused ([#51602](https://github.com/WordPress/gutenberg/pull/51602)). +- `Autocomplete`: Fix disappearing results issue when using multiple triggers inline ([#55301](https://github.com/WordPress/gutenberg/pull/55301)) ### Internal +- Update `@ariakit/react` to version `0.3.5` ([#55365](https://github.com/WordPress/gutenberg/pull/55365)) - `ConfirmDialog`: Migrate to TypeScript. ([#54954](https://github.com/WordPress/gutenberg/pull/54954)). ### New Features diff --git a/packages/components/package.json b/packages/components/package.json index 969bcc6300873..a8346b054a6e0 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -30,7 +30,8 @@ ], "types": "build-types", "dependencies": { - "@ariakit/react": "^0.3.3", + "@ariakit/react": "^0.3.5", + "@ariakit/test": "^0.3.0", "@babel/runtime": "^7.16.0", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.7.1", diff --git a/packages/components/src/autocomplete/index.tsx b/packages/components/src/autocomplete/index.tsx index 7825526fe34a5..b76e8548c08f2 100644 --- a/packages/components/src/autocomplete/index.tsx +++ b/packages/components/src/autocomplete/index.tsx @@ -22,6 +22,8 @@ import { isCollapsed, getTextContent, } from '@wordpress/rich-text'; +import { speak } from '@wordpress/a11y'; +import { isAppleOS } from '@wordpress/keycodes'; /** * Internal dependencies @@ -39,6 +41,35 @@ import type { WPCompleter, } from './types'; +const getNodeText = ( node: React.ReactNode ): string => { + if ( node === null ) { + return ''; + } + + switch ( typeof node ) { + case 'string': + case 'number': + return node.toString(); + break; + case 'boolean': + return ''; + break; + case 'object': { + if ( node instanceof Array ) { + return node.map( getNodeText ).join( '' ); + } + if ( 'props' in node ) { + return getNodeText( node.props.children ); + } + break; + } + default: + return ''; + } + + return ''; +}; + const EMPTY_FILTERED_OPTIONS: KeyedOption[] = []; export function useAutocomplete( { @@ -163,20 +194,35 @@ export function useAutocomplete( { ) { return; } + switch ( event.key ) { - case 'ArrowUp': - setSelectedIndex( + case 'ArrowUp': { + const newIndex = ( selectedIndex === 0 ? filteredOptions.length - : selectedIndex ) - 1 - ); + : selectedIndex ) - 1; + setSelectedIndex( newIndex ); + // See the related PR as to why this is necessary: https://github.com/WordPress/gutenberg/pull/54902. + if ( isAppleOS() ) { + speak( + getNodeText( filteredOptions[ newIndex ].label ), + 'assertive' + ); + } break; + } - case 'ArrowDown': - setSelectedIndex( - ( selectedIndex + 1 ) % filteredOptions.length - ); + case 'ArrowDown': { + const newIndex = ( selectedIndex + 1 ) % filteredOptions.length; + setSelectedIndex( newIndex ); + if ( isAppleOS() ) { + speak( + getNodeText( filteredOptions[ newIndex ].label ), + 'assertive' + ); + } break; + } case 'Escape': setAutocompleter( null ); @@ -218,82 +264,95 @@ export function useAutocomplete( { return; } - const completer = completers?.find( - ( { triggerPrefix, allowContext } ) => { - const index = textContent.lastIndexOf( triggerPrefix ); - - if ( index === -1 ) { - return false; - } - - const textWithoutTrigger = textContent.slice( - index + triggerPrefix.length + // Find the completer with the highest triggerPrefix index in the + // textContent. + const completer = completers.reduce< WPCompleter | null >( + ( lastTrigger, currentCompleter ) => { + const triggerIndex = textContent.lastIndexOf( + currentCompleter.triggerPrefix ); + const lastTriggerIndex = + lastTrigger !== null + ? textContent.lastIndexOf( lastTrigger.triggerPrefix ) + : -1; + + return triggerIndex > lastTriggerIndex + ? currentCompleter + : lastTrigger; + }, + null + ); - const tooDistantFromTrigger = textWithoutTrigger.length > 50; // 50 chars seems to be a good limit. - // This is a final barrier to prevent the effect from completing with - // an extremely long string, which causes the editor to slow-down - // significantly. This could happen, for example, if `matchingWhileBackspacing` - // is true and one of the "words" end up being too long. If that's the case, - // it will be caught by this guard. - if ( tooDistantFromTrigger ) return false; - - const mismatch = filteredOptions.length === 0; - const wordsFromTrigger = textWithoutTrigger.split( /\s/ ); - // We need to allow the effect to run when not backspacing and if there - // was a mismatch. i.e when typing a trigger + the match string or when - // clicking in an existing trigger word on the page. We do that if we - // detect that we have one word from trigger in the current textual context. - // - // Ex.: "Some text @a" <-- "@a" will be detected as the trigger word and - // allow the effect to run. It will run until there's a mismatch. - const hasOneTriggerWord = wordsFromTrigger.length === 1; - // This is used to allow the effect to run when backspacing and if - // "touching" a word that "belongs" to a trigger. We consider a "trigger - // word" any word up to the limit of 3 from the trigger character. - // Anything beyond that is ignored if there's a mismatch. This allows - // us to "escape" a mismatch when backspacing, but still imposing some - // sane limits. - // - // Ex: "Some text @marcelo sekkkk" <--- "kkkk" caused a mismatch, but - // if the user presses backspace here, it will show the completion popup again. - const matchingWhileBackspacing = - backspacing.current && - textWithoutTrigger.split( /\s/ ).length <= 3; - - if ( - mismatch && - ! ( matchingWhileBackspacing || hasOneTriggerWord ) - ) { - return false; - } - - const textAfterSelection = getTextContent( - slice( record, undefined, getTextContent( record ).length ) - ); + if ( ! completer ) { + if ( autocompleter ) reset(); + return; + } - if ( - allowContext && - ! allowContext( - textContent.slice( 0, index ), - textAfterSelection - ) - ) { - return false; - } + const { allowContext, triggerPrefix } = completer; + const triggerIndex = textContent.lastIndexOf( triggerPrefix ); + const textWithoutTrigger = textContent.slice( + triggerIndex + triggerPrefix.length + ); - if ( - /^\s/.test( textWithoutTrigger ) || - /\s\s+$/.test( textWithoutTrigger ) - ) { - return false; - } + const tooDistantFromTrigger = textWithoutTrigger.length > 50; // 50 chars seems to be a good limit. + // This is a final barrier to prevent the effect from completing with + // an extremely long string, which causes the editor to slow-down + // significantly. This could happen, for example, if `matchingWhileBackspacing` + // is true and one of the "words" end up being too long. If that's the case, + // it will be caught by this guard. + if ( tooDistantFromTrigger ) return; + + const mismatch = filteredOptions.length === 0; + const wordsFromTrigger = textWithoutTrigger.split( /\s/ ); + // We need to allow the effect to run when not backspacing and if there + // was a mismatch. i.e when typing a trigger + the match string or when + // clicking in an existing trigger word on the page. We do that if we + // detect that we have one word from trigger in the current textual context. + // + // Ex.: "Some text @a" <-- "@a" will be detected as the trigger word and + // allow the effect to run. It will run until there's a mismatch. + const hasOneTriggerWord = wordsFromTrigger.length === 1; + // This is used to allow the effect to run when backspacing and if + // "touching" a word that "belongs" to a trigger. We consider a "trigger + // word" any word up to the limit of 3 from the trigger character. + // Anything beyond that is ignored if there's a mismatch. This allows + // us to "escape" a mismatch when backspacing, but still imposing some + // sane limits. + // + // Ex: "Some text @marcelo sekkkk" <--- "kkkk" caused a mismatch, but + // if the user presses backspace here, it will show the completion popup again. + const matchingWhileBackspacing = + backspacing.current && wordsFromTrigger.length <= 3; + + if ( mismatch && ! ( matchingWhileBackspacing || hasOneTriggerWord ) ) { + if ( autocompleter ) reset(); + return; + } - return /[\u0000-\uFFFF]*$/.test( textWithoutTrigger ); - } + const textAfterSelection = getTextContent( + slice( record, undefined, getTextContent( record ).length ) ); - if ( ! completer ) { + if ( + allowContext && + ! allowContext( + textContent.slice( 0, triggerIndex ), + textAfterSelection + ) + ) { + if ( autocompleter ) reset(); + return; + } + + if ( + /^\s/.test( textWithoutTrigger ) || + /\s\s+$/.test( textWithoutTrigger ) + ) { + if ( autocompleter ) reset(); + return; + } + + if ( ! /[\u0000-\uFFFF]*$/.test( textWithoutTrigger ) ) { if ( autocompleter ) reset(); return; } diff --git a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap index 8edf2a4875e52..3934085f03528 100644 --- a/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap +++ b/packages/components/src/dimension-control/test/__snapshots__/index.test.js.snap @@ -119,8 +119,8 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = ` white-space: nowrap; text-overflow: ellipsis; font-size: 16px; - height: 30px; - min-height: 30px; + height: 32px; + min-height: 32px; padding-top: 0; padding-bottom: 0; padding-left: 8px; @@ -390,8 +390,8 @@ exports[`DimensionControl rendering renders with defaults 1`] = ` white-space: nowrap; text-overflow: ellipsis; font-size: 16px; - height: 30px; - min-height: 30px; + height: 32px; + min-height: 32px; padding-top: 0; padding-bottom: 0; padding-left: 8px; @@ -671,8 +671,8 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`] white-space: nowrap; text-overflow: ellipsis; font-size: 16px; - height: 30px; - min-height: 30px; + height: 32px; + min-height: 32px; padding-top: 0; padding-bottom: 0; padding-left: 8px; @@ -964,8 +964,8 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`] white-space: nowrap; text-overflow: ellipsis; font-size: 16px; - height: 30px; - min-height: 30px; + height: 32px; + min-height: 32px; padding-top: 0; padding-bottom: 0; padding-left: 8px; diff --git a/packages/components/src/dropdown-menu-v2-ariakit/README.md b/packages/components/src/dropdown-menu-v2-ariakit/README.md new file mode 100644 index 0000000000000..89fccb54e7d01 --- /dev/null +++ b/packages/components/src/dropdown-menu-v2-ariakit/README.md @@ -0,0 +1,324 @@ +# `DropdownMenu` (v2) + +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ +`DropdownMenu` displays a menu to the user (such as a set of actions or functions) triggered by a button. + + +## Design guidelines + +### Usage + +#### When to use a DropdownMenu + +Use a DropdownMenu when you want users to: + +- Choose an action or change a setting from a list, AND +- Only see the available choices contextually. + +`DropdownMenu` is a React component to render an expandable menu of buttons. It is similar in purpose to a `