feat: add react-scan in dev
This commit is contained in:
parent
665509e710
commit
0f75636342
8 changed files with 577 additions and 133 deletions
99
app/components/NumberInput.tsx
Normal file
99
app/components/NumberInput.tsx
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
import { Minus, Plus } from 'lucide-react';
|
||||
import { useRef } from 'react';
|
||||
import {
|
||||
type AriaNumberFieldProps,
|
||||
useLocale,
|
||||
useNumberField,
|
||||
} from 'react-aria';
|
||||
import { useNumberFieldState } from 'react-stately';
|
||||
import IconButton from '~/components/IconButton';
|
||||
import cn from '~/utils/cn';
|
||||
|
||||
export interface InputProps extends AriaNumberFieldProps {
|
||||
isRequired?: boolean;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export default function NumberInput(props: InputProps) {
|
||||
const { label, name } = props;
|
||||
const { locale } = useLocale();
|
||||
const state = useNumberFieldState({ ...props, locale });
|
||||
const ref = useRef<HTMLInputElement | null>(null);
|
||||
|
||||
const {
|
||||
labelProps,
|
||||
inputProps,
|
||||
groupProps,
|
||||
incrementButtonProps,
|
||||
decrementButtonProps,
|
||||
descriptionProps,
|
||||
errorMessageProps,
|
||||
isInvalid,
|
||||
validationErrors,
|
||||
} = useNumberField(props, state, ref);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<label
|
||||
{...labelProps}
|
||||
htmlFor={name}
|
||||
className={cn(
|
||||
'text-xs font-medium px-3 mb-0.5',
|
||||
'text-headplane-700 dark:text-headplane-100',
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
</label>
|
||||
<div
|
||||
{...groupProps}
|
||||
className={cn(
|
||||
'flex items-center gap-1 rounded-xl pr-1',
|
||||
'focus-within:outline-none focus-within:ring',
|
||||
'bg-white dark:bg-headplane-900',
|
||||
'border border-headplane-100 dark:border-headplane-800',
|
||||
)}
|
||||
>
|
||||
<input
|
||||
{...inputProps}
|
||||
required={props.isRequired}
|
||||
name={name}
|
||||
ref={ref}
|
||||
className="w-full pl-3 py-2 rounded-l-xl focus:outline-none"
|
||||
/>
|
||||
<IconButton
|
||||
{...decrementButtonProps}
|
||||
label="Decrement"
|
||||
className="w-7.5 h-7.5 rounded-lg"
|
||||
>
|
||||
<Minus className="p-1" />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...incrementButtonProps}
|
||||
label="Increment"
|
||||
className="w-7.5 h-7.5 rounded-lg"
|
||||
>
|
||||
<Plus className="p-1" />
|
||||
</IconButton>
|
||||
</div>
|
||||
{props.description && (
|
||||
<div
|
||||
{...descriptionProps}
|
||||
className={cn(
|
||||
'text-xs px-3 mt-1',
|
||||
'text-headplane-500 dark:text-headplane-400',
|
||||
)}
|
||||
>
|
||||
{props.description}
|
||||
</div>
|
||||
)}
|
||||
{isInvalid && (
|
||||
<div
|
||||
{...errorMessageProps}
|
||||
className={cn('text-xs px-3 mt-1', 'text-red-500 dark:text-red-400')}
|
||||
>
|
||||
{validationErrors.join(' ')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue