| 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 | |