@etsoo/react 1.5.9 → 1.5.13

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.
@@ -8,6 +8,7 @@ export declare namespace Labels {
8
8
  */
9
9
  const CommonPage: {
10
10
  add: string;
11
+ back: string;
11
12
  delete: string;
12
13
  more: string;
13
14
  pullToRefresh: string;
package/lib/app/Labels.js CHANGED
@@ -9,6 +9,7 @@ export var Labels;
9
9
  */
10
10
  Labels.CommonPage = {
11
11
  add: 'Add',
12
+ back: 'Back',
12
13
  delete: 'Delete',
13
14
  more: 'More',
14
15
  pullToRefresh: 'Pull down to refresh',
@@ -108,6 +108,19 @@ export declare class ReactApp<S extends IAppSettings, D extends IUser, P extends
108
108
  * @param name Application name
109
109
  */
110
110
  constructor(settings: S, name: string);
111
+ /**
112
+ * Get parsed Url under bridge host
113
+ * @param url Url
114
+ * @returns Parsed Url
115
+ */
116
+ protected getHostUrl(url: string): string;
117
+ /**
118
+ * Get parsed Url under bridge host
119
+ * @param url Url
120
+ * @param name App name in the host environment
121
+ * @returns Parsed Url
122
+ */
123
+ protected getHostUrlBase(url: string, name: string): string;
111
124
  /**
112
125
  * Override alert action result
113
126
  * @param result Action result
@@ -26,8 +26,8 @@ export function ReactAppStateDetector(props) {
26
26
  // Destruct
27
27
  const { targetFields, update } = props;
28
28
  // Context
29
- const { state } = globalApp == null
30
- ? { state: {} }
29
+ const { state = {} } = globalApp == null
30
+ ? {}
31
31
  : React.useContext(globalApp.userState.context);
32
32
  // Ready
33
33
  React.useEffect(() => {
@@ -67,7 +67,7 @@ export class ReactApp extends CoreApp {
67
67
  this.userState = new UserState();
68
68
  this.history =
69
69
  window.location.hostname === ''
70
- ? Utils.getMemoryHistory()
70
+ ? Utils.getMemoryHistory(this.getHostUrl(window.location.href))
71
71
  : undefined;
72
72
  this.cultureState = new CultureState(settings.currentCulture);
73
73
  this.pageState = new PageState();
@@ -91,6 +91,31 @@ export class ReactApp extends CoreApp {
91
91
  ReactApp._notifierProvider = NotifierMU.setup();
92
92
  return NotifierMU.instance;
93
93
  }
94
+ /**
95
+ * Get parsed Url under bridge host
96
+ * @param url Url
97
+ * @returns Parsed Url
98
+ */
99
+ getHostUrl(url) {
100
+ return this.getHostUrlBase(url, 'core');
101
+ }
102
+ /**
103
+ * Get parsed Url under bridge host
104
+ * @param url Url
105
+ * @param name App name in the host environment
106
+ * @returns Parsed Url
107
+ */
108
+ getHostUrlBase(url, name) {
109
+ if (url.startsWith('/'))
110
+ return url;
111
+ const identifier = `/${name}/`;
112
+ const pos = url.indexOf(identifier);
113
+ if (pos === -1)
114
+ return '/';
115
+ return url
116
+ .substring(pos + identifier.length - 1)
117
+ .replace('/index.html', '/'); // Router take / as start
118
+ }
94
119
  /**
95
120
  * Override alert action result
96
121
  * @param result Action result
@@ -32,6 +32,12 @@ export declare class ServiceApp<U extends IServiceUser = IServiceUser, P extends
32
32
  * @param name Application name
33
33
  */
34
34
  constructor(settings: S, name: string);
35
+ /**
36
+ * Get parsed Url under bridge host
37
+ * @param url Url
38
+ * @returns Parsed Url
39
+ */
40
+ protected getHostUrl(url: string): string;
35
41
  /**
36
42
  * Go to the login page
37
43
  * @param tryLogin Try to login again
@@ -39,6 +39,14 @@ export class ServiceApp extends ReactApp {
39
39
  set serviceUser(value) {
40
40
  this._serviceUser = value;
41
41
  }
42
+ /**
43
+ * Get parsed Url under bridge host
44
+ * @param url Url
45
+ * @returns Parsed Url
46
+ */
47
+ getHostUrl(url) {
48
+ return this.getHostUrlBase(url, 's' + this.settings.serviceId);
49
+ }
42
50
  /**
43
51
  * Go to the login page
44
52
  * @param tryLogin Try to login again
@@ -12,9 +12,10 @@ export declare namespace Utils {
12
12
  function formatInputValue(value: unknown): string | number | any[] | undefined;
13
13
  /**
14
14
  * Get memory history
15
+ * @param initialPath Initial path
15
16
  * @returns History
16
17
  */
17
- function getMemoryHistory(): History;
18
+ function getMemoryHistory(initialPath?: string): History;
18
19
  /**
19
20
  * Is safe click
20
21
  * @param event Mouse event
package/lib/app/Utils.js CHANGED
@@ -26,11 +26,12 @@ export var Utils;
26
26
  Utils.formatInputValue = formatInputValue;
27
27
  /**
28
28
  * Get memory history
29
+ * @param initialPath Initial path
29
30
  * @returns History
30
31
  */
31
- function getMemoryHistory() {
32
+ function getMemoryHistory(initialPath = '/') {
32
33
  if (memoryHistory == null) {
33
- memoryHistory = createHistory(createMemorySource('/'));
34
+ memoryHistory = createHistory(createMemorySource(initialPath));
34
35
  }
35
36
  return memoryHistory;
36
37
  }
package/lib/index.d.ts CHANGED
@@ -31,6 +31,7 @@ export * from './mu/texts/DateText';
31
31
  export * from './mu/texts/MoneyText';
32
32
  export * from './mu/texts/NumberText';
33
33
  export * from './mu/AuditDisplay';
34
+ export * from './mu/BackButton';
34
35
  export * from './mu/BridgeCloseButton';
35
36
  export * from './mu/ButtonLink';
36
37
  export * from './mu/ComboBox';
package/lib/index.js CHANGED
@@ -34,6 +34,7 @@ export * from './mu/texts/DateText';
34
34
  export * from './mu/texts/MoneyText';
35
35
  export * from './mu/texts/NumberText';
36
36
  export * from './mu/AuditDisplay';
37
+ export * from './mu/BackButton';
37
38
  export * from './mu/BridgeCloseButton';
38
39
  export * from './mu/ButtonLink';
39
40
  export * from './mu/ComboBox';
@@ -0,0 +1,13 @@
1
+ /// <reference types="react" />
2
+ import { IconButtonProps } from '@mui/material';
3
+ /**
4
+ * BackButton props
5
+ */
6
+ export interface BackButtonProps extends IconButtonProps {
7
+ }
8
+ /**
9
+ * BackButton
10
+ * @param props Props
11
+ * @returns Component
12
+ */
13
+ export declare function BackButton(props: BackButtonProps): JSX.Element;
@@ -0,0 +1,29 @@
1
+ import { IconButton } from '@mui/material';
2
+ import ArrowBackIcon from '@mui/icons-material/ArrowBack';
3
+ import React from 'react';
4
+ import { useNavigate } from '@reach/router';
5
+ /**
6
+ * BackButton
7
+ * @param props Props
8
+ * @returns Component
9
+ */
10
+ export function BackButton(props) {
11
+ // Destruct
12
+ const { color = 'primary', size = 'small', onClick, ...rest } = props;
13
+ // Navigate
14
+ const navigate = useNavigate();
15
+ // Click handler
16
+ const onClickLocal = (event) => {
17
+ if (onClick)
18
+ onClick(event);
19
+ navigate(-1);
20
+ };
21
+ return (React.createElement(IconButton, { "aria-label": "Back", color: color, size: size, onClick: onClickLocal, sx: {
22
+ border: (theme) => `1px solid ${(() => color != 'inherit' &&
23
+ color != 'default' &&
24
+ color in theme.palette
25
+ ? theme.palette[color]
26
+ : theme.palette.primary)().light}`
27
+ }, ...rest },
28
+ React.createElement(ArrowBackIcon, null)));
29
+ }
@@ -1,10 +1,14 @@
1
1
  /// <reference types="react" />
2
2
  import { IBridgeHost } from '@etsoo/appscript';
3
- import { IconButtonProps } from '@mui/material';
3
+ import { BoxProps, IconButtonProps } from '@mui/material';
4
4
  /**
5
5
  * Bridge close button props
6
6
  */
7
7
  export interface BridgeCloseButtonProps extends IconButtonProps {
8
+ /**
9
+ * Box props
10
+ */
11
+ boxProps?: BoxProps;
8
12
  /**
9
13
  * Validate the host
10
14
  * @param host Host
@@ -1,6 +1,6 @@
1
1
  import { BridgeUtils } from '@etsoo/appscript';
2
2
  import CloseIcon from '@mui/icons-material/Close';
3
- import { IconButton } from '@mui/material';
3
+ import { Box, IconButton } from '@mui/material';
4
4
  import React from 'react';
5
5
  import { globalApp } from '../app/ReactApp';
6
6
  /**
@@ -10,7 +10,7 @@ import { globalApp } from '../app/ReactApp';
10
10
  */
11
11
  export function BridgeCloseButton(props) {
12
12
  // Destruct
13
- const { onClick, title = typeof globalApp === 'undefined'
13
+ const { boxProps, onClick, title = typeof globalApp === 'undefined'
14
14
  ? 'Close'
15
15
  : globalApp.get('close'), validate, ...rest } = props;
16
16
  // Host
@@ -24,11 +24,7 @@ export function BridgeCloseButton(props) {
24
24
  onClick(event);
25
25
  host.exit();
26
26
  };
27
- return (React.createElement(IconButton, { "aria-label": "close", color: "secondary", onClick: onClickLocal, title: title, sx: {
28
- position: 'absolute',
29
- zIndex: (theme) => theme.zIndex.appBar + 1,
30
- top: (theme) => theme.spacing(0.5),
31
- right: (theme) => theme.spacing(0.5)
32
- }, ...rest },
33
- React.createElement(CloseIcon, null)));
27
+ return (React.createElement(Box, { ...boxProps },
28
+ React.createElement(IconButton, { "aria-label": "close", onClick: onClickLocal, title: title, ...rest },
29
+ React.createElement(CloseIcon, null))));
34
30
  }
@@ -7,6 +7,7 @@ import { MoreFab } from '../MoreFab';
7
7
  import { ReactAppStateDetector } from '../../app/ReactApp';
8
8
  import { Container, Fab } from '@mui/material';
9
9
  import RefreshIcon from '@mui/icons-material/Refresh';
10
+ import { BackButton } from '../BackButton';
10
11
  /**
11
12
  * Default scroll container
12
13
  */
@@ -17,7 +18,7 @@ export const CommonPageScrollContainer = global;
17
18
  */
18
19
  export function CommonPage(props) {
19
20
  // Destruct
20
- const { children, disableGutters = true, fabButtons, fabColumnDirection, fabPaddingAdjust = 1.5, fabSize = 'small', maxWidth = false, moreActions, onRefresh, onUpdate, onUpdateAll, paddings = MUGlobal.pagePaddings, scrollContainer, targetFields, sx = {}, ...rest } = props;
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
22
  // Merge style
22
23
  Object.assign(sx, {
23
24
  padding: paddings
@@ -53,6 +54,7 @@ export function CommonPage(props) {
53
54
  fabButtons,
54
55
  onRefresh != null && (React.createElement(Fab, { title: labels.refresh, size: fabSize, onClick: onRefresh, sx: { display: { xs: 'none', md: 'inherit' } } },
55
56
  React.createElement(RefreshIcon, null))),
56
- React.createElement(MoreFab, { size: fabSize, title: labels.more, actions: moreActions })),
57
+ React.createElement(MoreFab, { size: fabSize, title: labels.more, actions: moreActions }),
58
+ supportBack && (React.createElement(BackButton, { title: labels.back, size: fabSize }))),
57
59
  children)));
58
60
  }
@@ -18,7 +18,7 @@ export interface CommonPageProps extends Omit<ContainerProps, 'id'> {
18
18
  */
19
19
  fabSize?: CustomFabSize;
20
20
  /**
21
- * Fab flex column direction?
21
+ * Fab flex column direction, undefined to hide it
22
22
  */
23
23
  fabColumnDirection?: boolean;
24
24
  /**
@@ -49,6 +49,10 @@ export interface CommonPageProps extends Omit<ContainerProps, 'id'> {
49
49
  * Scroll container
50
50
  */
51
51
  scrollContainer?: HTMLElement | object;
52
+ /**
53
+ * Support back click
54
+ */
55
+ supportBack?: boolean;
52
56
  /**
53
57
  * State last changed fields
54
58
  */
@@ -16,6 +16,11 @@ export interface EditPageProps extends Omit<CommonPageProps, 'onSubmit'> {
16
16
  * On delete callback
17
17
  */
18
18
  onDelete?: () => Promise<void> | void;
19
+ /**
20
+ * Support back click
21
+ * @default true
22
+ */
23
+ supportBack?: boolean;
19
24
  }
20
25
  /**
21
26
  * Add / Edit page
@@ -5,13 +5,14 @@ import { MUGlobal } from '../MUGlobal';
5
5
  import { CommonPage, CommonPageScrollContainer } from './CommonPage';
6
6
  import SaveIcon from '@mui/icons-material/Save';
7
7
  import DeleteIcon from '@mui/icons-material/Delete';
8
+ import { BackButton } from '../BackButton';
8
9
  /**
9
10
  * Add / Edit page
10
11
  * @param props Props
11
12
  */
12
13
  export function EditPage(props) {
13
14
  // Destruct
14
- const { children, isEditing, onDelete, onSubmit, paddings = MUGlobal.pagePaddings, scrollContainer = CommonPageScrollContainer, ...rest } = props;
15
+ const { children, isEditing, onDelete, onSubmit, paddings = MUGlobal.pagePaddings, scrollContainer = CommonPageScrollContainer, supportBack = true, ...rest } = props;
15
16
  // Labels
16
17
  const labels = Labels.CommonPage;
17
18
  return (React.createElement(CommonPage, { paddings: paddings, scrollContainer: scrollContainer, ...rest },
@@ -23,5 +24,6 @@ export function EditPage(props) {
23
24
  paddingTop: paddings
24
25
  } },
25
26
  isEditing && onDelete && (React.createElement(Button, { color: "primary", variant: "outlined", onClick: () => onDelete(), startIcon: React.createElement(DeleteIcon, { color: "warning" }) }, labels.delete)),
26
- React.createElement(Button, { variant: "contained", type: "submit", startIcon: React.createElement(SaveIcon, null), sx: { flexGrow: 1 } }, labels.save)))));
27
+ React.createElement(Button, { variant: "contained", type: "submit", startIcon: React.createElement(SaveIcon, null), sx: { flexGrow: 1 } }, labels.save),
28
+ supportBack && React.createElement(BackButton, { title: labels.back })))));
27
29
  }
