@etsoo/materialui 1.5.71 → 1.5.72

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.
Files changed (58) hide show
  1. package/__tests__/ReactAppTests.tsx +12 -7
  2. package/__tests__/SelectEx.tsx +1 -1
  3. package/lib/cjs/DataGridEx.d.ts +8 -1
  4. package/lib/cjs/DataGridEx.js +71 -56
  5. package/lib/cjs/DataGridRenderers.d.ts +1 -1
  6. package/lib/cjs/DataGridRenderers.js +1 -1
  7. package/lib/cjs/MUUtils.d.ts +0 -9
  8. package/lib/cjs/MUUtils.js +0 -26
  9. package/lib/cjs/MobileListItemRenderer.d.ts +2 -2
  10. package/lib/cjs/ResponsibleContainer.d.ts +2 -7
  11. package/lib/cjs/ResponsibleContainer.js +8 -57
  12. package/lib/cjs/ScrollerListEx.d.ts +24 -9
  13. package/lib/cjs/ScrollerListEx.js +35 -38
  14. package/lib/cjs/TableEx.d.ts +7 -0
  15. package/lib/cjs/TableEx.js +6 -12
  16. package/lib/cjs/pages/DataGridPage.js +3 -32
  17. package/lib/cjs/pages/FixedListPage.js +5 -34
  18. package/lib/cjs/pages/ListPage.js +1 -29
  19. package/lib/cjs/pages/ResponsivePage.d.ts +2 -7
  20. package/lib/cjs/uses/useGridCacheInitLoad.d.ts +2 -0
  21. package/lib/cjs/uses/useGridCacheInitLoad.js +41 -0
  22. package/lib/cjs/uses/useListCacheInitLoad.d.ts +2 -0
  23. package/lib/cjs/uses/useListCacheInitLoad.js +38 -0
  24. package/lib/mjs/DataGridEx.d.ts +8 -1
  25. package/lib/mjs/DataGridEx.js +71 -56
  26. package/lib/mjs/DataGridRenderers.d.ts +1 -1
  27. package/lib/mjs/DataGridRenderers.js +1 -1
  28. package/lib/mjs/MUUtils.d.ts +0 -9
  29. package/lib/mjs/MUUtils.js +0 -26
  30. package/lib/mjs/MobileListItemRenderer.d.ts +2 -2
  31. package/lib/mjs/ResponsibleContainer.d.ts +2 -7
  32. package/lib/mjs/ResponsibleContainer.js +8 -57
  33. package/lib/mjs/ScrollerListEx.d.ts +24 -9
  34. package/lib/mjs/ScrollerListEx.js +35 -38
  35. package/lib/mjs/TableEx.d.ts +7 -0
  36. package/lib/mjs/TableEx.js +6 -12
  37. package/lib/mjs/pages/DataGridPage.js +3 -32
  38. package/lib/mjs/pages/FixedListPage.js +5 -34
  39. package/lib/mjs/pages/ListPage.js +1 -29
  40. package/lib/mjs/pages/ResponsivePage.d.ts +2 -7
  41. package/lib/mjs/uses/useGridCacheInitLoad.d.ts +2 -0
  42. package/lib/mjs/uses/useGridCacheInitLoad.js +35 -0
  43. package/lib/mjs/uses/useListCacheInitLoad.d.ts +2 -0
  44. package/lib/mjs/uses/useListCacheInitLoad.js +32 -0
  45. package/package.json +18 -19
  46. package/src/DataGridEx.tsx +151 -108
  47. package/src/DataGridRenderers.tsx +2 -1
  48. package/src/MUUtils.ts +0 -33
  49. package/src/MobileListItemRenderer.tsx +2 -2
  50. package/src/ResponsibleContainer.tsx +21 -94
  51. package/src/ScrollerListEx.tsx +109 -121
  52. package/src/TableEx.tsx +20 -12
  53. package/src/pages/DataGridPage.tsx +3 -49
  54. package/src/pages/FixedListPage.tsx +5 -49
  55. package/src/pages/ListPage.tsx +0 -43
  56. package/src/pages/ResponsivePage.tsx +3 -11
  57. package/src/uses/useGridCacheInitLoad.ts +55 -0
  58. package/src/uses/useListCacheInitLoad.ts +51 -0
