import "./drawer.css"; import type * as React from "react"; import { type ReactNode } from "react"; import { Dialog as Base } from "@base-ui/react/dialog"; import { useRender } from "@base-ui/react/use-render"; import { type StyleProps } from "@lotics/ui/style_props"; /** * The panel's inset — the ONE left edge the header, `DrawerScrollArea` and the * footer all sit on. * * `DrawerScrollArea` applies it, so an ordinary body never names this. It is * exported for the surfaces that cannot use it — a MIXED body and a PINNED one — * where a hardcoded `20` silently stops matching the day this one moves. */ export declare const DRAWER_GUTTER = 20; export interface DrawerProps extends StyleProps { open: boolean; onOpenChange: (open: boolean) => void; /** Header title. A string renders as the standard title; a node renders as-is. */ title?: ReactNode; /** * Panel width on non-small screens (number = px, or a `%` string). Rarely set — * the ONE standard width (600) fits record side-panels and lighter detail * alike. Full-width on small screens. */ width?: number | `${number}%`; /** * Record sequencing — step to the previous/next record WITHOUT closing the * drawer. Renders ◀ ▶ chevrons in the header and binds ←/→ while the drawer is * open (ignored while typing in a field). Pass `undefined` at either end of the * list to disable that side. */ onPrev?: () => void; onNext?: () => void; /** * WHERE IN THE SET this record is, as the PAIR — the caption between the * chevrons is worded from the active locale pack (`shape.position`). The pair * rather than the sentence, because the words belong to the pack and nothing in * a string prop can say so. `index` is the reader's ordinal — the FIRST record * is 1, not 0. */ position?: { index: number; total: number; }; /** * Drawer body — a BARE flex column filling the panel below the header, so a * full-bleed child reaches the panel edge. Wrap content in `DrawerScrollArea` * to get the panel's gutter; a `DrawerFooter` goes last, after it. */ children: ReactNode; testID?: string; /** * Where the overlay MOUNTS — Base UI's own portal target. Unset, it is the * nearest `PortalHost`, and the document where there is none: an overlay opened * from inside a host belongs in that host's DOM tree, which is what the host's * focus trap is scoped to. Pass `null` to send it to the document regardless. */ container?: HTMLElement | null; ref?: React.Ref; render?: Base.Popup.Props["render"]; } /** * A right-docked overlay panel: a scrim over the surface plus a full-height panel * pinned to the right edge. Use it for secondary content that should sit beside * the main surface without leaving it — a comment thread, a record side-panel — * where a centered Dialog would feel heavy. Controlled via `open`/`onOpenChange`; * the panel goes full-width on small screens. * * FOCUS OPENS ON THE PANEL, and the pager comes after the record — in the DOM, so * in tab order: the first thing a keyboard reader can act on must not be the * control that replaces what they opened. */ export declare function Drawer(props: DrawerProps): React.JSX.Element; export interface DrawerScrollAreaProps extends StyleProps { children: ReactNode; /** * The IDENTITY of the content in the scroller — a record id, a step name. * * Set it on a drawer that SWAPS its body in place. Changing it opens the new * content at the top and restores the previous content's offset when the key * comes back. Omit it on a drawer whose body is one thing. */ scrollKey?: string; ref?: React.Ref; render?: useRender.RenderProp; } /** * The scrolling, guttered content region of a `Drawer` — the counterpart of * `DialogScrollArea`, and what applies `DRAWER_GUTTER`. * * It ALWAYS scrolls, and there is deliberately no flag to stop it: a padded box * holding a `flex:1` scroller insets that scroller's VIEWPORT, so the list clips * short of the panel with dead space beneath it. A surface that needs a pinned * region above a scrolling one goes in the `Drawer`'s bare slot, and a body that * must reach the panel edge does NOT wrap in this. */ export declare function DrawerScrollArea(props: DrawerScrollAreaProps): React.JSX.Element; export interface DrawerFooterProps extends StyleProps { /** The action(s) — typically right-aligned `Button`s. Prepend a * `` hint to push them right with a summary on the left. */ children: ReactNode; ref?: React.Ref; render?: useRender.RenderProp; } /** * The pinned action bar at the bottom of a `Drawer` — a hairline-topped band (the * same chrome as `CardFooter` / `DialogFooter`). Render it as the LAST child of * the `Drawer`, after the scroll body; the body's `flex:1` pins it to the panel * bottom. */ export declare function DrawerFooter(props: DrawerFooterProps): React.ReactElement>;