@wordpress/block-library 9.45.0 → 9.45.1-next.v.202605131006.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 (84) hide show
  1. package/build/breadcrumbs/edit.cjs +1 -1
  2. package/build/breadcrumbs/edit.cjs.map +1 -1
  3. package/build/buttons/edit.cjs +0 -13
  4. package/build/buttons/edit.cjs.map +3 -3
  5. package/build/comment-reply-link/edit.cjs +2 -1
  6. package/build/comment-reply-link/edit.cjs.map +2 -2
  7. package/build/comments/edit/placeholder.cjs +2 -1
  8. package/build/comments/edit/placeholder.cjs.map +2 -2
  9. package/build/embed/transforms.cjs +24 -1
  10. package/build/embed/transforms.cjs.map +2 -2
  11. package/build/freeform/convert-to-blocks-button.cjs +2 -14
  12. package/build/freeform/convert-to-blocks-button.cjs.map +3 -3
  13. package/build/freeform/edit.cjs +43 -15
  14. package/build/freeform/edit.cjs.map +3 -3
  15. package/build/freeform/index.cjs +7 -1
  16. package/build/freeform/index.cjs.map +3 -3
  17. package/build/freeform/migration-notice.cjs +58 -0
  18. package/build/freeform/migration-notice.cjs.map +7 -0
  19. package/build/image/image.cjs +16 -52
  20. package/build/image/image.cjs.map +3 -3
  21. package/build/image/use-open-image-media-editor-modal.cjs +239 -0
  22. package/build/image/use-open-image-media-editor-modal.cjs.map +7 -0
  23. package/build/index.cjs +1 -5
  24. package/build/index.cjs.map +2 -2
  25. package/build/shortcode/transforms.cjs +27 -1
  26. package/build/shortcode/transforms.cjs.map +2 -2
  27. package/build/site-logo/edit.cjs +1 -0
  28. package/build/site-logo/edit.cjs.map +2 -2
  29. package/build/table/edit.cjs +2 -2
  30. package/build/table/edit.cjs.map +2 -2
  31. package/build-module/breadcrumbs/edit.mjs +1 -1
  32. package/build-module/breadcrumbs/edit.mjs.map +1 -1
  33. package/build-module/buttons/edit.mjs +0 -13
  34. package/build-module/buttons/edit.mjs.map +2 -2
  35. package/build-module/comment-reply-link/edit.mjs +3 -2
  36. package/build-module/comment-reply-link/edit.mjs.map +2 -2
  37. package/build-module/comments/edit/placeholder.mjs +3 -2
  38. package/build-module/comments/edit/placeholder.mjs.map +2 -2
  39. package/build-module/embed/transforms.mjs +24 -1
  40. package/build-module/embed/transforms.mjs.map +2 -2
  41. package/build-module/freeform/convert-to-blocks-button.mjs +3 -15
  42. package/build-module/freeform/convert-to-blocks-button.mjs.map +2 -2
  43. package/build-module/freeform/edit.mjs +44 -16
  44. package/build-module/freeform/edit.mjs.map +2 -2
  45. package/build-module/freeform/index.mjs +7 -1
  46. package/build-module/freeform/index.mjs.map +2 -2
  47. package/build-module/freeform/migration-notice.mjs +37 -0
  48. package/build-module/freeform/migration-notice.mjs.map +7 -0
  49. package/build-module/image/image.mjs +16 -52
  50. package/build-module/image/image.mjs.map +3 -3
  51. package/build-module/image/use-open-image-media-editor-modal.mjs +215 -0
  52. package/build-module/image/use-open-image-media-editor-modal.mjs.map +7 -0
  53. package/build-module/index.mjs +1 -5
  54. package/build-module/index.mjs.map +2 -2
  55. package/build-module/shortcode/transforms.mjs +27 -1
  56. package/build-module/shortcode/transforms.mjs.map +2 -2
  57. package/build-module/site-logo/edit.mjs +1 -0
  58. package/build-module/site-logo/edit.mjs.map +2 -2
  59. package/build-module/table/edit.mjs +3 -3
  60. package/build-module/table/edit.mjs.map +2 -2
  61. package/build-types/table-of-contents/list.d.ts +1 -1
  62. package/build-types/table-of-contents/list.d.ts.map +1 -1
  63. package/package.json +41 -40
  64. package/src/breadcrumbs/edit.js +1 -1
  65. package/src/buttons/edit.js +0 -13
  66. package/src/comment-reply-link/edit.js +5 -2
  67. package/src/comments/edit/placeholder.js +5 -2
  68. package/src/cover/editor.scss +2 -2
  69. package/src/cover/style.scss +10 -6
  70. package/src/embed/transforms.js +30 -4
  71. package/src/freeform/convert-to-blocks-button.js +3 -18
  72. package/src/freeform/edit.js +40 -7
  73. package/src/freeform/index.js +9 -1
  74. package/src/freeform/migration-notice.js +51 -0
  75. package/src/image/image.js +14 -63
  76. package/src/image/test/use-open-image-media-editor-modal.js +791 -0
  77. package/src/image/use-open-image-media-editor-modal.js +337 -0
  78. package/src/index.js +3 -16
  79. package/src/navigation/index.php +11 -1
  80. package/src/query/editor.scss +1 -2
  81. package/src/shortcode/transforms.js +37 -0
  82. package/src/site-logo/edit.js +5 -0
  83. package/src/table/edit.js +3 -3
  84. package/src/template-part/editor.scss +1 -1
