@wordpress/block-editor 15.14.1-next.v.202603102151.0 → 15.15.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 (112) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/block-bindings/attribute-control.cjs +5 -2
  3. package/build/components/block-bindings/attribute-control.cjs.map +2 -2
  4. package/build/components/block-inspector/edit-contents.cjs +5 -4
  5. package/build/components/block-inspector/edit-contents.cjs.map +2 -2
  6. package/build/components/block-list/block.cjs +9 -1
  7. package/build/components/block-list/block.cjs.map +2 -2
  8. package/build/components/block-list/use-block-props/index.cjs +10 -1
  9. package/build/components/block-list/use-block-props/index.cjs.map +2 -2
  10. package/build/components/block-styles/index.cjs +7 -1
  11. package/build/components/block-styles/index.cjs.map +3 -3
  12. package/build/components/block-variation-transforms/index.cjs +11 -5
  13. package/build/components/block-variation-transforms/index.cjs.map +2 -2
  14. package/build/components/block-visibility/use-block-visibility.cjs +4 -3
  15. package/build/components/block-visibility/use-block-visibility.cjs.map +2 -2
  16. package/build/components/global-styles/color-panel.cjs +1 -1
  17. package/build/components/global-styles/color-panel.cjs.map +2 -2
  18. package/build/components/global-styles/filters-panel.cjs.map +2 -2
  19. package/build/components/global-styles/index.cjs +3 -0
  20. package/build/components/global-styles/index.cjs.map +2 -2
  21. package/build/components/global-styles/state-control.cjs +81 -0
  22. package/build/components/global-styles/state-control.cjs.map +7 -0
  23. package/build/components/iframe/index.cjs +1 -3
  24. package/build/components/iframe/index.cjs.map +2 -2
  25. package/build/components/iframe/use-scale-canvas.cjs +0 -1
  26. package/build/components/iframe/use-scale-canvas.cjs.map +2 -2
  27. package/build/components/provider/index.cjs +1 -1
  28. package/build/components/provider/index.cjs.map +2 -2
  29. package/build/components/provider/use-media-upload-settings.cjs +1 -0
  30. package/build/components/provider/use-media-upload-settings.cjs.map +2 -2
  31. package/build/hooks/block-fields/media/index.cjs +140 -101
  32. package/build/hooks/block-fields/media/index.cjs.map +3 -3
  33. package/build/private-apis.cjs +1 -0
  34. package/build/private-apis.cjs.map +2 -2
  35. package/build/store/private-keys.cjs +3 -0
  36. package/build/store/private-keys.cjs.map +2 -2
  37. package/build/store/private-selectors.cjs +2 -1
  38. package/build/store/private-selectors.cjs.map +2 -2
  39. package/build/store/reducer.cjs +3 -4
  40. package/build/store/reducer.cjs.map +2 -2
  41. package/build/store/selectors.cjs +4 -4
  42. package/build/store/selectors.cjs.map +2 -2
  43. package/build-module/components/block-bindings/attribute-control.mjs +5 -2
  44. package/build-module/components/block-bindings/attribute-control.mjs.map +2 -2
  45. package/build-module/components/block-inspector/edit-contents.mjs +5 -4
  46. package/build-module/components/block-inspector/edit-contents.mjs.map +2 -2
  47. package/build-module/components/block-list/block.mjs +10 -2
  48. package/build-module/components/block-list/block.mjs.map +2 -2
  49. package/build-module/components/block-list/use-block-props/index.mjs +11 -2
  50. package/build-module/components/block-list/use-block-props/index.mjs.map +2 -2
  51. package/build-module/components/block-styles/index.mjs +7 -1
  52. package/build-module/components/block-styles/index.mjs.map +2 -2
  53. package/build-module/components/block-variation-transforms/index.mjs +11 -5
  54. package/build-module/components/block-variation-transforms/index.mjs.map +2 -2
  55. package/build-module/components/block-visibility/use-block-visibility.mjs +4 -3
  56. package/build-module/components/block-visibility/use-block-visibility.mjs.map +2 -2
  57. package/build-module/components/global-styles/color-panel.mjs +1 -1
  58. package/build-module/components/global-styles/color-panel.mjs.map +2 -2
  59. package/build-module/components/global-styles/filters-panel.mjs.map +2 -2
  60. package/build-module/components/global-styles/index.mjs +2 -0
  61. package/build-module/components/global-styles/index.mjs.map +2 -2
  62. package/build-module/components/global-styles/state-control.mjs +60 -0
  63. package/build-module/components/global-styles/state-control.mjs.map +7 -0
  64. package/build-module/components/iframe/index.mjs +2 -9
  65. package/build-module/components/iframe/index.mjs.map +2 -2
  66. package/build-module/components/iframe/use-scale-canvas.mjs +0 -1
  67. package/build-module/components/iframe/use-scale-canvas.mjs.map +2 -2
  68. package/build-module/components/provider/index.mjs +1 -1
  69. package/build-module/components/provider/index.mjs.map +2 -2
  70. package/build-module/components/provider/use-media-upload-settings.mjs +1 -0
  71. package/build-module/components/provider/use-media-upload-settings.mjs.map +2 -2
  72. package/build-module/hooks/block-fields/media/index.mjs +142 -102
  73. package/build-module/hooks/block-fields/media/index.mjs.map +2 -2
  74. package/build-module/private-apis.mjs +2 -0
  75. package/build-module/private-apis.mjs.map +2 -2
  76. package/build-module/store/private-keys.mjs +2 -0
  77. package/build-module/store/private-keys.mjs.map +2 -2
  78. package/build-module/store/private-selectors.mjs +2 -1
  79. package/build-module/store/private-selectors.mjs.map +2 -2
  80. package/build-module/store/reducer.mjs +3 -4
  81. package/build-module/store/reducer.mjs.map +2 -2
  82. package/build-module/store/selectors.mjs +4 -4
  83. package/build-module/store/selectors.mjs.map +2 -2
  84. package/build-style/content-rtl.css +2 -0
  85. package/build-style/content.css +2 -0
  86. package/build-style/style-rtl.css +30 -3
  87. package/build-style/style.css +30 -3
  88. package/package.json +39 -39
  89. package/src/components/block-bindings/attribute-control.js +8 -3
  90. package/src/components/block-inspector/edit-contents.js +5 -3
  91. package/src/components/block-list/block.js +10 -1
  92. package/src/components/block-list/use-block-props/index.js +11 -1
  93. package/src/components/block-styles/index.js +7 -1
  94. package/src/components/block-variation-transforms/index.js +41 -36
  95. package/src/components/block-visibility/use-block-visibility.js +4 -2
  96. package/src/components/global-styles/color-panel.js +3 -1
  97. package/src/components/global-styles/filters-panel.js +2 -0
  98. package/src/components/global-styles/index.js +1 -0
  99. package/src/components/global-styles/state-control.js +75 -0
  100. package/src/components/iframe/index.js +2 -12
  101. package/src/components/iframe/use-scale-canvas.js +0 -1
  102. package/src/components/link-control/style.scss +4 -2
  103. package/src/components/provider/index.js +2 -1
  104. package/src/components/provider/use-media-upload-settings.js +1 -0
  105. package/src/components/url-popover/style.scss +4 -2
  106. package/src/hooks/block-fields/media/index.js +143 -99
  107. package/src/hooks/block-fields/media/styles.scss +31 -3
  108. package/src/private-apis.js +2 -0
  109. package/src/store/private-keys.js +1 -0
  110. package/src/store/private-selectors.js +4 -1
  111. package/src/store/reducer.js +12 -6
  112. package/src/store/selectors.js +13 -6