@@ -36,6 +36,8 @@ export function ResponsibleContainer(props) {
36
36
  if (ref == null)
37
37
  return;
38
38
  state.ref = ref;
39
+ if (ref.element && elementReady)
40
+ elementReady(ref.element, true);
39
41
  });
40
42
  // Screen size detection
41
43
  const showDataGrid = useMediaQuery("(min-width:600px)");
@@ -77,44 +79,6 @@ export function ResponsibleContainer(props) {
77
79
  state.rect = rect;
78
80
  return false;
79
81
  });
80
- const onInitLoad = (ref) => {
81
- // Avoid repeatedly load from cache
82
- if (refs.current.initLoaded || !cacheKey)
83
- return undefined;
84
- // Cache data
85
- const cacheData = GridUtils.getCacheData(cacheKey, cacheMinutes);
86
- if (cacheData) {
87
- const { rows, state } = cacheData;
88
- GridUtils.mergeSearchData(state, searchData);
89
- // Scroll position
90
- const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
91
- if (scrollData) {
92
- if ("resetAfterColumnIndex" in ref) {
93
- const { scrollLeft, scrollTop } = JSON.parse(scrollData);
94
- globalThis.setTimeout(() => ref.scrollTo({ scrollLeft, scrollTop }), 0);
95
- }
96
- else {
97
- const { scrollOffset } = JSON.parse(scrollData);
98
- globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0);
99
- }
100
- }
101
- // Update flag value
102
- refs.current.initLoaded = true;
103
- // Return cached rows and state
104
- return [rows, state];
105
- }
106
- return undefined;
107
- };
108
- const onListScroll = (props) => {
109
- if (!cacheKey || !refs.current.initLoaded)
110
- return;
111
- sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
112
- };
113
- const onGridScroll = (props) => {
114
- if (!cacheKey || !refs.current.initLoaded)
115
- return;
116
- sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
117
- };
118
82
  // Rect
119
83
  const rect = dimensions[0][2];
120
84
  // Create list
@@ -144,26 +108,13 @@ export function ResponsibleContainer(props) {
144
108
  if (adjustFabHeight)
145
109
  heightLocal = adjustFabHeight(heightLocal, showDataGrid);
146
110
  if (showDataGrid) {
147
- // Delete
148
- delete rest.itemRenderer;
149
- return (_jsx(Box, { className: "DataGridBox", children: _jsx(DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, onDoubleClick: (_, data) => quickAction && quickAction(data), outerRef: (element) => {
150
- if (element != null && elementReady)
151
- elementReady(element, true);
152
- }, onScroll: onGridScroll, columns: columns, onUpdateRows: GridUtils.getUpdateRowsHandler(cacheKey), onInitLoad: onInitLoad, ...rest }) }));
111
+ // Remove useless props
112
+ const { itemRenderer, ...gridProps } = rest;
113
+ return (_jsx(Box, { className: "DataGridBox", children: _jsx(DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, onDoubleClick: (_, data) => quickAction && quickAction(data), columns: columns, ...gridProps }) }));
153
114
  }
154
- // Delete
155
- delete rest.checkable;
156
- delete rest.borderRowsCount;
157
- delete rest.bottomHeight;
158
- delete rest.footerItemRenderer;
159
- delete rest.headerHeight;
160
- delete rest.hideFooter;
161
- delete rest.hoverColor;
162
- delete rest.selectable;
163
- return (_jsx(Box, { className: "ListBox", sx: { height: heightLocal }, children: _jsx(ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, onUpdateRows: GridUtils.getUpdateRowsHandler(cacheKey), onInitLoad: onInitLoad, mRef: mRefs, onClick: (event, data) => quickAction && ReactUtils.isSafeClick(event) && quickAction(data), oRef: (element) => {
164
- if (element != null && elementReady)
165
- elementReady(element, false);
166
- }, onScroll: onListScroll, ...rest }) }));
115
+ // Remove useless props
116
+ const { checkable, borderRowsCount, bottomHeight, footerItemRenderer, headerHeight, hideFooter, hoverColor, selectable, ...listProps } = rest;
117
+ return (_jsx(Box, { className: "ListBox", sx: { height: heightLocal }, children: _jsx(ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, mRef: mRefs, onClick: (event, data) => quickAction && ReactUtils.isSafeClick(event) && quickAction(data), ...listProps }) }));
167
118
  })();
