/
githubmr
/
facebook-react
Обзор
Документация
Войти
/
githubmr
/
facebook-react
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
main
packages/react-dom-bindings/src/events/plugins/SimpleEventPlugin.js
233 строки
7 KB
Sebastian Silbermann
React DOM: Add support for Popover API (#27981)
20 май 2024, 23:01
Не верифицирован
20 май 2024, 23:01
6f90365
Код
Авторство
О чём код?
/** * Copyright (c) Meta Platforms, Inc. and 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 {DOMEventName} from '../../events/DOMEventNames'; 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 type {ReactSyntheticEvent} from '../ReactSyntheticEventType'; import { SyntheticEvent, SyntheticKeyboardEvent, SyntheticFocusEvent, SyntheticMouseEvent, SyntheticDragEvent, SyntheticTouchEvent, SyntheticAnimationEvent, SyntheticTransitionEvent, SyntheticUIEvent, SyntheticWheelEvent, SyntheticClipboardEvent, SyntheticPointerEvent, SyntheticToggleEvent, } from '../../events/SyntheticEvent'; import { ANIMATION_END, ANIMATION_ITERATION, ANIMATION_START, TRANSITION_END, } from '../DOMEventNames'; import { topLevelEventsToReactNames, registerSimpleEvents, } from '../DOMEventProperties'; import { accumulateSinglePhaseListeners, accumulateEventHandleNonManagedNodeListeners, } from '../DOMPluginEventSystem'; import { IS_EVENT_HANDLE_NON_MANAGED_NODE, IS_CAPTURE_PHASE, } from '../EventSystemFlags'; import getEventCharCode from '../getEventCharCode'; import {enableCreateEventHandleAPI} from 'shared/ReactFeatureFlags'; function extractEvents( dispatchQueue: DispatchQueue, domEventName: DOMEventName, targetInst: null | Fiber, nativeEvent: AnyNativeEvent, nativeEventTarget: null | EventTarget, eventSystemFlags: EventSystemFlags, targetContainer: EventTarget, ): void { const reactName = topLevelEventsToReactNames.get(domEventName); if (reactName === undefined) { return; } let SyntheticEventCtor = SyntheticEvent; let reactEventType: string = domEventName; switch (domEventName) { case 'keypress': // 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). // TODO: Fixed in https://bugzilla.mozilla.org/show_bug.cgi?id=968056. Can // probably remove. if (getEventCharCode(((nativeEvent: any): KeyboardEvent)) === 0) { return; } /* falls through */ case 'keydown': case 'keyup': SyntheticEventCtor = SyntheticKeyboardEvent; break; case 'focusin': reactEventType = 'focus'; SyntheticEventCtor = SyntheticFocusEvent; break; case 'focusout': reactEventType = 'blur'; SyntheticEventCtor = SyntheticFocusEvent; break; case 'beforeblur': case 'afterblur': SyntheticEventCtor = SyntheticFocusEvent; break; case 'click': // Firefox creates a click event on right mouse clicks. This removes the // unwanted click events. // TODO: Fixed in https://phabricator.services.mozilla.com/D26793. Can // probably remove. if (nativeEvent.button === 2) { return; } /* falls through */ case 'auxclick': case 'dblclick': case 'mousedown': case 'mousemove': case 'mouseup': // TODO: Disabled elements should not respond to mouse events /* falls through */ case 'mouseout': case 'mouseover': case 'contextmenu': SyntheticEventCtor = SyntheticMouseEvent; break; case 'drag': case 'dragend': case 'dragenter': case 'dragexit': case 'dragleave': case 'dragover': case 'dragstart': case 'drop': SyntheticEventCtor = SyntheticDragEvent; break; case 'touchcancel': case 'touchend': case 'touchmove': case 'touchstart': SyntheticEventCtor = SyntheticTouchEvent; break; case ANIMATION_END: case ANIMATION_ITERATION: case ANIMATION_START: SyntheticEventCtor = SyntheticAnimationEvent; break; case TRANSITION_END: SyntheticEventCtor = SyntheticTransitionEvent; break; case 'scroll': case 'scrollend': SyntheticEventCtor = SyntheticUIEvent; break; case 'wheel': SyntheticEventCtor = SyntheticWheelEvent; break; case 'copy': case 'cut': case 'paste': SyntheticEventCtor = SyntheticClipboardEvent; break; case 'gotpointercapture': case 'lostpointercapture': case 'pointercancel': case 'pointerdown': case 'pointermove': case 'pointerout': case 'pointerover': case 'pointerup': SyntheticEventCtor = SyntheticPointerEvent; break; case 'toggle': case 'beforetoggle': // MDN claims <details> should not receive ToggleEvent contradicting the spec: https://html.spec.whatwg.org/multipage/indices.html#event-toggle SyntheticEventCtor = SyntheticToggleEvent; break; default: // Unknown event. This is used by createEventHandle. break; } const inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0; if ( enableCreateEventHandleAPI && eventSystemFlags & IS_EVENT_HANDLE_NON_MANAGED_NODE ) { const listeners = accumulateEventHandleNonManagedNodeListeners( // TODO: this cast may not make sense for events like // "focus" where React listens to e.g. "focusin". ((reactEventType: any): DOMEventName), targetContainer, inCapturePhase, ); if (listeners.length > 0) { // Intentionally create event lazily. const event: ReactSyntheticEvent = new SyntheticEventCtor( reactName, reactEventType, null, nativeEvent, nativeEventTarget, ); dispatchQueue.push({event, listeners}); } } else { // Some events don't bubble in the browser. // In the past, React has always bubbled them, but this can be surprising. // We're going to try aligning closer to the browser behavior by not bubbling // them in React either. We'll start by not bubbling onScroll, and then expand. const accumulateTargetOnly = !inCapturePhase && // TODO: ideally, we'd eventually add all events from // nonDelegatedEvents list in DOMPluginEventSystem. // Then we can remove this special list. // This is a breaking change that can wait until React 18. (domEventName === 'scroll' || domEventName === 'scrollend'); const listeners = accumulateSinglePhaseListeners( targetInst, reactName, nativeEvent.type, inCapturePhase, accumulateTargetOnly, nativeEvent, ); if (listeners.length > 0) { // Intentionally create event lazily. const event: ReactSyntheticEvent = new SyntheticEventCtor( reactName, reactEventType, null, nativeEvent, nativeEventTarget, ); dispatchQueue.push({event, listeners}); } } } export {registerSimpleEvents as registerEvents, extractEvents};