@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
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { TextInput, Platform } from 'react-native';
4
+ import { TextInput, Platform, Dimensions } from 'react-native';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
9
  import { Component } from '@wordpress/element';
10
+ import { getPxFromCssUnit } from '@wordpress/block-editor';
10
11
 
11
12
  /**
12
13
  * Internal dependencies
@@ -61,7 +62,30 @@ export default class PlainText extends Component {
61
62
  this._input.blur();
62
63
  }
63
64
 
65
+ getFontSize() {
66
+ const { style } = this.props;
67
+
68
+ if ( ! style?.fontSize ) {
69
+ return;
70
+ }
71
+
72
+ const { width, height } = Dimensions.get( 'window' );
73
+ const cssUnitOptions = { height, width };
74
+
75
+ return {
76
+ fontSize: parseFloat(
77
+ getPxFromCssUnit( style.fontSize, cssUnitOptions )
78
+ ),
79
+ };
80
+ }
81
+
64
82
  render() {
83
+ const { style } = this.props;
84
+ const textStyles = [
85
+ style || styles[ 'block-editor-plain-text' ],
86
+ this.getFontSize(),
87
+ ];
88
+
65
89
  return (
66
90
  <TextInput
67
91
  { ...this.props }
@@ -75,9 +99,7 @@ export default class PlainText extends Component {
75
99
  ( this.props.style && this.props.style.fontFamily ) ||
76
100
  styles[ 'block-editor-plain-text' ].fontFamily
77
101
  }
78
- style={
79
- this.props.style || styles[ 'block-editor-plain-text' ]
80
- }
102
+ style={ textStyles }
81
103
  scrollEnabled={ false }
82
104
  />
83
105
  );
@@ -0,0 +1,67 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { noop } from 'lodash';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import {
10
+ forwardRef,
11
+ useRef,
12
+ useImperativeHandle,
13
+ memo,
14
+ useCallback,
15
+ } from '@wordpress/element';
16
+ import { Picker } from '@wordpress/components';
17
+ import { __ } from '@wordpress/i18n';
18
+
19
+ const DEFAULT_PICKER_OPTIONS = [
20
+ {
21
+ id: 'createEmbed',
22
+ label: __( 'Create embed' ),
23
+ value: 'createEmbed',
24
+ onSelect: noop,
25
+ },
26
+ {
27
+ id: 'createLink',
28
+ label: __( 'Create link' ),
29
+ value: 'createLink',
30
+ onSelect: noop,
31
+ },
32
+ ];
33
+
34
+ const EmbedHandlerPicker = forwardRef( ( {}, ref ) => {
35
+ const pickerRef = useRef();
36
+ const pickerOptions = useRef( DEFAULT_PICKER_OPTIONS ).current;
37
+
38
+ const onPickerSelect = useCallback(
39
+ ( value ) => {
40
+ const selectedItem = pickerOptions.find(
41
+ ( item ) => item.value === value
42
+ );
43
+ selectedItem.onSelect();
44
+ },
45
+ [ pickerOptions ]
46
+ );
47
+
48
+ useImperativeHandle( ref, () => ( {
49
+ presentPicker: ( { createEmbed, createLink } ) => {
50
+ pickerOptions[ 0 ].onSelect = createEmbed;
51
+ pickerOptions[ 1 ].onSelect = createLink;
52
+ pickerRef.current?.presentPicker();
53
+ },
54
+ } ) );
55
+
56
+ return (
57
+ <Picker
58
+ ref={ pickerRef }
59
+ options={ pickerOptions }
60
+ onChange={ onPickerSelect }
61
+ hideCancelButton
62
+ leftAlign
63
+ />
64
+ );
65
+ } );
66
+
67
+ export default memo( EmbedHandlerPicker );
@@ -26,6 +26,7 @@ import {
26
26
  } from '@wordpress/rich-text';
27
27
  import deprecated from '@wordpress/deprecated';
28
28
  import { BACKSPACE, DELETE } from '@wordpress/keycodes';
29
+ import { Popover } from '@wordpress/components';
29
30
 
30
31
  /**
31
32
  * Internal dependencies
@@ -307,14 +308,17 @@ function RichTextWrapper(
307
308
  { isSelected && (
308
309
  <keyboardShortcutContext.Provider value={ keyboardShortcuts }>
309
310
  <inputEventContext.Provider value={ inputEvents }>
310
- { children && children( { value, onChange, onFocus } ) }
311
- <FormatEdit
312
- value={ value }
313
- onChange={ onChange }
314
- onFocus={ onFocus }
315
- formatTypes={ formatTypes }
316
- forwardedRef={ anchorRef }
317
- />
311
+ <Popover.__unstableSlotNameProvider value="__unstable-block-tools-after">
312
+ { children &&
313
+ children( { value, onChange, onFocus } ) }
314
+ <FormatEdit
315
+ value={ value }
316
+ onChange={ onChange }
317
+ onFocus={ onFocus }
318
+ formatTypes={ formatTypes }
319
+ forwardedRef={ anchorRef }
320
+ />
321
+ </Popover.__unstableSlotNameProvider>
318
322
  </inputEventContext.Provider>
319
323
  </keyboardShortcutContext.Provider>
320
324
  ) }
@@ -55,7 +55,9 @@ import {
55
55
  getMultilineTag,
56
56
  getAllowedFormats,
57
57
  isShortcode,
58
+ createLinkInParagraph,
58
59
  } from './utils';
60
+ import EmbedHandlerPicker from './embed-handler-picker';
59
61
 
60
62
  const wrapperClasses = 'block-editor-rich-text';
61
63
  const classes = 'block-editor-rich-text__editable';
@@ -118,6 +120,7 @@ function RichTextWrapper(
118
120
  const fallbackRef = useRef();
119
121
  const { clientId, isSelected: blockIsSelected } = useBlockEditContext();
120
122
  const nativeProps = useNativeProps();
123
+ const embedHandlerPickerRef = useRef();
121
124
  const selector = ( select ) => {
122
125
  const {
123
126
  isCaretWithinFormattedText,
@@ -439,10 +442,19 @@ function RichTextWrapper(
439
442
  mode = 'BLOCKS';
440
443
  }
441
444
 
445
+ const isPastedURL = isURL( plainText.trim() );
446
+ const presentEmbedHandlerPicker = () =>
447
+ embedHandlerPickerRef.current?.presentPicker( {
448
+ createEmbed: () =>
449
+ onReplace( content, content.length - 1, -1 ),
450
+ createLink: () =>
451
+ createLinkInParagraph( plainText.trim(), onReplace ),
452
+ } );
453
+
442
454
  if (
443
455
  __unstableEmbedURLOnPaste &&
444
456
  isEmpty( value ) &&
445
- isURL( plainText.trim() )
457
+ isPastedURL
446
458
  ) {
447
459
  mode = 'BLOCKS';
448
460
  }
@@ -472,9 +484,30 @@ function RichTextWrapper(
472
484
 
473
485
  onChange( insert( value, valueToInsert ) );
474
486
  } else if ( content.length > 0 ) {
487
+ // When an URL is pasted in an empty paragraph then the EmbedHandlerPicker should showcase options allowing the transformation of that URL
488
+ // into either an Embed block or a link within the target paragraph. If the paragraph is non-empty, the URL is pasted as text.
489
+ const canPasteEmbed =
490
+ isPastedURL &&
491
+ content.length === 1 &&
492
+ content[ 0 ].name === 'core/embed';
475
493
  if ( onReplace && isEmpty( value ) ) {
494
+ if ( canPasteEmbed ) {
495
+ onChange(
496
+ insert( value, create( { text: plainText } ) )
497
+ );
498
+ if ( __unstableEmbedURLOnPaste ) {
499
+ presentEmbedHandlerPicker();
500
+ }
501
+ return;
502
+ }
476
503
  onReplace( content, content.length - 1, -1 );
477
504
  } else {
505
+ if ( canPasteEmbed ) {
506
+ onChange(
507
+ insert( value, create( { text: plainText } ) )
508
+ );
509
+ return;
510
+ }
478
511
  splitValue( value, content );
479
512
  }
480
513
  }
@@ -650,6 +683,7 @@ function RichTextWrapper(
650
683
  />
651
684
  ) }
652
685
  </Autocomplete>
686
+ <EmbedHandlerPicker ref={ embedHandlerPickerRef } />
653
687
  </>
654
688
  ) }
655
689
  </RichText>
@@ -21,6 +21,25 @@ import { filePasteHandler } from './file-paste-handler';
21
21
  import { addActiveFormats, isShortcode } from './utils';
22
22
  import { splitValue } from './split-value';
23
23
 
24
+ /** @typedef {import('@wordpress/rich-text').RichTextValue} RichTextValue */
25
+
26
+ /**
27
+ * Replaces line separators with line breaks if not multiline.
28
+ * Replaces line breaks with line separators if multiline.
29
+ *
30
+ * @param {RichTextValue} value Value to adjust.
31
+ * @param {boolean} isMultiline Whether to adjust to multiline or not.
32
+ *
33
+ * @return {RichTextValue} Adjusted value.
34
+ */
35
+ function adjustLines( value, isMultiline ) {
36
+ if ( isMultiline ) {
37
+ return replace( value, /\n+/g, LINE_SEPARATOR );
38
+ }
39
+
40
+ return replace( value, new RegExp( LINE_SEPARATOR, 'g' ), '\n' );
41
+ }
42
+
24
43
  export function usePasteHandler( props ) {
25
44
  const propsRef = useRef( props );
26
45
  propsRef.current = props;
@@ -110,13 +129,19 @@ export function usePasteHandler( props ) {
110
129
  // without filtering the data. The filters are only meant for externally
111
130
  // pasted content and remove inline styles.
112
131
  if ( isInternal ) {
113
- const pastedValue = create( {
132
+ const pastedMultilineTag =
133
+ clipboardData.getData( 'rich-text-multi-line-tag' ) ||
134
+ undefined;
135
+ let pastedValue = create( {
114
136
  html,
115
- multilineTag,
137
+ multilineTag: pastedMultilineTag,
116
138
  multilineWrapperTags:
117
- multilineTag === 'li' ? [ 'ul', 'ol' ] : undefined,
139
+ pastedMultilineTag === 'li'
140
+ ? [ 'ul', 'ol' ]
141
+ : undefined,
118
142
  preserveWhiteSpace,
119
143
  } );
144
+ pastedValue = adjustLines( pastedValue, !! multilineTag );
120
145
  addActiveFormats( pastedValue, value.activeFormats );
121
146
  onChange( insert( value, pastedValue ) );
122
147
  return;
@@ -190,18 +215,11 @@ export function usePasteHandler( props ) {
190
215
  if ( typeof content === 'string' ) {
191
216
  let valueToInsert = create( { html: content } );
192
217
 
193
- addActiveFormats( valueToInsert, value.activeFormats );
194
-
195
218
  // If the content should be multiline, we should process text
196
219
  // separated by a line break as separate lines.
197
- if ( multilineTag ) {
198
- valueToInsert = replace(
199
- valueToInsert,
200
- /\n+/g,
201
- LINE_SEPARATOR
202
- );
203
- }
220
+ valueToInsert = adjustLines( valueToInsert, !! multilineTag );
204
221
 
222
+ addActiveFormats( valueToInsert, value.activeFormats );
205
223
  onChange( insert( value, valueToInsert ) );
206
224
  } else if ( content.length > 0 ) {
207
225
  if ( onReplace && isEmpty( value ) ) {
@@ -3,6 +3,8 @@
3
3
  */
4
4
  import { regexp } from '@wordpress/shortcode';
5
5
  import deprecated from '@wordpress/deprecated';
6
+ import { renderToString } from '@wordpress/element';
7
+ import { createBlock } from '@wordpress/blocks';
6
8
 
7
9
  export function addActiveFormats( value, activeFormats ) {
8
10
  if ( activeFormats?.length ) {
@@ -60,3 +62,17 @@ export function getAllowedFormats( {
60
62
  getAllowedFormats.EMPTY_ARRAY = [];
61
63
 
62
64
  export const isShortcode = ( text ) => regexp( '.*' ).test( text );
65
+
66
+ /**
67
+ * Creates a link from pasted URL.
68
+ * Creates a paragraph block containing a link to the URL, and calls `onReplace`.
69
+ *
70
+ * @param {string} url The URL that could not be embedded.
71
+ * @param {Function} onReplace Function to call with the created fallback block.
72
+ */
73
+ export function createLinkInParagraph( url, onReplace ) {
74
+ const link = <a href={ url }>{ url }</a>;
75
+ onReplace(
76
+ createBlock( 'core/paragraph', { content: renderToString( link ) } )
77
+ );
78
+ }
@@ -0,0 +1,39 @@
1
+ # SkipToSelectedBlock
2
+
3
+ `SkipToSelectedBlock` provides a way for keyboard and assistive technologies users to jump back to the currently selected block.
4
+
5
+ The component renders as a visually hidden, secondary button with the text, 'Skip to the selected block'. When clicked it will set [focus](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/focus) on the currently selected block. This means that the currently selected block will now receive all keyboard and similar events by default until focus is moved elsewhere.
6
+
7
+ If there are multiple blocks selected, the focus will be set on the block that was selected first.
8
+
9
+ ## Usage
10
+
11
+ Render a `<SkipToSelectedBlock />` component passing in the currently selected block's `clientId`.
12
+
13
+ ```jsx
14
+ function render( { clientId } ) {
15
+ return (
16
+ <div>
17
+ <SkipToSelectedBlock selectedBlockClientId={ clientId } />
18
+ </div>
19
+ );
20
+ }
21
+ ```
22
+
23
+ _Note:_
24
+
25
+ ## Props
26
+
27
+ ### `selectedBlockClientId`
28
+
29
+ - **Type:** `String`
30
+ - **Required** `true`
31
+ - **Default:** `undefined`
32
+
33
+ The `selectedBlockClientId` is passed to `useBlockRef` inside the component to correctly reference the currently selected block.
34
+
35
+ If a `clientId` is not provided, the component will return `null`.
36
+
37
+ ## Examples
38
+
39
+ This component is currently used in the [block inspector](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-editor/src/components/block-inspector) in the sidebar, at the bottom right corner of the screen.
@@ -63,7 +63,7 @@ export function getValidAlignments(
63
63
  );
64
64
  } else if ( blockAlign === true ) {
65
65
  // `true` includes all alignments...
66
- validAlignments = ALL_ALIGNMENTS;
66
+ validAlignments = [ ...ALL_ALIGNMENTS ];
67
67
  } else {
68
68
  validAlignments = [];
69
69
  }
@@ -117,15 +117,19 @@ export function addAttribute( settings ) {
117
117
  export const withToolbarControls = createHigherOrderComponent(
118
118
  ( BlockEdit ) => ( props ) => {
119
119
  const { name: blockName } = props;
120
- // Compute the block allowed alignments without taking into account,
121
- // if the theme supports wide alignments or not
122
- // and without checking the layout for availble alignments.
123
- // BlockAlignmentToolbar takes both of these into account.
120
+ // Compute the block valid alignments by taking into account,
121
+ // if the theme supports wide alignments or not and the layout's
122
+ // availble alignments. We do that for conditionally rendering
123
+ // Slot.
124
124
  const blockAllowedAlignments = getValidAlignments(
125
125
  getBlockSupport( blockName, 'align' ),
126
126
  hasBlockSupport( blockName, 'alignWide', true )
127
127
  );
128
128
 
129
+ const validAlignments = useAvailableAlignments(
130
+ blockAllowedAlignments
131
+ ).map( ( { name } ) => name );
132
+
129
133
  const updateAlignment = ( nextAlign ) => {
130
134
  if ( ! nextAlign ) {
131
135
  const blockType = getBlockType( props.name );
@@ -139,7 +143,7 @@ export const withToolbarControls = createHigherOrderComponent(
139
143
 
140
144
  return (
141
145
  <>
142
- { blockAllowedAlignments.length > 0 && (
146
+ { !! validAlignments.length && (
143
147
  <BlockControls
144
148
  group="block"
145
149
  __experimentalShareWithChildBlocks
@@ -147,7 +151,7 @@ export const withToolbarControls = createHigherOrderComponent(
147
151
  <BlockAlignmentControl
148
152
  value={ props.attributes.align }
149
153
  onChange={ updateAlignment }
150
- controls={ blockAllowedAlignments }
154
+ controls={ validAlignments }
151
155
  />
152
156
  </BlockControls>
153
157
  ) }
@@ -81,9 +81,9 @@ export const withInspectorControl = createHigherOrderComponent(
81
81
 
82
82
  { isWeb && (
83
83
  <ExternalLink
84
- href={
84
+ href={ __(
85
85
  'https://wordpress.org/support/article/page-jumps/'
86
- }
86
+ ) }
87
87
  >
88
88
  { __( 'Learn more about anchors' ) }
89
89
  </ExternalLink>
@@ -1,39 +1,111 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { find } from 'lodash';
4
+ import { find, kebabCase } from 'lodash';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
+ import { addFilter } from '@wordpress/hooks';
9
10
  import { hasBlockSupport } from '@wordpress/blocks';
11
+ import TokenList from '@wordpress/token-list';
10
12
 
11
13
  /**
12
14
  * Internal dependencies
13
15
  */
14
- import { cleanEmptyObject } from './utils';
15
16
  import useSetting from '../components/use-setting';
16
17
  import FontFamilyControl from '../components/font-family';
17
18
 
18
19
  export const FONT_FAMILY_SUPPORT_KEY = 'typography.__experimentalFontFamily';
19
20
 
20
- const getFontFamilyFromAttributeValue = ( fontFamilies, value ) => {
21
- const attributeParsed = /var:preset\|font-family\|(.+)/.exec( value );
22
- if ( attributeParsed && attributeParsed[ 1 ] ) {
23
- const fontFamilyObject = find( fontFamilies, ( { slug } ) => {
24
- return slug === attributeParsed[ 1 ];
21
+ /**
22
+ * Filters registered block settings, extending attributes to include
23
+ * the `fontFamily` attribute.
24
+ *
25
+ * @param {Object} settings Original block settings
26
+ * @return {Object} Filtered block settings
27
+ */
28
+ function addAttributes( settings ) {
29
+ if ( ! hasBlockSupport( settings, FONT_FAMILY_SUPPORT_KEY ) ) {
30
+ return settings;
31
+ }
32
+
33
+ // Allow blocks to specify a default value if needed.
34
+ if ( ! settings.attributes.fontFamily ) {
35
+ Object.assign( settings.attributes, {
36
+ fontFamily: {
37
+ type: 'string',
38
+ },
25
39
  } );
26
- if ( fontFamilyObject ) {
27
- return fontFamilyObject.fontFamily;
28
- }
29
40
  }
30
- return value;
31
- };
41
+
42
+ return settings;
43
+ }
44
+
45
+ /**
46
+ * Override props assigned to save component to inject font family.
47
+ *
48
+ * @param {Object} props Additional props applied to save element
49
+ * @param {Object} blockType Block type
50
+ * @param {Object} attributes Block attributes
51
+ * @return {Object} Filtered props applied to save element
52
+ */
53
+ function addSaveProps( props, blockType, attributes ) {
54
+ if ( ! hasBlockSupport( blockType, FONT_FAMILY_SUPPORT_KEY ) ) {
55
+ return props;
56
+ }
57
+
58
+ if (
59
+ hasBlockSupport(
60
+ blockType,
61
+ '__experimentalSkipTypographySerialization'
62
+ )
63
+ ) {
64
+ return props;
65
+ }
66
+
67
+ if ( ! attributes?.fontFamily ) {
68
+ return props;
69
+ }
70
+
71
+ // Use TokenList to dedupe classes.
72
+ const classes = new TokenList( props.className );
73
+ classes.add( `has-${ kebabCase( attributes?.fontFamily ) }-font-family` );
74
+ const newClassName = classes.value;
75
+ props.className = newClassName ? newClassName : undefined;
76
+
77
+ return props;
78
+ }
79
+
80
+ /**
81
+ * Filters registered block settings to expand the block edit wrapper
82
+ * by applying the desired styles and classnames.
83
+ *
84
+ * @param {Object} settings Original block settings.
85
+ *
86
+ * @return {Object} Filtered block settings.
87
+ */
88
+ function addEditProps( settings ) {
89
+ if ( ! hasBlockSupport( settings, FONT_FAMILY_SUPPORT_KEY ) ) {
90
+ return settings;
91
+ }
92
+
93
+ const existingGetEditWrapperProps = settings.getEditWrapperProps;
94
+ settings.getEditWrapperProps = ( attributes ) => {
95
+ let props = {};
96
+ if ( existingGetEditWrapperProps ) {
97
+ props = existingGetEditWrapperProps( attributes );
98
+ }
99
+ return addSaveProps( props, settings, attributes );
100
+ };
101
+
102
+ return settings;
103
+ }
32
104
 
33
105
  export function FontFamilyEdit( {
34
106
  name,
35
107
  setAttributes,
36
- attributes: { style = {} },
108
+ attributes: { fontFamily },
37
109
  } ) {
38
110
  const fontFamilies = useSetting( 'typography.fontFamilies' );
39
111
  const isDisable = useIsFontFamilyDisabled( { name } );
@@ -42,26 +114,16 @@ export function FontFamilyEdit( {
42
114
  return null;
43
115
  }
44
116
 
45
- const value = getFontFamilyFromAttributeValue(
46
- fontFamilies,
47
- style.typography?.fontFamily
48
- );
117
+ const value = find( fontFamilies, ( { slug } ) => fontFamily === slug )
118
+ ?.fontFamily;
49
119
 
50
120
  function onChange( newValue ) {
51
121
  const predefinedFontFamily = find(
52
122
  fontFamilies,
53
- ( { fontFamily } ) => fontFamily === newValue
123
+ ( { fontFamily: f } ) => f === newValue
54
124
  );
55
125
  setAttributes( {
56
- style: cleanEmptyObject( {
57
- ...style,
58
- typography: {
59
- ...( style.typography || {} ),
60
- fontFamily: predefinedFontFamily
61
- ? `var:preset|font-family|${ predefinedFontFamily.slug }`
62
- : newValue || undefined,
63
- },
64
- } ),
126
+ fontFamily: predefinedFontFamily?.slug,
65
127
  } );
66
128
  }
67
129
 
@@ -89,3 +151,21 @@ export function useIsFontFamilyDisabled( { name } ) {
89
151
  ! hasBlockSupport( name, FONT_FAMILY_SUPPORT_KEY )
90
152
  );
91
153
  }
154
+
155
+ addFilter(
156
+ 'blocks.registerBlockType',
157
+ 'core/fontFamily/addAttribute',
158
+ addAttributes
159
+ );
160
+
161
+ addFilter(
162
+ 'blocks.getSaveContent.extraProps',
163
+ 'core/fontFamily/addSaveProps',
164
+ addSaveProps
165
+ );
166
+
167
+ addFilter(
168
+ 'blocks.registerBlockType',
169
+ 'core/fontFamily/addEditProps',
170
+ addEditProps
171
+ );
@@ -18,6 +18,7 @@ import classnames from 'classnames';
18
18
  /**
19
19
  * WordPress dependencies
20
20
  */
21
+ import { useContext, createPortal } from '@wordpress/element';
21
22
  import { addFilter } from '@wordpress/hooks';
22
23
  import {
23
24
  getBlockSupport,
@@ -30,6 +31,7 @@ import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
30
31
  /**
31
32
  * Internal dependencies
32
33
  */
34
+ import BlockList from '../components/block-list';
33
35
  import { BORDER_SUPPORT_KEY, BorderPanel } from './border';
34
36
  import { COLOR_SUPPORT_KEY, ColorEdit } from './color';
35
37
  import {
@@ -262,9 +264,9 @@ export const withBlockControls = createHigherOrderComponent(
262
264
  <>
263
265
  { shouldDisplayControls && (
264
266
  <>
267
+ <ColorEdit { ...props } />
265
268
  <TypographyPanel { ...props } />
266
269
  <BorderPanel { ...props } />
267
- <ColorEdit { ...props } />
268
270
  <DimensionsPanel { ...props } />
269
271
  </>
270
272
  ) }
@@ -292,16 +294,20 @@ const withElementsStyles = createHigherOrderComponent(
292
294
  blockElementsContainerIdentifier,
293
295
  props.attributes.style?.elements
294
296
  );
297
+ const element = useContext( BlockList.__unstableElementContext );
295
298
 
296
299
  return (
297
300
  <>
298
- { elements && (
299
- <style
300
- dangerouslySetInnerHTML={ {
301
- __html: styles,
302
- } }
303
- />
304
- ) }
301
+ { elements &&
302
+ element &&
303
+ createPortal(
304
+ <style
305
+ dangerouslySetInnerHTML={ {
306
+ __html: styles,
307
+ } }
308
+ />,
309
+ element
310
+ ) }
305
311
 
306
312
  <BlockListBlock
307
313
  { ...props }
@@ -144,9 +144,12 @@ export default {
144
144
 
145
145
  if ( hasBlockGapStylesSupport ) {
146
146
  style += `
147
+ ${ appendSelectors( selector, '> *' ) } {
148
+ margin-top: 0;
149
+ margin-bottom: 0;
150
+ }
147
151
  ${ appendSelectors( selector, '> * + *' ) } {
148
152
  margin-top: var( --wp--style--block-gap );
149
- margin-bottom: 0;
150
153
  }
151
154
  `;
152
155
  }