@wordpress/block-library 7.14.0 → 7.14.1

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 (104) hide show
  1. package/build/button/edit.js +8 -3
  2. package/build/button/edit.js.map +1 -1
  3. package/build/column/index.js +1 -1
  4. package/build/cover/index.js +1 -1
  5. package/build/group/edit.js +0 -17
  6. package/build/group/edit.js.map +1 -1
  7. package/build/group/index.js +1 -7
  8. package/build/group/index.js.map +1 -1
  9. package/build/group/transforms.js +4 -1
  10. package/build/group/transforms.js.map +1 -1
  11. package/build/group/variations.js +2 -1
  12. package/build/group/variations.js.map +1 -1
  13. package/build/media-text/edit.js +25 -11
  14. package/build/media-text/edit.js.map +1 -1
  15. package/build/media-text/media-container.js +4 -3
  16. package/build/media-text/media-container.js.map +1 -1
  17. package/build/navigation/edit/overlay-menu-icon.js +0 -8
  18. package/build/navigation/edit/overlay-menu-icon.js.map +1 -1
  19. package/build/navigation/edit/overlay-menu-preview.js +0 -12
  20. package/build/navigation/edit/overlay-menu-preview.js.map +1 -1
  21. package/build/navigation-link/edit.js +8 -3
  22. package/build/navigation-link/edit.js.map +1 -1
  23. package/build/navigation-submenu/edit.js +8 -3
  24. package/build/navigation-submenu/edit.js.map +1 -1
  25. package/build/post-date/edit.js +10 -6
  26. package/build/post-date/edit.js.map +1 -1
  27. package/build/query/edit/index.js +23 -211
  28. package/build/query/edit/index.js.map +1 -1
  29. package/build/query/edit/query-content.js +169 -0
  30. package/build/query/edit/query-content.js.map +1 -0
  31. package/build/query/edit/query-placeholder.js +69 -6
  32. package/build/query/edit/query-placeholder.js.map +1 -1
  33. package/build/query/utils.js +40 -0
  34. package/build/query/utils.js.map +1 -1
  35. package/build/social-link/edit.js +8 -6
  36. package/build/social-link/edit.js.map +1 -1
  37. package/build/template-part/edit/selection-modal.js +2 -13
  38. package/build/template-part/edit/selection-modal.js.map +1 -1
  39. package/build-module/button/edit.js +7 -3
  40. package/build-module/button/edit.js.map +1 -1
  41. package/build-module/column/index.js +1 -1
  42. package/build-module/cover/index.js +1 -1
  43. package/build-module/group/edit.js +1 -19
  44. package/build-module/group/edit.js.map +1 -1
  45. package/build-module/group/index.js +1 -7
  46. package/build-module/group/index.js.map +1 -1
  47. package/build-module/group/transforms.js +4 -1
  48. package/build-module/group/transforms.js.map +1 -1
  49. package/build-module/group/variations.js +2 -1
  50. package/build-module/group/variations.js.map +1 -1
  51. package/build-module/media-text/edit.js +25 -11
  52. package/build-module/media-text/edit.js.map +1 -1
  53. package/build-module/media-text/media-container.js +4 -3
  54. package/build-module/media-text/media-container.js.map +1 -1
  55. package/build-module/navigation/edit/overlay-menu-icon.js +1 -9
  56. package/build-module/navigation/edit/overlay-menu-icon.js.map +1 -1
  57. package/build-module/navigation/edit/overlay-menu-preview.js +0 -12
  58. package/build-module/navigation/edit/overlay-menu-preview.js.map +1 -1
  59. package/build-module/navigation-link/edit.js +7 -3
  60. package/build-module/navigation-link/edit.js.map +1 -1
  61. package/build-module/navigation-submenu/edit.js +7 -3
  62. package/build-module/navigation-submenu/edit.js.map +1 -1
  63. package/build-module/post-date/edit.js +11 -7
  64. package/build-module/post-date/edit.js.map +1 -1
  65. package/build-module/query/edit/index.js +27 -208
  66. package/build-module/query/edit/index.js.map +1 -1
  67. package/build-module/query/edit/query-content.js +152 -0
  68. package/build-module/query/edit/query-content.js.map +1 -0
  69. package/build-module/query/edit/query-placeholder.js +67 -5
  70. package/build-module/query/edit/query-placeholder.js.map +1 -1
  71. package/build-module/query/utils.js +37 -0
  72. package/build-module/query/utils.js.map +1 -1
  73. package/build-module/social-link/edit.js +9 -7
  74. package/build-module/social-link/edit.js.map +1 -1
  75. package/build-module/template-part/edit/selection-modal.js +3 -14
  76. package/build-module/template-part/edit/selection-modal.js.map +1 -1
  77. package/package.json +14 -14
  78. package/src/button/edit.js +10 -2
  79. package/src/column/block.json +1 -1
  80. package/src/comments/index.php +1 -1
  81. package/src/cover/block.json +1 -1
  82. package/src/group/block.json +1 -7
  83. package/src/group/edit.js +2 -12
  84. package/src/group/transforms.js +1 -0
  85. package/src/group/variations.js +2 -1
  86. package/src/list/test/__snapshots__/edit.native.js.snap +8 -32
  87. package/src/list/test/edit.native.js +16 -68
  88. package/src/media-text/edit.js +45 -29
  89. package/src/media-text/media-container.js +3 -2
  90. package/src/navigation/edit/overlay-menu-icon.js +1 -5
  91. package/src/navigation/edit/overlay-menu-preview.js +0 -10
  92. package/src/navigation/index.php +0 -4
  93. package/src/navigation-link/edit.js +6 -2
  94. package/src/navigation-submenu/edit.js +6 -2
  95. package/src/post-comments-form/index.php +1 -1
  96. package/src/post-date/edit.js +13 -4
  97. package/src/post-featured-image/index.php +1 -1
  98. package/src/query/edit/index.js +50 -227
  99. package/src/query/edit/query-content.js +131 -0
  100. package/src/query/edit/query-placeholder.js +87 -8
  101. package/src/query/utils.js +46 -0
  102. package/src/search/index.php +1 -1
  103. package/src/social-link/edit.js +9 -9
  104. package/src/template-part/edit/selection-modal.js +2 -14
