@wordpress/block-editor 12.10.2 → 12.10.4

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 (103) 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/global-styles/hooks.js +1 -1
  4. package/build/components/global-styles/hooks.js.map +1 -1
  5. package/build/components/global-styles/use-global-styles-output.js +17 -5
  6. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  7. package/build/components/global-styles/utils.js +22 -0
  8. package/build/components/global-styles/utils.js.map +1 -1
  9. package/build/components/iframe/index.js +9 -1
  10. package/build/components/iframe/index.js.map +1 -1
  11. package/build/components/inserter/block-patterns-filter.js +11 -10
  12. package/build/components/inserter/block-patterns-filter.js.map +1 -1
  13. package/build/components/inserter/block-patterns-tab.js +1 -1
  14. package/build/components/inserter/block-patterns-tab.js.map +1 -1
  15. package/build/components/inserter/media-tab/hooks.js +4 -33
  16. package/build/components/inserter/media-tab/hooks.js.map +1 -1
  17. package/build/components/link-control/search-item.js +36 -1
  18. package/build/components/link-control/search-item.js.map +1 -1
  19. package/build/components/list-view/block.js +1 -32
  20. package/build/components/list-view/block.js.map +1 -1
  21. package/build/components/list-view/branch.js +8 -1
  22. package/build/components/list-view/branch.js.map +1 -1
  23. package/build/components/list-view/index.js +8 -3
  24. package/build/components/list-view/index.js.map +1 -1
  25. package/build/components/list-view/utils.js +35 -0
  26. package/build/components/list-view/utils.js.map +1 -1
  27. package/build/components/tool-selector/index.js +2 -1
  28. package/build/components/tool-selector/index.js.map +1 -1
  29. package/build/hooks/block-rename-ui.js +5 -2
  30. package/build/hooks/block-rename-ui.js.map +1 -1
  31. package/build/store/actions.js +8 -12
  32. package/build/store/actions.js.map +1 -1
  33. package/build/store/private-selectors.js +55 -1
  34. package/build/store/private-selectors.js.map +1 -1
  35. package/build/store/reducer.js +19 -1
  36. package/build/store/reducer.js.map +1 -1
  37. package/build/utils/transform-styles/transforms/wrap.js +5 -0
  38. package/build/utils/transform-styles/transforms/wrap.js.map +1 -1
  39. package/build-module/components/block-styles/index.js +1 -2
  40. package/build-module/components/block-styles/index.js.map +1 -1
  41. package/build-module/components/global-styles/hooks.js +1 -1
  42. package/build-module/components/global-styles/hooks.js.map +1 -1
  43. package/build-module/components/global-styles/use-global-styles-output.js +17 -6
  44. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  45. package/build-module/components/global-styles/utils.js +21 -0
  46. package/build-module/components/global-styles/utils.js.map +1 -1
  47. package/build-module/components/iframe/index.js +9 -1
  48. package/build-module/components/iframe/index.js.map +1 -1
  49. package/build-module/components/inserter/block-patterns-filter.js +13 -12
  50. package/build-module/components/inserter/block-patterns-filter.js.map +1 -1
  51. package/build-module/components/inserter/block-patterns-tab.js +1 -1
  52. package/build-module/components/inserter/block-patterns-tab.js.map +1 -1
  53. package/build-module/components/inserter/media-tab/hooks.js +5 -34
  54. package/build-module/components/inserter/media-tab/hooks.js.map +1 -1
  55. package/build-module/components/link-control/search-item.js +37 -2
  56. package/build-module/components/link-control/search-item.js.map +1 -1
  57. package/build-module/components/list-view/block.js +3 -34
  58. package/build-module/components/list-view/block.js.map +1 -1
  59. package/build-module/components/list-view/branch.js +8 -1
  60. package/build-module/components/list-view/branch.js.map +1 -1
  61. package/build-module/components/list-view/index.js +8 -3
  62. package/build-module/components/list-view/index.js.map +1 -1
  63. package/build-module/components/list-view/utils.js +34 -0
  64. package/build-module/components/list-view/utils.js.map +1 -1
  65. package/build-module/components/tool-selector/index.js +2 -1
  66. package/build-module/components/tool-selector/index.js.map +1 -1
  67. package/build-module/hooks/block-rename-ui.js +5 -2
  68. package/build-module/hooks/block-rename-ui.js.map +1 -1
  69. package/build-module/store/actions.js +8 -12
  70. package/build-module/store/actions.js.map +1 -1
  71. package/build-module/store/private-selectors.js +52 -0
  72. package/build-module/store/private-selectors.js.map +1 -1
  73. package/build-module/store/reducer.js +18 -1
  74. package/build-module/store/reducer.js.map +1 -1
  75. package/build-module/utils/transform-styles/transforms/wrap.js +5 -0
  76. package/build-module/utils/transform-styles/transforms/wrap.js.map +1 -1
  77. package/build-style/style-rtl.css +1 -1
  78. package/build-style/style.css +1 -1
  79. package/package.json +32 -32
  80. package/src/components/block-styles/index.js +1 -4
  81. package/src/components/global-styles/hooks.js +1 -1
  82. package/src/components/global-styles/test/use-global-styles-output.js +39 -0
  83. package/src/components/global-styles/use-global-styles-output.js +26 -6
  84. package/src/components/global-styles/utils.js +21 -0
  85. package/src/components/iframe/index.js +8 -1
  86. package/src/components/inserter/block-patterns-filter.js +22 -10
  87. package/src/components/inserter/block-patterns-tab.js +0 -3
  88. package/src/components/inserter/media-tab/hooks.js +10 -44
  89. package/src/components/inserter/style.scss +1 -1
  90. package/src/components/link-control/search-item.js +55 -2
  91. package/src/components/list-view/block.js +3 -43
  92. package/src/components/list-view/branch.js +11 -1
  93. package/src/components/list-view/index.js +8 -4
  94. package/src/components/list-view/utils.js +37 -0
  95. package/src/components/tool-selector/index.js +1 -1
  96. package/src/hooks/block-rename-ui.js +14 -10
  97. package/src/store/actions.js +7 -11
  98. package/src/store/private-selectors.js +72 -0
  99. package/src/store/reducer.js +17 -0
  100. package/src/store/test/actions.js +10 -16
  101. package/src/utils/transform-styles/transforms/test/__snapshots__/wrap.js.snap +13 -6
  102. package/src/utils/transform-styles/transforms/test/wrap.js +9 -0
  103. package/src/utils/transform-styles/transforms/wrap.js +5 -0
