jattac.libs.web.responsive-table 0.9.1 → 0.10.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/dist/Context/TableContext.d.ts +1 -0
- package/dist/Hooks/useTableDataSource.d.ts +10 -0
- package/dist/Hooks/useTablePlugins.d.ts +2 -0
- package/dist/Plugins/IResponsiveTablePlugin.d.ts +2 -0
- package/dist/UI/ResponsiveTable.d.ts +17 -5
- package/dist/index.d.ts +4 -3
- package/dist/index.es.js +97 -14
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +96 -12
- package/dist/index.js.map +1 -1
- package/docs/api.md +63 -4
- package/docs/examples.md +148 -1
- package/docs/features.md +7 -1
- package/package.json +1 -1
|
@@ -9,6 +9,15 @@ interface UseTableDataSourceProps<TData> {
|
|
|
9
9
|
};
|
|
10
10
|
filter?: string;
|
|
11
11
|
}
|
|
12
|
+
export interface DataSourceState<TData> {
|
|
13
|
+
data: TData[];
|
|
14
|
+
currentPage: number;
|
|
15
|
+
hasMore: boolean;
|
|
16
|
+
totalCount?: number;
|
|
17
|
+
isLoading: boolean;
|
|
18
|
+
isFetchingMore: boolean;
|
|
19
|
+
error?: Error;
|
|
20
|
+
}
|
|
12
21
|
interface UseTableDataSourceReturn<TData> {
|
|
13
22
|
data: TData[];
|
|
14
23
|
currentPage: number;
|
|
@@ -18,6 +27,7 @@ interface UseTableDataSourceReturn<TData> {
|
|
|
18
27
|
isFetchingMore: boolean;
|
|
19
28
|
loadNextPage: () => Promise<void>;
|
|
20
29
|
resetAndFetch: () => Promise<void>;
|
|
30
|
+
error?: Error;
|
|
21
31
|
}
|
|
22
32
|
export declare const useTableDataSource: <TData>(props: UseTableDataSourceProps<TData>) => UseTableDataSourceReturn<TData>;
|
|
23
33
|
export {};
|
|
@@ -14,6 +14,7 @@ interface UseTablePluginsProps<TData> {
|
|
|
14
14
|
showFilter?: boolean;
|
|
15
15
|
filterPlaceholder?: string;
|
|
16
16
|
className?: string;
|
|
17
|
+
mode?: 'client' | 'server';
|
|
17
18
|
};
|
|
18
19
|
selectionProps?: {
|
|
19
20
|
onSelectionChange: (selectedItems: TData[]) => void;
|
|
@@ -28,6 +29,7 @@ interface UseTablePluginsProps<TData> {
|
|
|
28
29
|
columnDefinitions: (IResponsiveTableColumnDefinition<TData> | ((data: TData, rowIndex?: number) => IResponsiveTableColumnDefinition<TData>))[];
|
|
29
30
|
getScrollableElement: () => HTMLElement | null;
|
|
30
31
|
infiniteScrollProps?: IInfiniteScrollProps<TData>;
|
|
32
|
+
onFilterChange?: (filterText: string) => void;
|
|
31
33
|
}
|
|
32
34
|
interface UseTablePluginsReturn<TData> {
|
|
33
35
|
processedData: TData[];
|
|
@@ -28,6 +28,7 @@ export interface IPluginAPI<TData> {
|
|
|
28
28
|
showFilter?: boolean;
|
|
29
29
|
filterPlaceholder?: string;
|
|
30
30
|
className?: string;
|
|
31
|
+
mode?: 'client' | 'server';
|
|
31
32
|
};
|
|
32
33
|
selectionProps?: {
|
|
33
34
|
onSelectionChange: (selectedItems: TData[]) => void;
|
|
@@ -36,4 +37,5 @@ export interface IPluginAPI<TData> {
|
|
|
36
37
|
selectedItems?: TData[];
|
|
37
38
|
selectedRowClassName?: string;
|
|
38
39
|
};
|
|
40
|
+
onFilterChange?: (filterText: string) => void;
|
|
39
41
|
}
|
|
@@ -3,7 +3,13 @@ import { SortDirection } from '../Data/IResponsiveTableColumnDefinition';
|
|
|
3
3
|
import IFooterRowDefinition from '../Data/IFooterRowDefinition';
|
|
4
4
|
import { IResponsiveTablePlugin } from '../Plugins/IResponsiveTablePlugin';
|
|
5
5
|
import { ColumnDefinition, DataSource } from '../Context/TableContext';
|
|
6
|
+
import { DataSourceState } from '../Hooks/useTableDataSource';
|
|
6
7
|
export { ColumnDefinition };
|
|
8
|
+
export interface ResponsiveTableHandle<TData> {
|
|
9
|
+
loadNextPage: () => Promise<void>;
|
|
10
|
+
resetAndFetch: () => Promise<void>;
|
|
11
|
+
getState: () => DataSourceState<TData>;
|
|
12
|
+
}
|
|
7
13
|
interface IInfiniteScrollProps<TData> {
|
|
8
14
|
onLoadMore: (currentData: TData[]) => Promise<TData[] | null>;
|
|
9
15
|
hasMore?: boolean;
|
|
@@ -66,6 +72,8 @@ interface IProps<TData> {
|
|
|
66
72
|
showFilter?: boolean;
|
|
67
73
|
filterPlaceholder?: string;
|
|
68
74
|
className?: string;
|
|
75
|
+
/** When 'server', filter changes trigger a dataSource re-fetch with the filter param instead of client-side filtering. Default: 'client'. */
|
|
76
|
+
mode?: 'client' | 'server';
|
|
69
77
|
};
|
|
70
78
|
/** Configuration for row selection. */
|
|
71
79
|
selectionProps?: {
|
|
@@ -84,10 +92,14 @@ interface IProps<TData> {
|
|
|
84
92
|
sortProps?: ISortProps;
|
|
85
93
|
/** Custom CSS class to apply to each card in mobile view. */
|
|
86
94
|
mobileCardClassName?: string;
|
|
95
|
+
/** Callback fired whenever the dataSource state changes (data, page, loading, error). */
|
|
96
|
+
onDataSourceStateChange?: (state: DataSourceState<TData>) => void;
|
|
97
|
+
/** Callback fired when the current page changes. */
|
|
98
|
+
onPageChange?: (page: number) => void;
|
|
99
|
+
/** Callback fired when a dataSource fetch fails. */
|
|
100
|
+
onDataSourceError?: (error: Error) => void;
|
|
87
101
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
*/
|
|
92
|
-
declare function ResponsiveTable<TData>(props: IProps<TData>): React.JSX.Element;
|
|
102
|
+
declare const ResponsiveTable: <TData>(props: IProps<TData> & {
|
|
103
|
+
ref?: React.Ref<ResponsiveTableHandle<TData>>;
|
|
104
|
+
}) => React.ReactElement;
|
|
93
105
|
export default ResponsiveTable;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import IFooterColumnDefinition from './Data/IFooterColumnDefinition';
|
|
2
2
|
import IFooterRowDefinition from './Data/IFooterRowDefinition';
|
|
3
3
|
import { IResponsiveTableColumnDefinition, SortDirection } from './Data/IResponsiveTableColumnDefinition';
|
|
4
|
-
import ResponsiveTable from './UI/ResponsiveTable';
|
|
5
|
-
import { ColumnDefinition, DataSource, IDataSourceParams, DataSourceResult } from './Context/TableContext';
|
|
4
|
+
import ResponsiveTable, { ResponsiveTableHandle } from './UI/ResponsiveTable';
|
|
5
|
+
import { ColumnDefinition, DataSource, IDataSourceParams, DataSourceResult, useTableContext } from './Context/TableContext';
|
|
6
|
+
import { DataSourceState } from './Hooks/useTableDataSource';
|
|
6
7
|
import { FilterPlugin } from './Plugins/FilterPlugin';
|
|
7
8
|
import { InfiniteScrollPlugin } from './Plugins/InfiniteScrollPlugin';
|
|
8
9
|
import { IResponsiveTablePlugin } from './Plugins/IResponsiveTablePlugin';
|
|
9
10
|
import { SortPlugin } from './Plugins/SortPlugin';
|
|
10
11
|
import { SelectionPlugin } from './Plugins/SelectionPlugin';
|
|
11
|
-
export { SortDirection, IResponsiveTableColumnDefinition, ColumnDefinition, DataSource, IDataSourceParams, DataSourceResult, IFooterColumnDefinition, IFooterRowDefinition, FilterPlugin, InfiniteScrollPlugin, IResponsiveTablePlugin, SortPlugin, SelectionPlugin, };
|
|
12
|
+
export { SortDirection, IResponsiveTableColumnDefinition, ColumnDefinition, DataSource, IDataSourceParams, DataSourceResult, IFooterColumnDefinition, IFooterRowDefinition, FilterPlugin, InfiniteScrollPlugin, IResponsiveTablePlugin, SortPlugin, SelectionPlugin, ResponsiveTableHandle, DataSourceState, useTableContext, };
|
|
12
13
|
export default ResponsiveTable;
|
package/dist/index.es.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useCallback, useMemo, useContext, useRef, useEffect, useState } from 'react';
|
|
1
|
+
import React, { createContext, useCallback, useMemo, useContext, useRef, useEffect, useState, forwardRef, useImperativeHandle } from 'react';
|
|
2
2
|
|
|
3
3
|
function styleInject(css, ref) {
|
|
4
4
|
if ( ref === void 0 ) ref = {};
|
|
@@ -27,7 +27,7 @@ function styleInject(css, ref) {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
var css_248z$2 = ".ResponsiveTable-module_responsiveTable__4y-Od{--table-border-color:#e0e0e0;--table-header-bg:#f8f9fa;--table-row-hover-bg:#f1f3f5;--table-row-stripe-bg:#fafbfc;--card-bg:#fff;--card-border-color:#
|
|
30
|
+
var css_248z$2 = ".ResponsiveTable-module_responsiveTable__4y-Od{--table-border-color:#e0e0e0;--table-header-bg:#f8f9fa;--table-row-hover-bg:#f1f3f5;--table-row-stripe-bg:#fafbfc;--card-bg:#fff;--card-border-color:#d1d5db;--card-shadow:0 2px 8px rgba(0,0,0,.06);--text-color:#212529;--text-color-muted:#6c757d;--interactive-color:#0056b3;--primary-color:#007bff;--rt-mobile-card-shadow:0 1px 2px rgba(0,0,0,.04),0 4px 12px rgba(0,0,0,.06),0 12px 32px rgba(0,0,0,.04);--rt-mobile-card-radius:16px;--rt-mobile-bg-wash:#f1f5f9;--rt-mobile-label-color:#475569;--rt-mobile-value-color:#1e293b}.ResponsiveTable-module_tableContainer__VjWjH{border:1px solid var(--table-border-color);border-radius:8px;overflow-x:auto;width:100%}.ResponsiveTable-module_responsiveTable__4y-Od{background-color:var(--card-bg);border-collapse:collapse;color:var(--text-color);width:100%}.ResponsiveTable-module_responsiveTable__4y-Od thead th{background-color:var(--table-header-bg);border-bottom:2px solid var(--table-border-color);color:var(--text-color-muted);font-size:.75rem;font-weight:600;letter-spacing:.05em;padding:1rem;text-align:left;text-transform:uppercase;z-index:1}.ResponsiveTable-module_responsiveTable__4y-Od td{border-bottom:1px solid var(--table-border-color);font-size:.9rem;padding:1rem;text-align:left}.ResponsiveTable-module_responsiveTable__4y-Od tr:last-child td{border-bottom:none}.ResponsiveTable-module_responsiveTable__4y-Od tr:nth-child(2n){background-color:var(--table-row-stripe-bg)}.ResponsiveTable-module_responsiveTable__4y-Od tr:hover{background-color:var(--table-row-hover-bg)}.ResponsiveTable-module_cardContainer__Het4h{background-color:var(--rt-mobile-bg-wash);border-radius:var(--rt-mobile-card-radius);display:flex;flex-direction:column;gap:1.25rem;padding:1rem}.ResponsiveTable-module_card__b-U2v{background-color:var(--card-bg);border:1px solid var(--card-border-color);border-bottom:3px solid var(--primary-color);border-radius:var(--rt-mobile-card-radius);box-shadow:var(--rt-mobile-card-shadow);overflow:hidden;padding:1rem;transition:box-shadow .2s ease-in-out,transform .2s ease-in-out}.ResponsiveTable-module_card__b-U2v:hover{box-shadow:0 2px 4px rgba(0,0,0,.06),0 8px 24px rgba(0,0,0,.08),0 16px 48px rgba(0,0,0,.06);transform:translateY(-4px)}.ResponsiveTable-module_card-header__Ttk51{border-bottom:1px solid var(--table-border-color);margin-bottom:1rem;padding-bottom:.5rem}.ResponsiveTable-module_card-row__qvIUJ{align-items:flex-start;display:flex;gap:1rem;justify-content:space-between;margin:0 0 .75rem}.ResponsiveTable-module_card-row__qvIUJ.ResponsiveTable-module_stacked__FSaTB{align-items:stretch;flex-direction:column;gap:.25rem;margin-bottom:1rem}.ResponsiveTable-module_card-row__qvIUJ:last-child{margin-bottom:0}.ResponsiveTable-module_card-label__v9L71{color:var(--rt-mobile-label-color);font-size:.75rem;font-weight:600;text-transform:uppercase;white-space:nowrap}.ResponsiveTable-module_card-value__BO-c-{color:var(--rt-mobile-value-color);font-size:.95rem;text-align:right}.ResponsiveTable-module_card-row__qvIUJ.ResponsiveTable-module_stacked__FSaTB .ResponsiveTable-module_card-value__BO-c-{text-align:left}.ResponsiveTable-module_numberValue__-TLR1{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;text-align:right!important}.ResponsiveTable-module_dateValue__UMvqJ{color:var(--text-color-muted);font-size:.85rem}.ResponsiveTable-module_imageValue__wVb-p img{border-radius:8px;height:auto;max-width:100%;object-fit:cover}.ResponsiveTable-module_inputValue__CrGMx{margin-top:.5rem;width:100%}.ResponsiveTable-module_inputValue__CrGMx button,.ResponsiveTable-module_inputValue__CrGMx input[type=text],.ResponsiveTable-module_inputValue__CrGMx select,.ResponsiveTable-module_inputValue__CrGMx textarea{min-height:44px;width:100%!important}.ResponsiveTable-module_clickableRow__0kjWm{cursor:pointer}.ResponsiveTable-module_clickableHeader__xHQhF{cursor:pointer;transition:color .2s}.ResponsiveTable-module_clickableHeader__xHQhF:hover{color:var(--interactive-color)}.ResponsiveTable-module_sortable__yvA60{cursor:pointer}.ResponsiveTable-module_sorted-asc__jzOIa,.ResponsiveTable-module_sorted-desc__7WCFK{background-color:#f0f7ff!important;color:var(--interactive-color)!important}.ResponsiveTable-module_headerInnerWrapper__3VAhD{align-items:center;display:flex;justify-content:space-between;width:100%}.ResponsiveTable-module_headerContent__ODMzS{flex-grow:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ResponsiveTable-module_sortIcon__A9WtD{background-position:50%;background-repeat:no-repeat;background-size:contain;flex-shrink:0;height:1rem;margin-left:.5rem;opacity:.3;width:1rem}.ResponsiveTable-module_sortable__yvA60:hover .ResponsiveTable-module_sortIcon__A9WtD{opacity:.8}.ResponsiveTable-module_sortable__yvA60 .ResponsiveTable-module_sortIcon__A9WtD{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%236c757d'%3E%3Cpath d='M10 18h4v-2h-4v2zm-6-8v2h16V8H4zm3-6h10v2H7V2z'/%3E%3C/svg%3E\")}.ResponsiveTable-module_sorted-asc__jzOIa .ResponsiveTable-module_sortIcon__A9WtD{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%230056b3'%3E%3Cpath d='m7 14 5-5 5 5z'/%3E%3C/svg%3E\");opacity:1}.ResponsiveTable-module_sorted-desc__7WCFK .ResponsiveTable-module_sortIcon__A9WtD{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%230056b3'%3E%3Cpath d='m7 10 5 5 5-5z'/%3E%3C/svg%3E\");opacity:1}.ResponsiveTable-module_responsiveTable__4y-Od tfoot{background-color:var(--table-header-bg);border-top:2px solid var(--table-border-color)}.ResponsiveTable-module_footerCell__8H-uG{font-size:.9rem;font-weight:600;padding:1rem;text-align:right}.ResponsiveTable-module_clickableFooterCell__WB9Ss{color:var(--interactive-color);cursor:pointer}.ResponsiveTable-module_clickableFooterCell__WB9Ss:hover{text-decoration:underline}.ResponsiveTable-module_footerCard__-NE2M{background-color:var(--table-header-bg);border:1px solid var(--card-border-color);border-radius:12px;margin-top:1rem;overflow:hidden;padding:1.25rem}.ResponsiveTable-module_footer-card-row__Vv6Ur{display:flex;font-size:.9rem;font-weight:600;justify-content:space-between;margin:0 0 .75rem}.ResponsiveTable-module_selectedRow__-JyNW{background-color:#e7f1ff!important}.ResponsiveTable-module_card__b-U2v.ResponsiveTable-module_selectedRow__-JyNW{border-left:4px solid var(--primary-color)}.ResponsiveTable-module_animatedRow__SFjrJ{animation:ResponsiveTable-module_cardEntrance__6JjRV .5s cubic-bezier(.2,.8,.2,1) forwards;opacity:0}@keyframes ResponsiveTable-module_cardEntrance__6JjRV{0%{opacity:0;transform:translateY(15px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes ResponsiveTable-module_fadeInUp__jMCS7{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.ResponsiveTable-module_skeleton__XxsXW{background-color:#f0f0f0;border-radius:4px;overflow:hidden;position:relative}.ResponsiveTable-module_skeleton__XxsXW:after{animation:ResponsiveTable-module_shimmer__H8PhC 1.5s infinite;background:linear-gradient(90deg,transparent,hsla(0,0%,100%,.6),transparent);content:\"\";height:100%;left:-150%;position:absolute;top:0;width:150%}@keyframes ResponsiveTable-module_shimmer__H8PhC{0%{transform:translateX(0)}to{transform:translateX(100%)}}.ResponsiveTable-module_noDataWrapper__Rj-k3{align-items:center;background-color:var(--table-header-bg);border:2px dashed var(--table-border-color);border-radius:12px;color:var(--text-color-muted);display:flex;flex-direction:column;gap:1rem;justify-content:center;padding:4rem 2rem}.ResponsiveTable-module_noData__IpwNq{font-size:1.1rem;font-weight:500}.ResponsiveTable-module_spinner__Pn-3D{animation:ResponsiveTable-module_spin__i3NHn .8s linear infinite;border:3px solid rgba(0,0,0,.1);border-left:3px solid var(--primary-color);border-radius:50%;height:24px;width:24px}@keyframes ResponsiveTable-module_spin__i3NHn{to{transform:rotate(1turn)}}.ResponsiveTable-module_infoContainer__b9IF5{align-items:center;color:var(--text-color-muted);display:flex;font-size:.85rem;gap:.5rem;justify-content:center;padding:1.5rem}.ResponsiveTable-module_stickyHeader__-jjN- th{box-shadow:0 2px 4px rgba(0,0,0,.05);position:sticky;top:0}.ResponsiveTable-module_internalStickyHeader__idiJY th{position:sticky;top:0}";
|
|
31
31
|
var styles$2 = {"responsiveTable":"ResponsiveTable-module_responsiveTable__4y-Od","tableContainer":"ResponsiveTable-module_tableContainer__VjWjH","cardContainer":"ResponsiveTable-module_cardContainer__Het4h","card":"ResponsiveTable-module_card__b-U2v","card-header":"ResponsiveTable-module_card-header__Ttk51","card-row":"ResponsiveTable-module_card-row__qvIUJ","stacked":"ResponsiveTable-module_stacked__FSaTB","card-label":"ResponsiveTable-module_card-label__v9L71","card-value":"ResponsiveTable-module_card-value__BO-c-","numberValue":"ResponsiveTable-module_numberValue__-TLR1","dateValue":"ResponsiveTable-module_dateValue__UMvqJ","imageValue":"ResponsiveTable-module_imageValue__wVb-p","inputValue":"ResponsiveTable-module_inputValue__CrGMx","clickableRow":"ResponsiveTable-module_clickableRow__0kjWm","clickableHeader":"ResponsiveTable-module_clickableHeader__xHQhF","sortable":"ResponsiveTable-module_sortable__yvA60","sorted-asc":"ResponsiveTable-module_sorted-asc__jzOIa","sorted-desc":"ResponsiveTable-module_sorted-desc__7WCFK","headerInnerWrapper":"ResponsiveTable-module_headerInnerWrapper__3VAhD","headerContent":"ResponsiveTable-module_headerContent__ODMzS","sortIcon":"ResponsiveTable-module_sortIcon__A9WtD","footerCell":"ResponsiveTable-module_footerCell__8H-uG","clickableFooterCell":"ResponsiveTable-module_clickableFooterCell__WB9Ss","footerCard":"ResponsiveTable-module_footerCard__-NE2M","footer-card-row":"ResponsiveTable-module_footer-card-row__Vv6Ur","selectedRow":"ResponsiveTable-module_selectedRow__-JyNW","animatedRow":"ResponsiveTable-module_animatedRow__SFjrJ","cardEntrance":"ResponsiveTable-module_cardEntrance__6JjRV","skeleton":"ResponsiveTable-module_skeleton__XxsXW","shimmer":"ResponsiveTable-module_shimmer__H8PhC","noDataWrapper":"ResponsiveTable-module_noDataWrapper__Rj-k3","noData":"ResponsiveTable-module_noData__IpwNq","spinner":"ResponsiveTable-module_spinner__Pn-3D","spin":"ResponsiveTable-module_spin__i3NHn","infoContainer":"ResponsiveTable-module_infoContainer__b9IF5","stickyHeader":"ResponsiveTable-module_stickyHeader__-jjN-","internalStickyHeader":"ResponsiveTable-module_internalStickyHeader__idiJY","fadeInUp":"ResponsiveTable-module_fadeInUp__jMCS7"};
|
|
32
32
|
styleInject(css_248z$2);
|
|
33
33
|
|
|
@@ -496,6 +496,10 @@ class FilterPlugin {
|
|
|
496
496
|
} })));
|
|
497
497
|
};
|
|
498
498
|
this.processData = (data) => {
|
|
499
|
+
var _a;
|
|
500
|
+
if (((_a = this.api.filterProps) === null || _a === void 0 ? void 0 : _a.mode) === 'server') {
|
|
501
|
+
return data;
|
|
502
|
+
}
|
|
499
503
|
if (!this.filterText || !this.api.columnDefinitions) {
|
|
500
504
|
return data;
|
|
501
505
|
}
|
|
@@ -522,6 +526,10 @@ class FilterPlugin {
|
|
|
522
526
|
_row,
|
|
523
527
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
524
528
|
_column) => {
|
|
529
|
+
var _a;
|
|
530
|
+
if (((_a = this.api.filterProps) === null || _a === void 0 ? void 0 : _a.mode) === 'server') {
|
|
531
|
+
return content;
|
|
532
|
+
}
|
|
525
533
|
if (!this.filterText || typeof content !== 'string') {
|
|
526
534
|
return content;
|
|
527
535
|
}
|
|
@@ -534,8 +542,10 @@ class FilterPlugin {
|
|
|
534
542
|
clearTimeout(this.debounceTimeout);
|
|
535
543
|
}
|
|
536
544
|
this.debounceTimeout = setTimeout(() => {
|
|
545
|
+
var _a, _b;
|
|
537
546
|
this.filterText = currentFilterText;
|
|
538
547
|
this.api.forceUpdate();
|
|
548
|
+
(_b = (_a = this.api).onFilterChange) === null || _b === void 0 ? void 0 : _b.call(_a, currentFilterText);
|
|
539
549
|
}, 300);
|
|
540
550
|
};
|
|
541
551
|
}
|
|
@@ -757,7 +767,7 @@ class SortPlugin {
|
|
|
757
767
|
}
|
|
758
768
|
|
|
759
769
|
const useTablePlugins = (props) => {
|
|
760
|
-
const { data, plugins, filterProps, selectionProps, sortProps, columnDefinitions, getScrollableElement, infiniteScrollProps, } = props;
|
|
770
|
+
const { data, plugins, filterProps, selectionProps, sortProps, columnDefinitions, getScrollableElement, infiniteScrollProps, onFilterChange, } = props;
|
|
761
771
|
const [processedData, setProcessedData] = useState(data);
|
|
762
772
|
const [activePlugins, setActivePlugins] = useState([]);
|
|
763
773
|
// Persist internal plugins using refs to prevent state loss
|
|
@@ -831,6 +841,7 @@ const useTablePlugins = (props) => {
|
|
|
831
841
|
filterProps: filterProps,
|
|
832
842
|
selectionProps: selectionProps,
|
|
833
843
|
columnDefinitions: columnDefinitions,
|
|
844
|
+
onFilterChange: onFilterChange,
|
|
834
845
|
};
|
|
835
846
|
// Initialize/Refresh all active plugins with the current API
|
|
836
847
|
newActivePlugins.forEach((plugin) => {
|
|
@@ -856,6 +867,7 @@ const useTablePlugins = (props) => {
|
|
|
856
867
|
getScrollableElement,
|
|
857
868
|
infiniteScrollProps,
|
|
858
869
|
getRawColumnDefinition,
|
|
870
|
+
onFilterChange,
|
|
859
871
|
]);
|
|
860
872
|
const forceUpdatePlugins = useCallback(() => {
|
|
861
873
|
setProcessedData(initializePlugins());
|
|
@@ -1026,6 +1038,7 @@ const useTableDataSource = (props) => {
|
|
|
1026
1038
|
const [totalCount, setTotalCount] = useState(undefined);
|
|
1027
1039
|
const [isLoading, setIsLoading] = useState(false);
|
|
1028
1040
|
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
1041
|
+
const [error, setError] = useState(undefined);
|
|
1029
1042
|
const isInitialMount = useRef(true);
|
|
1030
1043
|
const fetchData = useCallback((page, isAppend) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1031
1044
|
if (!dataSource)
|
|
@@ -1037,6 +1050,7 @@ const useTableDataSource = (props) => {
|
|
|
1037
1050
|
setIsLoading(true);
|
|
1038
1051
|
}
|
|
1039
1052
|
try {
|
|
1053
|
+
setError(undefined);
|
|
1040
1054
|
const params = {
|
|
1041
1055
|
page,
|
|
1042
1056
|
pageSize,
|
|
@@ -1066,9 +1080,10 @@ const useTableDataSource = (props) => {
|
|
|
1066
1080
|
setHasMore(newItems.length === pageSize);
|
|
1067
1081
|
}
|
|
1068
1082
|
}
|
|
1069
|
-
catch (
|
|
1070
|
-
|
|
1083
|
+
catch (err) {
|
|
1084
|
+
setError(err);
|
|
1071
1085
|
setHasMore(false);
|
|
1086
|
+
console.error('Error fetching data from dataSource:', err);
|
|
1072
1087
|
}
|
|
1073
1088
|
finally {
|
|
1074
1089
|
setIsLoading(false);
|
|
@@ -1105,6 +1120,7 @@ const useTableDataSource = (props) => {
|
|
|
1105
1120
|
isFetchingMore,
|
|
1106
1121
|
loadNextPage,
|
|
1107
1122
|
resetAndFetch,
|
|
1123
|
+
error,
|
|
1108
1124
|
};
|
|
1109
1125
|
};
|
|
1110
1126
|
|
|
@@ -1112,8 +1128,8 @@ const useTableDataSource = (props) => {
|
|
|
1112
1128
|
* A highly customizable, mobile-first responsive React table.
|
|
1113
1129
|
* Supports static data or async data sources with built-in infinite scroll.
|
|
1114
1130
|
*/
|
|
1115
|
-
function
|
|
1116
|
-
const { columnDefinitions, data: initialData, dataSource, pageSize, noDataComponent, maxHeight, onRowClick, footerRows, mobileBreakpoint, plugins, enablePageLevelStickyHeader, infiniteScrollProps, filterProps, selectionProps, animationProps, sortProps, mobileCardClassName, } = props;
|
|
1131
|
+
function ResponsiveTableInner(props, ref) {
|
|
1132
|
+
const { columnDefinitions, data: initialData, dataSource, pageSize, noDataComponent, maxHeight, onRowClick, footerRows, mobileBreakpoint, plugins, enablePageLevelStickyHeader, infiniteScrollProps, filterProps, selectionProps, animationProps, sortProps, mobileCardClassName, onDataSourceStateChange, onPageChange, onDataSourceError, } = props;
|
|
1117
1133
|
const tableContainerRef = useRef(null);
|
|
1118
1134
|
const headerRef = useRef(null);
|
|
1119
1135
|
const { isMobile, isHeaderSticky } = useResponsiveTable({
|
|
@@ -1126,17 +1142,36 @@ function ResponsiveTable(props) {
|
|
|
1126
1142
|
const getScrollableElement = useCallback(() => tableContainerRef.current, []);
|
|
1127
1143
|
// Track active sort state for dataSource
|
|
1128
1144
|
const [activeSort /*, setActiveSort*/] = useState((sortProps === null || sortProps === void 0 ? void 0 : sortProps.initialSortColumn) ? { columnId: sortProps.initialSortColumn, direction: sortProps.initialSortDirection || 'asc' } : undefined);
|
|
1129
|
-
|
|
1145
|
+
// Track active filter state for dataSource
|
|
1146
|
+
const [activeFilter, setActiveFilter] = useState('');
|
|
1147
|
+
const handleFilterChange = useCallback((text) => {
|
|
1148
|
+
setActiveFilter(text);
|
|
1149
|
+
}, []);
|
|
1150
|
+
const { data: sourceData, isLoading: isSourceLoading, isFetchingMore, hasMore, totalCount, currentPage, loadNextPage, error, resetAndFetch, } = useTableDataSource({
|
|
1130
1151
|
dataSource,
|
|
1131
1152
|
pageSize,
|
|
1132
1153
|
initialData,
|
|
1133
1154
|
sort: activeSort,
|
|
1134
|
-
|
|
1155
|
+
filter: (filterProps === null || filterProps === void 0 ? void 0 : filterProps.mode) === 'server' ? activeFilter : undefined,
|
|
1135
1156
|
});
|
|
1157
|
+
useImperativeHandle(ref, () => ({
|
|
1158
|
+
loadNextPage: () => loadNextPage(),
|
|
1159
|
+
resetAndFetch: () => resetAndFetch(),
|
|
1160
|
+
getState: () => ({
|
|
1161
|
+
data: sourceData,
|
|
1162
|
+
currentPage,
|
|
1163
|
+
hasMore,
|
|
1164
|
+
totalCount,
|
|
1165
|
+
isLoading: isSourceLoading,
|
|
1166
|
+
isFetchingMore,
|
|
1167
|
+
error,
|
|
1168
|
+
}),
|
|
1169
|
+
}), [loadNextPage, resetAndFetch, sourceData, currentPage, hasMore, totalCount, isSourceLoading, isFetchingMore, error]);
|
|
1136
1170
|
const currentDataToProcess = dataSource ? sourceData : initialData;
|
|
1137
1171
|
const { processedData, activePlugins, visibleColumns } = useTablePlugins({
|
|
1138
1172
|
data: currentDataToProcess,
|
|
1139
1173
|
plugins,
|
|
1174
|
+
onFilterChange: (filterProps === null || filterProps === void 0 ? void 0 : filterProps.mode) === 'server' ? handleFilterChange : undefined,
|
|
1140
1175
|
filterProps,
|
|
1141
1176
|
selectionProps,
|
|
1142
1177
|
sortProps,
|
|
@@ -1144,11 +1179,32 @@ function ResponsiveTable(props) {
|
|
|
1144
1179
|
getScrollableElement,
|
|
1145
1180
|
infiniteScrollProps,
|
|
1146
1181
|
});
|
|
1147
|
-
//
|
|
1182
|
+
// Fire onDataSourceStateChange when dataSource state changes
|
|
1183
|
+
useEffect(() => {
|
|
1184
|
+
if (dataSource && onDataSourceStateChange) {
|
|
1185
|
+
onDataSourceStateChange({
|
|
1186
|
+
data: sourceData,
|
|
1187
|
+
currentPage,
|
|
1188
|
+
hasMore,
|
|
1189
|
+
totalCount,
|
|
1190
|
+
isLoading: isSourceLoading,
|
|
1191
|
+
isFetchingMore,
|
|
1192
|
+
error,
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
}, [dataSource, sourceData, currentPage, hasMore, totalCount, isSourceLoading, isFetchingMore, error, onDataSourceStateChange]);
|
|
1196
|
+
// Fire onPageChange when page changes
|
|
1197
|
+
useEffect(() => {
|
|
1198
|
+
if (dataSource && onPageChange) {
|
|
1199
|
+
onPageChange(currentPage);
|
|
1200
|
+
}
|
|
1201
|
+
}, [dataSource, currentPage, onPageChange]);
|
|
1202
|
+
// Fire onDataSourceError when error occurs
|
|
1148
1203
|
useEffect(() => {
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1204
|
+
if (dataSource && error && onDataSourceError) {
|
|
1205
|
+
onDataSourceError(error);
|
|
1206
|
+
}
|
|
1207
|
+
}, [dataSource, error, onDataSourceError]);
|
|
1152
1208
|
const hasData = useMemo(() => processedData.length > 0, [processedData]);
|
|
1153
1209
|
const noDataSvg = (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "#ccc", height: "40", width: "40", viewBox: "0 0 24 24" },
|
|
1154
1210
|
React.createElement("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-14h2v6h-2zm0 8h2v2h-2z" })));
|
|
@@ -1216,6 +1272,31 @@ function ResponsiveTable(props) {
|
|
|
1216
1272
|
if (isLoading && !hasData) {
|
|
1217
1273
|
return React.createElement(SkeletonView, { isMobile: isMobile, columnDefinitions: visibleColumns });
|
|
1218
1274
|
}
|
|
1275
|
+
if (error && !isLoading && !hasData) {
|
|
1276
|
+
return (React.createElement("div", { style: {
|
|
1277
|
+
display: 'flex',
|
|
1278
|
+
flexDirection: 'column',
|
|
1279
|
+
alignItems: 'center',
|
|
1280
|
+
justifyContent: 'center',
|
|
1281
|
+
padding: '4rem 2rem',
|
|
1282
|
+
gap: '1rem',
|
|
1283
|
+
color: '#6c757d',
|
|
1284
|
+
border: '2px dashed #e0e0e0',
|
|
1285
|
+
borderRadius: '12px',
|
|
1286
|
+
backgroundColor: '#f8f9fa',
|
|
1287
|
+
} },
|
|
1288
|
+
React.createElement("div", { style: { fontWeight: 500, fontSize: '1.1rem' } }, "Failed to load data"),
|
|
1289
|
+
React.createElement("div", { style: { fontSize: '0.85rem', textAlign: 'center' } }, error.message),
|
|
1290
|
+
React.createElement("button", { onClick: resetAndFetch, style: {
|
|
1291
|
+
padding: '0.5rem 1.5rem',
|
|
1292
|
+
backgroundColor: '#007bff',
|
|
1293
|
+
color: '#fff',
|
|
1294
|
+
border: 'none',
|
|
1295
|
+
borderRadius: '6px',
|
|
1296
|
+
cursor: 'pointer',
|
|
1297
|
+
fontWeight: 500,
|
|
1298
|
+
} }, "Retry")));
|
|
1299
|
+
}
|
|
1219
1300
|
return (React.createElement(TableProvider, { value: {
|
|
1220
1301
|
data: currentDataToProcess,
|
|
1221
1302
|
processedData,
|
|
@@ -1234,6 +1315,7 @@ function ResponsiveTable(props) {
|
|
|
1234
1315
|
isLoading: isSourceLoading,
|
|
1235
1316
|
isFetchingMore,
|
|
1236
1317
|
loadNextPage,
|
|
1318
|
+
error,
|
|
1237
1319
|
} : undefined,
|
|
1238
1320
|
mobileCardClassName,
|
|
1239
1321
|
} },
|
|
@@ -1243,6 +1325,7 @@ function ResponsiveTable(props) {
|
|
|
1243
1325
|
(hasData || isLoading) && isMobile && (React.createElement(MobileView, { mobileFooter: mobileFooter })),
|
|
1244
1326
|
(hasData || isLoading) && !isMobile && (React.createElement(DesktopView, { maxHeight: maxHeight, isHeaderSticky: isHeaderSticky, tableContainerRef: tableContainerRef, headerRef: headerRef, footerRows: footerRows, renderPluginFooters: renderPluginFooters })))));
|
|
1245
1327
|
}
|
|
1328
|
+
const ResponsiveTable = forwardRef(ResponsiveTableInner);
|
|
1246
1329
|
|
|
1247
1330
|
class InfiniteScrollPlugin {
|
|
1248
1331
|
constructor() {
|
|
@@ -1297,5 +1380,5 @@ class InfiniteScrollPlugin {
|
|
|
1297
1380
|
}
|
|
1298
1381
|
}
|
|
1299
1382
|
|
|
1300
|
-
export { FilterPlugin, InfiniteScrollPlugin, SelectionPlugin, SortPlugin, ResponsiveTable as default };
|
|
1383
|
+
export { FilterPlugin, InfiniteScrollPlugin, SelectionPlugin, SortPlugin, ResponsiveTable as default, useTableContext };
|
|
1301
1384
|
//# sourceMappingURL=index.es.js.map
|