all-purpose-table 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -104
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,27 +1,26 @@
|
|
|
1
|
-
# All Purpose Table
|
|
1
|
+
# All Purpose Table
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
A production-grade, plug-and-play React table component with TypeScript support and zero dependencies.
|
|
4
|
+
|
|
5
|
+
Demos can be found at: https://apt-demos.vercel.app/
|
|
6
6
|
|
|
7
7
|
## ✨ Features
|
|
8
8
|
|
|
9
9
|
- 🎯 **Plug and Play** - Install and use, no configuration needed
|
|
10
|
-
- 📦 **Zero Dependencies**
|
|
11
|
-
- 🟦 **TypeScript Native**
|
|
12
|
-
- 🌑 **Dark Mode** -
|
|
10
|
+
- 📦 **Zero Dependencies** — No CSS frameworks or icon libraries required
|
|
11
|
+
- 🟦 **TypeScript Native** — Full type safety and IntelliSense support
|
|
12
|
+
- 🌑 **Dark Mode** — `prefers-color-scheme` and manual class toggling (`.dark`, `html.dark`)
|
|
13
13
|
- 📊 **Feature Rich**:
|
|
14
|
-
- Sorting
|
|
15
|
-
- Pagination
|
|
14
|
+
- Sorting per column
|
|
15
|
+
- Pagination with configurable rows per page
|
|
16
16
|
- Column visibility toggle
|
|
17
|
-
- Column resizing
|
|
17
|
+
- Column resizing (drag) with optional localStorage persistence
|
|
18
18
|
- Expandable rows
|
|
19
19
|
- Custom cell renderers
|
|
20
|
+
- Full custom row rendering
|
|
20
21
|
- Row click handlers
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- Mobile responsive with auto-sizing
|
|
24
|
-
- Virtual scrolling ready
|
|
22
|
+
- Scrollable body with fixed header
|
|
23
|
+
- Mobile responsive with optional auto-sizing on header click
|
|
25
24
|
|
|
26
25
|
## 📦 Installation
|
|
27
26
|
|
|
@@ -31,41 +30,18 @@ npm install all-purpose-table
|
|
|
31
30
|
|
|
32
31
|
## ⚡ Quick Start
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
```jsx
|
|
33
|
+
```tsx
|
|
37
34
|
import { Table } from "all-purpose-table";
|
|
38
35
|
|
|
39
36
|
function App() {
|
|
40
37
|
const headers = [
|
|
41
|
-
{ accessor: "id",
|
|
42
|
-
{ accessor: "name",
|
|
43
|
-
{ accessor: "email", label: "Email", isSortable: false },
|
|
44
|
-
];
|
|
45
|
-
|
|
46
|
-
const data = [
|
|
47
|
-
{ id: 1, name: "John Doe", email: "john@example.com" },
|
|
48
|
-
{ id: 2, name: "Jane Smith", email: "jane@example.com" },
|
|
49
|
-
];
|
|
50
|
-
|
|
51
|
-
return <Table manualHeaders={headers} manualRowData={data} />;
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### TypeScript
|
|
56
|
-
|
|
57
|
-
```tsx
|
|
58
|
-
import { Table, TableHeader } from "all-purpose-table";
|
|
59
|
-
|
|
60
|
-
function App() {
|
|
61
|
-
const headers: TableHeader[] = [
|
|
62
|
-
{ accessor: "id", label: "ID", isSortable: true, width: 80 },
|
|
63
|
-
{ accessor: "name", label: "Name", isSortable: true, minWidth: 150 },
|
|
38
|
+
{ accessor: "id", label: "ID", isSortable: true },
|
|
39
|
+
{ accessor: "name", label: "Name", isSortable: true },
|
|
64
40
|
{ accessor: "email", label: "Email" },
|
|
65
41
|
];
|
|
66
42
|
|
|
67
43
|
const data = [
|
|
68
|
-
{ id: 1, name: "John Doe",
|
|
44
|
+
{ id: 1, name: "John Doe", email: "john@example.com" },
|
|
69
45
|
{ id: 2, name: "Jane Smith", email: "jane@example.com" },
|
|
70
46
|
];
|
|
71
47
|
|
|
@@ -125,12 +101,13 @@ const headers: TableHeader[] = [
|
|
|
125
101
|
accessor: "status",
|
|
126
102
|
label: "Status",
|
|
127
103
|
cellRenderer: ({ value }) => (
|
|
128
|
-
<span className={`
|
|
104
|
+
<span className={`badge badge-${value.toLowerCase()}`}>{value}</span>
|
|
129
105
|
),
|
|
130
106
|
},
|
|
131
107
|
{
|
|
132
108
|
accessor: "actions",
|
|
133
109
|
label: "Actions",
|
|
110
|
+
// Cells with accessor "actions" automatically stop row-click propagation
|
|
134
111
|
cellRenderer: ({ row }) => (
|
|
135
112
|
<button onClick={() => handleEdit(row.id)}>Edit</button>
|
|
136
113
|
),
|
|
@@ -138,34 +115,69 @@ const headers: TableHeader[] = [
|
|
|
138
115
|
];
|
|
139
116
|
```
|
|
140
117
|
|
|
141
|
-
###
|
|
118
|
+
### Expandable Rows
|
|
142
119
|
|
|
143
120
|
```tsx
|
|
121
|
+
const [expandedRowId, setExpandedRowId] = useState<string | null>(null);
|
|
122
|
+
|
|
144
123
|
<Table
|
|
145
124
|
manualHeaders={headers}
|
|
146
125
|
manualRowData={data}
|
|
147
|
-
|
|
126
|
+
expandedRowId={expandedRowId}
|
|
127
|
+
onRowClick={(row) =>
|
|
128
|
+
setExpandedRowId(expandedRowId === row.id ? null : row.id)
|
|
129
|
+
}
|
|
130
|
+
renderExpandedRow={(row) => (
|
|
131
|
+
<div style={{ padding: 16 }}>
|
|
132
|
+
<p>Details for {row.name}</p>
|
|
133
|
+
</div>
|
|
134
|
+
)}
|
|
148
135
|
/>
|
|
149
136
|
```
|
|
150
137
|
|
|
151
|
-
###
|
|
138
|
+
### Full Custom Row
|
|
139
|
+
|
|
140
|
+
Set `fullRow: true` on any data object to replace that row entirely with `renderFullRow`:
|
|
152
141
|
|
|
153
142
|
```tsx
|
|
154
|
-
const
|
|
143
|
+
const data = [
|
|
144
|
+
{ id: 1, name: "John" },
|
|
145
|
+
{ id: "divider", fullRow: true }, // uses renderFullRow
|
|
146
|
+
];
|
|
155
147
|
|
|
156
148
|
<Table
|
|
157
149
|
manualHeaders={headers}
|
|
158
150
|
manualRowData={data}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
setExpandedRowId(expandedRowId === row.id ? null : row.id)
|
|
162
|
-
}
|
|
163
|
-
renderExpandedRow={(row) => (
|
|
164
|
-
<div className="row-details">
|
|
165
|
-
<p>Additional details for {row.name}</p>
|
|
166
|
-
</div>
|
|
151
|
+
renderFullRow={(row) => (
|
|
152
|
+
<div style={{ padding: "8px 16px", fontWeight: "bold" }}>Section Header</div>
|
|
167
153
|
)}
|
|
168
|
-
|
|
154
|
+
/>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Rows Per Page Selector
|
|
158
|
+
|
|
159
|
+
The footer (including the dropdown) only renders when `onRowsPerPageChange` is provided:
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
const [rowsPerPage, setRowsPerPage] = useState(20);
|
|
163
|
+
|
|
164
|
+
<Table
|
|
165
|
+
manualHeaders={headers}
|
|
166
|
+
manualRowData={data}
|
|
167
|
+
rowsPerPage={rowsPerPage}
|
|
168
|
+
rowsPerPageOptions={[10, 20, 50, 100]}
|
|
169
|
+
onRowsPerPageChange={setRowsPerPage}
|
|
170
|
+
/>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Persistent Column Widths
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
<Table
|
|
177
|
+
manualHeaders={headers}
|
|
178
|
+
manualRowData={data}
|
|
179
|
+
columnWidthsStorageKey="my-table-columns"
|
|
180
|
+
/>
|
|
169
181
|
```
|
|
170
182
|
|
|
171
183
|
### Column Visibility Toggle
|
|
@@ -203,80 +215,65 @@ function App() {
|
|
|
203
215
|
|
|
204
216
|
## 🎨 Styling & Customization
|
|
205
217
|
|
|
206
|
-
The table comes with built-in styles
|
|
218
|
+
The table comes with built-in styles. All CSS classes are prefixed with `apt-` to avoid conflicts.
|
|
219
|
+
|
|
220
|
+
### Dark Mode
|
|
221
|
+
|
|
222
|
+
Dark mode is toggled by adding the `dark` class to any ancestor element (e.g. `<html>` or a wrapper `<div>`):
|
|
223
|
+
|
|
224
|
+
```jsx
|
|
225
|
+
// Toggle dark mode
|
|
226
|
+
document.documentElement.classList.toggle("dark");
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
No extra configuration is needed — the component responds automatically.
|
|
207
230
|
|
|
208
231
|
### CSS Variables
|
|
209
232
|
|
|
210
|
-
|
|
233
|
+
Override CSS variables to customise colours, spacing, and more:
|
|
211
234
|
|
|
212
235
|
```css
|
|
213
236
|
:root {
|
|
214
237
|
--apt-color-primary: #1f2937;
|
|
215
238
|
--apt-color-border: #d1d5db;
|
|
216
239
|
--apt-color-bg: white;
|
|
240
|
+
--apt-color-bg-secondary: #f9fafb;
|
|
217
241
|
--apt-color-accent: #9333ea;
|
|
218
242
|
/* ... and more */
|
|
219
243
|
}
|
|
220
244
|
```
|
|
221
245
|
|
|
222
|
-
###
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
.apt-tbody {
|
|
237
|
-
/* Table body */
|
|
238
|
-
}
|
|
239
|
-
.apt-row {
|
|
240
|
-
/* Table row */
|
|
241
|
-
}
|
|
242
|
-
.apt-td {
|
|
243
|
-
/* Table cell */
|
|
244
|
-
}
|
|
245
|
-
.apt-footer {
|
|
246
|
-
/* Pagination footer */
|
|
247
|
-
}
|
|
248
|
-
```
|
|
246
|
+
### CSS Class Reference
|
|
247
|
+
|
|
248
|
+
| Class | Element |
|
|
249
|
+
|---|---|
|
|
250
|
+
| `.apt-table-container` | Outermost wrapper |
|
|
251
|
+
| `.apt-scroll-area` | Scrollable region (contains both table parts) |
|
|
252
|
+
| `.apt-thead-wrapper` | Fixed header wrapper |
|
|
253
|
+
| `.apt-tbody-wrapper` | Scrollable body wrapper |
|
|
254
|
+
| `.apt-table` | `<table>` element |
|
|
255
|
+
| `.apt-thead` | `<thead>` |
|
|
256
|
+
| `.apt-tbody` | `<tbody>` |
|
|
257
|
+
| `.apt-row` | `<tr>` |
|
|
258
|
+
| `.apt-td` | `<td>` / `<th>` |
|
|
259
|
+
| `.apt-footer` | Pagination footer |
|
|
249
260
|
|
|
250
261
|
## 🔧 Framework Compatibility
|
|
251
262
|
|
|
252
|
-
Works seamlessly with:
|
|
253
|
-
|
|
254
|
-
- ✅ Create React App
|
|
255
263
|
- ✅ Next.js (App Router & Pages Router)
|
|
256
264
|
- ✅ Vite
|
|
265
|
+
- ✅ Create React App
|
|
257
266
|
- ✅ Remix
|
|
258
267
|
- ✅ Any React 17+ project
|
|
259
268
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
The table is fully responsive and includes:
|
|
263
|
-
|
|
264
|
-
- Horizontal scrolling on small screens
|
|
265
|
-
- Optional auto-sizing columns on header click
|
|
266
|
-
- Touch-friendly column resizing
|
|
267
|
-
- Configurable mobile breakpoint
|
|
268
|
-
|
|
269
|
-
## 🌙 Themes
|
|
270
|
-
|
|
271
|
-
Dark mode is supported automatically via CSS `prefers-color-scheme`. No JavaScript required!
|
|
269
|
+
> **Note:** The component uses browser APIs (`localStorage`, `ResizeObserver`, `window`) — wrap it in a client-only boundary when using SSR frameworks like Next.js App Router.
|
|
272
270
|
|
|
273
271
|
## 🏭 Production Ready
|
|
274
272
|
|
|
275
|
-
- **Tree-shakeable**
|
|
276
|
-
- **TypeScript**
|
|
277
|
-
- **
|
|
278
|
-
- **
|
|
279
|
-
- **Performant** - Optimized for large datasets
|
|
273
|
+
- **Tree-shakeable** — Only bundle what you use
|
|
274
|
+
- **TypeScript** — Full type definitions included
|
|
275
|
+
- **Zero dependencies** — No external libraries required
|
|
276
|
+
- **Performant** — `useMemo` and derived state throughout, no unnecessary re-renders
|
|
280
277
|
|
|
281
278
|
## 📄 License
|
|
282
279
|
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "all-purpose-table",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "A production-grade, plug-and-play React Table component with TypeScript support",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
|
-
"module": "dist/index.
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
@@ -43,5 +43,9 @@
|
|
|
43
43
|
"@types/react-dom": "^19.2.3",
|
|
44
44
|
"tsup": "^8.5.1",
|
|
45
45
|
"typescript": "^5.9.3"
|
|
46
|
+
},
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "https://github.com/X-Marosi/all-purpose-tablel.git"
|
|
46
50
|
}
|
|
47
51
|
}
|