@wordpress/editor 14.4.0 → 14.6.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 (375) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/bindings/post-meta.js +12 -0
  3. package/build/bindings/post-meta.js.map +1 -1
  4. package/build/components/blog-title/index.js +1 -1
  5. package/build/components/blog-title/index.js.map +1 -1
  6. package/build/components/commands/index.js +8 -2
  7. package/build/components/commands/index.js.map +1 -1
  8. package/build/components/create-template-part-modal/index.js +1 -0
  9. package/build/components/create-template-part-modal/index.js.map +1 -1
  10. package/build/components/document-bar/index.js +1 -1
  11. package/build/components/document-bar/index.js.map +1 -1
  12. package/build/components/global-styles-provider/index.js +17 -4
  13. package/build/components/global-styles-provider/index.js.map +1 -1
  14. package/build/components/header/index.js +2 -3
  15. package/build/components/header/index.js.map +1 -1
  16. package/build/components/inserter-sidebar/index.js +5 -2
  17. package/build/components/inserter-sidebar/index.js.map +1 -1
  18. package/build/components/page-attributes/parent.js +11 -6
  19. package/build/components/page-attributes/parent.js.map +1 -1
  20. package/build/components/post-actions/actions.js +10 -811
  21. package/build/components/post-actions/actions.js.map +1 -1
  22. package/build/components/post-actions/index.js +20 -19
  23. package/build/components/post-actions/index.js.map +1 -1
  24. package/build/components/post-author/hook.js +10 -3
  25. package/build/components/post-author/hook.js.map +1 -1
  26. package/build/components/post-author/panel.js +2 -1
  27. package/build/components/post-author/panel.js.map +1 -1
  28. package/build/components/post-card-panel/index.js +21 -21
  29. package/build/components/post-card-panel/index.js.map +1 -1
  30. package/build/components/post-comments/index.js +6 -20
  31. package/build/components/post-comments/index.js.map +1 -1
  32. package/build/components/post-featured-image/index.js +2 -0
  33. package/build/components/post-featured-image/index.js.map +1 -1
  34. package/build/components/post-publish-panel/postpublish.js +4 -0
  35. package/build/components/post-publish-panel/postpublish.js.map +1 -1
  36. package/build/components/post-slug/index.js +1 -0
  37. package/build/components/post-slug/index.js.map +1 -1
  38. package/build/components/post-status/index.js +17 -41
  39. package/build/components/post-status/index.js.map +1 -1
  40. package/build/components/post-taxonomies/hierarchical-term-selector.js +2 -1
  41. package/build/components/post-taxonomies/hierarchical-term-selector.js.map +1 -1
  42. package/build/components/post-template/create-new-template-modal.js +3 -0
  43. package/build/components/post-template/create-new-template-modal.js.map +1 -1
  44. package/build/components/post-url/index.js +6 -5
  45. package/build/components/post-url/index.js.map +1 -1
  46. package/build/components/post-url/panel.js +3 -2
  47. package/build/components/post-url/panel.js.map +1 -1
  48. package/build/components/preview-dropdown/index.js +82 -17
  49. package/build/components/preview-dropdown/index.js.map +1 -1
  50. package/build/components/provider/disable-non-page-content-blocks.js +14 -18
  51. package/build/components/provider/disable-non-page-content-blocks.js.map +1 -1
  52. package/build/components/sidebar/post-summary.js +10 -7
  53. package/build/components/sidebar/post-summary.js.map +1 -1
  54. package/build/components/site-discussion/index.js +6 -20
  55. package/build/components/site-discussion/index.js.map +1 -1
  56. package/build/components/template-content-panel/index.js +15 -13
  57. package/build/components/template-content-panel/index.js.map +1 -1
  58. package/build/components/visual-editor/index.js +2 -1
  59. package/build/components/visual-editor/index.js.map +1 -1
  60. package/build/dataviews/actions/duplicate-pattern.js +48 -0
  61. package/build/dataviews/actions/duplicate-pattern.js.map +1 -0
  62. package/build/dataviews/actions/duplicate-post.js +146 -0
  63. package/build/dataviews/actions/duplicate-post.js.map +1 -0
  64. package/build/dataviews/actions/duplicate-post.native.js +9 -0
  65. package/build/dataviews/actions/duplicate-post.native.js.map +1 -0
  66. package/build/dataviews/actions/duplicate-template-part.js +67 -0
  67. package/build/dataviews/actions/duplicate-template-part.js.map +1 -0
  68. package/build/dataviews/actions/export-pattern.native.js +9 -0
  69. package/build/dataviews/actions/export-pattern.native.js.map +1 -0
  70. package/build/dataviews/actions/permanently-delete-post.js +107 -0
  71. package/build/dataviews/actions/permanently-delete-post.js.map +1 -0
  72. package/build/dataviews/actions/rename-post.js +125 -0
  73. package/build/dataviews/actions/rename-post.js.map +1 -0
  74. package/build/dataviews/actions/reorder-page.js +116 -0
  75. package/build/dataviews/actions/reorder-page.js.map +1 -0
  76. package/build/dataviews/actions/reorder-page.native.js +9 -0
  77. package/build/dataviews/actions/reorder-page.native.js.map +1 -0
  78. package/build/dataviews/actions/reset-post.js +1 -1
  79. package/build/dataviews/actions/reset-post.js.map +1 -1
  80. package/build/dataviews/actions/restore-post.js +112 -0
  81. package/build/dataviews/actions/restore-post.js.map +1 -0
  82. package/build/dataviews/actions/trash-post.js +142 -0
  83. package/build/dataviews/actions/trash-post.js.map +1 -0
  84. package/build/dataviews/actions/utils.js +9 -1
  85. package/build/dataviews/actions/utils.js.map +1 -1
  86. package/build/dataviews/actions/view-post-revisions.js +49 -0
  87. package/build/dataviews/actions/view-post-revisions.js.map +1 -0
  88. package/build/dataviews/actions/view-post.js +36 -0
  89. package/build/dataviews/actions/view-post.js.map +1 -0
  90. package/build/dataviews/fields/index.js +32 -0
  91. package/build/dataviews/fields/index.js.map +1 -0
  92. package/build/dataviews/store/private-actions.js +59 -0
  93. package/build/dataviews/store/private-actions.js.map +1 -1
  94. package/build/dataviews/store/private-selectors.js +10 -10
  95. package/build/dataviews/store/private-selectors.js.map +1 -1
  96. package/build/dataviews/store/reducer.js +15 -1
  97. package/build/dataviews/store/reducer.js.map +1 -1
  98. package/build/dataviews/types.js.map +1 -1
  99. package/build/private-apis.js +2 -2
  100. package/build/private-apis.js.map +1 -1
  101. package/build/store/actions.js +16 -2
  102. package/build/store/actions.js.map +1 -1
  103. package/build/store/private-actions.js +9 -2
  104. package/build/store/private-actions.js.map +1 -1
  105. package/build/store/private-selectors.js +33 -2
  106. package/build/store/private-selectors.js.map +1 -1
  107. package/build/store/utils/is-template-revertable.js +1 -1
  108. package/build/store/utils/is-template-revertable.js.map +1 -1
  109. package/build-module/bindings/post-meta.js +12 -0
  110. package/build-module/bindings/post-meta.js.map +1 -1
  111. package/build-module/components/blog-title/index.js +1 -1
  112. package/build-module/components/blog-title/index.js.map +1 -1
  113. package/build-module/components/commands/index.js +8 -2
  114. package/build-module/components/commands/index.js.map +1 -1
  115. package/build-module/components/create-template-part-modal/index.js +1 -0
  116. package/build-module/components/create-template-part-modal/index.js.map +1 -1
  117. package/build-module/components/document-bar/index.js +1 -1
  118. package/build-module/components/document-bar/index.js.map +1 -1
  119. package/build-module/components/global-styles-provider/index.js +17 -4
  120. package/build-module/components/global-styles-provider/index.js.map +1 -1
  121. package/build-module/components/header/index.js +2 -3
  122. package/build-module/components/header/index.js.map +1 -1
  123. package/build-module/components/inserter-sidebar/index.js +5 -2
  124. package/build-module/components/inserter-sidebar/index.js.map +1 -1
  125. package/build-module/components/page-attributes/parent.js +12 -7
  126. package/build-module/components/page-attributes/parent.js.map +1 -1
  127. package/build-module/components/post-actions/actions.js +12 -814
  128. package/build-module/components/post-actions/actions.js.map +1 -1
  129. package/build-module/components/post-actions/index.js +20 -19
  130. package/build-module/components/post-actions/index.js.map +1 -1
  131. package/build-module/components/post-author/hook.js +10 -3
  132. package/build-module/components/post-author/hook.js.map +1 -1
  133. package/build-module/components/post-author/panel.js +2 -1
  134. package/build-module/components/post-author/panel.js.map +1 -1
  135. package/build-module/components/post-card-panel/index.js +21 -21
  136. package/build-module/components/post-card-panel/index.js.map +1 -1
  137. package/build-module/components/post-comments/index.js +7 -23
  138. package/build-module/components/post-comments/index.js.map +1 -1
  139. package/build-module/components/post-featured-image/index.js +2 -0
  140. package/build-module/components/post-featured-image/index.js.map +1 -1
  141. package/build-module/components/post-publish-panel/postpublish.js +4 -0
  142. package/build-module/components/post-publish-panel/postpublish.js.map +1 -1
  143. package/build-module/components/post-slug/index.js +1 -0
  144. package/build-module/components/post-slug/index.js.map +1 -1
  145. package/build-module/components/post-status/index.js +19 -43
  146. package/build-module/components/post-status/index.js.map +1 -1
  147. package/build-module/components/post-taxonomies/hierarchical-term-selector.js +3 -2
  148. package/build-module/components/post-taxonomies/hierarchical-term-selector.js.map +1 -1
  149. package/build-module/components/post-template/create-new-template-modal.js +3 -0
  150. package/build-module/components/post-template/create-new-template-modal.js.map +1 -1
  151. package/build-module/components/post-url/index.js +7 -6
  152. package/build-module/components/post-url/index.js.map +1 -1
  153. package/build-module/components/post-url/panel.js +4 -5
  154. package/build-module/components/post-url/panel.js.map +1 -1
  155. package/build-module/components/preview-dropdown/index.js +84 -19
  156. package/build-module/components/preview-dropdown/index.js.map +1 -1
  157. package/build-module/components/provider/disable-non-page-content-blocks.js +15 -19
  158. package/build-module/components/provider/disable-non-page-content-blocks.js.map +1 -1
  159. package/build-module/components/sidebar/post-summary.js +10 -7
  160. package/build-module/components/sidebar/post-summary.js.map +1 -1
  161. package/build-module/components/site-discussion/index.js +7 -21
  162. package/build-module/components/site-discussion/index.js.map +1 -1
  163. package/build-module/components/template-content-panel/index.js +16 -14
  164. package/build-module/components/template-content-panel/index.js.map +1 -1
  165. package/build-module/components/visual-editor/index.js +2 -1
  166. package/build-module/components/visual-editor/index.js.map +1 -1
  167. package/build-module/dataviews/actions/duplicate-pattern.js +39 -0
  168. package/build-module/dataviews/actions/duplicate-pattern.js.map +1 -0
  169. package/build-module/dataviews/actions/duplicate-post.js +139 -0
  170. package/build-module/dataviews/actions/duplicate-post.js.map +1 -0
  171. package/build-module/dataviews/actions/duplicate-post.native.js +3 -0
  172. package/build-module/dataviews/actions/duplicate-post.native.js.map +1 -0
  173. package/build-module/dataviews/actions/duplicate-template-part.js +58 -0
  174. package/build-module/dataviews/actions/duplicate-template-part.js.map +1 -0
  175. package/build-module/dataviews/actions/export-pattern.native.js +3 -0
  176. package/build-module/dataviews/actions/export-pattern.native.js.map +1 -0
  177. package/build-module/dataviews/actions/permanently-delete-post.js +99 -0
  178. package/build-module/dataviews/actions/permanently-delete-post.js.map +1 -0
  179. package/build-module/dataviews/actions/rename-post.js +118 -0
  180. package/build-module/dataviews/actions/rename-post.js.map +1 -0
  181. package/build-module/dataviews/actions/reorder-page.js +111 -0
  182. package/build-module/dataviews/actions/reorder-page.js.map +1 -0
  183. package/build-module/dataviews/actions/reorder-page.native.js +3 -0
  184. package/build-module/dataviews/actions/reorder-page.native.js.map +1 -0
  185. package/build-module/dataviews/actions/reset-post.js +1 -1
  186. package/build-module/dataviews/actions/reset-post.js.map +1 -1
  187. package/build-module/dataviews/actions/restore-post.js +104 -0
  188. package/build-module/dataviews/actions/restore-post.js.map +1 -0
  189. package/build-module/dataviews/actions/trash-post.js +135 -0
  190. package/build-module/dataviews/actions/trash-post.js.map +1 -0
  191. package/build-module/dataviews/actions/utils.js +7 -1
  192. package/build-module/dataviews/actions/utils.js.map +1 -1
  193. package/build-module/dataviews/actions/view-post-revisions.js +43 -0
  194. package/build-module/dataviews/actions/view-post-revisions.js.map +1 -0
  195. package/build-module/dataviews/actions/view-post.js +30 -0
  196. package/build-module/dataviews/actions/view-post.js.map +1 -0
  197. package/build-module/dataviews/fields/index.js +26 -0
  198. package/build-module/dataviews/fields/index.js.map +1 -0
  199. package/build-module/dataviews/store/private-actions.js +54 -0
  200. package/build-module/dataviews/store/private-actions.js.map +1 -1
  201. package/build-module/dataviews/store/private-selectors.js +8 -9
  202. package/build-module/dataviews/store/private-selectors.js.map +1 -1
  203. package/build-module/dataviews/store/reducer.js +15 -1
  204. package/build-module/dataviews/store/reducer.js.map +1 -1
  205. package/build-module/dataviews/types.js.map +1 -1
  206. package/build-module/private-apis.js +2 -2
  207. package/build-module/private-apis.js.map +1 -1
  208. package/build-module/store/actions.js +16 -2
  209. package/build-module/store/actions.js.map +1 -1
  210. package/build-module/store/private-actions.js +9 -2
  211. package/build-module/store/private-actions.js.map +1 -1
  212. package/build-module/store/private-selectors.js +32 -2
  213. package/build-module/store/private-selectors.js.map +1 -1
  214. package/build-module/store/utils/is-template-revertable.js +1 -1
  215. package/build-module/store/utils/is-template-revertable.js.map +1 -1
  216. package/build-style/style-rtl.css +21 -34
  217. package/build-style/style.css +21 -34
  218. package/build-types/bindings/post-meta.d.ts +6 -0
  219. package/build-types/bindings/post-meta.d.ts.map +1 -1
  220. package/build-types/components/commands/index.d.ts.map +1 -1
  221. package/build-types/components/create-template-part-modal/index.d.ts.map +1 -1
  222. package/build-types/components/global-styles-provider/index.d.ts.map +1 -1
  223. package/build-types/components/header/index.d.ts.map +1 -1
  224. package/build-types/components/inserter-sidebar/index.d.ts.map +1 -1
  225. package/build-types/components/page-attributes/parent.d.ts.map +1 -1
  226. package/build-types/components/post-actions/actions.d.ts +1 -26
  227. package/build-types/components/post-actions/actions.d.ts.map +1 -1
  228. package/build-types/components/post-actions/index.d.ts +3 -2
  229. package/build-types/components/post-actions/index.d.ts.map +1 -1
  230. package/build-types/components/post-author/hook.d.ts +1 -1
  231. package/build-types/components/post-author/hook.d.ts.map +1 -1
  232. package/build-types/components/post-author/panel.d.ts.map +1 -1
  233. package/build-types/components/post-card-panel/index.d.ts +4 -2
  234. package/build-types/components/post-card-panel/index.d.ts.map +1 -1
  235. package/build-types/components/post-comments/index.d.ts.map +1 -1
  236. package/build-types/components/post-slug/index.d.ts.map +1 -1
  237. package/build-types/components/post-status/index.d.ts +2 -1
  238. package/build-types/components/post-status/index.d.ts.map +1 -1
  239. package/build-types/components/post-taxonomies/hierarchical-term-selector.d.ts +1 -17
  240. package/build-types/components/post-taxonomies/hierarchical-term-selector.d.ts.map +1 -1
  241. package/build-types/components/post-template/create-new-template-modal.d.ts.map +1 -1
  242. package/build-types/components/post-url/index.d.ts.map +1 -1
  243. package/build-types/components/post-url/panel.d.ts.map +1 -1
  244. package/build-types/components/preview-dropdown/index.d.ts.map +1 -1
  245. package/build-types/components/provider/disable-non-page-content-blocks.d.ts.map +1 -1
  246. package/build-types/components/sidebar/post-summary.d.ts.map +1 -1
  247. package/build-types/components/site-discussion/index.d.ts.map +1 -1
  248. package/build-types/components/template-content-panel/index.d.ts.map +1 -1
  249. package/build-types/components/visual-editor/index.d.ts.map +1 -1
  250. package/build-types/dataviews/actions/duplicate-pattern.d.ts +5 -0
  251. package/build-types/dataviews/actions/duplicate-pattern.d.ts.map +1 -0
  252. package/build-types/dataviews/actions/duplicate-post.d.ts +5 -0
  253. package/build-types/dataviews/actions/duplicate-post.d.ts.map +1 -0
  254. package/build-types/dataviews/actions/duplicate-post.native.d.ts +3 -0
  255. package/build-types/dataviews/actions/duplicate-post.native.d.ts.map +1 -0
  256. package/build-types/dataviews/actions/duplicate-template-part.d.ts +5 -0
  257. package/build-types/dataviews/actions/duplicate-template-part.d.ts.map +1 -0
  258. package/build-types/dataviews/actions/export-pattern.native.d.ts +3 -0
  259. package/build-types/dataviews/actions/export-pattern.native.d.ts.map +1 -0
  260. package/build-types/dataviews/actions/permanently-delete-post.d.ts +5 -0
  261. package/build-types/dataviews/actions/permanently-delete-post.d.ts.map +1 -0
  262. package/build-types/dataviews/actions/rename-post.d.ts +5 -0
  263. package/build-types/dataviews/actions/rename-post.d.ts.map +1 -0
  264. package/build-types/dataviews/actions/reorder-page.d.ts +8 -0
  265. package/build-types/dataviews/actions/reorder-page.d.ts.map +1 -0
  266. package/build-types/dataviews/actions/reorder-page.native.d.ts +3 -0
  267. package/build-types/dataviews/actions/reorder-page.native.d.ts.map +1 -0
  268. package/build-types/dataviews/actions/reset-post.d.ts.map +1 -1
  269. package/build-types/dataviews/actions/restore-post.d.ts +5 -0
  270. package/build-types/dataviews/actions/restore-post.d.ts.map +1 -0
  271. package/build-types/dataviews/actions/trash-post.d.ts +5 -0
  272. package/build-types/dataviews/actions/trash-post.d.ts.map +1 -0
  273. package/build-types/dataviews/actions/utils.d.ts +5 -3
  274. package/build-types/dataviews/actions/utils.d.ts.map +1 -1
  275. package/build-types/dataviews/actions/view-post-revisions.d.ts +8 -0
  276. package/build-types/dataviews/actions/view-post-revisions.d.ts.map +1 -0
  277. package/build-types/dataviews/actions/view-post.d.ts +8 -0
  278. package/build-types/dataviews/actions/view-post.d.ts.map +1 -0
  279. package/build-types/dataviews/fields/index.d.ts +8 -0
  280. package/build-types/dataviews/fields/index.d.ts.map +1 -0
  281. package/build-types/dataviews/store/private-actions.d.ts +8 -3
  282. package/build-types/dataviews/store/private-actions.d.ts.map +1 -1
  283. package/build-types/dataviews/store/private-selectors.d.ts +2 -1
  284. package/build-types/dataviews/store/private-selectors.d.ts.map +1 -1
  285. package/build-types/dataviews/store/reducer.d.ts +4 -1
  286. package/build-types/dataviews/store/reducer.d.ts.map +1 -1
  287. package/build-types/dataviews/types.d.ts +66 -8
  288. package/build-types/dataviews/types.d.ts.map +1 -1
  289. package/build-types/store/actions.d.ts.map +1 -1
  290. package/build-types/store/private-actions.d.ts.map +1 -1
  291. package/build-types/store/private-selectors.d.ts +11 -0
  292. package/build-types/store/private-selectors.d.ts.map +1 -1
  293. package/build-types/store/reducer.d.ts +1 -0
  294. package/build-types/store/reducer.d.ts.map +1 -1
  295. package/build-types/store/utils/is-template-revertable.d.ts.map +1 -1
  296. package/package.json +36 -36
  297. package/src/bindings/post-meta.js +20 -0
  298. package/src/components/block-manager/style.scss +2 -2
  299. package/src/components/blog-title/index.js +1 -1
  300. package/src/components/commands/index.js +4 -2
  301. package/src/components/create-template-part-modal/index.js +1 -0
  302. package/src/components/document-bar/index.js +1 -1
  303. package/src/components/document-bar/style.scss +1 -1
  304. package/src/components/editor-interface/style.scss +5 -0
  305. package/src/components/error-boundary/style.native.scss +1 -1
  306. package/src/components/error-boundary/style.scss +1 -1
  307. package/src/components/global-styles-provider/index.js +16 -3
  308. package/src/components/header/index.js +1 -2
  309. package/src/components/inserter-sidebar/index.js +10 -4
  310. package/src/components/list-view-sidebar/style.scss +4 -0
  311. package/src/components/page-attributes/parent.js +38 -16
  312. package/src/components/post-actions/actions.js +10 -1044
  313. package/src/components/post-actions/index.js +25 -17
  314. package/src/components/post-author/hook.js +11 -3
  315. package/src/components/post-author/panel.js +3 -1
  316. package/src/components/post-card-panel/index.js +29 -28
  317. package/src/components/post-comments/index.js +7 -20
  318. package/src/components/post-discussion/style.scss +0 -9
  319. package/src/components/post-featured-image/index.js +2 -0
  320. package/src/components/post-format/style.scss +0 -6
  321. package/src/components/post-publish-panel/postpublish.js +8 -2
  322. package/src/components/post-publish-panel/test/__snapshots__/index.js.snap +10 -10
  323. package/src/components/post-slug/index.js +1 -0
  324. package/src/components/post-status/index.js +11 -41
  325. package/src/components/post-status/style.scss +0 -19
  326. package/src/components/post-taxonomies/hierarchical-term-selector.js +3 -1
  327. package/src/components/post-template/create-new-template-modal.js +7 -1
  328. package/src/components/post-url/index.js +15 -9
  329. package/src/components/post-url/panel.js +8 -2
  330. package/src/components/preview-dropdown/index.js +113 -35
  331. package/src/components/preview-dropdown/style.scss +5 -0
  332. package/src/components/provider/disable-non-page-content-blocks.js +27 -24
  333. package/src/components/save-publish-panels/style.scss +3 -3
  334. package/src/components/sidebar/post-summary.js +20 -16
  335. package/src/components/site-discussion/index.js +7 -19
  336. package/src/components/site-discussion/style.scss +0 -14
  337. package/src/components/template-content-panel/index.js +40 -22
  338. package/src/components/visual-editor/index.js +8 -6
  339. package/src/components/visual-editor/style.scss +1 -3
  340. package/src/dataviews/actions/duplicate-pattern.tsx +40 -0
  341. package/src/dataviews/actions/duplicate-post.native.tsx +3 -0
  342. package/src/dataviews/actions/duplicate-post.tsx +174 -0
  343. package/src/dataviews/actions/duplicate-template-part.tsx +70 -0
  344. package/src/dataviews/actions/export-pattern.native.tsx +3 -0
  345. package/src/dataviews/actions/permanently-delete-post.tsx +116 -0
  346. package/src/dataviews/actions/rename-post.tsx +146 -0
  347. package/src/dataviews/actions/reorder-page.native.tsx +3 -0
  348. package/src/dataviews/actions/reorder-page.tsx +125 -0
  349. package/src/dataviews/actions/reset-post.tsx +2 -1
  350. package/src/dataviews/actions/restore-post.tsx +134 -0
  351. package/src/dataviews/actions/trash-post.tsx +196 -0
  352. package/src/dataviews/actions/utils.ts +14 -4
  353. package/src/dataviews/actions/view-post-revisions.tsx +47 -0
  354. package/src/dataviews/actions/view-post.tsx +30 -0
  355. package/src/dataviews/fields/index.ts +26 -0
  356. package/src/dataviews/store/private-actions.ts +109 -0
  357. package/src/dataviews/store/private-selectors.ts +9 -17
  358. package/src/dataviews/store/reducer.ts +20 -1
  359. package/src/dataviews/types.ts +58 -6
  360. package/src/private-apis.js +2 -2
  361. package/src/store/actions.js +36 -13
  362. package/src/store/private-actions.js +9 -5
  363. package/src/store/private-selectors.js +45 -2
  364. package/src/store/test/private-selectors.js +78 -0
  365. package/src/store/utils/is-template-revertable.js +2 -1
  366. package/tsconfig.tsbuildinfo +1 -1
  367. package/build/dataviews/actions/index.js +0 -32
  368. package/build/dataviews/actions/index.js.map +0 -1
  369. package/build-module/dataviews/actions/index.js +0 -24
  370. package/build-module/dataviews/actions/index.js.map +0 -1
  371. package/build-types/dataviews/actions/index.d.ts +0 -2
  372. package/build-types/dataviews/actions/index.d.ts.map +0 -1
  373. package/src/components/document-outline/test/__snapshots__/index.js.snap +0 -111
  374. package/src/components/document-outline/test/index.js +0 -185
  375. package/src/dataviews/actions/index.ts +0 -25
