@aws-amplify/ui-react-native 1.2.19 → 1.2.21
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/CHANGELOG.md +57 -0
- package/dist/Authenticator/Authenticator.d.ts +101 -148
- package/dist/Authenticator/Authenticator.js +7 -3
- package/dist/Authenticator/Defaults/ConfirmResetPassword/ConfirmResetPassword.d.ts +13 -2
- package/dist/Authenticator/Defaults/ConfirmResetPassword/ConfirmResetPassword.js +4 -3
- package/dist/Authenticator/Defaults/ConfirmSignIn/ConfirmSignIn.d.ts +13 -2
- package/dist/Authenticator/Defaults/ConfirmSignIn/ConfirmSignIn.js +4 -3
- package/dist/Authenticator/Defaults/ConfirmSignUp/ConfirmSignUp.d.ts +13 -2
- package/dist/Authenticator/Defaults/ConfirmSignUp/ConfirmSignUp.js +4 -3
- package/dist/Authenticator/Defaults/ConfirmVerifyUser/ConfirmVerifyUser.d.ts +13 -2
- package/dist/Authenticator/Defaults/ConfirmVerifyUser/ConfirmVerifyUser.js +4 -3
- package/dist/Authenticator/Defaults/ForceNewPassword/ForceNewPassword.d.ts +13 -2
- package/dist/Authenticator/Defaults/ForceNewPassword/ForceNewPassword.js +4 -3
- package/dist/Authenticator/Defaults/ResetPassword/ResetPassword.d.ts +13 -2
- package/dist/Authenticator/Defaults/ResetPassword/ResetPassword.js +4 -3
- package/dist/Authenticator/Defaults/SetupTOTP/SetupTOTP.d.ts +13 -2
- package/dist/Authenticator/Defaults/SetupTOTP/SetupTOTP.js +4 -3
- package/dist/Authenticator/Defaults/SignIn/SignIn.d.ts +13 -2
- package/dist/Authenticator/Defaults/SignIn/SignIn.js +4 -3
- package/dist/Authenticator/Defaults/SignUp/SignUp.d.ts +13 -2
- package/dist/Authenticator/Defaults/SignUp/SignUp.js +4 -3
- package/dist/Authenticator/Defaults/VerifyUser/VerifyUser.d.ts +13 -2
- package/dist/Authenticator/Defaults/VerifyUser/VerifyUser.js +4 -3
- package/dist/Authenticator/Defaults/types.d.ts +21 -20
- package/dist/Authenticator/common/DefaultContent/types.d.ts +1 -1
- package/dist/Authenticator/common/DefaultFormFields/DefaultRadioFormFields.d.ts +7 -3
- package/dist/Authenticator/common/DefaultFormFields/DefaultRadioFormFields.js +4 -3
- package/dist/Authenticator/common/DefaultFormFields/DefaultTextFormFields.d.ts +6 -2
- package/dist/Authenticator/common/DefaultFormFields/DefaultTextFormFields.js +3 -3
- package/dist/Authenticator/common/DefaultFormFields/types.d.ts +12 -3
- package/dist/Authenticator/hooks/types.d.ts +3 -2
- package/dist/Authenticator/hooks/useFieldValues/types.d.ts +4 -1
- package/dist/Authenticator/hooks/useFieldValues/useFieldValues.d.ts +1 -1
- package/dist/Authenticator/hooks/useFieldValues/useFieldValues.js +21 -3
- package/dist/Authenticator/hooks/useFieldValues/utils.d.ts +10 -1
- package/dist/Authenticator/hooks/useFieldValues/utils.js +32 -2
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useDeprecationWarning/index.d.ts +1 -0
- package/dist/hooks/useDeprecationWarning/index.js +1 -0
- package/dist/hooks/useDeprecationWarning/useDeprecationWarning.d.ts +6 -0
- package/dist/hooks/useDeprecationWarning/useDeprecationWarning.js +11 -0
- package/dist/primitives/TextField/TextField.js +2 -1
- package/dist/primitives/TextField/styles.js +3 -0
- package/dist/primitives/TextField/types.d.ts +1 -0
- package/dist/theme/createTheme.js +24 -18
- package/dist/theme/types.d.ts +1 -1
- package/dist/utils/platform.d.ts +5 -0
- package/dist/utils/platform.js +2 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/jest.config.js +1 -0
- package/package.json +6 -5
- package/src/Authenticator/Authenticator.tsx +9 -6
- package/src/Authenticator/Defaults/ConfirmResetPassword/ConfirmResetPassword.tsx +7 -3
- package/src/Authenticator/Defaults/ConfirmSignIn/ConfirmSignIn.tsx +7 -3
- package/src/Authenticator/Defaults/ConfirmSignIn/__tests__/ConfirmSignIn.spec.tsx +1 -0
- package/src/Authenticator/Defaults/ConfirmSignUp/ConfirmSignUp.tsx +7 -3
- package/src/Authenticator/Defaults/ConfirmSignUp/__tests__/ConfirmSignUp.spec.tsx +1 -0
- package/src/Authenticator/Defaults/ConfirmVerifyUser/ConfirmVerifyUser.tsx +7 -3
- package/src/Authenticator/Defaults/ConfirmVerifyUser/__tests__/ConfirmVerifyUser.spec.tsx +1 -0
- package/src/Authenticator/Defaults/ForceNewPassword/ForceNewPassword.tsx +7 -3
- package/src/Authenticator/Defaults/ForceNewPassword/__tests__/__snapshots__/ForceNewPassword.spec.tsx.snap +1 -1
- package/src/Authenticator/Defaults/ResetPassword/ResetPassword.tsx +7 -3
- package/src/Authenticator/Defaults/ResetPassword/__tests__/ResetPassword.spec.tsx +1 -0
- package/src/Authenticator/Defaults/SetupTOTP/SetupTOTP.tsx +7 -3
- package/src/Authenticator/Defaults/SetupTOTP/__tests__/SetupTOTP.spec.tsx +1 -0
- package/src/Authenticator/Defaults/SignIn/SignIn.tsx +7 -3
- package/src/Authenticator/Defaults/SignIn/__tests__/SignIn.spec.tsx +1 -0
- package/src/Authenticator/Defaults/SignUp/SignUp.tsx +7 -3
- package/src/Authenticator/Defaults/SignUp/__tests__/__snapshots__/SignUp.spec.tsx.snap +1 -1
- package/src/Authenticator/Defaults/VerifyUser/VerifyUser.tsx +7 -3
- package/src/Authenticator/Defaults/VerifyUser/__tests__/VerifyUser.spec.tsx +1 -0
- package/src/Authenticator/Defaults/types.ts +63 -49
- package/src/Authenticator/__tests__/Authenticator.spec.tsx +16 -19
- package/src/Authenticator/__tests__/__snapshots__/Authenticator.spec.tsx.snap +1 -9
- package/src/Authenticator/__tests__/withAuthenticator.spec.tsx +1 -1
- package/src/Authenticator/common/DefaultContent/types.ts +1 -4
- package/src/Authenticator/common/DefaultFormFields/DefaultRadioFormFields.tsx +8 -6
- package/src/Authenticator/common/DefaultFormFields/DefaultTextFormFields.tsx +10 -7
- package/src/Authenticator/common/DefaultFormFields/types.ts +15 -5
- package/src/Authenticator/hooks/types.ts +3 -0
- package/src/Authenticator/hooks/useFieldValues/__tests__/useFieldValues.spec.ts +75 -2
- package/src/Authenticator/hooks/useFieldValues/__tests__/utils.spec.ts +67 -1
- package/src/Authenticator/hooks/useFieldValues/types.ts +5 -0
- package/src/Authenticator/hooks/useFieldValues/useFieldValues.ts +26 -1
- package/src/Authenticator/hooks/useFieldValues/utils.ts +44 -1
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useDeprecationWarning/__tests__/useDeprecationWarning.spec.ts +42 -0
- package/src/hooks/useDeprecationWarning/index.ts +1 -0
- package/src/hooks/useDeprecationWarning/useDeprecationWarning.ts +21 -0
- package/src/primitives/TextField/TextField.tsx +2 -1
- package/src/primitives/TextField/__tests__/TextField.spec.tsx +57 -8
- package/src/primitives/TextField/__tests__/__snapshots__/TextField.spec.tsx.snap +31 -31
- package/src/primitives/TextField/styles.ts +3 -0
- package/src/primitives/TextField/types.ts +1 -0
- package/src/theme/__tests__/createTheme.spec.ts +48 -0
- package/src/theme/createTheme.ts +44 -21
- package/src/theme/types.ts +17 -16
- package/src/utils/platform.ts +2 -0
- package/src/version.ts +1 -1
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from '../../common';
|
|
10
10
|
import { useFieldValues } from '../../hooks';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { DefaultSignUpProps } from '../types';
|
|
13
13
|
|
|
14
14
|
const COMPONENT_NAME = 'SignUp';
|
|
15
15
|
|
|
@@ -20,7 +20,7 @@ const {
|
|
|
20
20
|
getSignUpTabText,
|
|
21
21
|
} = authenticatorTextUtil;
|
|
22
22
|
|
|
23
|
-
const SignUp
|
|
23
|
+
const SignUp = ({
|
|
24
24
|
fields,
|
|
25
25
|
handleBlur,
|
|
26
26
|
handleChange,
|
|
@@ -29,11 +29,13 @@ const SignUp: DefaultSignUpComponent = ({
|
|
|
29
29
|
hideSignIn,
|
|
30
30
|
isPending,
|
|
31
31
|
toSignIn,
|
|
32
|
+
validationErrors,
|
|
32
33
|
...rest
|
|
33
|
-
}) => {
|
|
34
|
+
}: DefaultSignUpProps): JSX.Element => {
|
|
34
35
|
const {
|
|
35
36
|
disableFormSubmit,
|
|
36
37
|
fields: fieldsWithHandlers,
|
|
38
|
+
fieldValidationErrors,
|
|
37
39
|
handleFormSubmit,
|
|
38
40
|
} = useFieldValues({
|
|
39
41
|
componentName: COMPONENT_NAME,
|
|
@@ -41,6 +43,7 @@ const SignUp: DefaultSignUpComponent = ({
|
|
|
41
43
|
handleBlur,
|
|
42
44
|
handleChange,
|
|
43
45
|
handleSubmit,
|
|
46
|
+
validationErrors,
|
|
44
47
|
});
|
|
45
48
|
|
|
46
49
|
const disabled = hasValidationErrors || disableFormSubmit;
|
|
@@ -78,6 +81,7 @@ const SignUp: DefaultSignUpComponent = ({
|
|
|
78
81
|
fields={fieldsWithHandlers}
|
|
79
82
|
headerText={headerText}
|
|
80
83
|
isPending={isPending}
|
|
84
|
+
validationErrors={fieldValidationErrors}
|
|
81
85
|
/>
|
|
82
86
|
);
|
|
83
87
|
};
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
DefaultRadioFormFields,
|
|
9
9
|
} from '../../common';
|
|
10
10
|
import { useFieldValues } from '../../hooks';
|
|
11
|
-
import {
|
|
11
|
+
import { DefaultVerifyUserProps } from '../types';
|
|
12
12
|
|
|
13
13
|
const COMPONENT_NAME = 'VerifyUser';
|
|
14
14
|
|
|
@@ -19,17 +19,19 @@ const {
|
|
|
19
19
|
getAccountRecoveryInfoText,
|
|
20
20
|
} = authenticatorTextUtil;
|
|
21
21
|
|
|
22
|
-
const VerifyUser
|
|
22
|
+
const VerifyUser = ({
|
|
23
23
|
fields,
|
|
24
24
|
handleBlur,
|
|
25
25
|
handleChange,
|
|
26
26
|
handleSubmit,
|
|
27
27
|
skipVerification,
|
|
28
|
+
validationErrors,
|
|
28
29
|
...rest
|
|
29
|
-
}) => {
|
|
30
|
+
}: DefaultVerifyUserProps): JSX.Element => {
|
|
30
31
|
const {
|
|
31
32
|
disableFormSubmit: disabled,
|
|
32
33
|
fields: fieldsWithHandlers,
|
|
34
|
+
fieldValidationErrors,
|
|
33
35
|
handleFormSubmit,
|
|
34
36
|
} = useFieldValues({
|
|
35
37
|
componentName: COMPONENT_NAME,
|
|
@@ -37,6 +39,7 @@ const VerifyUser: DefaultVerifyUserComponent = ({
|
|
|
37
39
|
handleBlur,
|
|
38
40
|
handleChange,
|
|
39
41
|
handleSubmit,
|
|
42
|
+
validationErrors,
|
|
40
43
|
});
|
|
41
44
|
|
|
42
45
|
const headerText = getVerifyContactText();
|
|
@@ -59,6 +62,7 @@ const VerifyUser: DefaultVerifyUserComponent = ({
|
|
|
59
62
|
buttons={buttons}
|
|
60
63
|
fields={fieldsWithHandlers}
|
|
61
64
|
headerText={headerText}
|
|
65
|
+
validationErrors={fieldValidationErrors}
|
|
62
66
|
/>
|
|
63
67
|
);
|
|
64
68
|
};
|
|
@@ -21,55 +21,69 @@ export type DefaultComponents<
|
|
|
21
21
|
Props = {}
|
|
22
22
|
> = AuthenticatorComponentDefaults<FieldType, Props>;
|
|
23
23
|
|
|
24
|
-
export type
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
>['
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
export type
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
24
|
+
export type DefaultConfirmResetPasswordProps = React.ComponentPropsWithoutRef<
|
|
25
|
+
DefaultComponents<
|
|
26
|
+
TextFieldOptionsType,
|
|
27
|
+
{ style?: ConfirmResetPasswordStyle }
|
|
28
|
+
>['ConfirmResetPassword']
|
|
29
|
+
>;
|
|
30
|
+
|
|
31
|
+
export type DefaultConfirmSignInProps = React.ComponentPropsWithoutRef<
|
|
32
|
+
DefaultComponents<
|
|
33
|
+
TextFieldOptionsType,
|
|
34
|
+
{ style?: ConfirmSignInStyle }
|
|
35
|
+
>['ConfirmSignIn']
|
|
36
|
+
>;
|
|
37
|
+
|
|
38
|
+
export type DefaultConfirmSignUpProps = React.ComponentPropsWithoutRef<
|
|
39
|
+
DefaultComponents<
|
|
40
|
+
TextFieldOptionsType,
|
|
41
|
+
{ style?: ConfirmSignUpStyle }
|
|
42
|
+
>['ConfirmSignUp']
|
|
43
|
+
>;
|
|
44
|
+
|
|
45
|
+
export type DefaultConfirmVerifyUserProps = React.ComponentPropsWithoutRef<
|
|
46
|
+
DefaultComponents<
|
|
47
|
+
TextFieldOptionsType,
|
|
48
|
+
{ style?: ConfirmVerifyUserStyle }
|
|
49
|
+
>['ConfirmVerifyUser']
|
|
50
|
+
>;
|
|
51
|
+
|
|
52
|
+
export type DefaultForceNewPasswordProps = React.ComponentPropsWithoutRef<
|
|
53
|
+
DefaultComponents<
|
|
54
|
+
TextFieldOptionsType,
|
|
55
|
+
{ style?: ForceNewPasswordStyle }
|
|
56
|
+
>['ForceNewPassword']
|
|
57
|
+
>;
|
|
58
|
+
|
|
59
|
+
export type DefaultResetPasswordProps = React.ComponentPropsWithoutRef<
|
|
60
|
+
DefaultComponents<
|
|
61
|
+
TextFieldOptionsType,
|
|
62
|
+
{ style?: ResetPasswordStyle }
|
|
63
|
+
>['ResetPassword']
|
|
64
|
+
>;
|
|
65
|
+
|
|
66
|
+
export type DefaultSetupTOTPProps = React.ComponentPropsWithoutRef<
|
|
67
|
+
DefaultComponents<
|
|
68
|
+
TextFieldOptionsType,
|
|
69
|
+
{ style?: SetupTOTPStyle }
|
|
70
|
+
>['SetupTOTP']
|
|
71
|
+
>;
|
|
72
|
+
|
|
73
|
+
export type DefaultSignInProps = React.ComponentPropsWithoutRef<
|
|
74
|
+
DefaultComponents<TextFieldOptionsType, { style?: SignInStyle }>['SignIn']
|
|
75
|
+
>;
|
|
76
|
+
|
|
77
|
+
export type DefaultSignUpProps = React.ComponentPropsWithoutRef<
|
|
78
|
+
DefaultComponents<TextFieldOptionsType, { style?: SignUpStyle }>['SignUp']
|
|
79
|
+
>;
|
|
80
|
+
|
|
81
|
+
export type DefaultVerifyUserProps = React.ComponentPropsWithoutRef<
|
|
82
|
+
DefaultComponents<
|
|
83
|
+
RadioFieldOptions,
|
|
84
|
+
{ style?: VerifyUserStyle }
|
|
85
|
+
>['VerifyUser']
|
|
86
|
+
>;
|
|
73
87
|
|
|
74
88
|
/**
|
|
75
89
|
* Custom Authenticator components
|
|
@@ -81,30 +81,27 @@ describe('Authenticator', () => {
|
|
|
81
81
|
expect(toJSON()).toMatchSnapshot();
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
-
it
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
() => ({ route } as unknown as UseAuthenticator)
|
|
89
|
-
);
|
|
84
|
+
it('handles `authStatus` of authenticated as expected', () => {
|
|
85
|
+
useAuthenticatorSpy.mockImplementation(
|
|
86
|
+
() => ({ authStatus: 'authenticated' } as unknown as UseAuthenticator)
|
|
87
|
+
);
|
|
90
88
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
89
|
+
const { getByTestId, toJSON } = render(
|
|
90
|
+
<Authenticator>
|
|
91
|
+
<TestChildren />
|
|
92
|
+
</Authenticator>
|
|
93
|
+
);
|
|
96
94
|
|
|
97
|
-
|
|
95
|
+
const children = getByTestId(CHILD_TEST_ID);
|
|
98
96
|
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
expect(children.type).toBe('Text');
|
|
98
|
+
expect(children.props.children).toBe(CHILD_CONTENT);
|
|
101
99
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
);
|
|
100
|
+
expect(toJSON()).toMatchSnapshot();
|
|
101
|
+
});
|
|
105
102
|
|
|
106
|
-
it.each(['
|
|
107
|
-
'handles
|
|
103
|
+
it.each(['unauthenticated', 'configuring'])(
|
|
104
|
+
'handles an authStatus of %s as expected',
|
|
108
105
|
(route) => {
|
|
109
106
|
useAuthenticatorSpy.mockImplementation(
|
|
110
107
|
() => ({ route } as unknown as UseAuthenticator)
|
|
@@ -59,15 +59,7 @@ exports[`Authenticator behaves as expected in the happy path 1`] = `
|
|
|
59
59
|
</SafeAreaProvider>
|
|
60
60
|
`;
|
|
61
61
|
|
|
62
|
-
exports[`Authenticator handles
|
|
63
|
-
<Text
|
|
64
|
-
testID="child-test-id"
|
|
65
|
-
>
|
|
66
|
-
Test Children
|
|
67
|
-
</Text>
|
|
68
|
-
`;
|
|
69
|
-
|
|
70
|
-
exports[`Authenticator handles the signOut route as expected with children 1`] = `
|
|
62
|
+
exports[`Authenticator handles \`authStatus\` of authenticated as expected 1`] = `
|
|
71
63
|
<Text
|
|
72
64
|
testID="child-test-id"
|
|
73
65
|
>
|
|
@@ -60,10 +60,7 @@ export type DefaultContentProps<
|
|
|
60
60
|
| TextFieldOptionsType
|
|
61
61
|
| RadioFieldOptions
|
|
62
62
|
| unknown = unknown
|
|
63
|
-
> = Pick<
|
|
64
|
-
DefaultComponentProps<FieldsType>,
|
|
65
|
-
'error' | 'Footer' | 'isPending'
|
|
66
|
-
> & {
|
|
63
|
+
> = Pick<DefaultComponentProps<FieldsType>, 'error' | 'isPending'> & {
|
|
67
64
|
buttons: DefaultButtons;
|
|
68
65
|
body?: React.ReactNode;
|
|
69
66
|
fields: FieldsType[];
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { censorAllButFirstAndLast, censorPhoneNumber } from '@aws-amplify/ui';
|
|
3
3
|
|
|
4
4
|
import { Radio, RadioGroup } from '../../../primitives';
|
|
5
|
-
import {
|
|
5
|
+
import { DefaultRadioFormFieldsProps } from './types';
|
|
6
6
|
|
|
7
7
|
const censorContactInformation = (name: string, value: string): string => {
|
|
8
8
|
let censoredVal = value;
|
|
@@ -17,16 +17,16 @@ const censorContactInformation = (name: string, value: string): string => {
|
|
|
17
17
|
return censoredVal;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const DefaultRadioFormFields = ({
|
|
21
21
|
fields,
|
|
22
|
-
isPending,
|
|
23
22
|
fieldContainerStyle,
|
|
24
23
|
fieldLabelStyle,
|
|
24
|
+
isPending,
|
|
25
25
|
style,
|
|
26
|
-
}) => {
|
|
26
|
+
}: DefaultRadioFormFieldsProps): JSX.Element => {
|
|
27
27
|
return (
|
|
28
28
|
<RadioGroup disabled={isPending} style={style}>
|
|
29
|
-
{fields.map(({ name, value, ...props }) => (
|
|
29
|
+
{(fields ?? []).map(({ name, value, ...props }) => (
|
|
30
30
|
<Radio
|
|
31
31
|
{...props}
|
|
32
32
|
key={value}
|
|
@@ -42,4 +42,6 @@ const DefaultFormFields: DefaultRadioFormFieldsComponent = ({
|
|
|
42
42
|
);
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
DefaultRadioFormFields.displayName = 'FormFields';
|
|
46
|
+
|
|
47
|
+
export default DefaultRadioFormFields;
|
|
@@ -5,19 +5,22 @@ import { getErrors } from '@aws-amplify/ui';
|
|
|
5
5
|
|
|
6
6
|
import Field from './Field';
|
|
7
7
|
import { FieldErrors } from './FieldErrors';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
// DefaultTextFormFieldsComponent,
|
|
10
|
+
DefaultTextFormFieldsProps,
|
|
11
|
+
} from './types';
|
|
9
12
|
|
|
10
|
-
const DefaultTextFormFields
|
|
13
|
+
const DefaultTextFormFields = ({
|
|
11
14
|
fieldContainerStyle,
|
|
12
15
|
fieldErrorsContainer,
|
|
13
16
|
fieldErrorStyle,
|
|
14
17
|
fieldStyle,
|
|
15
|
-
fields
|
|
16
|
-
isPending,
|
|
18
|
+
fields,
|
|
19
|
+
isPending = false,
|
|
17
20
|
style,
|
|
18
21
|
validationErrors,
|
|
19
|
-
}) => {
|
|
20
|
-
const formFields = fields.map(({ name, type, ...field }) => {
|
|
22
|
+
}: DefaultTextFormFieldsProps): JSX.Element => {
|
|
23
|
+
const formFields = (fields ?? []).map(({ name, type, ...field }) => {
|
|
21
24
|
const errors = validationErrors ? getErrors(validationErrors?.[name]) : [];
|
|
22
25
|
|
|
23
26
|
const hasError = errors?.length > 0;
|
|
@@ -44,6 +47,6 @@ const DefaultTextFormFields: DefaultTextFormFieldsComponent = ({
|
|
|
44
47
|
return <View style={style}>{formFields}</View>;
|
|
45
48
|
};
|
|
46
49
|
|
|
47
|
-
DefaultTextFormFields.displayName = '
|
|
50
|
+
DefaultTextFormFields.displayName = 'FormFields';
|
|
48
51
|
|
|
49
52
|
export default DefaultTextFormFields;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { StyleProp, TextStyle, ViewStyle } from 'react-native';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AuthenticatorFormFieldsComponent,
|
|
4
|
+
UseAuthenticator,
|
|
5
|
+
} from '@aws-amplify/ui-react-core';
|
|
3
6
|
|
|
4
7
|
import { RadioFieldOptions, TextFieldOptionsType } from '../../hooks';
|
|
5
8
|
|
|
@@ -25,8 +28,15 @@ export interface DefaultFormFieldsStyle {
|
|
|
25
28
|
export type DefaultFormFieldsComponent<FieldsType> =
|
|
26
29
|
AuthenticatorFormFieldsComponent<FieldsType, DefaultFormFieldsStyle>;
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
interface FormFieldsProps extends DefaultFormFieldsStyle {
|
|
32
|
+
isPending?: UseAuthenticator['isPending'];
|
|
33
|
+
validationErrors?: UseAuthenticator['validationErrors'];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface DefaultTextFormFieldsProps extends FormFieldsProps {
|
|
37
|
+
fields?: TextFieldOptionsType[];
|
|
38
|
+
}
|
|
30
39
|
|
|
31
|
-
export
|
|
32
|
-
|
|
40
|
+
export interface DefaultRadioFormFieldsProps extends FormFieldsProps {
|
|
41
|
+
fields?: RadioFieldOptions[];
|
|
42
|
+
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
|
|
8
8
|
export type MachineFieldTypeKey = 'password' | 'tel';
|
|
9
9
|
export type AuthenticatorFieldTypeKey =
|
|
10
|
+
| 'email'
|
|
10
11
|
| 'password'
|
|
11
12
|
| 'phone'
|
|
12
13
|
| 'default'
|
|
@@ -23,10 +24,12 @@ type FieldOptions<FieldProps, Type extends AuthenticatorFieldTypeKey> = {
|
|
|
23
24
|
type: Type;
|
|
24
25
|
} & Omit<FieldProps, 'disabled' | 'onBlur'>;
|
|
25
26
|
|
|
27
|
+
type EmailFieldOptions = FieldOptions<PhoneNumberFieldProps, 'email'>;
|
|
26
28
|
type PasswordFieldOptions = FieldOptions<PasswordFieldProps, 'password'>;
|
|
27
29
|
type PhoneFieldOptions = FieldOptions<PhoneNumberFieldProps, 'phone'>;
|
|
28
30
|
type DefaultFieldOptions = FieldOptions<TextFieldProps, 'default'>;
|
|
29
31
|
export type TextFieldOptionsType = (
|
|
32
|
+
| EmailFieldOptions
|
|
30
33
|
| PasswordFieldOptions
|
|
31
34
|
| PhoneFieldOptions
|
|
32
35
|
| DefaultFieldOptions
|
|
@@ -2,7 +2,10 @@ import { act, renderHook } from '@testing-library/react-hooks';
|
|
|
2
2
|
import { NativeSyntheticEvent, TextInputFocusEventData } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import { Logger } from 'aws-amplify';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
UnverifiedContactMethodType,
|
|
7
|
+
authenticatorTextUtil,
|
|
8
|
+
} from '@aws-amplify/ui';
|
|
6
9
|
import {
|
|
7
10
|
RadioFieldOptions,
|
|
8
11
|
TextFieldOptionsType,
|
|
@@ -58,6 +61,7 @@ describe('useFieldValues', () => {
|
|
|
58
61
|
value: undefined,
|
|
59
62
|
},
|
|
60
63
|
],
|
|
64
|
+
fieldValidationErrors: {},
|
|
61
65
|
handleFormSubmit: expect.any(Function),
|
|
62
66
|
});
|
|
63
67
|
});
|
|
@@ -80,6 +84,7 @@ describe('useFieldValues', () => {
|
|
|
80
84
|
value: undefined,
|
|
81
85
|
},
|
|
82
86
|
],
|
|
87
|
+
fieldValidationErrors: {},
|
|
83
88
|
handleFormSubmit: expect.any(Function),
|
|
84
89
|
});
|
|
85
90
|
});
|
|
@@ -95,6 +100,7 @@ describe('useFieldValues', () => {
|
|
|
95
100
|
expect(result.current).toStrictEqual({
|
|
96
101
|
disableFormSubmit: true,
|
|
97
102
|
fields: [{ ...radioField, onChange: expect.any(Function) }],
|
|
103
|
+
fieldValidationErrors: {},
|
|
98
104
|
handleFormSubmit: expect.any(Function),
|
|
99
105
|
});
|
|
100
106
|
});
|
|
@@ -105,6 +111,7 @@ describe('useFieldValues', () => {
|
|
|
105
111
|
expect(result.current).toStrictEqual({
|
|
106
112
|
disableFormSubmit: false,
|
|
107
113
|
fields: mockfields,
|
|
114
|
+
fieldValidationErrors: {},
|
|
108
115
|
handleFormSubmit: expect.any(Function),
|
|
109
116
|
});
|
|
110
117
|
});
|
|
@@ -129,7 +136,9 @@ describe('useFieldValues', () => {
|
|
|
129
136
|
const mockEvent = {
|
|
130
137
|
nativeEvent: { target: 1 },
|
|
131
138
|
} as NativeSyntheticEvent<TextInputFocusEventData>;
|
|
132
|
-
|
|
139
|
+
act(() => {
|
|
140
|
+
result.current.fields[0].onBlur?.(mockEvent);
|
|
141
|
+
});
|
|
133
142
|
expect(props.handleBlur).toHaveBeenCalledTimes(1);
|
|
134
143
|
expect(props.handleBlur).toHaveBeenCalledWith({
|
|
135
144
|
name: textField.name,
|
|
@@ -153,6 +162,68 @@ describe('useFieldValues', () => {
|
|
|
153
162
|
});
|
|
154
163
|
});
|
|
155
164
|
|
|
165
|
+
it('runs validations for email fields', () => {
|
|
166
|
+
const emailField = {
|
|
167
|
+
label: 'test',
|
|
168
|
+
type: 'email',
|
|
169
|
+
name: 'invalid_email',
|
|
170
|
+
value: 'test@',
|
|
171
|
+
} as TextFieldOptionsType;
|
|
172
|
+
const phoneTextField = {
|
|
173
|
+
type: 'phone',
|
|
174
|
+
name: 'testPhone',
|
|
175
|
+
} as TextFieldOptionsType;
|
|
176
|
+
const { result } = renderHook(() =>
|
|
177
|
+
useFieldValues({
|
|
178
|
+
...props,
|
|
179
|
+
fields: [emailField, phoneTextField],
|
|
180
|
+
})
|
|
181
|
+
);
|
|
182
|
+
const mockEvent = {
|
|
183
|
+
nativeEvent: { target: 1 },
|
|
184
|
+
} as NativeSyntheticEvent<TextInputFocusEventData>;
|
|
185
|
+
act(() => {
|
|
186
|
+
result.current.fields[0].onBlur?.(mockEvent);
|
|
187
|
+
});
|
|
188
|
+
expect(props.handleBlur).toHaveBeenCalledTimes(1);
|
|
189
|
+
expect(props.handleBlur).toHaveBeenCalledWith({
|
|
190
|
+
name: emailField.name,
|
|
191
|
+
value: undefined,
|
|
192
|
+
});
|
|
193
|
+
expect(result.current.fieldValidationErrors).toStrictEqual({
|
|
194
|
+
[emailField.name]: [authenticatorTextUtil.getInvalidEmailText()],
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('runs validations for required fields', () => {
|
|
199
|
+
const requiredField = {
|
|
200
|
+
label: 'test',
|
|
201
|
+
type: 'password',
|
|
202
|
+
name: 'required',
|
|
203
|
+
required: true,
|
|
204
|
+
} as TextFieldOptionsType;
|
|
205
|
+
const { result } = renderHook(() =>
|
|
206
|
+
useFieldValues({
|
|
207
|
+
...props,
|
|
208
|
+
fields: [requiredField],
|
|
209
|
+
})
|
|
210
|
+
);
|
|
211
|
+
const mockEvent = {
|
|
212
|
+
nativeEvent: { target: 1 },
|
|
213
|
+
} as NativeSyntheticEvent<TextInputFocusEventData>;
|
|
214
|
+
act(() => {
|
|
215
|
+
result.current.fields[0].onBlur?.(mockEvent);
|
|
216
|
+
});
|
|
217
|
+
expect(props.handleBlur).toHaveBeenCalledTimes(1);
|
|
218
|
+
expect(props.handleBlur).toHaveBeenCalledWith({
|
|
219
|
+
name: requiredField.name,
|
|
220
|
+
value: undefined,
|
|
221
|
+
});
|
|
222
|
+
expect(result.current.fieldValidationErrors).toStrictEqual({
|
|
223
|
+
[requiredField.name]: [authenticatorTextUtil.getRequiredFieldText()],
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
|
|
156
227
|
it('calls expected handlers for radios', () => {
|
|
157
228
|
const { result } = renderHook(() =>
|
|
158
229
|
useFieldValues({
|
|
@@ -234,6 +305,7 @@ describe('useFieldValues', () => {
|
|
|
234
305
|
value: undefined,
|
|
235
306
|
},
|
|
236
307
|
],
|
|
308
|
+
fieldValidationErrors: {},
|
|
237
309
|
handleFormSubmit: expect.any(Function),
|
|
238
310
|
});
|
|
239
311
|
});
|
|
@@ -267,6 +339,7 @@ describe('useFieldValues', () => {
|
|
|
267
339
|
value: mockValue,
|
|
268
340
|
},
|
|
269
341
|
],
|
|
342
|
+
fieldValidationErrors: {},
|
|
270
343
|
handleFormSubmit: expect.any(Function),
|
|
271
344
|
});
|
|
272
345
|
});
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Logger } from 'aws-amplify';
|
|
2
|
-
import {
|
|
2
|
+
import { authenticatorTextUtil } from '@aws-amplify/ui';
|
|
3
3
|
|
|
4
|
+
import { TextFieldOptionsType, TypedField } from '../../types';
|
|
4
5
|
import {
|
|
5
6
|
getRouteTypedFields,
|
|
6
7
|
getSanitizedRadioFields,
|
|
7
8
|
getSanitizedTextFields,
|
|
9
|
+
runFieldValidation,
|
|
8
10
|
} from '../utils';
|
|
9
11
|
|
|
10
12
|
const warnSpy = jest.spyOn(Logger.prototype, 'warn');
|
|
@@ -214,3 +216,67 @@ describe('getRouteTypedFields', () => {
|
|
|
214
216
|
expect(fields).toStrictEqual(expected);
|
|
215
217
|
});
|
|
216
218
|
});
|
|
219
|
+
|
|
220
|
+
describe('runFieldValidation', () => {
|
|
221
|
+
const { getInvalidEmailText, getRequiredFieldText } = authenticatorTextUtil;
|
|
222
|
+
const field: TextFieldOptionsType = {
|
|
223
|
+
required: true,
|
|
224
|
+
type: 'email',
|
|
225
|
+
name: 'email',
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
it('should return an empty array when no errors are found', () => {
|
|
229
|
+
const value = 'test@example.com';
|
|
230
|
+
const stateValidations = {};
|
|
231
|
+
|
|
232
|
+
const result = runFieldValidation(field, value, stateValidations);
|
|
233
|
+
|
|
234
|
+
expect(result).toEqual([]);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('should return an array with the required field error when value is missing', () => {
|
|
238
|
+
const value = undefined;
|
|
239
|
+
const stateValidations = {};
|
|
240
|
+
|
|
241
|
+
const result = runFieldValidation(field, value, stateValidations);
|
|
242
|
+
|
|
243
|
+
expect(result).toEqual([getRequiredFieldText(), getInvalidEmailText()]);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('should return an array with the invalid email error when email value is invalid', () => {
|
|
247
|
+
const value = 'invalid-email';
|
|
248
|
+
const stateValidations = {};
|
|
249
|
+
|
|
250
|
+
const result = runFieldValidation(field, value, stateValidations);
|
|
251
|
+
|
|
252
|
+
expect(result).toEqual([getInvalidEmailText()]);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('should include state machine validation errors in the result', () => {
|
|
256
|
+
const value = 'test@example.com';
|
|
257
|
+
const errorMessage = 'Email already exists.';
|
|
258
|
+
const stateValidations = {
|
|
259
|
+
email: errorMessage,
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const result = runFieldValidation(field, value, stateValidations);
|
|
263
|
+
|
|
264
|
+
expect(result).toEqual([errorMessage]);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('should concatenate state machine validation errors with other errors', () => {
|
|
268
|
+
const value = undefined;
|
|
269
|
+
const errorMessage = 'Email already exists.';
|
|
270
|
+
const stateValidations = {
|
|
271
|
+
email: errorMessage,
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const result = runFieldValidation(field, value, stateValidations);
|
|
275
|
+
|
|
276
|
+
expect(result).toEqual([
|
|
277
|
+
getRequiredFieldText(),
|
|
278
|
+
getInvalidEmailText(),
|
|
279
|
+
errorMessage,
|
|
280
|
+
]);
|
|
281
|
+
});
|
|
282
|
+
});
|