@wordpress/editor 12.5.7 → 12.8.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 (46) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/components/post-featured-image/index.js +84 -41
  3. package/build/components/post-featured-image/index.js.map +1 -1
  4. package/build/components/post-text-editor/index.js +6 -6
  5. package/build/components/post-text-editor/index.js.map +1 -1
  6. package/build/components/post-title/index.js +13 -2
  7. package/build/components/post-title/index.js.map +1 -1
  8. package/build/components/post-visibility/index.js +132 -167
  9. package/build/components/post-visibility/index.js.map +1 -1
  10. package/build/components/post-visibility/label.js +5 -22
  11. package/build/components/post-visibility/label.js.map +1 -1
  12. package/build/components/post-visibility/utils.js +14 -13
  13. package/build/components/post-visibility/utils.js.map +1 -1
  14. package/build/components/provider/index.native.js +3 -1
  15. package/build/components/provider/index.native.js.map +1 -1
  16. package/build-module/components/post-featured-image/index.js +86 -42
  17. package/build-module/components/post-featured-image/index.js.map +1 -1
  18. package/build-module/components/post-text-editor/index.js +6 -6
  19. package/build-module/components/post-text-editor/index.js.map +1 -1
  20. package/build-module/components/post-title/index.js +12 -2
  21. package/build-module/components/post-title/index.js.map +1 -1
  22. package/build-module/components/post-visibility/index.js +132 -166
  23. package/build-module/components/post-visibility/index.js.map +1 -1
  24. package/build-module/components/post-visibility/label.js +5 -20
  25. package/build-module/components/post-visibility/label.js.map +1 -1
  26. package/build-module/components/post-visibility/utils.js +14 -13
  27. package/build-module/components/post-visibility/utils.js.map +1 -1
  28. package/build-module/components/provider/index.native.js +2 -1
  29. package/build-module/components/provider/index.native.js.map +1 -1
  30. package/build-style/style-rtl.css +51 -52
  31. package/build-style/style.css +51 -52
  32. package/package.json +28 -27
  33. package/src/components/autosave-monitor/test/index.js +3 -0
  34. package/src/components/editor-help/test/index.native.js +1 -1
  35. package/src/components/post-featured-image/index.js +102 -69
  36. package/src/components/post-saved-state/style.scss +9 -0
  37. package/src/components/post-slug/test/index.js +4 -4
  38. package/src/components/post-text-editor/index.js +5 -6
  39. package/src/components/post-title/index.js +16 -2
  40. package/src/components/post-visibility/index.js +130 -150
  41. package/src/components/post-visibility/label.js +6 -15
  42. package/src/components/post-visibility/style.scss +25 -20
  43. package/src/components/post-visibility/utils.js +7 -12
  44. package/src/components/provider/index.native.js +2 -1
  45. package/src/components/table-of-contents/style.scss +1 -3
  46. package/src/store/test/selectors.js +2 -2
@@ -16,8 +16,10 @@ import {
16
16
  withNotices,
17
17
  withFilters,
18
18
  } from '@wordpress/components';
19
+ import { isBlobURL } from '@wordpress/blob';
20
+ import { useState } from '@wordpress/element';
19
21
  import { compose } from '@wordpress/compose';
