jattac.libs.web.responsive-table 0.7.6 → 0.8.0
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 +31 -433
- package/dist/Data/IGroupedRowDefinition.d.ts +10 -0
- package/dist/Data/IResponsiveTableColumnDefinition.d.ts +1 -0
- package/dist/Hooks/useResponsiveTable.d.ts +14 -0
- package/dist/Hooks/useTablePlugins.d.ts +39 -0
- package/dist/Plugins/GroupingPlugin.d.ts +17 -0
- package/dist/Plugins/HighlightPlugin.d.ts +23 -0
- package/dist/UI/DesktopView.d.ts +42 -0
- package/dist/UI/InfiniteTable.d.ts +16 -42
- package/dist/UI/MobileView.d.ts +29 -0
- package/dist/UI/ResponsiveTable.d.ts +8 -45
- package/dist/UI/ResponsiveTable.test.d.ts +1 -0
- package/dist/UI/SkeletonView.d.ts +8 -0
- package/dist/index.js +708 -672
- package/dist/index.js.map +1 -1
- package/docs/api.md +65 -0
- package/docs/breaking-changes.md +28 -0
- package/docs/configuration.md +61 -0
- package/docs/custom-plugin-example.md +123 -0
- package/docs/development.md +40 -0
- package/docs/examples.md +207 -0
- package/docs/features.md +33 -0
- package/package.json +117 -71
package/README.md
CHANGED
|
@@ -1,460 +1,58 @@
|
|
|
1
|
-
# ResponsiveTable
|
|
1
|
+
# ResponsiveTable
|
|
2
|
+
## Enterprise-Grade React Data Grid Component
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
ResponsiveTable is a high-performance, type-safe React component designed for complex data visualization. It provides seamless layout transitions between desktop-optimized tabular displays and mobile-optimized card views, ensuring data integrity and accessibility across all device form factors.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* **
|
|
11
|
-
* **
|
|
12
|
-
* **Type-Safe API:** Built with TypeScript for a great developer experience.
|
|
13
|
-
* **Highly Customizable:** Control the rendering of every part of the table.
|
|
14
|
-
* **Animations:** Built-in support for loading skeletons and row animations.
|
|
15
|
-
* **Small Bundle Size:** Lightweight and optimized for performance.
|
|
16
|
-
|
|
17
|
-
## Table of Contents
|
|
18
|
-
|
|
19
|
-
- [Installation](#installation)
|
|
20
|
-
- [Getting Started](#getting-started)
|
|
21
|
-
- [Core Concepts](#core-concepts)
|
|
22
|
-
- [Column Definitions](#column-definitions)
|
|
23
|
-
- [Responsive Behavior](#responsive-behavior)
|
|
24
|
-
- [Advanced Guides](#advanced-guides)
|
|
25
|
-
- [Custom Cell Rendering](#custom-cell-rendering)
|
|
26
|
-
- [Clickable Rows and Headers](#clickable-rows-and-headers)
|
|
27
|
-
- [Dynamic and Conditional Columns](#dynamic-and-conditional-columns)
|
|
28
|
-
- [Advanced Footers](#advanced-footers)
|
|
29
|
-
- [Animations and Loading States](#animations-and-loading-states)
|
|
30
|
-
- [Plugin System](#plugin-system)
|
|
31
|
-
- [Using Plugins](#using-plugins)
|
|
32
|
-
- [Built-in Plugins](#built-in-plugins)
|
|
33
|
-
- [SortPlugin](#sortplugin)
|
|
34
|
-
- [SelectionPlugin](#selectionplugin)
|
|
35
|
-
- [FilterPlugin](#filterplugin)
|
|
36
|
-
- [InfiniteScrollPlugin](#infinitescrollplugin)
|
|
37
|
-
- [Building a Custom Plugin](#building-a-custom-plugin)
|
|
38
|
-
- [API Reference](#api-reference)
|
|
39
|
-
- [ResponsiveTable Props](#responsivetable-props)
|
|
40
|
-
- [ColumnDefinition Type](#columndefinition-type)
|
|
41
|
-
- [Footer Types](#footer-types)
|
|
42
|
-
- [Performance Best Practices](#performance-best-practices)
|
|
43
|
-
- [Troubleshooting / FAQ](#troubleshooting--faq)
|
|
44
|
-
- [Contributing](#contributing)
|
|
45
|
-
- [License](#license)
|
|
46
|
-
|
|
47
|
-
---
|
|
6
|
+
## Core Capabilities
|
|
7
|
+
* **Dynamic Layout Orchestration:** Automated transformation between standard table structures and mobile-optimized interfaces based on configurable breakpoints.
|
|
8
|
+
* **Extensible Architecture:** A robust plugin system for implementing sorting, filtering, row selection, and asynchronous data fetching.
|
|
9
|
+
* **Intelligent Layout Scaling:** Automated recalculation of footer colSpan ranges to maintain structural alignment when columns are programmatically excluded.
|
|
10
|
+
* **Performance Optimized:** An atomized internal architecture that decouples state management from rendering, minimizing re-render cycles.
|
|
11
|
+
* **Type Safety:** Comprehensive TypeScript definitions for predictable implementation and robust development workflows.
|
|
48
12
|
|
|
49
13
|
## Installation
|
|
50
14
|
|
|
51
|
-
Install the package using your favorite package manager:
|
|
52
|
-
|
|
53
15
|
```bash
|
|
54
16
|
npm install jattac.libs.web.responsive-table
|
|
55
17
|
```
|
|
56
18
|
|
|
57
|
-
|
|
19
|
+
## Basic Implementation
|
|
58
20
|
|
|
59
|
-
|
|
60
|
-
yarn add jattac.libs.web.responsive-table
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Getting Started
|
|
21
|
+
The following example demonstrates a standard implementation of the ResponsiveTable component:
|
|
64
22
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
```jsx
|
|
23
|
+
```tsx
|
|
68
24
|
import React from 'react';
|
|
69
|
-
import ResponsiveTable
|
|
70
|
-
|
|
71
|
-
// 1. Define your data structure
|
|
72
|
-
interface User {
|
|
73
|
-
id: number;
|
|
74
|
-
name: string;
|
|
75
|
-
email: string;
|
|
76
|
-
role: string;
|
|
77
|
-
}
|
|
25
|
+
import ResponsiveTable from 'jattac.libs.web.responsive-table';
|
|
78
26
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
{ id:
|
|
82
|
-
{ id: 2, name: 'Bob', email: 'bob@example.com', role: 'User' },
|
|
83
|
-
{ id: 3, name: 'Charlie', email: 'charlie@example.com', role: 'User' },
|
|
27
|
+
const data = [
|
|
28
|
+
{ id: 1, name: 'Administrative User' },
|
|
29
|
+
{ id: 2, name: 'Standard User' }
|
|
84
30
|
];
|
|
85
31
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
{
|
|
89
|
-
displayLabel: 'Name',
|
|
90
|
-
cellRenderer: (row) => row.name,
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
displayLabel: 'Email',
|
|
94
|
-
cellRenderer: (row) => row.email,
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
displayLabel: 'Role',
|
|
98
|
-
cellRenderer: (row) => row.role,
|
|
99
|
-
},
|
|
32
|
+
const columns = [
|
|
33
|
+
{ displayLabel: 'Identifier', cellRenderer: (row) => row.id },
|
|
34
|
+
{ displayLabel: 'User Name', cellRenderer: (row) => row.name },
|
|
100
35
|
];
|
|
101
36
|
|
|
102
|
-
// 4. Render the component
|
|
103
37
|
const App = () => (
|
|
104
|
-
<
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
columnDefinitions={columnDefinitions}
|
|
109
|
-
/>
|
|
110
|
-
</div>
|
|
38
|
+
<ResponsiveTable
|
|
39
|
+
data={data}
|
|
40
|
+
columnDefinitions={columns}
|
|
41
|
+
/>
|
|
111
42
|
);
|
|
112
|
-
|
|
113
|
-
export default App;
|
|
114
43
|
```
|
|
115
44
|
|
|
116
45
|
---
|
|
117
46
|
|
|
118
|
-
##
|
|
119
|
-
|
|
120
|
-
### Column Definitions
|
|
121
|
-
|
|
122
|
-
The `columnDefinitions` prop is the heart of the table. It's an array of objects where each object defines a column. The two most important properties are:
|
|
47
|
+
## Documentation Directory
|
|
123
48
|
|
|
124
|
-
|
|
125
|
-
* `cellRenderer`: A function that receives the row data and returns the content of the cell.
|
|
49
|
+
The following technical documentation provides comprehensive implementation guidance:
|
|
126
50
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
51
|
+
1. **[Technical Implementation Guide](./docs/examples.md)** - Practical examples for core features, including infinite scroll and plugin integration.
|
|
52
|
+
2. **[Functional Capabilities](./docs/features.md)** - A high-level overview of the component's feature set.
|
|
53
|
+
3. **[API Reference](./docs/api.md)** - Technical specifications for props, interfaces, and type definitions.
|
|
54
|
+
4. **[Configuration Specification](./docs/configuration.md)** - Detailed guidance on performance tuning and UI customization.
|
|
55
|
+
5. **[Architecture and Contribution Guide](./docs/development.md)** - Internal system design and development environment setup.
|
|
130
56
|
|
|
131
57
|
---
|
|
132
|
-
|
|
133
|
-
## Advanced Guides
|
|
134
|
-
|
|
135
|
-
### Custom Cell Rendering
|
|
136
|
-
|
|
137
|
-
You can render any React component in a cell using the `cellRenderer` function.
|
|
138
|
-
|
|
139
|
-
```jsx
|
|
140
|
-
const columnDefinitions: IResponsiveTableColumnDefinition<User>[] = [
|
|
141
|
-
{
|
|
142
|
-
displayLabel: 'Status',
|
|
143
|
-
cellRenderer: (row) => (
|
|
144
|
-
<span style={{
|
|
145
|
-
color: row.isActive ? 'green' : 'red',
|
|
146
|
-
fontWeight: 'bold',
|
|
147
|
-
}}>
|
|
148
|
-
{row.isActive ? 'Active' : 'Inactive'}
|
|
149
|
-
</span>
|
|
150
|
-
),
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
displayLabel: 'Actions',
|
|
154
|
-
cellRenderer: (row) => (
|
|
155
|
-
<button onClick={() => alert(`Editing ${row.name}`)}>
|
|
156
|
-
Edit
|
|
157
|
-
</button>
|
|
158
|
-
),
|
|
159
|
-
},
|
|
160
|
-
];
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
### Clickable Rows and Headers
|
|
164
|
-
|
|
165
|
-
* **Rows:** Use the `onRowClick` prop to handle row clicks.
|
|
166
|
-
* **Headers:** Use the `interactivity` property in a column definition to handle header clicks.
|
|
167
|
-
|
|
168
|
-
```jsx
|
|
169
|
-
<ResponsiveTable
|
|
170
|
-
data={users}
|
|
171
|
-
columnDefinitions={[
|
|
172
|
-
{
|
|
173
|
-
displayLabel: 'Name',
|
|
174
|
-
cellRenderer: (row) => row.name,
|
|
175
|
-
interactivity: {
|
|
176
|
-
id: 'name-header',
|
|
177
|
-
onHeaderClick: (id) => alert(`Clicked ${id}`),
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
// ...
|
|
181
|
-
]}
|
|
182
|
-
onRowClick={(row) => alert(`Clicked on ${row.name}`)}
|
|
183
|
-
/>
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### Dynamic and Conditional Columns
|
|
187
|
-
|
|
188
|
-
The `columnDefinitions` prop can be a function that returns an array of column definitions. This allows you to dynamically change the columns based on the data.
|
|
189
|
-
|
|
190
|
-
```jsx
|
|
191
|
-
const getColumnDefinitions = (user: User): IResponsiveTableColumnDefinition<User>[] => {
|
|
192
|
-
const columns: IResponsiveTableColumnDefinition<User>[] = [
|
|
193
|
-
// ... common columns
|
|
194
|
-
];
|
|
195
|
-
|
|
196
|
-
if (user.role === 'Admin') {
|
|
197
|
-
columns.push({
|
|
198
|
-
displayLabel: 'Admin Actions',
|
|
199
|
-
cellRenderer: () => <button>Delete User</button>,
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return columns;
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
<ResponsiveTable
|
|
207
|
-
data={users}
|
|
208
|
-
columnDefinitions={getColumnDefinitions}
|
|
209
|
-
/>
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
### Advanced Footers
|
|
213
|
-
|
|
214
|
-
You can add footer rows to the table using the `footerRows` prop.
|
|
215
|
-
|
|
216
|
-
```jsx
|
|
217
|
-
const footerRows: IFooterRowDefinition[] = [
|
|
218
|
-
{
|
|
219
|
-
columns: [
|
|
220
|
-
{
|
|
221
|
-
colSpan: 2,
|
|
222
|
-
cellRenderer: () => <strong>Total Users:</strong>,
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
colSpan: 1,
|
|
226
|
-
cellRenderer: () => <strong>{users.length}</strong>,
|
|
227
|
-
},
|
|
228
|
-
],
|
|
229
|
-
},
|
|
230
|
-
];
|
|
231
|
-
|
|
232
|
-
<ResponsiveTable
|
|
233
|
-
data={users}
|
|
234
|
-
columnDefinitions={columnDefinitions}
|
|
235
|
-
footerRows={footerRows}
|
|
236
|
-
/>
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### Animations and Loading States
|
|
240
|
-
|
|
241
|
-
Use the `animationProps` prop to show a loading skeleton and animate rows on load.
|
|
242
|
-
|
|
243
|
-
```jsx
|
|
244
|
-
<ResponsiveTable
|
|
245
|
-
data={users}
|
|
246
|
-
columnDefinitions={columnDefinitions}
|
|
247
|
-
animationProps={{
|
|
248
|
-
isLoading: true, // Shows a skeleton loader
|
|
249
|
-
animateOnLoad: true, // Animates rows on initial render
|
|
250
|
-
}}
|
|
251
|
-
/>
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
---
|
|
255
|
-
|
|
256
|
-
## Plugin System
|
|
257
|
-
|
|
258
|
-
### Using Plugins
|
|
259
|
-
|
|
260
|
-
To use a plugin, instantiate it and pass it to the `plugins` prop.
|
|
261
|
-
|
|
262
|
-
```jsx
|
|
263
|
-
import { SortPlugin } from 'jattac.libs.web.responsive-table';
|
|
264
|
-
|
|
265
|
-
const sortPlugin = new SortPlugin<User>();
|
|
266
|
-
|
|
267
|
-
<ResponsiveTable
|
|
268
|
-
data={users}
|
|
269
|
-
columnDefinitions={columnDefinitions}
|
|
270
|
-
plugins={[sortPlugin]}
|
|
271
|
-
/>
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### Built-in Plugins
|
|
275
|
-
|
|
276
|
-
#### SortPlugin
|
|
277
|
-
|
|
278
|
-
Enables column sorting.
|
|
279
|
-
|
|
280
|
-
**Usage:**
|
|
281
|
-
|
|
282
|
-
1. Add a `columnId` to the columns you want to be sortable.
|
|
283
|
-
2. Provide a `sortComparer` or `getSortableValue` function in the column definition.
|
|
284
|
-
3. Add the `SortPlugin` to the `plugins` prop.
|
|
285
|
-
|
|
286
|
-
```jsx
|
|
287
|
-
const sortPlugin = new SortPlugin<User>({
|
|
288
|
-
initialSortColumn: 'name',
|
|
289
|
-
initialSortDirection: 'asc',
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
const columnDefinitions: IResponsiveTableColumnDefinition<User>[] = [
|
|
293
|
-
{
|
|
294
|
-
columnId: 'name',
|
|
295
|
-
displayLabel: 'Name',
|
|
296
|
-
cellRenderer: (row) => row.name,
|
|
297
|
-
sortComparer: sortPlugin.comparers.caseInsensitiveString('name'),
|
|
298
|
-
},
|
|
299
|
-
// ...
|
|
300
|
-
];
|
|
301
|
-
|
|
302
|
-
<ResponsiveTable
|
|
303
|
-
data={users}
|
|
304
|
-
columnDefinitions={columnDefinitions}
|
|
305
|
-
plugins={[sortPlugin]}
|
|
306
|
-
/>
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
#### SelectionPlugin
|
|
310
|
-
|
|
311
|
-
Enables row selection.
|
|
312
|
-
|
|
313
|
-
**Usage:**
|
|
314
|
-
|
|
315
|
-
The `SelectionPlugin` is automatically enabled when you provide the `selectionProps`.
|
|
316
|
-
|
|
317
|
-
```jsx
|
|
318
|
-
<ResponsiveTable
|
|
319
|
-
data={users}
|
|
320
|
-
columnDefinitions={columnDefinitions}
|
|
321
|
-
selectionProps={{
|
|
322
|
-
onSelectionChange: (selectedItems) => console.log(selectedItems),
|
|
323
|
-
rowIdKey: 'id',
|
|
324
|
-
mode: 'multiple', // or 'single'
|
|
325
|
-
}}
|
|
326
|
-
/>
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
#### FilterPlugin
|
|
330
|
-
|
|
331
|
-
Adds a client-side search input to filter the table.
|
|
332
|
-
|
|
333
|
-
**Usage:**
|
|
334
|
-
|
|
335
|
-
The `FilterPlugin` is automatically enabled when you provide the `filterProps`. Add a `getFilterableValue` function to the columns you want to be filterable.
|
|
336
|
-
|
|
337
|
-
```jsx
|
|
338
|
-
const columnDefinitions: IResponsiveTableColumnDefinition<User>[] = [
|
|
339
|
-
{
|
|
340
|
-
displayLabel: 'Name',
|
|
341
|
-
cellRenderer: (row) => row.name,
|
|
342
|
-
getFilterableValue: (row) => row.name,
|
|
343
|
-
},
|
|
344
|
-
// ...
|
|
345
|
-
];
|
|
346
|
-
|
|
347
|
-
<ResponsiveTable
|
|
348
|
-
data={users}
|
|
349
|
-
columnDefinitions={columnDefinitions}
|
|
350
|
-
filterProps={{
|
|
351
|
-
showFilter: true,
|
|
352
|
-
filterPlaceholder: 'Search users...',
|
|
353
|
-
}}
|
|
354
|
-
/>
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
#### InfiniteScrollPlugin
|
|
358
|
-
|
|
359
|
-
Enables infinite scrolling.
|
|
360
|
-
|
|
361
|
-
**Usage:**
|
|
362
|
-
|
|
363
|
-
```jsx
|
|
364
|
-
import { InfiniteScrollPlugin } from 'jattac.libs.web.responsive-table';
|
|
365
|
-
|
|
366
|
-
const onLoadMore = async (currentData) => {
|
|
367
|
-
// Fetch more data...
|
|
368
|
-
return moreData;
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
<ResponsiveTable
|
|
372
|
-
data={data}
|
|
373
|
-
columnDefinitions={columnDefinitions}
|
|
374
|
-
plugins={[new InfiniteScrollPlugin()]}
|
|
375
|
-
infiniteScrollProps={{
|
|
376
|
-
onLoadMore: onLoadMore,
|
|
377
|
-
hasMore: true,
|
|
378
|
-
}}
|
|
379
|
-
maxHeight="600px" // Requires a scrollable container
|
|
380
|
-
/>
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
### Building a Custom Plugin
|
|
384
|
-
|
|
385
|
-
Implement the `IResponsiveTablePlugin` interface to create your own plugin.
|
|
386
|
-
|
|
387
|
-
```jsx
|
|
388
|
-
import { IResponsiveTablePlugin } from 'jattac.libs.web.responsive-table';
|
|
389
|
-
|
|
390
|
-
class MyCustomPlugin<TData> implements IResponsiveTablePlugin<TData> {
|
|
391
|
-
public id = 'my-custom-plugin';
|
|
392
|
-
|
|
393
|
-
public getRowProps = (row: TData) => {
|
|
394
|
-
if (row.isSpecial) {
|
|
395
|
-
return {
|
|
396
|
-
className: 'special-row',
|
|
397
|
-
style: { backgroundColor: 'lightblue' },
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
return {};
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// Usage:
|
|
405
|
-
// <ResponsiveTable plugins={[new MyCustomPlugin()]} ... />
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
---
|
|
409
|
-
|
|
410
|
-
## API Reference
|
|
411
|
-
|
|
412
|
-
### ResponsiveTable Props
|
|
413
|
-
|
|
414
|
-
| Prop | Type | Description |
|
|
415
|
-
| ---------------------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
416
|
-
| `columnDefinitions` | `ColumnDefinition<TData>[]` | **Required.** An array of objects that define the columns of the table. |
|
|
417
|
-
| `data` | `TData[]` | **Required.** The array of data to be displayed in the table. |
|
|
418
|
-
| `noDataComponent` | `ReactNode` | A custom component to display when there is no data. |
|
|
419
|
-
| `maxHeight` | `string` | Sets a maximum height for the table, making the body scrollable. E.g., `'500px'`. |
|
|
420
|
-
| `onRowClick` | `(item: TData) => void` | A callback function that is triggered when a row is clicked. |
|
|
421
|
-
| `footerRows` | `IFooterRowDefinition[]` | An array of objects that define the footer rows of the table. |
|
|
422
|
-
| `mobileBreakpoint` | `number` | The viewport width (in pixels) at which the table switches to the mobile card view. Defaults to `600`. |
|
|
423
|
-
| `plugins` | `IResponsiveTablePlugin<TData>[]` | An array of plugin instances to extend the table's functionality. |
|
|
424
|
-
| `enablePageLevelStickyHeader`| `boolean` | When `false`, disables the sticky behavior of the header at the page level. Defaults to `true`. |
|
|
425
|
-
| `animationProps` | `{ isLoading?: boolean; animateOnLoad?: boolean; }` | Props to control animations. `isLoading` shows a skeleton loader. `animateOnLoad` animates rows on initial render. |
|
|
426
|
-
| `filterProps` | `{ showFilter?: boolean; filterPlaceholder?: string; className?: string; }` | Props to configure the built-in filter functionality. `showFilter` enables the filter input. |
|
|
427
|
-
| `selectionProps` | `{ onSelectionChange: (selectedItems: TData[]) => void; rowIdKey: keyof TData; mode?: 'single' \| 'multiple'; selectedItems?: TData[]; selectedRowClassName?: string; }` | Props to enable and configure row selection. |
|
|
428
|
-
| `infiniteScrollProps` | `{ onLoadMore: (currentData: TData[]) => Promise<TData[] \| null>; hasMore?: boolean; loadingMoreComponent?: ReactNode; noMoreDataComponent?: ReactNode; }` | Props to enable infinite scrolling. |
|
|
429
|
-
|
|
430
|
-
### ColumnDefinition Type
|
|
431
|
-
|
|
432
|
-
`IResponsiveTableColumnDefinition<TData>` is a union type. See the source file for detailed information.
|
|
433
|
-
|
|
434
|
-
### Footer Types
|
|
435
|
-
|
|
436
|
-
`IFooterRowDefinition` and `IFooterColumnDefinition` are used to define the footer. See the source files for detailed information.
|
|
437
|
-
|
|
438
|
-
---
|
|
439
|
-
|
|
440
|
-
## Performance Best Practices
|
|
441
|
-
|
|
442
|
-
* **Memoize `data` and `columnDefinitions`:** To prevent unnecessary re-renders, wrap `data` and `columnDefinitions` in `React.useMemo`.
|
|
443
|
-
* **Lightweight `cellRenderer`:** Keep your `cellRenderer` functions as simple as possible.
|
|
444
|
-
* **Server-side Operations:** For large datasets, perform sorting, filtering, and pagination on the server.
|
|
445
|
-
|
|
446
|
-
---
|
|
447
|
-
|
|
448
|
-
## Troubleshooting / FAQ
|
|
449
|
-
|
|
450
|
-
This section will be populated with common issues and their solutions as they arise.
|
|
451
|
-
|
|
452
|
-
---
|
|
453
|
-
|
|
454
|
-
## Contributing
|
|
455
|
-
|
|
456
|
-
Contributions are welcome! Please follow the guidelines in the `CONTRIBUTING.md` file.
|
|
457
|
-
|
|
458
|
-
## License
|
|
459
|
-
|
|
460
|
-
This project is licensed under the MIT License.
|
|
58
|
+
**Next Step:** [Review the Technical Implementation Guide](./docs/examples.md)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface IGroupedRowDefinition<TData> {
|
|
3
|
+
id: string | number;
|
|
4
|
+
groupKey: string | number;
|
|
5
|
+
items: TData[];
|
|
6
|
+
groupHeaderRenderer: (groupKey: string | number, items: TData[], isExpanded: boolean) => ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
isExpanded?: boolean;
|
|
9
|
+
isGroupHeader?: boolean;
|
|
10
|
+
}
|
|
@@ -3,6 +3,7 @@ export type SortDirection = 'asc' | 'desc';
|
|
|
3
3
|
interface IResponsiveTableColumnDefinitionBase<TData> {
|
|
4
4
|
displayLabel: ReactNode;
|
|
5
5
|
cellRenderer: (data: TData) => ReactNode;
|
|
6
|
+
visible?: boolean;
|
|
6
7
|
dataKey?: keyof TData;
|
|
7
8
|
getFilterableValue?: (data: TData) => string | number;
|
|
8
9
|
interactivity?: {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface UseResponsiveTableProps {
|
|
2
|
+
mobileBreakpoint?: number;
|
|
3
|
+
enablePageLevelStickyHeader?: boolean;
|
|
4
|
+
maxHeight?: string;
|
|
5
|
+
headerRef?: React.RefObject<HTMLElement>;
|
|
6
|
+
scrollableRef?: React.RefObject<HTMLElement>;
|
|
7
|
+
}
|
|
8
|
+
interface UseResponsiveTableReturn {
|
|
9
|
+
isMobile: boolean;
|
|
10
|
+
isHeaderSticky: boolean;
|
|
11
|
+
debouncedScrollHandler: (currentTarget: HTMLElement) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare const useResponsiveTable: (props: UseResponsiveTableProps) => UseResponsiveTableReturn;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { IResponsiveTablePlugin } from '../Plugins/IResponsiveTablePlugin';
|
|
3
|
+
import { IResponsiveTableColumnDefinition, SortDirection } from '../Data/IResponsiveTableColumnDefinition';
|
|
4
|
+
interface IInfiniteScrollProps<TData> {
|
|
5
|
+
onLoadMore: (currentData: TData[]) => Promise<TData[] | null>;
|
|
6
|
+
hasMore?: boolean;
|
|
7
|
+
loadingMoreComponent?: ReactNode;
|
|
8
|
+
noMoreDataComponent?: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
interface UseTablePluginsProps<TData> {
|
|
11
|
+
data: TData[];
|
|
12
|
+
plugins?: IResponsiveTablePlugin<TData>[];
|
|
13
|
+
filterProps?: {
|
|
14
|
+
showFilter?: boolean;
|
|
15
|
+
filterPlaceholder?: string;
|
|
16
|
+
className?: string;
|
|
17
|
+
};
|
|
18
|
+
selectionProps?: {
|
|
19
|
+
onSelectionChange: (selectedItems: TData[]) => void;
|
|
20
|
+
rowIdKey: keyof TData;
|
|
21
|
+
mode?: 'single' | 'multiple';
|
|
22
|
+
selectedItems?: TData[];
|
|
23
|
+
};
|
|
24
|
+
sortProps?: {
|
|
25
|
+
initialSortColumn?: string;
|
|
26
|
+
initialSortDirection?: SortDirection;
|
|
27
|
+
};
|
|
28
|
+
columnDefinitions: (IResponsiveTableColumnDefinition<TData> | ((data: TData, rowIndex?: number) => IResponsiveTableColumnDefinition<TData>))[];
|
|
29
|
+
getScrollableElement: () => HTMLElement | null;
|
|
30
|
+
infiniteScrollProps?: IInfiniteScrollProps<TData>;
|
|
31
|
+
}
|
|
32
|
+
interface UseTablePluginsReturn<TData> {
|
|
33
|
+
processedData: TData[];
|
|
34
|
+
activePlugins: IResponsiveTablePlugin<TData>[];
|
|
35
|
+
visibleColumns: (IResponsiveTableColumnDefinition<TData> | ((data: TData, rowIndex?: number) => IResponsiveTableColumnDefinition<TData>))[];
|
|
36
|
+
forceUpdatePlugins: () => void;
|
|
37
|
+
}
|
|
38
|
+
export declare const useTablePlugins: <TData>(props: UseTablePluginsProps<TData>) => UseTablePluginsReturn<TData>;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { IResponsiveTablePlugin, IPluginAPI } from './IResponsiveTablePlugin';
|
|
3
|
+
import { IGroupedRowDefinition } from '../Data/IGroupedRowDefinition';
|
|
4
|
+
import { IGroupingProps } from '../UI/ResponsiveTable';
|
|
5
|
+
export declare class GroupingPlugin<TData extends object> implements IResponsiveTablePlugin<TData> {
|
|
6
|
+
id: string;
|
|
7
|
+
private api;
|
|
8
|
+
private groupingProps;
|
|
9
|
+
private expandedGroups;
|
|
10
|
+
constructor(groupingProps: IGroupingProps<TData>);
|
|
11
|
+
onPluginInit: (api: IPluginAPI<TData>) => void;
|
|
12
|
+
private getGroupKey;
|
|
13
|
+
private toggleGroup;
|
|
14
|
+
processData: (data: TData[]) => (TData | IGroupedRowDefinition<TData>)[];
|
|
15
|
+
getRowProps: (row: TData | IGroupedRowDefinition<TData>) => React.HTMLAttributes<HTMLElement>;
|
|
16
|
+
renderCell: (content: ReactNode, row: TData | IGroupedRowDefinition<TData>, _column: any) => ReactNode;
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IResponsiveTablePlugin, IPluginAPI } from './IResponsiveTablePlugin';
|
|
3
|
+
import { IGroupedRowDefinition } from '../Data/IGroupedRowDefinition';
|
|
4
|
+
export interface IHighlightProps<TData extends object> {
|
|
5
|
+
condition: (row: TData | IGroupedRowDefinition<TData>) => boolean;
|
|
6
|
+
highlightClassName?: string;
|
|
7
|
+
intervalMs?: number;
|
|
8
|
+
numFlashes?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare class HighlightPlugin<TOriginalData extends object> implements IResponsiveTablePlugin<TOriginalData> {
|
|
11
|
+
id: string;
|
|
12
|
+
private api;
|
|
13
|
+
private highlightProps;
|
|
14
|
+
private activeFlashes;
|
|
15
|
+
private initialMatchedRowIds;
|
|
16
|
+
constructor(props: IHighlightProps<TOriginalData>);
|
|
17
|
+
onPluginInit: (api: IPluginAPI<TOriginalData>) => void;
|
|
18
|
+
getRowProps: (row: TOriginalData | IGroupedRowDefinition<TOriginalData>) => React.HTMLAttributes<HTMLTableRowElement>;
|
|
19
|
+
private startFlashing;
|
|
20
|
+
private stopFlashing;
|
|
21
|
+
private flashRow;
|
|
22
|
+
processData: (data: (TOriginalData | IGroupedRowDefinition<TOriginalData>)[]) => (TOriginalData | IGroupedRowDefinition<TOriginalData>)[];
|
|
23
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IResponsiveTableColumnDefinition } from '../Data/IResponsiveTableColumnDefinition';
|
|
3
|
+
import IFooterColumnDefinition from '../Data/IFooterColumnDefinition';
|
|
4
|
+
import { ColumnDefinition } from './ResponsiveTable';
|
|
5
|
+
interface DesktopViewProps<TData> {
|
|
6
|
+
columnDefinitions: ColumnDefinition<TData>[];
|
|
7
|
+
originalColumnDefinitions: ColumnDefinition<TData>[];
|
|
8
|
+
currentData: TData[];
|
|
9
|
+
maxHeight?: string;
|
|
10
|
+
isHeaderSticky: boolean;
|
|
11
|
+
tableContainerRef: React.RefObject<HTMLDivElement>;
|
|
12
|
+
headerRef: React.RefObject<HTMLTableSectionElement>;
|
|
13
|
+
getRowProps: (row: TData) => React.HTMLAttributes<HTMLElement>;
|
|
14
|
+
getHeaderProps: (colDef: ColumnDefinition<TData>) => React.HTMLAttributes<HTMLElement> & {
|
|
15
|
+
className?: string;
|
|
16
|
+
};
|
|
17
|
+
onHeaderClickCallback: (colDef: ColumnDefinition<TData>) => ((id: string) => void) | undefined;
|
|
18
|
+
getClickableHeaderClassName: (onHeaderClick: ((id: string) => void) | undefined, colDef: ColumnDefinition<TData>) => string;
|
|
19
|
+
getRawColumnDefinition: (colDef: ColumnDefinition<TData>) => IResponsiveTableColumnDefinition<TData>;
|
|
20
|
+
getColumnDefinition: (colDef: ColumnDefinition<TData>, rowIndex: number) => IResponsiveTableColumnDefinition<TData>;
|
|
21
|
+
renderCell: (content: React.ReactNode, row: TData, colDef: IResponsiveTableColumnDefinition<TData>) => React.ReactNode;
|
|
22
|
+
rowClickFunction: (item: TData) => void;
|
|
23
|
+
footerRows?: {
|
|
24
|
+
columns: IFooterColumnDefinition[];
|
|
25
|
+
}[];
|
|
26
|
+
renderPluginFooters: () => React.ReactNode;
|
|
27
|
+
onScroll?: (e: React.UIEvent<HTMLDivElement>) => void;
|
|
28
|
+
animationProps?: {
|
|
29
|
+
isLoading?: boolean;
|
|
30
|
+
animateOnLoad?: boolean;
|
|
31
|
+
};
|
|
32
|
+
selectionProps?: {
|
|
33
|
+
onSelectionChange: (selectedItems: TData[]) => void;
|
|
34
|
+
rowIdKey: keyof TData;
|
|
35
|
+
mode?: 'single' | 'multiple';
|
|
36
|
+
selectedItems?: TData[];
|
|
37
|
+
selectedRowClassName?: string;
|
|
38
|
+
};
|
|
39
|
+
onRowClick?: (item: TData) => void;
|
|
40
|
+
}
|
|
41
|
+
declare function DesktopView<TData>(props: DesktopViewProps<TData>): React.JSX.Element;
|
|
42
|
+
export default DesktopView;
|