@wordpress/block-editor 12.10.3 → 12.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/build/components/block-styles/index.js +1 -2
  2. package/build/components/block-styles/index.js.map +1 -1
  3. package/build/components/block-switcher/pattern-transformations-menu.js +2 -4
  4. package/build/components/block-switcher/pattern-transformations-menu.js.map +1 -1
  5. package/build/components/iframe/index.js +9 -1
  6. package/build/components/iframe/index.js.map +1 -1
  7. package/build/components/inserter/block-patterns-filter.js +11 -10
  8. package/build/components/inserter/block-patterns-filter.js.map +1 -1
  9. package/build/components/inserter/block-patterns-tab.js +1 -1
  10. package/build/components/inserter/block-patterns-tab.js.map +1 -1
  11. package/build/components/inserter/media-tab/hooks.js +4 -33
  12. package/build/components/inserter/media-tab/hooks.js.map +1 -1
  13. package/build/components/list-view/block.js +1 -32
  14. package/build/components/list-view/block.js.map +1 -1
  15. package/build/components/list-view/branch.js +8 -1
  16. package/build/components/list-view/branch.js.map +1 -1
  17. package/build/components/list-view/index.js +8 -3
  18. package/build/components/list-view/index.js.map +1 -1
  19. package/build/components/list-view/utils.js +35 -0
  20. package/build/components/list-view/utils.js.map +1 -1
  21. package/build/store/actions.js +8 -12
  22. package/build/store/actions.js.map +1 -1
  23. package/build/store/private-selectors.js +55 -1
  24. package/build/store/private-selectors.js.map +1 -1
  25. package/build/store/reducer.js +19 -1
  26. package/build/store/reducer.js.map +1 -1
  27. package/build/utils/transform-styles/transforms/wrap.js +5 -0
  28. package/build/utils/transform-styles/transforms/wrap.js.map +1 -1
  29. package/build-module/components/block-styles/index.js +1 -2
  30. package/build-module/components/block-styles/index.js.map +1 -1
  31. package/build-module/components/block-switcher/pattern-transformations-menu.js +2 -4
  32. package/build-module/components/block-switcher/pattern-transformations-menu.js.map +1 -1
  33. package/build-module/components/iframe/index.js +9 -1
  34. package/build-module/components/iframe/index.js.map +1 -1
  35. package/build-module/components/inserter/block-patterns-filter.js +13 -12
  36. package/build-module/components/inserter/block-patterns-filter.js.map +1 -1
  37. package/build-module/components/inserter/block-patterns-tab.js +1 -1
  38. package/build-module/components/inserter/block-patterns-tab.js.map +1 -1
  39. package/build-module/components/inserter/media-tab/hooks.js +5 -34
  40. package/build-module/components/inserter/media-tab/hooks.js.map +1 -1
  41. package/build-module/components/list-view/block.js +3 -34
  42. package/build-module/components/list-view/block.js.map +1 -1
  43. package/build-module/components/list-view/branch.js +8 -1
  44. package/build-module/components/list-view/branch.js.map +1 -1
  45. package/build-module/components/list-view/index.js +8 -3
  46. package/build-module/components/list-view/index.js.map +1 -1
  47. package/build-module/components/list-view/utils.js +34 -0
  48. package/build-module/components/list-view/utils.js.map +1 -1
  49. package/build-module/store/actions.js +8 -12
  50. package/build-module/store/actions.js.map +1 -1
  51. package/build-module/store/private-selectors.js +52 -0
  52. package/build-module/store/private-selectors.js.map +1 -1
  53. package/build-module/store/reducer.js +18 -1
  54. package/build-module/store/reducer.js.map +1 -1
  55. package/build-module/utils/transform-styles/transforms/wrap.js +5 -0
  56. package/build-module/utils/transform-styles/transforms/wrap.js.map +1 -1
  57. package/build-style/style-rtl.css +6 -1
  58. package/build-style/style.css +6 -1
  59. package/package.json +32 -32
  60. package/src/components/block-styles/index.js +1 -4
  61. package/src/components/block-switcher/pattern-transformations-menu.js +1 -4
  62. package/src/components/block-switcher/style.scss +6 -0
  63. package/src/components/iframe/index.js +8 -1
  64. package/src/components/inserter/block-patterns-filter.js +22 -10
  65. package/src/components/inserter/block-patterns-tab.js +0 -3
  66. package/src/components/inserter/media-tab/hooks.js +10 -44
  67. package/src/components/inserter/style.scss +1 -1
  68. package/src/components/list-view/block.js +3 -43
  69. package/src/components/list-view/branch.js +11 -1
  70. package/src/components/list-view/index.js +8 -4
  71. package/src/components/list-view/utils.js +37 -0
  72. package/src/store/actions.js +7 -11
  73. package/src/store/private-selectors.js +72 -0
  74. package/src/store/reducer.js +17 -0
  75. package/src/store/test/actions.js +10 -16
  76. package/src/utils/transform-styles/transforms/test/__snapshots__/wrap.js.snap +13 -6
  77. package/src/utils/transform-styles/transforms/test/wrap.js +9 -0
  78. package/src/utils/transform-styles/transforms/wrap.js +5 -0
