@wordpress/block-library 9.45.0 → 9.45.1-next.v.202605131032.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 (84) hide show
  1. package/build/breadcrumbs/edit.cjs +1 -1
  2. package/build/breadcrumbs/edit.cjs.map +1 -1
  3. package/build/buttons/edit.cjs +0 -13
  4. package/build/buttons/edit.cjs.map +3 -3
  5. package/build/comment-reply-link/edit.cjs +2 -1
  6. package/build/comment-reply-link/edit.cjs.map +2 -2
  7. package/build/comments/edit/placeholder.cjs +2 -1
  8. package/build/comments/edit/placeholder.cjs.map +2 -2
  9. package/build/embed/transforms.cjs +24 -1
  10. package/build/embed/transforms.cjs.map +2 -2
  11. package/build/freeform/convert-to-blocks-button.cjs +2 -14
  12. package/build/freeform/convert-to-blocks-button.cjs.map +3 -3
  13. package/build/freeform/edit.cjs +43 -15
  14. package/build/freeform/edit.cjs.map +3 -3
  15. package/build/freeform/index.cjs +7 -1
  16. package/build/freeform/index.cjs.map +3 -3
  17. package/build/freeform/migration-notice.cjs +58 -0
  18. package/build/freeform/migration-notice.cjs.map +7 -0
  19. package/build/image/image.cjs +16 -52
  20. package/build/image/image.cjs.map +3 -3
  21. package/build/image/use-open-image-media-editor-modal.cjs +239 -0
  22. package/build/image/use-open-image-media-editor-modal.cjs.map +7 -0
  23. package/build/index.cjs +1 -5
  24. package/build/index.cjs.map +2 -2
  25. package/build/shortcode/transforms.cjs +27 -1
  26. package/build/shortcode/transforms.cjs.map +2 -2
  27. package/build/site-logo/edit.cjs +1 -0
  28. package/build/site-logo/edit.cjs.map +2 -2
  29. package/build/table/edit.cjs +2 -2
  30. package/build/table/edit.cjs.map +2 -2
  31. package/build-module/breadcrumbs/edit.mjs +1 -1
  32. package/build-module/breadcrumbs/edit.mjs.map +1 -1
  33. package/build-module/buttons/edit.mjs +0 -13
  34. package/build-module/buttons/edit.mjs.map +2 -2
  35. package/build-module/comment-reply-link/edit.mjs +3 -2
  36. package/build-module/comment-reply-link/edit.mjs.map +2 -2
  37. package/build-module/comments/edit/placeholder.mjs +3 -2
  38. package/build-module/comments/edit/placeholder.mjs.map +2 -2
  39. package/build-module/embed/transforms.mjs +24 -1
  40. package/build-module/embed/transforms.mjs.map +2 -2
  41. package/build-module/freeform/convert-to-blocks-button.mjs +3 -15
  42. package/build-module/freeform/convert-to-blocks-button.mjs.map +2 -2
  43. package/build-module/freeform/edit.mjs +44 -16
  44. package/build-module/freeform/edit.mjs.map +2 -2
  45. package/build-module/freeform/index.mjs +7 -1
  46. package/build-module/freeform/index.mjs.map +2 -2
  47. package/build-module/freeform/migration-notice.mjs +37 -0
  48. package/build-module/freeform/migration-notice.mjs.map +7 -0
  49. package/build-module/image/image.mjs +16 -52
  50. package/build-module/image/image.mjs.map +3 -3
  51. package/build-module/image/use-open-image-media-editor-modal.mjs +215 -0
  52. package/build-module/image/use-open-image-media-editor-modal.mjs.map +7 -0
  53. package/build-module/index.mjs +1 -5
  54. package/build-module/index.mjs.map +2 -2
  55. package/build-module/shortcode/transforms.mjs +27 -1
  56. package/build-module/shortcode/transforms.mjs.map +2 -2
  57. package/build-module/site-logo/edit.mjs +1 -0
  58. package/build-module/site-logo/edit.mjs.map +2 -2
  59. package/build-module/table/edit.mjs +3 -3
  60. package/build-module/table/edit.mjs.map +2 -2
  61. package/build-types/table-of-contents/list.d.ts +1 -1
  62. package/build-types/table-of-contents/list.d.ts.map +1 -1
  63. package/package.json +41 -40
  64. package/src/breadcrumbs/edit.js +1 -1
  65. package/src/buttons/edit.js +0 -13
  66. package/src/comment-reply-link/edit.js +5 -2
  67. package/src/comments/edit/placeholder.js +5 -2
  68. package/src/cover/editor.scss +2 -2
  69. package/src/cover/style.scss +10 -6
  70. package/src/embed/transforms.js +30 -4
  71. package/src/freeform/convert-to-blocks-button.js +3 -18
  72. package/src/freeform/edit.js +40 -7
  73. package/src/freeform/index.js +9 -1
  74. package/src/freeform/migration-notice.js +51 -0
  75. package/src/image/image.js +14 -63
  76. package/src/image/test/use-open-image-media-editor-modal.js +791 -0
  77. package/src/image/use-open-image-media-editor-modal.js +337 -0
  78. package/src/index.js +3 -16
  79. package/src/navigation/index.php +11 -1
  80. package/src/query/editor.scss +1 -2
  81. package/src/shortcode/transforms.js +37 -0
  82. package/src/site-logo/edit.js +5 -0
  83. package/src/table/edit.js +3 -3
  84. package/src/template-part/editor.scss +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/block-library",
