@wordpress/block-editor 9.6.0 → 9.7.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 (191) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/block-list/block.js +12 -2
  3. package/build/components/block-list/block.js.map +1 -1
  4. package/build/components/block-list/index.native.js +1 -1
  5. package/build/components/block-list/index.native.js.map +1 -1
  6. package/build/components/block-popover/inbetween.js +1 -1
  7. package/build/components/block-popover/inbetween.js.map +1 -1
  8. package/build/components/block-styles/index.js +3 -6
  9. package/build/components/block-styles/index.js.map +1 -1
  10. package/build/components/block-types-list/index.js +1 -1
  11. package/build/components/block-types-list/index.js.map +1 -1
  12. package/build/components/border-radius-control/index.js +3 -1
  13. package/build/components/border-radius-control/index.js.map +1 -1
  14. package/build/components/colors/utils.js +6 -2
  15. package/build/components/colors/utils.js.map +1 -1
  16. package/build/components/colors-gradients/control.js +7 -4
  17. package/build/components/colors-gradients/control.js.map +1 -1
  18. package/build/components/colors-gradients/dropdown.js +5 -2
  19. package/build/components/colors-gradients/dropdown.js.map +1 -1
  20. package/build/components/font-appearance-control/index.js +10 -4
  21. package/build/components/font-appearance-control/index.js.map +1 -1
  22. package/build/components/image-size-control/index.js +3 -1
  23. package/build/components/image-size-control/index.js.map +1 -1
  24. package/build/components/index.js +13 -6
  25. package/build/components/index.js.map +1 -1
  26. package/build/components/index.native.js +11 -4
  27. package/build/components/index.native.js.map +1 -1
  28. package/build/components/inserter/index.native.js +8 -3
  29. package/build/components/inserter/index.native.js.map +1 -1
  30. package/build/components/inserter-list-item/index.js +2 -19
  31. package/build/components/inserter-list-item/index.js.map +1 -1
  32. package/build/components/letter-spacing-control/index.js +6 -3
  33. package/build/components/letter-spacing-control/index.js.map +1 -1
  34. package/build/components/line-height-control/index.js +6 -3
  35. package/build/components/line-height-control/index.js.map +1 -1
  36. package/build/components/link-control/is-url-like.js +1 -7
  37. package/build/components/link-control/is-url-like.js.map +1 -1
  38. package/build/components/link-control/use-search-handler.js +1 -7
  39. package/build/components/link-control/use-search-handler.js.map +1 -1
  40. package/build/components/list-view/expander.js +3 -1
  41. package/build/components/list-view/expander.js.map +1 -1
  42. package/build/components/media-upload/index.native.js +8 -3
  43. package/build/components/media-upload/index.native.js.map +1 -1
  44. package/build/components/preview-options/index.js +2 -2
  45. package/build/components/preview-options/index.js.map +1 -1
  46. package/build/components/{use-no-recursive-renders → recursion-provider}/index.js +40 -18
  47. package/build/components/recursion-provider/index.js.map +1 -0
  48. package/build/components/rich-text/index.js +6 -1
  49. package/build/components/rich-text/index.js.map +1 -1
  50. package/build/components/rich-text/index.native.js +3 -1
  51. package/build/components/rich-text/index.native.js.map +1 -1
  52. package/build/components/rich-text/use-before-input-rules.js +110 -0
  53. package/build/components/rich-text/use-before-input-rules.js.map +1 -0
  54. package/build/components/text-decoration-control/index.js +3 -1
  55. package/build/components/text-decoration-control/index.js.map +1 -1
  56. package/build/components/text-transform-control/index.js +3 -1
  57. package/build/components/text-transform-control/index.js.map +1 -1
  58. package/build/components/url-popover/image-url-input-ui.js +4 -1
  59. package/build/components/url-popover/image-url-input-ui.js.map +1 -1
  60. package/build/components/writing-flow/use-arrow-nav.js +4 -25
  61. package/build/components/writing-flow/use-arrow-nav.js.map +1 -1
  62. package/build/components/writing-flow/use-drag-selection.js +9 -2
  63. package/build/components/writing-flow/use-drag-selection.js.map +1 -1
  64. package/build/components/writing-flow/use-select-all.js +3 -1
  65. package/build/components/writing-flow/use-select-all.js.map +1 -1
  66. package/build/hooks/layout.js +9 -2
  67. package/build/hooks/layout.js.map +1 -1
  68. package/build/utils/block-variation-transforms.js +15 -9
  69. package/build/utils/block-variation-transforms.js.map +1 -1
  70. package/build/utils/pasting.js +9 -1
  71. package/build/utils/pasting.js.map +1 -1
  72. package/build-module/components/block-list/block.js +13 -3
  73. package/build-module/components/block-list/block.js.map +1 -1
  74. package/build-module/components/block-list/index.native.js +1 -1
  75. package/build-module/components/block-list/index.native.js.map +1 -1
  76. package/build-module/components/block-popover/inbetween.js +1 -1
  77. package/build-module/components/block-popover/inbetween.js.map +1 -1
  78. package/build-module/components/block-styles/index.js +4 -7
  79. package/build-module/components/block-styles/index.js.map +1 -1
  80. package/build-module/components/block-types-list/index.js +1 -1
  81. package/build-module/components/block-types-list/index.js.map +1 -1
  82. package/build-module/components/border-radius-control/index.js +4 -2
  83. package/build-module/components/border-radius-control/index.js.map +1 -1
  84. package/build-module/components/colors/utils.js +7 -3
  85. package/build-module/components/colors/utils.js.map +1 -1
  86. package/build-module/components/colors-gradients/control.js +7 -4
  87. package/build-module/components/colors-gradients/control.js.map +1 -1
  88. package/build-module/components/colors-gradients/dropdown.js +5 -2
  89. package/build-module/components/colors-gradients/dropdown.js.map +1 -1
  90. package/build-module/components/font-appearance-control/index.js +7 -4
  91. package/build-module/components/font-appearance-control/index.js.map +1 -1
  92. package/build-module/components/image-size-control/index.js +3 -1
  93. package/build-module/components/image-size-control/index.js.map +1 -1
  94. package/build-module/components/index.js +1 -1
  95. package/build-module/components/index.js.map +1 -1
  96. package/build-module/components/index.native.js +1 -1
  97. package/build-module/components/index.native.js.map +1 -1
  98. package/build-module/components/inserter/index.native.js +9 -2
  99. package/build-module/components/inserter/index.native.js.map +1 -1
  100. package/build-module/components/inserter-list-item/index.js +1 -17
  101. package/build-module/components/inserter-list-item/index.js.map +1 -1
  102. package/build-module/components/letter-spacing-control/index.js +5 -3
  103. package/build-module/components/letter-spacing-control/index.js.map +1 -1
  104. package/build-module/components/line-height-control/index.js +5 -3
  105. package/build-module/components/line-height-control/index.js.map +1 -1
  106. package/build-module/components/link-control/is-url-like.js +1 -6
  107. package/build-module/components/link-control/is-url-like.js.map +1 -1
  108. package/build-module/components/link-control/use-search-handler.js +1 -6
  109. package/build-module/components/link-control/use-search-handler.js.map +1 -1
  110. package/build-module/components/list-view/expander.js +3 -2
  111. package/build-module/components/list-view/expander.js.map +1 -1
  112. package/build-module/components/media-upload/index.native.js +9 -2
  113. package/build-module/components/media-upload/index.native.js.map +1 -1
  114. package/build-module/components/preview-options/index.js +2 -2
  115. package/build-module/components/preview-options/index.js.map +1 -1
  116. package/build-module/components/{use-no-recursive-renders → recursion-provider}/index.js +39 -19
  117. package/build-module/components/recursion-provider/index.js.map +1 -0
  118. package/build-module/components/rich-text/index.js +5 -1
  119. package/build-module/components/rich-text/index.js.map +1 -1
  120. package/build-module/components/rich-text/index.native.js +3 -1
  121. package/build-module/components/rich-text/index.native.js.map +1 -1
  122. package/build-module/components/rich-text/use-before-input-rules.js +96 -0
  123. package/build-module/components/rich-text/use-before-input-rules.js.map +1 -0
  124. package/build-module/components/text-decoration-control/index.js +4 -2
  125. package/build-module/components/text-decoration-control/index.js.map +1 -1
  126. package/build-module/components/text-transform-control/index.js +4 -2
  127. package/build-module/components/text-transform-control/index.js.map +1 -1
  128. package/build-module/components/url-popover/image-url-input-ui.js +4 -1
  129. package/build-module/components/url-popover/image-url-input-ui.js.map +1 -1
  130. package/build-module/components/writing-flow/use-arrow-nav.js +5 -26
  131. package/build-module/components/writing-flow/use-arrow-nav.js.map +1 -1
  132. package/build-module/components/writing-flow/use-drag-selection.js +9 -2
  133. package/build-module/components/writing-flow/use-drag-selection.js.map +1 -1
  134. package/build-module/components/writing-flow/use-select-all.js +3 -1
  135. package/build-module/components/writing-flow/use-select-all.js.map +1 -1
  136. package/build-module/hooks/layout.js +9 -2
  137. package/build-module/hooks/layout.js.map +1 -1
  138. package/build-module/utils/block-variation-transforms.js +14 -7
  139. package/build-module/utils/block-variation-transforms.js.map +1 -1
  140. package/build-module/utils/pasting.js +9 -1
  141. package/build-module/utils/pasting.js.map +1 -1
  142. package/build-style/style-rtl.css +39 -7
  143. package/build-style/style.css +39 -7
  144. package/package.json +28 -28
  145. package/src/components/block-list/block.js +13 -2
  146. package/src/components/block-list/index.native.js +1 -1
  147. package/src/components/block-popover/inbetween.js +1 -0
  148. package/src/components/block-popover/style.scss +25 -2
  149. package/src/components/block-styles/index.js +4 -7
  150. package/src/components/block-styles/style.scss +10 -0
  151. package/src/components/block-types-list/index.js +1 -1
  152. package/src/components/border-radius-control/index.js +4 -1
  153. package/src/components/color-palette/test/__snapshots__/control.js.snap +93 -77
  154. package/src/components/colors/utils.js +5 -2
  155. package/src/components/colors-gradients/control.js +12 -8
  156. package/src/components/colors-gradients/dropdown.js +7 -2
  157. package/src/components/colors-gradients/style.scss +27 -5
  158. package/src/components/colors-gradients/test/control.js +3 -3
  159. package/src/components/font-appearance-control/index.js +3 -0
  160. package/src/components/image-size-control/README.md +7 -0
  161. package/src/components/image-size-control/index.js +2 -0
  162. package/src/components/index.js +4 -1
  163. package/src/components/index.native.js +4 -1
  164. package/src/components/inserter/index.native.js +7 -2
  165. package/src/components/inserter-list-item/index.js +1 -17
  166. package/src/components/letter-spacing-control/index.js +2 -0
  167. package/src/components/line-height-control/index.js +2 -0
  168. package/src/components/link-control/is-url-like.js +1 -6
  169. package/src/components/link-control/use-search-handler.js +1 -6
  170. package/src/components/list-view/expander.js +4 -2
  171. package/src/components/media-upload/index.native.js +7 -3
  172. package/src/components/preview-options/index.js +2 -2
  173. package/src/components/{use-no-recursive-renders → recursion-provider}/index.js +39 -28
  174. package/src/components/{use-no-recursive-renders/test/use-no-recursive-renders.js → recursion-provider/test/index.js} +5 -6
  175. package/src/components/rich-text/README.md +13 -1
  176. package/src/components/rich-text/index.js +2 -0
  177. package/src/components/rich-text/index.native.js +2 -0
  178. package/src/components/rich-text/use-before-input-rules.js +91 -0
  179. package/src/components/text-decoration-control/index.js +4 -2
  180. package/src/components/text-transform-control/index.js +4 -2
  181. package/src/components/url-popover/image-url-input-ui.js +3 -0
  182. package/src/components/writing-flow/use-arrow-nav.js +4 -33
  183. package/src/components/writing-flow/use-drag-selection.js +7 -1
  184. package/src/components/writing-flow/use-select-all.js +2 -1
  185. package/src/hooks/layout.js +8 -2
  186. package/src/utils/block-variation-transforms.js +13 -6
  187. package/src/utils/pasting.js +10 -1
  188. package/src/utils/test/block-variation-transforms.js +24 -0
  189. package/src/utils/test/pasting.js +10 -0
  190. package/build/components/use-no-recursive-renders/index.js.map +0 -1
  191. package/build-module/components/use-no-recursive-renders/index.js.map +0 -1