168
119
  const searchBar = React.useMemo(() => {
169
120
  if (!hasFields ||
@@ -1,15 +1,22 @@
1
1
  import { ScrollerListProps } from "@etsoo/react";
2
2
  import React from "react";
3
- import { ListChildComponentProps } from "react-window";
4
3
  import { MouseEventWithDataHandler } from "./MUGlobal";
5
4
  /**
6
5
  * Extended ScrollerList inner item renderer props
7
6
  */
8
- export interface ScrollerListExInnerItemRendererProps<T> extends ListChildComponentProps<T> {
7
+ export type ScrollerListExItemRendererProps<T> = {
9
8
  /**
10
- * Item selected
9
+ * Row index
11
10
  */
12
- selected: boolean;
11
+ index: number;
12
+ /**
13
+ * Row data
14
+ */
15
+ data: T;
16
+ /**
17
+ * Style
18
+ */
19
+ style: React.CSSProperties;
13
20
  /**
14
21
  * Item height
15
22
  */
@@ -22,7 +29,11 @@ export interface ScrollerListExInnerItemRendererProps<T> extends ListChildCompon
22
29
  * Default margins
23
30
  */
24
31
  margins: object;
25
- }
32
+ /**
33
+ * Item selected
34
+ */
35
+ selected: boolean;
36
+ };
26
37
  /**
27
38
  * Extended ScrollerList ItemSize type
28
39
  * 1. Callback function
@@ -33,19 +44,23 @@ export type ScrollerListExItemSize = ((index: number) => [number, number] | [num
33
44
  /**
34
45
  * Extended ScrollerList Props
35
46
  */
36
- export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "itemRenderer" | "itemSize"> & {
47
+ export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "rowComponent" | "rowHeight" | "onClick" | "onDoubleClick" | "onInitLoad"> & {
37
48
  /**
38
49
  * Alternating colors for odd/even rows
39
50
  */
40
51
  alternatingColors?: [string?, string?];
41
52
  /**
42
- * Inner item renderer
53
+ * Cache key
54
+ */
55
+ cacheKey?: string;
56
+ /**
57
+ * Cache minutes
43
58
  */
44
- innerItemRenderer: (props: ScrollerListExInnerItemRendererProps<T>) => React.ReactNode;
59
+ cacheMinutes?: number;
45
60
  /**
46
61
  * Item renderer
47
62
  */
48
- itemRenderer?: (props: ListChildComponentProps<T>) => React.ReactElement;
63
+ itemRenderer?: (props: ScrollerListExItemRendererProps<T>) => React.ReactNode;
49
64
  /**
50
65
  * Item size, a function indicates its a variable size list
51
66
  */
@@ -5,6 +5,9 @@ import { Utils } from "@etsoo/shared";
5
5
  import React from "react";
6
6
  import { MUGlobal } from "./MUGlobal";
7
7
  import { useTheme } from "@mui/material/styles";
8
+ import { GridUtils } from "./GridUtils";
9
+ import { useListCacheInitLoad } from "./uses/useListCacheInitLoad";
10
+ import Box from "@mui/material/Box";
8
11
  // Scroll bar size
9
12
  const scrollbarSize = 16;
10
13
  // Selected class name
@@ -68,24 +71,6 @@ const defaultMargin = (margin, horizon) => {
68
71
  marginBottom: half
69
72
  };
70
73
  };
71
- // Default itemRenderer
72
- function defaultItemRenderer({ index, innerItemRenderer, data, onMouseDown, selected, style, itemHeight, onClick, onDoubleClick, space, margins }) {
73
- // Child
74
- const child = innerItemRenderer({
75
- index,
76
- data,
77
- style,
78
- selected,
79
- itemHeight,
80
- space,
81
- margins
82
- });
83
- let rowClass = `ScrollerListEx-Row${index % 2}`;
84
- if (selected)
85
- rowClass += ` ${selectedClassName}`;
86
- // Layout
87
- return (_jsx("div", { className: rowClass, style: style, onMouseDown: (event) => onMouseDown(event.currentTarget, data), onClick: (event) => onClick && onClick(event, data), onDoubleClick: (event) => onDoubleClick && onDoubleClick(event, data), children: child }));
88
- }
89
74
  /**
90
75
  * Extended ScrollerList
91
76
  * @param props Props
@@ -113,20 +98,12 @@ export function ScrollerListEx(props) {
113
98
  return selected;
114
99
  };
115
100
  // Destruct
116
- const { alternatingColors = [undefined, undefined], className, idField = "id", innerItemRenderer, itemSize, itemRenderer = (itemProps) => {
117
- const [itemHeight, space, margins] = calculateItemSize(itemProps.index);
118
- return defaultItemRenderer({
119
- itemHeight,
120
- innerItemRenderer,
121
- onMouseDown,
122
- onClick,
123
- onDoubleClick,
124
- space,
125
- margins,
126
- selected: isSelected(itemProps.data),
127
- ...itemProps
128
- });
129
- }, onClick, onDoubleClick, onSelectChange, selectedColor = "#edf4fb", ...rest } = props;
101
+ const { alternatingColors = [undefined, undefined], className, cacheKey, cacheMinutes = 15, idField = "id", itemSize, itemRenderer = ({ data, itemHeight, margins }) => (_jsx(Box, { component: "pre", sx: {
102
+ height: itemHeight,
103
+ ...margins
104
+ }, children: JSON.stringify(data) })), onClick, onDoubleClick, onUpdateRows, onSelectChange, selectedColor = "#edf4fb", ...rest } = props;
105
+ // Init handler
106
+ const initHandler = useListCacheInitLoad(cacheKey, cacheMinutes);
130
107
  // Theme
131
108
  const theme = useTheme();
132
109
  // Cache calculation
@@ -150,11 +127,31 @@ export function ScrollerListEx(props) {
150
127
  // Calculation
151
128
  return itemSizeResult;
152
129
  };
153
- // Local item size
154
- const itemSizeLocal = (index) => {
155
- const [size, space] = calculateItemSize(index);
156
- return size + space;
157
- };
130
+ const onUpdateRowsHandler = React.useCallback((rows, state) => {
131
+ GridUtils.getUpdateRowsHandler(cacheKey)?.(rows, state);
132
+ onUpdateRows?.(rows, state);
133
+ }, [onUpdateRows, cacheKey]);
158
134
  // Layout
159
- return (_jsx(ScrollerList, { className: Utils.mergeClasses("ScrollerListEx-Body", className, createGridStyle(alternatingColors, selectedColor)), idField: idField, itemRenderer: itemRenderer, itemSize: itemSizeLocal, ...rest }));
135
+ return (_jsx(ScrollerList, { className: Utils.mergeClasses("ScrollerListEx-Body", className, createGridStyle(alternatingColors, selectedColor)), idField: idField, onRowsRendered: cacheKey
136
+ ? (visibleRows) => sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(visibleRows))
137
+ : undefined, onInitLoad: initHandler, onUpdateRows: onUpdateRowsHandler, rowComponent: ({ index, items, style }) => {
138
+ const data = items[index];
139
+ const selected = isSelected(data);
140
+ const rowClass = `ScrollerListEx-Row${index % 2}${selected ? ` ${selectedClassName}` : ""}`;
141
+ const [itemHeight, space, margins] = calculateItemSize(index);
142
+ // Child
143
+ const child = itemRenderer({
144
+ index,
145
+ data,
146
+ style,
147
+ selected,
148
+ itemHeight,
149
+ space,
150
+ margins
151
+ });
152
+ return (_jsx("div", { className: rowClass, style: style, onMouseDown: (event) => onMouseDown(event.currentTarget, data), onClick: (event) => onClick && onClick(event, data), onDoubleClick: (event) => onDoubleClick && onDoubleClick(event, data), children: child }));
153
+ }, rowHeight: (index) => {
154
+ const [size, space] = calculateItemSize(index);
155
+ return size + space;
156
+ }, ...rest }));
160
157
  }
@@ -43,6 +43,13 @@ export type TableExProps<T extends object, D extends DataTypes.Keys<T>> = TableP
43
43
  * Methods
44
44
  */
45
45
  mRef?: React.Ref<TableExMethodRef<T>>;
46
+ /**
47
+ * Data change handler
48
+ * @param rows Rows
49
+ * @param rowIndex Row index
50
+ * @param columnIndex Column index
51
+ */
52
+ onDataChange?: (rows: T[], rowIndex: number, columnIndex: number) => void;
46
53
  /**
47
54
  * On items select change
48
55
  */
@@ -27,7 +27,7 @@ export function TableEx(props) {
27
27
  // Theme
28
28
  const theme = useTheme();
29
29
  // Destruct
30
- const { alternatingColors = [theme.palette.action.hover, undefined], autoLoad = true, columns, defaultOrderBy, headerColors = [undefined, undefined], idField = "id", loadBatchSize, loadData, maxHeight, mRef, onSelectChange, rowHeight = 53, otherHeight = 110, threshold, ...rest } = props;
30
+ const { alternatingColors = [theme.palette.action.hover, undefined], autoLoad = true, columns, defaultOrderBy, headerColors = [undefined, undefined], idField = "id", loadBatchSize, loadData, maxHeight, mRef, onDataChange, onSelectChange, rowHeight = 53, otherHeight = 110, threshold, ...rest } = props;
31
31
  const selectable = onSelectChange != null;
32
32
  // Rows per page
33
33
  let rowsPerPageLocal;
@@ -83,6 +83,9 @@ export function TableEx(props) {
83
83
  });
84
84
  };
85
85
  React.useImperativeHandle(mRef, () => ({
86
+ get element() {
87
+ return null;
88
+ },
86
89
  delete(index) {
87
90
  const item = rows.at(index);
88
91
  if (item) {
@@ -97,20 +100,11 @@ export function TableEx(props) {
97
100
  newRows.splice(start, 0, item);
98
101
  setRows(newRows);
99
102
  },
100
- /**
101
- * Refresh data
102
- */
103
103
  refresh() {
104
104
  loadDataLocal();
105
105
  },
106
- /**
107
- * Reset
108
- */
109
106
  reset,
110
- scrollToRef(scrollOffset) {
111
- // Not implemented
112
- },
113
- scrollToItemRef(index) {
107
+ scrollToRow(param) {
114
108
  // Not implemented
115
109
  }
116
110
  }), []);
@@ -284,7 +278,7 @@ export function TableEx(props) {
284
278
  rowIndex,
285
279
  columnIndex,
286
280
  cellProps,
287
- setItems
281
+ triggerChange: () => onDataChange?.(rows, rowIndex, columnIndex)
288
282
  })) : (_jsx(React.Fragment, { children: "\u00A0" }));
289
283
  return (_jsx(TableCell, { ...cellProps, children: child }, `${rowId}${columnIndex}`));
290
284
  })] }, rowId));