3
- "version": "9.45.0",
3
+ "version": "9.45.1-next.v.202605131032.0+f6d6e7149",
4
4
  "description": "Block library for the WordPress editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -95,43 +95,44 @@
95
95
  ],
96
96
  "dependencies": {
97
97
  "@arraypress/waveform-player": "1.2.1",
98
- "@wordpress/a11y": "^4.45.0",
99
- "@wordpress/api-fetch": "^7.45.0",
100
- "@wordpress/autop": "^4.45.0",
101
- "@wordpress/base-styles": "^7.0.0",
102
- "@wordpress/blob": "^4.45.0",
103
- "@wordpress/block-editor": "^15.18.0",
104
- "@wordpress/blocks": "^15.18.0",
105
- "@wordpress/components": "^33.0.0",
106
- "@wordpress/compose": "^7.45.0",
107
- "@wordpress/core-data": "^7.45.0",
108
- "@wordpress/data": "^10.45.0",
109
- "@wordpress/date": "^5.45.0",
110
- "@wordpress/deprecated": "^4.45.0",
111
- "@wordpress/dom": "^4.45.0",
112
- "@wordpress/element": "^6.45.0",
113
- "@wordpress/escape-html": "^3.45.0",
114
- "@wordpress/hooks": "^4.45.0",
115
- "@wordpress/html-entities": "^4.45.0",
116
- "@wordpress/i18n": "^6.18.0",
117
- "@wordpress/icons": "^13.0.0",
118
- "@wordpress/interactivity": "^6.45.0",
119
- "@wordpress/interactivity-router": "^2.45.0",
120
- "@wordpress/keyboard-shortcuts": "^5.45.0",
121
- "@wordpress/keycodes": "^4.45.0",
122
- "@wordpress/latex-to-mathml": "^1.13.0",
123
- "@wordpress/notices": "^5.45.0",
124
- "@wordpress/patterns": "^2.45.0",
125
- "@wordpress/primitives": "^4.45.0",
126
- "@wordpress/private-apis": "^1.45.0",
127
- "@wordpress/reusable-blocks": "^5.45.0",
128
- "@wordpress/rich-text": "^7.45.0",
129
- "@wordpress/server-side-render": "^6.21.0",
130
- "@wordpress/ui": "^0.12.0",
131
- "@wordpress/upload-media": "^0.30.0",
132
- "@wordpress/url": "^4.45.0",
133
- "@wordpress/viewport": "^6.45.0",
134
- "@wordpress/wordcount": "^4.45.0",
98
+ "@wordpress/a11y": "^4.45.1-next.v.202605131032.0+f6d6e7149",
99
+ "@wordpress/api-fetch": "^7.45.1-next.v.202605131032.0+f6d6e7149",
100
+ "@wordpress/autop": "^4.45.1-next.v.202605131032.0+f6d6e7149",
101
+ "@wordpress/base-styles": "^8.0.1-next.v.202605131032.0+f6d6e7149",
102
+ "@wordpress/blob": "^4.45.1-next.v.202605131032.0+f6d6e7149",
103
+ "@wordpress/block-editor": "^15.19.1-next.v.202605131032.0+f6d6e7149",
104
+ "@wordpress/blocks": "^15.18.1-next.v.202605131032.0+f6d6e7149",
105
+ "@wordpress/components": "^33.1.1-next.v.202605131032.0+f6d6e7149",
106
+ "@wordpress/compose": "^7.45.1-next.v.202605131032.0+f6d6e7149",
107
+ "@wordpress/core-data": "^7.45.1-next.v.202605131032.0+f6d6e7149",
108
+ "@wordpress/data": "^10.45.1-next.v.202605131032.0+f6d6e7149",
109
+ "@wordpress/date": "^5.45.1-next.v.202605131032.0+f6d6e7149",
110
+ "@wordpress/deprecated": "^4.45.1-next.v.202605131032.0+f6d6e7149",
111
+ "@wordpress/dom": "^4.45.1-next.v.202605131032.0+f6d6e7149",
112
+ "@wordpress/element": "^6.45.1-next.v.202605131032.0+f6d6e7149",
113
+ "@wordpress/escape-html": "^3.45.1-next.v.202605131032.0+f6d6e7149",
114
+ "@wordpress/hooks": "^4.45.1-next.v.202605131032.0+f6d6e7149",
115
+ "@wordpress/html-entities": "^4.45.1-next.v.202605131032.0+f6d6e7149",
116
+ "@wordpress/i18n": "^6.18.1-next.v.202605131032.0+f6d6e7149",
117
+ "@wordpress/icons": "^13.0.1-next.v.202605131032.0+f6d6e7149",
118
+ "@wordpress/interactivity": "^6.45.1-next.v.202605131032.0+f6d6e7149",
119
+ "@wordpress/interactivity-router": "^2.45.1-next.v.202605131032.0+f6d6e7149",
120
+ "@wordpress/keyboard-shortcuts": "^5.45.1-next.v.202605131032.0+f6d6e7149",
121
+ "@wordpress/keycodes": "^4.45.1-next.v.202605131032.0+f6d6e7149",
122
+ "@wordpress/latex-to-mathml": "^1.13.1-next.v.202605131032.0+f6d6e7149",
123
+ "@wordpress/notices": "^5.45.1-next.v.202605131032.0+f6d6e7149",
124
+ "@wordpress/patterns": "^2.45.1-next.v.202605131032.0+f6d6e7149",
125
+ "@wordpress/primitives": "^4.45.1-next.v.202605131032.0+f6d6e7149",
126
+ "@wordpress/private-apis": "^1.45.1-next.v.202605131032.0+f6d6e7149",
127
+ "@wordpress/reusable-blocks": "^5.45.1-next.v.202605131032.0+f6d6e7149",
128
+ "@wordpress/rich-text": "^7.45.1-next.v.202605131032.0+f6d6e7149",
129
+ "@wordpress/server-side-render": "^6.21.1-next.v.202605131032.0+f6d6e7149",
130
+ "@wordpress/shortcode": "^4.45.1-next.v.202605131032.0+f6d6e7149",
131
+ "@wordpress/ui": "^0.13.1-next.v.202605131032.0+f6d6e7149",
132
+ "@wordpress/upload-media": "^0.30.1-next.v.202605131032.0+f6d6e7149",
133
+ "@wordpress/url": "^4.45.1-next.v.202605131032.0+f6d6e7149",
134
+ "@wordpress/viewport": "^6.45.1-next.v.202605131032.0+f6d6e7149",
135
+ "@wordpress/wordcount": "^4.45.1-next.v.202605131032.0+f6d6e7149",
135
136
  "change-case": "^4.1.2",
136
137
  "clsx": "^2.1.1",
137
138
  "colord": "^2.7.0",
@@ -140,7 +141,7 @@
140
141
  "html-react-parser": "5.2.11",
141
142
  "memize": "^2.1.0",
142
143
  "remove-accents": "^0.5.0",
143
- "uuid": "^9.0.1"
144
+ "uuid": "^14.0.0"
144
145
  },
