@wordpress/block-editor 10.0.2 → 10.1.1-next.4d3b314fd5.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 (153) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/block-draggable/index.js +1 -1
  3. package/build/components/block-draggable/index.js.map +1 -1
  4. package/build/components/block-list/index.js +19 -5
  5. package/build/components/block-list/index.js.map +1 -1
  6. package/build/components/block-list/use-block-props/index.js +7 -1
  7. package/build/components/block-list/use-block-props/index.js.map +1 -1
  8. package/build/components/block-list/use-in-between-inserter.js +14 -5
  9. package/build/components/block-list/use-in-between-inserter.js.map +1 -1
  10. package/build/components/block-popover/inbetween.js +24 -9
  11. package/build/components/block-popover/inbetween.js.map +1 -1
  12. package/build/components/block-popover/index.js +29 -3
  13. package/build/components/block-popover/index.js.map +1 -1
  14. package/build/components/block-preview/auto.js +23 -11
  15. package/build/components/block-preview/auto.js.map +1 -1
  16. package/build/components/block-styles/index.js +1 -3
  17. package/build/components/block-styles/index.js.map +1 -1
  18. package/build/components/block-tools/index.js +18 -13
  19. package/build/components/block-tools/index.js.map +1 -1
  20. package/build/components/block-tools/insertion-point.js +5 -3
  21. package/build/components/block-tools/insertion-point.js.map +1 -1
  22. package/build/components/block-tools/use-block-toolbar-popover-props.js +6 -3
  23. package/build/components/block-tools/use-block-toolbar-popover-props.js.map +1 -1
  24. package/build/components/block-variation-picker/index.native.js +2 -1
  25. package/build/components/block-variation-picker/index.native.js.map +1 -1
  26. package/build/components/button-block-appender/index.native.js +1 -0
  27. package/build/components/button-block-appender/index.native.js.map +1 -1
  28. package/build/components/index.js +9 -0
  29. package/build/components/index.js.map +1 -1
  30. package/build/components/list-view/index.js +2 -1
  31. package/build/components/list-view/index.js.map +1 -1
  32. package/build/components/rich-text/format-toolbar-container.js +8 -1
  33. package/build/components/rich-text/format-toolbar-container.js.map +1 -1
  34. package/build/components/rich-text/index.js +12 -0
  35. package/build/components/rich-text/index.js.map +1 -1
  36. package/build/components/url-input/index.js +1 -3
  37. package/build/components/url-input/index.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/use-setting/index.js +16 -12
  45. package/build/components/use-setting/index.js.map +1 -1
  46. package/build/components/writing-flow/use-arrow-nav.js +21 -8
  47. package/build/components/writing-flow/use-arrow-nav.js.map +1 -1
  48. package/build/hooks/index.js +13 -1
  49. package/build/hooks/index.js.map +1 -1
  50. package/build/hooks/layout.js +76 -23
  51. package/build/hooks/layout.js.map +1 -1
  52. package/build/index.js +14 -0
  53. package/build/index.js.map +1 -1
  54. package/build/store/reducer.js +33 -19
  55. package/build/store/reducer.js.map +1 -1
  56. package/build/store/selectors.js +5 -5
  57. package/build/store/selectors.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-list/index.js +22 -8
  61. package/build-module/components/block-list/index.js.map +1 -1
  62. package/build-module/components/block-list/use-block-props/index.js +8 -2
  63. package/build-module/components/block-list/use-block-props/index.js.map +1 -1
  64. package/build-module/components/block-list/use-in-between-inserter.js +15 -6
  65. package/build-module/components/block-list/use-in-between-inserter.js.map +1 -1
  66. package/build-module/components/block-popover/inbetween.js +24 -9
  67. package/build-module/components/block-popover/inbetween.js.map +1 -1
  68. package/build-module/components/block-popover/index.js +29 -4
  69. package/build-module/components/block-popover/index.js.map +1 -1
  70. package/build-module/components/block-preview/auto.js +22 -10
  71. package/build-module/components/block-preview/auto.js.map +1 -1
  72. package/build-module/components/block-styles/index.js +1 -2
  73. package/build-module/components/block-styles/index.js.map +1 -1
  74. package/build-module/components/block-tools/index.js +18 -12
  75. package/build-module/components/block-tools/index.js.map +1 -1
  76. package/build-module/components/block-tools/insertion-point.js +5 -3
  77. package/build-module/components/block-tools/insertion-point.js.map +1 -1
  78. package/build-module/components/block-tools/use-block-toolbar-popover-props.js +6 -3
  79. package/build-module/components/block-tools/use-block-toolbar-popover-props.js.map +1 -1
  80. package/build-module/components/block-variation-picker/index.native.js +2 -1
  81. package/build-module/components/block-variation-picker/index.native.js.map +1 -1
  82. package/build-module/components/button-block-appender/index.native.js +1 -0
  83. package/build-module/components/button-block-appender/index.native.js.map +1 -1
  84. package/build-module/components/index.js +1 -0
  85. package/build-module/components/index.js.map +1 -1
  86. package/build-module/components/list-view/index.js +2 -1
  87. package/build-module/components/list-view/index.js.map +1 -1
  88. package/build-module/components/rich-text/format-toolbar-container.js +6 -1
  89. package/build-module/components/rich-text/format-toolbar-container.js.map +1 -1
  90. package/build-module/components/rich-text/index.js +12 -0
  91. package/build-module/components/rich-text/index.js.map +1 -1
  92. package/build-module/components/url-input/index.js +1 -2
  93. package/build-module/components/url-input/index.js.map +1 -1
  94. package/build-module/components/url-popover/image-url-input-ui.js +1 -1
  95. package/build-module/components/url-popover/image-url-input-ui.js.map +1 -1
  96. package/build-module/components/use-block-drop-zone/index.js +19 -1
  97. package/build-module/components/use-block-drop-zone/index.js.map +1 -1
  98. package/build-module/components/use-on-block-drop/index.js +62 -21
  99. package/build-module/components/use-on-block-drop/index.js.map +1 -1
  100. package/build-module/components/use-setting/index.js +16 -12
  101. package/build-module/components/use-setting/index.js.map +1 -1
  102. package/build-module/components/writing-flow/use-arrow-nav.js +22 -9
  103. package/build-module/components/writing-flow/use-arrow-nav.js.map +1 -1
  104. package/build-module/hooks/index.js +1 -0
  105. package/build-module/hooks/index.js.map +1 -1
  106. package/build-module/hooks/layout.js +73 -23
  107. package/build-module/hooks/layout.js.map +1 -1
  108. package/build-module/index.js +1 -1
  109. package/build-module/index.js.map +1 -1
  110. package/build-module/store/reducer.js +29 -18
  111. package/build-module/store/reducer.js.map +1 -1
  112. package/build-module/store/selectors.js +5 -5
  113. package/build-module/store/selectors.js.map +1 -1
  114. package/build-style/style-rtl.css +24 -6
  115. package/build-style/style.css +24 -6
  116. package/package.json +29 -29
  117. package/src/components/block-controls/test/index.js +84 -8
  118. package/src/components/block-draggable/index.js +1 -1
  119. package/src/components/block-draggable/test/index.native.js +0 -9
  120. package/src/components/block-list/index.js +42 -6
  121. package/src/components/block-list/use-block-props/index.js +6 -1
  122. package/src/components/block-list/use-in-between-inserter.js +14 -8
  123. package/src/components/block-mover/style.scss +2 -7
  124. package/src/components/block-popover/inbetween.js +34 -10
  125. package/src/components/block-popover/index.js +47 -3
  126. package/src/components/block-preview/auto.js +77 -65
  127. package/src/components/block-preview/style.scss +13 -0
  128. package/src/components/block-styles/index.js +1 -2
  129. package/src/components/block-tools/index.js +16 -10
  130. package/src/components/block-tools/insertion-point.js +3 -3
  131. package/src/components/block-tools/use-block-toolbar-popover-props.js +6 -0
  132. package/src/components/block-variation-picker/index.native.js +1 -0
  133. package/src/components/button-block-appender/index.native.js +1 -0
  134. package/src/components/index.js +1 -0
  135. package/src/components/link-control/test/index.js +1 -2
  136. package/src/components/list-view/index.js +1 -0
  137. package/src/components/rich-text/format-toolbar-container.js +8 -2
  138. package/src/components/rich-text/index.js +14 -0
  139. package/src/components/url-input/index.js +6 -2
  140. package/src/components/url-popover/image-url-input-ui.js +1 -1
  141. package/src/components/use-block-drop-zone/index.js +26 -1
  142. package/src/components/use-on-block-drop/index.js +110 -35
  143. package/src/components/use-on-block-drop/test/index.js +33 -43
  144. package/src/components/use-setting/index.js +18 -16
  145. package/src/components/warning/style.scss +1 -0
  146. package/src/components/writing-flow/use-arrow-nav.js +23 -9
  147. package/src/hooks/index.js +1 -0
  148. package/src/hooks/layout.js +64 -21
  149. package/src/index.js +2 -0
  150. package/src/store/reducer.js +22 -14
  151. package/src/store/selectors.js +5 -4
  152. package/src/store/test/reducer.js +0 -17
  153. package/src/components/block-controls/test/__snapshots__/index.js.snap +0 -64
