@wordpress/block-library 8.23.0 → 8.24.1

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 (136) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/block/edit.js +8 -11
  3. package/build/block/edit.js.map +1 -1
  4. package/build/block/edit.native.js +3 -4
  5. package/build/block/edit.native.js.map +1 -1
  6. package/build/button/edit.js +4 -7
  7. package/build/button/edit.js.map +1 -1
  8. package/build/column/edit.js +1 -1
  9. package/build/column/edit.js.map +1 -1
  10. package/build/column/edit.native.js +1 -1
  11. package/build/column/edit.native.js.map +1 -1
  12. package/build/cover/edit/index.js +2 -1
  13. package/build/cover/edit/index.js.map +1 -1
  14. package/build/file/edit.js +8 -9
  15. package/build/file/edit.js.map +1 -1
  16. package/build/file/view.js +4 -6
  17. package/build/file/view.js.map +1 -1
  18. package/build/group/edit.js +3 -7
  19. package/build/group/edit.js.map +1 -1
  20. package/build/image/edit.js +17 -18
  21. package/build/image/edit.js.map +1 -1
  22. package/build/image/edit.native.js +22 -15
  23. package/build/image/edit.native.js.map +1 -1
  24. package/build/image/image.js +35 -27
  25. package/build/image/image.js.map +1 -1
  26. package/build/image/index.js +2 -3
  27. package/build/image/index.js.map +1 -1
  28. package/build/image/view.js +233 -268
  29. package/build/image/view.js.map +1 -1
  30. package/build/navigation/view.js +153 -176
  31. package/build/navigation/view.js.map +1 -1
  32. package/build/navigation-link/index.js +2 -1
  33. package/build/navigation-link/index.js.map +1 -1
  34. package/build/pattern/edit.js +1 -3
  35. package/build/pattern/edit.js.map +1 -1
  36. package/build/post-template/edit.js +1 -1
  37. package/build/post-template/edit.js.map +1 -1
  38. package/build/query/view.js +52 -60
  39. package/build/query/view.js.map +1 -1
  40. package/build/search/view.js +66 -74
  41. package/build/search/view.js.map +1 -1
  42. package/build/utils/remove-anchor-tag.js +17 -0
  43. package/build/utils/remove-anchor-tag.js.map +1 -0
  44. package/build-module/block/edit.js +8 -11
  45. package/build-module/block/edit.js.map +1 -1
  46. package/build-module/block/edit.native.js +3 -4
  47. package/build-module/block/edit.native.js.map +1 -1
  48. package/build-module/button/edit.js +4 -7
  49. package/build-module/button/edit.js.map +1 -1
  50. package/build-module/column/edit.js +1 -1
  51. package/build-module/column/edit.js.map +1 -1
  52. package/build-module/column/edit.native.js +1 -1
  53. package/build-module/column/edit.native.js.map +1 -1
  54. package/build-module/cover/edit/index.js +2 -1
  55. package/build-module/cover/edit/index.js.map +1 -1
  56. package/build-module/file/edit.js +8 -9
  57. package/build-module/file/edit.js.map +1 -1
  58. package/build-module/file/view.js +5 -7
  59. package/build-module/file/view.js.map +1 -1
  60. package/build-module/group/edit.js +3 -7
  61. package/build-module/group/edit.js.map +1 -1
  62. package/build-module/image/edit.js +18 -19
  63. package/build-module/image/edit.js.map +1 -1
  64. package/build-module/image/edit.native.js +23 -16
  65. package/build-module/image/edit.native.js.map +1 -1
  66. package/build-module/image/image.js +36 -28
  67. package/build-module/image/image.js.map +1 -1
  68. package/build-module/image/index.js +2 -3
  69. package/build-module/image/index.js.map +1 -1
  70. package/build-module/image/view.js +234 -269
  71. package/build-module/image/view.js.map +1 -1
  72. package/build-module/navigation/view.js +154 -177
  73. package/build-module/navigation/view.js.map +1 -1
  74. package/build-module/navigation-link/index.js +2 -1
  75. package/build-module/navigation-link/index.js.map +1 -1
  76. package/build-module/pattern/edit.js +1 -3
  77. package/build-module/pattern/edit.js.map +1 -1
  78. package/build-module/post-template/edit.js +1 -1
  79. package/build-module/post-template/edit.js.map +1 -1
  80. package/build-module/query/view.js +53 -61
  81. package/build-module/query/view.js.map +1 -1
  82. package/build-module/search/view.js +67 -75
  83. package/build-module/search/view.js.map +1 -1
  84. package/build-module/utils/remove-anchor-tag.js +11 -0
  85. package/build-module/utils/remove-anchor-tag.js.map +1 -0
  86. package/build-style/cover/style-rtl.css +14 -14
  87. package/build-style/cover/style.css +14 -14
  88. package/build-style/editor-rtl.css +6 -9
  89. package/build-style/editor.css +6 -9
  90. package/build-style/gallery/style-rtl.css +28 -0
  91. package/build-style/gallery/style.css +28 -0
  92. package/build-style/image/editor-rtl.css +0 -3
  93. package/build-style/image/editor.css +0 -3
  94. package/build-style/style-rtl.css +42 -14
  95. package/build-style/style.css +42 -14
  96. package/package.json +32 -32
  97. package/src/block/edit.js +18 -19
  98. package/src/block/edit.native.js +5 -13
  99. package/src/button/edit.js +6 -6
  100. package/src/buttons/test/__snapshots__/edit.native.js.snap +0 -6
  101. package/src/buttons/test/edit.native.js +0 -27
  102. package/src/column/edit.js +1 -1
  103. package/src/column/edit.native.js +1 -1
  104. package/src/cover/edit/index.js +1 -0
  105. package/src/cover/style.scss +1 -1
  106. package/src/cover/test/edit.js +1 -1
  107. package/src/editor.scss +6 -6
  108. package/src/file/edit.js +11 -10
  109. package/src/file/index.php +30 -11
  110. package/src/file/view.js +5 -7
  111. package/src/gallery/style.scss +1 -0
  112. package/src/group/edit.js +3 -11
  113. package/src/heading/test/__snapshots__/index.native.js.snap +6 -0
  114. package/src/heading/test/index.native.js +40 -0
  115. package/src/image/block.json +2 -3
  116. package/src/image/edit.js +16 -21
  117. package/src/image/edit.native.js +17 -18
  118. package/src/image/editor.scss +0 -7
  119. package/src/image/image.js +48 -51
  120. package/src/image/index.php +54 -45
  121. package/src/image/view.js +278 -334
  122. package/src/navigation/index.php +19 -10
  123. package/src/navigation/view.js +159 -192
  124. package/src/navigation-link/block.json +2 -1
  125. package/src/paragraph/test/edit.native.js +37 -1
  126. package/src/pattern/edit.js +5 -3
  127. package/src/post-template/edit.js +1 -1
  128. package/src/query/index.php +36 -22
  129. package/src/query/view.js +58 -65
  130. package/src/query-pagination-next/index.php +3 -3
  131. package/src/query-pagination-numbers/index.php +1 -1
  132. package/src/query-pagination-previous/index.php +3 -3
  133. package/src/search/index.php +40 -40
  134. package/src/search/view.js +58 -63
  135. package/src/utils/remove-anchor-tag.js +10 -0
  136. package/tsconfig.json +1 -0
