jattac.libs.web.responsive-table 0.2.3 → 0.2.5

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 CHANGED
@@ -11,7 +11,7 @@ ResponsiveTable is a powerful, lightweight, and fully responsive React component
11
11
  - **Interactive Elements**: Easily add click handlers for rows, headers, and footer cells.
12
12
  - **Performant**: Built with performance in mind, including debounced resize handling.
13
13
  - **Easy to Use**: A simple and intuitive API for quick integration.
14
- - **Extensible Plugin System**: Easily add new functionalities like filtering, infinite scrolling, or custom behaviors.
14
+ - **Extensible Plugin System**: Easily add new functionalities like filtering, sorting, or infinite scrolling.
15
15
 
16
16
  ## Installation
17
17
 
@@ -82,7 +82,9 @@ const AnimatedTable = () => {
82
82
  }, 2000);
83
83
  }, []);
84
84
 
85
- return <ResponsiveTable columnDefinitions={columns} data={data} animationProps={{ isLoading, animateOnLoad: true }} />;
85
+ return (
86
+ <ResponsiveTable columnDefinitions={columns} data={data} animationProps={{ isLoading, animateOnLoad: true }} />
87
+ );
86
88
  };
87
89
  ```
88
90
 
@@ -123,7 +125,7 @@ import ResponsiveTable from 'jattac.libs.web.responsive-table';
123
125
 
124
126
  const CustomCells = () => {
125
127
  const columns = [
126
- { displayLabel: 'User', cellRenderer: (row) => <strong>{row.user}</strong> },
128
+ { displayLabel: <strong>User</strong>, cellRenderer: (row) => <strong>{row.user}</strong> },
127
129
  {
128
130
  displayLabel: 'Status',
129
131
  cellRenderer: (row) => (
@@ -258,9 +260,7 @@ const NonStickyHeaderTable = () => {
258
260
 
259
261
  return (
260
262
  <div>
261
- <h1 style={{ height: '50vh', display: 'flex', alignItems: 'center' }}>
262
- Scroll down to see the table
263
- </h1>
263
+ <h1 style={{ height: '50vh', display: 'flex', alignItems: 'center' }}>Scroll down to see the table</h1>
264
264
  <ResponsiveTable
265
265
  columnDefinitions={columns}
266
266
  data={data}
@@ -284,13 +284,18 @@ Plugins are passed to the `ResponsiveTable` component via the `plugins` prop, wh
284
284
 
285
285
  ```jsx
286
286
  import React from 'react';
287
- import ResponsiveTable from 'jattac.libs.web.responsive-table';
288
- import { FilterPlugin } from 'jattac.libs.web.responsive-table/dist/Plugins/FilterPlugin'; // Adjust path as needed
287
+ // Note: All plugins are exported from the main package entry point.
288
+ import ResponsiveTable, { FilterPlugin } from 'jattac.libs.web.responsive-table';
289
289
 