20
- import { withSelect, withDispatch } from '@wordpress/data';
22
+ import { useSelect, withDispatch, withSelect } from '@wordpress/data';
21
23
  import {
22
24
  MediaUpload,
23
25
  MediaUploadCheck,
@@ -38,63 +40,94 @@ const DEFAULT_FEATURE_IMAGE_LABEL = __( 'Featured image' );
38
40
  const DEFAULT_SET_FEATURE_IMAGE_LABEL = __( 'Set featured image' );
39
41
  const DEFAULT_REMOVE_FEATURE_IMAGE_LABEL = __( 'Remove image' );
40
42
 
43
+ const instructions = (
44
+ <p>
45
+ { __(
46
+ 'To edit the featured image, you need permission to upload media.'
47
+ ) }
48
+ </p>
49
+ );
50
+
51
+ function getMediaDetails( media, postId ) {
52
+ if ( ! media ) {
53
+ return {};
54
+ }
55
+
56
+ const defaultSize = applyFilters(
57
+ 'editor.PostFeaturedImage.imageSize',
58
+ 'large',
59
+ media.id,
60
+ postId
61
+ );
62
+ if ( has( media, [ 'media_details', 'sizes', defaultSize ] ) ) {
63
+ return {
64
+ mediaWidth: media.media_details.sizes[ defaultSize ].width,
65
+ mediaHeight: media.media_details.sizes[ defaultSize ].height,
66
+ mediaSourceUrl: media.media_details.sizes[ defaultSize ].source_url,
67
+ };
68
+ }
69
+
70
+ // Use fallbackSize when defaultSize is not available.
71
+ const fallbackSize = applyFilters(
72
+ 'editor.PostFeaturedImage.imageSize',
73
+ 'thumbnail',
74
+ media.id,
75
+ postId
76
+ );
77
+ if ( has( media, [ 'media_details', 'sizes', fallbackSize ] ) ) {
78
+ return {
79
+ mediaWidth: media.media_details.sizes[ fallbackSize ].width,
80
+ mediaHeight: media.media_details.sizes[ fallbackSize ].height,
81
+ mediaSourceUrl:
82
+ media.media_details.sizes[ fallbackSize ].source_url,
83
+ };
84
+ }
85
+
86
+ // Use full image size when fallbackSize and defaultSize are not available.
87
+ return {
88
+ mediaWidth: media.media_details.width,
89
+ mediaHeight: media.media_details.height,
90
+ mediaSourceUrl: media.source_url,
91
+ };
92
+ }
93
+
41
94
  function PostFeaturedImage( {
42
95
  currentPostId,
43
96
  featuredImageId,
44
97
  onUpdateImage,
45
- onDropImage,
46
98
  onRemoveImage,
47
99
  media,
48
100
  postType,
49
101
  noticeUI,
102
+ noticeOperations,
50
103
  } ) {
104
+ const [ isLoading, setIsLoading ] = useState( false );
105
+ const mediaUpload = useSelect( ( select ) => {
106
+ return select( blockEditorStore ).getSettings().mediaUpload;
107
+ }, [] );
51
108
  const postLabel = get( postType, [ 'labels' ], {} );
52
- const instructions = (
53
- <p>
54
- { __(
55
- 'To edit the featured image, you need permission to upload media.'
56
- ) }
57
- </p>
109
+ const { mediaWidth, mediaHeight, mediaSourceUrl } = getMediaDetails(
110
+ media,
111
+ currentPostId
58
112
  );
59
113
 
60
- let mediaWidth, mediaHeight, mediaSourceUrl;
61
- if ( media ) {
62
- const mediaSize = applyFilters(
63
- 'editor.PostFeaturedImage.imageSize',
64
- 'post-thumbnail',
65
- media.id,
66
- currentPostId
67
- );
68
- if ( has( media, [ 'media_details', 'sizes', mediaSize ] ) ) {
69
- // Use mediaSize when available.
70
- mediaWidth = media.media_details.sizes[ mediaSize ].width;
71
- mediaHeight = media.media_details.sizes[ mediaSize ].height;
72
- mediaSourceUrl = media.media_details.sizes[ mediaSize ].source_url;
73
- } else {
74
- // Get fallbackMediaSize if mediaSize is not available.
75
- const fallbackMediaSize = applyFilters(
76
- 'editor.PostFeaturedImage.imageSize',
77
- 'thumbnail',
78
- media.id,
79
- currentPostId
80
- );
81
- if (
82
- has( media, [ 'media_details', 'sizes', fallbackMediaSize ] )
83
- ) {
84
- // Use fallbackMediaSize when mediaSize is not available.
85
- mediaWidth =
86
- media.media_details.sizes[ fallbackMediaSize ].width;
87
- mediaHeight =
88
- media.media_details.sizes[ fallbackMediaSize ].height;
89
- mediaSourceUrl =
90
- media.media_details.sizes[ fallbackMediaSize ].source_url;
91
- } else {
92
- // Use full image size when mediaFallbackSize and mediaSize are not available.
93
- mediaWidth = media.media_details.width;
94
- mediaHeight = media.media_details.height;
95
- mediaSourceUrl = media.source_url;
96
- }
97
- }
114
+ function onDropFiles( filesList ) {
115
+ mediaUpload( {
116
+ allowedTypes: [ 'image' ],
117
+ filesList,
118
+ onFileChange( [ image ] ) {
119
+ if ( isBlobURL( image?.url ) ) {
120
+ setIsLoading( true );
121
+ return;
122
+ }
123
+ onUpdateImage( image );
124
+ setIsLoading( false );
125
+ },
126
+ onError( message ) {
127
+ noticeOperations.removeAllNotices();
128
+ noticeOperations.createErrorNotice( message );
129
+ },
130
+ } );
98
131
  }
99
132
 
100
133
  return (
@@ -165,40 +198,40 @@ function PostFeaturedImage( {
165
198
  />
166
199
  </ResponsiveWrapper>
167
200
  ) }
168
- { !! featuredImageId && ! media && (
169
- <Spinner />
170
- ) }
201
+ { isLoading && <Spinner /> }
171
202
  { ! featuredImageId &&
203
+ ! isLoading &&
172
204
  ( postLabel.set_featured_image ||
173
205
  DEFAULT_SET_FEATURE_IMAGE_LABEL ) }
174
206
  </Button>
175
- <DropZone onFilesDrop={ onDropImage } />
207
+ <DropZone onFilesDrop={ onDropFiles } />
176
208
  </div>
177
209
  ) }
178
210
  value={ featuredImageId }
179
211
  />
180
212
  </MediaUploadCheck>
181
- { !! featuredImageId && media && ! media.isLoading && (
182
- <MediaUploadCheck>
183
- <MediaUpload
184
- title={
185
- postLabel.featured_image ||
186
- DEFAULT_FEATURE_IMAGE_LABEL
187
- }
188
- onSelect={ onUpdateImage }
189
- unstableFeaturedImageFlow
190
- allowedTypes={ ALLOWED_MEDIA_TYPES }
191
- modalClass="editor-post-featured-image__media-modal"
192
- render={ ( { open } ) => (
193
- <Button onClick={ open } variant="secondary">
194
- { __( 'Replace Image' ) }
195
- </Button>
196
- ) }
197
- />
198
- </MediaUploadCheck>
199
- ) }
200
213
  { !! featuredImageId && (
201
214
  <MediaUploadCheck>
215
+ { media && (
216
+ <MediaUpload
217
+ title={
218
+ postLabel.featured_image ||
219
+ DEFAULT_FEATURE_IMAGE_LABEL
220
+ }
221
+ onSelect={ onUpdateImage }
222
+ unstableFeaturedImageFlow
223
+ allowedTypes={ ALLOWED_MEDIA_TYPES }
224
+ modalClass="editor-post-featured-image__media-modal"
225
+ render={ ( { open } ) => (
226
+ <Button
227
+ onClick={ open }
228
+ variant="secondary"
229
+ >
230
+ { __( 'Replace Image' ) }
231
+ </Button>
232
+ ) }
233
+ />
234
+ ) }
202
235
  <Button
203
236
  onClick={ onRemoveImage }
204
237
  variant="link"
@@ -33,3 +33,12 @@
33
33
  }
34
34
  }
35
35
  }
36
+
37
+ // Overwrite rules from Button component packages/components/src/button/style.scss
38
+ .editor-post-save-draft.has-text.has-icon svg {
39
+ margin-right: 0;
40
+ }
41
+
42
+ :root[dir="rtl"] .editor-post-saved-state.has-text.has-icon {
43
+ justify-content: right;
44
+ }
@@ -15,11 +15,11 @@ describe( 'PostSlug', () => {
15
15
 
16
16
  wrapper.find( 'input' ).simulate( 'change', {
17
17
  target: {
18
- value: 'single-post',
18
+ value: 'single',
19
19
  },
20
20
  } );
21
21
 
22
- expect( wrapper.state().editedSlug ).toEqual( 'single-post' );
22
+ expect( wrapper.state().editedSlug ).toEqual( 'single' );
23
23
  } );
24
24
 
25
25
  it( 'should update slug', () => {
@@ -30,11 +30,11 @@ describe( 'PostSlug', () => {
30
30
 
31
31
  wrapper.find( 'input' ).simulate( 'blur', {
32
32
  target: {
33
- value: 'single-post',
33
+ value: 'single',
34
34
  },
35
35
  } );
36
36
 
37
- expect( onUpdateSlug ).toHaveBeenCalledWith( 'single-post' );
37
+ expect( onUpdateSlug ).toHaveBeenCalledWith( 'single' );
38
38
  } );
39
39
  } );
40
40
  } );
