@etsoo/materialui 1.5.72 → 1.5.74
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__/{ResponsePage.tsx → ResponsivePage.tsx} +11 -5
- package/lib/cjs/DataGridEx.d.ts +1 -1
- package/lib/cjs/DataGridEx.js +2 -2
- package/lib/cjs/MobileListItemRenderer.d.ts +1 -1
- package/lib/cjs/MobileListItemRenderer.js +2 -3
- package/lib/cjs/ResponsibleContainer.d.ts +8 -7
- package/lib/cjs/ResponsibleContainer.js +14 -4
- package/lib/cjs/ScrollerListEx.d.ts +5 -20
- package/lib/cjs/ScrollerListEx.js +11 -60
- package/lib/cjs/pages/ResponsivePage.d.ts +8 -7
- package/lib/mjs/DataGridEx.d.ts +1 -1
- package/lib/mjs/DataGridEx.js +2 -2
- package/lib/mjs/MobileListItemRenderer.d.ts +1 -1
- package/lib/mjs/MobileListItemRenderer.js +2 -3
- package/lib/mjs/ResponsibleContainer.d.ts +8 -7
- package/lib/mjs/ResponsibleContainer.js +14 -4
- package/lib/mjs/ScrollerListEx.d.ts +5 -20
- package/lib/mjs/ScrollerListEx.js +11 -60
- package/lib/mjs/pages/ResponsivePage.d.ts +8 -7
- package/package.json +3 -3
- package/src/DataGridEx.tsx +4 -1
- package/src/MobileListItemRenderer.tsx +2 -3
- package/src/ResponsibleContainer.tsx +31 -19
- package/src/ScrollerListEx.tsx +61 -138
- package/src/pages/ResponsivePage.tsx +15 -12
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { act, render } from "@testing-library/react";
|
|
1
|
+
import { act, render, renderHook } from "@testing-library/react";
|
|
2
2
|
import {
|
|
3
|
-
MUGlobal,
|
|
4
3
|
MobileListItemRenderer,
|
|
5
4
|
ReactAppContext,
|
|
6
5
|
ResponsivePage,
|
|
7
6
|
SearchField
|
|
8
7
|
} from "../src";
|
|
9
8
|
import React from "react";
|
|
9
|
+
import { GridMethodRef } from "@etsoo/react";
|
|
10
10
|
|
|
11
11
|
globalThis.ResizeObserver = vi.fn().mockImplementation(() => ({
|
|
12
12
|
observe: vi.fn(),
|
|
@@ -32,15 +32,21 @@ const fieldTemplate = {
|
|
|
32
32
|
name: "string"
|
|
33
33
|
} as const;
|
|
34
34
|
|
|
35
|
-
it("Render
|
|
35
|
+
it("Render ResponsivePage", async () => {
|
|
36
36
|
act(() => {
|
|
37
|
+
// Hook
|
|
38
|
+
const { result: ref } = renderHook(() =>
|
|
39
|
+
React.useRef<GridMethodRef<Data>>(undefined)
|
|
40
|
+
);
|
|
41
|
+
|
|
37
42
|
// Act
|
|
38
43
|
render(
|
|
39
44
|
<ReactAppContext.Provider value={null}>
|
|
40
45
|
<ResponsivePage<Data, typeof fieldTemplate>
|
|
41
46
|
fields={[<SearchField label="Keyword" name="keyword" minChars={2} />]}
|
|
42
47
|
height={200}
|
|
43
|
-
|
|
48
|
+
rowHeight={[53, 116]}
|
|
49
|
+
mRef={ref.current}
|
|
44
50
|
fieldTemplate={fieldTemplate}
|
|
45
51
|
loadData={({ id }) =>
|
|
46
52
|
Promise.resolve([
|
|
@@ -58,7 +64,7 @@ it("Render ResponsePage", async () => {
|
|
|
58
64
|
valueFormatter: ({ data }) => data?.deviceName ?? data?.name
|
|
59
65
|
}
|
|
60
66
|
]}
|
|
61
|
-
|
|
67
|
+
itemRenderer={(props) =>
|
|
62
68
|
MobileListItemRenderer(props, (data) => {
|
|
63
69
|
return [
|
|
64
70
|
data.name,
|
package/lib/cjs/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>, "cellComponent" | "columnCount" | "columnWidth" | "onClick" | "onDoubleClick" | "onInitLoad" | "width"> & {
|
|
17
|
+
export type DataGridExProps<T extends object, P extends GridJsonData = GridLoadDataProps> = Omit<ScrollerGridProps<T, P>, "cellComponent" | "columnCount" | "columnWidth" | "onClick" | "onDoubleClick" | "onInitLoad" | "rowHeight" | "width"> & Partial<Pick<ScrollerGridProps<T, P>, "rowHeight">> & {
|
|
18
18
|
/**
|
|
19
19
|
* Alternating colors for odd/even rows
|
|
20
20
|
*/
|
package/lib/cjs/DataGridEx.js
CHANGED
|
@@ -137,7 +137,7 @@ function DataGridEx(props) {
|
|
|
137
137
|
}) }));
|
|
138
138
|
}
|
|
139
139
|
// Destruct
|
|
140
|
-
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_1.DataGridRenderers.defaultFooterItemRenderer, hideFooter = false, hoverColor = "#f6f9fb", idField = "id", mRef = react_2.default.createRef(), onClick, onDataChange, onDoubleClick, onUpdateRows, selectable = true, selectedColor = "#edf4fb", width, ...rest } = props;
|
|
140
|
+
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_1.DataGridRenderers.defaultFooterItemRenderer, hideFooter = false, hoverColor = "#f6f9fb", idField = "id", mRef = react_2.default.createRef(), onClick, onDataChange, onDoubleClick, onUpdateRows, rowHeight = 53, selectable = true, selectedColor = "#edf4fb", width, ...rest } = props;
|
|
141
141
|
if (checkable) {
|
|
142
142
|
const cbColumn = {
|
|
143
143
|
field: "selected", // Avoid validation from data model
|
|
@@ -314,7 +314,7 @@ function DataGridEx(props) {
|
|
|
314
314
|
headerHeight -
|
|
315
315
|
(hideFooter ? 0 : bottomHeight + 1) -
|
|
316
316
|
scrollbarSize
|
|
317
|
-
: height, headerRenderer: headerRenderer, idField: idField, footerRenderer: hideFooter ? undefined : footerRenderer, width: Math.max(width ?? 0, widthCalculator.total), mRef: mRefLocal, ...rest }));
|
|
317
|
+
: height, headerRenderer: headerRenderer, idField: idField, footerRenderer: hideFooter ? undefined : footerRenderer, rowHeight: rowHeight, width: Math.max(width ?? 0, widthCalculator.total), mRef: mRefLocal, ...rest }));
|
|
318
318
|
}, [width]);
|
|
319
319
|
return ((0, jsx_runtime_1.jsx)(Paper_1.default, { sx: {
|
|
320
320
|
fontSize: "0.875rem",
|
|
@@ -8,7 +8,7 @@ import { ScrollerListExItemRendererProps } from "./ScrollerListEx";
|
|
|
8
8
|
* @param renderer Renderer for card content
|
|
9
9
|
* @returns Component
|
|
10
10
|
*/
|
|
11
|
-
export declare function MobileListItemRenderer<T>({ data,
|
|
11
|
+
export declare function MobileListItemRenderer<T>({ data, margins }: ScrollerListExItemRendererProps<T>, renderer: (data: T) => [
|
|
12
12
|
string,
|
|
13
13
|
string | undefined,
|
|
14
14
|
React.ReactNode | (ListItemReact | boolean)[],
|
|
@@ -17,14 +17,13 @@ const CardContent_1 = __importDefault(require("@mui/material/CardContent"));
|
|
|
17
17
|
* @param renderer Renderer for card content
|
|
18
18
|
* @returns Component
|
|
19
19
|
*/
|
|
20
|
-
function MobileListItemRenderer({ data,
|
|
20
|
+
function MobileListItemRenderer({ data, margins }, renderer) {
|
|
21
21
|
// Loading
|
|
22
22
|
if (data == null)
|
|
23
23
|
return (0, jsx_runtime_1.jsx)(LinearProgress_1.default, {});
|
|
24
24
|
// Elements
|
|
25
25
|
const [title, subheader, actions, children, cardActions] = renderer(data);
|
|
26
26
|
return ((0, jsx_runtime_1.jsxs)(Card_1.default, { sx: {
|
|
27
|
-
height: itemHeight,
|
|
28
27
|
...margins
|
|
29
28
|
}, children: [(0, jsx_runtime_1.jsx)(CardHeader_1.default, { sx: { paddingBottom: 0.5 }, action: Array.isArray(actions) ? ((0, jsx_runtime_1.jsx)(MoreFab_1.MoreFab, { iconButton: true, size: "small", anchorOrigin: {
|
|
30
29
|
vertical: "bottom",
|
|
@@ -37,6 +36,6 @@ function MobileListItemRenderer({ data, itemHeight, margins }, renderer) {
|
|
|
37
36
|
subheader: { variant: "caption" }
|
|
38
37
|
} }), (0, jsx_runtime_1.jsx)(CardContent_1.default, { sx: {
|
|
39
38
|
paddingTop: 0,
|
|
40
|
-
paddingBottom: cardActions == null ? Reflect.get(margins, "marginBottom") : 0
|
|
39
|
+
paddingBottom: cardActions == null ? Reflect.get(margins, "marginBottom") ?? 0 : 0
|
|
41
40
|
}, children: children }), cardActions] }));
|
|
42
41
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { GridColumn, GridJsonData, GridMethodRef, GridTemplateType } from "@etsoo/react";
|
|
3
3
|
import { DataGridExProps } from "./DataGridEx";
|
|
4
|
-
import {
|
|
4
|
+
import { ScrollerListExProps } from "./ScrollerListEx";
|
|
5
5
|
import { SxProps, Theme } from "@mui/material/styles";
|
|
6
6
|
/**
|
|
7
7
|
* ResponsibleContainer props
|
|
8
8
|
*/
|
|
9
|
-
export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProps<T>, "height" | "
|
|
9
|
+
export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProps<T>, "height" | "loadData" | "mRef" | "onInitLoad" | "onUpdateRows" | "rowHeight"> & {
|
|
10
10
|
/**
|
|
11
11
|
* Height will be deducted
|
|
12
12
|
* @param height Current calcuated height
|
|
@@ -44,10 +44,6 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
|
|
|
44
44
|
* Item renderer
|
|
45
45
|
*/
|
|
46
46
|
itemRenderer?: ScrollerListExProps<T>["itemRenderer"];
|
|
47
|
-
/**
|
|
48
|
-
* Item size, a function indicates its a variable size list
|
|
49
|
-
*/
|
|
50
|
-
itemSize: ScrollerListExItemSize;
|
|
51
47
|
/**
|
|
52
48
|
* Load data callback
|
|
53
49
|
*/
|
|
@@ -55,7 +51,7 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
|
|
|
55
51
|
/**
|
|
56
52
|
* Methods
|
|
57
53
|
*/
|
|
58
|
-
mRef?: React.
|
|
54
|
+
mRef?: React.RefObject<GridMethodRef<T> | undefined>;
|
|
59
55
|
/**
|
|
60
56
|
* Element ready callback
|
|
61
57
|
*/
|
|
@@ -72,6 +68,11 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
|
|
|
72
68
|
* Quick action for double click or click under mobile
|
|
73
69
|
*/
|
|
74
70
|
quickAction?: (data: T) => void;
|
|
71
|
+
/**
|
|
72
|
+
* Row height
|
|
73
|
+
* @param isGrid Is displaying as DataGrid
|
|
74
|
+
*/
|
|
75
|
+
rowHeight?: number | [number, number] | (<B extends boolean>(isGrid: B) => B extends true ? DataGridExProps<T>["rowHeight"] : ScrollerListExProps<T>["rowHeight"]);
|
|
75
76
|
/**
|
|
76
77
|
* Size ready to read miliseconds span
|
|
77
78
|
*/
|
|
@@ -32,7 +32,7 @@ function defaultContainerBoxSx(paddings, hasField, _dataGrid) {
|
|
|
32
32
|
*/
|
|
33
33
|
function ResponsibleContainer(props) {
|
|
34
34
|
// Destruct
|
|
35
|
-
const { adjustHeight, adjustFabHeight, cacheKey, cacheMinutes = 15, columns, containerBoxSx = defaultContainerBoxSx, elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal_1.MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, searchBarBottom = 8, searchBarTop, ...rest } = props;
|
|
35
|
+
const { adjustHeight, adjustFabHeight, cacheKey, cacheMinutes = 15, columns, containerBoxSx = defaultContainerBoxSx, elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal_1.MUGlobal.pagePaddings, pullToRefresh = true, quickAction, rowHeight, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, searchBarBottom = 8, searchBarTop, ...rest } = props;
|
|
36
36
|
// Labels
|
|
37
37
|
const labels = Labels_1.Labels.CommonPage;
|
|
38
38
|
// Refs
|
|
@@ -60,6 +60,16 @@ function ResponsibleContainer(props) {
|
|
|
60
60
|
state.mounted = true;
|
|
61
61
|
return loadData(GridUtils_1.GridUtils.createLoader(props, fieldTemplate, cacheKey, false), lastItem);
|
|
62
62
|
};
|
|
63
|
+
const getRowHeight = react_1.default.useCallback((isGrid) => {
|
|
64
|
+
if (rowHeight == null)
|
|
65
|
+
return undefined;
|
|
66
|
+
else if (typeof rowHeight === "number")
|
|
67
|
+
return isGrid ? undefined : rowHeight;
|
|
68
|
+
else if (Array.isArray(rowHeight))
|
|
69
|
+
return rowHeight[isGrid ? 0 : 1];
|
|
70
|
+
else
|
|
71
|
+
return rowHeight(isGrid);
|
|
72
|
+
}, [rowHeight]);
|
|
63
73
|
// Search data
|
|
64
74
|
const searchData = (0, react_2.useSearchParamsWithCache)(cacheKey);
|
|
65
75
|
// On submit callback
|
|
@@ -116,11 +126,11 @@ function ResponsibleContainer(props) {
|
|
|
116
126
|
if (showDataGrid) {
|
|
117
127
|
// Remove useless props
|
|
118
128
|
const { itemRenderer, ...gridProps } = rest;
|
|
119
|
-
return ((0, jsx_runtime_1.jsx)(Box_1.default, { className: "DataGridBox", children: (0, jsx_runtime_1.jsx)(DataGridEx_1.DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, onDoubleClick: (_, data) => quickAction && quickAction(data), columns: columns, ...gridProps }) }));
|
|
129
|
+
return ((0, jsx_runtime_1.jsx)(Box_1.default, { className: "DataGridBox", children: (0, jsx_runtime_1.jsx)(DataGridEx_1.DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, onDoubleClick: (_, data) => quickAction && quickAction(data), columns: columns, rowHeight: getRowHeight(true), ...gridProps }) }));
|
|
120
130
|
}
|
|
121
131
|
// Remove useless props
|
|
122
|
-
const { checkable, borderRowsCount, bottomHeight, footerItemRenderer, headerHeight, hideFooter, hoverColor, selectable, ...listProps } = rest;
|
|
123
|
-
return ((0, jsx_runtime_1.jsx)(Box_1.default, { className: "ListBox", sx: { height: heightLocal }, children: (0, jsx_runtime_1.jsx)(ScrollerListEx_1.ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, mRef: mRefs, onClick: (event, data) => quickAction && react_2.ReactUtils.isSafeClick(event) && quickAction(data), ...listProps }) }));
|
|
132
|
+
const { checkable, borderRowsCount, bottomHeight, footerItemRenderer, headerHeight, hideFooter, hoverColor, selectable, onCellsRendered, ...listProps } = rest;
|
|
133
|
+
return ((0, jsx_runtime_1.jsx)(Box_1.default, { className: "ListBox", sx: { height: heightLocal }, children: (0, jsx_runtime_1.jsx)(ScrollerListEx_1.ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, mRef: mRefs, onClick: (event, data) => quickAction && react_2.ReactUtils.isSafeClick(event) && quickAction(data), rowHeight: getRowHeight(false), ...listProps }) }));
|
|
124
134
|
})();
|
|
125
135
|
const searchBar = react_1.default.useMemo(() => {
|
|
126
136
|
if (!hasFields ||
|
|
@@ -17,14 +17,6 @@ export type ScrollerListExItemRendererProps<T> = {
|
|
|
17
17
|
* Style
|
|
18
18
|
*/
|
|
19
19
|
style: React.CSSProperties;
|
|
20
|
-
/**
|
|
21
|
-
* Item height
|
|
22
|
-
*/
|
|
23
|
-
itemHeight: number;
|
|
24
|
-
/**
|
|
25
|
-
* Item space
|
|
26
|
-
*/
|
|
27
|
-
space: number;
|
|
28
20
|
/**
|
|
29
21
|
* Default margins
|
|
30
22
|
*/
|
|
@@ -34,17 +26,10 @@ export type ScrollerListExItemRendererProps<T> = {
|
|
|
34
26
|
*/
|
|
35
27
|
selected: boolean;
|
|
36
28
|
};
|
|
37
|
-
/**
|
|
38
|
-
* Extended ScrollerList ItemSize type
|
|
39
|
-
* 1. Callback function
|
|
40
|
-
* 2. Static sets
|
|
41
|
-
* 3. Dynamic left & right margin calculation
|
|
42
|
-
*/
|
|
43
|
-
export type ScrollerListExItemSize = ((index: number) => [number, number] | [number, number, object]) | [number, number] | [number, object, (number | string)?];
|
|
44
29
|
/**
|
|
45
30
|
* Extended ScrollerList Props
|
|
46
31
|
*/
|
|
47
|
-
export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "rowComponent" | "rowHeight" | "onClick" | "onDoubleClick" | "onInitLoad"> & {
|
|
32
|
+
export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "rowComponent" | "rowHeight" | "onClick" | "onDoubleClick" | "onInitLoad"> & Partial<Pick<ScrollerListProps<T>, "rowHeight">> & {
|
|
48
33
|
/**
|
|
49
34
|
* Alternating colors for odd/even rows
|
|
50
35
|
*/
|
|
@@ -58,13 +43,13 @@ export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "
|
|
|
58
43
|
*/
|
|
59
44
|
cacheMinutes?: number;
|
|
60
45
|
/**
|
|
61
|
-
*
|
|
46
|
+
* Cell margins, default to half of MUGlobal.pagePaddings
|
|
62
47
|
*/
|
|
63
|
-
|
|
48
|
+
cellMargins?: object;
|
|
64
49
|
/**
|
|
65
|
-
* Item
|
|
50
|
+
* Item renderer
|
|
66
51
|
*/
|
|
67
|
-
|
|
52
|
+
itemRenderer?: (props: ScrollerListExItemRendererProps<T>) => React.ReactNode;
|
|
68
53
|
/**
|
|
69
54
|
* Double click handler
|
|
70
55
|
*/
|
|
@@ -10,7 +10,6 @@ const react_1 = require("@etsoo/react");
|
|
|
10
10
|
const shared_1 = require("@etsoo/shared");
|
|
11
11
|
const react_2 = __importDefault(require("react"));
|
|
12
12
|
const MUGlobal_1 = require("./MUGlobal");
|
|
13
|
-
const styles_1 = require("@mui/material/styles");
|
|
14
13
|
const GridUtils_1 = require("./GridUtils");
|
|
15
14
|
const useListCacheInitLoad_1 = require("./uses/useListCacheInitLoad");
|
|
16
15
|
const Box_1 = __importDefault(require("@mui/material/Box"));
|
|
@@ -48,31 +47,12 @@ const createGridStyle = (alternatingColors, selectedColor) => {
|
|
|
48
47
|
}
|
|
49
48
|
});
|
|
50
49
|
};
|
|
51
|
-
// Default
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
const half = MUGlobal_1.MUGlobal.half(margin);
|
|
55
|
-
if (horizon == null) {
|
|
56
|
-
const half = MUGlobal_1.MUGlobal.half(margin);
|
|
57
|
-
return {
|
|
58
|
-
marginLeft: margin,
|
|
59
|
-
marginRight: margin,
|
|
60
|
-
marginTop: half,
|
|
61
|
-
marginBottom: half
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
if ((typeof horizon === "number" && horizon >= 0) ||
|
|
65
|
-
(typeof horizon === "string" && /^-?\d+/.test(horizon))) {
|
|
66
|
-
return {
|
|
67
|
-
marginLeft: horizon,
|
|
68
|
-
marginRight: horizon,
|
|
69
|
-
marginTop: half,
|
|
70
|
-
marginBottom: half
|
|
71
|
-
};
|
|
72
|
-
}
|
|
50
|
+
// Default margins
|
|
51
|
+
const defaultMargins = () => {
|
|
52
|
+
const half = MUGlobal_1.MUGlobal.half(MUGlobal_1.MUGlobal.pagePaddings);
|
|
73
53
|
return {
|
|
74
|
-
marginLeft:
|
|
75
|
-
marginRight:
|
|
54
|
+
marginLeft: 0,
|
|
55
|
+
marginRight: 0,
|
|
76
56
|
marginTop: half,
|
|
77
57
|
marginBottom: half
|
|
78
58
|
};
|
|
@@ -104,35 +84,11 @@ function ScrollerListEx(props) {
|
|
|
104
84
|
return selected;
|
|
105
85
|
};
|
|
106
86
|
// Destruct
|
|
107
|
-
const { alternatingColors = [undefined, undefined], className, cacheKey, cacheMinutes = 15, idField = "id",
|
|
108
|
-
height: itemHeight,
|
|
87
|
+
const { alternatingColors = [undefined, undefined], className, cacheKey, cacheMinutes = 15, cellMargins = defaultMargins(), idField = "id", itemRenderer = ({ data, margins }) => ((0, jsx_runtime_1.jsx)(Box_1.default, { component: "pre", sx: {
|
|
109
88
|
...margins
|
|
110
|
-
}, children: JSON.stringify(data) })), onClick, onDoubleClick, onUpdateRows, onSelectChange, selectedColor = "#edf4fb", ...rest } = props;
|
|
89
|
+
}, children: JSON.stringify(data) })), onClick, onDoubleClick, onUpdateRows, onSelectChange, rowHeight = 116, selectedColor = "#edf4fb", ...rest } = props;
|
|
111
90
|
// Init handler
|
|
112
91
|
const initHandler = (0, useListCacheInitLoad_1.useListCacheInitLoad)(cacheKey, cacheMinutes);
|
|
113
|
-
// Theme
|
|
114
|
-
const theme = (0, styles_1.useTheme)();
|
|
115
|
-
// Cache calculation
|
|
116
|
-
const itemSizeResult = react_2.default.useMemo(() => {
|
|
117
|
-
if (typeof itemSize === "function")
|
|
118
|
-
return undefined;
|
|
119
|
-
const [size, spaces, h] = itemSize;
|
|
120
|
-
if (typeof spaces === "number")
|
|
121
|
-
return [size, spaces, defaultMargin(MUGlobal_1.MUGlobal.pagePaddings, undefined)];
|
|
122
|
-
return [size, MUGlobal_1.MUGlobal.getSpace(spaces, theme), defaultMargin(spaces, h)];
|
|
123
|
-
}, [itemSize]);
|
|
124
|
-
// Calculate size
|
|
125
|
-
const calculateItemSize = (index) => {
|
|
126
|
-
// Callback function
|
|
127
|
-
if (typeof itemSize === "function") {
|
|
128
|
-
const result = itemSize(index);
|
|
129
|
-
if (result.length == 2)
|
|
130
|
-
return [...result, defaultMargin(MUGlobal_1.MUGlobal.pagePaddings)];
|
|
131
|
-
return result;
|
|
132
|
-
}
|
|
133
|
-
// Calculation
|
|
134
|
-
return itemSizeResult;
|
|
135
|
-
};
|
|
136
92
|
const onUpdateRowsHandler = react_2.default.useCallback((rows, state) => {
|
|
137
93
|
GridUtils_1.GridUtils.getUpdateRowsHandler(cacheKey)?.(rows, state);
|
|
138
94
|
onUpdateRows?.(rows, state);
|
|
@@ -140,24 +96,19 @@ function ScrollerListEx(props) {
|
|
|
140
96
|
// Layout
|
|
141
97
|
return ((0, jsx_runtime_1.jsx)(react_1.ScrollerList, { className: shared_1.Utils.mergeClasses("ScrollerListEx-Body", className, createGridStyle(alternatingColors, selectedColor)), idField: idField, onRowsRendered: cacheKey
|
|
142
98
|
? (visibleRows) => sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(visibleRows))
|
|
143
|
-
: undefined, onInitLoad: initHandler, onUpdateRows: onUpdateRowsHandler, rowComponent: (
|
|
99
|
+
: undefined, onInitLoad: initHandler, onUpdateRows: onUpdateRowsHandler, rowComponent: (cellProps) => {
|
|
100
|
+
const { index, style, items } = cellProps;
|
|
144
101
|
const data = items[index];
|
|
145
102
|
const selected = isSelected(data);
|
|
146
103
|
const rowClass = `ScrollerListEx-Row${index % 2}${selected ? ` ${selectedClassName}` : ""}`;
|
|
147
|
-
const [itemHeight, space, margins] = calculateItemSize(index);
|
|
148
104
|
// Child
|
|
149
105
|
const child = itemRenderer({
|
|
150
106
|
index,
|
|
151
107
|
data,
|
|
152
108
|
style,
|
|
153
109
|
selected,
|
|
154
|
-
|
|
155
|
-
space,
|
|
156
|
-
margins
|
|
110
|
+
margins: cellMargins
|
|
157
111
|
});
|
|
158
112
|
return ((0, jsx_runtime_1.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 }));
|
|
159
|
-
}, rowHeight:
|
|
160
|
-
const [size, space] = calculateItemSize(index);
|
|
161
|
-
return size + space;
|
|
162
|
-
}, ...rest }));
|
|
113
|
+
}, rowHeight: rowHeight, ...rest }));
|
|
163
114
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { ResponsibleContainerProps } from "../ResponsibleContainer";
|
|
2
3
|
import type { DataGridPageProps } from "./DataGridPageProps";
|
|
3
|
-
import type {
|
|
4
|
+
import type { ScrollerListExProps } from "../ScrollerListEx";
|
|
4
5
|
import { GridMethodRef } from "@etsoo/react";
|
|
5
6
|
import type { OperationMessageHandlerAll } from "../messages/OperationMessageHandler";
|
|
6
7
|
/**
|
|
7
8
|
* Response page props
|
|
8
9
|
*/
|
|
9
|
-
export type ResponsePageProps<T extends object, F> = DataGridPageProps<T, F> & {
|
|
10
|
+
export type ResponsePageProps<T extends object, F> = Omit<DataGridPageProps<T, F>, "mRef" | "rowHeight"> & {
|
|
10
11
|
/**
|
|
11
12
|
*
|
|
12
13
|
* @param height Current height
|
|
@@ -22,14 +23,10 @@ export type ResponsePageProps<T extends object, F> = DataGridPageProps<T, F> & {
|
|
|
22
23
|
* Item renderer
|
|
23
24
|
*/
|
|
24
25
|
itemRenderer?: ScrollerListExProps<T>["itemRenderer"];
|
|
25
|
-
/**
|
|
26
|
-
* Item size, a function indicates its a variable size list
|
|
27
|
-
*/
|
|
28
|
-
itemSize: ScrollerListExItemSize;
|
|
29
26
|
/**
|
|
30
27
|
* Methods
|
|
31
28
|
*/
|
|
32
|
-
mRef?: React.
|
|
29
|
+
mRef?: React.RefObject<GridMethodRef<T> | undefined>;
|
|
33
30
|
/**
|
|
34
31
|
* Pull to refresh data
|
|
35
32
|
*/
|
|
@@ -42,6 +39,10 @@ export type ResponsePageProps<T extends object, F> = DataGridPageProps<T, F> & {
|
|
|
42
39
|
* Operation message handler
|
|
43
40
|
*/
|
|
44
41
|
operationMessageHandler?: OperationMessageHandlerAll;
|
|
42
|
+
/**
|
|
43
|
+
* Row height
|
|
44
|
+
*/
|
|
45
|
+
rowHeight?: ResponsibleContainerProps<T, F>["rowHeight"];
|
|
45
46
|
};
|
|
46
47
|
/**
|
|
47
48
|
* Fixed height list page
|
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>, "cellComponent" | "columnCount" | "columnWidth" | "onClick" | "onDoubleClick" | "onInitLoad" | "width"> & {
|
|
17
|
+
export type DataGridExProps<T extends object, P extends GridJsonData = GridLoadDataProps> = Omit<ScrollerGridProps<T, P>, "cellComponent" | "columnCount" | "columnWidth" | "onClick" | "onDoubleClick" | "onInitLoad" | "rowHeight" | "width"> & Partial<Pick<ScrollerGridProps<T, P>, "rowHeight">> & {
|
|
18
18
|
/**
|
|
19
19
|
* Alternating colors for odd/even rows
|
|
20
20
|
*/
|
package/lib/mjs/DataGridEx.js
CHANGED
|
@@ -130,7 +130,7 @@ export function DataGridEx(props) {
|
|
|
130
130
|
}) }));
|
|
131
131
|
}
|
|
132
132
|
// Destruct
|
|
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;
|
|
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, rowHeight = 53, selectable = true, selectedColor = "#edf4fb", width, ...rest } = props;
|
|
134
134
|
if (checkable) {
|
|
135
135
|
const cbColumn = {
|
|
136
136
|
field: "selected", // Avoid validation from data model
|
|
@@ -307,7 +307,7 @@ export function DataGridEx(props) {
|
|
|
307
307
|
headerHeight -
|
|
308
308
|
(hideFooter ? 0 : bottomHeight + 1) -
|
|
309
309
|
scrollbarSize
|
|
310
|
-
: height, headerRenderer: headerRenderer, idField: idField, footerRenderer: hideFooter ? undefined : footerRenderer, width: Math.max(width ?? 0, widthCalculator.total), mRef: mRefLocal, ...rest }));
|
|
310
|
+
: height, headerRenderer: headerRenderer, idField: idField, footerRenderer: hideFooter ? undefined : footerRenderer, rowHeight: rowHeight, width: Math.max(width ?? 0, widthCalculator.total), mRef: mRefLocal, ...rest }));
|
|
311
311
|
}, [width]);
|
|
312
312
|
return (_jsx(Paper, { sx: {
|
|
313
313
|
fontSize: "0.875rem",
|
|
@@ -8,7 +8,7 @@ import { ScrollerListExItemRendererProps } from "./ScrollerListEx";
|
|
|
8
8
|
* @param renderer Renderer for card content
|
|
9
9
|
* @returns Component
|
|
10
10
|
*/
|
|
11
|
-
export declare function MobileListItemRenderer<T>({ data,
|
|
11
|
+
export declare function MobileListItemRenderer<T>({ data, margins }: ScrollerListExItemRendererProps<T>, renderer: (data: T) => [
|
|
12
12
|
string,
|
|
13
13
|
string | undefined,
|
|
14
14
|
React.ReactNode | (ListItemReact | boolean)[],
|
|
@@ -11,14 +11,13 @@ import CardContent from "@mui/material/CardContent";
|
|
|
11
11
|
* @param renderer Renderer for card content
|
|
12
12
|
* @returns Component
|
|
13
13
|
*/
|
|
14
|
-
export function MobileListItemRenderer({ data,
|
|
14
|
+
export function MobileListItemRenderer({ data, margins }, renderer) {
|
|
15
15
|
// Loading
|
|
16
16
|
if (data == null)
|
|
17
17
|
return _jsx(LinearProgress, {});
|
|
18
18
|
// Elements
|
|
19
19
|
const [title, subheader, actions, children, cardActions] = renderer(data);
|
|
20
20
|
return (_jsxs(Card, { sx: {
|
|
21
|
-
height: itemHeight,
|
|
22
21
|
...margins
|
|
23
22
|
}, children: [_jsx(CardHeader, { sx: { paddingBottom: 0.5 }, action: Array.isArray(actions) ? (_jsx(MoreFab, { iconButton: true, size: "small", anchorOrigin: {
|
|
24
23
|
vertical: "bottom",
|
|
@@ -31,6 +30,6 @@ export function MobileListItemRenderer({ data, itemHeight, margins }, renderer)
|
|
|
31
30
|
subheader: { variant: "caption" }
|
|
32
31
|
} }), _jsx(CardContent, { sx: {
|
|
33
32
|
paddingTop: 0,
|
|
34
|
-
paddingBottom: cardActions == null ? Reflect.get(margins, "marginBottom") : 0
|
|
33
|
+
paddingBottom: cardActions == null ? Reflect.get(margins, "marginBottom") ?? 0 : 0
|
|
35
34
|
}, children: children }), cardActions] }));
|
|
36
35
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { GridColumn, GridJsonData, GridMethodRef, GridTemplateType } from "@etsoo/react";
|
|
3
3
|
import { DataGridExProps } from "./DataGridEx";
|
|
4
|
-
import {
|
|
4
|
+
import { ScrollerListExProps } from "./ScrollerListEx";
|
|
5
5
|
import { SxProps, Theme } from "@mui/material/styles";
|
|
6
6
|
/**
|
|
7
7
|
* ResponsibleContainer props
|
|
8
8
|
*/
|
|
9
|
-
export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProps<T>, "height" | "
|
|
9
|
+
export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProps<T>, "height" | "loadData" | "mRef" | "onInitLoad" | "onUpdateRows" | "rowHeight"> & {
|
|
10
10
|
/**
|
|
11
11
|
* Height will be deducted
|
|
12
12
|
* @param height Current calcuated height
|
|
@@ -44,10 +44,6 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
|
|
|
44
44
|
* Item renderer
|
|
45
45
|
*/
|
|
46
46
|
itemRenderer?: ScrollerListExProps<T>["itemRenderer"];
|
|
47
|
-
/**
|
|
48
|
-
* Item size, a function indicates its a variable size list
|
|
49
|
-
*/
|
|
50
|
-
itemSize: ScrollerListExItemSize;
|
|
51
47
|
/**
|
|
52
48
|
* Load data callback
|
|
53
49
|
*/
|
|
@@ -55,7 +51,7 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
|
|
|
55
51
|
/**
|
|
56
52
|
* Methods
|
|
57
53
|
*/
|
|
58
|
-
mRef?: React.
|
|
54
|
+
mRef?: React.RefObject<GridMethodRef<T> | undefined>;
|
|
59
55
|
/**
|
|
60
56
|
* Element ready callback
|
|
61
57
|
*/
|
|
@@ -72,6 +68,11 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
|
|
|
72
68
|
* Quick action for double click or click under mobile
|
|
73
69
|
*/
|
|
74
70
|
quickAction?: (data: T) => void;
|
|
71
|
+
/**
|
|
72
|
+
* Row height
|
|
73
|
+
* @param isGrid Is displaying as DataGrid
|
|
74
|
+
*/
|
|
75
|
+
rowHeight?: number | [number, number] | (<B extends boolean>(isGrid: B) => B extends true ? DataGridExProps<T>["rowHeight"] : ScrollerListExProps<T>["rowHeight"]);
|
|
75
76
|
/**
|
|
76
77
|
* Size ready to read miliseconds span
|
|
77
78
|
*/
|
|
@@ -26,7 +26,7 @@ function defaultContainerBoxSx(paddings, hasField, _dataGrid) {
|
|
|
26
26
|
*/
|
|
27
27
|
export function ResponsibleContainer(props) {
|
|
28
28
|
// Destruct
|
|
29
|
-
const { adjustHeight, adjustFabHeight, cacheKey, cacheMinutes = 15, columns, containerBoxSx = defaultContainerBoxSx, elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, searchBarBottom = 8, searchBarTop, ...rest } = props;
|
|
29
|
+
const { adjustHeight, adjustFabHeight, cacheKey, cacheMinutes = 15, columns, containerBoxSx = defaultContainerBoxSx, elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, quickAction, rowHeight, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, searchBarBottom = 8, searchBarTop, ...rest } = props;
|
|
30
30
|
// Labels
|
|
31
31
|
const labels = Labels.CommonPage;
|
|
32
32
|
// Refs
|
|
@@ -54,6 +54,16 @@ export function ResponsibleContainer(props) {
|
|
|
54
54
|
state.mounted = true;
|
|
55
55
|
return loadData(GridUtils.createLoader(props, fieldTemplate, cacheKey, false), lastItem);
|
|
56
56
|
};
|
|
57
|
+
const getRowHeight = React.useCallback((isGrid) => {
|
|
58
|
+
if (rowHeight == null)
|
|
59
|
+
return undefined;
|
|
60
|
+
else if (typeof rowHeight === "number")
|
|
61
|
+
return isGrid ? undefined : rowHeight;
|
|
62
|
+
else if (Array.isArray(rowHeight))
|
|
63
|
+
return rowHeight[isGrid ? 0 : 1];
|
|
64
|
+
else
|
|
65
|
+
return rowHeight(isGrid);
|
|
66
|
+
}, [rowHeight]);
|
|
57
67
|
// Search data
|
|
58
68
|
const searchData = useSearchParamsWithCache(cacheKey);
|
|
59
69
|
// On submit callback
|
|
@@ -110,11 +120,11 @@ export function ResponsibleContainer(props) {
|
|
|
110
120
|
if (showDataGrid) {
|
|
111
121
|
// Remove useless props
|
|
112
122
|
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 }) }));
|
|
123
|
+
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, rowHeight: getRowHeight(true), ...gridProps }) }));
|
|
114
124
|
}
|
|
115
125
|
// 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 }) }));
|
|
126
|
+
const { checkable, borderRowsCount, bottomHeight, footerItemRenderer, headerHeight, hideFooter, hoverColor, selectable, onCellsRendered, ...listProps } = rest;
|
|
127
|
+
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), rowHeight: getRowHeight(false), ...listProps }) }));
|
|
118
128
|
})();
|
|
119
129
|
const searchBar = React.useMemo(() => {
|
|
120
130
|
if (!hasFields ||
|
|
@@ -17,14 +17,6 @@ export type ScrollerListExItemRendererProps<T> = {
|
|
|
17
17
|
* Style
|
|
18
18
|
*/
|
|
19
19
|
style: React.CSSProperties;
|
|
20
|
-
/**
|
|
21
|
-
* Item height
|
|
22
|
-
*/
|
|
23
|
-
itemHeight: number;
|
|
24
|
-
/**
|
|
25
|
-
* Item space
|
|
26
|
-
*/
|
|
27
|
-
space: number;
|
|
28
20
|
/**
|
|
29
21
|
* Default margins
|
|
30
22
|
*/
|
|
@@ -34,17 +26,10 @@ export type ScrollerListExItemRendererProps<T> = {
|
|
|
34
26
|
*/
|
|
35
27
|
selected: boolean;
|
|
36
28
|
};
|
|
37
|
-
/**
|
|
38
|
-
* Extended ScrollerList ItemSize type
|
|
39
|
-
* 1. Callback function
|
|
40
|
-
* 2. Static sets
|
|
41
|
-
* 3. Dynamic left & right margin calculation
|
|
42
|
-
*/
|
|
43
|
-
export type ScrollerListExItemSize = ((index: number) => [number, number] | [number, number, object]) | [number, number] | [number, object, (number | string)?];
|
|
44
29
|
/**
|
|
45
30
|
* Extended ScrollerList Props
|
|
46
31
|
*/
|
|
47
|
-
export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "rowComponent" | "rowHeight" | "onClick" | "onDoubleClick" | "onInitLoad"> & {
|
|
32
|
+
export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "rowComponent" | "rowHeight" | "onClick" | "onDoubleClick" | "onInitLoad"> & Partial<Pick<ScrollerListProps<T>, "rowHeight">> & {
|
|
48
33
|
/**
|
|
49
34
|
* Alternating colors for odd/even rows
|
|
50
35
|
*/
|
|
@@ -58,13 +43,13 @@ export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "
|
|
|
58
43
|
*/
|
|
59
44
|
cacheMinutes?: number;
|
|
60
45
|
/**
|
|
61
|
-
*
|
|
46
|
+
* Cell margins, default to half of MUGlobal.pagePaddings
|
|
62
47
|
*/
|
|
63
|
-
|
|
48
|
+
cellMargins?: object;
|
|
64
49
|
/**
|
|
65
|
-
* Item
|
|
50
|
+
* Item renderer
|
|
66
51
|
*/
|
|
67
|
-
|
|
52
|
+
itemRenderer?: (props: ScrollerListExItemRendererProps<T>) => React.ReactNode;
|
|
68
53
|
/**
|
|
69
54
|
* Double click handler
|
|
70
55
|
*/
|