@wordpress/block-editor 8.1.1 → 8.2.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 (187) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +0 -24
  3. package/build/components/block-list/block.js +16 -2
  4. package/build/components/block-list/block.js.map +1 -1
  5. package/build/components/block-list/block.native.js +1 -1
  6. package/build/components/block-list/block.native.js.map +1 -1
  7. package/build/components/block-list/use-block-props/use-focus-first-element.js +3 -0
  8. package/build/components/block-list/use-block-props/use-focus-first-element.js.map +1 -1
  9. package/build/components/block-list/use-block-props/use-multi-selection.js +25 -27
  10. package/build/components/block-list/use-block-props/use-multi-selection.js.map +1 -1
  11. package/build/components/block-settings/container.native.js +1 -5
  12. package/build/components/block-settings/container.native.js.map +1 -1
  13. package/build/components/index.js +9 -0
  14. package/build/components/index.js.map +1 -1
  15. package/build/components/index.native.js +9 -0
  16. package/build/components/index.native.js.map +1 -1
  17. package/build/components/inserter/block-patterns-tab.js +3 -3
  18. package/build/components/inserter/block-patterns-tab.js.map +1 -1
  19. package/build/components/inserter/quick-inserter.js +19 -7
  20. package/build/components/inserter/quick-inserter.js.map +1 -1
  21. package/build/components/inserter/search-results.js +28 -11
  22. package/build/components/inserter/search-results.js.map +1 -1
  23. package/build/components/line-height-control/index.js +61 -43
  24. package/build/components/line-height-control/index.js.map +1 -1
  25. package/build/components/list-view/block-contents.js +8 -4
  26. package/build/components/list-view/block-contents.js.map +1 -1
  27. package/build/components/list-view/block-select-button.js +0 -1
  28. package/build/components/list-view/block-select-button.js.map +1 -1
  29. package/build/components/list-view/block.js +19 -8
  30. package/build/components/list-view/block.js.map +1 -1
  31. package/build/components/list-view/branch.js +2 -1
  32. package/build/components/list-view/branch.js.map +1 -1
  33. package/build/components/list-view/index.js +49 -41
  34. package/build/components/list-view/index.js.map +1 -1
  35. package/build/components/list-view/use-block-selection.js +139 -0
  36. package/build/components/list-view/use-block-selection.js.map +1 -0
  37. package/build/components/list-view/use-list-view-expand-selected-item.js +60 -0
  38. package/build/components/list-view/use-list-view-expand-selected-item.js.map +1 -0
  39. package/build/components/list-view/utils.js +29 -1
  40. package/build/components/list-view/utils.js.map +1 -1
  41. package/build/components/rich-text/index.js +7 -12
  42. package/build/components/rich-text/index.js.map +1 -1
  43. package/build/components/rich-text/use-paste-handler.js +0 -1
  44. package/build/components/rich-text/use-paste-handler.js.map +1 -1
  45. package/build/components/writing-flow/index.js +1 -0
  46. package/build/components/writing-flow/index.js.map +1 -1
  47. package/build/components/writing-flow/use-multi-selection.js +22 -24
  48. package/build/components/writing-flow/use-multi-selection.js.map +1 -1
  49. package/build/components/writing-flow/use-select-all.js +3 -2
  50. package/build/components/writing-flow/use-select-all.js.map +1 -1
  51. package/build/hooks/custom-class-name.js +40 -0
  52. package/build/hooks/custom-class-name.js.map +1 -1
  53. package/build/hooks/line-height.js +2 -0
  54. package/build/hooks/line-height.js.map +1 -1
  55. package/build/hooks/style.js +27 -11
  56. package/build/hooks/style.js.map +1 -1
  57. package/build/layouts/flow.js +7 -5
  58. package/build/layouts/flow.js.map +1 -1
  59. package/build/store/actions.js +51 -44
  60. package/build/store/actions.js.map +1 -1
  61. package/build/store/defaults.js +1 -0
  62. package/build/store/defaults.js.map +1 -1
  63. package/build/store/index.js +1 -2
  64. package/build/store/index.js.map +1 -1
  65. package/build/store/reducer.js +2 -2
  66. package/build/store/reducer.js.map +1 -1
  67. package/build/utils/index.js +0 -14
  68. package/build/utils/index.js.map +1 -1
  69. package/build-module/components/block-list/block.js +17 -3
  70. package/build-module/components/block-list/block.js.map +1 -1
  71. package/build-module/components/block-list/block.native.js +2 -2
  72. package/build-module/components/block-list/block.native.js.map +1 -1
  73. package/build-module/components/block-list/use-block-props/use-focus-first-element.js +2 -0
  74. package/build-module/components/block-list/use-block-props/use-focus-first-element.js.map +1 -1
  75. package/build-module/components/block-list/use-block-props/use-multi-selection.js +23 -28
  76. package/build-module/components/block-list/use-block-props/use-multi-selection.js.map +1 -1
  77. package/build-module/components/block-settings/container.native.js +2 -6
  78. package/build-module/components/block-settings/container.native.js.map +1 -1
  79. package/build-module/components/index.js +1 -0
  80. package/build-module/components/index.js.map +1 -1
  81. package/build-module/components/index.native.js +1 -0
  82. package/build-module/components/index.native.js.map +1 -1
  83. package/build-module/components/inserter/block-patterns-tab.js +3 -3
  84. package/build-module/components/inserter/block-patterns-tab.js.map +1 -1
  85. package/build-module/components/inserter/quick-inserter.js +19 -7
  86. package/build-module/components/inserter/quick-inserter.js.map +1 -1
  87. package/build-module/components/inserter/search-results.js +28 -11
  88. package/build-module/components/inserter/search-results.js.map +1 -1
  89. package/build-module/components/line-height-control/index.js +59 -43
  90. package/build-module/components/line-height-control/index.js.map +1 -1
  91. package/build-module/components/list-view/block-contents.js +8 -4
  92. package/build-module/components/list-view/block-contents.js.map +1 -1
  93. package/build-module/components/list-view/block-select-button.js +0 -1
  94. package/build-module/components/list-view/block-select-button.js.map +1 -1
  95. package/build-module/components/list-view/block.js +19 -8
  96. package/build-module/components/list-view/block.js.map +1 -1
  97. package/build-module/components/list-view/branch.js +2 -1
  98. package/build-module/components/list-view/branch.js.map +1 -1
  99. package/build-module/components/list-view/index.js +46 -42
  100. package/build-module/components/list-view/index.js.map +1 -1
  101. package/build-module/components/list-view/use-block-selection.js +123 -0
  102. package/build-module/components/list-view/use-block-selection.js.map +1 -0
  103. package/build-module/components/list-view/use-list-view-expand-selected-item.js +50 -0
  104. package/build-module/components/list-view/use-list-view-expand-selected-item.js.map +1 -0
  105. package/build-module/components/list-view/utils.js +25 -0
  106. package/build-module/components/list-view/utils.js.map +1 -1
  107. package/build-module/components/rich-text/index.js +7 -12
  108. package/build-module/components/rich-text/index.js.map +1 -1
  109. package/build-module/components/rich-text/use-paste-handler.js +0 -1
  110. package/build-module/components/rich-text/use-paste-handler.js.map +1 -1
  111. package/build-module/components/writing-flow/index.js +1 -0
  112. package/build-module/components/writing-flow/index.js.map +1 -1
  113. package/build-module/components/writing-flow/use-multi-selection.js +21 -21
  114. package/build-module/components/writing-flow/use-multi-selection.js.map +1 -1
  115. package/build-module/components/writing-flow/use-select-all.js +3 -2
  116. package/build-module/components/writing-flow/use-select-all.js.map +1 -1
  117. package/build-module/hooks/custom-class-name.js +38 -0
  118. package/build-module/hooks/custom-class-name.js.map +1 -1
  119. package/build-module/hooks/line-height.js +2 -0
  120. package/build-module/hooks/line-height.js.map +1 -1
  121. package/build-module/hooks/style.js +26 -11
  122. package/build-module/hooks/style.js.map +1 -1
  123. package/build-module/layouts/flow.js +7 -5
  124. package/build-module/layouts/flow.js.map +1 -1
  125. package/build-module/store/actions.js +48 -41
  126. package/build-module/store/actions.js.map +1 -1
  127. package/build-module/store/defaults.js +1 -0
  128. package/build-module/store/defaults.js.map +1 -1
  129. package/build-module/store/index.js +1 -2
  130. package/build-module/store/index.js.map +1 -1
  131. package/build-module/store/reducer.js +2 -2
  132. package/build-module/store/reducer.js.map +1 -1
  133. package/build-module/utils/index.js +0 -1
  134. package/build-module/utils/index.js.map +1 -1
  135. package/build-style/style-rtl.css +3 -12
  136. package/build-style/style.css +3 -12
  137. package/package.json +12 -11
  138. package/src/components/block-list/block.js +27 -3
  139. package/src/components/block-list/block.native.js +2 -1
  140. package/src/components/block-list/style.scss +3 -1
  141. package/src/components/block-list/use-block-props/use-focus-first-element.js +3 -0
  142. package/src/components/block-list/use-block-props/use-multi-selection.js +22 -30
  143. package/src/components/block-settings/container.native.js +5 -6
  144. package/src/components/index.js +1 -0
  145. package/src/components/index.native.js +1 -0
  146. package/src/components/inserter/block-patterns-tab.js +12 -16
  147. package/src/components/inserter/quick-inserter.js +31 -9
  148. package/src/components/inserter/search-results.js +54 -42
  149. package/src/components/line-height-control/README.md +13 -2
  150. package/src/components/line-height-control/index.js +63 -40
  151. package/src/components/line-height-control/stories/index.js +33 -0
  152. package/src/components/line-height-control/test/index.js +61 -0
  153. package/src/components/list-view/README.md +2 -2
  154. package/src/components/list-view/block-contents.js +10 -3
  155. package/src/components/list-view/block-select-button.js +0 -1
  156. package/src/components/list-view/block.js +29 -9
  157. package/src/components/list-view/branch.js +1 -0
  158. package/src/components/list-view/index.js +56 -30
  159. package/src/components/list-view/test/utils.js +50 -0
  160. package/src/components/list-view/use-block-selection.js +163 -0
  161. package/src/components/list-view/use-list-view-expand-selected-item.js +58 -0
  162. package/src/components/list-view/utils.js +31 -0
  163. package/src/components/rich-text/index.js +7 -14
  164. package/src/components/rich-text/use-paste-handler.js +0 -1
  165. package/src/components/writing-flow/index.js +1 -0
  166. package/src/components/writing-flow/use-multi-selection.js +17 -20
  167. package/src/components/writing-flow/use-select-all.js +6 -2
  168. package/src/hooks/custom-class-name.js +45 -0
  169. package/src/hooks/line-height.js +2 -0
  170. package/src/hooks/style.js +26 -11
  171. package/src/hooks/typography.scss +0 -4
  172. package/src/layouts/flow.js +10 -5
  173. package/src/store/actions.js +20 -10
  174. package/src/store/defaults.js +1 -0
  175. package/src/store/index.js +0 -1
  176. package/src/store/reducer.js +2 -1
  177. package/src/store/test/actions.js +1 -1
  178. package/src/store/test/reducer.js +9 -0
  179. package/src/style.scss +0 -1
  180. package/src/utils/index.js +0 -1
  181. package/build/utils/theme.js +0 -63
  182. package/build/utils/theme.js.map +0 -1
  183. package/build-module/utils/theme.js +0 -53
  184. package/build-module/utils/theme.js.map +0 -1
  185. package/src/components/line-height-control/style.scss +0 -8
  186. package/src/components/writing-flow/test/use-multi-selection.js +0 -36
  187. package/src/utils/theme.js +0 -48
