@wordpress/block-editor 15.8.1-next.16d95556a.0 → 15.8.1-next.dc3f6d3c1.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 (169) hide show
  1. package/build/components/block-inspector/edit-contents.js +19 -23
  2. package/build/components/block-inspector/edit-contents.js.map +3 -3
  3. package/build/components/block-inspector/index.js +7 -1
  4. package/build/components/block-inspector/index.js.map +2 -2
  5. package/build/components/block-list/block.js +4 -0
  6. package/build/components/block-list/block.js.map +2 -2
  7. package/build/components/block-list/use-block-props/index.js +3 -1
  8. package/build/components/block-list/use-block-props/index.js.map +2 -2
  9. package/build/components/block-list/use-block-props/use-is-hovered.js +16 -10
  10. package/build/components/block-list/use-block-props/use-is-hovered.js.map +2 -2
  11. package/build/components/block-settings-menu-controls/edit-section-menu-item.js +64 -0
  12. package/build/components/block-settings-menu-controls/edit-section-menu-item.js.map +7 -0
  13. package/build/components/block-settings-menu-controls/index.js +8 -0
  14. package/build/components/block-settings-menu-controls/index.js.map +2 -2
  15. package/build/components/block-toolbar/block-toolbar-icon.js +9 -9
  16. package/build/components/block-toolbar/block-toolbar-icon.js.map +2 -2
  17. package/build/components/block-variation-transforms/index.js +32 -5
  18. package/build/components/block-variation-transforms/index.js.map +2 -2
  19. package/build/components/border-radius-control/single-input-control.js +1 -0
  20. package/build/components/border-radius-control/single-input-control.js.map +2 -2
  21. package/build/components/content-only-controls/index.js +263 -0
  22. package/build/components/content-only-controls/index.js.map +7 -0
  23. package/build/components/content-only-controls/link/index.js +204 -0
  24. package/build/components/content-only-controls/link/index.js.map +7 -0
  25. package/build/components/content-only-controls/media/index.js +264 -0
  26. package/build/components/content-only-controls/media/index.js.map +7 -0
  27. package/build/components/content-only-controls/plain-text/index.js +68 -0
  28. package/build/components/content-only-controls/plain-text/index.js.map +7 -0
  29. package/build/components/content-only-controls/rich-text/index.js +197 -0
  30. package/build/components/content-only-controls/rich-text/index.js.map +7 -0
  31. package/build/components/content-only-controls/use-inspector-popover-placement.js +41 -0
  32. package/build/components/content-only-controls/use-inspector-popover-placement.js.map +7 -0
  33. package/build/components/inserter/media-tab/media-tab.js +1 -33
  34. package/build/components/inserter/media-tab/media-tab.js.map +3 -3
  35. package/build/components/inspector-controls-tabs/content-tab.js +6 -2
  36. package/build/components/inspector-controls-tabs/content-tab.js.map +3 -3
  37. package/build/components/inspector-controls-tabs/index.js +7 -1
  38. package/build/components/inspector-controls-tabs/index.js.map +2 -2
  39. package/build/components/list-view/block-select-button.js +11 -4
  40. package/build/components/list-view/block-select-button.js.map +2 -2
  41. package/build/components/media-placeholder/index.js +1 -31
  42. package/build/components/media-placeholder/index.js.map +3 -3
  43. package/build/components/media-replace-flow/index.js +4 -30
  44. package/build/components/media-replace-flow/index.js.map +3 -3
  45. package/build/components/use-block-display-information/index.js +21 -1
  46. package/build/components/use-block-display-information/index.js.map +3 -3
  47. package/build/hooks/block-bindings.js +52 -61
  48. package/build/hooks/block-bindings.js.map +3 -3
  49. package/build/hooks/use-content-only-section-edit.js +67 -0
  50. package/build/hooks/use-content-only-section-edit.js.map +7 -0
  51. package/build/layouts/constrained.js +2 -2
  52. package/build/layouts/constrained.js.map +2 -2
  53. package/build/private-apis.js +2 -3
  54. package/build/private-apis.js.map +3 -3
  55. package/build/store/private-keys.js +3 -0
  56. package/build/store/private-keys.js.map +2 -2
  57. package/build/store/private-selectors.js +1 -2
  58. package/build/store/private-selectors.js.map +2 -2
  59. package/build/store/reducer.js +1 -2
  60. package/build/store/reducer.js.map +2 -2
  61. package/build/utils/fit-text-utils.js +9 -1
  62. package/build/utils/fit-text-utils.js.map +2 -2
  63. package/build-module/components/block-inspector/edit-contents.js +9 -23
  64. package/build-module/components/block-inspector/edit-contents.js.map +2 -2
  65. package/build-module/components/block-inspector/index.js +7 -1
  66. package/build-module/components/block-inspector/index.js.map +2 -2
  67. package/build-module/components/block-list/block.js +4 -0
  68. package/build-module/components/block-list/block.js.map +2 -2
  69. package/build-module/components/block-list/use-block-props/index.js +3 -1
  70. package/build-module/components/block-list/use-block-props/index.js.map +2 -2
  71. package/build-module/components/block-list/use-block-props/use-is-hovered.js +16 -10
  72. package/build-module/components/block-list/use-block-props/use-is-hovered.js.map +2 -2
  73. package/build-module/components/block-settings-menu-controls/edit-section-menu-item.js +29 -0
  74. package/build-module/components/block-settings-menu-controls/edit-section-menu-item.js.map +7 -0
  75. package/build-module/components/block-settings-menu-controls/index.js +8 -0
  76. package/build-module/components/block-settings-menu-controls/index.js.map +2 -2
  77. package/build-module/components/block-toolbar/block-toolbar-icon.js +10 -10
  78. package/build-module/components/block-toolbar/block-toolbar-icon.js.map +2 -2
  79. package/build-module/components/block-variation-transforms/index.js +32 -5
  80. package/build-module/components/block-variation-transforms/index.js.map +2 -2
  81. package/build-module/components/border-radius-control/single-input-control.js +1 -0
  82. package/build-module/components/border-radius-control/single-input-control.js.map +2 -2
  83. package/build-module/components/content-only-controls/index.js +237 -0
  84. package/build-module/components/content-only-controls/index.js.map +7 -0
  85. package/build-module/components/content-only-controls/link/index.js +172 -0
  86. package/build-module/components/content-only-controls/link/index.js.map +7 -0
  87. package/build-module/components/content-only-controls/media/index.js +243 -0
  88. package/build-module/components/content-only-controls/media/index.js.map +7 -0
  89. package/build-module/components/content-only-controls/plain-text/index.js +50 -0
  90. package/build-module/components/content-only-controls/plain-text/index.js.map +7 -0
  91. package/build-module/components/content-only-controls/rich-text/index.js +174 -0
  92. package/build-module/components/content-only-controls/rich-text/index.js.map +7 -0
  93. package/build-module/components/content-only-controls/use-inspector-popover-placement.js +16 -0
  94. package/build-module/components/content-only-controls/use-inspector-popover-placement.js.map +7 -0
  95. package/build-module/components/inserter/media-tab/media-tab.js +2 -34
  96. package/build-module/components/inserter/media-tab/media-tab.js.map +2 -2
  97. package/build-module/components/inspector-controls-tabs/content-tab.js +7 -3
  98. package/build-module/components/inspector-controls-tabs/content-tab.js.map +2 -2
  99. package/build-module/components/inspector-controls-tabs/index.js +7 -1
  100. package/build-module/components/inspector-controls-tabs/index.js.map +2 -2
  101. package/build-module/components/list-view/block-select-button.js +18 -5
  102. package/build-module/components/list-view/block-select-button.js.map +2 -2
  103. package/build-module/components/media-placeholder/index.js +1 -31
  104. package/build-module/components/media-placeholder/index.js.map +2 -2
  105. package/build-module/components/media-replace-flow/index.js +4 -30
  106. package/build-module/components/media-replace-flow/index.js.map +2 -2
  107. package/build-module/components/use-block-display-information/index.js +21 -1
  108. package/build-module/components/use-block-display-information/index.js.map +3 -3
  109. package/build-module/hooks/block-bindings.js +57 -62
  110. package/build-module/hooks/block-bindings.js.map +2 -2
  111. package/build-module/hooks/use-content-only-section-edit.js +46 -0
  112. package/build-module/hooks/use-content-only-section-edit.js.map +7 -0
  113. package/build-module/layouts/constrained.js +2 -2
  114. package/build-module/layouts/constrained.js.map +2 -2
  115. package/build-module/private-apis.js +3 -3
  116. package/build-module/private-apis.js.map +2 -2
  117. package/build-module/store/private-keys.js +2 -0
  118. package/build-module/store/private-keys.js.map +2 -2
  119. package/build-module/store/private-selectors.js +1 -2
  120. package/build-module/store/private-selectors.js.map +2 -2
  121. package/build-module/store/reducer.js +1 -2
  122. package/build-module/store/reducer.js.map +2 -2
  123. package/build-module/utils/fit-text-utils.js +9 -1
  124. package/build-module/utils/fit-text-utils.js.map +2 -2
  125. package/build-style/style-rtl.css +132 -0
  126. package/build-style/style.css +132 -0
  127. package/package.json +37 -37
  128. package/src/components/block-inspector/edit-contents.js +10 -29
  129. package/src/components/block-inspector/index.js +4 -2
  130. package/src/components/block-list/block.js +6 -0
  131. package/src/components/block-list/use-block-props/index.js +3 -1
  132. package/src/components/block-list/use-block-props/use-is-hovered.js +24 -12
  133. package/src/components/block-settings-menu-controls/edit-section-menu-item.js +39 -0
  134. package/src/components/block-settings-menu-controls/index.js +7 -0
  135. package/src/components/block-toolbar/block-toolbar-icon.js +14 -10
  136. package/src/components/block-variation-transforms/index.js +96 -35
  137. package/src/components/border-radius-control/single-input-control.js +1 -0
  138. package/src/components/content-only-controls/index.js +296 -0
  139. package/src/components/content-only-controls/link/index.js +195 -0
  140. package/src/components/content-only-controls/link/styles.scss +23 -0
  141. package/src/components/content-only-controls/media/index.js +285 -0
  142. package/src/components/content-only-controls/media/styles.scss +47 -0
  143. package/src/components/content-only-controls/plain-text/index.js +49 -0
  144. package/src/components/content-only-controls/rich-text/index.js +193 -0
  145. package/src/components/content-only-controls/rich-text/styles.scss +24 -0
  146. package/src/components/content-only-controls/styles.scss +35 -0
  147. package/src/components/content-only-controls/use-inspector-popover-placement.js +19 -0
  148. package/src/components/inserter/media-tab/media-tab.js +2 -44
  149. package/src/components/inspector-controls-tabs/content-tab.js +12 -4
  150. package/src/components/inspector-controls-tabs/index.js +4 -1
  151. package/src/components/list-view/block-select-button.js +37 -24
  152. package/src/components/media-placeholder/index.js +1 -41
  153. package/src/components/media-replace-flow/index.js +3 -39
  154. package/src/components/use-block-display-information/index.js +30 -2
  155. package/src/hooks/block-bindings.js +71 -82
  156. package/src/hooks/use-content-only-section-edit.js +63 -0
  157. package/src/layouts/constrained.js +8 -2
  158. package/src/private-apis.js +2 -2
  159. package/src/store/private-keys.js +1 -0
  160. package/src/store/private-selectors.js +1 -2
  161. package/src/store/reducer.js +0 -3
  162. package/src/store/test/reducer.js +7 -17
  163. package/src/style.scss +1 -0
  164. package/src/utils/fit-text-utils.js +19 -1
  165. package/build/components/media-upload-modal/index.js +0 -29
  166. package/build/components/media-upload-modal/index.js.map +0 -7
  167. package/build-module/components/media-upload-modal/index.js +0 -8
  168. package/build-module/components/media-upload-modal/index.js.map +0 -7
  169. package/src/components/media-upload-modal/index.js +0 -18
