@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
@@ -8,7 +8,12 @@ import classnames from 'classnames';
8
8
  */
9
9
  import { useMergeRefs } from '@wordpress/compose';
10
10
  import { Popover } from '@wordpress/components';
11
- import { forwardRef, useMemo } from '@wordpress/element';
11
+ import {
12
+ forwardRef,
13
+ useMemo,
14
+ useReducer,
15
+ useLayoutEffect,
16
+ } from '@wordpress/element';
12
17
 
13
18
  /**
14
19
  * Internal dependencies
@@ -16,6 +21,8 @@ import { forwardRef, useMemo } from '@wordpress/element';
16
21
  import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs';
17
22
  import usePopoverScroll from './use-popover-scroll';
18
23
 
24
+ const MAX_POPOVER_RECOMPUTE_COUNTER = Number.MAX_SAFE_INTEGER;
25
+
19
26
  function BlockPopover(
20
27
  {
21
28
  clientId,
@@ -47,8 +54,41 @@ function BlockPopover(
47
54
  };
48
55
  }, [ selectedElement, lastSelectedElement, __unstableRefreshSize ] );
49
56
 
57
+ const [ popoverAnchorRecomputeCounter, forceRecomputePopoverAnchor ] =
58
+ useReducer(
59
+ // Module is there to make sure that the counter doesn't overflow.
60
+ ( s ) => ( s + 1 ) % MAX_POPOVER_RECOMPUTE_COUNTER,
61
+ 0
62
+ );
63
+
64
+ // When blocks are moved up/down, they are animated to their new position by
65
+ // updating the `transform` property manually (i.e. without using CSS
66
+ // transitions or animations). The animation, which can also scroll the block
67
+ // editor, can sometimes cause the position of the Popover to get out of sync.
68
+ // A MutationObserver is therefore used to make sure that changes to the
69
+ // selectedElement's attribute (i.e. `transform`) can be tracked and used to
70
+ // trigger the Popover to rerender.
71
+ useLayoutEffect( () => {
72
+ if ( ! selectedElement ) {
73
+ return;
74
+ }
75
+
76
+ const observer = new window.MutationObserver(
77
+ forceRecomputePopoverAnchor
78
+ );
79
+ observer.observe( selectedElement, { attributes: true } );
80
+
81
+ return () => {
82
+ observer.disconnect();
83
+ };
84
+ }, [ selectedElement ] );
85
+
50
86
  const popoverAnchor = useMemo( () => {
51
87
  if (
88
+ // popoverAnchorRecomputeCounter is by definition always equal or greater
89
+ // than 0. This check is only there to satisfy the correctness of the
90
+ // exhaustive-deps rule for the `useMemo` hook.
91
+ popoverAnchorRecomputeCounter < 0 ||
52
92
  ! selectedElement ||
53
93
  ( bottomClientId && ! lastSelectedElement )
54
94
  ) {
@@ -88,7 +128,12 @@ function BlockPopover(
88
128
  },
89
129
  ownerDocument: selectedElement.ownerDocument,
90
130
  };
91
- }, [ bottomClientId, lastSelectedElement, selectedElement ] );
131
+ }, [
132
+ bottomClientId,
133
+ lastSelectedElement,
134
+ selectedElement,
135
+ popoverAnchorRecomputeCounter,
136
+ ] );
92
137
 
93
138
  if ( ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) {
94
139
  return null;
@@ -98,7 +143,6 @@ function BlockPopover(
98
143
  <Popover
99
144
  ref={ mergedRefs }
100
145
  animate={ false }
101
- position="top right left"
102
146
  focusOnMount={ false }
103
147
  anchor={ popoverAnchor }
104
148
  // Render in the old slot if needed for backward compatibility,
@@ -20,13 +20,12 @@ let MemoizedBlockList;
20
20
 
21
21
  const MAX_HEIGHT = 2000;
22
22
 
23
- function AutoBlockPreview( {
23
+ function ScaledBlockPreview( {
24
24
  viewportWidth,
25
+ containerWidth,
25
26
  __experimentalPadding,
26
27
  __experimentalMinHeight,
27
28
  } ) {
28
- const [ containerResizeListener, { width: containerWidth } ] =
29
- useResizeObserver();
30
29
  const [ contentResizeListener, { height: contentHeight } ] =
31
30
  useResizeObserver();
32
31
  const { styles, assets, duotone } = useSelect( ( select ) => {
@@ -62,71 +61,84 @@ function AutoBlockPreview( {
62
61
 
63
62
  const scale = containerWidth / viewportWidth;
64
63
  return (
65
- <div className="block-editor-block-preview__container">
66
- { containerResizeListener }
67
- <Disabled
68
- className="block-editor-block-preview__content"
64
+ <Disabled
65
+ className="block-editor-block-preview__content"
66
+ style={ {
67
+ transform: `scale(${ scale })`,
68
+ height: contentHeight * scale,
69
+ maxHeight:
70
+ contentHeight > MAX_HEIGHT ? MAX_HEIGHT * scale : undefined,
71
+ minHeight: __experimentalMinHeight,
72
+ } }
73
+ >
74
+ <Iframe
75
+ head={ <EditorStyles styles={ editorStyles } /> }
76
+ assets={ assets }
77
+ contentRef={ useRefEffect( ( bodyElement ) => {
78
+ const {
79
+ ownerDocument: { documentElement },
80
+ } = bodyElement;
81
+ documentElement.classList.add(
82
+ 'block-editor-block-preview__content-iframe'
83
+ );
84
+ documentElement.style.position = 'absolute';
85
+ documentElement.style.width = '100%';
86
+ bodyElement.style.padding = __experimentalPadding + 'px';
87
+
88
+ // Necessary for contentResizeListener to work.
89
+ bodyElement.style.boxSizing = 'border-box';
90
+ bodyElement.style.position = 'absolute';
91
+ bodyElement.style.width = '100%';
92
+ }, [] ) }
93
+ aria-hidden
94
+ tabIndex={ -1 }
69
95
  style={ {
70
- transform: `scale(${ scale })`,
71
- height: contentHeight * scale,
72
- maxHeight:
73
- contentHeight > MAX_HEIGHT
74
- ? MAX_HEIGHT * scale
75
- : undefined,
76
- minHeight: __experimentalMinHeight,
96
+ position: 'absolute',
97
+ width: viewportWidth,
98
+ height: contentHeight,
99
+ pointerEvents: 'none',
100
+ // This is a catch-all max-height for patterns.
101
+ // See: https://github.com/WordPress/gutenberg/pull/38175.
102
+ maxHeight: MAX_HEIGHT,
103
+ minHeight:
104
+ scale !== 0 && scale < 1 && __experimentalMinHeight
105
+ ? __experimentalMinHeight / scale
106
+ : __experimentalMinHeight,
77
107
  } }
78
108
  >
79
- <Iframe
80
- head={ <EditorStyles styles={ editorStyles } /> }
81
- assets={ assets }
82
- contentRef={ useRefEffect( ( bodyElement ) => {
83
- const {
84
- ownerDocument: { documentElement },
85
- } = bodyElement;
86
- documentElement.classList.add(
87
- 'block-editor-block-preview__content-iframe'
88
- );
89
- documentElement.style.position = 'absolute';
90
- documentElement.style.width = '100%';
91
- bodyElement.style.padding =
92
- __experimentalPadding + 'px';
93
-
94
- // Necessary for contentResizeListener to work.
95
- bodyElement.style.boxSizing = 'border-box';
96
- bodyElement.style.position = 'absolute';
97
- bodyElement.style.width = '100%';
98
- }, [] ) }
99
- aria-hidden
100
- tabIndex={ -1 }
101
- style={ {
102
- position: 'absolute',
103
- width: viewportWidth,
104
- height: contentHeight,
105
- pointerEvents: 'none',
106
- // This is a catch-all max-height for patterns.
107
- // See: https://github.com/WordPress/gutenberg/pull/38175.
108
- maxHeight: MAX_HEIGHT,
109
- minHeight:
110
- scale !== 0 && scale < 1 && __experimentalMinHeight
111
- ? __experimentalMinHeight / scale
112
- : __experimentalMinHeight,
113
- } }
114
- >
115
- { contentResizeListener }
116
- {
117
- /* Filters need to be rendered before children to avoid Safari rendering issues. */
118
- svgFilters.map( ( preset ) => (
119
- <PresetDuotoneFilter
120
- preset={ preset }
121
- key={ preset.slug }
122
- />
123
- ) )
124
- }
125
- <MemoizedBlockList renderAppender={ false } />
126
- </Iframe>
127
- </Disabled>
128
- </div>
109
+ { contentResizeListener }
110
+ {
111
+ /* Filters need to be rendered before children to avoid Safari rendering issues. */
112
+ svgFilters.map( ( preset ) => (
113
+ <PresetDuotoneFilter
114
+ preset={ preset }
115
+ key={ preset.slug }
116
+ />
117
+ ) )
118
+ }
119
+ <MemoizedBlockList renderAppender={ false } />
120
+ </Iframe>
121
+ </Disabled>
129
122
  );