@@ -51,6 +51,7 @@ export default function PostTextEditor() {
51
51
  editPost( { content: newValue } );
52
52
  setValue( newValue );
53
53
  setIsDirty( true );
54
+ valueRef.current = newValue;
54
55
  };
55
56
 
56
57
  /**
@@ -66,15 +67,13 @@ export default function PostTextEditor() {
66
67
  }
67
68
  };
68
69
 
69
- useEffect( () => {
70
- valueRef.current = value;
71
- }, [ value ] );
72
-
73
70
  // Ensure changes aren't lost when component unmounts.
74
71
  useEffect( () => {
75
72
  return () => {
76
- const blocks = parse( valueRef.current );
77
- resetEditorBlocks( blocks );
73
+ if ( valueRef.current ) {
74
+ const blocks = parse( valueRef.current );
75
+ resetEditorBlocks( blocks );
76
+ }
78
77
  };
79
78
  }, [] );
80
79
 
@@ -7,7 +7,13 @@ import classnames from 'classnames';
7
7
  * WordPress dependencies
8
8
  */
9
9
  import { __ } from '@wordpress/i18n';
10
- import { useEffect, useRef, useState } from '@wordpress/element';
10
+ import {
11
+ forwardRef,
12
+ useEffect,
13
+ useImperativeHandle,
14
+ useRef,
15
+ useState,
16
+ } from '@wordpress/element';
11
17
  import { decodeEntities } from '@wordpress/html-entities';