@@ -0,0 +1,337 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { store as coreStore } from '@wordpress/core-data';
5
+ import {
6
+ privateApis as blockEditorPrivateApis,
7
+ store as blockEditorStore,
8
+ } from '@wordpress/block-editor';
9
+ import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
10
+ import { useRegistry, useSelect } from '@wordpress/data';
11
+ import { useCallback, useEffect, useRef } from '@wordpress/element';
12
+
13
+ /**
14
+ * Internal dependencies
15
+ */
16
+ import { unlock } from '../lock-unlock';
17
+
18
+ function normalizeImageBlockCaption( caption ) {
19
+ if ( typeof caption !== 'string' ) {
20
+ return '';
21
+ }
22
+
23
+ const textContent = stripHTML( caption ).trim();
24
+
25
+ if ( ! textContent ) {
26
+ return '';
27
+ }
28
+
29
+ return caption.replace( /\n/g, '<br>' );
30
+ }
31
+
32
+ function getAttachmentCaption( attachment ) {
33
+ const caption = attachment?.caption;
34
+
35
+ if ( typeof caption === 'string' ) {
36
+ return normalizeImageBlockCaption( caption );
37
+ }
38
+
39
+ if (
40
+ caption &&
41
+ typeof caption === 'object' &&
42
+ Object.hasOwn( caption, 'raw' )
43
+ ) {
44
+ return normalizeImageBlockCaption( caption.raw );
45
+ }
46
+
47
+ return undefined;
48
+ }
49
+
50
+ export function getImageBlockMetadataFromAttachment( attachment ) {
51
+ return {
52
+ alt:
53
+ typeof attachment?.alt_text === 'string'
54
+ ? attachment.alt_text
55
+ : attachment?.alt || '',
56
+ caption: getAttachmentCaption( attachment ),
57
+ };
58
+ }
59
+
60
+ function normalizeMetadataAttribute( value ) {
61
+ return value || '';
62
+ }
63
+
64
+ export function getSyncedImageBlockAttributes(
65
+ currentAttributes,
66
+ originalAttachment,
67
+ updatedAttachment
68
+ ) {
69
+ if ( ! originalAttachment || ! updatedAttachment ) {
70
+ return {};
71
+ }
72
+
73
+ const originalMetadata =
74
+ getImageBlockMetadataFromAttachment( originalAttachment );
75
+ const updatedMetadata =
76
+ getImageBlockMetadataFromAttachment( updatedAttachment );
77
+ const syncedAttributes = {};
78
+
79
+ const normalizedCurrentAlt = normalizeMetadataAttribute(
80
+ currentAttributes.alt
81
+ );
82
+ if (
83
+ originalMetadata.alt !== updatedMetadata.alt &&
84
+ ( normalizedCurrentAlt === originalMetadata.alt ||
85
+ ! normalizedCurrentAlt )
86
+ ) {
87
+ syncedAttributes.alt = updatedMetadata.alt;
88
+ }
89
+
90
+ const normalizedCurrentCaption = normalizeMetadataAttribute(
91
+ currentAttributes.caption
92
+ );
93
+ if (
94
+ originalMetadata.caption !== undefined &&
95
+ updatedMetadata.caption !== undefined &&
96
+ originalMetadata.caption !== updatedMetadata.caption &&
97
+ ( normalizedCurrentCaption === originalMetadata.caption ||
98
+ ! normalizedCurrentCaption )
99
+ ) {
100
+ syncedAttributes.caption = updatedMetadata.caption || undefined;
101
+ }
102
+
103
+ return syncedAttributes;
104
+ }
105
+
106
+ const { openMediaEditorModalKey } = unlock( blockEditorPrivateApis );
107
+ // Caption sync needs `caption.raw`; view/default attachment records can contain
108
+ // only rendered caption data or be tied to an in-flight stale resolution.
109
+ const ATTACHMENT_EDIT_QUERY = { context: 'edit' };
110
+
111
+ function getAttachmentFallbackForEmptyBlockMetadata( { alt, caption } ) {
112
+ const attachment = {};
113
+
114
+ if ( ! alt ) {
115
+ attachment.alt_text = '';
116
+ }
117
+
118
+ if ( ! caption?.toString() ) {
119
+ attachment.caption = '';
120
+ }
121
+
122
+ return Object.keys( attachment ).length ? attachment : undefined;
123
+ }
124
+
125
+ function hasKnownAttachmentMetadata( attachment ) {
126
+ if ( ! attachment ) {
127
+ return false;
128
+ }
129
+
130
+ const hasKnownAlt =
131
+ typeof attachment.alt_text === 'string' ||
132
+ typeof attachment.alt === 'string';
133
+ const hasKnownCaption =
134
+ getImageBlockMetadataFromAttachment( attachment ).caption !== undefined;
135
+
136
+ return hasKnownAlt && hasKnownCaption;
137
+ }
138
+
139
+ export function useOpenImageMediaEditorModal( { attributes, setAttributes } ) {
140
+ // Keep this hook private to the Image block and pass the block attributes
141
+ // object so the callsite stays compact. Destructure only the attributes
142
+ // currently used for metadata sync; add more here if the sync policy grows.
143
+ const { id, url, alt, caption } = attributes;
144
+ const registry = useRegistry();
145
+ const openMediaEditorModal = useSelect(
146
+ ( select ) =>
147
+ select( blockEditorStore ).getSettings()[ openMediaEditorModalKey ],
148
+ []
149
+ );
150
+ // Track the block's current alt and caption in a ref so handleMediaUpdate
151
+ // can read the latest values without being listed as a dependency (which
152
+ // would recreate the callback and re-register the onUpdate handler on every
153
+ // keystroke while the modal is open).
154
+ const blockMetadataRef = useRef( { alt, caption: caption?.toString() } );
155
+ // Snapshot of the attachment's metadata taken just before the modal opens,
156
+ // used as the baseline for detecting what changed during the editing session.
157
+ const mediaEditorMetadataBaselineRef = useRef();
158
+ // Incremented on every handleMediaUpdate call; stale async continuations
159
+ // check against this to bail out if a newer update has since started.
160
+ const mediaEditorMetadataSyncRequestRef = useRef( 0 );
161
+
162
+ useEffect( () => {
163
+ blockMetadataRef.current = { alt, caption: caption?.toString() };
164
+ }, [ alt, caption ] );
165
+
166
+ const getCachedAttachmentRecord = useCallback(
167
+ ( attachmentId ) => {
168
+ const { getEditedEntityRecord, getEntityRecord } =
169
+ registry.select( coreStore );
170
+ return (
171
+ getEditedEntityRecord(
172
+ 'postType',
173
+ 'attachment',
174
+ attachmentId
175
+ ) ||
176
+ getEntityRecord(
177
+ 'postType',
178
+ 'attachment',
179
+ attachmentId,
180
+ ATTACHMENT_EDIT_QUERY
181
+ ) ||
182
+ getEntityRecord( 'postType', 'attachment', attachmentId )
183
+ );
184
+ },
185
+ [ registry ]
186
+ );
187
+
188
+ const resolveAttachmentRecord = useCallback(
189
+ async ( attachmentId ) => {
190
+ const resolveSelect = registry.resolveSelect( coreStore );
191
+
192
+ try {
193
+ return (
194
+ ( await resolveSelect.getEntityRecord(
195
+ 'postType',
196
+ 'attachment',
197
+ attachmentId,
198
+ ATTACHMENT_EDIT_QUERY
199
+ ) ) ||
200
+ ( await resolveSelect.getEntityRecord(
201
+ 'postType',
202
+ 'attachment',
203
+ attachmentId
204
+ ) )
205
+ );
206
+ } catch {
207
+ return undefined;
208
+ }
209
+ },
210
+ [ registry ]
211
+ );
212
+
213
+ const resolveFreshAttachmentRecord = useCallback(
214
+ async ( attachmentId ) => {
215
+ // Bust cached records so resolveAttachmentRecord fetches the
216
+ // server state that reflects the media editor's saved changes.
217
+ const { invalidateResolution } = registry.dispatch( coreStore );
218
+
219
+ invalidateResolution( 'getEntityRecord', [
220
+ 'postType',
221
+ 'attachment',
222
+ attachmentId,
223
+ ] );
224
+ invalidateResolution( 'getEntityRecord', [
225
+ 'postType',
226
+ 'attachment',
227
+ attachmentId,
228
+ ATTACHMENT_EDIT_QUERY,
229
+ ] );
230
+ return resolveAttachmentRecord( attachmentId );
231
+ },
232
+ [ registry, resolveAttachmentRecord ]
233
+ );
234
+
235
+ const handleMediaUpdate = useCallback(
236
+ async ( { id: newId, url: newUrl } ) => {
237
+ if ( typeof newId !== 'number' ) {
238
+ return;
239
+ }
240
+
241
+ // Capture and clear the baseline so a rapid second save doesn't
242
+ // reuse a stale snapshot.
243
+ const originalAttachment = mediaEditorMetadataBaselineRef.current;
244
+ mediaEditorMetadataBaselineRef.current = undefined;
245
+ const syncRequest = ++mediaEditorMetadataSyncRequestRef.current;
246
+ const nextAttributes = {};
247
+
248
+ if ( newId !== id ) {
249
+ nextAttributes.id = newId;
250
+ nextAttributes.url = newUrl ?? url;
251
+ }
252
+
253
+ if ( originalAttachment ) {
254
+ // Fetch fresh server state so the comparison reflects what
255
+ // the media editor actually saved, not a potentially stale
256
+ // cache.
257
+ const resolvedAttachment =
258
+ await resolveFreshAttachmentRecord( newId );
259
+
260
+ // A newer update started while we were awaiting; discard
261
+ // this one.
262
+ if (
263
+ syncRequest !== mediaEditorMetadataSyncRequestRef.current
264
+ ) {
265
+ return;
266
+ }
267
+
268
+ // Sync alt text and caption back to the block only when
269
+ // they were changed in the media editor. Fields the user
270
+ // has independently customised on the block (i.e. values
271
+ // that don't match the pre-session attachment metadata)
272
+ // are left untouched.
273
+ const resolvedMetadataAttributes =
274
+ getSyncedImageBlockAttributes(
275
+ blockMetadataRef.current,
276
+ originalAttachment,
277
+ resolvedAttachment
278
+ );
279
+
280
+ if ( Object.keys( resolvedMetadataAttributes ).length ) {
281
+ Object.assign( nextAttributes, resolvedMetadataAttributes );
282
+ blockMetadataRef.current = {
283
+ ...blockMetadataRef.current,
284
+ ...resolvedMetadataAttributes,
285
+ };
286
+ }
287
+ }
288
+
289
+ if ( Object.keys( nextAttributes ).length ) {
290
+ setAttributes( nextAttributes );
291
+ }
292
+ },
293
+ [ id, resolveFreshAttachmentRecord, setAttributes, url ]
294
+ );
295
+
296
+ const openImageMediaEditorModal = useCallback( async () => {
297
+ if ( ! id || ! openMediaEditorModal ) {
298
+ return;
299
+ }
300
+
301
+ // Snapshot the attachment's current metadata before the user makes
302
+ // any changes so handleMediaUpdate can compare against it later.
303
+ // Prefer a freshly resolved edit-context record for accuracy; fall
304
+ // back to whatever is in the cache, or a minimal object derived from
305
+ // the block's own attributes when nothing is cached yet.
306
+ const cachedAttachmentRecord = getCachedAttachmentRecord( id );
307
+ const fallbackAttachmentRecord =
308
+ getAttachmentFallbackForEmptyBlockMetadata(
309
+ blockMetadataRef.current
310
+ );
311
+ const resolvedAttachmentRecord = hasKnownAttachmentMetadata(
312
+ cachedAttachmentRecord
313
+ )
314
+ ? undefined
315
+ : await resolveAttachmentRecord( id );
316
+
317
+ mediaEditorMetadataBaselineRef.current =
318
+ resolvedAttachmentRecord ||
319
+ ( hasKnownAttachmentMetadata( cachedAttachmentRecord )
320
+ ? cachedAttachmentRecord
321
+ : fallbackAttachmentRecord ) ||
322
+ cachedAttachmentRecord;
323
+
324
+ openMediaEditorModal( {
325
+ id,
326
+ onUpdate: handleMediaUpdate,
327
+ } );
328
+ }, [
329
+ getCachedAttachmentRecord,
330
+ handleMediaUpdate,
331
+ id,
332
+ openMediaEditorModal,
333
+ resolveAttachmentRecord,
334
+ ] );
335
+
336
+ return id && openMediaEditorModal ? openImageMediaEditorModal : undefined;
337
+ }
package/src/index.js CHANGED
@@ -296,22 +296,9 @@ const getAllBlocks = () => {
296
296
  blocks.push( playlistTrack );
297
297
  }
