63 lines
1.5 KiB
TypeScript
63 lines
1.5 KiB
TypeScript
import type { NumberInputProps } from "$/types/InputTypes";
|
|
import clsx from "clsx";
|
|
|
|
|
|
export default function NumberInput({
|
|
id,
|
|
className,
|
|
inputClassName,
|
|
labelClassName,
|
|
name,
|
|
min,
|
|
max,
|
|
step,
|
|
prefix,
|
|
suffix,
|
|
value,
|
|
onChange,
|
|
disabled,
|
|
children
|
|
}: Readonly<NumberInputProps>){
|
|
return (
|
|
<div
|
|
className={clsx(
|
|
"flex flex-row items-center justify-center rounded-lg border-2",
|
|
className
|
|
)}
|
|
>
|
|
<div className="relative flex flex-row items-center justify-center px-2 py-1 w-full">
|
|
<div className="flex flex-row items-center justify-start">
|
|
{ prefix && <span>{prefix}</span> }
|
|
<input
|
|
type="number"
|
|
id={id}
|
|
className={clsx(
|
|
"peer bg-transparent outline-none placeholder-transparent w-full",
|
|
"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
|
|
inputClassName
|
|
)}
|
|
name={name}
|
|
min={min}
|
|
max={max}
|
|
step={step}
|
|
value={value}
|
|
onChange={(e) => onChange(e.target.valueAsNumber || 0)}
|
|
disabled={disabled}
|
|
/>
|
|
{ suffix && <span>{suffix}</span> }
|
|
</div>
|
|
<label
|
|
className={clsx(
|
|
"absolute ml-2 -top-3 left-0 text-sm rounded-md px-1 select-none cursor-default",
|
|
labelClassName
|
|
)}
|
|
style={{ transitionProperty: "top, left, font-size, line-height", transitionTimingFunction: "cubic-bezier(0.4 0, 0.2, 1)", transitionDuration: "250ms" }}
|
|
htmlFor={id}
|
|
>
|
|
{children}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|