@wordpress/editor 12.6.0 → 12.9.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 (103) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/components/editor-help/help-section-title.native.js +43 -0
  3. package/build/components/editor-help/help-section-title.native.js.map +1 -0
  4. package/build/components/editor-help/help-topic-row.native.js +3 -2
  5. package/build/components/editor-help/help-topic-row.native.js.map +1 -1
  6. package/build/components/editor-help/icon-move-blocks.native.js +23 -0
  7. package/build/components/editor-help/icon-move-blocks.native.js.map +1 -0
  8. package/build/components/editor-help/index.native.js +10 -11
  9. package/build/components/editor-help/index.native.js.map +1 -1
  10. package/build/components/editor-help/move-blocks.native.js +14 -2
  11. package/build/components/editor-help/move-blocks.native.js.map +1 -1
  12. package/build/components/editor-help/view-sections.native.js +21 -5
  13. package/build/components/editor-help/view-sections.native.js.map +1 -1
  14. package/build/components/post-featured-image/index.js +84 -41
  15. package/build/components/post-featured-image/index.js.map +1 -1
  16. package/build/components/post-schedule/index.js +11 -18
  17. package/build/components/post-schedule/index.js.map +1 -1
  18. package/build/components/post-taxonomies/flat-term-selector.js +2 -2
  19. package/build/components/post-taxonomies/flat-term-selector.js.map +1 -1
  20. package/build/components/post-taxonomies/index.js +7 -1
  21. package/build/components/post-taxonomies/index.js.map +1 -1
  22. package/build/components/post-text-editor/index.js +12 -1
  23. package/build/components/post-text-editor/index.js.map +1 -1
  24. package/build/components/post-visibility/index.js +132 -167
  25. package/build/components/post-visibility/index.js.map +1 -1
  26. package/build/components/post-visibility/label.js +5 -22
  27. package/build/components/post-visibility/label.js.map +1 -1
  28. package/build/components/post-visibility/utils.js +14 -13
  29. package/build/components/post-visibility/utils.js.map +1 -1
  30. package/build/components/provider/index.native.js +3 -1
  31. package/build/components/provider/index.native.js.map +1 -1
  32. package/build/components/provider/use-block-editor-settings.js +15 -9
  33. package/build/components/provider/use-block-editor-settings.js.map +1 -1
  34. package/build/store/selectors.js +2 -2
  35. package/build/store/selectors.js.map +1 -1
  36. package/build-module/components/editor-help/help-section-title.native.js +31 -0
  37. package/build-module/components/editor-help/help-section-title.native.js.map +1 -0
  38. package/build-module/components/editor-help/help-topic-row.native.js +3 -2
  39. package/build-module/components/editor-help/help-topic-row.native.js.map +1 -1
  40. package/build-module/components/editor-help/icon-move-blocks.native.js +13 -0
  41. package/build-module/components/editor-help/icon-move-blocks.native.js.map +1 -0
  42. package/build-module/components/editor-help/index.native.js +10 -12
  43. package/build-module/components/editor-help/index.native.js.map +1 -1
  44. package/build-module/components/editor-help/move-blocks.native.js +15 -3
  45. package/build-module/components/editor-help/move-blocks.native.js.map +1 -1
  46. package/build-module/components/editor-help/view-sections.native.js +22 -6
  47. package/build-module/components/editor-help/view-sections.native.js.map +1 -1
  48. package/build-module/components/post-featured-image/index.js +86 -42
  49. package/build-module/components/post-featured-image/index.js.map +1 -1
  50. package/build-module/components/post-schedule/index.js +12 -19
  51. package/build-module/components/post-schedule/index.js.map +1 -1
  52. package/build-module/components/post-taxonomies/flat-term-selector.js +2 -2
  53. package/build-module/components/post-taxonomies/flat-term-selector.js.map +1 -1
  54. package/build-module/components/post-taxonomies/index.js +7 -1
  55. package/build-module/components/post-taxonomies/index.js.map +1 -1
  56. package/build-module/components/post-text-editor/index.js +13 -2
  57. package/build-module/components/post-text-editor/index.js.map +1 -1
  58. package/build-module/components/post-visibility/index.js +132 -166
  59. package/build-module/components/post-visibility/index.js.map +1 -1
  60. package/build-module/components/post-visibility/label.js +5 -20
  61. package/build-module/components/post-visibility/label.js.map +1 -1
  62. package/build-module/components/post-visibility/utils.js +14 -13
  63. package/build-module/components/post-visibility/utils.js.map +1 -1
  64. package/build-module/components/provider/index.native.js +2 -1
  65. package/build-module/components/provider/index.native.js.map +1 -1
  66. package/build-module/components/provider/use-block-editor-settings.js +16 -10
  67. package/build-module/components/provider/use-block-editor-settings.js.map +1 -1
  68. package/build-module/store/selectors.js +2 -2
  69. package/build-module/store/selectors.js.map +1 -1
  70. package/build-style/style-rtl.css +51 -52
  71. package/build-style/style.css +51 -52
  72. package/package.json +29 -28
  73. package/src/components/autosave-monitor/test/index.js +3 -0
  74. package/src/components/editor-help/help-section-title.native.js +29 -0
  75. package/src/components/editor-help/help-topic-row.native.js +2 -2
  76. package/src/components/editor-help/icon-move-blocks.native.js +10 -0
  77. package/src/components/editor-help/images/drag-and-drop-dark.png +0 -0
  78. package/src/components/editor-help/images/drag-and-drop-dark@2x.png +0 -0
  79. package/src/components/editor-help/images/drag-and-drop-dark@3x.png +0 -0
  80. package/src/components/editor-help/images/drag-and-drop-light.png +0 -0
  81. package/src/components/editor-help/images/drag-and-drop-light@2x.png +0 -0
  82. package/src/components/editor-help/images/drag-and-drop-light@3x.png +0 -0
  83. package/src/components/editor-help/index.native.js +20 -22
  84. package/src/components/editor-help/move-blocks.native.js +22 -2
  85. package/src/components/editor-help/style.scss +36 -4
  86. package/src/components/editor-help/test/index.native.js +1 -1
  87. package/src/components/editor-help/view-sections.native.js +23 -8
  88. package/src/components/post-featured-image/index.js +102 -69
  89. package/src/components/post-saved-state/style.scss +9 -0
  90. package/src/components/post-schedule/index.js +6 -13
  91. package/src/components/post-slug/test/index.js +4 -4
  92. package/src/components/post-taxonomies/flat-term-selector.js +5 -2
  93. package/src/components/post-taxonomies/index.js +3 -1
  94. package/src/components/post-text-editor/index.js +13 -1
  95. package/src/components/post-visibility/index.js +130 -150
  96. package/src/components/post-visibility/label.js +6 -15
  97. package/src/components/post-visibility/style.scss +25 -20
  98. package/src/components/post-visibility/utils.js +7 -12
  99. package/src/components/provider/index.native.js +2 -1
  100. package/src/components/provider/use-block-editor-settings.js +28 -12
  101. package/src/components/table-of-contents/style.scss +1 -3
  102. package/src/store/selectors.js +4 -2
  103. package/src/store/test/selectors.js +5 -5
