@aws-amplify/ui-react-core 3.4.0 → 3.4.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/hooks/useControlledReducer.mjs +26 -0
- package/dist/esm/index.mjs +2 -1
- package/dist/index.js +96 -74
- package/dist/types/hooks/index.d.ts +2 -1
- package/dist/types/hooks/useControlledReducer.d.ts +5 -0
- package/dist/types/index.d.ts +1 -1
- package/package.json +2 -2
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useControlledReducer.ts +46 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { isUndefined } from '@aws-amplify/ui';
|
|
3
|
+
import useHasValueUpdated from './useHasValueUpdated.mjs';
|
|
4
|
+
|
|
5
|
+
function useControlledReducer(reducer, initialState, options) {
|
|
6
|
+
const { controlledState, onStateChange } = options ?? {};
|
|
7
|
+
const [uncontrolledState, dispatch] = React__default.useReducer(reducer, controlledState ?? initialState);
|
|
8
|
+
const controlledStateRef = React__default.useRef();
|
|
9
|
+
if (!isUndefined(controlledState)) {
|
|
10
|
+
controlledStateRef.current = controlledState;
|
|
11
|
+
}
|
|
12
|
+
const hasUncontrolledStateChanged = useHasValueUpdated(uncontrolledState, true);
|
|
13
|
+
React__default.useEffect(() => {
|
|
14
|
+
// only run `onStateChange` if `uncontrolledState` has changed,
|
|
15
|
+
// ignore reference change to `onStateChange`
|
|
16
|
+
if (hasUncontrolledStateChanged) {
|
|
17
|
+
onStateChange?.(uncontrolledState);
|
|
18
|
+
}
|
|
19
|
+
}, [hasUncontrolledStateChanged, onStateChange, uncontrolledState]);
|
|
20
|
+
const state = controlledStateRef.current
|
|
21
|
+
? controlledStateRef.current
|
|
22
|
+
: uncontrolledState;
|
|
23
|
+
return React__default.useMemo(() => [state, dispatch], [state]);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { useControlledReducer as default };
|
package/dist/esm/index.mjs
CHANGED
|
@@ -10,11 +10,12 @@ export { default as FormProvider } from './components/FormCore/FormProvider.mjs'
|
|
|
10
10
|
export { default as withFormProvider } from './components/FormCore/withFormProvider.mjs';
|
|
11
11
|
export { default as RenderNothing } from './components/RenderNothing/RenderNothing.mjs';
|
|
12
12
|
export { default as useDataState } from './hooks/useDataState/useDataState.mjs';
|
|
13
|
+
export { default as useControlledReducer } from './hooks/useControlledReducer.mjs';
|
|
14
|
+
export { default as useDropZone } from './hooks/useDropZone.mjs';
|
|
13
15
|
export { default as useDeprecationWarning } from './hooks/useDeprecationWarning.mjs';
|
|
14
16
|
export { default as useGetUrl } from './hooks/useGetUrl.mjs';
|
|
15
17
|
export { default as useHasValueUpdated } from './hooks/useHasValueUpdated.mjs';
|
|
16
18
|
export { default as usePreviousValue } from './hooks/usePreviousValue.mjs';
|
|
17
19
|
export { default as useSetUserAgent } from './hooks/useSetUserAgent.mjs';
|
|
18
20
|
export { default as useTimeout } from './hooks/useTimeout.mjs';
|
|
19
|
-
export { default as useDropZone } from './hooks/useDropZone.mjs';
|
|
20
21
|
export { default as createContextUtilities } from './utils/createContextUtilities.mjs';
|
package/dist/index.js
CHANGED
|
@@ -649,55 +649,6 @@ function useDataState(action, initialData, options) {
|
|
|
649
649
|
return [dataState, handleAction];
|
|
650
650
|
}
|
|
651
651
|
|
|
652
|
-
/**
|
|
653
|
-
* Logs a deprecation warning message.
|
|
654
|
-
*
|
|
655
|
-
* @important Please use the React/React Native specific platform implementations.
|
|
656
|
-
* This version of the hook is a base implementation that the others extend from due
|
|
657
|
-
* to env differences between running in RN or the browser
|
|
658
|
-
*/
|
|
659
|
-
const useDeprecationWarning = ({ shouldWarn, message, }) => {
|
|
660
|
-
React__namespace.useEffect(() => {
|
|
661
|
-
if (shouldWarn) {
|
|
662
|
-
// eslint-disable-next-line no-console
|
|
663
|
-
console.warn(message);
|
|
664
|
-
}
|
|
665
|
-
}, [shouldWarn, message]);
|
|
666
|
-
};
|
|
667
|
-
|
|
668
|
-
const INIT_STATE = {
|
|
669
|
-
url: undefined,
|
|
670
|
-
expiresAt: undefined,
|
|
671
|
-
isLoading: true,
|
|
672
|
-
};
|
|
673
|
-
function useGetUrl(input) {
|
|
674
|
-
const [result, setResult] = React__namespace.useState(() => INIT_STATE);
|
|
675
|
-
React__namespace.useEffect(() => {
|
|
676
|
-
const { onError, ...getUrlInput } = input;
|
|
677
|
-
let ignore = false;
|
|
678
|
-
storage.getUrl(getUrlInput)
|
|
679
|
-
.then((response) => {
|
|
680
|
-
if (ignore) {
|
|
681
|
-
return;
|
|
682
|
-
}
|
|
683
|
-
setResult({ ...response, isLoading: false });
|
|
684
|
-
})
|
|
685
|
-
.catch((error) => {
|
|
686
|
-
if (ignore) {
|
|
687
|
-
return;
|
|
688
|
-
}
|
|
689
|
-
if (ui.isFunction(onError)) {
|
|
690
|
-
onError(error);
|
|
691
|
-
}
|
|
692
|
-
setResult({ ...INIT_STATE, isLoading: false });
|
|
693
|
-
});
|
|
694
|
-
return () => {
|
|
695
|
-
ignore = true;
|
|
696
|
-
};
|
|
697
|
-
}, [input]);
|
|
698
|
-
return result;
|
|
699
|
-
}
|
|
700
|
-
|
|
701
652
|
function usePreviousValue(value) {
|
|
702
653
|
const previous = React.useRef(undefined);
|
|
703
654
|
// update ref post render
|
|
@@ -730,33 +681,25 @@ function useHasValueUpdated(value, ignoreFirstRender = false) {
|
|
|
730
681
|
return previous !== value;
|
|
731
682
|
}
|
|
732
683
|
|
|
733
|
-
function
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
}, [componentName, packageName, version]);
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
function useTimeout({ callback, delay, }) {
|
|
745
|
-
const storedCallback = React__namespace["default"].useRef(callback);
|
|
746
|
-
React__namespace["default"].useLayoutEffect(() => {
|
|
747
|
-
storedCallback.current = callback;
|
|
748
|
-
}, [callback]);
|
|
684
|
+
function useControlledReducer(reducer, initialState, options) {
|
|
685
|
+
const { controlledState, onStateChange } = options ?? {};
|
|
686
|
+
const [uncontrolledState, dispatch] = React__namespace["default"].useReducer(reducer, controlledState ?? initialState);
|
|
687
|
+
const controlledStateRef = React__namespace["default"].useRef();
|
|
688
|
+
if (!ui.isUndefined(controlledState)) {
|
|
689
|
+
controlledStateRef.current = controlledState;
|
|
690
|
+
}
|
|
691
|
+
const hasUncontrolledStateChanged = useHasValueUpdated(uncontrolledState, true);
|
|
749
692
|
React__namespace["default"].useEffect(() => {
|
|
750
|
-
if
|
|
751
|
-
|
|
693
|
+
// only run `onStateChange` if `uncontrolledState` has changed,
|
|
694
|
+
// ignore reference change to `onStateChange`
|
|
695
|
+
if (hasUncontrolledStateChanged) {
|
|
696
|
+
onStateChange?.(uncontrolledState);
|
|
752
697
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
};
|
|
759
|
-
}, [delay]);
|
|
698
|
+
}, [hasUncontrolledStateChanged, onStateChange, uncontrolledState]);
|
|
699
|
+
const state = controlledStateRef.current
|
|
700
|
+
? controlledStateRef.current
|
|
701
|
+
: uncontrolledState;
|
|
702
|
+
return React__namespace["default"].useMemo(() => [state, dispatch], [state]);
|
|
760
703
|
}
|
|
761
704
|
|
|
762
705
|
function filterAllowedFiles(files, acceptedFileTypes) {
|
|
@@ -925,6 +868,84 @@ function useDropZone({ onDropComplete, onDragEnter: _onDragEnter, onDragLeave: _
|
|
|
925
868
|
};
|
|
926
869
|
}
|
|
927
870
|
|
|
871
|
+
/**
|
|
872
|
+
* Logs a deprecation warning message.
|
|
873
|
+
*
|
|
874
|
+
* @important Please use the React/React Native specific platform implementations.
|
|
875
|
+
* This version of the hook is a base implementation that the others extend from due
|
|
876
|
+
* to env differences between running in RN or the browser
|
|
877
|
+
*/
|
|
878
|
+
const useDeprecationWarning = ({ shouldWarn, message, }) => {
|
|
879
|
+
React__namespace.useEffect(() => {
|
|
880
|
+
if (shouldWarn) {
|
|
881
|
+
// eslint-disable-next-line no-console
|
|
882
|
+
console.warn(message);
|
|
883
|
+
}
|
|
884
|
+
}, [shouldWarn, message]);
|
|
885
|
+
};
|
|
886
|
+
|
|
887
|
+
const INIT_STATE = {
|
|
888
|
+
url: undefined,
|
|
889
|
+
expiresAt: undefined,
|
|
890
|
+
isLoading: true,
|
|
891
|
+
};
|
|
892
|
+
function useGetUrl(input) {
|
|
893
|
+
const [result, setResult] = React__namespace.useState(() => INIT_STATE);
|
|
894
|
+
React__namespace.useEffect(() => {
|
|
895
|
+
const { onError, ...getUrlInput } = input;
|
|
896
|
+
let ignore = false;
|
|
897
|
+
storage.getUrl(getUrlInput)
|
|
898
|
+
.then((response) => {
|
|
899
|
+
if (ignore) {
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
setResult({ ...response, isLoading: false });
|
|
903
|
+
})
|
|
904
|
+
.catch((error) => {
|
|
905
|
+
if (ignore) {
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
if (ui.isFunction(onError)) {
|
|
909
|
+
onError(error);
|
|
910
|
+
}
|
|
911
|
+
setResult({ ...INIT_STATE, isLoading: false });
|
|
912
|
+
});
|
|
913
|
+
return () => {
|
|
914
|
+
ignore = true;
|
|
915
|
+
};
|
|
916
|
+
}, [input]);
|
|
917
|
+
return result;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
function useSetUserAgent({ componentName, packageName, version, }) {
|
|
921
|
+
React.useEffect(() => {
|
|
922
|
+
const clearUserAgent = ui.setUserAgent({
|
|
923
|
+
componentName,
|
|
924
|
+
packageName,
|
|
925
|
+
version,
|
|
926
|
+
});
|
|
927
|
+
return clearUserAgent;
|
|
928
|
+
}, [componentName, packageName, version]);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
function useTimeout({ callback, delay, }) {
|
|
932
|
+
const storedCallback = React__namespace["default"].useRef(callback);
|
|
933
|
+
React__namespace["default"].useLayoutEffect(() => {
|
|
934
|
+
storedCallback.current = callback;
|
|
935
|
+
}, [callback]);
|
|
936
|
+
React__namespace["default"].useEffect(() => {
|
|
937
|
+
if (!ui.isFunction(storedCallback.current) || !delay) {
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
const timeoutId = setTimeout(() => {
|
|
941
|
+
storedCallback.current?.();
|
|
942
|
+
}, delay);
|
|
943
|
+
return () => {
|
|
944
|
+
clearTimeout(timeoutId);
|
|
945
|
+
};
|
|
946
|
+
}, [delay]);
|
|
947
|
+
}
|
|
948
|
+
|
|
928
949
|
const INVALID_OPTIONS_MESSAGE = 'an `errorMessage` or a `defaultValue` must be provided in `options`';
|
|
929
950
|
/**
|
|
930
951
|
* Uses `ContextType`/`Name` generics and `options` to create:
|
|
@@ -1013,6 +1034,7 @@ exports.resolveAuthenticatorComponents = resolveAuthenticatorComponents;
|
|
|
1013
1034
|
exports.useAuthenticator = useAuthenticator;
|
|
1014
1035
|
exports.useAuthenticatorInitMachine = useAuthenticatorInitMachine;
|
|
1015
1036
|
exports.useAuthenticatorRoute = useAuthenticatorRoute;
|
|
1037
|
+
exports.useControlledReducer = useControlledReducer;
|
|
1016
1038
|
exports.useDataState = useDataState;
|
|
1017
1039
|
exports.useDeprecationWarning = useDeprecationWarning;
|
|
1018
1040
|
exports.useDropZone = useDropZone;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { useDataState, AsyncDataAction, DataAction, DataState, } from './useDataState';
|
|
2
|
+
export { default as useControlledReducer } from './useControlledReducer';
|
|
3
|
+
export { default as useDropZone, UseDropZoneParams } from './useDropZone';
|
|
2
4
|
export { default as useDeprecationWarning, UseDeprecationWarning, } from './useDeprecationWarning';
|
|
3
5
|
export { default as useGetUrl } from './useGetUrl';
|
|
4
6
|
export { default as useHasValueUpdated } from './useHasValueUpdated';
|
|
5
7
|
export { default as usePreviousValue } from './usePreviousValue';
|
|
6
8
|
export { default as useSetUserAgent } from './useSetUserAgent';
|
|
7
9
|
export { default as useTimeout } from './useTimeout';
|
|
8
|
-
export { default as useDropZone, UseDropZoneParams } from './useDropZone';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export default function useControlledReducer<R extends React.Reducer<any, any>, S extends React.ReducerState<R>>(reducer: R, initialState: S, options?: {
|
|
3
|
+
controlledState?: S;
|
|
4
|
+
onStateChange?: (state: S) => void;
|
|
5
|
+
}): [S, React.Dispatch<React.ReducerAction<R>>];
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { AuthenticatorComponentDefaults, AuthenticatorComponentDefaultProps, AuthenticatorComponentOverrides, AuthenticatorFooterComponent, AuthenticatorFormFieldsComponent, AuthenticatorHeaderComponent, AuthenticatorLegacyField, AuthenticatorMachineContext, AuthenticatorProvider, AuthenticatorRouteComponentKey, AuthenticatorRouteComponentName, isAuthenticatorComponentRouteKey, resolveAuthenticatorComponents, useAuthenticator, useAuthenticatorRoute, UseAuthenticator, useAuthenticatorInitMachine, UseAuthenticatorRoute, } from './Authenticator';
|
|
2
2
|
export { FormProvider, FormProviderProps, RenderNothing, FormValues, FormHandle, useField, useForm, UseForm, Validate, Validator, withFormProvider, } from './components';
|
|
3
|
-
export { AsyncDataAction, DataAction, useDeprecationWarning, UseDeprecationWarning, useGetUrl, useHasValueUpdated, usePreviousValue, useSetUserAgent, useTimeout, useDataState, DataState, useDropZone, UseDropZoneParams, } from './hooks';
|
|
3
|
+
export { AsyncDataAction, DataAction, useControlledReducer, useDeprecationWarning, UseDeprecationWarning, useGetUrl, useHasValueUpdated, usePreviousValue, useSetUserAgent, useTimeout, useDataState, DataState, useDropZone, UseDropZoneParams, } from './hooks';
|
|
4
4
|
export { MergeProps } from './types';
|
|
5
5
|
export { createContextUtilities } from './utils';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aws-amplify/ui-react-core",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/esm/index.mjs",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"typecheck": "tsc --noEmit"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@aws-amplify/ui": "6.10.
|
|
43
|
+
"@aws-amplify/ui": "6.10.1",
|
|
44
44
|
"@xstate/react": "^3.2.2",
|
|
45
45
|
"lodash": "4.17.21",
|
|
46
46
|
"react-hook-form": "^7.53.2",
|
package/src/hooks/index.ts
CHANGED
|
@@ -5,6 +5,8 @@ export {
|
|
|
5
5
|
DataState,
|
|
6
6
|
} from './useDataState';
|
|
7
7
|
|
|
8
|
+
export { default as useControlledReducer } from './useControlledReducer';
|
|
9
|
+
export { default as useDropZone, UseDropZoneParams } from './useDropZone';
|
|
8
10
|
export {
|
|
9
11
|
default as useDeprecationWarning,
|
|
10
12
|
UseDeprecationWarning,
|
|
@@ -14,4 +16,3 @@ export { default as useHasValueUpdated } from './useHasValueUpdated';
|
|
|
14
16
|
export { default as usePreviousValue } from './usePreviousValue';
|
|
15
17
|
export { default as useSetUserAgent } from './useSetUserAgent';
|
|
16
18
|
export { default as useTimeout } from './useTimeout';
|
|
17
|
-
export { default as useDropZone, UseDropZoneParams } from './useDropZone';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { isUndefined } from '@aws-amplify/ui';
|
|
3
|
+
|
|
4
|
+
import useHasValueUpdated from './useHasValueUpdated';
|
|
5
|
+
|
|
6
|
+
export default function useControlledReducer<
|
|
7
|
+
R extends React.Reducer<any, any>,
|
|
8
|
+
S extends React.ReducerState<R>,
|
|
9
|
+
>(
|
|
10
|
+
reducer: R,
|
|
11
|
+
initialState: S,
|
|
12
|
+
options?: {
|
|
13
|
+
controlledState?: S;
|
|
14
|
+
onStateChange?: (state: S) => void;
|
|
15
|
+
}
|
|
16
|
+
): [S, React.Dispatch<React.ReducerAction<R>>] {
|
|
17
|
+
const { controlledState, onStateChange } = options ?? {};
|
|
18
|
+
|
|
19
|
+
const [uncontrolledState, dispatch] = React.useReducer(
|
|
20
|
+
reducer,
|
|
21
|
+
controlledState ?? initialState
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const controlledStateRef = React.useRef<S | undefined>();
|
|
25
|
+
if (!isUndefined(controlledState)) {
|
|
26
|
+
controlledStateRef.current = controlledState;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const hasUncontrolledStateChanged = useHasValueUpdated(
|
|
30
|
+
uncontrolledState,
|
|
31
|
+
true
|
|
32
|
+
);
|
|
33
|
+
React.useEffect(() => {
|
|
34
|
+
// only run `onStateChange` if `uncontrolledState` has changed,
|
|
35
|
+
// ignore reference change to `onStateChange`
|
|
36
|
+
if (hasUncontrolledStateChanged) {
|
|
37
|
+
onStateChange?.(uncontrolledState);
|
|
38
|
+
}
|
|
39
|
+
}, [hasUncontrolledStateChanged, onStateChange, uncontrolledState]);
|
|
40
|
+
|
|
41
|
+
const state = controlledStateRef.current
|
|
42
|
+
? controlledStateRef.current
|
|
43
|
+
: uncontrolledState;
|
|
44
|
+
|
|
45
|
+
return React.useMemo(() => [state, dispatch], [state]);
|
|
46
|
+
}
|