Revert focus event PRs (#18655)
* Revert "Further cleanup to before/after blur (#18649)" This reverts commit e2ccbf0358fafc8eb4470a45f5bca1cb97a4bba2. * Revert "Unify Flare FocusWithin responder with useFocusWithin (#18636)" This reverts commit f24a9e70980c2b1d0eb8309eb751315ff39f96bd.
Dominic Gannaway committed
Apr 17, 2020 at 16:27 UTC
58c895e59cd2822a9a7a67606d5fe7da5e09ba2a
4 files changed
+65
-56
packages/react-dom/src/client/ReactDOMComponent.js
+4
@@ -1355,6 +1355,10 @@ export function listenToEventResponderEventTypes(
1355
const targetEventType = isPassive
1356
? eventType
1357
: eventType.substring(0, eventType.length - 7);
1358
+ // We don't listen to this as we actually emulate it in the host config
1359
+ if (targetEventType === 'beforeblur') {
1360
+ continue;
1361
+ }
1362
if (!listenerMap.has(eventKey)) {
1363
if (isPassive) {
1364
const activeKey = targetEventType + '_active';
packages/react-dom/src/client/ReactDOMHostConfig.js
+31
-2
@@ -62,6 +62,7 @@ import {REACT_OPAQUE_ID_TYPE} from 'shared/ReactSymbols';
62
import {
63
mountEventResponder,
64
unmountEventResponder,
65
+ DEPRECATED_dispatchEventForResponderEventSystem,
66
} from '../events/DeprecatedDOMEventResponderSystem';
67
import {retryIfBlockedOn} from '../events/ReactDOMEventReplaying';
68
@@ -73,6 +74,8 @@ import {
74
enableScopeAPI,
75
} from 'shared/ReactFeatureFlags';
76
import {
77
+ RESPONDER_EVENT_SYSTEM,
78
+ IS_PASSIVE,
79
PLUGIN_EVENT_SYSTEM,
80
USE_EVENT_SYSTEM,
81
} from '../events/EventSystemFlags';
@@ -525,9 +528,22 @@ function createEvent(type: TopLevelType): Event {
528
}
529
530
function dispatchBeforeDetachedBlur(target: HTMLElement): void {
531
+ const targetInstance = getClosestInstanceFromNode(target);
532
((selectionInformation: any): SelectionInformation).activeElementDetached = target;
533
530
- if (enableDeprecatedFlareAPI || enableUseEventAPI) {
534
+ if (enableDeprecatedFlareAPI) {
535
+ DEPRECATED_dispatchEventForResponderEventSystem(
536
+ 'beforeblur',
537
+ targetInstance,
538
+ ({
539
+ target,
540
+ timeStamp: Date.now(),
541
+ }: any),
542
+ target,
543
+ RESPONDER_EVENT_SYSTEM | IS_PASSIVE,
544
+ );
545
+ }
546
+ if (enableUseEventAPI) {
547
const event = createEvent(TOP_BEFORE_BLUR);
548
// Dispatch "beforeblur" directly on the target,
549
// so it gets picked up by the event system and
@@ -537,7 +553,20 @@ function dispatchBeforeDetachedBlur(target: HTMLElement): void {
553
}
554
555
function dispatchAfterDetachedBlur(target: HTMLElement): void {
540
- if (enableDeprecatedFlareAPI || enableUseEventAPI) {
556
+ if (enableDeprecatedFlareAPI) {
557
+ DEPRECATED_dispatchEventForResponderEventSystem(
558
+ 'blur',
559
+ null,
560
+ ({
561
+ isTargetAttached: false,
562
+ target,
563
+ timeStamp: Date.now(),
564
+ }: any),
565
+ target,
566
+ RESPONDER_EVENT_SYSTEM | IS_PASSIVE,
567
+ );
568
+ }
569
+ if (enableUseEventAPI) {
570
const event = createEvent(TOP_AFTER_BLUR);
571
// So we know what was detached, make the relatedTarget the
572
// detached target on the "afterblur" event.
packages/react-interactions/events/src/dom/DeprecatedFocus.js
+15
-39
@@ -22,7 +22,7 @@ import {DiscreteEvent} from 'shared/ReactTypes';
22
*/
23
24
type FocusEvent = {|
25
- relatedTarget: null | Element | Document,
25
+ isTargetAttached: boolean,
26
target: Element | Document,
27
type: FocusEventType | FocusWithinEventType,
28
pointerType: PointerType,
@@ -53,7 +53,6 @@ type FocusEventType = 'focus' | 'blur' | 'focuschange' | 'focusvisiblechange';
53
type FocusWithinProps = {
54
disabled?: boolean,
55
onFocusWithin?: (e: FocusEvent) => void,
56
- onAfterBlurWithin?: (e: FocusEvent) => void,
56
onBeforeBlurWithin?: (e: FocusEvent) => void,
57
onBlurWithin?: (e: FocusEvent) => void,
58
onFocusWithinChange?: boolean => void,
@@ -66,8 +65,7 @@ type FocusWithinEventType =
65
| 'focuswithinchange'
66
| 'blurwithin'
67
| 'focuswithin'
69
- | 'beforeblurwithin'
70
- | 'afterblurwithin';
68
+ | 'beforeblurwithin';
69
70
/**
71
* Shared between Focus and FocusWithin
@@ -118,7 +116,8 @@ const focusVisibleEvents = hasPointerEvents
116
117
const targetEventTypes = ['focus', 'blur', 'beforeblur', ...focusVisibleEvents];
118
121
-const rootEventTypes = ['afterblur'];
119
+// Used only for the blur "detachedTarget" logic
120
+const rootEventTypes = ['blur'];
121
122
function addWindowEventListener(types, callback, options) {
123
types.forEach(type => {
@@ -193,10 +192,10 @@ function createFocusEvent(
192
type: FocusEventType | FocusWithinEventType,
193
target: Element | Document,
194
pointerType: PointerType,
196
- relatedTarget: null | Element | Document,
195
+ isTargetAttached: boolean,
196
): FocusEvent {
197
return {
199
- relatedTarget,
198
+ isTargetAttached,
199
target,
200
type,
201
pointerType,
@@ -298,7 +297,7 @@ function dispatchFocusEvents(
297
'focus',
298
target,
299
pointerType,
301
- null,
300
+ true,
301
);
302
context.dispatchEvent(syntheticEvent, onFocus, DiscreteEvent);
303
}
@@ -322,7 +321,7 @@ function dispatchBlurEvents(
321
'blur',
322
target,
323
pointerType,
325
- null,
324
+ true,
325
);
326
context.dispatchEvent(syntheticEvent, onBlur, DiscreteEvent);
327
}
@@ -347,7 +346,7 @@ function dispatchFocusWithinEvents(
346
'focuswithin',
347
target,
348
pointerType,
350
- null,
349
+ true,
350
);
351
context.dispatchEvent(syntheticEvent, onFocusWithin, DiscreteEvent);
352
}
@@ -362,39 +361,19 @@ function dispatchBlurWithinEvents(
361
const pointerType = state.pointerType;
362
const target = ((state.focusTarget: any): Element | Document) || event.target;
363
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
- null,
371
+ isTargetAttached,
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 onAfterBlurWithin = (props.onAfterBlurWithin: any);
385
- const relatedTarget = state.detachedTarget;
386
- if (isFunction(onAfterBlurWithin) && relatedTarget !== null) {
387
- const syntheticEvent = createFocusEvent(
388
- context,
389
- 'afterblurwithin',
390
- relatedTarget,
391
- pointerType,
392
- relatedTarget,
393
- );
394
- context.dispatchEvent(syntheticEvent, onAfterBlurWithin, DiscreteEvent);
395
- }
396
-}
397
-
377
function dispatchFocusChange(
378
context: ReactDOMResponderContext,
379
props: FocusProps,
@@ -637,7 +616,7 @@ const focusWithinResponderImpl = {
616
'beforeblurwithin',
617
event.target,
618
state.pointerType,
640
- null,
619
+ true,
620
);
621
state.detachedTarget = event.target;
622
context.dispatchEvent(
@@ -681,13 +660,10 @@ const focusWithinResponderImpl = {
660
props: FocusWithinProps,
661
state: FocusState,
662
): void {
684
- if (event.type === 'afterblur') {
663
+ if (event.type === 'blur') {
664
const detachedTarget = state.detachedTarget;
686
- if (
687
- detachedTarget !== null &&
688
- detachedTarget === event.nativeEvent.relatedTarget
689
- ) {
690
- dispatchAfterBlurWithinEvents(context, event, props, state);
665
+ if (detachedTarget !== null && detachedTarget === event.target) {
666
+ dispatchBlurWithinEvents(context, event, props, state);
667
state.detachedTarget = null;
668
if (state.addedRootEvents) {
669
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, onAfterBlurWithin, ref, innerRef, innerRef2;
293
+ let onBeforeBlurWithin, onBlurWithin, ref, innerRef, innerRef2;
294
295
beforeEach(() => {
296
onBeforeBlurWithin = jest.fn();
297
- onAfterBlurWithin = jest.fn();
297
+ onBlurWithin = 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
- onAfterBlurWithin,
308
+ onBlurWithin,
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(onAfterBlurWithin).toHaveBeenCalledTimes(0);
325
+ expect(onBlurWithin).toHaveBeenCalledTimes(0);
326
ReactDOM.render(<Component show={false} />, container);
327
expect(onBeforeBlurWithin).toHaveBeenCalledTimes(1);
328
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(1);
329
- expect(onAfterBlurWithin).toHaveBeenCalledWith(
330
- expect.objectContaining({relatedTarget: inner}),
328
+ expect(onBlurWithin).toHaveBeenCalledTimes(1);
329
+ expect(onBlurWithin).toHaveBeenCalledWith(
330
+ expect.objectContaining({isTargetAttached: false}),
331
);
332
});
333
@@ -336,7 +336,7 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => {
336
const Component = ({show}) => {
337
const listener = useFocusWithin({
338
onBeforeBlurWithin,
339
- onAfterBlurWithin,
339
+ onBlurWithin,
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(onAfterBlurWithin).toHaveBeenCalledTimes(0);
360
+ expect(onBlurWithin).toHaveBeenCalledTimes(0);
361
ReactDOM.render(<Component show={false} />, container);
362
expect(onBeforeBlurWithin).toHaveBeenCalledTimes(1);
363
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(1);
364
- expect(onAfterBlurWithin).toHaveBeenCalledWith(
365
- expect.objectContaining({relatedTarget: inner}),
363
+ expect(onBlurWithin).toHaveBeenCalledTimes(1);
364
+ expect(onBlurWithin).toHaveBeenCalledWith(
365
+ expect.objectContaining({isTargetAttached: false}),
366
);
367
});
368
@@ -418,7 +418,7 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => {
418
const Component = ({show}) => {
419
const listener = useFocusWithin({
420
onBeforeBlurWithin,
421
- onAfterBlurWithin,
421
+ onBlurWithin,
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(onAfterBlurWithin).toHaveBeenCalledTimes(0);
447
+ expect(onBlurWithin).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(onAfterBlurWithin).toHaveBeenCalledTimes(1);
457
+ expect(onBlurWithin).toHaveBeenCalledTimes(1);
458
resolve();
459
460
document.body.removeChild(container2);