zeed-dynamic-table
v2.0.0
Published
A flexible and dynamic table component for React and Next.js applications without Tailwind dependencies
Maintainers
Readme
React Dynamic Table
A highly configurable, feature-rich table component library for React applications with advanced rendering capabilities, dark mode support, and flexible customization options.
Features
- 🔄 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
Installation
npm install react-dynamic-table
# or
yarn add react-dynamic-tableBasic Usage
import { DynamicTable } from "react-dynamic-table";
// Sample data
const users = [
{ id: 1, name: "John Doe", email: "[email protected]", status: "Active" },
{ id: 2, name: "Jane Smith", email: "[email protected]", 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}`),
}}
/>
);
}Advanced Configuration
Column Types
The library supports various column types with specific rendering behaviors:
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>;
};
};Pagination
Configure pagination with the following options:
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>;
};Dynamic Data Access
The table supports nested data access using dot notation:
// Data with nested structure
const items = [
{
id: 1,
name: "John Doe",
contact: {
email: "[email protected]",
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" },
];Dynamic Links
Create links with dynamic parameters from row data:
{
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.
Component Hierarchy
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)Individual Component Exports
You can import individual components for custom table implementations:
import {
Table,
Thead,
Tbody,
Th,
Td,
ActionTd,
PaginationController,
} from "react-dynamic-table";Conditional Rendering
The library supports conditional rendering based on data values:
{
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'
}
}
}
]
}Custom Cell Rendering
Use the actionOptions.components property to create custom cell content:
{
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>
)
}
}Dark Mode Support
The library includes built-in dark mode support using Tailwind CSS classes:
// Add dark mode class to your app's root element
document.documentElement.classList.add("dark");
// The table will automatically adapt to dark modeAdvanced Usage Examples
Table with Inline Editing
{
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
}
}
}Dynamic Expressions in Props
You can use dynamic expressions in various props using the {} syntax:
{
columnName: 'Status',
accessor: 'status',
normalProps: {
td: {
className: 'font-medium {status === "active" ? "text-green-600" : "text-red-600"}'
}
}
}Nested Property Access with Square Brackets
Use square brackets to access nested properties:
{
columnName: 'Full Address',
useLink: true,
linkOptions: {
href: 'https://maps.google.com/?q=[location.address], [location.city], [location.country]'
}
}API Reference
DynamicTable Props
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
};Utility Functions
The library exports several utility functions that can be useful:
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);License
MIT