@@ -1,1052 +1,39 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { external, trash, backup } from '@wordpress/icons';
5
- import { addQueryArgs } from '@wordpress/url';
6
- import { useDispatch, useSelect, useRegistry } from '@wordpress/data';
7
- import { decodeEntities } from '@wordpress/html-entities';
8
- import { store as coreStore } from '@wordpress/core-data';
9
- import { __, _n, sprintf, _x } from '@wordpress/i18n';
10
- import { store as noticesStore } from '@wordpress/notices';
11
- import { useMemo, useState } from '@wordpress/element';
12
- import { privateApis as patternsPrivateApis } from '@wordpress/patterns';
13
- import { parse } from '@wordpress/blocks';
14
- import { DataForm } from '@wordpress/dataviews';
15
- import {
16
- Button,
17
- TextControl,
18
- __experimentalText as Text,
19
- __experimentalHStack as HStack,
20
- __experimentalVStack as VStack,
21
- __experimentalNumberControl as NumberControl,
22
- } from '@wordpress/components';
4
+ import { useDispatch, useSelect } from '@wordpress/data';
5
+ import { useMemo, useEffect } from '@wordpress/element';
23
6
 
24
7
  /**
25
8
  * Internal dependencies
26
9
  */
27
- import {
28
- TEMPLATE_ORIGINS,
29
- TEMPLATE_PART_POST_TYPE,
30
- TEMPLATE_POST_TYPE,
31
- PATTERN_POST_TYPE,
32
- } from '../../store/constants';
33
10
  import { store as editorStore } from '../../store';
34
11
  import { unlock } from '../../lock-unlock';
35
- import { CreateTemplatePartModalContents } from '../create-template-part-modal';
36
- import { getItemTitle } from '../../dataviews/actions/utils';
37
-
38
- // Patterns.
39
- const { PATTERN_TYPES, CreatePatternModalContents, useDuplicatePatternProps } =
40
- unlock( patternsPrivateApis );
41
-
42
- // TODO: this should be shared with other components (page-pages).
43
- const fields = [
44
- {
45
- type: 'text',
46
- header: __( 'Title' ),
47
- id: 'title',
48
- placeholder: __( 'No title' ),
49
- getValue: ( { item } ) => item.title,
50
- },
51
- ];
52
-
53
- const form = {
54
- visibleFields: [ 'title' ],
55
- };
56
-
57
- /**
58
- * Check if a template is removable.
59
- *
60
- * @param {Object} template The template entity to check.
61
- * @return {boolean} Whether the template is removable.
62
- */
63
- function isTemplateRemovable( template ) {
64
- if ( ! template ) {
65
- return false;
66
- }
67
- // In patterns list page we map the templates parts to a different object
68
- // than the one returned from the endpoint. This is why we need to check for
69
- // two props whether is custom or has a theme file.
70
- return (
71
- template?.source === TEMPLATE_ORIGINS.custom &&
72
- ! template?.has_theme_file
73
- );
74
- }
75
-
76
- const trashPostAction = {
77
- id: 'move-to-trash',
78
- label: __( 'Move to Trash' ),
79
- isPrimary: true,
80
- icon: trash,
81
- isEligible( item ) {
82
- return ! [ 'auto-draft', 'trash' ].includes( item.status );
83
- },
84
- supportsBulk: true,
85
- hideModalHeader: true,
86
- RenderModal: ( { items, closeModal, onActionPerformed } ) => {
87
- const [ isBusy, setIsBusy ] = useState( false );
88
- const { createSuccessNotice, createErrorNotice } =
89
- useDispatch( noticesStore );
90
- const { deleteEntityRecord } = useDispatch( coreStore );
91
- return (
92
- <VStack spacing="5">
93
- <Text>
94
- { items.length === 1
95
- ? sprintf(
96
- // translators: %s: The item's title.
97
- __(
98
- 'Are you sure you want to move to trash "%s"?'
99
- ),
100
- getItemTitle( items[ 0 ] )
101
- )
102
- : sprintf(
103
- // translators: %d: The number of items (2 or more).
104
- _n(
105
- 'Are you sure you want to move to trash %d item?',
106
- 'Are you sure you want to move to trash %d items?',
107
- items.length
108
- ),
109
- items.length
110
- ) }
111
- </Text>
112
- <HStack justify="right">
113
- <Button
114
- variant="tertiary"
115
- onClick={ closeModal }
116
- disabled={ isBusy }
117
- accessibleWhenDisabled
118
- >
119
- { __( 'Cancel' ) }
120
- </Button>
121
- <Button
122
- variant="primary"
123
- onClick={ async () => {
124
- setIsBusy( true );
125
- const promiseResult = await Promise.allSettled(
126
- items.map( ( item ) =>
127
- deleteEntityRecord(
128
- 'postType',
129
- item.type,
130
- item.id,
131
- {},
132
- { throwOnError: true }
133
- )
134
- )
135
- );
136
- // If all the promises were fulfilled with success.
137
- if (
138
- promiseResult.every(
139
- ( { status } ) => status === 'fulfilled'
140
- )
141
- ) {
142
- let successMessage;
143
- if ( promiseResult.length === 1 ) {
144
- successMessage = sprintf(
145
- /* translators: The item's title. */
146
- __( '"%s" moved to trash.' ),
147
- getItemTitle( items[ 0 ] )
148
- );
149
- } else {
150
- successMessage = sprintf(
151
- /* translators: The number of items. */
152
- _n(
153
- '%s item moved to trash.',
154
- '%s items moved to trash.',
155
- items.length
156
- ),
157
- items.length
158
- );
159
- }
160
- createSuccessNotice( successMessage, {
161
- type: 'snackbar',
162
- id: 'move-to-trash-action',
163
- } );
164
- } else {
165
- // If there was at least one failure.
166
- let errorMessage;
167
- // If we were trying to delete a single item.
168
- if ( promiseResult.length === 1 ) {
169
- if ( promiseResult[ 0 ].reason?.message ) {
170
- errorMessage =
171
- promiseResult[ 0 ].reason.message;
172
- } else {
173
- errorMessage = __(
174
- 'An error occurred while moving to trash the item.'
175
- );
176
- }
177
- // If we were trying to delete multiple items.
178
- } else {
179
- const errorMessages = new Set();
180
- const failedPromises = promiseResult.filter(
181
- ( { status } ) => status === 'rejected'
182
- );
183
- for ( const failedPromise of failedPromises ) {
184
- if ( failedPromise.reason?.message ) {
185
- errorMessages.add(
186
- failedPromise.reason.message
187
- );
188
- }
189
- }
190
- if ( errorMessages.size === 0 ) {
191
- errorMessage = __(
192
- 'An error occurred while moving to trash the items.'
193
- );
194
- } else if ( errorMessages.size === 1 ) {
195
- errorMessage = sprintf(
196
- /* translators: %s: an error message */
197
- __(
198
- 'An error occurred while moving to trash the item: %s'
199
- ),
200
- [ ...errorMessages ][ 0 ]
201
- );
202
- } else {
203
- errorMessage = sprintf(
204
- /* translators: %s: a list of comma separated error messages */
205
- __(
206
- 'Some errors occurred while moving to trash the items: %s'
207
- ),
208
- [ ...errorMessages ].join( ',' )
209
- );
210
- }
211
- }
212
- createErrorNotice( errorMessage, {
213
- type: 'snackbar',
214
- } );
215
- }
216
- if ( onActionPerformed ) {
217
- onActionPerformed( items );
218
- }
219
- setIsBusy( false );
220
- closeModal();
221
- } }
222
- isBusy={ isBusy }
223
- disabled={ isBusy }
224
- accessibleWhenDisabled
225
- >
226
- { __( 'Trash' ) }
227
- </Button>
228
- </HStack>
229
- </VStack>
230
- );
231
- },
232
- };
233
-
234
- function useCanUserEligibilityCheckPostType( capability, postType, action ) {
235
- const registry = useRegistry();
236
- return useMemo(
237
- () => ( {
238
- ...action,
239
- isEligible( item ) {
240
- return (
241
- action.isEligible( item ) &&
242
- registry.select( coreStore ).canUser( capability, {
243
- kind: 'postType',
244
- name: postType,
245
- id: item.id,
246
- } )
247
- );
248
- },
249
- } ),
250
- [ action, registry, capability, postType ]
251
- );
252
- }
253
-
254
- function useTrashPostAction( postType ) {
255
- return useCanUserEligibilityCheckPostType(
256
- 'delete',
257
- postType,
258
- trashPostAction
259
- );
260
- }
261
-
262
- const permanentlyDeletePostAction = {
263
- id: 'permanently-delete',
264
- label: __( 'Permanently delete' ),
265
- supportsBulk: true,
266
- isEligible( { status } ) {
267
- return status === 'trash';
268
- },
269
- async callback( posts, { registry, onActionPerformed } ) {
270
- const { createSuccessNotice, createErrorNotice } =
271
- registry.dispatch( noticesStore );
272
- const { deleteEntityRecord } = registry.dispatch( coreStore );
273
- const promiseResult = await Promise.allSettled(
274
- posts.map( ( post ) => {
275
- return deleteEntityRecord(
276
- 'postType',
277
- post.type,
278
- post.id,
279
- { force: true },
280
- { throwOnError: true }
281
- );
282
- } )
283
- );
284
- // If all the promises were fulfilled with success.
285
- if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) {
286
- let successMessage;
287
- if ( promiseResult.length === 1 ) {
288
- successMessage = sprintf(
289
- /* translators: The posts's title. */
290
- __( '"%s" permanently deleted.' ),
291
- getItemTitle( posts[ 0 ] )
292
- );
293
- } else {
294
- successMessage = __( 'The posts were permanently deleted.' );
295
- }
296
- createSuccessNotice( successMessage, {
297
- type: 'snackbar',
298
- id: 'permanently-delete-post-action',
299
- } );
300
- onActionPerformed?.( posts );
301
- } else {
302
- // If there was at lease one failure.
303
- let errorMessage;
304
- // If we were trying to permanently delete a single post.
305
- if ( promiseResult.length === 1 ) {
306
- if ( promiseResult[ 0 ].reason?.message ) {
307
- errorMessage = promiseResult[ 0 ].reason.message;
308
- } else {
309
- errorMessage = __(
310
- 'An error occurred while permanently deleting the post.'
311
- );
312
- }
313
- // If we were trying to permanently delete multiple posts
314
- } else {
315
- const errorMessages = new Set();
316
- const failedPromises = promiseResult.filter(
317
- ( { status } ) => status === 'rejected'
318
- );
319
- for ( const failedPromise of failedPromises ) {
320
- if ( failedPromise.reason?.message ) {
321
- errorMessages.add( failedPromise.reason.message );
322
- }
323
- }
324
- if ( errorMessages.size === 0 ) {
325
- errorMessage = __(
326
- 'An error occurred while permanently deleting the posts.'
327
- );
328
- } else if ( errorMessages.size === 1 ) {
329
- errorMessage = sprintf(
330
- /* translators: %s: an error message */
331
- __(
332
- 'An error occurred while permanently deleting the posts: %s'
333
- ),
334
- [ ...errorMessages ][ 0 ]
335
- );
336
- } else {
337
- errorMessage = sprintf(
338
- /* translators: %s: a list of comma separated error messages */
339
- __(
340
- 'Some errors occurred while permanently deleting the posts: %s'
341
- ),
342
- [ ...errorMessages ].join( ',' )
343
- );
344
- }
345
- }
346
- createErrorNotice( errorMessage, {
347
- type: 'snackbar',
348
- } );
349
- }
350
- },
351
- };
352
-
353
- function usePermanentlyDeletePostAction( postType ) {
354
- return useCanUserEligibilityCheckPostType(
355
- 'delete',
356
- postType,
357
- permanentlyDeletePostAction
358
- );
359
- }
360
-
361
- const restorePostAction = {
362
- id: 'restore',
363
- label: __( 'Restore' ),
364
- isPrimary: true,
365
- icon: backup,
366
- supportsBulk: true,
367
- isEligible( { status } ) {
368
- return status === 'trash';
369
- },
370
- async callback( posts, { registry, onActionPerformed } ) {
371
- const { createSuccessNotice, createErrorNotice } =
372
- registry.dispatch( noticesStore );
373
- const { editEntityRecord, saveEditedEntityRecord } =
374
- registry.dispatch( coreStore );
375
- await Promise.allSettled(
376
- posts.map( ( post ) => {
377
- return editEntityRecord( 'postType', post.type, post.id, {
378
- status: 'draft',
379
- } );
380
- } )
381
- );
382
- const promiseResult = await Promise.allSettled(
383
- posts.map( ( post ) => {
384
- return saveEditedEntityRecord( 'postType', post.type, post.id, {
385
- throwOnError: true,
386
- } );
387
- } )
388
- );
389
-
390
- if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) {
391
- let successMessage;
392
- if ( posts.length === 1 ) {
393
- successMessage = sprintf(
394
- /* translators: The number of posts. */
395
- __( '"%s" has been restored.' ),
396
- getItemTitle( posts[ 0 ] )
397
- );
398
- } else if ( posts[ 0 ].type === 'page' ) {
399
- successMessage = sprintf(
400
- /* translators: The number of posts. */
401
- __( '%d pages have been restored.' ),
402
- posts.length
403
- );
404
- } else {
405
- successMessage = sprintf(
406
- /* translators: The number of posts. */
407
- __( '%d posts have been restored.' ),
408
- posts.length
409
- );
410
- }
411
- createSuccessNotice( successMessage, {
412
- type: 'snackbar',
413
- id: 'restore-post-action',
414
- } );
415
- if ( onActionPerformed ) {
416
- onActionPerformed( posts );
417
- }
418
- } else {
419
- // If there was at lease one failure.
420
- let errorMessage;
421
- // If we were trying to move a single post to the trash.
422
- if ( promiseResult.length === 1 ) {
423
- if ( promiseResult[ 0 ].reason?.message ) {
424
- errorMessage = promiseResult[ 0 ].reason.message;
425
- } else {
426
- errorMessage = __(
427
- 'An error occurred while restoring the post.'
428
- );
429
- }
430
- // If we were trying to move multiple posts to the trash
431
- } else {
432
- const errorMessages = new Set();
433
- const failedPromises = promiseResult.filter(
434
- ( { status } ) => status === 'rejected'
435
- );
436
- for ( const failedPromise of failedPromises ) {
437
- if ( failedPromise.reason?.message ) {
438
- errorMessages.add( failedPromise.reason.message );
439
- }
440
- }
441
- if ( errorMessages.size === 0 ) {
442
- errorMessage = __(
443
- 'An error occurred while restoring the posts.'
444
- );
445
- } else if ( errorMessages.size === 1 ) {
446
- errorMessage = sprintf(
447
- /* translators: %s: an error message */
448
- __( 'An error occurred while restoring the posts: %s' ),
449
- [ ...errorMessages ][ 0 ]
450
- );
451
- } else {
452
- errorMessage = sprintf(
453
- /* translators: %s: a list of comma separated error messages */
454
- __(
455
- 'Some errors occurred while restoring the posts: %s'
456
- ),
457
- [ ...errorMessages ].join( ',' )
458
- );
459
- }
460
- }
461
- createErrorNotice( errorMessage, {
462
- type: 'snackbar',
463
- } );
464
- }
465
- },
466
- };
467
-
468
- function useRestorePostAction( postType ) {
469
- return useCanUserEligibilityCheckPostType(
470
- 'update',
471
- postType,
472
- restorePostAction
473
- );
474
- }
475
-
476
- const viewPostAction = {
477
- id: 'view-post',
478
- label: __( 'View' ),
479
- isPrimary: true,
480
- icon: external,
481
- isEligible( post ) {
482
- return post.status !== 'trash';
483
- },
484
- callback( posts, { onActionPerformed } ) {
485
- const post = posts[ 0 ];
486
- window.open( post.link, '_blank' );
487
- if ( onActionPerformed ) {
488
- onActionPerformed( posts );
489
- }
490
- },
491
- };
492
-
493
- const postRevisionsAction = {
494
- id: 'view-post-revisions',
495
- context: 'list',
496
- label( items ) {
497
- const revisionsCount =
498
- items[ 0 ]._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0;
499
- return sprintf(
500
- /* translators: %s: number of revisions */
501
- __( 'View revisions (%s)' ),
502
- revisionsCount
503
- );
504
- },
505
- isEligible: ( post ) => {
506
- if ( post.status === 'trash' ) {
507
- return false;
508
- }
509
- const lastRevisionId =
510
- post?._links?.[ 'predecessor-version' ]?.[ 0 ]?.id ?? null;
511
- const revisionsCount =
512
- post?._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0;
513
- return lastRevisionId && revisionsCount > 1;
514
- },
515
- callback( posts, { onActionPerformed } ) {
516
- const post = posts[ 0 ];
517
- const href = addQueryArgs( 'revision.php', {
518
- revision: post?._links?.[ 'predecessor-version' ]?.[ 0 ]?.id,
519
- } );
520
- document.location.href = href;
521
- if ( onActionPerformed ) {
522
- onActionPerformed( posts );
523
- }
524
- },
525
- };
526
-
527
- const renamePostAction = {
528
- id: 'rename-post',
529
- label: __( 'Rename' ),
530
- isEligible( post ) {
531
- if ( post.status === 'trash' ) {
532
- return false;
533
- }
534
- // Templates, template parts and patterns have special checks for renaming.
535
- if (
536
- ! [
537
- TEMPLATE_POST_TYPE,
538
- TEMPLATE_PART_POST_TYPE,
539
- ...Object.values( PATTERN_TYPES ),
540
- ].includes( post.type )
541
- ) {
542
- return true;
543
- }
544
- // In the case of templates, we can only rename custom templates.
545
- if ( post.type === TEMPLATE_POST_TYPE ) {
546
- return isTemplateRemovable( post ) && post.is_custom;
547
- }
548
- // Make necessary checks for template parts and patterns.
549
- const isTemplatePart = post.type === TEMPLATE_PART_POST_TYPE;
550
- const isUserPattern = post.type === PATTERN_TYPES.user;
551
- // In patterns list page we map the templates parts to a different object
552
- // than the one returned from the endpoint. This is why we need to check for
553
- // two props whether is custom or has a theme file.
554
- const isCustomPattern =
555
- isUserPattern ||
556
- ( isTemplatePart && post.source === TEMPLATE_ORIGINS.custom );
557
- const hasThemeFile = post?.has_theme_file;
558
- return isCustomPattern && ! hasThemeFile;
559
- },
560
- RenderModal: ( { items, closeModal, onActionPerformed } ) => {
561
- const [ item ] = items;
562
- const [ title, setTitle ] = useState( () => getItemTitle( item ) );
563
- const { editEntityRecord, saveEditedEntityRecord } =
564
- useDispatch( coreStore );
565
- const { createSuccessNotice, createErrorNotice } =
566
- useDispatch( noticesStore );
567
-
568
- async function onRename( event ) {
569
- event.preventDefault();
570
- try {
571
- await editEntityRecord( 'postType', item.type, item.id, {
572
- title,
573
- } );
574
- // Update state before saving rerenders the list.
575
- setTitle( '' );
576
- closeModal();
577
- // Persist edited entity.
578
- await saveEditedEntityRecord( 'postType', item.type, item.id, {
579
- throwOnError: true,
580
- } );
581
- createSuccessNotice( __( 'Name updated' ), {
582
- type: 'snackbar',
583
- } );
584
- onActionPerformed?.( items );
585
- } catch ( error ) {
586
- const errorMessage =
587
- error.message && error.code !== 'unknown_error'
588
- ? error.message
589
- : __( 'An error occurred while updating the name' );
590
- createErrorNotice( errorMessage, { type: 'snackbar' } );
591
- }
592
- }
593
-
594
- return (
595
- <form onSubmit={ onRename }>
596
- <VStack spacing="5">
597
- <TextControl
598
- __nextHasNoMarginBottom
599
- __next40pxDefaultSize
600
- label={ __( 'Name' ) }
601
- value={ title }
602
- onChange={ setTitle }
603
- required
604
- />
605
- <HStack justify="right">
606
- <Button
607
- __next40pxDefaultSize
608
- variant="tertiary"
609
- onClick={ () => {
610
- closeModal();
611
- } }
612
- >
613
- { __( 'Cancel' ) }
614
- </Button>
615
- <Button
616
- __next40pxDefaultSize
617
- variant="primary"
618
- type="submit"
619
- >
620
- { __( 'Save' ) }
621
- </Button>
622
- </HStack>
623
- </VStack>
624
- </form>
625
- );
626
- },
627
- };
628
-
629
- function useRenamePostAction( postType ) {
630
- return useCanUserEligibilityCheckPostType(
631
- 'update',
632
- postType,
633
- renamePostAction
634
- );
635
- }
636
-
637
- function ReorderModal( { items, closeModal, onActionPerformed } ) {
638
- const [ item ] = items;
639
- const { editEntityRecord, saveEditedEntityRecord } =
640
- useDispatch( coreStore );
641
- const { createSuccessNotice, createErrorNotice } =
642
- useDispatch( noticesStore );
643
- const [ orderInput, setOrderInput ] = useState( item.menu_order );
644
-
645
- async function onOrder( event ) {
646
- event.preventDefault();
647
- if (
648
- ! Number.isInteger( Number( orderInput ) ) ||
649
- orderInput?.trim?.() === ''
650
- ) {
651
- return;
652
- }
653
- try {
654
- await editEntityRecord( 'postType', item.type, item.id, {
655
- menu_order: orderInput,
656
- } );
657
- closeModal();
658
- // Persist edited entity.
659
- await saveEditedEntityRecord( 'postType', item.type, item.id, {
660
- throwOnError: true,
661
- } );
662
- createSuccessNotice( __( 'Order updated' ), {
663
- type: 'snackbar',
664
- } );
665
- onActionPerformed?.( items );
666
- } catch ( error ) {
667
- const errorMessage =
668
- error.message && error.code !== 'unknown_error'
669
- ? error.message
670
- : __( 'An error occurred while updating the order' );
671
- createErrorNotice( errorMessage, {
672
- type: 'snackbar',
673
- } );
674
- }
675
- }
676
- const saveIsDisabled =
677
- ! Number.isInteger( Number( orderInput ) ) ||
678
- orderInput?.trim?.() === '';
679
- return (
680
- <form onSubmit={ onOrder }>
681
- <VStack spacing="5">
682
- <div>
683
- { __(
684
- 'Determines the order of pages. Pages with the same order value are sorted alphabetically. Negative order values are supported.'
685
- ) }
686
- </div>
687
- <NumberControl
688
- __next40pxDefaultSize
689
- label={ __( 'Order' ) }
690
- help={ __( 'Set the page order.' ) }
691
- value={ orderInput }
692
- onChange={ setOrderInput }
693
- />
694
- <HStack justify="right">
695
- <Button
696
- __next40pxDefaultSize
697
- variant="tertiary"
698
- onClick={ () => {
699
- closeModal();
700
- } }
701
- >
702
- { __( 'Cancel' ) }
703
- </Button>
704
- <Button
705
- __next40pxDefaultSize
706
- variant="primary"
707
- type="submit"
708
- accessibleWhenDisabled
709
- disabled={ saveIsDisabled }
710
- __experimentalIsFocusable
711
- >
712
- { __( 'Save' ) }
713
- </Button>
714
- </HStack>
715
- </VStack>
716
- </form>
717
- );
718
- }
719
-
720
- function useReorderPagesAction( postType ) {
721
- const supportsPageAttributes = useSelect(
722
- ( select ) => {
723
- const { getPostType } = select( coreStore );
724
- const postTypeObject = getPostType( postType );
725
-
726
- return !! postTypeObject?.supports?.[ 'page-attributes' ];
727
- },
728
- [ postType ]
729
- );
730
-
731
- return useMemo(
732
- () =>
733
- supportsPageAttributes && {
734
- id: 'order-pages',
735
- label: __( 'Order' ),
736
- isEligible( { status } ) {
737
- return status !== 'trash';
738
- },
739
- RenderModal: ReorderModal,
740
- },
741
- [ supportsPageAttributes ]
742
- );
743
- }
744
-
745
- const useDuplicatePostAction = ( postType ) => {
746
- const userCanCreatePost = useSelect(
747
- ( select ) => {
748
- return select( coreStore ).canUser( 'create', {
749
- kind: 'postType',
750
- name: postType,
751
- } );
752
- },
753
- [ postType ]
754
- );
755
- return useMemo(
756
- () =>
757
- userCanCreatePost && {
758
- id: 'duplicate-post',
759
- label: _x( 'Duplicate', 'action label' ),
760
- isEligible( { status } ) {
761
- return status !== 'trash';
762
- },
763
- RenderModal: ( { items, closeModal, onActionPerformed } ) => {
764
- const [ item, setItem ] = useState( {
765
- ...items[ 0 ],
766
- title: sprintf(
767
- /* translators: %s: Existing template title */
768
- __( '%s (Copy)' ),
769
- getItemTitle( items[ 0 ] )
770
- ),
771
- } );
772
-
773
- const [ isCreatingPage, setIsCreatingPage ] =
774
- useState( false );
775
-
776
- const { saveEntityRecord } = useDispatch( coreStore );
777
- const { createSuccessNotice, createErrorNotice } =
778
- useDispatch( noticesStore );
779
-
780
- async function createPage( event ) {
781
- event.preventDefault();
782
-
783
- if ( isCreatingPage ) {
784
- return;
785
- }
786
-
787
- const newItemOject = {
788
- status: 'draft',
789
- title: item.title,
790
- slug: item.title || __( 'No title' ),
791
- comment_status: item.comment_status,
792
- content:
793
- typeof item.content === 'string'
794
- ? item.content
795
- : item.content.raw,
796
- excerpt: item.excerpt.raw,
797
- meta: item.meta,
798
- parent: item.parent,
799
- password: item.password,
800
- template: item.template,
801
- format: item.format,
802
- featured_media: item.featured_media,
803
- menu_order: item.menu_order,
804
- ping_status: item.ping_status,
805
- };
806
- const assignablePropertiesPrefix = 'wp:action-assign-';
807
- // Get all the properties that the current user is able to assign normally author, categories, tags,
808
- // and custom taxonomies.
809
- const assignableProperties = Object.keys(
810
- item?._links || {}
811
- )
812
- .filter( ( property ) =>
813
- property.startsWith(
814
- assignablePropertiesPrefix
815
- )
816
- )
817
- .map( ( property ) =>
818
- property.slice(
819
- assignablePropertiesPrefix.length
820
- )
821
- );
822
- assignableProperties.forEach( ( property ) => {
823
- if ( item[ property ] ) {
824
- newItemOject[ property ] = item[ property ];
825
- }
826
- } );
827
- setIsCreatingPage( true );
828
- try {
829
- const newItem = await saveEntityRecord(
830
- 'postType',
831
- item.type,
832
- newItemOject,
833
- { throwOnError: true }
834
- );
835
-
836
- createSuccessNotice(
837
- sprintf(
838
- // translators: %s: Title of the created template e.g: "Category".
839
- __( '"%s" successfully created.' ),
840
- decodeEntities(
841
- newItem.title?.rendered || item.title
842
- )
843
- ),
844
- {
845
- id: 'duplicate-post-action',
846
- type: 'snackbar',
847
- }
848
- );
849
-
850
- if ( onActionPerformed ) {
851
- onActionPerformed( [ newItem ] );
852
- }
853
- } catch ( error ) {
854
- const errorMessage =
855
- error.message && error.code !== 'unknown_error'
856
- ? error.message
857
- : __(
858
- 'An error occurred while duplicating the page.'
859
- );
860
-
861
- createErrorNotice( errorMessage, {
862
- type: 'snackbar',
863
- } );
864
- } finally {
865
- setIsCreatingPage( false );
866
- closeModal();
867
- }
868
- }
869
-
870
- return (
871
- <form onSubmit={ createPage }>
872
- <VStack spacing={ 3 }>
873
- <DataForm
874
- data={ item }
875
- fields={ fields }
876
- form={ form }
877
- onChange={ setItem }
878
- />
879
- <HStack spacing={ 2 } justify="end">
880
- <Button
881
- variant="tertiary"
882
- onClick={ closeModal }
883
- __next40pxDefaultSize
884
- >
885
- { __( 'Cancel' ) }
886
- </Button>
887
- <Button
888
- variant="primary"
889
- type="submit"
890
- isBusy={ isCreatingPage }
891
- aria-disabled={ isCreatingPage }
892
- __next40pxDefaultSize
893
- >
894
- { _x( 'Duplicate', 'action label' ) }
895
- </Button>
896
- </HStack>
897
- </VStack>
898
- </form>
899
- );
900
- },
901
- },
902
- [ userCanCreatePost ]
903
- );
904
- };
905
-
906
- export const duplicatePatternAction = {
907
- id: 'duplicate-pattern',
908
- label: _x( 'Duplicate', 'action label' ),
909
- isEligible: ( item ) => item.type !== TEMPLATE_PART_POST_TYPE,
910
- modalHeader: _x( 'Duplicate pattern', 'action label' ),
911
- RenderModal: ( { items, closeModal } ) => {
912
- const [ item ] = items;
913
- const duplicatedProps = useDuplicatePatternProps( {
914
- pattern: item,
915
- onSuccess: () => closeModal(),
916
- } );
917
- return (
918
- <CreatePatternModalContents
919
- onClose={ closeModal }
920
- confirmLabel={ _x( 'Duplicate', 'action label' ) }
921
- { ...duplicatedProps }
922
- />
923
- );
924
- },
925
- };
926
-
927
- export const duplicateTemplatePartAction = {
928
- id: 'duplicate-template-part',
929
- label: _x( 'Duplicate', 'action label' ),
930
- isEligible: ( item ) => item.type === TEMPLATE_PART_POST_TYPE,
931
- modalHeader: _x( 'Duplicate template part', 'action label' ),
932
- RenderModal: ( { items, closeModal } ) => {
933
- const [ item ] = items;
934
- const blocks = useMemo( () => {
935
- return (
936
- item.blocks ??
937
- parse(
938
- typeof item.content === 'string'
939
- ? item.content
940
- : item.content.raw,
941
- {
942
- __unstableSkipMigrationLogs: true,
943
- }
944
- )
945
- );
946
- }, [ item.content, item.blocks ] );
947
- const { createSuccessNotice } = useDispatch( noticesStore );
948
- function onTemplatePartSuccess() {
949
- createSuccessNotice(
950
- sprintf(
951
- // translators: %s: The new template part's title e.g. 'Call to action (copy)'.
952
- __( '"%s" duplicated.' ),
953
- getItemTitle( item )
954
- ),
955
- { type: 'snackbar', id: 'edit-site-patterns-success' }
956
- );
957
- closeModal();
958
- }
959
- return (
960
- <CreateTemplatePartModalContents
961
- blocks={ blocks }
962
- defaultArea={ item.area }
963
- defaultTitle={ sprintf(
964
- /* translators: %s: Existing template part title */
965
- __( '%s (Copy)' ),
966
- getItemTitle( item )
967
- ) }
968
- onCreate={ onTemplatePartSuccess }
969
- onError={ closeModal }
970
- confirmLabel={ _x( 'Duplicate', 'action label' ) }
971
- />
972
- );
973
- },
974
- };
975
12
 
