@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.
Files changed (299) hide show
  1. package/README.md +52 -27
  2. package/build/actions/delete-post.js +4 -0
  3. package/build/actions/delete-post.js.map +1 -1
  4. package/build/actions/duplicate-pattern.js +4 -0
  5. package/build/actions/duplicate-pattern.js.map +1 -1
  6. package/build/actions/duplicate-post.js +7 -3
  7. package/build/actions/duplicate-post.js.map +1 -1
  8. package/build/actions/duplicate-template-part.js +71 -0
  9. package/build/actions/duplicate-template-part.js.map +1 -0
  10. package/build/actions/export-pattern.js +4 -0
  11. package/build/actions/export-pattern.js.map +1 -1
  12. package/build/actions/index.js +3 -17
  13. package/build/actions/index.js.map +1 -1
  14. package/build/actions/permanently-delete-post.js +4 -1
  15. package/build/actions/permanently-delete-post.js.map +1 -1
  16. package/build/actions/rename-post.js +6 -2
  17. package/build/actions/rename-post.js.map +1 -1
  18. package/build/actions/reorder-page.js +4 -0
  19. package/build/actions/reorder-page.js.map +1 -1
  20. package/build/actions/reset-post.js +7 -3
  21. package/build/actions/reset-post.js.map +1 -1
  22. package/build/actions/restore-post.js +4 -1
  23. package/build/actions/restore-post.js.map +1 -1
  24. package/build/actions/trash-post.js +4 -1
  25. package/build/actions/trash-post.js.map +1 -1
  26. package/build/actions/utils.js +4 -12
  27. package/build/actions/utils.js.map +1 -1
  28. package/build/actions/view-post-revisions.js +4 -0
  29. package/build/actions/view-post-revisions.js.map +1 -1
  30. package/build/actions/view-post.js +4 -0
  31. package/build/actions/view-post.js.map +1 -1
  32. package/build/components/create-template-part-modal/index.js +213 -0
  33. package/build/components/create-template-part-modal/index.js.map +1 -0
  34. package/build/components/create-template-part-modal/utils.js +64 -0
  35. package/build/components/create-template-part-modal/utils.js.map +1 -0
  36. package/build/fields/featured-image/index.js +4 -0
  37. package/build/fields/featured-image/index.js.map +1 -1
  38. package/build/fields/index.js +28 -0
  39. package/build/fields/index.js.map +1 -1
  40. package/build/fields/order/index.js +4 -0
  41. package/build/fields/order/index.js.map +1 -1
  42. package/build/fields/page-title/index.js +36 -0
  43. package/build/fields/page-title/index.js.map +1 -0
  44. package/build/fields/page-title/view.js +45 -0
  45. package/build/fields/page-title/view.js.map +1 -0
  46. package/build/fields/parent/index.js +1 -1
  47. package/build/fields/parent/index.js.map +1 -1
  48. package/build/fields/password/index.js +1 -1
  49. package/build/fields/password/index.js.map +1 -1
  50. package/build/fields/pattern-title/index.js +36 -0
  51. package/build/fields/pattern-title/index.js.map +1 -0
  52. package/build/fields/pattern-title/view.js +45 -0
  53. package/build/fields/pattern-title/view.js.map +1 -0
  54. package/build/fields/slug/index.js +4 -0
  55. package/build/fields/slug/index.js.map +1 -1
  56. package/build/fields/slug/slug-view.js +1 -1
  57. package/build/fields/slug/slug-view.js.map +1 -1
  58. package/build/fields/slug/utils.js +3 -0
  59. package/build/fields/slug/utils.js.map +1 -1
  60. package/build/fields/template/index.js +29 -0
  61. package/build/fields/template/index.js.map +1 -0
  62. package/build/fields/template/template-edit.js +154 -0
  63. package/build/fields/template/template-edit.js.map +1 -0
  64. package/build/fields/template-title/index.js +36 -0
  65. package/build/fields/template-title/index.js.map +1 -0
  66. package/build/fields/title/index.js +10 -3
  67. package/build/fields/title/index.js.map +1 -1
  68. package/build/fields/title/view.js +48 -0
  69. package/build/fields/title/view.js.map +1 -0
  70. package/build/index.js +13 -0
  71. package/build/index.js.map +1 -1
  72. package/build/index.native.js +0 -26
  73. package/build/index.native.js.map +1 -1
  74. package/build/mutation/index.js +0 -1
  75. package/build/mutation/index.js.map +1 -1
  76. package/build/types.js.map +1 -1
  77. package/build-module/actions/delete-post.js +4 -0
  78. package/build-module/actions/delete-post.js.map +1 -1
  79. package/build-module/actions/duplicate-pattern.js +4 -0
  80. package/build-module/actions/duplicate-pattern.js.map +1 -1
  81. package/build-module/actions/duplicate-post.js +7 -3
  82. package/build-module/actions/duplicate-post.js.map +1 -1
  83. package/build-module/actions/duplicate-template-part.js +66 -0
  84. package/build-module/actions/duplicate-template-part.js.map +1 -0
  85. package/build-module/actions/export-pattern.js +4 -0
  86. package/build-module/actions/export-pattern.js.map +1 -1
  87. package/build-module/actions/index.js +1 -3
  88. package/build-module/actions/index.js.map +1 -1
  89. package/build-module/actions/permanently-delete-post.js +4 -1
  90. package/build-module/actions/permanently-delete-post.js.map +1 -1
  91. package/build-module/actions/rename-post.js +7 -3
  92. package/build-module/actions/rename-post.js.map +1 -1
  93. package/build-module/actions/reorder-page.js +4 -0
  94. package/build-module/actions/reorder-page.js.map +1 -1
  95. package/build-module/actions/reset-post.js +8 -4
  96. package/build-module/actions/reset-post.js.map +1 -1
  97. package/build-module/actions/restore-post.js +4 -1
  98. package/build-module/actions/restore-post.js.map +1 -1
  99. package/build-module/actions/trash-post.js +4 -1
  100. package/build-module/actions/trash-post.js.map +1 -1
  101. package/build-module/actions/utils.js +4 -11
  102. package/build-module/actions/utils.js.map +1 -1
  103. package/build-module/actions/view-post-revisions.js +4 -0
  104. package/build-module/actions/view-post-revisions.js.map +1 -1
  105. package/build-module/actions/view-post.js +4 -0
  106. package/build-module/actions/view-post.js.map +1 -1
  107. package/build-module/components/create-template-part-modal/index.js +204 -0
  108. package/build-module/components/create-template-part-modal/index.js.map +1 -0
  109. package/build-module/components/create-template-part-modal/utils.js +55 -0
  110. package/build-module/components/create-template-part-modal/utils.js.map +1 -0
  111. package/build-module/fields/featured-image/index.js +4 -0
  112. package/build-module/fields/featured-image/index.js.map +1 -1
  113. package/build-module/fields/index.js +4 -0
  114. package/build-module/fields/index.js.map +1 -1
  115. package/build-module/fields/order/index.js +4 -0
  116. package/build-module/fields/order/index.js.map +1 -1
  117. package/build-module/fields/page-title/index.js +30 -0
  118. package/build-module/fields/page-title/index.js.map +1 -0
  119. package/build-module/fields/page-title/view.js +39 -0
  120. package/build-module/fields/page-title/view.js.map +1 -0
  121. package/build-module/fields/parent/index.js +1 -1
  122. package/build-module/fields/parent/index.js.map +1 -1
  123. package/build-module/fields/password/index.js +1 -1
  124. package/build-module/fields/password/index.js.map +1 -1
  125. package/build-module/fields/pattern-title/index.js +30 -0
  126. package/build-module/fields/pattern-title/index.js.map +1 -0
  127. package/build-module/fields/pattern-title/view.js +36 -0
  128. package/build-module/fields/pattern-title/view.js.map +1 -0
  129. package/build-module/fields/slug/index.js +4 -0
  130. package/build-module/fields/slug/index.js.map +1 -1
  131. package/build-module/fields/slug/slug-view.js +1 -1
  132. package/build-module/fields/slug/slug-view.js.map +1 -1
  133. package/build-module/fields/slug/utils.js +3 -0
  134. package/build-module/fields/slug/utils.js.map +1 -1
  135. package/build-module/fields/template/index.js +22 -0
  136. package/build-module/fields/template/index.js.map +1 -0
  137. package/build-module/fields/template/template-edit.js +144 -0
  138. package/build-module/fields/template/template-edit.js.map +1 -0
  139. package/build-module/fields/template-title/index.js +30 -0
  140. package/build-module/fields/template-title/index.js.map +1 -0
  141. package/build-module/fields/title/index.js +9 -2
  142. package/build-module/fields/title/index.js.map +1 -1
  143. package/build-module/fields/title/view.js +39 -0
  144. package/build-module/fields/title/view.js.map +1 -0
  145. package/build-module/index.js +1 -0
  146. package/build-module/index.js.map +1 -1
  147. package/build-module/index.native.js +1 -2
  148. package/build-module/index.native.js.map +1 -1
  149. package/build-module/mutation/index.js +0 -1
  150. package/build-module/mutation/index.js.map +1 -1
  151. package/build-module/types.js.map +1 -1
  152. package/build-style/style-rtl.css +98 -0
  153. package/build-style/style.css +98 -0
  154. package/build-types/actions/delete-post.d.ts +3 -0
  155. package/build-types/actions/delete-post.d.ts.map +1 -1
  156. package/build-types/actions/duplicate-pattern.d.ts +3 -0
  157. package/build-types/actions/duplicate-pattern.d.ts.map +1 -1
  158. package/build-types/actions/duplicate-post.d.ts +3 -0
  159. package/build-types/actions/duplicate-post.d.ts.map +1 -1
  160. package/build-types/actions/duplicate-template-part.d.ts +14 -0
  161. package/build-types/actions/duplicate-template-part.d.ts.map +1 -0
  162. package/build-types/actions/export-pattern.d.ts +3 -0
  163. package/build-types/actions/export-pattern.d.ts.map +1 -1
  164. package/build-types/actions/index.d.ts +1 -3
  165. package/build-types/actions/index.d.ts.map +1 -1
  166. package/build-types/actions/permanently-delete-post.d.ts +3 -0
  167. package/build-types/actions/permanently-delete-post.d.ts.map +1 -1
  168. package/build-types/actions/rename-post.d.ts +3 -0
  169. package/build-types/actions/rename-post.d.ts.map +1 -1
  170. package/build-types/actions/reorder-page.d.ts +3 -0
  171. package/build-types/actions/reorder-page.d.ts.map +1 -1
  172. package/build-types/actions/reset-post.d.ts +3 -0
  173. package/build-types/actions/reset-post.d.ts.map +1 -1
  174. package/build-types/actions/restore-post.d.ts +3 -0
  175. package/build-types/actions/restore-post.d.ts.map +1 -1
  176. package/build-types/actions/trash-post.d.ts +3 -0
  177. package/build-types/actions/trash-post.d.ts.map +1 -1
  178. package/build-types/actions/utils.d.ts +7 -8
  179. package/build-types/actions/utils.d.ts.map +1 -1
  180. package/build-types/actions/view-post-revisions.d.ts +3 -0
  181. package/build-types/actions/view-post-revisions.d.ts.map +1 -1
  182. package/build-types/actions/view-post.d.ts +3 -0
  183. package/build-types/actions/view-post.d.ts.map +1 -1
  184. package/build-types/components/create-template-part-modal/index.d.ts +34 -0
  185. package/build-types/components/create-template-part-modal/index.d.ts.map +1 -0
  186. package/build-types/components/create-template-part-modal/utils.d.ts +4 -0
  187. package/build-types/components/create-template-part-modal/utils.d.ts.map +1 -0
  188. package/build-types/fields/featured-image/index.d.ts +3 -0
  189. package/build-types/fields/featured-image/index.d.ts.map +1 -1
  190. package/build-types/fields/index.d.ts +4 -0
  191. package/build-types/fields/index.d.ts.map +1 -1
  192. package/build-types/fields/order/index.d.ts +3 -0
  193. package/build-types/fields/order/index.d.ts.map +1 -1
  194. package/build-types/fields/page-title/index.d.ts +14 -0
  195. package/build-types/fields/page-title/index.d.ts.map +1 -0
  196. package/build-types/fields/page-title/view.d.ts +8 -0
  197. package/build-types/fields/page-title/view.d.ts.map +1 -0
  198. package/build-types/fields/parent/index.d.ts +1 -1
  199. package/build-types/fields/password/index.d.ts +1 -1
  200. package/build-types/fields/pattern-title/index.d.ts +14 -0
  201. package/build-types/fields/pattern-title/index.d.ts.map +1 -0
  202. package/build-types/fields/pattern-title/view.d.ts +9 -0
  203. package/build-types/fields/pattern-title/view.d.ts.map +1 -0
  204. package/build-types/fields/slug/index.d.ts +3 -0
  205. package/build-types/fields/slug/index.d.ts.map +1 -1
  206. package/build-types/fields/slug/utils.d.ts.map +1 -1
  207. package/build-types/fields/template/index.d.ts +11 -0
  208. package/build-types/fields/template/index.d.ts.map +1 -0
  209. package/build-types/fields/template/template-edit.d.ts +4 -0
  210. package/build-types/fields/template/template-edit.d.ts.map +1 -0
  211. package/build-types/fields/template-title/index.d.ts +14 -0
  212. package/build-types/fields/template-title/index.d.ts.map +1 -0
  213. package/build-types/fields/title/index.d.ts +7 -2
  214. package/build-types/fields/title/index.d.ts.map +1 -1
  215. package/build-types/fields/title/view.d.ts +14 -0
  216. package/build-types/fields/title/view.d.ts.map +1 -0
  217. package/build-types/index.d.ts +2 -1
  218. package/build-types/index.d.ts.map +1 -1
  219. package/build-types/index.native.d.ts +0 -2
  220. package/build-types/index.native.d.ts.map +1 -1
  221. package/build-types/lock-unlock.d.ts +1 -1
  222. package/build-types/lock-unlock.d.ts.map +1 -1
  223. package/build-types/types.d.ts +3 -0
  224. package/build-types/types.d.ts.map +1 -1
  225. package/package.json +24 -23
  226. package/src/actions/delete-post.tsx +3 -0
  227. package/src/actions/duplicate-pattern.tsx +3 -0
  228. package/src/actions/duplicate-post.tsx +6 -3
  229. package/src/actions/duplicate-template-part.tsx +74 -0
  230. package/src/actions/export-pattern.tsx +3 -0
  231. package/src/actions/index.ts +1 -3
  232. package/src/actions/permanently-delete-post.tsx +3 -0
  233. package/src/actions/rename-post.tsx +6 -6
  234. package/src/actions/reorder-page.tsx +3 -0
  235. package/src/actions/reset-post.tsx +7 -9
  236. package/src/actions/restore-post.tsx +3 -0
  237. package/src/actions/trash-post.tsx +3 -0
  238. package/src/actions/utils.ts +7 -15
  239. package/src/actions/view-post-revisions.tsx +3 -0
  240. package/src/actions/view-post.tsx +3 -0
  241. package/src/components/create-template-part-modal/index.tsx +274 -0
  242. package/src/components/create-template-part-modal/style.scss +63 -0
  243. package/src/components/create-template-part-modal/test/utils.js +60 -0
  244. package/src/components/create-template-part-modal/utils.js +68 -0
  245. package/src/fields/featured-image/index.ts +3 -0
  246. package/src/fields/index.ts +4 -0
  247. package/src/fields/order/index.ts +3 -0
  248. package/src/fields/page-title/index.ts +28 -0
  249. package/src/fields/page-title/style.scss +10 -0
  250. package/src/fields/page-title/view.tsx +38 -0
  251. package/src/fields/parent/index.ts +1 -1
  252. package/src/fields/password/index.tsx +1 -1
  253. package/src/fields/pattern-title/index.ts +28 -0
  254. package/src/fields/pattern-title/style.scss +3 -0
  255. package/src/fields/pattern-title/view.tsx +32 -0
  256. package/src/fields/slug/index.ts +3 -0
  257. package/src/fields/slug/slug-view.tsx +1 -1
  258. package/src/fields/slug/utils.ts +4 -0
  259. package/src/fields/template/index.ts +24 -0
  260. package/src/fields/template/style.scss +23 -0
  261. package/src/fields/template/template-edit.tsx +210 -0
  262. package/src/fields/template-title/index.ts +28 -0
  263. package/src/fields/title/index.ts +9 -3
  264. package/src/fields/title/style.scss +8 -0
  265. package/src/fields/title/view.tsx +43 -0
  266. package/src/index.native.ts +0 -2
  267. package/src/index.ts +2 -1
  268. package/src/style.scss +5 -0
  269. package/src/types.ts +3 -0
  270. package/tsconfig.json +2 -0
  271. package/tsconfig.tsbuildinfo +1 -1
  272. package/build/actions/duplicate-post.native.js +0 -9
  273. package/build/actions/duplicate-post.native.js.map +0 -1
  274. package/build/actions/export-pattern.native.js +0 -9
  275. package/build/actions/export-pattern.native.js.map +0 -1
  276. package/build/actions/reorder-page.native.js +0 -9
  277. package/build/actions/reorder-page.native.js.map +0 -1
  278. package/build/fields/title/title-view.js +0 -61
  279. package/build/fields/title/title-view.js.map +0 -1
  280. package/build-module/actions/duplicate-post.native.js +0 -3
  281. package/build-module/actions/duplicate-post.native.js.map +0 -1
  282. package/build-module/actions/export-pattern.native.js +0 -3
  283. package/build-module/actions/export-pattern.native.js.map +0 -1
  284. package/build-module/actions/reorder-page.native.js +0 -3
  285. package/build-module/actions/reorder-page.native.js.map +0 -1
  286. package/build-module/fields/title/title-view.js +0 -55
  287. package/build-module/fields/title/title-view.js.map +0 -1
  288. package/build-types/actions/duplicate-post.native.d.ts +0 -3
  289. package/build-types/actions/duplicate-post.native.d.ts.map +0 -1
  290. package/build-types/actions/export-pattern.native.d.ts +0 -3
  291. package/build-types/actions/export-pattern.native.d.ts.map +0 -1
  292. package/build-types/actions/reorder-page.native.d.ts +0 -3
  293. package/build-types/actions/reorder-page.native.d.ts.map +0 -1
  294. package/build-types/fields/title/title-view.d.ts +0 -9
  295. package/build-types/fields/title/title-view.d.ts.map +0 -1
  296. package/src/actions/duplicate-post.native.tsx +0 -3
  297. package/src/actions/export-pattern.native.tsx +0 -3
  298. package/src/actions/reorder-page.native.tsx +0 -3
  299. package/src/fields/title/title-view.tsx +0 -62
