@umituz/react-native-auth 1.2.1 → 1.3.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.
package/package.json
CHANGED
|
@@ -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
|
|
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"
|
|
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
|
|
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
|
|
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
|
);
|