@@ -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
+ }
@@ -3,8 +3,8 @@
3
3
  */
4
4
  import { __experimentalGetSettings } from '@wordpress/date';
5
5
  import { useDispatch, useSelect } from '@wordpress/data';
6
- import { DateTimePicker } from '@wordpress/components';
7
- import { useRef, useState, useMemo } from '@wordpress/element';
6
+ import { __experimentalPublishDateTimePicker as PublishDateTimePicker } from '@wordpress/block-editor';
7
+ import { useState, useMemo } from '@wordpress/element';
8
8
  import { store as coreStore } from '@wordpress/core-data';
9
9
 
10
10
  /**
@@ -21,7 +21,7 @@ function getDayOfTheMonth( date = new Date(), firstDay = true ) {
21
21
  ).toISOString();
22
22
  }
23
23
 
24
- export default function PostSchedule() {
24
+ export default function PostSchedule( { onClose } ) {
25
25
  const { postDate, postType } = useSelect(
26
26
  ( select ) => ( {
27
27
  postDate: select( editorStore ).getEditedPostAttribute( 'date' ),
@@ -61,7 +61,6 @@ export default function PostSchedule() {
61
61
  [ eventsByPostType ]
62
62
  );
63
63
 
64
- const ref = useRef();
65
64
  const settings = __experimentalGetSettings();
66
65
 
67
66
  // To know if the current timezone is a 12 hour time with look for "a" in the time format
@@ -75,20 +74,14 @@ export default function PostSchedule() {
75
74
  .join( '' ) // Reverse the string and test for "a" not followed by a slash.
76
75
  );
77
76
 
78
- function onChange( newDate ) {
79
- onUpdateDate( newDate );
80
- const { ownerDocument } = ref.current;
81
- ownerDocument.activeElement.blur();
82
- }
83
-
84
77
  return (
85
- <DateTimePicker
86
- ref={ ref }
78
+ <PublishDateTimePicker
87
79
  currentDate={ postDate }
88
- onChange={ onChange }
80
+ onChange={ onUpdateDate }
89
81
  is12Hour={ is12HourTime }
90
82
  events={ events }
91
83
  onMonthPreviewed={ setPreviewedMonth }
84
+ onClose={ onClose }
92
85
  />
93
86
  );
94
87
  }
@@ -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
  } );
@@ -177,7 +177,7 @@ function FlatTermSelector( { slug } ) {
177
177
  // while core data makes REST API requests.
178
178
  useEffect( () => {
179
179
  if ( hasResolvedTerms ) {
180
- const newValues = terms.map( ( term ) =>
180
+ const newValues = ( terms ?? [] ).map( ( term ) =>
181
181
  unescapeString( term.name )
182
182
  );
183
183
 
@@ -202,7 +202,10 @@ function FlatTermSelector( { slug } ) {
202
202
  }
203
203
 
204
204
  function onChange( termNames ) {
205
- const availableTerms = [ ...terms, ...( searchResults ?? [] ) ];
205
+ const availableTerms = [
206
+ ...( terms ?? [] ),
207
+ ...( searchResults ?? [] ),
208
+ ];
206
209
  const uniqueTerms = uniqBy( termNames, ( term ) => term.toLowerCase() );
207
210
  const newTermNames = uniqueTerms.filter(
208
211
  ( termName ) =>
@@ -28,7 +28,9 @@ export function PostTaxonomies( {
28
28
  );
29
29
  const visibleTaxonomies = filter(
30
30
  availableTaxonomies,
31
- ( taxonomy ) => taxonomy.visibility.show_ui
31
+ // In some circumstances .visibility can end up as undefined so optional chaining operator required.
32
+ // https://github.com/WordPress/gutenberg/issues/40326
33
+ ( taxonomy ) => taxonomy.visibility?.show_ui
32
34
  );
33
35
  return visibleTaxonomies.map( ( taxonomy ) => {
34
36
  const TaxonomyComponent = taxonomy.hierarchical
@@ -7,7 +7,7 @@ import Textarea from 'react-autosize-textarea';
7
7
  * WordPress dependencies
8
8
  */
