@wordpress/editor 14.1.0 → 14.2.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 (128) hide show
  1. package/CHANGELOG.md +14 -12
  2. package/README.md +28 -7
  3. package/build/components/create-template-part-modal/index.js +2 -0
  4. package/build/components/create-template-part-modal/index.js.map +1 -1
  5. package/build/components/document-bar/index.js +11 -4
  6. package/build/components/document-bar/index.js.map +1 -1
  7. package/build/components/editor-interface/index.js +5 -3
  8. package/build/components/editor-interface/index.js.map +1 -1
  9. package/build/components/entities-saved-states/entity-record-item.js +4 -12
  10. package/build/components/entities-saved-states/entity-record-item.js.map +1 -1
  11. package/build/components/global-keyboard-shortcuts/index.js +1 -1
  12. package/build/components/global-keyboard-shortcuts/index.js.map +1 -1
  13. package/build/components/global-styles-provider/index.js +6 -65
  14. package/build/components/global-styles-provider/index.js.map +1 -1
  15. package/build/components/header/index.js +6 -2
  16. package/build/components/header/index.js.map +1 -1
  17. package/build/components/index.js +10 -2
  18. package/build/components/index.js.map +1 -1
  19. package/build/components/post-actions/actions.js +321 -254
  20. package/build/components/post-actions/actions.js.map +1 -1
  21. package/build/components/post-actions/index.js +6 -1
  22. package/build/components/post-actions/index.js.map +1 -1
  23. package/build/components/post-excerpt/index.js +2 -1
  24. package/build/components/post-excerpt/index.js.map +1 -1
  25. package/build/components/post-excerpt/panel.js +2 -1
  26. package/build/components/post-excerpt/panel.js.map +1 -1
  27. package/build/components/post-slug/check.js +8 -1
  28. package/build/components/post-slug/check.js.map +1 -1
  29. package/build/components/post-slug/index.js +6 -0
  30. package/build/components/post-slug/index.js.map +1 -1
  31. package/build/components/post-status/index.js +2 -1
  32. package/build/components/post-status/index.js.map +1 -1
  33. package/build/components/post-sticky/index.js +9 -13
  34. package/build/components/post-sticky/index.js.map +1 -1
  35. package/build/components/post-template/create-new-template-modal.js +2 -0
  36. package/build/components/post-template/create-new-template-modal.js.map +1 -1
  37. package/build/components/sidebar/index.js +2 -1
  38. package/build/components/sidebar/index.js.map +1 -1
  39. package/build/components/sidebar/post-summary.js +1 -2
  40. package/build/components/sidebar/post-summary.js.map +1 -1
  41. package/build/components/template-part-content-panel/index.js +70 -0
  42. package/build/components/template-part-content-panel/index.js.map +1 -0
  43. package/build/hooks/pattern-overrides.js +1 -1
  44. package/build/hooks/pattern-overrides.js.map +1 -1
  45. package/build/lock-unlock.js +1 -1
  46. package/build/lock-unlock.js.map +1 -1
  47. package/build/store/private-actions.js +9 -5
  48. package/build/store/private-actions.js.map +1 -1
  49. package/build-module/components/create-template-part-modal/index.js +2 -0
  50. package/build-module/components/create-template-part-modal/index.js.map +1 -1
  51. package/build-module/components/document-bar/index.js +11 -4
  52. package/build-module/components/document-bar/index.js.map +1 -1
  53. package/build-module/components/editor-interface/index.js +5 -3
  54. package/build-module/components/editor-interface/index.js.map +1 -1
  55. package/build-module/components/entities-saved-states/entity-record-item.js +6 -14
  56. package/build-module/components/entities-saved-states/entity-record-item.js.map +1 -1
  57. package/build-module/components/global-keyboard-shortcuts/index.js +1 -1
  58. package/build-module/components/global-keyboard-shortcuts/index.js.map +1 -1
  59. package/build-module/components/global-styles-provider/index.js +7 -66
  60. package/build-module/components/global-styles-provider/index.js.map +1 -1
  61. package/build-module/components/header/index.js +6 -2
  62. package/build-module/components/header/index.js.map +1 -1
  63. package/build-module/components/index.js +11 -2
  64. package/build-module/components/index.js.map +1 -1
  65. package/build-module/components/post-actions/actions.js +322 -255
  66. package/build-module/components/post-actions/actions.js.map +1 -1
  67. package/build-module/components/post-actions/index.js +6 -1
  68. package/build-module/components/post-actions/index.js.map +1 -1
  69. package/build-module/components/post-excerpt/index.js +2 -1
  70. package/build-module/components/post-excerpt/index.js.map +1 -1
  71. package/build-module/components/post-excerpt/panel.js +2 -1
  72. package/build-module/components/post-excerpt/panel.js.map +1 -1
  73. package/build-module/components/post-slug/check.js +9 -0
  74. package/build-module/components/post-slug/check.js.map +1 -1
  75. package/build-module/components/post-slug/index.js +6 -0
  76. package/build-module/components/post-slug/index.js.map +1 -1
  77. package/build-module/components/post-status/index.js +2 -1
  78. package/build-module/components/post-status/index.js.map +1 -1
  79. package/build-module/components/post-sticky/index.js +10 -14
  80. package/build-module/components/post-sticky/index.js.map +1 -1
  81. package/build-module/components/post-template/create-new-template-modal.js +2 -0
  82. package/build-module/components/post-template/create-new-template-modal.js.map +1 -1
  83. package/build-module/components/sidebar/index.js +2 -1
  84. package/build-module/components/sidebar/index.js.map +1 -1
  85. package/build-module/components/sidebar/post-summary.js +1 -2
  86. package/build-module/components/sidebar/post-summary.js.map +1 -1
  87. package/build-module/components/template-part-content-panel/index.js +63 -0
  88. package/build-module/components/template-part-content-panel/index.js.map +1 -0
  89. package/build-module/hooks/pattern-overrides.js +1 -1
  90. package/build-module/hooks/pattern-overrides.js.map +1 -1
  91. package/build-module/lock-unlock.js +1 -1
  92. package/build-module/lock-unlock.js.map +1 -1
  93. package/build-module/store/private-actions.js +9 -5
  94. package/build-module/store/private-actions.js.map +1 -1
  95. package/build-style/style-rtl.css +11 -23
  96. package/build-style/style.css +11 -23
  97. package/package.json +35 -35
  98. package/src/components/create-template-part-modal/index.js +2 -0
  99. package/src/components/create-template-part-modal/style.scss +0 -6
  100. package/src/components/document-bar/index.js +11 -4
  101. package/src/components/editor-interface/index.js +14 -8
  102. package/src/components/entities-saved-states/entity-record-item.js +4 -14
  103. package/src/components/entities-saved-states/style.scss +0 -13
  104. package/src/components/global-keyboard-shortcuts/index.js +1 -1
  105. package/src/components/global-styles-provider/index.js +7 -90
  106. package/src/components/header/index.js +2 -1
  107. package/src/components/index.js +11 -2
  108. package/src/components/post-actions/actions.js +443 -374
  109. package/src/components/post-actions/index.js +3 -1
  110. package/src/components/post-card-panel/style.scss +1 -0
  111. package/src/components/post-excerpt/index.js +4 -1
  112. package/src/components/post-excerpt/panel.js +2 -1
  113. package/src/components/post-publish-panel/style.scss +1 -1
  114. package/src/components/post-slug/check.js +8 -0
  115. package/src/components/post-slug/index.js +5 -0
  116. package/src/components/post-status/index.js +2 -0
  117. package/src/components/post-sticky/index.js +10 -13
  118. package/src/components/post-sticky/style.scss +3 -2
  119. package/src/components/post-template/create-new-template-modal.js +2 -0
  120. package/src/components/post-url/style.scss +4 -0
  121. package/src/components/sidebar/index.js +2 -0
  122. package/src/components/sidebar/post-summary.js +0 -2
  123. package/src/components/template-part-content-panel/index.js +62 -0
  124. package/src/components/visual-editor/style.scss +2 -0
  125. package/src/hooks/pattern-overrides.js +2 -3
  126. package/src/lock-unlock.js +1 -1
  127. package/src/store/private-actions.js +54 -21
  128. package/tsconfig.tsbuildinfo +1 -1
