This commit is contained in:
Iliyan Angelov
2025-09-14 23:24:25 +03:00
commit c67067a2a4
71311 changed files with 6800714 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
import { keyboardKey, keyboardState } from './types';
export declare function getKeyEventProps(keyDef: keyboardKey, state: keyboardState): {
key: string | undefined;
code: string | undefined;
altKey: boolean;
ctrlKey: boolean;
metaKey: boolean;
shiftKey: boolean;
/** @deprecated use code instead */
keyCode: number | undefined;
};
export declare function getMouseEventProps(state: keyboardState): {
altKey: boolean;
ctrlKey: boolean;
metaKey: boolean;
shiftKey: boolean;
};

View File

@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getKeyEventProps = getKeyEventProps;
exports.getMouseEventProps = getMouseEventProps;
function getKeyEventProps(keyDef, state) {
var _keyDef$keyCode, _keyDef$key;
return {
key: keyDef.key,
code: keyDef.code,
altKey: state.modifiers.alt,
ctrlKey: state.modifiers.ctrl,
metaKey: state.modifiers.meta,
shiftKey: state.modifiers.shift,
/** @deprecated use code instead */
keyCode: (_keyDef$keyCode = keyDef.keyCode) != null ? _keyDef$keyCode : // istanbul ignore next
((_keyDef$key = keyDef.key) == null ? void 0 : _keyDef$key.length) === 1 ? keyDef.key.charCodeAt(0) : undefined
};
}
function getMouseEventProps(state) {
return {
altKey: state.modifiers.alt,
ctrlKey: state.modifiers.ctrl,
metaKey: state.modifiers.meta,
shiftKey: state.modifiers.shift
};
}

View File

@@ -0,0 +1,19 @@
import { keyboardKey, keyboardOptions } from './types';
/**
* Get the next key from keyMap
*
* Keys can be referenced by `{key}` or `{special}` as well as physical locations per `[code]`.
* Everything else will be interpreted as a typed character - e.g. `a`.
* Brackets `{` and `[` can be escaped by doubling - e.g. `foo[[bar` translates to `foo[bar`.
* Keeping the key pressed can be written as `{key>}`.
* When keeping the key pressed you can choose how long (how many keydown and keypress) the key is pressed `{key>3}`.
* You can then release the key per `{key>3/}` or keep it pressed and continue with the next key.
* Modifiers like `{shift}` imply being kept pressed. This can be turned of per `{shift/}`.
*/
export declare function getNextKeyDef(text: string, options: keyboardOptions): {
keyDef: keyboardKey;
consumedLength: number;
releasePrevious: boolean;
releaseSelf: boolean;
repeat: number;
};

View File

@@ -0,0 +1,174 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getNextKeyDef = getNextKeyDef;
var bracketDict;
(function (bracketDict) {
bracketDict["{"] = "}";
bracketDict["["] = "]";
})(bracketDict || (bracketDict = {}));
var legacyModifiers;
(function (legacyModifiers) {
legacyModifiers["alt"] = "alt";
legacyModifiers["ctrl"] = "ctrl";
legacyModifiers["meta"] = "meta";
legacyModifiers["shift"] = "shift";
})(legacyModifiers || (legacyModifiers = {}));
var legacyKeyMap;
/**
* Get the next key from keyMap
*
* Keys can be referenced by `{key}` or `{special}` as well as physical locations per `[code]`.
* Everything else will be interpreted as a typed character - e.g. `a`.
* Brackets `{` and `[` can be escaped by doubling - e.g. `foo[[bar` translates to `foo[bar`.
* Keeping the key pressed can be written as `{key>}`.
* When keeping the key pressed you can choose how long (how many keydown and keypress) the key is pressed `{key>3}`.
* You can then release the key per `{key>3/}` or keep it pressed and continue with the next key.
* Modifiers like `{shift}` imply being kept pressed. This can be turned of per `{shift/}`.
*/
(function (legacyKeyMap) {
legacyKeyMap["ctrl"] = "Control";
legacyKeyMap["del"] = "Delete";
legacyKeyMap["esc"] = "Escape";
legacyKeyMap["space"] = " ";
})(legacyKeyMap || (legacyKeyMap = {}));
function getNextKeyDef(text, options) {
var _options$keyboardMap$;
const {
type,
descriptor,
consumedLength,
releasePrevious,
releaseSelf,
repeat
} = readNextDescriptor(text);
const keyDef = (_options$keyboardMap$ = options.keyboardMap.find(def => {
if (type === '[') {
var _def$code;
return ((_def$code = def.code) == null ? void 0 : _def$code.toLowerCase()) === descriptor.toLowerCase();
} else if (type === '{') {
var _def$key;
const key = mapLegacyKey(descriptor);
return ((_def$key = def.key) == null ? void 0 : _def$key.toLowerCase()) === key.toLowerCase();
}
return def.key === descriptor;
})) != null ? _options$keyboardMap$ : {
key: 'Unknown',
code: 'Unknown',
[type === '[' ? 'code' : 'key']: descriptor
};
return {
keyDef,
consumedLength,
releasePrevious,
releaseSelf,
repeat
};
}
function readNextDescriptor(text) {
let pos = 0;
const startBracket = text[pos] in bracketDict ? text[pos] : '';
pos += startBracket.length; // `foo{{bar` is an escaped char at position 3,
// but `foo{{{>5}bar` should be treated as `{` pressed down for 5 keydowns.
const startBracketRepeated = startBracket ? text.match(new RegExp(`^\\${startBracket}+`))[0].length : 0;
const isEscapedChar = startBracketRepeated === 2 || startBracket === '{' && startBracketRepeated > 3;
const type = isEscapedChar ? '' : startBracket;
return {
type,
...(type === '' ? readPrintableChar(text, pos) : readTag(text, pos, type))
};
}
function readPrintableChar(text, pos) {
const descriptor = text[pos];
assertDescriptor(descriptor, text, pos);
pos += descriptor.length;
return {
consumedLength: pos,
descriptor,
releasePrevious: false,
releaseSelf: true,
repeat: 1
};
}
function readTag(text, pos, startBracket) {
var _text$slice$match, _text$slice$match$, _text$slice$match2;
const releasePreviousModifier = text[pos] === '/' ? '/' : '';
pos += releasePreviousModifier.length;
const descriptor = (_text$slice$match = text.slice(pos).match(/^\w+/)) == null ? void 0 : _text$slice$match[0];
assertDescriptor(descriptor, text, pos);
pos += descriptor.length;
const repeatModifier = (_text$slice$match$ = (_text$slice$match2 = text.slice(pos).match(/^>\d+/)) == null ? void 0 : _text$slice$match2[0]) != null ? _text$slice$match$ : '';
pos += repeatModifier.length;
const releaseSelfModifier = text[pos] === '/' || !repeatModifier && text[pos] === '>' ? text[pos] : '';
pos += releaseSelfModifier.length;
const expectedEndBracket = bracketDict[startBracket];
const endBracket = text[pos] === expectedEndBracket ? expectedEndBracket : '';
if (!endBracket) {
throw new Error(getErrorMessage([!repeatModifier && 'repeat modifier', !releaseSelfModifier && 'release modifier', `"${expectedEndBracket}"`].filter(Boolean).join(' or '), text[pos], text));
}
pos += endBracket.length;
return {
consumedLength: pos,
descriptor,
releasePrevious: !!releasePreviousModifier,
repeat: repeatModifier ? Math.max(Number(repeatModifier.substr(1)), 1) : 1,
releaseSelf: hasReleaseSelf(startBracket, descriptor, releaseSelfModifier, repeatModifier)
};
}
function assertDescriptor(descriptor, text, pos) {
if (!descriptor) {
throw new Error(getErrorMessage('key descriptor', text[pos], text));
}
}
function getEnumValue(f, key) {
return f[key];
}
function hasReleaseSelf(startBracket, descriptor, releaseSelfModifier, repeatModifier) {
if (releaseSelfModifier) {
return releaseSelfModifier === '/';
}
if (repeatModifier) {
return false;
}
if (startBracket === '{' && getEnumValue(legacyModifiers, descriptor.toLowerCase())) {
return false;
}
return true;
}
function mapLegacyKey(descriptor) {
var _getEnumValue;
return (_getEnumValue = getEnumValue(legacyKeyMap, descriptor)) != null ? _getEnumValue : descriptor;
}
function getErrorMessage(expected, found, text) {
return `Expected ${expected} but found "${found != null ? found : ''}" in "${text}"
See https://github.com/testing-library/user-event/blob/main/README.md#keyboardtext-options
for more information about how userEvent parses your input.`;
}