@@ -27,9 +27,10 @@ export function DataGridPage(props) {
27
27
  if (ref == null)
28
28
  return;
29
29
  states.ref = ref;
30
+ if (ref.element)
31
+ setStates({ element: ref.element });
30
32
  //setStates({ ref });
31
33
  });
32
- const initLoadedRef = React.useRef(null);
33
34
  // On submit callback
34
35
  const onSubmit = (data, _reset) => {
35
36
  setStates({ data });
@@ -39,33 +40,6 @@ export function DataGridPage(props) {
39
40
  };
40
41
  // Search data
41
42
  const searchData = useSearchParamsWithCache(cacheKey);
42
- const onInitLoad = (ref) => {
43
- // Avoid repeatedly load from cache
44
- if (initLoadedRef.current || !cacheKey)
45
- return undefined;
46
- // Cache data
47
- const cacheData = GridUtils.getCacheData(cacheKey, cacheMinutes);
48
- if (cacheData) {
49
- const { rows, state } = cacheData;
50
- GridUtils.mergeSearchData(state, searchData);
51
- // Scroll position
52
- const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
53
- if (scrollData) {
54
- const { scrollLeft, scrollTop } = JSON.parse(scrollData);
55
- globalThis.setTimeout(() => ref.scrollTo({ scrollLeft, scrollTop }), 0);
56
- }
57
- // Update flag value
58
- initLoadedRef.current = true;
59
- // Return cached rows and state
60
- return [rows, state];
61
- }
62
- return undefined;
63
- };
64
- const onGridScroll = (props) => {
65
- if (!cacheKey || !initLoadedRef.current)
66
- return;
67
- sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
68
- };
69
43
  // Watch container
70
44
  const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
71
45
  const rect = dimensions[0][2];
@@ -90,10 +64,7 @@ export function DataGridPage(props) {
90
64
  const gridHeight = states.height;
91
65
  if (gridHeight == null)
92
66
  return;
93
- return (_jsx(DataGridEx, { autoLoad: false, height: gridHeight, loadData: localLoadData, mRef: refs, onUpdateRows: GridUtils.getUpdateRowsHandler(cacheKey), onInitLoad: onInitLoad, onScroll: onGridScroll, outerRef: (element) => {
94
- if (element != null)
95
- setStates({ element });
96
- }, ...rest }));
67
+ return (_jsx(DataGridEx, { autoLoad: false, height: gridHeight, loadData: localLoadData, mRef: refs, ...rest }));
97
68
  }, [states.height]);
