@etsoo/react 1.6.79 → 1.6.81

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.
@@ -69,6 +69,18 @@ export type GridLoader<T extends object> = {
69
69
  * Load data
70
70
  */
71
71
  loadData: (props: GridLoadDataProps) => PromiseLike<T[] | null | undefined>;
72
+ /**
73
+ * Handler for init load
74
+ * @param ref Ref
75
+ * @returns Result
76
+ */
77
+ onInitLoad?: (ref: any) => [T[], Partial<GridLoaderStates<T>>?] | null | undefined;
78
+ /**
79
+ * Handler for updating rows
80
+ * @param rows Rows
81
+ * @param state State
82
+ */
83
+ onUpdateRows?: (rows: T[], state: GridLoaderStates<T>) => void;
72
84
  /**
73
85
  * Threshold at which to pre-fetch data; default is half of loadBatchSize
74
86
  */
@@ -7,12 +7,14 @@ import { VariableSizeGrid } from 'react-window';
7
7
  */
8
8
  export const ScrollerGrid = (props) => {
9
9
  // Destruct
10
- const { autoLoad = true, defaultOrderBy, defaultOrderByAsc, footerRenderer, headerRenderer, itemRenderer, idField = 'id', loadBatchSize, loadData, mRef, onItemsRendered, onSelectChange, rowHeight = 53, threshold = 6, width, ...rest } = props;
10
+ const { autoLoad = true, defaultOrderBy, defaultOrderByAsc, footerRenderer, headerRenderer, itemRenderer, idField = 'id', loadBatchSize, loadData, mRef, onItemsRendered, onSelectChange, rowHeight = 53, threshold = 6, width, onInitLoad, onUpdateRows, ...rest } = props;
11
11
  // Rows
12
12
  const [rows, updateRows] = React.useState([]);
13
13
  const setRows = (rows) => {
14
14
  state.loadedItems = rows.length;
15
15
  updateRows(rows);
16
+ if (onUpdateRows)
17
+ onUpdateRows(rows, state);
16
18
  };
17
19
  // Refs
18
20
  const refs = React.useRef({
@@ -116,7 +118,7 @@ export const ScrollerGrid = (props) => {
116
118
  onItemsRendered(props);
117
119
  };
118
120
  // Reset the state and load again
119
- const reset = (add) => {
121
+ const reset = (add, items = []) => {
120
122
  const resetState = {
121
123
  autoLoad: true,
122
124
  currentPage: 0,
@@ -129,7 +131,7 @@ export const ScrollerGrid = (props) => {
129
131
  Object.assign(state, resetState);
130
132
  // Reset items
131
133
  if (state.isMounted !== false)
132
- setRows([]);
134
+ setRows(items);
133
135
  };
134
136
  const instance = {
135
137
  scrollTo(params) {
@@ -210,8 +212,13 @@ export const ScrollerGrid = (props) => {
210
212
  // Row count
211
213
  const rowCount = state.hasNextPage ? rowLength + 1 : rowLength;
212
214
  // Auto load data when current page is 0
213
- if (state.currentPage === 0 && state.autoLoad)
214
- loadDataLocal();
215
+ if (state.currentPage === 0 && state.autoLoad) {
216
+ const initItems = onInitLoad == null ? undefined : onInitLoad(ref.current);
217
+ if (initItems)
218
+ reset(initItems[1], initItems[0]);
219
+ else
220
+ loadDataLocal();
221
+ }
215
222
  // Layout
216
223
  return (React.createElement(React.Fragment, null,
217
224
  headerRenderer && headerRenderer(state),
@@ -15,7 +15,7 @@ const calculateBatchSize = (height, itemSize) => {
15
15
  */
16
16
  export const ScrollerList = (props) => {
17
17
  // Destruct
18
- const { autoLoad = true, defaultOrderBy, defaultOrderByAsc, height = document.documentElement.clientHeight, width = '100%', mRef, oRef, style = {}, idField = 'id', itemRenderer, itemSize, loadBatchSize = calculateBatchSize(height, itemSize), loadData, threshold = GridSizeGet(loadBatchSize, height) / 2, onItemsRendered, ...rest } = props;
18
+ const { autoLoad = true, defaultOrderBy, defaultOrderByAsc, height = document.documentElement.clientHeight, width = '100%', mRef, oRef, style = {}, idField = 'id', itemRenderer, itemSize, loadBatchSize = calculateBatchSize(height, itemSize), loadData, threshold = GridSizeGet(loadBatchSize, height) / 2, onItemsRendered, onInitLoad, onUpdateRows, ...rest } = props;
19
19
  // Style
20
20
  Object.assign(style, {
21
21
  width: '100%',
@@ -31,6 +31,8 @@ export const ScrollerList = (props) => {
31
31
  const setRows = (rows) => {
32
32
  state.loadedItems = rows.length;
33
33
  updateRows(rows);
34
+ if (onUpdateRows)
35
+ onUpdateRows(rows, state);
34
36
  };
35
37
  // States
36
38
  const batchSize = GridSizeGet(loadBatchSize, height);
@@ -108,14 +110,21 @@ export const ScrollerList = (props) => {
108
110
  data: rows[itemProps.index]
109
111
  });
110
112
  };
111
- // Update scroll location
112
- const updateScroll = (scrollY) => {
113
- const outerItem = outerRef.current;
114
- const refMethods = listRef.current;
115
- if (outerItem == null || refMethods == null)
116
- return;
117
- const scrollTop = scrollY - outerItem.offsetTop;
118
- refMethods.scrollTo(scrollTop);
113
+ // Reset the state and load again
114
+ const reset = (add, items = []) => {
115
+ const resetState = {
116
+ autoLoad: true,
117
+ lastLoadedItems: undefined,
118
+ loadedItems: 0,
119
+ currentPage: 0,
120
+ hasNextPage: true,
121
+ isNextPageLoading: false,
122
+ ...add
123
+ };
124
+ Object.assign(state, resetState);
125
+ // Reset
126
+ if (state.isMounted !== false)
127
+ setRows(items);
119
128
  };
120
129
  React.useImperativeHandle(mRef, () => {
121
130
  const refMethods = listRef.current;
@@ -123,21 +132,7 @@ export const ScrollerList = (props) => {
123
132
  refresh() {
124
133
  loadDataLocal(0);
125
134
  },
126
- reset(add) {
127
- const resetState = {
128
- autoLoad: true,
129
- lastLoadedItems: undefined,
130
- loadedItems: 0,
131
- currentPage: 0,
132
- hasNextPage: true,
133
- isNextPageLoading: false,
134
- ...add
135
- };
136
- Object.assign(state, resetState);
137
- // Reset
138
- if (state.isMounted !== false)
139
- setRows([]);
140
- },
135
+ reset,
141
136
  scrollTo(scrollOffset) {
142
137
  refMethods.scrollTo(scrollOffset);
143
138
  },
@@ -148,30 +143,8 @@ export const ScrollerList = (props) => {
148
143
  }, []);
149
144
  // When layout ready
150
145
  React.useEffect(() => {
151
- let ticking = false;
152
- let lastKnownScrollPosition = 0;
153
- let requestAnimationFrameSeed = 0;
154
- // Window scroll handler
155
- const handleWindowScroll = () => {
156
- lastKnownScrollPosition = window.scrollY;
157
- if (!ticking) {
158
- requestAnimationFrameSeed = window.requestAnimationFrame(() => {
159
- updateScroll(lastKnownScrollPosition);
160
- ticking = false;
161
- requestAnimationFrameSeed = 0;
162
- });
163
- ticking = true;
164
- }
165
- };
166
- // Add scroll event
167
- window.addEventListener('scroll', handleWindowScroll);
168
146
  // Return clear function
169
147
  return () => {
170
- // Cancel animation frame
171
- if (requestAnimationFrameSeed > 0)
172
- window.cancelAnimationFrame(requestAnimationFrameSeed);
173
- // Remove scroll event
174
- window.removeEventListener('scroll', handleWindowScroll);
175
148
  state.isMounted = false;
176
149
  };
177
150
  }, []);
@@ -191,8 +164,13 @@ export const ScrollerList = (props) => {
191
164
  // Item count
192
165
  const itemCount = state.hasNextPage ? rowCount + 1 : rowCount;
193
166
  // Auto load data when current page is 0
194
- if (state.currentPage === 0 && state.autoLoad)
195
- loadDataLocal();
167
+ if (state.currentPage === 0 && state.autoLoad) {
168
+ const initItems = onInitLoad == null ? undefined : onInitLoad(listRef.current);
169
+ if (initItems)
170
+ reset(initItems[1], initItems[0]);
171
+ else
172
+ loadDataLocal();
173
+ }
196
174
  // Layout
197
175
  return typeof itemSize === 'function' ? (React.createElement(VariableSizeList, { height: height, width: width, itemCount: itemCount, itemKey: (index, data) => { var _a; return (_a = DataTypes.getIdValue1(data, idField)) !== null && _a !== void 0 ? _a : index; }, itemSize: itemSize, outerRef: refs, ref: listRef, style: style, onItemsRendered: onItemsRenderedLocal, ...rest }, itemRendererLocal)) : (React.createElement(FixedSizeList, { height: height, width: width, itemCount: itemCount, itemKey: (index, data) => { var _a; return (_a = DataTypes.getIdValue1(data, idField)) !== null && _a !== void 0 ? _a : index; }, itemSize: itemSize, outerRef: refs, ref: listRef, style: style, onItemsRendered: onItemsRenderedLocal, ...rest }, itemRendererLocal));
198
176
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/react",
3
- "version": "1.6.79",
3
+ "version": "1.6.81",
4
4
  "description": "TypeScript ReactJs UI Independent Framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -50,7 +50,7 @@
50
50
  "@emotion/css": "^11.11.0",
51
51
  "@emotion/react": "^11.11.0",
52
52
  "@emotion/styled": "^11.11.0",
53
- "@etsoo/appscript": "^1.4.5",
53
+ "@etsoo/appscript": "^1.4.8",
54
54
  "@etsoo/notificationbase": "^1.1.25",
55
55
  "@etsoo/shared": "^1.2.5",
56
56
  "@types/react": "^18.2.6",
@@ -105,6 +105,22 @@ export type GridLoader<T extends object> = {
105
105
  */
106
106
  loadData: (props: GridLoadDataProps) => PromiseLike<T[] | null | undefined>;
107
107
 
108
+ /**
109
+ * Handler for init load
110
+ * @param ref Ref
111
+ * @returns Result
112
+ */
113
+ onInitLoad?: (
114
+ ref: any
115
+ ) => [T[], Partial<GridLoaderStates<T>>?] | null | undefined;
116
+
117
+ /**
118
+ * Handler for updating rows
119
+ * @param rows Rows
120
+ * @param state State
121
+ */
122
+ onUpdateRows?: (rows: T[], state: GridLoaderStates<T>) => void;
123
+
108
124
  /**
109
125
  * Threshold at which to pre-fetch data; default is half of loadBatchSize
110
126
  */
@@ -181,6 +181,8 @@ export const ScrollerGrid = <
181
181
  rowHeight = 53,
182
182
  threshold = 6,
183
183
  width,
184
+ onInitLoad,
185
+ onUpdateRows,
184
186
  ...rest
185
187
  } = props;
186
188
 
@@ -189,6 +191,8 @@ export const ScrollerGrid = <
189
191
  const setRows = (rows: T[]) => {
190
192
  state.loadedItems = rows.length;
191
193
  updateRows(rows);
194
+
195
+ if (onUpdateRows) onUpdateRows(rows, state);
192
196
  };
193
197
 
194
198
  // Refs
@@ -320,7 +324,7 @@ export const ScrollerGrid = <
320
324
  };
321
325
 
322
326
  // Reset the state and load again
323
- const reset = (add?: Partial<GridLoaderStates<T>>) => {
327
+ const reset = (add?: Partial<GridLoaderStates<T>>, items: T[] = []) => {
324
328
  const resetState: Partial<GridLoaderStates<T>> = {
325
329
  autoLoad: true,
326
330
  currentPage: 0,
@@ -333,7 +337,7 @@ export const ScrollerGrid = <
333
337
  Object.assign(state, resetState);
334
338
 
335
339
  // Reset items
336
- if (state.isMounted !== false) setRows([]);
340
+ if (state.isMounted !== false) setRows(items);
337
341
  };
338
342
 
339
343
  const instance: ScrollerGridForwardRef<T> = {
@@ -425,7 +429,12 @@ export const ScrollerGrid = <
425
429
  const rowCount = state.hasNextPage ? rowLength + 1 : rowLength;
426
430
 
427
431
  // Auto load data when current page is 0
428
- if (state.currentPage === 0 && state.autoLoad) loadDataLocal();
432
+ if (state.currentPage === 0 && state.autoLoad) {
433
+ const initItems =
434
+ onInitLoad == null ? undefined : onInitLoad(ref.current);
435
+ if (initItems) reset(initItems[1], initItems[0]);
436
+ else loadDataLocal();
437
+ }
429
438
 
430
439
  // Layout
431
440
  return (
@@ -130,6 +130,8 @@ export const ScrollerList = <
130
130
  loadData,
131
131
  threshold = GridSizeGet(loadBatchSize, height) / 2,
132
132
  onItemsRendered,
133
+ onInitLoad,
134
+ onUpdateRows,
133
135
  ...rest
134
136
  } = props;
135
137
 
@@ -151,6 +153,8 @@ export const ScrollerList = <
151
153
  const setRows = (rows: T[]) => {
152
154
  state.loadedItems = rows.length;
153
155
  updateRows(rows);
156
+
157
+ if (onUpdateRows) onUpdateRows(rows, state);
154
158
  };
155
159
 
156
160
  // States
@@ -244,15 +248,21 @@ export const ScrollerList = <
244
248
  });
245
249
  };
246
250
 
247
- // Update scroll location
248
- const updateScroll = (scrollY: number) => {
249
- const outerItem = outerRef.current;
250
- const refMethods = listRef.current as ScrollerListRef;
251
- if (outerItem == null || refMethods == null) return;
252
-
253
- const scrollTop = scrollY - outerItem.offsetTop;
251
+ // Reset the state and load again
252
+ const reset = (add?: Partial<GridLoaderStates<T>>, items: T[] = []) => {
253
+ const resetState: Partial<GridLoaderStates<T>> = {
254
+ autoLoad: true,
255
+ lastLoadedItems: undefined,
256
+ loadedItems: 0,
257
+ currentPage: 0,
258
+ hasNextPage: true,
259
+ isNextPageLoading: false,
260
+ ...add
261
+ };
262
+ Object.assign(state, resetState);
254
263
 
255
- refMethods.scrollTo(scrollTop);
264
+ // Reset
265
+ if (state.isMounted !== false) setRows(items);
256
266
  };
257
267
 
258
268
  React.useImperativeHandle(
@@ -265,21 +275,7 @@ export const ScrollerList = <
265
275
  loadDataLocal(0);
266
276
  },
267
277
 
268
- reset(add?: Partial<GridLoaderStates<T>>): void {
269
- const resetState: Partial<GridLoaderStates<T>> = {
270
- autoLoad: true,
271
- lastLoadedItems: undefined,
272
- loadedItems: 0,
273
- currentPage: 0,
274
- hasNextPage: true,
275
- isNextPageLoading: false,
276
- ...add
277
- };
278
- Object.assign(state, resetState);
279
-
280
- // Reset
281
- if (state.isMounted !== false) setRows([]);
282
- },
278
+ reset,
283
279
 
284
280
  scrollTo(scrollOffset: number): void {
285
281
  refMethods.scrollTo(scrollOffset);
@@ -295,36 +291,8 @@ export const ScrollerList = <
295
291
 
296
292
  // When layout ready
297
293
  React.useEffect(() => {
298
- let ticking = false;
299
- let lastKnownScrollPosition = 0;
300
- let requestAnimationFrameSeed = 0;
301
-
302
- // Window scroll handler
303
- const handleWindowScroll = () => {
304
- lastKnownScrollPosition = window.scrollY;
305
-
306
- if (!ticking) {
307
- requestAnimationFrameSeed = window.requestAnimationFrame(() => {
308
- updateScroll(lastKnownScrollPosition);
309
- ticking = false;
310
- requestAnimationFrameSeed = 0;
311
- });
312
- ticking = true;
313
- }
314
- };
315
-
316
- // Add scroll event
317
- window.addEventListener('scroll', handleWindowScroll);
318
-
319
294
  // Return clear function
320
295
  return () => {
321
- // Cancel animation frame
322
- if (requestAnimationFrameSeed > 0)
323
- window.cancelAnimationFrame(requestAnimationFrameSeed);
324
-
325
- // Remove scroll event
326
- window.removeEventListener('scroll', handleWindowScroll);
327
-
328
296
  state.isMounted = false;
329
297
  };
330
298
  }, []);
@@ -349,7 +317,12 @@ export const ScrollerList = <
349
317
  const itemCount = state.hasNextPage ? rowCount + 1 : rowCount;
350
318
 
351
319
  // Auto load data when current page is 0
352
- if (state.currentPage === 0 && state.autoLoad) loadDataLocal();
320
+ if (state.currentPage === 0 && state.autoLoad) {
321
+ const initItems =
322
+ onInitLoad == null ? undefined : onInitLoad(listRef.current);
323
+ if (initItems) reset(initItems[1], initItems[0]);
324
+ else loadDataLocal();
325
+ }
353
326
 
354
327
  // Layout
355
328
  return typeof itemSize === 'function' ? (