5minbetter's picture
deploy: initial clean workspace without lfs history
33d9e63
Raw
History Blame Contribute Delete
3.13 kB
import React from 'react';
import { Copy } from 'lucide-react';
import { Label } from './Label';
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
label?: string;
error?: string;
helperText?: string;
onCopyClick?: () => void;
copyLabel?: string;
rightElement?: React.ReactNode;
labelRightElement?: React.ReactNode;
options?: { value: string; label: string }[];
}
export const Input: React.FC<InputProps> = ({
label,
error,
helperText,
className = '',
id,
onCopyClick,
copyLabel,
rightElement,
labelRightElement,
options,
...props
}) => {
const inputId = id || `input-${Date.now()}`;
return (
<div className="space-y-1">
{label && (
<div className="flex items-center justify-between mb-1">
<Label htmlFor={inputId} className="!mb-0">
{label}
</Label>
{labelRightElement && (
<div className="flex items-center gap-1.5">
{labelRightElement}
</div>
)}
</div>
)}
<div className="relative flex items-center w-full">
{props.type === 'select' ? (
<select
id={inputId}
className={`w-full px-3 py-2 text-sm border ${error
? 'border-red-500 focus:ring-red-500/10 focus:border-red-500'
: 'border-slate-200 focus:ring-2 focus:ring-orange-500/10 focus:border-orange-500'
} rounded-lg outline-none bg-white transition-all cursor-pointer ${className}`}
{...(props as unknown as React.SelectHTMLAttributes<HTMLSelectElement>)}
>
{options?.map((opt) => (
<option key={opt.value} value={opt.value}>
{opt.label}
</option>
))}
</select>
) : (
<input
id={inputId}
className={`w-full px-3 py-2 text-sm border ${error
? 'border-red-500 focus:ring-red-500/10 focus:border-red-500'
: 'border-slate-200 focus:ring-2 focus:ring-orange-500/10 focus:border-orange-500'
} rounded-lg outline-none transition-all ${onCopyClick || rightElement ? 'pr-24' : ''} ${className}`}
{...props}
/>
)}
{onCopyClick && !rightElement && (
<button
type="button"
onClick={onCopyClick}
className="absolute right-2 px-2 py-1 text-xs font-semibold text-orange-600 hover:text-orange-700 flex items-center gap-1 bg-orange-50 hover:bg-orange-100 rounded transition-colors cursor-pointer"
title={copyLabel || '복사'}
>
<Copy className="w-3 h-3" />
<span>{copyLabel || '복사'}</span>
</button>
)}
{rightElement && (
<div className="absolute right-2 flex items-center gap-1.5">
{rightElement}
</div>
)}
</div>
{error && <p className="text-[11px] text-red-500 font-semibold">{error}</p>}
{!error && helperText && <p className="text-[11px] text-slate-400">{helperText}</p>}
</div>
);
};