@wordpress/editor 14.14.0 → 14.15.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 (180) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/LICENSE.md +1 -1
  3. package/README.md +1 -0
  4. package/build/components/commands/index.js +28 -0
  5. package/build/components/commands/index.js.map +1 -1
  6. package/build/components/document-bar/index.js +2 -1
  7. package/build/components/document-bar/index.js.map +1 -1
  8. package/build/components/document-tools/index.js +3 -6
  9. package/build/components/document-tools/index.js.map +1 -1
  10. package/build/components/editor-help/intro-to-blocks.native.js +1 -1
  11. package/build/components/editor-help/intro-to-blocks.native.js.map +1 -1
  12. package/build/components/entities-saved-states/index.js +2 -1
  13. package/build/components/entities-saved-states/index.js.map +1 -1
  14. package/build/components/error-boundary/index.native.js +1 -1
  15. package/build/components/error-boundary/index.native.js.map +1 -1
  16. package/build/components/more-menu/index.js +0 -1
  17. package/build/components/more-menu/index.js.map +1 -1
  18. package/build/components/post-actions/actions.js +9 -4
  19. package/build/components/post-actions/actions.js.map +1 -1
  20. package/build/components/post-actions/index.js +17 -14
  21. package/build/components/post-actions/index.js.map +1 -1
  22. package/build/components/post-actions/set-as-homepage.js +23 -34
  23. package/build/components/post-actions/set-as-homepage.js.map +1 -1
  24. package/build/components/post-actions/set-as-posts-page.js +154 -0
  25. package/build/components/post-actions/set-as-posts-page.js.map +1 -0
  26. package/build/components/post-card-panel/index.js +12 -5
  27. package/build/components/post-card-panel/index.js.map +1 -1
  28. package/build/components/post-publish-panel/maybe-upload-media.js +1 -1
  29. package/build/components/post-publish-panel/maybe-upload-media.js.map +1 -1
  30. package/build/components/preferences-modal/index.js +2 -4
  31. package/build/components/preferences-modal/index.js.map +1 -1
  32. package/build/components/preview-dropdown/index.js +0 -1
  33. package/build/components/preview-dropdown/index.js.map +1 -1
  34. package/build/components/provider/disable-non-page-content-blocks.js +65 -13
  35. package/build/components/provider/disable-non-page-content-blocks.js.map +1 -1
  36. package/build/components/provider/index.js +9 -13
  37. package/build/components/provider/index.js.map +1 -1
  38. package/build/components/provider/use-block-editor-settings.js +3 -1
  39. package/build/components/provider/use-block-editor-settings.js.map +1 -1
  40. package/build/components/start-page-options/index.js +20 -107
  41. package/build/components/start-page-options/index.js.map +1 -1
  42. package/build/components/template-part-menu-items/index.js +2 -10
  43. package/build/components/template-part-menu-items/index.js.map +1 -1
  44. package/build/store/actions.js +0 -2
  45. package/build/store/actions.js.map +1 -1
  46. package/build/store/constants.js +1 -3
  47. package/build/store/constants.js.map +1 -1
  48. package/build/store/private-actions.js +1 -1
  49. package/build/store/private-actions.js.map +1 -1
  50. package/build/store/utils/notice-builder.js +3 -8
  51. package/build/store/utils/notice-builder.js.map +1 -1
  52. package/build/utils/get-item-title.js +32 -0
  53. package/build/utils/get-item-title.js.map +1 -0
  54. package/build/utils/media-sideload/index.js +21 -0
  55. package/build/utils/media-sideload/index.js.map +1 -0
  56. package/build/utils/media-sideload/index.native.js +8 -0
  57. package/build/utils/media-sideload/index.native.js.map +1 -0
  58. package/build/utils/media-upload/index.js +5 -2
  59. package/build/utils/media-upload/index.js.map +1 -1
  60. package/build-module/components/commands/index.js +28 -0
  61. package/build-module/components/commands/index.js.map +1 -1
  62. package/build-module/components/document-bar/index.js +2 -1
  63. package/build-module/components/document-bar/index.js.map +1 -1
  64. package/build-module/components/document-tools/index.js +4 -7
  65. package/build-module/components/document-tools/index.js.map +1 -1
  66. package/build-module/components/editor-help/intro-to-blocks.native.js +1 -1
  67. package/build-module/components/editor-help/intro-to-blocks.native.js.map +1 -1
  68. package/build-module/components/entities-saved-states/index.js +2 -1
  69. package/build-module/components/entities-saved-states/index.js.map +1 -1
  70. package/build-module/components/error-boundary/index.native.js +2 -2
  71. package/build-module/components/error-boundary/index.native.js.map +1 -1
  72. package/build-module/components/more-menu/index.js +0 -1
  73. package/build-module/components/more-menu/index.js.map +1 -1
  74. package/build-module/components/post-actions/actions.js +9 -4
  75. package/build-module/components/post-actions/actions.js.map +1 -1
  76. package/build-module/components/post-actions/index.js +18 -15
  77. package/build-module/components/post-actions/index.js.map +1 -1
  78. package/build-module/components/post-actions/set-as-homepage.js +22 -33
  79. package/build-module/components/post-actions/set-as-homepage.js.map +1 -1
  80. package/build-module/components/post-actions/set-as-posts-page.js +146 -0
  81. package/build-module/components/post-actions/set-as-posts-page.js.map +1 -0
  82. package/build-module/components/post-card-panel/index.js +11 -6
  83. package/build-module/components/post-card-panel/index.js.map +1 -1
  84. package/build-module/components/post-publish-panel/maybe-upload-media.js +2 -2
  85. package/build-module/components/post-publish-panel/maybe-upload-media.js.map +1 -1
  86. package/build-module/components/preferences-modal/index.js +2 -4
  87. package/build-module/components/preferences-modal/index.js.map +1 -1
  88. package/build-module/components/preview-dropdown/index.js +0 -1
  89. package/build-module/components/preview-dropdown/index.js.map +1 -1
  90. package/build-module/components/provider/disable-non-page-content-blocks.js +65 -13
  91. package/build-module/components/provider/disable-non-page-content-blocks.js.map +1 -1
  92. package/build-module/components/provider/index.js +10 -14
  93. package/build-module/components/provider/index.js.map +1 -1
  94. package/build-module/components/provider/use-block-editor-settings.js +3 -1
  95. package/build-module/components/provider/use-block-editor-settings.js.map +1 -1
  96. package/build-module/components/start-page-options/index.js +21 -107
  97. package/build-module/components/start-page-options/index.js.map +1 -1
  98. package/build-module/components/template-part-menu-items/index.js +2 -10
  99. package/build-module/components/template-part-menu-items/index.js.map +1 -1
  100. package/build-module/store/actions.js +0 -2
  101. package/build-module/store/actions.js.map +1 -1
  102. package/build-module/store/constants.js +0 -2
  103. package/build-module/store/constants.js.map +1 -1
  104. package/build-module/store/private-actions.js +1 -1
  105. package/build-module/store/private-actions.js.map +1 -1
  106. package/build-module/store/utils/notice-builder.js +3 -8
  107. package/build-module/store/utils/notice-builder.js.map +1 -1
  108. package/build-module/utils/get-item-title.js +26 -0
  109. package/build-module/utils/get-item-title.js.map +1 -0
  110. package/build-module/utils/media-sideload/index.js +14 -0
  111. package/build-module/utils/media-sideload/index.js.map +1 -0
  112. package/build-module/utils/media-sideload/index.native.js +2 -0
  113. package/build-module/utils/media-sideload/index.native.js.map +1 -0
  114. package/build-module/utils/media-upload/index.js +5 -2
  115. package/build-module/utils/media-upload/index.js.map +1 -1
  116. package/build-style/style-rtl.css +5 -25
  117. package/build-style/style.css +5 -25
  118. package/build-types/components/commands/index.d.ts.map +1 -1
  119. package/build-types/components/document-bar/index.d.ts.map +1 -1
  120. package/build-types/components/document-tools/index.d.ts.map +1 -1
  121. package/build-types/components/entities-saved-states/index.d.ts.map +1 -1
  122. package/build-types/components/more-menu/index.d.ts.map +1 -1
  123. package/build-types/components/post-actions/actions.d.ts.map +1 -1
  124. package/build-types/components/post-actions/index.d.ts.map +1 -1
  125. package/build-types/components/post-actions/set-as-homepage.d.ts.map +1 -1
  126. package/build-types/components/post-actions/set-as-posts-page.d.ts +10 -0
  127. package/build-types/components/post-actions/set-as-posts-page.d.ts.map +1 -0
  128. package/build-types/components/post-card-panel/index.d.ts.map +1 -1
  129. package/build-types/components/preferences-modal/index.d.ts.map +1 -1
  130. package/build-types/components/preview-dropdown/index.d.ts.map +1 -1
  131. package/build-types/components/provider/disable-non-page-content-blocks.d.ts.map +1 -1
  132. package/build-types/components/provider/index.d.ts.map +1 -1
  133. package/build-types/components/provider/use-block-editor-settings.d.ts.map +1 -1
  134. package/build-types/components/start-page-options/index.d.ts +1 -2
  135. package/build-types/components/start-page-options/index.d.ts.map +1 -1
  136. package/build-types/store/actions.d.ts.map +1 -1
  137. package/build-types/store/constants.d.ts +0 -2
  138. package/build-types/store/constants.d.ts.map +1 -1
  139. package/build-types/store/private-actions.d.ts.map +1 -1
  140. package/build-types/store/utils/notice-builder.d.ts.map +1 -1
  141. package/build-types/utils/get-item-title.d.ts +10 -0
  142. package/build-types/utils/get-item-title.d.ts.map +1 -0
  143. package/build-types/utils/media-sideload/index.d.ts +3 -0
  144. package/build-types/utils/media-sideload/index.d.ts.map +1 -0
  145. package/build-types/utils/media-upload/index.d.ts +3 -1
  146. package/build-types/utils/media-upload/index.d.ts.map +1 -1
  147. package/package.json +37 -37
  148. package/src/components/commands/index.js +29 -0
  149. package/src/components/document-bar/index.js +2 -1
  150. package/src/components/document-tools/index.js +3 -6
  151. package/src/components/document-tools/style.scss +0 -6
  152. package/src/components/editor-help/intro-to-blocks.native.js +1 -1
  153. package/src/components/entities-saved-states/index.js +5 -1
  154. package/src/components/error-boundary/index.native.js +2 -2
  155. package/src/components/more-menu/index.js +0 -1
  156. package/src/components/post-actions/actions.js +12 -4
  157. package/src/components/post-actions/index.js +19 -17
  158. package/src/components/post-actions/set-as-homepage.js +29 -45
  159. package/src/components/post-actions/set-as-posts-page.js +164 -0
  160. package/src/components/post-card-panel/index.js +8 -6
  161. package/src/components/post-card-panel/style.scss +4 -13
  162. package/src/components/post-publish-panel/maybe-upload-media.js +2 -2
  163. package/src/components/preferences-modal/index.js +8 -13
  164. package/src/components/preview-dropdown/index.js +0 -1
  165. package/src/components/provider/disable-non-page-content-blocks.js +64 -13
  166. package/src/components/provider/index.js +13 -27
  167. package/src/components/provider/use-block-editor-settings.js +3 -0
  168. package/src/components/start-page-options/index.js +28 -119
  169. package/src/components/template-part-menu-items/index.js +2 -11
  170. package/src/store/actions.js +0 -2
  171. package/src/store/constants.ts +0 -2
  172. package/src/store/private-actions.js +1 -1
  173. package/src/store/utils/notice-builder.js +3 -8
  174. package/src/store/utils/test/notice-builder.js +3 -4
  175. package/src/utils/get-item-title.js +25 -0
  176. package/src/utils/media-sideload/index.js +13 -0
  177. package/src/utils/media-sideload/index.native.js +1 -0
  178. package/src/utils/media-upload/index.js +4 -1
  179. package/tsconfig.json +1 -4
  180. package/tsconfig.tsbuildinfo +1 -1
