@wordpress/block-editor 10.1.0 → 10.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 (148) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/block-controls/slot.js +2 -2
  3. package/build/components/block-controls/slot.js.map +1 -1
  4. package/build/components/block-draggable/index.js +1 -1
  5. package/build/components/block-draggable/index.js.map +1 -1
  6. package/build/components/block-inspector/index.js +4 -5
  7. package/build/components/block-inspector/index.js.map +1 -1
  8. package/build/components/block-list/use-in-between-inserter.js +4 -4
  9. package/build/components/block-list/use-in-between-inserter.js.map +1 -1
  10. package/build/components/block-parent-selector/index.js +2 -2
  11. package/build/components/block-parent-selector/index.js.map +1 -1
  12. package/build/components/block-popover/inbetween.js +3 -1
  13. package/build/components/block-popover/inbetween.js.map +1 -1
  14. package/build/components/block-popover/index.js +20 -17
  15. package/build/components/block-popover/index.js.map +1 -1
  16. package/build/components/block-settings-menu/block-settings-dropdown.js +5 -5
  17. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  18. package/build/components/block-tools/index.js +1 -1
  19. package/build/components/block-tools/index.js.map +1 -1
  20. package/build/components/block-tools/use-block-toolbar-popover-props.js +6 -3
  21. package/build/components/block-tools/use-block-toolbar-popover-props.js.map +1 -1
  22. package/build/components/image-editor/use-transform-image.js +2 -2
  23. package/build/components/image-editor/use-transform-image.js.map +1 -1
  24. package/build/components/index.js +9 -0
  25. package/build/components/index.js.map +1 -1
  26. package/build/components/inserter/block-types-tab.js +1 -1
  27. package/build/components/inserter/block-types-tab.js.map +1 -1
  28. package/build/components/inserter/search-items.js +2 -17
  29. package/build/components/inserter/search-items.js.map +1 -1
  30. package/build/components/inspector-controls/slot.js +2 -1
  31. package/build/components/inspector-controls/slot.js.map +1 -1
  32. package/build/components/rich-text/index.js +17 -0
  33. package/build/components/rich-text/index.js.map +1 -1
  34. package/build/components/spacing-sizes-control/index.js +10 -2
  35. package/build/components/spacing-sizes-control/index.js.map +1 -1
  36. package/build/components/spacing-sizes-control/spacing-input-control.js +5 -4
  37. package/build/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
  38. package/build/components/url-popover/image-url-input-ui.js +1 -1
  39. package/build/components/url-popover/image-url-input-ui.js.map +1 -1
  40. package/build/components/use-block-drop-zone/index.js +19 -1
  41. package/build/components/use-block-drop-zone/index.js.map +1 -1
  42. package/build/components/use-on-block-drop/index.js +62 -20
  43. package/build/components/use-on-block-drop/index.js.map +1 -1
  44. package/build/components/writing-flow/use-arrow-nav.js +14 -7
  45. package/build/components/writing-flow/use-arrow-nav.js.map +1 -1
  46. package/build/hooks/index.js +13 -1
  47. package/build/hooks/index.js.map +1 -1
  48. package/build/hooks/layout.js +76 -23
  49. package/build/hooks/layout.js.map +1 -1
  50. package/build/index.js +14 -0
  51. package/build/index.js.map +1 -1
  52. package/build/store/reducer.js +5 -3
  53. package/build/store/reducer.js.map +1 -1
  54. package/build/store/selectors.js +1 -1
  55. package/build/store/selectors.js.map +1 -1
  56. package/build-module/components/block-controls/slot.js +3 -3
  57. package/build-module/components/block-controls/slot.js.map +1 -1
  58. package/build-module/components/block-draggable/index.js +1 -1
  59. package/build-module/components/block-draggable/index.js.map +1 -1
  60. package/build-module/components/block-inspector/index.js +5 -6
  61. package/build-module/components/block-inspector/index.js.map +1 -1
  62. package/build-module/components/block-list/use-in-between-inserter.js +4 -4
  63. package/build-module/components/block-list/use-in-between-inserter.js.map +1 -1
  64. package/build-module/components/block-parent-selector/index.js +2 -2
  65. package/build-module/components/block-parent-selector/index.js.map +1 -1
  66. package/build-module/components/block-popover/inbetween.js +3 -1
  67. package/build-module/components/block-popover/inbetween.js.map +1 -1
  68. package/build-module/components/block-popover/index.js +20 -17
  69. package/build-module/components/block-popover/index.js.map +1 -1
  70. package/build-module/components/block-settings-menu/block-settings-dropdown.js +7 -7
  71. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  72. package/build-module/components/block-tools/index.js +1 -1
  73. package/build-module/components/block-tools/index.js.map +1 -1
  74. package/build-module/components/block-tools/use-block-toolbar-popover-props.js +6 -3
  75. package/build-module/components/block-tools/use-block-toolbar-popover-props.js.map +1 -1
  76. package/build-module/components/image-editor/use-transform-image.js +2 -2
  77. package/build-module/components/image-editor/use-transform-image.js.map +1 -1
  78. package/build-module/components/index.js +1 -0
  79. package/build-module/components/index.js.map +1 -1
  80. package/build-module/components/inserter/block-types-tab.js +3 -3
  81. package/build-module/components/inserter/block-types-tab.js.map +1 -1
  82. package/build-module/components/inserter/search-items.js +3 -17
  83. package/build-module/components/inserter/search-items.js.map +1 -1
  84. package/build-module/components/inspector-controls/slot.js +3 -2
  85. package/build-module/components/inspector-controls/slot.js.map +1 -1
  86. package/build-module/components/rich-text/index.js +17 -0
  87. package/build-module/components/rich-text/index.js.map +1 -1
  88. package/build-module/components/spacing-sizes-control/index.js +10 -3
  89. package/build-module/components/spacing-sizes-control/index.js.map +1 -1
  90. package/build-module/components/spacing-sizes-control/spacing-input-control.js +6 -5
  91. package/build-module/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
  92. package/build-module/components/url-popover/image-url-input-ui.js +1 -1
  93. package/build-module/components/url-popover/image-url-input-ui.js.map +1 -1
  94. package/build-module/components/use-block-drop-zone/index.js +19 -1
  95. package/build-module/components/use-block-drop-zone/index.js.map +1 -1
  96. package/build-module/components/use-on-block-drop/index.js +62 -21
  97. package/build-module/components/use-on-block-drop/index.js.map +1 -1
  98. package/build-module/components/writing-flow/use-arrow-nav.js +14 -7
  99. package/build-module/components/writing-flow/use-arrow-nav.js.map +1 -1
  100. package/build-module/hooks/index.js +1 -0
  101. package/build-module/hooks/index.js.map +1 -1
  102. package/build-module/hooks/layout.js +73 -23
  103. package/build-module/hooks/layout.js.map +1 -1
  104. package/build-module/index.js +1 -1
  105. package/build-module/index.js.map +1 -1
  106. package/build-module/store/reducer.js +5 -4
  107. package/build-module/store/reducer.js.map +1 -1
  108. package/build-module/store/selectors.js +1 -1
  109. package/build-module/store/selectors.js.map +1 -1
  110. package/build-style/style-rtl.css +48 -23
  111. package/build-style/style.css +48 -23
  112. package/package.json +29 -30
  113. package/src/components/block-controls/slot.js +3 -3
  114. package/src/components/block-draggable/index.js +1 -1
  115. package/src/components/block-draggable/test/index.native.js +0 -9
  116. package/src/components/block-inspector/index.js +6 -10
  117. package/src/components/block-list/use-in-between-inserter.js +5 -5
  118. package/src/components/block-parent-selector/index.js +2 -2
  119. package/src/components/block-popover/inbetween.js +1 -1
  120. package/src/components/block-popover/index.js +37 -22
  121. package/src/components/block-preview/style.scss +13 -0
  122. package/src/components/block-settings-menu/block-settings-dropdown.js +7 -7
  123. package/src/components/block-switcher/test/__snapshots__/index.js.snap +104 -33
  124. package/src/components/block-switcher/test/index.js +121 -61
  125. package/src/components/block-tools/index.js +1 -1
  126. package/src/components/block-tools/use-block-toolbar-popover-props.js +6 -0
  127. package/src/components/button-block-appender/style.scss +3 -1
  128. package/src/components/image-editor/use-transform-image.js +2 -2
  129. package/src/components/index.js +1 -0
  130. package/src/components/inserter/block-types-tab.js +3 -3
  131. package/src/components/inserter/search-items.js +3 -15
  132. package/src/components/inserter/test/search-items.js +4 -0
  133. package/src/components/inspector-controls/slot.js +6 -2
  134. package/src/components/responsive-block-control/test/index.js +73 -118
  135. package/src/components/rich-text/index.js +22 -0
  136. package/src/components/spacing-sizes-control/index.js +15 -3
  137. package/src/components/spacing-sizes-control/spacing-input-control.js +8 -7
  138. package/src/components/spacing-sizes-control/style.scss +28 -24
  139. package/src/components/url-popover/image-url-input-ui.js +1 -1
  140. package/src/components/use-block-drop-zone/index.js +26 -1
  141. package/src/components/use-on-block-drop/index.js +110 -35
  142. package/src/components/use-on-block-drop/test/index.js +33 -43
  143. package/src/components/writing-flow/use-arrow-nav.js +12 -8
  144. package/src/hooks/index.js +1 -0
  145. package/src/hooks/layout.js +64 -21
  146. package/src/index.js +2 -0
  147. package/src/store/reducer.js +4 -4
  148. package/src/store/selectors.js +1 -0
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { castArray, flow } from 'lodash';
4
+ import { castArray } from 'lodash';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -18,7 +18,7 @@ import {
18
18
  } from '@wordpress/element';
