@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
@@ -6,7 +6,11 @@ import classnames from 'classnames';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- import { Button } from '@wordpress/components';
9
+ import {
10
+ Button,
11
+ __experimentalHStack as HStack,
12
+ __experimentalTruncate as Truncate,
13
+ } from '@wordpress/components';
10
14
  import { forwardRef } from '@wordpress/element';
11
15
  import { Icon, lock } from '@wordpress/icons';
12
16
  import { SPACE, ENTER } from '@wordpress/keycodes';
@@ -16,7 +20,7 @@ import { SPACE, ENTER } from '@wordpress/keycodes';
16
20
  */
17
21
  import BlockIcon from '../block-icon';
18
22
  import useBlockDisplayInformation from '../use-block-display-information';
19
- import BlockTitle from '../block-title';
23
+ import useBlockDisplayTitle from '../block-title/use-block-display-title';
20
24
  import ListViewExpander from './expander';
21
25
  import { useBlockLock } from '../block-lock';
22
26
 
@@ -35,6 +39,10 @@ function ListViewBlockSelectButton(
35
39
  ref
36
40
  ) {
37
41
  const blockInformation = useBlockDisplayInformation( clientId );
42
+ const blockTitle = useBlockDisplayTitle( {
43
+ clientId,
44
+ context: 'list-view',
45
+ } );
38
46
  const { isLocked } = useBlockLock( clientId );
39
47
 
40
48
  // The `href` attribute triggers the browser's native HTML drag operations.
@@ -72,19 +80,26 @@ function ListViewBlockSelectButton(
72
80
  >
73
81
  <ListViewExpander onClick={ onToggleExpanded } />
74
82
  <BlockIcon icon={ blockInformation?.icon } showColors />
75
- <span className="block-editor-list-view-block-select-button__title">
76
- <BlockTitle clientId={ clientId } maximumLength={ 35 } />
77
- </span>
78
- { blockInformation?.anchor && (
79
- <span className="block-editor-list-view-block-select-button__anchor">
80
- { blockInformation.anchor }
83
+ <HStack
84
+ alignment="center"
85
+ className="block-editor-list-view-block-select-button__label-wrapper"
86
+ justify="flex-start"
87
+ spacing={ 1 }
88
+ >
89
+ <span className="block-editor-list-view-block-select-button__title">
90
+ <Truncate ellipsizeMode="auto">{ blockTitle }</Truncate>
81
91
  </span>
82
- ) }
83
- { isLocked && (
84
- <span className="block-editor-list-view-block-select-button__lock">
85
- <Icon icon={ lock } />
86
- </span>
87
- ) }
92
+ { blockInformation?.anchor && (
93
+ <span className="block-editor-list-view-block-select-button__anchor">
94
+ { blockInformation.anchor }
95
+ </span>
96
+ ) }
97
+ { isLocked && (
98
+ <span className="block-editor-list-view-block-select-button__lock">
99
+ <Icon icon={ lock } />
100
+ </span>
101
+ ) }
102
+ </HStack>
88
103
  </Button>
89
104
  </>
90
105
  );
@@ -81,7 +81,7 @@ export default function ListViewDropIndicator( {
81
81
  left: rect.left + indent,
82
82
  right: rect.right,
83
83
  width: 0,
84
- height: rect.height,
84
+ height: 0,
85
85
  ownerDocument,
86
86
  };
87
87
 
@@ -97,7 +97,7 @@
97
97
  align-items: center;
98
98
  width: 100%;
99
99
  height: auto;
100
- padding: ($grid-unit-15 * 0.5) $grid-unit-15 ($grid-unit-15 * 0.5) 0;
100
+ padding: ($grid-unit-15 * 0.5) $grid-unit-05 ($grid-unit-15 * 0.5) 0;
101
101
  text-align: left;
102
102
  color: $gray-900;
103
103
  border-radius: $radius-block-ui;
@@ -207,7 +207,7 @@
207
207
  }
208
208
 
209
209
  .block-editor-list-view-block__menu-cell {
210
- padding-right: 5px;
210
+ padding-right: $grid-unit-05;
211
211
 
212
212
  .components-button.has-icon {
213
213
  height: 24px;
@@ -297,13 +297,27 @@
297
297
  }
298
298
  }
299
299
 
300
+ .block-editor-list-view-block-select-button__label-wrapper {
301
+ min-width: 120px;
302
+ }
303
+
304
+ .block-editor-list-view-block-select-button__title {
305
+ flex: 1;
306
+ position: relative;
307
+
308
+ .components-truncate {
309
+ position: absolute;
310
+ width: 100%;
311
+ transform: translateY(-50%);
312
+ }
313
+ }
314
+
300
315
  .block-editor-list-view-block-select-button__anchor {
301
316
  background: rgba($black, 0.1);
302
317
  border-radius: $radius-block-ui;
303
318
  display: inline-block;
304
319
  padding: 2px 6px;
305
- margin: 0 $grid-unit-10;
306
- max-width: 120px;
320
+ max-width: min(100px, 40%);
307
321
  overflow: hidden;
308
322
  text-overflow: ellipsis;
309
323
  }
@@ -71,6 +71,7 @@ export function MediaPlaceholder( {
71
71
  onSelect,
72
72
  onCancel,
73
73
  onSelectURL,
74
+ onToggleFeaturedImage,
74
75
  onDoubleClick,
75
76
  onFilesPreUpload = noop,
76
77
  onHTMLDrop = noop,
@@ -307,6 +308,22 @@ export function MediaPlaceholder( {
307
308
  );
308
309
  };
309
310
 
311
+ const renderFeaturedImageToggle = () => {
312
+ return (
313
+ onToggleFeaturedImage && (
314
+ <div className="block-editor-media-placeholder__url-input-container">
315
+ <Button
316
+ className="block-editor-media-placeholder__button"
317
+ onClick={ onToggleFeaturedImage }
318
+ variant="tertiary"
319
+ >
320
+ { __( 'Use featured image' ) }
321
+ </Button>
322
+ </div>
323
+ )
324
+ );
325
+ };
326
+
310
327
  const renderMediaUploadChecked = () => {
311
328
  const defaultButton = ( { open } ) => {
312
329
  return (
@@ -361,6 +378,7 @@ export function MediaPlaceholder( {
361
378
  </Button>
362
379
  { uploadMediaLibraryButton }
363
380
  { renderUrlSelectionUI() }
381
+ { renderFeaturedImageToggle() }
364
382
  { renderCancelLink() }
365
383
  </>
366
384
  );
@@ -389,6 +407,7 @@ export function MediaPlaceholder( {
389
407
  </FormFileUpload>
390
408
  { uploadMediaLibraryButton }
391
409
  { renderUrlSelectionUI() }
410
+ { renderFeaturedImageToggle() }
392
411
  { renderCancelLink() }
393
412
  </>
394
413
  );
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useState, useRef } from '@wordpress/element';
4
+ import { useRef } from '@wordpress/element';
5
5
  import { __ } from '@wordpress/i18n';
6
6
  import { speak } from '@wordpress/a11y';
7
7
  import {
@@ -55,7 +55,6 @@ const MediaReplaceFlow = ( {
55
55
  addToGallery,
56
56
  handleUpload = true,
57
57
  } ) => {
58
- const [ mediaURLValue, setMediaURLValue ] = useState( mediaURL );
59
58
  const mediaUpload = useSelect( ( select ) => {
60
59
  return select( blockEditorStore ).getSettings().mediaUpload;
61
60
  }, [] );
@@ -88,7 +87,6 @@ const MediaReplaceFlow = ( {
88
87
  onToggleFeaturedImage();
89
88
  }
90
89
  closeMenu();
91
- setMediaURLValue( media?.url );
92
90
  // Calling `onSelect` after the state update since it might unmount the component.
93
91
  onSelect( media );
94
92
  speak( __( 'The media file has been replaced' ) );
@@ -213,14 +211,13 @@ const MediaReplaceFlow = ( {
213
211
  { __( 'Current media URL:' ) }
214
212
  </span>
215
213
 
216
- <Tooltip text={ mediaURLValue } position="bottom">
214
+ <Tooltip text={ mediaURL } position="bottom">
217
215
  <div>
218
216
  <LinkControl
219
- value={ { url: mediaURLValue } }
217
+ value={ { url: mediaURL } }
220
218
  settings={ [] }
221
219
  showSuggestions={ false }
222
220
  onChange={ ( { url } ) => {
223
- setMediaURLValue( url );
224
221
  onSelectURL( url );
225
222
  editMediaButtonRef.current.focus();
226
223
  } }
@@ -3,6 +3,11 @@
3
3
  */
4
4
  import { render, fireEvent } from '@testing-library/react';
5
5
 
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { useState } from '@wordpress/element';
10
+
6
11
  /**
7
12
  * Internal dependencies
8
13
  */
@@ -10,19 +15,24 @@ import MediaReplaceFlow from '../';
10
15
 
11
16
  const noop = () => {};
12
17
 
13
- function setUpMediaReplaceFlow() {
14
- const { container } = render(
18
+ function TestWrapper() {
19
+ const [ mediaURL, setMediaURL ] = useState( 'https://example.media' );
20
+ return (
15
21
  <MediaReplaceFlow
16
22
  mediaId={ 1 }
17
- mediaURL={ 'https://example.media' }
23
+ mediaURL={ mediaURL }
18
24
  allowedTypes={ [ 'png' ] }
19
25
  accept="image/*"
20
26
  onSelect={ noop }
21
- onSelectURL={ noop }
27
+ onSelectURL={ setMediaURL }
22
28
  onError={ noop }
23
29
  onCloseModal={ noop }
24
30
  />
25
31
  );
32
+ }
33
+
34
+ function setUpMediaReplaceFlow() {
35
+ const { container } = render( <TestWrapper /> );
26
36
  return container;
27
37
  }
28
38
 
@@ -33,6 +33,7 @@ function URLPopover( {
33
33
  className="block-editor-url-popover"
34
34
  focusOnMount={ focusOnMount }
35
35
  position={ position }
36
+ __unstableShift
36
37
  { ...popoverProps }
37
38
  >
38
39
  <div className="block-editor-url-popover__input-container">
@@ -2,6 +2,7 @@
2
2
 
3
3
  exports[`URLPopover matches the snapshot in its default state 1`] = `
4
4
  <ForwardRef(Popover)
5
+ __unstableShift={true}
5
6
  className="block-editor-url-popover"
6
7
  focusOnMount="firstElement"
7
8
  position="bottom center"
@@ -38,6 +39,7 @@ exports[`URLPopover matches the snapshot in its default state 1`] = `
38
39
 
39
40
  exports[`URLPopover matches the snapshot when the settings are toggled open 1`] = `
40
41
  <ForwardRef(Popover)
42
+ __unstableShift={true}
41
43
  className="block-editor-url-popover"
42
44
  focusOnMount="firstElement"
43
45
  position="bottom center"
@@ -81,6 +83,7 @@ exports[`URLPopover matches the snapshot when the settings are toggled open 1`]
81
83
 
82
84
  exports[`URLPopover matches the snapshot when there are no settings 1`] = `
83
85
  <ForwardRef(Popover)
86
+ __unstableShift={true}
84
87
  className="block-editor-url-popover"
85
88
  focusOnMount="firstElement"
86
89
  position="bottom center"
@@ -11,7 +11,7 @@ import {
11
11
  isRTL,
12
12
  } from '@wordpress/dom';
13
13
  import { UP, DOWN, LEFT, RIGHT } from '@wordpress/keycodes';
14
- import { useSelect } from '@wordpress/data';
14
+ import { useDispatch, useSelect } from '@wordpress/data';
15
15
  import { useRefEffect } from '@wordpress/compose';
16
16
 
17
17
  /**
@@ -131,12 +131,15 @@ export function getClosestTabbable(
131
131
  export default function useArrowNav() {
132
132
  const {
133
133
  getSelectedBlockClientId,
134
+ getMultiSelectedBlocksStartClientId,
134
135
  getMultiSelectedBlocksEndClientId,
135
136
  getPreviousBlockClientId,
136
137
  getNextBlockClientId,
137
138
  getSettings,
138
139
  hasMultiSelection,
140
+ __unstableIsFullySelected,
139
141
  } = useSelect( blockEditorStore );
142
+ const { selectBlock } = useDispatch( blockEditorStore );
140
143
  return useRefEffect( ( node ) => {
141
144
  // Here a DOMRect is stored while moving the caret vertically so
142
145
  // vertical position of the start position can be restored. This is to
@@ -186,7 +189,35 @@ export default function useArrowNav() {
186
189
  const { ownerDocument } = node;
187
190
  const { defaultView } = ownerDocument;
188
191
 
192
+ // If there is a multi-selection, the arrow keys should collapse the
193
+ // selection to the start or end of the selection.
189
194
  if ( hasMultiSelection() ) {
195
+ // Only handle if we have a full selection (not a native partial
196
+ // selection).
197
+ if ( ! __unstableIsFullySelected() ) {
198
+ return;
199
+ }
200
+
201
+ if ( event.defaultPrevented ) {
202
+ return;
203
+ }
204
+
205
+ if ( ! isNav ) {
206
+ return;
207
+ }
208
+
209
+ if ( isShift ) {
210
+ return;
211
+ }
212
+
213
+ event.preventDefault();
214
+
215
+ if ( isReverse ) {
216
+ selectBlock( getMultiSelectedBlocksStartClientId() );
217
+ } else {
218
+ selectBlock( getMultiSelectedBlocksEndClientId(), -1 );
219
+ }
220
+
190
221
  return;
191
222
  }
192
223
 
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { first, last } from 'lodash';
5
-
6
1
  /**
7
2
  * WordPress dependencies
8
3
  */
@@ -13,7 +8,6 @@ import { useSelect } from '@wordpress/data';
13
8
  * Internal dependencies
14
9
  */
15
10
  import { store as blockEditorStore } from '../../store';
16
- import { __unstableUseBlockRef as useBlockRef } from '../block-list/use-block-props/use-block-refs';
17
11
 
18
12
  function selector( select ) {
19
13
  const {
@@ -44,10 +38,6 @@ export default function useMultiSelection() {
44
38
  selectedBlockClientId,
45
39
  isFullSelection,
46
40
  } = useSelect( selector, [] );
47
- const selectedRef = useBlockRef( selectedBlockClientId );
48
- // These must be in the right DOM order.
49
- const startRef = useBlockRef( first( multiSelectedBlockClientIds ) );
50
- const endRef = useBlockRef( last( multiSelectedBlockClientIds ) );
51
41
 
52
42
  /**
53
43
  * When the component updates, and there is multi selection, we need to
@@ -66,26 +56,6 @@ export default function useMultiSelection() {
66
56
  }
67
57
 
68
58
  if ( ! hasMultiSelection || isMultiSelecting ) {
69
- if ( ! selectedBlockClientId || isMultiSelecting ) {
70
- return;
71
- }
72
-
73
- const selection = defaultView.getSelection();
74
-
75
- if ( selection.rangeCount && ! selection.isCollapsed ) {
76
- const blockNode = selectedRef.current;
77
- const { startContainer, endContainer } =
78
- selection.getRangeAt( 0 );
79
-
80
- if (
81
- !! blockNode &&
82
- ( ! blockNode.contains( startContainer ) ||
83
- ! blockNode.contains( endContainer ) )
84
- ) {
85
- selection.removeAllRanges();
86
- }
87
- }
88
-
89
59
  return;
90
60
  }
91
61
 
@@ -105,25 +75,8 @@ export default function useMultiSelection() {
105
75
  // able to select across instances immediately.
106
76
  node.contentEditable = true;
107
77
 
108
- // For some browsers, like Safari, it is important that focus happens
109
- // BEFORE selection.
78
+ defaultView.getSelection().removeAllRanges();
110
79
  node.focus();
111
-
112
- // The block refs might not be immediately available
113
- // when dragging blocks into another block.
114
- if ( ! startRef.current || ! endRef.current ) {
115
- return;
116
- }
117
-
118
- const selection = defaultView.getSelection();
119
- const range = ownerDocument.createRange();
120
-
121
- // These must be in the right DOM order.
122
- range.setStartBefore( startRef.current );
123
- range.setEndAfter( endRef.current );
124
-
125
- selection.removeAllRanges();
126
- selection.addRange( range );
127
80
  },
128
81
  [
129
82
  hasMultiSelection,
@@ -84,12 +84,11 @@ export default function useSelectionObserver() {
84
84
 
85
85
  function onSelectionChange( event ) {
86
86
  const selection = defaultView.getSelection();
87
- // If no selection is found, end multi selection and disable the
88
- // contentEditable wrapper.
87
+
89
88
  if ( ! selection.rangeCount ) {
90
- setContentEditableWrapper( node, false );
91
89
  return;
92
90
  }
91
+
93
92
  // If selection is collapsed and we haven't used `shift+click`,
94
93
  // end multi selection and disable the contentEditable wrapper.
95
94
  // We have to check about `shift+click` case because elements
@@ -2,7 +2,6 @@
2
2
  * External dependencies
3
3
  */
4
4
  import classnames from 'classnames';
5
- import { isObject } from 'lodash';
6
5
 
7
6
  /**
8
7
  * WordPress dependencies
@@ -55,13 +54,21 @@ const hasLinkColorSupport = ( blockType ) => {
55
54
 
56
55
  const colorSupport = getBlockSupport( blockType, COLOR_SUPPORT_KEY );
57
56
 
58
- return isObject( colorSupport ) && !! colorSupport.link;
57
+ return (
58
+ colorSupport !== null &&
59
+ typeof colorSupport === 'object' &&
60
+ !! colorSupport.link
61
+ );
59
62
  };
60
63
 
61
64
  const hasGradientSupport = ( blockType ) => {
62
65
  const colorSupport = getBlockSupport( blockType, COLOR_SUPPORT_KEY );
63
66
 
64
- return isObject( colorSupport ) && !! colorSupport.gradients;
67
+ return (
68
+ colorSupport !== null &&
69
+ typeof colorSupport === 'object' &&
70
+ !! colorSupport.gradients
71
+ );
65
72
  };
66
73
 
67
74
  const hasBackgroundColorSupport = ( blockType ) => {
@@ -20,4 +20,5 @@ export { useCustomSides } from './dimensions';
20
20
  export { getBorderClassesAndStyles, useBorderProps } from './use-border-props';
21
21
  export { getColorClassesAndStyles, useColorProps } from './use-color-props';
22
22
  export { getSpacingClassesAndStyles } from './use-spacing-props';
23
+ export { getGapCSSValue } from './gap';
23
24
  export { useCachedTruthy } from './use-cached-truthy';
@@ -9,7 +9,11 @@ import { has, kebabCase } from 'lodash';
9
9
  */
10
10
  import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
11
11
  import { addFilter } from '@wordpress/hooks';
12
- import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks';
12
+ import {
13
+ getBlockDefaultClassName,
14
+ getBlockSupport,
15
+ hasBlockSupport,
16
+ } from '@wordpress/blocks';
13
17
  import { useSelect } from '@wordpress/data';
14
18
  import {
15
19
  Button,
@@ -40,35 +44,31 @@ const layoutBlockSupportKey = '__experimentalLayout';
40
44
  * have the style engine generate a more extensive list of utility classnames which
41
45
  * will then replace this method.
42
46
  *
43
- * @param { Array } attributes Array of block attributes.
47
+ * @param { Object } layout Layout object.
48
+ * @param { Object } layoutDefinitions An object containing layout definitions, stored in theme.json.
44
49
  *
45
50
  * @return { Array } Array of CSS classname strings.
46
51
  */
47
- function getLayoutClasses( attributes ) {
52
+ function getLayoutClasses( layout, layoutDefinitions ) {
48
53
  const layoutClassnames = [];
49
54
 
50
- if ( ! attributes.layout ) {
51
- return layoutClassnames;
52
- }
53
-
54
- if ( attributes?.layout?.orientation ) {
55
+ if ( layoutDefinitions?.[ layout?.type || 'default' ]?.className ) {
55
56
  layoutClassnames.push(
56
- `is-${ kebabCase( attributes.layout.orientation ) }`
57
+ layoutDefinitions?.[ layout?.type || 'default' ]?.className
57
58
  );
58
59
  }
59
60
 
60
- if ( attributes?.layout?.justifyContent ) {
61
+ if ( layout?.orientation ) {
62
+ layoutClassnames.push( `is-${ kebabCase( layout.orientation ) }` );
63
+ }
64
+
65
+ if ( layout?.justifyContent ) {
61
66
  layoutClassnames.push(
62
- `is-content-justification-${ kebabCase(
63
- attributes.layout.justifyContent
64
- ) }`
67
+ `is-content-justification-${ kebabCase( layout.justifyContent ) }`
65
68
  );
66
69
  }
67
70
 
68
- if (
69
- attributes?.layout?.flexWrap &&
70
- attributes.layout.flexWrap === 'nowrap'
71
- ) {
71
+ if ( layout?.flexWrap && layout.flexWrap === 'nowrap' ) {
72
72
  layoutClassnames.push( 'is-nowrap' );
73
73
  }
74
74
 
@@ -267,12 +267,36 @@ export const withLayoutStyles = createHigherOrderComponent(
267
267
  ? defaultThemeLayout
268
268
  : layout || defaultBlockLayout || {};
269
269
  const layoutClasses = shouldRenderLayoutStyles
270
- ? getLayoutClasses( attributes )
270
+ ? getLayoutClasses( usedLayout, defaultThemeLayout?.definitions )
271
271
  : null;
272
+ const selector = `.${ getBlockDefaultClassName(
273
+ name
274
+ ) }.wp-container-${ id }`;
275
+ const blockGapSupport = useSetting( 'spacing.blockGap' );
276
+ const hasBlockGapSupport = blockGapSupport !== null;
277
+
278
+ // Get CSS string for the current layout type.
279
+ // The CSS and `style` element is only output if it is not empty.
280
+ let css;
281
+ if ( shouldRenderLayoutStyles ) {
282
+ const fullLayoutType = getLayoutType(
283
+ usedLayout?.type || 'default'
284
+ );
285
+ css = fullLayoutType?.getLayoutStyle?.( {
286
+ blockName: name,
287
+ selector,
288
+ layout: usedLayout,
289
+ layoutDefinitions: defaultThemeLayout?.definitions,
290
+ style: attributes?.style,
291
+ hasBlockGapSupport,
292
+ } );
293
+ }
294
+
295
+ // Attach a `wp-container-` id-based class name as well as a layout class name such as `is-layout-flex`.
272
296
  const className = classnames(
273
297
  props?.className,
274
298
  {
275
- [ `wp-container-${ id }` ]: shouldRenderLayoutStyles,
299
+ [ `wp-container-${ id }` ]: shouldRenderLayoutStyles && !! css, // Only attach a container class if there is generated CSS to be attached.
276
300
  },
277
301
  layoutClasses
278
302
  );
@@ -281,10 +305,12 @@ export const withLayoutStyles = createHigherOrderComponent(
281
305
  <>
282
306
  { shouldRenderLayoutStyles &&
283
307
  element &&
308
+ !! css &&
284
309
  createPortal(
285
310
  <LayoutStyle
286
311
  blockName={ name }
287
- selector={ `.wp-container-${ id }` }
312
+ selector={ selector }
313
+ css={ css }
288
314
  layout={ usedLayout }
289
315
  style={ attributes?.style }
290
316
  />,
@@ -4,8 +4,6 @@
4
4
  import {
5
5
  pickBy,
6
6
  isEmpty,
7
- isObject,
8
- identity,
9
7
  mapValues,
10
8
  forEach,
11
9
  get,
@@ -19,6 +17,8 @@ import {
19
17
  */
20
18
  import { getBlockSupport } from '@wordpress/blocks';
21
19
 
20
+ const identity = ( x ) => x;
21
+
22
22
  /**
23
23
  * Removed falsy values from nested object.
24
24
  *
@@ -26,7 +26,11 @@ import { getBlockSupport } from '@wordpress/blocks';
26
26
  * @return {*} Object cleaned from falsy values
27
27
  */
28
28
  export const cleanEmptyObject = ( object ) => {
29
- if ( ! isObject( object ) || Array.isArray( object ) ) {
29
+ if (
30
+ object === null ||
31
+ typeof object !== 'object' ||
32
+ Array.isArray( object )
33
+ ) {
30
34
  return object;
31
35
  }
32
36
  const cleanedNestedObjects = pickBy(
package/src/index.js CHANGED
@@ -9,6 +9,7 @@ export {
9
9
  useColorProps as __experimentalUseColorProps,
10
10
  useCustomSides as __experimentalUseCustomSides,
11
11
  getSpacingClassesAndStyles as __experimentalGetSpacingClassesAndStyles,
12
+ getGapCSSValue as __experimentalGetGapCSSValue,
12
13
  useCachedTruthy,
13
14
  } from './hooks';
14
15
  export * from './components';