@@ -4,8 +4,7 @@
4
4
  import { __ } from '@wordpress/i18n';
5
5
  import { useViewportMatch } from '@wordpress/compose';
6
6
  import { Button } from '@wordpress/components';
7
- import { useCallback, useMemo, useState } from '@wordpress/element';
8
- import { useSelect } from '@wordpress/data';
7
+ import { useCallback, useMemo } from '@wordpress/element';
9
8
 
10
9
  /**
11
10
  * Internal dependencies
@@ -13,55 +12,14 @@ import { useSelect } from '@wordpress/data';
13
12
  import { MediaCategoryPanel } from './media-panel';
14
13
  import MediaUploadCheck from '../../media-upload/check';
15
14
  import MediaUpload from '../../media-upload';
16
- import MediaUploadModal from '../../media-upload-modal';
17
15
  import { useMediaCategories } from './hooks';
18
16
  import { getBlockAndPreviewFromMedia } from './utils';
19
17
  import MobileTabNavigation from '../mobile-tab-navigation';
20
18
  import CategoryTabs from '../category-tabs';
21
19
  import InserterNoResults from '../no-results';
22
- import { store as blockEditorStore } from '../../../store';
23
20
 
24
21
  const ALLOWED_MEDIA_TYPES = [ 'image', 'video', 'audio' ];
25
22
 
26
- /**
27
- * Conditional Media component that uses MediaUploadModal when experiment is enabled,
28
- * otherwise falls back to MediaUpload.
29
- *
30
- * @param {Object} root0 Component props.
31
- * @param {Function} root0.render Render prop function that receives { open } object.
32
- * @return {JSX.Element} The component.
33
- */
34
- function ConditionalMediaUpload( { render, ...props } ) {
35
- const [ isModalOpen, setIsModalOpen ] = useState( false );
36
- const mediaUpload = useSelect( ( select ) => {
37
- const { getSettings } = select( blockEditorStore );
38
- return getSettings().mediaUpload;
39
- }, [] );
40
-
41
- if ( window.__experimentalDataViewsMediaModal ) {
42
- return (
43
- <>
44
- { render && render( { open: () => setIsModalOpen( true ) } ) }
45
- <MediaUploadModal
46
- { ...props }
47
- isOpen={ isModalOpen }
48
- onClose={ () => {
49
- setIsModalOpen( false );
50
- props.onClose?.();
51
- } }
52
- onSelect={ ( media ) => {
53
- setIsModalOpen( false );
54
- props.onSelect?.( media );
55
- } }
56
- onUpload={ mediaUpload }
57
- />
58
- </>
59
- );
60
- }
61
-
62
- return <MediaUpload { ...props } render={ render } />;
63
- }
64
-
65
23
  function MediaTab( {
66
24
  rootClientId,
67
25
  selectedCategory,
@@ -113,7 +71,7 @@ function MediaTab( {
113
71
  { children }
114
72
  </CategoryTabs>
115
73
  <MediaUploadCheck>
116
- <ConditionalMediaUpload
74
+ <MediaUpload
117
75
  multiple={ false }
118
76
  onSelect={ onSelectMedia }
119
77
  allowedTypes={ ALLOWED_MEDIA_TYPES }
@@ -8,16 +8,24 @@ import { __ } from '@wordpress/i18n';
8
8
  * Internal dependencies
9
9
  */
10
10
  import BlockQuickNavigation from '../block-quick-navigation';
11
+ import ContentOnlyControls from '../content-only-controls';
11
12
 
12
- const ContentTab = ( { contentClientIds } ) => {
13
+ const ContentTab = ( { rootClientId, contentClientIds } ) => {
13
14
  if ( ! contentClientIds || contentClientIds.length === 0 ) {
14
15
  return null;
15
16
  }
16
17
 
17
18
  return (
18
- <PanelBody title={ __( 'Content' ) }>
19
- <BlockQuickNavigation clientIds={ contentClientIds } />
20
- </PanelBody>
19
+ <>
20
+ { ! window?.__experimentalContentOnlyPatternInsertion && (
21
+ <PanelBody title={ __( 'Content' ) }>
22
+ <BlockQuickNavigation clientIds={ contentClientIds } />
23
+ </PanelBody>
24
+ ) }
25
+ { window?.__experimentalContentOnlyPatternInsertion && (
26
+ <ContentOnlyControls rootClientId={ rootClientId } />
27
+ ) }
28
+ </>
21
29
  );
22
30
  };
23
31
 
@@ -109,7 +109,10 @@ export default function InspectorControlsTabs( {
109
109
  />
110
110
  </Tabs.TabPanel>
111
111
  <Tabs.TabPanel tabId={ TAB_CONTENT.name } focusable={ false }>
112
- <ContentTab contentClientIds={ contentClientIds } />
112
+ <ContentTab
113
+ rootClientId={ clientId }
114
+ contentClientIds={ contentClientIds }
115
+ />
113
116
  </Tabs.TabPanel>
114
117
  <Tabs.TabPanel tabId={ TAB_LIST_VIEW.name } focusable={ false }>
115
118
  <InspectorControls.Slot group="list" />
@@ -12,7 +12,13 @@ import {
12
12
  privateApis as componentsPrivateApis,
13
13
  } from '@wordpress/components';
14
14
  import { forwardRef } from '@wordpress/element';
15
- import { Icon, lockSmall as lock, pinSmall, unseen } from '@wordpress/icons';
15
+ import {
16
+ Icon,
17
+ lockSmall as lock,
18
+ pinSmall,
19
+ unseen,
20
+ symbol,
21
+ } from '@wordpress/icons';
16
22
  import { SPACE, ENTER } from '@wordpress/keycodes';
17
23
  import { useSelect } from '@wordpress/data';
18
24
  import { hasBlockSupport } from '@wordpress/blocks';
@@ -55,28 +61,35 @@ function ListViewBlockSelectButton(
55
61
  context: 'list-view',
56
62
  } );
57
63
  const { isLocked } = useBlockLock( clientId );
58
- const { canToggleBlockVisibility, isBlockHidden, isContentOnly } =
59
- useSelect(
60
- ( select ) => {
61
- const { getBlockName } = select( blockEditorStore );
62
- const { isBlockHidden: _isBlockHidden } = unlock(
63
- select( blockEditorStore )
64
- );
65
- return {
66
- canToggleBlockVisibility: hasBlockSupport(
67
- getBlockName( clientId ),
68
- 'blockVisibility',
69
- true
70
- ),
71
- isBlockHidden: _isBlockHidden( clientId ),
72
- isContentOnly:
73
- select( blockEditorStore ).getBlockEditingMode(
74
- clientId
75
- ) === 'contentOnly',
76
- };
77
- },
78
- [ clientId ]
79
- );
64
+ const {
65
+ canToggleBlockVisibility,
66
+ isBlockHidden,
67
+ isContentOnly,
68
+ hasPatternName,
69
+ } = useSelect(
70
+ ( select ) => {
71
+ const { getBlockName, getBlockAttributes } =
72
+ select( blockEditorStore );
73
+ const { isBlockHidden: _isBlockHidden } = unlock(
74
+ select( blockEditorStore )
75
+ );
76
+ const blockAttributes = getBlockAttributes( clientId );
77
+ return {
78
+ canToggleBlockVisibility: hasBlockSupport(
79
+ getBlockName( clientId ),
80
+ 'blockVisibility',
81
+ true
82
+ ),
83
+ isBlockHidden: _isBlockHidden( clientId ),
84
+ isContentOnly:
85
+ select( blockEditorStore ).getBlockEditingMode(
86
+ clientId
87
+ ) === 'contentOnly',
88
+ hasPatternName: !! blockAttributes?.metadata?.patternName,
89
+ };
90
+ },
91
+ [ clientId ]
92
+ );
80
93
  const shouldShowLockIcon = isLocked && ! isContentOnly;
81
94
  const shouldShowBlockVisibilityIcon =
82
95
  canToggleBlockVisibility && isBlockHidden;
@@ -123,7 +136,7 @@ function ListViewBlockSelectButton(
123
136
  >
124
137
  <ListViewExpander onClick={ onToggleExpanded } />
125
138
  <BlockIcon
126
- icon={ blockInformation?.icon }
139
+ icon={ hasPatternName ? symbol : blockInformation?.icon }
127
140
  showColors
128
141
  context="list-view"
129
142
  />
@@ -25,7 +25,6 @@ import deprecated from '@wordpress/deprecated';
25
25
  * Internal dependencies
26
26
  */
27
27
  import MediaUpload from '../media-upload';
28
- import MediaUploadModal from '../media-upload-modal';
29
28
  import MediaUploadCheck from '../media-upload/check';
30
29
  import URLPopover from '../url-popover';
31
30
  import { store as blockEditorStore } from '../../store';
@@ -33,45 +32,6 @@ import { parseDropEvent } from '../use-on-block-drop';
33
32
 
34
33
  const noop = () => {};
35
34
 
36
- /**
37
- * Conditional Media component that uses MediaUploadModal when experiment is enabled,
38
- * otherwise falls back to MediaUpload.
39
- *
40
- * @param {Object} root0 Component props.
41
- * @param {Function} root0.render Render prop function that receives { open } object.
42
- * @return {JSX.Element} The component.
43
- */
44
- function ConditionalMediaUpload( { render, ...props } ) {
45
- const [ isModalOpen, setIsModalOpen ] = useState( false );
46
- const mediaUpload = useSelect( ( select ) => {
47
- const { getSettings } = select( blockEditorStore );
48
- return getSettings().mediaUpload;
49
- }, [] );
50
-
51
- if ( window.__experimentalDataViewsMediaModal ) {
52
- return (
53
- <>
54
- { render && render( { open: () => setIsModalOpen( true ) } ) }
55
- <MediaUploadModal
56
- { ...props }
57
- isOpen={ isModalOpen }
58
- onClose={ () => {
59
- setIsModalOpen( false );
60
- props.onClose?.();
61
- } }
62
- onSelect={ ( media ) => {
63
- setIsModalOpen( false );
64
- props.onSelect?.( media );
65
- } }
66
- onUpload={ mediaUpload }
67
- />
68
- </>
69
- );
70
- }
71
-
72
- return <MediaUpload { ...props } render={ render } />;
73
- }
74
-
75
35
  const InsertFromURLPopover = ( {
76
36
  src,
77
37
  onChange,
@@ -488,7 +448,7 @@ export function MediaPlaceholder( {
488
448
  };
489
449
  const libraryButton = mediaLibraryButton ?? defaultButton;
490
450
  const uploadMediaLibraryButton = (
491
- <ConditionalMediaUpload
451
+ <MediaUpload
492
452
  addToGallery={ addToGallery }
493
453
  gallery={ multiple && onlyAllowsImages() }
494
454
  multiple={ multiple }
@@ -12,7 +12,6 @@ import {
12
12
  ToolbarButton,
13
13
  } from '@wordpress/components';
14
14
  import { useSelect, withDispatch } from '@wordpress/data';
15
- import { useState } from '@wordpress/element';
16
15
  import { DOWN } from '@wordpress/keycodes';
17
16
  import {
18
17
  postFeaturedImage,
@@ -27,7 +26,6 @@ import { store as noticesStore } from '@wordpress/notices';
27
26
  * Internal dependencies
28
27
  */
29
28
  import MediaUpload from '../media-upload';
30
- import MediaUploadModal from '../media-upload-modal';
31
29
  import MediaUploadCheck from '../media-upload/check';
32
30
  import LinkControl from '../link-control';
33
31
  import { store as blockEditorStore } from '../../store';
@@ -35,42 +33,6 @@ import { store as blockEditorStore } from '../../store';
35
33
  const noop = () => {};
36
34
  let uniqueId = 0;
37
35
 
38
- /**
39
- * Conditional Media component that uses MediaUploadModal when experiment is enabled,
40
- * otherwise falls back to MediaUpload.
41
- *
42
- * @param {Object} root0 Component props.
43
- * @param {Function} root0.render Render prop function that receives { open } object.
44
- * @return {JSX.Element} The component.
45
- */
46
- function ConditionalMediaUpload( { render, ...props } ) {
47
- const [ isModalOpen, setIsModalOpen ] = useState( false );
48
- const { getSettings } = useSelect( blockEditorStore );
49
-
50
- if ( window.__experimentalDataViewsMediaModal ) {
51
- return (
52
- <>
53
- { render && render( { open: () => setIsModalOpen( true ) } ) }
54
- <MediaUploadModal
55
- { ...props }
56
- isOpen={ isModalOpen }
57
- onClose={ () => {
58
- setIsModalOpen( false );
59
- props.onClose?.();
60
- } }
61
- onSelect={ ( media ) => {
62
- setIsModalOpen( false );
63
- props.onSelect?.( media );
64
- } }
65
- onUpload={ getSettings().mediaUpload }
66
- />
67
- </>
68
- );
69
- }
70
-
71
- return <MediaUpload { ...props } render={ render } />;
72
- }
73
-
74
36
  const MediaReplaceFlow = ( {
75
37
  mediaURL,
76
38
  mediaId,
@@ -93,6 +55,7 @@ const MediaReplaceFlow = ( {
93
55
  handleUpload = true,
94
56
  popoverProps,
95
57
  renderToggle,
58
+ className,
96
59
  } ) => {
97
60
  const { getSettings } = useSelect( blockEditorStore );
98
61
  const errorNoticeID = `block-editor/media-replace-flow/error-notice/${ ++uniqueId }`;
@@ -169,6 +132,7 @@ const MediaReplaceFlow = ( {
169
132
  return (
170
133
  <Dropdown
171
134
  popoverProps={ popoverProps }
135
+ className={ className }
172
136
  contentClassName="block-editor-media-replace-flow__options"
173
137
  renderToggle={ ( { isOpen, onToggle } ) => {
174
138
  if ( renderToggle ) {
@@ -195,7 +159,7 @@ const MediaReplaceFlow = ( {
195
159
  <>
196
160
  <NavigableMenu className="block-editor-media-replace-flow__media-upload-menu">
197
161
  <MediaUploadCheck>
198
- <ConditionalMediaUpload
162
+ <MediaUpload
199
163
  gallery={ gallery }
200
164
  addToGallery={ addToGallery }
201
165
  multiple={ multiple }
@@ -9,6 +9,7 @@ import {
9
9
  __experimentalGetBlockLabel as getBlockLabel,
10
10
  } from '@wordpress/blocks';
11
11
  import { __ } from '@wordpress/i18n';
12
+ import { symbol } from '@wordpress/icons';
12
13
 
13
14
  /**
14
15
  * Internal dependencies
@@ -71,8 +72,11 @@ export default function useBlockDisplayInformation( clientId ) {
71
72
  if ( ! clientId ) {
72
73
  return null;
73
74
  }
74
- const { getBlockName, getBlockAttributes } =
75
- select( blockEditorStore );
75
+ const {
76
+ getBlockName,
77
+ getBlockAttributes,
78
+ __experimentalGetParsedPattern,
79
+ } = select( blockEditorStore );
76
80
  const { getBlockType, getActiveBlockVariation } =
77
81
  select( blocksStore );
78
82
  const blockName = getBlockName( clientId );
@@ -81,6 +85,30 @@ export default function useBlockDisplayInformation( clientId ) {
81
85
  return null;
82
86
  }
83
87
  const attributes = getBlockAttributes( clientId );
88
+
89
+ // Check if this block is a pattern
90
+ const patternName = attributes?.metadata?.patternName;
91
+
92
+ if (
93
+ patternName &&
94
+ window?.__experimentalContentOnlyPatternInsertion
95
+ ) {
96
+ const pattern = __experimentalGetParsedPattern( patternName );
97
+
98
+ const positionLabel = getPositionTypeLabel( attributes );
99
+ return {
100
+ isSynced: false,
101
+ title: __( 'Pattern' ),
102
+ icon: symbol,
103
+ description:
104
+ pattern?.description || __( 'A block pattern.' ),
105
+ anchor: attributes?.anchor,
106
+ positionLabel,
107
+ positionType: attributes?.style?.position?.type,
108
+ name: pattern?.title || attributes?.metadata?.name,
109
+ };
110
+ }
111
+
84
112
  const match = getActiveBlockVariation( blockName, attributes );
85
113
  const isSynced =
86
114
  isReusableBlock( blockType ) || isTemplatePart( blockType );
@@ -7,7 +7,11 @@ import fastDeepEqual from 'fast-deep-equal/es6';
7
7
  * WordPress dependencies
8
8
  */
9
9
  import { __ } from '@wordpress/i18n';
10
- import { getBlockBindingsSources, getBlockType } from '@wordpress/blocks';
10
+ import {
11
+ getBlockBindingsSource,
12
+ getBlockType,
13
+ store as blockStore,
14
+ } from '@wordpress/blocks';
11
15
  import {
12
16
  __experimentalItemGroup as ItemGroup,
13
17
  __experimentalItem as Item,
@@ -33,8 +37,6 @@ import { store as blockEditorStore } from '../store';
33
37
 
34
38
  const { Menu } = unlock( componentsPrivateApis );
35
39
 
36
- const EMPTY_OBJECT = {};
37
-
38
40
  /**
39
41
  * Get the normalized attribute type for block bindings.
40
42
  * Converts 'rich-text' to 'string' since rich-text is stored as string.
@@ -80,10 +82,10 @@ function BlockBindingsPanelMenuContent( { attribute, binding, sources } ) {
80
82
  );
81
83
  return (
82
84
  <Menu placement={ isMobile ? 'bottom-start' : 'left-start' }>
83
- { Object.entries( sources ).map( ( [ sourceKey, source ] ) => {
85
+ { Object.entries( sources ).map( ( [ sourceKey, data ] ) => {
84
86
  // Only show sources that have compatible data for this specific attribute.
85
- const sourceDataItems = source.data?.filter(
86
- ( item ) => item?.type === attributeType
87
+ const sourceDataItems = data.filter(
88
+ ( item ) => item.type === attributeType
87
89
  );
88
90
 
89
91
  const noItemsAvailable =
@@ -93,6 +95,8 @@ function BlockBindingsPanelMenuContent( { attribute, binding, sources } ) {
93
95
  return null;
94
96
  }
95
97
 
98
+ const source = getBlockBindingsSource( sourceKey );
99
+
96
100
  return (
97
101
  <Menu
98
102
  key={ sourceKey }
@@ -106,17 +110,21 @@ function BlockBindingsPanelMenuContent( { attribute, binding, sources } ) {
106
110
  { sourceDataItems.map( ( item ) => {
107
111
  const itemBindings = {
108
112
  source: sourceKey,
109
- args: item?.args || {
113
+ args: item.args || {
110
114
  key: item.key,
111
115
  },
112
116
  };
113
- const values = source.getValues( {
114
- select,
115
- context: blockContext,
116
- bindings: {
117
- [ attribute ]: itemBindings,
118
- },
119
- } );
117
+ let values = {};
118
+ try {
119
+ values = source.getValues( {
120
+ select,
121
+ context: blockContext,
122
+ bindings: {
123
+ [ attribute ]: itemBindings,
124
+ },
125
+ } );
126
+ } catch ( e ) {}
127
+
120
128
  return (
121
129
  <Menu.CheckboxItem
122
130
  key={
@@ -160,7 +168,7 @@ function BlockBindingsPanelMenuContent( { attribute, binding, sources } ) {
160
168
  }
161
169
  >
162
170
  <Menu.ItemLabel>
163
- { item?.label }
171
+ { item.label }
164
172
  </Menu.ItemLabel>
165
173
  <Menu.ItemHelpText>
166
174
  { values[ attribute ] }
@@ -179,7 +187,8 @@ function BlockBindingsPanelMenuContent( { attribute, binding, sources } ) {
179
187
 
180
188
  function BlockBindingsAttribute( { attribute, binding, sources, blockName } ) {
181
189
  const { source: sourceName, args } = binding || {};
182
- const source = sources?.[ sourceName ];
190
+ const data = sources?.[ sourceName ];
191
+ const source = getBlockBindingsSource( sourceName );
183
192
 
184
193
  let displayText;
185
194
  let isValid = true;
@@ -189,8 +198,8 @@ function BlockBindingsAttribute( { attribute, binding, sources, blockName } ) {
189
198
  // Check if there are any compatible sources for this attribute type.
190
199
  const attributeType = getAttributeType( blockName, attribute );
191
200
 
192
- const hasCompatibleSources = Object.values( sources ).some( ( src ) =>
193
- src.data?.some( ( item ) => item?.type === attributeType )
201
+ const hasCompatibleSources = Object.values( sources ).some( ( items ) =>
202
+ items.some( ( item ) => item.type === attributeType )
194
203
  );
195
204
 
196
205
  if ( ! hasCompatibleSources ) {
@@ -203,14 +212,10 @@ function BlockBindingsAttribute( { attribute, binding, sources, blockName } ) {
203
212
  // If there's a binding but the source is not found, it's invalid.
204
213
  isValid = false;
205
214
  displayText = __( 'Source not registered' );
206
- if ( Object.keys( sources ).length === 0 ) {
207
- displayText = __( 'No sources available' );
208
- }
209
215
  } else {
210
216
  displayText =
211
- source.data?.find( ( item ) => fastDeepEqual( item.args, args ) )
212
- ?.label ||
213
- source.label ||
217
+ data?.find( ( item ) => fastDeepEqual( item.args, args ) )?.label ||
218
+ source?.label ||
214
219
  sourceName;
215
220
  }
216
221
 
@@ -299,68 +304,57 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
299
304
 
300
305
  // Use useSelect to ensure sources are updated whenever there are updates in block context
301
306
  // or when underlying data changes.
302
- // Still needs a fix regarding _sources scope.
303
- const _sources = {};
304
- const { sources, canUpdateBlockBindings, bindableAttributes } = useSelect(
307
+ const { canUpdateBlockBindings, bindableAttributes } = useSelect(
305
308
  ( select ) => {
306
309
  const { __experimentalBlockBindingsSupportedAttributes } =
307
310
  select( blockEditorStore ).getSettings();
308
- const _bindableAttributes =
309
- __experimentalBlockBindingsSupportedAttributes?.[ blockName ];
310
- if ( ! _bindableAttributes || _bindableAttributes.length === 0 ) {
311
- return EMPTY_OBJECT;
312
- }
313
-
314
- const registeredSources = getBlockBindingsSources();
315
- Object.entries( registeredSources ).forEach(
316
- ( [
317
- sourceName,
318
- { getFieldsList, usesContext, label, getValues },
319
- ] ) => {
320
- // Populate context.
311
+
312
+ return {
313
+ canUpdateBlockBindings:
314
+ select( blockEditorStore ).getSettings()
315
+ .canUpdateBlockBindings,
316
+ bindableAttributes:
317
+ __experimentalBlockBindingsSupportedAttributes?.[
318
+ blockName
319
+ ],
320
+ };
321
+ },
322
+ [ blockName ]
323
+ );
324
+
325
+ const sources = useSelect(
326
+ ( select ) => {
327
+ const { getAllBlockBindingsSources } = unlock(
328
+ select( blockStore )
329
+ );
330
+ const data = {};
331
+ Object.entries( getAllBlockBindingsSources() ).forEach(
332
+ ( [ sourceName, source ] ) => {
333
+ if ( ! source.getFieldsList ) {
334
+ return;
335
+ }
336
+
321
337
  const context = {};
322
- if ( usesContext?.length ) {
323
- for ( const key of usesContext ) {
338
+ if ( source.usesContext?.length ) {
339
+ for ( const key of source.usesContext ) {
324
340
  context[ key ] = blockContext[ key ];
325
341
  }
326
342
  }
327
- if ( getFieldsList ) {
328
- const fieldsListResult = getFieldsList( {
329
- select,
330
- context,
331
- } );
332
- _sources[ sourceName ] = {
333
- data: fieldsListResult || [],
334
- label,
335
- getValues,
336
- };
337
- } else {
338
- /*
339
- * Include sources without getFieldsList if they are already used in a binding.
340
- * This allows them to be displayed in read-only mode.
341
- */
342
- _sources[ sourceName ] = {
343
- data: [],
344
- label,
345
- getValues,
346
- };
343
+
344
+ const items = source.getFieldsList( {
345
+ select,
346
+ context,
347
+ } );
348
+ if ( items?.length ) {
349
+ data[ sourceName ] = items;
347
350
  }
348
351
  }
349
352
  );
350
-
351
- return {
352
- sources:
353
- Object.values( _sources ).length > 0
354
- ? _sources
355
- : EMPTY_OBJECT,
356
- canUpdateBlockBindings:
357
- select( blockEditorStore ).getSettings()
358
- .canUpdateBlockBindings,
359
- bindableAttributes: _bindableAttributes,
360
- };
353
+ return data;
361
354
  },
362
- [ blockContext, blockName ]
355
+ [ blockContext ]
363
356
  );
357
+
364
358
  // Return early if there are no bindable attributes.
365
359
  if ( ! bindableAttributes || bindableAttributes.length === 0 ) {
366
360
  return null;
@@ -368,10 +362,7 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
368
362
 
369
363
  const { bindings } = metadata || {};
370
364
 
371
- // Check if all sources have empty data arrays.
372
- const hasCompatibleData = Object.values( sources ).some(
373
- ( source ) => source.data && source.data.length > 0
374
- );
365
+ const hasCompatibleData = Object.keys( sources ).length > 0;
375
366
 
376
367
  // Lock the UI when the user can't update bindings or there are no fields to connect to.
377
368
  const readOnly = ! canUpdateBlockBindings || ! hasCompatibleData;
@@ -402,10 +393,8 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
402
393
 
403
394
  const hasCompatibleDataForAttribute = Object.values(
404
395
  sources
405
- ).some( ( source ) =>
406
- source.data?.some(
407
- ( item ) => item?.type === attributeType
408
- )
396
+ ).some( ( data ) =>
397
+ data.some( ( item ) => item.type === attributeType )
409
398
  );
410
399
 
411
400
  const isAttributeReadOnly =