@wordpress/block-editor 9.4.0 → 9.5.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 (234) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +1 -8
  3. package/build/components/block-list/block-invalid-warning.native.js +54 -6
  4. package/build/components/block-list/block-invalid-warning.native.js.map +1 -1
  5. package/build/components/block-list/block.js +2 -2
  6. package/build/components/block-list/block.js.map +1 -1
  7. package/build/components/block-list/block.native.js +2 -1
  8. package/build/components/block-list/block.native.js.map +1 -1
  9. package/build/components/block-list/index.native.js +4 -3
  10. package/build/components/block-list/index.native.js.map +1 -1
  11. package/build/components/block-list/layout.js +20 -5
  12. package/build/components/block-list/layout.js.map +1 -1
  13. package/build/components/block-list/use-block-props/use-block-class-names.js +5 -2
  14. package/build/components/block-list/use-block-props/use-block-class-names.js.map +1 -1
  15. package/build/components/block-lock/modal.js +35 -5
  16. package/build/components/block-lock/modal.js.map +1 -1
  17. package/build/components/block-pattern-setup/index.js +5 -17
  18. package/build/components/block-pattern-setup/index.js.map +1 -1
  19. package/build/components/block-popover/inbetween.js +1 -1
  20. package/build/components/block-popover/inbetween.js.map +1 -1
  21. package/build/components/block-popover/index.js +1 -1
  22. package/build/components/block-popover/index.js.map +1 -1
  23. package/build/components/block-settings-menu/block-mode-toggle.js +1 -1
  24. package/build/components/block-settings-menu/block-mode-toggle.js.map +1 -1
  25. package/build/components/block-settings-menu/block-settings-dropdown.js +4 -1
  26. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  27. package/build/components/block-styles/preview.native.js +3 -1
  28. package/build/components/block-styles/preview.native.js.map +1 -1
  29. package/build/components/block-switcher/index.js +7 -1
  30. package/build/components/block-switcher/index.js.map +1 -1
  31. package/build/components/block-title/index.js +8 -2
  32. package/build/components/block-title/index.js.map +1 -1
  33. package/build/components/block-title/use-block-display-title.js +12 -5
  34. package/build/components/block-title/use-block-display-title.js.map +1 -1
  35. package/build/components/block-tools/block-contextual-toolbar.js +1 -1
  36. package/build/components/block-tools/block-contextual-toolbar.js.map +1 -1
  37. package/build/components/border-radius-control/index.js +2 -0
  38. package/build/components/border-radius-control/index.js.map +1 -1
  39. package/build/components/colors/with-colors.js +1 -1
  40. package/build/components/colors/with-colors.js.map +1 -1
  41. package/build/components/colors-gradients/control.js +45 -39
  42. package/build/components/colors-gradients/control.js.map +1 -1
  43. package/build/components/date-format-picker/index.js +1 -1
  44. package/build/components/date-format-picker/index.js.map +1 -1
  45. package/build/components/iframe/index.js +19 -6
  46. package/build/components/iframe/index.js.map +1 -1
  47. package/build/components/link-control/index.js +1 -1
  48. package/build/components/link-control/index.js.map +1 -1
  49. package/build/components/list-view/block-select-button.js +15 -7
  50. package/build/components/list-view/block-select-button.js.map +1 -1
  51. package/build/components/list-view/drop-indicator.js +1 -1
  52. package/build/components/list-view/drop-indicator.js.map +1 -1
  53. package/build/components/media-placeholder/index.js +13 -2
  54. package/build/components/media-placeholder/index.js.map +1 -1
  55. package/build/components/media-replace-flow/index.js +3 -6
  56. package/build/components/media-replace-flow/index.js.map +1 -1
  57. package/build/components/url-popover/index.js +2 -1
  58. package/build/components/url-popover/index.js.map +1 -1
  59. package/build/components/writing-flow/use-arrow-nav.js +34 -2
  60. package/build/components/writing-flow/use-arrow-nav.js.map +1 -1
  61. package/build/components/writing-flow/use-multi-selection.js +3 -47
  62. package/build/components/writing-flow/use-multi-selection.js.map +1 -1
  63. package/build/components/writing-flow/use-selection-observer.js +1 -3
  64. package/build/components/writing-flow/use-selection-observer.js.map +1 -1
  65. package/build/hooks/color.js +2 -4
  66. package/build/hooks/color.js.map +1 -1
  67. package/build/hooks/index.js +8 -0
  68. package/build/hooks/index.js.map +1 -1
  69. package/build/hooks/layout.js +41 -14
  70. package/build/hooks/layout.js.map +1 -1
  71. package/build/hooks/utils.js +5 -3
  72. package/build/hooks/utils.js.map +1 -1
  73. package/build/index.js +7 -0
  74. package/build/index.js.map +1 -1
  75. package/build/layouts/flex.js +40 -36
  76. package/build/layouts/flex.js.map +1 -1
  77. package/build/layouts/flow.js +10 -35
  78. package/build/layouts/flow.js.map +1 -1
  79. package/build/layouts/utils.js +35 -3
  80. package/build/layouts/utils.js.map +1 -1
  81. package/build/store/actions.js +15 -18
  82. package/build/store/actions.js.map +1 -1
  83. package/build/store/index.js +0 -4
  84. package/build/store/index.js.map +1 -1
  85. package/build/store/reducer.js +5 -3
  86. package/build/store/reducer.js.map +1 -1
  87. package/build/store/selectors.js +3 -3
  88. package/build/store/selectors.js.map +1 -1
  89. package/build-module/components/block-list/block-invalid-warning.native.js +50 -6
  90. package/build-module/components/block-list/block-invalid-warning.native.js.map +1 -1
  91. package/build-module/components/block-list/block.js +2 -2
  92. package/build-module/components/block-list/block.js.map +1 -1
  93. package/build-module/components/block-list/block.native.js +2 -1
  94. package/build-module/components/block-list/block.native.js.map +1 -1
  95. package/build-module/components/block-list/index.native.js +3 -1
  96. package/build-module/components/block-list/index.native.js.map +1 -1
  97. package/build-module/components/block-list/layout.js +19 -4
  98. package/build-module/components/block-list/layout.js.map +1 -1
  99. package/build-module/components/block-list/use-block-props/use-block-class-names.js +5 -2
  100. package/build-module/components/block-list/use-block-props/use-block-class-names.js.map +1 -1
  101. package/build-module/components/block-lock/modal.js +37 -6
  102. package/build-module/components/block-lock/modal.js.map +1 -1
  103. package/build-module/components/block-pattern-setup/index.js +6 -18
  104. package/build-module/components/block-pattern-setup/index.js.map +1 -1
  105. package/build-module/components/block-popover/inbetween.js +1 -1
  106. package/build-module/components/block-popover/inbetween.js.map +1 -1
  107. package/build-module/components/block-popover/index.js +1 -1
  108. package/build-module/components/block-popover/index.js.map +1 -1
  109. package/build-module/components/block-settings-menu/block-mode-toggle.js +1 -1
  110. package/build-module/components/block-settings-menu/block-mode-toggle.js.map +1 -1
  111. package/build-module/components/block-settings-menu/block-settings-dropdown.js +4 -1
  112. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  113. package/build-module/components/block-styles/preview.native.js +3 -2
  114. package/build-module/components/block-styles/preview.native.js.map +1 -1
  115. package/build-module/components/block-switcher/index.js +7 -1
  116. package/build-module/components/block-switcher/index.js.map +1 -1
  117. package/build-module/components/block-title/index.js +8 -2
  118. package/build-module/components/block-title/index.js.map +1 -1
  119. package/build-module/components/block-title/use-block-display-title.js +12 -5
  120. package/build-module/components/block-title/use-block-display-title.js.map +1 -1
  121. package/build-module/components/block-tools/block-contextual-toolbar.js +1 -1
  122. package/build-module/components/block-tools/block-contextual-toolbar.js.map +1 -1
  123. package/build-module/components/border-radius-control/index.js +2 -0
  124. package/build-module/components/border-radius-control/index.js.map +1 -1
  125. package/build-module/components/colors/with-colors.js +2 -2
  126. package/build-module/components/colors/with-colors.js.map +1 -1
  127. package/build-module/components/colors-gradients/control.js +46 -40
  128. package/build-module/components/colors-gradients/control.js.map +1 -1
  129. package/build-module/components/date-format-picker/index.js +1 -1
  130. package/build-module/components/date-format-picker/index.js.map +1 -1
  131. package/build-module/components/iframe/index.js +19 -6
  132. package/build-module/components/iframe/index.js.map +1 -1
  133. package/build-module/components/link-control/index.js +1 -1
  134. package/build-module/components/link-control/index.js.map +1 -1
  135. package/build-module/components/list-view/block-select-button.js +16 -8
  136. package/build-module/components/list-view/block-select-button.js.map +1 -1
  137. package/build-module/components/list-view/drop-indicator.js +1 -1
  138. package/build-module/components/list-view/drop-indicator.js.map +1 -1
  139. package/build-module/components/media-placeholder/index.js +13 -2
  140. package/build-module/components/media-placeholder/index.js.map +1 -1
  141. package/build-module/components/media-replace-flow/index.js +4 -7
  142. package/build-module/components/media-replace-flow/index.js.map +1 -1
  143. package/build-module/components/url-popover/index.js +2 -1
  144. package/build-module/components/url-popover/index.js.map +1 -1
  145. package/build-module/components/writing-flow/use-arrow-nav.js +35 -3
  146. package/build-module/components/writing-flow/use-arrow-nav.js.map +1 -1
  147. package/build-module/components/writing-flow/use-multi-selection.js +3 -45
  148. package/build-module/components/writing-flow/use-multi-selection.js.map +1 -1
  149. package/build-module/components/writing-flow/use-selection-observer.js +1 -3
  150. package/build-module/components/writing-flow/use-selection-observer.js.map +1 -1
  151. package/build-module/hooks/color.js +2 -3
  152. package/build-module/hooks/color.js.map +1 -1
  153. package/build-module/hooks/index.js +1 -0
  154. package/build-module/hooks/index.js.map +1 -1
  155. package/build-module/hooks/layout.js +42 -15
  156. package/build-module/hooks/layout.js.map +1 -1
  157. package/build-module/hooks/utils.js +5 -2
  158. package/build-module/hooks/utils.js.map +1 -1
  159. package/build-module/index.js +1 -1
  160. package/build-module/index.js.map +1 -1
  161. package/build-module/layouts/flex.js +41 -33
  162. package/build-module/layouts/flex.js.map +1 -1
  163. package/build-module/layouts/flow.js +11 -36
  164. package/build-module/layouts/flow.js.map +1 -1
  165. package/build-module/layouts/utils.js +33 -3
  166. package/build-module/layouts/utils.js.map +1 -1
  167. package/build-module/store/actions.js +9 -10
  168. package/build-module/store/actions.js.map +1 -1
  169. package/build-module/store/index.js +0 -4
  170. package/build-module/store/index.js.map +1 -1
  171. package/build-module/store/reducer.js +5 -2
  172. package/build-module/store/reducer.js.map +1 -1
  173. package/build-module/store/selectors.js +4 -4
  174. package/build-module/store/selectors.js.map +1 -1
  175. package/build-style/style-rtl.css +36 -10
  176. package/build-style/style.css +36 -10
  177. package/package.json +28 -28
  178. package/src/components/block-list/block-invalid-warning.native.js +42 -7
  179. package/src/components/block-list/block.js +2 -2
  180. package/src/components/block-list/block.native.js +1 -0
  181. package/src/components/block-list/index.native.js +1 -1
  182. package/src/components/block-list/layout.js +15 -3
  183. package/src/components/block-list/style.scss +1 -1
  184. package/src/components/block-list/use-block-props/use-block-class-names.js +5 -1
  185. package/src/components/block-lock/modal.js +42 -4
  186. package/src/components/block-lock/style.scss +10 -0
  187. package/src/components/block-pattern-setup/index.js +3 -15
  188. package/src/components/block-pattern-setup/style.scss +4 -2
  189. package/src/components/block-popover/inbetween.js +1 -1
  190. package/src/components/block-popover/index.js +1 -1
  191. package/src/components/block-settings-menu/block-mode-toggle.js +1 -0
  192. package/src/components/block-settings-menu/block-settings-dropdown.js +4 -1
  193. package/src/components/block-styles/preview.native.js +3 -2
  194. package/src/components/block-switcher/index.js +7 -1
  195. package/src/components/block-title/index.js +3 -2
  196. package/src/components/block-title/use-block-display-title.js +11 -5
  197. package/src/components/block-tools/block-contextual-toolbar.js +3 -1
  198. package/src/components/border-radius-control/index.js +2 -0
  199. package/src/components/colors/with-colors.js +2 -2
  200. package/src/components/colors-gradients/control.js +77 -65
  201. package/src/components/colors-gradients/style.scss +4 -0
  202. package/src/components/colors-gradients/test/control.js +16 -23
  203. package/src/components/date-format-picker/index.js +1 -0
  204. package/src/components/iframe/index.js +25 -6
  205. package/src/components/inserter/style.scss +1 -1
  206. package/src/components/link-control/index.js +1 -0
  207. package/src/components/link-control/test/index.js +6 -4
  208. package/src/components/list-view/block-select-button.js +29 -14
  209. package/src/components/list-view/drop-indicator.js +1 -1
  210. package/src/components/list-view/style.scss +18 -4
  211. package/src/components/media-placeholder/index.js +19 -0
  212. package/src/components/media-replace-flow/index.js +3 -6
  213. package/src/components/media-replace-flow/test/index.js +14 -4
  214. package/src/components/url-popover/index.js +1 -0
  215. package/src/components/url-popover/test/__snapshots__/index.js.snap +3 -0
  216. package/src/components/writing-flow/use-arrow-nav.js +32 -1
  217. package/src/components/writing-flow/use-multi-selection.js +1 -48
  218. package/src/components/writing-flow/use-selection-observer.js +2 -3
  219. package/src/hooks/color.js +10 -3
  220. package/src/hooks/index.js +1 -0
  221. package/src/hooks/layout.js +46 -20
  222. package/src/hooks/utils.js +7 -3
  223. package/src/index.js +1 -0
  224. package/src/layouts/flex.js +47 -41
  225. package/src/layouts/flow.js +14 -35
  226. package/src/layouts/test/flex.js +21 -0
  227. package/src/layouts/test/flow.js +21 -0
  228. package/src/layouts/test/utils.js +138 -0
  229. package/src/layouts/utils.js +44 -3
  230. package/src/store/actions.js +10 -11
  231. package/src/store/index.js +0 -4
  232. package/src/store/reducer.js +3 -2
  233. package/src/store/selectors.js +3 -4
  234. package/tsconfig.json +2 -1
