Skip to content

Commit

Permalink
Merge branch 'beta' into build
Browse files Browse the repository at this point in the history
  • Loading branch information
ph-fritsche committed Dec 30, 2021
2 parents 12e88a8 + e9635f6 commit cb6ed16
Show file tree
Hide file tree
Showing 20 changed files with 327 additions and 183 deletions.
21 changes: 0 additions & 21 deletions src/keyboard/getEventProps.ts

This file was deleted.

18 changes: 13 additions & 5 deletions src/keyboard/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,19 @@ export function createKeyboardState(): keyboardState {
pressed: [],
carryChar: '',
modifiers: {
alt: false,
caps: false,
ctrl: false,
meta: false,
shift: false,
Alt: false,
AltGraph: false,
Control: false,
CapsLock: false,
Fn: false,
FnLock: false,
Meta: false,
NumLock: false,
ScrollLock: false,
Shift: false,
Symbol: false,
SymbolLock: false,
},
modifierPhase: {},
}
}
5 changes: 5 additions & 0 deletions src/keyboard/keyMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,10 @@ export const defaultKeyMap: keyboardKey[] = [
{code: 'PageUp', key: 'PageUp'},
{code: 'PageDown', key: 'PageDown'},

// Special keys that are not part of a default US-layout but included for specific behavior
{code: 'Fn', key: 'Fn'},
{code: 'Symbol', key: 'Symbol'},
{code: 'AltRight', key: 'AltGraph'},

// TODO: add mappings
]
7 changes: 3 additions & 4 deletions src/keyboard/keyboardAction.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {fireEvent} from '@testing-library/dom'
import {Config} from '../setup'
import {getActiveElement, wait} from '../utils'
import {getActiveElement, getKeyEventProps, wait} from '../utils'
import {behaviorPlugin, keyboardKey} from './types'
import * as plugins from './plugins'
import {getKeyEventProps} from './getEventProps'

