From 40e18a9749f4c9661d3b287b14e5cdaabe79017a Mon Sep 17 00:00:00 2001 From: Philipp Fritsche Date: Thu, 31 Mar 2022 17:18:15 +0000 Subject: [PATCH 1/2] fix(pointer): change selection before dispatching `focus` --- src/pointer/pointerPress.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/pointer/pointerPress.ts b/src/pointer/pointerPress.ts index da101fa4..8730f917 100644 --- a/src/pointer/pointerPress.ts +++ b/src/pointer/pointerPress.ts @@ -266,13 +266,6 @@ function mousedownDefaultBehavior({ node?: Node offset?: number }) { - // The closest focusable element is focused when a `mousedown` would have been fired. - // Even if there was no `mousedown` because the element was disabled. - // A `mousedown` that preventsDefault cancels this though. - focus(target) - - // TODO: What happens if a focus event handler interfers? - // An unprevented mousedown moves the cursor to the closest character. // We try to approximate the behavior for a no-layout environment. if (!targetIsDisabled) { @@ -326,6 +319,11 @@ function mousedownDefaultBehavior({ selection.addRange(range.cloneRange()) } } + + // The closest focusable element is focused when a `mousedown` would have been fired. + // Even if there was no `mousedown` because the element was disabled. + // A `mousedown` that preventsDefault cancels this though. + focus(target) } function getTextRange( From 822debf0b272bd41065edbe9793bf017b8566413 Mon Sep 17 00:00:00 2001 From: Philipp Fritsche Date: Thu, 31 Mar 2022 17:26:11 +0000 Subject: [PATCH 2/2] update tests --- tests/pointer/select.ts | 14 ++++++++++++++ tests/utility/type.ts | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/pointer/select.ts b/tests/pointer/select.ts index 7e2fc45a..83104663 100644 --- a/tests/pointer/select.ts +++ b/tests/pointer/select.ts @@ -368,3 +368,17 @@ describe('focus control when clicking label', () => { expect(input).not.toHaveFocus() }) }) + +test('focus event handler can override selection', async () => { + const {element, user} = setup(``, { + focus: false, + }) + element.addEventListener('focus', e => + (e.target as HTMLInputElement).select(), + ) + + await user.click(element) + + expect(element).toHaveProperty('selectionStart', 0) + expect(element).toHaveProperty('selectionEnd', 5) +}) diff --git a/tests/utility/type.ts b/tests/utility/type.ts index 1e4380c9..26e73131 100644 --- a/tests/utility/type.ts +++ b/tests/utility/type.ts @@ -19,9 +19,9 @@ test('type into input', async () => { input[value="foo"] - mousemove input[value="foo"] - pointerdown input[value="foo"] - mousedown: primary + input[value="foo"] - select input[value="foo"] - focus input[value="foo"] - focusin - input[value="foo"] - select input[value="foo"] - pointerup input[value="foo"] - mouseup: primary input[value="foo"] - click: primary