import React, { useState } from 'react'; import { FilterConfig } from '../../types'; import { cn } from '../../utils/cn'; interface TableFilterProps { /** * Filter configuration */ filter: FilterConfig; /** * Current filter value */ value: any; /** * Callback when filter value changes */ onChange: (value: any) => void; /** * Custom CSS class */ className?: string; } export const TableFilter: React.FC = ({ filter, value, onChange, className }) => { // Local state for filter input before committing (for debounced filters) const [localValue, setLocalValue] = useState(value !== undefined ? value : ''); // For debounced text filters const [timeoutId, setTimeoutId] = useState(null); // Handle filter change with optional debounce for text inputs const handleChange = (newValue: any, debounce = false) => { setLocalValue(newValue); if (debounce) { if (timeoutId) { clearTimeout(timeoutId); } const id = setTimeout(() => { onChange(newValue); }, 300); // 300ms debounce setTimeoutId(id); } else { onChange(newValue); } }; // Render filter based on type const renderFilter = () => { switch (filter.type) { case 'text': return ( handleChange(e.target.value, true)} placeholder={filter.placeholder || `Filter by ${filter.label}`} /> ); case 'select': return ( ); case 'boolean': return ( ); case 'number': return (
{ const val = e.target.value === '' ? '' : Number(e.target.value); if (Array.isArray(localValue)) { handleChange([val, localValue[1]], true); } else { handleChange(val, true); } }} placeholder={`Min`} /> - { const val = e.target.value === '' ? '' : Number(e.target.value); if (Array.isArray(localValue)) { handleChange([localValue[0], val], true); } else { handleChange([localValue || '', val], true); } }} placeholder={`Max`} />
); case 'date': return ( handleChange(e.target.value)} /> ); case 'dateRange': return (
{ const newValue = e.target.value || ''; if (Array.isArray(localValue)) { handleChange([newValue, localValue[1]]); } else { handleChange([newValue, '']); } }} placeholder="From" /> - { const newValue = e.target.value || ''; if (Array.isArray(localValue)) { handleChange([localValue[0], newValue]); } else { handleChange(['', newValue]); } }} placeholder="To" />
); case 'custom': return filter.render ? filter.render({ onChange, filter }) :
Custom filter
; default: return
Unknown filter type: {filter.type}
; } }; return (
{filter.label}
{renderFilter()} {(value !== undefined && value !== '' && value !== null) && ( )}
); }; export default TableFilter;