@wordpress/editor 13.22.0 → 13.24.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 (137) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/components/entities-saved-states/index.js +15 -1
  3. package/build/components/entities-saved-states/index.js.map +1 -1
  4. package/build/components/index.js +32 -0
  5. package/build/components/index.js.map +1 -1
  6. package/build/components/page-attributes/order.js +1 -0
  7. package/build/components/page-attributes/order.js.map +1 -1
  8. package/build/components/post-author/panel.js +24 -0
  9. package/build/components/post-author/panel.js.map +1 -0
  10. package/build/components/post-featured-image/index.js +3 -1
  11. package/build/components/post-featured-image/index.js.map +1 -1
  12. package/build/components/post-panel-row/index.js +36 -0
  13. package/build/components/post-panel-row/index.js.map +1 -0
  14. package/build/components/post-saved-state/index.js +21 -16
  15. package/build/components/post-saved-state/index.js.map +1 -1
  16. package/build/components/post-schedule/panel.js +67 -0
  17. package/build/components/post-schedule/panel.js.map +1 -0
  18. package/build/components/post-sync-status/index.js +9 -5
  19. package/build/components/post-sync-status/index.js.map +1 -1
  20. package/build/components/post-title/constants.js +11 -0
  21. package/build/components/post-title/constants.js.map +1 -0
  22. package/build/components/post-title/index.js +61 -90
  23. package/build/components/post-title/index.js.map +1 -1
  24. package/build/components/post-title/index.native.js +1 -1
  25. package/build/components/post-title/index.native.js.map +1 -1
  26. package/build/components/post-title/post-title-raw.js +92 -0
  27. package/build/components/post-title/post-title-raw.js.map +1 -0
  28. package/build/components/post-title/use-post-title-focus.js +64 -0
  29. package/build/components/post-title/use-post-title-focus.js.map +1 -0
  30. package/build/components/post-title/use-post-title.js +41 -0
  31. package/build/components/post-title/use-post-title.js.map +1 -0
  32. package/build/components/post-url/panel.js +70 -0
  33. package/build/components/post-url/panel.js.map +1 -0
  34. package/build/components/provider/constants.js +9 -0
  35. package/build/components/provider/constants.js.map +1 -0
  36. package/build/components/provider/disable-non-page-content-blocks.js +63 -0
  37. package/build/components/provider/disable-non-page-content-blocks.js.map +1 -0
  38. package/build/components/provider/index.js +126 -14
  39. package/build/components/provider/index.js.map +1 -1
  40. package/build/components/provider/use-block-editor-settings.js +22 -17
  41. package/build/components/provider/use-block-editor-settings.js.map +1 -1
  42. package/build/components/provider/use-block-editor-settings.native.js +2 -2
  43. package/build/components/provider/use-block-editor-settings.native.js.map +1 -1
  44. package/build/private-apis.js +7 -1
  45. package/build/private-apis.js.map +1 -1
  46. package/build/store/actions.js +23 -2
  47. package/build/store/actions.js.map +1 -1
  48. package/build/store/reducer.js +10 -1
  49. package/build/store/reducer.js.map +1 -1
  50. package/build/store/selectors.js +16 -2
  51. package/build/store/selectors.js.map +1 -1
  52. package/build-module/components/entities-saved-states/index.js +16 -2
  53. package/build-module/components/entities-saved-states/index.js.map +1 -1
  54. package/build-module/components/index.js +4 -0
  55. package/build-module/components/index.js.map +1 -1
  56. package/build-module/components/page-attributes/order.js +1 -0
  57. package/build-module/components/page-attributes/order.js.map +1 -1
  58. package/build-module/components/post-author/panel.js +14 -0
  59. package/build-module/components/post-author/panel.js.map +1 -0
  60. package/build-module/components/post-featured-image/index.js +3 -1
  61. package/build-module/components/post-featured-image/index.js.map +1 -1
  62. package/build-module/components/post-panel-row/index.js +27 -0
  63. package/build-module/components/post-panel-row/index.js.map +1 -0
  64. package/build-module/components/post-saved-state/index.js +22 -17
  65. package/build-module/components/post-saved-state/index.js.map +1 -1
  66. package/build-module/components/post-schedule/panel.js +59 -0
  67. package/build-module/components/post-schedule/panel.js.map +1 -0
  68. package/build-module/components/post-sync-status/index.js +10 -7
  69. package/build-module/components/post-sync-status/index.js.map +1 -1
  70. package/build-module/components/post-title/constants.js +3 -0
  71. package/build-module/components/post-title/constants.js.map +1 -0
  72. package/build-module/components/post-title/index.js +62 -92
  73. package/build-module/components/post-title/index.js.map +1 -1
  74. package/build-module/components/post-title/index.native.js +3 -3
  75. package/build-module/components/post-title/index.native.js.map +1 -1
  76. package/build-module/components/post-title/post-title-raw.js +83 -0
  77. package/build-module/components/post-title/post-title-raw.js.map +1 -0
  78. package/build-module/components/post-title/use-post-title-focus.js +57 -0
  79. package/build-module/components/post-title/use-post-title-focus.js.map +1 -0
  80. package/build-module/components/post-title/use-post-title.js +33 -0
  81. package/build-module/components/post-title/use-post-title.js.map +1 -0
  82. package/build-module/components/post-url/panel.js +62 -0
  83. package/build-module/components/post-url/panel.js.map +1 -0
  84. package/build-module/components/provider/constants.js +2 -0
  85. package/build-module/components/provider/constants.js.map +1 -0
  86. package/build-module/components/provider/disable-non-page-content-blocks.js +56 -0
  87. package/build-module/components/provider/disable-non-page-content-blocks.js.map +1 -0
  88. package/build-module/components/provider/index.js +127 -15
  89. package/build-module/components/provider/index.js.map +1 -1
  90. package/build-module/components/provider/use-block-editor-settings.js +22 -17
  91. package/build-module/components/provider/use-block-editor-settings.js.map +1 -1
  92. package/build-module/components/provider/use-block-editor-settings.native.js +2 -2
  93. package/build-module/components/provider/use-block-editor-settings.native.js.map +1 -1
  94. package/build-module/private-apis.js +6 -1
  95. package/build-module/private-apis.js.map +1 -1
  96. package/build-module/store/actions.js +21 -0
  97. package/build-module/store/actions.js.map +1 -1
  98. package/build-module/store/reducer.js +9 -1
  99. package/build-module/store/reducer.js.map +1 -1
  100. package/build-module/store/selectors.js +11 -0
  101. package/build-module/store/selectors.js.map +1 -1
  102. package/build-style/style-rtl.css +70 -10
  103. package/build-style/style.css +70 -10
  104. package/package.json +31 -31
  105. package/src/components/entities-saved-states/index.js +16 -1
  106. package/src/components/index.js +4 -0
  107. package/src/components/page-attributes/order.js +1 -0
  108. package/src/components/post-author/panel.js +18 -0
  109. package/src/components/post-author/style.scss +7 -0
  110. package/src/components/post-featured-image/index.js +3 -1
  111. package/src/components/post-panel-row/index.js +26 -0
  112. package/src/components/post-panel-row/style.scss +21 -0
  113. package/src/components/post-saved-state/index.js +46 -37
  114. package/src/components/post-schedule/panel.js +65 -0
  115. package/src/components/post-schedule/style.scss +23 -0
  116. package/src/components/post-sync-status/index.js +10 -8
  117. package/src/components/post-sync-status/style.scss +3 -18
  118. package/src/components/post-title/constants.js +4 -0
  119. package/src/components/post-title/index.js +56 -88
  120. package/src/components/post-title/index.native.js +4 -8
  121. package/src/components/post-title/post-title-raw.js +82 -0
  122. package/src/components/post-title/style.scss +5 -0
  123. package/src/components/post-title/use-post-title-focus.js +50 -0
  124. package/src/components/post-title/use-post-title.js +25 -0
  125. package/src/components/post-url/panel.js +60 -0
  126. package/src/components/post-url/style.scss +19 -0
  127. package/src/components/provider/README.md +37 -0
  128. package/src/components/provider/constants.js +5 -0
  129. package/src/components/provider/disable-non-page-content-blocks.js +55 -0
  130. package/src/components/provider/index.js +200 -14
  131. package/src/components/provider/use-block-editor-settings.js +54 -35
  132. package/src/components/provider/use-block-editor-settings.native.js +2 -2
  133. package/src/private-apis.js +6 -0
  134. package/src/store/actions.js +21 -0
  135. package/src/store/reducer.js +10 -0
  136. package/src/store/selectors.js +11 -0
  137. package/src/style.scss +4 -0
