@wordpress/block-library 10.2.0 → 10.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.
- package/CHANGELOG.md +16 -0
- package/build/accordion-panel/block.json +1 -0
- package/build/code/edit.cjs +3 -1
- package/build/code/edit.cjs.map +2 -2
- package/build/cover/block.json +1 -0
- package/build/cover/edit/block-controls.cjs +3 -1
- package/build/cover/edit/block-controls.cjs.map +2 -2
- package/build/cover/edit/index.cjs +75 -31
- package/build/cover/edit/index.cjs.map +2 -2
- package/build/embed/edit.cjs +1 -1
- package/build/embed/edit.cjs.map +2 -2
- package/build/embed/embed-placeholder.cjs +1 -1
- package/build/embed/embed-placeholder.cjs.map +2 -2
- package/build/gallery/dynamic-gallery.cjs +104 -61
- package/build/gallery/dynamic-gallery.cjs.map +3 -3
- package/build/gallery/use-dynamic-gallery.cjs +15 -8
- package/build/gallery/use-dynamic-gallery.cjs.map +2 -2
- package/build/heading/edit.cjs +1 -1
- package/build/heading/edit.cjs.map +2 -2
- package/build/html/modal.cjs +63 -54
- package/build/html/modal.cjs.map +3 -3
- package/build/icon/block.json +5 -3
- package/build/image/edit.cjs +1 -1
- package/build/image/edit.cjs.map +2 -2
- package/build/image/image.cjs +29 -5
- package/build/image/image.cjs.map +3 -3
- package/build/image/use-open-image-media-editor-modal.cjs +6 -2
- package/build/image/use-open-image-media-editor-modal.cjs.map +2 -2
- package/build/list-item/hooks/use-indent-list-item.cjs +10 -2
- package/build/list-item/hooks/use-indent-list-item.cjs.map +2 -2
- package/build/math/edit.cjs +39 -56
- package/build/math/edit.cjs.map +3 -3
- package/build/media-text/edit.cjs +2 -1
- package/build/media-text/edit.cjs.map +2 -2
- package/build/more/edit.cjs +2 -2
- package/build/more/edit.cjs.map +2 -2
- package/build/navigation/edit/index.cjs +30 -16
- package/build/navigation/edit/index.cjs.map +3 -3
- package/build/navigation/edit/use-layout-custom-properties.cjs +72 -0
- package/build/navigation/edit/use-layout-custom-properties.cjs.map +7 -0
- package/build/navigation/view.cjs +9 -6
- package/build/navigation/view.cjs.map +2 -2
- package/build/navigation-link/edit.cjs +3 -3
- package/build/navigation-link/edit.cjs.map +2 -2
- package/build/navigation-link/link-ui/index.cjs +2 -2
- package/build/navigation-link/link-ui/index.cjs.map +2 -2
- package/build/paragraph/block.json +0 -1
- package/build/paragraph/edit.cjs +5 -2
- package/build/paragraph/edit.cjs.map +3 -3
- package/build/paragraph/index.cjs +4 -1
- package/build/paragraph/index.cjs.map +2 -2
- package/build/playlist/context.cjs +2 -1
- package/build/playlist/context.cjs.map +2 -2
- package/build/playlist/edit.cjs +113 -26
- package/build/playlist/edit.cjs.map +2 -2
- package/build/playlist/utils.cjs +19 -4
- package/build/playlist/utils.cjs.map +2 -2
- package/build/playlist-track/edit.cjs +21 -6
- package/build/playlist-track/edit.cjs.map +2 -2
- package/build/post-content/edit.cjs +36 -15
- package/build/post-content/edit.cjs.map +2 -2
- package/build/post-featured-image/edit.cjs +3 -2
- package/build/post-featured-image/edit.cjs.map +2 -2
- package/build/post-terms/edit.cjs +2 -2
- package/build/post-terms/edit.cjs.map +2 -2
- package/build/post-title/edit.cjs +2 -2
- package/build/post-title/edit.cjs.map +2 -2
- package/build/preformatted/edit.cjs +3 -1
- package/build/preformatted/edit.cjs.map +2 -2
- package/build/pullquote/edit.cjs +5 -3
- package/build/pullquote/edit.cjs.map +2 -2
- package/build/query/edit/inspector-controls/index.cjs +4 -1
- package/build/query/edit/inspector-controls/index.cjs.map +2 -2
- package/build/query/edit/inspector-controls/offset-controls.cjs +1 -1
- package/build/query/edit/inspector-controls/offset-controls.cjs.map +2 -2
- package/build/read-more/edit.cjs +3 -1
- package/build/read-more/edit.cjs.map +2 -2
- package/build/site-tagline/edit.cjs +3 -1
- package/build/site-tagline/edit.cjs.map +2 -2
- package/build/site-title/edit.cjs +3 -1
- package/build/site-title/edit.cjs.map +2 -2
- package/build/social-links/edit.cjs +11 -4
- package/build/social-links/edit.cjs.map +2 -2
- package/build/tab-list/block.json +2 -1
- package/build/tab-list/edit.cjs +2 -0
- package/build/tab-list/edit.cjs.map +3 -3
- package/build/tab-list/tab-movers.cjs +87 -0
- package/build/tab-list/tab-movers.cjs.map +7 -0
- package/build/tab-panel/edit.cjs +1 -9
- package/build/tab-panel/edit.cjs.map +2 -2
- package/build/table/edit.cjs +1 -1
- package/build/table/edit.cjs.map +2 -2
- package/build/tabs/use-tab-actions.cjs +23 -1
- package/build/tabs/use-tab-actions.cjs.map +2 -2
- package/build/utils/caption.cjs +2 -2
- package/build/utils/caption.cjs.map +2 -2
- package/build/verse/edit.cjs +3 -1
- package/build/verse/edit.cjs.map +2 -2
- package/build/video/tracks-editor.cjs +0 -1
- package/build/video/tracks-editor.cjs.map +2 -2
- package/build-module/accordion-panel/block.json +1 -0
- package/build-module/code/edit.mjs +3 -1
- package/build-module/code/edit.mjs.map +2 -2
- package/build-module/cover/block.json +1 -0
- package/build-module/cover/edit/block-controls.mjs +3 -1
- package/build-module/cover/edit/block-controls.mjs.map +2 -2
- package/build-module/cover/edit/index.mjs +78 -34
- package/build-module/cover/edit/index.mjs.map +2 -2
- package/build-module/embed/edit.mjs +1 -1
- package/build-module/embed/edit.mjs.map +2 -2
- package/build-module/embed/embed-placeholder.mjs +1 -1
- package/build-module/embed/embed-placeholder.mjs.map +2 -2
- package/build-module/gallery/dynamic-gallery.mjs +104 -61
- package/build-module/gallery/dynamic-gallery.mjs.map +2 -2
- package/build-module/gallery/use-dynamic-gallery.mjs +16 -9
- package/build-module/gallery/use-dynamic-gallery.mjs.map +2 -2
- package/build-module/heading/edit.mjs +1 -1
- package/build-module/heading/edit.mjs.map +2 -2
- package/build-module/html/modal.mjs +68 -55
- package/build-module/html/modal.mjs.map +2 -2
- package/build-module/icon/block.json +5 -3
- package/build-module/image/edit.mjs +1 -1
- package/build-module/image/edit.mjs.map +2 -2
- package/build-module/image/image.mjs +19 -5
- package/build-module/image/image.mjs.map +2 -2
- package/build-module/image/use-open-image-media-editor-modal.mjs +6 -2
- package/build-module/image/use-open-image-media-editor-modal.mjs.map +2 -2
- package/build-module/list-item/hooks/use-indent-list-item.mjs +10 -2
- package/build-module/list-item/hooks/use-indent-list-item.mjs.map +2 -2
- package/build-module/math/edit.mjs +41 -60
- package/build-module/math/edit.mjs.map +2 -2
- package/build-module/media-text/edit.mjs +2 -1
- package/build-module/media-text/edit.mjs.map +2 -2
- package/build-module/more/edit.mjs +2 -2
- package/build-module/more/edit.mjs.map +2 -2
- package/build-module/navigation/edit/index.mjs +30 -16
- package/build-module/navigation/edit/index.mjs.map +2 -2
- package/build-module/navigation/edit/use-layout-custom-properties.mjs +51 -0
- package/build-module/navigation/edit/use-layout-custom-properties.mjs.map +7 -0
- package/build-module/navigation/view.mjs +9 -6
- package/build-module/navigation/view.mjs.map +2 -2
- package/build-module/navigation-link/edit.mjs +3 -3
- package/build-module/navigation-link/edit.mjs.map +2 -2
- package/build-module/navigation-link/link-ui/index.mjs +2 -2
- package/build-module/navigation-link/link-ui/index.mjs.map +2 -2
- package/build-module/paragraph/block.json +0 -1
- package/build-module/paragraph/edit.mjs +6 -2
- package/build-module/paragraph/edit.mjs.map +2 -2
- package/build-module/paragraph/index.mjs +4 -1
- package/build-module/paragraph/index.mjs.map +2 -2
- package/build-module/playlist/context.mjs +2 -1
- package/build-module/playlist/context.mjs.map +2 -2
- package/build-module/playlist/edit.mjs +113 -27
- package/build-module/playlist/edit.mjs.map +2 -2
- package/build-module/playlist/utils.mjs +19 -4
- package/build-module/playlist/utils.mjs.map +2 -2
- package/build-module/playlist-track/edit.mjs +21 -6
- package/build-module/playlist-track/edit.mjs.map +2 -2
- package/build-module/post-content/edit.mjs +37 -15
- package/build-module/post-content/edit.mjs.map +2 -2
- package/build-module/post-featured-image/edit.mjs +3 -2
- package/build-module/post-featured-image/edit.mjs.map +2 -2
- package/build-module/post-terms/edit.mjs +2 -2
- package/build-module/post-terms/edit.mjs.map +2 -2
- package/build-module/post-title/edit.mjs +2 -2
- package/build-module/post-title/edit.mjs.map +2 -2
- package/build-module/preformatted/edit.mjs +3 -1
- package/build-module/preformatted/edit.mjs.map +2 -2
- package/build-module/pullquote/edit.mjs +5 -3
- package/build-module/pullquote/edit.mjs.map +2 -2
- package/build-module/query/edit/inspector-controls/index.mjs +5 -2
- package/build-module/query/edit/inspector-controls/index.mjs.map +2 -2
- package/build-module/query/edit/inspector-controls/offset-controls.mjs +2 -2
- package/build-module/query/edit/inspector-controls/offset-controls.mjs.map +2 -2
- package/build-module/read-more/edit.mjs +3 -1
- package/build-module/read-more/edit.mjs.map +2 -2
- package/build-module/site-tagline/edit.mjs +3 -1
- package/build-module/site-tagline/edit.mjs.map +2 -2
- package/build-module/site-title/edit.mjs +3 -1
- package/build-module/site-title/edit.mjs.map +2 -2
- package/build-module/social-links/edit.mjs +11 -4
- package/build-module/social-links/edit.mjs.map +2 -2
- package/build-module/tab-list/block.json +2 -1
- package/build-module/tab-list/edit.mjs +2 -0
- package/build-module/tab-list/edit.mjs.map +2 -2
- package/build-module/tab-list/tab-movers.mjs +59 -0
- package/build-module/tab-list/tab-movers.mjs.map +7 -0
- package/build-module/tab-panel/edit.mjs +1 -9
- package/build-module/tab-panel/edit.mjs.map +2 -2
- package/build-module/table/edit.mjs +1 -1
- package/build-module/table/edit.mjs.map +2 -2
- package/build-module/tabs/use-tab-actions.mjs +23 -1
- package/build-module/tabs/use-tab-actions.mjs.map +2 -2
- package/build-module/utils/caption.mjs +2 -2
- package/build-module/utils/caption.mjs.map +2 -2
- package/build-module/verse/edit.mjs +3 -1
- package/build-module/verse/edit.mjs.map +2 -2
- package/build-module/video/tracks-editor.mjs +0 -1
- package/build-module/video/tracks-editor.mjs.map +2 -2
- package/build-style/cover/editor-rtl.css +3 -0
- package/build-style/cover/editor.css +3 -0
- package/build-style/editor-rtl.css +18 -41
- package/build-style/editor.css +18 -41
- package/build-style/icon/editor-rtl.css +1 -4
- package/build-style/icon/editor.css +1 -4
- package/build-style/image/editor-rtl.css +3 -32
- package/build-style/image/editor.css +3 -32
- package/build-style/playlist/editor-rtl.css +0 -5
- package/build-style/playlist/editor.css +0 -5
- package/build-style/playlist/style-rtl.css +44 -4
- package/build-style/playlist/style.css +44 -4
- package/build-style/pullquote/editor-rtl.css +4 -0
- package/build-style/pullquote/editor.css +4 -0
- package/build-style/style-rtl.css +44 -4
- package/build-style/style.css +44 -4
- package/build-style/tab-list/editor-rtl.css +101 -0
- package/build-style/tab-list/editor.css +101 -0
- package/package.json +43 -43
- package/src/accordion-panel/block.json +1 -0
- package/src/breadcrumbs/index.php +3 -1
- package/src/button/index.php +1 -1
- package/src/code/edit.js +7 -2
- package/src/cover/block.json +1 -0
- package/src/cover/edit/block-controls.js +5 -0
- package/src/cover/edit/index.js +100 -35
- package/src/cover/editor.scss +6 -0
- package/src/cover/index.php +9 -2
- package/src/editor.scss +1 -0
- package/src/embed/edit.js +3 -1
- package/src/embed/embed-placeholder.js +9 -7
- package/src/form/index.php +6 -4
- package/src/gallery/dynamic-gallery.js +133 -74
- package/src/gallery/use-dynamic-gallery.js +27 -12
- package/src/heading/edit.js +1 -1
- package/src/html/modal.js +13 -2
- package/src/icon/README.md +1 -3
- package/src/icon/block.json +5 -3
- package/src/icon/editor.scss +1 -4
- package/src/image/edit.js +1 -5
- package/src/image/editor.scss +6 -46
- package/src/image/image.js +37 -3
- package/src/image/test/use-open-image-media-editor-modal.js +37 -1
- package/src/image/use-open-image-media-editor-modal.js +8 -1
- package/src/latest-posts/index.php +3 -2
- package/src/list-item/hooks/use-indent-list-item.js +10 -1
- package/src/math/edit.js +42 -59
- package/src/media-text/edit.js +1 -0
- package/src/media-text/index.php +11 -2
- package/src/more/edit.js +7 -4
- package/src/navigation/edit/index.js +52 -36
- package/src/navigation/edit/test/layout-custom-properties.js +138 -0
- package/src/navigation/edit/use-layout-custom-properties.js +84 -0
- package/src/navigation/index.php +123 -12
- package/src/navigation/test/view.js +51 -0
- package/src/navigation/view.js +15 -14
- package/src/navigation-link/edit.js +11 -7
- package/src/navigation-link/index.php +64 -0
- package/src/navigation-link/link-ui/index.js +2 -1
- package/src/navigation-link/test/__snapshots__/hooks.js.snap +1 -1
- package/src/page-list/index.php +4 -3
- package/src/paragraph/README.md +0 -1
- package/src/paragraph/block.json +0 -1
- package/src/paragraph/edit.js +9 -2
- package/src/paragraph/index.js +4 -1
- package/src/pattern/index.php +5 -5
- package/src/playlist/context.js +1 -0
- package/src/playlist/edit.js +151 -47
- package/src/playlist/editor.scss +0 -7
- package/src/playlist/index.php +14 -9
- package/src/playlist/style.scss +3 -0
- package/src/playlist/test/edit-component.js +139 -0
- package/src/playlist/test/edit.js +30 -0
- package/src/playlist/utils.js +25 -4
- package/src/playlist-track/edit.js +22 -5
- package/src/playlist-track/index.php +8 -7
- package/src/playlist-track/test/edit.js +87 -3
- package/src/post-content/edit.js +45 -16
- package/src/post-excerpt/index.php +4 -1
- package/src/post-featured-image/edit.js +3 -2
- package/src/post-featured-image/index.php +4 -1
- package/src/post-terms/edit.js +7 -4
- package/src/post-title/edit.js +5 -3
- package/src/preformatted/edit.js +7 -2
- package/src/pullquote/edit.js +9 -4
- package/src/pullquote/editor.scss +6 -0
- package/src/query/edit/inspector-controls/index.js +5 -2
- package/src/query/edit/inspector-controls/offset-controls.js +2 -2
- package/src/read-more/edit.js +7 -2
- package/src/rss/index.php +9 -3
- package/src/site-tagline/edit.js +7 -2
- package/src/site-title/edit.js +7 -2
- package/src/social-link/index.php +19 -9
- package/src/social-links/edit.js +21 -12
- package/src/tab-list/block.json +2 -1
- package/src/tab-list/edit.js +2 -0
- package/src/tab-list/editor.scss +9 -0
- package/src/tab-list/tab-movers.js +72 -0
- package/src/tab-panel/edit.js +1 -9
- package/src/table/edit.js +1 -1
- package/src/table-of-contents/index.php +386 -1
- package/src/tabs/use-tab-actions.js +32 -3
- package/src/tag-cloud/index.php +3 -2
- package/src/template-part/index.php +2 -1
- package/src/utils/caption.js +7 -4
- package/src/utils/test/waveform-utils.js +63 -0
- package/src/verse/edit.js +7 -2
- package/src/video/index.php +2 -2
- package/src/video/tracks-editor.js +0 -1
package/src/code/edit.js
CHANGED
|
@@ -26,8 +26,13 @@ export default function CodeEdit( {
|
|
|
26
26
|
aria-label={ __( 'Code' ) }
|
|
27
27
|
preserveWhiteSpace
|
|
28
28
|
__unstablePastePlainText
|
|
29
|
-
__unstableOnSplitAtDoubleLineEnd={
|
|
30
|
-
insertBlocksAfter
|
|
29
|
+
__unstableOnSplitAtDoubleLineEnd={
|
|
30
|
+
insertBlocksAfter
|
|
31
|
+
? () =>
|
|
32
|
+
insertBlocksAfter(
|
|
33
|
+
createBlock( getDefaultBlockName() )
|
|
34
|
+
)
|
|
35
|
+
: undefined
|
|
31
36
|
}
|
|
32
37
|
style={ { whiteSpace: 'break-spaces' } }
|
|
33
38
|
/>
|
package/src/cover/block.json
CHANGED
|
@@ -35,6 +35,7 @@ export default function CoverBlockControls( {
|
|
|
35
35
|
onEditMedia,
|
|
36
36
|
editMediaButtonRef,
|
|
37
37
|
showEditMediaButton,
|
|
38
|
+
isEditMediaDisabled,
|
|
38
39
|
blockEditingMode,
|
|
39
40
|
} ) {
|
|
40
41
|
const {
|
|
@@ -123,6 +124,10 @@ export default function CoverBlockControls( {
|
|
|
123
124
|
label={ __( 'Crop background image' ) }
|
|
124
125
|
onClick={ onEditMedia }
|
|
125
126
|
aria-haspopup="dialog"
|
|
127
|
+
// Disable rather than hide while the edited image
|
|
128
|
+
// loads, so the button keeps focus when the modal
|
|
129
|
+
// closes instead of dropping it to the canvas.
|
|
130
|
+
disabled={ isEditMediaDisabled }
|
|
126
131
|
/>
|
|
127
132
|
) }
|
|
128
133
|
</BlockControls>
|
package/src/cover/edit/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
useLayoutEffect,
|
|
14
14
|
useMemo,
|
|
15
15
|
useRef,
|
|
16
|
+
useState,
|
|
16
17
|
} from '@wordpress/element';
|
|
17
18
|
import { Placeholder, SandBox, Spinner } from '@wordpress/components';
|
|
18
19
|
import { compose, useResizeObserver } from '@wordpress/compose';
|
|
@@ -20,7 +21,6 @@ import {
|
|
|
20
21
|
withColors,
|
|
21
22
|
ColorPalette,
|
|
22
23
|
useBlockProps,
|
|
23
|
-
useSettings,
|
|
24
24
|
useInnerBlocksProps,
|
|
25
25
|
__experimentalUseGradient,
|
|
26
26
|
store as blockEditorStore,
|
|
@@ -28,7 +28,8 @@ import {
|
|
|
28
28
|
privateApis as blockEditorPrivateApis,
|
|
29
29
|
} from '@wordpress/block-editor';
|
|
30
30
|
import { __ } from '@wordpress/i18n';
|
|
31
|
-
import { useSelect, useDispatch } from '@wordpress/data';
|
|
31
|
+
import { useSelect, useDispatch, useRegistry } from '@wordpress/data';
|
|
32
|
+
import { createBlocksFromInnerBlocksTemplate } from '@wordpress/blocks';
|
|
32
33
|
import { isBlobURL } from '@wordpress/blob';
|
|
33
34
|
import { store as noticesStore } from '@wordpress/notices';
|
|
34
35
|
|
|
@@ -134,8 +135,9 @@ function CoverEdit( {
|
|
|
134
135
|
[]
|
|
135
136
|
);
|
|
136
137
|
|
|
137
|
-
const { __unstableMarkNextChangeAsNotPersistent } =
|
|
138
|
+
const { __unstableMarkNextChangeAsNotPersistent, replaceInnerBlocks } =
|
|
138
139
|
useDispatch( blockEditorStore );
|
|
140
|
+
const registry = useRegistry();
|
|
139
141
|
|
|
140
142
|
// Ref to access latest values after async operations (e.g. getMediaColor),
|
|
141
143
|
// avoiding stale values that could overwrite concurrent remote changes.
|
|
@@ -225,6 +227,35 @@ function CoverEdit( {
|
|
|
225
227
|
const { createErrorNotice } = useDispatch( noticesStore );
|
|
226
228
|
const { gradientClass, gradientValue } = __experimentalUseGradient();
|
|
227
229
|
|
|
230
|
+
// Create the initial inner paragraph when the block gains a background
|
|
231
|
+
// and has no content yet.
|
|
232
|
+
const scaffoldInnerBlocks = () => {
|
|
233
|
+
const {
|
|
234
|
+
getBlocks,
|
|
235
|
+
isBlockSelected,
|
|
236
|
+
getSelectedBlocksInitialCaretPosition,
|
|
237
|
+
} = registry.select( blockEditorStore );
|
|
238
|
+
if ( getBlocks( clientId ).length > 0 ) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
// Check for fontSize support before we pass a fontSize attribute to
|
|
242
|
+
// the innerBlocks.
|
|
243
|
+
const [ fontSizes ] = unlock(
|
|
244
|
+
registry.select( blockEditorStore )
|
|
245
|
+
).getBlockSettings( clientId, 'typography.fontSizes' );
|
|
246
|
+
const hasFontSizes = fontSizes?.length > 0;
|
|
247
|
+
replaceInnerBlocks(
|
|
248
|
+
clientId,
|
|
249
|
+
createBlocksFromInnerBlocksTemplate(
|
|
250
|
+
getInnerBlocksTemplate( {
|
|
251
|
+
fontSize: hasFontSizes ? 'large' : undefined,
|
|
252
|
+
} )
|
|
253
|
+
),
|
|
254
|
+
isBlockSelected( clientId ),
|
|
255
|
+
getSelectedBlocksInitialCaretPosition()
|
|
256
|
+
);
|
|
257
|
+
};
|
|
258
|
+
|
|
228
259
|
const onSelectMedia = async ( newMedia ) => {
|
|
229
260
|
const mediaAttributes = attributesFromMedia( newMedia );
|
|
230
261
|
const isImage = [ newMedia?.type, newMedia?.media_type ].includes(
|
|
@@ -289,13 +320,17 @@ function CoverEdit( {
|
|
|
289
320
|
}
|
|
290
321
|
}
|
|
291
322
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
323
|
+
registry.batch( () => {
|
|
324
|
+
setAttributes( {
|
|
325
|
+
...mediaAttributes,
|
|
326
|
+
focalPoint: undefined,
|
|
327
|
+
useFeaturedImage: undefined,
|
|
328
|
+
dimRatio: newDimRatio,
|
|
329
|
+
isDark: newIsDark,
|
|
330
|
+
isUserOverlayColor: currentAttrs.isUserOverlayColor || false,
|
|
331
|
+
} );
|
|
332
|
+
|
|
333
|
+
scaffoldInnerBlocks();
|
|
299
334
|
} );
|
|
300
335
|
};
|
|
301
336
|
|
|
@@ -345,9 +380,17 @@ function CoverEdit( {
|
|
|
345
380
|
// Fold next attribute change into the same undo level as the setOverlayColor above.
|
|
346
381
|
__unstableMarkNextChangeAsNotPersistent();
|
|
347
382
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
383
|
+
registry.batch( () => {
|
|
384
|
+
setAttributes( {
|
|
385
|
+
isUserOverlayColor: true,
|
|
386
|
+
isDark: newIsDark,
|
|
387
|
+
} );
|
|
388
|
+
|
|
389
|
+
// Skip when the color is cleared: that returns the block to its
|
|
390
|
+
// placeholder, which only renders while there is no content.
|
|
391
|
+
if ( newOverlayColor ) {
|
|
392
|
+
scaffoldInnerBlocks();
|
|
393
|
+
}
|
|
351
394
|
} );
|
|
352
395
|
};
|
|
353
396
|
|
|
@@ -424,6 +467,12 @@ function CoverEdit( {
|
|
|
424
467
|
return getBackgroundEmbedHtml( embedPreview.html );
|
|
425
468
|
}, [ embedPreview, backgroundType ] );
|
|
426
469
|
|
|
470
|
+
// Set while the media editor has pointed the cover at a freshly
|
|
471
|
+
// generated file the browser hasn't finished loading; cleared by the
|
|
472
|
+
// background <img> load/error handlers (or immediately after
|
|
473
|
+
// setAttributes for CSS backgrounds, which never fire load events).
|
|
474
|
+
const [ isSwappingMedia, setIsSwappingMedia ] = useState( false );
|
|
475
|
+
|
|
427
476
|
const isUploadingMedia = isTemporaryMedia( id, url );
|
|
428
477
|
|
|
429
478
|
const isImageBackground = IMAGE_BACKGROUND_TYPE === backgroundType;
|
|
@@ -477,22 +526,11 @@ function CoverEdit( {
|
|
|
477
526
|
const ref = useRef();
|
|
478
527
|
const blockProps = useBlockProps( { ref } );
|
|
479
528
|
|
|
480
|
-
// Check for fontSize support before we pass a fontSize attribute to the innerBlocks.
|
|
481
|
-
const [ fontSizes ] = useSettings( 'typography.fontSizes' );
|
|
482
|
-
const hasFontSizes = fontSizes?.length > 0;
|
|
483
|
-
const innerBlocksTemplate = getInnerBlocksTemplate( {
|
|
484
|
-
fontSize: hasFontSizes ? 'large' : undefined,
|
|
485
|
-
} );
|
|
486
|
-
|
|
487
529
|
const innerBlocksProps = useInnerBlocksProps(
|
|
488
530
|
{
|
|
489
531
|
className: 'wp-block-cover__inner-container',
|
|
490
532
|
},
|
|
491
533
|
{
|
|
492
|
-
// Avoid template sync when the `templateLock` value is `all` or `contentOnly`.
|
|
493
|
-
// See: https://github.com/WordPress/gutenberg/pull/45632
|
|
494
|
-
template: ! hasInnerBlocks ? innerBlocksTemplate : undefined,
|
|
495
|
-
templateInsertUpdatesSelection: true,
|
|
496
534
|
allowedBlocks,
|
|
497
535
|
templateLock,
|
|
498
536
|
dropZoneElement: ref.current,
|
|
@@ -526,6 +564,10 @@ function CoverEdit( {
|
|
|
526
564
|
return;
|
|
527
565
|
}
|
|
528
566
|
|
|
567
|
+
if ( newId !== id && newUrl ) {
|
|
568
|
+
setIsSwappingMedia( true );
|
|
569
|
+
}
|
|
570
|
+
|
|
529
571
|
const nextAttributes = {
|
|
530
572
|
id: newId,
|
|
531
573
|
backgroundType: IMAGE_BACKGROUND_TYPE,
|
|
@@ -563,6 +605,17 @@ function CoverEdit( {
|
|
|
563
605
|
}
|
|
564
606
|
|
|
565
607
|
setAttributes( nextAttributes );
|
|
608
|
+
|
|
609
|
+
// A CSS background (parallax/repeated) renders as a div and
|
|
610
|
+
// never fires a load event; getMediaColor already fetched
|
|
611
|
+
// the file, so the swap is done once attributes are set.
|
|
612
|
+
const {
|
|
613
|
+
hasParallax: currentHasParallax,
|
|
614
|
+
isRepeated: currentIsRepeated,
|
|
615
|
+
} = propsRef.current.attributes;
|
|
616
|
+
if ( currentHasParallax || currentIsRepeated ) {
|
|
617
|
+
setIsSwappingMedia( false );
|
|
618
|
+
}
|
|
566
619
|
},
|
|
567
620
|
} );
|
|
568
621
|
}, [
|
|
@@ -615,15 +668,24 @@ function CoverEdit( {
|
|
|
615
668
|
averageBackgroundColor
|
|
616
669
|
);
|
|
617
670
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
671
|
+
registry.batch( () => {
|
|
672
|
+
setAttributes( {
|
|
673
|
+
id: undefined,
|
|
674
|
+
url: undefined,
|
|
675
|
+
useFeaturedImage: newUseFeaturedImage,
|
|
676
|
+
dimRatio: newDimRatio,
|
|
677
|
+
backgroundType: useFeaturedImage
|
|
678
|
+
? IMAGE_BACKGROUND_TYPE
|
|
679
|
+
: undefined,
|
|
680
|
+
isDark: newIsDark,
|
|
681
|
+
} );
|
|
682
|
+
|
|
683
|
+
// Skip when the featured image is disabled: that can return the
|
|
684
|
+
// block to its placeholder, which only renders while there is no
|
|
685
|
+
// content.
|
|
686
|
+
if ( newUseFeaturedImage ) {
|
|
687
|
+
scaffoldInnerBlocks();
|
|
688
|
+
}
|
|
627
689
|
} );
|
|
628
690
|
};
|
|
629
691
|
|
|
@@ -640,6 +702,7 @@ function CoverEdit( {
|
|
|
640
702
|
onEditMedia={ openCoverMediaEditorModal }
|
|
641
703
|
editMediaButtonRef={ editMediaButtonRef }
|
|
642
704
|
showEditMediaButton={ showEditMediaButton }
|
|
705
|
+
isEditMediaDisabled={ isSwappingMedia }
|
|
643
706
|
/>
|
|
644
707
|
);
|
|
645
708
|
|
|
@@ -722,7 +785,7 @@ function CoverEdit( {
|
|
|
722
785
|
{
|
|
723
786
|
'is-dark-theme': isDark,
|
|
724
787
|
'is-light': ! isDark,
|
|
725
|
-
'is-transient': isUploadingMedia,
|
|
788
|
+
'is-transient': isUploadingMedia || isSwappingMedia,
|
|
726
789
|
'has-parallax': hasParallax,
|
|
727
790
|
'is-repeated': isRepeated,
|
|
728
791
|
'has-custom-content-position':
|
|
@@ -762,6 +825,8 @@ function CoverEdit( {
|
|
|
762
825
|
alt={ alt }
|
|
763
826
|
src={ url }
|
|
764
827
|
style={ mediaStyle }
|
|
828
|
+
onLoad={ () => setIsSwappingMedia( false ) }
|
|
829
|
+
onError={ () => setIsSwappingMedia( false ) }
|
|
765
830
|
/>
|
|
766
831
|
) : (
|
|
767
832
|
<div
|
|
@@ -829,7 +894,7 @@ function CoverEdit( {
|
|
|
829
894
|
/>
|
|
830
895
|
) }
|
|
831
896
|
|
|
832
|
-
{ isUploadingMedia && <Spinner /> }
|
|
897
|
+
{ ( isUploadingMedia || isSwappingMedia ) && <Spinner /> }
|
|
833
898
|
|
|
834
899
|
<CoverPlaceholder
|
|
835
900
|
disableMediaButtons
|
package/src/cover/editor.scss
CHANGED
|
@@ -44,6 +44,12 @@
|
|
|
44
44
|
.wp-block-cover__inner-container {
|
|
45
45
|
z-index: 2;
|
|
46
46
|
}
|
|
47
|
+
|
|
48
|
+
// Keep the loading spinner above the dim overlay (1) and the inner
|
|
49
|
+
// blocks (2) so it stays visible over child content while media loads.
|
|
50
|
+
.components-spinner {
|
|
51
|
+
z-index: 3;
|
|
52
|
+
}
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
// Shown while media is being uploaded
|
package/src/cover/index.php
CHANGED
|
@@ -134,8 +134,15 @@ function render_block_core_cover( $attributes, $content ) {
|
|
|
134
134
|
return $content;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
$
|
|
138
|
-
|
|
137
|
+
$cover_focal_point = $attributes['focalPoint'] ?? null;
|
|
138
|
+
$focal_point_x = null;
|
|
139
|
+
$focal_point_y = null;
|
|
140
|
+
if ( is_array( $cover_focal_point ) ) {
|
|
141
|
+
$focal_point_x = isset( $cover_focal_point['x'] ) && is_numeric( $cover_focal_point['x'] ) ? $cover_focal_point['x'] : null;
|
|
142
|
+
$focal_point_y = isset( $cover_focal_point['y'] ) && is_numeric( $cover_focal_point['y'] ) ? $cover_focal_point['y'] : null;
|
|
143
|
+
}
|
|
144
|
+
$object_position = null !== $focal_point_x && null !== $focal_point_y
|
|
145
|
+
? round( $focal_point_x * 100 ) . '% ' . round( $focal_point_y * 100 ) . '%'
|
|
139
146
|
: null;
|
|
140
147
|
|
|
141
148
|
if ( ! ( $attributes['hasParallax'] || $attributes['isRepeated'] ) ) {
|
package/src/editor.scss
CHANGED
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
@use "./social-link/editor.scss" as *;
|
|
49
49
|
@use "./social-links/editor.scss" as *;
|
|
50
50
|
@use "./spacer/editor.scss" as *;
|
|
51
|
+
@use "./tab-list/editor.scss" as *;
|
|
51
52
|
@use "./table/editor.scss" as *;
|
|
52
53
|
@use "./template-part/editor.scss" as *;
|
|
53
54
|
@use "./term-template/editor.scss" as *;
|
package/src/embed/edit.js
CHANGED
|
@@ -239,7 +239,9 @@ const EmbedEdit = ( props ) => {
|
|
|
239
239
|
value={ url }
|
|
240
240
|
cannotEmbed={ cannotEmbed }
|
|
241
241
|
onChange={ ( value ) => setURL( value ) }
|
|
242
|
-
fallback={
|
|
242
|
+
fallback={
|
|
243
|
+
onReplace ? () => fallback( url, onReplace ) : undefined
|
|
244
|
+
}
|
|
243
245
|
tryAgain={ () => {
|
|
244
246
|
invalidateResolution( 'getEmbedPreview', [ url ] );
|
|
245
247
|
} }
|
|
@@ -70,13 +70,15 @@ export default function EmbedPlaceholder( {
|
|
|
70
70
|
>
|
|
71
71
|
{ _x( 'Try again', 'button label' ) }
|
|
72
72
|
</Button>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
{ fallback && (
|
|
74
|
+
<Button
|
|
75
|
+
__next40pxDefaultSize
|
|
76
|
+
variant="secondary"
|
|
77
|
+
onClick={ fallback }
|
|
78
|
+
>
|
|
79
|
+
{ _x( 'Convert to link', 'button label' ) }
|
|
80
|
+
</Button>
|
|
81
|
+
) }
|
|
80
82
|
</Stack>
|
|
81
83
|
</Stack>
|
|
82
84
|
) }
|
package/src/form/index.php
CHANGED
|
@@ -20,12 +20,13 @@ function render_block_core_form( $attributes, $content ) {
|
|
|
20
20
|
$processed_content->next_tag( 'form' );
|
|
21
21
|
|
|
22
22
|
// Get the action for this form.
|
|
23
|
-
$action
|
|
24
|
-
|
|
23
|
+
$action = '';
|
|
24
|
+
$form_action = $attributes['action'] ?? null;
|
|
25
|
+
if ( is_string( $form_action ) ) {
|
|
25
26
|
$action = str_replace(
|
|
26
27
|
array( '{SITE_URL}', '{ADMIN_URL}' ),
|
|
27
28
|
array( site_url(), admin_url() ),
|
|
28
|
-
$
|
|
29
|
+
$form_action
|
|
29
30
|
);
|
|
30
31
|
}
|
|
31
32
|
$processed_content->set_attribute( 'action', esc_attr( $action ) );
|
|
@@ -55,7 +56,8 @@ function render_block_core_form( $attributes, $content ) {
|
|
|
55
56
|
* @return string The extra fields.
|
|
56
57
|
*/
|
|
57
58
|
function block_core_form_extra_fields_comment_form( $extra_fields, $attributes ) {
|
|
58
|
-
|
|
59
|
+
$form_action = $attributes['action'] ?? null;
|
|
60
|
+
if ( ! empty( $form_action ) && is_string( $form_action ) && str_ends_with( $form_action, '/wp-comments-post.php' ) ) {
|
|
59
61
|
$extra_fields .= '<input type="hidden" name="comment_post_ID" value="' . get_the_ID() . '" id="comment_post_ID">';
|
|
60
62
|
}
|
|
61
63
|
return $extra_fields;
|
|
@@ -74,14 +74,44 @@ function OrderControl( { orderby, order, onChange } ) {
|
|
|
74
74
|
);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Confirmation for leaving dynamic mode, shown from both the block toolbar and
|
|
79
|
+
* the Source panel so the two entry points explain the change identically.
|
|
80
|
+
*
|
|
81
|
+
* Detaching keeps the images the gallery currently shows but breaks the link to
|
|
82
|
+
* its source, so it's worth confirming — mirroring the dialog `GallerySourcePanel`
|
|
83
|
+
* shows for the opposite direction.
|
|
84
|
+
*
|
|
85
|
+
* @param {Object} props
|
|
86
|
+
* @param {Function} props.onConfirm Called when the user confirms detaching.
|
|
87
|
+
* @param {Function} props.onCancel Called when the user dismisses the dialog.
|
|
88
|
+
*/
|
|
89
|
+
function DetachGalleryDialog( { onConfirm, onCancel } ) {
|
|
90
|
+
return (
|
|
91
|
+
<ConfirmDialog
|
|
92
|
+
isOpen
|
|
93
|
+
title={ __( 'Detach Gallery' ) }
|
|
94
|
+
__experimentalHideHeader={ false }
|
|
95
|
+
confirmButtonText={ __( 'Detach' ) }
|
|
96
|
+
onConfirm={ onConfirm }
|
|
97
|
+
onCancel={ onCancel }
|
|
98
|
+
size="medium"
|
|
99
|
+
>
|
|
100
|
+
{ __(
|
|
101
|
+
'The gallery displays the images attached to the post. Detaching will enable you to add, delete, or reorder images. However, new attachments will no longer be added automatically.'
|
|
102
|
+
) }
|
|
103
|
+
</ConfirmDialog>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
77
107
|
/**
|
|
78
108
|
* The Gallery block's "Source" inspector panel.
|
|
79
109
|
*
|
|
80
|
-
* In dynamic mode it shows the resolved source, a control to
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
110
|
+
* In dynamic mode it shows the resolved source, a control to detach the gallery
|
|
111
|
+
* from it, and the source ordering. In static mode it offers the entry point
|
|
112
|
+
* into dynamic mode. Either direction is a one-way change, so both are behind a
|
|
113
|
+
* confirmation dialog this panel owns. Rendered inside the block's
|
|
114
|
+
* `InspectorControls`, alongside the Settings panel.
|
|
85
115
|
*
|
|
86
116
|
* @param {Object} props
|
|
87
117
|
* @param {Object} props.dynamic The `useDynamicGallery` result.
|
|
@@ -110,6 +140,7 @@ export function GallerySourcePanel( {
|
|
|
110
140
|
const isDynamic = !! dynamicContent;
|
|
111
141
|
|
|
112
142
|
const [ isConfirming, setIsConfirming ] = useState( false );
|
|
143
|
+
const [ isConfirmingDetach, setIsConfirmingDetach ] = useState( false );
|
|
113
144
|
|
|
114
145
|
// Entering dynamic mode discards any hand-added images, so confirm first
|
|
115
146
|
// when there are images to lose; otherwise switch straight away.
|
|
@@ -123,63 +154,76 @@ export function GallerySourcePanel( {
|
|
|
123
154
|
|
|
124
155
|
if ( isDynamic ) {
|
|
125
156
|
return (
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
<div className="wp-block-gallery__source-settings">
|
|
132
|
-
<p className="wp-block-gallery__source-description">
|
|
133
|
-
{ sourceDescriptor?.description ??
|
|
134
|
-
__( 'Dynamic images.' ) }
|
|
135
|
-
</p>
|
|
136
|
-
<Button
|
|
137
|
-
__next40pxDefaultSize
|
|
138
|
-
variant="secondary"
|
|
139
|
-
onClick={ convertToStatic }
|
|
140
|
-
// Guard the race where the media is still resolving:
|
|
141
|
-
// converting now would map over an incomplete (or empty)
|
|
142
|
-
// list and produce a gallery missing images.
|
|
143
|
-
disabled={ isResolvingDynamic }
|
|
144
|
-
accessibleWhenDisabled
|
|
145
|
-
>
|
|
146
|
-
{ __( 'Convert to individual images' ) }
|
|
147
|
-
</Button>
|
|
148
|
-
</div>
|
|
149
|
-
{ hasMoreImagesThanCap && (
|
|
150
|
-
<Notice
|
|
151
|
-
className="wp-block-gallery__source-notice"
|
|
152
|
-
status="warning"
|
|
153
|
-
isDismissible={ false }
|
|
154
|
-
>
|
|
155
|
-
{ sprintf(
|
|
156
|
-
/* translators: 1: number of images shown. 2: total number of matching images. */
|
|
157
|
-
__(
|
|
158
|
-
'Only the first %1$d of %2$d images will be displayed.'
|
|
159
|
-
),
|
|
160
|
-
MAX_IMAGES,
|
|
161
|
-
dynamicMediaTotal
|
|
162
|
-
) }
|
|
163
|
-
</Notice>
|
|
164
|
-
) }
|
|
165
|
-
<ToolsPanelItem
|
|
166
|
-
isShownByDefault
|
|
167
|
-
label={ __( 'Order by' ) }
|
|
168
|
-
hasValue={ () =>
|
|
169
|
-
sourceOrderby !== DEFAULT_ORDERBY ||
|
|
170
|
-
sourceOrder !== DEFAULT_ORDER
|
|
171
|
-
}
|
|
172
|
-
onDeselect={ () => setSourceOrder( undefined, undefined ) }
|
|
157
|
+
<>
|
|
158
|
+
<ToolsPanel
|
|
159
|
+
label={ __( 'Source' ) }
|
|
160
|
+
resetAll={ resetSource }
|
|
161
|
+
dropdownMenuProps={ dropdownMenuProps }
|
|
173
162
|
>
|
|
174
|
-
<
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
163
|
+
<div className="wp-block-gallery__source-settings">
|
|
164
|
+
<p className="wp-block-gallery__source-description">
|
|
165
|
+
{ sourceDescriptor?.description ??
|
|
166
|
+
__( 'Dynamic images.' ) }
|
|
167
|
+
</p>
|
|
168
|
+
<Button
|
|
169
|
+
__next40pxDefaultSize
|
|
170
|
+
variant="secondary"
|
|
171
|
+
onClick={ () => setIsConfirmingDetach( true ) }
|
|
172
|
+
// Guard the race where the media is still resolving:
|
|
173
|
+
// detaching now would map over an incomplete (or
|
|
174
|
+
// empty) list and produce a gallery missing images.
|
|
175
|
+
disabled={ isResolvingDynamic }
|
|
176
|
+
accessibleWhenDisabled
|
|
177
|
+
>
|
|
178
|
+
{ __( 'Detach Gallery' ) }
|
|
179
|
+
</Button>
|
|
180
|
+
</div>
|
|
181
|
+
{ hasMoreImagesThanCap && (
|
|
182
|
+
<Notice
|
|
183
|
+
className="wp-block-gallery__source-notice"
|
|
184
|
+
status="warning"
|
|
185
|
+
isDismissible={ false }
|
|
186
|
+
>
|
|
187
|
+
{ sprintf(
|
|
188
|
+
/* translators: 1: number of images shown. 2: total number of matching images. */
|
|
189
|
+
__(
|
|
190
|
+
'Only the first %1$d of %2$d images will be displayed.'
|
|
191
|
+
),
|
|
192
|
+
MAX_IMAGES,
|
|
193
|
+
dynamicMediaTotal
|
|
194
|
+
) }
|
|
195
|
+
</Notice>
|
|
196
|
+
) }
|
|
197
|
+
<ToolsPanelItem
|
|
198
|
+
isShownByDefault
|
|
199
|
+
label={ __( 'Order by' ) }
|
|
200
|
+
hasValue={ () =>
|
|
201
|
+
sourceOrderby !== DEFAULT_ORDERBY ||
|
|
202
|
+
sourceOrder !== DEFAULT_ORDER
|
|
203
|
+
}
|
|
204
|
+
onDeselect={ () =>
|
|
205
|
+
setSourceOrder( undefined, undefined )
|
|
179
206
|
}
|
|
207
|
+
>
|
|
208
|
+
<OrderControl
|
|
209
|
+
orderby={ sourceOrderby }
|
|
210
|
+
order={ sourceOrder }
|
|
211
|
+
onChange={ ( { orderby, order } ) =>
|
|
212
|
+
setSourceOrder( orderby, order )
|
|
213
|
+
}
|
|
214
|
+
/>
|
|
215
|
+
</ToolsPanelItem>
|
|
216
|
+
</ToolsPanel>
|
|
217
|
+
{ isConfirmingDetach && (
|
|
218
|
+
<DetachGalleryDialog
|
|
219
|
+
onConfirm={ () => {
|
|
220
|
+
convertToStatic();
|
|
221
|
+
setIsConfirmingDetach( false );
|
|
222
|
+
} }
|
|
223
|
+
onCancel={ () => setIsConfirmingDetach( false ) }
|
|
180
224
|
/>
|
|
181
|
-
|
|
182
|
-
|
|
225
|
+
) }
|
|
226
|
+
</>
|
|
183
227
|
);
|
|
184
228
|
}
|
|
185
229
|
|
|
@@ -266,7 +310,8 @@ function GalleryImagesPreview( { imageBlocks } ) {
|
|
|
266
310
|
/**
|
|
267
311
|
* Renders a dynamic-mode gallery on the canvas:
|
|
268
312
|
*
|
|
269
|
-
* - a block-toolbar control to
|
|
313
|
+
* - a block-toolbar control to detach the gallery from its source, confirmed in
|
|
314
|
+
* a dialog;
|
|
270
315
|
* - the gallery `<figure>` wrapper holding a non-editable preview of the
|
|
271
316
|
* resolved media (or a placeholder while resolving / when nothing is found),
|
|
272
317
|
* with the gallery's provided context so the previewed images inherit
|
|
@@ -306,13 +351,15 @@ export function GalleryDynamicView( {
|
|
|
306
351
|
convertToStatic,
|
|
307
352
|
} = dynamic;
|
|
308
353
|
|
|
309
|
-
//
|
|
310
|
-
//
|
|
354
|
+
// Detaching the gallery materializes editable inner blocks, which is a
|
|
355
|
+
// structural change. Only offer it when the block is fully editable:
|
|
311
356
|
// under a content lock (e.g. inside a `contentOnly` group) the editing mode
|
|
312
357
|
// is `'contentOnly'`/`'disabled'`, where structural toolbar controls are
|
|
313
358
|
// hidden and the conversion shouldn't be possible.
|
|
314
359
|
const blockEditingMode = useBlockEditingMode();
|
|
315
360
|
|
|
361
|
+
const [ isConfirmingDetach, setIsConfirmingDetach ] = useState( false );
|
|
362
|
+
|
|
316
363
|
// Empty-state copy for the preview. Framed as forward-looking ("… will appear
|
|
317
364
|
// here") rather than as an error, since the same empty result covers both a
|
|
318
365
|
// post with no matching images and a template with no post in context yet —
|
|
@@ -326,18 +373,30 @@ export function GalleryDynamicView( {
|
|
|
326
373
|
return (
|
|
327
374
|
<>
|
|
328
375
|
{ blockEditingMode === 'default' && (
|
|
329
|
-
|
|
330
|
-
<
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
376
|
+
<>
|
|
377
|
+
<BlockControls group="other">
|
|
378
|
+
<ToolbarButton
|
|
379
|
+
onClick={ () => setIsConfirmingDetach( true ) }
|
|
380
|
+
// Same guard as the inspector's "Detach Gallery": both end in
|
|
381
|
+
// `convertToStatic`, which would map over a
|
|
382
|
+
// still-resolving (or empty) media list.
|
|
383
|
+
// (`ToolbarButton` stays focusable when disabled by
|
|
384
|
+
// default.)
|
|
385
|
+
disabled={ isResolvingDynamic }
|
|
386
|
+
>
|
|
387
|
+
{ __( 'Detach' ) }
|
|
388
|
+
</ToolbarButton>
|
|
389
|
+
</BlockControls>
|
|
390
|
+
{ isConfirmingDetach && (
|
|
391
|
+
<DetachGalleryDialog
|
|
392
|
+
onConfirm={ () => {
|
|
393
|
+
convertToStatic();
|
|
394
|
+
setIsConfirmingDetach( false );
|
|
395
|
+
} }
|
|
396
|
+
onCancel={ () => setIsConfirmingDetach( false ) }
|
|
397
|
+
/>
|
|
398
|
+
) }
|
|
399
|
+
</>
|
|
341
400
|
) }
|
|
342
401
|
<figure { ...blockProps }>
|
|
343
402
|
{ dynamicImageBlocks.length ? (
|