@etsoo/react 1.4.18 → 1.4.22

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.
@@ -1,57 +1,104 @@
1
1
  import { Box, Stack } from '@mui/material';
2
2
  import React from 'react';
3
+ import { Labels } from '../app/Labels';
3
4
  import { GridDataGet } from '../components/GridLoader';
4
5
  import useCombinedRefs from '../uses/useCombinedRefs';
5
6
  import { useDimensions } from '../uses/useDimensions';
6
7
  import { DataGridEx, DataGridExCalColumns } from './DataGridEx';
8
+ import { MUGlobal } from './MUGlobal';
9
+ import { PullToRefreshUI } from './PullToRefreshUI';
7
10
  import { ScrollerListEx } from './ScrollerListEx';
8
11
  import { SearchBar } from './SearchBar';
12
+ /**
13
+ * Responsible container
14
+ * @param props Props
15
+ * @returns Layout
16
+ */
9
17
  export function ResponsibleContainer(props) {
10
- var _a;
11
18
  // Destruct
12
- const { adjustHeight, columns, dataGridMinWidth = DataGridExCalColumns(columns).total, fields, fieldTemplate, height, listBoxSx, loadData, mRef, searchBoxSx, sizeReadyMiliseconds = 0, ...rest } = props;
19
+ const { adjustHeight, columns, dataGridMinWidth = DataGridExCalColumns(columns).total, fields, fieldTemplate, height, listBoxSx, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, searchBoxSx = { marginBottom: MUGlobal.half(paddings) }, sizeReadyMiliseconds = 0, ...rest } = props;
20
+ // Labels
21
+ const labels = Labels.CommonPage;
13
22
  // Refs
14
23
  const refs = React.useRef({});
24
+ const state = refs.current;
15
25
  const mRefs = useCombinedRefs(mRef, (ref) => {
16
26
  if (ref == null)
17
27
  return;
18
- refs.current.ref = ref;
28
+ state.ref = ref;
19
29
  });
30
+ // Update mounted state
31
+ React.useEffect(() => {
32
+ return () => {
33
+ state.mounted = false;
34
+ };
35
+ }, []);
20
36
  // Has fields
21
37
  const hasFields = fields != null && fields.length > 0;
38
+ // Load data
39
+ const localLoadData = (props) => {
40
+ state.mounted = true;
41
+ const data = GridDataGet(props, fieldTemplate);
42
+ return loadData(data);
43
+ };
44
+ // On submit callback
45
+ const onSubmit = (data, _reset) => {
46
+ if (data == null || state.ref == null)
47
+ return;
48
+ state.ref.reset({ data });
49
+ };
22
50
  // Watch container
23
- const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
51
+ const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds, (_preRect, rect) => {
52
+ // Check
53
+ if (rect == null)
54
+ return true;
55
+ // Last rect
56
+ const lastRect = state.rect;
57
+ // 32 = scroll bar width
58
+ if (lastRect != null &&
59
+ state.mounted !== true &&
60
+ Math.abs(rect.width - lastRect.width) <= 32 &&
61
+ Math.abs(rect.height - lastRect.height) <= 32)
62
+ return true;
63
+ // Hold the new rect
64
+ state.rect = rect;
65
+ return false;
66
+ });
67
+ // Rect
24
68
  const rect = dimensions[0][2];
