import React from 'react'; import { Search, Upload as UploadIcon } from 'lucide-react'; import { cn } from '../../utils/cn'; /* -------------------------------------------------------------------------- */ /* Text Input */ /* -------------------------------------------------------------------------- */ export interface InputProps extends React.InputHTMLAttributes { label?: string; icon?: React.ReactNode; } export const Input = React.forwardRef( ({ label, icon, className, type, autoComplete, required, id, ...props }, ref) => { // CRITIQUE FIX #4: Générer un ID stable si non fourni pour l'association avec le label const generatedId = React.useId(); const inputId = id || generatedId; // CRITIQUE FIX #4: Déterminer autoComplete par défaut basé sur le type const defaultAutoComplete = autoComplete !== undefined ? autoComplete : (type === 'email' ? 'email' : type === 'password' ? 'current-password' : undefined); // CRITIQUE FIX #51: S'assurer que aria-describedby et aria-invalid sont correctement passés const ariaDescribedBy = props['aria-describedby']; const ariaInvalid = props['aria-invalid']; return (
{label && ( )}
{icon && (
{icon}
)}
); } ); Input.displayName = 'Input'; /* -------------------------------------------------------------------------- */ /* Search Input */ /* -------------------------------------------------------------------------- */ export const SearchInput = React.forwardRef< HTMLInputElement, React.InputHTMLAttributes >((props, ref) => { return (
); }); SearchInput.displayName = 'SearchInput'; /* -------------------------------------------------------------------------- */ /* File Upload */ /* -------------------------------------------------------------------------- */ export interface FileUploadProps { onUpload?: (files: FileList) => void; className?: string; } export const FileUpload: React.FC = ({ onUpload, className }) => { return (

Drop your stems here

Support for WAV, FLAC, AIFF. Up to 500MB per file.{' '} Premium users get unlimited storage.

); };