doct-ui-auth-kit 1.0.3 → 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.
Files changed (53) hide show
  1. package/README.md +15 -0
  2. package/dist/auth-methods/apple.d.ts +1 -1
  3. package/dist/auth-methods/index.d.ts +1 -0
  4. package/dist/components/form/rhf-doct-phone-input.d.ts +1 -1
  5. package/dist/components/form/rhf-input-field.d.ts +1 -1
  6. package/dist/components/form/rhf-otp-input-field.d.ts +1 -1
  7. package/dist/components/layout/image-slider.d.ts +2 -19
  8. package/dist/components/layout/main-layout.d.ts +2 -46
  9. package/dist/core/auth-api-adapter.d.ts +1 -39
  10. package/dist/core/auth-context.d.ts +4 -50
  11. package/dist/core/auth-provider.d.ts +2 -35
  12. package/dist/core/auth-types.d.ts +3 -68
  13. package/dist/core/device-detection.d.ts +2 -6
  14. package/dist/core/sso-session.d.ts +2 -30
  15. package/dist/core/use-auth-flow.d.ts +2 -75
  16. package/dist/doct-ui-auth-kit.css +1 -0
  17. package/dist/hooks/index.d.ts +2 -0
  18. package/dist/hooks/use-login-entry-form.d.ts +4 -28
  19. package/dist/hooks/use-main-auth-page-handlers.d.ts +8 -0
  20. package/dist/hooks/use-otp-verification.d.ts +7 -31
  21. package/dist/hooks/use-repeat-login.d.ts +7 -0
  22. package/dist/hooks/use-signup-form.d.ts +4 -44
  23. package/dist/index.d.ts +18 -9
  24. package/dist/index.js +2943 -3452
  25. package/dist/pages/index.d.ts +5 -5
  26. package/dist/pages/login-entry.d.ts +40 -21
  27. package/dist/pages/main-login.d.ts +30 -14
  28. package/dist/pages/otp-verification.d.ts +43 -21
  29. package/dist/pages/repeat-login.d.ts +47 -18
  30. package/dist/pages/signup.d.ts +43 -23
  31. package/dist/pages.js +10 -5
  32. package/dist/signup-BJWKwg7j.js +1723 -0
  33. package/dist/types/auth-api-adapter.d.ts +43 -0
  34. package/dist/types/auth-provider.d.ts +37 -0
  35. package/dist/types/auth-types.d.ts +70 -0
  36. package/dist/types/device-detection.d.ts +7 -0
  37. package/dist/types/flow.d.ts +125 -0
  38. package/dist/types/forms.d.ts +2 -0
  39. package/dist/types/index.d.ts +13 -0
  40. package/dist/types/layout.d.ts +57 -0
  41. package/dist/types/login-form.d.ts +39 -0
  42. package/dist/types/main-login.d.ts +29 -0
  43. package/dist/types/otp-verification.d.ts +28 -0
  44. package/dist/types/pages.d.ts +133 -0
  45. package/dist/types/repeat-login.d.ts +28 -0
  46. package/dist/types/signup-form.d.ts +41 -0
  47. package/dist/types/sso-session.d.ts +33 -0
  48. package/dist/utils/index.d.ts +4 -0
  49. package/dist/utils/set-form-errors-from-zod.d.ts +11 -0
  50. package/dist/validations/index.d.ts +6 -0
  51. package/dist/validations/schemas.d.ts +76 -0
  52. package/package.json +105 -104
  53. package/dist/signup-x-Jm7XKn.js +0 -668
package/README.md CHANGED
@@ -14,6 +14,21 @@ Peer dependencies (install in your app if not already present):
14
14
  npm install react react-dom docthub-core-components react-hook-form zod
