import { ReactNode } from 'react'; import { AllOptionAccessor, OptionAccessor } from '../Shared/types'; export type ChipSelectProps = Readonly<{ /** Nombre del campo. Es el texto del estado vacío y el aria-label del trigger. */ label: string; icon?: ReactNode; /** Contenido del trigger cuando hay valor. Sin valor, el chip queda punteado. */ display?: ReactNode; error?: boolean; disabled?: boolean; isLoading?: boolean; searchable?: boolean; emptyMessage?: string; options: T[]; optionValue: OptionAccessor; optionLabel: OptionAccessor; /** Encabezado de grupo — opciones consecutivas con el mismo optionGroup comparten header. */ optionGroup?: AllOptionAccessor; /** Nodo a la izquierda del label (avatar, punto de color). */ optionLeading?: AllOptionAccessor; selectedValues: readonly (string | number)[]; multiple?: boolean; onToggle: (value: string | number) => void; /** Presente en opcionales single: agrega la acción "Quitar" al final de la lista. */ onClear?: () => void; /** * Motivo del bloqueo, como tooltip nativo. Un control apagado sin motivo se lee * como un bug — si va `disabled`, va esto. */ disabledReason?: string; /** * Lectura: el chip muestra el valor y no abre. Distinto de `disabled`, que es * "existe pero no ahora"; esto es "no es tuyo para cambiar". */ readOnly?: boolean; /** * Tope alcanzado en modo `multiple`: las opciones NO seleccionadas quedan * deshabilitadas, las seleccionadas siguen clickeables para poder liberar lugar. */ limitReached?: boolean; /** Nota al pie del panel cuando `limitReached`. Ej: "Máximo 3 etiquetas". */ limitMessage?: string; /** * Búsqueda controlada. Con estas dos props el filtrado local se desactiva y * `options` se toma tal cual viene: el consumidor decide qué mostrar. * * Hace falta cuando la búsqueda es server-side y paginada — filtrar de nuevo * en el cliente sobre una página de N resultados esconde los que el server ya * descartó. Sin estas props el comportamiento no cambia. */ searchValue?: string; onSearchChange?: (value: string) => void; className?: string; }>;