@ttoss/react-auth 1.6.42 → 1.7.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/dist/esm/index.js +428 -77
- package/dist/index.d.mts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +429 -78
- package/i18n/compiled/en.json +6 -0
- package/i18n/lang/en.json +4 -0
- package/package.json +1 -1
- package/src/Auth.tsx +116 -8
- package/src/AuthConfirmSignUp.tsx +1 -1
- package/src/{AuthRecoveryPassword.tsx → AuthForgotPassword.tsx} +18 -8
- package/src/AuthForgotPasswordResetPassword.tsx +158 -0
- package/src/AuthSignIn.tsx +2 -2
- package/src/types.ts +8 -0
package/i18n/compiled/en.json
CHANGED
package/i18n/lang/en.json
CHANGED
package/package.json
CHANGED
package/src/Auth.tsx
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { Auth as AmplifyAuth } from 'aws-amplify';
|
|
3
3
|
import { AuthConfirmSignUp } from './AuthConfirmSignUp';
|
|
4
|
+
import { AuthForgotPassword } from './AuthForgotPassword';
|
|
5
|
+
import { AuthForgotPasswordResetPassword } from './AuthForgotPasswordResetPassword';
|
|
4
6
|
import { AuthFullScreen } from './AuthFullScreen';
|
|
5
7
|
import { AuthSignIn } from './AuthSignIn';
|
|
6
8
|
import { AuthSignUp } from './AuthSignUp';
|
|
@@ -9,7 +11,13 @@ import { assign, createMachine } from 'xstate';
|
|
|
9
11
|
import { useAuth } from './AuthProvider';
|
|
10
12
|
import { useMachine } from '@xstate/react';
|
|
11
13
|
import { useNotifications } from '@ttoss/react-notifications';
|
|
12
|
-
import type {
|
|
14
|
+
import type {
|
|
15
|
+
OnConfirmSignUp,
|
|
16
|
+
OnForgotPassword,
|
|
17
|
+
OnForgotPasswordResetPassword,
|
|
18
|
+
OnSignIn,
|
|
19
|
+
OnSignUp,
|
|
20
|
+
} from './types';
|
|
13
21
|
|
|
14
22
|
type AuthState =
|
|
15
23
|
| {
|
|
@@ -27,6 +35,14 @@ type AuthState =
|
|
|
27
35
|
| {
|
|
28
36
|
value: 'signUpResendConfirmation';
|
|
29
37
|
context: { email: string };
|
|
38
|
+
}
|
|
39
|
+
| {
|
|
40
|
+
value: 'forgotPassword';
|
|
41
|
+
context: Record<string, never>;
|
|
42
|
+
}
|
|
43
|
+
| {
|
|
44
|
+
value: 'forgotPasswordResetPassword';
|
|
45
|
+
context: { email: string };
|
|
30
46
|
};
|
|
31
47
|
|
|
32
48
|
type AuthEvent =
|
|
@@ -34,7 +50,10 @@ type AuthEvent =
|
|
|
34
50
|
| { type: 'SIGN_UP_CONFIRM'; email: string }
|
|
35
51
|
| { type: 'SIGN_UP_CONFIRMED'; email: string }
|
|
36
52
|
| { type: 'SIGN_UP_RESEND_CONFIRMATION'; email: string }
|
|
37
|
-
| { type: 'RETURN_TO_SIGN_IN' }
|
|
53
|
+
| { type: 'RETURN_TO_SIGN_IN' }
|
|
54
|
+
| { type: 'FORGOT_PASSWORD' }
|
|
55
|
+
| { type: 'FORGOT_PASSWORD_RESET_PASSWORD'; email: string }
|
|
56
|
+
| { type: 'FORGOT_PASSWORD_CONFIRMED'; email: string };
|
|
38
57
|
|
|
39
58
|
type AuthContext = { email?: string };
|
|
40
59
|
|
|
@@ -50,6 +69,7 @@ const authMachine = createMachine<AuthContext, AuthEvent, AuthState>(
|
|
|
50
69
|
actions: ['assignEmail'],
|
|
51
70
|
target: 'signUpConfirm',
|
|
52
71
|
},
|
|
72
|
+
FORGOT_PASSWORD: { target: 'forgotPassword' },
|
|
53
73
|
},
|
|
54
74
|
},
|
|
55
75
|
signUp: {
|
|
@@ -69,13 +89,36 @@ const authMachine = createMachine<AuthContext, AuthEvent, AuthState>(
|
|
|
69
89
|
},
|
|
70
90
|
},
|
|
71
91
|
},
|
|
92
|
+
forgotPassword: {
|
|
93
|
+
on: {
|
|
94
|
+
RETURN_TO_SIGN_IN: { target: 'signIn' },
|
|
95
|
+
SIGN_UP: { target: 'signUp' },
|
|
96
|
+
FORGOT_PASSWORD_RESET_PASSWORD: {
|
|
97
|
+
actions: ['assignEmail'],
|
|
98
|
+
target: 'forgotPasswordResetPassword',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
forgotPasswordResetPassword: {
|
|
103
|
+
on: {
|
|
104
|
+
FORGOT_PASSWORD_CONFIRMED: {
|
|
105
|
+
actions: ['assignEmail'],
|
|
106
|
+
target: 'signIn',
|
|
107
|
+
},
|
|
108
|
+
RETURN_TO_SIGN_IN: { target: 'signIn' },
|
|
109
|
+
},
|
|
110
|
+
},
|
|
72
111
|
},
|
|
73
112
|
},
|
|
74
113
|
{
|
|
75
114
|
actions: {
|
|
76
115
|
assignEmail: assign({
|
|
77
116
|
email: (_, event) => {
|
|
78
|
-
|
|
117
|
+
if ('email' in event) {
|
|
118
|
+
return event.email;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return undefined;
|
|
79
122
|
},
|
|
80
123
|
}),
|
|
81
124
|
},
|
|
@@ -95,11 +138,12 @@ const AuthLogic = () => {
|
|
|
95
138
|
setLoading(true);
|
|
96
139
|
await AmplifyAuth.signIn(email, password);
|
|
97
140
|
// toast('Signed In');
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
98
142
|
} catch (error: any) {
|
|
99
143
|
switch (error.code) {
|
|
100
144
|
case 'UserNotConfirmedException':
|
|
101
145
|
await AmplifyAuth.resendSignUp(email);
|
|
102
|
-
send({ type: 'SIGN_UP_RESEND_CONFIRMATION', email }
|
|
146
|
+
send({ type: 'SIGN_UP_RESEND_CONFIRMATION', email });
|
|
103
147
|
break;
|
|
104
148
|
default:
|
|
105
149
|
// toast(JSON.stringify(error, null, 2));
|
|
@@ -122,7 +166,8 @@ const AuthLogic = () => {
|
|
|
122
166
|
attributes: { email },
|
|
123
167
|
});
|
|
124
168
|
// toast('Signed Up');
|
|
125
|
-
send({ type: 'SIGN_UP_CONFIRM', email }
|
|
169
|
+
send({ type: 'SIGN_UP_CONFIRM', email });
|
|
170
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
126
171
|
} catch (error: any) {
|
|
127
172
|
setNotifications({ type: 'error', message: error.message });
|
|
128
173
|
// toast(JSON.stringify(error, null, 2));
|
|
@@ -139,7 +184,8 @@ const AuthLogic = () => {
|
|
|
139
184
|
setLoading(true);
|
|
140
185
|
await AmplifyAuth.confirmSignUp(email, code);
|
|
141
186
|
// toast('Confirmed Signed In');
|
|
142
|
-
send({ type: 'SIGN_UP_CONFIRMED', email }
|
|
187
|
+
send({ type: 'SIGN_UP_CONFIRMED', email });
|
|
188
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
143
189
|
} catch (error: any) {
|
|
144
190
|
setNotifications({ type: 'error', message: error.message });
|
|
145
191
|
// toast(JSON.stringify(error, null, 2));
|
|
@@ -154,6 +200,43 @@ const AuthLogic = () => {
|
|
|
154
200
|
send({ type: 'RETURN_TO_SIGN_IN' });
|
|
155
201
|
}, [send]);
|
|
156
202
|
|
|
203
|
+
const onForgotPassword = React.useCallback<OnForgotPassword>(
|
|
204
|
+
async ({ email }) => {
|
|
205
|
+
try {
|
|
206
|
+
setLoading(true);
|
|
207
|
+
await AmplifyAuth.forgotPassword(email);
|
|
208
|
+
// toast('Forgot Password');
|
|
209
|
+
send({ type: 'FORGOT_PASSWORD_RESET_PASSWORD', email });
|
|
210
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
211
|
+
} catch (error: any) {
|
|
212
|
+
setNotifications({ type: 'error', message: error.message });
|
|
213
|
+
// toast(JSON.stringify(error, null, 2));
|
|
214
|
+
} finally {
|
|
215
|
+
setLoading(false);
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
[send, setLoading, setNotifications]
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
const onForgotPasswordResetPassword =
|
|
222
|
+
React.useCallback<OnForgotPasswordResetPassword>(
|
|
223
|
+
async ({ email, code, newPassword }) => {
|
|
224
|
+
try {
|
|
225
|
+
setLoading(true);
|
|
226
|
+
await AmplifyAuth.forgotPasswordSubmit(email, code, newPassword);
|
|
227
|
+
// toast('Forgot Password Reset Password');
|
|
228
|
+
send({ type: 'FORGOT_PASSWORD_CONFIRMED', email });
|
|
229
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
230
|
+
} catch (error: any) {
|
|
231
|
+
setNotifications({ type: 'error', message: error.message });
|
|
232
|
+
// toast(JSON.stringify(error, null, 2));
|
|
233
|
+
} finally {
|
|
234
|
+
setLoading(false);
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
[send, setLoading, setNotifications]
|
|
238
|
+
);
|
|
239
|
+
|
|
157
240
|
if (isAuthenticated) {
|
|
158
241
|
return null;
|
|
159
242
|
}
|
|
@@ -168,7 +251,29 @@ const AuthLogic = () => {
|
|
|
168
251
|
return (
|
|
169
252
|
<AuthConfirmSignUp
|
|
170
253
|
onConfirmSignUp={onConfirmSignUp}
|
|
171
|
-
email={
|
|
254
|
+
email={state.context.email}
|
|
255
|
+
/>
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (state.matches('forgotPassword')) {
|
|
260
|
+
return (
|
|
261
|
+
<AuthForgotPassword
|
|
262
|
+
onForgotPassword={onForgotPassword}
|
|
263
|
+
onCancel={onReturnToSignIn}
|
|
264
|
+
onSignUp={() => {
|
|
265
|
+
return send('SIGN_UP');
|
|
266
|
+
}}
|
|
267
|
+
/>
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (state.matches('forgotPasswordResetPassword')) {
|
|
272
|
+
return (
|
|
273
|
+
<AuthForgotPasswordResetPassword
|
|
274
|
+
email={state.context.email}
|
|
275
|
+
onForgotPasswordResetPassword={onForgotPasswordResetPassword}
|
|
276
|
+
onCancel={onReturnToSignIn}
|
|
172
277
|
/>
|
|
173
278
|
);
|
|
174
279
|
}
|
|
@@ -179,7 +284,10 @@ const AuthLogic = () => {
|
|
|
179
284
|
onSignUp={() => {
|
|
180
285
|
return send('SIGN_UP');
|
|
181
286
|
}}
|
|
182
|
-
|
|
287
|
+
onForgotPassword={() => {
|
|
288
|
+
return send('FORGOT_PASSWORD');
|
|
289
|
+
}}
|
|
290
|
+
defaultValues={{ email: state.context.email }}
|
|
183
291
|
/>
|
|
184
292
|
);
|
|
185
293
|
};
|
|
@@ -3,14 +3,19 @@ import { Button, Link, Text } from '@ttoss/ui';
|
|
|
3
3
|
import { Form, FormFieldInput, useForm, yup, yupResolver } from '@ttoss/forms';
|
|
4
4
|
import { NotificationsBox } from '@ttoss/react-notifications';
|
|
5
5
|
import { useI18n } from '@ttoss/react-i18n';
|
|
6
|
+
import type { OnForgotPassword } from './types';
|
|
6
7
|
|
|
7
|
-
export type
|
|
8
|
-
|
|
8
|
+
export type AuthForgotPasswordProps = {
|
|
9
|
+
onForgotPassword: OnForgotPassword;
|
|
10
|
+
onCancel: () => void;
|
|
11
|
+
onSignUp: () => void;
|
|
9
12
|
};
|
|
10
13
|
|
|
11
|
-
export const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
export const AuthForgotPassword = ({
|
|
15
|
+
onForgotPassword,
|
|
16
|
+
onCancel,
|
|
17
|
+
onSignUp,
|
|
18
|
+
}: AuthForgotPasswordProps) => {
|
|
14
19
|
const { intl } = useI18n();
|
|
15
20
|
|
|
16
21
|
const schema = yup
|
|
@@ -33,7 +38,7 @@ export const AuthRecoveryPassword = ({
|
|
|
33
38
|
})
|
|
34
39
|
.required();
|
|
35
40
|
|
|
36
|
-
const formMethods = useForm<yup.
|
|
41
|
+
const formMethods = useForm<yup.InferType<typeof schema>>({
|
|
37
42
|
resolver: yupResolver(schema),
|
|
38
43
|
mode: 'onBlur',
|
|
39
44
|
});
|
|
@@ -45,7 +50,7 @@ export const AuthRecoveryPassword = ({
|
|
|
45
50
|
maxWidth: '390px',
|
|
46
51
|
}}
|
|
47
52
|
onSubmit={({ email }) => {
|
|
48
|
-
return
|
|
53
|
+
return onForgotPassword({ email });
|
|
49
54
|
}}
|
|
50
55
|
>
|
|
51
56
|
<AuthCard
|
|
@@ -62,6 +67,7 @@ export const AuthRecoveryPassword = ({
|
|
|
62
67
|
<Button
|
|
63
68
|
sx={{ textAlign: 'center', display: 'initial' }}
|
|
64
69
|
variant="secondary"
|
|
70
|
+
onClick={onCancel}
|
|
65
71
|
>
|
|
66
72
|
{intl.formatMessage({
|
|
67
73
|
description: 'Cancel',
|
|
@@ -80,7 +86,11 @@ export const AuthRecoveryPassword = ({
|
|
|
80
86
|
|
|
81
87
|
<NotificationsBox />
|
|
82
88
|
|
|
83
|
-
<Text
|
|
89
|
+
<Text
|
|
90
|
+
sx={{ marginTop: 'xl', cursor: 'pointer' }}
|
|
91
|
+
as={Link}
|
|
92
|
+
onClick={onSignUp}
|
|
93
|
+
>
|
|
84
94
|
{intl.formatMessage({
|
|
85
95
|
description: 'Sign up now',
|
|
86
96
|
defaultMessage: 'Sign up now',
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { AuthCard } from './AuthCard';
|
|
3
|
+
import { Button } from '@ttoss/ui';
|
|
4
|
+
import {
|
|
5
|
+
Form,
|
|
6
|
+
FormFieldInput,
|
|
7
|
+
FormFieldPassword,
|
|
8
|
+
useForm,
|
|
9
|
+
yup,
|
|
10
|
+
yupResolver,
|
|
11
|
+
} from '@ttoss/forms';
|
|
12
|
+
import { NotificationsBox } from '@ttoss/react-notifications';
|
|
13
|
+
import { PASSWORD_MINIMUM_LENGTH } from '@ttoss/cloud-auth';
|
|
14
|
+
import { useI18n } from '@ttoss/react-i18n';
|
|
15
|
+
import type { OnForgotPasswordResetPassword } from './types';
|
|
16
|
+
|
|
17
|
+
export type AuthForgotPasswordResetPasswordProps = {
|
|
18
|
+
email: string;
|
|
19
|
+
onForgotPasswordResetPassword: OnForgotPasswordResetPassword;
|
|
20
|
+
onCancel: () => void;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const AuthForgotPasswordResetPassword = ({
|
|
24
|
+
email,
|
|
25
|
+
onForgotPasswordResetPassword,
|
|
26
|
+
onCancel,
|
|
27
|
+
}: AuthForgotPasswordResetPasswordProps) => {
|
|
28
|
+
const { intl } = useI18n();
|
|
29
|
+
|
|
30
|
+
const schema = React.useMemo(() => {
|
|
31
|
+
return yup
|
|
32
|
+
.object()
|
|
33
|
+
.shape({
|
|
34
|
+
code: yup
|
|
35
|
+
.string()
|
|
36
|
+
.required(
|
|
37
|
+
intl.formatMessage({
|
|
38
|
+
description: 'Required field.',
|
|
39
|
+
defaultMessage: 'Required field',
|
|
40
|
+
})
|
|
41
|
+
)
|
|
42
|
+
.max(
|
|
43
|
+
6,
|
|
44
|
+
intl.formatMessage(
|
|
45
|
+
{
|
|
46
|
+
description: 'Minimum {value} characters.',
|
|
47
|
+
defaultMessage: 'Minimum {value} characters',
|
|
48
|
+
},
|
|
49
|
+
{ value: 6 }
|
|
50
|
+
)
|
|
51
|
+
),
|
|
52
|
+
password: yup
|
|
53
|
+
.string()
|
|
54
|
+
.required(
|
|
55
|
+
intl.formatMessage({
|
|
56
|
+
description: 'Password is required.',
|
|
57
|
+
defaultMessage: 'Password field is required',
|
|
58
|
+
})
|
|
59
|
+
)
|
|
60
|
+
.min(
|
|
61
|
+
PASSWORD_MINIMUM_LENGTH,
|
|
62
|
+
intl.formatMessage(
|
|
63
|
+
{
|
|
64
|
+
description:
|
|
65
|
+
'Password must be at least {value} characters long.',
|
|
66
|
+
defaultMessage: 'Password requires {value} characters',
|
|
67
|
+
},
|
|
68
|
+
{ value: PASSWORD_MINIMUM_LENGTH }
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
.trim(),
|
|
72
|
+
confirmPassword: yup
|
|
73
|
+
.string()
|
|
74
|
+
.required(
|
|
75
|
+
intl.formatMessage({
|
|
76
|
+
description: 'Confirm Password is required.',
|
|
77
|
+
defaultMessage: 'Confirm password field is required',
|
|
78
|
+
})
|
|
79
|
+
)
|
|
80
|
+
.oneOf(
|
|
81
|
+
[yup.ref('password')],
|
|
82
|
+
intl.formatMessage({
|
|
83
|
+
description: 'Passwords are not the same',
|
|
84
|
+
defaultMessage: 'Passwords are not the same',
|
|
85
|
+
})
|
|
86
|
+
),
|
|
87
|
+
})
|
|
88
|
+
.required();
|
|
89
|
+
}, [intl]);
|
|
90
|
+
|
|
91
|
+
const formMethods = useForm<yup.InferType<typeof schema>>({
|
|
92
|
+
resolver: yupResolver(schema),
|
|
93
|
+
mode: 'onBlur',
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<Form
|
|
98
|
+
{...formMethods}
|
|
99
|
+
sx={{
|
|
100
|
+
maxWidth: '390px',
|
|
101
|
+
}}
|
|
102
|
+
onSubmit={({ code, password }) => {
|
|
103
|
+
return onForgotPasswordResetPassword({
|
|
104
|
+
email,
|
|
105
|
+
code,
|
|
106
|
+
newPassword: password,
|
|
107
|
+
});
|
|
108
|
+
}}
|
|
109
|
+
>
|
|
110
|
+
<AuthCard
|
|
111
|
+
buttonLabel={intl.formatMessage({
|
|
112
|
+
description: 'Recover Password',
|
|
113
|
+
defaultMessage: 'Recover Password',
|
|
114
|
+
})}
|
|
115
|
+
isValidForm={formMethods.formState.isValid}
|
|
116
|
+
title={intl.formatMessage({
|
|
117
|
+
description: 'Recovering Password',
|
|
118
|
+
defaultMessage: 'Recovering Password',
|
|
119
|
+
})}
|
|
120
|
+
extraButton={
|
|
121
|
+
<Button
|
|
122
|
+
sx={{ textAlign: 'center', display: 'initial' }}
|
|
123
|
+
variant="secondary"
|
|
124
|
+
onClick={onCancel}
|
|
125
|
+
>
|
|
126
|
+
{intl.formatMessage({
|
|
127
|
+
description: 'Cancel',
|
|
128
|
+
defaultMessage: 'Cancel',
|
|
129
|
+
})}
|
|
130
|
+
</Button>
|
|
131
|
+
}
|
|
132
|
+
>
|
|
133
|
+
<FormFieldInput
|
|
134
|
+
name="code"
|
|
135
|
+
label={intl.formatMessage({
|
|
136
|
+
description: 'Code',
|
|
137
|
+
defaultMessage: 'Code',
|
|
138
|
+
})}
|
|
139
|
+
/>
|
|
140
|
+
<FormFieldPassword
|
|
141
|
+
name="password"
|
|
142
|
+
label={intl.formatMessage({
|
|
143
|
+
description: 'Password label.',
|
|
144
|
+
defaultMessage: 'Password',
|
|
145
|
+
})}
|
|
146
|
+
/>
|
|
147
|
+
<FormFieldPassword
|
|
148
|
+
name="confirmPassword"
|
|
149
|
+
label={intl.formatMessage({
|
|
150
|
+
description: 'Confirm Password label.',
|
|
151
|
+
defaultMessage: 'Confirm password',
|
|
152
|
+
})}
|
|
153
|
+
/>
|
|
154
|
+
<NotificationsBox />
|
|
155
|
+
</AuthCard>
|
|
156
|
+
</Form>
|
|
157
|
+
);
|
|
158
|
+
};
|
package/src/AuthSignIn.tsx
CHANGED
|
@@ -17,7 +17,7 @@ import type { OnSignIn, OnSignInInput } from './types';
|
|
|
17
17
|
export type AuthSignInProps = {
|
|
18
18
|
onSignIn: OnSignIn;
|
|
19
19
|
onSignUp: () => void;
|
|
20
|
-
onForgotPassword
|
|
20
|
+
onForgotPassword: () => void;
|
|
21
21
|
defaultValues?: Partial<OnSignInInput>;
|
|
22
22
|
urlLogo?: string;
|
|
23
23
|
};
|
|
@@ -141,7 +141,7 @@ export const AuthSignIn = ({
|
|
|
141
141
|
/> */}
|
|
142
142
|
|
|
143
143
|
<Text
|
|
144
|
-
sx={{ marginLeft: 'auto' }}
|
|
144
|
+
sx={{ marginLeft: 'auto', cursor: 'pointer' }}
|
|
145
145
|
as={Link}
|
|
146
146
|
onClick={onForgotPassword}
|
|
147
147
|
>
|
package/src/types.ts
CHANGED
|
@@ -14,3 +14,11 @@ export type OnSignUpInput = {
|
|
|
14
14
|
export type OnSignUp = (input: OnSignUpInput) => void;
|
|
15
15
|
|
|
16
16
|
export type OnConfirmSignUp = (input: { email: string; code: string }) => void;
|
|
17
|
+
|
|
18
|
+
export type OnForgotPassword = (input: { email: string }) => void;
|
|
19
|
+
|
|
20
|
+
export type OnForgotPasswordResetPassword = (input: {
|
|
21
|
+
email: string;
|
|
22
|
+
code: string;
|
|
23
|
+
newPassword: string;
|
|
24
|
+
}) => void;
|