zeed-dynamic-table
Version:
A flexible and dynamic table component for React and Next.js applications without Tailwind dependencies
420 lines (350 loc) ⢠10.5 kB
Markdown
A highly configurable, feature-rich table component library for React applications with advanced rendering capabilities, dark mode support, and flexible customization options.
- š **Dynamic Data Rendering**: Display any data structure with custom cell rendering
- š **Dark Mode Support**: Built-in light and dark theme compatibility
- š± **Responsive Design**: Mobile-friendly layout with responsive controls
- š **Advanced Pagination**: Intuitive pagination with configurable controls
- š§© **Composable Components**: Use the entire table or individual components
- š **Search & Filtering**: Built-in search functionality
- š **Customizable Headers & Cells**: Full control over column rendering
- š **Automatic Link Support**: Both standard and Next.js links supported
- šØ **Style Flexibility**: Easy styling with Tailwind CSS and className props
- ā ļø **Error Handling**: Robust error recovery with useful debug information
```bash
npm install react-dynamic-table
yarn add react-dynamic-table
```
```tsx
import { DynamicTable } from "react-dynamic-table";
// Sample data
const users = [
{ id: 1, name: "John Doe", email: "john@example.com", status: "Active" },
{ id: 2, name: "Jane Smith", email: "jane@example.com", status: "Inactive" },
// ...more data
];
// Column configuration
const columns = [
{ columnName: "ID", accessor: "id" },
{ columnName: "Name", accessor: "name" },
{ columnName: "Email", accessor: "email" },
{
columnName: "Status",
accessor: "status",
useChip: true,
chipOptions: {
className: (item) =>
item.status === "Active"
? "bg-green-100 text-green-800"
: "bg-red-100 text-red-800",
},
},
{
columnName: "Actions",
useAction: true,
actionOptions: {
components: (item) => (
<div className="flex space-x-2">
<button className="text-blue-600 hover:underline">Edit</button>
<button className="text-red-600 hover:underline">Delete</button>
</div>
),
},
},
];
function UserTable() {
return (
<DynamicTable
items={users}
columns={columns}
tableName="Users"
keyAccessor="id"
topContentOptions={{
searchInput: {
placeholder: "Search users...",
onChange: (e) => console.log(e.target.value),
},
addButton: {
title: "Add User",
onClick: () => console.log("Add user clicked"),
},
}}
usePagination={true}
pagination={{
page: 1,
per_page: 10,
totalPages: 5,
handlePageChange: (page) => console.log(`Page changed to ${page}`),
}}
/>
);
}
```
The library supports various column types with specific rendering behaviors:
```tsx
type ColumnType<K extends string> = {
// Basic properties
columnName: string; // Display name in the header
accessor?: K; // Data property to access (supports dot notation)
static?: string | number; // Static value for all cells in this column
showIf?: boolean; // Conditional display of the entire column
rename?: string; // Alternative display name
// Rendering options
useDate?: boolean; // Format as date
join?: K[]; // Join multiple fields
// Special column types
useAction?: boolean; // Action buttons column
actionOptions?: ActionsType;
useOption?: boolean; // Dropdown/select column
optionOptions?: OptionOptions;
useLink?: boolean; // Make content a clickable link
linkOptions?: LinkOptionsType;
useChip?: boolean; // Display as a badge/chip
chipOptions?: ChipOptions;
// Conditional rendering
useCondition?: boolean;
condtions?: ColumnConditionsType<K>[];
// Custom props
normalProps?: {
th?: HTMLProps<HTMLTableColElement>;
td?: HTMLProps<HTMLTableCellElement>;
};
};
```
Configure pagination with the following options:
```tsx
type PAGINATION_TYPE = {
per_page: number; // Items per page
page: number; // Current page
totalPages: number; // Total number of pages
handlePageChange: (page: number) => void; // Page change handler
per_pageComponent?: ReactNode; // Custom per-page selector
baseProps?: HTMLProps<HTMLDivElement>;
leftBaseProps?: HTMLProps<HTMLDivElement>;
rightBaseProps?: HTMLProps<HTMLUListElement>;
};
```
The table supports nested data access using dot notation:
```tsx
// Data with nested structure
const items = [
{
id: 1,
name: "John Doe",
contact: {
email: "john@example.com",
phone: {
home: "555-1234",
work: "555-5678",
},
},
},
];
// Column configuration with nested access
const columns = [
{ columnName: "ID", accessor: "id" },
{ columnName: "Name", accessor: "name" },
{ columnName: "Email", accessor: "contact.email" },
{ columnName: "Work Phone", accessor: "contact.phone.work" },
];
```
Create links with dynamic parameters from row data:
```tsx
{
columnName: 'View Details',
accessor: 'name',
useLink: true,
linkOptions: {
href: '/users/[id]/profile',
className: 'text-blue-600 hover:underline'
}
}
```
The `[id]` part will be replaced with the actual `id` value from each row.
The library consists of several composable components:
```
DynamicTable
āāā TableTopContent (search, add button)
āāā TableBase
ā āāā Table
ā āāā Thead
ā ā āāā TheadTr (header row)
ā ā āāā Th (header cells)
ā āāā Tbody
ā āāā TbodyTr (body rows)
ā āāā Td (standard cells)
ā āāā ActionTd (action cells)
ā āāā Link (linked cells)
āāā PaginationController
āāā PaginationLeftBase (page info)
āāā PaginationRightBase (page navigation)
```
You can import individual components for custom table implementations:
```tsx
import {
Table,
Thead,
Tbody,
Th,
Td,
ActionTd,
PaginationController,
} from "react-dynamic-table";
```
The library supports conditional rendering based on data values:
```tsx
{
columnName: 'Status Display',
accessor: 'status',
useCondition: true,
condtions: [
{
// Render differently when status is "active"
condtion: {
compare: ['[status]', 'active']
},
redner: {
useChip: true,
chipOptions: {
className: 'bg-green-100 text-green-800'
}
}
},
{
// Render differently when status is "pending"
condtion: {
compare: ['[status]', 'pending']
},
redner: {
useChip: true,
chipOptions: {
className: 'bg-yellow-100 text-yellow-800'
}
}
}
]
}
```
Use the `actionOptions.components` property to create custom cell content:
```tsx
{
columnName: 'Custom Cell',
useAction: true,
actionOptions: {
components: (item) => (
<div className="flex items-center gap-2">
<img
src={item.avatar}
alt={item.name}
className="w-8 h-8 rounded-full"
/>
<div>
<div className="font-medium">{item.name}</div>
<div className="text-sm text-gray-500">{item.role}</div>
</div>
</div>
)
}
}
```
The library includes built-in dark mode support using Tailwind CSS classes:
```tsx
// Add dark mode class to your app's root element
document.documentElement.classList.add("dark");
// The table will automatically adapt to dark mode
```
```tsx
{
columnName: 'Status',
accessor: 'status',
useOption: true,
optionOptions: {
data: ['Active', 'Inactive', 'Pending'],
apiLink: '/api/update-status',
onRes: (response) => {
console.log('Status updated:', response);
// Update your local data or refetch
}
}
}
```
You can use dynamic expressions in various props using the `{}` syntax:
```tsx
{
columnName: 'Status',
accessor: 'status',
normalProps: {
td: {
className: 'font-medium {status === "active" ? "text-green-600" : "text-red-600"}'
}
}
}
```
Use square brackets to access nested properties:
```tsx
{
columnName: 'Full Address',
useLink: true,
linkOptions: {
href: 'https://maps.google.com/?q=[location.address], [location.city], [location.country]'
}
}
```
```tsx
type DynamicTablePropsType<T> = {
tableName?: string; // Display name for the table
topContent?: ReactNode; // Custom top content
topContentOptions?: TopContentOptionsType; // Configuration for built-in top content
columns: ColumnType<NestedFieldPaths<T>>[]; // Column definitions
items: T[]; // Data items to display
keyAccessor?: NestedFieldPaths<T>; // Unique key field in data
emptyContent?: ReactNode; // Content to show when no data
isLoading?: boolean; // Loading state flag
loadingContent?: ReactNode; // Content to show while loading
actions?: ActionsType[]; // Global actions configuration
actionColumName?: string; // Custom name for action column
usePagination?: boolean; // Enable/disable pagination
pagination?: PAGINATION_TYPE; // Pagination configuration
// Various HTML props for customizing subcomponents
tBodyProps?: HTMLProps<HTMLTableSectionElement>;
tHeadProps?: HTMLProps<HTMLTableSectionElement>;
tHeadTrProps?: HTMLProps<HTMLTableRowElement>;
tBodyTrProps?: HTMLProps<HTMLTableRowElement>;
baseProps?: HTMLProps<HTMLDivElement>;
tableBaseProps?: HTMLProps<HTMLDivElement>;
tableProps?: HTMLProps<HTMLTableElement>;
id?: string; // Custom ID for the table
};
```
The library exports several utility functions that can be useful:
```tsx
import { cn, getNestedValue, generateDynamicLink } from "react-dynamic-table";
// Combine class names with Tailwind CSS
const className = cn("base-class", conditional && "conditional-class");
// Get nested value from object using dot notation
const email = getNestedValue(user, "contact.email");
// Generate dynamic URL with data values
const profileUrl = generateDynamicLink("/users/[id]/profile", user);
```
MIT