qbs-react-grid 2.2.16 → 2.2.18
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/css/qbs-react-grid.css +1 -1
- package/dist/css/qbs-react-grid.min.css +1 -1
- package/dist/css/qbs-react-grid.min.css.map +1 -1
- package/es/Cell.js +2 -1
- package/es/Pagination.d.ts +3 -0
- package/es/Pagination.js +8 -3
- package/es/Table.d.ts +3 -0
- package/es/Table.js +18 -12
- package/es/index.d.ts +1 -1
- package/es/index.js +1 -1
- package/es/less/pagination.less +9 -9
- package/es/less/qbs-table.less +1 -2
- package/es/qbsTable/QbsTable.js +110 -73
- package/es/qbsTable/TableCardList.js +2 -0
- package/es/qbsTable/Toolbar.js +6 -3
- package/es/qbsTable/commontypes.d.ts +21 -12
- package/es/qbsTable/labels.d.ts +6 -2
- package/es/qbsTable/labels.js +10 -1
- package/es/qbsTable/utilities/CardComponent.d.ts +2 -0
- package/es/qbsTable/utilities/CardComponent.js +7 -3
- package/es/qbsTable/utilities/CardMenuDropdown.d.ts +2 -0
- package/es/qbsTable/utilities/CardMenuDropdown.js +7 -7
- package/es/qbsTable/utilities/SearchInput.d.ts +1 -0
- package/es/qbsTable/utilities/SearchInput.js +3 -1
- package/es/qbsTable/utilities/empty.js +1 -1
- package/es/qbsTable/utilities/tablecalc.d.ts +1 -1
- package/es/qbsTable/utilities/tablecalc.js +7 -2
- package/es/utils/useCellDescriptor.js +0 -1
- package/es/utils/useScrollListener.d.ts +1 -0
- package/es/utils/useScrollListener.js +5 -3
- package/lib/Cell.js +2 -1
- package/lib/Pagination.d.ts +3 -0
- package/lib/Pagination.js +8 -3
- package/lib/Table.d.ts +3 -0
- package/lib/Table.js +18 -12
- package/lib/index.d.ts +1 -1
- package/lib/index.js +3 -1
- package/lib/less/pagination.less +9 -9
- package/lib/less/qbs-table.less +1 -2
- package/lib/qbsTable/QbsTable.js +110 -73
- package/lib/qbsTable/TableCardList.js +2 -0
- package/lib/qbsTable/Toolbar.js +6 -3
- package/lib/qbsTable/commontypes.d.ts +21 -12
- package/lib/qbsTable/labels.d.ts +6 -2
- package/lib/qbsTable/labels.js +13 -2
- package/lib/qbsTable/utilities/CardComponent.d.ts +2 -0
- package/lib/qbsTable/utilities/CardComponent.js +7 -3
- package/lib/qbsTable/utilities/CardMenuDropdown.d.ts +2 -0
- package/lib/qbsTable/utilities/CardMenuDropdown.js +6 -5
- package/lib/qbsTable/utilities/SearchInput.d.ts +1 -0
- package/lib/qbsTable/utilities/SearchInput.js +3 -1
- package/lib/qbsTable/utilities/empty.js +1 -1
- package/lib/qbsTable/utilities/tablecalc.d.ts +1 -1
- package/lib/qbsTable/utilities/tablecalc.js +7 -2
- package/lib/utils/useCellDescriptor.js +0 -1
- package/lib/utils/useScrollListener.d.ts +1 -0
- package/lib/utils/useScrollListener.js +5 -3
- package/package.json +2 -2
- package/src/Cell.tsx +3 -1
- package/src/HeaderCell.tsx +0 -1
- package/src/Pagination.tsx +10 -3
- package/src/Table.tsx +23 -10
- package/src/customSelect.tsx +88 -88
- package/src/index.ts +2 -0
- package/src/less/pagination.less +9 -9
- package/src/less/qbs-table.less +1 -2
- package/src/qbsTable/QbsTable.tsx +84 -39
- package/src/qbsTable/TableCardList.tsx +2 -0
- package/src/qbsTable/Toolbar.tsx +4 -2
- package/src/qbsTable/commontypes.ts +21 -12
- package/src/qbsTable/labels.ts +9 -2
- package/src/qbsTable/utilities/CardComponent.tsx +7 -2
- package/src/qbsTable/utilities/CardMenuDropdown.tsx +11 -6
- package/src/qbsTable/utilities/SearchInput.tsx +3 -1
- package/src/qbsTable/utilities/empty.tsx +2 -2
- package/src/qbsTable/utilities/tablecalc.ts +8 -2
- package/src/utils/useCellDescriptor.ts +0 -1
- package/src/utils/useScrollListener.ts +13 -3
- package/src/utils/useTableRows.ts +1 -1
|
@@ -6,6 +6,7 @@ import ColumnGroup from '../ColumnGroup';
|
|
|
6
6
|
import HeaderCell from '../HeaderCell';
|
|
7
7
|
import Pagination from '../Pagination';
|
|
8
8
|
import Table from '../Table';
|
|
9
|
+
import isRTL from '../utils/isRTL';
|
|
9
10
|
import useResponsiveStore from '../utils/useResponsiveStore';
|
|
10
11
|
import { QbsColumnProps, QbsTableProps } from './commontypes';
|
|
11
12
|
import { mergeQbsTableLabels } from './labels';
|
|
@@ -31,6 +32,7 @@ import '../../dist/css/qbs-react-grid.css';
|
|
|
31
32
|
|
|
32
33
|
const CHECKBOX_LINE_HEIGHT = '36px';
|
|
33
34
|
const COLUMN_WIDTH = 250;
|
|
35
|
+
let REFRESH_KEY = 0;
|
|
34
36
|
const QbsTable: React.FC<QbsTableProps> = ({
|
|
35
37
|
handleColumnSort,
|
|
36
38
|
data,
|
|
@@ -52,7 +54,7 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
52
54
|
minHeight,
|
|
53
55
|
height = 630,
|
|
54
56
|
onExpandChange,
|
|
55
|
-
wordWrap,
|
|
57
|
+
wordWrap: propsWordWrap,
|
|
56
58
|
dataRowKey = 'id',
|
|
57
59
|
defaultExpandAllRows,
|
|
58
60
|
handleRowExpanded,
|
|
@@ -60,6 +62,7 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
60
62
|
rowExpand = false,
|
|
61
63
|
actionProps = [],
|
|
62
64
|
theme,
|
|
65
|
+
rtl: rtlProp,
|
|
63
66
|
handleMenuActions,
|
|
64
67
|
onRowClick,
|
|
65
68
|
expandedRowKeys,
|
|
@@ -93,33 +96,42 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
93
96
|
isCustomTableCardView = false,
|
|
94
97
|
handleTableCardView,
|
|
95
98
|
handleCustomCardLoader,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
hasMoreData,
|
|
100
|
+
loadMoreData,
|
|
101
|
+
infiniteLoading,
|
|
102
|
+
infiniteScroll = false,
|
|
99
103
|
rowViewToggle = false,
|
|
100
104
|
defaultRowView = true,
|
|
101
105
|
fullWidthView = false,
|
|
102
106
|
setTableFullView,
|
|
103
107
|
setRowViewToggle,
|
|
104
|
-
|
|
108
|
+
dropType = 'horizondal',
|
|
105
109
|
rowHeight,
|
|
110
|
+
isFullScreen,
|
|
106
111
|
showHeader = true,
|
|
112
|
+
labels: labelsProp
|
|
107
113
|
}) => {
|
|
108
114
|
const labels = useMemo(() => mergeQbsTableLabels(labelsProp), [labelsProp]);
|
|
109
|
-
const
|
|
110
|
-
if (!rowViewToggle) return wordWrap;
|
|
111
|
-
return defaultRowView ? false : 'break-word';
|
|
112
|
-
}, [rowViewToggle, defaultRowView, wordWrap]);
|
|
115
|
+
const [rowViewRefreshKey, setRowViewRefreshKey] = useState(0);
|
|
113
116
|
const [loading, setLoading] = useState(false);
|
|
114
117
|
const [columns, setColumns] = useState(propColumn);
|
|
115
118
|
const [checkedKeys, setCheckedKeys] = useState<(number | string)[]>([]);
|
|
116
|
-
const dataTheme = useMemo(
|
|
119
|
+
const dataTheme = useMemo(
|
|
120
|
+
() => theme ?? (typeof localStorage !== 'undefined' ? localStorage.getItem('theme') : null) ?? 'light',
|
|
121
|
+
[theme]
|
|
122
|
+
);
|
|
123
|
+
const rtl = rtlProp ?? isRTL();
|
|
117
124
|
const [isOpen, setIsOpen] = useState(false);
|
|
118
125
|
const prevColumns = useRef<any | null>(null);
|
|
119
126
|
const [tableViewToggle, setTableViewToggle] = useState(tableView);
|
|
120
127
|
const isMobile = useResponsiveStore();
|
|
121
128
|
const tableBodyRef = useRef<HTMLDivElement>(null);
|
|
122
|
-
const
|
|
129
|
+
const wheelWrapperRef = useRef<HTMLDivElement>(null);
|
|
130
|
+
const [wordWrap, setWordWrap] = useState(propsWordWrap ?? false);
|
|
131
|
+
const effectiveWordWrap = useMemo(() => {
|
|
132
|
+
if (!rowViewToggle) return wordWrap;
|
|
133
|
+
return defaultRowView ? false : 'break-word';
|
|
134
|
+
}, [rowViewToggle, defaultRowView, wordWrap]);
|
|
123
135
|
|
|
124
136
|
useEffect(() => {
|
|
125
137
|
if (rowViewToggle) {
|
|
@@ -178,16 +190,6 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
178
190
|
[checkedKeys]
|
|
179
191
|
);
|
|
180
192
|
|
|
181
|
-
const rowKeyField = dataRowKey ?? 'id';
|
|
182
|
-
const getRowClassName = useCallback(
|
|
183
|
-
(rowData: Record<string, unknown>) => {
|
|
184
|
-
if (!selection) return '';
|
|
185
|
-
const key = rowData?.[rowKeyField] as string | number | undefined;
|
|
186
|
-
return key !== undefined && checkedKeys?.includes(key) ? 'qbs-table-row-checked' : '';
|
|
187
|
-
},
|
|
188
|
-
[selection, checkedKeys, rowKeyField]
|
|
189
|
-
);
|
|
190
|
-
|
|
191
193
|
const handleToggle = useCallback(
|
|
192
194
|
(columnName: string) => {
|
|
193
195
|
let lastVisibleColumn: any = null;
|
|
@@ -223,6 +225,7 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
223
225
|
|
|
224
226
|
const handleColumnWidth = useCallback((newWidth?: number, dataKey?: any) => {
|
|
225
227
|
if (newWidth === undefined || dataKey === undefined) return;
|
|
228
|
+
REFRESH_KEY = REFRESH_KEY + 1;
|
|
226
229
|
setColumns(prevColumns =>
|
|
227
230
|
prevColumns.map(column =>
|
|
228
231
|
column.field === dataKey ? { ...column, colWidth: newWidth } : column
|
|
@@ -239,6 +242,14 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
239
242
|
);
|
|
240
243
|
}
|
|
241
244
|
}, [wordWrap]);
|
|
245
|
+
useEffect(() => {
|
|
246
|
+
if (!defaultRowView) {
|
|
247
|
+
setWordWrap('break-word');
|
|
248
|
+
} else {
|
|
249
|
+
setWordWrap(false);
|
|
250
|
+
}
|
|
251
|
+
REFRESH_KEY = REFRESH_KEY + 1;
|
|
252
|
+
}, [defaultRowView]);
|
|
242
253
|
|
|
243
254
|
const onReorder = useCallback((columns: QbsColumnProps[]) => {
|
|
244
255
|
setColumns(columns);
|
|
@@ -246,7 +257,6 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
246
257
|
|
|
247
258
|
// useEffect(() => {
|
|
248
259
|
// }, [columns]);
|
|
249
|
-
|
|
250
260
|
const handleClear = ([]) => {
|
|
251
261
|
setCheckedKeys([]);
|
|
252
262
|
handleChecked([]);
|
|
@@ -277,18 +287,31 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
277
287
|
setTableViewToggle: setTableViewToggle,
|
|
278
288
|
tableViewToggle: tableViewToggle,
|
|
279
289
|
enableTableToggle: enableTableToggle,
|
|
280
|
-
rowViewToggle,
|
|
281
|
-
defaultRowView,
|
|
282
|
-
fullWidthView,
|
|
283
|
-
setTableFullView,
|
|
284
|
-
setRowViewToggle,
|
|
285
|
-
isFullScreen,
|
|
290
|
+
rowViewToggle: rowViewToggle,
|
|
291
|
+
defaultRowView: defaultRowView,
|
|
292
|
+
fullWidthView: fullWidthView,
|
|
293
|
+
setTableFullView: setTableFullView,
|
|
294
|
+
setRowViewToggle: setRowViewToggle,
|
|
295
|
+
isFullScreen: isFullScreen,
|
|
286
296
|
labels,
|
|
287
297
|
rtl,
|
|
288
298
|
};
|
|
289
|
-
const themeToggle = useMemo(() => document.getElementById('themeToggle') as HTMLInputElement, []);
|
|
290
299
|
|
|
291
300
|
useEffect(() => {
|
|
301
|
+
if (!dataTheme || typeof document === 'undefined') return;
|
|
302
|
+
|
|
303
|
+
document.body.setAttribute('data-theme', dataTheme === 'dark' ? 'dark' : 'light');
|
|
304
|
+
document.documentElement.dataset.theme = dataTheme;
|
|
305
|
+
}, [dataTheme]);
|
|
306
|
+
|
|
307
|
+
const themeToggle = useMemo(
|
|
308
|
+
() => (typeof document !== 'undefined' ? document.getElementById('themeToggle') : null),
|
|
309
|
+
[]
|
|
310
|
+
) as HTMLInputElement | null;
|
|
311
|
+
|
|
312
|
+
useEffect(() => {
|
|
313
|
+
if (theme || typeof document === 'undefined') return;
|
|
314
|
+
|
|
292
315
|
const handleThemeToggle = () => {
|
|
293
316
|
if (themeToggle?.checked) {
|
|
294
317
|
document.body.setAttribute('data-theme', 'dark');
|
|
@@ -313,11 +336,10 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
313
336
|
themeToggle?.removeEventListener('change', handleThemeToggle);
|
|
314
337
|
document.removeEventListener('DOMContentLoaded', handleDOMContentLoaded);
|
|
315
338
|
};
|
|
316
|
-
}, [themeToggle]);
|
|
339
|
+
}, [theme, themeToggle]);
|
|
317
340
|
|
|
318
341
|
const handleExpanded = useCallback(
|
|
319
342
|
(rowData: any) => {
|
|
320
|
-
console.log(rowData);
|
|
321
343
|
const keyValue = dataRowKey as string;
|
|
322
344
|
const key = rowData[keyValue];
|
|
323
345
|
|
|
@@ -607,8 +629,25 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
607
629
|
[columns, dataTheme]
|
|
608
630
|
);
|
|
609
631
|
|
|
632
|
+
const handleInfiniteScroll = (scroll: number) => {
|
|
633
|
+
if (!infiniteScroll) return;
|
|
634
|
+
const wrapper = wheelWrapperRef.current;
|
|
635
|
+
if (!wrapper || !hasMoreData || infiniteLoading) return;
|
|
636
|
+
|
|
637
|
+
const { scrollTop, clientHeight } = wrapper;
|
|
638
|
+
const scrollHeight = Math.abs(scroll) + (height - headerHeight);
|
|
639
|
+
// Trigger fetch when user scrolls within 100px of bottom
|
|
640
|
+
if (scrollTop + clientHeight >= scrollHeight - 70) {
|
|
641
|
+
loadMoreData?.(); // fetch next page here
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
|
|
610
645
|
return (
|
|
611
|
-
<div
|
|
646
|
+
<div
|
|
647
|
+
className={`qbs-table ${classes.tableContainerClass}`}
|
|
648
|
+
data-theme={dataTheme}
|
|
649
|
+
dir={rtl ? 'rtl' : 'ltr'}
|
|
650
|
+
>
|
|
612
651
|
{toolbar && <ToolBar {...toolbarProps} />}
|
|
613
652
|
<div className="qbs-table-border-wrap">
|
|
614
653
|
{tableViewToggle ? (
|
|
@@ -616,16 +655,20 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
616
655
|
height={autoHeight ? undefined : height}
|
|
617
656
|
key={`${tableKey}-${rowViewRefreshKey}`}
|
|
618
657
|
tableKey={tableKey}
|
|
619
|
-
rtl={rtl}
|
|
620
658
|
data={data}
|
|
659
|
+
rtl={rtl}
|
|
621
660
|
tableBodyRef={tableBodyRef as React.RefObject<HTMLDivElement>}
|
|
622
661
|
dataTheme={dataTheme}
|
|
623
662
|
wordWrap={effectiveWordWrap}
|
|
663
|
+
wheelWrapperRef={wheelWrapperRef}
|
|
664
|
+
rowHeight={rowHeight}
|
|
624
665
|
autoHeight={autoHeight}
|
|
666
|
+
handleInfiniteScroll={handleInfiniteScroll}
|
|
625
667
|
sortColumn={sortColumn}
|
|
626
668
|
style={{ position: 'relative' }}
|
|
627
669
|
sortType={sortType}
|
|
628
670
|
onSortColumn={handleSortColumn}
|
|
671
|
+
infiniteLoading={infiniteLoading}
|
|
629
672
|
onRowClick={onRowClick}
|
|
630
673
|
tableBodyHeight={tableBodyHeight}
|
|
631
674
|
cellBordered={cellBordered}
|
|
@@ -634,13 +677,12 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
634
677
|
renderEmpty ? (
|
|
635
678
|
renderEmpty(info)
|
|
636
679
|
) : (
|
|
637
|
-
<NoData title={emptyTitle ??
|
|
680
|
+
<NoData title={emptyTitle ?? labels.noDataFound} subtitle={emptySubTitle} />
|
|
638
681
|
)
|
|
639
682
|
}
|
|
640
683
|
columns={columns}
|
|
641
684
|
minHeight={minHeight}
|
|
642
685
|
headerHeight={headerHeight}
|
|
643
|
-
rowHeight={rowHeight}
|
|
644
686
|
rowExpandedHeight={rowExpandedHeight}
|
|
645
687
|
loading={isLoading ?? loading}
|
|
646
688
|
showHeader={showHeader}
|
|
@@ -648,7 +690,6 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
648
690
|
expandedRowKeys={expandedRowKeys}
|
|
649
691
|
onExpandChange={onExpandChange}
|
|
650
692
|
rowKey={dataRowKey ?? 'id'}
|
|
651
|
-
rowClassName={selection ? getRowClassName : undefined}
|
|
652
693
|
defaultExpandAllRows={defaultExpandAllRows}
|
|
653
694
|
shouldUpdateScroll={shouldUpdateScroll}
|
|
654
695
|
renderRowExpanded={rowData => {
|
|
@@ -790,11 +831,12 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
790
831
|
</HeaderCell>
|
|
791
832
|
<ActionCell
|
|
792
833
|
tableBodyRef={tableBodyRef}
|
|
834
|
+
dropType={dropType}
|
|
835
|
+
wheelWrapperRef={wheelWrapperRef}
|
|
793
836
|
actionProps={actionProps}
|
|
794
837
|
className={`${classes.cellClass} ${classes.actionCellClass}`}
|
|
795
838
|
handleMenuActions={handleMenuActions}
|
|
796
839
|
dataTheme={dataTheme}
|
|
797
|
-
dropType={dropType}
|
|
798
840
|
/>
|
|
799
841
|
</Column>
|
|
800
842
|
)}
|
|
@@ -816,7 +858,7 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
816
858
|
>
|
|
817
859
|
{(data?.length === 0 || !data) && !isLoading && (
|
|
818
860
|
<div className="flex flex-col gap-2 p-2 mt-6 card-empty-container">
|
|
819
|
-
<NoData title={emptyTitle ??
|
|
861
|
+
<NoData title={emptyTitle ?? labels.noDataFound} subtitle={emptySubTitle} />
|
|
820
862
|
</div>
|
|
821
863
|
)}
|
|
822
864
|
{isLoading ? (
|
|
@@ -843,6 +885,7 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
843
885
|
columns={columns}
|
|
844
886
|
tableBodyRef={tableBodyRef}
|
|
845
887
|
actionProps={actionProps}
|
|
888
|
+
labels={labels}
|
|
846
889
|
/>
|
|
847
890
|
)}
|
|
848
891
|
</div>
|
|
@@ -851,7 +894,9 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
851
894
|
</div>
|
|
852
895
|
)}
|
|
853
896
|
<div>
|
|
854
|
-
{pagination && data?.length > 0 &&
|
|
897
|
+
{pagination && data?.length > 0 && (
|
|
898
|
+
<Pagination paginationProps={paginationProps} labels={labels} dataTheme={dataTheme} />
|
|
899
|
+
)}
|
|
855
900
|
</div>
|
|
856
901
|
</div>
|
|
857
902
|
</div>
|
|
@@ -106,6 +106,7 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
106
106
|
const [isOpen, setIsOpen] = useState(false);
|
|
107
107
|
const prevColumns = useRef<any | null>(null);
|
|
108
108
|
const tableBodyRef = useRef<HTMLDivElement>(null);
|
|
109
|
+
const wheelWrapperRef = useRef<HTMLDivElement>(null);
|
|
109
110
|
const handleSortColumn = useCallback(
|
|
110
111
|
(sortColumn: any, sortType: any) => {
|
|
111
112
|
setLoading(true);
|
|
@@ -481,6 +482,7 @@ const QbsTable: React.FC<QbsTableProps> = ({
|
|
|
481
482
|
rtl={rtl}
|
|
482
483
|
data={data}
|
|
483
484
|
tableBodyRef={tableBodyRef as React.RefObject<HTMLDivElement>}
|
|
485
|
+
wheelWrapperRef={wheelWrapperRef}
|
|
484
486
|
dataTheme={dataTheme}
|
|
485
487
|
wordWrap={effectiveWordWrap}
|
|
486
488
|
autoHeight={autoHeight}
|
package/src/qbsTable/Toolbar.tsx
CHANGED
|
@@ -230,11 +230,12 @@ const ToolBar: React.FC<QbsTableToolbarProps> = ({
|
|
|
230
230
|
{handleHide(actions) && (
|
|
231
231
|
<button
|
|
232
232
|
type="button"
|
|
233
|
-
className=
|
|
233
|
+
className={`btn ${actions?.buttonClassName ?? ''}`}
|
|
234
234
|
disabled={actions.disabled}
|
|
235
235
|
onClick={() => actions?.action(checkedKeys)}
|
|
236
236
|
>
|
|
237
|
-
{actions.
|
|
237
|
+
{actions?.icon && <span className="mr-2">{actions.icon}</span>}
|
|
238
|
+
<span>{actions.actionTitle}</span>
|
|
238
239
|
</button>
|
|
239
240
|
)}
|
|
240
241
|
</React.Fragment>
|
|
@@ -249,6 +250,7 @@ const ToolBar: React.FC<QbsTableToolbarProps> = ({
|
|
|
249
250
|
paginationProps.total ?? 0,
|
|
250
251
|
paginationProps.rowsPerPage ?? 0,
|
|
251
252
|
paginationProps.currentPage ?? 0,
|
|
253
|
+
labels.showingRange,
|
|
252
254
|
)}
|
|
253
255
|
</div>
|
|
254
256
|
)}
|
|
@@ -45,7 +45,7 @@ export interface PaginationProps {
|
|
|
45
45
|
export interface ActionProps {
|
|
46
46
|
title?: string;
|
|
47
47
|
action?: (row: any) => void;
|
|
48
|
-
icon
|
|
48
|
+
icon?: React.ReactNode;
|
|
49
49
|
toolTip?: string;
|
|
50
50
|
hidden?: boolean;
|
|
51
51
|
hide?: (data: any, index?: number) => boolean;
|
|
@@ -76,6 +76,7 @@ export interface QbsTableProps {
|
|
|
76
76
|
searchValue?: string;
|
|
77
77
|
handleSearchValue?: (value?: string) => void;
|
|
78
78
|
theme?: string;
|
|
79
|
+
rtl?: boolean;
|
|
79
80
|
onRowClick?: (data: any) => void;
|
|
80
81
|
cellBordered?: boolean;
|
|
81
82
|
bordered?: boolean;
|
|
@@ -89,9 +90,8 @@ export interface QbsTableProps {
|
|
|
89
90
|
expandedRowKeys?: readonly number[];
|
|
90
91
|
setExpandedRowKeys?: (value: readonly number[]) => void;
|
|
91
92
|
handleMenuActions?: (actions: ActionProps, rowData: any) => void;
|
|
92
|
-
dropType?: 'vertical' | string;
|
|
93
|
+
dropType?: 'horizondal' | 'vertical' | string;
|
|
93
94
|
labels?: QbsTableLabels;
|
|
94
|
-
rtl?: boolean;
|
|
95
95
|
handleRowExpanded?: (rowData: any) => React.ReactNode;
|
|
96
96
|
shouldUpdateScroll?: boolean;
|
|
97
97
|
rowExpand?: boolean;
|
|
@@ -105,6 +105,8 @@ export interface QbsTableProps {
|
|
|
105
105
|
disabled?: boolean;
|
|
106
106
|
hidden?: boolean;
|
|
107
107
|
customHide?: string;
|
|
108
|
+
buttonClassName?: string;
|
|
109
|
+
icon?: ReactElement | ReactNode;
|
|
108
110
|
}[];
|
|
109
111
|
selectedRows?: (number | string)[];
|
|
110
112
|
classes?: { [key: string]: any };
|
|
@@ -135,13 +137,18 @@ export interface QbsTableProps {
|
|
|
135
137
|
handleTableCardView?: (data: any) => React.ReactNode;
|
|
136
138
|
isCustomTableCardView?: boolean;
|
|
137
139
|
handleCustomCardLoader?: () => React.ReactNode;
|
|
140
|
+
hasMoreData?: boolean;
|
|
141
|
+
loadMoreData?: () => void;
|
|
142
|
+
infiniteScroll?: boolean;
|
|
143
|
+
infiniteLoading?: boolean;
|
|
144
|
+
viewMode?: string;
|
|
138
145
|
rowViewToggle?: boolean;
|
|
139
146
|
defaultRowView?: boolean;
|
|
140
147
|
fullWidthView?: boolean;
|
|
141
148
|
setTableFullView?: (value: boolean) => void;
|
|
142
149
|
setRowViewToggle?: (value: boolean) => void;
|
|
143
|
-
isFullScreen?: boolean;
|
|
144
150
|
rowHeight?: number;
|
|
151
|
+
isFullScreen?: boolean;
|
|
145
152
|
showHeader?: boolean;
|
|
146
153
|
}
|
|
147
154
|
|
|
@@ -168,23 +175,25 @@ export interface QbsTableToolbarProps {
|
|
|
168
175
|
dataLength: number;
|
|
169
176
|
headerHeight?: number;
|
|
170
177
|
searchPlaceholder?: string;
|
|
178
|
+
labels?: QbsTableLabels;
|
|
179
|
+
rtl?: boolean;
|
|
171
180
|
tableView?: boolean;
|
|
172
181
|
enableTableToggle?: boolean;
|
|
173
182
|
tableViewToggle?: boolean;
|
|
174
183
|
setTableViewToggle?: (value: boolean) => void;
|
|
175
|
-
rowViewToggle?: boolean;
|
|
176
|
-
defaultRowView?: boolean;
|
|
177
|
-
fullWidthView?: boolean;
|
|
178
|
-
setTableFullView?: (value: boolean) => void;
|
|
179
|
-
setRowViewToggle?: (value: boolean) => void;
|
|
180
|
-
isFullScreen?: boolean;
|
|
181
|
-
labels?: QbsTableLabels;
|
|
182
|
-
rtl?: boolean;
|
|
183
184
|
selectedRowActions?: {
|
|
184
185
|
actionTitle?: string;
|
|
185
186
|
action: (checked: (number | string)[]) => void;
|
|
186
187
|
disabled?: boolean;
|
|
187
188
|
hidden?: boolean;
|
|
188
189
|
customHide?: string;
|
|
190
|
+
buttonClassName?: string;
|
|
191
|
+
icon?: ReactElement | ReactNode;
|
|
189
192
|
}[];
|
|
193
|
+
rowViewToggle?: boolean;
|
|
194
|
+
defaultRowView?: boolean;
|
|
195
|
+
fullWidthView?: boolean;
|
|
196
|
+
setTableFullView?: (value: boolean) => void;
|
|
197
|
+
setRowViewToggle?: (value: boolean) => void;
|
|
198
|
+
isFullScreen?: boolean;
|
|
190
199
|
}
|
package/src/qbsTable/labels.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface QbsTableLabels {
|
|
2
2
|
search?: string;
|
|
3
3
|
searchAriaLabel?: string;
|
|
4
4
|
clear?: string;
|
|
@@ -19,7 +19,7 @@ export type QbsTableLabels = {
|
|
|
19
19
|
viewMore?: string;
|
|
20
20
|
viewLess?: string;
|
|
21
21
|
actions?: string;
|
|
22
|
-
}
|
|
22
|
+
}
|
|
23
23
|
|
|
24
24
|
export const defaultQbsTableLabels: QbsTableLabels = {
|
|
25
25
|
search: 'Search',
|
|
@@ -44,11 +44,18 @@ export const defaultQbsTableLabels: QbsTableLabels = {
|
|
|
44
44
|
actions: 'Actions',
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
+
/** @deprecated Use defaultQbsTableLabels */
|
|
48
|
+
export const DEFAULT_QBS_TABLE_LABELS = defaultQbsTableLabels;
|
|
49
|
+
|
|
47
50
|
export const mergeQbsTableLabels = (overrides?: QbsTableLabels): QbsTableLabels => ({
|
|
48
51
|
...defaultQbsTableLabels,
|
|
49
52
|
...overrides,
|
|
53
|
+
showingRange: overrides?.showingRange ?? defaultQbsTableLabels.showingRange,
|
|
50
54
|
});
|
|
51
55
|
|
|
56
|
+
/** @deprecated Use mergeQbsTableLabels */
|
|
57
|
+
export const mergeLabels = mergeQbsTableLabels;
|
|
58
|
+
|
|
52
59
|
export const formatSelectedItems = (count: number, labels?: QbsTableLabels): string => {
|
|
53
60
|
const merged = mergeQbsTableLabels(labels);
|
|
54
61
|
return `${merged.selectedItems} (${count})`;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useRef, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import { QbsColumnProps } from '../commontypes';
|
|
4
|
+
import { mergeLabels, type QbsTableLabels } from '../labels';
|
|
4
5
|
import CardMenuDropdown from './CardMenuDropdown';
|
|
5
6
|
import { handleCellFormat } from './handleFormatCell';
|
|
6
7
|
import { ArrowUpIcon } from './icons';
|
|
@@ -17,6 +18,7 @@ type Props = {
|
|
|
17
18
|
handleMenuActions?: () => void;
|
|
18
19
|
cardColumLimit?: number;
|
|
19
20
|
childDetailHeading?: string;
|
|
21
|
+
labels?: QbsTableLabels;
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
const CardComponent: React.FC<Props> = ({
|
|
@@ -27,8 +29,10 @@ const CardComponent: React.FC<Props> = ({
|
|
|
27
29
|
index,
|
|
28
30
|
cardColumLimit = 5,
|
|
29
31
|
handleMenuActions,
|
|
30
|
-
childDetailHeading = ''
|
|
32
|
+
childDetailHeading = '',
|
|
33
|
+
labels: labelsProp
|
|
31
34
|
}) => {
|
|
35
|
+
const labels = mergeLabels(labelsProp);
|
|
32
36
|
const [viewMore, setViewMore] = useState(false);
|
|
33
37
|
const initialDisplayCount = cardColumLimit;
|
|
34
38
|
|
|
@@ -102,13 +106,14 @@ const CardComponent: React.FC<Props> = ({
|
|
|
102
106
|
iconName="more"
|
|
103
107
|
rowIndex={index}
|
|
104
108
|
handleMenuActions={handleMenuActions}
|
|
109
|
+
labels={labels}
|
|
105
110
|
/>
|
|
106
111
|
</div>
|
|
107
112
|
|
|
108
113
|
{columns.length > initialDisplayCount && (
|
|
109
114
|
<TooltipComponent
|
|
110
115
|
tableBodyRef={useCardRef}
|
|
111
|
-
title={viewMore ?
|
|
116
|
+
title={viewMore ? labels.viewLess : labels.viewMore}
|
|
112
117
|
enabled={false}
|
|
113
118
|
>
|
|
114
119
|
<button
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
4
2
|
import { ActionProps } from '../commontypes';
|
|
3
|
+
import { mergeLabels, type QbsTableLabels } from '../labels';
|
|
5
4
|
import { ThreeDotIcon } from './icons';
|
|
6
5
|
import TooltipComponent from './ToolTip';
|
|
7
6
|
|
|
@@ -13,9 +12,16 @@ type Props = {
|
|
|
13
12
|
dataTheme?: string;
|
|
14
13
|
tableBodyRef: React.RefObject<HTMLDivElement>;
|
|
15
14
|
rowIndex?: number;
|
|
15
|
+
labels?: QbsTableLabels;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
const CardMenuDropdown: React.FC<Props> = ({
|
|
18
|
+
const CardMenuDropdown: React.FC<Props> = ({
|
|
19
|
+
actionDropDown,
|
|
20
|
+
handleMenuActions,
|
|
21
|
+
rowData,
|
|
22
|
+
labels: labelsProp
|
|
23
|
+
}) => {
|
|
24
|
+
const labels = mergeLabels(labelsProp);
|
|
19
25
|
const [openMenu, setOpenMenu] = useState(false);
|
|
20
26
|
const [menuPositionStyles, setMenuPositionStyles] = useState<{
|
|
21
27
|
top?: string;
|
|
@@ -46,7 +52,6 @@ const CardMenuDropdown: React.FC<Props> = ({ actionDropDown, handleMenuActions,
|
|
|
46
52
|
const dropdownHeight = 200; // Adjust this if your dropdown height varies
|
|
47
53
|
const spaceBelow = window.innerHeight - buttonRect.bottom;
|
|
48
54
|
const spaceAbove = buttonRect.top;
|
|
49
|
-
console.log(spaceAbove, spaceBelow, dropdownHeight);
|
|
50
55
|
if (spaceBelow < dropdownHeight && spaceAbove > spaceBelow) {
|
|
51
56
|
setMenuPositionStyles({
|
|
52
57
|
bottom: '30px',
|
|
@@ -76,7 +81,7 @@ const CardMenuDropdown: React.FC<Props> = ({ actionDropDown, handleMenuActions,
|
|
|
76
81
|
return (
|
|
77
82
|
<div className="dropdown text-black dark:text-white dark:bg-[#424242] bg-white" ref={menuRef}>
|
|
78
83
|
<button className="dropdown-toggle" onClick={toggleMenu} ref={menuButtonRef}>
|
|
79
|
-
<TooltipComponent title=
|
|
84
|
+
<TooltipComponent title={labels.actions} enabled={false}>
|
|
80
85
|
<ThreeDotIcon />
|
|
81
86
|
</TooltipComponent>
|
|
82
87
|
</button>
|
|
@@ -2,12 +2,14 @@ import React, { memo, useCallback } from 'react';
|
|
|
2
2
|
|
|
3
3
|
export interface SearchProps {
|
|
4
4
|
placeholder: string;
|
|
5
|
+
searchAriaLabel?: string;
|
|
5
6
|
handleChange: (value: string) => void;
|
|
6
7
|
searchValue: string | undefined;
|
|
7
8
|
handleSearch: (value?: string) => void;
|
|
8
9
|
}
|
|
9
10
|
const SearchInput: React.FC<SearchProps> = ({
|
|
10
11
|
placeholder,
|
|
12
|
+
searchAriaLabel = 'Search',
|
|
11
13
|
handleChange,
|
|
12
14
|
searchValue,
|
|
13
15
|
handleSearch
|
|
@@ -37,7 +39,7 @@ const SearchInput: React.FC<SearchProps> = ({
|
|
|
37
39
|
placeholder={placeholder}
|
|
38
40
|
value={searchValue ?? ''}
|
|
39
41
|
onChange={handleInputChange}
|
|
40
|
-
aria-label=
|
|
42
|
+
aria-label={searchAriaLabel}
|
|
41
43
|
/>
|
|
42
44
|
<button
|
|
43
45
|
className="search-button absolute left-1 bottom-1.5 bg-white text-grey-dark"
|
|
@@ -18,7 +18,7 @@ const NoData: React.FC<props> = ({ title, subtitle }) => {
|
|
|
18
18
|
}}
|
|
19
19
|
>
|
|
20
20
|
<div style={{ width: 145, marginBottom: 20 }} className="nodata-img">
|
|
21
|
-
|
|
21
|
+
<svg
|
|
22
22
|
xmlns="http://www.w3.org/2000/svg"
|
|
23
23
|
width="148"
|
|
24
24
|
height="132"
|
|
@@ -71,7 +71,7 @@ const NoData: React.FC<props> = ({ title, subtitle }) => {
|
|
|
71
71
|
fill="#797979"
|
|
72
72
|
d="M47.365 57.417a.926.926 0 00.926-.927v-1.777a.926.926 0 10-1.852 0v1.777c0 .512.415.927.926.927zM104.183 57.417a.926.926 0 00.926-.927v-1.777a.926.926 0 00-1.852 0v1.777c0 .512.414.927.926.927zM47.365 52.974a.926.926 0 00.926-.927V50.27a.926.926 0 00-1.852 0v1.777c0 .512.415.927.926.927zM104.183 52.974a.926.926 0 00.926-.927V50.27a.926.926 0 00-1.852 0v1.777c0 .512.414.927.926.927zM47.365 44.088a.926.926 0 00.926-.927v-1.777a.926.926 0 10-1.852 0v1.777c0 .512.415.927.926.927zM104.183 44.088a.926.926 0 00.926-.927v-1.777a.926.926 0 00-1.852 0v1.777c0 .512.414.927.926.927zM47.365 39.645a.926.926 0 00.926-.927v-1.777a.926.926 0 10-1.852 0v1.777c0 .512.415.927.926.927zM104.183 39.645a.926.926 0 00.926-.927v-1.777a.926.926 0 00-1.852 0v1.777c0 .512.414.927.926.927zM47.365 35.202a.926.926 0 00.926-.927v-1.777a.926.926 0 10-1.852 0v1.777c0 .512.415.927.926.927zM104.183 35.202a.926.926 0 00.926-.927v-1.777a.926.926 0 00-1.852 0v1.777c0 .512.414.927.926.927zM47.365 30.758a.926.926 0 00.926-.926v-.888c0-.248.02-.49.057-.726a.926.926 0 00-1.83-.288c-.052.33-.08.67-.08 1.014v.888c0 .512.416.926.927.926zM104.183 30.758a.926.926 0 00.926-.926v-.888c0-.345-.027-.683-.079-1.014a.926.926 0 10-1.83.288c.037.236.057.478.057.726v.888c0 .512.414.926.926.926zM47.881 26.426a.926.926 0 001.294-.204c.286-.394.633-.74 1.026-1.026a.926.926 0 00-1.09-1.498c-.55.4-1.034.884-1.434 1.434a.926.926 0 00.204 1.294zM103.667 26.426a.926.926 0 00.204-1.294 6.509 6.509 0 00-1.434-1.434.926.926 0 00-1.09 1.498c.393.286.74.632 1.026 1.026a.926.926 0 001.294.204zM51.138 23.597c.08.506.554.851 1.059.772a4.67 4.67 0 01.726-.057h.914a.926.926 0 000-1.852h-.914c-.344 0-.683.026-1.014.078a.926.926 0 00-.77 1.06zM100.41 23.597a.927.927 0 00-.771-1.059 6.522 6.522 0 00-1.014-.078h-.914a.926.926 0 100 1.852h.914c.248 0 .49.02.726.057a.926.926 0 001.059-.772zM55.653 23.386c0 .511.415.926.926.926h1.828a.926.926 0 000-1.852H56.58a.926.926 0 00-.926.926zM60.223 23.386c0 .511.415.926.926.926h1.828a.926.926 0 000-1.852H61.15a.926.926 0 00-.926.926zM64.793 23.386c0 .511.415.926.926.926h1.829a.926.926 0 000-1.852h-1.829a.926.926 0 00-.926.926zM69.364 23.386c0 .511.414.926.926.926h1.828a.926.926 0 000-1.852H70.29a.926.926 0 00-.927.926zM73.934 23.386c0 .511.414.926.926.926h1.828a.926.926 0 000-1.852H74.86a.926.926 0 00-.926.926zM78.504 23.386c0 .511.415.926.926.926h1.828a.926.926 0 000-1.852H79.43a.926.926 0 00-.926.926zM83.074 23.386c0 .511.415.926.927.926h1.828a.926.926 0 000-1.852H84a.926.926 0 00-.927.926zM87.644 23.386c0 .511.415.926.927.926h1.828a.926.926 0 000-1.852H88.57a.926.926 0 00-.927.926zM92.215 23.386c0 .511.414.926.926.926h1.828a.926.926 0 000-1.852h-1.828a.926.926 0 00-.926.926zM72.178 36.453a1.39 1.39 0 10-1.965 1.965l3.797 3.797-3.797 3.798a1.39 1.39 0 001.965 1.965l3.797-3.798 3.798 3.798a1.39 1.39 0 001.965-1.965l-3.798-3.798 3.798-3.797a1.39 1.39 0 10-1.965-1.965l-3.798 3.797-3.797-3.797z"
|
|
73
73
|
></path>
|
|
74
|
-
</svg>
|
|
74
|
+
</svg>{' '}
|
|
75
75
|
</div>
|
|
76
76
|
<p className="text-center text-common font-bold text-blackAlt nodata-title">{title}</p>
|
|
77
77
|
<span className="text-xxs font-medium text-grey-medium nodata-sub-title">{subtitle}</span>
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
export function getRowDisplayRange(
|
|
1
|
+
export function getRowDisplayRange(
|
|
2
|
+
totalRows: number,
|
|
3
|
+
rowsPerPage: number,
|
|
4
|
+
pageNumber: number,
|
|
5
|
+
formatRange: (start: number, end: number, total: number) => string = (start, end, total) =>
|
|
6
|
+
`Showing ${start} to ${end} of ${total}`
|
|
7
|
+
) {
|
|
2
8
|
const start = (pageNumber - 1) * rowsPerPage + 1;
|
|
3
9
|
const end = Math.min(pageNumber * rowsPerPage, totalRows);
|
|
4
10
|
|
|
5
|
-
return
|
|
11
|
+
return formatRange(start ?? 0, end ?? 0, totalRows ?? 0);
|
|
6
12
|
}
|
|
@@ -205,7 +205,6 @@ const useCellDescriptor = <Row extends RowDataType>(
|
|
|
205
205
|
if (treeCol) {
|
|
206
206
|
hasCustomTreeCol = true;
|
|
207
207
|
}
|
|
208
|
-
console.log(columns);
|
|
209
208
|
|
|
210
209
|
if (columnChildren?.length !== 2) {
|
|
211
210
|
throw new Error(`Component <HeaderCell> and <Cell> is required, column index: ${index} `);
|
|
@@ -4,6 +4,7 @@ import scrollLeft from 'dom-lib/scrollLeft';
|
|
|
4
4
|
import scrollTop from 'dom-lib/scrollTop';
|
|
5
5
|
import WheelHandler from 'dom-lib/WheelHandler';
|
|
6
6
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
7
|
+
|
|
7
8
|
import type { ListenerCallback, RowDataType } from '../@types/common';
|
|
8
9
|
import { BEZIER, SCROLLBAR_WIDTH, TRANSITION_DURATION } from '../constants';
|
|
9
10
|
import type { ScrollbarInstance } from '../Scrollbar';
|
|
@@ -50,6 +51,7 @@ interface ScrollListenerProps {
|
|
|
50
51
|
onTouchStart?: (event: React.TouchEvent) => void;
|
|
51
52
|
onTouchMove?: (event: React.TouchEvent) => void;
|
|
52
53
|
onTouchEnd?: (event: React.TouchEvent) => void;
|
|
54
|
+
handleInfiniteScroll?: (value: number) => void;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
/**
|
|
@@ -106,7 +108,8 @@ const useScrollListener = (props: ScrollListenerProps) => {
|
|
|
106
108
|
contentHeight,
|
|
107
109
|
headerHeight,
|
|
108
110
|
rtl,
|
|
109
|
-
tableKey
|
|
111
|
+
tableKey,
|
|
112
|
+
handleInfiniteScroll
|
|
110
113
|
} = props;
|
|
111
114
|
|
|
112
115
|
const wheelListener = useRef<ListenerCallback>(null);
|
|
@@ -187,6 +190,15 @@ const useScrollListener = (props: ScrollListenerProps) => {
|
|
|
187
190
|
setScrollX(x);
|
|
188
191
|
setScrollY(y);
|
|
189
192
|
|
|
193
|
+
if (
|
|
194
|
+
typeof handleInfiniteScroll === 'function' &&
|
|
195
|
+
deltaY !== 0 &&
|
|
196
|
+
!loading &&
|
|
197
|
+
Math.abs(y) + getTableHeight() >= contentHeight.current - 12
|
|
198
|
+
) {
|
|
199
|
+
handleInfiniteScroll(scrollY.current);
|
|
200
|
+
}
|
|
201
|
+
|
|
190
202
|
onScroll?.(Math.abs(x), Math.abs(y));
|
|
191
203
|
|
|
192
204
|
if (virtualized) {
|
|
@@ -297,7 +309,6 @@ const useScrollListener = (props: ScrollListenerProps) => {
|
|
|
297
309
|
if (!isTouching.current) {
|
|
298
310
|
return;
|
|
299
311
|
}
|
|
300
|
-
console.log('handleTouchMove');
|
|
301
312
|
|
|
302
313
|
const { pageX, pageY } = event.touches[0];
|
|
303
314
|
const deltaX = touchX.current - pageX;
|
|
@@ -338,7 +349,6 @@ const useScrollListener = (props: ScrollListenerProps) => {
|
|
|
338
349
|
if (!isTouching.current) {
|
|
339
350
|
return;
|
|
340
351
|
}
|
|
341
|
-
console.log('handleTouchEnd');
|
|
342
352
|
isTouching.current = false;
|
|
343
353
|
const touchDuration = new Date().getTime() - momentumStartTime.current;
|
|
344
354
|
const absDeltaY = Math.abs(scrollY.current - momentumStartY.current);
|