@wordpress/block-library 9.29.1-next.f34ab90e9.0 → 9.30.1-next.6870dfe5b.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 (168) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/accordion/edit.js +18 -1
  3. package/build/accordion/edit.js.map +1 -1
  4. package/build/accordion/index.js +0 -3
  5. package/build/accordion/index.js.map +1 -1
  6. package/build/accordion-content/edit.js +8 -8
  7. package/build/accordion-content/edit.js.map +1 -1
  8. package/build/accordion-content/index.js +2 -5
  9. package/build/accordion-content/index.js.map +1 -1
  10. package/build/accordion-header/index.js +0 -4
  11. package/build/accordion-header/index.js.map +1 -1
  12. package/build/accordion-panel/edit.js +5 -30
  13. package/build/accordion-panel/edit.js.map +1 -1
  14. package/build/accordion-panel/index.js +2 -5
  15. package/build/accordion-panel/index.js.map +1 -1
  16. package/build/accordion-panel/save.js +3 -29
  17. package/build/accordion-panel/save.js.map +1 -1
  18. package/build/audio/edit.js +3 -1
  19. package/build/audio/edit.js.map +1 -1
  20. package/build/gallery/index.js +2 -1
  21. package/build/gallery/index.js.map +1 -1
  22. package/build/group/variations.js +0 -12
  23. package/build/group/variations.js.map +1 -1
  24. package/build/image/image.js +1 -1
  25. package/build/image/image.js.map +1 -1
  26. package/build/navigation/constants.js +5 -1
  27. package/build/navigation/constants.js.map +1 -1
  28. package/build/navigation/edit/index.js +45 -1
  29. package/build/navigation/edit/index.js.map +1 -1
  30. package/build/navigation/edit/leaf-more-menu.js +0 -1
  31. package/build/navigation/edit/leaf-more-menu.js.map +1 -1
  32. package/build/navigation/edit/menu-inspector-controls.js +40 -5
  33. package/build/navigation/edit/menu-inspector-controls.js.map +1 -1
  34. package/build/navigation-link/block-inserter.js +69 -0
  35. package/build/navigation-link/block-inserter.js.map +1 -0
  36. package/build/navigation-link/dialog-wrapper.js +80 -0
  37. package/build/navigation-link/dialog-wrapper.js.map +1 -0
  38. package/build/navigation-link/link-ui.js +80 -116
  39. package/build/navigation-link/link-ui.js.map +1 -1
  40. package/build/navigation-link/page-creator.js +137 -0
  41. package/build/navigation-link/page-creator.js.map +1 -0
  42. package/build/query/edit/index.js.map +1 -1
  43. package/build/query/edit/query-content.js +7 -6
  44. package/build/query/edit/query-content.js.map +1 -1
  45. package/build/query/edit/query-placeholder.js +30 -9
  46. package/build/query/edit/query-placeholder.js.map +1 -1
  47. package/build/query/edit/query-toolbar.js +4 -2
  48. package/build/query/edit/query-toolbar.js.map +1 -1
  49. package/build/search/edit.js +22 -14
  50. package/build/search/edit.js.map +1 -1
  51. package/build/template-part/edit/placeholder.js +2 -1
  52. package/build/template-part/edit/placeholder.js.map +1 -1
  53. package/build/video/edit.js +3 -1
  54. package/build/video/edit.js.map +1 -1
  55. package/build-module/accordion/edit.js +20 -3
  56. package/build-module/accordion/edit.js.map +1 -1
  57. package/build-module/accordion/index.js +0 -3
  58. package/build-module/accordion/index.js.map +1 -1
  59. package/build-module/accordion-content/edit.js +8 -8
  60. package/build-module/accordion-content/edit.js.map +1 -1
  61. package/build-module/accordion-content/index.js +2 -5
  62. package/build-module/accordion-content/index.js.map +1 -1
  63. package/build-module/accordion-header/index.js +0 -4
  64. package/build-module/accordion-header/index.js.map +1 -1
  65. package/build-module/accordion-panel/edit.js +6 -29
  66. package/build-module/accordion-panel/edit.js.map +1 -1
  67. package/build-module/accordion-panel/index.js +2 -5
  68. package/build-module/accordion-panel/index.js.map +1 -1
  69. package/build-module/accordion-panel/save.js +4 -28
  70. package/build-module/accordion-panel/save.js.map +1 -1
  71. package/build-module/audio/edit.js +4 -2
  72. package/build-module/audio/edit.js.map +1 -1
  73. package/build-module/gallery/index.js +2 -1
  74. package/build-module/gallery/index.js.map +1 -1
  75. package/build-module/group/variations.js +0 -12
  76. package/build-module/group/variations.js.map +1 -1
  77. package/build-module/image/image.js +1 -1
  78. package/build-module/image/image.js.map +1 -1
  79. package/build-module/navigation/constants.js +5 -1
  80. package/build-module/navigation/constants.js.map +1 -1
  81. package/build-module/navigation/edit/index.js +50 -4
  82. package/build-module/navigation/edit/index.js.map +1 -1
  83. package/build-module/navigation/edit/leaf-more-menu.js +0 -1
  84. package/build-module/navigation/edit/leaf-more-menu.js.map +1 -1
  85. package/build-module/navigation/edit/menu-inspector-controls.js +40 -5
  86. package/build-module/navigation/edit/menu-inspector-controls.js.map +1 -1
  87. package/build-module/navigation-link/block-inserter.js +61 -0
  88. package/build-module/navigation-link/block-inserter.js.map +1 -0
  89. package/build-module/navigation-link/dialog-wrapper.js +75 -0
  90. package/build-module/navigation-link/dialog-wrapper.js.map +1 -0
  91. package/build-module/navigation-link/link-ui.js +85 -121
  92. package/build-module/navigation-link/link-ui.js.map +1 -1
  93. package/build-module/navigation-link/page-creator.js +130 -0
  94. package/build-module/navigation-link/page-creator.js.map +1 -0
  95. package/build-module/query/edit/index.js.map +1 -1
  96. package/build-module/query/edit/query-content.js +8 -7
  97. package/build-module/query/edit/query-content.js.map +1 -1
  98. package/build-module/query/edit/query-placeholder.js +30 -10
  99. package/build-module/query/edit/query-placeholder.js.map +1 -1
  100. package/build-module/query/edit/query-toolbar.js +4 -2
  101. package/build-module/query/edit/query-toolbar.js.map +1 -1
  102. package/build-module/search/edit.js +22 -14
  103. package/build-module/search/edit.js.map +1 -1
  104. package/build-module/template-part/edit/placeholder.js +2 -1
  105. package/build-module/template-part/edit/placeholder.js.map +1 -1
  106. package/build-module/video/edit.js +4 -2
  107. package/build-module/video/edit.js.map +1 -1
  108. package/build-style/accordion/style-rtl.css +8 -18
  109. package/build-style/accordion/style.css +8 -18
  110. package/build-style/editor-rtl.css +18 -0
  111. package/build-style/editor.css +18 -0
  112. package/build-style/form-input/style-rtl.css +4 -3
  113. package/build-style/form-input/style.css +4 -3
  114. package/build-style/navigation-link/editor-rtl.css +14 -0
  115. package/build-style/navigation-link/editor.css +14 -0
  116. package/build-style/navigation-link/style-rtl.css +1 -1
  117. package/build-style/navigation-link/style.css +1 -1
  118. package/build-style/post-comments-form/style-rtl.css +8 -5
  119. package/build-style/post-comments-form/style.css +8 -5
  120. package/build-style/query/editor-rtl.css +4 -0
  121. package/build-style/query/editor.css +4 -0
  122. package/build-style/search/style-rtl.css +11 -12
  123. package/build-style/search/style.css +11 -12
  124. package/build-style/style-rtl.css +32 -40
  125. package/build-style/style.css +32 -40
  126. package/package.json +35 -35
  127. package/src/accordion/block.json +0 -3
  128. package/src/accordion/edit.js +20 -0
  129. package/src/accordion/style.scss +12 -21
  130. package/src/accordion-content/block.json +2 -4
  131. package/src/accordion-content/edit.js +21 -27
  132. package/src/accordion-content/index.js +0 -1
  133. package/src/accordion-header/block.json +0 -3
  134. package/src/accordion-header/index.js +0 -1
  135. package/src/accordion-panel/block.json +2 -4
  136. package/src/accordion-panel/edit.js +11 -51
  137. package/src/accordion-panel/index.js +0 -1
  138. package/src/accordion-panel/save.js +4 -45
  139. package/src/audio/edit.js +6 -1
  140. package/src/cover/test/edit.js +1 -5
  141. package/src/form-input/style.scss +3 -2
  142. package/src/gallery/block.json +2 -1
  143. package/src/gallery/index.php +1 -1
  144. package/src/gallery/test/helpers.native.js +3 -3
  145. package/src/group/variations.js +0 -12
  146. package/src/image/image.js +2 -1
  147. package/src/navigation/constants.js +4 -0
  148. package/src/navigation/edit/index.js +50 -1
  149. package/src/navigation/edit/leaf-more-menu.js +0 -1
  150. package/src/navigation/edit/menu-inspector-controls.js +40 -5
  151. package/src/navigation-link/block-inserter.js +65 -0
  152. package/src/navigation-link/dialog-wrapper.js +74 -0
  153. package/src/navigation-link/editor.scss +17 -0
  154. package/src/navigation-link/link-ui.js +108 -158
  155. package/src/navigation-link/page-creator.js +157 -0
  156. package/src/navigation-link/style.scss +1 -1
  157. package/src/post-comments-form/style.scss +11 -11
  158. package/src/post-date/index.php +2 -1
  159. package/src/query/edit/index.js +1 -0
  160. package/src/query/edit/query-content.js +8 -4
  161. package/src/query/edit/query-placeholder.js +47 -17
  162. package/src/query/edit/query-toolbar.js +10 -2
  163. package/src/query/editor.scss +6 -1
  164. package/src/search/edit.js +44 -13
  165. package/src/search/index.php +16 -2
  166. package/src/search/style.scss +15 -16
  167. package/src/template-part/edit/placeholder.js +2 -1
  168. package/src/video/edit.js +6 -1