@@ -1045,8 +1045,8 @@
1045
1045
  min-width: 0 !important;
1046
1046
  }
1047
1047
  .block-editor-block-mover:not(.is-horizontal) .block-editor-block-mover__move-button-container > *::before {
1048
- height: 100%;
1049
- width: 100%;
1048
+ height: calc(100% - 4px);
1049
+ width: calc(100% - 4px);
1050
1050
  }
1051
1051
  .block-editor-block-mover:not(.is-horizontal) .block-editor-block-mover__move-button-container .block-editor-block-mover-button.is-up-button svg {
1052
1052
  top: 5px;
@@ -1066,9 +1066,6 @@
1066
1066
  padding-left: 0 !important;
1067
1067
  overflow: hidden;
1068
1068
  }
1069
- .block-editor-block-mover.is-horizontal .block-editor-block-mover__move-button-container > *::before {
1070
- height: 100%;
1071
- }
1072
1069
  .block-editor-block-mover.is-horizontal .block-editor-block-mover__move-button-container .block-editor-block-mover-button.is-up-button svg {
1073
1070
  right: 5px;
1074
1071
  }
@@ -1219,6 +1216,16 @@
1219
1216
  display: none;
1220
1217
  }
1221
1218
 
1219
+ .block-editor-block-preview__container::after {
1220
+ content: "";
1221
+ position: absolute;
1222
+ top: 0;
1223
+ right: 0;
1224
+ left: 0;
1225
+ bottom: 0;
1226
+ z-index: 1;
1227
+ }
1228
+
1222
1229
  .block-editor-block-settings-menu__popover .components-dropdown-menu__menu {
1223
1230
  padding: 0;
1224
1231
  }
