rn-swiftauth-sdk 1.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.
- package/README.md +574 -0
- package/dist/components/AuthScreen.d.ts +14 -0
- package/dist/components/AuthScreen.js +75 -0
- package/dist/components/LoginForm.d.ts +7 -0
- package/dist/components/LoginForm.js +180 -0
- package/dist/components/PasswordInput.d.ts +8 -0
- package/dist/components/PasswordInput.js +70 -0
- package/dist/components/SignUpForm.d.ts +8 -0
- package/dist/components/SignUpForm.js +198 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.js +19 -0
- package/dist/core/AuthContext.d.ts +3 -0
- package/dist/core/AuthContext.js +10 -0
- package/dist/core/AuthProvider.d.ts +8 -0
- package/dist/core/AuthProvider.js +350 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +18 -0
- package/dist/errors/errorMapper.d.ts +2 -0
- package/dist/errors/errorMapper.js +124 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +17 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +17 -0
- package/dist/hooks/useAuth.d.ts +2 -0
- package/dist/hooks/useAuth.js +13 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +27 -0
- package/dist/types/auth.types.d.ts +29 -0
- package/dist/types/auth.types.js +11 -0
- package/dist/types/config.types.d.ts +21 -0
- package/dist/types/config.types.js +12 -0
- package/dist/types/error.types.d.ts +23 -0
- package/dist/types/error.types.js +26 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.js +21 -0
- package/dist/types/ui.types.d.ts +20 -0
- package/dist/types/ui.types.js +2 -0
- package/dist/utils/validation.d.ts +3 -0
- package/dist/utils/validation.js +29 -0
- package/package.json +62 -0
- package/src/components/AuthScreen.tsx +87 -0
- package/src/components/LoginForm.tsx +246 -0
- package/src/components/PasswordInput.tsx +56 -0
- package/src/components/SignUpForm.tsx +293 -0
- package/src/components/index.ts +3 -0
- package/src/core/AuthContext.tsx +6 -0
- package/src/core/AuthProvider.tsx +362 -0
- package/src/core/index.ts +2 -0
- package/src/errors/errorMapper.ts +139 -0
- package/src/errors/index.ts +1 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useAuth.ts +13 -0
- package/src/index.ts +12 -0
- package/src/types/auth.types.ts +43 -0
- package/src/types/config.types.ts +46 -0
- package/src/types/error.types.ts +31 -0
- package/src/types/index.ts +5 -0
- package/src/types/ui.types.ts +26 -0
- package/src/utils/validation.ts +20 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.LoginForm = void 0;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const react_native_1 = require("react-native");
|
|
39
|
+
const useAuth_1 = require("../hooks/useAuth");
|
|
40
|
+
const PasswordInput_1 = require("./PasswordInput");
|
|
41
|
+
const validation_1 = require("../utils/validation");
|
|
42
|
+
const LoginForm = ({ styles: userStyles }) => {
|
|
43
|
+
const { signInWithEmail, signInWithGoogle, signInWithApple, isLoading, // ✅ Using the simplified boolean we added to context
|
|
44
|
+
error, config // ✅ We need this to check if social buttons are enabled
|
|
45
|
+
} = (0, useAuth_1.useAuth)();
|
|
46
|
+
const [email, setEmail] = (0, react_1.useState)('');
|
|
47
|
+
const [password, setPassword] = (0, react_1.useState)('');
|
|
48
|
+
// ✅ Validation Error State
|
|
49
|
+
const [validationErrors, setValidationErrors] = (0, react_1.useState)({});
|
|
50
|
+
const handleLogin = async () => {
|
|
51
|
+
// 1. Reset previous errors
|
|
52
|
+
setValidationErrors({});
|
|
53
|
+
// 2. Validate Inputs
|
|
54
|
+
const emailErr = (0, validation_1.validateEmail)(email);
|
|
55
|
+
const passErr = (0, validation_1.validatePasswordLogin)(password);
|
|
56
|
+
if (emailErr || passErr) {
|
|
57
|
+
setValidationErrors({
|
|
58
|
+
email: emailErr || undefined,
|
|
59
|
+
password: passErr || undefined
|
|
60
|
+
});
|
|
61
|
+
return; // 🛑 Stop if invalid
|
|
62
|
+
}
|
|
63
|
+
// 3. Attempt Login
|
|
64
|
+
try {
|
|
65
|
+
await signInWithEmail(email, password);
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
// Auth errors handled by global state
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const handleGoogleSignIn = async () => {
|
|
72
|
+
try {
|
|
73
|
+
await signInWithGoogle();
|
|
74
|
+
}
|
|
75
|
+
catch (e) {
|
|
76
|
+
console.error('Google Sign-In Error:', e);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const handleAppleSignIn = async () => {
|
|
80
|
+
try {
|
|
81
|
+
await signInWithApple();
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
console.error('Apple Sign-In Error:', e);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
return (react_1.default.createElement(react_native_1.View, { style: [defaultStyles.container, userStyles?.container] },
|
|
88
|
+
error && (react_1.default.createElement(react_native_1.Text, { style: [defaultStyles.errorText, userStyles?.errorText] }, error.message)),
|
|
89
|
+
react_1.default.createElement(react_native_1.TextInput, { style: [
|
|
90
|
+
defaultStyles.input,
|
|
91
|
+
userStyles?.input,
|
|
92
|
+
validationErrors.email ? { borderColor: 'red' } : {} // Highlight on error
|
|
93
|
+
], placeholder: "Email", value: email, onChangeText: (text) => {
|
|
94
|
+
setEmail(text);
|
|
95
|
+
if (validationErrors.email)
|
|
96
|
+
setValidationErrors({ ...validationErrors, email: undefined });
|
|
97
|
+
}, autoCapitalize: "none", keyboardType: "email-address", placeholderTextColor: "#999", editable: !isLoading }),
|
|
98
|
+
validationErrors.email && (react_1.default.createElement(react_native_1.Text, { style: defaultStyles.validationText }, validationErrors.email)),
|
|
99
|
+
react_1.default.createElement(PasswordInput_1.PasswordInput, { styles: userStyles, placeholder: "Password", value: password, onChangeText: (text) => {
|
|
100
|
+
setPassword(text);
|
|
101
|
+
if (validationErrors.password)
|
|
102
|
+
setValidationErrors({ ...validationErrors, password: undefined });
|
|
103
|
+
}, editable: !isLoading }),
|
|
104
|
+
validationErrors.password && (react_1.default.createElement(react_native_1.Text, { style: defaultStyles.validationText }, validationErrors.password)),
|
|
105
|
+
react_1.default.createElement(react_native_1.TouchableOpacity, { style: [
|
|
106
|
+
defaultStyles.button,
|
|
107
|
+
isLoading && defaultStyles.buttonDisabled,
|
|
108
|
+
userStyles?.button
|
|
109
|
+
], onPress: handleLogin, disabled: isLoading }, isLoading ? (react_1.default.createElement(react_native_1.ActivityIndicator, { color: userStyles?.loadingIndicatorColor || "#fff" })) : (react_1.default.createElement(react_native_1.Text, { style: [defaultStyles.buttonText, userStyles?.buttonText] }, "Sign In"))),
|
|
110
|
+
(config.enableGoogle || config.enableApple) && !isLoading && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
111
|
+
react_1.default.createElement(react_native_1.View, { style: defaultStyles.dividerContainer },
|
|
112
|
+
react_1.default.createElement(react_native_1.View, { style: defaultStyles.divider }),
|
|
113
|
+
react_1.default.createElement(react_native_1.Text, { style: defaultStyles.dividerText }, "OR"),
|
|
114
|
+
react_1.default.createElement(react_native_1.View, { style: defaultStyles.divider })),
|
|
115
|
+
config.enableGoogle && (react_1.default.createElement(react_native_1.TouchableOpacity, { style: [
|
|
116
|
+
defaultStyles.oauthButton,
|
|
117
|
+
defaultStyles.googleButton,
|
|
118
|
+
], onPress: handleGoogleSignIn },
|
|
119
|
+
react_1.default.createElement(react_native_1.Text, { style: defaultStyles.googleButtonText }, "Continue with Google"))),
|
|
120
|
+
config.enableApple && react_native_1.Platform.OS === 'ios' && (react_1.default.createElement(react_native_1.TouchableOpacity, { style: [
|
|
121
|
+
defaultStyles.oauthButton,
|
|
122
|
+
defaultStyles.appleButton,
|
|
123
|
+
], onPress: handleAppleSignIn },
|
|
124
|
+
react_1.default.createElement(react_native_1.Text, { style: defaultStyles.appleButtonText }, "Continue with Apple")))))));
|
|
125
|
+
};
|
|
126
|
+
exports.LoginForm = LoginForm;
|
|
127
|
+
const defaultStyles = react_native_1.StyleSheet.create({
|
|
128
|
+
container: { width: '100%', marginVertical: 10 },
|
|
129
|
+
input: {
|
|
130
|
+
backgroundColor: '#f5f5f5',
|
|
131
|
+
padding: 15,
|
|
132
|
+
borderRadius: 8,
|
|
133
|
+
marginBottom: 8, // Reduced slightly to make room for validation text
|
|
134
|
+
borderWidth: 1,
|
|
135
|
+
borderColor: '#e0e0e0',
|
|
136
|
+
fontSize: 16,
|
|
137
|
+
},
|
|
138
|
+
button: {
|
|
139
|
+
backgroundColor: '#007AFF',
|
|
140
|
+
padding: 15,
|
|
141
|
+
borderRadius: 8,
|
|
142
|
+
alignItems: 'center',
|
|
143
|
+
marginTop: 8,
|
|
144
|
+
},
|
|
145
|
+
buttonDisabled: { backgroundColor: '#a0cfff' },
|
|
146
|
+
buttonText: { color: '#fff', fontWeight: '600', fontSize: 16 },
|
|
147
|
+
errorText: { color: 'red', marginBottom: 12, fontSize: 14, textAlign: 'center' },
|
|
148
|
+
validationText: { color: 'red', fontSize: 12, marginBottom: 10, marginLeft: 4, marginTop: -4 },
|
|
149
|
+
dividerContainer: {
|
|
150
|
+
flexDirection: 'row',
|
|
151
|
+
alignItems: 'center',
|
|
152
|
+
marginVertical: 20,
|
|
153
|
+
},
|
|
154
|
+
divider: { flex: 1, height: 1, backgroundColor: '#e0e0e0' },
|
|
155
|
+
dividerText: { marginHorizontal: 16, color: '#666', fontSize: 14, fontWeight: '500' },
|
|
156
|
+
oauthButton: {
|
|
157
|
+
padding: 15,
|
|
158
|
+
borderRadius: 8,
|
|
159
|
+
alignItems: 'center',
|
|
160
|
+
marginBottom: 10,
|
|
161
|
+
flexDirection: 'row',
|
|
162
|
+
justifyContent: 'center',
|
|
163
|
+
},
|
|
164
|
+
googleButton: {
|
|
165
|
+
backgroundColor: '#fff',
|
|
166
|
+
borderWidth: 1,
|
|
167
|
+
borderColor: '#e0e0e0',
|
|
168
|
+
},
|
|
169
|
+
googleButtonText: {
|
|
170
|
+
color: '#000',
|
|
171
|
+
fontSize: 16,
|
|
172
|
+
fontWeight: '500',
|
|
173
|
+
},
|
|
174
|
+
appleButton: { backgroundColor: '#000' },
|
|
175
|
+
appleButtonText: {
|
|
176
|
+
color: '#fff',
|
|
177
|
+
fontSize: 16,
|
|
178
|
+
fontWeight: '600',
|
|
179
|
+
},
|
|
180
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TextInputProps } from 'react-native';
|
|
3
|
+
import { AuthScreenStyles } from '../types';
|
|
4
|
+
interface PasswordInputProps extends TextInputProps {
|
|
5
|
+
styles?: AuthScreenStyles;
|
|
6
|
+
}
|
|
7
|
+
export declare const PasswordInput: ({ styles, ...props }: PasswordInputProps) => React.JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PasswordInput = void 0;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const react_native_1 = require("react-native");
|
|
39
|
+
const PasswordInput = ({ styles, ...props }) => {
|
|
40
|
+
const [isVisible, setIsVisible] = (0, react_1.useState)(false);
|
|
41
|
+
return (react_1.default.createElement(react_native_1.View, { style: [defaultStyles.container, styles?.inputContainer] },
|
|
42
|
+
react_1.default.createElement(react_native_1.TextInput, { ...props, style: [defaultStyles.input, styles?.input, { flex: 1, borderWidth: 0, marginBottom: 0 }], secureTextEntry: !isVisible, placeholderTextColor: "#999" }),
|
|
43
|
+
react_1.default.createElement(react_native_1.TouchableOpacity, { onPress: () => setIsVisible(!isVisible), style: defaultStyles.iconContainer },
|
|
44
|
+
react_1.default.createElement(react_native_1.Text, { style: [defaultStyles.iconText, styles?.eyeIcon] }, isVisible ? "👁️🗨️" : "👁️"))));
|
|
45
|
+
};
|
|
46
|
+
exports.PasswordInput = PasswordInput;
|
|
47
|
+
const defaultStyles = react_native_1.StyleSheet.create({
|
|
48
|
+
container: {
|
|
49
|
+
flexDirection: 'row',
|
|
50
|
+
alignItems: 'center',
|
|
51
|
+
backgroundColor: '#f5f5f5',
|
|
52
|
+
borderRadius: 8,
|
|
53
|
+
borderWidth: 1,
|
|
54
|
+
borderColor: '#e0e0e0',
|
|
55
|
+
marginBottom: 12,
|
|
56
|
+
overflow: 'hidden',
|
|
57
|
+
},
|
|
58
|
+
input: {
|
|
59
|
+
padding: 15,
|
|
60
|
+
fontSize: 16,
|
|
61
|
+
backgroundColor: 'transparent',
|
|
62
|
+
},
|
|
63
|
+
iconContainer: {
|
|
64
|
+
padding: 15,
|
|
65
|
+
justifyContent: 'center',
|
|
66
|
+
},
|
|
67
|
+
iconText: {
|
|
68
|
+
fontSize: 18,
|
|
69
|
+
}
|
|
70
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AuthScreenStyles } from '../types';
|
|
3
|
+
interface SignUpFormProps {
|
|
4
|
+
styles?: AuthScreenStyles;
|
|
5
|
+
showHints?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare const SignUpForm: ({ styles: userStyles, showHints }: SignUpFormProps) => React.JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.SignUpForm = void 0;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const react_native_1 = require("react-native");
|
|
39
|
+
const useAuth_1 = require("../hooks/useAuth");
|
|
40
|
+
const PasswordInput_1 = require("./PasswordInput");
|
|
41
|
+
const validation_1 = require("../utils/validation");
|
|
42
|
+
const SignUpForm = ({ styles: userStyles, showHints = true }) => {
|
|
43
|
+
const { signUpWithEmail, signInWithGoogle, signInWithApple, isLoading, // ✅ Use boolean loading state
|
|
44
|
+
error, config // ✅ Use config for conditional rendering
|
|
45
|
+
} = (0, useAuth_1.useAuth)();
|
|
46
|
+
const [email, setEmail] = (0, react_1.useState)('');
|
|
47
|
+
const [password, setPassword] = (0, react_1.useState)('');
|
|
48
|
+
const [confirmPassword, setConfirmPassword] = (0, react_1.useState)('');
|
|
49
|
+
// ✅ Proper Validation State
|
|
50
|
+
const [validationErrors, setValidationErrors] = (0, react_1.useState)({});
|
|
51
|
+
// Password Requirements Logic for Visual Hints
|
|
52
|
+
const requirements = [
|
|
53
|
+
{ label: "At least 6 characters", met: password.length >= 6 },
|
|
54
|
+
{ label: "Contains a number", met: /\d/.test(password) },
|
|
55
|
+
{ label: "Passwords match", met: password.length > 0 && password === confirmPassword }
|
|
56
|
+
];
|
|
57
|
+
const handleSignUp = async () => {
|
|
58
|
+
// 1. Reset Errors
|
|
59
|
+
setValidationErrors({});
|
|
60
|
+
// 2. Validate Inputs
|
|
61
|
+
const emailErr = (0, validation_1.validateEmail)(email);
|
|
62
|
+
const passErr = (0, validation_1.validatePasswordSignup)(password);
|
|
63
|
+
let confirmErr;
|
|
64
|
+
if (password !== confirmPassword) {
|
|
65
|
+
confirmErr = "Passwords do not match.";
|
|
66
|
+
}
|
|
67
|
+
// 3. Check if any errors exist
|
|
68
|
+
if (emailErr || passErr || confirmErr) {
|
|
69
|
+
setValidationErrors({
|
|
70
|
+
email: emailErr || undefined,
|
|
71
|
+
password: passErr || undefined,
|
|
72
|
+
confirm: confirmErr || undefined
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// 4. Attempt Sign Up
|
|
77
|
+
try {
|
|
78
|
+
await signUpWithEmail(email, password);
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
// Global error handled by useAuth
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
const handleGoogleSignIn = async () => {
|
|
85
|
+
try {
|
|
86
|
+
await signInWithGoogle();
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
console.error('Google Sign-In Error:', e);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const handleAppleSignIn = async () => {
|
|
93
|
+
try {
|
|
94
|
+
await signInWithApple();
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
console.error('Apple Sign-In Error:', e);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
return (react_1.default.createElement(react_native_1.View, { style: [defaultStyles.container, userStyles?.container] },
|
|
101
|
+
error && (react_1.default.createElement(react_native_1.Text, { style: [defaultStyles.globalError, userStyles?.errorText] }, error.message)),
|
|
102
|
+
react_1.default.createElement(react_native_1.TextInput, { style: [
|
|
103
|
+
defaultStyles.input,
|
|
104
|
+
userStyles?.input,
|
|
105
|
+
validationErrors.email ? { borderColor: 'red' } : {}
|
|
106
|
+
], placeholder: "Email", value: email, onChangeText: (text) => {
|
|
107
|
+
setEmail(text);
|
|
108
|
+
if (validationErrors.email)
|
|
109
|
+
setValidationErrors({ ...validationErrors, email: undefined });
|
|
110
|
+
}, autoCapitalize: "none", keyboardType: "email-address", placeholderTextColor: "#999", editable: !isLoading }),
|
|
111
|
+
validationErrors.email && (react_1.default.createElement(react_native_1.Text, { style: defaultStyles.validationText }, validationErrors.email)),
|
|
112
|
+
react_1.default.createElement(PasswordInput_1.PasswordInput, { styles: userStyles, placeholder: "Password", value: password, onChangeText: (text) => {
|
|
113
|
+
setPassword(text);
|
|
114
|
+
if (validationErrors.password)
|
|
115
|
+
setValidationErrors({ ...validationErrors, password: undefined });
|
|
116
|
+
}, editable: !isLoading }),
|
|
117
|
+
validationErrors.password && (react_1.default.createElement(react_native_1.Text, { style: defaultStyles.validationText }, validationErrors.password)),
|
|
118
|
+
react_1.default.createElement(PasswordInput_1.PasswordInput, { styles: userStyles, placeholder: "Confirm Password", value: confirmPassword, onChangeText: (text) => {
|
|
119
|
+
setConfirmPassword(text);
|
|
120
|
+
if (validationErrors.confirm)
|
|
121
|
+
setValidationErrors({ ...validationErrors, confirm: undefined });
|
|
122
|
+
}, editable: !isLoading }),
|
|
123
|
+
validationErrors.confirm && (react_1.default.createElement(react_native_1.Text, { style: defaultStyles.validationText }, validationErrors.confirm)),
|
|
124
|
+
showHints && password.length > 0 && (react_1.default.createElement(react_native_1.View, { style: [defaultStyles.hintContainer, userStyles?.hintContainer] }, requirements.map((req, index) => (react_1.default.createElement(react_native_1.View, { key: index, style: defaultStyles.hintRow },
|
|
125
|
+
react_1.default.createElement(react_native_1.Text, { style: { fontSize: 14, marginRight: 6 } }, req.met ? "✅" : "⚪"),
|
|
126
|
+
react_1.default.createElement(react_native_1.Text, { style: [
|
|
127
|
+
defaultStyles.hintText,
|
|
128
|
+
userStyles?.hintText,
|
|
129
|
+
req.met && (userStyles?.hintTextMet || defaultStyles.hintTextMet)
|
|
130
|
+
] }, req.label)))))),
|
|
131
|
+
react_1.default.createElement(react_native_1.TouchableOpacity, { style: [
|
|
132
|
+
defaultStyles.button,
|
|
133
|
+
isLoading && defaultStyles.buttonDisabled,
|
|
134
|
+
userStyles?.button
|
|
135
|
+
], onPress: handleSignUp, disabled: isLoading }, isLoading ? (react_1.default.createElement(react_native_1.ActivityIndicator, { color: userStyles?.loadingIndicatorColor || "#fff" })) : (react_1.default.createElement(react_native_1.Text, { style: [defaultStyles.buttonText, userStyles?.buttonText] }, "Create Account"))),
|
|
136
|
+
(config.enableGoogle || config.enableApple) && !isLoading && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
137
|
+
react_1.default.createElement(react_native_1.View, { style: defaultStyles.dividerContainer },
|
|
138
|
+
react_1.default.createElement(react_native_1.View, { style: defaultStyles.divider }),
|
|
139
|
+
react_1.default.createElement(react_native_1.Text, { style: defaultStyles.dividerText }, "OR"),
|
|
140
|
+
react_1.default.createElement(react_native_1.View, { style: defaultStyles.divider })),
|
|
141
|
+
config.enableGoogle && (react_1.default.createElement(react_native_1.TouchableOpacity, { style: [defaultStyles.oauthButton, defaultStyles.googleButton], onPress: handleGoogleSignIn },
|
|
142
|
+
react_1.default.createElement(react_native_1.Text, { style: defaultStyles.googleButtonText }, "Sign up with Google"))),
|
|
143
|
+
config.enableApple && react_native_1.Platform.OS === 'ios' && (react_1.default.createElement(react_native_1.TouchableOpacity, { style: [defaultStyles.oauthButton, defaultStyles.appleButton], onPress: handleAppleSignIn },
|
|
144
|
+
react_1.default.createElement(react_native_1.Text, { style: defaultStyles.appleButtonText }, "Sign up with Apple")))))));
|
|
145
|
+
};
|
|
146
|
+
exports.SignUpForm = SignUpForm;
|
|
147
|
+
const defaultStyles = react_native_1.StyleSheet.create({
|
|
148
|
+
container: { width: '100%', marginVertical: 10 },
|
|
149
|
+
input: {
|
|
150
|
+
backgroundColor: '#f5f5f5',
|
|
151
|
+
padding: 15,
|
|
152
|
+
borderRadius: 8,
|
|
153
|
+
marginBottom: 8, // Reduced for validation text space
|
|
154
|
+
borderWidth: 1,
|
|
155
|
+
borderColor: '#e0e0e0',
|
|
156
|
+
fontSize: 16,
|
|
157
|
+
},
|
|
158
|
+
button: {
|
|
159
|
+
backgroundColor: '#34C759',
|
|
160
|
+
padding: 15,
|
|
161
|
+
borderRadius: 8,
|
|
162
|
+
alignItems: 'center',
|
|
163
|
+
marginTop: 8,
|
|
164
|
+
},
|
|
165
|
+
buttonDisabled: { backgroundColor: '#9ce4ae' },
|
|
166
|
+
buttonText: { color: '#fff', fontWeight: '600', fontSize: 16 },
|
|
167
|
+
globalError: { color: 'red', marginBottom: 12, fontSize: 14, textAlign: 'center' },
|
|
168
|
+
validationText: { color: 'red', fontSize: 12, marginBottom: 10, marginLeft: 4, marginTop: -4 },
|
|
169
|
+
// OAuth Styles
|
|
170
|
+
dividerContainer: {
|
|
171
|
+
flexDirection: 'row',
|
|
172
|
+
alignItems: 'center',
|
|
173
|
+
marginVertical: 20,
|
|
174
|
+
},
|
|
175
|
+
divider: { flex: 1, height: 1, backgroundColor: '#e0e0e0' },
|
|
176
|
+
dividerText: { marginHorizontal: 16, color: '#666', fontSize: 14 },
|
|
177
|
+
oauthButton: {
|
|
178
|
+
padding: 15,
|
|
179
|
+
borderRadius: 8,
|
|
180
|
+
alignItems: 'center',
|
|
181
|
+
marginBottom: 10,
|
|
182
|
+
flexDirection: 'row',
|
|
183
|
+
justifyContent: 'center',
|
|
184
|
+
},
|
|
185
|
+
googleButton: {
|
|
186
|
+
backgroundColor: '#fff',
|
|
187
|
+
borderWidth: 1,
|
|
188
|
+
borderColor: '#e0e0e0',
|
|
189
|
+
},
|
|
190
|
+
googleButtonText: { color: '#000', fontSize: 16, fontWeight: '500' },
|
|
191
|
+
appleButton: { backgroundColor: '#000' },
|
|
192
|
+
appleButtonText: { color: '#fff', fontSize: 16, fontWeight: '600' },
|
|
193
|
+
// Password Hint Styles
|
|
194
|
+
hintContainer: { marginBottom: 15, paddingLeft: 5 },
|
|
195
|
+
hintRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 4 },
|
|
196
|
+
hintText: { color: '#666', fontSize: 12 },
|
|
197
|
+
hintTextMet: { color: '#34C759', fontWeight: '600' }
|
|
198
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./AuthScreen"), exports);
|
|
18
|
+
__exportStar(require("./LoginForm"), exports);
|
|
19
|
+
__exportStar(require("./SignUpForm"), exports);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AuthContext = void 0;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
// Create the context with a default undefined value
|
|
9
|
+
// We force the type here to avoid checking for 'undefined' everywhere in the app
|
|
10
|
+
exports.AuthContext = react_1.default.createContext(undefined);
|