@wordpress/block-editor 7.0.3 → 7.0.4

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 (248) hide show
  1. package/build/components/block-actions/index.js +6 -5
  2. package/build/components/block-actions/index.js.map +1 -1
  3. package/build/components/block-alignment-control/use-available-alignments.js +17 -4
  4. package/build/components/block-alignment-control/use-available-alignments.js.map +1 -1
  5. package/build/components/block-inspector/index.js +1 -1
  6. package/build/components/block-inspector/index.js.map +1 -1
  7. package/build/components/block-list/block-html.js +5 -0
  8. package/build/components/block-list/block-html.js.map +1 -1
  9. package/build/components/block-list/block.native.js +2 -2
  10. package/build/components/block-list/block.native.js.map +1 -1
  11. package/build/components/block-list-appender/index.js +9 -1
  12. package/build/components/block-list-appender/index.js.map +1 -1
  13. package/build/components/block-settings-menu/block-settings-dropdown.js +2 -2
  14. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  15. package/build/components/block-settings-menu-controls/index.js +10 -3
  16. package/build/components/block-settings-menu-controls/index.js.map +1 -1
  17. package/build/components/block-switcher/block-styles-menu.js +1 -1
  18. package/build/components/block-switcher/block-styles-menu.js.map +1 -1
  19. package/build/components/block-tools/index.js +4 -1
  20. package/build/components/block-tools/index.js.map +1 -1
  21. package/build/components/block-tools/insertion-point.js +96 -7
  22. package/build/components/block-tools/insertion-point.js.map +1 -1
  23. package/build/components/border-radius-control/index.js.map +1 -1
  24. package/build/components/border-radius-control/utils.js +17 -8
  25. package/build/components/border-radius-control/utils.js.map +1 -1
  26. package/build/components/colors-gradients/control.js +17 -13
  27. package/build/components/colors-gradients/control.js.map +1 -1
  28. package/build/components/copy-handler/index.js +3 -3
  29. package/build/components/copy-handler/index.js.map +1 -1
  30. package/build/components/default-block-appender/index.js +2 -2
  31. package/build/components/default-block-appender/index.js.map +1 -1
  32. package/build/components/font-appearance-control/index.js +3 -5
  33. package/build/components/font-appearance-control/index.js.map +1 -1
  34. package/build/components/index.js +0 -18
  35. package/build/components/index.js.map +1 -1
  36. package/build/components/inserter/block-patterns-tab.js +11 -1
  37. package/build/components/inserter/block-patterns-tab.js.map +1 -1
  38. package/build/components/inserter/hooks/use-clipboard-block.native.js +5 -4
  39. package/build/components/inserter/hooks/use-clipboard-block.native.js.map +1 -1
  40. package/build/components/inserter/preview-panel.js +1 -1
  41. package/build/components/inserter/preview-panel.js.map +1 -1
  42. package/build/components/inspector-controls/block-support-slot-container.js +28 -0
  43. package/build/components/inspector-controls/block-support-slot-container.js.map +1 -0
  44. package/build/components/inspector-controls/block-support-tools-panel.js +7 -4
  45. package/build/components/inspector-controls/block-support-tools-panel.js.map +1 -1
  46. package/build/components/inspector-controls/fill.js +16 -1
  47. package/build/components/inspector-controls/fill.js.map +1 -1
  48. package/build/components/inspector-controls/slot.js +5 -2
  49. package/build/components/inspector-controls/slot.js.map +1 -1
  50. package/build/components/list-view/block-contents.js +1 -20
  51. package/build/components/list-view/block-contents.js.map +1 -1
  52. package/build/components/list-view/block.js +5 -36
  53. package/build/components/list-view/block.js.map +1 -1
  54. package/build/components/list-view/list-item.js +3 -2
  55. package/build/components/list-view/list-item.js.map +1 -1
  56. package/build/components/media-placeholder/index.js +26 -17
  57. package/build/components/media-placeholder/index.js.map +1 -1
  58. package/build/components/media-replace-flow/index.js +3 -2
  59. package/build/components/media-replace-flow/index.js.map +1 -1
  60. package/build/components/plain-text/index.native.js +30 -1
  61. package/build/components/plain-text/index.native.js.map +1 -1
  62. package/build/components/rich-text/embed-handler-picker.native.js +65 -0
  63. package/build/components/rich-text/embed-handler-picker.native.js.map +1 -0
  64. package/build/components/rich-text/index.js +5 -1
  65. package/build/components/rich-text/index.js.map +1 -1
  66. package/build/components/rich-text/index.native.js +41 -2
  67. package/build/components/rich-text/index.native.js.map +1 -1
  68. package/build/components/rich-text/use-paste-handler.js +28 -9
  69. package/build/components/rich-text/use-paste-handler.js.map +1 -1
  70. package/build/components/rich-text/utils.js +22 -0
  71. package/build/components/rich-text/utils.js.map +1 -1
  72. package/build/hooks/align.js +10 -7
  73. package/build/hooks/align.js.map +1 -1
  74. package/build/hooks/anchor.js +1 -1
  75. package/build/hooks/anchor.js.map +1 -1
  76. package/build/hooks/font-family.js +93 -23
  77. package/build/hooks/font-family.js.map +1 -1
  78. package/build/hooks/style.js +6 -3
  79. package/build/hooks/style.js.map +1 -1
  80. package/build/layouts/flow.js +4 -1
  81. package/build/layouts/flow.js.map +1 -1
  82. package/build/store/reducer.js +11 -1
  83. package/build/store/reducer.js.map +1 -1
  84. package/build/store/selectors.js +1 -3
  85. package/build/store/selectors.js.map +1 -1
  86. package/build/utils/transform-styles/transforms/wrap.js +16 -0
  87. package/build/utils/transform-styles/transforms/wrap.js.map +1 -1
  88. package/build-module/components/block-actions/index.js +6 -5
  89. package/build-module/components/block-actions/index.js.map +1 -1
  90. package/build-module/components/block-alignment-control/use-available-alignments.js +17 -4
  91. package/build-module/components/block-alignment-control/use-available-alignments.js.map +1 -1
  92. package/build-module/components/block-inspector/index.js +1 -1
  93. package/build-module/components/block-inspector/index.js.map +1 -1
  94. package/build-module/components/block-list/block-html.js +5 -0
  95. package/build-module/components/block-list/block-html.js.map +1 -1
  96. package/build-module/components/block-list/block.native.js +2 -2
  97. package/build-module/components/block-list/block.native.js.map +1 -1
  98. package/build-module/components/block-list-appender/index.js +9 -1
  99. package/build-module/components/block-list-appender/index.js.map +1 -1
  100. package/build-module/components/block-settings-menu/block-settings-dropdown.js +2 -2
  101. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  102. package/build-module/components/block-settings-menu-controls/index.js +10 -3
  103. package/build-module/components/block-settings-menu-controls/index.js.map +1 -1
  104. package/build-module/components/block-switcher/block-styles-menu.js +1 -1
  105. package/build-module/components/block-switcher/block-styles-menu.js.map +1 -1
  106. package/build-module/components/block-tools/index.js +4 -1
  107. package/build-module/components/block-tools/index.js.map +1 -1
  108. package/build-module/components/block-tools/insertion-point.js +96 -8
  109. package/build-module/components/block-tools/insertion-point.js.map +1 -1
  110. package/build-module/components/border-radius-control/index.js.map +1 -1
  111. package/build-module/components/border-radius-control/utils.js +16 -9
  112. package/build-module/components/border-radius-control/utils.js.map +1 -1
  113. package/build-module/components/colors-gradients/control.js +18 -14
  114. package/build-module/components/colors-gradients/control.js.map +1 -1
  115. package/build-module/components/copy-handler/index.js +3 -3
  116. package/build-module/components/copy-handler/index.js.map +1 -1
  117. package/build-module/components/default-block-appender/index.js +2 -2
  118. package/build-module/components/default-block-appender/index.js.map +1 -1
  119. package/build-module/components/font-appearance-control/index.js +3 -5
  120. package/build-module/components/font-appearance-control/index.js.map +1 -1
  121. package/build-module/components/index.js +0 -2
  122. package/build-module/components/index.js.map +1 -1
  123. package/build-module/components/inserter/block-patterns-tab.js +11 -1
  124. package/build-module/components/inserter/block-patterns-tab.js.map +1 -1
  125. package/build-module/components/inserter/hooks/use-clipboard-block.native.js +5 -4
  126. package/build-module/components/inserter/hooks/use-clipboard-block.native.js.map +1 -1
  127. package/build-module/components/inserter/preview-panel.js +1 -1
  128. package/build-module/components/inserter/preview-panel.js.map +1 -1
  129. package/build-module/components/inspector-controls/block-support-slot-container.js +18 -0
  130. package/build-module/components/inspector-controls/block-support-slot-container.js.map +1 -0
  131. package/build-module/components/inspector-controls/block-support-tools-panel.js +7 -4
  132. package/build-module/components/inspector-controls/block-support-tools-panel.js.map +1 -1
  133. package/build-module/components/inspector-controls/fill.js +16 -2
  134. package/build-module/components/inspector-controls/fill.js.map +1 -1
  135. package/build-module/components/inspector-controls/slot.js +4 -2
  136. package/build-module/components/inspector-controls/slot.js.map +1 -1
  137. package/build-module/components/list-view/block-contents.js +1 -18
  138. package/build-module/components/list-view/block-contents.js.map +1 -1
  139. package/build-module/components/list-view/block.js +7 -37
  140. package/build-module/components/list-view/block.js.map +1 -1
  141. package/build-module/components/list-view/list-item.js +3 -2
  142. package/build-module/components/list-view/list-item.js.map +1 -1
  143. package/build-module/components/media-placeholder/index.js +26 -17
  144. package/build-module/components/media-placeholder/index.js.map +1 -1
  145. package/build-module/components/media-replace-flow/index.js +3 -2
  146. package/build-module/components/media-replace-flow/index.js.map +1 -1
  147. package/build-module/components/plain-text/index.native.js +29 -2
  148. package/build-module/components/plain-text/index.native.js.map +1 -1
  149. package/build-module/components/rich-text/embed-handler-picker.native.js +53 -0
  150. package/build-module/components/rich-text/embed-handler-picker.native.js.map +1 -0
  151. package/build-module/components/rich-text/index.js +4 -1
  152. package/build-module/components/rich-text/index.js.map +1 -1
  153. package/build-module/components/rich-text/index.native.js +41 -3
  154. package/build-module/components/rich-text/index.native.js.map +1 -1
  155. package/build-module/components/rich-text/use-paste-handler.js +28 -9
  156. package/build-module/components/rich-text/use-paste-handler.js.map +1 -1
  157. package/build-module/components/rich-text/utils.js +20 -0
  158. package/build-module/components/rich-text/utils.js.map +1 -1
  159. package/build-module/hooks/align.js +10 -7
  160. package/build-module/hooks/align.js.map +1 -1
  161. package/build-module/hooks/anchor.js +1 -1
  162. package/build-module/hooks/anchor.js.map +1 -1
  163. package/build-module/hooks/font-family.js +91 -24
  164. package/build-module/hooks/font-family.js.map +1 -1
  165. package/build-module/hooks/style.js +6 -3
  166. package/build-module/hooks/style.js.map +1 -1
  167. package/build-module/layouts/flow.js +4 -1
  168. package/build-module/layouts/flow.js.map +1 -1
  169. package/build-module/store/reducer.js +11 -1
  170. package/build-module/store/reducer.js.map +1 -1
  171. package/build-module/store/selectors.js +2 -4
  172. package/build-module/store/selectors.js.map +1 -1
  173. package/build-module/utils/transform-styles/transforms/wrap.js +16 -0
  174. package/build-module/utils/transform-styles/transforms/wrap.js.map +1 -1
  175. package/build-style/style-rtl.css +52 -76
  176. package/build-style/style.css +52 -76
  177. package/package.json +14 -14
  178. package/src/components/block-actions/index.js +5 -5
  179. package/src/components/block-alignment-control/use-available-alignments.js +18 -3
  180. package/src/components/block-inspector/index.js +1 -1
  181. package/src/components/block-list/block-html.js +5 -0
  182. package/src/components/block-list/block.native.js +2 -2
  183. package/src/components/block-list-appender/index.js +8 -0
  184. package/src/components/block-preview/README.md +1 -1
  185. package/src/components/block-preview/style.scss +0 -17
  186. package/src/components/block-settings-menu/block-settings-dropdown.js +2 -2
  187. package/src/components/block-settings-menu-controls/index.js +9 -6
  188. package/src/components/block-switcher/block-styles-menu.js +1 -1
  189. package/src/components/block-tools/index.js +5 -2
  190. package/src/components/block-tools/insertion-point.js +97 -9
  191. package/src/components/block-tools/style.scss +4 -35
  192. package/src/components/border-radius-control/index.js +1 -0
  193. package/src/components/border-radius-control/test/utils.js +216 -0
  194. package/src/components/border-radius-control/utils.js +18 -10
  195. package/src/components/color-palette/test/__snapshots__/control.js.snap +103 -72
  196. package/src/components/colors-gradients/control.js +64 -61
  197. package/src/components/colors-gradients/style.scss +8 -5
  198. package/src/components/colors-gradients/test/control.js +43 -52
  199. package/src/components/copy-handler/index.js +1 -1
  200. package/src/components/default-block-appender/index.js +2 -2
  201. package/src/components/default-block-appender/test/__snapshots__/index.js.snap +3 -3
  202. package/src/components/font-appearance-control/index.js +12 -14
  203. package/src/components/font-appearance-control/style.scss +1 -1
  204. package/src/components/index.js +0 -2
  205. package/src/components/inserter/block-patterns-tab.js +11 -4
  206. package/src/components/inserter/hooks/use-clipboard-block.native.js +3 -2
  207. package/src/components/inserter/preview-panel.js +1 -1
  208. package/src/components/inserter/style.scss +1 -2
  209. package/src/components/inspector-controls/block-support-slot-container.js +10 -0
  210. package/src/components/inspector-controls/block-support-tools-panel.js +4 -2
  211. package/src/components/inspector-controls/fill.js +23 -2
  212. package/src/components/inspector-controls/slot.js +6 -1
  213. package/src/components/link-control/style.scss +9 -5
  214. package/src/components/list-view/block-contents.js +17 -38
  215. package/src/components/list-view/block.js +6 -51
  216. package/src/components/list-view/list-item.js +5 -4
  217. package/src/components/list-view/style.scss +56 -30
  218. package/src/components/media-placeholder/index.js +24 -17
  219. package/src/components/media-replace-flow/README.md +7 -0
  220. package/src/components/media-replace-flow/index.js +2 -0
  221. package/src/components/plain-text/index.native.js +26 -4
  222. package/src/components/rich-text/embed-handler-picker.native.js +67 -0
  223. package/src/components/rich-text/index.js +12 -8
  224. package/src/components/rich-text/index.native.js +35 -1
  225. package/src/components/rich-text/use-paste-handler.js +30 -12
  226. package/src/components/rich-text/utils.js +16 -0
  227. package/src/components/skip-to-selected-block/README.md +39 -0
  228. package/src/hooks/align.js +11 -7
  229. package/src/hooks/anchor.js +2 -2
  230. package/src/hooks/font-family.js +107 -27
  231. package/src/hooks/style.js +14 -8
  232. package/src/layouts/flow.js +4 -1
  233. package/src/store/reducer.js +17 -0
  234. package/src/store/selectors.js +2 -3
  235. package/src/store/test/reducer.js +22 -0
  236. package/src/utils/transform-styles/transforms/test/wrap.js +1 -1
  237. package/src/utils/transform-styles/transforms/wrap.js +16 -0
  238. package/tsconfig.tsbuildinfo +1 -1
  239. package/build/components/list-view/block-slot.js +0 -121
  240. package/build/components/list-view/block-slot.js.map +0 -1
  241. package/build/components/list-view/editor.js +0 -35
  242. package/build/components/list-view/editor.js.map +0 -1
  243. package/build-module/components/list-view/block-slot.js +0 -96
  244. package/build-module/components/list-view/block-slot.js.map +0 -1
  245. package/build-module/components/list-view/editor.js +0 -25
  246. package/build-module/components/list-view/editor.js.map +0 -1
  247. package/src/components/list-view/block-slot.js +0 -120
  248. package/src/components/list-view/editor.js +0 -29
