@wordpress/editor 13.2.0 → 13.3.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 (122) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/error-boundary/index.js +24 -30
  3. package/build/components/error-boundary/index.js.map +1 -1
  4. package/build/components/media-categories/index.js +237 -0
  5. package/build/components/media-categories/index.js.map +1 -0
  6. package/build/components/page-attributes/parent.js +1 -1
  7. package/build/components/page-attributes/parent.js.map +1 -1
  8. package/build/components/post-publish-panel/postpublish.js +1 -0
  9. package/build/components/post-publish-panel/postpublish.js.map +1 -1
  10. package/build/components/post-slug/index.js +1 -0
  11. package/build/components/post-slug/index.js.map +1 -1
  12. package/build/components/post-taxonomies/hierarchical-term-selector.js +7 -3
  13. package/build/components/post-taxonomies/hierarchical-term-selector.js.map +1 -1
  14. package/build/components/post-template/index.js +7 -4
  15. package/build/components/post-template/index.js.map +1 -1
  16. package/build/components/post-url/index.js +1 -0
  17. package/build/components/post-url/index.js.map +1 -1
  18. package/build/components/provider/index.js +26 -8
  19. package/build/components/provider/index.js.map +1 -1
  20. package/build/components/provider/index.native.js +21 -14
  21. package/build/components/provider/index.native.js.map +1 -1
  22. package/build/components/provider/use-block-editor-settings.js +7 -4
  23. package/build/components/provider/use-block-editor-settings.js.map +1 -1
  24. package/build/components/provider/use-block-editor-settings.native.js +1 -2
  25. package/build/components/provider/use-block-editor-settings.native.js.map +1 -1
  26. package/build/components/table-of-contents/index.js +3 -1
  27. package/build/components/table-of-contents/index.js.map +1 -1
  28. package/build/components/unsaved-changes-warning/index.js +1 -1
  29. package/build/components/unsaved-changes-warning/index.js.map +1 -1
  30. package/build/experiments.js +20 -0
  31. package/build/experiments.js.map +1 -0
  32. package/build/hooks/default-autocompleters.js +2 -7
  33. package/build/hooks/default-autocompleters.js.map +1 -1
  34. package/build/index.js +14 -0
  35. package/build/index.js.map +1 -1
  36. package/build/index.native.js +14 -0
  37. package/build/index.native.js.map +1 -1
  38. package/build/lockUnlock.js +19 -0
  39. package/build/lockUnlock.js.map +1 -0
  40. package/build/store/defaults.js +1 -2
  41. package/build/store/defaults.js.map +1 -1
  42. package/build/store/selectors.js +1 -1
  43. package/build/store/selectors.js.map +1 -1
  44. package/build/utils/terms.js +9 -5
  45. package/build/utils/terms.js.map +1 -1
  46. package/build-module/components/error-boundary/index.js +24 -30
  47. package/build-module/components/error-boundary/index.js.map +1 -1
  48. package/build-module/components/media-categories/index.js +225 -0
  49. package/build-module/components/media-categories/index.js.map +1 -0
  50. package/build-module/components/page-attributes/parent.js +2 -2
  51. package/build-module/components/page-attributes/parent.js.map +1 -1
  52. package/build-module/components/post-publish-panel/postpublish.js +1 -0
  53. package/build-module/components/post-publish-panel/postpublish.js.map +1 -1
  54. package/build-module/components/post-slug/index.js +1 -0
  55. package/build-module/components/post-slug/index.js.map +1 -1
  56. package/build-module/components/post-taxonomies/hierarchical-term-selector.js +8 -5
  57. package/build-module/components/post-taxonomies/hierarchical-term-selector.js.map +1 -1
  58. package/build-module/components/post-template/index.js +8 -5
  59. package/build-module/components/post-template/index.js.map +1 -1
  60. package/build-module/components/post-url/index.js +1 -0
  61. package/build-module/components/post-url/index.js.map +1 -1
  62. package/build-module/components/provider/index.js +21 -9
  63. package/build-module/components/provider/index.js.map +1 -1
  64. package/build-module/components/provider/index.native.js +20 -12
  65. package/build-module/components/provider/index.native.js.map +1 -1
  66. package/build-module/components/provider/use-block-editor-settings.js +5 -5
  67. package/build-module/components/provider/use-block-editor-settings.js.map +1 -1
  68. package/build-module/components/provider/use-block-editor-settings.native.js +1 -2
  69. package/build-module/components/provider/use-block-editor-settings.native.js.map +1 -1
  70. package/build-module/components/table-of-contents/index.js +3 -1
  71. package/build-module/components/table-of-contents/index.js.map +1 -1
  72. package/build-module/components/unsaved-changes-warning/index.js +1 -1
  73. package/build-module/components/unsaved-changes-warning/index.js.map +1 -1
  74. package/build-module/experiments.js +10 -0
  75. package/build-module/experiments.js.map +1 -0
  76. package/build-module/hooks/default-autocompleters.js +2 -6
  77. package/build-module/hooks/default-autocompleters.js.map +1 -1
  78. package/build-module/index.js +1 -0
  79. package/build-module/index.js.map +1 -1
  80. package/build-module/index.native.js +1 -0
  81. package/build-module/index.native.js.map +1 -1
  82. package/build-module/lockUnlock.js +9 -0
  83. package/build-module/lockUnlock.js.map +1 -0
  84. package/build-module/store/defaults.js +1 -2
  85. package/build-module/store/defaults.js.map +1 -1
  86. package/build-module/store/selectors.js +1 -1
  87. package/build-module/store/selectors.js.map +1 -1
  88. package/build-module/utils/terms.js +9 -6
  89. package/build-module/utils/terms.js.map +1 -1
  90. package/build-style/style-rtl.css +0 -3
  91. package/build-style/style.css +0 -3
  92. package/package.json +30 -29
  93. package/src/components/autosave-monitor/test/index.js +8 -2
  94. package/src/components/editor-help/test/index.native.js +5 -5
  95. package/src/components/error-boundary/index.js +24 -37
  96. package/src/components/media-categories/index.js +247 -0
  97. package/src/components/page-attributes/parent.js +2 -2
  98. package/src/components/page-attributes/test/order.js +4 -14
  99. package/src/components/post-preview-button/test/index.js +5 -17
  100. package/src/components/post-publish-button/test/index.js +5 -17
  101. package/src/components/post-publish-panel/postpublish.js +1 -0
  102. package/src/components/post-publish-panel/style.scss +1 -5
  103. package/src/components/post-publish-panel/test/__snapshots__/index.js.snap +2 -18
  104. package/src/components/post-saved-state/test/index.js +1 -5
  105. package/src/components/post-slug/index.js +1 -0
  106. package/src/components/post-taxonomies/hierarchical-term-selector.js +23 -17
  107. package/src/components/post-template/index.js +3 -4
  108. package/src/components/post-url/index.js +1 -0
  109. package/src/components/provider/index.js +120 -91
  110. package/src/components/provider/index.native.js +26 -17
  111. package/src/components/provider/use-block-editor-settings.js +60 -49
  112. package/src/components/provider/use-block-editor-settings.native.js +1 -2
  113. package/src/components/table-of-contents/index.js +3 -1
  114. package/src/components/unsaved-changes-warning/index.js +1 -1
  115. package/src/experiments.js +10 -0
  116. package/src/hooks/default-autocompleters.js +1 -6
  117. package/src/index.js +1 -0
  118. package/src/index.native.js +1 -0
  119. package/src/lockUnlock.js +9 -0
  120. package/src/store/defaults.js +0 -1
  121. package/src/store/selectors.js +1 -1
  122. package/src/utils/terms.js +8 -5
