import { useControllableState } from "@radix-ui/react-use-controllable-state"; import { buttonProps, elementProps, mergeProps } from "@seed-design/dom-utils"; import { Primitive, type PrimitiveProps } from "@seed-design/react-primitive"; import * as React from "react"; export interface UseDismissibleProps { defaultOpen?: boolean; open?: boolean; onDismiss?: () => void; } export type UseDismissibleReturn = ReturnType; export function useDismissible(props: UseDismissibleProps) { const [open = true, setOpen] = useControllableState({ prop: props.open, defaultProp: props.defaultOpen, onChange: (open) => { if (!open) { props.onDismiss?.(); } }, }); const dismiss = React.useCallback(() => setOpen(false), [setOpen]); return { open, dismiss, rootProps: elementProps({}), dismissButtonProps: buttonProps({ onClick: (e) => { if (e.defaultPrevented) return; dismiss(); }, }), }; } const DismissibleContext = React.createContext | null>(null); export const DismissibleProvider = DismissibleContext.Provider; export const useDismissibleContext = () => { const context = React.useContext(DismissibleContext); if (context === null) { throw new Error("useDismissibleContext should be used within DismissibleProvider"); } return context; }; export interface DismissibleRootProps extends PrimitiveProps, UseDismissibleProps, React.HTMLAttributes {} export const DismissibleRoot = React.forwardRef( ({ defaultOpen, open, onDismiss, ...otherProps }, ref) => { const api = useDismissible({ defaultOpen, open, onDismiss }); if (!api.open) return null; return ( ); }, ); export interface DismissibleCloseButtonProps extends PrimitiveProps, React.HTMLAttributes {} export const DismissibleCloseButton = React.forwardRef< HTMLButtonElement, DismissibleCloseButtonProps >((props, ref) => { const { dismissButtonProps } = useDismissibleContext(); return ; });