@@ -33,10 +33,10 @@ export default function PreviewOptions( {
33
33
  className: 'block-editor-post-preview__button-toggle',
34
34
  disabled: ! isEnabled,
35
35
  /* translators: button label text should, if possible, be under 16 characters. */
36
- children: __( 'Preview' ),
36
+ children: __( 'View' ),
37
37
  };
38
38
  const menuProps = {
39
- 'aria-label': __( 'Preview options' ),
39
+ 'aria-label': __( 'View options' ),
40
40
  };
41
41
  return (
42
42
  <DropdownMenu
@@ -1,12 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import {
5
- createContext,
6
- useCallback,
7
- useContext,
8
- useMemo,
9
- } from '@wordpress/element';
4
+ import { createContext, useContext, useMemo } from '@wordpress/element';
10
5
 
11
6
  /**
12
7
  * Internal dependencies
@@ -37,37 +32,53 @@ function addToBlockType( renderedBlocks, blockName, uniqueId ) {
37
32
  }
38
33
 
39
34
  /**
40
- * A React hook for keeping track of blocks previously rendered up in the block
41
- * tree. Blocks susceptible to recursion can use this hook in their `Edit`
42
- * function to prevent said recursion.
35
+ * A React context provider for use with the `useHasRecursion` hook to prevent recursive
36
+ * renders.
43
37
  *
44
- * @param {*} uniqueId Any value that acts as a unique identifier for a block instance.
45
- * @param {string} blockName Optional block name.
38
+ * Wrap block content with this provider and provide the same `uniqueId` prop as used
39
+ * with `useHasRecursion`.
40
+ *
41
+ * @param {Object} props
42
+ * @param {*} props.uniqueId Any value that acts as a unique identifier for a block instance.
43
+ * @param {string} props.blockName Optional block name.
44
+ * @param {JSX.Element} props.children React children.
46
45
  *
47
- * @return {[boolean, Function]} A tuple of:
48
- * - a boolean describing whether the provided id
49
- * has already been rendered;
50
- * - a React context provider to be used to wrap
51
- * other elements.
46
+ * @return {JSX.Element} A React element.
52
47
  */
53
- export default function useNoRecursiveRenders( uniqueId, blockName = '' ) {
48
+ export function RecursionProvider( { children, uniqueId, blockName = '' } ) {
54
49
  const previouslyRenderedBlocks = useContext( RenderedRefsContext );
55
50
  const { name } = useBlockEditContext();
51
+
56
52
  blockName = blockName || name;
57
- const hasAlreadyRendered = Boolean(
58
- previouslyRenderedBlocks[ blockName ]?.has( uniqueId )
59
- );
53
+
60
54
  const newRenderedBlocks = useMemo(
61
55
  () => addToBlockType( previouslyRenderedBlocks, blockName, uniqueId ),
62
56
  [ previouslyRenderedBlocks, blockName, uniqueId ]
63
57
  );
64
- const Provider = useCallback(
65
- ( { children } ) => (
66
- <RenderedRefsContext.Provider value={ newRenderedBlocks }>
67
- { children }
68
- </RenderedRefsContext.Provider>
69
- ),
70
- [ newRenderedBlocks ]
58
+
59
+ return (
60
+ <RenderedRefsContext.Provider value={ newRenderedBlocks }>
61
+ { children }
62
+ </RenderedRefsContext.Provider>
71
63
  );
72
- return [ hasAlreadyRendered, Provider ];
64
+ }
65
+
66
+ /**
67
+ * A React hook for keeping track of blocks previously rendered up in the block
68
+ * tree. Blocks susceptible to recursion can use this hook in their `Edit`
69
+ * function to prevent said recursion.
70
+ *
71
+ * Use this with the `RecursionProvider` component, using the same `uniqueId` value
72
+ * for both the hook and the provider.
73
+ *
74
+ * @param {*} uniqueId Any value that acts as a unique identifier for a block instance.
75
+ * @param {string} blockName Optional block name.
76
+ *
77
+ * @return {boolean} A boolean describing whether the provided id has already been rendered.
78
+ */
79
+ export function useHasRecursion( uniqueId, blockName = '' ) {
80
+ const previouslyRenderedBlocks = useContext( RenderedRefsContext );
81
+ const { name } = useBlockEditContext();
82
+ blockName = blockName || name;
83
+ return Boolean( previouslyRenderedBlocks[ blockName ]?.has( uniqueId ) );
73
84
  }
@@ -6,7 +6,7 @@ import { render } from '@testing-library/react';
6
6
  /**
7
7
  * Internal dependencies
8
8
  */
9
- import useNoRecursiveRenders from '../';
9
+ import { useHasRecursion, RecursionProvider } from '..';
10
10
  import {
11
11
  BlockEditContextProvider,
12
12
  useBlockEditContext,
@@ -16,15 +16,14 @@ import {
16
16
  // of calling itself depending on its `uniqueId` attribute.
17
17
  function Edit( { attributes: { uniqueId } } ) {
18
18
  const { name } = useBlockEditContext();
19
- const [ hasAlreadyRendered, RecursionProvider ] =
20
- useNoRecursiveRenders( uniqueId );
19
+ const hasRecursion = useHasRecursion( uniqueId );
21
20
 
22
- if ( hasAlreadyRendered ) {
21
+ if ( hasRecursion ) {
23
22
  return <div className={ `wp-block__${ name }--halted` }>Halt</div>;
24
23
  }
25
24
 
26
25
  return (
27
- <RecursionProvider>
26
+ <RecursionProvider uniqueId={ uniqueId }>
28
27
  <div className={ `wp-block__${ name }` }>
29
28
  { uniqueId === 'SIMPLE' && <p>Done</p> }
30
29
  { uniqueId === 'SINGLY-RECURSIVE' && (
@@ -48,7 +47,7 @@ function Edit( { attributes: { uniqueId } } ) {
48
47
  );
49
48
  }
50
49
 
51
- describe( 'useNoRecursiveRenders', () => {
50
+ describe( 'useHasRecursion/RecursionProvider', () => {
52
51
  const context = { name: 'reusable-block' };
53
52
 
54
53
  it( 'allows a single block to render', () => {
@@ -43,7 +43,19 @@ _Optional._ Called when the block can be removed. `forward` is true when the sel
43
43
 
44
44
  ### `allowedFormats: Array`
45
45
 
46
- _Optional._ By default, all registered formats are allowed. This setting can be used to fine-tune the allowed formats. Example: `[ 'core/bold', 'core/link' ]`.
46
+ _Optional._ By default, all registered formats are allowed. This setting can be used to fine-tune the allowed formats. If you want to limit the formats allowed, you can specify using allowedFormats property in your code. If you want to allow only bold and italic settings, then you need to pass it in array. Example: `[ 'core/bold', 'core/link' ]`.
47
+
48
+ {% ESNext %}
49
+
50
+ ```js
51
+ <RichText
52
+ tagName="h2"
53
+ value={ attributes.content }
54
+ allowedFormats={ [ 'core/bold', 'core/italic' ] } // Allow the content to be made bold or italic, but do not allow othe formatting options
55
+ onChange={ ( content ) => setAttributes( { content } ) }
56
+ placeholder={ __( 'Heading...' ) }
57
+ />
58
+ ```
47
59
 
48
60
  ### `withoutInteractiveFormatting: Boolean`
49
61
 
@@ -38,6 +38,7 @@ import { store as blockEditorStore } from '../../store';
38
38
  import { useUndoAutomaticChange } from './use-undo-automatic-change';
39
39
  import { useMarkPersistent } from './use-mark-persistent';
40
40
  import { usePasteHandler } from './use-paste-handler';
41
+ import { useBeforeInputRules } from './use-before-input-rules';
41
42
  import { useInputRules } from './use-input-rules';
42
43
  import { useEnter } from './use-enter';
43
44
  import { useFormatTypes } from './use-format-types';
@@ -359,6 +360,7 @@ function RichTextWrapper(
359
360
  autocompleteProps.ref,
360
361
  props.ref,
361
362
  richTextRef,
363
+ useBeforeInputRules( { value, onChange } ),
362
364
  useInputRules( {
363
365
  value,
364
366
  onChange,
@@ -113,6 +113,7 @@ function RichTextWrapper(
113
113
  setRef,
114
114
  disableSuggestions,
115
115
  disableAutocorrection,
116
+ containerWidth,
116
117
  ...props
117
118
  },
118
119
  forwardedRef
@@ -639,6 +640,7 @@ function RichTextWrapper(
639
640
  setRef={ setRef }
640
641
  disableSuggestions={ disableSuggestions }
641
642
  disableAutocorrection={ disableAutocorrection }
643
+ containerWidth={ containerWidth }
642
644
  // Props to be set on the editable container are destructured on the
643
645
  // element itself for web (see below), but passed through rich text
644
646
  // for native.
@@ -0,0 +1,91 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useRef } from '@wordpress/element';
5
+ import { useRefEffect } from '@wordpress/compose';
6
+ import { insert, isCollapsed } from '@wordpress/rich-text';
7
+ import { useDispatch } from '@wordpress/data';
8
+ import { applyFilters } from '@wordpress/hooks';
9
+
10
+ /**
11
+ * Internal dependencies
12
+ */
13
+ import { store as blockEditorStore } from '../../store';
14
+
15
+ /**
16
+ * When typing over a selection, the selection will we wrapped by a matching
17
+ * character pair. The second character is optional, it defaults to the first
18
+ * character.
19
+ *
20
+ * @type {string[]} Array of character pairs.
21
+ */
22
+ const wrapSelectionSettings = [ '`', '"', "'", '“”', '‘’' ];
23
+
24
+ export function useBeforeInputRules( props ) {
25
+ const {
26
+ __unstableMarkLastChangeAsPersistent,
27
+ __unstableMarkAutomaticChange,
28
+ } = useDispatch( blockEditorStore );
29
+ const propsRef = useRef( props );
30
+ propsRef.current = props;
31
+ return useRefEffect( ( element ) => {
32
+ function onInput( event ) {
33
+ const { inputType, data } = event;
34
+ const { value, onChange } = propsRef.current;
35
+
36
+ // Only run the rules when inserting text.
37
+ if ( inputType !== 'insertText' ) {
38
+ return;
39
+ }
40
+
41
+ if ( isCollapsed( value ) ) {
42
+ return;
43
+ }
44
+
45
+ const pair = applyFilters(
46
+ 'blockEditor.wrapSelectionSettings',
47
+ wrapSelectionSettings
48
+ ).find(
49
+ ( [ startChar, endChar ] ) =>
50
+ startChar === data || endChar === data
51
+ );
52
+
53
+ if ( ! pair ) {
54
+ return;
55
+ }
56
+
57
+ const [ startChar, endChar = startChar ] = pair;
58
+ const start = value.start;
59
+ const end = value.end + startChar.length;
60
+
61
+ let newValue = insert( value, startChar, start, start );
62
+ newValue = insert( newValue, endChar, end, end );
63
+
64
+ __unstableMarkLastChangeAsPersistent();
65
+ onChange( newValue );
66
+ __unstableMarkAutomaticChange();
67
+
68
+ const init = {};
69
+
70
+ for ( const key in event ) {
71
+ init[ key ] = event[ key ];
72
+ }
73
+
74
+ init.data = endChar;
75
+
76
+ const { ownerDocument } = element;
77
+ const { defaultView } = ownerDocument;
78
+ const newEvent = new defaultView.InputEvent( 'input', init );
79
+
80
+ // Dispatch an input event with the new data. This will trigger the
81
+ // input rules.
82
+ event.target.dispatchEvent( newEvent );
83
+ event.preventDefault();
84
+ }
85
+
86
+ element.addEventListener( 'beforeinput', onInput );
87
+ return () => {
88
+ element.removeEventListener( 'beforeinput', onInput );
89
+ };
90
+ }, [] );
91
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { Button } from '@wordpress/components';
4
+ import { BaseControl, Button } from '@wordpress/components';
5
5
  import { formatStrikethrough, formatUnderline } from '@wordpress/icons';
6
6
  import { __ } from '@wordpress/i18n';
7
7
 
@@ -30,7 +30,9 @@ const TEXT_DECORATIONS = [
30
30
  export default function TextDecorationControl( { value, onChange } ) {
31
31
  return (
32
32
  <fieldset className="block-editor-text-decoration-control">
33
- <legend>{ __( 'Decoration' ) }</legend>
33
+ <BaseControl.VisualLabel as="legend">
34
+ { __( 'Decoration' ) }
35
+ </BaseControl.VisualLabel>
34
36
  <div className="block-editor-text-decoration-control__buttons">
35
37
  { TEXT_DECORATIONS.map( ( textDecoration ) => {
36
38
  return (
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { Button } from '@wordpress/components';
4
+ import { BaseControl, Button } from '@wordpress/components';
5
5
  import { __ } from '@wordpress/i18n';
6
6
  import {
7
7
  formatCapitalize,
@@ -39,7 +39,9 @@ const TEXT_TRANSFORMS = [
39
39
  export default function TextTransformControl( { value, onChange } ) {
40
40
  return (
41
41
  <fieldset className="block-editor-text-transform-control">
42
- <legend>{ __( 'Letter case' ) }</legend>
42
+ <BaseControl.VisualLabel as="legend">
43
+ { __( 'Letter case' ) }
44
+ </BaseControl.VisualLabel>
43
45
  <div className="block-editor-text-transform-control__buttons">
44
46
  { TEXT_TRANSFORMS.map( ( textTransform ) => {
45
47
  return (
@@ -51,6 +51,7 @@ const ImageURLInputUI = ( {
51
51
  rel,
52
52
  } ) => {
53
53
  const [ isOpen, setIsOpen ] = useState( false );
54
+ const buttonRef = useRef( null );
54
55
  const openLinkUI = useCallback( () => {
55
56
  setIsOpen( true );
56
57
  } );
@@ -245,9 +246,11 @@ const ImageURLInputUI = ( {
245
246
  label={ url ? __( 'Edit link' ) : __( 'Insert link' ) }
246
247
  aria-expanded={ isOpen }
247
248
  onClick={ openLinkUI }
249
+ ref={ buttonRef }
248
250
  />
249
251
  { isOpen && (
250
252
  <URLPopover
253
+ anchorRef={ buttonRef }
251
254
  onFocusOutside={ onFocusOutside() }
252
255
  onClose={ closeLinkUI }
253
256
  renderSettings={ () => advancedOptions }
@@ -17,7 +17,7 @@ import { useRefEffect } from '@wordpress/compose';
17
17
  /**
18
18
  * Internal dependencies
19
19
  */
20
- import { isInSameBlock } from '../../utils/dom';
20
+ import { getBlockClientId } from '../../utils/dom';
21
21
  import { store as blockEditorStore } from '../../store';
22
22
 
23
23
  /**
@@ -130,11 +130,8 @@ export function getClosestTabbable(
130
130
 
131
131
  export default function useArrowNav() {
132
132
  const {
133
- getSelectedBlockClientId,
134
133
  getMultiSelectedBlocksStartClientId,
135
134
  getMultiSelectedBlocksEndClientId,
136
- getPreviousBlockClientId,
137
- getNextBlockClientId,
138
135
  getSettings,
139
136
  hasMultiSelection,
140
137
  __unstableIsFullySelected,
@@ -150,26 +147,13 @@ export default function useArrowNav() {
150
147
  verticalRect = null;
151
148
  }
152
149
 
153
- /**
154
- * Returns true if the given target field is the last in its block which
155
- * can be considered for tab transition. For example, in a block with
156
- * two text fields, this would return true when reversing from the first
157
- * of the two fields, but false when reversing from the second.
158
- *
159
- * @param {Element} target Currently focused text field.
160
- * @param {boolean} isReverse True if considering as the first field.
161
- *
162
- * @return {boolean} Whether field is at edge for tab transition.
163
- */
164
- function isTabbableEdge( target, isReverse ) {
150
+ function isClosestTabbableABlock( target, isReverse ) {
165
151
  const closestTabbable = getClosestTabbable(
166
152
  target,
167
153
  isReverse,
168
154
  node
169
155
  );
170
- return (
171
- ! closestTabbable || ! isInSameBlock( target, closestTabbable )
172
- );
156
+ return closestTabbable && getBlockClientId( closestTabbable );
173
157
  }
174
158
 
175
159
  function onKeyDown( event ) {
@@ -254,23 +238,10 @@ export default function useArrowNav() {
254
238
  // next, which is the exact reverse of LTR.
255
239
  const isReverseDir = isRTL( target ) ? ! isReverse : isReverse;
256
240
  const { keepCaretInsideBlock } = getSettings();
257
- const selectedBlockClientId = getSelectedBlockClientId();
258
241
 
259
242
  if ( isShift ) {
260
- const selectionEndClientId =
261
- getMultiSelectedBlocksEndClientId();
262
- const selectionBeforeEndClientId = getPreviousBlockClientId(
263
- selectionEndClientId || selectedBlockClientId
264
- );
265
- const selectionAfterEndClientId = getNextBlockClientId(
266
- selectionEndClientId || selectedBlockClientId
267
- );
268
-
269
243
  if (
270
- // Ensure that there is a target block.
271
- ( ( isReverse && selectionBeforeEndClientId ) ||
272
- ( ! isReverse && selectionAfterEndClientId ) ) &&
273
- isTabbableEdge( target, isReverse ) &&
244
+ isClosestTabbableABlock( target, isReverse ) &&
274
245
  isNavEdge( target, isReverse )
275
246
  ) {
276
247
  node.contentEditable = true;
@@ -27,7 +27,7 @@ function setContentEditableWrapper( node, value ) {
27
27
  export default function useDragSelection() {
28
28
  const { startMultiSelect, stopMultiSelect } =
29
29
  useDispatch( blockEditorStore );
30
- const { isSelectionEnabled, hasMultiSelection } =
30
+ const { isSelectionEnabled, hasMultiSelection, isDraggingBlocks } =
31
31
  useSelect( blockEditorStore );
32
32
  return useRefEffect(
33
33
  ( node ) => {
@@ -72,6 +72,12 @@ export default function useDragSelection() {
72
72
  }
73
73
 
74
74
  function onMouseLeave( { buttons, target } ) {
75
+ // Avoid triggering a multi-selection if the user is already
76
+ // dragging blocks.
77
+ if ( isDraggingBlocks() ) {
78
+ return;
79
+ }
80
+
75
81
  // The primary button must be pressed to initiate selection.
76
82
  // See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
77
83
  if ( buttons !== 1 ) {
@@ -19,7 +19,7 @@ import { store as blockEditorStore } from '../../store';
19
19
  export default function useSelectAll() {
20
20
  const { getBlockOrder, getSelectedBlockClientIds, getBlockRootClientId } =
21
21
  useSelect( blockEditorStore );
22
- const { multiSelect } = useDispatch( blockEditorStore );
22
+ const { multiSelect, selectBlock } = useDispatch( blockEditorStore );
23
23
  const isMatch = useShortcutEventMatch();
24
24
 
25
25
  return useRefEffect( ( node ) => {
@@ -53,6 +53,7 @@ export default function useSelectAll() {
53
53
  const lastClientId = last( blockClientIds );
54
54
 
55
55
  if ( firstClientId === lastClientId ) {
56
+ selectBlock( firstClientId );
56
57
  return;
57
58
  }
58
59
 
@@ -264,10 +264,16 @@ export const withInspectorControls = createHigherOrderComponent(
264
264
  export const withLayoutStyles = createHigherOrderComponent(
265
265
  ( BlockListBlock ) => ( props ) => {
266
266
  const { name, attributes } = props;
267
- const shouldRenderLayoutStyles = hasBlockSupport(
267
+ const hasLayoutBlockSupport = hasBlockSupport(
268
268
  name,
269
269
  layoutBlockSupportKey
270
270
  );
271
+ const disableLayoutStyles = useSelect( ( select ) => {
272
+ const { getSettings } = select( blockEditorStore );
273
+ return !! getSettings().disableLayoutStyles;
274
+ } );
275
+ const shouldRenderLayoutStyles =
276
+ hasLayoutBlockSupport && ! disableLayoutStyles;
271
277
  const id = useInstanceId( BlockListBlock );
272
278
  const defaultThemeLayout = useSetting( 'layout' ) || {};
273
279
  const element = useContext( BlockList.__unstableElementContext );
@@ -277,7 +283,7 @@ export const withLayoutStyles = createHigherOrderComponent(
277
283
  const usedLayout = layout?.inherit
278
284
  ? defaultThemeLayout
279
285
  : layout || defaultBlockLayout || {};
280
- const layoutClasses = shouldRenderLayoutStyles
286
+ const layoutClasses = hasLayoutBlockSupport
281
287
  ? useLayoutClasses( usedLayout, defaultThemeLayout?.definitions )
282
288
  : null;
283
289
  const selector = `.${ getBlockDefaultClassName(
@@ -1,10 +1,17 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { isMatch } from 'lodash';
5
-
6
1
  /** @typedef {import('@wordpress/blocks').WPBlockVariation} WPBlockVariation */
7
2
 
3
+ function matchesAttributes( blockAttributes, variation ) {
4
+ return Object.entries( variation ).every( ( [ key, value ] ) => {
5
+ if (
6
+ typeof value === 'object' &&
7
+ typeof blockAttributes[ key ] === 'object'
8
+ ) {
9
+ return matchesAttributes( blockAttributes[ key ], value );
10
+ }
11
+ return blockAttributes[ key ] === value;
12
+ } );
13
+ }
14
+
8
15
  /**
9
16
  * Matches the provided block variations with a block's attributes. If no match
10
17
  * or more than one matches are found it returns `undefined`. If a single match is
@@ -24,7 +31,7 @@ export const __experimentalGetMatchingVariation = (
24
31
  if ( ! variations || ! blockAttributes ) return;
25
32
  const matches = variations.filter( ( { attributes } ) => {
26
33
  if ( ! attributes || ! Object.keys( attributes ).length ) return false;
27
- return isMatch( blockAttributes, attributes );
34
+ return matchesAttributes( blockAttributes, attributes );
28
35
  } );
29
36
  if ( matches.length !== 1 ) return;
30
37
  return matches[ 0 ];
@@ -70,7 +70,16 @@ export function shouldDismissPastedFiles( files, html /*, plainText */ ) {
70
70
  // other elements found, like <figure>, but we assume that the user's
71
71
  // intention is to paste the actual image file.
72
72
  const IMAGE_TAG = /<\s*img\b/gi;
73
- return html.match( IMAGE_TAG )?.length !== 1;
73
+ if ( html.match( IMAGE_TAG )?.length !== 1 ) return true;
74
+
75
+ // Even when there is exactly one <img> tag in the HTML payload, we
76
+ // choose to weed out local images, i.e. those whose source starts with
77
+ // "file://". These payloads occur in specific configurations, such as
78
+ // when copying an entire document from Microsoft Word, that contains
79
+ // text and exactly one image, and pasting that content using Google
80
+ // Chrome.
81
+ const IMG_WITH_LOCAL_SRC = /<\s*img\b[^>]*\bsrc="file:\/\//i;
82
+ if ( html.match( IMG_WITH_LOCAL_SRC ) ) return true;
74
83
  }
75
84
 
76
85
  return false;
@@ -40,6 +40,18 @@ describe( 'getMatchingVariation', () => {
40
40
  getMatchingVariation( { level: 1, other: 'prop' }, variations )
41
41
  ).toBeUndefined();
42
42
  } );
43
+ it( 'when variation has a nested attribute', () => {
44
+ const variations = [
45
+ { name: 'one', attributes: { query: { author: 'somebody' } } },
46
+ { name: 'two', attributes: { query: { author: 'nobody' } } },
47
+ ];
48
+ expect(
49
+ getMatchingVariation(
50
+ { query: { author: 'foobar' }, other: 'prop' },
51
+ variations
52
+ )
53
+ ).toBeUndefined();
54
+ } );
43
55
  } );
44
56
  describe( 'should find a match', () => {
45
57
  it( 'when variation has one attribute', () => {
@@ -66,5 +78,17 @@ describe( 'getMatchingVariation', () => {
66
78
  ).name
67
79
  ).toEqual( 'one' );
68
80
  } );
81
+ it( 'when variation has a nested attribute', () => {
82
+ const variations = [
83
+ { name: 'one', attributes: { query: { author: 'somebody' } } },
84
+ { name: 'two', attributes: { query: { author: 'nobody' } } },
85
+ ];
86
+ expect(
87
+ getMatchingVariation(
88
+ { query: { author: 'somebody' }, other: 'prop' },
89
+ variations
90
+ ).name
91
+ ).toEqual( 'one' );
92
+ } );
69
93
  } );
70
94
  } );
@@ -81,4 +81,14 @@ describe( 'shouldDismissPastedFiles', () => {
81
81
  )
82
82
  ).toBe( true );
83
83
  } );
84
+
85
+ it( 'should return true when pasting an image-containing MS Word document via Chrome', () => {
86
+ expect(
87
+ shouldDismissPastedFiles(
88
+ [ mocks.pngImageFile ],
89
+ '<p>A</p><img src="file:////.../clip_image001.png" alt="..."><p>B</p>',
90
+ 'A\nB'
91
+ )
92
+ ).toBe( true );
93
+ } );
84
94
  } );
@@ -1 +0,0 @@
1
- {"version":3,"sources":["@wordpress/block-editor/src/components/use-no-recursive-renders/index.js"],"names":["RenderedRefsContext","addToBlockType","renderedBlocks","blockName","uniqueId","result","Set","add","useNoRecursiveRenders","previouslyRenderedBlocks","name","hasAlreadyRendered","Boolean","has","newRenderedBlocks","Provider","children"],"mappings":";;;;;;;AAGA;;AAUA;;AAbA;AACA;AACA;;AAQA;AACA;AACA;AAGA,MAAMA,mBAAmB,GAAG,4BAAe,EAAf,CAA5B;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,SAASC,cAAT,CAAyBC,cAAzB,EAAyCC,SAAzC,EAAoDC,QAApD,EAA+D;AAC9D,QAAMC,MAAM,GAAG,EACd,GAAGH,cADW;AAEd,KAAEC,SAAF,GAAeD,cAAc,CAAEC,SAAF,CAAd,GACZ,IAAIG,GAAJ,CAASJ,cAAc,CAAEC,SAAF,CAAvB,CADY,GAEZ,IAAIG,GAAJ;AAJW,GAAf;AAMAD,EAAAA,MAAM,CAAEF,SAAF,CAAN,CAAoBI,GAApB,CAAyBH,QAAzB;AAEA,SAAOC,MAAP;AACA;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACe,SAASG,qBAAT,CAAgCJ,QAAhC,EAA2D;AAAA;;AAAA,MAAjBD,SAAiB,uEAAL,EAAK;AACzE,QAAMM,wBAAwB,GAAG,yBAAYT,mBAAZ,CAAjC;AACA,QAAM;AAAEU,IAAAA;AAAF,MAAW,mCAAjB;AACAP,EAAAA,SAAS,GAAGA,SAAS,IAAIO,IAAzB;AACA,QAAMC,kBAAkB,GAAGC,OAAO,0BACjCH,wBAAwB,CAAEN,SAAF,CADS,0DACjC,sBAAuCU,GAAvC,CAA4CT,QAA5C,CADiC,CAAlC;AAGA,QAAMU,iBAAiB,GAAG,sBACzB,MAAMb,cAAc,CAAEQ,wBAAF,EAA4BN,SAA5B,EAAuCC,QAAvC,CADK,EAEzB,CAAEK,wBAAF,EAA4BN,SAA5B,EAAuCC,QAAvC,CAFyB,CAA1B;AAIA,QAAMW,QAAQ,GAAG,0BAChB;AAAA,QAAE;AAAEC,MAAAA;AAAF,KAAF;AAAA,WACC,4BAAC,mBAAD,CAAqB,QAArB;AAA8B,MAAA,KAAK,EAAGF;AAAtC,OACGE,QADH,CADD;AAAA,GADgB,EAMhB,CAAEF,iBAAF,CANgB,CAAjB;AAQA,SAAO,CAAEH,kBAAF,EAAsBI,QAAtB,CAAP;AACA","sourcesContent":["/**\n * WordPress dependencies\n */\nimport {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseMemo,\n} from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { useBlockEditContext } from '../block-edit/context';\n\nconst RenderedRefsContext = createContext( {} );\n\n/**\n * Immutably adds an unique identifier to a set scoped for a given block type.\n *\n * @param {Object} renderedBlocks Rendered blocks grouped by block name\n * @param {string} blockName Name of the block.\n * @param {*} uniqueId Any value that acts as a unique identifier for a block instance.\n *\n * @return {Object} The list of rendered blocks grouped by block name.\n */\nfunction addToBlockType( renderedBlocks, blockName, uniqueId ) {\n\tconst result = {\n\t\t...renderedBlocks,\n\t\t[ blockName ]: renderedBlocks[ blockName ]\n\t\t\t? new Set( renderedBlocks[ blockName ] )\n\t\t\t: new Set(),\n\t};\n\tresult[ blockName ].add( uniqueId );\n\n\treturn result;\n}\n\n/**\n * A React hook for keeping track of blocks previously rendered up in the block\n * tree. Blocks susceptible to recursion can use this hook in their `Edit`\n * function to prevent said recursion.\n *\n * @param {*} uniqueId Any value that acts as a unique identifier for a block instance.\n * @param {string} blockName Optional block name.\n *\n * @return {[boolean, Function]} A tuple of:\n * - a boolean describing whether the provided id\n * has already been rendered;\n * - a React context provider to be used to wrap\n * other elements.\n */\nexport default function useNoRecursiveRenders( uniqueId, blockName = '' ) {\n\tconst previouslyRenderedBlocks = useContext( RenderedRefsContext );\n\tconst { name } = useBlockEditContext();\n\tblockName = blockName || name;\n\tconst hasAlreadyRendered = Boolean(\n\t\tpreviouslyRenderedBlocks[ blockName ]?.has( uniqueId )\n\t);\n\tconst newRenderedBlocks = useMemo(\n\t\t() => addToBlockType( previouslyRenderedBlocks, blockName, uniqueId ),\n\t\t[ previouslyRenderedBlocks, blockName, uniqueId ]\n\t);\n\tconst Provider = useCallback(\n\t\t( { children } ) => (\n\t\t\t<RenderedRefsContext.Provider value={ newRenderedBlocks }>\n\t\t\t\t{ children }\n\t\t\t</RenderedRefsContext.Provider>\n\t\t),\n\t\t[ newRenderedBlocks ]\n\t);\n\treturn [ hasAlreadyRendered, Provider ];\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["@wordpress/block-editor/src/components/use-no-recursive-renders/index.js"],"names":["createContext","useCallback","useContext","useMemo","useBlockEditContext","RenderedRefsContext","addToBlockType","renderedBlocks","blockName","uniqueId","result","Set","add","useNoRecursiveRenders","previouslyRenderedBlocks","name","hasAlreadyRendered","Boolean","has","newRenderedBlocks","Provider","children"],"mappings":";;AAAA;AACA;AACA;AACA,SACCA,aADD,EAECC,WAFD,EAGCC,UAHD,EAICC,OAJD,QAKO,oBALP;AAOA;AACA;AACA;;AACA,SAASC,mBAAT,QAAoC,uBAApC;AAEA,MAAMC,mBAAmB,GAAGL,aAAa,CAAE,EAAF,CAAzC;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,SAASM,cAAT,CAAyBC,cAAzB,EAAyCC,SAAzC,EAAoDC,QAApD,EAA+D;AAC9D,QAAMC,MAAM,GAAG,EACd,GAAGH,cADW;AAEd,KAAEC,SAAF,GAAeD,cAAc,CAAEC,SAAF,CAAd,GACZ,IAAIG,GAAJ,CAASJ,cAAc,CAAEC,SAAF,CAAvB,CADY,GAEZ,IAAIG,GAAJ;AAJW,GAAf;AAMAD,EAAAA,MAAM,CAAEF,SAAF,CAAN,CAAoBI,GAApB,CAAyBH,QAAzB;AAEA,SAAOC,MAAP;AACA;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA,eAAe,SAASG,qBAAT,CAAgCJ,QAAhC,EAA2D;AAAA;;AAAA,MAAjBD,SAAiB,uEAAL,EAAK;AACzE,QAAMM,wBAAwB,GAAGZ,UAAU,CAAEG,mBAAF,CAA3C;AACA,QAAM;AAAEU,IAAAA;AAAF,MAAWX,mBAAmB,EAApC;AACAI,EAAAA,SAAS,GAAGA,SAAS,IAAIO,IAAzB;AACA,QAAMC,kBAAkB,GAAGC,OAAO,0BACjCH,wBAAwB,CAAEN,SAAF,CADS,0DACjC,sBAAuCU,GAAvC,CAA4CT,QAA5C,CADiC,CAAlC;AAGA,QAAMU,iBAAiB,GAAGhB,OAAO,CAChC,MAAMG,cAAc,CAAEQ,wBAAF,EAA4BN,SAA5B,EAAuCC,QAAvC,CADY,EAEhC,CAAEK,wBAAF,EAA4BN,SAA5B,EAAuCC,QAAvC,CAFgC,CAAjC;AAIA,QAAMW,QAAQ,GAAGnB,WAAW,CAC3B;AAAA,QAAE;AAAEoB,MAAAA;AAAF,KAAF;AAAA,WACC,cAAC,mBAAD,CAAqB,QAArB;AAA8B,MAAA,KAAK,EAAGF;AAAtC,OACGE,QADH,CADD;AAAA,GAD2B,EAM3B,CAAEF,iBAAF,CAN2B,CAA5B;AAQA,SAAO,CAAEH,kBAAF,EAAsBI,QAAtB,CAAP;AACA","sourcesContent":["/**\n * WordPress dependencies\n */\nimport {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseMemo,\n} from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { useBlockEditContext } from '../block-edit/context';\n\nconst RenderedRefsContext = createContext( {} );\n\n/**\n * Immutably adds an unique identifier to a set scoped for a given block type.\n *\n * @param {Object} renderedBlocks Rendered blocks grouped by block name\n * @param {string} blockName Name of the block.\n * @param {*} uniqueId Any value that acts as a unique identifier for a block instance.\n *\n * @return {Object} The list of rendered blocks grouped by block name.\n */\nfunction addToBlockType( renderedBlocks, blockName, uniqueId ) {\n\tconst result = {\n\t\t...renderedBlocks,\n\t\t[ blockName ]: renderedBlocks[ blockName ]\n\t\t\t? new Set( renderedBlocks[ blockName ] )\n\t\t\t: new Set(),\n\t};\n\tresult[ blockName ].add( uniqueId );\n\n\treturn result;\n}\n\n/**\n * A React hook for keeping track of blocks previously rendered up in the block\n * tree. Blocks susceptible to recursion can use this hook in their `Edit`\n * function to prevent said recursion.\n *\n * @param {*} uniqueId Any value that acts as a unique identifier for a block instance.\n * @param {string} blockName Optional block name.\n *\n * @return {[boolean, Function]} A tuple of:\n * - a boolean describing whether the provided id\n * has already been rendered;\n * - a React context provider to be used to wrap\n * other elements.\n */\nexport default function useNoRecursiveRenders( uniqueId, blockName = '' ) {\n\tconst previouslyRenderedBlocks = useContext( RenderedRefsContext );\n\tconst { name } = useBlockEditContext();\n\tblockName = blockName || name;\n\tconst hasAlreadyRendered = Boolean(\n\t\tpreviouslyRenderedBlocks[ blockName ]?.has( uniqueId )\n\t);\n\tconst newRenderedBlocks = useMemo(\n\t\t() => addToBlockType( previouslyRenderedBlocks, blockName, uniqueId ),\n\t\t[ previouslyRenderedBlocks, blockName, uniqueId ]\n\t);\n\tconst Provider = useCallback(\n\t\t( { children } ) => (\n\t\t\t<RenderedRefsContext.Provider value={ newRenderedBlocks }>\n\t\t\t\t{ children }\n\t\t\t</RenderedRefsContext.Provider>\n\t\t),\n\t\t[ newRenderedBlocks ]\n\t);\n\treturn [ hasAlreadyRendered, Provider ];\n}\n"]}