@@ -1768,9 +1775,19 @@
1768
1775
  bottom: 0;
1769
1776
  right: 0;
1770
1777
  pointer-events: none;
1771
- border: 1px dashed currentColor;
1772
1778
  border-radius: 2px;
1773
1779
  }
1780
+ .is-layout-constrained.block-editor-block-list__block:not(.is-selected) > .block-list-appender:only-child::after::before, .is-layout-flow.block-editor-block-list__block:not(.is-selected) > .block-list-appender:only-child::after::before {
1781
+ content: "";
1782
+ position: absolute;
1783
+ top: 0;
1784
+ left: 0;
1785
+ bottom: 0;
1786
+ right: 0;
1787
+ pointer-events: none;
1788
+ background: currentColor;
1789
+ opacity: 0.1;
1790
+ }
1774
1791
  .is-layout-constrained.block-editor-block-list__block:not(.is-selected) > .block-list-appender:only-child .block-editor-inserter, .is-layout-flow.block-editor-block-list__block:not(.is-selected) > .block-list-appender:only-child .block-editor-inserter {
1775
1792
  visibility: hidden;
1776
1793
  }
@@ -3640,6 +3657,7 @@ figcaption.block-editor-rich-text__editable [data-rich-text-placeholder]::before
3640
3657
  width: 100%;
3641
3658
  }
3642
3659
  .block-editor-warning .block-editor-warning__actions {
3660
+ align-items: center;
3643
3661
  display: flex;
3644
3662
  margin-top: 1em;
3645
3663
  }
@@ -1045,8 +1045,8 @@
1045
1045
  min-width: 0 !important;
1046
1046
  }
1047
1047
  .block-editor-block-mover:not(.is-horizontal) .block-editor-block-mover__move-button-container > *::before {
1048
- height: 100%;
1049
- width: 100%;
1048
+ height: calc(100% - 4px);
1049
+ width: calc(100% - 4px);
1050
1050
  }
1051
1051
  .block-editor-block-mover:not(.is-horizontal) .block-editor-block-mover__move-button-container .block-editor-block-mover-button.is-up-button svg {
1052
1052
  top: 5px;
@@ -1066,9 +1066,6 @@
1066
1066
  padding-right: 0 !important;
1067
1067
  overflow: hidden;
1068
1068
  }
1069
- .block-editor-block-mover.is-horizontal .block-editor-block-mover__move-button-container > *::before {
1070
- height: 100%;
1071
- }
1072
1069
  .block-editor-block-mover.is-horizontal .block-editor-block-mover__move-button-container .block-editor-block-mover-button.is-up-button svg {
1073
1070
  left: 5px;
1074
1071
  }
@@ -1219,6 +1216,16 @@
1219
1216
  display: none;
1220
1217
  }
1221
1218
 
1219
+ .block-editor-block-preview__container::after {
1220
+ content: "";
1221
+ position: absolute;
1222
+ top: 0;
1223
+ left: 0;
1224
+ right: 0;
1225
+ bottom: 0;
1226
+ z-index: 1;
1227
+ }
1228
+
1222
1229
  .block-editor-block-settings-menu__popover .components-dropdown-menu__menu {
1223
1230
  padding: 0;
1224
1231
  }
@@ -1768,9 +1775,19 @@
1768
1775
  bottom: 0;
1769
1776
  left: 0;
1770
1777
  pointer-events: none;
1771
- border: 1px dashed currentColor;
1772
1778
  border-radius: 2px;
1773
1779
  }
