Skip to content

Commit

Permalink
Safari: prevent focus capturing caused by flex display (WordPress#66402)
Browse files Browse the repository at this point in the history
Co-authored-by: ellatrix <ellatrix@git.wordpress.org>
Co-authored-by: mcsf <mcsf@git.wordpress.org>
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
  • Loading branch information
4 people authored and karthick-murugan committed Nov 13, 2024
1 parent d49bdd8 commit 0a1b5a9
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 18 deletions.
12 changes: 0 additions & 12 deletions packages/block-library/src/group/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,6 @@
}
}

// Reset user select, but the next rule should take precedence for nested
// groups.
:where([data-has-multi-selection]:not([contenteditable="true"]) .wp-block-group > *) {
user-select: initial;
}

// When we are not multi-selecting, prevent children from capturing the
// selection, which happens when the group is flex and children inlined.
:where([data-has-multi-selection]:not([contenteditable="true"]) .wp-block-group) {
user-select: none;
}

// Place block list appender in the same place content will appear.
[data-type="core/group"].is-selected {
.block-list-appender {
Expand Down
2 changes: 2 additions & 0 deletions packages/rich-text/src/component/event-listeners/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import formatBoundaries from './format-boundaries';
import deleteHandler from './delete';
import inputAndSelection from './input-and-selection';
import selectionChangeCompat from './selection-change-compat';
import { preventFocusCapture } from './prevent-focus-capture';

const allEventListeners = [
copyHandler,
Expand All @@ -21,6 +22,7 @@ const allEventListeners = [
deleteHandler,
inputAndSelection,
selectionChangeCompat,
preventFocusCapture,
];

export function useEventListeners( props ) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Prevents focus from being captured by the element when clicking _outside_
* around the element. This may happen when the parent element is flex.
* @see https://github.com/WordPress/gutenberg/pull/65857
* @see https://github.com/WordPress/gutenberg/pull/66402
*/
export function preventFocusCapture() {
return ( element ) => {
const { ownerDocument } = element;
const { defaultView } = ownerDocument;

let value = null;

function onPointerDown( event ) {
// Abort if the event is default prevented, we will not get a pointer up event.
if ( event.defaultPrevented ) {
return;
}
if ( event.target === element ) {
return;
}
if ( ! event.target.contains( element ) ) {
return;
}
value = element.getAttribute( 'contenteditable' );
element.setAttribute( 'contenteditable', 'false' );
defaultView.getSelection().removeAllRanges();
}

function onPointerUp() {
if ( value !== null ) {
element.setAttribute( 'contenteditable', value );
value = null;
}
}

defaultView.addEventListener( 'pointerdown', onPointerDown );
defaultView.addEventListener( 'pointerup', onPointerUp );
return () => {
defaultView.removeEventListener( 'pointerdown', onPointerDown );
defaultView.removeEventListener( 'pointerup', onPointerUp );
};
};
}
9 changes: 3 additions & 6 deletions test/e2e/specs/editor/various/multi-block-selection.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ test.describe( 'Multi-block selection (@firefox, @webkit)', () => {
] );
} );

test( 'should clear selection when clicking next to blocks (-firefox)', async ( {
test( 'should clear selection when clicking next to blocks', async ( {
page,
editor,
multiBlockSelectionUtils,
Expand All @@ -752,16 +752,13 @@ test.describe( 'Multi-block selection (@firefox, @webkit)', () => {
name: 'Block: Paragraph',
} )
.filter( { hasText: '1' } );
// For some reason in Chrome it requires two clicks, even though it
// doesn't when testing manually.
await paragraph1.click( {
position: { x: -1, y: 0 },
// Use force since it's outside the bounding box of the element.
force: true,
} );

await expect
.poll( multiBlockSelectionUtils.getSelectedFlatIndices )
.toEqual( [ 1 ] );

await paragraph1.click( {
position: { x: -1, y: 0 },
// Use force since it's outside the bounding box of the element.
Expand Down

0 comments on commit 0a1b5a9

Please sign in to comment.