@@ -7,18 +7,12 @@ import classnames from 'classnames';
7
7
  * WordPress dependencies
8
8
  */
9
9
  import { __ } from '@wordpress/i18n';
10
- import {
11
- forwardRef,
12
- useEffect,
13
- useImperativeHandle,
14
- useRef,
15
- useState,
16
- } from '@wordpress/element';
10
+ import { forwardRef, useState } from '@wordpress/element';
17
11
  import { decodeEntities } from '@wordpress/html-entities';
18
- import { ENTER } from '@wordpress/keycodes';
19
12
  import { useSelect, useDispatch } from '@wordpress/data';
20
- import { pasteHandler } from '@wordpress/blocks';
21
13
  import { store as blockEditorStore } from '@wordpress/block-editor';
14
+ import { ENTER } from '@wordpress/keycodes';
15
+ import { pasteHandler } from '@wordpress/blocks';
22
16
  import {
23
17
  __unstableUseRichText as useRichText,
24
18
  create,
@@ -31,78 +25,45 @@ import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
31
25
  /**
32
26
  * Internal dependencies
33
27
  */
34
- import PostTypeSupportCheck from '../post-type-support-check';
35
28
  import { store as editorStore } from '../../store';
36
-
37
- /**
38
- * Constants
39
- */
40
- const REGEXP_NEWLINES = /[\r\n]+/g;
29
+ import { DEFAULT_CLASSNAMES, REGEXP_NEWLINES } from './constants';
30
+ import usePostTitleFocus from './use-post-title-focus';
31
+ import usePostTitle from './use-post-title';
32
+ import PostTypeSupportCheck from '../post-type-support-check';
41
33
 
42
34
  function PostTitle( _, forwardedRef ) {
43
- const ref = useRef();
35
+ const { placeholder, hasFixedToolbar } = useSelect( ( select ) => {
36
+ const { getEditedPostAttribute } = select( editorStore );
37
+ const { getSettings } = select( blockEditorStore );
38
+ const { titlePlaceholder, hasFixedToolbar: _hasFixedToolbar } =
39
+ getSettings();
40
+
41
+ return {
42
+ title: getEditedPostAttribute( 'title' ),
43
+ placeholder: titlePlaceholder,
44
+ hasFixedToolbar: _hasFixedToolbar,
45
+ };
46
+ }, [] );
47
+
44
48
  const [ isSelected, setIsSelected ] = useState( false );
45
- const { editPost } = useDispatch( editorStore );
46
- const { insertDefaultBlock, clearSelectedBlock, insertBlocks } =
47
- useDispatch( blockEditorStore );
48
- const { isCleanNewPost, title, placeholder, hasFixedToolbar } = useSelect(
49
- ( select ) => {
50
- const { getEditedPostAttribute, isCleanNewPost: _isCleanNewPost } =
51
- select( editorStore );
52
- const { getSettings } = select( blockEditorStore );
53
- const { titlePlaceholder, hasFixedToolbar: _hasFixedToolbar } =
54
- getSettings();
55
-
56
- return {
57
- isCleanNewPost: _isCleanNewPost(),
58
- title: getEditedPostAttribute( 'title' ),
59
- placeholder: titlePlaceholder,
60
- hasFixedToolbar: _hasFixedToolbar,
61
- };
62
- },
63
- []
64
- );
65
49
 
66
- useImperativeHandle( forwardedRef, () => ( {
67
- focus: () => {
68
- ref?.current?.focus();
69
- },
70
- } ) );
50
+ const { ref: focusRef } = usePostTitleFocus( forwardedRef );
71
51
 
72
- useEffect( () => {
73
- if ( ! ref.current ) {
74
- return;
75
- }
52
+ const { title, setTitle: onUpdate } = usePostTitle();
76
53
 
77
- const { defaultView } = ref.current.ownerDocument;
78
- const { name, parent } = defaultView;
79
- const ownerDocument =
80
- name === 'editor-canvas' ? parent.document : defaultView.document;
81
- const { activeElement, body } = ownerDocument;
82
-
83
- // Only autofocus the title when the post is entirely empty. This should
84
- // only happen for a new post, which means we focus the title on new
85
- // post so the author can start typing right away, without needing to
86
- // click anything.
87
- if ( isCleanNewPost && ( ! activeElement || body === activeElement ) ) {
88
- ref.current.focus();
89
- }
90
- }, [ isCleanNewPost ] );
54
+ const [ selection, setSelection ] = useState( {} );
91
55
 
92
- function onEnterPress() {
93
- insertDefaultBlock( undefined, undefined, 0 );
56
+ const { clearSelectedBlock, insertBlocks, insertDefaultBlock } =
57
+ useDispatch( blockEditorStore );
58
+
59
+ function onChange( value ) {
60
+ onUpdate( value.replace( REGEXP_NEWLINES, ' ' ) );
94
61
  }
95
62
 
96
63
  function onInsertBlockAfter( blocks ) {
97
64
  insertBlocks( blocks, 0 );
98
65
  }
99
66
 
100
- function onUpdate( newTitle ) {
101
- editPost( { title: newTitle } );
102
- }
103
-
104
- const [ selection, setSelection ] = useState( {} );
105
-
106
67
  function onSelect() {
107
68
  setIsSelected( true );
108
69
  clearSelectedBlock();
@@ -113,8 +74,8 @@ function PostTitle( _, forwardedRef ) {
113
74
  setSelection( {} );
114
75
  }
115
76
 
116
- function onChange( value ) {
117
- onUpdate( value.replace( REGEXP_NEWLINES, ' ' ) );
77
+ function onEnterPress() {
78
+ insertDefaultBlock( undefined, undefined, 0 );
118
79
  }
119
80
 
120
81
  function onKeyDown( event ) {
@@ -170,7 +131,13 @@ function PostTitle( _, forwardedRef ) {
170
131
  ( firstBlock.name === 'core/heading' ||
171
132
  firstBlock.name === 'core/paragraph' )
172
133
  ) {
173
- onUpdate( stripHTML( firstBlock.attributes.content ) );
134
+ // Strip HTML to avoid unwanted HTML being added to the title.
135
+ // In the majority of cases it is assumed that HTML in the title
136
+ // is undesirable.
137
+ const contentNoHTML = stripHTML(
138
+ firstBlock.attributes.content
139
+ );
140
+ onUpdate( contentNoHTML );
174
141
  onInsertBlockAfter( content.slice( 1 ) );
175
142
  } else {
176
143
  onInsertBlockAfter( content );
@@ -180,10 +147,13 @@ function PostTitle( _, forwardedRef ) {
180
147
  ...create( { html: title } ),
181
148
  ...selection,
182
149
  };
183
- const newValue = insert(
184
- value,
185
- create( { html: stripHTML( content ) } )
186
- );
150
+
151
+ // Strip HTML to avoid unwanted HTML being added to the title.
152
+ // In the majority of cases it is assumed that HTML in the title
153
+ // is undesirable.
154
+ const contentNoHTML = stripHTML( content );
155
+
156
+ const newValue = insert( value, create( { html: contentNoHTML } ) );
187
157
  onUpdate( toHTMLString( { value: newValue } ) );
188
158
  setSelection( {
189
159
  start: newValue.start,
@@ -192,17 +162,9 @@ function PostTitle( _, forwardedRef ) {
192
162
  }
193
163
  }
194
164
 
195
- // The wp-block className is important for editor styles.
196
- // This same block is used in both the visual and the code editor.
197
- const className = classnames(
198
- 'wp-block wp-block-post-title block-editor-block-list__block editor-post-title editor-post-title__input rich-text',
199
- {
200
- 'is-selected': isSelected,
201
- 'has-fixed-toolbar': hasFixedToolbar,
202
- }
203
- );
204
165
  const decodedPlaceholder =
205
166
  decodeEntities( placeholder ) || __( 'Add title' );
167
+
206
168
  const { ref: richTextRef } = useRichText( {
207
169
  value: title,
208
170
  onChange,
@@ -221,15 +183,21 @@ function PostTitle( _, forwardedRef ) {
221
183
  };
222
184
  } );
223
185
  },
224
- __unstableDisableFormats: true,
225
- preserveWhiteSpace: true,
186
+ __unstableDisableFormats: false,
187
+ } );
188
+
189
+ // The wp-block className is important for editor styles.
190
+ // This same block is used in both the visual and the code editor.
191
+ const className = classnames( DEFAULT_CLASSNAMES, {
192
+ 'is-selected': isSelected,
193
+ 'has-fixed-toolbar': hasFixedToolbar,
226
194
  } );
227
195
 
228
- /* eslint-disable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */
229
196
  return (
197
+ /* eslint-disable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */
230
198
  <PostTypeSupportCheck supportKeys="title">
231
199
  <h1
232
- ref={ useMergeRefs( [ richTextRef, ref ] ) }
200
+ ref={ useMergeRefs( [ richTextRef, focusRef ] ) }
233
201
  contentEditable
234
202
  className={ className }
235
203
  aria-label={ decodedPlaceholder }
@@ -242,8 +210,8 @@ function PostTitle( _, forwardedRef ) {
242
210
  onPaste={ onPaste }
243
211
  />
244
212
  </PostTypeSupportCheck>
213
+ /* eslint-enable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */
245
214
  );
246
- /* eslint-enable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */
247
215
  }
248
216
 
249
217
  export default forwardRef( PostTitle );
@@ -7,18 +7,14 @@ import { View } from 'react-native';
7
7
  * WordPress dependencies
8
8
  */
9
9
  import { Component } from '@wordpress/element';
10
- import {
11
- __experimentalRichText as RichText,
12
- create,
13
- insert,
14
- } from '@wordpress/rich-text';
10
+ import { create, insert } from '@wordpress/rich-text';
15
11
  import { decodeEntities } from '@wordpress/html-entities';
16
12
  import { withDispatch, withSelect } from '@wordpress/data';
17
13
  import { withFocusOutside } from '@wordpress/components';
18
14
  import { withInstanceId, compose } from '@wordpress/compose';
19
15
  import { __, sprintf } from '@wordpress/i18n';
20
16
  import { pasteHandler } from '@wordpress/blocks';
21
- import { store as blockEditorStore } from '@wordpress/block-editor';
17
+ import { store as blockEditorStore, RichText } from '@wordpress/block-editor';
22
18
  import { store as editorStore } from '@wordpress/editor';
23
19
 
24
20
  /**
@@ -152,7 +148,7 @@ class PostTitle extends Component {
152
148
  accessibilityLabel={ this.getTitle( title, postType ) }
153
149
  accessibilityHint={ __( 'Updates the title.' ) }
154
150
  >
155
- <RichText
151
+ <RichText.Raw
156
152
  setRef={ this.setRef }
157
153
  accessibilityLabel={ this.getTitle( title, postType ) }
158
154
  tagName={ 'p' }
@@ -177,7 +173,7 @@ class PostTitle extends Component {
177
173
  disableEditingMenu={ true }
178
174
  __unstableIsSelected={ this.props.isSelected }
179
175
  __unstableOnCreateUndoLevel={ () => {} }
180
- ></RichText>
176
+ />
181
177
  </View>
182
178
  );
183
179
  }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import classnames from 'classnames';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { TextareaControl } from '@wordpress/components';
10
+ import { __ } from '@wordpress/i18n';
11
+ import { decodeEntities } from '@wordpress/html-entities';
12
+ import { useSelect } from '@wordpress/data';
13
+ import { store as blockEditorStore } from '@wordpress/block-editor';
14
+ import { useState, forwardRef } from '@wordpress/element';
15
+
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ import { DEFAULT_CLASSNAMES, REGEXP_NEWLINES } from './constants';
20
+ import usePostTitleFocus from './use-post-title-focus';
21
+ import usePostTitle from './use-post-title';
22
+
23
+ function PostTitleRaw( _, forwardedRef ) {
24
+ const { placeholder, hasFixedToolbar } = useSelect( ( select ) => {
25
+ const { getSettings } = select( blockEditorStore );
26
+ const { titlePlaceholder, hasFixedToolbar: _hasFixedToolbar } =
27
+ getSettings();
28
+
29
+ return {
30
+ placeholder: titlePlaceholder,
31
+ hasFixedToolbar: _hasFixedToolbar,
32
+ };
33
+ }, [] );
34
+
35
+ const [ isSelected, setIsSelected ] = useState( false );
36
+
37
+ const { title, setTitle: onUpdate } = usePostTitle();
38
+ const { ref: focusRef } = usePostTitleFocus( forwardedRef );
39
+
40
+ function onChange( value ) {
41
+ onUpdate( value.replace( REGEXP_NEWLINES, ' ' ) );
42
+ }
43
+
44
+ function onSelect() {
45
+ setIsSelected( true );
46
+ }
47
+
48
+ function onUnselect() {
49
+ setIsSelected( false );
50
+ }
51
+
52
+ // The wp-block className is important for editor styles.
53
+ // This same block is used in both the visual and the code editor.
54
+ const className = classnames( DEFAULT_CLASSNAMES, {
55
+ 'is-selected': isSelected,
56
+ 'has-fixed-toolbar': hasFixedToolbar,
57
+ 'is-raw-text': true,
58
+ } );
59
+
60
+ const decodedPlaceholder =
61
+ decodeEntities( placeholder ) || __( 'Add title' );
62
+
63
+ return (
64
+ <TextareaControl
65
+ ref={ focusRef }
66
+ value={ title }
67
+ onChange={ onChange }
68
+ onFocus={ onSelect }
69
+ onBlur={ onUnselect }
70
+ label={ placeholder }
71
+ className={ className }
72
+ placeholder={ decodedPlaceholder }
73
+ hideLabelFromVision={ true }
74
+ autoComplete="off"
75
+ dir="auto"
76
+ rows={ 1 }
77
+ __nextHasNoMarginBottom
78
+ />
79
+ );
80
+ }
81
+
82
+ export default forwardRef( PostTitleRaw );
@@ -0,0 +1,5 @@
1
+ // Raw Text Variant
2
+ .edit-post-text-editor__body .editor-post-title.is-raw-text {
3
+ margin-bottom: $grid-unit-30;
4
+ margin-top: 2px; // space for focus outline to appear.
5
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useEffect, useImperativeHandle, useRef } from '@wordpress/element';
5
+ import { useSelect } from '@wordpress/data';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import { store as editorStore } from '../../store';
11
+
12
+ export default function usePostTitleFocus( forwardedRef ) {
13
+ const ref = useRef();
14
+
15
+ const { isCleanNewPost } = useSelect( ( select ) => {
16
+ const { isCleanNewPost: _isCleanNewPost } = select( editorStore );
17
+
18
+ return {
19
+ isCleanNewPost: _isCleanNewPost(),
20
+ };
21
+ }, [] );
22
+
23
+ useImperativeHandle( forwardedRef, () => ( {
24
+ focus: () => {
25
+ ref?.current?.focus();
26
+ },
27
+ } ) );
28
+
29
+ useEffect( () => {
30
+ if ( ! ref.current ) {
31
+ return;
32
+ }
33
+
34
+ const { defaultView } = ref.current.ownerDocument;
35
+ const { name, parent } = defaultView;
36
+ const ownerDocument =
37
+ name === 'editor-canvas' ? parent.document : defaultView.document;
38
+ const { activeElement, body } = ownerDocument;
39
+
40
+ // Only autofocus the title when the post is entirely empty. This should
41
+ // only happen for a new post, which means we focus the title on new
42
+ // post so the author can start typing right away, without needing to
43
+ // click anything.
44
+ if ( isCleanNewPost && ( ! activeElement || body === activeElement ) ) {
45
+ ref.current.focus();
46
+ }
47
+ }, [ isCleanNewPost ] );
48
+
49
+ return { ref };
50
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useSelect, useDispatch } from '@wordpress/data';
5
+ /**
6
+ * Internal dependencies
7
+ */
8
+ import { store as editorStore } from '../../store';
9
+
10
+ export default function usePostTitle() {
11
+ const { editPost } = useDispatch( editorStore );
12
+ const { title } = useSelect( ( select ) => {
13
+ const { getEditedPostAttribute } = select( editorStore );
14
+
15
+ return {
16
+ title: getEditedPostAttribute( 'title' ),
17
+ };
18
+ }, [] );
19
+
20
+ function updateTitle( newTitle ) {
21
+ editPost( { title: newTitle } );
22
+ }
23
+
24
+ return { title, setTitle: updateTitle };
25
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useMemo, useState } from '@wordpress/element';
5
+ import { Dropdown, Button } from '@wordpress/components';
6
+ import { __, sprintf } from '@wordpress/i18n';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import PostURLCheck from './check';
12
+ import PostURL from './index';
13
+ import { usePostURLLabel } from './label';
14
+ import PostPanelRow from '../post-panel-row';
15
+
16
+ export default function PostURLPanel() {
17
+ // Use internal state instead of a ref to make sure that the component
18
+ // re-renders when the popover's anchor updates.
19
+ const [ popoverAnchor, setPopoverAnchor ] = useState( null );
20
+ // Memoize popoverProps to avoid returning a new object every time.
21
+ const popoverProps = useMemo(
22
+ () => ( { anchor: popoverAnchor, placement: 'bottom-end' } ),
23
+ [ popoverAnchor ]
24
+ );
25
+
26
+ return (
27
+ <PostURLCheck>
28
+ <PostPanelRow label={ __( 'URL' ) } ref={ setPopoverAnchor }>
29
+ <Dropdown
30
+ popoverProps={ popoverProps }
31
+ className="editor-post-url__panel-dropdown"
32
+ contentClassName="editor-post-url__panel-dialog"
33
+ focusOnMount
34
+ renderToggle={ ( { isOpen, onToggle } ) => (
35
+ <PostURLToggle isOpen={ isOpen } onClick={ onToggle } />
36
+ ) }
37
+ renderContent={ ( { onClose } ) => (
38
+ <PostURL onClose={ onClose } />
39
+ ) }
40
+ />
41
+ </PostPanelRow>
42
+ </PostURLCheck>
43
+ );
44
+ }
45
+
46
+ function PostURLToggle( { isOpen, onClick } ) {
47
+ const label = usePostURLLabel();
48
+ return (
49
+ <Button
50
+ className="editor-post-url__panel-toggle"
51
+ variant="tertiary"
52
+ aria-expanded={ isOpen }
53
+ // translators: %s: Current post URL.
54
+ aria-label={ sprintf( __( 'Change URL: %s' ), label ) }
55
+ onClick={ onClick }
56
+ >
57
+ { label }
58
+ </Button>
59
+ );
60
+ }
@@ -1,3 +1,22 @@
1
+ .editor-post-url__panel-dropdown {
2
+ width: 100%;
3
+ }
4
+
5
+ .components-button.editor-post-url__panel-toggle {
6
+ display: block;
7
+ max-width: 100%;
8
+ overflow: hidden;
9
+ text-align: left;
10
+ text-overflow: ellipsis;
11
+ white-space: nowrap;
12
+ }
13
+
14
+ .editor-post-url__panel-dialog .editor-post-url {
15
+ // sidebar width - popover padding - form margin
16
+ min-width: $sidebar-width - $grid-unit-20 - $grid-unit-20;
17
+ margin: $grid-unit-10;
18
+ }
19
+
1
20
  .editor-post-url__link-label {
2
21
  font-size: $default-font-size;
3
22
  font-weight: 400;
@@ -0,0 +1,37 @@
1
+ # EditorProvider
2
+
3
+ EditorProvider is a component which establishes a new post editing context, and serves as the entry point for a new post editor (or post with template editor).
4
+
5
+ It supports a big number of post types, including post, page, templates, custom post types, patterns, template parts.
6
+
7
+ All modification and changes are performed to the `@wordpress/core-data` store.
8
+
9
+ ## Props
10
+
11
+ ### `post`
12
+
13
+ - **Type:** `Object`
14
+ - **Required** `yes`
15
+
16
+ The post object to edit
17
+
18
+ ### `__unstableTemplate`
19
+
20
+ - **Type:** `Object`
21
+ - **Required** `no`
22
+
23
+ The template object wrapper the edited post. This is optional and can only be used when the post type supports templates (like posts and pages).
24
+
25
+ ### `settings`
26
+
27
+ - **Type:** `Object`
28
+ - **Required** `no`
29
+
30
+ The settings object to use for the editor. This is optional and can be used to override the default settings.
31
+
32
+ ### `children`
33
+
34
+ - **Type:** `Element`
35
+ - **Required** `no`
36
+
37
+ Children elements for which the BlockEditorProvider context should apply.
@@ -0,0 +1,5 @@
1
+ export const PAGE_CONTENT_BLOCK_TYPES = [
2
+ 'core/post-title',
3
+ 'core/post-featured-image',
4
+ 'core/post-content',
5
+ ];
@@ -0,0 +1,55 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useSelect, useDispatch } from '@wordpress/data';
5
+ import {
6
+ useBlockEditingMode,
7
+ store as blockEditorStore,
8
+ } from '@wordpress/block-editor';
9
+ import { useEffect } from '@wordpress/element';
10
+
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import { PAGE_CONTENT_BLOCK_TYPES } from './constants';
15
+
16
+ function DisableBlock( { clientId } ) {
17
+ const isDescendentOfQueryLoop = useSelect(
18
+ ( select ) => {
19
+ const { getBlockParentsByBlockName } = select( blockEditorStore );
20
+ return (
21
+ getBlockParentsByBlockName( clientId, 'core/query' ).length !==
22
+ 0
23
+ );
24
+ },
25
+ [ clientId ]
26
+ );
27
+ const mode = isDescendentOfQueryLoop ? undefined : 'contentOnly';
28
+ const { setBlockEditingMode, unsetBlockEditingMode } =
29
+ useDispatch( blockEditorStore );
30
+ useEffect( () => {
31
+ if ( mode ) {
32
+ setBlockEditingMode( clientId, mode );
33
+ return () => {
34
+ unsetBlockEditingMode( clientId );
35
+ };
36
+ }
37
+ }, [ clientId, mode, setBlockEditingMode, unsetBlockEditingMode ] );
38
+ }
39
+
40
+ /**
41
+ * Component that when rendered, makes it so that the site editor allows only
42
+ * page content to be edited.
43
+ */
44
+ export default function DisableNonPageContentBlocks() {
45
+ useBlockEditingMode( 'disabled' );
46
+ const clientIds = useSelect( ( select ) => {
47
+ const { __experimentalGetGlobalBlocksByName } =
48
+ select( blockEditorStore );
49
+ return __experimentalGetGlobalBlocksByName( PAGE_CONTENT_BLOCK_TYPES );
50
+ }, [] );
51
+
52
+ return clientIds.map( ( clientId ) => {
53
+ return <DisableBlock key={ clientId } clientId={ clientId } />;
54
+ } );
55
+ }