@etsoo/react 1.4.19 → 1.4.23

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.
@@ -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
  };
@@ -133,27 +133,26 @@ export const ScrollerList = <T extends Record<string, any>>(
133
133
 
134
134
  const refs = useCombinedRefs(oRef, outerRef);
135
135
 
136
+ // Rows
137
+ const [rows, updateRows] = React.useState<T[]>([]);
138
+ const setRows = (rows: T[]) => {
139
+ state.loadedItems = rows.length;
140
+ updateRows(rows);
141
+ };
142
+
136
143
  // States
137
- const [state, stateUpdate] = React.useReducer(
138
- (
139
- currentState: GridLoaderStates<T>,
140
- newState: Partial<GridLoaderStates<T>>
141
- ) => {
142
- return { ...currentState, ...newState };
143
- },
144
- {
145
- autoLoad,
146
- currentPage: 0,
147
- hasNextPage: true,
148
- isNextPageLoading: false,
149
- orderBy: defaultOrderBy,
150
- orderByAsc: defaultOrderByAsc,
151
- rows: [],
152
- batchSize: GridSizeGet(loadBatchSize, height),
153
- selectedItems: []
154
- }
155
- );
156
- const isMounted = React.useRef(true);
144
+ const stateRefs = React.useRef<GridLoaderStates<T>>({
145
+ autoLoad,
146
+ currentPage: 0,
147
+ loadedItems: 0,
148
+ hasNextPage: true,
149
+ isNextPageLoading: false,
150
+ orderBy: defaultOrderBy,
151
+ orderByAsc: defaultOrderByAsc,
152
+ batchSize: GridSizeGet(loadBatchSize, height),
153
+ selectedItems: []
154
+ });
155
+ const state = stateRefs.current;
157
156
 
158
157
  // Load data
159
158
  const loadDataLocal = (pageAdd: number = 1) => {
@@ -162,10 +161,10 @@ export const ScrollerList = <T extends Record<string, any>>(
162
161
 
163
162
  // Update state
164
163
  state.isNextPageLoading = true;
165
- // stateUpdate({ isNextPageLoading: true });
166
164
 
167
165
  // Parameters
168
- const { currentPage, batchSize, orderBy, orderByAsc, data } = state;
166
+ const { currentPage, batchSize, orderBy, orderByAsc, data, isMounted } =
167
+ state;
169
168
 
170
169
  const loadProps: GridLoadDataProps = {
171
170
  currentPage,
@@ -176,38 +175,35 @@ export const ScrollerList = <T extends Record<string, any>>(
176
175
  };
177
176
 
178
177
  loadData(loadProps).then((result) => {
179
- if (result == null || !isMounted.current) {
178
+ state.isMounted = true;
179
+
180
+ if (result == null || isMounted === false) {
180
181
  return;
181
182
  }
182
183
 
183
184
  const newItems = result.length;
185
+ state.lastLoadedItems = newItems;
186
+ state.hasNextPage = newItems >= loadBatchSize;
187
+ state.isNextPageLoading = false;
184
188
 
185
189
  if (pageAdd === 0) {
186
190
  // New items
187
- const rows = state.lastLoadedItems
188
- ? state.rows
191
+ const newRows = state.lastLoadedItems
192
+ ? [...rows]
189
193
  .splice(
190
- state.rows.length - state.lastLoadedItems,
194
+ rows.length - state.lastLoadedItems,
191
195
  state.lastLoadedItems
192
196
  )
193
197
  .concat(result)
194
198
  : result;
195
199
 
196
- // Refresh current page
197
- stateUpdate({
198
- rows,
199
- lastLoadedItems: newItems,
200
- hasNextPage: newItems >= loadBatchSize,
201
- isNextPageLoading: false
202
- });
200
+ // Update rows
201
+ setRows(newRows);
203
202
  } else {
204
- stateUpdate({
205
- rows: state.rows.concat(result),
206
- lastLoadedItems: newItems,
207
- currentPage: state.currentPage + pageAdd,
208
- hasNextPage: newItems >= loadBatchSize,
209
- isNextPageLoading: false
210
- });
203
+ state.currentPage = state.currentPage + pageAdd;
204
+
205
+ // Update rows
206
+ setRows([...rows, ...result]);
211
207
  }
212
208
  });
213
209
  };
@@ -216,7 +212,7 @@ export const ScrollerList = <T extends Record<string, any>>(
216
212
  // Custom render
217
213
  return itemRenderer({
218
214
  ...itemProps,
219
- data: state.rows[itemProps.index]
215
+ data: rows[itemProps.index]
220
216
  });
221
217
  };
222
218
 
@@ -241,17 +237,17 @@ export const ScrollerList = <T extends Record<string, any>>(
241
237
  loadDataLocal(0);
242
238
  },
243
239
 
244
- reset(add?: {}): void {
245
- // Reset state, will load data soon
246
- stateUpdate({
240
+ reset(add?: Partial<GridLoaderStates<T>>): void {
241
+ const resetState: Partial<GridLoaderStates<T>> = {
247
242
  autoLoad: true,
248
- rows: [],
249
243
  lastLoadedItems: undefined,
244
+ loadedItems: 0,
250
245
  currentPage: 0,
251
246
  hasNextPage: true,
252
247
  isNextPageLoading: false,
253
248
  ...add
254
- });
249
+ };
250
+ Object.assign(state, resetState);
255
251
  },
256
252
 
257
253
  scrollTo(scrollOffset: number): void {
@@ -298,12 +294,12 @@ export const ScrollerList = <T extends Record<string, any>>(
298
294
  // Remove scroll event
299
295
  window.removeEventListener('scroll', handleWindowScroll);
300
296
 
301
- isMounted.current = false;
297
+ state.isMounted = false;
302
298
  };
303
299
  }, []);
304
300
 
305
301
  // Destruct state
306
- const { autoLoad: stateAutoLoad, rows, hasNextPage, currentPage } = state;
302
+ const { autoLoad: stateAutoLoad, hasNextPage, currentPage } = state;
307
303
  const rowCount = rows.length;
308
304
 
309
305
  // Local items renderer callback
@@ -24,8 +24,6 @@ import {
24
24
  ScrollerGridProps
25
25
  } from '../components/ScrollerGrid';
26
26
  import useCombinedRefs from '../uses/useCombinedRefs';
27
- import { useDimensions } from '../uses/useDimensions';
28
- import { useWindowSize } from '../uses/useWindowSize';
29
27
  import { DataGridRenderers } from './DataGridRenderers';
30
28
 
31
29
  /**
@@ -79,6 +77,7 @@ export interface DataGridExProps<T extends Record<string, any>>
79
77
  * Footer item renderer
80
78
  */
81
79
  footerItemRenderer?: (
80
+ rows: T[],
82
81
  props: DataGridExFooterItemRendererProps<T>
83
82
  ) => React.ReactNode;
84
83
 
@@ -152,11 +151,6 @@ const createGridStyle = (
152
151
  });
153
152
  };
154
153
 
155
- interface States {
156
- gridWidth?: number;
157
- ref?: ScrollerGridForwardRef;
158
- }
159
-
160
154
  const rowItems = (
161
155
  div: HTMLDivElement,
162
156
  callback: (div: HTMLDivElement) => void
@@ -290,7 +284,7 @@ export function DataGridEx<T extends Record<string, any>>(
290
284
  );
291
285
  };
292
286
 
293
- function defaultFooterRenderer(states: GridLoaderStates<T>) {
287
+ function defaultFooterRenderer(rows: T[], states: GridLoaderStates<T>) {
294
288
  return (
295
289
  <Box
296
290
  className="DataGridEx-Footer"
@@ -310,7 +304,7 @@ export function DataGridEx<T extends Record<string, any>>(
310
304
 
311
305
  // Cell
312
306
  const cell = footerItemRenderer
313
- ? footerItemRenderer({
307
+ ? footerItemRenderer(rows, {
314
308
  column,
315
309
  index,
316
310
  states,
@@ -383,7 +377,7 @@ export function DataGridEx<T extends Record<string, any>>(
383
377
  color="primary"
384
378
  checked={selected}
385
379
  onChange={(_event, checked) => {
386
- state.ref?.selectItem(data, checked);
380
+ refs.current.ref?.selectItem(data, checked);
387
381
  }}
388
382
  />
389
383
  );
@@ -403,11 +397,11 @@ export function DataGridEx<T extends Record<string, any>>(
403
397
  color="primary"
404
398
  indeterminate={
405
399
  states.selectedItems.length > 0 &&
406
- states.selectedItems.length < states.rows.length
400
+ states.selectedItems.length < states.loadedItems
407
401
  }
408
402
  checked={states.selectedItems.length > 0}
409
403
  onChange={(_event, checked) =>
410
- state.ref?.selectAll(checked)
404
+ refs.current.ref?.selectAll(checked)
411
405
  }
412
406
  />
413
407
  );
@@ -422,19 +416,11 @@ export function DataGridEx<T extends Record<string, any>>(
422
416
  }
423
417
  }
424
418
 
425
- // States
426
- const [state, stateUpdate] = React.useReducer(
427
- (currentState: States, newState: Partial<States>) => {
428
- return { ...currentState, ...newState };
429
- },
430
- {
431
- gridWidth: width
432
- }
433
- );
419
+ const refs = React.useRef<{ ref?: ScrollerGridForwardRef }>({});
434
420
 
435
- const refs = useCombinedRefs(mRef, (ref: ScrollerGridForwardRef) => {
421
+ const mRefLocal = useCombinedRefs(mRef, (ref: ScrollerGridForwardRef) => {
436
422
  if (ref == null) return;
437
- state.ref = ref;
423
+ refs.current.ref = ref;
438
424
  });
439
425
 
440
426
  // New sort
@@ -442,8 +428,9 @@ export function DataGridEx<T extends Record<string, any>>(
442
428
  reset({ orderBy: field, orderByAsc: asc });
443
429
  };
444
430
 
431
+ // Reset
445
432
  const reset = (add: {}) => {
446
- state.ref?.reset(add);
433
+ refs.current.ref?.reset(add);
447
434
  };
448
435
 
449
436
  // Show hover tooltip for trucated text
@@ -594,14 +581,11 @@ export function DataGridEx<T extends Record<string, any>>(
594
581
  [columns]
595
582
  );
596
583
 
597
- // Grid width
598
- const { gridWidth } = state;
599
-
600
584
  // Column width
601
585
  const columnWidth = React.useCallback(
602
586
  (index: number) => {
603
587
  // Ignore null case
604
- if (gridWidth == null) return 0;
588
+ if (width == null) return 0;
605
589
 
606
590
  // Column
607
591
  const column = columns[index];
@@ -609,9 +593,9 @@ export function DataGridEx<T extends Record<string, any>>(
609
593
 
610
594
  // More space
611
595
  const leftWidth =
612
- gridWidth -
596
+ width -
613
597
  widthCalculator.total -
614
- (gridWidth < 800 ? 0 : scrollbarSize);
598
+ (width < 800 ? 0 : scrollbarSize);
615
599
 
616
600
  // Shared width
617
601
  const sharedWidth =
@@ -619,74 +603,50 @@ export function DataGridEx<T extends Record<string, any>>(
619
603
 
620
604
  return (column.minWidth || minWidth) + sharedWidth;
621
605
  },
622
- [columns, gridWidth]
606
+ [columns, width]
623
607
  );
624
608
 
625
609
  // Table
626
610
  const table = React.useMemo(() => {
627
- if (gridWidth != null) {
628
- const defaultOrderByAsc = defaultOrderBy
629
- ? columns.find((column) => column.field === defaultOrderBy)
630
- ?.sortAsc
631
- : undefined;
632
-
633
- return (
634
- <ScrollerGrid<T>
635
- className={Utils.mergeClasses(
636
- 'DataGridEx-Body',
637
- 'DataGridEx-CustomBar',
638
- className,
639
- createGridStyle(
640
- alternatingColors,
641
- selectedColor,
642
- hoverColor
643
- )
644
- )}
645
- columnCount={columns.length}
646
- columnWidth={columnWidth}
647
- defaultOrderBy={defaultOrderBy}
648
- defaultOrderByAsc={defaultOrderByAsc}
649
- height={
650
- height -
651
- headerHeight -
652
- (hideFooter ? 0 : bottomHeight + 1) -
653
- scrollbarSize
654
- }
655
- headerRenderer={headerRenderer}
656
- idField={idField}
657
- itemRenderer={itemRenderer}
658
- footerRenderer={hideFooter ? undefined : footerRenderer}
659
- width={Math.max(gridWidth, widthCalculator.total)}
660
- mRef={refs}
661
- {...rest}
662
- />
663
- );
664
- }
665
- }, [gridWidth]);
611
+ const defaultOrderByAsc = defaultOrderBy
612
+ ? columns.find((column) => column.field === defaultOrderBy)?.sortAsc
613
+ : undefined;
666
614
 
667
- // Watch container
668
- const { dimensions } = useDimensions(1, undefined, 50);
669
- const gridRect = dimensions[0][2];
670
-
671
- const windowSize = useWindowSize(50);
672
-
673
- React.useEffect(() => {
674
- if (gridRect == null || width != null) return;
675
-
676
- // Reset column widths
677
- if (state.ref) state.ref.resetAfterColumnIndex(0);
678
-
679
- const body = window.document.body;
680
- const scrollWidth = body.scrollWidth - body.clientWidth;
681
-
682
- stateUpdate({
683
- gridWidth: gridRect.width - scrollWidth
684
- });
685
- }, [gridRect, windowSize]);
615
+ return (
616
+ <ScrollerGrid<T>
617
+ className={Utils.mergeClasses(
618
+ 'DataGridEx-Body',
619
+ 'DataGridEx-CustomBar',
620
+ className,
621
+ createGridStyle(
622
+ alternatingColors,
623
+ selectedColor,
624
+ hoverColor
625
+ )
626
+ )}
627
+ columnCount={columns.length}
628
+ columnWidth={columnWidth}
629
+ defaultOrderBy={defaultOrderBy}
630
+ defaultOrderByAsc={defaultOrderByAsc}
631
+ height={
632
+ height -
633
+ headerHeight -
634
+ (hideFooter ? 0 : bottomHeight + 1) -
635
+ scrollbarSize
636
+ }
637
+ headerRenderer={headerRenderer}
638
+ idField={idField}
639
+ itemRenderer={itemRenderer}
640
+ footerRenderer={hideFooter ? undefined : footerRenderer}
641
+ width={Math.max(width ?? 0, widthCalculator.total)}
642
+ mRef={mRefLocal}
643
+ {...rest}
644
+ />
645
+ );
646
+ }, [width]);
686
647
 
687
648
  return (
688
649
  <Paper
689
- ref={dimensions[0][0]}
690
650
  sx={{
691
651
  fontSize: '0.875rem',
692
652
  height,
@@ -720,7 +680,7 @@ export function DataGridEx<T extends Record<string, any>>(
720
680
  <div
721
681
  className="DataGridEx-CustomBar"
722
682
  style={{
723
- width: gridWidth,
683
+ width,
724
684
  overflowX: 'auto',
725
685
  overflowY: 'hidden'
726
686
  }}