Files
ERP_Distribution/distribution_fe/components/shared/data-table/table-toolbar.tsx
T
2026-08-25 23:47:33 +05:30

126 lines
3.9 KiB
TypeScript

'use client';
import { useRef } from 'react';
import { HugeiconsIcon } from '@hugeicons/react';
import {
Search01Icon,
Cancel01Icon,
ColumnsThreeCogIcon,
Download01Icon,
} from '@hugeicons/core-free-icons';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { type ColumnDef, type ExportFormat } from './types';
interface TableToolbarProps<T> {
columns: ColumnDef<T>[];
hiddenColumns: Set<string>;
globalFilter: string;
showExport?: boolean;
exportFormats?: ExportFormat[];
selectedCount?: number;
onGlobalFilterChange: (value: string) => void;
onColumnVisibilityChange: (key: string) => void;
onExport?: (format: ExportFormat) => void;
onClearSelection?: () => void;
}
export function TableToolbar<T>({
columns,
hiddenColumns,
globalFilter,
showExport,
exportFormats = ['csv', 'excel', 'pdf'],
selectedCount = 0,
onGlobalFilterChange,
onColumnVisibilityChange,
onExport,
onClearSelection,
}: TableToolbarProps<T>) {
const inputRef = useRef<HTMLInputElement>(null);
const toggleableColumns = columns.filter(col => col.hideable !== false);
return (
<div className="flex items-center gap-2 p-3 border-b">
{/* Global search */}
<div className="relative flex-1 max-w-xs">
<HugeiconsIcon
icon={Search01Icon}
className="absolute left-2.5 top-1/2 -translate-y-1/2 size-4 text-muted-foreground pointer-events-none"
/>
<Input
ref={inputRef}
value={globalFilter}
onChange={e => onGlobalFilterChange(e.target.value)}
placeholder="Search…"
className="pl-8 pr-8 h-8 text-sm"
/>
{globalFilter && (
<button
onClick={() => onGlobalFilterChange('')}
className="absolute right-2.5 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
>
<HugeiconsIcon icon={Cancel01Icon} className="size-3.5" />
</button>
)}
</div>
{/* Selection badge */}
{selectedCount > 0 && (
<div className="flex items-center gap-1.5">
<Badge variant="secondary" className="text-xs">
{selectedCount} selected
</Badge>
<Button variant="ghost" size="xs" onClick={onClearSelection} className="text-xs h-6">
Clear
</Button>
</div>
)}
{/* Column visibility */}
<DropdownMenu>
<DropdownMenuTrigger render={<Button variant="outline" size="sm" className="gap-1.5" />}>
<HugeiconsIcon icon={ColumnsThreeCogIcon} className="size-4" />
Columns
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-48">
{toggleableColumns.map(col => (
<DropdownMenuCheckboxItem
key={col.key}
checked={!hiddenColumns.has(col.key)}
onCheckedChange={() => onColumnVisibilityChange(col.key)}
>
{col.title}
</DropdownMenuCheckboxItem>
))}
</DropdownMenuContent>
</DropdownMenu>
{/* Export */}
{showExport && onExport && (
<DropdownMenu>
<DropdownMenuTrigger render={<Button variant="outline" size="sm" className="gap-1.5" />}>
<HugeiconsIcon icon={Download01Icon} className="size-4" />
Export
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{exportFormats.map(fmt => (
<DropdownMenuItem key={fmt} onClick={() => onExport(fmt)}>
{fmt.toUpperCase()}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
)}
</div>
);
}