@wordpress/edit-site 5.20.1 → 5.21.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 (231) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/actions/trash-post.js +48 -0
  3. package/build/components/actions/trash-post.js.map +1 -0
  4. package/build/components/add-new-template/add-custom-template-modal-content.js +17 -13
  5. package/build/components/add-new-template/add-custom-template-modal-content.js.map +1 -1
  6. package/build/components/block-editor/resize-handle.js +2 -1
  7. package/build/components/block-editor/resize-handle.js.map +1 -1
  8. package/build/components/create-template-part-modal/index.js +10 -6
  9. package/build/components/create-template-part-modal/index.js.map +1 -1
  10. package/build/components/dataviews/dataviews.js +41 -32
  11. package/build/components/dataviews/dataviews.js.map +1 -1
  12. package/build/components/dataviews/field-actions.js +30 -0
  13. package/build/components/dataviews/field-actions.js.map +1 -0
  14. package/build/components/dataviews/filters.js +61 -0
  15. package/build/components/dataviews/filters.js.map +1 -0
  16. package/build/components/dataviews/in-filter.js +51 -0
  17. package/build/components/dataviews/in-filter.js.map +1 -0
  18. package/build/components/dataviews/index.js +0 -7
  19. package/build/components/dataviews/index.js.map +1 -1
  20. package/build/components/dataviews/pagination.js +75 -27
  21. package/build/components/dataviews/pagination.js.map +1 -1
  22. package/build/components/dataviews/text-filter.js +18 -12
  23. package/build/components/dataviews/text-filter.js.map +1 -1
  24. package/build/components/dataviews/view-actions.js +94 -56
  25. package/build/components/dataviews/view-actions.js.map +1 -1
  26. package/build/components/dataviews/view-grid.js +59 -0
  27. package/build/components/dataviews/view-grid.js.map +1 -0
  28. package/build/components/dataviews/view-list.js +283 -0
  29. package/build/components/dataviews/view-list.js.map +1 -0
  30. package/build/components/editor/index.js +2 -1
  31. package/build/components/editor/index.js.map +1 -1
  32. package/build/components/global-styles/font-library-modal/context.js +16 -10
  33. package/build/components/global-styles/font-library-modal/context.js.map +1 -1
  34. package/build/components/global-styles/font-library-modal/font-collection.js +20 -6
  35. package/build/components/global-styles/font-library-modal/font-collection.js.map +1 -1
  36. package/build/components/global-styles/screen-block.js +1 -2
  37. package/build/components/global-styles/screen-block.js.map +1 -1
  38. package/build/components/global-styles/screen-root.js +1 -2
  39. package/build/components/global-styles/screen-root.js.map +1 -1
  40. package/build/components/global-styles/ui.js +3 -4
  41. package/build/components/global-styles/ui.js.map +1 -1
  42. package/build/components/layout/index.js +10 -2
  43. package/build/components/layout/index.js.map +1 -1
  44. package/build/components/media/index.js +34 -0
  45. package/build/components/media/index.js.map +1 -0
  46. package/build/components/page-actions/index.js +0 -2
  47. package/build/components/page-actions/index.js.map +1 -1
  48. package/build/components/page-pages/index.js +153 -107
  49. package/build/components/page-pages/index.js.map +1 -1
  50. package/build/components/page-patterns/delete-category-menu-item.js +89 -0
  51. package/build/components/page-patterns/delete-category-menu-item.js.map +1 -0
  52. package/build/components/page-patterns/duplicate-menu-item.js +52 -131
  53. package/build/components/page-patterns/duplicate-menu-item.js.map +1 -1
  54. package/build/components/page-patterns/grid-item.js +1 -0
  55. package/build/components/page-patterns/grid-item.js.map +1 -1
  56. package/build/components/page-patterns/header.js +25 -3
  57. package/build/components/page-patterns/header.js.map +1 -1
  58. package/build/components/page-patterns/rename-category-menu-item.js +49 -0
  59. package/build/components/page-patterns/rename-category-menu-item.js.map +1 -0
  60. package/build/components/page-patterns/rename-menu-item.js +1 -1
  61. package/build/components/page-patterns/rename-menu-item.js.map +1 -1
  62. package/build/components/page-patterns/use-patterns.js +1 -0
  63. package/build/components/page-patterns/use-patterns.js.map +1 -1
  64. package/build/components/pattern-modal/duplicate.js +65 -0
  65. package/build/components/pattern-modal/duplicate.js.map +1 -0
  66. package/build/components/pattern-modal/index.js +24 -0
  67. package/build/components/pattern-modal/index.js.map +1 -0
  68. package/build/components/pattern-modal/rename.js +42 -0
  69. package/build/components/pattern-modal/rename.js.map +1 -0
  70. package/build/components/sidebar-edit-mode/template-panel/last-revision.js +3 -0
  71. package/build/components/sidebar-edit-mode/template-panel/last-revision.js.map +1 -1
  72. package/build/components/sidebar-navigation-screen-pattern/template-part-navigation-menu-list-item.js +2 -2
  73. package/build/components/sidebar-navigation-screen-pattern/template-part-navigation-menu-list-item.js.map +1 -1
  74. package/build/components/sidebar-navigation-screen-pattern/template-part-navigation-menu.js +2 -3
  75. package/build/components/sidebar-navigation-screen-pattern/template-part-navigation-menu.js.map +1 -1
  76. package/build/components/sidebar-navigation-screen-pattern/use-navigation-menu-title.js +29 -0
  77. package/build/components/sidebar-navigation-screen-pattern/use-navigation-menu-title.js.map +1 -0
  78. package/build/components/sidebar-navigation-screen-template/home-template-details.js +12 -1
  79. package/build/components/sidebar-navigation-screen-template/home-template-details.js.map +1 -1
  80. package/build/hooks/commands/use-common-commands.js +1 -2
  81. package/build/hooks/commands/use-common-commands.js.map +1 -1
  82. package/build/hooks/commands/use-edit-mode-commands.js +49 -0
  83. package/build/hooks/commands/use-edit-mode-commands.js.map +1 -1
  84. package/build/lock-unlock.js +1 -1
  85. package/build/lock-unlock.js.map +1 -1
  86. package/build/store/selectors.js +4 -5
  87. package/build/store/selectors.js.map +1 -1
  88. package/build-module/components/actions/trash-post.js +41 -0
  89. package/build-module/components/actions/trash-post.js.map +1 -0
  90. package/build-module/components/add-new-template/add-custom-template-modal-content.js +16 -12
  91. package/build-module/components/add-new-template/add-custom-template-modal-content.js.map +1 -1
  92. package/build-module/components/block-editor/resize-handle.js +2 -1
  93. package/build-module/components/block-editor/resize-handle.js.map +1 -1
  94. package/build-module/components/create-template-part-modal/index.js +10 -6
  95. package/build-module/components/create-template-part-modal/index.js.map +1 -1
  96. package/build-module/components/dataviews/dataviews.js +40 -31
  97. package/build-module/components/dataviews/dataviews.js.map +1 -1
  98. package/build-module/components/dataviews/field-actions.js +22 -0
  99. package/build-module/components/dataviews/field-actions.js.map +1 -0
  100. package/build-module/components/dataviews/filters.js +53 -0
  101. package/build-module/components/dataviews/filters.js.map +1 -0
  102. package/build-module/components/dataviews/in-filter.js +43 -0
  103. package/build-module/components/dataviews/in-filter.js.map +1 -0
  104. package/build-module/components/dataviews/index.js +0 -1
  105. package/build-module/components/dataviews/index.js.map +1 -1
  106. package/build-module/components/dataviews/pagination.js +74 -28
  107. package/build-module/components/dataviews/pagination.js.map +1 -1
  108. package/build-module/components/dataviews/text-filter.js +19 -13
  109. package/build-module/components/dataviews/text-filter.js.map +1 -1
  110. package/build-module/components/dataviews/view-actions.js +95 -54
  111. package/build-module/components/dataviews/view-actions.js.map +1 -1
  112. package/build-module/components/dataviews/view-grid.js +51 -0
  113. package/build-module/components/dataviews/view-grid.js.map +1 -0
  114. package/build-module/components/dataviews/view-list.js +274 -0
  115. package/build-module/components/dataviews/view-list.js.map +1 -0
  116. package/build-module/components/editor/index.js +2 -1
  117. package/build-module/components/editor/index.js.map +1 -1
  118. package/build-module/components/global-styles/font-library-modal/context.js +16 -10
  119. package/build-module/components/global-styles/font-library-modal/context.js.map +1 -1
  120. package/build-module/components/global-styles/font-library-modal/font-collection.js +20 -6
  121. package/build-module/components/global-styles/font-library-modal/font-collection.js.map +1 -1
  122. package/build-module/components/global-styles/screen-block.js +1 -2
  123. package/build-module/components/global-styles/screen-block.js.map +1 -1
  124. package/build-module/components/global-styles/screen-root.js +1 -2
  125. package/build-module/components/global-styles/screen-root.js.map +1 -1
  126. package/build-module/components/global-styles/ui.js +3 -4
  127. package/build-module/components/global-styles/ui.js.map +1 -1
  128. package/build-module/components/layout/index.js +11 -3
  129. package/build-module/components/layout/index.js.map +1 -1
  130. package/build-module/components/media/index.js +26 -0
  131. package/build-module/components/media/index.js.map +1 -0
  132. package/build-module/components/page-actions/index.js +0 -2
  133. package/build-module/components/page-actions/index.js.map +1 -1
  134. package/build-module/components/page-pages/index.js +156 -110
  135. package/build-module/components/page-pages/index.js.map +1 -1
  136. package/build-module/components/page-patterns/delete-category-menu-item.js +82 -0
  137. package/build-module/components/page-patterns/delete-category-menu-item.js.map +1 -0
  138. package/build-module/components/page-patterns/duplicate-menu-item.js +54 -133
  139. package/build-module/components/page-patterns/duplicate-menu-item.js.map +1 -1
  140. package/build-module/components/page-patterns/grid-item.js +1 -0
  141. package/build-module/components/page-patterns/grid-item.js.map +1 -1
  142. package/build-module/components/page-patterns/header.js +26 -4
  143. package/build-module/components/page-patterns/header.js.map +1 -1
  144. package/build-module/components/page-patterns/rename-category-menu-item.js +42 -0
  145. package/build-module/components/page-patterns/rename-category-menu-item.js.map +1 -0
  146. package/build-module/components/page-patterns/rename-menu-item.js +1 -1
  147. package/build-module/components/page-patterns/rename-menu-item.js.map +1 -1
  148. package/build-module/components/page-patterns/use-patterns.js +1 -0
  149. package/build-module/components/page-patterns/use-patterns.js.map +1 -1
  150. package/build-module/components/pattern-modal/duplicate.js +57 -0
  151. package/build-module/components/pattern-modal/duplicate.js.map +1 -0
  152. package/build-module/components/pattern-modal/index.js +14 -0
  153. package/build-module/components/pattern-modal/index.js.map +1 -0
  154. package/build-module/components/pattern-modal/rename.js +34 -0
  155. package/build-module/components/pattern-modal/rename.js.map +1 -0
  156. package/build-module/components/sidebar-edit-mode/template-panel/last-revision.js +3 -0
  157. package/build-module/components/sidebar-edit-mode/template-panel/last-revision.js.map +1 -1
  158. package/build-module/components/sidebar-navigation-screen-pattern/template-part-navigation-menu-list-item.js +2 -2
  159. package/build-module/components/sidebar-navigation-screen-pattern/template-part-navigation-menu-list-item.js.map +1 -1
  160. package/build-module/components/sidebar-navigation-screen-pattern/template-part-navigation-menu.js +2 -3
  161. package/build-module/components/sidebar-navigation-screen-pattern/template-part-navigation-menu.js.map +1 -1
  162. package/build-module/components/sidebar-navigation-screen-pattern/use-navigation-menu-title.js +22 -0
  163. package/build-module/components/sidebar-navigation-screen-pattern/use-navigation-menu-title.js.map +1 -0
  164. package/build-module/components/sidebar-navigation-screen-template/home-template-details.js +12 -1
  165. package/build-module/components/sidebar-navigation-screen-template/home-template-details.js.map +1 -1
  166. package/build-module/hooks/commands/use-common-commands.js +1 -2
  167. package/build-module/hooks/commands/use-common-commands.js.map +1 -1
  168. package/build-module/hooks/commands/use-edit-mode-commands.js +50 -1
  169. package/build-module/hooks/commands/use-edit-mode-commands.js.map +1 -1
  170. package/build-module/lock-unlock.js +1 -1
  171. package/build-module/lock-unlock.js.map +1 -1
  172. package/build-module/store/selectors.js +4 -5
  173. package/build-module/store/selectors.js.map +1 -1
  174. package/build-style/style-rtl.css +42 -9
  175. package/build-style/style.css +42 -9
  176. package/package.json +40 -40
  177. package/src/components/actions/trash-post.js +55 -0
  178. package/src/components/add-new-template/add-custom-template-modal-content.js +22 -17
  179. package/src/components/block-editor/resize-handle.js +1 -0
  180. package/src/components/create-template-part-modal/index.js +9 -5
  181. package/src/components/dataviews/README.md +107 -0
  182. package/src/components/dataviews/dataviews.js +44 -33
  183. package/src/components/dataviews/field-actions.js +28 -0
  184. package/src/components/dataviews/filters.js +57 -0
  185. package/src/components/dataviews/in-filter.js +47 -0
  186. package/src/components/dataviews/index.js +0 -1
  187. package/src/components/dataviews/pagination.js +71 -29
  188. package/src/components/dataviews/style.scss +11 -1
  189. package/src/components/dataviews/text-filter.js +19 -15
  190. package/src/components/dataviews/view-actions.js +108 -63
  191. package/src/components/dataviews/view-grid.js +60 -0
  192. package/src/components/dataviews/view-list.js +348 -0
  193. package/src/components/editor/index.js +2 -0
  194. package/src/components/global-styles/font-library-modal/context.js +17 -11
  195. package/src/components/global-styles/font-library-modal/font-collection.js +18 -10
  196. package/src/components/global-styles/screen-block.js +1 -2
  197. package/src/components/global-styles/screen-root.js +1 -2
  198. package/src/components/global-styles/style.scss +16 -4
  199. package/src/components/global-styles/ui.js +1 -2
  200. package/src/components/layout/index.js +12 -4
  201. package/src/components/media/index.js +25 -0
  202. package/src/components/page-actions/index.js +1 -7
  203. package/src/components/page-pages/index.js +156 -108
  204. package/src/components/page-pages/style.scss +3 -0
  205. package/src/components/page-patterns/delete-category-menu-item.js +104 -0
  206. package/src/components/page-patterns/duplicate-menu-item.js +68 -181
  207. package/src/components/page-patterns/grid-item.js +1 -0
  208. package/src/components/page-patterns/header.js +42 -6
  209. package/src/components/page-patterns/rename-category-menu-item.js +45 -0
  210. package/src/components/page-patterns/rename-menu-item.js +2 -2
  211. package/src/components/page-patterns/style.scss +8 -0
  212. package/src/components/page-patterns/use-patterns.js +5 -0
  213. package/src/components/pattern-modal/duplicate.js +53 -0
  214. package/src/components/pattern-modal/index.js +19 -0
  215. package/src/components/pattern-modal/rename.js +29 -0
  216. package/src/components/sidebar-edit-mode/template-panel/last-revision.js +4 -0
  217. package/src/components/sidebar-navigation-screen/style.scss +17 -5
  218. package/src/components/sidebar-navigation-screen-pattern/template-part-navigation-menu-list-item.js +2 -7
  219. package/src/components/sidebar-navigation-screen-pattern/template-part-navigation-menu.js +2 -8
  220. package/src/components/sidebar-navigation-screen-pattern/use-navigation-menu-title.js +32 -0
  221. package/src/components/sidebar-navigation-screen-template/home-template-details.js +21 -7
  222. package/src/hooks/commands/use-common-commands.js +1 -2
  223. package/src/hooks/commands/use-edit-mode-commands.js +41 -0
  224. package/src/lock-unlock.js +1 -1
  225. package/src/store/selectors.js +9 -10
  226. package/src/style.scss +1 -0
  227. package/build/components/dataviews/list-view.js +0 -89
  228. package/build/components/dataviews/list-view.js.map +0 -1
  229. package/build-module/components/dataviews/list-view.js +0 -80
  230. package/build-module/components/dataviews/list-view.js.map +0 -1
  231. package/src/components/dataviews/list-view.js +0 -106
