@wordpress/editor 13.31.0 → 13.32.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 (157) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +857 -0
  3. package/build/components/block-settings-menu/plugin-block-settings-menu-item.js +107 -0
  4. package/build/components/block-settings-menu/plugin-block-settings-menu-item.js.map +1 -0
  5. package/build/components/commands/index.js +1 -1
  6. package/build/components/commands/index.js.map +1 -1
  7. package/build/components/deprecated.js +158 -0
  8. package/build/components/deprecated.js.map +1 -1
  9. package/build/components/document-bar/index.js +5 -8
  10. package/build/components/document-bar/index.js.map +1 -1
  11. package/build/components/editor-canvas/edit-template-blocks-notification.js +2 -39
  12. package/build/components/editor-canvas/edit-template-blocks-notification.js.map +1 -1
  13. package/build/components/editor-canvas/index.js +3 -0
  14. package/build/components/editor-canvas/index.js.map +1 -1
  15. package/build/components/entities-saved-states/index.js +11 -85
  16. package/build/components/entities-saved-states/index.js.map +1 -1
  17. package/build/components/index.js +24 -0
  18. package/build/components/index.js.map +1 -1
  19. package/build/components/inserter-sidebar/index.js +5 -1
  20. package/build/components/inserter-sidebar/index.js.map +1 -1
  21. package/build/components/list-view-sidebar/index.js +2 -1
  22. package/build/components/list-view-sidebar/index.js.map +1 -1
  23. package/build/components/pattern-overrides-panel/index.js +30 -0
  24. package/build/components/pattern-overrides-panel/index.js.map +1 -0
  25. package/build/components/plugin-post-publish-panel/index.js +68 -0
  26. package/build/components/plugin-post-publish-panel/index.js.map +1 -0
  27. package/build/components/plugin-pre-publish-panel/index.js +71 -0
  28. package/build/components/plugin-pre-publish-panel/index.js.map +1 -0
  29. package/build/components/post-actions/actions.js +455 -0
  30. package/build/components/post-actions/actions.js.map +1 -0
  31. package/build/components/post-card-panel/index.js +93 -0
  32. package/build/components/post-card-panel/index.js.map +1 -0
  33. package/build/components/post-title/index.native.js +1 -1
  34. package/build/components/post-title/index.native.js.map +1 -1
  35. package/build/components/provider/disable-non-page-content-blocks.js +36 -20
  36. package/build/components/provider/disable-non-page-content-blocks.js.map +1 -1
  37. package/build/components/provider/use-block-editor-settings.js +8 -9
  38. package/build/components/provider/use-block-editor-settings.js.map +1 -1
  39. package/build/components/template-areas/index.js +70 -0
  40. package/build/components/template-areas/index.js.map +1 -0
  41. package/build/hooks/use-select-nearest-editable-block.js +87 -0
  42. package/build/hooks/use-select-nearest-editable-block.js.map +1 -0
  43. package/build/private-apis.js +6 -0
  44. package/build/private-apis.js.map +1 -1
  45. package/build/store/actions.js +46 -6
  46. package/build/store/actions.js.map +1 -1
  47. package/build/store/constants.js +3 -1
  48. package/build/store/constants.js.map +1 -1
  49. package/build/store/private-actions.js +80 -1
  50. package/build/store/private-actions.js.map +1 -1
  51. package/build/store/private-selectors.js +56 -3
  52. package/build/store/private-selectors.js.map +1 -1
  53. package/build/store/reducer.js +14 -1
  54. package/build/store/reducer.js.map +1 -1
  55. package/build/store/selectors.js +21 -11
  56. package/build/store/selectors.js.map +1 -1
  57. package/build/store/utils/get-filtered-template-parts.js +71 -0
  58. package/build/store/utils/get-filtered-template-parts.js.map +1 -0
  59. package/build-module/components/block-settings-menu/plugin-block-settings-menu-item.js +100 -0
  60. package/build-module/components/block-settings-menu/plugin-block-settings-menu-item.js.map +1 -0
  61. package/build-module/components/commands/index.js +1 -1
  62. package/build-module/components/commands/index.js.map +1 -1
  63. package/build-module/components/deprecated.js +159 -0
  64. package/build-module/components/deprecated.js.map +1 -1
  65. package/build-module/components/document-bar/index.js +6 -9
  66. package/build-module/components/document-bar/index.js.map +1 -1
  67. package/build-module/components/editor-canvas/edit-template-blocks-notification.js +4 -41
  68. package/build-module/components/editor-canvas/edit-template-blocks-notification.js.map +1 -1
  69. package/build-module/components/editor-canvas/index.js +3 -0
  70. package/build-module/components/editor-canvas/index.js.map +1 -1
  71. package/build-module/components/entities-saved-states/index.js +11 -85
  72. package/build-module/components/entities-saved-states/index.js.map +1 -1
  73. package/build-module/components/index.js +3 -0
  74. package/build-module/components/index.js.map +1 -1
  75. package/build-module/components/inserter-sidebar/index.js +5 -1
  76. package/build-module/components/inserter-sidebar/index.js.map +1 -1
  77. package/build-module/components/list-view-sidebar/index.js +2 -1
  78. package/build-module/components/list-view-sidebar/index.js.map +1 -1
  79. package/build-module/components/pattern-overrides-panel/index.js +23 -0
  80. package/build-module/components/pattern-overrides-panel/index.js.map +1 -0
  81. package/build-module/components/plugin-post-publish-panel/index.js +61 -0
  82. package/build-module/components/plugin-post-publish-panel/index.js.map +1 -0
  83. package/build-module/components/plugin-pre-publish-panel/index.js +64 -0
  84. package/build-module/components/plugin-pre-publish-panel/index.js.map +1 -0
  85. package/build-module/components/post-actions/actions.js +444 -0
  86. package/build-module/components/post-actions/actions.js.map +1 -0
  87. package/build-module/components/post-card-panel/index.js +85 -0
  88. package/build-module/components/post-card-panel/index.js.map +1 -0
  89. package/build-module/components/post-title/index.native.js +1 -1
  90. package/build-module/components/post-title/index.native.js.map +1 -1
  91. package/build-module/components/provider/disable-non-page-content-blocks.js +36 -20
  92. package/build-module/components/provider/disable-non-page-content-blocks.js.map +1 -1
  93. package/build-module/components/provider/use-block-editor-settings.js +9 -10
  94. package/build-module/components/provider/use-block-editor-settings.js.map +1 -1
  95. package/build-module/components/template-areas/index.js +63 -0
  96. package/build-module/components/template-areas/index.js.map +1 -0
  97. package/build-module/hooks/use-select-nearest-editable-block.js +80 -0
  98. package/build-module/hooks/use-select-nearest-editable-block.js.map +1 -0
  99. package/build-module/private-apis.js +6 -0
  100. package/build-module/private-apis.js.map +1 -1
  101. package/build-module/store/actions.js +37 -3
  102. package/build-module/store/actions.js.map +1 -1
  103. package/build-module/store/constants.js +2 -0
  104. package/build-module/store/constants.js.map +1 -1
  105. package/build-module/store/private-actions.js +78 -0
  106. package/build-module/store/private-actions.js.map +1 -1
  107. package/build-module/store/private-selectors.js +54 -3
  108. package/build-module/store/private-selectors.js.map +1 -1
  109. package/build-module/store/reducer.js +13 -1
  110. package/build-module/store/reducer.js.map +1 -1
  111. package/build-module/store/selectors.js +19 -10
  112. package/build-module/store/selectors.js.map +1 -1
  113. package/build-module/store/utils/get-filtered-template-parts.js +64 -0
  114. package/build-module/store/utils/get-filtered-template-parts.js.map +1 -0
  115. package/build-style/style-rtl.css +70 -27
  116. package/build-style/style.css +70 -27
  117. package/package.json +35 -35
  118. package/src/components/block-settings-menu/plugin-block-settings-menu-item.js +108 -0
  119. package/src/components/commands/index.js +1 -1
  120. package/src/components/deprecated.js +157 -0
  121. package/src/components/document-bar/index.js +9 -15
  122. package/src/components/document-bar/style.scss +9 -12
  123. package/src/components/document-tools/style.scss +4 -11
  124. package/src/components/editor-canvas/edit-template-blocks-notification.js +6 -56
  125. package/src/components/editor-canvas/index.js +4 -0
  126. package/src/components/entities-saved-states/index.js +12 -113
  127. package/src/components/index.js +3 -0
  128. package/src/components/inserter-sidebar/index.js +7 -1
  129. package/src/components/list-view-sidebar/index.js +1 -0
  130. package/src/components/list-view-sidebar/style.scss +1 -1
  131. package/src/components/pattern-overrides-panel/index.js +26 -0
  132. package/src/components/plugin-post-publish-panel/index.js +64 -0
  133. package/src/components/plugin-post-publish-panel/test/__snapshots__/index.js.snap +39 -0
  134. package/src/components/plugin-post-publish-panel/test/index.js +33 -0
  135. package/src/components/plugin-pre-publish-panel/index.js +67 -0
  136. package/src/components/plugin-pre-publish-panel/test/index.js +33 -0
  137. package/src/components/post-actions/actions.js +582 -0
  138. package/src/components/post-card-panel/index.js +108 -0
  139. package/src/components/post-card-panel/style.scss +32 -0
  140. package/src/components/post-featured-image/style.scss +3 -2
  141. package/src/components/post-title/index.native.js +1 -1
  142. package/src/components/provider/disable-non-page-content-blocks.js +40 -20
  143. package/src/components/provider/test/disable-non-page-content-blocks.js +35 -14
  144. package/src/components/provider/use-block-editor-settings.js +11 -11
  145. package/src/components/template-areas/index.js +85 -0
  146. package/src/components/template-areas/style.scss +23 -0
  147. package/src/hooks/use-select-nearest-editable-block.js +95 -0
  148. package/src/private-apis.js +6 -0
  149. package/src/store/actions.js +37 -3
  150. package/src/store/constants.js +2 -0
  151. package/src/store/private-actions.js +111 -0
  152. package/src/store/private-selectors.js +105 -17
  153. package/src/store/reducer.js +13 -0
  154. package/src/store/selectors.js +50 -40
  155. package/src/store/utils/get-filtered-template-parts.js +69 -0
  156. package/src/store/utils/test/get-filtered-template-parts.js +189 -0
  157. package/src/style.scss +2 -0