View File

@@ -0,0 +1,18 @@
import { keyboardState, keyboardOptions, keyboardKey } from './types';
export { specialCharMap } from './specialCharMap';
export type { keyboardOptions, keyboardKey };
export declare function keyboard(text: string, options?: Partial<keyboardOptions & {
keyboardState: keyboardState;
delay: 0;
}>): keyboardState;
export declare function keyboard(text: string, options: Partial<keyboardOptions & {
keyboardState: keyboardState;
delay: number;
}>): Promise<keyboardState>;
export declare function keyboardImplementationWrapper(text: string, config?: Partial<keyboardOptions & {
keyboardState: keyboardState;
}>): {
promise: Promise<void>;
state: keyboardState;
releaseAllKeys: () => void;
};

View File

@@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.keyboard = keyboard;
exports.keyboardImplementationWrapper = keyboardImplementationWrapper;
Object.defineProperty(exports, "specialCharMap", {
enumerable: true,
get: function () {
return _specialCharMap.specialCharMap;
}
});
var _dom = require("@testing-library/dom");
var _keyboardImplementation = require("./keyboardImplementation");
var _keyMap = require("./keyMap");
var _specialCharMap = require("./specialCharMap");
function keyboard(text, options) {
var _options$delay;
const {
promise,
state
} = keyboardImplementationWrapper(text, options);
if (((_options$delay = options == null ? void 0 : options.delay) != null ? _options$delay : 0) > 0) {
return (0, _dom.getConfig)().asyncWrapper(() => promise.then(() => state));
} else {
// prevent users from dealing with UnhandledPromiseRejectionWarning in sync call
promise.catch(console.error);
return state;
}
}
function keyboardImplementationWrapper(text, config = {}) {
const {
keyboardState: state = createKeyboardState(),
delay = 0,
document: doc = document,
autoModify = false,
keyboardMap = _keyMap.defaultKeyMap
} = config;
const options = {
delay,
document: doc,
autoModify,
keyboardMap
};
return {
promise: (0, _keyboardImplementation.keyboardImplementation)(text, options, state),
state,
releaseAllKeys: () => (0, _keyboardImplementation.releaseAllKeys)(options, state)
};
}
function createKeyboardState() {
return {
activeElement: null,
pressed: [],
carryChar: '',
modifiers: {
alt: false,
caps: false,
ctrl: false,
meta: false,
shift: false
}
};
}

View File

@@ -0,0 +1,5 @@
import { keyboardKey } from './types';
/**
* Mapping for a default US-104-QWERTY keyboard
*/
export declare const defaultKeyMap: keyboardKey[];

View File

