@wordpress/block-library 9.26.1-next.719a03cbe.0 → 9.27.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 (110) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/cover/edit/block-controls.js +4 -2
  3. package/build/cover/edit/block-controls.js.map +1 -1
  4. package/build/cover/edit/index.js +6 -3
  5. package/build/cover/edit/index.js.map +1 -1
  6. package/build/cover/edit/inspector-controls.js +11 -4
  7. package/build/cover/edit/inspector-controls.js.map +1 -1
  8. package/build/cover/edit/poster-image.js +81 -0
  9. package/build/cover/edit/poster-image.js.map +1 -0
  10. package/build/cover/index.js +6 -0
  11. package/build/cover/index.js.map +1 -1
  12. package/build/cover/save.js +3 -1
  13. package/build/cover/save.js.map +1 -1
  14. package/build/media-text/edit.js +2 -2
  15. package/build/media-text/edit.js.map +1 -1
  16. package/build/navigation-link/edit.js +32 -15
  17. package/build/navigation-link/edit.js.map +1 -1
  18. package/build/navigation-link/update-attributes.js +112 -14
  19. package/build/navigation-link/update-attributes.js.map +1 -1
  20. package/build/navigation-submenu/edit.js +19 -2
  21. package/build/navigation-submenu/edit.js.map +1 -1
  22. package/build/post-content/edit.js +78 -16
  23. package/build/post-content/edit.js.map +1 -1
  24. package/build/post-content/index.js +6 -0
  25. package/build/post-content/index.js.map +1 -1
  26. package/build/separator/edit.js +5 -30
  27. package/build/separator/edit.js.map +1 -1
  28. package/build/site-tagline/index.js +1 -1
  29. package/build/video/edit.js +2 -5
  30. package/build/video/edit.js.map +1 -1
  31. package/build/video/poster-image.js +25 -25
  32. package/build/video/poster-image.js.map +1 -1
  33. package/build/video/tracks-editor.js +95 -104
  34. package/build/video/tracks-editor.js.map +1 -1
  35. package/build/video/tracks.js +6 -2
  36. package/build/video/tracks.js.map +1 -1
  37. package/build-module/cover/edit/block-controls.js +4 -2
  38. package/build-module/cover/edit/block-controls.js.map +1 -1
  39. package/build-module/cover/edit/index.js +6 -3
  40. package/build-module/cover/edit/index.js.map +1 -1
  41. package/build-module/cover/edit/inspector-controls.js +10 -4
  42. package/build-module/cover/edit/inspector-controls.js.map +1 -1
  43. package/build-module/cover/edit/poster-image.js +74 -0
  44. package/build-module/cover/edit/poster-image.js.map +1 -0
  45. package/build-module/cover/index.js +6 -0
  46. package/build-module/cover/index.js.map +1 -1
  47. package/build-module/cover/save.js +3 -1
  48. package/build-module/cover/save.js.map +1 -1
  49. package/build-module/media-text/edit.js +2 -2
  50. package/build-module/media-text/edit.js.map +1 -1
  51. package/build-module/navigation-link/edit.js +32 -15
  52. package/build-module/navigation-link/edit.js.map +1 -1
  53. package/build-module/navigation-link/update-attributes.js +113 -15
  54. package/build-module/navigation-link/update-attributes.js.map +1 -1
  55. package/build-module/navigation-submenu/edit.js +20 -3
  56. package/build-module/navigation-submenu/edit.js.map +1 -1
  57. package/build-module/post-content/edit.js +80 -18
  58. package/build-module/post-content/edit.js.map +1 -1
  59. package/build-module/post-content/index.js +6 -0
  60. package/build-module/post-content/index.js.map +1 -1
  61. package/build-module/separator/edit.js +6 -31
  62. package/build-module/separator/edit.js.map +1 -1
  63. package/build-module/site-tagline/index.js +1 -1
  64. package/build-module/video/edit.js +2 -5
  65. package/build-module/video/edit.js.map +1 -1
  66. package/build-module/video/poster-image.js +26 -26
  67. package/build-module/video/poster-image.js.map +1 -1
  68. package/build-module/video/tracks-editor.js +96 -105
  69. package/build-module/video/tracks-editor.js.map +1 -1
  70. package/build-module/video/tracks.js +6 -2
  71. package/build-module/video/tracks.js.map +1 -1
  72. package/build-style/archives/editor-rtl.css +0 -4
  73. package/build-style/archives/editor.css +0 -4
  74. package/build-style/editor-rtl.css +0 -8
  75. package/build-style/editor.css +0 -8
  76. package/build-style/file/style-rtl.css +1 -1
  77. package/build-style/file/style.css +1 -1
  78. package/build-style/navigation/style-rtl.css +1 -0
  79. package/build-style/navigation/style.css +1 -0
  80. package/build-style/style-rtl.css +2 -1
  81. package/build-style/style.css +2 -1
  82. package/build-style/video/editor-rtl.css +0 -4
  83. package/build-style/video/editor.css +0 -4
  84. package/package.json +35 -35
  85. package/src/archives/editor.scss +0 -4
  86. package/src/comments-pagination/index.php +7 -2
  87. package/src/cover/block.json +6 -0
  88. package/src/cover/edit/block-controls.js +22 -17
  89. package/src/cover/edit/index.js +4 -1
  90. package/src/cover/edit/inspector-controls.js +11 -2
  91. package/src/cover/edit/poster-image.js +91 -0
  92. package/src/cover/save.js +2 -0
  93. package/src/file/style.scss +1 -1
  94. package/src/media-text/edit.js +1 -1
  95. package/src/navigation/style.scss +1 -0
  96. package/src/navigation-link/edit.js +28 -16
  97. package/src/navigation-link/test/edit.js +738 -6
  98. package/src/navigation-link/update-attributes.js +125 -12
  99. package/src/navigation-submenu/edit.js +21 -1
  100. package/src/post-content/block.json +6 -0
  101. package/src/post-content/edit.js +71 -19
  102. package/src/post-content/index.php +11 -4
  103. package/src/post-featured-image/index.php +3 -2
  104. package/src/separator/edit.js +8 -43
  105. package/src/site-tagline/block.json +1 -1
  106. package/src/video/edit.js +1 -4
  107. package/src/video/editor.scss +0 -6
  108. package/src/video/poster-image.js +29 -24
  109. package/src/video/tracks-editor.js +93 -103
  110. package/src/video/tracks.js +2 -1
