@wordpress/block-editor 9.5.0 → 9.6.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 (147) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/block-lock/modal.js +2 -2
  3. package/build/components/block-lock/modal.js.map +1 -1
  4. package/build/components/block-mobile-toolbar/block-actions-menu.native.js +1 -1
  5. package/build/components/block-mobile-toolbar/block-actions-menu.native.js.map +1 -1
  6. package/build/components/block-mover/mover-description.js +95 -32
  7. package/build/components/block-mover/mover-description.js.map +1 -1
  8. package/build/components/block-settings-menu-controls/index.js +1 -1
  9. package/build/components/block-settings-menu-controls/index.js.map +1 -1
  10. package/build/components/block-styles/preview.native.js +1 -3
  11. package/build/components/block-styles/preview.native.js.map +1 -1
  12. package/build/components/block-tools/block-selection-button.js +1 -7
  13. package/build/components/block-tools/block-selection-button.js.map +1 -1
  14. package/build/components/block-tools/index.js +4 -1
  15. package/build/components/block-tools/index.js.map +1 -1
  16. package/build/components/block-types-list/index.native.js +65 -23
  17. package/build/components/block-types-list/index.native.js.map +1 -1
  18. package/build/components/colors-gradients/control.js +1 -0
  19. package/build/components/colors-gradients/control.js.map +1 -1
  20. package/build/components/colors-gradients/dropdown.js +5 -2
  21. package/build/components/colors-gradients/dropdown.js.map +1 -1
  22. package/build/components/image-editor/cropper.js +4 -3
  23. package/build/components/image-editor/cropper.js.map +1 -1
  24. package/build/components/image-editor/index.js +3 -1
  25. package/build/components/image-editor/index.js.map +1 -1
  26. package/build/components/inserter/block-types-tab.native.js +30 -16
  27. package/build/components/inserter/block-types-tab.native.js.map +1 -1
  28. package/build/components/inserter/preview-panel.js +8 -8
  29. package/build/components/inserter/preview-panel.js.map +1 -1
  30. package/build/components/inserter/reusable-blocks-tab.native.js +5 -1
  31. package/build/components/inserter/reusable-blocks-tab.native.js.map +1 -1
  32. package/build/components/inserter/search-results.native.js +5 -2
  33. package/build/components/inserter/search-results.native.js.map +1 -1
  34. package/build/components/inserter/utils.native.js +21 -0
  35. package/build/components/inserter/utils.native.js.map +1 -1
  36. package/build/components/inserter-list-item/index.js +5 -1
  37. package/build/components/inserter-list-item/index.js.map +1 -1
  38. package/build/components/list-view/branch.js +1 -7
  39. package/build/components/list-view/branch.js.map +1 -1
  40. package/build/components/observe-typing/index.js +22 -8
  41. package/build/components/observe-typing/index.js.map +1 -1
  42. package/build/components/rich-text/format-toolbar-container.js +61 -12
  43. package/build/components/rich-text/format-toolbar-container.js.map +1 -1
  44. package/build/components/rich-text/index.js +2 -1
  45. package/build/components/rich-text/index.js.map +1 -1
  46. package/build/components/rich-text/use-format-types.js +36 -16
  47. package/build/components/rich-text/use-format-types.js.map +1 -1
  48. package/build/components/writing-flow/use-tab-nav.js +1 -1
  49. package/build/components/writing-flow/use-tab-nav.js.map +1 -1
  50. package/build/hooks/layout.js +14 -2
  51. package/build/hooks/layout.js.map +1 -1
  52. package/build/hooks/style.js +41 -31
  53. package/build/hooks/style.js.map +1 -1
  54. package/build/layouts/flow.js +26 -3
  55. package/build/layouts/flow.js.map +1 -1
  56. package/build-module/components/block-lock/modal.js +2 -2
  57. package/build-module/components/block-lock/modal.js.map +1 -1
  58. package/build-module/components/block-mobile-toolbar/block-actions-menu.native.js +2 -2
  59. package/build-module/components/block-mobile-toolbar/block-actions-menu.native.js.map +1 -1
  60. package/build-module/components/block-mover/mover-description.js +97 -33
  61. package/build-module/components/block-mover/mover-description.js.map +1 -1
  62. package/build-module/components/block-settings-menu-controls/index.js +2 -2
  63. package/build-module/components/block-settings-menu-controls/index.js.map +1 -1
  64. package/build-module/components/block-styles/preview.native.js +2 -3
  65. package/build-module/components/block-styles/preview.native.js.map +1 -1
  66. package/build-module/components/block-tools/block-selection-button.js +1 -7
  67. package/build-module/components/block-tools/block-selection-button.js.map +1 -1
  68. package/build-module/components/block-tools/index.js +4 -1
  69. package/build-module/components/block-tools/index.js.map +1 -1
  70. package/build-module/components/block-types-list/index.native.js +67 -25
  71. package/build-module/components/block-types-list/index.native.js.map +1 -1
  72. package/build-module/components/colors-gradients/control.js +1 -0
  73. package/build-module/components/colors-gradients/control.js.map +1 -1
  74. package/build-module/components/colors-gradients/dropdown.js +6 -3
  75. package/build-module/components/colors-gradients/dropdown.js.map +1 -1
  76. package/build-module/components/image-editor/cropper.js +4 -3
  77. package/build-module/components/image-editor/cropper.js.map +1 -1
  78. package/build-module/components/image-editor/index.js +3 -1
  79. package/build-module/components/image-editor/index.js.map +1 -1
  80. package/build-module/components/inserter/block-types-tab.native.js +31 -15
  81. package/build-module/components/inserter/block-types-tab.native.js.map +1 -1
  82. package/build-module/components/inserter/preview-panel.js +9 -9
  83. package/build-module/components/inserter/preview-panel.js.map +1 -1
  84. package/build-module/components/inserter/reusable-blocks-tab.native.js +6 -2
  85. package/build-module/components/inserter/reusable-blocks-tab.native.js.map +1 -1
  86. package/build-module/components/inserter/search-results.native.js +6 -3
  87. package/build-module/components/inserter/search-results.native.js.map +1 -1
  88. package/build-module/components/inserter/utils.native.js +19 -0
  89. package/build-module/components/inserter/utils.native.js.map +1 -1
  90. package/build-module/components/inserter-list-item/index.js +4 -1
  91. package/build-module/components/inserter-list-item/index.js.map +1 -1
  92. package/build-module/components/list-view/branch.js +1 -6
  93. package/build-module/components/list-view/branch.js.map +1 -1
  94. package/build-module/components/observe-typing/index.js +22 -8
  95. package/build-module/components/observe-typing/index.js.map +1 -1
  96. package/build-module/components/rich-text/format-toolbar-container.js +58 -12
  97. package/build-module/components/rich-text/format-toolbar-container.js.map +1 -1
  98. package/build-module/components/rich-text/index.js +2 -1
  99. package/build-module/components/rich-text/index.js.map +1 -1
  100. package/build-module/components/rich-text/use-format-types.js +37 -18
  101. package/build-module/components/rich-text/use-format-types.js.map +1 -1
  102. package/build-module/components/writing-flow/use-tab-nav.js +1 -1
  103. package/build-module/components/writing-flow/use-tab-nav.js.map +1 -1
  104. package/build-module/hooks/layout.js +14 -2
  105. package/build-module/hooks/layout.js.map +1 -1
  106. package/build-module/hooks/style.js +44 -35
  107. package/build-module/hooks/style.js.map +1 -1
  108. package/build-module/layouts/flow.js +25 -3
  109. package/build-module/layouts/flow.js.map +1 -1
  110. package/build-style/style-rtl.css +2 -2
  111. package/build-style/style.css +2 -2
  112. package/package.json +28 -28
  113. package/src/components/block-lock/modal.js +5 -5
  114. package/src/components/block-mobile-toolbar/block-actions-menu.native.js +3 -3
  115. package/src/components/block-mover/mover-description.js +131 -48
  116. package/src/components/block-mover/test/mover-description.js +55 -3
  117. package/src/components/block-settings-menu-controls/index.js +2 -2
  118. package/src/components/block-styles/preview.native.js +2 -2
  119. package/src/components/block-tools/block-selection-button.js +0 -5
  120. package/src/components/block-tools/index.js +4 -1
  121. package/src/components/block-types-list/index.native.js +76 -24
  122. package/src/components/block-types-list/style.native.scss +18 -0
  123. package/src/components/color-palette/test/__snapshots__/control.js.snap +0 -4
  124. package/src/components/colors/test/__snapshots__/with-colors.js.snap +1 -1
  125. package/src/components/colors/test/with-colors.js +1 -1
  126. package/src/components/colors-gradients/control.js +1 -0
  127. package/src/components/colors-gradients/dropdown.js +8 -2
  128. package/src/components/colors-gradients/style.scss +7 -8
  129. package/src/components/image-editor/cropper.js +9 -3
  130. package/src/components/image-editor/index.js +2 -0
  131. package/src/components/inserter/block-types-tab.native.js +42 -21
  132. package/src/components/inserter/preview-panel.js +6 -14
  133. package/src/components/inserter/reusable-blocks-tab.native.js +4 -2
  134. package/src/components/inserter/search-results.native.js +4 -2
  135. package/src/components/inserter/test/block-types-tab.native.js +2 -0
  136. package/src/components/inserter/test/utils.native.js +37 -0
  137. package/src/components/inserter/utils.native.js +11 -0
  138. package/src/components/inserter-list-item/index.js +4 -1
  139. package/src/components/list-view/branch.js +1 -6
  140. package/src/components/observe-typing/index.js +17 -14
  141. package/src/components/rich-text/format-toolbar-container.js +63 -14
  142. package/src/components/rich-text/index.js +1 -0
  143. package/src/components/rich-text/use-format-types.js +38 -17
  144. package/src/components/writing-flow/use-tab-nav.js +1 -1
  145. package/src/hooks/layout.js +14 -3
  146. package/src/hooks/style.js +46 -39
  147. package/src/layouts/flow.js +23 -1
