jattac.libs.web.responsive-table 0.2.15 → 0.2.17
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 +17 -40
- package/dist/UI/InfiniteTable.d.ts +27 -24
- package/dist/UI/ResponsiveTable.d.ts +15 -7
- package/dist/index.js +152 -1091
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ ResponsiveTable is a powerful, lightweight, and fully responsive React component
|
|
|
9
9
|
- **Dynamic Data Handling**: Define columns and footers based on your data or application state.
|
|
10
10
|
- **Delightful Animations**: Includes an optional skeleton loader and staggered row entrance animations.
|
|
11
11
|
- **Interactive Elements**: Easily add click handlers for rows, headers, and footer cells.
|
|
12
|
-
- **
|
|
12
|
+
- **Efficient & Responsive**: Built with efficiency in mind, including debounced resize handling for smooth transitions.
|
|
13
13
|
- **Easy to Use**: A simple and intuitive API for quick integration.
|
|
14
14
|
- **Extensible Plugin System**: Easily add new functionalities like filtering, sorting, or infinite scrolling.
|
|
15
15
|
|
|
@@ -230,15 +230,9 @@ const TableWithFooter = () => {
|
|
|
230
230
|
};
|
|
231
231
|
```
|
|
232
232
|
|
|
233
|
-
### Example 6: Disabling
|
|
233
|
+
### Example 6: Disabling Page-Level Sticky Header
|
|
234
234
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
Normally, as you slide the paper up to see items at the bottom, the titles disappear off the top.
|
|
238
|
-
|
|
239
|
-
This table has a special power: by default, the header "sticks" to the top of your view so you never forget which column is which.
|
|
240
|
-
|
|
241
|
-
But what if you don't want it to stick? The `enablePageLevelStickyHeader={false}` prop is like a magic switch. Flipping it to `false` tells the header to scroll away normally with the rest of the page.
|
|
235
|
+
By default, the table header remains fixed to the top of the viewport as the user scrolls down the page. This ensures the column titles are always visible. To disable this behavior and have the header scroll away with the rest of the page, set the `enablePageLevelStickyHeader` prop to `false`.
|
|
242
236
|
|
|
243
237
|
```jsx
|
|
244
238
|
import React from 'react';
|
|
@@ -501,9 +495,11 @@ const FilterableTable = () => {
|
|
|
501
495
|
|
|
502
496
|
#### `InfiniteScrollPlugin`
|
|
503
497
|
|
|
504
|
-
Enables
|
|
498
|
+
Enables a simple infinite scroll for loading more data as the user scrolls to the bottom of the table. This is useful for progressively loading data from an API without needing traditional pagination buttons.
|
|
499
|
+
|
|
500
|
+
> **Important:** To enable infinite scroll, you **must** give the table a bounded height. This is done by passing the `maxHeight` prop to the `<ResponsiveTable>`. This prop creates a scrollable container for the table body, which is required for the scroll detection to work.
|
|
505
501
|
|
|
506
|
-
> **
|
|
502
|
+
> **Performance Note:** This implementation renders all loaded rows into the DOM to guarantee correct column alignment and simplicity. It is **not a virtualized list**. For extremely large datasets (many thousands of rows), performance may degrade as more rows are loaded. It is best suited for scenarios where loading a few hundred up to a couple thousand rows is expected.
|
|
507
503
|
|
|
508
504
|
**Configuration (via `infiniteScrollProps` on `ResponsiveTable`):**
|
|
509
505
|
|
|
@@ -517,10 +513,10 @@ Enables high-performance virtualization for displaying large datasets. When enab
|
|
|
517
513
|
|
|
518
514
|
**Comprehensive Example:**
|
|
519
515
|
|
|
520
|
-
Here is a complete example
|
|
516
|
+
Here is a complete example showing how to use the infinite scroll feature. The parent component only needs to provide a function that fetches the next page of data.
|
|
521
517
|
|
|
522
518
|
```jsx
|
|
523
|
-
import React, { useState,
|
|
519
|
+
import React, { useState, useCallback } from 'react';
|
|
524
520
|
import ResponsiveTable from 'jattac.libs.web.responsive-table';
|
|
525
521
|
|
|
526
522
|
// Define the shape of our data items
|
|
@@ -551,35 +547,18 @@ const fetchData = async (page: number): Promise<DataItem[]> => {
|
|
|
551
547
|
};
|
|
552
548
|
|
|
553
549
|
const InfiniteScrollExample = () => {
|
|
554
|
-
//
|
|
555
|
-
const [data, setData] = useState<DataItem[]>([]);
|
|
556
|
-
// State to track if there is more data to be loaded
|
|
557
|
-
const [hasMore, setHasMore] = useState(true);
|
|
558
|
-
// State to track the current page number for the API call
|
|
550
|
+
// Keep track of the next page to fetch.
|
|
559
551
|
const [nextPage, setNextPage] = useState(0);
|
|
560
552
|
|
|
561
|
-
// The function
|
|
562
|
-
// It
|
|
553
|
+
// The onLoadMore function is now much simpler.
|
|
554
|
+
// It just needs to fetch the data and return it.
|
|
555
|
+
// The table will handle appending the data and managing the `hasMore` state internally.
|
|
563
556
|
const loadMoreItems = useCallback(async () => {
|
|
564
|
-
// Fetch the next page of data
|
|
565
557
|
const newItems = await fetchData(nextPage);
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
// If the API returns no more items, update hasMore to false
|
|
569
|
-
setHasMore(false);
|
|
570
|
-
} else {
|
|
571
|
-
// Add the new items to the existing data
|
|
572
|
-
setData((prevData) => [...prevData, ...newItems]);
|
|
573
|
-
// Increment the page number for the next fetch
|
|
574
|
-
setNextPage((prevPage) => prevPage + 1);
|
|
575
|
-
}
|
|
558
|
+
setNextPage((prevPage) => prevPage + 1);
|
|
559
|
+
return newItems; // <-- Simply return the new items
|
|
576
560
|
}, [nextPage]);
|
|
577
561
|
|
|
578
|
-
// Load the initial data when the component mounts
|
|
579
|
-
useEffect(() => {
|
|
580
|
-
loadMoreItems();
|
|
581
|
-
}, []); // The empty dependency array ensures this runs only once on mount
|
|
582
|
-
|
|
583
562
|
const columns = [
|
|
584
563
|
{ displayLabel: 'ID', dataKey: 'id', cellRenderer: (row) => row.id },
|
|
585
564
|
{ displayLabel: 'Value', dataKey: 'value', cellRenderer: (row) => row.value },
|
|
@@ -590,14 +569,12 @@ const InfiniteScrollExample = () => {
|
|
|
590
569
|
<div style={{ height: '400px' }}>
|
|
591
570
|
<ResponsiveTable
|
|
592
571
|
columnDefinitions={columns}
|
|
593
|
-
data={data
|
|
594
|
-
// The maxHeight prop makes the table body scrollable within the container.
|
|
572
|
+
data={[]} // Start with an empty array of initial data
|
|
595
573
|
maxHeight="100%"
|
|
596
|
-
// Pass the infinite scroll configuration
|
|
597
574
|
infiniteScrollProps={{
|
|
598
575
|
enableInfiniteScroll: true,
|
|
599
576
|
onLoadMore: loadMoreItems,
|
|
600
|
-
|
|
577
|
+
// Note: `hasMore` is not needed! The component infers it.
|
|
601
578
|
loadingMoreComponent: <h4>Loading more items...</h4>,
|
|
602
579
|
noMoreDataComponent: <p>You've reached the end!</p>,
|
|
603
580
|
}}
|
|
@@ -3,6 +3,20 @@ import { IResponsiveTableColumnDefinition } from '../Data/IResponsiveTableColumn
|
|
|
3
3
|
import IFooterRowDefinition from '../Data/IFooterRowDefinition';
|
|
4
4
|
import { IResponsiveTablePlugin } from '../Plugins/IResponsiveTablePlugin';
|
|
5
5
|
export type ColumnDefinition<TData> = IResponsiveTableColumnDefinition<TData> | ((data: TData, rowIndex?: number) => IResponsiveTableColumnDefinition<TData>);
|
|
6
|
+
type InfiniteScrollDisabled = {
|
|
7
|
+
enableInfiniteScroll?: false;
|
|
8
|
+
onLoadMore?: never;
|
|
9
|
+
hasMore?: never;
|
|
10
|
+
loadingMoreComponent?: never;
|
|
11
|
+
noMoreDataComponent?: never;
|
|
12
|
+
};
|
|
13
|
+
type InfiniteScrollEnabled<TData> = {
|
|
14
|
+
enableInfiniteScroll: true;
|
|
15
|
+
onLoadMore: (currentData: TData[]) => Promise<TData[] | null>;
|
|
16
|
+
hasMore?: boolean;
|
|
17
|
+
loadingMoreComponent?: ReactNode;
|
|
18
|
+
noMoreDataComponent?: ReactNode;
|
|
19
|
+
};
|
|
6
20
|
interface IProps<TData> {
|
|
7
21
|
columnDefinitions: ColumnDefinition<TData>[];
|
|
8
22
|
data: TData[];
|
|
@@ -13,13 +27,7 @@ interface IProps<TData> {
|
|
|
13
27
|
mobileBreakpoint?: number;
|
|
14
28
|
plugins?: IResponsiveTablePlugin<TData>[];
|
|
15
29
|
enablePageLevelStickyHeader?: boolean;
|
|
16
|
-
infiniteScrollProps?:
|
|
17
|
-
enableInfiniteScroll?: boolean;
|
|
18
|
-
onLoadMore?: (currentData: TData[]) => Promise<TData[] | null>;
|
|
19
|
-
hasMore?: boolean;
|
|
20
|
-
loadingMoreComponent?: ReactNode;
|
|
21
|
-
noMoreDataComponent?: ReactNode;
|
|
22
|
-
};
|
|
30
|
+
infiniteScrollProps?: InfiniteScrollDisabled | InfiniteScrollEnabled<TData>;
|
|
23
31
|
filterProps?: {
|
|
24
32
|
showFilter?: boolean;
|
|
25
33
|
filterPlaceholder?: string;
|
|
@@ -31,31 +39,31 @@ interface IProps<TData> {
|
|
|
31
39
|
}
|
|
32
40
|
interface IState<TData> {
|
|
33
41
|
isMobile: boolean;
|
|
42
|
+
internalData: TData[];
|
|
34
43
|
processedData: TData[];
|
|
35
44
|
isLoadingMore: boolean;
|
|
45
|
+
internalHasMore: boolean;
|
|
36
46
|
isHeaderSticky: boolean;
|
|
37
|
-
|
|
47
|
+
activePlugins: IResponsiveTablePlugin<TData>[];
|
|
38
48
|
}
|
|
39
49
|
declare class InfiniteTable<TData> extends Component<IProps<TData>, IState<TData>> {
|
|
40
50
|
private debouncedResize;
|
|
41
51
|
private tableContainerRef;
|
|
42
52
|
private headerRef;
|
|
43
|
-
private
|
|
53
|
+
private throttledScrollHandler;
|
|
44
54
|
constructor(props: IProps<TData>);
|
|
45
|
-
private get mobileBreakpoint();
|
|
46
|
-
private debounce;
|
|
47
|
-
private get data();
|
|
48
|
-
private get noDataSvg();
|
|
49
|
-
private get hasData();
|
|
50
|
-
private get noDataComponent();
|
|
51
55
|
componentDidMount(): void;
|
|
52
56
|
componentWillUnmount(): void;
|
|
53
|
-
|
|
54
|
-
private
|
|
57
|
+
private debounce;
|
|
58
|
+
private throttle;
|
|
59
|
+
handleResize: () => void;
|
|
55
60
|
private handleScroll;
|
|
61
|
+
private loadMoreData;
|
|
56
62
|
private initializePlugins;
|
|
57
63
|
private processData;
|
|
58
|
-
|
|
64
|
+
private get data();
|
|
65
|
+
private get hasData();
|
|
66
|
+
private get noDataComponent();
|
|
59
67
|
private getColumnDefinition;
|
|
60
68
|
private getRawColumnDefinition;
|
|
61
69
|
private onHeaderClickCallback;
|
|
@@ -63,13 +71,8 @@ declare class InfiniteTable<TData> extends Component<IProps<TData>, IState<TData
|
|
|
63
71
|
private getHeaderProps;
|
|
64
72
|
private get rowClickFunction();
|
|
65
73
|
private get rowClickStyle();
|
|
66
|
-
private get tableFooter();
|
|
67
|
-
private get mobileFooter();
|
|
68
|
-
private get skeletonView();
|
|
69
74
|
private get mobileView();
|
|
70
75
|
private get largeScreenView();
|
|
71
|
-
|
|
72
|
-
private renderPluginFooters;
|
|
73
|
-
render(): string | number | boolean | Iterable<React.ReactNode> | React.JSX.Element | null | undefined;
|
|
76
|
+
render(): React.JSX.Element;
|
|
74
77
|
}
|
|
75
78
|
export default InfiniteTable;
|
|
@@ -3,6 +3,20 @@ import { IResponsiveTableColumnDefinition } from '../Data/IResponsiveTableColumn
|
|
|
3
3
|
import IFooterRowDefinition from '../Data/IFooterRowDefinition';
|
|
4
4
|
import { IResponsiveTablePlugin } from '../Plugins/IResponsiveTablePlugin';
|
|
5
5
|
export type ColumnDefinition<TData> = IResponsiveTableColumnDefinition<TData> | ((data: TData, rowIndex?: number) => IResponsiveTableColumnDefinition<TData>);
|
|
6
|
+
type InfiniteScrollDisabled = {
|
|
7
|
+
enableInfiniteScroll?: false;
|
|
8
|
+
onLoadMore?: never;
|
|
9
|
+
hasMore?: never;
|
|
10
|
+
loadingMoreComponent?: never;
|
|
11
|
+
noMoreDataComponent?: never;
|
|
12
|
+
};
|
|
13
|
+
type InfiniteScrollEnabled<TData> = {
|
|
14
|
+
enableInfiniteScroll: true;
|
|
15
|
+
onLoadMore: (currentData: TData[]) => Promise<TData[] | null>;
|
|
16
|
+
hasMore?: boolean;
|
|
17
|
+
loadingMoreComponent?: ReactNode;
|
|
18
|
+
noMoreDataComponent?: ReactNode;
|
|
19
|
+
};
|
|
6
20
|
interface IProps<TData> {
|
|
7
21
|
columnDefinitions: ColumnDefinition<TData>[];
|
|
8
22
|
data: TData[];
|
|
@@ -13,13 +27,7 @@ interface IProps<TData> {
|
|
|
13
27
|
mobileBreakpoint?: number;
|
|
14
28
|
plugins?: IResponsiveTablePlugin<TData>[];
|
|
15
29
|
enablePageLevelStickyHeader?: boolean;
|
|
16
|
-
infiniteScrollProps?:
|
|
17
|
-
enableInfiniteScroll?: boolean;
|
|
18
|
-
onLoadMore?: (currentData: TData[]) => Promise<TData[] | null>;
|
|
19
|
-
hasMore?: boolean;
|
|
20
|
-
loadingMoreComponent?: ReactNode;
|
|
21
|
-
noMoreDataComponent?: ReactNode;
|
|
22
|
-
};
|
|
30
|
+
infiniteScrollProps?: InfiniteScrollDisabled | InfiniteScrollEnabled<TData>;
|
|
23
31
|
filterProps?: {
|
|
24
32
|
showFilter?: boolean;
|
|
25
33
|
filterPlaceholder?: string;
|