All files / packages/components/src number-input.web.tsx

90.9% Statements 10/11
93.33% Branches 14/15
80% Functions 4/5
90.9% Lines 10/11

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98                                                                                  8412x                     9658x 9658x   10x 3x         9658x 9658x       9658x 9658x                                                   75x        
import React from "react";
 
import { NumberInput as NumberInputRaw } from "@heroui/number-input";
 
import type { InputHandler, Props as InputProps } from "~components/input";
import { InputWrapper } from "~components/input.web";
import { cn, getErrorState, getMutationLoading } from "~components/utils";
 
export type Props = {
	ref?: React.RefObject<InputHandler>;
	fractionDigits: number;
	formatOptions?: Intl.NumberFormatOptions;
	defaultValue?: number;
	value?: number;
	onValueChange?: (nextValue: number) => void;
	minValue?: number;
	maxValue?: number;
	isInvalid?: boolean;
	hideStepper?: boolean;
	onKeyPress?: (key: string) => void;
} & Pick<
	InputProps,
	| "labelPlacement"
	| "onBlur"
	| "name"
	| "startContent"
	| "endContent"
	| "isDisabled"
	| "isReadOnly"
	| "isRequired"
	| "className"
	| "label"
	| "variant"
	| "color"
	| "errorMessage"
	| "mutation"
	| "fieldError"
	| "continuousMutations"
	| "aria-label"
>;
 
export const NumberInput: React.FC<Props> = ({
	className,
	fieldError,
	mutation,
	continuousMutations = false,
	fractionDigits,
	formatOptions,
	ref,
	onKeyPress,
	...props
}) => {
	const innerRef = React.useRef<HTMLInputElement>(null);
	React.useImperativeHandle(
		ref,
		() => ({
			focus: () => innerRef.current?.focus(),
			blur: () => innerRef.current?.blur(),
		}),
		[],
	);
	const isMutationLoading = getMutationLoading(mutation);
	const { isWarning, isError, errors } = getErrorState({
		mutation,
		fieldError,
	});
	const isSSR = typeof window === "undefined";
	return (
		<NumberInputRaw
			as={InputWrapper}
			ref={innerRef}
			{...props}
			isDisabled={
				(continuousMutations ? false : isMutationLoading) || props.isDisabled
			}
			color={isWarning ? "warning" : isError ? "danger" : undefined}
			description={errors.join("\n")}
			isInvalid={errors.length !== 0 || props.isInvalid}
			classNames={{
				base: className,
				description: cn(
					"whitespace-pre",
					isWarning ? "text-warning" : undefined,
				),
			}}
			step={10 ** -fractionDigits}
			formatOptions={
				isSSR
					? // iPhone make some format options mismatch on hydration
						// see https://github.com/adobe/react-spectrum/issues/8503
						{ maximumFractionDigits: 0, ...formatOptions }
					: { maximumFractionDigits: fractionDigits, ...formatOptions }
			}
			onKeyDown={(e) => onKeyPress?.(e.key)}
		/>
	);
};