Skip to content

Commit

Permalink
[Flare] Remove delay props from Press (#16247)
Browse files Browse the repository at this point in the history
Moving working with delays into user-space.
  • Loading branch information
necolas authored Jul 30, 2019
1 parent 55bc393 commit 1912b4a
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 697 deletions.
24 changes: 4 additions & 20 deletions packages/react-events/docs/Press.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,6 @@ type PressOffset = {

## Props

### delayPressEnd: number

The duration of the delay between when the press ends and when `onPressEnd` is
called.

### delayPressStart: number

The duration of a delay between when the press starts and when `onPressStart` is
called. This delay is cut short (and `onPressStart` is called) if the press is
released before the threshold is exceeded.

### disabled: boolean = false

Disables all `Press` events.
Expand All @@ -107,21 +96,16 @@ Called when the element changes press state (i.e., after `onPressStart` and
### onPressEnd: (e: PressEvent) => void

Called once the element is no longer pressed (because the press was released,
cancelled, or moved beyond the hit bounds). If the press starts again before the
`delayPressEnd` threshold is exceeded then the delay is reset to prevent
`onPressEnd` being called during a press.
cancelled, or moved beyond the hit bounds).

### onPressMove: (e: PressEvent) => void

Called when a press moves within the hit bounds of the element. `onPressMove` is
called immediately and doesn't wait for delayed `onPressStart`. Never called for
Called when a press moves within the hit bounds of the element. Never called for
keyboard-initiated press events.

### onPressStart: (e: PressEvent) => void

Called once the element is pressed down. If the press is released before the
`delayPressStart` threshold is exceeded then the delay is cut short and
`onPressStart` is called immediately.
Called once the element is pressed down.

### pressRetentionOffset: PressOffset

Expand All @@ -142,4 +126,4 @@ Whether to `preventDefault()` native events. Native behavior is prevented by
default. If an anchor is the child of `Press`, internal and external navigation
should be performed in `onPress`. To rely on native behavior instead, set
`preventDefault` to `false`, but be aware that native behavior will take place
immediately after interaction without respect for delays or long press.
immediately after interaction.
115 changes: 26 additions & 89 deletions packages/react-events/src/dom/Press.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ type PressListenerProps = {|

type PressProps = {|
disabled: boolean,
delayPressEnd: number,
delayPressStart: number,
pressRetentionOffset: {
top: number,
right: number,
Expand All @@ -53,7 +51,6 @@ type PressState = {
isPressWithinResponderRegion: boolean,
pointerType: PointerType,
pressTarget: null | Element | Document,
pressEndTimeout: null | number,
pressStartTimeout: null | number,
responderRegionOnActivation: null | $ReadOnly<{|
bottom: number,
Expand Down Expand Up @@ -106,8 +103,6 @@ const isMac =
typeof window !== 'undefined' && window.navigator != null
? /^Mac/.test(window.navigator.platform)
: false;
const DEFAULT_PRESS_END_DELAY_MS = 0;
const DEFAULT_PRESS_START_DELAY_MS = 0;
const DEFAULT_PRESS_RETENTION_OFFSET = {
bottom: 20,
top: 20,
Expand Down Expand Up @@ -240,35 +235,6 @@ function dispatchPressChangeEvent(
context.dispatchEvent('onPressChange', bool, DiscreteEvent);
}

function activate(event: ReactDOMResponderEvent, context, props, state) {
const nativeEvent: any = event.nativeEvent;
const {clientX: x, clientY: y} = state.touchEvent || nativeEvent;
const wasActivePressed = state.isActivePressed;
state.isActivePressed = true;
if (x !== undefined && y !== undefined) {
state.activationPosition = {x, y};
}

dispatchEvent(
'onPressStart',
event,
context,
state,
'pressstart',
DiscreteEvent,
);
if (!wasActivePressed) {
dispatchPressChangeEvent(context, state);
}
}

function deactivate(event: ?ReactDOMResponderEvent, context, props, state) {
state.isActivePressed = false;

dispatchEvent('onPressEnd', event, context, state, 'pressend', DiscreteEvent);
dispatchPressChangeEvent(context, state);
}

function dispatchPressStartEvents(
event: ReactDOMResponderEvent,
context: ReactDOMResponderContext,
Expand All @@ -277,29 +243,26 @@ function dispatchPressStartEvents(
): void {
state.isPressed = true;

if (state.pressEndTimeout !== null) {
context.clearTimeout(state.pressEndTimeout);
state.pressEndTimeout = null;
}

const dispatch = () => {
if (!state.isActivePressStart) {
state.isActivePressStart = true;
activate(event, context, props, state);
};
const nativeEvent: any = event.nativeEvent;
const {clientX: x, clientY: y} = state.touchEvent || nativeEvent;
const wasActivePressed = state.isActivePressed;
state.isActivePressed = true;
if (x !== undefined && y !== undefined) {
state.activationPosition = {x, y};
}

if (!state.isActivePressStart) {
const delayPressStart = calculateDelayMS(
props.delayPressStart,
0,
DEFAULT_PRESS_START_DELAY_MS,
dispatchEvent(
'onPressStart',
event,
context,
state,
'pressstart',
DiscreteEvent,
);
if (delayPressStart > 0) {
state.pressStartTimeout = context.setTimeout(() => {
state.pressStartTimeout = null;
dispatch();
}, delayPressStart);
} else {
dispatch();
if (!wasActivePressed) {
dispatchPressChangeEvent(context, state);
}
}
}
Expand All @@ -310,40 +273,20 @@ function dispatchPressEndEvents(
props: PressProps,
state: PressState,
): void {
const wasActivePressStart = state.isActivePressStart;
let activationWasForced = false;

state.isActivePressStart = false;
state.isPressed = false;

if (!wasActivePressStart && state.pressStartTimeout !== null) {
context.clearTimeout(state.pressStartTimeout);
state.pressStartTimeout = null;
// don't activate if a press has moved beyond the responder region
if (state.isPressWithinResponderRegion && event != null) {
// if we haven't yet activated (due to delays), activate now
activate(event, context, props, state);
activationWasForced = true;
}
}

if (state.isActivePressed) {
const delayPressEnd = calculateDelayMS(
props.delayPressEnd,
// if activation and deactivation occur during the same event there's no
// time for visual user feedback therefore a small delay is added before
// deactivating.
activationWasForced ? 10 : 0,
DEFAULT_PRESS_END_DELAY_MS,
state.isActivePressed = false;
dispatchEvent(
'onPressEnd',
event,
context,
state,
'pressend',
DiscreteEvent,
);
if (delayPressEnd > 0) {
state.pressEndTimeout = context.setTimeout(() => {
state.pressEndTimeout = null;
deactivate(event, context, props, state);
}, delayPressEnd);
} else {
deactivate(event, context, props, state);
}
dispatchPressChangeEvent(context, state);
}

state.responderRegionOnDeactivation = null;
Expand Down Expand Up @@ -380,11 +323,6 @@ function isValidKeyboardEvent(nativeEvent: Object): boolean {
);
}

function calculateDelayMS(delay: ?number, min = 0, fallback = 0) {
const maybeNumber = delay == null ? null : delay;
return Math.max(min, maybeNumber != null ? maybeNumber : fallback);
}

// TODO: account for touch hit slop
function calculateResponderRegion(
context: ReactDOMResponderContext,
Expand Down Expand Up @@ -550,7 +488,6 @@ const pressResponderImpl = {
isPressed: false,
isPressWithinResponderRegion: true,
pointerType: '',
pressEndTimeout: null,
pressStartTimeout: null,
pressTarget: null,
responderRegionOnActivation: null,
Expand Down
Loading

0 comments on commit 1912b4a

Please sign in to comment.