145
146
  "devDependencies": {
146
147
  "deep-freeze": "0.0.1"
@@ -152,5 +153,5 @@
152
153
  "publishConfig": {
153
154
  "access": "public"
154
155
  },
155
- "gitHead": "8c229eaed0e88c9827e2da3d73a78f9ddd77714b"
156
+ "gitHead": "0e198c7ac7ca634e73ded9220ce048c0302174dd"
156
157
  }
@@ -290,7 +290,7 @@ export default function BreadcrumbEdit( {
290
290
  setAttributes( { showOnHomePage: value } )
291
291
  }
292
292
  help={ __(
293
- 'If this breadcrumbs block appears in a template or template part that’s shown on the homepage, enable this option to display the breadcrumb trail. Otherwise, this setting has no effect.'
293
+ 'If this Breadcrumbs block appears in a template or template part that’s shown on the homepage, enable this option to display the breadcrumb trail. Otherwise, this setting has no effect.'
294
294
  ) }
295
295
  />
296
296
  <CheckboxControl
@@ -7,8 +7,6 @@ import clsx from 'clsx';
7
7
  * WordPress dependencies
8
8
  */
9
9
  import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
10
- import { useSelect } from '@wordpress/data';
11
- import { store as blocksStore } from '@wordpress/blocks';
12
10
 
13
11
  const DEFAULT_BLOCK = {
14
12
  name: 'core/button',
@@ -32,20 +30,9 @@ function ButtonsEdit( { attributes, className } ) {
32
30
  'has-custom-font-size': fontSize || style?.typography?.fontSize,
33
31
  } ),
34
32
  } );
