From 51e66cf9fa3448efdc7c5938405757dbb53c9079 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Wed, 8 May 2019 19:09:32 +0100 Subject: [PATCH] Experimental Event API: reduce code size of event modules (#15590) --- .../src/events/DOMEventResponderSystem.js | 60 +++++++++++++++---- packages/react-events/src/Focus.js | 5 +- packages/react-events/src/Hover.js | 10 +--- packages/react-events/src/Press.js | 26 ++++---- packages/react-events/src/utils.js | 34 ----------- packages/shared/ReactTypes.js | 5 ++ 6 files changed, 72 insertions(+), 68 deletions(-) diff --git a/packages/react-dom/src/events/DOMEventResponderSystem.js b/packages/react-dom/src/events/DOMEventResponderSystem.js index 803ad9652c..86f03cc62a 100644 --- a/packages/react-dom/src/events/DOMEventResponderSystem.js +++ b/packages/react-dom/src/events/DOMEventResponderSystem.js @@ -163,19 +163,7 @@ const eventResponderContext: ReactResponderContext = { } return false; }, - isTargetWithinEventComponent(target: Element | Document): boolean { - validateResponderContext(); - if (target != null) { - let fiber = getClosestInstanceFromNode(target); - while (fiber !== null) { - if (fiber.stateNode === currentInstance) { - return true; - } - fiber = fiber.return; - } - } - return false; - }, + isTargetWithinEventComponent, isTargetWithinEventResponderScope(target: Element | Document): boolean { validateResponderContext(); const responder = ((currentInstance: any): ReactEventComponentInstance) @@ -371,8 +359,54 @@ const eventResponderContext: ReactResponderContext = { return focusableElements; }, getActiveDocument, + objectAssign: Object.assign, + getEventPointerType( + event: ReactResponderEvent, + ): '' | 'mouse' | 'keyboard' | 'pen' | 'touch' { + const nativeEvent: any = event.nativeEvent; + const {type, pointerType} = nativeEvent; + if (pointerType != null) { + return pointerType; + } + if (type.indexOf('mouse') === 0) { + return 'mouse'; + } + if (type.indexOf('touch') === 0) { + return 'touch'; + } + if (type.indexOf('key') === 0) { + return 'keyboard'; + } + return ''; + }, + getEventCurrentTarget(event: ReactResponderEvent): Element { + const target: any = event.target; + let currentTarget = target; + while ( + currentTarget.parentNode && + currentTarget.parentNode.nodeType === Node.ELEMENT_NODE && + isTargetWithinEventComponent(currentTarget.parentNode) + ) { + currentTarget = currentTarget.parentNode; + } + return currentTarget; + }, }; +function isTargetWithinEventComponent(target: Element | Document): boolean { + validateResponderContext(); + if (target != null) { + let fiber = getClosestInstanceFromNode(target); + while (fiber !== null) { + if (fiber.stateNode === currentInstance) { + return true; + } + fiber = fiber.return; + } + } + return false; +} + function getActiveDocument(): Document { const eventComponentInstance = ((currentInstance: any): ReactEventComponentInstance); const rootElement = ((eventComponentInstance.rootInstance: any): Element); diff --git a/packages/react-events/src/Focus.js b/packages/react-events/src/Focus.js index 1984b8e0d0..2583c79a8c 100644 --- a/packages/react-events/src/Focus.js +++ b/packages/react-events/src/Focus.js @@ -13,7 +13,6 @@ import type { } from 'shared/ReactTypes'; import React from 'react'; -import {getEventCurrentTarget} from './utils.js'; type FocusProps = { disabled: boolean, @@ -173,7 +172,7 @@ const FocusResponder = { if (!state.isFocused) { // Limit focus events to the direct child of the event component. // Browser focus is not expected to bubble. - state.focusTarget = getEventCurrentTarget(event, context); + state.focusTarget = context.getEventCurrentTarget(event); if (state.focusTarget === target) { state.isFocused = true; state.isLocalFocusVisible = isGlobalFocusVisible; @@ -221,7 +220,7 @@ const FocusResponder = { // Focus should stop being visible if a pointer is used on the element // after it was focused using a keyboard. if ( - state.focusTarget === getEventCurrentTarget(event, context) && + state.focusTarget === context.getEventCurrentTarget(event) && (type === 'mousedown' || type === 'touchstart' || type === 'pointerdown') diff --git a/packages/react-events/src/Hover.js b/packages/react-events/src/Hover.js index 1e0e1d2ca6..97bf1a824b 100644 --- a/packages/react-events/src/Hover.js +++ b/packages/react-events/src/Hover.js @@ -13,11 +13,7 @@ import type { } from 'shared/ReactTypes'; import React from 'react'; -import { - getEventPointerType, - getEventCurrentTarget, - isEventPositionWithinTouchHitTarget, -} from './utils'; +import {isEventPositionWithinTouchHitTarget} from './utils'; type HoverProps = { disabled: boolean, @@ -264,7 +260,7 @@ const HoverResponder = { } return; } - const pointerType = getEventPointerType(event); + const pointerType = context.getEventPointerType(event); switch (type) { // START @@ -287,7 +283,7 @@ const HoverResponder = { state.isOverTouchHitTarget = true; return; } - state.hoverTarget = getEventCurrentTarget(event, context); + state.hoverTarget = context.getEventCurrentTarget(event); state.ignoreEmulatedMouseEvents = true; dispatchHoverStartEvents(event, context, props, state); } diff --git a/packages/react-events/src/Press.js b/packages/react-events/src/Press.js index 3385fbebfd..4c9cca7ea5 100644 --- a/packages/react-events/src/Press.js +++ b/packages/react-events/src/Press.js @@ -15,11 +15,7 @@ import type { import React from 'react'; -import { - getEventPointerType, - getEventCurrentTarget, - isEventPositionWithinTouchHitTarget, -} from './utils'; +import {isEventPositionWithinTouchHitTarget} from './utils'; type PressProps = { disabled: boolean, @@ -365,11 +361,16 @@ function calculateDelayMS(delay: ?number, min = 0, fallback = 0) { } // TODO: account for touch hit slop -function calculateResponderRegion(target: Element, props: PressProps) { - const pressRetentionOffset = { +function calculateResponderRegion( + context: ReactResponderContext, + target: Element, + props: PressProps, +) { + const pressRetentionOffset = context.objectAssign( + {}, ...DEFAULT_PRESS_RETENTION_OFFSET, ...props.pressRetentionOffset, - }; + ); const clientRect = target.getBoundingClientRect(); @@ -533,7 +534,7 @@ const PressResponder = { return; } const nativeEvent: any = event.nativeEvent; - const pointerType = getEventPointerType(event); + const pointerType = context.getEventPointerType(event); switch (type) { // START @@ -575,8 +576,9 @@ const PressResponder = { state.allowPressReentry = true; state.pointerType = pointerType; - state.pressTarget = getEventCurrentTarget(event, context); + state.pressTarget = context.getEventCurrentTarget(event); state.responderRegionOnActivation = calculateResponderRegion( + context, state.pressTarget, props, ); @@ -620,7 +622,7 @@ const PressResponder = { const {target, type} = event; const nativeEvent: any = event.nativeEvent; - const pointerType = getEventPointerType(event); + const pointerType = context.getEventPointerType(event); switch (type) { // MOVE @@ -641,6 +643,7 @@ const PressResponder = { state.responderRegionOnDeactivation == null ) { state.responderRegionOnDeactivation = calculateResponderRegion( + context, state.pressTarget, props, ); @@ -708,6 +711,7 @@ const PressResponder = { // already done during move event. if (state.responderRegionOnDeactivation == null) { state.responderRegionOnDeactivation = calculateResponderRegion( + context, state.pressTarget, props, ); diff --git a/packages/react-events/src/utils.js b/packages/react-events/src/utils.js index 9fb90c6e16..15848aafca 100644 --- a/packages/react-events/src/utils.js +++ b/packages/react-events/src/utils.js @@ -12,40 +12,6 @@ import type { ReactResponderContext, } from 'shared/ReactTypes'; -export function getEventCurrentTarget( - event: ReactResponderEvent, - context: ReactResponderContext, -): Element { - const target: any = event.target; - let currentTarget = target; - while ( - currentTarget.parentNode && - currentTarget.parentNode.nodeType === Node.ELEMENT_NODE && - context.isTargetWithinEventComponent(currentTarget.parentNode) - ) { - currentTarget = currentTarget.parentNode; - } - return currentTarget; -} - -export function getEventPointerType(event: ReactResponderEvent) { - const nativeEvent: any = event.nativeEvent; - const {type, pointerType} = nativeEvent; - if (pointerType != null) { - return pointerType; - } - if (type.indexOf('mouse') === 0) { - return 'mouse'; - } - if (type.indexOf('touch') === 0) { - return 'touch'; - } - if (type.indexOf('key') === 0) { - return 'keyboard'; - } - return ''; -} - export function isEventPositionWithinTouchHitTarget( event: ReactResponderEvent, context: ReactResponderContext, diff --git a/packages/shared/ReactTypes.js b/packages/shared/ReactTypes.js index 3fb4c46cea..fad4401638 100644 --- a/packages/shared/ReactTypes.js +++ b/packages/shared/ReactTypes.js @@ -188,4 +188,9 @@ export type ReactResponderContext = { clearTimeout: (timerId: Symbol) => void, getFocusableElementsInScope(): Array, getActiveDocument(): Document, + objectAssign: Function, + getEventPointerType( + event: ReactResponderEvent, + ): '' | 'mouse' | 'keyboard' | 'pen' | 'touch', + getEventCurrentTarget(event: ReactResponderEvent): Element, };