Files
towercontrol/src/components/ui/SearchInput.tsx
Julien Froidefond 0fcd4d68c1 feat: unify CardHeader padding across components
- Updated `CardHeader` padding from `pb-3` to `pb-4` in `JiraLogs`, `JiraSync`, `KanbanColumn`, `ObjectivesBoard`, and `DesktopControls` for consistent spacing.
- Refactored `DesktopControls` and `KanbanFilters` to utilize new `ControlPanel`, `ControlSection`, and `ControlGroup` components, enhancing layout structure and maintainability.
- Replaced button elements with `ToggleButton` and `FilterChip` components in various filter sections for improved UI consistency and usability.
2025-09-28 21:53:22 +02:00

79 lines
2.1 KiB
TypeScript

import { InputHTMLAttributes, forwardRef, useState, useEffect, useRef, useCallback } from 'react';
import { Input } from './Input';
import { cn } from '@/lib/utils';
interface SearchInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange'> {
value?: string;
onChange?: (value: string) => void;
onDebouncedChange?: (value: string) => void;
debounceMs?: number;
placeholder?: string;
className?: string;
}
const SearchInput = forwardRef<HTMLInputElement, SearchInputProps>(
({
value = '',
onChange,
onDebouncedChange,
debounceMs = 300,
placeholder = "Rechercher...",
className,
...props
}, ref) => {
const [localValue, setLocalValue] = useState(value);
const timeoutRef = useRef<number | undefined>(undefined);
// Fonction debouncée pour les changements
const debouncedChange = useCallback((searchValue: string) => {
if (timeoutRef.current) {
window.clearTimeout(timeoutRef.current);
}
timeoutRef.current = window.setTimeout(() => {
onDebouncedChange?.(searchValue);
}, debounceMs);
}, [onDebouncedChange, debounceMs]);
// Gérer les changements locaux
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value;
setLocalValue(newValue);
onChange?.(newValue);
debouncedChange(newValue);
};
// Synchroniser l'état local quand la valeur externe change
useEffect(() => {
setLocalValue(value);
}, [value]);
// Nettoyer le timeout au démontage
useEffect(() => {
return () => {
if (timeoutRef.current) {
window.clearTimeout(timeoutRef.current);
}
};
}, []);
return (
<div className={cn('flex-1 min-w-0', className)}>
<Input
ref={ref}
type="text"
value={localValue}
onChange={handleChange}
placeholder={placeholder}
className="bg-[var(--card)] border-[var(--border)] w-full"
{...props}
/>
</div>
);
}
);
SearchInput.displayName = 'SearchInput';
export { SearchInput };