@wordpress/edit-site 6.35.1-next.16d95556a.0 → 6.36.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 +6 -0
- package/build/components/add-new-template-legacy/add-custom-generic-template-modal-content.js +109 -0
- package/build/components/add-new-template-legacy/add-custom-generic-template-modal-content.js.map +7 -0
- package/build/components/add-new-template-legacy/add-custom-template-modal-content.js +328 -0
- package/build/components/add-new-template-legacy/add-custom-template-modal-content.js.map +7 -0
- package/build/components/add-new-template-legacy/index.js +389 -0
- package/build/components/add-new-template-legacy/index.js.map +7 -0
- package/build/components/add-new-template-legacy/utils.js +620 -0
- package/build/components/add-new-template-legacy/utils.js.map +7 -0
- package/build/components/page-templates/fields.js +3 -1
- package/build/components/page-templates/fields.js.map +2 -2
- package/build/components/page-templates/index-legacy.js +185 -0
- package/build/components/page-templates/index-legacy.js.map +7 -0
- package/build/components/post-list/index.js +10 -0
- package/build/components/post-list/index.js.map +2 -2
- package/build/components/sidebar-navigation-screen-templates-browse/content-legacy.js +101 -0
- package/build/components/sidebar-navigation-screen-templates-browse/content-legacy.js.map +7 -0
- package/build/components/sidebar-navigation-screen-templates-browse/index.js +2 -1
- package/build/components/sidebar-navigation-screen-templates-browse/index.js.map +3 -3
- package/build/components/site-editor-routes/templates.js +10 -2
- package/build/components/site-editor-routes/templates.js.map +3 -3
- package/build/components/site-hub/index.js +1 -1
- package/build/components/site-hub/index.js.map +2 -2
- package/build/utils/constants.js +6 -0
- package/build/utils/constants.js.map +2 -2
- package/build-module/components/add-new-template-legacy/add-custom-generic-template-modal-content.js +93 -0
- package/build-module/components/add-new-template-legacy/add-custom-generic-template-modal-content.js.map +7 -0
- package/build-module/components/add-new-template-legacy/add-custom-template-modal-content.js +316 -0
- package/build-module/components/add-new-template-legacy/add-custom-template-modal-content.js.map +7 -0
- package/build-module/components/add-new-template-legacy/index.js +390 -0
- package/build-module/components/add-new-template-legacy/index.js.map +7 -0
- package/build-module/components/add-new-template-legacy/utils.js +589 -0
- package/build-module/components/add-new-template-legacy/utils.js.map +7 -0
- package/build-module/components/page-templates/fields.js +3 -1
- package/build-module/components/page-templates/fields.js.map +2 -2
- package/build-module/components/page-templates/index-legacy.js +154 -0
- package/build-module/components/page-templates/index-legacy.js.map +7 -0
- package/build-module/components/post-list/index.js +12 -0
- package/build-module/components/post-list/index.js.map +2 -2
- package/build-module/components/sidebar-navigation-screen-templates-browse/content-legacy.js +70 -0
- package/build-module/components/sidebar-navigation-screen-templates-browse/content-legacy.js.map +7 -0
- package/build-module/components/sidebar-navigation-screen-templates-browse/index.js +2 -1
- package/build-module/components/sidebar-navigation-screen-templates-browse/index.js.map +2 -2
- package/build-module/components/site-editor-routes/templates.js +10 -2
- package/build-module/components/site-editor-routes/templates.js.map +2 -2
- package/build-module/components/site-hub/index.js +1 -1
- package/build-module/components/site-hub/index.js.map +2 -2
- package/build-module/utils/constants.js +4 -0
- package/build-module/utils/constants.js.map +2 -2
- package/build-style/style-rtl.css +309 -40
- package/build-style/style.css +309 -40
- package/package.json +46 -46
- package/src/components/add-new-template-legacy/add-custom-generic-template-modal-content.js +94 -0
- package/src/components/add-new-template-legacy/add-custom-template-modal-content.js +314 -0
- package/src/components/add-new-template-legacy/index.js +454 -0
- package/src/components/add-new-template-legacy/utils.js +760 -0
- package/src/components/page-templates/fields.js +13 -9
- package/src/components/page-templates/index-legacy.js +166 -0
- package/src/components/post-list/index.js +13 -0
- package/src/components/sidebar-navigation-screen-templates-browse/content-legacy.js +79 -0
- package/src/components/sidebar-navigation-screen-templates-browse/index.js +8 -1
- package/src/components/site-editor-routes/templates.js +22 -3
- package/src/components/site-hub/index.js +1 -1
- package/src/components/welcome-guide/style.scss +8 -0
- package/src/utils/constants.js +2 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { paramCase as kebabCase } from 'change-case';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* WordPress dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { useState, useEffect, useRef } from '@wordpress/element';
|
|
10
|
+
import { __ } from '@wordpress/i18n';
|
|
11
|
+
import {
|
|
12
|
+
Button,
|
|
13
|
+
TextControl,
|
|
14
|
+
__experimentalHStack as HStack,
|
|
15
|
+
__experimentalVStack as VStack,
|
|
16
|
+
} from '@wordpress/components';
|
|
17
|
+
|
|
18
|
+
function AddCustomGenericTemplateModalContent( { createTemplate, onBack } ) {
|
|
19
|
+
const [ title, setTitle ] = useState( '' );
|
|
20
|
+
const defaultTitle = __( 'Custom Template' );
|
|
21
|
+
const [ isBusy, setIsBusy ] = useState( false );
|
|
22
|
+
const inputRef = useRef();
|
|
23
|
+
|
|
24
|
+
// Set focus to the name input when the component mounts
|
|
25
|
+
useEffect( () => {
|
|
26
|
+
if ( inputRef.current ) {
|
|
27
|
+
inputRef.current.focus();
|
|
28
|
+
}
|
|
29
|
+
}, [] );
|
|
30
|
+
|
|
31
|
+
async function onCreateTemplate( event ) {
|
|
32
|
+
event.preventDefault();
|
|
33
|
+
if ( isBusy ) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
setIsBusy( true );
|
|
37
|
+
try {
|
|
38
|
+
await createTemplate(
|
|
39
|
+
{
|
|
40
|
+
slug:
|
|
41
|
+
kebabCase( title || defaultTitle ) ||
|
|
42
|
+
'wp-custom-template',
|
|
43
|
+
title: title || defaultTitle,
|
|
44
|
+
},
|
|
45
|
+
false
|
|
46
|
+
);
|
|
47
|
+
} finally {
|
|
48
|
+
setIsBusy( false );
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return (
|
|
52
|
+
<form onSubmit={ onCreateTemplate }>
|
|
53
|
+
<VStack spacing={ 6 }>
|
|
54
|
+
<TextControl
|
|
55
|
+
__next40pxDefaultSize
|
|
56
|
+
__nextHasNoMarginBottom
|
|
57
|
+
label={ __( 'Name' ) }
|
|
58
|
+
value={ title }
|
|
59
|
+
onChange={ setTitle }
|
|
60
|
+
placeholder={ defaultTitle }
|
|
61
|
+
disabled={ isBusy }
|
|
62
|
+
ref={ inputRef }
|
|
63
|
+
help={ __(
|
|
64
|
+
// eslint-disable-next-line no-restricted-syntax -- 'sidebar' is a common web design term for layouts
|
|
65
|
+
'Describe the template, e.g. "Post with sidebar". A custom template can be manually applied to any post or page.'
|
|
66
|
+
) }
|
|
67
|
+
/>
|
|
68
|
+
<HStack
|
|
69
|
+
className="edit-site-custom-generic-template__modal-actions"
|
|
70
|
+
justify="right"
|
|
71
|
+
>
|
|
72
|
+
<Button
|
|
73
|
+
__next40pxDefaultSize
|
|
74
|
+
variant="tertiary"
|
|
75
|
+
onClick={ onBack }
|
|
76
|
+
>
|
|
77
|
+
{ __( 'Back' ) }
|
|
78
|
+
</Button>
|
|
79
|
+
<Button
|
|
80
|
+
__next40pxDefaultSize
|
|
81
|
+
variant="primary"
|
|
82
|
+
type="submit"
|
|
83
|
+
isBusy={ isBusy }
|
|
84
|
+
aria-disabled={ isBusy }
|
|
85
|
+
>
|
|
86
|
+
{ __( 'Create' ) }
|
|
87
|
+
</Button>
|
|
88
|
+
</HStack>
|
|
89
|
+
</VStack>
|
|
90
|
+
</form>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default AddCustomGenericTemplateModalContent;
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useState, useMemo, useEffect } from '@wordpress/element';
|
|
5
|
+
import { __ } from '@wordpress/i18n';
|
|
6
|
+
import {
|
|
7
|
+
Button,
|
|
8
|
+
Flex,
|
|
9
|
+
FlexItem,
|
|
10
|
+
SearchControl,
|
|
11
|
+
TextHighlight,
|
|
12
|
+
Composite,
|
|
13
|
+
__experimentalText as Text,
|
|
14
|
+
__experimentalVStack as VStack,
|
|
15
|
+
} from '@wordpress/components';
|
|
16
|
+
import { useEntityRecords } from '@wordpress/core-data';
|
|
17
|
+
import { decodeEntities } from '@wordpress/html-entities';
|
|
18
|
+
import { useDebouncedInput } from '@wordpress/compose';
|
|
19
|
+
import { focus } from '@wordpress/dom';
|
|
20
|
+
import { safeDecodeURI } from '@wordpress/url';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Internal dependencies
|
|
24
|
+
*/
|
|
25
|
+
import { mapToIHasNameAndId } from './utils';
|
|
26
|
+
|
|
27
|
+
const EMPTY_ARRAY = [];
|
|
28
|
+
|
|
29
|
+
function SuggestionListItem( {
|
|
30
|
+
suggestion,
|
|
31
|
+
search,
|
|
32
|
+
onSelect,
|
|
33
|
+
entityForSuggestions,
|
|
34
|
+
} ) {
|
|
35
|
+
const baseCssClass =
|
|
36
|
+
'edit-site-custom-template-modal__suggestions_list__list-item';
|
|
37
|
+
return (
|
|
38
|
+
<Composite.Item
|
|
39
|
+
render={
|
|
40
|
+
<Button
|
|
41
|
+
__next40pxDefaultSize
|
|
42
|
+
role="option"
|
|
43
|
+
className={ baseCssClass }
|
|
44
|
+
onClick={ () =>
|
|
45
|
+
onSelect(
|
|
46
|
+
entityForSuggestions.config.getSpecificTemplate(
|
|
47
|
+
suggestion
|
|
48
|
+
)
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
/>
|
|
52
|
+
}
|
|
53
|
+
>
|
|
54
|
+
<Text
|
|
55
|
+
size="body"
|
|
56
|
+
lineHeight={ 1.53846153846 } // 20px
|
|
57
|
+
weight={ 500 }
|
|
58
|
+
className={ `${ baseCssClass }__title` }
|
|
59
|
+
>
|
|
60
|
+
<TextHighlight
|
|
61
|
+
text={ decodeEntities( suggestion.name ) }
|
|
62
|
+
highlight={ search }
|
|
63
|
+
/>
|
|
64
|
+
</Text>
|
|
65
|
+
{ suggestion.link && (
|
|
66
|
+
<Text
|
|
67
|
+
size="body"
|
|
68
|
+
lineHeight={ 1.53846153846 } // 20px
|
|
69
|
+
className={ `${ baseCssClass }__info` }
|
|
70
|
+
>
|
|
71
|
+
{ safeDecodeURI( suggestion.link ) }
|
|
72
|
+
</Text>
|
|
73
|
+
) }
|
|
74
|
+
</Composite.Item>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function useSearchSuggestions( entityForSuggestions, search ) {
|
|
79
|
+
const { config } = entityForSuggestions;
|
|
80
|
+
const query = useMemo(
|
|
81
|
+
() => ( {
|
|
82
|
+
order: 'asc',
|
|
83
|
+
context: 'view',
|
|
84
|
+
search,
|
|
85
|
+
per_page: search ? 20 : 10,
|
|
86
|
+
...config.queryArgs( search ),
|
|
87
|
+
} ),
|
|
88
|
+
[ search, config ]
|
|
89
|
+
);
|
|
90
|
+
const { records: searchResults, hasResolved: searchHasResolved } =
|
|
91
|
+
useEntityRecords(
|
|
92
|
+
entityForSuggestions.type,
|
|
93
|
+
entityForSuggestions.slug,
|
|
94
|
+
query
|
|
95
|
+
);
|
|
96
|
+
const [ suggestions, setSuggestions ] = useState( EMPTY_ARRAY );
|
|
97
|
+
useEffect( () => {
|
|
98
|
+
if ( ! searchHasResolved ) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
let newSuggestions = EMPTY_ARRAY;
|
|
102
|
+
if ( searchResults?.length ) {
|
|
103
|
+
newSuggestions = searchResults;
|
|
104
|
+
if ( config.recordNamePath ) {
|
|
105
|
+
newSuggestions = mapToIHasNameAndId(
|
|
106
|
+
newSuggestions,
|
|
107
|
+
config.recordNamePath
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Update suggestions only when the query has resolved, so as to keep
|
|
112
|
+
// the previous results in the UI.
|
|
113
|
+
setSuggestions( newSuggestions );
|
|
114
|
+
}, [ searchResults, searchHasResolved ] );
|
|
115
|
+
return suggestions;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function SuggestionList( { entityForSuggestions, onSelect } ) {
|
|
119
|
+
const [ search, setSearch, debouncedSearch ] = useDebouncedInput();
|
|
120
|
+
const suggestions = useSearchSuggestions(
|
|
121
|
+
entityForSuggestions,
|
|
122
|
+
debouncedSearch
|
|
123
|
+
);
|
|
124
|
+
const { labels } = entityForSuggestions;
|
|
125
|
+
const [ showSearchControl, setShowSearchControl ] = useState( false );
|
|
126
|
+
if ( ! showSearchControl && suggestions?.length > 9 ) {
|
|
127
|
+
setShowSearchControl( true );
|
|
128
|
+
}
|
|
129
|
+
return (
|
|
130
|
+
<>
|
|
131
|
+
{ showSearchControl && (
|
|
132
|
+
<SearchControl
|
|
133
|
+
__nextHasNoMarginBottom
|
|
134
|
+
onChange={ setSearch }
|
|
135
|
+
value={ search }
|
|
136
|
+
label={ labels.search_items }
|
|
137
|
+
placeholder={ labels.search_items }
|
|
138
|
+
/>
|
|
139
|
+
) }
|
|
140
|
+
{ !! suggestions?.length && (
|
|
141
|
+
<Composite
|
|
142
|
+
orientation="vertical"
|
|
143
|
+
role="listbox"
|
|
144
|
+
className="edit-site-custom-template-modal__suggestions_list"
|
|
145
|
+
aria-label={ __( 'Suggestions list' ) }
|
|
146
|
+
>
|
|
147
|
+
{ suggestions.map( ( suggestion ) => (
|
|
148
|
+
<SuggestionListItem
|
|
149
|
+
key={ suggestion.slug }
|
|
150
|
+
suggestion={ suggestion }
|
|
151
|
+
search={ debouncedSearch }
|
|
152
|
+
onSelect={ onSelect }
|
|
153
|
+
entityForSuggestions={ entityForSuggestions }
|
|
154
|
+
/>
|
|
155
|
+
) ) }
|
|
156
|
+
</Composite>
|
|
157
|
+
) }
|
|
158
|
+
{ debouncedSearch && ! suggestions?.length && (
|
|
159
|
+
<Text
|
|
160
|
+
as="p"
|
|
161
|
+
className="edit-site-custom-template-modal__no-results"
|
|
162
|
+
>
|
|
163
|
+
{ labels.not_found }
|
|
164
|
+
</Text>
|
|
165
|
+
) }
|
|
166
|
+
</>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function AddCustomTemplateModalContent( {
|
|
171
|
+
onSelect,
|
|
172
|
+
entityForSuggestions,
|
|
173
|
+
onBack,
|
|
174
|
+
containerRef,
|
|
175
|
+
} ) {
|
|
176
|
+
const [ showSearchEntities, setShowSearchEntities ] = useState(
|
|
177
|
+
entityForSuggestions.hasGeneralTemplate
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
// Focus on the first focusable element when the modal opens.
|
|
181
|
+
// We handle focus management in the parent modal, just need to focus on the first focusable element.
|
|
182
|
+
useEffect( () => {
|
|
183
|
+
if ( containerRef.current ) {
|
|
184
|
+
const [ firstFocusable ] = focus.focusable.find(
|
|
185
|
+
containerRef.current
|
|
186
|
+
);
|
|
187
|
+
firstFocusable?.focus();
|
|
188
|
+
}
|
|
189
|
+
}, [ showSearchEntities ] );
|
|
190
|
+
|
|
191
|
+
return (
|
|
192
|
+
<VStack
|
|
193
|
+
spacing={ 4 }
|
|
194
|
+
className="edit-site-custom-template-modal__contents-wrapper"
|
|
195
|
+
alignment="left"
|
|
196
|
+
>
|
|
197
|
+
{ ! showSearchEntities && (
|
|
198
|
+
<>
|
|
199
|
+
<Text as="p">
|
|
200
|
+
{ __(
|
|
201
|
+
'Select whether to create a single template for all items or a specific one.'
|
|
202
|
+
) }
|
|
203
|
+
</Text>
|
|
204
|
+
<Flex
|
|
205
|
+
className="edit-site-custom-template-modal__contents"
|
|
206
|
+
gap="4"
|
|
207
|
+
align="initial"
|
|
208
|
+
>
|
|
209
|
+
<FlexItem
|
|
210
|
+
isBlock
|
|
211
|
+
as={ Button }
|
|
212
|
+
onClick={ () => {
|
|
213
|
+
const {
|
|
214
|
+
slug,
|
|
215
|
+
title,
|
|
216
|
+
description,
|
|
217
|
+
templatePrefix,
|
|
218
|
+
} = entityForSuggestions.template;
|
|
219
|
+
onSelect( {
|
|
220
|
+
slug,
|
|
221
|
+
title,
|
|
222
|
+
description,
|
|
223
|
+
templatePrefix,
|
|
224
|
+
} );
|
|
225
|
+
} }
|
|
226
|
+
>
|
|
227
|
+
<Text
|
|
228
|
+
as="span"
|
|
229
|
+
weight={ 500 }
|
|
230
|
+
lineHeight={ 1.53846153846 } // 20px
|
|
231
|
+
>
|
|
232
|
+
{ entityForSuggestions.labels.all_items }
|
|
233
|
+
</Text>
|
|
234
|
+
<Text
|
|
235
|
+
as="span"
|
|
236
|
+
lineHeight={ 1.53846153846 } // 20px
|
|
237
|
+
>
|
|
238
|
+
{
|
|
239
|
+
// translators: The user is given the choice to set up a template for all items of a post type or taxonomy, or just a specific one.
|
|
240
|
+
__( 'For all items' )
|
|
241
|
+
}
|
|
242
|
+
</Text>
|
|
243
|
+
</FlexItem>
|
|
244
|
+
<FlexItem
|
|
245
|
+
isBlock
|
|
246
|
+
as={ Button }
|
|
247
|
+
onClick={ () => {
|
|
248
|
+
setShowSearchEntities( true );
|
|
249
|
+
} }
|
|
250
|
+
>
|
|
251
|
+
<Text
|
|
252
|
+
as="span"
|
|
253
|
+
weight={ 500 }
|
|
254
|
+
lineHeight={ 1.53846153846 } // 20px
|
|
255
|
+
>
|
|
256
|
+
{ entityForSuggestions.labels.singular_name }
|
|
257
|
+
</Text>
|
|
258
|
+
<Text
|
|
259
|
+
as="span"
|
|
260
|
+
lineHeight={ 1.53846153846 } // 20px
|
|
261
|
+
>
|
|
262
|
+
{
|
|
263
|
+
// translators: The user is given the choice to set up a template for all items of a post type or taxonomy, or just a specific one.
|
|
264
|
+
__( 'For a specific item' )
|
|
265
|
+
}
|
|
266
|
+
</Text>
|
|
267
|
+
</FlexItem>
|
|
268
|
+
</Flex>
|
|
269
|
+
<Flex justify="right">
|
|
270
|
+
<Button
|
|
271
|
+
__next40pxDefaultSize
|
|
272
|
+
variant="tertiary"
|
|
273
|
+
onClick={ onBack }
|
|
274
|
+
>
|
|
275
|
+
{ __( 'Back' ) }
|
|
276
|
+
</Button>
|
|
277
|
+
</Flex>
|
|
278
|
+
</>
|
|
279
|
+
) }
|
|
280
|
+
{ showSearchEntities && (
|
|
281
|
+
<>
|
|
282
|
+
<Text as="p">
|
|
283
|
+
{ __(
|
|
284
|
+
'This template will be used only for the specific item chosen.'
|
|
285
|
+
) }
|
|
286
|
+
</Text>
|
|
287
|
+
<SuggestionList
|
|
288
|
+
entityForSuggestions={ entityForSuggestions }
|
|
289
|
+
onSelect={ onSelect }
|
|
290
|
+
/>
|
|
291
|
+
<Flex justify="right">
|
|
292
|
+
<Button
|
|
293
|
+
__next40pxDefaultSize
|
|
294
|
+
variant="tertiary"
|
|
295
|
+
onClick={ () => {
|
|
296
|
+
// If general template exists, go directly back to main screen
|
|
297
|
+
// instead of showing the choice screen
|
|
298
|
+
if ( entityForSuggestions.hasGeneralTemplate ) {
|
|
299
|
+
onBack();
|
|
300
|
+
} else {
|
|
301
|
+
setShowSearchEntities( false );
|
|
302
|
+
}
|
|
303
|
+
} }
|
|
304
|
+
>
|
|
305
|
+
{ __( 'Back' ) }
|
|
306
|
+
</Button>
|
|
307
|
+
</Flex>
|
|
308
|
+
</>
|
|
309
|
+
) }
|
|
310
|
+
</VStack>
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export default AddCustomTemplateModalContent;
|