19
19
  import { __, sprintf } from '@wordpress/i18n';
20
20
  import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
21
- import { useCopyToClipboard } from '@wordpress/compose';
21
+ import { pipe, useCopyToClipboard } from '@wordpress/compose';
22
22
 
23
23
  /**
24
24
  * Internal dependencies
@@ -241,7 +241,7 @@ export function BlockSettingsDropdown( {
241
241
  />
242
242
  { canDuplicate && (
243
243
  <MenuItem
244
- onClick={ flow(
244
+ onClick={ pipe(
245
245
  onClose,
246
246
  onDuplicate,
247
247
  updateSelectionAfterDuplicate
@@ -254,7 +254,7 @@ export function BlockSettingsDropdown( {
254
254
  { canInsertDefaultBlock && (
255
255
  <>
256
256
  <MenuItem
257
- onClick={ flow(
257
+ onClick={ pipe(
258
258
  onClose,
259
259
  onInsertBefore
260
260
  ) }
@@ -263,7 +263,7 @@ export function BlockSettingsDropdown( {
263
263
  { __( 'Insert before' ) }
264
264
  </MenuItem>
265
265
  <MenuItem
266
- onClick={ flow(
266
+ onClick={ pipe(
267
267
  onClose,
268
268
  onInsertAfter
269
269
  ) }
@@ -275,7 +275,7 @@ export function BlockSettingsDropdown( {
275
275
  ) }
276
276
  { canMove && ! onlyBlock && (
277
277
  <MenuItem
278
- onClick={ flow( onClose, onMoveTo ) }
278
+ onClick={ pipe( onClose, onMoveTo ) }
279
279
  >
280
280
  { __( 'Move to' ) }
281
281
  </MenuItem>
@@ -302,7 +302,7 @@ export function BlockSettingsDropdown( {
302
302
  { canRemove && (
303
303
  <MenuGroup>
304
304
  <MenuItem
305
- onClick={ flow(
305
+ onClick={ pipe(
306
306
  onClose,
307
307
  onRemove,
308
308
  updateSelectionAfterRemove
@@ -1,43 +1,114 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`BlockSwitcherDropdownMenu should render disabled block switcher with multi block of different types when no transforms 1`] = `
4
- <ToolbarGroup>
5
- <ForwardRef(ToolbarButton)
6
- className="block-editor-block-switcher__no-switcher-icon"
7
- disabled={true}
8
- icon={
9
- <React.Fragment>
10
- <Memo(BlockIcon)
11
- icon={
12
- <SVG
13
- viewBox="0 0 24 24"
14
- xmlns="http://www.w3.org/2000/svg"
15
- >
16
- <Path
17
- d="M20.2 8v11c0 .7-.6 1.2-1.2 1.2H6v1.5h13c1.5 0 2.7-1.2 2.7-2.8V8zM18 16.4V4.6c0-.9-.7-1.6-1.6-1.6H4.6C3.7 3 3 3.7 3 4.6v11.8c0 .9.7 1.6 1.6 1.6h11.8c.9 0 1.6-.7 1.6-1.6zm-13.5 0V4.6c0-.1.1-.1.1-.1h11.8c.1 0 .1.1.1.1v11.8c0 .1-.1.1-.1.1H4.6l-.1-.1z"
18
- />
19
- </SVG>
20
- }
21
- showColors={true}
22
- />
23
- </React.Fragment>
24
- }
25
- />
26
- </ToolbarGroup>
4
+ <div>
5
+ <div
6
+ class="components-toolbar"
7
+ >
8
+ <div>
9
+ <button
10
+ aria-label="Block Name"
11
+ class="components-button components-toolbar__control block-editor-block-switcher__no-switcher-icon has-icon"
12
+ data-toolbar-item="true"
13
+ disabled=""
14
+ type="button"
15
+ >
16
+ <span
17
+ class="block-editor-block-icon has-colors"
18
+ >
19
+ <svg
20
+ aria-hidden="true"
21
+ focusable="false"
22
+ height="24"
23
+ viewBox="0 0 24 24"
24
+ width="24"
25
+ xmlns="http://www.w3.org/2000/svg"
26
+ >
27
+ <path
28
+ d="M20.2 8v11c0 .7-.6 1.2-1.2 1.2H6v1.5h13c1.5 0 2.7-1.2 2.7-2.8V8zM18 16.4V4.6c0-.9-.7-1.6-1.6-1.6H4.6C3.7 3 3 3.7 3 4.6v11.8c0 .9.7 1.6 1.6 1.6h11.8c.9 0 1.6-.7 1.6-1.6zm-13.5 0V4.6c0-.1.1-.1.1-.1h11.8c.1 0 .1.1.1.1v11.8c0 .1-.1.1-.1.1H4.6l-.1-.1z"
29
+ />
30
+ </svg>
31
+ </span>
32
+ </button>
33
+ </div>
34
+ </div>
35
+ </div>
27
36
  `;
28
37
 
29
38
  exports[`BlockSwitcherDropdownMenu should render enabled block switcher with multi block when transforms exist 1`] = `
30
- <ToolbarGroup>
31
- <ForwardRef(ToolbarItem)>
32
- <Component />
33
- </ForwardRef(ToolbarItem)>
34
- </ToolbarGroup>
39
+ <div>
40
+ <div
41
+ class="components-toolbar"
42
+ >
43
+ <div
44
+ class="components-dropdown components-dropdown-menu block-editor-block-switcher"
45
+ tabindex="-1"
46
+ >
47
+ <button
48
+ aria-describedby="components-button__description-2"
49
+ aria-expanded="false"
50
+ aria-haspopup="true"
51
+ aria-label="Block Name"
52
+ class="components-button components-dropdown-menu__toggle has-icon"
53
+ data-toolbar-item="true"
54
+ type="button"
55
+ >
56
+ <span
57
+ class="block-editor-block-icon block-editor-block-switcher__toggle has-colors"
58
+ />
59
+ </button>
60
+ <div
61
+ class="components-visually-hidden emotion-0 emotion-1"
62
+ data-wp-c16t="true"
63
+ data-wp-component="VisuallyHidden"
64
+ style="border: 0px; clip: rect(1px, 1px, 1px, 1px); clip-path: inset( 50% ); height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px; word-wrap: normal;"
65
+ >
66
+ <span
67
+ id="components-button__description-2"
68
+ >
69
+ Change type of 2 blocks
70
+ </span>
71
+ </div>
72
+ </div>
73
+ </div>
74
+ </div>
35
75
  `;
36
76
 
37
77
  exports[`BlockSwitcherDropdownMenu should render switcher with blocks 1`] = `
38
- <ToolbarGroup>
39
- <ForwardRef(ToolbarItem)>
40
- <Component />
41
- </ForwardRef(ToolbarItem)>
42
- </ToolbarGroup>
78
+ <div>
79
+ <div
80
+ class="components-toolbar"
81
+ >
82
+ <div
83
+ class="components-dropdown components-dropdown-menu block-editor-block-switcher"
84
+ tabindex="-1"
85
+ >
86
+ <button
87
+ aria-describedby="components-button__description-0"
88
+ aria-expanded="false"
89
+ aria-haspopup="true"
90
+ aria-label="Block Name"
91
+ class="components-button components-dropdown-menu__toggle has-icon"
92
+ data-toolbar-item="true"
93
+ type="button"
94
+ >
95
+ <span
96
+ class="block-editor-block-icon block-editor-block-switcher__toggle has-colors"
97
+ />
98
+ </button>
99
+ <div
100
+ class="components-visually-hidden emotion-0 emotion-1"
101
+ data-wp-c16t="true"
102
+ data-wp-component="VisuallyHidden"
103
+ style="border: 0px; clip: rect(1px, 1px, 1px, 1px); clip-path: inset( 50% ); height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px; word-wrap: normal;"
104
+ >
105
+ <span
106
+ id="components-button__description-0"
107
+ >
108
+ Block Name: Change block type or style
109
+ </span>
110
+ </div>
111
+ </div>
112
+ </div>
113
+ </div>
43
114
  `;
@@ -1,14 +1,14 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { shallow, mount } from 'enzyme';
4
+ import { render, screen, within } from '@testing-library/react';
5
+ import userEvent from '@testing-library/user-event';
5
6
 
6
7
  /**
7
8
  * WordPress dependencies
8
9
  */
