@wordpress/fields 0.5.0 → 0.5.1-next.a9f418477.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/README.md +52 -27
- package/build/actions/delete-post.js +4 -0
- package/build/actions/delete-post.js.map +1 -1
- package/build/actions/duplicate-pattern.js +4 -0
- package/build/actions/duplicate-pattern.js.map +1 -1
- package/build/actions/duplicate-post.js +7 -3
- package/build/actions/duplicate-post.js.map +1 -1
- package/build/actions/duplicate-template-part.js +71 -0
- package/build/actions/duplicate-template-part.js.map +1 -0
- package/build/actions/export-pattern.js +4 -0
- package/build/actions/export-pattern.js.map +1 -1
- package/build/actions/index.js +3 -17
- package/build/actions/index.js.map +1 -1
- package/build/actions/permanently-delete-post.js +4 -1
- package/build/actions/permanently-delete-post.js.map +1 -1
- package/build/actions/rename-post.js +6 -2
- package/build/actions/rename-post.js.map +1 -1
- package/build/actions/reorder-page.js +4 -0
- package/build/actions/reorder-page.js.map +1 -1
- package/build/actions/reset-post.js +7 -3
- package/build/actions/reset-post.js.map +1 -1
- package/build/actions/restore-post.js +4 -1
- package/build/actions/restore-post.js.map +1 -1
- package/build/actions/trash-post.js +4 -1
- package/build/actions/trash-post.js.map +1 -1
- package/build/actions/utils.js +4 -12
- package/build/actions/utils.js.map +1 -1
- package/build/actions/view-post-revisions.js +4 -0
- package/build/actions/view-post-revisions.js.map +1 -1
- package/build/actions/view-post.js +4 -0
- package/build/actions/view-post.js.map +1 -1
- package/build/components/create-template-part-modal/index.js +213 -0
- package/build/components/create-template-part-modal/index.js.map +1 -0
- package/build/components/create-template-part-modal/utils.js +64 -0
- package/build/components/create-template-part-modal/utils.js.map +1 -0
- package/build/fields/featured-image/index.js +4 -0
- package/build/fields/featured-image/index.js.map +1 -1
- package/build/fields/index.js +28 -0
- package/build/fields/index.js.map +1 -1
- package/build/fields/order/index.js +4 -0
- package/build/fields/order/index.js.map +1 -1
- package/build/fields/page-title/index.js +36 -0
- package/build/fields/page-title/index.js.map +1 -0
- package/build/fields/page-title/view.js +45 -0
- package/build/fields/page-title/view.js.map +1 -0
- package/build/fields/parent/index.js +1 -1
- package/build/fields/parent/index.js.map +1 -1
- package/build/fields/password/index.js +1 -1
- package/build/fields/password/index.js.map +1 -1
- package/build/fields/pattern-title/index.js +36 -0
- package/build/fields/pattern-title/index.js.map +1 -0
- package/build/fields/pattern-title/view.js +45 -0
- package/build/fields/pattern-title/view.js.map +1 -0
- package/build/fields/slug/index.js +4 -0
- package/build/fields/slug/index.js.map +1 -1
- package/build/fields/slug/slug-view.js +1 -1
- package/build/fields/slug/slug-view.js.map +1 -1
- package/build/fields/slug/utils.js +3 -0
- package/build/fields/slug/utils.js.map +1 -1
- package/build/fields/template/index.js +29 -0
- package/build/fields/template/index.js.map +1 -0
- package/build/fields/template/template-edit.js +154 -0
- package/build/fields/template/template-edit.js.map +1 -0
- package/build/fields/template-title/index.js +36 -0
- package/build/fields/template-title/index.js.map +1 -0
- package/build/fields/title/index.js +10 -3
- package/build/fields/title/index.js.map +1 -1
- package/build/fields/title/view.js +48 -0
- package/build/fields/title/view.js.map +1 -0
- package/build/index.js +13 -0
- package/build/index.js.map +1 -1
- package/build/index.native.js +0 -26
- package/build/index.native.js.map +1 -1
- package/build/mutation/index.js +0 -1
- package/build/mutation/index.js.map +1 -1
- package/build/types.js.map +1 -1
- package/build-module/actions/delete-post.js +4 -0
- package/build-module/actions/delete-post.js.map +1 -1
- package/build-module/actions/duplicate-pattern.js +4 -0
- package/build-module/actions/duplicate-pattern.js.map +1 -1
- package/build-module/actions/duplicate-post.js +7 -3
- package/build-module/actions/duplicate-post.js.map +1 -1
- package/build-module/actions/duplicate-template-part.js +66 -0
- package/build-module/actions/duplicate-template-part.js.map +1 -0
- package/build-module/actions/export-pattern.js +4 -0
- package/build-module/actions/export-pattern.js.map +1 -1
- package/build-module/actions/index.js +1 -3
- package/build-module/actions/index.js.map +1 -1
- package/build-module/actions/permanently-delete-post.js +4 -1
- package/build-module/actions/permanently-delete-post.js.map +1 -1
- package/build-module/actions/rename-post.js +7 -3
- package/build-module/actions/rename-post.js.map +1 -1
- package/build-module/actions/reorder-page.js +4 -0
- package/build-module/actions/reorder-page.js.map +1 -1
- package/build-module/actions/reset-post.js +8 -4
- package/build-module/actions/reset-post.js.map +1 -1
- package/build-module/actions/restore-post.js +4 -1
- package/build-module/actions/restore-post.js.map +1 -1
- package/build-module/actions/trash-post.js +4 -1
- package/build-module/actions/trash-post.js.map +1 -1
- package/build-module/actions/utils.js +4 -11
- package/build-module/actions/utils.js.map +1 -1
- package/build-module/actions/view-post-revisions.js +4 -0
- package/build-module/actions/view-post-revisions.js.map +1 -1
- package/build-module/actions/view-post.js +4 -0
- package/build-module/actions/view-post.js.map +1 -1
- package/build-module/components/create-template-part-modal/index.js +204 -0
- package/build-module/components/create-template-part-modal/index.js.map +1 -0
- package/build-module/components/create-template-part-modal/utils.js +55 -0
- package/build-module/components/create-template-part-modal/utils.js.map +1 -0
- package/build-module/fields/featured-image/index.js +4 -0
- package/build-module/fields/featured-image/index.js.map +1 -1
- package/build-module/fields/index.js +4 -0
- package/build-module/fields/index.js.map +1 -1
- package/build-module/fields/order/index.js +4 -0
- package/build-module/fields/order/index.js.map +1 -1
- package/build-module/fields/page-title/index.js +30 -0
- package/build-module/fields/page-title/index.js.map +1 -0
- package/build-module/fields/page-title/view.js +39 -0
- package/build-module/fields/page-title/view.js.map +1 -0
- package/build-module/fields/parent/index.js +1 -1
- package/build-module/fields/parent/index.js.map +1 -1
- package/build-module/fields/password/index.js +1 -1
- package/build-module/fields/password/index.js.map +1 -1
- package/build-module/fields/pattern-title/index.js +30 -0
- package/build-module/fields/pattern-title/index.js.map +1 -0
- package/build-module/fields/pattern-title/view.js +36 -0
- package/build-module/fields/pattern-title/view.js.map +1 -0
- package/build-module/fields/slug/index.js +4 -0
- package/build-module/fields/slug/index.js.map +1 -1
- package/build-module/fields/slug/slug-view.js +1 -1
- package/build-module/fields/slug/slug-view.js.map +1 -1
- package/build-module/fields/slug/utils.js +3 -0
- package/build-module/fields/slug/utils.js.map +1 -1
- package/build-module/fields/template/index.js +22 -0
- package/build-module/fields/template/index.js.map +1 -0
- package/build-module/fields/template/template-edit.js +144 -0
- package/build-module/fields/template/template-edit.js.map +1 -0
- package/build-module/fields/template-title/index.js +30 -0
- package/build-module/fields/template-title/index.js.map +1 -0
- package/build-module/fields/title/index.js +9 -2
- package/build-module/fields/title/index.js.map +1 -1
- package/build-module/fields/title/view.js +39 -0
- package/build-module/fields/title/view.js.map +1 -0
- package/build-module/index.js +1 -0
- package/build-module/index.js.map +1 -1
- package/build-module/index.native.js +1 -2
- package/build-module/index.native.js.map +1 -1
- package/build-module/mutation/index.js +0 -1
- package/build-module/mutation/index.js.map +1 -1
- package/build-module/types.js.map +1 -1
- package/build-style/style-rtl.css +98 -0
- package/build-style/style.css +98 -0
- package/build-types/actions/delete-post.d.ts +3 -0
- package/build-types/actions/delete-post.d.ts.map +1 -1
- package/build-types/actions/duplicate-pattern.d.ts +3 -0
- package/build-types/actions/duplicate-pattern.d.ts.map +1 -1
- package/build-types/actions/duplicate-post.d.ts +3 -0
- package/build-types/actions/duplicate-post.d.ts.map +1 -1
- package/build-types/actions/duplicate-template-part.d.ts +14 -0
- package/build-types/actions/duplicate-template-part.d.ts.map +1 -0
- package/build-types/actions/export-pattern.d.ts +3 -0
- package/build-types/actions/export-pattern.d.ts.map +1 -1
- package/build-types/actions/index.d.ts +1 -3
- package/build-types/actions/index.d.ts.map +1 -1
- package/build-types/actions/permanently-delete-post.d.ts +3 -0
- package/build-types/actions/permanently-delete-post.d.ts.map +1 -1
- package/build-types/actions/rename-post.d.ts +3 -0
- package/build-types/actions/rename-post.d.ts.map +1 -1
- package/build-types/actions/reorder-page.d.ts +3 -0
- package/build-types/actions/reorder-page.d.ts.map +1 -1
- package/build-types/actions/reset-post.d.ts +3 -0
- package/build-types/actions/reset-post.d.ts.map +1 -1
- package/build-types/actions/restore-post.d.ts +3 -0
- package/build-types/actions/restore-post.d.ts.map +1 -1
- package/build-types/actions/trash-post.d.ts +3 -0
- package/build-types/actions/trash-post.d.ts.map +1 -1
- package/build-types/actions/utils.d.ts +7 -8
- package/build-types/actions/utils.d.ts.map +1 -1
- package/build-types/actions/view-post-revisions.d.ts +3 -0
- package/build-types/actions/view-post-revisions.d.ts.map +1 -1
- package/build-types/actions/view-post.d.ts +3 -0
- package/build-types/actions/view-post.d.ts.map +1 -1
- package/build-types/components/create-template-part-modal/index.d.ts +34 -0
- package/build-types/components/create-template-part-modal/index.d.ts.map +1 -0
- package/build-types/components/create-template-part-modal/utils.d.ts +4 -0
- package/build-types/components/create-template-part-modal/utils.d.ts.map +1 -0
- package/build-types/fields/featured-image/index.d.ts +3 -0
- package/build-types/fields/featured-image/index.d.ts.map +1 -1
- package/build-types/fields/index.d.ts +4 -0
- package/build-types/fields/index.d.ts.map +1 -1
- package/build-types/fields/order/index.d.ts +3 -0
- package/build-types/fields/order/index.d.ts.map +1 -1
- package/build-types/fields/page-title/index.d.ts +14 -0
- package/build-types/fields/page-title/index.d.ts.map +1 -0
- package/build-types/fields/page-title/view.d.ts +8 -0
- package/build-types/fields/page-title/view.d.ts.map +1 -0
- package/build-types/fields/parent/index.d.ts +1 -1
- package/build-types/fields/password/index.d.ts +1 -1
- package/build-types/fields/pattern-title/index.d.ts +14 -0
- package/build-types/fields/pattern-title/index.d.ts.map +1 -0
- package/build-types/fields/pattern-title/view.d.ts +9 -0
- package/build-types/fields/pattern-title/view.d.ts.map +1 -0
- package/build-types/fields/slug/index.d.ts +3 -0
- package/build-types/fields/slug/index.d.ts.map +1 -1
- package/build-types/fields/slug/utils.d.ts.map +1 -1
- package/build-types/fields/template/index.d.ts +11 -0
- package/build-types/fields/template/index.d.ts.map +1 -0
- package/build-types/fields/template/template-edit.d.ts +4 -0
- package/build-types/fields/template/template-edit.d.ts.map +1 -0
- package/build-types/fields/template-title/index.d.ts +14 -0
- package/build-types/fields/template-title/index.d.ts.map +1 -0
- package/build-types/fields/title/index.d.ts +7 -2
- package/build-types/fields/title/index.d.ts.map +1 -1
- package/build-types/fields/title/view.d.ts +14 -0
- package/build-types/fields/title/view.d.ts.map +1 -0
- package/build-types/index.d.ts +2 -1
- package/build-types/index.d.ts.map +1 -1
- package/build-types/index.native.d.ts +0 -2
- package/build-types/index.native.d.ts.map +1 -1
- package/build-types/lock-unlock.d.ts +1 -1
- package/build-types/lock-unlock.d.ts.map +1 -1
- package/build-types/types.d.ts +3 -0
- package/build-types/types.d.ts.map +1 -1
- package/package.json +24 -23
- package/src/actions/delete-post.tsx +3 -0
- package/src/actions/duplicate-pattern.tsx +3 -0
- package/src/actions/duplicate-post.tsx +6 -3
- package/src/actions/duplicate-template-part.tsx +74 -0
- package/src/actions/export-pattern.tsx +3 -0
- package/src/actions/index.ts +1 -3
- package/src/actions/permanently-delete-post.tsx +3 -0
- package/src/actions/rename-post.tsx +6 -6
- package/src/actions/reorder-page.tsx +3 -0
- package/src/actions/reset-post.tsx +7 -9
- package/src/actions/restore-post.tsx +3 -0
- package/src/actions/trash-post.tsx +3 -0
- package/src/actions/utils.ts +7 -15
- package/src/actions/view-post-revisions.tsx +3 -0
- package/src/actions/view-post.tsx +3 -0
- package/src/components/create-template-part-modal/index.tsx +274 -0
- package/src/components/create-template-part-modal/style.scss +63 -0
- package/src/components/create-template-part-modal/test/utils.js +60 -0
- package/src/components/create-template-part-modal/utils.js +68 -0
- package/src/fields/featured-image/index.ts +3 -0
- package/src/fields/index.ts +4 -0
- package/src/fields/order/index.ts +3 -0
- package/src/fields/page-title/index.ts +28 -0
- package/src/fields/page-title/style.scss +10 -0
- package/src/fields/page-title/view.tsx +38 -0
- package/src/fields/parent/index.ts +1 -1
- package/src/fields/password/index.tsx +1 -1
- package/src/fields/pattern-title/index.ts +28 -0
- package/src/fields/pattern-title/style.scss +3 -0
- package/src/fields/pattern-title/view.tsx +32 -0
- package/src/fields/slug/index.ts +3 -0
- package/src/fields/slug/slug-view.tsx +1 -1
- package/src/fields/slug/utils.ts +4 -0
- package/src/fields/template/index.ts +24 -0
- package/src/fields/template/style.scss +23 -0
- package/src/fields/template/template-edit.tsx +210 -0
- package/src/fields/template-title/index.ts +28 -0
- package/src/fields/title/index.ts +9 -3
- package/src/fields/title/style.scss +8 -0
- package/src/fields/title/view.tsx +43 -0
- package/src/index.native.ts +0 -2
- package/src/index.ts +2 -1
- package/src/style.scss +5 -0
- package/src/types.ts +3 -0
- package/tsconfig.json +2 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/build/actions/duplicate-post.native.js +0 -9
- package/build/actions/duplicate-post.native.js.map +0 -1
- package/build/actions/export-pattern.native.js +0 -9
- package/build/actions/export-pattern.native.js.map +0 -1
- package/build/actions/reorder-page.native.js +0 -9
- package/build/actions/reorder-page.native.js.map +0 -1
- package/build/fields/title/title-view.js +0 -61
- package/build/fields/title/title-view.js.map +0 -1
- package/build-module/actions/duplicate-post.native.js +0 -3
- package/build-module/actions/duplicate-post.native.js.map +0 -1
- package/build-module/actions/export-pattern.native.js +0 -3
- package/build-module/actions/export-pattern.native.js.map +0 -1
- package/build-module/actions/reorder-page.native.js +0 -3
- package/build-module/actions/reorder-page.native.js.map +0 -1
- package/build-module/fields/title/title-view.js +0 -55
- package/build-module/fields/title/title-view.js.map +0 -1
- package/build-types/actions/duplicate-post.native.d.ts +0 -3
- package/build-types/actions/duplicate-post.native.d.ts.map +0 -1
- package/build-types/actions/export-pattern.native.d.ts +0 -3
- package/build-types/actions/export-pattern.native.d.ts.map +0 -1
- package/build-types/actions/reorder-page.native.d.ts +0 -3
- package/build-types/actions/reorder-page.native.d.ts.map +0 -1
- package/build-types/fields/title/title-view.d.ts +0 -9
- package/build-types/fields/title/title-view.d.ts.map +0 -1
- package/src/actions/duplicate-post.native.tsx +0 -3
- package/src/actions/export-pattern.native.tsx +0 -3
- package/src/actions/reorder-page.native.tsx +0 -3
- package/src/fields/title/title-view.tsx +0 -62
package/src/actions/index.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
export { default as viewPost } from './view-post';
|
|
2
2
|
export { default as reorderPage } from './reorder-page';
|
|
3
|
-
export { default as reorderPageNative } from './reorder-page.native';
|
|
4
3
|
export { default as duplicatePost } from './duplicate-post';
|
|
5
|
-
export { default as duplicatePostNative } from './duplicate-post.native';
|
|
6
4
|
export { default as renamePost } from './rename-post';
|
|
7
5
|
export { default as resetPost } from './reset-post';
|
|
8
6
|
export { default as duplicatePattern } from './duplicate-pattern';
|
|
9
7
|
export { default as exportPattern } from './export-pattern';
|
|
10
|
-
export { default as exportPatternNative } from './export-pattern.native';
|
|
11
8
|
export { default as viewPostRevisions } from './view-post-revisions';
|
|
12
9
|
export { default as permanentlyDeletePost } from './permanently-delete-post';
|
|
13
10
|
export { default as restorePost } from './restore-post';
|
|
14
11
|
export { default as trashPost } from './trash-post';
|
|
15
12
|
export { default as deletePost } from './delete-post';
|
|
13
|
+
export { default as duplicateTemplatePart } from './duplicate-template-part';
|
|
@@ -26,9 +26,6 @@ import {
|
|
|
26
26
|
isTemplateRemovable,
|
|
27
27
|
isTemplate,
|
|
28
28
|
isTemplatePart,
|
|
29
|
-
TEMPLATE_ORIGINS,
|
|
30
|
-
TEMPLATE_PART_POST_TYPE,
|
|
31
|
-
TEMPLATE_POST_TYPE,
|
|
32
29
|
} from './utils';
|
|
33
30
|
import type { CoreDataError, PostWithPermissions } from '../types';
|
|
34
31
|
|
|
@@ -45,8 +42,8 @@ const renamePost: Action< PostWithPermissions > = {
|
|
|
45
42
|
// Templates, template parts and patterns have special checks for renaming.
|
|
46
43
|
if (
|
|
47
44
|
! [
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
'wp_template',
|
|
46
|
+
'wp_template_part',
|
|
50
47
|
...Object.values( PATTERN_TYPES ),
|
|
51
48
|
].includes( post.type )
|
|
52
49
|
) {
|
|
@@ -64,7 +61,7 @@ const renamePost: Action< PostWithPermissions > = {
|
|
|
64
61
|
|
|
65
62
|
if ( isTemplatePart( post ) ) {
|
|
66
63
|
return (
|
|
67
|
-
post.source ===
|
|
64
|
+
post.source === 'custom' &&
|
|
68
65
|
! post?.has_theme_file &&
|
|
69
66
|
post.permissions?.update
|
|
70
67
|
);
|
|
@@ -142,4 +139,7 @@ const renamePost: Action< PostWithPermissions > = {
|
|
|
142
139
|
},
|
|
143
140
|
};
|
|
144
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Rename action for PostWithPermissions.
|
|
144
|
+
*/
|
|
145
145
|
export default renamePost;
|
|
@@ -22,12 +22,7 @@ import apiFetch from '@wordpress/api-fetch';
|
|
|
22
22
|
/**
|
|
23
23
|
* Internal dependencies
|
|
24
24
|
*/
|
|
25
|
-
import {
|
|
26
|
-
getItemTitle,
|
|
27
|
-
isTemplateOrTemplatePart,
|
|
28
|
-
TEMPLATE_ORIGINS,
|
|
29
|
-
TEMPLATE_POST_TYPE,
|
|
30
|
-
} from './utils';
|
|
25
|
+
import { getItemTitle, isTemplateOrTemplatePart } from './utils';
|
|
31
26
|
import type { CoreDataError, Template, TemplatePart } from '../types';
|
|
32
27
|
|
|
33
28
|
const isTemplateRevertable = (
|
|
@@ -38,7 +33,7 @@ const isTemplateRevertable = (
|
|
|
38
33
|
}
|
|
39
34
|
|
|
40
35
|
return (
|
|
41
|
-
templateOrTemplatePart.source ===
|
|
36
|
+
templateOrTemplatePart.source === 'custom' &&
|
|
42
37
|
( Boolean( templateOrTemplatePart?.plugin ) ||
|
|
43
38
|
templateOrTemplatePart?.has_theme_file )
|
|
44
39
|
);
|
|
@@ -186,7 +181,7 @@ const resetPostAction: Action< Template | TemplatePart > = {
|
|
|
186
181
|
isEligible: ( item ) => {
|
|
187
182
|
return (
|
|
188
183
|
isTemplateOrTemplatePart( item ) &&
|
|
189
|
-
item?.source ===
|
|
184
|
+
item?.source === 'custom' &&
|
|
190
185
|
( Boolean( item.type === 'wp_template' && item?.plugin ) ||
|
|
191
186
|
item?.has_theme_file )
|
|
192
187
|
);
|
|
@@ -231,7 +226,7 @@ const resetPostAction: Action< Template | TemplatePart > = {
|
|
|
231
226
|
);
|
|
232
227
|
} catch ( error ) {
|
|
233
228
|
let fallbackErrorMessage;
|
|
234
|
-
if ( items[ 0 ].type ===
|
|
229
|
+
if ( items[ 0 ].type === 'wp_template' ) {
|
|
235
230
|
fallbackErrorMessage =
|
|
236
231
|
items.length === 1
|
|
237
232
|
? __(
|
|
@@ -297,4 +292,7 @@ const resetPostAction: Action< Template | TemplatePart > = {
|
|
|
297
292
|
},
|
|
298
293
|
};
|
|
299
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Reset action for Template and TemplatePart.
|
|
297
|
+
*/
|
|
300
298
|
export default resetPostAction;
|
package/src/actions/utils.ts
CHANGED
|
@@ -8,29 +8,23 @@ import { decodeEntities } from '@wordpress/html-entities';
|
|
|
8
8
|
*/
|
|
9
9
|
import type { Post, TemplatePart, Template } from '../types';
|
|
10
10
|
|
|
11
|
-
export const TEMPLATE_POST_TYPE = 'wp_template';
|
|
12
|
-
export const TEMPLATE_PART_POST_TYPE = 'wp_template_part';
|
|
13
|
-
export const TEMPLATE_ORIGINS = {
|
|
14
|
-
custom: 'custom',
|
|
15
|
-
theme: 'theme',
|
|
16
|
-
plugin: 'plugin',
|
|
17
|
-
};
|
|
18
|
-
|
|
19
11
|
export function isTemplate( post: Post ): post is Template {
|
|
20
|
-
return post.type ===
|
|
12
|
+
return post.type === 'wp_template';
|
|
21
13
|
}
|
|
22
14
|
|
|
23
15
|
export function isTemplatePart( post: Post ): post is TemplatePart {
|
|
24
|
-
return post.type ===
|
|
16
|
+
return post.type === 'wp_template_part';
|
|
25
17
|
}
|
|
26
18
|
|
|
27
19
|
export function isTemplateOrTemplatePart(
|
|
28
20
|
p: Post
|
|
29
21
|
): p is Template | TemplatePart {
|
|
30
|
-
return p.type ===
|
|
22
|
+
return p.type === 'wp_template' || p.type === 'wp_template_part';
|
|
31
23
|
}
|
|
32
24
|
|
|
33
|
-
export function getItemTitle( item:
|
|
25
|
+
export function getItemTitle( item: {
|
|
26
|
+
title: string | { rendered: string } | { raw: string };
|
|
27
|
+
} ) {
|
|
34
28
|
if ( typeof item.title === 'string' ) {
|
|
35
29
|
return decodeEntities( item.title );
|
|
36
30
|
}
|
|
@@ -57,9 +51,7 @@ export function isTemplateRemovable( template: Template | TemplatePart ) {
|
|
|
57
51
|
// than the one returned from the endpoint. This is why we need to check for
|
|
58
52
|
// two props whether is custom or has a theme file.
|
|
59
53
|
return (
|
|
60
|
-
[ template.source, template.source ].includes(
|
|
61
|
-
TEMPLATE_ORIGINS.custom
|
|
62
|
-
) &&
|
|
54
|
+
[ template.source, template.source ].includes( 'custom' ) &&
|
|
63
55
|
! Boolean( template.type === 'wp_template' && template?.plugin ) &&
|
|
64
56
|
! template.has_theme_file
|
|
65
57
|
);
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
Icon,
|
|
6
|
+
BaseControl,
|
|
7
|
+
TextControl,
|
|
8
|
+
Flex,
|
|
9
|
+
FlexItem,
|
|
10
|
+
FlexBlock,
|
|
11
|
+
Button,
|
|
12
|
+
Modal,
|
|
13
|
+
__experimentalRadioGroup as RadioGroup,
|
|
14
|
+
__experimentalRadio as Radio,
|
|
15
|
+
__experimentalHStack as HStack,
|
|
16
|
+
__experimentalVStack as VStack,
|
|
17
|
+
} from '@wordpress/components';
|
|
18
|
+
import { useInstanceId } from '@wordpress/compose';
|
|
19
|
+
import { store as coreStore } from '@wordpress/core-data';
|
|
20
|
+
import { useDispatch, useSelect } from '@wordpress/data';
|
|
21
|
+
import { useState } from '@wordpress/element';
|
|
22
|
+
import { __ } from '@wordpress/i18n';
|
|
23
|
+
import {
|
|
24
|
+
check,
|
|
25
|
+
footer as footerIcon,
|
|
26
|
+
header as headerIcon,
|
|
27
|
+
sidebar as sidebarIcon,
|
|
28
|
+
symbolFilled as symbolFilledIcon,
|
|
29
|
+
} from '@wordpress/icons';
|
|
30
|
+
import { store as noticesStore } from '@wordpress/notices';
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
import { serialize } from '@wordpress/blocks';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Internal dependencies
|
|
36
|
+
*/
|
|
37
|
+
import {
|
|
38
|
+
getCleanTemplatePartSlug,
|
|
39
|
+
getUniqueTemplatePartTitle,
|
|
40
|
+
useExistingTemplateParts,
|
|
41
|
+
} from './utils';
|
|
42
|
+
|
|
43
|
+
type CreateTemplatePartModalContentsProps = {
|
|
44
|
+
defaultArea?: string;
|
|
45
|
+
blocks: any[];
|
|
46
|
+
confirmLabel?: string;
|
|
47
|
+
closeModal: () => void;
|
|
48
|
+
onCreate: ( templatePart: any ) => void;
|
|
49
|
+
onError?: () => void;
|
|
50
|
+
defaultTitle?: string;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* A React component that renders a modal for creating a template part. The modal displays a title and the contents for creating the template part.
|
|
55
|
+
* This component should not live in this package, it should be moved to a dedicated package responsible for managing template.
|
|
56
|
+
* @param {Object} props The component props.
|
|
57
|
+
* @param props.modalTitle
|
|
58
|
+
*/
|
|
59
|
+
export default function CreateTemplatePartModal( {
|
|
60
|
+
modalTitle,
|
|
61
|
+
...restProps
|
|
62
|
+
}: {
|
|
63
|
+
modalTitle: string;
|
|
64
|
+
} & CreateTemplatePartModalContentsProps ) {
|
|
65
|
+
const defaultModalTitle = useSelect(
|
|
66
|
+
( select ) =>
|
|
67
|
+
// @ts-ignore
|
|
68
|
+
select( coreStore ).getPostType( 'wp_template_part' )?.labels
|
|
69
|
+
?.add_new_item,
|
|
70
|
+
[]
|
|
71
|
+
);
|
|
72
|
+
return (
|
|
73
|
+
<Modal
|
|
74
|
+
title={ modalTitle || defaultModalTitle }
|
|
75
|
+
onRequestClose={ restProps.closeModal }
|
|
76
|
+
overlayClassName="fields-create-template-part-modal"
|
|
77
|
+
focusOnMount="firstContentElement"
|
|
78
|
+
size="medium"
|
|
79
|
+
>
|
|
80
|
+
{ /* @ts-ignore */ }
|
|
81
|
+
<CreateTemplatePartModalContents { ...restProps } />
|
|
82
|
+
</Modal>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const getTemplatePartIcon = ( iconName: string ) => {
|
|
87
|
+
if ( 'header' === iconName ) {
|
|
88
|
+
return headerIcon;
|
|
89
|
+
} else if ( 'footer' === iconName ) {
|
|
90
|
+
return footerIcon;
|
|
91
|
+
} else if ( 'sidebar' === iconName ) {
|
|
92
|
+
return sidebarIcon;
|
|
93
|
+
}
|
|
94
|
+
return symbolFilledIcon;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* A React component that renders the content of a model for creating a template part.
|
|
99
|
+
* This component should not live in this package; it should be moved to a dedicated package responsible for managing template.
|
|
100
|
+
*
|
|
101
|
+
* @param {Object} props - The component props.
|
|
102
|
+
* @param {string} [props.defaultArea=uncategorized] - The default area for the template part.
|
|
103
|
+
* @param {Array} [props.blocks=[]] - The blocks to be included in the template part.
|
|
104
|
+
* @param {string} [props.confirmLabel='Add'] - The label for the confirm button.
|
|
105
|
+
* @param {Function} props.closeModal - Function to close the modal.
|
|
106
|
+
* @param {Function} props.onCreate - Function to call when the template part is successfully created.
|
|
107
|
+
* @param {Function} [props.onError] - Function to call when there is an error creating the template part.
|
|
108
|
+
* @param {string} [props.defaultTitle=''] - The default title for the template part.
|
|
109
|
+
*/
|
|
110
|
+
export function CreateTemplatePartModalContents( {
|
|
111
|
+
defaultArea = 'uncategorized',
|
|
112
|
+
blocks = [],
|
|
113
|
+
confirmLabel = __( 'Add' ),
|
|
114
|
+
closeModal,
|
|
115
|
+
onCreate,
|
|
116
|
+
onError,
|
|
117
|
+
defaultTitle = '',
|
|
118
|
+
}: CreateTemplatePartModalContentsProps ) {
|
|
119
|
+
const { createErrorNotice } = useDispatch( noticesStore );
|
|
120
|
+
const { saveEntityRecord } = useDispatch( coreStore );
|
|
121
|
+
const existingTemplateParts = useExistingTemplateParts();
|
|
122
|
+
|
|
123
|
+
const [ title, setTitle ] = useState( defaultTitle );
|
|
124
|
+
const [ area, setArea ] = useState( defaultArea );
|
|
125
|
+
const [ isSubmitting, setIsSubmitting ] = useState( false );
|
|
126
|
+
const instanceId = useInstanceId( CreateTemplatePartModal );
|
|
127
|
+
|
|
128
|
+
const defaultTemplatePartAreas = useSelect( ( select ) => {
|
|
129
|
+
const areas =
|
|
130
|
+
// @ts-expect-error getEntityRecord is not typed with unstableBase as argument.
|
|
131
|
+
select( coreStore ).getEntityRecord< {
|
|
132
|
+
default_template_part_areas: Array< {
|
|
133
|
+
area: string;
|
|
134
|
+
label: string;
|
|
135
|
+
icon: string;
|
|
136
|
+
description: string;
|
|
137
|
+
} >;
|
|
138
|
+
} >( 'root', '__unstableBase' )?.default_template_part_areas || [];
|
|
139
|
+
|
|
140
|
+
return areas.map( ( item ) => {
|
|
141
|
+
return { ...item, icon: getTemplatePartIcon( item.icon ) };
|
|
142
|
+
} );
|
|
143
|
+
}, [] );
|
|
144
|
+
|
|
145
|
+
async function createTemplatePart() {
|
|
146
|
+
if ( ! title || isSubmitting ) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
setIsSubmitting( true );
|
|
152
|
+
const uniqueTitle = getUniqueTemplatePartTitle(
|
|
153
|
+
title,
|
|
154
|
+
existingTemplateParts
|
|
155
|
+
);
|
|
156
|
+
const cleanSlug = getCleanTemplatePartSlug( uniqueTitle );
|
|
157
|
+
|
|
158
|
+
const templatePart = await saveEntityRecord(
|
|
159
|
+
'postType',
|
|
160
|
+
'wp_template_part',
|
|
161
|
+
{
|
|
162
|
+
slug: cleanSlug,
|
|
163
|
+
title: uniqueTitle,
|
|
164
|
+
content: serialize( blocks ),
|
|
165
|
+
area,
|
|
166
|
+
},
|
|
167
|
+
{ throwOnError: true }
|
|
168
|
+
);
|
|
169
|
+
await onCreate( templatePart );
|
|
170
|
+
|
|
171
|
+
// TODO: Add a success notice?
|
|
172
|
+
} catch ( error ) {
|
|
173
|
+
const errorMessage =
|
|
174
|
+
error instanceof Error &&
|
|
175
|
+
'code' in error &&
|
|
176
|
+
error.message &&
|
|
177
|
+
error.code !== 'unknown_error'
|
|
178
|
+
? error.message
|
|
179
|
+
: __(
|
|
180
|
+
'An error occurred while creating the template part.'
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
createErrorNotice( errorMessage, { type: 'snackbar' } );
|
|
184
|
+
|
|
185
|
+
onError?.();
|
|
186
|
+
} finally {
|
|
187
|
+
setIsSubmitting( false );
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return (
|
|
191
|
+
<form
|
|
192
|
+
onSubmit={ async ( event ) => {
|
|
193
|
+
event.preventDefault();
|
|
194
|
+
await createTemplatePart();
|
|
195
|
+
} }
|
|
196
|
+
>
|
|
197
|
+
<VStack spacing="4">
|
|
198
|
+
<TextControl
|
|
199
|
+
__next40pxDefaultSize
|
|
200
|
+
__nextHasNoMarginBottom
|
|
201
|
+
label={ __( 'Name' ) }
|
|
202
|
+
value={ title }
|
|
203
|
+
onChange={ setTitle }
|
|
204
|
+
required
|
|
205
|
+
/>
|
|
206
|
+
<BaseControl
|
|
207
|
+
__nextHasNoMarginBottom
|
|
208
|
+
label={ __( 'Area' ) }
|
|
209
|
+
id={ `fields-create-template-part-modal__area-selection-${ instanceId }` }
|
|
210
|
+
className="fields-create-template-part-modal__area-base-control"
|
|
211
|
+
>
|
|
212
|
+
<RadioGroup
|
|
213
|
+
label={ __( 'Area' ) }
|
|
214
|
+
className="fields-create-template-part-modal__area-radio-group"
|
|
215
|
+
id={ `fields-create-template-part-modal__area-selection-${ instanceId }` }
|
|
216
|
+
onChange={ ( value ) =>
|
|
217
|
+
value && typeof value === 'string'
|
|
218
|
+
? setArea( value )
|
|
219
|
+
: () => void 0
|
|
220
|
+
}
|
|
221
|
+
checked={ area }
|
|
222
|
+
>
|
|
223
|
+
{ defaultTemplatePartAreas.map(
|
|
224
|
+
( { icon, label, area: value, description } ) => (
|
|
225
|
+
<Radio
|
|
226
|
+
__next40pxDefaultSize
|
|
227
|
+
key={ label }
|
|
228
|
+
value={ value }
|
|
229
|
+
className="fields-create-template-part-modal__area-radio"
|
|
230
|
+
>
|
|
231
|
+
<Flex align="start" justify="start">
|
|
232
|
+
<FlexItem>
|
|
233
|
+
<Icon icon={ icon } />
|
|
234
|
+
</FlexItem>
|
|
235
|
+
<FlexBlock className="fields-create-template-part-modal__option-label">
|
|
236
|
+
{ label }
|
|
237
|
+
<div>{ description }</div>
|
|
238
|
+
</FlexBlock>
|
|
239
|
+
|
|
240
|
+
<FlexItem className="fields-create-template-part-modal__checkbox">
|
|
241
|
+
{ area === value && (
|
|
242
|
+
<Icon icon={ check } />
|
|
243
|
+
) }
|
|
244
|
+
</FlexItem>
|
|
245
|
+
</Flex>
|
|
246
|
+
</Radio>
|
|
247
|
+
)
|
|
248
|
+
) }
|
|
249
|
+
</RadioGroup>
|
|
250
|
+
</BaseControl>
|
|
251
|
+
<HStack justify="right">
|
|
252
|
+
<Button
|
|
253
|
+
__next40pxDefaultSize
|
|
254
|
+
variant="tertiary"
|
|
255
|
+
onClick={ () => {
|
|
256
|
+
closeModal();
|
|
257
|
+
} }
|
|
258
|
+
>
|
|
259
|
+
{ __( 'Cancel' ) }
|
|
260
|
+
</Button>
|
|
261
|
+
<Button
|
|
262
|
+
__next40pxDefaultSize
|
|
263
|
+
variant="primary"
|
|
264
|
+
type="submit"
|
|
265
|
+
aria-disabled={ ! title || isSubmitting }
|
|
266
|
+
isBusy={ isSubmitting }
|
|
267
|
+
>
|
|
268
|
+
{ confirmLabel }
|
|
269
|
+
</Button>
|
|
270
|
+
</HStack>
|
|
271
|
+
</VStack>
|
|
272
|
+
</form>
|
|
273
|
+
);
|
|
274
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
.fields-create-template-part-modal {
|
|
2
|
+
z-index: z-index(".fields-create-template-part-modal");
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.fields-create-template-part-modal__area-radio-group {
|
|
6
|
+
width: 100%;
|
|
7
|
+
border: $border-width solid $gray-700;
|
|
8
|
+
border-radius: $radius-small;
|
|
9
|
+
|
|
10
|
+
.components-button.fields-create-template-part-modal__area-radio {
|
|
11
|
+
display: block;
|
|
12
|
+
width: 100%;
|
|
13
|
+
height: 100%;
|
|
14
|
+
text-align: left;
|
|
15
|
+
padding: $grid-unit-15;
|
|
16
|
+
|
|
17
|
+
&,
|
|
18
|
+
&.is-secondary:hover,
|
|
19
|
+
&.is-primary:hover {
|
|
20
|
+
margin: 0;
|
|
21
|
+
background-color: inherit;
|
|
22
|
+
border-bottom: $border-width solid $gray-700;
|
|
23
|
+
border-radius: 0;
|
|
24
|
+
|
|
25
|
+
&:not(:focus) {
|
|
26
|
+
box-shadow: none;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&:focus {
|
|
30
|
+
border-bottom: $border-width solid $white;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&:last-of-type {
|
|
34
|
+
border-bottom: none;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&:not(:hover),
|
|
39
|
+
&[aria-checked="true"] {
|
|
40
|
+
color: $gray-900;
|
|
41
|
+
cursor: auto;
|
|
42
|
+
|
|
43
|
+
.fields-create-template-part-modal__option-label div {
|
|
44
|
+
color: $gray-600;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.fields-create-template-part-modal__option-label {
|
|
49
|
+
padding-top: $grid-unit-05;
|
|
50
|
+
white-space: normal;
|
|
51
|
+
|
|
52
|
+
div {
|
|
53
|
+
padding-top: $grid-unit-05;
|
|
54
|
+
font-size: $helptext-font-size;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.fields-create-template-part-modal__checkbox {
|
|
59
|
+
margin-left: auto;
|
|
60
|
+
min-width: $grid-unit-30;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { getUniqueTemplatePartTitle, getCleanTemplatePartSlug } from '../utils';
|
|
5
|
+
|
|
6
|
+
describe( 'getUniqueTemplatePartTitle', () => {
|
|
7
|
+
it( 'should return the title if it is unique', () => {
|
|
8
|
+
const title = 'My Template Part';
|
|
9
|
+
const templateParts = [
|
|
10
|
+
{
|
|
11
|
+
title: {
|
|
12
|
+
rendered: 'Template Part With Another Title',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
expect( getUniqueTemplatePartTitle( title, templateParts ) ).toBe(
|
|
18
|
+
title
|
|
19
|
+
);
|
|
20
|
+
} );
|
|
21
|
+
|
|
22
|
+
it( 'should return the title with a suffix if it is not unique', () => {
|
|
23
|
+
const title = 'My Template Part';
|
|
24
|
+
const templateParts = [
|
|
25
|
+
{
|
|
26
|
+
title: {
|
|
27
|
+
rendered: 'My Template Part',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
title: {
|
|
32
|
+
rendered: 'My Template Part 2',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
expect( getUniqueTemplatePartTitle( title, templateParts ) ).toBe(
|
|
38
|
+
'My Template Part 3'
|
|
39
|
+
);
|
|
40
|
+
} );
|
|
41
|
+
} );
|
|
42
|
+
|
|
43
|
+
describe( 'getCleanTemplatePartSlug', () => {
|
|
44
|
+
it( 'should return a slug with only latin chars', () => {
|
|
45
|
+
const title = 'Myɶ Template Partɮ';
|
|
46
|
+
expect( getCleanTemplatePartSlug( title ) ).toBe( 'my-template-part' );
|
|
47
|
+
} );
|
|
48
|
+
|
|
49
|
+
it( 'should return a slug with only latin chars and numbers', () => {
|
|
50
|
+
const title = 'My Template Part 2';
|
|
51
|
+
expect( getCleanTemplatePartSlug( title ) ).toBe(
|
|
52
|
+
'my-template-part-2'
|
|
53
|
+
);
|
|
54
|
+
} );
|
|
55
|
+
|
|
56
|
+
it( 'should default the slug to wp-custom-part', () => {
|
|
57
|
+
const title = '';
|
|
58
|
+
expect( getCleanTemplatePartSlug( title ) ).toBe( 'wp-custom-part' );
|
|
59
|
+
} );
|
|
60
|
+
} );
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { paramCase as kebabCase } from 'change-case';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* WordPress dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { useSelect } from '@wordpress/data';
|
|
10
|
+
import { store as coreStore } from '@wordpress/core-data';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Internal dependencies
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export const useExistingTemplateParts = () => {
|
|
17
|
+
return (
|
|
18
|
+
useSelect(
|
|
19
|
+
( select ) =>
|
|
20
|
+
select( coreStore ).getEntityRecords(
|
|
21
|
+
'postType',
|
|
22
|
+
'wp_template_part',
|
|
23
|
+
{
|
|
24
|
+
per_page: -1,
|
|
25
|
+
}
|
|
26
|
+
),
|
|
27
|
+
[]
|
|
28
|
+
) ?? []
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Return a unique template part title based on
|
|
34
|
+
* the given title and existing template parts.
|
|
35
|
+
*
|
|
36
|
+
* @param {string} title The original template part title.
|
|
37
|
+
* @param {Object} templateParts The array of template part entities.
|
|
38
|
+
* @return {string} A unique template part title.
|
|
39
|
+
*/
|
|
40
|
+
export const getUniqueTemplatePartTitle = ( title, templateParts ) => {
|
|
41
|
+
const lowercaseTitle = title.toLowerCase();
|
|
42
|
+
const existingTitles = templateParts.map( ( templatePart ) =>
|
|
43
|
+
templatePart.title.rendered.toLowerCase()
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
if ( ! existingTitles.includes( lowercaseTitle ) ) {
|
|
47
|
+
return title;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let suffix = 2;
|
|
51
|
+
while ( existingTitles.includes( `${ lowercaseTitle } ${ suffix }` ) ) {
|
|
52
|
+
suffix++;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return `${ title } ${ suffix }`;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get a valid slug for a template part.
|
|
60
|
+
* Currently template parts only allow latin chars.
|
|
61
|
+
* The fallback slug will receive suffix by default.
|
|
62
|
+
*
|
|
63
|
+
* @param {string} title The template part title.
|
|
64
|
+
* @return {string} A valid template part slug.
|
|
65
|
+
*/
|
|
66
|
+
export const getCleanTemplatePartSlug = ( title ) => {
|
|
67
|
+
return kebabCase( title ).replace( /[^\w-]+/g, '' ) || 'wp-custom-part';
|
|
68
|
+
};
|