@@ -1160,6 +1160,7 @@
1160
1160
 
1161
1161
  .block-editor-block-switcher__preview__popover {
1162
1162
  display: none;
1163
+ overflow: hidden;
1163
1164
  }
1164
1165
  .block-editor-block-switcher__preview__popover.components-popover {
1165
1166
  margin-top: 11px;
@@ -1176,6 +1177,7 @@
1176
1177
  border-radius: 2px;
1177
1178
  outline: none;
1178
1179
  box-shadow: none;
1180
+ overflow: auto;
1179
1181
  }
1180
1182
  .block-editor-block-switcher__preview__popover .block-editor-block-switcher__preview {
1181
1183
  max-height: calc(500px - 32px);
@@ -1183,6 +1185,9 @@
1183
1185
  padding: 0 16px;
1184
1186
  overflow: hidden;
1185
1187
  }
1188
+ .block-editor-block-switcher__preview__popover .block-editor-block-switcher__preview.is-pattern-list-preview {
1189
+ overflow: unset;
1190
+ }
1186
1191
 
1187
1192
  .block-editor-block-switcher__preview-title {
1188
1193
  margin-bottom: 12px;
@@ -3867,7 +3872,7 @@
3867
3872
  overflow-y: auto;
3868
3873
  flex-grow: 1;
3869
3874
  height: 100%;
3870
- padding: 32px 24px;
3875
+ padding: 16px 24px;
3871
3876
  }
3872
3877
 
