@wordpress/block-editor 15.14.0 → 15.14.1-next.v.202603102151.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/build/components/block-tools/index.cjs +4 -3
- package/build/components/block-tools/index.cjs.map +2 -2
- package/build/components/iframe/index.cjs +14 -6
- package/build/components/iframe/index.cjs.map +2 -2
- package/build/components/observe-typing/index.cjs +9 -13
- package/build/components/observe-typing/index.cjs.map +2 -2
- package/build/components/provider/index.cjs +22 -6
- package/build/components/provider/index.cjs.map +2 -2
- package/build/hooks/block-fields/index.cjs +52 -31
- package/build/hooks/block-fields/index.cjs.map +2 -2
- package/build/hooks/cross-origin-isolation.cjs +7 -73
- package/build/hooks/cross-origin-isolation.cjs.map +2 -2
- package/build/private-apis.cjs +1 -0
- package/build/private-apis.cjs.map +2 -2
- package/build/store/private-keys.cjs +3 -0
- package/build/store/private-keys.cjs.map +2 -2
- package/build/store/selectors.cjs +9 -7
- package/build/store/selectors.cjs.map +2 -2
- package/build-module/components/block-tools/index.mjs +4 -3
- package/build-module/components/block-tools/index.mjs.map +2 -2
- package/build-module/components/iframe/index.mjs +14 -6
- package/build-module/components/iframe/index.mjs.map +2 -2
- package/build-module/components/observe-typing/index.mjs +9 -13
- package/build-module/components/observe-typing/index.mjs.map +2 -2
- package/build-module/components/provider/index.mjs +22 -6
- package/build-module/components/provider/index.mjs.map +2 -2
- package/build-module/hooks/block-fields/index.mjs +53 -32
- package/build-module/hooks/block-fields/index.mjs.map +2 -2
- package/build-module/hooks/cross-origin-isolation.mjs +7 -73
- package/build-module/hooks/cross-origin-isolation.mjs.map +2 -2
- package/build-module/private-apis.mjs +3 -1
- package/build-module/private-apis.mjs.map +2 -2
- package/build-module/store/private-keys.mjs +2 -0
- package/build-module/store/private-keys.mjs.map +2 -2
- package/build-module/store/selectors.mjs +9 -7
- package/build-module/store/selectors.mjs.map +2 -2
- package/build-style/style-rtl.css +8 -5
- package/build-style/style.css +8 -5
- package/package.json +39 -39
- package/src/components/block-tools/index.js +11 -4
- package/src/components/iframe/index.js +19 -6
- package/src/components/observe-typing/index.js +10 -14
- package/src/components/provider/index.js +47 -5
- package/src/components/responsive-block-control/style.scss +1 -0
- package/src/hooks/block-fields/index.js +44 -19
- package/src/hooks/block-fields/styles.scss +7 -9
- package/src/hooks/cross-origin-isolation.js +8 -107
- package/src/hooks/test/cross-origin-isolation.js +11 -42
- package/src/private-apis.js +2 -0
- package/src/store/private-keys.js +1 -0
- package/src/store/selectors.js +27 -9
- package/src/store/test/selectors.js +540 -0
|
@@ -3117,6 +3117,7 @@ iframe[name=editor-canvas] {
|
|
|
3117
3117
|
position: absolute;
|
|
3118
3118
|
width: 1px;
|
|
3119
3119
|
word-wrap: normal !important;
|
|
3120
|
+
word-break: normal !important;
|
|
3120
3121
|
}
|
|
3121
3122
|
|
|
3122
3123
|
.preset-input-control__wrapper > * {
|
|
@@ -3521,14 +3522,15 @@ iframe[name=editor-canvas] {
|
|
|
3521
3522
|
}
|
|
3522
3523
|
|
|
3523
3524
|
.block-editor-block-fields__container {
|
|
3524
|
-
padding: 0 16px;
|
|
3525
|
+
padding: 0 16px 16px;
|
|
3525
3526
|
}
|
|
3526
3527
|
.block-editor-block-fields__container:first-of-type {
|
|
3527
3528
|
padding-block-start: 8px;
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
.
|
|
3531
|
-
|
|
3529
|
+
/*
|
|
3530
|
+
* Add border for the entire content controls and remove the similar border
|
|
3531
|
+
* for tools panel.
|
|
3532
|
+
*/
|
|
3533
|
+
border-block-start: 1px solid #e0e0e0;
|
|
3532
3534
|
}
|
|
3533
3535
|
|
|
3534
3536
|
.block-editor-block-fields__header {
|
|
@@ -3542,6 +3544,7 @@ iframe[name=editor-canvas] {
|
|
|
3542
3544
|
|
|
3543
3545
|
.block-editor-block-fields__header-title {
|
|
3544
3546
|
flex: 1;
|
|
3547
|
+
/* Override the default margin on a h2 element. */
|
|
3545
3548
|
margin: 0 !important;
|
|
3546
3549
|
}
|
|
3547
3550
|
|
package/build-style/style.css
CHANGED
|
@@ -3119,6 +3119,7 @@ iframe[name=editor-canvas] {
|
|
|
3119
3119
|
position: absolute;
|
|
3120
3120
|
width: 1px;
|
|
3121
3121
|
word-wrap: normal !important;
|
|
3122
|
+
word-break: normal !important;
|
|
3122
3123
|
}
|
|
3123
3124
|
|
|
3124
3125
|
.preset-input-control__wrapper > * {
|
|
@@ -3523,14 +3524,15 @@ iframe[name=editor-canvas] {
|
|
|
3523
3524
|
}
|
|
3524
3525
|
|
|
3525
3526
|
.block-editor-block-fields__container {
|
|
3526
|
-
padding: 0 16px;
|
|
3527
|
+
padding: 0 16px 16px;
|
|
3527
3528
|
}
|
|
3528
3529
|
.block-editor-block-fields__container:first-of-type {
|
|
3529
3530
|
padding-block-start: 8px;
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
.
|
|
3533
|
-
|
|
3531
|
+
/*
|
|
3532
|
+
* Add border for the entire content controls and remove the similar border
|
|
3533
|
+
* for tools panel.
|
|
3534
|
+
*/
|
|
3535
|
+
border-block-start: 1px solid #e0e0e0;
|
|
3534
3536
|
}
|
|
3535
3537
|
|
|
3536
3538
|
.block-editor-block-fields__header {
|
|
@@ -3544,6 +3546,7 @@ iframe[name=editor-canvas] {
|
|
|
3544
3546
|
|
|
3545
3547
|
.block-editor-block-fields__header-title {
|
|
3546
3548
|
flex: 1;
|
|
3549
|
+
/* Override the default margin on a h2 element. */
|
|
3547
3550
|
margin: 0 !important;
|
|
3548
3551
|
}
|
|
3549
3552
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/block-editor",
|
|
3
|
-
"version": "15.14.0",
|
|
3
|
+
"version": "15.14.1-next.v.202603102151.0+59e17f9ec",
|
|
4
4
|
"description": "Generic block editor.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -61,43 +61,43 @@
|
|
|
61
61
|
],
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@react-spring/web": "^9.4.5",
|
|
64
|
-
"@wordpress/a11y": "^4.41.0",
|
|
65
|
-
"@wordpress/api-fetch": "^7.41.0",
|
|
66
|
-
"@wordpress/base-styles": "^6.17.0",
|
|
67
|
-
"@wordpress/blob": "^4.41.0",
|
|
68
|
-
"@wordpress/block-serialization-default-parser": "^5.41.0",
|
|
69
|
-
"@wordpress/blocks": "^15.14.0",
|
|
70
|
-
"@wordpress/commands": "^1.41.0",
|
|
71
|
-
"@wordpress/components": "^32.
|
|
72
|
-
"@wordpress/compose": "^7.41.0",
|
|
73
|
-
"@wordpress/data": "^10.41.0",
|
|
74
|
-
"@wordpress/dataviews": "^13.
|
|
75
|
-
"@wordpress/date": "^5.41.0",
|
|
76
|
-
"@wordpress/deprecated": "^4.41.0",
|
|
77
|
-
"@wordpress/dom": "^4.41.0",
|
|
78
|
-
"@wordpress/element": "^6.41.0",
|
|
79
|
-
"@wordpress/escape-html": "^3.41.0",
|
|
80
|
-
"@wordpress/global-styles-engine": "^1.8.0",
|
|
81
|
-
"@wordpress/hooks": "^4.41.0",
|
|
82
|
-
"@wordpress/html-entities": "^4.41.0",
|
|
83
|
-
"@wordpress/i18n": "^6.14.0",
|
|
84
|
-
"@wordpress/icons": "^
|
|
85
|
-
"@wordpress/image-cropper": "^1.5.0",
|
|
86
|
-
"@wordpress/interactivity": "^6.41.0",
|
|
87
|
-
"@wordpress/is-shallow-equal": "^5.41.0",
|
|
88
|
-
"@wordpress/keyboard-shortcuts": "^5.41.0",
|
|
89
|
-
"@wordpress/keycodes": "^4.41.0",
|
|
90
|
-
"@wordpress/notices": "^5.41.0",
|
|
91
|
-
"@wordpress/preferences": "^4.41.0",
|
|
92
|
-
"@wordpress/priority-queue": "^3.41.0",
|
|
93
|
-
"@wordpress/private-apis": "^1.41.0",
|
|
94
|
-
"@wordpress/rich-text": "^7.41.0",
|
|
95
|
-
"@wordpress/style-engine": "^2.41.0",
|
|
96
|
-
"@wordpress/token-list": "^3.41.0",
|
|
97
|
-
"@wordpress/upload-media": "^0.26.0",
|
|
98
|
-
"@wordpress/url": "^4.41.0",
|
|
99
|
-
"@wordpress/warning": "^3.41.0",
|
|
100
|
-
"@wordpress/wordcount": "^4.41.0",
|
|
64
|
+
"@wordpress/a11y": "^4.41.1-next.v.202603102151.0+59e17f9ec",
|
|
65
|
+
"@wordpress/api-fetch": "^7.41.1-next.v.202603102151.0+59e17f9ec",
|
|
66
|
+
"@wordpress/base-styles": "^6.17.1-next.v.202603102151.0+59e17f9ec",
|
|
67
|
+
"@wordpress/blob": "^4.41.1-next.v.202603102151.0+59e17f9ec",
|
|
68
|
+
"@wordpress/block-serialization-default-parser": "^5.41.1-next.v.202603102151.0+59e17f9ec",
|
|
69
|
+
"@wordpress/blocks": "^15.14.1-next.v.202603102151.0+59e17f9ec",
|
|
70
|
+
"@wordpress/commands": "^1.41.1-next.v.202603102151.0+59e17f9ec",
|
|
71
|
+
"@wordpress/components": "^32.4.1-next.v.202603102151.0+59e17f9ec",
|
|
72
|
+
"@wordpress/compose": "^7.41.1-next.v.202603102151.0+59e17f9ec",
|
|
73
|
+
"@wordpress/data": "^10.41.1-next.v.202603102151.0+59e17f9ec",
|
|
74
|
+
"@wordpress/dataviews": "^13.1.1-next.v.202603102151.0+59e17f9ec",
|
|
75
|
+
"@wordpress/date": "^5.41.1-next.v.202603102151.0+59e17f9ec",
|
|
76
|
+
"@wordpress/deprecated": "^4.41.1-next.v.202603102151.0+59e17f9ec",
|
|
77
|
+
"@wordpress/dom": "^4.41.1-next.v.202603102151.0+59e17f9ec",
|
|
78
|
+
"@wordpress/element": "^6.41.1-next.v.202603102151.0+59e17f9ec",
|
|
79
|
+
"@wordpress/escape-html": "^3.41.1-next.v.202603102151.0+59e17f9ec",
|
|
80
|
+
"@wordpress/global-styles-engine": "^1.8.1-next.v.202603102151.0+59e17f9ec",
|
|
81
|
+
"@wordpress/hooks": "^4.41.1-next.v.202603102151.0+59e17f9ec",
|
|
82
|
+
"@wordpress/html-entities": "^4.41.1-next.v.202603102151.0+59e17f9ec",
|
|
83
|
+
"@wordpress/i18n": "^6.14.1-next.v.202603102151.0+59e17f9ec",
|
|
84
|
+
"@wordpress/icons": "^12.0.1-next.v.202603102151.0+59e17f9ec",
|
|
85
|
+
"@wordpress/image-cropper": "^1.5.1-next.v.202603102151.0+59e17f9ec",
|
|
86
|
+
"@wordpress/interactivity": "^6.41.2-next.v.202603102151.0+59e17f9ec",
|
|
87
|
+
"@wordpress/is-shallow-equal": "^5.41.1-next.v.202603102151.0+59e17f9ec",
|
|
88
|
+
"@wordpress/keyboard-shortcuts": "^5.41.1-next.v.202603102151.0+59e17f9ec",
|
|
89
|
+
"@wordpress/keycodes": "^4.41.1-next.v.202603102151.0+59e17f9ec",
|
|
90
|
+
"@wordpress/notices": "^5.41.1-next.v.202603102151.0+59e17f9ec",
|
|
91
|
+
"@wordpress/preferences": "^4.41.1-next.v.202603102151.0+59e17f9ec",
|
|
92
|
+
"@wordpress/priority-queue": "^3.41.1-next.v.202603102151.0+59e17f9ec",
|
|
93
|
+
"@wordpress/private-apis": "^1.41.1-next.v.202603102151.0+59e17f9ec",
|
|
94
|
+
"@wordpress/rich-text": "^7.41.1-next.v.202603102151.0+59e17f9ec",
|
|
95
|
+
"@wordpress/style-engine": "^2.41.1-next.v.202603102151.0+59e17f9ec",
|
|
96
|
+
"@wordpress/token-list": "^3.41.1-next.v.202603102151.0+59e17f9ec",
|
|
97
|
+
"@wordpress/upload-media": "^0.26.1-next.v.202603102151.0+59e17f9ec",
|
|
98
|
+
"@wordpress/url": "^4.41.1-next.v.202603102151.0+59e17f9ec",
|
|
99
|
+
"@wordpress/warning": "^3.41.1-next.v.202603102151.0+59e17f9ec",
|
|
100
|
+
"@wordpress/wordcount": "^4.41.1-next.v.202603102151.0+59e17f9ec",
|
|
101
101
|
"change-case": "^4.1.2",
|
|
102
102
|
"clsx": "^2.1.1",
|
|
103
103
|
"colord": "^2.7.0",
|
|
@@ -124,5 +124,5 @@
|
|
|
124
124
|
"publishConfig": {
|
|
125
125
|
"access": "public"
|
|
126
126
|
},
|
|
127
|
-
"gitHead": "
|
|
127
|
+
"gitHead": "86db21e727d89e8f0dbba9300d2f97fd22b08693"
|
|
128
128
|
}
|
|
@@ -92,6 +92,7 @@ export default function BlockTools( {
|
|
|
92
92
|
getBlockName,
|
|
93
93
|
isGroupable,
|
|
94
94
|
getEditedContentOnlySection,
|
|
95
|
+
canEditBlock,
|
|
95
96
|
} = unlock( useSelect( blockEditorStore ) );
|
|
96
97
|
const { getGroupingBlockName } = useSelect( blocksStore );
|
|
97
98
|
const { showEmptyBlockSideInserter, showBlockToolbarPopover } =
|
|
@@ -234,7 +235,10 @@ export default function BlockTools( {
|
|
|
234
235
|
if ( clientIds.length === 1 ) {
|
|
235
236
|
const isContentOnly =
|
|
236
237
|
getBlockEditingMode( clientIds[ 0 ] ) === 'contentOnly';
|
|
237
|
-
const canRenameBlock =
|
|
238
|
+
const canRenameBlock =
|
|
239
|
+
canRename &&
|
|
240
|
+
! isContentOnly &&
|
|
241
|
+
canEditBlock( clientIds[ 0 ] );
|
|
238
242
|
if ( canRenameBlock ) {
|
|
239
243
|
event.preventDefault();
|
|
240
244
|
setRenamingBlockClientId( clientIds[ 0 ] );
|
|
@@ -255,11 +259,14 @@ export default function BlockTools( {
|
|
|
255
259
|
return;
|
|
256
260
|
}
|
|
257
261
|
|
|
258
|
-
// Don't allow visibility toggle for blocks that
|
|
259
|
-
//
|
|
262
|
+
// Don't allow visibility toggle for blocks that are not in the
|
|
263
|
+
// default editing mode or when block editing is disabled
|
|
264
|
+
// (e.g. Revisions UI with isPreviewMode).
|
|
260
265
|
if (
|
|
261
266
|
clientIds.some(
|
|
262
|
-
( id ) =>
|
|
267
|
+
( id ) =>
|
|
268
|
+
getBlockEditingMode( id ) !== 'default' ||
|
|
269
|
+
! canEditBlock( id )
|
|
263
270
|
)
|
|
264
271
|
) {
|
|
265
272
|
return;
|
|
@@ -116,7 +116,6 @@ function getIframeSrc( resolvedAssets ) {
|
|
|
116
116
|
<head>
|
|
117
117
|
<meta charset="utf-8">
|
|
118
118
|
<base href="${ window.location.href }">
|
|
119
|
-
<script>window.frameElement._load()</script>
|
|
120
119
|
<style>
|
|
121
120
|
html{
|
|
122
121
|
height: auto !important;
|
|
@@ -168,9 +167,6 @@ function Iframe( {
|
|
|
168
167
|
const [ before, writingFlowRef, after ] = useWritingFlow();
|
|
169
168
|
|
|
170
169
|
const setRef = useRefEffect( ( node ) => {
|
|
171
|
-
node._load = () => {
|
|
172
|
-
setIframeDocument( node.contentDocument );
|
|
173
|
-
};
|
|
174
170
|
let iFrameDocument;
|
|
175
171
|
// Prevent the default browser action for files dropped outside of dropzones.
|
|
176
172
|
function preventFileDropDefault( event ) {
|
|
@@ -218,6 +214,7 @@ function Iframe( {
|
|
|
218
214
|
const { contentDocument } = node;
|
|
219
215
|
const { documentElement } = contentDocument;
|
|
220
216
|
iFrameDocument = contentDocument;
|
|
217
|
+
setIframeDocument( contentDocument );
|
|
221
218
|
|
|
222
219
|
documentElement.classList.add( 'block-editor-iframe__html' );
|
|
223
220
|
|
|
@@ -257,7 +254,7 @@ function Iframe( {
|
|
|
257
254
|
node.addEventListener( 'load', onLoad );
|
|
258
255
|
|
|
259
256
|
return () => {
|
|
260
|
-
|
|
257
|
+
setIframeDocument( undefined );
|
|
261
258
|
node.removeEventListener( 'load', onLoad );
|
|
262
259
|
iFrameDocument?.removeEventListener(
|
|
263
260
|
'dragover',
|
|
@@ -284,13 +281,29 @@ function Iframe( {
|
|
|
284
281
|
} );
|
|
285
282
|
|
|
286
283
|
const disabledRef = useDisabled( { isDisabled: ! readonly } );
|
|
287
|
-
|
|
284
|
+
|
|
285
|
+
const unguardedBodyRef = useMergeRefs( [
|
|
288
286
|
useBubbleEvents( iframeDocument ),
|
|
289
287
|
contentRef,
|
|
290
288
|
writingFlowRef,
|
|
291
289
|
disabledRef,
|
|
292
290
|
] );
|
|
293
291
|
|
|
292
|
+
// Attach the body ref only when the iframe document and window are available.
|
|
293
|
+
// When an iframe element is moved in the DOM, like when reordering a list,
|
|
294
|
+
// its `window` object is destroyed and recreated, and the `defaultView` field is
|
|
295
|
+
// briefly `null`. We need to guard for such calls of the ref callbacks.
|
|
296
|
+
const bodyRef = useRefEffect(
|
|
297
|
+
( node ) => {
|
|
298
|
+
if ( node.ownerDocument.defaultView ) {
|
|
299
|
+
unguardedBodyRef( node );
|
|
300
|
+
return () => unguardedBodyRef( null );
|
|
301
|
+
}
|
|
302
|
+
return () => {};
|
|
303
|
+
},
|
|
304
|
+
[ unguardedBodyRef ]
|
|
305
|
+
);
|
|
306
|
+
|
|
294
307
|
const src = getIframeSrc( resolvedAssets );
|
|
295
308
|
|
|
296
309
|
// Make sure to not render the before and after focusable div elements in view
|
|
@@ -115,21 +115,15 @@ export function useMouseMoveTypingReset() {
|
|
|
115
115
|
* field, presses ESC or TAB, or moves the mouse in the document.
|
|
116
116
|
*/
|
|
117
117
|
export function useTypingObserver() {
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
};
|
|
123
|
-
}, [] );
|
|
118
|
+
const isTyping = useSelect(
|
|
119
|
+
( select ) => select( blockEditorStore ).isTyping(),
|
|
120
|
+
[]
|
|
121
|
+
);
|
|
124
122
|
const { startTyping, stopTyping } = useDispatch( blockEditorStore );
|
|
125
123
|
|
|
126
124
|
const ref1 = useMouseMoveTypingReset();
|
|
127
125
|
const ref2 = useRefEffect(
|
|
128
126
|
( node ) => {
|
|
129
|
-
const { ownerDocument } = node;
|
|
130
|
-
const { defaultView } = ownerDocument;
|
|
131
|
-
const selection = defaultView.getSelection();
|
|
132
|
-
|
|
133
127
|
// Listeners to stop typing should only be added when typing.
|
|
134
128
|
// Listeners to start typing should only be added when not typing.
|
|
135
129
|
if ( isTyping ) {
|
|
@@ -147,7 +141,7 @@ export function useTypingObserver() {
|
|
|
147
141
|
// before the keydown event, wait until after current stack
|
|
148
142
|
// before evaluating whether typing is to be stopped. Otherwise,
|
|
149
143
|
// typing will re-start.
|
|
150
|
-
timerId = defaultView.setTimeout( () => {
|
|
144
|
+
timerId = node.ownerDocument.defaultView.setTimeout( () => {
|
|
151
145
|
if ( ! isTextField( target ) ) {
|
|
152
146
|
stopTyping();
|
|
153
147
|
}
|
|
@@ -174,6 +168,8 @@ export function useTypingObserver() {
|
|
|
174
168
|
* uncollapsed (shift) selection.
|
|
175
169
|
*/
|
|
176
170
|
function stopTypingOnSelectionUncollapse() {
|
|
171
|
+
const selection =
|
|
172
|
+
node.ownerDocument.defaultView.getSelection();
|
|
177
173
|
if ( ! selection.isCollapsed ) {
|
|
178
174
|
stopTyping();
|
|
179
175
|
}
|
|
@@ -182,13 +178,13 @@ export function useTypingObserver() {
|
|
|
182
178
|
node.addEventListener( 'focus', stopTypingOnNonTextField );
|
|
183
179
|
node.addEventListener( 'keydown', stopTypingOnEscapeKey );
|
|
184
180
|
|
|
185
|
-
ownerDocument.addEventListener(
|
|
181
|
+
node.ownerDocument.addEventListener(
|
|
186
182
|
'selectionchange',
|
|
187
183
|
stopTypingOnSelectionUncollapse
|
|
188
184
|
);
|
|
189
185
|
|
|
190
186
|
return () => {
|
|
191
|
-
defaultView.clearTimeout( timerId );
|
|
187
|
+
node.ownerDocument.defaultView.clearTimeout( timerId );
|
|
192
188
|
node.removeEventListener(
|
|
193
189
|
'focus',
|
|
194
190
|
stopTypingOnNonTextField
|
|
@@ -197,7 +193,7 @@ export function useTypingObserver() {
|
|
|
197
193
|
'keydown',
|
|
198
194
|
stopTypingOnEscapeKey
|
|
199
195
|
);
|
|
200
|
-
ownerDocument.removeEventListener(
|
|
196
|
+
node.ownerDocument.removeEventListener(
|
|
201
197
|
'selectionchange',
|
|
202
198
|
stopTypingOnSelectionUncollapse
|
|
203
199
|
);
|
|
@@ -20,6 +20,7 @@ import { BlockRefsProvider } from './block-refs-provider';
|
|
|
20
20
|
import { unlock } from '../../lock-unlock';
|
|
21
21
|
import KeyboardShortcuts from '../keyboard-shortcuts';
|
|
22
22
|
import useMediaUploadSettings from './use-media-upload-settings';
|
|
23
|
+
import { mediaUploadOnSuccessKey } from '../../store/private-keys';
|
|
23
24
|
import { SelectionContext } from './selection-context';
|
|
24
25
|
|
|
25
26
|
/** @typedef {import('@wordpress/data').WPDataRegistry} WPDataRegistry */
|
|
@@ -89,6 +90,7 @@ function shouldEnableClientSideMediaProcessing() {
|
|
|
89
90
|
* or when adding a file to the editor via drag & drop.
|
|
90
91
|
*
|
|
91
92
|
* @param {WPDataRegistry} registry
|
|
93
|
+
* @param {Object} settings Block editor settings.
|
|
92
94
|
* @param {Object} $3 Parameters object passed to the function.
|
|
93
95
|
* @param {Array} $3.allowedTypes Array with the types of media that can be uploaded, if unset all types are allowed.
|
|
94
96
|
* @param {Object} $3.additionalData Additional data to include in the request.
|
|
@@ -100,6 +102,7 @@ function shouldEnableClientSideMediaProcessing() {
|
|
|
100
102
|
*/
|
|
101
103
|
function mediaUpload(
|
|
102
104
|
registry,
|
|
105
|
+
settings,
|
|
103
106
|
{
|
|
104
107
|
allowedTypes,
|
|
105
108
|
additionalData = {},
|
|
@@ -113,7 +116,10 @@ function mediaUpload(
|
|
|
113
116
|
void registry.dispatch( uploadStore ).addItems( {
|
|
114
117
|
files: Array.from( filesList ),
|
|
115
118
|
onChange: onFileChange,
|
|
116
|
-
onSuccess
|
|
119
|
+
onSuccess: ( attachments ) => {
|
|
120
|
+
settings?.[ mediaUploadOnSuccessKey ]?.( attachments );
|
|
121
|
+
onSuccess?.( attachments );
|
|
122
|
+
},
|
|
117
123
|
onBatchSuccess,
|
|
118
124
|
onError: ( { message } ) => onError( message ),
|
|
119
125
|
additionalData,
|
|
@@ -146,16 +152,38 @@ export const ExperimentalBlockEditorProvider = withRegistryProvider(
|
|
|
146
152
|
const isClientSideMediaEnabled =
|
|
147
153
|
shouldEnableClientSideMediaProcessing();
|
|
148
154
|
|
|
155
|
+
// Nested providers (e.g. from useBlockPreview) inherit settings
|
|
156
|
+
// where mediaUpload has already been replaced with the
|
|
157
|
+
// interceptor. Detect this so we skip the replacement and
|
|
158
|
+
// MediaUploadProvider for them — see the longer comment below.
|
|
159
|
+
const isMediaUploadIntercepted =
|
|
160
|
+
!! _settings?.mediaUpload?.__isMediaUploadInterceptor;
|
|
161
|
+
|
|
149
162
|
const settings = useMemo( () => {
|
|
150
|
-
if (
|
|
163
|
+
if (
|
|
164
|
+
isClientSideMediaEnabled &&
|
|
165
|
+
_settings?.mediaUpload &&
|
|
166
|
+
! isMediaUploadIntercepted
|
|
167
|
+
) {
|
|
151
168
|
// Create a new object so that the original props.settings.mediaUpload is not modified.
|
|
169
|
+
const interceptor = mediaUpload.bind(
|
|
170
|
+
null,
|
|
171
|
+
registry,
|
|
172
|
+
_settings
|
|
173
|
+
);
|
|
174
|
+
interceptor.__isMediaUploadInterceptor = true;
|
|
152
175
|
return {
|
|
153
176
|
..._settings,
|
|
154
|
-
mediaUpload:
|
|
177
|
+
mediaUpload: interceptor,
|
|
155
178
|
};
|
|
156
179
|
}
|
|
157
180
|
return _settings;
|
|
158
|
-
}, [
|
|
181
|
+
}, [
|
|
182
|
+
_settings,
|
|
183
|
+
registry,
|
|
184
|
+
isClientSideMediaEnabled,
|
|
185
|
+
isMediaUploadIntercepted,
|
|
186
|
+
] );
|
|
159
187
|
|
|
160
188
|
const { __experimentalUpdateSettings } = unlock(
|
|
161
189
|
useDispatch( blockEditorStore )
|
|
@@ -215,7 +243,21 @@ export const ExperimentalBlockEditorProvider = withRegistryProvider(
|
|
|
215
243
|
</SelectionContext.Provider>
|
|
216
244
|
);
|
|
217
245
|
|
|
218
|
-
|
|
246
|
+
// MediaUploadProvider writes the mediaUpload function from
|
|
247
|
+
// _settings into the shared upload-media store so the store can
|
|
248
|
+
// hand files off to the server. useMediaUploadSettings extracts
|
|
249
|
+
// mediaUpload from the original _settings prop — *before* the
|
|
250
|
+
// interceptor replacement above — so the store receives the
|
|
251
|
+
// real server-side upload function.
|
|
252
|
+
//
|
|
253
|
+
// Only the first (outermost) provider should do this.
|
|
254
|
+
// Nested providers (e.g. from useBlockPreview in
|
|
255
|
+
// core/post-template) inherit settings that already contain
|
|
256
|
+
// the interceptor, so their MediaUploadProvider would
|
|
257
|
+
// overwrite the store's server-side function with the
|
|
258
|
+
// interceptor, causing uploads to loop instead of reaching
|
|
259
|
+
// the server.
|
|
260
|
+
if ( isClientSideMediaEnabled && ! isMediaUploadIntercepted ) {
|
|
219
261
|
return (
|
|
220
262
|
<MediaUploadProvider
|
|
221
263
|
settings={ mediaUploadSettings }
|
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WordPress dependencies
|
|
3
|
-
*/
|
|
4
1
|
import {
|
|
5
2
|
privateApis as blocksPrivateApis,
|
|
6
3
|
getBlockType,
|
|
7
4
|
store as blocksStore,
|
|
8
5
|
} from '@wordpress/blocks';
|
|
6
|
+
import { useDebounce } from '@wordpress/compose';
|
|
9
7
|
import {
|
|
10
8
|
__experimentalHStack as HStack,
|
|
11
9
|
__experimentalTruncate as Truncate,
|
|
12
10
|
} from '@wordpress/components';
|
|
13
|
-
import { useSelect } from '@wordpress/data';
|
|
11
|
+
import { useDispatch, useSelect } from '@wordpress/data';
|
|
14
12
|
import { DataForm } from '@wordpress/dataviews';
|
|
15
13
|
import { useContext, useState, useMemo } from '@wordpress/element';
|
|
16
14
|
import { __ } from '@wordpress/i18n';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Internal dependencies
|
|
20
|
-
*/
|
|
21
15
|
import { store as blockEditorStore } from '../../store';
|
|
22
16
|
import { unlock } from '../../lock-unlock';
|
|
23
17
|
import BlockContext from '../../components/block-context';
|
|
@@ -55,16 +49,18 @@ function createConfiguredControl( ControlComponent, config = {} ) {
|
|
|
55
49
|
* @param {string} props.clientId The clientId of the block.
|
|
56
50
|
* @param {Object} props.blockType The blockType definition.
|
|
57
51
|
* @param {Function} props.setAttributes Action to set the block's attributes.
|
|
58
|
-
* @param {boolean} props.
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
52
|
+
* @param {boolean} props.isMultiBlock Whether forms for multiple blocks are shown at the same time.
|
|
53
|
+
* This changes the behavior of the component:
|
|
54
|
+
* - Only the first field is shown for each block.
|
|
55
|
+
* - A dropdown is rendered allowing display of additional fields.
|
|
56
|
+
* - Hovering the block fields highlights the block in the canvas
|
|
57
|
+
* - Focusing a block field soft-selects the block in the canvas.
|
|
62
58
|
*/
|
|
63
59
|
function BlockFields( {
|
|
64
60
|
clientId,
|
|
65
61
|
blockType,
|
|
66
62
|
setAttributes,
|
|
67
|
-
|
|
63
|
+
isMultiBlock = false,
|
|
68
64
|
} ) {
|
|
69
65
|
const blockTitle = useBlockDisplayTitle( {
|
|
70
66
|
clientId,
|
|
@@ -103,9 +99,16 @@ function BlockFields( {
|
|
|
103
99
|
},
|
|
104
100
|
[ blockContext, clientId ]
|
|
105
101
|
);
|
|
102
|
+
const { selectBlock, toggleBlockHighlight } =
|
|
103
|
+
useDispatch( blockEditorStore );
|
|
104
|
+
|
|
105
|
+
const debouncedToggleBlockHighlight = useDebounce(
|
|
106
|
+
toggleBlockHighlight,
|
|
107
|
+
50
|
|
108
|
+
);
|
|
106
109
|
|
|
107
110
|
const computedForm = useMemo( () => {
|
|
108
|
-
if ( !
|
|
111
|
+
if ( ! isMultiBlock ) {
|
|
109
112
|
return blockType?.[ formKey ];
|
|
110
113
|
}
|
|
111
114
|
|
|
@@ -114,7 +117,7 @@ function BlockFields( {
|
|
|
114
117
|
...blockType?.[ formKey ],
|
|
115
118
|
fields: [ blockType?.[ formKey ]?.fields?.[ 0 ] ],
|
|
116
119
|
};
|
|
117
|
-
}, [ blockType,
|
|
120
|
+
}, [ blockType, isMultiBlock ] );
|
|
118
121
|
|
|
119
122
|
const [ form, setForm ] = useState( computedForm );
|
|
120
123
|
|
|
@@ -182,10 +185,32 @@ function BlockFields( {
|
|
|
182
185
|
};
|
|
183
186
|
|
|
184
187
|
return (
|
|
185
|
-
<div
|
|
188
|
+
<div
|
|
189
|
+
className="block-editor-block-fields__container"
|
|
190
|
+
onMouseEnter={
|
|
191
|
+
isMultiBlock
|
|
192
|
+
? () => debouncedToggleBlockHighlight( clientId, true )
|
|
193
|
+
: undefined
|
|
194
|
+
}
|
|
195
|
+
onMouseLeave={ () =>
|
|
196
|
+
isMultiBlock
|
|
197
|
+
? debouncedToggleBlockHighlight( clientId, false )
|
|
198
|
+
: undefined
|
|
199
|
+
}
|
|
200
|
+
onFocus={
|
|
201
|
+
isMultiBlock
|
|
202
|
+
? () => {
|
|
203
|
+
selectBlock(
|
|
204
|
+
clientId,
|
|
205
|
+
null /* null to avoid focus on the block in the canvas */
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
: undefined
|
|
209
|
+
}
|
|
210
|
+
>
|
|
186
211
|
<div className="block-editor-block-fields__header">
|
|
187
212
|
<HStack spacing={ 1 }>
|
|
188
|
-
{
|
|
213
|
+
{ isMultiBlock && (
|
|
189
214
|
<>
|
|
190
215
|
<BlockIcon
|
|
191
216
|
className="block-editor-block-fields__header-icon"
|
|
@@ -203,7 +228,7 @@ function BlockFields( {
|
|
|
203
228
|
/>
|
|
204
229
|
</>
|
|
205
230
|
) }
|
|
206
|
-
{ !
|
|
231
|
+
{ ! isMultiBlock && (
|
|
207
232
|
<h2 className="block-editor-block-fields__header-title">
|
|
208
233
|
{ __( 'Content' ) }
|
|
209
234
|
</h2>
|
|
@@ -236,7 +261,7 @@ export function BlockFieldsPanel( props ) {
|
|
|
236
261
|
<BlockFields
|
|
237
262
|
{ ...props }
|
|
238
263
|
blockType={ blockType }
|
|
239
|
-
|
|
264
|
+
isMultiBlock={ isSelectionWithinCurrentSection }
|
|
240
265
|
/>
|
|
241
266
|
</InspectorControls>
|
|
242
267
|
);
|
|
@@ -5,17 +5,15 @@
|
|
|
5
5
|
@use "./rich-text/styles.scss" as *;
|
|
6
6
|
|
|
7
7
|
.block-editor-block-fields__container {
|
|
8
|
-
padding: 0 $grid-unit-20;
|
|
8
|
+
padding: 0 $grid-unit-20 $grid-unit-20;
|
|
9
9
|
|
|
10
10
|
&:first-of-type {
|
|
11
11
|
padding-block-start: $grid-unit-10;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
&:last-of-type {
|
|
18
|
-
padding-block-end: $grid-unit-20;
|
|
12
|
+
/*
|
|
13
|
+
* Add border for the entire content controls and remove the similar border
|
|
14
|
+
* for tools panel.
|
|
15
|
+
*/
|
|
16
|
+
border-block-start: $border-width solid $gray-200;
|
|
19
17
|
}
|
|
20
18
|
}
|
|
21
19
|
|
|
@@ -30,6 +28,6 @@
|
|
|
30
28
|
|
|
31
29
|
.block-editor-block-fields__header-title {
|
|
32
30
|
flex: 1;
|
|
33
|
-
|
|
31
|
+
/* Override the default margin on a h2 element. */
|
|
34
32
|
margin: 0 !important;
|
|
35
33
|
}
|