qbs-react-grid 2.2.17 → 2.2.19

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.
Files changed (79) hide show
  1. package/dist/css/qbs-react-grid.css +1 -1
  2. package/dist/css/qbs-react-grid.min.css +1 -1
  3. package/dist/css/qbs-react-grid.min.css.map +1 -1
  4. package/es/Cell.js +2 -1
  5. package/es/Pagination.d.ts +3 -0
  6. package/es/Pagination.js +8 -3
  7. package/es/Table.d.ts +3 -0
  8. package/es/Table.js +18 -12
  9. package/es/index.d.ts +1 -1
  10. package/es/index.js +1 -1
  11. package/es/less/pagination.less +9 -9
  12. package/es/qbsTable/QbsTable.js +110 -73
  13. package/es/qbsTable/TableCardList.js +2 -0
  14. package/es/qbsTable/Toolbar.js +6 -3
  15. package/es/qbsTable/commontypes.d.ts +21 -12
  16. package/es/qbsTable/labels.d.ts +6 -2
  17. package/es/qbsTable/labels.js +10 -1
  18. package/es/qbsTable/utilities/CardComponent.d.ts +2 -0
  19. package/es/qbsTable/utilities/CardComponent.js +7 -3
  20. package/es/qbsTable/utilities/CardMenuDropdown.d.ts +2 -0
  21. package/es/qbsTable/utilities/CardMenuDropdown.js +7 -7
  22. package/es/qbsTable/utilities/SearchInput.d.ts +1 -0
  23. package/es/qbsTable/utilities/SearchInput.js +3 -1
  24. package/es/qbsTable/utilities/VerticalDropDownMenu.js +36 -23
  25. package/es/qbsTable/utilities/empty.js +1 -1
  26. package/es/qbsTable/utilities/tablecalc.d.ts +1 -1
  27. package/es/qbsTable/utilities/tablecalc.js +7 -2
  28. package/es/utils/useCellDescriptor.js +0 -1
  29. package/es/utils/useScrollListener.d.ts +1 -0
  30. package/es/utils/useScrollListener.js +5 -3
  31. package/lib/Cell.js +2 -1
  32. package/lib/Pagination.d.ts +3 -0
  33. package/lib/Pagination.js +8 -3
  34. package/lib/Table.d.ts +3 -0
  35. package/lib/Table.js +18 -12
  36. package/lib/index.d.ts +1 -1
  37. package/lib/index.js +3 -1
  38. package/lib/less/pagination.less +9 -9
  39. package/lib/qbsTable/QbsTable.js +110 -73
  40. package/lib/qbsTable/TableCardList.js +2 -0
  41. package/lib/qbsTable/Toolbar.js +6 -3
  42. package/lib/qbsTable/commontypes.d.ts +21 -12
  43. package/lib/qbsTable/labels.d.ts +6 -2
  44. package/lib/qbsTable/labels.js +13 -2
  45. package/lib/qbsTable/utilities/CardComponent.d.ts +2 -0
  46. package/lib/qbsTable/utilities/CardComponent.js +7 -3
  47. package/lib/qbsTable/utilities/CardMenuDropdown.d.ts +2 -0
  48. package/lib/qbsTable/utilities/CardMenuDropdown.js +6 -5
  49. package/lib/qbsTable/utilities/SearchInput.d.ts +1 -0
  50. package/lib/qbsTable/utilities/SearchInput.js +3 -1
  51. package/lib/qbsTable/utilities/VerticalDropDownMenu.js +36 -23
  52. package/lib/qbsTable/utilities/empty.js +1 -1
  53. package/lib/qbsTable/utilities/tablecalc.d.ts +1 -1
  54. package/lib/qbsTable/utilities/tablecalc.js +7 -2
  55. package/lib/utils/useCellDescriptor.js +0 -1
  56. package/lib/utils/useScrollListener.d.ts +1 -0
  57. package/lib/utils/useScrollListener.js +5 -3
  58. package/package.json +2 -2
  59. package/src/Cell.tsx +3 -1
  60. package/src/HeaderCell.tsx +0 -1
  61. package/src/Pagination.tsx +10 -3
  62. package/src/Table.tsx +23 -10
  63. package/src/customSelect.tsx +88 -88
  64. package/src/index.ts +2 -0
  65. package/src/less/pagination.less +9 -9
  66. package/src/qbsTable/QbsTable.tsx +84 -39
  67. package/src/qbsTable/TableCardList.tsx +2 -0
  68. package/src/qbsTable/Toolbar.tsx +4 -2
  69. package/src/qbsTable/commontypes.ts +21 -12
  70. package/src/qbsTable/labels.ts +9 -2
  71. package/src/qbsTable/utilities/CardComponent.tsx +7 -2
  72. package/src/qbsTable/utilities/CardMenuDropdown.tsx +11 -6
  73. package/src/qbsTable/utilities/SearchInput.tsx +3 -1
  74. package/src/qbsTable/utilities/VerticalDropDownMenu.tsx +42 -30
  75. package/src/qbsTable/utilities/empty.tsx +2 -2
  76. package/src/qbsTable/utilities/tablecalc.ts +8 -2
  77. package/src/utils/useCellDescriptor.ts +0 -1
  78. package/src/utils/useScrollListener.ts +13 -3
  79. package/src/utils/useTableRows.ts +1 -1
