Gathering detailed insights and metrics for nextjs-reusable-table
Gathering detailed insights and metrics for nextjs-reusable-table
Gathering detailed insights and metrics for nextjs-reusable-table
Gathering detailed insights and metrics for nextjs-reusable-table
A highly customizable and reusable table component for Next.js applications, built with TypeScript and the latest technologies.
npm install nextjs-reusable-table
Typescript
Module System
Node Version
NPM Version
TypeScript (90.07%)
CSS (9.41%)
JavaScript (0.53%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
0BSD License
3 Stars
141 Commits
1 Watchers
1 Branches
1 Contributors
Updated on Jun 15, 2025
Latest Version
3.5.8
Package Id
nextjs-reusable-table@3.5.8
Unpacked Size
181.18 kB
Size
46.35 kB
File Count
11
NPM Version
10.9.0
Node Version
18.17.0
Published on
Jun 08, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
4
A highly customizable and reusable table component for Next.js applications, built with TypeScript and TailwindCSS.
1npm install nextjs-reusable-table@latest 2# or 3yarn add nextjs-reusable-table@latest 4# or 5pnpm add nextjs-reusable-table@latest
Note: This is a Client Component ("use client"). Using it in purely SSR contexts may require additional handling to avoid hydration mismatches.
1"use client"; 2import React from "react"; 3import { TableComponent } from "nextjs-reusable-table"; 4import "nextjs-reusable-table/dist/index.css"; 5 6interface User { 7 id: number; 8 name: string; 9} 10 11export default function BasicTable() { 12 const data: User[] = [ 13 { id: 1, name: "Alice" }, 14 { id: 2, name: "Bob" }, 15 ]; 16 17 return ( 18 <TableComponent<User> 19 columns={["ID", "Name"]} 20 data={data} 21 props={["id", "name"]} 22 /> 23 ); 24}
Next.js Reusable Table is designed for easy integration into Next.js apps. It supports sorting, pagination, row actions, and flexible data rendering via custom formatters. Built-in helpers handle arrays, dates, and URLs gracefully.
1<TableComponent 2 columns={["Name", "Email"]} 3 data={yourData} 4 props={["name", "email"]} 5 sortableProps={["name"]} 6/>
The table provides intelligent click handling:
1<TableComponent 2 actions 3 actionTexts={["Edit", "Delete"]} 4 actionFunctions={[(item) => editItem(item), (item) => deleteItem(item)]} 5/>
1<TableComponent 2 searchValue={searchTerm} 3 enablePagination 4 page={page} 5 setPage={setPage} 6 itemsPerPage={10} 7/>
1const customClassNames = { 2 table: "my-custom-table-styles", 3 thead: "bg-gray-200 text-gray-700", 4 tbody: "divide-y divide-gray-200", 5 pagination: { 6 container: "flex justify-center mt-4", 7 button: "px-2 py-1 border", 8 pageInfo: "mx-2", 9 }, 10}; 11 12<TableComponent 13 customClassNames={customClassNames} 14 disableDefaultStyles={false} 15/>;
1<TableComponent loading />
Pass noContentProps to customize text and icon:
1<TableComponent 2 noContentProps={{ 3 text: "No data found", 4 icon: <MyCustomIcon />, 5 }} 6/>
1"use client"; 2import React, { useState, useMemo } from "react"; 3import { TableComponent } from "nextjs-reusable-table"; 4import "nextjs-reusable-table/dist/index.css"; 5 6interface Project { 7 id: number; 8 title: string; 9 tags: string[]; 10 deadline: string; 11 active: boolean; 12 link: string; 13} 14 15export default function AdvancedProjectTable() { 16 const initialData: Project[] = [ 17 { 18 id: 1, 19 title: "Website Redesign", 20 tags: ["UI", "UX", "Frontend"], 21 deadline: "2025-03-15T10:30:00Z", 22 active: true, 23 link: "https://example.com/project/1", 24 }, 25 { 26 id: 2, 27 title: "Mobile App Development", 28 tags: ["iOS", "Android", "Backend"], 29 deadline: "2025-04-01T14:00:00Z", 30 active: false, 31 link: "https://example.com/project/2", 32 }, 33 { 34 id: 3, 35 title: "Marketing Campaign", 36 tags: ["SEO", "Social Media"], 37 deadline: "2025-02-20T09:00:00Z", 38 active: true, 39 link: "https://example.com/project/3", 40 }, 41 { 42 id: 4, 43 title: "E-commerce Platform", 44 tags: ["Frontend", "Backend", "API", "Payments", "Analytics"], 45 deadline: "2025-05-05T11:00:00Z", 46 active: true, 47 link: "https://example.com/project/4", 48 }, 49 { 50 id: 5, 51 title: "Data Analysis", 52 tags: ["Python", "ML", "Data Science"], 53 deadline: "2025-03-01T08:00:00Z", 54 active: false, 55 link: "https://example.com/project/5", 56 }, 57 ]; 58 59 const [projects, setProjects] = useState<Project[]>(initialData); 60 const [page, setPage] = useState<number>(1); 61 const [searchTerm, setSearchTerm] = useState<string>(""); 62 const [sortConfig, setSortConfig] = useState<{ 63 prop: keyof Project; 64 order: "asc" | "desc"; 65 } | null>(null); 66 67 const handleSort = (prop: keyof Project) => { 68 let order: "asc" | "desc" = "asc"; 69 if (sortConfig && sortConfig.prop === prop) { 70 order = sortConfig.order === "asc" ? "desc" : "asc"; 71 } 72 setSortConfig({ prop, order }); 73 }; 74 75 const editProject = (project: Project) => { 76 alert(`Edit project: ${project.title}`); 77 }; 78 79 const deleteProject = (project: Project) => { 80 alert(`Delete project: ${project.title}`); 81 }; 82 83 const handleRowClick = (project: Project) => { 84 console.log("Row clicked:", project); 85 }; 86 87 const formatValue = (value: string, prop: string, project: Project) => { 88 if (prop === "active") { 89 return project.active ? "Active" : "Archived"; 90 } 91 return value; 92 }; 93 94 const formatHeader = (header: string, prop: string, index: number) => ( 95 <div> 96 <span className="font-semibold uppercase tracking-wide">{header}</span> 97 </div> 98 ); 99 100 const sortedFilteredProjects = useMemo(() => { 101 const filtered = projects.filter((project) => { 102 const searchLower = searchTerm.toLowerCase(); 103 return ( 104 String(project.id).includes(searchLower) || 105 project.title.toLowerCase().includes(searchLower) || 106 project.tags.join(" ").toLowerCase().includes(searchLower) || 107 project.deadline.toLowerCase().includes(searchLower) || 108 (project.active ? "active" : "archived").includes(searchLower) || 109 project.link.toLowerCase().includes(searchLower) 110 ); 111 }); 112 if (sortConfig) { 113 filtered.sort((a, b) => { 114 const aValue = String(a[sortConfig.prop]).toLowerCase(); 115 const bValue = String(b[sortConfig.prop]).toLowerCase(); 116 if (aValue < bValue) return sortConfig.order === "asc" ? -1 : 1; 117 if (aValue > bValue) return sortConfig.order === "asc" ? 1 : -1; 118 return 0; 119 }); 120 } 121 return filtered; 122 }, [projects, searchTerm, sortConfig]); 123 124 const customClassNames = { 125 table: "border border-gray-300 rounded-md shadow-sm", 126 thead: "bg-blue-50 text-blue-700", 127 tbody: "", 128 th: "px-4 py-2", 129 tr: "", 130 td: "px-4 py-2", 131 pagination: { 132 container: "mt-4", 133 button: "bg-blue-500 text-white rounded px-3 py-1", 134 buttonDisabled: "bg-gray-300 text-gray-700 rounded px-3 py-1", 135 pageInfo: "text-blue-700", 136 }, 137 }; 138 139 return ( 140 <div className="p-4"> 141 <h1 className="text-2xl font-bold mb-4">Advanced Project Table</h1> 142 <div className="mb-4"> 143 <input 144 type="text" 145 placeholder="Search projects..." 146 value={searchTerm} 147 onChange={(e) => setSearchTerm(e.target.value)} 148 className="border border-gray-300 rounded px-2 py-1 w-full" 149 /> 150 </div> 151 <TableComponent<Project> 152 columns={["ID", "Title", "Tags", "Deadline", "Status", "Link"]} 153 data={sortedFilteredProjects} 154 props={["id", "title", "tags", "deadline", "active", "link"]} 155 sortableProps={["title", "deadline"]} 156 onSort={handleSort} 157 actionTexts={["Edit", "Delete"]} 158 actionFunctions={[editProject, deleteProject]} 159 rowOnClick={handleRowClick} 160 formatValue={formatValue} 161 formatHeader={formatHeader} 162 enablePagination 163 page={page} 164 setPage={setPage} 165 itemsPerPage={2} 166 noContentProps={{ text: "No projects found", icon: null }} 167 customClassNames={customClassNames} 168 /> 169 </div> 170 ); 171}
Prop | Type | Default | Description |
---|---|---|---|
columns | string[] | – | Column headers |
data | T[] | – | Array of data objects |
props | ReadonlyArray | – | Object keys to display |
actions | boolean | false | Enable action dropdown |
actionTexts | string[] | – | Labels for dropdown actions |
loading | boolean | false | Show loading skeleton |
actionFunctions | Array | – | Handlers for dropdown items |
searchValue | string | – | Filter rows by substring |
rowOnClick | (item: T) => void | – | Callback for row clicks |
enablePagination | boolean | false | Enable pagination |
page | number | 1 | Current page index |
setPage | (page: number) => void | – | Page setter callback |
itemsPerPage | number | 10 | Rows per page |
totalPages | number | – | Override total pages |
sortableProps | Array | [] | Columns that can be sorted |
formatValue | (val, prop, item) => React.ReactNode | – | Custom cell formatter |
enableDarkMode | boolean | true | Respect system dark mode |
disableDefaultStyles | boolean | false | Disable built-in styling |
customClassNames | object | {} | Tailwind class overrides |
noContentProps | object | {} | Custom empty state |
onSort | (prop: keyof T) => void | – | Callback triggered when a sortable column header is clicked. |
formatHeader | (header: string) => React.ReactNode | – | Custom header formatter |
Contributions are welcome! Please see CONTRIBUTING.md for details on how to get started.
We use Semantic Versioning for versioning. For the versions available, see the tags on this repository.
To bump the version, update the version
field in package.json
and follow the guidelines in the CONTRIBUTING.md file.
This project is licensed under the ISC License - see the LICENSE file for details.
This project adheres to the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code.
No vulnerabilities found.
No security vulnerabilities found.