35
- const { hasButtonVariations } = useSelect( ( select ) => {
36
- const buttonVariations = select( blocksStore ).getBlockVariations(
37
- 'core/button',
38
- 'inserter'
39
- );
40
- return {
41
- hasButtonVariations: buttonVariations.length > 0,
42
- };
43
- }, [] );
44
33
 
45
34
  const innerBlocksProps = useInnerBlocksProps( blockProps, {
46
35
  defaultBlock: DEFAULT_BLOCK,
47
- // This check should be handled by the `Inserter` internally to be consistent across all blocks that use it.
48
- directInsert: ! hasButtonVariations,
49
36
  template: [ [ 'core/button' ] ],
50
37
  templateInsertUpdatesSelection: true,
51
38
  orientation: layout?.orientation ?? 'horizontal',
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { __ } from '@wordpress/i18n';
4
+ import { _x } from '@wordpress/i18n';
5
5
  import { useBlockProps } from '@wordpress/block-editor';
6
6
 
7
7
  /**
@@ -20,7 +20,10 @@ function Edit( props ) {
20
20
  href="#comment-reply-pseudo-link"
21
21
  onClick={ ( event ) => event.preventDefault() }
22
22
  >
23
- { __( 'Reply' ) }
23
+ {
24
+ /* translators: Comment reply button text. */
25
+ _x( 'Reply', 'verb' )
26
+ }
24
27
  </a>
25
28
  </div>
26
29
  </>
@@ -2,7 +2,7 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { store as blockEditorStore } from '@wordpress/block-editor';
5
- import { __, sprintf } from '@wordpress/i18n';
5
+ import { __, _x, sprintf } from '@wordpress/i18n';
6
6
  import { useSelect } from '@wordpress/data';
7
7
  import { useEntityProp } from '@wordpress/core-data';
8
8
  import { createInterpolateElement } from '@wordpress/element';
@@ -109,7 +109,10 @@ export default function PostCommentsPlaceholder( { postType, postId } ) {
109
109
  'Reply to A WordPress Commenter'
110
110
  ) }
111
111
  >
112
- { __( 'Reply' ) }
112
+ {
113
+ /* translators: Comment reply button text. */
114
+ _x( 'Reply', 'verb' )
115
+ }
113
116
  </a>
114
117
  </div>
115
118
  </article>
@@ -1,5 +1,4 @@
1
1
  @use "@wordpress/base-styles/variables" as *;
2
- @use "@wordpress/base-styles/z-index" as *;
3
2
 