export interface KeyboardAction {
keyDef: keyboardKey
Expand Down Expand Up @@ -162,7 +161,7 @@ function applyPlugins(
function hasKeyPress(keyDef: keyboardKey, config: Config) {
return (
(keyDef.key?.length === 1 || keyDef.key === 'Enter') &&
!config.keyboardState.modifiers.ctrl &&
!config.keyboardState.modifiers.alt
!config.keyboardState.modifiers.Control &&
!config.keyboardState.modifiers.Alt
)
}
2 changes: 1 addition & 1 deletion src/keyboard/plugins/character.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ export const keypressBehavior: behaviorPlugin[] = [
prepareInput(
'\n',
element,
isContentEditable(element) && !keyboardState.modifiers.shift
isContentEditable(element) && !keyboardState.modifiers.Shift
? 'insertParagraph'
: 'insertLineBreak',
)?.commit()
Expand Down
2 changes: 1 addition & 1 deletion src/keyboard/plugins/combination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {selectAll} from '../../utils'
export const keydownBehavior: behaviorPlugin[] = [
{
matches: (keyDef, element, {keyboardState}) =>
keyDef.code === 'KeyA' && keyboardState.modifiers.ctrl,
keyDef.code === 'KeyA' && keyboardState.modifiers.Control,
handle: (keyDef, element) => selectAll(element),
},
]
71 changes: 4 additions & 67 deletions src/keyboard/plugins/functional.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,16 @@ import {
blur,
focus,
getTabDestination,
getUIEventModifiers,
hasFormSubmit,
isClickableInput,
isEditable,
isElementType,
prepareInput,
} from '../../utils'
import {getKeyEventProps, getMouseEventProps} from '../getEventProps'
import {behaviorPlugin} from '../types'

const modifierKeys = {
Alt: 'alt',
Control: 'ctrl',
Shift: 'shift',
Meta: 'meta',
} as const

export const preKeydownBehavior: behaviorPlugin[] = [
// modifierKeys switch on the modifier BEFORE the keydown event
...Object.entries(modifierKeys).map(
([key, modKey]): behaviorPlugin => ({
matches: keyDef => keyDef.key === key,
handle: (keyDef, element, {keyboardState}) => {
keyboardState.modifiers[modKey] = true
},
}),
),

// AltGraph produces an extra keydown for Control
// The modifier does not change
{
matches: keyDef => keyDef.key === 'AltGraph',
handle: (keyDef, element, {keyboardMap, keyboardState}) => {
const ctrlKeyDef = keyboardMap.find(
k => k.key === 'Control',
) ?? /* istanbul ignore next */ {key: 'Control', code: 'Control'}
fireEvent.keyDown(element, getKeyEventProps(ctrlKeyDef, keyboardState))
},
},
]

export const keydownBehavior: behaviorPlugin[] = [
{
matches: keyDef => keyDef.key === 'CapsLock',
handle: (keyDef, element, {keyboardState}) => {
keyboardState.modifiers.caps = !keyboardState.modifiers.caps
},
},
{
matches: (keyDef, element) =>
keyDef.key === 'Backspace' && isEditable(element),
Expand All @@ -66,7 +29,7 @@ export const keydownBehavior: behaviorPlugin[] = [
{
matches: keyDef => keyDef.key === 'Tab',
handle: (keyDef, element, {keyboardState}) => {
const dest = getTabDestination(element, keyboardState.modifiers.shift)
const dest = getTabDestination(element, keyboardState.modifiers.Shift)
if (dest === element.ownerDocument.body) {
blur(element)
} else {
Expand Down Expand Up @@ -103,7 +66,7 @@ export const keypressBehavior: behaviorPlugin[] = [
// Links with href defined should handle Enter the same as a click
(isElementType(element, 'a') && Boolean(element.href))),
handle: (keyDef, element, {keyboardState}) => {
fireEvent.click(element, getMouseEventProps(keyboardState))
fireEvent.click(element, getUIEventModifiers(keyboardState))
},
},
{
Expand All @@ -122,38 +85,12 @@ export const keypressBehavior: behaviorPlugin[] = [
},
]

export const preKeyupBehavior: behaviorPlugin[] = [
// modifierKeys switch off the modifier BEFORE the keyup event
...Object.entries(modifierKeys).map(
([key, modKey]): behaviorPlugin => ({
matches: keyDef => keyDef.key === key,
handle: (keyDef, element, {keyboardState}) => {
keyboardState.modifiers[modKey] = false
},
}),
),
]

export const keyupBehavior: behaviorPlugin[] = [
{
matches: (keyDef, element) =>
keyDef.key === ' ' && isClickableInput(element),
handle: (keyDef, element, {keyboardState}) => {
fireEvent.click(element, getMouseEventProps(keyboardState))
},
},
]

export const postKeyupBehavior: behaviorPlugin[] = [
// AltGraph produces an extra keyup for Control
// The modifier does not change
{
matches: keyDef => keyDef.key === 'AltGraph',
handle: (keyDef, element, {keyboardMap, keyboardState}) => {
const ctrlKeyDef = keyboardMap.find(
k => k.key === 'Control',
) ?? /* istanbul ignore next */ {key: 'Control', code: 'Control'}
fireEvent.keyUp(element, getKeyEventProps(ctrlKeyDef, keyboardState))
fireEvent.click(element, getUIEventModifiers(keyboardState))
},
},
]
7 changes: 4 additions & 3 deletions src/keyboard/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import * as controlKeys from './control'
import * as characterKeys from './character'
import * as functionalKeys from './functional'
import * as combination from './combination'
import * as modifiers from './modifiers'

export const preKeydownBehavior: behaviorPlugin[] = [
...functionalKeys.preKeydownBehavior,
...modifiers.preKeydownBehavior,
]

export const keydownBehavior: behaviorPlugin[] = [
Expand All @@ -22,11 +23,11 @@ export const keypressBehavior: behaviorPlugin[] = [
]

export const preKeyupBehavior: behaviorPlugin[] = [
...functionalKeys.preKeyupBehavior,
...modifiers.preKeyupBehavior,
]

export const keyupBehavior: behaviorPlugin[] = [...functionalKeys.keyupBehavior]

export const postKeyupBehavior: behaviorPlugin[] = [
...functionalKeys.postKeyupBehavior,
...modifiers.postKeyupBehavior,
]
92 changes: 92 additions & 0 deletions src/keyboard/plugins/modifiers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* This file should contain behavior for modifier keys:
* https://www.w3.org/TR/uievents-key/#keys-modifier
*/

import {fireEvent} from '@testing-library/dom'
import {getKeyEventProps} from '../../utils'
import {behaviorPlugin} from '../types'

const modifierKeys = [
'Alt',
'AltGraph',
'Control',
'Fn',
'Meta',
'Shift',
'Symbol',
] as const
type ModififierKey = typeof modifierKeys[number]

const modifierLocks = [
'CapsLock',
'FnLock',
'NumLock',
'ScrollLock',
'SymbolLock',
] as const
type ModififierLockKey = typeof modifierLocks[number]

// modifierKeys switch on the modifier BEFORE the keydown event
export const preKeydownBehavior: behaviorPlugin[] = [
{
matches: keyDef => modifierKeys.includes(keyDef.key as ModififierKey),
handle: (keyDef, element, {keyboardMap, keyboardState}) => {
keyboardState.modifiers[keyDef.key as ModififierKey] = true

// AltGraph produces an extra keydown for Control
// The modifier does not change
if (keyDef.key === 'AltGraph') {
const ctrlKeyDef = keyboardMap.find(
k => k.key === 'Control',
) ?? /* istanbul ignore next */ {key: 'Control', code: 'Control'}
fireEvent.keyDown(element, getKeyEventProps(ctrlKeyDef, keyboardState))
}
},
},
{
matches: keyDef => modifierLocks.includes(keyDef.key as ModififierLockKey),
handle: (keyDef, element, {keyboardState}) => {
const key = keyDef.key as ModififierLockKey
keyboardState.modifierPhase[key] = keyboardState.modifiers[key]

if (!keyboardState.modifierPhase[key]) {
keyboardState.modifiers[key] = true
}
},
},
]

// modifierKeys switch off the modifier BEFORE the keyup event
export const preKeyupBehavior: behaviorPlugin[] = [
{
matches: keyDef => modifierKeys.includes(keyDef.key as ModififierKey),
handle: (keyDef, element, {keyboardState}) => {
keyboardState.modifiers[keyDef.key as ModififierKey] = false
},
},
{
matches: keyDef => modifierLocks.includes(keyDef.key as ModififierLockKey),
handle: (keyDef, element, {keyboardState}) => {
const key = keyDef.key as ModififierLockKey

if (keyboardState.modifierPhase[key]) {
keyboardState.modifiers[key] = false
}
},
},
]

export const postKeyupBehavior: behaviorPlugin[] = [
// AltGraph produces an extra keyup for Control
// The modifier does not change
{
matches: keyDef => keyDef.key === 'AltGraph',
handle: (keyDef, element, {keyboardMap, keyboardState}) => {
const ctrlKeyDef = keyboardMap.find(
k => k.key === 'Control',
) ?? /* istanbul ignore next */ {key: 'Control', code: 'Control'}
fireEvent.keyUp(element, getKeyEventProps(ctrlKeyDef, keyboardState))
},
},
]
24 changes: 19 additions & 5 deletions src/keyboard/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,25 @@ export type keyboardState = {
Active modifiers
*/
modifiers: {
alt: boolean
caps: boolean
ctrl: boolean
meta: boolean
shift: boolean
Alt: boolean
AltGraph: boolean
CapsLock: boolean
Control: boolean
Fn: boolean
FnLock: boolean
Meta: boolean
NumLock: boolean
ScrollLock: boolean
Shift: boolean
Symbol: boolean
SymbolLock: boolean
}
modifierPhase: {
CapsLock?: boolean
FnLock?: boolean
NumLock?: boolean
ScrollLock?: boolean
SymbolLock?: boolean
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export * from './focus/selectAll'
export * from './focus/selection'
export * from './focus/selector'

export * from './keyboard/getKeyEventProps'
export * from './keyboard/getUIEventModifiers'

export * from './keyDef/readNextDescriptor'

export * from './misc/eventWrapper'
Expand Down
Loading

0 comments on commit cb6ed16

Please sign in to comment.