/** * Single source of truth for the card-entry responsive layout. * * The real card-entry form (`UnifiedCardEntry` in the core-flows app) and the * React/Vue/Angular skeleton loaders all render the same grid. Historically the * form drove the inline↔two-row switch from JS (a ResizeObserver toggling React * state) while the skeletons hard-coded their own guesses, so the two drifted. * * This module defines the grid templates and the breakpoint ONCE, as pure data * plus a CSS builder, so every consumer reflows at exactly the same width via a * CSS container query — no JS width measurement, nothing to keep in sync. */ export type CardEntryInputName = 'card-number' | 'expiration' | 'cvv'; /** * Minimum width (px) each field needs before the row is too cramped and the * layout drops to two rows. Mirrors the real form's field sizing. */ export declare const CARD_ENTRY_MIN_WIDTHS: Record; /** Notional gap (px) between fields, summed into the reflow breakpoint. */ export declare const CARD_ENTRY_SLOT_GAP_PX = 8; /** Field row height — matches the real form's `3rem` grid rows. */ export declare const CARD_ENTRY_ROW_HEIGHT = "3rem"; export declare const CARD_ENTRY_ROW_HEIGHT_PX = 48; /** 1px accent line between rows / between exp & cvv in the two-row layout. */ export declare const CARD_ENTRY_DIVIDER_PX = 1; /** * The form draws its fields inside a 1px border, so the query container (the * full iframe width) is 2px wider than the field row that `minRowWidth` * describes. The breakpoint bakes this in so form and skeleton flip together. */ export declare const CARD_ENTRY_BORDER_PX = 1; /** * The form insets its box by this much on every side (Tailwind `m-0.5`) so the * focus ring has room and isn't clipped at the iframe edge. It adds to the box's * rendered height, so the skeleton's height guess includes it to avoid a jump * when the loaded form replaces the skeleton. */ export declare const CARD_ENTRY_MARGIN_PX = 2; export type CardEntryConfig = { /** Mounted fields, in DOM/visual order. */ inputs: CardEntryInputName[]; /** Whether the animated card-brand icon renders left of the PAN slot. */ hasIcon?: boolean; /** Whether the layout may drop to two rows when narrow (default true). */ allowTwoRow?: boolean; }; export type CardEntryDivider = { area: string; orientation: 'v' | 'h'; }; export type CardEntryLayout = { /** grid-template for the wide (inline) layout. */ inline: string; /** grid-template for the narrow (two-row) layout, or null if it never reflows. */ twoRow: string | null; /** * Container width (px) below which the two-row layout applies, measured on the * query container (full iframe width, incl. the form's border). Null when the * config never reflows. */ breakpointPx: number | null; /** grid-area names that hold a field, in DOM order (same in both layouts). */ fieldAreas: string[]; /** Whether an `icon` area is present (both layouts). */ hasIconArea: boolean; /** Accent-line elements shown only in the two-row layout. */ twoRowDividers: CardEntryDivider[]; }; /** Resolve the full layout (templates + breakpoint + areas) for a config. */ export declare function buildCardEntryLayout({ inputs, hasIcon, allowTwoRow, }: CardEntryConfig): CardEntryLayout; /** * Container-query CSS that switches `gridSelector` between the inline and * two-row templates at the layout's breakpoint. The element matched by * `gridSelector` must be a descendant of a `container-type: inline-size` * ancestor named `containerName`. * * `extraBaseRules` are emitted before the `@container` block (e.g. the default * hidden state of two-row-only dividers); `extraCompactRules` are emitted inside * it (e.g. revealing those dividers / hiding wide-only chrome). Keeping the base * state first ensures the compact rules win when the query matches. */ export declare function buildCardEntryGridCss({ gridSelector, layout, containerName, extraBaseRules, extraCompactRules, }: { gridSelector: string; layout: CardEntryLayout; containerName?: string; extraBaseRules?: string; extraCompactRules?: string; }): string;