import React from 'react'; import type { AriaNumberFieldProps } from 'react-aria'; export type NumberInputSize = 'sm' | 'md' | 'lg'; type NumberInputDOMProps = Omit, keyof AriaNumberFieldProps | 'size' | 'type' | 'min' | 'max' | 'step' | 'disabled' | 'value' | 'defaultValue' | 'onChange'>; export interface NumberInputProps extends Omit, NumberInputDOMProps { /** * Controlled value. `null` is empty — never `NaN`, which is what the * underlying hook uses and which fails every `===` check a caller writes. */ value?: number | null; /** Uncontrolled starting value. `null` for empty. */ defaultValue?: number | null; /** * Fires when the value is committed — on blur, Enter, a step button or an * arrow key — not on every keystroke. `null` when the field was cleared. */ onChange?: (value: number | null) => void; /** Matches Input's `size`: Small, Medium, Large. */ size?: NumberInputSize; /** * The − and + buttons. On by default; turn off for a dense table cell where * the arrow keys are enough. */ showStepper?: boolean; /** Class names for the control box (`.ion-input`). */ className?: string; /** Class names for the `.ion-field` wrapper when a label or helper is shown. */ wrapperClassName?: string; } /** * NumberInput — a quantity, with formatting, bounds and steps. * * NOT ``, and the list of reasons is the component: * * It scrolls. A focused `type="number"` changes value under the mouse wheel, * so a user scrolling the page past a price field edits the price. The wheel * is OFF here by default (`isWheelDisabled`), and a caller has to ask for it. * * It cannot format. "1,234.50", "€12", "15%" are text to the browser's number * input, which rejects them. `formatOptions` takes `Intl.NumberFormatOptions`, * so currency, percent and units display and parse in the user's locale — * including "1.234,50" for a German user. * * It is not a number to the browser's validation either. `type="text"` with * the right `inputMode` gets the numeric keyboard on a phone without * Firefox letting letters in and Chrome silently reporting an empty value. * * EMPTY IS `null`, NOT `NaN`. React Aria reports an empty field as `NaN`, and * `NaN === NaN` is false — so every "is it empty" check a caller writes is * wrong. This converts at the boundary, both ways. * * − AND + SIT SIDE BY SIDE, NOT STACKED. Stacked chevrons split the field's * height in two, which puts a Small field's targets at 16px — under the 24px * WCAG 2.5.8 asks. Side by side, every size clears it. They are out of the tab * order, as React Aria sets them: the arrow keys do the same job from the field, * and two extra tab stops per number on a form is a tax on every keyboard user. * * The box is Input's, class for class, so every state — hover, focus, invalid, * read-only, disabled — is Input's and cannot drift from it. */ export declare const NumberInput: React.ForwardRefExoticComponent>; export {}; //# sourceMappingURL=NumberInput.d.ts.map