@etsoo/materialui 1.1.96 → 1.1.98
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/FabBox.d.ts +1 -1
- package/lib/FabBox.js +11 -14
- package/lib/MenuButton.d.ts +9 -0
- package/lib/MenuButton.js +58 -0
- package/lib/ResponsibleContainer.d.ts +7 -0
- package/lib/ResponsibleContainer.js +3 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/pages/CommonPage.d.ts +1 -1
- package/lib/pages/CommonPage.js +25 -24
- package/lib/pages/CommonPageProps.d.ts +9 -5
- package/lib/pages/ResponsivePageProps.d.ts +13 -6
- package/package.json +1 -1
- package/src/FabBox.tsx +38 -37
- package/src/MenuButton.tsx +115 -0
- package/src/ResponsibleContainer.tsx +12 -0
- package/src/index.ts +1 -0
- package/src/pages/CommonPage.tsx +102 -111
- package/src/pages/CommonPageProps.ts +58 -53
- package/src/pages/ResponsivePageProps.ts +56 -48
package/lib/FabBox.d.ts
CHANGED
package/lib/FabBox.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Box, useTheme } from
|
|
2
|
-
import React from
|
|
1
|
+
import { Box, useTheme } from "@mui/material";
|
|
2
|
+
import React from "react";
|
|
3
3
|
/**
|
|
4
4
|
* Fabs container box
|
|
5
5
|
* @param props Props
|
|
@@ -7,7 +7,7 @@ import React from 'react';
|
|
|
7
7
|
*/
|
|
8
8
|
export function FabBox(props) {
|
|
9
9
|
// Destruct
|
|
10
|
-
const { columnDirection, itemGap = 1, sx
|
|
10
|
+
const { columnDirection, itemGap = 1, sx, ...rest } = props;
|
|
11
11
|
// Theme
|
|
12
12
|
const theme = useTheme();
|
|
13
13
|
const spaceGap = theme.spacing(itemGap);
|
|
@@ -17,15 +17,12 @@ export function FabBox(props) {
|
|
|
17
17
|
const margin = columnDirection
|
|
18
18
|
? { marginTop: spaceGap }
|
|
19
19
|
: { marginLeft: spaceGap };
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
return React.createElement(Box, { sx: sx, ...rest });
|
|
20
|
+
return (React.createElement(Box, { sx: {
|
|
21
|
+
position: "fixed",
|
|
22
|
+
display: "flex",
|
|
23
|
+
alignItems: "center",
|
|
24
|
+
flexDirection: columnDirection ? "column" : "row",
|
|
25
|
+
"& > :not(style) + :not(style)": margin,
|
|
26
|
+
...sx
|
|
27
|
+
}, ...rest }));
|
|
31
28
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DataTypes } from "@etsoo/shared";
|
|
2
|
+
import { ButtonProps, MenuProps } from "@mui/material";
|
|
3
|
+
import React from "react";
|
|
4
|
+
export type MenuButtonProps<T extends DataTypes.IdItem> = Omit<MenuProps, "open"> & {
|
|
5
|
+
items: T[];
|
|
6
|
+
labelField: DataTypes.Keys<T, string>;
|
|
7
|
+
button: ((clickHandler: React.MouseEventHandler<HTMLButtonElement>) => React.ReactNode) | ButtonProps;
|
|
8
|
+
};
|
|
9
|
+
export declare function MenuButton<T extends DataTypes.IdItem>(props: MenuButtonProps<T>): JSX.Element;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Button, Menu, MenuItem } from "@mui/material";
|
|
2
|
+
import React from "react";
|
|
3
|
+
export function MenuButton(props) {
|
|
4
|
+
// Destruct
|
|
5
|
+
const { button, items, labelField, anchorOrigin = {
|
|
6
|
+
vertical: "top",
|
|
7
|
+
horizontal: "right"
|
|
8
|
+
}, transformOrigin = {
|
|
9
|
+
vertical: anchorOrigin.vertical === "center"
|
|
10
|
+
? "center"
|
|
11
|
+
: anchorOrigin.vertical === "top"
|
|
12
|
+
? "bottom"
|
|
13
|
+
: "top",
|
|
14
|
+
horizontal: anchorOrigin.horizontal
|
|
15
|
+
}, sx, ...rest } = props;
|
|
16
|
+
// Top?
|
|
17
|
+
const isTop = transformOrigin.vertical === "top";
|
|
18
|
+
// Menu anchor
|
|
19
|
+
const [anchorEl, setAnchorEl] = React.useState();
|
|
20
|
+
// Menu open or not
|
|
21
|
+
const isMenuOpen = Boolean(anchorEl);
|
|
22
|
+
const handleMenuOpen = (event) => {
|
|
23
|
+
setAnchorEl(event.currentTarget);
|
|
24
|
+
};
|
|
25
|
+
const handleMenuClose = () => {
|
|
26
|
+
setAnchorEl(undefined);
|
|
27
|
+
};
|
|
28
|
+
return (React.createElement(React.Fragment, null,
|
|
29
|
+
typeof button === "function" ? (button(handleMenuOpen)) : (React.createElement(Button, { onClick: handleMenuOpen, ...button })),
|
|
30
|
+
React.createElement(Menu, { PaperProps: {
|
|
31
|
+
elevation: 0,
|
|
32
|
+
sx: {
|
|
33
|
+
overflow: "visible",
|
|
34
|
+
filter: "drop-shadow(0px 2px 8px rgba(0,0,0,0.32))",
|
|
35
|
+
"& .MuiAvatar-root": {
|
|
36
|
+
width: 32,
|
|
37
|
+
height: 32
|
|
38
|
+
},
|
|
39
|
+
"&:before": {
|
|
40
|
+
content: '""',
|
|
41
|
+
display: "block",
|
|
42
|
+
position: "absolute",
|
|
43
|
+
top: isTop ? 0 : undefined,
|
|
44
|
+
bottom: isTop ? undefined : -10,
|
|
45
|
+
right: 14,
|
|
46
|
+
width: 10,
|
|
47
|
+
height: 10,
|
|
48
|
+
bgcolor: "background.paper",
|
|
49
|
+
transform: "translateY(-50%) rotate(45deg)",
|
|
50
|
+
zIndex: 0
|
|
51
|
+
},
|
|
52
|
+
...{ sx }
|
|
53
|
+
}
|
|
54
|
+
}, disableScrollLock: true, anchorEl: anchorEl, anchorOrigin: anchorOrigin, keepMounted: true, transformOrigin: transformOrigin, open: isMenuOpen, transitionDuration: 0, onClose: handleMenuClose, ...rest }, items.map((item) => {
|
|
55
|
+
const label = item[labelField];
|
|
56
|
+
return (React.createElement(MenuItem, { key: item.id, disabled: true }, label));
|
|
57
|
+
}))));
|
|
58
|
+
}
|
|
@@ -15,6 +15,13 @@ export type ResponsibleContainerProps<T extends object, F extends DataTypes.Basi
|
|
|
15
15
|
* @param rect Current rect data
|
|
16
16
|
*/
|
|
17
17
|
adjustHeight?: (height: number, rect: DOMRect) => number;
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
* @param height Current height
|
|
21
|
+
* @param isGrid Is displaying DataGrid
|
|
22
|
+
* @returns Adjusted height
|
|
23
|
+
*/
|
|
24
|
+
adjustFabHeight?: (height: number, isGrid: boolean) => number;
|
|
18
25
|
/**
|
|
19
26
|
* Columns
|
|
20
27
|
*/
|
|
@@ -22,7 +22,7 @@ function defaultContainerBoxSx(paddings, hasField, _dataGrid) {
|
|
|
22
22
|
*/
|
|
23
23
|
export function ResponsibleContainer(props) {
|
|
24
24
|
// Destruct
|
|
25
|
-
const { adjustHeight, columns, containerBoxSx = defaultContainerBoxSx, dataGridMinWidth = Math.max(576, DataGridExCalColumns(columns).total), elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, ...rest } = props;
|
|
25
|
+
const { adjustHeight, adjustFabHeight, columns, containerBoxSx = defaultContainerBoxSx, dataGridMinWidth = Math.max(576, DataGridExCalColumns(columns).total), elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, ...rest } = props;
|
|
26
26
|
// Labels
|
|
27
27
|
const labels = Labels.CommonPage;
|
|
28
28
|
// Refs
|
|
@@ -97,6 +97,8 @@ export function ResponsibleContainer(props) {
|
|
|
97
97
|
if (adjustHeight != null)
|
|
98
98
|
heightLocal -= adjustHeight(heightLocal, rect);
|
|
99
99
|
}
|
|
100
|
+
if (adjustFabHeight)
|
|
101
|
+
heightLocal = adjustFabHeight(heightLocal, showDataGrid);
|
|
100
102
|
if (showDataGrid) {
|
|
101
103
|
// Delete
|
|
102
104
|
delete rest.itemRenderer;
|
package/lib/index.d.ts
CHANGED
|
@@ -61,6 +61,7 @@ export * from "./ListItemRightIcon";
|
|
|
61
61
|
export * from "./ListMoreDisplay";
|
|
62
62
|
export * from "./LoadingButton";
|
|
63
63
|
export * from "./MaskInput";
|
|
64
|
+
export * from "./MenuButton";
|
|
64
65
|
export * from "./MobileListItemRenderer";
|
|
65
66
|
export * from "./MoneyInputField";
|
|
66
67
|
export * from "./MoreFab";
|
package/lib/index.js
CHANGED
|
@@ -61,6 +61,7 @@ export * from "./ListItemRightIcon";
|
|
|
61
61
|
export * from "./ListMoreDisplay";
|
|
62
62
|
export * from "./LoadingButton";
|
|
63
63
|
export * from "./MaskInput";
|
|
64
|
+
export * from "./MenuButton";
|
|
64
65
|
export * from "./MobileListItemRenderer";
|
|
65
66
|
export * from "./MoneyInputField";
|
|
66
67
|
export * from "./MoreFab";
|
package/lib/pages/CommonPage.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { FabBox } from
|
|
3
|
-
import { ScrollTopFab } from
|
|
4
|
-
import { MUGlobal } from
|
|
5
|
-
import { MoreFab } from
|
|
6
|
-
import { Container, Fab } from
|
|
7
|
-
import RefreshIcon from
|
|
8
|
-
import { BackButton } from
|
|
9
|
-
import { Labels } from
|
|
10
|
-
import { ReactAppStateDetector } from
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { FabBox } from "../FabBox";
|
|
3
|
+
import { ScrollTopFab } from "../ScrollTopFab";
|
|
4
|
+
import { MUGlobal } from "../MUGlobal";
|
|
5
|
+
import { MoreFab } from "../MoreFab";
|
|
6
|
+
import { Container, Fab, Paper } from "@mui/material";
|
|
7
|
+
import RefreshIcon from "@mui/icons-material/Refresh";
|
|
8
|
+
import { BackButton } from "../BackButton";
|
|
9
|
+
import { Labels } from "../app/Labels";
|
|
10
|
+
import { ReactAppStateDetector } from "../app/ReactApp";
|
|
11
11
|
/**
|
|
12
12
|
* Default scroll container
|
|
13
13
|
*/
|
|
@@ -18,12 +18,12 @@ export const CommonPageScrollContainer = global;
|
|
|
18
18
|
*/
|
|
19
19
|
export function CommonPage(props) {
|
|
20
20
|
// Destruct
|
|
21
|
-
const { children, disableGutters = true, fabButtons, fabColumnDirection, fabPaddingAdjust = 1.5, fabSize =
|
|
21
|
+
const { children, disableGutters = true, fabButtons, fabColumnDirection, fabPanel = fabColumnDirection, fabPaddingAdjust = 1.5, fabSize = "small", maxWidth = false, moreActions, onRefresh, onUpdate, onUpdateAll, paddings = MUGlobal.pagePaddings, scrollContainer, supportBack = false, targetFields, sx = {}, ...rest } = props;
|
|
22
22
|
// Fab padding
|
|
23
23
|
const fabPadding = MUGlobal.increase(MUGlobal.pagePaddings, fabPaddingAdjust);
|
|
24
|
-
if (typeof sx ===
|
|
24
|
+
if (typeof sx === "object" && sx != null && !Reflect.has(sx, "padding")) {
|
|
25
25
|
// Set default padding
|
|
26
|
-
Reflect.set(sx,
|
|
26
|
+
Reflect.set(sx, "padding", paddings);
|
|
27
27
|
}
|
|
28
28
|
// Labels
|
|
29
29
|
const labels = Labels.CommonPage;
|
|
@@ -41,20 +41,21 @@ export function CommonPage(props) {
|
|
|
41
41
|
onRefresh();
|
|
42
42
|
}
|
|
43
43
|
: undefined;
|
|
44
|
+
const fab = (React.createElement(FabBox, { sx: {
|
|
45
|
+
zIndex: 1,
|
|
46
|
+
bottom: (theme) => MUGlobal.updateWithTheme(fabPadding, theme.spacing),
|
|
47
|
+
right: (theme) => MUGlobal.updateWithTheme(fabPadding, theme.spacing)
|
|
48
|
+
}, columnDirection: fabColumnDirection },
|
|
49
|
+
scrollContainer && (React.createElement(ScrollTopFab, { size: fabSize, target: scrollContainer, title: labels.scrollTop })),
|
|
50
|
+
fabButtons,
|
|
51
|
+
onRefresh != null && (React.createElement(Fab, { title: labels.refresh, size: fabSize, onClick: onRefresh, sx: { display: { xs: "none", md: "inherit" } } },
|
|
52
|
+
React.createElement(RefreshIcon, null))),
|
|
53
|
+
React.createElement(MoreFab, { size: fabSize, title: labels.more, actions: moreActions }),
|
|
54
|
+
supportBack && React.createElement(BackButton, { title: labels.back, size: fabSize })));
|
|
44
55
|
// Return the UI
|
|
45
56
|
return (React.createElement(React.Fragment, null,
|
|
46
57
|
update && (React.createElement(ReactAppStateDetector, { targetFields: targetFields, update: update })),
|
|
47
58
|
React.createElement(Container, { disableGutters: disableGutters, maxWidth: maxWidth, sx: sx, id: "page-container", ...rest },
|
|
48
|
-
React.createElement(
|
|
49
|
-
zIndex: 1,
|
|
50
|
-
bottom: (theme) => MUGlobal.updateWithTheme(fabPadding, theme.spacing),
|
|
51
|
-
right: (theme) => MUGlobal.updateWithTheme(fabPadding, theme.spacing)
|
|
52
|
-
}, columnDirection: fabColumnDirection },
|
|
53
|
-
scrollContainer && (React.createElement(ScrollTopFab, { size: fabSize, target: scrollContainer, title: labels.scrollTop })),
|
|
54
|
-
fabButtons,
|
|
55
|
-
onRefresh != null && (React.createElement(Fab, { title: labels.refresh, size: fabSize, onClick: onRefresh, sx: { display: { xs: 'none', md: 'inherit' } } },
|
|
56
|
-
React.createElement(RefreshIcon, null))),
|
|
57
|
-
React.createElement(MoreFab, { size: fabSize, title: labels.more, actions: moreActions }),
|
|
58
|
-
supportBack && (React.createElement(BackButton, { title: labels.back, size: fabSize }))),
|
|
59
|
+
fabPanel ? React.createElement(Paper, { sx: { padding: 2 } }, fab) : fab,
|
|
59
60
|
children)));
|
|
60
61
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { UserKey } from
|
|
3
|
-
import { IStateUpdate, ListItemReact } from
|
|
4
|
-
import { ContainerProps } from
|
|
5
|
-
import { CustomFabSize } from
|
|
2
|
+
import { UserKey } from "@etsoo/appscript";
|
|
3
|
+
import { IStateUpdate, ListItemReact } from "@etsoo/react";
|
|
4
|
+
import { ContainerProps } from "@mui/material";
|
|
5
|
+
import { CustomFabSize } from "../CustomFabProps";
|
|
6
6
|
/**
|
|
7
7
|
* Common page props
|
|
8
8
|
* Default container id is 'pageContainer'
|
|
9
9
|
*/
|
|
10
|
-
export interface CommonPageProps extends Omit<ContainerProps,
|
|
10
|
+
export interface CommonPageProps extends Omit<ContainerProps, "id"> {
|
|
11
11
|
/**
|
|
12
12
|
* Fab buttons
|
|
13
13
|
*/
|
|
@@ -24,6 +24,10 @@ export interface CommonPageProps extends Omit<ContainerProps, 'id'> {
|
|
|
24
24
|
* Fab padding adjust
|
|
25
25
|
*/
|
|
26
26
|
fabPaddingAdjust?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Add panel to the Fab
|
|
29
|
+
*/
|
|
30
|
+
fabPanel?: boolean;
|
|
27
31
|
/**
|
|
28
32
|
* More actions
|
|
29
33
|
*/
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { GridMethodRef } from
|
|
3
|
-
import { DataTypes, IdDefaultType } from
|
|
4
|
-
import { ListChildComponentProps } from
|
|
5
|
-
import { ScrollerListExInnerItemRendererProps, ScrollerListExItemSize } from
|
|
6
|
-
import { DataGridPageProps } from
|
|
2
|
+
import { GridMethodRef } from "@etsoo/react";
|
|
3
|
+
import { DataTypes, IdDefaultType } from "@etsoo/shared";
|
|
4
|
+
import { ListChildComponentProps } from "react-window";
|
|
5
|
+
import { ScrollerListExInnerItemRendererProps, ScrollerListExItemSize } from "../ScrollerListEx";
|
|
6
|
+
import { DataGridPageProps } from "./DataGridPageProps";
|
|
7
7
|
/**
|
|
8
8
|
* Response page props
|
|
9
9
|
*/
|
|
10
|
-
export type ResponsePageProps<T extends object, F extends DataTypes.BasicTemplate, D extends DataTypes.Keys<T> = IdDefaultType<T>> = Omit<DataGridPageProps<T, F, D>,
|
|
10
|
+
export type ResponsePageProps<T extends object, F extends DataTypes.BasicTemplate, D extends DataTypes.Keys<T> = IdDefaultType<T>> = Omit<DataGridPageProps<T, F, D>, "mRef" | "itemKey" | "onScroll" | "onItemsRendered"> & {
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param height Current height
|
|
14
|
+
* @param isGrid Is displaying DataGrid
|
|
15
|
+
* @returns Adjusted height
|
|
16
|
+
*/
|
|
17
|
+
adjustFabHeight?: (height: number, isGrid: boolean) => number;
|
|
11
18
|
/**
|
|
12
19
|
* Min width to show Datagrid
|
|
13
20
|
*/
|
package/package.json
CHANGED
package/src/FabBox.tsx
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { Box, BoxProps, useTheme } from
|
|
2
|
-
import React from
|
|
1
|
+
import { Box, BoxProps, useTheme } from "@mui/material";
|
|
2
|
+
import React from "react";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Fabs container box props
|
|
6
6
|
*/
|
|
7
7
|
export type FabBoxProps = BoxProps & {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Item gap
|
|
10
|
+
*/
|
|
11
|
+
itemGap?: number;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Flex direction, row or column
|
|
15
|
+
*/
|
|
16
|
+
columnDirection?: boolean;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -22,30 +22,31 @@ export type FabBoxProps = BoxProps & {
|
|
|
22
22
|
* @returns Component
|
|
23
23
|
*/
|
|
24
24
|
export function FabBox(props: FabBoxProps) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
25
|
+
// Destruct
|
|
26
|
+
const { columnDirection, itemGap = 1, sx, ...rest } = props;
|
|
27
|
+
|
|
28
|
+
// Theme
|
|
29
|
+
const theme = useTheme();
|
|
30
|
+
const spaceGap = theme.spacing(itemGap);
|
|
31
|
+
|
|
32
|
+
if (columnDirection == null) return <React.Fragment />;
|
|
33
|
+
|
|
34
|
+
// margin
|
|
35
|
+
const margin = columnDirection
|
|
36
|
+
? { marginTop: spaceGap }
|
|
37
|
+
: { marginLeft: spaceGap };
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<Box
|
|
41
|
+
sx={{
|
|
42
|
+
position: "fixed",
|
|
43
|
+
display: "flex",
|
|
44
|
+
alignItems: "center",
|
|
45
|
+
flexDirection: columnDirection ? "column" : "row",
|
|
46
|
+
"& > :not(style) + :not(style)": margin,
|
|
47
|
+
...sx
|
|
48
|
+
}}
|
|
49
|
+
{...rest}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
51
52
|
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { DataTypes } from "@etsoo/shared";
|
|
2
|
+
import { Button, ButtonProps, Menu, MenuItem, MenuProps } from "@mui/material";
|
|
3
|
+
import React from "react";
|
|
4
|
+
|
|
5
|
+
export type MenuButtonProps<T extends DataTypes.IdItem> = Omit<
|
|
6
|
+
MenuProps,
|
|
7
|
+
"open"
|
|
8
|
+
> & {
|
|
9
|
+
items: T[];
|
|
10
|
+
labelField: DataTypes.Keys<T, string>;
|
|
11
|
+
button:
|
|
12
|
+
| ((
|
|
13
|
+
clickHandler: React.MouseEventHandler<HTMLButtonElement>
|
|
14
|
+
) => React.ReactNode)
|
|
15
|
+
| ButtonProps;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export function MenuButton<T extends DataTypes.IdItem>(
|
|
19
|
+
props: MenuButtonProps<T>
|
|
20
|
+
) {
|
|
21
|
+
// Destruct
|
|
22
|
+
const {
|
|
23
|
+
button,
|
|
24
|
+
items,
|
|
25
|
+
labelField,
|
|
26
|
+
anchorOrigin = {
|
|
27
|
+
vertical: "top",
|
|
28
|
+
horizontal: "right"
|
|
29
|
+
},
|
|
30
|
+
transformOrigin = {
|
|
31
|
+
vertical:
|
|
32
|
+
anchorOrigin.vertical === "center"
|
|
33
|
+
? "center"
|
|
34
|
+
: anchorOrigin.vertical === "top"
|
|
35
|
+
? "bottom"
|
|
36
|
+
: "top",
|
|
37
|
+
horizontal: anchorOrigin.horizontal
|
|
38
|
+
},
|
|
39
|
+
sx,
|
|
40
|
+
...rest
|
|
41
|
+
} = props;
|
|
42
|
+
|
|
43
|
+
// Top?
|
|
44
|
+
const isTop = transformOrigin.vertical === "top";
|
|
45
|
+
|
|
46
|
+
// Menu anchor
|
|
47
|
+
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement>();
|
|
48
|
+
|
|
49
|
+
// Menu open or not
|
|
50
|
+
const isMenuOpen = Boolean(anchorEl);
|
|
51
|
+
|
|
52
|
+
const handleMenuOpen = (event: React.MouseEvent<HTMLButtonElement>) => {
|
|
53
|
+
setAnchorEl(event.currentTarget);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const handleMenuClose = () => {
|
|
57
|
+
setAnchorEl(undefined);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<React.Fragment>
|
|
62
|
+
{typeof button === "function" ? (
|
|
63
|
+
button(handleMenuOpen)
|
|
64
|
+
) : (
|
|
65
|
+
<Button onClick={handleMenuOpen} {...button} />
|
|
66
|
+
)}
|
|
67
|
+
|
|
68
|
+
<Menu
|
|
69
|
+
PaperProps={{
|
|
70
|
+
elevation: 0,
|
|
71
|
+
sx: {
|
|
72
|
+
overflow: "visible",
|
|
73
|
+
filter: "drop-shadow(0px 2px 8px rgba(0,0,0,0.32))",
|
|
74
|
+
"& .MuiAvatar-root": {
|
|
75
|
+
width: 32,
|
|
76
|
+
height: 32
|
|
77
|
+
},
|
|
78
|
+
"&:before": {
|
|
79
|
+
content: '""',
|
|
80
|
+
display: "block",
|
|
81
|
+
position: "absolute",
|
|
82
|
+
top: isTop ? 0 : undefined,
|
|
83
|
+
bottom: isTop ? undefined : -10,
|
|
84
|
+
right: 14,
|
|
85
|
+
width: 10,
|
|
86
|
+
height: 10,
|
|
87
|
+
bgcolor: "background.paper",
|
|
88
|
+
transform: "translateY(-50%) rotate(45deg)",
|
|
89
|
+
zIndex: 0
|
|
90
|
+
},
|
|
91
|
+
...{ sx }
|
|
92
|
+
}
|
|
93
|
+
}}
|
|
94
|
+
disableScrollLock
|
|
95
|
+
anchorEl={anchorEl}
|
|
96
|
+
anchorOrigin={anchorOrigin}
|
|
97
|
+
keepMounted
|
|
98
|
+
transformOrigin={transformOrigin}
|
|
99
|
+
open={isMenuOpen}
|
|
100
|
+
transitionDuration={0}
|
|
101
|
+
onClose={handleMenuClose}
|
|
102
|
+
{...rest}
|
|
103
|
+
>
|
|
104
|
+
{items.map((item) => {
|
|
105
|
+
const label = item[labelField] as string;
|
|
106
|
+
return (
|
|
107
|
+
<MenuItem key={item.id} disabled>
|
|
108
|
+
{label}
|
|
109
|
+
</MenuItem>
|
|
110
|
+
);
|
|
111
|
+
})}
|
|
112
|
+
</Menu>
|
|
113
|
+
</React.Fragment>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
@@ -45,6 +45,14 @@ export type ResponsibleContainerProps<
|
|
|
45
45
|
*/
|
|
46
46
|
adjustHeight?: (height: number, rect: DOMRect) => number;
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
* @param height Current height
|
|
51
|
+
* @param isGrid Is displaying DataGrid
|
|
52
|
+
* @returns Adjusted height
|
|
53
|
+
*/
|
|
54
|
+
adjustFabHeight?: (height: number, isGrid: boolean) => number;
|
|
55
|
+
|
|
48
56
|
/**
|
|
49
57
|
* Columns
|
|
50
58
|
*/
|
|
@@ -171,6 +179,7 @@ export function ResponsibleContainer<
|
|
|
171
179
|
// Destruct
|
|
172
180
|
const {
|
|
173
181
|
adjustHeight,
|
|
182
|
+
adjustFabHeight,
|
|
174
183
|
columns,
|
|
175
184
|
containerBoxSx = defaultContainerBoxSx,
|
|
176
185
|
dataGridMinWidth = Math.max(576, DataGridExCalColumns(columns).total),
|
|
@@ -281,6 +290,9 @@ export function ResponsibleContainer<
|
|
|
281
290
|
if (adjustHeight != null) heightLocal -= adjustHeight(heightLocal, rect);
|
|
282
291
|
}
|
|
283
292
|
|
|
293
|
+
if (adjustFabHeight)
|
|
294
|
+
heightLocal = adjustFabHeight(heightLocal, showDataGrid);
|
|
295
|
+
|
|
284
296
|
if (showDataGrid) {
|
|
285
297
|
// Delete
|
|
286
298
|
delete rest.itemRenderer;
|
package/src/index.ts
CHANGED
|
@@ -64,6 +64,7 @@ export * from "./ListItemRightIcon";
|
|
|
64
64
|
export * from "./ListMoreDisplay";
|
|
65
65
|
export * from "./LoadingButton";
|
|
66
66
|
export * from "./MaskInput";
|
|
67
|
+
export * from "./MenuButton";
|
|
67
68
|
export * from "./MobileListItemRenderer";
|
|
68
69
|
export * from "./MoneyInputField";
|
|
69
70
|
export * from "./MoreFab";
|
package/src/pages/CommonPage.tsx
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { FabBox } from
|
|
3
|
-
import { ScrollTopFab } from
|
|
4
|
-
import { MUGlobal } from
|
|
5
|
-
import { CommonPageProps } from
|
|
6
|
-
import { MoreFab } from
|
|
7
|
-
import { Container, Fab } from
|
|
8
|
-
import RefreshIcon from
|
|
9
|
-
import { BackButton } from
|
|
10
|
-
import { Labels } from
|
|
11
|
-
import { ReactAppStateDetector } from
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { FabBox } from "../FabBox";
|
|
3
|
+
import { ScrollTopFab } from "../ScrollTopFab";
|
|
4
|
+
import { MUGlobal } from "../MUGlobal";
|
|
5
|
+
import { CommonPageProps } from "./CommonPageProps";
|
|
6
|
+
import { MoreFab } from "../MoreFab";
|
|
7
|
+
import { Container, Fab, Paper } from "@mui/material";
|
|
8
|
+
import RefreshIcon from "@mui/icons-material/Refresh";
|
|
9
|
+
import { BackButton } from "../BackButton";
|
|
10
|
+
import { Labels } from "../app/Labels";
|
|
11
|
+
import { ReactAppStateDetector } from "../app/ReactApp";
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Default scroll container
|
|
@@ -20,109 +20,100 @@ export const CommonPageScrollContainer = global;
|
|
|
20
20
|
* @param props Props
|
|
21
21
|
*/
|
|
22
22
|
export function CommonPage(props: CommonPageProps) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
23
|
+
// Destruct
|
|
24
|
+
const {
|
|
25
|
+
children,
|
|
26
|
+
disableGutters = true,
|
|
27
|
+
fabButtons,
|
|
28
|
+
fabColumnDirection,
|
|
29
|
+
fabPanel = fabColumnDirection,
|
|
30
|
+
fabPaddingAdjust = 1.5,
|
|
31
|
+
fabSize = "small",
|
|
32
|
+
maxWidth = false,
|
|
33
|
+
moreActions,
|
|
34
|
+
onRefresh,
|
|
35
|
+
onUpdate,
|
|
36
|
+
onUpdateAll,
|
|
37
|
+
paddings = MUGlobal.pagePaddings,
|
|
38
|
+
scrollContainer,
|
|
39
|
+
supportBack = false,
|
|
40
|
+
targetFields,
|
|
41
|
+
sx = {},
|
|
42
|
+
...rest
|
|
43
|
+
} = props;
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
MUGlobal.pagePaddings,
|
|
47
|
-
fabPaddingAdjust
|
|
48
|
-
);
|
|
45
|
+
// Fab padding
|
|
46
|
+
const fabPadding = MUGlobal.increase(MUGlobal.pagePaddings, fabPaddingAdjust);
|
|
49
47
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
if (typeof sx === "object" && sx != null && !Reflect.has(sx, "padding")) {
|
|
49
|
+
// Set default padding
|
|
50
|
+
Reflect.set(sx, "padding", paddings);
|
|
51
|
+
}
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
// Labels
|
|
54
|
+
const labels = Labels.CommonPage;
|
|
57
55
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
56
|
+
// Update
|
|
57
|
+
const update = onUpdateAll
|
|
58
|
+
? onUpdateAll
|
|
59
|
+
: onUpdate
|
|
60
|
+
? (authorized?: boolean) => {
|
|
61
|
+
if (authorized == null || authorized) onUpdate();
|
|
62
|
+
}
|
|
63
|
+
: onRefresh
|
|
64
|
+
? (authorized?: boolean) => {
|
|
65
|
+
if (authorized) onRefresh();
|
|
66
|
+
}
|
|
67
|
+
: undefined;
|
|
70
68
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
<BackButton title={labels.back} size={fabSize} />
|
|
122
|
-
)}
|
|
123
|
-
</FabBox>
|
|
124
|
-
{children}
|
|
125
|
-
</Container>
|
|
126
|
-
</React.Fragment>
|
|
127
|
-
);
|
|
69
|
+
const fab = (
|
|
70
|
+
<FabBox
|
|
71
|
+
sx={{
|
|
72
|
+
zIndex: 1,
|
|
73
|
+
bottom: (theme) => MUGlobal.updateWithTheme(fabPadding, theme.spacing),
|
|
74
|
+
right: (theme) => MUGlobal.updateWithTheme(fabPadding, theme.spacing)
|
|
75
|
+
}}
|
|
76
|
+
columnDirection={fabColumnDirection}
|
|
77
|
+
>
|
|
78
|
+
{scrollContainer && (
|
|
79
|
+
<ScrollTopFab
|
|
80
|
+
size={fabSize}
|
|
81
|
+
target={scrollContainer}
|
|
82
|
+
title={labels.scrollTop}
|
|
83
|
+
/>
|
|
84
|
+
)}
|
|
85
|
+
{fabButtons}
|
|
86
|
+
{onRefresh != null && (
|
|
87
|
+
<Fab
|
|
88
|
+
title={labels.refresh}
|
|
89
|
+
size={fabSize}
|
|
90
|
+
onClick={onRefresh}
|
|
91
|
+
sx={{ display: { xs: "none", md: "inherit" } }}
|
|
92
|
+
>
|
|
93
|
+
<RefreshIcon />
|
|
94
|
+
</Fab>
|
|
95
|
+
)}
|
|
96
|
+
<MoreFab size={fabSize} title={labels.more} actions={moreActions} />
|
|
97
|
+
{supportBack && <BackButton title={labels.back} size={fabSize} />}
|
|
98
|
+
</FabBox>
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// Return the UI
|
|
102
|
+
return (
|
|
103
|
+
<React.Fragment>
|
|
104
|
+
{update && (
|
|
105
|
+
<ReactAppStateDetector targetFields={targetFields} update={update} />
|
|
106
|
+
)}
|
|
107
|
+
<Container
|
|
108
|
+
disableGutters={disableGutters}
|
|
109
|
+
maxWidth={maxWidth}
|
|
110
|
+
sx={sx}
|
|
111
|
+
id="page-container"
|
|
112
|
+
{...rest}
|
|
113
|
+
>
|
|
114
|
+
{fabPanel ? <Paper sx={{ padding: 2 }}>{fab}</Paper> : fab}
|
|
115
|
+
{children}
|
|
116
|
+
</Container>
|
|
117
|
+
</React.Fragment>
|
|
118
|
+
);
|
|
128
119
|
}
|
|
@@ -1,70 +1,75 @@
|
|
|
1
|
-
import { UserKey } from
|
|
2
|
-
import { IStateUpdate, ListItemReact } from
|
|
3
|
-
import { ContainerProps } from
|
|
4
|
-
import { CustomFabSize } from
|
|
1
|
+
import { UserKey } from "@etsoo/appscript";
|
|
2
|
+
import { IStateUpdate, ListItemReact } from "@etsoo/react";
|
|
3
|
+
import { ContainerProps } from "@mui/material";
|
|
4
|
+
import { CustomFabSize } from "../CustomFabProps";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Common page props
|
|
8
8
|
* Default container id is 'pageContainer'
|
|
9
9
|
*/
|
|
10
|
-
export interface CommonPageProps extends Omit<ContainerProps,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
export interface CommonPageProps extends Omit<ContainerProps, "id"> {
|
|
11
|
+
/**
|
|
12
|
+
* Fab buttons
|
|
13
|
+
*/
|
|
14
|
+
fabButtons?: React.ReactNode;
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Fab size
|
|
18
|
+
*/
|
|
19
|
+
fabSize?: CustomFabSize;
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Fab flex column direction, undefined to hide it
|
|
23
|
+
*/
|
|
24
|
+
fabColumnDirection?: boolean;
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Fab padding adjust
|
|
28
|
+
*/
|
|
29
|
+
fabPaddingAdjust?: number;
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Add panel to the Fab
|
|
33
|
+
*/
|
|
34
|
+
fabPanel?: boolean;
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
/**
|
|
37
|
+
* More actions
|
|
38
|
+
*/
|
|
39
|
+
moreActions?: ListItemReact[];
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
/**
|
|
42
|
+
* On refresh callback, only when authorized = true
|
|
43
|
+
*/
|
|
44
|
+
onRefresh?: () => void | PromiseLike<void>;
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
/**
|
|
47
|
+
* On page update, when authorized = null or true case, may uses onRefresh
|
|
48
|
+
*/
|
|
49
|
+
onUpdate?: () => void | PromiseLike<void>;
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
/**
|
|
52
|
+
* On page update, all cases with authorized
|
|
53
|
+
*/
|
|
54
|
+
onUpdateAll?: IStateUpdate;
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Paddings
|
|
58
|
+
*/
|
|
59
|
+
paddings?: Record<string, string | number>;
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Scroll container
|
|
63
|
+
*/
|
|
64
|
+
scrollContainer?: HTMLElement | object;
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Support back click
|
|
68
|
+
*/
|
|
69
|
+
supportBack?: boolean;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* State last changed fields
|
|
73
|
+
*/
|
|
74
|
+
targetFields?: UserKey[];
|
|
70
75
|
}
|
|
@@ -1,57 +1,65 @@
|
|
|
1
|
-
import { GridMethodRef } from
|
|
2
|
-
import { DataTypes, IdDefaultType } from
|
|
3
|
-
import { ListChildComponentProps } from
|
|
1
|
+
import { GridMethodRef } from "@etsoo/react";
|
|
2
|
+
import { DataTypes, IdDefaultType } from "@etsoo/shared";
|
|
3
|
+
import { ListChildComponentProps } from "react-window";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from
|
|
8
|
-
import { DataGridPageProps } from
|
|
5
|
+
ScrollerListExInnerItemRendererProps,
|
|
6
|
+
ScrollerListExItemSize
|
|
7
|
+
} from "../ScrollerListEx";
|
|
8
|
+
import { DataGridPageProps } from "./DataGridPageProps";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Response page props
|
|
12
12
|
*/
|
|
13
13
|
export type ResponsePageProps<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
T extends object,
|
|
15
|
+
F extends DataTypes.BasicTemplate,
|
|
16
|
+
D extends DataTypes.Keys<T> = IdDefaultType<T>
|
|
17
17
|
> = Omit<
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
DataGridPageProps<T, F, D>,
|
|
19
|
+
"mRef" | "itemKey" | "onScroll" | "onItemsRendered"
|
|
20
20
|
> & {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* @param height Current height
|
|
24
|
+
* @param isGrid Is displaying DataGrid
|
|
25
|
+
* @returns Adjusted height
|
|
26
|
+
*/
|
|
27
|
+
adjustFabHeight?: (height: number, isGrid: boolean) => number;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Min width to show Datagrid
|
|
31
|
+
*/
|
|
32
|
+
dataGridMinWidth?: number;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Inner item renderer
|
|
36
|
+
*/
|
|
37
|
+
innerItemRenderer: (
|
|
38
|
+
props: ScrollerListExInnerItemRendererProps<T>
|
|
39
|
+
) => React.ReactNode;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Item renderer
|
|
43
|
+
*/
|
|
44
|
+
itemRenderer?: (props: ListChildComponentProps<T>) => React.ReactElement;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Item size, a function indicates its a variable size list
|
|
48
|
+
*/
|
|
49
|
+
itemSize: ScrollerListExItemSize;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Methods
|
|
53
|
+
*/
|
|
54
|
+
mRef?: React.MutableRefObject<GridMethodRef<T> | undefined>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Pull to refresh data
|
|
58
|
+
*/
|
|
59
|
+
pullToRefresh?: boolean;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Quick action for double click or click under mobile
|
|
63
|
+
*/
|
|
64
|
+
quickAction?: (data: T) => void;
|
|
57
65
|
};
|