@etsoo/materialui 1.3.67 → 1.3.69
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/UserAvatarEditor.js +13 -5
- package/lib/custom/CustomFieldViewer.d.ts +50 -0
- package/lib/custom/CustomFieldViewer.js +54 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/package.json +4 -4
- package/src/UserAvatarEditor.tsx +20 -7
- package/src/custom/CustomFieldViewer.tsx +138 -0
- package/src/index.ts +1 -0
package/lib/UserAvatarEditor.js
CHANGED
|
@@ -10,6 +10,7 @@ import RemoveIcon from "@mui/icons-material/Remove";
|
|
|
10
10
|
import AddIcon from "@mui/icons-material/Add";
|
|
11
11
|
import { Labels } from "./app/Labels";
|
|
12
12
|
import { FileUploadButton } from "./FileUploadButton";
|
|
13
|
+
const defaultSize = 300;
|
|
13
14
|
const defaultState = {
|
|
14
15
|
scale: 1,
|
|
15
16
|
rotate: 0
|
|
@@ -22,11 +23,11 @@ const defaultState = {
|
|
|
22
23
|
*/
|
|
23
24
|
export function UserAvatarEditor(props) {
|
|
24
25
|
// Destruct
|
|
25
|
-
const { border = 30, image, maxWidth, onDone, scaledResult = false, width =
|
|
26
|
+
const { border = 30, image, maxWidth, onDone, scaledResult = false, width = defaultSize, height = defaultSize, range = [0.1, 2, 0.1] } = props;
|
|
26
27
|
// Container width
|
|
27
28
|
const containerWidth = width + 2 * border + 44 + 4;
|
|
28
29
|
// Calculated max width
|
|
29
|
-
const maxWidthCalculated = maxWidth == null || maxWidth <
|
|
30
|
+
const maxWidthCalculated = maxWidth == null || maxWidth < defaultSize ? 2 * width : maxWidth;
|
|
30
31
|
// Labels
|
|
31
32
|
const labels = Labels.UserAvatarEditor;
|
|
32
33
|
// Ref
|
|
@@ -41,6 +42,10 @@ export function UserAvatarEditor(props) {
|
|
|
41
42
|
const [ready, setReady] = React.useState(false);
|
|
42
43
|
// Editor states
|
|
43
44
|
const [editorState, setEditorState] = React.useState(defaultState);
|
|
45
|
+
// Height
|
|
46
|
+
// noHeight: height is not set and will be updated dynamically
|
|
47
|
+
const noHeight = height <= 0;
|
|
48
|
+
const [localHeight, setHeight] = React.useState(noHeight ? defaultSize : height);
|
|
44
49
|
// Range
|
|
45
50
|
const [min, max, step] = range;
|
|
46
51
|
const marks = [
|
|
@@ -69,7 +74,10 @@ export function UserAvatarEditor(props) {
|
|
|
69
74
|
setScale(editorState.scale + (isAdd ? step : -step));
|
|
70
75
|
};
|
|
71
76
|
// Handle image load
|
|
72
|
-
const handleLoad = () => {
|
|
77
|
+
const handleLoad = (imageInfo) => {
|
|
78
|
+
if (noHeight) {
|
|
79
|
+
setHeight((imageInfo.height * width) / imageInfo.width);
|
|
80
|
+
}
|
|
73
81
|
setReady(true);
|
|
74
82
|
};
|
|
75
83
|
// Handle file upload
|
|
@@ -115,7 +123,7 @@ export function UserAvatarEditor(props) {
|
|
|
115
123
|
};
|
|
116
124
|
if (data.width > maxWidthCalculated) {
|
|
117
125
|
// Target height
|
|
118
|
-
const heightCalculated = (
|
|
126
|
+
const heightCalculated = (localHeight * maxWidthCalculated) / width;
|
|
119
127
|
// Target
|
|
120
128
|
const to = document.createElement("canvas");
|
|
121
129
|
to.width = maxWidthCalculated;
|
|
@@ -136,5 +144,5 @@ export function UserAvatarEditor(props) {
|
|
|
136
144
|
};
|
|
137
145
|
// Load the component
|
|
138
146
|
const AE = React.lazy(() => import("react-avatar-editor"));
|
|
139
|
-
return (_jsxs(Stack, { direction: "column", spacing: 0.5, width: containerWidth, children: [_jsx(FileUploadButton, { variant: "outlined", size: "medium", startIcon: _jsx(ComputerIcon, {}), fullWidth: true, onUploadFiles: handleFileUpload, inputProps: { multiple: false, accept: "image/png, image/jpeg" }, children: labels.upload }), _jsxs(Stack, { direction: "row", spacing: 0.5, children: [_jsx(React.Suspense, { fallback: _jsx(Skeleton, { variant: "rounded", width: width, height:
|
|
147
|
+
return (_jsxs(Stack, { direction: "column", spacing: 0.5, width: containerWidth, children: [_jsx(FileUploadButton, { variant: "outlined", size: "medium", startIcon: _jsx(ComputerIcon, {}), fullWidth: true, onUploadFiles: handleFileUpload, inputProps: { multiple: false, accept: "image/png, image/jpeg" }, children: labels.upload }), _jsxs(Stack, { direction: "row", spacing: 0.5, children: [_jsx(React.Suspense, { fallback: _jsx(Skeleton, { variant: "rounded", width: width, height: localHeight }), children: _jsx(AE, { ref: ref, border: border, width: width, height: localHeight, onLoadSuccess: handleLoad, image: previewImage ?? "", scale: editorState.scale, rotate: editorState.rotate }) }), _jsxs(ButtonGroup, { size: "small", orientation: "vertical", disabled: !ready, children: [_jsx(Button, { onClick: () => handleRotate(90), title: labels.rotateRight, children: _jsx(RotateRightIcon, {}) }), _jsx(Button, { onClick: () => handleRotate(-90), title: labels.rotateLeft, children: _jsx(RotateLeftIcon, {}) }), _jsx(Button, { onClick: handleReset, title: labels.reset, children: _jsx(ClearAllIcon, {}) })] })] }), _jsxs(Stack, { spacing: 0.5, direction: "row", sx: { paddingBottom: 2 }, alignItems: "center", children: [_jsx(IconButton, { size: "small", disabled: !ready || editorState.scale <= min, onClick: () => adjustScale(false), children: _jsx(RemoveIcon, {}) }), _jsx(Slider, { title: labels.zoom, disabled: !ready, min: min, max: max, step: step, value: editorState.scale, valueLabelDisplay: "auto", valueLabelFormat: (value) => `${Math.round(100 * value) / 100}`, marks: marks, onChange: handleZoom }), _jsx(IconButton, { size: "small", disabled: !ready || editorState.scale >= max, onClick: () => adjustScale(true), children: _jsx(AddIcon, {}) })] }), _jsx(Button, { ref: buttonRef, variant: "contained", startIcon: _jsx(DoneIcon, {}), disabled: !ready, onClick: handleDone, children: labels.done })] }));
|
|
140
148
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { CustomFieldData } from "@etsoo/appscript";
|
|
2
|
+
import { GridProps, TypographyProps } from "@mui/material";
|
|
3
|
+
/**
|
|
4
|
+
* Custom field viewer props
|
|
5
|
+
* 自定义字段查看器属性
|
|
6
|
+
*/
|
|
7
|
+
export type CustomFieldViewerProps = {
|
|
8
|
+
/**
|
|
9
|
+
* Custom fields
|
|
10
|
+
* 自定义字段
|
|
11
|
+
*/
|
|
12
|
+
fields: CustomFieldData[];
|
|
13
|
+
/**
|
|
14
|
+
* Grid props
|
|
15
|
+
* 网格属性
|
|
16
|
+
*/
|
|
17
|
+
gridProps?: GridProps;
|
|
18
|
+
/**
|
|
19
|
+
* JSON data
|
|
20
|
+
* JSON 数据
|
|
21
|
+
*/
|
|
22
|
+
jsonData: unknown;
|
|
23
|
+
/**
|
|
24
|
+
* Title label props
|
|
25
|
+
* 标题标签属性
|
|
26
|
+
*/
|
|
27
|
+
titleProps?: TypographyProps;
|
|
28
|
+
/**
|
|
29
|
+
* Vertical gap
|
|
30
|
+
* 垂直间距
|
|
31
|
+
*/
|
|
32
|
+
verticalGap?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Value label formatter
|
|
35
|
+
* 值标签格式化
|
|
36
|
+
*/
|
|
37
|
+
valueLabelFormatter?: (value: any, field: CustomFieldData) => string;
|
|
38
|
+
/**
|
|
39
|
+
* Value label props
|
|
40
|
+
* 值标签属性
|
|
41
|
+
*/
|
|
42
|
+
valueProps?: TypographyProps;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Custom field viewer
|
|
46
|
+
* 自定义字段查看器
|
|
47
|
+
* @param props Props
|
|
48
|
+
* @returns Component
|
|
49
|
+
*/
|
|
50
|
+
export declare function CustomFieldViewer(props: CustomFieldViewerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Grid, Typography } from "@mui/material";
|
|
3
|
+
import { CustomFieldUtils } from "./CustomFieldUtils";
|
|
4
|
+
import { MUGlobal } from "../MUGlobal";
|
|
5
|
+
import { VBox } from "../FlexBox";
|
|
6
|
+
import { DataTypes, Utils } from "@etsoo/shared";
|
|
7
|
+
/**
|
|
8
|
+
* Custom field viewer
|
|
9
|
+
* 自定义字段查看器
|
|
10
|
+
* @param props Props
|
|
11
|
+
* @returns Component
|
|
12
|
+
*/
|
|
13
|
+
export function CustomFieldViewer(props) {
|
|
14
|
+
// Destruct
|
|
15
|
+
const { fields, gridProps, jsonData, titleProps, verticalGap = 0.5, valueLabelFormatter = (value, field) => {
|
|
16
|
+
if (value == null)
|
|
17
|
+
return "";
|
|
18
|
+
if (field.options) {
|
|
19
|
+
const option = field.options.find((o) => o.id === value);
|
|
20
|
+
if (option) {
|
|
21
|
+
return DataTypes.getListItemLabel(option);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (typeof value === "object") {
|
|
25
|
+
if (value instanceof Date) {
|
|
26
|
+
return value.toLocaleString();
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
return JSON.stringify(value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
return `${value}`;
|
|
34
|
+
}
|
|
35
|
+
}, valueProps } = props;
|
|
36
|
+
const spacing = MUGlobal.half(MUGlobal.pagePaddings);
|
|
37
|
+
const data = typeof jsonData === "string" ? JSON.parse(jsonData) : jsonData;
|
|
38
|
+
if (data == null || typeof data !== "object" || Array.isArray(data)) {
|
|
39
|
+
throw new Error("Invalid JSON data");
|
|
40
|
+
}
|
|
41
|
+
return (_jsx(Grid, { container: true, justifyContent: "left", spacing: spacing, sx: {
|
|
42
|
+
".MuiTypography-subtitle2": {
|
|
43
|
+
fontWeight: "bold"
|
|
44
|
+
}
|
|
45
|
+
}, ...gridProps, children: fields.map((field, index) => {
|
|
46
|
+
// Field name
|
|
47
|
+
const name = field.name;
|
|
48
|
+
if (!name)
|
|
49
|
+
return;
|
|
50
|
+
// Field value
|
|
51
|
+
const value = Utils.getNestedValue(data, name);
|
|
52
|
+
return (_jsx(Grid, { item: true, ...field.gridItemProps, ...CustomFieldUtils.transformSpace(field.space), children: _jsxs(VBox, { gap: verticalGap, children: [_jsx(Typography, { fontWeight: "bold", fontSize: "small", ...titleProps, children: field.label ?? name }), _jsx(Typography, { ...valueProps, children: valueLabelFormatter(value, field) })] }) }, name ?? index));
|
|
53
|
+
}) }));
|
|
54
|
+
}
|
package/lib/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./app/Labels";
|
|
|
9
9
|
export * from "./app/ReactApp";
|
|
10
10
|
export * from "./app/ServiceApp";
|
|
11
11
|
export * from "./custom/CustomFieldUtils";
|
|
12
|
+
export * from "./custom/CustomFieldViewer";
|
|
12
13
|
export * from "./custom/CustomFieldWindow";
|
|
13
14
|
export * from "./messages/MessageUtils";
|
|
14
15
|
export * from "./messages/OperationMessageContainer";
|
package/lib/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./app/Labels";
|
|
|
9
9
|
export * from "./app/ReactApp";
|
|
10
10
|
export * from "./app/ServiceApp";
|
|
11
11
|
export * from "./custom/CustomFieldUtils";
|
|
12
|
+
export * from "./custom/CustomFieldViewer";
|
|
12
13
|
export * from "./custom/CustomFieldWindow";
|
|
13
14
|
export * from "./messages/MessageUtils";
|
|
14
15
|
export * from "./messages/OperationMessageContainer";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/materialui",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.69",
|
|
4
4
|
"description": "TypeScript Material-UI Implementation",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"@etsoo/notificationbase": "^1.1.42",
|
|
55
55
|
"@etsoo/react": "^1.7.54",
|
|
56
56
|
"@etsoo/shared": "^1.2.41",
|
|
57
|
-
"@mui/icons-material": "^5.15.
|
|
58
|
-
"@mui/material": "^5.15.
|
|
59
|
-
"@mui/x-data-grid": "^7.
|
|
57
|
+
"@mui/icons-material": "^5.15.19",
|
|
58
|
+
"@mui/material": "^5.15.19",
|
|
59
|
+
"@mui/x-data-grid": "^7.6.1",
|
|
60
60
|
"chart.js": "^4.4.3",
|
|
61
61
|
"chartjs-plugin-datalabels": "^2.2.0",
|
|
62
62
|
"eventemitter3": "^5.0.1",
|
package/src/UserAvatarEditor.tsx
CHANGED
|
@@ -17,6 +17,9 @@ import RemoveIcon from "@mui/icons-material/Remove";
|
|
|
17
17
|
import AddIcon from "@mui/icons-material/Add";
|
|
18
18
|
import { Labels } from "./app/Labels";
|
|
19
19
|
import { FileUploadButton } from "./FileUploadButton";
|
|
20
|
+
import { ImageState } from "react-avatar-editor";
|
|
21
|
+
|
|
22
|
+
const defaultSize = 300;
|
|
20
23
|
|
|
21
24
|
/**
|
|
22
25
|
* User avatar editor to Blob helper
|
|
@@ -109,8 +112,8 @@ export function UserAvatarEditor(props: UserAvatarEditorProps) {
|
|
|
109
112
|
maxWidth,
|
|
110
113
|
onDone,
|
|
111
114
|
scaledResult = false,
|
|
112
|
-
width =
|
|
113
|
-
height =
|
|
115
|
+
width = defaultSize,
|
|
116
|
+
height = defaultSize,
|
|
114
117
|
range = [0.1, 2, 0.1]
|
|
115
118
|
} = props;
|
|
116
119
|
|
|
@@ -119,7 +122,7 @@ export function UserAvatarEditor(props: UserAvatarEditorProps) {
|
|
|
119
122
|
|
|
120
123
|
// Calculated max width
|
|
121
124
|
const maxWidthCalculated =
|
|
122
|
-
maxWidth == null || maxWidth <
|
|
125
|
+
maxWidth == null || maxWidth < defaultSize ? 2 * width : maxWidth;
|
|
123
126
|
|
|
124
127
|
// Labels
|
|
125
128
|
const labels = Labels.UserAvatarEditor;
|
|
@@ -142,6 +145,13 @@ export function UserAvatarEditor(props: UserAvatarEditorProps) {
|
|
|
142
145
|
// Editor states
|
|
143
146
|
const [editorState, setEditorState] = React.useState(defaultState);
|
|
144
147
|
|
|
148
|
+
// Height
|
|
149
|
+
// noHeight: height is not set and will be updated dynamically
|
|
150
|
+
const noHeight = height <= 0;
|
|
151
|
+
const [localHeight, setHeight] = React.useState(
|
|
152
|
+
noHeight ? defaultSize : height
|
|
153
|
+
);
|
|
154
|
+
|
|
145
155
|
// Range
|
|
146
156
|
const [min, max, step] = range;
|
|
147
157
|
const marks = [
|
|
@@ -179,7 +189,10 @@ export function UserAvatarEditor(props: UserAvatarEditorProps) {
|
|
|
179
189
|
};
|
|
180
190
|
|
|
181
191
|
// Handle image load
|
|
182
|
-
const handleLoad = () => {
|
|
192
|
+
const handleLoad = (imageInfo: ImageState) => {
|
|
193
|
+
if (noHeight) {
|
|
194
|
+
setHeight((imageInfo.height * width) / imageInfo.width);
|
|
195
|
+
}
|
|
183
196
|
setReady(true);
|
|
184
197
|
};
|
|
185
198
|
|
|
@@ -238,7 +251,7 @@ export function UserAvatarEditor(props: UserAvatarEditorProps) {
|
|
|
238
251
|
|
|
239
252
|
if (data.width > maxWidthCalculated) {
|
|
240
253
|
// Target height
|
|
241
|
-
const heightCalculated = (
|
|
254
|
+
const heightCalculated = (localHeight * maxWidthCalculated) / width;
|
|
242
255
|
|
|
243
256
|
// Target
|
|
244
257
|
const to = document.createElement("canvas");
|
|
@@ -277,14 +290,14 @@ export function UserAvatarEditor(props: UserAvatarEditorProps) {
|
|
|
277
290
|
<Stack direction="row" spacing={0.5}>
|
|
278
291
|
<React.Suspense
|
|
279
292
|
fallback={
|
|
280
|
-
<Skeleton variant="rounded" width={width} height={
|
|
293
|
+
<Skeleton variant="rounded" width={width} height={localHeight} />
|
|
281
294
|
}
|
|
282
295
|
>
|
|
283
296
|
<AE
|
|
284
297
|
ref={ref}
|
|
285
298
|
border={border}
|
|
286
299
|
width={width}
|
|
287
|
-
height={
|
|
300
|
+
height={localHeight}
|
|
288
301
|
onLoadSuccess={handleLoad}
|
|
289
302
|
image={previewImage ?? ""}
|
|
290
303
|
scale={editorState.scale}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { CustomFieldData } from "@etsoo/appscript";
|
|
2
|
+
import { Grid, GridProps, Typography, TypographyProps } from "@mui/material";
|
|
3
|
+
import { CustomFieldUtils } from "./CustomFieldUtils";
|
|
4
|
+
import { MUGlobal } from "../MUGlobal";
|
|
5
|
+
import { VBox } from "../FlexBox";
|
|
6
|
+
import { DataTypes, Utils } from "@etsoo/shared";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Custom field viewer props
|
|
10
|
+
* 自定义字段查看器属性
|
|
11
|
+
*/
|
|
12
|
+
export type CustomFieldViewerProps = {
|
|
13
|
+
/**
|
|
14
|
+
* Custom fields
|
|
15
|
+
* 自定义字段
|
|
16
|
+
*/
|
|
17
|
+
fields: CustomFieldData[];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Grid props
|
|
21
|
+
* 网格属性
|
|
22
|
+
*/
|
|
23
|
+
gridProps?: GridProps;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* JSON data
|
|
27
|
+
* JSON 数据
|
|
28
|
+
*/
|
|
29
|
+
jsonData: unknown;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Title label props
|
|
33
|
+
* 标题标签属性
|
|
34
|
+
*/
|
|
35
|
+
titleProps?: TypographyProps;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Vertical gap
|
|
39
|
+
* 垂直间距
|
|
40
|
+
*/
|
|
41
|
+
verticalGap?: number;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Value label formatter
|
|
45
|
+
* 值标签格式化
|
|
46
|
+
*/
|
|
47
|
+
valueLabelFormatter?: (value: any, field: CustomFieldData) => string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Value label props
|
|
51
|
+
* 值标签属性
|
|
52
|
+
*/
|
|
53
|
+
valueProps?: TypographyProps;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Custom field viewer
|
|
58
|
+
* 自定义字段查看器
|
|
59
|
+
* @param props Props
|
|
60
|
+
* @returns Component
|
|
61
|
+
*/
|
|
62
|
+
export function CustomFieldViewer(props: CustomFieldViewerProps) {
|
|
63
|
+
// Destruct
|
|
64
|
+
const {
|
|
65
|
+
fields,
|
|
66
|
+
gridProps,
|
|
67
|
+
jsonData,
|
|
68
|
+
titleProps,
|
|
69
|
+
verticalGap = 0.5,
|
|
70
|
+
valueLabelFormatter = (value, field) => {
|
|
71
|
+
if (value == null) return "";
|
|
72
|
+
if (field.options) {
|
|
73
|
+
const option = field.options.find((o) => o.id === value);
|
|
74
|
+
if (option) {
|
|
75
|
+
return DataTypes.getListItemLabel(option);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (typeof value === "object") {
|
|
80
|
+
if (value instanceof Date) {
|
|
81
|
+
return value.toLocaleString();
|
|
82
|
+
} else {
|
|
83
|
+
return JSON.stringify(value);
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
return `${value}`;
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
valueProps
|
|
90
|
+
} = props;
|
|
91
|
+
|
|
92
|
+
const spacing = MUGlobal.half(MUGlobal.pagePaddings);
|
|
93
|
+
const data = typeof jsonData === "string" ? JSON.parse(jsonData) : jsonData;
|
|
94
|
+
if (data == null || typeof data !== "object" || Array.isArray(data)) {
|
|
95
|
+
throw new Error("Invalid JSON data");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<Grid
|
|
100
|
+
container
|
|
101
|
+
justifyContent="left"
|
|
102
|
+
spacing={spacing}
|
|
103
|
+
sx={{
|
|
104
|
+
".MuiTypography-subtitle2": {
|
|
105
|
+
fontWeight: "bold"
|
|
106
|
+
}
|
|
107
|
+
}}
|
|
108
|
+
{...gridProps}
|
|
109
|
+
>
|
|
110
|
+
{fields.map((field, index) => {
|
|
111
|
+
// Field name
|
|
112
|
+
const name = field.name;
|
|
113
|
+
if (!name) return;
|
|
114
|
+
|
|
115
|
+
// Field value
|
|
116
|
+
const value = Utils.getNestedValue(data, name);
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<Grid
|
|
120
|
+
item
|
|
121
|
+
key={name ?? index}
|
|
122
|
+
{...field.gridItemProps}
|
|
123
|
+
{...CustomFieldUtils.transformSpace(field.space)}
|
|
124
|
+
>
|
|
125
|
+
<VBox gap={verticalGap}>
|
|
126
|
+
<Typography fontWeight="bold" fontSize="small" {...titleProps}>
|
|
127
|
+
{field.label ?? name}
|
|
128
|
+
</Typography>
|
|
129
|
+
<Typography {...valueProps}>
|
|
130
|
+
{valueLabelFormatter(value, field)}
|
|
131
|
+
</Typography>
|
|
132
|
+
</VBox>
|
|
133
|
+
</Grid>
|
|
134
|
+
);
|
|
135
|
+
})}
|
|
136
|
+
</Grid>
|
|
137
|
+
);
|
|
138
|
+
}
|
package/src/index.ts
CHANGED