@@ -0,0 +1,139 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.defaultKeyMap = void 0;
var _types = require("./types");
/**
* Mapping for a default US-104-QWERTY keyboard
*/
const defaultKeyMap = [// alphanumeric keys
...'0123456789'.split('').map(c => ({
code: `Digit${c}`,
key: c
})), ...')!@#$%^&*('.split('').map((c, i) => ({
code: `Digit${i}`,
key: c,
shiftKey: true
})), ...'abcdefghijklmnopqrstuvwxyz'.split('').map(c => ({
code: `Key${c.toUpperCase()}`,
key: c
})), ...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('').map(c => ({
code: `Key${c}`,
key: c,
shiftKey: true
})), // alphanumeric block - functional
{
code: 'Space',
key: ' '
}, {
code: 'AltLeft',
key: 'Alt',
location: _types.DOM_KEY_LOCATION.LEFT,
keyCode: 18
}, {
code: 'AltRight',
key: 'Alt',
location: _types.DOM_KEY_LOCATION.RIGHT,
keyCode: 18
}, {
code: 'ShiftLeft',
key: 'Shift',
location: _types.DOM_KEY_LOCATION.LEFT,
keyCode: 16
}, {
code: 'ShiftRight',
key: 'Shift',
location: _types.DOM_KEY_LOCATION.RIGHT,
keyCode: 16
}, {
code: 'ControlLeft',
key: 'Control',
location: _types.DOM_KEY_LOCATION.LEFT,
keyCode: 17
}, {
code: 'ControlRight',
key: 'Control',
location: _types.DOM_KEY_LOCATION.RIGHT,
keyCode: 17
}, {
code: 'MetaLeft',
key: 'Meta',
location: _types.DOM_KEY_LOCATION.LEFT,
keyCode: 93
}, {
code: 'MetaRight',
key: 'Meta',
location: _types.DOM_KEY_LOCATION.RIGHT,
keyCode: 93
}, {
code: 'OSLeft',
key: 'OS',
location: _types.DOM_KEY_LOCATION.LEFT,
keyCode: 91
}, {
code: 'OSRight',
key: 'OS',
location: _types.DOM_KEY_LOCATION.RIGHT,
keyCode: 91
}, {
code: 'CapsLock',
key: 'CapsLock',
keyCode: 20
}, {
code: 'Backspace',
key: 'Backspace',
keyCode: 8
}, {
code: 'Enter',
key: 'Enter',
keyCode: 13
}, // function
{
code: 'Escape',
key: 'Escape',
keyCode: 27
}, // arrows
{
code: 'ArrowUp',
key: 'ArrowUp',
keyCode: 38
}, {
code: 'ArrowDown',
key: 'ArrowDown',
keyCode: 40
}, {
code: 'ArrowLeft',
key: 'ArrowLeft',
keyCode: 37
}, {
code: 'ArrowRight',
key: 'ArrowRight',
keyCode: 39
}, // control pad
{
code: 'Home',
key: 'Home',
keyCode: 36
}, {
code: 'End',
key: 'End',
keyCode: 35
}, {
code: 'Delete',
key: 'Delete',
keyCode: 46
}, {
code: 'PageUp',
key: 'PageUp',
keyCode: 33
}, {
code: 'PageDown',
key: 'PageDown',
keyCode: 34
} // TODO: add mappings
];
exports.defaultKeyMap = defaultKeyMap;

View File

@@ -0,0 +1,3 @@
import { keyboardState, keyboardOptions } from './types';
export declare function keyboardImplementation(text: string, options: keyboardOptions, state: keyboardState): Promise<void>;
export declare function releaseAllKeys(options: keyboardOptions, state: keyboardState): void;

View File

@@ -0,0 +1,167 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.keyboardImplementation = keyboardImplementation;
exports.releaseAllKeys = releaseAllKeys;
var _dom = require("@testing-library/dom");
var _utils = require("../utils");
var _getNextKeyDef = require("./getNextKeyDef");
var plugins = _interopRequireWildcard(require("./plugins"));
var _getEventProps = require("./getEventProps");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
async function keyboardImplementation(text, options, state) {
var _state$repeatKey;
const {
document
} = options;
const getCurrentElement = () => getActive(document);
const {
keyDef,
consumedLength,
releasePrevious,
releaseSelf,
repeat
} = (_state$repeatKey = state.repeatKey) != null ? _state$repeatKey : (0, _getNextKeyDef.getNextKeyDef)(text, options);
const replace = applyPlugins(plugins.replaceBehavior, keyDef, getCurrentElement(), options, state);
if (!replace) {
const pressed = state.pressed.find(p => p.keyDef === keyDef); // Release the key automatically if it was pressed before.
// Do not release the key on iterations on `state.repeatKey`.
if (pressed && !state.repeatKey) {
keyup(keyDef, getCurrentElement, options, state, pressed.unpreventedDefault);
}
if (!releasePrevious) {
const unpreventedDefault = keydown(keyDef, getCurrentElement, options, state);
if (unpreventedDefault && hasKeyPress(keyDef, state)) {
keypress(keyDef, getCurrentElement, options, state);
} // Release the key only on the last iteration on `state.repeatKey`.
if (releaseSelf && repeat <= 1) {
keyup(keyDef, getCurrentElement, options, state, unpreventedDefault);
}
}
}
if (repeat > 1) {
state.repeatKey = {
// don't consume again on the next iteration
consumedLength: 0,
keyDef,
releasePrevious,
releaseSelf,
repeat: repeat - 1
};
} else {
delete state.repeatKey;
}
if (text.length > consumedLength || repeat > 1) {
if (options.delay > 0) {
await (0, _utils.wait)(options.delay);
}
return keyboardImplementation(text.slice(consumedLength), options, state);
}
return void undefined;
}
function getActive(document) {
var _getActiveElement;
return (_getActiveElement = (0, _utils.getActiveElement)(document)) != null ? _getActiveElement :
/* istanbul ignore next */
document.body;
}
function releaseAllKeys(options, state) {
const getCurrentElement = () => getActive(options.document);
for (const k of state.pressed) {
keyup(k.keyDef, getCurrentElement, options, state, k.unpreventedDefault);
}
}
function keydown(keyDef, getCurrentElement, options, state) {
const element = getCurrentElement(); // clear carried characters when focus is moved
if (element !== state.activeElement) {
state.carryValue = undefined;
state.carryChar = '';
}
state.activeElement = element;
applyPlugins(plugins.preKeydownBehavior, keyDef, element, options, state);
const unpreventedDefault = _dom.fireEvent.keyDown(element, (0, _getEventProps.getKeyEventProps)(keyDef, state));
state.pressed.push({
keyDef,
unpreventedDefault
});
if (unpreventedDefault) {
// all default behavior like keypress/submit etc is applied to the currentElement
applyPlugins(plugins.keydownBehavior, keyDef, getCurrentElement(), options, state);
}
return unpreventedDefault;
}
function keypress(keyDef, getCurrentElement, options, state) {
const element = getCurrentElement();
const unpreventedDefault = _dom.fireEvent.keyPress(element, (0, _getEventProps.getKeyEventProps)(keyDef, state));
if (unpreventedDefault) {
applyPlugins(plugins.keypressBehavior, keyDef, getCurrentElement(), options, state);
}
}
function keyup(keyDef, getCurrentElement, options, state, unprevented) {
const element = getCurrentElement();
applyPlugins(plugins.preKeyupBehavior, keyDef, element, options, state);
const unpreventedDefault = _dom.fireEvent.keyUp(element, (0, _getEventProps.getKeyEventProps)(keyDef, state));
if (unprevented && unpreventedDefault) {
applyPlugins(plugins.keyupBehavior, keyDef, getCurrentElement(), options, state);
}
state.pressed = state.pressed.filter(k => k.keyDef !== keyDef);
applyPlugins(plugins.postKeyupBehavior, keyDef, element, options, state);
}
function applyPlugins(pluginCollection, keyDef, element, options, state) {
const plugin = pluginCollection.find(p => p.matches(keyDef, element, options, state));
if (plugin) {
plugin.handle(keyDef, element, options, state);
}
return !!plugin;
}
function hasKeyPress(keyDef, state) {
var _keyDef$key;
return (((_keyDef$key = keyDef.key) == null ? void 0 : _keyDef$key.length) === 1 || keyDef.key === 'Enter') && !state.modifiers.ctrl && !state.modifiers.alt;
}

