import { type ReactNode } from 'react'; import { type ModalV2Size } from './modal-v2'; /** Layout: pass `children` for one column, or `leftColumn`+`rightColumn` for two. */ type AdminFormModalLayout = { children: ReactNode; leftColumn?: never; rightColumn?: never; } | { leftColumn: ReactNode; rightColumn: ReactNode; children?: never; }; type AdminFormModalBaseProps = { title: ReactNode; /** Secondary line under the title (what this record is, why it matters). */ subtitle?: ReactNode; isOpen: boolean; onClose: () => void; onSave: () => void; saveLabel: string; canSave?: boolean; saving?: boolean; /** * The entity is still being fetched — the modal was opened from a URL on a * cold load, so there is no list row to borrow from. Content is hidden behind * a placeholder and Save is held until the form has real values to submit. */ loading?: boolean; error?: string | null; /** * Placeholder to show while `loading`, for modals whose body is NOT a field * grid. The default bars imply a form; a modal that resolves into a list or a * table would visibly change shape when the data lands. */ loadingContent?: ReactNode; /** Secondary actions pinned to the footer's LEFT edge (Delete, Preview…). */ footerExtras?: ReactNode; /** * Additional PRIMARY actions, rendered next to Save (Publish, Mark * Complete…). A second primary action put in `footerExtras` lands at the far * left, a whole modal-width away from the button it belongs beside. */ footerActions?: ReactNode; /** Status text between the extras and the buttons (e.g. "3 rules selected"). */ footerStatus?: ReactNode; /** Unsaved edits exist: shows the footer chip and guards close with a confirm. */ dirty?: boolean; /** Names WHAT is dirty (chip tooltip) — turns "why is this dirty?!" into a hover. */ dirtyDetail?: string; /** * Panel width. Two-column layouts are always `wide` — passing * `leftColumn`/`rightColumn` upgrades this automatically. */ size?: ModalV2Size; contentClassName?: string; }; /** * THE admin form-modal shell: header, scrolling content (one column or two), an * error line, and a Cancel/Save footer with optional extra actions. * * Every admin form modal renders this rather than reassembling `ModalV2` + * header + footer by hand. Three copies of the same shell had already been * written in one feature (repo form, rule form, bindings), which is how the * Save button ends up saying "Saving…" in one place and spinning silently in * another. * * Width is a `size` variant, never a call-site `max-w-*` — the widths had * drifted across seven values (`max-w-md` through `max-w-[1400px]`) for modals * doing the same job. */ export declare function AdminFormModal({ title, subtitle, isOpen, onClose, onSave, saveLabel, canSave, saving, loading, error, loadingContent, footerExtras, footerActions, footerStatus, dirty, dirtyDetail, size, contentClassName, children, leftColumn, rightColumn, }: AdminFormModalBaseProps & AdminFormModalLayout): import("react").JSX.Element | null; export {}; //# sourceMappingURL=admin-form-modal.d.ts.map