Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React events: keyboard press, types, tests #15314

Merged
merged 8 commits into from
Apr 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions packages/react-events/src/Focus.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
import type {EventResponderContext} from 'events/EventTypes';
import {REACT_EVENT_COMPONENT_TYPE} from 'shared/ReactSymbols';

const targetEventTypes = [
{name: 'focus', passive: true, capture: true},
{name: 'blur', passive: true, capture: true},
];
type FocusProps = {
disabled: boolean,
onBlur: (e: FocusEvent) => void,
onFocus: (e: FocusEvent) => void,
onFocusChange: boolean => void,
};

type FocusState = {
isFocused: boolean,
Expand All @@ -27,6 +29,11 @@ type FocusEvent = {|
type: FocusEventType,
|};

const targetEventTypes = [
{name: 'focus', passive: true, capture: true},
{name: 'blur', passive: true, capture: true},
];

function createFocusEvent(
type: FocusEventType,
target: Element | Document,
Expand All @@ -39,7 +46,10 @@ function createFocusEvent(
};
}

function dispatchFocusInEvents(context: EventResponderContext, props: Object) {
function dispatchFocusInEvents(
context: EventResponderContext,
props: FocusProps,
) {
const {event, eventTarget} = context;
if (context.isTargetWithinEventComponent((event: any).relatedTarget)) {
return;
Expand All @@ -53,19 +63,22 @@ function dispatchFocusInEvents(context: EventResponderContext, props: Object) {
context.dispatchEvent(syntheticEvent, {discrete: true});
}
if (props.onFocusChange) {
const focusChangeEventListener = () => {
const listener = () => {
props.onFocusChange(true);
};
const syntheticEvent = createFocusEvent(
'focuschange',
eventTarget,
focusChangeEventListener,
listener,
);
context.dispatchEvent(syntheticEvent, {discrete: true});
}
}

function dispatchFocusOutEvents(context: EventResponderContext, props: Object) {
function dispatchFocusOutEvents(
context: EventResponderContext,
props: FocusProps,
) {
const {event, eventTarget} = context;
if (context.isTargetWithinEventComponent((event: any).relatedTarget)) {
return;
Expand All @@ -75,13 +88,13 @@ function dispatchFocusOutEvents(context: EventResponderContext, props: Object) {
context.dispatchEvent(syntheticEvent, {discrete: true});
}
if (props.onFocusChange) {
const focusChangeEventListener = () => {
const listener = () => {
props.onFocusChange(false);
};
const syntheticEvent = createFocusEvent(
'focuschange',
eventTarget,
focusChangeEventListener,
listener,
);
context.dispatchEvent(syntheticEvent, {discrete: true});
}
Expand Down
65 changes: 41 additions & 24 deletions packages/react-events/src/Hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
import type {EventResponderContext} from 'events/EventTypes';
import {REACT_EVENT_COMPONENT_TYPE} from 'shared/ReactSymbols';

const targetEventTypes = [
'pointerover',
'pointermove',
'pointerout',
'pointercancel',
];
type HoverProps = {
disabled: boolean,
delayHoverEnd: number,
delayHoverStart: number,
onHoverChange: boolean => void,
onHoverEnd: (e: HoverEvent) => void,
onHoverStart: (e: HoverEvent) => void,
};

type HoverState = {
isHovered: boolean,
Expand All @@ -31,6 +33,21 @@ type HoverEvent = {|
type: HoverEventType,
|};

// const DEFAULT_HOVER_END_DELAY_MS = 0;
// const DEFAULT_HOVER_START_DELAY_MS = 0;

const targetEventTypes = [
'pointerover',
'pointermove',
'pointerout',
'pointercancel',
];

// If PointerEvents is not supported (e.g., Safari), also listen to touch and mouse events.
if (typeof window !== 'undefined' && window.PointerEvent === undefined) {
targetEventTypes.push('touchstart', 'mouseover', 'mouseout');
}

function createHoverEvent(
type: HoverEventType,
target: Element | Document,
Expand All @@ -43,16 +60,9 @@ function createHoverEvent(
};
}

// In the case we don't have PointerEvents (Safari), we listen to touch events
// too
if (typeof window !== 'undefined' && window.PointerEvent === undefined) {
targetEventTypes.push('touchstart', 'mouseover', 'mouseout');
}

function dispatchHoverStartEvents(
context: EventResponderContext,
props: Object,
state: HoverState,
props: HoverProps,
): void {
const {event, eventTarget} = context;
if (context.isTargetWithinEventComponent((event: any).relatedTarget)) {
Expand All @@ -67,19 +77,22 @@ function dispatchHoverStartEvents(
context.dispatchEvent(syntheticEvent, {discrete: true});
}
if (props.onHoverChange) {
const hoverChangeEventListener = () => {
const listener = () => {
props.onHoverChange(true);
};
const syntheticEvent = createHoverEvent(
'hoverchange',
eventTarget,
hoverChangeEventListener,
listener,
);
context.dispatchEvent(syntheticEvent, {discrete: true});
}
}

function dispatchHoverEndEvents(context: EventResponderContext, props: Object) {
function dispatchHoverEndEvents(
context: EventResponderContext,
props: HoverProps,
) {
const {event, eventTarget} = context;
if (context.isTargetWithinEventComponent((event: any).relatedTarget)) {
return;
Expand All @@ -93,13 +106,13 @@ function dispatchHoverEndEvents(context: EventResponderContext, props: Object) {
context.dispatchEvent(syntheticEvent, {discrete: true});
}
if (props.onHoverChange) {
const hoverChangeEventListener = () => {
const listener = () => {
props.onHoverChange(false);
};
const syntheticEvent = createHoverEvent(
'hoverchange',
eventTarget,
hoverChangeEventListener,
listener,
);
context.dispatchEvent(syntheticEvent, {discrete: true});
}
Expand All @@ -116,18 +129,22 @@ const HoverResponder = {
},
handleEvent(
context: EventResponderContext,
props: Object,
props: HoverProps,
state: HoverState,
): void {
const {eventType, eventTarget, event} = context;

switch (eventType) {
case 'touchstart':
// Touch devices don't have hover support
/**
* Prevent hover events when touch is being used.
*/
case 'touchstart': {
if (!state.isTouched) {
state.isTouched = true;
}
break;
}

case 'pointerover':
case 'mouseover': {
if (
Expand All @@ -148,7 +165,7 @@ const HoverResponder = {
state.isInHitSlop = true;
return;
}
dispatchHoverStartEvents(context, props, state);
dispatchHoverStartEvents(context, props);
state.isHovered = true;
}
break;
Expand All @@ -172,7 +189,7 @@ const HoverResponder = {
(event: any).y,
)
) {
dispatchHoverStartEvents(context, props, state);
dispatchHoverStartEvents(context, props);
state.isHovered = true;
state.isInHitSlop = false;
}
Expand Down
Loading