View File

@@ -0,0 +1,6 @@
/**
* This file should contain behavior for arrow keys as described here:
* https://w3c.github.io/uievents-code/#key-arrowpad-section
*/
import { behaviorPlugin } from '../types';
export declare const keydownBehavior: behaviorPlugin[];

View File

@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.keydownBehavior = void 0;
var _utils = require("../../utils");
/**
* This file should contain behavior for arrow keys as described here:
* https://w3c.github.io/uievents-code/#key-arrowpad-section
*/
const keydownBehavior = [{
// TODO: implement for contentEditable
matches: (keyDef, element) => (keyDef.key === 'ArrowLeft' || keyDef.key === 'ArrowRight') && (0, _utils.isElementType)(element, ['input', 'textarea']),
handle: (keyDef, element) => {
var _ref;
const {
selectionStart,
selectionEnd
} = (0, _utils.getSelectionRange)(element);
const direction = keyDef.key === 'ArrowLeft' ? -1 : 1;
const newPos = (_ref = selectionStart === selectionEnd ? (selectionStart != null ? selectionStart :
/* istanbul ignore next */
0) + direction : direction < 0 ? selectionStart : selectionEnd) != null ? _ref :
/* istanbul ignore next */
0;
(0, _utils.setSelectionRange)(element, newPos, newPos);
}
}];
exports.keydownBehavior = keydownBehavior;

View File

@@ -0,0 +1,5 @@
/**
* This file should cover the behavior for keys that produce character input
*/
import { behaviorPlugin } from '../types';
export declare const keypressBehavior: behaviorPlugin[];

View File