130
123
  }
131
124
 
132
- export default AutoBlockPreview;
125
+ export default function AutoBlockPreview( props ) {
126
+ const [ containerResizeListener, { width: containerWidth } ] =
127
+ useResizeObserver();
128
+
129
+ return (
130
+ <>
131
+ <div style={ { position: 'relative', width: '100%', height: 0 } }>
132
+ { containerResizeListener }
133
+ </div>
134
+ <div className="block-editor-block-preview__container">
135
+ { !! containerWidth && (
136
+ <ScaledBlockPreview
137
+ { ...props }
138
+ containerWidth={ containerWidth }
139
+ />
140
+ ) }
141
+ </div>
142
+ </>
143
+ );
144
+ }
@@ -64,3 +64,16 @@
64
64
  display: none;
65
65
  }
66
66
  }
67
+
68
+ // The goal of this pseudo-element is to cover the iframe
69
+ // otherwise it won't be able to drag elements containing
70
+ // the preview iframe in Safari.
71
+ .block-editor-block-preview__container::after {
72
+ content: "";
73
+ position: absolute;
74
+ top: 0;
75
+ left: 0;
76
+ right: 0;
77
+ bottom: 0;
78
+ z-index: 1;
79
+ }
@@ -1,14 +1,13 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { debounce } from 'lodash';
5
4
  import classnames from 'classnames';
