@akin-travel/partner-sdk 1.0.5
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 +1204 -0
- package/dist/account/components/AccountInfoSection.d.ts +46 -0
- package/dist/account/components/AccountInfoSection.d.ts.map +1 -0
- package/dist/account/components/AccountInfoSection.js +52 -0
- package/dist/account/components/AccountInfoSection.js.map +1 -0
- package/dist/account/components/NotificationPreferencesSection.d.ts +40 -0
- package/dist/account/components/NotificationPreferencesSection.d.ts.map +1 -0
- package/dist/account/components/NotificationPreferencesSection.js +116 -0
- package/dist/account/components/NotificationPreferencesSection.js.map +1 -0
- package/dist/account/components/PasskeySection.d.ts +49 -0
- package/dist/account/components/PasskeySection.d.ts.map +1 -0
- package/dist/account/components/PasskeySection.js +298 -0
- package/dist/account/components/PasskeySection.js.map +1 -0
- package/dist/account/hooks/useAccountForm.d.ts +23 -0
- package/dist/account/hooks/useAccountForm.d.ts.map +1 -0
- package/dist/account/hooks/useAccountForm.js +133 -0
- package/dist/account/hooks/useAccountForm.js.map +1 -0
- package/dist/account/index.d.ts +10 -0
- package/dist/account/index.d.ts.map +1 -0
- package/dist/account/index.js +21 -0
- package/dist/account/index.js.map +1 -0
- package/dist/auth/AkinAuthProvider.d.ts +31 -0
- package/dist/auth/AkinAuthProvider.d.ts.map +1 -0
- package/dist/auth/AkinAuthProvider.js +632 -0
- package/dist/auth/AkinAuthProvider.js.map +1 -0
- package/dist/auth/components/LoginForm.d.ts +63 -0
- package/dist/auth/components/LoginForm.d.ts.map +1 -0
- package/dist/auth/components/LoginForm.js +230 -0
- package/dist/auth/components/LoginForm.js.map +1 -0
- package/dist/auth/components/MagicLinkForm.d.ts +41 -0
- package/dist/auth/components/MagicLinkForm.d.ts.map +1 -0
- package/dist/auth/components/MagicLinkForm.js +88 -0
- package/dist/auth/components/MagicLinkForm.js.map +1 -0
- package/dist/auth/components/RequireAuth.d.ts +62 -0
- package/dist/auth/components/RequireAuth.d.ts.map +1 -0
- package/dist/auth/components/RequireAuth.js +63 -0
- package/dist/auth/components/RequireAuth.js.map +1 -0
- package/dist/auth/components/RequireGuest.d.ts +60 -0
- package/dist/auth/components/RequireGuest.d.ts.map +1 -0
- package/dist/auth/components/RequireGuest.js +64 -0
- package/dist/auth/components/RequireGuest.js.map +1 -0
- package/dist/auth/components/SignupForm.d.ts +45 -0
- package/dist/auth/components/SignupForm.d.ts.map +1 -0
- package/dist/auth/components/SignupForm.js +167 -0
- package/dist/auth/components/SignupForm.js.map +1 -0
- package/dist/auth/index.d.ts +10 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +21 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/client.d.ts +17 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +136 -0
- package/dist/client.js.map +1 -0
- package/dist/components/PhoneInput.d.ts +62 -0
- package/dist/components/PhoneInput.d.ts.map +1 -0
- package/dist/components/PhoneInput.js +65 -0
- package/dist/components/PhoneInput.js.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +9 -0
- package/dist/components/index.js.map +1 -0
- package/dist/config.d.ts +111 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +56 -0
- package/dist/config.js.map +1 -0
- package/dist/constants/preferences.d.ts +22 -0
- package/dist/constants/preferences.d.ts.map +1 -0
- package/dist/constants/preferences.js +52 -0
- package/dist/constants/preferences.js.map +1 -0
- package/dist/currency/CurrencyProvider.d.ts +46 -0
- package/dist/currency/CurrencyProvider.d.ts.map +1 -0
- package/dist/currency/CurrencyProvider.js +145 -0
- package/dist/currency/CurrencyProvider.js.map +1 -0
- package/dist/currency/components/CurrencySelector.d.ts +43 -0
- package/dist/currency/components/CurrencySelector.d.ts.map +1 -0
- package/dist/currency/components/CurrencySelector.js +58 -0
- package/dist/currency/components/CurrencySelector.js.map +1 -0
- package/dist/currency/exchangeRates.d.ts +40 -0
- package/dist/currency/exchangeRates.d.ts.map +1 -0
- package/dist/currency/exchangeRates.js +90 -0
- package/dist/currency/exchangeRates.js.map +1 -0
- package/dist/currency/index.d.ts +6 -0
- package/dist/currency/index.d.ts.map +1 -0
- package/dist/currency/index.js +20 -0
- package/dist/currency/index.js.map +1 -0
- package/dist/header/components/CurrencyAccordion.d.ts +45 -0
- package/dist/header/components/CurrencyAccordion.d.ts.map +1 -0
- package/dist/header/components/CurrencyAccordion.js +54 -0
- package/dist/header/components/CurrencyAccordion.js.map +1 -0
- package/dist/header/components/HeaderMenu.d.ts +49 -0
- package/dist/header/components/HeaderMenu.d.ts.map +1 -0
- package/dist/header/components/HeaderMenu.js +95 -0
- package/dist/header/components/HeaderMenu.js.map +1 -0
- package/dist/header/components/LanguageAccordion.d.ts +45 -0
- package/dist/header/components/LanguageAccordion.d.ts.map +1 -0
- package/dist/header/components/LanguageAccordion.js +54 -0
- package/dist/header/components/LanguageAccordion.js.map +1 -0
- package/dist/header/components/UserAvatar.d.ts +26 -0
- package/dist/header/components/UserAvatar.d.ts.map +1 -0
- package/dist/header/components/UserAvatar.js +46 -0
- package/dist/header/components/UserAvatar.js.map +1 -0
- package/dist/header/index.d.ts +10 -0
- package/dist/header/index.d.ts.map +1 -0
- package/dist/header/index.js +13 -0
- package/dist/header/index.js.map +1 -0
- package/dist/i18n/I18nProvider.d.ts +57 -0
- package/dist/i18n/I18nProvider.d.ts.map +1 -0
- package/dist/i18n/I18nProvider.js +205 -0
- package/dist/i18n/I18nProvider.js.map +1 -0
- package/dist/i18n/components/LanguageSelector.d.ts +43 -0
- package/dist/i18n/components/LanguageSelector.d.ts.map +1 -0
- package/dist/i18n/components/LanguageSelector.js +57 -0
- package/dist/i18n/components/LanguageSelector.js.map +1 -0
- package/dist/i18n/index.d.ts +5 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +14 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/translations/en.json +283 -0
- package/dist/i18n/translations/es.json +283 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +191 -0
- package/dist/index.js.map +1 -0
- package/dist/loyalty/AkinLoyaltyProvider.d.ts +18 -0
- package/dist/loyalty/AkinLoyaltyProvider.d.ts.map +1 -0
- package/dist/loyalty/AkinLoyaltyProvider.js +399 -0
- package/dist/loyalty/AkinLoyaltyProvider.js.map +1 -0
- package/dist/loyalty/components/LoyaltyCard.d.ts +48 -0
- package/dist/loyalty/components/LoyaltyCard.d.ts.map +1 -0
- package/dist/loyalty/components/LoyaltyCard.js +140 -0
- package/dist/loyalty/components/LoyaltyCard.js.map +1 -0
- package/dist/loyalty/components/PointsDisplay.d.ts +40 -0
- package/dist/loyalty/components/PointsDisplay.d.ts.map +1 -0
- package/dist/loyalty/components/PointsDisplay.js +32 -0
- package/dist/loyalty/components/PointsDisplay.js.map +1 -0
- package/dist/loyalty/components/PreviousStays.d.ts +59 -0
- package/dist/loyalty/components/PreviousStays.d.ts.map +1 -0
- package/dist/loyalty/components/PreviousStays.js +101 -0
- package/dist/loyalty/components/PreviousStays.js.map +1 -0
- package/dist/loyalty/components/SimpleTierCards.d.ts +51 -0
- package/dist/loyalty/components/SimpleTierCards.d.ts.map +1 -0
- package/dist/loyalty/components/SimpleTierCards.js +96 -0
- package/dist/loyalty/components/SimpleTierCards.js.map +1 -0
- package/dist/loyalty/components/TierCard.d.ts +30 -0
- package/dist/loyalty/components/TierCard.d.ts.map +1 -0
- package/dist/loyalty/components/TierCard.js +41 -0
- package/dist/loyalty/components/TierCard.js.map +1 -0
- package/dist/loyalty/components/TierProgress.d.ts +32 -0
- package/dist/loyalty/components/TierProgress.d.ts.map +1 -0
- package/dist/loyalty/components/TierProgress.js +41 -0
- package/dist/loyalty/components/TierProgress.js.map +1 -0
- package/dist/loyalty/components/TierRequirementsTable.d.ts +54 -0
- package/dist/loyalty/components/TierRequirementsTable.d.ts.map +1 -0
- package/dist/loyalty/components/TierRequirementsTable.js +104 -0
- package/dist/loyalty/components/TierRequirementsTable.js.map +1 -0
- package/dist/loyalty/components/TransactionList.d.ts +44 -0
- package/dist/loyalty/components/TransactionList.d.ts.map +1 -0
- package/dist/loyalty/components/TransactionList.js +112 -0
- package/dist/loyalty/components/TransactionList.js.map +1 -0
- package/dist/loyalty/components/UpcomingStays.d.ts +49 -0
- package/dist/loyalty/components/UpcomingStays.d.ts.map +1 -0
- package/dist/loyalty/components/UpcomingStays.js +60 -0
- package/dist/loyalty/components/UpcomingStays.js.map +1 -0
- package/dist/loyalty/index.d.ts +12 -0
- package/dist/loyalty/index.d.ts.map +1 -0
- package/dist/loyalty/index.js +27 -0
- package/dist/loyalty/index.js.map +1 -0
- package/dist/types/account.d.ts +108 -0
- package/dist/types/account.d.ts.map +1 -0
- package/dist/types/account.js +3 -0
- package/dist/types/account.js.map +1 -0
- package/dist/types/auth.d.ts +205 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/auth.js +3 -0
- package/dist/types/auth.js.map +1 -0
- package/dist/types/currency.d.ts +102 -0
- package/dist/types/currency.d.ts.map +1 -0
- package/dist/types/currency.js +3 -0
- package/dist/types/currency.js.map +1 -0
- package/dist/types/header.d.ts +105 -0
- package/dist/types/header.d.ts.map +1 -0
- package/dist/types/header.js +3 -0
- package/dist/types/header.js.map +1 -0
- package/dist/types/i18n.d.ts +90 -0
- package/dist/types/i18n.d.ts.map +1 -0
- package/dist/types/i18n.js +3 -0
- package/dist/types/i18n.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/loyalty.d.ts +312 -0
- package/dist/types/loyalty.d.ts.map +1 -0
- package/dist/types/loyalty.js +3 -0
- package/dist/types/loyalty.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +10 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/tierLabels.d.ts +27 -0
- package/dist/utils/tierLabels.d.ts.map +1 -0
- package/dist/utils/tierLabels.js +110 -0
- package/dist/utils/tierLabels.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { LoginFormRenderProps, LoginMode } from '../../types/auth';
|
|
3
|
+
interface LoginFormProps {
|
|
4
|
+
/**
|
|
5
|
+
* Render function that receives form state and handlers
|
|
6
|
+
* Use this to build your own styled login form
|
|
7
|
+
*/
|
|
8
|
+
children: (props: LoginFormRenderProps) => ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* Called when login succeeds
|
|
11
|
+
*/
|
|
12
|
+
onSuccess?: () => void;
|
|
13
|
+
/**
|
|
14
|
+
* Called when login fails
|
|
15
|
+
*/
|
|
16
|
+
onError?: (error: string) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Initial login mode
|
|
19
|
+
* @default 'passkey' if supported, 'magic-link' otherwise
|
|
20
|
+
*/
|
|
21
|
+
initialMode?: LoginMode;
|
|
22
|
+
/**
|
|
23
|
+
* Whether to use password-based login instead of passwordless
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
usePassword?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Headless LoginForm component
|
|
30
|
+
*
|
|
31
|
+
* Provides all the logic for login - you provide the UI.
|
|
32
|
+
* Supports passkey-first with magic link fallback (recommended) or traditional password login.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* // Passkey-first with magic link fallback (recommended)
|
|
37
|
+
* <LoginForm onSuccess={() => router.push('/dashboard')}>
|
|
38
|
+
* {({ mode, setMode, email, setEmail, isLoading, error, handlePasskeyLogin, handleMagicLink, passkeySupported }) => (
|
|
39
|
+
* <div>
|
|
40
|
+
* {mode === 'passkey' && (
|
|
41
|
+
* <>
|
|
42
|
+
* <button onClick={handlePasskeyLogin} disabled={!passkeySupported || isLoading}>
|
|
43
|
+
* Sign in with Passkey
|
|
44
|
+
* </button>
|
|
45
|
+
* <button onClick={() => setMode('magic-link')}>Use email instead</button>
|
|
46
|
+
* </>
|
|
47
|
+
* )}
|
|
48
|
+
* {mode === 'magic-link' && (
|
|
49
|
+
* <form onSubmit={(e) => { e.preventDefault(); handleMagicLink(); }}>
|
|
50
|
+
* <input value={email} onChange={e => setEmail(e.target.value)} placeholder="Email" />
|
|
51
|
+
* <button type="submit" disabled={isLoading}>Send sign-in link</button>
|
|
52
|
+
* </form>
|
|
53
|
+
* )}
|
|
54
|
+
* {mode === 'magic-link-sent' && <p>Check your email for a sign-in link!</p>}
|
|
55
|
+
* {error && <p>{error}</p>}
|
|
56
|
+
* </div>
|
|
57
|
+
* )}
|
|
58
|
+
* </LoginForm>
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function LoginForm({ children, onSuccess, onError, initialMode, usePassword }: LoginFormProps): import("react/jsx-runtime").JSX.Element;
|
|
62
|
+
export {};
|
|
63
|
+
//# sourceMappingURL=LoginForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoginForm.d.ts","sourceRoot":"","sources":["../../../src/auth/components/LoginForm.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAoC,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AAEhG,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAExE,UAAU,cAAc;IACtB;;;OAGG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,SAAS,CAAC;IAErD;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAEvB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IAExB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,WAAmB,EAAE,EAAE,cAAc,2CA2M3G"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.LoginForm = LoginForm;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const AkinAuthProvider_1 = require("../AkinAuthProvider");
|
|
8
|
+
/**
|
|
9
|
+
* Headless LoginForm component
|
|
10
|
+
*
|
|
11
|
+
* Provides all the logic for login - you provide the UI.
|
|
12
|
+
* Supports passkey-first with magic link fallback (recommended) or traditional password login.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* // Passkey-first with magic link fallback (recommended)
|
|
17
|
+
* <LoginForm onSuccess={() => router.push('/dashboard')}>
|
|
18
|
+
* {({ mode, setMode, email, setEmail, isLoading, error, handlePasskeyLogin, handleMagicLink, passkeySupported }) => (
|
|
19
|
+
* <div>
|
|
20
|
+
* {mode === 'passkey' && (
|
|
21
|
+
* <>
|
|
22
|
+
* <button onClick={handlePasskeyLogin} disabled={!passkeySupported || isLoading}>
|
|
23
|
+
* Sign in with Passkey
|
|
24
|
+
* </button>
|
|
25
|
+
* <button onClick={() => setMode('magic-link')}>Use email instead</button>
|
|
26
|
+
* </>
|
|
27
|
+
* )}
|
|
28
|
+
* {mode === 'magic-link' && (
|
|
29
|
+
* <form onSubmit={(e) => { e.preventDefault(); handleMagicLink(); }}>
|
|
30
|
+
* <input value={email} onChange={e => setEmail(e.target.value)} placeholder="Email" />
|
|
31
|
+
* <button type="submit" disabled={isLoading}>Send sign-in link</button>
|
|
32
|
+
* </form>
|
|
33
|
+
* )}
|
|
34
|
+
* {mode === 'magic-link-sent' && <p>Check your email for a sign-in link!</p>}
|
|
35
|
+
* {error && <p>{error}</p>}
|
|
36
|
+
* </div>
|
|
37
|
+
* )}
|
|
38
|
+
* </LoginForm>
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
function LoginForm({ children, onSuccess, onError, initialMode, usePassword = false }) {
|
|
42
|
+
const { signIn, requestMagicLink, signInWithGoogle, signInWithPasskey, clearError, error: authError, } = (0, AkinAuthProvider_1.useAkinAuth)();
|
|
43
|
+
const [email, setEmail] = (0, react_1.useState)('');
|
|
44
|
+
const [password, setPassword] = (0, react_1.useState)('');
|
|
45
|
+
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
|
|
46
|
+
const [localError, setLocalError] = (0, react_1.useState)(null);
|
|
47
|
+
const [passkeySupported, setPasskeySupported] = (0, react_1.useState)(false);
|
|
48
|
+
const [mode, setMode] = (0, react_1.useState)(initialMode || (usePassword ? 'password' : 'passkey'));
|
|
49
|
+
// Check passkey support on mount
|
|
50
|
+
(0, react_1.useEffect)(() => {
|
|
51
|
+
const checkPasskeySupport = async () => {
|
|
52
|
+
if (typeof window !== 'undefined' && window.PublicKeyCredential) {
|
|
53
|
+
try {
|
|
54
|
+
const available = await PublicKeyCredential.isConditionalMediationAvailable?.();
|
|
55
|
+
setPasskeySupported(available ?? true);
|
|
56
|
+
// If passkeys not supported and we're in passkey mode, switch to magic-link
|
|
57
|
+
if (!available && mode === 'passkey' && !usePassword) {
|
|
58
|
+
setMode('magic-link');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
setPasskeySupported(false);
|
|
63
|
+
if (mode === 'passkey' && !usePassword) {
|
|
64
|
+
setMode('magic-link');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
setPasskeySupported(false);
|
|
70
|
+
if (mode === 'passkey' && !usePassword) {
|
|
71
|
+
setMode('magic-link');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
checkPasskeySupport();
|
|
76
|
+
}, [mode, usePassword]);
|
|
77
|
+
const error = localError || authError;
|
|
78
|
+
const handleSubmit = (0, react_1.useCallback)(async (e) => {
|
|
79
|
+
e.preventDefault();
|
|
80
|
+
setLocalError(null);
|
|
81
|
+
clearError();
|
|
82
|
+
if (!email.trim()) {
|
|
83
|
+
setLocalError('Email is required');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (mode === 'password') {
|
|
87
|
+
if (!password) {
|
|
88
|
+
setLocalError('Password is required');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
setIsLoading(true);
|
|
92
|
+
try {
|
|
93
|
+
await signIn(email.trim(), password);
|
|
94
|
+
onSuccess?.();
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
const message = err instanceof Error ? err.message : 'Login failed';
|
|
98
|
+
setLocalError(message);
|
|
99
|
+
onError?.(message);
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
setIsLoading(false);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else if (mode === 'magic-link') {
|
|
106
|
+
setIsLoading(true);
|
|
107
|
+
try {
|
|
108
|
+
const result = await requestMagicLink(email.trim());
|
|
109
|
+
if (result.success) {
|
|
110
|
+
setMode('magic-link-sent');
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
setLocalError(result.error || 'Failed to send magic link');
|
|
114
|
+
onError?.(result.error || 'Failed to send magic link');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
const message = err instanceof Error ? err.message : 'Failed to send magic link';
|
|
119
|
+
setLocalError(message);
|
|
120
|
+
onError?.(message);
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
setIsLoading(false);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}, [email, password, mode, signIn, requestMagicLink, clearError, onSuccess, onError]);
|
|
127
|
+
const handleGoogleLogin = (0, react_1.useCallback)(async () => {
|
|
128
|
+
setLocalError(null);
|
|
129
|
+
clearError();
|
|
130
|
+
setIsLoading(true);
|
|
131
|
+
try {
|
|
132
|
+
await signInWithGoogle();
|
|
133
|
+
onSuccess?.();
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
const message = err instanceof Error ? err.message : 'Google login failed';
|
|
137
|
+
setLocalError(message);
|
|
138
|
+
onError?.(message);
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
setIsLoading(false);
|
|
142
|
+
}
|
|
143
|
+
}, [signInWithGoogle, clearError, onSuccess, onError]);
|
|
144
|
+
const handlePasskeyLogin = (0, react_1.useCallback)(async () => {
|
|
145
|
+
setLocalError(null);
|
|
146
|
+
clearError();
|
|
147
|
+
setIsLoading(true);
|
|
148
|
+
try {
|
|
149
|
+
await signInWithPasskey();
|
|
150
|
+
onSuccess?.();
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
const message = err instanceof Error ? err.message : 'Passkey login failed';
|
|
154
|
+
setLocalError(message);
|
|
155
|
+
onError?.(message);
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
setIsLoading(false);
|
|
159
|
+
}
|
|
160
|
+
}, [signInWithPasskey, clearError, onSuccess, onError]);
|
|
161
|
+
const handleMagicLink = (0, react_1.useCallback)(async () => {
|
|
162
|
+
setLocalError(null);
|
|
163
|
+
clearError();
|
|
164
|
+
if (!email.trim()) {
|
|
165
|
+
setLocalError('Email is required');
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
setIsLoading(true);
|
|
169
|
+
try {
|
|
170
|
+
const result = await requestMagicLink(email.trim());
|
|
171
|
+
if (result.success) {
|
|
172
|
+
setMode('magic-link-sent');
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
setLocalError(result.error || 'Failed to send magic link');
|
|
176
|
+
onError?.(result.error || 'Failed to send magic link');
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
const message = err instanceof Error ? err.message : 'Failed to send magic link';
|
|
181
|
+
setLocalError(message);
|
|
182
|
+
onError?.(message);
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
setIsLoading(false);
|
|
186
|
+
}
|
|
187
|
+
}, [email, requestMagicLink, clearError, onError]);
|
|
188
|
+
const handleResendMagicLink = (0, react_1.useCallback)(async () => {
|
|
189
|
+
setLocalError(null);
|
|
190
|
+
clearError();
|
|
191
|
+
setIsLoading(true);
|
|
192
|
+
try {
|
|
193
|
+
const result = await requestMagicLink(email.trim());
|
|
194
|
+
if (!result.success) {
|
|
195
|
+
setLocalError(result.error || 'Failed to resend magic link');
|
|
196
|
+
onError?.(result.error || 'Failed to resend magic link');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
const message = err instanceof Error ? err.message : 'Failed to resend magic link';
|
|
201
|
+
setLocalError(message);
|
|
202
|
+
onError?.(message);
|
|
203
|
+
}
|
|
204
|
+
finally {
|
|
205
|
+
setIsLoading(false);
|
|
206
|
+
}
|
|
207
|
+
}, [email, requestMagicLink, clearError, onError]);
|
|
208
|
+
const handleClearError = (0, react_1.useCallback)(() => {
|
|
209
|
+
setLocalError(null);
|
|
210
|
+
clearError();
|
|
211
|
+
}, [clearError]);
|
|
212
|
+
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children({
|
|
213
|
+
mode,
|
|
214
|
+
setMode,
|
|
215
|
+
email,
|
|
216
|
+
setEmail,
|
|
217
|
+
password,
|
|
218
|
+
setPassword,
|
|
219
|
+
isLoading,
|
|
220
|
+
error,
|
|
221
|
+
passkeySupported,
|
|
222
|
+
handleSubmit,
|
|
223
|
+
handleGoogleLogin,
|
|
224
|
+
handlePasskeyLogin,
|
|
225
|
+
handleMagicLink,
|
|
226
|
+
handleResendMagicLink,
|
|
227
|
+
clearError: handleClearError,
|
|
228
|
+
}) }));
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=LoginForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoginForm.js","sourceRoot":"","sources":["../../../src/auth/components/LoginForm.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { MagicLinkFormRenderProps } from '../../types/auth';
|
|
3
|
+
interface MagicLinkFormProps {
|
|
4
|
+
/**
|
|
5
|
+
* Render function that receives form state and handlers
|
|
6
|
+
* Use this to build your own styled magic link form
|
|
7
|
+
*/
|
|
8
|
+
children: (props: MagicLinkFormRenderProps) => ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* Called when magic link is sent successfully
|
|
11
|
+
*/
|
|
12
|
+
onSuccess?: () => void;
|
|
13
|
+
/**
|
|
14
|
+
* Called when sending magic link fails
|
|
15
|
+
*/
|
|
16
|
+
onError?: (error: string) => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Headless MagicLinkForm component
|
|
20
|
+
*
|
|
21
|
+
* Provides all the logic for requesting a magic link - you provide the UI.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* <MagicLinkForm onSuccess={() => setShowSuccess(true)}>
|
|
26
|
+
* {({ email, setEmail, isLoading, error, success, handleSubmit }) => (
|
|
27
|
+
* <form onSubmit={handleSubmit}>
|
|
28
|
+
* <input value={email} onChange={e => setEmail(e.target.value)} placeholder="Email" />
|
|
29
|
+
* {error && <p className="error">{error}</p>}
|
|
30
|
+
* {success && <p className="success">Check your email for a login link!</p>}
|
|
31
|
+
* <button type="submit" disabled={isLoading || success}>
|
|
32
|
+
* {isLoading ? 'Sending...' : 'Send Magic Link'}
|
|
33
|
+
* </button>
|
|
34
|
+
* </form>
|
|
35
|
+
* )}
|
|
36
|
+
* </MagicLinkForm>
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function MagicLinkForm({ children, onSuccess, onError }: MagicLinkFormProps): import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=MagicLinkForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MagicLinkForm.d.ts","sourceRoot":"","sources":["../../../src/auth/components/MagicLinkForm.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAyB,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AAErF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAEjE,UAAU,kBAAkB;IAC1B;;;OAGG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,SAAS,CAAC;IAEzD;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAEvB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,kBAAkB,2CAwEjF"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.MagicLinkForm = MagicLinkForm;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const AkinAuthProvider_1 = require("../AkinAuthProvider");
|
|
8
|
+
/**
|
|
9
|
+
* Headless MagicLinkForm component
|
|
10
|
+
*
|
|
11
|
+
* Provides all the logic for requesting a magic link - you provide the UI.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <MagicLinkForm onSuccess={() => setShowSuccess(true)}>
|
|
16
|
+
* {({ email, setEmail, isLoading, error, success, handleSubmit }) => (
|
|
17
|
+
* <form onSubmit={handleSubmit}>
|
|
18
|
+
* <input value={email} onChange={e => setEmail(e.target.value)} placeholder="Email" />
|
|
19
|
+
* {error && <p className="error">{error}</p>}
|
|
20
|
+
* {success && <p className="success">Check your email for a login link!</p>}
|
|
21
|
+
* <button type="submit" disabled={isLoading || success}>
|
|
22
|
+
* {isLoading ? 'Sending...' : 'Send Magic Link'}
|
|
23
|
+
* </button>
|
|
24
|
+
* </form>
|
|
25
|
+
* )}
|
|
26
|
+
* </MagicLinkForm>
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
function MagicLinkForm({ children, onSuccess, onError }) {
|
|
30
|
+
const { requestMagicLink, clearError, error: authError } = (0, AkinAuthProvider_1.useAkinAuth)();
|
|
31
|
+
const [email, setEmail] = (0, react_1.useState)('');
|
|
32
|
+
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
|
|
33
|
+
const [localError, setLocalError] = (0, react_1.useState)(null);
|
|
34
|
+
const [success, setSuccess] = (0, react_1.useState)(false);
|
|
35
|
+
const error = localError || authError;
|
|
36
|
+
const handleSubmit = (0, react_1.useCallback)(async (e) => {
|
|
37
|
+
e.preventDefault();
|
|
38
|
+
setLocalError(null);
|
|
39
|
+
setSuccess(false);
|
|
40
|
+
clearError();
|
|
41
|
+
if (!email.trim()) {
|
|
42
|
+
setLocalError('Email is required');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// Basic email validation
|
|
46
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
47
|
+
if (!emailRegex.test(email.trim())) {
|
|
48
|
+
setLocalError('Please enter a valid email address');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
setIsLoading(true);
|
|
52
|
+
try {
|
|
53
|
+
const result = await requestMagicLink(email.trim());
|
|
54
|
+
if (result.success) {
|
|
55
|
+
setSuccess(true);
|
|
56
|
+
onSuccess?.();
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const errorMsg = result.error || 'Failed to send magic link';
|
|
60
|
+
setLocalError(errorMsg);
|
|
61
|
+
onError?.(errorMsg);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const message = err instanceof Error ? err.message : 'Failed to send magic link';
|
|
66
|
+
setLocalError(message);
|
|
67
|
+
onError?.(message);
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
setIsLoading(false);
|
|
71
|
+
}
|
|
72
|
+
}, [email, requestMagicLink, clearError, onSuccess, onError]);
|
|
73
|
+
const handleClearError = (0, react_1.useCallback)(() => {
|
|
74
|
+
setLocalError(null);
|
|
75
|
+
setSuccess(false);
|
|
76
|
+
clearError();
|
|
77
|
+
}, [clearError]);
|
|
78
|
+
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children({
|
|
79
|
+
email,
|
|
80
|
+
setEmail,
|
|
81
|
+
isLoading,
|
|
82
|
+
error,
|
|
83
|
+
success,
|
|
84
|
+
handleSubmit,
|
|
85
|
+
clearError: handleClearError,
|
|
86
|
+
}) }));
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=MagicLinkForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MagicLinkForm.js","sourceRoot":"","sources":["../../../src/auth/components/MagicLinkForm.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { useAkinAuth } from '../AkinAuthProvider';
|
|
3
|
+
export interface RequireAuthProps {
|
|
4
|
+
/**
|
|
5
|
+
* Content to render when user is authenticated
|
|
6
|
+
*/
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* Content to render while authentication state is loading
|
|
10
|
+
* Defaults to null (render nothing)
|
|
11
|
+
*/
|
|
12
|
+
loadingFallback?: ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* Content to render when user is not authenticated
|
|
15
|
+
* Can be a redirect component, login form, or any other content
|
|
16
|
+
*/
|
|
17
|
+
fallback?: ReactNode;
|
|
18
|
+
/**
|
|
19
|
+
* Callback fired when user is not authenticated
|
|
20
|
+
* Useful for programmatic redirects
|
|
21
|
+
*/
|
|
22
|
+
onUnauthenticated?: () => void;
|
|
23
|
+
}
|
|
24
|
+
export interface RequireAuthRenderProps {
|
|
25
|
+
isAuthenticated: boolean;
|
|
26
|
+
isLoading: boolean;
|
|
27
|
+
member: ReturnType<typeof useAkinAuth>['member'];
|
|
28
|
+
user: ReturnType<typeof useAkinAuth>['user'];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Wrapper component that only renders children when user is authenticated
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // With fallback content
|
|
35
|
+
* <RequireAuth fallback={<Navigate to="/login" />}>
|
|
36
|
+
* <Dashboard />
|
|
37
|
+
* </RequireAuth>
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* // With loading state
|
|
41
|
+
* <RequireAuth
|
|
42
|
+
* loadingFallback={<LoadingSpinner />}
|
|
43
|
+
* fallback={<Navigate to="/login" />}
|
|
44
|
+
* >
|
|
45
|
+
* <Dashboard />
|
|
46
|
+
* </RequireAuth>
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* // With callback
|
|
50
|
+
* <RequireAuth
|
|
51
|
+
* onUnauthenticated={() => router.push('/login')}
|
|
52
|
+
* >
|
|
53
|
+
* <Dashboard />
|
|
54
|
+
* </RequireAuth>
|
|
55
|
+
*/
|
|
56
|
+
export declare function RequireAuth({ children, loadingFallback, fallback, onUnauthenticated, }: RequireAuthProps): import("react/jsx-runtime").JSX.Element;
|
|
57
|
+
export declare namespace RequireAuth {
|
|
58
|
+
var Headless: ({ children, }: {
|
|
59
|
+
children: (props: RequireAuthRenderProps) => ReactNode;
|
|
60
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=RequireAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequireAuth.d.ts","sourceRoot":"","sources":["../../../src/auth/components/RequireAuth.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,QAAQ,CAAC,CAAC;IACjD,IAAI,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;CAC9C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,eAAsB,EACtB,QAAe,EACf,iBAAiB,GAClB,EAAE,gBAAgB,2CAgBlB;yBArBe,WAAW;kCAqCxB;QACD,QAAQ,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,SAAS,CAAC;KACxD"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.RequireAuth = RequireAuth;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const AkinAuthProvider_1 = require("../AkinAuthProvider");
|
|
7
|
+
/**
|
|
8
|
+
* Wrapper component that only renders children when user is authenticated
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // With fallback content
|
|
12
|
+
* <RequireAuth fallback={<Navigate to="/login" />}>
|
|
13
|
+
* <Dashboard />
|
|
14
|
+
* </RequireAuth>
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // With loading state
|
|
18
|
+
* <RequireAuth
|
|
19
|
+
* loadingFallback={<LoadingSpinner />}
|
|
20
|
+
* fallback={<Navigate to="/login" />}
|
|
21
|
+
* >
|
|
22
|
+
* <Dashboard />
|
|
23
|
+
* </RequireAuth>
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // With callback
|
|
27
|
+
* <RequireAuth
|
|
28
|
+
* onUnauthenticated={() => router.push('/login')}
|
|
29
|
+
* >
|
|
30
|
+
* <Dashboard />
|
|
31
|
+
* </RequireAuth>
|
|
32
|
+
*/
|
|
33
|
+
function RequireAuth({ children, loadingFallback = null, fallback = null, onUnauthenticated, }) {
|
|
34
|
+
const { isAuthenticated, isLoading, member, user } = (0, AkinAuthProvider_1.useAkinAuth)();
|
|
35
|
+
// Still loading auth state
|
|
36
|
+
if (isLoading) {
|
|
37
|
+
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: loadingFallback });
|
|
38
|
+
}
|
|
39
|
+
// Not authenticated
|
|
40
|
+
if (!isAuthenticated) {
|
|
41
|
+
onUnauthenticated?.();
|
|
42
|
+
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: fallback });
|
|
43
|
+
}
|
|
44
|
+
// Authenticated - render children
|
|
45
|
+
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Headless version with render props for full control
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* <RequireAuth.Headless>
|
|
52
|
+
* {({ isAuthenticated, isLoading, member }) => (
|
|
53
|
+
* isLoading ? <Spinner /> :
|
|
54
|
+
* isAuthenticated ? <Dashboard member={member} /> :
|
|
55
|
+
* <Redirect to="/login" />
|
|
56
|
+
* )}
|
|
57
|
+
* </RequireAuth.Headless>
|
|
58
|
+
*/
|
|
59
|
+
RequireAuth.Headless = function RequireAuthHeadless({ children, }) {
|
|
60
|
+
const { isAuthenticated, isLoading, member, user } = (0, AkinAuthProvider_1.useAkinAuth)();
|
|
61
|
+
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children({ isAuthenticated, isLoading, member, user }) });
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=RequireAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequireAuth.js","sourceRoot":"","sources":["../../../src/auth/components/RequireAuth.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;AA4Db,kCAqBC;;AA9ED,0DAAkD;AA+BlD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,eAAe,GAAG,IAAI,EACtB,QAAQ,GAAG,IAAI,EACf,iBAAiB,GACA;IACjB,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAA,8BAAW,GAAE,CAAC;IAEnE,2BAA2B;IAC3B,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,2DAAG,eAAe,GAAI,CAAC;IAChC,CAAC;IAED,oBAAoB;IACpB,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,iBAAiB,EAAE,EAAE,CAAC;QACtB,OAAO,2DAAG,QAAQ,GAAI,CAAC;IACzB,CAAC;IAED,kCAAkC;IAClC,OAAO,2DAAG,QAAQ,GAAI,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,WAAW,CAAC,QAAQ,GAAG,SAAS,mBAAmB,CAAC,EAClD,QAAQ,GAGT;IACC,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAA,8BAAW,GAAE,CAAC;IAEnE,OAAO,2DAAG,QAAQ,CAAC,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAI,CAAC;AACvE,CAAC,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface RequireGuestProps {
|
|
3
|
+
/**
|
|
4
|
+
* Content to render when user is NOT authenticated (guest)
|
|
5
|
+
*/
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* Content to render while authentication state is loading
|
|
9
|
+
* Defaults to null (render nothing)
|
|
10
|
+
*/
|
|
11
|
+
loadingFallback?: ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* Content to render when user IS authenticated
|
|
14
|
+
* Can be a redirect component or any other content
|
|
15
|
+
*/
|
|
16
|
+
fallback?: ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* Callback fired when user is authenticated
|
|
19
|
+
* Useful for programmatic redirects
|
|
20
|
+
*/
|
|
21
|
+
onAuthenticated?: () => void;
|
|
22
|
+
}
|
|
23
|
+
export interface RequireGuestRenderProps {
|
|
24
|
+
isAuthenticated: boolean;
|
|
25
|
+
isLoading: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Wrapper component that only renders children when user is NOT authenticated
|
|
29
|
+
* Useful for login/signup pages that should redirect authenticated users
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // With fallback redirect
|
|
33
|
+
* <RequireGuest fallback={<Navigate to="/dashboard" />}>
|
|
34
|
+
* <LoginPage />
|
|
35
|
+
* </RequireGuest>
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // With loading state
|
|
39
|
+
* <RequireGuest
|
|
40
|
+
* loadingFallback={<LoadingSpinner />}
|
|
41
|
+
* fallback={<Navigate to="/dashboard" />}
|
|
42
|
+
* >
|
|
43
|
+
* <LoginPage />
|
|
44
|
+
* </RequireGuest>
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // With callback
|
|
48
|
+
* <RequireGuest
|
|
49
|
+
* onAuthenticated={() => router.push('/dashboard')}
|
|
50
|
+
* >
|
|
51
|
+
* <LoginPage />
|
|
52
|
+
* </RequireGuest>
|
|
53
|
+
*/
|
|
54
|
+
export declare function RequireGuest({ children, loadingFallback, fallback, onAuthenticated, }: RequireGuestProps): import("react/jsx-runtime").JSX.Element;
|
|
55
|
+
export declare namespace RequireGuest {
|
|
56
|
+
var Headless: ({ children, }: {
|
|
57
|
+
children: (props: RequireGuestRenderProps) => ReactNode;
|
|
58
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=RequireGuest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequireGuest.d.ts","sourceRoot":"","sources":["../../../src/auth/components/RequireGuest.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,eAAsB,EACtB,QAAe,EACf,eAAe,GAChB,EAAE,iBAAiB,2CAgBnB;yBArBe,YAAY;kCAqCzB;QACD,QAAQ,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,SAAS,CAAC;KACzD"}
|