@@ -0,0 +1,195 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.keypressBehavior = void 0;
var _dom = require("@testing-library/dom");
var _shared = require("../shared");
var _utils = require("../../utils");
/**
* This file should cover the behavior for keys that produce character input
*/
const keypressBehavior = [{
matches: (keyDef, element) => {
var _keyDef$key;
return ((_keyDef$key = keyDef.key) == null ? void 0 : _keyDef$key.length) === 1 && (0, _utils.isElementType)(element, 'input', {
type: 'time',
readOnly: false
});
},
handle: (keyDef, element, options, state) => {
var _state$carryValue;
let newEntry = keyDef.key;
const textToBeTyped = ((_state$carryValue = state.carryValue) != null ? _state$carryValue : '') + newEntry;
const timeNewEntry = (0, _utils.buildTimeValue)(textToBeTyped);
if ((0, _utils.isValidInputTimeValue)(element, timeNewEntry)) {
newEntry = timeNewEntry;
}
const {
newValue,
newSelectionStart
} = (0, _utils.calculateNewValue)(newEntry, element);
const prevValue = (0, _utils.getValue)(element); // this check was provided by fireInputEventIfNeeded
// TODO: verify if it is even needed by this handler
if (prevValue !== newValue) {
(0, _shared.fireInputEvent)(element, {
newValue,
newSelectionStart,
eventOverrides: {
data: keyDef.key,
inputType: 'insertText'
}
});
}
(0, _shared.fireChangeForInputTimeIfValid)(element, prevValue, timeNewEntry);
state.carryValue = textToBeTyped;
}
}, {
matches: (keyDef, element) => {
var _keyDef$key2;
return ((_keyDef$key2 = keyDef.key) == null ? void 0 : _keyDef$key2.length) === 1 && (0, _utils.isElementType)(element, 'input', {
type: 'date',
readOnly: false
});
},
handle: (keyDef, element, options, state) => {
var _state$carryValue2;
let newEntry = keyDef.key;
const textToBeTyped = ((_state$carryValue2 = state.carryValue) != null ? _state$carryValue2 : '') + newEntry;
const isValidToBeTyped = (0, _utils.isValidDateValue)(element, textToBeTyped);
if (isValidToBeTyped) {
newEntry = textToBeTyped;
}
const {
newValue,
newSelectionStart
} = (0, _utils.calculateNewValue)(newEntry, element);
const prevValue = (0, _utils.getValue)(element); // this check was provided by fireInputEventIfNeeded
// TODO: verify if it is even needed by this handler
if (prevValue !== newValue) {
(0, _shared.fireInputEvent)(element, {
newValue,
newSelectionStart,
eventOverrides: {
data: keyDef.key,
inputType: 'insertText'
}
});
}
if (isValidToBeTyped) {
_dom.fireEvent.change(element, {
target: {
value: textToBeTyped
}
});
}
state.carryValue = textToBeTyped;
}
}, {
matches: (keyDef, element) => {
var _keyDef$key3;
return ((_keyDef$key3 = keyDef.key) == null ? void 0 : _keyDef$key3.length) === 1 && (0, _utils.isElementType)(element, 'input', {
type: 'number',
readOnly: false
});
},
handle: (keyDef, element, options, state) => {
var _ref, _state$carryValue3, _newValue$match, _newValue$match2;
if (!/[\d.\-e]/.test(keyDef.key)) {
return;
}
const oldValue = (_ref = (_state$carryValue3 = state.carryValue) != null ? _state$carryValue3 : (0, _utils.getValue)(element)) != null ? _ref :
/* istanbul ignore next */
'';
const {
newValue,
newSelectionStart
} = (0, _utils.calculateNewValue)(keyDef.key, element, oldValue); // the browser allows some invalid input but not others
// it allows up to two '-' at any place before any 'e' or one directly following 'e'
// it allows one '.' at any place before e
const valueParts = newValue.split('e', 2);
if (Number((_newValue$match = newValue.match(/-/g)) == null ? void 0 : _newValue$match.length) > 2 || Number((_newValue$match2 = newValue.match(/\./g)) == null ? void 0 : _newValue$match2.length) > 1 || valueParts[1] && !/^-?\d*$/.test(valueParts[1])) {
return;
}
(0, _shared.fireInputEvent)(element, {
newValue,
newSelectionStart,
eventOverrides: {
data: keyDef.key,
inputType: 'insertText'
}
});
const appliedValue = (0, _utils.getValue)(element);
if (appliedValue === newValue) {
state.carryValue = undefined;
} else {
state.carryValue = newValue;
}
}
}, {
matches: (keyDef, element) => {
var _keyDef$key4;
return ((_keyDef$key4 = keyDef.key) == null ? void 0 : _keyDef$key4.length) === 1 && ((0, _utils.isElementType)(element, ['input', 'textarea'], {
readOnly: false
}) && !(0, _utils.isClickableInput)(element) || (0, _utils.isContentEditable)(element)) && (0, _utils.getSpaceUntilMaxLength)(element) !== 0;
},
handle: (keyDef, element) => {
const {
newValue,
newSelectionStart
} = (0, _utils.calculateNewValue)(keyDef.key, element);
(0, _shared.fireInputEvent)(element, {
newValue,
newSelectionStart,
eventOverrides: {
data: keyDef.key,
inputType: 'insertText'
}
});
}
}, {
matches: (keyDef, element) => keyDef.key === 'Enter' && ((0, _utils.isElementType)(element, 'textarea', {
readOnly: false
}) || (0, _utils.isContentEditable)(element)) && (0, _utils.getSpaceUntilMaxLength)(element) !== 0,
handle: (keyDef, element, options, state) => {
const {
newValue,
newSelectionStart
} = (0, _utils.calculateNewValue)('\n', element);
const inputType = (0, _utils.isContentEditable)(element) && !state.modifiers.shift ? 'insertParagraph' : 'insertLineBreak';
(0, _shared.fireInputEvent)(element, {
newValue,
newSelectionStart,
eventOverrides: {
inputType
}
});
}
}];
exports.keypressBehavior = keypressBehavior;

View File

@@ -0,0 +1,6 @@
/**
* This file should contain behavior for arrow keys as described here:
* https://w3c.github.io/uievents-code/#key-controlpad-section
*/
import { behaviorPlugin } from '../types';
export declare const keydownBehavior: behaviorPlugin[];

View File

@@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.keydownBehavior = void 0;
var _utils = require("../../utils");
var _shared = require("../shared");
/**
* This file should contain behavior for arrow keys as described here:
* https://w3c.github.io/uievents-code/#key-controlpad-section
*/
const keydownBehavior = [{
matches: (keyDef, element) => (keyDef.key === 'Home' || keyDef.key === 'End') && ((0, _utils.isElementType)(element, ['input', 'textarea']) || (0, _utils.isContentEditable)(element)),
handle: (keyDef, element) => {
// This could probably been improved by collapsing a selection range
if (keyDef.key === 'Home') {
(0, _utils.setSelectionRange)(element, 0, 0);
} else {
var _getValue$length, _getValue;
const newPos = (_getValue$length = (_getValue = (0, _utils.getValue)(element)) == null ? void 0 : _getValue.length) != null ? _getValue$length :
/* istanbul ignore next */
0;
(0, _utils.setSelectionRange)(element, newPos, newPos);
}
}
}, {
matches: (keyDef, element) => (keyDef.key === 'PageUp' || keyDef.key === 'PageDown') && (0, _utils.isElementType)(element, ['input']),
handle: (keyDef, element) => {
// This could probably been improved by collapsing a selection range
if (keyDef.key === 'PageUp') {
(0, _utils.setSelectionRange)(element, 0, 0);
} else {
var _getValue$length2, _getValue2;
const newPos = (_getValue$length2 = (_getValue2 = (0, _utils.getValue)(element)) == null ? void 0 : _getValue2.length) != null ? _getValue$length2 :
/* istanbul ignore next */
0;
(0, _utils.setSelectionRange)(element, newPos, newPos);
}
}
}, {
matches: (keyDef, element) => keyDef.key === 'Delete' && (0, _utils.isEditable)(element) && !(0, _utils.isCursorAtEnd)(element),
handle: (keDef, element, options, state) => {
const {
newValue,
newSelectionStart
} = (0, _utils.calculateNewValue)('', element, state.carryValue, undefined, 'forward');
(0, _shared.fireInputEvent)(element, {
newValue,
newSelectionStart,
eventOverrides: {
inputType: 'deleteContentForward'
}
});
(0, _shared.carryValue)(element, state, newValue);
}
}];
exports.keydownBehavior = keydownBehavior;

View File

@@ -0,0 +1,11 @@
/**
* This file should contain behavior for functional keys as described here:
* https://w3c.github.io/uievents-code/#key-alphanumeric-functional
*/
import { behaviorPlugin } from '../types';
export declare const preKeydownBehavior: behaviorPlugin[];
export declare const keydownBehavior: behaviorPlugin[];
export declare const keypressBehavior: behaviorPlugin[];
export declare const preKeyupBehavior: behaviorPlugin[];
export declare const keyupBehavior: behaviorPlugin[];
export declare const postKeyupBehavior: behaviorPlugin[];

