UNPKG

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
# 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 ```bash npm install react-dynamic-table # or yarn add react-dynamic-table ``` ## Basic Usage ```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}`), }} /> ); } ``` ## Advanced Configuration ### Column Types 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>; }; }; ``` ### Pagination 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>; }; ``` ### Dynamic Data Access 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" }, ]; ``` ### Dynamic Links 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. ## 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: ```tsx import { Table, Thead, Tbody, Th, Td, ActionTd, PaginationController, } from "react-dynamic-table"; ``` ## Conditional Rendering 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' } } } ] } ``` ## Custom Cell Rendering 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> ) } } ``` ## Dark Mode Support 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 ``` ## Advanced Usage Examples ### Table with Inline Editing ```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 } } } ``` ### Dynamic Expressions in Props 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"}' } } } ``` ### Nested Property Access with Square Brackets 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]' } } ``` ## API Reference ### DynamicTable Props ```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 }; ``` ## Utility Functions 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); ``` ## License MIT