React input-number component with increment/decrement controls, formatting, and high-precision decimal support
npx @tessl/cli install tessl/npm-rc-component--input-number@1.0.0RC Input Number is a React component that provides a controlled numeric input field with built-in increment/decrement controls, high-precision decimal arithmetic, and extensive customization options. It supports keyboard navigation, mouse wheel interaction, formatting, validation, and accessibility features.
npm install @rc-component/input-numberimport InputNumber from "@rc-component/input-number";
import type { InputNumberProps, ValueType, InputNumberRef } from "@rc-component/input-number";For CommonJS:
const InputNumber = require("@rc-component/input-number");import React from "react";
import InputNumber from "@rc-component/input-number";
// Basic controlled component
function BasicExample() {
const [value, setValue] = React.useState<number | null>(10);
return (
<InputNumber
value={value}
onChange={setValue}
min={0}
max={100}
step={1}
/>
);
}
// With formatting and precision
function FormattedExample() {
const [value, setValue] = React.useState<string>("12.34");
return (
<InputNumber
stringMode
value={value}
onChange={setValue}
precision={2}
decimalSeparator=","
formatter={(value) => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
parser={(value) => value?.replace(/\$\s?|(,*)/g, '') || ''}
/>
);
}RC Input Number is built around several key components:
InputNumber component wraps the internal input with BaseInput for consistent stylingInternalInputNumber handles the core numeric logic and state managementStepHandler component provides the increment/decrement buttons with long-press support@rc-component/mini-decimal for high-precision arithmetic avoiding floating-point errorsuseCursor) and frame scheduling (useFrame)The main InputNumber component that provides controlled numeric input with validation and formatting.
/**
* React input number component with step controls and high-precision arithmetic
*/
declare const InputNumber: <T extends ValueType = ValueType>(
props: React.PropsWithChildren<InputNumberProps<T>> & {
ref?: React.Ref<InputNumberRef>;
}
) => React.ReactElement;
interface InputNumberProps<T extends ValueType = ValueType>
extends Omit<
React.InputHTMLAttributes<HTMLInputElement>,
'value' | 'defaultValue' | 'onInput' | 'onChange' | 'prefix' | 'suffix'
> {
/** value will show as string */
stringMode?: boolean;
/** Default value for uncontrolled mode */
defaultValue?: T;
/** Current value for controlled mode */
value?: T | null;
/** CSS class prefix (default: 'rc-input-number') */
prefixCls?: string;
/** Additional CSS class name */
className?: string;
/** Inline styles */
style?: React.CSSProperties;
/** Minimum allowed value */
min?: T;
/** Maximum allowed value */
max?: T;
/** Step increment/decrement value (default: 1) */
step?: ValueType;
/** Tab index for keyboard navigation */
tabIndex?: number;
/** Show/hide step control buttons (default: true) */
controls?: boolean;
/** Prefix content inside input */
prefix?: React.ReactNode;
/** Suffix content inside input */
suffix?: React.ReactNode;
/** Content before input wrapper */
addonBefore?: React.ReactNode;
/** Content after input wrapper */
addonAfter?: React.ReactNode;
/** Custom class names for different parts */
classNames?: {
input?: string;
affixWrapper?: string;
prefix?: string;
suffix?: string;
groupWrapper?: string;
};
/** Custom up button content */
upHandler?: React.ReactNode;
/** Custom down button content */
downHandler?: React.ReactNode;
/** Enable keyboard arrow key control (default: true) */
keyboard?: boolean;
/** Enable mouse wheel to change value */
changeOnWheel?: boolean;
/** Parse display value to validate number */
parser?: (displayValue: string | undefined) => T;
/** Transform value to display value show in input */
formatter?: (value: T | undefined, info: { userTyping: boolean; input: string }) => string;
/** Number of decimal places to display */
precision?: number;
/** Custom decimal separator character */
decimalSeparator?: string;
/** Input text change callback */
onInput?: (text: string) => void;
/** Value change callback */
onChange?: (value: T | null) => void;
/** Enter key press handler */
onPressEnter?: React.KeyboardEventHandler<HTMLInputElement>;
/** Step change callback with detailed information */
onStep?: (value: T, info: {
offset: ValueType;
type: 'up' | 'down';
emitter: 'handler' | 'keyboard' | 'wheel'
}) => void;
/** Trigger change on blur event (default: true) */
changeOnBlur?: boolean;
}Interface for accessing the component methods via ref.
interface InputNumberRef extends HTMLInputElement {
/** Focus the input with optional focus options */
focus: (options?: InputFocusOptions) => void;
/** Blur the input */
blur: () => void;
/** Access to native DOM element */
nativeElement: HTMLElement;
}
interface InputFocusOptions {
/** Whether to prevent scroll when focusing */
preventScroll?: boolean;
/** Cursor selection range */
cursor?: {
start?: number;
end?: number;
};
}Core type definitions for numeric values and validation.
/** Union type for numeric values supporting both strings and numbers */
type ValueType = string | number;The component includes built-in step controls with the following behavior:
keyboard={false})changeOnWheel propAdvanced formatting capabilities for display and input parsing:
// Custom currency formatter
const currencyFormatter = (value: string | undefined) => {
if (!value) return '';
return `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
};
const currencyParser = (value: string | undefined) => {
return value?.replace(/\$\s?|(,*)/g, '') || '';
};
<InputNumber
formatter={currencyFormatter}
parser={currencyParser}
precision={2}
/>The component uses @rc-component/mini-decimal internally to avoid JavaScript floating-point precision issues:
Built-in validation features:
Comprehensive event system for different interaction types:
<InputNumber
onChange={(value) => {
console.log('Value changed:', value);
}}
onStep={(value, info) => {
console.log('Stepped:', value, 'via', info.emitter, info.type);
}}
onInput={(text) => {
console.log('Raw input:', text);
}}
onPressEnter={(event) => {
console.log('Enter pressed');
}}
/>For applications requiring string-based numeric handling:
<InputNumber
stringMode
value="123.456789"
precision={6}
onChange={(stringValue) => {
// Value returned as string: "123.456789"
console.log(typeof stringValue); // "string"
}}
/>This mode is useful for: