2023-09-18 16:14:33 -04:00
|
|
|
import { useMemo, useState } from 'react';
|
2023-06-21 04:10:07 -04:00
|
|
|
|
|
|
|
const NOOP = (_: boolean) => {};
|
|
|
|
|
2023-06-23 08:54:16 -07:00
|
|
|
const useToggle = ({ initialValue = false, closeDelay = 0, openDelay = 0, onToggle = NOOP } = {}) => {
|
2023-06-21 04:10:07 -04:00
|
|
|
const [isOpen, setIsOpen] = useState<boolean>(initialValue);
|
2023-06-23 08:54:16 -07:00
|
|
|
const [transition, setTransition] = useState<'opening' | 'closing' | null>(null);
|
|
|
|
const isOpening = transition === 'opening';
|
|
|
|
const isClosing = transition === 'closing';
|
|
|
|
const isTransitioning = transition !== null;
|
2023-06-21 04:10:07 -04:00
|
|
|
|
2023-09-18 16:14:33 -04:00
|
|
|
const toggleClose = useMemo(
|
|
|
|
() => () => {
|
2023-06-23 08:54:16 -07:00
|
|
|
setTransition('closing');
|
2023-06-21 04:10:07 -04:00
|
|
|
window.setTimeout(() => {
|
|
|
|
setIsOpen(false);
|
2023-06-23 08:54:16 -07:00
|
|
|
setTransition(null);
|
2023-06-21 04:10:07 -04:00
|
|
|
onToggle(false);
|
|
|
|
}, closeDelay);
|
2023-09-18 16:14:33 -04:00
|
|
|
},
|
|
|
|
[closeDelay, onToggle],
|
|
|
|
);
|
|
|
|
|
|
|
|
const toggleOpen = useMemo(
|
|
|
|
() => () => {
|
2023-06-23 08:54:16 -07:00
|
|
|
setTransition('opening');
|
|
|
|
window.setTimeout(() => {
|
|
|
|
setIsOpen(true);
|
|
|
|
setTransition(null);
|
|
|
|
onToggle(true);
|
|
|
|
}, openDelay);
|
2023-09-18 16:14:33 -04:00
|
|
|
},
|
|
|
|
[openDelay, onToggle],
|
|
|
|
);
|
|
|
|
|
|
|
|
const toggle = () => {
|
|
|
|
if (isOpen) {
|
|
|
|
toggleClose();
|
|
|
|
} else {
|
|
|
|
toggleOpen();
|
2023-06-21 04:10:07 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-09-18 16:14:33 -04:00
|
|
|
return { isOpen, isClosing, isOpening, isTransitioning, toggle, toggleOpen, toggleClose } as const;
|
2023-06-21 04:10:07 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
export default useToggle;
|