@@ -2,7 +2,89 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { escapeHTML } from '@wordpress/escape-html';
5
- import { safeDecodeURI } from '@wordpress/url';
5
+ import { safeDecodeURI, getPath } from '@wordpress/url';
6
+
7
+ /**
8
+ * Determines if an entity link should be severed based on URL changes.
9
+ *
10
+ * @param {string} originalUrl - The original URL
11
+ * @param {string} newUrl - The new URL
12
+ * @return {boolean} True if the entity link should be severed
13
+ */
14
+ const shouldSeverEntityLink = ( originalUrl, newUrl ) => {
15
+ if ( ! originalUrl || ! newUrl ) {
16
+ return false;
17
+ }
18
+
19
+ const normalizePath = ( path ) => {
20
+ if ( ! path ) {
21
+ return '';
22
+ }
23
+ return path.replace( /\/+$/, '' ); // Remove trailing slashes
24
+ };
25
+
26
+ // Helper function to create URL objects with proper base handling
27
+ const createUrlObject = ( url, baseUrl = null ) => {
28
+ try {
29
+ // Always provide a base URL - it will be ignored for absolute URLs
30
+ // Use window.location.origin in browser, fallback for Node/tests
31
+ const base =
32
+ baseUrl ||
33
+ ( typeof window !== 'undefined'
34
+ ? window.location.origin
35
+ : 'https://wordpress.org' );
36
+ return new URL( url, base );
37
+ } catch ( error ) {
38
+ // If URL construction still fails, it's likely an invalid URL
39
+ // and we should sever the entity link
40
+ return null;
41
+ }
42
+ };
43
+
44
+ const originalUrlObj = createUrlObject( originalUrl );
45
+ if ( ! originalUrlObj ) {
46
+ return true;
47
+ }
48
+
49
+ const newUrlObj = createUrlObject( newUrl, originalUrl );
50
+ if ( ! newUrlObj ) {
51
+ return true;
52
+ }
53
+
54
+ // Move these declarations here, after the null checks
55
+ const originalHostname = originalUrlObj.hostname;
56
+ const newHostname = newUrlObj.hostname;
57
+ const originalPath = normalizePath( getPath( originalUrlObj.toString() ) );
58
+ const newPath = normalizePath( getPath( newUrlObj.toString() ) );
59
+
60
+ // If hostname or path changed, sever the entity link
61
+ if ( originalHostname !== newHostname || originalPath !== newPath ) {
62
+ return true;
63
+ }
64
+
65
+ // Special handling for plain permalinks (query string post IDs)
66
+ const originalP = originalUrlObj.searchParams.get( 'p' );
67
+ const newP = newUrlObj.searchParams.get( 'p' );
68
+
69
+ // If both are plain permalinks (with ?p= or ?page_id=), compare the IDs
70
+ if ( originalP && newP && originalP !== newP ) {
71
+ return true;
72
+ }
73
+
74
+ const originalPageId = originalUrlObj.searchParams.get( 'page_id' );
75
+ const newPageId = newUrlObj.searchParams.get( 'page_id' );
76
+
77
+ if ( originalPageId && newPageId && originalPageId !== newPageId ) {
78
+ return true;
79
+ }
80
+ // If switching between ?p= and ?page_id=, or one is missing, sever
81
+ if ( ( originalP && newPageId ) || ( originalPageId && newP ) ) {
82
+ return true;
83
+ }
84
+
85
+ // If only query string or fragment changed, preserve the entity link
86
+ return false;
87
+ };
6
88
 
