@aws-amplify/ui-react-core 2.1.32 → 3.0.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.
Files changed (82) hide show
  1. package/dist/esm/Authenticator/context/AuthenticatorProvider.mjs +5 -6
  2. package/dist/esm/Authenticator/hooks/constants.mjs +4 -4
  3. package/dist/esm/Authenticator/hooks/useAuthenticator/useAuthenticator.mjs +14 -11
  4. package/dist/esm/Authenticator/hooks/useAuthenticator/utils.mjs +10 -18
  5. package/dist/esm/Authenticator/hooks/useAuthenticatorRoute/constants.mjs +7 -4
  6. package/dist/esm/Authenticator/hooks/useAuthenticatorRoute/useAuthenticatorRoute.mjs +6 -6
  7. package/dist/esm/Authenticator/hooks/useAuthenticatorRoute/utils.mjs +47 -18
  8. package/dist/esm/Authenticator/hooks/utils.mjs +2 -2
  9. package/dist/esm/components/FormCore/FormProvider.mjs +15 -0
  10. package/dist/esm/components/FormCore/useField.mjs +20 -0
  11. package/dist/esm/components/FormCore/useForm.mjs +51 -0
  12. package/dist/esm/components/FormCore/withFormProvider.mjs +15 -0
  13. package/dist/esm/hooks/useSetUserAgent.mjs +15 -0
  14. package/dist/esm/hooks/useTimeout.mjs +22 -0
  15. package/dist/esm/index.mjs +7 -0
  16. package/dist/esm/utils/createContextUtilities.mjs +80 -0
  17. package/dist/index.js +284 -96
  18. package/dist/types/Authenticator/hooks/types.d.ts +10 -7
  19. package/dist/types/Authenticator/hooks/useAuthenticator/types.d.ts +1 -3
  20. package/dist/types/Authenticator/hooks/useAuthenticator/utils.d.ts +2 -3
  21. package/dist/types/Authenticator/hooks/useAuthenticatorRoute/types.d.ts +3 -3
  22. package/dist/types/Authenticator/hooks/useAuthenticatorRoute/useAuthenticatorRoute.d.ts +2 -2
  23. package/dist/types/Authenticator/hooks/useAuthenticatorRoute/utils.d.ts +2 -2
  24. package/dist/types/components/FormCore/FormProvider.d.ts +4 -0
  25. package/dist/types/components/FormCore/index.d.ts +5 -0
  26. package/dist/types/components/FormCore/types.d.ts +217 -0
  27. package/dist/types/components/FormCore/useControlledField.d.ts +9 -0
  28. package/dist/types/components/FormCore/useField.d.ts +9 -0
  29. package/dist/types/components/FormCore/useForm.d.ts +12 -0
  30. package/dist/types/components/FormCore/withFormProvider.d.ts +8 -0
  31. package/dist/types/components/index.d.ts +1 -0
  32. package/dist/types/hooks/index.d.ts +2 -0
  33. package/dist/types/hooks/useSetUserAgent.d.ts +2 -0
  34. package/dist/types/hooks/useTimeout.d.ts +4 -0
  35. package/dist/types/index.d.ts +3 -2
  36. package/dist/types/types/index.d.ts +1 -1
  37. package/dist/types/types/types.d.ts +2 -0
  38. package/dist/types/utils/createContextUtilities.d.ts +26 -18
  39. package/package.json +11 -29
  40. package/src/Authenticator/context/AuthenticatorContext.tsx +17 -0
  41. package/src/Authenticator/context/AuthenticatorProvider.tsx +82 -0
  42. package/src/Authenticator/context/index.ts +2 -0
  43. package/src/Authenticator/hooks/constants.ts +30 -0
  44. package/src/Authenticator/hooks/index.ts +5 -0
  45. package/src/Authenticator/hooks/types.ts +218 -0
  46. package/src/Authenticator/hooks/useAuthenticator/__mock__/useAuthenticator.ts +66 -0
  47. package/src/Authenticator/hooks/useAuthenticator/constants.ts +2 -0
  48. package/src/Authenticator/hooks/useAuthenticator/index.ts +2 -0
  49. package/src/Authenticator/hooks/useAuthenticator/types.ts +48 -0
  50. package/src/Authenticator/hooks/useAuthenticator/useAuthenticator.ts +72 -0
  51. package/src/Authenticator/hooks/useAuthenticator/utils.ts +97 -0
  52. package/src/Authenticator/hooks/useAuthenticatorInitMachine/index.ts +1 -0
  53. package/src/Authenticator/hooks/useAuthenticatorInitMachine/useAuthenticatorInitMachine.tsx +25 -0
  54. package/src/Authenticator/hooks/useAuthenticatorRoute/constants.ts +107 -0
  55. package/src/Authenticator/hooks/useAuthenticatorRoute/index.ts +2 -0
  56. package/src/Authenticator/hooks/useAuthenticatorRoute/types.ts +111 -0
  57. package/src/Authenticator/hooks/useAuthenticatorRoute/useAuthenticatorRoute.ts +126 -0
  58. package/src/Authenticator/hooks/useAuthenticatorRoute/utils.ts +204 -0
  59. package/src/Authenticator/hooks/utils.ts +38 -0
  60. package/src/Authenticator/index.ts +23 -0
  61. package/src/components/FormCore/FormProvider.tsx +37 -0
  62. package/src/components/FormCore/index.ts +13 -0
  63. package/src/components/FormCore/types.ts +277 -0
  64. package/src/components/FormCore/useControlledField.ts +73 -0
  65. package/src/components/FormCore/useField.ts +25 -0
  66. package/src/components/FormCore/useForm.ts +84 -0
  67. package/src/components/FormCore/withFormProvider.tsx +31 -0
  68. package/src/components/RenderNothing/RenderNothing.tsx +6 -0
  69. package/src/components/RenderNothing/index.ts +1 -0
  70. package/src/components/index.ts +15 -0
  71. package/src/hooks/index.ts +8 -0
  72. package/src/hooks/useDeprecationWarning.ts +27 -0
  73. package/src/hooks/useHasValueUpdated.ts +28 -0
  74. package/src/hooks/usePreviousValue.ts +15 -0
  75. package/src/hooks/useSetUserAgent.ts +18 -0
  76. package/src/hooks/useTimeout.ts +30 -0
  77. package/src/index.ts +48 -0
  78. package/src/types/index.ts +1 -0
  79. package/src/types/types.ts +3 -0
  80. package/src/utils/createContextUtilities.tsx +131 -0
  81. package/src/utils/index.ts +1 -0
  82. package/dist/esm/node_modules/tslib/tslib.es6.mjs +0 -38