3873
3878
  .block-editor-block-patterns-list__list-item .block-editor-block-preview__container {
@@ -1160,6 +1160,7 @@
1160
1160
 
1161
1161
  .block-editor-block-switcher__preview__popover {
1162
1162
  display: none;
1163
+ overflow: hidden;
1163
1164
  }
1164
1165
  .block-editor-block-switcher__preview__popover.components-popover {
1165
1166
  margin-top: 11px;
@@ -1176,6 +1177,7 @@
1176
1177
  border-radius: 2px;
1177
1178
  outline: none;
1178
1179
  box-shadow: none;
1180
+ overflow: auto;
1179
1181
  }
1180
1182
  .block-editor-block-switcher__preview__popover .block-editor-block-switcher__preview {
1181
1183
  max-height: calc(500px - 32px);
@@ -1183,6 +1185,9 @@
1183
1185
  padding: 0 16px;
1184
1186
  overflow: hidden;
1185
1187
  }
1188
+ .block-editor-block-switcher__preview__popover .block-editor-block-switcher__preview.is-pattern-list-preview {
1189
+ overflow: unset;
1190
+ }
1186
1191
 
1187
1192
  .block-editor-block-switcher__preview-title {
1188
1193
  margin-bottom: 12px;
@@ -3868,7 +3873,7 @@
3868
3873
  overflow-y: auto;
3869
3874
  flex-grow: 1;
3870
3875
  height: 100%;
3871
- padding: 32px 24px;
3876
+ padding: 16px 24px;
3872
3877
  }
3873
3878
 
3874
3879
  .block-editor-block-patterns-list__list-item .block-editor-block-preview__container {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/block-editor",
3
- "version": "12.10.3",
3
+ "version": "12.10.5",
4
4
  "description": "Generic block editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -35,36 +35,36 @@
35
35
  "@emotion/react": "^11.7.1",
36
36
  "@emotion/styled": "^11.6.0",
37
37
  "@react-spring/web": "^9.4.5",
38
- "@wordpress/a11y": "^3.42.3",
39
- "@wordpress/api-fetch": "^6.39.3",
40
- "@wordpress/blob": "^3.42.3",
41
- "@wordpress/blocks": "^12.19.3",
42
- "@wordpress/commands": "^0.13.3",
43
- "@wordpress/components": "^25.8.3",
44
- "@wordpress/compose": "^6.19.3",
45
- "@wordpress/data": "^9.12.3",
46
- "@wordpress/date": "^4.42.3",
47
- "@wordpress/deprecated": "^3.42.3",
48
- "@wordpress/dom": "^3.42.3",
49
- "@wordpress/element": "^5.19.3",
50
- "@wordpress/escape-html": "^2.42.3",
51
- "@wordpress/hooks": "^3.42.3",
52
- "@wordpress/html-entities": "^3.42.3",
53
- "@wordpress/i18n": "^4.42.3",
54
- "@wordpress/icons": "^9.33.3",
55
- "@wordpress/is-shallow-equal": "^4.42.3",
56
- "@wordpress/keyboard-shortcuts": "^4.19.3",
57
- "@wordpress/keycodes": "^3.42.3",
58
- "@wordpress/notices": "^4.10.3",
59
- "@wordpress/preferences": "^3.19.3",
60
- "@wordpress/private-apis": "^0.24.3",
61
- "@wordpress/rich-text": "^6.19.3",
62
- "@wordpress/shortcode": "^3.42.3",
63
- "@wordpress/style-engine": "^1.25.3",
64
- "@wordpress/token-list": "^2.42.3",
65
- "@wordpress/url": "^3.43.3",
66
- "@wordpress/warning": "^2.42.3",
67
- "@wordpress/wordcount": "^3.42.3",
38
+ "@wordpress/a11y": "^3.42.5",
39
+ "@wordpress/api-fetch": "^6.39.5",
40
+ "@wordpress/blob": "^3.42.5",
41
+ "@wordpress/blocks": "^12.19.5",
42
+ "@wordpress/commands": "^0.13.5",
43
+ "@wordpress/components": "^25.8.5",
44
+ "@wordpress/compose": "^6.19.5",
45
+ "@wordpress/data": "^9.12.5",
46
+ "@wordpress/date": "^4.42.5",
47
+ "@wordpress/deprecated": "^3.42.5",
48
+ "@wordpress/dom": "^3.42.5",
49
+ "@wordpress/element": "^5.19.5",
50
+ "@wordpress/escape-html": "^2.42.5",
51
+ "@wordpress/hooks": "^3.42.5",
52
+ "@wordpress/html-entities": "^3.42.5",
53
+ "@wordpress/i18n": "^4.42.5",
54
+ "@wordpress/icons": "^9.33.5",
55
+ "@wordpress/is-shallow-equal": "^4.42.5",
56
+ "@wordpress/keyboard-shortcuts": "^4.19.5",
57
+ "@wordpress/keycodes": "^3.42.5",
58
+ "@wordpress/notices": "^4.10.5",
59
+ "@wordpress/preferences": "^3.19.5",
60
+ "@wordpress/private-apis": "^0.24.5",
61
+ "@wordpress/rich-text": "^6.19.5",
62
+ "@wordpress/shortcode": "^3.42.5",
63
+ "@wordpress/style-engine": "^1.25.5",
64
+ "@wordpress/token-list": "^2.42.5",
65
+ "@wordpress/url": "^3.43.5",
66
+ "@wordpress/warning": "^2.42.5",
67
+ "@wordpress/wordcount": "^3.42.5",
68
68
  "change-case": "^4.1.2",
69
69
  "classnames": "^2.3.1",
70
70
  "colord": "^2.7.0",
@@ -86,5 +86,5 @@
86
86
  "publishConfig": {
87
87
  "access": "public"
88
88
  },
89
- "gitHead": "6256f93c37705d142f75a99f1fc808540ca7dca8"
89
+ "gitHead": "edc87d3e33740b82b30f5e21c5953ecded84f08f"
90
90
  }
@@ -14,7 +14,6 @@ import {
14
14
  Popover,
15
15
  } from '@wordpress/components';
16
16
  import deprecated from '@wordpress/deprecated';
17
- import { __ } from '@wordpress/i18n';
18
17
 
19
18
  /**
20
19
  * Internal dependencies
@@ -65,9 +64,7 @@ function BlockStyles( { clientId, onSwitch = noop, onHoverClassName = noop } ) {
65
64
  <div className="block-editor-block-styles">
66
65
  <div className="block-editor-block-styles__variants">
67
66
  { stylesToRender.map( ( style ) => {
68
- const buttonText = style.isDefault
69
- ? __( 'Default' )
70
- : style.label || style.name;
67
+ const buttonText = style.label || style.name;
71
68
 
72
69
  return (
73
70
  <Button
@@ -60,10 +60,7 @@ function PreviewPatternsPopover( { patterns, onSelect } ) {
60
60
  className="block-editor-block-switcher__preview__popover"
61
61
  position="bottom right"
62
62
  >
63
- <div className="block-editor-block-switcher__preview">
64
- <div className="block-editor-block-switcher__preview-title">
65
- { __( 'Preview' ) }
66
- </div>
63
+ <div className="block-editor-block-switcher__preview is-pattern-list-preview">
67
64
  <BlockPatternsList
68
65
  patterns={ patterns }
69
66
  onSelect={ onSelect }
@@ -98,6 +98,7 @@
98
98
 
99
99
  .block-editor-block-switcher__preview__popover {
100
100
  display: none;
101
+ overflow: hidden;
101
102
 
102
103
  // Position correctly. Needs specificity.
103
104
  &.components-popover {
@@ -115,6 +116,7 @@
115
116
  border-radius: $radius-block-ui;
116
117
  outline: none;
117
118
  box-shadow: none;
119
+ overflow: auto;
118
120
  }
119
121
 
120
122
  .block-editor-block-switcher__preview {
@@ -124,6 +126,10 @@
124
126
  // Use padding to prevent the pattern previews focus style from being cut-off.
125
127
  padding: 0 $grid-unit-20;
126
128
  overflow: hidden;
129
+
130
+ &.is-pattern-list-preview {
131
+ overflow: unset;
132
+ }
127
133
  }
128
134
  }
129
135
 
@@ -38,7 +38,14 @@ function bubbleEvent( event, Constructor, frame ) {
38
38
  init[ key ] = event[ key ];
39
39
  }
40
40
 
41
- if ( event instanceof frame.ownerDocument.defaultView.MouseEvent ) {
41
+ // Check if the event is a MouseEvent generated within the iframe.
42
+ // If so, adjust the coordinates to be relative to the position of
43
+ // the iframe. This ensures that components such as Draggable
44
+ // receive coordinates relative to the window, instead of relative
45
+ // to the iframe. Without this, the Draggable event handler would
46
+ // result in components "jumping" position as soon as the user
47
+ // drags over the iframe.
48
+ if ( event instanceof frame.contentDocument.defaultView.MouseEvent ) {
42
49
  const rect = frame.getBoundingClientRect();
43
50
  init.clientX += rect.left;
44
51
  init.clientY += rect.top;
@@ -7,10 +7,11 @@ import {
7
7
  DropdownMenu,
8
8
  MenuGroup,
9
9
  MenuItemsChoice,
10
+ ExternalLink,
10
11
  } from '@wordpress/components';
11
12
  import { __ } from '@wordpress/i18n';
12
13
  import { Icon } from '@wordpress/icons';
13
- import { useMemo } from '@wordpress/element';
14
+ import { useMemo, createInterpolateElement } from '@wordpress/element';
14
15
 
15
16
  /**
16
17
  * Internal dependencies
@@ -73,13 +74,11 @@ export function BlockPatternsSyncFilter( {
73
74
  {
74
75
  value: SYNC_TYPES.full,
75
76
  label: __( 'Synced' ),
76
- info: __( 'Updated everywhere' ),
77
77
  disabled: shouldDisableSyncFilter,
78
78
  },
79
79
  {
80
80
  value: SYNC_TYPES.unsynced,
81
- label: __( 'Standard' ),
82
- info: __( 'Edit freely' ),
81
+ label: __( 'Not synced' ),
83
82
  disabled: shouldDisableSyncFilter,
84
83
  },
85
84
  ],
@@ -95,20 +94,17 @@ export function BlockPatternsSyncFilter( {
95
94
  },
96
95
  {
97
96
  value: PATTERN_TYPES.directory,
98
- label: __( 'Directory' ),
99
- info: __( 'Pattern directory & core' ),
97
+ label: __( 'Pattern Directory' ),
100
98
  disabled: shouldDisableNonUserSources,
101
99
  },
102
100
  {
103
101
  value: PATTERN_TYPES.theme,
104
- label: __( 'Theme' ),
105
- info: __( 'Bundled with the theme' ),
102
+ label: __( 'Theme & Plugins' ),
106
103
  disabled: shouldDisableNonUserSources,
107
104
  },
108
105
  {
109
106
  value: PATTERN_TYPES.user,
110
107
  label: __( 'User' ),
111
- info: __( 'Custom created' ),
112
108
  },
113
109
  ],
114
110
  [ shouldDisableNonUserSources ]
@@ -149,7 +145,7 @@ export function BlockPatternsSyncFilter( {
149
145
  >
150
146
  { () => (
151
147
  <>
152
- <MenuGroup label={ __( 'Author' ) }>
148
+ <MenuGroup label={ __( 'Source' ) }>
153
149
  <MenuItemsChoice
154
150
  choices={ patternSourceMenuOptions }
155
151
  onSelect={ ( value ) => {
@@ -175,6 +171,22 @@ export function BlockPatternsSyncFilter( {
175
171
  value={ patternSyncFilter }
176
172
  />
177
173
  </MenuGroup>
174
+ <div className="block-editor-tool-selector__help">
175
+ { createInterpolateElement(
176
+ __(
177
+ 'Patterns are available from the <Link>WordPress.org Pattern Directory</Link>, bundled in the active theme, or created by users on this site. Only patterns created on this site can be synced.'
178
+ ),
179
+ {
180
+ Link: (
181
+ <ExternalLink
182
+ href={ __(
183
+ 'https://wordpress.org/patterns/'
184
+ ) }
185
+ />
186
+ ),
187
+ }
188
+ ) }
189
+ </div>
178
190
  </>
179
191
  ) }
180
192
  </DropdownMenu>
@@ -321,9 +321,6 @@ export function BlockPatternsCategoryPanel( {
321
321
  category={ category }
322
322
  />
323
323
  </HStack>
324
- { category.description && (
325
- <Text>{ category.description }</Text>
326
- ) }
327
324
  { ! currentCategoryPatterns.length && (
328
325
  <Text
329
326
  variant="muted"
@@ -1,16 +1,17 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useEffect, useState, useRef, useMemo } from '@wordpress/element';
4
+ import { useEffect, useState, useRef } from '@wordpress/element';
5
5
  import { useSelect } from '@wordpress/data';
6
6
 
7
7
  /**
8
8
  * Internal dependencies
9
9
  */
10
10
  import { store as blockEditorStore } from '../../../store';
11
+ import { unlock } from '../../../lock-unlock';
11
12
 
12
- /** @typedef {import('./api').InserterMediaRequest} InserterMediaRequest */
13
- /** @typedef {import('./api').InserterMediaItem} InserterMediaItem */
13
+ /** @typedef {import('../../../store/actions').InserterMediaRequest} InserterMediaRequest */
14
+ /** @typedef {import('../../../store/actions').InserterMediaItem} InserterMediaItem */
14
15
 
15
16
  /**
16
17
  * Fetches media items based on the provided category.
@@ -50,48 +51,14 @@ export function useMediaResults( category, query = {} ) {
50
51
  return { mediaList, isLoading };
51
52
  }
52
53
 
53
- function useInserterMediaCategories() {
54
- const {
55
- inserterMediaCategories,
56
- allowedMimeTypes,
57
- enableOpenverseMediaCategory,
58
- } = useSelect( ( select ) => {
59
- const settings = select( blockEditorStore ).getSettings();
60
- return {
61
- inserterMediaCategories: settings.inserterMediaCategories,
62
- allowedMimeTypes: settings.allowedMimeTypes,
63
- enableOpenverseMediaCategory: settings.enableOpenverseMediaCategory,
64
- };
65
- }, [] );
66
- // The allowed `mime_types` can be altered by `upload_mimes` filter and restrict
67
- // some of them. In this case we shouldn't add the category to the available media
68
- // categories list in the inserter.
69
- const allowedCategories = useMemo( () => {
70
- if ( ! inserterMediaCategories || ! allowedMimeTypes ) {
71
- return;
72
- }
73
- return inserterMediaCategories.filter( ( category ) => {
74
- // Check if Openverse category is enabled.
75
- if (
76
- ! enableOpenverseMediaCategory &&
77
- category.name === 'openverse'
78
- ) {
79
- return false;
80
- }
81
- return Object.values( allowedMimeTypes ).some( ( mimeType ) =>
82
- mimeType.startsWith( `${ category.mediaType }/` )
83
- );
84
- } );
85
- }, [
86
- inserterMediaCategories,
87
- allowedMimeTypes,
88
- enableOpenverseMediaCategory,
89
- ] );
90
- return allowedCategories;
91
- }
92
-
93
54
  export function useMediaCategories( rootClientId ) {
94
55
  const [ categories, setCategories ] = useState( [] );
56
+
57
+ const inserterMediaCategories = useSelect(
58
+ ( select ) =>
59
+ unlock( select( blockEditorStore ) ).getInserterMediaCategories(),
60
+ []
61
+ );
95
62
  const { canInsertImage, canInsertVideo, canInsertAudio } = useSelect(
96
63
  ( select ) => {
97
64
  const { canInsertBlockType } = select( blockEditorStore );
@@ -112,7 +79,6 @@ export function useMediaCategories( rootClientId ) {
112
79
  },
113
80
  [ rootClientId ]
114
81
  );
115
- const inserterMediaCategories = useInserterMediaCategories();
116
82
  useEffect( () => {
117
83
  ( async () => {
118
84
  const _categories = [];
@@ -314,7 +314,7 @@ $block-inserter-tabs-height: 44px;
314
314
  overflow-y: auto;
315
315
  flex-grow: 1;
316
316
  height: 100%;
317
- padding: $grid-unit-40 $grid-unit-30;
317
+ padding: $grid-unit-20 $grid-unit-30;
318
318
  }
319
319
  }
320
320
 
@@ -13,16 +13,9 @@ import {
13
13
  } from '@wordpress/components';
14
14
  import { useInstanceId } from '@wordpress/compose';
15
15
  import { moreVertical } from '@wordpress/icons';
16
- import {
17
- useState,
18
- useRef,
19
- useEffect,
20
- useCallback,
21
- memo,
22
- } from '@wordpress/element';
16
+ import { useState, useRef, useCallback, memo } from '@wordpress/element';
23
17
  import { useDispatch, useSelect } from '@wordpress/data';
24
18
  import { sprintf, __ } from '@wordpress/i18n';
25
- import { focus } from '@wordpress/dom';
26
19
  import { ESCAPE } from '@wordpress/keycodes';
27
20
 
28
21
  /**
@@ -36,7 +29,7 @@ import {
36
29
  } from '../block-mover/button';
37
30
  import ListViewBlockContents from './block-contents';
38
31
  import { useListViewContext } from './context';
39
- import { getBlockPositionDescription } from './utils';
32
+ import { getBlockPositionDescription, focusListItem } from './utils';
40
33
  import { store as blockEditorStore } from '../../store';
41
34
  import useBlockDisplayInformation from '../use-block-display-information';
42
35
  import { useBlockLock } from '../block-lock';
@@ -120,7 +113,6 @@ function ListViewBlock( {
120
113
  );
121
114
 
122
115
  const {
123
- isTreeGridMounted,
124
116
  expand,
125
117
  collapse,
126
118
  BlockSettingsMenu,
@@ -142,15 +134,6 @@ function ListViewBlock( {
142
134
  { 'is-visible': isHovered || isFirstSelectedBlock }
143
135
  );
144
136
 
145
- // If ListView has experimental features related to the Persistent List View,
146
- // only focus the selected list item on mount; otherwise the list would always
147
- // try to steal the focus from the editor canvas.
148
- useEffect( () => {
149
- if ( ! isTreeGridMounted && isSelected ) {
150
- cellRef.current.focus();
151
- }
152
- }, [] );
153
-
154
137
  // If multiple blocks are selected, deselect all blocks when the user
155
138
  // presses the escape key.
156
139
  const onKeyDown = ( event ) => {
@@ -188,30 +171,7 @@ function ListViewBlock( {
188
171
  selectBlock( undefined, focusClientId, null, null );
189
172
  }
190
173
 
191
- const getFocusElement = () => {
192
- const row = treeGridElementRef.current?.querySelector(
193
- `[role=row][data-block="${ focusClientId }"]`
194
- );
195
- if ( ! row ) return null;
196
- // Focus the first focusable in the row, which is the ListViewBlockSelectButton.
197
- return focus.focusable.find( row )[ 0 ];
198
- };
199
-
200
- let focusElement = getFocusElement();
201
- if ( focusElement ) {
202
- focusElement.focus();
203
- } else {
204
- // The element hasn't been painted yet. Defer focusing on the next frame.
205
- // This could happen when all blocks have been deleted and the default block
206
- // hasn't been added to the editor yet.
207
- window.requestAnimationFrame( () => {
208
- focusElement = getFocusElement();
209
- // Ignore if the element still doesn't exist.
210
- if ( focusElement ) {
211
- focusElement.focus();
212
- }
213
- } );
214
- }
174
+ focusListItem( focusClientId, treeGridElementRef );
215
175
  },
216
176
  [ selectBlock, treeGridElementRef ]
217
177
  );
@@ -168,8 +168,18 @@ function ListViewBranch( props ) {
168
168
  );
169
169
  const isSelectedBranch =
170
170
  isBranchSelected || ( isSelected && hasNestedBlocks );
171
+
172
+ // To avoid performance issues, we only render blocks that are in view,
173
+ // or blocks that are selected or dragged. If a block is selected,
174
+ // it is only counted if it is the first of the block selection.
175
+ // This prevents the entire tree from being rendered when a branch is
176
+ // selected, or a user selects all blocks, while still enabling scroll
177
+ // into view behavior when selecting a block or opening the list view.
171
178
  const showBlock =
172
- isDragged || blockInView || isSelected || isBranchDragged;
179
+ isDragged ||
180
+ blockInView ||
181
+ isBranchDragged ||
182
+ ( isSelected && clientId === selectedClientIds[ 0 ] );
173
183
  return (
174
184
  <AsyncModeProvider key={ clientId } value={ ! isSelected }>
175
185
  { showBlock && (
@@ -32,6 +32,7 @@ import useListViewDropZone from './use-list-view-drop-zone';
32
32
  import useListViewExpandSelectedItem from './use-list-view-expand-selected-item';
33
33
  import { store as blockEditorStore } from '../../store';
34
34
  import { BlockSettingsDropdown } from '../block-settings-menu/block-settings-dropdown';
35
+ import { focusListItem } from './utils';
35
36
 
36
37
  const expanded = ( state, action ) => {
37
38
  if ( Array.isArray( action.clientIds ) ) {
@@ -132,8 +133,6 @@ function ListViewComponent(
132
133
  const elementRef = useRef();
133
134
  const treeGridRef = useMergeRefs( [ elementRef, dropZoneRef, ref ] );
134
135
 
135
- const isMounted = useRef( false );
136
-
137
136
  const [ insertedBlock, setInsertedBlock ] = useState( null );
138
137
 
139
138
  const { setSelectedTreeId } = useListViewExpandSelectedItem( {
@@ -156,7 +155,13 @@ function ListViewComponent(
156
155
  [ setSelectedTreeId, updateBlockSelection, onSelect, getBlock ]
157
156
  );
158
157
  useEffect( () => {
159
- isMounted.current = true;
158
+ // If a blocks are already selected when the list view is initially
159
+ // mounted, shift focus to the first selected block.
160
+ if ( selectedClientIds?.length ) {
161
+ focusListItem( selectedClientIds[ 0 ], elementRef );
162
+ }
163
+ // Disable reason: Only focus on the selected item when the list view is mounted.
164
+ // eslint-disable-next-line react-hooks/exhaustive-deps
160
165
  }, [] );
161
166
 
162
167
  const expand = useCallback(
@@ -204,7 +209,6 @@ function ListViewComponent(
204
209
 
205
210
  const contextValue = useMemo(
206
211
  () => ( {
207
- isTreeGridMounted: isMounted.current,
208
212
  draggedClientIds,
209
213
  expandedState,
210
214
  expand,
@@ -2,6 +2,7 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { __, sprintf } from '@wordpress/i18n';
5
+ import { focus } from '@wordpress/dom';
5
6
 
6
7
  export const getBlockPositionDescription = ( position, siblingCount, level ) =>
7
8
  sprintf(
@@ -56,3 +57,39 @@ export function getCommonDepthClientIds(
56
57
  end,
57
58
  };
58
59
  }
60
+
61
+ /**
62
+ * Shift focus to the list view item associated with a particular clientId.
63
+ *
64
+ * @typedef {import('@wordpress/element').RefObject} RefObject
65
+ *
66
+ * @param {string} focusClientId The client ID of the block to focus.
67
+ * @param {RefObject<HTMLElement>} treeGridElementRef The container element to search within.
68
+ */
69
+ export function focusListItem( focusClientId, treeGridElementRef ) {
70
+ const getFocusElement = () => {
71
+ const row = treeGridElementRef.current?.querySelector(
72
+ `[role=row][data-block="${ focusClientId }"]`
73
+ );
74
+ if ( ! row ) return null;
75
+ // Focus the first focusable in the row, which is the ListViewBlockSelectButton.
76
+ return focus.focusable.find( row )[ 0 ];
77
+ };
78
+
79
+ let focusElement = getFocusElement();
80
+ if ( focusElement ) {
81
+ focusElement.focus();
82
+ } else {
83
+ // The element hasn't been painted yet. Defer focusing on the next frame.
84
+ // This could happen when all blocks have been deleted and the default block
85
+ // hasn't been added to the editor yet.
86
+ window.requestAnimationFrame( () => {
87
+ focusElement = getFocusElement();
88
+
89
+ // Ignore if the element still doesn't exist.
90
+ if ( focusElement ) {
91
+ focusElement.focus();
92
+ }
93
+ } );
94
+ }
95
+ }
@@ -1893,9 +1893,10 @@ export const registerInserterMediaCategory =
1893
1893
  );