98
69
  const { ref, data } = states;
99
70
  React.useEffect(() => {
@@ -19,7 +19,6 @@ export function FixedListPage(props) {
19
19
  pageProps.paddings ??= MUGlobal.pagePaddings;
20
20
  // States
21
21
  const [states] = React.useState({});
22
- const initLoadedRef = React.useRef(null);
23
22
  // Scroll container
24
23
  const [scrollContainer, updateScrollContainer] = React.useState();
25
24
  const refs = useCombinedRefs(mRef, (ref) => {
@@ -27,6 +26,8 @@ export function FixedListPage(props) {
27
26
  return;
28
27
  const first = states.ref == null;
29
28
  states.ref = ref;
29
+ if (ref.element)
30
+ updateScrollContainer(ref.element);
30
31
  if (first)
31
32
  reset();
32
33
  });
@@ -43,35 +44,6 @@ export function FixedListPage(props) {
43
44
  const localLoadData = (props, lastItem) => {
44
45
  return loadData(GridUtils.createLoader(props, fieldTemplate, cacheKey, false), lastItem);
45
46
  };
46
- // Search data
47
- const searchData = useSearchParamsWithCache(cacheKey);
48
- const onInitLoad = (ref) => {
49
- // Avoid repeatedly load from cache
50
- if (initLoadedRef.current || !cacheKey)
51
- return undefined;
52
- // Cache data
53
- const cacheData = GridUtils.getCacheData(cacheKey, cacheMinutes);
54
- if (cacheData) {
55
- const { rows, state } = cacheData;
56
- GridUtils.mergeSearchData(state, searchData);
57
- // Scroll position
58
- const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
59
- if (scrollData) {
60
- const { scrollOffset } = JSON.parse(scrollData);
61
- globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0);
62
- }
63
- // Update flag value
64
- initLoadedRef.current = true;
65
- // Return cached rows and state
66
- return [rows, state];
67
- }
68
- return undefined;
69
- };
70
- const onListScroll = (props) => {
71
- if (!cacheKey || !initLoadedRef.current)
72
- return;
73
- sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
74
- };
75
47
  // Watch container
76
48
  const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
77
49
  const rect = dimensions[0][2];
@@ -86,12 +58,11 @@ export function FixedListPage(props) {
86
58
  : adjustHeight(height, rect);
87
59
  return (_jsx(Box, { id: "list-container", sx: {
88
60
  height: height + "px"
89
- }, children: _jsx(ScrollerListEx, { autoLoad: false, height: height, loadData: localLoadData, mRef: refs, onUpdateRows: GridUtils.getUpdateRowsHandler(cacheKey), onInitLoad: onInitLoad, onScroll: onListScroll, oRef: (element) => {
90
- if (element != null)
91
- updateScrollContainer(element);
92
- }, ...rest }) }));
61
+ }, children: _jsx(ScrollerListEx, { autoLoad: false, height: height, loadData: localLoadData, mRef: refs, ...rest }) }));
93
62
  }