@@ -2,16 +2,13 @@
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
4
  "name": "core/accordion-content",
5
- "version": "0.1.0",
6
5
  "title": "Accordion Content",
7
6
  "category": "design",
8
7
  "description": "Displays a section of content in an accordion, including a header and expandable content.",
9
- "example": {},
10
8
  "__experimental": true,
11
9
  "parent": [ "core/accordion" ],
12
10
  "allowedBlocks": [ "core/accordion-header", "core/accordion-panel" ],
13
11
  "supports": {
14
- "align": [ "wide", "full" ],
15
12
  "color": {
16
13
  "background": true,
17
14
  "gradient": true
@@ -33,7 +30,8 @@
33
30
  "width": true
34
31
  }
35
32
  },
36
- "shadow": true
33
+ "shadow": true,
34
+ "layout": true
37
35
  },
38
36
  "attributes": {
39
37
  "openByDefault": {
@@ -25,11 +25,8 @@ import clsx from 'clsx';
25
25
  */
26
26
  import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
27
27
 
28
- export default function Edit( {
29
- attributes: { openByDefault },
30
- clientId,
31
- setAttributes,
32
- } ) {
28
+ export default function Edit( { attributes, clientId, setAttributes } ) {
29
+ const { openByDefault } = attributes;
33
30
  const dropdownMenuProps = useToolsPanelDropdownMenuProps();
34
31
 
35
32
  const { isSelected, getBlockOrder } = useSelect(
@@ -67,29 +64,26 @@ export default function Edit( {
67
64
  updateBlockAttributes,
68
65
  ] );
69
66
 
70
- const blockProps = useBlockProps();
71
- const innerBlocksProps = useInnerBlocksProps(
72
- {
73
- ...blockProps,
74
- className: clsx( blockProps.className, {
75
- 'is-open': openByDefault || isSelected,
76
- } ),
77
- },
78
- {
79
- template: [
80
- [ 'core/accordion-header', {} ],
81
- [
82
- 'core/accordion-panel',
83
- {
84
- openByDefault,
85
- },
86
- ],
67
+ const blockProps = useBlockProps( {
68
+ className: clsx( {
69
+ 'is-open': openByDefault || isSelected,
70
+ } ),
71
+ } );
72
+
73
+ const innerBlocksProps = useInnerBlocksProps( blockProps, {
74
+ template: [
75
+ [ 'core/accordion-header', {} ],
76
+ [
77
+ 'core/accordion-panel',
78
+ {
79
+ openByDefault,
80
+ },
87
81
  ],
88
- templateLock: 'all',
89
- directInsert: true,
90
- templateInsertUpdatesSelection: true,
91
- }
92
- );
82
+ ],
83
+ templateLock: 'all',
84
+ directInsert: true,
85
+ templateInsertUpdatesSelection: true,
86
+ } );
93
87
 
94
88
  return (
95
89
  <>
@@ -13,7 +13,6 @@ export { metadata, name };
13
13
 
14
14
  export const settings = {
15
15
  icon,
16
- example: {},
17
16
  edit,
18
17
  save,
19
18
  };
@@ -2,11 +2,9 @@
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
4
  "name": "core/accordion-header",
5
- "version": "0.1.0",
6
5
  "title": "Accordion Header",
7
6
  "category": "design",
8
7
  "description": "Displays an accordion header.",
9
- "example": {},
10
8
  "__experimental": true,
11
9
  "parent": [ "core/accordion-content" ],
12
10
  "usesContext": [
@@ -20,7 +18,6 @@
20
18
  "gradient": true
21
19
  },
22
20
  "align": false,
23
- "border": true,
24
21
  "interactivity": true,
25
22
  "spacing": {
26
23
  "padding": true,
@@ -13,7 +13,6 @@ export { metadata, name };
13
13
 
14
14
  export const settings = {
15
15
  icon,
16
- example: {},
17
16
  edit,
18
17
  save,
19
18
  };
@@ -2,11 +2,9 @@
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "apiVersion": 3,
4
4
  "name": "core/accordion-panel",
5
- "version": "0.1.0",
6
5
  "title": "Accordion Panel",
7
6
  "category": "design",
8
7
  "description": "Displays an accordion panel.",
9
- "example": {},
10
8
  "__experimental": true,
11
9
  "parent": [ "core/accordion-content" ],
12
10
  "supports": {
@@ -14,7 +12,6 @@
14
12
  "background": true,
15
13
  "gradient": true
16
14
  },
17
- "border": true,
18
15
  "interactivity": true,
19
16
  "spacing": {
20
17
  "padding": true,
@@ -50,7 +47,8 @@
50
47
  "fontSize": true
51
48
  }
52
49
  },
53
- "shadow": true
50
+ "shadow": true,
51
+ "layout": true
54
52
  },
55
53
  "attributes": {
56
54
  "allowedBlocks": {
@@ -1,61 +1,21 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import {
5
- useBlockProps,
6
- useInnerBlocksProps,
7
- __experimentalUseBorderProps as useBorderProps,
8
- __experimentalUseColorProps as useColorProps,
9
- __experimentalGetSpacingClassesAndStyles as useSpacingProps,
10
- __experimentalGetShadowClassesAndStyles as useShadowProps,
11
- } from '@wordpress/block-editor';
12
- /**
13
- * External dependencies
14
- */
15
- import clsx from 'clsx';
4
+ import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
16
5
 
17
6
  export default function Edit( { attributes } ) {
18
7
  const { allowedBlocks, templateLock, openByDefault, isSelected } =
19
8
  attributes;
20
- const borderProps = useBorderProps( attributes );
21
- const colorProps = useColorProps( attributes );
22
- const spacingProps = useSpacingProps( attributes );
23
- const shadowProps = useShadowProps( attributes );
24
9
 
25
- const blockProps = useBlockProps();
26
- const innerBlocksProps = useInnerBlocksProps(
27
- {
28
- className: 'accordion-content__wrapper',
29
- style: {
30
- ...spacingProps.style,
31
- },
32
- },
33
- {
34
- allowedBlocks,
35
- template: [ [ 'core/paragraph', {} ] ],
36
- templateLock,
37
- }
38
- );
10
+ const blockProps = useBlockProps( {
11
+ 'aria-hidden': ! isSelected && ! openByDefault,
12
+ } );
13
+
14
+ const innerBlocksProps = useInnerBlocksProps( blockProps, {
15
+ allowedBlocks,
16
+ template: [ [ 'core/paragraph', {} ] ],
17
+ templateLock,
18
+ } );
39
19
 
40
- return (
41
- <div
42
- { ...blockProps }
43
- className={ clsx(
44
- blockProps.className,
45
- colorProps.className,
46
- borderProps.className,
47
- {
48
- [ `has-custom-font-size` ]: blockProps?.style?.fontSize,
49
- }
50
- ) }
51
- style={ {
52
- ...borderProps.style,
53
- ...colorProps.style,
54
- ...shadowProps.style,
55
- } }
56
- aria-hidden={ ! isSelected && ! openByDefault }
57
- >
58
- <div { ...innerBlocksProps } />
59
- </div>
60
- );
20
+ return <div { ...innerBlocksProps } />;
61
21
  }
@@ -13,7 +13,6 @@ export { metadata, name };
13
13
 
14
14
  export const settings = {
15
15
  icon,
16
- example: {},
17
16
  edit,
18
17
  save,
19
18
  };
@@ -1,51 +1,10 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import {
5
- InnerBlocks,
6
- useBlockProps,
7
- __experimentalGetBorderClassesAndStyles as getBorderClassesAndStyles,
8
- __experimentalGetColorClassesAndStyles as getColorClassesAndStyles,
9
- __experimentalGetSpacingClassesAndStyles as getSpacingClassesAndStyles,
10
- __experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles,
11
- } from '@wordpress/block-editor';
12
- /**
13
- * External dependencies
14
- */
15
- import clsx from 'clsx';
4
+ import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
16
5
 
17
- export default function save( { attributes } ) {
6
+ export default function save() {
18
7
  const blockProps = useBlockProps.save();
19
- const borderProps = getBorderClassesAndStyles( attributes );
20
- const colorProps = getColorClassesAndStyles( attributes );
21
- const spacingProps = getSpacingClassesAndStyles( attributes );
22
- const shadowProps = getShadowClassesAndStyles( attributes );
23
-
24
- return (
25
- <div
26
- { ...blockProps }
27
- className={ clsx(
28
- blockProps.className,
29
- colorProps.className,
30
- borderProps.className,
31
- {
32
- [ `has-custom-font-size` ]: blockProps?.style?.fontSize,
33
- }
34
- ) }
35
- style={ {
36
- ...borderProps.style,
37
- ...colorProps.style,
38
- ...shadowProps.style,
39
- } }
40
- >
41
- <div
42
- className="accordion-content__wrapper"
43
- style={ {
44
- ...spacingProps.style,
45
- } }
46
- >
47
- <InnerBlocks.Content />
48
- </div>
49
- </div>
50
- );
8
+ const innerBlocksProps = useInnerBlocksProps.save( blockProps );
9
+ return <div { ...innerBlocksProps } />;
51
10
  }
package/src/audio/edit.js CHANGED
@@ -22,6 +22,7 @@ import {
22
22
  MediaPlaceholder,
23
23
  MediaReplaceFlow,
24
24
  useBlockProps,
25
+ useBlockEditingMode,
25
26
  } from '@wordpress/block-editor';
26
27
  import { __, _x } from '@wordpress/i18n';
27
28
  import { useDispatch } from '@wordpress/data';
@@ -51,6 +52,8 @@ function AudioEdit( {
51
52
  } ) {
52
53
  const { id, autoplay, loop, preload, src } = attributes;
53
54
  const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob );
55
+ const blockEditingMode = useBlockEditingMode();
56
+ const hasNonContentControls = blockEditingMode === 'default';
54
57
 
55
58
  useUploadMediaFromBlobURL( {
56
59
  url: temporaryURL,
@@ -264,7 +267,9 @@ function AudioEdit( {
264
267
  isSelected={ isSingleSelected }
265
268
  insertBlocksAfter={ insertBlocksAfter }
266
269
  label={ __( 'Audio caption text' ) }
267
- showToolbarButton={ isSingleSelected }
270
+ showToolbarButton={
271
+ isSingleSelected && hasNonContentControls
272
+ }
268
273
  />
269
274
  </figure>
270
275
  </>
@@ -51,11 +51,7 @@ async function createAndSelectBlock() {
51
51
  name: 'Black',
52
52
  } )
53
53
  );
54
- await userEvent.click(
55
- screen.getByRole( 'button', {
56
- name: 'Select parent block: Cover',
57
- } )
58
- );
54
+ await selectBlock( 'Block: Cover' );
59
55
  }
60
56
 
61
57
  describe( 'Cover block', () => {
@@ -34,7 +34,7 @@
34
34
  width: fit-content;
35
35
  }
36
36
 
37
- .wp-block-form-input__input {
37
+ :where(.wp-block-form-input__input) {
38
38
  padding: 0 0.5em;
39
39
  font-size: 1em;
40
40
  margin-bottom: 0.5em;
@@ -54,7 +54,8 @@
54
54
  &[type="week"] {
55
55
  min-height: 2em;
56
56
  line-height: 2;
57
- border: 1px solid;
57
+ border-width: 1px;
58
+ border-style: solid;
58
59
  }
59
60
  }
60
61
 
@@ -75,7 +75,8 @@
75
75
  "caption": {
76
76
  "type": "rich-text",
77
77
  "source": "rich-text",
78
- "selector": ".blocks-gallery-caption"
78
+ "selector": ".blocks-gallery-caption",
79
+ "role": "content"
79
80
  },
80
81
  "imageCrop": {
81
82
  "type": "boolean",
@@ -142,7 +142,7 @@ function block_core_gallery_render( $attributes, $content ) {
142
142
 
143
143
  // This pattern matches figure elements with the `wp-block-image` class to
144
144
  // avoid the gallery's wrapping `figure` element and extract images only.
145
- $pattern = '/<figure[^>]*\bwp-block-image\b[^>]*>.*?<\/figure>/';
145
+ $pattern = '/<figure[^>]*\bwp-block-image\b[^>]*>.*?<\/figure>/s';
146
146
 
147
147
  // Find all Image blocks.
148
148
  preg_match_all( $pattern, $updated_content, $matches );
@@ -65,9 +65,9 @@ export const initializeWithGalleryBlock = async ( {
65
65
  /**
66
66
  * Gets a gallery item within a Gallery block.
67
67
  *
68
- * @param {import('react-test-renderer').ReactTestInstance} galleryBlock Gallery block instance.
69
- * @param {number} rowIndex Row position within the Gallery block.
70
- * @return {import('react-test-renderer').ReactTestInstance} Gallery item.
68
+ * @param {ReturnType<import('@testing-library/react-native').RenderAPI['getByTestId']>} galleryBlock Gallery block instance.
69
+ * @param {number} rowIndex Row position within the Gallery block.
70
+ * @return {ReturnType<import('@testing-library/react-native').RenderAPI['getByTestId']>} Gallery item.
71
71
  */
72
72
  export const getGalleryItem = ( galleryBlock, rowIndex ) =>
73
73
  getInnerBlock( galleryBlock, 'Image', { rowIndex } );
@@ -9,48 +9,36 @@ const example = {
9
9
  {
10
10
  name: 'core/paragraph',
11
11
  attributes: {
12
- customTextColor: '#cf2e2e',
13
- fontSize: 'large',
14
12
  content: __( 'One.' ),
15
13
  },
16
14
  },
17
15
  {
18
16
  name: 'core/paragraph',
19
17
  attributes: {
20
- customTextColor: '#ff6900',
21
- fontSize: 'large',
22
18
  content: __( 'Two.' ),
23
19
  },
24
20
  },
25
21
  {
26
22
  name: 'core/paragraph',
27
23
  attributes: {
28
- customTextColor: '#fcb900',
29
- fontSize: 'large',
30
24
  content: __( 'Three.' ),
31
25
  },
32
26
  },
33
27
  {
34
28
  name: 'core/paragraph',
35
29
  attributes: {
36
- customTextColor: '#00d084',
37
- fontSize: 'large',
38
30
  content: __( 'Four.' ),
39
31
  },
40
32
  },
41
33
  {
42
34
  name: 'core/paragraph',
43
35
  attributes: {
44
- customTextColor: '#0693e3',
45
- fontSize: 'large',
46
36
  content: __( 'Five.' ),
47
37
  },
48
38
  },
49
39
  {
50
40
  name: 'core/paragraph',
51
41
  attributes: {
52
- customTextColor: '#9b51e0',
53
- fontSize: 'large',
54
42
  content: __( 'Six.' ),
55
43
  },
56
44
  },
@@ -706,7 +706,8 @@ export default function Image( {
706
706
  ! lockHrefControls &&
707
707
  ! lockUrlControls;
708
708
 
709
- const showCoverControls = isSingleSelected && canInsertCover;
709
+ const showCoverControls =
710
+ isSingleSelected && canInsertCover && ! isContentOnlyMode;
710
711
 
711
712
  const showBlockControls = showUrlInput || allowCrop || showCoverControls;
712
713
 
@@ -1,5 +1,9 @@
1
1
  export const DEFAULT_BLOCK = {
2
2
  name: 'core/navigation-link',
3
+ attributes: {
4
+ kind: 'post-type',
5
+ type: 'page',
6
+ },
3
7
  };
4
8
 
5
9
  export const PRIORITIZED_INSERTER_BLOCKS = [
@@ -26,6 +26,7 @@ import {
26
26
  __experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown,
27
27
  __experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients,
28
28
  useBlockEditingMode,
29
+ BlockControls,
29
30
  } from '@wordpress/block-editor';
30
31
  import { EntityProvider, store as coreStore } from '@wordpress/core-data';
31
32
 
@@ -40,10 +41,13 @@ import {
40
41
  Button,
41
42
  Spinner,
42
43
  Notice,
44
+ ToolbarButton,
45
+ ToolbarGroup,
43
46
  } from '@wordpress/components';
44
47
  import { __ } from '@wordpress/i18n';
45
48
  import { speak } from '@wordpress/a11y';
46
- import { close, Icon } from '@wordpress/icons';
49
+ import { close, Icon, page } from '@wordpress/icons';
50
+ import { createBlock } from '@wordpress/blocks';
47
51
  import { useInstanceId } from '@wordpress/compose';
48
52
 
49
53
  /**
@@ -75,6 +79,48 @@ import AccessibleDescription from './accessible-description';
75
79
  import AccessibleMenuDescription from './accessible-menu-description';
76
80
  import { unlock } from '../../lock-unlock';
77
81
  import { useToolsPanelDropdownMenuProps } from '../../utils/hooks';
82
+ import { DEFAULT_BLOCK } from '../constants';
83
+
84
+ /**
85
+ * Component that renders the Add page button for the Navigation block.
86
+ *
87
+ * @param {Object} props Component props.
88
+ * @param {string} props.clientId Block client ID.
89
+ * @return {JSX.Element|null} The Add page button component or null if not applicable.
90
+ */
91
+ function NavigationAddPageButton( { clientId } ) {
92
+ const { insertBlock } = useDispatch( blockEditorStore );
93
+ const { getBlockCount } = useSelect( blockEditorStore );
94
+
95
+ const onAddPage = useCallback( () => {
96
+ // Get the current number of blocks to insert at the end
97
+ const blockCount = getBlockCount( clientId );
98
+
99
+ // Create a new navigation link block (default block)
100
+ const newBlock = createBlock( DEFAULT_BLOCK.name, {
101
+ kind: DEFAULT_BLOCK.attributes.kind,
102
+ type: DEFAULT_BLOCK.attributes.type,
103
+ } );
104
+
105
+ // Insert the block at the end of the navigation
106
+ insertBlock( newBlock, blockCount, clientId );
107
+ }, [ clientId, insertBlock, getBlockCount ] );
108
+
109
+ return (
110
+ <BlockControls>
111
+ <ToolbarGroup>
112
+ <ToolbarButton
113
+ name="add-page"
114
+ icon={ page }
115
+ title={ __( 'Add page' ) }
116
+ onClick={ onAddPage }
117
+ >
118
+ { __( 'Add page' ) }
119
+ </ToolbarButton>
120
+ </ToolbarGroup>
121
+ </BlockControls>
122
+ );
123
+ }
78
124
 
79
125
  function ColorTools( {
80
126
  textColor,
@@ -937,6 +983,9 @@ function Navigation( {
937
983
  blockEditingMode={ blockEditingMode }
938
984
  />
939
985
  { blockEditingMode === 'default' && stylingInspectorControls }
986
+ { blockEditingMode === 'contentOnly' && isEntityAvailable && (
987
+ <NavigationAddPageButton clientId={ clientId } />
988
+ ) }
940
989
  { blockEditingMode === 'default' && isEntityAvailable && (
941
990
  <InspectorControls group="advanced">
942
991
  { hasResolvedCanUserUpdateNavigationMenu &&
@@ -146,7 +146,6 @@ export default function LeafMoreMenu( props ) {
146
146
  <AddSubmenuItem
147
147
  block={ block }
148
148
  onClose={ onClose }
149
- expanded
150
149
  expandedState={ props.expandedState }
151
150
  expand={ props.expand }
152
151
  setInsertedBlock={ props.setInsertedBlock }
@@ -35,7 +35,8 @@ const BLOCKS_WITH_LINK_UI_SUPPORT = [
35
35
  const { PrivateListView } = unlock( blockEditorPrivateApis );
36
36
 
37
37
  function AdditionalBlockContent( { block, insertedBlock, setInsertedBlock } ) {
38
- const { updateBlockAttributes } = useDispatch( blockEditorStore );
38
+ const { updateBlockAttributes, removeBlock } =
39
+ useDispatch( blockEditorStore );
39
40
 
40
41
  const supportsLinkControls = BLOCKS_WITH_LINK_UI_SUPPORT?.includes(
41
42
  insertedBlock?.name
@@ -47,6 +48,27 @@ function AdditionalBlockContent( { block, insertedBlock, setInsertedBlock } ) {
47
48
  return null;
48
49
  }
49
50
 
51
+ /**
52
+ * Cleanup function for auto-inserted Navigation Link blocks.
53
+ *
54
+ * Removes the block if it has no URL and clears the inserted block state.
55
+ * This ensures consistent cleanup behavior across different contexts.
56
+ */
57
+ const cleanupInsertedBlock = () => {
58
+ // Prevent automatic block selection when removing blocks in list view context
59
+ // This avoids focus stealing that would close the list view and switch to canvas
60
+ const shouldAutoSelectBlock = false;
61
+
62
+ // Follows the exact same pattern as Navigation Link block's onClose handler
63
+ // If there is no URL then remove the auto-inserted block to avoid empty blocks
64
+ if ( ! insertedBlock?.attributes?.url && insertedBlock?.clientId ) {
65
+ // Remove the block entirely to avoid poor UX
66
+ // This matches the Navigation Link block's behavior
67
+ removeBlock( insertedBlock.clientId, shouldAutoSelectBlock );
68
+ }
69
+ setInsertedBlock( null );
70
+ };
71
+
50
72
  const setInsertedBlockAttributes =
51
73
  ( _insertedBlockClientId ) => ( _updatedAttributes ) => {
52
74
  if ( ! _insertedBlockClientId ) {
@@ -55,12 +77,28 @@ function AdditionalBlockContent( { block, insertedBlock, setInsertedBlock } ) {
55
77
  updateBlockAttributes( _insertedBlockClientId, _updatedAttributes );
56
78
  };
57
79
 
80
+ // Wrapper function to clean up original block when a new block is selected
81
+ const handleSetInsertedBlock = ( newBlock ) => {
82
+ // Prevent automatic block selection when removing blocks in list view context
83
+ // This avoids focus stealing that would close the list view and switch to canvas
84
+ const shouldAutoSelectBlock = false;
85
+
86
+ // If we have an existing inserted block and a new block is being set,
87
+ // remove the original block to avoid duplicates
88
+ if ( insertedBlock?.clientId && newBlock ) {
89
+ removeBlock( insertedBlock.clientId, shouldAutoSelectBlock );
90
+ }
91
+ setInsertedBlock( newBlock );
92
+ };
93
+
58
94
  return (
59
95
  <LinkUI
60
96
  clientId={ insertedBlock?.clientId }
61
97
  link={ insertedBlock?.attributes }
98
+ onBlockInsert={ handleSetInsertedBlock }
62
99
  onClose={ () => {
63
- setInsertedBlock( null );
100
+ // Use cleanup function
101
+ cleanupInsertedBlock();
64
102
  } }
65
103
  onChange={ ( updatedValue ) => {
66
104
  updateAttributes(
@@ -70,9 +108,6 @@ function AdditionalBlockContent( { block, insertedBlock, setInsertedBlock } ) {
70
108
  );
71
109
  setInsertedBlock( null );
72
110
  } }
73
- onCancel={ () => {
74
- setInsertedBlock( null );
75
- } }
76
111
  />
77
112
  );
78
113
  }