290
290
  const MyTableWithPlugins = () => {
291
291
  const columns = [
292
292
  { displayLabel: 'Name', dataKey: 'name', cellRenderer: (row) => row.name, getFilterableValue: (row) => row.name },
293
- { displayLabel: 'Age', dataKey: 'age', cellRenderer: (row) => row.age, getFilterableValue: (row) => row.age.toString() },
293
+ {
294
+ displayLabel: 'Age',
295
+ dataKey: 'age',
296
+ cellRenderer: (row) => row.age,
297
+ getFilterableValue: (row) => row.age.toString(),
298
+ },
294
299
  ];
295
300
 
296
301
  const data = [
@@ -304,7 +309,7 @@ const MyTableWithPlugins = () => {
304
309
  columnDefinitions={columns}
305
310
  data={data}
306
311
  // Enable built-in filter plugin via props
307
- filterProps={{ showFilter: true, filterPlaceholder: "Search by name or age..." }}
312
+ filterProps={{ showFilter: true, filterPlaceholder: 'Search by name or age...' }}
308
313
  // Or provide a custom instance of the plugin
309
314
  // plugins={[new FilterPlugin()]}
310
315
  />
@@ -314,21 +319,160 @@ const MyTableWithPlugins = () => {
314
319
 
315
320
  ### Built-in Plugins
316
321
 
322
+ #### `SortPlugin`
323
+
324
+ The `SortPlugin` provides powerful, type-safe, and highly customizable column sorting. It adds intuitive UI cues, allowing users to click column headers to sort the data in ascending, descending, or original order.
325
+
326
+ **Enabling the `SortPlugin`:**
327
+
328
+ To use the plugin, you must first import it and provide a generic instance of it to the `plugins` prop. The real power comes from making the plugin instance generic with your data type, which provides type-safety and IDE autocompletion for the sort comparer helpers.
329
+
330
+ ```jsx
331
+ import React from 'react';
332
+ import ResponsiveTable, { IResponsiveTableColumnDefinition, SortPlugin } from 'jattac.libs.web.responsive-table';
333
+
334
+ // Define the shape of your data
335
+ interface User {
336
+ id: number;
337
+ name: string;
338
+ signupDate: string;
339
+ logins: number;
340
+ }
341
+
342
+ // 1. Create a single, generic instance of the plugin.
343
+ // This is the ONLY setup step required.
344
+ const sortPlugin = new SortPlugin<User>({
345
+ initialSortColumn: 'logins',
346
+ initialSortDirection: 'desc',
347
+ });
348
+
349
+ // 2. Define the columns, using the helpers directly from the plugin instance.
350
+ const columnDefinitions: IResponsiveTableColumnDefinition<User>[] = [
351
+ // ... see examples below
352
+ ];
353
+
354
+ const UserTable = ({ users }) => (
355
+ <ResponsiveTable
356
+ columnDefinitions={columnDefinitions}
357
+ data={users}
358
+ // 3. Pass the already-configured plugin to the table.
359
+ plugins={[sortPlugin]}
360
+ />
361
+ );
362
+ ```
363
+
364
+ **How to Make Columns Sortable (Opt-In):**
365
+
366
+ A column is made sortable by adding either a `sortComparer` or a `getSortableValue` property to its definition.
367
+
368
+ - `sortComparer`: A function that defines the exact comparison logic. This is the most powerful option and should be used for complex data types or custom logic.
369
+ - `getSortableValue`: A simpler function that just returns the primitive value (string, number, etc.) to be used in a default comparison.
370
+
371
+ **Example 1: Using Type-Safe Comparer Helpers**
372
+
373
+ The `SortPlugin` instance provides a `comparers` object with pre-built, type-safe helper functions to eliminate boilerplate for common sorting scenarios. This is the recommended approach.
374
+
375
+ ```jsx
376
+ const columnDefinitions: IResponsiveTableColumnDefinition<User>[] = [
377
+ {
378
+ displayLabel: 'Name',
379
+ dataKey: 'name',
380
+ cellRenderer: (user) => user.name,
381
+ // The plugin instance itself provides the type-safe helpers.
382
+ // The string 'name' is fully type-checked against the User interface.
383
+ sortComparer: sortPlugin.comparers.caseInsensitiveString('name'),
384
+ },
385
+ {
386
+ displayLabel: 'Signup Date',
387
+ dataKey: 'signupDate',
388
+ cellRenderer: (user) => new Date(user.signupDate).toLocaleDateString(),
389
+ // IDE autocompletion for 'signupDate' works perfectly.
390
+ sortComparer: sortPlugin.comparers.date('signupDate'),
391
+ },
392
+ {
393
+ displayLabel: 'Logins',
394
+ dataKey: 'logins',
395
+ cellRenderer: (user) => user.logins,
396
+ sortComparer: sortPlugin.comparers.numeric('logins'),
397
+ },
398
+ {
399
+ displayLabel: 'Actions',
400
+ // This column is NOT sortable because it has no sort-related properties.
401
+ cellRenderer: (user) => <button>View</button>,
402
+ },
403
+ ];
404
+ ```
405
+
406
+ **Example 2: Writing a Custom `sortComparer`**
407
+
408
+ For unique requirements, you can write your own comparison function from scratch.
409
+
410
+ ```jsx
411
+ const columnDefinitions: IResponsiveTableColumnDefinition<User>[] = [
412
+ {
413
+ displayLabel: 'Name',
414
+ dataKey: 'name',
415
+ cellRenderer: (user) => user.name,
416
+ // Writing custom logic for a case-sensitive sort
417
+ sortComparer: (a, b, direction) => {
418
+ const nameA = a.name; // No .toLowerCase()
419
+ const nameB = b.name;
420
+ if (nameA < nameB) return direction === 'asc' ? -1 : 1;
421
+ if (nameA > nameB) return direction === 'asc' ? 1 : -1;
422
+ return 0;
423
+ },
424
+ },
425
+ ];
426
+ ```
427
+
428
+ **Example 3: Using `getSortableValue` for Simple Cases**
429
+
430
+ If you don't need special logic, `getSortableValue` is a concise way to enable default sorting on a property.
431
+
432
+ ```jsx
433
+ const columnDefinitions: IResponsiveTableColumnDefinition<User>[] = [
434
+ {
435
+ displayLabel: 'Logins',
436
+ dataKey: 'logins',
437
+ cellRenderer: (user) => user.logins,
438
+ // This enables a simple, default numerical sort on the 'logins' property.
439
+ getSortableValue: (user) => user.logins,
440
+ },
441
+ ];
442
+ ```
443
+
444
+ **Plugin Options (via `new SortPlugin(options)`):**
445
+
446
+ | Prop | Type (`keyof TData`) | Description |
447
+ | ---------------------- | -------------------- | ------------------------------------------------- |
448
+ | `initialSortColumn` | `string` | The `dataKey` of the column to sort by initially. |
449
+ | `initialSortDirection` | `'asc' \| 'desc'` | The direction for the initial sort. |
450
+
451
+ **`SortPlugin.comparers` API:**
452
+
453
+ The `comparers` object on your `SortPlugin` instance provides the following helper methods. Each method is a factory that takes a `dataKey` (which is type-checked against your data model) and returns a `sortComparer` function.
454
+
455
+ | Method | Description |
456
+ | -------------------------------- | ----------------------------------------------------------------------------- |
457
+ | `numeric(dataKey)` | Performs a standard numerical sort. |
458
+ | `caseInsensitiveString(dataKey)` | Performs a case-insensitive alphabetical sort. |
459
+ | `date(dataKey)` | Correctly sorts dates, assuming the data is a valid date string or timestamp. |
460
+
317
461
  #### `FilterPlugin`
318
462
 
319
463
  Provides a search input to filter table data. It can be enabled by setting `filterProps.showFilter` to `true` on the `ResponsiveTable` component. For columns to be filterable, you must provide a `getFilterableValue` function in their `IResponsiveTableColumnDefinition`.
320
464
 
321
465
  **Props for `FilterPlugin` (via `filterProps` on `ResponsiveTable`):**
322
466
 
323
- | Prop | Type | Description |
324
- | ----------------- | -------- | --------------------------------------------------------------------------- |
325
- | `showFilter` | `boolean`| If `true`, displays a filter input field above the table. |
326
- | `filterPlaceholder`| `string` | Placeholder text for the filter input. Defaults to "Search...". |
467
+ | Prop | Type | Description |
468
+ | ------------------- | --------- | --------------------------------------------------------------- |
469
+ | `showFilter` | `boolean` | If `true`, displays a filter input field above the table. |
470
+ | `filterPlaceholder` | `string` | Placeholder text for the filter input. Defaults to "Search...". |
327
471
 
328
472
  **Example with `FilterPlugin`:**
329
473
 
330
474
  ```jsx
331
- import React, { useState } from 'react';
475
+ import React from 'react';
332
476
  import ResponsiveTable from 'jattac.libs.web.responsive-table';
333
477
 
334
478
  const FilterableTable = () => {
@@ -349,7 +493,7 @@ const FilterableTable = () => {
349
493
  <ResponsiveTable
350
494
  columnDefinitions={columns}
351
495
  data={initialData}
352
- filterProps={{ showFilter: true, filterPlaceholder: "Filter users..." }}
496
+ filterProps={{ showFilter: true, filterPlaceholder: 'Filter users...' }}
353
497
  />
354
498
  );
355
499
  };
@@ -361,13 +505,13 @@ Enables infinite scrolling for the table, loading more data as the user scrolls
361
505
 
362
506
  **Props for `InfiniteScrollPlugin` (via `infiniteScrollProps` on `ResponsiveTable`):**
363
507
 
364
- | Prop | Type | Description |
365
- | --------------------- | ------------------------------------ | --------------------------------------------------------------------------- |
366
- | `enableInfiniteScroll`| `boolean` | If `true`, enables infinite scrolling. |
367
- | `onLoadMore` | `(currentData: TData[]) => Promise<TData[] | null>` | Callback function to load more data. Should return a Promise resolving to new data or `null`. |
368
- | `hasMore` | `boolean` | Indicates if there is more data to load. |
369
- | `loadingMoreComponent`| `ReactNode` | Custom component to display while loading more data. Defaults to "Loading more...". |
370
- | `noMoreDataComponent` | `ReactNode` | Custom component to display when no more data is available. Defaults to "No more data.". |
508
+ | Prop | Type | Description |
509
+ | ---------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
510
+ | `enableInfiniteScroll` | `boolean` | If `true`, enables infinite scrolling. |
511
+ | `onLoadMore` | `(currentData: TData[]) => Promise<TData[] | null>` | Callback function to load more data. Should return a Promise resolving to new data or `null`. |
512
+ | `hasMore` | `boolean` | Indicates if there is more data to load. |
513
+ | `loadingMoreComponent` | `ReactNode` | Custom component to display while loading more data. Defaults to "Loading more...". |
514
+ | `noMoreDataComponent` | `ReactNode` | Custom component to display when no more data is available. Defaults to "No more data.". |
371
515
 
372
516
  **Example with `InfiniteScrollPlugin`:**
373
517
 
@@ -394,7 +538,7 @@ const InfiniteScrollTable = () => {
394
538
  };
395
539
 
396
540
  useEffect(() => {
397
- fetchData(0).then(initialData => {
541
+ fetchData(0).then((initialData) => {
398
542
  setData(initialData);
399
543
  setPage(1);
400
544
  });
@@ -419,7 +563,9 @@ const InfiniteScrollTable = () => {
419
563
  ];
420
564
 
421
565
  return (
422
- <div style={{ height: '300px' }}> {/* Container for scrollable table */}
566
+ <div style={{ height: '300px' }}>
567
+ {' '}
568
+ {/* Container for scrollable table */}
423
569
  <ResponsiveTable
424
570
  columnDefinitions={columns}
425
571
  data={data}
@@ -437,173 +583,38 @@ const InfiniteScrollTable = () => {
437
583
  };
438
584
  ```
439
585
 
440
- ### Extending Functionality with Custom Plugins
441
-
442
- Developers can create their own custom plugins to add unique features to the `ResponsiveTable`. This is achieved by implementing the `IResponsiveTablePlugin` interface.
443
-
444
- **`IResponsiveTablePlugin<TData>` Interface:**
445
-
446
- | Property | Type | Description |
447
- | -------------- | ------------------------------------ | --------------------------------------------------------------------------- |
448
- | `id` | `string` | A unique identifier for the plugin. |
449
- | `renderHeader?`| `() => ReactNode` | Optional. A function that returns a React component to be rendered above the table. |
450
- | `renderFooter?`| `() => ReactNode` | Optional. A function that returns a React component to be rendered below the table. |
451
- | `processData?` | `(data: TData[]) => TData[]` | Optional. A function that processes the table data before it is rendered. Useful for sorting, filtering, or transforming data. |
452
- | `onPluginInit?`| `(api: IPluginAPI<TData>) => void` | Optional. A callback function that provides the plugin with an API to interact with the `ResponsiveTable` component. |
453
-
454
- **`IPluginAPI<TData>` Interface:**
455
-
456
- This interface provides methods and properties for plugins to interact with the `ResponsiveTable` component.
457
-
458
- | Property | Type | Description |
459
- | -------------------- | ------------------------------------ | --------------------------------------------------------------------------- |
460
- | `getData` | `() => TData[]` | Returns the current raw data array being used by the table. |
461
- | `forceUpdate` | `() => void` | Forces the `ResponsiveTable` component to re-render. Useful after a plugin modifies internal state that affects rendering. |
462
- | `columnDefinitions` | `ColumnDefinition<TData>[]` | Provides access to the table's column definitions. |
463
- | `getScrollableElement?`| `() => HTMLElement | null` | Optional. Returns the HTML element that is scrollable, if `maxHeight` is set. Useful for implementing scroll-based features. |
464
- | `infiniteScrollProps?`| `object` | Optional. Provides access to the `infiniteScrollProps` passed to the `ResponsiveTable`. |
465
- | `filterProps?` | `object` | Optional. Provides access to the `filterProps` passed to the `ResponsiveTable`. |
466
-
467
- **Example: Custom Sorting Plugin**
468
-
469
- This example demonstrates a simple sorting plugin that allows sorting by a specified column.
470
-
471
- ```typescript
472
- // src/Plugins/SortPlugin.ts
473
- import React from 'react';
474
- import { IResponsiveTablePlugin, IPluginAPI } from './IResponsiveTablePlugin';
475
- import IResponsiveTableColumnDefinition from '../Data/IResponsiveTableColumnDefinition';
476
-
477
- export class SortPlugin<TData> implements IResponsiveTablePlugin<TData> {
478
- public id = 'sort';
479
- private api!: IPluginAPI<TData>;
480
- private sortColumn: string | null = null;
481
- private sortDirection: 'asc' | 'desc' = 'asc';
482
-
483
- public onPluginInit = (api: IPluginAPI<TData>) => {
484
- this.api = api;
485
- };
486
-
487
- public renderHeader = () => {
488
- return (
489
- <div style={{ marginBottom: '1rem' }}>
490
- Sort by:
491
- <select onChange={this.handleColumnChange} style={{ marginLeft: '0.5rem' }}>
492
- <option value="">None</option>
493
- {this.api.columnDefinitions.map((colDef) => {
494
- const rawColDef = colDef as IResponsiveTableColumnDefinition<TData>;
495
- if (rawColDef.dataKey) {
496
- return <option key={rawColDef.dataKey} value={rawColDef.dataKey}>{rawColDef.displayLabel}</option>;
497
- }
498
- return null;
499
- })}
500
- </select>
501
- {this.sortColumn && (
502
- <button onClick={this.toggleSortDirection} style={{ marginLeft: '0.5rem' }}>
503
- {this.sortDirection === 'asc' ? 'Ascending' : 'Descending'}
504
- </button>
505
- )}
506
- </div>
507
- );
508
- };
509
-
510
- public processData = (data: TData[]): TData[] => {
511
- if (!this.sortColumn) {
512
- return data;
513
- }
514
-
515
- const sortedData = [...data].sort((a, b) => {
516
- const aValue = a[this.sortColumn as keyof TData];
517
- const bValue = b[this.sortColumn as keyof TData];
518
-
519
- if (aValue < bValue) return this.sortDirection === 'asc' ? -1 : 1;
520
- if (aValue > bValue) return this.sortDirection === 'asc' ? 1 : -1;
521
- return 0;
522
- });
523
-
524
- return sortedData;
525
- };
526
-
527
- private handleColumnChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
528
- this.sortColumn = e.target.value || null;
529
- this.api.forceUpdate();
530
- };
531
-
532
- private toggleSortDirection = () => {
533
- this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
534
- this.api.forceUpdate();
535
- };
536
- }
537
-
538
- // Usage in your component:
539
- ```jsx
540
- import React from 'react';
541
- import ResponsiveTable from 'jattac.libs.web.responsive-table';
542
- import { SortPlugin } from './SortPlugin'; // Assuming SortPlugin.ts is in the same directory
543
-
544
- const SortableTable = () => {
545
- const data = [
546
- { id: 1, name: 'Alice', age: 30 },
547
- { id: 2, name: 'Bob', age: 25 },
548
- { id: 3, name: 'Charlie', age: 35 },
549
- ];
550
-
551
- const columns = [
552
- { displayLabel: 'ID', dataKey: 'id', cellRenderer: (row) => row.id },
553
- { displayLabel: 'Name', dataKey: 'name', cellRenderer: (row) => row.name },
554
- { displayLabel: 'Age', dataKey: 'age', cellRenderer: (row) => row.age },
555
- ];
556
-
557
- return (
558
- <ResponsiveTable
559
- columnDefinitions={columns}
560
- data={data}
561
- plugins={[new SortPlugin()]}
562
- />
563
- );
564
- };
565
- ```
566
-
567
- **Other Plugin Ideas (beyond Filtering and Infinite Scroll):**
568
-
569
- - **Column Resizing Plugin:** Allows users to drag column headers to resize columns.
570
- - **Row Selection Plugin:** Adds checkboxes to rows for multi-row selection.
571
- - **Export Data Plugin:** Provides buttons to export table data to CSV, Excel, or PDF.
572
- - **Drag-and-Drop Reordering Plugin:** Enables reordering of rows or columns via drag and drop.
573
- - **Column Visibility Toggle Plugin:** Allows users to show/hide specific columns.
574
-
575
- ---
576
-
577
586
  ---
578
587
 
579
588
  ## API Reference
580
589
 
581
590
  ### `ResponsiveTable` Props
582
591
 
583
- | Prop | Type | Required | Description |
584
- | ----------------------------- | ------------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------- |
585
- | `columnDefinitions` | `IResponsiveTableColumnDefinition[]` | Yes | An array of objects defining the table columns. |
586
- | `data` | `TData[]` | Yes | An array of data objects to populate the table rows. |
587
- | `footerRows` | `IFooterRowDefinition[]` | No | An array of objects defining the table footer. |
588
- | `onRowClick` | `(item: TData) => void` | No | A callback function that is triggered when a row is clicked. |
589
- | `noDataComponent` | `ReactNode` | No | A custom component to display when there is no data. |
590
- | `maxHeight` | `string` | No | Sets a maximum height for the table body, making it scrollable. |
591
- | `mobileBreakpoint` | `number` | No | The pixel width at which the table switches to the mobile view. Defaults to `600`. |
592
- | `enablePageLevelStickyHeader` | `boolean` | No | If `false`, disables the header from sticking to the top of the page on scroll. Defaults to `true`. |
593
- | `plugins` | `IResponsiveTablePlugin<TData>[]` | No | An array of plugin instances to extend table functionality. |
594
- | `infiniteScrollProps` | `object` | No | Configuration for the built-in infinite scroll plugin. |
595
- | `filterProps` | `object` | No | Configuration for the built-in filter plugin. |
596
- | `animationProps` | `object` | No | Configuration for animations, including `isLoading` and `animateOnLoad`. |
597
-
598
- ### `IResponsiveTableColumnDefinition`
599
-
600
- | Property | Type | Required | Description |
601
- | --------------- | --------------------------- | -------- | ------------------------------------------------------------------------------ |
602
- | `displayLabel` | `string` | Yes | The label displayed in the table header. |
603
- | `cellRenderer` | `(row: TData) => ReactNode` | Yes | A function that returns the content to be rendered in the cell. |
604
- | `dataKey` | `string` | No | A key to match the column to a property in the data object (optional). |
605
- | `interactivity` | `object` | No | An object to define header interactivity (`onHeaderClick`, `id`, `className`). |
606
- | `getFilterableValue`| `(row: TData) => string` | No | A function that returns the string value to be used for filtering this column. Required for `FilterPlugin`. |
592
+ | Prop | Type | Required | Description |
593
+ | ----------------------------- | ------------------------------------ | -------- | --------------------------------------------------------------------------------------------------- |
594
+ | `columnDefinitions` | `IResponsiveTableColumnDefinition[]` | Yes | An array of objects defining the table columns. |
595
+ | `data` | `TData[]` | Yes | An array of data objects to populate the table rows. |
596
+ | `footerRows` | `IFooterRowDefinition[]` | No | An array of objects defining the table footer. |
597
+ | `onRowClick` | `(item: TData) => void` | No | A callback function that is triggered when a row is clicked. |
598
+ | `noDataComponent` | `ReactNode` | No | A custom component to display when there is no data. |
599
+ | `maxHeight` | `string` | No | Sets a maximum height for the table body, making it scrollable. |
600
+ | `mobileBreakpoint` | `number` | No | The pixel width at which the table switches to the mobile view. Defaults to `600`. |
601
+ | `enablePageLevelStickyHeader` | `boolean` | No | If `false`, disables the header from sticking to the top of the page on scroll. Defaults to `true`. |
602
+ | `plugins` | `IResponsiveTablePlugin<TData>[]` | No | An array of plugin instances to extend table functionality. |
603
+ | `infiniteScrollProps` | `object` | No | Configuration for the built-in infinite scroll plugin. |
604
+ | `filterProps` | `object` | No | Configuration for the built-in filter plugin. |
605
+ | `animationProps` | `object` | No | Configuration for animations, including `isLoading` and `animateOnLoad`. |
606
+
607
+ ### `IResponsiveTableColumnDefinition<TData>`
608
+
609
+ | Property | Type | Required | Description |
610
+ | -------------------- | ------------------------------------------------------------ | -------- | ---------------------------------------------------------------------------------------- |
611
+ | `displayLabel` | `ReactNode` | Yes | The label displayed in the table header (can be a string or any React component). |
612
+ | `cellRenderer` | `(row: TData) => ReactNode` | Yes | A function that returns the content to be rendered in the cell. |
613
+ | `dataKey` | `string` | No | A key to match the column to a property in the data object (required for sorting). |
614
+ | `interactivity` | `object` | No | An object to define header interactivity (`onHeaderClick`, `id`, `className`). |
615
+ | `getFilterableValue` | `(row: TData) => string \| number` | No | A function that returns the string or number value to be used for filtering this column. |
616
+ | `getSortableValue` | `(row: TData) => any` | No | A function that returns a primitive value from a row to be used for default sorting. |
617
+ | `sortComparer` | `(a: TData, b: TData, direction: 'asc' \| 'desc') => number` | No | A function that provides the precise comparison logic for sorting a column. |
607
618
 
608
619
  ### `IFooterRowDefinition`
609
620
 
@@ -613,13 +624,13 @@ const SortableTable = () => {
613
624
 
614
625
  ### `IFooterColumnDefinition`
615
626
 
616
- | Property | Type | Required | Description |
617
- | -------------- | ----------------- | -------- | ------------------------------------------------------------------------------ |
618
- | `colSpan` | `number` | Yes | The number of columns the footer cell should span. |
619
- | `cellRenderer` | `() => ReactNode` | Yes | A function that returns the content for the footer cell. |
627
+ | Property | Type | Required | Description |
628
+ | -------------- | ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
629
+ | `colSpan` | `number` | Yes | The number of columns the footer cell should span. |
630
+ | `cellRenderer` | `() => ReactNode` | Yes | A function that returns the content for the footer cell. |
620
631
  | `displayLabel` | `ReactNode` | No | An optional, explicit label for the footer cell. In mobile view, if `colSpan` is 1 and this is not provided, the corresponding column header will be used as a fallback. This is required for `colSpan` > 1 if you want a label to be displayed. |
621
- | `onCellClick` | `() => void` | No | An optional click handler for the footer cell. |
622
- | `className` | `string` | No | Optional class name for custom styling of the footer cell. |
632
+ | `onCellClick` | `() => void` | No | An optional click handler for the footer cell. |
633
+ | `className` | `string` | No | Optional class name for custom styling of the footer cell. |
623
634
 
624
635
  ## License
625
636
 
@@ -1,11 +1,15 @@
1
1
  import { ReactNode } from 'react';
2
+ export type SortDirection = 'asc' | 'desc';
2
3
  export default interface IResponsiveTableColumnDefinition<TData> {
3
4
  displayLabel: ReactNode;
4
5
  cellRenderer: (data: TData) => ReactNode;
6
+ dataKey?: string;
5
7
  interactivity?: {
6
8
  id: string;
7
9
  onHeaderClick?: (id: string) => void;
8
10
  className?: string;
9
11
  };
10
12
  getFilterableValue?: (data: TData) => string | number;
13
+ getSortableValue?: (row: TData) => any;
14
+ sortComparer?: (a: TData, b: TData, direction: SortDirection) => number;
11
15
  }
@@ -0,0 +1,29 @@
1
+ import { IResponsiveTablePlugin, IPluginAPI } from './IResponsiveTablePlugin';
2
+ import IResponsiveTableColumnDefinition, { SortDirection } from '../Data/IResponsiveTableColumnDefinition';
3
+ export interface ISortPluginOptions<TData> {
4
+ initialSortColumn?: keyof TData;
5
+ initialSortDirection?: SortDirection;
6
+ }
7
+ export declare class SortPlugin<TData> implements IResponsiveTablePlugin<TData> {
8
+ id: string;
9
+ private api;
10
+ private sortColumn;
11
+ private sortDirection;
12
+ readonly comparers: {
13
+ numeric: (key: keyof TData) => (a: TData, b: TData, direction: SortDirection) => number;
14
+ caseInsensitiveString: (key: keyof TData) => (a: TData, b: TData, direction: SortDirection) => 0 | 1 | -1;
15
+ date: (key: keyof TData) => (a: TData, b: TData, direction: SortDirection) => number;
16
+ };
17
+ constructor(options?: ISortPluginOptions<TData>);
18
+ onPluginInit: (api: IPluginAPI<TData>) => void;
19
+ processData: (data: TData[]) => TData[];
20
+ getHeaderProps: (columnDef: IResponsiveTableColumnDefinition<TData>) => {
21
+ onClick?: undefined;
22
+ className?: undefined;
23
+ 'aria-sort'?: undefined;
24
+ } | {
25
+ onClick: () => void;
26
+ className: string;
27
+ 'aria-sort': string;
28
+ };
29
+ }
@@ -57,6 +57,7 @@ declare class ResponsiveTable<TData> extends Component<IProps<TData>, IState<TDa
57
57
  private getRawColumnDefinition;
58
58
  private onHeaderClickCallback;
59
59
  private getClickableHeaderClassName;
60
+ private getHeaderProps;
60
61
  private get rowClickFunction();
61
62
  private get rowClickStyle();
62
63
  private get tableFooter();
package/dist/index.d.ts CHANGED
@@ -5,5 +5,6 @@ import ResponsiveTable, { ColumnDefinition } from './UI/ResponsiveTable';
5
5
  import { FilterPlugin } from './Plugins/FilterPlugin';
6
6
  import { InfiniteScrollPlugin } from './Plugins/InfiniteScrollPlugin';
7
7
  import { IResponsiveTablePlugin } from './Plugins/IResponsiveTablePlugin';
8
- export { IResponsiveTableColumnDefinition, ColumnDefinition, IFooterColumnDefinition, IFooterRowDefinition, FilterPlugin, InfiniteScrollPlugin, IResponsiveTablePlugin };
8
+ import { SortPlugin } from './Plugins/SortPlugin';
9
+ export { IResponsiveTableColumnDefinition, ColumnDefinition, IFooterColumnDefinition, IFooterRowDefinition, FilterPlugin, InfiniteScrollPlugin, IResponsiveTablePlugin, SortPlugin };
9
10
  export default ResponsiveTable;