@sudobility/building_blocks 0.0.28 → 0.0.29
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.
|
@@ -3,4 +3,4 @@ export type { AppSitemapPageProps, SitemapPageText, SitemapSection, SitemapLink,
|
|
|
3
3
|
export { AppTextPage } from './app-text-page';
|
|
4
4
|
export type { AppTextPageProps, TextPageContent, TextSection, TextSectionWithContent, TextSectionWithList, TextSectionWithSubsections, TextPageContact, TextPageContactInfo, GdprNotice, } from './app-text-page';
|
|
5
5
|
export { LoginPage } from './login-page';
|
|
6
|
-
export type { LoginPageProps, LoginPageText } from './login-page';
|
|
6
|
+
export type { LoginPageProps, LoginPageText, AuthErrorInfo, } from './login-page';
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import { type Auth } from 'firebase/auth';
|
|
3
|
+
/**
|
|
4
|
+
* Auth error info passed to onAuthError callback
|
|
5
|
+
*/
|
|
6
|
+
export interface AuthErrorInfo {
|
|
7
|
+
/** Firebase error code (e.g., 'auth/popup-closed-by-user') */
|
|
8
|
+
code: string;
|
|
9
|
+
/** Error message */
|
|
10
|
+
message: string;
|
|
11
|
+
/** Whether this is a user-initiated action (like closing popup) vs actual error */
|
|
12
|
+
isUserAction: boolean;
|
|
13
|
+
}
|
|
3
14
|
/**
|
|
4
15
|
* Props for the LoginPage component
|
|
5
16
|
*/
|
|
@@ -12,6 +23,8 @@ export interface LoginPageProps {
|
|
|
12
23
|
auth: Auth;
|
|
13
24
|
/** Callback fired on successful authentication */
|
|
14
25
|
onSuccess: () => void;
|
|
26
|
+
/** Callback fired on auth errors - if provided, errors won't be shown inline */
|
|
27
|
+
onAuthError?: (error: AuthErrorInfo) => void;
|
|
15
28
|
/** Whether to show Google sign-in option (default: true) */
|
|
16
29
|
showGoogleSignIn?: boolean;
|
|
17
30
|
/** Whether to show sign-up option (default: true) */
|
|
@@ -38,26 +51,4 @@ export interface LoginPageText {
|
|
|
38
51
|
alreadyHaveAccount: string;
|
|
39
52
|
dontHaveAccount: string;
|
|
40
53
|
}
|
|
41
|
-
|
|
42
|
-
* A reusable login page component with email/password and Google sign-in support.
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* ```tsx
|
|
46
|
-
* import { LoginPage } from '@sudobility/building_blocks';
|
|
47
|
-
* import { getFirebaseAuth } from '@sudobility/auth_lib';
|
|
48
|
-
*
|
|
49
|
-
* function MyLoginPage() {
|
|
50
|
-
* const navigate = useNavigate();
|
|
51
|
-
* const auth = getFirebaseAuth();
|
|
52
|
-
*
|
|
53
|
-
* return (
|
|
54
|
-
* <LoginPage
|
|
55
|
-
* appName="My App"
|
|
56
|
-
* auth={auth}
|
|
57
|
-
* onSuccess={() => navigate('/')}
|
|
58
|
-
* />
|
|
59
|
-
* );
|
|
60
|
-
* }
|
|
61
|
-
* ```
|
|
62
|
-
*/
|
|
63
|
-
export declare function LoginPage({ appName, logo, auth, onSuccess, showGoogleSignIn, showSignUp, className, primaryColorClass, }: LoginPageProps): import("react/jsx-runtime").JSX.Element;
|
|
54
|
+
export declare function LoginPage({ appName, logo, auth, onSuccess, onAuthError, showGoogleSignIn, showSignUp, className, primaryColorClass, }: LoginPageProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/index.js
CHANGED
|
@@ -5193,11 +5193,17 @@ const defaultText = {
|
|
|
5193
5193
|
alreadyHaveAccount: "Already have an account?",
|
|
5194
5194
|
dontHaveAccount: "Don't have an account?"
|
|
5195
5195
|
};
|
|
5196
|
+
const USER_ACTION_ERROR_CODES = [
|
|
5197
|
+
"auth/popup-closed-by-user",
|
|
5198
|
+
"auth/cancelled-popup-request",
|
|
5199
|
+
"auth/user-cancelled"
|
|
5200
|
+
];
|
|
5196
5201
|
function LoginPage({
|
|
5197
5202
|
appName,
|
|
5198
5203
|
logo,
|
|
5199
5204
|
auth,
|
|
5200
5205
|
onSuccess,
|
|
5206
|
+
onAuthError,
|
|
5201
5207
|
showGoogleSignIn = true,
|
|
5202
5208
|
showSignUp = true,
|
|
5203
5209
|
className = "",
|
|
@@ -5208,6 +5214,17 @@ function LoginPage({
|
|
|
5208
5214
|
const [password, setPassword] = useState("");
|
|
5209
5215
|
const [error, setError] = useState(null);
|
|
5210
5216
|
const [isLoading, setIsLoading] = useState(false);
|
|
5217
|
+
const handleAuthError = (err) => {
|
|
5218
|
+
const firebaseError = err;
|
|
5219
|
+
const code = firebaseError.code || "unknown";
|
|
5220
|
+
const message = firebaseError.message || "Authentication failed";
|
|
5221
|
+
const isUserAction = USER_ACTION_ERROR_CODES.includes(code);
|
|
5222
|
+
if (onAuthError) {
|
|
5223
|
+
onAuthError({ code, message, isUserAction });
|
|
5224
|
+
} else if (!isUserAction) {
|
|
5225
|
+
setError(message);
|
|
5226
|
+
}
|
|
5227
|
+
};
|
|
5211
5228
|
const handleSubmit = async (e) => {
|
|
5212
5229
|
e.preventDefault();
|
|
5213
5230
|
setError(null);
|
|
@@ -5221,7 +5238,7 @@ function LoginPage({
|
|
|
5221
5238
|
}
|
|
5222
5239
|
onSuccess();
|
|
5223
5240
|
} catch (err) {
|
|
5224
|
-
|
|
5241
|
+
handleAuthError(err);
|
|
5225
5242
|
} finally {
|
|
5226
5243
|
setIsLoading(false);
|
|
5227
5244
|
}
|
|
@@ -5235,7 +5252,7 @@ function LoginPage({
|
|
|
5235
5252
|
await signInWithPopup(auth, provider);
|
|
5236
5253
|
onSuccess();
|
|
5237
5254
|
} catch (err) {
|
|
5238
|
-
|
|
5255
|
+
handleAuthError(err);
|
|
5239
5256
|
} finally {
|
|
5240
5257
|
setIsLoading(false);
|
|
5241
5258
|
}
|