@@ -8,12 +8,7 @@ import clsx from 'clsx';
8
8
  */
9
9
  import { useState, createPortal, forwardRef } from '@wordpress/element';
10
10
  import { __ } from '@wordpress/i18n';
11
- import {
12
- useMergeRefs,
13
- useRefEffect,
14
- useDisabled,
15
- useViewportMatch,
16
- } from '@wordpress/compose';
11
+ import { useMergeRefs, useRefEffect, useDisabled } from '@wordpress/compose';
17
12
  import { __experimentalStyleProvider as StyleProvider } from '@wordpress/components';
18
13
  import { useSelect } from '@wordpress/data';
19
14
 
@@ -25,8 +20,6 @@ import { getCompatibilityStyles } from './get-compatibility-styles';
25
20
  import { useScaleCanvas } from './use-scale-canvas';
26
21
  import { store as blockEditorStore } from '../../store';
27
22
 
28
- const ViewportWidthProvider = useViewportMatch.__experimentalWidthProvider;
29
-
30
23
  function bubbleEvent( event, Constructor, frame ) {
31
24
  const init = {};
32
25
 
@@ -271,7 +264,6 @@ function Iframe( {
271
264
  const {
272
265
  contentResizeListener,
273
266
  containerResizeListener,
274
- containerWidth,
275
267
  isZoomedOut,
276
268
  scaleContainerWidth,
277
269
  } = useScaleCanvas( {
@@ -368,9 +360,7 @@ function Iframe( {
368
360
  >
369
361
  { contentResizeListener }
370
362
  <StyleProvider document={ iframeDocument }>
371
- <ViewportWidthProvider value={ containerWidth }>
372
- { children }
373
- </ViewportWidthProvider>
363
+ { children }
374
364
  </StyleProvider>
375
365
  </body>,
376
366
  iframeDocument.documentElement
@@ -484,7 +484,6 @@ export function useScaleCanvas( {
484
484
  return {
485
485
  isZoomedOut,
486
486
  scaleContainerWidth,
487
- containerWidth,
488
487
  contentResizeListener,
489
488
  containerResizeListener,
490
489
  };
@@ -18,12 +18,14 @@ $block-editor-link-control-number-of-actions: 1;
18
18
 
19
19
  .block-editor-link-control {
20
20
  position: relative;
21
- min-width: $modal-min-width;
21
+ // TODO: Replace with a --wpds-dimension-surface-width-* token.
22
+ min-width: 350px;
22
23
 
23
24
  .components-popover__content & {
24
25
  min-width: auto;
25
26
  width: 90vw;
26
- max-width: $modal-min-width;
27
+ // TODO: Replace with a --wpds-dimension-surface-width-* token.
28
+ max-width: 350px;
27
29
  }
28
30
 
29
31
  .show-icon-labels & {
@@ -121,7 +121,8 @@ function mediaUpload(
121
121
  onSuccess?.( attachments );
122
122
  },
123
123
  onBatchSuccess,
124
- onError: ( { message } ) => onError( message ),
124
+ onError: ( error ) =>
125
+ onError( typeof error === 'string' ? error : error?.message ?? '' ),
125
126
  additionalData,
126
127
  allowedTypes,
127
128
  } );
@@ -15,6 +15,7 @@ function useMediaUploadSettings( settings = {} ) {
15
15
  () => ( {
16
16
  mediaUpload: settings.mediaUpload,
17
17
  mediaSideload: settings.mediaSideload,
18
+ mediaFinalize: settings.mediaFinalize,
18
19
  maxUploadFileSize: settings.maxUploadFileSize,
19
20
  allowedMimeTypes: settings.allowedMimeTypes,
20
21
  allImageSizes: settings.allImageSizes,
@@ -65,7 +65,8 @@
65
65
  min-width: 150px;
66
66
  // Avoids the popover from growing too wide when the URL is long.
67
67
  // See https://github.com/WordPress/gutenberg/issues/58599
68
- max-width: $modal-min-width;
68
+ // TODO: Replace with a --wpds-dimension-surface-width-* token.
69
+ max-width: 350px;
69
70
 
70
71
  &.has-invalid-link {
71
72
  color: $alert-red;
@@ -75,7 +76,8 @@
75
76
  .block-editor-url-popover__expand-on-click {
76
77
  display: flex;
77
78
  align-items: center;
78
- min-width: $modal-min-width;
79
+ // TODO: Replace with a --wpds-dimension-surface-width-* token.
80
+ min-width: 350px;
79
81
  white-space: nowrap;
80
82
 
81
83
  .text {
@@ -7,12 +7,15 @@ import {
7
7
  __experimentalGrid as Grid,
8
8
  } from '@wordpress/components';
9
9
  import { useSelect } from '@wordpress/data';
10
+ import { focus } from '@wordpress/dom';
11
+ import { useRef } from '@wordpress/element';
10
12
  import { __ } from '@wordpress/i18n';
11
13
  import {
12
14
  audio as audioIcon,
13
15
  image as imageIcon,
14
16
  media as mediaIcon,
15
17
  video as videoIcon,
18
+ reset as resetIcon,
16
19
  } from '@wordpress/icons';
17
20
 
18
21
  /**
@@ -24,6 +27,23 @@ import { useInspectorPopoverPlacement } from '../use-inspector-popover-placement
24
27
  import { getMediaSelectKey } from '../../../store/private-keys';
25
28
  import { store as blockEditorStore } from '../../../store';
26
29
 
30
+ /**
31
+ * Focuses the toggle button.
32
+ *
33
+ * @param {Object} containerRef - ref object containing current element
34
+ */
35
+ const focusToggleButton = ( containerRef ) => {
36
+ // Use requestAnimationFrame to ensure DOM updates are complete.
37
+ window.requestAnimationFrame( () => {
38
+ const [ toggleButton ] = focus.tabbable.find( containerRef?.current );
39
+ if ( ! toggleButton ) {
40
+ return;
41
+ }
42
+
43
+ toggleButton.focus();
44
+ } );
45
+ };
46
+
27
47
  function MediaThumbnail( { data, field, attachment, config } ) {
28
48
  const { allowedTypes = [], multiple = false } = config || {};
29
49
 
@@ -36,8 +56,8 @@ function MediaThumbnail( { data, field, attachment, config } ) {
36
56
  <div className="block-editor-content-only-controls__media-thumbnail">
37
57
  <img
38
58
  alt=""
39
- width={ 24 }
40
- height={ 24 }
59
+ width={ 20 }
60
+ height={ 20 }
41
61
  src={
42
62
  attachment.media_type === 'image'
43
63
  ? attachment.source_url
@@ -55,7 +75,7 @@ function MediaThumbnail( { data, field, attachment, config } ) {
55
75
  if ( allowedTypes[ 0 ] === 'image' && url ) {
56
76
  return (
57
77
  <div className="block-editor-content-only-controls__media-thumbnail">
58
- <img alt="" width={ 24 } height={ 24 } src={ url } />
78
+ <img alt="" width={ 20 } height={ 20 } src={ url } />
59
79
  </div>
60
80
  );
61
81
  }
@@ -72,11 +92,11 @@ function MediaThumbnail( { data, field, attachment, config } ) {
72
92
  }
73
93
 
74
94
  if ( icon ) {
75
- return <Icon icon={ icon } size={ 24 } />;
95
+ return <Icon icon={ icon } size={ 20 } />;
76
96
  }
77
97
  }
78
98
 
79
- return <Icon icon={ mediaIcon } size={ 24 } />;
99
+ return <Icon icon={ mediaIcon } size={ 20 } />;
80
100
  }
81
101
 
82
102
  export default function Media( { data, field, onChange, config = {} } ) {
@@ -116,117 +136,141 @@ export default function Media( { data, field, onChange, config = {} } ) {
116
136
  if ( allowedTypes.length === 1 ) {
117
137
  const allowedType = allowedTypes[ 0 ];
118
138
  if ( allowedType === 'image' ) {
119
- chooseItemLabel = __( 'Choose an image…' );
139
+ chooseItemLabel = __( 'Image' );
120
140
  } else if ( allowedType === 'video' ) {
121
- chooseItemLabel = __( 'Choose a video…' );
141
+ chooseItemLabel = __( 'Video' );
122
142
  } else if ( allowedType === 'application' ) {
123
- chooseItemLabel = __( 'Choose a file…' );
143
+ chooseItemLabel = __( 'File' );
124
144
  } else {
125
- chooseItemLabel = __( 'Choose a media item…' );
145
+ chooseItemLabel = __( 'Media' );
126
146
  }
127
147
  } else {
128
- chooseItemLabel = __( 'Choose a media item…' );
148
+ chooseItemLabel = __( 'Media' );
129
149
  }
150
+ const containerRef = useRef();
130
151
 
131
152
  return (
132
153
  <MediaUploadCheck>
133
- <MediaReplaceFlow
134
- className="block-editor-content-only-controls__media-replace-flow"
135
- allowedTypes={ allowedTypes }
136
- mediaId={ id }
137
- mediaURL={ url }
138
- multiple={ multiple }
139
- popoverProps={ popoverProps }
140
- onReset={ () => {
141
- onChange(
142
- field.setValue( {
143
- item: data,
144
- value: {},
145
- } )
146
- );
147
- } }
148
- { ...( useFeaturedImage && {
149
- useFeaturedImage: !! value?.featuredImage,
150
- onToggleFeaturedImage: () => {
154
+ <div
155
+ ref={ containerRef }
156
+ className="block-editor-content-only-controls"
157
+ >
158
+ <MediaReplaceFlow
159
+ className="block-editor-content-only-controls__media-replace-flow"
160
+ allowedTypes={ allowedTypes }
161
+ mediaId={ id }
162
+ mediaURL={ url }
163
+ multiple={ multiple }
164
+ popoverProps={ popoverProps }
165
+ onReset={ () => {
151
166
  onChange(
152
167
  field.setValue( {
153
168
  item: data,
154
- value: {
155
- featuredImage: ! value?.featuredImage,
156
- },
169
+ value: {},
157
170
  } )
158
171
  );
159
- },
160
- } ) }
161
- onSelect={ ( selectedMedia ) => {
162
- if ( selectedMedia.id && selectedMedia.url ) {
163
- const newValue = {
164
- ...selectedMedia,
165
- mediaType: selectedMedia.media_type,
166
- };
167
-
168
- // Turn off featured image when manually selecting media
169
- if ( useFeaturedImage ) {
170
- newValue.featuredImage = false;
171
- }
172
+ } }
173
+ { ...( useFeaturedImage && {
174
+ useFeaturedImage: !! value?.featuredImage,
175
+ onToggleFeaturedImage: () => {
176
+ onChange(
177
+ field.setValue( {
178
+ item: data,
179
+ value: {
180
+ featuredImage: ! value?.featuredImage,
181
+ },
182
+ } )
183
+ );
184
+ },
185
+ } ) }
186
+ onSelect={ ( selectedMedia ) => {
187
+ if ( selectedMedia.id && selectedMedia.url ) {
188
+ const newValue = {
189
+ ...selectedMedia,
190
+ mediaType: selectedMedia.media_type,
191
+ };
172
192
 
173
- onChange(
174
- field.setValue( {
175
- item: data,
176
- value: newValue,
177
- } )
178
- );
179
- }
180
- } }
181
- renderToggle={ ( buttonProps ) => (
182
- <Button
183
- __next40pxDefaultSize
184
- className="block-editor-content-only-controls__media"
185
- { ...buttonProps }
186
- >
187
- <Grid
188
- rowGap={ 0 }
189
- columnGap={ 8 }
190
- templateColumns="24px 1fr"
191
- className="block-editor-content-only-controls__media-row"
193
+ // Turn off featured image when manually selecting media
194
+ if ( useFeaturedImage ) {
195
+ newValue.featuredImage = false;
196
+ }
197
+
198
+ onChange(
199
+ field.setValue( {
200
+ item: data,
201
+ value: newValue,
202
+ } )
203
+ );
204
+ }
205
+ } }
206
+ renderToggle={ ( buttonProps ) => (
207
+ <Button
208
+ __next40pxDefaultSize
209
+ className="block-editor-content-only-controls__media"
210
+ { ...buttonProps }
192
211
  >
193
- { url && (
194
- <>
195
- <MediaThumbnail
196
- attachment={ attachment }
197
- field={ field }
198
- data={ data }
199
- config={ config }
200
- />
201
- <span className="block-editor-content-only-controls__media-title">
202
- {
203
- // TODO - truncate long titles or url smartly (e.g. show filename).
204
- attachment?.title?.raw &&
205
- attachment?.title?.raw !== ''
206
- ? attachment?.title?.raw
207
- : url
208
- }
209
- </span>
210
- </>
211
- ) }
212
- { ! url && (
213
- <>
214
- <span
215
- className="block-editor-content-only-controls__media-placeholder"
216
- style={ {
217
- width: '24px',
218
- height: '24px',
219
- } }
220
- />
221
- <span className="block-editor-content-only-controls__media-title">
222
- { chooseItemLabel }
223
- </span>
224
- </>
225
- ) }
226
- </Grid>
227
- </Button>
212
+ <Grid
213
+ rowGap={ 0 }
214
+ columnGap={ 8 }
215
+ templateColumns="20px 1fr"
216
+ className="block-editor-content-only-controls__media-row"
217
+ >
218
+ { url && (
219
+ <>
220
+ <MediaThumbnail
221
+ attachment={ attachment }
222
+ field={ field }
223
+ data={ data }
224
+ config={ config }
225
+ />
226
+ <span className="block-editor-content-only-controls__media-title">
227
+ {
228
+ // TODO - truncate long titles or url smartly (e.g. show filename).
229
+ attachment?.title?.raw &&
230
+ attachment?.title?.raw !== ''
231
+ ? attachment?.title?.raw
232
+ : url
233
+ }
234
+ </span>
235
+ </>
236
+ ) }
237
+ { ! url && (
238
+ <>
239
+ <span
240
+ className="block-editor-content-only-controls__media-placeholder"
241
+ style={ {
242
+ width: '20px',
243
+ height: '20px',
244
+ } }
245
+ />
246
+ <span className="block-editor-content-only-controls__media-title">
247
+ { chooseItemLabel }
248
+ </span>
249
+ </>
250
+ ) }
251
+ </Grid>
252
+ </Button>
253
+ ) }
254
+ />
255
+ { url && (
256
+ <Button
257
+ label={ __( 'Reset' ) }
258
+ className="block-editor-content-only-controls__media-reset"
259
+ size="small"
260
+ icon={ resetIcon }
261
+ onClick={ () => {
262
+ onChange(
263
+ field.setValue( {
264
+ item: data,
265
+ value: {},
266
+ } )
267
+ );
268
+
269
+ focusToggleButton( containerRef );
270
+ } }
271
+ />
228
272
  ) }
229
- />
273
+ </div>
230
274
  </MediaUploadCheck>
231
275
  );
232
276
  }
@@ -4,7 +4,7 @@
4
4
  .block-editor-content-only-controls__media {
5
5
  width: 100%;
6
6
  box-shadow: inset 0 0 0 $border-width $gray-400;
7
- padding: $grid-unit-10;
7
+ padding-right: $grid-unit-40;
8
8
 
9
9
  &:focus:not(:disabled) {
10
10
  // Allow smooth transition between focused and unfocused box-shadow states.
@@ -41,10 +41,11 @@
41
41
  }
42
42
 
43
43
  .block-editor-content-only-controls__media-thumbnail {
44
- width: 24px;
45
- height: 24px;
44
+ width: 20px;
45
+ height: 20px;
46
46
  border-radius: $radius-small;
47
47
  align-self: center;
48
+ overflow: hidden;
48
49
 
49
50
  img {
50
51
  width: 100% !important;
@@ -52,3 +53,30 @@
52
53
  object-fit: cover;
53
54
  }
54
55
  }
56
+
57
+ .block-editor-content-only-controls {
58
+ position: relative;
59
+ }
60
+
61
+ .block-editor-content-only-controls__media-reset {
62
+ position: absolute;
63
+ right: 0;
64
+ top: $grid-unit;
65
+ margin: auto $grid-unit auto;
66
+ opacity: 0;
67
+ border-radius: $radius-small;
68
+ @media not ( prefers-reduced-motion ) {
69
+ transition: opacity 0.1s ease-in-out;
70
+ }
71
+
72
+ .block-editor-content-only-controls:hover &,
73
+ &:focus,
74
+ &:hover {
75
+ opacity: 1;
76
+ }
77
+
78
+ @media (hover: none) {
79
+ // Show reset button on devices that do not support hover.
80
+ opacity: 1;
81
+ }
82
+ }
@@ -48,6 +48,7 @@ import {
48
48
  deviceTypeKey,
49
49
  isIsolatedEditorKey,
50
50
  isNavigationOverlayContextKey,
51
+ isNavigationPostEditorKey,
51
52
  mediaUploadOnSuccessKey,
52
53
  } from './store/private-keys';
53
54
  import { requiresWrapperOnCopy } from './components/writing-flow/utils';
@@ -130,6 +131,7 @@ lock( privateApis, {
130
131
  deviceTypeKey,
131
132
  isIsolatedEditorKey,
132
133
  isNavigationOverlayContextKey,
134
+ isNavigationPostEditorKey,
133
135
  mediaUploadOnSuccessKey,
134
136
  useBlockElement,
135
137
  useBlockElementRef,
@@ -10,4 +10,5 @@ export const deviceTypeKey = Symbol( 'deviceTypeKey' );
10
10
  export const isNavigationOverlayContextKey = Symbol(
11
11
  'isNavigationOverlayContext'
12
12
  );
13
+ export const isNavigationPostEditorKey = Symbol( 'isNavigationPostEditor' );
13
14
  export const mediaUploadOnSuccessKey = Symbol( 'mediaUploadOnSuccess' );
@@ -501,10 +501,13 @@ function isSectionBlockCandidate( state, clientId ) {
501
501
  const disableContentOnlyForUnsyncedPatterns =
502
502
  state.settings?.disableContentOnlyForUnsyncedPatterns;
503
503
 
504
+ const disableContentOnlyForTemplateParts =
505
+ state.settings?.disableContentOnlyForTemplateParts;
506
+
504
507
  if (
505
508
  ( ( ! disableContentOnlyForUnsyncedPatterns &&
506
509
  attributes?.metadata?.patternName ) ||
507
- isTemplatePart ) &&
510
+ ( isTemplatePart && ! disableContentOnlyForTemplateParts ) ) &&
508
511
  ! isIsolatedEditor
509
512
  ) {
510
513
  return true;
@@ -2279,9 +2279,6 @@ function openedListViewPanels(
2279
2279
  } );
2280
2280
  return hasChanges ? { ...state, panels: newPanels } : state;
2281
2281
  }
2282
- case 'RESET_BLOCKS':
2283
- // Clear all panel state when blocks are reset
2284
- return { allOpen: false, panels: {} };
2285
2282
  }
2286
2283
  return state;
2287
2284
  }
@@ -2550,10 +2547,15 @@ function getDerivedBlockEditingModesForTree( state, treeClientId = '' ) {
2550
2547
  state.blocks.attributes.get( clientId )?.metadata
2551
2548
  ?.patternName
2552
2549
  );
2550
+ const disableContentOnlyForTemplateParts =
2551
+ state.settings?.disableContentOnlyForTemplateParts;
2552
+
2553
2553
  const contentOnlyParents = [
2554
2554
  ...contentOnlyTemplateLockedClientIds,
2555
2555
  ...unsyncedPatternClientIds,
2556
- ...( isIsolatedEditor ? [] : templatePartClientIds ),
2556
+ ...( isIsolatedEditor || disableContentOnlyForTemplateParts
2557
+ ? []
2558
+ : templatePartClientIds ),
2557
2559
  ];
2558
2560
 
2559
2561
  traverseBlockTree( state, treeClientId, ( block ) => {
@@ -3072,7 +3074,8 @@ export function withDerivedBlockEditingModes( reducer ) {
3072
3074
  case 'UPDATE_SETTINGS': {
3073
3075
  // Recompute the entire tree if the section root,
3074
3076
  // the effective disableContentOnlyForUnsyncedPatterns value,
3075
- // or the isIsolatedEditor value changes.
3077
+ // the isIsolatedEditor value, or the
3078
+ // disableContentOnlyForTemplateParts value changes.
3076
3079
  // These are all values that affect the computation.
3077
3080
  if (
3078
3081
  state?.settings?.[ sectionRootClientIdKey ] !==
@@ -3082,7 +3085,10 @@ export function withDerivedBlockEditingModes( reducer ) {
3082
3085
  !! nextState?.settings
3083
3086
  ?.disableContentOnlyForUnsyncedPatterns ||
3084
3087
  !! state?.settings?.[ isIsolatedEditorKey ] !==
3085
- !! nextState?.settings?.[ isIsolatedEditorKey ]
3088
+ !! nextState?.settings?.[ isIsolatedEditorKey ] ||
3089
+ !! state?.settings?.disableContentOnlyForTemplateParts !==
3090
+ !! nextState?.settings
3091
+ ?.disableContentOnlyForTemplateParts
3086
3092
  ) {
3087
3093
  return {
3088
3094
  ...nextState,
@@ -1705,9 +1705,21 @@ const canInsertBlockTypeUnmemoized = (
1705
1705
  }
1706
1706
 
1707
1707
  const blockEditingMode = getBlockEditingMode( state, rootClientId ?? '' );
1708
+
1709
+ // Compute section context early so the disabled check below can use it.
1710
+ const isParentSectionBlock = !! isSectionBlock( state, rootClientId );
1711
+ const sectionClientId = isParentSectionBlock
1712
+ ? rootClientId
1713
+ : getParentSectionBlock( state, rootClientId );
1714
+ const isWithinSection = !! sectionClientId;
1715
+
1716
+ // Disabled containers reject all blocks, with one exception: within a
1717
+ // section, the default block (paragraph) is allowed through so it can
1718
+ // reach the content-insertion logic further down (lines 1748-1772)
1719
+ // which conditionally permits it where a sibling paragraph exists.
1708
1720
  if (
1709
1721
  blockEditingMode === 'disabled' &&
1710
- blockName !== getDefaultBlockName()
1722
+ ( ! isWithinSection || blockName !== getDefaultBlockName() )
1711
1723
  ) {
1712
1724
  return false;
1713
1725
  }
@@ -1723,11 +1735,6 @@ const canInsertBlockTypeUnmemoized = (
1723
1735
  // It shouldn't be possible to insert inside a section block unless in
1724
1736
  // some cases when the block is a content block.
1725
1737
  const isContentRoleBlock = isContentBlock( blockName );
1726
- const isParentSectionBlock = !! isSectionBlock( state, rootClientId );
1727
- const sectionClientId = isParentSectionBlock
1728
- ? rootClientId
1729
- : getParentSectionBlock( state, rootClientId );
1730
- const isWithinSection = !! sectionClientId;
1731
1738
  if ( isWithinSection && ! isContentRoleBlock ) {
1732
1739
  return false;
1733
1740
  }