@wordpress/editor 14.49.1 → 14.51.1-next.v.202607070741.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 +12 -0
- package/build/components/collab-sidebar/format.cjs +83 -0
- package/build/components/collab-sidebar/format.cjs.map +7 -0
- package/build/components/collab-sidebar/hooks.cjs +117 -16
- package/build/components/collab-sidebar/hooks.cjs.map +2 -2
- package/build/components/collab-sidebar/index.cjs +18 -2
- package/build/components/collab-sidebar/index.cjs.map +2 -2
- package/build/components/collab-sidebar/note-highlight-styles.cjs +67 -0
- package/build/components/collab-sidebar/note-highlight-styles.cjs.map +7 -0
- package/build/components/collab-sidebar/utils.cjs +139 -0
- package/build/components/collab-sidebar/utils.cjs.map +2 -2
- package/build/components/collaborators-presence/use-collaborator-notifications.cjs +55 -30
- package/build/components/collaborators-presence/use-collaborator-notifications.cjs.map +2 -2
- package/build/components/commands/index.cjs +99 -3
- package/build/components/commands/index.cjs.map +2 -2
- package/build/components/document-bar/index.cjs +28 -34
- package/build/components/document-bar/index.cjs.map +2 -2
- package/build/components/entities-saved-states/index.cjs +1 -4
- package/build/components/entities-saved-states/index.cjs.map +2 -2
- package/build/components/header/index.cjs +1 -8
- package/build/components/header/index.cjs.map +2 -2
- package/build/components/media-categories/index.cjs +92 -6
- package/build/components/media-categories/index.cjs.map +2 -2
- package/build/components/page-attributes/parent.cjs +0 -1
- package/build/components/page-attributes/parent.cjs.map +2 -2
- package/build/components/post-author/combobox.cjs +0 -1
- package/build/components/post-author/combobox.cjs.map +2 -2
- package/build/components/post-author/select.cjs +0 -1
- package/build/components/post-author/select.cjs.map +2 -2
- package/build/components/post-preview-button/index.cjs +29 -2
- package/build/components/post-preview-button/index.cjs.map +2 -2
- package/build/components/post-publish-panel/maybe-upload-media.cjs +15 -26
- package/build/components/post-publish-panel/maybe-upload-media.cjs.map +3 -3
- package/build/components/post-revisions-preview/revisions-slider.cjs +3 -1
- package/build/components/post-revisions-preview/revisions-slider.cjs.map +2 -2
- package/build/components/post-taxonomies/flat-term-selector.cjs +0 -1
- package/build/components/post-taxonomies/flat-term-selector.cjs.map +2 -2
- package/build/components/post-taxonomies/hierarchical-term-selector.cjs +0 -2
- package/build/components/post-taxonomies/hierarchical-term-selector.cjs.map +2 -2
- package/build/components/post-template/classic-theme.cjs +0 -1
- package/build/components/post-template/classic-theme.cjs.map +2 -2
- package/build/components/preferences-modal/index.cjs +54 -28
- package/build/components/preferences-modal/index.cjs.map +2 -2
- package/build/components/preview-dropdown/index.cjs +38 -9
- package/build/components/preview-dropdown/index.cjs.map +3 -3
- package/build/components/provider/use-block-editor-settings.cjs +23 -9
- package/build/components/provider/use-block-editor-settings.cjs.map +3 -3
- package/build/components/resizable-editor/index.cjs +54 -9
- package/build/components/resizable-editor/index.cjs.map +3 -3
- package/build/components/sidebar/dataform-post-summary.cjs +5 -1
- package/build/components/sidebar/dataform-post-summary.cjs.map +3 -3
- package/build/components/sidebar/index.cjs +29 -38
- package/build/components/sidebar/index.cjs.map +3 -3
- package/build/components/sidebar/post-summary.cjs +0 -13
- package/build/components/sidebar/post-summary.cjs.map +3 -3
- package/build/components/visual-editor/index.cjs +15 -11
- package/build/components/visual-editor/index.cjs.map +3 -3
- package/build/dataviews/store/private-actions.cjs +24 -19
- package/build/dataviews/store/private-actions.cjs.map +2 -2
- package/build/store/actions.cjs +5 -3
- package/build/store/actions.cjs.map +2 -2
- package/build/store/constants.cjs +26 -0
- package/build/store/constants.cjs.map +2 -2
- package/build/store/private-actions.cjs +25 -18
- package/build/store/private-actions.cjs.map +3 -3
- package/build/store/private-selectors.cjs +5 -0
- package/build/store/private-selectors.cjs.map +2 -2
- package/build/store/reducer.cjs +6 -6
- package/build/store/reducer.cjs.map +2 -2
- package/build/store/selectors.cjs +3 -1
- package/build/store/selectors.cjs.map +2 -2
- package/build/utils/device-type.cjs +52 -0
- package/build/utils/device-type.cjs.map +7 -0
- package/build/utils/media-sideload-from-url/index.cjs +63 -0
- package/build/utils/media-sideload-from-url/index.cjs.map +7 -0
- package/build-module/components/collab-sidebar/format.mjs +57 -0
- package/build-module/components/collab-sidebar/format.mjs.map +7 -0
- package/build-module/components/collab-sidebar/hooks.mjs +121 -16
- package/build-module/components/collab-sidebar/hooks.mjs.map +2 -2
- package/build-module/components/collab-sidebar/index.mjs +21 -5
- package/build-module/components/collab-sidebar/index.mjs.map +2 -2
- package/build-module/components/collab-sidebar/note-highlight-styles.mjs +41 -0
- package/build-module/components/collab-sidebar/note-highlight-styles.mjs.map +7 -0
- package/build-module/components/collab-sidebar/utils.mjs +133 -0
- package/build-module/components/collab-sidebar/utils.mjs.map +2 -2
- package/build-module/components/collaborators-presence/use-collaborator-notifications.mjs +55 -30
- package/build-module/components/collaborators-presence/use-collaborator-notifications.mjs.map +2 -2
- package/build-module/components/commands/index.mjs +99 -3
- package/build-module/components/commands/index.mjs.map +2 -2
- package/build-module/components/document-bar/index.mjs +28 -34
- package/build-module/components/document-bar/index.mjs.map +2 -2
- package/build-module/components/entities-saved-states/index.mjs +1 -4
- package/build-module/components/entities-saved-states/index.mjs.map +2 -2
- package/build-module/components/header/index.mjs +1 -13
- package/build-module/components/header/index.mjs.map +2 -2
- package/build-module/components/media-categories/index.mjs +93 -7
- package/build-module/components/media-categories/index.mjs.map +2 -2
- package/build-module/components/page-attributes/parent.mjs +0 -1
- package/build-module/components/page-attributes/parent.mjs.map +2 -2
- package/build-module/components/post-author/combobox.mjs +0 -1
- package/build-module/components/post-author/combobox.mjs.map +2 -2
- package/build-module/components/post-author/select.mjs +0 -1
- package/build-module/components/post-author/select.mjs.map +2 -2
- package/build-module/components/post-preview-button/index.mjs +29 -2
- package/build-module/components/post-preview-button/index.mjs.map +2 -2
- package/build-module/components/post-publish-panel/maybe-upload-media.mjs +19 -27
- package/build-module/components/post-publish-panel/maybe-upload-media.mjs.map +2 -2
- package/build-module/components/post-revisions-preview/revisions-slider.mjs +3 -1
- package/build-module/components/post-revisions-preview/revisions-slider.mjs.map +2 -2
- package/build-module/components/post-taxonomies/flat-term-selector.mjs +0 -1
- package/build-module/components/post-taxonomies/flat-term-selector.mjs.map +2 -2
- package/build-module/components/post-taxonomies/hierarchical-term-selector.mjs +0 -2
- package/build-module/components/post-taxonomies/hierarchical-term-selector.mjs.map +2 -2
- package/build-module/components/post-template/classic-theme.mjs +0 -1
- package/build-module/components/post-template/classic-theme.mjs.map +2 -2
- package/build-module/components/preferences-modal/index.mjs +54 -28
- package/build-module/components/preferences-modal/index.mjs.map +2 -2
- package/build-module/components/preview-dropdown/index.mjs +38 -9
- package/build-module/components/preview-dropdown/index.mjs.map +2 -2
- package/build-module/components/provider/use-block-editor-settings.mjs +23 -9
- package/build-module/components/provider/use-block-editor-settings.mjs.map +2 -2
- package/build-module/components/resizable-editor/index.mjs +55 -10
- package/build-module/components/resizable-editor/index.mjs.map +2 -2
- package/build-module/components/sidebar/dataform-post-summary.mjs +6 -2
- package/build-module/components/sidebar/dataform-post-summary.mjs.map +2 -2
- package/build-module/components/sidebar/index.mjs +29 -42
- package/build-module/components/sidebar/index.mjs.map +2 -2
- package/build-module/components/sidebar/post-summary.mjs +0 -13
- package/build-module/components/sidebar/post-summary.mjs.map +2 -2
- package/build-module/components/visual-editor/index.mjs +16 -13
- package/build-module/components/visual-editor/index.mjs.map +2 -2
- package/build-module/dataviews/store/private-actions.mjs +26 -19
- package/build-module/dataviews/store/private-actions.mjs.map +2 -2
- package/build-module/store/actions.mjs +5 -3
- package/build-module/store/actions.mjs.map +2 -2
- package/build-module/store/constants.mjs +25 -0
- package/build-module/store/constants.mjs.map +2 -2
- package/build-module/store/private-actions.mjs +27 -17
- package/build-module/store/private-actions.mjs.map +2 -2
- package/build-module/store/private-selectors.mjs +4 -0
- package/build-module/store/private-selectors.mjs.map +2 -2
- package/build-module/store/reducer.mjs +5 -5
- package/build-module/store/reducer.mjs.map +2 -2
- package/build-module/store/selectors.mjs +3 -1
- package/build-module/store/selectors.mjs.map +2 -2
- package/build-module/utils/device-type.mjs +25 -0
- package/build-module/utils/device-type.mjs.map +7 -0
- package/build-module/utils/media-sideload-from-url/index.mjs +32 -0
- package/build-module/utils/media-sideload-from-url/index.mjs.map +7 -0
- package/build-style/style-rtl.css +84 -39
- package/build-style/style.css +84 -39
- package/build-types/components/collab-sidebar/format.d.ts +17 -0
- package/build-types/components/collab-sidebar/format.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/hooks.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/index.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/note-highlight-styles.d.ts +31 -0
- package/build-types/components/collab-sidebar/note-highlight-styles.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/utils.d.ts +82 -2
- package/build-types/components/collab-sidebar/utils.d.ts.map +1 -1
- package/build-types/components/collaborators-presence/use-collaborator-notifications.d.ts.map +1 -1
- package/build-types/components/commands/index.d.ts.map +1 -1
- package/build-types/components/document-bar/index.d.ts.map +1 -1
- package/build-types/components/entities-saved-states/index.d.ts.map +1 -1
- package/build-types/components/header/index.d.ts.map +1 -1
- package/build-types/components/media-categories/index.d.ts +12 -3
- package/build-types/components/media-categories/index.d.ts.map +1 -1
- package/build-types/components/page-attributes/parent.d.ts.map +1 -1
- package/build-types/components/post-author/combobox.d.ts.map +1 -1
- package/build-types/components/post-author/select.d.ts.map +1 -1
- package/build-types/components/post-preview-button/index.d.ts.map +1 -1
- package/build-types/components/post-publish-panel/maybe-upload-media.d.ts.map +1 -1
- package/build-types/components/post-revisions-preview/revisions-slider.d.ts.map +1 -1
- package/build-types/components/post-taxonomies/flat-term-selector.d.ts.map +1 -1
- package/build-types/components/post-taxonomies/hierarchical-term-selector.d.ts.map +1 -1
- package/build-types/components/post-template/classic-theme.d.ts.map +1 -1
- package/build-types/components/preview-dropdown/index.d.ts.map +1 -1
- package/build-types/components/provider/use-block-editor-settings.d.ts.map +1 -1
- package/build-types/components/resizable-editor/index.d.ts.map +1 -1
- package/build-types/components/sidebar/dataform-post-summary.d.ts.map +1 -1
- package/build-types/components/sidebar/index.d.ts.map +1 -1
- package/build-types/components/sidebar/post-summary.d.ts.map +1 -1
- package/build-types/components/visual-editor/index.d.ts.map +1 -1
- package/build-types/dataviews/store/private-actions.d.ts.map +1 -1
- package/build-types/store/actions.d.ts.map +1 -1
- package/build-types/store/constants.d.ts +6 -0
- package/build-types/store/constants.d.ts.map +1 -1
- package/build-types/store/index.d.ts +2 -2
- package/build-types/store/private-actions.d.ts +9 -15
- package/build-types/store/private-actions.d.ts.map +1 -1
- package/build-types/store/private-selectors.d.ts +7 -0
- package/build-types/store/private-selectors.d.ts.map +1 -1
- package/build-types/store/reducer.d.ts +6 -7
- package/build-types/store/reducer.d.ts.map +1 -1
- package/build-types/store/selectors.d.ts +1 -1
- package/build-types/store/selectors.d.ts.map +1 -1
- package/build-types/utils/device-type.d.ts +23 -0
- package/build-types/utils/device-type.d.ts.map +1 -0
- package/build-types/utils/get-template-part-icon.d.ts.map +1 -1
- package/build-types/utils/media-sideload-from-url/index.d.ts +18 -0
- package/build-types/utils/media-sideload-from-url/index.d.ts.map +1 -0
- package/package.json +48 -46
- package/src/components/collab-sidebar/format.js +72 -0
- package/src/components/collab-sidebar/hooks.js +203 -22
- package/src/components/collab-sidebar/index.js +19 -5
- package/src/components/collab-sidebar/note-highlight-styles.js +83 -0
- package/src/components/collab-sidebar/style.scss +9 -0
- package/src/components/collab-sidebar/test/note-highlight-styles.js +106 -0
- package/src/components/collab-sidebar/test/utils.js +471 -0
- package/src/components/collab-sidebar/utils.js +225 -2
- package/src/components/collaborators-presence/test/use-collaborator-notifications.ts +265 -262
- package/src/components/collaborators-presence/use-collaborator-notifications.ts +70 -34
- package/src/components/commands/index.js +142 -0
- package/src/components/document-bar/index.js +0 -9
- package/src/components/document-bar/style.scss +0 -17
- package/src/components/entities-saved-states/index.js +1 -5
- package/src/components/header/index.js +1 -15
- package/src/components/header/style.scss +7 -3
- package/src/components/media-categories/index.js +160 -6
- package/src/components/media-categories/test/index.js +202 -0
- package/src/components/page-attributes/parent.js +0 -1
- package/src/components/post-author/combobox.js +0 -1
- package/src/components/post-author/select.js +0 -1
- package/src/components/post-preview-button/index.js +68 -2
- package/src/components/post-publish-panel/maybe-upload-media.js +25 -30
- package/src/components/post-publish-panel/style.scss +1 -1
- package/src/components/post-publish-panel/test/__snapshots__/index.js.snap +11 -127
- package/src/components/post-revisions-preview/revisions-slider.js +4 -1
- package/src/components/post-revisions-preview/test/block-diff.js +2 -2
- package/src/components/post-taxonomies/flat-term-selector.js +0 -1
- package/src/components/post-taxonomies/hierarchical-term-selector.js +0 -2
- package/src/components/post-template/classic-theme.js +0 -1
- package/src/components/preferences-modal/index.js +40 -22
- package/src/components/preferences-modal/test/index.js +83 -0
- package/src/components/preview-dropdown/index.js +42 -3
- package/src/components/provider/use-block-editor-settings.js +42 -7
- package/src/components/resizable-editor/index.js +71 -9
- package/src/components/resizable-editor/style.scss +7 -0
- package/src/components/sidebar/dataform-post-summary.js +13 -1
- package/src/components/sidebar/index.js +32 -47
- package/src/components/sidebar/post-summary.js +0 -17
- package/src/components/styles-canvas/style.scss +1 -2
- package/src/components/visual-editor/index.js +19 -15
- package/src/components/visual-editor/style.scss +11 -4
- package/src/dataviews/store/private-actions.ts +30 -26
- package/src/store/actions.js +6 -3
- package/src/store/constants.ts +45 -0
- package/src/store/private-actions.js +38 -28
- package/src/store/private-selectors.js +10 -0
- package/src/store/reducer.js +7 -9
- package/src/store/selectors.js +3 -1
- package/src/store/test/actions.js +31 -22
- package/src/utils/device-type.js +46 -0
- package/src/utils/media-sideload-from-url/index.js +54 -0
- package/src/utils/media-sideload-from-url/test/index.js +162 -0
- package/build/components/post-publish-panel/media-util.cjs +0 -72
- package/build/components/post-publish-panel/media-util.cjs.map +0 -7
- package/build-module/components/post-publish-panel/media-util.mjs +0 -46
- package/build-module/components/post-publish-panel/media-util.mjs.map +0 -7
- package/build-types/components/post-publish-panel/media-util.d.ts +0 -20
- package/build-types/components/post-publish-panel/media-util.d.ts.map +0 -1
- package/src/components/post-publish-panel/media-util.js +0 -87
- package/src/components/post-publish-panel/test/media-util.js +0 -118
|
@@ -37,6 +37,8 @@ import {
|
|
|
37
37
|
templateTitleField,
|
|
38
38
|
pageTitleField,
|
|
39
39
|
patternTitleField,
|
|
40
|
+
patternDescriptionField,
|
|
41
|
+
patternSyncStatusField,
|
|
40
42
|
notesField,
|
|
41
43
|
scheduledDateField,
|
|
42
44
|
lastEditedDateField,
|
|
@@ -265,59 +267,59 @@ export const registerPostTypeSchema =
|
|
|
265
267
|
if ( postType === ATTACHMENT_POST_TYPE ) {
|
|
266
268
|
fields = ORDERED_MEDIA_FIELDS;
|
|
267
269
|
} else {
|
|
270
|
+
const postTypeSlug = postTypeConfig.slug;
|
|
271
|
+
const isDesignPostType = DESIGN_POST_TYPES.includes( postTypeSlug );
|
|
272
|
+
const isPattern = postTypeSlug === 'wp_block';
|
|
273
|
+
|
|
268
274
|
fields = [
|
|
269
275
|
postTypeConfig.supports?.thumbnail &&
|
|
270
276
|
currentTheme?.theme_supports?.[ 'post-thumbnails' ] &&
|
|
271
277
|
featuredImageField,
|
|
272
|
-
!
|
|
278
|
+
! isDesignPostType &&
|
|
273
279
|
postTypeConfig.supports?.author &&
|
|
274
280
|
authorField,
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
!
|
|
279
|
-
|
|
280
|
-
! DESIGN_POST_TYPES.includes( postTypeConfig.slug ) &&
|
|
281
|
-
dateField,
|
|
282
|
-
! DESIGN_POST_TYPES.includes( postTypeConfig.slug ) &&
|
|
283
|
-
scheduledDateField,
|
|
281
|
+
postTypeSlug === 'wp_template' && templateAuthorField,
|
|
282
|
+
postTypeSlug === 'wp_template_part' && templatePartAuthorField,
|
|
283
|
+
! isDesignPostType && statusField,
|
|
284
|
+
! isDesignPostType && dateField,
|
|
285
|
+
! isDesignPostType && scheduledDateField,
|
|
284
286
|
lastEditedDateField,
|
|
285
|
-
!
|
|
286
|
-
|
|
287
|
-
! DESIGN_POST_TYPES.includes( postTypeConfig.slug ) &&
|
|
287
|
+
! isDesignPostType && slugField,
|
|
288
|
+
! isDesignPostType &&
|
|
288
289
|
postTypeConfig.supports?.excerpt &&
|
|
289
290
|
excerptField,
|
|
291
|
+
isPattern &&
|
|
292
|
+
postTypeConfig.supports?.excerpt &&
|
|
293
|
+
patternDescriptionField,
|
|
290
294
|
postTypeConfig.supports?.[ 'page-attributes' ] && parentField,
|
|
291
295
|
postTypeConfig.supports?.comments && commentStatusField,
|
|
292
296
|
postTypeConfig.supports?.trackbacks && pingStatusField,
|
|
293
297
|
( postTypeConfig.supports?.comments ||
|
|
294
298
|
postTypeConfig.supports?.trackbacks ) &&
|
|
295
299
|
discussionField,
|
|
296
|
-
!
|
|
297
|
-
templateField,
|
|
300
|
+
! isDesignPostType && templateField,
|
|
298
301
|
postTypeConfig.supports?.[ 'post-formats' ] &&
|
|
299
302
|
! disablePostFormats &&
|
|
300
303
|
formatField,
|
|
301
|
-
!
|
|
304
|
+
( ! isDesignPostType || isPattern ) &&
|
|
302
305
|
postTypeConfig.supports?.editor &&
|
|
303
306
|
postContentInfoField,
|
|
304
|
-
!
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
postTypeConfig.slug === 'wp_template' &&
|
|
309
|
-
readOnlyDescriptionField,
|
|
307
|
+
! isDesignPostType && passwordField,
|
|
308
|
+
postTypeSlug === 'post' && stickyField,
|
|
309
|
+
postTypeSlug === 'wp_template' && descriptionField,
|
|
310
|
+
postTypeSlug === 'wp_template' && readOnlyDescriptionField,
|
|
310
311
|
// The `home`/`index` template summary exposes a few fields that
|
|
311
312
|
// target other entities (`root/site` and the posts page).
|
|
312
313
|
// `DataFormPostSummary` overrides them to read/write the right
|
|
313
314
|
// entity and to control their visibility.
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
315
|
+
postTypeSlug === 'wp_template' && postsPageTitleField,
|
|
316
|
+
postTypeSlug === 'wp_template' && postsPerPageField,
|
|
317
|
+
postTypeSlug === 'wp_template' && siteDiscussionField,
|
|
317
318
|
postTypeConfig.supports?.editor &&
|
|
318
319
|
postTypeConfig.viewable &&
|
|
319
320
|
postPreviewField,
|
|
320
321
|
hasEditorNotesSupport( postTypeConfig.supports ) && notesField,
|
|
322
|
+
isPattern && patternSyncStatusField,
|
|
321
323
|
].filter( Boolean );
|
|
322
324
|
if ( postTypeConfig.supports?.title ) {
|
|
323
325
|
let _titleField;
|
|
@@ -325,7 +327,9 @@ export const registerPostTypeSchema =
|
|
|
325
327
|
_titleField = pageTitleField;
|
|
326
328
|
} else if ( postType === 'wp_template' ) {
|
|
327
329
|
_titleField = templateTitleField;
|
|
328
|
-
} else if (
|
|
330
|
+
} else if (
|
|
331
|
+
[ 'wp_block', 'wp_template_part' ].includes( postType )
|
|
332
|
+
) {
|
|
329
333
|
_titleField = patternTitleField;
|
|
330
334
|
} else {
|
|
331
335
|
_titleField = titleField;
|
package/src/store/actions.js
CHANGED
|
@@ -30,6 +30,9 @@ import {
|
|
|
30
30
|
getNotificationArgumentsForTrashFail,
|
|
31
31
|
} from './utils/notice-builder';
|
|
32
32
|
import { unlock } from '../lock-unlock';
|
|
33
|
+
import { setCanvasWidth } from './private-actions';
|
|
34
|
+
import { getCanvasWidthByDeviceType } from '../utils/device-type';
|
|
35
|
+
|
|
33
36
|
/**
|
|
34
37
|
* Returns an action generator used in signalling that editor has initialized with
|
|
35
38
|
* the specified post object and editor settings.
|
|
@@ -757,9 +760,9 @@ export const setRenderingMode =
|
|
|
757
760
|
* @return {Object} Action object.
|
|
758
761
|
*/
|
|
759
762
|
export function setDeviceType( deviceType ) {
|
|
760
|
-
return {
|
|
761
|
-
|
|
762
|
-
|
|
763
|
+
return ( { dispatch } ) => {
|
|
764
|
+
const width = getCanvasWidthByDeviceType( deviceType );
|
|
765
|
+
dispatch( setCanvasWidth( width ) );
|
|
763
766
|
};
|
|
764
767
|
}
|
|
765
768
|
|
package/src/store/constants.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { __ } from '@wordpress/i18n';
|
|
5
|
+
import { desktop, tablet, mobile } from '@wordpress/icons';
|
|
6
|
+
|
|
1
7
|
/**
|
|
2
8
|
* Set of post properties for which edits should assume a merging behavior,
|
|
3
9
|
* assuming an object value.
|
|
@@ -37,3 +43,42 @@ export const DESIGN_POST_TYPES = [
|
|
|
37
43
|
PATTERN_POST_TYPE,
|
|
38
44
|
NAVIGATION_POST_TYPE,
|
|
39
45
|
];
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
* Contains the device types and their corresponding canvas width.
|
|
49
|
+
* Matches the breakpoints in packages/base-styles/_breakpoints.scss,
|
|
50
|
+
* and breakpoints in packages/compose/src/hooks/use-viewport-match/index.js.
|
|
51
|
+
* minus 1 to trigger the media query for device preview.
|
|
52
|
+
*
|
|
53
|
+
* These breakpoints are currently hardcoded, but are expected to become
|
|
54
|
+
* customizable via the `settings.viewport` values in theme.json in the future.
|
|
55
|
+
* See https://github.com/WordPress/gutenberg/pull/79104.
|
|
56
|
+
*/
|
|
57
|
+
export const DEVICE_TYPES: Record<
|
|
58
|
+
string,
|
|
59
|
+
{
|
|
60
|
+
value: string;
|
|
61
|
+
label: string;
|
|
62
|
+
icon: React.JSX.Element;
|
|
63
|
+
canvasWidth: number | undefined;
|
|
64
|
+
}
|
|
65
|
+
> = {
|
|
66
|
+
Desktop: {
|
|
67
|
+
value: 'Desktop',
|
|
68
|
+
label: __( 'Desktop' ),
|
|
69
|
+
icon: desktop,
|
|
70
|
+
canvasWidth: undefined,
|
|
71
|
+
},
|
|
72
|
+
Tablet: {
|
|
73
|
+
value: 'Tablet',
|
|
74
|
+
label: __( 'Tablet' ),
|
|
75
|
+
icon: tablet,
|
|
76
|
+
canvasWidth: 782 - 1, // preview for useViewportMatch( 'medium', '<' )
|
|
77
|
+
},
|
|
78
|
+
Mobile: {
|
|
79
|
+
value: 'Mobile',
|
|
80
|
+
label: __( 'Mobile' ),
|
|
81
|
+
icon: mobile,
|
|
82
|
+
canvasWidth: 480 - 1, // preview for useViewportMatch( 'mobile', '<' )
|
|
83
|
+
},
|
|
84
|
+
};
|
|
@@ -17,35 +17,13 @@ import { dateI18n, getSettings as getDateSettings } from '@wordpress/date';
|
|
|
17
17
|
*/
|
|
18
18
|
import isTemplateRevertable from './utils/is-template-revertable';
|
|
19
19
|
import { buildRevisionsPageQuery } from './private-selectors';
|
|
20
|
+
import {
|
|
21
|
+
getDeviceTypeByCanvasWidth,
|
|
22
|
+
VIEWPORT_STATE_BY_DEVICE_TYPE,
|
|
23
|
+
} from '../utils/device-type';
|
|
20
24
|
import { unlock } from '../lock-unlock';
|
|
21
25
|
export * from '../dataviews/store/private-actions';
|
|
22
26
|
|
|
23
|
-
const DEVICE_TYPE_BY_VIEWPORT_STATE = {
|
|
24
|
-
'@mobile': 'Mobile',
|
|
25
|
-
'@tablet': 'Tablet',
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Updates the editor preview device in response to a block-editor viewport
|
|
30
|
-
* state signal.
|
|
31
|
-
*
|
|
32
|
-
* @param {Object} options Viewport state change options.
|
|
33
|
-
* @param {string} options.viewport Selected viewport state.
|
|
34
|
-
* @param {boolean} options.showStateOnCanvas Whether canvas preview is enabled.
|
|
35
|
-
*/
|
|
36
|
-
export const updateDeviceTypeForViewportState =
|
|
37
|
-
( { viewport = 'default', showStateOnCanvas = true } = {} ) =>
|
|
38
|
-
( { dispatch, registry } ) => {
|
|
39
|
-
if ( ! showStateOnCanvas ) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
dispatch.setDeviceType(
|
|
44
|
-
DEVICE_TYPE_BY_VIEWPORT_STATE[ viewport ] ?? 'Desktop'
|
|
45
|
-
);
|
|
46
|
-
unlock( registry.dispatch( blockEditorStore ) ).resetZoomLevel();
|
|
47
|
-
};
|
|
48
|
-
|
|
49
27
|
/**
|
|
50
28
|
* Returns an action object used to set which template is currently being used/edited.
|
|
51
29
|
*
|
|
@@ -231,9 +209,13 @@ export const saveDirtyEntities =
|
|
|
231
209
|
registry
|
|
232
210
|
.dispatch( blockEditorStore )
|
|
233
211
|
.__unstableMarkLastChangeAsPersistent();
|
|
212
|
+
|
|
234
213
|
Promise.all( pendingSavedRecords )
|
|
235
|
-
.then( ( values ) => {
|
|
236
|
-
|
|
214
|
+
.then( async ( values ) => {
|
|
215
|
+
if ( onSave ) {
|
|
216
|
+
await onSave();
|
|
217
|
+
}
|
|
218
|
+
return values;
|
|
237
219
|
} )
|
|
238
220
|
.then( ( values ) => {
|
|
239
221
|
if (
|
|
@@ -603,6 +585,34 @@ export function resetStylesNavigation() {
|
|
|
603
585
|
};
|
|
604
586
|
}
|
|
605
587
|
|
|
588
|
+
/**
|
|
589
|
+
* Set the width of the canvas.
|
|
590
|
+
*
|
|
591
|
+
* @param {number} width The width of the canvas in pixels.
|
|
592
|
+
*/
|
|
593
|
+
export function setCanvasWidth( width ) {
|
|
594
|
+
return ( { dispatch, registry } ) => {
|
|
595
|
+
dispatch( {
|
|
596
|
+
type: 'SET_CANVAS_WIDTH',
|
|
597
|
+
width,
|
|
598
|
+
} );
|
|
599
|
+
|
|
600
|
+
// While Responsive editing is enabled, the canvas width also drives the
|
|
601
|
+
// viewport style state, whether changed via the device preview or by
|
|
602
|
+
// manually resizing the canvas.
|
|
603
|
+
if (
|
|
604
|
+
unlock( registry.select( blockEditorStore ) ).isResponsiveEditing()
|
|
605
|
+
) {
|
|
606
|
+
const deviceType = getDeviceTypeByCanvasWidth( width );
|
|
607
|
+
unlock(
|
|
608
|
+
registry.dispatch( blockEditorStore )
|
|
609
|
+
).setStyleStateViewport(
|
|
610
|
+
VIEWPORT_STATE_BY_DEVICE_TYPE[ deviceType ] ?? 'default'
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
|
|
606
616
|
/**
|
|
607
617
|
* Set the current revision ID for revisions preview mode.
|
|
608
618
|
* Pass a revision ID to enter revisions mode, or null to exit.
|
|
@@ -353,6 +353,16 @@ export function getShowStylebook( state ) {
|
|
|
353
353
|
return state.showStylebook ?? false;
|
|
354
354
|
}
|
|
355
355
|
|
|
356
|
+
/**
|
|
357
|
+
* Get the canvas width.
|
|
358
|
+
*
|
|
359
|
+
* @param {Object} state Global application state.
|
|
360
|
+
* @return {number} The canvas width in pixels.
|
|
361
|
+
*/
|
|
362
|
+
export function getCanvasWidth( state ) {
|
|
363
|
+
return state.canvasWidth;
|
|
364
|
+
}
|
|
365
|
+
|
|
356
366
|
/**
|
|
357
367
|
* Returns the current revisions page number.
|
|
358
368
|
*
|
package/src/store/reducer.js
CHANGED
|
@@ -277,19 +277,17 @@ export function renderingMode( state = 'post-only', action ) {
|
|
|
277
277
|
}
|
|
278
278
|
|
|
279
279
|
/**
|
|
280
|
-
* Reducer
|
|
280
|
+
* Reducer for the canvas width.
|
|
281
281
|
*
|
|
282
|
-
* @param {
|
|
282
|
+
* @param {number} state Current state.
|
|
283
283
|
* @param {Object} action Dispatched action.
|
|
284
|
-
*
|
|
285
|
-
* @return {Object} Updated state.
|
|
284
|
+
* @return {number} Updated state.
|
|
286
285
|
*/
|
|
287
|
-
export function
|
|
286
|
+
export function canvasWidth( state = undefined, action ) {
|
|
288
287
|
switch ( action.type ) {
|
|
289
|
-
case '
|
|
290
|
-
return action.
|
|
288
|
+
case 'SET_CANVAS_WIDTH':
|
|
289
|
+
return action.width;
|
|
291
290
|
}
|
|
292
|
-
|
|
293
291
|
return state;
|
|
294
292
|
}
|
|
295
293
|
|
|
@@ -500,7 +498,7 @@ export default combineReducers( {
|
|
|
500
498
|
editorSettings,
|
|
501
499
|
postAutosavingLock,
|
|
502
500
|
renderingMode,
|
|
503
|
-
|
|
501
|
+
canvasWidth,
|
|
504
502
|
removedPanels,
|
|
505
503
|
blockInserterPanel,
|
|
506
504
|
inserterSidebarToggleRef,
|
package/src/store/selectors.js
CHANGED
|
@@ -29,6 +29,7 @@ import { getPostRawValue } from './reducer';
|
|
|
29
29
|
import { getTemplatePartIcon } from '../utils/get-template-part-icon';
|
|
30
30
|
import { unlock } from '../lock-unlock';
|
|
31
31
|
import { getTemplateInfo } from '../utils/get-template-info';
|
|
32
|
+
import { getDeviceTypeByCanvasWidth } from '../utils/device-type';
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* Shared reference to an empty object for cases where it is important to avoid
|
|
@@ -1352,7 +1353,8 @@ export const getDeviceType = createRegistrySelector(
|
|
|
1352
1353
|
if ( isZoomOut ) {
|
|
1353
1354
|
return 'Desktop';
|
|
1354
1355
|
}
|
|
1355
|
-
|
|
1356
|
+
const canvasWidth = state.canvasWidth;
|
|
1357
|
+
return getDeviceTypeByCanvasWidth( canvasWidth );
|
|
1356
1358
|
}
|
|
1357
1359
|
);
|
|
1358
1360
|
|
|
@@ -12,8 +12,8 @@ import { store as preferencesStore } from '@wordpress/preferences';
|
|
|
12
12
|
* Internal dependencies
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import * as actions from '../actions';
|
|
16
15
|
import { store as editorStore } from '..';
|
|
16
|
+
import * as actions from '../actions';
|
|
17
17
|
import { unlock } from '../../lock-unlock';
|
|
18
18
|
|
|
19
19
|
const postId = 44;
|
|
@@ -64,36 +64,45 @@ const getMethod = ( options ) =>
|
|
|
64
64
|
options.headers?.[ 'X-HTTP-Method-Override' ] || options.method || 'GET';
|
|
65
65
|
|
|
66
66
|
describe( 'Post actions', () => {
|
|
67
|
-
describe( '
|
|
68
|
-
it( '
|
|
67
|
+
describe( 'setCanvasWidth', () => {
|
|
68
|
+
it( 'syncs the viewport style state while Responsive editing is enabled', () => {
|
|
69
69
|
const registry = createRegistryWithStores();
|
|
70
|
+
const getViewport = () =>
|
|
71
|
+
unlock(
|
|
72
|
+
registry.select( blockEditorStore )
|
|
73
|
+
).getStyleStateViewport();
|
|
74
|
+
const setCanvasWidth = ( width ) =>
|
|
75
|
+
unlock( registry.dispatch( editorStore ) ).setCanvasWidth(
|
|
76
|
+
width
|
|
77
|
+
);
|
|
70
78
|
|
|
71
79
|
unlock(
|
|
72
|
-
registry.dispatch(
|
|
73
|
-
).
|
|
74
|
-
viewport: '@mobile',
|
|
75
|
-
showStateOnCanvas: true,
|
|
76
|
-
} );
|
|
80
|
+
registry.dispatch( blockEditorStore )
|
|
81
|
+
).setResponsiveEditing( true );
|
|
77
82
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
);
|
|
83
|
+
// A tablet-sized canvas selects the tablet viewport.
|
|
84
|
+
setCanvasWidth( 600 );
|
|
85
|
+
expect( getViewport() ).toBe( '@tablet' );
|
|
86
|
+
|
|
87
|
+
// A mobile-sized canvas selects the mobile viewport.
|
|
88
|
+
setCanvasWidth( 400 );
|
|
89
|
+
expect( getViewport() ).toBe( '@mobile' );
|
|
90
|
+
|
|
91
|
+
// A full-width (desktop) canvas resets to the default viewport.
|
|
92
|
+
setCanvasWidth( undefined );
|
|
93
|
+
expect( getViewport() ).toBe( 'default' );
|
|
81
94
|
} );
|
|
82
95
|
|
|
83
|
-
it( '
|
|
96
|
+
it( 'leaves the viewport style state untouched while Responsive editing is disabled', () => {
|
|
84
97
|
const registry = createRegistryWithStores();
|
|
85
|
-
|
|
98
|
+
const getViewport = () =>
|
|
99
|
+
unlock(
|
|
100
|
+
registry.select( blockEditorStore )
|
|
101
|
+
).getStyleStateViewport();
|
|
86
102
|
|
|
87
|
-
unlock(
|
|
88
|
-
registry.dispatch( editorStore )
|
|
89
|
-
).updateDeviceTypeForViewportState( {
|
|
90
|
-
viewport: '@mobile',
|
|
91
|
-
showStateOnCanvas: false,
|
|
92
|
-
} );
|
|
103
|
+
unlock( registry.dispatch( editorStore ) ).setCanvasWidth( 400 );
|
|
93
104
|
|
|
94
|
-
expect(
|
|
95
|
-
'Tablet'
|
|
96
|
-
);
|
|
105
|
+
expect( getViewport() ).toBe( 'default' );
|
|
97
106
|
} );
|
|
98
107
|
} );
|
|
99
108
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { DEVICE_TYPES } from '../store/constants';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Maps a device preview type to its corresponding viewport style state. Used
|
|
8
|
+
* when Responsive editing is enabled so the device preview drives which
|
|
9
|
+
* viewport block style edits are applied to.
|
|
10
|
+
*
|
|
11
|
+
* @type {Object}
|
|
12
|
+
*/
|
|
13
|
+
export const VIEWPORT_STATE_BY_DEVICE_TYPE = {
|
|
14
|
+
Desktop: 'default',
|
|
15
|
+
Tablet: '@tablet',
|
|
16
|
+
Mobile: '@mobile',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Gets the most appropriate device type based on the canvas width.
|
|
21
|
+
*
|
|
22
|
+
* @param {number} canvasWidth The canvas width in pixels.
|
|
23
|
+
* @return {string} The device type.
|
|
24
|
+
*/
|
|
25
|
+
export function getDeviceTypeByCanvasWidth( canvasWidth ) {
|
|
26
|
+
// Mobile
|
|
27
|
+
if ( canvasWidth && canvasWidth <= DEVICE_TYPES.Mobile.canvasWidth ) {
|
|
28
|
+
return DEVICE_TYPES.Mobile.value;
|
|
29
|
+
}
|
|
30
|
+
// Tablet
|
|
31
|
+
if ( canvasWidth && canvasWidth <= DEVICE_TYPES.Tablet.canvasWidth ) {
|
|
32
|
+
return DEVICE_TYPES.Tablet.value;
|
|
33
|
+
}
|
|
34
|
+
// Desktop
|
|
35
|
+
return DEVICE_TYPES.Desktop.value;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get the canvas width by device type.
|
|
40
|
+
*
|
|
41
|
+
* @param {string} deviceType The device type.
|
|
42
|
+
* @return {number|undefined} The canvas width in pixels.
|
|
43
|
+
*/
|
|
44
|
+
export function getCanvasWidthByDeviceType( deviceType ) {
|
|
45
|
+
return DEVICE_TYPES[ deviceType ]?.canvasWidth;
|
|
46
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import apiFetch from '@wordpress/api-fetch';
|
|
5
|
+
import { select } from '@wordpress/data';
|
|
6
|
+
import { transformAttachment } from '@wordpress/media-utils';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Internal dependencies
|
|
10
|
+
*/
|
|
11
|
+
import { store as editorStore } from '../../store';
|
|
12
|
+
|
|
13
|
+
const noop = () => {};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Sideloads an external image into the media library from its URL.
|
|
17
|
+
*
|
|
18
|
+
* The server downloads the remote file, which avoids a cross-origin browser
|
|
19
|
+
* fetch that fails when the editor is cross-origin isolated. Since the server
|
|
20
|
+
* owns the upload it also generates sub-sizes, as with a regular upload.
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} $0 Parameters object.
|
|
23
|
+
* @param {string} $0.url URL of the external image to sideload.
|
|
24
|
+
* @param {Function} $0.onSuccess Function called with the new attachment on success.
|
|
25
|
+
* @param {Function} $0.onError Function called with an error message on failure.
|
|
26
|
+
*/
|
|
27
|
+
export default function mediaSideloadFromUrl( {
|
|
28
|
+
url,
|
|
29
|
+
onSuccess,
|
|
30
|
+
onError = noop,
|
|
31
|
+
} ) {
|
|
32
|
+
const currentPost = select( editorStore ).getCurrentPost();
|
|
33
|
+
// Templates and template parts store their numerical ID in `wp_id`.
|
|
34
|
+
const currentPostId =
|
|
35
|
+
typeof currentPost?.id === 'number'
|
|
36
|
+
? currentPost.id
|
|
37
|
+
: currentPost?.wp_id;
|
|
38
|
+
const postData = currentPostId ? { post: currentPostId } : {};
|
|
39
|
+
|
|
40
|
+
apiFetch( {
|
|
41
|
+
path: '/wp/v2/media',
|
|
42
|
+
method: 'POST',
|
|
43
|
+
data: {
|
|
44
|
+
url,
|
|
45
|
+
...postData,
|
|
46
|
+
},
|
|
47
|
+
} )
|
|
48
|
+
.then( ( attachment ) => {
|
|
49
|
+
onSuccess?.( transformAttachment( attachment ) );
|
|
50
|
+
} )
|
|
51
|
+
.catch( ( error ) => {
|
|
52
|
+
onError( error?.message || error );
|
|
53
|
+
} );
|
|
54
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import apiFetch from '@wordpress/api-fetch';
|
|
5
|
+
import { select } from '@wordpress/data';
|
|
6
|
+
import { transformAttachment } from '@wordpress/media-utils';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Internal dependencies
|
|
10
|
+
*/
|
|
11
|
+
import mediaSideloadFromUrl from '..';
|
|
12
|
+
|
|
13
|
+
jest.mock( '@wordpress/api-fetch', () => jest.fn() );
|
|
14
|
+
jest.mock( '@wordpress/data', () => ( {
|
|
15
|
+
select: jest.fn(),
|
|
16
|
+
} ) );
|
|
17
|
+
/*
|
|
18
|
+
* The store and transformAttachment are mocked so this unit test does not pull
|
|
19
|
+
* in the full @wordpress/media-utils / core-data import chain (which needs the
|
|
20
|
+
* real @wordpress/data). transformAttachment's mapping is covered in
|
|
21
|
+
* @wordpress/media-utils; here we only verify mediaSideloadFromUrl forwards
|
|
22
|
+
* whatever it returns.
|
|
23
|
+
*/
|
|
24
|
+
jest.mock( '../../../store', () => ( { store: 'core/editor' } ) );
|
|
25
|
+
jest.mock( '@wordpress/media-utils', () => ( {
|
|
26
|
+
transformAttachment: jest.fn( ( attachment ) => ( {
|
|
27
|
+
id: attachment.id,
|
|
28
|
+
url: attachment.source_url,
|
|
29
|
+
alt: attachment.alt_text,
|
|
30
|
+
} ) ),
|
|
31
|
+
} ) );
|
|
32
|
+
|
|
33
|
+
const mockRestAttachment = {
|
|
34
|
+
id: 123,
|
|
35
|
+
alt_text: 'An external photo.',
|
|
36
|
+
caption: { raw: '' },
|
|
37
|
+
title: { raw: 'photo' },
|
|
38
|
+
source_url: 'https://example.com/wp-content/uploads/photo.jpg',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Sets the post returned by `getCurrentPost()` for a test.
|
|
43
|
+
*
|
|
44
|
+
* @param {Object|undefined} post The post object, or undefined for no post.
|
|
45
|
+
*/
|
|
46
|
+
function mockCurrentPost( post ) {
|
|
47
|
+
select.mockReturnValue( {
|
|
48
|
+
getCurrentPost: () => post,
|
|
49
|
+
} );
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
describe( 'mediaSideloadFromUrl', () => {
|
|
53
|
+
beforeEach( () => {
|
|
54
|
+
jest.clearAllMocks();
|
|
55
|
+
mockCurrentPost( { id: 42 } );
|
|
56
|
+
} );
|
|
57
|
+
|
|
58
|
+
it( 'should POST to /wp/v2/media with the url, leaving sub-size generation to the server', async () => {
|
|
59
|
+
apiFetch.mockResolvedValue( mockRestAttachment );
|
|
60
|
+
|
|
61
|
+
await new Promise( ( resolve ) => {
|
|
62
|
+
mediaSideloadFromUrl( {
|
|
63
|
+
url: 'https://example.com/photo.jpg',
|
|
64
|
+
onSuccess: resolve,
|
|
65
|
+
} );
|
|
66
|
+
} );
|
|
67
|
+
|
|
68
|
+
expect( apiFetch ).toHaveBeenCalledWith( {
|
|
69
|
+
path: '/wp/v2/media',
|
|
70
|
+
method: 'POST',
|
|
71
|
+
data: {
|
|
72
|
+
url: 'https://example.com/photo.jpg',
|
|
73
|
+
post: 42,
|
|
74
|
+
},
|
|
75
|
+
} );
|
|
76
|
+
} );
|
|
77
|
+
|
|
78
|
+
it( 'should pass the transformed attachment to onSuccess', async () => {
|
|
79
|
+
apiFetch.mockResolvedValue( mockRestAttachment );
|
|
80
|
+
|
|
81
|
+
const media = await new Promise( ( resolve ) => {
|
|
82
|
+
mediaSideloadFromUrl( {
|
|
83
|
+
url: 'https://example.com/photo.jpg',
|
|
84
|
+
onSuccess: resolve,
|
|
85
|
+
} );
|
|
86
|
+
} );
|
|
87
|
+
|
|
88
|
+
/*
|
|
89
|
+
* The raw REST attachment is run through transformAttachment, which maps
|
|
90
|
+
* it to the editor shape the image block expects (url, alt).
|
|
91
|
+
*/
|
|
92
|
+
expect( transformAttachment ).toHaveBeenCalledWith(
|
|
93
|
+
mockRestAttachment
|
|
94
|
+
);
|
|
95
|
+
expect( media ).toMatchObject( {
|
|
96
|
+
id: 123,
|
|
97
|
+
url: 'https://example.com/wp-content/uploads/photo.jpg',
|
|
98
|
+
alt: 'An external photo.',
|
|
99
|
+
} );
|
|
100
|
+
} );
|
|
101
|
+
|
|
102
|
+
it( 'should fall back to wp_id when the post id is not numeric', async () => {
|
|
103
|
+
apiFetch.mockResolvedValue( mockRestAttachment );
|
|
104
|
+
// Templates and template parts expose their numeric id as `wp_id`.
|
|
105
|
+
mockCurrentPost( { id: 'my-theme//header', wp_id: 99 } );
|
|
106
|
+
|
|
107
|
+
await new Promise( ( resolve ) => {
|
|
108
|
+
mediaSideloadFromUrl( {
|
|
109
|
+
url: 'https://example.com/photo.jpg',
|
|
110
|
+
onSuccess: resolve,
|
|
111
|
+
} );
|
|
112
|
+
} );
|
|
113
|
+
|
|
114
|
+
expect( apiFetch ).toHaveBeenCalledWith(
|
|
115
|
+
expect.objectContaining( {
|
|
116
|
+
data: expect.objectContaining( { post: 99 } ),
|
|
117
|
+
} )
|
|
118
|
+
);
|
|
119
|
+
} );
|
|
120
|
+
|
|
121
|
+
it( 'should omit the post param when there is no current post', async () => {
|
|
122
|
+
apiFetch.mockResolvedValue( mockRestAttachment );
|
|
123
|
+
mockCurrentPost( undefined );
|
|
124
|
+
|
|
125
|
+
await new Promise( ( resolve ) => {
|
|
126
|
+
mediaSideloadFromUrl( {
|
|
127
|
+
url: 'https://example.com/photo.jpg',
|
|
128
|
+
onSuccess: resolve,
|
|
129
|
+
} );
|
|
130
|
+
} );
|
|
131
|
+
|
|
132
|
+
const { data } = apiFetch.mock.calls[ 0 ][ 0 ];
|
|
133
|
+
expect( data ).not.toHaveProperty( 'post' );
|
|
134
|
+
} );
|
|
135
|
+
|
|
136
|
+
it( 'should pass the error message to onError on failure', async () => {
|
|
137
|
+
apiFetch.mockRejectedValue(
|
|
138
|
+
new Error( 'Could not download the image.' )
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
const message = await new Promise( ( resolve ) => {
|
|
142
|
+
mediaSideloadFromUrl( {
|
|
143
|
+
url: 'https://example.com/photo.jpg',
|
|
144
|
+
onSuccess: () => {},
|
|
145
|
+
onError: resolve,
|
|
146
|
+
} );
|
|
147
|
+
} );
|
|
148
|
+
|
|
149
|
+
expect( message ).toBe( 'Could not download the image.' );
|
|
150
|
+
} );
|
|
151
|
+
|
|
152
|
+
it( 'should not throw when onError is omitted and the request fails', async () => {
|
|
153
|
+
apiFetch.mockRejectedValue( new Error( 'Network error' ) );
|
|
154
|
+
|
|
155
|
+
expect( () =>
|
|
156
|
+
mediaSideloadFromUrl( { url: 'https://example.com/photo.jpg' } )
|
|
157
|
+
).not.toThrow();
|
|
158
|
+
|
|
159
|
+
// Let the rejected promise settle so the default noop onError runs.
|
|
160
|
+
await Promise.resolve();
|
|
161
|
+
} );
|
|
162
|
+
} );
|