@@ -85,7 +85,6 @@ const deletePostAction = {
85
85
  RenderModal: ({
86
86
  items,
87
87
  closeModal,
88
- onActionStart,
89
88
  onActionPerformed
90
89
  }) => {
91
90
  const [isBusy, setIsBusy] = (0, _element.useState)(false);
@@ -112,9 +111,6 @@ const deletePostAction = {
112
111
  variant: "primary",
113
112
  onClick: async () => {
114
113
  setIsBusy(true);
115
- if (onActionStart) {
116
- onActionStart(items);
117
- }
118
114
  await removeTemplates(items, {
119
115
  allowUndo: false
120
116
  });
@@ -144,7 +140,6 @@ const trashPostAction = {
144
140
  RenderModal: ({
145
141
  items,
146
142
  closeModal,
147
- onActionStart,
148
143
  onActionPerformed
149
144
  }) => {
150
145
  const [isBusy, setIsBusy] = (0, _element.useState)(false);
@@ -175,9 +170,6 @@ const trashPostAction = {
175
170
  variant: "primary",
176
171
  onClick: async () => {
177
172
  setIsBusy(true);
178
- if (onActionStart) {
179
- onActionStart(items);
180
- }
181
173
  const promiseResult = await Promise.allSettled(items.map(item => deleteEntityRecord('postType', item.type, item.id, {}, {
182
174
  throwOnError: true
183
175
  })));
@@ -250,176 +242,192 @@ const trashPostAction = {
250
242
  });
251
243
  }
252
244
  };
253
- function usePermanentlyDeletePostAction() {
254
- const {
255
- createSuccessNotice,
256
- createErrorNotice
257
- } = (0, _data.useDispatch)(_notices.store);
258
- const {
259
- deleteEntityRecord
260
- } = (0, _data.useDispatch)(_coreData.store);
245
+ function useCanUserEligibilityCheckPostType(capability, resource, action) {
246
+ const registry = (0, _data.useRegistry)();
261
247
  return (0, _element.useMemo)(() => ({
262
- id: 'permanently-delete',
263
- label: (0, _i18n.__)('Permanently delete'),
264
- supportsBulk: true,
265
- isEligible({
248
+ ...action,
249
+ isEligible(item) {
250
+ return action.isEligible(item) && registry.select(_coreData.store).canUser(capability, resource, item.id);
251
+ }
252
+ }), [action, registry, capability, resource]);
253
+ }
254
+ function useTrashPostAction(resource) {
255
+ return useCanUserEligibilityCheckPostType('delete', resource, trashPostAction);
256
+ }
257
+ const permanentlyDeletePostAction = {
258
+ id: 'permanently-delete',
259
+ label: (0, _i18n.__)('Permanently delete'),
260
+ supportsBulk: true,
261
+ isEligible({
262
+ status
263
+ }) {
264
+ return status === 'trash';
265
+ },
266
+ async callback(posts, {
267
+ registry
268
+ }) {
269
+ const {
270
+ createSuccessNotice,
271
+ createErrorNotice
272
+ } = registry.dispatch(_notices.store);
273
+ const {
274
+ deleteEntityRecord
275
+ } = registry.dispatch(_coreData.store);
276
+ const promiseResult = await Promise.allSettled(posts.map(post => {
277
+ return deleteEntityRecord('postType', post.type, post.id, {
278
+ force: true
279
+ }, {
280
+ throwOnError: true
281
+ });
282
+ }));
283
+ // If all the promises were fulfilled with success.
284
+ if (promiseResult.every(({
266
285
  status
267
- }) {
268
- return status === 'trash';
269
- },
270
- async callback(posts, onActionPerformed) {
271
- const promiseResult = await Promise.allSettled(posts.map(post => {
272
- return deleteEntityRecord('postType', post.type, post.id, {
273
- force: true
274
- }, {
275
- throwOnError: true
276
- });
277
- }));
278
- // If all the promises were fulfilled with success.
279
- if (promiseResult.every(({
280
- status
281
- }) => status === 'fulfilled')) {
282
- let successMessage;
283
- if (promiseResult.length === 1) {
284
- successMessage = (0, _i18n.sprintf)( /* translators: The posts's title. */
285
- (0, _i18n.__)('"%s" permanently deleted.'), getItemTitle(posts[0]));
286
+ }) => status === 'fulfilled')) {
287
+ let successMessage;
288
+ if (promiseResult.length === 1) {
289
+ successMessage = (0, _i18n.sprintf)( /* translators: The posts's title. */
290
+ (0, _i18n.__)('"%s" permanently deleted.'), getItemTitle(posts[0]));
291
+ } else {
292
+ successMessage = (0, _i18n.__)('The posts were permanently deleted.');
293
+ }
294
+ createSuccessNotice(successMessage, {
295
+ type: 'snackbar',
296
+ id: 'permanently-delete-post-action'
297
+ });
298
+ } else {
299
+ // If there was at lease one failure.
300
+ let errorMessage;
301
+ // If we were trying to permanently delete a single post.
302
+ if (promiseResult.length === 1) {
303
+ if (promiseResult[0].reason?.message) {
304
+ errorMessage = promiseResult[0].reason.message;
286
305
  } else {
287
- successMessage = (0, _i18n.__)('The posts were permanently deleted.');
288
- }
289
- createSuccessNotice(successMessage, {
290
- type: 'snackbar',
291
- id: 'permanently-delete-post-action'
292
- });
293
- if (onActionPerformed) {
294
- onActionPerformed(posts);
306
+ errorMessage = (0, _i18n.__)('An error occurred while permanently deleting the post.');
295
307
  }
308
+ // If we were trying to permanently delete multiple posts
296
309
  } else {
297
- // If there was at lease one failure.
298
- let errorMessage;
299
- // If we were trying to permanently delete a single post.
300
- if (promiseResult.length === 1) {
301
- if (promiseResult[0].reason?.message) {
302
- errorMessage = promiseResult[0].reason.message;
303
- } else {
304
- errorMessage = (0, _i18n.__)('An error occurred while permanently deleting the post.');
310
+ const errorMessages = new Set();
311
+ const failedPromises = promiseResult.filter(({
312
+ status
313
+ }) => status === 'rejected');
314
+ for (const failedPromise of failedPromises) {
315
+ if (failedPromise.reason?.message) {
316
+ errorMessages.add(failedPromise.reason.message);
305
317
  }
306
- // If we were trying to permanently delete multiple posts
318
+ }
319
+ if (errorMessages.size === 0) {
320
+ errorMessage = (0, _i18n.__)('An error occurred while permanently deleting the posts.');
321
+ } else if (errorMessages.size === 1) {
322
+ errorMessage = (0, _i18n.sprintf)( /* translators: %s: an error message */
323
+ (0, _i18n.__)('An error occurred while permanently deleting the posts: %s'), [...errorMessages][0]);
307
324
  } else {
308
- const errorMessages = new Set();
309
- const failedPromises = promiseResult.filter(({
310
- status
311
- }) => status === 'rejected');
312
- for (const failedPromise of failedPromises) {
313
- if (failedPromise.reason?.message) {
314
- errorMessages.add(failedPromise.reason.message);
315
- }
316
- }
317
- if (errorMessages.size === 0) {
318
- errorMessage = (0, _i18n.__)('An error occurred while permanently deleting the posts.');
319
- } else if (errorMessages.size === 1) {
320
- errorMessage = (0, _i18n.sprintf)( /* translators: %s: an error message */
321
- (0, _i18n.__)('An error occurred while permanently deleting the posts: %s'), [...errorMessages][0]);
322
- } else {
323
- errorMessage = (0, _i18n.sprintf)( /* translators: %s: a list of comma separated error messages */
324
- (0, _i18n.__)('Some errors occurred while permanently deleting the posts: %s'), [...errorMessages].join(','));
325
- }
325
+ errorMessage = (0, _i18n.sprintf)( /* translators: %s: a list of comma separated error messages */
326
+ (0, _i18n.__)('Some errors occurred while permanently deleting the posts: %s'), [...errorMessages].join(','));
326
327
  }
327
- createErrorNotice(errorMessage, {
328
- type: 'snackbar'
329
- });
330
328
  }
329
+ createErrorNotice(errorMessage, {
330
+ type: 'snackbar'
331
+ });
331
332
  }
332
- }), [createSuccessNotice, createErrorNotice, deleteEntityRecord]);
333
+ }
334
+ };
335
+ function usePermanentlyDeletePostAction(resource) {
336
+ return useCanUserEligibilityCheckPostType('delete', resource, permanentlyDeletePostAction);
333
337
  }
334
- function useRestorePostAction() {
335
- const {
336
- createSuccessNotice,
337
- createErrorNotice
338
- } = (0, _data.useDispatch)(_notices.store);
339
- const {
340
- editEntityRecord,
341
- saveEditedEntityRecord
342
- } = (0, _data.useDispatch)(_coreData.store);
343
- return (0, _element.useMemo)(() => ({
344
- id: 'restore',
345
- label: (0, _i18n.__)('Restore'),
346
- isPrimary: true,
347
- icon: _icons.backup,
348
- supportsBulk: true,
349
- isEligible({
338
+ const restorePostAction = {
339
+ id: 'restore',
340
+ label: (0, _i18n.__)('Restore'),
341
+ isPrimary: true,
342
+ icon: _icons.backup,
343
+ supportsBulk: true,
344
+ isEligible({
345
+ status
346
+ }) {
347
+ return status === 'trash';
348
+ },
349
+ async callback(posts, {
350
+ registry,
351
+ onActionPerformed
352
+ }) {
353
+ const {
354
+ createSuccessNotice,
355
+ createErrorNotice
356
+ } = registry.dispatch(_notices.store);
357
+ const {
358
+ editEntityRecord,
359
+ saveEditedEntityRecord
360
+ } = registry.dispatch(_coreData.store);
361
+ await Promise.allSettled(posts.map(post => {
362
+ return editEntityRecord('postType', post.type, post.id, {
363
+ status: 'draft'
364
+ });
365
+ }));
366
+ const promiseResult = await Promise.allSettled(posts.map(post => {
367
+ return saveEditedEntityRecord('postType', post.type, post.id, {
368
+ throwOnError: true
369
+ });
370
+ }));
371
+ if (promiseResult.every(({
350
372
  status
351
- }) {
352
- return status === 'trash';
353
- },
354
- async callback(posts, onActionPerformed) {
355
- await Promise.allSettled(posts.map(post => {
356
- return editEntityRecord('postType', post.type, post.id, {
357
- status: 'draft'
358
- });
359
- }));
360
- const promiseResult = await Promise.allSettled(posts.map(post => {
361
- return saveEditedEntityRecord('postType', post.type, post.id, {
362
- throwOnError: true
363
- });
364
- }));
365
- if (promiseResult.every(({
366
- status
367
- }) => status === 'fulfilled')) {
368
- let successMessage;
369
- if (posts.length === 1) {
370
- successMessage = (0, _i18n.sprintf)( /* translators: The number of posts. */
371
- (0, _i18n.__)('"%s" has been restored.'), getItemTitle(posts[0]));
372
- } else if (posts[0].type === 'page') {
373
- successMessage = (0, _i18n.sprintf)( /* translators: The number of posts. */
374
- (0, _i18n.__)('%d pages have been restored.'), posts.length);
373
+ }) => status === 'fulfilled')) {
374
+ let successMessage;
375
+ if (posts.length === 1) {
376
+ successMessage = (0, _i18n.sprintf)( /* translators: The number of posts. */
377
+ (0, _i18n.__)('"%s" has been restored.'), getItemTitle(posts[0]));
378
+ } else if (posts[0].type === 'page') {
379
+ successMessage = (0, _i18n.sprintf)( /* translators: The number of posts. */
380
+ (0, _i18n.__)('%d pages have been restored.'), posts.length);
381
+ } else {
382
+ successMessage = (0, _i18n.sprintf)( /* translators: The number of posts. */
383
+ (0, _i18n.__)('%d posts have been restored.'), posts.length);
384
+ }
385
+ createSuccessNotice(successMessage, {
386
+ type: 'snackbar',
387
+ id: 'restore-post-action'
388
+ });
389
+ if (onActionPerformed) {
390
+ onActionPerformed(posts);
391
+ }
392
+ } else {
393
+ // If there was at lease one failure.
394
+ let errorMessage;
395
+ // If we were trying to move a single post to the trash.
396
+ if (promiseResult.length === 1) {
397
+ if (promiseResult[0].reason?.message) {
398
+ errorMessage = promiseResult[0].reason.message;
375
399
  } else {
376
- successMessage = (0, _i18n.sprintf)( /* translators: The number of posts. */
377
- (0, _i18n.__)('%d posts have been restored.'), posts.length);
378
- }
379
- createSuccessNotice(successMessage, {
380
- type: 'snackbar',
381
- id: 'restore-post-action'
382
- });
383
- if (onActionPerformed) {
384
- onActionPerformed(posts);
400
+ errorMessage = (0, _i18n.__)('An error occurred while restoring the post.');
385
401
  }
402
+ // If we were trying to move multiple posts to the trash
386
403
  } else {
387
- // If there was at lease one failure.
388
- let errorMessage;
389
- // If we were trying to move a single post to the trash.
390
- if (promiseResult.length === 1) {
391
- if (promiseResult[0].reason?.message) {
392
- errorMessage = promiseResult[0].reason.message;
393
- } else {
394
- errorMessage = (0, _i18n.__)('An error occurred while restoring the post.');
404
+ const errorMessages = new Set();
405
+ const failedPromises = promiseResult.filter(({
406
+ status
407
+ }) => status === 'rejected');
408
+ for (const failedPromise of failedPromises) {
409
+ if (failedPromise.reason?.message) {
410
+ errorMessages.add(failedPromise.reason.message);
395
411
  }
396
- // If we were trying to move multiple posts to the trash
412
+ }
413
+ if (errorMessages.size === 0) {
414
+ errorMessage = (0, _i18n.__)('An error occurred while restoring the posts.');
415
+ } else if (errorMessages.size === 1) {
416
+ errorMessage = (0, _i18n.sprintf)( /* translators: %s: an error message */
417
+ (0, _i18n.__)('An error occurred while restoring the posts: %s'), [...errorMessages][0]);
397
418
  } else {
398
- const errorMessages = new Set();
399
- const failedPromises = promiseResult.filter(({
400
- status
401
- }) => status === 'rejected');
402
- for (const failedPromise of failedPromises) {
403
- if (failedPromise.reason?.message) {
404
- errorMessages.add(failedPromise.reason.message);
405
- }
406
- }
407
- if (errorMessages.size === 0) {
408
- errorMessage = (0, _i18n.__)('An error occurred while restoring the posts.');
409
- } else if (errorMessages.size === 1) {
410
- errorMessage = (0, _i18n.sprintf)( /* translators: %s: an error message */
411
- (0, _i18n.__)('An error occurred while restoring the posts: %s'), [...errorMessages][0]);
412
- } else {
413
- errorMessage = (0, _i18n.sprintf)( /* translators: %s: a list of comma separated error messages */
414
- (0, _i18n.__)('Some errors occurred while restoring the posts: %s'), [...errorMessages].join(','));
415
- }
419
+ errorMessage = (0, _i18n.sprintf)( /* translators: %s: a list of comma separated error messages */
420
+ (0, _i18n.__)('Some errors occurred while restoring the posts: %s'), [...errorMessages].join(','));
416
421
  }
417
- createErrorNotice(errorMessage, {
418
- type: 'snackbar'
419
- });
420
422
  }
423
+ createErrorNotice(errorMessage, {
424
+ type: 'snackbar'
425
+ });
421
426
  }
422
- }), [createSuccessNotice, createErrorNotice, editEntityRecord, saveEditedEntityRecord]);
427
+ }
428
+ };
429
+ function useRestorePostAction(resource) {
430
+ return useCanUserEligibilityCheckPostType('update', resource, restorePostAction);
423
431
  }
424
432
  const viewPostAction = {
425
433
  id: 'view-post',
@@ -429,7 +437,9 @@ const viewPostAction = {
429
437
  isEligible(post) {
430
438
  return post.status !== 'trash';
431
439
  },
432
- callback(posts, onActionPerformed) {
440
+ callback(posts, {
441
+ onActionPerformed
442
+ }) {
433
443
  const post = posts[0];
434
444
  window.open(post.link, '_blank');
435
445
  if (onActionPerformed) {
@@ -439,6 +449,7 @@ const viewPostAction = {
439
449
  };
440
450
  const postRevisionsAction = {
441
451
  id: 'view-post-revisions',
452
+ context: 'list',
442
453
  label(items) {
443
454
  var _items$0$_links$versi;
444
455
  const revisionsCount = (_items$0$_links$versi = items[0]._links?.['version-history']?.[0]?.count) !== null && _items$0$_links$versi !== void 0 ? _items$0$_links$versi : 0;
@@ -454,7 +465,9 @@ const postRevisionsAction = {
454
465
  const revisionsCount = (_post$_links$version = post?._links?.['version-history']?.[0]?.count) !== null && _post$_links$version !== void 0 ? _post$_links$version : 0;
455
466
  return lastRevisionId && revisionsCount > 1;
456
467
  },
457
- callback(posts, onActionPerformed) {
468
+ callback(posts, {
469
+ onActionPerformed
470
+ }) {
458
471
  const post = posts[0];
459
472
  const href = (0, _url.addQueryArgs)('revision.php', {
460
473
  revision: post?._links?.['predecessor-version']?.[0]?.id
@@ -561,42 +574,55 @@ const renamePostAction = {
561
574
  });
562
575
  }
563
576
  };
564
- const duplicatePostAction = {
565
- id: 'duplicate-post',
566
- label: (0, _i18n._x)('Duplicate', 'action label'),
567
- isEligible({
568
- status
569
- }) {
570
- return status !== 'trash';
571
- },
572
- RenderModal: ({
573
- items,
574
- closeModal,
575
- onActionPerformed
576
- }) => {
577
- const [item] = items;
578
- const [isCreatingPage, setIsCreatingPage] = (0, _element.useState)(false);
579
- const [title, setTitle] = (0, _element.useState)((0, _i18n.sprintf)( /* translators: %s: Existing item title */
580
- (0, _i18n.__)('%s (Copy)'), getItemTitle(item)));
581
- const {
582
- saveEntityRecord
583
- } = (0, _data.useDispatch)(_coreData.store);
577
+ function useRenamePostAction(resource) {
578
+ return useCanUserEligibilityCheckPostType('update', resource, renamePostAction);
579
+ }
580
+ const useDuplicatePostAction = postType => {
581
+ const {
582
+ userCanCreatePost
583
+ } = (0, _data.useSelect)(select => {
584
584
  const {
585
- createSuccessNotice,
586
- createErrorNotice
587
- } = (0, _data.useDispatch)(_notices.store);
588
- async function createPage(event) {
589
- event.preventDefault();
590
- if (isCreatingPage) {
591
- return;
592
- }
593
- setIsCreatingPage(true);
594
- try {
595
- const newItem = await saveEntityRecord('postType', item.type, {
585
+ getPostType,
586
+ canUser
587
+ } = select(_coreData.store);
588
+ const resource = getPostType(postType)?.rest_base || '';
589
+ return {
590
+ userCanCreatePost: canUser('create', resource)
591
+ };
592
+ }, [postType]);
593
+ return (0, _element.useMemo)(() => userCanCreatePost && {
594
+ id: 'duplicate-post',
595
+ label: (0, _i18n._x)('Duplicate', 'action label'),
596
+ isEligible({
597
+ status
598
+ }) {
599
+ return status !== 'trash';
600
+ },
601
+ RenderModal: ({
602
+ items,
603
+ closeModal,
604
+ onActionPerformed
605
+ }) => {
606
+ const [item] = items;
607
+ const [isCreatingPage, setIsCreatingPage] = (0, _element.useState)(false);
608
+ const [title, setTitle] = (0, _element.useState)((0, _i18n.sprintf)( /* translators: %s: Existing item title */
609
+ (0, _i18n.__)('%s (Copy)'), getItemTitle(item)));
610
+ const {
611
+ saveEntityRecord
612
+ } = (0, _data.useDispatch)(_coreData.store);
613
+ const {
614
+ createSuccessNotice,
615
+ createErrorNotice
616
+ } = (0, _data.useDispatch)(_notices.store);
617
+ async function createPage(event) {
618
+ event.preventDefault();
619
+ if (isCreatingPage) {
620
+ return;
621
+ }
622
+ const newItemOject = {
596
623
  status: 'draft',
597
624
  title,
598
625
  slug: title || (0, _i18n.__)('No title'),
599
- author: item.author,
600
626
  comment_status: item.comment_status,
601
627
  content: typeof item.content === 'string' ? item.content : item.content.raw,
602
628
  excerpt: item.excerpt.raw,
@@ -607,58 +633,69 @@ const duplicatePostAction = {
607
633
  format: item.format,
608
634
  featured_media: item.featured_media,
609
635
  menu_order: item.menu_order,
610
- ping_status: item.ping_status,
611
- categories: item.categories,
612
- tags: item.tags
613
- }, {
614
- throwOnError: true
615
- });
616
- createSuccessNotice((0, _i18n.sprintf)(
617
- // translators: %s: Title of the created template e.g: "Category".
618
- (0, _i18n.__)('"%s" successfully created.'), (0, _htmlEntities.decodeEntities)(newItem.title?.rendered || title)), {
619
- id: 'duplicate-post-action',
620
- type: 'snackbar'
636
+ ping_status: item.ping_status
637
+ };
638
+ const assignablePropertiesPrefix = 'wp:action-assign-';
639
+ // Get all the properties that the current user is able to assign normally author, categories, tags,
640
+ // and custom taxonomies.
641
+ const assignableProperties = Object.keys(item?._links || {}).filter(property => property.startsWith(assignablePropertiesPrefix)).map(property => property.slice(assignablePropertiesPrefix.length));
642
+ assignableProperties.forEach(property => {
643
+ if (item[property]) {
644
+ newItemOject[property] = item[property];
645
+ }
621
646
  });
622
- if (onActionPerformed) {
623
- onActionPerformed([newItem]);
647
+ setIsCreatingPage(true);
648
+ try {
649
+ const newItem = await saveEntityRecord('postType', item.type, newItemOject, {
650
+ throwOnError: true
651
+ });
652
+ createSuccessNotice((0, _i18n.sprintf)(
653
+ // translators: %s: Title of the created template e.g: "Category".
654
+ (0, _i18n.__)('"%s" successfully created.'), (0, _htmlEntities.decodeEntities)(newItem.title?.rendered || title)), {
655
+ id: 'duplicate-post-action',
656
+ type: 'snackbar'
657
+ });
658
+ if (onActionPerformed) {
659
+ onActionPerformed([newItem]);
660
+ }
661
+ } catch (error) {
662
+ const errorMessage = error.message && error.code !== 'unknown_error' ? error.message : (0, _i18n.__)('An error occurred while duplicating the page.');
663
+ createErrorNotice(errorMessage, {
664
+ type: 'snackbar'
665
+ });
666
+ } finally {
667
+ setIsCreatingPage(false);
668
+ closeModal();
624
669
  }
625
- } catch (error) {
626
- const errorMessage = error.message && error.code !== 'unknown_error' ? error.message : (0, _i18n.__)('An error occurred while duplicating the page.');
627
- createErrorNotice(errorMessage, {
628
- type: 'snackbar'
629
- });
630
- } finally {
631
- setIsCreatingPage(false);
632
- closeModal();
633
670
  }
634
- }
635
- return /*#__PURE__*/(0, _jsxRuntime.jsx)("form", {
636
- onSubmit: createPage,
637
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalVStack, {
638
- spacing: 3,
639
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.TextControl, {
640
- label: (0, _i18n.__)('Title'),
641
- onChange: setTitle,
642
- placeholder: (0, _i18n.__)('No title'),
643
- value: title
644
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalHStack, {
645
- spacing: 2,
646
- justify: "end",
647
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
648
- variant: "tertiary",
649
- onClick: closeModal,
650
- children: (0, _i18n.__)('Cancel')
651
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
652
- variant: "primary",
653
- type: "submit",
654
- isBusy: isCreatingPage,
655
- "aria-disabled": isCreatingPage,
656
- children: (0, _i18n._x)('Duplicate', 'action label')
671
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("form", {
672
+ onSubmit: createPage,
673
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalVStack, {
674
+ spacing: 3,
675
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.TextControl, {
676
+ label: (0, _i18n.__)('Title'),
677
+ onChange: setTitle,
678
+ placeholder: (0, _i18n.__)('No title'),
679
+ value: title
680
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalHStack, {
681
+ spacing: 2,
682
+ justify: "end",
683
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
684
+ variant: "tertiary",
685
+ onClick: closeModal,
686
+ children: (0, _i18n.__)('Cancel')
687
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
688
+ variant: "primary",
689
+ type: "submit",
690
+ isBusy: isCreatingPage,
691
+ "aria-disabled": isCreatingPage,
692
+ children: (0, _i18n._x)('Duplicate', 'action label')
693
+ })]
657
694
  })]
658
- })]
659
- })
660
- });
661
- }
695
+ })
696
+ });
697
+ }
698
+ }, [userCanCreatePost]);
662
699
  };
663
700
  const isTemplatePartRevertable = item => {
664
701
  if (!item) {
@@ -679,7 +716,6 @@ const resetTemplateAction = {
679
716
  RenderModal: ({
680
717
  items,
681
718
  closeModal,
682
- onActionStart,
683
719
  onActionPerformed
684
720
  }) => {
685
721
  const [isBusy, setIsBusy] = (0, _element.useState)(false);
@@ -743,9 +779,6 @@ const resetTemplateAction = {
743
779
  variant: "primary",
744
780
  onClick: async () => {
745
781
  setIsBusy(true);
746
- if (onActionStart) {
747
- onActionStart(items);
748
- }
749
782
  await onConfirm(items);
750
783
  onActionPerformed?.(items);
751
784
  setIsBusy(false);
@@ -815,24 +848,41 @@ const duplicateTemplatePartAction = exports.duplicateTemplatePartAction = {
815
848
  });
816
849
  }
817
850
  };
818
- function usePostActions(postType, onActionPerformed) {
851
+ function usePostActions({
852
+ postType,
853
+ onActionPerformed,
854
+ context
855
+ }) {
819
856
  const {
820
857
  defaultActions,
821
- postTypeObject
858
+ postTypeObject,
859
+ userCanCreatePostType,
860
+ resource,
861
+ cachedCanUserResolvers
822
862
  } = (0, _data.useSelect)(select => {
823
863
  const {
824
- getPostType
864
+ getPostType,
865
+ canUser,
866
+ getCachedResolvers
825
867
  } = select(_coreData.store);
826
868
  const {
827
869
  getEntityActions
828
870
  } = (0, _lockUnlock.unlock)(select(_store.store));
871
+ const _postTypeObject = getPostType(postType);
872
+ const _resource = _postTypeObject?.rest_base || '';
829
873
  return {
830
- postTypeObject: getPostType(postType),
831
- defaultActions: getEntityActions('postType', postType)
874
+ postTypeObject: _postTypeObject,
875
+ defaultActions: getEntityActions('postType', postType),
876
+ userCanCreatePostType: canUser('create', _resource),
877
+ resource: _resource,
878
+ cachedCanUserResolvers: getCachedResolvers()?.canUser
832
879
  };
833
880
  }, [postType]);
834
- const permanentlyDeletePostAction = usePermanentlyDeletePostAction();
835
- const restorePostAction = useRestorePostAction();
881
+ const duplicatePostAction = useDuplicatePostAction(postType);
882
+ const trashPostActionForPostType = useTrashPostAction(resource);
883
+ const permanentlyDeletePostActionForPostType = usePermanentlyDeletePostAction(resource);
884
+ const renamePostActionForPostType = useRenamePostAction(resource);
885
+ const restorePostActionForPostType = useRestorePostAction(resource);
836
886
  const isTemplateOrTemplatePart = [_constants.TEMPLATE_POST_TYPE, _constants.TEMPLATE_PART_POST_TYPE].includes(postType);
837
887
  const isPattern = postType === _constants.PATTERN_POST_TYPE;
838
888
  const isLoaded = !!postTypeObject;
@@ -842,14 +892,28 @@ function usePostActions(postType, onActionPerformed) {
842
892
  if (!isLoaded) {
843
893
  return [];
844
894
  }
845
- const actions = [postTypeObject?.viewable && viewPostAction, supportsRevisions && postRevisionsAction, globalThis.IS_GUTENBERG_PLUGIN ? !isTemplateOrTemplatePart && !isPattern && duplicatePostAction : false, isTemplateOrTemplatePart && duplicateTemplatePartAction, isPattern && duplicatePatternAction, supportsTitle && renamePostAction, isPattern && _exportPatternAction.exportPatternAsJSONAction, isTemplateOrTemplatePart ? resetTemplateAction : restorePostAction, isTemplateOrTemplatePart || isPattern ? deletePostAction : trashPostAction, !isTemplateOrTemplatePart && permanentlyDeletePostAction, ...defaultActions].filter(Boolean);
895
+ let actions = [postTypeObject?.viewable && viewPostAction, supportsRevisions && postRevisionsAction, globalThis.IS_GUTENBERG_PLUGIN ? !isTemplateOrTemplatePart && !isPattern && duplicatePostAction : false, isTemplateOrTemplatePart && userCanCreatePostType && duplicateTemplatePartAction, isPattern && userCanCreatePostType && duplicatePatternAction, supportsTitle && renamePostActionForPostType, isPattern && _exportPatternAction.exportPatternAsJSONAction, isTemplateOrTemplatePart ? resetTemplateAction : restorePostActionForPostType, isTemplateOrTemplatePart || isPattern ? deletePostAction : trashPostActionForPostType, !isTemplateOrTemplatePart && permanentlyDeletePostActionForPostType, ...defaultActions].filter(Boolean);
896
+ // Filter actions based on provided context. If not provided
897
+ // all actions are returned. We'll have a single entry for getting the actions
898
+ // and the consumer should provide the context to filter the actions, if needed.
899
+ // Actions should also provide the `context` they support, if it's specific, to
900
+ // compare with the provided context to get all the actions.
901
+ // Right now the only supported context is `list`.
902
+ actions = actions.filter(action => {
903
+ if (!action.context) {
904
+ return true;
905
+ }
906
+ return action.context === context;
907
+ });
846
908
  if (onActionPerformed) {
847
909
  for (let i = 0; i < actions.length; ++i) {
848
910
  if (actions[i].callback) {
849
911
  const existingCallback = actions[i].callback;
850
912
  actions[i] = {
851
913
  ...actions[i],
852
- callback: (items, _onActionPerformed) => {
914
+ callback: (items, {
915
+ _onActionPerformed
916
+ }) => {
853
917
  existingCallback(items, _items => {
854
918
  if (_onActionPerformed) {
855
919
  _onActionPerformed(_items);
@@ -879,6 +943,9 @@ function usePostActions(postType, onActionPerformed) {
879
943
  }
880
944
  }
881
945
  return actions;
882
- }, [defaultActions, isTemplateOrTemplatePart, isPattern, postTypeObject?.viewable, permanentlyDeletePostAction, restorePostAction, onActionPerformed, isLoaded, supportsRevisions, supportsTitle]);
946
+ // We are making this use memo depend on cachedCanUserResolvers as a way to make the component using this hook re-render
947
+ // when user capabilities are resolved. This makes sure the isEligible functions of actions dependent on capabilities are re-evaluated.
948
+ // eslint-disable-next-line react-hooks/exhaustive-deps
949
+ }, [defaultActions, userCanCreatePostType, isTemplateOrTemplatePart, isPattern, postTypeObject?.viewable, duplicatePostAction, trashPostActionForPostType, restorePostActionForPostType, renamePostActionForPostType, permanentlyDeletePostActionForPostType, onActionPerformed, isLoaded, supportsRevisions, supportsTitle, context, cachedCanUserResolvers]);
883
950
  }
884
951
  //# sourceMappingURL=actions.js.map