25
- const showDataGrid = ((_a = rect === null || rect === void 0 ? void 0 : rect.width) !== null && _a !== void 0 ? _a : 0) >= dataGridMinWidth;
26
- React.useEffect(() => {
27
- if (rect != null && rect.height > 50 && height == null) {
28
- let gridHeight = window.innerHeight - Math.round(rect.top + rect.height + 1);
69
+ // Create list
70
+ const [list, showDataGrid] = (() => {
71
+ // No layout
72
+ if (rect == null)
73
+ return [null, false];
74
+ // Width
75
+ const width = rect.width;
76
+ // Show DataGrid or List dependng on width
77
+ const showDataGrid = width >= dataGridMinWidth;
78
+ // Height
79
+ let heightLocal;
80
+ if (height != null) {
81
+ heightLocal = height;
82
+ }
83
+ else {
84
+ // Auto calculation
85
+ heightLocal = window.innerHeight - Math.round(rect.bottom + 1);
29
86
  const style = window.getComputedStyle(dimensions[0][1]);
30
- const boxPadding = parseFloat(style.paddingLeft);
31
- if (!isNaN(boxPadding))
32
- gridHeight -= 2 * boxPadding;
87
+ const boxMargin = parseFloat(style.marginBottom);
88
+ if (!isNaN(boxMargin))
89
+ heightLocal -= 3 * boxMargin; // 1 - Box, 2 - Page bottom
33
90
  if (adjustHeight != null) {
34
- gridHeight -= adjustHeight(gridHeight);
35
- }
36
- if (gridHeight !== refs.current.height) {
37
- refs.current.height = gridHeight;
91
+ heightLocal -= adjustHeight(heightLocal);
38
92
  }
39
93
  }
40
- }, [rect]);
41
- const localLoadData = (props) => {
42
- const data = GridDataGet(props, fieldTemplate);
43
- return loadData(data);
44
- };
45
- const gridHeight = refs.current.height;
46
- console.log(rect, gridHeight, showDataGrid);
47
- const list = React.useMemo(() => {
48
- if (gridHeight == null)
49
- return;
50
94
  if (showDataGrid) {
51
95
  // Delete
52
96
  delete rest.itemRenderer;
53
- return (React.createElement(Box, { sx: listBoxSx == null ? undefined : listBoxSx(true) },
54
- React.createElement(DataGridEx, { autoLoad: !hasFields, height: gridHeight, loadData: localLoadData, mRef: mRefs, columns: columns, ...rest })));
97
+ return [
98
+ React.createElement(Box, { sx: listBoxSx == null ? undefined : listBoxSx(true) },
99
+ React.createElement(DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, columns: columns, ...rest })),
100
+ true
101
+ ];
55
102
  }
56
103
  // Delete
57
104
  delete rest.checkable;
@@ -62,18 +109,25 @@ export function ResponsibleContainer(props) {
62
109
  delete rest.hideFooter;
63
110
  delete rest.hoverColor;
64
111
  delete rest.selectable;
65
- return (React.createElement(Box, { sx: listBoxSx == null ? undefined : listBoxSx(false) },
66
- React.createElement(ScrollerListEx, { autoLoad: !hasFields, height: gridHeight, loadData: localLoadData, mRef: mRefs, ...rest })));
67
- }, [gridHeight, showDataGrid]);
68
- // On submit callback
69
- const onSubmit = (data, _reset) => {
70
- if (data == null || rect == null || refs.current.ref == null)
71
- return;
72
- refs.current.ref.reset({ data });
73
- };
112
+ return [
113
+ React.createElement(Box, { sx: listBoxSx == null ? undefined : listBoxSx(false) },
114
+ React.createElement(ScrollerListEx, { autoLoad: !hasFields, width: rect.width, height: heightLocal, loadData: localLoadData, mRef: mRefs, ...rest })),
115
+ false
116
+ ];
117
+ })();
118
+ // Pull container
119
+ const pullContainer = list
120
+ ? showDataGrid
121
+ ? '.DataGridEx-Body'
122
+ : '.ScrollerListEx-Body'
123
+ : undefined;
74
124
  // Layout
75
- return (React.createElement(Stack, null,
76
- hasFields && (React.createElement(Box, { ref: dimensions[0][0], sx: searchBoxSx },
77
- React.createElement(SearchBar, { fields: fields, onSubmit: onSubmit }))),
78
- list));
125
+ return (React.createElement(React.Fragment, null,
126
+ React.createElement(Stack, null,
127
+ React.createElement(Box, { ref: dimensions[0][0], sx: searchBoxSx }, hasFields && (React.createElement(SearchBar, { fields: fields, onSubmit: onSubmit }))),
128
+ list),
129
+ pullToRefresh && pullContainer && (React.createElement(PullToRefreshUI, { mainElement: pullContainer, triggerElement: pullContainer, instructionsPullToRefresh: labels.pullToRefresh, instructionsReleaseToRefresh: labels.releaseToRefresh, instructionsRefreshing: labels.refreshing, onRefresh: () => { var _a; return (_a = state.ref) === null || _a === void 0 ? void 0 : _a.reset(); }, shouldPullToRefresh: () => {
130
+ const container = document.querySelector(pullContainer);
131
+ return !(container === null || container === void 0 ? void 0 : container.scrollTop);
132
+ } }))));
79
133
  }