package/src/Table.tsx CHANGED
@@ -224,6 +224,7 @@ export interface TableProps<Row, Key> extends Omit<StandardProps, 'onScroll'> {
224
224
  expanded?: boolean
225
225
  ) => React.ReactNode;
226
226
  tableKey?: string;
227
+ infiniteLoading?: boolean;
227
228
  /** Customize what you can do to expand a zone */
228
229
  renderRowExpanded?: (rowData?: Row) => React.ReactNode;
229
230
 
@@ -259,13 +260,16 @@ export interface TableProps<Row, Key> extends Omit<StandardProps, 'onScroll'> {
259
260
 
260
261
  /** Callback for the `touchend` event. */
261
262
  onTouchEnd?: (event: React.TouchEvent) => void;
262
-
263
+ handleInfiniteScroll?: (value: number) => void;
263
264
  /**
264
265
  * Callback after table data update.
265
266
  * @deprecated use `shouldUpdateScroll` instead
266
267
  **/
267
268
  onDataUpdated?: (nextData: Row[], scrollTo: (coord: { x: number; y: number }) => void) => void;
268
269
  tableBodyRef: React.RefObject<HTMLDivElement>;
270
+
271
+ wheelWrapperRef: React.RefObject<HTMLDivElement | null>;
272
+
269
273
  bodyRef?: (ref: HTMLElement) => void;
270
274
  }
271
275
 