@@ -14,6 +14,18 @@ import { doAction } from '@wordpress/hooks';
14
14
  */
15
15
  import { store as editorStore } from '../../store';
16
16
 
17
+ function getContent() {
18
+ try {
19
+ // While `select` in a component is generally discouraged, it is
20
+ // used here because it (a) reduces the chance of data loss in the
21
+ // case of additional errors by performing a direct retrieval and
22
+ // (b) avoids the performance cost associated with unnecessary
23
+ // content serialization throughout the lifetime of a non-erroring
24
+ // application.
25
+ return select( editorStore ).getEditedPostContent();
26
+ } catch ( error ) {}
27
+ }
28
+
17
29
  function CopyButton( { text, children } ) {
18
30
  const ref = useCopyToClipboard( text );
19
31
  return (
@@ -27,34 +39,17 @@ class ErrorBoundary extends Component {
27
39
  constructor() {
28
40
  super( ...arguments );
29
41
 
30
- this.reboot = this.reboot.bind( this );
31
- this.getContent = this.getContent.bind( this );
32
-
33
42
  this.state = {
34
43
  error: null,
35
44
  };
36
45
  }
37
46
 
38
47
  componentDidCatch( error ) {
39
- this.setState( { error } );
40
-
41
48
  doAction( 'editor.ErrorBoundary.errorLogged', error );
42
49
  }
43
50
 
44
- reboot() {
45
- this.props.onError();
46
- }
47
-
48
- getContent() {
49
- try {
50
- // While `select` in a component is generally discouraged, it is
51
- // used here because it (a) reduces the chance of data loss in the
52
- // case of additional errors by performing a direct retrieval and
53
- // (b) avoids the performance cost associated with unnecessary
54
- // content serialization throughout the lifetime of a non-erroring
55
- // application.
56
- return select( editorStore ).getEditedPostContent();
57
- } catch ( error ) {}
51
+ static getDerivedStateFromError( error ) {
52
+ return { error };
58
53
  }
59
54
 
60
55
  render() {
@@ -63,25 +58,17 @@ class ErrorBoundary extends Component {
63
58
  return this.props.children;
64
59
  }
65
60
 
61
+ const actions = [
62
+ <CopyButton key="copy-post" text={ getContent }>
63
+ { __( 'Copy Post Text' ) }
64
+ </CopyButton>,
65
+ <CopyButton key="copy-error" text={ error.stack }>
66
+ { __( 'Copy Error' ) }
67
+ </CopyButton>,
68
+ ];
69
+
66
70
  return (
67
- <Warning
68
- className="editor-error-boundary"
69
- actions={ [
70
- <Button
71
- key="recovery"
72
- onClick={ this.reboot }
73
- variant="secondary"
74
- >
75
- { __( 'Attempt Recovery' ) }
76
- </Button>,
77
- <CopyButton key="copy-post" text={ this.getContent }>
78
- { __( 'Copy Post Text' ) }
79
- </CopyButton>,
80
- <CopyButton key="copy-error" text={ error.stack }>
81
- { __( 'Copy Error' ) }
82
- </CopyButton>,
83
- ] }
84
- >
71
+ <Warning className="editor-error-boundary" actions={ actions }>
85
72
  { __( 'The editor has encountered an unexpected error.' ) }
86
73
  </Warning>
87
74
  );
@@ -0,0 +1,247 @@
1
+ /**
2
+ * The `editor` settings here need to be in sync with the corresponding ones in `editor` package.
3
+ * See `packages/editor/src/components/media-categories/index.js`.
4
+ *
5
+ * In the future we could consider creating an Openvese package that can be used in both `editor` and `site-editor`.
6
+ * The rest of the settings would still need to be in sync though.
7
+ */
8
+
9
+ /**
10
+ * WordPress dependencies
11
+ */
12
+ import { __, sprintf, _x } from '@wordpress/i18n';
13
+ import { resolveSelect } from '@wordpress/data';
14
+ import { decodeEntities } from '@wordpress/html-entities';
15
+
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ import { store as coreStore } from '@wordpress/core-data';
20
+
21
+ /** @typedef {import('@wordpress/block-editor').InserterMediaRequest} InserterMediaRequest */
22
+ /** @typedef {import('@wordpress/block-editor').InserterMediaItem} InserterMediaItem */
23
+ /**
24
+ * Interface for inserter media category labels.
25
+ *
26
+ * @typedef {Object} InserterMediaCategoryLabels
27
+ * @property {string} name General name of the media category. It's used in the inserter media items list.
28
+ * @property {string} [search_items='Search'] Label for searching items. Default is ‘Search Posts’ / ‘Search Pages’.
29
+ */
30
+ /**
31
+ * Interface for inserter media category.
32
+ *
33
+ * @typedef {Object} InserterMediaCategory
34
+ * @property {string} name The name of the media category, that should be unique among all media categories.
35
+ * @property {InserterMediaCategoryLabels} labels Labels for the media category.
36
+ * @property {('image'|'audio'|'video')} mediaType The media type of the media category.
37
+ * @property {(InserterMediaRequest) => Promise<InserterMediaItem[]>} fetch The function to fetch media items for the category.
38
+ * @property {(InserterMediaItem) => string} [getReportUrl] If the media category supports reporting media items, this function should return
39
+ * the report url for the media item. It accepts the `InserterMediaItem` as an argument.
40
+ * @property {boolean} [isExternalResource] If the media category is an external resource, this should be set to true.
41
+ * This is used to avoid making a request to the external resource when the user
42
+ * opens the inserter for the first time.
43
+ */
44
+
45
+ const getExternalLink = ( url, text ) =>
46
+ `<a ${ getExternalLinkAttributes( url ) }>${ text }</a>`;
47
+
48
+ const getExternalLinkAttributes = ( url ) =>
49
+ `href="${ url }" target="_blank" rel="noreferrer noopener"`;
50
+
51
+ const getOpenverseLicense = ( license, licenseVersion ) => {
52
+ let licenseName = license.trim();
53
+ // PDM has no abbreviation
54
+ if ( license !== 'pdm' ) {
55
+ licenseName = license.toUpperCase().replace( 'SAMPLING', 'Sampling' );
56
+ }
57
+ // If version is known, append version to the name.
58
+ // The license has to have a version to be valid. Only
59
+ // PDM (public domain mark) doesn't have a version.
60
+ if ( licenseVersion ) {
61
+ licenseName += ` ${ licenseVersion }`;
62
+ }
63
+ // For licenses other than public-domain marks, prepend 'CC' to the name.
64
+ if ( ! [ 'pdm', 'cc0' ].includes( license ) ) {
65
+ licenseName = `CC ${ licenseName }`;
66
+ }
67
+ return licenseName;
68
+ };
69
+
70
+ const getOpenverseCaption = ( item ) => {
71
+ const {
72
+ title,
73
+ foreign_landing_url: foreignLandingUrl,
74
+ creator,
75
+ creator_url: creatorUrl,
76
+ license,
77
+ license_version: licenseVersion,
78
+ license_url: licenseUrl,
79
+ } = item;
80
+ const fullLicense = getOpenverseLicense( license, licenseVersion );
81
+ const _creator = decodeEntities( creator );
82
+ let _caption;
83
+ if ( _creator ) {
84
+ _caption = title
85
+ ? sprintf(
86
+ // translators: %1s: Title of a media work from Openverse; %2s: Name of the work's creator; %3s: Work's licence e.g: "CC0 1.0".
87
+ _x( '"%1$s" by %2$s/ %3$s', 'caption' ),
88
+ getExternalLink(
89
+ foreignLandingUrl,
90
+ decodeEntities( title )
91
+ ),
92
+ creatorUrl
93
+ ? getExternalLink( creatorUrl, _creator )
94
+ : _creator,
95
+ licenseUrl
96
+ ? getExternalLink(
97
+ `${ licenseUrl }?ref=openverse`,
98
+ fullLicense
99
+ )
100
+ : fullLicense
101
+ )
102
+ : sprintf(
103
+ // translators: %1s: Link attributes for a given Openverse media work; %2s: Name of the work's creator; %3s: Works's licence e.g: "CC0 1.0".
104
+ _x( '<a %1$s>Work</a> by %2$s/ %3$s', 'caption' ),
105
+ getExternalLinkAttributes( foreignLandingUrl ),
106
+ creatorUrl
107
+ ? getExternalLink( creatorUrl, _creator )
108
+ : _creator,
109
+ licenseUrl
110
+ ? getExternalLink(
111
+ `${ licenseUrl }?ref=openverse`,
112
+ fullLicense
113
+ )
114
+ : fullLicense
115
+ );
116
+ } else {
117
+ _caption = title
118
+ ? sprintf(
119
+ // translators: %1s: Title of a media work from Openverse; %2s: Work's licence e.g: "CC0 1.0".
120
+ _x( '"%1$s"/ %2$s', 'caption' ),
121
+ getExternalLink(
122
+ foreignLandingUrl,
123
+ decodeEntities( title )
124
+ ),
125
+ licenseUrl
126
+ ? getExternalLink(
127
+ `${ licenseUrl }?ref=openverse`,
128
+ fullLicense
129
+ )
130
+ : fullLicense
131
+ )
132
+ : sprintf(
133
+ // translators: %1s: Link attributes for a given Openverse media work; %2s: Works's licence e.g: "CC0 1.0".
134
+ _x( '<a %1$s>Work</a>/ %3$s', 'caption' ),
135
+ getExternalLinkAttributes( foreignLandingUrl ),
136
+ licenseUrl
137
+ ? getExternalLink(
138
+ `${ licenseUrl }?ref=openverse`,
139
+ fullLicense
140
+ )
141
+ : fullLicense
142
+ );
143
+ }
144
+ return _caption.replace( /\s{2}/g, ' ' );
145
+ };
146
+
147
+ const coreMediaFetch = async ( query = {} ) => {
148
+ const mediaItems = await resolveSelect( coreStore ).getMediaItems( {
149
+ ...query,
150
+ orderBy: !! query?.search ? 'relevance' : 'date',
151
+ } );
152
+ return mediaItems.map( ( mediaItem ) => ( {
153
+ ...mediaItem,
154
+ alt: mediaItem.alt_text,
155
+ url: mediaItem.source_url,
156
+ previewUrl: mediaItem.media_details?.sizes?.medium?.source_url,
157
+ caption: mediaItem.caption?.raw,
158
+ } ) );
159
+ };
160
+
161
+ /** @type {InserterMediaCategory[]} */
162
+ const inserterMediaCategories = [
163
+ {
164
+ name: 'images',
165
+ labels: {
166
+ name: __( 'Images' ),
167
+ search_items: __( 'Search images' ),
168
+ },
169
+ mediaType: 'image',
170
+ async fetch( query = {} ) {
171
+ return coreMediaFetch( { ...query, media_type: 'image' } );
172
+ },
173
+ },
174
+ {
175
+ name: 'videos',
176
+ labels: {
177
+ name: __( 'Videos' ),
178
+ search_items: __( 'Search videos' ),
179
+ },
180
+ mediaType: 'video',
181
+ async fetch( query = {} ) {
182
+ return coreMediaFetch( { ...query, media_type: 'video' } );
183
+ },
184
+ },
185
+ {
186
+ name: 'audio',
187
+ labels: {
188
+ name: __( 'Audio' ),
189
+ search_items: __( 'Search audio' ),
190
+ },
191
+ mediaType: 'audio',
192
+ async fetch( query = {} ) {
193
+ return coreMediaFetch( { ...query, media_type: 'audio' } );
194
+ },
195
+ },
196
+ {
197
+ name: 'openverse',
198
+ labels: {
199
+ name: __( 'Openverse' ),
200
+ search_items: __( 'Search Openverse' ),
201
+ },
202
+ mediaType: 'image',
203
+ async fetch( query = {} ) {
204
+ const defaultArgs = {
205
+ mature: false,
206
+ excluded_source: 'flickr,inaturalist,wikimedia',
207
+ license: 'pdm,cc0',
208
+ };
209
+ const finalQuery = { ...query, ...defaultArgs };
210
+ const mapFromInserterMediaRequest = {
211
+ per_page: 'page_size',
212
+ search: 'q',
213
+ };
214
+ const url = new URL(
215
+ 'https://api.openverse.engineering/v1/images/'
216
+ );
217
+ Object.entries( finalQuery ).forEach( ( [ key, value ] ) => {
218
+ const queryKey = mapFromInserterMediaRequest[ key ] || key;
219
+ url.searchParams.set( queryKey, value );
220
+ } );
221
+ const response = await window.fetch( url, {
222
+ headers: {
223
+ 'User-Agent': 'WordPress/inserter-media-fetch',
224
+ },
225
+ } );
226
+ const jsonResponse = await response.json();
227
+ const results = jsonResponse.results;
228
+ return results.map( ( result ) => ( {
229
+ ...result,
230
+ // This is a temp solution for better titles, until Openverse API
231
+ // completes the cleaning up of some titles of their upstream data.
232
+ title: result.title?.toLowerCase().startsWith( 'file:' )
233
+ ? result.title.slice( 5 )
234
+ : result.title,
235
+ sourceId: result.id,
236
+ id: undefined,
237
+ caption: getOpenverseCaption( result ),
238
+ previewUrl: result.thumbnail,
239
+ } ) );
240
+ },
241
+ getReportUrl: ( { sourceId } ) =>
242
+ `https://wordpress.org/openverse/image/${ sourceId }/report/`,
243
+ isExternalResource: true,
244
+ },
245
+ ];
246
+
247
+ export default inserterMediaCategories;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { get, unescape as unescapeString } from 'lodash';
4
+ import { get } from 'lodash';
5
5
  import removeAccents from 'remove-accents';
6
6
 
7
7
  /**
@@ -93,7 +93,7 @@ export function PageAttributesParent() {
93
93
  {
94
94
  value: treeNode.id,
95
95
  label:
96
- '— '.repeat( level ) + unescapeString( treeNode.name ),
96
+ '— '.repeat( level ) + decodeEntities( treeNode.name ),
97
97
  rawName: treeNode.name,
98
98
  },
99
99
  ...getOptionsFromTree( treeNode.children || [], level + 1 ),
@@ -9,8 +9,6 @@ import userEvent from '@testing-library/user-event';
9
9
  */
10
10
  import { PageAttributesOrder } from '../order';
11
11
 
12
- jest.useFakeTimers();
13
-
14
12
  describe( 'PageAttributesOrder', () => {
15
13
  /**
16
14
  * When starting to type inside the spinbutton, select the current value
@@ -22,9 +20,7 @@ describe( 'PageAttributesOrder', () => {
22
20
  };
23
21
 
24
22
  it( 'should reject invalid input', async () => {
25
- const user = userEvent.setup( {
26
- advanceTimers: jest.advanceTimersByTime,
27
- } );
23
+ const user = userEvent.setup();
28
24
 
29
25
  const onUpdateOrder = jest.fn();
30
26
 
@@ -41,9 +37,7 @@ describe( 'PageAttributesOrder', () => {
41
37
  } );
42
38
 
43
39
  it( 'should update with zero input', async () => {
44
- const user = userEvent.setup( {
45
- advanceTimers: jest.advanceTimersByTime,
46
- } );
40
+ const user = userEvent.setup();
47
41
 
48
42
  const onUpdateOrder = jest.fn();
49
43
 
@@ -59,9 +53,7 @@ describe( 'PageAttributesOrder', () => {
59
53
  } );
60
54
 
61
55
  it( 'should update with valid positive input', async () => {
62
- const user = userEvent.setup( {
63
- advanceTimers: jest.advanceTimersByTime,
64
- } );
56
+ const user = userEvent.setup();
65
57
 
66
58
  const onUpdateOrder = jest.fn();
67
59
 
@@ -77,9 +69,7 @@ describe( 'PageAttributesOrder', () => {
77
69
  } );
78
70
 
79
71
  it( 'should update with valid negative input', async () => {
80
- const user = userEvent.setup( {
81
- advanceTimers: jest.advanceTimersByTime,
82
- } );
72
+ const user = userEvent.setup();
83
73
 
84
74
  const onUpdateOrder = jest.fn();
85
75
 
@@ -9,8 +9,6 @@ import userEvent from '@testing-library/user-event';
9
9
  */
10
10
  import { PostPreviewButton } from '../';
11
11
 
12
- jest.useFakeTimers();
13
-
14
12
  describe( 'PostPreviewButton', () => {
15
13
  const documentWrite = jest.fn();
16
14
  const documentTitle = jest.fn();
@@ -175,9 +173,7 @@ describe( 'PostPreviewButton', () => {
175
173
  } );
176
174
 
177
175
  it( 'should save post if `isDraft` is `true`', async () => {
178
- const user = userEvent.setup( {
179
- advanceTimers: jest.advanceTimersByTime,
180
- } );
176
+ const user = userEvent.setup();
181
177
  const url = 'https://wordpress.org';
182
178
  const savePost = jest.fn();
183
179
  const autosave = jest.fn();
@@ -203,9 +199,7 @@ describe( 'PostPreviewButton', () => {
203
199
  } );
204
200
 
205
201
  it( 'should autosave post if `isDraft` is `false`', async () => {
206
- const user = userEvent.setup( {
207
- advanceTimers: jest.advanceTimersByTime,
208
- } );
202
+ const user = userEvent.setup();
209
203
  const url = 'https://wordpress.org';
210
204
  const savePost = jest.fn();
211
205
  const autosave = jest.fn();
@@ -231,9 +225,7 @@ describe( 'PostPreviewButton', () => {
231
225
  } );
232
226
 
233
227
  it( 'should open a window with the specified target', async () => {
234
- const user = userEvent.setup( {
235
- advanceTimers: jest.advanceTimersByTime,
236
- } );
228
+ const user = userEvent.setup();
237
229
  const postId = 123;
238
230
  const url = 'https://wordpress.org';
239
231
 
@@ -257,9 +249,7 @@ describe( 'PostPreviewButton', () => {
257
249
  } );
258
250
 
259
251
  it( 'should set the location in the window properly', async () => {
260
- const user = userEvent.setup( {
261
- advanceTimers: jest.advanceTimersByTime,
262
- } );
252
+ const user = userEvent.setup();
263
253
  const postId = 123;
264
254
  const url = 'https://wordpress.org';
265
255
 
@@ -290,9 +280,7 @@ describe( 'PostPreviewButton', () => {
290
280
  } );
291
281
 
292
282
  it( 'should display a `Generating preview` message while waiting for autosaving', async () => {
293
- const user = userEvent.setup( {
294
- advanceTimers: jest.advanceTimersByTime,
295
- } );
283
+ const user = userEvent.setup();
296
284
  const previewText = 'Generating preview…';
297
285
  const url = 'https://wordpress.org';
298
286
  const savePost = jest.fn();
@@ -9,8 +9,6 @@ import userEvent from '@testing-library/user-event';
9
9
  */
10
10
  import { PostPublishButton } from '../';
11
11
 
12
- jest.useFakeTimers();
13
-
14
12
  describe( 'PostPublishButton', () => {
15
13
  describe( 'aria-disabled', () => {
16
14
  it( 'should be true if post is currently saving', () => {
@@ -92,9 +90,7 @@ describe( 'PostPublishButton', () => {
92
90
 
93
91
  describe( 'publish status', () => {
94
92
  it( 'should be pending for contributor', async () => {
95
- const user = userEvent.setup( {
96
- advanceTimers: jest.advanceTimersByTime,
97
- } );
93
+ const user = userEvent.setup();
98
94
  const onStatusChange = jest.fn();
99
95
  const onSave = jest.fn();
100
96
  render(
@@ -115,9 +111,7 @@ describe( 'PostPublishButton', () => {
115
111
  } );
116
112
 
117
113
  it( 'should be future for scheduled post', async () => {
118
- const user = userEvent.setup( {
119
- advanceTimers: jest.advanceTimersByTime,
120
- } );
114
+ const user = userEvent.setup();
121
115
  const onStatusChange = jest.fn();
122
116
  const onSave = jest.fn();
123
117
  render(
@@ -139,9 +133,7 @@ describe( 'PostPublishButton', () => {
139
133
  } );
140
134
 
141
135
  it( 'should be private for private visibility', async () => {
142
- const user = userEvent.setup( {
143
- advanceTimers: jest.advanceTimersByTime,
144
- } );
136
+ const user = userEvent.setup();
145
137
  const onStatusChange = jest.fn();
146
138
  const onSave = jest.fn();
147
139
  render(
@@ -163,9 +155,7 @@ describe( 'PostPublishButton', () => {
163
155
  } );
164
156
 
165
157
  it( 'should be publish otherwise', async () => {
166
- const user = userEvent.setup( {
167
- advanceTimers: jest.advanceTimersByTime,
168
- } );
158
+ const user = userEvent.setup();
169
159
  const onStatusChange = jest.fn();
170
160
  const onSave = jest.fn();
171
161
  render(
@@ -188,9 +178,7 @@ describe( 'PostPublishButton', () => {
188
178
 
189
179
  describe( 'click', () => {
190
180
  it( 'should save with status', async () => {
191
- const user = userEvent.setup( {
192
- advanceTimers: jest.advanceTimersByTime,
193
- } );
181
+ const user = userEvent.setup();
194
182
  const onStatusChange = jest.fn();
195
183
  const onSave = jest.fn();
196
184
  render(
@@ -122,6 +122,7 @@ class PostPublishPanelPostpublish extends Component {
122
122
  </p>
123
123
  <div className="post-publish-panel__postpublish-post-address-container">
124
124
  <TextControl
125
+ __nextHasNoMarginBottom
125
126
  className="post-publish-panel__postpublish-post-address"
126
127
  readOnly
127
128
  label={ sprintf(
@@ -4,7 +4,7 @@
4
4
 
5
5
  .editor-post-publish-panel__content {
6
6
  // Ensure the post-publish panel accounts for the header and footer height.
7
- min-height: calc(100% - #{ $header-height + 84px });
7
+ min-height: calc(100% - #{$header-height + 84px});
8
8
 
9
9
  .components-spinner {
10
10
  display: block;
@@ -157,10 +157,6 @@
157
157
  align-items: flex-end;
158
158
  margin-bottom: $grid-unit-20;
159
159
 
160
- .components-base-control__field {
161
- margin-bottom: 0;
162
- }
163
-
164
160
  .post-publish-panel__postpublish-post-address {
165
161
  flex: 1;
166
162
  }
@@ -13,10 +13,6 @@ exports[`PostPublishPanel should render the post-publish panel if the post is pu
13
13
  box-sizing: inherit;
14
14
  }
15
15
 
16
- .emotion-2 {
17
- margin-bottom: calc(4px * 2);
18
- }
19
-
20
16
  .components-panel__row .emotion-2 {
21
17
  margin-bottom: inherit;
22
18
  }
@@ -31,10 +27,6 @@ exports[`PostPublishPanel should render the post-publish panel if the post is pu
31
27
  padding: 0;
32
28
  }
33
29
 
34
- .components-panel__row .emotion-8 {
35
- margin-bottom: inherit;
36
- }
37
-
38
30
  <div>
39
31
  <div
40
32
  class="editor-post-publish-panel"
@@ -145,7 +137,7 @@ exports[`PostPublishPanel should render the post-publish panel if the post is pu
145
137
  class="components-base-control components-checkbox-control emotion-0 emotion-1"
146
138
  >
147
139
  <div
148
- class="components-base-control__field emotion-8 emotion-3"
140
+ class="components-base-control__field emotion-2 emotion-3"
149
141
  >
150
142
  <span
151
143
  class="components-checkbox-control__input-container"
@@ -183,10 +175,6 @@ exports[`PostPublishPanel should render the post-publish panel if the post is sc
183
175
  box-sizing: inherit;
184
176
  }
185
177
 
186
- .emotion-2 {
187
- margin-bottom: calc(4px * 2);
188
- }
189
-
190
178
  .components-panel__row .emotion-2 {
191
179
  margin-bottom: inherit;
192
180
  }
@@ -201,10 +189,6 @@ exports[`PostPublishPanel should render the post-publish panel if the post is sc
201
189
  padding: 0;
202
190
  }
203
191
 
204
- .components-panel__row .emotion-8 {
205
- margin-bottom: inherit;
206
- }
207
-
208
192
  <div>
209
193
  <div
210
194
  class="editor-post-publish-panel"
@@ -315,7 +299,7 @@ exports[`PostPublishPanel should render the post-publish panel if the post is sc
315
299
  class="components-base-control components-checkbox-control emotion-0 emotion-1"
316
300
  >
317
301
  <div
318
- class="components-base-control__field emotion-8 emotion-3"
302
+ class="components-base-control__field emotion-2 emotion-3"
319
303
  >
320
304
  <span
321
305
  class="components-checkbox-control__input-container"
@@ -15,8 +15,6 @@ import { useSelect } from '@wordpress/data';
15
15
  */
16
16
  import PostSavedState from '../';
17
17
 
18
- jest.useFakeTimers();
19
-
20
18
  const mockSavePost = jest.fn();
21
19
 
22
20
  jest.mock( '@wordpress/data/src/components/use-dispatch', () => {
@@ -96,9 +94,7 @@ describe( 'PostSavedState', () => {
96
94
  } );
97
95
 
98
96
  it( 'should return Save button if edits to be saved', async () => {
99
- const user = userEvent.setup( {
100
- advanceTimers: jest.advanceTimersByTime,
101
- } );
97
+ const user = userEvent.setup();
102
98
 
103
99
  useSelect.mockImplementation( () => ( {
104
100
  isDirty: true,
@@ -46,6 +46,7 @@ export class PostSlug extends Component {
46
46
  return (
47
47
  <PostSlugCheck>
48
48
  <TextControl
49
+ __nextHasNoMarginBottom
49
50
  label={ __( 'Slug' ) }
50
51
  autoComplete="off"
51
52
  spellCheck="false"