@@ -73,4 +73,7 @@ const exportPattern: Action< Pattern > = {
73
73
  },
74
74
  };
75
75
 
76
+ /**
77
+ * Export action as JSON for Pattern.
78
+ */
76
79
  export default exportPattern;
@@ -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';
@@ -115,4 +115,7 @@ const permanentlyDeletePost: Action< PostWithPermissions > = {
115
115
  },
116
116
  };
117
117
 
118
+ /**
119
+ * Delete action for PostWithPermissions.
120
+ */
118
121
  export default permanentlyDeletePost;
@@ -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
- TEMPLATE_POST_TYPE,
49
- TEMPLATE_PART_POST_TYPE,
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 === TEMPLATE_ORIGINS.custom &&
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;
@@ -122,4 +122,7 @@ const reorderPage: Action< BasePost > = {
122
122
  RenderModal: ReorderModal,
123
123
  };
124
124
 
125
+ /**
126
+ * Reorder action for BasePost.
127
+ */
125
128
  export default reorderPage;
@@ -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 === TEMPLATE_ORIGINS.custom &&
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 === TEMPLATE_ORIGINS.custom &&
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 === TEMPLATE_POST_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;
@@ -131,4 +131,7 @@ const restorePost: Action< PostWithPermissions > = {
131
131
  },