@@ -66,8 +66,7 @@ export function ScrollerListEx(props) {
66
66
  const [selectedDiv, selectedData] = (_a = selectedItem.current) !== null && _a !== void 0 ? _a : [];
67
67
  if (selectedData != null && selectedData[idField] === data[idField])
68
68
  return;
69
- if (selectedDiv != null)
70
- selectedDiv.classList.remove(selectedClassName);
69
+ selectedDiv === null || selectedDiv === void 0 ? void 0 : selectedDiv.classList.remove(selectedClassName);
71
70
  div.classList.add(selectedClassName);
72
71
  selectedItem.current = [div, data];
73
72
  if (onSelectChange)
package/lib/mu/TableEx.js CHANGED
@@ -34,35 +34,39 @@ export function TableEx(props) {
34
34
  else {
35
35
  rowsPerPageLocal = 10;
36
36
  }
37
+ // Rows
38
+ const [rows, updateRows] = React.useState([]);
39
+ const setRows = (rows) => {
40
+ state.loadedItems = rows.length;
41
+ updateRows(rows);
42
+ };
37
43
  // States
38
- const [state, stateUpdate] = React.useReducer((currentState, newState) => {
39
- return { ...currentState, ...newState };
40
- }, {
44
+ const stateRefs = React.useRef({
41
45
  autoLoad,
42
46
  currentPage: 0,
47
+ loadedItems: 0,
43
48
  hasNextPage: true,
44
49
  isNextPageLoading: false,
45
50
  orderBy: defaultOrderBy,
46
51
  orderByAsc: defaultOrderBy
47
52
  ? (_a = columns.find((column) => column.field === defaultOrderBy)) === null || _a === void 0 ? void 0 : _a.sortAsc
48
53
  : undefined,
49
- rows: [],
50
54
  batchSize: rowsPerPageLocal,
51
55
  selectedItems: []
52
56
  });
53
- const isMounted = React.useRef(true);
57
+ const state = stateRefs.current;
54
58
  // Reset the state and load again
55
59
  const reset = (add) => {
56
- const state = {
60
+ const resetState = {
57
61
  autoLoad: true,
58
62
  currentPage: 0,
63
+ loadedItems: 0,
59
64
  hasNextPage: true,
60
65
  isNextPageLoading: false,
61
66
  lastLoadedItems: undefined,
62
- rows: [],
63
67
  ...add
64
68
  };
65
- stateUpdate(state);
69
+ Object.assign(state, resetState);
66
70
  };
67
71
  React.useImperativeHandle(mRef, () => ({
68
72
  /**
@@ -84,7 +88,7 @@ export function TableEx(props) {
84
88
  // Update state
85
89
  state.isNextPageLoading = true;
86
90
  // Parameters
87
- const { currentPage, batchSize, orderBy, orderByAsc, data } = state;
91
+ const { currentPage, batchSize, orderBy, orderByAsc, data, isMounted } = state;
88
92
  const loadProps = {
89
93
  currentPage,
90
94
  batchSize,
@@ -93,16 +97,16 @@ export function TableEx(props) {
93
97
  data
94
98
  };
95
99
  loadData(loadProps).then((result) => {
96
- if (!isMounted.current || result == null) {
100
+ state.isMounted = true;
101
+ if (result == null || isMounted === false) {
97
102
  return;
98
103
  }
99
104
  const newItems = result.length;
100
- stateUpdate({
101
- rows: result,
102
- lastLoadedItems: newItems,
103
- hasNextPage: newItems >= batchSize,
104
- isNextPageLoading: false
105
- });
105
+ state.lastLoadedItems = newItems;
106
+ state.hasNextPage = newItems >= batchSize;
107
+ state.isNextPageLoading = false;
108
+ // Update rows
109
+ setRows(result);
106
110
  });
107
111
  };
108
112
  const handleChangePage = (_event, newPage) => {
@@ -111,11 +115,11 @@ export function TableEx(props) {
111
115
  loadDataLocal();
112
116
  };
113
117
  const handleChangeRowsPerPage = (event) => {
114
- const rowsPerPage = parseInt(event.target.value);
115
- reset({ rowsPerPage });
118
+ const batchSize = parseInt(event.target.value);
119
+ reset({ batchSize });
116
120
  };
117
121
  const handleSelect = (item, checked) => {
118
- const selectedItems = [...state.selectedItems];
122
+ const selectedItems = state.selectedItems;
119
123
  const index = selectedItems.findIndex((selectedItem) => selectedItem[idField] === item[idField]);
120
124
  if (checked) {
121
125
  if (index === -1)
@@ -128,11 +132,10 @@ export function TableEx(props) {
128
132
  if (onSelectChange != null) {
129
133
  onSelectChange(selectedItems);
130
134
  }
131
- stateUpdate({ selectedItems });
132
135
  };
133
136
  const handleSelectAll = (checked) => {
134
- const selectedItems = [...state.selectedItems];
135
- state.rows.forEach((row) => {
137
+ const selectedItems = state.selectedItems;
138
+ rows.forEach((row) => {
136
139
  const index = selectedItems.findIndex((selectedItem) => selectedItem[idField] === row[idField]);
137
140
  if (checked) {
138
141
  if (index === -1)
@@ -145,14 +148,13 @@ export function TableEx(props) {
145
148
  if (onSelectChange != null) {
146
149
  onSelectChange(selectedItems);
147
150
  }
148
- stateUpdate({ selectedItems });
149
151
  };
150
152
  // New sort
151
153
  const handleSort = (field, asc) => {
152
154
  reset({ orderBy: field, orderByAsc: asc });
153
155
  };
154
156
  // Destruct states
155
- const { autoLoad: stateAutoLoad, currentPage, hasNextPage, lastLoadedItems, orderBy, rows, batchSize, selectedItems } = state;
157
+ const { autoLoad: stateAutoLoad, currentPage, hasNextPage, lastLoadedItems, orderBy, batchSize, selectedItems } = state;
156
158
  // Current page selected items
157
159
  const pageSelectedItems = selectable
158
160
  ? rows.reduce((previousValue, currentItem) => {
@@ -170,7 +172,7 @@ export function TableEx(props) {
170
172
  loadDataLocal();
171
173
  React.useEffect(() => {
172
174
  return () => {
173
- isMounted.current = false;
175
+ state.isMounted = false;
174
176
  };
175
177
  }, []);
176
178
  // Layout
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  /// <reference types="react" />
3
2
  import { CommonPageProps } from './CommonPageProps';
4
3
  /**
@@ -8,7 +7,7 @@ export declare const CommonPagePullContainer = "#page-container";
8
7
  /**
9
8
  * Default scroll container
10
9
  */
11
- export declare const CommonPageScrollContainer: NodeJS.Global & typeof globalThis;
10
+ export declare const CommonPageScrollContainer: typeof globalThis;
12
11
  /**
13
12
  * Common page
14
13
  * @param props Props
@@ -1,13 +1,5 @@
1
1
  import { DomUtils } from '@etsoo/shared';
2
2
  import React from 'react';
3
- const createRef = (source, index) => {
4
- return [
5
- (instance) => {
6
- if (instance != null)
7
- source[index][1] = instance;
8
- }
9
- ];
10
- };
11
3
  /**
12
4
  * Calculate element(s) dimensions
13
5
  * @param elements Observed elments count
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/react",
3
- "version": "1.4.18",
3
+ "version": "1.4.22",
4
4
  "description": "TypeScript ReactJs framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -54,7 +54,7 @@
54
54
  "@etsoo/notificationbase": "^1.1.0",
55
55
  "@etsoo/shared": "^1.1.3",
56
56
  "@mui/icons-material": "^5.2.5",
57
- "@mui/material": "^5.2.7",
57
+ "@mui/material": "^5.2.8",
58
58
  "@reach/router": "^1.3.4",
59
59
  "@types/pica": "^5.1.3",
60
60
  "@types/pulltorefreshjs": "^0.1.5",
@@ -76,15 +76,15 @@
76
76
  "react-window": "^1.8.6"
77
77
  },
78
78
  "devDependencies": {
79
- "@babel/cli": "^7.16.7",
79
+ "@babel/cli": "^7.16.8",
80
80
  "@babel/core": "^7.16.7",
81
- "@babel/plugin-transform-runtime": "^7.16.7",
82
- "@babel/preset-env": "^7.16.7",
83
- "@babel/runtime-corejs3": "^7.16.7",
81
+ "@babel/plugin-transform-runtime": "^7.16.8",
82
+ "@babel/preset-env": "^7.16.8",
83
+ "@babel/runtime-corejs3": "^7.16.8",
84
84
  "@types/jest": "^27.4.0",
85
85
  "@types/react-test-renderer": "^17.0.1",
86
- "@typescript-eslint/eslint-plugin": "^5.9.0",
87
- "@typescript-eslint/parser": "^5.9.0",
86
+ "@typescript-eslint/eslint-plugin": "^5.9.1",
87
+ "@typescript-eslint/parser": "^5.9.1",
88
88
  "eslint": "^8.6.0",
89
89
  "eslint-config-airbnb-base": "^15.0.0",
90
90
  "eslint-plugin-import": "^2.25.4",
@@ -126,6 +126,11 @@ export interface GridLoaderStates<T> extends GridLoadDataProps {
126
126
  */
127
127
  lastLoadedItems?: number;
128
128
 
129
+ /**
130
+ * All loaded items count
131
+ */
132
+ loadedItems: number;
133
+
129
134
  /**
130
135
  * Has next page?
131
136
  */
@@ -137,9 +142,9 @@ export interface GridLoaderStates<T> extends GridLoadDataProps {
137
142
  isNextPageLoading: boolean;
138
143
 
139
144
  /**
140
- * Current rows
145
+ * Is mounted
141
146
  */
142
- rows: T[];
147
+ isMounted?: boolean;
143
148
 
144
149
  /**
145
150
  * Selected items of id
@@ -40,7 +40,10 @@ export interface ScrollerGridProps<T>
40
40
  /**
41
41
  * Footer renderer
42
42
  */
43
- footerRenderer?: (states: GridLoaderStates<T>) => React.ReactNode;
43
+ footerRenderer?: (
44
+ rows: T[],
45
+ states: GridLoaderStates<T>
46
+ ) => React.ReactNode;
44
47
 
45
48
  /**
46
49
  * Header renderer
@@ -163,29 +166,28 @@ export const ScrollerGrid = <T extends Record<string, unknown>>(
163
166
  ...rest
164
167
  } = props;
165
168
 
166
- // States
167
- const [state, stateUpdate] = React.useReducer(
168
- (
169
- currentState: GridLoaderStates<T>,
170
- newState: Partial<GridLoaderStates<T>>
171
- ) => {
172
- return { ...currentState, ...newState };
173
- },
174
- {
175
- autoLoad,
176
- currentPage: 0,
177
- hasNextPage: true,
178
- isNextPageLoading: false,
179
- orderBy: defaultOrderBy,
180
- orderByAsc: defaultOrderByAsc,
181
- rows: [],
182
- batchSize: 10,
183
- selectedItems: []
184
- }
185
- );
186
- const isMounted = React.useRef(true);
169
+ // Rows
170
+ const [rows, updateRows] = React.useState<T[]>([]);
171
+ const setRows = (rows: T[]) => {
172
+ state.loadedItems = rows.length;
173
+ updateRows(rows);
174
+ };
187
175
 
188
- const ref = React.createRef<VariableSizeGrid<T>>();
176
+ // Refs
177
+ const refs = React.useRef<GridLoaderStates<T>>({
178
+ autoLoad,
179
+ currentPage: 0,
180
+ hasNextPage: true,
181
+ isNextPageLoading: false,
182
+ orderBy: defaultOrderBy,
183
+ orderByAsc: defaultOrderByAsc,
184
+ batchSize: 10,
185
+ loadedItems: 0,
186
+ selectedItems: []
187
+ });
188
+ const state = refs.current;
189
+
190
+ const ref = React.useRef<VariableSizeGrid<T>>(null);
189
191
 
190
192
  // Load data
191
193
  const loadDataLocal = (pageAdd: number = 1) => {
@@ -194,10 +196,10 @@ export const ScrollerGrid = <T extends Record<string, unknown>>(
194
196
 
195
197
  // Update state
196
198
  state.isNextPageLoading = true;
197
- // stateUpdate({ isNextPageLoading: true });
198
199
 
199
200
  // Parameters
200
- const { currentPage, batchSize, orderBy, orderByAsc, data } = state;
201
+ const { currentPage, batchSize, orderBy, orderByAsc, data, isMounted } =
202
+ state;
201
203
 
202
204
  const loadProps: GridLoadDataProps = {
203
205
  currentPage,
@@ -208,38 +210,36 @@ export const ScrollerGrid = <T extends Record<string, unknown>>(
208
210
  };
209
211
 
210
212
  loadData(loadProps).then((result) => {
211
- if (result == null || !isMounted.current) {
213
+ state.isMounted = true;
214
+
215
+ if (result == null || isMounted === false) {
212
216
  return;
213
217
  }
214
218
 
215
219
  const newItems = result.length;
220
+ state.lastLoadedItems = newItems;
221
+ state.isNextPageLoading = false;
222
+ state.hasNextPage = newItems >= batchSize;
216
223
 
217
224
  if (pageAdd === 0) {
218
225
  // New items
219
- const rows = state.lastLoadedItems
220
- ? state.rows
226
+ const newRows = state.lastLoadedItems
227
+ ? [...rows]
221
228
  .splice(
222
- state.rows.length - state.lastLoadedItems,
229
+ rows.length - state.lastLoadedItems,
223
230
  state.lastLoadedItems
224
231
  )
225
232
  .concat(result)
226
233
  : result;
227
234
 
228
- // Refresh current page
229
- stateUpdate({
230
- rows,
231
- lastLoadedItems: newItems,
232
- isNextPageLoading: false,
233
- hasNextPage: newItems >= batchSize
234
- });
235
+ // Update rows
236
+ setRows(newRows);
235
237
  } else {
236
- stateUpdate({
237
- rows: state.rows.concat(result),
238
- lastLoadedItems: newItems,
239
- isNextPageLoading: false,
240
- currentPage: state.currentPage + pageAdd,
241
- hasNextPage: newItems >= batchSize
242
- });
238
+ // Set current page
239
+ state.currentPage = state.currentPage + pageAdd;
240
+
241
+ // Update rows
242
+ setRows([...rows, ...result]);
243
243
  }
244
244
  });
245
245
  };
@@ -251,8 +251,8 @@ export const ScrollerGrid = <T extends Record<string, unknown>>(
251
251
  ) => {
252
252
  // Custom render
253
253
  const data =
254
- itemProps.rowIndex < state.rows.length
255
- ? state.rows[itemProps.rowIndex]
254
+ itemProps.rowIndex < rows.length
255
+ ? rows[itemProps.rowIndex]
256
256
  : undefined;
257
257
  return itemRenderer({
258
258
  ...itemProps,
@@ -264,7 +264,7 @@ export const ScrollerGrid = <T extends Record<string, unknown>>(
264
264
  // Local items renderer callback
265
265
  const onItemsRenderedLocal = (props: GridOnItemsRenderedProps) => {
266
266
  // No items, means no necessary to load more data during reset
267
- const itemCount = state.rows.length;
267
+ const itemCount = rows.length;
268
268
  if (
269
269
  itemCount > 0 &&
270
270
  props.visibleRowStopIndex + threshold > itemCount
@@ -278,17 +278,20 @@ export const ScrollerGrid = <T extends Record<string, unknown>>(
278
278
  };
279
279
 
280
280
  // Reset the state and load again
281
- const reset = (add?: {}) => {
282
- const state = {
281
+ const reset = (add?: Partial<GridLoaderStates<T>>) => {
282
+ const resetState: Partial<GridLoaderStates<T>> = {
283
283
  autoLoad: true,
284
284
  currentPage: 0,
285
+ loadedItems: 0,
285
286
  hasNextPage: true,
286
287
  isNextPageLoading: false,
287
288
  lastLoadedItems: undefined,
288
- rows: [],
289
289
  ...add
290
290
  };
291
- stateUpdate(state);
291
+ Object.assign(state, resetState);
292
+
293
+ // Reset items
294
+ setRows([]);
292
295
  };
293
296
 
294
297
  React.useImperativeHandle(
@@ -307,16 +310,14 @@ export const ScrollerGrid = <T extends Record<string, unknown>>(
307
310
  select(rowIndex: number) {
308
311
  // Select only one item
309
312
  const selectedItems = state.selectedItems;
310
- selectedItems[0] = state.rows[rowIndex];
313
+ selectedItems[0] = rows[rowIndex];
311
314
 
312
315
  if (onSelectChange) onSelectChange(selectedItems);
313
-
314
- stateUpdate({ selectedItems });
315
316
  },
316
317
  selectAll(checked: boolean) {
317
318
  const selectedItems = state.selectedItems;
318
319
 
319
- state.rows.forEach((row) => {
320
+ rows.forEach((row) => {
320
321
  const index = selectedItems.findIndex(
321
322
  (selectedItem) => selectedItem[idField] === row[idField]
322
323
  );
@@ -329,8 +330,6 @@ export const ScrollerGrid = <T extends Record<string, unknown>>(
329
330
  });
330
331
 
331
332
  if (onSelectChange) onSelectChange(selectedItems);
332
-
333
- stateUpdate({ selectedItems });
334
333
  },
335
334
  selectItem(item: T, checked: boolean) {
336
335
  const selectedItems = state.selectedItems;
@@ -345,8 +344,6 @@ export const ScrollerGrid = <T extends Record<string, unknown>>(
345
344
  }
346
345
 
347
346
  if (onSelectChange) onSelectChange(selectedItems);
348
-
349
- stateUpdate({ selectedItems });
350
347
  },
351
348
  reset,
352
349
  resetAfterColumnIndex(index: number, shouldForceUpdate?: boolean) {
@@ -363,17 +360,26 @@ export const ScrollerGrid = <T extends Record<string, unknown>>(
363
360
  ref.current?.resetAfterRowIndex(index, shouldForceUpdate);
364
361
  }
365
362
  }),
366
- [state.rows, state.selectedItems]
363
+ [rows]
367
364
  );
368
365
 
369
366
  React.useEffect(() => {
370
367
  return () => {
371
- isMounted.current = false;
368
+ state.isMounted = false;
372
369
  };
373
370
  }, []);
374
371
 
372
+ // Force update to work with the new width
373
+ React.useEffect(() => {
374
+ ref.current?.resetAfterIndices({
375
+ columnIndex: 0,
376
+ rowIndex: 0,
377
+ shouldForceUpdate: true
378
+ });
379
+ }, [width]);
380
+
375
381
  // Destruct state
376
- const { autoLoad: stateAutoLoad, rows, hasNextPage, currentPage } = state;
382
+ const { autoLoad: stateAutoLoad, hasNextPage, currentPage } = state;
377
383
  const rowLength = rows.length;
378
384
 
379
385
  // Row count
@@ -388,7 +394,7 @@ export const ScrollerGrid = <T extends Record<string, unknown>>(
388
394
  {headerRenderer && headerRenderer(state)}
389
395
  <VariableSizeGrid<T>
390
396
  itemKey={({ columnIndex, rowIndex }) => {
391
- const data = state.rows[rowIndex];
397
+ const data = rows[rowIndex];
392
398
  if (data == null) return [rowIndex, columnIndex].join(',');
393
399
  return [data[idField], columnIndex].join(',');
394
400
  }}
@@ -406,7 +412,7 @@ export const ScrollerGrid = <T extends Record<string, unknown>>(
406
412
  >
407
413
  {(props) => itemRendererLocal(props, state)}
408
414
  </VariableSizeGrid>
409
- {footerRenderer && footerRenderer(state)}
415
+ {footerRenderer && footerRenderer(rows, state)}
410
416
  </React.Fragment>
411
417
  );
412
418
  };