mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-08-15 18:45:06 +00:00
This is copied from facebook/react with various fixes applied (which I'll push upstream at a later date). Necessary for testing the Responder Event System rewrite.
439 lines
9.1 KiB
JavaScript
439 lines
9.1 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
import createEvent from './createEvent';
|
|
import { buttonType, buttonsType, defaultPointerSize, defaultBrowserChromeSize } from './constants';
|
|
|
|
/**
|
|
* Native event object mocks for higher-level events.
|
|
*
|
|
* 1. Each event type defines the exact object that it accepts. This ensures
|
|
* that no arbitrary properties can be assigned to events, and the properties
|
|
* that don't exist on specific event types (e.g., 'pointerType') are not added
|
|
* to the respective native event.
|
|
*
|
|
* 2. Properties that cannot be relied on due to inconsistent browser support (e.g., 'x' and 'y') are not
|
|
* added to the native event. Others that shouldn't be arbitrarily customized (e.g., 'screenX')
|
|
* are automatically inferred from associated values.
|
|
*
|
|
* 3. PointerEvent and TouchEvent fields are normalized (e.g., 'rotationAngle' -> 'twist')
|
|
*/
|
|
|
|
function emptyFunction() {}
|
|
|
|
function createGetModifierState(keyArg, data) {
|
|
if (keyArg === 'Alt') {
|
|
return data.altKey || false;
|
|
}
|
|
if (keyArg === 'Control') {
|
|
return data.ctrlKey || false;
|
|
}
|
|
if (keyArg === 'Meta') {
|
|
return data.metaKey || false;
|
|
}
|
|
if (keyArg === 'Shift') {
|
|
return data.shiftKey || false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* KeyboardEvent
|
|
*/
|
|
|
|
function createKeyboardEvent(
|
|
type,
|
|
{
|
|
altKey = false,
|
|
ctrlKey = false,
|
|
isComposing = false,
|
|
key = '',
|
|
metaKey = false,
|
|
preventDefault = emptyFunction,
|
|
shiftKey = false
|
|
} = {}
|
|
) {
|
|
const modifierState = { altKey, ctrlKey, metaKey, shiftKey };
|
|
|
|
const eventPayload = {
|
|
altKey,
|
|
ctrlKey,
|
|
getModifierState(keyArg) {
|
|
return createGetModifierState(keyArg, modifierState);
|
|
},
|
|
isComposing,
|
|
key,
|
|
metaKey,
|
|
preventDefault,
|
|
shiftKey
|
|
};
|
|
|
|
if (isComposing) {
|
|
eventPayload.keyCode = 229;
|
|
}
|
|
|
|
return createEvent(type, eventPayload);
|
|
}
|
|
|
|
/**
|
|
* MouseEvent
|
|
*/
|
|
|
|
function createMouseEvent(
|
|
type,
|
|
{
|
|
altKey = false,
|
|
button = buttonType.none,
|
|
buttons = buttonsType.none,
|
|
ctrlKey = false,
|
|
detail = 1,
|
|
metaKey = false,
|
|
movementX = 0,
|
|
movementY = 0,
|
|
offsetX = 0,
|
|
offsetY = 0,
|
|
pageX,
|
|
pageY,
|
|
preventDefault = emptyFunction,
|
|
screenX,
|
|
screenY,
|
|
shiftKey = false,
|
|
timeStamp,
|
|
x = 0,
|
|
y = 0
|
|
} = {}
|
|
) {
|
|
const modifierState = { altKey, ctrlKey, metaKey, shiftKey };
|
|
|
|
return createEvent(type, {
|
|
altKey,
|
|
button,
|
|
buttons,
|
|
clientX: x,
|
|
clientY: y,
|
|
ctrlKey,
|
|
detail,
|
|
getModifierState(keyArg) {
|
|
return createGetModifierState(keyArg, modifierState);
|
|
},
|
|
metaKey,
|
|
movementX,
|
|
movementY,
|
|
offsetX,
|
|
offsetY,
|
|
pageX: pageX || x,
|
|
pageY: pageY || y,
|
|
preventDefault,
|
|
screenX: screenX === 0 ? screenX : x,
|
|
screenY: screenY === 0 ? screenY : y + defaultBrowserChromeSize,
|
|
shiftKey,
|
|
timeStamp
|
|
});
|
|
}
|
|
|
|
/**
|
|
* PointerEvent
|
|
*/
|
|
|
|
function createPointerEvent(
|
|
type,
|
|
{
|
|
altKey = false,
|
|
button = buttonType.none,
|
|
buttons = buttonsType.none,
|
|
ctrlKey = false,
|
|
detail = 1,
|
|
height,
|
|
metaKey = false,
|
|
movementX = 0,
|
|
movementY = 0,
|
|
offsetX = 0,
|
|
offsetY = 0,
|
|
pageX,
|
|
pageY,
|
|
pointerId,
|
|
pressure = 0,
|
|
preventDefault = emptyFunction,
|
|
pointerType = 'mouse',
|
|
screenX,
|
|
screenY,
|
|
shiftKey = false,
|
|
tangentialPressure = 0,
|
|
tiltX = 0,
|
|
tiltY = 0,
|
|
timeStamp,
|
|
twist = 0,
|
|
width,
|
|
x = 0,
|
|
y = 0
|
|
} = {}
|
|
) {
|
|
const modifierState = { altKey, ctrlKey, metaKey, shiftKey };
|
|
const isMouse = pointerType === 'mouse';
|
|
|
|
return createEvent(type, {
|
|
altKey,
|
|
button,
|
|
buttons,
|
|
clientX: x,
|
|
clientY: y,
|
|
ctrlKey,
|
|
detail,
|
|
getModifierState(keyArg) {
|
|
return createGetModifierState(keyArg, modifierState);
|
|
},
|
|
height: isMouse ? 1 : height != null ? height : defaultPointerSize,
|
|
metaKey,
|
|
movementX,
|
|
movementY,
|
|
offsetX,
|
|
offsetY,
|
|
pageX: pageX || x,
|
|
pageY: pageY || y,
|
|
pointerId,
|
|
pointerType,
|
|
pressure,
|
|
preventDefault,
|
|
releasePointerCapture: emptyFunction,
|
|
screenX: screenX === 0 ? screenX : x,
|
|
screenY: screenY === 0 ? screenY : y + defaultBrowserChromeSize,
|
|
setPointerCapture: emptyFunction,
|
|
shiftKey,
|
|
tangentialPressure,
|
|
tiltX,
|
|
tiltY,
|
|
timeStamp,
|
|
twist,
|
|
width: isMouse ? 1 : width != null ? width : defaultPointerSize
|
|
});
|
|
}
|
|
|
|
/**
|
|
* TouchEvent
|
|
*/
|
|
|
|
function createTouchEvent(type, payload) {
|
|
return createEvent(type, {
|
|
preventDefault: emptyFunction,
|
|
...payload,
|
|
detail: 0,
|
|
sourceCapabilities: {
|
|
firesTouchEvents: true
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* DOM events
|
|
*/
|
|
|
|
export function blur({ relatedTarget } = {}) {
|
|
return createEvent('blur', { relatedTarget });
|
|
}
|
|
|
|
export function click(payload) {
|
|
return createMouseEvent('click', {
|
|
button: buttonType.primary,
|
|
...payload
|
|
});
|
|
}
|
|
|
|
export function contextmenu(payload) {
|
|
return createMouseEvent('contextmenu', {
|
|
...payload,
|
|
detail: 0
|
|
});
|
|
}
|
|
|
|
export function dragstart(payload) {
|
|
return createMouseEvent('dragstart', {
|
|
...payload,
|
|
detail: 0
|
|
});
|
|
}
|
|
|
|
export function focus({ relatedTarget } = {}) {
|
|
return createEvent('focus', { relatedTarget });
|
|
}
|
|
|
|
export function focusin({ relatedTarget } = {}) {
|
|
return createEvent('focusin', { relatedTarget });
|
|
}
|
|
|
|
export function focusout({ relatedTarget } = {}) {
|
|
return createEvent('focusout', { relatedTarget });
|
|
}
|
|
|
|
export function gotpointercapture(payload) {
|
|
return createPointerEvent('gotpointercapture', payload);
|
|
}
|
|
|
|
export function keydown(payload) {
|
|
return createKeyboardEvent('keydown', payload);
|
|
}
|
|
|
|
export function keyup(payload) {
|
|
return createKeyboardEvent('keyup', payload);
|
|
}
|
|
|
|
export function lostpointercapture(payload) {
|
|
return createPointerEvent('lostpointercapture', payload);
|
|
}
|
|
|
|
export function mousedown(payload) {
|
|
// The value of 'button' and 'buttons' for 'mousedown' must not be none.
|
|
const button =
|
|
payload != null && payload.button !== buttonType.none ? payload.button : buttonType.primary;
|
|
const buttons =
|
|
payload != null && payload.buttons !== buttonsType.none ? payload.buttons : buttonsType.primary;
|
|
|
|
return createMouseEvent('mousedown', {
|
|
...payload,
|
|
button,
|
|
buttons
|
|
});
|
|
}
|
|
|
|
export function mouseenter(payload) {
|
|
return createMouseEvent('mouseenter', payload);
|
|
}
|
|
|
|
export function mouseleave(payload) {
|
|
return createMouseEvent('mouseleave', payload);
|
|
}
|
|
|
|
export function mousemove(payload) {
|
|
return createMouseEvent('mousemove', {
|
|
// 0 is also the uninitialized value (i.e., don't assume it means primary button down)
|
|
button: 0,
|
|
buttons: 0,
|
|
...payload
|
|
});
|
|
}
|
|
|
|
export function mouseout(payload) {
|
|
return createMouseEvent('mouseout', payload);
|
|
}
|
|
|
|
export function mouseover(payload) {
|
|
return createMouseEvent('mouseover', payload);
|
|
}
|
|
|
|
export function mouseup(payload) {
|
|
return createMouseEvent('mouseup', {
|
|
button: buttonType.primary,
|
|
...payload,
|
|
buttons: buttonsType.none
|
|
});
|
|
}
|
|
export function pointercancel(payload) {
|
|
return createPointerEvent('pointercancel', {
|
|
...payload,
|
|
buttons: 0,
|
|
detail: 0,
|
|
height: 1,
|
|
pageX: 0,
|
|
pageY: 0,
|
|
pressure: 0,
|
|
screenX: 0,
|
|
screenY: 0,
|
|
width: 1,
|
|
x: 0,
|
|
y: 0
|
|
});
|
|
}
|
|
|
|
export function pointerdown(payload) {
|
|
const isTouch = payload != null && payload.pointerType === 'touch';
|
|
return createPointerEvent('pointerdown', {
|
|
button: buttonType.primary,
|
|
buttons: buttonsType.primary,
|
|
pressure: isTouch ? 1 : 0.5,
|
|
...payload
|
|
});
|
|
}
|
|
|
|
export function pointerenter(payload) {
|
|
return createPointerEvent('pointerenter', payload);
|
|
}
|
|
|
|
export function pointerleave(payload) {
|
|
return createPointerEvent('pointerleave', payload);
|
|
}
|
|
|
|
export function pointermove(payload) {
|
|
return createPointerEvent('pointermove', {
|
|
...payload,
|
|
button: buttonType.none,
|
|
buttons: buttonsType.none
|
|
});
|
|
}
|
|
|
|
export function pointerout(payload) {
|
|
return createPointerEvent('pointerout', payload);
|
|
}
|
|
|
|
export function pointerover(payload) {
|
|
return createPointerEvent('pointerover', payload);
|
|
}
|
|
|
|
export function pointerup(payload) {
|
|
return createPointerEvent('pointerup', {
|
|
button: buttonType.primary,
|
|
...payload,
|
|
buttons: buttonsType.none,
|
|
pressure: 0
|
|
});
|
|
}
|
|
|
|
export function scroll() {
|
|
return createEvent('scroll', { bubbles: false });
|
|
}
|
|
|
|
export function select() {
|
|
return createEvent('select');
|
|
}
|
|
|
|
export function selectionchange() {
|
|
return createEvent('selectionchange');
|
|
}
|
|
|
|
export function touchcancel(payload) {
|
|
return createTouchEvent('touchcancel', payload);
|
|
}
|
|
|
|
export function touchend(payload) {
|
|
return createTouchEvent('touchend', payload);
|
|
}
|
|
|
|
export function touchmove(payload) {
|
|
return createTouchEvent('touchmove', payload);
|
|
}
|
|
|
|
export function touchstart(payload) {
|
|
return createTouchEvent('touchstart', payload);
|
|
}
|
|
|
|
export function virtualclick(payload) {
|
|
return createMouseEvent('click', {
|
|
button: 0,
|
|
...payload,
|
|
buttons: 0,
|
|
detail: 0,
|
|
height: 1,
|
|
pageX: 0,
|
|
pageY: 0,
|
|
pressure: 0,
|
|
screenX: 0,
|
|
screenY: 0,
|
|
width: 1,
|
|
x: 0,
|
|
y: 0
|
|
});
|
|
}
|