976
13
  export function usePostActions( { postType, onActionPerformed, context } ) {
977
- const {
978
- defaultActions,
979
- postTypeObject,
980
- userCanCreatePostType,
981
- cachedCanUserResolvers,
982
- } = useSelect(
14
+ const { defaultActions } = useSelect(
983
15
  ( select ) => {
984
- const { getPostType, canUser, getCachedResolvers } =
985
- select( coreStore );
986
16
  const { getEntityActions } = unlock( select( editorStore ) );
987
- const _postTypeObject = getPostType( postType );
988
17
  return {
989
- postTypeObject: _postTypeObject,
990
18
  defaultActions: getEntityActions( 'postType', postType ),
991
- userCanCreatePostType: canUser( 'create', {
992
- kind: 'postType',
993
- name: postType,
994
- } ),
995
- cachedCanUserResolvers: getCachedResolvers()?.canUser,
996
19
  };
997
20
  },
998
21
  [ postType ]
999
22
  );
1000
23
 
1001
- const duplicatePostAction = useDuplicatePostAction( postType );
1002
- const trashPostActionForPostType = useTrashPostAction( postType );
1003
- const permanentlyDeletePostActionForPostType =
1004
- usePermanentlyDeletePostAction( postType );
1005
- const renamePostActionForPostType = useRenamePostAction( postType );
1006
- const restorePostActionForPostType = useRestorePostAction( postType );
1007
- const reorderPagesAction = useReorderPagesAction( postType );
1008
- const isTemplateOrTemplatePart = [
1009
- TEMPLATE_POST_TYPE,
1010
- TEMPLATE_PART_POST_TYPE,
1011
- ].includes( postType );
1012
- const isPattern = postType === PATTERN_POST_TYPE;
1013
- const isLoaded = !! postTypeObject;
1014
- const supportsRevisions = !! postTypeObject?.supports?.revisions;
1015
- const supportsTitle = !! postTypeObject?.supports?.title;
1016
- return useMemo( () => {
1017
- if ( ! isLoaded ) {
1018
- return [];
1019
- }
24
+ const { registerPostTypeActions } = unlock( useDispatch( editorStore ) );
25
+ useEffect( () => {
26
+ registerPostTypeActions( postType );
27
+ }, [ registerPostTypeActions, postType ] );
1020
28
 
1021
- let actions = [
1022
- postTypeObject?.viewable && viewPostAction,
1023
- supportsRevisions && postRevisionsAction,
1024
- globalThis.IS_GUTENBERG_PLUGIN
1025
- ? ! isTemplateOrTemplatePart &&
1026
- ! isPattern &&
1027
- duplicatePostAction
1028
- : false,
1029
- isTemplateOrTemplatePart &&
1030
- userCanCreatePostType &&
1031
- duplicateTemplatePartAction,
1032
- isPattern && userCanCreatePostType && duplicatePatternAction,
1033
- supportsTitle && renamePostActionForPostType,
1034
- reorderPagesAction,
1035
- ! isTemplateOrTemplatePart && restorePostActionForPostType,
1036
- ! isTemplateOrTemplatePart &&
1037
- ! isPattern &&
1038
- trashPostActionForPostType,
1039
- ! isTemplateOrTemplatePart &&
1040
- permanentlyDeletePostActionForPostType,
1041
- ...defaultActions,
1042
- ].filter( Boolean );
29
+ return useMemo( () => {
1043
30
  // Filter actions based on provided context. If not provided
1044
31
  // all actions are returned. We'll have a single entry for getting the actions
1045
32
  // and the consumer should provide the context to filter the actions, if needed.
1046
33
  // Actions should also provide the `context` they support, if it's specific, to
1047
34
  // compare with the provided context to get all the actions.
1048
35
  // Right now the only supported context is `list`.
1049
- actions = actions.filter( ( action ) => {
36
+ const actions = defaultActions.filter( ( action ) => {
1050
37
  if ( ! action.context ) {
1051
38
  return true;
1052
39
  }
@@ -1101,26 +88,5 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
1101
88
  }
1102
89
 
1103
90
  return actions;
1104
- // We are making this use memo depend on cachedCanUserResolvers as a way to make the component using this hook re-render
1105
- // when user capabilities are resolved. This makes sure the isEligible functions of actions dependent on capabilities are re-evaluated.
1106
- // eslint-disable-next-line react-hooks/exhaustive-deps
1107
- }, [
1108
- defaultActions,
1109
- userCanCreatePostType,
1110
- isTemplateOrTemplatePart,
1111
- isPattern,
1112
- postTypeObject?.viewable,
1113
- duplicatePostAction,
1114
- reorderPagesAction,
1115
- trashPostActionForPostType,
1116
- restorePostActionForPostType,
1117
- renamePostActionForPostType,
1118
- permanentlyDeletePostActionForPostType,
1119
- onActionPerformed,
1120
- isLoaded,
1121
- supportsRevisions,
1122
- supportsTitle,
1123
- context,
1124
- cachedCanUserResolvers,
1125
- ] );
91
+ }, [ defaultActions, onActionPerformed, context ] );
1126
92
  }