@@ -123,7 +123,7 @@
123
123
  h4,
124
124
  h5,
125
125
  h6 {
126
- &:not(.has-text-color) {
126
+ &:where(:not(.has-text-color)) {
127
127
  color: inherit;
128
128
  }
129
129
  }
@@ -53,7 +53,7 @@ async function createAndSelectBlock() {
53
53
  );
54
54
  await userEvent.click(
55
55
  screen.getByRole( 'button', {
56
- name: 'Select Cover',
56
+ name: 'Select parent block: Cover',
57
57
  } )
58
58
  );
59
59
  }
package/src/editor.scss CHANGED
@@ -65,7 +65,7 @@
65
65
 
66
66
  // This CSS Custom Properties aren't used anymore as defaults,
67
67
  // but we still need to keep them for backward compatibility.
68
- .editor-styles-wrapper {
68
+ :where(.editor-styles-wrapper) {
69
69
  --wp--preset--font-size--normal: 16px;
70
70
  --wp--preset--font-size--huge: 42px;
71
71
  }
@@ -74,19 +74,19 @@
74
74
  //
75
75
  // The reason we add the editor class wrapper here is
76
76
  // to avoid enqueing the classes twice: here and in ./editor.scss
77
- .editor-styles-wrapper .has-regular-font-size {
77
+ :where(.editor-styles-wrapper) .has-regular-font-size {
78
78
  font-size: 16px;
79
79
  }
80
80
 
81
- .editor-styles-wrapper .has-larger-font-size {
81
+ :where(.editor-styles-wrapper) .has-larger-font-size {
82
82
  font-size: 42px;
83
83
  }
84
84
 
85
- .editor-styles-wrapper .has-normal-font-size {
85
+ :where(.editor-styles-wrapper) .has-normal-font-size {
86
86
  font-size: var(--wp--preset--font-size--normal);
87
87
  }
88
88
 
89
- .editor-styles-wrapper .has-huge-font-size {
89
+ :where(.editor-styles-wrapper) .has-huge-font-size {
90
90
  font-size: var(--wp--preset--font-size--huge);
91
91
  }
92
92
 
@@ -98,6 +98,6 @@
98
98
  */
99
99
 
100
100
  // Remove the browser default border for iframe in Custom HTML block, Embed block, etc.
101
- .editor-styles-wrapper iframe:not([frameborder]) {
101
+ :where(.editor-styles-wrapper) iframe:not([frameborder]) {
102
102
  border: 0;
103
103
  }
package/src/file/edit.js CHANGED
@@ -35,6 +35,7 @@ import { store as noticesStore } from '@wordpress/notices';
35
35
  */
36
36
  import FileBlockInspector from './inspector';
37
37
  import { browserSupportsPdfs } from './utils';
38
+ import removeAnchorTag from '../utils/remove-anchor-tag';
38
39
 
39
40
  export const MIN_PREVIEW_HEIGHT = 200;
40
41
  export const MAX_PREVIEW_HEIGHT = 2000;
@@ -102,7 +103,9 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) {
102
103
  }
103
104
 
104
105
  if ( downloadButtonText === undefined ) {
105
- changeDownloadButtonText( _x( 'Download', 'button label' ) );
106
+ setAttributes( {
107
+ downloadButtonText: _x( 'Download', 'button label' ),
108
+ } );
106
109
  }
107
110
  }, [] );
108
111
 
@@ -148,13 +151,6 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) {
148
151
  setAttributes( { showDownloadButton: newValue } );
149
152
  }
150
153
 
151
- function changeDownloadButtonText( newValue ) {
152
- // Remove anchor tags from button text content.
153
- setAttributes( {
154
- downloadButtonText: newValue.replace( /<\/?a[^>]*>/g, '' ),
155
- } );
156
- }
157
-
158
154
  function changeDisplayPreview( newValue ) {
159
155
  setAttributes( { displayPreview: newValue } );
160
156
  }
@@ -277,7 +273,9 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) {
277
273
  placeholder={ __( 'Write file name…' ) }
278
274
  withoutInteractiveFormatting
279
275
  onChange={ ( text ) =>
280
- setAttributes( { fileName: text } )
276
+ setAttributes( {
277
+ fileName: removeAnchorTag( text ),
278
+ } )
281
279
  }
282
280
  href={ textLinkHref }
283
281
  />
@@ -301,7 +299,10 @@ function FileEdit( { attributes, isSelected, setAttributes, clientId } ) {
301
299
  withoutInteractiveFormatting
302
300
  placeholder={ __( 'Add text…' ) }
303
301
  onChange={ ( text ) =>
304
- changeDownloadButtonText( text )
302
+ setAttributes( {
303
+ downloadButtonText:
304
+ removeAnchorTag( text ),
305
+ } )
305
306
  }
306
307
  />
307
308
  </div>
@@ -15,19 +15,29 @@
15
15
  * @return string Returns the block content.
16
16
  */
17
17
  function render_block_core_file( $attributes, $content, $block ) {
18
+ $is_gutenberg_plugin = defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN;
18
19
  $should_load_view_script = ! empty( $attributes['displayPreview'] );
19
20
  $view_js_file = 'wp-block-file-view';
20
- // If the script already exists, there is no point in removing it from viewScript.
21
- if ( ! wp_script_is( $view_js_file ) ) {
22
- $script_handles = $block->block_type->view_script_handles;
21
+ $script_handles = $block->block_type->view_script_handles;
23
22
 
24
- // If the script is not needed, and it is still in the `view_script_handles`, remove it.
25
- if ( ! $should_load_view_script && in_array( $view_js_file, $script_handles, true ) ) {
26
- $block->block_type->view_script_handles = array_diff( $script_handles, array( $view_js_file ) );
23
+ if ( $is_gutenberg_plugin ) {
24
+ if ( $should_load_view_script ) {
25
+ gutenberg_enqueue_module( '@wordpress/block-library/file-block' );
27
26
  }
28
- // If the script is needed, but it was previously removed, add it again.
29
- if ( $should_load_view_script && ! in_array( $view_js_file, $script_handles, true ) ) {
30
- $block->block_type->view_script_handles = array_merge( $script_handles, array( $view_js_file ) );
27
+ // Remove the view script because we are using the module.
28
+ $block->block_type->view_script_handles = array_diff( $script_handles, array( $view_js_file ) );
29
+ } else {
30
+ // If the script already exists, there is no point in removing it from viewScript.
31
+ if ( ! wp_script_is( $view_js_file ) ) {
32
+
33
+ // If the script is not needed, and it is still in the `view_script_handles`, remove it.
34
+ if ( ! $should_load_view_script && in_array( $view_js_file, $script_handles, true ) ) {
35
+ $block->block_type->view_script_handles = array_diff( $script_handles, array( $view_js_file ) );
36
+ }
37
+ // If the script is needed, but it was previously removed, add it again.
38
+ if ( $should_load_view_script && ! in_array( $view_js_file, $script_handles, true ) ) {
39
+ $block->block_type->view_script_handles = array_merge( $script_handles, array( $view_js_file ) );
40
+ }
31
41
  }
32
42
  }
33
43
 
@@ -57,9 +67,9 @@ function render_block_core_file( $attributes, $content, $block ) {
57
67
  if ( $should_load_view_script ) {
58
68
  $processor = new WP_HTML_Tag_Processor( $content );
59
69
  $processor->next_tag();
60
- $processor->set_attribute( 'data-wp-interactive', '' );
70
+ $processor->set_attribute( 'data-wp-interactive', '{"namespace":"core/file"}' );
61
71
  $processor->next_tag( 'object' );
62
- $processor->set_attribute( 'data-wp-bind--hidden', '!selectors.core.file.hasPdfPreview' );
72
+ $processor->set_attribute( 'data-wp-bind--hidden', '!state.hasPdfPreview' );
63
73
  $processor->set_attribute( 'hidden', true );
64
74
  return $processor->get_updated_html();
65
75
  }
@@ -96,5 +106,14 @@ function register_block_core_file() {
96
106
  'render_callback' => 'render_block_core_file',
97
107
  )
98
108
  );
109
+
110
+ if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
111
+ gutenberg_register_module(
112
+ '@wordpress/block-library/file-block',
113
+ gutenberg_url( '/build/interactivity/file.min.js' ),
114
+ array( '@wordpress/interactivity' ),
115
+ defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
116
+ );
117
+ }
99
118
  }
100
119
  add_action( 'init', 'register_block_core_file' );
package/src/file/view.js CHANGED
@@ -5,14 +5,12 @@ import { store } from '@wordpress/interactivity';
5
5
  /**
6
6
  * Internal dependencies
7
7
  */
8
- import { browserSupportsPdfs as hasPdfPreview } from './utils';
8
+ import { browserSupportsPdfs } from './utils';
9
9
 
10
- store( {
11
- selectors: {
12
- core: {
13
- file: {
14
- hasPdfPreview,
15
- },
10
+ store( 'core/file', {
11
+ state: {
12
+ get hasPdfPreview() {
13
+ return browserSupportsPdfs();
16
14
  },
17
15
  },
18
16
  } );
@@ -57,6 +57,7 @@ figure.wp-block-gallery.has-nested-images {
57
57
  text-align: center;
58
58
  width: 100%;
59
59
  box-sizing: border-box;
60
+ @include custom-scrollbars-on-hover(transparent, rgba($white, 0.8));
60
61
 
61
62
  img {
62
63
  display: inline;
package/src/group/edit.js CHANGED
@@ -71,13 +71,7 @@ function GroupEditControls( { tagName, onSelectTagName } ) {
71
71
  );
72
72
  }
73
73
 
74
- function GroupEdit( {
75
- attributes,
76
- name,
77
- setAttributes,
78
- clientId,
79
- __unstableLayoutClassNames: layoutClassNames,
80
- } ) {
74
+ function GroupEdit( { attributes, name, setAttributes, clientId } ) {
81
75
  const { hasInnerBlocks, themeSupportsLayout } = useSelect(
82
76
  ( select ) => {
83
77
  const { getBlock, getSettings } = select( blockEditorStore );
@@ -103,9 +97,8 @@ function GroupEdit( {
103
97
  themeSupportsLayout || type === 'flex' || type === 'grid';
104
98
 
105
99
  // Hooks.
106
- const blockProps = useBlockProps( {
107
- className: ! layoutSupportEnabled ? layoutClassNames : null,
108
- } );
100
+ const blockProps = useBlockProps();
101
+
109
102
  const [ showPlaceholder, setShowPlaceholder ] = useShouldShowPlaceHolder( {
110
103
  attributes,
111
104
  usedLayoutType: type,
@@ -134,7 +127,6 @@ function GroupEdit( {
134
127
  templateLock,
135
128
  allowedBlocks,
136
129
  renderAppender,
137
- __unstableDisableLayoutClassNames: ! layoutSupportEnabled,
138
130
  }
139
131
  );
140
132
 
@@ -6,6 +6,12 @@ exports[`Heading block inserts block 1`] = `
6
6
  <!-- /wp:heading -->"
7
7
  `;
8
8
 
9
+ exports[`Heading block should merge with an empty Paragraph block and keep being the Heading block 1`] = `
10
+ "<!-- wp:heading -->
11
+ <h2 class="wp-block-heading">A quick brown fox jumps over the lazy dog.</h2>
12
+ <!-- /wp:heading -->"
13
+ `;
14
+
9
15
  exports[`Heading block should set a background color 1`] = `
10
16
  "<!-- wp:heading {"backgroundColor":"luminous-vivid-orange"} -->
11
17
  <h2 class="wp-block-heading has-luminous-vivid-orange-background-color has-background">A quick brown fox jumps over the lazy dog.</h2>
@@ -17,6 +17,7 @@ import {
17
17
  */
18
18
  import { getBlockTypes, unregisterBlockType } from '@wordpress/blocks';
19
19
  import { registerCoreBlocks } from '@wordpress/block-library';
20
+ import { BACKSPACE, ENTER } from '@wordpress/keycodes';
20
21
 
21
22
  beforeAll( () => {
22
23
  // Register all core blocks
@@ -134,4 +135,43 @@ describe( 'Heading block', () => {
134
135
  )
135
136
  ).toBeVisible();
136
137
  } );
138
+
139
+ it( 'should merge with an empty Paragraph block and keep being the Heading block', async () => {
140
+ // Arrange
141
+ const screen = await initializeEditor();
142
+ await addBlock( screen, 'Paragraph' );
143
+
144
+ // Act
145
+ const paragraphBlock = getBlock( screen, 'Paragraph' );
146
+ fireEvent.press( paragraphBlock );
147
+
148
+ const paragraphTextInput =
149
+ within( paragraphBlock ).getByPlaceholderText( 'Start writing…' );
150
+ fireEvent( paragraphTextInput, 'onKeyDown', {
151
+ nativeEvent: {},
152
+ preventDefault() {},
153
+ keyCode: ENTER,
154
+ } );
155
+
156
+ await addBlock( screen, 'Heading' );
157
+ const headingBlock = getBlock( screen, 'Heading', { rowIndex: 2 } );
158
+ fireEvent.press( headingBlock );
159
+
160
+ const headingTextInput =
161
+ within( headingBlock ).getByPlaceholderText( 'Heading' );
162
+ typeInRichText(
163
+ headingTextInput,
164
+ 'A quick brown fox jumps over the lazy dog.',
165
+ { finalSelectionStart: 0, finalSelectionEnd: 0 }
166
+ );
167
+
168
+ fireEvent( headingTextInput, 'onKeyDown', {
169
+ nativeEvent: {},
170
+ preventDefault() {},
171
+ keyCode: BACKSPACE,
172
+ } );
173
+
174
+ // Assert
175
+ expect( getEditorHtml() ).toMatchSnapshot();
176
+ } );
137
177
  } );
@@ -9,9 +9,6 @@
9
9
  "keywords": [ "img", "photo", "picture" ],
10
10
  "textdomain": "default",
11
11
  "attributes": {
12
- "align": {
13
- "type": "string"
14
- },
15
12
  "url": {
16
13
  "type": "string",
17
14
  "source": "attribute",
@@ -95,6 +92,8 @@
95
92
  }
96
93
  },
97
94
  "supports": {
95
+ "interactivity": true,
96
+ "align": [ "left", "center", "right", "wide", "full" ],
98
97
  "anchor": true,
99
98
  "color": {
100
99
  "text": false,
package/src/image/edit.js CHANGED
@@ -10,8 +10,6 @@ import { getBlobByURL, isBlobURL, revokeBlobURL } from '@wordpress/blob';
10
10
  import { Placeholder } from '@wordpress/components';
11
11
  import { useDispatch, useSelect } from '@wordpress/data';
12
12
  import {
13
- BlockAlignmentControl,
14
- BlockControls,
15
13
  BlockIcon,
16
14
  MediaPlaceholder,
17
15
  useBlockProps,
@@ -106,13 +104,13 @@ export function ImageEdit( {
106
104
  url = '',
107
105
  alt,
108
106
  caption,
109
- align,
110
107
  id,
111
108
  width,
112
109
  height,
113
110
  sizeSlug,
114
111
  aspectRatio,
115
112
  scale,
113
+ align,
116
114
  } = attributes;
117
115
  const [ temporaryURL, setTemporaryURL ] = useState();
118
116
 
@@ -126,6 +124,21 @@ export function ImageEdit( {
126
124
  captionRef.current = caption;
127
125
  }, [ caption ] );
128
126
 
127
+ const { __unstableMarkNextChangeAsNotPersistent } =
128
+ useDispatch( blockEditorStore );
129
+
130
+ useEffect( () => {
131
+ if ( [ 'wide', 'full' ].includes( align ) ) {
132
+ __unstableMarkNextChangeAsNotPersistent();
133
+ setAttributes( {
134
+ width: undefined,
135
+ height: undefined,
136
+ aspectRatio: undefined,
137
+ scale: undefined,
138
+ } );
139
+ }
140
+ }, [ align ] );
141
+
129
142
  const ref = useRef();
130
143
  const { imageDefaultSize, mediaUpload } = useSelect( ( select ) => {
131
144
  const { getSettings } = select( blockEditorStore );
@@ -255,16 +268,6 @@ export function ImageEdit( {
255
268
  }
256
269
  }
257
270
 
258
- function updateAlignment( nextAlign ) {
259
- const extraUpdatedAttributes = [ 'wide', 'full' ].includes( nextAlign )
260
- ? { width: undefined, height: undefined }
261
- : {};
262
- setAttributes( {
263
- ...extraUpdatedAttributes,
264
- align: nextAlign,
265
- } );
266
- }
267
-
268
271
  let isTemp = isTemporaryImage( id, url );
269
272
 
270
273
  // Upload a temporary image on mount.
@@ -375,14 +378,6 @@ export function ImageEdit( {
375
378
  clientId={ clientId }
376
379
  blockEditingMode={ blockEditingMode }
377
380
  />
378
- { ! url && blockEditingMode === 'default' && (
379
- <BlockControls group="block">
380
- <BlockAlignmentControl
381
- value={ align }
382
- onChange={ updateAlignment }
383
- />
384
- </BlockControls>
385
- ) }
386
381
  <MediaPlaceholder
387
382
  icon={ <BlockIcon icon={ icon } /> }
388
383
  onSelect={ onSelectImage }
@@ -44,7 +44,6 @@ import {
44
44
  MEDIA_TYPE_IMAGE,
45
45
  BlockControls,
46
46
  InspectorControls,
47
- BlockAlignmentToolbar,
48
47
  BlockStyles,
49
48
  store as blockEditorStore,
50
49
  blockSettingsScreens,
@@ -212,7 +211,6 @@ export class ImageEdit extends Component {
212
211
  this.onSetFeatured = this.onSetFeatured.bind( this );
213
212
  this.onFocusCaption = this.onFocusCaption.bind( this );
214
213
  this.onSelectURL = this.onSelectURL.bind( this );
215
- this.updateAlignment = this.updateAlignment.bind( this );
216
214
  this.accessibilityLabelCreator =
217
215
  this.accessibilityLabelCreator.bind( this );
218
216
  this.setMappedAttributes = this.setMappedAttributes.bind( this );
@@ -305,6 +303,20 @@ export class ImageEdit extends Component {
305
303
  this.replacedFeaturedImage = false;
306
304
  setFeaturedImage( id );
307
305
  }
306
+
307
+ const { align } = attributes;
308
+ const { __unstableMarkNextChangeAsNotPersistent } = this.props;
309
+
310
+ // Update the attributes if the align is wide or full
311
+ if ( [ 'wide', 'full' ].includes( align ) ) {
312
+ __unstableMarkNextChangeAsNotPersistent();
313
+ setAttributes( {
314
+ width: undefined,
315
+ height: undefined,
316
+ aspectRatio: undefined,
317
+ scale: undefined,
318
+ } );
319
+ }
308
320
  }
309
321
 
310
322
  static getDerivedStateFromProps( props, state ) {
@@ -391,18 +403,6 @@ export class ImageEdit extends Component {
391
403
  } );
392
404
  }
393
405
 
394
- updateAlignment( nextAlign ) {
395
- const extraUpdatedAttributes = Object.values(
396
- WIDE_ALIGNMENTS.alignments
397
- ).includes( nextAlign )
398
- ? { width: undefined, height: undefined }
399
- : {};
400
- this.props.setAttributes( {
401
- ...extraUpdatedAttributes,
402
- align: nextAlign,
403
- } );
404
- }
405
-
406
406
  onSetNewTab( value ) {
407
407
  const updatedLinkTarget = getUpdatedLinkTargetSettings(
408
408
  value,
@@ -711,10 +711,6 @@ export class ImageEdit extends Component {
711
711
  onClick={ open }
712
712
  />
713
713
  </ToolbarGroup>
714
- <BlockAlignmentToolbar
715
- value={ align }
716
- onChange={ this.updateAlignment }
717
- />
718
714
  </BlockControls>
719
715
  );
720
716
 
@@ -941,8 +937,11 @@ export default compose( [
941
937
  } ),
942
938
  withDispatch( ( dispatch ) => {
943
939
  const { createErrorNotice } = dispatch( noticesStore );
940
+ const { __unstableMarkNextChangeAsNotPersistent } =
941
+ dispatch( blockEditorStore );
944
942
 
945
943
  return {
944
+ __unstableMarkNextChangeAsNotPersistent,
946
945
  createErrorNotice,
947
946
  closeSettingsBottomSheet() {
948
947
  dispatch( editPostStore ).closeGeneralSidebar();
@@ -62,13 +62,6 @@ figure.wp-block-image:not(.wp-block) {
62
62
  left: 50%;
63
63
  transform: translate(-50%, -50%);
64
64
  }
65
-
66
- // When the Image block is linked,
67
- // it's wrapped with a disabled <a /> tag.
68
- // Restore cursor style so it doesn't appear 'clickable'.
69
- > a {
70
- cursor: default;
71
- }
72
65
  }
73
66
 
74
67
  // This is necessary for the editor resize handles to accurately work on a non-floated, non-resized, small image.
@@ -25,7 +25,6 @@ import {
25
25
  MediaReplaceFlow,
26
26
  store as blockEditorStore,
27
27
  useSettings,
28
- BlockAlignmentControl,
29
28
  __experimentalImageEditor as ImageEditor,
30
29
  __experimentalGetElementClassName,
31
30
  __experimentalUseBorderProps as useBorderProps,
@@ -83,9 +82,29 @@ const scaleOptions = [
83
82
  },
84
83
  ];
85
84
 
86
- const disabledClickProps = {
87
- onClick: ( event ) => event.preventDefault(),
88
- 'aria-disabled': true,
85
+ // If the image has a href, wrap in an <a /> tag to trigger any inherited link element styles.
86
+ const ImageWrapper = ( { href, children } ) => {
87
+ if ( ! href ) {
88
+ return children;
89
+ }
90
+ return (
91
+ <a
92
+ href={ href }
93
+ onClick={ ( event ) => event.preventDefault() }
94
+ aria-disabled={ true }
95
+ style={ {
96
+ // When the Image block is linked,
97
+ // it's wrapped with a disabled <a /> tag.
98
+ // Restore cursor style so it doesn't appear 'clickable'
99
+ // and remove pointer events. Safari needs the display property.
100
+ pointerEvents: 'none',
101
+ cursor: 'default',
102
+ display: 'inline',
103
+ } }
104
+ >
105
+ { children }
106
+ </a>
107
+ );
89
108
  };
90
109
 
91
110
  export default function Image( {
@@ -333,21 +352,6 @@ export default function Image( {
333
352
  } );
334
353
  }
335
354
 
336
- function updateAlignment( nextAlign ) {
337
- const extraUpdatedAttributes = [ 'wide', 'full' ].includes( nextAlign )
338
- ? {
339
- width: undefined,
340
- height: undefined,
341
- aspectRatio: undefined,
342
- scale: undefined,
343
- }
344
- : {};
345
- setAttributes( {
346
- ...extraUpdatedAttributes,
347
- align: nextAlign,
348
- } );
349
- }
350
-
351
355
  useEffect( () => {
352
356
  if ( ! isSelected ) {
353
357
  setIsEditingImage( false );
@@ -435,12 +439,6 @@ export default function Image( {
435
439
  const controls = (
436
440
  <>
437
441
  <BlockControls group="block">
438
- { hasNonContentControls && (
439
- <BlockAlignmentControl
440
- value={ align }
441
- onChange={ updateAlignment }
442
- />
443
- ) }
444
442
  { hasNonContentControls && (
445
443
  <ToolbarButton
446
444
  onClick={ () => {
@@ -653,25 +651,31 @@ export default function Image( {
653
651
 
654
652
  if ( canEditImage && isEditingImage ) {
655
653
  img = (
656
- <ImageEditor
657
- id={ id }
658
- url={ url }
659
- width={ numericWidth }
660
- height={ numericHeight }
661
- clientWidth={ fallbackClientWidth }
662
- naturalHeight={ naturalHeight }
663
- naturalWidth={ naturalWidth }
664
- onSaveImage={ ( imageAttributes ) =>
665
- setAttributes( imageAttributes )
666
- }
667
- onFinishEditing={ () => {
668
- setIsEditingImage( false );
669
- } }
670
- borderProps={ isRounded ? undefined : borderProps }
671
- />
654
+ <ImageWrapper href={ href }>
655
+ <ImageEditor
656
+ id={ id }
657
+ url={ url }
658
+ width={ numericWidth }
659
+ height={ numericHeight }
660
+ clientWidth={ fallbackClientWidth }
661
+ naturalHeight={ naturalHeight }
662
+ naturalWidth={ naturalWidth }
663
+ onSaveImage={ ( imageAttributes ) =>
664
+ setAttributes( imageAttributes )
665
+ }
666
+ onFinishEditing={ () => {
667
+ setIsEditingImage( false );
668
+ } }
669
+ borderProps={ isRounded ? undefined : borderProps }
670
+ />
671
+ </ImageWrapper>
672
672
  );
673
673
  } else if ( ! isResizable ) {
674
- img = <div style={ { width, height, aspectRatio } }>{ img }</div>;
674
+ img = (
675
+ <div style={ { width, height, aspectRatio } }>
676
+ <ImageWrapper href={ href }>{ img }</ImageWrapper>
677
+ </div>
678
+ );
675
679
  } else {
676
680
  const numericRatio = aspectRatio && evalAspectRatio( aspectRatio );
677
681
  const customRatio = numericWidth / numericHeight;
@@ -774,7 +778,7 @@ export default function Image( {
774
778
  } }
775
779
  resizeRatio={ align === 'center' ? 2 : 1 }
776
780
  >
777
- { img }
781
+ <ImageWrapper href={ href }>{ img }</ImageWrapper>
778
782
  </ResizableBox>
779
783
  );
780
784
  }
@@ -788,14 +792,7 @@ export default function Image( {
788
792
  { /* Hide controls during upload to avoid component remount,
789
793
  which causes duplicated image upload. */ }
790
794
  { ! temporaryURL && controls }
791
- { /* If the image has a href, wrap in an <a /> tag to trigger any inherited link element styles */ }
792
- { !! href ? (
793
- <a href={ href } { ...disabledClickProps }>
794
- { img }
795
- </a>
796
- ) : (
797
- img
798
- ) }
795
+ { img }
799
796
  { showCaption &&
800
797
  ( ! RichText.isEmpty( caption ) || isSelected ) && (
801
798
  <RichText