diff --git a/.eslintrc.js b/.eslintrc.js index dfe779b4683523..d0c22090b93e87 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -156,6 +156,7 @@ module.exports = { 'plugin:eslint-comments/recommended', 'plugin:storybook/recommended', ], + plugins: [ 'react-compiler' ], globals: { wp: 'off', globalThis: 'readonly', @@ -222,6 +223,15 @@ module.exports = { definedTags: [ 'jest-environment' ], }, ], + 'react-compiler/react-compiler': [ + 'error', + { + environment: { + enableTreatRefLikeIdentifiersAsRefs: true, + validateRefAccessDuringRender: false, + }, + }, + ], }, overrides: [ { @@ -236,6 +246,7 @@ module.exports = { 'import/no-unresolved': 'off', 'import/named': 'off', '@wordpress/data-no-store-string-literals': 'off', + 'react-compiler/react-compiler': 'off', }, }, { @@ -551,6 +562,7 @@ module.exports = { { files: [ 'packages/interactivity*/src/**' ], rules: { + 'react-compiler/react-compiler': 'off', 'react/react-in-jsx-scope': 'error', }, }, diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index 65bb55e3f63201..43a71809b5bbe7 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -28,7 +28,7 @@ jobs: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Java - uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # v4.4.0 + uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0 with: distribution: 'corretto' java-version: '17' @@ -47,7 +47,7 @@ jobs: run: npm run native test:e2e:setup - name: Gradle cache - uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0 + uses: gradle/actions/setup-gradle@473878a77f1b98e2b5ac4af93489d1656a80a5ed # v4.2.0 # AVD cache disabled as it caused emulator termination to hang indefinitely. # https://github.com/ReactiveCircus/android-emulator-runner/issues/385 diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index 8851c7c12c4a4a..d28ee65c719e43 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -27,7 +27,7 @@ jobs: with: show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: ruby/setup-ruby@7bae1d00b5db9166f4f0fc47985a3a5702cb58f0 # v1.197.0 + - uses: ruby/setup-ruby@a2bbe5b1b236842c1cb7dd11e8e3b51e0a616acc # v1.202.0 with: # `.ruby-version` file location working-directory: packages/react-native-editor/ios diff --git a/backport-changelog/6.8/7265.md b/backport-changelog/6.8/7265.md new file mode 100644 index 00000000000000..44ba36053aa0d9 --- /dev/null +++ b/backport-changelog/6.8/7265.md @@ -0,0 +1,4 @@ +https://github.com/WordPress/wordpress-develop/pull/7265 + +* https://github.com/WordPress/gutenberg/pull/66850 +* https://github.com/WordPress/gutenberg/pull/66947 diff --git a/backport-changelog/6.8/7784.md b/backport-changelog/6.8/7784.md new file mode 100644 index 00000000000000..b18dca88112a71 --- /dev/null +++ b/backport-changelog/6.8/7784.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7784 + +* https://github.com/WordPress/gutenberg/pull/66948 diff --git a/changelog.txt b/changelog.txt index 0dc99f5e205e32..d9236e513469af 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,315 @@ == Changelog == += 19.6.4 = + +- PostTaxonomiesFlatTermSelector: abstract wrapper component (#66625) + + += 19.6.3 = + +- Revert "Set image width to fit-content to solve aspect ratio problems in Firefox. ([#66217](https://github.com/WordPress/gutenberg/pull/66804)) + + += 19.7.0-rc.2 = + + +- Comments controller: fix issue where comments are allowed when closed (https://github.com/WordPress/gutenberg/pull/66976) + + += 19.6.2 = + +- Comments controller: fix issue where comments are allowed when closed [#66976](https://github.com/WordPress/gutenberg/pull/66976) + + += 19.7.0-rc.1 = + + +## Changelog + +### Enhancements + +- Add "show template" to preview dropdown. ([66514](https://github.com/WordPress/gutenberg/pull/66514)) +- Iframe: Always enable for block themes, in core too. ([66800](https://github.com/WordPress/gutenberg/pull/66800)) +- Media Utils: Add experimental `sideloadMedia`. ([66378](https://github.com/WordPress/gutenberg/pull/66378)) +- Post fields: Clean up. ([66941](https://github.com/WordPress/gutenberg/pull/66941)) +- Post fields: Extract `title` from `edit-site` to `fields` package. ([66940](https://github.com/WordPress/gutenberg/pull/66940)) +- Post fields: Move `comment_status` from edit-site to fields package. ([66934](https://github.com/WordPress/gutenberg/pull/66934)) +- Post fields: Move `date` fields from `edit-site` to `fields` package. ([66938](https://github.com/WordPress/gutenberg/pull/66938)) +- Post fields: Move `status` from `edit-site` to `fields`. ([66937](https://github.com/WordPress/gutenberg/pull/66937)) +- Relocate “View” external link to end of editor header controls. ([66785](https://github.com/WordPress/gutenberg/pull/66785)) + +#### Block Library +- Added toggle control to set any image as feature image if no feature image is set for post. ([65896](https://github.com/WordPress/gutenberg/pull/65896)) +- Improve cover z-index solution. ([66249](https://github.com/WordPress/gutenberg/pull/66249)) +- Post Content: Add border and spacing support. ([66366](https://github.com/WordPress/gutenberg/pull/66366)) +- Query Loop: Use templateSlug and postType for more context. ([65820](https://github.com/WordPress/gutenberg/pull/65820)) +- Update text case of "Starter Content". ([66954](https://github.com/WordPress/gutenberg/pull/66954)) +- [Details Block]: Adds anchor support in details block. ([66734](https://github.com/WordPress/gutenberg/pull/66734)) + +#### Components +- Guide: Use small size button for page controls. ([66607](https://github.com/WordPress/gutenberg/pull/66607)) +- MenuItem: Add 40px size prop on Button. ([66596](https://github.com/WordPress/gutenberg/pull/66596)) +- Notice: Add appropriate size props to Buttons. ([66593](https://github.com/WordPress/gutenberg/pull/66593)) +- PaletteEdit: Add appropriate size props to Buttons. ([66590](https://github.com/WordPress/gutenberg/pull/66590)) +- Popover: Add small size prop to close button. ([66587](https://github.com/WordPress/gutenberg/pull/66587)) + +#### Global Styles +- Global styles revisions: Move focus and active state to list item. ([66780](https://github.com/WordPress/gutenberg/pull/66780)) +- Site editor: Integrate global styles controls and style book preview into the styles panel. ([65619](https://github.com/WordPress/gutenberg/pull/65619)) + +#### DataViews +- DataViews Fields API: Default getValueFromId supports nested objects. ([66890](https://github.com/WordPress/gutenberg/pull/66890)) + +#### Block Editor +- Inserter: Add 'Starter Content' category to the inserter. ([66819](https://github.com/WordPress/gutenberg/pull/66819)) + +#### Zoom Out +- Enable zoom out mode for non-iframe editor. ([66789](https://github.com/WordPress/gutenberg/pull/66789)) + +#### Themes +- Theme JSON Resolver: Remove theme json merge in resolve_theme_file_uris. ([66662](https://github.com/WordPress/gutenberg/pull/66662)) + +#### Edit Mode +- Image block: Add support for "more" dropdown for additional tools in Write mode. ([66605](https://github.com/WordPress/gutenberg/pull/66605)) + +#### Style Book +- Add a landing section to stylebook tabs. ([66545](https://github.com/WordPress/gutenberg/pull/66545)) + +#### Media +- Media Library: Expose filters dropdown for individual images, such as with the Image block. ([65965](https://github.com/WordPress/gutenberg/pull/65965)) + + +### Bug Fixes + +- Block toolbar: Restrict visible child calculation to known blocks. ([66702](https://github.com/WordPress/gutenberg/pull/66702)) +- ComplementaryArea: Fix button position. ([66677](https://github.com/WordPress/gutenberg/pull/66677)) +- Fix Paragraph appender layout shift (building on 66061). ([66779](https://github.com/WordPress/gutenberg/pull/66779)) +- Fix: Set the `fit-content` width for images that are not `.svg`. ([66643](https://github.com/WordPress/gutenberg/pull/66643)) +- Preference modal: Avoid fetching all reusable blocks when the site editor loads. ([66621](https://github.com/WordPress/gutenberg/pull/66621)) +- Revert "Set image width to `fit-content` to solve aspect ratio problems in Firefox. (#66217)". ([66804](https://github.com/WordPress/gutenberg/pull/66804)) +- Safari: Fix site editor template error. ([66647](https://github.com/WordPress/gutenberg/pull/66647)) +- Safari: Prevent focus capturing caused by flex display. ([66402](https://github.com/WordPress/gutenberg/pull/66402)) +- Select Mode: Hide tool selector in the post editor and force design mode. ([66784](https://github.com/WordPress/gutenberg/pull/66784)) +- Shadow panel: Make the delete modal text translatable. ([66712](https://github.com/WordPress/gutenberg/pull/66712)) +- Site Editor: Fix template for page-on-front option. ([66739](https://github.com/WordPress/gutenberg/pull/66739)) +- WP Scripts: Make watch mode more resilient for developer errors. ([66752](https://github.com/WordPress/gutenberg/pull/66752)) +- getDefaultTemplateId: Ensure entity configuration is loaded. ([66650](https://github.com/WordPress/gutenberg/pull/66650)) + +#### Block Library +- Cover: Fix media library image selection. ([66782](https://github.com/WordPress/gutenberg/pull/66782)) +- Cover: Show DropZone only when dragging withing the block. ([66912](https://github.com/WordPress/gutenberg/pull/66912)) +- Media & Text: Set `.wp-block-media-text__media a` display to block. ([66915](https://github.com/WordPress/gutenberg/pull/66915)) +- Prevent duplicate post format taxonomy queries. ([66627](https://github.com/WordPress/gutenberg/pull/66627)) +- Query Loop: Check for postTypeFromContext before using it. ([66655](https://github.com/WordPress/gutenberg/pull/66655)) +- Query Loop: Remove postTypeFromContext. ([66681](https://github.com/WordPress/gutenberg/pull/66681)) + +#### Block Editor +- Appender: Fix initial position. ([66711](https://github.com/WordPress/gutenberg/pull/66711)) +- Appender: Fix outside canvas styles. ([66630](https://github.com/WordPress/gutenberg/pull/66630)) +- Block Inspector: Restore bottom margin for RadioControl. ([66688](https://github.com/WordPress/gutenberg/pull/66688)) +- Iframed editor: Fix relative wp-content URLs. ([66751](https://github.com/WordPress/gutenberg/pull/66751)) + +#### Global Styles +- Section Styles: Fix insecure properties removal for inner block types and elements. ([66896](https://github.com/WordPress/gutenberg/pull/66896)) +- Style book: Reduce margin selector specificity so that it doesn't override global block styles. ([66895](https://github.com/WordPress/gutenberg/pull/66895)) +- Theme JSON: Replace top-level background style objects on merge. ([66656](https://github.com/WordPress/gutenberg/pull/66656)) + +#### Components +- FormTokenField: Fix token styles. ([66640](https://github.com/WordPress/gutenberg/pull/66640)) +- Storybook: Fix DataViews action modals. ([66727](https://github.com/WordPress/gutenberg/pull/66727)) +- ToggleGroupControl: Fix active background for `zero` value. ([66855](https://github.com/WordPress/gutenberg/pull/66855)) + +#### Post Editor +- Disable device preview button in pattern/template part/navitation editor. ([65970](https://github.com/WordPress/gutenberg/pull/65970)) +- PostTaxonomiesFlatTermSelector: Abstract wrapper component. ([66625](https://github.com/WordPress/gutenberg/pull/66625)) +- VisualEditor: Always output has-global-padding classname when in post only mode. ([66626](https://github.com/WordPress/gutenberg/pull/66626)) + +#### DataViews +- Fix TypeError when duplicating uncategorized theme patterns. ([66889](https://github.com/WordPress/gutenberg/pull/66889)) +- Tweak primary field in patterns grid layout. ([66733](https://github.com/WordPress/gutenberg/pull/66733)) + +#### Meta Boxes +- Fix: Show Meta Boxes at the bottom of the screen regardless of the current rendering mode. ([66508](https://github.com/WordPress/gutenberg/pull/66508)) +- Hide metaboxes in Zoom Out. ([66886](https://github.com/WordPress/gutenberg/pull/66886)) + +#### Site Editor +- DataViews: Fix 'aria-label' for pattern preview element. ([66601](https://github.com/WordPress/gutenberg/pull/66601)) +- Site Hub: Fixed navigation redirect on mobile devices for classic themes. ([66867](https://github.com/WordPress/gutenberg/pull/66867)) + +#### Media +- Add `x-wav` mime type for wav files in Firefox. ([66850](https://github.com/WordPress/gutenberg/pull/66850)) +- Ensure HEIC files selectable from “Upload” button. ([66292](https://github.com/WordPress/gutenberg/pull/66292)) + +#### Patterns +- Fix uncategorized pattern browsing when pattern has no categories. ([66945](https://github.com/WordPress/gutenberg/pull/66945)) + +#### Interactivity API +- Fix property modification from inherited context two or more levels above. ([66872](https://github.com/WordPress/gutenberg/pull/66872)) + +#### Block API +- Process Block Type: Copy deprecation to a new object instead of mutating when stabilizing supports. ([66849](https://github.com/WordPress/gutenberg/pull/66849)) + +#### Design Tools +- Block Gap: Fix block spacing control for axial gap supported blocks. ([66783](https://github.com/WordPress/gutenberg/pull/66783)) + +#### Document Settings +- Editor: Restore the 'PluginPostStatusInfo' slot position. ([66665](https://github.com/WordPress/gutenberg/pull/66665)) + +#### Templates API +- Fix flash when clicking template name in the editor when a plugin registered template matches a default WP theme template. ([66359](https://github.com/WordPress/gutenberg/pull/66359)) + +#### Block bindings +- Fix unset array key warning in block-bindings.php. ([66337](https://github.com/WordPress/gutenberg/pull/66337)) + + +### Accessibility + +- Fix : Snackbar Notice Inconsistency. ([66405](https://github.com/WordPress/gutenberg/pull/66405)) +- Image: Add `aria-haspopup` prop write mode `more` tools menu items. ([66815](https://github.com/WordPress/gutenberg/pull/66815)) +- Site Icon Focus fix. ([66952](https://github.com/WordPress/gutenberg/pull/66952)) + +#### Components +- Popover: Fix missing label of the headerTitle Close button. ([66813](https://github.com/WordPress/gutenberg/pull/66813)) + +#### Post Editor +- Fix inconsistent sidebars close buttons sizes. ([66756](https://github.com/WordPress/gutenberg/pull/66756)) + +#### Block Library +- Remove unnecessary tooltip from Video block Text tracks button. ([66716](https://github.com/WordPress/gutenberg/pull/66716)) + +#### Block Editor +- Speak 'Block moved up/down' after using keyboard actions to move up/down. ([64966](https://github.com/WordPress/gutenberg/pull/64966)) + +#### Patterns +- Block Patterns List: Fix visual title and tooltip inconsistencies. ([64815](https://github.com/WordPress/gutenberg/pull/64815)) + + +### Performance + +- Inline Commenting: Avoid querying comments on editor load. ([66670](https://github.com/WordPress/gutenberg/pull/66670)) +- Patterns: Receive intermediate responses while unbound request is resolving. ([66713](https://github.com/WordPress/gutenberg/pull/66713)) +- Perf metrics: Update select and other metrics to use non-empty paragraphs. ([66762](https://github.com/WordPress/gutenberg/pull/66762)) +- Site Editor: Preload settings requests. ([66488](https://github.com/WordPress/gutenberg/pull/66488)) +- Site Editor: Speed up load by preloading home and front-page templates. ([66579](https://github.com/WordPress/gutenberg/pull/66579)) +- Site editor: Preload post if needed. ([66631](https://github.com/WordPress/gutenberg/pull/66631)) + +#### Global Styles +- Preload user global styles based on user caps. ([66541](https://github.com/WordPress/gutenberg/pull/66541)) + + +### Experiments + +- Add `isVisible` option to fields within DataForm. ([65826](https://github.com/WordPress/gutenberg/pull/65826)) +- DataViews: Implement `isItemClickable` and `onClickItem` props. ([66365](https://github.com/WordPress/gutenberg/pull/66365)) + +#### DataViews +- Quick Edit - Slug Field: Improve slug preview. ([66559](https://github.com/WordPress/gutenberg/pull/66559)) +- QuickEdit: Add password field data to the pages quick edit. ([66567](https://github.com/WordPress/gutenberg/pull/66567)) + + +### Documentation + +- Add 6.6.2 to Version in WordPress. ([66870](https://github.com/WordPress/gutenberg/pull/66870)) +- Add missing properties for DataViews/DataForm components. ([66749](https://github.com/WordPress/gutenberg/pull/66749)) +- Add section about the Fields API. ([66761](https://github.com/WordPress/gutenberg/pull/66761)) +- Block Bindings: Documentation API reference. ([66251](https://github.com/WordPress/gutenberg/pull/66251)) +- Docs: Include a note about supported licenses in WordPress packages. ([66562](https://github.com/WordPress/gutenberg/pull/66562)) +- Document `filterSortAndPaginate` & `isItemValid` utilities. ([66738](https://github.com/WordPress/gutenberg/pull/66738)) +- Feat: Storybook: Improve component organisation - Navigation Category - Issue #66275. ([66658](https://github.com/WordPress/gutenberg/pull/66658)) +- Feat: Storybook: Improve component organisation - Overlays Category - Issue #66275. ([66657](https://github.com/WordPress/gutenberg/pull/66657)) +- Feat: Storybook: Improve component organisation - Selection & Input Category - Issue #66275. ([66660](https://github.com/WordPress/gutenberg/pull/66660)) +- Feat: Storybook: Improve component organisation - Typography - Issue #66275. ([66633](https://github.com/WordPress/gutenberg/pull/66633)) +- Improve readability of DataViews documentation. ([66766](https://github.com/WordPress/gutenberg/pull/66766)) +- Move documentation for filter operators to proper place. ([66743](https://github.com/WordPress/gutenberg/pull/66743)) +- Reorganize to bootstrap DataForm API section. ([66729](https://github.com/WordPress/gutenberg/pull/66729)) +- Storybook: Improve component organisation - Actions. ([66680](https://github.com/WordPress/gutenberg/pull/66680)) +- Storybook: Log `warning()` when in dev mode. ([66568](https://github.com/WordPress/gutenberg/pull/66568)) +- Update Commands documentation with the existing contexts. ([66860](https://github.com/WordPress/gutenberg/pull/66860)) + + +### Code Quality + +- BlockPatternsList: Use the Async component. ([66744](https://github.com/WordPress/gutenberg/pull/66744)) +- Core Commands: Fix add new post URL assignment. ([66830](https://github.com/WordPress/gutenberg/pull/66830)) +- Inline Commenting: Optimize store selector and misc changes. ([66592](https://github.com/WordPress/gutenberg/pull/66592)) +- Remove unnecessary boolean assignments. ([66857](https://github.com/WordPress/gutenberg/pull/66857)) +- TypeScript: Fix and improve types for private-apis. ([66667](https://github.com/WordPress/gutenberg/pull/66667)) + +#### Block Editor +- Fix 'useSelect' dependencies for the 'RichText' component. ([66964](https://github.com/WordPress/gutenberg/pull/66964)) +- Fix ESLint warning for 'useBlockTypesState' hook. ([66757](https://github.com/WordPress/gutenberg/pull/66757)) +- Fix React Compiler error for 'BlockProps' util component. ([66809](https://github.com/WordPress/gutenberg/pull/66809)) +- Optimize `getVisibleElementBounds` in scrollable cases. ([66546](https://github.com/WordPress/gutenberg/pull/66546)) +- Revert: Fix unable to remove empty blocks on merge (#65262) + alternative. ([66564](https://github.com/WordPress/gutenberg/pull/66564)) +- URLInput: Fix incorrect classname for suggestions. ([66714](https://github.com/WordPress/gutenberg/pull/66714)) + +#### Site Editor +- Avoid using edited entity state in site editor loading hook. ([66924](https://github.com/WordPress/gutenberg/pull/66924)) +- Avoid using edited post selectors in welcome guide. ([66926](https://github.com/WordPress/gutenberg/pull/66926)) +- Edit Site: Refactor to remove usage of edited entity state. ([66922](https://github.com/WordPress/gutenberg/pull/66922)) +- Edit Site: Remove leftover 'priority-queue' dependency. ([66773](https://github.com/WordPress/gutenberg/pull/66773)) +- Remove useEditedEntityRecord hook. ([66955](https://github.com/WordPress/gutenberg/pull/66955)) + +#### Components +- Fix React Compiler error for 'useScrollRectIntoView'. ([66498](https://github.com/WordPress/gutenberg/pull/66498)) +- Panel: Add 40px size prop to Button. ([66589](https://github.com/WordPress/gutenberg/pull/66589)) +- Radio: Deprecate 36px default size. ([66572](https://github.com/WordPress/gutenberg/pull/66572)) +- Snackbar: Use `link` variant for action Button. ([66560](https://github.com/WordPress/gutenberg/pull/66560)) + +#### Data Layer +- Convert the emitter module in data package to TS. ([66669](https://github.com/WordPress/gutenberg/pull/66669)) +- Data: Rename useSelect internals to fix React Compiler violations. ([66807](https://github.com/WordPress/gutenberg/pull/66807)) +- Data: Upgrade Redux to v5.0.1. ([66966](https://github.com/WordPress/gutenberg/pull/66966)) + +#### Post Editor +- ESLint: Fix React Compiler violations in various commands. ([66787](https://github.com/WordPress/gutenberg/pull/66787)) +- Fix TS types for editor package. ([66754](https://github.com/WordPress/gutenberg/pull/66754)) + +#### Zoom Out +- Zoom-out: Move default background to the iframe component. ([66284](https://github.com/WordPress/gutenberg/pull/66284)) + +#### Design Tools +- Typography: Stabilize typography block supports within block processing. ([63401](https://github.com/WordPress/gutenberg/pull/63401)) + + +### Tools + +#### Testing +- Media: Check for `wav` mime type using isset. ([66947](https://github.com/WordPress/gutenberg/pull/66947)) + +#### Build Tooling +- Enforce the same order of fields in `package.json` files. ([66239](https://github.com/WordPress/gutenberg/pull/66239)) +- Introduce React Scanner for component usage stats. ([65463](https://github.com/WordPress/gutenberg/pull/65463)) + + +### Various + +- Style engine: Wrap array_merge in conditionals to prevent unnecessary merging. ([66661](https://github.com/WordPress/gutenberg/pull/66661)) + +#### Block Library +- Update placeholder text for blocks that support drag and drop. ([66842](https://github.com/WordPress/gutenberg/pull/66842)) +- update: Add Media to Add media in cover block. ([66835](https://github.com/WordPress/gutenberg/pull/66835)) + + +## First-time contributors + +The following PRs were merged by first-time contributors: + +- @benharri: Fix unset array key warning in block-bindings.php. ([66337](https://github.com/WordPress/gutenberg/pull/66337)) +- @benniledl: Add 6.6.2 to Version in WordPress. ([66870](https://github.com/WordPress/gutenberg/pull/66870)) +- @Infinite-Null: Media & Text: Set `.wp-block-media-text__media a` display to block. ([66915](https://github.com/WordPress/gutenberg/pull/66915)) +- @karthick-murugan: Site Icon Focus fix. ([66952](https://github.com/WordPress/gutenberg/pull/66952)) +- @rinkalpagdar: Post Content: Add border and spacing support. ([66366](https://github.com/WordPress/gutenberg/pull/66366)) +- @yogeshbhutkar: Site Hub: Fixed navigation redirect on mobile devices for classic themes. ([66867](https://github.com/WordPress/gutenberg/pull/66867)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @adamsilverstein @afercia @Aljullu @amitraj2203 @andrewserong @benharri @benniledl @carolinan @cbravobernal @DAreRodz @dcalhoun @ellatrix @fabiankaegy @gigitux @gziolo @hbhalodia @Infinite-Null @jasmussen @jorgefilipecosta @jsnajdr @juanfra @karthick-murugan @kevin940726 @louwie17 @Mamaduka @manzoorwanijk @matiasbenedetto @mikachan @mirka @n2erjo00 @ntsekouras @oandregal @ramonjd @renatho @rinkalpagdar @Soean @stokesman @swissspidy @t-hamano @tellthemachines @tyxla @up1512001 @Vrishabhsk @yogeshbhutkar @youknowriad + + = 19.6.1 = diff --git a/docs/getting-started/fundamentals/block-in-the-editor.md b/docs/getting-started/fundamentals/block-in-the-editor.md index d1f2a25063e6c6..1d51239907d8b5 100644 --- a/docs/getting-started/fundamentals/block-in-the-editor.md +++ b/docs/getting-started/fundamentals/block-in-the-editor.md @@ -139,6 +139,8 @@ export default function Edit( { attributes, setAttributes } ) { setAttributes( { message: val } ) } style={ { diff --git a/docs/getting-started/tutorial.md b/docs/getting-started/tutorial.md index 4e43241f63fb16..2a5dd979d3a569 100644 --- a/docs/getting-started/tutorial.md +++ b/docs/getting-started/tutorial.md @@ -480,6 +480,8 @@ export default function Edit( { attributes, setAttributes } ) { { showStartingYear && ( @@ -139,6 +141,8 @@ function EditPageForm( { pageId, onCancel, onSaveFinished } ) { return (
@@ -164,6 +168,8 @@ function VanillaReactForm({ initialTitle }) { const [title, setTitle] = useState( initialTitle ); return ( @@ -233,6 +239,8 @@ function EditPageForm( { pageId, onCancel, onSaveFinished } ) { return (
diff --git a/docs/reference-guides/block-api/block-edit-save.md b/docs/reference-guides/block-api/block-edit-save.md index 9e4dd3d1a916bd..86721c77e463c6 100644 --- a/docs/reference-guides/block-api/block-edit-save.md +++ b/docs/reference-guides/block-api/block-edit-save.md @@ -210,6 +210,8 @@ edit: ( { attributes, setAttributes } ) => { return (
{ return (
{ diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index a27de8211c824a..34db859f71d1de 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -512,7 +512,7 @@ Display a list of all pages. ([Source](https://github.com/WordPress/gutenberg/tr - **Name:** core/page-list - **Category:** widgets - **Allowed Blocks:** core/page-list-item -- **Supports:** interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~ +- **Supports:** interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~ - **Attributes:** isNested, parentPageID ## Page List Item diff --git a/docs/reference-guides/data/data-core-edit-site.md b/docs/reference-guides/data/data-core-edit-site.md index 775dd66a821ef0..a16c53861daada 100644 --- a/docs/reference-guides/data/data-core-edit-site.md +++ b/docs/reference-guides/data/data-core-edit-site.md @@ -52,6 +52,8 @@ _Returns_ ### getEditedPostId +> **Deprecated** + Returns the ID of the currently edited template or template part. _Parameters_ @@ -64,6 +66,8 @@ _Returns_ ### getEditedPostType +> **Deprecated** + Returns the current edited post type (wp_template or wp_template_part). _Parameters_ @@ -189,6 +193,8 @@ _Returns_ ### isPage +> **Deprecated** + Whether or not the editor has a page loaded into it. _Related_ @@ -273,6 +279,8 @@ _Parameters_ ### setEditedEntity +> **Deprecated** + Action that sets an edited entity. _Parameters_ @@ -287,6 +295,8 @@ _Returns_ ### setEditedPostContext +> **Deprecated** + Set's the current block editor context. _Parameters_ @@ -345,6 +355,8 @@ _Parameters_ ### setNavigationMenu +> **Deprecated** + Action that sets a navigation menu. _Parameters_ @@ -385,6 +397,8 @@ _Returns_ ### setTemplatePart +> **Deprecated** + Action that sets a template part. _Parameters_ 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 4a4ff98697b5f3..1a1b2540b258b9 100644 --- a/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md +++ b/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md @@ -45,6 +45,8 @@ const PluginSidebarMoreMenuItemTest = () => { ) }

setText( newText ) } diff --git a/docs/reference-guides/slotfills/plugin-sidebar.md b/docs/reference-guides/slotfills/plugin-sidebar.md index 9bf911b3bb13f2..7191b80e54e2d6 100644 --- a/docs/reference-guides/slotfills/plugin-sidebar.md +++ b/docs/reference-guides/slotfills/plugin-sidebar.md @@ -38,6 +38,8 @@ const PluginSidebarExample = () => { ) }

setText( newText ) } diff --git a/gutenberg.php b/gutenberg.php index eed059a15c9a35..f79182f3ead567 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.5 * Requires PHP: 7.2 - * Version: 19.6.1 + * Version: 19.7.0-rc.2 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index d505916450cafb..10f80c3f3cdb7b 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2749,9 +2749,21 @@ private static function get_block_nodes( $theme_json, $selectors = array(), $opt foreach ( $theme_json['styles']['blocks'] as $name => $node ) { $node_path = array( 'styles', 'blocks', $name ); if ( $include_node_paths_only ) { - $nodes[] = array( + $variation_paths = array(); + if ( $include_variations && isset( $node['variations'] ) ) { + foreach ( $node['variations'] as $variation => $variation_node ) { + $variation_paths[] = array( + 'path' => array( 'styles', 'blocks', $name, 'variations', $variation ), + ); + } + } + $node = array( 'path' => $node_path, ); + if ( ! empty( $variation_paths ) ) { + $node['variations'] = $variation_paths; + } + $nodes[] = $node; } else { $selector = null; if ( isset( $selectors[ $name ]['selector'] ) ) { diff --git a/lib/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php b/lib/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php index 981b9dbd840319..60b45b1a63adef 100644 --- a/lib/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php +++ b/lib/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php @@ -10,6 +10,10 @@ class Gutenberg_REST_Comment_Controller_6_8 extends WP_REST_Comments_Controller { public function create_item_permissions_check( $request ) { + if ( empty( $request['comment_type'] ) || 'comment' === $request['comment_type'] ) { + return parent::create_item_permissions_check( $request ); + } + if ( ! is_user_logged_in() ) { if ( get_option( 'comment_registration' ) ) { return new WP_Error( @@ -90,14 +94,6 @@ public function create_item_permissions_check( $request ) { ); } - if ( 'draft' === $post->post_status && 'comment' === $request['comment_type'] ) { - return new WP_Error( - 'rest_comment_draft_post', - __( 'Sorry, you are not allowed to create a comment on this post.' ), - array( 'status' => 403 ) - ); - } - if ( 'trash' === $post->post_status ) { return new WP_Error( 'rest_comment_trash_post', @@ -114,14 +110,6 @@ public function create_item_permissions_check( $request ) { ); } - if ( ! comments_open( $post->ID ) && 'comment' === $request['comment_type'] ) { - return new WP_Error( - 'rest_comment_closed', - __( 'Sorry, comments are closed for this item.' ), - array( 'status' => 403 ) - ); - } - return true; } } diff --git a/lib/compat/wordpress-6.8/functions.php b/lib/compat/wordpress-6.8/functions.php new file mode 100644 index 00000000000000..a4658d1a182c73 --- /dev/null +++ b/lib/compat/wordpress-6.8/functions.php @@ -0,0 +1,35 @@ + 'audio/wav'` + * + * @since 6.8.0 + * + * @param string[] $mime_types Mime types. + * @return string[] Mime types keyed by the file extension regex corresponding to those types. +*/ +function gutenberg_get_mime_types_6_8( $mime_types ) { + /* + * Only add support if there is existing support for 'wav'. + * Some plugins may have deliberately disabled it. + */ + if ( ! isset( $mime_types['wav'] ) && ! isset( $mime_types['wav|x-wav'] ) ) { + return $mime_types; + } + /* + * Also, given that other themes or plugins may have already + * tried to add x-wav type support, only + * add the mime type if it doesn't already exist + * to avoid overriding any customizations. + */ + if ( ! isset( $mime_types['x-wav'] ) && ! isset( $mime_types['wav|x-wav'] ) ) { + $mime_types['x-wav'] = 'audio/wav'; + } + return $mime_types; +} +add_filter( 'mime_types', 'gutenberg_get_mime_types_6_8', 99 ); diff --git a/lib/load.php b/lib/load.php index 6236f0eb04b3c6..d7e4a33cd02c92 100644 --- a/lib/load.php +++ b/lib/load.php @@ -119,6 +119,7 @@ function gutenberg_is_experiment_enabled( $name ) { // WordPress 6.8 compat. require __DIR__ . '/compat/wordpress-6.8/preload.php'; require __DIR__ . '/compat/wordpress-6.8/blocks.php'; +require __DIR__ . '/compat/wordpress-6.8/functions.php'; // Experimental features. require __DIR__ . '/experimental/block-editor-settings-mobile.php'; diff --git a/package-lock.json b/package-lock.json index 0bb48c55c5326c..036acafe885fa6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "19.6.1", + "version": "19.7.0-rc.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "19.6.1", + "version": "19.7.0-rc.2", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ @@ -91,6 +91,7 @@ "eslint-plugin-jest": "27.2.3", "eslint-plugin-jest-dom": "5.0.2", "eslint-plugin-prettier": "5.0.0", + "eslint-plugin-react-compiler": "19.0.0-beta-8a03594-20241020", "eslint-plugin-ssr-friendly": "1.0.6", "eslint-plugin-storybook": "0.6.13", "eslint-plugin-testing-library": "6.0.2", @@ -119,7 +120,6 @@ "npm-run-all": "4.1.5", "patch-package": "8.0.0", "postcss": "8.4.38", - "postcss-import": "16.1.0", "postcss-loader": "6.2.1", "postcss-local-keyframes": "^0.0.2", "prettier": "npm:wp-prettier@3.0.3", @@ -135,7 +135,7 @@ "react-scanner": "1.2.0", "react-test-renderer": "18.3.1", "reassure": "0.7.1", - "redux": "4.1.2", + "redux": "5.0.1", "resize-observer-polyfill": "1.5.1", "rimraf": "3.0.2", "rtlcss": "4.0.0", @@ -2479,6 +2479,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", @@ -21155,6 +21172,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -25346,6 +25364,41 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, + "node_modules/eslint-plugin-react-compiler": { + "version": "19.0.0-beta-8a03594-20241020", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.0.0-beta-8a03594-20241020.tgz", + "integrity": "sha512-bYg1COih1s3r14IV/AKdQs/SN7CQmNI0ZaMtPdgZ6gp1S1Q/KGP9P43w7R6dHJ4wYpuMBvekNJHQdVu+x6UM+A==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "hermes-parser": "^0.20.1", + "zod": "^3.22.4", + "zod-validation-error": "^3.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.0.0 || >= 18.0.0" + }, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-plugin-react-compiler/node_modules/hermes-estree": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.20.1.tgz", + "integrity": "sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg==", + "dev": true + }, + "node_modules/eslint-plugin-react-compiler/node_modules/hermes-parser": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.20.1.tgz", + "integrity": "sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA==", + "dev": true, + "dependencies": { + "hermes-estree": "0.20.1" + } + }, "node_modules/eslint-plugin-react-hooks": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz", @@ -40556,6 +40609,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -40835,27 +40889,6 @@ "postcss": "^8.2.15" } }, - "node_modules/postcss-import": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz", - "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-import/node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, "node_modules/postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", @@ -43336,14 +43369,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dependencies": { - "pify": "^2.3.0" - } - }, "node_modules/read-cmd-shim": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", @@ -43764,12 +43789,9 @@ } }, "node_modules/redux": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", - "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", - "dependencies": { - "@babel/runtime": "^7.9.2" - } + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" }, "node_modules/regenerate": { "version": "1.4.2", @@ -51852,9 +51874,21 @@ "url": "https://github.com/sponsors/colinhacks" } }, + "node_modules/zod-validation-error": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.4.0.tgz", + "integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==", + "dev": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.18.0" + } + }, "packages/a11y": { "name": "@wordpress/a11y", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -51868,7 +51902,7 @@ }, "packages/annotations": { "name": "@wordpress/annotations", - "version": "3.11.0", + "version": "3.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -51896,7 +51930,7 @@ }, "packages/api-fetch": { "name": "@wordpress/api-fetch", - "version": "7.11.0", + "version": "7.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -51910,7 +51944,7 @@ }, "packages/autop": { "name": "@wordpress/autop", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -51922,7 +51956,7 @@ }, "packages/babel-plugin-import-jsx-pragma": { "name": "@wordpress/babel-plugin-import-jsx-pragma", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -51934,7 +51968,7 @@ }, "packages/babel-plugin-makepot": { "name": "@wordpress/babel-plugin-makepot", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "deepmerge": "^4.3.0", @@ -51951,7 +51985,7 @@ }, "packages/babel-preset-default": { "name": "@wordpress/babel-preset-default", - "version": "8.11.0", + "version": "8.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -53082,7 +53116,7 @@ }, "packages/base-styles": { "name": "@wordpress/base-styles", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53091,7 +53125,7 @@ }, "packages/blob": { "name": "@wordpress/blob", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -53103,7 +53137,7 @@ }, "packages/block-directory": { "name": "@wordpress/block-directory", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53139,7 +53173,7 @@ }, "packages/block-editor": { "name": "@wordpress/block-editor", - "version": "14.6.0", + "version": "14.7.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53239,7 +53273,7 @@ }, "packages/block-library": { "name": "@wordpress/block-library", - "version": "9.11.0", + "version": "9.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53305,7 +53339,7 @@ }, "packages/block-serialization-default-parser": { "name": "@wordpress/block-serialization-default-parser", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -53317,7 +53351,7 @@ }, "packages/block-serialization-spec-parser": { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "pegjs": "^0.10.0", @@ -53330,7 +53364,7 @@ }, "packages/blocks": { "name": "@wordpress/blocks", - "version": "14.0.0", + "version": "14.1.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53384,7 +53418,7 @@ }, "packages/browserslist-config": { "name": "@wordpress/browserslist-config", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53393,7 +53427,7 @@ }, "packages/commands": { "name": "@wordpress/commands", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53632,7 +53666,7 @@ }, "packages/components": { "name": "@wordpress/components", - "version": "28.11.0", + "version": "28.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -53753,7 +53787,7 @@ }, "packages/compose": { "name": "@wordpress/compose", - "version": "7.11.0", + "version": "7.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53790,7 +53824,7 @@ }, "packages/core-commands": { "name": "@wordpress/core-commands", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53819,7 +53853,7 @@ }, "packages/core-data": { "name": "@wordpress/core-data", - "version": "7.11.0", + "version": "7.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53864,7 +53898,7 @@ }, "packages/create-block": { "name": "@wordpress/create-block", - "version": "4.54.0", + "version": "4.55.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/lazy-import": "*", @@ -53891,7 +53925,7 @@ }, "packages/create-block-interactive-template": { "name": "@wordpress/create-block-interactive-template", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53900,7 +53934,7 @@ }, "packages/create-block-tutorial-template": { "name": "@wordpress/create-block-tutorial-template", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -53909,7 +53943,7 @@ }, "packages/customize-widgets": { "name": "@wordpress/customize-widgets", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53948,7 +53982,7 @@ }, "packages/data": { "name": "@wordpress/data", - "version": "10.11.0", + "version": "10.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53963,7 +53997,7 @@ "equivalent-key-map": "^0.2.2", "is-plain-object": "^5.0.0", "is-promise": "^4.0.0", - "redux": "^4.1.2", + "redux": "^5.0.1", "rememo": "^4.0.2", "use-memo-one": "^1.1.1" }, @@ -53977,7 +54011,7 @@ }, "packages/data-controls": { "name": "@wordpress/data-controls", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -53995,7 +54029,7 @@ }, "packages/dataviews": { "name": "@wordpress/dataviews", - "version": "4.7.0", + "version": "4.8.0", "license": "GPL-2.0-or-later", "dependencies": { "@ariakit/react": "^0.4.10", @@ -54052,7 +54086,7 @@ }, "packages/date": { "name": "@wordpress/date", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54067,7 +54101,7 @@ }, "packages/dependency-extraction-webpack-plugin": { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "json2php": "^0.0.7" @@ -54082,7 +54116,7 @@ }, "packages/deprecated": { "name": "@wordpress/deprecated", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54095,7 +54129,7 @@ }, "packages/docgen": { "name": "@wordpress/docgen", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -54116,7 +54150,7 @@ }, "packages/dom": { "name": "@wordpress/dom", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54129,7 +54163,7 @@ }, "packages/dom-ready": { "name": "@wordpress/dom-ready", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54141,7 +54175,7 @@ }, "packages/e2e-test-utils": { "name": "@wordpress/e2e-test-utils", - "version": "11.11.0", + "version": "11.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54163,7 +54197,7 @@ }, "packages/e2e-test-utils-playwright": { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "change-case": "^4.1.2", @@ -54189,7 +54223,7 @@ }, "packages/e2e-tests": { "name": "@wordpress/e2e-tests", - "version": "8.11.0", + "version": "8.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/e2e-test-utils": "*", @@ -54227,7 +54261,7 @@ }, "packages/edit-post": { "name": "@wordpress/edit-post", - "version": "8.11.0", + "version": "8.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54274,7 +54308,7 @@ }, "packages/edit-site": { "name": "@wordpress/edit-site", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54336,7 +54370,7 @@ }, "packages/edit-widgets": { "name": "@wordpress/edit-widgets", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54380,7 +54414,7 @@ }, "packages/editor": { "name": "@wordpress/editor", - "version": "14.11.0", + "version": "14.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54442,7 +54476,7 @@ }, "packages/element": { "name": "@wordpress/element", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54461,7 +54495,7 @@ }, "packages/env": { "name": "@wordpress/env", - "version": "10.11.0", + "version": "10.12.0", "license": "GPL-2.0-or-later", "dependencies": { "chalk": "^4.0.0", @@ -54592,7 +54626,7 @@ }, "packages/escape-html": { "name": "@wordpress/escape-html", - "version": "3.11.0", + "version": "3.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54604,7 +54638,7 @@ }, "packages/eslint-plugin": { "name": "@wordpress/eslint-plugin", - "version": "21.4.0", + "version": "21.5.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/eslint-parser": "7.25.7", @@ -54673,7 +54707,7 @@ }, "packages/fields": { "name": "@wordpress/fields", - "version": "0.3.0", + "version": "0.4.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54685,6 +54719,7 @@ "@wordpress/core-data": "*", "@wordpress/data": "*", "@wordpress/dataviews": "*", + "@wordpress/date": "*", "@wordpress/element": "*", "@wordpress/hooks": "*", "@wordpress/html-entities": "*", @@ -54700,6 +54735,7 @@ "@wordpress/warning": "*", "change-case": "4.1.2", "client-zip": "^2.4.5", + "clsx": "2.1.1", "remove-accents": "^0.5.0" }, "engines": { @@ -54712,7 +54748,7 @@ }, "packages/format-library": { "name": "@wordpress/format-library", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54740,7 +54776,7 @@ }, "packages/hooks": { "name": "@wordpress/hooks", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54752,7 +54788,7 @@ }, "packages/html-entities": { "name": "@wordpress/html-entities", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54764,7 +54800,7 @@ }, "packages/i18n": { "name": "@wordpress/i18n", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54784,7 +54820,7 @@ }, "packages/icons": { "name": "@wordpress/icons", - "version": "10.11.0", + "version": "10.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54798,7 +54834,7 @@ }, "packages/interactivity": { "name": "@wordpress/interactivity", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@preact/signals": "^1.3.0", @@ -54811,7 +54847,7 @@ }, "packages/interactivity-router": { "name": "@wordpress/interactivity-router", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/a11y": "*", @@ -54824,7 +54860,7 @@ }, "packages/interface": { "name": "@wordpress/interface", - "version": "8.0.0", + "version": "8.1.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54852,7 +54888,7 @@ }, "packages/is-shallow-equal": { "name": "@wordpress/is-shallow-equal", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -54864,7 +54900,7 @@ }, "packages/jest-console": { "name": "@wordpress/jest-console", - "version": "8.11.0", + "version": "8.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54880,7 +54916,7 @@ }, "packages/jest-preset-default": { "name": "@wordpress/jest-preset-default", - "version": "12.11.0", + "version": "12.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/jest-console": "*", @@ -54897,7 +54933,7 @@ }, "packages/jest-puppeteer-axe": { "name": "@wordpress/jest-puppeteer-axe", - "version": "7.11.0", + "version": "7.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@axe-core/puppeteer": "^4.0.0", @@ -54919,7 +54955,7 @@ }, "packages/keyboard-shortcuts": { "name": "@wordpress/keyboard-shortcuts", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54937,7 +54973,7 @@ }, "packages/keycodes": { "name": "@wordpress/keycodes", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54950,7 +54986,7 @@ }, "packages/lazy-import": { "name": "@wordpress/lazy-import", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "execa": "^4.0.2", @@ -54964,7 +55000,7 @@ }, "packages/list-reusable-blocks": { "name": "@wordpress/list-reusable-blocks", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -54987,7 +55023,7 @@ }, "packages/media-utils": { "name": "@wordpress/media-utils", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55004,7 +55040,7 @@ }, "packages/notices": { "name": "@wordpress/notices", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55021,7 +55057,7 @@ }, "packages/npm-package-json-lint-config": { "name": "@wordpress/npm-package-json-lint-config", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55033,7 +55069,7 @@ }, "packages/nux": { "name": "@wordpress/nux", - "version": "9.11.0", + "version": "9.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55056,7 +55092,7 @@ }, "packages/patterns": { "name": "@wordpress/patterns", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55086,7 +55122,7 @@ }, "packages/plugins": { "name": "@wordpress/plugins", - "version": "7.11.0", + "version": "7.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55110,7 +55146,7 @@ }, "packages/postcss-plugins-preset": { "name": "@wordpress/postcss-plugins-preset", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@wordpress/base-styles": "*", @@ -55126,7 +55162,7 @@ }, "packages/postcss-themes": { "name": "@wordpress/postcss-themes", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55138,7 +55174,7 @@ }, "packages/preferences": { "name": "@wordpress/preferences", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55164,7 +55200,7 @@ }, "packages/preferences-persistence": { "name": "@wordpress/preferences-persistence", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55177,7 +55213,7 @@ }, "packages/prettier-config": { "name": "@wordpress/prettier-config", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55189,7 +55225,7 @@ }, "packages/primitives": { "name": "@wordpress/primitives", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55206,7 +55242,7 @@ }, "packages/priority-queue": { "name": "@wordpress/priority-queue", - "version": "3.11.0", + "version": "3.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55219,7 +55255,7 @@ }, "packages/private-apis": { "name": "@wordpress/private-apis", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -55231,7 +55267,7 @@ }, "packages/project-management-automation": { "name": "@wordpress/project-management-automation", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@actions/core": "1.9.1", @@ -55259,7 +55295,7 @@ }, "packages/react-i18n": { "name": "@wordpress/react-i18n", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55415,7 +55451,7 @@ }, "packages/readable-js-assets-webpack-plugin": { "name": "@wordpress/readable-js-assets-webpack-plugin", - "version": "3.11.0", + "version": "3.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -55427,7 +55463,7 @@ }, "packages/redux-routine": { "name": "@wordpress/redux-routine", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55470,7 +55506,7 @@ }, "packages/reusable-blocks": { "name": "@wordpress/reusable-blocks", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55497,7 +55533,7 @@ }, "packages/rich-text": { "name": "@wordpress/rich-text", - "version": "7.11.0", + "version": "7.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55521,7 +55557,7 @@ }, "packages/router": { "name": "@wordpress/router", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -55540,7 +55576,7 @@ }, "packages/scripts": { "name": "@wordpress/scripts", - "version": "30.4.0", + "version": "30.5.1", "license": "GPL-2.0-or-later", "dependencies": { "@babel/core": "7.25.7", @@ -55585,7 +55621,6 @@ "npm-package-json-lint": "^6.4.0", "npm-packlist": "^3.0.0", "postcss": "^8.4.5", - "postcss-import": "^16.1.0", "postcss-loader": "^6.2.1", "prettier": "npm:wp-prettier@3.0.3", "puppeteer-core": "^23.1.0", @@ -55974,7 +56009,7 @@ }, "packages/server-side-render": { "name": "@wordpress/server-side-render", - "version": "5.11.0", + "version": "5.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56000,7 +56035,7 @@ }, "packages/shortcode": { "name": "@wordpress/shortcode", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56013,7 +56048,7 @@ }, "packages/style-engine": { "name": "@wordpress/style-engine", - "version": "2.11.0", + "version": "2.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56026,7 +56061,7 @@ }, "packages/stylelint-config": { "name": "@wordpress/stylelint-config", - "version": "23.3.0", + "version": "23.4.0", "license": "MIT", "dependencies": { "@stylistic/stylelint-plugin": "^3.0.1", @@ -56137,7 +56172,7 @@ }, "packages/sync": { "name": "@wordpress/sync", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56158,7 +56193,7 @@ }, "packages/token-list": { "name": "@wordpress/token-list", - "version": "3.11.0", + "version": "3.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" @@ -56170,7 +56205,7 @@ }, "packages/undo-manager": { "name": "@wordpress/undo-manager", - "version": "1.11.0", + "version": "1.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56183,7 +56218,7 @@ }, "packages/url": { "name": "@wordpress/url", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56196,7 +56231,7 @@ }, "packages/viewport": { "name": "@wordpress/viewport", - "version": "6.11.0", + "version": "6.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56226,7 +56261,7 @@ }, "packages/warning": { "name": "@wordpress/warning", - "version": "3.11.0", + "version": "3.12.0", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -56235,7 +56270,7 @@ }, "packages/widgets": { "name": "@wordpress/widgets", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7", @@ -56263,7 +56298,7 @@ }, "packages/wordcount": { "name": "@wordpress/wordcount", - "version": "4.11.0", + "version": "4.12.0", "license": "GPL-2.0-or-later", "dependencies": { "@babel/runtime": "7.25.7" diff --git a/package.json b/package.json index 0fdb7ad563cd15..751bde40240811 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "19.6.1", + "version": "19.7.0-rc.2", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", @@ -100,6 +100,7 @@ "eslint-plugin-jest": "27.2.3", "eslint-plugin-jest-dom": "5.0.2", "eslint-plugin-prettier": "5.0.0", + "eslint-plugin-react-compiler": "19.0.0-beta-8a03594-20241020", "eslint-plugin-ssr-friendly": "1.0.6", "eslint-plugin-storybook": "0.6.13", "eslint-plugin-testing-library": "6.0.2", @@ -128,7 +129,6 @@ "npm-run-all": "4.1.5", "patch-package": "8.0.0", "postcss": "8.4.38", - "postcss-import": "16.1.0", "postcss-loader": "6.2.1", "postcss-local-keyframes": "^0.0.2", "prettier": "npm:wp-prettier@3.0.3", @@ -144,7 +144,7 @@ "react-scanner": "1.2.0", "react-test-renderer": "18.3.1", "reassure": "0.7.1", - "redux": "4.1.2", + "redux": "5.0.1", "resize-observer-polyfill": "1.5.1", "rimraf": "3.0.2", "rtlcss": "4.0.0", diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 5e90577e9155ab..dfd1e62906f9f4 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/a11y/package.json b/packages/a11y/package.json index 008bd9088e0778..1fcffd9cdfe69f 100644 --- a/packages/a11y/package.json +++ b/packages/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/a11y", - "version": "4.11.0", + "version": "4.12.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 0618f4962f5eb5..07e9267e5b04c5 100644 --- a/packages/annotations/CHANGELOG.md +++ b/packages/annotations/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.12.0 (2024-11-16) + ## 3.11.0 (2024-10-30) ## 3.10.0 (2024-10-16) diff --git a/packages/annotations/package.json b/packages/annotations/package.json index b1d6d210807a87..269c16d159e9f6 100644 --- a/packages/annotations/package.json +++ b/packages/annotations/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/annotations", - "version": "3.11.0", + "version": "3.12.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 8d3faea535faf3..e2ba79548592ec 100644 --- a/packages/api-fetch/CHANGELOG.md +++ b/packages/api-fetch/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.12.0 (2024-11-16) + ## 7.11.0 (2024-10-30) ## 7.10.0 (2024-10-16) diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 7d5b8dfd588897..07d90568dc9413 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/api-fetch", - "version": "7.11.0", + "version": "7.12.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 9534b183d6ebb1..dd9879ca23b746 100644 --- a/packages/autop/CHANGELOG.md +++ b/packages/autop/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/autop/package.json b/packages/autop/package.json index 336dda06edfe2c..60b7102850020a 100644 --- a/packages/autop/package.json +++ b/packages/autop/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/autop", - "version": "4.11.0", + "version": "4.12.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 87bc412fd90eb3..38a36491fe9a81 100644 --- a/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md +++ b/packages/babel-plugin-import-jsx-pragma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/babel-plugin-import-jsx-pragma/package.json b/packages/babel-plugin-import-jsx-pragma/package.json index d9b565b4e27ec0..231886784bd3f0 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": "5.11.0", + "version": "5.12.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 f643a9304c68ab..1e22ee8b4eabb4 100644 --- a/packages/babel-plugin-makepot/CHANGELOG.md +++ b/packages/babel-plugin-makepot/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ## 6.11.0 (2024-10-30) ## 6.10.0 (2024-10-16) diff --git a/packages/babel-plugin-makepot/package.json b/packages/babel-plugin-makepot/package.json index cf04d3dc72e409..4f18f8556d68dd 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": "6.11.0", + "version": "6.12.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 d6eef13b90d456..8cce12417d2e26 100644 --- a/packages/babel-preset-default/CHANGELOG.md +++ b/packages/babel-preset-default/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.12.0 (2024-11-16) + ## 8.11.0 (2024-10-30) ## 8.10.0 (2024-10-16) diff --git a/packages/babel-preset-default/package.json b/packages/babel-preset-default/package.json index 2f727d1886425d..b305500dc20795 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": "8.11.0", + "version": "8.12.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 61ff1100ac6453..67fdcfa2424530 100644 --- a/packages/base-styles/CHANGELOG.md +++ b/packages/base-styles/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/base-styles/package.json b/packages/base-styles/package.json index 7246dc83eaf4c6..bcdb19206b39e9 100644 --- a/packages/base-styles/package.json +++ b/packages/base-styles/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/base-styles", - "version": "5.11.0", + "version": "5.12.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 660c60776c7bd1..2edfa51064106f 100644 --- a/packages/blob/CHANGELOG.md +++ b/packages/blob/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/blob/package.json b/packages/blob/package.json index 0dc01ac7198f59..2134bcd21e9346 100644 --- a/packages/blob/package.json +++ b/packages/blob/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blob", - "version": "4.11.0", + "version": "4.12.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 53636f34dad586..37b6b6b3ece40a 100644 --- a/packages/block-directory/CHANGELOG.md +++ b/packages/block-directory/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/block-directory/package.json b/packages/block-directory/package.json index 18a40824aa4754..a005e5be7cd60b 100644 --- a/packages/block-directory/package.json +++ b/packages/block-directory/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-directory", - "version": "5.11.0", + "version": "5.12.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 6755c4ec83f215..3c1e63c75c75ff 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.7.0 (2024-11-16) + ## 14.6.0 (2024-10-30) ## 14.5.0 (2024-10-16) diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index b4672bc57690eb..031b34933691a3 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-editor", - "version": "14.6.0", + "version": "14.7.0", "description": "Generic block editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-editor/src/components/block-lock/modal.js b/packages/block-editor/src/components/block-lock/modal.js index 7d09f7b63f8cd0..3be23f6adde146 100644 --- a/packages/block-editor/src/components/block-lock/modal.js +++ b/packages/block-editor/src/components/block-lock/modal.js @@ -24,7 +24,7 @@ import useBlockDisplayInformation from '../use-block-display-information'; import { store as blockEditorStore } from '../../store'; // Entity based blocks which allow edit locking -const ALLOWS_EDIT_LOCKING = [ 'core/block', 'core/navigation' ]; +const ALLOWS_EDIT_LOCKING = [ 'core/navigation' ]; function getTemplateLockValue( lock ) { // Prevents all operations. diff --git a/packages/block-editor/src/components/block-mover/README.md b/packages/block-editor/src/components/block-mover/README.md index 38520072b4ac86..b781de773ef9f3 100644 --- a/packages/block-editor/src/components/block-mover/README.md +++ b/packages/block-editor/src/components/block-mover/README.md @@ -1,12 +1,10 @@ -# Block mover +# BlockMover -Block movers allow moving blocks inside the editor using up and down buttons. +BlockMover component allows moving blocks inside the editor using up and down buttons. ![Block mover screenshot](https://make.wordpress.org/core/files/2020/08/block-mover-screenshot.png) -## Development guidelines - -### Usage +## Usage Shows the block mover buttons in the block toolbar. @@ -15,13 +13,22 @@ import { BlockMover } from '@wordpress/block-editor'; const MyMover = () => ; ``` -### Props +## Props -#### clientIds +### clientIds -Blocks IDs +The IDs of the blocks to move. - Type: `Array` +- Required: Yes + +### hideDragHandle + +If this property is true, the drag handle is hidden. + +- Type: `boolean` +- Required: No +- Default: `false` ## Related components diff --git a/packages/block-editor/src/components/block-mover/stories/index.story.js b/packages/block-editor/src/components/block-mover/stories/index.story.js index de30260563f91e..de6d13c797b4d9 100644 --- a/packages/block-editor/src/components/block-mover/stories/index.story.js +++ b/packages/block-editor/src/components/block-mover/stories/index.story.js @@ -14,6 +14,7 @@ import BlockMover from '../'; import { ExperimentalBlockEditorProvider } from '../../provider'; import { store as blockEditorStore } from '../../../store'; +// For the purpose of this story, we need to register the core blocks samples. registerCoreBlocks(); const blocks = [ // vertical @@ -30,81 +31,82 @@ const blocks = [ ] ), ]; -function Provider( { children } ) { - const wrapperStyle = { margin: '24px', position: 'relative' }; - - return ( -
+/** + * BlockMover component allows moving blocks inside the editor using up and down buttons. + */ +const meta = { + title: 'BlockEditor/BlockMover', + component: BlockMover, + parameters: { + docs: { canvas: { sourceState: 'shown' } }, + }, + decorators: [ + ( Story ) => ( - { children } + + + -
- ); -} - -function BlockMoverStory() { - const { updateBlockListSettings } = useDispatch( blockEditorStore ); - - useEffect( () => { - /** - * This shouldn't be needed but unfortunatley - * the layout orientation is not declarative, we need - * to render the blocks to update the block settings in the state. - */ - updateBlockListSettings( blocks[ 1 ].clientId, { - orientation: 'horizontal', - } ); - }, [] ); - - return ( -
-

The mover by default is vertical

- - - - -

- But it can also accommodate horizontal blocks. -

- - - + ), + ], + argTypes: { + clientIds: { + control: { + type: 'none', + }, + description: 'The client IDs of the blocks to move.', + }, + hideDragHandle: { + control: { + type: 'boolean', + }, + description: 'If this property is true, the drag handle is hidden.', + }, + }, +}; +export default meta; -

We can also hide the drag handle.

- - - -
- ); -} +export const Default = { + args: { + clientIds: [ blocks[ 0 ].innerBlocks[ 1 ].clientId ], + }, +}; -export default { - title: 'BlockEditor/BlockMover', +/** + * This story shows the block mover with horizontal orientation. + * It is necessary to render the blocks to update the block settings in the state. + */ +export const Horizontal = { + decorators: [ + ( Story ) => { + const { updateBlockListSettings } = useDispatch( blockEditorStore ); + useEffect( () => { + /** + * This shouldn't be needed but unfortunately + * the layout orientation is not declarative, we need + * to render the blocks to update the block settings in the state. + */ + updateBlockListSettings( blocks[ 1 ].clientId, { + orientation: 'horizontal', + } ); + }, [] ); + return ; + }, + ], + args: { + clientIds: [ blocks[ 1 ].innerBlocks[ 1 ].clientId ], + }, + parameters: { + docs: { canvas: { sourceState: 'hidden' } }, + }, }; -export const _default = () => { - return ( - - - - ); +/** + * You can hide the drag handle by `hideDragHandle` attribute. + */ +export const HideDragHandle = { + args: { + ...Default.args, + hideDragHandle: true, + }, }; diff --git a/packages/block-editor/src/components/block-patterns-list/README.md b/packages/block-editor/src/components/block-patterns-list/README.md index 18e7ead5d1805a..f4c6cc6141de13 100644 --- a/packages/block-editor/src/components/block-patterns-list/README.md +++ b/packages/block-editor/src/components/block-patterns-list/README.md @@ -61,6 +61,14 @@ The aria label for the block patterns list. - Required: No - Default: `Block Patterns` +#### showTitlesAsTooltip + +Whether to render the title of each pattern as a tooltip. User-defined patterns always show their visual title regardless of this prop. + +- Type: `boolean` +- Required: No +- Default: `false` + ## Related components Block Editor components are components that can be used to compose the UI of your block editor. Thus, they can only be used under a [`BlockEditorProvider`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/provider/README.md) in the components tree. diff --git a/packages/block-editor/src/components/block-patterns-list/index.js b/packages/block-editor/src/components/block-patterns-list/index.js index 741a92ddf10dfa..8128e89418f45a 100644 --- a/packages/block-editor/src/components/block-patterns-list/index.js +++ b/packages/block-editor/src/components/block-patterns-list/index.js @@ -39,14 +39,14 @@ function BlockPattern( { pattern, onClick, onHover, - showTitle = true, - showTooltip, + showTitlesAsTooltip, category, } ) { const [ isDragging, setIsDragging ] = useState( false ); const { blocks, viewportWidth } = pattern; const instanceId = useInstanceId( BlockPattern ); const descriptionId = `block-editor-block-patterns-list__item-description-${ instanceId }`; + const isUserPattern = pattern.type === INSERTER_PATTERN_TYPES.user; // When we have a selected category and the pattern is draggable, we need to update the // pattern's categories in metadata to only contain the selected category, and pass this to @@ -94,10 +94,7 @@ function BlockPattern( { } } > - - { showTitle && ( + { ( ! showTitlesAsTooltip || isUserPattern ) && ( - { pattern.type === - INSERTER_PATTERN_TYPES.user && - ! pattern.syncStatus && ( -
- -
- ) } - { ( ! showTooltip || - pattern.type === - INSERTER_PATTERN_TYPES.user ) && ( -
- { pattern.title } + { isUserPattern && ! pattern.syncStatus && ( +
+
) } +
+ { pattern.title } +
) } @@ -196,7 +186,6 @@ function BlockPatternsList( orientation, label = __( 'Block patterns' ), category, - showTitle = true, showTitlesAsTooltip, pagingProps, }, @@ -230,8 +219,7 @@ function BlockPatternsList( onClick={ onClickPattern } onHover={ onHover } isDraggable={ isDraggable } - showTitle={ showTitle } - showTooltip={ showTitlesAsTooltip } + showTitlesAsTooltip={ showTitlesAsTooltip } category={ category } /> ) ) } diff --git a/packages/block-editor/src/components/block-patterns-list/stories/index.story.js b/packages/block-editor/src/components/block-patterns-list/stories/index.story.js index 0ebb4520d98fd4..ad9bffab762c23 100644 --- a/packages/block-editor/src/components/block-patterns-list/stories/index.story.js +++ b/packages/block-editor/src/components/block-patterns-list/stories/index.story.js @@ -31,7 +31,6 @@ export const Default = { blockPatterns: patterns, isDraggable: false, label: 'Block patterns story', - showTitle: true, showTitlesAsTooltip: false, }, argTypes: { @@ -40,18 +39,11 @@ export const Default = { description: 'Usually this component is used with `useAsyncList` for performance reasons and you should provide the returned list from that hook. Alternatively it should have the same value with `blockPatterns`.', }, - showTitle: { - description: 'Whether to render the title of each pattern.', - table: { - defaultValue: { summary: true }, - type: { summary: 'boolean' }, - }, - }, onClickPattern: { type: 'function' }, onHover: { type: 'function' }, showTitlesAsTooltip: { description: - 'Whether to render the title of each pattern as a tooltip. If enabled, it takes precedence over `showTitle` prop.', + 'Whether to render the title of each pattern as a tooltip. If enabled', }, orientation: { description: 'Orientation for the underlying composite widget.', diff --git a/packages/block-editor/src/components/block-toolbar/change-design.js b/packages/block-editor/src/components/block-toolbar/change-design.js index 9da1affe4273cc..2d69675218ea48 100644 --- a/packages/block-editor/src/components/block-toolbar/change-design.js +++ b/packages/block-editor/src/components/block-toolbar/change-design.js @@ -118,7 +118,7 @@ export default function ChangeDesign( { clientId } ) { ) } diff --git a/packages/block-editor/src/components/inserter-draggable-blocks/index.js b/packages/block-editor/src/components/inserter-draggable-blocks/index.js index 5a63535be3d3ce..0e1aaadc72e67b 100644 --- a/packages/block-editor/src/components/inserter-draggable-blocks/index.js +++ b/packages/block-editor/src/components/inserter-draggable-blocks/index.js @@ -29,6 +29,15 @@ const InserterDraggableBlocks = ( { blocks, }; + const blocksContainMedia = + blocks.filter( + ( block ) => + ( block.name === 'core/image' || + block.name === 'core/audio' || + block.name === 'core/video' ) && + ( block.attributes.url || block.attributes.src ) + ).length > 0; + const blockTypeIcon = useSelect( ( select ) => { const { getBlockType } = select( blocksStore ); @@ -63,7 +72,7 @@ const InserterDraggableBlocks = ( { ? [ createBlock( 'core/block', { ref: pattern.id } ) ] : blocks; event.dataTransfer.setData( - 'text/html', + blocksContainMedia ? 'default' : 'text/html', serialize( parsedBlocks ) ); } } diff --git a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js index 296b432bd685c3..8e5e50500ec72b 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js +++ b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js @@ -85,10 +85,10 @@ function PatternList( { return true; } if ( selectedCategory === 'uncategorized' ) { - const hasKnownCategory = pattern.categories.some( - ( category ) => + const hasKnownCategory = + pattern.categories?.some( ( category ) => registeredPatternCategories.includes( category ) - ); + ) ?? false; return ! pattern.categories?.length || ! hasKnownCategory; } 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 141ebf8cc84016..01e41111b7c890 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 @@ -79,7 +79,6 @@ function BlockPatternsTab( { onInsert={ onInsert } rootClientId={ rootClientId } category={ category } - showTitlesAsTooltip={ false } />
) } diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/utils.js b/packages/block-editor/src/components/inserter/block-patterns-tab/utils.js index 58065ac33ad2b5..7e2b71545e7969 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/utils.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/utils.js @@ -27,7 +27,7 @@ export const myPatternsCategory = { export const starterPatternsCategory = { name: 'core/starter-content', - label: __( 'Starter Content' ), + label: __( 'Starter content' ), }; export function isPatternFiltered( pattern, sourceFilter, syncFilter ) { diff --git a/packages/block-editor/src/components/inspector-controls/README.md b/packages/block-editor/src/components/inspector-controls/README.md index fd4847f53472b2..916f53b5f42d8b 100644 --- a/packages/block-editor/src/components/inspector-controls/README.md +++ b/packages/block-editor/src/components/inspector-controls/README.md @@ -116,6 +116,7 @@ registerBlockType( 'my-plugin/inspector-controls-example', { { diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index 07a3f8829e71d1..e7b6c836468f02 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -239,7 +239,7 @@ export function MediaPlaceholder( { ( block.name === 'core/image' || block.name === 'core/audio' || block.name === 'core/video' ) && - block.attributes.url + ( block.attributes.url || block.attributes.src ) ? [ block ] : recursivelyFindMediaFromBlocks( block.innerBlocks ) ); @@ -252,33 +252,37 @@ export function MediaPlaceholder( { } const uploadedMediaList = await Promise.all( - mediaBlocks.map( ( block ) => - block.attributes.id - ? block.attributes - : new Promise( ( resolve, reject ) => { - window - .fetch( block.attributes.url ) - .then( ( response ) => response.blob() ) - .then( ( blob ) => - mediaUpload( { - filesList: [ blob ], - additionalData: { - title: block.attributes.title, - alt_text: block.attributes.alt, - caption: block.attributes.caption, - }, - onFileChange: ( [ media ] ) => { - if ( media.id ) { - resolve( media ); - } - }, - allowedTypes, - onError: reject, - } ) - ) - .catch( () => resolve( block.attributes.url ) ); - } ) - ) + mediaBlocks.map( ( block ) => { + const blockType = block.name.split( '/' )[ 1 ]; + if ( block.attributes.id ) { + block.attributes.type = blockType; + return block.attributes; + } + return new Promise( ( resolve, reject ) => { + window + .fetch( block.attributes.url ) + .then( ( response ) => response.blob() ) + .then( ( blob ) => + mediaUpload( { + filesList: [ blob ], + additionalData: { + title: block.attributes.title, + alt_text: block.attributes.alt, + caption: block.attributes.caption, + type: blockType, + }, + onFileChange: ( [ media ] ) => { + if ( media.id ) { + resolve( media ); + } + }, + allowedTypes, + onError: reject, + } ) + ) + .catch( () => resolve( block.attributes.url ) ); + } ); + } ) ).catch( ( err ) => onError( err ) ); if ( multiple ) { @@ -288,8 +292,10 @@ export function MediaPlaceholder( { } } - async function onHTMLDrop( HTML ) { - const blocks = pasteHandler( { HTML } ); + async function onDrop( event ) { + const blocks = pasteHandler( { + HTML: event.dataTransfer?.getData( 'default' ), + } ); return await handleBlocksDrop( blocks ); } @@ -379,9 +385,7 @@ export function MediaPlaceholder( { return null; } - return ( - - ); + return ; }; const renderCancelLink = () => { diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index 8a5d99a7eb9f0a..8f179d08570ad1 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -233,7 +233,14 @@ export function RichTextWrapper( bindingsLabel: _bindingsLabel, }; }, - [ blockBindings, identifier, blockName, blockContext, adjustedValue ] + [ + blockBindings, + identifier, + blockName, + adjustedValue, + clientId, + blockContext, + ] ); const shouldDisableEditing = readOnly || disableBoundBlock; diff --git a/packages/block-editor/src/layouts/flex.js b/packages/block-editor/src/layouts/flex.js index 81718449695651..f57ccbde466169 100644 --- a/packages/block-editor/src/layouts/flex.js +++ b/packages/block-editor/src/layouts/flex.js @@ -66,24 +66,27 @@ export default { onChange, layoutBlockSupport = {}, } ) { - const { allowOrientation = true } = layoutBlockSupport; + const { allowOrientation = true, allowJustification = true } = + layoutBlockSupport; return ( <> - - - - - { allowOrientation && ( + { allowJustification && ( + + + + ) } + { allowOrientation && ( + - ) } - + + ) } @@ -94,17 +97,22 @@ export default { onChange, layoutBlockSupport, } ) { - if ( layoutBlockSupport?.allowSwitching ) { + const { allowVerticalAlignment = true, allowJustification = true } = + layoutBlockSupport; + + if ( ! allowJustification && ! allowVerticalAlignment ) { return null; } - const { allowVerticalAlignment = true } = layoutBlockSupport; + return ( - + { allowJustification && ( + + ) } { allowVerticalAlignment && ( { + categories: userPattern.wp_pattern_category?.map( ( catId ) => { const category = __experimentalUserPatternCategories.find( ( { id } ) => id === catId ); diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index 4b5cf59f81910d..cab58f72ff70ee 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 9.12.0 (2024-11-16) + ## 9.11.0 (2024-10-30) ## 9.10.0 (2024-10-16) diff --git a/packages/block-library/package.json b/packages/block-library/package.json index b196e53e5cd0f9..e507ef36367268 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-library", - "version": "9.11.0", + "version": "9.12.0", "description": "Block library for the WordPress editor.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-library/src/block-keyboard-shortcuts/index.js b/packages/block-library/src/block-keyboard-shortcuts/index.js index 6d9cde8364001f..2ce106b8ed99dc 100644 --- a/packages/block-library/src/block-keyboard-shortcuts/index.js +++ b/packages/block-library/src/block-keyboard-shortcuts/index.js @@ -90,22 +90,36 @@ function BlockKeyboardShortcuts() { }, } ); } ); - }, [] ); + }, [ registerShortcut ] ); 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 ) - ); - } ); + useShortcut( + 'core/block-editor/transform-paragraph-to-heading-1', + ( event ) => handleTransformHeadingAndParagraph( event, 1 ) + ); + useShortcut( + 'core/block-editor/transform-paragraph-to-heading-2', + ( event ) => handleTransformHeadingAndParagraph( event, 2 ) + ); + useShortcut( + 'core/block-editor/transform-paragraph-to-heading-3', + ( event ) => handleTransformHeadingAndParagraph( event, 3 ) + ); + useShortcut( + 'core/block-editor/transform-paragraph-to-heading-4', + ( event ) => handleTransformHeadingAndParagraph( event, 4 ) + ); + useShortcut( + 'core/block-editor/transform-paragraph-to-heading-5', + ( event ) => handleTransformHeadingAndParagraph( event, 5 ) + ); + useShortcut( + 'core/block-editor/transform-paragraph-to-heading-6', + ( event ) => handleTransformHeadingAndParagraph( event, 6 ) + ); return null; } diff --git a/packages/block-library/src/button/index.js b/packages/block-library/src/button/index.js index 2b05b280028abd..32212afc2eb706 100644 --- a/packages/block-library/src/button/index.js +++ b/packages/block-library/src/button/index.js @@ -22,7 +22,7 @@ export const settings = { example: { attributes: { className: 'is-style-fill', - text: __( 'Call to Action' ), + text: __( 'Call to action' ), }, }, edit, diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index 1c86d953bc0bab..3ad7039b558924 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -201,7 +201,7 @@ function CoverEdit( { averageBackgroundColor ); - if ( backgroundType === IMAGE_BACKGROUND_TYPE && mediaAttributes.id ) { + if ( backgroundType === IMAGE_BACKGROUND_TYPE && mediaAttributes?.id ) { const { imageDefaultSize } = getSettings(); // Try to use the previous selected image size if it's available diff --git a/packages/block-library/src/cover/shared.js b/packages/block-library/src/cover/shared.js index 37390354a37d63..7628300cbf8cff 100644 --- a/packages/block-library/src/cover/shared.js +++ b/packages/block-library/src/cover/shared.js @@ -35,7 +35,7 @@ export function dimRatioToClass( ratio ) { } export function attributesFromMedia( media ) { - if ( ! media || ! media.url ) { + if ( ! media || ( ! media.url && ! media.src ) ) { return { url: undefined, id: undefined, @@ -52,23 +52,23 @@ export function attributesFromMedia( media ) { if ( media.media_type === IMAGE_BACKGROUND_TYPE ) { mediaType = IMAGE_BACKGROUND_TYPE; } else { - // only images and videos are accepted so if the media_type is not an image we can assume it is a video. + // Only images and videos are accepted so if the media_type is not an image we can assume it is a video. // Videos contain the media type of 'file' in the object returned from the rest api. mediaType = VIDEO_BACKGROUND_TYPE; } - } else { // For media selections originated from existing files in the media library. - if ( - media.type !== IMAGE_BACKGROUND_TYPE && - media.type !== VIDEO_BACKGROUND_TYPE - ) { - return; - } + } else if ( + media.type && + ( media.type === IMAGE_BACKGROUND_TYPE || + media.type === VIDEO_BACKGROUND_TYPE ) + ) { mediaType = media.type; + } else { + return; } return { - url: media.url, + url: media.url || media.src, id: media.id, alt: media?.alt, backgroundType: mediaType, diff --git a/packages/block-library/src/media-text/style.scss b/packages/block-library/src/media-text/style.scss index 0f7a34f05548c0..727380a3759c6e 100644 --- a/packages/block-library/src/media-text/style.scss +++ b/packages/block-library/src/media-text/style.scss @@ -69,7 +69,7 @@ } .wp-block-media-text__media a { - display: inline-block; + display: block; } .wp-block-media-text__media img, diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index fa9bb5a56f8012..dd300eb12c6feb 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -344,6 +344,10 @@ private static function get_navigation_name( $attributes ) { $navigation_name = $attributes['ariaLabel'] ?? ''; + if ( ! empty( $navigation_name ) ) { + return $navigation_name; + } + // Load the navigation post. if ( array_key_exists( 'ref', $attributes ) ) { $navigation_post = get_post( $attributes['ref'] ); @@ -813,7 +817,7 @@ function block_core_navigation_add_directives_to_submenu( $tags, $block_attribut ) ) { // Add directives to the parent `
  • `. $tags->set_attribute( 'data-wp-interactive', 'core/navigation' ); - $tags->set_attribute( 'data-wp-context', '{ "submenuOpenedBy": { "click": false, "hover": false, "focus": false }, "type": "submenu" }' ); + $tags->set_attribute( 'data-wp-context', '{ "submenuOpenedBy": { "click": false, "hover": false, "focus": false }, "type": "submenu", "modal": null }' ); $tags->set_attribute( 'data-wp-watch', 'callbacks.initMenu' ); $tags->set_attribute( 'data-wp-on--focusout', 'actions.handleMenuFocusout' ); $tags->set_attribute( 'data-wp-on--keydown', 'actions.handleMenuKeydown' ); diff --git a/packages/block-library/src/page-list/block.json b/packages/block-library/src/page-list/block.json index b465e4ef5dc3d0..16a620dc177d7c 100644 --- a/packages/block-library/src/page-list/block.json +++ b/packages/block-library/src/page-list/block.json @@ -51,6 +51,20 @@ }, "interactivity": { "clientNavigation": true + }, + "__experimentalBorder": { + "radius": true, + "color": true, + "width": true, + "style": true + }, + "spacing": { + "padding": true, + "margin": true, + "__experimentalDefaultControls": { + "padding": false, + "margin": false + } } }, "editorStyle": "wp-block-page-list-editor", diff --git a/packages/block-library/src/page-list/style.scss b/packages/block-library/src/page-list/style.scss index d06a6142573bec..ab04d57e61b965 100644 --- a/packages/block-library/src/page-list/style.scss +++ b/packages/block-library/src/page-list/style.scss @@ -15,3 +15,7 @@ background-color: inherit; } } +.wp-block-page-list { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; +} diff --git a/packages/block-library/src/rss/index.php b/packages/block-library/src/rss/index.php index 32885863402d5e..85e4e63c9dbf7a 100644 --- a/packages/block-library/src/rss/index.php +++ b/packages/block-library/src/rss/index.php @@ -61,17 +61,20 @@ function render_block_core_rss( $attributes ) { $author = $item->get_author(); if ( is_object( $author ) ) { $author = $author->get_name(); - $author = '' . sprintf( - /* translators: byline. %s: author. */ - __( 'by %s' ), - esc_html( strip_tags( $author ) ) - ) . ''; + if ( ! empty( $author ) ) { + $author = '' . sprintf( + /* translators: byline. %s: author. */ + __( 'by %s' ), + esc_html( strip_tags( $author ) ) + ) . ''; + } } } - $excerpt = ''; - if ( $attributes['displayExcerpt'] ) { - $excerpt = html_entity_decode( $item->get_description(), ENT_QUOTES, get_option( 'blog_charset' ) ); + $excerpt = ''; + $description = $item->get_description(); + if ( $attributes['displayExcerpt'] && ! empty( $description ) ) { + $excerpt = html_entity_decode( $description, ENT_QUOTES, get_option( 'blog_charset' ) ); $excerpt = esc_attr( wp_trim_words( $excerpt, $attributes['excerptLength'], ' […]' ) ); // Change existing [...] to […]. diff --git a/packages/block-library/src/social-link/edit.js b/packages/block-library/src/social-link/edit.js index 47af181bfe17e8..14b0f11334a091 100644 --- a/packages/block-library/src/social-link/edit.js +++ b/packages/block-library/src/social-link/edit.js @@ -6,7 +6,7 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { DELETE, BACKSPACE } from '@wordpress/keycodes'; +import { DELETE, BACKSPACE, ENTER } from '@wordpress/keycodes'; import { useDispatch } from '@wordpress/data'; import { @@ -16,7 +16,7 @@ import { useBlockProps, store as blockEditorStore, } from '@wordpress/block-editor'; -import { useState } from '@wordpress/element'; +import { useState, useRef } from '@wordpress/element'; import { Button, PanelBody, @@ -24,6 +24,7 @@ import { TextControl, __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper, } from '@wordpress/components'; +import { useMergeRefs } from '@wordpress/compose'; import { __ } from '@wordpress/i18n'; import { keyboardReturn } from '@wordpress/icons'; @@ -112,12 +113,19 @@ const SocialLinkEdit = ( { iconBackgroundColorValue, } = context; const [ showURLPopover, setPopover ] = useState( false ); - const classes = clsx( 'wp-social-link', 'wp-social-link-' + service, { - 'wp-social-link__is-incomplete': ! url, - [ `has-${ iconColor }-color` ]: iconColor, - [ `has-${ iconBackgroundColor }-background-color` ]: - iconBackgroundColor, - } ); + const wrapperClasses = clsx( + 'wp-social-link', + // Manually adding this class for backwards compatibility of CSS when moving the + // blockProps from the li to the button: https://github.com/WordPress/gutenberg/pull/64883 + 'wp-block-social-link', + 'wp-social-link-' + service, + { + 'wp-social-link__is-incomplete': ! url, + [ `has-${ iconColor }-color` ]: iconColor, + [ `has-${ iconBackgroundColor }-background-color` ]: + iconBackgroundColor, + } + ); // Use internal state instead of a ref to make sure that the component // re-renders when the popover's anchor updates. @@ -131,11 +139,16 @@ const SocialLinkEdit = ( { // spaces. The PHP render callback fallbacks to the social name as well. const socialLinkText = label.trim() === '' ? socialLinkName : label; + const ref = useRef(); const blockProps = useBlockProps( { - className: classes, - style: { - color: iconColorValue, - backgroundColor: iconBackgroundColorValue, + className: 'wp-block-social-link-anchor', + ref: useMergeRefs( [ setPopoverAnchor, ref ] ), + onClick: () => setPopover( true ), + onKeyDown: ( event ) => { + if ( event.keyCode === ENTER ) { + event.preventDefault(); + setPopover( true ); + } }, } ); @@ -169,13 +182,27 @@ const SocialLinkEdit = ( { onChange={ ( value ) => setAttributes( { rel: value } ) } /> -
  • - + { /* eslint-enable jsx-a11y/no-redundant-roles */ } { isSelected && showURLPopover && ( ); diff --git a/packages/block-serialization-default-parser/CHANGELOG.md b/packages/block-serialization-default-parser/CHANGELOG.md index 5911f22795d463..5542b052e1037a 100644 --- a/packages/block-serialization-default-parser/CHANGELOG.md +++ b/packages/block-serialization-default-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/block-serialization-default-parser/package.json b/packages/block-serialization-default-parser/package.json index 010132ac971db1..a448804ae9ba8c 100644 --- a/packages/block-serialization-default-parser/package.json +++ b/packages/block-serialization-default-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-default-parser", - "version": "5.11.0", + "version": "5.12.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/block-serialization-spec-parser/CHANGELOG.md b/packages/block-serialization-spec-parser/CHANGELOG.md index 1833dff1e52c83..3ff70ac28cc19b 100644 --- a/packages/block-serialization-spec-parser/CHANGELOG.md +++ b/packages/block-serialization-spec-parser/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/block-serialization-spec-parser/package.json b/packages/block-serialization-spec-parser/package.json index d430d2afeebf5a..30aa5679a7c01a 100644 --- a/packages/block-serialization-spec-parser/package.json +++ b/packages/block-serialization-spec-parser/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/block-serialization-spec-parser", - "version": "5.11.0", + "version": "5.12.0", "description": "Block serialization specification parser for WordPress posts.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 54fc6f77a7427d..216918b44c0b80 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 14.1.0 (2024-11-16) + ## 14.0.0 (2024-10-30) ### Breaking changes diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 42890e9b7d56bc..15102734ff34f1 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/blocks", - "version": "14.0.0", + "version": "14.1.0", "description": "Block API for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/browserslist-config/CHANGELOG.md b/packages/browserslist-config/CHANGELOG.md index 1ef626d40ef832..64a49c04621840 100644 --- a/packages/browserslist-config/CHANGELOG.md +++ b/packages/browserslist-config/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ## 6.11.0 (2024-10-30) ## 6.10.0 (2024-10-16) diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 65bc5231f0651b..f5b60a9bb7e783 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/browserslist-config", - "version": "6.11.0", + "version": "6.12.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 2ec9f745b774fd..e1e995f9710aeb 100644 --- a/packages/commands/CHANGELOG.md +++ b/packages/commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.12.0 (2024-11-16) + ## 1.11.0 (2024-10-30) ## 1.10.0 (2024-10-16) diff --git a/packages/commands/package.json b/packages/commands/package.json index cebf3237a00d75..0f252c5e90ade3 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/commands", - "version": "1.11.0", + "version": "1.12.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 abd32b37c4c650..d93eb30ac0ec50 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -4,6 +4,26 @@ ### Deprecations +- `DimensionControl`: Deprecate 36px default size ([#66705](https://github.com/WordPress/gutenberg/pull/66705)). +- `TextControl`: Deprecate 36px default size ([#66745](https://github.com/WordPress/gutenberg/pull/66745). + +### Bug Fixes + +- `ToggleGroupControl`: Fix active background for `0` value ([#66855](https://github.com/WordPress/gutenberg/pull/66855)). +- `SlotFill`: Fix a bug where a stale value of `fillProps` could be used ([#67000](https://github.com/WordPress/gutenberg/pull/67000)). + +### Experimental + +- `SlotFill`: Remove registration API methods from return value of `__experimentalUseSlot` ([#67070](https://github.com/WordPress/gutenberg/pull/67070)). + +### Internal + +- `SlotFill`: fix dependencies of `Fill` registration effects ([#67071](https://github.com/WordPress/gutenberg/pull/67071)). + +## 28.12.0 (2024-11-16) + +### Deprecations + - `Radio`: Deprecate 36px default size ([#66572](https://github.com/WordPress/gutenberg/pull/66572)). ### Bug Fixes diff --git a/packages/components/package.json b/packages/components/package.json index 6871511cf5b1e5..b297b31e544f98 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/components", - "version": "28.11.0", + "version": "28.12.0", "description": "UI components for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/components/src/base-control/stories/index.story.tsx b/packages/components/src/base-control/stories/index.story.tsx index ca35b793621577..90517c75b5e95e 100644 --- a/packages/components/src/base-control/stories/index.story.tsx +++ b/packages/components/src/base-control/stories/index.story.tsx @@ -10,7 +10,8 @@ import BaseControl, { useBaseControlProps } from '..'; import Button from '../../button'; const meta: Meta< typeof BaseControl > = { - title: 'Components/BaseControl', + title: 'Components/Selection & Input/Common/BaseControl', + id: 'components-basecontrol', component: BaseControl, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 diff --git a/packages/components/src/checkbox-control/stories/index.story.tsx b/packages/components/src/checkbox-control/stories/index.story.tsx index 3c55ba3192a3cf..a68e380a8f7332 100644 --- a/packages/components/src/checkbox-control/stories/index.story.tsx +++ b/packages/components/src/checkbox-control/stories/index.story.tsx @@ -17,7 +17,8 @@ import { HStack } from '../../h-stack'; const meta: Meta< typeof CheckboxControl > = { component: CheckboxControl, - title: 'Components/CheckboxControl', + title: 'Components/Selection & Input/Common/CheckboxControl', + id: 'components-checkboxcontrol', argTypes: { onChange: { action: 'onChange', diff --git a/packages/components/src/circular-option-picker/stories/index.story.tsx b/packages/components/src/circular-option-picker/stories/index.story.tsx index e091a2ac54d41e..d0314670fe1694 100644 --- a/packages/components/src/circular-option-picker/stories/index.story.tsx +++ b/packages/components/src/circular-option-picker/stories/index.story.tsx @@ -17,7 +17,8 @@ const CircularOptionPickerStoryContext = createContext< { } >( {} ); const meta: Meta< typeof CircularOptionPicker > = { - title: 'Components/CircularOptionPicker', + title: 'Components/Selection & Input/Color/CircularOptionPicker', + id: 'components-circularoptionpicker', component: CircularOptionPicker, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 diff --git a/packages/components/src/color-indicator/stories/index.story.tsx b/packages/components/src/color-indicator/stories/index.story.tsx index 8a2557f30659e0..c24c26f5e844b3 100644 --- a/packages/components/src/color-indicator/stories/index.story.tsx +++ b/packages/components/src/color-indicator/stories/index.story.tsx @@ -10,7 +10,8 @@ import ColorIndicator from '..'; const meta: Meta< typeof ColorIndicator > = { component: ColorIndicator, - title: 'Components/ColorIndicator', + title: 'Components/Selection & Input/Color/ColorIndicator', + id: 'components-colorindicator', argTypes: { colorValue: { control: { type: 'color' }, diff --git a/packages/components/src/color-palette/stories/index.story.tsx b/packages/components/src/color-palette/stories/index.story.tsx index 727e840ff99358..5342fc5222be6a 100644 --- a/packages/components/src/color-palette/stories/index.story.tsx +++ b/packages/components/src/color-palette/stories/index.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import ColorPalette from '..'; const meta: Meta< typeof ColorPalette > = { - title: 'Components/ColorPalette', + title: 'Components/Selection & Input/Color/ColorPalette', + id: 'components-colorpalette', component: ColorPalette, argTypes: { as: { control: { type: null } }, diff --git a/packages/components/src/color-picker/stories/index.story.tsx b/packages/components/src/color-picker/stories/index.story.tsx index 9f2198515db1e6..44040a5265c5d3 100644 --- a/packages/components/src/color-picker/stories/index.story.tsx +++ b/packages/components/src/color-picker/stories/index.story.tsx @@ -10,7 +10,8 @@ import { ColorPicker } from '../component'; const meta: Meta< typeof ColorPicker > = { component: ColorPicker, - title: 'Components/ColorPicker', + title: 'Components/Selection & Input/Color/ColorPicker', + id: 'components-colorpicker', argTypes: { as: { control: { type: null } }, color: { control: { type: null } }, diff --git a/packages/components/src/combobox-control/stories/index.story.tsx b/packages/components/src/combobox-control/stories/index.story.tsx index 516cd262fd5aa6..954f0d96fb0d76 100644 --- a/packages/components/src/combobox-control/stories/index.story.tsx +++ b/packages/components/src/combobox-control/stories/index.story.tsx @@ -34,7 +34,8 @@ const countries = [ ]; const meta: Meta< typeof ComboboxControl > = { - title: 'Components/ComboboxControl', + title: 'Components/Selection & Input/Common/ComboboxControl', + id: 'components-comboboxcontrol', component: ComboboxControl, argTypes: { value: { control: { type: null } }, diff --git a/packages/components/src/confirm-dialog/stories/index.story.tsx b/packages/components/src/confirm-dialog/stories/index.story.tsx index 85636c0ddc81ed..9496d85939edf3 100644 --- a/packages/components/src/confirm-dialog/stories/index.story.tsx +++ b/packages/components/src/confirm-dialog/stories/index.story.tsx @@ -16,7 +16,8 @@ import { ConfirmDialog } from '../component'; const meta: Meta< typeof ConfirmDialog > = { component: ConfirmDialog, - title: 'Components (Experimental)/ConfirmDialog', + title: 'Components (Experimental)/Overlays/ConfirmDialog', + id: 'components-experimental-confirmdialog', argTypes: { isOpen: { control: { type: null }, diff --git a/packages/components/src/custom-gradient-picker/stories/index.story.tsx b/packages/components/src/custom-gradient-picker/stories/index.story.tsx index 3be8eb36e5a3c2..23d5239e5d240d 100644 --- a/packages/components/src/custom-gradient-picker/stories/index.story.tsx +++ b/packages/components/src/custom-gradient-picker/stories/index.story.tsx @@ -13,7 +13,8 @@ import { useState } from '@wordpress/element'; import CustomGradientPicker from '../'; const meta: Meta< typeof CustomGradientPicker > = { - title: 'Components/CustomGradientPicker', + title: 'Components/Selection & Input/Color/CustomGradientPicker', + id: 'components-customgradientpicker', component: CustomGradientPicker, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/custom-select-control-v2/stories/index.story.tsx b/packages/components/src/custom-select-control-v2/stories/index.story.tsx index a3324a5fa03a47..3595ee2e951990 100644 --- a/packages/components/src/custom-select-control-v2/stories/index.story.tsx +++ b/packages/components/src/custom-select-control-v2/stories/index.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import CustomSelectControlV2 from '..'; const meta: Meta< typeof CustomSelectControlV2 > = { - title: 'Components/CustomSelectControl v2', + title: 'Components/Selection & Input/Common/CustomSelectControl v2', + id: 'components-customselectcontrol-v2', component: CustomSelectControlV2, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 diff --git a/packages/components/src/date-time/stories/date-time.story.tsx b/packages/components/src/date-time/stories/date-time.story.tsx index 86a627bbec35e0..7636e2fdc80a30 100644 --- a/packages/components/src/date-time/stories/date-time.story.tsx +++ b/packages/components/src/date-time/stories/date-time.story.tsx @@ -15,7 +15,8 @@ import DateTimePicker from '../date-time'; import { daysFromNow, isWeekend } from './utils'; const meta: Meta< typeof DateTimePicker > = { - title: 'Components/DateTimePicker', + title: 'Components/Selection & Input/Time & Date/DateTimePicker', + id: 'components-datetimepicker', component: DateTimePicker, argTypes: { currentDate: { control: 'date' }, diff --git a/packages/components/src/date-time/stories/date.story.tsx b/packages/components/src/date-time/stories/date.story.tsx index 8d1513d014c8c8..36fef0c5bfd195 100644 --- a/packages/components/src/date-time/stories/date.story.tsx +++ b/packages/components/src/date-time/stories/date.story.tsx @@ -15,7 +15,8 @@ import DatePicker from '../date'; import { daysFromNow, isWeekend } from './utils'; const meta: Meta< typeof DatePicker > = { - title: 'Components/DatePicker', + title: 'Components/Selection & Input/Time & Date/DatePicker', + id: 'components-datepicker', component: DatePicker, argTypes: { currentDate: { control: 'date' }, diff --git a/packages/components/src/date-time/stories/time.story.tsx b/packages/components/src/date-time/stories/time.story.tsx index 947b5bd64d5eb1..c19b5b4f48f5c2 100644 --- a/packages/components/src/date-time/stories/time.story.tsx +++ b/packages/components/src/date-time/stories/time.story.tsx @@ -14,7 +14,8 @@ import { useState, useEffect } from '@wordpress/element'; import TimePicker from '../time'; const meta: Meta< typeof TimePicker > = { - title: 'Components/TimePicker', + title: 'Components/Selection & Input/Time & Date/TimePicker', + id: 'components-timepicker', component: TimePicker, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { 'TimePicker.TimeInput': TimePicker.TimeInput }, diff --git a/packages/components/src/dimension-control/README.md b/packages/components/src/dimension-control/README.md index 78c1a60275c13a..fd04d99ca4ca93 100644 --- a/packages/components/src/dimension-control/README.md +++ b/packages/components/src/dimension-control/README.md @@ -22,6 +22,7 @@ export default function MyCustomDimensionControl() { return ( setPaddingSize( value ) } diff --git a/packages/components/src/dimension-control/index.tsx b/packages/components/src/dimension-control/index.tsx index 25880f9b4fdb38..2cc39379ebde0c 100644 --- a/packages/components/src/dimension-control/index.tsx +++ b/packages/components/src/dimension-control/index.tsx @@ -18,6 +18,7 @@ import type { DimensionControlProps, Size } from './types'; import type { SelectControlSingleSelectionProps } from '../select-control/types'; import { ContextSystemProvider } from '../context'; import deprecated from '@wordpress/deprecated'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; const CONTEXT_VALUE = { BaseControl: { @@ -41,6 +42,7 @@ const CONTEXT_VALUE = { * * return ( * { const theSize = findSizeBySlug( sizes, val ); diff --git a/packages/components/src/dimension-control/stories/index.story.tsx b/packages/components/src/dimension-control/stories/index.story.tsx index 15a63fcf6ccf6c..61fd0aae4ee768 100644 --- a/packages/components/src/dimension-control/stories/index.story.tsx +++ b/packages/components/src/dimension-control/stories/index.story.tsx @@ -50,6 +50,7 @@ const Template: StoryFn< typeof DimensionControl > = ( args ) => ( export const Default = Template.bind( {} ); Default.args = { __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, label: 'Please select a size', sizes, }; 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 bd2c26d641fe72..fd6cc2df3fcde7 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 @@ -126,12 +126,12 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = ` white-space: nowrap; text-overflow: ellipsis; font-size: 16px; - height: 32px; - min-height: 32px; + height: 40px; + min-height: 40px; padding-top: 0; padding-bottom: 0; - padding-left: 8px; - padding-right: 26px; + padding-left: 12px; + padding-right: 30px; overflow: hidden; } @@ -157,8 +157,8 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = ` } .emotion-21 { - -webkit-padding-end: 8px; - padding-inline-end: 8px; + -webkit-padding-end: 12px; + padding-inline-end: 12px; position: absolute; pointer-events: none; right: 0; @@ -408,12 +408,12 @@ exports[`DimensionControl rendering renders with defaults 1`] = ` white-space: nowrap; text-overflow: ellipsis; font-size: 16px; - height: 32px; - min-height: 32px; + height: 40px; + min-height: 40px; padding-top: 0; padding-bottom: 0; - padding-left: 8px; - padding-right: 26px; + padding-left: 12px; + padding-right: 30px; overflow: hidden; } @@ -439,8 +439,8 @@ exports[`DimensionControl rendering renders with defaults 1`] = ` } .emotion-21 { - -webkit-padding-end: 8px; - padding-inline-end: 8px; + -webkit-padding-end: 12px; + padding-inline-end: 12px; position: absolute; pointer-events: none; right: 0; @@ -700,12 +700,12 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`] white-space: nowrap; text-overflow: ellipsis; font-size: 16px; - height: 32px; - min-height: 32px; + height: 40px; + min-height: 40px; padding-top: 0; padding-bottom: 0; - padding-left: 8px; - padding-right: 26px; + padding-left: 12px; + padding-right: 30px; overflow: hidden; } @@ -731,8 +731,8 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`] } .emotion-21 { - -webkit-padding-end: 8px; - padding-inline-end: 8px; + -webkit-padding-end: 12px; + padding-inline-end: 12px; position: absolute; pointer-events: none; right: 0; @@ -1004,12 +1004,12 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`] white-space: nowrap; text-overflow: ellipsis; font-size: 16px; - height: 32px; - min-height: 32px; + height: 40px; + min-height: 40px; padding-top: 0; padding-bottom: 0; - padding-left: 8px; - padding-right: 26px; + padding-left: 12px; + padding-right: 30px; overflow: hidden; } @@ -1035,8 +1035,8 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`] } .emotion-21 { - -webkit-padding-end: 8px; - padding-inline-end: 8px; + -webkit-padding-end: 12px; + padding-inline-end: 12px; position: absolute; pointer-events: none; right: 0; diff --git a/packages/components/src/dimension-control/test/index.test.js b/packages/components/src/dimension-control/test/index.test.js index 14f1c509f70cf9..8f3cb7ea944cd1 100644 --- a/packages/components/src/dimension-control/test/index.test.js +++ b/packages/components/src/dimension-control/test/index.test.js @@ -15,7 +15,13 @@ import { plus } from '@wordpress/icons'; import { DimensionControl as _DimensionControl } from '../'; const DimensionControl = ( props ) => { - return <_DimensionControl { ...props } __nextHasNoMarginBottom />; + return ( + <_DimensionControl + { ...props } + __next40pxDefaultSize + __nextHasNoMarginBottom + /> + ); }; describe( 'DimensionControl', () => { diff --git a/packages/components/src/disabled/README.md b/packages/components/src/disabled/README.md index 9b257acd0f737b..e9eb6398554d9d 100644 --- a/packages/components/src/disabled/README.md +++ b/packages/components/src/disabled/README.md @@ -13,7 +13,14 @@ import { Button, Disabled, TextControl } from '@wordpress/components'; const MyDisabled = () => { const [ isDisabled, setIsDisabled ] = useState( true ); - let input = {} } />; + let input = ( + {} } + /> + ); if ( isDisabled ) { input = { input }; } @@ -38,12 +45,7 @@ A component can detect if it has been wrapped in a `` by accessing i ```jsx function CustomButton( props ) { const isDisabled = useContext( Disabled.Context ); - return ( -
  • ); -} +}; ``` diff --git a/packages/components/src/higher-order/with-focus-return/README.md b/packages/components/src/higher-order/with-focus-return/README.md index b99d76bc6f1c9a..81cecad4310f11 100644 --- a/packages/components/src/higher-order/with-focus-return/README.md +++ b/packages/components/src/higher-order/with-focus-return/README.md @@ -13,7 +13,12 @@ import { withFocusReturn, TextControl, Button } from '@wordpress/components'; const EnhancedComponent = withFocusReturn( () => (
    Focus will return to the previous input when this component is unmounted - {} } /> + {} } + />
    ) ); @@ -27,6 +32,8 @@ const MyComponentWithFocusReturn = () => { return (
    setText( value ) } @@ -39,7 +46,7 @@ const MyComponentWithFocusReturn = () => { ) }
    ); -} +}; ``` `withFocusReturn` can optionally be called as a higher-order function creator. Provided an options object, a new higher-order function is returned. diff --git a/packages/components/src/input-control/stories/index.story.tsx b/packages/components/src/input-control/stories/index.story.tsx index 1a9290e8e856ea..8cef6a5d37c81b 100644 --- a/packages/components/src/input-control/stories/index.story.tsx +++ b/packages/components/src/input-control/stories/index.story.tsx @@ -16,7 +16,8 @@ import { InputControlSuffixWrapper } from '../input-suffix-wrapper'; import Button from '../../button'; const meta: Meta< typeof InputControl > = { - title: 'Components (Experimental)/InputControl', + title: 'Components (Experimental)/Selection & Input/InputControl', + id: 'components-experimental-inputcontrol', component: InputControl, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { InputControlPrefixWrapper, InputControlSuffixWrapper }, diff --git a/packages/components/src/menu/stories/index.story.tsx b/packages/components/src/menu/stories/index.story.tsx index ecb4cc3c7593f8..92501c33269580 100644 --- a/packages/components/src/menu/stories/index.story.tsx +++ b/packages/components/src/menu/stories/index.story.tsx @@ -22,7 +22,8 @@ import { createSlotFill, Provider as SlotFillProvider } from '../../slot-fill'; import { ContextSystemProvider } from '../../context'; const meta: Meta< typeof Menu > = { - title: 'Components (Experimental)/Menu', + id: 'components-experimental-menu', + title: 'Components (Experimental)/Actions/Menu', component: Menu, subcomponents: { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 diff --git a/packages/components/src/modal/stories/index.story.tsx b/packages/components/src/modal/stories/index.story.tsx index f180de0dc06a46..92c922bcb8a977 100644 --- a/packages/components/src/modal/stories/index.story.tsx +++ b/packages/components/src/modal/stories/index.story.tsx @@ -19,7 +19,8 @@ import type { ModalProps } from '../types'; const meta: Meta< typeof Modal > = { component: Modal, - title: 'Components/Modal', + title: 'Components/Overlays/Modal', + id: 'components-modal', argTypes: { children: { control: { type: null }, diff --git a/packages/components/src/number-control/stories/index.story.tsx b/packages/components/src/number-control/stories/index.story.tsx index 3588063f0f4bb2..3feb0d63eadc2a 100644 --- a/packages/components/src/number-control/stories/index.story.tsx +++ b/packages/components/src/number-control/stories/index.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import NumberControl from '..'; const meta: Meta< typeof NumberControl > = { - title: 'Components (Experimental)/NumberControl', + title: 'Components (Experimental)/Selection & Input/NumberControl', + id: 'components-experimental-numbercontrol', component: NumberControl, argTypes: { onChange: { action: 'onChange' }, diff --git a/packages/components/src/placeholder/stories/index.story.tsx b/packages/components/src/placeholder/stories/index.story.tsx index 541eeceedc27d4..1a0db673320bca 100644 --- a/packages/components/src/placeholder/stories/index.story.tsx +++ b/packages/components/src/placeholder/stories/index.story.tsx @@ -45,6 +45,7 @@ const Template: StoryFn< typeof Placeholder > = ( args ) => {
    = { - title: 'Components/Popover', + title: 'Components/Overlays/Popover', + id: 'components-popover', component: Popover, argTypes: { anchor: { control: { type: null } }, diff --git a/packages/components/src/radio-control/stories/index.story.tsx b/packages/components/src/radio-control/stories/index.story.tsx index dae00e57962f47..3c76f7610d0d79 100644 --- a/packages/components/src/radio-control/stories/index.story.tsx +++ b/packages/components/src/radio-control/stories/index.story.tsx @@ -15,7 +15,8 @@ import RadioControl from '..'; const meta: Meta< typeof RadioControl > = { component: RadioControl, - title: 'Components/RadioControl', + title: 'Components/Selection & Input/Common/RadioControl', + id: 'components-radiocontrol', argTypes: { onChange: { action: 'onChange', diff --git a/packages/components/src/range-control/stories/index.story.tsx b/packages/components/src/range-control/stories/index.story.tsx index 7775c364195722..dcff3513733527 100644 --- a/packages/components/src/range-control/stories/index.story.tsx +++ b/packages/components/src/range-control/stories/index.story.tsx @@ -18,7 +18,8 @@ const ICONS = { starEmpty, starFilled, styles, wordpress }; const meta: Meta< typeof RangeControl > = { component: RangeControl, - title: 'Components/RangeControl', + title: 'Components/Selection & Input/Common/RangeControl', + id: 'components-rangecontrol', argTypes: { afterIcon: { control: { type: 'select' }, diff --git a/packages/components/src/responsive-wrapper/stories/index.story.tsx b/packages/components/src/responsive-wrapper/stories/index.story.tsx index cf676c3bcec801..d684a00c870028 100644 --- a/packages/components/src/responsive-wrapper/stories/index.story.tsx +++ b/packages/components/src/responsive-wrapper/stories/index.story.tsx @@ -10,7 +10,8 @@ import ResponsiveWrapper from '..'; const meta: Meta< typeof ResponsiveWrapper > = { component: ResponsiveWrapper, - title: 'Components/ResponsiveWrapper', + title: 'Components/Layout/ResponsiveWrapper', + id: 'components-responsivewrapper', argTypes: { children: { control: { type: null } }, }, diff --git a/packages/components/src/search-control/stories/index.story.tsx b/packages/components/src/search-control/stories/index.story.tsx index 59618dd7e0913b..5e5f6b594e73e7 100644 --- a/packages/components/src/search-control/stories/index.story.tsx +++ b/packages/components/src/search-control/stories/index.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import SearchControl from '..'; const meta: Meta< typeof SearchControl > = { - title: 'Components/SearchControl', + title: 'Components/Selection & Input/Common/SearchControl', + id: 'components-searchcontrol', component: SearchControl, argTypes: { onChange: { action: 'onChange' }, diff --git a/packages/components/src/select-control/stories/index.story.tsx b/packages/components/src/select-control/stories/index.story.tsx index 5e57a4eaecd5ab..e9461ef6904f6f 100644 --- a/packages/components/src/select-control/stories/index.story.tsx +++ b/packages/components/src/select-control/stories/index.story.tsx @@ -15,7 +15,8 @@ import SelectControl from '../'; import { InputControlPrefixWrapper } from '../../input-control/input-prefix-wrapper'; const meta: Meta< typeof SelectControl > = { - title: 'Components/SelectControl', + title: 'Components/Selection & Input/Common/SelectControl', + id: 'components-selectcontrol', component: SelectControl, argTypes: { help: { control: { type: 'text' } }, diff --git a/packages/components/src/slot-fill/bubbles-virtually/fill.tsx b/packages/components/src/slot-fill/bubbles-virtually/fill.tsx index 3cfadbadc62c4b..b1b82aac5c0567 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/fill.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/fill.tsx @@ -1,12 +1,19 @@ /** * WordPress dependencies */ -import { useRef, useState, useEffect, createPortal } from '@wordpress/element'; +import { useObservableValue } from '@wordpress/compose'; +import { + useContext, + useRef, + useState, + useEffect, + createPortal, +} from '@wordpress/element'; /** * Internal dependencies */ -import useSlot from './use-slot'; +import SlotFillContext from './slot-fill-context'; import StyleProvider from '../../style-provider'; import type { FillComponentProps } from '../types'; @@ -28,9 +35,9 @@ function useForceUpdate() { }; } -export default function Fill( props: FillComponentProps ) { - const { name, children } = props; - const { registerFill, unregisterFill, ...slot } = useSlot( name ); +export default function Fill( { name, children }: FillComponentProps ) { + const registry = useContext( SlotFillContext ); + const slot = useObservableValue( registry.slots, name ); const rerender = useForceUpdate(); const ref = useRef( { rerender } ); @@ -38,13 +45,13 @@ export default function Fill( props: FillComponentProps ) { // We register fills so we can keep track of their existence. // Some Slot implementations need to know if there're already fills // registered so they can choose to render themselves or not. - registerFill( ref ); + registry.registerFill( name, ref ); return () => { - unregisterFill( ref ); + registry.unregisterFill( name, ref ); }; - }, [ registerFill, unregisterFill ] ); + }, [ registry, name ] ); - if ( ! slot.ref || ! slot.ref.current ) { + if ( ! slot || ! slot.ref.current ) { return null; } diff --git a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx index 4d68db6fd175ee..16a19c6569fda6 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx @@ -34,15 +34,23 @@ function createSlotRegistry(): SlotFillBubblesVirtuallyContext { const unregisterSlot: SlotFillBubblesVirtuallyContext[ 'unregisterSlot' ] = ( name, ref ) => { + const slot = slots.get( name ); + if ( ! slot ) { + return; + } + // Make sure we're not unregistering a slot registered by another element // See https://github.com/WordPress/gutenberg/pull/19242#issuecomment-590295412 - if ( slots.get( name )?.ref === ref ) { - slots.delete( name ); + if ( slot.ref !== ref ) { + return; } + + slots.delete( name ); }; const updateSlot: SlotFillBubblesVirtuallyContext[ 'updateSlot' ] = ( name, + ref, fillProps ) => { const slot = slots.get( name ); @@ -50,6 +58,10 @@ function createSlotRegistry(): SlotFillBubblesVirtuallyContext { return; } + if ( slot.ref !== ref ) { + return; + } + if ( isShallowEqual( slot.fillProps, fillProps ) ) { return; } @@ -69,20 +81,18 @@ function createSlotRegistry(): SlotFillBubblesVirtuallyContext { fills.set( name, [ ...( fills.get( name ) || [] ), ref ] ); }; - const unregisterFill: SlotFillBubblesVirtuallyContext[ 'registerFill' ] = ( - name, - ref - ) => { - const fillsForName = fills.get( name ); - if ( ! fillsForName ) { - return; - } + const unregisterFill: SlotFillBubblesVirtuallyContext[ 'unregisterFill' ] = + ( name, ref ) => { + const fillsForName = fills.get( name ); + if ( ! fillsForName ) { + return; + } - fills.set( - name, - fillsForName.filter( ( fillRef ) => fillRef !== ref ) - ); - }; + fills.set( + name, + fillsForName.filter( ( fillRef ) => fillRef !== ref ) + ); + }; return { slots, diff --git a/packages/components/src/slot-fill/bubbles-virtually/slot.tsx b/packages/components/src/slot-fill/bubbles-virtually/slot.tsx index 6ac2d51e1f857f..b8ead7fc7ea8ba 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/slot.tsx +++ b/packages/components/src/slot-fill/bubbles-virtually/slot.tsx @@ -35,29 +35,33 @@ function Slot( as, // `children` is not allowed. However, if it is passed, // it will be displayed as is, so remove `children`. - // @ts-ignore children, ...restProps } = props; const { registerSlot, unregisterSlot, ...registry } = useContext( SlotFillContext ); + const ref = useRef< HTMLElement >( null ); + // We don't want to unregister and register the slot whenever + // `fillProps` change, which would cause the fill to be re-mounted. Instead, + // we can just update the slot (see hook below). + // For more context, see https://github.com/WordPress/gutenberg/pull/44403#discussion_r994415973 + const fillPropsRef = useRef( fillProps ); + useLayoutEffect( () => { + fillPropsRef.current = fillProps; + }, [ fillProps ] ); + useLayoutEffect( () => { - registerSlot( name, ref, fillProps ); + registerSlot( name, ref, fillPropsRef.current ); return () => { unregisterSlot( name, ref ); }; - // We don't want to unregister and register the slot whenever - // `fillProps` change, which would cause the fill to be re-mounted. Instead, - // we can just update the slot (see hook below). - // For more context, see https://github.com/WordPress/gutenberg/pull/44403#discussion_r994415973 }, [ registerSlot, unregisterSlot, name ] ); - // fillProps may be an update that interacts with the layout, so we - // useLayoutEffect. + useLayoutEffect( () => { - registry.updateSlot( name, fillProps ); + registry.updateSlot( name, ref, fillPropsRef.current ); } ); return ( diff --git a/packages/components/src/slot-fill/bubbles-virtually/use-slot.ts b/packages/components/src/slot-fill/bubbles-virtually/use-slot.ts index d1d37e1d8e541c..cac57a024e4ee2 100644 --- a/packages/components/src/slot-fill/bubbles-virtually/use-slot.ts +++ b/packages/components/src/slot-fill/bubbles-virtually/use-slot.ts @@ -1,40 +1,17 @@ /** * WordPress dependencies */ -import { useMemo, useContext } from '@wordpress/element'; +import { useContext } from '@wordpress/element'; import { useObservableValue } from '@wordpress/compose'; /** * Internal dependencies */ import SlotFillContext from './slot-fill-context'; -import type { - SlotFillBubblesVirtuallyFillRef, - SlotFillBubblesVirtuallySlotRef, - FillProps, - SlotKey, -} from '../types'; +import type { SlotKey } from '../types'; export default function useSlot( name: SlotKey ) { const registry = useContext( SlotFillContext ); const slot = useObservableValue( registry.slots, name ); - - const api = useMemo( - () => ( { - updateSlot: ( fillProps: FillProps ) => - registry.updateSlot( name, fillProps ), - unregisterSlot: ( ref: SlotFillBubblesVirtuallySlotRef ) => - registry.unregisterSlot( name, ref ), - registerFill: ( ref: SlotFillBubblesVirtuallyFillRef ) => - registry.registerFill( name, ref ), - unregisterFill: ( ref: SlotFillBubblesVirtuallyFillRef ) => - registry.unregisterFill( name, ref ), - } ), - [ name, registry ] - ); - - return { - ...slot, - ...api, - }; + return { ...slot }; } diff --git a/packages/components/src/slot-fill/fill.ts b/packages/components/src/slot-fill/fill.ts index 4134af25684b07..b11b7af09b82f0 100644 --- a/packages/components/src/slot-fill/fill.ts +++ b/packages/components/src/slot-fill/fill.ts @@ -11,7 +11,7 @@ import useSlot from './use-slot'; import type { FillComponentProps } from './types'; export default function Fill( { name, children }: FillComponentProps ) { - const { registerFill, unregisterFill } = useContext( SlotFillContext ); + const registry = useContext( SlotFillContext ); const slot = useSlot( name ); const ref = useRef( { @@ -21,32 +21,17 @@ export default function Fill( { name, children }: FillComponentProps ) { useLayoutEffect( () => { const refValue = ref.current; - registerFill( name, refValue ); - return () => unregisterFill( name, refValue ); - // The useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior. - // We'll leave them as-is until a more detailed investigation/refactor can be performed. - }, [] ); + refValue.name = name; + registry.registerFill( name, refValue ); + return () => registry.unregisterFill( name, refValue ); + }, [ registry, name ] ); useLayoutEffect( () => { ref.current.children = children; if ( slot ) { slot.forceUpdate(); } - // The useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior. - // We'll leave them as-is until a more detailed investigation/refactor can be performed. - }, [ children ] ); - - useLayoutEffect( () => { - if ( name === ref.current.name ) { - // Ignore initial effect. - return; - } - unregisterFill( ref.current.name, ref.current ); - ref.current.name = name; - registerFill( name, ref.current ); - // The useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior. - // We'll leave them as-is until a more detailed investigation/refactor can be performed. - }, [ name ] ); + }, [ slot, children ] ); return null; } diff --git a/packages/components/src/slot-fill/types.ts b/packages/components/src/slot-fill/types.ts index 1711e04cbb1f47..7e1b8b7e1f3f9f 100644 --- a/packages/components/src/slot-fill/types.ts +++ b/packages/components/src/slot-fill/types.ts @@ -131,7 +131,11 @@ export type SlotFillBubblesVirtuallyContext = { name: SlotKey, ref: SlotFillBubblesVirtuallySlotRef ) => void; - updateSlot: ( name: SlotKey, fillProps: FillProps ) => void; + updateSlot: ( + name: SlotKey, + ref: SlotFillBubblesVirtuallySlotRef, + fillProps: FillProps + ) => void; registerFill: ( name: SlotKey, ref: SlotFillBubblesVirtuallyFillRef diff --git a/packages/components/src/text-control/README.md b/packages/components/src/text-control/README.md index 0b6e2d4ebc684e..80f3145a4325b3 100644 --- a/packages/components/src/text-control/README.md +++ b/packages/components/src/text-control/README.md @@ -63,6 +63,7 @@ const MyTextControl = () => { return ( setClassName( value ) } diff --git a/packages/components/src/text-control/index.tsx b/packages/components/src/text-control/index.tsx index ea2d2c17bb9cf6..83881542fe7b7b 100644 --- a/packages/components/src/text-control/index.tsx +++ b/packages/components/src/text-control/index.tsx @@ -16,6 +16,7 @@ import { forwardRef } from '@wordpress/element'; import BaseControl from '../base-control'; import type { WordPressComponentProps } from '../context'; import type { TextControlProps } from './types'; +import { maybeWarnDeprecated36pxSize } from '../utils/deprecated-36px-size'; function UnforwardedTextControl( props: WordPressComponentProps< TextControlProps, 'input', false >, @@ -38,6 +39,12 @@ function UnforwardedTextControl( const onChangeValue = ( event: ChangeEvent< HTMLInputElement > ) => onChange( event.target.value ); + maybeWarnDeprecated36pxSize( { + componentName: 'TextControl', + size: undefined, + __next40pxDefaultSize, + } ); + return ( setClassName( value ) } diff --git a/packages/components/src/text-control/stories/index.story.tsx b/packages/components/src/text-control/stories/index.story.tsx index bebdb2caf75f63..948eca84a634c7 100644 --- a/packages/components/src/text-control/stories/index.story.tsx +++ b/packages/components/src/text-control/stories/index.story.tsx @@ -54,6 +54,7 @@ export const Default: StoryFn< typeof TextControl > = DefaultTemplate.bind( ); Default.args = { __nextHasNoMarginBottom: true, + __next40pxDefaultSize: true, }; export const WithLabelAndHelpText: StoryFn< typeof TextControl > = diff --git a/packages/components/src/text-control/test/text-control.tsx b/packages/components/src/text-control/test/text-control.tsx index 19b17cae443614..7eb3a82d2fb5f5 100644 --- a/packages/components/src/text-control/test/text-control.tsx +++ b/packages/components/src/text-control/test/text-control.tsx @@ -9,7 +9,13 @@ import { render, screen } from '@testing-library/react'; import _TextControl from '..'; const TextControl = ( props: React.ComponentProps< typeof _TextControl > ) => { - return <_TextControl { ...props } __nextHasNoMarginBottom />; + return ( + <_TextControl + { ...props } + __nextHasNoMarginBottom + __next40pxDefaultSize + /> + ); }; const noop = () => {}; diff --git a/packages/components/src/text-highlight/stories/index.story.tsx b/packages/components/src/text-highlight/stories/index.story.tsx index d54149d8e19d3c..f9538b7130095d 100644 --- a/packages/components/src/text-highlight/stories/index.story.tsx +++ b/packages/components/src/text-highlight/stories/index.story.tsx @@ -10,7 +10,8 @@ import TextHighlight from '..'; const meta: Meta< typeof TextHighlight > = { component: TextHighlight, - title: 'Components/TextHighlight', + title: 'Components/Typography/TextHighlight', + id: 'components-texthighlight', parameters: { controls: { expanded: true, diff --git a/packages/components/src/text/stories/index.story.tsx b/packages/components/src/text/stories/index.story.tsx index f762ca3b4e3ff7..92a2c7eb9be3e3 100644 --- a/packages/components/src/text/stories/index.story.tsx +++ b/packages/components/src/text/stories/index.story.tsx @@ -10,7 +10,8 @@ import { Text } from '../component'; const meta: Meta< typeof Text > = { component: Text, - title: 'Components (Experimental)/Text', + title: 'Components (Experimental)/Typography/Text', + id: 'components-experimental-text', argTypes: { as: { control: { type: 'text' } }, color: { control: { type: 'color' } }, diff --git a/packages/components/src/textarea-control/stories/index.story.tsx b/packages/components/src/textarea-control/stories/index.story.tsx index a8e5dc036248db..c303883a92c5d7 100644 --- a/packages/components/src/textarea-control/stories/index.story.tsx +++ b/packages/components/src/textarea-control/stories/index.story.tsx @@ -15,7 +15,8 @@ import TextareaControl from '..'; const meta: Meta< typeof TextareaControl > = { component: TextareaControl, - title: 'Components/TextareaControl', + title: 'Components/Selection & Input/Common/TextareaControl', + id: 'components-textareacontrol', argTypes: { onChange: { action: 'onChange' }, label: { control: { type: 'text' } }, diff --git a/packages/components/src/toggle-control/stories/index.story.tsx b/packages/components/src/toggle-control/stories/index.story.tsx index 97723aa207a394..b9db0474bc7603 100644 --- a/packages/components/src/toggle-control/stories/index.story.tsx +++ b/packages/components/src/toggle-control/stories/index.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import ToggleControl from '..'; const meta: Meta< typeof ToggleControl > = { - title: 'Components/ToggleControl', + title: 'Components/Selection & Input/Common/ToggleControl', + id: 'components-togglecontrol', component: ToggleControl, argTypes: { checked: { control: { type: null } }, diff --git a/packages/components/src/toggle-group-control/stories/index.story.tsx b/packages/components/src/toggle-group-control/stories/index.story.tsx index 92f1e6076248bd..afdfa457f66348 100644 --- a/packages/components/src/toggle-group-control/stories/index.story.tsx +++ b/packages/components/src/toggle-group-control/stories/index.story.tsx @@ -27,7 +27,8 @@ const meta: Meta< typeof ToggleGroupControl > = { component: ToggleGroupControl, // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 subcomponents: { ToggleGroupControlOption, ToggleGroupControlOptionIcon }, - title: 'Components (Experimental)/ToggleGroupControl', + title: 'Components (Experimental)/Selection & Input/ToggleGroupControl', + id: 'components-experimental-togglegroupcontrol', argTypes: { help: { control: { type: 'text' } }, onChange: { action: 'onChange' }, diff --git a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx index 7f384f70ae1dc5..0c3cadf210d84a 100644 --- a/packages/components/src/toggle-group-control/toggle-group-control/component.tsx +++ b/packages/components/src/toggle-group-control/toggle-group-control/component.tsx @@ -52,7 +52,7 @@ function UnconnectedToggleGroupControl( const [ controlElement, setControlElement ] = useState< HTMLElement >(); const refs = useMergeRefs( [ setControlElement, forwardedRef ] ); const selectedRect = useTrackElementOffsetRect( - value ? selectedElement : undefined + value || value === 0 ? selectedElement : undefined ); useAnimatedOffsetRect( controlElement, selectedRect, { prefix: 'selected', diff --git a/packages/components/src/tooltip/stories/index.story.tsx b/packages/components/src/tooltip/stories/index.story.tsx index b006bc03aced96..4bddba0ff7b666 100644 --- a/packages/components/src/tooltip/stories/index.story.tsx +++ b/packages/components/src/tooltip/stories/index.story.tsx @@ -15,7 +15,8 @@ import Tooltip from '..'; import Button from '../../button'; const meta: Meta< typeof Tooltip > = { - title: 'Components/Tooltip', + title: 'Components/Overlays/Tooltip', + id: 'components-tooltip', component: Tooltip, argTypes: { children: { control: { type: null } }, diff --git a/packages/components/src/tree-select/stories/index.story.tsx b/packages/components/src/tree-select/stories/index.story.tsx index 33103786bbc541..703147dc145344 100644 --- a/packages/components/src/tree-select/stories/index.story.tsx +++ b/packages/components/src/tree-select/stories/index.story.tsx @@ -14,7 +14,8 @@ import { useState } from '@wordpress/element'; import TreeSelect from '../'; const meta: Meta< typeof TreeSelect > = { - title: 'Components/TreeSelect', + title: 'Components/Selection & Input/Common/TreeSelect', + id: 'components-treeselect', component: TreeSelect, argTypes: { help: { control: { type: 'text' } }, diff --git a/packages/components/src/truncate/stories/index.story.tsx b/packages/components/src/truncate/stories/index.story.tsx index 84eaf59edbb3e1..3b06831c59aa07 100644 --- a/packages/components/src/truncate/stories/index.story.tsx +++ b/packages/components/src/truncate/stories/index.story.tsx @@ -10,7 +10,8 @@ import { Truncate } from '..'; const meta: Meta< typeof Truncate > = { component: Truncate, - title: 'Components (Experimental)/Truncate', + title: 'Components (Experimental)/Typography/Truncate', + id: 'components-experimental-truncate', argTypes: { children: { control: { type: 'text' } }, as: { control: { type: 'text' } }, diff --git a/packages/components/src/unit-control/stories/index.story.tsx b/packages/components/src/unit-control/stories/index.story.tsx index 5134d4902144da..de8f476e26e5c7 100644 --- a/packages/components/src/unit-control/stories/index.story.tsx +++ b/packages/components/src/unit-control/stories/index.story.tsx @@ -16,7 +16,8 @@ import { CSS_UNITS } from '../utils'; const meta: Meta< typeof UnitControl > = { component: UnitControl, - title: 'Components (Experimental)/UnitControl', + title: 'Components (Experimental)/Selection & Input/UnitControl', + id: 'components-experimental-unitcontrol', argTypes: { __unstableInputWidth: { control: { type: 'text' } }, __unstableStateReducer: { control: { type: null } }, diff --git a/packages/components/src/v-stack/stories/index.story.tsx b/packages/components/src/v-stack/stories/index.story.tsx index 781c1bce6676cc..11d6d579abc81e 100644 --- a/packages/components/src/v-stack/stories/index.story.tsx +++ b/packages/components/src/v-stack/stories/index.story.tsx @@ -25,7 +25,8 @@ const ALIGNMENTS = { const meta: Meta< typeof VStack > = { component: VStack, - title: 'Components (Experimental)/VStack', + title: 'Components (Experimental)/Layout/VStack', + id: 'components-experimental-vstack', argTypes: { alignment: { control: { type: 'select' }, diff --git a/packages/components/src/visually-hidden/stories/index.story.tsx b/packages/components/src/visually-hidden/stories/index.story.tsx index 8abe45a94aab4f..6ebcf9a2e949ce 100644 --- a/packages/components/src/visually-hidden/stories/index.story.tsx +++ b/packages/components/src/visually-hidden/stories/index.story.tsx @@ -10,7 +10,7 @@ import { VisuallyHidden } from '..'; const meta: Meta< typeof VisuallyHidden > = { component: VisuallyHidden, - title: 'Components/Utilities/VisuallyHidden', + title: 'Components/Typography/VisuallyHidden', id: 'components-visuallyhidden', argTypes: { children: { control: { type: null } }, diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 8f8bedfde15d4a..897ea34a88ae7f 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.12.0 (2024-11-16) + ## 7.11.0 (2024-10-30) ## 7.10.0 (2024-10-16) diff --git a/packages/compose/package.json b/packages/compose/package.json index 68b00b24298d87..596a50405ad476 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/compose", - "version": "7.11.0", + "version": "7.12.0", "description": "WordPress higher-order components (HOCs).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md index b98e0c55e24ff5..8928305ce32e57 100644 --- a/packages/core-commands/CHANGELOG.md +++ b/packages/core-commands/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.12.0 (2024-11-16) + ## 1.11.0 (2024-10-30) ## 1.10.0 (2024-10-16) diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json index db2fb900865c80..172431aa3d0913 100644 --- a/packages/core-commands/package.json +++ b/packages/core-commands/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/core-commands", - "version": "1.11.0", + "version": "1.12.0", "description": "WordPress core reusable commands.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/core-data/CHANGELOG.md b/packages/core-data/CHANGELOG.md index 31b44fa32dd0a4..d2744383594baa 100644 --- a/packages/core-data/CHANGELOG.md +++ b/packages/core-data/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 7.12.0 (2024-11-16) + ## 7.11.0 (2024-10-30) ## 7.10.0 (2024-10-16) diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 079f95ddbfc7a6..eb6980cdd4eea1 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -1083,6 +1083,8 @@ function PageRenameForm( { id } ) { return (
    * + createSelector( + () => { + const siteData = select( STORE_NAME ).getEntityRecord( + 'root', + 'site' + ) as SiteData | undefined; + if ( ! siteData ) { + return null; + } + const homepageId = + siteData?.show_on_front === 'page' + ? normalizePageId( siteData.page_on_front ) + : null; + if ( homepageId ) { + return { postType: 'page', postId: homepageId }; + } + const frontPageTemplateId = select( + STORE_NAME + ).getDefaultTemplateId( { + slug: 'front-page', + } ); + return { postType: 'wp_template', postId: frontPageTemplateId }; + }, + ( state ) => [ + // @ts-expect-error + getEntityRecord( state, 'root', 'site' ), + getDefaultTemplateId( state, { + slug: 'front-page', + } ), + ] + ) +); + +export const getPostsPageId = createRegistrySelector( ( select ) => () => { + const siteData = select( STORE_NAME ).getEntityRecord( 'root', 'site' ) as + | SiteData + | undefined; + return siteData?.show_on_front === 'page' + ? normalizePageId( siteData.page_for_posts ) + : null; +} ); + +export const getTemplateId = createRegistrySelector( + ( select ) => ( state, postType, postId ) => { + const homepage = unlock( select( STORE_NAME ) ).getHomePage(); + + if ( ! homepage ) { + return; + } + + // For the front page, we always use the front page template if existing. + if ( + postType === 'page' && + postType === homepage?.postType && + postId.toString() === homepage?.postId + ) { + // The /lookup endpoint cannot currently handle a lookup + // when a page is set as the front page, so specifically in + // that case, we want to check if there is a front page + // template, and instead of falling back to the home + // template, we want to fall back to the page template. + const templates = select( STORE_NAME ).getEntityRecords( + 'postType', + 'wp_template', + { + per_page: -1, + } + ); + if ( ! templates ) { + return; + } + const id = templates.find( ( { slug } ) => slug === 'front-page' ) + ?.id; + if ( id ) { + return id; + } + // If no front page template is found, continue with the + // logic below (fetching the page template). + } + + const editedEntity = select( STORE_NAME ).getEditedEntityRecord( + 'postType', + postType, + postId + ); + if ( ! editedEntity ) { + return; + } + const postsPageId = unlock( select( STORE_NAME ) ).getPostsPageId(); + // Check if the current page is the posts page. + if ( postType === 'page' && postsPageId === postId.toString() ) { + return select( STORE_NAME ).getDefaultTemplateId( { + slug: 'home', + } ); + } + // First see if the post/page has an assigned template and fetch it. + const currentTemplateSlug = editedEntity.template; + if ( currentTemplateSlug ) { + const currentTemplate = select( STORE_NAME ) + .getEntityRecords( 'postType', 'wp_template', { + per_page: -1, + } ) + ?.find( ( { slug } ) => slug === currentTemplateSlug ); + if ( currentTemplate ) { + return currentTemplate.id; + } + } + // If no template is assigned, use the default template. + let slugToCheck; + // In `draft` status we might not have a slug available, so we use the `single` + // post type templates slug(ex page, single-post, single-product etc..). + // Pages do not need the `single` prefix in the slug to be prioritized + // through template hierarchy. + if ( editedEntity.slug ) { + slugToCheck = + postType === 'page' + ? `${ postType }-${ editedEntity.slug }` + : `single-${ postType }-${ editedEntity.slug }`; + } else { + slugToCheck = postType === 'page' ? 'page' : `single-${ postType }`; + } + return select( STORE_NAME ).getDefaultTemplateId( { + slug: slugToCheck, + } ); + } +); diff --git a/packages/create-block-interactive-template/package.json b/packages/create-block-interactive-template/package.json index bd34bed4d2e256..94e5f3b3ed4e0b 100644 --- a/packages/create-block-interactive-template/package.json +++ b/packages/create-block-interactive-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-interactive-template", - "version": "2.11.0", + "version": "2.12.0", "description": "Template for @wordpress/create-block to create interactive blocks with the Interactivity API.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block-tutorial-template/CHANGELOG.md b/packages/create-block-tutorial-template/CHANGELOG.md index dd043522c27a6b..9a9e8e8d7b1ab6 100644 --- a/packages/create-block-tutorial-template/CHANGELOG.md +++ b/packages/create-block-tutorial-template/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/create-block-tutorial-template/package.json b/packages/create-block-tutorial-template/package.json index c2ea39fad8ba74..31c91064ddbaa6 100644 --- a/packages/create-block-tutorial-template/package.json +++ b/packages/create-block-tutorial-template/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block-tutorial-template", - "version": "4.11.0", + "version": "4.12.0", "description": "This is a template for @wordpress/create-block that creates an example 'Copyright Date' block. This block is used in the official WordPress block development Quick Start Guide.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index c961882082541c..075386562f3841 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.55.0 (2024-11-16) + ## 4.54.0 (2024-10-30) ### Enhancement diff --git a/packages/create-block/package.json b/packages/create-block/package.json index dbb8e56ea72151..edee3d421de957 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/create-block", - "version": "4.54.0", + "version": "4.55.0", "description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/customize-widgets/CHANGELOG.md b/packages/customize-widgets/CHANGELOG.md index b36ed481749ea9..41c9f2257f0a4d 100644 --- a/packages/customize-widgets/CHANGELOG.md +++ b/packages/customize-widgets/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/customize-widgets/package.json b/packages/customize-widgets/package.json index 41b3a7bd463aa3..9c1e117d2145e8 100644 --- a/packages/customize-widgets/package.json +++ b/packages/customize-widgets/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/customize-widgets", - "version": "5.11.0", + "version": "5.12.0", "description": "Widgets blocks in Customizer Module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data-controls/CHANGELOG.md b/packages/data-controls/CHANGELOG.md index c536d850f8c733..5b5c2e179f8bd3 100644 --- a/packages/data-controls/CHANGELOG.md +++ b/packages/data-controls/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/data-controls/package.json b/packages/data-controls/package.json index e4898ff1d0e1ab..0977dbb27f988c 100644 --- a/packages/data-controls/package.json +++ b/packages/data-controls/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data-controls", - "version": "4.11.0", + "version": "4.12.0", "description": "A set of common controls for the @wordpress/data api.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/data/CHANGELOG.md b/packages/data/CHANGELOG.md index 98c553b08b67b9..0537039794505f 100644 --- a/packages/data/CHANGELOG.md +++ b/packages/data/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +### Enhancements + +- Upgrade `redux` dependency to `^5.0.1` ([#66966](https://github.com/WordPress/gutenberg/pull/66966)) + +## 10.12.0 (2024-11-16) + ## 10.11.0 (2024-10-30) ## 10.10.0 (2024-10-16) diff --git a/packages/data/README.md b/packages/data/README.md index 25dd75820fb5db..b6e0e03b1d8b72 100644 --- a/packages/data/README.md +++ b/packages/data/README.md @@ -42,13 +42,6 @@ const actions = { discountPercent, }; }, - - fetchFromAPI( path ) { - return { - type: 'FETCH_FROM_API', - path, - }; - }, }; const store = createReduxStore( 'my-shop', { @@ -84,17 +77,11 @@ const store = createReduxStore( 'my-shop', { }, }, - controls: { - FETCH_FROM_API( action ) { - return apiFetch( { path: action.path } ); - }, - }, - resolvers: { - *getPrice( item ) { + getPrice: ( item ) => async ({ dispatch }) => { { const path = '/wp/v2/prices/' + item; - const price = yield actions.fetchFromAPI( path ); - return actions.setPrice( item, price ); + const price = await apiFetch( { path } ); + dispatch.setPrice( item, price ); }, }, } ); @@ -133,13 +120,21 @@ A **resolver** is a side-effect for a selector. If your selector result may need The `resolvers` option should be passed as an object where each key is the name of the selector to act upon, the value a function which receives the same arguments passed to the selector, excluding the state argument. It can then dispatch as necessary to fulfill the requirements of the selector, taking advantage of the fact that most data consumers will subscribe to subsequent state changes (by `subscribe` or `withSelect`). -#### `controls` +Resolvers, in combination with [thunks](https://github.com/WordPress/gutenberg/blob/trunk/docs/how-to-guides/thunks.md#thunks-can-be-async), can be used to implement asynchronous data flows for your store. -A **control** defines the execution flow behavior associated with a specific action type. This can be particularly useful in implementing asynchronous data flows for your store. By defining your action creator or resolvers as a generator which yields specific controlled action types, the execution will proceed as defined by the control handler. +#### `controls` (deprecated) -The `controls` option should be passed as an object where each key is the name of the action type to act upon, the value a function which receives the original action object. It should returns either a promise which is to resolve when evaluation of the action should continue, or a value. The value or resolved promise value is assigned on the return value of the yield assignment. If the control handler returns undefined, the execution is not continued. +To handle asynchronous data flows, it is recommended to use [thunks](https://github.com/WordPress/gutenberg/blob/trunk/docs/how-to-guides/thunks.md#thunks-can-be-async) instead of `controls`. -Refer to the [documentation of `@wordpress/redux-routine`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/redux-routine/README.md) for more information. +
    + View controls explanation +
    +A control defines the execution flow behavior associated with a specific action type. Before thunks, controls were used to implement asynchronous data flows for your store. By defining your action creator or resolvers as a generator which yields specific controlled action types, the execution will proceed as defined by the control handler. +

    +The controls option should be passed as an object where each key is the name of the action type to act upon, the value a function which receives the original action object. It should returns either a promise which is to resolve when evaluation of the action should continue, or a value. The value or resolved promise value is assigned on the return value of the yield assignment. If the control handler returns undefined, the execution is not continued. +

    +Refer to the documentation of @wordpress/redux-routine for more information. +
    #### `initialState` @@ -262,7 +257,7 @@ The data module shares many of the same [core principles](https://redux.js.org/i The [higher-order components](#higher-order-components) were created to complement this distinction. The intention with splitting `withSelect` and `withDispatch` — where in React Redux they are combined under `connect` as `mapStateToProps` and `mapDispatchToProps` arguments — is to more accurately reflect that dispatch is not dependent upon a subscription to state changes, and to allow for state-derived values to be used in `withDispatch` (via [higher-order component composition](https://github.com/WordPress/gutenberg/tree/HEAD/packages/compose/README.md)). -The data module also has built-in solutions for handling asynchronous side-effects, through [resolvers](#resolvers) and [controls](#controls). These differ slightly from [standard redux async solutions](https://redux.js.org/advanced/async-actions) like [`redux-thunk`](https://github.com/gaearon/redux-thunk) or [`redux-saga`](https://redux-saga.js.org/). +The data module also has built-in solutions for handling asynchronous side-effects, through [resolvers](#resolvers) and [thunks](https://github.com/WordPress/gutenberg/blob/trunk/docs/how-to-guides/thunks.md#thunks-can-be-async). These differ slightly from [standard redux async solutions](https://redux.js.org/advanced/async-actions) like [`redux-thunk`](https://github.com/gaearon/redux-thunk) or [`redux-saga`](https://redux-saga.js.org/). Specific implementation differences from Redux and React Redux: diff --git a/packages/data/package.json b/packages/data/package.json index fd1ef7ef4d7489..e325b82357b955 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/data", - "version": "10.11.0", + "version": "10.12.0", "description": "Data module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", @@ -42,7 +42,7 @@ "equivalent-key-map": "^0.2.2", "is-plain-object": "^5.0.0", "is-promise": "^4.0.0", - "redux": "^4.1.2", + "redux": "^5.0.1", "rememo": "^4.0.2", "use-memo-one": "^1.1.1" }, diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 60cdad73b32efe..7fdcdf2808e812 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +### Bug Fixes + +- Fix focus loss when removing all filters or resetting ([#67003](https://github.com/WordPress/gutenberg/pull/67003)). + +## 4.8.0 (2024-11-16) + ## 4.7.0 (2024-10-30) ## 4.6.0 (2024-10-16) @@ -23,8 +29,7 @@ ## Internal - The "move left/move right" controls in the table layout (popup displayed on cliking header) are always visible. ([#64646](https://github.com/WordPress/gutenberg/pull/64646)). Before this, its visibility depending on filters, enableSorting, and enableHiding. -- Filters no longer display the elements' description. ([#64674](https://github.com/WordPress/gutenberg/pull/64674)) - +- Filters no longer display the elements' description. ([#64674](https://github.com/WordPress/gutenberg/pull/64674)) ## Enhancements diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index ff20386862929e..621e3c7ba71ce2 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -358,6 +358,14 @@ Callback that signals the user selected one of more items. It receives the list If `selection` and `onChangeSelection` are provided, the `DataViews` component behaves as a controlled component, otherwise, it behaves like an uncontrolled component. +### `isItemClickable`: `function` + +A function that determines if a media field or a primary field are clickable. It receives an item as an argument and returns a boolean value indicating whether the item can be clicked. + +### `onClickItem`: `function` + +A callback function that is triggered when a user clicks on a media field or primary field. This function is currently implemented only in the `grid` and `list` views. + #### `header`: React component React component to be rendered next to the view config button. diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index df30fea1a1c714..80cfbf24be5651 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dataviews", - "version": "4.7.0", + "version": "4.8.0", "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dataviews/src/components/dataviews-context/index.ts b/packages/dataviews/src/components/dataviews-context/index.ts index 3936288b3095b0..87acade73bc819 100644 --- a/packages/dataviews/src/components/dataviews-context/index.ts +++ b/packages/dataviews/src/components/dataviews-context/index.ts @@ -26,6 +26,8 @@ type DataViewsContextType< Item > = { openedFilter: string | null; setOpenedFilter: ( openedFilter: string | null ) => void; getItemId: ( item: Item ) => string; + onClickItem: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; density: number; }; @@ -43,6 +45,8 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( { setOpenedFilter: () => {}, openedFilter: null, getItemId: ( item ) => item.id, + onClickItem: () => {}, + isItemClickable: () => false, density: 0, } ); diff --git a/packages/dataviews/src/components/dataviews-filters/index.tsx b/packages/dataviews/src/components/dataviews-filters/index.tsx index 9722844cf4a141..440df4f17310d6 100644 --- a/packages/dataviews/src/components/dataviews-filters/index.tsx +++ b/packages/dataviews/src/components/dataviews-filters/index.tsx @@ -7,6 +7,7 @@ import { useRef, useMemo, useCallback, + useEffect, } from '@wordpress/element'; import { __experimentalHStack as HStack, Button } from '@wordpress/components'; import { funnel } from '@wordpress/icons'; @@ -70,7 +71,7 @@ export function useFilters( fields: NormalizedField< any >[], view: View ) { }, [ fields, view ] ); } -export function FilterVisibilityToggle( { +export function FiltersToggle( { filters, view, onChangeView, @@ -85,6 +86,7 @@ export function FilterVisibilityToggle( { isShowingFilter: boolean; setIsShowingFilter: React.Dispatch< React.SetStateAction< boolean > >; } ) { + const buttonRef = useRef< HTMLButtonElement >( null ); const onChangeViewWithFilterVisibility = useCallback( ( _view: View ) => { onChangeView( _view ); @@ -98,48 +100,81 @@ export function FilterVisibilityToggle( { if ( filters.length === 0 ) { return null; } - if ( ! hasVisibleFilters ) { - return ( - - } - /> - ); - } + + const addFilterButtonProps = { + label: __( 'Add filter' ), + 'aria-expanded': false, + isPressed: false, + }; + const toggleFiltersButtonProps = { + label: _x( 'Filter', 'verb' ), + 'aria-expanded': isShowingFilter, + isPressed: isShowingFilter, + onClick: () => { + if ( ! isShowingFilter ) { + setOpenedFilter( null ); + } + setIsShowingFilter( ! isShowingFilter ); + }, + }; + const buttonComponent = ( +
    + ); +} + +function FilterVisibilityToggle( { + buttonRef, + filtersCount, + children, +}: { + buttonRef: React.RefObject< HTMLButtonElement >; + filtersCount?: number; + children: React.ReactNode; +} ) { + // Focus the `add filter` button when unmounts. + useEffect( + () => () => { + buttonRef.current?.focus(); + }, + [ buttonRef ] + ); + return ( + <> + { children } + { !! filtersCount && ( - { view.filters?.length } + { filtersCount } ) } -
    + ); } diff --git a/packages/dataviews/src/components/dataviews-item-actions/index.tsx b/packages/dataviews/src/components/dataviews-item-actions/index.tsx index 20e58a2c6bb1fb..c1a1f84b99e624 100644 --- a/packages/dataviews/src/components/dataviews-item-actions/index.tsx +++ b/packages/dataviews/src/components/dataviews-item-actions/index.tsx @@ -59,6 +59,12 @@ interface CompactItemActionsProps< Item > { actions: Action< Item >[]; } +interface PrimaryActionsProps< Item > { + item: Item; + actions: Action< Item >[]; + registry: ReturnType< typeof useRegistry >; +} + function ButtonTrigger< Item >( { action, onClick, @@ -179,6 +185,13 @@ export function ActionsMenuGroup< Item >( { ); } +function hasOnlyOneActionAndIsPrimary< Item >( + primaryActions: Action< Item >[], + actions: Action< Item >[] +) { + return primaryActions.length === 1 && actions.length; +} + export default function ItemActions< Item >( { item, actions, @@ -199,9 +212,21 @@ export default function ItemActions< Item >( { eligibleActions: _eligibleActions, }; }, [ actions, item ] ); + if ( isCompact ) { return ; } + + if ( hasOnlyOneActionAndIsPrimary( primaryActions, actions ) ) { + return ( + + ); + } + return ( ( { width: 'auto', } } > - { !! primaryActions.length && - primaryActions.map( ( action ) => { - if ( 'RenderModal' in action ) { - return ( - - ); - } - return ( - { - action.callback( [ item ], { registry } ); - } } - items={ [ item ] } - /> - ); - } ) } + ); @@ -262,3 +269,36 @@ function CompactItemActions< Item >( { ); } + +function PrimaryActions< Item >( { + item, + actions, + registry, +}: PrimaryActionsProps< Item > ) { + if ( ! Array.isArray( actions ) || actions.length === 0 ) { + return null; + } + + return actions.map( ( action ) => { + if ( 'RenderModal' in action ) { + return ( + + ); + } + return ( + { + action.callback( [ item ], { registry } ); + } } + items={ [ item ] } + /> + ); + } ); +} diff --git a/packages/dataviews/src/components/dataviews-layout/index.tsx b/packages/dataviews/src/components/dataviews-layout/index.tsx index bae4071fe2f773..4ef0125b1f64b5 100644 --- a/packages/dataviews/src/components/dataviews-layout/index.tsx +++ b/packages/dataviews/src/components/dataviews-layout/index.tsx @@ -28,6 +28,8 @@ export default function DataViewsLayout() { onChangeSelection, setOpenedFilter, density, + onClickItem, + isItemClickable, } = useContext( DataViewsContext ); const ViewComponent = VIEW_LAYOUTS.find( ( v ) => v.type === view.type ) @@ -44,6 +46,8 @@ export default function DataViewsLayout() { onChangeSelection={ onChangeSelection } selection={ selection } setOpenedFilter={ setOpenedFilter } + onClickItem={ onClickItem } + isItemClickable={ isItemClickable } view={ view } density={ density } /> diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index da60ab15ecadec..3e8224e61bc5d5 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -16,7 +16,7 @@ import DataViewsContext from '../dataviews-context'; import { default as DataViewsFilters, useFilters, - FilterVisibilityToggle, + FiltersToggle, } from '../dataviews-filters'; import DataViewsLayout from '../dataviews-layout'; import DataViewsFooter from '../dataviews-footer'; @@ -44,12 +44,17 @@ type DataViewsProps< Item > = { defaultLayouts: SupportedLayouts; selection?: string[]; onChangeSelection?: ( items: string[] ) => void; + onClickItem?: ( item: Item ) => void; + isItemClickable?: ( item: Item ) => boolean; header?: ReactNode; } & ( Item extends ItemWithId ? { getItemId?: ( item: Item ) => string } : { getItemId: ( item: Item ) => string } ); const defaultGetItemId = ( item: ItemWithId ) => item.id; +const defaultIsItemClickable = () => false; +const defaultOnClickItem = () => {}; +const EMPTY_ARRAY: any[] = []; export default function DataViews< Item >( { view, @@ -57,7 +62,7 @@ export default function DataViews< Item >( { fields, search = true, searchLabel = undefined, - actions = [], + actions = EMPTY_ARRAY, data, getItemId = defaultGetItemId, isLoading = false, @@ -65,6 +70,8 @@ export default function DataViews< Item >( { defaultLayouts, selection: selectionProperty, onChangeSelection, + onClickItem = defaultOnClickItem, + isItemClickable = defaultIsItemClickable, header, }: DataViewsProps< Item > ) { const [ selectionState, setSelectionState ] = useState< string[] >( [] ); @@ -110,6 +117,8 @@ export default function DataViews< Item >( { openedFilter, setOpenedFilter, getItemId, + isItemClickable, + onClickItem, density, } } > @@ -126,7 +135,7 @@ export default function DataViews< Item >( { className="dataviews__search" > { search && } - { const [ view, setView ] = useState< View >( { ...DEFAULT_VIEW, fields: [ 'title', 'description', 'categories' ], + layout: defaultLayouts[ DEFAULT_VIEW.type ].layout, } ); const { data: shownData, paginationInfo } = useMemo( () => { return filterSortAndPaginate( data, view, fields ); diff --git a/packages/dataviews/src/components/dataviews/style.scss b/packages/dataviews/src/components/dataviews/style.scss index aa8fbcfb009c05..bd75a1ff9e2a18 100644 --- a/packages/dataviews/src/components/dataviews/style.scss +++ b/packages/dataviews/src/components/dataviews/style.scss @@ -19,7 +19,7 @@ position: sticky; left: 0; transition: padding ease-out 0.1s; - @include reduce-motion("transition"); + @include reduce-motion( "transition" ); } .dataviews-view-list__primary-field, @@ -62,6 +62,13 @@ } } +.dataviews-view-list__primary-field--clickable, +.dataviews-view-grid__primary-field--clickable, +.dataviews-view-grid__media--clickable, +.dataviews-view-table__primary-field > .dataviews-view-table__cell-content--clickable { + cursor: pointer; +} + .dataviews-no-results, .dataviews-loading { padding: 0 $grid-unit-60; @@ -70,7 +77,7 @@ align-items: center; justify-content: center; transition: padding ease-out 0.1s; - @include reduce-motion("transition"); + @include reduce-motion( "transition" ); } /* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */ @@ -86,4 +93,3 @@ padding-right: $grid-unit-30; } } - diff --git a/packages/dataviews/src/dataforms-layouts/panel/style.scss b/packages/dataviews/src/dataforms-layouts/panel/style.scss index ae69c4ff45243a..c7058f6366b3b6 100644 --- a/packages/dataviews/src/dataforms-layouts/panel/style.scss +++ b/packages/dataviews/src/dataforms-layouts/panel/style.scss @@ -44,3 +44,7 @@ .dataforms-layouts-panel__dropdown-header { margin-bottom: $grid-unit-20; } + +.components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown { + z-index: z-index(".components-popover.components-dropdown__content.dataforms-layouts-panel__field-dropdown"); +} diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx index 230ffe0dc50b5c..e218172b7900aa 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx @@ -24,11 +24,14 @@ import SingleSelectionCheckbox from '../../components/dataviews-selection-checkb import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actions'; import type { Action, NormalizedField, ViewGridProps } from '../../types'; import type { SetSelection } from '../../private-types'; +import getClickableItemProps from '../utils/get-clickable-item-props'; interface GridItemProps< Item > { selection: string[]; onChangeSelection: SetSelection; getItemId: ( item: Item ) => string; + onClickItem: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; item: Item; actions: Action< Item >[]; mediaField?: NormalizedField< Item >; @@ -41,6 +44,8 @@ interface GridItemProps< Item > { function GridItem< Item >( { selection, onChangeSelection, + onClickItem, + isItemClickable, getItemId, item, actions, @@ -59,6 +64,21 @@ function GridItem< Item >( { const renderedPrimaryField = primaryField?.render ? ( ) : null; + + const clickableMediaItemProps = getClickableItemProps( + item, + isItemClickable, + onClickItem, + 'dataviews-view-grid__media' + ); + + const clickablePrimaryItemProps = getClickableItemProps( + item, + isItemClickable, + onClickItem, + 'dataviews-view-grid__primary-field' + ); + return ( ( { } } } > -
    - { renderedMediaField } -
    +
    { renderedMediaField }
    ( { justify="space-between" className="dataviews-view-grid__title-actions" > - +
    { renderedPrimaryField } - +
    { !! badgeFields?.length && ( @@ -170,6 +188,8 @@ export default function ViewGrid< Item >( { getItemId, isLoading, onChangeSelection, + onClickItem, + isItemClickable, selection, view, density, @@ -223,6 +243,8 @@ export default function ViewGrid< Item >( { key={ getItemId( item ) } selection={ selection } onChangeSelection={ onChangeSelection } + onClickItem={ onClickItem } + isItemClickable={ isItemClickable } getItemId={ getItemId } item={ item } actions={ actions } diff --git a/packages/dataviews/src/dataviews-layouts/grid/style.scss b/packages/dataviews/src/dataviews-layouts/grid/style.scss index 6286ed94685a04..081adf51b5dc11 100644 --- a/packages/dataviews/src/dataviews-layouts/grid/style.scss +++ b/packages/dataviews/src/dataviews-layouts/grid/style.scss @@ -17,8 +17,15 @@ .dataviews-view-grid__primary-field { min-height: $grid-unit-40; // Preserve layout when there is no ellipsis button + display: flex; + align-items: center; + + &--clickable { + width: fit-content; + } } + &.is-selected { .dataviews-view-grid__fields .dataviews-view-grid__field .dataviews-view-grid__field-value { color: $gray-900; diff --git a/packages/dataviews/src/dataviews-layouts/list/index.tsx b/packages/dataviews/src/dataviews-layouts/list/index.tsx index a4f94e482c69b3..47b9961d97df18 100644 --- a/packages/dataviews/src/dataviews-layouts/list/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/list/index.tsx @@ -170,11 +170,13 @@ function ListItem< Item >( { ( action ) => action.isPrimary && !! action.icon ); return { - primaryAction: _primaryActions?.[ 0 ], + primaryAction: _primaryActions[ 0 ], eligibleActions: _eligibleActions, }; }, [ actions, item ] ); + const hasOnlyOnePrimaryAction = primaryAction && actions.length === 1; + const renderedMediaField = mediaField?.render ? (
    @@ -194,33 +196,35 @@ function ListItem< Item >( { item={ item } /> ) } -
    - - } + { ! hasOnlyOnePrimaryAction && ( +
    + + } + /> + } + placement="bottom-end" + > + - } - placement="bottom-end" - > - - -
    +
    +
    + ) } ); diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx index 4e1607b01489c2..8ef41db1c38798 100644 --- a/packages/dataviews/src/dataviews-layouts/table/index.tsx +++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx @@ -35,11 +35,14 @@ import type { import type { SetSelection } from '../../private-types'; import ColumnHeaderMenu from './column-header-menu'; import { getVisibleFieldIds } from '../index'; +import getClickableItemProps from '../utils/get-clickable-item-props'; interface TableColumnFieldProps< Item > { primaryField?: NormalizedField< Item >; field: NormalizedField< Item >; item: Item; + isItemClickable: ( item: Item ) => boolean; + onClickItem: ( item: Item ) => void; } interface TableColumnCombinedProps< Item > { @@ -48,6 +51,8 @@ interface TableColumnCombinedProps< Item > { field: CombinedField; item: Item; view: ViewTableType; + isItemClickable: ( item: Item ) => boolean; + onClickItem: ( item: Item ) => void; } interface TableColumnProps< Item > { @@ -56,6 +61,8 @@ interface TableColumnProps< Item > { item: Item; column: string; view: ViewTableType; + isItemClickable: ( item: Item ) => boolean; + onClickItem: ( item: Item ) => void; } interface TableRowProps< Item > { @@ -69,6 +76,8 @@ interface TableRowProps< Item > { selection: string[]; getItemId: ( item: Item ) => string; onChangeSelection: SetSelection; + isItemClickable: ( item: Item ) => boolean; + onClickItem: ( item: Item ) => void; } function TableColumn< Item >( { @@ -102,15 +111,29 @@ function TableColumnField< Item >( { primaryField, item, field, + isItemClickable, + onClickItem, }: TableColumnFieldProps< Item > ) { + const isPrimaryField = primaryField?.id === field.id; + const isItemClickableField = ( i: Item ) => + isItemClickable( i ) && isPrimaryField; + + const clickableProps = getClickableItemProps( + item, + isItemClickableField, + onClickItem, + 'dataviews-view-table__cell-content' + ); + return (
    - +
    + +
    ); } @@ -139,6 +162,8 @@ function TableRow< Item >( { primaryField, selection, getItemId, + isItemClickable, + onClickItem, onChangeSelection, }: TableRowProps< Item > ) { const hasPossibleBulkAction = useHasAPossibleBulkAction( actions, item ); @@ -214,6 +239,8 @@ function TableRow< Item >( { ( { onChangeSelection, selection, setOpenedFilter, + onClickItem, + isItemClickable, view, }: ViewTableProps< Item > ) { const headerMenuRefs = useRef< @@ -392,6 +421,8 @@ function ViewTable< Item >( { selection={ selection } getItemId={ getItemId } onChangeSelection={ onChangeSelection } + onClickItem={ onClickItem } + isItemClickable={ isItemClickable } /> ) ) } diff --git a/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts new file mode 100644 index 00000000000000..e2a6081a68fa3e --- /dev/null +++ b/packages/dataviews/src/dataviews-layouts/utils/get-clickable-item-props.ts @@ -0,0 +1,22 @@ +export default function getClickableItemProps< Item >( + item: Item, + isItemClickable: ( item: Item ) => boolean, + onClickItem: ( item: Item ) => void, + className: string +) { + if ( ! isItemClickable( item ) ) { + return { className }; + } + + return { + className: `${ className } ${ className }--clickable`, + role: 'button', + tabIndex: 0, + onClick: () => onClickItem( item ), + onKeyDown: ( event: React.KeyboardEvent ) => { + if ( event.key === 'Enter' || event.key === '' ) { + onClickItem( item ); + } + }, + }; +} diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts index 0ea0965704d18c..71990f72d4eecd 100644 --- a/packages/dataviews/src/types.ts +++ b/packages/dataviews/src/types.ts @@ -498,6 +498,8 @@ export interface ViewBaseProps< Item > { onChangeSelection: SetSelection; selection: string[]; setOpenedFilter: ( fieldId: string ) => void; + onClickItem: ( item: Item ) => void; + isItemClickable: ( item: Item ) => boolean; view: View; density: number; } diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index 1d0508bd5325ad..a385b61dc17281 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 5.12.0 (2024-11-16) + ## 5.11.0 (2024-10-30) ## 5.10.0 (2024-10-16) diff --git a/packages/date/README.md b/packages/date/README.md index 8edd4e94a8538f..ed2dfdd4790324 100644 --- a/packages/date/README.md +++ b/packages/date/README.md @@ -50,7 +50,7 @@ _Parameters_ - _dateFormat_ `string`: PHP-style formatting string. See php.net/date. - _dateValue_ `Moment | Date | string | undefined`: Date object or string, parsable by moment.js. -- _timezone_ `string | number | boolean | undefined`: Timezone to output result in or a UTC offset. Defaults to timezone from site. Notice: `boolean` is effectively deprecated, but still supported for backward compatibility reasons. +- _timezone_ `string | number | boolean | undefined=`: Timezone to output result in or a UTC offset. Defaults to timezone from site. Notice: `boolean` is effectively deprecated, but still supported for backward compatibility reasons. _Returns_ diff --git a/packages/date/package.json b/packages/date/package.json index d67c1dc527caee..0d98f3954d92d0 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/date", - "version": "5.11.0", + "version": "5.12.0", "description": "Date module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/date/src/index.js b/packages/date/src/index.js index 90f65f62628dc8..b632de3a7431f6 100644 --- a/packages/date/src/index.js +++ b/packages/date/src/index.js @@ -525,15 +525,15 @@ export function gmdate( dateFormat, dateValue = new Date() ) { * Backward Compatibility Notice: if `timezone` is set to `true`, the function * behaves like `gmdateI18n`. * - * @param {string} dateFormat PHP-style formatting string. - * See php.net/date. - * @param {Moment | Date | string | undefined} dateValue Date object or string, parsable by - * moment.js. - * @param {string | number | boolean | undefined} timezone Timezone to output result in or a - * UTC offset. Defaults to timezone from - * site. Notice: `boolean` is effectively - * deprecated, but still supported for - * backward compatibility reasons. + * @param {string} dateFormat PHP-style formatting string. + * See php.net/date. + * @param {Moment | Date | string | undefined} dateValue Date object or string, parsable by + * moment.js. + * @param {string | number | boolean | undefined=} timezone Timezone to output result in or a + * UTC offset. Defaults to timezone from + * site. Notice: `boolean` is effectively + * deprecated, but still supported for + * backward compatibility reasons. * * @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones * @see https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 080234c319e477..ee79a75513b996 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ## 6.11.0 (2024-10-30) ## 6.10.0 (2024-10-16) diff --git a/packages/dependency-extraction-webpack-plugin/package.json b/packages/dependency-extraction-webpack-plugin/package.json index cb7a4e60bf015d..f168f379aa819d 100644 --- a/packages/dependency-extraction-webpack-plugin/package.json +++ b/packages/dependency-extraction-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dependency-extraction-webpack-plugin", - "version": "6.11.0", + "version": "6.12.0", "description": "Extract WordPress script dependencies from webpack bundles.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/deprecated/CHANGELOG.md b/packages/deprecated/CHANGELOG.md index 5ba83861f7cd3d..861aaa9ad69f25 100644 --- a/packages/deprecated/CHANGELOG.md +++ b/packages/deprecated/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/deprecated/package.json b/packages/deprecated/package.json index 64ffc6cd30b251..11d351d17acb49 100644 --- a/packages/deprecated/package.json +++ b/packages/deprecated/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/deprecated", - "version": "4.11.0", + "version": "4.12.0", "description": "Deprecation utility for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index b7374d6f921cb4..7c92855715e325 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 2.12.0 (2024-11-16) + ## 2.11.0 (2024-10-30) ## 2.10.0 (2024-10-16) diff --git a/packages/docgen/package.json b/packages/docgen/package.json index be73d0625b63ed..f9df5281bd5259 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/docgen", - "version": "2.11.0", + "version": "2.12.0", "description": "Autogenerate public API documentation from exports and JSDoc comments.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom-ready/CHANGELOG.md b/packages/dom-ready/CHANGELOG.md index ffdaeff6e892cf..2b6647faa8332b 100644 --- a/packages/dom-ready/CHANGELOG.md +++ b/packages/dom-ready/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/dom-ready/package.json b/packages/dom-ready/package.json index 6e7986c4965dc6..7302df37787ca5 100644 --- a/packages/dom-ready/package.json +++ b/packages/dom-ready/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom-ready", - "version": "4.11.0", + "version": "4.12.0", "description": "Execute callback after the DOM is loaded.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/dom/CHANGELOG.md b/packages/dom/CHANGELOG.md index b868abb474e62f..f44165f23fd515 100644 --- a/packages/dom/CHANGELOG.md +++ b/packages/dom/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.12.0 (2024-11-16) + ## 4.11.0 (2024-10-30) ## 4.10.0 (2024-10-16) diff --git a/packages/dom/package.json b/packages/dom/package.json index 97576e9a22e0ff..a717c1ee0b9a5d 100644 --- a/packages/dom/package.json +++ b/packages/dom/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/dom", - "version": "4.11.0", + "version": "4.12.0", "description": "DOM utilities module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils-playwright/CHANGELOG.md b/packages/e2e-test-utils-playwright/CHANGELOG.md index cbe574c55790a0..968963de3b79d8 100644 --- a/packages/e2e-test-utils-playwright/CHANGELOG.md +++ b/packages/e2e-test-utils-playwright/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 1.12.0 (2024-11-16) + ## 1.11.0 (2024-10-30) ## 1.10.0 (2024-10-16) diff --git a/packages/e2e-test-utils-playwright/package.json b/packages/e2e-test-utils-playwright/package.json index 8a2703bfdec54d..43ef469ac88471 100644 --- a/packages/e2e-test-utils-playwright/package.json +++ b/packages/e2e-test-utils-playwright/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils-playwright", - "version": "1.11.0", + "version": "1.12.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index 137b1ba872dc54..1974f72e3fb215 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 11.12.0 (2024-11-16) + ## 11.11.0 (2024-10-30) ## 11.10.0 (2024-10-16) diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index 2ff76b73ed2fbf..ee7a4deaa2ee94 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-test-utils", - "version": "11.11.0", + "version": "11.12.0", "description": "End-To-End (E2E) test utils for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/e2e-test-utils/src/site-editor.js b/packages/e2e-test-utils/src/site-editor.js index 98ba34f7db4f51..d3717982ba3a54 100644 --- a/packages/e2e-test-utils/src/site-editor.js +++ b/packages/e2e-test-utils/src/site-editor.js @@ -44,11 +44,11 @@ export async function disableSiteEditorWelcomeGuide() { export function getCurrentSiteEditorContent() { return page.evaluate( () => { const postId = window.wp.data - .select( 'core/edit-site' ) - .getEditedPostId(); + .select( 'core/editor' ) + .getCurrentPostId(); const postType = window.wp.data - .select( 'core/edit-site' ) - .getEditedPostType(); + .select( 'core/editor' ) + .getCurrentPostType(); const record = window.wp.data .select( 'core' ) .getEditedEntityRecord( 'postType', postType, postId ); diff --git a/packages/e2e-tests/CHANGELOG.md b/packages/e2e-tests/CHANGELOG.md index 610a2bb9697452..e6f405a0d21115 100644 --- a/packages/e2e-tests/CHANGELOG.md +++ b/packages/e2e-tests/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.12.0 (2024-11-16) + ## 8.11.0 (2024-10-30) ## 8.10.0 (2024-10-16) diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index cceaa6210a2dd9..ee87ea8430654d 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/e2e-tests", - "version": "8.11.0", + "version": "8.12.0", "description": "End-To-End (E2E) tests for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index 48a101b543821e..56f37b13ae6225 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 8.12.0 (2024-11-16) + ## 8.11.0 (2024-10-30) ## 8.10.0 (2024-10-16) diff --git a/packages/edit-post/package.json b/packages/edit-post/package.json index 1b28c1d5f31aa6..ba2bdea38bbe43 100644 --- a/packages/edit-post/package.json +++ b/packages/edit-post/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-post", - "version": "8.11.0", + "version": "8.12.0", "description": "Edit Post module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index b50e17054fd3ef..aec14eab989f03 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -399,10 +399,10 @@ function Layout( { } = useSelect( ( select ) => { const { get } = select( preferencesStore ); - const { isFeatureActive, getEditedPostTemplateId } = unlock( - select( editPostStore ) + const { isFeatureActive } = select( editPostStore ); + const { canUser, getPostType, getTemplateId } = unlock( + select( coreStore ) ); - const { canUser, getPostType } = select( coreStore ); const supportsTemplateMode = settings.supportsTemplateMode; const isViewable = @@ -424,14 +424,16 @@ function Layout( { !! select( blockEditorStore ).getBlockSelectionStart(), showIconLabels: get( 'core', 'showIconLabels' ), isDistractionFree: get( 'core', 'distractionFree' ), - showMetaBoxes: ! DESIGN_POST_TYPES.includes( currentPostType ), + showMetaBoxes: + ! DESIGN_POST_TYPES.includes( currentPostType ) && + ! isZoomOut(), isWelcomeGuideVisible: isFeatureActive( 'welcomeGuide' ), templateId: supportsTemplateMode && isViewable && canViewTemplate && ! isEditingTemplate - ? getEditedPostTemplateId() + ? getTemplateId( currentPostType, currentPostId ) : null, enablePaddingAppender: ! isZoomOut() && @@ -439,7 +441,12 @@ function Layout( { ! DESIGN_POST_TYPES.includes( currentPostType ), }; }, - [ currentPostType, isEditingTemplate, settings.supportsTemplateMode ] + [ + currentPostType, + currentPostId, + isEditingTemplate, + settings.supportsTemplateMode, + ] ); const [ paddingAppenderRef, paddingStyle ] = usePaddingAppender( enablePaddingAppender diff --git a/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js b/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js index b8125e96c7c2cf..f3db9d123f9d71 100644 --- a/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js +++ b/packages/edit-post/src/components/preferences-modal/enable-custom-fields.js @@ -4,7 +4,7 @@ import { useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { Button } from '@wordpress/components'; -import { withSelect } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; import { privateApis as preferencesPrivateApis } from '@wordpress/preferences'; import { getPathAndQueryString } from '@wordpress/url'; @@ -57,7 +57,10 @@ export function CustomFieldsConfirmation( { willEnable } ) { ); } -export function EnableCustomFieldsOption( { label, areCustomFieldsEnabled } ) { +export default function EnableCustomFieldsOption( { label } ) { + const areCustomFieldsEnabled = useSelect( ( select ) => { + return !! select( editorStore ).getEditorSettings().enableCustomFields; + }, [] ); const [ isChecked, setIsChecked ] = useState( areCustomFieldsEnabled ); return ( @@ -72,8 +75,3 @@ export function EnableCustomFieldsOption( { label, areCustomFieldsEnabled } ) { ); } - -export default withSelect( ( select ) => ( { - areCustomFieldsEnabled: - !! select( editorStore ).getEditorSettings().enableCustomFields, -} ) )( EnableCustomFieldsOption ); diff --git a/packages/edit-post/src/components/preferences-modal/enable-panel.js b/packages/edit-post/src/components/preferences-modal/enable-panel.js index d698cdc360cae2..9053b74a695d6d 100644 --- a/packages/edit-post/src/components/preferences-modal/enable-panel.js +++ b/packages/edit-post/src/components/preferences-modal/enable-panel.js @@ -1,8 +1,7 @@ /** * WordPress dependencies */ -import { compose, ifCondition } from '@wordpress/compose'; -import { withSelect, withDispatch } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { store as editorStore } from '@wordpress/editor'; import { privateApis as preferencesPrivateApis } from '@wordpress/preferences'; @@ -13,18 +12,29 @@ import { unlock } from '../../lock-unlock'; const { PreferenceBaseOption } = unlock( preferencesPrivateApis ); -export default compose( - withSelect( ( select, { panelName } ) => { - const { isEditorPanelEnabled, isEditorPanelRemoved } = - select( editorStore ); - return { - isRemoved: isEditorPanelRemoved( panelName ), - isChecked: isEditorPanelEnabled( panelName ), - }; - } ), - ifCondition( ( { isRemoved } ) => ! isRemoved ), - withDispatch( ( dispatch, { panelName } ) => ( { - onChange: () => - dispatch( editorStore ).toggleEditorPanelEnabled( panelName ), - } ) ) -)( PreferenceBaseOption ); +export default function EnablePanelOption( props ) { + const { toggleEditorPanelEnabled } = useDispatch( editorStore ); + const { isChecked, isRemoved } = useSelect( + ( select ) => { + const { isEditorPanelEnabled, isEditorPanelRemoved } = + select( editorStore ); + return { + isChecked: isEditorPanelEnabled( props.panelName ), + isRemoved: isEditorPanelRemoved( props.panelName ), + }; + }, + [ props.panelName ] + ); + + if ( isRemoved ) { + return null; + } + + return ( + toggleEditorPanelEnabled( props.panelName ) } + { ...props } + /> + ); +} diff --git a/packages/edit-post/src/components/preferences-modal/test/enable-custom-fields.js b/packages/edit-post/src/components/preferences-modal/test/enable-custom-fields.js index 2dbeadec8350ac..adfa4a3df391da 100644 --- a/packages/edit-post/src/components/preferences-modal/test/enable-custom-fields.js +++ b/packages/edit-post/src/components/preferences-modal/test/enable-custom-fields.js @@ -4,27 +4,38 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + /** * Internal dependencies */ import { - EnableCustomFieldsOption, + default as EnableCustomFieldsOption, CustomFieldsConfirmation, } from '../enable-custom-fields'; +jest.mock( '@wordpress/data/src/components/use-select', () => jest.fn() ); + +function setupUseSelectMock( areCustomFieldsEnabled ) { + useSelect.mockImplementation( () => { + return areCustomFieldsEnabled; + } ); +} + describe( 'EnableCustomFieldsOption', () => { it( 'renders a checked checkbox when custom fields are enabled', () => { - const { container } = render( - - ); + setupUseSelectMock( true ); + const { container } = render( ); expect( container ).toMatchSnapshot(); } ); it( 'renders an unchecked checkbox when custom fields are disabled', () => { - const { container } = render( - - ); + setupUseSelectMock( false ); + const { container } = render( ); expect( container ).toMatchSnapshot(); } ); @@ -32,9 +43,8 @@ describe( 'EnableCustomFieldsOption', () => { it( 'renders an unchecked checkbox and a confirmation message when toggled off', async () => { const user = userEvent.setup(); - const { container } = render( - - ); + setupUseSelectMock( true ); + const { container } = render( ); await user.click( screen.getByRole( 'checkbox' ) ); @@ -44,9 +54,8 @@ describe( 'EnableCustomFieldsOption', () => { it( 'renders a checked checkbox and a confirmation message when toggled on', async () => { const user = userEvent.setup(); - const { container } = render( - - ); + setupUseSelectMock( false ); + const { container } = render( ); await user.click( screen.getByRole( 'checkbox' ) ); diff --git a/packages/edit-post/src/store/index.js b/packages/edit-post/src/store/index.js index 17033b759292d7..93dae7606d0e3c 100644 --- a/packages/edit-post/src/store/index.js +++ b/packages/edit-post/src/store/index.js @@ -9,9 +9,7 @@ import { createReduxStore, register } from '@wordpress/data'; import reducer from './reducer'; import * as actions from './actions'; import * as selectors from './selectors'; -import * as privateSelectors from './private-selectors'; import { STORE_NAME } from './constants'; -import { unlock } from '../lock-unlock'; /** * Store definition for the edit post namespace. @@ -26,4 +24,3 @@ export const store = createReduxStore( STORE_NAME, { selectors, } ); register( store ); -unlock( store ).registerPrivateSelectors( privateSelectors ); diff --git a/packages/edit-post/src/store/private-selectors.js b/packages/edit-post/src/store/private-selectors.js deleted file mode 100644 index 246b2754d895ab..00000000000000 --- a/packages/edit-post/src/store/private-selectors.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * WordPress dependencies - */ -import { createRegistrySelector } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; -import { store as editorStore } from '@wordpress/editor'; - -export const getEditedPostTemplateId = createRegistrySelector( - ( select ) => () => { - const { - id: postId, - type: postType, - slug, - } = select( editorStore ).getCurrentPost(); - const { getEntityRecord, getEntityRecords, canUser } = - select( coreStore ); - const siteSettings = canUser( 'read', { - kind: 'root', - name: 'site', - } ) - ? getEntityRecord( 'root', 'site' ) - : undefined; - // First check if the current page is set as the posts page. - const isPostsPage = +postId === siteSettings?.page_for_posts; - if ( isPostsPage ) { - return select( coreStore ).getDefaultTemplateId( { slug: 'home' } ); - } - const currentTemplate = - select( editorStore ).getEditedPostAttribute( 'template' ); - if ( currentTemplate ) { - const templateWithSameSlug = getEntityRecords( - 'postType', - 'wp_template', - { per_page: -1 } - )?.find( ( template ) => template.slug === currentTemplate ); - if ( ! templateWithSameSlug ) { - return templateWithSameSlug; - } - return templateWithSameSlug.id; - } - let slugToCheck; - // In `draft` status we might not have a slug available, so we use the `single` - // post type templates slug(ex page, single-post, single-product etc..). - // Pages do not need the `single` prefix in the slug to be prioritized - // through template hierarchy. - if ( slug ) { - slugToCheck = - postType === 'page' - ? `${ postType }-${ slug }` - : `single-${ postType }-${ slug }`; - } else { - slugToCheck = postType === 'page' ? 'page' : `single-${ postType }`; - } - - if ( postType ) { - return select( coreStore ).getDefaultTemplateId( { - slug: slugToCheck, - } ); - } - } -); diff --git a/packages/edit-post/src/store/selectors.js b/packages/edit-post/src/store/selectors.js index 8d85249e8100ba..f6516dd0206c00 100644 --- a/packages/edit-post/src/store/selectors.js +++ b/packages/edit-post/src/store/selectors.js @@ -14,8 +14,6 @@ import deprecated from '@wordpress/deprecated'; * Internal dependencies */ import { unlock } from '../lock-unlock'; -import { getEditedPostTemplateId } from './private-selectors'; - const { interfaceStore } = unlock( editorPrivateApis ); const EMPTY_ARRAY = []; const EMPTY_OBJECT = {}; @@ -555,8 +553,13 @@ export function areMetaBoxesInitialized( state ) { * @return {Object?} Post Template. */ export const getEditedPostTemplate = createRegistrySelector( - ( select ) => ( state ) => { - const templateId = getEditedPostTemplateId( state ); + ( select ) => () => { + const { id: postId, type: postType } = + select( editorStore ).getCurrentPost(); + const templateId = unlock( select( coreStore ) ).getTemplateId( + postType, + postId + ); if ( ! templateId ) { return undefined; } diff --git a/packages/edit-site/CHANGELOG.md b/packages/edit-site/CHANGELOG.md index 7efa4f6c5b9d45..0c90c024b0cd99 100644 --- a/packages/edit-site/CHANGELOG.md +++ b/packages/edit-site/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 6.12.0 (2024-11-16) + ## 6.11.0 (2024-10-30) ## 6.10.0 (2024-10-16) diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json index 41bf39c1e08332..11ce70b876bc45 100644 --- a/packages/edit-site/package.json +++ b/packages/edit-site/package.json @@ -1,6 +1,6 @@ { "name": "@wordpress/edit-site", - "version": "6.11.0", + "version": "6.12.0", "description": "Edit Site Page module for WordPress.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", diff --git a/packages/edit-site/src/components/app/index.js b/packages/edit-site/src/components/app/index.js index 133a376c9c246d..3588565fcb3c17 100644 --- a/packages/edit-site/src/components/app/index.js +++ b/packages/edit-site/src/components/app/index.js @@ -18,8 +18,6 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; import Layout from '../layout'; import { unlock } from '../../lock-unlock'; import { useCommonCommands } from '../../hooks/commands/use-common-commands'; -import { useEditModeCommands } from '../../hooks/commands/use-edit-mode-commands'; -import useInitEditedEntityFromURL from '../sync-state-with-url/use-init-edited-entity-from-url'; import useActiveRoute from '../layout/router'; import useSetCommandContext from '../../hooks/commands/use-set-command-context'; import { useRegisterSiteEditorRoutes } from '../site-editor-routes'; @@ -28,9 +26,6 @@ const { RouterProvider } = unlock( routerPrivateApis ); const { GlobalStylesProvider } = unlock( editorPrivateApis ); function AppLayout() { - // This ensures the edited entity id and type are initialized properly. - useInitEditedEntityFromURL(); - useEditModeCommands(); useCommonCommands(); useSetCommandContext(); useRegisterSiteEditorRoutes(); diff --git a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js index 37fa0a2eaf30c2..5c75de6d81e720 100644 --- a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js +++ b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js @@ -36,26 +36,21 @@ function useNavigateToPreviousEntityRecord() { return goBack; } -export function useSpecificEditorSettings() { +export function useSpecificEditorSettings( + shouldUseTemplateAsDefaultRenderingMode +) { const { params } = useLocation(); const { canvas = 'view' } = params; const onNavigateToEntityRecord = useNavigateToEntityRecord(); - const { settings, shouldUseTemplateAsDefaultRenderingMode } = useSelect( - ( select ) => { - const { getEditedPostContext, getSettings } = unlock( - select( editSiteStore ) - ); - const _context = getEditedPostContext(); - return { - settings: getSettings(), - // TODO: The `postType` check should be removed when the default rendering mode per post type is merged. - // @see https://github.com/WordPress/gutenberg/pull/62304/ - shouldUseTemplateAsDefaultRenderingMode: - _context?.postId && _context?.postType !== 'post', - }; - }, - [] - ); + const { settings } = useSelect( ( select ) => { + const { getSettings } = select( editSiteStore ); + return { + settings: getSettings(), + }; + }, [] ); + + // TODO: The `shouldUseTemplateAsDefaultRenderingMode` check should be removed when the default rendering mode per post type is merged. + // @see https://github.com/WordPress/gutenberg/pull/62304/ const defaultRenderingMode = shouldUseTemplateAsDefaultRenderingMode ? 'template-locked' : 'post-only'; diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 8f0ca0c5b29718..51d734f25c6adb 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -49,6 +49,11 @@ import useEditorIframeProps from '../block-editor/use-editor-iframe-props'; import useEditorTitle from './use-editor-title'; import { useIsSiteEditorLoading } from '../layout/hooks'; import { useAdaptEditorToCanvas } from './use-adapt-editor-to-canvas'; +import { TEMPLATE_POST_TYPE } from '../../utils/constants'; +import { + useResolveEditedEntity, + useSyncDeprecatedEntityIntoState, +} from './use-resolve-edited-entity'; const { Editor, BackButton } = unlock( editorPrivateApis ); const { useHistory, useLocation } = unlock( routerPrivateApis ); @@ -84,38 +89,25 @@ export default function EditSiteEditor( { isPostsList = false } ) { const { canvas = 'view' } = params; const isLoading = useIsSiteEditorLoading(); useAdaptEditorToCanvas( canvas ); + const entity = useResolveEditedEntity(); + // deprecated sync state with url + useSyncDeprecatedEntityIntoState( entity ); + const { postType, postId, context } = entity; const { - editedPostType, - editedPostId, - contextPostType, - contextPostId, - isEditingPage, supportsGlobalStyles, showIconLabels, editorCanvasView, currentPostIsTrashed, hasSiteIcon, } = useSelect( ( select ) => { - const { - getEditorCanvasContainerView, - getEditedPostContext, - isPage, - getEditedPostType, - getEditedPostId, - } = unlock( select( editSiteStore ) ); + const { getEditorCanvasContainerView } = unlock( + select( editSiteStore ) + ); const { get } = select( preferencesStore ); const { getCurrentTheme, getEntityRecord } = select( coreDataStore ); - const _context = getEditedPostContext(); const siteData = getEntityRecord( 'root', '__unstableBase', undefined ); - // The currently selected entity to display. - // Typically template or template part in the site editor. return { - editedPostType: getEditedPostType(), - editedPostId: getEditedPostId(), - contextPostType: _context?.postId ? _context.postType : undefined, - contextPostId: _context?.postId ? _context.postId : undefined, - isEditingPage: isPage(), supportsGlobalStyles: getCurrentTheme()?.is_block_theme, showIconLabels: get( 'core', 'showIconLabels' ), editorCanvasView: getEditorCanvasContainerView(), @@ -125,18 +117,23 @@ export default function EditSiteEditor( { isPostsList = false } ) { hasSiteIcon: !! siteData?.site_icon_url, }; }, [] ); - useEditorTitle(); + const postWithTemplate = !! context?.postId; + useEditorTitle( + postWithTemplate ? context.postType : postType, + postWithTemplate ? context.postId : postId + ); const _isPreviewingTheme = isPreviewingTheme(); const hasDefaultEditorCanvasView = ! useHasEditorCanvasContainer(); const iframeProps = useEditorIframeProps(); const isEditMode = canvas === 'edit'; - const postWithTemplate = !! contextPostId; const loadingProgressId = useInstanceId( CanvasLoader, 'edit-site-editor__loading-progress' ); - const settings = useSpecificEditorSettings(); + const settings = useSpecificEditorSettings( + !! context?.postId && context?.postType !== 'post' + ); const styles = useMemo( () => [ ...settings.styles, @@ -214,18 +211,22 @@ export default function EditSiteEditor( { isPostsList = false } ) { return ( <> - + { isEditMode && } { ! isReady ? : null } - { isEditMode && } + { isEditMode && ( + + ) } { isReady && ( + ! postWithTemplate && ( + + ) } > { isEditMode && ( diff --git a/packages/edit-site/src/components/editor/use-editor-title.js b/packages/edit-site/src/components/editor/use-editor-title.js index 0645c2031a3af0..2ad4e94ccc3e80 100644 --- a/packages/edit-site/src/components/editor/use-editor-title.js +++ b/packages/edit-site/src/components/editor/use-editor-title.js @@ -2,34 +2,58 @@ * WordPress dependencies */ import { _x, sprintf } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { store as editorStore } from '@wordpress/editor'; +import { decodeEntities } from '@wordpress/html-entities'; /** * Internal dependencies */ -import useEditedEntityRecord from '../use-edited-entity-record'; import useTitle from '../routes/use-title'; import { POST_TYPE_LABELS, TEMPLATE_POST_TYPE } from '../../utils/constants'; -function useEditorTitle() { - const { - record: editedPost, - getTitle, - isLoaded: hasLoadedPost, - } = useEditedEntityRecord(); - let title; - if ( hasLoadedPost ) { - title = sprintf( +function useEditorTitle( postType, postId ) { + const { title, isLoaded } = useSelect( + ( select ) => { + const { getEditedEntityRecord, hasFinishedResolution } = + select( coreStore ); + const { __experimentalGetTemplateInfo: getTemplateInfo } = + select( editorStore ); + const _record = getEditedEntityRecord( + 'postType', + postType, + postId + ); + const _isLoaded = hasFinishedResolution( 'getEditedEntityRecord', [ + 'postType', + postType, + postId, + ] ); + const templateInfo = getTemplateInfo( _record ); + + return { + title: templateInfo.title, + isLoaded: _isLoaded, + }; + }, + [ postType, postId ] + ); + + let editorTitle; + if ( isLoaded ) { + editorTitle = sprintf( // translators: A breadcrumb trail for the Admin document title. 1: title of template being edited, 2: type of template (Template or Template Part). _x( '%1$s ‹ %2$s', 'breadcrumb trail' ), - getTitle(), - POST_TYPE_LABELS[ editedPost.type ] ?? + decodeEntities( title ), + POST_TYPE_LABELS[ postType ] ?? POST_TYPE_LABELS[ TEMPLATE_POST_TYPE ] ); } // Only announce the title once the editor is ready to prevent "Replace" // action in from double-announcing. - useTitle( hasLoadedPost && title ); + useTitle( isLoaded && editorTitle ); } export default useEditorTitle; diff --git a/packages/edit-site/src/components/editor/use-resolve-edited-entity.js b/packages/edit-site/src/components/editor/use-resolve-edited-entity.js new file mode 100644 index 00000000000000..4f873738704141 --- /dev/null +++ b/packages/edit-site/src/components/editor/use-resolve-edited-entity.js @@ -0,0 +1,132 @@ +/** + * WordPress dependencies + */ +import { useEffect, useMemo } from '@wordpress/element'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { store as coreDataStore } from '@wordpress/core-data'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; + +/** + * Internal dependencies + */ +import { store as editSiteStore } from '../../store'; +import { unlock } from '../../lock-unlock'; +import { + TEMPLATE_POST_TYPE, + TEMPLATE_PART_POST_TYPE, + NAVIGATION_POST_TYPE, + PATTERN_TYPES, +} from '../../utils/constants'; + +const { useLocation } = unlock( routerPrivateApis ); + +const postTypesWithoutParentTemplate = [ + TEMPLATE_POST_TYPE, + TEMPLATE_PART_POST_TYPE, + NAVIGATION_POST_TYPE, + PATTERN_TYPES.user, +]; + +const authorizedPostTypes = [ 'page', 'post' ]; + +export function useResolveEditedEntity() { + const { params = {} } = useLocation(); + const { postId, postType } = params; + const homePage = useSelect( ( select ) => { + const { getHomePage } = unlock( select( coreDataStore ) ); + return getHomePage(); + }, [] ); + + /** + * This is a hook that recreates the logic to resolve a template for a given WordPress postID postTypeId + * in order to match the frontend as closely as possible in the site editor. + * + * It is not possible to rely on the server logic because there maybe unsaved changes that impact the template resolution. + */ + const resolvedTemplateId = useSelect( + ( select ) => { + // If we're rendering a post type that doesn't have a template + // no need to resolve its template. + if ( + postTypesWithoutParentTemplate.includes( postType ) && + postId + ) { + return; + } + + // Don't trigger resolution for multi-selected posts. + if ( postId && postId.includes( ',' ) ) { + return; + } + + const { getTemplateId } = unlock( select( coreDataStore ) ); + + // If we're rendering a specific page, we need to resolve its template. + // The site editor only supports pages for now, not other CPTs. + if ( + postType && + postId && + authorizedPostTypes.includes( postType ) + ) { + return getTemplateId( postType, postId ); + } + + // If we're rendering the home page, and we have a static home page, resolve its template. + if ( homePage?.postType === 'page' ) { + return getTemplateId( 'page', homePage?.postId ); + } + + if ( homePage?.postType === 'wp_template' ) { + return homePage?.postId; + } + }, + [ homePage, postId, postType ] + ); + + const context = useMemo( () => { + if ( postTypesWithoutParentTemplate.includes( postType ) && postId ) { + return {}; + } + + if ( postType && postId && authorizedPostTypes.includes( postType ) ) { + return { postType, postId }; + } + // TODO: for post types lists we should probably not render the front page, but maybe a placeholder + // with a message like "Select a page" or something similar. + if ( homePage?.postType === 'page' ) { + return { postType: 'page', postId: homePage?.postId }; + } + + return {}; + }, [ homePage, postType, postId ] ); + + if ( postTypesWithoutParentTemplate.includes( postType ) && postId ) { + return { isReady: true, postType, postId, context }; + } + + if ( !! homePage ) { + return { + isReady: resolvedTemplateId !== undefined, + postType: TEMPLATE_POST_TYPE, + postId: resolvedTemplateId, + context, + }; + } + + return { isReady: false }; +} + +export function useSyncDeprecatedEntityIntoState( { + postType, + postId, + context, + isReady, +} ) { + const { setEditedEntity } = useDispatch( editSiteStore ); + + useEffect( () => { + if ( isReady ) { + setEditedEntity( postType, postId, context ); + } + }, [ isReady, postType, postId, context, setEditedEntity ] ); +} diff --git a/packages/edit-site/src/components/global-styles-renderer/index.js b/packages/edit-site/src/components/global-styles-renderer/index.js index 2e840a7acdc375..d3e84ff5390996 100644 --- a/packages/edit-site/src/components/global-styles-renderer/index.js +++ b/packages/edit-site/src/components/global-styles-renderer/index.js @@ -10,17 +10,11 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; */ import { store as editSiteStore } from '../../store'; import { unlock } from '../../lock-unlock'; -import { TEMPLATE_POST_TYPE } from '../../utils/constants'; const { useGlobalStylesOutput } = unlock( blockEditorPrivateApis ); -function useGlobalStylesRenderer() { - const postType = useSelect( ( select ) => { - return select( editSiteStore ).getEditedPostType(); - } ); - const [ styles, settings ] = useGlobalStylesOutput( - postType !== TEMPLATE_POST_TYPE - ); +function useGlobalStylesRenderer( disableRootPadding ) { + const [ styles, settings ] = useGlobalStylesOutput( disableRootPadding ); const { getSettings } = useSelect( editSiteStore ); const { updateSettings } = useDispatch( editSiteStore ); @@ -41,8 +35,8 @@ function useGlobalStylesRenderer() { }, [ styles, settings, updateSettings, getSettings ] ); } -export function GlobalStylesRenderer() { - useGlobalStylesRenderer(); +export function GlobalStylesRenderer( { disableRootPadding } ) { + useGlobalStylesRenderer( disableRootPadding ); return null; } diff --git a/packages/edit-site/src/components/global-styles-sidebar/index.js b/packages/edit-site/src/components/global-styles-sidebar/index.js index c0ad313d5d477c..d46346b50dae37 100644 --- a/packages/edit-site/src/components/global-styles-sidebar/index.js +++ b/packages/edit-site/src/components/global-styles-sidebar/index.js @@ -5,7 +5,7 @@ import { FlexItem, Flex, Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { styles, seen, backup } from '@wordpress/icons'; import { useSelect, useDispatch } from '@wordpress/data'; -import { useEffect } from '@wordpress/element'; +import { useEffect, useRef } from '@wordpress/element'; import { store as preferencesStore } from '@wordpress/preferences'; import { store as editorStore, @@ -29,7 +29,7 @@ const { useLocation } = unlock( routerPrivateApis ); export default function GlobalStylesSidebar() { const { params } = useLocation(); - const { canvas = 'view' } = params; + const { canvas = 'view', path } = params; const { shouldClearCanvasContainerView, isStyleBookOpened, @@ -128,6 +128,20 @@ export default function GlobalStylesSidebar() { ); }; + const { getActiveComplementaryArea } = useSelect( interfaceStore ); + const { enableComplementaryArea } = useDispatch( interfaceStore ); + const previousActiveAreaRef = useRef( null ); + + useEffect( () => { + if ( path?.startsWith( '/wp_global_styles' ) && canvas === 'edit' ) { + previousActiveAreaRef.current = + getActiveComplementaryArea( 'core' ); + enableComplementaryArea( 'core', 'edit-site/global-styles' ); + } else if ( previousActiveAreaRef.current ) { + enableComplementaryArea( 'core', previousActiveAreaRef.current ); + } + }, [ path, enableComplementaryArea, canvas, getActiveComplementaryArea ] ); + return ( spacingType === 'blockGap' ) ) ) { - settings.spacing.blockGap = false; + disableBlockGap = true; } // Only allow `aspectRatio` support if the block is not the grouping block. @@ -124,10 +128,25 @@ function ScreenBlock( { name, variation } ) { // for all three at once. Until there is the ability to set a different aspect // ratio for each variation, we disable the aspect ratio controls for the // grouping block in global styles. - if ( settings?.dimensions?.aspectRatio && name === 'core/group' ) { - settings.dimensions.aspectRatio = false; + let disableAspectRatio = false; + if ( + settingsForBlockElement?.dimensions?.aspectRatio && + name === 'core/group' + ) { + disableAspectRatio = true; } + const settings = useMemo( () => { + const updatedSettings = structuredClone( settingsForBlockElement ); + if ( disableBlockGap ) { + updatedSettings.spacing.blockGap = false; + } + if ( disableAspectRatio ) { + updatedSettings.dimensions.aspectRatio = false; + } + return updatedSettings; + }, [ settingsForBlockElement, disableBlockGap, disableAspectRatio ] ); + const blockVariations = useBlockVariations( name ); const hasBackgroundPanel = useHasBackgroundPanel( settings ); const hasTypographyPanel = useHasTypographyPanel( settings ); diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index 0cab4c13aa3ee7..22ebad383884e9 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -19,7 +19,7 @@ import { __ } from '@wordpress/i18n'; import { store as preferencesStore } from '@wordpress/preferences'; import { moreVertical } from '@wordpress/icons'; import { store as coreStore } from '@wordpress/core-data'; -import { useEffect, Fragment } from '@wordpress/element'; +import { useEffect } from '@wordpress/element'; import { usePrevious } from '@wordpress/compose'; /** diff --git a/packages/edit-site/src/components/layout/hooks.js b/packages/edit-site/src/components/layout/hooks.js index 184e1b44896c5b..490fcf39ea622a 100644 --- a/packages/edit-site/src/components/layout/hooks.js +++ b/packages/edit-site/src/components/layout/hooks.js @@ -5,15 +5,9 @@ import { useEffect, useState } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -/** - * Internal dependencies - */ -import useEditedEntityRecord from '../use-edited-entity-record'; - const MAX_LOADING_TIME = 10000; // 10 seconds export function useIsSiteEditorLoading() { - const { isLoaded: hasLoadedPost } = useEditedEntityRecord(); const [ loaded, setLoaded ] = useState( false ); const inLoadingPause = useSelect( ( select ) => { @@ -64,5 +58,5 @@ export function useIsSiteEditorLoading() { } }, [ inLoadingPause ] ); - return ! loaded || ! hasLoadedPost; + return ! loaded; } diff --git a/packages/edit-site/src/components/page-patterns/use-patterns.js b/packages/edit-site/src/components/page-patterns/use-patterns.js index f32e278e6354f5..e226298857c4da 100644 --- a/packages/edit-site/src/components/page-patterns/use-patterns.js +++ b/packages/edit-site/src/components/page-patterns/use-patterns.js @@ -156,7 +156,7 @@ const selectPatterns = createSelector( categoryId, hasCategory: ( item, currentCategory ) => { if ( item.type === PATTERN_TYPES.user ) { - return item.wp_pattern_category.some( + return item.wp_pattern_category?.some( ( catId ) => userPatternCategories.find( ( cat ) => cat.id === catId @@ -173,7 +173,7 @@ const selectPatterns = createSelector( return ( userPatternCategories?.length && ( ! item.wp_pattern_category?.length || - ! item.wp_pattern_category.some( ( catId ) => + ! item.wp_pattern_category?.some( ( catId ) => userPatternCategories.find( ( cat ) => cat.id === catId ) diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index fbff29ed67afa1..a535eef4ce7878 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -18,10 +18,9 @@ import { privateApis as editorPrivateApis } from '@wordpress/editor'; * Internal dependencies */ import Page from '../page'; -import usePostFields from '../post-fields'; import { unlock } from '../../lock-unlock'; -const { PostCardPanel } = unlock( editorPrivateApis ); +const { PostCardPanel, usePostFields } = unlock( editorPrivateApis ); const fieldsWithBulkEditSupport = [ 'title', diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js deleted file mode 100644 index e659a4f96f23f6..00000000000000 --- a/packages/edit-site/src/components/post-fields/index.js +++ /dev/null @@ -1,367 +0,0 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - -/** - * WordPress dependencies - */ -import { __, sprintf } from '@wordpress/i18n'; -import { decodeEntities } from '@wordpress/html-entities'; -import { - featuredImageField, - slugField, - parentField, - passwordField, -} from '@wordpress/fields'; -import { - createInterpolateElement, - useMemo, - useState, -} from '@wordpress/element'; -import { dateI18n, getDate, getSettings } from '@wordpress/date'; -import { - trash, - drafts, - published, - scheduled, - pending, - notAllowed, - commentAuthorAvatar as authorIcon, -} from '@wordpress/icons'; -import { __experimentalHStack as HStack, Icon } from '@wordpress/components'; -import { useSelect } from '@wordpress/data'; -import { useEntityRecords, store as coreStore } from '@wordpress/core-data'; - -/** - * Internal dependencies - */ -import { - LAYOUT_GRID, - LAYOUT_TABLE, - OPERATOR_IS_ANY, -} from '../../utils/constants'; -import { default as Link } from '../routes/link'; - -// See https://github.com/WordPress/gutenberg/issues/55886 -// We do not support custom statutes at the moment. -const STATUSES = [ - { - value: 'draft', - label: __( 'Draft' ), - icon: drafts, - description: __( 'Not ready to publish.' ), - }, - { - value: 'future', - label: __( 'Scheduled' ), - icon: scheduled, - description: __( 'Publish automatically on a chosen date.' ), - }, - { - value: 'pending', - label: __( 'Pending Review' ), - icon: pending, - description: __( 'Waiting for review before publishing.' ), - }, - { - value: 'private', - label: __( 'Private' ), - icon: notAllowed, - description: __( 'Only visible to site admins and editors.' ), - }, - { - value: 'publish', - label: __( 'Published' ), - icon: published, - description: __( 'Visible to everyone.' ), - }, - { value: 'trash', label: __( 'Trash' ), icon: trash }, -]; - -const getFormattedDate = ( dateToDisplay ) => - dateI18n( - getSettings().formats.datetimeAbbreviated, - getDate( dateToDisplay ) - ); - -function PostStatusField( { item } ) { - const status = STATUSES.find( ( { value } ) => value === item.status ); - const label = status?.label || item.status; - const icon = status?.icon; - return ( - - { icon && ( -
    - -
    - ) } - { label } -
    - ); -} - -function PostAuthorField( { item } ) { - const { text, imageUrl } = useSelect( - ( select ) => { - const { getUser } = select( coreStore ); - const user = getUser( item.author ); - return { - imageUrl: user?.avatar_urls?.[ 48 ], - text: user?.name, - }; - }, - [ item ] - ); - const [ isImageLoaded, setIsImageLoaded ] = useState( false ); - return ( - - { !! imageUrl && ( -
    - setIsImageLoaded( true ) } - alt={ __( 'Author avatar' ) } - src={ imageUrl } - /> -
    - ) } - { ! imageUrl && ( -
    - -
    - ) } - { text } -
    - ); -} - -function usePostFields( viewType ) { - const { records: authors, isResolving: isLoadingAuthors } = - useEntityRecords( 'root', 'user', { per_page: -1 } ); - - const { frontPageId, postsPageId } = useSelect( ( select ) => { - const { getEntityRecord } = select( coreStore ); - const siteSettings = getEntityRecord( 'root', 'site' ); - return { - frontPageId: siteSettings?.page_on_front, - postsPageId: siteSettings?.page_for_posts, - }; - }, [] ); - - const fields = useMemo( - () => [ - featuredImageField, - { - label: __( 'Title' ), - id: 'title', - type: 'text', - getValue: ( { item } ) => - typeof item.title === 'string' - ? item.title - : item.title?.raw, - render: ( { item } ) => { - const addLink = - [ LAYOUT_TABLE, LAYOUT_GRID ].includes( viewType ) && - item.status !== 'trash'; - const renderedTitle = - typeof item.title === 'string' - ? item.title - : item.title?.rendered; - const title = addLink ? ( - - { decodeEntities( renderedTitle ) || - __( '(no title)' ) } - - ) : ( - - { decodeEntities( renderedTitle ) || - __( '(no title)' ) } - - ); - - let suffix = ''; - if ( item.id === frontPageId ) { - suffix = ( - - { __( 'Homepage' ) } - - ); - } else if ( item.id === postsPageId ) { - suffix = ( - - { __( 'Posts Page' ) } - - ); - } - - return ( - - { title } - { suffix } - - ); - }, - enableHiding: false, - }, - { - label: __( 'Author' ), - id: 'author', - type: 'integer', - elements: - authors?.map( ( { id, name } ) => ( { - value: id, - label: name, - } ) ) || [], - render: PostAuthorField, - sort: ( a, b, direction ) => { - const nameA = a._embedded?.author?.[ 0 ]?.name || ''; - const nameB = b._embedded?.author?.[ 0 ]?.name || ''; - - return direction === 'asc' - ? nameA.localeCompare( nameB ) - : nameB.localeCompare( nameA ); - }, - }, - { - label: __( 'Status' ), - id: 'status', - type: 'text', - elements: STATUSES, - render: PostStatusField, - Edit: 'radio', - enableSorting: false, - filterBy: { - operators: [ OPERATOR_IS_ANY ], - }, - }, - { - label: __( 'Date' ), - id: 'date', - type: 'datetime', - render: ( { item } ) => { - const isDraftOrPrivate = [ 'draft', 'private' ].includes( - item.status - ); - if ( isDraftOrPrivate ) { - return createInterpolateElement( - sprintf( - /* translators: %s: page creation or modification date. */ - __( 'Modified: ' ), - getFormattedDate( item.date ) - ), - { - span: , - time: