Skip to content

Commit

Permalink
feat: Implement cursor navigation with navigation keys (#404)
Browse files Browse the repository at this point in the history
* feat(type): Implement cursor navigation with ArrowLeft and ArrowRight

* refactor(navigation-key): use a Number instead to hit all the lines

* test(type): simplify snapshot

* style(type): remove whitespace

Co-authored-by: Jesu Castillo <castillojesuj@gmail.com>

Closes #354
  • Loading branch information
juanca committed Nov 3, 2020
1 parent ee7c74f commit 01c3a56
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/__tests__/type.js
Expand Up @@ -1022,3 +1022,47 @@ test('should not type inside a contenteditable=false div', () => {
div - click: Left (0)
`)
})

test('navigation key: {arrowleft} and {arrowright} moves the cursor', () => {
const {element, getEventSnapshot} = setup('<input />')
userEvent.type(element, 'b{arrowleft}a{arrowright}c')
expect(getEventSnapshot()).toMatchInlineSnapshot(`
Events fired on: input[value="abc"]
input[value=""] - pointerover
input[value=""] - pointerenter
input[value=""] - mouseover: Left (0)
input[value=""] - mouseenter: Left (0)
input[value=""] - pointermove
input[value=""] - mousemove: Left (0)
input[value=""] - pointerdown
input[value=""] - mousedown: Left (0)
input[value=""] - focus
input[value=""] - focusin
input[value=""] - pointerup
input[value=""] - mouseup: Left (0)
input[value=""] - click: Left (0)
input[value=""] - keydown: b (98)
input[value=""] - keypress: b (98)
input[value="b"] - input
"{CURSOR}" -> "b{CURSOR}"
input[value="b"] - keyup: b (98)
input[value="b"] - keydown: ArrowLeft (37)
input[value="b"] - select
input[value="b"] - keyup: ArrowLeft (37)
input[value="b"] - keydown: a (97)
input[value="b"] - keypress: a (97)
input[value="ab"] - input
"{CURSOR}b" -> "ab{CURSOR}"
input[value="ab"] - select
input[value="ab"] - keyup: a (97)
input[value="ab"] - keydown: ArrowRight (39)
input[value="ab"] - select
input[value="ab"] - keyup: ArrowRight (39)
input[value="ab"] - keydown: c (99)
input[value="ab"] - keypress: c (99)
input[value="abc"] - input
"ab{CURSOR}" -> "abc{CURSOR}"
input[value="abc"] - keyup: c (99)
`)
})
50 changes: 50 additions & 0 deletions src/keys/navigation-key.js
@@ -0,0 +1,50 @@
import {fireEvent} from '@testing-library/dom'

import {setSelectionRangeIfNecessary} from '../utils'

const keys = {
ArrowLeft: {
keyCode: 37,
},
ArrowRight: {
keyCode: 39,
},
}

function getSelectionRange(currentElement, key) {
const {selectionStart, selectionEnd} = currentElement()
const cursorChange = Number(key in keys) * (key === 'ArrowLeft' ? -1 : 1)
return {
selectionStart: selectionStart + cursorChange,
selectionEnd: selectionEnd + cursorChange,
}
}

function navigationKey(key) {
const event = {
key,
keyCode: keys[key].keyCode,
which: keys[key].keyCode,
}

return ({currentElement, eventOverrides}) => {
fireEvent.keyDown(currentElement(), {
...event,
...eventOverrides,
})

const range = getSelectionRange(currentElement, key)
setSelectionRangeIfNecessary(
currentElement(),
range.selectionStart,
range.selectionEnd,
)

fireEvent.keyUp(currentElement(), {
...event,
...eventOverrides,
})
}
}

export {navigationKey}
3 changes: 3 additions & 0 deletions src/type.js
Expand Up @@ -15,6 +15,7 @@ import {
isContentEditable,
} from './utils'
import {click} from './click'
import {navigationKey} from './keys/navigation-key'

const modifierCallbackMap = {
...createModifierCallbackEntries({
Expand Down Expand Up @@ -44,6 +45,8 @@ const modifierCallbackMap = {
}

const specialCharCallbackMap = {
'{arrowleft}': navigationKey('ArrowLeft'),
'{arrowright}': navigationKey('ArrowRight'),
'{enter}': handleEnter,
'{esc}': handleEsc,
'{del}': handleDel,
Expand Down

0 comments on commit 01c3a56

Please sign in to comment.