9
10
  import { useSelect } from '@wordpress/data';
10
11
  import { registerBlockType, unregisterBlockType } from '@wordpress/blocks';
11
- import { Button } from '@wordpress/components';
12
12
  import { copy } from '@wordpress/icons';
13
13
 
14
14
  /**
@@ -17,23 +17,25 @@ import { copy } from '@wordpress/icons';
17
17
  import { BlockSwitcher, BlockSwitcherDropdownMenu } from '../';
18
18
 
19
19
  jest.mock( '@wordpress/data/src/components/use-select', () => jest.fn() );
20
- jest.mock( '../../block-title/use-block-display-title', () => jest.fn() );
20
+ jest.mock( '../../block-title/use-block-display-title', () =>
21
+ jest.fn().mockReturnValue( 'Block Name' )
22
+ );
21
23
 
22
24
  describe( 'BlockSwitcher', () => {
23
25
  test( 'should not render block switcher without blocks', () => {
24
26
  useSelect.mockImplementation( () => ( {} ) );
25
- const wrapper = shallow( <BlockSwitcher /> );
26
- expect( wrapper.html() ).toBeNull();
27
+ const { container } = render( <BlockSwitcher /> );
28
+ expect( container ).toBeEmptyDOMElement();
27
29
  } );
28
30
 
29
31
  test( 'should not render block switcher with null blocks', () => {
30
32
  useSelect.mockImplementation( () => ( { blocks: [ null ] } ) );
31
- const wrapper = shallow(
33
+ const { container } = render(
32
34
  <BlockSwitcher
33
35
  clientIds={ [ 'a1303fd6-3e60-4fff-a770-0e0ea656c5b9' ] }
34
36
  />
35
37
  );
36
- expect( wrapper.html() ).toBeNull();
38
+ expect( container ).toBeEmptyDOMElement();
37
39
  } );
38
40
  } );
39
41
  describe( 'BlockSwitcherDropdownMenu', () => {
@@ -122,10 +124,10 @@ describe( 'BlockSwitcherDropdownMenu', () => {
122
124
  ],
123
125
  canRemove: true,
124
126
  } ) );
125
- const wrapper = shallow(
127
+ const { container } = render(
126
128
  <BlockSwitcherDropdownMenu blocks={ [ headingBlock1 ] } />
127
129
  );
128
- expect( wrapper ).toMatchSnapshot();
130
+ expect( container ).toMatchSnapshot();
129
131
  } );
130
132
 
131
133
  test( 'should render disabled block switcher with multi block of different types when no transforms', () => {
@@ -133,12 +135,12 @@ describe( 'BlockSwitcherDropdownMenu', () => {
133
135
  possibleBlockTransformations: [],
134
136
  icon: copy,
135
137
  } ) );
136
- const wrapper = shallow(
138
+ const { container } = render(
137
139
  <BlockSwitcherDropdownMenu
138
140
  blocks={ [ headingBlock1, textBlock ] }
139
141
  />
140
142
  );
141
- expect( wrapper ).toMatchSnapshot();
143
+ expect( container ).toMatchSnapshot();
142
144
  } );
143
145
 
144
146
  test( 'should render enabled block switcher with multi block when transforms exist', () => {
@@ -149,12 +151,12 @@ describe( 'BlockSwitcherDropdownMenu', () => {
149
151
  ],
150
152
  canRemove: true,
151
153
  } ) );
152
- const wrapper = shallow(
154
+ const { container } = render(
153
155
  <BlockSwitcherDropdownMenu
154
156
  blocks={ [ headingBlock1, headingBlock2 ] }
155
157
  />
156
158
  );
157
- expect( wrapper ).toMatchSnapshot();
159
+ expect( container ).toMatchSnapshot();
158
160
  } );
159
161
 
160
162
  describe( 'Dropdown', () => {
@@ -166,70 +168,128 @@ describe( 'BlockSwitcherDropdownMenu', () => {
166
168
  canRemove: true,
167
169
  } ) );
168
170
  } );
169
- const getDropdown = () =>
170
- mount(
171
- <BlockSwitcherDropdownMenu blocks={ [ headingBlock1 ] } />
172
- ).find( 'Dropdown' );
173
171
 
174
172
  test( 'should dropdown exist', () => {
175
- expect( getDropdown() ).toHaveLength( 1 );
176
- } );
173
+ render(
174
+ <BlockSwitcherDropdownMenu blocks={ [ headingBlock1 ] } />
175
+ );
177
176
 
178
- describe( '.renderToggle', () => {
179
- const onToggleStub = jest.fn();
180
- const mockKeyDown = {
181
- preventDefault: () => {},
182
- code: 'ArrowDown',
183
- };
177
+ expect(
178
+ screen.getByRole( 'button', {
179
+ name: 'Block Name',
180
+ expanded: false,
181
+ } )
182
+ ).toBeVisible();
183
+ } );
184
184
 
185
- afterEach( () => {
186
- onToggleStub.mockReset();
185
+ test( 'should simulate a keydown event, which should open transform toggle.', async () => {
186
+ const user = userEvent.setup( {
187
+ advanceTimers: jest.advanceTimersByTime,
187
188
  } );
188
189
 
189
- test( 'should simulate a keydown event, which should call onToggle and open transform toggle.', () => {
190
- const toggleClosed = mount(
191
- getDropdown().props().renderToggle( {
192
- onToggle: onToggleStub,
193
- isOpen: false,
194
- } )
195
- );
196
- const iconButtonClosed = toggleClosed.find( Button );
190
+ render(
191
+ <BlockSwitcherDropdownMenu blocks={ [ headingBlock1 ] } />
192
+ );
193
+
194
+ expect(
195
+ screen.getByRole( 'button', {
196
+ name: 'Block Name',
197
+ expanded: false,
198
+ } )
199
+ ).toBeVisible();
200
+ expect(
201
+ screen.queryByRole( 'menu', {
202
+ name: 'Block Name',
203
+ } )
204
+ ).not.toBeInTheDocument();
205
+
206
+ await user.type(
207
+ screen.getByRole( 'button', {
208
+ name: 'Block Name',
209
+ expanded: false,
210
+ } ),
211
+ '[ArrowDown]'
212
+ );
197
213
 
198
- iconButtonClosed.simulate( 'keydown', mockKeyDown );
214
+ expect(
215
+ screen.getByRole( 'button', {
216
+ name: 'Block Name',
217
+ expanded: true,
218
+ } )
219
+ ).toBeVisible();
199
220
 
200
- expect( onToggleStub ).toHaveBeenCalledTimes( 1 );
221
+ const menu = screen.getByRole( 'menu', {
222
+ name: 'Block Name',
201
223
  } );
224
+ expect( menu ).toBeInTheDocument();
225
+ expect( menu ).not.toBeVisible();
226
+ } );
202
227
 
203
- test( 'should simulate a click event, which should call onToggle.', () => {
204
- const toggleOpen = mount(
205
- getDropdown().props().renderToggle( {
206
- onToggle: onToggleStub,
207
- isOpen: true,
208
- } )
209
- );
210
- const iconButtonOpen = toggleOpen.find( Button );
228
+ test( 'should simulate a click event, which should call onToggle.', async () => {
229
+ const user = userEvent.setup( {
230
+ advanceTimers: jest.advanceTimersByTime,
231
+ } );
232
+
233
+ render(
234
+ <BlockSwitcherDropdownMenu blocks={ [ headingBlock1 ] } />
235
+ );
236
+
237
+ expect(
238
+ screen.getByRole( 'button', {
239
+ name: 'Block Name',
240
+ expanded: false,
241
+ } )
242
+ ).toBeVisible();
243
+ expect(
244
+ screen.queryByRole( 'menu', {
245
+ name: 'Block Name',
246
+ } )
247
+ ).not.toBeInTheDocument();
248
+
249
+ await user.click(
250
+ screen.getByRole( 'button', {
251
+ name: 'Block Name',
252
+ expanded: false,
253
+ } )
254
+ );
211
255
 
212
- iconButtonOpen.simulate( 'keydown', mockKeyDown );
256
+ expect(
257
+ screen.getByRole( 'button', {
258
+ name: 'Block Name',
259
+ expanded: true,
260
+ } )
261
+ ).toBeVisible();
213
262
 
214
- expect( onToggleStub ).toHaveBeenCalledTimes( 0 );
263
+ const menu = screen.getByRole( 'menu', {
264
+ name: 'Block Name',
215
265
  } );
266
+ expect( menu ).toBeInTheDocument();
267
+ expect( menu ).not.toBeVisible();
216
268
  } );
217
269
 
218
- describe( '.renderContent', () => {
219
- test( 'should create the transform items for the chosen block. A heading block will have 3 items', () => {
220
- const onCloseStub = jest.fn();
221
- const content = shallow(
222
- <div>
223
- { getDropdown()
224
- .props()
225
- .renderContent( { onClose: onCloseStub } ) }
226
- </div>
227
- );
228
- const blockList = content.find( 'BlockTransformationsMenu' );
229
- expect(
230
- blockList.prop( 'possibleBlockTransformations' )
231
- ).toHaveLength( 1 );
270
+ test( 'should create the transform items for the chosen block.', async () => {
271
+ const user = userEvent.setup( {
272
+ advanceTimers: jest.advanceTimersByTime,
232
273
  } );
274
+
275
+ render(
276
+ <BlockSwitcherDropdownMenu blocks={ [ headingBlock1 ] } />
277
+ );
278
+
279
+ await user.click(
280
+ screen.getByRole( 'button', {
281
+ name: 'Block Name',
282
+ expanded: false,
283
+ } )
284
+ );
285
+
286
+ expect(
287
+ within(
288
+ screen.getByRole( 'menu', {
289
+ name: 'Block Name',
290
+ } )
291
+ ).getAllByRole( 'menuitem' )
292
+ ).toHaveLength( 1 );
233
293
  } );
234
294
  } );
235
295
  } );
@@ -124,7 +124,7 @@ export default function BlockTools( {
124
124
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
125
125
  <div { ...props } onKeyDown={ onKeyDown }>
126
126
  <InsertionPointOpenRef.Provider value={ useRef( false ) }>
127
- { ! isTyping && ! isZoomOutMode && (
127
+ { ! isTyping && (
128
128
  <InsertionPoint
129
129
  __unstableContentRef={ __unstableContentRef }
130
130
  />
@@ -11,10 +11,15 @@ import { useCallback, useLayoutEffect, useState } from '@wordpress/element';
11
11
  import { store as blockEditorStore } from '../../store';
12
12
  import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs';
13
13
 
14
+ const COMMON_PROPS = {
15
+ placement: 'top-start',
16
+ };
17
+
14
18
  // By default the toolbar sets the `shift` prop. If the user scrolls the page
15
19
  // down the toolbar will stay on screen by adopting a sticky position at the
16
20
  // top of the viewport.
17
21
  const DEFAULT_PROPS = {
22
+ ...COMMON_PROPS,
18
23
  flip: false,
19
24
  shift: true,
20
25
  };
@@ -25,6 +30,7 @@ const DEFAULT_PROPS = {
25
30
  // the block. This only happens if the block is smaller than the viewport, as
26
31
  // otherwise the toolbar will be off-screen.
27
32
  const RESTRICTED_HEIGHT_PROPS = {
33
+ ...COMMON_PROPS,
28
34
  flip: true,
29
35
  shift: false,
30
36
  };
@@ -35,7 +35,9 @@
35
35
  // When the appender shows up in empty container blocks, such as Group and Columns, add an extra click state.
36
36
  .block-list-appender:only-child {
37
37
  .is-layout-constrained.block-editor-block-list__block:not(.is-selected) > &,
38
- .is-layout-flow.block-editor-block-list__block:not(.is-selected) > & {
38
+ .is-layout-flow.block-editor-block-list__block:not(.is-selected) > &,
39
+ .is-layout-constrained.block-editor-block-list__block:not(.is-selected) > .block-editor-block-list__layout > &,
40
+ .is-layout-flow.block-editor-block-list__block:not(.is-selected) > .block-editor-block-list__layout > & {
39
41
  pointer-events: none;
40
42
 
41
43
  &::after {
@@ -41,7 +41,7 @@ function useTransformState( { url, naturalWidth, naturalHeight } ) {
41
41
  if ( angle === 0 ) {
42
42
  setEditedUrl();
43
43
  setRotation( angle );
44
- setAspect( 1 / aspect );
44
+ setAspect( naturalWidth / naturalHeight );
45
45
  setPosition( {
46
46
  x: -( position.y * naturalAspectRatio ),
47
47
  y: position.x * naturalAspectRatio,
@@ -80,7 +80,7 @@ function useTransformState( { url, naturalWidth, naturalHeight } ) {
80
80
  canvas.toBlob( ( blob ) => {
81
81
  setEditedUrl( URL.createObjectURL( blob ) );
82
82
  setRotation( angle );
83
- setAspect( 1 / aspect );
83
+ setAspect( canvas.width / canvas.height );
84
84
  setPosition( {
85
85
  x: -( position.y * naturalAspectRatio ),
86
86
  y: position.x * naturalAspectRatio,
@@ -155,6 +155,7 @@ export {
155
155
  export { default as __experimentalBlockPatternsList } from './block-patterns-list';
156
156
  export { default as __experimentalPublishDateTimePicker } from './publish-date-time-picker';
157
157
  export { default as __experimentalInspectorPopoverHeader } from './inspector-popover-header';
158
+ export { default as __experimentalUseOnBlockDrop } from './use-on-block-drop';
158
159
 
159
160
  /*
160
161
  * State Related Components
@@ -1,14 +1,14 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { map, flow, groupBy, orderBy } from 'lodash';
4
+ import { map, groupBy, orderBy } from 'lodash';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
9
  import { __, _x } from '@wordpress/i18n';
10
10
  import { useMemo, useEffect } from '@wordpress/element';
11
- import { useAsyncList } from '@wordpress/compose';
11
+ import { pipe, useAsyncList } from '@wordpress/compose';
12
12
 
13
13
  /**
14
14
  * Internal dependencies
@@ -53,7 +53,7 @@ export function BlockTypesTab( {
53
53
  }, [ items ] );
54
54
 
55
55
  const itemsPerCategory = useMemo( () => {
56
- return flow(
56
+ return pipe(
57
57
  ( itemList ) =>
58
58
  itemList.filter(
59
59
  ( item ) => item.category && item.category !== 'reusable'
@@ -1,9 +1,8 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { noCase } from 'change-case';
5
4
  import removeAccents from 'remove-accents';
6
- import { find } from 'lodash';
5
+ import { find, words } from 'lodash';
7
6
 
8
7
  // Default search helpers.
9
8
  const defaultGetName = ( item ) => item.name || '';
@@ -36,17 +35,6 @@ function normalizeSearchInput( input = '' ) {
36
35
  return input;
37
36
  }
38
37
 
39
- /**
40
- * Extracts words from an input string.
41
- *
42
- * @param {string} input The input string.
43
- *
44
- * @return {Array} Words, extracted from the input string.
45
- */
46
- function extractWords( input = '' ) {
47
- return noCase( input ).split( ' ' ).filter( Boolean );
48
- }
49
-
50
38
  /**
51
39
  * Converts the search term into a list of normalized terms.
52
40
  *
@@ -55,7 +43,7 @@ function extractWords( input = '' ) {
55
43
  * @return {string[]} The normalized list of search terms.
56
44
  */