@@ -2,217 +2,104 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { MenuItem } from '@wordpress/components';
5
- import { store as coreStore } from '@wordpress/core-data';
6
5
  import { useDispatch } from '@wordpress/data';
6
+ import { useState } from '@wordpress/element';
7
7
  import { __, sprintf } from '@wordpress/i18n';
8
8
  import { store as noticesStore } from '@wordpress/notices';
9
+ import { privateApis as patternsPrivateApis } from '@wordpress/patterns';
9
10
  import { privateApis as routerPrivateApis } from '@wordpress/router';
10
11
 
11
12
  /**
12
13
  * Internal dependencies
13
14
  */
14
- import {
15
- TEMPLATE_PART_POST_TYPE,
16
- PATTERN_TYPES,
17
- PATTERN_SYNC_TYPES,
18
- } from '../../utils/constants';
19
- import {
20
- useExistingTemplateParts,
21
- getUniqueTemplatePartTitle,
22
- getCleanTemplatePartSlug,
23
- } from '../../utils/template-part-create';
15
+ import { TEMPLATE_PART_POST_TYPE, PATTERN_TYPES } from '../../utils/constants';
24
16
  import { unlock } from '../../lock-unlock';
25
- import usePatternCategories from '../sidebar-navigation-screen-patterns/use-pattern-categories';
17
+ import CreateTemplatePartModal from '../create-template-part-modal';
26
18
 