12
18
  import { ENTER } from '@wordpress/keycodes';
13
19
  import { useSelect, useDispatch } from '@wordpress/data';
@@ -27,7 +33,7 @@ import { store as editorStore } from '../../store';
27
33
  */
28
34
  const REGEXP_NEWLINES = /[\r\n]+/g;
29
35
 
30
- export default function PostTitle() {
36
+ function PostTitle( _, forwardedRef ) {
31
37
  const ref = useRef();
32
38
  const [ isSelected, setIsSelected ] = useState( false );
33
39
  const { editPost } = useDispatch( editorStore );
@@ -63,6 +69,12 @@ export default function PostTitle() {
63
69
  };
64
70
  }, [] );
65
71
 
72
+ useImperativeHandle( forwardedRef, () => ( {
73
+ focus: () => {
74
+ ref?.current?.focus();
75
+ },
76
+ } ) );
77
+
66
78
  useEffect( () => {
67
79
  if ( ! ref.current ) {
68
80
  return;
@@ -219,3 +231,5 @@ export default function PostTitle() {
219
231
  );
220
232
  /* eslint-enable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */
221
233
  }
234
+
235
+ export default forwardRef( PostTitle );
@@ -2,13 +2,15 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
- import { Component } from '@wordpress/element';
5
+ import { useState } from '@wordpress/element';
6
6
  import {
7
7
  VisuallyHidden,
8
8
  __experimentalConfirmDialog as ConfirmDialog,
9
+ Button,
9
10
  } from '@wordpress/components';
10
- import { withInstanceId, compose } from '@wordpress/compose';
11
- import { withSelect, withDispatch } from '@wordpress/data';
11
+ import { useInstanceId } from '@wordpress/compose';
12
+ import { useSelect, useDispatch } from '@wordpress/data';
13
+ import { close as closeIcon } from '@wordpress/icons';
12
14
 
13
15
  /**
14
16
  * Internal dependencies
@@ -16,172 +18,150 @@ import { withSelect, withDispatch } from '@wordpress/data';
16
18
  import { visibilityOptions } from './utils';
17
19
  import { store as editorStore } from '../../store';
18
20
 
19
- export class PostVisibility extends Component {
20
- constructor( props ) {
21
- super( ...arguments );
21
+ export default function PostVisibility( { onClose } ) {
22
+ const instanceId = useInstanceId( PostVisibility );
22
23
 
23
- this.setPublic = this.setPublic.bind( this );
24
- this.setPrivate = this.setPrivate.bind( this );
25
- this.setPasswordProtected = this.setPasswordProtected.bind( this );
26
- this.updatePassword = this.updatePassword.bind( this );
24
+ const { status, visibility, password } = useSelect( ( select ) => ( {
25
+ status: select( editorStore ).getEditedPostAttribute( 'status' ),
26
+ visibility: select( editorStore ).getEditedPostVisibility(),
27
+ password: select( editorStore ).getEditedPostAttribute( 'password' ),
28
+ } ) );
27
29
 
28
- this.state = {
29
- hasPassword: !! props.password,
30
- showPrivateConfirmDialog: false,
31
- };
32
- }
30
+ const { editPost, savePost } = useDispatch( editorStore );
33
31
 
34
- setPublic() {
35
- const { visibility, onUpdateVisibility, status } = this.props;
32
+ const [ hasPassword, setHasPassword ] = useState( !! password );
33
+ const [ showPrivateConfirmDialog, setShowPrivateConfirmDialog ] = useState(
34
+ false
35
+ );
36
36
 
37
- onUpdateVisibility( visibility === 'private' ? 'draft' : status );
38
- this.setState( { hasPassword: false } );
39
- }
40
-
41
- setPrivate() {
42
- this.setState( { showPrivateConfirmDialog: true } );
43
- }
44
-
45
- confirmPrivate = () => {
46
- const { onUpdateVisibility, onSave } = this.props;
47
-
48
- onUpdateVisibility( 'private' );
49
- this.setState( {
50
- hasPassword: false,
51
- showPrivateConfirmDialog: false,
37
+ const setPublic = () => {
38
+ editPost( {
39
+ status: visibility === 'private' ? 'draft' : status,
40
+ password: '',
52
41
  } );
53
- onSave();
42
+ setHasPassword( false );
54
43
  };
55
44
 
56
- handleDialogCancel = () => {
57
- this.setState( { showPrivateConfirmDialog: false } );
45
+ const setPrivate = () => {
46
+ setShowPrivateConfirmDialog( true );
58
47
  };
59
48
 
60
- setPasswordProtected() {
61
- const { visibility, onUpdateVisibility, status, password } = this.props;
62
-
63
- onUpdateVisibility(
64
- visibility === 'private' ? 'draft' : status,
65
- password || ''
66
- );
67
- this.setState( { hasPassword: true } );
68
- }
49
+ const confirmPrivate = () => {
50
+ editPost( { status: 'private', password: '' } );
51
+ setHasPassword( false );
52
+ setShowPrivateConfirmDialog( false );
53
+ savePost();
54
+ };
69
55
 
70
- updatePassword( event ) {
71
- const { status, onUpdateVisibility } = this.props;
72
- onUpdateVisibility( status, event.target.value );
73
- }
56
+ const handleDialogCancel = () => {
57
+ setShowPrivateConfirmDialog( false );
58
+ };
74
59
 
75
- render() {
76
- const { visibility, password, instanceId } = this.props;
60
+ const setPasswordProtected = () => {
61
+ editPost( {
62
+ status: visibility === 'private' ? 'draft' : status,
63
+ password: password || '',
64
+ } );
65
+ setHasPassword( true );
66
+ };
77
67
 
78
- const visibilityHandlers = {
79
- public: {
80
- onSelect: this.setPublic,
81
- checked: visibility === 'public' && ! this.state.hasPassword,
82
- },
83
- private: {
84
- onSelect: this.setPrivate,
85
- checked: visibility === 'private',
86
- },
87
- password: {
88
- onSelect: this.setPasswordProtected,
89
- checked: this.state.hasPassword,
90
- },
91
- };
68
+ const updatePassword = ( event ) => {
69
+ editPost( { password: event.target.value } );
70
+ };
92
71
 
93
- return [
94
- <fieldset
95
- key="visibility-selector"
96
- className="editor-post-visibility__dialog-fieldset"
97
- >
98
- <legend className="editor-post-visibility__dialog-legend">
99
- { __( 'Post Visibility' ) }
72
+ return (
73
+ <>
74
+ <Button
75
+ className="editor-post-visibility__close"
76
+ isSmall
77
+ icon={ closeIcon }
78
+ onClick={ onClose }
79
+ />
80
+ <fieldset className="editor-post-visibility__fieldset">
81
+ <legend className="editor-post-visibility__legend">
82
+ { __( 'Visibility' ) }
100
83
  </legend>
101
- { visibilityOptions.map( ( { value, label, info } ) => (
102
- <div
103
- key={ value }
104
- className="editor-post-visibility__choice"
105
- >
84
+ <p className="editor-post-visibility__description">
85
+ { __( 'Control how this post is viewed.' ) }
86
+ </p>
87
+ <PostVisibilityChoice
88
+ instanceId={ instanceId }
89
+ value="public"
90
+ label={ visibilityOptions.public.label }
91
+ info={ visibilityOptions.public.info }
92
+ checked={ visibility === 'public' && ! hasPassword }
93
+ onChange={ setPublic }
94
+ />
95
+ <PostVisibilityChoice
96
+ instanceId={ instanceId }
97
+ value="private"
98
+ label={ visibilityOptions.private.label }
99
+ info={ visibilityOptions.private.info }
100
+ checked={ visibility === 'private' }
101
+ onChange={ setPrivate }
102
+ />
103
+ <PostVisibilityChoice
104
+ instanceId={ instanceId }
105
+ value="password"
106
+ label={ visibilityOptions.password.label }
107
+ info={ visibilityOptions.password.info }
108
+ checked={ hasPassword }
109
+ onChange={ setPasswordProtected }
110
+ />
111
+ { hasPassword && (
112
+ <div className="editor-post-visibility__password">
113
+ <VisuallyHidden
114
+ as="label"
115
+ htmlFor={ `editor-post-visibility__password-input-${ instanceId }` }
116
+ >
117
+ { __( 'Create password' ) }
118
+ </VisuallyHidden>
106
119
  <input
107
- type="radio"
108
- name={ `editor-post-visibility__setting-${ instanceId }` }
109
- value={ value }
110
- onChange={ visibilityHandlers[ value ].onSelect }
111
- checked={ visibilityHandlers[ value ].checked }
112
- id={ `editor-post-${ value }-${ instanceId }` }
113
- aria-describedby={ `editor-post-${ value }-${ instanceId }-description` }
114
- className="editor-post-visibility__dialog-radio"
120
+ className="editor-post-visibility__password-input"
121
+ id={ `editor-post-visibility__password-input-${ instanceId }` }
122
+ type="text"
123
+ onChange={ updatePassword }
124
+ value={ password }
125
+ placeholder={ __( 'Use a secure password' ) }
115
126
  />
116
- <label
117
- htmlFor={ `editor-post-${ value }-${ instanceId }` }
118
- className="editor-post-visibility__dialog-label"
119
- >
120
- { label }
121
- </label>
122
- {
123
- <p
124
- id={ `editor-post-${ value }-${ instanceId }-description` }
125
- className="editor-post-visibility__dialog-info"
126
- >
127
- { info }
128
- </p>
129
- }
130
127
  </div>
131
- ) ) }
132
- </fieldset>,
133
- this.state.hasPassword && (
134
- <div
135
- className="editor-post-visibility__dialog-password"
136
- key="password-selector"
137
- >
138
- <VisuallyHidden
139
- as="label"
140
- htmlFor={ `editor-post-visibility__dialog-password-input-${ instanceId }` }
141
- >
142
- { __( 'Create password' ) }
143
- </VisuallyHidden>
144
- <input
145
- className="editor-post-visibility__dialog-password-input"
146
- id={ `editor-post-visibility__dialog-password-input-${ instanceId }` }
147
- type="text"
148
- onChange={ this.updatePassword }
149
- value={ password }
150
- placeholder={ __( 'Use a secure password' ) }
151
- />
152
- </div>
153
- ),
128
+ ) }
129
+ </fieldset>
154
130
  <ConfirmDialog
155
- key="private-publish-confirmation"
156
- isOpen={ this.state.showPrivateConfirmDialog }
157
- onConfirm={ this.confirmPrivate }
158
- onCancel={ this.handleDialogCancel }
131
+ isOpen={ showPrivateConfirmDialog }
132
+ onConfirm={ confirmPrivate }
133
+ onCancel={ handleDialogCancel }
159
134
  >
160
135
  { __( 'Would you like to privately publish this post now?' ) }
161
- </ConfirmDialog>,
162
- ];
163
- }
136
+ </ConfirmDialog>
137
+ </>
138
+ );
164
139
  }
165
140
 
166
- export default compose( [
167
- withSelect( ( select ) => {
168
- const { getEditedPostAttribute, getEditedPostVisibility } = select(
169
- editorStore
170
- );
171
- return {
172
- status: getEditedPostAttribute( 'status' ),
173
- visibility: getEditedPostVisibility(),
174
- password: getEditedPostAttribute( 'password' ),
175
- };
176
- } ),
177
- withDispatch( ( dispatch ) => {
178
- const { savePost, editPost } = dispatch( editorStore );
179
- return {
180
- onSave: savePost,
181
- onUpdateVisibility( status, password = '' ) {
182
- editPost( { status, password } );
183
- },
184
- };
185
- } ),
186
- withInstanceId,
187
- ] )( PostVisibility );
141
+ function PostVisibilityChoice( { instanceId, value, label, info, ...props } ) {
142
+ return (
143
+ <div className="editor-post-visibility__choice">
144
+ <input
145
+ type="radio"
146
+ name={ `editor-post-visibility__setting-${ instanceId }` }
147
+ value={ value }
148
+ id={ `editor-post-${ value }-${ instanceId }` }
149
+ aria-describedby={ `editor-post-${ value }-${ instanceId }-description` }
150
+ className="editor-post-visibility__radio"
151
+ { ...props }
152
+ />
153
+ <label
154
+ htmlFor={ `editor-post-${ value }-${ instanceId }` }
155
+ className="editor-post-visibility__label"
156
+ >
157
+ { label }
158
+ </label>
159
+ <p
160
+ id={ `editor-post-${ value }-${ instanceId }-description` }
161
+ className="editor-post-visibility__info"
162
+ >
163
+ { info }
164
+ </p>
165
+ </div>
166
+ );
167
+ }
@@ -1,12 +1,7 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { find } from 'lodash';
5
-
6
1
  /**
7
2
  * WordPress dependencies
8
3
  */
9
- import { withSelect } from '@wordpress/data';
4
+ import { useSelect } from '@wordpress/data';
10
5
 
11
6
  /**
12
7
  * Internal dependencies
@@ -14,13 +9,9 @@ import { withSelect } from '@wordpress/data';
14
9
  import { visibilityOptions } from './utils';
15
10
  import { store as editorStore } from '../../store';
16
11
 
17
- function PostVisibilityLabel( { visibility } ) {
18
- const getVisibilityLabel = () =>
19
- find( visibilityOptions, { value: visibility } ).label;
20
-
21
- return getVisibilityLabel( visibility );
12
+ export default function PostVisibilityLabel() {
13
+ const visibility = useSelect( ( select ) =>
14
+ select( editorStore ).getEditedPostVisibility()
15
+ );
16
+ return visibilityOptions[ visibility ]?.label;
22
17
  }
23
-
24
- export default withSelect( ( select ) => ( {
25
- visibility: select( editorStore ).getEditedPostVisibility(),
26
- } ) )( PostVisibilityLabel );