import type { Accessor } from "solid-js"; import { createControllableSignal } from "./create-controllable-signal"; export interface CreateDisclosureStateOptions { open?: boolean | undefined; defaultOpen?: boolean | undefined; onOpenChange?: ((open: boolean) => void) | undefined; } export interface DisclosureState { isOpen: Accessor; open: () => void; close: () => void; toggle: () => void; } /** * Shared open/close state for all disclosure components (Dialog, Popover, * Tooltip, Collapsible, etc.). Wraps createControllableSignal with * convenience open/close/toggle methods. */ export function createDisclosureState(options: CreateDisclosureStateOptions): DisclosureState { const [isOpen, setIsOpen] = createControllableSignal({ value: () => options.open, defaultValue: () => options.defaultOpen ?? false, ...(options.onOpenChange !== undefined && { onChange: options.onOpenChange }), }); return { isOpen, open: () => setIsOpen(true), close: () => setIsOpen(false), // Imperative-only: do not call toggle() inside a reactive computation (effect/memo), // as isOpen() would create an unwanted reactive dependency there. toggle: () => setIsOpen(!isOpen()), }; }