94
63
  }, [rect]);
64
+ // Search data
65
+ const searchData = useSearchParamsWithCache(cacheKey);
95
66
  const f = typeof fields == "function" ? fields(searchData ?? {}) : fields;
96
67
  const { paddings, ...pageRest } = pageProps;
97
68
  // Layout
@@ -27,7 +27,6 @@ export function ListPage(props) {
27
27
  if (first)
28
28
  reset();
29
29
  });
30
- const initLoadedRef = React.useRef(null);
31
30
  const reset = () => {
32
31
  if (states.data == null || states.ref == null)
33
32
  return;
@@ -46,36 +45,9 @@ export function ListPage(props) {
46
45
  const rect = dimensions[0][2];
47
46
  // Search data
48
47
  const searchData = useSearchParamsWithCache(cacheKey);
49
- const onInitLoad = (ref) => {
50
- // Avoid repeatedly load from cache
51
- if (initLoadedRef.current || !cacheKey)
52
- return undefined;
53
- // Cache data
54
- const cacheData = GridUtils.getCacheData(cacheKey, cacheMinutes);
55
- if (cacheData) {
56
- const { rows, state } = cacheData;
57
- GridUtils.mergeSearchData(state, searchData);
58
- // Scroll position
59
- const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
60
- if (scrollData) {
61
- const { scrollOffset } = JSON.parse(scrollData);
62
- globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0);
63
- }
64
- // Update flag value
65
- initLoadedRef.current = true;
66
- // Return cached rows and state
67
- return [rows, state];
68
- }
69
- return undefined;
70
- };
71
- const onListScroll = (props) => {
72
- if (!cacheKey || !initLoadedRef.current)
73
- return;
74
- sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
75
- };
76
48
  const f = typeof fields == "function" ? fields(searchData ?? {}) : fields;
77
49
  // Layout
78
50
  return (_jsx(CommonPage, { ...pageProps, scrollContainer: globalThis, children: _jsxs(Stack, { children: [_jsx(Box, { ref: dimensions[0][0], sx: {
79
51
  paddingBottom: pageProps.paddings
80
- }, children: rect && rect.width > 100 && (_jsx(SearchBar, { fields: f, onSubmit: onSubmit, top: searchBarTop, width: rect.width })) }), _jsx(ScrollerListEx, { autoLoad: false, loadData: localLoadData, onUpdateRows: GridUtils.getUpdateRowsHandler(cacheKey), onInitLoad: onInitLoad, onScroll: onListScroll, mRef: refs, ...rest })] }) }));
52
+ }, children: rect && rect.width > 100 && (_jsx(SearchBar, { fields: f, onSubmit: onSubmit, top: searchBarTop, width: rect.width })) }), _jsx(ScrollerListEx, { autoLoad: false, loadData: localLoadData, mRef: refs, ...rest })] }) }));
81
53
  }
@@ -1,7 +1,6 @@
1
1
  import React from "react";
2
2
  import type { DataGridPageProps } from "./DataGridPageProps";
3
- import type { ScrollerListExInnerItemRendererProps, ScrollerListExItemSize } from "../ScrollerListEx";
4
- import { ListChildComponentProps } from "react-window";
3
+ import type { ScrollerListExItemSize, ScrollerListExProps } from "../ScrollerListEx";
5
4
  import { GridMethodRef } from "@etsoo/react";
6
5
  import type { OperationMessageHandlerAll } from "../messages/OperationMessageHandler";
7
6
  /**
@@ -19,14 +18,10 @@ export type ResponsePageProps<T extends object, F> = DataGridPageProps<T, F> & {
19
18
  * Min width to show Datagrid
20
19
  */
21
20
  dataGridMinWidth?: number;
22
- /**
23
- * Inner item renderer
24
- */
25
- innerItemRenderer: (props: ScrollerListExInnerItemRendererProps<T>) => React.ReactNode;
26
21
  /**
27
22
  * Item renderer
28
23
  */
29
- itemRenderer?: (props: ListChildComponentProps<T>) => React.ReactElement;
24
+ itemRenderer?: ScrollerListExProps<T>["itemRenderer"];
30
25
  /**
31
26
  * Item size, a function indicates its a variable size list
32
27
  */