@@ -115,6 +115,10 @@ export function EntitiesSavedStatesExtensible( {
115
115
  'description'
116
116
  );
117
117
 
118
+ const selectItemsToSaveDescription = !! dirtyEntityRecords.length
119
+ ? __( 'Select the items you want to save.' )
120
+ : undefined;
121
+
118
122
  return (
119
123
  <div
120
124
  ref={ renderDialog ? saveDialogRef : undefined }
@@ -180,7 +184,7 @@ export function EntitiesSavedStatesExtensible( {
180
184
  ),
181
185
  { strong: <strong /> }
182
186
  )
183
- : __( 'Select the items you want to save.' ) }
187
+ : selectItemsToSaveDescription }
184
188
  </p>
185
189
  </div>
186
190
 
@@ -16,7 +16,7 @@ import {
16
16
  usePreferredColorSchemeStyle,
17
17
  withPreferredColorScheme,
18
18
  } from '@wordpress/compose';
19
- import { warning } from '@wordpress/icons';
19
+ import { cautionFilled } from '@wordpress/icons';
20
20
  import { Icon } from '@wordpress/components';
21
21
 
22
22
  /**
@@ -141,7 +141,7 @@ class ErrorBoundary extends Component {
141
141
  <View style={ styles[ 'error-boundary__container' ] }>
142
142
  <View style={ iconContainerStyle }>
143
143
  <Icon
144
- icon={ warning }
144
+ icon={ cautionFilled }
145
145
  { ...styles[ 'error-boundary__icon' ] }
146
146
  />
147
147
  </View>
@@ -113,7 +113,6 @@ export default function MoreMenu() {
113
113
  <ActionItem.Slot
114
114
  name="core/plugin-more-menu"
115
115
  label={ __( 'Plugins' ) }
116
- as={ MenuGroup }
117
116
  fillProps={ { onClick: onClose } }
118
117
  />
119
118
  <MenuGroup label={ __( 'Tools' ) }>
@@ -11,6 +11,7 @@ import { store as coreStore } from '@wordpress/core-data';
11
11
  import { store as editorStore } from '../../store';
12
12
  import { unlock } from '../../lock-unlock';
13
13
  import { useSetAsHomepageAction } from './set-as-homepage';
14
+ import { useSetAsPostsPageAction } from './set-as-posts-page';
14
15
 
15
16
  export function usePostActions( { postType, onActionPerformed, context } ) {
16
17
  const { defaultActions } = useSelect(
@@ -43,7 +44,8 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
43
44
  );
44
45
 
45
46
  const setAsHomepageAction = useSetAsHomepageAction();
46
- const shouldShowSetAsHomepageAction =
47
+ const setAsPostsPageAction = useSetAsPostsPageAction();
48
+ const shouldShowHomepageActions =
47
49
  canManageOptions && ! hasFrontPageTemplate;
48
50
 
49
51
  const { registerPostTypeSchema } = unlock( useDispatch( editorStore ) );
@@ -53,10 +55,15 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
53
55
 
54
56
  return useMemo( () => {
55
57
  let actions = [ ...defaultActions ];
56
- if ( shouldShowSetAsHomepageAction ) {
57
- actions.push( setAsHomepageAction );
58
+ if ( shouldShowHomepageActions ) {
59
+ actions.push( setAsHomepageAction, setAsPostsPageAction );
58
60
  }
59
61
 
62
+ // Ensure "Move to trash" is always the last action.
63
+ actions = actions.sort( ( a, b ) =>
64
+ b.id === 'move-to-trash' ? -1 : 0
65
+ );
66
+
60
67
  // Filter actions based on provided context. If not provided
61
68
  // all actions are returned. We'll have a single entry for getting the actions
62
69
  // and the consumer should provide the context to filter the actions, if needed.
@@ -123,6 +130,7 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
123
130
  defaultActions,
124
131
  onActionPerformed,
125
132
  setAsHomepageAction,
126
- shouldShowSetAsHomepageAction,
133
+ setAsPostsPageAction,
134
+ shouldShowHomepageActions,
127
135
  ] );
128
136
  }
@@ -74,24 +74,26 @@ export default function PostActions( { postType, postId, onActionPerformed } ) {
74
74
 
75
75
  return (
76
76
  <>
77
- <Menu
78
- trigger={
79
- <Button
80
- size="small"
81
- icon={ moreVertical }
82
- label={ __( 'Actions' ) }
83
- disabled={ ! actions.length }
84
- accessibleWhenDisabled
85
- className="editor-all-actions-button"
86
- />
87
- }
88
- placement="bottom-end"
89
- >
90
- <ActionsDropdownMenuGroup
91
- actions={ actions }
92
- items={ itemsWithPermissions }
93
- setActiveModalAction={ setActiveModalAction }
77
+ <Menu placement="bottom-end">
78
+ <Menu.TriggerButton
79
+ render={
80
+ <Button
81
+ size="small"
82
+ icon={ moreVertical }
83
+ label={ __( 'Actions' ) }
84
+ disabled={ ! actions.length }
85
+ accessibleWhenDisabled
86
+ className="editor-all-actions-button"
87
+ />
88
+ }
94
89
  />
90
+ <Menu.Popover>
91
+ <ActionsDropdownMenuGroup
92
+ actions={ actions }
93
+ items={ itemsWithPermissions }
94
+ setActiveModalAction={ setActiveModalAction }
95
+ />
96
+ </Menu.Popover>
95
97
  </Menu>
96
98
  { !! activeModalAction && (
97
99
  <ActionModal
@@ -12,20 +12,11 @@ import {
12
12
  import { useDispatch, useSelect } from '@wordpress/data';
13
13
  import { store as coreStore } from '@wordpress/core-data';
14
14
  import { store as noticesStore } from '@wordpress/notices';
15
- import { decodeEntities } from '@wordpress/html-entities';
16
15
 
17
- const getItemTitle = ( item ) => {
18
- if ( typeof item.title === 'string' ) {
19
- return decodeEntities( item.title );
20
- }
21
- if ( item.title && 'rendered' in item.title ) {
22
- return decodeEntities( item.title.rendered );
23
- }
24
- if ( item.title && 'raw' in item.title ) {
25
- return decodeEntities( item.title.raw );
26
- }
27
- return '';
28
- };
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ import { getItemTitle } from '../../utils/get-item-title';
29
20
 
30
21
  const SetAsHomepageModal = ( { items, closeModal } ) => {
31
22
  const [ item ] = items;
@@ -47,12 +38,8 @@ const SetAsHomepageModal = ( { items, closeModal } ) => {
47
38
  };
48
39
  }
49
40
  );
50
- const currentHomePageTitle = currentHomePage
51
- ? getItemTitle( currentHomePage )
52
- : '';
53
41
 
54
- const { saveEditedEntityRecord, saveEntityRecord } =
55
- useDispatch( coreStore );
42
+ const { saveEntityRecord } = useDispatch( coreStore );
56
43
  const { createSuccessNotice, createErrorNotice } =
57
44
  useDispatch( noticesStore );
58
45
 
@@ -60,52 +47,44 @@ const SetAsHomepageModal = ( { items, closeModal } ) => {
60
47
  event.preventDefault();
61
48
 
62
49
  try {
63
- // Save new home page settings.
64
- await saveEditedEntityRecord( 'root', 'site', undefined, {
65
- page_on_front: item.id,
66
- show_on_front: 'page',
67
- } );
68
-
69
- // This second call to a save function is a workaround for a bug in
70
- // `saveEditedEntityRecord`. This forces the root site settings to be updated.
71
- // See https://github.com/WordPress/gutenberg/issues/67161.
72
50
  await saveEntityRecord( 'root', 'site', {
73
51
  page_on_front: item.id,
74
52
  show_on_front: 'page',
75
53
  } );
76
54
 
77
- createSuccessNotice( __( 'Homepage updated' ), {
55
+ createSuccessNotice( __( 'Homepage updated.' ), {
78
56
  type: 'snackbar',
79
57
  } );
80
58
  } catch ( error ) {
81
- const typedError = error;
82
59
  const errorMessage =
83
- typedError.message && typedError.code !== 'unknown_error'
84
- ? typedError.message
85
- : __( 'An error occurred while setting the homepage' );
60
+ error.message && error.code !== 'unknown_error'
61
+ ? error.message
62
+ : __( 'An error occurred while setting the homepage.' );
86
63
  createErrorNotice( errorMessage, { type: 'snackbar' } );
87
64
  } finally {
88
65
  closeModal?.();
89
66
  }
90
67
  }
91
68
 
92
- const modalWarning =
93
- 'posts' === showOnFront
94
- ? __(
95
- 'This will replace the current homepage which is set to display latest posts.'
96
- )
97
- : sprintf(
98
- // translators: %s: title of the current home page.
99
- __( 'This will replace the current homepage: "%s"' ),
100
- currentHomePageTitle
101
- );
69
+ let modalWarning = '';
70
+ if ( 'posts' === showOnFront ) {
71
+ modalWarning = __(
72
+ 'This will replace the current homepage which is set to display latest posts.'
73
+ );
74
+ } else if ( currentHomePage ) {
75
+ modalWarning = sprintf(
76
+ // translators: %s: title of the current home page.
77
+ __( 'This will replace the current homepage: "%s"' ),
78
+ getItemTitle( currentHomePage )
79
+ );
80
+ }
102
81
 
103
82
  const modalText = sprintf(
104
83
  // translators: %1$s: title of the page to be set as the homepage, %2$s: homepage replacement warning message.
105
84
  __( 'Set "%1$s" as the site homepage? %2$s' ),
106
85
  pageTitle,
107
86
  modalWarning
108
- );
87
+ ).trim();
109
88
 
110
89
  // translators: Button label to confirm setting the specified page as the homepage.
111
90
  const modalButtonLabel = __( 'Set homepage' );
@@ -143,8 +122,13 @@ const SetAsHomepageModal = ( { items, closeModal } ) => {
143
122
 
144
123
  export const useSetAsHomepageAction = () => {
145
124
  const { pageOnFront, pageForPosts } = useSelect( ( select ) => {
146
- const { getEntityRecord } = select( coreStore );
147
- const siteSettings = getEntityRecord( 'root', 'site' );
125
+ const { getEntityRecord, canUser } = select( coreStore );
126
+ const siteSettings = canUser( 'read', {
127
+ kind: 'root',
128
+ name: 'site',
129
+ } )
130
+ ? getEntityRecord( 'root', 'site' )
131
+ : undefined;
148
132
  return {
149
133
  pageOnFront: siteSettings?.page_on_front,
150
134
  pageForPosts: siteSettings?.page_for_posts,
@@ -0,0 +1,164 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { __, sprintf } from '@wordpress/i18n';
5
+ import { useMemo } from '@wordpress/element';
6
+ import {
7
+ Button,
8
+ __experimentalText as Text,
9
+ __experimentalHStack as HStack,
10
+ __experimentalVStack as VStack,
11
+ } from '@wordpress/components';
12
+ import { useDispatch, useSelect } from '@wordpress/data';
13
+ import { store as coreStore } from '@wordpress/core-data';
14
+ import { store as noticesStore } from '@wordpress/notices';
15
+
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ import { getItemTitle } from '../../utils/get-item-title';
20
+
21
+ const SetAsPostsPageModal = ( { items, closeModal } ) => {
22
+ const [ item ] = items;
23
+ const pageTitle = getItemTitle( item );
24
+ const { currentPostsPage, isPageForPostsSet, isSaving } = useSelect(
25
+ ( select ) => {
26
+ const { getEntityRecord, isSavingEntityRecord } =
27
+ select( coreStore );
28
+ const siteSettings = getEntityRecord( 'root', 'site' );
29
+ const currentPostsPageItem = getEntityRecord(
30
+ 'postType',
31
+ 'page',
32
+ siteSettings?.page_for_posts
33
+ );
34
+ return {
35
+ currentPostsPage: currentPostsPageItem,
36
+ isPageForPostsSet: siteSettings?.page_for_posts !== 0,
37
+ isSaving: isSavingEntityRecord( 'root', 'site' ),
38
+ };
39
+ }
40
+ );
41
+
42
+ const { saveEntityRecord } = useDispatch( coreStore );
43
+ const { createSuccessNotice, createErrorNotice } =
44
+ useDispatch( noticesStore );
45
+
46
+ async function onSetPageAsPostsPage( event ) {
47
+ event.preventDefault();
48
+
49
+ try {
50
+ await saveEntityRecord( 'root', 'site', {
51
+ page_for_posts: item.id,
52
+ show_on_front: 'page',
53
+ } );
54
+
55
+ createSuccessNotice( __( 'Posts page updated.' ), {
56
+ type: 'snackbar',
57
+ } );
58
+ } catch ( error ) {
59
+ const errorMessage =
60
+ error.message && error.code !== 'unknown_error'
61
+ ? error.message
62
+ : __( 'An error occurred while setting the posts page.' );
63
+ createErrorNotice( errorMessage, { type: 'snackbar' } );
64
+ } finally {
65
+ closeModal?.();
66
+ }
67
+ }
68
+
69
+ const modalWarning =
70
+ isPageForPostsSet && currentPostsPage
71
+ ? sprintf(
72
+ // translators: %s: title of the current posts page.
73
+ __( 'This will replace the current posts page: "%s"' ),
74
+ getItemTitle( currentPostsPage )
75
+ )
76
+ : __( 'This page will show the latest posts.' );
77
+
78
+ const modalText = sprintf(
79
+ // translators: %1$s: title of the page to be set as the posts page, %2$s: posts page replacement warning message.
80
+ __( 'Set "%1$s" as the posts page? %2$s' ),
81
+ pageTitle,
82
+ modalWarning
83
+ );
84
+
85
+ // translators: Button label to confirm setting the specified page as the posts page.
86
+ const modalButtonLabel = __( 'Set posts page' );
87
+
88
+ return (
89
+ <form onSubmit={ onSetPageAsPostsPage }>
90
+ <VStack spacing="5">
91
+ <Text>{ modalText }</Text>
92
+ <HStack justify="right">
93
+ <Button
94
+ __next40pxDefaultSize
95
+ variant="tertiary"
96
+ onClick={ () => {
97
+ closeModal?.();
98
+ } }
99
+ disabled={ isSaving }
100
+ accessibleWhenDisabled
101
+ >
102
+ { __( 'Cancel' ) }
103
+ </Button>
104
+ <Button
105
+ __next40pxDefaultSize
106
+ variant="primary"
107
+ type="submit"
108
+ disabled={ isSaving }
109
+ accessibleWhenDisabled
110
+ >
111
+ { modalButtonLabel }
112
+ </Button>
113
+ </HStack>
114
+ </VStack>
115
+ </form>
116
+ );
117
+ };
118
+
119
+ export const useSetAsPostsPageAction = () => {
120
+ const { pageOnFront, pageForPosts } = useSelect( ( select ) => {
121
+ const { getEntityRecord, canUser } = select( coreStore );
122
+ const siteSettings = canUser( 'read', {
123
+ kind: 'root',
124
+ name: 'site',
125
+ } )
126
+ ? getEntityRecord( 'root', 'site' )
127
+ : undefined;
128
+
129
+ return {
130
+ pageOnFront: siteSettings?.page_on_front,
131
+ pageForPosts: siteSettings?.page_for_posts,
132
+ };
133
+ } );
134
+
135
+ return useMemo(
136
+ () => ( {
137
+ id: 'set-as-posts-page',
138
+ label: __( 'Set as posts page' ),
139
+ isEligible( post ) {
140
+ if ( post.status !== 'publish' ) {
141
+ return false;
142
+ }
143
+
144
+ if ( post.type !== 'page' ) {
145
+ return false;
146
+ }
147
+
148
+ // Don't show the action if the page is already set as the homepage.
149
+ if ( pageOnFront === post.id ) {
150
+ return false;
151
+ }
152
+
153
+ // Don't show the action if the page is already set as the page for posts.
154
+ if ( pageForPosts === post.id ) {
155
+ return false;
156
+ }
157
+
158
+ return true;
159
+ },
160
+ RenderModal: SetAsPostsPageModal,
161
+ } ),
162
+ [ pageForPosts, pageOnFront ]
163
+ );
164
+ };
@@ -6,12 +6,13 @@ import {
6
6
  __experimentalHStack as HStack,
7
7
  __experimentalVStack as VStack,
8
8
  __experimentalText as Text,
9
+ privateApis as componentsPrivateApis,
9
10
  } from '@wordpress/components';
10
11
  import { store as coreStore } from '@wordpress/core-data';
11
12
  import { useSelect } from '@wordpress/data';
12
13
  import { useMemo } from '@wordpress/element';
13
14
  import { __, sprintf } from '@wordpress/i18n';
14
- import { decodeEntities } from '@wordpress/html-entities';
15
+ import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
15
16
 
16
17
  /**
17
18
  * Internal dependencies
@@ -25,6 +26,7 @@ import { unlock } from '../../lock-unlock';
25
26
  import PostActions from '../post-actions';
26
27
  import usePageTypeBadge from '../../utils/pageTypeBadge';
27
28
  import { getTemplateInfo } from '../../utils/get-template-info';
29
+ const { Badge } = unlock( componentsPrivateApis );
28
30
 
29
31
  /**
30
32
  * Renders a title of the post type and the available quick actions available within a 3-dot dropdown.
@@ -92,7 +94,7 @@ export default function PostCardPanel( {
92
94
  labels?.name
93
95
  );
94
96
  } else if ( postTitle ) {
95
- title = decodeEntities( postTitle );
97
+ title = stripHTML( postTitle );
96
98
  }
97
99
 
98
100
  return (
@@ -109,11 +111,11 @@ export default function PostCardPanel( {
109
111
  className="editor-post-card-panel__title"
110
112
  as="h2"
111
113
  >
112
- { title }
114
+ <span className="editor-post-card-panel__title-name">
115
+ { title }
116
+ </span>
113
117
  { pageTypeBadge && postIds.length === 1 && (
114
- <span className="editor-post-card-panel__title-badge">
115
- { pageTypeBadge }
116
- </span>
118
+ <Badge>{ pageTypeBadge }</Badge>
117
119
  ) }
118
120
  </Text>
119
121
  <PostActions
@@ -9,7 +9,6 @@
9
9
  &.editor-post-card-panel__title {
10
10
  @include heading-medium();
11
11
  margin: 0;
12
- padding: 2px 0;
13
12
  display: flex;
14
13
  align-items: center;
15
14
  flex-wrap: wrap;
@@ -34,19 +33,11 @@
34
33
  margin-bottom: $grid-unit-10;
35
34
  }
36
35
 
36
+ .editor-post-card-panel__title-name {
37
+ padding: 2px 0;
38
+ }
39
+
37
40
  .editor-post-card-panel__description {
38
41
  color: $gray-700;
39
42
  }
40
43
  }
41
-
42
- .editor-post-card-panel__title-badge {
43
- background: $gray-100;
44
- color: $gray-800;
45
- padding: 0 $grid-unit-05;
46
- border-radius: $radius-small;
47
- font-size: 12px;
48
- font-weight: 400;
49
- flex-shrink: 0;
50
- line-height: $grid-unit-05 * 5;
51
- display: inline-block;
52
- }
@@ -9,7 +9,7 @@ import {
9
9
  __unstableAnimatePresence as AnimatePresence,
10
10
  } from '@wordpress/components';
11
11
  import { useSelect, useDispatch } from '@wordpress/data';
12
- import { __ } from '@wordpress/i18n';
12
+ import { __, _x } from '@wordpress/i18n';
13
13
  import { store as blockEditorStore } from '@wordpress/block-editor';
14
14
  import { useState } from '@wordpress/element';
15
15
  import { isBlobURL } from '@wordpress/blob';
@@ -260,7 +260,7 @@ export default function MaybeUploadMediaPanel() {
260
260
  variant="primary"
261
261
  onClick={ uploadImages }
262
262
  >
263
- { __( 'Upload' ) }
263
+ { _x( 'Upload', 'verb' ) }
264
264
  </Button>
265
265
  ) }
266
266
  </div>
@@ -26,7 +26,6 @@ import PageAttributesCheck from '../page-attributes/check';
26
26
  import PostTypeSupportCheck from '../post-type-support-check';
27
27
  import { store as editorStore } from '../../store';
28
28
  import { unlock } from '../../lock-unlock';
29
- import { useStartPatterns } from '../start-page-options';
30
29
 
31
30
  const {
32
31
  PreferencesModal,
@@ -73,7 +72,6 @@ function PreferencesModalContents( { extraSections = {} } ) {
73
72
  const { setIsListViewOpened, setIsInserterOpened } =
74
73
  useDispatch( editorStore );
75
74
  const { set: setPreference } = useDispatch( preferencesStore );
76
- const hasStarterPatterns = !! useStartPatterns().length;
77
75
 
78
76
  const sections = useMemo(
79
77
  () =>
@@ -114,16 +112,14 @@ function PreferencesModalContents( { extraSections = {} } ) {
114
112
  'Allow right-click contextual menus'
115
113
  ) }
116
114
  />
117
- { hasStarterPatterns && (
118
- <PreferenceToggleControl
119
- scope="core"
120
- featureName="enableChoosePatternModal"
121
- help={ __(
122
- 'Shows starter patterns when creating a new page.'
123
- ) }
124
- label={ __( 'Show starter patterns' ) }
125
- />
126
- ) }
115
+ <PreferenceToggleControl
116
+ scope="core"
117
+ featureName="enableChoosePatternModal"
118
+ help={ __(
119
+ 'Shows starter patterns when creating a new page.'
120
+ ) }
121
+ label={ __( 'Show starter patterns' ) }
122
+ />
127
123
  </PreferencesModalSection>
128
124
  <PreferencesModalSection
129
125
  title={ __( 'Document settings' ) }
@@ -341,7 +337,6 @@ function PreferencesModalContents( { extraSections = {} } ) {
341
337
  setIsListViewOpened,
342
338
  setPreference,
343
339
  isLargeViewport,
344
- hasStarterPatterns,
345
340
  ]
346
341
  );
347
342
 
@@ -190,7 +190,6 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) {
190
190
  ) }
191
191
  <ActionItem.Slot
192
192
  name="core/plugin-preview-menu"
193
- as={ MenuGroup }
194
193
  fillProps={ { onClick: onClose } }
195
194
  />
196
195
  </>