@wordpress/block-library 9.30.0 → 9.30.1-next.836ecdcae.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 (75) hide show
  1. package/build/accordion-content/edit.js +8 -8
  2. package/build/accordion-content/edit.js.map +1 -1
  3. package/build/accordion-content/index.js +2 -1
  4. package/build/accordion-content/index.js.map +1 -1
  5. package/build/accordion-panel/index.js +2 -1
  6. package/build/accordion-panel/index.js.map +1 -1
  7. package/build/navigation/constants.js +5 -1
  8. package/build/navigation/constants.js.map +1 -1
  9. package/build/navigation/edit/index.js +45 -1
  10. package/build/navigation/edit/index.js.map +1 -1
  11. package/build/navigation/edit/leaf-more-menu.js +0 -1
  12. package/build/navigation/edit/leaf-more-menu.js.map +1 -1
  13. package/build/navigation/edit/menu-inspector-controls.js +40 -5
  14. package/build/navigation/edit/menu-inspector-controls.js.map +1 -1
  15. package/build/navigation-link/link-ui.js +64 -56
  16. package/build/navigation-link/link-ui.js.map +1 -1
  17. package/build/navigation-link/page-creator.js +143 -0
  18. package/build/navigation-link/page-creator.js.map +1 -0
  19. package/build/search/edit.js +22 -14
  20. package/build/search/edit.js.map +1 -1
  21. package/build-module/accordion-content/edit.js +8 -8
  22. package/build-module/accordion-content/edit.js.map +1 -1
  23. package/build-module/accordion-content/index.js +2 -1
  24. package/build-module/accordion-content/index.js.map +1 -1
  25. package/build-module/accordion-panel/index.js +2 -1
  26. package/build-module/accordion-panel/index.js.map +1 -1
  27. package/build-module/navigation/constants.js +5 -1
  28. package/build-module/navigation/constants.js.map +1 -1
  29. package/build-module/navigation/edit/index.js +50 -4
  30. package/build-module/navigation/edit/index.js.map +1 -1
  31. package/build-module/navigation/edit/leaf-more-menu.js +0 -1
  32. package/build-module/navigation/edit/leaf-more-menu.js.map +1 -1
  33. package/build-module/navigation/edit/menu-inspector-controls.js +40 -5
  34. package/build-module/navigation/edit/menu-inspector-controls.js.map +1 -1
  35. package/build-module/navigation-link/link-ui.js +68 -60
  36. package/build-module/navigation-link/link-ui.js.map +1 -1
  37. package/build-module/navigation-link/page-creator.js +137 -0
  38. package/build-module/navigation-link/page-creator.js.map +1 -0
  39. package/build-module/search/edit.js +22 -14
  40. package/build-module/search/edit.js.map +1 -1
  41. package/build-style/accordion/style-rtl.css +5 -6
  42. package/build-style/accordion/style.css +5 -6
  43. package/build-style/editor-rtl.css +14 -0
  44. package/build-style/editor.css +14 -0
  45. package/build-style/form-input/style-rtl.css +4 -3
  46. package/build-style/form-input/style.css +4 -3
  47. package/build-style/navigation-link/editor-rtl.css +14 -0
  48. package/build-style/navigation-link/editor.css +14 -0
  49. package/build-style/navigation-link/style-rtl.css +1 -1
  50. package/build-style/navigation-link/style.css +1 -1
  51. package/build-style/post-comments-form/style-rtl.css +8 -5
  52. package/build-style/post-comments-form/style.css +8 -5
  53. package/build-style/search/style-rtl.css +11 -12
  54. package/build-style/search/style.css +11 -12
  55. package/build-style/style-rtl.css +29 -27
  56. package/build-style/style.css +29 -27
  57. package/package.json +35 -35
  58. package/src/accordion/style.scss +6 -6
  59. package/src/accordion-content/block.json +2 -1
  60. package/src/accordion-content/edit.js +21 -27
  61. package/src/accordion-panel/block.json +2 -1
  62. package/src/cover/test/edit.js +1 -5
  63. package/src/form-input/style.scss +3 -2
  64. package/src/navigation/constants.js +4 -0
  65. package/src/navigation/edit/index.js +50 -1
  66. package/src/navigation/edit/leaf-more-menu.js +0 -1
  67. package/src/navigation/edit/menu-inspector-controls.js +40 -5
  68. package/src/navigation-link/editor.scss +17 -0
  69. package/src/navigation-link/link-ui.js +88 -81
  70. package/src/navigation-link/page-creator.js +164 -0
  71. package/src/navigation-link/style.scss +1 -1
  72. package/src/post-comments-form/style.scss +11 -11
  73. package/src/search/edit.js +44 -13
  74. package/src/search/index.php +16 -2
  75. package/src/search/style.scss +15 -16
