@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 CHANGED
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- import { BoxProps } from '@mui/material';
2
+ import { BoxProps } from "@mui/material";
3
3
  /**
4
4
  * Fabs container box props
5
5
  */
package/lib/FabBox.js CHANGED
@@ -1,5 +1,5 @@
1
- import { Box, useTheme } from '@mui/material';
2
- import React from 'react';
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 = {}, ...rest } = props;
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
- // Default style
21
- if (typeof sx === 'object') {
22
- Object.assign(sx, {
23
- position: 'fixed',
24
- display: 'flex',
25
- alignItems: 'center',
26
- flexDirection: columnDirection ? 'column' : 'row',
27
- '& > :not(style) + :not(style)': margin
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";
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- import { CommonPageProps } from './CommonPageProps';
2
+ import { CommonPageProps } from "./CommonPageProps";
3
3
  /**
4
4
  * Default scroll container
5
5
  */
@@ -1,13 +1,13 @@
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 } 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';
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 = 'small', maxWidth = false, moreActions, onRefresh, onUpdate, onUpdateAll, paddings = MUGlobal.pagePaddings, scrollContainer, supportBack = false, targetFields, sx = {}, ...rest } = props;
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 === 'object' && sx != null && !Reflect.has(sx, 'padding')) {
24
+ if (typeof sx === "object" && sx != null && !Reflect.has(sx, "padding")) {
25
25
  // Set default padding
26
- Reflect.set(sx, 'padding', paddings);
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(FabBox, { sx: {
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 '@etsoo/appscript';
3
- import { IStateUpdate, ListItemReact } from '@etsoo/react';
4
- import { ContainerProps } from '@mui/material';
5
- import { CustomFabSize } from '../CustomFabProps';
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, 'id'> {
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 '@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';
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>, 'mRef' | 'itemKey' | 'onScroll' | 'onItemsRendered'> & {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.1.96",
3
+ "version": "1.1.98",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
package/src/FabBox.tsx CHANGED
@@ -1,19 +1,19 @@
1
- import { Box, BoxProps, useTheme } from '@mui/material';
2
- import React from 'react';
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
- * Item gap
10
- */
11
- itemGap?: number;
12
-
13
- /**
14
- * Flex direction, row or column
15
- */
16
- columnDirection?: boolean;
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
- // 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
- // Default style
40
- if (typeof sx === 'object') {
41
- Object.assign(sx as any, {
42
- position: 'fixed',
43
- display: 'flex',
44
- alignItems: 'center',
45
- flexDirection: columnDirection ? 'column' : 'row',
46
- '& > :not(style) + :not(style)': margin
47
- });
48
- }
49
-
50
- return <Box sx={sx} {...rest} />;
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";
@@ -1,14 +1,14 @@
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 } 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';
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
- // Destruct
24
- const {
25
- children,
26
- disableGutters = true,
27
- fabButtons,
28
- fabColumnDirection,
29
- fabPaddingAdjust = 1.5,
30
- fabSize = 'small',
31
- maxWidth = false,
32
- moreActions,
33
- onRefresh,
34
- onUpdate,
35
- onUpdateAll,
36
- paddings = MUGlobal.pagePaddings,
37
- scrollContainer,
38
- supportBack = false,
39
- targetFields,
40
- sx = {},
41
- ...rest
42
- } = props;
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
- // Fab padding
45
- const fabPadding = MUGlobal.increase(
46
- MUGlobal.pagePaddings,
47
- fabPaddingAdjust
48
- );
45
+ // Fab padding
46
+ const fabPadding = MUGlobal.increase(MUGlobal.pagePaddings, fabPaddingAdjust);
49
47
 
50
- if (typeof sx === 'object' && sx != null && !Reflect.has(sx, 'padding')) {
51
- // Set default padding
52
- Reflect.set(sx, 'padding', paddings);
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
- // Labels
56
- const labels = Labels.CommonPage;
53
+ // Labels
54
+ const labels = Labels.CommonPage;
57
55
 
58
- // Update
59
- const update = onUpdateAll
60
- ? onUpdateAll
61
- : onUpdate
62
- ? (authorized?: boolean) => {
63
- if (authorized == null || authorized) onUpdate();
64
- }
65
- : onRefresh
66
- ? (authorized?: boolean) => {
67
- if (authorized) onRefresh();
68
- }
69
- : undefined;
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
- // Return the UI
72
- return (
73
- <React.Fragment>
74
- {update && (
75
- <ReactAppStateDetector
76
- targetFields={targetFields}
77
- update={update}
78
- />
79
- )}
80
- <Container
81
- disableGutters={disableGutters}
82
- maxWidth={maxWidth}
83
- sx={sx}
84
- id="page-container"
85
- {...rest}
86
- >
87
- <FabBox
88
- sx={{
89
- zIndex: 1,
90
- bottom: (theme) =>
91
- MUGlobal.updateWithTheme(fabPadding, theme.spacing),
92
- right: (theme) =>
93
- MUGlobal.updateWithTheme(fabPadding, theme.spacing)
94
- }}
95
- columnDirection={fabColumnDirection}
96
- >
97
- {scrollContainer && (
98
- <ScrollTopFab
99
- size={fabSize}
100
- target={scrollContainer}
101
- title={labels.scrollTop}
102
- />
103
- )}
104
- {fabButtons}
105
- {onRefresh != null && (
106
- <Fab
107
- title={labels.refresh}
108
- size={fabSize}
109
- onClick={onRefresh}
110
- sx={{ display: { xs: 'none', md: 'inherit' } }}
111
- >
112
- <RefreshIcon />
113
- </Fab>
114
- )}
115
- <MoreFab
116
- size={fabSize}
117
- title={labels.more}
118
- actions={moreActions}
119
- />
120
- {supportBack && (
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 '@etsoo/appscript';
2
- import { IStateUpdate, ListItemReact } from '@etsoo/react';
3
- import { ContainerProps } from '@mui/material';
4
- import { CustomFabSize } from '../CustomFabProps';
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, 'id'> {
11
- /**
12
- * Fab buttons
13
- */
14
- fabButtons?: React.ReactNode;
10
+ export interface CommonPageProps extends Omit<ContainerProps, "id"> {
11
+ /**
12
+ * Fab buttons
13
+ */
14
+ fabButtons?: React.ReactNode;
15
15
 
16
- /**
17
- * Fab size
18
- */
19
- fabSize?: CustomFabSize;
16
+ /**
17
+ * Fab size
18
+ */
19
+ fabSize?: CustomFabSize;
20
20
 
21
- /**
22
- * Fab flex column direction, undefined to hide it
23
- */
24
- fabColumnDirection?: boolean;
21
+ /**
22
+ * Fab flex column direction, undefined to hide it
23
+ */
24
+ fabColumnDirection?: boolean;
25
25
 
26
- /**
27
- * Fab padding adjust
28
- */
29
- fabPaddingAdjust?: number;
26
+ /**
27
+ * Fab padding adjust
28
+ */
29
+ fabPaddingAdjust?: number;
30
30
 
31
- /**
32
- * More actions
33
- */
34
- moreActions?: ListItemReact[];
31
+ /**
32
+ * Add panel to the Fab
33
+ */
34
+ fabPanel?: boolean;
35
35
 
36
- /**
37
- * On refresh callback, only when authorized = true
38
- */
39
- onRefresh?: () => void | PromiseLike<void>;
36
+ /**
37
+ * More actions
38
+ */
39
+ moreActions?: ListItemReact[];
40
40
 
41
- /**
42
- * On page update, when authorized = null or true case, may uses onRefresh
43
- */
44
- onUpdate?: () => void | PromiseLike<void>;
41
+ /**
42
+ * On refresh callback, only when authorized = true
43
+ */
44
+ onRefresh?: () => void | PromiseLike<void>;
45
45
 
46
- /**
47
- * On page update, all cases with authorized
48
- */
49
- onUpdateAll?: IStateUpdate;
46
+ /**
47
+ * On page update, when authorized = null or true case, may uses onRefresh
48
+ */
49
+ onUpdate?: () => void | PromiseLike<void>;
50
50
 
51
- /**
52
- * Paddings
53
- */
54
- paddings?: Record<string, string | number>;
51
+ /**
52
+ * On page update, all cases with authorized
53
+ */
54
+ onUpdateAll?: IStateUpdate;
55
55
 
56
- /**
57
- * Scroll container
58
- */
59
- scrollContainer?: HTMLElement | object;
56
+ /**
57
+ * Paddings
58
+ */
59
+ paddings?: Record<string, string | number>;
60
60
 
61
- /**
62
- * Support back click
63
- */
64
- supportBack?: boolean;
61
+ /**
62
+ * Scroll container
63
+ */
64
+ scrollContainer?: HTMLElement | object;
65
65
 
66
- /**
67
- * State last changed fields
68
- */
69
- targetFields?: UserKey[];
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 '@etsoo/react';
2
- import { DataTypes, IdDefaultType } from '@etsoo/shared';
3
- import { ListChildComponentProps } from 'react-window';
1
+ import { GridMethodRef } from "@etsoo/react";
2
+ import { DataTypes, IdDefaultType } from "@etsoo/shared";
3
+ import { ListChildComponentProps } from "react-window";
4
4
  import {
5
- ScrollerListExInnerItemRendererProps,
6
- ScrollerListExItemSize
7
- } from '../ScrollerListEx';
8
- import { DataGridPageProps } from './DataGridPageProps';
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
- T extends object,
15
- F extends DataTypes.BasicTemplate,
16
- D extends DataTypes.Keys<T> = IdDefaultType<T>
14
+ T extends object,
15
+ F extends DataTypes.BasicTemplate,
16
+ D extends DataTypes.Keys<T> = IdDefaultType<T>
17
17
  > = Omit<
18
- DataGridPageProps<T, F, D>,
19
- 'mRef' | 'itemKey' | 'onScroll' | 'onItemsRendered'
18
+ DataGridPageProps<T, F, D>,
19
+ "mRef" | "itemKey" | "onScroll" | "onItemsRendered"
20
20
  > & {
21
- /**
22
- * Min width to show Datagrid
23
- */
24
- dataGridMinWidth?: number;
25
-
26
- /**
27
- * Inner item renderer
28
- */
29
- innerItemRenderer: (
30
- props: ScrollerListExInnerItemRendererProps<T>
31
- ) => React.ReactNode;
32
-
33
- /**
34
- * Item renderer
35
- */
36
- itemRenderer?: (props: ListChildComponentProps<T>) => React.ReactElement;
37
-
38
- /**
39
- * Item size, a function indicates its a variable size list
40
- */
41
- itemSize: ScrollerListExItemSize;
42
-
43
- /**
44
- * Methods
45
- */
46
- mRef?: React.MutableRefObject<GridMethodRef<T> | undefined>;
47
-
48
- /**
49
- * Pull to refresh data
50
- */
51
- pullToRefresh?: boolean;
52
-
53
- /**
54
- * Quick action for double click or click under mobile
55
- */
56
- quickAction?: (data: T) => void;
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
  };