@@ -11,14 +11,12 @@ import {
11
11
  arrowDown,
12
12
  } from '@wordpress/icons';
13
13
  import { Button, ToggleControl, Flex, FlexItem } from '@wordpress/components';
14
- import { getBlockSupport } from '@wordpress/blocks';
15
14
 
16
15
  /**
17
16
  * Internal dependencies
18
17
  */
19
- import { appendSelectors } from './utils';
18
+ import { appendSelectors, getBlockGapCSS } from './utils';
20
19
  import { getGapCSSValue } from '../hooks/gap';
21
- import useSetting from '../components/use-setting';
22
20
  import {
23
21
  BlockControls,
24
22
  JustifyContentControl,
@@ -107,59 +105,67 @@ export default {
107
105
  </BlockControls>
108
106
  );
109
107
  },
110
- save: function FlexLayoutStyle( { selector, layout, style, blockName } ) {
108
+ getLayoutStyle: function getLayoutStyle( {
109
+ selector,
110
+ layout,
111
+ style,
112
+ blockName,
113
+ hasBlockGapSupport,
114
+ layoutDefinitions,
115
+ } ) {
111
116
  const { orientation = 'horizontal' } = layout;
112
- const blockGapSupport = useSetting( 'spacing.blockGap' );
113
- const fallbackValue =
114
- getBlockSupport( blockName, [
115
- 'spacing',
116
- 'blockGap',
117
- '__experimentalDefault',
118
- ] ) || '0.5em';
119
117
 
120
- const hasBlockGapStylesSupport = blockGapSupport !== null;
121
118
  // If a block's block.json skips serialization for spacing or spacing.blockGap,
122
119
  // don't apply the user-defined value to the styles.
123
120
  const blockGapValue =
124
121
  style?.spacing?.blockGap &&
125
122
  ! shouldSkipSerialization( blockName, 'spacing', 'blockGap' )
126
- ? getGapCSSValue( style?.spacing?.blockGap, fallbackValue )
127
- : `var( --wp--style--block-gap, ${ fallbackValue } )`;
128
- const justifyContent =
129
- justifyContentMap[ layout.justifyContent ] ||
130
- justifyContentMap.left;
123
+ ? getGapCSSValue( style?.spacing?.blockGap )
124
+ : undefined;
125
+ const justifyContent = justifyContentMap[ layout.justifyContent ];
131
126
  const flexWrap = flexWrapOptions.includes( layout.flexWrap )
132
127
  ? layout.flexWrap
133
128
  : 'wrap';
134
129
  const verticalAlignment =
135
- verticalAlignmentMap[ layout.verticalAlignment ] ||
136
- verticalAlignmentMap.center;
137
- const rowOrientation = `
138
- flex-direction: row;
139
- align-items: ${ verticalAlignment };
140
- justify-content: ${ justifyContent };
141
- `;
130
+ verticalAlignmentMap[ layout.verticalAlignment ];
142
131
  const alignItems =
143
132
  alignItemsMap[ layout.justifyContent ] || alignItemsMap.left;
144
- const columnOrientation = `
145
- flex-direction: column;
146
- align-items: ${ alignItems };
147
- `;
148
133
 
149
- return (
150
- <style>{ `
151
- ${ appendSelectors( selector ) } {
152
- display: flex;
153
- flex-wrap: ${ flexWrap };
154
- gap: ${ hasBlockGapStylesSupport ? blockGapValue : fallbackValue };
155
- ${ orientation === 'horizontal' ? rowOrientation : columnOrientation }
156
- }
134
+ let output = '';
135
+ const rules = [];
157
136
 
158
- ${ appendSelectors( selector, '> *' ) } {
159
- margin: 0;
160
- }
161
- ` }</style>
162
- );
137
+ if ( flexWrap && flexWrap !== 'wrap' ) {
138
+ rules.push( `flex-wrap: ${ flexWrap }` );
139
+ }
140
+
141
+ if ( orientation === 'horizontal' ) {
142
+ if ( verticalAlignment ) {
143
+ rules.push( `align-items: ${ verticalAlignment }` );
144
+ }
145
+ if ( justifyContent ) {
146
+ rules.push( `justify-content: ${ justifyContent }` );
147
+ }
148
+ } else {
149
+ rules.push( 'flex-direction: column' );
150
+ rules.push( `align-items: ${ alignItems }` );
151
+ }
152
+
153
+ if ( rules.length ) {
154
+ output = `${ appendSelectors( selector ) } {
155
+ ${ rules.join( '; ' ) };
156
+ }`;
157
+ }
158
+
159
+ // Output blockGap styles based on rules contained in layout definitions in theme.json.
160
+ if ( hasBlockGapSupport && blockGapValue ) {
161
+ output += getBlockGapCSS(
162
+ selector,
163
+ layoutDefinitions,
164
+ 'flex',
165
+ blockGapValue
166
+ );
167
+ }
168
+ return output;
163
169
  },
164
170
  getOrientation( layout ) {
165
171
  const { orientation = 'horizontal' } = layout;
@@ -13,7 +13,7 @@ import { Icon, positionCenter, stretchWide } from '@wordpress/icons';
13
13
  * Internal dependencies
14
14
  */
15
15
  import useSetting from '../components/use-setting';
16
- import { appendSelectors } from './utils';
16
+ import { appendSelectors, getBlockGapCSS } from './utils';
17
17
  import { getGapBoxControlValueFromStyle } from '../hooks/gap';
18
18
  import { shouldSkipSerialization } from '../hooks/utils';
19
19
 
@@ -107,15 +107,15 @@ export default {
107
107
  toolBarControls: function DefaultLayoutToolbarControls() {
108
108
  return null;
109
109
  },
110
- save: function DefaultLayoutStyle( {
110
+ getLayoutStyle: function getLayoutStyle( {
111
111
  selector,
112
112
  layout = {},
113
113
  style,
114
114
  blockName,
115
+ hasBlockGapSupport,
116
+ layoutDefinitions,
115
117
  } ) {
116
118
  const { contentSize, wideSize } = layout;
117
- const blockGapSupport = useSetting( 'spacing.blockGap' );
118
- const hasBlockGapStylesSupport = blockGapSupport !== null;
119
119
  const blockGapStyleValue = getGapBoxControlValueFromStyle(
120
120
  style?.spacing?.blockGap
121
121
  );
@@ -125,7 +125,7 @@ export default {
125
125
  blockGapStyleValue?.top &&
126
126
  ! shouldSkipSerialization( blockName, 'spacing', 'blockGap' )
127
127
  ? blockGapStyleValue?.top
128
- : 'var( --wp--style--block-gap )';
128
+ : '';
129
129
 
130
130
  let output =
131
131
  !! contentSize || !! wideSize
@@ -147,37 +147,16 @@ export default {
147
147
  `
148
148
  : '';
149
149
 
150
- output += `
151
- ${ appendSelectors( selector, '> .alignleft' ) } {
152
- float: left;
153
- margin-inline-start: 0;
154
- margin-inline-end: 2em;
155
- }
156
- ${ appendSelectors( selector, '> .alignright' ) } {
157
- float: right;
158
- margin-inline-start: 2em;
159
- margin-inline-end: 0;
160
- }
161
-
162
- ${ appendSelectors( selector, '> .aligncenter' ) } {
163
- margin-left: auto !important;
164
- margin-right: auto !important;
165
- }
166
- `;
167
-
168
- if ( hasBlockGapStylesSupport ) {
169
- output += `
170
- ${ appendSelectors( selector, '> *' ) } {
171
- margin-block-start: 0;
172
- margin-block-end: 0;
173
- }
174
- ${ appendSelectors( selector, '> * + *' ) } {
175
- margin-block-start: ${ blockGapValue };
176
- }
177
- `;
150
+ // Output blockGap styles based on rules contained in layout definitions in theme.json.
151
+ if ( hasBlockGapSupport && blockGapValue ) {
152
+ output += getBlockGapCSS(
153
+ selector,
154
+ layoutDefinitions,
155
+ 'default',
156
+ blockGapValue
157
+ );
178
158
  }
179
-
180
- return <style>{ output }</style>;
159
+ return output;
181
160
  },
182
161
  getOrientation() {
183
162
  return 'vertical';
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import flex from '../flex';
5
+
6
+ describe( 'getLayoutStyle', () => {
7
+ it( 'should return an empty string if no non-default params are provided', () => {
8
+ const expected = '';
9
+
10
+ const result = flex.getLayoutStyle( {
11
+ selector: '.my-container',
12
+ layout: {},
13
+ style: {},
14
+ blockName: 'test-block',
15
+ hasBlockGapSupport: false,
16
+ layoutDefinitions: undefined,
17
+ } );
18
+
19
+ expect( result ).toBe( expected );
20
+ } );
21
+ } );
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import flow from '../flow';
5
+
6
+ describe( 'getLayoutStyle', () => {
7
+ it( 'should return an empty string if no non-default params are provided', () => {
8
+ const expected = '';
9
+
10
+ const result = flow.getLayoutStyle( {
11
+ selector: '.my-container',
12
+ layout: {},
13
+ style: {},
14
+ blockName: 'test-block',
15
+ hasBlockGapSupport: false,
16
+ layoutDefinitions: undefined,
17
+ } );
18
+
19
+ expect( result ).toBe( expected );
20
+ } );
21
+ } );
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import { appendSelectors, getBlockGapCSS } from '../utils';
5
+
6
+ const layoutDefinitions = {
7
+ default: {
8
+ spacingStyles: [
9
+ {
10
+ selector: ' > *',
11
+ rules: {
12
+ 'margin-block-start': '0',
13
+ 'margin-block-end': '0',
14
+ },
15
+ },
16
+ {
17
+ selector: ' > * + *',
18
+ rules: {
19
+ 'margin-block-start': null,
20
+ 'margin-block-end': '0',
21
+ },
22
+ },
23
+ ],
24
+ },
25
+ flex: {
26
+ spacingStyles: [
27
+ {
28
+ selector: '',
29
+ rules: {
30
+ gap: null,
31
+ },
32
+ },
33
+ ],
34
+ },
35
+ };
36
+
37
+ describe( 'getBlockGapCSS', () => {
38
+ it( 'should output default blockGap rules', () => {
39
+ const expected =
40
+ '.editor-styles-wrapper .my-container > * { margin-block-start: 0; margin-block-end: 0; }.editor-styles-wrapper .my-container > * + * { margin-block-start: 3em; margin-block-end: 0; }';
41
+
42
+ const result = getBlockGapCSS(
43
+ '.my-container',
44
+ layoutDefinitions,
45
+ 'default',
46
+ '3em'
47
+ );
48
+
49
+ expect( result ).toBe( expected );
50
+ } );
51
+
52
+ it( 'should output flex blockGap rules', () => {
53
+ const expected = '.editor-styles-wrapper .my-container { gap: 3em; }';
54
+
55
+ const result = getBlockGapCSS(
56
+ '.my-container',
57
+ layoutDefinitions,
58
+ 'flex',
59
+ '3em'
60
+ );
61
+
62
+ expect( result ).toBe( expected );
63
+ } );
64
+
65
+ it( 'should return an empty string if layout type cannot be found', () => {
66
+ const expected = '';
67
+
68
+ const result = getBlockGapCSS(
69
+ '.my-container',
70
+ layoutDefinitions,
71
+ 'aTypeThatDoesNotExist',
72
+ '3em'
73
+ );
74
+
75
+ expect( result ).toBe( expected );
76
+ } );
77
+
78
+ it( 'should return an empty string if layout definitions cannot be found', () => {
79
+ const expected = '';
80
+
81
+ const result = getBlockGapCSS(
82
+ '.my-container',
83
+ undefined,
84
+ 'flex',
85
+ '3em'
86
+ );
87
+
88
+ expect( result ).toBe( expected );
89
+ } );
90
+
91
+ it( 'should return an empty string if blockGap is empty', () => {
92
+ const expected = '';
93
+
94
+ const result = getBlockGapCSS(
95
+ '.my-container',
96
+ layoutDefinitions,
97
+ 'flex',
98
+ null
99
+ );
100
+
101
+ expect( result ).toBe( expected );
102
+ } );
103
+
104
+ it( 'should treat a blockGap string containing 0 as a valid value', () => {
105
+ const expected = '.editor-styles-wrapper .my-container { gap: 0; }';
106
+
107
+ const result = getBlockGapCSS(
108
+ '.my-container',
109
+ layoutDefinitions,
110
+ 'flex',
111
+ '0'
112
+ );
113
+
114
+ expect( result ).toBe( expected );
115
+ } );
116
+ } );
117
+
118
+ describe( 'appendSelectors', () => {
119
+ it( 'should append a subselector without an appended selector', () => {
120
+ expect( appendSelectors( '.original-selector' ) ).toBe(
121
+ '.editor-styles-wrapper .original-selector'
122
+ );
123
+ } );
124
+
125
+ it( 'should append a subselector to a single selector', () => {
126
+ expect( appendSelectors( '.original-selector', '.appended' ) ).toBe(
127
+ '.editor-styles-wrapper .original-selector .appended'
128
+ );
129
+ } );
130
+
131
+ it( 'should append a subselector to multiple selectors', () => {
132
+ expect(
133
+ appendSelectors( '.first-selector,.second-selector', '.appended' )
134
+ ).toBe(
135
+ '.editor-styles-wrapper .first-selector .appended,.editor-styles-wrapper .second-selector .appended'
136
+ );
137
+ } );
138
+ } );
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Utility to generate the proper CSS selector for layout styles.
3
3
  *
4
- * @param {string|string[]} selectors - CSS selectors
5
- * @param {boolean} append - string to append.
4
+ * @param {string} selectors CSS selector, also supports multiple comma-separated selectors.
5
+ * @param {string} append The string to append.
6
6
  *
7
7
  * @return {string} - CSS selector.
8
8
  */
@@ -17,7 +17,48 @@ export function appendSelectors( selectors, append = '' ) {
17
17
  .split( ',' )
18
18
  .map(
19
19
  ( subselector ) =>
20
- `.editor-styles-wrapper ${ subselector } ${ append }`
20
+ `.editor-styles-wrapper ${ subselector }${
21
+ append ? ` ${ append }` : ''
22
+ }`
21
23
  )
22
24
  .join( ',' );
23
25
  }
26
+
27
+ /**
28
+ * Get generated blockGap CSS rules based on layout definitions provided in theme.json
29
+ * Falsy values in the layout definition's spacingStyles rules will be swapped out
30
+ * with the provided `blockGapValue`.
31
+ *
32
+ * @param {string} selector The CSS selector to target for the generated rules.
33
+ * @param {Object} layoutDefinitions Layout definitions object from theme.json.
34
+ * @param {string} layoutType The layout type (e.g. `default` or `flex`).
35
+ * @param {string} blockGapValue The current blockGap value to be applied.
36
+ * @return {string} The generated CSS rules.
37
+ */
38
+ export function getBlockGapCSS(
39
+ selector,
40
+ layoutDefinitions,
41
+ layoutType,
42
+ blockGapValue
43
+ ) {
44
+ let output = '';
45
+ if (
46
+ layoutDefinitions?.[ layoutType ]?.spacingStyles?.length &&
47
+ blockGapValue
48
+ ) {
49
+ layoutDefinitions[ layoutType ].spacingStyles.forEach( ( gapStyle ) => {
50
+ output += `${ appendSelectors(
51
+ selector,
52
+ gapStyle.selector.trim()
53
+ ) } { `;
54
+ output += Object.entries( gapStyle.rules )
55
+ .map(
56
+ ( [ cssProperty, value ] ) =>
57
+ `${ cssProperty }: ${ value ? value : blockGapValue }`
58
+ )
59
+ .join( '; ' );
60
+ output += '; }';
61
+ } );
62
+ }
63
+ return output;
64
+ }
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { castArray, first, isObject, last, some } from 'lodash';
5
-
6
1
  /**
7
2
  * WordPress dependencies
8
3
  */
@@ -31,6 +26,9 @@ import {
31
26
  START_OF_SELECTED_AREA,
32
27
  } from '../utils/selection';
33
28
 
29
+ const castArray = ( maybeArray ) =>
30
+ Array.isArray( maybeArray ) ? maybeArray : [ maybeArray ];
31
+
34
32
  /**
35
33
  * Action which will insert a default block insert action if there
36
34
  * are no other blocks at the root of the editor. This action should be used
@@ -396,7 +394,7 @@ export const replaceBlocks =
396
394
  castArray( blocks ),
397
395
  select.getSettings()
398
396
  );
399
- const rootClientId = select.getBlockRootClientId( first( clientIds ) );
397
+ const rootClientId = select.getBlockRootClientId( clientIds[ 0 ] );
400
398
  // Replace is valid if the new blocks can be inserted in the root block.
401
399
  for ( let index = 0; index < blocks.length; index++ ) {
402
400
  const block = blocks[ index ];
@@ -583,7 +581,7 @@ export const insertBlocks =
583
581
  ) =>
584
582
  ( { select, dispatch } ) => {
585
583
  /* eslint-enable jsdoc/valid-types */
586
- if ( isObject( initialPosition ) ) {
584
+ if ( initialPosition !== null && typeof initialPosition === 'object' ) {
587
585
  meta = initialPosition;
588
586
  initialPosition = 0;
589
587
  deprecated(
@@ -1504,7 +1502,7 @@ export const duplicateBlocks =
1504
1502
 
1505
1503
  // Return early if blocks don't exist.
1506
1504
  const blocks = select.getBlocksByClientId( clientIds );
1507
- if ( some( blocks, ( block ) => ! block ) ) {
1505
+ if ( blocks.some( ( block ) => ! block ) ) {
1508
1506
  return;
1509
1507
  }
1510
1508
 
@@ -1520,8 +1518,9 @@ export const duplicateBlocks =
1520
1518
  }
1521
1519
 
1522
1520
  const rootClientId = select.getBlockRootClientId( clientIds[ 0 ] );
1521
+ const clientIdsArray = castArray( clientIds );
1523
1522
  const lastSelectedIndex = select.getBlockIndex(
1524
- last( castArray( clientIds ) )
1523
+ clientIdsArray[ clientIdsArray.length - 1 ]
1525
1524
  );
1526
1525
  const clonedBlocks = blocks.map( ( block ) =>
1527
1526
  __experimentalCloneSanitizedBlock( block )
@@ -1534,8 +1533,8 @@ export const duplicateBlocks =
1534
1533
  );
1535
1534
  if ( clonedBlocks.length > 1 && updateSelection ) {
1536
1535
  dispatch.multiSelect(
1537
- first( clonedBlocks ).clientId,
1538
- last( clonedBlocks ).clientId
1536
+ clonedBlocks[ 0 ].clientId,
1537
+ clonedBlocks[ clonedBlocks.length - 1 ].clientId
1539
1538
  );
1540
1539
  }
1541
1540
  return clonedBlocks.map( ( block ) => block.clientId );
@@ -15,8 +15,6 @@ import { STORE_NAME } from './constants';
15
15
  * Block editor data store configuration.
16
16
  *
17
17
  * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#registerStore
18
- *
19
- * @type {Object}
20
18
  */
21
19
  export const storeConfig = {
22
20
  reducer,
@@ -28,8 +26,6 @@ export const storeConfig = {
28
26
  * Store definition for the block editor namespace.
29
27
  *
30
28
  * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
31
- *
32
- * @type {Object}
33
29
  */
34
30
  export const store = createReduxStore( STORE_NAME, {
35
31
  ...storeConfig,
@@ -11,7 +11,6 @@ import {
11
11
  mapValues,
12
12
  isEqual,
13
13
  isEmpty,
14
- identity,
15
14
  omitBy,
16
15
  } from 'lodash';
17
16
 
@@ -26,6 +25,8 @@ import { store as blocksStore } from '@wordpress/blocks';
26
25
  import { PREFERENCES_DEFAULTS, SETTINGS_DEFAULTS } from './defaults';
27
26
  import { insertAt, moveTo } from './array';
28
27
 
28
+ const identity = ( x ) => x;
29
+
29
30
  /**
30
31
  * Given an array of blocks, returns an object where each key is a nesting
31
32
  * context, the value of which is an array of block client IDs existing within
@@ -1690,7 +1691,7 @@ export function lastBlockAttributesChange( state, action ) {
1690
1691
  /**
1691
1692
  * Reducer returning automatic change state.
1692
1693
  *
1693
- * @param {boolean} state Current state.
1694
+ * @param {?string} state Current state.
1694
1695
  * @param {Object} action Dispatched action.
1695
1696
  *
1696
1697
  * @return {string} Updated state.
@@ -4,7 +4,6 @@
4
4
  import {
5
5
  castArray,
6
6
  first,
7
- isBoolean,
8
7
  last,
9
8
  map,
10
9
  reduce,
@@ -1382,7 +1381,7 @@ export function getBlockInsertionPoint( state ) {
1382
1381
 
1383
1382
  if ( clientId ) {
1384
1383
  rootClientId = getBlockRootClientId( state, clientId ) || undefined;
1385
- index = getBlockIndex( state, selectionEnd.clientId, rootClientId ) + 1;
1384
+ index = getBlockIndex( state, selectionEnd.clientId ) + 1;
1386
1385
  } else {
1387
1386
  index = getBlockOrder( state ).length;
1388
1387
  }
@@ -1445,7 +1444,7 @@ export function getTemplateLock( state, rootClientId ) {
1445
1444
  }
1446
1445
 
1447
1446
  const checkAllowList = ( list, item, defaultResult = null ) => {
1448
- if ( isBoolean( list ) ) {
1447
+ if ( typeof list === 'boolean' ) {
1449
1448
  return list;
1450
1449
  }
1451
1450
  if ( Array.isArray( list ) ) {
@@ -2218,7 +2217,7 @@ export const __experimentalGetDirectInsertBlock = createSelector(
2218
2217
  );
2219
2218
 
2220
2219
  const checkAllowListRecursive = ( blocks, allowedBlockTypes ) => {
2221
- if ( isBoolean( allowedBlockTypes ) ) {
2220
+ if ( typeof allowedBlockTypes === 'boolean' ) {
2222
2221
  return allowedBlockTypes;
2223
2222
  }
2224
2223
 
package/tsconfig.json CHANGED
@@ -7,7 +7,8 @@
7
7
  "references": [
8
8
  { "path": "../deprecated" },
9
9
  { "path": "../element" },
10
- { "path": "../hooks" }
10
+ { "path": "../hooks" },
11
+ { "path": "../data" }
11
12
  ],
12
13
  // NOTE: This package is being progressively typed. You are encouraged to
13
14
  // expand this array with files which can be type-checked. At some point in