7
89
  /**
8
90
  * @typedef {'post-type'|'custom'|'taxonomy'|'post-type-archive'} WPNavigationLinkKind
@@ -42,19 +124,23 @@ export const updateAttributes = (
42
124
 
43
125
  const {
44
126
  title: newLabel = '', // the title of any provided Post.
45
- url: newUrl = '',
127
+ label: newLabelFromLabel = '', // alternative to title
128
+ url: newUrl,
46
129
  opensInNewTab,
47
- id,
130
+ id: newID,
48
131
  kind: newKind = originalKind,
49
132
  type: newType = originalType,
50
133
  } = updatedValue;
51
134
 
52
- const newLabelWithoutHttp = newLabel.replace( /http(s?):\/\//gi, '' );
53
- const newUrlWithoutHttp = newUrl.replace( /http(s?):\/\//gi, '' );
135
+ // Use title if provided, otherwise fall back to label
136
+ const finalNewLabel = newLabel || newLabelFromLabel;
137
+
138
+ const newLabelWithoutHttp = finalNewLabel.replace( /http(s?):\/\//gi, '' );
139
+ const newUrlWithoutHttp = newUrl?.replace( /http(s?):\/\//gi, '' ) ?? '';
54
140
 
55
141
  const useNewLabel =
56
- newLabel &&
57
- newLabel !== originalLabel &&
142
+ finalNewLabel &&
143
+ finalNewLabel !== originalLabel &&
58
144
  // LinkControl without the title field relies
59
145
  // on the check below. Specifically, it assumes that
60
146
  // the URL is the same as a title.
@@ -73,7 +159,7 @@ export const updateAttributes = (
73
159
  // - https://github.com/WordPress/gutenberg/pull/41063
74
160
  // - https://github.com/WordPress/gutenberg/pull/18617.
75
161
  const label = useNewLabel
76
- ? escapeHTML( newLabel )
162
+ ? escapeHTML( finalNewLabel )
77
163
  : originalLabel || escapeHTML( newUrlWithoutHttp );
78
164
 
79
165
  // In https://github.com/WordPress/gutenberg/pull/24670 we decided to use "tag" in favor of "post_tag"
@@ -86,13 +172,40 @@ export const updateAttributes = (
86
172
  ( ! newKind && ! isBuiltInType ) || newKind === 'custom';
87
173
  const kind = isCustomLink ? 'custom' : newKind;
88
174
 
89
- setAttributes( {
175
+ const attributes = {
90
176
  // Passed `url` may already be encoded. To prevent double encoding, decodeURI is executed to revert to the original string.
91
- ...( newUrl && { url: encodeURI( safeDecodeURI( newUrl ) ) } ),
177
+ ...( newUrl !== undefined
178
+ ? { url: newUrl ? encodeURI( safeDecodeURI( newUrl ) ) : newUrl }
179
+ : {} ),
92
180
  ...( label && { label } ),
93
181
  ...( undefined !== opensInNewTab && { opensInNewTab } ),
94
- ...( id && Number.isInteger( id ) && { id } ),
95
182
  ...( kind && { kind } ),
96
183
  ...( type && type !== 'URL' && { type } ),
97
- } );
184
+ };
185
+
186
+ // If the block's id is set then the menu item is linking to an entity.
187
+ // Therefore, if the URL is set but a new ID is not provided, check if
188
+ // the entity link should be severed based on URL changes.
189
+ if ( newUrl && ! newID && blockAttributes.id ) {
190
+ const shouldSever = shouldSeverEntityLink(
191
+ blockAttributes.url,
192
+ newUrl
193
+ );
194
+
195
+ if ( shouldSever ) {
196
+ attributes.id = undefined; // explicitly "unset" the ID.
197
+ // When URL is manually changed in a way that severs the entity link,
198
+ // update kind and type to "custom" to indicate this is now a custom link.
199
+ attributes.kind = 'custom';
200
+ attributes.type = 'custom';
201
+ }
202
+ } else if ( newID && Number.isInteger( newID ) ) {
203
+ attributes.id = newID;
204
+ } else if ( blockAttributes.id ) {
205
+ // If we have an existing ID and no URL change, ensure kind and type are preserved
206
+ attributes.kind = kind;
207
+ attributes.type = type;
208
+ }
209
+
210
+ setAttributes( attributes );
98
211
  };
@@ -8,6 +8,7 @@ import clsx from 'clsx';
8
8
  */
