@wordpress/block-library 9.43.0 → 9.44.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 (140) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/code/edit.cjs +2 -1
  3. package/build/code/edit.cjs.map +2 -2
  4. package/build/cover/edit/color-utils.cjs +1 -1
  5. package/build/cover/edit/color-utils.cjs.map +2 -2
  6. package/build/cover/edit/index.cjs +39 -26
  7. package/build/cover/edit/index.cjs.map +2 -2
  8. package/build/cover/embed-video-utils.cjs +9 -7
  9. package/build/cover/embed-video-utils.cjs.map +2 -2
  10. package/build/embed/embed-preview.cjs +2 -1
  11. package/build/embed/embed-preview.cjs.map +2 -2
  12. package/build/file/utils/index.cjs +1 -1
  13. package/build/file/utils/index.cjs.map +2 -2
  14. package/build/form/view.cjs +1 -1
  15. package/build/form/view.cjs.map +2 -2
  16. package/build/icon/edit.cjs +1 -3
  17. package/build/icon/edit.cjs.map +2 -2
  18. package/build/image/image.cjs +32 -9
  19. package/build/image/image.cjs.map +2 -2
  20. package/build/navigation-link/link-ui/index.cjs +12 -1
  21. package/build/navigation-link/link-ui/index.cjs.map +2 -2
  22. package/build/navigation-link/link-ui/page-creator.cjs +1 -1
  23. package/build/navigation-link/link-ui/page-creator.cjs.map +2 -2
  24. package/build/navigation-link/shared/update-attributes.cjs +1 -1
  25. package/build/navigation-link/shared/update-attributes.cjs.map +2 -2
  26. package/build/navigation-link/shared/use-link-preview.cjs +1 -1
  27. package/build/navigation-link/shared/use-link-preview.cjs.map +2 -2
  28. package/build/paragraph/use-enter.cjs +4 -5
  29. package/build/paragraph/use-enter.cjs.map +2 -2
  30. package/build/pattern/edit.cjs +1 -1
  31. package/build/pattern/edit.cjs.map +2 -2
  32. package/build/search/block.json +5 -5
  33. package/build/search/edit.cjs +8 -33
  34. package/build/search/edit.cjs.map +2 -2
  35. package/build/separator/transforms.cjs +12 -4
  36. package/build/separator/transforms.cjs.map +2 -2
  37. package/build/tab/add-tab-toolbar-control.cjs +5 -17
  38. package/build/tab/add-tab-toolbar-control.cjs.map +2 -2
  39. package/build/tab/block.json +2 -1
  40. package/build/tab/remove-tab-toolbar-control.cjs +1 -4
  41. package/build/tab/remove-tab-toolbar-control.cjs.map +2 -2
  42. package/build/tabs/edit.cjs +45 -45
  43. package/build/tabs/edit.cjs.map +2 -2
  44. package/build/tabs-menu/block.json +1 -2
  45. package/build/tabs-menu-item/block.json +0 -6
  46. package/build/tabs-menu-item/edit.cjs +2 -8
  47. package/build/tabs-menu-item/edit.cjs.map +2 -2
  48. package/build-module/code/edit.mjs +2 -1
  49. package/build-module/code/edit.mjs.map +2 -2
  50. package/build-module/cover/edit/color-utils.mjs +1 -1
  51. package/build-module/cover/edit/color-utils.mjs.map +2 -2
  52. package/build-module/cover/edit/index.mjs +47 -29
  53. package/build-module/cover/edit/index.mjs.map +2 -2
  54. package/build-module/cover/embed-video-utils.mjs +8 -6
  55. package/build-module/cover/embed-video-utils.mjs.map +2 -2
  56. package/build-module/embed/embed-preview.mjs +2 -1
  57. package/build-module/embed/embed-preview.mjs.map +2 -2
  58. package/build-module/file/utils/index.mjs +1 -1
  59. package/build-module/file/utils/index.mjs.map +2 -2
  60. package/build-module/form/view.mjs +1 -1
  61. package/build-module/form/view.mjs.map +2 -2
  62. package/build-module/icon/edit.mjs +1 -3
  63. package/build-module/icon/edit.mjs.map +2 -2
  64. package/build-module/image/image.mjs +32 -9
  65. package/build-module/image/image.mjs.map +2 -2
  66. package/build-module/navigation-link/link-ui/index.mjs +12 -1
  67. package/build-module/navigation-link/link-ui/index.mjs.map +2 -2
  68. package/build-module/navigation-link/link-ui/page-creator.mjs +1 -1
  69. package/build-module/navigation-link/link-ui/page-creator.mjs.map +2 -2
  70. package/build-module/navigation-link/shared/update-attributes.mjs +1 -1
  71. package/build-module/navigation-link/shared/update-attributes.mjs.map +2 -2
  72. package/build-module/navigation-link/shared/use-link-preview.mjs +1 -1
  73. package/build-module/navigation-link/shared/use-link-preview.mjs.map +2 -2
  74. package/build-module/paragraph/use-enter.mjs +4 -5
  75. package/build-module/paragraph/use-enter.mjs.map +2 -2
  76. package/build-module/pattern/edit.mjs +1 -1
  77. package/build-module/pattern/edit.mjs.map +2 -2
  78. package/build-module/search/block.json +5 -5
  79. package/build-module/search/edit.mjs +8 -33
  80. package/build-module/search/edit.mjs.map +2 -2
  81. package/build-module/separator/transforms.mjs +17 -5
  82. package/build-module/separator/transforms.mjs.map +2 -2
  83. package/build-module/tab/add-tab-toolbar-control.mjs +6 -18
  84. package/build-module/tab/add-tab-toolbar-control.mjs.map +2 -2
  85. package/build-module/tab/block.json +2 -1
  86. package/build-module/tab/remove-tab-toolbar-control.mjs +1 -4
  87. package/build-module/tab/remove-tab-toolbar-control.mjs.map +2 -2
  88. package/build-module/tabs/edit.mjs +45 -45
  89. package/build-module/tabs/edit.mjs.map +2 -2
  90. package/build-module/tabs-menu/block.json +1 -2
  91. package/build-module/tabs-menu-item/block.json +0 -6
  92. package/build-module/tabs-menu-item/edit.mjs +3 -9
  93. package/build-module/tabs-menu-item/edit.mjs.map +2 -2
  94. package/build-style/code/style-rtl.css +1 -1
  95. package/build-style/code/style.css +1 -1
  96. package/build-style/post-author-biography/style-rtl.css +1 -0
  97. package/build-style/post-author-biography/style.css +1 -0
  98. package/build-style/style-rtl.css +11 -16
  99. package/build-style/style.css +11 -16
  100. package/build-style/tabs-menu-item/style-rtl.css +9 -6
  101. package/build-style/tabs-menu-item/style.css +9 -6
  102. package/package.json +38 -38
  103. package/src/code/edit.js +1 -0
  104. package/src/code/style.scss +1 -1
  105. package/src/cover/edit/color-utils.js +1 -1
  106. package/src/cover/edit/index.js +72 -35
  107. package/src/cover/embed-video-utils.js +10 -8
  108. package/src/embed/embed-preview.js +6 -5
  109. package/src/embed/test/index.native.js +3 -2
  110. package/src/file/utils/index.js +1 -1
  111. package/src/form/view.js +1 -1
  112. package/src/icon/edit.js +1 -3
  113. package/src/image/image.js +56 -9
  114. package/src/image/index.php +4 -4
  115. package/src/navigation-link/link-ui/index.js +12 -1
  116. package/src/navigation-link/link-ui/page-creator.js +1 -1
  117. package/src/navigation-link/shared/update-attributes.js +1 -1
  118. package/src/navigation-link/shared/use-link-preview.js +1 -1
  119. package/src/paragraph/use-enter.js +5 -5
  120. package/src/pattern/edit.js +1 -1
  121. package/src/post-author-biography/style.scss +1 -0
  122. package/src/search/block.json +5 -5
  123. package/src/search/edit.js +4 -35
  124. package/src/search/index.php +23 -3
  125. package/src/separator/transforms.js +19 -5
  126. package/src/style.scss +0 -1
  127. package/src/tab/add-tab-toolbar-control.js +24 -42
  128. package/src/tab/block.json +2 -1
  129. package/src/tab/index.php +21 -4
  130. package/src/tab/remove-tab-toolbar-control.js +1 -9
  131. package/src/tabs/edit.js +59 -66
  132. package/src/tabs/index.php +14 -15
  133. package/src/tabs-menu/block.json +1 -2
  134. package/src/tabs-menu/index.php +6 -17
  135. package/src/tabs-menu-item/block.json +0 -6
  136. package/src/tabs-menu-item/edit.js +3 -15
  137. package/src/tabs-menu-item/style.scss +10 -8
  138. package/build-style/tabs-menu/style-rtl.css +0 -8
  139. package/build-style/tabs-menu/style.css +0 -8
  140. package/src/tabs-menu/style.scss +0 -8