@@ -0,0 +1,277 @@
1
+ import React from 'react';
2
+ import { DefaultValues } from 'react-hook-form';
3
+
4
+ export interface FormValues {
5
+ [k: string]: string;
6
+ }
7
+
8
+ export type FocusHandler = (event?: any) => void;
9
+ export type ChangeHandler = (event?: any) => void;
10
+
11
+ export type SubmitHandler<Values extends FormValues = FormValues> = (
12
+ values: Values,
13
+ event?: React.BaseSyntheticEvent
14
+ ) => void;
15
+
16
+ type RefCallback = (node: any) => void;
17
+
18
+ export interface SetFormValueParams<Name extends string = string> {
19
+ /**
20
+ * `Form` value `name`
21
+ */
22
+ name: Name;
23
+
24
+ /**
25
+ * `value` to be applied
26
+ */
27
+ value: string;
28
+
29
+ /**
30
+ * Whether validation should be ran
31
+ */
32
+ shouldValidate?: boolean;
33
+ }
34
+
35
+ type SetFormValue<Name extends string = string> = (
36
+ params: SetFormValueParams<Name>
37
+ ) => void;
38
+
39
+ /**
40
+ * `Field` validator callback
41
+ *
42
+ * @param value current `Field` value`
43
+ * @param values current `Form` values
44
+ * @returns `string` message on invalid `Field`, `undefined` on valid
45
+ */
46
+ export type Validator<Values extends FormValues = FormValues> = (
47
+ value: string,
48
+ values: Values
49
+ ) => string | undefined;
50
+
51
+ export type Validate<Values extends FormValues = FormValues> =
52
+ | Validator<Values>
53
+ | Record<string, Validator<Values>>;
54
+
55
+ export interface RegisterFieldParams<Values extends FormValues = FormValues> {
56
+ disabled?: boolean;
57
+ name: string;
58
+ onBlur?: FocusHandler;
59
+ onChange?: ChangeHandler;
60
+ validate?: Validate<Values>;
61
+ value?: string;
62
+ }
63
+
64
+ export interface UseFormParams<
65
+ Values extends FormValues = FormValues,
66
+ OnSubmit extends SubmitHandler<Values> = SubmitHandler<Values>
67
+ > {
68
+ /**
69
+ * Custom error message provided to `Error` on call to `useForm` outside `FormProvider`
70
+ */
71
+ errorMessage?: string;
72
+
73
+ /**
74
+ * Submit event handler
75
+ */
76
+ onSubmit?: OnSubmit;
77
+ }
78
+
79
+ /**
80
+ * `Form` aware `Field` props to be provided to UI components
81
+ */
82
+ interface RegisterProps<Name extends string = string> {
83
+ disabled?: boolean;
84
+ name: Name;
85
+ onBlur: FocusHandler;
86
+ onChange: ChangeHandler;
87
+ ref: RefCallback;
88
+ }
89
+
90
+ interface FieldState {
91
+ errorMessage: string | undefined;
92
+ hasError: boolean;
93
+ invalid: boolean;
94
+ isDirty: boolean;
95
+ isTouched: boolean;
96
+ }
97
+
98
+ export type UseForm<Values extends FormValues = FormValues> = {
99
+ /**
100
+ * Get `Field` state of `name`
101
+ */
102
+ getFieldState: (name: string) => FieldState;
103
+
104
+ /**
105
+ * Get current `Form` values
106
+ */
107
+ getValues: () => FormValues;
108
+
109
+ /**
110
+ * `Form` validity state
111
+ */
112
+ isValid: boolean;
113
+
114
+ /**
115
+ * Registers `name` to `Form` values, returns `Form` aware `Field` handlers and `ref`
116
+ */
117
+ registerField: (params: RegisterFieldParams) => RegisterProps;
118
+
119
+ /**
120
+ * Reset `Form` values
121
+ */
122
+ reset: (values: Values) => void;
123
+
124
+ /**
125
+ * Sets `Form` value of `name` param to provided `value`
126
+ */
127
+ setFormValue: SetFormValue;
128
+
129
+ /**
130
+ * `Form` submit callback prop
131
+ *
132
+ * @usage
133
+ * ```tsx
134
+ * const { onSubmit } = useForm();
135
+ *
136
+ * <form onSubmit={onSubmit} />
137
+ * ```
138
+ */
139
+ onSubmit: (e?: React.BaseSyntheticEvent) => void;
140
+ };
141
+
142
+ export type FormHandle<Values extends FormValues = FormValues> = {
143
+ /**
144
+ * Get current `Form` values
145
+ */
146
+ getValues: () => Values;
147
+
148
+ /**
149
+ * Reset `Form` values to default values
150
+ */
151
+ reset: () => void;
152
+ };
153
+
154
+ type ValidationMode = 'onBlur' | 'onChange' | 'onSubmit' | 'onTouched' | 'all';
155
+
156
+ export interface FormProviderProps<Values extends FormValues = FormValues> {
157
+ /**
158
+ * `Form` children
159
+ */
160
+ children?: React.ReactNode;
161
+
162
+ /**
163
+ * `Form` default values
164
+ */
165
+ defaultValues?: DefaultValues<Values>;
166
+
167
+ /**
168
+ * Validation mode applied to `Field` components:
169
+ *
170
+ * - `onTouched`: Validate on first blur event and every subsequent change event
171
+ * - `onBlur`: validate on blur events only
172
+ * - `onChange`: validate on change events, non-performant
173
+ * - `all`: validate on blur and change events
174
+ *
175
+ * @default
176
+ * "onTouched"
177
+ */
178
+ mode?: ValidationMode;
179
+ }
180
+
181
+ /**
182
+ * For use with React only.
183
+ */
184
+ export interface UseField<Name extends string = string>
185
+ extends FieldState,
186
+ RegisterProps {
187
+ name: Name;
188
+ }
189
+
190
+ /**
191
+ * For use with React only.
192
+ */
193
+ export interface UseFieldParams<
194
+ OnBlur extends FocusHandler | undefined,
195
+ OnChange extends ChangeHandler | undefined,
196
+ Values extends FormValues = FormValues
197
+ > {
198
+ /**
199
+ * Controlled `disabled` state
200
+ */
201
+ disabled?: boolean;
202
+
203
+ /**
204
+ * Controlled blur event handler
205
+ */
206
+ onBlur?: OnBlur;
207
+
208
+ /**
209
+ * Controlled change event handler
210
+ */
211
+ onChange?: OnChange;
212
+
213
+ /**
214
+ * `Field` name, must be unique
215
+ */
216
+ name: string;
217
+
218
+ /**
219
+ * `Field` validation handler. Accepts a callback function or an
220
+ * object of callback functions to validate against
221
+ *
222
+ * @usage
223
+ * ```tsx
224
+ *
225
+ * // validate `password` and `confim_pasword` values match
226
+ * const validate = (value: string, values: Values) =>
227
+ * value === values['confirm_password']
228
+ * ? undefined
229
+ * : 'Passwords must match!';
230
+ *
231
+ *
232
+ * const passwordProps = useField({ name: 'password' });
233
+ *
234
+ * const confirmPasswordProps = useField({
235
+ * name: 'confirm_password',
236
+ * validate
237
+ * });
238
+ *
239
+ * return (
240
+ * <>
241
+ * <TextField {...passwordProps} />
242
+ * <TextField {...confirmPasswordProps} />
243
+ * </>
244
+ * )
245
+ * ```
246
+ */
247
+ validate?: Validate<Values>;
248
+ }
249
+
250
+ /**
251
+ * For use with React Native only.
252
+ */
253
+ export interface UseControlledFieldParams<
254
+ OnBlur extends FocusHandler | undefined,
255
+ Values extends FormValues = FormValues
256
+ > extends Omit<UseFieldParams<OnBlur, undefined, Values>, 'onChange'> {
257
+ /**
258
+ * Controlled text change event handler
259
+ */
260
+ onChangeText?: (value: string) => void;
261
+ }
262
+
263
+ /**
264
+ * For use with React Native only.
265
+ */
266
+ export interface UseControlledField<Name extends string = string>
267
+ extends Omit<UseField<Name>, 'onChange'> {
268
+ name: Name;
269
+
270
+ /**
271
+ * React Native only.
272
+ * Controlled text change event handler
273
+ */
274
+ onChangeText: (value: string) => void;
275
+
276
+ value: string;
277
+ }
@@ -0,0 +1,73 @@
1
+ import { useController } from 'react-hook-form';
2
+
3
+ import {
4
+ FormValues,
5
+ FocusHandler,
6
+ UseControlledField,
7
+ UseControlledFieldParams,
8
+ } from './types';
9
+ import { isTypedFunction } from '@aws-amplify/ui';
10
+
11
+ export const DEFAULT_ERROR_MESSAGE =
12
+ '`useControlledField` must be used within a `FormProvider`';
13
+
14
+ /**
15
+ * `Field` integration hook for usage with React Native `Field` components
16
+ *
17
+ * @param params Requires `name`, all additional params optional
18
+ * @returns `Form` aware `Field` handlers and state values
19
+ */
20
+ export default function useControlledField<OnBlur extends FocusHandler>({
21
+ onBlur: _onBlur,
22
+ onChangeText: _onChangeText,
23
+ ...rest
24
+ }: UseControlledFieldParams<OnBlur>): UseControlledField {
25
+ // If called outside a `FormProvider`, `useController` throws a `TypeError` instead
26
+ // of failing gracefully (for example returning `undefined` or `null`).
27
+ // Wrap call to `useController` in a `try`/`catch` for graceful failure
28
+ let controller;
29
+ try {
30
+ controller = useController<FormValues>(rest);
31
+ } catch {
32
+ throw new Error(DEFAULT_ERROR_MESSAGE);
33
+ }
34
+
35
+ const {
36
+ // `useController.onChange` handles `string` values passed directly to `onChange`
37
+ // for RN support, map to `onChangeText`
38
+ field: { name, onBlur, onChange: onChangeText, ref, value },
39
+ fieldState: { error, isDirty, isTouched },
40
+ formState: { isValid: invalid },
41
+ } = controller;
42
+
43
+ const errorMessage = error?.message;
44
+ const hasError = !!errorMessage;
45
+
46
+ const handleBlur = (event: Parameters<OnBlur>[0]) => {
47
+ if (isTypedFunction(_onBlur)) {
48
+ _onBlur(event);
49
+ }
50
+ // `useController.onBlur` does not receive params
51
+ onBlur();
52
+ };
53
+
54
+ const handleChangeText = (event: string) => {
55
+ if (isTypedFunction(_onChangeText)) {
56
+ _onChangeText(event);
57
+ }
58
+ onChangeText(event);
59
+ };
60
+
61
+ return {
62
+ errorMessage,
63
+ hasError,
64
+ invalid,
65
+ isDirty,
66
+ isTouched,
67
+ name,
68
+ onBlur: handleBlur,
69
+ onChangeText: handleChangeText,
70
+ ref,
71
+ value,
72
+ };
73
+ }
@@ -0,0 +1,25 @@
1
+ import useForm from './useForm';
2
+ import { ChangeHandler, FocusHandler, UseField, UseFieldParams } from './types';
3
+
4
+ export const DEFAULT_ERROR_MESSAGE =
5
+ '`useField` must be used within a `FormProvider`';
6
+
7
+ /**
8
+ * `Field` integration hook for usage with React `Field` components.
9
+ *
10
+ * @param params Requires `name`, all additional params optional
11
+ * @returns `Form` aware `Field` event handlers and state values
12
+ */
13
+ export default function useField<
14
+ OnBlur extends FocusHandler,
15
+ OnChange extends ChangeHandler
16
+ >(params: UseFieldParams<OnBlur, OnChange>): UseField {
17
+ const { getFieldState, registerField } = useForm({
18
+ errorMessage: DEFAULT_ERROR_MESSAGE,
19
+ });
20
+
21
+ return {
22
+ ...registerField(params),
23
+ ...getFieldState(params.name),
24
+ };
25
+ }
@@ -0,0 +1,84 @@
1
+ import React from 'react';
2
+ import { useFormContext } from 'react-hook-form';
3
+ import { noop } from '@aws-amplify/ui';
4
+
5
+ import {
6
+ FormValues,
7
+ RegisterFieldParams,
8
+ SetFormValueParams,
9
+ SubmitHandler,
10
+ UseForm,
11
+ UseFormParams,
12
+ } from './types';
13
+
14
+ export const DEFAULT_ERROR_MESSAGE =
15
+ '`useForm` must be called inside a `FormProvider`';
16
+
17
+ /**
18
+ * Utility hook corresponding to `FormProvider`, must be used within a `FormProvider`
19
+ *
20
+ * @internal Extend for public export. `useForm` and `UseForm` are an abstraction layer
21
+ * on top of `useFormContext` and `UseFormReturn`, imported from `react-hook-form`
22
+ *
23
+ * @param options optional parameters
24
+ * @returns `Form` utilities
25
+ */
26
+ export default function useForm<
27
+ Values extends FormValues = FormValues,
28
+ OnSubmit extends SubmitHandler = SubmitHandler
29
+ >(options: UseFormParams<Values, OnSubmit> = {}): UseForm<Values> {
30
+ const formContext = useFormContext();
31
+ const { errorMessage, onSubmit: _onSubmit } = options;
32
+
33
+ if (!formContext) {
34
+ throw new Error(errorMessage ?? DEFAULT_ERROR_MESSAGE);
35
+ }
36
+
37
+ const {
38
+ formState,
39
+ getFieldState: _getFieldState,
40
+ getValues,
41
+ handleSubmit,
42
+ register,
43
+ reset,
44
+ setValue,
45
+ } = formContext;
46
+
47
+ // Do not memoize, `formState` updates on all events
48
+ const getFieldState = (name: string) => {
49
+ const { error, ...fieldState } = _getFieldState(name, formState);
50
+
51
+ const { message: errorMessage } = error ?? {};
52
+ return { ...fieldState, errorMessage, hasError: !!errorMessage };
53
+ };
54
+
55
+ // memoize `registerField` and `setFormValue` together,
56
+ // `register` and `setValue` maintain stable references
57
+ const { registerField, setFormValue } = React.useMemo(() => {
58
+ return {
59
+ registerField: ({ name, ...options }: RegisterFieldParams) =>
60
+ register(name, options),
61
+ setFormValue: ({ name, value, ...options }: SetFormValueParams) =>
62
+ setValue(name, value, options),
63
+ };
64
+ }, [register, setValue]);
65
+
66
+ const onSubmit = React.useCallback(
67
+ (event?: React.BaseSyntheticEvent) => {
68
+ const handler = _onSubmit ? handleSubmit(_onSubmit) : noop;
69
+
70
+ handler(event);
71
+ },
72
+ [_onSubmit, handleSubmit]
73
+ );
74
+
75
+ return {
76
+ getFieldState,
77
+ getValues,
78
+ isValid: formState.isValid,
79
+ onSubmit,
80
+ registerField,
81
+ reset,
82
+ setFormValue,
83
+ };
84
+ }
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+
3
+ import { AnyComponent, MergeProps } from '../../types';
4
+
5
+ import FormProvider from './FormProvider';
6
+ import { FormHandle, FormProviderProps } from './types';
7
+
8
+ /**
9
+ * @param Child `Form` base component wrapped inside `FormProvider`
10
+ * @returns Composed `Form` component exposing `FormContext` values to descendents
11
+ */
12
+ export default function withFormProvider<
13
+ ChildComp extends AnyComponent,
14
+ ChildProps extends React.ComponentPropsWithRef<ChildComp>,
15
+ Props extends MergeProps<FormProviderProps, ChildProps>
16
+ >(
17
+ Child: ChildComp
18
+ ): React.ForwardRefExoticComponent<
19
+ React.PropsWithoutRef<Props> & React.RefAttributes<FormHandle>
20
+ > {
21
+ return React.forwardRef<FormHandle, Props>(function Form(
22
+ { defaultValues, mode, ...props },
23
+ ref
24
+ ) {
25
+ return (
26
+ <FormProvider defaultValues={defaultValues} mode={mode} ref={ref}>
27
+ <Child {...(props as ChildProps)} />
28
+ </FormProvider>
29
+ );
30
+ });
31
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Utility component for rendering nothing.
3
+ */
4
+ export default function RenderNothing<Props>(_: Props): JSX.Element | null {
5
+ return null;
6
+ }
@@ -0,0 +1 @@
1
+ export { default as RenderNothing } from './RenderNothing';
@@ -0,0 +1,15 @@
1
+ export {
2
+ FormProvider,
3
+ FormProviderProps,
4
+ FormValues,
5
+ FormHandle,
6
+ SubmitHandler,
7
+ useField,
8
+ useForm,
9
+ UseForm,
10
+ Validate,
11
+ Validator,
12
+ withFormProvider,
13
+ } from './FormCore';
14
+
15
+ export { RenderNothing } from './RenderNothing';
@@ -0,0 +1,8 @@
1
+ export {
2
+ default as useDeprecationWarning,
3
+ UseDeprecationWarning,
4
+ } from './useDeprecationWarning';
5
+ export { default as useHasValueUpdated } from './useHasValueUpdated';
6
+ export { default as usePreviousValue } from './usePreviousValue';
7
+ export { default as useSetUserAgent } from './useSetUserAgent';
8
+ export { default as useTimeout } from './useTimeout';
@@ -0,0 +1,27 @@
1
+ import * as React from 'react';
2
+
3
+ export type UseDeprecationWarning = (params: {
4
+ shouldWarn: boolean;
5
+ message: string;
6
+ }) => void;
7
+
8
+ /**
9
+ * Logs a deprecation warning message.
10
+ *
11
+ * @important Please use the React/React Native specific platform implementations.
12
+ * This version of the hook is a base implementation that the others extend from due
13
+ * to env differences between running in RN or the browser
14
+ */
15
+ const useDeprecationWarning: UseDeprecationWarning = ({
16
+ shouldWarn,
17
+ message,
18
+ }) => {
19
+ React.useEffect(() => {
20
+ if (shouldWarn) {
21
+ // eslint-disable-next-line no-console
22
+ console.warn(message);
23
+ }
24
+ }, [shouldWarn, message]);
25
+ };
26
+
27
+ export default useDeprecationWarning;
@@ -0,0 +1,28 @@
1
+ import { isUndefined } from '@aws-amplify/ui';
2
+
3
+ import usePreviousValue from './usePreviousValue';
4
+
5
+ /**
6
+ * @param value `value` to track for updates
7
+ * @param ignoreFirstRender whether to ignore initial render. defaults to `false`
8
+ * @returns a boolean representing whether the tracked `value` has updated between renders
9
+ *
10
+ * Returns `false`:
11
+ * - on initial render when ignoring first render
12
+ * - current and previous `value` are equal
13
+ *
14
+ * Returns `true`:
15
+ * - on initial render when not ignoring first render (default behavior)
16
+ * - current and previous `value` are not equal
17
+ */
18
+ export default function useHasValueUpdated<Value>(
19
+ value: Value,
20
+ ignoreFirstRender = false
21
+ ): boolean {
22
+ const previous = usePreviousValue<Value>(value);
23
+ const shouldIgnoreChange = isUndefined(previous) && ignoreFirstRender;
24
+ if (shouldIgnoreChange) {
25
+ return false;
26
+ }
27
+ return previous !== value;
28
+ }
@@ -0,0 +1,15 @@
1
+ import { useEffect, useRef } from 'react';
2
+
3
+ export default function usePreviousValue<Value>(
4
+ value: Value
5
+ ): Value | undefined {
6
+ const previous = useRef<Value>();
7
+
8
+ // update ref post render
9
+ useEffect(() => {
10
+ previous.current = value;
11
+ }, [value]);
12
+
13
+ // return previous ref
14
+ return previous.current;
15
+ }
@@ -0,0 +1,18 @@
1
+ import { useEffect } from 'react';
2
+ import { setUserAgent, SetUserAgentOptions } from '@aws-amplify/ui';
3
+
4
+ export default function useSetUserAgent({
5
+ componentName,
6
+ packageName,
7
+ version,
8
+ }: SetUserAgentOptions): void {
9
+ useEffect(() => {
10
+ const clearUserAgent = setUserAgent({
11
+ componentName,
12
+ packageName,
13
+ version,
14
+ });
15
+
16
+ return clearUserAgent;
17
+ }, [componentName, packageName, version]);
18
+ }
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { isTypedFunction } from '@aws-amplify/ui';
3
+
4
+ export default function useTimeout({
5
+ callback,
6
+ delay,
7
+ }: {
8
+ callback?: () => void;
9
+ delay?: number;
10
+ }): void {
11
+ const storedCallback = React.useRef(callback);
12
+
13
+ React.useLayoutEffect(() => {
14
+ storedCallback.current = callback;
15
+ }, [callback]);
16
+
17
+ React.useEffect(() => {
18
+ if (!isTypedFunction(storedCallback.current) || !delay) {
19
+ return;
20
+ }
21
+
22
+ const timeoutId = setTimeout(() => {
23
+ storedCallback.current?.();
24
+ }, delay);
25
+
26
+ return () => {
27
+ clearTimeout(timeoutId);
28
+ };
29
+ }, [delay]);
30
+ }
package/src/index.ts ADDED
@@ -0,0 +1,48 @@
1
+ // features
2
+ export {
3
+ AuthenticatorComponentDefaults,
4
+ AuthenticatorComponentDefaultProps,
5
+ AuthenticatorComponentOverrides,
6
+ AuthenticatorFooterComponent,
7
+ AuthenticatorFormFieldsComponent,
8
+ AuthenticatorHeaderComponent,
9
+ AuthenticatorLegacyField,
10
+ AuthenticatorMachineContext,
11
+ AuthenticatorProvider,
12
+ AuthenticatorRouteComponentKey,
13
+ AuthenticatorRouteComponentName,
14
+ isAuthenticatorComponentRouteKey,
15
+ resolveAuthenticatorComponents,
16
+ useAuthenticator,
17
+ useAuthenticatorRoute,
18
+ UseAuthenticator,
19
+ useAuthenticatorInitMachine,
20
+ UseAuthenticatorRoute,
21
+ } from './Authenticator';
22
+
23
+ export {
24
+ FormProvider,
25
+ FormProviderProps,
26
+ RenderNothing,
27
+ FormValues,
28
+ FormHandle,
29
+ useField,
30
+ useForm,
31
+ UseForm,
32
+ Validate,
33
+ Validator,
34
+ withFormProvider,
35
+ } from './components';
36
+
37
+ export {
38
+ useDeprecationWarning,
39
+ UseDeprecationWarning,
40
+ useHasValueUpdated,
41
+ usePreviousValue,
42
+ useSetUserAgent,
43
+ useTimeout,
44
+ } from './hooks';
45
+
46
+ export { MergeProps } from './types';
47
+
48
+ export { createContextUtilities } from './utils';
@@ -0,0 +1 @@
1
+ export { AnyComponent, MergeProps } from './types';