|
import type { CSSProperties } from 'react' |
|
import React from 'react' |
|
import { useTranslation } from 'react-i18next' |
|
import { RiCloseCircleFill, RiErrorWarningLine, RiSearchLine } from '@remixicon/react' |
|
import { type VariantProps, cva } from 'class-variance-authority' |
|
import cn from '@/utils/classnames' |
|
|
|
export const inputVariants = cva( |
|
'', |
|
{ |
|
variants: { |
|
size: { |
|
regular: 'px-3 radius-md system-sm-regular', |
|
large: 'px-4 radius-lg system-md-regular', |
|
}, |
|
}, |
|
defaultVariants: { |
|
size: 'regular', |
|
}, |
|
}, |
|
) |
|
|
|
export type InputProps = { |
|
showLeftIcon?: boolean |
|
showClearIcon?: boolean |
|
onClear?: () => void |
|
disabled?: boolean |
|
destructive?: boolean |
|
wrapperClassName?: string |
|
styleCss?: CSSProperties |
|
} & React.InputHTMLAttributes<HTMLInputElement> & VariantProps<typeof inputVariants> |
|
|
|
const Input = ({ |
|
size, |
|
disabled, |
|
destructive, |
|
showLeftIcon, |
|
showClearIcon, |
|
onClear, |
|
wrapperClassName, |
|
className, |
|
styleCss, |
|
value, |
|
placeholder, |
|
onChange, |
|
...props |
|
}: InputProps) => { |
|
const { t } = useTranslation() |
|
return ( |
|
<div className={cn('relative w-full', wrapperClassName)}> |
|
{showLeftIcon && <RiSearchLine className={cn('absolute left-2 top-1/2 -translate-y-1/2 w-4 h-4 text-components-input-text-placeholder')} />} |
|
<input |
|
style={styleCss} |
|
className={cn( |
|
'w-full py-[7px] bg-components-input-bg-normal border border-transparent text-components-input-text-filled hover:bg-components-input-bg-hover hover:border-components-input-border-hover focus:bg-components-input-bg-active focus:border-components-input-border-active focus:shadow-xs placeholder:text-components-input-text-placeholder appearance-none outline-none caret-primary-600', |
|
inputVariants({ size }), |
|
showLeftIcon && 'pl-[26px]', |
|
showLeftIcon && size === 'large' && 'pl-7', |
|
showClearIcon && value && 'pr-[26px]', |
|
showClearIcon && value && size === 'large' && 'pr-7', |
|
destructive && 'pr-[26px]', |
|
destructive && size === 'large' && 'pr-7', |
|
disabled && 'bg-components-input-bg-disabled border-transparent text-components-input-text-filled-disabled cursor-not-allowed hover:bg-components-input-bg-disabled hover:border-transparent', |
|
destructive && 'bg-components-input-bg-destructive border-components-input-border-destructive text-components-input-text-filled hover:bg-components-input-bg-destructive hover:border-components-input-border-destructive focus:bg-components-input-bg-destructive focus:border-components-input-border-destructive', |
|
className, |
|
)} |
|
placeholder={placeholder ?? (showLeftIcon ? t('common.operation.search') ?? '' : t('common.placeholder.input'))} |
|
value={value} |
|
onChange={onChange} |
|
disabled={disabled} |
|
{...props} |
|
/> |
|
{showClearIcon && value && !disabled && !destructive && ( |
|
<div className={cn('absolute right-2 top-1/2 -translate-y-1/2 group p-[1px] cursor-pointer')} onClick={onClear}> |
|
<RiCloseCircleFill className='w-3.5 h-3.5 text-text-quaternary cursor-pointer group-hover:text-text-tertiary' /> |
|
</div> |
|
)} |
|
{destructive && ( |
|
<RiErrorWarningLine className='absolute right-2 top-1/2 -translate-y-1/2 w-4 h-4 text-text-destructive-secondary' /> |
|
)} |
|
</div> |
|
) |
|
} |
|
|
|
export default Input |
|
|