1780
+ .is-layout-constrained.block-editor-block-list__block:not(.is-selected) > .block-list-appender:only-child::after::before, .is-layout-flow.block-editor-block-list__block:not(.is-selected) > .block-list-appender:only-child::after::before {
1781
+ content: "";
1782
+ position: absolute;
1783
+ top: 0;
1784
+ right: 0;
1785
+ bottom: 0;
1786
+ left: 0;
1787
+ pointer-events: none;
1788
+ background: currentColor;
1789
+ opacity: 0.1;
1790
+ }
1774
1791
  .is-layout-constrained.block-editor-block-list__block:not(.is-selected) > .block-list-appender:only-child .block-editor-inserter, .is-layout-flow.block-editor-block-list__block:not(.is-selected) > .block-list-appender:only-child .block-editor-inserter {
1775
1792
  visibility: hidden;
1776
1793
  }
@@ -3640,6 +3657,7 @@ figcaption.block-editor-rich-text__editable [data-rich-text-placeholder]::before
3640
3657
  width: 100%;
3641
3658
  }
3642
3659
  .block-editor-warning .block-editor-warning__actions {
3660
+ align-items: center;
3643
3661
  display: flex;
3644
3662
  margin-top: 1em;
3645
3663
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/block-editor",
3
- "version": "10.0.2",
3
+ "version": "10.1.1-next.4d3b314fd5.0",
4
4
  "description": "Generic block editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -33,32 +33,32 @@
33
33
  "dependencies": {
34
34
  "@babel/runtime": "^7.16.0",
35
35
  "@react-spring/web": "^9.4.5",
36
- "@wordpress/a11y": "^3.17.1",
37
- "@wordpress/api-fetch": "^6.14.1",
38
- "@wordpress/blob": "^3.17.1",
39
- "@wordpress/blocks": "^11.16.2",
40
- "@wordpress/components": "^21.0.2",
41
- "@wordpress/compose": "^5.15.2",
42
- "@wordpress/data": "^7.1.2",
43
- "@wordpress/date": "^4.17.1",
44
- "@wordpress/deprecated": "^3.17.1",
45
- "@wordpress/dom": "^3.17.2",
46
- "@wordpress/element": "^4.15.1",
47
- "@wordpress/hooks": "^3.17.1",
48
- "@wordpress/html-entities": "^3.17.1",
49
- "@wordpress/i18n": "^4.17.1",
50
- "@wordpress/icons": "^9.8.1",
51
- "@wordpress/is-shallow-equal": "^4.17.1",
52
- "@wordpress/keyboard-shortcuts": "^3.15.2",
53
- "@wordpress/keycodes": "^3.17.1",
54
- "@wordpress/notices": "^3.17.2",
55
- "@wordpress/rich-text": "^5.15.2",
56
- "@wordpress/shortcode": "^3.17.1",
57
- "@wordpress/style-engine": "^1.0.1",
58
- "@wordpress/token-list": "^2.17.1",
59
- "@wordpress/url": "^3.18.1",
60
- "@wordpress/warning": "^2.17.1",
61
- "@wordpress/wordcount": "^3.17.1",
36
+ "@wordpress/a11y": "^3.18.1-next.4d3b314fd5.0",
37
+ "@wordpress/api-fetch": "^6.15.1-next.4d3b314fd5.0",
38
+ "@wordpress/blob": "^3.18.1-next.4d3b314fd5.0",
39
+ "@wordpress/blocks": "^11.18.1-next.4d3b314fd5.0",
40
+ "@wordpress/components": "^21.1.2-next.4d3b314fd5.0",
41
+ "@wordpress/compose": "^5.16.1-next.4d3b314fd5.0",
42
+ "@wordpress/data": "^7.2.1-next.4d3b314fd5.0",
43
+ "@wordpress/date": "^4.18.1-next.4d3b314fd5.0",
44
+ "@wordpress/deprecated": "^3.18.1-next.4d3b314fd5.0",
45
+ "@wordpress/dom": "^3.18.1-next.4d3b314fd5.0",
46
+ "@wordpress/element": "^4.16.1-next.4d3b314fd5.0",
47
+ "@wordpress/hooks": "^3.18.1-next.4d3b314fd5.0",
48
+ "@wordpress/html-entities": "^3.18.1-next.4d3b314fd5.0",
49
+ "@wordpress/i18n": "^4.18.1-next.4d3b314fd5.0",
50
+ "@wordpress/icons": "^9.9.1-next.4d3b314fd5.0",
51
+ "@wordpress/is-shallow-equal": "^4.18.1-next.4d3b314fd5.0",
52
+ "@wordpress/keyboard-shortcuts": "^3.16.1-next.4d3b314fd5.0",
53
+ "@wordpress/keycodes": "^3.18.1-next.4d3b314fd5.0",
54
+ "@wordpress/notices": "^3.18.1-next.4d3b314fd5.0",
55
+ "@wordpress/rich-text": "^5.16.1-next.4d3b314fd5.0",
56
+ "@wordpress/shortcode": "^3.18.1-next.4d3b314fd5.0",
57
+ "@wordpress/style-engine": "^1.1.1-next.4d3b314fd5.0",
58
+ "@wordpress/token-list": "^2.18.1-next.4d3b314fd5.0",
59
+ "@wordpress/url": "^3.19.1-next.4d3b314fd5.0",
60
+ "@wordpress/warning": "^2.18.1-next.4d3b314fd5.0",
61
+ "@wordpress/wordcount": "^3.18.1-next.4d3b314fd5.0",
62
62
  "change-case": "^4.1.2",
63
63
  "classnames": "^2.3.1",
64
64
  "colord": "^2.7.0",
@@ -67,7 +67,7 @@
67
67
  "inherits": "^2.0.3",
68
68
  "lodash": "^4.17.21",
69
69
  "react-autosize-textarea": "^7.1.0",
70
- "react-easy-crop": "^3.0.0",
70
+ "react-easy-crop": "^4.5.1",
71
71
  "rememo": "^4.0.0",
72
72
  "remove-accents": "^0.4.2",
73
73
  "traverse": "^0.6.6"
@@ -79,5 +79,5 @@
79
79
  "publishConfig": {
80
80
  "access": "public"
81
81
  },
82
- "gitHead": "f6021282457317c7e12dcc3a3f02c9ac28e16a30"
82
+ "gitHead": "25054766423cb49d959eb656c2533530073ff5c2"
83
83
  }
@@ -1,11 +1,17 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { shallow } from 'enzyme';
4
+ import { render, screen } from '@testing-library/react';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
+ import {
10
+ registerBlockType,
11
+ unregisterBlockType,
12
+ getBlockTypes,
13
+ } from '@wordpress/blocks';
14
+ import { SlotFillProvider, ToolbarGroup } from '@wordpress/components';
9
15
  import { alignCenter, alignLeft, alignRight } from '@wordpress/icons';
10
16
 
11
17
  /**
@@ -33,15 +39,85 @@ describe( 'BlockControls', () => {
33
39
  },
34
40
  ];
35
41
 
42
+ beforeEach( () => {
43
+ const edit = ( { children } ) => <>{ children }</>;
44
+
45
+ registerBlockType( 'core/test-block', {
46
+ save: () => {},
47
+ category: 'text',
48
+ title: 'block title',
49
+ edit,
50
+ } );
51
+ } );
52
+
53
+ afterEach( () => {
54
+ getBlockTypes().forEach( ( block ) => {
55
+ unregisterBlockType( block.name );
56
+ } );
57
+ } );
58
+
36
59
  it( 'should render a dynamic toolbar of controls', () => {
37
- const wrapper = shallow(
38
- <BlockEdit isSelected>
39
- <BlockControls controls={ controls }>
40
- <p>Child</p>
41
- </BlockControls>
42
- </BlockEdit>
60
+ render(
61
+ <SlotFillProvider>
62
+ <BlockEdit name="core/test-block" isSelected>
63
+ <BlockControls controls={ controls }>
64
+ <p>Child</p>
65
+ </BlockControls>
66
+ </BlockEdit>
67
+ <BlockControls.Slot />
68
+ </SlotFillProvider>
43
69
  );
44
70
 
45
- expect( wrapper ).toMatchSnapshot();
71
+ expect(
72
+ screen.getAllByRole( 'button', { name: /^Align [\w]+/ } )
73
+ ).toHaveLength( controls.length );
74
+
75
+ controls.forEach( ( { title, align } ) => {
76
+ const control = screen.getByRole( 'button', {
77
+ name: title,
78
+ } );
79
+ expect( control ).toBeVisible();
80
+ expect( control ).toHaveAttribute( 'align', align );
81
+ } );
82
+ } );
83
+
84
+ it( 'should render its children', () => {
85
+ render(
86
+ <SlotFillProvider>
87
+ <BlockEdit name="core/test-block" isSelected>
88
+ <BlockControls controls={ controls }>
89
+ <p>Child</p>
90
+ </BlockControls>
91
+ </BlockEdit>
92
+ <BlockControls.Slot />
93
+ </SlotFillProvider>
94
+ );
95
+
96
+ expect( screen.getByText( 'Child' ) ).toBeVisible();
97
+ } );
98
+
99
+ it( 'should a dynamic toolbar when passed as children', () => {
100
+ render(
101
+ <SlotFillProvider>
102
+ <BlockEdit name="core/test-block" isSelected>
103
+ <BlockControls>
104
+ <ToolbarGroup controls={ controls } />
105
+ </BlockControls>
106
+ </BlockEdit>
107
+ <BlockControls.Slot />
108
+ </SlotFillProvider>
109
+ );
110
+
111
+ expect(
112
+ screen.getAllByRole( 'button', { name: /^Align [\w]+/ } )
113
+ ).toHaveLength( controls.length );
114
+
115
+ controls.forEach( ( { title, align } ) => {
116
+ const control = screen.getByRole( 'button', {
117
+ name: title,
118
+ } );
119
+ expect( control ).toBeVisible();
120
+ expect( control ).toHaveAttribute( 'align', align );
121
+ } );
46
122
  } );
47
123
  } );
@@ -52,7 +52,7 @@ const BlockDraggable = ( {
52
52
  }, [] );
53
53
 
54
54
  if ( ! isDraggable ) {
55
- return children( { isDraggable: false } );
55
+ return children( { draggable: false } );
56
56
  }
57
57
 
58
58
  const transferData = {
@@ -29,15 +29,6 @@ import {
29
29
  getDraggableChip,
30
30
  } from './helpers';
31
31
 
32
- // Mock throttle to allow updating the dragging position on every "onDragOver" event.
33
- jest.mock( 'lodash', () => ( {
34
- ...jest.requireActual( 'lodash' ),
35
- throttle: ( fn ) => {
36
- fn.cancel = jest.fn();
37
- return fn;
38
- },
39
- } ) );
40
-
41
32
  beforeAll( () => {
42
33
  // Register all core blocks
43
34
  registerCoreBlocks();
@@ -6,9 +6,23 @@ import classnames from 'classnames';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- import { AsyncModeProvider, useSelect, useDispatch } from '@wordpress/data';
10
- import { useViewportMatch, useMergeRefs } from '@wordpress/compose';
11
- import { createContext, useState, useMemo } from '@wordpress/element';
9
+ import {
10
+ AsyncModeProvider,
11
+ useSelect,
12
+ useDispatch,
13
+ useRegistry,
14
+ } from '@wordpress/data';
15
+ import {
16
+ useViewportMatch,
17
+ useMergeRefs,
18
+ useDebounce,
19
+ } from '@wordpress/compose';
20
+ import {
21
+ createContext,
22
+ useState,
23
+ useMemo,
24
+ useCallback,
25
+ } from '@wordpress/element';
12
26
 
13
27
  /**
14
28
  * Internal dependencies
@@ -30,6 +44,7 @@ import {
30
44
  const elementContext = createContext();
31
45
 
32
46
  export const IntersectionObserver = createContext();
47
+ const pendingBlockVisibilityUpdatesPerRegistry = new WeakMap();
33
48
 
34
49
  function Root( { className, ...settings } ) {
35
50
  const [ element, setElement ] = useState();
@@ -47,7 +62,24 @@ function Root( { className, ...settings } ) {
47
62
  },
48
63
  []
49
64
  );
65
+ const registry = useRegistry();
50
66
  const { setBlockVisibility } = useDispatch( blockEditorStore );
67
+
68
+ const delayedBlockVisibilityUpdates = useDebounce(
69
+ useCallback( () => {
70
+ const updates = {};
71
+ pendingBlockVisibilityUpdatesPerRegistry
72
+ .get( registry )
73
+ .forEach( ( [ id, isIntersecting ] ) => {
74
+ updates[ id ] = isIntersecting;
75
+ } );
76
+ setBlockVisibility( updates );
77
+ }, [ registry ] ),
78
+ 300,
79
+ {
80
+ trailing: true,
81
+ }
82
+ );
51
83
  const intersectionObserver = useMemo( () => {
52
84
  const { IntersectionObserver: Observer } = window;
53
85
 
@@ -56,12 +88,16 @@ function Root( { className, ...settings } ) {
56
88
  }
57
89
 
58
90
  return new Observer( ( entries ) => {
59
- const updates = {};
91
+ if ( ! pendingBlockVisibilityUpdatesPerRegistry.get( registry ) ) {
92
+ pendingBlockVisibilityUpdatesPerRegistry.set( registry, [] );
93
+ }
60
94
  for ( const entry of entries ) {
61
95
  const clientId = entry.target.getAttribute( 'data-block' );
62
- updates[ clientId ] = entry.isIntersecting;
96
+ pendingBlockVisibilityUpdatesPerRegistry
97
+ .get( registry )
98
+ .push( [ clientId, entry.isIntersecting ] );
63
99
  }
64
- setBlockVisibility( updates );
100
+ delayedBlockVisibilityUpdates();
65
101
  } );
66
102
  }, [] );
67
103
  const innerBlocksProps = useInnerBlocksProps(
@@ -11,6 +11,7 @@ import { __, sprintf } from '@wordpress/i18n';
11
11
  import {
12
12
  __unstableGetBlockProps as getBlockProps,
13
13
  getBlockType,
14
+ store as blocksStore,
14
15
  } from '@wordpress/blocks';
15
16
  import { useMergeRefs, useDisabled } from '@wordpress/compose';
16
17
  import { useSelect } from '@wordpress/data';
@@ -77,6 +78,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
77
78
  } = useSelect(
78
79
  ( select ) => {
79
80
  const {
81
+ getBlockAttributes,
80
82
  getBlockIndex,
81
83
  getBlockMode,
82
84
  getBlockName,
@@ -87,19 +89,22 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
87
89
  isAncestorMultiSelected,
88
90
  isFirstMultiSelectedBlock,
89
91
  } = select( blockEditorStore );
92
+ const { getActiveBlockVariation } = select( blocksStore );
90
93
  const isSelected = isBlockSelected( clientId );
91
94
  const isPartOfMultiSelection =
92
95
  isBlockMultiSelected( clientId ) ||
93
96
  isAncestorMultiSelected( clientId );
94
97
  const blockName = getBlockName( clientId );
95
98
  const blockType = getBlockType( blockName );
99
+ const attributes = getBlockAttributes( clientId );
100
+ const match = getActiveBlockVariation( blockName, attributes );
96
101
 
97
102
  return {
98
103
  index: getBlockIndex( clientId ),
99
104
  mode: getBlockMode( clientId ),
100
105
  name: blockName,
101
106
  blockApiVersion: blockType?.apiVersion || 1,
102
- blockTitle: blockType?.title,
107
+ blockTitle: match?.title || blockType?.title,
103
108
  isPartOfSelection: isSelected || isPartOfMultiSelection,
104
109
  adjustScrolling:
105
110
  isSelected || isFirstMultiSelectedBlock( clientId ),
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useRefEffect } from '@wordpress/compose';
5
-
4
+ import { useRefEffect, useDebounce } from '@wordpress/compose';
6
5
  import { useSelect, useDispatch } from '@wordpress/data';
7
6
  import { useContext } from '@wordpress/element';
8
7
 
@@ -33,6 +32,10 @@ export function useInBetweenInserter() {
33
32
  const { showInsertionPoint, hideInsertionPoint } =
34
33
  useDispatch( blockEditorStore );
35
34
 
35
+ const delayedShowInsertionPoint = useDebounce( showInsertionPoint, 500, {
36
+ trailing: true,
37
+ } );
38
+
36
39
  return useRefEffect(
37
40
  ( node ) => {
38
41
  if ( isInBetweenInserterDisabled ) {
@@ -53,6 +56,7 @@ export function useInBetweenInserter() {
53
56
  'block-editor-block-list__layout'
54
57
  )
55
58
  ) {
59
+ delayedShowInsertionPoint.cancel();
56
60
  if ( isBlockInsertionPointVisible() ) {
57
61
  hideInsertionPoint();
58
62
  }
@@ -79,19 +83,19 @@ export function useInBetweenInserter() {
79
83
  const orientation =
80
84
  getBlockListSettings( rootClientId )?.orientation ||
81
85
  'vertical';
82
- const rect = event.target.getBoundingClientRect();
83
- const offsetTop = event.clientY - rect.top;
84
- const offsetLeft = event.clientX - rect.left;
86
+ const offsetTop = event.clientY;
87
+ const offsetLeft = event.clientX;
85
88
 
86
89
  const children = Array.from( event.target.children );
87
90
  let element = children.find( ( blockEl ) => {
91
+ const blockElRect = blockEl.getBoundingClientRect();
88
92
  return (
89
93
  ( blockEl.classList.contains( 'wp-block' ) &&
90
94
  orientation === 'vertical' &&
91
- blockEl.offsetTop > offsetTop ) ||
95
+ blockElRect.top > offsetTop ) ||
92
96
  ( blockEl.classList.contains( 'wp-block' ) &&
93
97
  orientation === 'horizontal' &&
94
- blockEl.offsetLeft > offsetLeft )
98
+ blockElRect.left > offsetLeft )
95
99
  );
96
100
  } );
97
101
 
@@ -134,6 +138,7 @@ export function useInBetweenInserter() {
134
138
  ( event.clientX > elementRect.right ||
135
139
  event.clientX < elementRect.left ) )
136
140
  ) {
141
+ delayedShowInsertionPoint.cancel();
137
142
  if ( isBlockInsertionPointVisible() ) {
138
143
  hideInsertionPoint();
139
144
  }
@@ -145,13 +150,14 @@ export function useInBetweenInserter() {
145
150
  // Don't show the in-between inserter before the first block in
146
151
  // the list (preserves the original behaviour).
147
152
  if ( index === 0 ) {
153
+ delayedShowInsertionPoint.cancel();
148
154
  if ( isBlockInsertionPointVisible() ) {
149
155
  hideInsertionPoint();
150
156
  }
151
157
  return;
152
158
  }
153
159
 
154
- showInsertionPoint( rootClientId, index, {
160
+ delayedShowInsertionPoint( rootClientId, index, {
155
161
  __unstableWithInserter: true,
156
162
  } );
157
163
  }
@@ -15,8 +15,8 @@
15
15
 
16
16
  // Focus style.
17
17
  &::before {
18
- height: 100%;
19
- width: 100%;
18
+ height: calc(100% - 4px);
19
+ width: calc(100% - 4px);
20
20
  }
21
21
  }
22
22
 
@@ -40,11 +40,6 @@
40
40
  padding-left: 0 !important;
41
41
  padding-right: 0 !important;
42
42
  overflow: hidden;
43
-
44
- // Focus style.
45
- &::before {
46
- height: 100%;
47
- }
48
43
  }
49
44
 
50
45
  .block-editor-block-mover-button.is-up-button svg {
@@ -23,6 +23,8 @@ import { store as blockEditorStore } from '../../store';
23
23
  import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs';
24
24
  import usePopoverScroll from './use-popover-scroll';
25
25
 
26
+ const MAX_POPOVER_RECOMPUTE_COUNTER = Number.MAX_SAFE_INTEGER;
27
+
26
28
  export const InsertionPointOpenRef = createContext();
27
29
 
28
30
  function BlockPopoverInbetween( {
@@ -34,8 +36,9 @@ function BlockPopoverInbetween( {
34
36
  ...props
35
37
  } ) {
36
38
  // This is a temporary hack to get the inbetween inserter to recompute properly.
37
- const [ positionRecompute, forceRecompute ] = useReducer(
38
- ( s ) => s + 1,
39
+ const [ popoverRecomputeCounter, forcePopoverRecompute ] = useReducer(
40
+ // Module is there to make sure that the counter doesn't overflow.
41
+ ( s ) => ( s + 1 ) % MAX_POPOVER_RECOMPUTE_COUNTER,
39
42
  0
40
43
  );
41
44
 
@@ -66,7 +69,14 @@ function BlockPopoverInbetween( {
66
69
  const nextElement = useBlockElement( nextClientId );
67
70
  const isVertical = orientation === 'vertical';
68
71
  const style = useMemo( () => {
69
- if ( ( ! previousElement && ! nextElement ) || ! isVisible ) {
72
+ if (
73
+ // popoverRecomputeCounter is by definition always equal or greater than 0.
74
+ // This check is only there to satisfy the correctness of the
75
+ // exhaustive-deps rule for the `useMemo` hook.
76
+ popoverRecomputeCounter < 0 ||
77
+ ( ! previousElement && ! nextElement ) ||
78
+ ! isVisible
79
+ ) {
70
80
  return {};
71
81
  }
72
82
 
@@ -102,12 +112,19 @@ function BlockPopoverInbetween( {
102
112
  previousElement,
103
113
  nextElement,
104
114
  isVertical,
105
- positionRecompute,
115
+ popoverRecomputeCounter,
106
116
  isVisible,
107
117
  ] );
108
118
 
109
119
  const popoverAnchor = useMemo( () => {
110
- if ( ( ! previousElement && ! nextElement ) || ! isVisible ) {
120
+ if (
121
+ // popoverRecomputeCounter is by definition always equal or greater than 0.
122
+ // This check is only there to satisfy the correctness of the
123
+ // exhaustive-deps rule for the `useMemo` hook.
124
+ popoverRecomputeCounter < 0 ||
125
+ ( ! previousElement && ! nextElement ) ||
126
+ ! isVisible
127
+ ) {
111
128
  return undefined;
112
129
  }
113
130
 
@@ -161,7 +178,7 @@ function BlockPopoverInbetween( {
161
178
  }, [
162
179
  previousElement,
163
180
  nextElement,
164
- positionRecompute,
181
+ popoverRecomputeCounter,
165
182
  isVertical,
166
183
  isVisible,
167
184
  ] );
@@ -169,11 +186,18 @@ function BlockPopoverInbetween( {
169
186
  const popoverScrollRef = usePopoverScroll( __unstableContentRef );
170
187
 
171
188
  // This is only needed for a smooth transition when moving blocks.
189
+ // When blocks are moved up/down, their position can be set by
190
+ // updating the `transform` property manually (i.e. without using CSS
191
+ // transitions or animations). The animation, which can also scroll the block
192
+ // editor, can sometimes cause the position of the Popover to get out of sync.
193
+ // A MutationObserver is therefore used to make sure that changes to the
194
+ // selectedElement's attribute (i.e. `transform`) can be tracked and used to
195
+ // trigger the Popover to rerender.
172
196
  useLayoutEffect( () => {
173
197
  if ( ! previousElement ) {
174
198
  return;
175
199
  }
176
- const observer = new window.MutationObserver( forceRecompute );
200
+ const observer = new window.MutationObserver( forcePopoverRecompute );
177
201
  observer.observe( previousElement, { attributes: true } );
178
202
 
179
203
  return () => {
@@ -185,7 +209,7 @@ function BlockPopoverInbetween( {
185
209
  if ( ! nextElement ) {
186
210
  return;
187
211
  }
188
- const observer = new window.MutationObserver( forceRecompute );
212
+ const observer = new window.MutationObserver( forcePopoverRecompute );
189
213
  observer.observe( nextElement, { attributes: true } );
190
214
 
191
215
  return () => {
@@ -199,12 +223,12 @@ function BlockPopoverInbetween( {
199
223
  }
200
224
  previousElement.ownerDocument.defaultView.addEventListener(
201
225
  'resize',
202
- forceRecompute
226
+ forcePopoverRecompute
203
227
  );
204
228
  return () => {
205
229
  previousElement.ownerDocument.defaultView.removeEventListener(
206
230
  'resize',
207
- forceRecompute
231
+ forcePopoverRecompute
208
232
  );
209
233
  };
210
234
  }, [ previousElement ] );