@@ -62,7 +62,7 @@ function getItemField(field, data) {
62
62
  */
63
63
  export function ViewPage(props) {
64
64
  // Destruct
65
- const { actions, children, fields, loadData, paddings = MUGlobal.pagePaddings, supportRefresh = true, ...rest } = props;
65
+ const { actions, children, fields, loadData, paddings = MUGlobal.pagePaddings, supportRefresh = true, fabColumnDirection = true, supportBack = true, ...rest } = props;
66
66
  // Data
67
67
  const [data, setData] = React.useState();
68
68
  // Load data
@@ -72,7 +72,7 @@ export function ViewPage(props) {
72
72
  return;
73
73
  setData(result);
74
74
  };
75
- return (React.createElement(CommonPage, { paddings: paddings, onRefresh: supportRefresh ? refresh : undefined, onUpdate: supportRefresh ? undefined : refresh, ...rest, scrollContainer: global }, data == null ? (React.createElement(LinearProgress, null)) : (React.createElement(React.Fragment, null,
75
+ return (React.createElement(CommonPage, { paddings: paddings, onRefresh: supportRefresh ? refresh : undefined, onUpdate: supportRefresh ? undefined : refresh, ...rest, scrollContainer: globalThis, fabColumnDirection: fabColumnDirection, supportBack: supportBack }, data == null ? (React.createElement(LinearProgress, null)) : (React.createElement(React.Fragment, null,
76
76
  React.createElement(Grid, { container: true, justifyContent: "left", spacing: paddings, className: "ET-ViewPage", sx: {
77
77
  '.MuiTypography-subtitle2': {
78
78
  fontWeight: 'bold'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/react",
3
- "version": "1.5.9",
3
+ "version": "1.5.13",
4
4
  "description": "TypeScript ReactJs framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
package/src/app/Labels.ts CHANGED
@@ -9,6 +9,7 @@ export namespace Labels {
9
9
  */
10
10
  export const CommonPage = {
11
11
  add: 'Add',
12
+ back: 'Back',
12
13
  delete: 'Delete',
13
14
  more: 'More',
14
15
  pullToRefresh: 'Pull down to refresh',
@@ -56,12 +56,10 @@ export function ReactAppStateDetector(props: IStateProps) {
56
56
  const { targetFields, update } = props;
57
57
 
58
58
  // Context
59
- const { state } =
59
+ const { state = {} } =
60
60
  globalApp == null
61
- ? ({ state: {} } as UserCalls<IUser>)
62
- : React.useContext(
63
- (globalApp.userState as UserState<IUser>).context
64
- );
61
+ ? ({} as UserCalls<IUser>)
62
+ : React.useContext(globalApp.userState.context);
65
63
 
66
64
  // Ready
67
65
  React.useEffect(() => {
@@ -223,7 +221,7 @@ export class ReactApp<
223
221
  );
224
222
  this.history =
225
223
  window.location.hostname === ''
226
- ? Utils.getMemoryHistory()
224
+ ? Utils.getMemoryHistory(this.getHostUrl(window.location.href))
227
225
  : undefined;
228
226
  this.cultureState = new CultureState(settings.currentCulture);
229
227
  this.pageState = new PageState<P>();
@@ -231,6 +229,33 @@ export class ReactApp<
231
229
  globalApp = this;
232
230
  }
233
231
 
232
+ /**
233
+ * Get parsed Url under bridge host
234
+ * @param url Url
235
+ * @returns Parsed Url
236
+ */
237
+ protected getHostUrl(url: string) {
238
+ return this.getHostUrlBase(url, 'core');
239
+ }
240
+
241
+ /**
242
+ * Get parsed Url under bridge host
243
+ * @param url Url
244
+ * @param name App name in the host environment
245
+ * @returns Parsed Url
246
+ */
247
+ protected getHostUrlBase(url: string, name: string) {
248
+ if (url.startsWith('/')) return url;
249
+
250
+ const identifier = `/${name}/`;
251
+ const pos = url.indexOf(identifier);
252
+ if (pos === -1) return '/';
253
+
254
+ return url
255
+ .substring(pos + identifier.length - 1)
256
+ .replace('/index.html', '/'); // Router take / as start
257
+ }
258
+
234
259
  /**
235
260
  * Override alert action result
236
261
  * @param result Action result
@@ -68,6 +68,15 @@ export class ServiceApp<
68
68
  this.serviceApi = api;
69
69
  }
70
70
 
71
+ /**
72
+ * Get parsed Url under bridge host
73
+ * @param url Url
74
+ * @returns Parsed Url
75
+ */
76
+ protected override getHostUrl(url: string) {
77
+ return this.getHostUrlBase(url, 's' + this.settings.serviceId);
78
+ }
79
+
71
80
  /**
72
81
  * Go to the login page
73
82
  * @param tryLogin Try to login again
package/src/app/Utils.ts CHANGED
@@ -28,11 +28,12 @@ export namespace Utils {
28
28
 
29
29
  /**
30
30
  * Get memory history
31
+ * @param initialPath Initial path
31
32
  * @returns History
32
33
  */
33
- export function getMemoryHistory() {
34
+ export function getMemoryHistory(initialPath: string = '/') {
34
35
  if (memoryHistory == null) {
35
- memoryHistory = createHistory(createMemorySource('/'));
36
+ memoryHistory = createHistory(createMemorySource(initialPath));
36
37
  }
37
38
  return memoryHistory;
38
39
  }
package/src/index.ts CHANGED
@@ -38,6 +38,7 @@ export * from './mu/texts/MoneyText';
38
38
  export * from './mu/texts/NumberText';
39
39
 
40
40
  export * from './mu/AuditDisplay';
41
+ export * from './mu/BackButton';
41
42
  export * from './mu/BridgeCloseButton';
42
43
  export * from './mu/ButtonLink';
43
44
  export * from './mu/ComboBox';
@@ -0,0 +1,51 @@
1
+ import { IconButton, IconButtonProps } from '@mui/material';
2
+ import ArrowBackIcon from '@mui/icons-material/ArrowBack';
3
+ import React from 'react';
4
+ import { useNavigate } from '@reach/router';
5
+
6
+ /**
7
+ * BackButton props
8
+ */
9
+ export interface BackButtonProps extends IconButtonProps {}
10
+
11
+ /**
12
+ * BackButton
13
+ * @param props Props
14
+ * @returns Component
15
+ */
16
+ export function BackButton(props: BackButtonProps) {
17
+ // Destruct
18
+ const { color = 'primary', size = 'small', onClick, ...rest } = props;
19
+
20
+ // Navigate
21
+ const navigate = useNavigate();
22
+
23
+ // Click handler
24
+ const onClickLocal = (event: React.MouseEvent<HTMLButtonElement>) => {
25
+ if (onClick) onClick(event);
26
+ navigate(-1);
27
+ };
28
+
29
+ return (
30
+ <IconButton
31
+ aria-label="Back"
32
+ color={color}
33
+ size={size}
34
+ onClick={onClickLocal}
35
+ sx={{
36
+ border: (theme) =>
37
+ `1px solid ${
38
+ (() =>
39
+ color != 'inherit' &&
40
+ color != 'default' &&
41
+ color in theme.palette
42
+ ? theme.palette[color]
43
+ : theme.palette.primary)().light
44
+ }`
45
+ }}
46
+ {...rest}
47
+ >
48
+ <ArrowBackIcon />
49
+ </IconButton>
50
+ );
51
+ }
@@ -1,6 +1,6 @@
1
1
  import { BridgeUtils, IBridgeHost } from '@etsoo/appscript';
2
2
  import CloseIcon from '@mui/icons-material/Close';
3
- import { IconButton, IconButtonProps } from '@mui/material';
3
+ import { Box, BoxProps, IconButton, IconButtonProps } from '@mui/material';
4
4
  import React from 'react';
5
5
  import { globalApp } from '../app/ReactApp';
6
6
 
@@ -8,6 +8,11 @@ import { globalApp } from '../app/ReactApp';
8
8
  * Bridge close button props
9
9
  */
10
10
  export interface BridgeCloseButtonProps extends IconButtonProps {
11
+ /**
12
+ * Box props
13
+ */
14
+ boxProps?: BoxProps;
15
+
11
16
  /**
12
17
  * Validate the host
13
18
  * @param host Host
@@ -23,6 +28,7 @@ export interface BridgeCloseButtonProps extends IconButtonProps {
23
28
  export function BridgeCloseButton(props: BridgeCloseButtonProps) {
24
29
  // Destruct
25
30
  const {
31
+ boxProps,
26
32
  onClick,
27
33
  title = typeof globalApp === 'undefined'
28
34
  ? 'Close'
@@ -45,20 +51,15 @@ export function BridgeCloseButton(props: BridgeCloseButtonProps) {
45
51
  };
46
52
 
47
53
  return (
48
- <IconButton
49
- aria-label="close"
50
- color="secondary"
51
- onClick={onClickLocal}
52
- title={title}
53
- sx={{
54
- position: 'absolute',
55
- zIndex: (theme) => theme.zIndex.appBar + 1,
56
- top: (theme) => theme.spacing(0.5),
57
- right: (theme) => theme.spacing(0.5)
58
- }}
59
- {...rest}
60
- >
61
- <CloseIcon />
62
- </IconButton>
54
+ <Box {...boxProps}>
55
+ <IconButton
56
+ aria-label="close"
57
+ onClick={onClickLocal}
58
+ title={title}
59
+ {...rest}
60
+ >
61
+ <CloseIcon />
62
+ </IconButton>
63
+ </Box>
63
64
  );
64
65
  }
@@ -8,6 +8,7 @@ import { MoreFab } from '../MoreFab';
8
8
  import { ReactAppStateDetector } from '../../app/ReactApp';
9
9
  import { Container, Fab } from '@mui/material';
10
10
  import RefreshIcon from '@mui/icons-material/Refresh';
11
+ import { BackButton } from '../BackButton';
11
12
 
12
13
  /**
13
14
  * Default scroll container
@@ -34,6 +35,7 @@ export function CommonPage(props: CommonPageProps) {
34
35
  onUpdateAll,
35
36
  paddings = MUGlobal.pagePaddings,
36
37
  scrollContainer,
38
+ supportBack = false,
37
39
  targetFields,
38
40
  sx = {},
39
41
  ...rest
@@ -115,6 +117,9 @@ export function CommonPage(props: CommonPageProps) {
115
117
  title={labels.more}
116
118
  actions={moreActions}
117
119
  />
120
+ {supportBack && (
121
+ <BackButton title={labels.back} size={fabSize} />
122
+ )}
118
123
  </FabBox>
119
124
  {children}
120
125
  </Container>
@@ -20,7 +20,7 @@ export interface CommonPageProps extends Omit<ContainerProps, 'id'> {
20
20
  fabSize?: CustomFabSize;
21
21
 
22
22
  /**
23
- * Fab flex column direction?
23
+ * Fab flex column direction, undefined to hide it
24
24
  */
25
25
  fabColumnDirection?: boolean;
26
26
 
@@ -59,6 +59,11 @@ export interface CommonPageProps extends Omit<ContainerProps, 'id'> {
59
59
  */
60
60
  scrollContainer?: HTMLElement | object;
61
61
 
62
+ /**
63
+ * Support back click
64
+ */
65
+ supportBack?: boolean;
66
+
62
67
  /**
63
68
  * State last changed fields
64
69
  */
@@ -6,6 +6,7 @@ import { CommonPage, CommonPageScrollContainer } from './CommonPage';
6
6
  import { CommonPageProps } from './CommonPageProps';
7
7
  import SaveIcon from '@mui/icons-material/Save';
8
8
  import DeleteIcon from '@mui/icons-material/Delete';
9
+ import { BackButton } from '../BackButton';
9
10
 
10
11
  /**
11
12
  * Add / Edit page props
@@ -25,6 +26,12 @@ export interface EditPageProps extends Omit<CommonPageProps, 'onSubmit'> {
25
26
  * On delete callback
26
27
  */
27
28
  onDelete?: () => Promise<void> | void;
29
+
30
+ /**
31
+ * Support back click
32
+ * @default true
33
+ */
34
+ supportBack?: boolean;
28
35
  }
29
36
 
30
37
  /**
@@ -40,6 +47,7 @@ export function EditPage(props: EditPageProps) {
40
47
  onSubmit,
41
48
  paddings = MUGlobal.pagePaddings,
42
49
  scrollContainer = CommonPageScrollContainer,
50
+ supportBack = true,
43
51
  ...rest
44
52
  } = props;
45
53
 
@@ -91,6 +99,7 @@ export function EditPage(props: EditPageProps) {
91
99
  >
92
100
  {labels.save}
93
101
  </Button>
102
+ {supportBack && <BackButton title={labels.back} />}
94
103
  </Grid>
95
104
  </form>
96
105
  </CommonPage>
@@ -165,6 +165,8 @@ export function ViewPage<T extends {}>(props: ViewPageProps<T>) {
165
165
  loadData,
166
166
  paddings = MUGlobal.pagePaddings,
167
167
  supportRefresh = true,
168
+ fabColumnDirection = true,
169
+ supportBack = true,
168
170
  ...rest
169
171
  } = props;
170
172
 
@@ -184,7 +186,9 @@ export function ViewPage<T extends {}>(props: ViewPageProps<T>) {
184
186
  onRefresh={supportRefresh ? refresh : undefined}
185
187
  onUpdate={supportRefresh ? undefined : refresh}
186
188
  {...rest}
187
- scrollContainer={global}
189
+ scrollContainer={globalThis}
190
+ fabColumnDirection={fabColumnDirection}
191
+ supportBack={supportBack}
188
192
  >
189
193
  {data == null ? (
190
194
  <LinearProgress />