132
132
  };
133
133
 
134
+ /**
135
+ * Restore action for PostWithPermissions.
136
+ */
134
137
  export default restorePost;
@@ -195,4 +195,7 @@ const trashPost: Action< PostWithPermissions > = {
195
195
  },
196
196
  };
197
197
 
198
+ /**
199
+ * Trash action for PostWithPermissions.
200
+ */
198
201
  export default trashPost;
@@ -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 === TEMPLATE_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 === TEMPLATE_PART_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 === TEMPLATE_POST_TYPE || p.type === TEMPLATE_PART_POST_TYPE;
22
+ return p.type === 'wp_template' || p.type === 'wp_template_part';
31
23
  }
32
24
 
33
- export function getItemTitle( item: Post ) {
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
  );
@@ -44,4 +44,7 @@ const viewPostRevisions: Action< Post > = {
44
44
  },
45
45
  };
46
46
 
47
+ /**
48
+ * View post revisions action for Post.
49
+ */
47
50
  export default viewPostRevisions;
@@ -27,4 +27,7 @@ const viewPost: Action< BasePost > = {
27
27
  },
28
28
  };
29
29
 
30
+ /**
31
+ * View post action for BasePost.
32
+ */
30
33
  export default viewPost;
@@ -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
+ };
@@ -20,4 +20,7 @@ const featuredImageField: Field< BasePost > = {
20
20
  enableSorting: false,
21
21
  };
22
22
 
23
+ /**
24
+ * Featured Image field for BasePost.
25
+ */
23
26
  export default featuredImageField;