@truworth/twc-auth 3.0.11 → 3.0.13
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/README.md +13 -19
- package/build/src/components/ConfirmationModal/index.native.js +2 -2
- package/build/src/components/ConfirmationModal/types.js +2 -1
- package/build/src/components/VerifyMobileOTP/index.native.js +4 -1
- package/build/src/contexts/AuthContext.js +7 -1
- package/build/src/helpers/show-message/types.js +2 -1
- package/build/src/hooks/internal/useTimer.js +1 -1
- package/build/src/screens/EnterEmail/index.native.js +1 -2
- package/build/src/screens/EnterMobile/components/ExistingAccountsSheet/index.native.js +3 -3
- package/build/src/screens/EnterMobile/index.native.js +3 -3
- package/build/src/screens/SSOLogin/AuthenticationMethods/hooks/internal/useSSOAuthenticationMethods.js +27 -3
- package/build/src/screens/SSOLogin/AuthenticationMethods/index.js +10 -8
- package/build/src/screens/SSOLogin/AuthenticationMethods/index.native.js +20 -5
- package/build/src/screens/SignUp/index.native.js +4 -4
- package/build/src/screens/VerifyResetPasswordOTP/hooks/internal/useVerifyResetPasswordOTP.js +1 -1
- package/build/types/components/ConfirmationModal/types.d.ts +4 -2
- package/build/types/helpers/show-message/types.d.ts +3 -1
- package/build/types/screens/SSOLogin/AuthenticationMethods/hooks/internal/useSSOAuthenticationMethods.d.ts +7 -1
- package/build/types/screens/SSOLogin/SearchOrganization/types.d.ts +2 -1
- package/build/types/screens/Welcome/hooks/internal/useWelcome.d.ts +1 -1
- package/get-metro-config.js +2 -2
- package/package.json +8 -12
package/README.md
CHANGED
|
@@ -37,11 +37,10 @@ Truworth Auth Module - A comprehensive authentication solution for React Native
|
|
|
37
37
|
react-native-gesture-handler \
|
|
38
38
|
react-native-linear-gradient \
|
|
39
39
|
react-native-modalize \
|
|
40
|
-
react-native-reanimated \
|
|
41
40
|
react-native-screens \
|
|
42
41
|
react-native-safe-area-context \
|
|
43
42
|
react-native-svg \
|
|
44
|
-
react-native-vector-icons \
|
|
43
|
+
@react-native-vector-icons/ionicons \
|
|
45
44
|
react@^18.2.0 \
|
|
46
45
|
react-native@^0.74.5
|
|
47
46
|
```
|
|
@@ -52,9 +51,7 @@ Truworth Auth Module - A comprehensive authentication solution for React Native
|
|
|
52
51
|
npx pod-install
|
|
53
52
|
```
|
|
54
53
|
|
|
55
|
-
4. For React
|
|
56
|
-
|
|
57
|
-
5. For React Navigation, wrap your app with `NavigationContainer` and ensure you've followed the [getting started guide](https://reactnavigation.org/docs/getting-started/).
|
|
54
|
+
4. For React Navigation, wrap your app with `NavigationContainer` and ensure you've followed the [getting started guide](https://reactnavigation.org/docs/getting-started/).
|
|
58
55
|
|
|
59
56
|
#### React Native Dependencies
|
|
60
57
|
|
|
@@ -73,11 +70,10 @@ Truworth Auth Module - A comprehensive authentication solution for React Native
|
|
|
73
70
|
| react-native-gesture-handler | >=2.16.0 |
|
|
74
71
|
| react-native-linear-gradient | >=2.8.3 |
|
|
75
72
|
| react-native-modalize | >=2.1.1 |
|
|
76
|
-
| react-native-reanimated | >=3.13.0 |
|
|
77
73
|
| react-native-safe-area-context | >=5.3.0 |
|
|
78
74
|
| react-native-screens | >=3.31.1 |
|
|
79
75
|
| react-native-svg | >=15.8.0 |
|
|
80
|
-
| react-native-vector-icons
|
|
76
|
+
| @react-native-vector-icons/ionicons | >=13.0.0 |
|
|
81
77
|
|
|
82
78
|
> Note: lottie-react-native, react-native-fast-image are optional and only needed if your app uses features that depend on them.
|
|
83
79
|
|
|
@@ -106,15 +102,15 @@ Truworth Auth Module - A comprehensive authentication solution for React Native
|
|
|
106
102
|
2. Install peer dependencies:
|
|
107
103
|
```bash
|
|
108
104
|
npm install \
|
|
109
|
-
next@^15.0.4 \
|
|
110
|
-
@react-google-maps/api@>=2.20.6 \
|
|
111
|
-
@truworth/twc-web-design@>=1.9.0 \
|
|
112
|
-
antd@>=5.6.3 \
|
|
113
|
-
framer-motion@>=12.6.2 \
|
|
114
|
-
lodash@>=4.17.21 \
|
|
115
|
-
lucide-react@>=0.483.0 \
|
|
116
|
-
react@>=18.2.0 \
|
|
117
|
-
react-dom@>=18.2.0
|
|
105
|
+
'next@^15.0.4' \
|
|
106
|
+
'@react-google-maps/api@>=2.20.6' \
|
|
107
|
+
'@truworth/twc-web-design@>=1.9.0' \
|
|
108
|
+
'antd@>=5.6.3' \
|
|
109
|
+
'framer-motion@>=12.6.2' \
|
|
110
|
+
'lodash@>=4.17.21' \
|
|
111
|
+
'lucide-react@>=0.483.0' \
|
|
112
|
+
'react@>=18.2.0' \
|
|
113
|
+
'react-dom@>=18.2.0'
|
|
118
114
|
```
|
|
119
115
|
|
|
120
116
|
## Running the Example Applications of the TWC-Auth Package
|
|
@@ -163,9 +159,7 @@ This repository includes example applications for both mobile (React Native) and
|
|
|
163
159
|
Copy the example environment variables below into a new file named `.env` in the `apps/web` directory.
|
|
164
160
|
|
|
165
161
|
```shell
|
|
166
|
-
NEXT_PUBLIC_ENVIRONMENT
|
|
167
|
-
|
|
168
|
-
NODE_ENV=development/production
|
|
162
|
+
NEXT_PUBLIC_ENVIRONMENT=<ENVIRONMENT> # ENVIRONMENT can be "development" or "production"
|
|
169
163
|
|
|
170
164
|
NEXT_PUBLIC_MEMBER_IMAGES_URL=<value>
|
|
171
165
|
|
|
@@ -2,11 +2,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { View, Text } from 'react-native';
|
|
3
3
|
import { Modal } from '@ui-kitten/components';
|
|
4
4
|
import { Colors, RoundedButton } from '@truworth/twc-rn-common';
|
|
5
|
-
import
|
|
5
|
+
import { Ionicons } from '@react-native-vector-icons/ionicons';
|
|
6
6
|
const { primary, gray } = Colors;
|
|
7
7
|
const ConfirmationModal = ({ title, visible, onClose, onProceed, onDismiss, primaryLabel, secondaryLabel, iconName = "information-circle-outline", iconColor = primary.primary_main, description }) => {
|
|
8
8
|
return (_jsx(Modal, { visible: visible, onBackdropPress: onClose, backdropStyle: { backgroundColor: 'rgba(0, 0, 0, 0.25)' }, children: _jsxs(View, { style: { flex: 1, backgroundColor: 'white', padding: 32, marginHorizontal: 16, borderRadius: 12, marginTop: -50 }, children: [iconName &&
|
|
9
|
-
_jsx(
|
|
9
|
+
_jsx(Ionicons, { name: iconName, size: 64, color: iconColor, style: { alignSelf: 'center', marginBottom: 12 } }), title &&
|
|
10
10
|
_jsx(Text, { style: { fontSize: 16, textAlign: 'center', fontWeight: '600', color: gray.gray_900, marginBottom: 24, lineHeight: 20 }, children: title }), description &&
|
|
11
11
|
_jsx(Text, { style: { fontSize: 12, textAlign: 'center', fontWeight: '600', color: gray.gray_600, marginTop: -16, marginBottom: 24, lineHeight: 16 }, children: description }), primaryLabel &&
|
|
12
12
|
_jsx(RoundedButton, { size: 'large', label: primaryLabel, onPress: () => { onClose(); onProceed?.(); } }), secondaryLabel &&
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Ionicons } from '@react-native-vector-icons/ionicons';
|
|
@@ -16,9 +16,12 @@ const VerifyMobileOTP = ({ validateOTP, timer, status, resendOTP, phone }) => {
|
|
|
16
16
|
}
|
|
17
17
|
}, [otp]);
|
|
18
18
|
useEffect(() => {
|
|
19
|
-
if (otpValue && otpValue.length
|
|
19
|
+
if (otpValue && otpValue.length === 6) {
|
|
20
20
|
setOtp(otpValue);
|
|
21
21
|
}
|
|
22
|
+
else if (!otpValue) {
|
|
23
|
+
setOtp('');
|
|
24
|
+
}
|
|
22
25
|
}, [otpValue]);
|
|
23
26
|
return (_jsxs(Layout, { style: { flex: 1, backgroundColor: '#FFFFFF' }, children: [_jsx(Header, {}), _jsxs(CustomKeyboardAvoidingView, { behavior: Platform.OS === 'ios' ? 'padding' : undefined, keyboardVerticalOffset: 0, children: [_jsxs(ScrollView, { style: { paddingHorizontal: 20, paddingTop: 32, flex: 1 }, children: [_jsxs(Text, { textBreakStrategy: 'simple', style: {
|
|
24
27
|
fontSize: 20, fontWeight: '600', color: gray.gray_900,
|
|
@@ -125,6 +125,7 @@ const AuthProvider = ({ children, router, basePath = '', LogoComponent, session,
|
|
|
125
125
|
setClient(null);
|
|
126
126
|
setRegistrationMethod(null);
|
|
127
127
|
setProfile(null);
|
|
128
|
+
setOtpValue('');
|
|
128
129
|
}, []);
|
|
129
130
|
/**
|
|
130
131
|
* Helper to normalize and format user profile data
|
|
@@ -152,6 +153,11 @@ const AuthProvider = ({ children, router, basePath = '', LogoComponent, session,
|
|
|
152
153
|
const handleOtpReceived = (otp) => {
|
|
153
154
|
setOtpValue(otp);
|
|
154
155
|
};
|
|
156
|
+
/** Clears SMS auto-fill buffer so it does not repopulate OTP after navigating to the main app. */
|
|
157
|
+
const handleLoginSuccess = useCallback((result) => {
|
|
158
|
+
setOtpValue('');
|
|
159
|
+
onLogin(result);
|
|
160
|
+
}, [onLogin]);
|
|
155
161
|
const AuthContextValues = {
|
|
156
162
|
token,
|
|
157
163
|
profile,
|
|
@@ -177,7 +183,7 @@ const AuthProvider = ({ children, router, basePath = '', LogoComponent, session,
|
|
|
177
183
|
registrationMethod,
|
|
178
184
|
socialLoginConfig,
|
|
179
185
|
onLaunchAuthSession,
|
|
180
|
-
onLogin,
|
|
186
|
+
onLogin: handleLoginSuccess,
|
|
181
187
|
logout,
|
|
182
188
|
refreshSession: onRefreshSession,
|
|
183
189
|
onTokenChange: (token) => setToken(token),
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { Ionicons } from "@react-native-vector-icons/ionicons";
|
|
2
|
+
import React from "react";
|
|
@@ -19,7 +19,7 @@ const useTimer = (duration) => {
|
|
|
19
19
|
return timer;
|
|
20
20
|
};
|
|
21
21
|
const useInterval = (callback, delay) => {
|
|
22
|
-
const savedCallback = useRef();
|
|
22
|
+
const savedCallback = useRef(undefined);
|
|
23
23
|
// Remember the latest function.
|
|
24
24
|
useEffect(() => {
|
|
25
25
|
savedCallback.current = callback;
|
|
@@ -5,7 +5,6 @@ import { Colors, TextInputField } from '@truworth/twc-rn-common';
|
|
|
5
5
|
import { useEnterEmail } from './hooks/internal/useEnterEmail';
|
|
6
6
|
import { ScreenLayout } from '../../components/ScreenLayout/index.native';
|
|
7
7
|
import { ConfirmationModal as LoginConflictModal } from '../../components/ConfirmationModal';
|
|
8
|
-
import { RegistrationMethod } from '../../enums';
|
|
9
8
|
const { utility } = Colors;
|
|
10
9
|
const EnterEmail = ({ navigation }) => {
|
|
11
10
|
const { email, isEmailValid, handleEmailChange, handleClearEmail, handleEmailExists, loading, loginConflictTitle, loginConflictDescription, isLoginConflictModalVisible, setIsLoginConflictModalVisible } = useEnterEmail();
|
|
@@ -25,7 +24,7 @@ const EnterEmail = ({ navigation }) => {
|
|
|
25
24
|
handleEmailExists({ onValidate });
|
|
26
25
|
},
|
|
27
26
|
disabled: !isEmailValid,
|
|
28
|
-
}, children: _jsx(TextInputField, { value: email, placeholder: 'Enter here...', onChangeValue: handleEmailChange, rightIcon2: email.length > 0 ? 'close' :
|
|
27
|
+
}, children: _jsx(TextInputField, { value: email, placeholder: 'Enter here...', onChangeValue: handleEmailChange, rightIcon2: email.length > 0 ? 'close' : undefined, onPressRightIcon2: handleClearEmail, autoFocus: true, autoCapitalize: 'none', keyboardType: 'email-address' }) }), isLoginConflictModalVisible &&
|
|
29
28
|
_jsx(LoginConflictModal, { title: loginConflictTitle, description: loginConflictDescription, visible: isLoginConflictModalVisible, onProceed: () => setIsLoginConflictModalVisible(false), onClose: () => setIsLoginConflictModalVisible(false), iconColor: utility.warning_main, primaryLabel: 'Okay' })] }));
|
|
30
29
|
};
|
|
31
30
|
export default EnterEmail;
|
|
@@ -9,7 +9,7 @@ import { useExistingAccountsSheet } from './hooks/internal/useExistingAccountsSh
|
|
|
9
9
|
import { useAuthPackageContext } from '../../../../hooks/internal/useAuthPackageContext';
|
|
10
10
|
import { LoginMethodCode } from '../../../../enums';
|
|
11
11
|
import moment from 'moment';
|
|
12
|
-
import
|
|
12
|
+
import { Ionicons } from '@react-native-vector-icons/ionicons';
|
|
13
13
|
const { primary, gray, utility } = Colors;
|
|
14
14
|
const ExistingAccountsSheet = ({ visible, hide, phone, existingAccounts }) => {
|
|
15
15
|
const { ref: sheetRef, open: openSheet, close: closeSheet } = useModalize();
|
|
@@ -64,10 +64,10 @@ const ExistingAccountsSheet = ({ visible, hide, phone, existingAccounts }) => {
|
|
|
64
64
|
marginBottom: 8,
|
|
65
65
|
flexDirection: 'row',
|
|
66
66
|
alignItems: 'center',
|
|
67
|
-
}, children: [_jsx(
|
|
67
|
+
}, children: [_jsx(Ionicons, { size: 16, name: "information-circle", style: { marginRight: 8 }, color: utility.warning_main }), _jsxs(Text, { style: {
|
|
68
68
|
flex: 1, fontSize: 12, fontWeight: '500',
|
|
69
69
|
lineHeight: 18, color: gray.gray_500,
|
|
70
70
|
}, children: ["Once you proceed, this phone number will be ", _jsx(Text, { style: { fontWeight: '600', color: gray.gray_900 }, children: "removed from other accounts." })] })] }), _jsx(RoundedButton, { label: 'Link and Continue', size: 'large', loading: loading, disabled: !selectedAccount, onPress: onContinue, containerStyle: { marginBottom: 8 } }), openChatSupport &&
|
|
71
|
-
_jsxs(TouchableOpacity, { activeOpacity: 0.8, onPress: openChatSupport, style: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', padding: 8 }, children: [_jsx(
|
|
71
|
+
_jsxs(TouchableOpacity, { activeOpacity: 0.8, onPress: openChatSupport, style: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', padding: 8 }, children: [_jsx(Ionicons, { size: 12, name: 'headset', color: primary.primary_main }), _jsx(Text, { style: { fontSize: 14, fontWeight: '600', color: primary.primary_main, marginStart: 8 }, children: "Connect with Support" })] })] }) }));
|
|
72
72
|
};
|
|
73
73
|
export { ExistingAccountsSheet };
|
|
@@ -4,7 +4,7 @@ import { Keyboard, Text, TextInput, TouchableOpacity, View } from 'react-native'
|
|
|
4
4
|
import { Colors } from '@truworth/twc-rn-common';
|
|
5
5
|
import { Layout } from '@ui-kitten/components';
|
|
6
6
|
import { useEffect } from 'react';
|
|
7
|
-
import
|
|
7
|
+
import { Ionicons } from '@react-native-vector-icons/ionicons';
|
|
8
8
|
import { ScreenLayout } from '../../components/ScreenLayout';
|
|
9
9
|
import { useEnterMobile } from './hooks/internal/useEnterMobile';
|
|
10
10
|
import { ExistingAccountsSheet } from './components/ExistingAccountsSheet/index.native';
|
|
@@ -46,11 +46,11 @@ const EnterMobile = ({ navigation }) => {
|
|
|
46
46
|
borderWidth: 1, borderRadius: 8,
|
|
47
47
|
paddingHorizontal: 12, height: 56,
|
|
48
48
|
backgroundColor: primary.white, marginTop: 4,
|
|
49
|
-
}, children: [_jsxs(TouchableOpacity, { activeOpacity: 0.8, onPress: changeCountryCode, style: { flexDirection: 'row', alignItems: 'center' }, children: [_jsx(Text, { style: { fontSize: 14, color: primary.black, fontWeight: '500' }, children: `+${countryCode}` }), _jsx(
|
|
49
|
+
}, children: [_jsxs(TouchableOpacity, { activeOpacity: 0.8, onPress: changeCountryCode, style: { flexDirection: 'row', alignItems: 'center' }, children: [_jsx(Text, { style: { fontSize: 14, color: primary.black, fontWeight: '500' }, children: `+${countryCode}` }), _jsx(Ionicons, { name: 'caret-down', size: 14, color: gray.gray_900 })] }), _jsx(TextInput, { style: {
|
|
50
50
|
flex: 1, fontSize: 14, fontWeight: '500',
|
|
51
51
|
color: primary.black, marginLeft: 2,
|
|
52
52
|
}, onChangeText: text => handleEnterMobile(text), value: phone, keyboardType: "numeric", maxLength: countryCode === '91' ? 10 : 14, autoFocus: true }), phone.length > 0 &&
|
|
53
|
-
_jsx(TouchableOpacity, { activeOpacity: 0.8, onPress: handleClearPhoneInput, children: _jsx(
|
|
53
|
+
_jsx(TouchableOpacity, { activeOpacity: 0.8, onPress: handleClearPhoneInput, children: _jsx(Ionicons, { name: 'close', size: 24, color: gray.gray_900 }) })] }) }), showExistingAccountsSheet &&
|
|
54
54
|
_jsx(ExistingAccountsSheet, { phone: phone, visible: showExistingAccountsSheet, existingAccounts: existingAccounts, hide: () => setShowExistingAccountsSheet(false) })] }));
|
|
55
55
|
};
|
|
56
56
|
export default EnterMobile;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { useState, useRef, useEffect } from "react";
|
|
1
|
+
import { useState, useRef, useEffect, useMemo } from "react";
|
|
2
2
|
import { axiosClient } from "../../../../../api/axiosClient";
|
|
3
3
|
import { showMessage } from "../../../../../helpers/show-message";
|
|
4
|
-
const useSSOAuthenticationMethods = () => {
|
|
4
|
+
const useSSOAuthenticationMethods = ({ client }) => {
|
|
5
5
|
const [loading, setLoading] = useState(false);
|
|
6
6
|
const isMountedRef = useRef(true);
|
|
7
7
|
useEffect(() => {
|
|
@@ -34,6 +34,30 @@ const useSSOAuthenticationMethods = () => {
|
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
36
|
};
|
|
37
|
-
|
|
37
|
+
const headingText = useMemo(() => {
|
|
38
|
+
if (client?.ssoEnabled && client?.mobileLoginEnabled) {
|
|
39
|
+
return `Choose how to sign in`;
|
|
40
|
+
}
|
|
41
|
+
if (client?.ssoEnabled) {
|
|
42
|
+
return `Sign in with your organization account`;
|
|
43
|
+
}
|
|
44
|
+
if (client?.mobileLoginEnabled) {
|
|
45
|
+
return `Sign in with your mobile number`;
|
|
46
|
+
}
|
|
47
|
+
return 'No Single Sign-On methods are available';
|
|
48
|
+
}, [client?.ssoEnabled, client?.mobileLoginEnabled]);
|
|
49
|
+
const subHeadingText = useMemo(() => {
|
|
50
|
+
if (!client?.ssoEnabled && !client?.mobileLoginEnabled) {
|
|
51
|
+
return 'Your organization has not configured any single sign-on methods yet. Please contact your administrator.';
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}, [client?.ssoEnabled, client?.mobileLoginEnabled]);
|
|
55
|
+
return {
|
|
56
|
+
loading,
|
|
57
|
+
initiateSSOLogin,
|
|
58
|
+
headingText,
|
|
59
|
+
subHeadingText,
|
|
60
|
+
hasMultipleLoginOptions: client?.ssoEnabled && client?.mobileLoginEnabled,
|
|
61
|
+
};
|
|
38
62
|
};
|
|
39
63
|
export { useSSOAuthenticationMethods };
|
|
@@ -6,9 +6,9 @@ import { ScreenLayout } from "../../../components/ScreenLayout";
|
|
|
6
6
|
import { CDN_IMAGES_URL } from "../../../constants/cdn-url";
|
|
7
7
|
import { showMessage } from "../../../helpers/show-message";
|
|
8
8
|
import React from "react";
|
|
9
|
-
import { KeyRound,
|
|
9
|
+
import { KeyRound, Smartphone } from "lucide-react";
|
|
10
10
|
const SSOAuthenticationMethods = ({ client, onPressBack, handleMobileLogin }) => {
|
|
11
|
-
const { loading, initiateSSOLogin } = useSSOAuthenticationMethods();
|
|
11
|
+
const { loading, initiateSSOLogin, hasMultipleLoginOptions, headingText, subHeadingText } = useSSOAuthenticationMethods({ client });
|
|
12
12
|
const { LogoComponent } = useAuthPackageContext();
|
|
13
13
|
const renderLogo = () => {
|
|
14
14
|
if (!LogoComponent) {
|
|
@@ -40,11 +40,13 @@ const SSOAuthenticationMethods = ({ client, onPressBack, handleMobileLogin }) =>
|
|
|
40
40
|
};
|
|
41
41
|
return (_jsx(ScreenLayout, { onPressBack: onPressBack, title: _jsxs(Flex, { direction: "column", children: [client?.image ?
|
|
42
42
|
_jsx("img", { src: client?.image, width: 175, height: 117, alt: `${client?.name ?? 'Client'} logo` })
|
|
43
|
-
: renderLogo(), _jsx(Typography, { type: "heading", size: "h5", className: "
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
: renderLogo(), _jsx(Typography, { type: "heading", size: "h5", className: "mb-4 mt-6", children: headingText }), subHeadingText &&
|
|
44
|
+
_jsx(Typography, { type: "body", size: "large", className: "text-gray-600", children: subHeadingText }), client?.ssoEnabled &&
|
|
45
|
+
_jsx(Button, { label: "Login with SSO", isFullWidth: true, variant: "primary", leftIcon: _jsx(KeyRound, {}), onClick: () => initiateSSOLogin({
|
|
46
|
+
clientId: client.id,
|
|
47
|
+
onSSOLoginInitiated
|
|
48
|
+
}), loading: loading }), hasMultipleLoginOptions &&
|
|
49
|
+
_jsxs(_Fragment, { children: [_jsx(Typography, { type: "body", size: "large", className: "mt-6 text-gray-600", children: "Recommended for quick access" }), _jsxs(Flex, { align: "center", className: "my-4", children: [_jsx(Flex, { className: "flex-1 border-t border-gray-300" }), _jsx(Typography, { type: 'body', size: 'small', className: "text-gray-500 px-4", children: "OR" }), _jsx(Flex, { className: "flex-1 border-t border-gray-300" })] })] }), client?.mobileLoginEnabled &&
|
|
50
|
+
_jsx(Button, { label: "Login with Mobile Number", isFullWidth: true, className: "mt-6", leftIcon: _jsx(Smartphone, {}), variant: "secondary", onClick: handleMobileLogin })] }) }));
|
|
49
51
|
};
|
|
50
52
|
export default SSOAuthenticationMethods;
|
|
@@ -13,9 +13,9 @@ const { primary, gray } = Colors;
|
|
|
13
13
|
const SSOAuthenticationMethods = ({ route }) => {
|
|
14
14
|
const { client } = route.params;
|
|
15
15
|
const [aspectRatio, setAspectRatio] = useState(1);
|
|
16
|
-
const { loading, initiateSSOLogin } = useSSOAuthenticationMethods();
|
|
17
|
-
const { LogoComponent } = useAuthPackageContext();
|
|
16
|
+
const { loading, initiateSSOLogin, hasMultipleLoginOptions, headingText, subHeadingText } = useSSOAuthenticationMethods({ client });
|
|
18
17
|
const navigation = useNavigation();
|
|
18
|
+
const { LogoComponent } = useAuthPackageContext();
|
|
19
19
|
useEffect(() => {
|
|
20
20
|
if (client.image) {
|
|
21
21
|
Image.getSize(client.image, (width, height) => {
|
|
@@ -52,8 +52,23 @@ const SSOAuthenticationMethods = ({ route }) => {
|
|
|
52
52
|
};
|
|
53
53
|
return (_jsx(ScreenLayout, { title: "", containerStyle: { flex: 1, backgroundColor: primary.white }, children: _jsxs(View, { style: { flex: 1, justifyContent: 'center' }, children: [client.image ?
|
|
54
54
|
_jsx(FastImage, { source: { uri: client.image }, resizeMode: 'contain', style: { width: 180, aspectRatio: aspectRatio, alignSelf: 'center', marginTop: -150 } })
|
|
55
|
-
: renderLogo(), _jsx(Text, { style: { textAlign: 'center', fontSize:
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
: renderLogo(), _jsx(Text, { style: { textAlign: 'center', fontSize: 18, fontWeight: '600', color: gray.gray_700, marginTop: 30, lineHeight: 32 }, children: headingText }), subHeadingText &&
|
|
56
|
+
_jsx(Text, { style: {
|
|
57
|
+
textAlign: 'center',
|
|
58
|
+
fontSize: 16,
|
|
59
|
+
lineHeight: 22,
|
|
60
|
+
color: gray.gray_600,
|
|
61
|
+
marginTop: 12,
|
|
62
|
+
marginHorizontal: 32,
|
|
63
|
+
}, children: subHeadingText }), client?.ssoEnabled &&
|
|
64
|
+
_jsx(RoundedButton, { loading: loading, type: 'primary', label: 'Login with SSO', size: 'large', containerStyle: { marginTop: 18 }, onPress: () => initiateSSOLogin({
|
|
65
|
+
clientId: client.id,
|
|
66
|
+
onSSOLoginInitiated,
|
|
67
|
+
}), leftIcon: 'key-outline' }), hasMultipleLoginOptions &&
|
|
68
|
+
_jsxs(_Fragment, { children: [_jsx(Text, { style: { textAlign: 'center', fontSize: 14, color: gray.gray_700, marginTop: 20, }, children: "Recommended for quick access" }), _jsxs(View, { style: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', marginTop: 30, marginHorizontal: 30 }, children: [_jsx(View, { style: { flex: 1, height: 1, backgroundColor: gray.gray_200, } }), _jsx(Text, { style: { width: 50, textAlign: 'center', color: gray.gray_500, fontSize: 16, }, children: "OR" }), _jsx(View, { style: { flex: 1, height: 1, backgroundColor: gray.gray_200, } })] })] }), client?.mobileLoginEnabled &&
|
|
69
|
+
_jsx(RoundedButton, { type: 'secondary', label: 'Login with Mobile Number', size: 'large', containerStyle: {
|
|
70
|
+
marginHorizontal: 16,
|
|
71
|
+
marginTop: 30
|
|
72
|
+
}, onPress: () => navigation.navigate('EnterMobile'), leftIcon: 'phone-portrait-outline' })] }) }));
|
|
58
73
|
};
|
|
59
74
|
export default SSOAuthenticationMethods;
|
|
@@ -5,7 +5,7 @@ import { useNavigation } from '@react-navigation/native';
|
|
|
5
5
|
import { useModalize } from 'react-native-modalize';
|
|
6
6
|
import { Layout } from '@ui-kitten/components';
|
|
7
7
|
import DateTimePicker from '@react-native-community/datetimepicker';
|
|
8
|
-
import
|
|
8
|
+
import { Ionicons } from '@react-native-vector-icons/ionicons';
|
|
9
9
|
import moment from 'moment';
|
|
10
10
|
import { BottomSheet, Chips, Colors, TextInputField, DateInputField, widthPercentageToDP as wp, isIphoneX, RoundedButton, CustomKeyboardAvoidingView } from '@truworth/twc-rn-common';
|
|
11
11
|
import { ScreenLayout } from '../../components/ScreenLayout';
|
|
@@ -112,11 +112,11 @@ const MobileInputField = ({ phone, countryCode, onChangeCountryCode, onChangeMob
|
|
|
112
112
|
borderColor: phone.length > 0
|
|
113
113
|
? error?.show ? utility.danger_main : gray.gray_500
|
|
114
114
|
: gray.gray_300,
|
|
115
|
-
}, children: [_jsxs(TouchableOpacity, { activeOpacity: 0.8, onPress: onChangeCountryCode, style: { flexDirection: 'row', alignItems: 'center' }, children: [_jsx(Text, { style: { fontSize: 14, color: primary.black, fontWeight: '500' }, children: `+${countryCode}` }), _jsx(
|
|
115
|
+
}, children: [_jsxs(TouchableOpacity, { activeOpacity: 0.8, onPress: onChangeCountryCode, style: { flexDirection: 'row', alignItems: 'center' }, children: [_jsx(Text, { style: { fontSize: 14, color: primary.black, fontWeight: '500' }, children: `+${countryCode}` }), _jsx(Ionicons, { size: 14, name: 'caret-down', color: gray.gray_900 })] }), _jsx(TextInput, { style: {
|
|
116
116
|
flex: 1, fontSize: 14, fontWeight: '500',
|
|
117
117
|
color: primary.black, marginLeft: 2,
|
|
118
118
|
}, onChangeText: text => onChangeMobile(text), value: phone, keyboardType: "numeric", maxLength: countryCode === '91' ? 10 : 14 }), phone.length > 0 &&
|
|
119
|
-
_jsx(TouchableOpacity, { activeOpacity: 0.8, onPress: onCross, style: { position: 'absolute', right: 10 }, children: _jsx(
|
|
119
|
+
_jsx(TouchableOpacity, { activeOpacity: 0.8, onPress: onCross, style: { position: 'absolute', right: 10 }, children: _jsx(Ionicons, { size: 24, name: 'close', color: gray.gray_900 }) })] }), _jsx(Text, { style: { fontSize: 12, fontWeight: '500', color: utility.danger_main, marginStart: 4, marginTop: 4 }, children: error?.show ? error?.message : '' })] }));
|
|
120
120
|
};
|
|
121
121
|
const KnowMoreModal = ({ visible, hide }) => {
|
|
122
122
|
const { ref: knowMoreRef, open: openKnowMoreSheet, close: closeKnowMoreSheet } = useModalize();
|
|
@@ -178,7 +178,7 @@ const LinkedAccountsSheet = ({ visible, hide, linkedAccounts, countryCode, phone
|
|
|
178
178
|
justifyContent: 'center',
|
|
179
179
|
padding: 8,
|
|
180
180
|
marginTop: 8
|
|
181
|
-
}, children: [_jsx(
|
|
181
|
+
}, children: [_jsx(Ionicons, { name: 'headset', size: 12, color: primary.primary_main }), _jsx(Text, { style: {
|
|
182
182
|
fontSize: 14,
|
|
183
183
|
fontWeight: '600',
|
|
184
184
|
color: primary.primary_main,
|
package/build/src/screens/VerifyResetPasswordOTP/hooks/internal/useVerifyResetPasswordOTP.js
CHANGED
|
@@ -9,7 +9,7 @@ import { axiosClient } from "../../../../api/axiosClient";
|
|
|
9
9
|
const useVerifyResetPasswordOTP = ({ email }) => {
|
|
10
10
|
const [resendOTPCounter, setResendOTPCounter] = useState(0);
|
|
11
11
|
const [status, setStatus] = useState("idle");
|
|
12
|
-
const resetStatusTimeoutRef = useRef();
|
|
12
|
+
const resetStatusTimeoutRef = useRef(undefined);
|
|
13
13
|
const sessionTokenRef = useRef('');
|
|
14
14
|
const scheduleStatusReset = (delay) => {
|
|
15
15
|
if (resetStatusTimeoutRef.current) {
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Ionicons } from '@react-native-vector-icons/ionicons';
|
|
1
3
|
type ConfirmationModalProps = {
|
|
2
4
|
title: string;
|
|
3
5
|
visible: boolean;
|
|
4
6
|
primaryLabel: string;
|
|
5
7
|
secondaryLabel?: string;
|
|
6
|
-
iconName?:
|
|
8
|
+
iconName?: React.ComponentProps<typeof Ionicons>['name'];
|
|
7
9
|
/** @deprecated Use iconClassName instead for Tailwind classes */
|
|
8
|
-
iconColor?:
|
|
10
|
+
iconColor?: React.ComponentProps<typeof Ionicons>['color'];
|
|
9
11
|
/** Tailwind classes for icon styling, e.g. "text-primary" or "text-utility-warning-main" */
|
|
10
12
|
iconClassName?: string;
|
|
11
13
|
onClose: () => void;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { Ionicons } from "@react-native-vector-icons/ionicons";
|
|
2
|
+
import React from "react";
|
|
1
3
|
interface MessageHandlerProps {
|
|
2
4
|
message: string | Error | object;
|
|
3
5
|
type?: 'error' | 'info' | 'message' | 'success' | 'warning';
|
|
4
|
-
leftIcon?:
|
|
6
|
+
leftIcon?: React.ComponentProps<typeof Ionicons>['name'];
|
|
5
7
|
}
|
|
6
8
|
export type { MessageHandlerProps };
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type { SSOInitiationData } from "../../types";
|
|
2
|
-
|
|
2
|
+
import type { Client } from "../../../../../types/types";
|
|
3
|
+
declare const useSSOAuthenticationMethods: ({ client }: {
|
|
4
|
+
client: Client;
|
|
5
|
+
}) => {
|
|
3
6
|
loading: boolean;
|
|
4
7
|
initiateSSOLogin: ({ clientId, onSSOLoginInitiated }: {
|
|
5
8
|
clientId: number;
|
|
6
9
|
onSSOLoginInitiated: (data: SSOInitiationData) => void;
|
|
7
10
|
}) => void;
|
|
11
|
+
headingText: string;
|
|
12
|
+
subHeadingText: string | null;
|
|
13
|
+
hasMultipleLoginOptions: boolean;
|
|
8
14
|
};
|
|
9
15
|
export { useSSOAuthenticationMethods };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
1
2
|
import type { Client } from "../../../types/types";
|
|
2
3
|
interface SSOSearchOrganizationProps {
|
|
3
4
|
onPressBack: () => void;
|
|
@@ -8,6 +9,6 @@ type OptionWithClient = {
|
|
|
8
9
|
value: string;
|
|
9
10
|
image: string;
|
|
10
11
|
client: Client;
|
|
11
|
-
label:
|
|
12
|
+
label: ReactNode;
|
|
12
13
|
};
|
|
13
14
|
export type { Client, SSOSearchOrganizationProps, OptionWithClient };
|
|
@@ -11,7 +11,7 @@ declare const useWelcome: () => {
|
|
|
11
11
|
setShowSocialLoginModal: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
12
12
|
socialLoginType: SocialLoginsEnum | undefined;
|
|
13
13
|
setSocialLoginType: import("react").Dispatch<import("react").SetStateAction<SocialLoginsEnum | undefined>>;
|
|
14
|
-
LogoComponent: import("react").ComponentType<{}> | import("react").ReactElement<
|
|
14
|
+
LogoComponent: import("react").ComponentType<{}> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | undefined;
|
|
15
15
|
onLaunchAuthSession: (() => void) | undefined;
|
|
16
16
|
socialLoginConfig: Partial<Record<SocialLoginsEnum, {
|
|
17
17
|
enabled?: boolean;
|
package/get-metro-config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
|
-
const
|
|
2
|
+
const escapeStringRegexp = require("escape-string-regexp")
|
|
3
3
|
const exclusionList = require("metro-config/src/defaults/exclusionList")
|
|
4
4
|
|
|
5
5
|
const getMetroConfig = (dirPath, packagePath) => {
|
|
@@ -18,7 +18,7 @@ const getMetroConfig = (dirPath, packagePath) => {
|
|
|
18
18
|
blacklistRE: exclusionList(
|
|
19
19
|
packagePeerDeps.map(
|
|
20
20
|
(peerDep) =>
|
|
21
|
-
new RegExp(`^${
|
|
21
|
+
new RegExp(`^${escapeStringRegexp(path.join(packageDir, 'node_modules', peerDep))}\\/.*$`)
|
|
22
22
|
)
|
|
23
23
|
),
|
|
24
24
|
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"description": "Truworth Auth Package for React Native and Web",
|
|
7
|
-
"version": "3.0.
|
|
7
|
+
"version": "3.0.13",
|
|
8
8
|
"main": "build/src/index.js",
|
|
9
9
|
"types": "build/types/index.d.ts",
|
|
10
10
|
"files": [
|
|
@@ -27,11 +27,12 @@
|
|
|
27
27
|
"@react-native-google-signin/google-signin": "12.2.1",
|
|
28
28
|
"@react-navigation/native": "7.1.17",
|
|
29
29
|
"@react-navigation/native-stack": "7.3.26",
|
|
30
|
-
"@truworth/twc-rn-common": "2.0.
|
|
30
|
+
"@truworth/twc-rn-common": "2.0.4",
|
|
31
31
|
"@truworth/twc-web-design": "2.1.0",
|
|
32
32
|
"@twotalltotems/react-native-otp-input": "1.3.11",
|
|
33
|
+
"@react-native-vector-icons/ionicons": "13.0.0",
|
|
33
34
|
"@types/lodash": "^4.17.15",
|
|
34
|
-
"@types/react": "
|
|
35
|
+
"@types/react": "19.2.14",
|
|
35
36
|
"@types/react-google-recaptcha": "^2.1.9",
|
|
36
37
|
"@types/react-native": "^0.72.0",
|
|
37
38
|
"@types/url-parse": "^1.4.11",
|
|
@@ -54,9 +55,9 @@
|
|
|
54
55
|
"react-native-fast-image": "8.6.3",
|
|
55
56
|
"react-native-fbsdk-next": "13.4.1",
|
|
56
57
|
"react-native-linear-gradient": "2.8.3",
|
|
58
|
+
"react-native-gesture-handler": "2.28.0",
|
|
57
59
|
"react-native-modalize": "2.1.1",
|
|
58
60
|
"react-native-parsed-text": "^0.0.22",
|
|
59
|
-
"react-native-reanimated": "4.1.0",
|
|
60
61
|
"react-native-rsa-native": "2.0.5",
|
|
61
62
|
"react-native-safe-area-context": "5.6.1",
|
|
62
63
|
"react-native-svg": "15.12.0",
|
|
@@ -70,8 +71,8 @@
|
|
|
70
71
|
"@react-google-maps/api": ">=2.20.6",
|
|
71
72
|
"date-fns": ">=3.0.0",
|
|
72
73
|
"@react-native-community/datetimepicker": ">=8.1.1",
|
|
73
|
-
"@react-navigation/native": ">=
|
|
74
|
-
"@react-navigation/native-stack": ">=
|
|
74
|
+
"@react-navigation/native": ">=7.0.0",
|
|
75
|
+
"@react-navigation/native-stack": ">=7.0.0",
|
|
75
76
|
"@truworth/twc-rn-common": ">=1.0.12",
|
|
76
77
|
"@truworth/twc-web-design": ">=1.9.0",
|
|
77
78
|
"@ui-kitten/components": ">=5.1.2",
|
|
@@ -82,16 +83,11 @@
|
|
|
82
83
|
"lucide-react": ">=0.483.0",
|
|
83
84
|
"react": ">=18.2.0",
|
|
84
85
|
"react-dom": ">=18.2.0",
|
|
85
|
-
"react-native": ">=0.
|
|
86
|
+
"react-native": ">=0.78.0",
|
|
86
87
|
"react-native-fast-image": ">=8.6.3",
|
|
87
88
|
"react-native-linear-gradient": ">=2.8.3",
|
|
88
|
-
"react-native-modalize": ">=2.1.1",
|
|
89
|
-
"react-native-reanimated": ">=3.13.0",
|
|
90
89
|
"react-native-safe-area-context": ">=5.3.0",
|
|
91
90
|
"react-native-svg": ">=15.8.0",
|
|
92
91
|
"react-native-vector-icons": ">=9.2.0"
|
|
93
|
-
},
|
|
94
|
-
"overrides": {
|
|
95
|
-
"prismjs": "1.30.0"
|
|
96
92
|
}
|
|
97
93
|
}
|