Skip to content

Commit 094bd3a

Browse files
Drag and drop: fix firefox compat logic (#67439)
Co-authored-by: ellatrix <[email protected]> Co-authored-by: youknowriad <[email protected]>
1 parent 0b3a191 commit 094bd3a

File tree

2 files changed

+66
-10
lines changed

2 files changed

+66
-10
lines changed

packages/block-editor/src/components/block-list/use-block-props/index.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,6 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
104104
canMove,
105105
} = useContext( PrivateBlockContext );
106106

107-
const canDrag = canMove && ! hasChildSelected;
108-
109107
// translators: %s: Type of block (i.e. Text, Image etc)
110108
const blockLabel = sprintf( __( 'Block: %s' ), blockTitle );
111109
const htmlSuffix = mode === 'html' && ! __unstableIsHtml ? '-visual' : '';
@@ -125,7 +123,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
125123
isEnabled: isSectionBlock,
126124
} ),
127125
useScrollIntoView( { isSelected } ),
128-
canDrag ? ffDragRef : undefined,
126+
canMove ? ffDragRef : undefined,
129127
] );
130128

131129
const blockEditContext = useBlockEditContext();
@@ -158,7 +156,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
158156

159157
return {
160158
tabIndex: blockEditingMode === 'disabled' ? -1 : 0,
161-
draggable: canDrag ? true : undefined,
159+
draggable: canMove && ! hasChildSelected ? true : undefined,
162160
...wrapperProps,
163161
...props,
164162
ref: mergedRefs,

packages/block-editor/src/components/block-list/use-block-props/use-firefox-draggable-compatibility.js

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,68 @@
33
*/
44
import { useRefEffect } from '@wordpress/compose';
55

6+
const nodesByDocument = new Map();
7+
8+
function add( doc, node ) {
9+
let set = nodesByDocument.get( doc );
10+
if ( ! set ) {
11+
set = new Set();
12+
nodesByDocument.set( doc, set );
13+
doc.addEventListener( 'pointerdown', down );
14+
}
15+
set.add( node );
16+
}
17+
18+
function remove( doc, node ) {
19+
const set = nodesByDocument.get( doc );
20+
if ( set ) {
21+
set.delete( node );
22+
restore( node );
23+
if ( set.size === 0 ) {
24+
nodesByDocument.delete( doc );
25+
doc.removeEventListener( 'pointerdown', down );
26+
}
27+
}
28+
}
29+
30+
function restore( node ) {
31+
const prevDraggable = node.getAttribute( 'data-draggable' );
32+
if ( prevDraggable ) {
33+
node.removeAttribute( 'data-draggable' );
34+
// Only restore if `draggable` is still removed. It could have been
35+
// changed by React in the meantime.
36+
if ( prevDraggable === 'true' && ! node.getAttribute( 'draggable' ) ) {
37+
node.setAttribute( 'draggable', 'true' );
38+
}
39+
}
40+
}
41+
42+
function down( event ) {
43+
const { target } = event;
44+
const { ownerDocument, isContentEditable } = target;
45+
const nodes = nodesByDocument.get( ownerDocument );
46+
47+
if ( isContentEditable ) {
48+
// Whenever an editable element is clicked, check which draggable
49+
// blocks contain this element, and temporarily disable draggability.
50+
for ( const node of nodes ) {
51+
if (
52+
node.getAttribute( 'draggable' ) === 'true' &&
53+
node.contains( target )
54+
) {
55+
node.removeAttribute( 'draggable' );
56+
node.setAttribute( 'data-draggable', 'true' );
57+
}
58+
}
59+
} else {
60+
// Whenever a non-editable element is clicked, re-enable draggability
61+
// for any blocks that were previously disabled.
62+
for ( const node of nodes ) {
63+
restore( node );
64+
}
65+
}
66+
}
67+
668
/**
769
* In Firefox, the `draggable` and `contenteditable` attributes don't play well
870
* together. When `contenteditable` is within a `draggable` element, selection
@@ -13,13 +75,9 @@ import { useRefEffect } from '@wordpress/compose';
1375
*/
1476
export function useFirefoxDraggableCompatibility() {
1577
return useRefEffect( ( node ) => {
16-
function onDown( event ) {
17-
node.draggable = ! event.target.isContentEditable;
18-
}
19-
const { ownerDocument } = node;
20-
ownerDocument.addEventListener( 'pointerdown', onDown );
78+
add( node.ownerDocument, node );
2179
return () => {
22-
ownerDocument.removeEventListener( 'pointerdown', onDown );
80+
remove( node.ownerDocument, node );
2381
};
2482
}, [] );
2583
}

0 commit comments

Comments
 (0)