@@ -2,32 +2,81 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { Popover, ToolbarGroup } from '@wordpress/components';
5
+ import { useSelect } from '@wordpress/data';
6
+ import {
7
+ isCollapsed,
8
+ getActiveFormats,
9
+ useAnchorRef,
10
+ store as richTextStore,
11
+ } from '@wordpress/rich-text';
5
12
 
6
13
  /**
7
14
  * Internal dependencies
8
15
  */
9
16
  import BlockControls from '../block-controls';
10
17
  import FormatToolbar from './format-toolbar';
18
+ import { store as blockEditorStore } from '../../store';
19
+
20
+ function InlineSelectionToolbar( { value, anchorRef, activeFormats } ) {
21
+ const lastFormat = activeFormats[ activeFormats.length - 1 ];
22
+ const lastFormatType = lastFormat?.type;
23
+ const settings = useSelect(
24
+ ( select ) => select( richTextStore ).getFormatType( lastFormatType ),
25
+ [ lastFormatType ]
26
+ );
27
+ const selectionRef = useAnchorRef( {
28
+ ref: anchorRef,
29
+ value,
30
+ settings,
31
+ } );
32
+
33
+ return <InlineToolbar anchorRef={ selectionRef } />;
34
+ }
35
+
36
+ function InlineToolbar( { anchorRef } ) {
37
+ return (
38
+ <Popover
39
+ position="top center"
40
+ focusOnMount={ false }
41
+ anchorRef={ anchorRef }
42
+ className="block-editor-rich-text__inline-format-toolbar"
43
+ __unstableSlotName="block-toolbar"
44
+ >
45
+ <div className="block-editor-rich-text__inline-format-toolbar-group">
46
+ <ToolbarGroup>
47
+ <FormatToolbar />
48
+ </ToolbarGroup>
49
+ </div>
50
+ </Popover>
51
+ );
52
+ }
53
+
54
+ const FormatToolbarContainer = ( { inline, anchorRef, value } ) => {
55
+ const hasInlineToolbar = useSelect(
56
+ ( select ) => select( blockEditorStore ).getSettings().hasInlineToolbar,
57
+ []
58
+ );
11
59
 
12
- const FormatToolbarContainer = ( { inline, anchorRef } ) => {
13
60
  if ( inline ) {
14
- // Render in popover.
61
+ return <InlineToolbar anchorRef={ anchorRef } />;
62
+ }
63
+
64
+ if ( hasInlineToolbar ) {
65
+ const activeFormats = getActiveFormats( value );
66
+
67
+ if ( isCollapsed( value ) && ! activeFormats.length ) {
68
+ return null;
69
+ }
70
+
15
71
  return (
16
- <Popover
17
- position="top center"
18
- focusOnMount={ false }
72
+ <InlineSelectionToolbar
19
73
  anchorRef={ anchorRef }
20
- className="block-editor-rich-text__inline-format-toolbar"
21
- __unstableSlotName="block-toolbar"
22
- >
23
- <div className="block-editor-rich-text__inline-format-toolbar-group">
24
- <ToolbarGroup>
25
- <FormatToolbar />
26
- </ToolbarGroup>
27
- </div>
28
- </Popover>
74
+ value={ value }
75
+ activeFormats={ activeFormats }
76
+ />
29
77
  );
30
78
  }
79
+
31
80
  // Render regular toolbar.
32
81
  return (
33
82
  <BlockControls group="inline">
@@ -344,6 +344,7 @@ function RichTextWrapper(
344
344
  <FormatToolbarContainer
345
345
  inline={ inlineToolbar }
346
346
  anchorRef={ anchorRef }
347
+ value={ value }
347
348
  />
348
349
  ) }
349
350
  <TagName
@@ -1,12 +1,13 @@
1
1
  /**
2
- * WordPress dependencies
2
+ * External dependencies
3
3
  */
4
- import { useMemo } from '@wordpress/element';
5
- import { useSelect, useDispatch } from '@wordpress/data';
4
+ import { mapKeys } from 'lodash';
6
5
 
7
6
  /**
8
- * Internal dependencies
7
+ * WordPress dependencies
9
8
  */
9
+ import { useMemo } from '@wordpress/element';
10
+ import { useSelect, useDispatch } from '@wordpress/data';
10
11
  import { store as richTextStore } from '@wordpress/rich-text';
11
12
 
12
13
  function formatTypesSelector( select ) {
@@ -32,6 +33,21 @@ const interactiveContentTags = new Set( [
32
33
  'video',
33
34
  ] );
34
35
 
36
+ function prefixSelectKeys( selected, prefix ) {
37
+ if ( typeof selected !== 'object' ) return { [ prefix ]: selected };
38
+ return mapKeys( selected, ( value, key ) => `${ prefix }.${ key }` );
39
+ }
40
+
41
+ function getPrefixedSelectKeys( selected, prefix ) {
42
+ if ( selected[ prefix ] ) return selected[ prefix ];
43
+ return Object.keys( selected )
44
+ .filter( ( key ) => key.startsWith( prefix + '.' ) )
45
+ .reduce( ( accumulator, key ) => {
46
+ accumulator[ key.slice( prefix.length + 1 ) ] = selected[ key ];
47
+ return accumulator;
48
+ }, {} );
49
+ }
50
+
35
51
  /**
36
52
  * This hook provides RichText with the `formatTypes` and its derived props from
37
53
  * experimental format type settings.
@@ -68,18 +84,23 @@ export function useFormatTypes( {
68
84
  const keyedSelected = useSelect(
69
85
  ( select ) =>
70
86
  formatTypes.reduce( ( accumulator, type ) => {
71
- if ( type.__experimentalGetPropsForEditableTreePreparation ) {
72
- accumulator[ type.name ] =
87
+ if ( ! type.__experimentalGetPropsForEditableTreePreparation ) {
88
+ return accumulator;
89
+ }
90
+
91
+ return {
92
+ ...accumulator,
93
+ ...prefixSelectKeys(
73
94
  type.__experimentalGetPropsForEditableTreePreparation(
74
95
  select,
75
96
  {
76
97
  richTextIdentifier: identifier,
77
98
  blockClientId: clientId,
78
99
  }
79
- );
80
- }
81
-
82
- return accumulator;
100
+ ),
101
+ type.name
102
+ ),
103
+ };
83
104
  }, {} ),
84
105
  [ formatTypes, clientId, identifier ]
85
106
  );
@@ -89,11 +110,14 @@ export function useFormatTypes( {
89
110
  const changeHandlers = [];
90
111
  const dependencies = [];
91
112
 
113
+ for ( const key in keyedSelected ) {
114
+ dependencies.push( keyedSelected[ key ] );
115
+ }
116
+
92
117
  formatTypes.forEach( ( type ) => {
93
118
  if ( type.__experimentalCreatePrepareEditableTree ) {
94
- const selected = keyedSelected[ type.name ];
95
119
  const handler = type.__experimentalCreatePrepareEditableTree(
96
- selected,
120
+ getPrefixedSelectKeys( keyedSelected, type.name ),
97
121
  {
98
122
  richTextIdentifier: identifier,
99
123
  blockClientId: clientId,
@@ -105,10 +129,6 @@ export function useFormatTypes( {
105
129
  } else {
106
130
  prepareHandlers.push( handler );
107
131
  }
108
-
109
- for ( const key in selected ) {
110
- dependencies.push( selected[ key ] );
111
- }
112
132
  }
113
133
 
114
134
  if ( type.__experimentalCreateOnChangeEditableValue ) {
@@ -125,10 +145,11 @@ export function useFormatTypes( {
125
145
  );
126
146
  }
127
147
 
148
+ const selected = getPrefixedSelectKeys( keyedSelected, type.name );
128
149
  changeHandlers.push(
129
150
  type.__experimentalCreateOnChangeEditableValue(
130
151
  {
131
- ...( keyedSelected[ type.name ] || {} ),
152
+ ...( typeof selected === 'object' ? selected : {} ),
132
153
  ...dispatchers,
133
154
  },
134
155
  {
@@ -75,7 +75,7 @@ export default function useTabNav() {
75
75
  return;
76
76
  }
77
77
 
78
- if ( event.keyCode === ESCAPE && ! hasMultiSelection() ) {
78
+ if ( event.keyCode === ESCAPE ) {
79
79
  event.preventDefault();
80
80
  setNavigationMode( true );
81
81
  return;
@@ -49,7 +49,12 @@ const layoutBlockSupportKey = '__experimentalLayout';
49
49
  *
50
50
  * @return { Array } Array of CSS classname strings.
51
51
  */
52
- function getLayoutClasses( layout, layoutDefinitions ) {
52
+ function useLayoutClasses( layout, layoutDefinitions ) {
53
+ const rootPaddingAlignment = useSelect( ( select ) => {
54
+ const { getSettings } = select( blockEditorStore );
55
+ return getSettings().__experimentalFeatures
56
+ ?.useRootPaddingAwareAlignments;
57
+ }, [] );
53
58
  const layoutClassnames = [];
54
59
 
55
60
  if ( layoutDefinitions?.[ layout?.type || 'default' ]?.className ) {
@@ -58,6 +63,10 @@ function getLayoutClasses( layout, layoutDefinitions ) {
58
63
  );
59
64
  }
60
65
 
66
+ if ( ( layout?.inherit || layout?.contentSize ) && rootPaddingAlignment ) {
67
+ layoutClassnames.push( 'has-global-padding' );
68
+ }
69
+
61
70
  if ( layout?.orientation ) {
62
71
  layoutClassnames.push( `is-${ kebabCase( layout.orientation ) }` );
63
72
  }
@@ -136,7 +145,9 @@ function LayoutPanel( { setAttributes, attributes, name: blockName } ) {
136
145
  checked={ ! inherit }
137
146
  onChange={ () =>
138
147
  setAttributes( {
139
- layout: { inherit: ! inherit },
148
+ layout: {
149
+ inherit: ! inherit,
150
+ },
140
151
  } )
141
152
  }
142
153
  />
@@ -267,7 +278,7 @@ export const withLayoutStyles = createHigherOrderComponent(
267
278
  ? defaultThemeLayout
268
279
  : layout || defaultBlockLayout || {};
269
280
  const layoutClasses = shouldRenderLayoutStyles
270
- ? getLayoutClasses( usedLayout, defaultThemeLayout?.definitions )
281
+ ? useLayoutClasses( usedLayout, defaultThemeLayout?.definitions )
271
282
  : null;
272
283
  const selector = `.${ getBlockDefaultClassName(
273
284
  name
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { get, has, isEmpty, kebabCase, omit } from 'lodash';
4
+ import { get, has, omit } from 'lodash';
5
5
  import classnames from 'classnames';
6
6
 
7
7
  /**
8
8
  * WordPress dependencies
9
9
  */
10
- import { useContext, createPortal } from '@wordpress/element';
10
+ import { useContext, useMemo, createPortal } from '@wordpress/element';
11
11
  import { addFilter } from '@wordpress/hooks';
12
12
  import {
13
13
  getBlockSupport,
@@ -16,7 +16,10 @@ import {
16
16
  __EXPERIMENTAL_ELEMENTS as ELEMENTS,
17
17
  } from '@wordpress/blocks';
18
18
  import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
19
- import { getCSSRules } from '@wordpress/style-engine';
19
+ import {
20
+ getCSSRules,
21
+ generate as generateStyles,
22
+ } from '@wordpress/style-engine';
20
23
 
21
24
  /**
22
25
  * Internal dependencies
@@ -68,6 +71,9 @@ export function getInlineStyles( styles = {} ) {
68
71
  const ignoredStyles = [ 'spacing.blockGap' ];
69
72
  const output = {};
70
73
  Object.keys( STYLE_PROPERTY ).forEach( ( propKey ) => {
74
+ if ( STYLE_PROPERTY[ propKey ].rootOnly ) {
75
+ return;
76
+ }
71
77
  const path = STYLE_PROPERTY[ propKey ].value;
72
78
  const subPaths = STYLE_PROPERTY[ propKey ].properties;
73
79
  // Ignore styles on elements because they are handled on the server.
@@ -105,28 +111,6 @@ export function getInlineStyles( styles = {} ) {
105
111
  return output;
106
112
  }
107
113
 
108
- function compileElementsStyles( selector, elements = {} ) {
109
- return Object.entries( elements )
110
- .map( ( [ element, styles ] ) => {
111
- const elementStyles = getInlineStyles( styles );
112
- if ( ! isEmpty( elementStyles ) ) {
113
- // The .editor-styles-wrapper selector is required on elements styles. As it is
114
- // added to all other editor styles, not providing it causes reset and global
115
- // styles to override element styles because of higher specificity.
116
- return [
117
- `.editor-styles-wrapper .${ selector } ${ ELEMENTS[ element ] }{`,
118
- ...Object.entries( elementStyles ).map(
119
- ( [ cssProperty, value ] ) =>
120
- `\t${ kebabCase( cssProperty ) }: ${ value };`
121
- ),
122
- '}',
123
- ].join( '\n' );
124
- }
125
- return '';
126
- } )
127
- .join( '\n' );
128
- }
129
-
130
114
  /**
131
115
  * Filters registered block settings, extending attributes to include `style` attribute.
132
116
  *
@@ -323,23 +307,46 @@ const withElementsStyles = createHigherOrderComponent(
323
307
  'link'
324
308
  );
325
309
 
326
- // The Elements API only supports link colors for now,
327
- // hence the specific omission of `link` in the elements styles.
328
- // This might need to be refactored or removed if the Elements API
329
- // changes or `link` supports styles beyond `color`.
330
- const elements = skipLinkColorSerialization
331
- ? omit( props.attributes.style?.elements, [ 'link' ] )
332
- : props.attributes.style?.elements;
333
-
334
- const styles = compileElementsStyles(
335
- blockElementsContainerIdentifier,
336
- elements
337
- );
310
+ const styles = useMemo( () => {
311
+ const rawElementsStyles = props.attributes.style?.elements;
312
+ const elementCssRules = [];
313
+ if (
314
+ rawElementsStyles &&
315
+ Object.keys( rawElementsStyles ).length > 0
316
+ ) {
317
+ // Remove values based on whether serialization has been skipped for a specific style.
318
+ const filteredElementsStyles = {
319
+ ...rawElementsStyles,
320
+ link: {
321
+ ...rawElementsStyles.link,
322
+ color: ! skipLinkColorSerialization
323
+ ? rawElementsStyles.link?.color
324
+ : undefined,
325
+ },
326
+ };
327
+
328
+ for ( const [ elementName, elementStyles ] of Object.entries(
329
+ filteredElementsStyles
330
+ ) ) {
331
+ const cssRule = generateStyles( elementStyles, {
332
+ // The .editor-styles-wrapper selector is required on elements styles. As it is
333
+ // added to all other editor styles, not providing it causes reset and global
334
+ // styles to override element styles because of higher specificity.
335
+ selector: `.editor-styles-wrapper .${ blockElementsContainerIdentifier } ${ ELEMENTS[ elementName ] }`,
336
+ } );
337
+ if ( !! cssRule ) {
338
+ elementCssRules.push( cssRule );
339
+ }
340
+ }
341
+ }
342
+ return elementCssRules.length > 0 ? elementCssRules : undefined;
343
+ }, [ props.attributes.style?.elements ] );
344
+
338
345
  const element = useContext( BlockList.__unstableElementContext );
339
346
 
340
347
  return (
341
348
  <>
342
- { elements &&
349
+ { styles &&
343
350
  element &&
344
351
  createPortal(
345
352
  <style
@@ -353,7 +360,7 @@ const withElementsStyles = createHigherOrderComponent(
353
360
  <BlockListBlock
354
361
  { ...props }
355
362
  className={
356
- elements
363
+ props.attributes.style?.elements
357
364
  ? classnames(
358
365
  props.className,
359
366
  blockElementsContainerIdentifier
@@ -8,6 +8,7 @@ import {
8
8
  } from '@wordpress/components';
9
9
  import { __, sprintf } from '@wordpress/i18n';
10
10
  import { Icon, positionCenter, stretchWide } from '@wordpress/icons';
11
+ import { getCSSRules } from '@wordpress/style-engine';
11
12
 
12
13
  /**
13
14
  * Internal dependencies
@@ -132,7 +133,7 @@ export default {
132
133
  ? `
133
134
  ${ appendSelectors(
134
135
  selector,
135
- '> :where(:not(.alignleft):not(.alignright))'
136
+ '> :where(:not(.alignleft):not(.alignright):not(.alignfull))'
136
137
  ) } {
137
138
  max-width: ${ contentSize ?? wideSize };
138
139
  margin-left: auto !important;
@@ -147,6 +148,27 @@ export default {
147
148
  `
148
149
  : '';
149
150
 
151
+ // If there is custom padding, add negative margins for alignfull blocks.
152
+ if ( style?.spacing?.padding ) {
153
+ // The style object might be storing a preset so we need to make sure we get a usable value.
154
+ const paddingValues = getCSSRules( style );
155
+ paddingValues.forEach( ( rule ) => {
156
+ if ( rule.key === 'paddingRight' ) {
157
+ output += `
158
+ ${ appendSelectors( selector, '> .alignfull' ) } {
159
+ margin-right: calc(${ rule.value } * -1);
160
+ }
161
+ `;
162
+ } else if ( rule.key === 'paddingLeft' ) {
163
+ output += `
164
+ ${ appendSelectors( selector, '> .alignfull' ) } {
165
+ margin-left: calc(${ rule.value } * -1);
166
+ }
167
+ `;
168
+ }
169
+ } );
170
+ }
171
+
150
172
  // Output blockGap styles based on rules contained in layout definitions in theme.json.
151
173
  if ( hasBlockGapSupport && blockGapValue ) {
152
174
  output += getBlockGapCSS(