import { default as React } from 'react'; import { InputProps } from '../Input/types'; import { AllOptionAccessor, LabelVariant, OptionAccessor } from '../Shared/types'; export interface SelectOptionType { id: string | number; label: string; /** @deprecated Use `id` instead. Kept for backward compatibility. */ value?: string | number; isGroupHeader?: boolean; groupLabelNode?: React.ReactNode; groupData?: { groupOptions: SelectOptionType[]; }; originalOption?: unknown; } export type SelectSize = "small" | "medium" | "large"; export type SelectVariant = "default" | "error" | "success"; export type SelectDisplayMode = "compact" | "chips"; export type SelectOverflow = "wrap" | "scroll"; export type { LabelVariant }; export type ChipItem = { type: "group"; groupLabel: string; count: number; groupId: string | number; options: T[]; } | { type: "option"; option: T; id: string | number; label: string; }; export interface SelectDropdownOptions { hideSearchBar?: boolean; inputProps?: Partial; dropdownHeight?: string; controlledSearchValue?: string; onSearchValueChange?: (value: string) => void; onSearchClear?: () => void; searchPlaceholder?: string; isLoading?: boolean; footer?: React.ReactNode; loadingComponent?: React.ReactNode; enableGroupToggle?: boolean; /** Group IDs (optionValue) that start expanded when the dropdown opens */ initialExpandedGroupIds?: (string | number)[]; /** Start all groups expanded. Takes precedence over initialExpandedGroupIds. */ allGroupsExpanded?: boolean; /** Whether grouped options use accordion mode (only one group open at a time). Default: true */ groupAccordion?: boolean; focusSearchInputOnOpen?: boolean; optionContainerClassName?: string; groupContainerClassName?: string; } interface DeprecatedDropdownOptions { /** @deprecated Use controlledSearchValue */ controledSearchValue?: string; /** @deprecated Use searchPlaceholder */ inputSearchPlaceholder?: string; } export declare function normalizeDropdownOptions(options?: SelectDropdownOptions & DeprecatedDropdownOptions): SelectDropdownOptions | undefined; export interface SelectOptionActivatePayload { /** Objeto resuelto de flattenOptions */ option: T; /** ID de la opción (optionValue) */ value: string | number; /** Estado actual según el value del Select */ isSelected: boolean; multiple: boolean; /** Origen de la activación — útil para demos y telemetría */ source: "mouse" | "keyboard"; /** Ejecuta el toggle por defecto (handleSelect) */ commit: () => void; /** Cierra el dropdown */ close: () => void; } export interface SelectOptionRendererProps { option: T; isSelected: boolean; onSelect: (closeOnSelect?: boolean) => void; multiple: boolean; disabled?: boolean; /** @deprecated Always false. Loading state is handled by the dropdown skeleton, not per-option. */ isLoading?: boolean; isOptionActive?: boolean; /** @deprecated Use closure pattern instead. Will be removed in next major. */ renderContext?: unknown; } export interface SelectGroupHeaderRendererProps { group: T; label: React.ReactNode | string; groupOptions: T[]; groupSelectedIds: (string | number)[]; multiple: boolean; disabled?: boolean; expanded: boolean; toggleGroup: (nextExpanded?: boolean) => void; selectGroup: (mode?: "toggle" | "select" | "deselect") => void; /** @deprecated Use closure pattern instead. Will be removed in next major. */ renderContext?: unknown; } export interface SelectionDisplayProps { selectedOptions: T[]; placeholder?: string; multiple: boolean; onRemoveOption: (optionId: string | number) => void; disabled?: boolean; } export interface SelectControlsHandle { open: () => void; close: () => void; toggle: () => void; selectOption: (value: string | number) => void; clearSelection: () => void; subscribeOpenChange: (cb: (open: boolean) => void) => () => void; searchInputRef: React.RefObject; /** @deprecated Use selectOption(value) instead */ handleOptionSelect: (option: SelectOptionType, closeOnSelect?: boolean) => void; } /** @deprecated Use SelectControlsHandle */ export type SelectControlsHandler = SelectControlsHandle; export type SelectControlsRef = React.MutableRefObject; interface BaseSelectProps { label: string; options: T[]; optionLabel: OptionAccessor; optionValue: OptionAccessor; optionActive?: AllOptionAccessor; renderOption?: React.ComponentType>; renderOptionGroupHeader?: React.ComponentType>; renderSelection?: React.ComponentType>; /** @deprecated Use closure pattern. Access context variables directly in your render function. */ renderOptionContext?: unknown; id?: string; name?: string; disabled?: boolean; isLoading?: boolean; emptyMessage?: string; variant?: SelectVariant; size?: SelectSize; labelVariant?: LabelVariant; placeholder?: string; overflow?: SelectOverflow; dropdownOptions?: SelectDropdownOptions & DeprecatedDropdownOptions; onClose?: () => void; onClear?: () => void; onRemoveOption?: (option: T) => void; /** * Punto de activación de una opción, disparado igual por mouse y teclado. * Si se provee, reemplaza el commit por defecto: el consumidor decide si * commitear (`commit()`), cerrar (`close()`), o manejar estado propio. * Si no se provee, la activación commitea normal (toggle + cierre en single). */ onOptionActivate?: (payload: SelectOptionActivatePayload) => void; /** @deprecated Use onChange */ onOptionClick?: (option: SelectOptionType, name?: string) => void; controls?: SelectControlsRef; disableOpenOnFocus?: boolean; helperComponent?: React.ReactNode; errorComponent?: React.ReactNode; /** Props para el Input interno del trigger (p. ej. cardBackground). */ inputProps?: Partial; className?: string; containerClassName?: string; /** @deprecated Style via className or containerClassName */ buttonClassName?: string; /** @deprecated Dropdown styled via dropdownOptions */ dropdownClassName?: string; width?: string; height?: string; tabIndex?: number; /** @deprecated Menu handles positioning internally */ attachToParent?: boolean; /** * Dropdown rendering mode on mobile devices. * "floating" (default): standard floating dropdown, repositions with keyboard. * "drawer": bottom-sheet drawer on mobile, floating on desktop. */ mobileDropdown?: "floating" | "drawer"; } type SelectSingleControlled = BaseSelectProps & { multiple?: false; /** Controlled: la fuente de verdad está afuera. onChange es obligatorio. */ value: string | number | undefined; onChange: (newValue: SelectOptionType | undefined, name?: string) => void; defaultValue?: never; displayMode?: "compact"; groupSelection?: never; }; type SelectSingleUncontrolled = BaseSelectProps & { multiple?: false; /** Uncontrolled: Select mantiene la selección internamente. */ defaultValue?: string | number; value?: never; onChange?: (newValue: SelectOptionType | undefined, name?: string) => void; displayMode?: "compact"; groupSelection?: never; }; export type SingleSelectProps = SelectSingleControlled | SelectSingleUncontrolled; type SelectMultipleControlled = BaseSelectProps & { multiple: true; value: (string | number)[]; onChange: (newValue: SelectOptionType[], name?: string) => void; defaultValue?: never; displayMode?: SelectDisplayMode; groupSelection?: boolean; }; type SelectMultipleUncontrolled = BaseSelectProps & { multiple: true; defaultValue?: (string | number)[]; value?: never; onChange?: (newValue: SelectOptionType[], name?: string) => void; displayMode?: SelectDisplayMode; groupSelection?: boolean; }; export type MultipleSelectProps = SelectMultipleControlled | SelectMultipleUncontrolled; export type SelectProps = SingleSelectProps | MultipleSelectProps; /** * @deprecated TContext is deprecated. Use closure pattern for render context. * The second generic is silently ignored. */ export type SelectPropsCompat = SelectProps; /** @deprecated Use SelectionDisplayProps */ export type CustomSelectionDisplayProps = SelectionDisplayProps; /** @deprecated Use SelectOptionRendererProps */ export type CustomSelectOptionRendererProps = SelectOptionRendererProps; /** @deprecated Use SelectGroupHeaderRendererProps */ export type CustomSelectOptionGroupHeaderProps = SelectGroupHeaderRendererProps; /** @deprecated Use SelectDropdownOptions */ export type DropdownOptionsProps = SelectDropdownOptions & DeprecatedDropdownOptions;