jattac.libs.web.responsive-table 0.2.2 → 0.2.4
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 +631 -581
- package/dist/Data/IResponsiveTableColumnDefinition.d.ts +4 -0
- package/dist/Plugins/SortPlugin.d.ts +29 -0
- package/dist/UI/ResponsiveTable.d.ts +5 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +136 -6
- package/dist/index.js.map +1 -1
- package/package.json +66 -60
- package/.eslintrc.json +0 -8
- package/.prettierrc +0 -5
- package/gemini/commit_message.txt +0 -1
- package/gemini/index.md +0 -1
- package/gemini/project_analysis.md +0 -41
- package/gemini/release_git_steps.md +0 -80
- package/rollup.config.js +0 -23
- package/set-origin-urls.sh +0 -32
- package/src/Data/IFooterColumnDefinition.ts +0 -21
- package/src/Data/IFooterRowDefinition.ts +0 -5
- package/src/Data/IResponsiveTableColumnDefinition.tsx +0 -12
- package/src/Plugins/FilterPlugin.tsx +0 -71
- package/src/Plugins/IResponsiveTablePlugin.ts +0 -48
- package/src/Plugins/InfiniteScrollPlugin.tsx +0 -73
- package/src/Styles/ResponsiveTable.module.css +0 -253
- package/src/UI/ResponsiveTable.tsx +0 -532
- package/src/index.tsx +0 -10
- package/src/typings.d.ts +0 -14
- package/tsconfig.json +0 -22
- package/update-dependancies.sh +0 -4
|
@@ -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
|
+
}
|
|
@@ -12,6 +12,7 @@ interface IProps<TData> {
|
|
|
12
12
|
footerRows?: IFooterRowDefinition[];
|
|
13
13
|
mobileBreakpoint?: number;
|
|
14
14
|
plugins?: IResponsiveTablePlugin<TData>[];
|
|
15
|
+
enablePageLevelStickyHeader?: boolean;
|
|
15
16
|
infiniteScrollProps?: {
|
|
16
17
|
enableInfiniteScroll?: boolean;
|
|
17
18
|
onLoadMore?: (currentData: TData[]) => Promise<TData[] | null>;
|
|
@@ -32,10 +33,12 @@ interface IState<TData> {
|
|
|
32
33
|
isMobile: boolean;
|
|
33
34
|
processedData: TData[];
|
|
34
35
|
isLoadingMore: boolean;
|
|
36
|
+
isHeaderSticky: boolean;
|
|
35
37
|
}
|
|
36
38
|
declare class ResponsiveTable<TData> extends Component<IProps<TData>, IState<TData>> {
|
|
37
39
|
private debouncedResize;
|
|
38
40
|
private tableContainerRef;
|
|
41
|
+
private headerRef;
|
|
39
42
|
constructor(props: IProps<TData>);
|
|
40
43
|
private get mobileBreakpoint();
|
|
41
44
|
private debounce;
|
|
@@ -46,6 +49,7 @@ declare class ResponsiveTable<TData> extends Component<IProps<TData>, IState<TDa
|
|
|
46
49
|
componentDidMount(): void;
|
|
47
50
|
componentWillUnmount(): void;
|
|
48
51
|
componentDidUpdate(prevProps: IProps<TData>): void;
|
|
52
|
+
private handleScroll;
|
|
49
53
|
private initializePlugins;
|
|
50
54
|
private processData;
|
|
51
55
|
handleResize: () => void;
|
|
@@ -53,6 +57,7 @@ declare class ResponsiveTable<TData> extends Component<IProps<TData>, IState<TDa
|
|
|
53
57
|
private getRawColumnDefinition;
|
|
54
58
|
private onHeaderClickCallback;
|
|
55
59
|
private getClickableHeaderClassName;
|
|
60
|
+
private getHeaderProps;
|
|
56
61
|
private get rowClickFunction();
|
|
57
62
|
private get rowClickStyle();
|
|
58
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
|
-
|
|
8
|
+
import { SortPlugin } from './Plugins/SortPlugin';
|
|
9
|
+
export { IResponsiveTableColumnDefinition, ColumnDefinition, IFooterColumnDefinition, IFooterRowDefinition, FilterPlugin, InfiniteScrollPlugin, IResponsiveTablePlugin, SortPlugin };
|
|
9
10
|
export default ResponsiveTable;
|
package/dist/index.js
CHANGED
|
@@ -31,8 +31,8 @@ function styleInject(css, ref) {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
var css_248z = "/* Using CSS variables for a more maintainable and themeable design */\n.ResponsiveTable-module_responsiveTable__4y-Od {\n --table-border-color: #e0e0e0;\n --table-header-bg: #f8f9fa;\n --table-row-hover-bg: #e9ecef;\n --table-row-stripe-bg: #f2f2f2;\n --card-bg: #ffffff;\n --card-border-color: #e0e0e0;\n --card-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n --text-color: #212529;\n --text-color-muted: #6c757d;\n --interactive-color: #0056b3;\n}\n\n/* Mobile Card View */\n.ResponsiveTable-module_card__b-U2v {\n background-color: var(--card-bg);\n border: 1px solid var(--card-border-color);\n margin-bottom: 1rem;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: var(--card-shadow);\n transition: box-shadow 0.2s ease-in-out;\n}\n\n.ResponsiveTable-module_card__b-U2v:hover {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n}\n\n/* This is not used in the component, but keeping it styled in case it's added back */\n.ResponsiveTable-module_card-header__Ttk51 {\n background-color: var(--table-header-bg);\n padding: 0.75rem 1rem;\n font-weight: 600; /* Bolder */\n border-bottom: 1px solid var(--table-border-color);\n}\n\n.ResponsiveTable-module_card-body__XIy0h {\n padding: 1rem;\n font-size: 0.9rem;\n}\n\n.ResponsiveTable-module_card-body__XIy0h p {\n margin: 0 0 0.75rem;\n display: flex;\n justify-content: space-between;\n}\n\n.ResponsiveTable-module_card-body__XIy0h p:last-child {\n margin-bottom: 0;\n}\n\n.ResponsiveTable-module_card-label__v9L71 {\n font-weight: 600;\n color: var(--text-color);\n margin-right: 0.5rem;\n}\n\n/* Desktop Table View */\n.ResponsiveTable-module_responsiveTable__4y-Od {\n width: 100%;\n border-collapse: collapse;\n color: var(--text-color);\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od thead th {\n background-color: var(--table-header-bg);\n position: sticky;\n top: 0;\n z-index:
|
|
35
|
-
var styles = {"responsiveTable":"ResponsiveTable-module_responsiveTable__4y-Od","card":"ResponsiveTable-module_card__b-U2v","card-header":"ResponsiveTable-module_card-header__Ttk51","card-body":"ResponsiveTable-module_card-body__XIy0h","card-label":"ResponsiveTable-module_card-label__v9L71","clickableHeader":"ResponsiveTable-module_clickableHeader__xHQhF","footerCell":"ResponsiveTable-module_footerCell__8H-uG","clickableFooterCell":"ResponsiveTable-module_clickableFooterCell__WB9Ss","footerCard":"ResponsiveTable-module_footerCard__-NE2M","footer-card-body":"ResponsiveTable-module_footer-card-body__CtBMv","footer-card-row":"ResponsiveTable-module_footer-card-row__Vv6Ur","animatedRow":"ResponsiveTable-module_animatedRow__SFjrJ","skeleton":"ResponsiveTable-module_skeleton__XxsXW","skeletonText":"ResponsiveTable-module_skeletonText__T-Lgq","skeletonCard":"ResponsiveTable-module_skeletonCard__AYVwL","noDataWrapper":"ResponsiveTable-module_noDataWrapper__Rj-k3","noData":"ResponsiveTable-module_noData__IpwNq"};
|
|
34
|
+
var css_248z = "/* Using CSS variables for a more maintainable and themeable design */\r\n.ResponsiveTable-module_responsiveTable__4y-Od {\r\n --table-border-color: #e0e0e0;\r\n --table-header-bg: #f8f9fa;\r\n --table-row-hover-bg: #e9ecef;\r\n --table-row-stripe-bg: #f2f2f2;\r\n --card-bg: #ffffff;\r\n --card-border-color: #e0e0e0;\r\n --card-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\r\n --text-color: #212529;\r\n --text-color-muted: #6c757d;\r\n --interactive-color: #0056b3;\r\n}\r\n\r\n/* Mobile Card View */\r\n.ResponsiveTable-module_card__b-U2v {\r\n background-color: var(--card-bg);\r\n border: 1px solid var(--card-border-color);\r\n margin-bottom: 1rem;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n box-shadow: var(--card-shadow);\r\n transition: box-shadow 0.2s ease-in-out;\r\n}\r\n\r\n.ResponsiveTable-module_card__b-U2v:hover {\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\r\n}\r\n\r\n/* This is not used in the component, but keeping it styled in case it's added back */\r\n.ResponsiveTable-module_card-header__Ttk51 {\r\n background-color: var(--table-header-bg);\r\n padding: 0.75rem 1rem;\r\n font-weight: 600; /* Bolder */\r\n border-bottom: 1px solid var(--table-border-color);\r\n}\r\n\r\n.ResponsiveTable-module_card-body__XIy0h {\r\n padding: 1rem;\r\n font-size: 0.9rem;\r\n}\r\n\r\n.ResponsiveTable-module_card-body__XIy0h p {\r\n margin: 0 0 0.75rem;\r\n display: flex;\r\n justify-content: space-between;\r\n}\r\n\r\n.ResponsiveTable-module_card-body__XIy0h p:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.ResponsiveTable-module_card-label__v9L71 {\r\n font-weight: 600;\r\n color: var(--text-color);\r\n margin-right: 0.5rem;\r\n}\r\n\r\n/* Desktop Table View */\r\n.ResponsiveTable-module_responsiveTable__4y-Od {\r\n width: 100%;\r\n border-collapse: collapse;\r\n color: var(--text-color);\r\n}\r\n\r\n.ResponsiveTable-module_responsiveTable__4y-Od thead th {\r\n background-color: var(--table-header-bg);\r\n position: sticky;\r\n top: 0;\r\n z-index: 1;\r\n font-weight: 600;\r\n text-align: left;\r\n padding: 1rem;\r\n border-bottom: 2px solid var(--table-border-color);\r\n}\r\n\r\n.ResponsiveTable-module_responsiveTable__4y-Od td {\r\n padding: 1rem;\r\n border-bottom: 1px solid var(--table-border-color);\r\n text-align: left;\r\n}\r\n\r\n.ResponsiveTable-module_responsiveTable__4y-Od tr {\r\n background-color: var(--card-bg);\r\n transition: background-color 0.2s ease-in-out;\r\n}\r\n\r\n/* Subtle striping for better readability */\r\n.ResponsiveTable-module_responsiveTable__4y-Od tr:nth-child(even) {\r\n background-color: var(--table-row-stripe-bg);\r\n}\r\n\r\n/* Modern hover effect */\r\n.ResponsiveTable-module_responsiveTable__4y-Od tr:hover {\r\n background-color: var(--table-row-hover-bg);\r\n}\r\n\r\n/* Clickable Header Style */\r\n.ResponsiveTable-module_clickableHeader__xHQhF {\r\n cursor: pointer;\r\n color: var(--interactive-color);\r\n}\r\n\r\n.ResponsiveTable-module_clickableHeader__xHQhF:hover {\r\n text-decoration: underline;\r\n}\r\n\r\n/* Sortable Header Styles */\r\n.ResponsiveTable-module_responsiveTable__4y-Od th.ResponsiveTable-module_sortable__yvA60 {\r\n cursor: pointer;\r\n position: relative;\r\n padding-right: 2rem; /* Space for the icon */\r\n}\r\n\r\n.ResponsiveTable-module_responsiveTable__4y-Od th .ResponsiveTable-module_sortIcon__A9WtD {\r\n position: absolute;\r\n right: 0.5rem;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n width: 1rem;\r\n height: 1rem;\r\n opacity: 0.4;\r\n transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out;\r\n}\r\n\r\n.ResponsiveTable-module_responsiveTable__4y-Od th.ResponsiveTable-module_sortable__yvA60:hover .ResponsiveTable-module_sortIcon__A9WtD {\r\n opacity: 1;\r\n}\r\n\r\n/* Default unsorted icon (up and down arrows) */\r\n.ResponsiveTable-module_responsiveTable__4y-Od th.ResponsiveTable-module_sortable__yvA60 .ResponsiveTable-module_sortIcon__A9WtD::before,\r\n.ResponsiveTable-module_responsiveTable__4y-Od th.ResponsiveTable-module_sortable__yvA60 .ResponsiveTable-module_sortIcon__A9WtD::after {\r\n content: '';\r\n position: absolute;\r\n display: block;\r\n width: 0;\r\n height: 0;\r\n border-left: 0.4em solid transparent;\r\n border-right: 0.4em solid transparent;\r\n}\r\n\r\n.ResponsiveTable-module_responsiveTable__4y-Od th.ResponsiveTable-module_sortable__yvA60 .ResponsiveTable-module_sortIcon__A9WtD::before {\r\n border-bottom: 0.4em solid var(--text-color);\r\n top: 0.1em;\r\n}\r\n\r\n.ResponsiveTable-module_responsiveTable__4y-Od th.ResponsiveTable-module_sortable__yvA60 .ResponsiveTable-module_sortIcon__A9WtD::after {\r\n border-top: 0.4em solid var(--text-color);\r\n bottom: 0.1em;\r\n}\r\n\r\n/* Sorted Ascending Icon */\r\n.ResponsiveTable-module_responsiveTable__4y-Od th.ResponsiveTable-module_sorted-asc__jzOIa .ResponsiveTable-module_sortIcon__A9WtD,\r\n.ResponsiveTable-module_responsiveTable__4y-Od th.ResponsiveTable-module_sorted-desc__7WCFK .ResponsiveTable-module_sortIcon__A9WtD {\r\n opacity: 1;\r\n}\r\n\r\n.ResponsiveTable-module_responsiveTable__4y-Od th.ResponsiveTable-module_sorted-asc__jzOIa .ResponsiveTable-module_sortIcon__A9WtD::before {\r\n border-bottom-color: var(--interactive-color);\r\n}\r\n\r\n.ResponsiveTable-module_responsiveTable__4y-Od th.ResponsiveTable-module_sorted-asc__jzOIa .ResponsiveTable-module_sortIcon__A9WtD::after {\r\n opacity: 0.4;\r\n}\r\n\r\n/* Sorted Descending Icon */\r\n.ResponsiveTable-module_responsiveTable__4y-Od th.ResponsiveTable-module_sorted-desc__7WCFK .ResponsiveTable-module_sortIcon__A9WtD::after {\r\n border-top-color: var(--interactive-color);\r\n}\r\n\r\n.ResponsiveTable-module_responsiveTable__4y-Od th.ResponsiveTable-module_sorted-desc__7WCFK .ResponsiveTable-module_sortIcon__A9WtD::before {\r\n opacity: 0.4;\r\n}\r\n\r\n\r\n.ResponsiveTable-module_responsiveTable__4y-Od tfoot {\r\n background-color: var(--table-header-bg);\r\n border-top: 2px solid var(--table-border-color);\r\n font-weight: 600;\r\n}\r\n\r\n.ResponsiveTable-module_footerCell__8H-uG {\r\n padding: 1rem;\r\n text-align: right;\r\n font-weight: 600;\r\n}\r\n\r\n.ResponsiveTable-module_clickableFooterCell__WB9Ss {\r\n cursor: pointer;\r\n color: var(--interactive-color);\r\n}\r\n\r\n.ResponsiveTable-module_clickableFooterCell__WB9Ss:hover {\r\n text-decoration: underline;\r\n}\r\n\r\n.ResponsiveTable-module_footerCard__-NE2M {\r\n background-color: var(--table-header-bg);\r\n border: 1px solid var(--card-border-color);\r\n border-top: 2px solid var(--table-border-color);\r\n margin-bottom: 1rem;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n box-shadow: none;\r\n}\r\n\r\n.ResponsiveTable-module_footer-card-body__CtBMv {\r\n padding: 1rem;\r\n font-size: 0.9rem;\r\n}\r\n\r\n.ResponsiveTable-module_footer-card-row__Vv6Ur {\r\n margin: 0 0 0.75rem;\r\n display: flex;\r\n justify-content: space-between;\r\n font-weight: 600;\r\n}\r\n\r\n/* No Data State */\r\n\r\n/* Staggered Entrance Animation */\r\n.ResponsiveTable-module_animatedRow__SFjrJ {\r\n animation: ResponsiveTable-module_fadeInUp__jMCS7 0.5s ease-out forwards;\r\n opacity: 0;\r\n}\r\n\r\n@keyframes ResponsiveTable-module_fadeInUp__jMCS7 {\r\n from {\r\n opacity: 0;\r\n transform: translateY(20px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n}\r\n\r\n/* Skeleton Loader */\r\n.ResponsiveTable-module_skeleton__XxsXW {\r\n background-color: #e0e0e0;\r\n border-radius: 4px;\r\n position: relative;\r\n overflow: hidden;\r\n}\r\n\r\n.ResponsiveTable-module_skeleton__XxsXW::after {\r\n content: '';\r\n position: absolute;\r\n top: 0;\r\n left: -150%;\r\n width: 150%;\r\n height: 100%;\r\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);\r\n animation: ResponsiveTable-module_shimmer__H8PhC 1.5s infinite;\r\n}\r\n\r\n.ResponsiveTable-module_skeletonText__T-Lgq {\r\n height: 1.2em;\r\n width: 100%;\r\n}\r\n\r\n.ResponsiveTable-module_skeletonCard__AYVwL {\r\n background-color: var(--card-bg);\r\n border: 1px solid var(--card-border-color);\r\n margin-bottom: 1rem;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n padding: 1rem;\r\n}\r\n\r\n@keyframes ResponsiveTable-module_shimmer__H8PhC {\r\n 0% {\r\n transform: translateX(0);\r\n }\r\n 100% {\r\n transform: translateX(100%);\r\n }\r\n}\r\n.ResponsiveTable-module_noDataWrapper__Rj-k3 {\r\n color: var(--text-color-muted); /* Softer color */\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n height: 100%;\r\n gap: 10px;\r\n padding: 40px;\r\n background-color: var(--table-header-bg);\r\n border: 1px dashed var(--table-border-color);\r\n border-radius: 8px;\r\n}\r\n\r\n.ResponsiveTable-module_noData__IpwNq {\r\n text-align: center;\r\n font-weight: 500; /* Less aggressive than bold */\r\n font-size: 1rem;\r\n}\r\n\r\n.ResponsiveTable-module_row-exit__EVX6T {\r\n opacity: 0;\r\n transform: scaleY(0);\r\n transition: transform 0.3s ease-out, opacity 0.3s ease-out;\r\n}\r\n\r\n.ResponsiveTable-module_row-enter__YKgI4 {\r\n opacity: 0;\r\n transform: translateY(20px);\r\n transition: transform 0.5s ease-out, opacity 0.5s ease-out;\r\n}\r\n\r\n.ResponsiveTable-module_row-flash__a4NOm {\r\n animation: ResponsiveTable-module_flash__nxeAX 0.5s ease-out;\r\n}\r\n\r\n@keyframes ResponsiveTable-module_flash__nxeAX {\r\n 0% {\r\n background-color: var(--table-row-hover-bg);\r\n }\r\n 100% {\r\n background-color: transparent;\r\n }\r\n}\r\n\r\n.ResponsiveTable-module_stickyHeader__-jjN- {\r\n position: sticky;\r\n top: 0;\r\n z-index: 1;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\r\n}\r\n";
|
|
35
|
+
var styles = {"responsiveTable":"ResponsiveTable-module_responsiveTable__4y-Od","card":"ResponsiveTable-module_card__b-U2v","card-header":"ResponsiveTable-module_card-header__Ttk51","card-body":"ResponsiveTable-module_card-body__XIy0h","card-label":"ResponsiveTable-module_card-label__v9L71","clickableHeader":"ResponsiveTable-module_clickableHeader__xHQhF","sortIcon":"ResponsiveTable-module_sortIcon__A9WtD","footerCell":"ResponsiveTable-module_footerCell__8H-uG","clickableFooterCell":"ResponsiveTable-module_clickableFooterCell__WB9Ss","footerCard":"ResponsiveTable-module_footerCard__-NE2M","footer-card-body":"ResponsiveTable-module_footer-card-body__CtBMv","footer-card-row":"ResponsiveTable-module_footer-card-row__Vv6Ur","animatedRow":"ResponsiveTable-module_animatedRow__SFjrJ","skeleton":"ResponsiveTable-module_skeleton__XxsXW","skeletonText":"ResponsiveTable-module_skeletonText__T-Lgq","skeletonCard":"ResponsiveTable-module_skeletonCard__AYVwL","noDataWrapper":"ResponsiveTable-module_noDataWrapper__Rj-k3","noData":"ResponsiveTable-module_noData__IpwNq","stickyHeader":"ResponsiveTable-module_stickyHeader__-jjN-"};
|
|
36
36
|
styleInject(css_248z);
|
|
37
37
|
|
|
38
38
|
class FilterPlugin {
|
|
@@ -972,6 +972,16 @@ class ResponsiveTable extends React.Component {
|
|
|
972
972
|
constructor(props) {
|
|
973
973
|
super(props);
|
|
974
974
|
this.tableContainerRef = React.createRef();
|
|
975
|
+
this.headerRef = React.createRef();
|
|
976
|
+
this.handleScroll = () => {
|
|
977
|
+
if (this.headerRef.current && !this.props.maxHeight) {
|
|
978
|
+
const { top } = this.headerRef.current.getBoundingClientRect();
|
|
979
|
+
const isSticky = top <= 0;
|
|
980
|
+
if (isSticky !== this.state.isHeaderSticky) {
|
|
981
|
+
this.setState({ isHeaderSticky: isSticky });
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
};
|
|
975
985
|
this.handleResize = () => {
|
|
976
986
|
this.setState({
|
|
977
987
|
isMobile: window.innerWidth <= this.mobileBreakpoint,
|
|
@@ -981,6 +991,7 @@ class ResponsiveTable extends React.Component {
|
|
|
981
991
|
isMobile: false,
|
|
982
992
|
processedData: props.data,
|
|
983
993
|
isLoadingMore: false,
|
|
994
|
+
isHeaderSticky: false,
|
|
984
995
|
};
|
|
985
996
|
this.debouncedResize = this.debounce(this.handleResize, 200);
|
|
986
997
|
}
|
|
@@ -1017,10 +1028,16 @@ class ResponsiveTable extends React.Component {
|
|
|
1017
1028
|
componentDidMount() {
|
|
1018
1029
|
this.handleResize(); // Initial check
|
|
1019
1030
|
window.addEventListener('resize', this.debouncedResize);
|
|
1031
|
+
if (this.props.enablePageLevelStickyHeader !== false) {
|
|
1032
|
+
window.addEventListener('scroll', this.handleScroll);
|
|
1033
|
+
}
|
|
1020
1034
|
this.initializePlugins();
|
|
1021
1035
|
}
|
|
1022
1036
|
componentWillUnmount() {
|
|
1023
1037
|
window.removeEventListener('resize', this.debouncedResize);
|
|
1038
|
+
if (this.props.enablePageLevelStickyHeader !== false) {
|
|
1039
|
+
window.removeEventListener('scroll', this.handleScroll);
|
|
1040
|
+
}
|
|
1024
1041
|
}
|
|
1025
1042
|
componentDidUpdate(prevProps) {
|
|
1026
1043
|
var _a, _b, _c;
|
|
@@ -1109,6 +1126,17 @@ class ResponsiveTable extends React.Component {
|
|
|
1109
1126
|
: '';
|
|
1110
1127
|
return clickableHeaderClassName;
|
|
1111
1128
|
}
|
|
1129
|
+
getHeaderProps(columnDefinition) {
|
|
1130
|
+
let headerProps = {};
|
|
1131
|
+
if (this.props.plugins) {
|
|
1132
|
+
this.props.plugins.forEach((plugin) => {
|
|
1133
|
+
if (plugin.getHeaderProps) {
|
|
1134
|
+
Object.assign(headerProps, plugin.getHeaderProps(this.getRawColumnDefinition(columnDefinition)));
|
|
1135
|
+
}
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1138
|
+
return headerProps;
|
|
1139
|
+
}
|
|
1112
1140
|
get rowClickFunction() {
|
|
1113
1141
|
if (this.props.onRowClick) {
|
|
1114
1142
|
return this.props.onRowClick;
|
|
@@ -1204,13 +1232,14 @@ class ResponsiveTable extends React.Component {
|
|
|
1204
1232
|
};
|
|
1205
1233
|
return (React.createElement("div", { style: fixedHeadersStyle, ref: this.tableContainerRef },
|
|
1206
1234
|
React.createElement("table", { className: styles['responsiveTable'] },
|
|
1207
|
-
React.createElement("thead",
|
|
1235
|
+
React.createElement("thead", { ref: this.headerRef, className: this.state.isHeaderSticky ? styles.stickyHeader : '' },
|
|
1208
1236
|
React.createElement("tr", null, this.props.columnDefinitions.map((columnDefinition, colIndex) => {
|
|
1209
1237
|
const onHeaderClickCallback = this.onHeaderClickCallback(columnDefinition);
|
|
1210
1238
|
const clickableHeaderClassName = this.getClickableHeaderClassName(onHeaderClickCallback, columnDefinition);
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1239
|
+
const headerProps = this.getHeaderProps(columnDefinition);
|
|
1240
|
+
return (React.createElement("th", Object.assign({ key: colIndex, className: `${clickableHeaderClassName}` }, headerProps),
|
|
1241
|
+
this.getColumnDefinition(columnDefinition, 0).displayLabel,
|
|
1242
|
+
React.createElement("span", { className: styles.sortIcon })));
|
|
1214
1243
|
}))),
|
|
1215
1244
|
React.createElement("tbody", null, ((_a = this.props.infiniteScrollProps) === null || _a === void 0 ? void 0 : _a.enableInfiniteScroll) ? (React.createElement(FixedSizeList, { height: fixedHeadersStyle.maxHeight ? (typeof fixedHeadersStyle.maxHeight === 'string' ? parseFloat(fixedHeadersStyle.maxHeight) : fixedHeadersStyle.maxHeight) : 500, itemCount: this.data.length, itemSize: 50, width: '100%', outerRef: this.tableContainerRef }, Row)) : (this.data.map((row, rowIndex) => {
|
|
1216
1245
|
var _a;
|
|
@@ -1226,6 +1255,10 @@ class ResponsiveTable extends React.Component {
|
|
|
1226
1255
|
}
|
|
1227
1256
|
return this.props.plugins.map((plugin) => {
|
|
1228
1257
|
if (plugin.renderHeader) {
|
|
1258
|
+
// For sort plugin, only render header in mobile view
|
|
1259
|
+
if (plugin.id === 'sort' && !this.state.isMobile) {
|
|
1260
|
+
return null;
|
|
1261
|
+
}
|
|
1229
1262
|
return React.createElement("div", { key: plugin.id }, plugin.renderHeader());
|
|
1230
1263
|
}
|
|
1231
1264
|
return null;
|
|
@@ -1255,7 +1288,104 @@ class ResponsiveTable extends React.Component {
|
|
|
1255
1288
|
}
|
|
1256
1289
|
}
|
|
1257
1290
|
|
|
1291
|
+
// Type-safe sort comparer helpers
|
|
1292
|
+
const createSortComparers = () => ({
|
|
1293
|
+
numeric: (key) => (a, b, direction) => {
|
|
1294
|
+
const valA = a[key];
|
|
1295
|
+
const valB = b[key];
|
|
1296
|
+
return direction === 'asc' ? valA - valB : valB - valA;
|
|
1297
|
+
},
|
|
1298
|
+
caseInsensitiveString: (key) => (a, b, direction) => {
|
|
1299
|
+
const valA = a[key].toLowerCase();
|
|
1300
|
+
const valB = b[key].toLowerCase();
|
|
1301
|
+
if (valA < valB)
|
|
1302
|
+
return direction === 'asc' ? -1 : 1;
|
|
1303
|
+
if (valA > valB)
|
|
1304
|
+
return direction === 'asc' ? 1 : -1;
|
|
1305
|
+
return 0;
|
|
1306
|
+
},
|
|
1307
|
+
date: (key) => (a, b, direction) => {
|
|
1308
|
+
const dateA = new Date(a[key]).getTime();
|
|
1309
|
+
const dateB = new Date(b[key]).getTime();
|
|
1310
|
+
return direction === 'asc' ? dateA - dateB : dateB - dateA;
|
|
1311
|
+
},
|
|
1312
|
+
});
|
|
1313
|
+
class SortPlugin {
|
|
1314
|
+
constructor(options) {
|
|
1315
|
+
var _a, _b;
|
|
1316
|
+
this.id = 'sort';
|
|
1317
|
+
this.comparers = createSortComparers();
|
|
1318
|
+
this.onPluginInit = (api) => {
|
|
1319
|
+
this.api = api;
|
|
1320
|
+
};
|
|
1321
|
+
this.processData = (data) => {
|
|
1322
|
+
if (!this.sortColumn || !this.sortDirection) {
|
|
1323
|
+
return data;
|
|
1324
|
+
}
|
|
1325
|
+
const columnDef = this.api.columnDefinitions.find((col) => col.dataKey === this.sortColumn);
|
|
1326
|
+
if (!columnDef) {
|
|
1327
|
+
return data;
|
|
1328
|
+
}
|
|
1329
|
+
const sortedData = [...data].sort((a, b) => {
|
|
1330
|
+
if (columnDef.sortComparer) {
|
|
1331
|
+
return columnDef.sortComparer(a, b, this.sortDirection);
|
|
1332
|
+
}
|
|
1333
|
+
let aValue, bValue;
|
|
1334
|
+
if (columnDef.getSortableValue) {
|
|
1335
|
+
aValue = columnDef.getSortableValue(a);
|
|
1336
|
+
bValue = columnDef.getSortableValue(b);
|
|
1337
|
+
}
|
|
1338
|
+
else {
|
|
1339
|
+
aValue = a[this.sortColumn];
|
|
1340
|
+
bValue = b[this.sortColumn];
|
|
1341
|
+
}
|
|
1342
|
+
if (aValue < bValue)
|
|
1343
|
+
return this.sortDirection === 'asc' ? -1 : 1;
|
|
1344
|
+
if (aValue > bValue)
|
|
1345
|
+
return this.sortDirection === 'asc' ? 1 : -1;
|
|
1346
|
+
return 0;
|
|
1347
|
+
});
|
|
1348
|
+
return sortedData;
|
|
1349
|
+
};
|
|
1350
|
+
this.getHeaderProps = (columnDef) => {
|
|
1351
|
+
const { dataKey, sortComparer, getSortableValue } = columnDef;
|
|
1352
|
+
const isSortable = !!(sortComparer || getSortableValue);
|
|
1353
|
+
if (!isSortable || !dataKey) {
|
|
1354
|
+
return {};
|
|
1355
|
+
}
|
|
1356
|
+
const onHeaderClick = () => {
|
|
1357
|
+
if (this.sortColumn === dataKey) {
|
|
1358
|
+
if (this.sortDirection === 'desc') {
|
|
1359
|
+
this.sortColumn = null;
|
|
1360
|
+
this.sortDirection = null;
|
|
1361
|
+
}
|
|
1362
|
+
else {
|
|
1363
|
+
this.sortDirection = 'desc';
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
else {
|
|
1367
|
+
this.sortColumn = dataKey;
|
|
1368
|
+
this.sortDirection = 'asc';
|
|
1369
|
+
}
|
|
1370
|
+
this.api.forceUpdate();
|
|
1371
|
+
};
|
|
1372
|
+
let sortClassName = 'sortable';
|
|
1373
|
+
if (this.sortColumn === dataKey) {
|
|
1374
|
+
sortClassName = `sorted-${this.sortDirection}`;
|
|
1375
|
+
}
|
|
1376
|
+
return {
|
|
1377
|
+
onClick: onHeaderClick,
|
|
1378
|
+
className: sortClassName,
|
|
1379
|
+
'aria-sort': this.sortColumn === dataKey ? (this.sortDirection === 'asc' ? 'ascending' : 'descending') : 'none',
|
|
1380
|
+
};
|
|
1381
|
+
};
|
|
1382
|
+
this.sortColumn = (_a = options === null || options === void 0 ? void 0 : options.initialSortColumn) !== null && _a !== void 0 ? _a : null;
|
|
1383
|
+
this.sortDirection = (_b = options === null || options === void 0 ? void 0 : options.initialSortDirection) !== null && _b !== void 0 ? _b : null;
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1258
1387
|
exports.FilterPlugin = FilterPlugin;
|
|
1259
1388
|
exports.InfiniteScrollPlugin = InfiniteScrollPlugin;
|
|
1389
|
+
exports.SortPlugin = SortPlugin;
|
|
1260
1390
|
exports.default = ResponsiveTable;
|
|
1261
1391
|
//# sourceMappingURL=index.js.map
|