@@ -11,6 +11,7 @@ import { Component, createRef, useMemo } from '@wordpress/element';
11
11
  import {
12
12
  GlobalStylesContext,
13
13
  getMergedGlobalStyles,
14
+ useMobileGlobalStylesColors,
14
15
  alignmentHelpers,
15
16
  useGlobalStyles,
16
17
  } from '@wordpress/components';
@@ -50,7 +51,7 @@ function BlockForType( {
50
51
  blockWidth,
51
52
  baseGlobalStyles,
52
53
  } ) {
53
- const defaultColors = useSetting( 'color.palette' ) || emptyArray;
54
+ const defaultColors = useMobileGlobalStylesColors();
54
55
  const fontSizes = useSetting( 'typography.fontSizes' ) || emptyArray;
55
56
  const globalStyle = useGlobalStyles();
56
57
  const mergedStyle = useMemo( () => {
@@ -321,7 +321,9 @@
321
321
  }
322
322
 
323
323
  .wp-block[data-align="left"] > *,
324
- .wp-block[data-align="right"] > * {
324
+ .wp-block[data-align="right"] > *,
325
+ .wp-block.alignleft,
326
+ .wp-block.alignright {
325
327
  // Without z-index, won't be clickable as "above" adjacent content.
326
328
  z-index: z-index("{core/image aligned left or right} .wp-block");
327
329
  }
@@ -15,6 +15,7 @@ import { useSelect } from '@wordpress/data';
15
15
  */
16
16
  import { isInsideRootBlock } from '../../../utils/dom';
17
17
  import { store as blockEditorStore } from '../../../store';
18
+ import { setContentEditableWrapper } from './use-multi-selection';
18
19
 
19
20
  /** @typedef {import('@wordpress/element').RefObject} RefObject */
20
21
 
@@ -95,6 +96,8 @@ export function useFocusFirstElement( clientId ) {
95
96
  return;
96
97
  }
97
98
 
99
+ setContentEditableWrapper( ref.current, false );
100
+
98
101
  placeCaretAtHorizontalEdge( target, isReverse );
99
102
  }, [ initialPosition ] );
100
103
 
@@ -10,18 +10,15 @@ import { useRefEffect } from '@wordpress/compose';
10
10
  import { store as blockEditorStore } from '../../../store';
11
11
  import { getBlockClientId } from '../../../utils/dom';
12
12
 
13
- function toggleRichText( container, toggle ) {
14
- Array.from(
15
- container
16
- .closest( '.is-root-container' )
17
- .querySelectorAll( '.rich-text' )
18
- ).forEach( ( node ) => {
19
- if ( toggle ) {
20
- node.setAttribute( 'contenteditable', true );
21
- } else {
22
- node.removeAttribute( 'contenteditable' );
23
- }
24
- } );
13
+ /**
14
+ * Sets the `contenteditable` wrapper element to `value`.
15
+ *
16
+ * @param {HTMLElement} node Block element.
17
+ * @param {boolean} value `contentEditable` value (true or false)
18
+ */
19
+ export function setContentEditableWrapper( node, value ) {
20
+ // Since `closest` considers `node` as a candidate, use `parentElement`.
21
+ node.parentElement.closest( '[contenteditable]' ).contentEditable = value;
25
22
  }
26
23
 
27
24
  /**
@@ -54,10 +51,10 @@ export function useMultiSelection( clientId ) {
54
51
  function onSelectionChange( { isSelectionEnd } ) {
55
52
  const selection = defaultView.getSelection();
56
53
 
57
- // If no selection is found, end multi selection and enable all rich
58
- // text areas.
54
+ // If no selection is found, end multi selection and disable the
55
+ // contentEditable wrapper.
59
56
  if ( ! selection.rangeCount || selection.isCollapsed ) {
60
- toggleRichText( node, true );
57
+ setContentEditableWrapper( node, false );
61
58
  return;
62
59
  }
63
60
 
@@ -70,10 +67,10 @@ export function useMultiSelection( clientId ) {
70
67
  // If the selection is complete (on mouse up), and no
71
68
  // multiple blocks have been selected, set focus back to the
72
69
  // anchor element. if the anchor element contains the
73
- // selection. Additionally, rich text elements that were
74
- // previously disabled can now be enabled again.
70
+ // selection. Additionally, the contentEditable wrapper can
71
+ // now be disabled again.
75
72
  if ( isSelectionEnd ) {
76
- toggleRichText( node, true );
73
+ setContentEditableWrapper( node, false );
77
74
 
78
75
  if ( selection.rangeCount ) {
79
76
  const {
@@ -144,16 +141,11 @@ export function useMultiSelection( clientId ) {
144
141
  );
145
142
  defaultView.addEventListener( 'mouseup', onSelectionEnd );
146
143
 
147
- // Removing the contenteditable attributes within the block
148
- // editor is essential for selection to work across editable
149
- // areas. The edible hosts are removed, allowing selection to be
150
- // extended outside the DOM element. `startMultiSelect` sets a
151
- // flag in the store so the rich text components are updated,
152
- // but the rerender may happen very slowly, especially in Safari
153
- // for the blocks that are asynchonously rendered. To ensure the
154
- // browser instantly removes the selection boundaries, we remove
155
- // the contenteditable attributes manually.
156
- toggleRichText( node, false );
144
+ // Allow cross contentEditable selection by temporarily making
145
+ // all content editable. We can't rely on using the store and
146
+ // React because re-rending happens too slowly. We need to be
147
+ // able to select across instances immediately.
148
+ setContentEditableWrapper( node, true );
157
149
  }
158
150
 
159
151
  function onMouseDown( event ) {
@@ -189,9 +181,9 @@ export function useMultiSelection( clientId ) {
189
181
  const start = startPath[ depth ];
190
182
  const end = endPath[ depth ];
191
183
  // Handle the case of having selected a parent block and
192
- // then sfift+click on a child.
184
+ // then shift+click on a child.
193
185
  if ( start !== end ) {
194
- toggleRichText( node, false );
186
+ setContentEditableWrapper( node, true );
195
187
  multiSelect( start, end );
196
188
  event.preventDefault();
197
189
  }
@@ -1,7 +1,10 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { InspectorControls, useSetting } from '@wordpress/block-editor';
4
+ import {
5
+ InspectorControls,
6
+ useMultipleOriginColorsAndGradients,
7
+ } from '@wordpress/block-editor';
5
8
  import {
6
9
  BottomSheet,
7
10
  ColorSettings,
@@ -28,13 +31,9 @@ export const blockSettingsScreens = {
28
31
  function BottomSheetSettings( {
29
32
  editorSidebarOpened,
30
33
  closeGeneralSidebar,
31
- settings,
32
34
  ...props
33
35
  } ) {
34
- const colorSettings = {
35
- colors: useSetting( 'color.palette' ) || settings.colors,
36
- gradients: useSetting( 'color.gradients' ) || settings.gradients,
37
- };
36
+ const colorSettings = useMultipleOriginColorsAndGradients();
38
37
 
39
38
  return (
40
39
  <BottomSheet
@@ -145,6 +145,7 @@ export { default as WritingFlow } from './writing-flow';
145
145
  export { default as useBlockDisplayInformation } from './use-block-display-information';
146
146
  export { default as __unstableIframe } from './iframe';
147
147
  export { default as __experimentalUseNoRecursiveRenders } from './use-no-recursive-renders';
148
+ export { default as __experimentalBlockPatternsList } from './block-patterns-list';
148
149
 
149
150
  /*
150
151
  * State Related Components
@@ -56,6 +56,7 @@ export { default as useSetting } from './use-setting';
56
56
  export { default as __experimentalUseNoRecursiveRenders } from './use-no-recursive-renders';
57
57
  export { default as Warning } from './warning';
58
58
  export { default as ContrastChecker } from './contrast-checker';
59
+ export { default as useMultipleOriginColorsAndGradients } from './colors-gradients/use-multiple-origin-colors-and-gradients';
59
60
 
60
61
  export {
61
62
  BottomSheetSettings,
@@ -144,23 +144,19 @@ function BlockPatternsTabs( {
144
144
 
145
145
  return (
146
146
  <>
147
+ <PatternInserterPanel
148
+ selectedCategory={ patternCategory }
149
+ patternCategories={ populatedCategories }
150
+ onClickCategory={ onClickCategory }
151
+ openPatternExplorer={ () => setShowPatternsExplorer( true ) }
152
+ />
147
153
  { ! showPatternsExplorer && (
148
- <>
149
- <PatternInserterPanel
150
- selectedCategory={ patternCategory }
151
- patternCategories={ populatedCategories }
152
- onClickCategory={ onClickCategory }
153
- openPatternExplorer={ () =>
154
- setShowPatternsExplorer( true )
155
- }
156
- />
157
- <BlockPatternsCategory
158
- rootClientId={ rootClientId }
159
- onInsert={ onInsert }
160
- selectedCategory={ patternCategory }
161
- populatedCategories={ populatedCategories }
162
- />
163
- </>
154
+ <BlockPatternsCategory
155
+ rootClientId={ rootClientId }
156
+ onInsert={ onInsert }
157
+ selectedCategory={ patternCategory }
158
+ populatedCategories={ populatedCategories }
159
+ />
164
160
  ) }
165
161
  { showPatternsExplorer && (
166
162
  <PatternsExplorerModal
@@ -23,6 +23,7 @@ import { store as blockEditorStore } from '../../store';
23
23
  const SEARCH_THRESHOLD = 6;
24
24
  const SHOWN_BLOCK_TYPES = 6;
25
25
  const SHOWN_BLOCK_PATTERNS = 2;
26
+ const SHOWN_BLOCK_PATTERNS_WITH_PRIORITIZATION = 4;
26
27
 
27
28
  export default function QuickInserter( {
28
29
  onSelect,
@@ -46,26 +47,39 @@ export default function QuickInserter( {
46
47
  onInsertBlocks,
47
48
  destinationRootClientId
48
49
  );
49
- const showPatterns = patterns.length && !! filterValue;
50
- const showSearch =
51
- ( showPatterns && patterns.length > SEARCH_THRESHOLD ) ||
52
- blockTypes.length > SEARCH_THRESHOLD;
53
50
 
54
- const { setInserterIsOpened, insertionIndex } = useSelect(
51
+ const {
52
+ setInserterIsOpened,
53
+ insertionIndex,
54
+ prioritizePatterns,
55
+ } = useSelect(
55
56
  ( select ) => {
56
57
  const { getSettings, getBlockIndex, getBlockCount } = select(
57
58
  blockEditorStore
58
59
  );
60
+ const settings = getSettings();
59
61
  const index = getBlockIndex( clientId );
62
+ const blockCount = getBlockCount();
63
+
60
64
  return {
61
- setInserterIsOpened: getSettings()
62
- .__experimentalSetIsInserterOpened,
63
- insertionIndex: index === -1 ? getBlockCount() : index,
65
+ setInserterIsOpened: settings.__experimentalSetIsInserterOpened,
66
+ prioritizePatterns:
67
+ settings.__experimentalPreferPatternsOnRoot &&
68
+ ! rootClientId &&
69
+ index > 0 &&
70
+ ( index < blockCount || blockCount === 0 ),
71
+ insertionIndex: index === -1 ? blockCount : index,
64
72
  };
65
73
  },
66
74
  [ clientId, rootClientId ]
67
75
  );
68
76
 
77
+ const showPatterns =
78
+ patterns.length && ( !! filterValue || prioritizePatterns );
79
+ const showSearch =
80
+ ( showPatterns && patterns.length > SEARCH_THRESHOLD ) ||
81
+ blockTypes.length > SEARCH_THRESHOLD;
82
+
69
83
  useEffect( () => {
70
84
  if ( setInserterIsOpened ) {
71
85
  setInserterIsOpened( false );
@@ -78,6 +92,13 @@ export default function QuickInserter( {
78
92
  setInserterIsOpened( { rootClientId, insertionIndex, filterValue } );
79
93
  };
80
94
 
95
+ let maxBlockPatterns = 0;
96
+ if ( showPatterns ) {
97
+ maxBlockPatterns = prioritizePatterns
98
+ ? SHOWN_BLOCK_PATTERNS_WITH_PRIORITIZATION
99
+ : SHOWN_BLOCK_PATTERNS;
100
+ }
101
+
81
102
  return (
82
103
  <div
83
104
  className={ classnames( 'block-editor-inserter__quick-inserter', {
@@ -104,9 +125,10 @@ export default function QuickInserter( {
104
125
  rootClientId={ rootClientId }
105
126
  clientId={ clientId }
106
127
  isAppender={ isAppender }
107
- maxBlockPatterns={ showPatterns ? SHOWN_BLOCK_PATTERNS : 0 }
128
+ maxBlockPatterns={ maxBlockPatterns }
108
129
  maxBlockTypes={ SHOWN_BLOCK_TYPES }
109
130
  isDraggable={ false }
131
+ prioritizePatterns={ prioritizePatterns }
110
132
  />
111
133
  </div>
112
134
 
@@ -48,6 +48,7 @@ function InserterSearchResults( {
48
48
  showBlockDirectory = false,
49
49
  isDraggable = true,
50
50
  shouldFocusBlock = true,
51
+ prioritizePatterns,
51
52
  } ) {
52
53
  const debouncedSpeak = useDebounce( speak, 500 );
53
54
 
@@ -70,7 +71,25 @@ function InserterSearchResults( {
70
71
  destinationRootClientId
71
72
  );
72
73
 
74
+ const filteredBlockPatterns = useMemo( () => {
75
+ if ( maxBlockPatterns === 0 ) {
76
+ return [];
77
+ }
78
+ const results = searchItems( patterns, filterValue );
79
+ return maxBlockPatterns !== undefined
80
+ ? results.slice( 0, maxBlockPatterns )
81
+ : results;
82
+ }, [ filterValue, patterns, maxBlockPatterns ] );
83
+
84
+ let maxBlockTypesToShow = maxBlockTypes;
85
+ if ( prioritizePatterns && filteredBlockPatterns.length > 2 ) {
86
+ maxBlockTypesToShow = 0;
87
+ }
88
+
73
89
  const filteredBlockTypes = useMemo( () => {
90
+ if ( maxBlockTypesToShow === 0 ) {
91
+ return [];
92
+ }
74
93
  const results = searchBlockItems(
75
94
  orderBy( blockTypes, [ 'frecency' ], [ 'desc' ] ),
76
95
  blockTypeCategories,
@@ -78,8 +97,8 @@ function InserterSearchResults( {
78
97
  filterValue
79
98
  );
80
99
 
81
- return maxBlockTypes !== undefined
82
- ? results.slice( 0, maxBlockTypes )
100
+ return maxBlockTypesToShow !== undefined
101
+ ? results.slice( 0, maxBlockTypesToShow )
83
102
  : results;
84
103
  }, [
85
104
  filterValue,
@@ -89,13 +108,6 @@ function InserterSearchResults( {
89
108
  maxBlockTypes,
90
109
  ] );
91
110
 
92
- const filteredBlockPatterns = useMemo( () => {
93
- const results = searchItems( patterns, filterValue );
94
- return maxBlockPatterns !== undefined
95
- ? results.slice( 0, maxBlockPatterns )
96
- : results;
97
- }, [ filterValue, patterns, maxBlockPatterns ] );
98
-
99
111
  // Announce search results on change
100
112
  useEffect( () => {
101
113
  if ( ! filterValue ) {
@@ -122,49 +134,49 @@ function InserterSearchResults( {
122
134
  const hasItems =
123
135
  ! isEmpty( filteredBlockTypes ) || ! isEmpty( filteredBlockPatterns );
124
136
 
137
+ const blocksUI = !! filteredBlockTypes.length && (
138
+ <InserterPanel
139
+ title={ <VisuallyHidden>{ __( 'Blocks' ) }</VisuallyHidden> }
140
+ >
141
+ <BlockTypesList
142
+ items={ currentShownBlockTypes }
143
+ onSelect={ onSelectBlockType }
144
+ onHover={ onHover }
145
+ label={ __( 'Blocks' ) }
146
+ isDraggable={ isDraggable }
147
+ />
148
+ </InserterPanel>
149
+ );
150
+
151
+ const patternsUI = !! filteredBlockPatterns.length && (
152
+ <InserterPanel
153
+ title={
154
+ <VisuallyHidden>{ __( 'Block Patterns' ) }</VisuallyHidden>
155
+ }
156
+ >
157
+ <div className="block-editor-inserter__quick-inserter-patterns">
158
+ <BlockPatternsList
159
+ shownPatterns={ currentShownPatterns }
160
+ blockPatterns={ filteredBlockPatterns }
161
+ onClickPattern={ onSelectBlockPattern }
162
+ isDraggable={ isDraggable }
163
+ />
164
+ </div>
165
+ </InserterPanel>
166
+ );
167
+
125
168
  return (
126
169
  <InserterListbox>
127
170
  { ! showBlockDirectory && ! hasItems && <InserterNoResults /> }
128
171
 
129
- { !! filteredBlockTypes.length && (
130
- <InserterPanel
131
- title={
132
- <VisuallyHidden>{ __( 'Blocks' ) }</VisuallyHidden>
133
- }
134
- >
135
- <BlockTypesList
136
- items={ currentShownBlockTypes }
137
- onSelect={ onSelectBlockType }
138
- onHover={ onHover }
139
- label={ __( 'Blocks' ) }
140
- isDraggable={ isDraggable }
141
- />
142
- </InserterPanel>
143
- ) }
172
+ { prioritizePatterns ? patternsUI : blocksUI }
144
173
 
145
174
  { !! filteredBlockTypes.length &&
146
175
  !! filteredBlockPatterns.length && (
147
176
  <div className="block-editor-inserter__quick-inserter-separator" />
148
177
  ) }
149
178
 
150
- { !! filteredBlockPatterns.length && (
151
- <InserterPanel
152
- title={
153
- <VisuallyHidden>
154
- { __( 'Block Patterns' ) }
155
- </VisuallyHidden>
156
- }
157
- >
158
- <div className="block-editor-inserter__quick-inserter-patterns">
159
- <BlockPatternsList
160
- shownPatterns={ currentShownPatterns }
161
- blockPatterns={ filteredBlockPatterns }
162
- onClickPattern={ onSelectBlockPattern }
163
- isDraggable={ isDraggable }
164
- />
165
- </div>
166
- </InserterPanel>
167
- ) }
179
+ { prioritizePatterns ? blocksUI : patternsUI }
168
180
 
169
181
  { showBlockDirectory && (
170
182
  <__unstableInserterMenuExtension.Slot
@@ -18,9 +18,13 @@ _Note:_ It is worth noting that the line height setting option is an opt-in feat
18
18
  Renders the markup for the line height setting option in the block inspector.
19
19
 
20
20
  ```jsx
21
- import { KeyboardShortcuts } from '@wordpress/block-editor';
21
+ import { LineHeightControl } from '@wordpress/block-editor';
22
22
  const MyLineHeightControl = () => (
23
- <LineHeightControl value={ lineHeight } onChange={ onChange } />
23
+ <LineHeightControl
24
+ value={ lineHeight }
25
+ onChange={ onChange }
26
+ __nextHasNoMarginBottom={ true }
27
+ />
24
28
  );
25
29
  ```
26
30
 
@@ -38,6 +42,13 @@ The value of the line height.
38
42
 
39
43
  A callback function that handles the application of the line height value.
40
44
 
45
+ #### `__nextHasNoMarginBottom`
46
+
47
+ - **Type:** `boolean`
48
+ - **Default:** `false`
49
+
50
+ Start opting into the new margin-free styles that will become the default in a future version, currently scheduled to be WordPress 6.4. (The prop can be safely removed once this happens.)
51
+
41
52
  ## Related components
42
53
 
43
54
  Block Editor components are components that can be used to compose the UI of your block editor. Thus, they can only be used under a [`BlockEditorProvider`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/provider/README.md) in the components tree.
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
+ import deprecated from '@wordpress/deprecated';
4
5
  import { __ } from '@wordpress/i18n';
5
- import { TextControl } from '@wordpress/components';
6
- import { ZERO } from '@wordpress/keycodes';
6
+ import { __experimentalNumberControl as NumberControl } from '@wordpress/components';
7
7
 
8
8
  /**
9
9
  * Internal dependencies
@@ -15,64 +15,87 @@ import {
15
15
  isLineHeightDefined,
16
16
  } from './utils';
17
17
 
18
- export default function LineHeightControl( { value: lineHeight, onChange } ) {
18
+ export default function LineHeightControl( {
19
+ value: lineHeight,
20
+ onChange,
21
+ /** Start opting into the new margin-free styles that will become the default in a future version. */
22
+ __nextHasNoMarginBottom = false,
23
+ __unstableInputWidth = '60px',
24
+ } ) {
19
25
  const isDefined = isLineHeightDefined( lineHeight );
20
26
 
21
- const handleOnKeyDown = ( event ) => {
22
- const { keyCode } = event;
23
-
24
- if ( keyCode === ZERO && ! isDefined ) {
25
- /**
26
- * Prevents the onChange callback from firing, which prevents
27
- * the logic from assuming the change was triggered from
28
- * an input arrow CLICK.
29
- */
30
- event.preventDefault();
31
- onChange( '0' );
32
- }
33
- };
34
-
35
- const handleOnChange = ( nextValue ) => {
27
+ const adjustNextValue = ( nextValue, wasTypedOrPasted ) => {
36
28
  // Set the next value without modification if lineHeight has been defined
37
- if ( isDefined ) {
38
- onChange( nextValue );
39
- return;
40
- }
29
+ if ( isDefined ) return nextValue;
41
30
 
42
- // Otherwise...
43
31
  /**
44
- * The following logic handles the initial up/down arrow CLICK of the
45
- * input element. This is so that the next values (from an undefined value state)
46
- * are more better suited for line-height rendering.
32
+ * The following logic handles the initial step up/down action
33
+ * (from an undefined value state) so that the next values are better suited for
34
+ * line-height rendering. For example, the first step up should immediately
35
+ * go to 1.6, rather than the normally expected 0.1.
36
+ *
37
+ * Step up/down actions can be triggered by keydowns of the up/down arrow keys,
38
+ * or by clicking the spin buttons.
47
39
  */
48
- let adjustedNextValue = nextValue;
49
-
50
40
  switch ( nextValue ) {
51
41
  case `${ STEP }`:
52
42
  // Increment by step value
53
- adjustedNextValue = BASE_DEFAULT_VALUE + STEP;
54
- break;
55
- case '0':
43
+ return BASE_DEFAULT_VALUE + STEP;
44
+ case '0': {
45
+ // This means the user explicitly input '0', rather than stepped down
46
+ // from an undefined value state
47
+ if ( wasTypedOrPasted ) return nextValue;
56
48
  // Decrement by step value
57
- adjustedNextValue = BASE_DEFAULT_VALUE - STEP;
58
- break;
49
+ return BASE_DEFAULT_VALUE - STEP;
50
+ }
51
+ case '':
52
+ return BASE_DEFAULT_VALUE;
53
+ default:
54
+ return nextValue;
59
55
  }
56
+ };
60
57
 
61
- onChange( adjustedNextValue );
58
+ const stateReducer = ( state, action ) => {
59
+ // Be careful when changing this — cross-browser behavior of the
60
+ // `inputType` field in `input` events are inconsistent.
61
+ // For example, Firefox emits an input event with inputType="insertReplacementText"
62
+ // on spin button clicks, while other browsers do not even emit an input event.
63
+ const wasTypedOrPasted = [ 'insertText', 'insertFromPaste' ].includes(
64
+ action.payload.event.nativeEvent?.inputType
65
+ );
66
+ state.value = adjustNextValue( state.value, wasTypedOrPasted );
67
+ return state;
62
68
  };
63
69
 
64
70
  const value = isDefined ? lineHeight : RESET_VALUE;
65
71
 
72
+ if ( ! __nextHasNoMarginBottom ) {
73
+ deprecated(
74
+ 'Bottom margin styles for wp.blockEditor.LineHeightControl',
75
+ {
76
+ since: '6.0',
77
+ version: '6.4',
78
+ hint:
79
+ 'Set the `__nextHasNoMarginBottom` prop to true to start opting into the new styles, which will become the default in a future version',
80
+ }
81
+ );
82
+ }
83
+ const deprecatedStyles = __nextHasNoMarginBottom
84
+ ? undefined
85
+ : { marginBottom: 24 };
86
+
66
87
  return (
67
- <div className="block-editor-line-height-control">
68
- <TextControl
69
- autoComplete="off"
70
- onKeyDown={ handleOnKeyDown }
71
- onChange={ handleOnChange }
88
+ <div
89
+ className="block-editor-line-height-control"
90
+ style={ deprecatedStyles }
91
+ >
92
+ <NumberControl
93
+ __unstableInputWidth={ __unstableInputWidth }
94
+ __unstableStateReducer={ stateReducer }
95
+ onChange={ onChange }
72
96
  label={ __( 'Line height' ) }
73
97
  placeholder={ BASE_DEFAULT_VALUE }
74
98
  step={ STEP }
75
- type="number"
76
99
  value={ value }
77
100
  min={ 0 }
78
101
  />
@@ -0,0 +1,33 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useState } from '@wordpress/element';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import LineHeightControl from '../';
10
+
11
+ export default {
12
+ component: LineHeightControl,
13
+ title: 'BlockEditor/LineHeightControl',
14
+ };
15
+
16
+ const Template = ( props ) => {
17
+ const [ value, setValue ] = useState();
18
+ return (
19
+ <LineHeightControl onChange={ setValue } value={ value } { ...props } />
20
+ );
21
+ };
22
+
23
+ export const Default = Template.bind( {} );
24
+ Default.args = {
25
+ __nextHasNoMarginBottom: true,
26
+ __unstableInputWidth: '60px',
27
+ };
28
+
29
+ export const UnconstrainedWidth = Template.bind( {} );
30
+ UnconstrainedWidth.args = {
31
+ ...Default.args,
32
+ __unstableInputWidth: '100%',
33
+ };