57
45
  export const getNormalizedSearchTerms = ( input = '' ) => {
58
- return extractWords( normalizeSearchInput( input ) );
46
+ return words( normalizeSearchInput( input ) );
59
47
  };
60
48
 
61
49
  const removeMatchingTerms = ( unmatchedTerms, unprocessedTerms ) => {
@@ -162,7 +150,7 @@ export function getItemSearchRank( item, searchTerm, config = {} ) {
162
150
  category,
163
151
  collection,
164
152
  ].join( ' ' );
165
- const normalizedSearchTerms = extractWords( normalizedSearchInput );
153
+ const normalizedSearchTerms = words( normalizedSearchInput );
166
154
  const unmatchedTerms = removeMatchingTerms(
167
155
  normalizedSearchTerms,
168
156
  terms
@@ -42,6 +42,10 @@ describe( 'getNormalizedSearchTerms', () => {
42
42
  getNormalizedSearchTerms( ' Média & Text Tag-Cloud > 123' )
43
43
  ).toEqual( [ 'media', 'text', 'tag', 'cloud', '123' ] );
44
44
  } );
45
+
46
+ it( 'should support non-latin letters', () => {
47
+ expect( getNormalizedSearchTerms( 'მედია' ) ).toEqual( [ 'მედია' ] );
48
+ } );
45
49
  } );
46
50
 
47
51
  describe( 'getItemSearchRank', () => {
@@ -1,7 +1,10 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { __experimentalUseSlot as useSlot } from '@wordpress/components';
4
+ import {
5
+ __experimentalUseSlot as useSlot,
6
+ __experimentalUseSlotFills as useSlotFills,
7
+ } from '@wordpress/components';
5
8
  import warning from '@wordpress/warning';
6
9
 
7
10
  /**
@@ -18,12 +21,13 @@ export default function InspectorControlsSlot( {
18
21
  } ) {
19
22
  const Slot = groups[ group ]?.Slot;
20
23
  const slot = useSlot( Slot?.__unstableName );
24
+ const fills = useSlotFills( Slot?.__unstableName );
21
25
  if ( ! Slot || ! slot ) {
22
26
  warning( `Unknown InspectorControl group "${ group }" provided.` );
23
27
  return null;
24
28
  }
25
29
 
26
- const hasFills = Boolean( slot.fills && slot.fills.length );
30
+ const hasFills = Boolean( fills && fills.length );
27
31
  if ( ! hasFills ) {
28
32
  return null;
29
33
  }