@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.
- package/__tests__/ReactAppTests.tsx +12 -7
- package/__tests__/SelectEx.tsx +1 -1
- package/lib/cjs/DataGridEx.d.ts +8 -1
- package/lib/cjs/DataGridEx.js +71 -56
- package/lib/cjs/DataGridRenderers.d.ts +1 -1
- package/lib/cjs/DataGridRenderers.js +1 -1
- package/lib/cjs/MUUtils.d.ts +0 -9
- package/lib/cjs/MUUtils.js +0 -26
- package/lib/cjs/MobileListItemRenderer.d.ts +2 -2
- package/lib/cjs/ResponsibleContainer.d.ts +2 -7
- package/lib/cjs/ResponsibleContainer.js +8 -57
- package/lib/cjs/ScrollerListEx.d.ts +24 -9
- package/lib/cjs/ScrollerListEx.js +35 -38
- package/lib/cjs/TableEx.d.ts +7 -0
- package/lib/cjs/TableEx.js +6 -12
- package/lib/cjs/pages/DataGridPage.js +3 -32
- package/lib/cjs/pages/FixedListPage.js +5 -34
- package/lib/cjs/pages/ListPage.js +1 -29
- package/lib/cjs/pages/ResponsivePage.d.ts +2 -7
- package/lib/cjs/uses/useGridCacheInitLoad.d.ts +2 -0
- package/lib/cjs/uses/useGridCacheInitLoad.js +41 -0
- package/lib/cjs/uses/useListCacheInitLoad.d.ts +2 -0
- package/lib/cjs/uses/useListCacheInitLoad.js +38 -0
- package/lib/mjs/DataGridEx.d.ts +8 -1
- package/lib/mjs/DataGridEx.js +71 -56
- package/lib/mjs/DataGridRenderers.d.ts +1 -1
- package/lib/mjs/DataGridRenderers.js +1 -1
- package/lib/mjs/MUUtils.d.ts +0 -9
- package/lib/mjs/MUUtils.js +0 -26
- package/lib/mjs/MobileListItemRenderer.d.ts +2 -2
- package/lib/mjs/ResponsibleContainer.d.ts +2 -7
- package/lib/mjs/ResponsibleContainer.js +8 -57
- package/lib/mjs/ScrollerListEx.d.ts +24 -9
- package/lib/mjs/ScrollerListEx.js +35 -38
- package/lib/mjs/TableEx.d.ts +7 -0
- package/lib/mjs/TableEx.js +6 -12
- package/lib/mjs/pages/DataGridPage.js +3 -32
- package/lib/mjs/pages/FixedListPage.js +5 -34
- package/lib/mjs/pages/ListPage.js +1 -29
- package/lib/mjs/pages/ResponsivePage.d.ts +2 -7
- package/lib/mjs/uses/useGridCacheInitLoad.d.ts +2 -0
- package/lib/mjs/uses/useGridCacheInitLoad.js +35 -0
- package/lib/mjs/uses/useListCacheInitLoad.d.ts +2 -0
- package/lib/mjs/uses/useListCacheInitLoad.js +32 -0
- package/package.json +18 -19
- package/src/DataGridEx.tsx +151 -108
- package/src/DataGridRenderers.tsx +2 -1
- package/src/MUUtils.ts +0 -33
- package/src/MobileListItemRenderer.tsx +2 -2
- package/src/ResponsibleContainer.tsx +21 -94
- package/src/ScrollerListEx.tsx +109 -121
- package/src/TableEx.tsx +20 -12
- package/src/pages/DataGridPage.tsx +3 -49
- package/src/pages/FixedListPage.tsx +5 -49
- package/src/pages/ListPage.tsx +0 -43
- package/src/pages/ResponsivePage.tsx +3 -11
- package/src/uses/useGridCacheInitLoad.ts +55 -0
- package/src/uses/useListCacheInitLoad.ts +51 -0
package/lib/cjs/TableEx.js
CHANGED
|
@@ -34,7 +34,7 @@ function TableEx(props) {
|
|
|
34
34
|
// Theme
|
|
35
35
|
const theme = (0, styles_1.useTheme)();
|
|
36
36
|
// Destruct
|
|
37
|
-
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;
|
|
37
|
+
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;
|
|
38
38
|
const selectable = onSelectChange != null;
|
|
39
39
|
// Rows per page
|
|
40
40
|
let rowsPerPageLocal;
|
|
@@ -90,6 +90,9 @@ function TableEx(props) {
|
|
|
90
90
|
});
|
|
91
91
|
};
|
|
92
92
|
react_2.default.useImperativeHandle(mRef, () => ({
|
|
93
|
+
get element() {
|
|
94
|
+
return null;
|
|
95
|
+
},
|
|
93
96
|
delete(index) {
|
|
94
97
|
const item = rows.at(index);
|
|
95
98
|
if (item) {
|
|
@@ -104,20 +107,11 @@ function TableEx(props) {
|
|
|
104
107
|
newRows.splice(start, 0, item);
|
|
105
108
|
setRows(newRows);
|
|
106
109
|
},
|
|
107
|
-
/**
|
|
108
|
-
* Refresh data
|
|
109
|
-
*/
|
|
110
110
|
refresh() {
|
|
111
111
|
loadDataLocal();
|
|
112
112
|
},
|
|
113
|
-
/**
|
|
114
|
-
* Reset
|
|
115
|
-
*/
|
|
116
113
|
reset,
|
|
117
|
-
|
|
118
|
-
// Not implemented
|
|
119
|
-
},
|
|
120
|
-
scrollToItemRef(index) {
|
|
114
|
+
scrollToRow(param) {
|
|
121
115
|
// Not implemented
|
|
122
116
|
}
|
|
123
117
|
}), []);
|
|
@@ -291,7 +285,7 @@ function TableEx(props) {
|
|
|
291
285
|
rowIndex,
|
|
292
286
|
columnIndex,
|
|
293
287
|
cellProps,
|
|
294
|
-
|
|
288
|
+
triggerChange: () => onDataChange?.(rows, rowIndex, columnIndex)
|
|
295
289
|
})) : ((0, jsx_runtime_1.jsx)(react_2.default.Fragment, { children: "\u00A0" }));
|
|
296
290
|
return ((0, jsx_runtime_1.jsx)(TableCell_1.default, { ...cellProps, children: child }, `${rowId}${columnIndex}`));
|
|
297
291
|
})] }, rowId));
|
|
@@ -33,9 +33,10 @@ function DataGridPage(props) {
|
|
|
33
33
|
if (ref == null)
|
|
34
34
|
return;
|
|
35
35
|
states.ref = ref;
|
|
36
|
+
if (ref.element)
|
|
37
|
+
setStates({ element: ref.element });
|
|
36
38
|
//setStates({ ref });
|
|
37
39
|
});
|
|
38
|
-
const initLoadedRef = react_2.default.useRef(null);
|
|
39
40
|
// On submit callback
|
|
40
41
|
const onSubmit = (data, _reset) => {
|
|
41
42
|
setStates({ data });
|
|
@@ -45,33 +46,6 @@ function DataGridPage(props) {
|
|
|
45
46
|
};
|
|
46
47
|
// Search data
|
|
47
48
|
const searchData = (0, react_1.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_1.GridUtils.getCacheData(cacheKey, cacheMinutes);
|
|
54
|
-
if (cacheData) {
|
|
55
|
-
const { rows, state } = cacheData;
|
|
56
|
-
GridUtils_1.GridUtils.mergeSearchData(state, searchData);
|
|
57
|
-
// Scroll position
|
|
58
|
-
const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
|
|
59
|
-
if (scrollData) {
|
|
60
|
-
const { scrollLeft, scrollTop } = JSON.parse(scrollData);
|
|
61
|
-
globalThis.setTimeout(() => ref.scrollTo({ scrollLeft, scrollTop }), 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 onGridScroll = (props) => {
|
|
71
|
-
if (!cacheKey || !initLoadedRef.current)
|
|
72
|
-
return;
|
|
73
|
-
sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
|
|
74
|
-
};
|
|
75
49
|
// Watch container
|
|
76
50
|
const { dimensions } = (0, react_1.useDimensions)(1, undefined, sizeReadyMiliseconds);
|
|
77
51
|
const rect = dimensions[0][2];
|
|
@@ -96,10 +70,7 @@ function DataGridPage(props) {
|
|
|
96
70
|
const gridHeight = states.height;
|
|
97
71
|
if (gridHeight == null)
|
|
98
72
|
return;
|
|
99
|
-
return ((0, jsx_runtime_1.jsx)(DataGridEx_1.DataGridEx, { autoLoad: false, height: gridHeight, loadData: localLoadData, mRef: refs,
|
|
100
|
-
if (element != null)
|
|
101
|
-
setStates({ element });
|
|
102
|
-
}, ...rest }));
|
|
73
|
+
return ((0, jsx_runtime_1.jsx)(DataGridEx_1.DataGridEx, { autoLoad: false, height: gridHeight, loadData: localLoadData, mRef: refs, ...rest }));
|
|
103
74
|
}, [states.height]);
|
|
104
75
|
const { ref, data } = states;
|
|
105
76
|
react_2.default.useEffect(() => {
|
|
@@ -25,7 +25,6 @@ function FixedListPage(props) {
|
|
|
25
25
|
pageProps.paddings ??= MUGlobal_1.MUGlobal.pagePaddings;
|
|
26
26
|
// States
|
|
27
27
|
const [states] = react_2.default.useState({});
|
|
28
|
-
const initLoadedRef = react_2.default.useRef(null);
|
|
29
28
|
// Scroll container
|
|
30
29
|
const [scrollContainer, updateScrollContainer] = react_2.default.useState();
|
|
31
30
|
const refs = (0, react_1.useCombinedRefs)(mRef, (ref) => {
|
|
@@ -33,6 +32,8 @@ function FixedListPage(props) {
|
|
|
33
32
|
return;
|
|
34
33
|
const first = states.ref == null;
|
|
35
34
|
states.ref = ref;
|
|
35
|
+
if (ref.element)
|
|
36
|
+
updateScrollContainer(ref.element);
|
|
36
37
|
if (first)
|
|
37
38
|
reset();
|
|
38
39
|
});
|
|
@@ -49,35 +50,6 @@ function FixedListPage(props) {
|
|
|
49
50
|
const localLoadData = (props, lastItem) => {
|
|
50
51
|
return loadData(GridUtils_1.GridUtils.createLoader(props, fieldTemplate, cacheKey, false), lastItem);
|
|
51
52
|
};
|
|
52
|
-
// Search data
|
|
53
|
-
const searchData = (0, react_1.useSearchParamsWithCache)(cacheKey);
|
|
54
|
-
const onInitLoad = (ref) => {
|
|
55
|
-
// Avoid repeatedly load from cache
|
|
56
|
-
if (initLoadedRef.current || !cacheKey)
|
|
57
|
-
return undefined;
|
|
58
|
-
// Cache data
|
|
59
|
-
const cacheData = GridUtils_1.GridUtils.getCacheData(cacheKey, cacheMinutes);
|
|
60
|
-
if (cacheData) {
|
|
61
|
-
const { rows, state } = cacheData;
|
|
62
|
-
GridUtils_1.GridUtils.mergeSearchData(state, searchData);
|
|
63
|
-
// Scroll position
|
|
64
|
-
const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
|
|
65
|
-
if (scrollData) {
|
|
66
|
-
const { scrollOffset } = JSON.parse(scrollData);
|
|
67
|
-
globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0);
|
|
68
|
-
}
|
|
69
|
-
// Update flag value
|
|
70
|
-
initLoadedRef.current = true;
|
|
71
|
-
// Return cached rows and state
|
|
72
|
-
return [rows, state];
|
|
73
|
-
}
|
|
74
|
-
return undefined;
|
|
75
|
-
};
|
|
76
|
-
const onListScroll = (props) => {
|
|
77
|
-
if (!cacheKey || !initLoadedRef.current)
|
|
78
|
-
return;
|
|
79
|
-
sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
|
|
80
|
-
};
|
|
81
53
|
// Watch container
|
|
82
54
|
const { dimensions } = (0, react_1.useDimensions)(1, undefined, sizeReadyMiliseconds);
|
|
83
55
|
const rect = dimensions[0][2];
|
|
@@ -92,12 +64,11 @@ function FixedListPage(props) {
|
|
|
92
64
|
: adjustHeight(height, rect);
|
|
93
65
|
return ((0, jsx_runtime_1.jsx)(Box_1.default, { id: "list-container", sx: {
|
|
94
66
|
height: height + "px"
|
|
95
|
-
}, children: (0, jsx_runtime_1.jsx)(ScrollerListEx_1.ScrollerListEx, { autoLoad: false, height: height, loadData: localLoadData, mRef: refs,
|
|
96
|
-
if (element != null)
|
|
97
|
-
updateScrollContainer(element);
|
|
98
|
-
}, ...rest }) }));
|
|
67
|
+
}, children: (0, jsx_runtime_1.jsx)(ScrollerListEx_1.ScrollerListEx, { autoLoad: false, height: height, loadData: localLoadData, mRef: refs, ...rest }) }));
|
|
99
68
|
}
|
|
100
69
|
}, [rect]);
|
|
70
|
+
// Search data
|
|
71
|
+
const searchData = (0, react_1.useSearchParamsWithCache)(cacheKey);
|
|
101
72
|
const f = typeof fields == "function" ? fields(searchData ?? {}) : fields;
|
|
102
73
|
const { paddings, ...pageRest } = pageProps;
|
|
103
74
|
// Layout
|
|
@@ -33,7 +33,6 @@ function ListPage(props) {
|
|
|
33
33
|
if (first)
|
|
34
34
|
reset();
|
|
35
35
|
});
|
|
36
|
-
const initLoadedRef = react_2.default.useRef(null);
|
|
37
36
|
const reset = () => {
|
|
38
37
|
if (states.data == null || states.ref == null)
|
|
39
38
|
return;
|
|
@@ -52,36 +51,9 @@ function ListPage(props) {
|
|
|
52
51
|
const rect = dimensions[0][2];
|
|
53
52
|
// Search data
|
|
54
53
|
const searchData = (0, react_1.useSearchParamsWithCache)(cacheKey);
|
|
55
|
-
const onInitLoad = (ref) => {
|
|
56
|
-
// Avoid repeatedly load from cache
|
|
57
|
-
if (initLoadedRef.current || !cacheKey)
|
|
58
|
-
return undefined;
|
|
59
|
-
// Cache data
|
|
60
|
-
const cacheData = GridUtils_1.GridUtils.getCacheData(cacheKey, cacheMinutes);
|
|
61
|
-
if (cacheData) {
|
|
62
|
-
const { rows, state } = cacheData;
|
|
63
|
-
GridUtils_1.GridUtils.mergeSearchData(state, searchData);
|
|
64
|
-
// Scroll position
|
|
65
|
-
const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
|
|
66
|
-
if (scrollData) {
|
|
67
|
-
const { scrollOffset } = JSON.parse(scrollData);
|
|
68
|
-
globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0);
|
|
69
|
-
}
|
|
70
|
-
// Update flag value
|
|
71
|
-
initLoadedRef.current = true;
|
|
72
|
-
// Return cached rows and state
|
|
73
|
-
return [rows, state];
|
|
74
|
-
}
|
|
75
|
-
return undefined;
|
|
76
|
-
};
|
|
77
|
-
const onListScroll = (props) => {
|
|
78
|
-
if (!cacheKey || !initLoadedRef.current)
|
|
79
|
-
return;
|
|
80
|
-
sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
|
|
81
|
-
};
|
|
82
54
|
const f = typeof fields == "function" ? fields(searchData ?? {}) : fields;
|
|
83
55
|
// Layout
|
|
84
56
|
return ((0, jsx_runtime_1.jsx)(CommonPage_1.CommonPage, { ...pageProps, scrollContainer: globalThis, children: (0, jsx_runtime_1.jsxs)(Stack_1.default, { children: [(0, jsx_runtime_1.jsx)(Box_1.default, { ref: dimensions[0][0], sx: {
|
|
85
57
|
paddingBottom: pageProps.paddings
|
|
86
|
-
}, children: rect && rect.width > 100 && ((0, jsx_runtime_1.jsx)(SearchBar_1.SearchBar, { fields: f, onSubmit: onSubmit, top: searchBarTop, width: rect.width })) }), (0, jsx_runtime_1.jsx)(ScrollerListEx_1.ScrollerListEx, { autoLoad: false, loadData: localLoadData,
|
|
58
|
+
}, children: rect && rect.width > 100 && ((0, jsx_runtime_1.jsx)(SearchBar_1.SearchBar, { fields: f, onSubmit: onSubmit, top: searchBarTop, width: rect.width })) }), (0, jsx_runtime_1.jsx)(ScrollerListEx_1.ScrollerListEx, { autoLoad: false, loadData: localLoadData, mRef: refs, ...rest })] }) }));
|
|
87
59
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { DataGridPageProps } from "./DataGridPageProps";
|
|
3
|
-
import type {
|
|
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?:
|
|
24
|
+
itemRenderer?: ScrollerListExProps<T>["itemRenderer"];
|
|
30
25
|
/**
|
|
31
26
|
* Item size, a function indicates its a variable size list
|
|
32
27
|
*/
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.useGridCacheInitLoad = useGridCacheInitLoad;
|
|
7
|
+
const react_1 = require("@etsoo/react");
|
|
8
|
+
const react_2 = __importDefault(require("react"));
|
|
9
|
+
const GridUtils_1 = require("../GridUtils");
|
|
10
|
+
const shared_1 = require("@etsoo/shared");
|
|
11
|
+
function useGridCacheInitLoad(cacheKey, cacheMinutes) {
|
|
12
|
+
// Reference
|
|
13
|
+
const ref = react_2.default.useRef(null);
|
|
14
|
+
// Search data
|
|
15
|
+
const searchData = (0, react_1.useSearchParamsWithCache)(cacheKey);
|
|
16
|
+
// Avoid repeatedly load from cache
|
|
17
|
+
if (ref.current || !cacheKey)
|
|
18
|
+
return undefined;
|
|
19
|
+
// Cache data
|
|
20
|
+
const cacheData = GridUtils_1.GridUtils.getCacheData(cacheKey, cacheMinutes);
|
|
21
|
+
if (cacheData) {
|
|
22
|
+
const { rows, state } = cacheData;
|
|
23
|
+
GridUtils_1.GridUtils.mergeSearchData(state, searchData);
|
|
24
|
+
// Update flag value
|
|
25
|
+
ref.current = true;
|
|
26
|
+
return (ref) => {
|
|
27
|
+
// Scroll position
|
|
28
|
+
const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
|
|
29
|
+
if (scrollData) {
|
|
30
|
+
const data = JSON.parse(scrollData);
|
|
31
|
+
shared_1.ExtendUtils.waitFor(() => ref.scrollToCell({
|
|
32
|
+
rowIndex: data.rowStartIndex,
|
|
33
|
+
columnIndex: data.columnStartIndex
|
|
34
|
+
}), 100);
|
|
35
|
+
}
|
|
36
|
+
// Return cached rows and state
|
|
37
|
+
return [rows, state];
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.useListCacheInitLoad = useListCacheInitLoad;
|
|
7
|
+
const react_1 = require("@etsoo/react");
|
|
8
|
+
const react_2 = __importDefault(require("react"));
|
|
9
|
+
const GridUtils_1 = require("../GridUtils");
|
|
10
|
+
const shared_1 = require("@etsoo/shared");
|
|
11
|
+
function useListCacheInitLoad(cacheKey, cacheMinutes) {
|
|
12
|
+
// Reference
|
|
13
|
+
const ref = react_2.default.useRef(null);
|
|
14
|
+
// Search data
|
|
15
|
+
const searchData = (0, react_1.useSearchParamsWithCache)(cacheKey);
|
|
16
|
+
// Avoid repeatedly load from cache
|
|
17
|
+
if (ref.current || !cacheKey)
|
|
18
|
+
return undefined;
|
|
19
|
+
// Cache data
|
|
20
|
+
const cacheData = GridUtils_1.GridUtils.getCacheData(cacheKey, cacheMinutes);
|
|
21
|
+
if (cacheData) {
|
|
22
|
+
const { rows, state } = cacheData;
|
|
23
|
+
GridUtils_1.GridUtils.mergeSearchData(state, searchData);
|
|
24
|
+
// Update flag value
|
|
25
|
+
ref.current = true;
|
|
26
|
+
return (ref) => {
|
|
27
|
+
// Scroll position
|
|
28
|
+
const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
|
|
29
|
+
if (scrollData) {
|
|
30
|
+
const data = JSON.parse(scrollData);
|
|
31
|
+
shared_1.ExtendUtils.waitFor(() => ref.scrollToRow({ index: data.startIndex }), 100);
|
|
32
|
+
}
|
|
33
|
+
// Return cached rows and state
|
|
34
|
+
return [rows, state];
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
package/lib/mjs/DataGridEx.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export type DataGridExFooterItemRendererProps<T extends object> = {
|
|
|
14
14
|
/**
|
|
15
15
|
* Extended DataGrid with VariableSizeGrid props
|
|
16
16
|
*/
|
|
17
|
-
export type DataGridExProps<T extends object, P extends GridJsonData = GridLoadDataProps> = Omit<ScrollerGridProps<T, P>, "
|
|
17
|
+
export type DataGridExProps<T extends object, P extends GridJsonData = GridLoadDataProps> = Omit<ScrollerGridProps<T, P>, "cellComponent" | "columnCount" | "columnWidth" | "onClick" | "onDoubleClick" | "onInitLoad" | "width"> & {
|
|
18
18
|
/**
|
|
19
19
|
* Alternating colors for odd/even rows
|
|
20
20
|
*/
|
|
@@ -70,6 +70,13 @@ export type DataGridExProps<T extends object, P extends GridJsonData = GridLoadD
|
|
|
70
70
|
* Click handler
|
|
71
71
|
*/
|
|
72
72
|
onClick?: MouseEventWithDataHandler<T>;
|
|
73
|
+
/**
|
|
74
|
+
* Data change handler
|
|
75
|
+
* @param rows Rows
|
|
76
|
+
* @param rowIndex Row index
|
|
77
|
+
* @param columnIndex Column index
|
|
78
|
+
*/
|
|
79
|
+
onDataChange?: (rows: T[], rowIndex: number, columnIndex: number) => void;
|
|
73
80
|
/**
|
|
74
81
|
* Selectable to support hover over and out effect and row clickable
|
|
75
82
|
* @default true
|
package/lib/mjs/DataGridEx.js
CHANGED
|
@@ -9,6 +9,8 @@ import Box from "@mui/material/Box";
|
|
|
9
9
|
import TableSortLabel from "@mui/material/TableSortLabel";
|
|
10
10
|
import Checkbox from "@mui/material/Checkbox";
|
|
11
11
|
import Paper from "@mui/material/Paper";
|
|
12
|
+
import { GridUtils } from "./GridUtils";
|
|
13
|
+
import { useGridCacheInitLoad } from "./uses/useGridCacheInitLoad";
|
|
12
14
|
// Borders
|
|
13
15
|
const boldBorder = "2px solid rgba(224, 224, 224, 1)";
|
|
14
16
|
const thinBorder = "1px solid rgba(224, 224, 224, 1)";
|
|
@@ -128,7 +130,7 @@ export function DataGridEx(props) {
|
|
|
128
130
|
}) }));
|
|
129
131
|
}
|
|
130
132
|
// Destruct
|
|
131
|
-
const { alternatingColors = [theme.palette.grey[100], undefined], borderRowsCount, bottomHeight = 53, checkable = false, className, columns, defaultOrderBy, height, headerHeight = 56, headerRenderer = defaultHeaderRenderer, footerRenderer = defaultFooterRenderer, footerItemRenderer = DataGridRenderers.defaultFooterItemRenderer, hideFooter = false, hoverColor = "#f6f9fb", idField = "id", mRef = React.createRef(), onClick, onDoubleClick, selectable = true, selectedColor = "#edf4fb", width, ...rest } = props;
|
|
133
|
+
const { alternatingColors = [theme.palette.grey[100], undefined], borderRowsCount, bottomHeight = 53, cacheKey, cacheMinutes = 15, checkable = false, className, columns, defaultOrderBy, height, headerHeight = 56, headerRenderer = defaultHeaderRenderer, footerRenderer = defaultFooterRenderer, footerItemRenderer = DataGridRenderers.defaultFooterItemRenderer, hideFooter = false, hoverColor = "#f6f9fb", idField = "id", mRef = React.createRef(), onClick, onDataChange, onDoubleClick, onUpdateRows, selectable = true, selectedColor = "#edf4fb", width, ...rest } = props;
|
|
132
134
|
if (checkable) {
|
|
133
135
|
const cbColumn = {
|
|
134
136
|
field: "selected", // Avoid validation from data model
|
|
@@ -161,6 +163,8 @@ export function DataGridEx(props) {
|
|
|
161
163
|
columns.unshift(cbColumn);
|
|
162
164
|
}
|
|
163
165
|
}
|
|
166
|
+
// Init handler
|
|
167
|
+
const initHandler = useGridCacheInitLoad(cacheKey, cacheMinutes);
|
|
164
168
|
const refs = React.useRef({});
|
|
165
169
|
const mRefLocal = useCombinedRefs(mRef, (ref) => {
|
|
166
170
|
if (ref == null)
|
|
@@ -219,57 +223,6 @@ export function DataGridEx(props) {
|
|
|
219
223
|
div.classList.remove("DataGridEx-Hover");
|
|
220
224
|
});
|
|
221
225
|
};
|
|
222
|
-
/**
|
|
223
|
-
* Item renderer
|
|
224
|
-
*/
|
|
225
|
-
const itemRenderer = ({ columnIndex, rowIndex, style, data, selectedItems, setItems }) => {
|
|
226
|
-
// Column
|
|
227
|
-
const { align, cellRenderer = DataGridRenderers.defaultCellRenderer, cellBoxStyle, field, type, valueFormatter, renderProps } = columns[columnIndex];
|
|
228
|
-
// Props
|
|
229
|
-
const formatProps = {
|
|
230
|
-
data,
|
|
231
|
-
field,
|
|
232
|
-
rowIndex,
|
|
233
|
-
columnIndex
|
|
234
|
-
};
|
|
235
|
-
let rowClass = `DataGridEx-Cell${rowIndex % 2}`;
|
|
236
|
-
if (borderRowsCount != null &&
|
|
237
|
-
borderRowsCount > 0 &&
|
|
238
|
-
(rowIndex + 1) % borderRowsCount === 0) {
|
|
239
|
-
rowClass += ` DataGridEx-Cell-Border`;
|
|
240
|
-
}
|
|
241
|
-
// Selected
|
|
242
|
-
const selected = data != null &&
|
|
243
|
-
(selectedRowIndex.current === rowIndex ||
|
|
244
|
-
selectedItems.some((selectedItem) => selectedItem != null && selectedItem[idField] === data[idField]));
|
|
245
|
-
if (selected) {
|
|
246
|
-
rowClass += ` DataGridEx-Selected`;
|
|
247
|
-
}
|
|
248
|
-
// Box style
|
|
249
|
-
const boxStyle = data == null || cellBoxStyle == null
|
|
250
|
-
? undefined
|
|
251
|
-
: typeof cellBoxStyle === "function"
|
|
252
|
-
? cellBoxStyle(data)
|
|
253
|
-
: cellBoxStyle;
|
|
254
|
-
const cellProps = {
|
|
255
|
-
className: "DataGridEx-Cell",
|
|
256
|
-
textAlign: GridAlignGet(align, type),
|
|
257
|
-
sx: { ...boxStyle }
|
|
258
|
-
};
|
|
259
|
-
const child = cellRenderer({
|
|
260
|
-
data,
|
|
261
|
-
field,
|
|
262
|
-
formattedValue: valueFormatter ? valueFormatter(formatProps) : undefined,
|
|
263
|
-
selected,
|
|
264
|
-
type,
|
|
265
|
-
rowIndex,
|
|
266
|
-
columnIndex,
|
|
267
|
-
cellProps,
|
|
268
|
-
renderProps: typeof renderProps === "function" ? renderProps(data) : renderProps,
|
|
269
|
-
setItems
|
|
270
|
-
});
|
|
271
|
-
return (_jsx("div", { className: rowClass, style: style, "data-row": rowIndex, "data-column": columnIndex, onMouseDown: selectable && !checkable ? handleMouseDown : undefined, onMouseOver: selectable ? handleMouseOver : undefined, onMouseOut: selectable ? handleMouseOut : undefined, onClick: (event) => onClick && data != null && onClick(event, data), onDoubleClick: (event) => onDoubleClick && data != null && onDoubleClick(event, data), children: _jsx(Box, { ...cellProps, onMouseEnter: handleMouseEnter, children: child }) }));
|
|
272
|
-
};
|
|
273
226
|
// Column width calculator
|
|
274
227
|
const widthCalculator = React.useMemo(() => DataGridExCalColumns(columns), [columns]);
|
|
275
228
|
// Column width
|
|
@@ -287,12 +240,74 @@ export function DataGridEx(props) {
|
|
|
287
240
|
const sharedWidth = leftWidth > 0 ? leftWidth / widthCalculator.unset : 0;
|
|
288
241
|
return (column.minWidth || minWidth) + sharedWidth;
|
|
289
242
|
}, [columns, width]);
|
|
243
|
+
const onUpdateRowsHandler = React.useCallback((rows, state) => {
|
|
244
|
+
GridUtils.getUpdateRowsHandler(cacheKey)?.(rows, state);
|
|
245
|
+
onUpdateRows?.(rows, state);
|
|
246
|
+
}, [onUpdateRows, cacheKey]);
|
|
290
247
|
// Table
|
|
291
248
|
const table = React.useMemo(() => {
|
|
292
|
-
return (_jsx(ScrollerGrid, { className: Utils.mergeClasses("DataGridEx-Body", "DataGridEx-CustomBar", className, createGridStyle(alternatingColors, selectedColor, hoverColor)),
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
249
|
+
return (_jsx(ScrollerGrid, { className: Utils.mergeClasses("DataGridEx-Body", "DataGridEx-CustomBar", className, createGridStyle(alternatingColors, selectedColor, hoverColor)), onCellsRendered: cacheKey
|
|
250
|
+
? (visibleCells) => sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(visibleCells))
|
|
251
|
+
: undefined, onInitLoad: initHandler, onUpdateRows: onUpdateRowsHandler, cellComponent: ({ rowIndex, columnIndex, style, rows, states }) => {
|
|
252
|
+
// Column
|
|
253
|
+
const { align, cellRenderer = DataGridRenderers.defaultCellRenderer, cellBoxStyle, field, type, valueFormatter, renderProps } = columns[columnIndex];
|
|
254
|
+
// Data
|
|
255
|
+
const data = rows[rowIndex];
|
|
256
|
+
// Props
|
|
257
|
+
const formatProps = {
|
|
258
|
+
data,
|
|
259
|
+
field,
|
|
260
|
+
rowIndex,
|
|
261
|
+
columnIndex
|
|
262
|
+
};
|
|
263
|
+
let rowClass = `DataGridEx-Cell${rowIndex % 2}`;
|
|
264
|
+
if (borderRowsCount != null &&
|
|
265
|
+
borderRowsCount > 0 &&
|
|
266
|
+
(rowIndex + 1) % borderRowsCount === 0) {
|
|
267
|
+
rowClass += ` DataGridEx-Cell-Border`;
|
|
268
|
+
}
|
|
269
|
+
// Selected
|
|
270
|
+
const selected = data != null &&
|
|
271
|
+
(selectedRowIndex.current === rowIndex ||
|
|
272
|
+
states.selectedItems.some((selectedItem) => selectedItem != null &&
|
|
273
|
+
selectedItem[idField] === data[idField]));
|
|
274
|
+
if (selected) {
|
|
275
|
+
rowClass += ` DataGridEx-Selected`;
|
|
276
|
+
}
|
|
277
|
+
// Box style
|
|
278
|
+
const boxStyle = data == null || cellBoxStyle == null
|
|
279
|
+
? undefined
|
|
280
|
+
: typeof cellBoxStyle === "function"
|
|
281
|
+
? cellBoxStyle(data)
|
|
282
|
+
: cellBoxStyle;
|
|
283
|
+
const cellProps = {
|
|
284
|
+
className: "DataGridEx-Cell",
|
|
285
|
+
textAlign: GridAlignGet(align, type),
|
|
286
|
+
sx: { ...boxStyle }
|
|
287
|
+
};
|
|
288
|
+
const child = cellRenderer({
|
|
289
|
+
data,
|
|
290
|
+
field,
|
|
291
|
+
formattedValue: valueFormatter
|
|
292
|
+
? valueFormatter(formatProps)
|
|
293
|
+
: undefined,
|
|
294
|
+
selected,
|
|
295
|
+
type,
|
|
296
|
+
rowIndex,
|
|
297
|
+
columnIndex,
|
|
298
|
+
cellProps,
|
|
299
|
+
renderProps: typeof renderProps === "function"
|
|
300
|
+
? renderProps(data)
|
|
301
|
+
: renderProps,
|
|
302
|
+
triggerChange: () => onDataChange?.(rows, rowIndex, columnIndex)
|
|
303
|
+
});
|
|
304
|
+
return (_jsx("div", { className: rowClass, style: style, "data-row": rowIndex, "data-column": columnIndex, onMouseDown: selectable && !checkable ? handleMouseDown : undefined, onMouseOver: selectable ? handleMouseOver : undefined, onMouseOut: selectable ? handleMouseOut : undefined, onClick: (event) => onClick && data != null && onClick(event, data), onDoubleClick: (event) => onDoubleClick && data != null && onDoubleClick(event, data), children: _jsx(Box, { ...cellProps, onMouseEnter: handleMouseEnter, children: child }) }));
|
|
305
|
+
}, columnCount: columns.length, columnWidth: columnWidth, defaultOrderBy: defaultOrderBy, height: typeof height === "number"
|
|
306
|
+
? height -
|
|
307
|
+
headerHeight -
|
|
308
|
+
(hideFooter ? 0 : bottomHeight + 1) -
|
|
309
|
+
scrollbarSize
|
|
310
|
+
: height, headerRenderer: headerRenderer, idField: idField, footerRenderer: hideFooter ? undefined : footerRenderer, width: Math.max(width ?? 0, widthCalculator.total), mRef: mRefLocal, ...rest }));
|
|
296
311
|
}, [width]);
|
|
297
312
|
return (_jsx(Paper, { sx: {
|
|
298
313
|
fontSize: "0.875rem",
|
|
@@ -10,7 +10,7 @@ export declare namespace DataGridRenderers {
|
|
|
10
10
|
* @param param Props
|
|
11
11
|
* @returns Component
|
|
12
12
|
*/
|
|
13
|
-
function defaultCellRenderer<T extends Record<string, any>>({ cellProps, data, field, formattedValue, columnIndex, type, renderProps }: GridCellRendererProps<T>): React.ReactNode;
|
|
13
|
+
function defaultCellRenderer<T extends Record<string, any>>({ cellProps, data, field, formattedValue, columnIndex, type, renderProps, triggerChange }: GridCellRendererProps<T>): React.ReactNode;
|
|
14
14
|
/**
|
|
15
15
|
* Default footer item renderer
|
|
16
16
|
* @param rows Rows
|
|
@@ -15,7 +15,7 @@ export var DataGridRenderers;
|
|
|
15
15
|
* @param param Props
|
|
16
16
|
* @returns Component
|
|
17
17
|
*/
|
|
18
|
-
function defaultCellRenderer({ cellProps, data, field, formattedValue, columnIndex, type, renderProps }) {
|
|
18
|
+
function defaultCellRenderer({ cellProps, data, field, formattedValue, columnIndex, type, renderProps, triggerChange }) {
|
|
19
19
|
// Is loading
|
|
20
20
|
if (data == null) {
|
|
21
21
|
// First column, show loading indicator
|
package/lib/mjs/MUUtils.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { QueryRQ } from "@etsoo/appscript";
|
|
2
|
-
import { IdType } from "@etsoo/shared";
|
|
3
1
|
import { GridApiCommunity } from "@mui/x-data-grid/internals";
|
|
4
2
|
/**
|
|
5
3
|
* MU utilities
|
|
@@ -12,11 +10,4 @@ export declare namespace MUUtils {
|
|
|
12
10
|
* @returns Results
|
|
13
11
|
*/
|
|
14
12
|
function getGridData<T>(grid: GridApiCommunity, checkField: keyof T | ((item: T) => boolean)): T[];
|
|
15
|
-
/**
|
|
16
|
-
* Setup paging keysets
|
|
17
|
-
* @param data Paging data
|
|
18
|
-
* @param lastItem Last item of the query
|
|
19
|
-
* @param idField Id field
|
|
20
|
-
*/
|
|
21
|
-
function setupPagingKeysets<T, K extends IdType = number>(data: QueryRQ<K>, lastItem: T | undefined, idField: keyof T & string): QueryRQ<K>;
|
|
22
13
|
}
|
package/lib/mjs/MUUtils.js
CHANGED
|
@@ -26,30 +26,4 @@ export var MUUtils;
|
|
|
26
26
|
return items;
|
|
27
27
|
}
|
|
28
28
|
MUUtils.getGridData = getGridData;
|
|
29
|
-
/**
|
|
30
|
-
* Setup paging keysets
|
|
31
|
-
* @param data Paging data
|
|
32
|
-
* @param lastItem Last item of the query
|
|
33
|
-
* @param idField Id field
|
|
34
|
-
*/
|
|
35
|
-
function setupPagingKeysets(data, lastItem, idField) {
|
|
36
|
-
// If the id field is not set for ordering, add it with descending
|
|
37
|
-
if (typeof data.queryPaging === "object") {
|
|
38
|
-
const orderBy = (data.queryPaging.orderBy ??= []);
|
|
39
|
-
const idUpper = idField.toUpperCase();
|
|
40
|
-
if (!orderBy.find((o) => o.field.toUpperCase() === idUpper)) {
|
|
41
|
-
orderBy.push({ field: idField, desc: true, unique: true });
|
|
42
|
-
}
|
|
43
|
-
// Set the paging keysets
|
|
44
|
-
if (lastItem) {
|
|
45
|
-
const keysets = orderBy.map((o) => Reflect.get(lastItem, o.field));
|
|
46
|
-
data.queryPaging.keysets = keysets;
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
data.queryPaging.keysets = undefined;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return data;
|
|
53
|
-
}
|
|
54
|
-
MUUtils.setupPagingKeysets = setupPagingKeysets;
|
|
55
29
|
})(MUUtils || (MUUtils = {}));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ListItemReact } from "@etsoo/react";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { ScrollerListExItemRendererProps } from "./ScrollerListEx";
|
|
4
4
|
/**
|
|
5
5
|
* Default mobile list item renderer
|
|
6
6
|
* @param param0 List renderer props
|
|
@@ -8,7 +8,7 @@ import { ScrollerListExInnerItemRendererProps } from "./ScrollerListEx";
|
|
|
8
8
|
* @param renderer Renderer for card content
|
|
9
9
|
* @returns Component
|
|
10
10
|
*/
|
|
11
|
-
export declare function MobileListItemRenderer<T>({ data, itemHeight, margins }:
|
|
11
|
+
export declare function MobileListItemRenderer<T>({ data, itemHeight, margins }: ScrollerListExItemRendererProps<T>, renderer: (data: T) => [
|
|
12
12
|
string,
|
|
13
13
|
string | undefined,
|
|
14
14
|
React.ReactNode | (ListItemReact | boolean)[],
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { ListChildComponentProps } from "react-window";
|
|
3
2
|
import { GridColumn, GridJsonData, GridMethodRef, GridTemplateType } from "@etsoo/react";
|
|
4
3
|
import { DataGridExProps } from "./DataGridEx";
|
|
5
|
-
import {
|
|
4
|
+
import { ScrollerListExItemSize, ScrollerListExProps } from "./ScrollerListEx";
|
|
6
5
|
import { SxProps, Theme } from "@mui/material/styles";
|
|
7
6
|
/**
|
|
8
7
|
* ResponsibleContainer props
|
|
@@ -41,14 +40,10 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
|
|
|
41
40
|
* Grid height
|
|
42
41
|
*/
|
|
43
42
|
height?: number;
|
|
44
|
-
/**
|
|
45
|
-
* Inner item renderer
|
|
46
|
-
*/
|
|
47
|
-
innerItemRenderer: (props: ScrollerListExInnerItemRendererProps<T>) => React.ReactNode;
|
|
48
43
|
/**
|
|
49
44
|
* Item renderer
|
|
50
45
|
*/
|
|
51
|
-
itemRenderer?:
|
|
46
|
+
itemRenderer?: ScrollerListExProps<T>["itemRenderer"];
|
|
52
47
|
/**
|
|
53
48
|
* Item size, a function indicates its a variable size list
|
|
54
49
|
*/
|