import * as React from 'react'; import { useId } from 'react'; import { Check } from 'lucide-react'; import { cn } from '@/lib/utils'; /** * CheckboxProps - Propriétés du composant Checkbox * * @interface CheckboxProps * @extends Omit, 'onChange'> */ export interface CheckboxProps extends Omit, 'onChange'> { /** * Label à afficher à côté de la checkbox * * @example * ```tsx * * ``` */ label?: string; /** * Fonction appelée lorsque l'état checked change * Reçoit la nouvelle valeur booléenne * * @param {boolean} checked - Nouvel état checked * * @example * ```tsx * console.log(checked)} /> * ``` */ onCheckedChange?: (checked: boolean) => void; } /** * Checkbox - Composant de case à cocher avec design system Kodo * * Composant de checkbox avec support pour les labels et les callbacks. * Utilise le design system Kodo avec une icône Check animée lors de la sélection. * * @example * ```tsx * // Checkbox simple * * * // Checkbox contrôlée * * * // Checkbox désactivée * * ``` * * @component * @param {CheckboxProps} props - Propriétés du composant * @returns {JSX.Element} Élément label contenant une checkbox stylisée */ export const Checkbox = React.forwardRef( ({ label, className = '', onCheckedChange, id, ...props }, ref) => { // CRITIQUE FIX #37: Utiliser useId() pour générer un ID stable pour l'association label/input const generatedId = useId(); const checkboxId = id || generatedId; const labelId = `${checkboxId}-label`; const handleChange = (e: React.ChangeEvent) => { if (onCheckedChange) { onCheckedChange(e.target.checked); } }; // CRITIQUE FIX #37: Si aucun label n'est fourni, s'assurer qu'il y a un aria-label // const hasAccessibleLabel = label || props['aria-label'] || props['aria-labelledby']; return ( ); }, ); Checkbox.displayName = 'Checkbox';