@wordpress/block-library 9.7.1-next.1f6eadc42.0 → 9.8.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.
- package/CHANGELOG.md +2 -0
- package/build/categories/edit.js +38 -17
- package/build/categories/edit.js.map +1 -1
- package/build/categories/index.js +10 -3
- package/build/categories/index.js.map +1 -1
- package/build/categories/variations.js +43 -0
- package/build/categories/variations.js.map +1 -0
- package/build/embed/edit.js +1 -0
- package/build/embed/edit.js.map +1 -1
- package/build/embed/edit.native.js +1 -0
- package/build/embed/edit.native.js.map +1 -1
- package/build/embed/embed-preview.js +80 -100
- package/build/embed/embed-preview.js.map +1 -1
- package/build/embed/embed-preview.native.js +1 -0
- package/build/embed/embed-preview.native.js.map +1 -1
- package/build/form/view.js +1 -0
- package/build/form/view.js.map +1 -1
- package/build/image/image.js +5 -2
- package/build/image/image.js.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/navigation-submenu/index.js +13 -0
- package/build/navigation-submenu/index.js.map +1 -1
- package/build/post-template/edit.js +6 -1
- package/build/post-template/edit.js.map +1 -1
- package/build/post-title/index.js +1 -4
- package/build/post-title/index.js.map +1 -1
- package/build/query/edit/inspector-controls/format-controls.js +102 -0
- package/build/query/edit/inspector-controls/format-controls.js.map +1 -0
- package/build/query/edit/inspector-controls/index.js +45 -9
- package/build/query/edit/inspector-controls/index.js.map +1 -1
- package/build/query/edit/query-content.js +26 -10
- package/build/query/edit/query-content.js.map +1 -1
- package/build/query/index.js +3 -1
- package/build/query/index.js.map +1 -1
- package/build/query/utils.js +12 -1
- package/build/query/utils.js.map +1 -1
- package/build/site-title/index.js +1 -4
- package/build/site-title/index.js.map +1 -1
- package/build/social-link/edit.js +13 -11
- package/build/social-link/edit.js.map +1 -1
- package/build-module/categories/edit.js +40 -19
- package/build-module/categories/edit.js.map +1 -1
- package/build-module/categories/index.js +10 -3
- package/build-module/categories/index.js.map +1 -1
- package/build-module/categories/variations.js +36 -0
- package/build-module/categories/variations.js.map +1 -0
- package/build-module/embed/edit.js +1 -0
- package/build-module/embed/edit.js.map +1 -1
- package/build-module/embed/edit.native.js +1 -0
- package/build-module/embed/edit.native.js.map +1 -1
- package/build-module/embed/embed-preview.js +80 -100
- package/build-module/embed/embed-preview.js.map +1 -1
- package/build-module/embed/embed-preview.native.js +1 -0
- package/build-module/embed/embed-preview.native.js.map +1 -1
- package/build-module/form/view.js +1 -0
- package/build-module/form/view.js.map +1 -1
- package/build-module/image/image.js +5 -2
- package/build-module/image/image.js.map +1 -1
- package/build-module/index.js +1 -0
- package/build-module/index.js.map +1 -1
- package/build-module/navigation-submenu/index.js +13 -0
- package/build-module/navigation-submenu/index.js.map +1 -1
- package/build-module/post-template/edit.js +6 -1
- package/build-module/post-template/edit.js.map +1 -1
- package/build-module/post-title/index.js +1 -4
- package/build-module/post-title/index.js.map +1 -1
- package/build-module/query/edit/inspector-controls/format-controls.js +96 -0
- package/build-module/query/edit/inspector-controls/format-controls.js.map +1 -0
- package/build-module/query/edit/inspector-controls/index.js +45 -9
- package/build-module/query/edit/inspector-controls/index.js.map +1 -1
- package/build-module/query/edit/query-content.js +27 -11
- package/build-module/query/edit/query-content.js.map +1 -1
- package/build-module/query/index.js +3 -1
- package/build-module/query/index.js.map +1 -1
- package/build-module/query/utils.js +12 -1
- package/build-module/query/utils.js.map +1 -1
- package/build-module/site-title/index.js +1 -4
- package/build-module/site-title/index.js.map +1 -1
- package/build-module/social-link/edit.js +14 -12
- package/build-module/social-link/edit.js.map +1 -1
- package/build-style/editor-rtl.css +1 -1
- package/build-style/editor.css +1 -1
- package/build-style/gallery/editor-rtl.css +1 -1
- package/build-style/gallery/editor.css +1 -1
- package/build-style/post-title/style-rtl.css +4 -18
- package/build-style/post-title/style.css +4 -18
- package/build-style/site-title/style-rtl.css +4 -18
- package/build-style/site-title/style.css +4 -18
- package/build-style/style-rtl.css +8 -36
- package/build-style/style.css +8 -36
- package/package.json +35 -35
- package/src/categories/block.json +7 -2
- package/src/categories/edit.js +69 -30
- package/src/categories/index.js +2 -0
- package/src/categories/index.php +21 -9
- package/src/categories/variations.js +40 -0
- package/src/comments-pagination-next/index.php +1 -1
- package/src/comments-pagination-previous/index.php +2 -1
- package/src/embed/embed-preview.js +96 -112
- package/src/image/image.js +2 -1
- package/src/navigation-submenu/block.json +13 -0
- package/src/post-template/edit.js +6 -0
- package/src/post-template/index.php +5 -0
- package/src/post-title/block.json +1 -4
- package/src/post-title/style.scss +4 -21
- package/src/query/block.json +3 -1
- package/src/query/edit/inspector-controls/format-controls.js +90 -0
- package/src/query/edit/inspector-controls/index.js +68 -9
- package/src/query/edit/query-content.js +38 -5
- package/src/query/utils.js +16 -1
- package/src/site-title/block.json +1 -4
- package/src/site-title/style.scss +4 -21
- package/src/social-link/edit.js +11 -7
|
@@ -14,7 +14,7 @@ import clsx from 'clsx';
|
|
|
14
14
|
import { __, sprintf } from '@wordpress/i18n';
|
|
15
15
|
import { Placeholder, SandBox } from '@wordpress/components';
|
|
16
16
|
import { BlockIcon } from '@wordpress/block-editor';
|
|
17
|
-
import {
|
|
17
|
+
import { useState } from '@wordpress/element';
|
|
18
18
|
import { getAuthority } from '@wordpress/url';
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -23,129 +23,113 @@ import { getAuthority } from '@wordpress/url';
|
|
|
23
23
|
import WpEmbedPreview from './wp-embed-preview';
|
|
24
24
|
import { Caption } from '../utils/caption';
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return { interactive: false };
|
|
41
|
-
}
|
|
26
|
+
export default function EmbedPreview( {
|
|
27
|
+
preview,
|
|
28
|
+
previewable,
|
|
29
|
+
url,
|
|
30
|
+
type,
|
|
31
|
+
isSelected,
|
|
32
|
+
className,
|
|
33
|
+
icon,
|
|
34
|
+
label,
|
|
35
|
+
insertBlocksAfter,
|
|
36
|
+
attributes,
|
|
37
|
+
setAttributes,
|
|
38
|
+
} ) {
|
|
39
|
+
const [ interactive, setInteractive ] = useState( false );
|
|
42
40
|
|
|
43
|
-
|
|
41
|
+
if ( ! isSelected && interactive ) {
|
|
42
|
+
// We only want to change this when the block is not selected, because changing it when
|
|
43
|
+
// the block becomes selected makes the overlap disappear too early. Hiding the overlay
|
|
44
|
+
// happens on mouseup when the overlay is clicked.
|
|
45
|
+
setInteractive( false );
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
hideOverlay() {
|
|
48
|
+
const hideOverlay = () => {
|
|
47
49
|
// This is called onMouseUp on the overlay. We can't respond to the `isSelected` prop
|
|
48
50
|
// changing, because that happens on mouse down, and the overlay immediately disappears,
|
|
49
51
|
// and the mouse event can end up in the preview content. We can't use onClick on
|
|
50
52
|
// the overlay to hide it either, because then the editor misses the mouseup event, and
|
|
51
53
|
// thinks we're multi-selecting blocks.
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
+
setInteractive( true );
|
|
55
|
+
};
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
const {
|
|
57
|
-
preview,
|
|
58
|
-
previewable,
|
|
59
|
-
url,
|
|
60
|
-
type,
|
|
61
|
-
className,
|
|
62
|
-
icon,
|
|
63
|
-
label,
|
|
64
|
-
insertBlocksAfter,
|
|
65
|
-
attributes,
|
|
66
|
-
setAttributes,
|
|
67
|
-
isSelected,
|
|
68
|
-
} = this.props;
|
|
69
|
-
const { scripts } = preview;
|
|
70
|
-
const { interactive } = this.state;
|
|
57
|
+
const { scripts } = preview;
|
|
71
58
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
59
|
+
const html = 'photo' === type ? getPhotoHtml( preview ) : preview.html;
|
|
60
|
+
const embedSourceUrl = getAuthority( url );
|
|
61
|
+
const iframeTitle = sprintf(
|
|
62
|
+
// translators: %s: host providing embed content e.g: www.youtube.com
|
|
63
|
+
__( 'Embedded content from %s' ),
|
|
64
|
+
embedSourceUrl
|
|
65
|
+
);
|
|
66
|
+
const sandboxClassnames = clsx(
|
|
67
|
+
type,
|
|
68
|
+
className,
|
|
69
|
+
'wp-block-embed__wrapper'
|
|
70
|
+
);
|
|
84
71
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
72
|
+
// Disabled because the overlay div doesn't actually have a role or functionality
|
|
73
|
+
// as far as the user is concerned. We're just catching the first click so that
|
|
74
|
+
// the block can be selected without interacting with the embed preview that the overlay covers.
|
|
75
|
+
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
76
|
+
const embedWrapper =
|
|
77
|
+
'wp-embed' === type ? (
|
|
78
|
+
<WpEmbedPreview html={ html } />
|
|
79
|
+
) : (
|
|
80
|
+
<div className="wp-block-embed__wrapper">
|
|
81
|
+
<SandBox
|
|
82
|
+
html={ html }
|
|
83
|
+
scripts={ scripts }
|
|
84
|
+
title={ iframeTitle }
|
|
85
|
+
type={ sandboxClassnames }
|
|
86
|
+
onFocus={ hideOverlay }
|
|
87
|
+
/>
|
|
88
|
+
{ ! interactive && (
|
|
89
|
+
<div
|
|
90
|
+
className="block-library-embed__interactive-overlay"
|
|
91
|
+
onMouseUp={ hideOverlay }
|
|
100
92
|
/>
|
|
101
|
-
{ ! interactive && (
|
|
102
|
-
<div
|
|
103
|
-
className="block-library-embed__interactive-overlay"
|
|
104
|
-
onMouseUp={ this.hideOverlay }
|
|
105
|
-
/>
|
|
106
|
-
) }
|
|
107
|
-
</div>
|
|
108
|
-
);
|
|
109
|
-
/* eslint-enable jsx-a11y/no-static-element-interactions */
|
|
110
|
-
|
|
111
|
-
return (
|
|
112
|
-
<figure
|
|
113
|
-
className={ clsx( className, 'wp-block-embed', {
|
|
114
|
-
'is-type-video': 'video' === type,
|
|
115
|
-
} ) }
|
|
116
|
-
>
|
|
117
|
-
{ previewable ? (
|
|
118
|
-
embedWrapper
|
|
119
|
-
) : (
|
|
120
|
-
<Placeholder
|
|
121
|
-
icon={ <BlockIcon icon={ icon } showColors /> }
|
|
122
|
-
label={ label }
|
|
123
|
-
>
|
|
124
|
-
<p className="components-placeholder__error">
|
|
125
|
-
<a href={ url }>{ url }</a>
|
|
126
|
-
</p>
|
|
127
|
-
<p className="components-placeholder__error">
|
|
128
|
-
{ sprintf(
|
|
129
|
-
/* translators: %s: host providing embed content e.g: www.youtube.com */
|
|
130
|
-
__(
|
|
131
|
-
"Embedded content from %s can't be previewed in the editor."
|
|
132
|
-
),
|
|
133
|
-
embedSourceUrl
|
|
134
|
-
) }
|
|
135
|
-
</p>
|
|
136
|
-
</Placeholder>
|
|
137
93
|
) }
|
|
138
|
-
|
|
139
|
-
attributes={ attributes }
|
|
140
|
-
setAttributes={ setAttributes }
|
|
141
|
-
isSelected={ isSelected }
|
|
142
|
-
insertBlocksAfter={ insertBlocksAfter }
|
|
143
|
-
label={ __( 'Embed caption text' ) }
|
|
144
|
-
showToolbarButton={ isSelected }
|
|
145
|
-
/>
|
|
146
|
-
</figure>
|
|
94
|
+
</div>
|
|
147
95
|
);
|
|
148
|
-
|
|
149
|
-
}
|
|
96
|
+
/* eslint-enable jsx-a11y/no-static-element-interactions */
|
|
150
97
|
|
|
151
|
-
|
|
98
|
+
return (
|
|
99
|
+
<figure
|
|
100
|
+
className={ clsx( className, 'wp-block-embed', {
|
|
101
|
+
'is-type-video': 'video' === type,
|
|
102
|
+
} ) }
|
|
103
|
+
>
|
|
104
|
+
{ previewable ? (
|
|
105
|
+
embedWrapper
|
|
106
|
+
) : (
|
|
107
|
+
<Placeholder
|
|
108
|
+
icon={ <BlockIcon icon={ icon } showColors /> }
|
|
109
|
+
label={ label }
|
|
110
|
+
>
|
|
111
|
+
<p className="components-placeholder__error">
|
|
112
|
+
<a href={ url }>{ url }</a>
|
|
113
|
+
</p>
|
|
114
|
+
<p className="components-placeholder__error">
|
|
115
|
+
{ sprintf(
|
|
116
|
+
/* translators: %s: host providing embed content e.g: www.youtube.com */
|
|
117
|
+
__(
|
|
118
|
+
"Embedded content from %s can't be previewed in the editor."
|
|
119
|
+
),
|
|
120
|
+
embedSourceUrl
|
|
121
|
+
) }
|
|
122
|
+
</p>
|
|
123
|
+
</Placeholder>
|
|
124
|
+
) }
|
|
125
|
+
<Caption
|
|
126
|
+
attributes={ attributes }
|
|
127
|
+
setAttributes={ setAttributes }
|
|
128
|
+
isSelected={ isSelected }
|
|
129
|
+
insertBlocksAfter={ insertBlocksAfter }
|
|
130
|
+
label={ __( 'Embed caption text' ) }
|
|
131
|
+
showToolbarButton={ isSelected }
|
|
132
|
+
/>
|
|
133
|
+
</figure>
|
|
134
|
+
);
|
|
135
|
+
}
|
package/src/image/image.js
CHANGED
|
@@ -559,7 +559,8 @@ export default function Image( {
|
|
|
559
559
|
const mediaReplaceFlow = isSingleSelected &&
|
|
560
560
|
! isEditingImage &&
|
|
561
561
|
! lockUrlControls && (
|
|
562
|
-
|
|
562
|
+
// For contentOnly mode, put this button in its own area so it has borders around it.
|
|
563
|
+
<BlockControls group={ isContentOnlyMode ? 'inline' : 'other' }>
|
|
563
564
|
<MediaReplaceFlow
|
|
564
565
|
mediaId={ id }
|
|
565
566
|
mediaURL={ url }
|
|
@@ -59,6 +59,19 @@
|
|
|
59
59
|
"supports": {
|
|
60
60
|
"reusable": false,
|
|
61
61
|
"html": false,
|
|
62
|
+
"typography": {
|
|
63
|
+
"fontSize": true,
|
|
64
|
+
"lineHeight": true,
|
|
65
|
+
"__experimentalFontFamily": true,
|
|
66
|
+
"__experimentalFontWeight": true,
|
|
67
|
+
"__experimentalFontStyle": true,
|
|
68
|
+
"__experimentalTextTransform": true,
|
|
69
|
+
"__experimentalTextDecoration": true,
|
|
70
|
+
"__experimentalLetterSpacing": true,
|
|
71
|
+
"__experimentalDefaultControls": {
|
|
72
|
+
"fontSize": true
|
|
73
|
+
}
|
|
74
|
+
},
|
|
62
75
|
"interactivity": {
|
|
63
76
|
"clientNavigation": true
|
|
64
77
|
}
|
|
@@ -90,6 +90,7 @@ export default function PostTemplateEdit( {
|
|
|
90
90
|
taxQuery,
|
|
91
91
|
parents,
|
|
92
92
|
pages,
|
|
93
|
+
format,
|
|
93
94
|
// We gather extra query args to pass to the REST API call.
|
|
94
95
|
// This way extenders of Query Loop can add their own query args,
|
|
95
96
|
// and have accurate previews in the editor.
|
|
@@ -163,6 +164,10 @@ export default function PostTemplateEdit( {
|
|
|
163
164
|
if ( parents?.length ) {
|
|
164
165
|
query.parent = parents;
|
|
165
166
|
}
|
|
167
|
+
if ( format?.length ) {
|
|
168
|
+
query.format = format;
|
|
169
|
+
}
|
|
170
|
+
|
|
166
171
|
// If sticky is not set, it will return all posts in the results.
|
|
167
172
|
// If sticky is set to `only`, it will limit the results to sticky posts only.
|
|
168
173
|
// If it is anything else, it will exclude sticky posts from results. For the record the value stored is `exclude`.
|
|
@@ -205,6 +210,7 @@ export default function PostTemplateEdit( {
|
|
|
205
210
|
templateSlug,
|
|
206
211
|
taxQuery,
|
|
207
212
|
parents,
|
|
213
|
+
format,
|
|
208
214
|
restQueryArgs,
|
|
209
215
|
previewPostType,
|
|
210
216
|
]
|
|
@@ -64,6 +64,11 @@ function render_block_core_post_template( $attributes, $content, $block ) {
|
|
|
64
64
|
if ( in_the_loop() ) {
|
|
65
65
|
$query = clone $wp_query;
|
|
66
66
|
$query->rewind_posts();
|
|
67
|
+
|
|
68
|
+
// If in a single post of any post type, default to the 'post' post type.
|
|
69
|
+
if ( is_singular() ) {
|
|
70
|
+
query_posts( array( 'post_type' => 'post' ) );
|
|
71
|
+
}
|
|
67
72
|
} else {
|
|
68
73
|
$query = $wp_query;
|
|
69
74
|
}
|
|
@@ -3,31 +3,14 @@
|
|
|
3
3
|
// This block has customizable padding, border-box makes that more predictable.
|
|
4
4
|
box-sizing: border-box;
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
&[class*="-font-family"] :where(a),
|
|
10
|
-
&[style*="font-family"] :where(a) {
|
|
6
|
+
:where(a) {
|
|
7
|
+
display: inline-block;
|
|
11
8
|
font-family: inherit;
|
|
12
|
-
}
|
|
13
|
-
&[class*="-font-size"] :where(a),
|
|
14
|
-
&[style*="font-size"] :where(a) {
|
|
15
9
|
font-size: inherit;
|
|
16
|
-
}
|
|
17
|
-
&[style*="line-height"] :where(a) {
|
|
18
|
-
line-height: inherit;
|
|
19
|
-
}
|
|
20
|
-
&[style*="font-style"] :where(a) {
|
|
21
10
|
font-style: inherit;
|
|
22
|
-
|
|
23
|
-
&[style*="letter-spacing"] :where(a) {
|
|
11
|
+
font-weight: inherit;
|
|
24
12
|
letter-spacing: inherit;
|
|
25
|
-
|
|
26
|
-
&[style*="text-decoration"] :where(a) {
|
|
13
|
+
line-height: inherit;
|
|
27
14
|
text-decoration: inherit;
|
|
28
15
|
}
|
|
29
|
-
|
|
30
|
-
a {
|
|
31
|
-
display: inline-block;
|
|
32
|
-
}
|
|
33
16
|
}
|
package/src/query/block.json
CHANGED
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"sticky": "",
|
|
26
26
|
"inherit": true,
|
|
27
27
|
"taxQuery": null,
|
|
28
|
-
"parents": []
|
|
28
|
+
"parents": [],
|
|
29
|
+
"format": []
|
|
29
30
|
}
|
|
30
31
|
},
|
|
31
32
|
"tagName": {
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
"default": false
|
|
41
42
|
}
|
|
42
43
|
},
|
|
44
|
+
"usesContext": [ "postType" ],
|
|
43
45
|
"providesContext": {
|
|
44
46
|
"queryId": "queryId",
|
|
45
47
|
"query": "query",
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { FormTokenField } from '@wordpress/components';
|
|
5
|
+
import { useSelect } from '@wordpress/data';
|
|
6
|
+
import { store as coreStore } from '@wordpress/core-data';
|
|
7
|
+
import { __ } from '@wordpress/i18n';
|
|
8
|
+
|
|
9
|
+
// All WP post formats, sorted alphabetically by translated name.
|
|
10
|
+
// Value is the post format slug. Label is the name.
|
|
11
|
+
const POST_FORMATS = [
|
|
12
|
+
{ value: 'aside', label: __( 'Aside' ) },
|
|
13
|
+
{ value: 'audio', label: __( 'Audio' ) },
|
|
14
|
+
{ value: 'chat', label: __( 'Chat' ) },
|
|
15
|
+
{ value: 'gallery', label: __( 'Gallery' ) },
|
|
16
|
+
{ value: 'image', label: __( 'Image' ) },
|
|
17
|
+
{ value: 'link', label: __( 'Link' ) },
|
|
18
|
+
{ value: 'quote', label: __( 'Quote' ) },
|
|
19
|
+
{ value: 'standard', label: __( 'Standard' ) },
|
|
20
|
+
{ value: 'status', label: __( 'Status' ) },
|
|
21
|
+
{ value: 'video', label: __( 'Video' ) },
|
|
22
|
+
].sort( ( a, b ) => {
|
|
23
|
+
const normalizedA = a.label.toUpperCase();
|
|
24
|
+
const normalizedB = b.label.toUpperCase();
|
|
25
|
+
|
|
26
|
+
if ( normalizedA < normalizedB ) {
|
|
27
|
+
return -1;
|
|
28
|
+
}
|
|
29
|
+
if ( normalizedA > normalizedB ) {
|
|
30
|
+
return 1;
|
|
31
|
+
}
|
|
32
|
+
return 0;
|
|
33
|
+
} );
|
|
34
|
+
|
|
35
|
+
// A helper function to convert translatable post format names into their static values.
|
|
36
|
+
function formatNamesToValues( names, formats ) {
|
|
37
|
+
return names
|
|
38
|
+
.map( ( name ) => {
|
|
39
|
+
return formats.find(
|
|
40
|
+
( item ) =>
|
|
41
|
+
item.label.toLocaleLowerCase() === name.toLocaleLowerCase()
|
|
42
|
+
)?.value;
|
|
43
|
+
} )
|
|
44
|
+
.filter( Boolean );
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default function FormatControls( { onChange, query: { format } } ) {
|
|
48
|
+
// 'format' is expected to be an array. If it is not an array, for example
|
|
49
|
+
// if a user has manually entered an invalid value in the block markup,
|
|
50
|
+
// convert it to an array to prevent JavaScript errors.
|
|
51
|
+
const normalizedFormats = Array.isArray( format ) ? format : [ format ];
|
|
52
|
+
|
|
53
|
+
const { supportedFormats } = useSelect( ( select ) => {
|
|
54
|
+
const themeSupports = select( coreStore ).getThemeSupports();
|
|
55
|
+
return {
|
|
56
|
+
supportedFormats: themeSupports.formats,
|
|
57
|
+
};
|
|
58
|
+
}, [] );
|
|
59
|
+
|
|
60
|
+
const formats = POST_FORMATS.filter( ( item ) =>
|
|
61
|
+
supportedFormats.includes( item.value )
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const values = normalizedFormats
|
|
65
|
+
.map(
|
|
66
|
+
( name ) => formats.find( ( item ) => item.value === name )?.label
|
|
67
|
+
)
|
|
68
|
+
.filter( Boolean );
|
|
69
|
+
|
|
70
|
+
const suggestions = formats
|
|
71
|
+
.filter( ( item ) => ! format.includes( item.value ) )
|
|
72
|
+
.map( ( item ) => item.label );
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<FormTokenField
|
|
76
|
+
label={ __( 'Formats' ) }
|
|
77
|
+
value={ values }
|
|
78
|
+
suggestions={ suggestions }
|
|
79
|
+
onChange={ ( newValues ) => {
|
|
80
|
+
onChange( {
|
|
81
|
+
format: formatNamesToValues( newValues, formats ),
|
|
82
|
+
} );
|
|
83
|
+
} }
|
|
84
|
+
__experimentalShowHowTo={ false }
|
|
85
|
+
__experimentalExpandOnFocus
|
|
86
|
+
__nextHasNoMarginBottom
|
|
87
|
+
__next40pxDefaultSize
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
__experimentalToolsPanel as ToolsPanel,
|
|
13
13
|
__experimentalToolsPanelItem as ToolsPanelItem,
|
|
14
14
|
} from '@wordpress/components';
|
|
15
|
+
import { useSelect } from '@wordpress/data';
|
|
16
|
+
import { store as coreStore } from '@wordpress/core-data';
|
|
15
17
|
import { __ } from '@wordpress/i18n';
|
|
16
18
|
import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
|
|
17
19
|
import { debounce } from '@wordpress/compose';
|
|
@@ -24,6 +26,7 @@ import OrderControl from './order-control';
|
|
|
24
26
|
import AuthorControl from './author-control';
|
|
25
27
|
import ParentControl from './parent-control';
|
|
26
28
|
import { TaxonomyControls } from './taxonomy-controls';
|
|
29
|
+
import FormatControls from './format-controls';
|
|
27
30
|
import StickyControl from './sticky-control';
|
|
28
31
|
import CreateNewPostLink from './create-new-post-link';
|
|
29
32
|
import PerPageControl from './per-page-control';
|
|
@@ -42,7 +45,7 @@ import { useToolsPanelDropdownMenuProps } from '../../../utils/hooks';
|
|
|
42
45
|
const { BlockInfo } = unlock( blockEditorPrivateApis );
|
|
43
46
|
|
|
44
47
|
export default function QueryInspectorControls( props ) {
|
|
45
|
-
const { attributes, setQuery, setDisplayLayout } = props;
|
|
48
|
+
const { attributes, setQuery, setDisplayLayout, isTemplate } = props;
|
|
46
49
|
const { query, displayLayout } = attributes;
|
|
47
50
|
const {
|
|
48
51
|
order,
|
|
@@ -56,10 +59,15 @@ export default function QueryInspectorControls( props ) {
|
|
|
56
59
|
inherit,
|
|
57
60
|
taxQuery,
|
|
58
61
|
parents,
|
|
62
|
+
format,
|
|
59
63
|
} = query;
|
|
60
64
|
const allowedControls = useAllowedControls( attributes );
|
|
61
65
|
const [ showSticky, setShowSticky ] = useState( postType === 'post' );
|
|
62
|
-
const {
|
|
66
|
+
const {
|
|
67
|
+
postTypesTaxonomiesMap,
|
|
68
|
+
postTypesSelectOptions,
|
|
69
|
+
postTypeFormatSupportMap,
|
|
70
|
+
} = usePostTypes();
|
|
63
71
|
const taxonomies = useTaxonomies( postType );
|
|
64
72
|
const isPostTypeHierarchical = useIsPostTypeHierarchical( postType );
|
|
65
73
|
useEffect( () => {
|
|
@@ -88,6 +96,14 @@ export default function QueryInspectorControls( props ) {
|
|
|
88
96
|
}
|
|
89
97
|
// We need to reset `parents` because they are tied to each post type.
|
|
90
98
|
updateQuery.parents = [];
|
|
99
|
+
// Post types can register post format support with `add_post_type_support`.
|
|
100
|
+
// But we need to reset the `format` property when switching to post types
|
|
101
|
+
// that do not support post formats.
|
|
102
|
+
const hasFormatSupport = postTypeFormatSupportMap[ newValue ];
|
|
103
|
+
if ( ! hasFormatSupport ) {
|
|
104
|
+
updateQuery.format = [];
|
|
105
|
+
}
|
|
106
|
+
|
|
91
107
|
setQuery( updateQuery );
|
|
92
108
|
};
|
|
93
109
|
const [ querySearch, setQuerySearch ] = useState( query.search );
|
|
@@ -103,20 +119,25 @@ export default function QueryInspectorControls( props ) {
|
|
|
103
119
|
onChangeDebounced();
|
|
104
120
|
return onChangeDebounced.cancel;
|
|
105
121
|
}, [ querySearch, onChangeDebounced ] );
|
|
106
|
-
|
|
122
|
+
|
|
123
|
+
const showInheritControl =
|
|
124
|
+
isTemplate && isControlAllowed( allowedControls, 'inherit' );
|
|
107
125
|
const showPostTypeControl =
|
|
108
|
-
! inherit && isControlAllowed( allowedControls, 'postType' )
|
|
126
|
+
( ! inherit && isControlAllowed( allowedControls, 'postType' ) ) ||
|
|
127
|
+
! isTemplate;
|
|
109
128
|
const postTypeControlLabel = __( 'Post type' );
|
|
110
129
|
const postTypeControlHelp = __(
|
|
111
130
|
'Select the type of content to display: posts, pages, or custom post types.'
|
|
112
131
|
);
|
|
113
132
|
const showColumnsControl = false;
|
|
114
133
|
const showOrderControl =
|
|
115
|
-
! inherit && isControlAllowed( allowedControls, 'order' )
|
|
134
|
+
( ! inherit && isControlAllowed( allowedControls, 'order' ) ) ||
|
|
135
|
+
! isTemplate;
|
|
116
136
|
const showStickyControl =
|
|
117
|
-
! inherit &&
|
|
118
|
-
|
|
119
|
-
|
|
137
|
+
( ! inherit &&
|
|
138
|
+
showSticky &&
|
|
139
|
+
isControlAllowed( allowedControls, 'sticky' ) ) ||
|
|
140
|
+
( showSticky && ! isTemplate );
|
|
120
141
|
const showSettingsPanel =
|
|
121
142
|
showInheritControl ||
|
|
122
143
|
showPostTypeControl ||
|
|
@@ -132,11 +153,36 @@ export default function QueryInspectorControls( props ) {
|
|
|
132
153
|
isControlAllowed( allowedControls, 'parents' ) &&
|
|
133
154
|
isPostTypeHierarchical;
|
|
134
155
|
|
|
156
|
+
const postTypeHasFormatSupport = postTypeFormatSupportMap[ postType ];
|
|
157
|
+
const showFormatControl = useSelect(
|
|
158
|
+
( select ) => {
|
|
159
|
+
// Check if the post type supports post formats and if the control is allowed.
|
|
160
|
+
if (
|
|
161
|
+
! postTypeHasFormatSupport ||
|
|
162
|
+
! isControlAllowed( allowedControls, 'format' )
|
|
163
|
+
) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const themeSupports = select( coreStore ).getThemeSupports();
|
|
168
|
+
|
|
169
|
+
// If there are no supported formats, getThemeSupports still includes the default 'standard' format,
|
|
170
|
+
// and in this case the control should not be shown since the user has no other formats to choose from.
|
|
171
|
+
return (
|
|
172
|
+
themeSupports.formats &&
|
|
173
|
+
themeSupports.formats.length > 0 &&
|
|
174
|
+
themeSupports.formats.some( ( type ) => type !== 'standard' )
|
|
175
|
+
);
|
|
176
|
+
},
|
|
177
|
+
[ allowedControls, postTypeHasFormatSupport ]
|
|
178
|
+
);
|
|
179
|
+
|
|
135
180
|
const showFiltersPanel =
|
|
136
181
|
showTaxControl ||
|
|
137
182
|
showAuthorControl ||
|
|
138
183
|
showSearchControl ||
|
|
139
|
-
showParentControl
|
|
184
|
+
showParentControl ||
|
|
185
|
+
showFormatControl;
|
|
140
186
|
const dropdownMenuProps = useToolsPanelDropdownMenuProps();
|
|
141
187
|
|
|
142
188
|
const showPostCountControl = isControlAllowed(
|
|
@@ -313,6 +359,7 @@ export default function QueryInspectorControls( props ) {
|
|
|
313
359
|
parents: [],
|
|
314
360
|
search: '',
|
|
315
361
|
taxQuery: null,
|
|
362
|
+
format: [],
|
|
316
363
|
} );
|
|
317
364
|
setQuerySearch( '' );
|
|
318
365
|
} }
|
|
@@ -374,6 +421,18 @@ export default function QueryInspectorControls( props ) {
|
|
|
374
421
|
/>
|
|
375
422
|
</ToolsPanelItem>
|
|
376
423
|
) }
|
|
424
|
+
{ showFormatControl && (
|
|
425
|
+
<ToolsPanelItem
|
|
426
|
+
hasValue={ () => !! format?.length }
|
|
427
|
+
label={ __( 'Formats' ) }
|
|
428
|
+
onDeselect={ () => setQuery( { format: [] } ) }
|
|
429
|
+
>
|
|
430
|
+
<FormatControls
|
|
431
|
+
onChange={ setQuery }
|
|
432
|
+
query={ query }
|
|
433
|
+
/>
|
|
434
|
+
</ToolsPanelItem>
|
|
435
|
+
) }
|
|
377
436
|
</ToolsPanel>
|
|
378
437
|
) }
|
|
379
438
|
</>
|