@samitouri / QOS-React-2 / commits / e276a5e850

[Flare] Remove delay props from Hover (#16248)

Moving working with delays into user-space.

Nicolas Gallagher committed Jul 30, 2019 at 09:29 UTC e276a5e85046c2cf336f623d975b1af01b251b5e
3 files changed +5 -259
packages/react-events/docs/Hover.md
+3 -17
@@ -37,16 +37,6 @@ type HoverEvent = {
37
38 ## Props
39
40 -### delayHoverEnd: number
41 -
42 -The duration of the delay between when hover ends and when `onHoverEnd` is
43 -called.
44 -
45 -### delayHoverStart: number
46 -
47 -The duration of the delay between when hover starts and when `onHoverStart` is
48 -called.
49 -
40 ### disabled: boolean
41
42 Disables all `Hover` events.
@@ -58,19 +48,15 @@ Called when the element changes hover state (i.e., after `onHoverStart` and
48
49 ### onHoverEnd: (e: HoverEvent) => void
50
61 -Called once the element is no longer hovered. It will be cancelled if the
62 -pointer leaves the element before the `delayHoverStart` threshold is exceeded.
51 +Called once the element is no longer hovered.
52
53 ### onHoverMove: (e: HoverEvent) => void
54
66 -Called when the pointer moves within the hit bounds of the element. `onHoverMove` is
67 -called immediately and doesn't wait for delayed `onHoverStart`.
55 +Called when the pointer moves within the hit bounds of the element.
56
57 ### onHoverStart: (e: HoverEvent) => void
58
71 -Called once the element is hovered. It will not be called if the pointer leaves
72 -the element before the `delayHoverStart` threshold is exceeded. And it will not
73 -be called more than once before `onHoverEnd` is called.
59 +Called once the element is hovered.
60
61 ### preventDefault: boolean = true
62
packages/react-events/src/dom/Hover.js
+2 -43
@@ -24,8 +24,6 @@ type HoverListenerProps = {|
24
25 type HoverProps = {
26 disabled: boolean,
27 - delayHoverEnd: number,
28 - delayHoverStart: number,
27 preventDefault: boolean,
28 };
29
@@ -55,9 +53,6 @@ type HoverEvent = {|
53 y: null | number,
54 |};
55
58 -const DEFAULT_HOVER_END_DELAY_MS = 0;
59 -const DEFAULT_HOVER_START_DELAY_MS = 0;
60 -
56 const targetEventTypes = [
57 'pointerover',
58 'pointermove',
@@ -136,7 +131,7 @@ function dispatchHoverStartEvents(
131 state.hoverEndTimeout = null;
132 }
133
139 - const activate = () => {
134 + if (!state.isActiveHovered) {
135 state.isActiveHovered = true;
136 const syntheticEvent = createHoverEvent(
137 event,
@@ -146,22 +141,6 @@ function dispatchHoverStartEvents(
141 );
142 context.dispatchEvent('onHoverStart', syntheticEvent, UserBlockingEvent);
143 dispatchHoverChangeEvent(event, context, props, state);
149 - };
150 -
151 - if (!state.isActiveHovered) {
152 - const delayHoverStart = calculateDelayMS(
153 - props.delayHoverStart,
154 - 0,
155 - DEFAULT_HOVER_START_DELAY_MS,
156 - );
157 - if (delayHoverStart > 0) {
158 - state.hoverStartTimeout = context.setTimeout(() => {
159 - state.hoverStartTimeout = null;
160 - activate();
161 - }, delayHoverStart);
162 - } else {
163 - activate();
164 - }
144 }
145 }
146
@@ -188,7 +167,7 @@ function dispatchHoverEndEvents(
167 state.hoverStartTimeout = null;
168 }
169
191 - const deactivate = () => {
170 + if (state.isActiveHovered) {
171 state.isActiveHovered = false;
172
173 const syntheticEvent = createHoverEvent(
@@ -202,29 +181,9 @@ function dispatchHoverEndEvents(
181 state.hoverTarget = null;
182 state.ignoreEmulatedMouseEvents = false;
183 state.isTouched = false;
205 - };
206 -
207 - if (state.isActiveHovered) {
208 - const delayHoverEnd = calculateDelayMS(
209 - props.delayHoverEnd,
210 - 0,
211 - DEFAULT_HOVER_END_DELAY_MS,
212 - );
213 - if (delayHoverEnd > 0) {
214 - state.hoverEndTimeout = context.setTimeout(() => {
215 - deactivate();
216 - }, delayHoverEnd);
217 - } else {
218 - deactivate();
219 - }
184 }
185 }
186
223 -function calculateDelayMS(delay: ?number, min = 0, fallback = 0) {
224 - const maybeNumber = delay == null ? null : delay;
225 - return Math.max(min, maybeNumber != null ? maybeNumber : fallback);
226 -}
227 -
187 function unmountResponder(
188 context: ReactDOMResponderContext,
189 props: HoverProps,
packages/react-events/src/dom/__tests__/Hover-test.internal.js
-199
@@ -167,97 +167,6 @@ describe('Hover event responder', () => {
167 );
168 expect(onHoverStart).not.toBeCalled();
169 });
170 -
171 - describe('delayHoverStart', () => {
172 - it('can be configured', () => {
173 - const Component = () => {
174 - useHoverListener({
175 - onHoverStart: onHoverStart,
176 - });
177 - return (
178 - <div
179 - ref={ref}
180 - responders={<HoverResponder delayHoverStart={2000} />}
181 - />
182 - );
183 - };
184 - ReactDOM.render(<Component />, container);
185 -
186 - ref.current.dispatchEvent(createEvent('pointerover'));
187 - jest.advanceTimersByTime(1999);
188 - expect(onHoverStart).not.toBeCalled();
189 - jest.advanceTimersByTime(1);
190 - expect(onHoverStart).toHaveBeenCalledTimes(1);
191 - });
192 -
193 - it('is reset if "pointerout" is dispatched during a delay', () => {
194 - const Component = () => {
195 - useHoverListener({
196 - onHoverStart: onHoverStart,
197 - });
198 - return (
199 - <div
200 - ref={ref}
201 - responders={<HoverResponder delayHoverStart={500} />}
202 - />
203 - );
204 - };
205 - ReactDOM.render(<Component />, container);
206 -
207 - ref.current.dispatchEvent(createEvent('pointerover'));
208 - jest.advanceTimersByTime(499);
209 - ref.current.dispatchEvent(createEvent('pointerout'));
210 - jest.advanceTimersByTime(1);
211 - expect(onHoverStart).not.toBeCalled();
212 - ref.current.dispatchEvent(createEvent('pointerover'));
213 - jest.runAllTimers();
214 - expect(onHoverStart).toHaveBeenCalledTimes(1);
215 - });
216 -
217 - it('onHoverStart is called synchronously if delay is 0ms', () => {
218 - const Component = () => {
219 - useHoverListener({
220 - onHoverStart: onHoverStart,
221 - });
222 - return (
223 - <div
224 - ref={ref}
225 - responders={<HoverResponder delayHoverStart={0} />}
226 - />
227 - );
228 - };
229 - ReactDOM.render(<Component />, container);
230 -
231 - ref.current.dispatchEvent(createEvent('pointerover'));
232 - expect(onHoverStart).toHaveBeenCalledTimes(1);
233 - });
234 -
235 - it('onHoverStart is only called once per active hover', () => {
236 - const Component = () => {
237 - useHoverListener({
238 - onHoverStart: onHoverStart,
239 - });
240 - return (
241 - <div
242 - ref={ref}
243 - responders={
244 - <HoverResponder delayHoverStart={500} delayHoverEnd={100} />
245 - }
246 - />
247 - );
248 - };
249 - ReactDOM.render(<Component />, container);
250 -
251 - ref.current.dispatchEvent(createEvent('pointerover'));
252 - jest.advanceTimersByTime(500);
253 - expect(onHoverStart).toHaveBeenCalledTimes(1);
254 - ref.current.dispatchEvent(createEvent('pointerout'));
255 - jest.advanceTimersByTime(10);
256 - ref.current.dispatchEvent(createEvent('pointerover'));
257 - jest.runAllTimers();
258 - expect(onHoverStart).toHaveBeenCalledTimes(1);
259 - });
260 - });
170 });
171
172 describe('onHoverChange', () => {
@@ -399,114 +308,6 @@ describe('Hover event responder', () => {
308 ref.current.dispatchEvent(createEvent('mouseout'));
309 expect(onHoverEnd).not.toBeCalled();
310 });
402 -
403 - describe('delayHoverEnd', () => {
404 - it('can be configured', () => {
405 - const Component = () => {
406 - useHoverListener({
407 - onHoverEnd,
408 - });
409 - return (
410 - <div
411 - ref={ref}
412 - responders={<HoverResponder delayHoverEnd={2000} />}
413 - />
414 - );
415 - };
416 - ReactDOM.render(<Component />, container);
417 -
418 - ref.current.dispatchEvent(createEvent('pointerover'));
419 - ref.current.dispatchEvent(createEvent('pointerout'));
420 - jest.advanceTimersByTime(1999);
421 - expect(onHoverEnd).not.toBeCalled();
422 - jest.advanceTimersByTime(1);
423 - expect(onHoverEnd).toHaveBeenCalledTimes(1);
424 - });
425 -
426 - it('delayHoverEnd is called synchronously if delay is 0ms', () => {
427 - const Component = () => {
428 - useHoverListener({
429 - onHoverEnd,
430 - });
431 - return (
432 - <div ref={ref} responders={<HoverResponder delayHoverEnd={0} />} />
433 - );
434 - };
435 - ReactDOM.render(<Component />, container);
436 -
437 - ref.current.dispatchEvent(createEvent('pointerover'));
438 - ref.current.dispatchEvent(createEvent('pointerout'));
439 - expect(onHoverEnd).toHaveBeenCalledTimes(1);
440 - });
441 -
442 - it('onHoverEnd is only called once per active hover', () => {
443 - const Component = () => {
444 - useHoverListener({
445 - onHoverEnd,
446 - });
447 - return (
448 - <div
449 - ref={ref}
450 - responders={<HoverResponder delayHoverEnd={500} />}
451 - />
452 - );
453 - };
454 - ReactDOM.render(<Component />, container);
455 -
456 - ref.current.dispatchEvent(createEvent('pointerover'));
457 - ref.current.dispatchEvent(createEvent('pointerout'));
458 - jest.advanceTimersByTime(499);
459 - ref.current.dispatchEvent(createEvent('pointerover'));
460 - jest.advanceTimersByTime(100);
461 - ref.current.dispatchEvent(createEvent('pointerout'));
462 - jest.runAllTimers();
463 - expect(onHoverEnd).toHaveBeenCalledTimes(1);
464 - });
465 -
466 - it('onHoverEnd is not called if "pointerover" is dispatched during a delay', () => {
467 - const Component = () => {
468 - useHoverListener({
469 - onHoverEnd,
470 - });
471 - return (
472 - <div
473 - ref={ref}
474 - responders={<HoverResponder delayHoverEnd={500} />}
475 - />
476 - );
477 - };
478 - ReactDOM.render(<Component />, container);
479 -
480 - ref.current.dispatchEvent(createEvent('pointerover'));
481 - ref.current.dispatchEvent(createEvent('pointerout'));
482 - jest.advanceTimersByTime(499);
483 - ref.current.dispatchEvent(createEvent('pointerover'));
484 - jest.advanceTimersByTime(1);
485 - expect(onHoverEnd).not.toBeCalled();
486 - });
487 -
488 - it('onHoverEnd is not called if there was no active hover', () => {
489 - const Component = () => {
490 - useHoverListener({
491 - onHoverEnd,
492 - });
493 - return (
494 - <div
495 - ref={ref}
496 - responders={
497 - <HoverResponder delayHoverStart={500} delayHoverEnd={100} />
498 - }
499 - />
500 - );
501 - };
502 - ReactDOM.render(<Component />, container);
503 -
504 - ref.current.dispatchEvent(createEvent('pointerover'));
505 - ref.current.dispatchEvent(createEvent('pointerout'));
506 - jest.runAllTimers();
507 - expect(onHoverEnd).not.toBeCalled();
508 - });
509 - });
311 });
312
313 describe('onHoverMove', () => {