UNPKG

@gechiui/compose

Version:
82 lines (73 loc) 3.02 kB
/** * GeChiUI dependencies */ import { useRef, useEffect, useCallback } from '@gechiui/element'; import { ESCAPE } from '@gechiui/keycodes'; /** * Internal dependencies */ import useConstrainedTabbing from '../use-constrained-tabbing'; import useFocusOnMount from '../use-focus-on-mount'; import useFocusReturn from '../use-focus-return'; import useFocusOutside from '../use-focus-outside'; import useMergeRefs from '../use-merge-refs'; /* eslint-disable jsdoc/valid-types */ /** * @typedef DialogOptions * @property {Parameters<useFocusOnMount>[0]} focusOnMount Focus on mount arguments. * @property {() => void} onClose Function to call when the dialog is closed. */ /* eslint-enable jsdoc/valid-types */ /** * Returns a ref and props to apply to a dialog wrapper to enable the following behaviors: * - constrained tabbing. * - focus on mount. * - return focus on unmount. * - focus outside. * * @param {DialogOptions} options Dialog Options. */ function useDialog(options) { /** * @type {import('react').MutableRefObject<DialogOptions | undefined>} */ const currentOptions = useRef(); useEffect(() => { currentOptions.current = options; }, Object.values(options)); const constrainedTabbingRef = useConstrainedTabbing(); const focusOnMountRef = useFocusOnMount(options.focusOnMount); const focusReturnRef = useFocusReturn(); const focusOutsideProps = useFocusOutside(event => { var _currentOptions$curre, _currentOptions$curre2; // This unstable prop is here only to manage backward compatibility // for the Popover component otherwise, the onClose should be enough. // @ts-ignore unstable property if ((_currentOptions$curre = currentOptions.current) !== null && _currentOptions$curre !== void 0 && _currentOptions$curre.__unstableOnClose) { // @ts-ignore unstable property currentOptions.current.__unstableOnClose('focus-outside', event); } else if ((_currentOptions$curre2 = currentOptions.current) !== null && _currentOptions$curre2 !== void 0 && _currentOptions$curre2.onClose) { currentOptions.current.onClose(); } }); const closeOnEscapeRef = useCallback(node => { if (!node) { return; } node.addEventListener('keydown', ( /** @type {KeyboardEvent} */ event) => { var _currentOptions$curre3; // Close on escape if (event.keyCode === ESCAPE && !event.defaultPrevented && (_currentOptions$curre3 = currentOptions.current) !== null && _currentOptions$curre3 !== void 0 && _currentOptions$curre3.onClose) { event.preventDefault(); currentOptions.current.onClose(); } }); }, []); return [useMergeRefs([options.focusOnMount !== false ? constrainedTabbingRef : null, options.focusOnMount !== false ? focusReturnRef : null, options.focusOnMount !== false ? focusOnMountRef : null, closeOnEscapeRef]), { ...focusOutsideProps, tabIndex: '-1' }]; } export default useDialog; //# sourceMappingURL=index.js.map