Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions components/atom/pinInput/src/hooks/useKeyPress.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
import {useEffect} from 'react'

const UNIDENTIFIED_KEYS = ['Unidentified', 'Process']

const useKeyPress = (callback, {target, onChange}) => {
const events = []
return useEffect(() => {
const element = target?.current
if (element) {
events.push(element.addEventListener('keydown', callback))
if (!element) return

const handleKeyDown = event => {
if (UNIDENTIFIED_KEYS.includes(event.key)) return
if (event.key.length === 1) {
event.preventDefault()
}
callback(event)
}

const handleInput = event => {
if (!event.data) return
// eslint-disable-next-line n/no-callback-literal
callback({key: event.data, preventDefault: () => {}})
}

element.addEventListener('keydown', handleKeyDown)
element.addEventListener('input', handleInput)
return () => {
events.forEach(event => {
if (element) element.removeEventListener('keydown', callback)
})
element.removeEventListener('keydown', handleKeyDown)
element.removeEventListener('input', handleInput)
}
}, [target, callback, onChange]) // eslint-disable-line react-hooks/exhaustive-deps
}
Expand Down
68 changes: 68 additions & 0 deletions components/atom/pinInput/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1570,6 +1570,74 @@ describe(json.name, () => {
expect(focusPosition).to.equal(initialFocusPosition + 1)
expect(newInnerValue.filter(Boolean).join('')).to.equal(args.value)
})

it("given an 'Unidentified' key event (mobile virtual keyboard) should NOT change anything", () => {
// Given
const args = {value: '123456'}
const eventArgs = {key: 'Unidentified'}

// When
const hook = setupReducerEnvironment(args)
let [store, dispatch] = hook.result.current

const {focusPosition: initialFocusPosition, innerValue} = store

// Then
expect(initialFocusPosition).to.equal(0)
expect(innerValue.filter(Boolean).join('')).to.equal(args.value)

// And
// Given
const onChange = () => null
const keyboardEvent = new KeyboardEvent('keydown', {...eventArgs})

// When
dispatch(atomPinInputActions.setKey({event: keyboardEvent, onChange}))
hook.rerender()

// Then
store = hook.result.current[0]
const focusPosition = store.focusPosition
const newInnerValue = store.innerValue
expect(focusPosition).to.equal(initialFocusPosition)
expect(newInnerValue.filter(Boolean).join('')).to.equal(args.value)
})

it('given a synthetic input event (mobile fallback) with a valid char changes innerValue and increments focusPosition', () => {
// Given
const args = {value: '123456'}

// When
const hook = setupReducerEnvironment(args)
let [store, dispatch] = hook.result.current

const {focusPosition: initialFocusPosition, innerValue} = store

// Then
expect(initialFocusPosition).to.equal(0)
expect(innerValue.filter(Boolean).join('')).to.equal(args.value)

// And
// Given
const onChange = () => null
const syntheticEvent = {key: '9', preventDefault: () => {}}

// When
dispatch(atomPinInputActions.setKey({event: syntheticEvent, onChange}))
hook.rerender()

// Then
store = hook.result.current[0]
const focusPosition = store.focusPosition
const newInnerValue = store.innerValue
expect(focusPosition).to.equal(initialFocusPosition + 1)
expect(newInnerValue.filter(Boolean).join('')).to.equal(
args.value
.split('')
.map((value, index) => (index === initialFocusPosition ? '9' : value))
.join('')
)
})
})

describe('atomPinInputActions', () => {
Expand Down
Loading