1894
1894
  return;
1895
1895
  }
1896
- const { inserterMediaCategories = [] } = select.getSettings();
1896
+ const registeredInserterMediaCategories =
1897
+ select.getRegisteredInserterMediaCategories();
1897
1898
  if (
1898
- inserterMediaCategories.some(
1899
+ registeredInserterMediaCategories.some(
1899
1900
  ( { name } ) => name === category.name
1900
1901
  )
1901
1902
  ) {
@@ -1905,8 +1906,8 @@ export const registerInserterMediaCategory =
1905
1906
  return;
1906
1907
  }
1907
1908
  if (
1908
- inserterMediaCategories.some(
1909
- ( { labels: { name } } ) => name === category.labels?.name
1909
+ registeredInserterMediaCategories.some(
1910
+ ( { labels: { name } = {} } ) => name === category.labels?.name
1910
1911
  )
1911
1912
  ) {
1912
1913
  console.error(
@@ -1919,13 +1920,8 @@ export const registerInserterMediaCategory =
1919
1920
  // private, so extenders can only add new inserter media categories and don't have any
1920
1921
  // control over the core media categories.
1921
1922
  dispatch( {
1922
- type: 'UPDATE_SETTINGS',
1923
- settings: {
1924
- inserterMediaCategories: [
1925
- ...inserterMediaCategories,
1926
- { ...category, isExternalResource: true },
1927
- ],
1928
- },
1923
+ type: 'REGISTER_INSERTER_MEDIA_CATEGORY',
1924
+ category: { ...category, isExternalResource: true },
1929
1925
  } );
1930
1926
  };
1931
1927