@@ -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
+ }
@@ -51,7 +51,7 @@ function ToolSelector( props, ref ) {
51
51
  label={ __( 'Tools' ) }
52
52
  />
53
53
  ) }
54
- popoverProps={ { placement: 'bottom-start' } }
54
+ popoverProps={ { placement: 'bottom-start', variant: undefined } }
55
55
  renderContent={ () => (
56
56
  <>
57
57
  <NavigableMenu role="menu" aria-label={ __( 'Tools' ) }>
@@ -44,17 +44,21 @@ function RenameModal( { blockName, originalBlockName, onClose, onSave } ) {
44
44
  );
45
45
 
46
46
  const handleSubmit = () => {
47
- // Must be assertive to immediately announce change.
48
- speak(
49
- sprintf(
50
- /* translators: %1$s: type of update (either reset of changed). %2$s: new name/label for the block */
51
- __( 'Block name %1$s to: "%2$s".' ),
52
- nameIsOriginal || nameIsEmpty ? __( 'reset' ) : __( 'changed' ),
53
- editedBlockName
54
- ),
55
- 'assertive'
56
- );
47
+ const message =
48
+ nameIsOriginal || nameIsEmpty
49
+ ? sprintf(
50
+ /* translators: %s: new name/label for the block */
51
+ __( 'Block name reset to: "%s".' ),
52
+ editedBlockName
53
+ )
54
+ : sprintf(
55
+ /* translators: %s: new name/label for the block */
56
+ __( 'Block name changed to: "%s".' ),
57
+ editedBlockName
58
+ );
57
59
 
60
+ // Must be assertive to immediately announce change.
61
+ speak( message, 'assertive' );
58
62
  onSave( editedBlockName );
59
63
 
60
64
  // Immediate close avoids ability to hit save multiple times.
@@ -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
 
@@ -164,3 +164,75 @@ export function getOpenedBlockSettingsMenu( state ) {
164
164
  export function getStyleOverrides( state ) {
165
165
  return state.styleOverrides;
166
166
  }
167
+
168
+ /** @typedef {import('./actions').InserterMediaCategory} InserterMediaCategory */
169
+ /**
170
+ * Returns the registered inserter media categories through the public API.
171
+ *
172
+ * @param {Object} state Editor state.
173
+ *
174
+ * @return {InserterMediaCategory[]} Inserter media categories.
175
+ */
176
+ export function getRegisteredInserterMediaCategories( state ) {
177
+ return state.registeredInserterMediaCategories;
178
+ }
179
+
180
+ /**
181
+ * Returns an array containing the allowed inserter media categories.
182
+ * It merges the registered media categories from extenders with the
183
+ * core ones. It also takes into account the allowed `mime_types`, which
184
+ * can be altered by `upload_mimes` filter and restrict some of them.
185
+ *
186
+ * @param {Object} state Global application state.
187
+ *
188
+ * @return {InserterMediaCategory[]} Client IDs of descendants.
189
+ */
190
+ export const getInserterMediaCategories = createSelector(
191
+ ( state ) => {
192
+ const {
193
+ settings: {
194
+ inserterMediaCategories,
195
+ allowedMimeTypes,
196
+ enableOpenverseMediaCategory,
197
+ },
198
+ registeredInserterMediaCategories,
199
+ } = state;
200
+ // The allowed `mime_types` can be altered by `upload_mimes` filter and restrict
201
+ // some of them. In this case we shouldn't add the category to the available media
202
+ // categories list in the inserter.
203
+ if (
204
+ ( ! inserterMediaCategories &&
205
+ ! registeredInserterMediaCategories.length ) ||
206
+ ! allowedMimeTypes
207
+ ) {
208
+ return;
209
+ }
210
+ const coreInserterMediaCategoriesNames =
211
+ inserterMediaCategories?.map( ( { name } ) => name ) || [];
212
+ const mergedCategories = [
213
+ ...( inserterMediaCategories || [] ),
214
+ ...( registeredInserterMediaCategories || [] ).filter(
215
+ ( { name } ) =>
216
+ ! coreInserterMediaCategoriesNames.includes( name )
217
+ ),
218
+ ];
219
+ return mergedCategories.filter( ( category ) => {
220
+ // Check if Openverse category is enabled.
221
+ if (
222
+ ! enableOpenverseMediaCategory &&
223
+ category.name === 'openverse'
224
+ ) {
225
+ return false;
226
+ }
227
+ return Object.values( allowedMimeTypes ).some( ( mimeType ) =>
228
+ mimeType.startsWith( `${ category.mediaType }/` )
229
+ );
230
+ } );
231
+ },
232
+ ( state ) => [
233
+ state.settings.inserterMediaCategories,
234
+ state.settings.allowedMimeTypes,
235
+ state.settings.enableOpenverseMediaCategory,
236
+ state.registeredInserterMediaCategories,
237
+ ]
238
+ );
@@ -1949,6 +1949,22 @@ export function styleOverrides( state = new Map(), action ) {
1949
1949
  return state;
1950
1950
  }
1951
1951
 
1952
+ /**
1953
+ * Reducer returning a map of the registered inserter media categories.
1954
+ *
1955
+ * @param {Array} state Current state.
1956
+ * @param {Object} action Dispatched action.
1957
+ *
1958
+ * @return {Array} Updated state.
1959
+ */
1960
+ export function registeredInserterMediaCategories( state = [], action ) {
1961
+ switch ( action.type ) {
1962
+ case 'REGISTER_INSERTER_MEDIA_CATEGORY':
1963
+ return [ ...state, action.category ];
1964
+ }
1965
+ return state;
1966
+ }
1967
+
1952
1968
  const combinedReducers = combineReducers( {
1953
1969
  blocks,
1954
1970
  isTyping,
@@ -1976,6 +1992,7 @@ const combinedReducers = combineReducers( {
1976
1992
  removalPromptData,
1977
1993
  blockRemovalRules,
1978
1994
  openedBlockSettingsMenu,
1995
+ registeredInserterMediaCategories,
1979
1996
  } );
1980
1997
 
1981
1998
  function withAutomaticChangeReset( reducer ) {
@@ -1279,9 +1279,9 @@ describe( 'actions', () => {
1279
1279
  fetch: () => {},
1280
1280
  } )( {
1281
1281
  select: {
1282
- getSettings: () => ( {
1283
- inserterMediaCategories: [ { name: 'a' } ],
1284
- } ),
1282
+ getRegisteredInserterMediaCategories: () => [
1283
+ { name: 'a' },
1284
+ ],
1285
1285
  },
1286
1286
  } );
1287
1287
  expect( console ).toHaveErroredWith(
@@ -1296,11 +1296,9 @@ describe( 'actions', () => {
1296
1296
  fetch: () => {},
1297
1297
  } )( {
1298
1298
  select: {
1299
- getSettings: () => ( {
1300
- inserterMediaCategories: [
1301
- { labels: { name: 'a' } },
1302
- ],
1303
- } ),
1299
+ getRegisteredInserterMediaCategories: () => [
1300
+ { labels: { name: 'a' } },
1301
+ ],
1304
1302
  },
1305
1303
  } );
1306
1304
  expect( console ).toHaveErroredWith(
@@ -1321,18 +1319,14 @@ describe( 'actions', () => {
1321
1319
  const dispatch = jest.fn();
1322
1320
  registerInserterMediaCategory( category )( {
1323
1321
  select: {
1324
- getSettings: () => ( { inserterMediaCategories } ),
1322
+ getRegisteredInserterMediaCategories: () =>
1323
+ inserterMediaCategories,
1325
1324
  },
1326
1325
  dispatch,
1327
1326
  } );
1328
1327
  expect( dispatch ).toHaveBeenLastCalledWith( {
1329
- type: 'UPDATE_SETTINGS',
1330
- settings: {
1331
- inserterMediaCategories: [
1332
- ...inserterMediaCategories,
1333
- { ...category, isExternalResource: true },
1334
- ],
1335
- },
1328
+ type: 'REGISTER_INSERTER_MEDIA_CATEGORY',
1329
+ category: { ...category, isExternalResource: true },
1336
1330
  } );
1337
1331
  } );
1338
1332
  } );
@@ -22,6 +22,19 @@ color: red;
22
22
  }"
23
23
  `;
24
24
 
25
+ exports[`CSS selector wrap should not double wrap selectors 1`] = `
26
+ ".my-namespace h1,
27
+ .my-namespace .red {
28
+ color: red;
29
+ }"
30
+ `;
31
+
32
+ exports[`CSS selector wrap should replace :root selectors 1`] = `
33
+ ".my-namespace {
34
+ --my-color: #ff0000;
35
+ }"
36
+ `;
37
+
25
38
  exports[`CSS selector wrap should replace root tags 1`] = `
26
39
  ".my-namespace,
27
40
  .my-namespace h1 {
@@ -49,9 +62,3 @@ color: red;
49
62
  }
50
63
  }"
51
64
  `;
52
-
53
- exports[`CSS selector wrap should replace :root selectors 1`] = `
54
- ".my-namespace {
55
- --my-color: #ff0000;
56
- }"
57
- `;
@@ -83,4 +83,13 @@ describe( 'CSS selector wrap', () => {
83
83
 
84
84
  expect( output ).toMatchSnapshot();
85
85
  } );
86
+
87
+ it( 'should not double wrap selectors', () => {
88
+ const callback = wrap( '.my-namespace' );
89
+ const input = ` .my-namespace h1, .red { color: red; }`;
90
+
91
+ const output = traverse( input, callback );
92
+
93
+ expect( output ).toMatchSnapshot();
94
+ } );
86
95
  } );
@@ -27,6 +27,11 @@ const wrap =
27
27
  return selector;
28
28
  }
29
29
 
30
+ // Skip the update when a selector already has a namespace + space (" ").
31
+ if ( selector.trim().startsWith( `${ namespace } ` ) ) {
32
+ return selector;
33
+ }
34
+
30
35
  // Anything other than a root tag is always prefixed.
31
36
  {
32
37
  if ( ! selector.match( IS_ROOT_TAG ) ) {