@ziprin/react-table
v1.1.2
Published
A lightweight, customizable React table component with RTL support, sorting, filtering, and pagination built on top of TanStack Table
Maintainers
Readme
@ziprin/react-table
A lightweight, customizable React table component with RTL support, sorting, filtering, and pagination built on top of TanStack Table v8.
✨ Features
- 🚀 RTL Support: Complete Persian/Farsi and right-to-left support
- 📱 Responsive Design: Mobile-friendly with auto-hide columns
- 🎨 Customizable: Full styling control with Tailwind CSS
- ⚡ Performance: Optimized with React.useMemo and efficient re-renders
- 🔧 TypeScript: Full type safety and IntelliSense support
- 🎯 TanStack Table v8: Latest version with all features
- 🎛️ State Management: Internal and external state control
- 📊 Multiple Modes: Scroll, AutoHide, Cards for mobile
📦 Installation
For Vite Projects
# Install the package and its peer dependency
pnpm add @ziprin/react-table @tanstack/react-table
# That's it! No additional setup neededFor Next.js Projects
# Install the package and its peer dependency
pnpm add @ziprin/react-table @tanstack/react-table
# That's it! No additional setup neededManual Installation (if needed)
# If you don't have React installed
pnpm add react react-dom
# Then install the table package
pnpm add @ziprin/react-table @tanstack/react-tableNote: This package works with React 18+ and React 19. No additional dependencies or build tools required!
🚀 Quick Start
Basic Usage
import { Table, TableProvider } from '@ziprin/react-table';
import type { ColumnDef } from '@tanstack/react-table';
type User = {
id: string;
name: string;
email: string;
status: 'active' | 'inactive';
};
const columns: ColumnDef<User>[] = [
{
header: 'نام',
accessorKey: 'name',
},
{
header: 'ایمیل',
accessorKey: 'email',
},
{
header: 'وضعیت',
accessorKey: 'status',
},
];
const data: User[] = [
{ id: '1', name: 'علی احمدی', email: '[email protected]', status: 'active' },
{ id: '2', name: 'مریم رضایی', email: '[email protected]', status: 'inactive' },
];
function App() {
return (
<TableProvider data={data} columns={columns}>
<Table />
</TableProvider>
);
}Advanced Usage with Custom Styling
import { Table, TableProvider, useTableMethods } from '@ziprin/react-table';
import type { ColumnDef } from '@tanstack/react-table';
const columns: ColumnDef<User>[] = [
{
header: 'نام',
accessorKey: 'name',
meta: {
priority: 0, // Mobile priority (0-5)
align: 'right',
sticky: 'right',
},
},
{
header: 'وضعیت',
accessorKey: 'status',
meta: {
customCell: ({ value }) => (
<span className={`px-2 py-1 rounded text-xs ${
value === 'active' ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'
}`}>
{value === 'active' ? 'فعال' : 'غیرفعال'}
</span>
),
},
},
];
function AdvancedTable() {
return (
<TableProvider
data={data}
columns={columns}
dir="rtl"
density="spacious"
mobileMode="autoHide"
selectionMode="multiple"
>
<Table />
</TableProvider>
);
}📚 API Reference
TableProvider Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| data | T[] | - | Array of data |
| columns | ColumnDef<T>[] | - | Column definitions |
| dir | 'ltr' \| 'rtl' | 'rtl' | Text direction |
| density | 'compact' \| 'normal' \| 'spacious' | 'normal' | Row density |
| mobileMode | 'scroll' \| 'autoHide' \| 'cards' | 'scroll' | Mobile behavior |
| paginationMode | 'pages' \| 'infinite' | 'pages' | Pagination type |
| selectionMode | 'none' \| 'single' \| 'multiple' | 'multiple' | Row selection |
| sorting | SortingState | - | External sorting control |
| onSortingChange | (sorting: SortingState) => void | - | Sorting change handler |
| pagination | PaginationState | - | External pagination control |
| onPaginationChange | (pagination: PaginationState) => void | - | Pagination change handler |
Column Meta Options
meta: {
priority: 0, // Mobile priority (0-5)
align: "center", // "left" | "center" | "right" | "start" | "end"
sticky: "left", // "left" | "right" | "start" | "end" | false
minWidth: 120, // Minimum width
maxWidth: 300, // Maximum width
icon: <IconComponent />, // Header icon
cellIcon: (value) => <Icon />, // Cell icon function
customCell: CustomComponent, // Custom cell component
} as ColumnMetaHooks
useTable
Access the table instance and methods:
import { useTable } from '@ziprin/react-table';
function MyComponent() {
const table = useTable();
const handleExport = () => {
const selected = table.getSelectedRowModel().rows;
console.log('Selected:', selected);
};
return (
<button onClick={handleExport}>
Export Selected
</button>
);
}useTableMethods
Access table methods directly:
import { useTableMethods } from '@ziprin/react-table';
function MyComponent() {
const { getSelectedRowModel, getSortedRowModel } = useTableMethods();
return (
<div>
Selected: {getSelectedRowModel().rows.length}
</div>
);
}🎨 Styling
Custom ClassNames
<TableProvider
data={data}
columns={columns}
classNames={{
container: {
root: "bg-white rounded-lg shadow-lg border"
},
header: {
cell: "font-bold text-gray-900 bg-gray-50"
},
body: {
row: "hover:bg-gray-50 border-b"
},
pagination: {
root: "bg-gray-50 px-4 py-2"
}
}}
>
<Table />
</TableProvider>Mobile Modes
- Scroll Mode (default): Horizontal scrolling
- AutoHide Mode: Hide columns based on priority
- Cards Mode: Display as cards on mobile
🔧 Configuration
TypeScript Support
import type {
DataGridProps,
ColumnMeta,
Density,
MobileMode
} from '@ziprin/react-table';
// Your component with full type safetyExternal State Control
import { useState } from 'react';
import { Table, TableProvider } from '@ziprin/react-table';
import type { SortingState, PaginationState } from '@tanstack/react-table';
function ControlledTable() {
const [sorting, setSorting] = useState<SortingState>([]);
const [pagination, setPagination] = useState<PaginationState>({
pageIndex: 0,
pageSize: 10,
});
return (
<TableProvider
data={data}
columns={columns}
sorting={sorting}
onSortingChange={setSorting}
pagination={pagination}
onPaginationChange={setPagination}
>
<Table />
</TableProvider>
);
}📱 Mobile Support
Priority System
Set column priorities for mobile display:
const columns: ColumnDef<User>[] = [
{
header: 'نام',
accessorKey: 'name',
meta: { priority: 0 }, // Always visible
},
{
header: 'ایمیل',
accessorKey: 'email',
meta: { priority: 1 }, // Visible on larger screens
},
{
header: 'جزئیات',
accessorKey: 'details',
meta: { priority: 2 }, // Hidden on small screens
},
];Responsive Breakpoints
The component automatically adapts to screen sizes:
- Mobile: < 768px
- Tablet: 768px - 1024px
- Desktop: > 1024px
🚀 Performance
Optimization Features
- React.useMemo: Optimized re-renders
- Virtualization Ready: Ready for large datasets
- Tree Shaking: Only import what you use
- Minimal Bundle: ~20KB gzipped
Best Practices
// ✅ Good: Memoize columns
const columns = useMemo(() => [
// column definitions
], []);
// ✅ Good: Memoize data transformations
const processedData = useMemo(() =>
data.map(item => ({ ...item, processed: true })),
[data]
);
// ❌ Avoid: Creating columns in render
const columns = [
// This will cause unnecessary re-renders
];🧪 Testing
Unit Tests
import { render, screen } from '@testing-library/react';
import { Table, TableProvider } from '@ziprin/react-table';
test('renders table with data', () => {
render(
<TableProvider data={testData} columns={testColumns}>
<Table />
</TableProvider>
);
expect(screen.getByText('نام')).toBeInTheDocument();
});E2E Tests
import { test, expect } from '@playwright/test';
test('table sorting works', async ({ page }) => {
await page.goto('/');
await page.click('[data-testid="sort-name"]');
await expect(page.locator('.sorted')).toBeVisible();
});📦 Bundle Size
| Component | Size (gzipped) | |-----------|----------------| | Core (Table + Provider) | ~8-12KB | | With all features | ~15-20KB | | Full package | ~20-25KB |
🔗 Dependencies
Peer Dependencies
react: ^18.0.0 || ^19.0.0react-dom: ^18.0.0 || ^19.0.0@tanstack/react-table: ^8.0.0
Optional Dependencies
tailwindcss: For styling (recommended)
🤝 Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
📄 License
MIT License - see LICENSE file for details.
🆘 Support
🙏 Acknowledgments
- Built on top of TanStack Table
- Styled with Tailwind CSS
- Icons from Heroicons
Made with ❤️ for the Persian/Farsi developer community
