@faybl/react-utils 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -94,6 +94,16 @@ dark app has to declare it, with MUI through `<CssBaseline enableColorScheme />`
|
|
|
94
94
|
page the user left, which asks the user to sign in again. `signOutUrl` on the
|
|
95
95
|
provider sends it somewhere else instead.
|
|
96
96
|
|
|
97
|
+
`dialogComponent` replaces the dialog with one of the app's own, which gets
|
|
98
|
+
`open`, `onSignIn` and `labels`. An MUI app passes the one from
|
|
99
|
+
`@faybl/react-utils/mui`, which takes the app's theme:
|
|
100
|
+
|
|
101
|
+
```jsx
|
|
102
|
+
import { MuiSessionExpiredDialog } from '@faybl/react-utils/mui';
|
|
103
|
+
|
|
104
|
+
<SessionProvider client={client} dialogComponent={MuiSessionExpiredDialog}>
|
|
105
|
+
```
|
|
106
|
+
|
|
97
107
|
An app that handles the expiry itself can still use the dialog:
|
|
98
108
|
|
|
99
109
|
```jsx
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faybl/react-utils",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "React hooks for Faybl web apps",
|
|
5
5
|
"license": "TBD",
|
|
6
6
|
"author": "Arcturitech",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"exports": {
|
|
9
|
-
".": "./src/index.js"
|
|
9
|
+
".": "./src/index.js",
|
|
10
|
+
"./mui": "./src/mui/index.js"
|
|
10
11
|
},
|
|
11
12
|
"files": [
|
|
12
13
|
"src"
|
|
@@ -22,15 +23,19 @@
|
|
|
22
23
|
},
|
|
23
24
|
"peerDependencies": {
|
|
24
25
|
"@faybl/client": "^4.1.0",
|
|
26
|
+
"@mui/material": "^9.0.0",
|
|
25
27
|
"react": "^19.2.0"
|
|
26
28
|
},
|
|
27
29
|
"peerDependenciesMeta": {
|
|
28
30
|
"@faybl/client": {
|
|
29
31
|
"optional": true
|
|
32
|
+
},
|
|
33
|
+
"@mui/material": {
|
|
34
|
+
"optional": true
|
|
30
35
|
}
|
|
31
36
|
},
|
|
32
37
|
"dependencies": {
|
|
33
|
-
"@faybl/utils": "^2.0
|
|
38
|
+
"@faybl/utils": "^2.1.0"
|
|
34
39
|
},
|
|
35
40
|
"engines": {
|
|
36
41
|
"node": ">=22"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createElement, useEffect, useId, useRef } from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { DEFAULT_SESSION_DIALOG_LABELS } from './sessionDialogLabels.js';
|
|
4
4
|
|
|
5
5
|
// Its colours are the browser's for the page's CSS color-scheme, which a dark
|
|
6
6
|
// app sets on the root element (MUI: CssBaseline enableColorScheme).
|
|
@@ -40,7 +40,7 @@ const useModal = (open) => {
|
|
|
40
40
|
export const SessionExpiredDialog = ({ open, onSignIn, labels }) => {
|
|
41
41
|
const ref = useModal(open);
|
|
42
42
|
const titleId = useId();
|
|
43
|
-
const { title, action } = { ...
|
|
43
|
+
const { title, action } = { ...DEFAULT_SESSION_DIALOG_LABELS, ...labels };
|
|
44
44
|
return createElement(
|
|
45
45
|
'dialog',
|
|
46
46
|
{ ref, 'aria-labelledby': titleId, onCancel: keepOpen, style: dialogStyle },
|
package/src/SessionProvider.js
CHANGED
|
@@ -61,6 +61,7 @@ const useAutomaticReload = (reaction) =>
|
|
|
61
61
|
* @param {number} [params.reloadCooldownMs] Default 30 000
|
|
62
62
|
* @param {string} [params.signOutUrl] Where signOut goes; through the login proxy by default
|
|
63
63
|
* @param {{ title?: string, action?: string }} [params.dialogLabels]
|
|
64
|
+
* @param {import('react').ComponentType} [params.dialogComponent] Drawn for `dialog`; gets `open`, `onSignIn` and `labels`
|
|
64
65
|
* @param {import('react').ReactNode} params.children
|
|
65
66
|
*/
|
|
66
67
|
export const SessionProvider = ({
|
|
@@ -70,6 +71,7 @@ export const SessionProvider = ({
|
|
|
70
71
|
reloadCooldownMs = DEFAULT_RELOAD_COOLDOWN_MS,
|
|
71
72
|
signOutUrl,
|
|
72
73
|
dialogLabels,
|
|
74
|
+
dialogComponent = SessionExpiredDialog,
|
|
73
75
|
children,
|
|
74
76
|
}) => {
|
|
75
77
|
const reactions = useMemo(
|
|
@@ -108,7 +110,7 @@ export const SessionProvider = ({
|
|
|
108
110
|
SessionContext,
|
|
109
111
|
{ value },
|
|
110
112
|
children,
|
|
111
|
-
createElement(
|
|
113
|
+
createElement(dialogComponent, {
|
|
112
114
|
open: reaction === REACTION.DIALOG,
|
|
113
115
|
onSignIn: reloadPage,
|
|
114
116
|
labels: dialogLabels,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Button, Dialog, DialogActions, DialogTitle } from '@mui/material';
|
|
2
|
+
import { createElement, useId } from 'react';
|
|
3
|
+
|
|
4
|
+
import { DEFAULT_SESSION_DIALOG_LABELS } from '../sessionDialogLabels.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* SessionExpiredDialog drawn with MUI, so it takes the app's theme. Pass it to
|
|
8
|
+
* SessionProvider as `dialogComponent`. It has no onClose: neither Escape nor
|
|
9
|
+
* the backdrop closes it, since the only way on is to sign in again.
|
|
10
|
+
* @param {object} params
|
|
11
|
+
* @param {boolean} params.open
|
|
12
|
+
* @param {() => void} params.onSignIn
|
|
13
|
+
* @param {{ title?: string, action?: string }} [params.labels]
|
|
14
|
+
*/
|
|
15
|
+
export const MuiSessionExpiredDialog = ({ open, onSignIn, labels }) => {
|
|
16
|
+
const titleId = useId();
|
|
17
|
+
const { title, action } = { ...DEFAULT_SESSION_DIALOG_LABELS, ...labels };
|
|
18
|
+
return createElement(
|
|
19
|
+
Dialog,
|
|
20
|
+
{ open, 'aria-labelledby': titleId },
|
|
21
|
+
createElement(DialogTitle, { id: titleId }, title),
|
|
22
|
+
createElement(
|
|
23
|
+
DialogActions,
|
|
24
|
+
undefined,
|
|
25
|
+
createElement(Button, { variant: 'contained', onClick: onSignIn, autoFocus: true }, action),
|
|
26
|
+
),
|
|
27
|
+
);
|
|
28
|
+
};
|
package/src/mui/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MuiSessionExpiredDialog } from './MuiSessionExpiredDialog.js';
|