@etsoo/react 1.8.51 → 1.8.52

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,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from "react";
3
- import { VariableSizeGrid } from "react-window";
3
+ import { Grid, useGridRef } from "react-window";
4
+ import { useCombinedRefs } from "../uses/useCombinedRefs";
4
5
  /**
5
6
  * Scroller vertical grid
6
7
  * @param props Props
@@ -8,17 +9,26 @@ import { VariableSizeGrid } from "react-window";
8
9
  */
9
10
  export const ScrollerGrid = (props) => {
10
11
  // Destruct
11
- const { autoLoad = true, defaultOrderBy, footerRenderer, headerRenderer, itemRenderer, idField = "id", loadBatchSize, loadData, mRef, onItemsRendered, onSelectChange, rowHeight = 53, threshold = 6, width, onInitLoad, onUpdateRows, ...rest } = props;
12
+ const { autoLoad = true, defaultOrderBy, footerRenderer, headerRenderer, height = "100%", gridRef, width = "100%", style = {}, idField = "id", loadBatchSize, loadData, mRef, onCellsRendered, onSelectChange, rowHeight = 53, threshold = 3, onInitLoad, onUpdateRows, ...rest } = props;
13
+ // Style
14
+ Object.assign(style, {
15
+ width,
16
+ height,
17
+ overflowX: "hidden"
18
+ });
19
+ // Refs
20
+ const localRef = useGridRef(null);
21
+ const refs = useCombinedRefs(gridRef, localRef);
12
22
  // Rows
13
23
  const [rows, updateRows] = React.useState([]);
14
24
  const setRows = (rows, reset = false) => {
15
- refs.current.loadedItems = rows.length;
25
+ stateRefs.current.loadedItems = rows.length;
16
26
  updateRows(rows);
17
27
  if (!reset && onUpdateRows)
18
- onUpdateRows(rows, refs.current);
28
+ onUpdateRows(rows, stateRefs.current);
19
29
  };
20
- // Refs
21
- const refs = React.useRef({
30
+ // State Refs
31
+ const stateRefs = React.useRef({
22
32
  queryPaging: {
23
33
  currentPage: 0,
24
34
  orderBy: defaultOrderBy,
@@ -31,58 +41,58 @@ export const ScrollerGrid = (props) => {
31
41
  selectedItems: [],
32
42
  idCache: {}
33
43
  });
34
- const ref = React.useRef(null);
35
44
  // Load data
36
45
  const loadDataLocal = (pageAdd = 1) => {
37
46
  // Prevent multiple loadings
38
- if (!refs.current.hasNextPage ||
39
- refs.current.isNextPageLoading ||
40
- refs.current.isMounted === false)
47
+ if (!stateRefs.current.hasNextPage ||
48
+ stateRefs.current.isNextPageLoading ||
49
+ stateRefs.current.isMounted === false)
41
50
  return;
42
51
  // Update state
43
- refs.current.isNextPageLoading = true;
52
+ stateRefs.current.isNextPageLoading = true;
44
53
  // Parameters
45
- const { queryPaging, data } = refs.current;
54
+ const { queryPaging, data } = stateRefs.current;
46
55
  const loadProps = {
47
56
  queryPaging,
48
57
  data
49
58
  };
50
- loadData(loadProps, refs.current.lastItem).then((result) => {
51
- if (result == null || refs.current.isMounted === false) {
59
+ loadData(loadProps, stateRefs.current.lastItem).then((result) => {
60
+ if (result == null || stateRefs.current.isMounted === false) {
52
61
  return;
53
62
  }
54
- refs.current.isMounted = true;
63
+ stateRefs.current.isMounted = true;
55
64
  const newItems = result.length;
56
- refs.current.lastLoadedItems = newItems;
57
- refs.current.lastItem = result.at(-1);
58
- refs.current.isNextPageLoading = false;
59
- refs.current.hasNextPage = newItems >= refs.current.queryPaging.batchSize;
65
+ stateRefs.current.lastLoadedItems = newItems;
66
+ stateRefs.current.lastItem = result.at(-1);
67
+ stateRefs.current.isNextPageLoading = false;
68
+ stateRefs.current.hasNextPage =
69
+ newItems >= stateRefs.current.queryPaging.batchSize;
60
70
  if (pageAdd === 0) {
61
71
  // New items
62
- const newRows = refs.current.lastLoadedItems
72
+ const newRows = stateRefs.current.lastLoadedItems
63
73
  ? [...rows]
64
- .splice(rows.length - refs.current.lastLoadedItems, refs.current.lastLoadedItems)
74
+ .splice(rows.length - stateRefs.current.lastLoadedItems, stateRefs.current.lastLoadedItems)
65
75
  .concat(result)
66
76
  : result;
67
- refs.current.idCache = {};
77
+ stateRefs.current.idCache = {};
68
78
  for (const row of newRows) {
69
79
  const id = row[idField];
70
- refs.current.idCache[id] = null;
80
+ stateRefs.current.idCache[id] = null;
71
81
  }
72
82
  // Update rows
73
83
  setRows(newRows);
74
84
  }
75
85
  else {
76
86
  // Set current page
77
- if (refs.current.queryPaging.currentPage == null)
78
- refs.current.queryPaging.currentPage = pageAdd;
87
+ if (stateRefs.current.queryPaging.currentPage == null)
88
+ stateRefs.current.queryPaging.currentPage = pageAdd;
79
89
  else
80
- refs.current.queryPaging.currentPage += pageAdd;
90
+ stateRefs.current.queryPaging.currentPage += pageAdd;
81
91
  // Update rows, avoid duplicate items
82
92
  const newRows = [...rows];
83
93
  for (const item of result) {
84
94
  const id = item[idField];
85
- if (refs.current.idCache[id] === undefined) {
95
+ if (stateRefs.current.idCache[id] === undefined) {
86
96
  newRows.push(item);
87
97
  }
88
98
  }
@@ -90,34 +100,6 @@ export const ScrollerGrid = (props) => {
90
100
  }
91
101
  });
92
102
  };
93
- // Item renderer
94
- const itemRendererLocal = (itemProps, state) => {
95
- // Custom render
96
- const data = itemProps.rowIndex < rows.length ? rows[itemProps.rowIndex] : undefined;
97
- return itemRenderer({
98
- ...itemProps,
99
- data,
100
- selectedItems: state.selectedItems,
101
- setItems: (callback) => {
102
- const result = callback(rows, instance);
103
- if (result == null)
104
- return;
105
- setRows(result);
106
- }
107
- });
108
- };
109
- // Local items renderer callback
110
- const onItemsRenderedLocal = (props) => {
111
- // No items, means no necessary to load more data during reset
112
- const itemCount = rows.length;
113
- if (itemCount > 0 && props.visibleRowStopIndex + threshold > itemCount) {
114
- // Auto load next page
115
- loadDataLocal();
116
- }
117
- // Custom
118
- if (onItemsRendered)
119
- onItemsRendered(props);
120
- };
121
103
  // Reset the state and load again
122
104
  const reset = (add, items = []) => {
123
105
  const { queryPaging, ...rest } = add ?? {};
@@ -130,16 +112,16 @@ export const ScrollerGrid = (props) => {
130
112
  lastItem: undefined,
131
113
  ...rest
132
114
  };
133
- Object.assign(refs.current, resetState);
134
- Object.assign(refs.current.queryPaging, {
115
+ Object.assign(stateRefs.current, resetState);
116
+ Object.assign(stateRefs.current.queryPaging, {
135
117
  currentPage: 0,
136
118
  ...queryPaging
137
119
  });
138
120
  // Reset items
139
- if (refs.current.isMounted !== false)
121
+ if (stateRefs.current.isMounted !== false)
140
122
  setRows(items, true);
141
123
  };
142
- const instance = {
124
+ React.useImperativeHandle(mRef, () => ({
143
125
  delete(index) {
144
126
  const item = rows.at(index);
145
127
  if (item) {
@@ -154,27 +136,28 @@ export const ScrollerGrid = (props) => {
154
136
  newRows.splice(start, 0, item);
155
137
  setRows(newRows);
156
138
  },
157
- scrollTo(params) {
158
- ref.current?.scrollTo(params);
139
+ refresh() {
140
+ loadDataLocal(0);
159
141
  },
160
- scrollToItem(params) {
161
- ref.current?.scrollToItem(params);
142
+ reset,
143
+ scrollToCell(param) {
144
+ localRef.current?.scrollToCell(param);
162
145
  },
163
- scrollToRef(scrollOffset) {
164
- ref.current?.scrollTo({ scrollLeft: 0, scrollTop: scrollOffset });
146
+ scrollToColumn(param) {
147
+ localRef.current?.scrollToColumn(param);
165
148
  },
166
- scrollToItemRef(index, align) {
167
- ref.current?.scrollToItem({ rowIndex: index, align });
149
+ scrollToRow(param) {
150
+ localRef.current?.scrollToRow(param);
168
151
  },
169
152
  select(rowIndex) {
170
153
  // Select only one item
171
- const selectedItems = refs.current.selectedItems;
154
+ const selectedItems = stateRefs.current.selectedItems;
172
155
  selectedItems[0] = rows[rowIndex];
173
156
  if (onSelectChange)
174
157
  onSelectChange(selectedItems);
175
158
  },
176
159
  selectAll(checked) {
177
- const selectedItems = refs.current.selectedItems;
160
+ const selectedItems = stateRefs.current.selectedItems;
178
161
  rows.forEach((row) => {
179
162
  const index = selectedItems.findIndex((selectedItem) => selectedItem[idField] === row[idField]);
180
163
  if (checked) {
@@ -189,7 +172,7 @@ export const ScrollerGrid = (props) => {
189
172
  onSelectChange(selectedItems);
190
173
  },
191
174
  selectItem(item, checked) {
192
- const selectedItems = refs.current.selectedItems;
175
+ const selectedItems = stateRefs.current.selectedItems;
193
176
  const index = selectedItems.findIndex((selectedItem) => selectedItem[idField] === item[idField]);
194
177
  if (checked) {
195
178
  if (index === -1)
@@ -201,35 +184,15 @@ export const ScrollerGrid = (props) => {
201
184
  }
202
185
  if (onSelectChange)
203
186
  onSelectChange(selectedItems);
204
- },
205
- reset,
206
- resetAfterColumnIndex(index, shouldForceUpdate) {
207
- ref.current?.resetAfterColumnIndex(index, shouldForceUpdate);
208
- },
209
- resetAfterIndices(params) {
210
- ref.current?.resetAfterIndices(params);
211
- },
212
- resetAfterRowIndex(index, shouldForceUpdate) {
213
- ref.current?.resetAfterRowIndex(index, shouldForceUpdate);
214
187
  }
215
- };
216
- React.useImperativeHandle(mRef, () => instance, [rows]);
217
- // Force update to work with the new width and rowHeight
218
- React.useEffect(() => {
219
- ref.current?.resetAfterIndices({
220
- columnIndex: 0,
221
- rowIndex: 0,
222
- shouldForceUpdate: true
223
- });
224
- }, [width, rowHeight]);
188
+ }), [rows]);
225
189
  // Rows
226
- const rowLength = rows.length;
227
- // Row count
228
- const rowCount = refs.current.hasNextPage ? rowLength + 1 : rowLength;
190
+ const rowCount = rows.length;
229
191
  React.useEffect(() => {
230
192
  // Auto load data when current page is 0
231
- if (refs.current.queryPaging.currentPage === 0 && refs.current.autoLoad) {
232
- const initItems = onInitLoad == null ? undefined : onInitLoad(ref.current);
193
+ if (stateRefs.current.queryPaging.currentPage === 0 &&
194
+ stateRefs.current.autoLoad) {
195
+ const initItems = onInitLoad == null ? undefined : onInitLoad(stateRefs.current);
233
196
  if (initItems)
234
197
  reset(initItems[1], initItems[0]);
235
198
  else
@@ -238,14 +201,17 @@ export const ScrollerGrid = (props) => {
238
201
  }, [onInitLoad, loadDataLocal]);
239
202
  React.useEffect(() => {
240
203
  return () => {
241
- refs.current.isMounted = false;
204
+ stateRefs.current.isMounted = false;
242
205
  };
243
206
  }, []);
244
207
  // Layout
245
- return (_jsxs(React.Fragment, { children: [headerRenderer && headerRenderer(refs.current), _jsx(VariableSizeGrid, { itemKey: ({ columnIndex, rowIndex, data }) => {
246
- if (data == null)
247
- return [rowIndex, columnIndex].join(",");
248
- // ${data[idField]}-${rowIndex} always unique but no cache for the same item
249
- return [`${data[idField]}`, columnIndex].join(",");
250
- }, onItemsRendered: onItemsRenderedLocal, ref: ref, rowCount: rowCount, rowHeight: typeof rowHeight === "function" ? rowHeight : () => rowHeight, style: { overflowX: "hidden" }, width: width, ...rest, children: (props) => itemRendererLocal(props, refs.current) }), footerRenderer && footerRenderer(rows, refs.current)] }));
208
+ return (_jsxs(React.Fragment, { children: [headerRenderer && headerRenderer(stateRefs.current), _jsx(Grid, { cellProps: { rows, states: stateRefs.current }, gridRef: refs, onCellsRendered: (visibleCells, allCells) => {
209
+ // No items, means no necessary to load more data during reset
210
+ if (rowCount > 0 &&
211
+ visibleCells.rowStopIndex + threshold > rowCount) {
212
+ // Auto load next page
213
+ loadDataLocal();
214
+ }
215
+ onCellsRendered?.(visibleCells, allCells);
216
+ }, overscanCount: threshold, rowHeight: rowHeight, rowCount: rowCount, style: style, ...rest }), footerRenderer && footerRenderer(rows, stateRefs.current)] }));
251
217
  };
@@ -1,66 +1,41 @@
1
1
  import { DataTypes } from "@etsoo/shared";
2
2
  import React from "react";
3
- import { Align, ListChildComponentProps, ListProps } from "react-window";
3
+ import { ListProps } from "react-window";
4
4
  import { GridLoader } from "./GridLoader";
5
5
  import { GridMethodRef } from "./GridMethodRef";
6
+ type ScrollerListRowProps<T extends object> = {
7
+ items: T[];
8
+ };
9
+ /**
10
+ * Scroller list forward ref
11
+ */
12
+ export interface ScrollerListForwardRef<T> extends GridMethodRef<T> {
13
+ }
6
14
  /**
7
15
  * Scroller vertical list props
8
16
  */
9
- export type ScrollerListProps<T extends object> = GridLoader<T> & Omit<ListProps<T>, "outerRef" | "height" | "width" | "children" | "itemCount"> & {
10
- /**
11
- * Methods ref
12
- */
13
- mRef?: React.Ref<ScrollerListForwardRef<T>>;
14
- /**
15
- * Outer div ref
16
- */
17
- oRef?: React.Ref<HTMLDivElement>;
17
+ export type ScrollerListProps<T extends object> = GridLoader<T> & Omit<ListProps<ScrollerListRowProps<T>>, "rowCount" | "rowProps" | "overscanCount"> & {
18
18
  /**
19
19
  * Height of the list
20
20
  */
21
- height?: number;
22
- /**
23
- * Width of the list
24
- */
25
- width?: number | string;
21
+ height?: number | string;
26
22
  /**
27
23
  * Id field
28
24
  */
29
25
  idField?: DataTypes.Keys<T>;
30
26
  /**
31
- * Item renderer
27
+ * Methods ref
32
28
  */
33
- itemRenderer: (props: ListChildComponentProps<T>) => React.ReactElement;
29
+ mRef?: React.Ref<ScrollerListForwardRef<T>>;
34
30
  /**
35
- * Item size, a function indicates its a variable size list
31
+ * Width of the list
36
32
  */
37
- itemSize: ((index: number) => number) | number;
33
+ width?: number | string;
38
34
  };
39
- /**
40
- * Scroller list ref
41
- */
42
- export interface ScrollerListRef {
43
- /**
44
- * Scroll to the specified offset (scrollTop or scrollLeft, depending on the direction prop).
45
- */
46
- scrollTo(scrollOffset: number): void;
47
- /**
48
- * Scroll to the specified item.
49
- */
50
- scrollToItem(index: number, align?: Align): void;
51
- }
52
- /**
53
- * Scroller list forward ref
54
- */
55
- export interface ScrollerListForwardRef<T> extends GridMethodRef<T> {
56
- /**
57
- * Refresh latest page data
58
- */
59
- refresh(): void;
60
- }
61
35
  /**
62
36
  * Scroller vertical list
63
37
  * @param props Props
64
38
  * @returns Component
65
39
  */
66
40
  export declare const ScrollerList: <T extends object>(props: ScrollerListProps<T>) => import("react/jsx-runtime").JSX.Element;
41
+ export {};
@@ -1,13 +1,16 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { DataTypes, Utils } from "@etsoo/shared";
2
+ import { Utils } from "@etsoo/shared";
3
3
  import React from "react";
4
- import { FixedSizeList, VariableSizeList } from "react-window";
4
+ import { List, useListRef } from "react-window";
5
5
  import { useCombinedRefs } from "../uses/useCombinedRefs";
6
- import { GridSizeGet } from "./GridLoader";
7
6
  // Calculate loadBatchSize
8
- const calculateBatchSize = (height, itemSize) => {
9
- const size = Utils.getResult(itemSize, 0);
10
- return 2 + Math.ceil(height / size);
7
+ const calculateBatchSize = (height, rowHeight) => {
8
+ if (typeof height === "number" &&
9
+ typeof rowHeight === "number" &&
10
+ rowHeight > 0) {
11
+ return 1 + Math.ceil(height / rowHeight);
12
+ }
13
+ return 10;
11
14
  };
12
15
  /**
13
16
  * Scroller vertical list
@@ -16,18 +19,14 @@ const calculateBatchSize = (height, itemSize) => {
16
19
  */
17
20
  export const ScrollerList = (props) => {
18
21
  // Destruct
19
- const { autoLoad = true, defaultOrderBy, 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;
22
+ const { autoLoad = true, defaultOrderBy, height = "100%", width = "100%", mRef, style = {}, idField = "id", rowHeight, listRef, loadBatchSize = calculateBatchSize(height, rowHeight), loadData, threshold = 3, onRowsRendered, onInitLoad, onUpdateRows, ...rest } = props;
20
23
  // Style
21
24
  Object.assign(style, {
22
- width: "100%",
23
- height: "100%",
24
- display: "inline-block"
25
+ width,
26
+ height
25
27
  });
26
- // Refs
27
- const listRef = React.useRef(null);
28
- const outerRef = React.useRef(null);
29
- const refs = useCombinedRefs(oRef, outerRef);
30
- // Rows
28
+ const localRef = useListRef(null);
29
+ const refs = useCombinedRefs(listRef, localRef);
31
30
  const [rows, updateRows] = React.useState([]);
32
31
  const setRows = (rows, reset = false) => {
33
32
  stateRefs.current.loadedItems = rows.length;
@@ -35,8 +34,7 @@ export const ScrollerList = (props) => {
35
34
  if (!reset && onUpdateRows)
36
35
  onUpdateRows(rows, stateRefs.current);
37
36
  };
38
- // States
39
- const batchSize = GridSizeGet(loadBatchSize, height);
37
+ const batchSize = Utils.getResult(loadBatchSize, height);
40
38
  const stateRefs = React.useRef({
41
39
  queryPaging: {
42
40
  currentPage: 0,
@@ -107,13 +105,6 @@ export const ScrollerList = (props) => {
107
105
  }
108
106
  });
109
107
  };
110
- const itemRendererLocal = (itemProps) => {
111
- // Custom render
112
- return itemRenderer({
113
- ...itemProps,
114
- data: rows[itemProps.index]
115
- });
116
- };
117
108
  // Reset the state and load again
118
109
  const reset = (add, items = []) => {
119
110
  const { queryPaging, ...rest } = add ?? {};
@@ -136,7 +127,6 @@ export const ScrollerList = (props) => {
136
127
  setRows(items, true);
137
128
  };
138
129
  React.useImperativeHandle(mRef, () => {
139
- const refMethods = listRef.current;
140
130
  return {
141
131
  delete(index) {
142
132
  const item = rows.at(index);
@@ -156,47 +146,38 @@ export const ScrollerList = (props) => {
156
146
  loadDataLocal(0);
157
147
  },
158
148
  reset,
159
- scrollToRef(scrollOffset) {
160
- refMethods.scrollTo(scrollOffset);
161
- },
162
- scrollToItemRef(index, align) {
163
- refMethods.scrollToItem(index, align);
149
+ scrollToRow(param) {
150
+ localRef.current?.scrollToRow(param);
164
151
  }
165
152
  };
166
153
  }, []);
167
- // Row count
168
- const rowCount = rows.length;
169
- // Local items renderer callback
170
- const onItemsRenderedLocal = (props) => {
171
- // No items, means no necessary to load more data during reset
172
- if (rowCount > 0 && props.visibleStopIndex + threshold > rowCount) {
173
- // Auto load next page
174
- loadDataLocal();
175
- }
176
- // Custom
177
- if (onItemsRendered)
178
- onItemsRendered(props);
179
- };
180
- // Item count
181
- const itemCount = stateRefs.current.hasNextPage ? rowCount + 1 : rowCount;
154
+ // When layout ready
155
+ React.useEffect(() => {
156
+ // Return clear function
157
+ return () => {
158
+ stateRefs.current.isMounted = false;
159
+ };
160
+ }, []);
182
161
  React.useEffect(() => {
183
162
  // Auto load data when current page is 0
184
163
  if (stateRefs.current.queryPaging?.currentPage === 0 &&
185
164
  stateRefs.current.autoLoad) {
186
- const initItems = onInitLoad == null ? undefined : onInitLoad(listRef.current);
165
+ const initItems = onInitLoad == null ? undefined : onInitLoad(localRef.current);
187
166
  if (initItems)
188
167
  reset(initItems[1], initItems[0]);
189
168
  else
190
169
  loadDataLocal();
191
170
  }
192
171
  }, [onInitLoad, loadDataLocal]);
193
- // When layout ready
194
- React.useEffect(() => {
195
- // Return clear function
196
- return () => {
197
- stateRefs.current.isMounted = false;
198
- };
199
- }, []);
172
+ // Row count
173
+ const rowCount = rows.length;
200
174
  // Layout
201
- return typeof itemSize === "function" ? (_jsx(VariableSizeList, { height: height, width: width, itemCount: itemCount, itemKey: (index, data) => DataTypes.getIdValue1(data, idField) ?? index, itemSize: itemSize, outerRef: refs, ref: listRef, style: style, onItemsRendered: onItemsRenderedLocal, ...rest, children: itemRendererLocal })) : (_jsx(FixedSizeList, { height: height, width: width, itemCount: itemCount, itemKey: (index, data) => DataTypes.getIdValue1(data, idField) ?? index, itemSize: itemSize, outerRef: refs, ref: listRef, style: style, onItemsRendered: onItemsRenderedLocal, ...rest, children: itemRendererLocal }));
175
+ return (_jsx(List, { listRef: refs, onRowsRendered: (visibleCells, allCells) => {
176
+ // No items, means no necessary to load more data during reset
177
+ if (rowCount > 0 && visibleCells.stopIndex + threshold > rowCount) {
178
+ // Auto load next page
179
+ loadDataLocal();
180
+ }
181
+ onRowsRendered?.(visibleCells, allCells);
182
+ }, overscanCount: threshold, rowHeight: rowHeight, rowCount: rowCount, rowProps: { items: rows }, style: style, ...rest }));
202
183
  };
@@ -10,7 +10,6 @@ export * from "./components/ListItemReact";
10
10
  export * from "./components/ScrollerGrid";
11
11
  export * from "./components/ScrollerList";
12
12
  export * from "./components/ScrollRestoration";
13
- export type { ListOnScrollProps, GridOnScrollProps, VariableSizeGrid } from "react-window";
14
13
  export * from "./custom/CustomFieldReact";
15
14
  export * from "./notifier/Notifier";
16
15
  export * from "@etsoo/notificationbase";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/react",
3
- "version": "1.8.51",
3
+ "version": "1.8.52",
4
4
  "description": "TypeScript ReactJs UI Independent Framework",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -38,27 +38,27 @@
38
38
  "@emotion/css": "^11.13.5",
39
39
  "@emotion/react": "^11.14.0",
40
40
  "@emotion/styled": "^11.14.1",
41
- "@etsoo/appscript": "^1.6.43",
42
- "@etsoo/notificationbase": "^1.1.63",
43
- "@etsoo/shared": "^1.2.75",
41
+ "@etsoo/appscript": "^1.6.45",
42
+ "@etsoo/notificationbase": "^1.1.64",
43
+ "@etsoo/shared": "^1.2.76",
44
44
  "react": "^19.1.1",
45
45
  "react-dom": "^19.1.1",
46
- "react-router-dom": "^7.8.1",
47
- "react-window": "^1.8.11"
46
+ "react-router-dom": "^7.9.1",
47
+ "react-window": "^2.1.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@babel/cli": "^7.28.3",
51
- "@babel/core": "^7.28.3",
51
+ "@babel/core": "^7.28.4",
52
52
  "@babel/plugin-transform-runtime": "^7.28.3",
53
53
  "@babel/preset-env": "^7.28.3",
54
- "@babel/runtime-corejs3": "^7.28.3",
55
- "@testing-library/jest-dom": "^6.7.0",
54
+ "@babel/runtime-corejs3": "^7.28.4",
55
+ "@testing-library/jest-dom": "^6.8.0",
56
56
  "@testing-library/react": "^16.3.0",
57
- "@types/react": "^19.1.10",
58
- "@types/react-dom": "^19.1.7",
57
+ "@types/react": "^19.1.13",
58
+ "@types/react-dom": "^19.1.9",
59
59
  "@types/react-window": "^1.8.8",
60
- "@vitejs/plugin-react": "^5.0.1",
61
- "jsdom": "^26.1.0",
60
+ "@vitejs/plugin-react": "^5.0.2",
61
+ "jsdom": "^27.0.0",
62
62
  "typescript": "^5.9.2",
63
63
  "vitest": "^3.2.4"
64
64
  }
package/setupTests.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { vi } from "vitest";
2
+
3
+ (globalThis as any).IS_REACT_ACT_ENVIRONMENT = true;
4
+
5
+ // Mock the ResizeObserver
6
+ const ResizeObserverMock = vi.fn(() => ({
7
+ observe: vi.fn(),
8
+ unobserve: vi.fn(),
9
+ disconnect: vi.fn()
10
+ }));
11
+
12
+ // Stub the global ResizeObserver
13
+ vi.stubGlobal("ResizeObserver", ResizeObserverMock);
@@ -4,7 +4,7 @@ import { DataTypes, DomUtils } from "@etsoo/shared";
4
4
  /**
5
5
  * Grid size
6
6
  */
7
- export type GridSize = number | ((input: number) => number);
7
+ export type GridSize = number | ((input: number | string) => number);
8
8
 
9
9
  /**
10
10
  * Grid size calculation
@@ -132,7 +132,7 @@ export type GridLoader<
132
132
  defaultOrderBy?: QueryPagingOrder[];
133
133
 
134
134
  /**
135
- * Batch size when load data, default will be calcuated with height and itemSize
135
+ * Batch size when load data, default will be calcuated with height and rowHeight
136
136
  */
137
137
  loadBatchSize?: GridSize;
138
138
 
@@ -1,6 +1,11 @@
1
- import { Align } from "react-window";
1
+ import { ListImperativeAPI } from "react-window";
2
2
  import { GridLoaderPartialStates } from "./GridLoader";
3
3
 
4
+ /**
5
+ * Scroll to row parameter type
6
+ */
7
+ export type ScrollToRowParam = Parameters<ListImperativeAPI["scrollToRow"]>[0];
8
+
4
9
  /**
5
10
  * Grid method ref
6
11
  */
@@ -19,18 +24,19 @@ export interface GridMethodRef<T> {
19
24
  insert(item: T, start: number): void;
20
25
 
21
26
  /**
22
- * Reset
23
- * @param add Additional data
27
+ * Refresh latest page data
24
28
  */
25
- reset(add?: GridLoaderPartialStates<T>): void;
29
+ refresh(): void;
26
30
 
27
31
  /**
28
- * Scroll to the specified offset (scrollTop or scrollLeft, depending on the direction prop).
32
+ * Reset
33
+ * @param add Additional data
29
34
  */
30
- scrollToRef(scrollOffset: number): void;
35
+ reset(add?: GridLoaderPartialStates<T>): void;
31
36
 
32
37
  /**
33
- * Scroll to the specified item.
38
+ * Scroll to the row
39
+ * @param param Parameters to control
34
40
  */
35
- scrollToItemRef(index: number, align?: Align): void;
41
+ scrollToRow(param: ScrollToRowParam): void;
36
42
  }