19
+ const { DuplicatePatternModal } = unlock( patternsPrivateApis );
27
20
  const { useHistory } = unlock( routerPrivateApis );
28
21
 
29
- function getPatternMeta( item ) {
30
- if ( item.type === PATTERN_TYPES.theme ) {
31
- return { wp_pattern_sync_status: PATTERN_SYNC_TYPES.unsynced };
32
- }
33
-
34
- const syncStatus = item.patternBlock.wp_pattern_sync_status;
35
- const isUnsynced = syncStatus === PATTERN_SYNC_TYPES.unsynced;
36
-
37
- return {
38
- ...item.patternBlock.meta,
39
- wp_pattern_sync_status: isUnsynced ? syncStatus : undefined,
40
- };
41
- }
42
-
43
22
  export default function DuplicateMenuItem( {
44
23
  categoryId,
45
24
  item,
46
25
  label = __( 'Duplicate' ),
47
26
  onClose,
48
27
  } ) {
49
- const { saveEntityRecord, invalidateResolution } = useDispatch( coreStore );
50
- const { createErrorNotice, createSuccessNotice } =
51
- useDispatch( noticesStore );
52
-
28
+ const { createSuccessNotice } = useDispatch( noticesStore );
29
+ const [ isModalOpen, setIsModalOpen ] = useState( false );
53
30
  const history = useHistory();
54
- const existingTemplateParts = useExistingTemplateParts();
55
- const { patternCategories } = usePatternCategories();
56
31
 
57
- async function createTemplatePart() {
58
- try {
59
- const copiedTitle = sprintf(
60
- /* translators: %s: Existing template part title */
61
- __( '%s (Copy)' ),
62
- item.title
63
- );
64
- const title = getUniqueTemplatePartTitle(
65
- copiedTitle,
66
- existingTemplateParts
67
- );
68
- const slug = getCleanTemplatePartSlug( title );
69
- const { area, content } = item.templatePart;
70
-
71
- const result = await saveEntityRecord(
72
- 'postType',
73
- TEMPLATE_PART_POST_TYPE,
74
- { slug, title, content, area },
75
- { throwOnError: true }
76
- );
77
-
78
- createSuccessNotice(
79
- sprintf(
80
- // translators: %s: The new template part's title e.g. 'Call to action (copy)'.
81
- __( '"%s" duplicated.' ),
82
- item.title
83
- ),
84
- {
85
- type: 'snackbar',
86
- id: 'edit-site-patterns-success',
87
- }
88
- );
32
+ const closeModal = () => setIsModalOpen( false );
89
33
 
90
- history.push( {
91
- postType: TEMPLATE_PART_POST_TYPE,
92
- postId: result?.id,
93
- categoryType: TEMPLATE_PART_POST_TYPE,
94
- categoryId,
95
- } );
34
+ const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE;
35
+ const isThemePattern = item.type === PATTERN_TYPES.theme;
96
36
 
97
- onClose();
98
- } catch ( error ) {
99
- const errorMessage =
100
- error.message && error.code !== 'unknown_error'
101
- ? error.message
102
- : __(
103
- 'An error occurred while creating the template part.'
104
- );
105
-
106
- createErrorNotice( errorMessage, {
37
+ async function onTemplatePartSuccess( templatePart ) {
38
+ createSuccessNotice(
39
+ sprintf(
40
+ // translators: %s: The new template part's title e.g. 'Call to action (copy)'.
41
+ __( '"%s" duplicated.' ),
42
+ item.title
43
+ ),
44
+ {
107
45
  type: 'snackbar',
108
- id: 'edit-site-patterns-error',
109
- } );
110
- onClose();
111
- }
112
- }
113
-
114
- async function findOrCreateTerm( term ) {
115
- try {
116
- const newTerm = await saveEntityRecord(
117
- 'taxonomy',
118
- 'wp_pattern_category',
119
- {
120
- name: term.label,
121
- slug: term.name,
122
- description: term.description,
123
- },
124
- {
125
- throwOnError: true,
126
- }
127
- );
128
- invalidateResolution( 'getUserPatternCategories' );
129
- return newTerm.id;
130
- } catch ( error ) {
131
- if ( error.code !== 'term_exists' ) {
132
- throw error;
46
+ id: 'edit-site-patterns-success',
133
47
  }
48
+ );
134
49
 
135
- return error.data.term_id;
136
- }
137
- }
138
-
139
- async function getCategories( categories ) {
140
- const terms = categories.map( ( category ) => {
141
- const fullCategory = patternCategories.find(
142
- ( cat ) => cat.name === category
143
- );
144
- if ( fullCategory.id ) {
145
- return fullCategory.id;
146
- }
147
- return findOrCreateTerm( fullCategory );
50
+ history.push( {
51
+ postType: TEMPLATE_PART_POST_TYPE,
52
+ postId: templatePart?.id,
53
+ categoryType: TEMPLATE_PART_POST_TYPE,
54
+ categoryId,
148
55
  } );
149
56
 
150
- return Promise.all( terms );
57
+ onClose();
151
58
  }
152
59
 
153
- async function createPattern() {
154
- try {
155
- const isThemePattern = item.type === PATTERN_TYPES.theme;
156
- const title = sprintf(
157
- /* translators: %s: Existing pattern title */
158
- __( '%s (Copy)' ),
159
- item.title || item.name
160
- );
161
- const categories = await getCategories( item.categories || [] );
162
-
163
- const result = await saveEntityRecord(
164
- 'postType',
165
- PATTERN_TYPES.user,
166
- {
167
- content: isThemePattern
168
- ? item.content
169
- : item.patternBlock.content,
170
- meta: getPatternMeta( item ),
171
- status: 'publish',
172
- title,
173
- wp_pattern_category: categories,
174
- },
175
- { throwOnError: true }
176
- );
177
-
178
- createSuccessNotice(
179
- sprintf(
180
- // translators: %s: The new pattern's title e.g. 'Call to action (copy)'.
181
- __( '"%s" duplicated.' ),
182
- item.title || item.name
183
- ),
184
- {
185
- type: 'snackbar',
186
- id: 'edit-site-patterns-success',
187
- }
188
- );
189
-
190
- history.push( {
191
- categoryType: PATTERN_TYPES.theme,
192
- categoryId,
193
- postType: PATTERN_TYPES.user,
194
- postId: result?.id,
195
- } );
196
-
197
- onClose();
198
- } catch ( error ) {
199
- const errorMessage =
200
- error.message && error.code !== 'unknown_error'
201
- ? error.message
202
- : __( 'An error occurred while creating the pattern.' );
60
+ function onPatternSuccess( { pattern } ) {
61
+ history.push( {
62
+ categoryType: PATTERN_TYPES.theme,
63
+ categoryId,
64
+ postType: PATTERN_TYPES.user,
65
+ postId: pattern.id,
66
+ } );
203
67
 
204
- createErrorNotice( errorMessage, {
205
- type: 'snackbar',
206
- id: 'edit-site-patterns-error',
207
- } );
208
- onClose();
209
- }
68
+ onClose();
210
69
  }
211
70
 
212
- const createItem =
213
- item.type === TEMPLATE_PART_POST_TYPE
214
- ? createTemplatePart
215
- : createPattern;
216
-
217
- return <MenuItem onClick={ createItem }>{ label }</MenuItem>;
71
+ return (
72
+ <>
73
+ <MenuItem
74
+ onClick={ () => setIsModalOpen( true ) }
75
+ aria-expanded={ isModalOpen }
76
+ aria-haspopup="dialog"
77
+ >
78
+ { label }
79
+ </MenuItem>
80
+ { isModalOpen && ! isTemplatePart && (
81
+ <DuplicatePatternModal
82
+ onClose={ closeModal }
83
+ onSuccess={ onPatternSuccess }
84
+ pattern={ isThemePattern ? item : item.patternBlock }
85
+ />
86
+ ) }
87
+ { isModalOpen && isTemplatePart && (
88
+ <CreateTemplatePartModal
89
+ blocks={ item.blocks }
90
+ closeModal={ closeModal }
91
+ confirmLabel={ __( 'Duplicate' ) }
92
+ defaultArea={ item.templatePart.area }
93
+ defaultTitle={ sprintf(
94
+ /* translators: %s: Existing template part title */
95
+ __( '%s (Copy)' ),
96
+ item.title
97
+ ) }
98
+ modalTitle={ __( 'Duplicate template part' ) }
99
+ onCreate={ onTemplatePartSuccess }
100
+ onError={ closeModal }
101
+ />
102
+ ) }
103
+ </>
104
+ );
218
105
  }
@@ -174,6 +174,7 @@ function GridItem( { categoryId, item, ...props } ) {
174
174
  // Even though still incomplete, passing ids helps performance.
175
175
  // @see https://reakit.io/docs/composite/#performance.
176
176
  id={ `edit-site-patterns-${ item.name }` }
177
+ type="button"
177
178
  { ...props }
178
179
  onClick={
179
180
  item.type !== PATTERN_TYPES.theme ? onClick : undefined
@@ -2,16 +2,23 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import {
5
- __experimentalVStack as VStack,
5
+ DropdownMenu,
6
+ MenuGroup,
7
+ __experimentalHStack as HStack,
6
8
  __experimentalHeading as Heading,
7
9
  __experimentalText as Text,
10
+ __experimentalVStack as VStack,
8
11
  } from '@wordpress/components';
9
12
  import { store as editorStore } from '@wordpress/editor';
10
13
  import { useSelect } from '@wordpress/data';
14
+ import { __, sprintf } from '@wordpress/i18n';
15
+ import { moreVertical } from '@wordpress/icons';
11
16
 
12
17
  /**
13
18
  * Internal dependencies
14
19
  */
20
+ import RenameCategoryMenuItem from './rename-category-menu-item';
21
+ import DeleteCategoryMenuItem from './delete-category-menu-item';
15
22
  import usePatternCategories from '../sidebar-navigation-screen-patterns/use-pattern-categories';
16
23
  import { TEMPLATE_PART_POST_TYPE, PATTERN_TYPES } from '../../utils/constants';
17
24
 
@@ -28,7 +35,7 @@ export default function PatternsHeader( {
28
35
  []
29
36
  );
30
37
 
31
- let title, description;
38
+ let title, description, patternCategory;
32
39
  if ( type === TEMPLATE_PART_POST_TYPE ) {
33
40
  const templatePartArea = templatePartAreas.find(
34
41
  ( area ) => area.area === categoryId
@@ -36,7 +43,7 @@ export default function PatternsHeader( {
36
43
  title = templatePartArea?.label;
37
44
  description = templatePartArea?.description;
38
45
  } else if ( type === PATTERN_TYPES.theme ) {
39
- const patternCategory = patternCategories.find(
46
+ patternCategory = patternCategories.find(
40
47
  ( category ) => category.name === categoryId
41
48
  );
42
49
  title = patternCategory?.label;
@@ -47,9 +54,38 @@ export default function PatternsHeader( {
47
54
 
48
55
  return (
49
56
  <VStack className="edit-site-patterns__section-header">
50
- <Heading as="h2" level={ 4 } id={ titleId }>
51
- { title }
52
- </Heading>
57
+ <HStack justify="space-between">
58
+ <Heading as="h2" level={ 4 } id={ titleId }>
59
+ { title }
60
+ </Heading>
61
+ { !! patternCategory?.id && (
62
+ <DropdownMenu
63
+ icon={ moreVertical }
64
+ label={ __( 'Actions' ) }
65
+ toggleProps={ {
66
+ className: 'edit-site-patterns__button',
67
+ describedBy: sprintf(
68
+ /* translators: %s: pattern category name */
69
+ __( 'Action menu for %s pattern category' ),
70
+ title
71
+ ),
72
+ } }
73
+ >
74
+ { ( { onClose } ) => (
75
+ <MenuGroup>
76
+ <RenameCategoryMenuItem
77
+ category={ patternCategory }
78
+ onClose={ onClose }
79
+ />
80
+ <DeleteCategoryMenuItem
81
+ category={ patternCategory }
82
+ onClose={ onClose }
83
+ />
84
+ </MenuGroup>
85
+ ) }
86
+ </DropdownMenu>
87
+ ) }
88
+ </HStack>
53
89
  { description ? (
54
90
  <Text variant="muted" as="p" id={ descriptionId }>
55
91
  { description }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { MenuItem } from '@wordpress/components';
5
+ import { useState } from '@wordpress/element';
6
+ import { __ } from '@wordpress/i18n';
7
+ import { privateApis as patternsPrivateApis } from '@wordpress/patterns';
8
+
9
+ /**
10
+ * Internal dependencies
11
+ */
12
+ import { unlock } from '../../lock-unlock';
13
+
14
+ const { RenamePatternCategoryModal } = unlock( patternsPrivateApis );
15
+
16
+ export default function RenameCategoryMenuItem( { category, onClose } ) {
17
+ const [ isModalOpen, setIsModalOpen ] = useState( false );
18
+
19
+ // User created pattern categories have their properties updated when
20
+ // retrieved via `getUserPatternCategories`. The rename modal expects an
21
+ // object that will match the pattern category entity.
22
+ const normalizedCategory = {
23
+ id: category.id,
24
+ slug: category.slug,
25
+ name: category.label,
26
+ };
27
+
28
+ return (
29
+ <>
30
+ <MenuItem onClick={ () => setIsModalOpen( true ) }>
31
+ { __( 'Rename' ) }
32
+ </MenuItem>
33
+ { isModalOpen && (
34
+ <RenamePatternCategoryModal
35
+ category={ normalizedCategory }
36
+ onClose={ () => {
37
+ setIsModalOpen( false );
38
+ onClose();
39
+ } }
40
+ overlayClassName="edit-site-list__rename-modal"
41
+ />
42
+ ) }
43
+ </>
44
+ );
45
+ }
@@ -61,9 +61,9 @@ export default function RenameMenuItem( { item, onClose } ) {
61
61
  const fallbackErrorMessage =
62
62
  item.type === TEMPLATE_PART_POST_TYPE
63
63
  ? __(
64
- 'An error occurred while reverting the template part.'
64
+ 'An error occurred while renaming the template part.'
65
65
  )
66
- : __( 'An error occurred while reverting the pattern.' );
66
+ : __( 'An error occurred while renaming the pattern.' );
67
67
  const errorMessage =
68
68
  error.message && error.code !== 'unknown_error'
69
69
  ? error.message
@@ -101,6 +101,10 @@
101
101
  background: $gray-900;
102
102
  padding: $grid-unit-40 $grid-unit-40 $grid-unit-20;
103
103
  z-index: z-index(".edit-site-patterns__header");
104
+
105
+ .edit-site-patterns__button {
106
+ color: $gray-600;
107
+ }
104
108
  }
105
109
 
106
110
  .edit-site-patterns__section {
@@ -218,3 +222,7 @@
218
222
  .edit-site-patterns__no-results {
219
223
  color: $gray-600;
220
224
  }
225
+
226
+ .edit-site-patterns__delete-modal {
227
+ width: $modal-width-small;
228
+ }
@@ -195,6 +195,11 @@ const patternBlockToPattern = ( patternBlock, categories ) => ( {
195
195
  : patternCategoryId
196
196
  ),
197
197
  } ),
198
+ termLabels: patternBlock.wp_pattern_category.map( ( patternCategoryId ) =>
199
+ categories?.get( patternCategoryId )
200
+ ? categories.get( patternCategoryId ).label
201
+ : patternCategoryId
202
+ ),
198
203
  id: patternBlock.id,
199
204
  name: patternBlock.slug,
200
205
  syncStatus: patternBlock.wp_pattern_sync_status || PATTERN_SYNC_TYPES.full,
@@ -0,0 +1,53 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useDispatch, useSelect } from '@wordpress/data';
5
+ import { store as interfaceStore } from '@wordpress/interface';
6
+ import { privateApis as patternsPrivateApis } from '@wordpress/patterns';
7
+ import { privateApis as routerPrivateApis } from '@wordpress/router';
8
+ import { getQueryArgs } from '@wordpress/url';
9
+
10
+ /**
11
+ * Internal dependencies
12
+ */
13
+ import { PATTERN_MODALS } from './';
14
+ import { PATTERN_TYPES } from '../../utils/constants';
15
+ import { unlock } from '../../lock-unlock';
16
+ import useEditedEntityRecord from '../use-edited-entity-record';
17
+
18
+ const { DuplicatePatternModal } = unlock( patternsPrivateApis );
19
+ const { useHistory } = unlock( routerPrivateApis );
20
+
21
+ export default function PatternDuplicateModal() {
22
+ const { record } = useEditedEntityRecord();
23
+ const { categoryType, categoryId } = getQueryArgs( window.location.href );
24
+ const { closeModal } = useDispatch( interfaceStore );
25
+ const history = useHistory();
26
+
27
+ const isActive = useSelect( ( select ) =>
28
+ select( interfaceStore ).isModalActive( PATTERN_MODALS.duplicate )
29
+ );
30
+
31
+ if ( ! isActive ) {
32
+ return null;
33
+ }
34
+
35
+ function onSuccess( { pattern: newPattern } ) {
36
+ history.push( {
37
+ categoryType,
38
+ categoryId,
39
+ postType: PATTERN_TYPES.user,
40
+ postId: newPattern.id,
41
+ } );
42
+
43
+ closeModal();
44
+ }
45
+
46
+ return (
47
+ <DuplicatePatternModal
48
+ onClose={ closeModal }
49
+ onSuccess={ onSuccess }
50
+ pattern={ record }
51
+ />
52
+ );
53
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import PatternRenameModal from './rename';
5
+ import PatternDuplicateModal from './duplicate';
6
+
7
+ export const PATTERN_MODALS = {
8
+ rename: 'edit-site/pattern-rename',
9
+ duplicate: 'edit-site/pattern-duplicate',
10
+ };
11
+
12
+ export default function PatternModal() {
13
+ return (
14
+ <>
15
+ <PatternDuplicateModal />
16
+ <PatternRenameModal />
17
+ </>
18
+ );
19
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useDispatch, useSelect } from '@wordpress/data';
5
+ import { store as interfaceStore } from '@wordpress/interface';
6
+ import { privateApis as patternsPrivateApis } from '@wordpress/patterns';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import { PATTERN_MODALS } from './';
12
+ import { unlock } from '../../lock-unlock';
13
+ import useEditedEntityRecord from '../use-edited-entity-record';
14
+
15
+ const { RenamePatternModal } = unlock( patternsPrivateApis );
16
+
17
+ export default function PatternRenameModal() {
18
+ const { record: pattern } = useEditedEntityRecord();
19
+ const { closeModal } = useDispatch( interfaceStore );
20
+ const isActive = useSelect( ( select ) =>
21
+ select( interfaceStore ).isModalActive( PATTERN_MODALS.rename )
22
+ );
23
+
24
+ if ( ! isActive ) {
25
+ return null;
26
+ }
27
+
28
+ return <RenamePatternModal onClose={ closeModal } pattern={ pattern } />;
29
+ }
@@ -31,6 +31,10 @@ const useRevisionData = () => {
31
31
  function PostLastRevisionCheck( { children } ) {
32
32
  const { lastRevisionId, revisionsCount } = useRevisionData();
33
33
 
34
+ if ( ! process.env.IS_GUTENBERG_PLUGIN ) {
35
+ return null;
36
+ }
37
+
34
38
  if ( ! lastRevisionId || revisionsCount < 2 ) {
35
39
  return null;
36
40
  }
@@ -76,18 +76,30 @@
76
76
  }
77
77
 
78
78
  .edit-site-sidebar-navigation-screen__content .edit-site-global-styles-style-variations-container {
79
+ @include break-medium() {
80
+ // Safari does not currently support `scrollbar-gutter: stable`, so at
81
+ // particular viewport sizes it's possible for previews to render prior to a
82
+ // scrollbar appearing. This then causes a scrollbar to appear, which reduces
83
+ // the width of the container and can cause the preview's width to change.
84
+ // As a result, the preview can go into an endless loop of resizing, causing
85
+ // the preview elements to appear to "dance". A workaround is to provide a
86
+ // max-width for the container, which prevents the introduction of the scrollbar
87
+ // from causing the preview's width to change.
88
+ // See: https://github.com/WordPress/gutenberg/issues/55112
89
+ max-width: 292px;
90
+ }
91
+
79
92
  .edit-site-global-styles-variations_item-preview {
80
- border: $gray-900 $border-width solid;
93
+ box-shadow: 0 0 0 $border-width $gray-900;
81
94
  }
82
95
  .edit-site-global-styles-variations_item.is-active .edit-site-global-styles-variations_item-preview {
83
- border: $gray-100 $border-width solid;
96
+ box-shadow: 0 0 0 $border-width $gray-100;
84
97
  }
85
98
  .edit-site-global-styles-variations_item:hover .edit-site-global-styles-variations_item-preview {
86
- border: var(--wp-admin-theme-color) $border-width solid;
99
+ box-shadow: 0 0 0 $border-width var(--wp-admin-theme-color);
87
100
  }
88
-
89
101
  .edit-site-global-styles-variations_item:focus .edit-site-global-styles-variations_item-preview {
90
- border: var(--wp-admin-theme-color) var(--wp-admin-border-width-focus) solid;
102
+ box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
91
103
  }
92
104
  }
93
105
 
@@ -1,23 +1,18 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useEntityProp } from '@wordpress/core-data';
5
4
  import { __ } from '@wordpress/i18n';
6
5
 
7
6
  /**
8
7
  * Internal dependencies
9
8
  */
10
9
  import SidebarNavigationItem from '../sidebar-navigation-item';
10
+ import useNavigationMenuTitle from './use-navigation-menu-title';
11
11
  import { useLink } from '../routes/link';
12
12
  import { NAVIGATION_POST_TYPE } from '../../utils/constants';
13
13
 
14
14
  export default function TemplatePartNavigationMenuListItem( { id } ) {
15
- const [ title ] = useEntityProp(
16
- 'postType',
17
- NAVIGATION_POST_TYPE,
18
- 'title',
19
- id
20
- );
15
+ const title = useNavigationMenuTitle( id );
21
16
 
22
17
  const linkInfo = useLink( {
23
18
  postId: id,
@@ -3,21 +3,15 @@
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
5
  import { __experimentalHeading as Heading } from '@wordpress/components';
6
- import { useEntityProp } from '@wordpress/core-data';
7
6
 
8
7
  /**
9
8
  * Internal dependencies
10
9
  */
11
10
  import NavigationMenuEditor from '../sidebar-navigation-screen-navigation-menu/navigation-menu-editor';
12
- import { NAVIGATION_POST_TYPE } from '../../utils/constants';
11
+ import useNavigationMenuTitle from './use-navigation-menu-title';
13
12
 
14
13
  export default function TemplatePartNavigationMenu( { id } ) {
15
- const [ title ] = useEntityProp(
16
- 'postType',
17
- NAVIGATION_POST_TYPE,
18
- 'title',
19
- id
20
- );
14
+ const title = useNavigationMenuTitle( id );
21
15
 
22
16
  if ( ! id || title === undefined ) {
23
17
  return null;