@wordpress/block-editor 15.9.1-next.738bb1424.0 → 15.9.1-next.8fd3f8831.0

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 (63) hide show
  1. package/build/components/block-card/index.cjs +56 -49
  2. package/build/components/block-card/index.cjs.map +3 -3
  3. package/build/components/block-settings-menu/block-settings-dropdown.cjs +0 -17
  4. package/build/components/block-settings-menu/block-settings-dropdown.cjs.map +2 -2
  5. package/build/components/inspector-controls-tabs/index.cjs +15 -16
  6. package/build/components/inspector-controls-tabs/index.cjs.map +3 -3
  7. package/build/components/inspector-controls-tabs/use-inspector-controls-tabs.cjs +1 -3
  8. package/build/components/inspector-controls-tabs/use-inspector-controls-tabs.cjs.map +3 -3
  9. package/build/components/list-view/block.cjs +4 -4
  10. package/build/components/list-view/block.cjs.map +2 -2
  11. package/build/hooks/index.cjs +3 -1
  12. package/build/hooks/index.cjs.map +3 -3
  13. package/build/hooks/list-view.cjs +89 -0
  14. package/build/hooks/list-view.cjs.map +7 -0
  15. package/build/store/private-actions.cjs +0 -8
  16. package/build/store/private-actions.cjs.map +2 -2
  17. package/build/store/private-selectors.cjs +0 -5
  18. package/build/store/private-selectors.cjs.map +2 -2
  19. package/build/store/reducer.cjs +0 -9
  20. package/build/store/reducer.cjs.map +2 -2
  21. package/build-module/components/block-card/index.js +58 -50
  22. package/build-module/components/block-card/index.js.map +2 -2
  23. package/build-module/components/block-settings-menu/block-settings-dropdown.js +0 -17
  24. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +2 -2
  25. package/build-module/components/inspector-controls-tabs/index.js +16 -17
  26. package/build-module/components/inspector-controls-tabs/index.js.map +2 -2
  27. package/build-module/components/inspector-controls-tabs/use-inspector-controls-tabs.js +1 -3
  28. package/build-module/components/inspector-controls-tabs/use-inspector-controls-tabs.js.map +2 -2
  29. package/build-module/components/list-view/block.js +4 -4
  30. package/build-module/components/list-view/block.js.map +2 -2
  31. package/build-module/hooks/index.js +3 -1
  32. package/build-module/hooks/index.js.map +2 -2
  33. package/build-module/hooks/list-view.js +52 -0
  34. package/build-module/hooks/list-view.js.map +7 -0
  35. package/build-module/store/private-actions.js +0 -7
  36. package/build-module/store/private-actions.js.map +2 -2
  37. package/build-module/store/private-selectors.js +0 -4
  38. package/build-module/store/private-selectors.js.map +2 -2
  39. package/build-module/store/reducer.js +0 -8
  40. package/build-module/store/reducer.js.map +2 -2
  41. package/build-style/content-rtl.css +4 -0
  42. package/build-style/content.css +4 -0
  43. package/build-style/style-rtl.css +4 -2
  44. package/build-style/style.css +4 -2
  45. package/package.json +39 -39
  46. package/src/components/block-card/index.js +83 -57
  47. package/src/components/block-card/style.scss +0 -2
  48. package/src/components/block-settings-menu/block-settings-dropdown.js +0 -33
  49. package/src/components/inspector-controls-tabs/index.js +19 -31
  50. package/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js +1 -3
  51. package/src/components/list-view/block.js +5 -4
  52. package/src/hooks/index.js +2 -0
  53. package/src/hooks/list-view.js +80 -0
  54. package/src/store/private-actions.js +0 -13
  55. package/src/store/private-selectors.js +0 -10
  56. package/src/store/reducer.js +0 -16
  57. package/src/store/test/private-actions.js +0 -17
  58. package/src/store/test/reducer.js +0 -25
  59. package/build/components/inspector-controls-tabs/use-is-list-view-tab-disabled.cjs +0 -36
  60. package/build/components/inspector-controls-tabs/use-is-list-view-tab-disabled.cjs.map +0 -7
  61. package/build-module/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js +0 -11
  62. package/build-module/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js.map +0 -7
  63. package/src/components/inspector-controls-tabs/use-is-list-view-tab-disabled.js +0 -9
