@wordpress/block-library 9.19.2 → 9.21.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 +4 -0
- package/build/archives/edit.js +2 -2
- package/build/archives/edit.js.map +1 -1
- package/build/audio/edit.js +66 -33
- package/build/audio/edit.js.map +1 -1
- package/build/avatar/index.js +8 -3
- package/build/avatar/index.js.map +1 -1
- package/build/button/edit.js +43 -16
- package/build/button/edit.js.map +1 -1
- package/build/categories/edit.js +3 -3
- package/build/categories/edit.js.map +1 -1
- package/build/comment-template/hooks.js +6 -0
- package/build/comment-template/hooks.js.map +1 -1
- package/build/cover/index.js +8 -1
- package/build/cover/index.js.map +1 -1
- package/build/embed/edit.js +4 -1
- package/build/embed/edit.js.map +1 -1
- package/build/image/constants.js +2 -1
- package/build/image/constants.js.map +1 -1
- package/build/image/edit.js +3 -2
- package/build/image/edit.js.map +1 -1
- package/build/image/image.js +98 -80
- package/build/image/image.js.map +1 -1
- package/build/navigation/edit/index.js +8 -4
- package/build/navigation/edit/index.js.map +1 -1
- package/build/navigation-link/edit.js +27 -8
- package/build/navigation-link/edit.js.map +1 -1
- package/build/post-author/index.js +8 -1
- package/build/post-author/index.js.map +1 -1
- package/build/post-featured-image/edit.js +2 -1
- package/build/post-featured-image/edit.js.map +1 -1
- package/build/rss/edit.js +21 -1
- package/build/rss/edit.js.map +1 -1
- package/build/rss/index.js +7 -0
- package/build/rss/index.js.map +1 -1
- package/build/site-logo/index.js +8 -1
- package/build/site-logo/index.js.map +1 -1
- package/build/site-title/edit.js +1 -1
- package/build/site-title/edit.js.map +1 -1
- package/build/social-links/index.js +1 -0
- package/build/social-links/index.js.map +1 -1
- package/build/table-of-contents/edit.js +50 -8
- package/build/table-of-contents/edit.js.map +1 -1
- package/build/table-of-contents/hooks.js +13 -4
- package/build/table-of-contents/hooks.js.map +1 -1
- package/build/table-of-contents/index.js +3 -0
- package/build/table-of-contents/index.js.map +1 -1
- package/build-module/archives/edit.js +2 -2
- package/build-module/archives/edit.js.map +1 -1
- package/build-module/audio/edit.js +68 -35
- package/build-module/audio/edit.js.map +1 -1
- package/build-module/avatar/index.js +8 -3
- package/build-module/avatar/index.js.map +1 -1
- package/build-module/button/edit.js +44 -17
- package/build-module/button/edit.js.map +1 -1
- package/build-module/categories/edit.js +3 -3
- package/build-module/categories/edit.js.map +1 -1
- package/build-module/comment-template/hooks.js +6 -0
- package/build-module/comment-template/hooks.js.map +1 -1
- package/build-module/cover/index.js +8 -1
- package/build-module/cover/index.js.map +1 -1
- package/build-module/embed/edit.js +4 -1
- package/build-module/embed/edit.js.map +1 -1
- package/build-module/image/constants.js +1 -0
- package/build-module/image/constants.js.map +1 -1
- package/build-module/image/edit.js +3 -2
- package/build-module/image/edit.js.map +1 -1
- package/build-module/image/image.js +102 -84
- package/build-module/image/image.js.map +1 -1
- package/build-module/navigation/edit/index.js +8 -4
- package/build-module/navigation/edit/index.js.map +1 -1
- package/build-module/navigation-link/edit.js +28 -9
- package/build-module/navigation-link/edit.js.map +1 -1
- package/build-module/post-author/index.js +8 -1
- package/build-module/post-author/index.js.map +1 -1
- package/build-module/post-featured-image/edit.js +2 -1
- package/build-module/post-featured-image/edit.js.map +1 -1
- package/build-module/rss/edit.js +22 -2
- package/build-module/rss/edit.js.map +1 -1
- package/build-module/rss/index.js +7 -0
- package/build-module/rss/index.js.map +1 -1
- package/build-module/site-logo/index.js +8 -1
- package/build-module/site-logo/index.js.map +1 -1
- package/build-module/site-title/edit.js +1 -1
- package/build-module/site-title/edit.js.map +1 -1
- package/build-module/social-links/index.js +1 -0
- package/build-module/social-links/index.js.map +1 -1
- package/build-module/table-of-contents/edit.js +52 -10
- package/build-module/table-of-contents/edit.js.map +1 -1
- package/build-module/table-of-contents/hooks.js +13 -4
- package/build-module/table-of-contents/hooks.js.map +1 -1
- package/build-module/table-of-contents/index.js +3 -0
- package/build-module/table-of-contents/index.js.map +1 -1
- package/build-style/editor-rtl.css +0 -9
- package/build-style/editor.css +0 -9
- package/build-style/image/editor-rtl.css +0 -9
- package/build-style/image/editor.css +0 -9
- package/package.json +35 -35
- package/src/archives/edit.js +2 -2
- package/src/audio/edit.js +84 -33
- package/src/avatar/block.json +8 -3
- package/src/button/edit.js +69 -24
- package/src/categories/edit.js +3 -3
- package/src/comment-template/hooks.js +14 -6
- package/src/cover/block.json +8 -1
- package/src/embed/edit.js +7 -1
- package/src/image/constants.js +1 -0
- package/src/image/edit.js +3 -3
- package/src/image/editor.scss +0 -13
- package/src/image/image.js +124 -134
- package/src/navigation/edit/index.js +4 -0
- package/src/navigation-link/edit.js +45 -11
- package/src/post-author/block.json +8 -1
- package/src/post-featured-image/edit.js +2 -1
- package/src/rss/block.json +7 -0
- package/src/rss/edit.js +21 -0
- package/src/rss/index.php +27 -9
- package/src/site-logo/block.json +8 -1
- package/src/site-title/edit.js +1 -1
- package/src/site-title/index.php +1 -1
- package/src/social-links/block.json +1 -0
- package/src/table-of-contents/block.json +3 -0
- package/src/table-of-contents/edit.js +45 -4
- package/src/table-of-contents/hooks.js +12 -3
package/src/button/edit.js
CHANGED
|
@@ -15,7 +15,13 @@ import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
|
|
|
15
15
|
* WordPress dependencies
|
|
16
16
|
*/
|
|
17
17
|
import { __, sprintf } from '@wordpress/i18n';
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
useEffect,
|
|
20
|
+
useState,
|
|
21
|
+
useRef,
|
|
22
|
+
useMemo,
|
|
23
|
+
createInterpolateElement,
|
|
24
|
+
} from '@wordpress/element';
|
|
19
25
|
import {
|
|
20
26
|
TextControl,
|
|
21
27
|
ToolbarButton,
|
|
@@ -219,6 +225,63 @@ function ButtonEdit( props ) {
|
|
|
219
225
|
const nofollow = !! rel?.includes( NOFOLLOW_REL );
|
|
220
226
|
const isLinkTag = 'a' === TagName;
|
|
221
227
|
|
|
228
|
+
const {
|
|
229
|
+
createPageEntity,
|
|
230
|
+
userCanCreatePages,
|
|
231
|
+
lockUrlControls = false,
|
|
232
|
+
} = useSelect(
|
|
233
|
+
( select ) => {
|
|
234
|
+
if ( ! isSelected ) {
|
|
235
|
+
return {};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const _settings = select( blockEditorStore ).getSettings();
|
|
239
|
+
|
|
240
|
+
const blockBindingsSource = getBlockBindingsSource(
|
|
241
|
+
metadata?.bindings?.url?.source
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
return {
|
|
245
|
+
createPageEntity: _settings.__experimentalCreatePageEntity,
|
|
246
|
+
userCanCreatePages: _settings.__experimentalUserCanCreatePages,
|
|
247
|
+
lockUrlControls:
|
|
248
|
+
!! metadata?.bindings?.url &&
|
|
249
|
+
! blockBindingsSource?.canUserEditValue?.( {
|
|
250
|
+
select,
|
|
251
|
+
context,
|
|
252
|
+
args: metadata?.bindings?.url?.args,
|
|
253
|
+
} ),
|
|
254
|
+
};
|
|
255
|
+
},
|
|
256
|
+
[ context, isSelected, metadata?.bindings?.url ]
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
async function handleCreate( pageTitle ) {
|
|
260
|
+
const page = await createPageEntity( {
|
|
261
|
+
title: pageTitle,
|
|
262
|
+
status: 'draft',
|
|
263
|
+
} );
|
|
264
|
+
|
|
265
|
+
return {
|
|
266
|
+
id: page.id,
|
|
267
|
+
type: page.type,
|
|
268
|
+
title: page.title.rendered,
|
|
269
|
+
url: page.link,
|
|
270
|
+
kind: 'post-type',
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function createButtonText( searchTerm ) {
|
|
275
|
+
return createInterpolateElement(
|
|
276
|
+
sprintf(
|
|
277
|
+
/* translators: %s: search term. */
|
|
278
|
+
__( 'Create page: <mark>%s</mark>' ),
|
|
279
|
+
searchTerm
|
|
280
|
+
),
|
|
281
|
+
{ mark: <mark /> }
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
222
285
|
function startEditing( event ) {
|
|
223
286
|
event.preventDefault();
|
|
224
287
|
setIsEditingURL( true );
|
|
@@ -249,29 +312,6 @@ function ButtonEdit( props ) {
|
|
|
249
312
|
const useEnterRef = useEnter( { content: text, clientId } );
|
|
250
313
|
const mergedRef = useMergeRefs( [ useEnterRef, richTextRef ] );
|
|
251
314
|
|
|
252
|
-
const { lockUrlControls = false } = useSelect(
|
|
253
|
-
( select ) => {
|
|
254
|
-
if ( ! isSelected ) {
|
|
255
|
-
return {};
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
const blockBindingsSource = getBlockBindingsSource(
|
|
259
|
-
metadata?.bindings?.url?.source
|
|
260
|
-
);
|
|
261
|
-
|
|
262
|
-
return {
|
|
263
|
-
lockUrlControls:
|
|
264
|
-
!! metadata?.bindings?.url &&
|
|
265
|
-
! blockBindingsSource?.canUserEditValue?.( {
|
|
266
|
-
select,
|
|
267
|
-
context,
|
|
268
|
-
args: metadata?.bindings?.url?.args,
|
|
269
|
-
} ),
|
|
270
|
-
};
|
|
271
|
-
},
|
|
272
|
-
[ context, isSelected, metadata?.bindings?.url ]
|
|
273
|
-
);
|
|
274
|
-
|
|
275
315
|
const [ fluidTypographySettings, layout ] = useSettings(
|
|
276
316
|
'typography.fluid',
|
|
277
317
|
'layout'
|
|
@@ -400,6 +440,11 @@ function ButtonEdit( props ) {
|
|
|
400
440
|
} }
|
|
401
441
|
forceIsEditingLink={ isEditingURL }
|
|
402
442
|
settings={ LINK_SETTINGS }
|
|
443
|
+
createSuggestion={
|
|
444
|
+
createPageEntity && handleCreate
|
|
445
|
+
}
|
|
446
|
+
withCreateSuggestion={ userCanCreatePages }
|
|
447
|
+
createSuggestionButtonText={ createButtonText }
|
|
403
448
|
/>
|
|
404
449
|
</Popover>
|
|
405
450
|
) }
|
package/src/categories/edit.js
CHANGED
|
@@ -125,7 +125,7 @@ export default function CategoriesEdit( {
|
|
|
125
125
|
<RichText
|
|
126
126
|
className="wp-block-categories__label"
|
|
127
127
|
aria-label={ __( 'Label text' ) }
|
|
128
|
-
placeholder={ taxonomy
|
|
128
|
+
placeholder={ taxonomy?.name }
|
|
129
129
|
withoutInteractiveFormatting
|
|
130
130
|
value={ label }
|
|
131
131
|
onChange={ ( html ) =>
|
|
@@ -134,7 +134,7 @@ export default function CategoriesEdit( {
|
|
|
134
134
|
/>
|
|
135
135
|
) : (
|
|
136
136
|
<VisuallyHidden as="label" htmlFor={ selectId }>
|
|
137
|
-
{ label ? label : taxonomy
|
|
137
|
+
{ label ? label : taxonomy?.name }
|
|
138
138
|
</VisuallyHidden>
|
|
139
139
|
) }
|
|
140
140
|
<select id={ selectId }>
|
|
@@ -142,7 +142,7 @@ export default function CategoriesEdit( {
|
|
|
142
142
|
{ sprintf(
|
|
143
143
|
/* translators: %s: taxonomy's singular name */
|
|
144
144
|
__( 'Select %s' ),
|
|
145
|
-
taxonomy
|
|
145
|
+
taxonomy?.labels?.singular_name
|
|
146
146
|
) }
|
|
147
147
|
</option>
|
|
148
148
|
{ categoriesList.map( ( category ) =>
|
|
@@ -107,13 +107,21 @@ const useDefaultPageIndex = ( { defaultPage, postId, perPage, queryArgs } ) => {
|
|
|
107
107
|
} ),
|
|
108
108
|
method: 'HEAD',
|
|
109
109
|
parse: false,
|
|
110
|
-
} )
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
} )
|
|
111
|
+
.then( ( res ) => {
|
|
112
|
+
const pages = parseInt( res.headers.get( 'X-WP-TotalPages' ) );
|
|
113
|
+
setDefaultPages( {
|
|
114
|
+
...defaultPages,
|
|
115
|
+
[ key ]: pages <= 1 ? 1 : pages, // If there are 0 pages, it means that there are no comments, but there is no 0th page.
|
|
116
|
+
} );
|
|
117
|
+
} )
|
|
118
|
+
.catch( () => {
|
|
119
|
+
// There's no 0th page, but we can't know the number of pages, fallback to 1.
|
|
120
|
+
setDefaultPages( {
|
|
121
|
+
...defaultPages,
|
|
122
|
+
[ key ]: 1,
|
|
123
|
+
} );
|
|
115
124
|
} );
|
|
116
|
-
} );
|
|
117
125
|
}, [ defaultPage, postId, perPage, setDefaultPages ] );
|
|
118
126
|
|
|
119
127
|
// The oldest one is always the first one.
|
package/src/cover/block.json
CHANGED
|
@@ -111,7 +111,6 @@
|
|
|
111
111
|
}
|
|
112
112
|
},
|
|
113
113
|
"color": {
|
|
114
|
-
"__experimentalDuotone": "> .wp-block-cover__image-background, > .wp-block-cover__video-background",
|
|
115
114
|
"heading": true,
|
|
116
115
|
"text": true,
|
|
117
116
|
"background": false,
|
|
@@ -139,6 +138,14 @@
|
|
|
139
138
|
},
|
|
140
139
|
"interactivity": {
|
|
141
140
|
"clientNavigation": true
|
|
141
|
+
},
|
|
142
|
+
"filter": {
|
|
143
|
+
"duotone": true
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
"selectors": {
|
|
147
|
+
"filter": {
|
|
148
|
+
"duotone": ".wp-block-cover > .wp-block-cover__image-background, .wp-block-cover > .wp-block-cover__video-background"
|
|
142
149
|
}
|
|
143
150
|
},
|
|
144
151
|
"editorStyle": "wp-block-cover-editor",
|
package/src/embed/edit.js
CHANGED
|
@@ -172,7 +172,13 @@ const EmbedEdit = ( props ) => {
|
|
|
172
172
|
// When obtaining an incoming preview,
|
|
173
173
|
// we set the attributes derived from the preview data.
|
|
174
174
|
const mergedAttributes = getMergedAttributes();
|
|
175
|
-
|
|
175
|
+
const hasChanges = Object.keys( mergedAttributes ).some(
|
|
176
|
+
( key ) => mergedAttributes[ key ] !== attributes[ key ]
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
if ( hasChanges ) {
|
|
180
|
+
setAttributes( mergedAttributes );
|
|
181
|
+
}
|
|
176
182
|
|
|
177
183
|
if ( onReplace ) {
|
|
178
184
|
const upgradedBlock = createUpgradedEmbedBlock(
|
package/src/image/constants.js
CHANGED
package/src/image/edit.js
CHANGED
|
@@ -116,9 +116,9 @@ export function ImageEdit( {
|
|
|
116
116
|
// Only observe the max width from the parent container when the parent layout is not flex nor grid.
|
|
117
117
|
// This won't work for them because the container width changes with the image.
|
|
118
118
|
// TODO: Find a way to observe the container width for flex and grid layouts.
|
|
119
|
+
const layoutType = parentLayout?.type || parentLayout?.default?.type;
|
|
119
120
|
const isMaxWidthContainerWidth =
|
|
120
|
-
!
|
|
121
|
-
( parentLayout.type !== 'flex' && parentLayout.type !== 'grid' );
|
|
121
|
+
! layoutType || ( layoutType !== 'flex' && layoutType !== 'grid' );
|
|
122
122
|
const [ maxWidthObserver, maxContentWidth ] = useMaxWidthObserver();
|
|
123
123
|
|
|
124
124
|
const [ placeholderResizeListener, { width: placeholderWidth } ] =
|
|
@@ -452,7 +452,7 @@ export function ImageEdit( {
|
|
|
452
452
|
context={ context }
|
|
453
453
|
clientId={ clientId }
|
|
454
454
|
blockEditingMode={ blockEditingMode }
|
|
455
|
-
parentLayoutType={
|
|
455
|
+
parentLayoutType={ layoutType }
|
|
456
456
|
maxContentWidth={ maxContentWidth }
|
|
457
457
|
/>
|
|
458
458
|
<MediaPlaceholder
|
package/src/image/editor.scss
CHANGED
|
@@ -48,19 +48,6 @@ figure.wp-block-image:not(.wp-block) {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
// This is necessary for the editor resize handles to accurately work on a non-floated, non-resized, small image.
|
|
52
|
-
.wp-block-image .components-resizable-box__container {
|
|
53
|
-
// Using "display: table" because:
|
|
54
|
-
// - it visually hides empty white space in between elements
|
|
55
|
-
// - it allows the element to be as wide as its contents (instead of 100% width, as it would be with `display: block`)
|
|
56
|
-
display: table;
|
|
57
|
-
img {
|
|
58
|
-
display: block;
|
|
59
|
-
width: inherit;
|
|
60
|
-
height: inherit;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
51
|
.block-editor-block-list__block[data-type="core/image"] .block-editor-block-toolbar .block-editor-url-input__button-modal {
|
|
65
52
|
position: absolute;
|
|
66
53
|
left: 0;
|
package/src/image/image.js
CHANGED
|
@@ -19,7 +19,11 @@ import {
|
|
|
19
19
|
DropdownMenu,
|
|
20
20
|
Popover,
|
|
21
21
|
} from '@wordpress/components';
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
useMergeRefs,
|
|
24
|
+
useResizeObserver,
|
|
25
|
+
useViewportMatch,
|
|
26
|
+
} from '@wordpress/compose';
|
|
23
27
|
import { useSelect, useDispatch } from '@wordpress/data';
|
|
24
28
|
import {
|
|
25
29
|
BlockControls,
|
|
@@ -34,13 +38,13 @@ import {
|
|
|
34
38
|
privateApis as blockEditorPrivateApis,
|
|
35
39
|
BlockSettingsMenuControls,
|
|
36
40
|
} from '@wordpress/block-editor';
|
|
37
|
-
import { useEffect, useMemo, useState
|
|
41
|
+
import { useCallback, useEffect, useMemo, useState } from '@wordpress/element';
|
|
38
42
|
import { __, _x, sprintf, isRTL } from '@wordpress/i18n';
|
|
39
43
|
import { getFilename } from '@wordpress/url';
|
|
40
44
|
import { getBlockBindingsSource, switchToBlockType } from '@wordpress/blocks';
|
|
41
45
|
import { crop, overlayText, upload, chevronDown } from '@wordpress/icons';
|
|
42
46
|
import { store as noticesStore } from '@wordpress/notices';
|
|
43
|
-
import { store as coreStore
|
|
47
|
+
import { store as coreStore } from '@wordpress/core-data';
|
|
44
48
|
|
|
45
49
|
/**
|
|
46
50
|
* Internal dependencies
|
|
@@ -54,7 +58,7 @@ import { Caption } from '../utils/caption';
|
|
|
54
58
|
* Module constants
|
|
55
59
|
*/
|
|
56
60
|
import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
|
|
57
|
-
import { MIN_SIZE, ALLOWED_MEDIA_TYPES } from './constants';
|
|
61
|
+
import { MIN_SIZE, ALLOWED_MEDIA_TYPES, SIZED_LAYOUTS } from './constants';
|
|
58
62
|
import { evalAspectRatio } from './utils';
|
|
59
63
|
|
|
60
64
|
const { DimensionsTool, ResolutionTool } = unlock( blockEditorPrivateApis );
|
|
@@ -280,14 +284,23 @@ export default function Image( {
|
|
|
280
284
|
lightbox,
|
|
281
285
|
metadata,
|
|
282
286
|
} = attributes;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
const
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
287
|
+
const [ imageElement, setImageElement ] = useState();
|
|
288
|
+
const [ resizeDelta, setResizeDelta ] = useState( null );
|
|
289
|
+
const [ pixelSize, setPixelSize ] = useState( {} );
|
|
290
|
+
const [ offsetTop, setOffsetTop ] = useState( 0 );
|
|
291
|
+
const setResizeObserved = useResizeObserver( ( [ entry ] ) => {
|
|
292
|
+
if ( ! resizeDelta ) {
|
|
293
|
+
const [ box ] = entry.borderBoxSize;
|
|
294
|
+
setPixelSize( { width: box.inlineSize, height: box.blockSize } );
|
|
295
|
+
}
|
|
296
|
+
// This is usually 0 unless the image height is less than the line-height.
|
|
297
|
+
setOffsetTop( entry.target.offsetTop );
|
|
298
|
+
} );
|
|
299
|
+
const effectResizeableBoxPlacement = useCallback( () => {
|
|
300
|
+
setOffsetTop( imageElement?.offsetTop ?? 0 );
|
|
301
|
+
}, [ imageElement ] );
|
|
302
|
+
const setRefs = useMergeRefs( [ setImageElement, setResizeObserved ] );
|
|
289
303
|
const { allowResize = true } = context;
|
|
290
|
-
const { getBlock, getSettings } = useSelect( blockEditorStore );
|
|
291
304
|
|
|
292
305
|
const image = useSelect(
|
|
293
306
|
( select ) =>
|
|
@@ -299,7 +312,7 @@ export default function Image( {
|
|
|
299
312
|
|
|
300
313
|
const { canInsertCover, imageEditing, imageSizes, maxWidth } = useSelect(
|
|
301
314
|
( select ) => {
|
|
302
|
-
const { getBlockRootClientId, canInsertBlockType } =
|
|
315
|
+
const { getBlockRootClientId, canInsertBlockType, getSettings } =
|
|
303
316
|
select( blockEditorStore );
|
|
304
317
|
|
|
305
318
|
const rootClientId = getBlockRootClientId( clientId );
|
|
@@ -317,10 +330,13 @@ export default function Image( {
|
|
|
317
330
|
},
|
|
318
331
|
[ clientId ]
|
|
319
332
|
);
|
|
333
|
+
const { getBlock, getSettings } = useSelect( blockEditorStore );
|
|
320
334
|
|
|
321
335
|
const { replaceBlocks, toggleSelection } = useDispatch( blockEditorStore );
|
|
322
336
|
const { createErrorNotice, createSuccessNotice } =
|
|
323
337
|
useDispatch( noticesStore );
|
|
338
|
+
const { editEntityRecord } = useDispatch( coreStore );
|
|
339
|
+
|
|
324
340
|
const isLargeViewport = useViewportMatch( 'medium' );
|
|
325
341
|
const isWideAligned = [ 'wide', 'full' ].includes( align );
|
|
326
342
|
const [
|
|
@@ -367,36 +383,20 @@ export default function Image( {
|
|
|
367
383
|
.then( ( blob ) => setExternalBlob( blob ) )
|
|
368
384
|
// Do nothing, cannot upload.
|
|
369
385
|
.catch( () => {} );
|
|
370
|
-
}, [ id, url, isSingleSelected, externalBlob ] );
|
|
386
|
+
}, [ id, url, isSingleSelected, externalBlob, getSettings ] );
|
|
371
387
|
|
|
372
|
-
// Get naturalWidth and naturalHeight from image
|
|
388
|
+
// Get naturalWidth and naturalHeight from image, and fall back to loaded natural
|
|
373
389
|
// width and height. This resolves an issue in Safari where the loaded natural
|
|
374
390
|
// width and height is otherwise lost when switching between alignments.
|
|
375
391
|
// See: https://github.com/WordPress/gutenberg/pull/37210.
|
|
376
392
|
const { naturalWidth, naturalHeight } = useMemo( () => {
|
|
377
393
|
return {
|
|
378
394
|
naturalWidth:
|
|
379
|
-
|
|
380
|
-
loadedNaturalWidth ||
|
|
381
|
-
undefined,
|
|
395
|
+
imageElement?.naturalWidth || loadedNaturalWidth || undefined,
|
|
382
396
|
naturalHeight:
|
|
383
|
-
|
|
384
|
-
loadedNaturalHeight ||
|
|
385
|
-
undefined,
|
|
397
|
+
imageElement?.naturalHeight || loadedNaturalHeight || undefined,
|
|
386
398
|
};
|
|
387
|
-
}, [
|
|
388
|
-
loadedNaturalWidth,
|
|
389
|
-
loadedNaturalHeight,
|
|
390
|
-
imageRef.current?.complete,
|
|
391
|
-
] );
|
|
392
|
-
|
|
393
|
-
function onResizeStart() {
|
|
394
|
-
toggleSelection( false );
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
function onResizeStop() {
|
|
398
|
-
toggleSelection( true );
|
|
399
|
-
}
|
|
399
|
+
}, [ loadedNaturalWidth, loadedNaturalHeight, imageElement?.complete ] );
|
|
400
400
|
|
|
401
401
|
function onImageError() {
|
|
402
402
|
setHasImageErrored( true );
|
|
@@ -541,49 +541,49 @@ export default function Image( {
|
|
|
541
541
|
|
|
542
542
|
const dropdownMenuProps = useToolsPanelDropdownMenuProps();
|
|
543
543
|
|
|
544
|
-
const dimensionsControl =
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
544
|
+
const dimensionsControl =
|
|
545
|
+
isResizable &&
|
|
546
|
+
( SIZED_LAYOUTS.includes( parentLayoutType ) ? (
|
|
547
|
+
<DimensionsTool
|
|
548
|
+
value={ { aspectRatio } }
|
|
549
|
+
onChange={ ( { aspectRatio: newAspectRatio } ) => {
|
|
550
|
+
setAttributes( {
|
|
551
|
+
aspectRatio: newAspectRatio,
|
|
552
|
+
scale: 'cover',
|
|
553
|
+
} );
|
|
554
|
+
} }
|
|
555
|
+
defaultAspectRatio="auto"
|
|
556
|
+
tools={ [ 'aspectRatio' ] }
|
|
557
|
+
/>
|
|
558
|
+
) : (
|
|
559
|
+
<DimensionsTool
|
|
560
|
+
value={ { width, height, scale, aspectRatio } }
|
|
561
|
+
onChange={ ( {
|
|
562
|
+
width: newWidth,
|
|
562
563
|
height: newHeight,
|
|
563
564
|
scale: newScale,
|
|
564
565
|
aspectRatio: newAspectRatio,
|
|
565
|
-
} )
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
);
|
|
566
|
+
} ) => {
|
|
567
|
+
// Rebuilding the object forces setting `undefined`
|
|
568
|
+
// for values that are removed since setAttributes
|
|
569
|
+
// doesn't do anything with keys that aren't set.
|
|
570
|
+
setAttributes( {
|
|
571
|
+
// CSS includes `height: auto`, but we need
|
|
572
|
+
// `width: auto` to fix the aspect ratio when
|
|
573
|
+
// only height is set due to the width and
|
|
574
|
+
// height attributes set via the server.
|
|
575
|
+
width: ! newWidth && newHeight ? 'auto' : newWidth,
|
|
576
|
+
height: newHeight,
|
|
577
|
+
scale: newScale,
|
|
578
|
+
aspectRatio: newAspectRatio,
|
|
579
|
+
} );
|
|
580
|
+
} }
|
|
581
|
+
defaultScale="cover"
|
|
582
|
+
defaultAspectRatio="auto"
|
|
583
|
+
scaleOptions={ scaleOptions }
|
|
584
|
+
unitsOptions={ dimensionsUnitsOptions }
|
|
585
|
+
/>
|
|
586
|
+
) );
|
|
587
587
|
|
|
588
588
|
const resetAll = () => {
|
|
589
589
|
setAttributes( {
|
|
@@ -603,10 +603,7 @@ export default function Image( {
|
|
|
603
603
|
resetAll={ resetAll }
|
|
604
604
|
dropdownMenuProps={ dropdownMenuProps }
|
|
605
605
|
>
|
|
606
|
-
{
|
|
607
|
-
( parentLayoutType === 'grid'
|
|
608
|
-
? aspectRatioControl
|
|
609
|
-
: dimensionsControl ) }
|
|
606
|
+
{ dimensionsControl }
|
|
610
607
|
</ToolsPanel>
|
|
611
608
|
</InspectorControls>
|
|
612
609
|
);
|
|
@@ -835,10 +832,7 @@ export default function Image( {
|
|
|
835
832
|
/>
|
|
836
833
|
</ToolsPanelItem>
|
|
837
834
|
) }
|
|
838
|
-
{
|
|
839
|
-
( parentLayoutType === 'grid'
|
|
840
|
-
? aspectRatioControl
|
|
841
|
-
: dimensionsControl ) }
|
|
835
|
+
{ dimensionsControl }
|
|
842
836
|
{ !! imageSizeOptions.length && (
|
|
843
837
|
<ResolutionTool
|
|
844
838
|
value={ sizeSlug }
|
|
@@ -899,13 +893,6 @@ export default function Image( {
|
|
|
899
893
|
const { postType, postId, queryId } = context;
|
|
900
894
|
const isDescendentOfQueryLoop = Number.isFinite( queryId );
|
|
901
895
|
|
|
902
|
-
const [ , setFeaturedImage ] = useEntityProp(
|
|
903
|
-
'postType',
|
|
904
|
-
postType,
|
|
905
|
-
'featured_media',
|
|
906
|
-
postId
|
|
907
|
-
);
|
|
908
|
-
|
|
909
896
|
let img =
|
|
910
897
|
temporaryURL && hasImageErrored ? (
|
|
911
898
|
// Show a placeholder during upload when the blob URL can't be loaded. This can
|
|
@@ -926,17 +913,19 @@ export default function Image( {
|
|
|
926
913
|
alt={ defaultedAlt }
|
|
927
914
|
onError={ onImageError }
|
|
928
915
|
onLoad={ onImageLoad }
|
|
929
|
-
ref={
|
|
916
|
+
ref={ setRefs }
|
|
930
917
|
className={ borderProps.className }
|
|
918
|
+
width={ naturalWidth }
|
|
919
|
+
height={ naturalHeight }
|
|
931
920
|
style={ {
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
921
|
+
aspectRatio,
|
|
922
|
+
...( resizeDelta
|
|
923
|
+
? {
|
|
924
|
+
width: pixelSize.width + resizeDelta.width,
|
|
925
|
+
height:
|
|
926
|
+
pixelSize.height + resizeDelta.height,
|
|
927
|
+
}
|
|
928
|
+
: { width, height } ),
|
|
940
929
|
objectFit: scale,
|
|
941
930
|
...borderProps.style,
|
|
942
931
|
...shadowProps.style,
|
|
@@ -953,8 +942,7 @@ export default function Image( {
|
|
|
953
942
|
<ImageEditor
|
|
954
943
|
id={ id }
|
|
955
944
|
url={ url }
|
|
956
|
-
|
|
957
|
-
height={ numericHeight }
|
|
945
|
+
{ ...pixelSize }
|
|
958
946
|
naturalHeight={ naturalHeight }
|
|
959
947
|
naturalWidth={ naturalWidth }
|
|
960
948
|
onSaveImage={ ( imageAttributes ) =>
|
|
@@ -967,26 +955,21 @@ export default function Image( {
|
|
|
967
955
|
/>
|
|
968
956
|
</ImageWrapper>
|
|
969
957
|
);
|
|
970
|
-
} else if ( ! isResizable || parentLayoutType === 'grid' ) {
|
|
971
|
-
img = (
|
|
972
|
-
<div style={ { width, height, aspectRatio } }>
|
|
973
|
-
<ImageWrapper href={ href }>{ img }</ImageWrapper>
|
|
974
|
-
</div>
|
|
975
|
-
);
|
|
976
958
|
} else {
|
|
959
|
+
img = <ImageWrapper href={ href }>{ img }</ImageWrapper>;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
let resizableBox;
|
|
963
|
+
if (
|
|
964
|
+
isResizable &&
|
|
965
|
+
isSingleSelected &&
|
|
966
|
+
! isEditingImage &&
|
|
967
|
+
! SIZED_LAYOUTS.includes( parentLayoutType )
|
|
968
|
+
) {
|
|
977
969
|
const numericRatio = aspectRatio && evalAspectRatio( aspectRatio );
|
|
978
|
-
const customRatio =
|
|
970
|
+
const customRatio = pixelSize.width / pixelSize.height;
|
|
979
971
|
const naturalRatio = naturalWidth / naturalHeight;
|
|
980
972
|
const ratio = numericRatio || customRatio || naturalRatio || 1;
|
|
981
|
-
const currentWidth =
|
|
982
|
-
! numericWidth && numericHeight
|
|
983
|
-
? numericHeight * ratio
|
|
984
|
-
: numericWidth;
|
|
985
|
-
const currentHeight =
|
|
986
|
-
! numericHeight && numericWidth
|
|
987
|
-
? numericWidth / ratio
|
|
988
|
-
: numericHeight;
|
|
989
|
-
|
|
990
973
|
const minWidth =
|
|
991
974
|
naturalWidth < naturalHeight ? MIN_SIZE : MIN_SIZE * ratio;
|
|
992
975
|
const minHeight =
|
|
@@ -1032,21 +1015,17 @@ export default function Image( {
|
|
|
1032
1015
|
}
|
|
1033
1016
|
}
|
|
1034
1017
|
/* eslint-enable no-lonely-if */
|
|
1035
|
-
|
|
1018
|
+
resizableBox = (
|
|
1036
1019
|
<ResizableBox
|
|
1020
|
+
ref={ effectResizeableBoxPlacement }
|
|
1037
1021
|
style={ {
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
: undefined,
|
|
1044
|
-
} }
|
|
1045
|
-
size={ {
|
|
1046
|
-
width: currentWidth ?? 'auto',
|
|
1047
|
-
height: currentHeight ?? 'auto',
|
|
1022
|
+
position: 'absolute',
|
|
1023
|
+
// To match the vertical-align: bottom of the img (from style.scss)
|
|
1024
|
+
// syncs the top with the img. This matters when the img height is
|
|
1025
|
+
// less than the line-height.
|
|
1026
|
+
inset: `${ offsetTop }px 0 0 0`,
|
|
1048
1027
|
} }
|
|
1049
|
-
|
|
1028
|
+
size={ pixelSize }
|
|
1050
1029
|
minWidth={ minWidth }
|
|
1051
1030
|
maxWidth={ maxResizeWidth }
|
|
1052
1031
|
minHeight={ minHeight }
|
|
@@ -1058,9 +1037,19 @@ export default function Image( {
|
|
|
1058
1037
|
bottom: true,
|
|
1059
1038
|
left: showLeftHandle,
|
|
1060
1039
|
} }
|
|
1061
|
-
onResizeStart={
|
|
1062
|
-
|
|
1063
|
-
|
|
1040
|
+
onResizeStart={ () => {
|
|
1041
|
+
toggleSelection( false );
|
|
1042
|
+
} }
|
|
1043
|
+
onResize={ ( event, direction, elt, delta ) => {
|
|
1044
|
+
setResizeDelta( delta );
|
|
1045
|
+
} }
|
|
1046
|
+
onResizeStop={ ( event, direction, elt, delta ) => {
|
|
1047
|
+
toggleSelection( true );
|
|
1048
|
+
setResizeDelta( null );
|
|
1049
|
+
setPixelSize( ( current ) => ( {
|
|
1050
|
+
width: current.width + delta.width,
|
|
1051
|
+
height: current.height + delta.height,
|
|
1052
|
+
} ) );
|
|
1064
1053
|
|
|
1065
1054
|
// Clear hardcoded width if the resized width is close to the max-content width.
|
|
1066
1055
|
if (
|
|
@@ -1091,9 +1080,7 @@ export default function Image( {
|
|
|
1091
1080
|
} );
|
|
1092
1081
|
} }
|
|
1093
1082
|
resizeRatio={ align === 'center' ? 2 : 1 }
|
|
1094
|
-
|
|
1095
|
-
<ImageWrapper href={ href }>{ img }</ImageWrapper>
|
|
1096
|
-
</ResizableBox>
|
|
1083
|
+
/>
|
|
1097
1084
|
);
|
|
1098
1085
|
}
|
|
1099
1086
|
|
|
@@ -1111,7 +1098,9 @@ export default function Image( {
|
|
|
1111
1098
|
* Set the post's featured image with the current image.
|
|
1112
1099
|
*/
|
|
1113
1100
|
const setPostFeatureImage = () => {
|
|
1114
|
-
|
|
1101
|
+
editEntityRecord( 'postType', postType, postId, {
|
|
1102
|
+
featured_media: id,
|
|
1103
|
+
} );
|
|
1115
1104
|
createSuccessNotice( __( 'Post featured image updated.' ), {
|
|
1116
1105
|
type: 'snackbar',
|
|
1117
1106
|
} );
|
|
@@ -1139,6 +1128,7 @@ export default function Image( {
|
|
|
1139
1128
|
{ controls }
|
|
1140
1129
|
{ featuredImageControl }
|
|
1141
1130
|
{ img }
|
|
1131
|
+
{ resizableBox }
|
|
1142
1132
|
|
|
1143
1133
|
<Caption
|
|
1144
1134
|
attributes={ attributes }
|