@wordpress/editor 13.23.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.
- package/CHANGELOG.md +2 -0
- package/build/components/entities-saved-states/index.js +15 -1
- package/build/components/entities-saved-states/index.js.map +1 -1
- package/build/components/index.js +26 -2
- package/build/components/index.js.map +1 -1
- package/build/components/post-author/panel.js +24 -0
- package/build/components/post-author/panel.js.map +1 -0
- package/build/components/post-panel-row/index.js +36 -0
- package/build/components/post-panel-row/index.js.map +1 -0
- package/build/components/post-saved-state/index.js +21 -16
- package/build/components/post-saved-state/index.js.map +1 -1
- package/build/components/post-schedule/panel.js +67 -0
- package/build/components/post-schedule/panel.js.map +1 -0
- package/build/components/post-sync-status/index.js +8 -4
- package/build/components/post-sync-status/index.js.map +1 -1
- package/build/components/post-title/constants.js +11 -0
- package/build/components/post-title/constants.js.map +1 -0
- package/build/components/post-title/index.js +61 -89
- package/build/components/post-title/index.js.map +1 -1
- package/build/components/post-title/post-title-raw.js +92 -0
- package/build/components/post-title/post-title-raw.js.map +1 -0
- package/build/components/post-title/use-post-title-focus.js +64 -0
- package/build/components/post-title/use-post-title-focus.js.map +1 -0
- package/build/components/post-title/use-post-title.js +41 -0
- package/build/components/post-title/use-post-title.js.map +1 -0
- package/build/components/post-url/panel.js +4 -3
- package/build/components/post-url/panel.js.map +1 -1
- package/build/components/provider/constants.js +9 -0
- package/build/components/provider/constants.js.map +1 -0
- package/build/components/provider/disable-non-page-content-blocks.js +63 -0
- package/build/components/provider/disable-non-page-content-blocks.js.map +1 -0
- package/build/components/provider/index.js +8 -7
- package/build/components/provider/index.js.map +1 -1
- package/build/private-apis.js +2 -0
- package/build/private-apis.js.map +1 -1
- package/build/store/actions.js +23 -2
- package/build/store/actions.js.map +1 -1
- package/build/store/reducer.js +10 -1
- package/build/store/reducer.js.map +1 -1
- package/build/store/selectors.js +16 -2
- package/build/store/selectors.js.map +1 -1
- package/build-module/components/entities-saved-states/index.js +16 -2
- package/build-module/components/entities-saved-states/index.js.map +1 -1
- package/build-module/components/index.js +3 -0
- package/build-module/components/index.js.map +1 -1
- package/build-module/components/post-author/panel.js +14 -0
- package/build-module/components/post-author/panel.js.map +1 -0
- package/build-module/components/post-panel-row/index.js +27 -0
- package/build-module/components/post-panel-row/index.js.map +1 -0
- package/build-module/components/post-saved-state/index.js +22 -17
- package/build-module/components/post-saved-state/index.js.map +1 -1
- package/build-module/components/post-schedule/panel.js +59 -0
- package/build-module/components/post-schedule/panel.js.map +1 -0
- package/build-module/components/post-sync-status/index.js +8 -5
- package/build-module/components/post-sync-status/index.js.map +1 -1
- package/build-module/components/post-title/constants.js +3 -0
- package/build-module/components/post-title/constants.js.map +1 -0
- package/build-module/components/post-title/index.js +62 -91
- package/build-module/components/post-title/index.js.map +1 -1
- package/build-module/components/post-title/post-title-raw.js +83 -0
- package/build-module/components/post-title/post-title-raw.js.map +1 -0
- package/build-module/components/post-title/use-post-title-focus.js +57 -0
- package/build-module/components/post-title/use-post-title-focus.js.map +1 -0
- package/build-module/components/post-title/use-post-title.js +33 -0
- package/build-module/components/post-title/use-post-title.js.map +1 -0
- package/build-module/components/post-url/panel.js +5 -4
- package/build-module/components/post-url/panel.js.map +1 -1
- package/build-module/components/provider/constants.js +2 -0
- package/build-module/components/provider/constants.js.map +1 -0
- package/build-module/components/provider/disable-non-page-content-blocks.js +56 -0
- package/build-module/components/provider/disable-non-page-content-blocks.js.map +1 -0
- package/build-module/components/provider/index.js +6 -4
- package/build-module/components/provider/index.js.map +1 -1
- package/build-module/private-apis.js +2 -0
- package/build-module/private-apis.js.map +1 -1
- package/build-module/store/actions.js +21 -0
- package/build-module/store/actions.js.map +1 -1
- package/build-module/store/reducer.js +9 -1
- package/build-module/store/reducer.js.map +1 -1
- package/build-module/store/selectors.js +11 -0
- package/build-module/store/selectors.js.map +1 -1
- package/build-style/style-rtl.css +51 -18
- package/build-style/style.css +51 -18
- package/package.json +31 -31
- package/src/components/entities-saved-states/index.js +16 -1
- package/src/components/index.js +3 -0
- package/src/components/post-author/panel.js +18 -0
- package/src/components/post-author/style.scss +7 -0
- package/src/components/post-panel-row/index.js +26 -0
- package/src/components/post-panel-row/style.scss +21 -0
- package/src/components/post-saved-state/index.js +46 -37
- package/src/components/post-schedule/panel.js +65 -0
- package/src/components/post-schedule/style.scss +23 -0
- package/src/components/post-sync-status/index.js +5 -6
- package/src/components/post-sync-status/style.scss +3 -17
- package/src/components/post-title/constants.js +4 -0
- package/src/components/post-title/index.js +56 -87
- package/src/components/post-title/post-title-raw.js +82 -0
- package/src/components/post-title/style.scss +5 -0
- package/src/components/post-title/use-post-title-focus.js +50 -0
- package/src/components/post-title/use-post-title.js +25 -0
- package/src/components/post-url/panel.js +4 -8
- package/src/components/post-url/style.scss +1 -12
- package/src/components/provider/README.md +0 -13
- package/src/components/provider/constants.js +5 -0
- package/src/components/provider/disable-non-page-content-blocks.js +55 -0
- package/src/components/provider/index.js +19 -9
- package/src/private-apis.js +2 -0
- package/src/store/actions.js +21 -0
- package/src/store/reducer.js +10 -0
- package/src/store/selectors.js +11 -0
- 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
|
-
|
|
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
|
|
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
|
-
|
|
67
|
-
focus: () => {
|
|
68
|
-
ref?.current?.focus();
|
|
69
|
-
},
|
|
70
|
-
} ) );
|
|
50
|
+
const { ref: focusRef } = usePostTitleFocus( forwardedRef );
|
|
71
51
|
|
|
72
|
-
|
|
73
|
-
if ( ! ref.current ) {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
52
|
+
const { title, setTitle: onUpdate } = usePostTitle();
|
|
76
53
|
|
|
77
|
-
|
|
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
|
-
|
|
93
|
-
|
|
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
|
|
117
|
-
|
|
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
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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,14 +183,21 @@ function PostTitle( _, forwardedRef ) {
|
|
|
221
183
|
};
|
|
222
184
|
} );
|
|
223
185
|
},
|
|
224
|
-
__unstableDisableFormats:
|
|
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,
|
|
225
194
|
} );
|
|
226
195
|
|
|
227
|
-
/* eslint-disable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */
|
|
228
196
|
return (
|
|
197
|
+
/* eslint-disable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */
|
|
229
198
|
<PostTypeSupportCheck supportKeys="title">
|
|
230
199
|
<h1
|
|
231
|
-
ref={ useMergeRefs( [ richTextRef,
|
|
200
|
+
ref={ useMergeRefs( [ richTextRef, focusRef ] ) }
|
|
232
201
|
contentEditable
|
|
233
202
|
className={ className }
|
|
234
203
|
aria-label={ decodedPlaceholder }
|
|
@@ -241,8 +210,8 @@ function PostTitle( _, forwardedRef ) {
|
|
|
241
210
|
onPaste={ onPaste }
|
|
242
211
|
/>
|
|
243
212
|
</PostTypeSupportCheck>
|
|
213
|
+
/* eslint-enable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */
|
|
244
214
|
);
|
|
245
|
-
/* eslint-enable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */
|
|
246
215
|
}
|
|
247
216
|
|
|
248
217
|
export default forwardRef( PostTitle );
|
|
@@ -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,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
|
+
}
|
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { useMemo, useState } from '@wordpress/element';
|
|
5
|
-
import {
|
|
6
|
-
__experimentalHStack as HStack,
|
|
7
|
-
Dropdown,
|
|
8
|
-
Button,
|
|
9
|
-
} from '@wordpress/components';
|
|
5
|
+
import { Dropdown, Button } from '@wordpress/components';
|
|
10
6
|
import { __, sprintf } from '@wordpress/i18n';
|
|
11
7
|
|
|
12
8
|
/**
|
|
@@ -15,6 +11,7 @@ import { __, sprintf } from '@wordpress/i18n';
|
|
|
15
11
|
import PostURLCheck from './check';
|
|
16
12
|
import PostURL from './index';
|
|
17
13
|
import { usePostURLLabel } from './label';
|
|
14
|
+
import PostPanelRow from '../post-panel-row';
|
|
18
15
|
|
|
19
16
|
export default function PostURLPanel() {
|
|
20
17
|
// Use internal state instead of a ref to make sure that the component
|
|
@@ -28,8 +25,7 @@ export default function PostURLPanel() {
|
|
|
28
25
|
|
|
29
26
|
return (
|
|
30
27
|
<PostURLCheck>
|
|
31
|
-
<
|
|
32
|
-
<span>{ __( 'URL' ) }</span>
|
|
28
|
+
<PostPanelRow label={ __( 'URL' ) } ref={ setPopoverAnchor }>
|
|
33
29
|
<Dropdown
|
|
34
30
|
popoverProps={ popoverProps }
|
|
35
31
|
className="editor-post-url__panel-dropdown"
|
|
@@ -42,7 +38,7 @@ export default function PostURLPanel() {
|
|
|
42
38
|
<PostURL onClose={ onClose } />
|
|
43
39
|
) }
|
|
44
40
|
/>
|
|
45
|
-
</
|
|
41
|
+
</PostPanelRow>
|
|
46
42
|
</PostURLCheck>
|
|
47
43
|
);
|
|
48
44
|
}
|
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
.editor-post-url__panel {
|
|
2
|
-
width: 100%;
|
|
3
|
-
justify-content: flex-start;
|
|
4
|
-
align-items: flex-start;
|
|
5
|
-
|
|
6
|
-
span {
|
|
7
|
-
display: block;
|
|
8
|
-
width: 30%;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
1
|
.editor-post-url__panel-dropdown {
|
|
13
|
-
width:
|
|
2
|
+
width: 100%;
|
|
14
3
|
}
|
|
15
4
|
|
|
16
5
|
.components-button.editor-post-url__panel-toggle {
|
|
@@ -22,19 +22,6 @@ The post object to edit
|
|
|
22
22
|
|
|
23
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
24
|
|
|
25
|
-
### `mode`
|
|
26
|
-
|
|
27
|
-
- **Type:** `String`
|
|
28
|
-
- **Required** `no`
|
|
29
|
-
- **default** `all`
|
|
30
|
-
|
|
31
|
-
This is the rendering mode of the post editor. We support multiple rendering modes:
|
|
32
|
-
|
|
33
|
-
- `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.
|
|
34
|
-
- `template-only`: This mode renders the editor with only the template blocks visible.
|
|
35
|
-
- `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.
|
|
36
|
-
- `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.
|
|
37
|
-
|
|
38
25
|
### `settings`
|
|
39
26
|
|
|
40
27
|
- **Type:** `Object`
|
|
@@ -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
|
+
}
|
|
@@ -22,16 +22,13 @@ import withRegistryProvider from './with-registry-provider';
|
|
|
22
22
|
import { store as editorStore } from '../../store';
|
|
23
23
|
import useBlockEditorSettings from './use-block-editor-settings';
|
|
24
24
|
import { unlock } from '../../lock-unlock';
|
|
25
|
+
import DisableNonPageContentBlocks from './disable-non-page-content-blocks';
|
|
26
|
+
import { PAGE_CONTENT_BLOCK_TYPES } from './constants';
|
|
25
27
|
|
|
26
28
|
const { ExperimentalBlockEditorProvider } = unlock( blockEditorPrivateApis );
|
|
27
29
|
const { PatternsMenuItems } = unlock( editPatternsPrivateApis );
|
|
28
30
|
|
|
29
31
|
const noop = () => {};
|
|
30
|
-
export const PAGE_CONTENT_BLOCK_TYPES = [
|
|
31
|
-
'core/post-title',
|
|
32
|
-
'core/post-featured-image',
|
|
33
|
-
'core/post-content',
|
|
34
|
-
];
|
|
35
32
|
|
|
36
33
|
/**
|
|
37
34
|
* For the Navigation block editor, we need to force the block editor to contentOnly for that block.
|
|
@@ -128,6 +125,10 @@ function useBlockEditorProps( post, template, mode ) {
|
|
|
128
125
|
}
|
|
129
126
|
|
|
130
127
|
if ( mode === 'post-only' ) {
|
|
128
|
+
const postContentBlocks =
|
|
129
|
+
extractPageContentBlockTypesFromTemplateBlocks(
|
|
130
|
+
templateBlocks
|
|
131
|
+
);
|
|
131
132
|
return [
|
|
132
133
|
createBlock(
|
|
133
134
|
'core/group',
|
|
@@ -141,9 +142,12 @@ function useBlockEditorProps( post, template, mode ) {
|
|
|
141
142
|
},
|
|
142
143
|
},
|
|
143
144
|
},
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
postContentBlocks.length
|
|
146
|
+
? postContentBlocks
|
|
147
|
+
: [
|
|
148
|
+
createBlock( 'core/post-title' ),
|
|
149
|
+
createBlock( 'core/post-content' ),
|
|
150
|
+
]
|
|
147
151
|
),
|
|
148
152
|
];
|
|
149
153
|
}
|
|
@@ -181,7 +185,6 @@ function useBlockEditorProps( post, template, mode ) {
|
|
|
181
185
|
|
|
182
186
|
export const ExperimentalEditorProvider = withRegistryProvider(
|
|
183
187
|
( {
|
|
184
|
-
mode = 'all',
|
|
185
188
|
post,
|
|
186
189
|
settings,
|
|
187
190
|
recovery,
|
|
@@ -190,6 +193,10 @@ export const ExperimentalEditorProvider = withRegistryProvider(
|
|
|
190
193
|
BlockEditorProviderComponent = ExperimentalBlockEditorProvider,
|
|
191
194
|
__unstableTemplate: template,
|
|
192
195
|
} ) => {
|
|
196
|
+
const mode = useSelect(
|
|
197
|
+
( select ) => select( editorStore ).getRenderingMode(),
|
|
198
|
+
[]
|
|
199
|
+
);
|
|
193
200
|
const shouldRenderTemplate = !! template && mode !== 'post-only';
|
|
194
201
|
const rootLevelPost = shouldRenderTemplate ? template : post;
|
|
195
202
|
const defaultBlockContext = useMemo( () => {
|
|
@@ -308,6 +315,9 @@ export const ExperimentalEditorProvider = withRegistryProvider(
|
|
|
308
315
|
>
|
|
309
316
|
{ children }
|
|
310
317
|
<PatternsMenuItems />
|
|
318
|
+
{ [ 'post-only', 'template-locked' ].includes(
|
|
319
|
+
mode
|
|
320
|
+
) && <DisableNonPageContentBlocks /> }
|
|
311
321
|
</BlockEditorProviderComponent>
|
|
312
322
|
</BlockContextProvider>
|
|
313
323
|
</EntityProvider>
|
package/src/private-apis.js
CHANGED
|
@@ -5,11 +5,13 @@ import { ExperimentalEditorProvider } from './components/provider';
|
|
|
5
5
|
import { lock } from './lock-unlock';
|
|
6
6
|
import { EntitiesSavedStatesExtensible } from './components/entities-saved-states';
|
|
7
7
|
import useBlockEditorSettings from './components/provider/use-block-editor-settings';
|
|
8
|
+
import PostPanelRow from './components/post-panel-row';
|
|
8
9
|
|
|
9
10
|
export const privateApis = {};
|
|
10
11
|
lock( privateApis, {
|
|
11
12
|
ExperimentalEditorProvider,
|
|
12
13
|
EntitiesSavedStatesExtensible,
|
|
14
|
+
PostPanelRow,
|
|
13
15
|
|
|
14
16
|
// This is a temporary private API while we're updating the site editor to use EditorProvider.
|
|
15
17
|
useBlockEditorSettings,
|
package/src/store/actions.js
CHANGED
|
@@ -548,6 +548,27 @@ export function updateEditorSettings( settings ) {
|
|
|
548
548
|
};
|
|
549
549
|
}
|
|
550
550
|
|
|
551
|
+
/**
|
|
552
|
+
* Returns an action used to set the rendering mode of the post editor. We support multiple rendering modes:
|
|
553
|
+
*
|
|
554
|
+
* - `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.
|
|
555
|
+
* - `template-only`: This mode renders the editor with only the template blocks visible.
|
|
556
|
+
* - `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.
|
|
557
|
+
* - `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.
|
|
558
|
+
*
|
|
559
|
+
* @param {string} mode Mode (one of 'template-only', 'post-only', 'template-locked' or 'all').
|
|
560
|
+
*/
|
|
561
|
+
export const setRenderingMode =
|
|
562
|
+
( mode ) =>
|
|
563
|
+
( { dispatch, registry } ) => {
|
|
564
|
+
registry.dispatch( blockEditorStore ).clearSelectedBlock();
|
|
565
|
+
|
|
566
|
+
dispatch( {
|
|
567
|
+
type: 'SET_RENDERING_MODE',
|
|
568
|
+
mode,
|
|
569
|
+
} );
|
|
570
|
+
};
|
|
571
|
+
|
|
551
572
|
/**
|
|
552
573
|
* Backward compatibility
|
|
553
574
|
*/
|
package/src/store/reducer.js
CHANGED
|
@@ -279,6 +279,15 @@ export function editorSettings( state = EDITOR_SETTINGS_DEFAULTS, action ) {
|
|
|
279
279
|
return state;
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
+
export function renderingMode( state = 'all', action ) {
|
|
283
|
+
switch ( action.type ) {
|
|
284
|
+
case 'SET_RENDERING_MODE':
|
|
285
|
+
return action.mode;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return state;
|
|
289
|
+
}
|
|
290
|
+
|
|
282
291
|
export default combineReducers( {
|
|
283
292
|
postId,
|
|
284
293
|
postType,
|
|
@@ -290,4 +299,5 @@ export default combineReducers( {
|
|
|
290
299
|
isReady,
|
|
291
300
|
editorSettings,
|
|
292
301
|
postAutosavingLock,
|
|
302
|
+
renderingMode,
|
|
293
303
|
} );
|
package/src/store/selectors.js
CHANGED
|
@@ -1188,6 +1188,17 @@ export function getEditorSettings( state ) {
|
|
|
1188
1188
|
return state.editorSettings;
|
|
1189
1189
|
}
|
|
1190
1190
|
|
|
1191
|
+
/**
|
|
1192
|
+
* Returns the post editor's rendering mode.
|
|
1193
|
+
*
|
|
1194
|
+
* @param {Object} state Editor state.
|
|
1195
|
+
*
|
|
1196
|
+
* @return {string} Rendering mode.
|
|
1197
|
+
*/
|
|
1198
|
+
export function getRenderingMode( state ) {
|
|
1199
|
+
return state.renderingMode;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1191
1202
|
/*
|
|
1192
1203
|
* Backward compatibility
|
|
1193
1204
|
*/
|