/** sm 32px, md 40px, lg 48px high, matching the button scale; the hit area is padded to 44px. */ export type QuantityStepperSize = "sm" | "md" | "lg"; /** soft is a tonal fill; outline is a 1px control border on any surface. */ export type QuantityStepperVariant = "soft" | "outline"; /** Compact − qty + control. Display only: the number is never typed, which keeps it fast on mobile. */ export interface QuantityStepperProps { /** Controlled quantity; pair with `onValueChange`. */ value?: number; /** Starting quantity when uncontrolled; defaults to `min`. */ defaultValue?: number; /** Fires with the new clamped quantity after a plus or minus press; not fired when a limit blocks the change. */ onValueChange?: (value: number) => void; /** Lowest value; defaults to 1. At the floor the minus button is aria-disabled. */ min?: number; /** Highest value; omit for no ceiling. At the ceiling the plus button is aria-disabled. */ max?: number; /** Amount added or removed per press; defaults to 1. */ step?: number; /** Control height; defaults to `md`. */ size?: QuantityStepperSize; /** Surface style; defaults to `soft`. */ variant?: QuantityStepperVariant; /** At `min` the minus becomes a trash button that calls onRemove, for cart lines. */ removable?: boolean; /** Fires when the trash button is pressed at `min`; only reachable with `removable`. */ onRemove?: () => void; /** Dims the stepper and disables both buttons. */ disabled?: boolean; /** Product name, so the group reads "Quantity of Slim-Fit Denim Jacket". */ itemLabel?: string; /** Set on the group; the buttons get `-dec` and `-inc`. */ "data-testid"?: string; }