9
9
  import { __ } from '@wordpress/i18n';
10
- import { useState } from '@wordpress/element';
10
+ import { useEffect, useState, useRef } from '@wordpress/element';
11
11
  import { parse } from '@wordpress/blocks';
12
12
  import { useDispatch, useSelect } from '@wordpress/data';
13
13
  import { useInstanceId } from '@wordpress/compose';
@@ -29,6 +29,7 @@ export default function PostTextEditor() {
29
29
  const [ value, setValue ] = useState( postContent );
30
30
  const [ isDirty, setIsDirty ] = useState( false );
31
31
  const instanceId = useInstanceId( PostTextEditor );
32
+ const valueRef = useRef();
32
33
 
33
34
  if ( ! isDirty && value !== postContent ) {
34
35
  setValue( postContent );
@@ -50,6 +51,7 @@ export default function PostTextEditor() {
50
51
  editPost( { content: newValue } );
51
52
  setValue( newValue );
52
53
  setIsDirty( true );
54
+ valueRef.current = newValue;
53
55
  };
54
56
 
55
57
  /**
@@ -65,6 +67,16 @@ export default function PostTextEditor() {
65
67
  }
66
68
  };
67
69
 
70
+ // Ensure changes aren't lost when component unmounts.
71
+ useEffect( () => {
72
+ return () => {
73
+ if ( valueRef.current ) {
74
+ const blocks = parse( valueRef.current );
75
+ resetEditorBlocks( blocks );
76
+ }
77
+ };
78
+ }, [] );
79
+
68
80
  return (
69
81
  <>
70
82
  <VisuallyHidden