import { useCallback, useMemo } from 'react';
import { useControllableState } from '../primitives/controllable-state';
export interface UseDisclosureOptions {
defaultOpen?: boolean;
/** Controlled open state. Pass this to drive it from outside. */
open?: boolean;
onOpenChange?: (open: boolean) => void;
}
export interface UseDisclosureResult {
isOpen: boolean;
open: () => void;
close: () => void;
toggle: () => void;
/** Spread onto Dialog, BottomSheet or Select. */
props: { open: boolean; onOpenChange: (open: boolean) => void };
}
/**
* Open/closed state for an overlay.
*
* The same controlled-or-uncontrolled pattern Dialog, BottomSheet and Select
* implement internally, lifted out for when you need to drive one from
* elsewhere — closing a sheet after a request settles, say.
*
* ```tsx
* const sheet = useDisclosure();
*
* …
* ```
*/
export function useDisclosure({
defaultOpen = false,
open: controlledOpen,
onOpenChange,
}: UseDisclosureOptions = {}): UseDisclosureResult {
const { value: isOpen, setValue: setOpen } = useControllableState({
value: controlledOpen,
defaultValue: defaultOpen,
onChange: onOpenChange,
});
const open = useCallback(() => setOpen(true), [setOpen]);
const close = useCallback(() => setOpen(false), [setOpen]);
const toggle = useCallback(() => setOpen(!isOpen), [setOpen, isOpen]);
return useMemo(
() => ({ isOpen, open, close, toggle, props: { open: isOpen, onOpenChange: setOpen } }),
[isOpen, open, close, toggle, setOpen]
);
}