@wordpress/block-editor 11.1.0 → 11.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE.md +1 -1
  3. package/build/components/block-actions/index.js +9 -0
  4. package/build/components/block-actions/index.js.map +1 -1
  5. package/build/components/block-inspector/index.js +4 -2
  6. package/build/components/block-inspector/index.js.map +1 -1
  7. package/build/components/block-preview/auto.js +1 -4
  8. package/build/components/block-preview/auto.js.map +1 -1
  9. package/build/components/block-settings-menu/block-settings-dropdown.js +4 -1
  10. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  11. package/build/components/block-styles/index.js +3 -1
  12. package/build/components/block-styles/index.js.map +1 -1
  13. package/build/components/block-tools/use-block-toolbar-popover-props.js +43 -10
  14. package/build/components/block-tools/use-block-toolbar-popover-props.js.map +1 -1
  15. package/build/components/default-style-picker/index.js +1 -0
  16. package/build/components/default-style-picker/index.js.map +1 -1
  17. package/build/components/font-sizes/with-font-sizes.js +5 -8
  18. package/build/components/font-sizes/with-font-sizes.js.map +1 -1
  19. package/build/components/iframe/index.js +37 -8
  20. package/build/components/iframe/index.js.map +1 -1
  21. package/build/components/iframe/use-compatibility-styles.js +6 -1
  22. package/build/components/iframe/use-compatibility-styles.js.map +1 -1
  23. package/build/components/image-size-control/index.js +1 -0
  24. package/build/components/image-size-control/index.js.map +1 -1
  25. package/build/components/inserter/block-patterns-tab.js +4 -4
  26. package/build/components/inserter/block-patterns-tab.js.map +1 -1
  27. package/build/components/inserter/index.js +3 -2
  28. package/build/components/inserter/index.js.map +1 -1
  29. package/build/components/inserter/menu.js +11 -5
  30. package/build/components/inserter/menu.js.map +1 -1
  31. package/build/components/inspector-controls/groups.js +3 -1
  32. package/build/components/inspector-controls/groups.js.map +1 -1
  33. package/build/components/inspector-controls-tabs/position-controls-panel.js +46 -0
  34. package/build/components/inspector-controls-tabs/position-controls-panel.js.map +1 -0
  35. package/build/components/inspector-controls-tabs/settings-tab.js +3 -1
  36. package/build/components/inspector-controls-tabs/settings-tab.js.map +1 -1
  37. package/build/components/inspector-controls-tabs/use-inspector-controls-tabs.js +4 -11
  38. package/build/components/inspector-controls-tabs/use-inspector-controls-tabs.js.map +1 -1
  39. package/build/components/link-control/search-input.js +1 -0
  40. package/build/components/link-control/search-input.js.map +1 -1
  41. package/build/components/off-canvas-editor/appender.js +2 -38
  42. package/build/components/off-canvas-editor/appender.js.map +1 -1
  43. package/build/components/off-canvas-editor/block-contents.js +38 -5
  44. package/build/components/off-canvas-editor/block-contents.js.map +1 -1
  45. package/build/components/off-canvas-editor/block.js +7 -25
  46. package/build/components/off-canvas-editor/block.js.map +1 -1
  47. package/build/components/off-canvas-editor/index.js +7 -4
  48. package/build/components/off-canvas-editor/index.js.map +1 -1
  49. package/build/components/provider/index.js +3 -1
  50. package/build/components/provider/index.js.map +1 -1
  51. package/build/components/rich-text/use-enter.js +4 -5
  52. package/build/components/rich-text/use-enter.js.map +1 -1
  53. package/build/components/url-input/button.js +1 -0
  54. package/build/components/url-input/button.js.map +1 -1
  55. package/build/components/url-input/index.js +15 -1
  56. package/build/components/url-input/index.js.map +1 -1
  57. package/build/components/url-popover/link-editor.js +1 -0
  58. package/build/components/url-popover/link-editor.js.map +1 -1
  59. package/build/components/use-paste-styles/index.js +188 -0
  60. package/build/components/use-paste-styles/index.js.map +1 -0
  61. package/build/components/writing-flow/use-arrow-nav.js +22 -29
  62. package/build/components/writing-flow/use-arrow-nav.js.map +1 -1
  63. package/build/hooks/index.js +2 -0
  64. package/build/hooks/index.js.map +1 -1
  65. package/build/hooks/metadata.js +1 -1
  66. package/build/hooks/metadata.js.map +1 -1
  67. package/build/hooks/position.js +376 -0
  68. package/build/hooks/position.js.map +1 -0
  69. package/build/hooks/supports.js +328 -0
  70. package/build/hooks/supports.js.map +1 -0
  71. package/build/store/reducer.js +6 -2
  72. package/build/store/reducer.js.map +1 -1
  73. package/build/store/selectors.js +8 -6
  74. package/build/store/selectors.js.map +1 -1
  75. package/build-module/components/block-actions/index.js +6 -0
  76. package/build-module/components/block-actions/index.js.map +1 -1
  77. package/build-module/components/block-inspector/index.js +3 -2
  78. package/build-module/components/block-inspector/index.js.map +1 -1
  79. package/build-module/components/block-preview/auto.js +1 -4
  80. package/build-module/components/block-preview/auto.js.map +1 -1
  81. package/build-module/components/block-settings-menu/block-settings-dropdown.js +4 -1
  82. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  83. package/build-module/components/block-styles/index.js +2 -1
  84. package/build-module/components/block-styles/index.js.map +1 -1
  85. package/build-module/components/block-tools/use-block-toolbar-popover-props.js +42 -11
  86. package/build-module/components/block-tools/use-block-toolbar-popover-props.js.map +1 -1
  87. package/build-module/components/default-style-picker/index.js +1 -0
  88. package/build-module/components/default-style-picker/index.js.map +1 -1
  89. package/build-module/components/font-sizes/with-font-sizes.js +5 -7
  90. package/build-module/components/font-sizes/with-font-sizes.js.map +1 -1
  91. package/build-module/components/iframe/index.js +36 -9
  92. package/build-module/components/iframe/index.js.map +1 -1
  93. package/build-module/components/iframe/use-compatibility-styles.js +6 -1
  94. package/build-module/components/iframe/use-compatibility-styles.js.map +1 -1
  95. package/build-module/components/image-size-control/index.js +1 -0
  96. package/build-module/components/image-size-control/index.js.map +1 -1
  97. package/build-module/components/inserter/block-patterns-tab.js +4 -4
  98. package/build-module/components/inserter/block-patterns-tab.js.map +1 -1
  99. package/build-module/components/inserter/index.js +3 -2
  100. package/build-module/components/inserter/index.js.map +1 -1
  101. package/build-module/components/inserter/menu.js +11 -5
  102. package/build-module/components/inserter/menu.js.map +1 -1
  103. package/build-module/components/inspector-controls/groups.js +3 -1
  104. package/build-module/components/inspector-controls/groups.js.map +1 -1
  105. package/build-module/components/inspector-controls-tabs/position-controls-panel.js +33 -0
  106. package/build-module/components/inspector-controls-tabs/position-controls-panel.js.map +1 -0
  107. package/build-module/components/inspector-controls-tabs/settings-tab.js +2 -1
  108. package/build-module/components/inspector-controls-tabs/settings-tab.js.map +1 -1
  109. package/build-module/components/inspector-controls-tabs/use-inspector-controls-tabs.js +4 -11
  110. package/build-module/components/inspector-controls-tabs/use-inspector-controls-tabs.js.map +1 -1
  111. package/build-module/components/link-control/search-input.js +1 -0
  112. package/build-module/components/link-control/search-input.js.map +1 -1
  113. package/build-module/components/off-canvas-editor/appender.js +3 -36
  114. package/build-module/components/off-canvas-editor/appender.js.map +1 -1
  115. package/build-module/components/off-canvas-editor/block-contents.js +37 -7
  116. package/build-module/components/off-canvas-editor/block-contents.js.map +1 -1
  117. package/build-module/components/off-canvas-editor/block.js +9 -27
  118. package/build-module/components/off-canvas-editor/block.js.map +1 -1
  119. package/build-module/components/off-canvas-editor/index.js +7 -4
  120. package/build-module/components/off-canvas-editor/index.js.map +1 -1
  121. package/build-module/components/provider/index.js +3 -1
  122. package/build-module/components/provider/index.js.map +1 -1
  123. package/build-module/components/rich-text/use-enter.js +4 -5
  124. package/build-module/components/rich-text/use-enter.js.map +1 -1
  125. package/build-module/components/url-input/button.js +1 -0
  126. package/build-module/components/url-input/button.js.map +1 -1
  127. package/build-module/components/url-input/index.js +14 -1
  128. package/build-module/components/url-input/index.js.map +1 -1
  129. package/build-module/components/url-popover/link-editor.js +1 -0
  130. package/build-module/components/url-popover/link-editor.js.map +1 -1
  131. package/build-module/components/use-paste-styles/index.js +174 -0
  132. package/build-module/components/use-paste-styles/index.js.map +1 -0
  133. package/build-module/components/writing-flow/use-arrow-nav.js +22 -29
  134. package/build-module/components/writing-flow/use-arrow-nav.js.map +1 -1
  135. package/build-module/hooks/index.js +1 -0
  136. package/build-module/hooks/index.js.map +1 -1
  137. package/build-module/hooks/metadata.js +1 -1
  138. package/build-module/hooks/metadata.js.map +1 -1
  139. package/build-module/hooks/position.js +337 -0
  140. package/build-module/hooks/position.js.map +1 -0
  141. package/build-module/hooks/supports.js +257 -0
  142. package/build-module/hooks/supports.js.map +1 -0
  143. package/build-module/store/reducer.js +6 -2
  144. package/build-module/store/reducer.js.map +1 -1
  145. package/build-module/store/selectors.js +7 -5
  146. package/build-module/store/selectors.js.map +1 -1
  147. package/build-style/content-rtl.css +57 -0
  148. package/build-style/content.css +57 -0
  149. package/build-style/style-rtl.css +27 -58
  150. package/build-style/style.css +27 -58
  151. package/package.json +29 -29
  152. package/src/components/block-actions/index.js +5 -0
  153. package/src/components/block-inspector/index.js +3 -1
  154. package/src/components/block-preview/auto.js +2 -4
  155. package/src/components/block-settings-menu/block-settings-dropdown.js +4 -0
  156. package/src/components/block-styles/index.js +4 -1
  157. package/src/components/block-tools/use-block-toolbar-popover-props.js +68 -12
  158. package/src/components/button-block-appender/{style.scss → content.scss} +0 -0
  159. package/src/components/default-style-picker/index.js +1 -0
  160. package/src/components/font-sizes/with-font-sizes.js +33 -33
  161. package/src/components/iframe/index.js +52 -19
  162. package/src/components/iframe/use-compatibility-styles.js +6 -0
  163. package/src/components/image-size-control/index.js +1 -0
  164. package/src/components/inserter/block-patterns-tab.js +7 -4
  165. package/src/components/inserter/index.js +46 -41
  166. package/src/components/inserter/menu.js +8 -4
  167. package/src/components/inserter/test/__snapshots__/index.native.js.snap +117 -0
  168. package/src/components/inserter/test/index.native.js +255 -1
  169. package/src/components/inspector-controls/groups.js +2 -0
  170. package/src/components/inspector-controls-tabs/position-controls-panel.js +37 -0
  171. package/src/components/inspector-controls-tabs/settings-tab.js +2 -0
  172. package/src/components/inspector-controls-tabs/style.scss +15 -0
  173. package/src/components/inspector-controls-tabs/use-inspector-controls-tabs.js +3 -8
  174. package/src/components/link-control/search-input.js +1 -0
  175. package/src/components/link-control/style.scss +1 -0
  176. package/src/components/list-view/style.scss +13 -3
  177. package/src/components/off-canvas-editor/appender.js +2 -52
  178. package/src/components/off-canvas-editor/block-contents.js +84 -23
  179. package/src/components/off-canvas-editor/block.js +28 -60
  180. package/src/components/off-canvas-editor/index.js +12 -2
  181. package/src/components/provider/index.js +4 -1
  182. package/src/components/rich-text/use-enter.js +4 -4
  183. package/src/components/url-input/README.md +5 -0
  184. package/src/components/url-input/button.js +1 -0
  185. package/src/components/url-input/index.js +15 -1
  186. package/src/components/url-popover/link-editor.js +1 -0
  187. package/src/components/use-paste-styles/index.js +230 -0
  188. package/src/components/writing-flow/use-arrow-nav.js +20 -28
  189. package/src/content.scss +1 -0
  190. package/src/hooks/index.js +1 -0
  191. package/src/hooks/metadata.js +1 -2
  192. package/src/hooks/position.js +375 -0
  193. package/src/hooks/position.scss +18 -0
  194. package/src/hooks/supports.js +302 -0
  195. package/src/hooks/test/__snapshots__/align.native.js.snap +73 -0
  196. package/src/hooks/test/align.native.js +133 -0
  197. package/src/store/reducer.js +7 -2
  198. package/src/store/selectors.js +5 -5
  199. package/src/store/test/reducer.js +45 -3
  200. package/src/store/test/selectors.js +12 -9
  201. package/src/style.scss +2 -1
