import { type ReactNode } from "react"; import { type TextInput as RNTextInput } from "react-native"; import { type ColorTokens, type ViewStyle, type TextStyle, type LayoutStyle } 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 buttons, adjustment keys, or direct entry change 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 and adjustment keys. 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 (decorative, * never in the accessible name) and announces the control as required, * * through * aria-required on the web's numeric field and with the word in its name ("Quantity, * required") on iOS and Android. * * * with the word in its name ("Quantity, required"). * * The star takes effect only alongside `label`. */ required?: boolean; /** * A unit or note beside the control, 16 px after it on the same line ("× 4px", * "items"): a string is set in the 400 13 px subtle ink, a node as it is. Unlike * `description`, it reads as part of the value's line. */ suffix?: ReactNode; small?: boolean; large?: boolean; disabled?: boolean; /** Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds. */ style?: LayoutStyle; } export interface StepperSkin { /** Clear Liquid Glass text entry on the web appearance. */ liquid?: boolean; /** * The outer group container (the [ − | value | + ] shell shape). `focused` is the * value field holding focus: a skin whose group has a border paints its focus state * there (the web box turns its border `ring`) and sets `groupShowsFocus`. */ group: (t: ColorTokens, size: Size, disabled: boolean, focused: boolean) => ViewStyle; /** * The group's border is the value field's keyboard focus indicator, so the field * suppresses the browser's ring. A skin whose field sits bare (no box of its own to * paint) leaves it unset, and the field keeps the kit's themed ring. */ groupShowsFocus?: boolean; /** 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; /** A ± button's wash under a hovering pointer; omit for none. */ buttonHover?: (t: ColorTokens) => 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 and px size; `off` is a button at its bound (or the whole control disabled). */ glyph: (t: ColorTokens, size: Size, off: boolean) => { color: string; 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 control's opacity when disabled (solid mode). */ disabledOpacity: number; /** * 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 secondary description line under the control (per-OS supporting-text type). */ description: (t: ColorTokens, size: Size) => TextStyle; /** A string `suffix`'s type beside the control. */ suffix: (t: ColorTokens) => TextStyle; } export declare function sizeOf(p: StepperProps): Size; export declare function createStepper(skin: StepperSkin): import("react").ForwardRefExoticComponent>; //# sourceMappingURL=stepper.shared.d.ts.map