CustomSelect_CustomSelect.jsx
import React, { useState, useEffect, useRef } from 'react';
import { useTheme } from '../../Contexts/UserContext';
import './CustomSelect.scss';
/**
* Componente CustomSelect que crea un selector de opciones con capacidad de filtrado y enfoque.
*
* @component
*
* @param {Array} opciones - Array de opciones que se mostrarán en el selector.
* @param {string} valorSeleccionado - El valor actualmente seleccionado en el selector.
* @param {function} setValorSeleccionado - Función para actualizar el valor seleccionado.
* @param {string} [titulo='Titulo'] - Título que se mostrará sobre el selector.
* @param {string} [placeholder] - Texto que aparece como placeholder.
*
* @returns {JSX.Element} Un campo de selección con las opciones filtradas y seleccionables.
*/
const CustomSelect = ({ opciones, valorSeleccionado, setValorSeleccionado, titulo = 'Titulo', placeholder }) => {
const [abierto, setAbierto] = useState(false);
const [filtro, setFiltro] = useState(valorSeleccionado || ''); // Estado del input
const selectRef = useRef(null);
const { theme } = useTheme();
// Sincroniza el input con el valor seleccionado
useEffect(() => {
setFiltro(valorSeleccionado);
}, [valorSeleccionado]);
const opcionesFiltradas = opciones.filter((opcion) =>
opcion?.toLowerCase().includes(filtro?.toLowerCase() || '')
);
const manejarSeleccion = (opcion) => {
setValorSeleccionado(opcion);
setFiltro(opcion);
setAbierto(false);
};
useEffect(() => {
const manejarClickFuera = (event) => {
if (selectRef.current && !selectRef.current.contains(event.target)) {
setAbierto(false);
}
};
document.addEventListener('click', manejarClickFuera);
return () => {
document.removeEventListener('click', manejarClickFuera);
};
}, []);
const [isFocused, setIsFocused] = useState(false);
return (
<div
className={`custom-select ${theme}`}
ref={selectRef}
>
<p
htmlFor='selected'
className={`input-title lato ${isFocused ? 'focused' : ''}`}
>
{titulo}
</p>
<input
type='text'
value={filtro}
onChange={(e) => {
setFiltro(e.target.value);
setAbierto(true);
}}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
onClick={() => setAbierto(true)}
placeholder={placeholder}
className='selected'
/>
{abierto && (
<div className='options'>
<div
className='option'
onClick={() => manejarSeleccion('')}
>
{titulo}
</div>
{opcionesFiltradas.length > 0 ? (
opcionesFiltradas.map((opcion, index) => (
<div
key={index}
className='option'
onClick={() => manejarSeleccion(opcion)}
>
{opcion}
</div>
))
) : (
<div className='option disabled'>No hay resultados</div>
)}
</div>
)}
</div>
);
};
export default CustomSelect;