Event API: Add FocusScope surface (#15487)

This commit is contained in:
Dominic Gannaway
2019-04-25 02:01:09 +01:00
committed by GitHub
parent 3f058debc2
commit 64e3da286f
24 changed files with 499 additions and 346 deletions
+62 -64
View File
@@ -84,6 +84,8 @@ const eventListeners:
($Shape<PartialEventObject>) => void,
> = new PossiblyWeakMap();
let alreadyDispatching = false;
let currentTimers = new Map();
let currentOwner = null;
let currentInstance: null | ReactEventComponentInstance = null;
@@ -322,61 +324,65 @@ const eventResponderContext: ReactResponderContext = {
}
}
},
getEventTargetsFromTarget(
target: Element | Document,
queryType?: Symbol | number,
queryKey?: string,
): Array<{
node: Element,
props: null | Object,
}> {
validateResponderContext();
const eventTargetHostComponents = [];
let node = getClosestInstanceFromNode(target);
// We traverse up the fiber tree from the target fiber, to the
// current event component fiber. Along the way, we check if
// the fiber has any children that are event targets. If there
// are, we query them (optionally) to ensure they match the
// specified type and key. We then push the event target props
// along with the associated parent host component of that event
// target.
getFocusableElementsInScope(): Array<HTMLElement> {
const focusableElements = [];
const eventComponentInstance = ((currentInstance: any): ReactEventComponentInstance);
let node = ((eventComponentInstance.currentFiber: any): Fiber).child;
while (node !== null) {
if (node.stateNode === currentInstance) {
break;
}
let child = node.child;
if (isFiberHostComponentFocusable(node)) {
focusableElements.push(node.stateNode);
} else {
const child = node.child;
while (child !== null) {
if (
child.tag === EventTargetWorkTag &&
queryEventTarget(child, queryType, queryKey)
) {
const props = child.stateNode.props;
let parent = child.return;
if (parent !== null) {
if (parent.stateNode === currentInstance) {
break;
}
if (parent.tag === HostComponent) {
eventTargetHostComponents.push({
node: parent.stateNode,
props,
});
break;
}
parent = parent.return;
}
break;
if (child !== null) {
node = child;
continue;
}
child = child.sibling;
}
node = node.return;
const sibling = node.sibling;
if (sibling !== null) {
node = sibling;
continue;
}
const parent = node.return;
if (parent === null) {
break;
}
node = parent.sibling;
}
return eventTargetHostComponents;
return focusableElements;
},
};
function isFiberHostComponentFocusable(fiber: Fiber): boolean {
if (fiber.tag !== HostComponent) {
return false;
}
const {type, memoizedProps} = fiber;
if (memoizedProps.tabIndex === -1 || memoizedProps.disabled) {
return false;
}
if (memoizedProps.tabIndex === 0) {
return true;
}
if (type === 'a' || type === 'area') {
return !!memoizedProps.href;
}
return (
type === 'button' ||
type === 'textarea' ||
type === 'input' ||
type === 'object' ||
type === 'select'
);
}
function processTimers(timers: Map<Symbol, ResponderTimer>): void {
const timersArr = Array.from(timers.values());
currentEventQueue = createEventQueue();
@@ -398,20 +404,6 @@ function processTimers(timers: Map<Symbol, ResponderTimer>): void {
}
}
function queryEventTarget(
child: Fiber,
queryType: void | Symbol | number,
queryKey: void | string,
): boolean {
if (queryType !== undefined && child.type.type !== queryType) {
return false;
}
if (queryKey !== undefined && child.key !== queryKey) {
return false;
}
return true;
}
function createResponderEvent(
topLevelType: string,
nativeEvent: AnyNativeEvent,
@@ -467,7 +459,7 @@ export function processEventQueue(): void {
}
}
function getTargetEventTypes(
function getTargetEventTypesSet(
eventTypes: Array<ReactEventResponderEventType>,
): Set<DOMTopLevelEventType> {
let cachedSet = targetEventTypeCached.get(eventTypes);
@@ -497,12 +489,13 @@ function getTargetEventResponderInstances(
const eventComponentInstance = node.stateNode;
if (currentOwner === null || currentOwner === eventComponentInstance) {
const responder = eventComponentInstance.responder;
const targetEventTypes = responder.targetEventTypes;
// Validate the target event type exists on the responder
const targetEventTypes = getTargetEventTypes(
responder.targetEventTypes,
);
if (targetEventTypes.has(topLevelType)) {
eventResponderInstances.push(eventComponentInstance);
if (targetEventTypes !== undefined) {
const targetEventTypesSet = getTargetEventTypesSet(targetEventTypes);
if (targetEventTypesSet.has(topLevelType)) {
eventResponderInstances.push(eventComponentInstance);
}
}
}
}
@@ -716,6 +709,10 @@ export function dispatchEventForResponderEventSystem(
eventSystemFlags: EventSystemFlags,
): void {
if (enableEventAPI) {
if (alreadyDispatching) {
return;
}
alreadyDispatching = true;
currentEventQueue = createEventQueue();
try {
traverseAndHandleEventResponderInstances(
@@ -730,6 +727,7 @@ export function dispatchEventForResponderEventSystem(
currentTimers = null;
currentInstance = null;
currentEventQueue = null;
alreadyDispatching = false;
}
}
}
@@ -12,7 +12,6 @@
let React;
let ReactFeatureFlags;
let ReactDOM;
let ReactSymbols;
function createReactEventComponent(
targetEventTypes,
@@ -57,14 +56,6 @@ function dispatchClickEvent(element) {
dispatchEvent(element, 'click');
}
function createReactEventTarget(type) {
return {
$$typeof: ReactSymbols.REACT_EVENT_TARGET_TYPE,
displayName: 'TestEventTarget',
type,
};
}
// This is a new feature in Fiber so I put it in its own test file. It could
// probably move to one of the other test files once it is official.
describe('DOMEventResponderSystem', () => {
@@ -78,7 +69,6 @@ describe('DOMEventResponderSystem', () => {
ReactDOM = require('react-dom');
container = document.createElement('div');
document.body.appendChild(container);
ReactSymbols = require('shared/ReactSymbols');
});
afterEach(() => {
@@ -676,235 +666,6 @@ describe('DOMEventResponderSystem', () => {
expect(onOwnershipChangeFired).toEqual(1);
});
it('should be possible to get event targets', () => {
let queryResult = null;
const buttonRef = React.createRef();
const divRef = React.createRef();
const eventTargetType = Symbol.for('react.event_target.test');
const EventTarget = createReactEventTarget(eventTargetType);
const EventComponent = createReactEventComponent(
['click'],
undefined,
undefined,
(event, context, props, state) => {
queryResult = Array.from(
context.getEventTargetsFromTarget(event.target),
);
},
);
const Test = () => (
<EventComponent>
<div ref={divRef}>
<EventTarget foo={1} />
<button ref={buttonRef}>
<EventTarget foo={2} />
Press me!
</button>
</div>
</EventComponent>
);
ReactDOM.render(<Test />, container);
let buttonElement = buttonRef.current;
let divElement = divRef.current;
dispatchClickEvent(buttonElement);
jest.runAllTimers();
expect(queryResult).toEqual([
{
node: buttonElement,
props: {
foo: 2,
},
},
{
node: divElement,
props: {
foo: 1,
},
},
]);
});
it('should be possible to query event targets by type', () => {
let queryResult = null;
const buttonRef = React.createRef();
const divRef = React.createRef();
const eventTargetType = Symbol.for('react.event_target.test');
const EventTarget = createReactEventTarget(eventTargetType);
const eventTargetType2 = Symbol.for('react.event_target.test2');
const EventTarget2 = createReactEventTarget(eventTargetType2);
const EventComponent = createReactEventComponent(
['click'],
undefined,
undefined,
(event, context, props, state) => {
queryResult = context.getEventTargetsFromTarget(
event.target,
eventTargetType2,
);
},
);
const Test = () => (
<EventComponent>
<div ref={divRef}>
<EventTarget2 foo={1} />
<button ref={buttonRef}>
<EventTarget foo={2} />
Press me!
</button>
</div>
</EventComponent>
);
ReactDOM.render(<Test />, container);
let buttonElement = buttonRef.current;
let divElement = divRef.current;
dispatchClickEvent(buttonElement);
jest.runAllTimers();
expect(queryResult).toEqual([
{
node: divElement,
props: {
foo: 1,
},
},
]);
});
it('should be possible to query event targets by key', () => {
let queryResult = null;
const buttonRef = React.createRef();
const divRef = React.createRef();
const eventTargetType = Symbol.for('react.event_target.test');
const EventTarget = createReactEventTarget(eventTargetType);
const EventComponent = createReactEventComponent(
['click'],
undefined,
undefined,
(event, context, props, state) => {
queryResult = context.getEventTargetsFromTarget(
event.target,
undefined,
'a',
);
},
);
const Test = () => (
<EventComponent>
<div ref={divRef}>
<EventTarget foo={1} />
<button ref={buttonRef}>
<EventTarget key="a" foo={2} />
Press me!
</button>
</div>
</EventComponent>
);
ReactDOM.render(<Test />, container);
let buttonElement = buttonRef.current;
dispatchClickEvent(buttonElement);
jest.runAllTimers();
expect(queryResult).toEqual([
{
node: buttonElement,
props: {
foo: 2,
},
},
]);
});
it('should be possible to query event targets by type and key', () => {
let queryResult = null;
let queryResult2 = null;
let queryResult3 = null;
const buttonRef = React.createRef();
const divRef = React.createRef();
const eventTargetType = Symbol.for('react.event_target.test');
const EventTarget = createReactEventTarget(eventTargetType);
const eventTargetType2 = Symbol.for('react.event_target.test2');
const EventTarget2 = createReactEventTarget(eventTargetType2);
const EventComponent = createReactEventComponent(
['click'],
undefined,
undefined,
(event, context, props, state) => {
queryResult = context.getEventTargetsFromTarget(
event.target,
eventTargetType2,
'a',
);
queryResult2 = context.getEventTargetsFromTarget(
event.target,
eventTargetType,
'c',
);
// Should return an empty array as this doesn't exist
queryResult3 = context.getEventTargetsFromTarget(
event.target,
eventTargetType,
'd',
);
},
);
const Test = () => (
<EventComponent>
<div ref={divRef}>
<EventTarget2 key="a" foo={1} />
<EventTarget2 key="b" foo={2} />
<button ref={buttonRef}>
<EventTarget key="c" foo={3} />
Press me!
</button>
</div>
</EventComponent>
);
ReactDOM.render(<Test />, container);
let buttonElement = buttonRef.current;
let divElement = divRef.current;
dispatchClickEvent(buttonElement);
jest.runAllTimers();
expect(queryResult).toEqual([
{
node: divElement,
props: {
foo: 1,
},
},
]);
expect(queryResult2).toEqual([
{
node: buttonElement,
props: {
foo: 3,
},
},
]);
expect(queryResult3).toEqual([]);
});
it('the event responder root listeners should fire on a root click event', () => {
let eventResponderFiredCount = 0;
let eventLog = [];
+6 -1
View File
@@ -12,6 +12,8 @@ import warning from 'shared/warning';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import voidElementTags from './voidElementTags';
import {enableEventAPI} from 'shared/ReactFeatureFlags';
import {REACT_EVENT_TARGET_TYPE} from 'shared/ReactSymbols';
const HTML = '__html';
@@ -27,7 +29,10 @@ function assertValidProps(tag: string, props: ?Object) {
// Note the use of `==` which checks for null or undefined.
if (voidElementTags[tag]) {
invariant(
props.children == null && props.dangerouslySetInnerHTML == null,
(props.children == null ||
(enableEventAPI &&
props.children.type.$$typeof === REACT_EVENT_TARGET_TYPE)) &&
props.dangerouslySetInnerHTML == null,
'%s is a void element tag and must neither have `children` nor ' +
'use `dangerouslySetInnerHTML`.%s',
tag,
+14
View File
@@ -0,0 +1,14 @@
/**
* 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
*/
'use strict';
const Drag = require('./src/Drag');
module.exports = Drag.default || Drag;
+14
View File
@@ -0,0 +1,14 @@
/**
* 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
*/
'use strict';
const Focus = require('./src/Focus');
module.exports = Focus.default || Focus;
+14
View File
@@ -0,0 +1,14 @@
/**
* 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
*/
'use strict';
const FocusScope = require('./src/FocusScope');
module.exports = FocusScope.default || FocusScope;
+14
View File
@@ -0,0 +1,14 @@
/**
* 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
*/
'use strict';
const Hover = require('./src/Hover');
module.exports = Hover.default || Hover;
+14
View File
@@ -0,0 +1,14 @@
/**
* 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
*/
'use strict';
const Press = require('./src/Press');
module.exports = Press.default || Press;
+14
View File
@@ -0,0 +1,14 @@
/**
* 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
*/
'use strict';
const Swipe = require('./src/Swipe');
module.exports = Swipe.default || Swipe;
+7
View File
@@ -0,0 +1,7 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-events-drag.production.min.js');
} else {
module.exports = require('./cjs/react-events-drag.development.js');
}
+7
View File
@@ -0,0 +1,7 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-events-focus.production.min.js');
} else {
module.exports = require('./cjs/react-events-focus.development.js');
}
+7
View File
@@ -0,0 +1,7 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-events-focus-scope.production.min.js');
} else {
module.exports = require('./cjs/react-events-focus-scope.development.js');
}
+7
View File
@@ -0,0 +1,7 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-events-hover.production.min.js');
} else {
module.exports = require('./cjs/react-events-hover.development.js');
}
+7
View File
@@ -0,0 +1,7 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-events-press.production.min.js');
} else {
module.exports = require('./cjs/react-events-press.development.js');
}
+7
View File
@@ -0,0 +1,7 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-events-swipe.production.min.js');
} else {
module.exports = require('./cjs/react-events-swipe.development.js');
}
+6 -5
View File
@@ -12,11 +12,12 @@
"files": [
"LICENSE",
"README.md",
"press.js",
"hover.js",
"focus.js",
"swipe.js",
"drag.js",
"Press.js",
"Hover.js",
"Focus.js",
"Swipe.js",
"Drag.js",
"FocusScope.js",
"index.js",
"build-info.json",
"cjs/",
+157
View File
@@ -0,0 +1,157 @@
/**
* 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 {
ReactResponderEvent,
ReactResponderContext,
} from 'shared/ReactTypes';
import {REACT_EVENT_COMPONENT_TYPE} from 'shared/ReactSymbols';
type FocusScopeProps = {
autoFocus: Boolean,
restoreFocus: Boolean,
trap: Boolean,
};
type FocusScopeState = {
nodeToRestore: null | HTMLElement,
currentFocusedNode: null | HTMLElement,
};
const rootEventTypes = [
{name: 'focus', passive: true, capture: true},
{name: 'keydown', passive: false},
];
function focusFirstChildEventTarget(
context: ReactResponderContext,
state: FocusScopeState,
): void {
const elements = context.getFocusableElementsInScope();
if (elements.length > 0) {
const firstElement = elements[0];
firstElement.focus();
state.currentFocusedNode = firstElement;
}
}
function focusLastChildEventTarget(
context: ReactResponderContext,
state: FocusScopeState,
): void {
const elements = context.getFocusableElementsInScope();
const length = elements.length;
if (elements.length > 0) {
const lastElement = elements[length - 1];
lastElement.focus();
state.currentFocusedNode = lastElement;
}
}
const FocusScopeResponder = {
rootEventTypes,
createInitialState(): FocusScopeState {
return {
nodeToRestore: null,
currentFocusedNode: null,
};
},
onRootEvent(
event: ReactResponderEvent,
context: ReactResponderContext,
props: FocusScopeProps,
state: FocusScopeState,
) {
const {type, target, nativeEvent} = event;
if (type === 'focus') {
if (context.isTargetWithinEventComponent(target)) {
state.currentFocusedNode = ((target: any): HTMLElement);
} else if (props.trap) {
if (state.currentFocusedNode !== null) {
state.currentFocusedNode.focus();
} else {
focusFirstChildEventTarget(context, state);
}
}
} else if (type === 'keydown' && nativeEvent.key === 'Tab') {
const currentFocusedNode = state.currentFocusedNode;
if (currentFocusedNode !== null) {
const {altkey, ctrlKey, metaKey, shiftKey} = (nativeEvent: any);
// Skip if any of these keys are being pressed
if (altkey || ctrlKey || metaKey) {
return;
}
const elements = context.getFocusableElementsInScope();
const position = elements.indexOf(currentFocusedNode);
if (shiftKey) {
if (position === 0) {
if (props.trap) {
focusLastChildEventTarget(context, state);
} else {
return;
}
} else {
const previousElement = elements[position - 1];
previousElement.focus();
state.currentFocusedNode = previousElement;
}
} else {
if (position === elements.length - 1) {
if (props.trap) {
focusFirstChildEventTarget(context, state);
} else {
return;
}
} else {
const nextElement = elements[position + 1];
nextElement.focus();
state.currentFocusedNode = nextElement;
}
}
((nativeEvent: any): KeyboardEvent).preventDefault();
}
}
},
onMount(
context: ReactResponderContext,
props: FocusScopeProps,
state: FocusScopeState,
) {
if (props.restoreFocus) {
state.nodeToRestore = document.activeElement;
}
if (props.autoFocus) {
focusFirstChildEventTarget(context, state);
}
},
onUnmount(
context: ReactResponderContext,
props: FocusScopeProps,
state: FocusScopeState,
) {
if (props.restoreFocus && state.nodeToRestore !== null) {
state.nodeToRestore.focus();
}
},
onOwnershipChange(
context: ReactResponderContext,
props: FocusScopeProps,
state: FocusScopeState,
) {
// unmountResponder(context, props, state);
},
};
export default {
$$typeof: REACT_EVENT_COMPONENT_TYPE,
displayName: 'FocusScope',
props: null,
responder: FocusScopeResponder,
};
-12
View File
@@ -10,8 +10,6 @@
import {
REACT_EVENT_TARGET_TYPE,
REACT_EVENT_TARGET_TOUCH_HIT,
REACT_EVENT_FOCUS_TARGET,
REACT_EVENT_PRESS_TARGET,
} from 'shared/ReactSymbols';
import type {ReactEventTarget} from 'shared/ReactTypes';
@@ -19,13 +17,3 @@ export const TouchHitTarget: ReactEventTarget = {
$$typeof: REACT_EVENT_TARGET_TYPE,
type: REACT_EVENT_TARGET_TOUCH_HIT,
};
export const FocusTarget: ReactEventTarget = {
$$typeof: REACT_EVENT_TARGET_TYPE,
type: REACT_EVENT_FOCUS_TARGET,
};
export const PressTarget: ReactEventTarget = {
$$typeof: REACT_EVENT_TARGET_TYPE,
type: REACT_EVENT_PRESS_TARGET,
};
@@ -0,0 +1,117 @@
/**
* 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.
*
* @emails react-core
*/
'use strict';
let React;
let ReactFeatureFlags;
let ReactDOM;
let FocusScope;
const createTabForward = type => {
const event = new KeyboardEvent('keydown', {
key: 'Tab',
bubbles: true,
cancelable: true,
});
return event;
};
const createTabBackward = type => {
const event = new KeyboardEvent('keydown', {
key: 'Tab',
shiftKey: true,
bubbles: true,
cancelable: true,
});
return event;
};
describe('FocusScope event responder', () => {
let container;
beforeEach(() => {
jest.resetModules();
ReactFeatureFlags = require('shared/ReactFeatureFlags');
ReactFeatureFlags.enableEventAPI = true;
React = require('react');
ReactDOM = require('react-dom');
FocusScope = require('react-events/FocusScope');
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
document.body.removeChild(container);
container = null;
});
it('when using a simple focus scope with autofocus', () => {
const inputRef = React.createRef();
const input2Ref = React.createRef();
const buttonRef = React.createRef();
const butto2nRef = React.createRef();
const divRef = React.createRef();
const SimpleFocusScope = () => (
<div>
<FocusScope autoFocus={true}>
<input ref={inputRef} />
<button ref={buttonRef} />
<div ref={divRef} tabIndex={0} />
<input ref={input2Ref} tabIndex={-1} />
<button ref={butto2nRef} />
</FocusScope>
</div>
);
ReactDOM.render(<SimpleFocusScope />, container);
expect(document.activeElement).toBe(inputRef.current);
document.dispatchEvent(createTabForward());
expect(document.activeElement).toBe(buttonRef.current);
document.dispatchEvent(createTabForward());
expect(document.activeElement).toBe(divRef.current);
document.dispatchEvent(createTabForward());
expect(document.activeElement).toBe(butto2nRef.current);
document.dispatchEvent(createTabBackward());
expect(document.activeElement).toBe(divRef.current);
});
it('when using a simple focus scope with autofocus and trapping', () => {
const inputRef = React.createRef();
const input2Ref = React.createRef();
const buttonRef = React.createRef();
const button2Ref = React.createRef();
const SimpleFocusScope = () => (
<div>
<FocusScope autoFocus={true} trap={true}>
<input ref={inputRef} tabIndex={-1} />
<button ref={buttonRef} id={1} />
<button ref={button2Ref} id={2} />
<input ref={input2Ref} tabIndex={-1} />
</FocusScope>
</div>
);
ReactDOM.render(<SimpleFocusScope />, container);
expect(document.activeElement).toBe(buttonRef.current);
document.dispatchEvent(createTabForward());
expect(document.activeElement).toBe(button2Ref.current);
document.dispatchEvent(createTabForward());
expect(document.activeElement).toBe(buttonRef.current);
document.dispatchEvent(createTabForward());
expect(document.activeElement).toBe(button2Ref.current);
document.dispatchEvent(createTabBackward());
expect(document.activeElement).toBe(buttonRef.current);
document.dispatchEvent(createTabBackward());
expect(document.activeElement).toBe(button2Ref.current);
});
});
@@ -812,6 +812,7 @@ function completeWork(
responderState = responder.createInitialState(newProps);
}
eventComponentInstance = workInProgress.stateNode = {
currentFiber: workInProgress,
props: newProps,
responder,
rootEventTypes: null,
@@ -824,6 +825,8 @@ function completeWork(
eventComponentInstance.props = newProps;
// Update the root container, so we can properly unmount events at some point
eventComponentInstance.rootInstance = rootContainerInstance;
// Update the current fiber
eventComponentInstance.currentFiber = workInProgress;
updateEventComponent(eventComponentInstance);
}
}
-6
View File
@@ -57,12 +57,6 @@ export const REACT_EVENT_TARGET_TYPE = hasSymbol
export const REACT_EVENT_TARGET_TOUCH_HIT = hasSymbol
? Symbol.for('react.event_target.touch_hit')
: 0xead7;
export const REACT_EVENT_FOCUS_TARGET = hasSymbol
? Symbol.for('react.event_target.focus')
: 0xead8;
export const REACT_EVENT_PRESS_TARGET = hasSymbol
? Symbol.for('react.event_target.press')
: 0xead9;
const MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
const FAUX_ITERATOR_SYMBOL = '@@iterator';
+2 -8
View File
@@ -126,6 +126,7 @@ export type ReactEventResponder = {
};
export type ReactEventComponentInstance = {|
currentFiber: mixed,
props: null | Object,
responder: ReactEventResponder,
rootEventTypes: null | Set<string>,
@@ -189,12 +190,5 @@ export type ReactResponderContext = {
releaseOwnership: () => boolean,
setTimeout: (func: () => void, timeout: number) => Symbol,
clearTimeout: (timerId: Symbol) => void,
getEventTargetsFromTarget: (
target: Element | Document,
queryType?: Symbol | number,
queryKey?: string,
) => Array<{
node: Element,
props: null | Object,
}>,
getFocusableElementsInScope(): Array<HTMLElement>,
};
-6
View File
@@ -25,8 +25,6 @@ import {
REACT_EVENT_COMPONENT_TYPE,
REACT_EVENT_TARGET_TYPE,
REACT_EVENT_TARGET_TOUCH_HIT,
REACT_EVENT_FOCUS_TARGET,
REACT_EVENT_PRESS_TARGET,
} from 'shared/ReactSymbols';
import {refineResolvedLazyComponent} from 'shared/ReactLazyComponent';
import type {ReactEventComponent, ReactEventTarget} from 'shared/ReactTypes';
@@ -112,10 +110,6 @@ function getComponentName(type: mixed): string | null {
const eventTarget = ((type: any): ReactEventTarget);
if (eventTarget.type === REACT_EVENT_TARGET_TOUCH_HIT) {
return 'TouchHitTarget';
} else if (eventTarget.type === REACT_EVENT_FOCUS_TARGET) {
return 'FocusTarget';
} else if (eventTarget.type === REACT_EVENT_PRESS_TARGET) {
return 'PressTarget';
}
const displayName = eventTarget.displayName;
if (displayName !== undefined) {
+20 -5
View File
@@ -490,7 +490,7 @@ const bundles = [
FB_WWW_PROD,
],
moduleType: NON_FIBER_RENDERER,
entry: 'react-events/press',
entry: 'react-events/Press',
global: 'ReactEventsPress',
externals: [],
},
@@ -505,7 +505,7 @@ const bundles = [
FB_WWW_PROD,
],
moduleType: NON_FIBER_RENDERER,
entry: 'react-events/hover',
entry: 'react-events/Hover',
global: 'ReactEventsHover',
externals: [],
},
@@ -520,7 +520,7 @@ const bundles = [
FB_WWW_PROD,
],
moduleType: NON_FIBER_RENDERER,
entry: 'react-events/focus',
entry: 'react-events/Focus',
global: 'ReactEventsFocus',
externals: [],
},
@@ -535,7 +535,22 @@ const bundles = [
FB_WWW_PROD,
],
moduleType: NON_FIBER_RENDERER,
entry: 'react-events/swipe',
entry: 'react-events/FocusScope',
global: 'ReactEventsFocusScope',
externals: [],
},
{
bundleTypes: [
UMD_DEV,
UMD_PROD,
NODE_DEV,
NODE_PROD,
FB_WWW_DEV,
FB_WWW_PROD,
],
moduleType: NON_FIBER_RENDERER,
entry: 'react-events/Swipe',
global: 'ReactEventsSwipe',
externals: [],
},
@@ -550,7 +565,7 @@ const bundles = [
FB_WWW_PROD,
],
moduleType: NON_FIBER_RENDERER,
entry: 'react-events/drag',
entry: 'react-events/Drag',
global: 'ReactEventsDrag',
externals: [],
},