@etsoo/materialui 1.4.98 → 1.5.0
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/lib/cjs/ErrorAlert.d.ts +16 -0
- package/lib/cjs/ErrorAlert.js +19 -0
- package/lib/cjs/ViewContainer.d.ts +107 -0
- package/lib/cjs/ViewContainer.js +230 -0
- package/lib/cjs/index.d.ts +2 -0
- package/lib/cjs/index.js +2 -0
- package/lib/cjs/pages/ViewPage.d.ts +2 -95
- package/lib/cjs/pages/ViewPage.js +10 -223
- package/lib/mjs/ErrorAlert.d.ts +16 -0
- package/lib/mjs/ErrorAlert.js +16 -0
- package/lib/mjs/ViewContainer.d.ts +107 -0
- package/lib/mjs/ViewContainer.js +222 -0
- package/lib/mjs/index.d.ts +2 -0
- package/lib/mjs/index.js +2 -0
- package/lib/mjs/pages/ViewPage.d.ts +2 -95
- package/lib/mjs/pages/ViewPage.js +5 -216
- package/package.json +9 -9
- package/src/ErrorAlert.tsx +32 -0
- package/src/ViewContainer.tsx +437 -0
- package/src/index.ts +2 -0
- package/src/pages/ViewPage.tsx +17 -415
|
@@ -3,251 +3,39 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.ViewPageSize = void 0;
|
|
7
|
-
exports.ViewPageGridItem = ViewPageGridItem;
|
|
8
6
|
exports.ViewPage = ViewPage;
|
|
9
|
-
const react_1 = require("react");
|
|
10
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
11
|
-
const
|
|
8
|
+
const react_1 = require("@etsoo/react");
|
|
12
9
|
const shared_1 = require("@etsoo/shared");
|
|
13
10
|
const material_1 = require("@mui/material");
|
|
14
|
-
const
|
|
11
|
+
const react_2 = __importDefault(require("react"));
|
|
15
12
|
const Labels_1 = require("../app/Labels");
|
|
16
|
-
const GridDataFormat_1 = require("../GridDataFormat");
|
|
17
13
|
const MUGlobal_1 = require("../MUGlobal");
|
|
18
14
|
const PullToRefreshUI_1 = require("../PullToRefreshUI");
|
|
19
15
|
const CommonPage_1 = require("./CommonPage");
|
|
20
16
|
const MessageUtils_1 = require("../messages/MessageUtils");
|
|
21
17
|
const OperationMessageContainer_1 = require("../messages/OperationMessageContainer");
|
|
22
|
-
const
|
|
23
|
-
const useCurrentBreakpoint_1 = require("../useCurrentBreakpoint");
|
|
24
|
-
const breakpoints = ["xs", "sm", "md", "lg", "xl"];
|
|
25
|
-
/**
|
|
26
|
-
* View page grid item size
|
|
27
|
-
*/
|
|
28
|
-
var ViewPageSize;
|
|
29
|
-
(function (ViewPageSize) {
|
|
30
|
-
ViewPageSize.large = {
|
|
31
|
-
xs: 12,
|
|
32
|
-
sm: 12,
|
|
33
|
-
md: 9,
|
|
34
|
-
lg: 6,
|
|
35
|
-
xl: 4
|
|
36
|
-
};
|
|
37
|
-
ViewPageSize.medium = {
|
|
38
|
-
xs: 12,
|
|
39
|
-
sm: 12,
|
|
40
|
-
md: 6,
|
|
41
|
-
lg: 4,
|
|
42
|
-
xl: 3
|
|
43
|
-
};
|
|
44
|
-
ViewPageSize.line = {
|
|
45
|
-
xs: 12,
|
|
46
|
-
sm: 12,
|
|
47
|
-
md: 12,
|
|
48
|
-
lg: 12,
|
|
49
|
-
xl: 12
|
|
50
|
-
};
|
|
51
|
-
ViewPageSize.small = { xs: 6, sm: 6, md: 4, lg: 3, xl: 2 };
|
|
52
|
-
ViewPageSize.smallLine = {
|
|
53
|
-
xs: 12,
|
|
54
|
-
sm: 6,
|
|
55
|
-
md: 4,
|
|
56
|
-
lg: 3,
|
|
57
|
-
xl: 2
|
|
58
|
-
};
|
|
59
|
-
function matchSize(size) {
|
|
60
|
-
return Object.fromEntries(Object.entries(size).map(([key, value]) => [
|
|
61
|
-
key,
|
|
62
|
-
value == null ? undefined : value === 12 ? 12 : 12 - value
|
|
63
|
-
]));
|
|
64
|
-
}
|
|
65
|
-
ViewPageSize.matchSize = matchSize;
|
|
66
|
-
})(ViewPageSize || (exports.ViewPageSize = ViewPageSize = {}));
|
|
67
|
-
/**
|
|
68
|
-
* View page grid item
|
|
69
|
-
* @param props Props
|
|
70
|
-
* @returns Result
|
|
71
|
-
*/
|
|
72
|
-
function ViewPageGridItem(props) {
|
|
73
|
-
// Destruct
|
|
74
|
-
const { data, label, singleRow, ...gridProps } = props;
|
|
75
|
-
// Default options
|
|
76
|
-
let options = {};
|
|
77
|
-
if (gridProps.size == null) {
|
|
78
|
-
options = getResp(singleRow ?? "small");
|
|
79
|
-
}
|
|
80
|
-
else if (singleRow != null) {
|
|
81
|
-
options = getResp(singleRow ?? "small");
|
|
82
|
-
}
|
|
83
|
-
// Layout
|
|
84
|
-
return ((0, jsx_runtime_1.jsxs)(material_1.Grid2, { ...gridProps, ...options, children: [label != null && ((0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "caption", component: "div", children: [label, ":"] })), typeof data === "object" ? (data) : ((0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle2", children: data }))] }));
|
|
85
|
-
}
|
|
86
|
-
function formatItemData(app, fieldData) {
|
|
87
|
-
if (fieldData == null)
|
|
88
|
-
return undefined;
|
|
89
|
-
if (typeof fieldData === "string")
|
|
90
|
-
return fieldData;
|
|
91
|
-
if (fieldData instanceof Date)
|
|
92
|
-
return app.formatDate(fieldData, "d");
|
|
93
|
-
return `${fieldData}`;
|
|
94
|
-
}
|
|
95
|
-
function getResp(singleRow) {
|
|
96
|
-
const size = typeof singleRow === "object"
|
|
97
|
-
? singleRow
|
|
98
|
-
: singleRow === "medium"
|
|
99
|
-
? ViewPageSize.medium
|
|
100
|
-
: singleRow === "large"
|
|
101
|
-
? ViewPageSize.large
|
|
102
|
-
: singleRow === true
|
|
103
|
-
? ViewPageSize.line
|
|
104
|
-
: singleRow === false
|
|
105
|
-
? ViewPageSize.smallLine
|
|
106
|
-
: ViewPageSize.small;
|
|
107
|
-
return size;
|
|
108
|
-
}
|
|
109
|
-
function getItemField(app, field, data) {
|
|
110
|
-
// Item data and label
|
|
111
|
-
let itemData, itemLabel, gridProps = {}, size;
|
|
112
|
-
if (Array.isArray(field)) {
|
|
113
|
-
const [fieldData, fieldType, renderProps, singleRow = "small"] = field;
|
|
114
|
-
itemData = (0, GridDataFormat_1.GridDataFormat)(data[fieldData], fieldType, renderProps);
|
|
115
|
-
itemLabel = app.get(fieldData) ?? fieldData;
|
|
116
|
-
size = getResp(singleRow);
|
|
117
|
-
gridProps = { size };
|
|
118
|
-
}
|
|
119
|
-
else if (typeof field === "object") {
|
|
120
|
-
// Destruct
|
|
121
|
-
const { data: fieldData, dataType, label: fieldLabel, renderProps, singleRow = "default", ...rest } = field;
|
|
122
|
-
// Size
|
|
123
|
-
size = getResp(singleRow);
|
|
124
|
-
gridProps = {
|
|
125
|
-
...rest,
|
|
126
|
-
size
|
|
127
|
-
};
|
|
128
|
-
// Field data
|
|
129
|
-
if (typeof fieldData === "function")
|
|
130
|
-
itemData = fieldData(data);
|
|
131
|
-
else if (dataType == null)
|
|
132
|
-
itemData = formatItemData(app, data[fieldData]);
|
|
133
|
-
else
|
|
134
|
-
itemData = (0, GridDataFormat_1.GridDataFormat)(data[fieldData], dataType, renderProps);
|
|
135
|
-
// Field label
|
|
136
|
-
itemLabel =
|
|
137
|
-
fieldLabel === ""
|
|
138
|
-
? undefined
|
|
139
|
-
: fieldLabel == null && typeof fieldData === "string"
|
|
140
|
-
? app.get(fieldData) ?? fieldData
|
|
141
|
-
: typeof fieldLabel === "function"
|
|
142
|
-
? fieldLabel(data)
|
|
143
|
-
: fieldLabel != null
|
|
144
|
-
? app.get(fieldLabel) ?? fieldLabel
|
|
145
|
-
: undefined;
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
// Single field format
|
|
149
|
-
itemData = formatItemData(app, data[field]);
|
|
150
|
-
itemLabel = app.get(field) ?? field;
|
|
151
|
-
size = ViewPageSize.small;
|
|
152
|
-
gridProps = { size };
|
|
153
|
-
}
|
|
154
|
-
return [itemData, itemLabel, gridProps, size];
|
|
155
|
-
}
|
|
156
|
-
function getItemSize(bp, size) {
|
|
157
|
-
const v = size[bp];
|
|
158
|
-
if (v != null)
|
|
159
|
-
return v;
|
|
160
|
-
const index = breakpoints.indexOf(bp);
|
|
161
|
-
for (let i = index; i >= 0; i--) {
|
|
162
|
-
const v = size[breakpoints[i]];
|
|
163
|
-
if (v != null)
|
|
164
|
-
return v;
|
|
165
|
-
}
|
|
166
|
-
return 12;
|
|
167
|
-
}
|
|
18
|
+
const ViewContainer_1 = require("../ViewContainer");
|
|
168
19
|
/**
|
|
169
20
|
* View page
|
|
170
21
|
* @param props Props
|
|
171
22
|
*/
|
|
172
23
|
function ViewPage(props) {
|
|
173
|
-
// Global app
|
|
174
|
-
const app = (0, ReactApp_1.useRequiredAppContext)();
|
|
175
24
|
// Destruct
|
|
176
|
-
const { actions, children, fields, loadData, paddings = MUGlobal_1.MUGlobal.pagePaddings, spacing
|
|
177
|
-
// Current breakpoint
|
|
178
|
-
const bp = (0, useCurrentBreakpoint_1.useCurrentBreakpoint)();
|
|
25
|
+
const { actions, children, fields, loadData, paddings = MUGlobal_1.MUGlobal.pagePaddings, spacing, actionPaddings = MUGlobal_1.MUGlobal.pagePaddings, supportRefresh = true, fabColumnDirection = true, fabTop = true, supportBack = true, pullToRefresh = true, gridRef, operationMessageHandler, titleBar, leftContainer, leftContainerLines, leftContainerProps, ...rest } = props;
|
|
179
26
|
// Data
|
|
180
|
-
const [data, setData] =
|
|
27
|
+
const [data, setData] = react_2.default.useState();
|
|
181
28
|
// Labels
|
|
182
29
|
const labels = Labels_1.Labels.CommonPage;
|
|
183
30
|
// Container
|
|
184
31
|
const pullContainer = "#page-container";
|
|
185
|
-
// Left container
|
|
186
|
-
const { size = ViewPageSize.smallLine, ...leftContainerPropsRest } = leftContainerProps;
|
|
187
32
|
// Load data
|
|
188
|
-
const refresh =
|
|
33
|
+
const refresh = react_2.default.useCallback(async () => {
|
|
189
34
|
const result = await loadData();
|
|
190
35
|
// When failed or no data returned, show the loading bar
|
|
191
36
|
setData(result);
|
|
192
37
|
}, [loadData]);
|
|
193
|
-
|
|
194
|
-
const fieldIndexRef = react_3.default.useRef(0);
|
|
195
|
-
const createFields = react_3.default.useCallback((data, maxItems = 0) => {
|
|
196
|
-
let validItems = 0;
|
|
197
|
-
const items = [];
|
|
198
|
-
let i = fieldIndexRef.current;
|
|
199
|
-
for (; i < fields.length; i++) {
|
|
200
|
-
const field = fields[i];
|
|
201
|
-
let oneSize;
|
|
202
|
-
let oneItem;
|
|
203
|
-
if (typeof field === "function") {
|
|
204
|
-
// Most flexible way, do whatever you want
|
|
205
|
-
const createdResult = field(data, refresh);
|
|
206
|
-
if (createdResult == null || createdResult === "")
|
|
207
|
-
continue;
|
|
208
|
-
if (Array.isArray(createdResult)) {
|
|
209
|
-
const [created, size] = createdResult;
|
|
210
|
-
oneSize = size;
|
|
211
|
-
oneItem = created;
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
oneSize = ViewPageSize.line;
|
|
215
|
-
oneItem = createdResult;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
const [itemData, itemLabel, gridProps, size] = getItemField(app, field, data);
|
|
220
|
-
// Some callback function may return '' instead of undefined
|
|
221
|
-
if (itemData == null || itemData === "")
|
|
222
|
-
continue;
|
|
223
|
-
oneSize = size;
|
|
224
|
-
oneItem = ((0, react_1.createElement)(ViewPageGridItem, { ...gridProps, key: i, data: itemData, label: itemLabel }));
|
|
225
|
-
}
|
|
226
|
-
// Max lines
|
|
227
|
-
if (maxItems > 0) {
|
|
228
|
-
const itemSize = getItemSize(bp, oneSize);
|
|
229
|
-
if (maxItems < validItems + itemSize) {
|
|
230
|
-
fieldIndexRef.current = i;
|
|
231
|
-
break;
|
|
232
|
-
}
|
|
233
|
-
else {
|
|
234
|
-
items.push(oneItem);
|
|
235
|
-
validItems += itemSize;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
items.push(oneItem);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
if (maxItems === 0) {
|
|
243
|
-
fieldIndexRef.current = 0;
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
fieldIndexRef.current = i;
|
|
247
|
-
}
|
|
248
|
-
return items;
|
|
249
|
-
}, [app, refresh, fields, data, bp]);
|
|
250
|
-
react_3.default.useEffect(() => {
|
|
38
|
+
react_2.default.useEffect(() => {
|
|
251
39
|
const refreshHandler = async () => {
|
|
252
40
|
await refresh();
|
|
253
41
|
};
|
|
@@ -256,19 +44,18 @@ function ViewPage(props) {
|
|
|
256
44
|
MessageUtils_1.MessageUtils.offRefresh(refreshHandler);
|
|
257
45
|
};
|
|
258
46
|
}, [refresh]);
|
|
259
|
-
let leftResult;
|
|
260
47
|
return ((0, jsx_runtime_1.jsx)(CommonPage_1.CommonPage, { paddings: paddings, onRefresh: supportRefresh ? refresh : undefined, onUpdate: supportRefresh ? undefined : refresh, sx: {
|
|
261
48
|
".MuiTypography-subtitle2": {
|
|
262
49
|
fontWeight: "bold"
|
|
263
50
|
}
|
|
264
|
-
}, ...rest, scrollContainer: globalThis, fabColumnDirection: fabColumnDirection, fabTop: fabTop, supportBack: supportBack, children: data == null ? ((0, jsx_runtime_1.jsx)(material_1.LinearProgress, {})) : ((0, jsx_runtime_1.jsxs)(
|
|
51
|
+
}, ...rest, scrollContainer: globalThis, fabColumnDirection: fabColumnDirection, fabTop: fabTop, supportBack: supportBack, children: data == null ? ((0, jsx_runtime_1.jsx)(material_1.LinearProgress, {})) : ((0, jsx_runtime_1.jsxs)(react_2.default.Fragment, { children: [operationMessageHandler && ((0, jsx_runtime_1.jsx)(OperationMessageContainer_1.OperationMessageContainer, { handler: "id" in operationMessageHandler
|
|
265
52
|
? [
|
|
266
53
|
operationMessageHandler.types,
|
|
267
54
|
refresh,
|
|
268
55
|
operationMessageHandler.id
|
|
269
56
|
]
|
|
270
|
-
: operationMessageHandler })), titleBar && titleBar(data), (0, jsx_runtime_1.
|
|
57
|
+
: operationMessageHandler })), titleBar && titleBar(data), (0, jsx_runtime_1.jsx)(ViewContainer_1.ViewContainer, { data: data, fields: fields, gridRef: gridRef, leftContainer: leftContainer, leftContainerLines: leftContainerLines, leftContainerProps: leftContainerProps, refresh: refresh, spacing: spacing }), actions !== null && ((0, jsx_runtime_1.jsx)(material_1.Stack, { className: "ET-ViewPage-Actions", direction: "row", width: "100%", flexWrap: "wrap", justifyContent: "center", paddingTop: actions == null ? undefined : actionPaddings, paddingBottom: actionPaddings, gap: actionPaddings, children: actions != null && shared_1.Utils.getResult(actions, data, refresh) })), shared_1.Utils.getResult(children, data, refresh), pullToRefresh && ((0, jsx_runtime_1.jsx)(PullToRefreshUI_1.PullToRefreshUI, { mainElement: pullContainer, triggerElement: pullContainer, instructionsPullToRefresh: labels.pullToRefresh, instructionsReleaseToRefresh: labels.releaseToRefresh, instructionsRefreshing: labels.refreshing, onRefresh: refresh, shouldPullToRefresh: () => {
|
|
271
58
|
const container = document.querySelector(pullContainer);
|
|
272
59
|
return !container?.scrollTop;
|
|
273
|
-
} })), (0, jsx_runtime_1.jsx)(
|
|
60
|
+
} })), (0, jsx_runtime_1.jsx)(react_1.ScrollRestoration, {})] })) }));
|
|
274
61
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AlertProps } from "@mui/material";
|
|
2
|
+
/**
|
|
3
|
+
* Error alert props
|
|
4
|
+
*/
|
|
5
|
+
export type ErrorAlertProps = AlertProps & {
|
|
6
|
+
/**
|
|
7
|
+
* Message to display
|
|
8
|
+
*/
|
|
9
|
+
message?: React.ReactNode;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Error alert component
|
|
13
|
+
* @param props Props
|
|
14
|
+
* @returns Component
|
|
15
|
+
*/
|
|
16
|
+
export declare function ErrorAlert(props: ErrorAlertProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Alert } from "@mui/material";
|
|
3
|
+
import { useAppContext } from "./app/ReactApp";
|
|
4
|
+
/**
|
|
5
|
+
* Error alert component
|
|
6
|
+
* @param props Props
|
|
7
|
+
* @returns Component
|
|
8
|
+
*/
|
|
9
|
+
export function ErrorAlert(props) {
|
|
10
|
+
// Global app
|
|
11
|
+
const app = useAppContext();
|
|
12
|
+
// Destruct
|
|
13
|
+
const { message = app?.get("idError"), ...alertProps } = props;
|
|
14
|
+
// Layout
|
|
15
|
+
return (_jsx(Alert, { severity: "error", ...alertProps, children: message }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Breakpoint, Grid2Props } from "@mui/material";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { DataTypes } from "@etsoo/shared";
|
|
4
|
+
import { GridColumnRenderProps, GridDataType } from "@etsoo/react";
|
|
5
|
+
/**
|
|
6
|
+
* View page item size
|
|
7
|
+
*/
|
|
8
|
+
export type ViewPageItemSize = Record<Breakpoint, number | undefined>;
|
|
9
|
+
/**
|
|
10
|
+
* View page grid item size
|
|
11
|
+
*/
|
|
12
|
+
export declare namespace ViewPageSize {
|
|
13
|
+
const large: ViewPageItemSize;
|
|
14
|
+
const medium: ViewPageItemSize;
|
|
15
|
+
const line: ViewPageItemSize;
|
|
16
|
+
const small: ViewPageItemSize;
|
|
17
|
+
const smallLine: ViewPageItemSize;
|
|
18
|
+
function matchSize(size: ViewPageItemSize): {
|
|
19
|
+
[k: string]: number | undefined;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* View page row width type
|
|
24
|
+
*/
|
|
25
|
+
export type ViewPageRowType = boolean | "default" | "small" | "medium" | "large" | ViewPageItemSize;
|
|
26
|
+
/**
|
|
27
|
+
* View page grid item properties
|
|
28
|
+
*/
|
|
29
|
+
export type ViewPageGridItemProps = Grid2Props & {
|
|
30
|
+
data: React.ReactNode;
|
|
31
|
+
label?: React.ReactNode;
|
|
32
|
+
singleRow?: ViewPageRowType;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* View page grid item
|
|
36
|
+
* @param props Props
|
|
37
|
+
* @returns Result
|
|
38
|
+
*/
|
|
39
|
+
export declare function ViewPageGridItem(props: ViewPageGridItemProps): import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
/**
|
|
41
|
+
* View page display field
|
|
42
|
+
*/
|
|
43
|
+
export interface ViewPageField<T extends object> extends Grid2Props {
|
|
44
|
+
/**
|
|
45
|
+
* Data field
|
|
46
|
+
*/
|
|
47
|
+
data: (string & keyof T) | ((item: T) => React.ReactNode);
|
|
48
|
+
/**
|
|
49
|
+
* Data type
|
|
50
|
+
*/
|
|
51
|
+
dataType?: GridDataType;
|
|
52
|
+
/**
|
|
53
|
+
* Label field
|
|
54
|
+
*/
|
|
55
|
+
label?: string | ((item: T) => React.ReactNode);
|
|
56
|
+
/**
|
|
57
|
+
* Display as single row
|
|
58
|
+
*/
|
|
59
|
+
singleRow?: ViewPageRowType;
|
|
60
|
+
/**
|
|
61
|
+
* Render props
|
|
62
|
+
*/
|
|
63
|
+
renderProps?: GridColumnRenderProps;
|
|
64
|
+
}
|
|
65
|
+
type ViewPageFieldTypeNarrow<T extends object> = (string & keyof T) | [string & keyof T, GridDataType, GridColumnRenderProps?, ViewPageRowType?] | ViewPageField<T>;
|
|
66
|
+
/**
|
|
67
|
+
* View page field type
|
|
68
|
+
*/
|
|
69
|
+
export type ViewPageFieldType<T extends object> = ViewPageFieldTypeNarrow<T> | ((data: T, refresh: () => Promise<void>) => React.ReactNode | [React.ReactNode, ViewPageItemSize]);
|
|
70
|
+
export type ViewContainerProps<T extends DataTypes.StringRecord> = {
|
|
71
|
+
/**
|
|
72
|
+
* Data
|
|
73
|
+
*/
|
|
74
|
+
data: T;
|
|
75
|
+
/**
|
|
76
|
+
* Fields to display
|
|
77
|
+
*/
|
|
78
|
+
fields: ViewPageFieldType<T>[];
|
|
79
|
+
/**
|
|
80
|
+
* Grid container reference
|
|
81
|
+
*/
|
|
82
|
+
gridRef?: React.Ref<HTMLDivElement>;
|
|
83
|
+
/**
|
|
84
|
+
* Left container
|
|
85
|
+
*/
|
|
86
|
+
leftContainer?: (data: T) => React.ReactNode;
|
|
87
|
+
/**
|
|
88
|
+
* Left container height in lines
|
|
89
|
+
*/
|
|
90
|
+
leftContainerLines?: number;
|
|
91
|
+
/**
|
|
92
|
+
* Left container properties
|
|
93
|
+
*/
|
|
94
|
+
leftContainerProps?: Omit<Grid2Props, "size"> & {
|
|
95
|
+
size?: ViewPageItemSize;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Refresh function
|
|
99
|
+
*/
|
|
100
|
+
refresh: () => Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Grid spacing
|
|
103
|
+
*/
|
|
104
|
+
spacing?: Record<string, string | number>;
|
|
105
|
+
};
|
|
106
|
+
export declare function ViewContainer<T extends DataTypes.StringRecord>(props: ViewContainerProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
107
|
+
export {};
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { createElement as _createElement } from "react";
|
|
2
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Grid2, Typography } from "@mui/material";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { MUGlobal } from "./MUGlobal";
|
|
6
|
+
import { useCurrentBreakpoint } from "./useCurrentBreakpoint";
|
|
7
|
+
import { GridDataFormat } from "./GridDataFormat";
|
|
8
|
+
import { useRequiredAppContext } from "./app/ReactApp";
|
|
9
|
+
function formatItemData(app, fieldData) {
|
|
10
|
+
if (fieldData == null)
|
|
11
|
+
return undefined;
|
|
12
|
+
if (typeof fieldData === "string")
|
|
13
|
+
return fieldData;
|
|
14
|
+
if (fieldData instanceof Date)
|
|
15
|
+
return app.formatDate(fieldData, "d");
|
|
16
|
+
return `${fieldData}`;
|
|
17
|
+
}
|
|
18
|
+
function getResp(singleRow) {
|
|
19
|
+
const size = typeof singleRow === "object"
|
|
20
|
+
? singleRow
|
|
21
|
+
: singleRow === "medium"
|
|
22
|
+
? ViewPageSize.medium
|
|
23
|
+
: singleRow === "large"
|
|
24
|
+
? ViewPageSize.large
|
|
25
|
+
: singleRow === true
|
|
26
|
+
? ViewPageSize.line
|
|
27
|
+
: singleRow === false
|
|
28
|
+
? ViewPageSize.smallLine
|
|
29
|
+
: ViewPageSize.small;
|
|
30
|
+
return size;
|
|
31
|
+
}
|
|
32
|
+
function getItemField(app, field, data) {
|
|
33
|
+
// Item data and label
|
|
34
|
+
let itemData, itemLabel, gridProps = {}, size;
|
|
35
|
+
if (Array.isArray(field)) {
|
|
36
|
+
const [fieldData, fieldType, renderProps, singleRow = "small"] = field;
|
|
37
|
+
itemData = GridDataFormat(data[fieldData], fieldType, renderProps);
|
|
38
|
+
itemLabel = app.get(fieldData) ?? fieldData;
|
|
39
|
+
size = getResp(singleRow);
|
|
40
|
+
gridProps = { size };
|
|
41
|
+
}
|
|
42
|
+
else if (typeof field === "object") {
|
|
43
|
+
// Destruct
|
|
44
|
+
const { data: fieldData, dataType, label: fieldLabel, renderProps, singleRow = "default", ...rest } = field;
|
|
45
|
+
// Size
|
|
46
|
+
size = getResp(singleRow);
|
|
47
|
+
gridProps = {
|
|
48
|
+
...rest,
|
|
49
|
+
size
|
|
50
|
+
};
|
|
51
|
+
// Field data
|
|
52
|
+
if (typeof fieldData === "function")
|
|
53
|
+
itemData = fieldData(data);
|
|
54
|
+
else if (dataType == null)
|
|
55
|
+
itemData = formatItemData(app, data[fieldData]);
|
|
56
|
+
else
|
|
57
|
+
itemData = GridDataFormat(data[fieldData], dataType, renderProps);
|
|
58
|
+
// Field label
|
|
59
|
+
itemLabel =
|
|
60
|
+
fieldLabel === ""
|
|
61
|
+
? undefined
|
|
62
|
+
: fieldLabel == null && typeof fieldData === "string"
|
|
63
|
+
? app.get(fieldData) ?? fieldData
|
|
64
|
+
: typeof fieldLabel === "function"
|
|
65
|
+
? fieldLabel(data)
|
|
66
|
+
: fieldLabel != null
|
|
67
|
+
? app.get(fieldLabel) ?? fieldLabel
|
|
68
|
+
: undefined;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// Single field format
|
|
72
|
+
itemData = formatItemData(app, data[field]);
|
|
73
|
+
itemLabel = app.get(field) ?? field;
|
|
74
|
+
size = ViewPageSize.small;
|
|
75
|
+
gridProps = { size };
|
|
76
|
+
}
|
|
77
|
+
return [itemData, itemLabel, gridProps, size];
|
|
78
|
+
}
|
|
79
|
+
function getItemSize(bp, size) {
|
|
80
|
+
const v = size[bp];
|
|
81
|
+
if (v != null)
|
|
82
|
+
return v;
|
|
83
|
+
const index = breakpoints.indexOf(bp);
|
|
84
|
+
for (let i = index; i >= 0; i--) {
|
|
85
|
+
const v = size[breakpoints[i]];
|
|
86
|
+
if (v != null)
|
|
87
|
+
return v;
|
|
88
|
+
}
|
|
89
|
+
return 12;
|
|
90
|
+
}
|
|
91
|
+
const breakpoints = ["xs", "sm", "md", "lg", "xl"];
|
|
92
|
+
/**
|
|
93
|
+
* View page grid item size
|
|
94
|
+
*/
|
|
95
|
+
export var ViewPageSize;
|
|
96
|
+
(function (ViewPageSize) {
|
|
97
|
+
ViewPageSize.large = {
|
|
98
|
+
xs: 12,
|
|
99
|
+
sm: 12,
|
|
100
|
+
md: 9,
|
|
101
|
+
lg: 6,
|
|
102
|
+
xl: 4
|
|
103
|
+
};
|
|
104
|
+
ViewPageSize.medium = {
|
|
105
|
+
xs: 12,
|
|
106
|
+
sm: 12,
|
|
107
|
+
md: 6,
|
|
108
|
+
lg: 4,
|
|
109
|
+
xl: 3
|
|
110
|
+
};
|
|
111
|
+
ViewPageSize.line = {
|
|
112
|
+
xs: 12,
|
|
113
|
+
sm: 12,
|
|
114
|
+
md: 12,
|
|
115
|
+
lg: 12,
|
|
116
|
+
xl: 12
|
|
117
|
+
};
|
|
118
|
+
ViewPageSize.small = { xs: 6, sm: 6, md: 4, lg: 3, xl: 2 };
|
|
119
|
+
ViewPageSize.smallLine = {
|
|
120
|
+
xs: 12,
|
|
121
|
+
sm: 6,
|
|
122
|
+
md: 4,
|
|
123
|
+
lg: 3,
|
|
124
|
+
xl: 2
|
|
125
|
+
};
|
|
126
|
+
function matchSize(size) {
|
|
127
|
+
return Object.fromEntries(Object.entries(size).map(([key, value]) => [
|
|
128
|
+
key,
|
|
129
|
+
value == null ? undefined : value === 12 ? 12 : 12 - value
|
|
130
|
+
]));
|
|
131
|
+
}
|
|
132
|
+
ViewPageSize.matchSize = matchSize;
|
|
133
|
+
})(ViewPageSize || (ViewPageSize = {}));
|
|
134
|
+
/**
|
|
135
|
+
* View page grid item
|
|
136
|
+
* @param props Props
|
|
137
|
+
* @returns Result
|
|
138
|
+
*/
|
|
139
|
+
export function ViewPageGridItem(props) {
|
|
140
|
+
// Destruct
|
|
141
|
+
const { data, label, singleRow, ...gridProps } = props;
|
|
142
|
+
// Default options
|
|
143
|
+
let options = {};
|
|
144
|
+
if (gridProps.size == null) {
|
|
145
|
+
options = getResp(singleRow ?? "small");
|
|
146
|
+
}
|
|
147
|
+
else if (singleRow != null) {
|
|
148
|
+
options = getResp(singleRow ?? "small");
|
|
149
|
+
}
|
|
150
|
+
// Layout
|
|
151
|
+
return (_jsxs(Grid2, { ...gridProps, ...options, children: [label != null && (_jsxs(Typography, { variant: "caption", component: "div", children: [label, ":"] })), typeof data === "object" ? (data) : (_jsx(Typography, { variant: "subtitle2", children: data }))] }));
|
|
152
|
+
}
|
|
153
|
+
export function ViewContainer(props) {
|
|
154
|
+
// Global app
|
|
155
|
+
const app = useRequiredAppContext();
|
|
156
|
+
// Destruct
|
|
157
|
+
const { data, fields, gridRef, leftContainer, leftContainerLines = 3, leftContainerProps = {}, refresh, spacing = MUGlobal.half(MUGlobal.pagePaddings), ...rest } = props;
|
|
158
|
+
// Left container
|
|
159
|
+
const { size = ViewPageSize.smallLine, ...leftContainerPropsRest } = leftContainerProps;
|
|
160
|
+
// Current breakpoint
|
|
161
|
+
const bp = useCurrentBreakpoint();
|
|
162
|
+
// Create fields
|
|
163
|
+
const fieldIndexRef = React.useRef(0);
|
|
164
|
+
const createFields = React.useCallback((data, maxItems = 0) => {
|
|
165
|
+
let validItems = 0;
|
|
166
|
+
const items = [];
|
|
167
|
+
let i = fieldIndexRef.current;
|
|
168
|
+
for (; i < fields.length; i++) {
|
|
169
|
+
const field = fields[i];
|
|
170
|
+
let oneSize;
|
|
171
|
+
let oneItem;
|
|
172
|
+
if (typeof field === "function") {
|
|
173
|
+
// Most flexible way, do whatever you want
|
|
174
|
+
const createdResult = field(data, refresh);
|
|
175
|
+
if (createdResult == null || createdResult === "")
|
|
176
|
+
continue;
|
|
177
|
+
if (Array.isArray(createdResult)) {
|
|
178
|
+
const [created, size] = createdResult;
|
|
179
|
+
oneSize = size;
|
|
180
|
+
oneItem = created;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
oneSize = ViewPageSize.line;
|
|
184
|
+
oneItem = createdResult;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
const [itemData, itemLabel, gridProps, size] = getItemField(app, field, data);
|
|
189
|
+
// Some callback function may return '' instead of undefined
|
|
190
|
+
if (itemData == null || itemData === "")
|
|
191
|
+
continue;
|
|
192
|
+
oneSize = size;
|
|
193
|
+
oneItem = (_createElement(ViewPageGridItem, { ...gridProps, key: i, data: itemData, label: itemLabel }));
|
|
194
|
+
}
|
|
195
|
+
// Max lines
|
|
196
|
+
if (maxItems > 0) {
|
|
197
|
+
const itemSize = getItemSize(bp, oneSize);
|
|
198
|
+
if (maxItems < validItems + itemSize) {
|
|
199
|
+
fieldIndexRef.current = i;
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
items.push(oneItem);
|
|
204
|
+
validItems += itemSize;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
items.push(oneItem);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (maxItems === 0) {
|
|
212
|
+
fieldIndexRef.current = 0;
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
fieldIndexRef.current = i;
|
|
216
|
+
}
|
|
217
|
+
return items;
|
|
218
|
+
}, [app, fields, data, bp]);
|
|
219
|
+
let leftResult;
|
|
220
|
+
// Layout
|
|
221
|
+
return (_jsxs(Grid2, { container: true, justifyContent: "left", className: "ET-ViewPage", ref: gridRef, spacing: spacing, children: [leftContainer && (leftResult = leftContainer(data)) != null && (_jsxs(React.Fragment, { children: [_jsx(Grid2, { container: true, className: "ET-ViewPage-LeftContainer", spacing: spacing, size: size, ...leftContainerPropsRest, children: leftResult }), _jsx(Grid2, { container: true, className: "ET-ViewPage-LeftOthers", spacing: spacing, size: ViewPageSize.matchSize(size), children: createFields(data, leftContainerLines * (12 - getItemSize(bp, size))) })] })), createFields(data)] }));
|
|
222
|
+
}
|
package/lib/mjs/index.d.ts
CHANGED
|
@@ -53,6 +53,7 @@ export * from "./DialogButton";
|
|
|
53
53
|
export * from "./DnDList";
|
|
54
54
|
export * from "./DraggablePaperComponent";
|
|
55
55
|
export * from "./EmailInput";
|
|
56
|
+
export * from "./ErrorAlert";
|
|
56
57
|
export * from "./FabBox";
|
|
57
58
|
export * from "./FieldSetEx";
|
|
58
59
|
export * from "./FileUploadButton";
|
|
@@ -116,3 +117,4 @@ export * from "./useCurrentBreakpoint";
|
|
|
116
117
|
export * from "./TooltipClick";
|
|
117
118
|
export * from "./UserAvatar";
|
|
118
119
|
export * from "./UserAvatarEditor";
|
|
120
|
+
export * from "./ViewContainer";
|
package/lib/mjs/index.js
CHANGED
|
@@ -53,6 +53,7 @@ export * from "./DialogButton";
|
|
|
53
53
|
export * from "./DnDList";
|
|
54
54
|
export * from "./DraggablePaperComponent";
|
|
55
55
|
export * from "./EmailInput";
|
|
56
|
+
export * from "./ErrorAlert";
|
|
56
57
|
export * from "./FabBox";
|
|
57
58
|
export * from "./FieldSetEx";
|
|
58
59
|
export * from "./FileUploadButton";
|
|
@@ -116,3 +117,4 @@ export * from "./useCurrentBreakpoint";
|
|
|
116
117
|
export * from "./TooltipClick";
|
|
117
118
|
export * from "./UserAvatar";
|
|
118
119
|
export * from "./UserAvatarEditor";
|
|
120
|
+
export * from "./ViewContainer";
|