@dloizides/auth-web 1.2.1 → 1.2.2

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/labels.ts","../src/components/testIds.ts","../src/components/useAuthStyles.ts","../src/hooks/useBffAuth.ts","../src/theme/AuthTheme.ts","../src/theme/AuthThemeProvider.tsx","../src/components/LoginForm.tsx","../src/hooks/useBffPasswordHooks.ts","../src/components/ForgotPasswordForm.tsx","../src/hooks/ResetPasswordError.ts","../src/password/PasswordPolicyError.ts","../src/password/passwordPolicy.ts","../src/hooks/useResetPasswordForm.ts","../src/components/ResetPasswordForm.tsx","../src/components/OtpFormSteps.tsx","../src/hooks/OtpLoginStep.ts","../src/hooks/useOtpLogin.ts","../src/components/OtpForm.tsx","../src/hooks/usePinLogin.ts","../src/components/PinForm.tsx","../src/client/createBffAuthClient.ts","../src/router/resolvePostLoginRoute.ts"],"names":["useMemo","StyleSheet","BffAuthStatus","useState","useRef","useEffect","useCallback","createContext","useContext","jsx","View","jsxs","Text","TextInput","TouchableOpacity","ActivityIndicator","useMutation","Fragment","ResetPasswordError","PasswordPolicyError","OtpLoginStep","toError","EMAIL_REGEX","isValidEmail","transportErrorFor","createFetchHttpClient","BffAuthClient"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Label bags for the auth components.\n *\n * `@dloizides/auth-web` ships **no** translation framework — it is i18n-agnostic\n * by design (each app already owns its own i18n). Every user-facing string a\n * component renders is supplied by the consuming app through a typed `labels`\n * prop. The app passes strings it has already localised with `FM()` / `t()`.\n *\n * Each bag has a `DEFAULT_*` constant (English) so a component renders sensibly\n * with no `labels` prop and a consuming app can spread-override only the keys\n * it wants to change.\n */\n\n/** Strings rendered by `<LoginForm>`. */\nexport interface LoginFormLabels {\n title: string;\n subtitle: string;\n usernameLabel: string;\n usernamePlaceholder: string;\n passwordLabel: string;\n passwordPlaceholder: string;\n submit: string;\n /** Shown while the login request is in flight. */\n submitting: string;\n /** The \"Forgot password?\" link text. */\n forgotPassword: string;\n /** Generic credentials-rejected message. */\n invalidCredentials: string;\n /** Shown when one or both fields are empty on submit. */\n missingFields: string;\n}\n\n/** Strings rendered by `<ForgotPasswordForm>`. */\nexport interface ForgotPasswordFormLabels {\n title: string;\n /** Copy above the email field. */\n description: string;\n emailLabel: string;\n emailPlaceholder: string;\n submit: string;\n submitting: string;\n /** Generic confirmation, shown regardless of whether the email is registered. */\n successMessage: string;\n /** Shown on a network / 5xx failure. */\n networkError: string;\n /** Shown when the entered value is not a valid email. */\n invalidEmail: string;\n}\n\n/** Strings rendered by `<OtpForm>` — the two-step email-OTP login form. */\nexport interface OtpFormLabels {\n // ── Step 1: request a code ────────────────────────────────────────────────\n /** Title shown on the request-a-code step. */\n requestTitle: string;\n /** Copy above the email field. */\n requestDescription: string;\n emailLabel: string;\n emailPlaceholder: string;\n /** The \"send code\" button. */\n requestSubmit: string;\n /** Shown while the request is in flight. */\n requesting: string;\n /** Shown when the entered value is not a valid email. */\n invalidEmail: string;\n\n // ── Step 2: enter the code ────────────────────────────────────────────────\n /** Title shown on the enter-the-code step. */\n verifyTitle: string;\n /** Copy above the code field; `{identifier}` is replaced with the email. */\n verifyDescription: string;\n codeLabel: string;\n codePlaceholder: string;\n /** The \"verify\" button. */\n verifySubmit: string;\n /** Shown while verification is in flight. */\n verifying: string;\n /** Shown when the code field is empty on submit. */\n missingCode: string;\n /** Generic \"that code was wrong / expired\" message. */\n invalidCode: string;\n\n // ── Step 2 affordances ────────────────────────────────────────────────────\n /** The \"resend code\" link text. */\n resend: string;\n /** Shown while a resend is in flight. */\n resending: string;\n /** The \"use a different email\" link text — returns to step 1. */\n changeEmail: string;\n}\n\n/** Strings rendered by `<PinForm>` — the single-step event-PIN login form. */\nexport interface PinFormLabels {\n /** Title shown above the PIN field. */\n title: string;\n /** Copy above the PIN field. */\n description: string;\n pinLabel: string;\n pinPlaceholder: string;\n /** The \"sign in\" button. */\n submit: string;\n /** Shown while the PIN exchange is in flight. */\n submitting: string;\n /** Shown when the PIN field is empty on submit. */\n missingPin: string;\n /** Generic \"that PIN was wrong / expired / locked out\" message. */\n invalidPin: string;\n}\n\n/** Strings rendered by `<ResetPasswordForm>`. */\nexport interface ResetPasswordFormLabels {\n title: string;\n description: string;\n newPasswordLabel: string;\n newPasswordPlaceholder: string;\n confirmPasswordLabel: string;\n confirmPasswordPlaceholder: string;\n submit: string;\n submitting: string;\n /** Error: one or both fields empty. */\n errorEmpty: string;\n /** Error: the new password fails the policy. */\n errorWeakPassword: string;\n /** Error: confirm does not match. */\n errorMismatch: string;\n /** Error: the reset token is missing / expired / consumed. */\n errorTokenInvalid: string;\n /** Error: a network / 5xx failure. */\n errorNetwork: string;\n}\n\nexport const DEFAULT_LOGIN_LABELS: LoginFormLabels = {\n title: 'Sign in',\n subtitle: 'Welcome back',\n usernameLabel: 'Username',\n usernamePlaceholder: 'Enter your username',\n passwordLabel: 'Password',\n passwordPlaceholder: 'Enter your password',\n submit: 'Sign in',\n submitting: 'Signing in...',\n forgotPassword: 'Forgot password?',\n invalidCredentials: 'Incorrect username or password.',\n missingFields: 'Enter both your username and password.',\n};\n\nexport const DEFAULT_FORGOT_PASSWORD_LABELS: ForgotPasswordFormLabels = {\n title: 'Forgot password',\n description: 'Enter your email and we will send you a reset link.',\n emailLabel: 'Email',\n emailPlaceholder: 'Enter your email',\n submit: 'Send reset link',\n submitting: 'Sending...',\n successMessage: 'If that email is registered, a reset link is on its way.',\n networkError: 'Something went wrong. Please try again.',\n invalidEmail: 'Enter a valid email address.',\n};\n\nexport const DEFAULT_OTP_LABELS: OtpFormLabels = {\n requestTitle: 'Sign in with a code',\n requestDescription: 'Enter your email and we will send you a one-time code.',\n emailLabel: 'Email',\n emailPlaceholder: 'Enter your email',\n requestSubmit: 'Send code',\n requesting: 'Sending...',\n invalidEmail: 'Enter a valid email address.',\n verifyTitle: 'Enter your code',\n verifyDescription: 'We sent a one-time code to {identifier}.',\n codeLabel: 'One-time code',\n codePlaceholder: 'Enter the code',\n verifySubmit: 'Verify',\n verifying: 'Verifying...',\n missingCode: 'Enter the code we emailed you.',\n invalidCode: 'That code is incorrect or has expired.',\n resend: 'Resend code',\n resending: 'Resending...',\n changeEmail: 'Use a different email',\n};\n\nexport const DEFAULT_PIN_LABELS: PinFormLabels = {\n title: 'Enter your event PIN',\n description: 'Enter the PIN for this event to sign in.',\n pinLabel: 'PIN',\n pinPlaceholder: 'Enter your PIN',\n submit: 'Sign in',\n submitting: 'Signing in...',\n missingPin: 'Enter your event PIN.',\n invalidPin: 'That PIN is incorrect, has expired, or is locked out.',\n};\n\nexport const DEFAULT_RESET_PASSWORD_LABELS: ResetPasswordFormLabels = {\n title: 'Reset password',\n description: 'Choose a new password for your account.',\n newPasswordLabel: 'New password',\n newPasswordPlaceholder: 'Enter a new password',\n confirmPasswordLabel: 'Confirm password',\n confirmPasswordPlaceholder: 'Re-enter the new password',\n submit: 'Reset password',\n submitting: 'Resetting...',\n errorEmpty: 'Fill in both password fields.',\n errorWeakPassword:\n 'Use at least 8 characters with an uppercase letter, a lowercase letter and a digit.',\n errorMismatch: 'The passwords do not match.',\n errorTokenInvalid: 'This reset link is invalid or has expired. Request a new one.',\n errorNetwork: 'Something went wrong. Please try again.',\n};\n","/**\n * Stable `testID` values for every interactive element the auth components\n * render. Exported so E2E suites and unit tests reference one source of truth\n * rather than hard-coding string literals.\n *\n * Each component also accepts a `testIdPrefix` prop; when set, these base IDs\n * are prefixed so two forms can coexist on one screen without ID collisions.\n *\n * `sonarjs/no-hardcoded-passwords` is disabled for this file: it flags keys\n * such as `loginPasswordInput`, but every value here is a UI test ID, not a\n * credential. There are no secrets in this module.\n */\n/* eslint-disable sonarjs/no-hardcoded-passwords */\nexport const AuthTestIds = {\n loginForm: 'auth-login-form',\n loginUsernameInput: 'auth-login-username',\n loginPasswordInput: 'auth-login-password',\n loginSubmitButton: 'auth-login-submit',\n loginForgotLink: 'auth-login-forgot-link',\n loginError: 'auth-login-error',\n\n forgotPasswordForm: 'auth-forgot-form',\n forgotPasswordEmailInput: 'auth-forgot-email',\n forgotPasswordSubmitButton: 'auth-forgot-submit',\n forgotPasswordError: 'auth-forgot-error',\n forgotPasswordSuccess: 'auth-forgot-success',\n\n resetPasswordForm: 'auth-reset-form',\n resetPasswordNewInput: 'auth-reset-new',\n resetPasswordConfirmInput: 'auth-reset-confirm',\n resetPasswordSubmitButton: 'auth-reset-submit',\n resetPasswordError: 'auth-reset-error',\n\n otpForm: 'auth-otp-form',\n otpEmailInput: 'auth-otp-email',\n otpRequestButton: 'auth-otp-request',\n otpCodeInput: 'auth-otp-code',\n otpVerifyButton: 'auth-otp-verify',\n otpResendButton: 'auth-otp-resend',\n otpChangeEmailButton: 'auth-otp-change-email',\n otpError: 'auth-otp-error',\n\n pinForm: 'auth-pin-form',\n pinInput: 'auth-pin-input',\n pinSubmitButton: 'auth-pin-submit',\n pinError: 'auth-pin-error',\n} as const;\n\n/** Apply an optional prefix to a base test ID. */\nexport function withTestIdPrefix(baseId: string, prefix?: string): string {\n return prefix === undefined || prefix === '' ? baseId : `${prefix}-${baseId}`;\n}\n","/**\n * `useAuthStyles` — turns an `AuthTheme` token bag into a React Native\n * `StyleSheet` shared by all three auth forms.\n *\n * Building the stylesheet here (once, memoised per theme) keeps each form\n * component focused on layout + behaviour, and guarantees the three forms are\n * visually consistent. Token → style mapping lives in exactly one place, so an\n * app re-theming `<LoginForm>` automatically re-themes the others.\n */\nimport { useMemo } from 'react';\n\nimport { StyleSheet, type TextStyle, type ViewStyle } from 'react-native';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\n\n/** The named styles every auth form draws from. */\nexport interface AuthStyles {\n screen: ViewStyle;\n card: ViewStyle;\n title: TextStyle;\n subtitle: TextStyle;\n fieldGroup: ViewStyle;\n label: TextStyle;\n input: TextStyle;\n inputError: TextStyle;\n primaryButton: ViewStyle;\n primaryButtonDisabled: ViewStyle;\n primaryButtonText: TextStyle;\n linkText: TextStyle;\n errorText: TextStyle;\n successText: TextStyle;\n helperText: TextStyle;\n}\n\nconst FULL_WIDTH = '100%';\nconst CARD_MAX_WIDTH = 420;\nconst BUTTON_VERTICAL_PADDING = 14;\n\n/** Build the auth `StyleSheet` from the resolved theme. */\nexport function useAuthStyles(theme: AuthTheme): AuthStyles {\n return useMemo(() => {\n const { colors, radii, spacing, typography } = theme;\n return StyleSheet.create<AuthStyles>({\n screen: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n padding: spacing.md,\n backgroundColor: colors.background,\n },\n card: {\n width: FULL_WIDTH,\n maxWidth: CARD_MAX_WIDTH,\n borderRadius: radii.card,\n padding: spacing.xl,\n backgroundColor: colors.surface,\n },\n title: {\n fontSize: typography.title,\n fontWeight: 'bold',\n textAlign: 'center',\n marginBottom: spacing.xs,\n color: colors.text,\n },\n subtitle: {\n fontSize: typography.subtitle,\n textAlign: 'center',\n marginBottom: spacing.lg,\n color: colors.textSecondary,\n },\n fieldGroup: {\n marginBottom: spacing.md,\n },\n label: {\n fontSize: typography.label,\n fontWeight: '600',\n marginBottom: spacing.xs,\n color: colors.text,\n },\n input: {\n borderWidth: 1,\n borderRadius: radii.input,\n padding: spacing.sm,\n fontSize: typography.body,\n borderColor: colors.border,\n backgroundColor: colors.background,\n color: colors.text,\n },\n inputError: {\n borderColor: colors.danger,\n },\n primaryButton: {\n borderRadius: radii.input,\n paddingVertical: BUTTON_VERTICAL_PADDING,\n alignItems: 'center',\n justifyContent: 'center',\n marginTop: spacing.xs,\n backgroundColor: colors.primary,\n },\n primaryButtonDisabled: {\n backgroundColor: colors.border,\n },\n primaryButtonText: {\n fontSize: typography.body,\n fontWeight: '600',\n color: colors.onPrimary,\n },\n linkText: {\n fontSize: typography.caption,\n textDecorationLine: 'underline',\n color: colors.primary,\n },\n errorText: {\n fontSize: typography.caption,\n marginTop: spacing.xs,\n color: colors.danger,\n },\n successText: {\n fontSize: typography.body,\n lineHeight: typography.body * 1.4,\n color: colors.success,\n },\n helperText: {\n fontSize: typography.caption,\n color: colors.textSecondary,\n },\n });\n }, [theme]);\n}\n","/**\n * `useBffAuth` — the headless login/logout/session hook.\n *\n * This is the \"escape hatch\" half of the package's design: apps that want a\n * fully custom layout skip `<LoginForm>` and drive auth themselves with this\n * hook. `<LoginForm>` itself is built on top of it, so the ready-made and the\n * custom paths share one code path.\n *\n * It owns nothing the BFF owns: no tokens, no refresh, no realm awareness. It\n * holds only the *current user* (the sanitised claims from `/bff/me`) plus the\n * in-flight status of `login` / `logout`. The httpOnly session cookie is the\n * single source of truth — `refresh()` re-reads `/bff/me` to resync.\n *\n * `BffUser` and `BffAuthClient` come from `@dloizides/auth-client`.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { BffAuthClient, BffLoginRequest, BffUser } from '@dloizides/auth-client';\n\n/** Lifecycle status of the auth session. */\nexport const enum BffAuthStatus {\n /** The initial `/bff/me` probe has not finished yet. */\n Loading = 'loading',\n /** A live session exists; `user` is populated. */\n Authenticated = 'authenticated',\n /** No session; `user` is `null`. */\n Unauthenticated = 'unauthenticated',\n}\n\nexport interface UseBffAuthOptions {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /**\n * When `true` (default), the hook probes `GET /bff/me` on mount to bootstrap\n * `status`/`user`. Set `false` to skip the probe (e.g. on a public page).\n */\n probeOnMount?: boolean;\n}\n\nexport interface UseBffAuthResult {\n /** The signed-in user, or `null` when there is no session. */\n user: BffUser | null;\n /** Session lifecycle status. */\n status: BffAuthStatus;\n /** `true` while a `login` or `logout` call is in flight. */\n isSubmitting: boolean;\n /** The last `login`/`logout`/`refresh` error, cleared on the next attempt. */\n error: Error | null;\n /** ROPC password login via `POST /bff/login`. Resolves to the user; rejects on failure. */\n login: (request: BffLoginRequest) => Promise<BffUser>;\n /** End the session via `POST /bff/logout`. Always resolves; never throws to the caller. */\n logout: () => Promise<void>;\n /** Re-read `GET /bff/me` and resync `user`/`status`. */\n refresh: () => Promise<void>;\n}\n\n/** Internal: the mutable session state the hook tracks. */\ninterface SessionState {\n user: BffUser | null;\n status: BffAuthStatus;\n}\n\nconst INITIAL_LOADING: SessionState = { user: null, status: BffAuthStatus.Loading };\nconst INITIAL_IDLE: SessionState = { user: null, status: BffAuthStatus.Unauthenticated };\n\nfunction toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value));\n}\n\n/**\n * Headless BFF auth. Returns the current user, the session status, and\n * `login` / `logout` / `refresh` callbacks. No rendering — the consumer (or\n * `<LoginForm>`) wires it to UI.\n */\nexport function useBffAuth(options: UseBffAuthOptions): UseBffAuthResult {\n const { client, probeOnMount = true } = options;\n\n const [session, setSession] = useState<SessionState>(\n probeOnMount ? INITIAL_LOADING : INITIAL_IDLE,\n );\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Guard against a `setState` after the consumer unmounts mid-request.\n const mountedRef = useRef(true);\n useEffect(() => {\n mountedRef.current = true;\n return (): void => {\n mountedRef.current = false;\n };\n }, []);\n\n const safeSetSession = useCallback((next: SessionState) => {\n if (mountedRef.current) {\n setSession(next);\n }\n }, []);\n\n const refresh = useCallback(async (): Promise<void> => {\n try {\n const user = await client.getCurrentUser();\n safeSetSession(\n user === null\n ? INITIAL_IDLE\n : { user, status: BffAuthStatus.Authenticated },\n );\n } catch (caught) {\n safeSetSession(INITIAL_IDLE);\n if (mountedRef.current) {\n setError(toError(caught));\n }\n }\n }, [client, safeSetSession]);\n\n const login = useCallback(\n async (request: BffLoginRequest): Promise<BffUser> => {\n if (mountedRef.current) {\n setIsSubmitting(true);\n setError(null);\n }\n try {\n const user = await client.login(request);\n safeSetSession({ user, status: BffAuthStatus.Authenticated });\n return user;\n } catch (caught) {\n const err = toError(caught);\n if (mountedRef.current) {\n setError(err);\n }\n throw err;\n } finally {\n if (mountedRef.current) {\n setIsSubmitting(false);\n }\n }\n },\n [client, safeSetSession],\n );\n\n const logout = useCallback(async (): Promise<void> => {\n if (mountedRef.current) {\n setIsSubmitting(true);\n setError(null);\n }\n try {\n await client.logout();\n } catch (caught) {\n // A failed logout still leaves the SPA logged out client-side — surface\n // the error but do not reject; the caller's UI should not get stuck.\n if (mountedRef.current) {\n setError(toError(caught));\n }\n } finally {\n safeSetSession(INITIAL_IDLE);\n if (mountedRef.current) {\n setIsSubmitting(false);\n }\n }\n }, [client, safeSetSession]);\n\n // Bootstrap the session once on mount when probing is enabled.\n useEffect(() => {\n if (probeOnMount) {\n void refresh();\n }\n // `refresh` is stable for a stable `client`; `probeOnMount` is read once.\n }, [probeOnMount, refresh]);\n\n return useMemo(\n () => ({\n user: session.user,\n status: session.status,\n isSubmitting,\n error,\n login,\n logout,\n refresh,\n }),\n [session.user, session.status, isSubmitting, error, login, logout, refresh],\n );\n}\n","/**\n * `AuthTheme` — the design-token contract every `@dloizides/auth-web` component\n * is styled against.\n *\n * The package owns **no** brand. Katalogos, Erevna and Kefi each look different;\n * each one maps its own theme system onto this flat token bag and passes it in\n * (via the `theme` prop or `<AuthThemeProvider>`). The component code only ever\n * reads these tokens — never an app-specific theme object — so the same\n * `<LoginForm>` renders on-brand in three visually distinct apps.\n *\n * Keep this shape minimal and stable: it is a public API surface.\n */\n\n/** Colour tokens — the only colours the auth components reference. */\nexport interface AuthThemeColors {\n /** Page / screen background behind the form card. */\n background: string;\n /** The form card surface colour. */\n surface: string;\n /** Primary text (titles, labels, input text). */\n text: string;\n /** Muted / secondary text (subtitles, helper copy). */\n textSecondary: string;\n /** Input + card border colour; also the disabled-button fill. */\n border: string;\n /** Brand primary — the submit button fill and link colour. */\n primary: string;\n /** Text drawn on top of `primary` (e.g. the submit button label). */\n onPrimary: string;\n /** Error text and error-state borders. */\n danger: string;\n /** Success text (e.g. the forgot-password confirmation). */\n success: string;\n}\n\n/** Corner-radius tokens. */\nexport interface AuthThemeRadii {\n /** Inputs and buttons. */\n input: number;\n /** The form card. */\n card: number;\n}\n\n/** Spacing scale (in density-independent pixels). */\nexport interface AuthThemeSpacing {\n /** Tight gap — e.g. label-to-input. */\n xs: number;\n /** Small gap. */\n sm: number;\n /** Default gap — between stacked fields. */\n md: number;\n /** Large gap — section separation. */\n lg: number;\n /** Card inner padding. */\n xl: number;\n}\n\n/** Font-size tokens. */\nexport interface AuthThemeTypography {\n /** Form title. */\n title: number;\n /** Form subtitle. */\n subtitle: number;\n /** Field labels. */\n label: number;\n /** Input text and button text. */\n body: number;\n /** Helper / error / footer copy. */\n caption: number;\n}\n\n/** The full token bag a consuming app supplies. */\nexport interface AuthTheme {\n colors: AuthThemeColors;\n radii: AuthThemeRadii;\n spacing: AuthThemeSpacing;\n typography: AuthThemeTypography;\n}\n\n/**\n * A neutral, accessible light-mode theme. Apps are expected to override this —\n * it exists so a component renders sensibly with zero configuration and so\n * `<AuthThemeProvider>` has a default value.\n */\nexport const defaultAuthTheme: AuthTheme = {\n colors: {\n background: '#f5f5f7',\n surface: '#ffffff',\n text: '#1a1a1a',\n textSecondary: '#6b6b6b',\n border: '#d0d0d5',\n primary: '#2563eb',\n onPrimary: '#ffffff',\n danger: '#d33333',\n success: '#1f7a3d',\n },\n radii: {\n input: 8,\n card: 12,\n },\n spacing: {\n xs: 8,\n sm: 12,\n md: 20,\n lg: 32,\n xl: 24,\n },\n typography: {\n title: 28,\n subtitle: 16,\n label: 14,\n body: 16,\n caption: 12,\n },\n};\n","/**\n * React context for the `AuthTheme`.\n *\n * Two ways to theme `@dloizides/auth-web` components:\n *\n * 1. Wrap the auth screens in `<AuthThemeProvider theme={appAuthTheme}>` —\n * every component below reads the theme from context.\n * 2. Pass `theme` directly as a prop to an individual component — the prop\n * always wins over context.\n *\n * With neither, components fall back to `defaultAuthTheme`. `useAuthTheme()`\n * implements that precedence (prop → context → default) so each component does\n * not re-derive it.\n */\nimport { createContext, useContext, useMemo, type ReactElement, type ReactNode } from 'react';\n\nimport { defaultAuthTheme, type AuthTheme } from './AuthTheme';\n\nconst AuthThemeContext = createContext<AuthTheme>(defaultAuthTheme);\n\nexport interface AuthThemeProviderProps {\n /** The token bag every descendant auth component is styled against. */\n theme: AuthTheme;\n children: ReactNode;\n}\n\n/** Provides an `AuthTheme` to every `@dloizides/auth-web` component below it. */\nexport function AuthThemeProvider({\n theme,\n children,\n}: Readonly<AuthThemeProviderProps>): ReactElement {\n return <AuthThemeContext.Provider value={theme}>{children}</AuthThemeContext.Provider>;\n}\n\n/**\n * Resolve the effective theme for a component.\n *\n * Precedence: an explicit `themeProp` (if given) wins over the context value,\n * which itself defaults to `defaultAuthTheme` when no provider is mounted.\n */\nexport function useAuthTheme(themeProp?: AuthTheme): AuthTheme {\n const contextTheme = useContext(AuthThemeContext);\n return useMemo(() => themeProp ?? contextTheme, [themeProp, contextTheme]);\n}\n","/**\n * `<LoginForm>` — the ready-made, themeable password-login form.\n *\n * The \"themeable component\" half of the package design: drop it in, pass a\n * `client`, a `theme` (or wrap in `<AuthThemeProvider>`) and a localised\n * `labels` bag, and you have a branded login surface. It is built on the\n * headless `useBffAuth` hook, so the ready-made and custom-layout paths share\n * one code path.\n *\n * The package ships no router and no i18n. `onSuccess` hands the signed-in\n * `BffUser` back to the app, which decides where to navigate (typically via\n * `resolvePostLoginRoute`). All copy comes from `labels`.\n */\nimport { useCallback, useMemo, useState, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TextInput, TouchableOpacity, View } from 'react-native';\n\nimport { DEFAULT_LOGIN_LABELS, type LoginFormLabels } from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { useBffAuth } from '../hooks/useBffAuth';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\nimport type { BffAuthClient, BffUser } from '@dloizides/auth-client';\n\nexport interface LoginFormProps {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. Falls back to the default theme. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<LoginFormLabels>;\n /** Called with the signed-in user after a successful login. */\n onSuccess: (user: BffUser) => void;\n /** Called when the user taps the \"Forgot password?\" link. Omit to hide the link. */\n onForgotPassword?: () => void;\n /** Prefix applied to every `testID` so multiple forms can share a screen. */\n testIdPrefix?: string;\n}\n\n/** Themeable password-login form built on `useBffAuth`. */\nexport function LoginForm({\n client,\n theme: themeProp,\n labels: labelsProp,\n onSuccess,\n onForgotPassword,\n testIdPrefix,\n}: Readonly<LoginFormProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<LoginFormLabels>(\n () => ({ ...DEFAULT_LOGIN_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n // probeOnMount is off: the login screen does not need a /bff/me round-trip.\n const { login, isSubmitting } = useBffAuth({ client, probeOnMount: false });\n\n const [username, setUsername] = useState('');\n const [password, setPassword] = useState('');\n const [errorText, setErrorText] = useState<string | null>(null);\n\n const runLogin = useCallback(async (): Promise<void> => {\n setErrorText(null);\n const trimmedUsername = username.trim();\n const hasMissingField = trimmedUsername.length === 0 || password.length === 0;\n if (hasMissingField) {\n setErrorText(labels.missingFields);\n return;\n }\n try {\n const user = await login({ username: trimmedUsername, password });\n onSuccess(user);\n } catch {\n // The BFF answers a wrong credential with a non-2xx; show a generic\n // message — never echo the raw error (it can leak whether the user exists).\n setErrorText(labels.invalidCredentials);\n }\n }, [username, password, login, onSuccess, labels.missingFields, labels.invalidCredentials]);\n\n // `onPress` expects a void-returning handler; `runLogin` is async, so wrap it.\n const handleSubmit = useCallback((): void => {\n void runLogin();\n }, [runLogin]);\n\n const submitButtonStyle = isSubmitting\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n\n return (\n <View style={styles.screen}>\n <View style={styles.card} testID={withTestIdPrefix(AuthTestIds.loginForm, testIdPrefix)}>\n <Text style={styles.title}>{labels.title}</Text>\n <Text style={styles.subtitle}>{labels.subtitle}</Text>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.usernameLabel}</Text>\n <TextInput\n accessibilityHint={labels.usernamePlaceholder}\n accessibilityLabel={labels.usernameLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!isSubmitting}\n placeholder={labels.usernamePlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.loginUsernameInput, testIdPrefix)}\n value={username}\n onChangeText={setUsername}\n />\n </View>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.passwordLabel}</Text>\n <TextInput\n secureTextEntry\n accessibilityHint={labels.passwordPlaceholder}\n accessibilityLabel={labels.passwordLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!isSubmitting}\n placeholder={labels.passwordPlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.loginPasswordInput, testIdPrefix)}\n value={password}\n onChangeText={setPassword}\n />\n </View>\n\n {errorText !== null ? (\n <Text\n style={styles.errorText}\n testID={withTestIdPrefix(AuthTestIds.loginError, testIdPrefix)}\n >\n {errorText}\n </Text>\n ) : null}\n\n {onForgotPassword !== undefined ? (\n <TouchableOpacity\n accessibilityHint={labels.forgotPassword}\n accessibilityLabel={labels.forgotPassword}\n accessibilityRole=\"link\"\n disabled={isSubmitting}\n style={styles.fieldGroup}\n testID={withTestIdPrefix(AuthTestIds.loginForgotLink, testIdPrefix)}\n onPress={onForgotPassword}\n >\n <Text style={styles.linkText}>{labels.forgotPassword}</Text>\n </TouchableOpacity>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.submit}\n accessibilityLabel={isSubmitting ? labels.submitting : labels.submit}\n accessibilityRole=\"button\"\n disabled={isSubmitting}\n style={submitButtonStyle}\n testID={withTestIdPrefix(AuthTestIds.loginSubmitButton, testIdPrefix)}\n onPress={handleSubmit}\n >\n {isSubmitting ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.submit}</Text>\n )}\n </TouchableOpacity>\n </View>\n </View>\n );\n}\n","/**\n * React Query mutation hooks for the BFF password-reset flow.\n *\n * Headless counterparts to `<ForgotPasswordForm>` / `<ResetPasswordForm>` —\n * apps with a custom layout use these directly. They POST to the same-origin\n * `/bff/forgot-password` and `/bff/reset-password`, which the BFF proxies to\n * TenantService.\n *\n * Extracted + generalised from `apps/katalogos-web/src/auth/bffPasswordHooks.ts`.\n * Difference: the katalogos version closed over a module-level singleton\n * `bffAuthClient`; the package version takes the `client` in the options so it\n * carries no global state.\n *\n * The mutation result type is `undefined` (not `void`): the BFF endpoints\n * return no body, and `undefined` is a valid generic argument where the lint\n * config rejects `void`.\n */\nimport { useMutation, type UseMutationOptions, type UseMutationResult } from '@tanstack/react-query';\n\nimport type {\n BffAuthClient,\n BffForgotPasswordRequest,\n BffResetPasswordRequest,\n} from '@dloizides/auth-client';\n\nexport type UseBffForgotPasswordOptions = Omit<\n UseMutationOptions<undefined, Error, BffForgotPasswordRequest>,\n 'mutationFn'\n> & {\n /** The same-origin BFF client. */\n client: BffAuthClient;\n};\n\n/**\n * Mutation that POSTs to `/bff/forgot-password`.\n *\n * The backend returns 200 unconditionally (no email enumeration); the UI\n * should show the same \"if that email exists, we sent a link\" message whether\n * `onSuccess` or `onError` fires.\n */\nexport function useBffForgotPassword(\n options: UseBffForgotPasswordOptions,\n): UseMutationResult<undefined, Error, BffForgotPasswordRequest> {\n const { client, ...rest } = options;\n return useMutation<undefined, Error, BffForgotPasswordRequest>({\n mutationFn: async (request) => {\n await client.forgotPassword(request);\n return undefined;\n },\n ...rest,\n });\n}\n\nexport type UseBffResetPasswordOptions = Omit<\n UseMutationOptions<undefined, Error, BffResetPasswordRequest>,\n 'mutationFn'\n> & {\n /** The same-origin BFF client. */\n client: BffAuthClient;\n};\n\n/**\n * Mutation that POSTs to `/bff/reset-password`. A `400` (invalid / expired\n * token) surfaces as a rejected mutation with the status in the error message.\n */\nexport function useBffResetPassword(\n options: UseBffResetPasswordOptions,\n): UseMutationResult<undefined, Error, BffResetPasswordRequest> {\n const { client, ...rest } = options;\n return useMutation<undefined, Error, BffResetPasswordRequest>({\n mutationFn: async (request) => {\n await client.resetPassword(request);\n return undefined;\n },\n ...rest,\n });\n}\n","/**\n * `<ForgotPasswordForm>` — the ready-made, themeable \"request a reset link\"\n * form.\n *\n * Captures an email and POSTs to `/bff/forgot-password` via the headless\n * `useBffForgotPassword` hook. The backend answers 200 unconditionally (no\n * email enumeration), so on success the form swaps to a generic confirmation\n * message — it never reveals whether the address is registered.\n *\n * Extracted + generalised from `apps/katalogos-web/src/components/Auth/\n * ForgotPasswordModal.tsx` — minus the modal shell (apps own the surface) and\n * the app-specific `FM()` calls (copy now comes from `labels`).\n */\nimport { useCallback, useMemo, useState, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TextInput, TouchableOpacity, View } from 'react-native';\n\nimport { DEFAULT_FORGOT_PASSWORD_LABELS, type ForgotPasswordFormLabels } from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { useBffForgotPassword } from '../hooks/useBffPasswordHooks';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\nimport type { BffAuthClient } from '@dloizides/auth-client';\n\n// A deliberately loose, linear-time email shape check — `[^@\\s]` and `[^.\\s]`\n// character classes have no overlapping alternation, so there is no\n// super-linear backtracking. Strict validation is the backend's job.\nconst EMAIL_REGEX = /^[^@\\s]+@[^.\\s]+\\.[^\\s]+$/;\n\nexport interface ForgotPasswordFormProps {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<ForgotPasswordFormLabels>;\n /**\n * Full URL with a `{token}` placeholder; forwarded to the backend so it can\n * build the reset-email link without hardcoding any frontend host. Optional —\n * apps that configure the template server-side can omit it.\n */\n resetUrlTemplate?: string;\n /** Called once the request succeeds (the generic-confirmation state). */\n onSuccess?: () => void;\n /** Prefix applied to every `testID`. */\n testIdPrefix?: string;\n}\n\n/** `true` when `value` looks like an email address. */\nfunction isValidEmail(value: string): boolean {\n return EMAIL_REGEX.test(value);\n}\n\n/** Themeable \"request a reset link\" form built on `useBffForgotPassword`. */\nexport function ForgotPasswordForm({\n client,\n theme: themeProp,\n labels: labelsProp,\n resetUrlTemplate,\n onSuccess,\n testIdPrefix,\n}: Readonly<ForgotPasswordFormProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<ForgotPasswordFormLabels>(\n () => ({ ...DEFAULT_FORGOT_PASSWORD_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n const [email, setEmail] = useState('');\n const [submitted, setSubmitted] = useState(false);\n const [errorText, setErrorText] = useState<string | null>(null);\n\n const mutationOptions = useMemo(\n () => ({\n client,\n onSuccess: (): void => {\n setSubmitted(true);\n onSuccess?.();\n },\n onError: (): void => {\n // Only a network / 5xx failure reaches here — a 200 (the no-enumeration\n // branch) is success. Show a friendly retry message.\n setErrorText(labels.networkError);\n },\n }),\n [client, onSuccess, labels.networkError],\n );\n const mutation = useBffForgotPassword(mutationOptions);\n\n const isPending = mutation.status === 'pending';\n\n const handleSubmit = useCallback((): void => {\n setErrorText(null);\n const trimmedEmail = email.trim();\n if (!isValidEmail(trimmedEmail)) {\n setErrorText(labels.invalidEmail);\n return;\n }\n mutation.mutate({ email: trimmedEmail, resetUrlTemplate });\n }, [email, mutation, resetUrlTemplate, labels.invalidEmail]);\n\n const submitButtonStyle = isPending\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n\n return (\n <View style={styles.screen}>\n <View\n style={styles.card}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix)}\n >\n <Text style={styles.title}>{labels.title}</Text>\n\n {submitted ? (\n <Text\n style={styles.successText}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordSuccess, testIdPrefix)}\n >\n {labels.successMessage}\n </Text>\n ) : (\n <>\n <Text style={styles.subtitle}>{labels.description}</Text>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.emailLabel}</Text>\n <TextInput\n accessibilityHint={labels.emailPlaceholder}\n accessibilityLabel={labels.emailLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!isPending}\n keyboardType=\"email-address\"\n placeholder={labels.emailPlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordEmailInput, testIdPrefix)}\n value={email}\n onChangeText={setEmail}\n />\n </View>\n\n {errorText !== null ? (\n <Text\n style={styles.errorText}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordError, testIdPrefix)}\n >\n {errorText}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.submit}\n accessibilityLabel={isPending ? labels.submitting : labels.submit}\n accessibilityRole=\"button\"\n disabled={isPending}\n style={submitButtonStyle}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordSubmitButton, testIdPrefix)}\n onPress={handleSubmit}\n >\n {isPending ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.submit}</Text>\n )}\n </TouchableOpacity>\n </>\n )}\n </View>\n </View>\n );\n}\n","/**\n * The discrete failure states the reset-password flow can surface.\n *\n * Each member is the stable key a consuming app maps onto a localised message.\n * `useResetPasswordForm` reports exactly one of these at a time, preferring the\n * earliest-fixable issue so the user resolves one thing at a time.\n */\nexport const enum ResetPasswordError {\n /** One or both password fields are empty. */\n Empty = 'empty',\n /** The new password fails the shared password policy. */\n WeakPassword = 'weakPassword',\n /** The confirm field does not match the new password. */\n Mismatch = 'mismatch',\n /** The reset token is missing, expired, or already consumed. */\n TokenInvalid = 'tokenInvalid',\n /** A network or 5xx failure prevented the reset from completing. */\n Network = 'network',\n}\n","/**\n * The discrete ways a password can fail the shared client-side policy.\n *\n * Each member is the stable key a consuming app maps onto a localised message —\n * the package never ships translated copy.\n */\nexport const enum PasswordPolicyError {\n /** Shorter than `PASSWORD_MIN_LENGTH`. */\n TooShort = 'tooShort',\n /** Longer than `PASSWORD_MAX_LENGTH`. */\n TooLong = 'tooLong',\n /** Contains no `A-Z` character. */\n MissingUppercase = 'missingUppercase',\n /** Contains no `a-z` character. */\n MissingLowercase = 'missingLowercase',\n /** Contains no `0-9` character. */\n MissingDigit = 'missingDigit',\n}\n","/**\n * Client-side password policy that mirrors the backend\n * (TenantService `ResetPasswordRequestValidator`):\n *\n * - 8 ≤ length ≤ 128\n * - at least one uppercase letter\n * - at least one lowercase letter\n * - at least one digit\n *\n * Shared so every app's `<ResetPasswordForm>` (and any future password input)\n * rejects ~99% of bad passwords before a network round-trip. Extracted from\n * `apps/katalogos-web/src/auth/passwordPolicy.ts`.\n */\nimport { PasswordPolicyError } from './PasswordPolicyError';\n\nconst UPPERCASE_REGEX = /[A-Z]/;\nconst LOWERCASE_REGEX = /[a-z]/;\nconst DIGIT_REGEX = /\\d/;\n\n/** Minimum acceptable password length. */\nexport const PASSWORD_MIN_LENGTH = 8;\n/** Maximum acceptable password length. */\nexport const PASSWORD_MAX_LENGTH = 128;\n\n/**\n * Return every policy rule the given password violates. An empty array means\n * the password is acceptable.\n */\nexport function validatePasswordPolicy(password: string): PasswordPolicyError[] {\n const errors: PasswordPolicyError[] = [];\n if (password.length < PASSWORD_MIN_LENGTH) {\n errors.push(PasswordPolicyError.TooShort);\n }\n if (password.length > PASSWORD_MAX_LENGTH) {\n errors.push(PasswordPolicyError.TooLong);\n }\n if (!UPPERCASE_REGEX.test(password)) {\n errors.push(PasswordPolicyError.MissingUppercase);\n }\n if (!LOWERCASE_REGEX.test(password)) {\n errors.push(PasswordPolicyError.MissingLowercase);\n }\n if (!DIGIT_REGEX.test(password)) {\n errors.push(PasswordPolicyError.MissingDigit);\n }\n return errors;\n}\n\n/** `true` when the password satisfies every policy rule. */\nexport function isPasswordValid(password: string): boolean {\n return validatePasswordPolicy(password).length === 0;\n}\n","/**\n * `useResetPasswordForm` — form-state + submit logic for the reset-password\n * screen.\n *\n * The (testable) logic — policy validation, confirm-match, error mapping — is\n * kept out of the rendered component so `<ResetPasswordForm>` stays thin and\n * the rules are unit-tested directly. The hook returns plain values + callbacks\n * the component (or a custom layout) wires to JSX.\n *\n * Behaviour:\n * - Validates the new password against the shared `passwordPolicy`.\n * - Validates confirmPassword matches.\n * - Surfaces a single `ResetPasswordError` at submit time, preferring the\n * earliest-fixable issue (empty → weak → mismatch → token).\n * - Calls `useBffResetPassword` (`POST /bff/reset-password`). On success,\n * invokes the supplied `onSuccess`.\n *\n * Extracted + generalised from `apps/katalogos-web/src/auth/useResetPasswordForm.ts`.\n */\nimport { useMemo, useState } from 'react';\n\nimport { ResetPasswordError } from './ResetPasswordError';\nimport { useBffResetPassword } from './useBffPasswordHooks';\nimport { isPasswordValid } from '../password/passwordPolicy';\n\nimport type { BffAuthClient } from '@dloizides/auth-client';\n\nconst HTTP_BAD_REQUEST = 400;\n\nexport interface UseResetPasswordFormArgs {\n /** The same-origin BFF client. */\n client: BffAuthClient;\n /** The reset token, typically read from the deep-link URL. */\n token: string;\n /** Invoked once the password has been reset successfully. */\n onSuccess: () => void;\n}\n\nexport interface UseResetPasswordFormResult {\n newPassword: string;\n confirmPassword: string;\n setNewPassword: (value: string) => void;\n setConfirmPassword: (value: string) => void;\n /** `true` while the reset request is in flight. */\n isSubmitting: boolean;\n /** The single active error, or `null` when the form is clean. */\n errorKey: ResetPasswordError | null;\n /** `true` once a token-related failure is detected (drives a \"request a new link\" UI). */\n hasInvalidToken: boolean;\n /** Validate, then submit. */\n submit: () => void;\n}\n\n/** `true` when the BFF error message carries the given HTTP status. */\nfunction isHttpStatusError(message: string, status: number): boolean {\n return message.includes(` status ${String(status)}`);\n}\n\n/** Run the synchronous pre-flight checks; the earliest-fixable failure wins. */\nfunction preflight(args: {\n newPassword: string;\n confirm: string;\n token: string;\n}): ResetPasswordError | null {\n if (args.newPassword.length === 0 || args.confirm.length === 0) {\n return ResetPasswordError.Empty;\n }\n if (!isPasswordValid(args.newPassword)) {\n return ResetPasswordError.WeakPassword;\n }\n if (args.newPassword !== args.confirm) {\n return ResetPasswordError.Mismatch;\n }\n if (args.token === '') {\n return ResetPasswordError.TokenInvalid;\n }\n return null;\n}\n\ninterface MutationCallbacks {\n onSuccess: () => void;\n setErrorKey: (error: ResetPasswordError) => void;\n setHasInvalidToken: (value: boolean) => void;\n}\n\n/** Wire the reset mutation, mapping a backend 400 onto a token-invalid error. */\nfunction useResetMutation(\n client: BffAuthClient,\n callbacks: MutationCallbacks,\n): ReturnType<typeof useBffResetPassword> {\n const mutationOptions = useMemo(\n () => ({\n client,\n onSuccess: callbacks.onSuccess,\n onError: (err: Error): void => {\n if (isHttpStatusError(err.message, HTTP_BAD_REQUEST)) {\n callbacks.setHasInvalidToken(true);\n callbacks.setErrorKey(ResetPasswordError.TokenInvalid);\n return;\n }\n callbacks.setErrorKey(ResetPasswordError.Network);\n },\n }),\n [client, callbacks],\n );\n return useBffResetPassword(mutationOptions);\n}\n\ninterface SubmitArgs {\n newPassword: string;\n confirmPassword: string;\n token: string;\n setErrorKey: (error: ResetPasswordError | null) => void;\n setHasInvalidToken: (value: boolean) => void;\n mutate: (request: { token: string; newPassword: string }) => void;\n}\n\n/** Validate, then either fire the mutation or surface the pre-flight failure. */\nfunction runSubmit(args: SubmitArgs): void {\n args.setErrorKey(null);\n const failure = preflight({\n newPassword: args.newPassword,\n confirm: args.confirmPassword,\n token: args.token,\n });\n if (failure === null) {\n args.mutate({ token: args.token, newPassword: args.newPassword });\n return;\n }\n if (failure === ResetPasswordError.TokenInvalid) {\n args.setHasInvalidToken(true);\n }\n args.setErrorKey(failure);\n}\n\ninterface FormState {\n newPassword: string;\n confirmPassword: string;\n errorKey: ResetPasswordError | null;\n hasInvalidToken: boolean;\n}\n\ninterface FormSetters {\n setNewPassword: (value: string) => void;\n setConfirmPassword: (value: string) => void;\n setErrorKey: (error: ResetPasswordError | null) => void;\n setHasInvalidToken: (value: boolean) => void;\n}\n\n/** Bundle the four `useState` cells the form needs. */\nfunction useFormState(): { state: FormState; setters: FormSetters } {\n const [newPassword, setNewPassword] = useState('');\n const [confirmPassword, setConfirmPassword] = useState('');\n const [errorKey, setErrorKey] = useState<ResetPasswordError | null>(null);\n const [hasInvalidToken, setHasInvalidToken] = useState(false);\n return {\n state: { newPassword, confirmPassword, errorKey, hasInvalidToken },\n setters: { setNewPassword, setConfirmPassword, setErrorKey, setHasInvalidToken },\n };\n}\n\n/**\n * Headless reset-password form logic. Returns the field values, setters, the\n * single active error, and a `submit` callback.\n */\nexport function useResetPasswordForm({\n client,\n token,\n onSuccess,\n}: UseResetPasswordFormArgs): UseResetPasswordFormResult {\n const { state, setters } = useFormState();\n const callbacks = useMemo<MutationCallbacks>(\n () => ({\n onSuccess,\n setErrorKey: setters.setErrorKey,\n setHasInvalidToken: setters.setHasInvalidToken,\n }),\n [onSuccess, setters.setErrorKey, setters.setHasInvalidToken],\n );\n const mutation = useResetMutation(client, callbacks);\n const submit = (): void =>\n runSubmit({\n newPassword: state.newPassword,\n confirmPassword: state.confirmPassword,\n token,\n setErrorKey: setters.setErrorKey,\n setHasInvalidToken: setters.setHasInvalidToken,\n mutate: mutation.mutate,\n });\n return {\n newPassword: state.newPassword,\n confirmPassword: state.confirmPassword,\n setNewPassword: setters.setNewPassword,\n setConfirmPassword: setters.setConfirmPassword,\n isSubmitting: mutation.status === 'pending',\n errorKey: state.errorKey,\n hasInvalidToken: state.hasInvalidToken,\n submit,\n };\n}\n","/**\n * `<ResetPasswordForm>` — the ready-made, themeable \"choose a new password\"\n * form.\n *\n * Built on the headless `useResetPasswordForm` hook, which owns all the logic\n * (shared password policy, confirm-match, backend-error mapping). The component\n * is a thin render layer: two fields, one button, one error line.\n *\n * Extracted + generalised from `apps/katalogos-web/src/auth/useResetPasswordForm.ts`\n * + the katalogos reset-password route — minus the app-specific `FM()` and\n * router calls (copy is in `labels`, navigation is the app's `onSuccess`).\n */\nimport { useMemo, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TextInput, TouchableOpacity, View } from 'react-native';\n\nimport { DEFAULT_RESET_PASSWORD_LABELS, type ResetPasswordFormLabels } from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { ResetPasswordError } from '../hooks/ResetPasswordError';\nimport { useResetPasswordForm } from '../hooks/useResetPasswordForm';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\nimport type { BffAuthClient } from '@dloizides/auth-client';\n\nexport interface ResetPasswordFormProps {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /** The reset token, typically read from the deep-link URL by the app. */\n token: string;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<ResetPasswordFormLabels>;\n /** Called once the password has been reset successfully. */\n onSuccess: () => void;\n /** Prefix applied to every `testID`. */\n testIdPrefix?: string;\n}\n\n/** Resolve the active `ResetPasswordError` onto its localised message. */\nfunction errorMessage(\n errorKey: ResetPasswordError | null,\n labels: ResetPasswordFormLabels,\n): string | null {\n switch (errorKey) {\n case ResetPasswordError.Empty:\n return labels.errorEmpty;\n case ResetPasswordError.WeakPassword:\n return labels.errorWeakPassword;\n case ResetPasswordError.Mismatch:\n return labels.errorMismatch;\n case ResetPasswordError.TokenInvalid:\n return labels.errorTokenInvalid;\n case ResetPasswordError.Network:\n return labels.errorNetwork;\n default:\n return null;\n }\n}\n\n/** Themeable \"choose a new password\" form built on `useResetPasswordForm`. */\nexport function ResetPasswordForm({\n client,\n token,\n theme: themeProp,\n labels: labelsProp,\n onSuccess,\n testIdPrefix,\n}: Readonly<ResetPasswordFormProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<ResetPasswordFormLabels>(\n () => ({ ...DEFAULT_RESET_PASSWORD_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n const form = useResetPasswordForm({ client, token, onSuccess });\n const message = errorMessage(form.errorKey, labels);\n\n const submitButtonStyle = form.isSubmitting\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n\n return (\n <View style={styles.screen}>\n <View\n style={styles.card}\n testID={withTestIdPrefix(AuthTestIds.resetPasswordForm, testIdPrefix)}\n >\n <Text style={styles.title}>{labels.title}</Text>\n <Text style={styles.subtitle}>{labels.description}</Text>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.newPasswordLabel}</Text>\n <TextInput\n secureTextEntry\n accessibilityHint={labels.newPasswordPlaceholder}\n accessibilityLabel={labels.newPasswordLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!form.isSubmitting}\n placeholder={labels.newPasswordPlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.resetPasswordNewInput, testIdPrefix)}\n value={form.newPassword}\n onChangeText={form.setNewPassword}\n />\n </View>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.confirmPasswordLabel}</Text>\n <TextInput\n secureTextEntry\n accessibilityHint={labels.confirmPasswordPlaceholder}\n accessibilityLabel={labels.confirmPasswordLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!form.isSubmitting}\n placeholder={labels.confirmPasswordPlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.resetPasswordConfirmInput, testIdPrefix)}\n value={form.confirmPassword}\n onChangeText={form.setConfirmPassword}\n />\n </View>\n\n {message !== null ? (\n <Text\n style={styles.errorText}\n testID={withTestIdPrefix(AuthTestIds.resetPasswordError, testIdPrefix)}\n >\n {message}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.submit}\n accessibilityLabel={form.isSubmitting ? labels.submitting : labels.submit}\n accessibilityRole=\"button\"\n disabled={form.isSubmitting}\n style={submitButtonStyle}\n testID={withTestIdPrefix(AuthTestIds.resetPasswordSubmitButton, testIdPrefix)}\n onPress={form.submit}\n >\n {form.isSubmitting ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.submit}</Text>\n )}\n </TouchableOpacity>\n </View>\n </View>\n );\n}\n","/**\n * The two step sub-components of `<OtpForm>` — `<OtpRequestStep>` (collect the\n * email, ask the BFF to send a code) and `<OtpVerifyStep>` (collect the code,\n * verify it, offer resend / change-email).\n *\n * Split out of `OtpForm.tsx` to keep that file focused on the flow wiring; each\n * step is a thin, self-contained render layer. Both are styled by the shared\n * `AuthStyles` token-derived stylesheet so they match the other auth forms.\n */\nimport { useState, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TextInput, TouchableOpacity, View } from 'react-native';\n\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { type AuthStyles } from './useAuthStyles';\n\nimport type { OtpFormLabels } from './labels';\nimport type { AuthTheme } from '../theme/AuthTheme';\n\nexport interface OtpRequestStepProps {\n styles: AuthStyles;\n theme: AuthTheme;\n labels: OtpFormLabels;\n testIdPrefix?: string;\n isSubmitting: boolean;\n errorText: string | null;\n /** Called with the trimmed email when the user taps \"send code\". */\n onSubmit: (email: string) => void;\n}\n\n/** Step 1 — collect the email and trigger `POST /bff/otp/request`. */\nexport function OtpRequestStep({\n styles,\n theme,\n labels,\n testIdPrefix,\n isSubmitting,\n errorText,\n onSubmit,\n}: Readonly<OtpRequestStepProps>): ReactElement {\n const [email, setEmail] = useState('');\n const buttonStyle = isSubmitting\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n\n return (\n <>\n <Text style={styles.title}>{labels.requestTitle}</Text>\n <Text style={styles.subtitle}>{labels.requestDescription}</Text>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.emailLabel}</Text>\n <TextInput\n accessibilityHint={labels.emailPlaceholder}\n accessibilityLabel={labels.emailLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!isSubmitting}\n keyboardType=\"email-address\"\n placeholder={labels.emailPlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.otpEmailInput, testIdPrefix)}\n value={email}\n onChangeText={setEmail}\n />\n </View>\n\n {errorText !== null ? (\n <Text style={styles.errorText} testID={withTestIdPrefix(AuthTestIds.otpError, testIdPrefix)}>\n {errorText}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.requestSubmit}\n accessibilityLabel={isSubmitting ? labels.requesting : labels.requestSubmit}\n accessibilityRole=\"button\"\n disabled={isSubmitting}\n style={buttonStyle}\n testID={withTestIdPrefix(AuthTestIds.otpRequestButton, testIdPrefix)}\n onPress={(): void => onSubmit(email.trim())}\n >\n {isSubmitting ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.requestSubmit}</Text>\n )}\n </TouchableOpacity>\n </>\n );\n}\n\nexport interface OtpVerifyStepProps {\n styles: AuthStyles;\n theme: AuthTheme;\n labels: OtpFormLabels;\n testIdPrefix?: string;\n /** The email the code was sent to — interpolated into the description copy. */\n identifier: string;\n isSubmitting: boolean;\n errorText: string | null;\n /** Called with the trimmed code when the user taps \"verify\". */\n onSubmit: (code: string) => void;\n /** Called when the user taps \"resend code\". */\n onResend: () => void;\n /** Called when the user taps \"use a different email\". */\n onChangeEmail: () => void;\n}\n\n/** Step 2 — collect the code, verify it, and offer resend / change-email. */\nexport function OtpVerifyStep({\n styles,\n theme,\n labels,\n testIdPrefix,\n identifier,\n isSubmitting,\n errorText,\n onSubmit,\n onResend,\n onChangeEmail,\n}: Readonly<OtpVerifyStepProps>): ReactElement {\n const [code, setCode] = useState('');\n const buttonStyle = isSubmitting\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n const description = labels.verifyDescription.replace('{identifier}', identifier);\n\n return (\n <>\n <Text style={styles.title}>{labels.verifyTitle}</Text>\n <Text style={styles.subtitle}>{description}</Text>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.codeLabel}</Text>\n <TextInput\n accessibilityHint={labels.codePlaceholder}\n accessibilityLabel={labels.codeLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!isSubmitting}\n keyboardType=\"number-pad\"\n placeholder={labels.codePlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.otpCodeInput, testIdPrefix)}\n value={code}\n onChangeText={setCode}\n />\n </View>\n\n {errorText !== null ? (\n <Text style={styles.errorText} testID={withTestIdPrefix(AuthTestIds.otpError, testIdPrefix)}>\n {errorText}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.verifySubmit}\n accessibilityLabel={isSubmitting ? labels.verifying : labels.verifySubmit}\n accessibilityRole=\"button\"\n disabled={isSubmitting}\n style={buttonStyle}\n testID={withTestIdPrefix(AuthTestIds.otpVerifyButton, testIdPrefix)}\n onPress={(): void => onSubmit(code.trim())}\n >\n {isSubmitting ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.verifySubmit}</Text>\n )}\n </TouchableOpacity>\n\n <TouchableOpacity\n accessibilityHint={labels.resend}\n accessibilityLabel={isSubmitting ? labels.resending : labels.resend}\n accessibilityRole=\"link\"\n disabled={isSubmitting}\n style={styles.fieldGroup}\n testID={withTestIdPrefix(AuthTestIds.otpResendButton, testIdPrefix)}\n onPress={onResend}\n >\n <Text style={styles.linkText}>{isSubmitting ? labels.resending : labels.resend}</Text>\n </TouchableOpacity>\n\n <TouchableOpacity\n accessibilityHint={labels.changeEmail}\n accessibilityLabel={labels.changeEmail}\n accessibilityRole=\"link\"\n disabled={isSubmitting}\n testID={withTestIdPrefix(AuthTestIds.otpChangeEmailButton, testIdPrefix)}\n onPress={onChangeEmail}\n >\n <Text style={styles.linkText}>{labels.changeEmail}</Text>\n </TouchableOpacity>\n </>\n );\n}\n","/**\n * The two discrete steps of the email-OTP login flow.\n *\n * `useOtpLogin` is at exactly one of these at a time, and `<OtpForm>` renders a\n * different surface per step. The flow is strictly forward: a request moves\n * `RequestCode` → `EnterCode`; a resend stays on `EnterCode`. Each member is a\n * stable key — `<OtpForm>` switches on it, never on a string literal.\n */\nexport const enum OtpLoginStep {\n /** Step 1: collect the email and ask the BFF to send a code. */\n RequestCode = 'requestCode',\n /** Step 2: the code is on its way — collect and verify it. */\n EnterCode = 'enterCode',\n}\n","/**\n * `useOtpLogin` — the headless email-OTP login hook.\n *\n * The \"escape hatch\" half of the OTP design: apps that want a fully custom\n * layout skip `<OtpForm>` and drive the two-step flow themselves with this\n * hook. `<OtpForm>` itself is built on top of it, so the ready-made and the\n * custom paths share one code path — the same lesson as `useBffAuth`.\n *\n * The flow is a small forward state machine:\n *\n * step 1 `RequestCode` → `requestCode(identifier)` → `POST /bff/otp/request`\n * step 2 `EnterCode` → `verifyCode(otp)` → `POST /bff/otp/verify`\n * → `resend()` → `POST /bff/otp/request`\n *\n * It owns nothing the BFF owns — no tokens, no refresh, no realm awareness. It\n * holds only the current step, the identifier the code was sent to, the latest\n * `requestOtp` result (so the UI can show the expiry), and the in-flight status\n * + error. A successful `verifyCode` resolves to the `BffUser` exactly like\n * `useBffAuth.login`; the consumer routes from there.\n *\n * `BffAuthClient` / `BffUser` / `BffOtpRequestResult` come from\n * `@dloizides/auth-client`.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { OtpLoginStep } from './OtpLoginStep';\n\nimport type {\n BffAuthClient,\n BffOtpRequestResult,\n BffUser,\n} from '@dloizides/auth-client';\n\nexport interface UseOtpLoginOptions {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n}\n\nexport interface UseOtpLoginResult {\n /** Which of the two steps the flow is currently on. */\n step: OtpLoginStep;\n /** The identifier (email) the code was last requested for; `''` before step 1. */\n identifier: string;\n /**\n * The latest `POST /bff/otp/request` result, or `null` before any request.\n * Carries `expiresIn` for a countdown — never depend on `code` being present.\n */\n lastRequest: BffOtpRequestResult | null;\n /** `true` while a `requestCode` / `verifyCode` / `resend` call is in flight. */\n isSubmitting: boolean;\n /** The last error, cleared at the start of the next attempt. */\n error: Error | null;\n /**\n * Step 1 — ask the BFF to email a code to `identifier`. On success the flow\n * advances to `EnterCode`. Rejects (and stays on `RequestCode`) on failure.\n */\n requestCode: (identifier: string) => Promise<BffOtpRequestResult>;\n /**\n * Step 2 — verify the entered `otp` for the stored identifier. Resolves to the\n * signed-in `BffUser`; rejects on a bad / expired code (the flow stays on\n * `EnterCode` so the user can retry or resend).\n */\n verifyCode: (otp: string) => Promise<BffUser>;\n /**\n * Re-send a code to the stored identifier without leaving `EnterCode`. A\n * convenience wrapper over `requestOtp` for the step-2 \"resend\" affordance.\n */\n resend: () => Promise<BffOtpRequestResult>;\n /** Return to step 1 (e.g. the user mistyped their email). Clears the error. */\n reset: () => void;\n}\n\nfunction toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value));\n}\n\n/** Internal: the step + identifier + last-request triple the hook tracks. */\ninterface FlowState {\n step: OtpLoginStep;\n identifier: string;\n lastRequest: BffOtpRequestResult | null;\n}\n\nconst INITIAL_FLOW: FlowState = {\n step: OtpLoginStep.RequestCode,\n identifier: '',\n lastRequest: null,\n};\n\n/**\n * Headless email-OTP login. Returns the current step, the in-flight status, and\n * `requestCode` / `verifyCode` / `resend` / `reset` callbacks. No rendering —\n * the consumer (or `<OtpForm>`) wires it to UI.\n */\nexport function useOtpLogin(options: UseOtpLoginOptions): UseOtpLoginResult {\n const { client } = options;\n\n const [flow, setFlow] = useState<FlowState>(INITIAL_FLOW);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Guard against a `setState` after the consumer unmounts mid-request.\n const mountedRef = useRef(true);\n useEffect(() => {\n mountedRef.current = true;\n return (): void => {\n mountedRef.current = false;\n };\n }, []);\n\n // The identifier is also held in a ref so `verifyCode` / `resend` read the\n // latest value without being re-created every time `flow` changes.\n const identifierRef = useRef('');\n\n const beginAttempt = useCallback((): void => {\n if (mountedRef.current) {\n setIsSubmitting(true);\n setError(null);\n }\n }, []);\n\n const endAttempt = useCallback((): void => {\n if (mountedRef.current) {\n setIsSubmitting(false);\n }\n }, []);\n\n /** Shared `requestOtp` call used by both `requestCode` and `resend`. */\n const sendCode = useCallback(\n async (identifier: string): Promise<BffOtpRequestResult> => {\n beginAttempt();\n try {\n const result = await client.requestOtp({ identifier });\n identifierRef.current = identifier;\n if (mountedRef.current) {\n setFlow({ step: OtpLoginStep.EnterCode, identifier, lastRequest: result });\n }\n return result;\n } catch (caught) {\n const err = toError(caught);\n if (mountedRef.current) {\n setError(err);\n }\n throw err;\n } finally {\n endAttempt();\n }\n },\n [client, beginAttempt, endAttempt],\n );\n\n const requestCode = useCallback(\n (identifier: string): Promise<BffOtpRequestResult> => sendCode(identifier),\n [sendCode],\n );\n\n const resend = useCallback(\n (): Promise<BffOtpRequestResult> => sendCode(identifierRef.current),\n [sendCode],\n );\n\n const verifyCode = useCallback(\n async (otp: string): Promise<BffUser> => {\n beginAttempt();\n try {\n return await client.verifyOtp({ username: identifierRef.current, otp });\n } catch (caught) {\n const err = toError(caught);\n if (mountedRef.current) {\n setError(err);\n }\n throw err;\n } finally {\n endAttempt();\n }\n },\n [client, beginAttempt, endAttempt],\n );\n\n const reset = useCallback((): void => {\n identifierRef.current = '';\n if (mountedRef.current) {\n setFlow(INITIAL_FLOW);\n setError(null);\n }\n }, []);\n\n return useMemo(\n () => ({\n step: flow.step,\n identifier: flow.identifier,\n lastRequest: flow.lastRequest,\n isSubmitting,\n error,\n requestCode,\n verifyCode,\n resend,\n reset,\n }),\n [\n flow.step,\n flow.identifier,\n flow.lastRequest,\n isSubmitting,\n error,\n requestCode,\n verifyCode,\n resend,\n reset,\n ],\n );\n}\n","/**\n * `<OtpForm>` — the ready-made, themeable two-step email-OTP login form.\n *\n * The \"themeable component\" half of the OTP design: drop it in, pass a\n * `client`, a `theme` (or wrap in `<AuthThemeProvider>`) and a localised\n * `labels` bag, and you have a branded email-OTP surface. It is built on the\n * headless `useOtpLogin` hook, so the ready-made and custom-layout paths share\n * one code path — the same pattern as `<LoginForm>`.\n *\n * Two steps, switched on `OtpLoginStep`:\n * 1. `RequestCode` — `<OtpRequestStep>`: an email field + a \"send code\" button.\n * 2. `EnterCode` — `<OtpVerifyStep>`: a code field + a \"verify\" button, plus\n * \"resend code\" and \"use a different email\" affordances.\n *\n * The package ships no router and no i18n. `onSuccess` hands the signed-in\n * `BffUser` back to the app; all copy comes from `labels`.\n */\nimport { useCallback, useMemo, useState, type ReactElement } from 'react';\n\nimport { View } from 'react-native';\n\nimport { DEFAULT_OTP_LABELS, type OtpFormLabels } from './labels';\nimport { OtpRequestStep, OtpVerifyStep } from './OtpFormSteps';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { OtpLoginStep } from '../hooks/OtpLoginStep';\nimport { useOtpLogin, type UseOtpLoginResult } from '../hooks/useOtpLogin';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\nimport type { BffAuthClient, BffUser } from '@dloizides/auth-client';\n\n// A deliberately loose, linear-time email shape check — identical to the one\n// `<ForgotPasswordForm>` uses. Strict validation is the backend's job.\nconst EMAIL_REGEX = /^[^@\\s]+@[^.\\s]+\\.[^\\s]+$/;\n\nexport interface OtpFormProps {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. Falls back to the default theme. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<OtpFormLabels>;\n /** Called with the signed-in user after a successful code verification. */\n onSuccess: (user: BffUser) => void;\n /** Prefix applied to every `testID` so multiple forms can share a screen. */\n testIdPrefix?: string;\n}\n\n/** `true` when `value` looks like an email address. */\nfunction isValidEmail(value: string): boolean {\n return EMAIL_REGEX.test(value);\n}\n\n/** Resolve the in-flight transport error onto a localised, non-leaking message. */\nfunction transportErrorFor(\n step: OtpLoginStep,\n error: Error | null,\n labels: OtpFormLabels,\n): string | null {\n if (error === null) {\n return null;\n }\n // Never echo the raw error — it can leak whether the identifier exists. Show\n // a generic, step-appropriate message instead.\n return step === OtpLoginStep.RequestCode ? labels.invalidEmail : labels.invalidCode;\n}\n\n/** Drive step 1: validate the email locally, then call `requestCode`. */\nfunction useRequestHandler(\n otp: UseOtpLoginResult,\n labels: OtpFormLabels,\n setLocalError: (value: string | null) => void,\n): (email: string) => void {\n return useCallback(\n (email: string): void => {\n setLocalError(null);\n if (!isValidEmail(email)) {\n setLocalError(labels.invalidEmail);\n return;\n }\n void otp.requestCode(email).catch(() => undefined);\n },\n [otp, labels.invalidEmail, setLocalError],\n );\n}\n\n/** Drive step 2: validate the code is present, then call `verifyCode`. */\nfunction useVerifyHandler(\n otp: UseOtpLoginResult,\n labels: OtpFormLabels,\n setLocalError: (value: string | null) => void,\n onSuccess: (user: BffUser) => void,\n): (code: string) => void {\n return useCallback(\n (code: string): void => {\n setLocalError(null);\n if (code.length === 0) {\n setLocalError(labels.missingCode);\n return;\n }\n otp\n .verifyCode(code)\n .then((user) => {\n onSuccess(user);\n })\n .catch(() => undefined);\n },\n [otp, labels.missingCode, setLocalError, onSuccess],\n );\n}\n\n/** Themeable two-step email-OTP login form built on `useOtpLogin`. */\nexport function OtpForm({\n client,\n theme: themeProp,\n labels: labelsProp,\n onSuccess,\n testIdPrefix,\n}: Readonly<OtpFormProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<OtpFormLabels>(\n () => ({ ...DEFAULT_OTP_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n const otp = useOtpLogin({ client });\n // A local validation error (bad email / empty code) lives separately from the\n // hook's transport error so a client-side failure does not need a round-trip.\n const [localError, setLocalError] = useState<string | null>(null);\n\n const handleRequest = useRequestHandler(otp, labels, setLocalError);\n const handleVerify = useVerifyHandler(otp, labels, setLocalError, onSuccess);\n const handleResend = useCallback((): void => {\n setLocalError(null);\n void otp.resend().catch(() => undefined);\n }, [otp]);\n const handleChangeEmail = useCallback((): void => {\n setLocalError(null);\n otp.reset();\n }, [otp]);\n\n const errorText = localError ?? transportErrorFor(otp.step, otp.error, labels);\n\n return (\n <View style={styles.screen}>\n <View style={styles.card} testID={withTestIdPrefix(AuthTestIds.otpForm, testIdPrefix)}>\n {otp.step === OtpLoginStep.RequestCode ? (\n <OtpRequestStep\n errorText={errorText}\n isSubmitting={otp.isSubmitting}\n labels={labels}\n styles={styles}\n testIdPrefix={testIdPrefix}\n theme={theme}\n onSubmit={handleRequest}\n />\n ) : (\n <OtpVerifyStep\n errorText={errorText}\n identifier={otp.identifier}\n isSubmitting={otp.isSubmitting}\n labels={labels}\n styles={styles}\n testIdPrefix={testIdPrefix}\n theme={theme}\n onChangeEmail={handleChangeEmail}\n onResend={handleResend}\n onSubmit={handleVerify}\n />\n )}\n </View>\n </View>\n );\n}\n","/**\n * `usePinLogin` — the headless event-scoped PIN login hook.\n *\n * The \"escape hatch\" half of the PIN design: apps that want a fully custom\n * layout skip `<PinForm>` and drive the flow themselves with this hook.\n * `<PinForm>` itself is built on top of it, so the ready-made and the custom\n * paths share one code path — the same lesson as `useOtpLogin` / `useBffAuth`.\n *\n * Unlike `useOtpLogin` the PIN flow is a **single step** — there is no\n * request/verify split, the staff member just enters the PIN:\n *\n * `submit(pin)` → `POST /bff/pin/login` → `BffUser`\n *\n * The `(event, pin)` pair alone identifies the staff member (unified-auth plan\n * §4.4) — the `eventExternalId` is supplied to the hook by the page/route, the\n * PIN by the user. It owns nothing the BFF owns — no tokens, no refresh, no\n * realm awareness. It holds only the in-flight status + error. A successful\n * `submit` resolves to the `BffUser` exactly like `useBffAuth.login`; the\n * consumer routes from there.\n *\n * `BffAuthClient` / `BffUser` come from `@dloizides/auth-client`.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { BffAuthClient, BffUser } from '@dloizides/auth-client';\n\nexport interface UsePinLoginOptions {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /**\n * External id of the event the PIN is scoped to. Supplied by the page/route\n * — the event context is never typed by the user.\n */\n eventExternalId: string;\n}\n\nexport interface UsePinLoginResult {\n /** `true` while a `submit` call is in flight. */\n isSubmitting: boolean;\n /** The last error, cleared at the start of the next attempt. */\n error: Error | null;\n /**\n * Exchange the entered `pin` (for the hook's `eventExternalId`) for a\n * session. Resolves to the signed-in `BffUser`; rejects on a bad / expired /\n * locked-out PIN (the consumer can let the user retry).\n */\n submit: (pin: string) => Promise<BffUser>;\n /** Clear the current error so the form can be retried cleanly. */\n reset: () => void;\n}\n\nfunction toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value));\n}\n\n/**\n * Headless event-scoped PIN login. Returns the in-flight status, the last\n * error, and `submit` / `reset` callbacks. No rendering — the consumer (or\n * `<PinForm>`) wires it to UI.\n */\nexport function usePinLogin(options: UsePinLoginOptions): UsePinLoginResult {\n const { client, eventExternalId } = options;\n\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Guard against a `setState` after the consumer unmounts mid-request.\n const mountedRef = useRef(true);\n useEffect(() => {\n mountedRef.current = true;\n return (): void => {\n mountedRef.current = false;\n };\n }, []);\n\n // The event id is also held in a ref so `submit` reads the latest value\n // without being re-created every time the prop changes.\n const eventIdRef = useRef(eventExternalId);\n useEffect(() => {\n eventIdRef.current = eventExternalId;\n }, [eventExternalId]);\n\n const submit = useCallback(\n async (pin: string): Promise<BffUser> => {\n if (mountedRef.current) {\n setIsSubmitting(true);\n setError(null);\n }\n try {\n return await client.pinLogin({ pin, eventExternalId: eventIdRef.current });\n } catch (caught) {\n const err = toError(caught);\n if (mountedRef.current) {\n setError(err);\n }\n throw err;\n } finally {\n if (mountedRef.current) {\n setIsSubmitting(false);\n }\n }\n },\n [client],\n );\n\n const reset = useCallback((): void => {\n if (mountedRef.current) {\n setError(null);\n }\n }, []);\n\n return useMemo(\n () => ({ isSubmitting, error, submit, reset }),\n [isSubmitting, error, submit, reset],\n );\n}\n","/**\n * `<PinForm>` — the ready-made, themeable single-step event-PIN login form.\n *\n * The \"themeable component\" half of the PIN design: drop it in, pass a\n * `client`, the `eventExternalId` of the event the staff member is signing in\n * to, a `theme` (or wrap in `<AuthThemeProvider>`) and a localised `labels`\n * bag, and you have a branded event-PIN surface. It is built on the headless\n * `usePinLogin` hook, so the ready-made and custom-layout paths share one code\n * path — the same pattern as `<OtpForm>` / `<LoginForm>`.\n *\n * Unlike `<OtpForm>` the PIN flow is a single step: a PIN field + a \"sign in\"\n * button. The `eventExternalId` is a prop, never typed by the user — the event\n * context comes from the route/page the form is rendered on.\n *\n * The package ships no router and no i18n. `onSuccess` hands the signed-in\n * `BffUser` back to the app; all copy comes from `labels`.\n */\nimport { useCallback, useMemo, useState, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TextInput, TouchableOpacity, View } from 'react-native';\n\nimport { DEFAULT_PIN_LABELS, type PinFormLabels } from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { usePinLogin, type UsePinLoginResult } from '../hooks/usePinLogin';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\nimport type { BffAuthClient, BffUser } from '@dloizides/auth-client';\n\nexport interface PinFormProps {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /**\n * External id of the event the PIN is scoped to. Supplied by the route/page\n * — the event context is never typed by the user.\n */\n eventExternalId: string;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. Falls back to the default theme. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<PinFormLabels>;\n /** Called with the signed-in user after a successful PIN exchange. */\n onSuccess: (user: BffUser) => void;\n /** Prefix applied to every `testID` so multiple forms can share a screen. */\n testIdPrefix?: string;\n}\n\n/** Resolve the in-flight transport error onto a localised, non-leaking message. */\nfunction transportErrorFor(error: Error | null, labels: PinFormLabels): string | null {\n if (error === null) {\n return null;\n }\n // Never echo the raw error — show a generic message instead.\n return labels.invalidPin;\n}\n\n/** Drive the single submit step: validate the PIN is present, then call `submit`. */\nfunction useSubmitHandler(\n pin: UsePinLoginResult,\n labels: PinFormLabels,\n setLocalError: (value: string | null) => void,\n onSuccess: (user: BffUser) => void,\n): (value: string) => void {\n return useCallback(\n (value: string): void => {\n setLocalError(null);\n if (value.length === 0) {\n setLocalError(labels.missingPin);\n return;\n }\n pin\n .submit(value)\n .then((user) => {\n onSuccess(user);\n })\n .catch(() => undefined);\n },\n [pin, labels.missingPin, setLocalError, onSuccess],\n );\n}\n\n/** Themeable single-step event-PIN login form built on `usePinLogin`. */\nexport function PinForm({\n client,\n eventExternalId,\n theme: themeProp,\n labels: labelsProp,\n onSuccess,\n testIdPrefix,\n}: Readonly<PinFormProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<PinFormLabels>(\n () => ({ ...DEFAULT_PIN_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n const pin = usePinLogin({ client, eventExternalId });\n // A local validation error (empty PIN) lives separately from the hook's\n // transport error so a client-side failure does not need a round-trip.\n const [localError, setLocalError] = useState<string | null>(null);\n const [pinValue, setPinValue] = useState('');\n\n const handleSubmit = useSubmitHandler(pin, labels, setLocalError, onSuccess);\n\n const errorText = localError ?? transportErrorFor(pin.error, labels);\n const buttonStyle = pin.isSubmitting\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n\n return (\n <View style={styles.screen}>\n <View style={styles.card} testID={withTestIdPrefix(AuthTestIds.pinForm, testIdPrefix)}>\n <Text style={styles.title}>{labels.title}</Text>\n <Text style={styles.subtitle}>{labels.description}</Text>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.pinLabel}</Text>\n <TextInput\n accessibilityHint={labels.pinPlaceholder}\n accessibilityLabel={labels.pinLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!pin.isSubmitting}\n keyboardType=\"number-pad\"\n placeholder={labels.pinPlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n secureTextEntry\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.pinInput, testIdPrefix)}\n value={pinValue}\n onChangeText={setPinValue}\n />\n </View>\n\n {errorText !== null ? (\n <Text\n style={styles.errorText}\n testID={withTestIdPrefix(AuthTestIds.pinError, testIdPrefix)}\n >\n {errorText}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.submit}\n accessibilityLabel={pin.isSubmitting ? labels.submitting : labels.submit}\n accessibilityRole=\"button\"\n disabled={pin.isSubmitting}\n style={buttonStyle}\n testID={withTestIdPrefix(AuthTestIds.pinSubmitButton, testIdPrefix)}\n onPress={(): void => handleSubmit(pinValue.trim())}\n >\n {pin.isSubmitting ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.submit}</Text>\n )}\n </TouchableOpacity>\n </View>\n </View>\n );\n}\n","/**\n * `createBffAuthClient` — the one-line wiring of a same-origin `BffAuthClient`.\n *\n * `BffAuthClient` (from `@dloizides/auth-client`) needs an `HttpClient`. Every\n * app wired it the same way — `createFetchHttpClient(fetch)` — and every app\n * hit the same trap: binding `fetch` at module load throws in a non-browser\n * runtime (the Jest/jsdom test environment has no `fetch` global). The lesson\n * of Phase 1 was \"copy-pasted auth adapters ship the same bug N times\", so the\n * correct wiring lives here once.\n *\n * `fetch` is resolved **lazily, per request** — module load stays\n * side-effect-free. `baseUrl` is omitted by default → same-origin: every\n * `/bff/*` call goes to the SPA's own host, which is fronted by the per-app\n * BFF (`bff-katalogos`, `bff-erevna`, ...).\n *\n * Extracted + generalised from `apps/katalogos-web/src/auth/bffAuthClient.ts`.\n */\nimport {\n BffAuthClient,\n createFetchHttpClient,\n type HttpClient,\n type HttpRequest,\n type HttpResponse,\n} from '@dloizides/auth-client';\n\nexport interface CreateBffAuthClientOptions {\n /**\n * BFF origin. Omit (the production default) for same-origin — the SPA's own\n * host is the BFF. An explicit origin is only useful for a non-same-origin\n * BFF or for tests.\n */\n baseUrl?: string;\n /**\n * Override the HTTP transport. Defaults to a lazily-resolved native `fetch`.\n * Tests pass a fake `HttpClient` here; production never needs to.\n */\n http?: HttpClient;\n}\n\n/**\n * Resolve the platform `fetch` lazily, per request.\n *\n * Resolving inside the request — never at module load — keeps importing this\n * module side-effect-free, so a test runtime without a `fetch` global does not\n * blow up the moment any file transitively imports `@dloizides/auth-web`.\n */\nasync function lazyFetchHttpClient(request: HttpRequest): Promise<HttpResponse> {\n const fetchImpl: typeof fetch | undefined =\n typeof fetch === 'function' ? fetch.bind(globalThis) : undefined;\n if (fetchImpl === undefined) {\n throw new Error('createBffAuthClient: fetch is not available in this environment');\n }\n return createFetchHttpClient(fetchImpl)(request);\n}\n\n/**\n * Build a same-origin `BffAuthClient`. With no arguments this is the exact\n * production wiring: same-origin, lazy `fetch`, no token handling.\n */\nexport function createBffAuthClient(options: CreateBffAuthClientOptions = {}): BffAuthClient {\n return new BffAuthClient({\n http: options.http ?? lazyFetchHttpClient,\n baseUrl: options.baseUrl,\n });\n}\n","/**\n * `resolvePostLoginRoute` — the role-based post-login router helper.\n *\n * The unified-auth plan's secondary goal is to kill the \"too many login links\"\n * problem (KUCY V2 has seven, one per role). One login surface; after a\n * successful login the app reads the user's role from the token claims and\n * routes to the right dashboard.\n *\n * This helper is intentionally pure and app-agnostic. The package does NOT\n * know any app's routes — the consuming app supplies a `RoleRouteTable`\n * mapping role → path. The helper picks the highest-priority matching role.\n *\n * Role priority: a user can hold several roles (`superUser` + `admin` + ...).\n * The table is consulted in the order its entries are listed — the FIRST\n * entry whose role the user holds wins. So an app lists the most privileged\n * role first. A `fallback` covers a user whose roles match no entry.\n */\nimport type { BffUser } from '@dloizides/auth-client';\n\n/** One role → route mapping. */\nexport interface RoleRoute {\n /** The Keycloak role name to match against the user's claims. */\n role: string;\n /** The route/path to send a user holding that role to. */\n route: string;\n}\n\n/** An app-supplied, ordered role-routing table. */\nexport interface RoleRouteTable {\n /**\n * Ordered list of role → route entries. Order is priority: the first entry\n * whose `role` the user holds is chosen. List the most privileged role first.\n */\n routes: RoleRoute[];\n /**\n * Route used when the user holds none of the listed roles. When omitted and\n * nothing matches, `resolvePostLoginRoute` returns `null` and the caller\n * decides what to do (e.g. show an \"no access\" screen).\n */\n fallback?: string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** Read a string array of roles from a `realm_access`-shaped value. */\nfunction readRealmAccessRoles(realmAccess: unknown): string[] {\n if (!isRecord(realmAccess)) {\n return [];\n }\n const roles = realmAccess.roles;\n if (!Array.isArray(roles)) {\n return [];\n }\n return roles.filter((role): role is string => typeof role === 'string');\n}\n\n/**\n * Collect every role on a `BffUser` — both the flat `roles` array and the\n * nested `realm_access.roles` — into a de-duplicated set. The BFF may surface\n * roles in either shape; this normalises both.\n */\nexport function collectUserRoles(user: BffUser): string[] {\n const flat = Array.isArray(user.roles)\n ? user.roles.filter((role): role is string => typeof role === 'string')\n : [];\n const realm = readRealmAccessRoles(user.realm_access);\n return Array.from(new Set([...flat, ...realm]));\n}\n\n/**\n * Resolve the post-login route for a user against an app-supplied table.\n *\n * Returns the route of the first table entry whose role the user holds; if no\n * entry matches, returns the table's `fallback`, or `null` when there is none.\n */\nexport function resolvePostLoginRoute(user: BffUser, table: RoleRouteTable): string | null {\n const userRoles = new Set(collectUserRoles(user));\n for (const entry of table.routes) {\n if (userRoles.has(entry.role)) {\n return entry.route;\n }\n }\n return table.fallback ?? null;\n}\n"]}
1
+ {"version":3,"sources":["../src/components/labels.ts","../src/components/testIds.ts","../src/components/useAuthStyles.ts","../src/hooks/useBffAuth.ts","../src/theme/AuthTheme.ts","../src/theme/AuthThemeProvider.tsx","../src/components/LoginForm.tsx","../src/hooks/useBffPasswordHooks.ts","../src/components/ForgotPasswordForm.tsx","../src/hooks/ResetPasswordError.ts","../src/password/PasswordPolicyError.ts","../src/password/passwordPolicy.ts","../src/hooks/useResetPasswordForm.ts","../src/components/ResetPasswordForm.tsx","../src/components/OtpFormSteps.tsx","../src/hooks/OtpLoginStep.ts","../src/hooks/useOtpLogin.ts","../src/components/OtpForm.tsx","../src/hooks/usePinLogin.ts","../src/components/PinForm.tsx","../src/client/createBffAuthClient.ts","../src/router/resolvePostLoginRoute.ts"],"names":["useMemo","StyleSheet","BffAuthStatus","useState","useRef","useEffect","useCallback","createContext","useContext","jsx","View","jsxs","Text","TextInput","TouchableOpacity","ActivityIndicator","useMutation","Fragment","ResetPasswordError","PasswordPolicyError","OtpLoginStep","toError","EMAIL_REGEX","isValidEmail","transportErrorFor","createFetchHttpClient","BffAuthClient"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Label bags for the auth components.\n *\n * `@dloizides/auth-web` ships **no** translation framework — it is i18n-agnostic\n * by design (each app already owns its own i18n). Every user-facing string a\n * component renders is supplied by the consuming app through a typed `labels`\n * prop. The app passes strings it has already localised with `FM()` / `t()`.\n *\n * Each bag has a `DEFAULT_*` constant (English) so a component renders sensibly\n * with no `labels` prop and a consuming app can spread-override only the keys\n * it wants to change.\n */\n\n/** Strings rendered by `<LoginForm>`. */\nexport interface LoginFormLabels {\n title: string;\n subtitle: string;\n usernameLabel: string;\n usernamePlaceholder: string;\n passwordLabel: string;\n passwordPlaceholder: string;\n submit: string;\n /** Shown while the login request is in flight. */\n submitting: string;\n /** The \"Forgot password?\" link text. */\n forgotPassword: string;\n /** The \"Create account\" link shown below the submit button when an\n * `onSignUp` handler is supplied. Omit the handler to hide the link. */\n signUp: string;\n /** Generic credentials-rejected message. */\n invalidCredentials: string;\n /** Shown when one or both fields are empty on submit. */\n missingFields: string;\n}\n\n/** Strings rendered by `<ForgotPasswordForm>`. */\nexport interface ForgotPasswordFormLabels {\n title: string;\n /** Copy above the email field. */\n description: string;\n emailLabel: string;\n emailPlaceholder: string;\n submit: string;\n submitting: string;\n /** Generic confirmation, shown regardless of whether the email is registered. */\n successMessage: string;\n /** Shown on a network / 5xx failure. */\n networkError: string;\n /** Shown when the entered value is not a valid email. */\n invalidEmail: string;\n}\n\n/** Strings rendered by `<OtpForm>` — the two-step email-OTP login form. */\nexport interface OtpFormLabels {\n // ── Step 1: request a code ────────────────────────────────────────────────\n /** Title shown on the request-a-code step. */\n requestTitle: string;\n /** Copy above the email field. */\n requestDescription: string;\n emailLabel: string;\n emailPlaceholder: string;\n /** The \"send code\" button. */\n requestSubmit: string;\n /** Shown while the request is in flight. */\n requesting: string;\n /** Shown when the entered value is not a valid email. */\n invalidEmail: string;\n\n // ── Step 2: enter the code ────────────────────────────────────────────────\n /** Title shown on the enter-the-code step. */\n verifyTitle: string;\n /** Copy above the code field; `{identifier}` is replaced with the email. */\n verifyDescription: string;\n codeLabel: string;\n codePlaceholder: string;\n /** The \"verify\" button. */\n verifySubmit: string;\n /** Shown while verification is in flight. */\n verifying: string;\n /** Shown when the code field is empty on submit. */\n missingCode: string;\n /** Generic \"that code was wrong / expired\" message. */\n invalidCode: string;\n\n // ── Step 2 affordances ────────────────────────────────────────────────────\n /** The \"resend code\" link text. */\n resend: string;\n /** Shown while a resend is in flight. */\n resending: string;\n /** The \"use a different email\" link text — returns to step 1. */\n changeEmail: string;\n}\n\n/** Strings rendered by `<PinForm>` — the single-step event-PIN login form. */\nexport interface PinFormLabels {\n /** Title shown above the PIN field. */\n title: string;\n /** Copy above the PIN field. */\n description: string;\n pinLabel: string;\n pinPlaceholder: string;\n /** The \"sign in\" button. */\n submit: string;\n /** Shown while the PIN exchange is in flight. */\n submitting: string;\n /** Shown when the PIN field is empty on submit. */\n missingPin: string;\n /** Generic \"that PIN was wrong / expired / locked out\" message. */\n invalidPin: string;\n}\n\n/** Strings rendered by `<ResetPasswordForm>`. */\nexport interface ResetPasswordFormLabels {\n title: string;\n description: string;\n newPasswordLabel: string;\n newPasswordPlaceholder: string;\n confirmPasswordLabel: string;\n confirmPasswordPlaceholder: string;\n submit: string;\n submitting: string;\n /** Error: one or both fields empty. */\n errorEmpty: string;\n /** Error: the new password fails the policy. */\n errorWeakPassword: string;\n /** Error: confirm does not match. */\n errorMismatch: string;\n /** Error: the reset token is missing / expired / consumed. */\n errorTokenInvalid: string;\n /** Error: a network / 5xx failure. */\n errorNetwork: string;\n}\n\nexport const DEFAULT_LOGIN_LABELS: LoginFormLabels = {\n title: 'Sign in',\n subtitle: 'Welcome back',\n usernameLabel: 'Username',\n usernamePlaceholder: 'Enter your username',\n passwordLabel: 'Password',\n passwordPlaceholder: 'Enter your password',\n submit: 'Sign in',\n submitting: 'Signing in...',\n forgotPassword: 'Forgot password?',\n signUp: 'Create an account',\n invalidCredentials: 'Incorrect username or password.',\n missingFields: 'Enter both your username and password.',\n};\n\nexport const DEFAULT_FORGOT_PASSWORD_LABELS: ForgotPasswordFormLabels = {\n title: 'Forgot password',\n description: 'Enter your email and we will send you a reset link.',\n emailLabel: 'Email',\n emailPlaceholder: 'Enter your email',\n submit: 'Send reset link',\n submitting: 'Sending...',\n successMessage: 'If that email is registered, a reset link is on its way.',\n networkError: 'Something went wrong. Please try again.',\n invalidEmail: 'Enter a valid email address.',\n};\n\nexport const DEFAULT_OTP_LABELS: OtpFormLabels = {\n requestTitle: 'Sign in with a code',\n requestDescription: 'Enter your email and we will send you a one-time code.',\n emailLabel: 'Email',\n emailPlaceholder: 'Enter your email',\n requestSubmit: 'Send code',\n requesting: 'Sending...',\n invalidEmail: 'Enter a valid email address.',\n verifyTitle: 'Enter your code',\n verifyDescription: 'We sent a one-time code to {identifier}.',\n codeLabel: 'One-time code',\n codePlaceholder: 'Enter the code',\n verifySubmit: 'Verify',\n verifying: 'Verifying...',\n missingCode: 'Enter the code we emailed you.',\n invalidCode: 'That code is incorrect or has expired.',\n resend: 'Resend code',\n resending: 'Resending...',\n changeEmail: 'Use a different email',\n};\n\nexport const DEFAULT_PIN_LABELS: PinFormLabels = {\n title: 'Enter your event PIN',\n description: 'Enter the PIN for this event to sign in.',\n pinLabel: 'PIN',\n pinPlaceholder: 'Enter your PIN',\n submit: 'Sign in',\n submitting: 'Signing in...',\n missingPin: 'Enter your event PIN.',\n invalidPin: 'That PIN is incorrect, has expired, or is locked out.',\n};\n\nexport const DEFAULT_RESET_PASSWORD_LABELS: ResetPasswordFormLabels = {\n title: 'Reset password',\n description: 'Choose a new password for your account.',\n newPasswordLabel: 'New password',\n newPasswordPlaceholder: 'Enter a new password',\n confirmPasswordLabel: 'Confirm password',\n confirmPasswordPlaceholder: 'Re-enter the new password',\n submit: 'Reset password',\n submitting: 'Resetting...',\n errorEmpty: 'Fill in both password fields.',\n errorWeakPassword:\n 'Use at least 8 characters with an uppercase letter, a lowercase letter and a digit.',\n errorMismatch: 'The passwords do not match.',\n errorTokenInvalid: 'This reset link is invalid or has expired. Request a new one.',\n errorNetwork: 'Something went wrong. Please try again.',\n};\n","/**\n * Stable `testID` values for every interactive element the auth components\n * render. Exported so E2E suites and unit tests reference one source of truth\n * rather than hard-coding string literals.\n *\n * Each component also accepts a `testIdPrefix` prop; when set, these base IDs\n * are prefixed so two forms can coexist on one screen without ID collisions.\n *\n * `sonarjs/no-hardcoded-passwords` is disabled for this file: it flags keys\n * such as `loginPasswordInput`, but every value here is a UI test ID, not a\n * credential. There are no secrets in this module.\n */\n/* eslint-disable sonarjs/no-hardcoded-passwords */\nexport const AuthTestIds = {\n loginForm: 'auth-login-form',\n loginUsernameInput: 'auth-login-username',\n loginPasswordInput: 'auth-login-password',\n loginSubmitButton: 'auth-login-submit',\n loginForgotLink: 'auth-login-forgot-link',\n loginSignUpLink: 'auth-login-signup-link',\n loginError: 'auth-login-error',\n\n forgotPasswordForm: 'auth-forgot-form',\n forgotPasswordEmailInput: 'auth-forgot-email',\n forgotPasswordSubmitButton: 'auth-forgot-submit',\n forgotPasswordError: 'auth-forgot-error',\n forgotPasswordSuccess: 'auth-forgot-success',\n\n resetPasswordForm: 'auth-reset-form',\n resetPasswordNewInput: 'auth-reset-new',\n resetPasswordConfirmInput: 'auth-reset-confirm',\n resetPasswordSubmitButton: 'auth-reset-submit',\n resetPasswordError: 'auth-reset-error',\n\n otpForm: 'auth-otp-form',\n otpEmailInput: 'auth-otp-email',\n otpRequestButton: 'auth-otp-request',\n otpCodeInput: 'auth-otp-code',\n otpVerifyButton: 'auth-otp-verify',\n otpResendButton: 'auth-otp-resend',\n otpChangeEmailButton: 'auth-otp-change-email',\n otpError: 'auth-otp-error',\n\n pinForm: 'auth-pin-form',\n pinInput: 'auth-pin-input',\n pinSubmitButton: 'auth-pin-submit',\n pinError: 'auth-pin-error',\n} as const;\n\n/** Apply an optional prefix to a base test ID. */\nexport function withTestIdPrefix(baseId: string, prefix?: string): string {\n return prefix === undefined || prefix === '' ? baseId : `${prefix}-${baseId}`;\n}\n","/**\n * `useAuthStyles` — turns an `AuthTheme` token bag into a React Native\n * `StyleSheet` shared by all three auth forms.\n *\n * Building the stylesheet here (once, memoised per theme) keeps each form\n * component focused on layout + behaviour, and guarantees the three forms are\n * visually consistent. Token → style mapping lives in exactly one place, so an\n * app re-theming `<LoginForm>` automatically re-themes the others.\n */\nimport { useMemo } from 'react';\n\nimport { StyleSheet, type TextStyle, type ViewStyle } from 'react-native';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\n\n/** The named styles every auth form draws from. */\nexport interface AuthStyles {\n screen: ViewStyle;\n card: ViewStyle;\n title: TextStyle;\n subtitle: TextStyle;\n fieldGroup: ViewStyle;\n label: TextStyle;\n input: TextStyle;\n inputError: TextStyle;\n primaryButton: ViewStyle;\n primaryButtonDisabled: ViewStyle;\n primaryButtonText: TextStyle;\n linkText: TextStyle;\n errorText: TextStyle;\n successText: TextStyle;\n helperText: TextStyle;\n}\n\nconst FULL_WIDTH = '100%';\nconst CARD_MAX_WIDTH = 420;\nconst BUTTON_VERTICAL_PADDING = 14;\n\n/** Build the auth `StyleSheet` from the resolved theme. */\nexport function useAuthStyles(theme: AuthTheme): AuthStyles {\n return useMemo(() => {\n const { colors, radii, spacing, typography } = theme;\n return StyleSheet.create<AuthStyles>({\n screen: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n padding: spacing.md,\n backgroundColor: colors.background,\n },\n card: {\n width: FULL_WIDTH,\n maxWidth: CARD_MAX_WIDTH,\n borderRadius: radii.card,\n padding: spacing.xl,\n backgroundColor: colors.surface,\n },\n title: {\n fontSize: typography.title,\n fontWeight: 'bold',\n textAlign: 'center',\n marginBottom: spacing.xs,\n color: colors.text,\n },\n subtitle: {\n fontSize: typography.subtitle,\n textAlign: 'center',\n marginBottom: spacing.lg,\n color: colors.textSecondary,\n },\n fieldGroup: {\n marginBottom: spacing.md,\n },\n label: {\n fontSize: typography.label,\n fontWeight: '600',\n marginBottom: spacing.xs,\n color: colors.text,\n },\n input: {\n borderWidth: 1,\n borderRadius: radii.input,\n padding: spacing.sm,\n fontSize: typography.body,\n borderColor: colors.border,\n backgroundColor: colors.background,\n color: colors.text,\n },\n inputError: {\n borderColor: colors.danger,\n },\n primaryButton: {\n borderRadius: radii.input,\n paddingVertical: BUTTON_VERTICAL_PADDING,\n alignItems: 'center',\n justifyContent: 'center',\n marginTop: spacing.xs,\n backgroundColor: colors.primary,\n },\n primaryButtonDisabled: {\n backgroundColor: colors.border,\n },\n primaryButtonText: {\n fontSize: typography.body,\n fontWeight: '600',\n color: colors.onPrimary,\n },\n linkText: {\n fontSize: typography.caption,\n textDecorationLine: 'underline',\n color: colors.primary,\n },\n errorText: {\n fontSize: typography.caption,\n marginTop: spacing.xs,\n color: colors.danger,\n },\n successText: {\n fontSize: typography.body,\n lineHeight: typography.body * 1.4,\n color: colors.success,\n },\n helperText: {\n fontSize: typography.caption,\n color: colors.textSecondary,\n },\n });\n }, [theme]);\n}\n","/**\n * `useBffAuth` — the headless login/logout/session hook.\n *\n * This is the \"escape hatch\" half of the package's design: apps that want a\n * fully custom layout skip `<LoginForm>` and drive auth themselves with this\n * hook. `<LoginForm>` itself is built on top of it, so the ready-made and the\n * custom paths share one code path.\n *\n * It owns nothing the BFF owns: no tokens, no refresh, no realm awareness. It\n * holds only the *current user* (the sanitised claims from `/bff/me`) plus the\n * in-flight status of `login` / `logout`. The httpOnly session cookie is the\n * single source of truth — `refresh()` re-reads `/bff/me` to resync.\n *\n * `BffUser` and `BffAuthClient` come from `@dloizides/auth-client`.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { BffAuthClient, BffLoginRequest, BffUser } from '@dloizides/auth-client';\n\n/** Lifecycle status of the auth session. */\nexport const enum BffAuthStatus {\n /** The initial `/bff/me` probe has not finished yet. */\n Loading = 'loading',\n /** A live session exists; `user` is populated. */\n Authenticated = 'authenticated',\n /** No session; `user` is `null`. */\n Unauthenticated = 'unauthenticated',\n}\n\nexport interface UseBffAuthOptions {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /**\n * When `true` (default), the hook probes `GET /bff/me` on mount to bootstrap\n * `status`/`user`. Set `false` to skip the probe (e.g. on a public page).\n */\n probeOnMount?: boolean;\n}\n\nexport interface UseBffAuthResult {\n /** The signed-in user, or `null` when there is no session. */\n user: BffUser | null;\n /** Session lifecycle status. */\n status: BffAuthStatus;\n /** `true` while a `login` or `logout` call is in flight. */\n isSubmitting: boolean;\n /** The last `login`/`logout`/`refresh` error, cleared on the next attempt. */\n error: Error | null;\n /** ROPC password login via `POST /bff/login`. Resolves to the user; rejects on failure. */\n login: (request: BffLoginRequest) => Promise<BffUser>;\n /** End the session via `POST /bff/logout`. Always resolves; never throws to the caller. */\n logout: () => Promise<void>;\n /** Re-read `GET /bff/me` and resync `user`/`status`. */\n refresh: () => Promise<void>;\n}\n\n/** Internal: the mutable session state the hook tracks. */\ninterface SessionState {\n user: BffUser | null;\n status: BffAuthStatus;\n}\n\nconst INITIAL_LOADING: SessionState = { user: null, status: BffAuthStatus.Loading };\nconst INITIAL_IDLE: SessionState = { user: null, status: BffAuthStatus.Unauthenticated };\n\nfunction toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value));\n}\n\n/**\n * Headless BFF auth. Returns the current user, the session status, and\n * `login` / `logout` / `refresh` callbacks. No rendering — the consumer (or\n * `<LoginForm>`) wires it to UI.\n */\nexport function useBffAuth(options: UseBffAuthOptions): UseBffAuthResult {\n const { client, probeOnMount = true } = options;\n\n const [session, setSession] = useState<SessionState>(\n probeOnMount ? INITIAL_LOADING : INITIAL_IDLE,\n );\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Guard against a `setState` after the consumer unmounts mid-request.\n const mountedRef = useRef(true);\n useEffect(() => {\n mountedRef.current = true;\n return (): void => {\n mountedRef.current = false;\n };\n }, []);\n\n const safeSetSession = useCallback((next: SessionState) => {\n if (mountedRef.current) {\n setSession(next);\n }\n }, []);\n\n const refresh = useCallback(async (): Promise<void> => {\n try {\n const user = await client.getCurrentUser();\n safeSetSession(\n user === null\n ? INITIAL_IDLE\n : { user, status: BffAuthStatus.Authenticated },\n );\n } catch (caught) {\n safeSetSession(INITIAL_IDLE);\n if (mountedRef.current) {\n setError(toError(caught));\n }\n }\n }, [client, safeSetSession]);\n\n const login = useCallback(\n async (request: BffLoginRequest): Promise<BffUser> => {\n if (mountedRef.current) {\n setIsSubmitting(true);\n setError(null);\n }\n try {\n const user = await client.login(request);\n safeSetSession({ user, status: BffAuthStatus.Authenticated });\n return user;\n } catch (caught) {\n const err = toError(caught);\n if (mountedRef.current) {\n setError(err);\n }\n throw err;\n } finally {\n if (mountedRef.current) {\n setIsSubmitting(false);\n }\n }\n },\n [client, safeSetSession],\n );\n\n const logout = useCallback(async (): Promise<void> => {\n if (mountedRef.current) {\n setIsSubmitting(true);\n setError(null);\n }\n try {\n await client.logout();\n } catch (caught) {\n // A failed logout still leaves the SPA logged out client-side — surface\n // the error but do not reject; the caller's UI should not get stuck.\n if (mountedRef.current) {\n setError(toError(caught));\n }\n } finally {\n safeSetSession(INITIAL_IDLE);\n if (mountedRef.current) {\n setIsSubmitting(false);\n }\n }\n }, [client, safeSetSession]);\n\n // Bootstrap the session once on mount when probing is enabled.\n useEffect(() => {\n if (probeOnMount) {\n void refresh();\n }\n // `refresh` is stable for a stable `client`; `probeOnMount` is read once.\n }, [probeOnMount, refresh]);\n\n return useMemo(\n () => ({\n user: session.user,\n status: session.status,\n isSubmitting,\n error,\n login,\n logout,\n refresh,\n }),\n [session.user, session.status, isSubmitting, error, login, logout, refresh],\n );\n}\n","/**\n * `AuthTheme` — the design-token contract every `@dloizides/auth-web` component\n * is styled against.\n *\n * The package owns **no** brand. Katalogos, Erevna and Kefi each look different;\n * each one maps its own theme system onto this flat token bag and passes it in\n * (via the `theme` prop or `<AuthThemeProvider>`). The component code only ever\n * reads these tokens — never an app-specific theme object — so the same\n * `<LoginForm>` renders on-brand in three visually distinct apps.\n *\n * Keep this shape minimal and stable: it is a public API surface.\n */\n\n/** Colour tokens — the only colours the auth components reference. */\nexport interface AuthThemeColors {\n /** Page / screen background behind the form card. */\n background: string;\n /** The form card surface colour. */\n surface: string;\n /** Primary text (titles, labels, input text). */\n text: string;\n /** Muted / secondary text (subtitles, helper copy). */\n textSecondary: string;\n /** Input + card border colour; also the disabled-button fill. */\n border: string;\n /** Brand primary — the submit button fill and link colour. */\n primary: string;\n /** Text drawn on top of `primary` (e.g. the submit button label). */\n onPrimary: string;\n /** Error text and error-state borders. */\n danger: string;\n /** Success text (e.g. the forgot-password confirmation). */\n success: string;\n}\n\n/** Corner-radius tokens. */\nexport interface AuthThemeRadii {\n /** Inputs and buttons. */\n input: number;\n /** The form card. */\n card: number;\n}\n\n/** Spacing scale (in density-independent pixels). */\nexport interface AuthThemeSpacing {\n /** Tight gap — e.g. label-to-input. */\n xs: number;\n /** Small gap. */\n sm: number;\n /** Default gap — between stacked fields. */\n md: number;\n /** Large gap — section separation. */\n lg: number;\n /** Card inner padding. */\n xl: number;\n}\n\n/** Font-size tokens. */\nexport interface AuthThemeTypography {\n /** Form title. */\n title: number;\n /** Form subtitle. */\n subtitle: number;\n /** Field labels. */\n label: number;\n /** Input text and button text. */\n body: number;\n /** Helper / error / footer copy. */\n caption: number;\n}\n\n/** The full token bag a consuming app supplies. */\nexport interface AuthTheme {\n colors: AuthThemeColors;\n radii: AuthThemeRadii;\n spacing: AuthThemeSpacing;\n typography: AuthThemeTypography;\n}\n\n/**\n * A neutral, accessible light-mode theme. Apps are expected to override this —\n * it exists so a component renders sensibly with zero configuration and so\n * `<AuthThemeProvider>` has a default value.\n */\nexport const defaultAuthTheme: AuthTheme = {\n colors: {\n background: '#f5f5f7',\n surface: '#ffffff',\n text: '#1a1a1a',\n textSecondary: '#6b6b6b',\n border: '#d0d0d5',\n primary: '#2563eb',\n onPrimary: '#ffffff',\n danger: '#d33333',\n success: '#1f7a3d',\n },\n radii: {\n input: 8,\n card: 12,\n },\n spacing: {\n xs: 8,\n sm: 12,\n md: 20,\n lg: 32,\n xl: 24,\n },\n typography: {\n title: 28,\n subtitle: 16,\n label: 14,\n body: 16,\n caption: 12,\n },\n};\n","/**\n * React context for the `AuthTheme`.\n *\n * Two ways to theme `@dloizides/auth-web` components:\n *\n * 1. Wrap the auth screens in `<AuthThemeProvider theme={appAuthTheme}>` —\n * every component below reads the theme from context.\n * 2. Pass `theme` directly as a prop to an individual component — the prop\n * always wins over context.\n *\n * With neither, components fall back to `defaultAuthTheme`. `useAuthTheme()`\n * implements that precedence (prop → context → default) so each component does\n * not re-derive it.\n */\nimport { createContext, useContext, useMemo, type ReactElement, type ReactNode } from 'react';\n\nimport { defaultAuthTheme, type AuthTheme } from './AuthTheme';\n\nconst AuthThemeContext = createContext<AuthTheme>(defaultAuthTheme);\n\nexport interface AuthThemeProviderProps {\n /** The token bag every descendant auth component is styled against. */\n theme: AuthTheme;\n children: ReactNode;\n}\n\n/** Provides an `AuthTheme` to every `@dloizides/auth-web` component below it. */\nexport function AuthThemeProvider({\n theme,\n children,\n}: Readonly<AuthThemeProviderProps>): ReactElement {\n return <AuthThemeContext.Provider value={theme}>{children}</AuthThemeContext.Provider>;\n}\n\n/**\n * Resolve the effective theme for a component.\n *\n * Precedence: an explicit `themeProp` (if given) wins over the context value,\n * which itself defaults to `defaultAuthTheme` when no provider is mounted.\n */\nexport function useAuthTheme(themeProp?: AuthTheme): AuthTheme {\n const contextTheme = useContext(AuthThemeContext);\n return useMemo(() => themeProp ?? contextTheme, [themeProp, contextTheme]);\n}\n","/**\n * `<LoginForm>` — the ready-made, themeable password-login form.\n *\n * The \"themeable component\" half of the package design: drop it in, pass a\n * `client`, a `theme` (or wrap in `<AuthThemeProvider>`) and a localised\n * `labels` bag, and you have a branded login surface. It is built on the\n * headless `useBffAuth` hook, so the ready-made and custom-layout paths share\n * one code path.\n *\n * The package ships no router and no i18n. `onSuccess` hands the signed-in\n * `BffUser` back to the app, which decides where to navigate (typically via\n * `resolvePostLoginRoute`). All copy comes from `labels`.\n */\nimport { useCallback, useMemo, useState, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TextInput, TouchableOpacity, View } from 'react-native';\n\nimport { DEFAULT_LOGIN_LABELS, type LoginFormLabels } from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { useBffAuth } from '../hooks/useBffAuth';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\nimport type { BffAuthClient, BffUser } from '@dloizides/auth-client';\n\nexport interface LoginFormProps {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. Falls back to the default theme. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<LoginFormLabels>;\n /** Called with the signed-in user after a successful login. */\n onSuccess: (user: BffUser) => void;\n /** Called when the user taps the \"Forgot password?\" link. Omit to hide the link. */\n onForgotPassword?: () => void;\n /**\n * Called when the user taps the \"Create account\" link. Omit to hide the link\n * (the registration UI then has to be reached some other way — direct nav,\n * marketing CTA, etc.). The consuming app decides where the link routes;\n * `<LoginForm>` just surfaces the entry point.\n */\n onSignUp?: () => void;\n /** Prefix applied to every `testID` so multiple forms can share a screen. */\n testIdPrefix?: string;\n}\n\n/** Themeable password-login form built on `useBffAuth`. */\nexport function LoginForm({\n client,\n theme: themeProp,\n labels: labelsProp,\n onSuccess,\n onForgotPassword,\n onSignUp,\n testIdPrefix,\n}: Readonly<LoginFormProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<LoginFormLabels>(\n () => ({ ...DEFAULT_LOGIN_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n // probeOnMount is off: the login screen does not need a /bff/me round-trip.\n const { login, isSubmitting } = useBffAuth({ client, probeOnMount: false });\n\n const [username, setUsername] = useState('');\n const [password, setPassword] = useState('');\n const [errorText, setErrorText] = useState<string | null>(null);\n\n const runLogin = useCallback(async (): Promise<void> => {\n setErrorText(null);\n const trimmedUsername = username.trim();\n const hasMissingField = trimmedUsername.length === 0 || password.length === 0;\n if (hasMissingField) {\n setErrorText(labels.missingFields);\n return;\n }\n try {\n const user = await login({ username: trimmedUsername, password });\n onSuccess(user);\n } catch {\n // The BFF answers a wrong credential with a non-2xx; show a generic\n // message — never echo the raw error (it can leak whether the user exists).\n setErrorText(labels.invalidCredentials);\n }\n }, [username, password, login, onSuccess, labels.missingFields, labels.invalidCredentials]);\n\n // `onPress` expects a void-returning handler; `runLogin` is async, so wrap it.\n const handleSubmit = useCallback((): void => {\n void runLogin();\n }, [runLogin]);\n\n const submitButtonStyle = isSubmitting\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n\n return (\n <View style={styles.screen}>\n <View style={styles.card} testID={withTestIdPrefix(AuthTestIds.loginForm, testIdPrefix)}>\n <Text style={styles.title}>{labels.title}</Text>\n <Text style={styles.subtitle}>{labels.subtitle}</Text>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.usernameLabel}</Text>\n <TextInput\n accessibilityHint={labels.usernamePlaceholder}\n accessibilityLabel={labels.usernameLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!isSubmitting}\n placeholder={labels.usernamePlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.loginUsernameInput, testIdPrefix)}\n value={username}\n onChangeText={setUsername}\n />\n </View>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.passwordLabel}</Text>\n <TextInput\n secureTextEntry\n accessibilityHint={labels.passwordPlaceholder}\n accessibilityLabel={labels.passwordLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!isSubmitting}\n placeholder={labels.passwordPlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.loginPasswordInput, testIdPrefix)}\n value={password}\n onChangeText={setPassword}\n />\n </View>\n\n {errorText !== null ? (\n <Text\n style={styles.errorText}\n testID={withTestIdPrefix(AuthTestIds.loginError, testIdPrefix)}\n >\n {errorText}\n </Text>\n ) : null}\n\n {onForgotPassword !== undefined ? (\n <TouchableOpacity\n accessibilityHint={labels.forgotPassword}\n accessibilityLabel={labels.forgotPassword}\n accessibilityRole=\"link\"\n disabled={isSubmitting}\n style={styles.fieldGroup}\n testID={withTestIdPrefix(AuthTestIds.loginForgotLink, testIdPrefix)}\n onPress={onForgotPassword}\n >\n <Text style={styles.linkText}>{labels.forgotPassword}</Text>\n </TouchableOpacity>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.submit}\n accessibilityLabel={isSubmitting ? labels.submitting : labels.submit}\n accessibilityRole=\"button\"\n disabled={isSubmitting}\n style={submitButtonStyle}\n testID={withTestIdPrefix(AuthTestIds.loginSubmitButton, testIdPrefix)}\n onPress={handleSubmit}\n >\n {isSubmitting ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.submit}</Text>\n )}\n </TouchableOpacity>\n\n {onSignUp !== undefined ? (\n <TouchableOpacity\n accessibilityHint={labels.signUp}\n accessibilityLabel={labels.signUp}\n accessibilityRole=\"link\"\n disabled={isSubmitting}\n style={styles.fieldGroup}\n testID={withTestIdPrefix(AuthTestIds.loginSignUpLink, testIdPrefix)}\n onPress={onSignUp}\n >\n <Text style={styles.linkText}>{labels.signUp}</Text>\n </TouchableOpacity>\n ) : null}\n </View>\n </View>\n );\n}\n","/**\n * React Query mutation hooks for the BFF password-reset flow.\n *\n * Headless counterparts to `<ForgotPasswordForm>` / `<ResetPasswordForm>` —\n * apps with a custom layout use these directly. They POST to the same-origin\n * `/bff/forgot-password` and `/bff/reset-password`, which the BFF proxies to\n * TenantService.\n *\n * Extracted + generalised from `apps/katalogos-web/src/auth/bffPasswordHooks.ts`.\n * Difference: the katalogos version closed over a module-level singleton\n * `bffAuthClient`; the package version takes the `client` in the options so it\n * carries no global state.\n *\n * The mutation result type is `undefined` (not `void`): the BFF endpoints\n * return no body, and `undefined` is a valid generic argument where the lint\n * config rejects `void`.\n */\nimport { useMutation, type UseMutationOptions, type UseMutationResult } from '@tanstack/react-query';\n\nimport type {\n BffAuthClient,\n BffForgotPasswordRequest,\n BffResetPasswordRequest,\n} from '@dloizides/auth-client';\n\nexport type UseBffForgotPasswordOptions = Omit<\n UseMutationOptions<undefined, Error, BffForgotPasswordRequest>,\n 'mutationFn'\n> & {\n /** The same-origin BFF client. */\n client: BffAuthClient;\n};\n\n/**\n * Mutation that POSTs to `/bff/forgot-password`.\n *\n * The backend returns 200 unconditionally (no email enumeration); the UI\n * should show the same \"if that email exists, we sent a link\" message whether\n * `onSuccess` or `onError` fires.\n */\nexport function useBffForgotPassword(\n options: UseBffForgotPasswordOptions,\n): UseMutationResult<undefined, Error, BffForgotPasswordRequest> {\n const { client, ...rest } = options;\n return useMutation<undefined, Error, BffForgotPasswordRequest>({\n mutationFn: async (request) => {\n await client.forgotPassword(request);\n return undefined;\n },\n ...rest,\n });\n}\n\nexport type UseBffResetPasswordOptions = Omit<\n UseMutationOptions<undefined, Error, BffResetPasswordRequest>,\n 'mutationFn'\n> & {\n /** The same-origin BFF client. */\n client: BffAuthClient;\n};\n\n/**\n * Mutation that POSTs to `/bff/reset-password`. A `400` (invalid / expired\n * token) surfaces as a rejected mutation with the status in the error message.\n */\nexport function useBffResetPassword(\n options: UseBffResetPasswordOptions,\n): UseMutationResult<undefined, Error, BffResetPasswordRequest> {\n const { client, ...rest } = options;\n return useMutation<undefined, Error, BffResetPasswordRequest>({\n mutationFn: async (request) => {\n await client.resetPassword(request);\n return undefined;\n },\n ...rest,\n });\n}\n","/**\n * `<ForgotPasswordForm>` — the ready-made, themeable \"request a reset link\"\n * form.\n *\n * Captures an email and POSTs to `/bff/forgot-password` via the headless\n * `useBffForgotPassword` hook. The backend answers 200 unconditionally (no\n * email enumeration), so on success the form swaps to a generic confirmation\n * message — it never reveals whether the address is registered.\n *\n * Extracted + generalised from `apps/katalogos-web/src/components/Auth/\n * ForgotPasswordModal.tsx` — minus the modal shell (apps own the surface) and\n * the app-specific `FM()` calls (copy now comes from `labels`).\n */\nimport { useCallback, useMemo, useState, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TextInput, TouchableOpacity, View } from 'react-native';\n\nimport { DEFAULT_FORGOT_PASSWORD_LABELS, type ForgotPasswordFormLabels } from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { useBffForgotPassword } from '../hooks/useBffPasswordHooks';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\nimport type { BffAuthClient } from '@dloizides/auth-client';\n\n// A deliberately loose, linear-time email shape check — `[^@\\s]` and `[^.\\s]`\n// character classes have no overlapping alternation, so there is no\n// super-linear backtracking. Strict validation is the backend's job.\nconst EMAIL_REGEX = /^[^@\\s]+@[^.\\s]+\\.[^\\s]+$/;\n\nexport interface ForgotPasswordFormProps {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<ForgotPasswordFormLabels>;\n /**\n * Full URL with a `{token}` placeholder; forwarded to the backend so it can\n * build the reset-email link without hardcoding any frontend host. Optional —\n * apps that configure the template server-side can omit it.\n */\n resetUrlTemplate?: string;\n /** Called once the request succeeds (the generic-confirmation state). */\n onSuccess?: () => void;\n /** Prefix applied to every `testID`. */\n testIdPrefix?: string;\n}\n\n/** `true` when `value` looks like an email address. */\nfunction isValidEmail(value: string): boolean {\n return EMAIL_REGEX.test(value);\n}\n\n/** Themeable \"request a reset link\" form built on `useBffForgotPassword`. */\nexport function ForgotPasswordForm({\n client,\n theme: themeProp,\n labels: labelsProp,\n resetUrlTemplate,\n onSuccess,\n testIdPrefix,\n}: Readonly<ForgotPasswordFormProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<ForgotPasswordFormLabels>(\n () => ({ ...DEFAULT_FORGOT_PASSWORD_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n const [email, setEmail] = useState('');\n const [submitted, setSubmitted] = useState(false);\n const [errorText, setErrorText] = useState<string | null>(null);\n\n const mutationOptions = useMemo(\n () => ({\n client,\n onSuccess: (): void => {\n setSubmitted(true);\n onSuccess?.();\n },\n onError: (): void => {\n // Only a network / 5xx failure reaches here — a 200 (the no-enumeration\n // branch) is success. Show a friendly retry message.\n setErrorText(labels.networkError);\n },\n }),\n [client, onSuccess, labels.networkError],\n );\n const mutation = useBffForgotPassword(mutationOptions);\n\n const isPending = mutation.status === 'pending';\n\n const handleSubmit = useCallback((): void => {\n setErrorText(null);\n const trimmedEmail = email.trim();\n if (!isValidEmail(trimmedEmail)) {\n setErrorText(labels.invalidEmail);\n return;\n }\n mutation.mutate({ email: trimmedEmail, resetUrlTemplate });\n }, [email, mutation, resetUrlTemplate, labels.invalidEmail]);\n\n const submitButtonStyle = isPending\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n\n return (\n <View style={styles.screen}>\n <View\n style={styles.card}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix)}\n >\n <Text style={styles.title}>{labels.title}</Text>\n\n {submitted ? (\n <Text\n style={styles.successText}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordSuccess, testIdPrefix)}\n >\n {labels.successMessage}\n </Text>\n ) : (\n <>\n <Text style={styles.subtitle}>{labels.description}</Text>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.emailLabel}</Text>\n <TextInput\n accessibilityHint={labels.emailPlaceholder}\n accessibilityLabel={labels.emailLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!isPending}\n keyboardType=\"email-address\"\n placeholder={labels.emailPlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordEmailInput, testIdPrefix)}\n value={email}\n onChangeText={setEmail}\n />\n </View>\n\n {errorText !== null ? (\n <Text\n style={styles.errorText}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordError, testIdPrefix)}\n >\n {errorText}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.submit}\n accessibilityLabel={isPending ? labels.submitting : labels.submit}\n accessibilityRole=\"button\"\n disabled={isPending}\n style={submitButtonStyle}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordSubmitButton, testIdPrefix)}\n onPress={handleSubmit}\n >\n {isPending ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.submit}</Text>\n )}\n </TouchableOpacity>\n </>\n )}\n </View>\n </View>\n );\n}\n","/**\n * The discrete failure states the reset-password flow can surface.\n *\n * Each member is the stable key a consuming app maps onto a localised message.\n * `useResetPasswordForm` reports exactly one of these at a time, preferring the\n * earliest-fixable issue so the user resolves one thing at a time.\n */\nexport const enum ResetPasswordError {\n /** One or both password fields are empty. */\n Empty = 'empty',\n /** The new password fails the shared password policy. */\n WeakPassword = 'weakPassword',\n /** The confirm field does not match the new password. */\n Mismatch = 'mismatch',\n /** The reset token is missing, expired, or already consumed. */\n TokenInvalid = 'tokenInvalid',\n /** A network or 5xx failure prevented the reset from completing. */\n Network = 'network',\n}\n","/**\n * The discrete ways a password can fail the shared client-side policy.\n *\n * Each member is the stable key a consuming app maps onto a localised message —\n * the package never ships translated copy.\n */\nexport const enum PasswordPolicyError {\n /** Shorter than `PASSWORD_MIN_LENGTH`. */\n TooShort = 'tooShort',\n /** Longer than `PASSWORD_MAX_LENGTH`. */\n TooLong = 'tooLong',\n /** Contains no `A-Z` character. */\n MissingUppercase = 'missingUppercase',\n /** Contains no `a-z` character. */\n MissingLowercase = 'missingLowercase',\n /** Contains no `0-9` character. */\n MissingDigit = 'missingDigit',\n}\n","/**\n * Client-side password policy that mirrors the backend\n * (TenantService `ResetPasswordRequestValidator`):\n *\n * - 8 ≤ length ≤ 128\n * - at least one uppercase letter\n * - at least one lowercase letter\n * - at least one digit\n *\n * Shared so every app's `<ResetPasswordForm>` (and any future password input)\n * rejects ~99% of bad passwords before a network round-trip. Extracted from\n * `apps/katalogos-web/src/auth/passwordPolicy.ts`.\n */\nimport { PasswordPolicyError } from './PasswordPolicyError';\n\nconst UPPERCASE_REGEX = /[A-Z]/;\nconst LOWERCASE_REGEX = /[a-z]/;\nconst DIGIT_REGEX = /\\d/;\n\n/** Minimum acceptable password length. */\nexport const PASSWORD_MIN_LENGTH = 8;\n/** Maximum acceptable password length. */\nexport const PASSWORD_MAX_LENGTH = 128;\n\n/**\n * Return every policy rule the given password violates. An empty array means\n * the password is acceptable.\n */\nexport function validatePasswordPolicy(password: string): PasswordPolicyError[] {\n const errors: PasswordPolicyError[] = [];\n if (password.length < PASSWORD_MIN_LENGTH) {\n errors.push(PasswordPolicyError.TooShort);\n }\n if (password.length > PASSWORD_MAX_LENGTH) {\n errors.push(PasswordPolicyError.TooLong);\n }\n if (!UPPERCASE_REGEX.test(password)) {\n errors.push(PasswordPolicyError.MissingUppercase);\n }\n if (!LOWERCASE_REGEX.test(password)) {\n errors.push(PasswordPolicyError.MissingLowercase);\n }\n if (!DIGIT_REGEX.test(password)) {\n errors.push(PasswordPolicyError.MissingDigit);\n }\n return errors;\n}\n\n/** `true` when the password satisfies every policy rule. */\nexport function isPasswordValid(password: string): boolean {\n return validatePasswordPolicy(password).length === 0;\n}\n","/**\n * `useResetPasswordForm` — form-state + submit logic for the reset-password\n * screen.\n *\n * The (testable) logic — policy validation, confirm-match, error mapping — is\n * kept out of the rendered component so `<ResetPasswordForm>` stays thin and\n * the rules are unit-tested directly. The hook returns plain values + callbacks\n * the component (or a custom layout) wires to JSX.\n *\n * Behaviour:\n * - Validates the new password against the shared `passwordPolicy`.\n * - Validates confirmPassword matches.\n * - Surfaces a single `ResetPasswordError` at submit time, preferring the\n * earliest-fixable issue (empty → weak → mismatch → token).\n * - Calls `useBffResetPassword` (`POST /bff/reset-password`). On success,\n * invokes the supplied `onSuccess`.\n *\n * Extracted + generalised from `apps/katalogos-web/src/auth/useResetPasswordForm.ts`.\n */\nimport { useMemo, useState } from 'react';\n\nimport { ResetPasswordError } from './ResetPasswordError';\nimport { useBffResetPassword } from './useBffPasswordHooks';\nimport { isPasswordValid } from '../password/passwordPolicy';\n\nimport type { BffAuthClient } from '@dloizides/auth-client';\n\nconst HTTP_BAD_REQUEST = 400;\n\nexport interface UseResetPasswordFormArgs {\n /** The same-origin BFF client. */\n client: BffAuthClient;\n /** The reset token, typically read from the deep-link URL. */\n token: string;\n /** Invoked once the password has been reset successfully. */\n onSuccess: () => void;\n}\n\nexport interface UseResetPasswordFormResult {\n newPassword: string;\n confirmPassword: string;\n setNewPassword: (value: string) => void;\n setConfirmPassword: (value: string) => void;\n /** `true` while the reset request is in flight. */\n isSubmitting: boolean;\n /** The single active error, or `null` when the form is clean. */\n errorKey: ResetPasswordError | null;\n /** `true` once a token-related failure is detected (drives a \"request a new link\" UI). */\n hasInvalidToken: boolean;\n /** Validate, then submit. */\n submit: () => void;\n}\n\n/** `true` when the BFF error message carries the given HTTP status. */\nfunction isHttpStatusError(message: string, status: number): boolean {\n return message.includes(` status ${String(status)}`);\n}\n\n/** Run the synchronous pre-flight checks; the earliest-fixable failure wins. */\nfunction preflight(args: {\n newPassword: string;\n confirm: string;\n token: string;\n}): ResetPasswordError | null {\n if (args.newPassword.length === 0 || args.confirm.length === 0) {\n return ResetPasswordError.Empty;\n }\n if (!isPasswordValid(args.newPassword)) {\n return ResetPasswordError.WeakPassword;\n }\n if (args.newPassword !== args.confirm) {\n return ResetPasswordError.Mismatch;\n }\n if (args.token === '') {\n return ResetPasswordError.TokenInvalid;\n }\n return null;\n}\n\ninterface MutationCallbacks {\n onSuccess: () => void;\n setErrorKey: (error: ResetPasswordError) => void;\n setHasInvalidToken: (value: boolean) => void;\n}\n\n/** Wire the reset mutation, mapping a backend 400 onto a token-invalid error. */\nfunction useResetMutation(\n client: BffAuthClient,\n callbacks: MutationCallbacks,\n): ReturnType<typeof useBffResetPassword> {\n const mutationOptions = useMemo(\n () => ({\n client,\n onSuccess: callbacks.onSuccess,\n onError: (err: Error): void => {\n if (isHttpStatusError(err.message, HTTP_BAD_REQUEST)) {\n callbacks.setHasInvalidToken(true);\n callbacks.setErrorKey(ResetPasswordError.TokenInvalid);\n return;\n }\n callbacks.setErrorKey(ResetPasswordError.Network);\n },\n }),\n [client, callbacks],\n );\n return useBffResetPassword(mutationOptions);\n}\n\ninterface SubmitArgs {\n newPassword: string;\n confirmPassword: string;\n token: string;\n setErrorKey: (error: ResetPasswordError | null) => void;\n setHasInvalidToken: (value: boolean) => void;\n mutate: (request: { token: string; newPassword: string }) => void;\n}\n\n/** Validate, then either fire the mutation or surface the pre-flight failure. */\nfunction runSubmit(args: SubmitArgs): void {\n args.setErrorKey(null);\n const failure = preflight({\n newPassword: args.newPassword,\n confirm: args.confirmPassword,\n token: args.token,\n });\n if (failure === null) {\n args.mutate({ token: args.token, newPassword: args.newPassword });\n return;\n }\n if (failure === ResetPasswordError.TokenInvalid) {\n args.setHasInvalidToken(true);\n }\n args.setErrorKey(failure);\n}\n\ninterface FormState {\n newPassword: string;\n confirmPassword: string;\n errorKey: ResetPasswordError | null;\n hasInvalidToken: boolean;\n}\n\ninterface FormSetters {\n setNewPassword: (value: string) => void;\n setConfirmPassword: (value: string) => void;\n setErrorKey: (error: ResetPasswordError | null) => void;\n setHasInvalidToken: (value: boolean) => void;\n}\n\n/** Bundle the four `useState` cells the form needs. */\nfunction useFormState(): { state: FormState; setters: FormSetters } {\n const [newPassword, setNewPassword] = useState('');\n const [confirmPassword, setConfirmPassword] = useState('');\n const [errorKey, setErrorKey] = useState<ResetPasswordError | null>(null);\n const [hasInvalidToken, setHasInvalidToken] = useState(false);\n return {\n state: { newPassword, confirmPassword, errorKey, hasInvalidToken },\n setters: { setNewPassword, setConfirmPassword, setErrorKey, setHasInvalidToken },\n };\n}\n\n/**\n * Headless reset-password form logic. Returns the field values, setters, the\n * single active error, and a `submit` callback.\n */\nexport function useResetPasswordForm({\n client,\n token,\n onSuccess,\n}: UseResetPasswordFormArgs): UseResetPasswordFormResult {\n const { state, setters } = useFormState();\n const callbacks = useMemo<MutationCallbacks>(\n () => ({\n onSuccess,\n setErrorKey: setters.setErrorKey,\n setHasInvalidToken: setters.setHasInvalidToken,\n }),\n [onSuccess, setters.setErrorKey, setters.setHasInvalidToken],\n );\n const mutation = useResetMutation(client, callbacks);\n const submit = (): void =>\n runSubmit({\n newPassword: state.newPassword,\n confirmPassword: state.confirmPassword,\n token,\n setErrorKey: setters.setErrorKey,\n setHasInvalidToken: setters.setHasInvalidToken,\n mutate: mutation.mutate,\n });\n return {\n newPassword: state.newPassword,\n confirmPassword: state.confirmPassword,\n setNewPassword: setters.setNewPassword,\n setConfirmPassword: setters.setConfirmPassword,\n isSubmitting: mutation.status === 'pending',\n errorKey: state.errorKey,\n hasInvalidToken: state.hasInvalidToken,\n submit,\n };\n}\n","/**\n * `<ResetPasswordForm>` — the ready-made, themeable \"choose a new password\"\n * form.\n *\n * Built on the headless `useResetPasswordForm` hook, which owns all the logic\n * (shared password policy, confirm-match, backend-error mapping). The component\n * is a thin render layer: two fields, one button, one error line.\n *\n * Extracted + generalised from `apps/katalogos-web/src/auth/useResetPasswordForm.ts`\n * + the katalogos reset-password route — minus the app-specific `FM()` and\n * router calls (copy is in `labels`, navigation is the app's `onSuccess`).\n */\nimport { useMemo, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TextInput, TouchableOpacity, View } from 'react-native';\n\nimport { DEFAULT_RESET_PASSWORD_LABELS, type ResetPasswordFormLabels } from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { ResetPasswordError } from '../hooks/ResetPasswordError';\nimport { useResetPasswordForm } from '../hooks/useResetPasswordForm';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\nimport type { BffAuthClient } from '@dloizides/auth-client';\n\nexport interface ResetPasswordFormProps {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /** The reset token, typically read from the deep-link URL by the app. */\n token: string;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<ResetPasswordFormLabels>;\n /** Called once the password has been reset successfully. */\n onSuccess: () => void;\n /** Prefix applied to every `testID`. */\n testIdPrefix?: string;\n}\n\n/** Resolve the active `ResetPasswordError` onto its localised message. */\nfunction errorMessage(\n errorKey: ResetPasswordError | null,\n labels: ResetPasswordFormLabels,\n): string | null {\n switch (errorKey) {\n case ResetPasswordError.Empty:\n return labels.errorEmpty;\n case ResetPasswordError.WeakPassword:\n return labels.errorWeakPassword;\n case ResetPasswordError.Mismatch:\n return labels.errorMismatch;\n case ResetPasswordError.TokenInvalid:\n return labels.errorTokenInvalid;\n case ResetPasswordError.Network:\n return labels.errorNetwork;\n default:\n return null;\n }\n}\n\n/** Themeable \"choose a new password\" form built on `useResetPasswordForm`. */\nexport function ResetPasswordForm({\n client,\n token,\n theme: themeProp,\n labels: labelsProp,\n onSuccess,\n testIdPrefix,\n}: Readonly<ResetPasswordFormProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<ResetPasswordFormLabels>(\n () => ({ ...DEFAULT_RESET_PASSWORD_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n const form = useResetPasswordForm({ client, token, onSuccess });\n const message = errorMessage(form.errorKey, labels);\n\n const submitButtonStyle = form.isSubmitting\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n\n return (\n <View style={styles.screen}>\n <View\n style={styles.card}\n testID={withTestIdPrefix(AuthTestIds.resetPasswordForm, testIdPrefix)}\n >\n <Text style={styles.title}>{labels.title}</Text>\n <Text style={styles.subtitle}>{labels.description}</Text>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.newPasswordLabel}</Text>\n <TextInput\n secureTextEntry\n accessibilityHint={labels.newPasswordPlaceholder}\n accessibilityLabel={labels.newPasswordLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!form.isSubmitting}\n placeholder={labels.newPasswordPlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.resetPasswordNewInput, testIdPrefix)}\n value={form.newPassword}\n onChangeText={form.setNewPassword}\n />\n </View>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.confirmPasswordLabel}</Text>\n <TextInput\n secureTextEntry\n accessibilityHint={labels.confirmPasswordPlaceholder}\n accessibilityLabel={labels.confirmPasswordLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!form.isSubmitting}\n placeholder={labels.confirmPasswordPlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.resetPasswordConfirmInput, testIdPrefix)}\n value={form.confirmPassword}\n onChangeText={form.setConfirmPassword}\n />\n </View>\n\n {message !== null ? (\n <Text\n style={styles.errorText}\n testID={withTestIdPrefix(AuthTestIds.resetPasswordError, testIdPrefix)}\n >\n {message}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.submit}\n accessibilityLabel={form.isSubmitting ? labels.submitting : labels.submit}\n accessibilityRole=\"button\"\n disabled={form.isSubmitting}\n style={submitButtonStyle}\n testID={withTestIdPrefix(AuthTestIds.resetPasswordSubmitButton, testIdPrefix)}\n onPress={form.submit}\n >\n {form.isSubmitting ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.submit}</Text>\n )}\n </TouchableOpacity>\n </View>\n </View>\n );\n}\n","/**\n * The two step sub-components of `<OtpForm>` — `<OtpRequestStep>` (collect the\n * email, ask the BFF to send a code) and `<OtpVerifyStep>` (collect the code,\n * verify it, offer resend / change-email).\n *\n * Split out of `OtpForm.tsx` to keep that file focused on the flow wiring; each\n * step is a thin, self-contained render layer. Both are styled by the shared\n * `AuthStyles` token-derived stylesheet so they match the other auth forms.\n */\nimport { useState, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TextInput, TouchableOpacity, View } from 'react-native';\n\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { type AuthStyles } from './useAuthStyles';\n\nimport type { OtpFormLabels } from './labels';\nimport type { AuthTheme } from '../theme/AuthTheme';\n\nexport interface OtpRequestStepProps {\n styles: AuthStyles;\n theme: AuthTheme;\n labels: OtpFormLabels;\n testIdPrefix?: string;\n isSubmitting: boolean;\n errorText: string | null;\n /** Called with the trimmed email when the user taps \"send code\". */\n onSubmit: (email: string) => void;\n}\n\n/** Step 1 — collect the email and trigger `POST /bff/otp/request`. */\nexport function OtpRequestStep({\n styles,\n theme,\n labels,\n testIdPrefix,\n isSubmitting,\n errorText,\n onSubmit,\n}: Readonly<OtpRequestStepProps>): ReactElement {\n const [email, setEmail] = useState('');\n const buttonStyle = isSubmitting\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n\n return (\n <>\n <Text style={styles.title}>{labels.requestTitle}</Text>\n <Text style={styles.subtitle}>{labels.requestDescription}</Text>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.emailLabel}</Text>\n <TextInput\n accessibilityHint={labels.emailPlaceholder}\n accessibilityLabel={labels.emailLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!isSubmitting}\n keyboardType=\"email-address\"\n placeholder={labels.emailPlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.otpEmailInput, testIdPrefix)}\n value={email}\n onChangeText={setEmail}\n />\n </View>\n\n {errorText !== null ? (\n <Text style={styles.errorText} testID={withTestIdPrefix(AuthTestIds.otpError, testIdPrefix)}>\n {errorText}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.requestSubmit}\n accessibilityLabel={isSubmitting ? labels.requesting : labels.requestSubmit}\n accessibilityRole=\"button\"\n disabled={isSubmitting}\n style={buttonStyle}\n testID={withTestIdPrefix(AuthTestIds.otpRequestButton, testIdPrefix)}\n onPress={(): void => onSubmit(email.trim())}\n >\n {isSubmitting ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.requestSubmit}</Text>\n )}\n </TouchableOpacity>\n </>\n );\n}\n\nexport interface OtpVerifyStepProps {\n styles: AuthStyles;\n theme: AuthTheme;\n labels: OtpFormLabels;\n testIdPrefix?: string;\n /** The email the code was sent to — interpolated into the description copy. */\n identifier: string;\n isSubmitting: boolean;\n errorText: string | null;\n /** Called with the trimmed code when the user taps \"verify\". */\n onSubmit: (code: string) => void;\n /** Called when the user taps \"resend code\". */\n onResend: () => void;\n /** Called when the user taps \"use a different email\". */\n onChangeEmail: () => void;\n}\n\n/** Step 2 — collect the code, verify it, and offer resend / change-email. */\nexport function OtpVerifyStep({\n styles,\n theme,\n labels,\n testIdPrefix,\n identifier,\n isSubmitting,\n errorText,\n onSubmit,\n onResend,\n onChangeEmail,\n}: Readonly<OtpVerifyStepProps>): ReactElement {\n const [code, setCode] = useState('');\n const buttonStyle = isSubmitting\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n const description = labels.verifyDescription.replace('{identifier}', identifier);\n\n return (\n <>\n <Text style={styles.title}>{labels.verifyTitle}</Text>\n <Text style={styles.subtitle}>{description}</Text>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.codeLabel}</Text>\n <TextInput\n accessibilityHint={labels.codePlaceholder}\n accessibilityLabel={labels.codeLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!isSubmitting}\n keyboardType=\"number-pad\"\n placeholder={labels.codePlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.otpCodeInput, testIdPrefix)}\n value={code}\n onChangeText={setCode}\n />\n </View>\n\n {errorText !== null ? (\n <Text style={styles.errorText} testID={withTestIdPrefix(AuthTestIds.otpError, testIdPrefix)}>\n {errorText}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.verifySubmit}\n accessibilityLabel={isSubmitting ? labels.verifying : labels.verifySubmit}\n accessibilityRole=\"button\"\n disabled={isSubmitting}\n style={buttonStyle}\n testID={withTestIdPrefix(AuthTestIds.otpVerifyButton, testIdPrefix)}\n onPress={(): void => onSubmit(code.trim())}\n >\n {isSubmitting ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.verifySubmit}</Text>\n )}\n </TouchableOpacity>\n\n <TouchableOpacity\n accessibilityHint={labels.resend}\n accessibilityLabel={isSubmitting ? labels.resending : labels.resend}\n accessibilityRole=\"link\"\n disabled={isSubmitting}\n style={styles.fieldGroup}\n testID={withTestIdPrefix(AuthTestIds.otpResendButton, testIdPrefix)}\n onPress={onResend}\n >\n <Text style={styles.linkText}>{isSubmitting ? labels.resending : labels.resend}</Text>\n </TouchableOpacity>\n\n <TouchableOpacity\n accessibilityHint={labels.changeEmail}\n accessibilityLabel={labels.changeEmail}\n accessibilityRole=\"link\"\n disabled={isSubmitting}\n testID={withTestIdPrefix(AuthTestIds.otpChangeEmailButton, testIdPrefix)}\n onPress={onChangeEmail}\n >\n <Text style={styles.linkText}>{labels.changeEmail}</Text>\n </TouchableOpacity>\n </>\n );\n}\n","/**\n * The two discrete steps of the email-OTP login flow.\n *\n * `useOtpLogin` is at exactly one of these at a time, and `<OtpForm>` renders a\n * different surface per step. The flow is strictly forward: a request moves\n * `RequestCode` → `EnterCode`; a resend stays on `EnterCode`. Each member is a\n * stable key — `<OtpForm>` switches on it, never on a string literal.\n */\nexport const enum OtpLoginStep {\n /** Step 1: collect the email and ask the BFF to send a code. */\n RequestCode = 'requestCode',\n /** Step 2: the code is on its way — collect and verify it. */\n EnterCode = 'enterCode',\n}\n","/**\n * `useOtpLogin` — the headless email-OTP login hook.\n *\n * The \"escape hatch\" half of the OTP design: apps that want a fully custom\n * layout skip `<OtpForm>` and drive the two-step flow themselves with this\n * hook. `<OtpForm>` itself is built on top of it, so the ready-made and the\n * custom paths share one code path — the same lesson as `useBffAuth`.\n *\n * The flow is a small forward state machine:\n *\n * step 1 `RequestCode` → `requestCode(identifier)` → `POST /bff/otp/request`\n * step 2 `EnterCode` → `verifyCode(otp)` → `POST /bff/otp/verify`\n * → `resend()` → `POST /bff/otp/request`\n *\n * It owns nothing the BFF owns — no tokens, no refresh, no realm awareness. It\n * holds only the current step, the identifier the code was sent to, the latest\n * `requestOtp` result (so the UI can show the expiry), and the in-flight status\n * + error. A successful `verifyCode` resolves to the `BffUser` exactly like\n * `useBffAuth.login`; the consumer routes from there.\n *\n * `BffAuthClient` / `BffUser` / `BffOtpRequestResult` come from\n * `@dloizides/auth-client`.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { OtpLoginStep } from './OtpLoginStep';\n\nimport type {\n BffAuthClient,\n BffOtpRequestResult,\n BffUser,\n} from '@dloizides/auth-client';\n\nexport interface UseOtpLoginOptions {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n}\n\nexport interface UseOtpLoginResult {\n /** Which of the two steps the flow is currently on. */\n step: OtpLoginStep;\n /** The identifier (email) the code was last requested for; `''` before step 1. */\n identifier: string;\n /**\n * The latest `POST /bff/otp/request` result, or `null` before any request.\n * Carries `expiresIn` for a countdown — never depend on `code` being present.\n */\n lastRequest: BffOtpRequestResult | null;\n /** `true` while a `requestCode` / `verifyCode` / `resend` call is in flight. */\n isSubmitting: boolean;\n /** The last error, cleared at the start of the next attempt. */\n error: Error | null;\n /**\n * Step 1 — ask the BFF to email a code to `identifier`. On success the flow\n * advances to `EnterCode`. Rejects (and stays on `RequestCode`) on failure.\n */\n requestCode: (identifier: string) => Promise<BffOtpRequestResult>;\n /**\n * Step 2 — verify the entered `otp` for the stored identifier. Resolves to the\n * signed-in `BffUser`; rejects on a bad / expired code (the flow stays on\n * `EnterCode` so the user can retry or resend).\n */\n verifyCode: (otp: string) => Promise<BffUser>;\n /**\n * Re-send a code to the stored identifier without leaving `EnterCode`. A\n * convenience wrapper over `requestOtp` for the step-2 \"resend\" affordance.\n */\n resend: () => Promise<BffOtpRequestResult>;\n /** Return to step 1 (e.g. the user mistyped their email). Clears the error. */\n reset: () => void;\n}\n\nfunction toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value));\n}\n\n/** Internal: the step + identifier + last-request triple the hook tracks. */\ninterface FlowState {\n step: OtpLoginStep;\n identifier: string;\n lastRequest: BffOtpRequestResult | null;\n}\n\nconst INITIAL_FLOW: FlowState = {\n step: OtpLoginStep.RequestCode,\n identifier: '',\n lastRequest: null,\n};\n\n/**\n * Headless email-OTP login. Returns the current step, the in-flight status, and\n * `requestCode` / `verifyCode` / `resend` / `reset` callbacks. No rendering —\n * the consumer (or `<OtpForm>`) wires it to UI.\n */\nexport function useOtpLogin(options: UseOtpLoginOptions): UseOtpLoginResult {\n const { client } = options;\n\n const [flow, setFlow] = useState<FlowState>(INITIAL_FLOW);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Guard against a `setState` after the consumer unmounts mid-request.\n const mountedRef = useRef(true);\n useEffect(() => {\n mountedRef.current = true;\n return (): void => {\n mountedRef.current = false;\n };\n }, []);\n\n // The identifier is also held in a ref so `verifyCode` / `resend` read the\n // latest value without being re-created every time `flow` changes.\n const identifierRef = useRef('');\n\n const beginAttempt = useCallback((): void => {\n if (mountedRef.current) {\n setIsSubmitting(true);\n setError(null);\n }\n }, []);\n\n const endAttempt = useCallback((): void => {\n if (mountedRef.current) {\n setIsSubmitting(false);\n }\n }, []);\n\n /** Shared `requestOtp` call used by both `requestCode` and `resend`. */\n const sendCode = useCallback(\n async (identifier: string): Promise<BffOtpRequestResult> => {\n beginAttempt();\n try {\n const result = await client.requestOtp({ identifier });\n identifierRef.current = identifier;\n if (mountedRef.current) {\n setFlow({ step: OtpLoginStep.EnterCode, identifier, lastRequest: result });\n }\n return result;\n } catch (caught) {\n const err = toError(caught);\n if (mountedRef.current) {\n setError(err);\n }\n throw err;\n } finally {\n endAttempt();\n }\n },\n [client, beginAttempt, endAttempt],\n );\n\n const requestCode = useCallback(\n (identifier: string): Promise<BffOtpRequestResult> => sendCode(identifier),\n [sendCode],\n );\n\n const resend = useCallback(\n (): Promise<BffOtpRequestResult> => sendCode(identifierRef.current),\n [sendCode],\n );\n\n const verifyCode = useCallback(\n async (otp: string): Promise<BffUser> => {\n beginAttempt();\n try {\n return await client.verifyOtp({ username: identifierRef.current, otp });\n } catch (caught) {\n const err = toError(caught);\n if (mountedRef.current) {\n setError(err);\n }\n throw err;\n } finally {\n endAttempt();\n }\n },\n [client, beginAttempt, endAttempt],\n );\n\n const reset = useCallback((): void => {\n identifierRef.current = '';\n if (mountedRef.current) {\n setFlow(INITIAL_FLOW);\n setError(null);\n }\n }, []);\n\n return useMemo(\n () => ({\n step: flow.step,\n identifier: flow.identifier,\n lastRequest: flow.lastRequest,\n isSubmitting,\n error,\n requestCode,\n verifyCode,\n resend,\n reset,\n }),\n [\n flow.step,\n flow.identifier,\n flow.lastRequest,\n isSubmitting,\n error,\n requestCode,\n verifyCode,\n resend,\n reset,\n ],\n );\n}\n","/**\n * `<OtpForm>` — the ready-made, themeable two-step email-OTP login form.\n *\n * The \"themeable component\" half of the OTP design: drop it in, pass a\n * `client`, a `theme` (or wrap in `<AuthThemeProvider>`) and a localised\n * `labels` bag, and you have a branded email-OTP surface. It is built on the\n * headless `useOtpLogin` hook, so the ready-made and custom-layout paths share\n * one code path — the same pattern as `<LoginForm>`.\n *\n * Two steps, switched on `OtpLoginStep`:\n * 1. `RequestCode` — `<OtpRequestStep>`: an email field + a \"send code\" button.\n * 2. `EnterCode` — `<OtpVerifyStep>`: a code field + a \"verify\" button, plus\n * \"resend code\" and \"use a different email\" affordances.\n *\n * The package ships no router and no i18n. `onSuccess` hands the signed-in\n * `BffUser` back to the app; all copy comes from `labels`.\n */\nimport { useCallback, useMemo, useState, type ReactElement } from 'react';\n\nimport { View } from 'react-native';\n\nimport { DEFAULT_OTP_LABELS, type OtpFormLabels } from './labels';\nimport { OtpRequestStep, OtpVerifyStep } from './OtpFormSteps';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { OtpLoginStep } from '../hooks/OtpLoginStep';\nimport { useOtpLogin, type UseOtpLoginResult } from '../hooks/useOtpLogin';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\nimport type { BffAuthClient, BffUser } from '@dloizides/auth-client';\n\n// A deliberately loose, linear-time email shape check — identical to the one\n// `<ForgotPasswordForm>` uses. Strict validation is the backend's job.\nconst EMAIL_REGEX = /^[^@\\s]+@[^.\\s]+\\.[^\\s]+$/;\n\nexport interface OtpFormProps {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. Falls back to the default theme. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<OtpFormLabels>;\n /** Called with the signed-in user after a successful code verification. */\n onSuccess: (user: BffUser) => void;\n /** Prefix applied to every `testID` so multiple forms can share a screen. */\n testIdPrefix?: string;\n}\n\n/** `true` when `value` looks like an email address. */\nfunction isValidEmail(value: string): boolean {\n return EMAIL_REGEX.test(value);\n}\n\n/** Resolve the in-flight transport error onto a localised, non-leaking message. */\nfunction transportErrorFor(\n step: OtpLoginStep,\n error: Error | null,\n labels: OtpFormLabels,\n): string | null {\n if (error === null) {\n return null;\n }\n // Never echo the raw error — it can leak whether the identifier exists. Show\n // a generic, step-appropriate message instead.\n return step === OtpLoginStep.RequestCode ? labels.invalidEmail : labels.invalidCode;\n}\n\n/** Drive step 1: validate the email locally, then call `requestCode`. */\nfunction useRequestHandler(\n otp: UseOtpLoginResult,\n labels: OtpFormLabels,\n setLocalError: (value: string | null) => void,\n): (email: string) => void {\n return useCallback(\n (email: string): void => {\n setLocalError(null);\n if (!isValidEmail(email)) {\n setLocalError(labels.invalidEmail);\n return;\n }\n void otp.requestCode(email).catch(() => undefined);\n },\n [otp, labels.invalidEmail, setLocalError],\n );\n}\n\n/** Drive step 2: validate the code is present, then call `verifyCode`. */\nfunction useVerifyHandler(\n otp: UseOtpLoginResult,\n labels: OtpFormLabels,\n setLocalError: (value: string | null) => void,\n onSuccess: (user: BffUser) => void,\n): (code: string) => void {\n return useCallback(\n (code: string): void => {\n setLocalError(null);\n if (code.length === 0) {\n setLocalError(labels.missingCode);\n return;\n }\n otp\n .verifyCode(code)\n .then((user) => {\n onSuccess(user);\n })\n .catch(() => undefined);\n },\n [otp, labels.missingCode, setLocalError, onSuccess],\n );\n}\n\n/** Themeable two-step email-OTP login form built on `useOtpLogin`. */\nexport function OtpForm({\n client,\n theme: themeProp,\n labels: labelsProp,\n onSuccess,\n testIdPrefix,\n}: Readonly<OtpFormProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<OtpFormLabels>(\n () => ({ ...DEFAULT_OTP_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n const otp = useOtpLogin({ client });\n // A local validation error (bad email / empty code) lives separately from the\n // hook's transport error so a client-side failure does not need a round-trip.\n const [localError, setLocalError] = useState<string | null>(null);\n\n const handleRequest = useRequestHandler(otp, labels, setLocalError);\n const handleVerify = useVerifyHandler(otp, labels, setLocalError, onSuccess);\n const handleResend = useCallback((): void => {\n setLocalError(null);\n void otp.resend().catch(() => undefined);\n }, [otp]);\n const handleChangeEmail = useCallback((): void => {\n setLocalError(null);\n otp.reset();\n }, [otp]);\n\n const errorText = localError ?? transportErrorFor(otp.step, otp.error, labels);\n\n return (\n <View style={styles.screen}>\n <View style={styles.card} testID={withTestIdPrefix(AuthTestIds.otpForm, testIdPrefix)}>\n {otp.step === OtpLoginStep.RequestCode ? (\n <OtpRequestStep\n errorText={errorText}\n isSubmitting={otp.isSubmitting}\n labels={labels}\n styles={styles}\n testIdPrefix={testIdPrefix}\n theme={theme}\n onSubmit={handleRequest}\n />\n ) : (\n <OtpVerifyStep\n errorText={errorText}\n identifier={otp.identifier}\n isSubmitting={otp.isSubmitting}\n labels={labels}\n styles={styles}\n testIdPrefix={testIdPrefix}\n theme={theme}\n onChangeEmail={handleChangeEmail}\n onResend={handleResend}\n onSubmit={handleVerify}\n />\n )}\n </View>\n </View>\n );\n}\n","/**\n * `usePinLogin` — the headless event-scoped PIN login hook.\n *\n * The \"escape hatch\" half of the PIN design: apps that want a fully custom\n * layout skip `<PinForm>` and drive the flow themselves with this hook.\n * `<PinForm>` itself is built on top of it, so the ready-made and the custom\n * paths share one code path — the same lesson as `useOtpLogin` / `useBffAuth`.\n *\n * Unlike `useOtpLogin` the PIN flow is a **single step** — there is no\n * request/verify split, the staff member just enters the PIN:\n *\n * `submit(pin)` → `POST /bff/pin/login` → `BffUser`\n *\n * The `(event, pin)` pair alone identifies the staff member (unified-auth plan\n * §4.4) — the `eventExternalId` is supplied to the hook by the page/route, the\n * PIN by the user. It owns nothing the BFF owns — no tokens, no refresh, no\n * realm awareness. It holds only the in-flight status + error. A successful\n * `submit` resolves to the `BffUser` exactly like `useBffAuth.login`; the\n * consumer routes from there.\n *\n * `BffAuthClient` / `BffUser` come from `@dloizides/auth-client`.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { BffAuthClient, BffUser } from '@dloizides/auth-client';\n\nexport interface UsePinLoginOptions {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /**\n * External id of the event the PIN is scoped to. Supplied by the page/route\n * — the event context is never typed by the user.\n */\n eventExternalId: string;\n}\n\nexport interface UsePinLoginResult {\n /** `true` while a `submit` call is in flight. */\n isSubmitting: boolean;\n /** The last error, cleared at the start of the next attempt. */\n error: Error | null;\n /**\n * Exchange the entered `pin` (for the hook's `eventExternalId`) for a\n * session. Resolves to the signed-in `BffUser`; rejects on a bad / expired /\n * locked-out PIN (the consumer can let the user retry).\n */\n submit: (pin: string) => Promise<BffUser>;\n /** Clear the current error so the form can be retried cleanly. */\n reset: () => void;\n}\n\nfunction toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value));\n}\n\n/**\n * Headless event-scoped PIN login. Returns the in-flight status, the last\n * error, and `submit` / `reset` callbacks. No rendering — the consumer (or\n * `<PinForm>`) wires it to UI.\n */\nexport function usePinLogin(options: UsePinLoginOptions): UsePinLoginResult {\n const { client, eventExternalId } = options;\n\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Guard against a `setState` after the consumer unmounts mid-request.\n const mountedRef = useRef(true);\n useEffect(() => {\n mountedRef.current = true;\n return (): void => {\n mountedRef.current = false;\n };\n }, []);\n\n // The event id is also held in a ref so `submit` reads the latest value\n // without being re-created every time the prop changes.\n const eventIdRef = useRef(eventExternalId);\n useEffect(() => {\n eventIdRef.current = eventExternalId;\n }, [eventExternalId]);\n\n const submit = useCallback(\n async (pin: string): Promise<BffUser> => {\n if (mountedRef.current) {\n setIsSubmitting(true);\n setError(null);\n }\n try {\n return await client.pinLogin({ pin, eventExternalId: eventIdRef.current });\n } catch (caught) {\n const err = toError(caught);\n if (mountedRef.current) {\n setError(err);\n }\n throw err;\n } finally {\n if (mountedRef.current) {\n setIsSubmitting(false);\n }\n }\n },\n [client],\n );\n\n const reset = useCallback((): void => {\n if (mountedRef.current) {\n setError(null);\n }\n }, []);\n\n return useMemo(\n () => ({ isSubmitting, error, submit, reset }),\n [isSubmitting, error, submit, reset],\n );\n}\n","/**\n * `<PinForm>` — the ready-made, themeable single-step event-PIN login form.\n *\n * The \"themeable component\" half of the PIN design: drop it in, pass a\n * `client`, the `eventExternalId` of the event the staff member is signing in\n * to, a `theme` (or wrap in `<AuthThemeProvider>`) and a localised `labels`\n * bag, and you have a branded event-PIN surface. It is built on the headless\n * `usePinLogin` hook, so the ready-made and custom-layout paths share one code\n * path — the same pattern as `<OtpForm>` / `<LoginForm>`.\n *\n * Unlike `<OtpForm>` the PIN flow is a single step: a PIN field + a \"sign in\"\n * button. The `eventExternalId` is a prop, never typed by the user — the event\n * context comes from the route/page the form is rendered on.\n *\n * The package ships no router and no i18n. `onSuccess` hands the signed-in\n * `BffUser` back to the app; all copy comes from `labels`.\n */\nimport { useCallback, useMemo, useState, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TextInput, TouchableOpacity, View } from 'react-native';\n\nimport { DEFAULT_PIN_LABELS, type PinFormLabels } from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { usePinLogin, type UsePinLoginResult } from '../hooks/usePinLogin';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\nimport type { BffAuthClient, BffUser } from '@dloizides/auth-client';\n\nexport interface PinFormProps {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /**\n * External id of the event the PIN is scoped to. Supplied by the route/page\n * — the event context is never typed by the user.\n */\n eventExternalId: string;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. Falls back to the default theme. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<PinFormLabels>;\n /** Called with the signed-in user after a successful PIN exchange. */\n onSuccess: (user: BffUser) => void;\n /** Prefix applied to every `testID` so multiple forms can share a screen. */\n testIdPrefix?: string;\n}\n\n/** Resolve the in-flight transport error onto a localised, non-leaking message. */\nfunction transportErrorFor(error: Error | null, labels: PinFormLabels): string | null {\n if (error === null) {\n return null;\n }\n // Never echo the raw error — show a generic message instead.\n return labels.invalidPin;\n}\n\n/** Drive the single submit step: validate the PIN is present, then call `submit`. */\nfunction useSubmitHandler(\n pin: UsePinLoginResult,\n labels: PinFormLabels,\n setLocalError: (value: string | null) => void,\n onSuccess: (user: BffUser) => void,\n): (value: string) => void {\n return useCallback(\n (value: string): void => {\n setLocalError(null);\n if (value.length === 0) {\n setLocalError(labels.missingPin);\n return;\n }\n pin\n .submit(value)\n .then((user) => {\n onSuccess(user);\n })\n .catch(() => undefined);\n },\n [pin, labels.missingPin, setLocalError, onSuccess],\n );\n}\n\n/** Themeable single-step event-PIN login form built on `usePinLogin`. */\nexport function PinForm({\n client,\n eventExternalId,\n theme: themeProp,\n labels: labelsProp,\n onSuccess,\n testIdPrefix,\n}: Readonly<PinFormProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<PinFormLabels>(\n () => ({ ...DEFAULT_PIN_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n const pin = usePinLogin({ client, eventExternalId });\n // A local validation error (empty PIN) lives separately from the hook's\n // transport error so a client-side failure does not need a round-trip.\n const [localError, setLocalError] = useState<string | null>(null);\n const [pinValue, setPinValue] = useState('');\n\n const handleSubmit = useSubmitHandler(pin, labels, setLocalError, onSuccess);\n\n const errorText = localError ?? transportErrorFor(pin.error, labels);\n const buttonStyle = pin.isSubmitting\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n\n return (\n <View style={styles.screen}>\n <View style={styles.card} testID={withTestIdPrefix(AuthTestIds.pinForm, testIdPrefix)}>\n <Text style={styles.title}>{labels.title}</Text>\n <Text style={styles.subtitle}>{labels.description}</Text>\n\n <View style={styles.fieldGroup}>\n <Text style={styles.label}>{labels.pinLabel}</Text>\n <TextInput\n accessibilityHint={labels.pinPlaceholder}\n accessibilityLabel={labels.pinLabel}\n autoCapitalize=\"none\"\n autoCorrect={false}\n editable={!pin.isSubmitting}\n keyboardType=\"number-pad\"\n placeholder={labels.pinPlaceholder}\n placeholderTextColor={theme.colors.textSecondary}\n secureTextEntry\n style={styles.input}\n testID={withTestIdPrefix(AuthTestIds.pinInput, testIdPrefix)}\n value={pinValue}\n onChangeText={setPinValue}\n />\n </View>\n\n {errorText !== null ? (\n <Text\n style={styles.errorText}\n testID={withTestIdPrefix(AuthTestIds.pinError, testIdPrefix)}\n >\n {errorText}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.submit}\n accessibilityLabel={pin.isSubmitting ? labels.submitting : labels.submit}\n accessibilityRole=\"button\"\n disabled={pin.isSubmitting}\n style={buttonStyle}\n testID={withTestIdPrefix(AuthTestIds.pinSubmitButton, testIdPrefix)}\n onPress={(): void => handleSubmit(pinValue.trim())}\n >\n {pin.isSubmitting ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.submit}</Text>\n )}\n </TouchableOpacity>\n </View>\n </View>\n );\n}\n","/**\n * `createBffAuthClient` — the one-line wiring of a same-origin `BffAuthClient`.\n *\n * `BffAuthClient` (from `@dloizides/auth-client`) needs an `HttpClient`. Every\n * app wired it the same way — `createFetchHttpClient(fetch)` — and every app\n * hit the same trap: binding `fetch` at module load throws in a non-browser\n * runtime (the Jest/jsdom test environment has no `fetch` global). The lesson\n * of Phase 1 was \"copy-pasted auth adapters ship the same bug N times\", so the\n * correct wiring lives here once.\n *\n * `fetch` is resolved **lazily, per request** — module load stays\n * side-effect-free. `baseUrl` is omitted by default → same-origin: every\n * `/bff/*` call goes to the SPA's own host, which is fronted by the per-app\n * BFF (`bff-katalogos`, `bff-erevna`, ...).\n *\n * Extracted + generalised from `apps/katalogos-web/src/auth/bffAuthClient.ts`.\n */\nimport {\n BffAuthClient,\n createFetchHttpClient,\n type HttpClient,\n type HttpRequest,\n type HttpResponse,\n} from '@dloizides/auth-client';\n\nexport interface CreateBffAuthClientOptions {\n /**\n * BFF origin. Omit (the production default) for same-origin — the SPA's own\n * host is the BFF. An explicit origin is only useful for a non-same-origin\n * BFF or for tests.\n */\n baseUrl?: string;\n /**\n * Override the HTTP transport. Defaults to a lazily-resolved native `fetch`.\n * Tests pass a fake `HttpClient` here; production never needs to.\n */\n http?: HttpClient;\n}\n\n/**\n * Resolve the platform `fetch` lazily, per request.\n *\n * Resolving inside the request — never at module load — keeps importing this\n * module side-effect-free, so a test runtime without a `fetch` global does not\n * blow up the moment any file transitively imports `@dloizides/auth-web`.\n */\nasync function lazyFetchHttpClient(request: HttpRequest): Promise<HttpResponse> {\n const fetchImpl: typeof fetch | undefined =\n typeof fetch === 'function' ? fetch.bind(globalThis) : undefined;\n if (fetchImpl === undefined) {\n throw new Error('createBffAuthClient: fetch is not available in this environment');\n }\n return createFetchHttpClient(fetchImpl)(request);\n}\n\n/**\n * Build a same-origin `BffAuthClient`. With no arguments this is the exact\n * production wiring: same-origin, lazy `fetch`, no token handling.\n */\nexport function createBffAuthClient(options: CreateBffAuthClientOptions = {}): BffAuthClient {\n return new BffAuthClient({\n http: options.http ?? lazyFetchHttpClient,\n baseUrl: options.baseUrl,\n });\n}\n","/**\n * `resolvePostLoginRoute` — the role-based post-login router helper.\n *\n * The unified-auth plan's secondary goal is to kill the \"too many login links\"\n * problem (KUCY V2 has seven, one per role). One login surface; after a\n * successful login the app reads the user's role from the token claims and\n * routes to the right dashboard.\n *\n * This helper is intentionally pure and app-agnostic. The package does NOT\n * know any app's routes — the consuming app supplies a `RoleRouteTable`\n * mapping role → path. The helper picks the highest-priority matching role.\n *\n * Role priority: a user can hold several roles (`superUser` + `admin` + ...).\n * The table is consulted in the order its entries are listed — the FIRST\n * entry whose role the user holds wins. So an app lists the most privileged\n * role first. A `fallback` covers a user whose roles match no entry.\n */\nimport type { BffUser } from '@dloizides/auth-client';\n\n/** One role → route mapping. */\nexport interface RoleRoute {\n /** The Keycloak role name to match against the user's claims. */\n role: string;\n /** The route/path to send a user holding that role to. */\n route: string;\n}\n\n/** An app-supplied, ordered role-routing table. */\nexport interface RoleRouteTable {\n /**\n * Ordered list of role → route entries. Order is priority: the first entry\n * whose `role` the user holds is chosen. List the most privileged role first.\n */\n routes: RoleRoute[];\n /**\n * Route used when the user holds none of the listed roles. When omitted and\n * nothing matches, `resolvePostLoginRoute` returns `null` and the caller\n * decides what to do (e.g. show an \"no access\" screen).\n */\n fallback?: string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** Read a string array of roles from a `realm_access`-shaped value. */\nfunction readRealmAccessRoles(realmAccess: unknown): string[] {\n if (!isRecord(realmAccess)) {\n return [];\n }\n const roles = realmAccess.roles;\n if (!Array.isArray(roles)) {\n return [];\n }\n return roles.filter((role): role is string => typeof role === 'string');\n}\n\n/**\n * Collect every role on a `BffUser` — both the flat `roles` array and the\n * nested `realm_access.roles` — into a de-duplicated set. The BFF may surface\n * roles in either shape; this normalises both.\n */\nexport function collectUserRoles(user: BffUser): string[] {\n const flat = Array.isArray(user.roles)\n ? user.roles.filter((role): role is string => typeof role === 'string')\n : [];\n const realm = readRealmAccessRoles(user.realm_access);\n return Array.from(new Set([...flat, ...realm]));\n}\n\n/**\n * Resolve the post-login route for a user against an app-supplied table.\n *\n * Returns the route of the first table entry whose role the user holds; if no\n * entry matches, returns the table's `fallback`, or `null` when there is none.\n */\nexport function resolvePostLoginRoute(user: BffUser, table: RoleRouteTable): string | null {\n const userRoles = new Set(collectUserRoles(user));\n for (const entry of table.routes) {\n if (userRoles.has(entry.role)) {\n return entry.route;\n }\n }\n return table.fallback ?? null;\n}\n"]}