View File

@@ -0,0 +1,131 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.preKeyupBehavior = exports.preKeydownBehavior = exports.postKeyupBehavior = exports.keyupBehavior = exports.keypressBehavior = exports.keydownBehavior = void 0;
var _dom = require("@testing-library/dom");
var _utils = require("../../utils");
var _getEventProps = require("../getEventProps");
var _shared = require("../shared");
/**
* This file should contain behavior for functional keys as described here:
* https://w3c.github.io/uievents-code/#key-alphanumeric-functional
*/
const modifierKeys = {
Alt: 'alt',
Control: 'ctrl',
Shift: 'shift',
Meta: 'meta'
};
const preKeydownBehavior = [// modifierKeys switch on the modifier BEFORE the keydown event
...Object.entries(modifierKeys).map(([key, modKey]) => ({
matches: keyDef => keyDef.key === key,
handle: (keyDef, element, options, state) => {
state.modifiers[modKey] = true;
}
})), // AltGraph produces an extra keydown for Control
// The modifier does not change
{
matches: keyDef => keyDef.key === 'AltGraph',
handle: (keyDef, element, options, state) => {
var _options$keyboardMap$;
const ctrlKeyDef = (_options$keyboardMap$ = options.keyboardMap.find(k => k.key === 'Control')) != null ? _options$keyboardMap$ :
/* istanbul ignore next */
{
key: 'Control',
code: 'Control'
};
_dom.fireEvent.keyDown(element, (0, _getEventProps.getKeyEventProps)(ctrlKeyDef, state));
}
}];
exports.preKeydownBehavior = preKeydownBehavior;
const keydownBehavior = [{
matches: keyDef => keyDef.key === 'CapsLock',
handle: (keyDef, element, options, state) => {
state.modifiers.caps = !state.modifiers.caps;
}
}, {
matches: (keyDef, element) => keyDef.key === 'Backspace' && (0, _utils.isEditable)(element) && !(0, _utils.isCursorAtStart)(element),
handle: (keyDef, element, options, state) => {
const {
newValue,
newSelectionStart
} = (0, _utils.calculateNewValue)('', element, state.carryValue, undefined, 'backward');
(0, _shared.fireInputEvent)(element, {
newValue,
newSelectionStart,
eventOverrides: {
inputType: 'deleteContentBackward'
}
});
(0, _shared.carryValue)(element, state, newValue);
}
}];
exports.keydownBehavior = keydownBehavior;
const keypressBehavior = [{
matches: (keyDef, element) => keyDef.key === 'Enter' && (0, _utils.isElementType)(element, 'input') && ['checkbox', 'radio'].includes(element.type),
handle: (keyDef, element) => {
const form = element.form;
if ((0, _utils.hasFormSubmit)(form)) {
_dom.fireEvent.submit(form);
}
}
}, {
matches: (keyDef, element) => keyDef.key === 'Enter' && ((0, _utils.isClickableInput)(element) || // Links with href defined should handle Enter the same as a click
(0, _utils.isElementType)(element, 'a') && Boolean(element.href)),
handle: (keyDef, element, options, state) => {
_dom.fireEvent.click(element, (0, _getEventProps.getMouseEventProps)(state));
}
}, {
matches: (keyDef, element) => keyDef.key === 'Enter' && (0, _utils.isElementType)(element, 'input'),
handle: (keyDef, element) => {
const form = element.form;
if (form && (form.querySelectorAll('input').length === 1 || (0, _utils.hasFormSubmit)(form))) {
_dom.fireEvent.submit(form);
}
}
}];
exports.keypressBehavior = keypressBehavior;
const preKeyupBehavior = [// modifierKeys switch off the modifier BEFORE the keyup event
...Object.entries(modifierKeys).map(([key, modKey]) => ({
matches: keyDef => keyDef.key === key,
handle: (keyDef, element, options, state) => {
state.modifiers[modKey] = false;
}
}))];
exports.preKeyupBehavior = preKeyupBehavior;
const keyupBehavior = [{
matches: (keyDef, element) => keyDef.key === ' ' && (0, _utils.isClickableInput)(element),
handle: (keyDef, element, options, state) => {
_dom.fireEvent.click(element, (0, _getEventProps.getMouseEventProps)(state));
}
}];
exports.keyupBehavior = keyupBehavior;
const postKeyupBehavior = [// AltGraph produces an extra keyup for Control
// The modifier does not change
{
matches: keyDef => keyDef.key === 'AltGraph',
handle: (keyDef, element, options, state) => {
var _options$keyboardMap$2;
const ctrlKeyDef = (_options$keyboardMap$2 = options.keyboardMap.find(k => k.key === 'Control')) != null ? _options$keyboardMap$2 :
/* istanbul ignore next */
{
key: 'Control',
code: 'Control'
};
_dom.fireEvent.keyUp(element, (0, _getEventProps.getKeyEventProps)(ctrlKeyDef, state));
}
}];
exports.postKeyupBehavior = postKeyupBehavior;

View File

@@ -0,0 +1,8 @@
import { behaviorPlugin } from '../types';
export declare const replaceBehavior: behaviorPlugin[];
export declare const preKeydownBehavior: behaviorPlugin[];
export declare const keydownBehavior: behaviorPlugin[];
export declare const keypressBehavior: behaviorPlugin[];
export declare const preKeyupBehavior: behaviorPlugin[];
export declare const keyupBehavior: behaviorPlugin[];
export declare const postKeyupBehavior: behaviorPlugin[];

View File

