@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.
@@ -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
  }}
@@ -115,22 +115,21 @@ export namespace DataGridRenderers {
115
115
  * @param param Props
116
116
  * @returns Component
117
117
  */
118
- export function defaultFooterItemRenderer<T>({
119
- index,
120
- states,
121
- checkable
122
- }: DataGridExFooterItemRendererProps<T>) {
123
- const { selectedItems, rows, hasNextPage } = states;
118
+ export function defaultFooterItemRenderer<T>(
119
+ _rows: T[],
120
+ { index, states, checkable }: DataGridExFooterItemRendererProps<T>
121
+ ) {
122
+ const { selectedItems, loadedItems, hasNextPage } = states;
124
123
 
125
124
  if (checkable && index === 1) {
126
125
  return [
127
126
  selectedItems.length,
128
- rows.length.toLocaleString() + (hasNextPage ? '+' : '')
127
+ loadedItems.toLocaleString() + (hasNextPage ? '+' : '')
129
128
  ].join(' / ');
130
129
  }
131
130
 
132
131
  if (!checkable && index === 0) {
133
- return rows.length.toLocaleString() + (hasNextPage ? '+' : '');
132
+ return loadedItems.toLocaleString() + (hasNextPage ? '+' : '');
134
133
  }
135
134
 
136
135
  return undefined;
@@ -1,3 +1,5 @@
1
+ import { GridLoaderStates } from '../components/GridLoader';
2
+
1
3
  /**
2
4
  * Grid method ref
3
5
  */
@@ -6,5 +8,5 @@ export interface GridMethodRef {
6
8
  * Reset
7
9
  * @param add Additional data
8
10
  */
9
- reset(add?: {}): void;
11
+ reset(add?: Partial<GridLoaderStates<unknown>>): void;
10
12
  }