@@ -83,6 +83,10 @@
83
83
  /**
84
84
  * Reset the WP Admin page styles for Gutenberg-like pages.
85
85
  */
86
+ /**
87
+ * Creates a checkerboard pattern background to indicate transparency.
88
+ * @param {String} $size - The size of the squares in the checkerboard pattern. Default is 12px.
89
+ */
86
90
  :root {
87
91
  --wp-block-synced-color: #7a00df;
88
92
  --wp-block-synced-color--rgb: 122, 0, 223;
@@ -83,6 +83,10 @@
83
83
  /**
84
84
  * Reset the WP Admin page styles for Gutenberg-like pages.
85
85
  */
86
+ /**
87
+ * Creates a checkerboard pattern background to indicate transparency.
88
+ * @param {String} $size - The size of the squares in the checkerboard pattern. Default is 12px.
89
+ */
86
90
  :root {
87
91
  --wp-block-synced-color: #7a00df;
88
92
  --wp-block-synced-color--rgb: 122, 0, 223;
@@ -83,6 +83,10 @@
83
83
  /**
84
84
  * Reset the WP Admin page styles for Gutenberg-like pages.
85
85
  */
86
+ /**
87
+ * Creates a checkerboard pattern background to indicate transparency.
88
+ * @param {String} $size - The size of the squares in the checkerboard pattern. Default is 12px.
89
+ */
86
90
  :root {
87
91
  --wp-block-synced-color: #7a00df;
88
92
  --wp-block-synced-color--rgb: 122, 0, 223;
@@ -661,9 +665,7 @@ iframe[name=editor-canvas] {
661
665
  }
662
666
 
663
667
  .block-editor-block-card {
664
- align-items: flex-start;
665
668
  color: #1e1e1e;
666
- display: flex;
667
669
  padding: 16px;
668
670
  }
669
671
  .block-editor-block-card.is-parent {
@@ -83,6 +83,10 @@
83
83
  /**
84
84
  * Reset the WP Admin page styles for Gutenberg-like pages.
85
85
  */
86
+ /**
87
+ * Creates a checkerboard pattern background to indicate transparency.
88
+ * @param {String} $size - The size of the squares in the checkerboard pattern. Default is 12px.
89
+ */
86
90
  :root {
87
91
  --wp-block-synced-color: #7a00df;
88
92
  --wp-block-synced-color--rgb: 122, 0, 223;
@@ -661,9 +665,7 @@ iframe[name=editor-canvas] {
661
665
  }
662
666
 
663
667
  .block-editor-block-card {
664
- align-items: flex-start;
665
668
  color: #1e1e1e;
666
- display: flex;
667
669
  padding: 16px;
668
670
  }
669
671
  .block-editor-block-card.is-parent {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/block-editor",
3
- "version": "15.9.1-next.738bb1424.0",
3
+ "version": "15.9.1-next.8fd3f8831.0",
4
4
  "description": "Generic block editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -62,43 +62,43 @@
62
62
  ],
63
63
  "dependencies": {
64
64
  "@react-spring/web": "^9.4.5",
65
- "@wordpress/a11y": "^4.36.1-next.738bb1424.0",
66
- "@wordpress/api-fetch": "^7.36.1-next.738bb1424.0",
67
- "@wordpress/base-styles": "^6.12.1-next.738bb1424.0",
68
- "@wordpress/blob": "^4.36.1-next.738bb1424.0",
69
- "@wordpress/block-serialization-default-parser": "^5.36.1-next.738bb1424.0",
70
- "@wordpress/blocks": "^15.9.1-next.738bb1424.0",
71
- "@wordpress/commands": "^1.36.1-next.738bb1424.0",
72
- "@wordpress/components": "^31.0.1-next.738bb1424.0",
73
- "@wordpress/compose": "^7.36.1-next.738bb1424.0",
74
- "@wordpress/data": "^10.36.1-next.738bb1424.0",
75
- "@wordpress/dataviews": "^11.1.1-next.738bb1424.0",
76
- "@wordpress/date": "^5.36.1-next.738bb1424.0",
77
- "@wordpress/deprecated": "^4.36.1-next.738bb1424.0",
78
- "@wordpress/dom": "^4.36.1-next.738bb1424.0",
79
- "@wordpress/element": "^6.36.1-next.738bb1424.0",
80
- "@wordpress/escape-html": "^3.36.1-next.738bb1424.0",
81
- "@wordpress/global-styles-engine": "^1.3.1-next.738bb1424.0",
82
- "@wordpress/hooks": "^4.36.1-next.738bb1424.0",
83
- "@wordpress/html-entities": "^4.36.1-next.738bb1424.0",
84
- "@wordpress/i18n": "^6.9.1-next.738bb1424.0",
85
- "@wordpress/icons": "^11.3.1-next.738bb1424.0",
86
- "@wordpress/image-cropper": "^1.0.1-next.738bb1424.0",
87
- "@wordpress/interactivity": "^6.36.1-next.738bb1424.0",
88
- "@wordpress/is-shallow-equal": "^5.36.1-next.738bb1424.0",
89
- "@wordpress/keyboard-shortcuts": "^5.36.1-next.738bb1424.0",
90
- "@wordpress/keycodes": "^4.36.1-next.738bb1424.0",
91
- "@wordpress/notices": "^5.36.1-next.738bb1424.0",
92
- "@wordpress/preferences": "^4.36.1-next.738bb1424.0",
93
- "@wordpress/priority-queue": "^3.36.1-next.738bb1424.0",
94
- "@wordpress/private-apis": "^1.36.1-next.738bb1424.0",
95
- "@wordpress/rich-text": "^7.36.1-next.738bb1424.0",
96
- "@wordpress/style-engine": "^2.36.1-next.738bb1424.0",
97
- "@wordpress/token-list": "^3.36.1-next.738bb1424.0",
98
- "@wordpress/upload-media": "^0.21.1-next.738bb1424.0",
99
- "@wordpress/url": "^4.36.1-next.738bb1424.0",
100
- "@wordpress/warning": "^3.36.1-next.738bb1424.0",
101
- "@wordpress/wordcount": "^4.36.1-next.738bb1424.0",
65
+ "@wordpress/a11y": "^4.36.1-next.8fd3f8831.0",
66
+ "@wordpress/api-fetch": "^7.36.1-next.8fd3f8831.0",
67
+ "@wordpress/base-styles": "^6.12.1-next.8fd3f8831.0",
68
+ "@wordpress/blob": "^4.36.1-next.8fd3f8831.0",
69
+ "@wordpress/block-serialization-default-parser": "^5.36.1-next.8fd3f8831.0",
70
+ "@wordpress/blocks": "^15.9.1-next.8fd3f8831.0",
71
+ "@wordpress/commands": "^1.36.1-next.8fd3f8831.0",
72
+ "@wordpress/components": "^31.0.1-next.8fd3f8831.0",
73
+ "@wordpress/compose": "^7.36.1-next.8fd3f8831.0",
74
+ "@wordpress/data": "^10.36.1-next.8fd3f8831.0",
75
+ "@wordpress/dataviews": "^11.1.1-next.8fd3f8831.0",
76
+ "@wordpress/date": "^5.36.1-next.8fd3f8831.0",
77
+ "@wordpress/deprecated": "^4.36.1-next.8fd3f8831.0",
78
+ "@wordpress/dom": "^4.36.1-next.8fd3f8831.0",
79
+ "@wordpress/element": "^6.36.1-next.8fd3f8831.0",
80
+ "@wordpress/escape-html": "^3.36.1-next.8fd3f8831.0",
81
+ "@wordpress/global-styles-engine": "^1.3.1-next.8fd3f8831.0",
82
+ "@wordpress/hooks": "^4.36.1-next.8fd3f8831.0",
83
+ "@wordpress/html-entities": "^4.36.1-next.8fd3f8831.0",
84
+ "@wordpress/i18n": "^6.9.1-next.8fd3f8831.0",
85
+ "@wordpress/icons": "^11.3.1-next.8fd3f8831.0",
86
+ "@wordpress/image-cropper": "^1.0.1-next.8fd3f8831.0",
87
+ "@wordpress/interactivity": "^6.36.1-next.8fd3f8831.0",
88
+ "@wordpress/is-shallow-equal": "^5.36.1-next.8fd3f8831.0",
89
+ "@wordpress/keyboard-shortcuts": "^5.36.1-next.8fd3f8831.0",
90
+ "@wordpress/keycodes": "^4.36.1-next.8fd3f8831.0",
91
+ "@wordpress/notices": "^5.36.1-next.8fd3f8831.0",
92
+ "@wordpress/preferences": "^4.36.1-next.8fd3f8831.0",
93
+ "@wordpress/priority-queue": "^3.36.1-next.8fd3f8831.0",
94
+ "@wordpress/private-apis": "^1.36.1-next.8fd3f8831.0",
95
+ "@wordpress/rich-text": "^7.36.1-next.8fd3f8831.0",
96
+ "@wordpress/style-engine": "^2.36.1-next.8fd3f8831.0",
97
+ "@wordpress/token-list": "^3.36.1-next.8fd3f8831.0",
98
+ "@wordpress/upload-media": "^0.21.1-next.8fd3f8831.0",
99
+ "@wordpress/url": "^4.36.1-next.8fd3f8831.0",
100
+ "@wordpress/warning": "^3.36.1-next.8fd3f8831.0",
101
+ "@wordpress/wordcount": "^4.36.1-next.8fd3f8831.0",
102
102
  "change-case": "^4.1.2",
103
103
  "clsx": "^2.1.1",
104
104
  "colord": "^2.7.0",
@@ -121,5 +121,5 @@
121
121
  "publishConfig": {
122
122
  "access": "public"
123
123
  },
124
- "gitHead": "ab1b004c0d61c295aa34bc86ea07f979343983ce"
124
+ "gitHead": "e582b351bc4c4b8734bb087f63a3beec9875c3c7"
125
125
  }
@@ -11,17 +11,19 @@ import {
11
11
  Icon,
12
12
  __experimentalText as Text,
13
13
  __experimentalVStack as VStack,
14
+ __experimentalHStack as HStack,
14
15
  privateApis as componentsPrivateApis,
15
16
  } from '@wordpress/components';
16
17
  import { useDispatch, useSelect } from '@wordpress/data';
17
18
  import deprecated from '@wordpress/deprecated';
18
- import { __, isRTL } from '@wordpress/i18n';
19
+ import { __, sprintf, isRTL } from '@wordpress/i18n';
19
20
  import {
20
21
  chevronLeft,
21
22
  chevronRight,
22
23
  arrowRight,
23
24
  arrowLeft,
24
25
  } from '@wordpress/icons';
26
+ import { getBlockType, hasBlockSupport } from '@wordpress/blocks';
25
27
 
26
28
  /**
27
29
  * Internal dependencies
@@ -103,18 +105,32 @@ function BlockCard( {
103
105
  ( { title, icon, description } = blockType );
104
106
  }
105
107
 
106
- const parentNavBlockClientId = useSelect(
108
+ const { parentBlockClientId, parentBlockName } = useSelect(
107
109
  ( select ) => {
108
110
  if ( parentClientId || isChild || ! allowParentNavigation ) {
109
- return;
111
+ return {};
110
112
  }
111
- const { getBlockParentsByBlockName } = select( blockEditorStore );
113
+ const { getBlockParents, getBlockName } =
114
+ select( blockEditorStore );
112
115
 
113
- return getBlockParentsByBlockName(
114
- clientId,
115
- 'core/navigation',
116
- true
117
- )[ 0 ];
116
+ // Find the closest parent block that is either:
117
+ // 1. A navigation block (special case for ad-hoc list view support)
118
+ // 2. Any block with listView support
119
+ const parents = getBlockParents( clientId, true );
120
+ const foundParentId = parents.find( ( parentId ) => {
121
+ const parentName = getBlockName( parentId );
122
+ return (
123
+ parentName === 'core/navigation' ||
124
+ hasBlockSupport( parentName, 'listView' )
125
+ );
126
+ } );
127
+
128
+ return {
129
+ parentBlockClientId: foundParentId,
130
+ parentBlockName: foundParentId
131
+ ? getBlockName( foundParentId )
132
+ : null,
133
+ };
118
134
  },
119
135
  [ clientId, allowParentNavigation, isChild, parentClientId ]
120
136
  );
@@ -134,56 +150,66 @@ function BlockCard( {
134
150
  className
135
151
  ) }
136
152
  >
137
- { parentNavBlockClientId && ( // This is only used by the Navigation block for now. It's not ideal having Navigation block specific code here.
138
- <Button
139
- onClick={ () => selectBlock( parentNavBlockClientId ) }
140
- label={
141
- parentNavBlockClientId
142
- ? __( 'Go to parent Navigation block' )
143
- : // TODO - improve copy, not sure that we should use the term 'section'
144
- __( 'Go to parent section' )
145
- }
146
- style={
147
- // TODO: This style override is also used in ToolsPanelHeader.
148
- // It should be supported out-of-the-box by Button.
149
- { minWidth: 24, padding: 0 }
150
- }
151
- icon={ isRTL() ? chevronRight : chevronLeft }
152
- size="small"
153
- />
154
- ) }
155
- { isChild && (
156
- <span className="block-editor-block-card__child-indicator-icon">
157
- <Icon icon={ isRTL() ? arrowLeft : arrowRight } />
158
- </span>
159
- ) }
160
- <OptionalParentSelectButton
161
- onClick={
162
- parentClientId
163
- ? () => {
164
- selectBlock( parentClientId );
165
- }
166
- : undefined
167
- }
168
- >
169
- <BlockIcon icon={ icon } showColors />
170
- <VStack spacing={ 1 }>
171
- <TitleElement className="block-editor-block-card__title">
172
- <span className="block-editor-block-card__name">
173
- { !! name?.length ? name : title }
153
+ <VStack>
154
+ <HStack justify="flex-start" spacing={ 0 }>
155
+ { parentBlockClientId && (
156
+ <Button
157
+ onClick={ () => selectBlock( parentBlockClientId ) }
158
+ label={
159
+ parentBlockName
160
+ ? sprintf(
161
+ /* translators: %s: The name of the parent block. */
162
+ __( 'Go to "%s" block' ),
163
+ getBlockType( parentBlockName )
164
+ ?.title
165
+ )
166
+ : __( 'Go to parent block' )
167
+ }
168
+ style={
169
+ // TODO: This style override is also used in ToolsPanelHeader.
170
+ // It should be supported out-of-the-box by Button.
171
+ { minWidth: 24, padding: 0 }
172
+ }
173
+ icon={ isRTL() ? chevronRight : chevronLeft }
174
+ size="small"
175
+ />
176
+ ) }
177
+ { isChild && (
178
+ <span className="block-editor-block-card__child-indicator-icon">
179
+ <Icon icon={ isRTL() ? arrowLeft : arrowRight } />
174
180
  </span>
175
- { ! parentClientId && ! isChild && !! name?.length && (
176
- <Badge>{ title }</Badge>
177
- ) }
178
- </TitleElement>
179
- { ! parentClientId && ! isChild && description && (
180
- <Text className="block-editor-block-card__description">
181
- { description }
182
- </Text>
183
181
  ) }
184
- { children }
185
- </VStack>
186
- </OptionalParentSelectButton>
182
+ <OptionalParentSelectButton
183
+ onClick={
184
+ parentClientId
185
+ ? () => {
186
+ selectBlock( parentClientId );
187
+ }
188
+ : undefined
189
+ }
190
+ >
191
+ <BlockIcon icon={ icon } showColors />
192
+ <VStack spacing={ 1 }>
193
+ <TitleElement className="block-editor-block-card__title">
194
+ <span className="block-editor-block-card__name">
195
+ { !! name?.length ? name : title }
196
+ </span>
197
+ { ! parentClientId &&
198
+ ! isChild &&
199
+ !! name?.length && (
200
+ <Badge>{ title }</Badge>
201
+ ) }
202
+ </TitleElement>
203
+ { children }
204
+ </VStack>
205
+ </OptionalParentSelectButton>
206
+ </HStack>
207
+ { ! parentClientId && ! isChild && description && (
208
+ <Text className="block-editor-block-card__description">
209
+ { description }
210
+ </Text>
211
+ ) }
212
+ </VStack>
187
213
  </div>
188
214
  );
189
215
  }
@@ -2,9 +2,7 @@
2
2
  @use "@wordpress/base-styles/colors" as *;
3
3
 
4
4
  .block-editor-block-card {
5
- align-items: flex-start;
6
5
  color: $gray-900;
7
- display: flex;
8
6
  padding: $grid-unit-20;
9
7
 
10
8
  &.is-parent {
@@ -77,7 +77,6 @@ export function BlockSettingsDropdown( {
77
77
  ...props
78
78
  } ) {
79
79
  // Get the client id of the current block for this menu, if one is set.
80
- const currentClientId = block?.clientId;
81
80
  const count = clientIds.length;
82
81
  const firstBlockClientId = clientIds[ 0 ];
83
82
 
@@ -86,7 +85,6 @@ export function BlockSettingsDropdown( {
86
85
  parentBlockType,
87
86
  previousBlockClientId,
88
87
  selectedBlockClientIds,
89
- openedBlockSettingsMenu,
90
88
  isContentOnly,
91
89
  isZoomOut,
92
90
  } = useSelect(
@@ -97,7 +95,6 @@ export function BlockSettingsDropdown( {
97
95
  getPreviousBlockClientId,
98
96
  getSelectedBlockClientIds,
99
97
  getBlockAttributes,
100
- getOpenedBlockSettingsMenu,
101
98
  getBlockEditingMode,
102
99
  isZoomOut: _isZoomOut,
103
100
  } = unlock( select( blockEditorStore ) );
@@ -121,7 +118,6 @@ export function BlockSettingsDropdown( {
121
118
  previousBlockClientId:
122
119
  getPreviousBlockClientId( firstBlockClientId ),
123
120
  selectedBlockClientIds: getSelectedBlockClientIds(),
124
- openedBlockSettingsMenu: getOpenedBlockSettingsMenu(),
125
121
  isContentOnly:
126
122
  getBlockEditingMode( firstBlockClientId ) === 'contentOnly',
127
123
  isZoomOut: _isZoomOut(),
@@ -133,10 +129,6 @@ export function BlockSettingsDropdown( {
133
129
  const { getBlockOrder, getSelectedBlockClientIds } =
134
130
  useSelect( blockEditorStore );
135
131
 
136
- const { setOpenedBlockSettingsMenu } = unlock(
137
- useDispatch( blockEditorStore )
138
- );
139
-
140
132
  const shortcuts = useSelect( ( select ) => {
141
133
  const { getShortcutRepresentation } = select( keyboardShortcutsStore );
142
134
  return {
@@ -191,29 +183,6 @@ export function BlockSettingsDropdown( {
191
183
  const parentBlockIsSelected =
192
184
  selectedBlockClientIds?.includes( firstParentClientId );
193
185
 
194
- // When a currentClientId is in use, treat the menu as a controlled component.
195
- // This ensures that only one block settings menu is open at a time.
196
- // This is a temporary solution to work around an issue with `onFocusOutside`
197
- // where it does not allow a dropdown to be closed if focus was never within
198
- // the dropdown to begin with. Examples include a user either CMD+Clicking or
199
- // right clicking into an inactive window.
200
- // See: https://github.com/WordPress/gutenberg/pull/54083
201
- const open = ! currentClientId
202
- ? undefined
203
- : openedBlockSettingsMenu === currentClientId || false;
204
-
205
- function onToggle( localOpen ) {
206
- if ( localOpen && openedBlockSettingsMenu !== currentClientId ) {
207
- setOpenedBlockSettingsMenu( currentClientId );
208
- } else if (
209
- ! localOpen &&
210
- openedBlockSettingsMenu &&
211
- openedBlockSettingsMenu === currentClientId
212
- ) {
213
- setOpenedBlockSettingsMenu( undefined );
214
- }
215
- }
216
-
217
186
  const shouldShowBlockParentMenuItem =
218
187
  ! parentBlockIsSelected && !! firstParentClientId;
219
188
 
@@ -254,8 +223,6 @@ export function BlockSettingsDropdown( {
254
223
  label={ __( 'Options' ) }
255
224
  className="block-editor-block-settings-menu"
256
225
  popoverProps={ POPOVER_PROPS }
257
- open={ open }
258
- onToggle={ onToggle }
259
226
  noIcons
260
227
  { ...props }
261
228
  >
@@ -6,7 +6,7 @@ import {
6
6
  Tooltip,
7
7
  privateApis as componentsPrivateApis,
8
8
  } from '@wordpress/components';
9
- import { useEffect, useState } from '@wordpress/element';
9
+ import { useEffect, useState, useRef } from '@wordpress/element';
10
10
  import { store as preferencesStore } from '@wordpress/preferences';
11
11
  import { useSelect } from '@wordpress/data';
12
12
 
@@ -18,7 +18,6 @@ import SettingsTab from './settings-tab';
18
18
  import StylesTab from './styles-tab';
19
19
  import ContentTab from './content-tab';
20
20
  import InspectorControls from '../inspector-controls';
21
- import useIsListViewTabDisabled from './use-is-list-view-tab-disabled';
22
21
  import { unlock } from '../../lock-unlock';
23
22
 
24
23
  const { Tabs } = unlock( componentsPrivateApis );
@@ -35,47 +34,36 @@ export default function InspectorControlsTabs( {
35
34
  return select( preferencesStore ).get( 'core', 'showIconLabels' );
36
35
  }, [] );
37
36
 
38
- // The tabs panel will mount before fills are rendered to the list view
39
- // slot. This means the list view tab isn't initially included in the
40
- // available tabs so the panel defaults selection to the settings tab
41
- // which at the time is the first tab. This check allows blocks known to
42
- // include the list view tab to set it as the tab selected by default.
43
- const initialTabName = ! useIsListViewTabDisabled( blockName )
44
- ? TAB_LIST_VIEW.name
45
- : undefined;
37
+ const [ selectedTabId, setSelectedTabId ] = useState( tabs[ 0 ]?.name );
38
+ const hasUserSelectionRef = useRef( false );
46
39
 
47
- const [ selectedTabId, setSelectedTabId ] = useState(
48
- initialTabName ?? tabs[ 0 ]?.name
49
- );
40
+ // Reset when switching blocks
41
+ useEffect( () => {
42
+ hasUserSelectionRef.current = false;
43
+ }, [ clientId ] );
50
44
 
51
- // When the active tab is not amongst the available `tabs`, it indicates
52
- // the list of tabs was changed dynamically with the active one being
53
- // removed. Set the active tab back to the first tab.
45
+ // Auto-select first available tab unless user has made a selection
54
46
  useEffect( () => {
55
- // Skip this behavior if `initialTabName` is supplied. In the navigation
56
- // block, the list view tab isn't present in `tabs` initially. The early
57
- // return here prevents the dynamic behavior that follows from overriding
58
- // `initialTabName`.
59
- if ( initialTabName ) {
47
+ if ( ! tabs?.length || hasUserSelectionRef.current ) {
60
48
  return;
61
49
  }
62
50
 
63
- if ( tabs?.length && selectedTabId ) {
64
- const activeTab = tabs.find(
65
- ( tab ) => tab.name === selectedTabId
66
- );
67
- if ( ! activeTab ) {
68
- setSelectedTabId( tabs[ 0 ].name );
69
- }
51
+ const firstTabName = tabs[ 0 ]?.name;
52
+ if ( selectedTabId !== firstTabName ) {
53
+ setSelectedTabId( firstTabName );
70
54
  }
71
- }, [ tabs, selectedTabId, initialTabName ] );
55
+ }, [ tabs, selectedTabId ] );
56
+
57
+ const handleTabSelect = ( tabId ) => {
58
+ setSelectedTabId( tabId );
59
+ hasUserSelectionRef.current = true;
60
+ };
72
61
 
73
62
  return (
74
63
  <div className="block-editor-block-inspector__tabs">
75
64
  <Tabs
76
- defaultTabId={ initialTabName }
77
65
  selectedTabId={ selectedTabId }
78
- onSelect={ setSelectedTabId }
66
+ onSelect={ handleTabSelect }
79
67
  key={ clientId }
80
68
  >
81
69
  <Tabs.TabList>
@@ -8,7 +8,6 @@ import { useSelect } from '@wordpress/data';
8
8
  * Internal dependencies
9
9
  */
10
10
  import InspectorControlsGroups from '../inspector-controls/groups';
11
- import useIsListViewTabDisabled from './use-is-list-view-tab-disabled';
12
11
  import { InspectorAdvancedControls } from '../inspector-controls';
13
12
  import { TAB_LIST_VIEW, TAB_SETTINGS, TAB_STYLES, TAB_CONTENT } from './utils';
14
13
  import { store as blockEditorStore } from '../../store';
@@ -50,9 +49,8 @@ export default function useInspectorControlsTabs(
50
49
  } = InspectorControlsGroups;
51
50
 
52
51
  // List View Tab: If there are any fills for the list group add that tab.
53
- const listViewDisabled = useIsListViewTabDisabled( blockName );
54
52
  const listFills = useSlotFills( listGroup.name );
55
- const hasListFills = ! listViewDisabled && !! listFills && listFills.length;
53
+ const hasListFills = !! listFills && listFills.length;
56
54
 
57
55
  // Styles Tab: Add this tab if there are any fills for block supports
58
56
  // e.g. border, color, spacing, typography, etc.
@@ -96,7 +96,6 @@ function ListViewBlock( {
96
96
  removeBlocks,
97
97
  insertAfterBlock,
98
98
  insertBeforeBlock,
99
- setOpenedBlockSettingsMenu,
100
99
  updateBlockAttributes,
101
100
  } = unlock( useDispatch( blockEditorStore ) );
102
101
  const debouncedToggleBlockHighlight = useDebounce(
@@ -298,7 +297,6 @@ function ListViewBlock( {
298
297
  const newlySelectedBlocks = getSelectedBlockClientIds();
299
298
 
300
299
  // Focus the first block of the newly inserted blocks, to keep focus within the list view.
301
- setOpenedBlockSettingsMenu( undefined );
302
300
  updateFocusAndSelection( newlySelectedBlocks[ 0 ], false );
303
301
  } else if ( isMatch( 'core/block-editor/insert-after', event ) ) {
304
302
  event.preventDefault();
@@ -308,7 +306,6 @@ function ListViewBlock( {
308
306
  const newlySelectedBlocks = getSelectedBlockClientIds();
309
307
 
310
308
  // Focus the first block of the newly inserted blocks, to keep focus within the list view.
311
- setOpenedBlockSettingsMenu( undefined );
312
309
  updateFocusAndSelection( newlySelectedBlocks[ 0 ], false );
313
310
  } else if ( isMatch( 'core/block-editor/select-all', event ) ) {
314
311
  event.preventDefault();
@@ -368,7 +365,6 @@ function ListViewBlock( {
368
365
  speak( __( 'Selected blocks are grouped.' ) );
369
366
  const newlySelectedBlocks = getSelectedBlockClientIds();
370
367
  // Focus the first block of the newly inserted blocks, to keep focus within the list view.
371
- setOpenedBlockSettingsMenu( undefined );
372
368
  updateFocusAndSelection( newlySelectedBlocks[ 0 ], false );
373
369
  }
374
370
  } else if (
@@ -449,6 +445,11 @@ function ListViewBlock( {
449
445
  // Allow right-clicking an item in the List View to open up the block settings dropdown.
450
446
  const onContextMenu = useCallback(
451
447
  ( event ) => {
448
+ const { ownerDocument } = settingsRef?.current || {};
449
+ if ( ! ownerDocument || ! ownerDocument.hasFocus() ) {
450
+ return;
451
+ }
452
+
452
453
  if ( showBlockActions && allowRightClickOverrides ) {
453
454
  settingsRef.current?.click();
454
455
  // Ensure the position of the settings dropdown is at the cursor.
@@ -33,6 +33,7 @@ import contentLockUI from './content-lock-ui';
33
33
  import './metadata';
34
34
  import blockHooks from './block-hooks';
35
35
  import blockBindingsPanel from './block-bindings';
36
+ import listView from './list-view';
36
37
  import './block-renaming';
37
38
  import './grid-visualizer';
38
39
 
@@ -52,6 +53,7 @@ createBlockEditFilter(
52
53
  blockBindingsPanel,
53
54
  childLayout,
54
55
  allowedBlocks,
56
+ listView,
55
57
  ].filter( Boolean )
56
58
  );
57
59
  createBlockListBlockFilter( [