Skip to content

Commit df337e6

Browse files
committed
Add delay props to Press event module
1 parent a065260 commit df337e6

File tree

3 files changed

+390
-64
lines changed

3 files changed

+390
-64
lines changed

packages/react-events/src/Hover.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,11 @@ function dispatchHoverStartEvents(
115115
};
116116

117117
if (!state.isActiveHovered) {
118-
const delayHoverStart = calculateDelayMS(props.delayHoverStart, 0, DEFAULT_HOVER_START_DELAY_MS);
118+
const delayHoverStart = calculateDelayMS(
119+
props.delayHoverStart,
120+
0,
121+
DEFAULT_HOVER_START_DELAY_MS,
122+
);
119123
if (delayHoverStart > 0) {
120124
state.hoverStartTimeout = context.setTimeout(() => {
121125
state.hoverStartTimeout = null;
@@ -162,7 +166,11 @@ function dispatchHoverEndEvents(
162166
};
163167

164168
if (state.isActiveHovered) {
165-
const delayHoverEnd = calculateDelayMS(props.delayHoverEnd, 0, DEFAULT_HOVER_END_DELAY_MS);
169+
const delayHoverEnd = calculateDelayMS(
170+
props.delayHoverEnd,
171+
0,
172+
DEFAULT_HOVER_END_DELAY_MS,
173+
);
166174
if (delayHoverEnd > 0) {
167175
state.hoverEndTimeout = context.setTimeout(() => {
168176
deactivate();

packages/react-events/src/Press.js

Lines changed: 112 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,15 @@ type PressProps = {
2727

2828
type PressState = {
2929
defaultPrevented: boolean,
30+
isActivePressed: boolean,
31+
isActivePressStart: boolean,
3032
isAnchorTouched: boolean,
3133
isLongPressed: boolean,
3234
isPressed: boolean,
3335
longPressTimeout: null | TimeoutID,
3436
pressTarget: null | Element | Document,
37+
pressEndTimeout: null | TimeoutID,
38+
pressStartTimeout: null | TimeoutID,
3539
shouldSkipMouseAfterTouch: boolean,
3640
};
3741

@@ -49,9 +53,8 @@ type PressEvent = {|
4953
type: PressEventType,
5054
|};
5155

52-
// const DEFAULT_PRESS_DELAY_MS = 0;
53-
// const DEFAULT_PRESS_END_DELAY_MS = 0;
54-
// const DEFAULT_PRESS_START_DELAY_MS = 0;
56+
const DEFAULT_PRESS_END_DELAY_MS = 0;
57+
const DEFAULT_PRESS_START_DELAY_MS = 0;
5558
const DEFAULT_LONG_PRESS_DELAY_MS = 500;
5659

5760
const targetEventTypes = [
@@ -102,7 +105,7 @@ function dispatchPressChangeEvent(
102105
state: PressState,
103106
): void {
104107
const listener = () => {
105-
props.onPressChange(state.isPressed);
108+
props.onPressChange(state.isActivePressed);
106109
};
107110
dispatchEvent(context, state, 'presschange', listener);
108111
}
@@ -118,45 +121,93 @@ function dispatchLongPressChangeEvent(
118121
dispatchEvent(context, state, 'longpresschange', listener);
119122
}
120123

124+
function activate(context, props, state) {
125+
const wasActivePressed = state.isActivePressed;
126+
state.isActivePressed = true;
127+
128+
if (props.onPressStart) {
129+
dispatchEvent(context, state, 'pressstart', props.onPressStart);
130+
}
131+
if (!wasActivePressed && props.onPressChange) {
132+
dispatchPressChangeEvent(context, props, state);
133+
}
134+
}
135+
136+
function deactivate(context, props, state) {
137+
const wasLongPressed = state.isLongPressed;
138+
state.isActivePressed = false;
139+
state.isLongPressed = false;
140+
141+
if (props.onPressEnd) {
142+
dispatchEvent(context, state, 'pressend', props.onPressEnd);
143+
}
144+
if (props.onPressChange) {
145+
dispatchPressChangeEvent(context, props, state);
146+
}
147+
if (wasLongPressed && props.onLongPressChange) {
148+
dispatchLongPressChangeEvent(context, props, state);
149+
}
150+
}
151+
121152
function dispatchPressStartEvents(
122153
context: ResponderContext,
123154
props: PressProps,
124155
state: PressState,
125156
): void {
126157
state.isPressed = true;
127158

128-
if (props.onPressStart) {
129-
dispatchEvent(context, state, 'pressstart', props.onPressStart);
159+
if (state.pressEndTimeout !== null) {
160+
clearTimeout(state.pressEndTimeout);
161+
state.pressEndTimeout = null;
130162
}
131-
if (props.onPressChange) {
132-
dispatchPressChangeEvent(context, props, state);
133-
}
134-
if ((props.onLongPress || props.onLongPressChange) && !state.isLongPressed) {
135-
const delayLongPress = calculateDelayMS(
136-
props.delayLongPress,
137-
10,
138-
DEFAULT_LONG_PRESS_DELAY_MS,
139-
);
140163

141-
state.longPressTimeout = context.setTimeout(() => {
142-
state.isLongPressed = true;
143-
state.longPressTimeout = null;
144-
145-
if (props.onLongPress) {
146-
const listener = e => {
147-
props.onLongPress(e);
148-
// TODO address this again at some point
149-
// if (e.nativeEvent.defaultPrevented) {
150-
// state.defaultPrevented = true;
151-
// }
152-
};
153-
dispatchEvent(context, state, 'longpress', listener);
154-
}
164+
const dispatch = () => {
165+
state.isActivePressStart = true;
166+
activate(context, props, state);
167+
168+
if (
169+
(props.onLongPress || props.onLongPressChange) &&
170+
!state.isLongPressed
171+
) {
172+
const delayLongPress = calculateDelayMS(
173+
props.delayLongPress,
174+
10,
175+
DEFAULT_LONG_PRESS_DELAY_MS,
176+
);
177+
state.longPressTimeout = context.setTimeout(() => {
178+
state.isLongPressed = true;
179+
state.longPressTimeout = null;
180+
if (props.onLongPress) {
181+
const listener = e => {
182+
props.onLongPress(e);
183+
// TODO address this again at some point
184+
// if (e.nativeEvent.defaultPrevented) {
185+
// state.defaultPrevented = true;
186+
// }
187+
};
188+
dispatchEvent(context, state, 'longpress', listener);
189+
}
190+
if (props.onLongPressChange) {
191+
dispatchLongPressChangeEvent(context, props, state);
192+
}
193+
}, delayLongPress);
194+
}
195+
};
155196

156-
if (props.onLongPressChange) {
157-
dispatchLongPressChangeEvent(context, props, state);
158-
}
159-
}, delayLongPress);
197+
if (!state.isActivePressStart) {
198+
const delayPressStart = calculateDelayMS(
199+
props.delayPressStart,
200+
0,
201+
DEFAULT_PRESS_START_DELAY_MS,
202+
);
203+
if (delayPressStart > 0) {
204+
state.pressStartTimeout = context.setTimeout(() => {
205+
state.pressStartTimeout = null;
206+
dispatch();
207+
}, delayPressStart);
208+
} else {
209+
dispatch();
210+
}
160211
}
161212
}
162213

@@ -165,25 +216,36 @@ function dispatchPressEndEvents(
165216
props: PressProps,
166217
state: PressState,
167218
): void {
219+
const wasActivePressStart = state.isActivePressStart;
220+
221+
state.isActivePressStart = false;
222+
state.isPressed = false;
223+
168224
if (state.longPressTimeout !== null) {
169225
clearTimeout(state.longPressTimeout);
170226
state.longPressTimeout = null;
171227
}
172-
if (props.onPressEnd) {
173-
dispatchEvent(context, state, 'pressend', props.onPressEnd);
174-
}
175228

176-
if (state.isPressed) {
177-
state.isPressed = false;
178-
if (props.onPressChange) {
179-
dispatchPressChangeEvent(context, props, state);
180-
}
229+
if (!wasActivePressStart && state.pressStartTimeout !== null) {
230+
clearTimeout(state.pressStartTimeout);
231+
state.pressStartTimeout = null;
232+
// if we haven't yet activated (due to delays), activate now
233+
activate(context, props, state);
181234
}
182235

183-
if (state.isLongPressed) {
184-
state.isLongPressed = false;
185-
if (props.onLongPressChange) {
186-
dispatchLongPressChangeEvent(context, props, state);
236+
if (state.isActivePressed) {
237+
const delayPressEnd = calculateDelayMS(
238+
props.delayPressEnd,
239+
0,
240+
DEFAULT_PRESS_END_DELAY_MS,
241+
);
242+
if (delayPressEnd > 0) {
243+
state.pressEndTimeout = context.setTimeout(() => {
244+
state.pressEndTimeout = null;
245+
deactivate(context, props, state);
246+
}, delayPressEnd);
247+
} else {
248+
deactivate(context, props, state);
187249
}
188250
}
189251
}
@@ -208,12 +270,8 @@ function unmountResponder(
208270
state: PressState,
209271
): void {
210272
if (state.isPressed) {
211-
state.isPressed = false;
212273
dispatchPressEndEvents(context, props, state);
213-
if (state.longPressTimeout !== null) {
214-
clearTimeout(state.longPressTimeout);
215-
state.longPressTimeout = null;
216-
}
274+
context.removeRootEventTypes(rootEventTypes);
217275
}
218276
}
219277

@@ -222,10 +280,14 @@ const PressResponder = {
222280
createInitialState(): PressState {
223281
return {
224282
defaultPrevented: false,
283+
isActivePressed: false,
284+
isActivePressStart: false,
225285
isAnchorTouched: false,
226286
isLongPressed: false,
227287
isPressed: false,
228288
longPressTimeout: null,
289+
pressEndTimeout: null,
290+
pressStartTimeout: null,
229291
pressTarget: null,
230292
shouldSkipMouseAfterTouch: false,
231293
};

0 commit comments

Comments
 (0)