@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.replaceBehavior = exports.preKeyupBehavior = exports.preKeydownBehavior = exports.postKeyupBehavior = exports.keyupBehavior = exports.keypressBehavior = exports.keydownBehavior = void 0;
var _utils = require("../../utils");
var arrowKeys = _interopRequireWildcard(require("./arrow"));
var controlKeys = _interopRequireWildcard(require("./control"));
var characterKeys = _interopRequireWildcard(require("./character"));
var functionalKeys = _interopRequireWildcard(require("./functional"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const replaceBehavior = [{
matches: (keyDef, element) => keyDef.key === 'selectall' && (0, _utils.isElementType)(element, ['input', 'textarea']),
handle: (keyDef, element, options, state) => {
var _state$carryValue;
(0, _utils.setSelectionRange)(element, 0, ((_state$carryValue = state.carryValue) != null ? _state$carryValue : element.value).length);
}
}];
exports.replaceBehavior = replaceBehavior;
const preKeydownBehavior = [...functionalKeys.preKeydownBehavior];
exports.preKeydownBehavior = preKeydownBehavior;
const keydownBehavior = [...arrowKeys.keydownBehavior, ...controlKeys.keydownBehavior, ...functionalKeys.keydownBehavior];
exports.keydownBehavior = keydownBehavior;
const keypressBehavior = [...functionalKeys.keypressBehavior, ...characterKeys.keypressBehavior];
exports.keypressBehavior = keypressBehavior;
const preKeyupBehavior = [...functionalKeys.preKeyupBehavior];
exports.preKeyupBehavior = preKeyupBehavior;
const keyupBehavior = [...functionalKeys.keyupBehavior];
exports.keyupBehavior = keyupBehavior;
const postKeyupBehavior = [...functionalKeys.postKeyupBehavior];
exports.postKeyupBehavior = postKeyupBehavior;

View File

@@ -0,0 +1,2 @@
import { keyboardState } from '../types';
export declare function carryValue(element: Element, state: keyboardState, newValue: string): void;

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.carryValue = carryValue;
var _utils = require("../../utils");
function carryValue(element, state, newValue) {
const value = (0, _utils.getValue)(element);
state.carryValue = value !== newValue && value === '' && (0, _utils.hasUnreliableEmptyValue)(element) ? newValue : undefined;
}

View File

@@ -0,0 +1,3 @@
export declare function fireChangeForInputTimeIfValid(el: HTMLInputElement & {
type: 'time';
}, prevValue: unknown, timeNewEntry: string): void;

View File

@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.fireChangeForInputTimeIfValid = fireChangeForInputTimeIfValid;
var _dom = require("@testing-library/dom");
var _utils = require("../../utils");
function fireChangeForInputTimeIfValid(el, prevValue, timeNewEntry) {
if ((0, _utils.isValidInputTimeValue)(el, timeNewEntry) && prevValue !== timeNewEntry) {
_dom.fireEvent.change(el, {
target: {
value: timeNewEntry
}
});
}
}

View File

@@ -0,0 +1,17 @@
import { fireEvent } from '@testing-library/dom';
export declare function fireInputEvent(element: HTMLElement, { newValue, newSelectionStart, eventOverrides, }: {
newValue: string;
newSelectionStart: number;
eventOverrides: Partial<Parameters<typeof fireEvent>[1]> & {
[k: string]: unknown;
};
}): void;
declare const initial: unique symbol;
declare const onBlur: unique symbol;
declare global {
interface Element {
[initial]?: string;
[onBlur]?: EventListener;
}
}
export {};

View File

@@ -0,0 +1,110 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.fireInputEvent = fireInputEvent;
var _dom = require("@testing-library/dom");
var _utils = require("../../utils");
function fireInputEvent(element, {
newValue,
newSelectionStart,
eventOverrides
}) {
// apply the changes before firing the input event, so that input handlers can access the altered dom and selection
if ((0, _utils.isContentEditable)(element)) {
applyNative(element, 'textContent', newValue);
} else
/* istanbul ignore else */
if ((0, _utils.isElementType)(element, ['input', 'textarea'])) {
applyNative(element, 'value', newValue);
} else {
// TODO: properly type guard
throw new Error('Invalid Element');
}
setSelectionRangeAfterInput(element, newSelectionStart);
_dom.fireEvent.input(element, { ...eventOverrides
});
setSelectionRangeAfterInputHandler(element, newValue, newSelectionStart);
}
function setSelectionRangeAfterInput(element, newSelectionStart) {
(0, _utils.setSelectionRange)(element, newSelectionStart, newSelectionStart);
}
function setSelectionRangeAfterInputHandler(element, newValue, newSelectionStart) {
const value = (0, _utils.getValue)(element); // don't apply this workaround on elements that don't necessarily report the visible value - e.g. number
// TODO: this could probably be only applied when there is keyboardState.carryValue
const isUnreliableValue = value === '' && (0, _utils.hasUnreliableEmptyValue)(element);
if (!isUnreliableValue && value === newValue) {
const {
selectionStart
} = (0, _utils.getSelectionRange)(element);
if (selectionStart === value.length) {
// The value was changed as expected, but the cursor was moved to the end
// TODO: this could probably be only applied when we work around a framework setter on the element in applyNative
(0, _utils.setSelectionRange)(element, newSelectionStart, newSelectionStart);
}
}
}
const initial = Symbol('initial input value/textContent');
const onBlur = Symbol('onBlur');
/**
* React tracks the changes on element properties.
* This workaround tries to alter the DOM element without React noticing,
* so that it later picks up the change.
*
* @see https://github.com/facebook/react/blob/148f8e497c7d37a3c7ab99f01dec2692427272b1/packages/react-dom/src/client/inputValueTracking.js#L51-L104
*/
function applyNative(element, propName, propValue) {
const descriptor = Object.getOwnPropertyDescriptor(element, propName);
const nativeDescriptor = Object.getOwnPropertyDescriptor(element.constructor.prototype, propName);
if (descriptor && nativeDescriptor) {
Object.defineProperty(element, propName, nativeDescriptor);
} // Keep track of the initial value to determine if a change event should be dispatched.
// CONSTRAINT: We can not determine what happened between focus event and our first API call.
if (element[initial] === undefined) {
element[initial] = String(element[propName]);
}
element[propName] = propValue; // Add an event listener for the blur event to the capture phase on the window.
// CONSTRAINT: Currently there is no cross-platform solution to unshift the event handler stack.
// Our change event might occur after other event handlers on the blur event have been processed.
if (!element[onBlur]) {
var _element$ownerDocumen;
(_element$ownerDocumen = element.ownerDocument.defaultView) == null ? void 0 : _element$ownerDocumen.addEventListener('blur', element[onBlur] = () => {
const initV = element[initial]; // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete element[onBlur]; // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete element[initial];
if (String(element[propName]) !== initV) {
_dom.fireEvent.change(element);
}
}, {
capture: true,
once: true
});
}
if (descriptor) {
Object.defineProperty(element, propName, descriptor);
}
}

View File

@@ -0,0 +1,3 @@
export * from './carryValue';
export * from './fireChangeForInputTimeIfValid';
export * from './fireInputEvent';

View File

@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _carryValue = require("./carryValue");
Object.keys(_carryValue).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _carryValue[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _carryValue[key];
}
});
});
var _fireChangeForInputTimeIfValid = require("./fireChangeForInputTimeIfValid");
Object.keys(_fireChangeForInputTimeIfValid).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _fireChangeForInputTimeIfValid[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _fireChangeForInputTimeIfValid[key];
}
});
});
var _fireInputEvent = require("./fireInputEvent");
Object.keys(_fireInputEvent).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _fireInputEvent[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _fireInputEvent[key];
}
});
});