@@ -0,0 +1,2 @@
1
+ import { ScrollerGridProps } from "@etsoo/react";
2
+ export declare function useGridCacheInitLoad<T extends object>(cacheKey: string | undefined, cacheMinutes: number): ScrollerGridProps<T>["onInitLoad"];
@@ -0,0 +1,35 @@
1
+ import { useSearchParamsWithCache } from "@etsoo/react";
2
+ import React from "react";
3
+ import { GridUtils } from "../GridUtils";
4
+ import { ExtendUtils } from "@etsoo/shared";
5
+ export function useGridCacheInitLoad(cacheKey, cacheMinutes) {
6
+ // Reference
7
+ const ref = React.useRef(null);
8
+ // Search data
9
+ const searchData = useSearchParamsWithCache(cacheKey);
10
+ // Avoid repeatedly load from cache
11
+ if (ref.current || !cacheKey)
12
+ return undefined;
13
+ // Cache data
14
+ const cacheData = GridUtils.getCacheData(cacheKey, cacheMinutes);
15
+ if (cacheData) {
16
+ const { rows, state } = cacheData;
17
+ GridUtils.mergeSearchData(state, searchData);
18
+ // Update flag value
19
+ ref.current = true;
20
+ return (ref) => {
21
+ // Scroll position
22
+ const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
23
+ if (scrollData) {
24
+ const data = JSON.parse(scrollData);
25
+ ExtendUtils.waitFor(() => ref.scrollToCell({
26
+ rowIndex: data.rowStartIndex,
27
+ columnIndex: data.columnStartIndex
28
+ }), 100);
29
+ }
30
+ // Return cached rows and state
31
+ return [rows, state];
32
+ };
33
+ }
34
+ return undefined;
35
+ }
@@ -0,0 +1,2 @@
1
+ import { ScrollerListProps } from "@etsoo/react";
2
+ export declare function useListCacheInitLoad<T extends object>(cacheKey: string | undefined, cacheMinutes: number): ScrollerListProps<T>["onInitLoad"];
@@ -0,0 +1,32 @@
1
+ import { useSearchParamsWithCache } from "@etsoo/react";
2
+ import React from "react";
3
+ import { GridUtils } from "../GridUtils";
4
+ import { ExtendUtils } from "@etsoo/shared";
5
+ export function useListCacheInitLoad(cacheKey, cacheMinutes) {
6
+ // Reference
7
+ const ref = React.useRef(null);
8
+ // Search data
9
+ const searchData = useSearchParamsWithCache(cacheKey);
10
+ // Avoid repeatedly load from cache
11
+ if (ref.current || !cacheKey)
12
+ return undefined;
13
+ // Cache data
14
+ const cacheData = GridUtils.getCacheData(cacheKey, cacheMinutes);
15
+ if (cacheData) {
16
+ const { rows, state } = cacheData;
17
+ GridUtils.mergeSearchData(state, searchData);
18
+ // Update flag value
19
+ ref.current = true;
20
+ return (ref) => {
21
+ // Scroll position
22
+ const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
23
+ if (scrollData) {
24
+ const data = JSON.parse(scrollData);
25
+ ExtendUtils.waitFor(() => ref.scrollToRow({ index: data.startIndex }), 100);
26
+ }
27
+ // Return cached rows and state
28
+ return [rows, state];
29
+ };
30
+ }
31
+ return undefined;
32
+ }