@@ -2,231 +2,62 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { useSelect, useDispatch } from '@wordpress/data';
5
- import { store as blocksStore } from '@wordpress/blocks';
6
- import { useInstanceId } from '@wordpress/compose';
7
- import { useState, useEffect, useMemo } from '@wordpress/element';
5
+ import { useState, useMemo } from '@wordpress/element';
8
6
  import {
9
- BlockControls,
10
7
  BlockContextProvider,
11
- InspectorControls,
12
- useBlockProps,
13
- useSetting,
14
8
  store as blockEditorStore,
15
- useInnerBlocksProps,
16
- __experimentalGetMatchingVariation as getMatchingVariation,
17
9
  __experimentalBlockPatternSetup as BlockPatternSetup,
18
10
  } from '@wordpress/block-editor';
19
- import {
20
- Button,
21
- SelectControl,
22
- Placeholder,
23
- Modal,
24
- } from '@wordpress/components';
11
+ import { Modal } from '@wordpress/components';
25
12
  import { __ } from '@wordpress/i18n';
26
13
 
27
14
  /**
28
15
  * Internal dependencies
29
16
  */
30
- import QueryToolbar from './query-toolbar';
31
- import QueryInspectorControls from './inspector-controls';
17
+ import QueryContent from './query-content';
32
18
  import QueryPlaceholder from './query-placeholder';