9
9
  import { useSelect, useDispatch } from '@wordpress/data';
10
10
  import {
11
+ CheckboxControl,
11
12
  TextControl,
12
13
  TextareaControl,
13
14
  ToolbarButton,
@@ -134,7 +135,7 @@ export default function NavigationSubmenuEdit( {
134
135
  context,
135
136
  clientId,
136
137
  } ) {
137
- const { label, url, description, rel } = attributes;
138
+ const { label, url, description, rel, opensInNewTab } = attributes;
138
139
 
139
140
  const { showSubmenuIcon, maxNestingLevel, openSubmenusOnClick } = context;
140
141
 
@@ -392,6 +393,7 @@ export default function NavigationSubmenuEdit( {
392
393
  url: '',
393
394
  description: '',
394
395
  rel: '',
396
+ opensInNewTab: false,
395
397
  } );
396
398
  } }
397
399
  dropdownMenuProps={ dropdownMenuProps }
@@ -433,6 +435,24 @@ export default function NavigationSubmenuEdit( {
433
435
  />
434
436
  </ToolsPanelItem>
435
437
 
438
+ <ToolsPanelItem
439
+ hasValue={ () => !! opensInNewTab }
440
+ label={ __( 'Open in new tab' ) }
441
+ onDeselect={ () =>
442
+ setAttributes( { opensInNewTab: false } )
443
+ }
444
+ isShownByDefault
445
+ >
446
+ <CheckboxControl
447
+ __nextHasNoMarginBottom
448
+ label={ __( 'Open in new tab' ) }
449
+ checked={ opensInNewTab }
450
+ onChange={ ( value ) =>
451
+ setAttributes( { opensInNewTab: value } )
452
+ }
453
+ />
454
+ </ToolsPanelItem>
455
+
436
456
  <ToolsPanelItem
437
457
  label={ __( 'Description' ) }
438
458
  isShownByDefault
@@ -7,6 +7,12 @@
7
7
  "description": "Displays the contents of a post or page.",
8
8
  "textdomain": "default",
9
9
  "usesContext": [ "postId", "postType", "queryId" ],
10
+ "attributes": {
11
+ "tagName": {
12
+ "type": "string",
13
+ "default": "div"
14
+ }
15
+ },
10
16
  "example": {
11
17
  "viewportWidth": 350
12
18
  },
@@ -3,11 +3,13 @@
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
5
  import {
6
+ InspectorControls,
6
7
  useBlockProps,
7
8
  useInnerBlocksProps,
8
9
  RecursionProvider,
9
10
  useHasRecursion,
10
11
  Warning,
12
+ privateApis as blockEditorPrivateApis,
11
13
  __experimentalUseBlockPreview as useBlockPreview,
12
14
  } from '@wordpress/block-editor';
13
15
  import { parse } from '@wordpress/blocks';
@@ -23,6 +25,9 @@ import { useMemo } from '@wordpress/element';
23
25
  * Internal dependencies
24
26
  */
25
27
  import { useCanEditEntity } from '../utils/hooks';
28
+ import { unlock } from '../lock-unlock';
29
+
30
+ const { HTMLElementControl } = unlock( blockEditorPrivateApis );
26
31
 
27
32
  function ReadOnlyContent( {
28
33
  parentLayout,
@@ -30,6 +35,7 @@ function ReadOnlyContent( {
30
35
  userCanEdit,
31
36
  postType,
32
37
  postId,
38
+ tagName: TagName = 'div',
33
39
  } ) {
34
40
  const [ , , content ] = useEntityProp(
35
41
  'postType',
@@ -60,18 +66,18 @@ function ReadOnlyContent( {
60
66
  }
61
67
 
62
68
  return content?.protected ? (
63
- <div { ...blockProps }>
69
+ <TagName { ...blockProps }>
64
70
  <Warning>{ __( 'This content is password protected.' ) }</Warning>
65
- </div>
71
+ </TagName>
66
72
  ) : (
67
- <div
73
+ <TagName
68
74
  { ...blockProps }
69
75
  dangerouslySetInnerHTML={ { __html: content?.rendered } }
70
- ></div>
76
+ ></TagName>
71
77
  );
72
78
  }
73
79
 
74
- function EditableContent( { context = {} } ) {
80
+ function EditableContent( { context = {}, tagName: TagName = 'div' } ) {
75
81
  const { postType, postId } = context;
76
82
 
77
83
  const [ blocks, onInput, onChange ] = useEntityBlockEditor(
@@ -104,12 +110,15 @@ function EditableContent( { context = {} } ) {
104
110
  template: ! hasInnerBlocks ? initialInnerBlocks : undefined,
105
111
  }
106
112
  );
107
- return <div { ...props } />;
113
+ return <TagName { ...props } />;
108
114
  }
109
115
 
110
116
  function Content( props ) {
111
- const { context: { queryId, postType, postId } = {}, layoutClassNames } =
112
- props;
117
+ const {
118
+ context: { queryId, postType, postId } = {},
119
+ layoutClassNames,
120
+ tagName,
121
+ } = props;
113
122
  const userCanEdit = useCanEditEntity( 'postType', postType, postId );
114
123
  if ( userCanEdit === undefined ) {
115
124
  return null;
@@ -127,6 +136,7 @@ function Content( props ) {
127
136
  userCanEdit={ userCanEdit }
128
137
  postType={ postType }
129
138
  postId={ postId }
139
+ tagName={ tagName }
130
140
  />
131
141
  );
132
142
  }
@@ -165,8 +175,39 @@ function RecursionError() {
165
175
  );
166
176
  }
167
177
 
178
+ /**
179
+ * Render inspector controls for the PostContent block.
180
+ *
181
+ * @param {Object} props Component props.
182
+ * @param {string} props.tagName The HTML tag name.
183
+ * @param {Function} props.onSelectTagName onChange function for the SelectControl.
184
+ * @param {string} props.clientId The client ID of the current block.
185
+ *
186
+ * @return {JSX.Element} The control group.
187
+ */
188
+ function PostContentEditControls( { tagName, onSelectTagName, clientId } ) {
189
+ return (
190
+ <InspectorControls group="advanced">
191
+ <HTMLElementControl
192
+ tagName={ tagName }
193
+ onChange={ onSelectTagName }
194
+ clientId={ clientId }
195
+ options={ [
196
+ { label: __( 'Default (<div>)' ), value: 'div' },
197
+ { label: '<main>', value: 'main' },
198
+ { label: '<section>', value: 'section' },
199
+ { label: '<article>', value: 'article' },
200
+ ] }
201
+ />
202
+ </InspectorControls>
203
+ );
204
+ }
205
+
168
206
  export default function PostContentEdit( {
169
207
  context,
208
+ attributes: { tagName = 'div' },
209
+ setAttributes,
210
+ clientId,
170
211
  __unstableLayoutClassNames: layoutClassNames,
171
212
  __unstableParentLayout: parentLayout,
172
213
  } ) {
@@ -177,17 +218,28 @@ export default function PostContentEdit( {
177
218
  return <RecursionError />;
178
219
  }
179
220
 
221
+ const handleSelectTagName = ( value ) => {
222
+ setAttributes( { tagName: value } );
223
+ };
224
+
180
225
  return (
181
- <RecursionProvider uniqueId={ contextPostId }>
182
- { contextPostId && contextPostType ? (
183
- <Content
184
- context={ context }
185
- parentLayout={ parentLayout }
186
- layoutClassNames={ layoutClassNames }
187
- />
188
- ) : (
189
- <Placeholder layoutClassNames={ layoutClassNames } />
190
- ) }
191
- </RecursionProvider>
226
+ <>
227
+ <PostContentEditControls
228
+ tagName={ tagName }
229
+ onSelectTagName={ handleSelectTagName }
230
+ clientId={ clientId }
231
+ />
232
+ <RecursionProvider uniqueId={ contextPostId }>
233
+ { contextPostId && contextPostType ? (
234
+ <Content
235
+ context={ context }
236
+ parentLayout={ parentLayout }
237
+ layoutClassNames={ layoutClassNames }
238
+ />
239
+ ) : (
240
+ <Placeholder layoutClassNames={ layoutClassNames } />
241
+ ) }
242
+ </RecursionProvider>
243
+ </>
192
244
  );
193
245
  }
@@ -54,12 +54,19 @@ function render_block_core_post_content( $attributes, $content, $block ) {
54
54
  return '';
55
55
  }
56
56
 
57
+ $tag_name = 'div';
58
+
59
+ if ( ! empty( $attributes['tagName'] ) && tag_escape( $attributes['tagName'] ) === $attributes['tagName'] ) {
60
+ $tag_name = $attributes['tagName'];
61
+ }
62
+
57
63
  $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => 'entry-content' ) );
58
64
 
59
- return (
60
- '<div ' . $wrapper_attributes . '>' .
61
- $content .
62
- '</div>'
65
+ return sprintf(
66
+ '<%1$s %2$s>%3$s</%1$s>',
67
+ $tag_name,
68
+ $wrapper_attributes,
69
+ $content
63
70
  );
64
71
  }
65
72
 
@@ -27,8 +27,9 @@ function render_block_core_post_featured_image( $attributes, $content, $block )
27
27
  $overlay_markup = get_block_core_post_featured_image_overlay_element_markup( $attributes );
28
28
 
29
29
  if ( $is_link ) {
30
- if ( get_the_title( $post_ID ) ) {
31
- $attr['alt'] = trim( strip_tags( get_the_title( $post_ID ) ) );
30
+ $title = get_the_title( $post_ID );
31
+ if ( $title ) {
32
+ $attr['alt'] = trim( strip_tags( $title ) );
32
33
  } else {
33
34
  $attr['alt'] = sprintf(
34
35
  // translators: %d is the post ID.
@@ -7,26 +7,18 @@ import clsx from 'clsx';
7
7
  * WordPress dependencies
8
8
  */
9
9
  import {
10
- HorizontalRule,
11
- SelectControl,
12
- PanelBody,
13
- __experimentalToolsPanel as ToolsPanel,
14
- __experimentalToolsPanelItem as ToolsPanelItem,
15
- } from '@wordpress/components';
16
- import {
17
- useBlockProps,
18
10
  getColorClassName,
19
- __experimentalUseColorProps as useColorProps,
20
11
  InspectorControls,
12
+ useBlockProps,
13
+ __experimentalUseColorProps as useColorProps,
21
14
  } from '@wordpress/block-editor';
22
- import { Platform } from '@wordpress/element';
15
+ import { HorizontalRule, SelectControl } from '@wordpress/components';
23
16
  import { __ } from '@wordpress/i18n';
24
17
 
25
18
  /**
26
19
  * Internal dependencies
27
20
  */
28
21
  import useDeprecatedOpacity from './use-deprecated-opacity';
29
- import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
30
22
 
31
23
  const HtmlElementControl = ( { tagName, setAttributes } ) => {
32
24
  return (
@@ -58,7 +50,6 @@ export default function SeparatorEdit( { attributes, setAttributes } ) {
58
50
  const colorProps = useColorProps( attributes );
59
51
  const currentColor = colorProps?.style?.backgroundColor;
60
52
  const hasCustomColor = !! style?.color?.background;
61
- const dropdownMenuProps = useToolsPanelDropdownMenuProps();
62
53
 
63
54
  useDeprecatedOpacity( opacity, currentColor, setAttributes );
64
55
 
@@ -84,37 +75,11 @@ export default function SeparatorEdit( { attributes, setAttributes } ) {
84
75
 
85
76
  return (
86
77
  <>
87
- <InspectorControls>
88
- { Platform.isNative ? (
89
- <PanelBody title={ __( 'Settings' ) }>
90
- <HtmlElementControl
91
- tagName={ tagName }
92
- setAttributes={ setAttributes }
93
- />
94
- </PanelBody>
95
- ) : (
96
- <ToolsPanel
97
- label={ __( 'Settings' ) }
98
- resetAll={ () => {
99
- setAttributes( { tagName: 'hr' } );
100
- } }
101
- dropdownMenuProps={ dropdownMenuProps }
102
- >
103
- <ToolsPanelItem
104
- hasValue={ () => tagName !== 'hr' }
105
- label={ __( 'HTML element' ) }
106
- onDeselect={ () =>
107
- setAttributes( { tagName: 'hr' } )
108
- }
109
- isShownByDefault
110
- >
111
- <HtmlElementControl
112
- tagName={ tagName }
113
- setAttributes={ setAttributes }
114
- />
115
- </ToolsPanelItem>
116
- </ToolsPanel>
117
- ) }
78
+ <InspectorControls group="advanced">
79
+ <HtmlElementControl
80
+ tagName={ tagName }
81
+ setAttributes={ setAttributes }
82
+ />
118
83
  </InspectorControls>
119
84
  <Wrapper
120
85
  { ...useBlockProps( {
@@ -4,7 +4,7 @@
4
4
  "name": "core/site-tagline",
5
5
  "title": "Site Tagline",
6
6
  "category": "theme",
7
- "description": "Describe in a few words what the site is about. The tagline can be used in search results or when sharing on social networks even if it’s not displayed in the theme design.",
7
+ "description": "Describe in a few words what this site is about. This is important for search results, sharing on social media, and gives overall clarity to visitors.",
8
8
  "keywords": [ "description" ],
9
9
  "textdomain": "default",
10
10
  "attributes": {
package/src/video/edit.js CHANGED
@@ -23,7 +23,6 @@ import {
23
23
  } from '@wordpress/block-editor';
24
24
  import { useRef, useEffect, useState } from '@wordpress/element';
25
25
  import { __ } from '@wordpress/i18n';
26
- import { useInstanceId } from '@wordpress/compose';
27
26
  import { useDispatch } from '@wordpress/data';
28
27
  import { video as icon } from '@wordpress/icons';
29
28
  import { store as noticesStore } from '@wordpress/notices';
@@ -52,7 +51,6 @@ function VideoEdit( {
52
51
  insertBlocksAfter,
53
52
  onReplace,
54
53
  } ) {
55
- const instanceId = useInstanceId( VideoEdit );
56
54
  const videoPlayer = useRef();
57
55
  const { id, controls, poster, src, tracks } = attributes;
58
56
  const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob );
@@ -210,7 +208,7 @@ function VideoEdit( {
210
208
  muted: false,
211
209
  playsInline: false,
212
210
  preload: 'metadata',
213
- poster: '',
211
+ poster: undefined,
214
212
  } );
215
213
  } }
216
214
  dropdownMenuProps={ dropdownMenuProps }
@@ -222,7 +220,6 @@ function VideoEdit( {
222
220
  <PosterImage
223
221
  poster={ poster }
224
222
  setAttributes={ setAttributes }
225
- instanceId={ instanceId }
226
223
  />
227
224
  </ToolsPanel>
228
225
  </InspectorControls>
@@ -19,12 +19,6 @@
19
19
  }
20
20
  }
21
21
 
22
- .editor-video-poster-control {
23
- .components-button {
24
- margin-right: $grid-unit-10;
25
- }
26
- }
27
-
28
22
  .block-library-video-tracks-editor {
29
23
  z-index: z-index("{core/video track editor popover}");
30
24
  }
@@ -5,16 +5,21 @@ import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
5
5
  import {
6
6
  Button,
7
7
  BaseControl,
8
+ __experimentalHStack as HStack,
8
9
  __experimentalToolsPanelItem as ToolsPanelItem,
9
10
  } from '@wordpress/components';
10
11
  import { __, sprintf } from '@wordpress/i18n';
11
12
  import { useRef } from '@wordpress/element';
13
+ import { useInstanceId } from '@wordpress/compose';
12
14
 
13
- function PosterImage( { poster, setAttributes, instanceId } ) {
14
- const posterImageButton = useRef();
15
- const VIDEO_POSTER_ALLOWED_MEDIA_TYPES = [ 'image' ];
15
+ const VIDEO_POSTER_ALLOWED_MEDIA_TYPES = [ 'image' ];
16
16
 
17
- const videoPosterDescription = `video-block__poster-image-description-${ instanceId }`;
17
+ function PosterImage( { poster, setAttributes } ) {
18
+ const posterButtonRef = useRef();
19
+ const descriptionId = useInstanceId(
20
+ PosterImage,
21
+ 'video-block__poster-image-description'
22
+ );
18
23
 
19
24
  function onSelectPoster( image ) {
20
25
  setAttributes( { poster: image.url } );
@@ -24,23 +29,23 @@ function PosterImage( { poster, setAttributes, instanceId } ) {
24
29
  setAttributes( { poster: undefined } );
25
30
 
26
31
  // Move focus back to the Media Upload button.
27
- posterImageButton.current.focus();
32
+ posterButtonRef.current.focus();
28
33
  }
29
34
 
30
35
  return (
31
- <ToolsPanelItem
32
- label={ __( 'Poster image' ) }
33
- isShownByDefault
34
- hasValue={ () => !! poster }
35
- onDeselect={ () => {
36
- setAttributes( { poster: '' } );
37
- } }
38
- >
39
- <MediaUploadCheck>
40
- <div className="editor-video-poster-control">
41
- <BaseControl.VisualLabel>
42
- { __( 'Poster image' ) }
43
- </BaseControl.VisualLabel>
36
+ <MediaUploadCheck>
37
+ <ToolsPanelItem
38
+ label={ __( 'Poster image' ) }
39
+ isShownByDefault
40
+ hasValue={ () => !! poster }
41
+ onDeselect={ () => {
42
+ setAttributes( { poster: undefined } );
43
+ } }
44
+ >
45
+ <BaseControl.VisualLabel>
46
+ { __( 'Poster image' ) }
47
+ </BaseControl.VisualLabel>
48
+ <HStack justify="flex-start">
44
49
  <MediaUpload
45
50
  title={ __( 'Select poster image' ) }
46
51
  onSelect={ onSelectPoster }
@@ -50,14 +55,14 @@ function PosterImage( { poster, setAttributes, instanceId } ) {
50
55
  __next40pxDefaultSize
51
56
  variant="primary"
52
57
  onClick={ open }
53
- ref={ posterImageButton }
54
- aria-describedby={ videoPosterDescription }
58
+ ref={ posterButtonRef }
59
+ aria-describedby={ descriptionId }
55
60
  >
56
61
  { ! poster ? __( 'Select' ) : __( 'Replace' ) }
57
62
  </Button>
58
63
  ) }
59
64
  />
60
- <p id={ videoPosterDescription } hidden>
65
+ <p id={ descriptionId } hidden>
61
66
  { poster
62
67
  ? sprintf(
63
68
  /* translators: %s: poster image URL. */
@@ -77,9 +82,9 @@ function PosterImage( { poster, setAttributes, instanceId } ) {
77
82
  { __( 'Remove' ) }
78
83
  </Button>
79
84
  ) }
80
- </div>
81
- </MediaUploadCheck>
82
- </ToolsPanelItem>
85
+ </HStack>
86
+ </ToolsPanelItem>
87
+ </MediaUploadCheck>
83
88
  );
84
89
  }
85
90