@@ -74,18 +74,20 @@ function findVideoEmbedProvider( url ) {
74
74
  }
75
75
 
76
76
  /**
77
- * Extracts iframe src from embed HTML.
77
+ * Modifies embed HTML to use background video parameters.
78
78
  *
79
- * @param {string} html The embed HTML.
80
- * @return {string|null} The iframe src URL or null if not found.
79
+ * @param {string} html The original embed HTML.
80
+ * @return {string|null} The modified embed HTML, or null if not possible.
81
81
  */
82
- export function getIframeSrc( html ) {
83
- if ( ! html ) {
82
+ export function getBackgroundEmbedHtml( html ) {
83
+ const srcMatch = html?.match( /src=["']([^"']+)["']/ );
84
+ if ( ! srcMatch ) {
84
85
  return null;
85
86
  }
86
87
 
87
- const srcMatch = html.match( /src=["']([^"']+)["']/ );
88
- return srcMatch ? srcMatch[ 1 ] : null;
88
+ const iframeSrc = srcMatch[ 1 ];
89
+ const backgroundSrc = getBackgroundVideoSrc( iframeSrc );
90
+ return html.replace( iframeSrc, backgroundSrc );
89
91
  }
90
92
 
91
93
  /**
@@ -189,7 +191,7 @@ export function getBackgroundVideoSrc( src ) {
189
191
  }
190
192
 
191
193
  return url.toString();
192
- } catch ( error ) {
194
+ } catch {
193
195
  // If URL parsing fails, return original src
194
196
  return src;
195
197
  }
@@ -1,8 +1,3 @@
1
- /**
2
- * Internal dependencies
3
- */
4
- import { getPhotoHtml } from './util';
5
-
6
1
  /**
7
2
  * External dependencies
8
3
  */
@@ -17,6 +12,11 @@ import { BlockIcon } from '@wordpress/block-editor';
17
12
  import { useState } from '@wordpress/element';
18
13
  import { getAuthority } from '@wordpress/url';
19
14
 
15
+ /**
16
+ * Internal dependencies
17
+ */
18
+ import { getPhotoHtml } from './util';
19
+
20
20
  /**
21
21
  * Internal dependencies
22
22
  */
@@ -75,6 +75,7 @@ export default function EmbedPreview( {
75
75
  ) : (
76
76
  <div className="wp-block-embed__wrapper">
77
77
  <SandBox
78
+ allowSameOrigin
78
79
  html={ html }
79
80
  scripts={ scripts }
80
81
  title={ iframeTitle }
@@ -28,9 +28,10 @@ import { requestPreview } from '@wordpress/react-native-bridge';
28
28
  /**
29
29
  * Internal dependencies
30
30
  */
31
+ import { WebView } from 'react-native-webview';
32
+
31
33
  import * as paragraph from '../../paragraph';
32
34
  import * as embed from '..';
33
- import { WebView } from 'react-native-webview';
34
35
 
35
36
  // Override modal mock to prevent unmounting it when is not visible.
36
37
  // This is required to be able to trigger onClose and onDismiss events when
@@ -1114,7 +1115,7 @@ describe( 'Embed block', () => {
1114
1115
  try {
1115
1116
  mediaSettingsPanel =
1116
1117
  await screen.findByText( 'Media settings' );
1117
- } catch ( e ) {
1118
+ } catch {
1118
1119
  // NOOP.
1119
1120
  }
1120
1121
 
@@ -54,7 +54,7 @@ const createActiveXObject = ( type ) => {
54
54
  let ax;
55
55
  try {
56
56
  ax = new window.ActiveXObject( type );
57
- } catch ( e ) {
57
+ } catch {
58
58
  ax = undefined;
59
59
  }
60
60
  return ax;
package/src/form/view.js CHANGED
@@ -47,7 +47,7 @@ document.querySelectorAll( 'form.wp-block-form' ).forEach( function ( form ) {
47
47
  } else {
48
48
  redirectNotification( 'error' );
49
49
  }
50
- } catch ( error ) {
50
+ } catch {
51
51
  redirectNotification( 'error' );
52
52
  }
53
53
  } );
package/src/icon/edit.js CHANGED
@@ -78,9 +78,7 @@ export function Edit( { attributes, setAttributes } ) {
78
78
  ? getEntityRecord( 'root', 'icon', icon )
79
79
  : null,
80
80
  allIcons: isInserterOpen
81
- ? getEntityRecords( 'root', 'icon', {
82
- per_page: -1,
83
- } )
81
+ ? getEntityRecords( 'root', 'icon' )
84
82
  : undefined,
85
83
  };
86
84
  },
@@ -313,7 +313,7 @@ export default function Image( {
313
313
  const setRefs = useMergeRefs( [ setImageElement, setResizeObserved ] );
314
314
  const { allowResize = true } = context;
315
315
 
316
- const { image, canUserEdit } = useSelect(
316
+ const { image, canUserEdit, attachmentResolutionError } = useSelect(
317
317
  ( select ) => {
318
318
  const imageRecord =
319
319
  id && isSingleSelected
@@ -325,6 +325,23 @@ export default function Image( {
325
325
  )
326
326
  : null;
327
327
 
328
+ // Check if the attachment resolution failed with a specific error.
329
+ // We use getResolutionError instead of hasFinishedResolution so we
330
+ // can distinguish 404 (attachment doesn't exist) from transient
331
+ // errors (500, 403, network) that shouldn't clear the id.
332
+ const resolutionError =
333
+ id && isSingleSelected
334
+ ? select( coreStore ).getResolutionError(
335
+ 'getEntityRecord',
336
+ [
337
+ 'postType',
338
+ 'attachment',
339
+ id,
340
+ { context: 'view' },
341
+ ]
342
+ )
343
+ : null;
344
+
328
345
  // Check edit permissions when the media editor experiment is enabled.
329
346
  // Only check when imageRecord is available to avoid unnecessary API requests.
330
347
  let canEdit = false;
@@ -339,11 +356,33 @@ export default function Image( {
339
356
  return {
340
357
  image: imageRecord,
341
358
  canUserEdit: canEdit,
359
+ attachmentResolutionError: resolutionError,
342
360
  };
343
361
  },
344
362
  [ id, isSingleSelected ]
345
363
  );
346
364
 
365
+ // If the image has an id but the attachment doesn't exist on this site,
366
+ // clear the id so Gutenberg treats the image as external.
367
+ // This handles content copied between WordPress sites.
368
+ //
369
+ // Known limitation: if a different attachment with the same id happens to
370
+ // exist on the destination site, the lookup will succeed and the wrong
371
+ // local image will be used. URL matching could address this in a follow-up.
372
+ // See: https://github.com/WordPress/gutenberg/issues/74156
373
+ useEffect( () => {
374
+ if ( ! id || ! isSingleSelected ) {
375
+ return;
376
+ }
377
+ // Only clear for confirmed 404s. apiFetch throws the Response object
378
+ // for HTTP errors, so checking .status === 404 avoids incorrectly
379
+ // clearing the id on 403, 500, or network failures, which would
380
+ // cause data loss for valid local attachments.
381
+ if ( attachmentResolutionError?.status === 404 ) {
382
+ setAttributes( { id: undefined } );
383
+ }
384
+ }, [ id, isSingleSelected, attachmentResolutionError, setAttributes ] );
385
+
347
386
  const {
348
387
  canInsertCover,
349
388
  imageEditing,
@@ -396,6 +435,9 @@ export default function Image( {
396
435
  hasNonContentControls &&
397
436
  ! isWideAligned &&
398
437
  isLargeViewport;
438
+ // An image is uploading if it has a temporary blob URL, or if it is
439
+ // being processed client-side (e.g. transcoded or generating sub-sizes).
440
+ const isUploading = !! temporaryURL || isSideloading;
399
441
  const imageSizeOptions = imageSizes
400
442
  .filter(
401
443
  ( { slug } ) => image?.media_details?.sizes?.[ slug ]?.source_url
@@ -532,6 +574,7 @@ export default function Image( {
532
574
  if ( ! mediaUpload ) {
533
575
  return;
534
576
  }
577
+ let notified = false;
535
578
  mediaUpload( {
536
579
  filesList: [ externalBlob ],
537
580
  onFileChange( [ img ] ) {
@@ -541,10 +584,15 @@ export default function Image( {
541
584
  return;
542
585
  }
543
586
 
544
- setExternalBlob();
545
- createSuccessNotice( __( 'Image uploaded.' ), {
546
- type: 'snackbar',
547
- } );
587
+ // With client-side media processing, onFileChange fires
588
+ // for each generated sub-size. Only show the notice once.
589
+ if ( ! notified ) {
590
+ notified = true;
591
+ setExternalBlob();
592
+ createSuccessNotice( __( 'Image uploaded.' ), {
593
+ type: 'snackbar',
594
+ } );
595
+ }
548
596
  },
549
597
  allowedTypes: ALLOWED_MEDIA_TYPES,
550
598
  onError( message ) {
@@ -885,9 +933,7 @@ export default function Image( {
885
933
  onSelectURL={ onSelectURL }
886
934
  onError={ onUploadError }
887
935
  onReset={ () => onSelectImage( undefined ) }
888
- isUploading={
889
- !! temporaryURL || isSideloading
890
- }
936
+ isUploading={ isUploading }
891
937
  emptyLabel={ __( 'Add image' ) }
892
938
  />
893
939
  </ToolsPanelItem>
@@ -1078,7 +1124,7 @@ export default function Image( {
1078
1124
  ...shadowProps.style,
1079
1125
  } }
1080
1126
  />
1081
- { ( temporaryURL || isSideloading ) && <Spinner /> }
1127
+ { isUploading && <Spinner /> }
1082
1128
  </>
1083
1129
  );
1084
1130
 
@@ -1110,6 +1156,7 @@ export default function Image( {
1110
1156
  isResizable &&
1111
1157
  isSingleSelected &&
1112
1158
  ! isEditingImage &&
1159
+ ! isUploading &&
1113
1160
  ! SIZED_LAYOUTS.includes( parentLayoutType )
1114
1161
  ) {
1115
1162
  const numericRatio = aspectRatio && evalAspectRatio( aspectRatio );
@@ -205,8 +205,8 @@ function block_core_image_render_lightbox( $block_content, $block, $block_instan
205
205
  array(
206
206
  'defaultAriaLabel' => __( 'Enlarged image' ),
207
207
  'closeButtonText' => esc_html__( 'Close' ),
208
- 'prevButtonText' => esc_html__( 'Previous' ),
209
- 'nextButtonText' => esc_html__( 'Next' ),
208
+ 'prevButtonText' => esc_html_x( 'Previous', 'previous image in lightbox' ),
209
+ 'nextButtonText' => esc_html_x( 'Next', 'next image in lightbox' ),
210
210
  )
211
211
  );
212
212
 
@@ -323,8 +323,8 @@ function block_core_image_render_lightbox( $block_content, $block, $block_instan
323
323
  function block_core_image_print_lightbox_overlay() {
324
324
  $dialog_label = esc_attr__( 'Enlarged images' );
325
325
  $close_button_text = esc_attr__( 'Close' );
326
- $prev_button_text = esc_attr__( 'Previous' );
327
- $next_button_text = esc_attr__( 'Next' );
326
+ $prev_button_text = esc_attr_x( 'Previous', 'previous image in lightbox' );
327
+ $next_button_text = esc_attr_x( 'Next', 'next image in lightbox' );
328
328
  $close_button_icon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false"><path d="m13.06 12 6.47-6.47-1.06-1.06L12 10.94 5.53 4.47 4.47 5.53 10.94 12l-6.47 6.47 1.06 1.06L12 13.06l6.47 6.47 1.06-1.06L13.06 12Z"></path></svg>';
329
329
  $prev_button_icon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="28" height="28" aria-hidden="true" focusable="false"><path d="M14.6 7l-1.2-1L8 12l5.4 6 1.2-1-4.6-5z"></path></svg>';
330
330
  $next_button_icon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="28" height="28" aria-hidden="true" focusable="false"><path d="M10.6 6L9.4 7l4.6 5-4.6 5 1.2 1 5.4-6z"></path></svg>';
@@ -124,13 +124,24 @@ function UnforwardedLinkUI( props, ref ) {
124
124
  url,
125
125
  opensInNewTab,
126
126
  title: label && stripHTML( label ),
127
+ entityTitle: entityRecord?.title?.rendered || entityRecord?.name,
127
128
  kind,
128
129
  type,
129
130
  id,
130
131
  image,
131
132
  badges,
132
133
  } ),
133
- [ label, opensInNewTab, url, kind, type, id, image, badges ]
134
+ [
135
+ label,
136
+ opensInNewTab,
137
+ url,
138
+ kind,
139
+ type,
140
+ id,
141
+ image,
142
+ badges,
143
+ entityRecord,
144
+ ]
134
145
  );
135
146
 
136
147
  const handlePageCreated = ( pageLink ) => {
@@ -103,7 +103,7 @@ export function LinkUIPageCreator( {
103
103
 
104
104
  onPageCreated( pageLink );
105
105
  }
106
- } catch ( error ) {
106
+ } catch {
107
107
  // Show error notice
108
108
  createErrorNotice(
109
109
  __( 'Failed to create page. Please try again.' ),
@@ -34,7 +34,7 @@ const shouldSeverEntityLink = ( originalUrl, newUrl ) => {
34
34
  ? window.location.origin
35
35
  : 'https://wordpress.org' );
36
36
  return new URL( url, base );
37
- } catch ( error ) {
37
+ } catch {
38
38
  // If URL construction still fails, it's likely an invalid URL
39
39
  // and we should sever the entity link
40
40
  return null;
@@ -101,7 +101,7 @@ export function computeDisplayUrl( { linkUrl, homeUrl } = {} ) {
101
101
  // Different host - this is an external link
102
102
  isExternal = true;
103
103
  }
104
- } catch ( e ) {
104
+ } catch {
105
105
  // URL parsing failed - treat as external (e.g. no homeUrl, or URL without protocol)
106
106
  isExternal = true;
107
107
  }
@@ -90,12 +90,12 @@ export function useOnEnter( props ) {
90
90
  }
91
91
 
92
92
  const defaultBlockName = getDefaultBlockName();
93
+ const wrapperBlockName = getBlockName( wrapperClientId );
94
+ const grandparentClientId = getBlockRootClientId( wrapperClientId );
93
95
 
94
96
  if (
95
- ! canInsertBlockType(
96
- defaultBlockName,
97
- getBlockRootClientId( wrapperClientId )
98
- )
97
+ ! canInsertBlockType( defaultBlockName, grandparentClientId ) ||
98
+ ! canInsertBlockType( wrapperBlockName, grandparentClientId )
99
99
  ) {
100
100
  return;
101
101
  }
@@ -119,7 +119,7 @@ export function useOnEnter( props ) {
119
119
  insertBlock(
120
120
  createBlock( defaultBlockName ),
121
121
  blockIndex + 1,
122
- getBlockRootClientId( wrapperClientId ),
122
+ grandparentClientId,
123
123
  true
124
124
  );
125
125
  } );
@@ -78,7 +78,7 @@ const PatternEdit = ( { attributes, clientId } ) => {
78
78
  if ( ! hasRecursionError && selectedPattern?.blocks ) {
79
79
  try {
80
80
  parsePatternDependencies( selectedPattern );
81
- } catch ( error ) {
81
+ } catch {
82
82
  setHasRecursionError( true );
83
83
  return;
84
84
  }
@@ -1,4 +1,5 @@
1
1
  .wp-block-post-author-biography {
2
2
  // This block has customizable padding, border-box makes that more predictable.
3
3
  box-sizing: border-box;
4
+ white-space: pre-wrap;
4
5
  }
@@ -42,10 +42,6 @@
42
42
  "query": {
43
43
  "type": "object",
44
44
  "default": {}
45
- },
46
- "isSearchFieldHidden": {
47
- "type": "boolean",
48
- "default": false
49
45
  }
50
46
  },
51
47
  "supports": {
@@ -92,5 +88,9 @@
92
88
  "html": false
93
89
  },
94
90
  "editorStyle": "wp-block-search-editor",
95
- "style": "wp-block-search"
91
+ "style": "wp-block-search",
92
+ "selectors": {
93
+ "color": ".wp-block-search .wp-block-search__button, .wp-block-search.wp-block-search__no-button .wp-block-search__input",
94
+ "border": ".wp-block-search.wp-block-search__button-outside .wp-block-search__input, .wp-block-search.wp-block-search__button-outside .wp-block-search__button, .wp-block-search.wp-block-search__no-button .wp-block-search__input, .wp-block-search.wp-block-search__button-only .wp-block-search__input, .wp-block-search.wp-block-search__button-only .wp-block-search__button, .wp-block-search.wp-block-search__button-inside .wp-block-search__inside-wrapper"
95
+ }
96
96
  }
@@ -70,7 +70,6 @@ export default function SearchEdit( {
70
70
  buttonText,
71
71
  buttonPosition,
72
72
  buttonUseIcon,
73
- isSearchFieldHidden,
74
73
  style,
75
74
  } = attributes;
76
75
 
@@ -139,6 +138,7 @@ export default function SearchEdit( {
139
138
  const isButtonPositionOutside = 'button-outside' === buttonPosition;
140
139
  const hasNoButton = 'no-button' === buttonPosition;
141
140
  const hasOnlyButton = 'button-only' === buttonPosition;
141
+ const isSearchFieldHidden = hasOnlyButton && ! isSelected;
142
142
  const searchFieldRef = useRef();
143
143
  const buttonRef = useRef();
144
144
 
@@ -147,25 +147,6 @@ export default function SearchEdit( {
147
147
  defaultValues: { '%': PC_WIDTH_DEFAULT, px: PX_WIDTH_DEFAULT },
148
148
  } );
149
149
 
150
- useEffect( () => {
151
- if ( hasOnlyButton && ! isSelected ) {
152
- setAttributes( {
153
- isSearchFieldHidden: true,
154
- } );
155
- }
156
- }, [ hasOnlyButton, isSelected, setAttributes ] );
157
-
158
- // Show the search field when width changes.
159
- useEffect( () => {
160
- if ( ! hasOnlyButton || ! isSelected ) {
161
- return;
162
- }
163
-
164
- setAttributes( {
165
- isSearchFieldHidden: false,
166
- } );
167
- }, [ hasOnlyButton, isSelected, setAttributes, width ] );
168
-
169
150
  const getBlockClassNames = () => {
170
151
  return clsx(
171
152
  className,
@@ -183,7 +164,7 @@ export default function SearchEdit( {
183
164
  buttonUseIcon && ! hasNoButton
184
165
  ? 'wp-block-search__icon-button'
185
166
  : undefined,
186
- hasOnlyButton && isSearchFieldHidden
167
+ isSearchFieldHidden
187
168
  ? 'wp-block-search__searchfield-hidden'
188
169
  : undefined
189
170
  );
@@ -223,10 +204,12 @@ export default function SearchEdit( {
223
204
  // If the input is inside the wrapper, the wrapper gets the border color styles/classes, not the input control.
224
205
  const textFieldClasses = clsx(
225
206
  'wp-block-search__input',
207
+ hasNoButton ? colorProps.className : undefined,
226
208
  isButtonPositionInside ? undefined : borderProps.className,
227
209
  typographyProps.className
228
210
  );
229
211
  const textFieldStyles = {
212
+ ...( hasNoButton ? colorProps.style : {} ),
230
213
  ...( isButtonPositionInside
231
214
  ? {
232
215
  borderRadius: borderProps.style?.borderRadius,
@@ -292,14 +275,6 @@ export default function SearchEdit( {
292
275
  }
293
276
  : borderProps.style ),
294
277
  };
295
- const handleButtonClick = () => {
296
- if ( hasOnlyButton ) {
297
- setAttributes( {
298
- isSearchFieldHidden: ! isSearchFieldHidden,
299
- } );
300
- }
301
- };
302
-
303
278
  return (
304
279
  <>
305
280
  { buttonUseIcon && (
@@ -312,7 +287,6 @@ export default function SearchEdit( {
312
287
  ? stripHTML( buttonText )
313
288
  : __( 'Search' )
314
289
  }
315
- onClick={ handleButtonClick }
316
290
  ref={ buttonRef }
317
291
  >
318
292
  <Icon icon={ search } />
@@ -331,7 +305,6 @@ export default function SearchEdit( {
331
305
  onChange={ ( html ) =>
332
306
  setAttributes( { buttonText: html } )
333
307
  }
334
- onClick={ handleButtonClick }
335
308
  />
336
309
  ) }
337
310
  </>
@@ -351,7 +324,6 @@ export default function SearchEdit( {
351
324
  showLabel: true,
352
325
  buttonUseIcon: false,
353
326
  buttonPosition: 'button-outside',
354
- isSearchFieldHidden: false,
355
327
  } );
356
328
  } }
357
329
  dropdownMenuProps={ dropdownMenuProps }
@@ -382,7 +354,6 @@ export default function SearchEdit( {
382
354
  onDeselect={ () => {
383
355
  setAttributes( {
384
356
  buttonPosition: 'button-outside',
385
- isSearchFieldHidden: false,
386
357
  } );
387
358
  } }
388
359
  isShownByDefault
@@ -394,8 +365,6 @@ export default function SearchEdit( {
394
365
  onChange={ ( value ) => {
395
366
  setAttributes( {
396
367
  buttonPosition: value,
397
- isSearchFieldHidden:
398
- value === 'button-only',
399
368
  } );
400
369
  } }
401
370
  options={ buttonPositionControls }
@@ -69,6 +69,9 @@ function render_block_core_search( $attributes ) {
69
69
  if ( ! empty( $typography_classes ) ) {
70
70
  $input_classes[] = $typography_classes;
71
71
  }
72
+ if ( ! $show_button && ! empty( $color_classes ) ) {
73
+ $input_classes[] = $color_classes;
74
+ }
72
75
  if ( $input->next_tag() ) {
73
76
  $input->add_class( implode( ' ', $input_classes ) );
74
77
  $input->set_attribute( 'id', $input_id );
@@ -430,20 +433,37 @@ function styles_for_block_core_search( $attributes ) {
430
433
  }
431
434
  }
432
435
 
436
+ $use_input_for_colors = ! empty( $attributes['buttonPosition'] ) && 'no-button' === $attributes['buttonPosition'];
437
+
433
438
  // Add color styles.
434
439
  $has_text_color = ! empty( $attributes['style']['color']['text'] );
435
440
  if ( $has_text_color ) {
436
- $button_styles[] = sprintf( 'color: %s;', $attributes['style']['color']['text'] );
441
+ $text_color_style = sprintf( 'color: %s;', $attributes['style']['color']['text'] );
442
+ if ( $use_input_for_colors ) {
443
+ $input_styles[] = $text_color_style;
444
+ } else {
445
+ $button_styles[] = $text_color_style;
446
+ }
437
447
  }
438
448
 
439
449
  $has_background_color = ! empty( $attributes['style']['color']['background'] );
440
450
  if ( $has_background_color ) {
441
- $button_styles[] = sprintf( 'background-color: %s;', $attributes['style']['color']['background'] );
451
+ $background_color_style = sprintf( 'background-color: %s;', $attributes['style']['color']['background'] );
452
+ if ( $use_input_for_colors ) {
453
+ $input_styles[] = $background_color_style;
454
+ } else {
455
+ $button_styles[] = $background_color_style;
456
+ }
442
457
  }
443
458
 
444
459
  $has_custom_gradient = ! empty( $attributes['style']['color']['gradient'] );
445
460
  if ( $has_custom_gradient ) {
446
- $button_styles[] = sprintf( 'background: %s;', $attributes['style']['color']['gradient'] );
461
+ $custom_gradient_style = sprintf( 'background: %s;', $attributes['style']['color']['gradient'] );
462
+ if ( $use_input_for_colors ) {
463
+ $input_styles[] = $custom_gradient_style;
464
+ } else {
465
+ $button_styles[] = $custom_gradient_style;
466
+ }
447
467
  }
448
468
 
449
469
  // Get typography styles to be shared across inner elements.
@@ -1,17 +1,31 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { createBlock, getDefaultBlockName } from '@wordpress/blocks';
4
+ import {
5
+ createBlock,
6
+ getBlockVariations,
7
+ getDefaultBlockName,
8
+ } from '@wordpress/blocks';
5
9
 
6
10
  const transforms = {
7
11
  from: [
8
12
  {
9
13
  type: 'input',
10
14
  regExp: /^-{3,}$/,
11
- transform: () => [
12
- createBlock( 'core/separator' ),
13
- createBlock( getDefaultBlockName() ),
14
- ],
15
+ transform: () => {
16
+ // Check for default variation to apply default variation attributes.
17
+ const defaultVariation = getBlockVariations(
18
+ 'core/separator'
19
+ )?.find( ( variation ) => variation.isDefault );
20
+
21
+ return [
22
+ createBlock(
23
+ 'core/separator',
24
+ defaultVariation?.attributes ?? {}
25
+ ),
26
+ createBlock( getDefaultBlockName() ),
27
+ ];
28
+ },
15
29
  },
16
30
  {
17
31
  type: 'raw',
package/src/style.scss CHANGED
@@ -79,7 +79,6 @@
79
79
  @use "./table/style.scss" as *;
80
80
  @use "./table-of-contents/style.scss" as *;
81
81
  @use "./tabs/style.scss" as *;
82
- @use "./tabs-menu/style.scss" as *;
83
82
  @use "./tabs-menu-item/style.scss" as *;
84
83
  @use "./term-count/style.scss" as *;
85
84
  @use "./term-description/style.scss" as *;