@aws-amplify/ui-react-core 2.1.33 → 3.0.1
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/Authenticator/context/AuthenticatorProvider.mjs +5 -6
- package/dist/esm/Authenticator/hooks/constants.mjs +4 -4
- package/dist/esm/Authenticator/hooks/useAuthenticator/useAuthenticator.mjs +14 -11
- package/dist/esm/Authenticator/hooks/useAuthenticator/utils.mjs +10 -18
- package/dist/esm/Authenticator/hooks/useAuthenticatorRoute/constants.mjs +7 -4
- package/dist/esm/Authenticator/hooks/useAuthenticatorRoute/useAuthenticatorRoute.mjs +6 -6
- package/dist/esm/Authenticator/hooks/useAuthenticatorRoute/utils.mjs +47 -18
- package/dist/esm/Authenticator/hooks/utils.mjs +2 -2
- package/dist/esm/components/FormCore/FormProvider.mjs +15 -0
- package/dist/esm/components/FormCore/useField.mjs +20 -0
- package/dist/esm/components/FormCore/useForm.mjs +51 -0
- package/dist/esm/components/FormCore/withFormProvider.mjs +15 -0
- package/dist/esm/hooks/useSetUserAgent.mjs +15 -0
- package/dist/esm/hooks/useTimeout.mjs +22 -0
- package/dist/esm/index.mjs +7 -0
- package/dist/esm/utils/createContextUtilities.mjs +80 -0
- package/dist/index.js +284 -96
- package/dist/types/Authenticator/hooks/types.d.ts +10 -7
- package/dist/types/Authenticator/hooks/useAuthenticator/types.d.ts +1 -3
- package/dist/types/Authenticator/hooks/useAuthenticator/utils.d.ts +2 -3
- package/dist/types/Authenticator/hooks/useAuthenticatorRoute/types.d.ts +3 -3
- package/dist/types/Authenticator/hooks/useAuthenticatorRoute/useAuthenticatorRoute.d.ts +2 -2
- package/dist/types/Authenticator/hooks/useAuthenticatorRoute/utils.d.ts +2 -2
- package/dist/types/components/FormCore/FormProvider.d.ts +4 -0
- package/dist/types/components/FormCore/index.d.ts +5 -0
- package/dist/types/components/FormCore/types.d.ts +217 -0
- package/dist/types/components/FormCore/useControlledField.d.ts +9 -0
- package/dist/types/components/FormCore/useField.d.ts +9 -0
- package/dist/types/components/FormCore/useForm.d.ts +12 -0
- package/dist/types/components/FormCore/withFormProvider.d.ts +8 -0
- package/dist/types/components/index.d.ts +1 -0
- package/dist/types/hooks/index.d.ts +2 -0
- package/dist/types/hooks/useSetUserAgent.d.ts +2 -0
- package/dist/types/hooks/useTimeout.d.ts +4 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/types.d.ts +2 -0
- package/dist/types/utils/createContextUtilities.d.ts +26 -18
- package/package.json +11 -29
- package/src/Authenticator/context/AuthenticatorContext.tsx +17 -0
- package/src/Authenticator/context/AuthenticatorProvider.tsx +82 -0
- package/src/Authenticator/context/index.ts +2 -0
- package/src/Authenticator/hooks/constants.ts +30 -0
- package/src/Authenticator/hooks/index.ts +5 -0
- package/src/Authenticator/hooks/types.ts +218 -0
- package/src/Authenticator/hooks/useAuthenticator/__mock__/useAuthenticator.ts +66 -0
- package/src/Authenticator/hooks/useAuthenticator/constants.ts +2 -0
- package/src/Authenticator/hooks/useAuthenticator/index.ts +2 -0
- package/src/Authenticator/hooks/useAuthenticator/types.ts +48 -0
- package/src/Authenticator/hooks/useAuthenticator/useAuthenticator.ts +72 -0
- package/src/Authenticator/hooks/useAuthenticator/utils.ts +97 -0
- package/src/Authenticator/hooks/useAuthenticatorInitMachine/index.ts +1 -0
- package/src/Authenticator/hooks/useAuthenticatorInitMachine/useAuthenticatorInitMachine.tsx +25 -0
- package/src/Authenticator/hooks/useAuthenticatorRoute/constants.ts +107 -0
- package/src/Authenticator/hooks/useAuthenticatorRoute/index.ts +2 -0
- package/src/Authenticator/hooks/useAuthenticatorRoute/types.ts +111 -0
- package/src/Authenticator/hooks/useAuthenticatorRoute/useAuthenticatorRoute.ts +126 -0
- package/src/Authenticator/hooks/useAuthenticatorRoute/utils.ts +204 -0
- package/src/Authenticator/hooks/utils.ts +38 -0
- package/src/Authenticator/index.ts +23 -0
- package/src/components/FormCore/FormProvider.tsx +37 -0
- package/src/components/FormCore/index.ts +13 -0
- package/src/components/FormCore/types.ts +277 -0
- package/src/components/FormCore/useControlledField.ts +73 -0
- package/src/components/FormCore/useField.ts +25 -0
- package/src/components/FormCore/useForm.ts +84 -0
- package/src/components/FormCore/withFormProvider.tsx +31 -0
- package/src/components/RenderNothing/RenderNothing.tsx +6 -0
- package/src/components/RenderNothing/index.ts +1 -0
- package/src/components/index.ts +15 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/useDeprecationWarning.ts +27 -0
- package/src/hooks/useHasValueUpdated.ts +28 -0
- package/src/hooks/usePreviousValue.ts +15 -0
- package/src/hooks/useSetUserAgent.ts +18 -0
- package/src/hooks/useTimeout.ts +30 -0
- package/src/index.ts +48 -0
- package/src/types/index.ts +1 -0
- package/src/types/types.ts +3 -0
- package/src/utils/createContextUtilities.tsx +131 -0
- package/src/utils/index.ts +1 -0
- package/dist/esm/node_modules/tslib/tslib.es6.mjs +0 -38
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { __awaiter } from '../../node_modules/tslib/tslib.es6.mjs';
|
|
2
1
|
import React__default, { useContext, useMemo, useEffect } from 'react';
|
|
3
2
|
import { useInterpret } from '@xstate/react';
|
|
4
|
-
import {
|
|
3
|
+
import { getCurrentUser } from 'aws-amplify/auth';
|
|
5
4
|
import { createAuthenticatorMachine, listenToAuthHub, defaultAuthHubHandler } from '@aws-amplify/ui';
|
|
6
5
|
import { AuthenticatorContext } from './AuthenticatorContext.mjs';
|
|
7
6
|
|
|
8
|
-
const createHubHandler = (options) => (data, service) =>
|
|
9
|
-
|
|
10
|
-
}
|
|
7
|
+
const createHubHandler = (options) => async (data, service) => {
|
|
8
|
+
await defaultAuthHubHandler(data, service, options);
|
|
9
|
+
};
|
|
11
10
|
function AuthenticatorProvider({ children, }) {
|
|
12
11
|
// `authStatus` is exposed by `useAuthenticator` but should not be derived directly from the
|
|
13
12
|
// state machine as the machine only updates on `Authenticator` initiated events, which
|
|
@@ -16,7 +15,7 @@ function AuthenticatorProvider({ children, }) {
|
|
|
16
15
|
const [authStatus, setAuthStatus] = React__default.useState('configuring');
|
|
17
16
|
// only run on first render
|
|
18
17
|
React__default.useEffect(() => {
|
|
19
|
-
|
|
18
|
+
getCurrentUser()
|
|
20
19
|
.then(() => {
|
|
21
20
|
setAuthStatus('authenticated');
|
|
22
21
|
})
|
|
@@ -4,8 +4,8 @@ const COMPONENT_ROUTE_KEYS = [
|
|
|
4
4
|
'confirmSignUp',
|
|
5
5
|
'confirmVerifyUser',
|
|
6
6
|
'forceNewPassword',
|
|
7
|
-
'
|
|
8
|
-
'
|
|
7
|
+
'forgotPassword',
|
|
8
|
+
'setupTotp',
|
|
9
9
|
'signIn',
|
|
10
10
|
'signUp',
|
|
11
11
|
'verifyUser',
|
|
@@ -16,8 +16,8 @@ const COMPONENT_ROUTE_NAMES = [
|
|
|
16
16
|
'ConfirmSignUp',
|
|
17
17
|
'ConfirmVerifyUser',
|
|
18
18
|
'ForceNewPassword',
|
|
19
|
-
'
|
|
20
|
-
'
|
|
19
|
+
'ForgotPassword',
|
|
20
|
+
'SetupTotp',
|
|
21
21
|
'SignIn',
|
|
22
22
|
'SignUp',
|
|
23
23
|
'VerifyUser',
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { __rest } from '../../../node_modules/tslib/tslib.es6.mjs';
|
|
2
1
|
import React__default, { useCallback } from 'react';
|
|
3
2
|
import { useSelector } from '@xstate/react';
|
|
4
3
|
import { getServiceFacade } from '@aws-amplify/ui';
|
|
5
|
-
import 'aws-amplify';
|
|
4
|
+
import 'aws-amplify/auth';
|
|
6
5
|
import { AuthenticatorContext } from '../../context/AuthenticatorContext.mjs';
|
|
7
6
|
import { USE_AUTHENTICATOR_ERROR } from './constants.mjs';
|
|
8
|
-
import { getQRFields, getMachineFields,
|
|
7
|
+
import { getQRFields, getMachineFields, getComparator, defaultComparator } from './utils.mjs';
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* [📖 Docs](https://ui.docs.amplify.aws/react/connected-components/authenticator/headless#useauthenticator-hook)
|
|
@@ -17,27 +16,31 @@ function useAuthenticator(selector) {
|
|
|
17
16
|
}
|
|
18
17
|
const { service } = context;
|
|
19
18
|
const { send } = service;
|
|
20
|
-
const xstateSelector = useCallback((state) => (
|
|
19
|
+
const xstateSelector = useCallback((state) => ({ ...getServiceFacade({ send, state }) }), [send]);
|
|
21
20
|
const comparator = selector ? getComparator(selector) : defaultComparator;
|
|
22
21
|
// the purpose of `context.authStatus`is to intentionally override `facade.authStatus`. `facade.authStatus` does
|
|
23
22
|
// not update on external sign in events (for example when a user is not using the `Authenticator`).
|
|
24
23
|
const { authStatus } = context;
|
|
25
24
|
const facade = useSelector(service, xstateSelector, comparator);
|
|
26
|
-
const { route, totpSecretCode,
|
|
25
|
+
const { route, totpSecretCode, unverifiedUserAttributes, user, ...rest } = facade;
|
|
27
26
|
// do not memoize output. `service.getSnapshot` reference remains stable preventing
|
|
28
27
|
// `fields` from updating with current form state on value changes
|
|
29
28
|
const serviceSnapshot = service.getSnapshot();
|
|
30
|
-
// legacy `QRFields` values only used for
|
|
31
|
-
const QRFields = route === '
|
|
29
|
+
// legacy `QRFields` values only used for SetupTotp page to retrieve issuer information, will be removed in future
|
|
30
|
+
const QRFields = route === 'setupTotp' ? getQRFields(serviceSnapshot) : null;
|
|
32
31
|
// legacy `formFields` values required until form state is removed from state machine
|
|
33
|
-
const fields = getMachineFields(route, serviceSnapshot,
|
|
34
|
-
return
|
|
32
|
+
const fields = getMachineFields(route, serviceSnapshot, unverifiedUserAttributes);
|
|
33
|
+
return {
|
|
34
|
+
...rest,
|
|
35
|
+
authStatus,
|
|
35
36
|
route,
|
|
36
37
|
totpSecretCode,
|
|
37
|
-
|
|
38
|
+
unverifiedUserAttributes,
|
|
38
39
|
user,
|
|
39
40
|
/** @deprecated For internal use only */
|
|
40
|
-
fields,
|
|
41
|
+
fields,
|
|
42
|
+
QRFields,
|
|
43
|
+
};
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
export { useAuthenticator as default };
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { __awaiter } from '../../../node_modules/tslib/tslib.es6.mjs';
|
|
2
|
-
import { Auth } from 'aws-amplify';
|
|
3
1
|
import { getActorContext, getSortedFormFields, isString, areEmptyArrays, areEmptyObjects } from '@aws-amplify/ui';
|
|
4
2
|
import { isComponentRouteKey } from '../utils.mjs';
|
|
5
3
|
|
|
@@ -27,19 +25,13 @@ const getComparator = (selector) => (currentFacade, nextFacade) => {
|
|
|
27
25
|
// Shallow compare the array values
|
|
28
26
|
return areSelectorDepsEqual(currentSelectorDeps, nextSelectorDeps);
|
|
29
27
|
};
|
|
30
|
-
const getQRFields = (state) => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
};
|
|
34
|
-
const
|
|
35
|
-
return
|
|
36
|
-
|
|
37
|
-
});
|
|
38
|
-
};
|
|
39
|
-
const flattenFormFields = (fields) => fields.flatMap(([name, options]) => (Object.assign({ name }, options)));
|
|
40
|
-
const convertContactMethodsToFields = (unverifiedContactMethods) => {
|
|
41
|
-
return (unverifiedContactMethods &&
|
|
42
|
-
Object.entries(unverifiedContactMethods).map(([name, value]) => {
|
|
28
|
+
const getQRFields = (state) => ({
|
|
29
|
+
...getActorContext(state)?.formFields?.setupTotp?.QR,
|
|
30
|
+
});
|
|
31
|
+
const flattenFormFields = (fields) => fields.flatMap(([name, options]) => ({ name, ...options }));
|
|
32
|
+
const convertContactMethodsToFields = (unverifiedUserAttributes) => {
|
|
33
|
+
return (unverifiedUserAttributes &&
|
|
34
|
+
Object.entries(unverifiedUserAttributes).map(([name, value]) => {
|
|
43
35
|
const valueIsString = isString(value);
|
|
44
36
|
if (!valueIsString || !name) {
|
|
45
37
|
return {};
|
|
@@ -51,13 +43,13 @@ const convertContactMethodsToFields = (unverifiedContactMethods) => {
|
|
|
51
43
|
* Retrieves default and custom (RWA only, to be updated) form field values from state machine
|
|
52
44
|
* for subcomponent routes that render fields
|
|
53
45
|
*/
|
|
54
|
-
const getMachineFields = (route, state,
|
|
46
|
+
const getMachineFields = (route, state, unverifiedUserAttributes) => {
|
|
55
47
|
if (isComponentRouteKey(route)) {
|
|
56
48
|
return route === 'verifyUser'
|
|
57
|
-
? convertContactMethodsToFields(
|
|
49
|
+
? convertContactMethodsToFields(unverifiedUserAttributes)
|
|
58
50
|
: flattenFormFields(getSortedFormFields(route, state));
|
|
59
51
|
}
|
|
60
52
|
return [];
|
|
61
53
|
};
|
|
62
54
|
|
|
63
|
-
export { areSelectorDepsEqual, defaultComparator, getComparator, getMachineFields, getQRFields
|
|
55
|
+
export { areSelectorDepsEqual, defaultComparator, getComparator, getMachineFields, getQRFields };
|
|
@@ -18,8 +18,8 @@ const CONFIRM_RESET_PASSWORD_MACHINE_KEYS = [
|
|
|
18
18
|
];
|
|
19
19
|
const CONFIRM_SIGN_IN_MACHINE_KEYS = [
|
|
20
20
|
...COMMON_ROUTE_MACHINE_KEYS,
|
|
21
|
+
'challengeName',
|
|
21
22
|
'toSignIn',
|
|
22
|
-
'user',
|
|
23
23
|
];
|
|
24
24
|
const CONFIRM_SIGN_UP_MACHINE_KEYS = [
|
|
25
25
|
...COMMON_ROUTE_MACHINE_KEYS,
|
|
@@ -42,13 +42,15 @@ const RESET_PASSWORD_MACHINE_KEYS = [
|
|
|
42
42
|
];
|
|
43
43
|
const SIGN_IN_MACHINE_KEYS = [
|
|
44
44
|
...COMMON_ROUTE_MACHINE_KEYS,
|
|
45
|
+
'socialProviders',
|
|
45
46
|
'toFederatedSignIn',
|
|
46
|
-
'
|
|
47
|
+
'toForgotPassword',
|
|
47
48
|
'toSignUp',
|
|
48
49
|
];
|
|
49
50
|
const SIGN_UP_MACHINE_KEYS = [
|
|
50
51
|
...COMMON_ROUTE_MACHINE_KEYS,
|
|
51
52
|
'hasValidationErrors',
|
|
53
|
+
'socialProviders',
|
|
52
54
|
'toSignIn',
|
|
53
55
|
'validationErrors',
|
|
54
56
|
];
|
|
@@ -56,6 +58,7 @@ const SETUP_TOTP_MACHINE_KEYS = [
|
|
|
56
58
|
...COMMON_ROUTE_MACHINE_KEYS,
|
|
57
59
|
'toSignIn',
|
|
58
60
|
'totpSecretCode',
|
|
61
|
+
'username',
|
|
59
62
|
];
|
|
60
63
|
const VERIFY_USER_MACHINE_KEYS = [
|
|
61
64
|
...COMMON_ROUTE_MACHINE_KEYS,
|
|
@@ -69,8 +72,8 @@ const MACHINE_PROP_KEYS = {
|
|
|
69
72
|
forceNewPassword: FORCE_NEW_PASSWORD_MACHINE_KEYS,
|
|
70
73
|
signIn: SIGN_IN_MACHINE_KEYS,
|
|
71
74
|
signUp: SIGN_UP_MACHINE_KEYS,
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
forgotPassword: RESET_PASSWORD_MACHINE_KEYS,
|
|
76
|
+
setupTotp: SETUP_TOTP_MACHINE_KEYS,
|
|
74
77
|
verifyUser: VERIFY_USER_MACHINE_KEYS,
|
|
75
78
|
};
|
|
76
79
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
import useAuthenticator from '../useAuthenticator/useAuthenticator.mjs';
|
|
3
|
-
import { getRouteMachineSelector, resolveDefault, resolveVerifyUserRoute, resolveSignUpRoute, resolveSignInRoute,
|
|
3
|
+
import { getRouteMachineSelector, resolveDefault, resolveVerifyUserRoute, resolveSignUpRoute, resolveSignInRoute, resolveSetupTotpRoute, resolveForgotPasswordRoute, resolveForceNewPasswordRoute, resolveConfirmVerifyUserRoute, resolveConfirmSignUpRoute, resolveConfirmSignInRoute, resolveConfirmResetPasswordRoute, routeSelector } from './utils.mjs';
|
|
4
4
|
|
|
5
5
|
function useAuthenticatorRoute({ components, }) {
|
|
6
6
|
const { route } = useAuthenticator(routeSelector);
|
|
@@ -11,7 +11,7 @@ function useAuthenticatorRoute({ components, }) {
|
|
|
11
11
|
// Only state machine props specified by the current `routeSelector` will have their current value
|
|
12
12
|
// returned by `useAuthenticator`, non-machine props returned will always be the current value
|
|
13
13
|
const routeSelectorProps = useAuthenticator(routeMachineSelector);
|
|
14
|
-
const { ConfirmResetPassword, ConfirmSignIn, ConfirmSignUp, ConfirmVerifyUser, ForceNewPassword,
|
|
14
|
+
const { ConfirmResetPassword, ConfirmSignIn, ConfirmSignUp, ConfirmVerifyUser, ForceNewPassword, ForgotPassword, SetupTotp, SignIn, SignUp, VerifyUser, } = components;
|
|
15
15
|
switch (route) {
|
|
16
16
|
case 'confirmResetPassword': {
|
|
17
17
|
return resolveConfirmResetPasswordRoute(ConfirmResetPassword, routeSelectorProps);
|
|
@@ -28,11 +28,11 @@ function useAuthenticatorRoute({ components, }) {
|
|
|
28
28
|
case 'forceNewPassword': {
|
|
29
29
|
return resolveForceNewPasswordRoute(ForceNewPassword, routeSelectorProps);
|
|
30
30
|
}
|
|
31
|
-
case '
|
|
32
|
-
return
|
|
31
|
+
case 'forgotPassword': {
|
|
32
|
+
return resolveForgotPasswordRoute(ForgotPassword, routeSelectorProps);
|
|
33
33
|
}
|
|
34
|
-
case '
|
|
35
|
-
return
|
|
34
|
+
case 'setupTotp': {
|
|
35
|
+
return resolveSetupTotpRoute(SetupTotp, routeSelectorProps);
|
|
36
36
|
}
|
|
37
37
|
case 'signIn': {
|
|
38
38
|
return resolveSignInRoute(SignIn, routeSelectorProps);
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import 'react';
|
|
2
|
+
import 'react-hook-form';
|
|
3
|
+
import '@aws-amplify/ui';
|
|
4
|
+
import '../../../components/FormCore/FormProvider.mjs';
|
|
2
5
|
import RenderNothing from '../../../components/RenderNothing/RenderNothing.mjs';
|
|
3
6
|
import { isComponentRouteKey } from '../utils.mjs';
|
|
4
7
|
import { MACHINE_PROP_KEYS, EVENT_HANDLER_KEY_MAP } from './constants.mjs';
|
|
@@ -15,47 +18,66 @@ const getRouteMachineSelector = (route) => isComponentRouteKey(route)
|
|
|
15
18
|
: routeSelector;
|
|
16
19
|
const isFormEventHandlerKey = (key) => ['updateBlur', 'updateForm', 'submitForm'].includes(key);
|
|
17
20
|
const convertEventHandlerKey = (key) => EVENT_HANDLER_KEY_MAP[key];
|
|
18
|
-
const getConvertedMachineProps = (route, context) => MACHINE_PROP_KEYS[route].reduce((acc, key) => (
|
|
21
|
+
const getConvertedMachineProps = (route, context) => MACHINE_PROP_KEYS[route].reduce((acc, key) => ({
|
|
22
|
+
...acc,
|
|
23
|
+
[isFormEventHandlerKey(key) ? convertEventHandlerKey(key) : key]: context[key],
|
|
24
|
+
}), {});
|
|
19
25
|
function resolveConfirmResetPasswordRoute(Component, props) {
|
|
20
26
|
return {
|
|
21
27
|
Component,
|
|
22
|
-
props:
|
|
28
|
+
props: {
|
|
29
|
+
...Component,
|
|
30
|
+
...getConvertedMachineProps('confirmResetPassword', props),
|
|
31
|
+
},
|
|
23
32
|
};
|
|
24
33
|
}
|
|
25
34
|
function resolveConfirmSignInRoute(Component, props) {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
const challengeName = user.challengeName;
|
|
29
|
-
return { Component, props: Object.assign(Object.assign(Object.assign({}, Component), machineProps), { challengeName }) };
|
|
35
|
+
const { challengeName, ...machineProps } = getConvertedMachineProps('confirmSignIn', props);
|
|
36
|
+
return { Component, props: { ...Component, ...machineProps, challengeName } };
|
|
30
37
|
}
|
|
31
38
|
function resolveConfirmSignUpRoute(Component, props) {
|
|
32
39
|
return {
|
|
33
40
|
Component,
|
|
34
|
-
props:
|
|
41
|
+
props: {
|
|
42
|
+
...Component,
|
|
43
|
+
...getConvertedMachineProps('confirmSignUp', props),
|
|
44
|
+
},
|
|
35
45
|
};
|
|
36
46
|
}
|
|
37
47
|
function resolveConfirmVerifyUserRoute(Component, props) {
|
|
38
48
|
return {
|
|
39
49
|
Component,
|
|
40
|
-
props:
|
|
50
|
+
props: {
|
|
51
|
+
...Component,
|
|
52
|
+
...getConvertedMachineProps('confirmVerifyUser', props),
|
|
53
|
+
},
|
|
41
54
|
};
|
|
42
55
|
}
|
|
43
56
|
function resolveForceNewPasswordRoute(Component, props) {
|
|
44
57
|
return {
|
|
45
58
|
Component,
|
|
46
|
-
props:
|
|
59
|
+
props: {
|
|
60
|
+
...Component,
|
|
61
|
+
...getConvertedMachineProps('forceNewPassword', props),
|
|
62
|
+
},
|
|
47
63
|
};
|
|
48
64
|
}
|
|
49
|
-
function
|
|
65
|
+
function resolveForgotPasswordRoute(Component, props) {
|
|
50
66
|
return {
|
|
51
67
|
Component,
|
|
52
|
-
props:
|
|
68
|
+
props: {
|
|
69
|
+
...Component,
|
|
70
|
+
...getConvertedMachineProps('forgotPassword', props),
|
|
71
|
+
},
|
|
53
72
|
};
|
|
54
73
|
}
|
|
55
|
-
function
|
|
74
|
+
function resolveSetupTotpRoute(Component, props) {
|
|
56
75
|
return {
|
|
57
76
|
Component,
|
|
58
|
-
props:
|
|
77
|
+
props: {
|
|
78
|
+
...Component,
|
|
79
|
+
...getConvertedMachineProps('setupTotp', props),
|
|
80
|
+
},
|
|
59
81
|
};
|
|
60
82
|
}
|
|
61
83
|
function resolveSignInRoute(Component, props) {
|
|
@@ -63,19 +85,26 @@ function resolveSignInRoute(Component, props) {
|
|
|
63
85
|
const hideSignUp = false;
|
|
64
86
|
return {
|
|
65
87
|
Component,
|
|
66
|
-
props:
|
|
88
|
+
props: {
|
|
89
|
+
...Component,
|
|
90
|
+
...getConvertedMachineProps('signIn', props),
|
|
91
|
+
hideSignUp,
|
|
92
|
+
},
|
|
67
93
|
};
|
|
68
94
|
}
|
|
69
95
|
function resolveSignUpRoute(Component, props) {
|
|
70
96
|
return {
|
|
71
97
|
Component,
|
|
72
|
-
props:
|
|
98
|
+
props: { ...Component, ...getConvertedMachineProps('signUp', props) },
|
|
73
99
|
};
|
|
74
100
|
}
|
|
75
101
|
function resolveVerifyUserRoute(Component, props) {
|
|
76
102
|
return {
|
|
77
103
|
Component,
|
|
78
|
-
props:
|
|
104
|
+
props: {
|
|
105
|
+
...Component,
|
|
106
|
+
...getConvertedMachineProps('verifyUser', props),
|
|
107
|
+
},
|
|
79
108
|
};
|
|
80
109
|
}
|
|
81
110
|
function resolveDefault() {
|
|
@@ -85,4 +114,4 @@ function resolveDefault() {
|
|
|
85
114
|
};
|
|
86
115
|
}
|
|
87
116
|
|
|
88
|
-
export { getRouteMachineSelector, resolveConfirmResetPasswordRoute, resolveConfirmSignInRoute, resolveConfirmSignUpRoute, resolveConfirmVerifyUserRoute, resolveDefault, resolveForceNewPasswordRoute,
|
|
117
|
+
export { getRouteMachineSelector, resolveConfirmResetPasswordRoute, resolveConfirmSignInRoute, resolveConfirmSignUpRoute, resolveConfirmVerifyUserRoute, resolveDefault, resolveForceNewPasswordRoute, resolveForgotPasswordRoute, resolveSetupTotpRoute, resolveSignInRoute, resolveSignUpRoute, resolveVerifyUserRoute, routeSelector };
|
|
@@ -9,7 +9,7 @@ function resolveAuthenticatorComponents(defaults, overrides) {
|
|
|
9
9
|
const Default = defaults[route];
|
|
10
10
|
const Override = overrides[route];
|
|
11
11
|
if (typeof Override !== 'function') {
|
|
12
|
-
return
|
|
12
|
+
return { ...components, [route]: Default };
|
|
13
13
|
}
|
|
14
14
|
const { Footer, FormFields, Header } = Default;
|
|
15
15
|
// cast to allow assigning of component slots
|
|
@@ -17,7 +17,7 @@ function resolveAuthenticatorComponents(defaults, overrides) {
|
|
|
17
17
|
Component.Footer = Footer;
|
|
18
18
|
Component.FormFields = FormFields;
|
|
19
19
|
Component.Header = Header;
|
|
20
|
-
return
|
|
20
|
+
return { ...components, [route]: Component };
|
|
21
21
|
}, {});
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { useForm, FormProvider as FormProvider$1 } from 'react-hook-form';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_MODE = 'onTouched';
|
|
5
|
+
const FormProvider = React__default.forwardRef(function FormProvider({ children, defaultValues, mode = DEFAULT_MODE }, ref) {
|
|
6
|
+
const formProviderProps = useForm({
|
|
7
|
+
defaultValues,
|
|
8
|
+
mode,
|
|
9
|
+
});
|
|
10
|
+
const { getValues, reset } = formProviderProps;
|
|
11
|
+
React__default.useImperativeHandle(ref, () => ({ getValues, reset: () => reset(defaultValues) }), [defaultValues, getValues, reset]);
|
|
12
|
+
return (React__default.createElement(FormProvider$1, { ...formProviderProps }, children));
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export { FormProvider as default };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import useForm from './useForm.mjs';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_ERROR_MESSAGE = '`useField` must be used within a `FormProvider`';
|
|
4
|
+
/**
|
|
5
|
+
* `Field` integration hook for usage with React `Field` components.
|
|
6
|
+
*
|
|
7
|
+
* @param params Requires `name`, all additional params optional
|
|
8
|
+
* @returns `Form` aware `Field` event handlers and state values
|
|
9
|
+
*/
|
|
10
|
+
function useField(params) {
|
|
11
|
+
const { getFieldState, registerField } = useForm({
|
|
12
|
+
errorMessage: DEFAULT_ERROR_MESSAGE,
|
|
13
|
+
});
|
|
14
|
+
return {
|
|
15
|
+
...registerField(params),
|
|
16
|
+
...getFieldState(params.name),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { DEFAULT_ERROR_MESSAGE, useField as default };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { useFormContext } from 'react-hook-form';
|
|
3
|
+
import { noop } from '@aws-amplify/ui';
|
|
4
|
+
|
|
5
|
+
const DEFAULT_ERROR_MESSAGE = '`useForm` must be called inside a `FormProvider`';
|
|
6
|
+
/**
|
|
7
|
+
* Utility hook corresponding to `FormProvider`, must be used within a `FormProvider`
|
|
8
|
+
*
|
|
9
|
+
* @internal Extend for public export. `useForm` and `UseForm` are an abstraction layer
|
|
10
|
+
* on top of `useFormContext` and `UseFormReturn`, imported from `react-hook-form`
|
|
11
|
+
*
|
|
12
|
+
* @param options optional parameters
|
|
13
|
+
* @returns `Form` utilities
|
|
14
|
+
*/
|
|
15
|
+
function useForm(options = {}) {
|
|
16
|
+
const formContext = useFormContext();
|
|
17
|
+
const { errorMessage, onSubmit: _onSubmit } = options;
|
|
18
|
+
if (!formContext) {
|
|
19
|
+
throw new Error(errorMessage ?? DEFAULT_ERROR_MESSAGE);
|
|
20
|
+
}
|
|
21
|
+
const { formState, getFieldState: _getFieldState, getValues, handleSubmit, register, reset, setValue, } = formContext;
|
|
22
|
+
// Do not memoize, `formState` updates on all events
|
|
23
|
+
const getFieldState = (name) => {
|
|
24
|
+
const { error, ...fieldState } = _getFieldState(name, formState);
|
|
25
|
+
const { message: errorMessage } = error ?? {};
|
|
26
|
+
return { ...fieldState, errorMessage, hasError: !!errorMessage };
|
|
27
|
+
};
|
|
28
|
+
// memoize `registerField` and `setFormValue` together,
|
|
29
|
+
// `register` and `setValue` maintain stable references
|
|
30
|
+
const { registerField, setFormValue } = React__default.useMemo(() => {
|
|
31
|
+
return {
|
|
32
|
+
registerField: ({ name, ...options }) => register(name, options),
|
|
33
|
+
setFormValue: ({ name, value, ...options }) => setValue(name, value, options),
|
|
34
|
+
};
|
|
35
|
+
}, [register, setValue]);
|
|
36
|
+
const onSubmit = React__default.useCallback((event) => {
|
|
37
|
+
const handler = _onSubmit ? handleSubmit(_onSubmit) : noop;
|
|
38
|
+
handler(event);
|
|
39
|
+
}, [_onSubmit, handleSubmit]);
|
|
40
|
+
return {
|
|
41
|
+
getFieldState,
|
|
42
|
+
getValues,
|
|
43
|
+
isValid: formState.isValid,
|
|
44
|
+
onSubmit,
|
|
45
|
+
registerField,
|
|
46
|
+
reset,
|
|
47
|
+
setFormValue,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { DEFAULT_ERROR_MESSAGE, useForm as default };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import FormProvider from './FormProvider.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @param Child `Form` base component wrapped inside `FormProvider`
|
|
6
|
+
* @returns Composed `Form` component exposing `FormContext` values to descendents
|
|
7
|
+
*/
|
|
8
|
+
function withFormProvider(Child) {
|
|
9
|
+
return React__default.forwardRef(function Form({ defaultValues, mode, ...props }, ref) {
|
|
10
|
+
return (React__default.createElement(FormProvider, { defaultValues: defaultValues, mode: mode, ref: ref },
|
|
11
|
+
React__default.createElement(Child, { ...props })));
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { withFormProvider as default };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { setUserAgent } from '@aws-amplify/ui';
|
|
3
|
+
|
|
4
|
+
function useSetUserAgent({ componentName, packageName, version, }) {
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
const clearUserAgent = setUserAgent({
|
|
7
|
+
componentName,
|
|
8
|
+
packageName,
|
|
9
|
+
version,
|
|
10
|
+
});
|
|
11
|
+
return clearUserAgent;
|
|
12
|
+
}, [componentName, packageName, version]);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { useSetUserAgent as default };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { isTypedFunction } from '@aws-amplify/ui';
|
|
3
|
+
|
|
4
|
+
function useTimeout({ callback, delay, }) {
|
|
5
|
+
const storedCallback = React__default.useRef(callback);
|
|
6
|
+
React__default.useLayoutEffect(() => {
|
|
7
|
+
storedCallback.current = callback;
|
|
8
|
+
}, [callback]);
|
|
9
|
+
React__default.useEffect(() => {
|
|
10
|
+
if (!isTypedFunction(storedCallback.current) || !delay) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const timeoutId = setTimeout(() => {
|
|
14
|
+
storedCallback.current?.();
|
|
15
|
+
}, delay);
|
|
16
|
+
return () => {
|
|
17
|
+
clearTimeout(timeoutId);
|
|
18
|
+
};
|
|
19
|
+
}, [delay]);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { useTimeout as default };
|
package/dist/esm/index.mjs
CHANGED
|
@@ -4,7 +4,14 @@ export { default as useAuthenticator } from './Authenticator/hooks/useAuthentica
|
|
|
4
4
|
export { default as useAuthenticatorRoute } from './Authenticator/hooks/useAuthenticatorRoute/useAuthenticatorRoute.mjs';
|
|
5
5
|
export { default as useAuthenticatorInitMachine } from './Authenticator/hooks/useAuthenticatorInitMachine/useAuthenticatorInitMachine.mjs';
|
|
6
6
|
export { isComponentRouteKey as isAuthenticatorComponentRouteKey, resolveAuthenticatorComponents } from './Authenticator/hooks/utils.mjs';
|
|
7
|
+
export { default as useField } from './components/FormCore/useField.mjs';
|
|
8
|
+
export { default as useForm } from './components/FormCore/useForm.mjs';
|
|
9
|
+
export { default as FormProvider } from './components/FormCore/FormProvider.mjs';
|
|
10
|
+
export { default as withFormProvider } from './components/FormCore/withFormProvider.mjs';
|
|
7
11
|
export { default as RenderNothing } from './components/RenderNothing/RenderNothing.mjs';
|
|
8
12
|
export { default as useDeprecationWarning } from './hooks/useDeprecationWarning.mjs';
|
|
9
13
|
export { default as useHasValueUpdated } from './hooks/useHasValueUpdated.mjs';
|
|
10
14
|
export { default as usePreviousValue } from './hooks/usePreviousValue.mjs';
|
|
15
|
+
export { default as useSetUserAgent } from './hooks/useSetUserAgent.mjs';
|
|
16
|
+
export { default as useTimeout } from './hooks/useTimeout.mjs';
|
|
17
|
+
export { default as createContextUtilities } from './utils/createContextUtilities.mjs';
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { isUndefined, isString } from '@aws-amplify/ui';
|
|
3
|
+
|
|
4
|
+
const INVALID_OPTIONS_MESSAGE = 'an `errorMessage` or a `defaultValue` must be provided in `options`';
|
|
5
|
+
/**
|
|
6
|
+
* Uses `ContextType`/`Name` generics and `options` to create:
|
|
7
|
+
* - `${Name}Context`: React Context of type `ContextType`
|
|
8
|
+
* - `Provider${Name}`: React Context `Provider` component exposing the `ContextType`
|
|
9
|
+
* as optional props
|
|
10
|
+
* - `use${Name}`: Utility Hook exposing the values of `ContextType`. Allows
|
|
11
|
+
* params with `errorMessage` for granular error messaging
|
|
12
|
+
*
|
|
13
|
+
* @template ContextType Type definition of the Context.
|
|
14
|
+
* > For most use cases the keys of `ContextType` should not be optional in
|
|
15
|
+
* preference of explicit `undefined` to avoid optional types on the
|
|
16
|
+
* Utility Hook return
|
|
17
|
+
*
|
|
18
|
+
* @param options Context utility options. Requires a `contextName`, and
|
|
19
|
+
* either a `defaultValue` of `ContextType` **or** an `errorMessage`
|
|
20
|
+
* allowing for differing behaviors of the Utility Hook when used outside a
|
|
21
|
+
* parent `Provider`:
|
|
22
|
+
*
|
|
23
|
+
* - `defaultValue`: Ensures the Utility Hook returns a default value for
|
|
24
|
+
* scenarios **where the missing context values should not impact usage**
|
|
25
|
+
* - `errorMessage`: Ensures the Utility Hook throws an error for
|
|
26
|
+
* scenarios **where the missing context values should prevent** usage
|
|
27
|
+
*
|
|
28
|
+
* @returns `Context`, `Provider` Component and `useContext` Utility Hook
|
|
29
|
+
*
|
|
30
|
+
* @usage
|
|
31
|
+
* ```ts
|
|
32
|
+
* interface StuffContextType {
|
|
33
|
+
* things: number;
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* // with `defaultValue`
|
|
37
|
+
* const defaultValue: StuffContextType = { things: 7 };
|
|
38
|
+
*
|
|
39
|
+
* const { StuffProvider, useStuff } = createContextUtilities({
|
|
40
|
+
* contextName: 'Stuff',
|
|
41
|
+
* defaultValue,
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* // with `errorMessage`
|
|
45
|
+
* const { StuffProvider, useStuff } = createContextUtilities<StuffContextType>({
|
|
46
|
+
* contextName: 'Stuff',
|
|
47
|
+
* errorMessage: '`useStuff` must be used in a `StuffProvider`'
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
function createContextUtilities(options) {
|
|
52
|
+
const { contextName, defaultValue, errorMessage } = options ?? {};
|
|
53
|
+
if (isUndefined(defaultValue) && !isString(errorMessage)) {
|
|
54
|
+
throw new Error(INVALID_OPTIONS_MESSAGE);
|
|
55
|
+
}
|
|
56
|
+
const Context = React__default.createContext(defaultValue);
|
|
57
|
+
function Provider(props) {
|
|
58
|
+
const { children, ...context } = props;
|
|
59
|
+
const value = React__default.useMemo(() => context,
|
|
60
|
+
// Unpack `context` for the dep array; using `[context]` results in
|
|
61
|
+
// evaluation on every render
|
|
62
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
63
|
+
Object.values(context));
|
|
64
|
+
return React__default.createElement(Context.Provider, { value: value }, children);
|
|
65
|
+
}
|
|
66
|
+
Provider.displayName = `${contextName}Provider`;
|
|
67
|
+
return {
|
|
68
|
+
[`use${contextName}`]: function (params) {
|
|
69
|
+
const context = React__default.useContext(Context);
|
|
70
|
+
if (isUndefined(context)) {
|
|
71
|
+
throw new Error(params?.errorMessage ?? errorMessage);
|
|
72
|
+
}
|
|
73
|
+
return context;
|
|
74
|
+
},
|
|
75
|
+
[`${contextName}Provider`]: Provider,
|
|
76
|
+
[`${contextName}Context`]: Context,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export { INVALID_OPTIONS_MESSAGE, createContextUtilities as default };
|