UNPKG

@madulinux/react-datatable

Version:

Reusable DataTable component for React with sorting, paging, filter, and export.

604 lines (501 loc) โ€ข 15.5 kB
# @madulinux/react-datatable [![npm version](https://img.shields.io/npm/v/@madulinux/react-datatable.svg)](https://www.npmjs.com/package/@madulinux/react-datatable) [![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/) [![React](https://img.shields.io/badge/React-17%2B-61dafb.svg)](https://reactjs.org/) Enterprise-grade React components for advanced data tables and select inputs with full TypeScript support, accessibility, and modern UI/UX. --- ## ๐Ÿ“š Quick Links - ๐Ÿ“– [Complete Documentation](DOCUMENTATION.md) - ๐Ÿ”ฝ [Select2 Documentation](SELECT2_DOCUMENTATION.md) - ๐ŸŒ [npm Package](https://www.npmjs.com/package/@madulinux/react-datatable) - ๐Ÿ› [Report Issues](https://github.com/madulinux/react-datatable/issues) --- ## โœจ Features ### DataTable Component - โœ… **Sorting** - Multi-column with default sort support - โœ… **Pagination** - Customizable with per-page options - โœ… **Search** - Global search functionality - โœ… **Filtering** - Simple & advanced filters with filter builder - โœ… **Row Selection** - Single & multiple with bulk actions - โœ… **Export** - CSV & Excel support - โœ… **Column Management** - Visibility toggle & drag-to-reorder - โœ… **Responsive** - Mobile, tablet, desktop optimized - โœ… **Accessibility** - WCAG compliant, keyboard navigation - โœ… **Error Handling** - Robust error management with retry - โœ… **State Persistence** - Save preferences to localStorage - โœ… **TypeScript** - Full type safety with generics ### Select2 Component - โœ… **Async Data** - Load options from API with pagination - โœ… **Search** - Real-time search with debouncing - โœ… **Multi-Select** - Select multiple items with tags - โœ… **Min Input** - Require minimum characters before fetch - โœ… **Max Selections** - Limit number of selections - โœ… **Select All / Clear All** - Bulk selection actions - โœ… **Error Handling** - Robust error management - โœ… **Keyboard Navigation** - Full keyboard support - โœ… **Accessibility** - Screen reader support, ARIA attributes - โœ… **Custom Rendering** - Customize options and selected display --- ## ๐Ÿš€ Installation ```bash npm install @madulinux/react-datatable ``` ### Peer Dependencies ```json { "react": ">=17.0.0", "react-dom": ">=17.0.0" } ``` --- ## ๐Ÿ”ฅ Quick Start ### DataTable - Basic Example ```tsx import DataTable from '@madulinux/react-datatable'; interface User { id: number; name: string; email: string; status: 'active' | 'inactive'; } const columns = [ { key: 'name', label: 'Name', sortable: true }, { key: 'email', label: 'Email', sortable: true }, { key: 'status', label: 'Status', render: (user) => ( <span className={user.status === 'active' ? 'text-green-600' : 'text-gray-400'}> {user.status} </span> ) } ]; const fetchData = async ({ page, perPage, search, orderBy, orderDir }) => { const response = await fetch( `/api/users?page=${page}&perPage=${perPage}&search=${search}` ); const data = await response.json(); return { data: data.users, total: data.total }; }; function UsersTable() { return ( <DataTable columns={columns} fetchData={fetchData} defaultPerPage={25} defaultOrderBy="name" defaultOrderDir="asc" /> ); } ``` ### Select2 - Basic Example ```tsx import { Select2 } from '@madulinux/react-datatable'; interface City { id: number; label: string; } function CitySelector() { const [selectedCity, setSelectedCity] = useState<City | null>(null); const fetchCities = async ({ search, page }) => { const response = await fetch( `/api/cities?search=${search}&page=${page}&perPage=20` ); const data = await response.json(); return { data: data.cities, hasMore: data.hasMore }; }; return ( <Select2 value={selectedCity} onChange={setSelectedCity} fetchOptions={fetchCities} placeholder="Select a city..." /> ); } ``` --- ## ๐Ÿ“– Documentation ### Complete Guides - **[DOCUMENTATION.md](DOCUMENTATION.md)** - Complete documentation for all components - **[SELECT2_DOCUMENTATION.md](SELECT2_DOCUMENTATION.md)** - Detailed Select2 component guide ### Key Topics 1. **DataTable** - Column configuration - Sorting & pagination - Filtering (simple & advanced) - Row selection & bulk actions - Export functionality - Responsive design - State persistence 2. **Select2** - Async data fetching - Search & debouncing - Multi-select mode - Min input & max selections - Custom rendering - Error handling 3. **Advanced Features** - Advanced filter builder - Column visibility & reordering - Export to CSV/Excel - Responsive breakpoints - Accessibility features --- ## ๐ŸŽฏ Advanced Examples ### DataTable with All Features ```tsx <DataTable columns={columns} fetchData={fetchUsers} filters={filters} actions={(user) => ( <div className="flex gap-2"> <button onClick={() => editUser(user)}>Edit</button> <button onClick={() => deleteUser(user)}>Delete</button> </div> )} selectionConfig={{ enableRowSelection: true, selectionMode: 'multiple', bulkActions: [ { label: 'Delete Selected', action: async (rows) => await deleteUsers(rows), variant: 'destructive', requiresConfirmation: true } ] }} exportConfig={{ enableExport: true, exportFormats: ['csv', 'excel'], exportFileName: 'users-export' }} responsiveConfig={{ enableResponsive: true, mobileStackedView: true, compactMode: true }} enableColumnVisibility enableColumnReordering enableAdvancedFilters storageKey="users-table" /> ``` ### Select2 Multi-Select with Max Limit ```tsx <Select2 isMulti maxSelections={5} minInput={2} value={selectedItems} onChange={setSelectedItems} fetchOptions={fetchItems} onMaxSelectionsReached={() => { toast.error('Maximum 5 items can be selected'); }} placeholder="Search items (min 2 characters)..." renderOption={(item) => ( <div className="flex items-center gap-2"> <img src={item.image} className="w-8 h-8 rounded" /> <span>{item.label}</span> </div> )} /> ``` --- ## ๐ŸŽจ Styling This package uses **Tailwind CSS** and **shadcn/ui** components. You can customize styling using: 1. **className props** ```tsx <DataTable className="bg-white rounded-lg shadow" /> ``` 2. **Tailwind configuration** ```js // tailwind.config.js module.exports = { theme: { extend: { colors: { primary: {...} } } } } ``` 3. **CSS variables** ```css :root { --primary: ...; --muted: ...; } ``` --- ## โ™ฟ Accessibility All components are built with accessibility in mind: - โœ… **WCAG 2.1 AA** compliant - โœ… **Keyboard navigation** - Full keyboard support - โœ… **Screen readers** - ARIA attributes and live regions - โœ… **Focus management** - Proper focus handling - โœ… **Color contrast** - Meets contrast requirements --- ## ๐Ÿงช TypeScript Support Full TypeScript support with generics: ```tsx interface User { id: number; name: string; email: string; } // Type-safe columns const columns: DataTableColumn<User>[] = [ { key: 'name', label: 'Name' }, { key: 'email', label: 'Email' } ]; // Type-safe Select2 <Select2<User> value={selectedUser} onChange={setSelectedUser} fetchOptions={fetchUsers} /> ``` --- ## ๐Ÿ“ฆ What's Included - `DataTable` - Main data table component - `Select2` - Advanced select component - `DataTablePagination` - Standalone pagination - `AdvancedFilterValueInput` - Filter input component - `DataTableUtils` - Utility functions - Type definitions for all components --- ## ๐Ÿ› ๏ธ Troubleshooting ### Common Issues **Data not loading?** ```tsx // Ensure fetchData returns correct format return { data: [...], total: 100 }; ``` **TypeScript errors?** ```tsx // Items must have id and label interface Item { id: number; label: string; } ``` **Infinite re-renders?** ```tsx // Memoize fetchData const fetchData = useCallback(async () => {...}, []); ``` See [DOCUMENTATION.md](DOCUMENTATION.md#troubleshooting) for more solutions. --- ## ๐Ÿค Contributing Contributions are welcome! Please feel free to submit a Pull Request. 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/AmazingFeature`) 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`) 4. Push to the branch (`git push origin feature/AmazingFeature`) 5. Open a Pull Request --- ## ๐Ÿ“‹ Changelog ### v1.0.7 (2024-11-03) **๐Ÿ› Critical Bug Fix - Filter Not Triggering Fetch** - Fixed filter changes not triggering data fetch - Wrapped `activeFilterValues` in `useMemo` to ensure changes are tracked - Filter state changes now properly trigger `fetchTableData` re-execution - Added debug logging to track filter value changes - Enhanced debug logging: - `activeFilterValues updated: {...}` - When filter values change - `Filter changed: [key] [value]` - When user changes filter - `Fetching data with filters: {...}` - When API is called **Root Cause:** `activeFilterValues` was a simple assignment (`externalFilterValues ?? filterValues`), which didn't create a new reference when `filterValues` changed. React's dependency tracking couldn't detect the change, so `fetchTableData` wasn't re-executed. **Solution:** ```typescript // Before (broken) const activeFilterValues = externalFilterValues ?? filterValues; // After (fixed) const activeFilterValues = useMemo(() => { return externalFilterValues ?? filterValues; }, [externalFilterValues, filterValues]); ``` **Expected Console Logs After Fix:** ``` Filter changed: status active New filter values: {status: 'active'} activeFilterValues updated: {status: 'active'} โ† NEW Fetching data with filters: {status: 'active'} โ† Now triggers! ``` ### v1.0.6 (2024-11-03) **๐Ÿ› Critical Bug Fixes** - Fixed "SelectItem cannot have empty value" error in select/multiselect filters - Changed placeholder value from `""` to `"__all__"` - Properly handles undefined/cleared filter values - Fixed "Multiple React instances" error when using date filter - Removed DatePicker component that was bundling React - Replaced with native HTML5 `<input type="date">` - Date and daterange filters now use native browser date picker - Removed unused DatePicker import to prevent React bundling issues **โš ๏ธ Breaking Changes** - Date filters now use native HTML5 date input instead of custom DatePicker - DatePicker component is no longer used (prevents React bundling conflicts) **๐Ÿ“ฆ Migration** If you're using date filters: ```tsx // Still works the same way, just uses native date input { key: 'createdAt', label: 'Created Date', type: 'date', width: 180 } ``` ### v1.0.5 (2024-11-03) **โœจ Major Filter System Improvement** - Created `DataTableFilterInput` component for proper filter type handling - Full support for all filter types: - `select` - Dropdown with options - `multiselect` - Multiple selection (simplified) - `text` / `search` - Text input - `number` - Number input - `date` - Date picker - `daterange` - Date range picker (from/to) - `boolean` - Checkbox - Enhanced `DataTableFilter` interface: - `width`: Custom width for filter input - `fetchOptions`: Async data fetching for select/multiselect - Filters now properly use their `type` property instead of defaulting to select - Better responsive sizing for filter inputs - Improved filter value handling (supports string, number, boolean, undefined) **๐Ÿ“ฆ Usage Example** ```tsx <DataTable columns={columns} fetchData={fetchData} filters={[ { key: 'status', label: 'Status', type: 'select', options: [ { value: 'active', label: 'Active' }, { value: 'inactive', label: 'Inactive' } ], width: 150 }, { key: 'search', label: 'Search', type: 'text', placeholder: 'Search products...', width: 250 }, { key: 'price', label: 'Price', type: 'number', placeholder: 'Min price', width: 120 }, { key: 'createdAt', label: 'Created Date', type: 'date', width: 180 }, { key: 'featured', label: 'Featured', type: 'boolean' } ]} /> ``` ### v1.0.4 (2024-11-03) **โœจ New Features & Improvements** - Added `DataTableHeaderConfig` interface for header customization - `showHeader`: Show/hide table header - `stickyHeader`: Make header sticky on scroll - `headerClassName`: Custom className for header - `headerRowClassName`: Custom className for header row - `headerHeight`: Custom header height - Enhanced `DataTableColumn` interface: - `width`, `minWidth`, `maxWidth`: Proper CSS width support (accepts '200px', '20%', or 200) - `headerClassName`: Custom className for header cells - `cellClassName`: Custom className for body cells - `align`: Text alignment ('left' | 'center' | 'right') - Fixed width property - now uses inline styles instead of broken Tailwind classes - Added utility functions: `getColumnStyle()`, `getAlignmentClass()`, `getCSSWidth()` - Improved responsive table styling with better overflow handling **๐Ÿ› Bug Fixes** - Fixed column width not working (was using invalid `'w-' + col.width` approach) - Fixed header and cell alignment support **๐Ÿ“ฆ Usage Example** ```tsx <DataTable columns={[ { key: 'name', label: 'Name', width: 200, // or '200px' or '20%' align: 'left', headerClassName: 'bg-blue-50', cellClassName: 'font-medium' }, { key: 'price', label: 'Price', width: '15%', align: 'right' } ]} headerConfig={{ stickyHeader: true, headerClassName: 'bg-gray-100' }} // ... other props /> ``` ### v1.0.3 (2024-11-02) **๐Ÿ› Critical Bug Fix** - Fixed "Invalid hook call" error from Radix UI components bundling their own React - Added esbuild alias to ensure React is never bundled from any dependency - Configured `noExternal` for Radix UI packages to bundle them but use external React - Package now correctly shares single React instance with host application across all dependencies **๐Ÿ“ฆ Migration** If you're upgrading from v1.0.2 or earlier: 1. Update to v1.0.3: `npm install @madulinux/react-datatable@latest` 2. Clear your build cache: `npm run build` or `php artisan view:clear` 3. Restart your dev server 4. Error should be completely resolved ### v1.0.2 (2024-11-02) **๐Ÿ› Bug Fixes** - Fixed "Invalid hook call" error when using package in Laravel Inertia and other React applications - Removed React from bundled dependencies - now properly uses peer dependencies - Added `react/jsx-runtime` and `react/jsx-dev-runtime` to external dependencies - Package now correctly shares React instance with host application **โš ๏ธ Note:** This version had partial fix. v1.0.3 completes the fix for Radix UI dependencies. --- ## ๐Ÿ“ License MIT ยฉ [madulinux](https://github.com/madulinux) --- ## ๐Ÿ‘ค Author **madulinux** - GitHub: [@madulinux](https://github.com/madulinux) - npm: [~madulinux](https://www.npmjs.com/~madulinux) --- ## ๐ŸŒŸ Show Your Support Give a โญ๏ธ if this project helped you! --- **Made with โค๏ธ by madulinux**