@@ -16,7 +16,7 @@ const WIDE_CONTROLS = [ 'wide', 'full' ];
16
16
  export default function useAvailableAlignments( controls = DEFAULT_CONTROLS ) {
17
17
  // Always add the `none` option if not exists.
18
18
  if ( ! controls.includes( 'none' ) ) {
19
- controls.unshift( 'none' );
19
+ controls = [ 'none', ...controls ];
20
20
  }
21
21
  const { wideControlsEnabled = false, themeSupportsLayout } = useSelect(
22
22
  ( select ) => {
@@ -34,9 +34,15 @@ export default function useAvailableAlignments( controls = DEFAULT_CONTROLS ) {
34
34
  const layoutAlignments = layoutType.getAlignments( layout );
35
35
 
36
36
  if ( themeSupportsLayout ) {
37
- return layoutAlignments.filter( ( { name: alignmentName } ) =>
38
- controls.includes( alignmentName )
37
+ const alignments = layoutAlignments.filter(
38
+ ( { name: alignmentName } ) => controls.includes( alignmentName )
39
39
  );
40
+ // While we treat `none` as an alignment, we shouldn't return it if no
41
+ // other alignments exist.
42
+ if ( alignments.length === 1 && alignments[ 0 ].name === 'none' ) {
43
+ return [];
44
+ }
45
+ return alignments;
40
46
  }
41
47
 
42
48
  // Starting here, it's the fallback for themes not supporting the layout config.
@@ -54,5 +60,14 @@ export default function useAvailableAlignments( controls = DEFAULT_CONTROLS ) {
54
60
  )
55
61
  .map( ( enabledControl ) => ( { name: enabledControl } ) );
56
62
 
63
+ // While we treat `none` as an alignment, we shouldn't return it if no
64
+ // other alignments exist.
65
+ if (
66
+ enabledControls.length === 1 &&
67
+ enabledControls[ 0 ].name === 'none'
68
+ ) {
69
+ return [];
70
+ }
71
+
57
72
  return enabledControls;
58
73
  }
@@ -131,7 +131,7 @@ const BlockInspectorSingleBlock = ( {
131
131
  <InspectorControls.Slot bubblesVirtually={ bubblesVirtually } />
132
132
  <InspectorControls.Slot
133
133
  __experimentalGroup="dimensions"
134
- bubblesVirtually={ false }
134
+ bubblesVirtually={ bubblesVirtually }
135
135
  label={ __( 'Dimensions' ) }
136
136
  />
137
137
  <div>
@@ -30,6 +30,11 @@ function BlockHTML( { clientId } ) {
30
30
  const { updateBlock } = useDispatch( blockEditorStore );
31
31
  const onChange = () => {
32
32
  const blockType = getBlockType( block.name );
33
+
34
+ if ( ! blockType ) {
35
+ return;
36
+ }
37
+
33
38
  const attributes = getBlockAttributes(
34
39
  blockType,
35
40
  html,
@@ -321,8 +321,8 @@ export default compose( [
321
321
  const { name, attributes, isValid } = block || {};
322
322
 
323
323
  const blockType = getBlockType( name || 'core/missing' );
324
- const title = blockType.title;
325
- const icon = blockType.icon;
324
+ const title = blockType?.title;
325
+ const icon = blockType?.icon;
326
326
 
327
327
  const parents = getBlockParents( clientId, true );
328
328
  const parentId = parents[ 0 ] || '';
@@ -87,6 +87,14 @@ function BlockListAppender( {
87
87
  'block-list-appender wp-block',
88
88
  className
89
89
  ) }
90
+ // The appender exists to let you add the first Paragraph before
91
+ // any is inserted. To that end, this appender should visually be
92
+ // presented as a block. That means theme CSS should style it as if
93
+ // it were an empty paragraph block. That means a `wp-block` class to
94
+ // ensure the width is correct, and a [data-block] attribute to ensure
95
+ // the correct margin is applied, especially for classic themes which
96
+ // have commonly targeted that attribute for margins.
97
+ data-block
90
98
  >
91
99
  { appender }
92
100
  </TagName>
@@ -22,7 +22,7 @@ A block instance (object) or a blocks array you would like to render a preview.
22
22
  ### `viewportWidth`
23
23
 
24
24
  - **Type:** `Int`
25
- - **Default:** `700`
25
+ - **Default:** `1200`
26
26
 
27
27
  Width of the preview container in pixels. Controls at what size the blocks will be rendered inside the preview.
28
28
 
@@ -10,12 +10,6 @@
10
10
 
11
11
  overflow: hidden;
12
12
 
13
- // Overrides the default padding applied in editor styles otherwise preview centering break.
14
- &.editor-styles-wrapper {
15
- padding: 0;
16
- margin: 0;
17
- }
18
-
19
13
  .block-editor-block-preview__content {
20
14
  // This element receives inline styles for width, height, and transform-scale.
21
15
  // Those inline styles are calculated to fit a perfect thumbnail.
@@ -40,16 +34,5 @@
40
34
  .block-list-appender {
41
35
  display: none;
42
36
  }
43
-
44
- // Reset default editor padding
45
- .block-editor-block-list__layout.is-root-container {
46
- padding-left: 0;
47
- padding-right: 0;
48
-
49
- > .wp-block[data-align="full"] {
50
- margin-left: 0;
51
- margin-right: 0;
52
- }
53
- }
54
37
  }
55
38
  }
@@ -90,11 +90,11 @@ export function BlockSettingsDropdown( {
90
90
  { ( {
91
91
  canDuplicate,
92
92
  canInsertDefaultBlock,
93
+ canMove,
93
94
  canRemove,
94
95
  onDuplicate,
95
96
  onInsertAfter,
96
97
  onInsertBefore,
97
- isLocked,
98
98
  onRemove,
99
99
  onCopy,
100
100
  onMoveTo,
@@ -157,7 +157,7 @@ export function BlockSettingsDropdown( {
157
157
  </MenuItem>
158
158
  </>
159
159
  ) }
160
- { ! isLocked && ! onlyBlock && (
160
+ { canMove && ! onlyBlock && (
161
161
  <MenuItem
162
162
  onClick={ flow( onClose, onMoveTo ) }
163
163
  >
@@ -25,17 +25,20 @@ import { store as blockEditorStore } from '../../store';
25
25
  const { Fill, Slot } = createSlotFill( 'BlockSettingsMenuControls' );
26
26
 
27
27
  const BlockSettingsMenuControlsSlot = ( { fillProps, clientIds = null } ) => {
28
- const selectedBlocks = useSelect(
28
+ const { selectedBlocks, selectedClientIds } = useSelect(
29
29
  ( select ) => {
30
30
  const { getBlocksByClientId, getSelectedBlockClientIds } = select(
31
31
  blockEditorStore
32
32
  );
33
33
  const ids =
34
34
  clientIds !== null ? clientIds : getSelectedBlockClientIds();
35
- return map(
36
- compact( getBlocksByClientId( ids ) ),
37
- ( block ) => block.name
38
- );
35
+ return {
36
+ selectedBlocks: map(
37
+ compact( getBlocksByClientId( ids ) ),
38
+ ( block ) => block.name
39
+ ),
40
+ selectedClientIds: ids,
41
+ };
39
42
  },
40
43
  [ clientIds ]
41
44
  );
@@ -46,7 +49,7 @@ const BlockSettingsMenuControlsSlot = ( { fillProps, clientIds = null } ) => {
46
49
  const { isGroupable, isUngroupable } = convertToGroupButtonProps;
47
50
  const showConvertToGroupButton = isGroupable || isUngroupable;
48
51
  return (
49
- <Slot fillProps={ { ...fillProps, selectedBlocks } }>
52
+ <Slot fillProps={ { ...fillProps, selectedBlocks, selectedClientIds } }>
50
53
  { ( fills ) => {
51
54
  if ( fills?.length > 0 || showConvertToGroupButton ) {
52
55
  return (
@@ -33,7 +33,7 @@ export default function BlockStylesMenu( { hoveredBlock, onSwitch } ) {
33
33
  { hoveredClassName && (
34
34
  <PreviewBlockPopover
35
35
  blocks={
36
- blockType.example
36
+ blockType && blockType.example
37
37
  ? getBlockFromExample( blockType.name, {
38
38
  attributes: {
39
39
  ...blockType.example.attributes,
@@ -128,8 +128,11 @@ export default function BlockTools( {
128
128
  ref={ usePopoverScroll( __unstableContentRef ) }
129
129
  />
130
130
  { children }
131
- { /* Forward compatibility: a place to render block tools behind the
132
- content so it can be tabbed to properly. */ }
131
+ { /* Used for inline rich text popovers. */ }
132
+ <Popover.Slot
133
+ name="__unstable-block-tools-after"
134
+ ref={ usePopoverScroll( __unstableContentRef ) }
135
+ />
133
136
  </InsertionPoint>
134
137
  </div>
135
138
  );
@@ -14,7 +14,8 @@ import {
14
14
  createContext,
15
15
  useContext,
16
16
  } from '@wordpress/element';
17
- import { Popover } from '@wordpress/components';
17
+ import { Popover, __unstableMotion as motion } from '@wordpress/components';
18
+ import { useReducedMotion } from '@wordpress/compose';
18
19
  import { isRTL } from '@wordpress/i18n';
19
20
 
20
21
  /**
@@ -79,7 +80,7 @@ function InsertionPointPopover( {
79
80
  }, [] );
80
81
  const previousElement = useBlockElement( previousClientId );
81
82
  const nextElement = useBlockElement( nextClientId );
82
-
83
+ const isVertical = orientation === 'vertical';
83
84
  const style = useMemo( () => {
84
85
  if ( ! previousElement && ! nextElement ) {
85
86
  return {};
@@ -92,7 +93,7 @@ function InsertionPointPopover( {
92
93
  ? nextElement.getBoundingClientRect()
93
94
  : null;
94
95
 
95
- if ( orientation === 'vertical' ) {
96
+ if ( isVertical ) {
96
97
  return {
97
98
  width: previousElement
98
99
  ? previousElement.offsetWidth
@@ -133,7 +134,7 @@ function InsertionPointPopover( {
133
134
  ? nextElement.getBoundingClientRect()
134
135
  : null;
135
136
 
136
- if ( orientation === 'vertical' ) {
137
+ if ( isVertical ) {
137
138
  if ( isRTL() ) {
138
139
  return {
139
140
  top: previousRect ? previousRect.bottom : nextRect.top,
@@ -173,6 +174,7 @@ function InsertionPointPopover( {
173
174
  }, [ previousElement, nextElement ] );
174
175
 
175
176
  const popoverScrollRef = usePopoverScroll( __unstableContentRef );
177
+ const disableMotion = useReducedMotion();
176
178
 
177
179
  const className = classnames(
178
180
  'block-editor-block-list__insertion-point',
@@ -198,6 +200,79 @@ function InsertionPointPopover( {
198
200
  const showInsertionPointInserter =
199
201
  previousElement && nextElement && isInserterShown;
200
202
 
203
+ // Define animation variants for the line element.
204
+ const horizontalLine = {
205
+ start: {
206
+ width: 0,
207
+ top: '50%',
208
+ bottom: '50%',
209
+ x: 0,
210
+ },
211
+ rest: {
212
+ width: 4,
213
+ top: 0,
214
+ bottom: 0,
215
+ x: -2,
216
+ },
217
+ hover: {
218
+ width: 4,
219
+ top: 0,
220
+ bottom: 0,
221
+ x: -2,
222
+ },
223
+ };
224
+ const verticalLine = {
225
+ start: {
226
+ height: 0,
227
+ left: '50%',
228
+ right: '50%',
229
+ y: 0,
230
+ },
231
+ rest: {
232
+ height: 4,
233
+ left: 0,
234
+ right: 0,
235
+ y: -2,
236
+ },
237
+ hover: {
238
+ height: 4,
239
+ left: 0,
240
+ right: 0,
241
+ y: -2,
242
+ },
243
+ };
244
+ const lineVariants = {
245
+ // Initial position starts from the center and invisible.
246
+ start: {
247
+ ...( ! isVertical ? horizontalLine.start : verticalLine.start ),
248
+ opacity: 0,
249
+ },
250
+ // The line expands to fill the container. If the inserter is visible it
251
+ // is delayed so it appears orchestrated.
252
+ rest: {
253
+ ...( ! isVertical ? horizontalLine.rest : verticalLine.rest ),
254
+ opacity: 1,
255
+ borderRadius: '2px',
256
+ transition: { delay: showInsertionPointInserter ? 0.4 : 0 },
257
+ },
258
+ hover: {
259
+ ...( ! isVertical ? horizontalLine.hover : verticalLine.hover ),
260
+ opacity: 1,
261
+ borderRadius: '2px',
262
+ transition: { delay: 0.4 },
263
+ },
264
+ };
265
+
266
+ const inserterVariants = {
267
+ start: {
268
+ scale: disableMotion ? 1 : 0,
269
+ },
270
+ rest: {
271
+ scale: 1,
272
+ transition: { delay: 0.2 },
273
+ },
274
+ };
275
+
201
276
  /* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */
202
277
  // While ideally it would be enough to capture the
203
278
  // bubbling focus event from the Inserter, due to the
@@ -216,8 +291,17 @@ function InsertionPointPopover( {
216
291
  // Render in the old slot if needed for backward compatibility,
217
292
  // otherwise render in place (not in the the default popover slot).
218
293
  __unstableSlotName={ __unstablePopoverSlot || null }
294
+ // Forces a remount of the popover when its position changes
295
+ // This makes sure the popover doesn't animate from its previous position.
296
+ key={ nextClientId + '--' + rootClientId }
219
297
  >
220
- <div
298
+ <motion.div
299
+ layout={ ! disableMotion }
300
+ initial={ disableMotion ? 'rest' : 'start' }
301
+ animate="rest"
302
+ whileHover="hover"
303
+ whileTap="pressed"
304
+ exit="start"
221
305
  ref={ ref }
222
306
  tabIndex={ -1 }
223
307
  onClick={ onClick }
@@ -227,9 +311,13 @@ function InsertionPointPopover( {
227
311
  } ) }
228
312
  style={ style }
229
313
  >
230
- <div className="block-editor-block-list__insertion-point-indicator" />
314
+ <motion.div
315
+ variants={ lineVariants }
316
+ className="block-editor-block-list__insertion-point-indicator"
317
+ />
231
318
  { showInsertionPointInserter && (
232
- <div
319
+ <motion.div
320
+ variants={ inserterVariants }
233
321
  className={ classnames(
234
322
  'block-editor-block-list__insertion-point-inserter'
235
323
  ) }
@@ -246,9 +334,9 @@ function InsertionPointPopover( {
246
334
  openRef.current = false;
247
335
  } }
248
336
  />
249
- </div>
337
+ </motion.div>
250
338
  ) }
251
- </div>
339
+ </motion.div>
252
340
  </Popover>
253
341
  );
254
342
  /* eslint-enable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */
@@ -10,15 +10,8 @@
10
10
  position: absolute;
11
11
  background: var(--wp-admin-theme-color);
12
12
 
13
- // Provide a muted animation that isn't too noisy.
14
- animation: block-editor-inserter__toggle__fade-in-animation-delayed 0.3s ease;
15
- animation-fill-mode: forwards;
16
- @include reduce-motion("animation");
17
-
18
13
  .block-editor-block-list__insertion-point.is-vertical > & {
19
14
  top: 50%;
20
- right: 0;
21
- left: 0;
22
15
  height: $border-width;
23
16
  }
24
17
 
@@ -26,7 +19,6 @@
26
19
  top: 0;
27
20
  right: 0;
28
21
  left: 50%;
29
- height: 100%;
30
22
  width: $border-width;
31
23
  }
32
24
  }
@@ -42,8 +34,8 @@
42
34
 
43
35
  justify-content: center;
44
36
 
45
- top: calc(50% - #{ $button-size-small * 0.5 });
46
- left: calc(50% - #{ $button-size-small * 0.5 });
37
+ top: calc(50% - #{$button-size-small * 0.5});
38
+ left: calc(50% - #{$button-size-small * 0.5});
47
39
  }
48
40
 
49
41
  .block-editor-block-list__block-popover-inserter {
@@ -86,29 +78,6 @@
86
78
  }
87
79
  }
88
80
 
89
- .block-editor-block-list__insertion-point-inserter,
90
- .block-editor-block-list__block-popover-inserter {
91
- .block-editor-inserter__toggle.components-button {
92
- // Fade it in after a delay.
93
- animation: block-editor-inserter__toggle__fade-in-animation-delayed 0.3s ease;
94
- animation-fill-mode: forwards;
95
- @include reduce-motion("animation");
96
- }
97
- }
98
-
99
- @keyframes block-editor-inserter__toggle__fade-in-animation-delayed {
100
- 0% {
101
- opacity: 0;
102
- }
103
- 60% {
104
- opacity: 0;
105
- }
106
- 100% {
107
- opacity: 1;
108
- }
109
- }
110
-
111
-
112
81
  /**
113
82
  * Block Toolbar when contextual.
114
83
  */
@@ -181,7 +150,6 @@
181
150
  }
182
151
  }
183
152
 
184
-
185
153
  /**
186
154
  * Block Label for Navigation/Selection Mode
187
155
  */
@@ -270,7 +238,8 @@
270
238
  }
271
239
  }
272
240
 
273
- .components-popover__content.components-popover__content { // Needs specificity.
241
+ .components-popover__content.components-popover__content {
242
+ // Needs specificity.
274
243
  background: none;
275
244
  border: none;
276
245
  box-shadow: none;
@@ -53,6 +53,7 @@ export default function BorderRadiusControl( { onChange, values } ) {
53
53
  const units = useCustomUnits( {
54
54
  availableUnits: useSetting( 'spacing.units' ) || [ 'px', 'em', 'rem' ],
55
55
  } );
56
+
56
57
  const unit = getAllUnit( values );
57
58
  const unitConfig = units && units.find( ( item ) => item.value === unit );
58
59
  const step = unitConfig?.step || 1;
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import {
5
+ getAllUnit,
6
+ getAllValue,
7
+ hasMixedValues,
8
+ hasDefinedValues,
9
+ mode,
10
+ } from '../utils';
11
+
12
+ describe( 'getAllUnit', () => {
13
+ describe( 'when provided string based values', () => {
14
+ it( 'should return valid unit when passed a valid unit', () => {
15
+ expect( getAllUnit( '32em' ) ).toBe( 'em' );
16
+ } );
17
+
18
+ it( 'should fall back to px when passed an invalid unit', () => {
19
+ expect( getAllUnit( '32apples' ) ).toBe( 'px' );
20
+ } );
21
+
22
+ it( 'should fall back to px when passed a value without a unit', () => {
23
+ expect( getAllUnit( '32' ) ).toBe( 'px' );
24
+ } );
25
+ } );
26
+
27
+ describe( 'when provided object based values', () => {
28
+ it( 'should return the most common value', () => {
29
+ const values = {
30
+ bottomLeft: '2em',
31
+ bottomRight: '2em',
32
+ topLeft: '0',
33
+ topRight: '2px',
34
+ };
35
+ expect( getAllUnit( values ) ).toBe( 'em' );
36
+ } );
37
+
38
+ it( 'should return the real value when the most common value is undefined', () => {
39
+ const values = {
40
+ bottomLeft: '0',
41
+ bottomRight: '0',
42
+ topLeft: '0',
43
+ topRight: '2em',
44
+ };
45
+ expect( getAllUnit( values ) ).toBe( 'em' );
46
+ } );
47
+
48
+ it( 'should return the most common value there are no undefined values', () => {
49
+ const values = {
50
+ bottomLeft: '1em',
51
+ bottomRight: '1em',
52
+ topLeft: '2px',
53
+ topRight: '2em',
54
+ };
55
+ expect( getAllUnit( values ) ).toBe( 'em' );
56
+ } );
57
+
58
+ it( 'should fall back to px when all values are undefined or equivalent', () => {
59
+ const values = {
60
+ bottomLeft: '0',
61
+ bottomRight: undefined,
62
+ topLeft: undefined,
63
+ topRight: '0',
64
+ };
65
+ expect( getAllUnit( values ) ).toBe( 'px' );
66
+ } );
67
+ } );
68
+
69
+ describe( 'when provided invalid values', () => {
70
+ it( 'should return px when passed an array', () => {
71
+ expect( getAllUnit( [] ) ).toBe( 'px' );
72
+ } );
73
+ it( 'should return px when passed a boolean', () => {
74
+ expect( getAllUnit( false ) ).toBe( 'px' );
75
+ } );
76
+ it( 'should return px when passed undefined', () => {
77
+ expect( getAllUnit( false ) ).toBe( 'px' );
78
+ } );
79
+ } );
80
+ } );
81
+
82
+ describe( 'getAllValue', () => {
83
+ describe( 'when provided string based values', () => {
84
+ it( 'should return valid value + unit when passed a valid unit', () => {
85
+ expect( getAllValue( '32em' ) ).toBe( '32em' );
86
+ } );
87
+
88
+ it( 'should return string as-is without parsing it', () => {
89
+ expect( getAllValue( '32apples' ) ).toBe( '32apples' );
90
+ } );
91
+ } );
92
+
93
+ describe( 'when provided object based values', () => {
94
+ it( 'should return null if values are mixed', () => {
95
+ const values = {
96
+ bottomLeft: '2em',
97
+ bottomRight: '2em',
98
+ topLeft: '0',
99
+ topRight: '2px',
100
+ };
101
+ expect( getAllValue( values ) ).toBe( null );
102
+ } );
103
+
104
+ it( 'should return the common value + unit when all values are the same', () => {
105
+ const values = {
106
+ bottomLeft: '1em',
107
+ bottomRight: '1em',
108
+ topLeft: '1em',
109
+ topRight: '1em',
110
+ };
111
+ expect( getAllValue( values ) ).toBe( '1em' );
112
+ } );
113
+
114
+ it( 'should return the common value + most common unit when same values but different units', () => {
115
+ const values = {
116
+ bottomLeft: '1em',
117
+ bottomRight: '1em',
118
+ topLeft: '1px',
119
+ topRight: '1rem',
120
+ };
121
+ expect( getAllValue( values ) ).toBe( '1em' );
122
+ } );
123
+
124
+ it( 'should fall back to null when values are undefined', () => {
125
+ const values = {
126
+ bottomLeft: undefined,
127
+ bottomRight: undefined,
128
+ topLeft: undefined,
129
+ topRight: undefined,
130
+ };
131
+ expect( getAllValue( values ) ).toBe( null );
132
+ } );
133
+ } );
134
+
135
+ describe( 'when provided invalid values', () => {
136
+ it( 'should return px when passed an array', () => {
137
+ expect( getAllValue( [] ) ).toBe( null );
138
+ } );
139
+ it( 'should return px when passed a boolean', () => {
140
+ expect( getAllValue( false ) ).toBe( null );
141
+ } );
142
+ it( 'should return px when passed undefined', () => {
143
+ expect( getAllValue( false ) ).toBe( null );
144
+ } );
145
+ } );
146
+ } );
147
+
148
+ describe( 'hasMixedValues', () => {
149
+ it( 'should return false when passed a string value', () => {
150
+ expect( hasMixedValues( '2px' ) ).toBe( false );
151
+ } );
152
+
153
+ it( 'should return true when passed mixed values', () => {
154
+ const values = {
155
+ bottomLeft: '1em',
156
+ bottomRight: '1px',
157
+ topLeft: '2px',
158
+ topRight: '2em',
159
+ };
160
+ expect( hasMixedValues( values ) ).toBe( true );
161
+ } );
162
+
163
+ it( 'should return false when passed a common value', () => {
164
+ const values = {
165
+ bottomLeft: '1em',
166
+ bottomRight: '1em',
167
+ topLeft: '1em',
168
+ topRight: '1em',
169
+ };
170
+ expect( hasMixedValues( values ) ).toBe( false );
171
+ } );
172
+ } );
173
+
174
+ describe( 'hasDefinedValues', () => {
175
+ it( 'should return false when passed a falsy value', () => {
176
+ expect( hasDefinedValues( undefined ) ).toBe( false );
177
+ expect( hasDefinedValues( null ) ).toBe( false );
178
+ expect( hasDefinedValues( '' ) ).toBe( false );
179
+ } );
180
+
181
+ it( 'should return true when passed a non empty string value', () => {
182
+ expect( hasDefinedValues( '1px' ) ).toBe( true );
183
+ } );
184
+
185
+ it( 'should return false when passed an object with empty values', () => {
186
+ const values = {
187
+ bottomLeft: undefined,
188
+ bottomRight: undefined,
189
+ topLeft: undefined,
190
+ topRight: undefined,
191
+ };
192
+ expect( hasDefinedValues( values ) ).toBe( false );
193
+ } );
194
+
195
+ it( 'should return true when passed an object with at least one real value', () => {
196
+ const values = {
197
+ bottomLeft: undefined,
198
+ bottomRight: '1px',
199
+ topLeft: undefined,
200
+ topRight: undefined,
201
+ };
202
+ expect( hasDefinedValues( values ) ).toBe( true );
203
+ } );
204
+ } );
205
+
206
+ describe( 'mode', () => {
207
+ it( 'should return the most common value', () => {
208
+ const values = [ 'a', 'z', 'z', 'b', undefined ];
209
+ expect( mode( values ) ).toBe( 'z' );
210
+ } );
211
+
212
+ it( 'should return the most common real value', () => {
213
+ const values = [ undefined, 'a', undefined, undefined, undefined ];
214
+ expect( mode( values ) ).toBe( 'a' );
215
+ } );
216
+ } );