@@ -302,8 +306,7 @@ const Table = React.forwardRef(<Row extends RowDataType, Key>(props: TableProps<
302
306
  loading: 'Loading...'
303
307
  },
304
308
  showHeader = true,
305
- pagination = true,
306
- paginationProps = {},
309
+
307
310
  sortColumn,
308
311
  rowHeight = ROW_HEIGHT,
309
312
  sortType: sortTypeProp,
@@ -335,21 +338,21 @@ const Table = React.forwardRef(<Row extends RowDataType, Key>(props: TableProps<
335
338
  onTouchStart,
336
339
  onTouchMove,
337
340
  onTouchEnd,
338
- dataTheme,
339
341
  tableBodyHeight,
340
342
  columns,
341
343
  tableBodyRef,
342
344
  tableKey,
345
+ handleInfiniteScroll,
346
+ infiniteLoading,
347
+ wheelWrapperRef,
343
348
  ...rest
344
349
  } = props;
345
-
346
350
  const {
347
351
  withClassPrefix,
348
352
  merge: mergeCls,
349
353
  prefix
350
354
  } = useClassNames(classPrefix, typeof classPrefix !== 'undefined');
351
355
  const childTableRef = useRef<HTMLDivElement>(null);
352
-
353
356
  // Use `forceUpdate` to force the component to re-render after manipulating the DOM.
354
357
  const [, forceUpdate] = useReducer(x => x + 1, 0);
355
358
  const [expandedRowKeys, setExpandedRowKeys] = useControlled(
@@ -408,7 +411,6 @@ const Table = React.forwardRef(<Row extends RowDataType, Key>(props: TableProps<
408
411
  const affixHeaderWrapperRef = useRef<HTMLDivElement>(null);
409
412
  const headerWrapperRef = useRef<HTMLDivElement>(null);
410
413
  // const tableBodyRef = useRef<HTMLDivElement>(null);
411
- const wheelWrapperRef = useRef<HTMLDivElement>(null);
412
414
  const scrollbarXRef = useRef<ScrollbarInstance>(null);
413
415
  const scrollbarYRef = useRef<ScrollbarInstance>(null);
414
416
 
@@ -533,7 +535,8 @@ const Table = React.forwardRef(<Row extends RowDataType, Key>(props: TableProps<
533
535
  onScroll,
534
536
  onTouchStart,
535
537
  onTouchMove,
536
- onTouchEnd
538
+ onTouchEnd,
539
+ handleInfiniteScroll
537
540
  });
538
541
 
539
542
  const { headerCells, bodyCells, allColumnsWidth, hasCustomTreeCol } = useCellDescriptor({
@@ -953,7 +956,9 @@ const Table = React.forwardRef(<Row extends RowDataType, Key>(props: TableProps<
953
956
  tableId={id}
954
957
  style={{ width: tableWidth.current }}
955
958
  length={tableWidth.current}
956
- onScroll={onScrollHorizontal}
959
+ onScroll={delta => {
960
+ onScrollHorizontal(delta);
961
+ }}
957
962
  scrollLength={contentWidth.current}
958
963
  ref={scrollbarXRef}
959
964
  />
@@ -1132,13 +1137,21 @@ const Table = React.forwardRef(<Row extends RowDataType, Key>(props: TableProps<
1132
1137
  role="rowgroup"
1133
1138
  className={prefix('body-row-wrapper')}
1134
1139
  style={bodyStyles}
1135
- onScroll={onScrollBody}
1140
+ onScroll={e => {
1141
+ onScrollBody?.(e); // existing handler
1142
+ }}
1136
1143
  >
1137
1144
  {!loading && (
1138
1145
  <div style={wheelStyles} className={prefix('body-wheel-area')} ref={wheelWrapperRef}>
1139
1146
  {topHideHeight ? <Row style={topRowStyles} className="virtualized" /> : null}
1140
1147
  {visibleRows.current}
1141
1148
  {bottomHideHeight ? <Row style={bottomRowStyles} className="virtualized" /> : null}
1149
+
1150
+ {infiniteLoading && (
1151
+ <div style={{ padding: 12, textAlign: 'center' }}>
1152
+ <span>Loading more rows…</span>
1153
+ </div>
1154
+ )}
1142
1155
  </div>
1143
1156
  )}
1144
1157
 
@@ -1,88 +1,88 @@
1
- import React, { FC, useState, useEffect, useRef } from 'react';
2
-
3
- type CustomSelectProps = {
4
- options: number[];
5
- selectedValue: number;
6
- onChange: (value: number) => void;
7
- };
8
-
9
- const CustomSelect: FC<CustomSelectProps> = ({ options, selectedValue, onChange }) => {
10
- const [isOpen, setIsOpen] = useState(false);
11
- const [dropdownPosition, setDropdownPosition] = useState('bottom');
12
- const ref = useRef<HTMLDivElement>(null);
13
- const inputRef = useRef<HTMLDivElement>(null);
14
-
15
- const adjustDropdownPosition = () => {
16
- if (inputRef.current) {
17
- const inputBoxRect = inputRef.current.getBoundingClientRect();
18
- const viewportHeight = window.innerHeight;
19
-
20
- const spaceAbove = inputBoxRect.top;
21
- const spaceBelow = viewportHeight - inputBoxRect.bottom;
22
-
23
- if (spaceAbove > spaceBelow) {
24
- setDropdownPosition('top');
25
- } else {
26
- setDropdownPosition('bottom');
27
- }
28
- }
29
- };
30
-
31
- const handleToggle = () => {
32
- setIsOpen(prevIsOpen => !prevIsOpen);
33
- };
34
-
35
- const handleSelect = (value: number) => {
36
- onChange(value);
37
- setIsOpen(false);
38
- };
39
-
40
- const handleClickOutside = (event: MouseEvent) => {
41
- if (ref.current && !ref.current.contains(event.target as Node)) {
42
- setIsOpen(false);
43
- }
44
- };
45
-
46
- useEffect(() => {
47
- if (isOpen) {
48
- adjustDropdownPosition();
49
- window.addEventListener('resize', adjustDropdownPosition);
50
- } else {
51
- window.removeEventListener('resize', adjustDropdownPosition);
52
- }
53
-
54
- return () => {
55
- window.removeEventListener('resize', adjustDropdownPosition);
56
- };
57
- }, [isOpen]);
58
-
59
- useEffect(() => {
60
- document.addEventListener('mousedown', handleClickOutside);
61
- return () => {
62
- document.removeEventListener('mousedown', handleClickOutside);
63
- };
64
- }, []);
65
-
66
- return (
67
- <div className="custom-select" ref={ref}>
68
- <div className="custom-select-trigger" onClick={handleToggle} ref={inputRef}>
69
- {selectedValue}
70
- </div>
71
- {isOpen && (
72
- <ul className={`custom-select-options ${dropdownPosition}`}>
73
- {options.map(option => (
74
- <li
75
- key={option}
76
- className={`custom-select-option ${option === selectedValue ? 'selected' : ''}`}
77
- onClick={() => handleSelect(option)}
78
- >
79
- {option}
80
- </li>
81
- ))}
82
- </ul>
83
- )}
84
- </div>
85
- );
86
- };
87
-
88
- export default CustomSelect;
1
+ import React, { FC, useState, useEffect, useRef } from 'react';
2
+
3
+ type CustomSelectProps = {
4
+ options: number[];
5
+ selectedValue: number;
6
+ onChange: (value: number) => void;
7
+ };
8
+
9
+ const CustomSelect: FC<CustomSelectProps> = ({ options, selectedValue, onChange }) => {
10
+ const [isOpen, setIsOpen] = useState(false);
11
+ const [dropdownPosition, setDropdownPosition] = useState('bottom');
12
+ const ref = useRef<HTMLDivElement>(null);
13
+ const inputRef = useRef<HTMLDivElement>(null);
14
+
15
+ const adjustDropdownPosition = () => {
16
+ if (inputRef.current) {
17
+ const inputBoxRect = inputRef.current.getBoundingClientRect();
18
+ const viewportHeight = window.innerHeight;
19
+
20
+ const spaceAbove = inputBoxRect.top;
21
+ const spaceBelow = viewportHeight - inputBoxRect.bottom;
22
+
23
+ if (spaceAbove > spaceBelow) {
24
+ setDropdownPosition('top');
25
+ } else {
26
+ setDropdownPosition('bottom');
27
+ }
28
+ }
29
+ };
30
+
31
+ const handleToggle = () => {
32
+ setIsOpen(prevIsOpen => !prevIsOpen);
33
+ };
34
+
35
+ const handleSelect = (value: number) => {
36
+ onChange(value);
37
+ setIsOpen(false);
38
+ };
39
+
40
+ const handleClickOutside = (event: MouseEvent) => {
41
+ if (ref.current && !ref.current.contains(event.target as Node)) {
42
+ setIsOpen(false);
43
+ }
44
+ };
45
+
46
+ useEffect(() => {
47
+ if (isOpen) {
48
+ adjustDropdownPosition();
49
+ window.addEventListener('resize', adjustDropdownPosition);
50
+ } else {
51
+ window.removeEventListener('resize', adjustDropdownPosition);
52
+ }
53
+
54
+ return () => {
55
+ window.removeEventListener('resize', adjustDropdownPosition);
56
+ };
57
+ }, [isOpen]);
58
+
59
+ useEffect(() => {
60
+ document.addEventListener('mousedown', handleClickOutside);
61
+ return () => {
62
+ document.removeEventListener('mousedown', handleClickOutside);
63
+ };
64
+ }, []);
65
+
66
+ return (
67
+ <div className="custom-select" ref={ref}>
68
+ <div className="custom-select-trigger" onClick={handleToggle} ref={inputRef}>
69
+ {selectedValue}
70
+ </div>
71
+ {isOpen && (
72
+ <ul className={`custom-select-options ${dropdownPosition}`}>
73
+ {options.map(option => (
74
+ <li
75
+ key={option}
76
+ className={`custom-select-option ${option === selectedValue ? 'selected' : ''}`}
77
+ onClick={() => handleSelect(option)}
78
+ >
79
+ {option}
80
+ </li>
81
+ ))}
82
+ </ul>
83
+ )}
84
+ </div>
85
+ );
86
+ };
87
+
88
+ export default CustomSelect;
package/src/index.ts CHANGED
@@ -15,7 +15,9 @@ export type { QbsTableProps } from './qbsTable/commontypes';
15
15
  export type { QbsTableLabels } from './qbsTable/labels';
16
16
  export {
17
17
  mergeQbsTableLabels,
18
+ mergeLabels,
18
19
  defaultQbsTableLabels,
20
+ DEFAULT_QBS_TABLE_LABELS,
19
21
  formatSelectedItems,
20
22
  } from './qbsTable/labels';
21
23
  export type {
@@ -5,8 +5,8 @@
5
5
  min-height: 40px;
6
6
  align-items: center;
7
7
  border-radius: 0 0 4px 4px;
8
- border-top: 1px solid #d6d8dc;
9
- background: #fff;
8
+ border-top: 1px solid var(--base-gray-border, #d6d8dc);
9
+ background: var(--table-bg, #fff);
10
10
  &-header {
11
11
  border-bottom: 1px solid #eee;
12
12
  position: absolute;
@@ -27,8 +27,8 @@
27
27
  font-weight: 500;
28
28
  line-height: 20px;
29
29
  border-radius: 6px;
30
- border: 1px solid #d6d8dc;
31
- background: #fff;
30
+ border: 1px solid var(--base-gray-border, #d6d8dc);
31
+ background: var(--gray-light-1, #fff);
32
32
  }
33
33
  .qbs-table-icon-container {
34
34
  padding: 0;
@@ -109,7 +109,7 @@
109
109
  font-style: normal;
110
110
  font-weight: 500;
111
111
  line-height: 20px;
112
- color: #313131;
112
+ color: var(--gray-dark-3, #313131);
113
113
  }
114
114
  }
115
115
 
@@ -125,7 +125,7 @@
125
125
  .custom-select-trigger {
126
126
  padding: 2px 8px;
127
127
  cursor: pointer;
128
- border: 1px solid #d6d8dc;
128
+ border: 1px solid var(--base-gray-border, #d6d8dc);
129
129
  border-radius: 4px;
130
130
  min-width: 65px;
131
131
  position: relative;
@@ -140,7 +140,7 @@
140
140
  list-style: none;
141
141
  margin: 2px 0 0;
142
142
  padding: 0;
143
- background: #fff;
143
+ background: var(--gray-light-1, #fff);
144
144
  border-radius: 8px;
145
145
  box-shadow: 0 8px 20px 0 #00000026;
146
146
  }
@@ -158,7 +158,7 @@ ul.custom-select-options.top {
158
158
 
159
159
  .custom-select-option:hover,
160
160
  .custom-select-option.selected {
161
- background-color: #f0f0f0;
161
+ background-color: var(--table-row-hover-bg, #f0f0f0);
162
162
  }
163
163
 
164
164
  .custom-select-trigger:before {
@@ -167,7 +167,7 @@ ul.custom-select-options.top {
167
167
  right: 10px;
168
168
  top: 6px;
169
169
  font-weight: bold;
170
- border: solid black;
170
+ border: solid var(--gray-dark-3, black);
171
171
  border-width: 0 1px 1px 0;
172
172
  display: inline-block;
173
173
  padding: 3px;
@@ -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
- dropType,
97
- labels: labelsProp,
98
- rtl = false,
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
- isFullScreen = false,
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 effectiveWordWrap = useMemo(() => {
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(() => localStorage.getItem('theme') ?? theme, [theme]);
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 [rowViewRefreshKey, setRowViewRefreshKey] = useState(0);
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 className={`qbs-table ${classes.tableContainerClass}`} data-theme={dataTheme}>
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 ?? 'No Data Found'} subtitle={emptySubTitle} />
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 ?? 'No Data Found'} subtitle={emptySubTitle} />
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 && <Pagination paginationProps={paginationProps} />}
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}