@@ -3,13 +3,20 @@
3
3
  */
4
4
  import { useRefEffect } from '@wordpress/compose';
5
5
  import { useSelect } from '@wordpress/data';
6
- import { useCallback, useLayoutEffect, useState } from '@wordpress/element';
6
+ import { getScrollContainer } from '@wordpress/dom';
7
+ import {
8
+ useCallback,
9
+ useLayoutEffect,
10
+ useMemo,
11
+ useState,
12
+ } from '@wordpress/element';
7
13
 
8
14
  /**
9
15
  * Internal dependencies
10
16
  */
11
17
  import { store as blockEditorStore } from '../../store';
12
18
  import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs';
19
+ import { hasStickyOrFixedPositionValue } from '../../hooks/position';
13
20
 
14
21
  const COMMON_PROPS = {
15
22
  placement: 'top-start',
@@ -40,28 +47,50 @@ const RESTRICTED_HEIGHT_PROPS = {
40
47
  *
41
48
  * @param {Element} contentElement The DOM element that represents the editor content or canvas.
42
49
  * @param {Element} selectedBlockElement The outer DOM element of the first selected block.
50
+ * @param {Element} scrollContainer The scrollable container for the contentElement.
43
51
  * @param {number} toolbarHeight The height of the toolbar in pixels.
52
+ * @param {boolean} isSticky Whether or not the selected block is sticky or fixed.
44
53
  *
45
54
  * @return {Object} The popover props used to determine the position of the toolbar.
46
55
  */
47
- function getProps( contentElement, selectedBlockElement, toolbarHeight ) {
56
+ function getProps(
57
+ contentElement,
58
+ selectedBlockElement,
59
+ scrollContainer,
60
+ toolbarHeight,
61
+ isSticky
62
+ ) {
48
63
  if ( ! contentElement || ! selectedBlockElement ) {
49
64
  return DEFAULT_PROPS;
50
65
  }
51
66
 
67
+ // Get how far the content area has been scrolled.
68
+ const scrollTop = scrollContainer?.scrollTop || 0;
69
+
52
70
  const blockRect = selectedBlockElement.getBoundingClientRect();
53
71
  const contentRect = contentElement.getBoundingClientRect();
54
72
 
73
+ // Get the vertical position of top of the visible content area.
74
+ const topOfContentElementInViewport = scrollTop + contentRect.top;
75
+
55
76
  // The document element's clientHeight represents the viewport height.
56
77
  const viewportHeight =
57
78
  contentElement.ownerDocument.documentElement.clientHeight;
58
79
 
59
- const hasSpaceForToolbarAbove =
60
- blockRect.top - contentRect.top > toolbarHeight;
80
+ // The restricted height area is calculated as the sum of the
81
+ // vertical position of the visible content area, plus the height
82
+ // of the block toolbar.
83
+ const restrictedTopArea = topOfContentElementInViewport + toolbarHeight;
84
+ const hasSpaceForToolbarAbove = blockRect.top > restrictedTopArea;
85
+
61
86
  const isBlockTallerThanViewport =
62
87
  blockRect.height > viewportHeight - toolbarHeight;
63
88
 
64
- if ( hasSpaceForToolbarAbove || isBlockTallerThanViewport ) {
89
+ // Sticky blocks are treated as if they will never have enough space for the toolbar above.
90
+ if (
91
+ ! isSticky &&
92
+ ( hasSpaceForToolbarAbove || isBlockTallerThanViewport )
93
+ ) {
65
94
  return DEFAULT_PROPS;
66
95
  }
67
96
 
@@ -83,13 +112,34 @@ export default function useBlockToolbarPopoverProps( {
83
112
  } ) {
84
113
  const selectedBlockElement = useBlockElement( clientId );
85
114
  const [ toolbarHeight, setToolbarHeight ] = useState( 0 );
86
- const [ props, setProps ] = useState( () =>
87
- getProps( contentElement, selectedBlockElement, toolbarHeight )
88
- );
89
- const blockIndex = useSelect(
90
- ( select ) => select( blockEditorStore ).getBlockIndex( clientId ),
115
+ const { blockIndex, isSticky } = useSelect(
116
+ ( select ) => {
117
+ const { getBlockIndex, getBlockAttributes } =
118
+ select( blockEditorStore );
119
+ return {
120
+ blockIndex: getBlockIndex( clientId ),
121
+ isSticky: hasStickyOrFixedPositionValue(
122
+ getBlockAttributes( clientId )
123
+ ),
124
+ };
125
+ },
91
126
  [ clientId ]
92
127
  );
128
+ const scrollContainer = useMemo( () => {
129
+ if ( ! contentElement ) {
130
+ return;
131
+ }
132
+ return getScrollContainer( contentElement );
133
+ }, [ contentElement ] );
134
+ const [ props, setProps ] = useState( () =>
135
+ getProps(
136
+ contentElement,
137
+ selectedBlockElement,
138
+ scrollContainer,
139
+ toolbarHeight,
140
+ isSticky
141
+ )
142
+ );
93
143
 
94
144
  const popoverRef = useRefEffect( ( popoverNode ) => {
95
145
  setToolbarHeight( popoverNode.offsetHeight );
@@ -98,9 +148,15 @@ export default function useBlockToolbarPopoverProps( {
98
148
  const updateProps = useCallback(
99
149
  () =>
100
150
  setProps(
101
- getProps( contentElement, selectedBlockElement, toolbarHeight )
151
+ getProps(
152
+ contentElement,
153
+ selectedBlockElement,
154
+ scrollContainer,
155
+ toolbarHeight,
156
+ isSticky
157
+ )
102
158
  ),
103
- [ contentElement, selectedBlockElement, toolbarHeight ]
159
+ [ contentElement, selectedBlockElement, scrollContainer, toolbarHeight ]
104
160
  );
105
161
 
106
162
  // Update props when the block is moved. This also ensures the props are
@@ -58,6 +58,7 @@ export default function DefaultStylePicker( { blockName } ) {
58
58
  onUpdatePreferredStyleVariations && (
59
59
  <div className="default-style-picker__default-switcher">
60
60
  <SelectControl
61
+ __nextHasNoMarginBottom
61
62
  options={ selectOptions }
62
63
  value={ preferredStyle || '' }
63
64
  label={ __( 'Default Style' ) }
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { pickBy } from 'lodash';
5
-
6
1
  /**
7
2
  * WordPress dependencies
8
3
  */
@@ -160,35 +155,40 @@ export default ( ...fontSizeNames ) => {
160
155
  }
161
156
 
162
157
  const newState = Object.entries(
163
- pickBy(
164
- fontSizeAttributeNames,
165
- didAttributesChange
158
+ fontSizeAttributeNames
159
+ )
160
+ .filter( ( [ key, value ] ) =>
161
+ didAttributesChange( value, key )
166
162
  )
167
- ).reduce(
168
- (
169
- newStateAccumulator,
170
- [
171
- fontSizeAttributeName,
172
- customFontSizeAttributeName,
173
- ]
174
- ) => {
175
- const fontSizeAttributeValue =
176
- attributes[ fontSizeAttributeName ];
177
- const fontSizeObject = getFontSize(
178
- fontSizes,
179
- fontSizeAttributeValue,
180
- attributes[ customFontSizeAttributeName ]
181
- );
182
- newStateAccumulator[ fontSizeAttributeName ] = {
183
- ...fontSizeObject,
184
- class: getFontSizeClass(
185
- fontSizeAttributeValue
186
- ),
187
- };
188
- return newStateAccumulator;
189
- },
190
- {}
191
- );
163
+ .reduce(
164
+ (
165
+ newStateAccumulator,
166
+ [
167
+ fontSizeAttributeName,
168
+ customFontSizeAttributeName,
169
+ ]
170
+ ) => {
171
+ const fontSizeAttributeValue =
172
+ attributes[ fontSizeAttributeName ];
173
+ const fontSizeObject = getFontSize(
174
+ fontSizes,
175
+ fontSizeAttributeValue,
176
+ attributes[
177
+ customFontSizeAttributeName
178
+ ]
179
+ );
180
+ newStateAccumulator[
181
+ fontSizeAttributeName
182
+ ] = {
183
+ ...fontSizeObject,
184
+ class: getFontSizeClass(
185
+ fontSizeAttributeValue
186
+ ),
187
+ };
188
+ return newStateAccumulator;
189
+ },
190
+ {}
191
+ );
192
192
 
193
193
  return {
194
194
  ...previousState,
@@ -12,6 +12,7 @@ import {
12
12
  forwardRef,
13
13
  useMemo,
14
14
  useReducer,
15
+ renderToString,
15
16
  } from '@wordpress/element';
16
17
  import { __ } from '@wordpress/i18n';
17
18
  import {
@@ -20,6 +21,7 @@ import {
20
21
  useRefEffect,
21
22
  } from '@wordpress/compose';
22
23
  import { __experimentalStyleProvider as StyleProvider } from '@wordpress/components';
24
+ import { useSelect } from '@wordpress/data';
23
25
 
24
26
  /**
25
27
  * Internal dependencies
@@ -27,6 +29,7 @@ import { __experimentalStyleProvider as StyleProvider } from '@wordpress/compone
27
29
  import { useBlockSelectionClearer } from '../block-selection-clearer';
28
30
  import { useWritingFlow } from '../writing-flow';
29
31
  import { useCompatibilityStyles } from './use-compatibility-styles';
32
+ import { store as blockEditorStore } from '../../store';
30
33
 
31
34
  /**
32
35
  * Bubbles some event types (keydown, keypress, and dragover) to parent document
@@ -97,20 +100,22 @@ async function loadScript( head, { id, src } ) {
97
100
  } );
98
101
  }
99
102
 
100
- function Iframe(
101
- {
102
- contentRef,
103
- children,
104
- head,
105
- tabIndex = 0,
106
- assets,
107
- scale = 1,
108
- frameSize = 0,
109
- readonly,
110
- ...props
111
- },
112
- ref
113
- ) {
103
+ function Iframe( {
104
+ contentRef,
105
+ children,
106
+ head,
107
+ tabIndex = 0,
108
+ scale = 1,
109
+ frameSize = 0,
110
+ readonly,
111
+ forwardedRef: ref,
112
+ ...props
113
+ } ) {
114
+ const assets = useSelect(
115
+ ( select ) =>
116
+ select( blockEditorStore ).getSettings().__unstableResolvedAssets,
117
+ []
118
+ );
114
119
  const [ , forceRender ] = useReducer( () => ( {} ) );
115
120
  const [ iframeDocument, setIframeDocument ] = useState();
116
121
  const [ bodyClasses, setBodyClasses ] = useState( [] );
@@ -204,7 +209,7 @@ function Iframe(
204
209
  }, [] );
205
210
  const bodyRef = useMergeRefs( [ contentRef, clearerRef, writingFlowRef ] );
206
211
 
207
- head = (
212
+ const styleAssets = (
208
213
  <>
209
214
  <style>{ 'html{height:auto!important;}body{margin:0}' }</style>
210
215
  { [ ...styles, ...neededCompatStyles ].map(
@@ -224,10 +229,16 @@ function Iframe(
224
229
  );
225
230
  }
226
231
  ) }
227
- { head }
228
232
  </>
229
233
  );
230
234
 
235
+ // Correct doctype is required to enable rendering in standards
236
+ // mode. Also preload the styles to avoid a flash of unstyled
237
+ // content.
238
+ const srcDoc = useMemo( () => {
239
+ return '<!doctype html>' + renderToString( styleAssets );
240
+ }, [] );
241
+
231
242
  return (
232
243
  <>
233
244
  { tabIndex >= 0 && before }
@@ -235,14 +246,17 @@ function Iframe(
235
246
  { ...props }
236
247
  ref={ useMergeRefs( [ ref, setRef ] ) }
237
248
  tabIndex={ tabIndex }
238
- // Correct doctype is required to enable rendering in standards mode
239
- srcDoc="<!doctype html>"
249
+ // Correct doctype is required to enable rendering in standards
250
+ // mode. Also preload the styles to avoid a flash of unstyled
251
+ // content.
252
+ srcDoc={ srcDoc }
240
253
  title={ __( 'Editor canvas' ) }
241
254
  >
242
255
  { iframeDocument &&
243
256
  createPortal(
244
257
  <>
245
258
  <head ref={ headRef }>
259
+ { styleAssets }
246
260
  { head }
247
261
  <style>
248
262
  { `html { transition: background 5s; ${
@@ -286,4 +300,23 @@ function Iframe(
286
300
  );
287
301
  }
288
302
 
289
- export default forwardRef( Iframe );
303
+ function IframeIfReady( props, ref ) {
304
+ const isInitialised = useSelect(
305
+ ( select ) =>
306
+ select( blockEditorStore ).getSettings().__internalIsInitialized,
307
+ []
308
+ );
309
+
310
+ // We shouldn't render the iframe until the editor settings are initialised.
311
+ // The initial settings are needed to get the styles for the srcDoc, which
312
+ // cannot be changed after the iframe is mounted. srcDoc is used to to set
313
+ // the initial iframe HTML, which is required to avoid a flash of unstyled
314
+ // content.
315
+ if ( ! isInitialised ) {
316
+ return null;
317
+ }
318
+
319
+ return <Iframe { ...props } forwardedRef={ ref } />;
320
+ }
321
+
322
+ export default forwardRef( IframeIfReady );
@@ -28,6 +28,12 @@ export function useCompatibilityStyles() {
28
28
 
29
29
  const { ownerNode, cssRules } = styleSheet;
30
30
 
31
+ // Stylesheet is added by another stylesheet. See
32
+ // https://developer.mozilla.org/en-US/docs/Web/API/StyleSheet/ownerNode#notes.
33
+ if ( ownerNode === null ) {
34
+ return accumulator;
35
+ }
36
+
31
37
  if ( ! cssRules ) {
32
38
  return accumulator;
33
39
  }
@@ -41,6 +41,7 @@ export default function ImageSizeControl( {
41
41
  <>
42
42
  { ! isEmpty( imageSizeOptions ) && (
43
43
  <SelectControl
44
+ __nextHasNoMarginBottom
44
45
  label={ __( 'Image size' ) }
45
46
  value={ slug }
46
47
  options={ imageSizeOptions }
@@ -28,8 +28,11 @@ import BlockPatternList from '../block-patterns-list';
28
28
  import PatternsExplorerModal from './block-patterns-explorer/explorer';
29
29
  import MobileTabNavigation from './mobile-tab-navigation';
30
30
 
31
- function usePatternsCategories() {
32
- const [ allPatterns, allCategories ] = usePatternsState();
31
+ function usePatternsCategories( rootClientId ) {
32
+ const [ allPatterns, allCategories ] = usePatternsState(
33
+ undefined,
34
+ rootClientId
35
+ );
33
36
 
34
37
  const hasRegisteredCategory = useCallback(
35
38
  ( pattern ) => {
@@ -128,7 +131,7 @@ export function BlockPatternsCategoryPanel( {
128
131
  rootClientId
129
132
  );
130
133
 
131
- const availableCategories = usePatternsCategories();
134
+ const availableCategories = usePatternsCategories( rootClientId );
132
135
  const currentCategoryPatterns = useMemo(
133
136
  () =>
134
137
  allPatterns.filter( ( pattern ) => {
@@ -184,7 +187,7 @@ function BlockPatternsTabs( {
184
187
  rootClientId,
185
188
  } ) {
186
189
  const [ showPatternsExplorer, setShowPatternsExplorer ] = useState( false );
187
- const categories = usePatternsCategories();
190
+ const categories = usePatternsCategories( rootClientId );
188
191
  const isMobile = useViewportMatch( 'medium', '<' );
189
192
  return (
190
193
  <>
@@ -220,48 +220,53 @@ class Inserter extends Component {
220
220
  }
221
221
 
222
222
  export default compose( [
223
- withSelect( ( select, { clientId, rootClientId } ) => {
224
- const {
225
- getBlockRootClientId,
226
- hasInserterItems,
227
- __experimentalGetAllowedBlocks,
228
- __experimentalGetDirectInsertBlock,
229
- getSettings,
230
- } = select( blockEditorStore );
231
-
232
- const { getBlockVariations } = select( blocksStore );
233
-
234
- rootClientId =
235
- rootClientId || getBlockRootClientId( clientId ) || undefined;
236
-
237
- const allowedBlocks = __experimentalGetAllowedBlocks( rootClientId );
238
-
239
- const directInsertBlock =
240
- __experimentalGetDirectInsertBlock( rootClientId );
241
-
242
- const settings = getSettings();
243
-
244
- const hasSingleBlockType =
245
- allowedBlocks?.length === 1 &&
246
- getBlockVariations( allowedBlocks[ 0 ].name, 'inserter' )
247
- ?.length === 0;
248
-
249
- let allowedBlockType = false;
250
- if ( hasSingleBlockType ) {
251
- allowedBlockType = allowedBlocks[ 0 ];
223
+ withSelect(
224
+ ( select, { clientId, rootClientId, shouldDirectInsert = true } ) => {
225
+ const {
226
+ getBlockRootClientId,
227
+ hasInserterItems,
228
+ __experimentalGetAllowedBlocks,
229
+ __experimentalGetDirectInsertBlock,
230
+ getSettings,
231
+ } = select( blockEditorStore );
232
+
233
+ const { getBlockVariations } = select( blocksStore );
234
+
235
+ rootClientId =
236
+ rootClientId || getBlockRootClientId( clientId ) || undefined;
237
+
238
+ const allowedBlocks =
239
+ __experimentalGetAllowedBlocks( rootClientId );
240
+
241
+ const directInsertBlock =
242
+ shouldDirectInsert &&
243
+ __experimentalGetDirectInsertBlock( rootClientId );
244
+
245
+ const settings = getSettings();
246
+
247
+ const hasSingleBlockType =
248
+ allowedBlocks?.length === 1 &&
249
+ getBlockVariations( allowedBlocks[ 0 ].name, 'inserter' )
250
+ ?.length === 0;
251
+
252
+ let allowedBlockType = false;
253
+ if ( hasSingleBlockType ) {
254
+ allowedBlockType = allowedBlocks[ 0 ];
255
+ }
256
+
257
+ return {
258
+ hasItems: hasInserterItems( rootClientId ),
259
+ hasSingleBlockType,
260
+ blockTitle: allowedBlockType ? allowedBlockType.title : '',
261
+ allowedBlockType,
262
+ directInsertBlock,
263
+ rootClientId,
264
+ prioritizePatterns:
265
+ settings.__experimentalPreferPatternsOnRoot &&
266
+ ! rootClientId,
267
+ };
252
268
  }
253
-
254
- return {
255
- hasItems: hasInserterItems( rootClientId ),
256
- hasSingleBlockType,
257
- blockTitle: allowedBlockType ? allowedBlockType.title : '',
258
- allowedBlockType,
259
- directInsertBlock,
260
- rootClientId,
261
- prioritizePatterns:
262
- settings.__experimentalPreferPatternsOnRoot && ! rootClientId,
263
- };
264
- } ),
269
+ ),
265
270
  withDispatch( ( dispatch, ownProps, { select } ) => {
266
271
  return {
267
272
  insertOnlyAllowedBlock() {
@@ -67,20 +67,24 @@ function InserterMenu(
67
67
  insertionIndex: __experimentalInsertionIndex,
68
68
  shouldFocusBlock,
69
69
  } );
70
- const { showPatterns, hasReusableBlocks } = useSelect(
70
+ const { showPatterns, inserterItems } = useSelect(
71
71
  ( select ) => {
72
- const { __experimentalGetAllowedPatterns, getSettings } =
72
+ const { __experimentalGetAllowedPatterns, getInserterItems } =
73
73
  select( blockEditorStore );
74
74
  return {
75
75
  showPatterns: !! __experimentalGetAllowedPatterns(
76
76
  destinationRootClientId
77
77
  ).length,
78
- hasReusableBlocks:
79
- !! getSettings().__experimentalReusableBlocks?.length,
78
+ inserterItems: getInserterItems( destinationRootClientId ),
80
79
  };
81
80
  },
82
81
  [ destinationRootClientId ]
83
82
  );
83
+ const hasReusableBlocks = useMemo( () => {
84
+ return inserterItems.some(
85
+ ( { category } ) => category === 'reusable'
86
+ );
87
+ }, [ inserterItems ] );
84
88
 
85
89
  const mediaCategories = useMediaCategories( destinationRootClientId );
86
90
  const showMedia = !! mediaCategories.length;
@@ -0,0 +1,117 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Inserter can add blocks adds new block at the end of post 1`] = `
4
+ "<!-- wp:spacer -->
5
+ <div style=\\"height:100px\\" aria-hidden=\\"true\\" class=\\"wp-block-spacer\\"></div>
6
+ <!-- /wp:spacer -->
7
+
8
+ <!-- wp:heading -->
9
+ <h2 class=\\"wp-block-heading\\"></h2>
10
+ <!-- /wp:heading -->"
11
+ `;
12
+
13
+ exports[`Inserter can add blocks after another block 1`] = `
14
+ "<!-- wp:spacer -->
15
+ <div style=\\"height:100px\\" aria-hidden=\\"true\\" class=\\"wp-block-spacer\\"></div>
16
+ <!-- /wp:spacer -->
17
+
18
+ <!-- wp:heading -->
19
+ <h2 class=\\"wp-block-heading\\"></h2>
20
+ <!-- /wp:heading -->
21
+
22
+ <!-- wp:more -->
23
+ <!--more-->
24
+ <!-- /wp:more -->
25
+
26
+ <!-- wp:paragraph -->
27
+ <p></p>
28
+ <!-- /wp:paragraph -->"
29
+ `;
30
+
31
+ exports[`Inserter can add blocks before another block 1`] = `
32
+ "<!-- wp:heading -->
33
+ <h2 class=\\"wp-block-heading\\"></h2>
34
+ <!-- /wp:heading -->
35
+
36
+ <!-- wp:paragraph -->
37
+ <p></p>
38
+ <!-- /wp:paragraph -->"
39
+ `;
40
+
41
+ exports[`Inserter can add blocks creates a new Paragraph block tapping on the empty area below the last block 1`] = `
42
+ "<!-- wp:spacer -->
43
+ <div style=\\"height:100px\\" aria-hidden=\\"true\\" class=\\"wp-block-spacer\\"></div>
44
+ <!-- /wp:spacer -->
45
+
46
+ <!-- wp:heading -->
47
+ <h2 class=\\"wp-block-heading\\"></h2>
48
+ <!-- /wp:heading -->
49
+
50
+ <!-- wp:paragraph -->
51
+ <p></p>
52
+ <!-- /wp:paragraph -->"
53
+ `;
54
+
55
+ exports[`Inserter can add blocks inserts between 2 existing blocks 1`] = `
56
+ "<!-- wp:spacer -->
57
+ <div style=\\"height:100px\\" aria-hidden=\\"true\\" class=\\"wp-block-spacer\\"></div>
58
+ <!-- /wp:spacer -->
59
+
60
+ <!-- wp:more -->
61
+ <!--more-->
62
+ <!-- /wp:more -->
63
+
64
+ <!-- wp:heading -->
65
+ <h2 class=\\"wp-block-heading\\"></h2>
66
+ <!-- /wp:heading -->"
67
+ `;
68
+
69
+ exports[`Inserter can add blocks inserts block at the end of post when no block is selected 1`] = `
70
+ "<!-- wp:spacer -->
71
+ <div style=\\"height:100px\\" aria-hidden=\\"true\\" class=\\"wp-block-spacer\\"></div>
72
+ <!-- /wp:spacer -->
73
+
74
+ <!-- wp:heading -->
75
+ <h2 class=\\"wp-block-heading\\"></h2>
76
+ <!-- /wp:heading -->
77
+
78
+ <!-- wp:more -->
79
+ <!--more-->
80
+ <!-- /wp:more -->"
81
+ `;
82
+
83
+ exports[`Inserter can add blocks to the beginning 1`] = `
84
+ "<!-- wp:more -->
85
+ <!--more-->
86
+ <!-- /wp:more -->
87
+
88
+ <!-- wp:spacer -->
89
+ <div style=\\"height:100px\\" aria-hidden=\\"true\\" class=\\"wp-block-spacer\\"></div>
90
+ <!-- /wp:spacer -->
91
+
92
+ <!-- wp:heading -->
93
+ <h2 class=\\"wp-block-heading\\"></h2>
94
+ <!-- /wp:heading -->
95
+
96
+ <!-- wp:paragraph -->
97
+ <p></p>
98
+ <!-- /wp:paragraph -->"
99
+ `;
100
+
101
+ exports[`Inserter can add blocks to the end 1`] = `
102
+ "<!-- wp:spacer -->
103
+ <div style=\\"height:100px\\" aria-hidden=\\"true\\" class=\\"wp-block-spacer\\"></div>
104
+ <!-- /wp:spacer -->
105
+
106
+ <!-- wp:heading -->
107
+ <h2 class=\\"wp-block-heading\\"></h2>
108
+ <!-- /wp:heading -->
109
+
110
+ <!-- wp:paragraph -->
111
+ <p></p>
112
+ <!-- /wp:paragraph -->
113
+
114
+ <!-- wp:more -->
115
+ <!--more-->
116
+ <!-- /wp:more -->"
117
+ `;