import type * as React from 'react'; import type { AutoFocusEvent } from '../utils/dismissal.js'; import type { PassThroughProps } from '../utils/passThrough.js'; import type { PortalProps } from '../utils/portal.js'; import type { PrimitivePropsWithRef } from '../utils/primitive.js'; import type { FocusOutsideEvent, InteractOutsideEvent } from '../utils/useDismiss.js'; /** * Viewport edge (logical: `start`/`end` mirror under `dir="rtl"`; `top`/`bottom` physical). */ export type DrawerPlacement = 'start' | 'end' | 'top' | 'bottom'; /** * Dismissal policy — `any` (Escape + outside), `escape`, `outside`, or `none`; events fire regardless, this only decides if an un-prevented one closes the drawer. */ export type DrawerDismiss = 'any' | 'escape' | 'outside' | 'none'; /** * Props for the {@link Drawer} root. Standard attributes ({@link * PassThroughProps}) land on the derived `DrawerContent` panel. */ export interface DrawerProps extends PassThroughProps { /** * The trigger and portal, typically — the drawer's own DOM is rendered via {@link DrawerPortal}. * @default undefined */ children?: React.ReactNode | undefined; /** * Whether the drawer is open, for controlled usage. Pair with `onOpenChange`. * @default undefined — uncontrolled, tracks its own open state internally. */ open?: boolean | undefined; /** * Whether the drawer is initially open, for uncontrolled usage. * @default false */ defaultOpen?: boolean | undefined; /** * Fires with the new open state whenever the drawer opens or closes, controlled or not. * @default undefined — no-op if omitted. */ onOpenChange?: ((open: boolean) => void) | undefined; /** * Fires once the open/close animation settles, for work that must not race the transition. * @default undefined */ onOpenChangeComplete?: ((open: boolean) => void) | undefined; /** * Viewport edge, logical so it mirrors under `dir="rtl"`, surfaced as `data-placement`. * @default 'end' */ placement?: DrawerPlacement | undefined; /** * Whether the drawer traps focus, locks scroll, and blocks page interaction; `false` leaves the page interactive. * @default true */ modal?: boolean | undefined; /** * Dismissal policy — `'any'`, `'escape'`, `'outside'`, or `'none'` — reflected as `data-dismiss` on Content; the drawer dismisses on outside interaction whether modal or not, and this is the only way to disable it. * @default 'any' */ dismiss?: DrawerDismiss | undefined; /** * The derived panel's title, rendered as a `DrawerTitle`; only read when `children` is plain body content. * @default undefined — no derived title. */ title?: string | undefined; /** * The derived panel's description, rendered as a `DrawerDescription`; only read when `children` is plain body content. * @default undefined — no derived description. */ description?: string | undefined; /** * Content rendered after the body in the derived panel — typically the action buttons; only read when `children` is plain body content. * @default undefined — no footer. */ footer?: React.ReactNode | undefined; /** * Whether the derived panel can be dismissed at all — `false` forces `dismiss="none"` and withholds the close button. * @default true */ dismissible?: boolean | undefined; /** * Panel thickness rung the skin reads, fed to the derived `DrawerContent`. * @default undefined — the skin's own default thickness. */ size?: 'sm' | 'md' | 'lg' | (string & {}) | undefined; /** * DOM node the derived Portal renders the overlay into, so it inherits that subtree's theme and stacking context (e.g. a `[data-skdx-theme]` wrapper). * @default undefined — `document.body`. */ portalContainer?: Element | DocumentFragment | null | undefined; } /** Props for {@link DrawerTrigger}, the button that opens the drawer. */ export interface DrawerTriggerProps extends PrimitivePropsWithRef<'button'> { } /** Props for {@link DrawerPortal}, which teleports its children to `document.body`. */ export interface DrawerPortalProps extends PortalProps { /** * Keep portal mounted while closed (useful for exit animation libraries). * @default false */ forceMount?: boolean | undefined; } /** Props for {@link DrawerOverlay}, the scrim rendered behind `DrawerContent`. */ export interface DrawerOverlayProps extends PrimitivePropsWithRef<'div'> { /** * Keep overlay mounted while closed (useful for exit animation libraries). * @default false */ forceMount?: boolean | undefined; } /** Props for {@link DrawerContent}, the drawer's sliding panel. */ export interface DrawerContentProps extends PrimitivePropsWithRef<'div'> { /** * Panel thickness rung the skin reads, mirrored to `data-size` on the panel. * @default undefined — the skin's own default thickness. */ size?: 'sm' | 'md' | 'lg' | (string & {}) | undefined; /** * Keep panel mounted while closed (useful for exit animation libraries). * @default false */ forceMount?: boolean | undefined; /** * Fires on Escape, modal or non-modal; call `event.preventDefault()` to prevent close. * @default undefined */ onEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined; /** * Fires on pointer-down outside; call `event.preventDefault()` to prevent close. * @default undefined */ onPointerDownOutside?: ((event: PointerEvent) => void) | undefined; /** * Fires when focus moves outside, a cancelable stand-in for `focusin`; call `event.preventDefault()` to prevent close. * @default undefined */ onFocusOutside?: ((event: FocusOutsideEvent) => void) | undefined; /** * Fires for pointer-down or focus outside, before the specific handlers; one `preventDefault()` vetoes either. * @default undefined */ onInteractOutside?: ((event: InteractOutsideEvent) => void) | undefined; /** * Fires before focus enters on open, modal only; call `event.preventDefault()` to place focus yourself. * @default focus moves to first tabbable element. */ onOpenAutoFocus?: ((event: AutoFocusEvent) => void) | undefined; /** * Fires before focus returns on close — always for modal, only when the user had moved focus inside for non-modal; call `event.preventDefault()` to suppress the return. * @default focus returns to pre-open focus or Trigger. */ onCloseAutoFocus?: ((event: AutoFocusEvent) => void) | undefined; /** * CSS selector for the element to focus on open, resolved inside the panel and applied only when `onOpenAutoFocus` isn't vetoed; falls back to the first tabbable element. * @default first tabbable element. */ initialFocus?: string | undefined; /** * CSS selector for the element to focus on close, resolved at document level and applied only when `onCloseAutoFocus` isn't vetoed; falls back to the pre-open focus. * @default pre-open focus. */ finalFocus?: string | undefined; } /** Props for {@link DrawerTitle}, the drawer's accessible name. */ export interface DrawerTitleProps extends PrimitivePropsWithRef<'h2'> { } /** Props for {@link DrawerDescription}, the drawer's accessible description. */ export interface DrawerDescriptionProps extends PrimitivePropsWithRef<'p'> { } /** Props for {@link DrawerClose}, a button that closes the drawer. */ export interface DrawerCloseProps extends PrimitivePropsWithRef<'button'> { }