View File

@@ -0,0 +1,22 @@
/**
* @deprecated This list of strings with special meaning is no longer necessary
* as we've introduced a standardized way to describe any keystroke for `userEvent`.
* @see https://testing-library.com/docs/ecosystem-user-event#keyboardtext-options
*/
export declare const specialCharMap: {
readonly arrowLeft: "{arrowleft}";
readonly arrowRight: "{arrowright}";
readonly arrowDown: "{arrowdown}";
readonly arrowUp: "{arrowup}";
readonly enter: "{enter}";
readonly escape: "{esc}";
readonly delete: "{del}";
readonly backspace: "{backspace}";
readonly home: "{home}";
readonly end: "{end}";
readonly selectAll: "{selectall}";
readonly space: "{space}";
readonly whitespace: " ";
readonly pageUp: "{pageUp}";
readonly pageDown: "{pageDown}";
};

View File

@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.specialCharMap = void 0;
/**
* @deprecated This list of strings with special meaning is no longer necessary
* as we've introduced a standardized way to describe any keystroke for `userEvent`.
* @see https://testing-library.com/docs/ecosystem-user-event#keyboardtext-options
*/
const specialCharMap = {
arrowLeft: '{arrowleft}',
arrowRight: '{arrowright}',
arrowDown: '{arrowdown}',
arrowUp: '{arrowup}',
enter: '{enter}',
escape: '{esc}',
delete: '{del}',
backspace: '{backspace}',
home: '{home}',
end: '{end}',
selectAll: '{selectall}',
space: '{space}',
whitespace: ' ',
pageUp: '{pageUp}',
pageDown: '{pageDown}'
};
exports.specialCharMap = specialCharMap;

View File

@@ -0,0 +1,77 @@
import { getNextKeyDef } from './getNextKeyDef';
/**
* @internal Do not create/alter this by yourself as this type might be subject to changes.
*/
export declare type keyboardState = {
/**
All keys that have been pressed and not been lifted up yet.
*/
pressed: {
keyDef: keyboardKey;
unpreventedDefault: boolean;
}[];
/**
Active modifiers
*/
modifiers: {
alt: boolean;
caps: boolean;
ctrl: boolean;
meta: boolean;
shift: boolean;
};
/**
The element the keyboard input is performed on.
Some behavior might differ if the activeElement changes between corresponding keyboard events.
*/
activeElement: Element | null;
/**
For HTMLInputElements type='number':
If the last input char is '.', '-' or 'e',
the IDL value attribute does not reflect the input value.
*/
carryValue?: string;
/**
Carry over characters to following key handlers.
E.g. ^1
*/
carryChar: string;
/**
Repeat keydown and keypress event
*/
repeatKey?: ReturnType<typeof getNextKeyDef>;
};
export declare type keyboardOptions = {
/** Document in which to perform the events */
document: Document;
/** Delay between keystrokes */
delay: number;
/** Add modifiers for given keys - not implemented yet */
autoModify: boolean;
/** Keyboard layout to use */
keyboardMap: keyboardKey[];
};
export declare enum DOM_KEY_LOCATION {
STANDARD = 0,
LEFT = 1,
RIGHT = 2,
NUMPAD = 3
}
export interface keyboardKey {
/** Physical location on a keyboard */
code?: string;
/** Character or functional key descriptor */
key?: string;
/** Location on the keyboard for keys with multiple representation */
location?: DOM_KEY_LOCATION;
/** keyCode for legacy support */
keyCode?: number;
/** Does the character in `key` require/imply AltRight to be pressed? */
altGr?: boolean;
/** Does the character in `key` require/imply a shiftKey to be pressed? */
shift?: boolean;
}
export interface behaviorPlugin {
matches: (keyDef: keyboardKey, element: Element, options: keyboardOptions, state: keyboardState) => boolean;
handle: (keyDef: keyboardKey, element: Element, options: keyboardOptions, state: keyboardState) => void;
}

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DOM_KEY_LOCATION = void 0;
/**
* @internal Do not create/alter this by yourself as this type might be subject to changes.
*/
let DOM_KEY_LOCATION;
exports.DOM_KEY_LOCATION = DOM_KEY_LOCATION;
(function (DOM_KEY_LOCATION) {
DOM_KEY_LOCATION[DOM_KEY_LOCATION["STANDARD"] = 0] = "STANDARD";
DOM_KEY_LOCATION[DOM_KEY_LOCATION["LEFT"] = 1] = "LEFT";
DOM_KEY_LOCATION[DOM_KEY_LOCATION["RIGHT"] = 2] = "RIGHT";
DOM_KEY_LOCATION[DOM_KEY_LOCATION["NUMPAD"] = 3] = "NUMPAD";
})(DOM_KEY_LOCATION || (exports.DOM_KEY_LOCATION = DOM_KEY_LOCATION = {}));