@@ -12,7 +12,6 @@
12
12
 
13
13
  .editor-post-featured-image__container {
14
14
  position: relative;
15
- aspect-ratio: 2/1;
16
15
 
17
16
  &:hover,
18
17
  &:focus,
@@ -31,8 +30,9 @@
31
30
  @include reduce-motion("transition");
32
31
  box-shadow: 0 0 0 0 var(--wp-admin-theme-color);
33
32
  overflow: hidden; // Ensure the focus style properly encapsulates the image.
34
- outline: $border-width solid rgba(0, 0, 0, 0.1);
35
33
  outline-offset: -#{$border-width};
34
+ min-height: $grid-unit-50 * 2;
35
+ margin-bottom: $grid-unit-20;
36
36
 
37
37
  display: flex;
38
38
  justify-content: center;
@@ -40,6 +40,7 @@
40
40
 
41
41
  .editor-post-featured-image__preview {
42
42
  height: auto;
43
+ outline: $border-width solid rgba($black, 0.1);
43
44
 
44
45
  .editor-post-featured-image__preview-image {
45
46
  object-fit: cover;
@@ -164,7 +164,7 @@ class PostTitle extends Component {
164
164
  accessibilityHint={ __( 'Updates the title.' ) }
165
165
  >
166
166
  <RichText.Raw
167
- setRef={ this.setRef }
167
+ ref={ this.setRef }
168
168
  accessibilityLabel={ this.getTitle( title, postType ) }
169
169
  tagName={ 'p' }
170
170
  tagsToEliminate={ [ 'strong' ] }
@@ -4,50 +4,70 @@
4
4
  import { useSelect, useDispatch } from '@wordpress/data';
5
5
  import { store as blockEditorStore } from '@wordpress/block-editor';
6
6
  import { useEffect } from '@wordpress/element';
7
+ import { applyFilters } from '@wordpress/hooks';
7
8
 
8
- const PAGE_CONTENT_BLOCKS = [
9
+ const CONTENT_ONLY_BLOCKS = applyFilters( 'editor.postContentBlockTypes', [
9
10
  'core/post-title',
10
11
  'core/post-featured-image',
11
12
  'core/post-content',
12
- ];
13
+ 'core/template-part',
14
+ ] );
13
15
 
14
- function useDisableNonPageContentBlocks() {
15
- const contentIds = useSelect( ( select ) => {
16
+ /**
17
+ * Component that when rendered, makes it so that the site editor allows only
18
+ * page content to be edited.
19
+ */
20
+ export default function DisableNonPageContentBlocks() {
21
+ const contentOnlyIds = useSelect( ( select ) => {
16
22
  const { getBlocksByName, getBlockParents, getBlockName } =
17
23
  select( blockEditorStore );
18
- return getBlocksByName( PAGE_CONTENT_BLOCKS ).filter( ( clientId ) =>
24
+ return getBlocksByName( CONTENT_ONLY_BLOCKS ).filter( ( clientId ) =>
19
25
  getBlockParents( clientId ).every( ( parentClientId ) => {
20
26
  const parentBlockName = getBlockName( parentClientId );
21
27
  return (
28
+ // Ignore descendents of the query block.
22
29
  parentBlockName !== 'core/query' &&
23
- ! PAGE_CONTENT_BLOCKS.includes( parentBlockName )
30
+ // Enable only the top-most block.
31
+ ! CONTENT_ONLY_BLOCKS.includes( parentBlockName )
24
32
  );
25
33
  } )
26
34
  );
27
35
  }, [] );
28
36
 
37
+ const disabledIds = useSelect( ( select ) => {
38
+ const { getBlocksByName, getBlockOrder } = select( blockEditorStore );
39
+ return getBlocksByName( [ 'core/template-part' ] ).flatMap(
40
+ ( clientId ) => getBlockOrder( clientId )
41
+ );
42
+ }, [] );
43
+
29
44
  const { setBlockEditingMode, unsetBlockEditingMode } =
30
45
  useDispatch( blockEditorStore );
31
46
 
32
47
  useEffect( () => {
33
- setBlockEditingMode( '', 'disabled' ); // Disable editing at the root level.
34
-
35
- for ( const contentId of contentIds ) {
36
- setBlockEditingMode( contentId, 'contentOnly' ); // Re-enable each content block.
48
+ setBlockEditingMode( '', 'disabled' );
49
+ for ( const clientId of contentOnlyIds ) {
50
+ setBlockEditingMode( clientId, 'contentOnly' );
37
51
  }
52
+ for ( const clientId of disabledIds ) {
53
+ setBlockEditingMode( clientId, 'disabled' );
54
+ }
55
+
38
56
  return () => {
39
57
  unsetBlockEditingMode( '' );
40
- for ( const contentId of contentIds ) {
41
- unsetBlockEditingMode( contentId );
58
+ for ( const clientId of contentOnlyIds ) {
59
+ unsetBlockEditingMode( clientId );
60
+ }
61
+ for ( const clientId of disabledIds ) {
62
+ unsetBlockEditingMode( clientId );
42
63
  }
43
64
  };
44
- }, [ contentIds, setBlockEditingMode, unsetBlockEditingMode ] );
45
- }
65
+ }, [
66
+ contentOnlyIds,
67
+ disabledIds,
68
+ setBlockEditingMode,
69
+ unsetBlockEditingMode,
70
+ ] );
46
71
 
47
- /**
48
- * Component that when rendered, makes it so that the site editor allows only
49
- * page content to be edited.
50
- */
51
- export default function DisableNonPageContentBlocks() {
52
- useDisableNonPageContentBlocks();
72
+ return null;
53
73
  }
@@ -55,6 +55,13 @@ describe( 'DisableNonPageContentBlocks', () => {
55
55
  getBlockName( state, clientId ) {
56
56
  return testBlocks[ clientId ];
57
57
  },
58
+ getBlockOrder( state, rootClientId ) {
59
+ return Object.keys( testBlocks ).filter(
60
+ ( clientId ) =>
61
+ clientId.startsWith( rootClientId ) &&
62
+ clientId !== rootClientId
63
+ );
64
+ },
58
65
  },
59
66
  actions: {
60
67
  setBlockEditingMode,
@@ -69,22 +76,36 @@ describe( 'DisableNonPageContentBlocks', () => {
69
76
  </RegistryProvider>
70
77
  );
71
78
 
72
- expect( setBlockEditingMode.mock.calls ).toEqual( [
73
- [ '', 'disabled' ], // root
74
- [ '10', 'contentOnly' ], // post-title
75
- [ '11', 'contentOnly' ], // post-featured-image
76
- [ '12', 'contentOnly' ], // post-content
77
- // NOT the post-featured-image nested within post-content
78
- // NOT any of the content blocks within query
79
- ] );
79
+ expect( setBlockEditingMode.mock.calls ).toEqual(
80
+ expect.arrayContaining( [
81
+ [ '', 'disabled' ], // root
82
+ [ '0', 'contentOnly' ], // core/template-part
83
+ [ '00', 'disabled' ], // core/site-title
84
+ [ '01', 'disabled' ], // core/navigation
85
+ [ '10', 'contentOnly' ], // post-title
86
+ [ '11', 'contentOnly' ], // post-featured-image
87
+ [ '12', 'contentOnly' ], // post-content
88
+ [ '3', 'contentOnly' ], // core/template-part
89
+ [ '30', 'disabled' ], // core/paragraph
90
+ // NOT the post-featured-image nested within post-content
91
+ // NOT any of the content blocks within query
92
+ ] )
93
+ );
80
94
 
81
95
  unmount();
82
96
 
83
- expect( unsetBlockEditingMode.mock.calls ).toEqual( [
84
- [ '' ], // root
85
- [ '10' ], // post-title
86
- [ '11' ], // post-featured-image
87
- [ '12' ], // post-content
88
- ] );
97
+ expect( unsetBlockEditingMode.mock.calls ).toEqual(
98
+ expect.arrayContaining( [
99
+ [ '' ], // root
100
+ [ '0' ], // core/template-part
101
+ [ '00' ], // core/site-title
102
+ [ '01' ], // core/navigation
103
+ [ '10' ], // post-title
104
+ [ '11' ], // post-featured-image
105
+ [ '12' ], // post-content
106
+ [ '3' ], // core/template-part
107
+ [ '30' ], // core/paragraph
108
+ ] )
109
+ );
89
110
  } );
90
111
  } );
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { Platform, useMemo, useCallback } from '@wordpress/element';
4
+ import { useMemo, useCallback } from '@wordpress/element';
5
5
  import { useDispatch, useSelect } from '@wordpress/data';
6
6
  import {
7
7
  store as coreStore,
@@ -24,6 +24,14 @@ import { unlock } from '../../lock-unlock';
24
24
 
25
25
  const EMPTY_BLOCKS_LIST = [];
26
26
 
27
+ function __experimentalReusableBlocksSelect( select ) {
28
+ return (
29
+ select( coreStore ).getEntityRecords( 'postType', 'wp_block', {
30
+ per_page: -1,
31
+ } ) ?? EMPTY_BLOCKS_LIST
32
+ );
33
+ }
34
+
27
35
  const BLOCK_EDITOR_SETTINGS = [
28
36
  '__experimentalBlockDirectory',
29
37
  '__experimentalDiscussionSettings',
@@ -92,7 +100,6 @@ function useBlockEditorSettings( settings, postType, postId ) {
92
100
  hasFixedToolbar,
93
101
  isDistractionFree,
94
102
  keepCaretInsideBlock,
95
- reusableBlocks,
96
103
  hasUploadPermissions,
97
104
  hiddenBlockTypes,
98
105
  canUseUnfilteredHTML,
@@ -103,13 +110,11 @@ function useBlockEditorSettings( settings, postType, postId ) {
103
110
  restBlockPatternCategories,
104
111
  } = useSelect(
105
112
  ( select ) => {
106
- const isWeb = Platform.OS === 'web';
107
113
  const {
108
114
  canUser,
109
115
  getRawEntityRecord,
110
116
  getEntityRecord,
111
117
  getUserPatternCategories,
112
- getEntityRecords,
113
118
  getBlockPatternCategories,
114
119
  } = select( coreStore );
115
120
  const { get } = select( preferencesStore );
@@ -135,11 +140,6 @@ function useBlockEditorSettings( settings, postType, postId ) {
135
140
  hiddenBlockTypes: get( 'core', 'hiddenBlockTypes' ),
136
141
  isDistractionFree: get( 'core', 'distractionFree' ),
137
142
  keepCaretInsideBlock: get( 'core', 'keepCaretInsideBlock' ),
138
- reusableBlocks: isWeb
139
- ? getEntityRecords( 'postType', 'wp_block', {
140
- per_page: -1,
141
- } )
142
- : EMPTY_BLOCKS_LIST, // Reusable blocks are fetched in the native version of this hook.
143
143
  hasUploadPermissions: canUser( 'create', 'media' ) ?? true,
144
144
  userCanCreatePages: canUser( 'create', 'pages' ),
145
145
  pageOnFront: siteSettings?.page_on_front,
@@ -249,7 +249,8 @@ function useBlockEditorSettings( settings, postType, postId ) {
249
249
  unlock( select( coreStore ) ).getBlockPatternsForPostType(
250
250
  postType
251
251
  ),
252
- __experimentalReusableBlocks: reusableBlocks,
252
+ [ unlock( privateApis ).reusableBlocksSelectKey ]:
253
+ __experimentalReusableBlocksSelect,
253
254
  __experimentalBlockPatternCategories: blockPatternCategories,
254
255
  __experimentalUserPatternCategories: userPatternCategories,
255
256
  __experimentalFetchLinkSuggestions: ( search, searchOptions ) =>
@@ -288,7 +289,6 @@ function useBlockEditorSettings( settings, postType, postId ) {
288
289
  keepCaretInsideBlock,
289
290
  settings,
290
291
  hasUploadPermissions,
291
- reusableBlocks,
292
292
  userPatternCategories,
293
293
  blockPatterns,
294
294
  blockPatternCategories,
@@ -0,0 +1,85 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useSelect, useDispatch } from '@wordpress/data';
5
+ import {
6
+ Button,
7
+ __experimentalHeading as Heading,
8
+ } from '@wordpress/components';
9
+
10
+ import { store as blockEditorStore } from '@wordpress/block-editor';
11
+ import { __ } from '@wordpress/i18n';
12
+
13
+ /**
14
+ * Internal dependencies
15
+ */
16
+ import { store as editorStore } from '../../store';
17
+ import { unlock } from '../../lock-unlock';
18
+
19
+ function TemplateAreaItem( { area, clientId } ) {
20
+ const { selectBlock, toggleBlockHighlight } =
21
+ useDispatch( blockEditorStore );
22
+ const templatePartArea = useSelect(
23
+ ( select ) => {
24
+ const defaultAreas =
25
+ select(
26
+ editorStore
27
+ ).__experimentalGetDefaultTemplatePartAreas();
28
+
29
+ return defaultAreas.find(
30
+ ( defaultArea ) => defaultArea.area === area
31
+ );
32
+ },
33
+ [ area ]
34
+ );
35
+
36
+ const highlightBlock = () => toggleBlockHighlight( clientId, true );
37
+ const cancelHighlightBlock = () => toggleBlockHighlight( clientId, false );
38
+
39
+ return (
40
+ <Button
41
+ className="editor-template-areas__item"
42
+ icon={ templatePartArea?.icon }
43
+ onMouseOver={ highlightBlock }
44
+ onMouseLeave={ cancelHighlightBlock }
45
+ onFocus={ highlightBlock }
46
+ onBlur={ cancelHighlightBlock }
47
+ onClick={ () => {
48
+ selectBlock( clientId );
49
+ } }
50
+ >
51
+ { templatePartArea?.label }
52
+ </Button>
53
+ );
54
+ }
55
+
56
+ export default function TemplateAreas() {
57
+ const templateParts = useSelect(
58
+ ( select ) =>
59
+ unlock( select( editorStore ) ).getCurrentTemplateTemplateParts(),
60
+ []
61
+ );
62
+
63
+ if ( ! templateParts.length ) {
64
+ return null;
65
+ }
66
+
67
+ return (
68
+ <section className="editor-template-areas">
69
+ <Heading level={ 3 } className="editor-template-areas__title">
70
+ { __( 'Areas' ) }
71
+ </Heading>
72
+
73
+ <ul className="editor-template-areas__list">
74
+ { templateParts.map( ( { templatePart, block } ) => (
75
+ <li key={ block.clientId }>
76
+ <TemplateAreaItem
77
+ area={ templatePart.area }
78
+ clientId={ block.clientId }
79
+ />
80
+ </li>
81
+ ) ) }
82
+ </ul>
83
+ </section>
84
+ );
85
+ }
@@ -0,0 +1,23 @@
1
+ .editor-template-areas {
2
+ margin-top: $grid-unit-20;
3
+ &__list {
4
+ margin: 0;
5
+ > li {
6
+ margin: 0;
7
+ }
8
+ }
9
+
10
+ &__item {
11
+ width: 100%;
12
+
13
+ // Override the default padding.
14
+ &.components-button.has-icon {
15
+ padding: 0;
16
+ }
17
+ }
18
+ }
19
+
20
+ h3.components-heading.editor-template-areas__title {
21
+ font-weight: 500;
22
+ margin: 0 0 $grid-unit-10;
23
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useRefEffect } from '@wordpress/compose';
5
+ import { useSelect, useDispatch } from '@wordpress/data';
6
+ import { store as blockEditorStore } from '@wordpress/block-editor';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import { unlock } from '../lock-unlock';
12
+
13
+ const DISTANCE_THRESHOLD = 500;
14
+
15
+ function clamp( value, min, max ) {
16
+ return Math.min( Math.max( value, min ), max );
17
+ }
18
+
19
+ function distanceFromRect( x, y, rect ) {
20
+ const dx = x - clamp( x, rect.left, rect.right );
21
+ const dy = y - clamp( y, rect.top, rect.bottom );
22
+ return Math.sqrt( dx * dx + dy * dy );
23
+ }
24
+
25
+ export default function useSelectNearestEditableBlock( {
26
+ isEnabled = true,
27
+ } = {} ) {
28
+ const { getEnabledClientIdsTree, getBlockName, getBlockOrder } = unlock(
29
+ useSelect( blockEditorStore )
30
+ );
31
+ const { selectBlock } = useDispatch( blockEditorStore );
32
+
33
+ return useRefEffect(
34
+ ( element ) => {
35
+ if ( ! isEnabled ) {
36
+ return;
37
+ }
38
+
39
+ const selectNearestEditableBlock = ( x, y ) => {
40
+ const editableBlockClientIds =
41
+ getEnabledClientIdsTree().flatMap( ( { clientId } ) => {
42
+ const blockName = getBlockName( clientId );
43
+ if ( blockName === 'core/template-part' ) {
44
+ return [];
45
+ }
46
+ if ( blockName === 'core/post-content' ) {
47
+ const innerBlocks = getBlockOrder( clientId );
48
+ if ( innerBlocks.length ) {
49
+ return innerBlocks;
50
+ }
51
+ }
52
+ return [ clientId ];
53
+ } );
54
+
55
+ let nearestDistance = Infinity,
56
+ nearestClientId = null;
57
+
58
+ for ( const clientId of editableBlockClientIds ) {
59
+ const block = element.querySelector(
60
+ `[data-block="${ clientId }"]`
61
+ );
62
+ if ( ! block ) {
63
+ continue;
64
+ }
65
+ const rect = block.getBoundingClientRect();
66
+ const distance = distanceFromRect( x, y, rect );
67
+ if (
68
+ distance < nearestDistance &&
69
+ distance < DISTANCE_THRESHOLD
70
+ ) {
71
+ nearestDistance = distance;
72
+ nearestClientId = clientId;
73
+ }
74
+ }
75
+
76
+ if ( nearestClientId ) {
77
+ selectBlock( nearestClientId );
78
+ }
79
+ };
80
+
81
+ const handleClick = ( event ) => {
82
+ const shouldSelect =
83
+ event.target === element ||
84
+ event.target.classList.contains( 'is-root-container' );
85
+ if ( shouldSelect ) {
86
+ selectNearestEditableBlock( event.clientX, event.clientY );
87
+ }
88
+ };
89
+
90
+ element.addEventListener( 'click', handleClick );
91
+ return () => element.removeEventListener( 'click', handleClick );
92
+ },
93
+ [ isEnabled ]
94
+ );
95
+ }
@@ -10,11 +10,14 @@ import DocumentTools from './components/document-tools';
10
10
  import InserterSidebar from './components/inserter-sidebar';
11
11
  import ListViewSidebar from './components/list-view-sidebar';
12
12
  import ModeSwitcher from './components/mode-switcher';
13
+ import PatternOverridesPanel from './components/pattern-overrides-panel';
13
14
  import PluginPostExcerpt from './components/post-excerpt/plugin';
14
15
  import PostPanelRow from './components/post-panel-row';
15
16
  import PostViewLink from './components/post-view-link';
16
17
  import PreviewDropdown from './components/preview-dropdown';
17
18
  import PreferencesModal from './components/preferences-modal';
19
+ import { usePostActions } from './components/post-actions/actions';
20
+ import PostCardPanel from './components/post-card-panel';
18
21
 
19
22
  export const privateApis = {};
20
23
  lock( privateApis, {
@@ -25,11 +28,14 @@ lock( privateApis, {
25
28
  InserterSidebar,
26
29
  ListViewSidebar,
27
30
  ModeSwitcher,
31
+ PatternOverridesPanel,
28
32
  PluginPostExcerpt,
29
33
  PostPanelRow,
30
34
  PostViewLink,
31
35
  PreviewDropdown,
32
36
  PreferencesModal,
37
+ usePostActions,
38
+ PostCardPanel,
33
39
 
34
40
  // This is a temporary private API while we're updating the site editor to use EditorProvider.
35
41
  useBlockEditorSettings,
@@ -406,7 +406,7 @@ export const enablePublishSidebar =
406
406
  ( { registry } ) => {
407
407
  registry
408
408
  .dispatch( preferencesStore )
409
- .set( 'core/edit-post', 'isPublishSidebarEnabled', true );
409
+ .set( 'core', 'isPublishSidebarEnabled', true );
410
410
  };
411
411
 
412
412
  /**
@@ -417,7 +417,7 @@ export const disablePublishSidebar =
417
417
  ( { registry } ) => {
418
418
  registry
419
419
  .dispatch( preferencesStore )
420
- .set( 'core/edit-post', 'isPublishSidebarEnabled', false );
420
+ .set( 'core', 'isPublishSidebarEnabled', false );
421
421
  };
422
422
 
423
423
  /**
@@ -583,7 +583,6 @@ export function updateEditorSettings( settings ) {
583
583
  /**
584
584
  * Returns an action used to set the rendering mode of the post editor. We support multiple rendering modes:
585
585
  *
586
- * - `all`: This is the default mode. It renders the post editor with all the features available. If a template is provided, it's preferred over the post.
587
586
  * - `post-only`: This mode extracts the post blocks from the template and renders only those. The idea is to allow the user to edit the post/page in isolation without the wrapping template.
588
587
  * - `template-locked`: This mode renders both the template and the post blocks but the template blocks are locked and can't be edited. The post blocks are editable.
589
588
  *
@@ -820,6 +819,41 @@ export const switchEditorMode =
820
819
  }
821
820
  };
822
821
 
822
+ /**
823
+ * Returns an action object used in signalling that the user opened the publish
824
+ * sidebar.
825
+ *
826
+ * @return {Object} Action object
827
+ */
828
+ export function openPublishSidebar() {
829
+ return {
830
+ type: 'OPEN_PUBLISH_SIDEBAR',
831
+ };
832
+ }
833
+
834
+ /**
835
+ * Returns an action object used in signalling that the user closed the
836
+ * publish sidebar.
837
+ *
838
+ * @return {Object} Action object.
839
+ */
840
+ export function closePublishSidebar() {
841
+ return {
842
+ type: 'CLOSE_PUBLISH_SIDEBAR',
843
+ };
844
+ }
845
+
846
+ /**
847
+ * Returns an action object used in signalling that the user toggles the publish sidebar.
848
+ *
849
+ * @return {Object} Action object
850
+ */
851
+ export function togglePublishSidebar() {
852
+ return {
853
+ type: 'TOGGLE_PUBLISH_SIDEBAR',
854
+ };
855
+ }
856
+
823
857
  /**
824
858
  * Backward compatibility
825
859
  */
@@ -18,3 +18,5 @@ export const TRASH_POST_NOTICE_ID = 'TRASH_POST_NOTICE_ID';
18
18
  export const PERMALINK_POSTNAME_REGEX = /%(?:postname|pagename)%/;
19
19
  export const ONE_MINUTE_IN_MS = 60 * 1000;
20
20
  export const AUTOSAVE_PROPERTIES = [ 'title', 'excerpt', 'content' ];
21
+ export const TEMPLATE_POST_TYPE = 'wp_template';
22
+ export const TEMPLATE_PART_POST_TYPE = 'wp_template_part';