import { type ReactNode } from "react"; import { TextInput } from "react-native"; import { type ColorTokens, type StyleProp, type ViewStyle, type TextStyle } from "../../style/index.js"; export type Size = "small" | "base" | "large"; export interface StepperProps { /** Controlled numeric value (clamped to [min, max] for display); omit for uncontrolled use. */ value?: number; /** Initial value for uncontrolled use (a bare steps out of the box). Default `min`. */ defaultValue?: number; /** Fired with the next clamped value when ±, or direct entry, changes it (both modes). */ onChange?: (next: number) => void; /** E2E hook forwarded to the group container. */ testID?: string; /** Lower bound. Default 0. The − button disables when value <= min. */ min?: number; /** Upper bound. Default Number.MAX_SAFE_INTEGER. The + button disables when value >= max. */ max?: number; /** Increment/decrement amount for the ± buttons. Default 1. */ step?: number; /** * The control's persistent, component-owned label. When set it renders as a * VISIBLE title ABOVE the ± control (mirroring Input's above-field placement, * per-OS type from the skin) and becomes the group's programmatic name (wired via * accessibilityLabel + aria-labelledby). When omitted, the control keeps the * invisible "Number" accessible-name fallback and renders no visible label, so a * bare `` looks exactly as before. */ label?: string; /** Optional muted secondary line rendered under the label (parity with Input). Takes effect only alongside `label`. */ description?: ReactNode; /** * Marks the control required: appends a destructive "*" to the label (hidden from * the accessible name) and sets aria-required on the group/field. Takes effect only * alongside `label`. */ required?: boolean; small?: boolean; large?: boolean; disabled?: boolean; /** Outer layout composition only (width/flex within a parent), never a restyle hook. */ style?: StyleProp; } export interface StepperSkin { /** The outer group container (the [ − | value | + ] shell shape). */ group: (t: ColorTokens, size: Size, disabled: boolean) => ViewStyle; /** One ± button cell; `side` lets the skin round the matching outer corner. */ button: (t: ColorTokens, size: Size, side: "left" | "right", disabled: boolean, pressed: boolean) => ViewStyle; /** The editable center field surface (and its type scale). */ field: (t: ColorTokens, size: Size, disabled: boolean) => TextStyle; /** Divider line between a button and the value (null = no separator on this skin). */ divider: ((t: ColorTokens, disabled: boolean) => ViewStyle) | null; /** The ± glyph color token and px size for a given size/state. */ glyph: (t: ColorTokens, size: Size, disabled: boolean) => { color: keyof ColorTokens; size: number; }; /** * Web dims a ± button on press. null on Android (ripple carries the feedback) * and on iOS (the skin's `button` paints a highlight fill on the pressed half * instead — the iOS 27 stepper never dims its glyph). */ pressedOpacity: number | null; /** Android ripple over a ± button; null on iOS/web. */ ripple: ((t: ColorTokens) => { color: string; borderless: boolean; }) | null; /** * Uniform hitSlop (px per edge) padding a ± button's touch target out to the * platform minimum (Android M3 48dp); null = no padding (web, and iOS where * Apple's own 32pt UIStepper sets the precedent). */ hitSlop: ((size: Size) => number) | null; /** Layout order: the iOS HIG puts the value field to the LEFT of the [ − | + ] pill. */ fieldOnLeft: boolean; /** * The persistent label rendered ABOVE the control (the canonical field-label * type, matching Input's label scale): iOS the SF field-label (semibold 600, * -0.15 tracking), web the 500-weight title, Android the M3 label (medium, M3 * tracking). The floating M3 in-container label Input uses does not apply — a ± * button row has no filled field box to float a label into — so Android keeps the * component-owned title above, at the M3 label type. */ labelAbove: (t: ColorTokens, size: Size) => TextStyle; /** The muted secondary description line under the label (per-OS supporting-text type). */ description: (t: ColorTokens, size: Size) => TextStyle; } /** Build a Stepper component from a platform skin. */ export declare function createStepper(skin: StepperSkin): import("react").ForwardRefExoticComponent>; //# sourceMappingURL=stepper.shared.d.ts.map