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

Unify Flare FocusWithin responder with useFocusWithin (#18636)

Dominic Gannaway committed Apr 16, 2020 at 19:35 UTC f24a9e70980c2b1d0eb8309eb751315ff39f96bd
3 files changed +53 -32
packages/react-dom/src/client/ReactDOMHostConfig.js
+2 -3
@@ -555,11 +555,10 @@ function dispatchBeforeDetachedBlur(target: HTMLElement): void {
555 function dispatchAfterDetachedBlur(target: HTMLElement): void {
556 if (enableDeprecatedFlareAPI) {
557 DEPRECATED_dispatchEventForResponderEventSystem(
558 - 'blur',
558 + 'afterblur',
559 null,
560 ({
561 - isTargetAttached: false,
562 - target,
561 + relatedTarget: target,
562 timeStamp: Date.now(),
563 }: any),
564 target,
packages/react-interactions/events/src/dom/DeprecatedFocus.js
+36 -14
@@ -22,7 +22,7 @@ import {DiscreteEvent} from 'shared/ReactTypes';
22 */
23
24 type FocusEvent = {|
25 - isTargetAttached: boolean,
25 + relatedTarget: null | Element | Document,
26 target: Element | Document,
27 type: FocusEventType | FocusWithinEventType,
28 pointerType: PointerType,
@@ -53,6 +53,7 @@ type FocusEventType = 'focus' | 'blur' | 'focuschange' | 'focusvisiblechange';
53 type FocusWithinProps = {
54 disabled?: boolean,
55 onFocusWithin?: (e: FocusEvent) => void,
56 + onAfterBlurWithin?: (e: FocusEvent) => void,
57 onBeforeBlurWithin?: (e: FocusEvent) => void,
58 onBlurWithin?: (e: FocusEvent) => void,
59 onFocusWithinChange?: boolean => void,
@@ -65,7 +66,8 @@ type FocusWithinEventType =
66 | 'focuswithinchange'
67 | 'blurwithin'
68 | 'focuswithin'
68 - | 'beforeblurwithin';
69 + | 'beforeblurwithin'
70 + | 'afterblurwithin';
71
72 /**
73 * Shared between Focus and FocusWithin
@@ -116,8 +118,7 @@ const focusVisibleEvents = hasPointerEvents
118
119 const targetEventTypes = ['focus', 'blur', 'beforeblur', ...focusVisibleEvents];
120
119 -// Used only for the blur "detachedTarget" logic
120 -const rootEventTypes = ['blur'];
121 +const rootEventTypes = ['afterblur'];
122
123 function addWindowEventListener(types, callback, options) {
124 types.forEach(type => {
@@ -192,10 +193,10 @@ function createFocusEvent(
193 type: FocusEventType | FocusWithinEventType,
194 target: Element | Document,
195 pointerType: PointerType,
195 - isTargetAttached: boolean,
196 + relatedTarget: null | Element | Document,
197 ): FocusEvent {
198 return {
198 - isTargetAttached,
199 + relatedTarget,
200 target,
201 type,
202 pointerType,
@@ -297,7 +298,7 @@ function dispatchFocusEvents(
298 'focus',
299 target,
300 pointerType,
300 - true,
301 + null,
302 );
303 context.dispatchEvent(syntheticEvent, onFocus, DiscreteEvent);
304 }
@@ -321,7 +322,7 @@ function dispatchBlurEvents(
322 'blur',
323 target,
324 pointerType,
324 - true,
325 + null,
326 );
327 context.dispatchEvent(syntheticEvent, onBlur, DiscreteEvent);
328 }
@@ -346,7 +347,7 @@ function dispatchFocusWithinEvents(
347 'focuswithin',
348 target,
349 pointerType,
349 - true,
350 + null,
351 );
352 context.dispatchEvent(syntheticEvent, onFocusWithin, DiscreteEvent);
353 }
@@ -361,19 +362,40 @@ function dispatchBlurWithinEvents(
362 const pointerType = state.pointerType;
363 const target = ((state.focusTarget: any): Element | Document) || event.target;
364 const onBlurWithin = (props.onBlurWithin: any);
364 - const isTargetAttached = state.detachedTarget === null;
365 if (isFunction(onBlurWithin)) {
366 const syntheticEvent = createFocusEvent(
367 context,
368 'blurwithin',
369 target,
370 pointerType,
371 - isTargetAttached,
371 + null,
372 );
373 context.dispatchEvent(syntheticEvent, onBlurWithin, DiscreteEvent);
374 }
375 }
376
377 +function dispatchAfterBlurWithinEvents(
378 + context: ReactDOMResponderContext,
379 + event: ReactDOMResponderEvent,
380 + props: FocusWithinProps,
381 + state: FocusState,
382 +) {
383 + const pointerType = state.pointerType;
384 + const target = ((state.focusTarget: any): Element | Document) || event.target;
385 + const onAfterBlurWithin = (props.onAfterBlurWithin: any);
386 + const relatedTarget = state.detachedTarget;
387 + if (isFunction(onAfterBlurWithin)) {
388 + const syntheticEvent = createFocusEvent(
389 + context,
390 + 'afterblurwithin',
391 + target,
392 + pointerType,
393 + relatedTarget,
394 + );
395 + context.dispatchEvent(syntheticEvent, onAfterBlurWithin, DiscreteEvent);
396 + }
397 +}
398 +
399 function dispatchFocusChange(
400 context: ReactDOMResponderContext,
401 props: FocusProps,
@@ -616,7 +638,7 @@ const focusWithinResponderImpl = {
638 'beforeblurwithin',
639 event.target,
640 state.pointerType,
619 - true,
641 + null,
642 );
643 state.detachedTarget = event.target;
644 context.dispatchEvent(
@@ -660,10 +682,10 @@ const focusWithinResponderImpl = {
682 props: FocusWithinProps,
683 state: FocusState,
684 ): void {
663 - if (event.type === 'blur') {
685 + if (event.type === 'afterblur') {
686 const detachedTarget = state.detachedTarget;
687 if (detachedTarget !== null && detachedTarget === event.target) {
666 - dispatchBlurWithinEvents(context, event, props, state);
688 + dispatchAfterBlurWithinEvents(context, event, props, state);
689 state.detachedTarget = null;
690 if (state.addedRootEvents) {
691 state.addedRootEvents = false;
packages/react-interactions/events/src/dom/__tests__/FocusWithin-test.internal.js
+15 -15
@@ -290,11 +290,11 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => {
290 });
291
292 describe('onBeforeBlurWithin', () => {
293 - let onBeforeBlurWithin, onBlurWithin, ref, innerRef, innerRef2;
293 + let onBeforeBlurWithin, onAfterBlurWithin, ref, innerRef, innerRef2;
294
295 beforeEach(() => {
296 onBeforeBlurWithin = jest.fn();
297 - onBlurWithin = jest.fn();
297 + onAfterBlurWithin = jest.fn();
298 ref = React.createRef();
299 innerRef = React.createRef();
300 innerRef2 = React.createRef();
@@ -305,7 +305,7 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => {
305 const Component = ({show}) => {
306 const listener = useFocusWithin({
307 onBeforeBlurWithin,
308 - onBlurWithin,
308 + onAfterBlurWithin,
309 });
310 return (
311 <div ref={ref} DEPRECATED_flareListeners={listener}>
@@ -322,12 +322,12 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => {
322 target.keydown({key: 'Tab'});
323 target.focus();
324 expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
325 - expect(onBlurWithin).toHaveBeenCalledTimes(0);
325 + expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
326 ReactDOM.render(<Component show={false} />, container);
327 expect(onBeforeBlurWithin).toHaveBeenCalledTimes(1);
328 - expect(onBlurWithin).toHaveBeenCalledTimes(1);
329 - expect(onBlurWithin).toHaveBeenCalledWith(
330 - expect.objectContaining({isTargetAttached: false}),
328 + expect(onAfterBlurWithin).toHaveBeenCalledTimes(1);
329 + expect(onAfterBlurWithin).toHaveBeenCalledWith(
330 + expect.objectContaining({relatedTarget: inner}),
331 );
332 });
333
@@ -336,7 +336,7 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => {
336 const Component = ({show}) => {
337 const listener = useFocusWithin({
338 onBeforeBlurWithin,
339 - onBlurWithin,
339 + onAfterBlurWithin,
340 });
341 return (
342 <div ref={ref} DEPRECATED_flareListeners={listener}>
@@ -357,12 +357,12 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => {
357 target.keydown({key: 'Tab'});
358 target.focus();
359 expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
360 - expect(onBlurWithin).toHaveBeenCalledTimes(0);
360 + expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
361 ReactDOM.render(<Component show={false} />, container);
362 expect(onBeforeBlurWithin).toHaveBeenCalledTimes(1);
363 - expect(onBlurWithin).toHaveBeenCalledTimes(1);
364 - expect(onBlurWithin).toHaveBeenCalledWith(
365 - expect.objectContaining({isTargetAttached: false}),
363 + expect(onAfterBlurWithin).toHaveBeenCalledTimes(1);
364 + expect(onAfterBlurWithin).toHaveBeenCalledWith(
365 + expect.objectContaining({relatedTarget: inner}),
366 );
367 });
368
@@ -418,7 +418,7 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => {
418 const Component = ({show}) => {
419 const listener = useFocusWithin({
420 onBeforeBlurWithin,
421 - onBlurWithin,
421 + onAfterBlurWithin,
422 });
423
424 return (
@@ -444,7 +444,7 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => {
444 target.keydown({key: 'Tab'});
445 target.focus();
446 expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
447 - expect(onBlurWithin).toHaveBeenCalledTimes(0);
447 + expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
448
449 suspend = true;
450 root.render(<Component />);
@@ -454,7 +454,7 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => {
454 '<div><input style="display: none;">Loading...</div>',
455 );
456 expect(onBeforeBlurWithin).toHaveBeenCalledTimes(1);
457 - expect(onBlurWithin).toHaveBeenCalledTimes(1);
457 + expect(onAfterBlurWithin).toHaveBeenCalledTimes(1);
458 resolve();
459
460 document.body.removeChild(container2);