MCPcopy Index your code
hub / github.com/adobe/react-spectrum / useSyntheticBlurEvent

Function useSyntheticBlurEvent

packages/react-aria/src/interactions/utils.ts:37–111  ·  view source on GitHub ↗
(
  onBlur: (e: ReactFocusEvent<Target>) => void
)

Source from the content-addressed store, hash-verified

35}
36
37export function useSyntheticBlurEvent<Target extends Element = Element>(
38 onBlur: (e: ReactFocusEvent<Target>) => void
39): (e: ReactFocusEvent<Target>) => void {
40 let stateRef = useRef({
41 isFocused: false,
42 observer: null as MutationObserver | null
43 });
44
45 // Clean up MutationObserver on unmount. See below.
46
47 useLayoutEffect(() => {
48 const state = stateRef.current;
49 return () => {
50 if (state.observer) {
51 state.observer.disconnect();
52 state.observer = null;
53 }
54 };
55 }, []);
56
57 // This function is called during a React onFocus event.
58 return useCallback(
59 (e: ReactFocusEvent<Target>) => {
60 // React does not fire onBlur when an element is disabled. https://github.com/facebook/react/issues/9142
61 // Most browsers fire a native focusout event in this case, except for Firefox. In that case, we use a
62 // MutationObserver to watch for the disabled attribute, and dispatch these events ourselves.
63 // For browsers that do, focusout fires before the MutationObserver, so onBlur should not fire twice.
64 let eventTarget = getEventTarget(e);
65 if (
66 eventTarget instanceof HTMLButtonElement ||
67 eventTarget instanceof HTMLInputElement ||
68 eventTarget instanceof HTMLTextAreaElement ||
69 eventTarget instanceof HTMLSelectElement
70 ) {
71 stateRef.current.isFocused = true;
72
73 let target = eventTarget;
74 let onBlurHandler: EventListenerOrEventListenerObject | null = e => {
75 stateRef.current.isFocused = false;
76
77 if (target.disabled) {
78 // For backward compatibility, dispatch a (fake) React synthetic event.
79 let event = createSyntheticEvent<ReactFocusEvent<Target>>(e);
80 onBlur?.(event);
81 }
82
83 // We no longer need the MutationObserver once the target is blurred.
84 if (stateRef.current.observer) {
85 stateRef.current.observer.disconnect();
86 stateRef.current.observer = null;
87 }
88 };
89
90 target.addEventListener('focusout', onBlurHandler, {once: true});
91
92 stateRef.current.observer = new MutationObserver(() => {
93 if (stateRef.current.isFocused && target.disabled) {
94 stateRef.current.observer?.disconnect();

Callers 2

useFocusFunction · 0.90
useFocusWithinFunction · 0.90

Calls 3

getEventTargetFunction · 0.90
getActiveElementFunction · 0.90
addEventListenerMethod · 0.80

Tested by

no test coverage detected