UNPKG

@gravity-ui/uikit

Version:

Gravity UI base styling and components

58 lines (57 loc) 2.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useSyntheticBlurEvent = useSyntheticBlurEvent; const tslib_1 = require("tslib"); const React = tslib_1.__importStar(require("react")); const SyntheticFocusEvent_1 = require("./SyntheticFocusEvent.js"); // React does not fire onBlur when an element is disabled https://github.com/facebook/react/issues/9142 function useSyntheticBlurEvent(onBlur) { const stateRef = React.useRef({ isFocused: false, observer: null, }); React.useEffect(() => { const state = stateRef.current; return () => { if (state.observer) { state.observer.disconnect(); state.observer = null; } }; }, []); const handleFocus = React.useCallback((event) => { const target = event.target; if (target instanceof HTMLButtonElement || target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement) { stateRef.current.isFocused = true; const handleBlur = (e) => { stateRef.current.isFocused = false; if (target.disabled) { onBlur?.(new SyntheticFocusEvent_1.SyntheticFocusEvent('blur', e)); } if (stateRef.current.observer) { stateRef.current.observer.disconnect(); stateRef.current.observer = null; } }; // TS can't resolve correct definition for addEventListener when target is union type // @ts-expect-error target.addEventListener('focusout', handleBlur, { once: true }); const observer = new MutationObserver(() => { if (stateRef.current.isFocused && target.disabled) { observer.disconnect(); stateRef.current.observer = null; const relatedTarget = target === document.activeElement ? null : document.activeElement; target.dispatchEvent(new FocusEvent('blur', { relatedTarget })); target.dispatchEvent(new FocusEvent('focusout', { relatedTarget, bubbles: true })); } }); observer.observe(target, { attributes: true, attributeFilter: ['disabled'] }); stateRef.current.observer = observer; } }, [onBlur]); return handleFocus; } //# sourceMappingURL=useSyntheticBlurEvent.js.map