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