Skip to content

Commit

Permalink
fix(pointer): fire pointer events on disabled elements (#818)
Browse files Browse the repository at this point in the history
  • Loading branch information
ph-fritsche authored Jan 1, 2022
1 parent 4f56856 commit ef2f4e5
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 61 deletions.
106 changes: 54 additions & 52 deletions src/pointer/pointerPress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,39 +102,40 @@ function down(
}
pointerState.pressed.push(pressObj)

if (!targetIsDisabled) {
if (pointerType !== 'mouse') {
fire('pointerover')
fire('pointerenter')
}
if (
pointerType !== 'mouse' ||
!pointerState.pressed.some(
p => p.keyDef !== keyDef && p.keyDef.pointerType === pointerType,
)
) {
fire('pointerdown')
}
if (pointerType === 'mouse') {
if (pointerType !== 'mouse') {
fire('pointerover')
fire('pointerenter')
}
if (
pointerType !== 'mouse' ||
!pointerState.pressed.some(
p => p.keyDef !== keyDef && p.keyDef.pointerType === pointerType,
)
) {
fire('pointerdown')
}

// TODO: touch...

if (pointerType === 'mouse') {
if (!targetIsDisabled) {
pressObj.unpreventedDefault = fire('mousedown')
}

// TODO: touch...
}

if (pointerType === 'mouse' && pressObj.unpreventedDefault) {
mousedownDefaultBehavior({
target,
targetIsDisabled,
clickCount,
position: pointerState.position[pointerName],
node,
offset,
})
}
if (pressObj.unpreventedDefault) {
mousedownDefaultBehavior({
target,
targetIsDisabled,
clickCount,
position: pointerState.position[pointerName],
node,
offset,
})
}

if (pointerType === 'mouse' && button === 'secondary') {
fire('contextmenu')
if (button === 'secondary') {
fire('contextmenu')
}
}

return pressObj
Expand Down Expand Up @@ -179,37 +180,38 @@ function up(

// TODO: pointerleave for touch device

if (!targetIsDisabled) {
if (
pointerType !== 'mouse' ||
!pointerState.pressed.filter(p => p.keyDef.pointerType === pointerType)
.length
) {
fire('pointerup')
}
if (pointerType !== 'mouse') {
fire('pointerout')
fire('pointerleave')
}
if (pointerType !== 'mouse' && !isMultiTouch) {
if (
pointerType !== 'mouse' ||
!pointerState.pressed.filter(p => p.keyDef.pointerType === pointerType)
.length
) {
fire('pointerup')
}
if (pointerType !== 'mouse') {
fire('pointerout')
fire('pointerleave')
}

if (pointerType !== 'mouse' && !isMultiTouch) {
if (!targetIsDisabled) {
if (clickCount === 1) {
fire('mouseover')
fire('mouseenter')
}
fire('mousemove')
unpreventedDefault = fire('mousedown') && unpreventedDefault
}
}

if (unpreventedDefault && pointerType !== 'mouse' && !isMultiTouch) {
mousedownDefaultBehavior({
target,
targetIsDisabled,
clickCount,
position: pointerState.position[pointerName],
node,
offset,
})
if (unpreventedDefault) {
mousedownDefaultBehavior({
target,
targetIsDisabled,
clickCount,
position: pointerState.position[pointerName],
node,
offset,
})
}
}

delete pointerState.position[pointerName].selectionRange
Expand Down
31 changes: 23 additions & 8 deletions tests/pointer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,22 +109,37 @@ describe('delay', () => {
})

test('only pointer events on disabled elements', async () => {
const {element, getEventSnapshot, getEvents} = setup('<button disabled />')
const {element, getEventSnapshot, eventWasFired} = setup(
'<button disabled />',
)

await userEvent.pointer([{target: element}, {keys: '[MouseLeft]'}])
await userEvent.pointer([
{target: element},
{keys: '[MouseLeft]'},
{target: element, keys: '[TouchA]'},
])

expect(getEventSnapshot()).toMatchInlineSnapshot(`
Events fired on: button
button - pointerover
button - pointerenter
button - pointermove
button - pointerdown
button - pointerup
button - pointerover
button - pointerenter
button - pointerdown
button - pointerup
button - pointerout
button - pointerleave
`)

expect(getEvents('pointerover')).toHaveLength(1)
// TODO: pointer down/up also happen on disabled elements
// expect(getEvents('pointerdown')).toHaveLength(1)
expect(getEvents('mouseover')).toHaveLength(0)
expect(getEvents('mousedown')).toHaveLength(0)
expect(getEvents('click')).toHaveLength(0)
expect(eventWasFired('pointerover')).toBe(true)
expect(eventWasFired('pointerdown')).toBe(true)
expect(eventWasFired('pointerup')).toBe(true)
expect(eventWasFired('mouseover')).toBe(false)
expect(eventWasFired('mousedown')).toBe(false)
expect(eventWasFired('mouseup')).toBe(false)
expect(eventWasFired('click')).toBe(false)
})
3 changes: 2 additions & 1 deletion tests/pointer/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ test('move focus to closest focusable element', async () => {
await userEvent.pointer({keys: '[MouseLeft>]', target: element.children[1]})
expect(element.children[1]).toHaveFocus()

await userEvent.pointer({keys: '[MouseLeft>]', target: element.children[0]})
await userEvent.pointer({keys: '[TouchA]', target: element.children[0]})
expect(element).toHaveFocus()
})

Expand All @@ -35,6 +35,7 @@ test('mousedown handlers can prevent moving focus', async () => {
element.addEventListener('mousedown', e => e.preventDefault())

await userEvent.pointer({keys: '[MouseLeft>]', target: element})
await userEvent.pointer({keys: '[TouchA]', target: element})

expect(element).not.toHaveFocus()
expect(element).toHaveProperty('selectionStart', 0)
Expand Down

0 comments on commit ef2f4e5

Please sign in to comment.