diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md index cc6b8e4d613513..ce1a0a1acffa54 100644 --- a/.github/SUPPORT.md +++ b/.github/SUPPORT.md @@ -5,7 +5,7 @@ Welcome to Gutenberg, a WordPress project. We hope you join us in creating the f * Please see the [Contributing Guidelines](https://github.com/WordPress/gutenberg/blob/HEAD/CONTRIBUTING.md) for additional information on how to contribute. -* As with all WordPress projects, we want to ensure a welcoming environment for everyone. With that in mind, all contributors are expected to follow our [Code of Conduct](https://github.com/WordPress/gutenberg/blob/HEAD/CODE_OF_CONDUCT.md). +* As with all WordPress projects, we want to ensure a welcoming environment for everyone. With that in mind, all contributors are expected to follow our [Code of Conduct](https://make.wordpress.org/handbook/community-code-of-conduct/). * Join us on Slack for real-time communication, it is where maintainers coordinate around the project. To get started using Slack, see: https://make.wordpress.org/chat/ diff --git a/.gitignore b/.gitignore index 48cd7580beed14..f699ecfcd4b9ba 100644 --- a/.gitignore +++ b/.gitignore @@ -48,4 +48,5 @@ test/storybook-playwright/specs/__snapshots__ test/storybook-playwright/specs/*-snapshots/** test/gutenberg-test-themes/twentytwentyone test/gutenberg-test-themes/twentytwentythree +test/gutenberg-test-themes/twentytwentyfour packages/react-native-editor/src/setup-local.js diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index f9afa872a60842..00000000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,11 +0,0 @@ -This project comes under the WordPress [Etiquette](https://wordpress.org/about/etiquette/): - -In the WordPress open source project, we realize that our biggest asset is the community that we foster. The project, as a whole, follows these basic philosophical principles from The Cathedral and The Bazaar. - -- Contributions to the WordPress open source project are for the benefit of the WordPress community as a whole, not specific businesses or individuals. All actions taken as a contributor should be made with the best interests of the community in mind. -- Participation in the WordPress open source project is open to all who wish to join, regardless of ability, skill, financial status, or any other criteria. -- The WordPress open source project is a volunteer-run community. Even in cases where contributors are sponsored by companies, that time is donated for the benefit of the entire open source community. -- Any member of the community can donate their time and contribute to the project in any form including design, code, documentation, community building, etc. For more information, go to make.wordpress.org. -- The WordPress open source community cares about diversity. We strive to maintain a welcoming environment where everyone can feel included, by keeping communication free of discrimination, incitement to violence, promotion of hate, and unwelcoming behavior. - -The team involved will block any user who causes any breach in this. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cd137ea37201c9..8eb4b77dbfcca9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ To learn all about contributing to the Gutenberg project, see the [Contributor G ## Guidelines -- As with all WordPress projects, we want to ensure a welcoming environment for everyone. With that in mind, all contributors are expected to follow our [Code of Conduct](/CODE_OF_CONDUCT.md). +- As with all WordPress projects, we want to ensure a welcoming environment for everyone. With that in mind, all contributors are expected to follow our [Code of Conduct](https://make.wordpress.org/handbook/community-code-of-conduct/). - Contributors should review the [overall process and best practices for pull requests](https://github.com/WordPress/gutenberg/blob/trunk/docs/contributors/repository-management.md#pull-requests), adhering to WordPress' [JavaScript coding standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/javascript/) and [accessibility coding standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/accessibility/). diff --git a/README.md b/README.md index d5b299baadc7f8..33f76716470751 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ To get up and running quickly with **code contribution** see [Getting Started Wi In whichever way you wish to contribute please be sure to read the [Contributing Guidelines](https://github.com/WordPress/gutenberg/blob/HEAD/CONTRIBUTING.md) first. -As with all WordPress projects, we want to ensure a welcoming environment for everyone. With that in mind, all contributors are expected to follow our [Code of Conduct](https://github.com/WordPress/gutenberg/blob/HEAD/CODE_OF_CONDUCT.md). +As with all WordPress projects, we want to ensure a welcoming environment for everyone. With that in mind, all contributors are expected to follow our [Code of Conduct](https://make.wordpress.org/handbook/community-code-of-conduct/). ## Get Involved diff --git a/changelog.txt b/changelog.txt index c11c4246a60bdb..9505059dd3b706 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,609 @@ == Changelog == += 17.7.0 = + +## Changelog + + +### Enhancements + +- Improve translators comments for wp.date.setSettings in compat file. ([58488](https://github.com/WordPress/gutenberg/pull/58488)) +- Interactive Template: Use viewScriptModule. ([58211](https://github.com/WordPress/gutenberg/pull/58211)) + +#### Components + +- Adding `constrainTabbing` prop to `useDialog` hook. ([57962](https://github.com/WordPress/gutenberg/pull/57962)) +- Allow limiting the number of maximum visible Snackbars. ([58559](https://github.com/WordPress/gutenberg/pull/58559)) +- ConfirmDialog: Add `__next40pxDefaultSize` to buttons. ([58421](https://github.com/WordPress/gutenberg/pull/58421)) +- Expand theming support in COLORS. ([58097](https://github.com/WordPress/gutenberg/pull/58097)) +- FocalPointPicker: Apply modern styling. ([58459](https://github.com/WordPress/gutenberg/pull/58459)) +- Implement Tabs in widget editor settings. ([57886](https://github.com/WordPress/gutenberg/pull/57886)) +- Implement `Tabs` in site-editor settings. ([56959](https://github.com/WordPress/gutenberg/pull/56959)) +- Implementing `useCompositeState` with Ariakit. ([57304](https://github.com/WordPress/gutenberg/pull/57304)) +- InputBase: Add `isBorderless` prop. ([58750](https://github.com/WordPress/gutenberg/pull/58750)) +- Replace `TabPanel` with `Tabs` in the editor Document Overview sidebar. ([57082](https://github.com/WordPress/gutenberg/pull/57082)) +- SearchControl: Refactor to use InputControl internally. ([56524](https://github.com/WordPress/gutenberg/pull/56524)) +- Show borders for disabled secondary buttons. ([58606](https://github.com/WordPress/gutenberg/pull/58606)) + +#### Data Views + +- Add outline to template preview in table layout. ([58738](https://github.com/WordPress/gutenberg/pull/58738)) +- Add: Delete bulk action to patterns. ([58747](https://github.com/WordPress/gutenberg/pull/58747)) +- Add: Selection and bulk actions to grid view. ([58144](https://github.com/WordPress/gutenberg/pull/58144)) +- DataViews: Add primary filter API. ([58427](https://github.com/WordPress/gutenberg/pull/58427)) +- DataViews: In patterns page, show sync status filter by default. ([58367](https://github.com/WordPress/gutenberg/pull/58367)) +- DataViews: Redesign of filters. ([58569](https://github.com/WordPress/gutenberg/pull/58569)) +- Remove min-width style on table cells. ([58204](https://github.com/WordPress/gutenberg/pull/58204)) +- Update 'Rows per page' view option label to account for Grid layout. ([58457](https://github.com/WordPress/gutenberg/pull/58457)) +- Update dataviews search input placeholder. ([58742](https://github.com/WordPress/gutenberg/pull/58742)) +- Update spacing around title in grid layout. ([58739](https://github.com/WordPress/gutenberg/pull/58739)) + +#### Interactivity API + +- Add `block supports` for `clientNavigation` and `interactive` properties on `block.json` schema. ([58132](https://github.com/WordPress/gutenberg/pull/58132)) +- Image block: Refactor and remove `data-wp-body`. ([58835](https://github.com/WordPress/gutenberg/pull/58835)) +- Interactivity Router: Fix initial page cache. ([58496](https://github.com/WordPress/gutenberg/pull/58496)) +- Interactivity Router: Move ARIA live region and loading bar to the Interactivity Router. ([58377](https://github.com/WordPress/gutenberg/pull/58377)) +- Limit the exported APIs. ([58864](https://github.com/WordPress/gutenberg/pull/58864)) +- Mark all core block stores as private. ([58722](https://github.com/WordPress/gutenberg/pull/58722)) +- Server Directive Processor for `data-wp-each`. ([58498](https://github.com/WordPress/gutenberg/pull/58498)) +- Support setting a namespace using a string in `data-wp-interactive`. ([58743](https://github.com/WordPress/gutenberg/pull/58743)) +- Allow global configs for namespaces. ([58749](https://github.com/WordPress/gutenberg/pull/58749)) + +#### Block Library + +- Follow up on the Post navigation link taxonomy filters. ([57949](https://github.com/WordPress/gutenberg/pull/57949)) +- Home Link: Render Home text if there is no attribute label present. ([58387](https://github.com/WordPress/gutenberg/pull/58387)) +- Organize gallery controls. ([58407](https://github.com/WordPress/gutenberg/pull/58407)) +- Pattern: Use the '__experimentalLabel' method to get a title. ([58646](https://github.com/WordPress/gutenberg/pull/58646)) +- Social Icons: Update Patreon icon. ([56951](https://github.com/WordPress/gutenberg/pull/56951)) +- Try: Disable text selection for post content placeholder block. ([58169](https://github.com/WordPress/gutenberg/pull/58169)) +- Update pattern block copy in light of pattern overrides. ([58231](https://github.com/WordPress/gutenberg/pull/58231)) +- Add shadow support for column, columns and image. ([57982](https://github.com/WordPress/gutenberg/pull/57982)) + +#### Global Styles + +- Add style engine support for nested at-rules. ([58867](https://github.com/WordPress/gutenberg/pull/58867)) +- Move Shadow controls to Border panel. ([58466](https://github.com/WordPress/gutenberg/pull/58466)) +- Shadow: Update shadow support to allow explicit skipping of serialization. ([58306](https://github.com/WordPress/gutenberg/pull/58306)) +- Try: Remove shadow preset overflow. ([58663](https://github.com/WordPress/gutenberg/pull/58663)) +- Update return values from getGlobalStylesChanges(). ([58707](https://github.com/WordPress/gutenberg/pull/58707)) +- Add support for transform and letter spacing controls in Global Styles > Typography > Elements. ([58142](https://github.com/WordPress/gutenberg/pull/58142)) + +#### Block Editor + +- Drag and drop: Allow dragging from inserter or desktop to template parts. ([58589](https://github.com/WordPress/gutenberg/pull/58589)) +- Drag and drop: Allow dropping within template parts. ([58423](https://github.com/WordPress/gutenberg/pull/58423)) +- Implement "Add block" UI for Nav block Link UI. ([57756](https://github.com/WordPress/gutenberg/pull/57756)) +- Implementing new UX for invoking rich text Link UI. ([57986](https://github.com/WordPress/gutenberg/pull/57986)) +- Remove open in new tab from link preview. ([58744](https://github.com/WordPress/gutenberg/pull/58744)) +- Use consistent labels, remove additional settings, and copySmall icon LinkControl. ([58183](https://github.com/WordPress/gutenberg/pull/58183)) + +#### Site Editor + +- Apply 40px across summary panel. ([58730](https://github.com/WordPress/gutenberg/pull/58730)) +- Apply custom scroll style to fixed header block toolbar. ([57444](https://github.com/WordPress/gutenberg/pull/57444)) +- Improve SiteIcon display and transition. ([58472](https://github.com/WordPress/gutenberg/pull/58472)) +- Only show 'Back' button when user came from an editor canvas. ([58710](https://github.com/WordPress/gutenberg/pull/58710)) +- Update "focus mode" to consistently use the Document Bar's Back button. ([58528](https://github.com/WordPress/gutenberg/pull/58528)) + +#### Patterns + +- Add a confirmation dialog when a user tries to delete a synced pattern with overrides. ([58796](https://github.com/WordPress/gutenberg/pull/58796)) +- Add the block name to the pattern content data. ([58715](https://github.com/WordPress/gutenberg/pull/58715)) +- Flash editable block outlines instead of always showing them. ([58159](https://github.com/WordPress/gutenberg/pull/58159)) + +#### Design Tools + +- Background image support: Add background position controls. ([58592](https://github.com/WordPress/gutenberg/pull/58592)) +- Tweak metrics and labels for background size controls. ([58854](https://github.com/WordPress/gutenberg/pull/58854)) + +#### Post Editor + +- Editor: Limit visible Snackbars from the consumers. ([58598](https://github.com/WordPress/gutenberg/pull/58598)) +- Save entities panel: Update styles. ([58706](https://github.com/WordPress/gutenberg/pull/58706)) + +#### Font Library + +- Add sanitize from schema util. ([58571](https://github.com/WordPress/gutenberg/pull/58571)) +- Font Collections: Update registration function signature and add caching. ([58363](https://github.com/WordPress/gutenberg/pull/58363)) +- Font Library: Show 'Add fonts' button when there are no fonts installed. ([58580](https://github.com/WordPress/gutenberg/pull/58580)) + +#### Inspector Controls + +- Tweak FocalPointPicker inspector controls. ([58448](https://github.com/WordPress/gutenberg/pull/58448)) +- Tweak Media & Text inspector controls. ([58447](https://github.com/WordPress/gutenberg/pull/58447)) + +#### Custom Fields + +- Block Bindings: Ensure to pass bound attributes. ([58844](https://github.com/WordPress/gutenberg/pull/58844)) + +#### Commands + +- Try debouncing search for post-type navigation. ([58810](https://github.com/WordPress/gutenberg/pull/58810)) + +#### Document Settings + +- Tweak revisions panel for improved scanning. ([58751](https://github.com/WordPress/gutenberg/pull/58751)) + +#### Synced Patterns + +- Support button's link settings for Pattern Overrides. ([58587](https://github.com/WordPress/gutenberg/pull/58587)) + +#### Block API + +- Block Hooks: Set ignoredHookedBlocks metada attr upon insertion. ([58553](https://github.com/WordPress/gutenberg/pull/58553)) + +#### List View + +- Add keyboard clipboard events for cut, copy, paste. ([57838](https://github.com/WordPress/gutenberg/pull/57838)) + + +### New APIs + +#### Block API + +- Blocks: Add handling for block.json viewScriptModule. ([58731](https://github.com/WordPress/gutenberg/pull/58731)) + + +### Bug Fixes + +- Core data: useEntityBlockEditor: Fix parsed blocks cache. ([58841](https://github.com/WordPress/gutenberg/pull/58841)) +- Footnotes: Fix anchor order replacing. ([58791](https://github.com/WordPress/gutenberg/pull/58791)) + +#### Block Editor + +- Block Switcher: Use consistent labels. ([58240](https://github.com/WordPress/gutenberg/pull/58240)) +- Don't move focus within the toolbar if it is already focused. ([58570](https://github.com/WordPress/gutenberg/pull/58570)) +- Don't show Link preview when no selection. ([58771](https://github.com/WordPress/gutenberg/pull/58771)) +- Fix Link UI popover anchor in rich text. ([58282](https://github.com/WordPress/gutenberg/pull/58282)) +- Fix empty link preview after creating link from empty selection. ([58863](https://github.com/WordPress/gutenberg/pull/58863)) +- Hide the 'Content' panel for locked blocks when there's no content. ([58259](https://github.com/WordPress/gutenberg/pull/58259)) +- ImageURLInputUI: Fix focus loss when settings are changed. ([58647](https://github.com/WordPress/gutenberg/pull/58647)) +- Link UI: Polish lightbox pieces. ([58666](https://github.com/WordPress/gutenberg/pull/58666)) +- Media Replace Flow: Vertically align the URL. ([58621](https://github.com/WordPress/gutenberg/pull/58621)) +- MediaReplaceFlow: Restore popover width. ([58597](https://github.com/WordPress/gutenberg/pull/58597)) +- Rich Text: Only apply focus to elements, not selection. ([58745](https://github.com/WordPress/gutenberg/pull/58745)) +- Rich text: Preserve white space should strip \r. ([58805](https://github.com/WordPress/gutenberg/pull/58805)) +- Settings may be undefined. ([58658](https://github.com/WordPress/gutenberg/pull/58658)) +- useOnBlockDrop: Fix the Gallery block check. ([58711](https://github.com/WordPress/gutenberg/pull/58711)) + +#### Components + +- Add a timezone offset value for display purposes. ([56682](https://github.com/WordPress/gutenberg/pull/56682)) +- Fix Placeholder component padding when body text font size is changed. ([58323](https://github.com/WordPress/gutenberg/pull/58323)) +- Fix URLPopover preview overflow. ([58741](https://github.com/WordPress/gutenberg/pull/58741)) +- Fix the Snackbar auto-dismissal timers. ([58604](https://github.com/WordPress/gutenberg/pull/58604)) +- Popover: Add `box-sizing` reset style. ([58871](https://github.com/WordPress/gutenberg/pull/58871)) +- Set post editor sidebar tabs to manual activation. ([58041](https://github.com/WordPress/gutenberg/pull/58041)) +- Tabs: Delay `activeId` updates until focus can be properly detected. ([58625](https://github.com/WordPress/gutenberg/pull/58625)) +- Tabs: Fix infinite loop in useEffect. ([58861](https://github.com/WordPress/gutenberg/pull/58861)) +- Tabs: Improve Controlled Mode Focus Handling. ([57696](https://github.com/WordPress/gutenberg/pull/57696)) +- Try: Fix lightbox URL popover position. ([58600](https://github.com/WordPress/gutenberg/pull/58600)) + +#### Block Library + +- Fix [#54352](https://github.com/WordPress/gutenberg/issues/54352) prevents php 8.1 fatal when template parts are not found in non-debug environments. ([54354](https://github.com/WordPress/gutenberg/pull/54354)) +- Fix Query pagination not working in template parts and patterns. ([58602](https://github.com/WordPress/gutenberg/pull/58602)) +- Fix URL escaping for array parameters in Navigation links. ([58068](https://github.com/WordPress/gutenberg/pull/58068)) +- Fix missing data in email submissions. ([55691](https://github.com/WordPress/gutenberg/pull/55691)) +- Fix: Removing footnotes from the allowed blocks does not remove footnotes. ([58855](https://github.com/WordPress/gutenberg/pull/58855)) +- Navigation Link: Use get_block_type_variations to register variations. ([58389](https://github.com/WordPress/gutenberg/pull/58389)) +- Prevent usage of `gutenberg_url` in block-library. ([58242](https://github.com/WordPress/gutenberg/pull/58242)) +- Template Part: Reflect name updates without saving changes. ([58644](https://github.com/WordPress/gutenberg/pull/58644)) +- Try: Make gallery randomization work when nested. ([58733](https://github.com/WordPress/gutenberg/pull/58733)) + +#### Data Views + +- DataViews: Fix applied default layout props. ([58400](https://github.com/WordPress/gutenberg/pull/58400)) +- DataViews: Fix nested buttons and placeholder text in list layout. ([58304](https://github.com/WordPress/gutenberg/pull/58304)) +- DataViews: Fix some small issues with featured image. ([58371](https://github.com/WordPress/gutenberg/pull/58371)) +- DataViews: Make it possible to toggle Author field in templates and template parts. ([58609](https://github.com/WordPress/gutenberg/pull/58609)) +- DataViews: Remove test artifact (status filter was set as primary). ([58682](https://github.com/WordPress/gutenberg/pull/58682)) +- DataViews: Use chips for filter summary. ([58816](https://github.com/WordPress/gutenberg/pull/58816)) +- Fix double scrollbar in grid layout. ([58536](https://github.com/WordPress/gutenberg/pull/58536)) +- Fix: Dataviews selection on patterns grid view. ([58726](https://github.com/WordPress/gutenberg/pull/58726)) + +#### Site Editor + +- Add context for the All translatable string and enforce l10n best practices. ([58196](https://github.com/WordPress/gutenberg/pull/58196)) +- Break long URL in page sidebar. ([58763](https://github.com/WordPress/gutenberg/pull/58763)) +- Editor: Fix block context defined for template parts. ([58807](https://github.com/WordPress/gutenberg/pull/58807)) +- Fix line-height in block card. ([58246](https://github.com/WordPress/gutenberg/pull/58246)) +- Hide export button if non-block-based theme. ([58346](https://github.com/WordPress/gutenberg/pull/58346)) +- Mobile site editor header toolbar button bugfix. ([58852](https://github.com/WordPress/gutenberg/pull/58852)) + +#### Post Editor + +- Editor: Don't hide authors' Combobox if the current author is missing. ([58719](https://github.com/WordPress/gutenberg/pull/58719)) +- Fix permalink input field text overflow ellipsis for Firefox. ([57310](https://github.com/WordPress/gutenberg/pull/57310)) +- Fix the position and size of the Options menu,. ([57515](https://github.com/WordPress/gutenberg/pull/57515)) +- Fix: Use old template panel if user doesn’t have access to view templates. ([58485](https://github.com/WordPress/gutenberg/pull/58485)) +- Template editing: Update fullscreen WP back functionality. ([58534](https://github.com/WordPress/gutenberg/pull/58534)) + +#### Interactivity API + +- Add `supports.interactivity` to the Query block. ([58316](https://github.com/WordPress/gutenberg/pull/58316)) +- Fix state intialization for asynchronous private stores. ([58754](https://github.com/WordPress/gutenberg/pull/58754)) +- Remove non-default suffix data wp context processing. ([58664](https://github.com/WordPress/gutenberg/pull/58664)) +- Use compat versions of HTML APIs. ([58846](https://github.com/WordPress/gutenberg/pull/58846)) + +#### Global Styles + +- Block Styles: Fix block style variation selector generation. ([58051](https://github.com/WordPress/gutenberg/pull/58051)) +- Fix Global styles text settings bleeding into placeholder component. ([58303](https://github.com/WordPress/gutenberg/pull/58303)) +- Global styles revisions: Fix is-selected rules from affecting other areas of the editor. ([58228](https://github.com/WordPress/gutenberg/pull/58228)) +- Site Editor: Prevent classic theme from accessing global style menu. ([58345](https://github.com/WordPress/gutenberg/pull/58345)) + +#### List View + +- Fix error when switching between template preview modes. ([58533](https://github.com/WordPress/gutenberg/pull/58533)) +- Navigation Submenu Block: Make block name affect list view. ([58296](https://github.com/WordPress/gutenberg/pull/58296)) +- Template Part: Fix site editor error when loading with list view set to always display. ([58868](https://github.com/WordPress/gutenberg/pull/58868)) + +#### Font Library + +- Avoid mutating fontface data. ([58473](https://github.com/WordPress/gutenberg/pull/58473)) +- Avoid running init functions when font library is available in core. ([58793](https://github.com/WordPress/gutenberg/pull/58793)) +- Fix size of demo text. ([58849](https://github.com/WordPress/gutenberg/pull/58849)) + +#### Typography + +- Fix font library modal dialog translatable strings. ([58256](https://github.com/WordPress/gutenberg/pull/58256)) +- Font Library: Change referenced tab name on Google Fonts confirmation dialog. ([58584](https://github.com/WordPress/gutenberg/pull/58584)) +- Font size: Allow for custom font size handling. ([58422](https://github.com/WordPress/gutenberg/pull/58422)) + +#### Script Modules API + +- Add import map polyfill. ([58263](https://github.com/WordPress/gutenberg/pull/58263)) +- Import Maps: Only emit CDATA wrappers for inline scripts for JavaScript. ([58818](https://github.com/WordPress/gutenberg/pull/58818)) + +#### Extensibility + +- Fix broken list markup in navigation block when 3rd party blocks are used as decendants of navigation block. ([55551](https://github.com/WordPress/gutenberg/pull/55551)) +- Navigation block: Check Block Hooks API callback hasn't already been added. ([58772](https://github.com/WordPress/gutenberg/pull/58772)) + +#### Synced Patterns + +- Disable overriding links of images inside pattern instances. ([58660](https://github.com/WordPress/gutenberg/pull/58660)) +- Fix nested pattern overrides and disable editing inner pattern. ([58541](https://github.com/WordPress/gutenberg/pull/58541)) + +#### Inspector Controls + +- Add missing PanelBody title for the columns block inspector. ([58452](https://github.com/WordPress/gutenberg/pull/58452)) +- Add spacing between input controls with custom values. ([58410](https://github.com/WordPress/gutenberg/pull/58410)) + +#### Custom Fields + +- Block Bindings: Update bindings registry with latest changes. ([58843](https://github.com/WordPress/gutenberg/pull/58843)) + +#### History + +- Columns: Batch vertical alignment updates. ([58801](https://github.com/WordPress/gutenberg/pull/58801)) + +#### Document Settings + +- Editor: Ensure the current author is included in the dropdown. ([58716](https://github.com/WordPress/gutenberg/pull/58716)) + +#### Rich Text + +- Add aria-readonly attribute to Rich Text component. ([58687](https://github.com/WordPress/gutenberg/pull/58687)) + +#### Navigation Menus + +- Navigation: Update the fallback block list to avoid a PHP Warning. ([58588](https://github.com/WordPress/gutenberg/pull/58588)) + +#### Patterns + +- Update the bindings attribs of blocks added during experimental phase. ([58483](https://github.com/WordPress/gutenberg/pull/58483)) + +#### Distraction Free + +- Add default restoration of UI when exiting distraction free mode. ([58455](https://github.com/WordPress/gutenberg/pull/58455)) + + +### Accessibility + +- Escape as Select/Edit mode Toggle. ([58637](https://github.com/WordPress/gutenberg/pull/58637)) +- Global styles revisions: Update text color contrast. ([58340](https://github.com/WordPress/gutenberg/pull/58340)) + +#### Components + +- CustomSelect: Disable `virtualFocus` to fix issue for screenreaders. ([58585](https://github.com/WordPress/gutenberg/pull/58585)) +- Font Library modal: Try to improve checkbox labelling. ([58339](https://github.com/WordPress/gutenberg/pull/58339)) +- PaletteEdit: Fix palette item accessibility. ([58214](https://github.com/WordPress/gutenberg/pull/58214)) + +#### Font Library + +- Buttons position and accessibility. ([58212](https://github.com/WordPress/gutenberg/pull/58212)) +- Fix focus loss when update/install button is pressed. ([58364](https://github.com/WordPress/gutenberg/pull/58364)) +- Removed and elements from Font Library Modal. ([58221](https://github.com/WordPress/gutenberg/pull/58221)) + +#### Block Library + +- Fix image link preset suggestions arrow key navigation. ([58615](https://github.com/WordPress/gutenberg/pull/58615)) + +#### CSS & Styling + +- Font Library: Fix font preview vertical alignment and respect reduce motion preference. ([58451](https://github.com/WordPress/gutenberg/pull/58451)) + +#### Widgets Editor + +- Widget Editor: Don't disable the Save button. ([58365](https://github.com/WordPress/gutenberg/pull/58365)) + +#### Typography + +- Fix fonts modal dialog buttons accessibility. ([58309](https://github.com/WordPress/gutenberg/pull/58309)) + +#### Commands + +- Fix labeling of the command palette. ([56718](https://github.com/WordPress/gutenberg/pull/56718)) + + +### Performance + +- Block editor: Optimise getGlobalBlockCount/getClientIdsWithDescendants. ([58356](https://github.com/WordPress/gutenberg/pull/58356)) +- Block editor: Prevent isSubtreeDisabled call if not needed. ([58349](https://github.com/WordPress/gutenberg/pull/58349)) +- Block editor: Reduce appender sync! subscriptions. ([58556](https://github.com/WordPress/gutenberg/pull/58556)) +- Block editor: selectors: Avoid has() or double get() on Maps. ([58372](https://github.com/WordPress/gutenberg/pull/58372)) +- Block preview: Prevent recalculating editor styles if additional styles is empty. ([58244](https://github.com/WordPress/gutenberg/pull/58244)) +- Image block: Remove a block editor store sub. ([57232](https://github.com/WordPress/gutenberg/pull/57232)) +- Inner blocks: Don't re-render list when controlled blocks change. ([58575](https://github.com/WordPress/gutenberg/pull/58575)) +- InnerBlocks: Fix continuous re-rendering on inner blocks change. ([58348](https://github.com/WordPress/gutenberg/pull/58348)) +- Navigation: Fix performance regression. ([58513](https://github.com/WordPress/gutenberg/pull/58513)) +- Post template: Don't fetch taxonomies if not needed. ([58245](https://github.com/WordPress/gutenberg/pull/58245)) +- Site editor: Add pattern/template load performance test with TT4. ([58734](https://github.com/WordPress/gutenberg/pull/58734)) +- Site editor: Avoid double post content parse (alternative). ([58146](https://github.com/WordPress/gutenberg/pull/58146)) +- Unmemoize Block component selectors. ([58355](https://github.com/WordPress/gutenberg/pull/58355)) +- core-data: Memoize `getEntitiesConfig` selector. ([58393](https://github.com/WordPress/gutenberg/pull/58393)) +- getBlockSettings: Avoid memoized selector with clientId. ([58405](https://github.com/WordPress/gutenberg/pull/58405)) +- useSettings: Extract selector. ([58354](https://github.com/WordPress/gutenberg/pull/58354)) + +#### Font Library + +- Font Collections: Lazy load json configuration for better performance. ([58530](https://github.com/WordPress/gutenberg/pull/58530)) + +#### List View + +- Unmemo recursive getEnabledClientIdsTree. ([58525](https://github.com/WordPress/gutenberg/pull/58525)) + +#### Block Editor + +- Optimize the 'useBlockDisplayTitle' hook. ([58250](https://github.com/WordPress/gutenberg/pull/58250)) + +#### Interactivity API + +- Break up long hydration task in interactivity init. ([58227](https://github.com/WordPress/gutenberg/pull/58227)) + + +### Experiments + +#### Data Views + +- Update styling details in list item layout. ([58397](https://github.com/WordPress/gutenberg/pull/58397)) + +#### Synced Patterns + +- Add a control per block to reset pattern overrides. ([57907](https://github.com/WordPress/gutenberg/pull/57907)) + + +### Documentation + +- Add video embed documentation and grammar fixes in the Block Editor Handbook. ([58029](https://github.com/WordPress/gutenberg/pull/58029)) +- Block API: Add `viewStyle` property support to `block.json`. ([55492](https://github.com/WordPress/gutenberg/pull/55492)) +- CheckboxControl: Add custom label example to Storybook. ([58438](https://github.com/WordPress/gutenberg/pull/58438)) +- Docs: Copy and formatting edits for the "Markup representation of a block" guide. ([58688](https://github.com/WordPress/gutenberg/pull/58688)) +- Docs: Copy and formatting edits for the "Registration of a block" guide. ([58709](https://github.com/WordPress/gutenberg/pull/58709)) +- Docs: Copy and formatting edits for the "Static or Dynamic rendering" guide. ([58681](https://github.com/WordPress/gutenberg/pull/58681)) +- Docs: Copy and formatting edits for the "The block in the Editor" guide. ([58697](https://github.com/WordPress/gutenberg/pull/58697)) +- Docs: Copy and formatting edits for the "The block wrapper" guide. ([58704](https://github.com/WordPress/gutenberg/pull/58704)) +- Docs: Copy and formatting edits for the "Working with Javascript for the Block Editor" guide. ([58651](https://github.com/WordPress/gutenberg/pull/58651)) +- Docs: Copy and formatting edits for the "block.json" guide. ([58732](https://github.com/WordPress/gutenberg/pull/58732)) +- Docs: Copy edits and list formatting for main Block Editor Handbook readme. ([58652](https://github.com/WordPress/gutenberg/pull/58652)) +- Docs: Fix list formatting and some grammar in the Entities explanation doc. ([58655](https://github.com/WordPress/gutenberg/pull/58655)) +- Docs: Fix list markup in the Fundamentals of Block Development section. ([58226](https://github.com/WordPress/gutenberg/pull/58226)) +- Docs: Fix mistake in viewScriptModule documentation. ([58815](https://github.com/WordPress/gutenberg/pull/58815)) +- Docs: Formatting and copy edits for the File structure of a block guide. ([58635](https://github.com/WordPress/gutenberg/pull/58635)) +- Docs: Minor copy edits for the Block Development Environment page. ([58614](https://github.com/WordPress/gutenberg/pull/58614)) +- Docs: Remove duplicate content and update links. ([58358](https://github.com/WordPress/gutenberg/pull/58358)) +- Docs: Update link to the correct Fundamentals doc. ([58352](https://github.com/WordPress/gutenberg/pull/58352)) +- Docs: Update list formatting and descriptions in the Fundamentals of Block Development doc. ([58630](https://github.com/WordPress/gutenberg/pull/58630)) +- Docs: Update the Getting Started readme in the Block Editor Handbook. ([58624](https://github.com/WordPress/gutenberg/pull/58624)) +- Reference Gutenberg in PHP documentation from main documentation. ([58453](https://github.com/WordPress/gutenberg/pull/58453)) +- Removed extra parenthesis from document. ([58662](https://github.com/WordPress/gutenberg/pull/58662)) +- Restructure the FAQs to work with the new TOC design in the Block Editor Handbook. ([58351](https://github.com/WordPress/gutenberg/pull/58351)) +- Storybook: Add badges to private components. ([58123](https://github.com/WordPress/gutenberg/pull/58123)) +- Update documentation to avoid recommending early return PHP "anti-pattern". ([58454](https://github.com/WordPress/gutenberg/pull/58454)) +- Update to rename reusable blocks. ([58633](https://github.com/WordPress/gutenberg/pull/58633)) +- Update versions-in-wordpress.md. ([58545](https://github.com/WordPress/gutenberg/pull/58545)) +- fix: InnerBlocks schema description in block.json. ([58649](https://github.com/WordPress/gutenberg/pull/58649)) + + +### Code Quality + +- Avoid running pattern overrides migration in WordPress core. ([58487](https://github.com/WordPress/gutenberg/pull/58487)) +- Build: Add package build shebang and sync comments. ([58264](https://github.com/WordPress/gutenberg/pull/58264)) +- Date: Merge 6.4 and 6.5 compat files. ([58479](https://github.com/WordPress/gutenberg/pull/58479)) +- DefaultBlockAppender: Refactor to hooks. ([58809](https://github.com/WordPress/gutenberg/pull/58809)) +- Docs: Clarify the non-contextual post types. ([58836](https://github.com/WordPress/gutenberg/pull/58836)) +- Layout block supports use `str_contains`. ([58251](https://github.com/WordPress/gutenberg/pull/58251)) +- Move Nav Link PHPUnit tests to blocks directory. ([58460](https://github.com/WordPress/gutenberg/pull/58460)) + +#### Font Library + +- Address feedback from wordpress-develop#6027. ([58691](https://github.com/WordPress/gutenberg/pull/58691)) +- Fix font library unit tests nit-picks [round 2]. ([58612](https://github.com/WordPress/gutenberg/pull/58612)) +- Font Collections: Standardizes docblock comments. ([58654](https://github.com/WordPress/gutenberg/pull/58654)) +- Font Library Address Outstanding Feedback from WP 6.4 review. ([58675](https://github.com/WordPress/gutenberg/pull/58675)) +- Move Fonts Library to compat dir for 6.5. ([58608](https://github.com/WordPress/gutenberg/pull/58608)) +- Remove font family and font face preview keys from theme.json schema. ([58395](https://github.com/WordPress/gutenberg/pull/58395)) +- Remove old and unused component and css. ([58449](https://github.com/WordPress/gutenberg/pull/58449)) +- Remove slug from collection schema to accommodate the changes on the wp_register_font_collection function signature. ([58623](https://github.com/WordPress/gutenberg/pull/58623)) +- Remove tests from classes that were already merged in core. ([58752](https://github.com/WordPress/gutenberg/pull/58752)) +- Remove tests from font library rest controllers already merged into core. ([58778](https://github.com/WordPress/gutenberg/pull/58778)) +- Return null if a font collection is not registered. ([58735](https://github.com/WordPress/gutenberg/pull/58735)) +- Simplify font collection schema. ([58574](https://github.com/WordPress/gutenberg/pull/58574)) +- Update Font Library REST API code to align with Core standards. ([58619](https://github.com/WordPress/gutenberg/pull/58619)) +- Update Font Library non-REST API code to align with Core standards. ([58607](https://github.com/WordPress/gutenberg/pull/58607)) +- Update font collection json schema. ([58413](https://github.com/WordPress/gutenberg/pull/58413)) +- Update fonts collection data URL for Gutenberg 17.7. ([58746](https://github.com/WordPress/gutenberg/pull/58746)) +- Use Button's API to disable footer buttons. ([58529](https://github.com/WordPress/gutenberg/pull/58529)) +- [Font Library] Update PHPUnit tests per Core coding standards and practices. ([58502](https://github.com/WordPress/gutenberg/pull/58502)) + +#### Components + +- Add eslint rule for theme var regressions. ([58130](https://github.com/WordPress/gutenberg/pull/58130)) +- Add stylelint rule for theme var regressions. ([58098](https://github.com/WordPress/gutenberg/pull/58098)) +- AnglePickerControl: Hard deprecate bottom margin. ([58700](https://github.com/WordPress/gutenberg/pull/58700)) +- CustomGradientPicker: Hard deprecate outer margins. ([58699](https://github.com/WordPress/gutenberg/pull/58699)) +- FontSizePicker: Hard deprecate bottom margin. ([58702](https://github.com/WordPress/gutenberg/pull/58702)) +- GradientPicker: Hard deprecate outer margins. ([58701](https://github.com/WordPress/gutenberg/pull/58701)) +- Remove deprecation warnings for `__next36pxDefaultSize`. ([58703](https://github.com/WordPress/gutenberg/pull/58703)) + +#### Block Library + +- Interactivity API - Blocks: Move interactivity registration to render. ([58678](https://github.com/WordPress/gutenberg/pull/58678)) +- Navigation: Move the Navigation block rendering tests to the blocks directory. ([58247](https://github.com/WordPress/gutenberg/pull/58247)) +- Navigation: Remove use of Gutenberg_Navigation_Fallback class. ([58369](https://github.com/WordPress/gutenberg/pull/58369)) +- Paragraph: Update comment block. ([58419](https://github.com/WordPress/gutenberg/pull/58419)) +- Rename variation build methods. ([58538](https://github.com/WordPress/gutenberg/pull/58538)) +- Template Part: Derive 'hasInnerBlocks' inside selector. ([58680](https://github.com/WordPress/gutenberg/pull/58680)) + +#### Block Editor + +- Block Switcher: Don't use the 'useBlockDisplayInformation' hook. ([58562](https://github.com/WordPress/gutenberg/pull/58562)) +- BlockSelectionButton: Don't use the 'useBlockDisplayInformation' hook. ([58640](https://github.com/WordPress/gutenberg/pull/58640)) +- Link Control: Simplify the sprintf. ([58831](https://github.com/WordPress/gutenberg/pull/58831)) +- RichTextData: Use a private property. ([58557](https://github.com/WordPress/gutenberg/pull/58557)) + +#### Post Editor + +- Editor Settings: Rename the getPostLinkProps setting. ([58416](https://github.com/WordPress/gutenberg/pull/58416)) +- Editor: Reuse data query in the post author components. ([58760](https://github.com/WordPress/gutenberg/pull/58760)) +- Editor: Use hooks instead of HoCs in the post-taxonomies components. ([58446](https://github.com/WordPress/gutenberg/pull/58446)) +- Fix: Refactor pre publish panel to use function component instead of class. ([58441](https://github.com/WordPress/gutenberg/pull/58441)) + +#### Custom Fields + +- Block Bindings: Remove unneeded 'setAttributes' override. ([58806](https://github.com/WordPress/gutenberg/pull/58806)) + +#### Patterns + +- Pattern overrides: Update overrides attribute data structure and rename it to `content`. ([58596](https://github.com/WordPress/gutenberg/pull/58596)) + + +### Tools + +- Add BlockJsonDependenciesPlugin to modules build. ([57927](https://github.com/WordPress/gutenberg/pull/57927)) +- DEWP: Fix script module import field. ([58770](https://github.com/WordPress/gutenberg/pull/58770)) +- Introduce a Props Bot workflow. ([58576](https://github.com/WordPress/gutenberg/pull/58576)) +- More refinements to Props Bot run conditions. ([58617](https://github.com/WordPress/gutenberg/pull/58617)) +- Refine when Props Bot runs. ([58616](https://github.com/WordPress/gutenberg/pull/58616)) +- Remove noahtallen from .wp-env codeowners. ([58283](https://github.com/WordPress/gutenberg/pull/58283)) +- Scripts: Add viewScriptModule block.json support. ([58203](https://github.com/WordPress/gutenberg/pull/58203)) + +#### Testing + +- "Multiple use" block validation logic improvement [with Playwright]. ([57576](https://github.com/WordPress/gutenberg/pull/57576)) +- Block Bindings: Add block bindings end-to-end tests. ([58550](https://github.com/WordPress/gutenberg/pull/58550)) +- Block Bindings: Add tests for the frontend and polish the existing ones. ([58676](https://github.com/WordPress/gutenberg/pull/58676)) +- Block Bindings: Improve the code of the block bindings tests. ([58785](https://github.com/WordPress/gutenberg/pull/58785)) +- Button: Add focusable disabled variant to vizreg Storybook. ([58634](https://github.com/WordPress/gutenberg/pull/58634)) +- CustomSelect: Add tests for new features. ([58583](https://github.com/WordPress/gutenberg/pull/58583)) +- Fix flaky test of data-wp-on-window directive. ([58642](https://github.com/WordPress/gutenberg/pull/58642)) +- Flaky Test: Fix "directives inside islands should not be hydrated twice". ([58516](https://github.com/WordPress/gutenberg/pull/58516)) +- Interactivity API: Fix flaky test in `data-wp-on-document`. ([58668](https://github.com/WordPress/gutenberg/pull/58668)) +- Migrate remaining 'inserting blocks' end-to-end tests to Playwright. ([58108](https://github.com/WordPress/gutenberg/pull/58108)) +- Migrate remaining 'pattern block' end-to-end tests to Playwright. ([58486](https://github.com/WordPress/gutenberg/pull/58486)) +- SearchControl: Add unit tests. ([58693](https://github.com/WordPress/gutenberg/pull/58693)) +- Try fixing flaky 'inserting blocks' end-to-end tests. ([58848](https://github.com/WordPress/gutenberg/pull/58848)) +- Try fixing flaky Paragraph block end-to-end test. ([58208](https://github.com/WordPress/gutenberg/pull/58208)) +- Use toBeDisabled instead of aria-disabled check. ([58694](https://github.com/WordPress/gutenberg/pull/58694)) +- e2e: Add a test to confirm that the focus moves from the post title to the paragraph using the enter key. ([58872](https://github.com/WordPress/gutenberg/pull/58872)) +- end-to-end Utils: Ensure deleteAllUsers does not delete current user. ([58320](https://github.com/WordPress/gutenberg/pull/58320)) + +#### Build Tooling + +- Add missing Interactivity API label to changelog script. ([58879](https://github.com/WordPress/gutenberg/pull/58879)) +- Enable dynamic import transform for React Native tests. ([58546](https://github.com/WordPress/gutenberg/pull/58546)) +- Fix: Remove mention of weekly meeting from first time contributor PR label. ([58547](https://github.com/WordPress/gutenberg/pull/58547)) +- Interactivity API: Move Core implementation to compat 6.5 folder. ([58829](https://github.com/WordPress/gutenberg/pull/58829)) +- Remove phpunit tests for features backported to Core. ([58776](https://github.com/WordPress/gutenberg/pull/58776)) +- Update Performance tests base branch. ([58890](https://github.com/WordPress/gutenberg/pull/58890)) +- Workflows: Add 'Technical Prototype' to the type-related labels list. ([58163](https://github.com/WordPress/gutenberg/pull/58163)) + + +### Security + +#### Font Library + +- Sanitize font collection data. ([58636](https://github.com/WordPress/gutenberg/pull/58636)) + +#### REST API + +- Font Library REST API: Sanitize font family and font face settings. ([58590](https://github.com/WordPress/gutenberg/pull/58590)) + + +### Various + +- Script loader 6.4 compat: Check for init hook completion. ([58406](https://github.com/WordPress/gutenberg/pull/58406)) + +#### Font Library + +- Code style and code quality feedback from core 6.5 review. ([58736](https://github.com/WordPress/gutenberg/pull/58736)) +- Move getAllowedMimeTypes to FontUtils. ([58667](https://github.com/WordPress/gutenberg/pull/58667)) +- Refactor as a singleton. ([58669](https://github.com/WordPress/gutenberg/pull/58669)) + +#### Components + +- Removing Reakit `Composite` implementation. ([58620](https://github.com/WordPress/gutenberg/pull/58620)) +- Removing Reakit as a dependency. ([58631](https://github.com/WordPress/gutenberg/pull/58631)) +- Update the Snackbar warning message. ([58591](https://github.com/WordPress/gutenberg/pull/58591)) + +#### Global Styles + +- Always output core block global styles after base global styles. ([58761](https://github.com/WordPress/gutenberg/pull/58761)) +- Backport theme.json tests from Core. ([58476](https://github.com/WordPress/gutenberg/pull/58476)) + +#### Block Library + +- Reduce label and fix capitalization for image block upload label. ([58677](https://github.com/WordPress/gutenberg/pull/58677)) +- Separator: Remove border-bottom property. ([55725](https://github.com/WordPress/gutenberg/pull/55725)) + +#### Patterns + +- Update pattern copy to Synced instead of Fully Synced. ([58876](https://github.com/WordPress/gutenberg/pull/58876)) + +#### Block API + +- ViewScriptModule: 6.5 compatibility changes. ([58832](https://github.com/WordPress/gutenberg/pull/58832)) + +#### Custom Fields + +- Block Bindings: Backport block bindings refactor from WordPress core. ([58683](https://github.com/WordPress/gutenberg/pull/58683)) + +#### Inspector Controls + +- Change cover block's "Media settings" label to "Settings". ([58463](https://github.com/WordPress/gutenberg/pull/58463)) + +## First time contributors + +The following PRs were merged by first time contributors: + +- @at-benni: Update versions-in-wordpress.md. ([58545](https://github.com/WordPress/gutenberg/pull/58545)) +- @krupal-panchal: Removed extra parenthesis from document. ([58662](https://github.com/WordPress/gutenberg/pull/58662)) +- @shreyash3087: fix: InnerBlocks schema description in block.json. ([58649](https://github.com/WordPress/gutenberg/pull/58649)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @afercia @ajlende @andrewhayward @andrewserong @annezazu @anton-vlasenko @antonis @aristath @artemiomorales @at-benni @brookewp @c4rl0sbr4v0 @carolinan @chad1008 @ciampo @creativecoder @DAreRodz @dcalhoun @dd32 @derekblank @desrosj @draganescu @ellatrix @fabiankaegy @fai-sal @fluiddot @gaambo @getdave @glendaviesnz @hellofromtonya @ironprogrammer @jameskoster @jasmussen @jeherve @jeryj @jorgefilipecosta @jsnajdr @kevin940726 @krupal-panchal @luisherranz @madhusudhand @MaggieCabrera @Mamaduka @matiasbenedetto @mikachan @mirka @ndiego @noahtallen @noisysocks @ntsekouras @oandregal @ockham @pbking @ramonjd @retrofox @richtabor @SantosGuillamot @scruffian @shreyash3087 @sirreal @t-hamano @talldan @tellthemachines @tjcafferkey @tomjn @tyxla @vcanales @westonruter @WunderBart @youknowriad + + + + = 17.6.6 = ## Changelog diff --git a/gutenberg.php b/gutenberg.php index b86c9381c1a323..c9edbb32024c8c 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.3 * Requires PHP: 7.0 - * Version: 17.7.0-rc.1 + * Version: 17.7.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/lib/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php b/lib/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php index e7b2ac85f6e525..74fa31d53199e0 100644 --- a/lib/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php +++ b/lib/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php @@ -69,6 +69,15 @@ public function get_item( $request ) { return $revision; } + if ( (int) $parent->ID !== (int) $revision->post_parent ) { + return new WP_Error( + 'rest_revision_parent_id_mismatch', + /* translators: %d: A post id. */ + sprintf( __( 'The revision does not belong to the specified parent with id of "%d"' ), $parent->ID ), + array( 'status' => 404 ) + ); + } + $response = $this->prepare_item_for_response( $revision, $request ); return rest_ensure_response( $response ); } diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php index 4a01f748d16e42..cd402a8e545003 100644 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php +++ b/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php @@ -221,8 +221,10 @@ private static function get_sanitization_schema() { array( 'font_family_settings' => array( 'name' => 'sanitize_text_field', - 'slug' => 'sanitize_title', - 'fontFamily' => 'sanitize_text_field', + 'slug' => static function ( $value ) { + return _wp_to_kebab_case( sanitize_title( $value ) ); + }, + 'fontFamily' => 'WP_Font_Utils::sanitize_font_family', 'preview' => 'sanitize_url', 'fontFace' => array( array( diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php index 23c95d633fb47b..7af1b0af002f55 100644 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php +++ b/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php @@ -20,11 +20,41 @@ * @access private */ class WP_Font_Utils { + + /** + * Adds surrounding quotes to font family names that contain special characters. + * + * It follows the recommendations from the CSS Fonts Module Level 4. + * @link https://www.w3.org/TR/css-fonts-4/#font-family-prop + * + * @since 6.5.0 + * @access private + * + * @see sanitize_font_family() + * + * @param string $item A font family name. + * @return string The font family name with surrounding quotes if necessary. + */ + private static function maybe_add_quotes( $item ) { + // Match any non alphabetic characters (a-zA-Z), dashes -, or parenthesis (). + $regex = '/[^a-zA-Z\-()]+/'; + $item = trim( $item ); + if ( preg_match( $regex, $item ) ) { + // Removes leading and trailing quotes. + $item = preg_replace( '/^["\']|["\']$/', '', $item ); + return "\"$item\""; + } + return $item; + } + /** * Sanitizes and formats font family names. * * - Applies `sanitize_text_field` - * - Adds surrounding quotes to names that contain spaces and are not already quoted + * - Adds surrounding quotes to names that special + * + * It follows the recommendations from the CSS Fonts Module Level 4. + * @link https://www.w3.org/TR/css-fonts-4/#font-family-prop * * @since 6.5.0 * @access private @@ -39,26 +69,19 @@ public static function sanitize_font_family( $font_family ) { return ''; } - $font_family = sanitize_text_field( $font_family ); - $font_families = explode( ',', $font_family ); - $wrapped_font_families = array_map( - function ( $family ) { - $trimmed = trim( $family ); - if ( ! empty( $trimmed ) && str_contains( $trimmed, ' ' ) && ! str_contains( $trimmed, "'" ) && ! str_contains( $trimmed, '"' ) ) { - return '"' . $trimmed . '"'; + $output = trim( sanitize_text_field( $font_family ) ); + $formatted_items = array(); + if ( str_contains( $output, ',' ) ) { + $items = explode( ',', $output ); + foreach ( $items as $item ) { + $formatted_item = self::maybe_add_quotes( $item ); + if ( ! empty( $formatted_item ) ) { + $formatted_items[] = $formatted_item; } - return $trimmed; - }, - $font_families - ); - - if ( count( $wrapped_font_families ) === 1 ) { - $font_family = $wrapped_font_families[0]; - } else { - $font_family = implode( ', ', $wrapped_font_families ); + } + return implode( ', ', $formatted_items ); } - - return $font_family; + return self::maybe_add_quotes( $output ); } /** @@ -233,8 +256,8 @@ public static function get_allowed_font_mime_types() { return array( 'otf' => 'application/vnd.ms-opentype', 'ttf' => PHP_VERSION_ID >= 70400 ? 'font/sfnt' : $php_7_ttf_mime_type, - 'woff' => PHP_VERSION_ID >= 80100 ? 'font/woff' : 'application/font-woff', - 'woff2' => PHP_VERSION_ID >= 80100 ? 'font/woff2' : 'application/font-woff2', + 'woff' => PHP_VERSION_ID >= 80112 ? 'font/woff' : 'application/font-woff', + 'woff2' => PHP_VERSION_ID >= 80112 ? 'font/woff2' : 'application/font-woff2', ); } } diff --git a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php index 3bfade3aa4aa75..1fc757accf6f6b 100644 --- a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php +++ b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php @@ -800,14 +800,14 @@ public function print_router_loading_and_screen_reader_markup() { echo <<
HTML; diff --git a/package-lock.json b/package-lock.json index 15002da92150ff..d2f56e9fc60c72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "17.7.0-rc.1", + "version": "17.7.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "17.7.0-rc.1", + "version": "17.7.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 190173d15ccadb..d662caeb1f2bb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "17.7.0-rc.1", + "version": "17.7.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 0fb7f55b9955d2..245d0ee4348b2e 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -54,7 +54,11 @@ export function BlockPreview( { [] ); const settings = useMemo( - () => ( { ...originalSettings, __unstableIsPreviewMode: true } ), + () => ( { + ...originalSettings, + focusMode: false, // Disable "Spotlight mode". + __unstableIsPreviewMode: true, + } ), [ originalSettings ] ); const renderedBlocks = useMemo( @@ -117,6 +121,7 @@ export function useBlockPreview( { blocks, props = {}, layout } ) { () => ( { ...originalSettings, styles: undefined, // Clear styles included by the parent settings, as they are already output by the parent's EditorStyles. + focusMode: false, // Disable "Spotlight mode". __unstableIsPreviewMode: true, } ), [ originalSettings ] diff --git a/packages/block-editor/src/components/date-format-picker/index.js b/packages/block-editor/src/components/date-format-picker/index.js index 7a2ed46b4a9b04..8c35b025bfccf6 100644 --- a/packages/block-editor/src/components/date-format-picker/index.js +++ b/packages/block-editor/src/components/date-format-picker/index.js @@ -117,7 +117,6 @@ function NonDefaultControls( { format, onChange } ) { return ( onChange( selectedItem.style ) } - __nextUnconstrainedWidth /> ) ); diff --git a/packages/block-editor/src/components/global-styles/border-panel.js b/packages/block-editor/src/components/global-styles/border-panel.js index 0dee6040c87052..960c19289157a3 100644 --- a/packages/block-editor/src/components/global-styles/border-panel.js +++ b/packages/block-editor/src/components/global-styles/border-panel.js @@ -19,7 +19,7 @@ import { __ } from '@wordpress/i18n'; import BorderRadiusControl from '../border-radius-control'; import { useColorsPerOrigin } from './hooks'; import { getValueFromVariable, TOOLSPANEL_DROPDOWNMENU_PROPS } from './utils'; -import { mergeOrigins } from '../../store/get-block-settings'; +import { overrideOrigins } from '../../store/get-block-settings'; import { setImmutably } from '../../utils/object'; import { getBorderPanelLabel } from '../../hooks/border'; import { ShadowPopover } from './shadow-panel-components'; @@ -154,12 +154,12 @@ export default function BorderPanel( { // Shadow const shadow = decodeValue( inheritedValue?.shadow ); - const shadowPresets = settings?.shadow?.presets; - const mergedShadowPresets = shadowPresets - ? mergeOrigins( shadowPresets ) + const shadowPresets = settings?.shadow?.presets ?? {}; + const overriddenShadowPresets = shadowPresets + ? overrideOrigins( shadowPresets ) : []; const setShadow = ( newValue ) => { - const slug = mergedShadowPresets?.find( + const slug = overriddenShadowPresets?.find( ( { shadow: shadowName } ) => shadowName === newValue )?.slug; diff --git a/packages/block-editor/src/components/global-styles/typography-panel.js b/packages/block-editor/src/components/global-styles/typography-panel.js index e689d84c83c981..6b09b146f9ea17 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -13,7 +13,11 @@ import { useCallback } from '@wordpress/element'; /** * Internal dependencies */ -import { mergeOrigins, hasMergedOrigins } from '../../store/get-block-settings'; +import { + mergeOrigins, + overrideOrigins, + hasOriginValue, +} from '../../store/get-block-settings'; import FontFamilyControl from '../font-family'; import FontAppearanceControl from '../font-appearance-control'; import LineHeightControl from '../line-height-control'; @@ -53,13 +57,13 @@ export function useHasTypographyPanel( settings ) { function useHasFontSizeControl( settings ) { return ( - hasMergedOrigins( settings?.typography?.fontSizes ) || + hasOriginValue( settings?.typography?.fontSizes ) || settings?.typography?.customFontSize ); } function useHasFontFamilyControl( settings ) { - return hasMergedOrigins( settings?.typography?.fontFamilies ); + return hasOriginValue( settings?.typography?.fontFamilies ); } function useHasLineHeightControl( settings ) { @@ -101,10 +105,10 @@ function useHasTextColumnsControl( settings ) { } function getUniqueFontSizesBySlug( settings ) { - const fontSizes = settings?.typography?.fontSizes; - const mergedFontSizes = fontSizes ? mergeOrigins( fontSizes ) : []; + const fontSizes = settings?.typography?.fontSizes ?? {}; + const overriddenFontSizes = fontSizes ? overrideOrigins( fontSizes ) : []; const uniqueSizes = []; - for ( const currentSize of mergedFontSizes ) { + for ( const currentSize of overriddenFontSizes ) { if ( ! uniqueSizes.some( ( { slug } ) => slug === currentSize.slug ) ) { uniqueSizes.push( currentSize ); } @@ -162,7 +166,7 @@ export default function TypographyPanel( { // Font Family const hasFontFamilyEnabled = useHasFontFamilyControl( settings ); - const fontFamilies = settings?.typography?.fontFamilies; + const fontFamilies = settings?.typography?.fontFamilies ?? {}; const mergedFontFamilies = fontFamilies ? mergeOrigins( fontFamilies ) : []; const fontFamily = decodeValue( inheritedValue?.typography?.fontFamily ); const setFontFamily = ( newValue ) => { diff --git a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js index c2b6ae30de7ac9..f0b0d28e70c0fd 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js @@ -297,7 +297,6 @@ export default function SpacingInputControl( { options={ options } label={ ariaLabel } hideLabelFromVision={ true } - __nextUnconstrainedWidth={ true } size={ '__unstable-large' } onMouseOver={ onMouseOver } onMouseOut={ onMouseOut } diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index 80b6090eca2190..1564d9ea9a81ca 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -374,11 +374,14 @@ function backgroundSizeHelpText( value ) { } export const coordsToBackgroundPosition = ( value ) => { - if ( ! value || isNaN( value.x ) || isNaN( value.y ) ) { + if ( ! value || ( isNaN( value.x ) && isNaN( value.y ) ) ) { return undefined; } - return `${ value.x * 100 }% ${ value.y * 100 }%`; + const x = isNaN( value.x ) ? 0.5 : value.x; + const y = isNaN( value.y ) ? 0.5 : value.y; + + return `${ x * 100 }% ${ y * 100 }%`; }; export const backgroundPositionToCoords = ( value ) => { diff --git a/packages/block-editor/src/hooks/position.js b/packages/block-editor/src/hooks/position.js index 5017cb34fc18bd..e1e26d54aa2420 100644 --- a/packages/block-editor/src/hooks/position.js +++ b/packages/block-editor/src/hooks/position.js @@ -288,7 +288,6 @@ export function PositionPanelPure( { help={ stickyHelpText } > value?.[ key ]?.length ); @@ -203,8 +214,8 @@ export function getBlockSettings( state, clientId, ...paths ) { // Return if the setting was found in either the block instance or the store. if ( result !== undefined ) { - if ( PATHS_WITH_MERGE[ normalizedPath ] ) { - return mergeOrigins( result ); + if ( PATHS_WITH_OVERRIDE[ normalizedPath ] ) { + return overrideOrigins( result ); } return result; } diff --git a/packages/block-editor/src/store/index.js b/packages/block-editor/src/store/index.js index 10e16a0779cd63..0bcc00cb5f6ae8 100644 --- a/packages/block-editor/src/store/index.js +++ b/packages/block-editor/src/store/index.js @@ -10,7 +10,6 @@ import reducer from './reducer'; import * as selectors from './selectors'; import * as privateActions from './private-actions'; import * as privateSelectors from './private-selectors'; -import * as resolvers from './resolvers'; import * as actions from './actions'; import { STORE_NAME } from './constants'; import { unlock } from '../lock-unlock'; @@ -23,7 +22,6 @@ import { unlock } from '../lock-unlock'; export const storeConfig = { reducer, selectors, - resolvers, actions, }; diff --git a/packages/block-editor/src/store/private-actions.js b/packages/block-editor/src/store/private-actions.js index d1db598c8c8e65..ae0a06152fb933 100644 --- a/packages/block-editor/src/store/private-actions.js +++ b/packages/block-editor/src/store/private-actions.js @@ -140,6 +140,15 @@ export const privateRemoveBlocks = } if ( rules[ 'bindings/core/pattern-overrides' ] ) { + const parentPatternBlocks = + select.getBlockParentsByBlockName( + clientId, + 'core/block' + ); + // We only need to run this check when editing the original pattern, not pattern instances. + if ( parentPatternBlocks?.length > 0 ) { + continue; + } const blockAttributes = select.getBlockAttributes( clientId ); if ( diff --git a/packages/block-editor/src/store/private-keys.js b/packages/block-editor/src/store/private-keys.js new file mode 100644 index 00000000000000..8bfa4bb68297f8 --- /dev/null +++ b/packages/block-editor/src/store/private-keys.js @@ -0,0 +1 @@ +export const selectBlockPatternsKey = Symbol( 'selectBlockPatternsKey' ); diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 4700e50f739f45..c885e43ba75208 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -22,6 +22,7 @@ import { checkAllowListRecursive, getAllPatternsDependants } from './utils'; import { INSERTER_PATTERN_TYPES } from '../components/inserter/block-patterns-tab/utils'; import { STORE_NAME } from './constants'; import { unlock } from '../lock-unlock'; +import { selectBlockPatternsKey } from './private-keys'; export { getBlockSettings } from './get-block-settings'; @@ -250,10 +251,6 @@ export const getInserterMediaCategories = createSelector( ] ); -export function getFetchedPatterns( state ) { - return state.blockPatterns; -} - /** * Returns whether there is at least one allowed pattern for inner blocks children. * This is useful for deferring the parsing of all patterns until needed. @@ -285,7 +282,7 @@ export const hasAllowedPatterns = createRegistrySelector( ( select ) => } ); }, ( state, rootClientId ) => [ - getAllPatternsDependants( state ), + getAllPatternsDependants( select )( state ), state.settings.allowedBlockTypes, state.settings.templateLock, state.blockListSettings[ rootClientId ], @@ -325,12 +322,12 @@ export const getAllPatterns = createRegistrySelector( ( select ) => return [ ...userPatterns, ...__experimentalBlockPatterns, - ...unlock( select( STORE_NAME ) ).getFetchedPatterns(), + ...( state.settings[ selectBlockPatternsKey ]?.( select ) ?? [] ), ].filter( ( x, index, arr ) => index === arr.findIndex( ( y ) => x.name === y.name ) ); - }, getAllPatternsDependants ) + }, getAllPatternsDependants( select ) ) ); /** diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 0be421b757bce1..1b535e51950164 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -2064,15 +2064,6 @@ function blockBindingsSources( state = {}, action ) { return state; } -function blockPatterns( state = [], action ) { - switch ( action.type ) { - case 'RECEIVE_BLOCK_PATTERNS': - return action.patterns; - } - - return state; -} - const combinedReducers = combineReducers( { blocks, isDragging, @@ -2105,7 +2096,6 @@ const combinedReducers = combineReducers( { openedBlockSettingsMenu, registeredInserterMediaCategories, blockBindingsSources, - blockPatterns, } ); function withAutomaticChangeReset( reducer ) { diff --git a/packages/block-editor/src/store/resolvers.js b/packages/block-editor/src/store/resolvers.js deleted file mode 100644 index 40c51d241ac676..00000000000000 --- a/packages/block-editor/src/store/resolvers.js +++ /dev/null @@ -1,17 +0,0 @@ -export const getFetchedPatterns = - () => - async ( { dispatch, select } ) => { - const { __experimentalFetchBlockPatterns } = select.getSettings(); - if ( ! __experimentalFetchBlockPatterns ) { - return []; - } - const patterns = await __experimentalFetchBlockPatterns(); - dispatch( { type: 'RECEIVE_BLOCK_PATTERNS', patterns } ); - }; - -getFetchedPatterns.shouldInvalidate = ( action ) => { - return ( - action.type === 'UPDATE_SETTINGS' && - !! action.settings.__experimentalFetchBlockPatterns - ); -}; diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 3475e2b5351c80..87d22e3e4727d7 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2299,12 +2299,12 @@ export const __experimentalGetParsedPattern = createRegistrySelector( __unstableSkipMigrationLogs: true, } ), }; - }, getAllPatternsDependants ) + }, getAllPatternsDependants( select ) ) ); -const getAllowedPatternsDependants = ( state, rootClientId ) => { +const getAllowedPatternsDependants = ( select ) => ( state, rootClientId ) => { return [ - ...getAllPatternsDependants( state ), + ...getAllPatternsDependants( select )( state ), state.settings.allowedBlockTypes, state.settings.templateLock, state.blockListSettings[ rootClientId ], @@ -2345,7 +2345,7 @@ export const __experimentalGetAllowedPatterns = createRegistrySelector( ); return patternsAllowed; - }, getAllowedPatternsDependants ); + }, getAllowedPatternsDependants( select ) ); } ); @@ -2384,7 +2384,7 @@ export const getPatternsByBlockTypes = createRegistrySelector( ( select ) => return filteredPatterns; }, ( state, blockNames, rootClientId ) => - getAllowedPatternsDependants( state, rootClientId ) + getAllowedPatternsDependants( select )( state, rootClientId ) ) ); @@ -2458,7 +2458,7 @@ export const __experimentalGetPatternTransformItems = createRegistrySelector( ); }, ( state, blocks, rootClientId ) => - getAllowedPatternsDependants( state, rootClientId ) + getAllowedPatternsDependants( select )( state, rootClientId ) ) ); diff --git a/packages/block-editor/src/store/utils.js b/packages/block-editor/src/store/utils.js index 6cde56da1b55a7..4d9d114946c1fd 100644 --- a/packages/block-editor/src/store/utils.js +++ b/packages/block-editor/src/store/utils.js @@ -1,3 +1,8 @@ +/** + * Internal dependencies + */ +import { selectBlockPatternsKey } from './private-keys'; + export const checkAllowList = ( list, item, defaultResult = null ) => { if ( typeof list === 'boolean' ) { return list; @@ -40,12 +45,12 @@ export const checkAllowListRecursive = ( blocks, allowedBlockTypes ) => { return true; }; -export const getAllPatternsDependants = ( state ) => { +export const getAllPatternsDependants = ( select ) => ( state ) => { return [ state.settings.__experimentalBlockPatterns, state.settings.__experimentalUserPatternCategories, state.settings.__experimentalReusableBlocks, - state.settings.__experimentalFetchBlockPatterns, + state.settings[ selectBlockPatternsKey ]?.( select ), state.blockPatterns, ]; }; diff --git a/packages/block-library/src/search/index.php b/packages/block-library/src/search/index.php index 5688e2871a2463..c368c2ab03dbf8 100644 --- a/packages/block-library/src/search/index.php +++ b/packages/block-library/src/search/index.php @@ -188,7 +188,7 @@ function render_block_core_search( $attributes ) { ) ); $form_directives = ' - data-wp-interactive=\'"core/search"\'' + data-wp-interactive="core/search"' . $form_context . 'data-wp-class--wp-block-search__searchfield-hidden="!context.isSearchInputVisible" data-wp-on--keydown="actions.handleSearchKeydown" diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js index 8af2d0940c8fcc..99de83353166c7 100644 --- a/packages/blocks/src/api/constants.js +++ b/packages/blocks/src/api/constants.js @@ -271,11 +271,13 @@ export const __EXPERIMENTAL_ELEMENTS = { cite: 'cite', }; -export const __EXPERIMENTAL_PATHS_WITH_MERGE = { +// These paths may have three origins, custom, theme, and default, +// and are expected to override other origins with custom, theme, +// and default priority. +export const __EXPERIMENTAL_PATHS_WITH_OVERRIDE = { 'color.duotone': true, 'color.gradients': true, 'color.palette': true, - 'typography.fontFamilies': true, 'typography.fontSizes': true, 'spacing.spacingSizes': true, }; diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js index 2ddeb3a60f0abb..aa72979818c9c7 100644 --- a/packages/blocks/src/api/index.js +++ b/packages/blocks/src/api/index.js @@ -162,5 +162,5 @@ export { default as node } from './node'; export { __EXPERIMENTAL_STYLE_PROPERTY, __EXPERIMENTAL_ELEMENTS, - __EXPERIMENTAL_PATHS_WITH_MERGE, + __EXPERIMENTAL_PATHS_WITH_OVERRIDE, } from './constants'; diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index b6d1af65f61f72..9edf124bbdf73c 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- `CustomSelectControl`: Remove deprecated `__nextUnconstrainedWidth` prop and promote to default behavior ([#58974](https://github.com/WordPress/gutenberg/pull/58974)). + ## 26.0.1 (2024-02-13) ### Bug Fix diff --git a/packages/components/src/alignment-matrix-control/test/index.tsx b/packages/components/src/alignment-matrix-control/test/index.tsx index a820b69b26c8ff..57c13f8c92eee0 100644 --- a/packages/components/src/alignment-matrix-control/test/index.tsx +++ b/packages/components/src/alignment-matrix-control/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen, waitFor, within } from '@testing-library/react'; -import { press, click } from '@ariakit/test'; +import { press, click, sleep } from '@ariakit/test'; /** * Internal dependencies @@ -39,6 +39,7 @@ describe( 'AlignmentMatrixControl', () => { it( 'should be centered by default', async () => { await renderAndInitCompositeStore( ); + await sleep(); await press.Tab(); expect( getCell( 'center center' ) ).toHaveFocus(); @@ -109,6 +110,7 @@ describe( 'AlignmentMatrixControl', () => { ); + await sleep(); await press.Tab(); await press[ keyRef ](); diff --git a/packages/components/src/circular-option-picker/test/index.tsx b/packages/components/src/circular-option-picker/test/index.tsx index 0a168432629f8f..ab3042784eab62 100644 --- a/packages/components/src/circular-option-picker/test/index.tsx +++ b/packages/components/src/circular-option-picker/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen } from '@testing-library/react'; -import { press } from '@ariakit/test'; +import { press, sleep } from '@ariakit/test'; /** * Internal dependencies @@ -78,6 +78,7 @@ describe( 'CircularOptionPicker', () => { /> ); + await sleep(); await press.Tab(); expect( getOption( 'Option One' ) ).toHaveFocus(); await press.ArrowRight(); @@ -97,6 +98,7 @@ describe( 'CircularOptionPicker', () => { /> ); + await sleep(); await press.Tab(); expect( getOption( 'Option One' ) ).toHaveFocus(); await press.ArrowRight(); @@ -116,6 +118,7 @@ describe( 'CircularOptionPicker', () => { /> ); + await sleep(); await press.Tab(); expect( getOption( 'Option One' ) ).toHaveFocus(); await press.ArrowRight(); diff --git a/packages/components/src/composite/legacy/test/index.tsx b/packages/components/src/composite/legacy/test/index.tsx index ee6654f9fd3698..315532a8b50869 100644 --- a/packages/components/src/composite/legacy/test/index.tsx +++ b/packages/components/src/composite/legacy/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { queryByAttribute, render, screen } from '@testing-library/react'; -import { press, waitFor } from '@ariakit/test'; +import { press, sleep, waitFor } from '@ariakit/test'; /** * Internal dependencies @@ -178,10 +178,13 @@ describe.each( [ ); renderAndValidate( ); + await sleep(); await press.Tab(); expect( screen.getByText( 'Before' ) ).toHaveFocus(); + await sleep(); await press.Tab(); expect( screen.getByText( 'Item 1' ) ).toHaveFocus(); + await sleep(); await press.Tab(); expect( screen.getByText( 'After' ) ).toHaveFocus(); await press.ShiftTab(); @@ -210,6 +213,7 @@ describe.each( [ expect( item2 ).toBeDisabled(); + await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -239,6 +243,7 @@ describe.each( [ expect( item2 ).toBeEnabled(); expect( item2 ).toHaveAttribute( 'aria-disabled', 'true' ); + await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -274,8 +279,9 @@ describe.each( [ renderAndValidate( ); const { item2 } = getOneDimensionalItems(); + await sleep(); await press.Tab(); - expect( item2 ).toHaveFocus(); + await waitFor( () => expect( item2 ).toHaveFocus() ); } ); } ); @@ -317,6 +323,7 @@ describe.each( [ test( 'All directions work with no orientation', async () => { const { item1, item2, item3 } = useOneDimensionalTest(); + await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -354,6 +361,7 @@ describe.each( [ orientation: 'horizontal', } ); + await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -383,6 +391,7 @@ describe.each( [ orientation: 'vertical', } ); + await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press( next ); @@ -412,6 +421,7 @@ describe.each( [ loop: true, } ); + await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -434,6 +444,7 @@ describe.each( [ const { itemA1, itemA2, itemA3, itemB1, itemB2, itemC1, itemC3 } = useTwoDimensionalTest(); + await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press.ArrowUp(); @@ -470,6 +481,7 @@ describe.each( [ const { itemA1, itemA2, itemA3, itemB1, itemC1, itemC3 } = useTwoDimensionalTest( { loop: true } ); + await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press( next ); @@ -494,6 +506,7 @@ describe.each( [ const { itemA1, itemA2, itemA3, itemB1, itemC1, itemC3 } = useTwoDimensionalTest( { wrap: true } ); + await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press( next ); @@ -526,6 +539,7 @@ describe.each( [ wrap: true, } ); + await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press( previous ); @@ -541,6 +555,7 @@ describe.each( [ test( 'Focus shifts if vertical neighbour unavailable when shift enabled', async () => { const { itemA1, itemB1, itemB2, itemC1 } = useShiftTest( true ); + await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press.ArrowDown(); @@ -562,6 +577,7 @@ describe.each( [ test( 'Focus does not shift if vertical neighbour unavailable when shift not enabled', async () => { const { itemA1, itemB1, itemB2 } = useShiftTest( false ); + await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press.ArrowDown(); diff --git a/packages/components/src/custom-select-control-v2/test/index.tsx b/packages/components/src/custom-select-control-v2/test/index.tsx index cdc93205fba98e..f8d9a4ebd61959 100644 --- a/packages/components/src/custom-select-control-v2/test/index.tsx +++ b/packages/components/src/custom-select-control-v2/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen } from '@testing-library/react'; -import { click, press, type } from '@ariakit/test'; +import { click, press, sleep, type } from '@ariakit/test'; /** * WordPress dependencies @@ -106,6 +106,7 @@ describe( 'With Legacy Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); await press.Enter(); expect( @@ -315,6 +316,7 @@ describe( 'With Legacy Props', () => { ); + await sleep(); await press.Tab(); expect( screen.getByRole( 'combobox', { @@ -336,6 +338,7 @@ describe( 'With Legacy Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); @@ -361,6 +364,7 @@ describe( 'With Legacy Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); await press.Enter(); expect( @@ -381,6 +385,7 @@ describe( 'With Legacy Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); @@ -544,6 +549,7 @@ describe( 'With Default Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); await press.Enter(); expect( @@ -572,6 +578,7 @@ describe( 'With Default Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); @@ -597,6 +604,7 @@ describe( 'With Default Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); await press.Enter(); expect( @@ -617,6 +625,7 @@ describe( 'With Default Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); diff --git a/packages/components/src/custom-select-control/README.md b/packages/components/src/custom-select-control/README.md index 56f82f6ead84b6..ff890c606af467 100644 --- a/packages/components/src/custom-select-control/README.md +++ b/packages/components/src/custom-select-control/README.md @@ -41,7 +41,6 @@ function MyCustomSelectControl() { const [ , setFontSize ] = useState(); return ( setFontSize( selectedItem ) } @@ -53,7 +52,6 @@ function MyControlledCustomSelectControl() { const [ fontSize, setFontSize ] = useState( options[ 0 ] ); return ( setFontSize( selectedItem ) } @@ -114,14 +112,6 @@ Can be used to externally control the value of the control, like in the `MyContr - Type: `Object` - Required: No -#### __nextUnconstrainedWidth - -Start opting into the unconstrained width style that will become the default in a future version, currently scheduled to be WordPress 6.4. (The prop can be safely removed once this happens.) - -- Type: `Boolean` -- Required: No -- Default: `false` - #### onMouseOver A handler for onMouseOver events. diff --git a/packages/components/src/custom-select-control/index.js b/packages/components/src/custom-select-control/index.js index eb3cf5ba0676e0..5805e18b98dd41 100644 --- a/packages/components/src/custom-select-control/index.js +++ b/packages/components/src/custom-select-control/index.js @@ -11,7 +11,6 @@ import classnames from 'classnames'; import { Icon, check } from '@wordpress/icons'; import { __, sprintf } from '@wordpress/i18n'; import { useCallback, useState } from '@wordpress/element'; -import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -19,9 +18,9 @@ import deprecated from '@wordpress/deprecated'; import { VisuallyHidden } from '../visually-hidden'; import { Select as SelectControlSelect } from '../select-control/styles/select-control-styles'; import SelectControlChevronDown from '../select-control/chevron-down'; -import { InputBaseWithBackCompatMinWidth } from './styles'; import { StyledLabel } from '../base-control/styles/base-control-styles'; import { useDeprecated36pxDefaultSizeProp } from '../utils/use-deprecated-props'; +import InputBase from '../input-control/input-base'; const itemToString = ( item ) => item?.name; // This is needed so that in Windows, where @@ -67,8 +66,6 @@ export default function CustomSelectControl( props ) { const { /** Start opting into the larger default height that will become the default size in a future version. */ __next40pxDefaultSize = false, - /** Start opting into the unconstrained width that will become the default in a future version. */ - __nextUnconstrainedWidth = false, className, hideLabelFromVision, label, @@ -116,17 +113,6 @@ export default function CustomSelectControl( props ) { onBlur?.( e ); } - if ( ! __nextUnconstrainedWidth ) { - deprecated( - 'Constrained width styles for wp.components.CustomSelectControl', - { - since: '6.1', - version: '6.4', - hint: 'Set the `__nextUnconstrainedWidth` prop to true to start opting into the new styles, which will become the default in a future version', - } - ); - } - function getDescribedBy() { if ( describedBy ) { return describedBy; @@ -180,14 +166,9 @@ export default function CustomSelectControl( props ) { { label } ) } - } > @@ -215,7 +196,7 @@ export default function CustomSelectControl( props ) { ) } - + { /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */ }
    { isOpen && diff --git a/packages/components/src/custom-select-control/stories/index.story.js b/packages/components/src/custom-select-control/stories/index.story.js index d8fea5c7baa003..ecfa3b06392ae9 100644 --- a/packages/components/src/custom-select-control/stories/index.story.js +++ b/packages/components/src/custom-select-control/stories/index.story.js @@ -20,7 +20,6 @@ export default { export const Default = CustomSelectControl.bind( {} ); Default.args = { - __nextUnconstrainedWidth: true, label: 'Label', options: [ { diff --git a/packages/components/src/custom-select-control/styles.ts b/packages/components/src/custom-select-control/styles.ts deleted file mode 100644 index e16b5d0b7bdd7a..00000000000000 --- a/packages/components/src/custom-select-control/styles.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * External dependencies - */ -import { css } from '@emotion/react'; -import styled from '@emotion/styled'; - -/** - * Internal dependencies - */ -import InputBase from '../input-control/input-base'; -import { Container as InputControlContainer } from '../input-control/styles/input-control-styles'; - -type BackCompatMinWidthProps = { - __nextUnconstrainedWidth: boolean; -}; - -const backCompatMinWidth = ( props: BackCompatMinWidthProps ) => - ! props.__nextUnconstrainedWidth - ? css` - ${ InputControlContainer } { - min-width: 130px; - } - ` - : ''; - -export const InputBaseWithBackCompatMinWidth = styled( InputBase )` - ${ backCompatMinWidth } -`; diff --git a/packages/components/src/custom-select-control/test/index.js b/packages/components/src/custom-select-control/test/index.js index 52bb841a4f953e..a4c61d0cdcecd9 100644 --- a/packages/components/src/custom-select-control/test/index.js +++ b/packages/components/src/custom-select-control/test/index.js @@ -46,7 +46,6 @@ const props = { }, }, ], - __nextUnconstrainedWidth: true, }; const ControlledCustomSelectControl = ( { options } ) => { diff --git a/packages/components/src/dropdown-menu-v2/test/index.tsx b/packages/components/src/dropdown-menu-v2/test/index.tsx index f58639a545a056..10351d6cb588aa 100644 --- a/packages/components/src/dropdown-menu-v2/test/index.tsx +++ b/packages/components/src/dropdown-menu-v2/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen, waitFor } from '@testing-library/react'; -import { press, click, hover, type } from '@ariakit/test'; +import { press, click, hover, sleep, type } from '@ariakit/test'; /** * WordPress dependencies @@ -123,6 +123,7 @@ describe( 'DropdownMenu', () => { } ); // Move focus on the toggle + await sleep(); await press.Tab(); expect( toggleButton ).toHaveFocus(); @@ -153,6 +154,7 @@ describe( 'DropdownMenu', () => { } ); // Move focus on the toggle + await sleep(); await press.Tab(); expect( toggleButton ).toHaveFocus(); @@ -908,6 +910,7 @@ describe( 'DropdownMenu', () => { // The outer button can be focused by pressing tab. Doing so will cause // the DropdownMenu to close. + await sleep(); await press.Tab(); expect( outerButton ).toBeInTheDocument(); expect( screen.queryByRole( 'menu' ) ).not.toBeInTheDocument(); diff --git a/packages/components/src/font-size-picker/font-size-picker-select.tsx b/packages/components/src/font-size-picker/font-size-picker-select.tsx index 32438cfab81153..c5dca6bdb37a04 100644 --- a/packages/components/src/font-size-picker/font-size-picker-select.tsx +++ b/packages/components/src/font-size-picker/font-size-picker-select.tsx @@ -69,7 +69,6 @@ const FontSizePickerSelect = ( props: FontSizePickerSelectProps ) => { return ( { // Tab should initially focus the first tab in the tablist, which // is Alpha. + await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) ).toHaveFocus(); // By default the tabpanel should receive focus + await sleep(); await press.Tab(); expect( selectedTabPanel ).toHaveFocus(); } ); @@ -229,12 +231,14 @@ describe( 'Tabs', () => { // Tab should initially focus the first tab in the tablist, which // is Alpha. + await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) ).toHaveFocus(); // Because the alpha tabpanel is set to `focusable: false`, pressing // the Tab key should focus the button, not the tabpanel + await sleep(); await press.Tab(); expect( alphaButton ).toHaveFocus(); } ); @@ -305,6 +309,7 @@ describe( 'Tabs', () => { // Tab to focus the tablist. Make sure alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -338,6 +343,7 @@ describe( 'Tabs', () => { // Tab to focus the tablist. Make sure Alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -373,6 +379,7 @@ describe( 'Tabs', () => { // Tab to focus the tablist. Make sure alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -472,6 +479,7 @@ describe( 'Tabs', () => { // Tab to focus the tablist. Make sure Alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); // Confirm onSelect has not been re-called @@ -514,6 +522,7 @@ describe( 'Tabs', () => { // Tab should initially focus the first tab in the tablist, which // is Alpha. + await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) @@ -522,6 +531,7 @@ describe( 'Tabs', () => { // Because all other tabs should have `tabindex=-1`, pressing Tab // should NOT move the focus to the next tab, which is Beta. // Instead, focus should go to the currently selected tabpanel (alpha). + await sleep(); await press.Tab(); expect( await screen.findByRole( 'tabpanel', { @@ -832,6 +842,7 @@ describe( 'Tabs', () => { expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); // Move focus to the tablist, make sure alpha is focused. + await sleep(); await press.Tab(); expect( screen.getByRole( 'tab', { name: 'Alpha' } ) @@ -1185,10 +1196,18 @@ describe( 'Tabs', () => { /> ); + // Due to the timing of the component re-rendering, we + // need to force a delay to ensure the test doesn't run + // the upcoming assertions too early. + // see https://github.com/WordPress/gutenberg/pull/58629#issuecomment-1924875249 + await sleep(); + // Tab key should focus the currently selected tab, which is Beta. await press.Tab(); - expect( await getSelectedTab() ).toHaveTextContent( - 'Beta' + await waitFor( async () => + expect( await getSelectedTab() ).toHaveTextContent( + 'Beta' + ) ); expect( await getSelectedTab() ).toHaveFocus(); @@ -1201,9 +1220,11 @@ describe( 'Tabs', () => { ); // When the selected tab is changed, it should not automatically receive focus. + expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( screen.getByRole( 'tab', { name: 'Beta' } ) ).toHaveFocus(); @@ -1228,7 +1249,9 @@ describe( 'Tabs', () => { ); // Tab key should focus the currently selected tab, which is Beta. + await sleep(); await press.Tab(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveTextContent( 'Beta' @@ -1247,9 +1270,11 @@ describe( 'Tabs', () => { ); // When the selected tab is changed, it should not automatically receive focus. + expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( screen.getByRole( 'tab', { name: 'Beta' } ) ).toHaveFocus(); @@ -1261,6 +1286,7 @@ describe( 'Tabs', () => { ).toHaveFocus(); // Press tab, move focus back to the tablist + await sleep(); await press.Tab(); const betaTab = screen.getByRole( 'tab', { @@ -1282,6 +1308,7 @@ describe( 'Tabs', () => { it( 'should automatically select a newly focused tab', async () => { render( ); + await sleep(); await press.Tab(); // Tab key should focus the currently selected tab, which is Beta. @@ -1307,10 +1334,13 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); // Tab key should focus the currently selected tab, which is Beta. + await sleep(); await press.Tab(); - expect( - await screen.findByRole( 'tab', { name: 'Beta' } ) - ).toHaveFocus(); + await waitFor( async () => + expect( + await screen.findByRole( 'tab', { name: 'Beta' } ) + ).toHaveFocus() + ); // Arrow key should move focus but not automatically change the selected tab. await press.ArrowRight(); diff --git a/packages/components/src/toggle-group-control/test/index.tsx b/packages/components/src/toggle-group-control/test/index.tsx index a8835bc66c58d4..c607d384b0e407 100644 --- a/packages/components/src/toggle-group-control/test/index.tsx +++ b/packages/components/src/toggle-group-control/test/index.tsx @@ -334,9 +334,11 @@ describe.each( [ name: 'R', } ); + await sleep(); await press.Tab(); expect( rigas ).toHaveFocus(); + await sleep(); await press.Tab(); // When in controlled mode, there is an additional "Reset" button. @@ -392,6 +394,7 @@ describe.each( [ ); + await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { @@ -400,6 +403,7 @@ describe.each( [ } ) ).toHaveFocus(); + await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { diff --git a/packages/components/src/tooltip/test/index.tsx b/packages/components/src/tooltip/test/index.tsx index 85e29f5f3809bc..66734b1737053c 100644 --- a/packages/components/src/tooltip/test/index.tsx +++ b/packages/components/src/tooltip/test/index.tsx @@ -67,6 +67,7 @@ describe( 'Tooltip', () => { screen.getByRole( 'button', { name: 'Second button' } ) ).toBeVisible(); + await sleep(); await press.Tab(); expectTooltipToBeHidden(); @@ -134,6 +135,7 @@ describe( 'Tooltip', () => { ); // Focus the anchor, tooltip should show + await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { name: 'Tooltip anchor' } ) @@ -141,6 +143,7 @@ describe( 'Tooltip', () => { await waitExpectTooltipToShow(); // Focus the other button, tooltip should hide + await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { name: 'Focus me' } ) @@ -166,11 +169,13 @@ describe( 'Tooltip', () => { expect( anchor ).toHaveAttribute( 'aria-disabled', 'true' ); // Focus anchor, tooltip should show + await sleep(); await press.Tab(); expect( anchor ).toHaveFocus(); await waitExpectTooltipToShow(); // Focus another button, tooltip should hide + await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { diff --git a/packages/core-data/src/private-selectors.ts b/packages/core-data/src/private-selectors.ts index 94aa00e1c8de45..85dc4e3be7203c 100644 --- a/packages/core-data/src/private-selectors.ts +++ b/packages/core-data/src/private-selectors.ts @@ -1,7 +1,18 @@ +/** + * External dependencies + */ +import createSelector from 'rememo'; + +/** + * WordPress dependencies + */ +import { createRegistrySelector } from '@wordpress/data'; + /** * Internal dependencies */ import type { State } from './selectors'; +import { STORE_NAME } from './name'; type EntityRecordKey = string | number; @@ -28,3 +39,19 @@ export function getNavigationFallbackId( ): EntityRecordKey | undefined { return state.navigationFallbackId; } + +export const getBlockPatternsForPostType = createRegistrySelector( + ( select: any ) => + createSelector( + ( state, postType ) => + select( STORE_NAME ) + .getBlockPatterns() + .filter( + ( { postTypes } ) => + ! postTypes || + ( Array.isArray( postTypes ) && + postTypes.includes( postType ) ) + ), + () => [ select( STORE_NAME ).getBlockPatterns() ] + ) +); diff --git a/packages/create-block-interactive-template/block-templates/render.php.mustache b/packages/create-block-interactive-template/block-templates/render.php.mustache index 960da619f790a4..bb8f843d80a77e 100644 --- a/packages/create-block-interactive-template/block-templates/render.php.mustache +++ b/packages/create-block-interactive-template/block-templates/render.php.mustache @@ -17,7 +17,7 @@ $unique_id = wp_unique_id( 'p-' );
    - data-wp-interactive='{ "namespace": "{{namespace}}" }' + data-wp-interactive="{{namespace}}" data-wp-context='{ "isOpen": false }' data-wp-watch="callbacks.logIsOpen" > diff --git a/packages/edit-site/src/components/test/error-boundary.js b/packages/customize-widgets/src/components/error-boundary/test/error-boundary.js similarity index 94% rename from packages/edit-site/src/components/test/error-boundary.js rename to packages/customize-widgets/src/components/error-boundary/test/error-boundary.js index 7b9977e10f1315..27ec4c80419676 100644 --- a/packages/edit-site/src/components/test/error-boundary.js +++ b/packages/customize-widgets/src/components/error-boundary/test/error-boundary.js @@ -1,15 +1,17 @@ +/** + * External dependencies + */ +import { render } from '@testing-library/react'; + /** * WordPress dependencies */ import * as wpHooks from '@wordpress/hooks'; + /** * Internal dependencies */ -import ErrorBoundary from '../error-boundary'; -/** - * External dependencies - */ -import { render } from '@testing-library/react'; +import ErrorBoundary from '../index'; const theError = new Error( 'Kaboom' ); diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index e476546c514cef..bbc2271db6573c 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -12,85 +12,147 @@ npm install @wordpress/dataviews --save ## Usage -```js - item.id } - isLoading={ isLoadingData } - supportedLayouts={ [ 'table' ] } - deferredRendering={ true } - onSelectionChange={ ( items ) => { /* ... */ } } -/> +```jsx +const Example = () => { + + // Declare data, fields, etc. + + return ( + + ); +} ``` -## Data +## Properties + +### `data`: `Object[]` The dataset to work with, represented as a one-dimensional array. Example: ```js -[ - { id: 1, title: "Title", ... }, - { ... } +const data = [ + { + id: 1, + title: "Title", + author: "Admin", + date: "2012-04-23T18:25:43.511Z" + }, + { /* ... */ } ] ``` -By default, dataviews would use each record's `id` as an unique identifier. If it's not, the consumer should provide a `getItemId` function that returns one. See "Other props" section. +By default, dataviews would use each record's `id` as an unique identifier. If it's not, the consumer should provide a `getItemId` function that returns one. -## Pagination Info +### `fields`: `Object[]` -- `totalItems`: the total number of items in the datasets. -- `totalPages`: the total number of pages, taking into account the total items in the dataset and the number of items per page provided by the user. +The fields describe the visible items for each record in the dataset. -## View +Example: + +```js +const fields = [ + { + id: 'title', + header: 'Title', + getValue: ({ item }) => item.title, + enableHiding: false, + }, + { + id: 'date', + header: 'Date', + getValue: ( { item } ) => item.date, + render: ( { item } ) => { + return ( + + ); + } + }, + { + id: 'author', + header: __( 'Author' ), + getValue: ( { item } ) => item.author, + render: ( { item } ) => { + return ( + { item.author } + ); + }, + type: 'enumeration', + elements: [ + { value: 1, label: 'Admin' } + { value: 2, label: 'User' } + ] + enableSorting: false + } +] +``` + +Each field is an object with the following properties: + +- `id`: identifier for the field. Unique. +- `header`: the field's name to be shown in the UI. +- `getValue`: function that returns the value of the field. +- `render`: function that renders the field. Optional, `getValue` will be used if `render` is not defined. +- `elements`: the set of valid values for the field's value. +- `type`: the type of the field. Used to generate the proper filters. Only `enumeration` available at the moment. See "Field types". +- `enableSorting`: whether the data can be sorted by the given field. True by default. +- `enableHiding`: whether the field can be hidden. True by default. +- `filterBy`: configuration for the filters. + - `operators`: the list of operators supported by the field. + - `isPrimary`: whether it is a primary filter. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter. + +### `view`: `object` The view object configures how the dataset is visible to the user. Example: ```js -{ +const view = { type: 'table', - perPage: 5, - page: 1, - sort: { - field: 'date', - direction: 'desc', - }, search: '', filters: [ { field: 'author', operator: 'in', value: 2 }, { field: 'status', operator: 'in', value: 'publish,draft' } ], + page: 1, + perPage: 5, + sort: { + field: 'date', + direction: 'desc', + }, hiddenFields: [ 'date', 'featured-image' ], layout: {}, } ``` -- `type`: view type, one of `table`, `grid`, `list`. See "View types". -- `perPage`: number of records to show per page. -- `page`: the page that is visible. -- `sort.field`: field used for sorting the dataset. -- `sort.direction`: the direction to use for sorting, one of `asc` or `desc`. +Properties: + +- `type`: view type, one of `table`, `grid`, `list`. See "Layout types". - `search`: the text search applied to the dataset. - `filters`: the filters applied to the dataset. Each item describes: - `field`: which field this filter is bound to. - `operator`: which type of filter it is. One of `in`, `notIn`. See "Operator types". - `value`: the actual value selected by the user. +- `perPage`: number of records to show per page. +- `page`: the page that is visible. +- `sort`: + - `field`: the field used for sorting the dataset. + - `direction`: the direction to use for sorting, one of `asc` or `desc`. - `hiddenFields`: the `id` of the fields that are hidden in the UI. - `layout`: config that is specific to a particular layout type. - `mediaField`: used by the `grid` and `list` layouts. The `id` of the field to be used for rendering each card's media. - - `primaryField`: used by the `grid` and `list` layouts. The `id` of the field to be highlighted in each card/list item. + - `primaryField`: used by the `table`, `grid` and `list` layouts. The `id` of the field to be highlighted in each row/card/item. -### onChangeView: syncing view and data +### `onChangeView`: `function` The view is a representation of the visible state of the dataset: what type of layout is used to display it (table, grid, etc.), how the dataset is filtered, how it is sorted or paginated. @@ -147,65 +209,17 @@ function MyCustomPageTable() { data={ records } view={ view } onChangeView={ setView } - "..." + // ... /> ); } ``` -## Fields - -The fields describe the visible items for each record in the dataset. - -Example: - -```js -[ - { - id: 'date', - header: __( 'Date' ), - getValue: ( { item } ) => item.date, - render: ( { item } ) => { - return ( - - ); - }, - enableHiding: false - }, - { - id: 'author', - header: __( 'Author' ), - getValue: ( { item } ) => item.author, - render: ( { item } ) => { - return ( - { item.author } - ); - }, - type: 'enumeration', - elements: [ - { value: 1, label: 'Admin' } - { value: 2, label: 'User' } - ] - enableSorting: false - } -] -``` - -- `id`: identifier for the field. Unique. -- `header`: the field's name to be shown in the UI. -- `getValue`: function that returns the value of the field. -- `render`: function that renders the field. -- `elements`: the set of valid values for the field's value. -- `type`: the type of the field. Used to generate the proper filters. Only `enumeration` available at the moment. See "Field types". -- `enableSorting`: whether the data can be sorted by the given field. True by default. -- `enableHiding`: whether the field can be hidden. True by default. -- `filterBy`: configuration for the filters. - - `operators`: the list of operators supported by the field. - - `isPrimary`: whether it is a primary filter. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter. +### `actions`: `Object[]` -## Actions +Collection of operations that can be performed upon each record. -Array of operations that can be performed upon each record. Each action is an object with the following properties: +Each action is an object with the following properties: - `id`: string, required. Unique identifier of the action. For example, `move-to-trash`. - `label`: string, required. User facing description of the action. For example, `Move to Trash`. @@ -217,28 +231,59 @@ Array of operations that can be performed upon each record. Each action is an ob - `RenderModal`: ReactElement, optional. If an action requires that some UI be rendered in a modal, it can provide a component which takes as props the record as `item` and a `closeModal` function. When this prop is provided, the `callback` property is ignored. - `hideModalHeader`: boolean, optional. This property is used in combination with `RenderModal` and controls the visibility of the modal's header. If the action renders a modal and doesn't hide the header, the action's label is going to be used in the modal's header. +### `paginationInfo`: `Object` + +- `totalItems`: the total number of items in the datasets. +- `totalPages`: the total number of pages, taking into account the total items in the dataset and the number of items per page provided by the user. + +### `search`: `boolean` + +Whether the search input is enabled. `true` by default. + +### `searchLabel`: `string` + +What text to show in the search input. "Search" by default. + +### `getItemId`: `function` + +Function that receives an item and returns an unique identifier for it. By default, it uses the `id` of the item as unique identifier. If it's not, the consumer should provide their own. + +### `isLoading`: `boolean` + +Whether the data is loading. `false` by default. + +### `supportedLayouts`: `String[]` + +Array of layouts supported. By default, all are: `table`, `grid`, `list`. + +### `deferredRendering`: `boolean` + +Whether the items should be rendered asynchronously. Useful when there's a field that takes a lot of time (e.g.: previews). `false` by default. + +### `onSelectionChange`: `function` + +Callback that signals the user selected one of more items, and takes them as parameter. So far, only the `list` view implements it. + +### `onDetailsChange`: `function` + +Callback that signals the user triggered the details for one of more items, and takes them as paremeter. So far, only the `list` view implements it. + ## Types -- Layout types: - - `table`: the view uses a table layout. - - `grid`: the view uses a grid layout. - - `list`: the view uses a list layout. -- Field types: - - `enumeration`: the field value should be taken and can be filtered from a closed list of elements. -- Operator types: - - `in`: operator to be used in filters for fields of type `enumeration`. - - `notIn`: operator to be used in filters for fields of type `enumeration`. - -## Other properties - -- `search`: whether the search input is enabled. `true` by default. -- `searchLabel`: what text to show in the search input. "Filter list" by default. -- `getItemId`: function that receives an item and returns an unique identifier for it. By default, it uses the `id` of the item as unique identifier. If it's not, the consumer should provide their own. -- `isLoading`: whether the data is loading. `false` by default. -- `supportedLayouts`: array of layouts supported. By default, all are: `table`, `grid`, `list`. -- `deferredRendering`: whether the items should be rendered asynchronously. Useful when there's a field that takes a lot of time (e.g.: previews). `false` by default. -- `onSelectionChange`: callback that signals the user selected one of more items, and takes them as parameter. So far, only the `list` view implements it. -- `onDetailsChange`: callback that signals the user triggered the details for one of more items, and takes them as paremeter. So far, only the `list` view implements it. +### Layouts + +- `table`: the view uses a table layout. +- `grid`: the view uses a grid layout. +- `list`: the view uses a list layout. + +### Fields + +- `enumeration`: the field value should be taken and can be filtered from a closed list of elements. + +### Operators + +- `in`: operator to be used in filters for fields of type `enumeration`. +- `notIn`: operator to be used in filters for fields of type `enumeration`. ## Contributing to this package diff --git a/packages/dataviews/src/stories/index.story.js b/packages/dataviews/src/stories/index.story.js index e0bea0c92c2b21..e7fbfbbe554b01 100644 --- a/packages/dataviews/src/stories/index.story.js +++ b/packages/dataviews/src/stories/index.story.js @@ -6,9 +6,9 @@ import { useState, useMemo, useCallback } from '@wordpress/element'; /** * Internal dependencies */ -import { DataViews, LAYOUT_GRID, LAYOUT_TABLE } from '../index'; - +import { DataViews } from '../index'; import { DEFAULT_VIEW, actions, data } from './fixtures'; +import { LAYOUT_GRID, LAYOUT_TABLE } from '../constants'; const meta = { title: 'DataViews (Experimental)/DataViews', @@ -17,7 +17,9 @@ const meta = { export default meta; const defaultConfigPerViewType = { - [ LAYOUT_TABLE ]: {}, + [ LAYOUT_TABLE ]: { + primaryField: 'title', + }, [ LAYOUT_GRID ]: { mediaField: 'image', primaryField: 'title', @@ -100,23 +102,19 @@ export const Default = ( props ) => { }; }, [ view ] ); const onChangeView = useCallback( - ( viewUpdater ) => { - let updatedView = - typeof viewUpdater === 'function' - ? viewUpdater( view ) - : viewUpdater; - if ( updatedView.type !== view.type ) { - updatedView = { - ...updatedView, + ( newView ) => { + if ( newView.type !== view.type ) { + newView = { + ...newView, layout: { - ...defaultConfigPerViewType[ updatedView.type ], + ...defaultConfigPerViewType[ newView.type ], }, }; } - setView( updatedView ); + setView( newView ); }, - [ view, setView ] + [ view.type, setView ] ); return ( { }; Default.args = { actions, - getItemId: ( item ) => item.id, - isLoading: false, supportedLayouts: [ LAYOUT_TABLE, LAYOUT_GRID ], }; diff --git a/packages/dataviews/src/view-grid.js b/packages/dataviews/src/view-grid.js index 14024163878d1d..44ab1822a60750 100644 --- a/packages/dataviews/src/view-grid.js +++ b/packages/dataviews/src/view-grid.js @@ -12,6 +12,7 @@ import { __experimentalVStack as VStack, Tooltip, } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; import { useAsyncList } from '@wordpress/compose'; import { useState } from '@wordpress/element'; @@ -128,6 +129,7 @@ export default function ViewGrid( { fields, view, actions, + isLoading, getItemId, deferredRendering, selection, @@ -148,29 +150,45 @@ export default function ViewGrid( { ); const shownData = useAsyncList( data, { step: 3 } ); const usedData = deferredRendering ? shownData : data; + const hasData = !! usedData?.length; return ( - - { usedData.map( ( item ) => { - return ( - - ); - } ) } - + <> + { hasData && ( + + { usedData.map( ( item ) => { + return ( + + ); + } ) } + + ) } + { ! hasData && ( +
    +

    { isLoading ? __( 'Loading…' ) : __( 'No results' ) }

    +
    + ) } + ); } diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-bind/render.php b/packages/e2e-tests/plugins/interactive-blocks/directive-bind/render.php index 24e3c9343c1157..1511a8b428de10 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-bind/render.php +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-bind/render.php @@ -8,7 +8,7 @@ wp_enqueue_script_module( 'directive-bind-view' ); ?> -