@umituz/react-native-auth 1.2.1 → 1.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-auth",
3
- "version": "1.2.1",
3
+ "version": "1.3.1",
4
4
  "description": "Firebase Authentication wrapper for React Native apps - Secure, type-safe, and production-ready",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
package/src/index.ts CHANGED
@@ -67,5 +67,10 @@ export type { UseAuthResult } from './presentation/hooks/useAuth';
67
67
  export { LoginScreen } from './presentation/screens/LoginScreen';
68
68
  export { RegisterScreen } from './presentation/screens/RegisterScreen';
69
69
  export { AuthNavigator } from './presentation/navigation/AuthNavigator';
70
- export type { AuthStackParamList } from './presentation/navigation/AuthNavigator';
70
+ export type {
71
+ AuthStackParamList,
72
+ AuthNavigatorProps,
73
+ } from './presentation/navigation/AuthNavigator';
74
+ export { AuthLegalLinks } from './presentation/components/AuthLegalLinks';
75
+ export type { AuthLegalLinksProps } from './presentation/components/AuthLegalLinks';
71
76
 
@@ -14,6 +14,7 @@ import {
14
14
  } from "firebase/auth";
15
15
  import type { IAuthService, SignUpParams, SignInParams } from "../../application/ports/IAuthService";
16
16
  import {
17
+ AuthError,
17
18
  AuthInitializationError,
18
19
  AuthConfigurationError,
19
20
  AuthValidationError,
@@ -84,6 +85,7 @@ function validatePassword(
84
85
  * Map Firebase Auth errors to domain errors
85
86
  */
86
87
  function mapFirebaseAuthError(error: any): Error {
88
+ // Extract error code and message
87
89
  const code = error?.code || "";
88
90
  const message = error?.message || "Authentication failed";
89
91
 
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Auth Legal Links Component
3
+ * Display Terms of Service and Privacy Policy links
4
+ */
5
+
6
+ import React from "react";
7
+ import { View, StyleSheet, Linking } from "react-native";
8
+ import { AtomicButton, AtomicText } from "@umituz/react-native-design-system";
9
+ import { useAppDesignTokens } from "@umituz/react-native-theme";
10
+ import { useLocalization } from "@umituz/react-native-localization";
11
+
12
+ export interface AuthLegalLinksProps {
13
+ /**
14
+ * Terms of Service URL
15
+ */
16
+ termsUrl?: string;
17
+ /**
18
+ * Privacy Policy URL
19
+ */
20
+ privacyUrl?: string;
21
+ /**
22
+ * Callback when Terms of Service is pressed
23
+ */
24
+ onTermsPress?: () => void;
25
+ /**
26
+ * Callback when Privacy Policy is pressed
27
+ */
28
+ onPrivacyPress?: () => void;
29
+ /**
30
+ * Custom text before links
31
+ */
32
+ prefixText?: string;
33
+ }
34
+
35
+ export const AuthLegalLinks: React.FC<AuthLegalLinksProps> = ({
36
+ termsUrl,
37
+ privacyUrl,
38
+ onTermsPress,
39
+ onPrivacyPress,
40
+ prefixText,
41
+ }) => {
42
+ const tokens = useAppDesignTokens();
43
+ const { t } = useLocalization();
44
+
45
+ const handleTermsPress = async () => {
46
+ if (onTermsPress) {
47
+ onTermsPress();
48
+ } else if (termsUrl) {
49
+ await Linking.openURL(termsUrl);
50
+ }
51
+ };
52
+
53
+ const handlePrivacyPress = async () => {
54
+ if (onPrivacyPress) {
55
+ onPrivacyPress();
56
+ } else if (privacyUrl) {
57
+ await Linking.openURL(privacyUrl);
58
+ }
59
+ };
60
+
61
+ const hasTerms = termsUrl || onTermsPress;
62
+ const hasPrivacy = privacyUrl || onPrivacyPress;
63
+
64
+ if (!hasTerms && !hasPrivacy) {
65
+ return null;
66
+ }
67
+
68
+ return (
69
+ <View style={styles.container}>
70
+ {prefixText && (
71
+ <AtomicText
72
+ type="bodySmall"
73
+ color="secondary"
74
+ style={styles.prefixText}
75
+ >
76
+ {prefixText}
77
+ </AtomicText>
78
+ )}
79
+ <View style={styles.linksContainer}>
80
+ {hasTerms && (
81
+ <AtomicButton
82
+ variant="text"
83
+ onPress={handleTermsPress}
84
+ style={styles.linkButton}
85
+ >
86
+ <AtomicText type="bodySmall" color="primary">
87
+ {t("auth.termsOfService") || "Terms of Service"}
88
+ </AtomicText>
89
+ </AtomicButton>
90
+ )}
91
+ {hasTerms && hasPrivacy && (
92
+ <AtomicText type="bodySmall" color="secondary" style={styles.separator}>
93
+ {" • "}
94
+ </AtomicText>
95
+ )}
96
+ {hasPrivacy && (
97
+ <AtomicButton
98
+ variant="text"
99
+ onPress={handlePrivacyPress}
100
+ style={styles.linkButton}
101
+ >
102
+ <AtomicText type="bodySmall" color="primary">
103
+ {t("auth.privacyPolicy") || "Privacy Policy"}
104
+ </AtomicText>
105
+ </AtomicButton>
106
+ )}
107
+ </View>
108
+ </View>
109
+ );
110
+ };
111
+
112
+ const styles = StyleSheet.create({
113
+ container: {
114
+ marginTop: 16,
115
+ alignItems: "center",
116
+ },
117
+ prefixText: {
118
+ marginBottom: 8,
119
+ textAlign: "center",
120
+ },
121
+ linksContainer: {
122
+ flexDirection: "row",
123
+ alignItems: "center",
124
+ justifyContent: "center",
125
+ flexWrap: "wrap",
126
+ },
127
+ linkButton: {
128
+ paddingHorizontal: 4,
129
+ paddingVertical: 4,
130
+ },
131
+ separator: {
132
+ marginHorizontal: 4,
133
+ },
134
+ });
135
+
@@ -16,13 +16,22 @@ import {
16
16
  import { useAuth } from "../hooks/useAuth";
17
17
  import { AuthErrorDisplay } from "./AuthErrorDisplay";
18
18
  import { AuthLink } from "./AuthLink";
19
+ import { AuthLegalLinks } from "./AuthLegalLinks";
19
20
 
20
21
  interface RegisterFormProps {
21
22
  onNavigateToLogin: () => void;
23
+ termsUrl?: string;
24
+ privacyUrl?: string;
25
+ onTermsPress?: () => void;
26
+ onPrivacyPress?: () => void;
22
27
  }
23
28
 
24
29
  export const RegisterForm: React.FC<RegisterFormProps> = ({
25
30
  onNavigateToLogin,
31
+ termsUrl,
32
+ privacyUrl,
33
+ onTermsPress,
34
+ onPrivacyPress,
26
35
  }) => {
27
36
  const { t } = useLocalization();
28
37
  const { signUp, loading, error } = useAuth();
@@ -206,6 +215,14 @@ export const RegisterForm: React.FC<RegisterFormProps> = ({
206
215
  onPress={onNavigateToLogin}
207
216
  disabled={loading}
208
217
  />
218
+
219
+ <AuthLegalLinks
220
+ termsUrl={termsUrl}
221
+ privacyUrl={privacyUrl}
222
+ onTermsPress={onTermsPress}
223
+ onPrivacyPress={onPrivacyPress}
224
+ prefixText={t("auth.bySigningUp") || "By signing up, you agree to our"}
225
+ />
209
226
  </>
210
227
  );
211
228
  };
@@ -20,7 +20,31 @@ const AuthStack = createStackNavigator<AuthStackParamList>();
20
20
 
21
21
  const SHOW_REGISTER_KEY = "auth_show_register";
22
22
 
23
- export const AuthNavigator: React.FC = () => {
23
+ export interface AuthNavigatorProps {
24
+ /**
25
+ * Terms of Service URL
26
+ */
27
+ termsUrl?: string;
28
+ /**
29
+ * Privacy Policy URL
30
+ */
31
+ privacyUrl?: string;
32
+ /**
33
+ * Callback when Terms of Service is pressed
34
+ */
35
+ onTermsPress?: () => void;
36
+ /**
37
+ * Callback when Privacy Policy is pressed
38
+ */
39
+ onPrivacyPress?: () => void;
40
+ }
41
+
42
+ export const AuthNavigator: React.FC<AuthNavigatorProps> = ({
43
+ termsUrl,
44
+ privacyUrl,
45
+ onTermsPress,
46
+ onPrivacyPress,
47
+ }) => {
24
48
  const tokens = useAppDesignTokens();
25
49
  const [initialRouteName, setInitialRouteName] = useState<
26
50
  "Login" | "Register" | undefined
@@ -51,7 +75,17 @@ export const AuthNavigator: React.FC = () => {
51
75
  }}
52
76
  >
53
77
  <AuthStack.Screen name="Login" component={LoginScreen} />
54
- <AuthStack.Screen name="Register" component={RegisterScreen} />
78
+ <AuthStack.Screen name="Register">
79
+ {(props) => (
80
+ <RegisterScreen
81
+ {...props}
82
+ termsUrl={termsUrl}
83
+ privacyUrl={privacyUrl}
84
+ onTermsPress={onTermsPress}
85
+ onPrivacyPress={onPrivacyPress}
86
+ />
87
+ )}
88
+ </AuthStack.Screen>
55
89
  </AuthStack.Navigator>
56
90
  );
57
91
  };
@@ -18,7 +18,19 @@ type RegisterScreenNavigationProp = StackNavigationProp<
18
18
  "Register"
19
19
  >;
20
20
 
21
- export const RegisterScreen: React.FC = () => {
21
+ export interface RegisterScreenProps {
22
+ termsUrl?: string;
23
+ privacyUrl?: string;
24
+ onTermsPress?: () => void;
25
+ onPrivacyPress?: () => void;
26
+ }
27
+
28
+ export const RegisterScreen: React.FC<RegisterScreenProps> = ({
29
+ termsUrl,
30
+ privacyUrl,
31
+ onTermsPress,
32
+ onPrivacyPress,
33
+ }) => {
22
34
  const { t } = useLocalization();
23
35
  const navigation = useNavigation<RegisterScreenNavigationProp>();
24
36
 
@@ -30,7 +42,13 @@ export const RegisterScreen: React.FC = () => {
30
42
  <AuthContainer>
31
43
  <AuthHeader title={t("auth.createAccount")} />
32
44
  <AuthFormCard>
33
- <RegisterForm onNavigateToLogin={handleNavigateToLogin} />
45
+ <RegisterForm
46
+ onNavigateToLogin={handleNavigateToLogin}
47
+ termsUrl={termsUrl}
48
+ privacyUrl={privacyUrl}
49
+ onTermsPress={onTermsPress}
50
+ onPrivacyPress={onPrivacyPress}
51
+ />
34
52
  </AuthFormCard>
35
53
  </AuthContainer>
36
54
  );