6
5
 
7
6
  /**
8
7
  * WordPress dependencies
9
8
  */
10
9
  import { useState, useLayoutEffect } from '@wordpress/element';
11
- import { useViewportMatch } from '@wordpress/compose';
10
+ import { debounce, useViewportMatch } from '@wordpress/compose';
12
11
  import {
13
12
  Button,
14
13
  __experimentalTruncate as Truncate,
@@ -20,6 +20,17 @@ import BlockContextualToolbar from './block-contextual-toolbar';
20
20
  import usePopoverScroll from '../block-popover/use-popover-scroll';
21
21
  import ZoomOutModeInserters from './zoom-out-mode-inserters';
22
22
 
23
+ function selector( select ) {
24
+ const { __unstableGetEditorMode, getSettings, isTyping } =
25
+ select( blockEditorStore );
26
+
27
+ return {
28
+ isZoomOutMode: __unstableGetEditorMode() === 'zoom-out',
29
+ hasFixedToolbar: getSettings().hasFixedToolbar,
30
+ isTyping: isTyping(),
31
+ };
32
+ }
33
+
23
34
  /**
24
35
  * Renders block tools (the block toolbar, select/navigation mode toolbar, the
25
36
  * insertion point and a slot for the inline rich text toolbar). Must be wrapped
@@ -35,15 +46,10 @@ export default function BlockTools( {
35
46
  ...props
36
47
  } ) {
37
48
  const isLargeViewport = useViewportMatch( 'medium' );
38
- const { hasFixedToolbar, isZoomOutMode } = useSelect( ( select ) => {
39
- const { __unstableGetEditorMode, getSettings } =
40
- select( blockEditorStore );
41
-
42
- return {
43
- isZoomOutMode: __unstableGetEditorMode() === 'zoom-out',
44
- hasFixedToolbar: getSettings().hasFixedToolbar,
45
- };
46
- }, [] );
49
+ const { hasFixedToolbar, isZoomOutMode, isTyping } = useSelect(
50
+ selector,
51
+ []
52
+ );
47
53
  const isMatch = useShortcutEventMatch();
48
54
  const { getSelectedBlockClientIds, getBlockRootClientId } =
49
55
  useSelect( blockEditorStore );
@@ -118,7 +124,7 @@ export default function BlockTools( {
118
124
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
119
125
  <div { ...props } onKeyDown={ onKeyDown }>
120
126
  <InsertionPointOpenRef.Provider value={ useRef( false ) }>
121
- { ! isZoomOutMode && (
127
+ { ! isTyping && (
122
128
  <InsertionPoint
123
129
  __unstableContentRef={ __unstableContentRef }
124
130
  />
@@ -149,13 +149,13 @@ function InsertionPointPopover( {
149
149
  ...( ! isVertical ? horizontalLine.rest : verticalLine.rest ),
150
150
  opacity: 1,
151
151
  borderRadius: '2px',
152
- transition: { delay: isInserterShown ? 0.4 : 0 },
152
+ transition: { delay: isInserterShown ? 0.1 : 0, type: 'tween' },
153
153
  },
154
154
  hover: {
155
155
  ...( ! isVertical ? horizontalLine.hover : verticalLine.hover ),
156
156
  opacity: 1,
157
157
  borderRadius: '2px',
158
- transition: { delay: 0.4 },
158
+ transition: { delay: 0.1, type: 'tween' },
159
159
  },
160
160
  };
161
161
 
@@ -165,7 +165,7 @@ function InsertionPointPopover( {
165
165
  },
166
166
  rest: {
167
167
  scale: 1,
168
- transition: { delay: 0.2 },
168
+ transition: { type: 'tween' },
169
169
  },
170
170
  };
171
171
 
@@ -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
  };
@@ -85,6 +85,7 @@ function BlockVariationPicker( { isVisible, onClose, clientId, variations } ) {
85
85
  title={ __( 'Select a layout' ) }
86
86
  contentStyle={ styles.contentStyle }
87
87
  leftButton={ leftButton }
88
+ testID="block-variation-modal"
88
89
  >
89
90
  <ScrollView
90
91
  horizontal
@@ -43,6 +43,7 @@ function ButtonBlockAppender( {
43
43
  rootClientId={ rootClientId }
44
44
  renderToggle={ ( { onToggle, disabled, isOpen } ) => (
45
45
  <Button
46
+ testID="appender-button"
46
47
  onClick={ onAddBlock || onToggle }
47
48
  aria-expanded={ isOpen }
48
49
  disabled={ disabled }
@@ -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
@@ -24,8 +24,7 @@ import {
24
24
  } from './fixtures';
25
25
 
26
26
  // Mock debounce() so that it runs instantly.
27
- jest.mock( 'lodash', () => ( {
28
- ...jest.requireActual( 'lodash' ),
27
+ jest.mock( '@wordpress/compose/src/utils/debounce', () => ( {
29
28
  debounce: ( fn ) => {
30
29
  fn.cancel = jest.fn();
31
30
  return fn;
@@ -188,6 +188,7 @@ function ListView(
188
188
  onCollapseRow={ collapseRow }
189
189
  onExpandRow={ expandRow }
190
190
  onFocusRow={ focusRow }
191
+ applicationAriaLabel={ __( 'Block navigation structure' ) }
191
192
  >
192
193
  <ListViewContext.Provider value={ contextValue }>
193
194
  <ListViewBranch
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
+ import { __ } from '@wordpress/i18n';
4
5
  import { Popover, ToolbarGroup } from '@wordpress/components';
5
6
  import { useSelect } from '@wordpress/data';
6
7
  import {
@@ -15,6 +16,7 @@ import {
15
16
  */
16
17
  import BlockControls from '../block-controls';
17
18
  import FormatToolbar from './format-toolbar';
19
+ import NavigableToolbar from '../navigable-toolbar';
18
20
  import { store as blockEditorStore } from '../../store';
19
21
 
20
22
  function InlineSelectionToolbar( {
@@ -46,11 +48,15 @@ function InlineToolbar( { popoverAnchor } ) {
46
48
  className="block-editor-rich-text__inline-format-toolbar"
47
49
  __unstableSlotName="block-toolbar"
48
50
  >
49
- <div className="block-editor-rich-text__inline-format-toolbar-group">
51
+ <NavigableToolbar
52
+ className="block-editor-rich-text__inline-format-toolbar-group"
53
+ /* translators: accessibility text for the inline format toolbar */
54
+ aria-label={ __( 'Format tools' ) }
55
+ >
50
56
  <ToolbarGroup>
51
57
  <FormatToolbar />
52
58
  </ToolbarGroup>
53
- </div>
59
+ </NavigableToolbar>
54
60
  </Popover>
55
61
  );
56
62
  }
@@ -173,6 +173,13 @@ function RichTextWrapper(
173
173
 
174
174
  // Handle deprecated format.
175
175
  if ( Array.isArray( originalValue ) ) {
176
+ deprecated( 'wp.blockEditor.RichText value prop as children type', {
177
+ since: '6.1',
178
+ version: '6.3',
179
+ alternative: 'value prop as string',
180
+ link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/',
181
+ } );
182
+
176
183
  adjustedValue = childrenSource.toHTML( originalValue );
177
184
  adjustedOnChange = ( newValue ) =>
178
185
  originalOnChange(
@@ -436,6 +443,13 @@ ForwardedRichTextContainer.Content = ( {
436
443
  } ) => {
437
444
  // Handle deprecated `children` and `node` sources.
438
445
  if ( Array.isArray( value ) ) {
446
+ deprecated( 'wp.blockEditor.RichText value prop as children type', {
447
+ since: '6.1',
448
+ version: '6.3',
449
+ alternative: 'value prop as string',
450
+ link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/',
451
+ } );
452
+
439
453
  value = childrenSource.toHTML( value );
440
454
  }
441
455
 
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { debounce } from 'lodash';
5
4
  import classnames from 'classnames';
6
5
  import scrollIntoView from 'dom-scroll-into-view';
7
6
 
@@ -18,7 +17,12 @@ import {
18
17
  withSpokenMessages,
19
18
  Popover,
20
19
  } from '@wordpress/components';
21
- import { withInstanceId, withSafeTimeout, compose } from '@wordpress/compose';
20
+ import {
21
+ compose,
22
+ debounce,
23
+ withInstanceId,
24
+ withSafeTimeout,
25
+ } from '@wordpress/compose';
22
26
  import { withSelect } from '@wordpress/data';
23
27
  import { isURL } from '@wordpress/url';
24
28
 
@@ -221,7 +221,7 @@ const ImageURLInputUI = ( {
221
221
  checked={ linkTarget === '_blank' }
222
222
  />
223
223
  <TextControl
224
- label={ __( 'Link Rel' ) }
224
+ label={ __( 'Link rel' ) }
225
225
  value={ rel ?? '' }
226
226
  onChange={ onSetLinkRel }
227
227
  />
@@ -73,6 +73,20 @@ export function getNearestBlockIndex( elements, position, orientation ) {
73
73
  return candidateIndex;
74
74
  }
75
75
 
76
+ /**
77
+ * Determine if the element is an empty paragraph block.
78
+ *
79
+ * @param {?HTMLElement} element The element being tested.
80
+ * @return {boolean} True or False.
81
+ */
82
+ function isEmptyParagraph( element ) {
83
+ return (
84
+ !! element &&
85
+ element.dataset.type === 'core/paragraph' &&
86
+ element.dataset.empty === 'true'
87
+ );
88
+ }
89
+
76
90
  /**
77
91
  * @typedef {Object} WPBlockDropZoneConfig
78
92
  * @property {string} rootClientId The root client id for the block list.
@@ -130,7 +144,18 @@ export default function useBlockDropZone( {
130
144
 
131
145
  setTargetBlockIndex( targetIndex === undefined ? 0 : targetIndex );
132
146
 
133
- if ( targetIndex !== null ) {
147
+ if ( targetIndex !== undefined ) {
148
+ const nextBlock = blockElements[ targetIndex ];
149
+ const previousBlock = blockElements[ targetIndex - 1 ];
150
+
151
+ // Don't show the insertion point when it's near an empty paragraph block.
152
+ if (
153
+ isEmptyParagraph( nextBlock ) ||
154
+ isEmptyParagraph( previousBlock )
155
+ ) {
156
+ return;
157
+ }
158
+
134
159
  showInsertionPoint( targetRootClientId, targetIndex );
135
160
  }
136
161
  }, [] ),