@@ -8,7 +8,7 @@ import {
8
8
  VisuallyHidden,
9
9
  __experimentalVStack as VStack,
10
10
  } from '@wordpress/components';
11
- import { __, sprintf, isRTL } from '@wordpress/i18n';
11
+ import { __, isRTL } from '@wordpress/i18n';
12
12
  import {
13
13
  LinkControl,
14
14
  store as blockEditorStore,
@@ -16,19 +16,14 @@ import {
16
16
  useBlockEditingMode,
17
17
  } from '@wordpress/block-editor';
18
18
  import {
19
- createInterpolateElement,
20
19
  useMemo,
21
20
  useState,
22
21
  useRef,
23
22
  useEffect,
24
23
  forwardRef,
25
24
  } from '@wordpress/element';
26
- import {
27
- store as coreStore,
28
- useResourcePermissions,
29
- } from '@wordpress/core-data';
30
- import { decodeEntities } from '@wordpress/html-entities';
31
- import { useSelect, useDispatch } from '@wordpress/data';
25
+ import { useResourcePermissions } from '@wordpress/core-data';
26
+ import { useSelect } from '@wordpress/data';
32
27
  import { chevronLeftSmall, chevronRightSmall, plus } from '@wordpress/icons';
33
28
  import { useInstanceId, useFocusOnMount } from '@wordpress/compose';
34
29
 
@@ -36,6 +31,7 @@ import { useInstanceId, useFocusOnMount } from '@wordpress/compose';
36
31
  * Internal dependencies
37
32
  */
38
33
  import { unlock } from '../lock-unlock';
34
+ import { LinkUIPageCreator } from './page-creator';
39
35
 
40
36
  const { PrivateQuickInserter: QuickInserter } = unlock(
41
37
  blockEditorPrivateApis
@@ -79,7 +75,7 @@ export function getSuggestionsQuery( type, kind ) {
79
75
  }
80
76
  }
81
77
 
82
- function LinkUIBlockInserter( { clientId, onBack } ) {
78
+ function LinkUIBlockInserter( { clientId, onBack, onBlockInsert } ) {
83
79
  const { rootBlockClientId } = useSelect(
84
80
  ( select ) => {
85
81
  const { getBlockRootClientId } = select( blockEditorStore );
@@ -139,7 +135,8 @@ function LinkUIBlockInserter( { clientId, onBack } ) {
139
135
  clientId={ clientId }
140
136
  isAppender={ false }
141
137
  prioritizePatterns={ false }
142
- selectBlockOnInsert
138
+ selectBlockOnInsert={ ! onBlockInsert }
139
+ onSelect={ onBlockInsert ? onBlockInsert : undefined }
143
140
  hasSearch={ false }
144
141
  />
145
142
  </div>
@@ -151,42 +148,14 @@ function UnforwardedLinkUI( props, ref ) {
151
148
  const postType = type || 'page';
152
149
 
153
150
  const [ addingBlock, setAddingBlock ] = useState( false );
151
+ const [ addingPage, setAddingPage ] = useState( false );
154
152
  const [ focusAddBlockButton, setFocusAddBlockButton ] = useState( false );
155
- const { saveEntityRecord } = useDispatch( coreStore );
153
+ const [ focusAddPageButton, setFocusAddPageButton ] = useState( false );
156
154
  const permissions = useResourcePermissions( {
157
155
  kind: 'postType',
158
156
  name: postType,
159
157
  } );
160
158
 
161
- // Check if we're in contentOnly mode
162
- const blockEditingMode = useBlockEditingMode();
163
- const isDefaultBlockEditingMode = blockEditingMode === 'default';
164
-
165
- async function handleCreate( pageTitle ) {
166
- const page = await saveEntityRecord( 'postType', postType, {
167
- title: pageTitle,
168
- status: 'draft',
169
- } );
170
-
171
- return {
172
- id: page.id,
173
- type: postType,
174
- // Make `title` property consistent with that in `fetchLinkSuggestions` where the `rendered` title (containing HTML entities)
175
- // is also being decoded. By being consistent in both locations we avoid having to branch in the rendering output code.
176
- // Ideally in the future we will update both APIs to utilise the "raw" form of the title which is better suited to edit contexts.
177
- // e.g.
178
- // - title.raw = "Yes & No"
179
- // - title.rendered = "Yes &#038; No"
180
- // - decodeEntities( title.rendered ) = "Yes & No"
181
- // See:
182
- // - https://github.com/WordPress/gutenberg/pull/41063
183
- // - https://github.com/WordPress/gutenberg/blob/a1e1fdc0e6278457e9f4fc0b31ac6d2095f5450b/packages/core-data/src/fetch/__experimental-fetch-link-suggestions.js#L212-L218
184
- title: decodeEntities( page.title.rendered ),
185
- url: page.link,
186
- kind: 'post-type',
187
- };
188
- }
189
-
190
159
  // Memoize link value to avoid overriding the LinkControl's internal state.
191
160
  // This is a temporary fix. See https://github.com/WordPress/gutenberg/issues/50976#issuecomment-1568226407.
192
161
  const link = useMemo(
@@ -198,6 +167,13 @@ function UnforwardedLinkUI( props, ref ) {
198
167
  [ label, opensInNewTab, url ]
199
168
  );
200
169
 
170
+ const handlePageCreated = ( pageLink ) => {
171
+ // Set the new page as the current link
172
+ props.onChange( pageLink );
173
+ // Return to main Link UI
174
+ setAddingPage( false );
175
+ };
176
+
201
177
  const dialogTitleId = useInstanceId(
202
178
  LinkUI,
203
179
  `link-ui-link-control__title`
@@ -207,6 +183,8 @@ function UnforwardedLinkUI( props, ref ) {
207
183
  `link-ui-link-control__description`
208
184
  );
209
185
 
186
+ const blockEditingMode = useBlockEditingMode();
187
+
210
188
  return (
211
189
  <Popover
212
190
  ref={ ref }
@@ -215,7 +193,7 @@ function UnforwardedLinkUI( props, ref ) {
215
193
  anchor={ props.anchor }
216
194
  shift
217
195
  >
218
- { ! addingBlock && (
196
+ { ! addingBlock && ! addingPage && (
219
197
  <div
220
198
  role="dialog"
221
199
  aria-labelledby={ dialogTitleId }
@@ -235,30 +213,7 @@ function UnforwardedLinkUI( props, ref ) {
235
213
  hasRichPreviews
236
214
  value={ link }
237
215
  showInitialSuggestions
238
- withCreateSuggestion={ permissions.canCreate }
239
- createSuggestion={ handleCreate }
240
- createSuggestionButtonText={ ( searchTerm ) => {
241
- let format;
242
-
243
- if ( type === 'post' ) {
244
- /* translators: %s: search term. */
245
- format = __(
246
- 'Create draft post: <mark>%s</mark>'
247
- );
248
- } else {
249
- /* translators: %s: search term. */
250
- format = __(
251
- 'Create draft page: <mark>%s</mark>'
252
- );
253
- }
254
-
255
- return createInterpolateElement(
256
- sprintf( format, searchTerm ),
257
- {
258
- mark: <mark />,
259
- }
260
- );
261
- } }
216
+ withCreateSuggestion={ false }
262
217
  noDirectEntry={ !! type }
263
218
  noURLSuggestion={ !! type }
264
219
  suggestionsQuery={ getSuggestionsQuery( type, kind ) }
@@ -266,14 +221,20 @@ function UnforwardedLinkUI( props, ref ) {
266
221
  onRemove={ props.onRemove }
267
222
  onCancel={ props.onCancel }
268
223
  renderControlBottom={ () =>
269
- ! link?.url?.length &&
270
- isDefaultBlockEditingMode && (
224
+ ! link?.url?.length && (
271
225
  <LinkUITools
272
226
  focusAddBlockButton={ focusAddBlockButton }
227
+ focusAddPageButton={ focusAddPageButton }
273
228
  setAddingBlock={ () => {
274
229
  setAddingBlock( true );
275
230
  setFocusAddBlockButton( false );
276
231
  } }
232
+ setAddingPage={ () => {
233
+ setAddingPage( true );
234
+ setFocusAddPageButton( false );
235
+ } }
236
+ canCreatePage={ permissions.canCreate }
237
+ blockEditingMode={ blockEditingMode }
277
238
  />
278
239
  )
279
240
  }
@@ -287,7 +248,22 @@ function UnforwardedLinkUI( props, ref ) {
287
248
  onBack={ () => {
288
249
  setAddingBlock( false );
289
250
  setFocusAddBlockButton( true );
251
+ setFocusAddPageButton( false );
252
+ } }
253
+ onBlockInsert={ props?.onBlockInsert }
254
+ />
255
+ ) }
256
+
257
+ { addingPage && (
258
+ <LinkUIPageCreator
259
+ postType={ postType }
260
+ onBack={ () => {
261
+ setAddingPage( false );
262
+ setFocusAddPageButton( true );
263
+ setFocusAddBlockButton( false );
290
264
  } }
265
+ onPageCreated={ handlePageCreated }
266
+ initialTitle={ link?.url || '' }
291
267
  />
292
268
  ) }
293
269
  </Popover>
@@ -296,9 +272,17 @@ function UnforwardedLinkUI( props, ref ) {
296
272
 
297
273
  export const LinkUI = forwardRef( UnforwardedLinkUI );
298
274
 
299
- const LinkUITools = ( { setAddingBlock, focusAddBlockButton } ) => {
275
+ const LinkUITools = ( {
276
+ setAddingBlock,
277
+ setAddingPage,
278
+ focusAddBlockButton,
279
+ focusAddPageButton,
280
+ canCreatePage,
281
+ blockEditingMode,
282
+ } ) => {
300
283
  const blockInserterAriaRole = 'listbox';
301
284
  const addBlockButtonRef = useRef();
285
+ const addPageButtonRef = useRef();
302
286
 
303
287
  // Focus the add block button when the popover is opened.
304
288
  useEffect( () => {
@@ -307,20 +291,43 @@ const LinkUITools = ( { setAddingBlock, focusAddBlockButton } ) => {
307
291
  }
308
292
  }, [ focusAddBlockButton ] );
309
293
 
294
+ // Focus the add page button when the popover is opened.
295
+ useEffect( () => {
296
+ if ( focusAddPageButton ) {
297
+ addPageButtonRef.current?.focus();
298
+ }
299
+ }, [ focusAddPageButton ] );
300
+
310
301
  return (
311
- <VStack className="link-ui-tools">
312
- <Button
313
- __next40pxDefaultSize
314
- ref={ addBlockButtonRef }
315
- icon={ plus }
316
- onClick={ ( e ) => {
317
- e.preventDefault();
318
- setAddingBlock( true );
319
- } }
320
- aria-haspopup={ blockInserterAriaRole }
321
- >
322
- { __( 'Add block' ) }
323
- </Button>
302
+ <VStack spacing={ 0 } className="link-ui-tools">
303
+ { canCreatePage && (
304
+ <Button
305
+ __next40pxDefaultSize
306
+ ref={ addPageButtonRef }
307
+ icon={ plus }
308
+ onClick={ ( e ) => {
309
+ e.preventDefault();
310
+ setAddingPage( true );
311
+ } }
312
+ aria-haspopup={ blockInserterAriaRole }
313
+ >
314
+ { __( 'Create page' ) }
315
+ </Button>
316
+ ) }
317
+ { blockEditingMode === 'default' && (
318
+ <Button
319
+ __next40pxDefaultSize
320
+ ref={ addBlockButtonRef }
321
+ icon={ plus }
322
+ onClick={ ( e ) => {
323
+ e.preventDefault();
324
+ setAddingBlock( true );
325
+ } }
326
+ aria-haspopup={ blockInserterAriaRole }
327
+ >
328
+ { __( 'Add block' ) }
329
+ </Button>
330
+ ) }
324
331
  </VStack>
325
332
  );
326
333
  };
@@ -0,0 +1,164 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import {
5
+ Button,
6
+ TextControl,
7
+ Notice,
8
+ CheckboxControl,
9
+ __experimentalVStack as VStack,
10
+ __experimentalHStack as HStack,
11
+ } from '@wordpress/components';
12
+ import { __, isRTL } from '@wordpress/i18n';
13
+ import { useSelect, useDispatch } from '@wordpress/data';
14
+ import { store as coreStore } from '@wordpress/core-data';
15
+ import { decodeEntities } from '@wordpress/html-entities';
16
+ import { useState } from '@wordpress/element';
17
+ import { chevronLeftSmall, chevronRightSmall } from '@wordpress/icons';
18
+ import { useFocusOnMount } from '@wordpress/compose';
19
+
20
+ /**
21
+ * Component for creating new pages within the Navigation Link UI.
22
+ *
23
+ * @param {Object} props Component props.
24
+ * @param {string} props.postType The post type to create.
25
+ * @param {Function} props.onBack Callback when user wants to go back.
26
+ * @param {Function} props.onPageCreated Callback when page is successfully created.
27
+ * @param {string} [props.initialTitle] Initial title to pre-fill the form.
28
+ */
29
+ export function LinkUIPageCreator( {
30
+ postType,
31
+ onBack,
32
+ onPageCreated,
33
+ initialTitle = '',
34
+ } ) {
35
+ const [ title, setTitle ] = useState( initialTitle );
36
+ const [ shouldPublish, setShouldPublish ] = useState( false );
37
+
38
+ // Focus the first element when the component mounts
39
+ const focusOnMountRef = useFocusOnMount( 'firstElement' );
40
+
41
+ // Check if the title is valid for submission
42
+ const isTitleValid = title.trim().length > 0;
43
+
44
+ // Get the last created entity record (without ID) to track creation state
45
+ const { lastError, isSaving } = useSelect(
46
+ ( select ) => ( {
47
+ lastError: select( coreStore ).getLastEntitySaveError(
48
+ 'postType',
49
+ postType
50
+ ),
51
+ isSaving: select( coreStore ).isSavingEntityRecord(
52
+ 'postType',
53
+ postType
54
+ ),
55
+ } ),
56
+ [ postType ]
57
+ );
58
+
59
+ const { saveEntityRecord } = useDispatch( coreStore );
60
+
61
+ async function createPage( event ) {
62
+ event.preventDefault();
63
+ if ( isSaving || ! isTitleValid ) {
64
+ return;
65
+ }
66
+
67
+ try {
68
+ const savedRecord = await saveEntityRecord(
69
+ 'postType',
70
+ postType,
71
+ {
72
+ title,
73
+ status: shouldPublish ? 'publish' : 'draft',
74
+ },
75
+ { throwOnError: true }
76
+ );
77
+
78
+ if ( savedRecord ) {
79
+ // Create the page link object from the saved record
80
+ const pageLink = {
81
+ id: savedRecord.id,
82
+ type: postType,
83
+ title: decodeEntities( savedRecord.title.rendered ),
84
+ url: savedRecord.link,
85
+ kind: 'post-type',
86
+ };
87
+
88
+ onPageCreated( pageLink );
89
+ }
90
+ } catch ( error ) {
91
+ // Error handling is done via the data store selectors
92
+ }
93
+ }
94
+
95
+ const isSubmitDisabled = isSaving || ! isTitleValid;
96
+
97
+ return (
98
+ <div className="link-ui-page-creator" ref={ focusOnMountRef }>
99
+ <Button
100
+ className="link-ui-page-creator__back"
101
+ icon={ isRTL() ? chevronRightSmall : chevronLeftSmall }
102
+ onClick={ ( e ) => {
103
+ e.preventDefault();
104
+ onBack();
105
+ } }
106
+ size="small"
107
+ >
108
+ { __( 'Back' ) }
109
+ </Button>
110
+
111
+ <VStack className="link-ui-page-creator__inner" spacing={ 4 }>
112
+ <form onSubmit={ createPage }>
113
+ <VStack spacing={ 4 }>
114
+ <TextControl
115
+ __next40pxDefaultSize
116
+ __nextHasNoMarginBottom
117
+ label={ __( 'Title' ) }
118
+ onChange={ setTitle }
119
+ placeholder={ __( 'No title' ) }
120
+ value={ title }
121
+ />
122
+
123
+ <CheckboxControl
124
+ __nextHasNoMarginBottom
125
+ label={ __( 'Publish immediately' ) }
126
+ help={ __(
127
+ 'If unchecked, the page will be created as a draft.'
128
+ ) }
129
+ checked={ shouldPublish }
130
+ onChange={ setShouldPublish }
131
+ />
132
+
133
+ { lastError && (
134
+ <Notice status="error" isDismissible={ false }>
135
+ { lastError.message }
136
+ </Notice>
137
+ ) }
138
+
139
+ <HStack spacing={ 2 } justify="flex-end">
140
+ <Button
141
+ __next40pxDefaultSize
142
+ variant="tertiary"
143
+ onClick={ onBack }
144
+ disabled={ isSaving }
145
+ accessibleWhenDisabled
146
+ >
147
+ { __( 'Cancel' ) }
148
+ </Button>
149
+ <Button
150
+ __next40pxDefaultSize
151
+ variant="primary"
152
+ type="submit"
153
+ isBusy={ isSaving }
154
+ aria-disabled={ isSubmitDisabled }
155
+ >
156
+ { __( 'Create page' ) }
157
+ </Button>
158
+ </HStack>
159
+ </VStack>
160
+ </form>
161
+ </VStack>
162
+ </div>
163
+ );
164
+ }
@@ -16,7 +16,7 @@
16
16
  }
17
17
 
18
18
  .link-ui-tools {
19
- border-top: 1px solid $gray-100;
19
+ outline: 1px solid $gray-100;
20
20
  padding: $grid-unit-10;
21
21
  }
22
22
 
@@ -1,16 +1,16 @@
1
1
  // Allow these default styles to be overridden by global styles.
2
- :where(.wp-block-post-comments-form) {
3
- textarea,
4
- input:not([type="submit"]) {
5
- border: 1px solid $gray-600;
6
- font-size: 1em;
7
- font-family: inherit;
8
- }
2
+ :where(.wp-block-post-comments-form textarea),
3
+ :where(.wp-block-post-comments-form input:not([type="submit"])) {
4
+ border-width: 1px;
5
+ border-style: solid;
6
+ border-color: $gray-600;
7
+ font-size: 1em;
8
+ font-family: inherit;
9
+ }
9
10
 
10
- textarea,
11
- input:where(:not([type="submit"]):not([type="checkbox"])) {
12
- padding: calc(0.667em + 2px); // The extra 2px is added to match outline buttons.
13
- }
11
+ :where(.wp-block-post-comments-form textarea),
12
+ :where(.wp-block-post-comments-form input:where(:not([type="submit"]):not([type="checkbox"]))) {
13
+ padding: calc(0.667em + 2px); // The extra 2px is added to match outline buttons.
14
14
  }
15
15
 
16
16
  .wp-block-post-comments-form {
@@ -228,7 +228,17 @@ export default function SearchEdit( {
228
228
  );
229
229
  const textFieldStyles = {
230
230
  ...( isButtonPositionInside
231
- ? { borderRadius }
231
+ ? {
232
+ borderRadius: borderProps.style?.borderRadius,
233
+ borderTopLeftRadius:
234
+ borderProps.style?.borderTopLeftRadius,
235
+ borderTopRightRadius:
236
+ borderProps.style?.borderTopRightRadius,
237
+ borderBottomLeftRadius:
238
+ borderProps.style?.borderBottomLeftRadius,
239
+ borderBottomRightRadius:
240
+ borderProps.style?.borderBottomRightRadius,
241
+ }
232
242
  : borderProps.style ),
233
243
  ...typographyProps.style,
234
244
  textDecoration: undefined,
@@ -269,7 +279,17 @@ export default function SearchEdit( {
269
279
  ...colorProps.style,
270
280
  ...typographyProps.style,
271
281
  ...( isButtonPositionInside
272
- ? { borderRadius }
282
+ ? {
283
+ borderRadius: borderProps.style?.borderRadius,
284
+ borderTopLeftRadius:
285
+ borderProps.style?.borderTopLeftRadius,
286
+ borderTopRightRadius:
287
+ borderProps.style?.borderTopRightRadius,
288
+ borderBottomLeftRadius:
289
+ borderProps.style?.borderBottomLeftRadius,
290
+ borderBottomRightRadius:
291
+ borderProps.style?.borderBottomRightRadius,
292
+ }
273
293
  : borderProps.style ),
274
294
  };
275
295
  const handleButtonClick = () => {
@@ -495,8 +515,13 @@ export default function SearchEdit( {
495
515
  </>
496
516
  );
497
517
 
518
+ const isNonZeroBorderRadius = ( radius ) =>
519
+ radius !== undefined && parseInt( radius, 10 ) !== 0;
520
+
498
521
  const padBorderRadius = ( radius ) =>
499
- radius ? `calc(${ radius } + ${ DEFAULT_INNER_PADDING })` : undefined;
522
+ isNonZeroBorderRadius( radius )
523
+ ? `calc(${ radius } + ${ DEFAULT_INNER_PADDING })`
524
+ : undefined;
500
525
 
501
526
  const getWrapperStyles = () => {
502
527
  const styles = isButtonPositionInside
@@ -512,10 +537,7 @@ export default function SearchEdit( {
512
537
  borderProps.style?.borderBottomRightRadius,
513
538
  };
514
539
 
515
- const isNonZeroBorderRadius =
516
- borderRadius !== undefined && parseInt( borderRadius, 10 ) !== 0;
517
-
518
- if ( isButtonPositionInside && isNonZeroBorderRadius ) {
540
+ if ( isButtonPositionInside ) {
519
541
  // We have button inside wrapper and a border radius value to apply.
520
542
  // Add default padding so we don't get "fat" corners.
521
543
  //
@@ -524,15 +546,24 @@ export default function SearchEdit( {
524
546
 
525
547
  if ( typeof borderRadius === 'object' ) {
526
548
  // Individual corner border radii present.
527
- const { topLeft, topRight, bottomLeft, bottomRight } =
528
- borderRadius;
549
+ const {
550
+ borderTopLeftRadius,
551
+ borderTopRightRadius,
552
+ borderBottomLeftRadius,
553
+ borderBottomRightRadius,
554
+ } = borderProps.style;
529
555
 
530
556
  return {
531
557
  ...styles,
532
- borderTopLeftRadius: padBorderRadius( topLeft ),
533
- borderTopRightRadius: padBorderRadius( topRight ),
534
- borderBottomLeftRadius: padBorderRadius( bottomLeft ),
535
- borderBottomRightRadius: padBorderRadius( bottomRight ),
558
+ borderTopLeftRadius: padBorderRadius( borderTopLeftRadius ),
559
+ borderTopRightRadius:
560
+ padBorderRadius( borderTopRightRadius ),
561
+ borderBottomLeftRadius: padBorderRadius(
562
+ borderBottomLeftRadius
563
+ ),
564
+ borderBottomRightRadius: padBorderRadius(
565
+ borderBottomRightRadius
566
+ ),
536
567
  };
537
568
  }
538
569
 
@@ -372,6 +372,13 @@ function styles_for_block_core_search( $attributes ) {
372
372
  if ( is_array( $border_radius ) ) {
373
373
  // Apply styles for individual corner border radii.
374
374
  foreach ( $border_radius as $key => $value ) {
375
+ // Get border-radius CSS variable from preset value if provided.
376
+ if ( is_string( $value ) && str_contains( $value, 'var:preset|border-radius|' ) ) {
377
+ $index_to_splice = strrpos( $value, '|' ) + 1;
378
+ $slug = _wp_to_kebab_case( substr( $value, $index_to_splice ) );
379
+ $value = "var(--wp--preset--border-radius--$slug)";
380
+ }
381
+
375
382
  if ( null !== $value ) {
376
383
  // Convert camelCase key to kebab-case.
377
384
  $name = strtolower( preg_replace( '/(?<!^)[A-Z]/', '-$0', $key ) );
@@ -387,7 +394,7 @@ function styles_for_block_core_search( $attributes ) {
387
394
 
388
395
  // Add adjusted border radius styles for the wrapper element
389
396
  // if button is positioned inside.
390
- if ( $is_button_inside && intval( $value ) !== 0 ) {
397
+ if ( $is_button_inside && ( intval( $value ) !== 0 || str_contains( $value, 'var(--wp--preset--border-radius--' ) ) ) {
391
398
  $wrapper_styles[] = sprintf(
392
399
  'border-%s-radius: calc(%s + %s);',
393
400
  esc_attr( $name ),
@@ -399,7 +406,14 @@ function styles_for_block_core_search( $attributes ) {
399
406
  }
400
407
  } else {
401
408
  // Numeric check is for backwards compatibility purposes.
402
- $border_radius = is_numeric( $border_radius ) ? $border_radius . 'px' : $border_radius;
409
+ $border_radius = is_numeric( $border_radius ) ? $border_radius . 'px' : $border_radius;
410
+ // Get border-radius CSS variable from preset value if provided.
411
+ if ( is_string( $border_radius ) && str_contains( $border_radius, 'var:preset|border-radius|' ) ) {
412
+ $index_to_splice = strrpos( $border_radius, '|' ) + 1;
413
+ $slug = _wp_to_kebab_case( substr( $border_radius, $index_to_splice ) );
414
+ $border_radius = "var(--wp--preset--border-radius--$slug)";
415
+ }
416
+
403
417
  $border_style = sprintf( 'border-radius: %s;', esc_attr( $border_radius ) );
404
418
  $input_styles[] = $border_style;
405
419
  $button_styles[] = $border_style;
@@ -37,21 +37,6 @@ $button-spacing-y: math.div($grid-unit-15, 2); // 6px
37
37
  width: 100%;
38
38
  }
39
39
 
40
- .wp-block-search__input {
41
- padding: $grid-unit-10;
42
- flex-grow: 1;
43
- margin-left: 0;
44
- margin-right: 0;
45
- min-width: 3rem;
46
- border: 1px solid $gray-600;
47
- // !important used to forcibly prevent undesired application of
48
- // text-decoration styles on the input field.
49
- text-decoration: unset !important;
50
-
51
- // Hides a redundant extra search icon on Mobile Safari.
52
- appearance: initial;
53
- }
54
-
55
40
  .wp-block-search.wp-block-search__button-only {
56
41
  .wp-block-search__button {
57
42
  margin-left: 0;
@@ -104,12 +89,26 @@ $button-spacing-y: math.div($grid-unit-15, 2); // 6px
104
89
  letter-spacing: inherit;
105
90
  text-transform: inherit;
106
91
  font-style: inherit;
92
+ padding: $grid-unit-10;
93
+ flex-grow: 1;
94
+ margin-left: 0;
95
+ margin-right: 0;
96
+ min-width: 3rem;
97
+ border: 1px solid $gray-600;
98
+ // !important used to forcibly prevent undesired application of
99
+ // text-decoration styles on the input field.
100
+ text-decoration: unset !important;
101
+
102
+ // Hides a redundant extra search icon on Mobile Safari.
103
+ appearance: initial;
107
104
  }
108
105
 
109
106
  // We are lowering the specificity so that the button element can override the rule for the button inside the search block.
110
107
  :where(.wp-block-search__button-inside .wp-block-search__inside-wrapper) {
111
108
  padding: $grid-unit-05;
112
- border: 1px solid $gray-600;
109
+ border-width: 1px;
110
+ border-style: solid;
111
+ border-color: $gray-600;
113
112
  background-color: $white;
114
113
  box-sizing: border-box;
115
114