15
15
  ```
16
16
 
17
+ ## Global styles
18
+
19
+ Import the kit CSS once in your app (e.g. in `main.tsx` or `_app.tsx`) so Tailwind and base styles apply:
20
+
21
+ ```tsx
22
+ import 'doct-ui-auth-kit/style.css';
23
+ ```
24
+
25
+ If you use `docthub-core-components`, import its styles first, then the auth kit:
26
+
27
+ ```tsx
28
+ import 'docthub-core-components/style.css';
29
+ import 'doct-ui-auth-kit/style.css';
30
+ ```
31
+
17
32
  ## Consumer imports
18
33
 
19
34
  Install the package and import components, layouts, and types from the library:
@@ -14,6 +14,6 @@ export interface UseAppleSignInOptions {
14
14
  * Stub: Apple Sign-In hook. Not implemented yet.
15
15
  * Use adapter.authenticateWithProvider({ provider: 'apple', credential }) when you have the token.
16
16
  */
17
- export declare function useAppleSignIn(_options: UseAppleSignInOptions): {
17
+ export declare function useAppleSignIn(options: UseAppleSignInOptions): {
18
18
  triggerSignIn: () => void;
19
19
  };
@@ -1 +1,2 @@
1
+ export { type UseAppleSignInOptions, useAppleSignIn, } from './apple';
1
2
  export { type UseGoogleAuthOptions, type UseGoogleAuthReturn, useGoogleAuth, } from './google';
@@ -1,2 +1,2 @@
1
1
  import type { RHFDoctPhoneInputFieldProps } from '@/types/forms';
2
- export declare function RHFDoctPhoneInputField({ name, label, placeholder, helperText, defaultCountry, variant, required, disabled, control, error, }: RHFDoctPhoneInputFieldProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function RHFDoctPhoneInputField({ name, label, placeholder, helperText, defaultCountry, variant, required, disabled, control, error, autoFocus, }: RHFDoctPhoneInputFieldProps): import("react/jsx-runtime").JSX.Element;
@@ -1,2 +1,2 @@
1
1
  import type { RHFInputFieldProps } from '@/types/forms';
2
- export declare function RHFInputField({ name, label, placeholder, className, control, required, type, disabled, onKeyDown, maxLength, numericOnly, }: RHFInputFieldProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function RHFInputField({ name, label, placeholder, className, control, required, type, disabled, onKeyDown, maxLength, numericOnly, autoFocus, }: RHFInputFieldProps): import("react/jsx-runtime").JSX.Element;
@@ -1,2 +1,2 @@
1
1
  import type { RHFOtpInputFieldProps } from '@/types/forms';
2
- export declare function RHFOtpInputField({ name, label, className, control, length, inputClassName, }: RHFOtpInputFieldProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function RHFOtpInputField({ name, label, className, control, length, inputClassName, autoFocus, }: RHFOtpInputFieldProps): import("react/jsx-runtime").JSX.Element;
@@ -1,22 +1,5 @@
1
- /**
2
- * Props for the ImageSlider component.
3
- */
4
- export interface ImageSliderProps {
5
- /** Array of image URLs to display */
6
- images: string[];
7
- /** Auto-play interval in milliseconds (0 to disable) */
8
- autoPlayInterval?: number;
9
- /** Additional className for the root container */
10
- className?: string;
11
- /** Whether to hide the built-in slider indicators */
12
- hideIndicators?: boolean;
13
- /** Optional callback fired whenever the active slide changes */
14
- onSlideChange?: (index: number) => void;
15
- /** Controlled active index (makes component controlled) */
16
- activeIndex?: number;
17
- /** Callback for manual slide navigation in controlled mode */
18
- onNavigate?: (index: number) => void;
19
- }
1
+ import type { ImageSliderProps } from '@/types';
2
+ export type { ImageSliderProps } from '@/types';
20
3
  /**
21
4
  * Image slider component with indicator dots.
22
5
  * Supports both controlled and uncontrolled modes.
@@ -1,49 +1,5 @@
1
- import { type ReactNode } from 'react';
2
- /**
3
- * Props for the MainLayout component.
4
- *
5
- * @remarks
6
- * This layout provides a two-panel authentication page structure:
7
- * - Left panel: Marketing content with image slider, CTA, and image card
8
- * - Right panel: Authentication content (provided as children)
9
- */
10
- export interface MainLayoutProps {
11
- /** Array of image URLs for the slider */
12
- sliderImages?: string[];
13
- /** Auto-play interval for slider in milliseconds (0 to disable) */
14
- sliderAutoPlayInterval?: number;
15
- /** Call-to-action text displayed above the image card. Set to null to hide */
16
- ctaText?: ReactNode | null;
17
- /** Per-slide title/CTA (overrides ctaText when provided; uses active slide index) */
18
- sliderTitles?: (ReactNode | string)[] | undefined;
19
- /** Additional className for the root container */
20
- className?: string;
21
- /** Additional className for the marketing panel (left side) */
22
- marketingClassName?: string;
23
- /** Additional className for the content panel (right side) */
24
- contentClassName?: string;
25
- /** Main authentication content (typically AuthLayout.Root with slots) */
26
- children: ReactNode;
27
- }
28
- /**
29
- * Props for the MarketingPanel component (left side)
30
- */
31
- export interface MarketingPanelProps {
32
- /** Array of image URLs for the slider */
33
- sliderImages: string[];
34
- /** Auto-play interval for slider in milliseconds */
35
- sliderAutoPlayInterval: number;
36
- /** Active slide index (controlled) */
37
- activeSlideIndex: number;
38
- /** Callback when slide changes */
39
- onSlideChange: (index: number) => void;
40
- /** Call-to-action text */
41
- ctaText?: ReactNode | null;
42
- /** Per-slide title/CTA (overrides ctaText when provided) */
43
- sliderTitles?: (ReactNode | string)[] | undefined;
44
- /** Additional className */
45
- className?: string;
46
- }
1
+ import type { MainLayoutProps, MarketingPanelProps } from '@/types';
2
+ export type { MainLayoutProps, MarketingPanelProps } from '@/types';
47
3
  /**
48
4
  * Marketing panel component - displays CTA, image slider, and indicators
49
5
  */
@@ -3,42 +3,4 @@
3
3
  * Consumers implement this to connect the SDK to their central auth service.
4
4
  * The SDK never performs HTTP calls directly.
5
5
  */
6
- import type { AuthenticateWithProviderParams, CompleteProfileParams, SendOtpResponse, SSOSession, VerifyOtpResponse } from './auth-types';
7
- /** Parameters for sending OTP to phone or email. */
8
- export interface SendOtpParams {
9
- type: 'phone' | 'email';
10
- value: string;
11
- }
12
- /** Parameters for verifying OTP. */
13
- export interface VerifyOtpParams {
14
- type: 'phone' | 'email';
15
- value: string;
16
- otp: string;
17
- }
18
- /**
19
- * Adapter implemented by the consumer to talk to the central auth service.
20
- * All methods return promises; the SDK handles loading/error state.
21
- */
22
- export interface AuthApiAdapter {
23
- /** Send OTP to the given phone or email. */
24
- sendOtp(params: SendOtpParams): Promise<SendOtpResponse>;
25
- /**
26
- * Verify OTP. Returns session if existing user, or isNewUser flag for profile completion.
27
- * May return conflict error when identifier is linked to another account.
28
- */
29
- verifyOtp(params: VerifyOtpParams): Promise<VerifyOtpResponse>;
30
- /** Complete profile for new users; returns SSO session. */
31
- completeProfile(params: CompleteProfileParams): Promise<SSOSession>;
32
- /** Authenticate with a third-party provider (Google/Apple) credential. */
33
- authenticateWithProvider(params: AuthenticateWithProviderParams): Promise<VerifyOtpResponse>;
34
- /** Validate an existing SSO session token; called on SDK mount. Returns null if invalid/expired. */
35
- validateSession(token: string): Promise<SSOSession | null>;
36
- /**
37
- * Optional: validate session using server-read cookie (no token from client).
38
- * Required when using serverCookieTokenStorage. Client sends credentials;
39
- * server reads cookie from the request and returns session or null.
40
- */
41
- validateSessionFromCookie?(): Promise<SSOSession | null>;
42
- /** Optional: refresh an expired SSO session using refresh token. */
43
- refreshSession?(refreshToken: string): Promise<SSOSession | null>;
44
- }
6
+ export type { AuthApiAdapter, SendOtpParams, VerifyOtpParams, } from '@/types';
@@ -1,51 +1,5 @@
1
- import type { SSOSession } from './auth-types';
2
- import type { AuthFlowState } from './use-auth-flow';
3
- /** Provider config slice exposed to flow for Google/Apple wiring. */
4
- export interface AuthFlowProviderConfig {
5
- google?: {
6
- clientId: string;
7
- enableOneTap?: boolean;
8
- };
9
- apple?: {
10
- clientId: string;
11
- redirectUri: string;
12
- };
13
- }
14
- /** Async actions that perform I/O and dispatch to the flow reducer. */
15
- export interface AuthFlowActions {
16
- selectMethod: (method: 'phone' | 'email' | 'google' | 'apple') => void;
17
- /** From REPEAT_LOGIN: continue with last used method. */
18
- continueWithLastMethod: () => void;
19
- submitIdentifier: (data: {
20
- phone?: string;
21
- email?: string;
22
- }) => void;
23
- /** SIGNUP_DETAILS step: submit name + phone/email, then OTP (foreign) or complete (Indian). */
24
- submitSignupDetails: (data: {
25
- fullName: string;
26
- phone?: string;
27
- email?: string;
28
- }) => void;
29
- verifyOtp: (otp: string) => void;
30
- resendOtp: () => void;
31
- providerCallback: (params: {
32
- provider: 'google' | 'apple';
33
- credential: string;
34
- }) => void;
35
- goBack: () => void;
36
- reset: () => void;
37
- signOut: () => void;
38
- }
39
- export interface AuthFlowContextValue {
40
- state: AuthFlowState;
41
- actions: AuthFlowActions;
42
- /** Session when step is AUTHENTICATED. */
43
- session: SSOSession | null;
44
- /** True while step is CHECKING_SESSION. */
45
- isLoading: boolean;
46
- /** Provider config for Google/Apple (One Tap, Sign-In button). */
47
- providerConfig: AuthFlowProviderConfig | undefined;
48
- }
1
+ import type { AuthFlowContextValue } from '@/types';
2
+ export type { AuthFlowActions, AuthFlowContextValue, AuthFlowProviderConfig, } from '@/types';
49
3
  export declare const AuthFlowContext: import("react").Context<AuthFlowContextValue | null>;
50
4
  /**
51
5
  * Hook to access auth flow state and actions. Must be used within SSOAuthProvider.
@@ -55,9 +9,9 @@ export declare function useAuthFlow(): AuthFlowContextValue;
55
9
  * Hook to access SSO session state only. Must be used within SSOAuthProvider.
56
10
  */
57
11
  export declare function useAuthSession(): {
58
- session: SSOSession | null;
12
+ session: import("@/types").SSOSession | null;
59
13
  isAuthenticated: boolean;
60
14
  isLoading: boolean;
61
15
  signOut: () => void;
62
- authMethod: import("./auth-types").AuthMethod | null;
16
+ authMethod: import("@/types").AuthMethod | null;
63
17
  };
@@ -1,38 +1,5 @@
1
- import type { AuthApiAdapter } from './auth-api-adapter';
2
- import type { AuthError, SSOSession } from './auth-types';
3
- import type { TokenStorageStrategy } from './sso-session';
4
- export interface SSOAuthConfig {
5
- /** Consumer-provided adapter to their central auth service. */
6
- apiAdapter: AuthApiAdapter;
7
- /** Auth method configs (Google client ID, Apple client ID, etc.). */
8
- providers?: {
9
- google?: {
10
- clientId: string;
11
- enableOneTap?: boolean;
12
- };
13
- apple?: {
14
- clientId: string;
15
- redirectUri: string;
16
- };
17
- };
18
- /** Called when SSO session is established (any method). */
19
- onAuthSuccess: (session: SSOSession) => void;
20
- /** Called on auth errors. */
21
- onAuthError?: (error: AuthError) => void;
22
- /** Optional: called when user signs out. */
23
- onSignOut?: () => void;
24
- /** SSO token persistence strategy. Defaults to localStorage. */
25
- tokenStorage?: TokenStorageStrategy;
26
- /** Branding customization (logo, slider images). */
27
- branding?: {
28
- logo?: React.ReactNode;
29
- sliderImages?: string[];
30
- };
31
- }
32
- export interface SSOAuthProviderProps {
33
- config: SSOAuthConfig;
34
- children: React.ReactNode;
35
- }
1
+ import type { SSOAuthProviderProps } from '@/types';
2
+ export type { SSOAuthConfig, SSOAuthProviderProps } from '@/types';
36
3
  /**
37
4
  * SSO Auth provider: runs session check on mount, holds flow state, and provides async actions.
38
5
  */
@@ -1,70 +1,5 @@
1
1
  /**
2
- * SSO auth domain types: session, flow steps, adapter contracts, and error codes.
3
- * Used by the flow engine, provider, and adapter implementations.
2
+ * Re-export of auth domain types from central types folder.
3
+ * Prefer importing from @/types; this file keeps @/core/auth-types working.
4
4
  */
5
- /** Auth methods available in the SSO system. */
6
- export type AuthMethod = 'phone' | 'email' | 'google' | 'apple';
7
- /** User payload in the SSO session. */
8
- export interface SSOUser {
9
- id: string;
10
- name: string;
11
- email?: string;
12
- phone?: string;
13
- avatar?: string;
14
- isNewUser: boolean;
15
- }
16
- /** The SSO session — same structure regardless of auth method used. */
17
- export interface SSOSession {
18
- accessToken: string;
19
- refreshToken?: string;
20
- expiresAt: number;
21
- user: SSOUser;
22
- authMethod: AuthMethod;
23
- }
24
- /** User type for layout and OTP routing: Indian (+91) vs Foreign (non +91). */
25
- export type UserType = 'INDIAN' | 'FOREIGN';
26
- /** Flow states for the state machine. */
27
- export type AuthStep = 'CHECKING_SESSION' | 'REPEAT_LOGIN' | 'METHOD_SELECT' | 'PHONE_ENTRY' | 'EMAIL_ENTRY' | 'OTP_VERIFICATION' | 'SIGNUP_DETAILS' | 'PROVIDER_PENDING' | 'AUTHENTICATED';
28
- /** Error codes from the central auth service. */
29
- export type AuthErrorCode = 'IDENTIFIER_CONFLICT' | 'OTP_EXPIRED' | 'OTP_INVALID' | 'OTP_RATE_LIMIT' | 'SESSION_EXPIRED' | 'PROVIDER_AUTH_FAILED' | 'NETWORK_ERROR' | 'UNKNOWN';
30
- /** Auth error with code and optional message / linked identifier. */
31
- export interface AuthError {
32
- code: AuthErrorCode;
33
- message?: string;
34
- /** Masked linked identifier when conflict (e.g. "+91 98XXXX0X0X"). */
35
- linkedIdentifier?: string;
36
- }
37
- /** Response from sendOtp. */
38
- export interface SendOtpResponse {
39
- success: boolean;
40
- /** Masked value for display (e.g. "+91 9825910X0X" or "j***@gmail.com"). */
41
- maskedValue?: string;
42
- error?: AuthError;
43
- }
44
- /** Result of verifyOtp or authenticateWithProvider: existing user gets session, new user gets profile step. */
45
- export interface VerifyOtpResponse {
46
- /** Present when user exists and is authenticated. */
47
- session?: SSOSession;
48
- /** True when user is new and must complete profile. */
49
- isNewUser: boolean;
50
- /** When isNewUser and conflict (e.g. email already linked), masked linked identifier. */
51
- conflict?: AuthError;
52
- }
53
- /** Input for completeProfile (new users). */
54
- export interface CompleteProfileParams {
55
- fullName: string;
56
- email?: string;
57
- phone?: string;
58
- }
59
- /** Input for authenticateWithProvider (Google/Apple credential). */
60
- export interface AuthenticateWithProviderParams {
61
- provider: 'google' | 'apple';
62
- /** Id token or equivalent from the provider. */
63
- credential: string;
64
- }
65
- /** Repeat-login device history (method + masked identifier). */
66
- export interface RepeatLoginInfo {
67
- method: AuthMethod;
68
- maskedIdentifier: string;
69
- timestamp: number;
70
- }
5
+ export type { AuthError, AuthErrorCode, AuthenticateWithProviderParams, AuthMethod, AuthStep, CompleteProfileParams, RepeatLoginInfo, SendOtpResponse, SSOSession, SSOUser, UserType, VerifyOtpResponse, } from '@/types';
@@ -2,12 +2,8 @@
2
2
  * Device-based repeat login detection.
3
3
  * Stores last-used method and masked identifier in localStorage (device-local UX only).
4
4
  */
5
- import type { AuthMethod } from './auth-types';
6
- export interface StoredRepeatLogin {
7
- method: AuthMethod;
8
- maskedIdentifier: string;
9
- timestamp: number;
10
- }
5
+ import type { StoredRepeatLogin } from '@/types';
6
+ export type { StoredRepeatLogin } from '@/types';
11
7
  /**
12
8
  * Reads repeat-login info from localStorage if present.
13
9
  * Safe to call in browser; returns null in SSR or when not found.
@@ -2,12 +2,8 @@
2
2
  * SSO session management: token persistence strategies and useAuthSession hook.
3
3
  * Token storage is consumer-configurable for cross-app SSO (e.g. shared cookie domain).
4
4
  */
5
- /** How/where the SSO token is stored for cross-app access. */
6
- export interface TokenStorageStrategy {
7
- get(): string | null;
8
- set(token: string, expiresAt: number): void;
9
- remove(): void;
10
- }
5
+ import type { AxiosAuthInterceptorInstance, TokenStorageStrategy } from '@/types';
6
+ export type { AxiosAuthInterceptorInstance, AxiosRequestConfig, TokenStorageStrategy, } from '@/types';
11
7
  /**
12
8
  * Token storage using localStorage (single-origin).
13
9
  * Suitable for dev or when all Docthub apps share the same origin.
@@ -21,30 +17,6 @@ export declare function localStorageTokenStorage(): TokenStorageStrategy;
21
17
  * cookie is sent on every request.
22
18
  */
23
19
  export declare function serverCookieTokenStorage(): TokenStorageStrategy;
24
- /**
25
- * Axios instance shape needed to attach auth interceptors (avoids hard axios dependency).
26
- * Use createAxiosAuthInterceptors with your axios instance.
27
- */
28
- export interface AxiosAuthInterceptorInstance {
29
- interceptors: {
30
- request: {
31
- use(onFulfilled?: (config: AxiosRequestConfig) => AxiosRequestConfig | Promise<AxiosRequestConfig>, onRejected?: (err: unknown) => unknown): number;
32
- };
33
- response: {
34
- use(onFulfilled?: (res: unknown) => unknown, onRejected?: (err: unknown) => unknown): number;
35
- };
36
- };
37
- defaults: {
38
- withCredentials?: boolean;
39
- };
40
- }
41
- /** Minimal request config type for the interceptor (no axios import). */
42
- export interface AxiosRequestConfig {
43
- headers?: Record<string, string> | {
44
- [key: string]: string;
45
- };
46
- withCredentials?: boolean;
47
- }
48
20
  /**
49
21
  * Attaches request and response interceptors to an axios instance for SSO auth
50
22
  * when using server-side cookies (e.g. serverCookieTokenStorage):
@@ -2,81 +2,8 @@
2
2
  * Auth flow state machine: reducer and state type.
3
3
  * Side effects (API calls, token persistence) are performed by the provider; this module is pure.
4
4
  */
5
- import type { AuthStep, SSOSession, UserType } from './auth-types';
6
- /** Identifier type for OTP / profile steps. */
7
- export type IdentifierType = 'phone' | 'email';
8
- /** Full state for the auth flow. */
9
- export interface AuthFlowState {
10
- step: AuthStep;
11
- /** Previous step for goBack. */
12
- lastStep: AuthStep;
13
- /** Indian (+91) vs Foreign (non +91); drives layout and OTP routing. */
14
- userType: UserType;
15
- /** Current identifier value (phone or email) when in OTP or signup. */
16
- identifierValue: string;
17
- /** Type of identifier (phone vs email). */
18
- identifierType: IdentifierType;
19
- /** Masked value for display (e.g. "+91 9825910X0X"). */
20
- maskedRecipient: string;
21
- /** For SIGNUP_DETAILS (Indian): which field to collect (phone or email). */
22
- signupCollectField: IdentifierType;
23
- /** For REPEAT_LOGIN: last used method label. */
24
- lastMethod: string;
25
- /** Set when step is AUTHENTICATED. */
26
- session: SSOSession | null;
27
- /** Foreign flow: phone value when user entered phone before signup details. */
28
- pendingPhone: string;
29
- /** Foreign flow: signup form data for completeProfile after OTP verify. */
30
- pendingFullName: string;
31
- pendingEmail: string;
32
- }
5
+ import type { AuthFlowAction, AuthFlowState, AuthStep } from '@/types';
6
+ export type { AuthFlowAction, AuthFlowState, IdentifierType } from '@/types';
33
7
  export declare const INITIAL_STEP: AuthStep;
34
8
  export declare function getInitialAuthFlowState(): AuthFlowState;
35
- /** Pure reducer actions. */
36
- export type AuthFlowAction = {
37
- type: 'SET_SESSION';
38
- session: SSOSession;
39
- } | {
40
- type: 'SET_STEP_REPEAT_LOGIN';
41
- lastMethod: string;
42
- maskedIdentifier: string;
43
- } | {
44
- type: 'SET_STEP_METHOD_SELECT';
45
- } | {
46
- type: 'SET_STEP_PHONE_ENTRY';
47
- } | {
48
- type: 'SET_STEP_EMAIL_ENTRY';
49
- } | {
50
- type: 'SET_STEP_OTP_VERIFICATION';
51
- userType: UserType;
52
- identifierType: IdentifierType;
53
- value: string;
54
- maskedValue: string;
55
- /** Foreign flow: for completeProfile after OTP. */
56
- pendingFullName?: string;
57
- pendingEmail?: string;
58
- pendingPhone?: string;
59
- } | {
60
- type: 'SET_STEP_SIGNUP_DETAILS';
61
- userType: UserType;
62
- /** Indian: which field to collect (phone or email). Foreign: ignored. */
63
- signupCollectField: IdentifierType;
64
- /** Foreign only: phone value when user entered phone before signup. */
65
- pendingPhone?: string;
66
- /** When coming from identifier entry (foreign): preserve for later OTP. */
67
- identifierType?: IdentifierType;
68
- identifierValue?: string;
69
- maskedRecipient?: string;
70
- } | {
71
- type: 'SET_STEP_PROVIDER_PENDING';
72
- } | {
73
- type: 'SET_STEP_AUTHENTICATED';
74
- session: SSOSession;
75
- } | {
76
- type: 'GO_BACK';
77
- } | {
78
- type: 'RESET';
79
- } | {
80
- type: 'SIGN_OUT';
81
- };
82
9
  export declare function authFlowReducer(state: AuthFlowState, action: AuthFlowAction): AuthFlowState;
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--font-inter),Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media(min-width:640px){.container{max-width:640px}}@media(min-width:768px){.container{max-width:768px}}@media(min-width:1024px){.container{max-width:1024px}}@media(min-width:1280px){.container{max-width:1280px}}@media(min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.-top-10{top:-2.5rem}.left-1\/2{left:50%}.top-2\.5{top:.625rem}.top-\[152\.5px\]{top:152.5px}.z-10{z-index:10}.z-20{z-index:20}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.block{display:block}.inline{display:inline}.flex{display:flex}.hidden{display:none}.h-1{height:.25rem}.h-10{height:2.5rem}.h-5{height:1.25rem}.h-\[100dvh\]{height:100dvh}.h-\[30px\]{height:30px}.h-full{height:100%}.min-h-0{min-height:0px}.min-h-svh{min-height:100svh}.w-10{width:2.5rem}.w-2{width:.5rem}.w-5{width:1.25rem}.w-8{width:2rem}.w-\[140px\]{width:140px}.w-\[328px\]{width:328px}.w-auto{width:auto}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0px}.min-w-full{min-width:100%}.max-w-\[320px\]{max-width:320px}.max-w-\[360px\]{max-width:360px}.max-w-\[400px\]{max-width:400px}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-\[12px\]{gap:12px}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.whitespace-pre-line{white-space:pre-line}.rounded-\[10px\]{border-radius:10px}.rounded-\[3px\]{border-radius:3px}.border{border-width:1px}.border-\[rgba\(0\,0\,0\,0\.12\)\]{border-color:#0000001f}.bg-\[\#002830\]{--tw-bg-opacity: 1;background-color:rgb(0 40 48 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/40{background-color:#fff6}.bg-white\/50{background-color:#ffffff80}.object-cover{-o-object-fit:cover;object-fit:cover}.object-center{-o-object-position:center;object-position:center}.p-2{padding:.5rem}.p-8{padding:2rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-\[22px\]{padding-left:22px;padding-right:22px}.py-12{padding-top:3rem;padding-bottom:3rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.py-\[14px\]{padding-top:14px;padding-bottom:14px}.pt-5{padding-top:1.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-bold{font-weight:700}.font-semibold{font-weight:600}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.text-\[\#002830\]{--tw-text-opacity: 1;color:rgb(0 40 48 / var(--tw-text-opacity, 1))}.text-\[\#1e595a\]{--tw-text-opacity: 1;color:rgb(30 89 90 / var(--tw-text-opacity, 1))}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity, 1))}.text-black\/80{color:#000c}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.opacity-80{opacity:.8}.outline{outline-style:solid}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}@keyframes enter{0%{opacity:var(--tw-enter-opacity, 1);transform:translate3d(var(--tw-enter-translate-x, 0),var(--tw-enter-translate-y, 0),0) scale3d(var(--tw-enter-scale, 1),var(--tw-enter-scale, 1),var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity, 1);transform:translate3d(var(--tw-exit-translate-x, 0),var(--tw-exit-translate-y, 0),0) scale3d(var(--tw-exit-scale, 1),var(--tw-exit-scale, 1),var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0))}}.duration-300{animation-duration:.3s}.duration-500{animation-duration:.5s}.ease-in-out{animation-timing-function:cubic-bezier(.4,0,.2,1)}:root{font-family:var( --font-inter, "Inter", system-ui, Avenir, Helvetica, Arial, sans-serif );line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{margin:0;min-width:320px;min-height:100vh}#root{min-height:100vh;width:100%}.hover\:bg-white\/60:hover{background-color:#fff9}@media(min-width:640px){.sm\:flex{display:flex}}@media(min-width:768px){.md\:mb-6{margin-bottom:1.5rem}.md\:px-\[20px\]{padding-left:20px;padding-right:20px}.md\:py-12{padding-top:3rem;padding-bottom:3rem}.md\:py-8{padding-top:2rem;padding-bottom:2rem}.md\:pt-\[20px\]{padding-top:20px}}@media(min-width:1024px){.lg\:block{display:block}.lg\:h-\[100dvh\]{height:100dvh}.lg\:w-\[432px\]{width:432px}.lg\:flex-shrink-0{flex-shrink:0}.lg\:flex-grow-0{flex-grow:0}.lg\:flex-row{flex-direction:row}}
@@ -1,3 +1,5 @@
1
1
  export { type EmailFormValues, type LoginEntryFormValues, type LoginEntryMode, type PhoneFormValues, type UseLoginEntryFormOptions, type UseLoginEntryFormReturn, useLoginEntryForm, } from './use-login-entry-form';
2
+ export { type MainAuthPageHandlers, type MainLoginAppleProviderConfig, type MainLoginGoogleProviderConfig, type MainLoginPageProvidersConfig, type UseMainAuthPageHandlersOptions, useMainAuthPageHandlers, } from './use-main-auth-page-handlers';
2
3
  export { DEFAULT_OTP_TITLES, OTP_LENGTH, type OtpFormValues, type OtpVerificationMode, RESEND_COOLDOWN_EMAIL_SECONDS, RESEND_COOLDOWN_PHONE_SECONDS, type UseOtpVerificationOptions, type UseOtpVerificationReturn, useOtpVerification, } from './use-otp-verification';
4
+ export { type UseRepeatLoginOptions, type UseRepeatLoginReturn, useRepeatLogin, } from './use-repeat-login';
3
5
  export { type SignupEmailFormValues, type SignupEntryMode, type SignupFormValues, type SignupPhoneFormValues, type UseSignupFormOptions, type UseSignupFormReturn, useSignupForm, } from './use-signup-form';
@@ -1,32 +1,8 @@
1
- import type { UseFormReturn } from 'react-hook-form';
2
- import { z } from 'zod';
3
- /** Login mode: phone number or email */
4
- export type LoginEntryMode = 'phone' | 'email';
5
- declare const phoneFormSchema: z.ZodObject<{
6
- phone: z.ZodString;
7
- }, z.core.$strip>;
8
- declare const emailFormSchema: z.ZodObject<{
9
- email: z.ZodString;
10
- }, z.core.$strip>;
11
- export type PhoneFormValues = z.infer<typeof phoneFormSchema>;
12
- export type EmailFormValues = z.infer<typeof emailFormSchema>;
13
- export type LoginEntryFormValues = PhoneFormValues | EmailFormValues;
14
- export interface UseLoginEntryFormOptions {
15
- mode: LoginEntryMode;
16
- /** Called with valid form data on submit. Omit or pass undefined when not needed. */
17
- onSubmit?: ((data: {
18
- phone?: string;
19
- email?: string;
20
- }) => void) | undefined;
21
- }
22
- export interface UseLoginEntryFormReturn {
23
- methods: UseFormReturn<LoginEntryFormValues>;
24
- handleSubmit: (data: LoginEntryFormValues) => void;
25
- isPhone: boolean;
26
- }
1
+ import type { UseLoginEntryFormOptions, UseLoginEntryFormReturn } from '@/types';
2
+ export type { EmailFormValues, LoginEntryFormValues, LoginEntryMode, LoginEntrySubmitData, PhoneFormValues, UseLoginEntryFormOptions, UseLoginEntryFormReturn, } from '@/types';
27
3
  /**
28
4
  * Form state and validation for the login entry screen (phone or email).
5
+ * Business logic: when submitApi is provided, hook runs validate → submitApi(data) → onSuccess() (e.g. redirect).
29
6
  * Use with LoginEntry component or build a custom UI with the returned methods.
30
7
  */
31
- export declare function useLoginEntryForm({ mode, onSubmit, }: UseLoginEntryFormOptions): UseLoginEntryFormReturn;
32
- export {};
8
+ export declare function useLoginEntryForm({ mode, onSubmit, submitApi, onSuccess, onError, }: UseLoginEntryFormOptions): UseLoginEntryFormReturn;
@@ -0,0 +1,8 @@
1
+ import type { MainAuthPageHandlers, UseMainAuthPageHandlersOptions } from '@/types';
2
+ export type { MainAuthPageHandlers, MainLoginAppleProviderConfig, MainLoginGoogleProviderConfig, MainLoginPageProvidersConfig, UseMainAuthPageHandlersOptions, } from '@/types';
3
+ /**
4
+ * Main auth page business logic: resolves CTA handlers from optional overrides and optional provider config.
5
+ * When providers.google / providers.apple are set, the lib runs Google/Apple OAuth and calls onCredential;
6
+ * otherwise uses overrides or no-op defaults.
7
+ */
8
+ export declare function useMainAuthPageHandlers(options?: Readonly<UseMainAuthPageHandlersOptions>): MainAuthPageHandlers;
@@ -1,36 +1,12 @@
1
- import type { UseFormReturn } from 'react-hook-form';
2
- import { z } from 'zod';
3
- /** OTP verification mode: mobile (phone) or email */
4
- export type OtpVerificationMode = 'phone' | 'email';
5
- export declare const OTP_LENGTH = 6;
6
- /** Resend cooldown: 60s for phone OTP, 2 min for email OTP (per design). */
7
- export declare const RESEND_COOLDOWN_PHONE_SECONDS = 60;
8
- export declare const RESEND_COOLDOWN_EMAIL_SECONDS = 120;
9
- export declare function getResendCooldownSeconds(mode: OtpVerificationMode): number;
10
- declare const otpFormSchema: z.ZodObject<{
11
- otp: z.ZodArray<z.ZodString>;
12
- }, z.core.$strip>;
13
- export type OtpFormValues = z.infer<typeof otpFormSchema>;
14
- export declare const DEFAULT_OTP_TITLES: Record<OtpVerificationMode, string>;
1
+ import type { OtpVerificationMode, UseOtpVerificationOptions, UseOtpVerificationReturn } from '@/types';
2
+ export type { OtpFormValues, OtpVerificationMode, UseOtpVerificationOptions, UseOtpVerificationReturn, } from '@/types';
15
3
  /** Instruction line below recipient (Figma: "Kindly check your Email Inbox."). */
16
4
  export declare const DEFAULT_OTP_INSTRUCTIONS: Record<OtpVerificationMode, string>;
17
- export interface UseOtpVerificationOptions {
18
- /** OTP mode: phone (60s cooldown) or email (2 min cooldown). */
19
- mode: OtpVerificationMode;
20
- onSubmit?: ((otp: string) => void) | undefined;
21
- onResendCode?: (() => void) | undefined;
22
- }
23
- export interface UseOtpVerificationReturn {
24
- methods: UseFormReturn<OtpFormValues>;
25
- handleSubmit: (data: OtpFormValues) => void;
26
- handleResend: () => void;
27
- resendSecondsLeft: number;
28
- canResend: boolean;
29
- timerText: string;
30
- }
5
+ export declare const DEFAULT_OTP_TITLES: Record<OtpVerificationMode, string>;
6
+ /** Re-export for consumers who import from hooks. */
7
+ export { getResendCooldownSeconds, OTP_LENGTH, RESEND_COOLDOWN_EMAIL_SECONDS, RESEND_COOLDOWN_PHONE_SECONDS, } from '@/validations';
31
8
  /**
32
9
  * Form state, resend countdown, and validation for OTP verification.
33
- * Use with OtpVerification component or build a custom OTP UI.
10
+ * When submitApi is provided, hook runs: validate submitApi(otp) → onSuccess() (e.g. redirect).
34
11
  */
35
- export declare function useOtpVerification({ mode, onSubmit, onResendCode, }: UseOtpVerificationOptions): UseOtpVerificationReturn;
36
- export {};
12
+ export declare function useOtpVerification({ mode, onSubmit, onResendCode, submitApi, onSuccess, onError, }: UseOtpVerificationOptions): UseOtpVerificationReturn;
@@ -0,0 +1,7 @@
1
+ import type { UseRepeatLoginOptions, UseRepeatLoginReturn } from '@/types';
2
+ export type { UseRepeatLoginOptions, UseRepeatLoginReturn } from '@/types';
3
+ /**
4
+ * Business logic for repeat login: continue with last method (sync or async via continueApi).
5
+ * When continueApi is provided, runs: continueApi() → onSuccess(); otherwise calls onContinueWithLastMethod.
6
+ */
7
+ export declare function useRepeatLogin(options?: UseRepeatLoginOptions): UseRepeatLoginReturn;