"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TailwindTable = TailwindTable;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const cn_js_1 = require("../utils/cn.js");
/**
 * Table component built with Tailwind CSS
 *
 * A flexible table component with support for sorting, filtering, and various styling options.
 *
 * @example
 * // Basic usage
 * <TailwindTable
 *   data={users}
 *   columns={[
 *     { id: 'name', header: 'Name', accessor: row => row.name },
 *     { id: 'email', header: 'Email', accessor: row => row.email },
 *     { id: 'role', header: 'Role', accessor: row => row.role }
 *   ]}
 * />
 *
 * @example
 * // With sorting and filtering
 * <TailwindTable
 *   data={users}
 *   columns={[
 *     {
 *       id: 'name',
 *       header: 'Name',
 *       accessor: row => row.name,
 *       sortable: true,
 *       filterable: true
 *     },
 *     // ... other columns
 *   ]}
 *   sortable
 *   filterable
 *   defaultSortColumn="name"
 *   defaultSortDirection="asc"
 * />
 */
function TailwindTable({ data, columns, variant = 'simple', size = 'md', sortable = false, defaultSortColumn, defaultSortDirection, onSort, filterable = false, filterValue: externalFilterValue, onFilter, stickyHeader = false, isLoading = false, emptyText = 'No data available', loadingText = 'Loading...', isScrollable = false, onRowClick, selectable = false, selectedRows = [], onSelectRows, className, tableClassName, headerClassName, bodyClassName, rowClassName, cellClassName, caption, hasFooter = false, footer, footerClassName, }) {
    // Internal state for sorting
    const [sortColumn, setSortColumn] = (0, react_1.useState)(defaultSortColumn);
    const [sortDirection, setSortDirection] = (0, react_1.useState)(defaultSortDirection);
    // Internal state for filtering
    const [internalFilterValue, setInternalFilterValue] = (0, react_1.useState)('');
    const filterValue = externalFilterValue !== undefined ? externalFilterValue : internalFilterValue;
    // Internal state for selection
    const [internalSelectedRows, setInternalSelectedRows] = (0, react_1.useState)(selectedRows);
    // Update internal selection when external changes
    (0, react_1.useEffect)(() => {
        setInternalSelectedRows(selectedRows);
    }, [selectedRows]);
    // Sort data if sortable and sort column is set
    const sortedData = (0, react_1.useMemo)(() => {
        if (!sortable || !sortColumn || !sortDirection) {
            return [...data];
        }
        const column = columns.find(col => col.id === sortColumn);
        if (!column || !column.sortable) {
            return [...data];
        }
        return [...data].sort((a, b) => {
            if (column.sortFn) {
                return column.sortFn(a, b, sortDirection);
            }
            const valueA = column.accessor(a, 0);
            const valueB = column.accessor(b, 0);
            // Handle string comparison
            if (typeof valueA === 'string' && typeof valueB === 'string') {
                return sortDirection === 'asc'
                    ? valueA.localeCompare(valueB)
                    : valueB.localeCompare(valueA);
            }
            // Handle number comparison
            if (typeof valueA === 'number' && typeof valueB === 'number') {
                return sortDirection === 'asc'
                    ? valueA - valueB
                    : valueB - valueA;
            }
            // Default to string comparison
            const strA = String(valueA);
            const strB = String(valueB);
            return sortDirection === 'asc'
                ? strA.localeCompare(strB)
                : strB.localeCompare(strA);
        });
    }, [data, columns, sortable, sortColumn, sortDirection]);
    // Filter data if filterable and filter value is set
    const filteredData = (0, react_1.useMemo)(() => {
        if (!filterable || !filterValue) {
            return sortedData;
        }
        const lowerFilterValue = filterValue.toLowerCase();
        return sortedData.filter(row => {
            return columns.some(column => {
                if (!column.filterable)
                    return false;
                const value = column.accessor(row, 0);
                if (value == null)
                    return false;
                return String(value).toLowerCase().includes(lowerFilterValue);
            });
        });
    }, [sortedData, columns, filterable, filterValue]);
    // Handle column header click for sorting
    const handleHeaderClick = (column) => {
        if (!sortable || !column.sortable)
            return;
        let newDirection;
        if (sortColumn !== column.id) {
            // New column, start with ascending
            newDirection = 'asc';
        }
        else {
            // Toggle direction or clear
            newDirection = sortDirection === 'asc' ? 'desc' :
                sortDirection === 'desc' ? undefined : 'asc';
        }
        setSortColumn(newDirection ? column.id : undefined);
        setSortDirection(newDirection);
        onSort?.(column.id, newDirection);
    };
    // Handle filter change
    const handleFilterChange = (e) => {
        const value = e.target.value;
        setInternalFilterValue(value);
        onFilter?.(value);
    };
    // Handle row click
    const handleRowClick = (row, index) => {
        onRowClick?.(row, index);
    };
    // Handle row selection
    const handleRowSelection = (index) => {
        const newSelectedRows = [...internalSelectedRows];
        const selectedIndex = newSelectedRows.indexOf(index);
        if (selectedIndex === -1) {
            newSelectedRows.push(index);
        }
        else {
            newSelectedRows.splice(selectedIndex, 1);
        }
        setInternalSelectedRows(newSelectedRows);
        onSelectRows?.(newSelectedRows);
    };
    // Handle select all
    const handleSelectAll = () => {
        if (internalSelectedRows.length === filteredData.length) {
            setInternalSelectedRows([]);
            onSelectRows?.([]);
        }
        else {
            const allIndices = filteredData.map((_, index) => index);
            setInternalSelectedRows(allIndices);
            onSelectRows?.(allIndices);
        }
    };
    // Size classes
    const sizeClasses = {
        table: {
            sm: 'text-xs',
            md: 'text-sm',
            lg: 'text-base',
        },
        cell: {
            sm: 'px-2 py-1',
            md: 'px-4 py-2',
            lg: 'px-6 py-3',
        }
    };
    // Variant classes
    const variantClasses = {
        simple: {
            table: 'border-collapse',
            header: 'border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800',
            headerCell: 'font-medium text-gray-700 dark:text-gray-300 text-left',
            body: '',
            row: 'border-b border-gray-100 dark:border-gray-800',
            cell: 'text-gray-600 dark:text-gray-400',
        },
        striped: {
            table: 'border-collapse',
            header: 'border-b-2 border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800',
            headerCell: 'font-medium text-gray-700 dark:text-gray-300 text-left',
            body: '',
            row: 'border-b border-gray-100 dark:border-gray-800 even:bg-gray-50 dark:even:bg-gray-800',
            cell: 'text-gray-600 dark:text-gray-400',
        },
        bordered: {
            table: 'border-collapse border border-gray-200 dark:border-gray-700',
            header: 'bg-gray-50 dark:bg-gray-800',
            headerCell: 'font-medium text-gray-700 dark:text-gray-300 text-left border border-gray-200 dark:border-gray-700',
            body: '',
            row: '',
            cell: 'text-gray-600 dark:text-gray-400 border border-gray-200 dark:border-gray-700',
        },
        unstyled: {
            table: '',
            header: '',
            headerCell: 'text-left',
            body: '',
            row: '',
            cell: '',
        },
    };
    // Container classes
    const containerClasses = (0, cn_js_1.cn)('w-full', isScrollable && 'overflow-x-auto', className);
    // Table classes
    const tableClasses = (0, cn_js_1.cn)('w-full', sizeClasses.table[size], variantClasses[variant].table, tableClassName);
    // Header classes
    const headerClasses = (0, cn_js_1.cn)(variantClasses[variant].header, stickyHeader && 'sticky top-0 z-10', headerClassName);
    // Body classes
    const bodyClasses = (0, cn_js_1.cn)(variantClasses[variant].body, bodyClassName);
    // Get row class names
    const getRowClassNames = (row, index) => {
        return (0, cn_js_1.cn)(variantClasses[variant].row, onRowClick && 'cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700', internalSelectedRows.includes(index) && 'bg-blue-50 dark:bg-blue-900', typeof rowClassName === 'function' ? rowClassName(row, index) : rowClassName);
    };
    // Get cell class names
    const getCellClassNames = (row, column, index) => {
        return (0, cn_js_1.cn)(variantClasses[variant].cell, sizeClasses.cell[size], typeof cellClassName === 'function' ? cellClassName(row, column, index) : cellClassName);
    };
    // Footer classes
    const footerClasses = (0, cn_js_1.cn)('border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800', sizeClasses.cell[size], footerClassName);
    return ((0, jsx_runtime_1.jsxs)("div", { className: containerClasses, children: [filterable && ((0, jsx_runtime_1.jsx)("div", { className: "mb-4", children: (0, jsx_runtime_1.jsx)("input", { type: "text", value: filterValue, onChange: handleFilterChange, placeholder: "Filter...", className: "px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-800 dark:text-gray-300" }) })), (0, jsx_runtime_1.jsxs)("table", { className: tableClasses, children: [caption && ((0, jsx_runtime_1.jsx)("caption", { className: "p-2 text-left text-gray-600 dark:text-gray-400 font-medium", children: caption })), (0, jsx_runtime_1.jsx)("thead", { className: headerClasses, children: (0, jsx_runtime_1.jsxs)("tr", { children: [selectable && ((0, jsx_runtime_1.jsx)("th", { className: (0, cn_js_1.cn)(variantClasses[variant].headerCell, sizeClasses.cell[size]), children: (0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: internalSelectedRows.length === filteredData.length && filteredData.length > 0, onChange: handleSelectAll, className: "rounded border-gray-300 text-primary-600 focus:ring-primary-500" }) })), columns.map((column, index) => ((0, jsx_runtime_1.jsx)("th", { className: (0, cn_js_1.cn)(variantClasses[variant].headerCell, sizeClasses.cell[size], column.sortable && sortable && 'cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700', column.className), style: column.width ? { width: column.width } : undefined, onClick: () => column.sortable && sortable && handleHeaderClick(column), children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1", children: [column.renderHeader ? (column.renderHeader(column)) : ((0, jsx_runtime_1.jsx)("span", { children: column.header })), column.sortable && sortable && sortColumn === column.id && ((0, jsx_runtime_1.jsx)("span", { className: "inline-block ml-1", children: sortDirection === 'asc' ? '↑' : sortDirection === 'desc' ? '↓' : '' }))] }) }, column.id)))] }) }), (0, jsx_runtime_1.jsxs)("tbody", { className: bodyClasses, children: [isLoading && ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", { colSpan: columns.length + (selectable ? 1 : 0), className: (0, cn_js_1.cn)(sizeClasses.cell[size], 'text-center py-8'), children: loadingText }) })), !isLoading && filteredData.length === 0 && ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", { colSpan: columns.length + (selectable ? 1 : 0), className: (0, cn_js_1.cn)(sizeClasses.cell[size], 'text-center py-8'), children: emptyText }) })), !isLoading && filteredData.map((row, rowIndex) => ((0, jsx_runtime_1.jsxs)("tr", { className: getRowClassNames(row, rowIndex), onClick: () => onRowClick && handleRowClick(row, rowIndex), children: [selectable && ((0, jsx_runtime_1.jsx)("td", { className: (0, cn_js_1.cn)(variantClasses[variant].cell, sizeClasses.cell[size]), children: (0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: internalSelectedRows.includes(rowIndex), onChange: (e) => {
                                                e.stopPropagation();
                                                handleRowSelection(rowIndex);
                                            }, className: "rounded border-gray-300 text-primary-600 focus:ring-primary-500" }) })), columns.map((column, colIndex) => {
                                        const cellValue = column.accessor(row, rowIndex);
                                        return ((0, jsx_runtime_1.jsx)("td", { className: getCellClassNames(row, column, rowIndex), style: column.width ? { width: column.width } : undefined, children: column.renderCell
                                                ? column.renderCell(cellValue, row, rowIndex)
                                                : cellValue }, `${rowIndex}-${column.id}`));
                                    })] }, rowIndex)))] }), hasFooter && ((0, jsx_runtime_1.jsx)("tfoot", { className: footerClasses, children: (0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", { colSpan: columns.length + (selectable ? 1 : 0), children: footer }) }) }))] })] }));
}
TailwindTable.displayName = 'TailwindTable';
exports.default = TailwindTable;
//# sourceMappingURL=TailwindTable.js.map