298
298
 
299
- // When in a WordPress context, conditionally
300
- // add the classic block and TinyMCE editor
301
- // under any of the following conditions:
302
- // - the current post contains a classic block
303
- // - the experiment to disable TinyMCE isn't active.
304
- // - a query argument specifies that TinyMCE should be loaded
305
- if (
306
- window?.wp?.oldEditor &&
307
- ( window?.wp?.needsClassicBlock ||
308
- ! window?.__experimentalDisableTinymce ||
309
- !! new URLSearchParams( window?.location?.search ).get(
310
- 'requiresTinymce'
311
- ) )
312
- ) {
313
- blocks.push( classic );
314
- }
299
+ // Always register the classic block. Inserter availability is controlled
300
+ // by the block's `supports.inserter` value in `freeform/init`.
301
+ blocks.push( classic );
315
302
 
316
303
  return blocks.filter( Boolean );
317
304
  };
@@ -425,7 +425,11 @@ class WP_Navigation_Block_Renderer {
425
425
  $full_template_part_id = $theme . '//' . $slug;
426
426
  $block_template = get_block_file_template( $full_template_part_id, 'wp_template_part' );
427
427
  if ( isset( $block_template->content ) ) {
428
- $parsed_blocks = parse_blocks( $block_template->content );
428
+ // Expand shortcodes before parsing blocks, matching the order in
429
+ // `render_block_core_template_part()`.
430
+ $content = shortcode_unautop( $block_template->content );
431
+ $content = do_shortcode( $content );
432
+ $parsed_blocks = parse_blocks( $content );
429
433
  $blocks = block_core_navigation_filter_out_empty_blocks( $parsed_blocks );
430
434
  // Disable overlay menu for any navigation blocks within the overlay to prevent nested overlays.
431
435
  $blocks = static::disable_overlay_menu_for_nested_navigation_blocks( $blocks );
@@ -449,6 +453,12 @@ class WP_Navigation_Block_Renderer {
449
453
  // Re-serialize, and run Block Hooks algorithm to inject hooked blocks.
450
454
  $markup = serialize_blocks( $blocks );
451
455
  $markup = apply_block_hooks_to_content_from_post_object( $markup, $template_part_post );
456
+
457
+ // Expand shortcodes before parsing blocks, matching the order in
458
+ // `render_block_core_template_part()`.
459
+ $markup = shortcode_unautop( $markup );
460
+ $markup = do_shortcode( $markup );
461
+
452
462
  $blocks = parse_blocks( $markup );
453
463
 
454
464
  // Disable overlay menu for any navigation blocks within the overlay to prevent nested overlays.
@@ -2,7 +2,6 @@
2
2
  @use "@wordpress/base-styles/colors" as *;
3
3
  @use "@wordpress/base-styles/mixins" as *;
4
4
  @use "@wordpress/base-styles/variables" as *;
5
- @use "@wordpress/base-styles/z-index" as *;
6
5
 
7
6
  .block-library-query-pattern__selection-modal {
8
7
  .block-editor-block-patterns-list {
@@ -25,7 +24,7 @@
25
24
  padding: $grid-unit-20 0;
26
25
  transform: translateY(- $grid-unit-05); // Offsets the top padding on the modal content container
27
26
  margin-bottom: - $grid-unit-05;
28
- z-index: z-index(".block-library-query-pattern__selection-search");
27
+ z-index: 2; // Above the BlockPreview z-index: 1 overlay in the scrolling list.
29
28
  }
30
29
  }
31
30
 
@@ -2,6 +2,25 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { removep, autop } from '@wordpress/autop';
5
+ import { getBlockTransforms, rawHandler } from '@wordpress/blocks';
6
+ import { next } from '@wordpress/shortcode';
7
+
8
+ const getShortcodeFromTransforms = () =>
9
+ getBlockTransforms( 'from' ).filter(
10
+ ( transform ) =>
11
+ transform.type === 'shortcode' &&
12
+ transform.blockName !== 'core/shortcode'
13
+ );
14
+
15
+ // Single-shortcode only: keeps the transform menu honest (one block in, one
16
+ // block out) and avoids unmatched shortcodes silently falling back to freeform.
17
+ const isSingleShortcode = ( text, tag ) => {
18
+ const trimmed = text.trim();
19
+ const match = next( tag, trimmed );
20
+ return (
21
+ !! match && match.index === 0 && match.content.length === trimmed.length
22
+ );
23
+ };
5
24
 
6
25
  const transforms = {
7
26
  from: [
@@ -26,6 +45,24 @@ const transforms = {
26
45
  priority: 20,
27
46
  },
28
47
  ],
48
+ // One `to` transform per registered shortcode-from block. A single transform
49
+ // with a dynamic `blocks` list won't work: `isMatch` runs once per
50
+ // transform, so all targets would surface (or none) regardless of which
51
+ // shortcode tag the block actually contains.
52
+ get to() {
53
+ return getShortcodeFromTransforms().map( ( fromTransform ) => ( {
54
+ type: 'block',
55
+ blocks: [ fromTransform.blockName ],
56
+ isMatch: ( { text } ) => {
57
+ return []
58
+ .concat( fromTransform.tag )
59
+ .some( ( tag ) => isSingleShortcode( text, tag ) );
60
+ },
61
+ transform: ( { text } ) => {
62
+ return rawHandler( { HTML: `<p>${ text.trim() }</p>` } );
63
+ },
64
+ } ) );
65
+ },
29
66
  };
30
67
 
31
68
  export default transforms;
@@ -409,6 +409,11 @@ const SiteLogo = ( {
409
409
  } )
410
410
  : () => setIsEditingImage( true )
411
411
  }
412
+ aria-haspopup={
413
+ openMediaEditorModal && logoId
414
+ ? 'dialog'
415
+ : undefined
416
+ }
412
417
  icon={ crop }
413
418
  label={ __( 'Crop' ) }
414
419
  />
package/src/table/edit.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  __experimentalUseBorderProps as useBorderProps,
25
25
  useBlockEditingMode,
26
26
  } from '@wordpress/block-editor';
27
- import { __ } from '@wordpress/i18n';
27
+ import { __, _x } from '@wordpress/i18n';
28
28
  import {
29
29
  Button,
30
30
  Placeholder,
@@ -91,8 +91,8 @@ const cellAriaLabel = {
91
91
  };
92
92
 
93
93
  const placeholder = {
94
- head: __( 'Header label' ),
95
- foot: __( 'Footer label' ),
94
+ head: _x( 'Header label', 'table header' ),
95
+ foot: _x( 'Footer label', 'table footer' ),
96
96
  };
97
97
 
98
98
  function TSection( { name, ...props } ) {
@@ -25,7 +25,7 @@
25
25
  position: sticky;
26
26
  top: 0;
27
27
  padding: $grid-unit-20 0;
28
- z-index: z-index(".block-library-template-part__selection-search");
28
+ z-index: 2; // Above the BlockPreview z-index: 1 overlay in the scrolling list.
29
29
  }
30
30
 
31
31
  // We don't use .is-outline-mode in this case so colors take effect properly in the block editor.