33
- import { DEFAULTS_POSTS_PER_PAGE } from '../constants';
34
- import { getTransformedBlocksFromPattern } from '../utils';
35
-
36
- const TEMPLATE = [ [ 'core/post-template' ] ];
37
- export function QueryContent( {
38
- attributes,
39
- setAttributes,
40
- openPatternSelectionModal,
41
- name,
42
- clientId,
43
- } ) {
44
- const {
45
- queryId,
46
- query,
47
- displayLayout,
48
- tagName: TagName = 'div',
49
- layout = {},
50
- } = attributes;
51
- const { __unstableMarkNextChangeAsNotPersistent } =
52
- useDispatch( blockEditorStore );
53
- const instanceId = useInstanceId( QueryContent );
54
- const { themeSupportsLayout } = useSelect( ( select ) => {
55
- const { getSettings } = select( blockEditorStore );
56
- return { themeSupportsLayout: getSettings()?.supportsLayout };
57
- }, [] );
58
- const defaultLayout = useSetting( 'layout' ) || {};
59
- const usedLayout = !! layout && layout.inherit ? defaultLayout : layout;
60
- const blockProps = useBlockProps();
61
- const innerBlocksProps = useInnerBlocksProps( blockProps, {
62
- template: TEMPLATE,
63
- __experimentalLayout: themeSupportsLayout ? usedLayout : undefined,
64
- } );
65
- const { postsPerPage } = useSelect( ( select ) => {
66
- const { getSettings } = select( blockEditorStore );
67
- return {
68
- postsPerPage:
69
- +getSettings().postsPerPage || DEFAULTS_POSTS_PER_PAGE,
70
- };
71
- }, [] );
72
- // There are some effects running where some initialization logic is
73
- // happening and setting some values to some attributes (ex. queryId).
74
- // These updates can cause an `undo trap` where undoing will result in
75
- // resetting again, so we need to mark these changes as not persistent
76
- // with `__unstableMarkNextChangeAsNotPersistent`.
19
+ import {
20
+ useBlockNameForPatterns,
21
+ getTransformedBlocksFromPattern,
22
+ } from '../utils';
77
23
 
78
- // Changes in query property (which is an object) need to be in the same callback,
79
- // because updates are batched after the render and changes in different query properties
80
- // would cause to override previous wanted changes.
81
- useEffect( () => {
82
- const newQuery = {};
83
- if ( ! query.perPage && postsPerPage ) {
84
- newQuery.perPage = postsPerPage;
85
- }
86
- if ( !! Object.keys( newQuery ).length ) {
87
- __unstableMarkNextChangeAsNotPersistent();
88
- updateQuery( newQuery );
89
- }
90
- }, [ query.perPage ] );
91
- // We need this for multi-query block pagination.
92
- // Query parameters for each block are scoped to their ID.
93
- useEffect( () => {
94
- if ( ! Number.isFinite( queryId ) ) {
95
- __unstableMarkNextChangeAsNotPersistent();
96
- setAttributes( { queryId: instanceId } );
97
- }
98
- }, [ queryId, instanceId ] );
99
- const updateQuery = ( newQuery ) =>
100
- setAttributes( { query: { ...query, ...newQuery } } );
101
- const updateDisplayLayout = ( newDisplayLayout ) =>
102
- setAttributes( {
103
- displayLayout: { ...displayLayout, ...newDisplayLayout },
104
- } );
24
+ const QueryEdit = ( props ) => {
25
+ const { clientId, attributes } = props;
26
+ const [ isPatternSelectionModalOpen, setIsPatternSelectionModalOpen ] =
27
+ useState( false );
28
+ const hasInnerBlocks = useSelect(
29
+ ( select ) =>
30
+ !! select( blockEditorStore ).getBlocks( clientId ).length,
31
+ [ clientId ]
32
+ );
33
+ const Component = hasInnerBlocks ? QueryContent : QueryPlaceholder;
105
34
  return (
106
35
  <>
107
- <QueryInspectorControls
108
- attributes={ attributes }
109
- setQuery={ updateQuery }
110
- setDisplayLayout={ updateDisplayLayout }
36
+ <Component
37
+ { ...props }
38
+ openPatternSelectionModal={ () =>
39
+ setIsPatternSelectionModalOpen( true )
40
+ }
111
41
  />
112
- <BlockControls>
113
- <QueryToolbar
114
- name={ name }
42
+ { isPatternSelectionModalOpen && (
43
+ <PatternSelectionModal
115
44
  clientId={ clientId }
116
45
  attributes={ attributes }
117
- setQuery={ updateQuery }
118
- setDisplayLayout={ updateDisplayLayout }
119
- openPatternSelectionModal={ openPatternSelectionModal }
120
- />
121
- </BlockControls>
122
- <InspectorControls __experimentalGroup="advanced">
123
- <SelectControl
124
- label={ __( 'HTML element' ) }
125
- options={ [
126
- { label: __( 'Default (<div>)' ), value: 'div' },
127
- { label: '<main>', value: 'main' },
128
- { label: '<section>', value: 'section' },
129
- { label: '<aside>', value: 'aside' },
130
- ] }
131
- value={ TagName }
132
- onChange={ ( value ) =>
133
- setAttributes( { tagName: value } )
46
+ setIsPatternSelectionModalOpen={
47
+ setIsPatternSelectionModalOpen
134
48
  }
135
49
  />
136
- </InspectorControls>
137
- <TagName { ...innerBlocksProps } />
50
+ ) }
138
51
  </>
139
52
  );
140
- }
53
+ };
141
54
 
142
- function QueryPatternSetup( {
143
- attributes,
55
+ function PatternSelectionModal( {
144
56
  clientId,
145
- name,
146
- openPatternSelectionModal,
147
- setAttributes,
57
+ attributes,
58
+ setIsPatternSelectionModalOpen,
148
59
  } ) {
149
- const [ isStartingBlank, setIsStartingBlank ] = useState( false );
150
- const blockProps = useBlockProps();
151
-
152
- const { blockType, allVariations, hasPatterns } = useSelect(
153
- ( select ) => {
154
- const { getBlockVariations, getBlockType } = select( blocksStore );
155
- const {
156
- getBlockRootClientId,
157
- __experimentalGetPatternsByBlockTypes,
158
- } = select( blockEditorStore );
159
- const rootClientId = getBlockRootClientId( clientId );
160
-
161
- return {
162
- blockType: getBlockType( name ),
163
- allVariations: getBlockVariations( name ),
164
- hasPatterns: !! __experimentalGetPatternsByBlockTypes(
165
- name,
166
- rootClientId
167
- ).length,
168
- };
169
- },
170
- [ name, clientId ]
171
- );
172
-
173
- const matchingVariation = getMatchingVariation( attributes, allVariations );
174
- const icon = matchingVariation?.icon || blockType?.icon?.src;
175
- const label = matchingVariation?.title || blockType?.title;
176
- if ( isStartingBlank ) {
177
- return (
178
- <QueryPlaceholder
179
- clientId={ clientId }
180
- name={ name }
181
- attributes={ attributes }
182
- setAttributes={ setAttributes }
183
- icon={ icon }
184
- label={ label }
185
- />
186
- );
187
- }
188
- return (
189
- <div { ...blockProps }>
190
- <Placeholder
191
- icon={ icon }
192
- label={ label }
193
- instructions={ __(
194
- 'Choose a pattern for the query loop or start blank.'
195
- ) }
196
- >
197
- { !! hasPatterns && (
198
- <Button
199
- variant="primary"
200
- onClick={ openPatternSelectionModal }
201
- >
202
- { __( 'Choose' ) }
203
- </Button>
204
- ) }
205
-
206
- <Button
207
- variant="secondary"
208
- onClick={ () => {
209
- setIsStartingBlank( true );
210
- } }
211
- >
212
- { __( 'Start blank' ) }
213
- </Button>
214
- </Placeholder>
215
- </div>
216
- );
217
- }
218
-
219
- const QueryEdit = ( props ) => {
220
- const { clientId, name, attributes } = props;
221
- const [ isPatternSelectionModalOpen, setIsPatternSelectionModalOpen ] =
222
- useState( false );
223
60
  const { replaceBlock, selectBlock } = useDispatch( blockEditorStore );
224
- const hasInnerBlocks = useSelect(
225
- ( select ) =>
226
- !! select( blockEditorStore ).getBlocks( clientId ).length,
227
- [ clientId ]
228
- );
229
- const Component = hasInnerBlocks ? QueryContent : QueryPatternSetup;
230
61
  const onBlockPatternSelect = ( blocks ) => {
231
62
  const { newBlocks, queryClientIds } = getTransformedBlocksFromPattern(
232
63
  blocks,
@@ -245,34 +76,26 @@ const QueryEdit = ( props ) => {
245
76
  } ),
246
77
  [ attributes.query.postType ]
247
78
  );
79
+ const blockNameForPatterns = useBlockNameForPatterns(
80
+ clientId,
81
+ attributes
82
+ );
248
83
  return (
249
- <>
250
- <Component
251
- { ...props }
252
- openPatternSelectionModal={ () =>
253
- setIsPatternSelectionModalOpen( true )
254
- }
255
- />
256
- { isPatternSelectionModalOpen && (
257
- <Modal
258
- className="block-editor-query-pattern__selection-modal"
259
- title={ __( 'Choose a pattern' ) }
260
- closeLabel={ __( 'Cancel' ) }
261
- onRequestClose={ () =>
262
- setIsPatternSelectionModalOpen( false )
263
- }
264
- >
265
- <BlockContextProvider value={ blockPreviewContext }>
266
- <BlockPatternSetup
267
- blockName={ name }
268
- clientId={ clientId }
269
- onBlockPatternSelect={ onBlockPatternSelect }
270
- />
271
- </BlockContextProvider>
272
- </Modal>
273
- ) }
274
- </>
84
+ <Modal
85
+ className="block-editor-query-pattern__selection-modal"
86
+ title={ __( 'Choose a pattern' ) }
87
+ closeLabel={ __( 'Cancel' ) }
88
+ onRequestClose={ () => setIsPatternSelectionModalOpen( false ) }
89
+ >
90
+ <BlockContextProvider value={ blockPreviewContext }>
91
+ <BlockPatternSetup
92
+ blockName={ blockNameForPatterns }
93
+ clientId={ clientId }
94
+ onBlockPatternSelect={ onBlockPatternSelect }
95
+ />
96
+ </BlockContextProvider>
97
+ </Modal>
275
98
  );
276
- };
99
+ }
277
100
 
278
101
  export default QueryEdit;
@@ -0,0 +1,131 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useSelect, useDispatch } from '@wordpress/data';
5
+ import { useInstanceId } from '@wordpress/compose';
6
+ import { useEffect } from '@wordpress/element';
7
+ import {
8
+ BlockControls,
9
+ InspectorControls,
10
+ useBlockProps,
11
+ useSetting,
12
+ store as blockEditorStore,
13
+ useInnerBlocksProps,
14
+ } from '@wordpress/block-editor';
15
+ import { SelectControl } from '@wordpress/components';
16
+ import { __ } from '@wordpress/i18n';
17
+
18
+ /**
19
+ * Internal dependencies
20
+ */
21
+ import QueryToolbar from './query-toolbar';
22
+ import QueryInspectorControls from './inspector-controls';
23
+ import { DEFAULTS_POSTS_PER_PAGE } from '../constants';
24
+
25
+ const TEMPLATE = [ [ 'core/post-template' ] ];
26
+ export default function QueryContent( {
27
+ attributes,
28
+ setAttributes,
29
+ openPatternSelectionModal,
30
+ name,
31
+ clientId,
32
+ } ) {
33
+ const {
34
+ queryId,
35
+ query,
36
+ displayLayout,
37
+ tagName: TagName = 'div',
38
+ layout = {},
39
+ } = attributes;
40
+ const { __unstableMarkNextChangeAsNotPersistent } =
41
+ useDispatch( blockEditorStore );
42
+ const instanceId = useInstanceId( QueryContent );
43
+ const { themeSupportsLayout } = useSelect( ( select ) => {
44
+ const { getSettings } = select( blockEditorStore );
45
+ return { themeSupportsLayout: getSettings()?.supportsLayout };
46
+ }, [] );
47
+ const defaultLayout = useSetting( 'layout' ) || {};
48
+ const usedLayout = ! layout?.type
49
+ ? { ...defaultLayout, ...layout, type: 'default' }
50
+ : { ...defaultLayout, ...layout };
51
+ const blockProps = useBlockProps();
52
+ const innerBlocksProps = useInnerBlocksProps( blockProps, {
53
+ template: TEMPLATE,
54
+ __experimentalLayout: themeSupportsLayout ? usedLayout : undefined,
55
+ } );
56
+ const { postsPerPage } = useSelect( ( select ) => {
57
+ const { getSettings } = select( blockEditorStore );
58
+ return {
59
+ postsPerPage:
60
+ +getSettings().postsPerPage || DEFAULTS_POSTS_PER_PAGE,
61
+ };
62
+ }, [] );
63
+ // There are some effects running where some initialization logic is
64
+ // happening and setting some values to some attributes (ex. queryId).
65
+ // These updates can cause an `undo trap` where undoing will result in
66
+ // resetting again, so we need to mark these changes as not persistent
67
+ // with `__unstableMarkNextChangeAsNotPersistent`.
68
+
69
+ // Changes in query property (which is an object) need to be in the same callback,
70
+ // because updates are batched after the render and changes in different query properties
71
+ // would cause to override previous wanted changes.
72
+ useEffect( () => {
73
+ const newQuery = {};
74
+ if ( ! query.perPage && postsPerPage ) {
75
+ newQuery.perPage = postsPerPage;
76
+ }
77
+ if ( !! Object.keys( newQuery ).length ) {
78
+ __unstableMarkNextChangeAsNotPersistent();
79
+ updateQuery( newQuery );
80
+ }
81
+ }, [ query.perPage ] );
82
+ // We need this for multi-query block pagination.
83
+ // Query parameters for each block are scoped to their ID.
84
+ useEffect( () => {
85
+ if ( ! Number.isFinite( queryId ) ) {
86
+ __unstableMarkNextChangeAsNotPersistent();
87
+ setAttributes( { queryId: instanceId } );
88
+ }
89
+ }, [ queryId, instanceId ] );
90
+ const updateQuery = ( newQuery ) =>
91
+ setAttributes( { query: { ...query, ...newQuery } } );
92
+ const updateDisplayLayout = ( newDisplayLayout ) =>
93
+ setAttributes( {
94
+ displayLayout: { ...displayLayout, ...newDisplayLayout },
95
+ } );
96
+ return (
97
+ <>
98
+ <QueryInspectorControls
99
+ attributes={ attributes }
100
+ setQuery={ updateQuery }
101
+ setDisplayLayout={ updateDisplayLayout }
102
+ />
103
+ <BlockControls>
104
+ <QueryToolbar
105
+ name={ name }
106
+ clientId={ clientId }
107
+ attributes={ attributes }
108
+ setQuery={ updateQuery }
109
+ setDisplayLayout={ updateDisplayLayout }
110
+ openPatternSelectionModal={ openPatternSelectionModal }
111
+ />
112
+ </BlockControls>
113
+ <InspectorControls __experimentalGroup="advanced">
114
+ <SelectControl
115
+ label={ __( 'HTML element' ) }
116
+ options={ [
117
+ { label: __( 'Default (<div>)' ), value: 'div' },
118
+ { label: '<main>', value: 'main' },
119
+ { label: '<section>', value: 'section' },
120
+ { label: '<aside>', value: 'aside' },
121
+ ] }
122
+ value={ TagName }
123
+ onChange={ ( value ) =>
124
+ setAttributes( { tagName: value } )
125
+ }
126
+ />
127
+ </InspectorControls>
128
+ <TagName { ...innerBlocksProps } />
129
+ </>
130
+ );
131
+ }
@@ -2,17 +2,98 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { useSelect, useDispatch } from '@wordpress/data';
5
- import {
6
- useBlockProps,
7
- __experimentalBlockVariationPicker,
8
- store as blockEditorStore,
9
- } from '@wordpress/block-editor';
10
5
  import {
11
6
  createBlocksFromInnerBlocksTemplate,
12
7
  store as blocksStore,
13
8
  } from '@wordpress/blocks';
9
+ import { useState } from '@wordpress/element';
10
+ import {
11
+ useBlockProps,
12
+ store as blockEditorStore,
13
+ __experimentalBlockVariationPicker,
14
+ __experimentalGetMatchingVariation as getMatchingVariation,
15
+ } from '@wordpress/block-editor';
16
+ import { Button, Placeholder } from '@wordpress/components';
17
+ import { __ } from '@wordpress/i18n';
14
18
 
15
- function QueryPlaceholder( {
19
+ export default function QueryPlaceholder( {
20
+ attributes,
21
+ clientId,
22
+ name,
23
+ openPatternSelectionModal,
24
+ setAttributes,
25
+ } ) {
26
+ const [ isStartingBlank, setIsStartingBlank ] = useState( false );
27
+ const blockProps = useBlockProps();
28
+
29
+ const { blockType, allVariations, hasPatterns } = useSelect(
30
+ ( select ) => {
31
+ const { getBlockVariations, getBlockType } = select( blocksStore );
32
+ const {
33
+ getBlockRootClientId,
34
+ __experimentalGetPatternsByBlockTypes,
35
+ } = select( blockEditorStore );
36
+ const rootClientId = getBlockRootClientId( clientId );
37
+
38
+ return {
39
+ blockType: getBlockType( name ),
40
+ allVariations: getBlockVariations( name ),
41
+ hasPatterns: !! __experimentalGetPatternsByBlockTypes(
42
+ name,
43
+ rootClientId
44
+ ).length,
45
+ };
46
+ },
47
+ [ name, clientId ]
48
+ );
49
+
50
+ const matchingVariation = getMatchingVariation( attributes, allVariations );
51
+ const icon = matchingVariation?.icon || blockType?.icon?.src;
52
+ const label = matchingVariation?.title || blockType?.title;
53
+ if ( isStartingBlank ) {
54
+ return (
55
+ <QueryVariationPicker
56
+ clientId={ clientId }
57
+ name={ name }
58
+ attributes={ attributes }
59
+ setAttributes={ setAttributes }
60
+ icon={ icon }
61
+ label={ label }
62
+ />
63
+ );
64
+ }
65
+ return (
66
+ <div { ...blockProps }>
67
+ <Placeholder
68
+ icon={ icon }
69
+ label={ label }
70
+ instructions={ __(
71
+ 'Choose a pattern for the query loop or start blank.'
72
+ ) }
73
+ >
74
+ { !! hasPatterns && (
75
+ <Button
76
+ variant="primary"
77
+ onClick={ openPatternSelectionModal }
78
+ >
79
+ { __( 'Choose' ) }
80
+ </Button>
81
+ ) }
82
+
83
+ <Button
84
+ variant="secondary"
85
+ onClick={ () => {
86
+ setIsStartingBlank( true );
87
+ } }
88
+ >
89
+ { __( 'Start blank' ) }
90
+ </Button>
91
+ </Placeholder>
92
+ </div>
93
+ );
94
+ }
95
+
96
+ function QueryVariationPicker( {
16
97
  clientId,
17
98
  name,
18
99
  attributes,
@@ -70,5 +151,3 @@ function QueryPlaceholder( {
70
151
  </div>
71
152
  );
72
153
  }
73
-
74
- export default QueryPlaceholder;
@@ -9,6 +9,7 @@ import { get } from 'lodash';
9
9
  import { useSelect } from '@wordpress/data';
10
10
  import { useMemo } from '@wordpress/element';
11
11
  import { store as coreStore } from '@wordpress/core-data';
12
+ import { store as blockEditorStore } from '@wordpress/block-editor';
12
13
  import { decodeEntities } from '@wordpress/html-entities';
13
14
  import { cloneBlock, store as blocksStore } from '@wordpress/blocks';
14
15
 
@@ -214,3 +215,48 @@ export const getTransformedBlocksFromPattern = (
214
215
  }
215
216
  return { newBlocks: clonedBlocks, queryClientIds };
216
217
  };
218
+
219
+ /**
220
+ * Helper hook that determines if there is an active variation of the block
221
+ * and if there are available specific patterns for this variation.
222
+ * If there are, these patterns are going to be the only ones suggested to
223
+ * the user in setup and replace flow, without including the default ones
224
+ * for Query Loop.
225
+ *
226
+ * If there are no such patterns, the default ones for Query Loop are going
227
+ * to be suggested.
228
+ *
229
+ * @param {string} clientId The block's client ID.
230
+ * @param {Object} attributes The block's attributes.
231
+ * @return {string} The block name to be used in the patterns suggestions.
232
+ */
233
+ export function useBlockNameForPatterns( clientId, attributes ) {
234
+ const activeVariationName = useSelect(
235
+ ( select ) =>
236
+ select( blocksStore ).getActiveBlockVariation(
237
+ queryLoopName,
238
+ attributes
239
+ )?.name,
240
+
241
+ [ attributes ]
242
+ );
243
+ const blockName = `${ queryLoopName }/${ activeVariationName }`;
244
+ const activeVariationPatterns = useSelect(
245
+ ( select ) => {
246
+ if ( ! activeVariationName ) {
247
+ return;
248
+ }
249
+ const {
250
+ getBlockRootClientId,
251
+ __experimentalGetPatternsByBlockTypes,
252
+ } = select( blockEditorStore );
253
+ const rootClientId = getBlockRootClientId( clientId );
254
+ return __experimentalGetPatternsByBlockTypes(
255
+ blockName,
256
+ rootClientId
257
+ );
258
+ },
259
+ [ clientId, activeVariationName ]
260
+ );
261
+ return activeVariationPatterns?.length ? blockName : queryLoopName;
262
+ }
@@ -121,7 +121,7 @@ function render_block_core_search( $attributes ) {
121
121
  }
122
122
 
123
123
  // Include the button element class.
124
- $button_classes[] = wp_theme_element_class_name( 'button' );
124
+ $button_classes[] = wp_theme_get_element_class_name( 'button' );
125
125
  $button_markup = sprintf(
126
126
  '<button type="submit" class="%s" %s %s>%s</button>',
127
127
  esc_attr( implode( ' ', $button_classes ) ),
@@ -12,7 +12,7 @@ import {
12
12
  URLInput,
13
13
  useBlockProps,
14
14
  } from '@wordpress/block-editor';
15
- import { Fragment, useState, useRef } from '@wordpress/element';
15
+ import { Fragment, useState } from '@wordpress/element';
16
16
  import {
17
17
  Button,
18
18
  PanelBody,
@@ -31,12 +31,9 @@ const SocialLinkURLPopover = ( {
31
31
  url,
32
32
  setAttributes,
33
33
  setPopover,
34
- anchorRef,
34
+ popoverAnchor,
35
35
  } ) => (
36
- <URLPopover
37
- anchorRef={ anchorRef?.current }
38
- onClose={ () => setPopover( false ) }
39
- >
36
+ <URLPopover anchor={ popoverAnchor } onClose={ () => setPopover( false ) }>
40
37
  <form
41
38
  className="block-editor-url-popover__link-editor"
42
39
  onSubmit={ ( event ) => {
@@ -76,7 +73,10 @@ const SocialLinkEdit = ( {
76
73
  'wp-social-link__is-incomplete': ! url,
77
74
  } );
78
75
 
79
- const ref = useRef();
76
+ // Use internal state instead of a ref to make sure that the component
77
+ // re-renders when the popover's anchor updates.
78
+ const [ popoverAnchor, setPopoverAnchor ] = useState( null );
79
+
80
80
  const IconComponent = getIconBySite( service );
81
81
  const socialLinkName = getNameBySite( service );
82
82
  const socialLinkLabel = label ?? socialLinkName;
@@ -116,7 +116,7 @@ const SocialLinkEdit = ( {
116
116
  <li { ...blockProps }>
117
117
  <Button
118
118
  className="wp-block-social-link-anchor"
119
- ref={ ref }
119
+ ref={ setPopoverAnchor }
120
120
  onClick={ () => setPopover( true ) }
121
121
  >
122
122
  <IconComponent />
@@ -132,7 +132,7 @@ const SocialLinkEdit = ( {
132
132
  url={ url }
133
133
  setAttributes={ setAttributes }
134
134
  setPopover={ setPopover }
135
- anchorRef={ ref }
135
+ popoverAnchor={ popoverAnchor }
136
136
  />
137
137
  ) }
138
138
  </Button>