4
3
  .wp-block-cover {
5
4
  // Override default cover styles
@@ -13,7 +12,8 @@
13
12
  .components-placeholder {
14
13
  &.is-large {
15
14
  justify-content: flex-start;
16
- z-index: z-index(".wp-block-cover.is-placeholder .components-placeholder.is-large");
15
+ // Lift the resizer UI above the surrounding placeholder content.
16
+ z-index: 1;
17
17
  }
18
18
  }
19
19
 
@@ -1,6 +1,5 @@
1
1
  @use "@wordpress/base-styles/colors" as *;
2
2
  @use "@wordpress/base-styles/variables" as *;
3
- @use "@wordpress/base-styles/z-index" as *;
4
3
 
5
4
  .wp-block-cover-image,
6
5
  .wp-block-cover {
@@ -348,15 +347,18 @@ body:not(.editor-styles-wrapper) .wp-block-cover:not(
348
347
  )
349
348
  ) {
350
349
  .wp-block-cover__video-background {
351
- z-index: z-index(".wp-block-cover__video-background");
350
+ // Background media sits at the base of the stack.
351
+ z-index: 0;
352
352
  }
353
353
 
354
354
  .wp-block-cover__embed-background {
355
- z-index: z-index(".wp-block-cover__video-background");
355
+ // Shares the same base layer as the video background.
356
+ z-index: 0;
356
357
  }
357
358
 
358
359
  .wp-block-cover__image-background {
359
- z-index: z-index(".wp-block-cover__image-background");
360
+ // Background media sits at the base of the stack.
361
+ z-index: 0;
360
362
  }
361
363
 
362
364
  // The first selector is required for old Cover markup/
@@ -364,11 +366,13 @@ body:not(.editor-styles-wrapper) .wp-block-cover:not(
364
366
  &.has-background-dim:not(.has-background-gradient)::before,
365
367
  .wp-block-cover__background,
366
368
  .wp-block-cover__gradient-background {
367
- z-index: z-index(".wp-block-cover.has-background-dim::before");
369
+ // Sit above the video/image/embed background media.
370
+ z-index: 1;
368
371
  }
369
372
 
370
373
  .wp-block-cover__inner-container {
371
- z-index: z-index(".wp-block-cover__inner-container");
374
+ // Lift the inner blocks above the background media and overlay.
375
+ z-index: 1;
372
376
 
373
377
  // Reset the z-index to auto when the body has a modal open. So when the
374
378
  // modal is inside the cover, it doesn't create a stacking context.
@@ -2,6 +2,7 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { createBlock } from '@wordpress/blocks';
5
+ import { isURL, getFilename } from '@wordpress/url';
5
6
 
6
7
  /**
7
8
  * Internal dependencies
@@ -22,10 +23,24 @@ const transforms = {
22
23
  from: [
23
24
  {
24
25
  type: 'raw',
25
- isMatch: ( node ) =>
26
- node.nodeName === 'P' &&
27
- /^\s*(https?:\/\/\S+)\s*$/i.test( node.textContent ) &&
28
- node.textContent?.match( /https/gi )?.length === 1,
26
+ isMatch: ( node ) => {
27
+ if ( node.nodeName !== 'P' ) {
28
+ return false;
29
+ }
30
+ const trimmed = node.textContent.trim();
31
+ if (
32
+ ! isURL( trimmed ) ||
33
+ ! /^https:\/\//i.test( trimmed ) ||
34
+ trimmed.match( /https:\/\//gi )?.length !== 1
35
+ ) {
36
+ return false;
37
+ }
38
+ // Reject URLs whose filename ends in a file extension,
39
+ // except common page extensions used by permalinks.
40
+ return ! /\.(?!(html?|php)$)[a-z0-9]+$/i.test(
41
+ getFilename( trimmed ) || ''
42
+ );
43
+ },
29
44
  transform: ( node ) => {
30
45
  const url = rewriteXToTwitter( node.textContent.trim() );
31
46
  return createBlock( EMBED_BLOCK, {
@@ -34,6 +49,17 @@ const transforms = {
34
49
  } );
35
50
  },
36
51
  },
52
+ {
53
+ type: 'shortcode',
54
+ tag: 'embed',
55
+ transform: ( _attrs, { shortcode } ) => {
56
+ const url = rewriteXToTwitter( shortcode.content?.trim() );
57
+ return createBlock( EMBED_BLOCK, {
58
+ url,
59
+ ...findMoreSuitableBlock( url )?.attributes,
60
+ } );
61
+ },
62
+ },
37
63
  ],
38
64
  to: [
39
65
  {
@@ -3,27 +3,12 @@
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
5
  import { ToolbarButton } from '@wordpress/components';
6
- import { useDispatch, useSelect } from '@wordpress/data';
7
- import { rawHandler, serialize } from '@wordpress/blocks';
8
- import { store as blockEditorStore } from '@wordpress/block-editor';
9
-
10
- const ConvertToBlocksButton = ( { clientId } ) => {
11
- const { replaceBlocks } = useDispatch( blockEditorStore );
12
- const block = useSelect(
13
- ( select ) => {
14
- return select( blockEditorStore ).getBlock( clientId );
15
- },
16
- [ clientId ]
17
- );
6
+ import { rawHandler } from '@wordpress/blocks';
18
7
 
8
+ const ConvertToBlocksButton = ( { content, onReplace } ) => {
19
9
  return (
20
10
  <ToolbarButton
21
- onClick={ () =>
22
- replaceBlocks(
23
- block.clientId,
24
- rawHandler( { HTML: serialize( block ) } )
25
- )
26
- }
11
+ onClick={ () => onReplace( rawHandler( { HTML: content } ) ) }
27
12
  >
28
13
  { __( 'Convert to blocks' ) }
29
14
  </ToolbarButton>
@@ -7,7 +7,7 @@ import {
7
7
  useBlockProps,
8
8
  store as blockEditorStore,
9
9
  } from '@wordpress/block-editor';
10
- import { useSelect } from '@wordpress/data';
10
+ import { useDispatch, useSelect } from '@wordpress/data';
11
11
  import {
12
12
  Button,
13
13
  Placeholder,
@@ -22,12 +22,14 @@ import { classic } from '@wordpress/icons';
22
22
  * Internal dependencies
23
23
  */
24
24
  import ConvertToBlocksButton from './convert-to-blocks-button';
25
+ import MigrationNotice from './migration-notice';
25
26
  import ModalEdit from './modal';
26
27
 
27
28
  export default function FreeformEdit( {
28
29
  attributes,
29
30
  setAttributes,
30
31
  clientId,
32
+ onReplace,
31
33
  } ) {
32
34
  const { content } = attributes;
33
35
  const [ isOpen, setOpen ] = useState( false );
@@ -37,13 +39,21 @@ export default function FreeformEdit( {
37
39
  ( select ) => select( blockEditorStore ).canRemoveBlock( clientId ),
38
40
  [ clientId ]
39
41
  );
42
+ const { removeBlock } = useDispatch( blockEditorStore );
43
+
44
+ // Gated by an experiment so authors can opt into a stronger nudge to
45
+ // migrate Classic block content ahead of its planned deprecation.
46
+ const isDeprecationMode = window.__experimentalClassicBlockDeprecation;
40
47
 
41
48
  return (
42
49
  <>
43
- { canRemove && (
50
+ { canRemove && ! isDeprecationMode && (
44
51
  <BlockControls>
45
52
  <ToolbarGroup>
46
- <ConvertToBlocksButton clientId={ clientId } />
53
+ <ConvertToBlocksButton
54
+ content={ content }
55
+ onReplace={ onReplace }
56
+ />
47
57
  </ToolbarGroup>
48
58
  </BlockControls>
49
59
  ) }
@@ -58,19 +68,42 @@ export default function FreeformEdit( {
58
68
  </ToolbarGroup>
59
69
  </BlockControls>
60
70
  <div { ...useBlockProps() }>
71
+ { isDeprecationMode && canRemove && content && (
72
+ <MigrationNotice
73
+ content={ content }
74
+ onReplace={ onReplace }
75
+ />
76
+ ) }
61
77
  { content ? (
62
78
  <RawHTML>{ content }</RawHTML>
63
79
  ) : (
64
80
  <Placeholder
65
81
  icon={ <BlockIcon icon={ classic } /> }
66
82
  label={ __( 'Classic' ) }
67
- instructions={ __(
68
- 'Use the classic editor to add content.'
69
- ) }
83
+ instructions={
84
+ isDeprecationMode
85
+ ? __(
86
+ 'The Classic block is being phased out. It’s recommended to use other blocks for the best editing experience.'
87
+ )
88
+ : __( 'Use the classic editor to add content.' )
89
+ }
70
90
  >
91
+ { isDeprecationMode && canRemove && (
92
+ <Button
93
+ __next40pxDefaultSize
94
+ variant="primary"
95
+ onClick={ () => removeBlock( clientId ) }
96
+ >
97
+ { __( 'Remove block' ) }
98
+ </Button>
99
+ ) }
71
100
  <Button
72
101
  __next40pxDefaultSize
73
- variant="primary"
102
+ variant={
103
+ isDeprecationMode && canRemove
104
+ ? 'secondary'
105
+ : 'primary'
106
+ }
74
107
  onClick={ () => setOpen( true ) }
75
108
  >
76
109
  { __( 'Edit contents' ) }
@@ -21,4 +21,12 @@ export const settings = {
21
21
  save,
22
22
  };
23
23
 
24
- export const init = () => initBlock( { name, metadata, settings } );
24
+ export const init = () => {
25
+ // Only expose the block in the inserter if the current post actually needs
26
+ // a classic block.
27
+ const supports = {
28
+ ...metadata.supports,
29
+ inserter: !! window?.__needsClassicBlock,
30
+ };
31
+ return initBlock( { name, metadata, settings: { ...settings, supports } } );
32
+ };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { Warning } from '@wordpress/block-editor';
5
+ import { Button } from '@wordpress/components';
6
+ import { createBlock, rawHandler } from '@wordpress/blocks';
7
+ import { __ } from '@wordpress/i18n';
8
+
9
+ /**
10
+ * Block-level deprecation warning rendered when the
11
+ * `gutenberg-classic-block-deprecation` experiment is enabled.
12
+ *
13
+ * Uses the same `Warning` primitive as `core/missing` so the experience is
14
+ * visually consistent with how the editor already surfaces deprecated blocks,
15
+ * and offers two migration actions - a primary "Convert to blocks", and a
16
+ * secondary "Convert to Custom HTML".
17
+ *
18
+ * @param {Object} props
19
+ * @param {string} props.content Raw HTML content of the Classic block.
20
+ * @param {Function} props.onReplace Replace the current block with the given blocks.
21
+ */
22
+ export default function MigrationNotice( { content, onReplace } ) {
23
+ const actions = [
24
+ <Button
25
+ __next40pxDefaultSize
26
+ key="convert-to-blocks"
27
+ variant="primary"
28
+ onClick={ () => onReplace( rawHandler( { HTML: content } ) ) }
29
+ >
30
+ { __( 'Convert to blocks' ) }
31
+ </Button>,
32
+ <Button
33
+ __next40pxDefaultSize
34
+ key="convert-to-html"
35
+ variant="secondary"
36
+ onClick={ () =>
37
+ onReplace( createBlock( 'core/html', { content } ) )
38
+ }
39
+ >
40
+ { __( 'Convert to HTML' ) }
41
+ </Button>,
42
+ ];
43
+
44
+ return (
45
+ <Warning actions={ actions }>
46
+ { __(
47
+ 'The Classic block is being phased out. Convert this content to blocks for the best editing experience, or move it to a Custom HTML block to preserve the markup as-is.'
48
+ ) }
49
+ </Warning>
50
+ );
51
+ }
@@ -62,6 +62,7 @@ import { isExternalImage } from './edit';
62
62
  import { Caption } from '../utils/caption';
63
63
  import { MediaControl } from '../utils/media-control';
64
64
  import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
65
+ import { useOpenImageMediaEditorModal } from './use-open-image-media-editor-modal';
65
66
  import {
66
67
  MIN_SIZE,
67
68
  ALLOWED_MEDIA_TYPES,
@@ -70,12 +71,9 @@ import {
70
71
  } from './constants';
71
72
  import { evalAspectRatio, mediaPosition } from './utils';
72
73
 
73
- const {
74
- DimensionsTool,
75
- ResolutionTool,
76
- mediaEditKey,
77
- openMediaEditorModalKey,
78
- } = unlock( blockEditorPrivateApis );
74
+ const { DimensionsTool, ResolutionTool, mediaEditKey } = unlock(
75
+ blockEditorPrivateApis
76
+ );
79
77
 
80
78
  const scaleOptions = [
81
79
  {
@@ -316,7 +314,7 @@ export default function Image( {
316
314
  const setRefs = useMergeRefs( [ setImageElement, setResizeObserved ] );
317
315
  const { allowResize = true } = context;
318
316
 
319
- const { image, canUserEdit, attachmentResolutionError } = useSelect(
317
+ const { image, attachmentResolutionError } = useSelect(
320
318
  ( select ) => {
321
319
  const imageRecord =
322
320
  id && isSingleSelected
@@ -345,20 +343,8 @@ export default function Image( {
345
343
  )
346
344
  : null;
347
345
 
348
- // Check edit permissions when the media editor experiment is enabled.
349
- // Only check when imageRecord is available to avoid unnecessary API requests.
350
- let canEdit = false;
351
- if ( imageRecord && window?.__experimentalMediaEditor ) {
352
- canEdit = !! select( coreStore ).canUser( 'update', {
353
- kind: 'postType',
354
- name: 'attachment',
355
- id,
356
- } );
357
- }
358
-
359
346
  return {
360
347
  image: imageRecord,
361
- canUserEdit: canEdit,
362
348
  attachmentResolutionError: resolutionError,
363
349
  };
364
350
  },
@@ -393,21 +379,10 @@ export default function Image( {
393
379
  [ clientId ]
394
380
  );
395
381
  const { getBlock, getSettings } = useSelect( blockEditorStore );
396
- const settings = getSettings();
397
- const { onNavigateToEntityRecord } = settings;
398
- const openMediaEditorModal = settings[ openMediaEditorModalKey ];
399
-
400
- const handleMediaUpdate = useCallback(
401
- ( { id: newId, url: newUrl } ) => {
402
- if ( typeof newId === 'number' && newId !== id ) {
403
- setAttributes( {
404
- id: newId,
405
- url: newUrl ?? url,
406
- } );
407
- }
408
- },
409
- [ id, url, setAttributes ]
410
- );
382
+ const openImageMediaEditorModal = useOpenImageMediaEditorModal( {
383
+ attributes,
384
+ setAttributes,
385
+ } );
411
386
 
412
387
  const {
413
388
  replaceBlocks,
@@ -848,28 +823,6 @@ export default function Image( {
848
823
  const hasDataFormBlockFields =
849
824
  window?.__experimentalContentOnlyInspectorFields;
850
825
 
851
- const editMediaButton = window?.__experimentalMediaEditor &&
852
- id &&
853
- isSingleSelected &&
854
- canUserEdit &&
855
- !! editMediaEntity &&
856
- ! isExternalImage( id, url ) &&
857
- ! isEditingImage &&
858
- onNavigateToEntityRecord && (
859
- <BlockControls group="other">
860
- <ToolbarButton
861
- onClick={ () => {
862
- onNavigateToEntityRecord( {
863
- postId: id,
864
- postType: 'attachment',
865
- } );
866
- } }
867
- >
868
- { __( 'Edit media' ) }
869
- </ToolbarButton>
870
- </BlockControls>
871
- );
872
-
873
826
  const controls = (
874
827
  <>
875
828
  { showBlockControls && (
@@ -893,14 +846,13 @@ export default function Image( {
893
846
  { allowCrop && (
894
847
  <ToolbarButton
895
848
  onClick={
896
- openMediaEditorModal && id
897
- ? () =>
898
- openMediaEditorModal( {
899
- id,
900
- onUpdate: handleMediaUpdate,
901
- } )
849
+ openImageMediaEditorModal
850
+ ? openImageMediaEditorModal
902
851
  : () => setIsEditingImage( true )
903
852
  }
853
+ aria-haspopup={
854
+ openImageMediaEditorModal ? 'dialog' : undefined
855
+ }
904
856
  icon={ crop }
905
857
  label={ __( 'Crop' ) }
906
858
  />
@@ -1351,7 +1303,6 @@ export default function Image( {
1351
1303
 
1352
1304
  return (
1353
1305
  <>
1354
- { editMediaButton }
1355
1306
  { mediaReplaceFlow }
1356
1307
  { controls }
1357
1308
  { featuredImageControl }