mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
187 lines
6.2 KiB
JavaScript
187 lines
6.2 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.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
import type {TopLevelType} from '../../events/TopLevelEventTypes';
|
|
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
|
|
import type {AnyNativeEvent} from '../../events/PluginModuleType';
|
|
import type {DispatchQueue} from '../DOMPluginEventSystem';
|
|
import type {EventSystemFlags} from '../EventSystemFlags';
|
|
|
|
import {
|
|
SyntheticEvent,
|
|
AnimationEventInterface,
|
|
ClipboardEventInterface,
|
|
FocusEventInterface,
|
|
KeyboardEventInterface,
|
|
MouseEventInterface,
|
|
PointerEventInterface,
|
|
DragEventInterface,
|
|
TouchEventInterface,
|
|
TransitionEventInterface,
|
|
UIEventInterface,
|
|
WheelEventInterface,
|
|
} from '../../events/SyntheticEvent';
|
|
|
|
import * as DOMTopLevelEventTypes from '../DOMTopLevelEventTypes';
|
|
import {
|
|
topLevelEventsToReactNames,
|
|
registerSimpleEvents,
|
|
} from '../DOMEventProperties';
|
|
import {
|
|
accumulateSinglePhaseListeners,
|
|
accumulateEventHandleNonManagedNodeListeners,
|
|
} from '../DOMPluginEventSystem';
|
|
import {IS_EVENT_HANDLE_NON_MANAGED_NODE} from '../EventSystemFlags';
|
|
|
|
import getEventCharCode from '../getEventCharCode';
|
|
import {IS_CAPTURE_PHASE} from '../EventSystemFlags';
|
|
|
|
import {enableCreateEventHandleAPI} from 'shared/ReactFeatureFlags';
|
|
|
|
function extractEvents(
|
|
dispatchQueue: DispatchQueue,
|
|
topLevelType: TopLevelType,
|
|
targetInst: null | Fiber,
|
|
nativeEvent: AnyNativeEvent,
|
|
nativeEventTarget: null | EventTarget,
|
|
eventSystemFlags: EventSystemFlags,
|
|
targetContainer: EventTarget,
|
|
): void {
|
|
const reactName = topLevelEventsToReactNames.get(topLevelType);
|
|
if (reactName === undefined) {
|
|
return;
|
|
}
|
|
let EventInterface;
|
|
switch (topLevelType) {
|
|
case DOMTopLevelEventTypes.TOP_KEY_PRESS:
|
|
// Firefox creates a keypress event for function keys too. This removes
|
|
// the unwanted keypress events. Enter is however both printable and
|
|
// non-printable. One would expect Tab to be as well (but it isn't).
|
|
if (getEventCharCode(((nativeEvent: any): KeyboardEvent)) === 0) {
|
|
return;
|
|
}
|
|
/* falls through */
|
|
case DOMTopLevelEventTypes.TOP_KEY_DOWN:
|
|
case DOMTopLevelEventTypes.TOP_KEY_UP:
|
|
EventInterface = KeyboardEventInterface;
|
|
break;
|
|
case DOMTopLevelEventTypes.TOP_FOCUS_IN:
|
|
case DOMTopLevelEventTypes.TOP_FOCUS_OUT:
|
|
case DOMTopLevelEventTypes.TOP_BEFORE_BLUR:
|
|
case DOMTopLevelEventTypes.TOP_AFTER_BLUR:
|
|
EventInterface = FocusEventInterface;
|
|
break;
|
|
case DOMTopLevelEventTypes.TOP_CLICK:
|
|
// Firefox creates a click event on right mouse clicks. This removes the
|
|
// unwanted click events.
|
|
if (nativeEvent.button === 2) {
|
|
return;
|
|
}
|
|
/* falls through */
|
|
case DOMTopLevelEventTypes.TOP_AUX_CLICK:
|
|
case DOMTopLevelEventTypes.TOP_DOUBLE_CLICK:
|
|
case DOMTopLevelEventTypes.TOP_MOUSE_DOWN:
|
|
case DOMTopLevelEventTypes.TOP_MOUSE_MOVE:
|
|
case DOMTopLevelEventTypes.TOP_MOUSE_UP:
|
|
// TODO: Disabled elements should not respond to mouse events
|
|
/* falls through */
|
|
case DOMTopLevelEventTypes.TOP_MOUSE_OUT:
|
|
case DOMTopLevelEventTypes.TOP_MOUSE_OVER:
|
|
case DOMTopLevelEventTypes.TOP_CONTEXT_MENU:
|
|
EventInterface = MouseEventInterface;
|
|
break;
|
|
case DOMTopLevelEventTypes.TOP_DRAG:
|
|
case DOMTopLevelEventTypes.TOP_DRAG_END:
|
|
case DOMTopLevelEventTypes.TOP_DRAG_ENTER:
|
|
case DOMTopLevelEventTypes.TOP_DRAG_EXIT:
|
|
case DOMTopLevelEventTypes.TOP_DRAG_LEAVE:
|
|
case DOMTopLevelEventTypes.TOP_DRAG_OVER:
|
|
case DOMTopLevelEventTypes.TOP_DRAG_START:
|
|
case DOMTopLevelEventTypes.TOP_DROP:
|
|
EventInterface = DragEventInterface;
|
|
break;
|
|
case DOMTopLevelEventTypes.TOP_TOUCH_CANCEL:
|
|
case DOMTopLevelEventTypes.TOP_TOUCH_END:
|
|
case DOMTopLevelEventTypes.TOP_TOUCH_MOVE:
|
|
case DOMTopLevelEventTypes.TOP_TOUCH_START:
|
|
EventInterface = TouchEventInterface;
|
|
break;
|
|
case DOMTopLevelEventTypes.TOP_ANIMATION_END:
|
|
case DOMTopLevelEventTypes.TOP_ANIMATION_ITERATION:
|
|
case DOMTopLevelEventTypes.TOP_ANIMATION_START:
|
|
EventInterface = AnimationEventInterface;
|
|
break;
|
|
case DOMTopLevelEventTypes.TOP_TRANSITION_END:
|
|
EventInterface = TransitionEventInterface;
|
|
break;
|
|
case DOMTopLevelEventTypes.TOP_SCROLL:
|
|
EventInterface = UIEventInterface;
|
|
break;
|
|
case DOMTopLevelEventTypes.TOP_WHEEL:
|
|
EventInterface = WheelEventInterface;
|
|
break;
|
|
case DOMTopLevelEventTypes.TOP_COPY:
|
|
case DOMTopLevelEventTypes.TOP_CUT:
|
|
case DOMTopLevelEventTypes.TOP_PASTE:
|
|
EventInterface = ClipboardEventInterface;
|
|
break;
|
|
case DOMTopLevelEventTypes.TOP_GOT_POINTER_CAPTURE:
|
|
case DOMTopLevelEventTypes.TOP_LOST_POINTER_CAPTURE:
|
|
case DOMTopLevelEventTypes.TOP_POINTER_CANCEL:
|
|
case DOMTopLevelEventTypes.TOP_POINTER_DOWN:
|
|
case DOMTopLevelEventTypes.TOP_POINTER_MOVE:
|
|
case DOMTopLevelEventTypes.TOP_POINTER_OUT:
|
|
case DOMTopLevelEventTypes.TOP_POINTER_OVER:
|
|
case DOMTopLevelEventTypes.TOP_POINTER_UP:
|
|
EventInterface = PointerEventInterface;
|
|
break;
|
|
default:
|
|
// Unknown event. This is used by createEventHandle.
|
|
break;
|
|
}
|
|
const event = new SyntheticEvent(
|
|
reactName,
|
|
null,
|
|
nativeEvent,
|
|
nativeEventTarget,
|
|
EventInterface,
|
|
);
|
|
|
|
const inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0;
|
|
if (
|
|
enableCreateEventHandleAPI &&
|
|
eventSystemFlags & IS_EVENT_HANDLE_NON_MANAGED_NODE
|
|
) {
|
|
accumulateEventHandleNonManagedNodeListeners(
|
|
dispatchQueue,
|
|
event,
|
|
targetContainer,
|
|
inCapturePhase,
|
|
);
|
|
} else {
|
|
// TODO: We may also want to re-use the accumulateTargetOnly flag to
|
|
// special case bubbling for onScroll/media events at a later point.
|
|
// In which case we will want to make this flag boolean and ensure
|
|
// we change the targetInst to be of the container instance. Like:
|
|
const accumulateTargetOnly = false;
|
|
|
|
// We traverse only capture or bubble phase listeners
|
|
accumulateSinglePhaseListeners(
|
|
targetInst,
|
|
dispatchQueue,
|
|
event,
|
|
inCapturePhase,
|
|
accumulateTargetOnly,
|
|
);
|
|
}
|
|
return event;
|
|
}
|
|
|
|
export {registerSimpleEvents as registerEvents, extractEvents};
|