import { type ViewStyle, type TextStyle } from "react-native"; import { type IconName } from "../icon/icon.js"; import { type ColorTokens, type FloatingLabelStyles } from "../../style/index.js"; export type Size = "small" | "base" | "large"; /** Where a field's `shortcut` keycap sits and which compact Kbd it is. */ export interface ShortcutSpec { endInset: number; gap: number; cap: "small" | "tiny"; } /** The interaction state a skin resolves colours for. */ export interface FieldState { focused: boolean; error: boolean; /** The trailing addon is the pressable action suffix (addonBox only). */ action?: boolean; } export interface InputSkin extends FloatingLabelStyles { /** The platform's compact outlined density, using the same editor and behavior. */ compact?: InputSkin; /** Clear material for the web skin. */ liquid?: boolean; /** Type scale per size; the field and its addons share it so they line up. */ text: (t: ColorTokens, size: Size) => TextStyle; /** Height of the single-line bare field. */ bareBox: (size: Size) => TextStyle; /** Total (border-box) height of the grouped layout, matching the bare field. * The shell enforces it as minHeight on the group container, so the row keeps * its height even when no addon box is present (icon-only groups). */ groupedHeight: (size: Size) => number; /** The bare field surface: shape, fill, border/underline for the active state. */ bareField: (t: ColorTokens, borderColor: keyof ColorTokens, focused: boolean, error: boolean) => TextStyle; /** The grouped (addon) outer: the row that shares one border/underline. */ groupContainer: (t: ColorTokens, borderColor: keyof ColorTokens, focused: boolean, error: boolean) => ViewStyle; /** The inner field inside the group (fills the field area; pads away from icons and * from prefix/suffix affixes so the value hugs an inline affix — see groupField). */ groupField: (t: ColorTokens, opts: { leadingIcon: boolean; trailingIcon: boolean; hasPrefix: boolean; hasSuffix: boolean; action?: boolean; }) => TextStyle; /** A prefix/suffix addon box. Stretches to the row height (alignItems stretch); * it must not set its own height, or it would re-inflate the container past * groupedHeight by the border/indicator band. The iOS box follows the field's * state (its divider and fill tint with focus and error); web and Android * ignore the state. */ addonBox: (t: ColorTokens, side: "left" | "right", state: FieldState) => ViewStyle; /** The addon's ink, and any type of its own (it is applied over the value type). */ addonText: (t: ColorTokens, side?: "left" | "right") => TextStyle; /** The action suffix's label, applied over the value type. */ actionText: (t: ColorTokens) => TextStyle; /** Glyph size (px) of the overlaid leading/trailing icon and the trailing action * glyphs (the password eye, the clear button). */ iconSize: number; /** The glyph colour by state. `action` is a pressable trailing glyph (eye, clear), * which the hand-off draws a step darker than the passive leading glyph. */ iconColor: (t: ColorTokens, state: FieldState & { action: boolean; }) => string; /** Gap between the above-field label and the field (the Field/Form rhythm). */ labelGap: number; /** The `search` field's own anatomy: the web's borderless toolbar row, the iOS * search field, the Material 3 search bar. A container with a fill takes a pane * under glass. */ search?: { container: (tokens: ColorTokens) => ViewStyle; /** The magnifier: its size, stroke and ink. */ icon: { size: number; bold: boolean; color: (tokens: ColorTokens) => string; }; field: (tokens: ColorTokens) => TextStyle; placeholder: (tokens: ColorTokens) => TextStyle; }; referenceLabel?: (tokens: ColorTokens) => TextStyle; softFill?: (tokens: ColorTokens) => string; /** Overlaid icon position inside the field area (left or right gutter). The shell * anchors it to the field-area wrapper — the container's CONTENT box — never to * the bordered container itself: the Android active indicator changes the * container's border/padding band on focus, and an overlay spanning that band * would re-center and visibly shift its icon by half the change. */ iconOverlay: (side: "left" | "right") => ViewStyle; /** Whether a pointer hover steps the resting edge to `subtle-foreground` (web only; * native pointer hover waits on the owner, src/style/hover.tsx). */ hover?: boolean; /** The halo around a focused box (a box-shadow spread), or null for none. */ focusHalo?: (t: ColorTokens, error: boolean) => ViewStyle | null; /** What a read-only field changes on its box (bare and grouped), by the field's state. */ readOnlyField?: (t: ColorTokens, state?: FieldState) => ViewStyle; /** * A frame drawn OVER a read-only field (the Android dashed edge with its subtle * underline just inside it), non-interactive and absolutely positioned, so it moves * neither the floating label nor the content box. The underline shows at rest; a * focused or errored field keeps its own active indicator instead. */ readOnlyFrame?: (t: ColorTokens) => { frame: ViewStyle; underline: ViewStyle; }; /** * The clear button as a filled disc with an x (web, iOS): the disc's diameter, the x's * size and the two inks. Without it the clear button is the plain circled-x glyph at * `iconSize` (Android). The button's box is never smaller than `iconSize`, so a disc * smaller than the glyphs (iOS) keeps the glyphs' touch geometry, centered in it. */ clearDisc?: { size: number; glyph: number; fill: (t: ColorTokens) => string; ink: (t: ColorTokens) => string; }; /** * The passive suffix is inline text in the field area, BEFORE the trailing glyphs (web, * Android). Without it the suffix is a boxed segment at the edge, after them (iOS). */ inlineSuffix?: boolean; /** An errored field with no clear or eye button shows a trailing alert glyph (Android). */ errorGlyph?: boolean; /** * The `shortcut` keycap at the field's end, per field size: the inset from the field's * end, the gap to the value (or to an inline suffix), and the compact Kbd step it takes. */ shortcut: (size: Size) => ShortcutSpec; /** * The password toggle's glyph while the value is masked and once it is revealed. Without * it the toggle is the iOS reference's order: eye.slash while masked, eye once revealed. */ revealGlyph?: { masked: IconName; revealed: IconName; }; /** * The caret a field held focused by an InteractionOverride draws after its value (the * bar's box and fill), since a pinned field is not the platform's focused input and shows * no native caret. Without it a pinned field draws none (iOS, Android). */ pinnedCaret?: (t: ColorTokens) => ViewStyle; /** The placeholder ink. */ placeholder: (t: ColorTokens) => string; /** Opacity applied to the field when disabled. */ disabledOpacity: number; /** iOS/web dim the action suffix on press; Android uses a ripple instead (null). */ pressedOpacity: number | null; /** Android ripple over the action suffix; null on iOS/web. */ ripple: ((t: ColorTokens) => { color: string; borderless: boolean; }) | null; /** The above-field label's whole type and ink: every skin supplies it, Android's too, * for the fields that cannot float their label there (a grouped Input, PhoneInput). */ labelAbove: NonNullable["labelAbove"]>; } export declare const webSkin: InputSkin; export declare const iosSkin: InputSkin; export declare const androidSkin: InputSkin; //# sourceMappingURL=input.styles.d.ts.map