@dloizides/auth-web 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +706 -1
- package/dist/index.d.ts +706 -1
- package/dist/index.js +1152 -90
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1128 -92
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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/useForgotPasswordSubmit.ts","../src/components/ForgotPasswordFields.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","EMAIL_REGEX","ResetPasswordError","PasswordPolicyError","OtpLoginStep","toError","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/**\n * Strings rendered by `<ForgotPasswordFields>` — the embedded modal body. It is\n * the forgot-password form plus the two modal affordances (`cancel` alongside\n * submit, `close` on the success state) that a screen-shaped form has no need of.\n */\nexport interface ForgotPasswordFieldsLabels extends ForgotPasswordFormLabels {\n /** The \"cancel\" button shown alongside submit. */\n cancel: string;\n /** The \"close\" button shown on the success state. */\n close: 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_FORGOT_PASSWORD_FIELDS_LABELS: ForgotPasswordFieldsLabels = {\n ...DEFAULT_FORGOT_PASSWORD_LABELS,\n cancel: 'Cancel',\n close: 'Close',\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 forgotPasswordCancelButton: 'auth-forgot-cancel',\n forgotPasswordCloseButton: 'auth-forgot-close',\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 * `useForgotPasswordSubmit` — react-query-FREE form-state + submit logic for a\n * \"request a reset link\" surface.\n *\n * Why a second forgot-password hook when `useBffForgotPassword` already exists?\n * That one wraps `useMutation`, so it can only run under a `QueryClientProvider`.\n * The product login routes (katalogos / erevna / kefi) deliberately keep\n * react-query OUT of their bundle — there is no provider there, and mounting a\n * `useMutation` crashes with \"No QueryClient set\". Every app therefore\n * hand-rolled the same direct-`client.forgotPassword` call. This hook is that\n * shared logic, promoted into the package: a plain `useState` + promise chain,\n * safe on a provider-less route.\n *\n * Behaviour mirrors the apps' modal exactly:\n * - `canSubmit` is true only when the trimmed email looks valid and no request\n * is in flight (the submit button gates on this).\n * - `submit()` no-ops when the email is invalid or a request is already running.\n * - The backend is anti-enumeration (always 200 for the \"found an account?\"\n * branch), so the only failure that surfaces is a network / 5xx one, via\n * `hasNetworkError`.\n * - `reset()` clears everything — call it when the modal closes so reopening\n * shows a fresh form.\n */\nimport { useCallback, useState } from 'react';\n\nimport type { BffAuthClient, BffForgotPasswordRequest } from '@dloizides/auth-client';\n\n// A deliberately loose, linear-time email shape check — the `[^@\\s]` / `[^.\\s]`\n// character classes share no alternation, so there is no super-linear\n// backtracking. Strict validation is the backend's job.\nconst EMAIL_REGEX = /^[^@\\s]+@[^.\\s]+\\.[^\\s]+$/;\n\n/** `true` when `value` (after trimming) looks like an email address. */\nexport function isValidForgotPasswordEmail(value: string): boolean {\n return EMAIL_REGEX.test(value.trim());\n}\n\nexport interface UseForgotPasswordSubmitArgs {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /**\n * Full URL with a `{token}` placeholder, forwarded to the backend so it can\n * build the reset-email link without hardcoding a frontend host.\n */\n resetUrlTemplate?: string;\n /** Invoked once the request succeeds (the generic-confirmation state). */\n onSuccess?: () => void;\n}\n\nexport interface UseForgotPasswordSubmitResult {\n email: string;\n setEmail: (value: string) => void;\n /** `true` once the request has succeeded (show the generic confirmation). */\n submitted: boolean;\n /** `true` while the request is in flight. */\n isSubmitting: boolean;\n /** `true` when the last submit hit a network / 5xx failure. */\n hasNetworkError: boolean;\n /** `true` when the email is valid and no request is in flight. */\n canSubmit: boolean;\n /** Validate, then fire the request (no-op when `canSubmit` is false). */\n submit: () => void;\n /** Clear all state — call when the modal closes. */\n reset: () => void;\n}\n\n/** Headless, react-query-free \"request a reset link\" logic. */\nexport function useForgotPasswordSubmit({\n client,\n resetUrlTemplate,\n onSuccess,\n}: UseForgotPasswordSubmitArgs): UseForgotPasswordSubmitResult {\n const [email, setEmail] = useState('');\n const [submitted, setSubmitted] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [hasNetworkError, setHasNetworkError] = useState(false);\n\n const canSubmit = isValidForgotPasswordEmail(email) && !isSubmitting;\n\n const submit = useCallback((): void => {\n const target = email.trim();\n if (!isValidForgotPasswordEmail(target) || isSubmitting) {\n return;\n }\n setHasNetworkError(false);\n setIsSubmitting(true);\n const request: BffForgotPasswordRequest = { email: target, resetUrlTemplate };\n client\n .forgotPassword(request)\n .then(() => {\n setSubmitted(true);\n onSuccess?.();\n })\n .catch(() => setHasNetworkError(true))\n .finally(() => setIsSubmitting(false));\n }, [client, email, isSubmitting, resetUrlTemplate, onSuccess]);\n\n const reset = useCallback((): void => {\n setEmail('');\n setSubmitted(false);\n setIsSubmitting(false);\n setHasNetworkError(false);\n }, []);\n\n return {\n email,\n setEmail,\n submitted,\n isSubmitting,\n hasNetworkError,\n canSubmit,\n submit,\n reset,\n };\n}\n","/**\n * `<ForgotPasswordFields>` — the embedded, themeable \"request a reset link\"\n * body, sized to live INSIDE an app-owned modal shell (not a full screen).\n *\n * The product apps each show \"Forgot password?\" as a modal launched from their\n * login route, wrapping their own modal chrome (title bar + close affordance)\n * around an identical email field + submit/cancel body. This is that body,\n * promoted into the package so the three apps stop hand-rolling it.\n *\n * Built on the react-query-free `useForgotPasswordSubmit` hook, so it renders +\n * submits on a provider-less login route (where `useMutation` would crash). The\n * backend is anti-enumeration, so a successful request swaps to a generic\n * confirmation that never reveals whether the address is registered.\n *\n * Differs from the screen-shaped `<ForgotPasswordForm>`: no outer screen/card\n * wrapper and no title (the host modal owns those), plus two modal affordances —\n * a `Cancel` button beside submit and a `Close` button on the success state —\n * each rendered only when its handler is supplied.\n */\nimport { useEffect, useMemo, type ReactElement } from 'react';\n\nimport {\n ActivityIndicator,\n StyleSheet,\n Text,\n TextInput,\n TouchableOpacity,\n View,\n type TextStyle,\n type ViewStyle,\n} from 'react-native';\n\nimport {\n DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS,\n type ForgotPasswordFieldsLabels,\n} from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { useForgotPasswordSubmit } from '../hooks/useForgotPasswordSubmit';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\nimport type { BffAuthClient } from '@dloizides/auth-client';\n\nconst SECONDARY_BORDER_WIDTH = 1;\n\nexport interface ForgotPasswordFieldsProps {\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<ForgotPasswordFieldsLabels>;\n /**\n * Full URL with a `{token}` placeholder, forwarded to the backend so it can\n * build the reset-email link without hardcoding a frontend host.\n */\n resetUrlTemplate?: string;\n /**\n * The host modal's open state. When it flips to `false` the body clears\n * itself, so reopening shows a fresh form regardless of which affordance\n * closed it. Defaults to `true` for non-modal embedding.\n */\n visible?: boolean;\n /** Called once the request succeeds (the generic-confirmation state). */\n onSuccess?: () => void;\n /** When supplied, renders a Cancel button beside submit. */\n onCancel?: () => void;\n /** When supplied, renders a Close button on the success state. */\n onClose?: () => void;\n /** Prefix applied to every `testID`. */\n testIdPrefix?: string;\n}\n\n/** The modal-specific styles `useAuthStyles` does not carry. */\ninterface ModalStyles {\n body: ViewStyle;\n actions: ViewStyle;\n secondaryButton: ViewStyle;\n secondaryButtonText: TextStyle;\n}\n\n/** Build the modal-only styles from the resolved theme. */\nfunction useModalStyles(theme: AuthTheme): ModalStyles {\n return useMemo(\n () =>\n StyleSheet.create<ModalStyles>({\n body: { padding: theme.spacing.md },\n actions: {\n flexDirection: 'row',\n justifyContent: 'flex-end',\n alignItems: 'center',\n marginTop: theme.spacing.md,\n gap: theme.spacing.sm,\n },\n secondaryButton: {\n borderRadius: theme.radii.input,\n paddingVertical: theme.spacing.sm,\n paddingHorizontal: theme.spacing.md,\n borderWidth: SECONDARY_BORDER_WIDTH,\n borderColor: theme.colors.border,\n },\n secondaryButtonText: {\n fontSize: theme.typography.body,\n fontWeight: '600',\n color: theme.colors.text,\n },\n }),\n [theme],\n );\n}\n\n/** Embedded \"request a reset link\" body for an app-owned modal. */\nexport function ForgotPasswordFields({\n client,\n theme: themeProp,\n labels: labelsProp,\n resetUrlTemplate,\n visible = true,\n onSuccess,\n onCancel,\n onClose,\n testIdPrefix,\n}: Readonly<ForgotPasswordFieldsProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const modalStyles = useModalStyles(theme);\n const labels = useMemo<ForgotPasswordFieldsLabels>(\n () => ({ ...DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n const form = useForgotPasswordSubmit({ client, resetUrlTemplate, onSuccess });\n\n // Clear the body when the host modal closes, so reopening starts fresh.\n const { reset } = form;\n useEffect(() => {\n if (!visible) {\n reset();\n }\n }, [visible, reset]);\n\n const submitButtonStyle = form.canSubmit\n ? styles.primaryButton\n : [styles.primaryButton, styles.primaryButtonDisabled];\n\n const handleCancel = (): void => {\n form.reset();\n onCancel?.();\n };\n\n const handleClose = (): void => {\n form.reset();\n onClose?.();\n };\n\n if (form.submitted) {\n return (\n <View style={modalStyles.body} testID={withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix)}>\n <Text style={styles.successText} testID={withTestIdPrefix(AuthTestIds.forgotPasswordSuccess, testIdPrefix)}>\n {labels.successMessage}\n </Text>\n {onClose !== undefined ? (\n <View style={modalStyles.actions}>\n <TouchableOpacity\n accessibilityHint={labels.close}\n accessibilityLabel={labels.close}\n accessibilityRole=\"button\"\n style={styles.primaryButton}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordCloseButton, testIdPrefix)}\n onPress={handleClose}\n >\n <Text style={styles.primaryButtonText}>{labels.close}</Text>\n </TouchableOpacity>\n </View>\n ) : null}\n </View>\n );\n }\n\n return (\n <View style={modalStyles.body} testID={withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix)}>\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={!form.isSubmitting}\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={form.email}\n onChangeText={form.setEmail}\n />\n </View>\n\n {form.hasNetworkError ? (\n <Text style={styles.errorText} testID={withTestIdPrefix(AuthTestIds.forgotPasswordError, testIdPrefix)}>\n {labels.networkError}\n </Text>\n ) : null}\n\n <View style={modalStyles.actions}>\n {onCancel !== undefined ? (\n <TouchableOpacity\n accessibilityHint={labels.cancel}\n accessibilityLabel={labels.cancel}\n accessibilityRole=\"button\"\n disabled={form.isSubmitting}\n style={modalStyles.secondaryButton}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordCancelButton, testIdPrefix)}\n onPress={handleCancel}\n >\n <Text style={modalStyles.secondaryButtonText}>{labels.cancel}</Text>\n </TouchableOpacity>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.submit}\n accessibilityLabel={form.isSubmitting ? labels.submitting : labels.submit}\n accessibilityRole=\"button\"\n disabled={!form.canSubmit}\n style={submitButtonStyle}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordSubmitButton, 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 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/useForgotPasswordSubmit.ts","../src/components/ForgotPasswordFields.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/components/DevicePinInput.tsx","../src/components/interpolate.ts","../src/devicePin/devicePinConstants.ts","../src/components/DevicePinLengthPicker.tsx","../src/devicePin/DevicePinErrorKey.ts","../src/devicePin/useDevicePinUnlock.ts","../src/components/DevicePinUnlockScreen.tsx","../src/devicePin/DevicePinEnrollErrorKey.ts","../src/devicePin/useDevicePinEnroll.ts","../src/components/DevicePinEnrollForm.tsx","../src/components/DevicePinOffer.tsx","../src/devicePin/useDevicePinDisable.ts","../src/components/DevicePinSettingsCard.tsx","../src/passkey/passkeyNavigation.ts","../src/components/PasskeyLoginButton.tsx","../src/components/PasskeySettingsCard.tsx","../src/devicePin/useBffLoginConfig.ts","../src/client/createBffAuthClient.ts","../src/router/resolvePostLoginRoute.ts"],"names":["useMemo","StyleSheet","BffAuthStatus","useState","useRef","useEffect","useCallback","createContext","useContext","styles","jsx","View","jsxs","Text","TextInput","TouchableOpacity","ActivityIndicator","useMutation","Fragment","EMAIL_REGEX","ResetPasswordError","PasswordPolicyError","OtpLoginStep","toError","isValidEmail","transportErrorFor","Pressable","DevicePinErrorKey","DevicePinEnrollErrorKey","resolveErrorText","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/**\n * Strings rendered by `<ForgotPasswordFields>` — the embedded modal body. It is\n * the forgot-password form plus the two modal affordances (`cancel` alongside\n * submit, `close` on the success state) that a screen-shaped form has no need of.\n */\nexport interface ForgotPasswordFieldsLabels extends ForgotPasswordFormLabels {\n /** The \"cancel\" button shown alongside submit. */\n cancel: string;\n /** The \"close\" button shown on the success state. */\n close: 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/**\n * Strings rendered by `<DevicePinUnlockScreen>` — the returning-device unlock\n * gate. `{name}` / `{count}` placeholders are substituted by the component.\n */\nexport interface DevicePinUnlockLabels {\n /** Greeting with the remembered username; `{name}` is substituted. */\n title: string;\n /** Greeting when no username is remembered. */\n titleNoName: string;\n /** Copy above the PIN pad; `{count}` is substituted with the PIN length. */\n description: string;\n pinLabel: string;\n pinPlaceholder: string;\n /** The \"unlock\" submit button. */\n submit: string;\n /** Shown while the unlock is in flight. */\n submitting: string;\n /** The \"sign in with password instead\" escape link. */\n usePasswordInstead: string;\n /** Accessibility hint for the escape link. */\n usePasswordHint: string;\n /** Error: not enough digits entered; `{count}` is substituted. */\n errorIncomplete: string;\n /** Error: wrong PIN / unknown device (generic). */\n errorInvalid: string;\n /** Error: locked out, no retry hint. */\n errorLockedOut: string;\n /** Error: locked out with a retry hint; `{count}` is the seconds. */\n errorLockedOutRetry: string;\n /** Error: rate-limited, no retry hint. */\n errorRateLimited: string;\n /** Error: rate-limited with a retry hint; `{count}` is the seconds. */\n errorRateLimitedRetry: string;\n /** Error: anything else (network / unexpected). */\n errorGeneric: string;\n /** Accessibility label for a filled PIN dot. */\n digitFilledHint: string;\n /** Accessibility label for an empty PIN dot. */\n digitEmptyHint: string;\n}\n\n/**\n * Strings rendered by `<DevicePinEnrollForm>` (and the length picker it hosts)\n * plus the `<DevicePinOffer>` wrapper. `{count}` placeholders are substituted.\n */\nexport interface DevicePinEnrollLabels {\n // ── Offer (post-login skippable card) ─────────────────────────────────────\n offerTitle: string;\n offerDescription: string;\n offerAccept: string;\n offerAcceptHint: string;\n offerSkip: string;\n offerSkipHint: string;\n\n // ── Enrol form ────────────────────────────────────────────────────────────\n formTitle: string;\n /** Copy above the form; `{count}` is substituted with the chosen length. */\n formDescription: string;\n lengthLabel: string;\n /** Accessibility hint for a length pill; `{count}` is substituted. */\n lengthOptionHint: string;\n pinLabel: string;\n pinPlaceholder: string;\n confirmLabel: string;\n confirmPlaceholder: string;\n submit: string;\n submitting: string;\n cancel: string;\n cancelHint: string;\n /** Error: PINs do not match / wrong length; `{count}` is substituted. */\n errorMismatch: string;\n /** Error: the current session is not authenticated. */\n errorUnauthorized: string;\n /** Error: the session already has a PIN / is forbidden. */\n errorForbidden: string;\n /** Error: the PIN failed server-side validation. */\n errorInvalidPin: string;\n /** Error: any other failure. */\n errorFailed: string;\n}\n\n/** Strings rendered by `<DevicePinSettingsCard>` — the account toggle. */\nexport interface DevicePinSettingsLabels {\n title: string;\n description: string;\n /** Status line when a device PIN is enabled. */\n statusEnabled: string;\n /** Status line when no device PIN is set. */\n statusDisabled: string;\n /** The \"enable\" button. */\n enable: string;\n enableHint: string;\n /** The \"disable\" button. */\n disable: string;\n disableHint: string;\n /** Shown while disabling is in flight. */\n disabling: string;\n /** Error shown when disabling fails. */\n disableFailed: string;\n}\n\n/** Strings rendered by `<PasskeyLoginButton>` — the login-surface passkey CTA. */\nexport interface PasskeyLoginLabels {\n /** The \"sign in with a passkey\" button. */\n signInButton: string;\n signInHint: string;\n /** Error banner when the ceremony was cancelled. */\n errorCancelled: string;\n /** Error banner when the ceremony failed. */\n errorFailed: string;\n}\n\n/** Strings rendered by `<PasskeySettingsCard>` — the account passkey card. */\nexport interface PasskeySettingsLabels {\n title: string;\n description: string;\n /** Italic hint about the re-auth step. */\n reauthHint: string;\n /** The \"add a passkey\" button. */\n addButton: string;\n addHint: string;\n /** Success line shown after returning from a registration. */\n registeredSuccess: 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_FORGOT_PASSWORD_FIELDS_LABELS: ForgotPasswordFieldsLabels = {\n ...DEFAULT_FORGOT_PASSWORD_LABELS,\n cancel: 'Cancel',\n close: 'Close',\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_DEVICE_PIN_UNLOCK_LABELS: DevicePinUnlockLabels = {\n title: 'Welcome back, {name}',\n titleNoName: 'Welcome back',\n description: 'Enter your {count}-digit PIN to sign in on this device.',\n pinLabel: 'PIN',\n pinPlaceholder: 'Enter your PIN',\n submit: 'Unlock',\n submitting: 'Signing in...',\n usePasswordInstead: 'Sign in with password instead',\n usePasswordHint: 'Switch to signing in with your username and password',\n errorIncomplete: 'Enter all {count} digits of your PIN.',\n errorInvalid: 'That PIN is incorrect. Try again.',\n errorLockedOut: 'Too many attempts. Try again later.',\n errorLockedOutRetry: 'Too many attempts. Try again in {count} seconds.',\n errorRateLimited: 'Too many requests. Try again later.',\n errorRateLimitedRetry: 'Too many requests. Try again in {count} seconds.',\n errorGeneric: 'Something went wrong. Try again, or sign in with your password.',\n digitFilledHint: 'PIN digit entered',\n digitEmptyHint: 'PIN digit not yet entered',\n};\n\nexport const DEFAULT_DEVICE_PIN_ENROLL_LABELS: DevicePinEnrollLabels = {\n offerTitle: 'Set a PIN for faster sign-in?',\n offerDescription:\n 'Next time, sign in on this device with a short PIN instead of your full password.',\n offerAccept: 'Set up a PIN',\n offerAcceptHint: 'Open the form to choose a quick sign-in PIN',\n offerSkip: 'Not now',\n offerSkipHint: 'Dismiss the PIN setup offer',\n formTitle: 'Choose your PIN',\n formDescription:\n 'Pick a {count}-digit PIN you will remember. You will use it to sign in on this device.',\n lengthLabel: 'PIN length',\n lengthOptionHint: 'Use a {count}-digit PIN',\n pinLabel: 'New PIN',\n pinPlaceholder: 'Enter a new PIN',\n confirmLabel: 'Confirm PIN',\n confirmPlaceholder: 'Re-enter your PIN',\n submit: 'Save PIN',\n submitting: 'Saving...',\n cancel: 'Cancel',\n cancelHint: 'Close the PIN setup form without saving',\n errorMismatch: 'The PINs must match and be exactly {count} digits.',\n errorUnauthorized: 'Your session has expired. Sign in again to set a PIN.',\n errorForbidden: 'A PIN is already set for this session.',\n errorInvalidPin: 'That PIN is not allowed. Choose a different one.',\n errorFailed: 'Could not set your PIN. Try again later.',\n};\n\nexport const DEFAULT_DEVICE_PIN_SETTINGS_LABELS: DevicePinSettingsLabels = {\n title: 'Quick PIN sign-in',\n description: 'Sign in on this device with a short PIN instead of your full password.',\n statusEnabled: 'Quick PIN sign-in is enabled on this device.',\n statusDisabled: 'Quick PIN sign-in is off.',\n enable: 'Enable quick PIN sign-in',\n enableHint: 'Set a PIN so you can sign in faster on this device',\n disable: 'Disable',\n disableHint: 'Remove the PIN sign-in from this device',\n disabling: 'Disabling...',\n disableFailed: 'Could not disable PIN sign-in. Try again later.',\n};\n\nexport const DEFAULT_PASSKEY_LOGIN_LABELS: PasskeyLoginLabels = {\n signInButton: 'Sign in with a passkey',\n signInHint: 'Use your fingerprint, face, or security key to sign in',\n errorCancelled:\n 'Passkey sign-in was cancelled. You can try again or sign in another way.',\n errorFailed: \"Passkey sign-in didn't work. Try again, or sign in another way.\",\n};\n\nexport const DEFAULT_PASSKEY_SETTINGS_LABELS: PasskeySettingsLabels = {\n title: 'Passkeys',\n description:\n 'Add a passkey to sign in with your fingerprint, face, or a security key instead of a password.',\n reauthHint: \"You'll be asked to confirm your password before adding a passkey.\",\n addButton: 'Add a passkey',\n addHint: 'Start setting up a passkey for this account',\n registeredSuccess: 'Your passkey was added. You can now use it to sign in.',\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 forgotPasswordCancelButton: 'auth-forgot-cancel',\n forgotPasswordCloseButton: 'auth-forgot-close',\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\n // Device-PIN unlock gate\n devicePinUnlock: 'auth-device-pin-unlock',\n devicePinUnlockInput: 'auth-device-pin-unlock-input',\n devicePinUnlockSubmit: 'auth-device-pin-unlock-submit',\n devicePinUnlockUsePassword: 'auth-device-pin-unlock-use-password',\n devicePinUnlockError: 'auth-device-pin-unlock-error',\n\n // Device-PIN enrol form + length picker\n devicePinEnrollForm: 'auth-device-pin-enroll-form',\n devicePinEnrollLength: 'auth-device-pin-enroll-length',\n devicePinEnrollPin: 'auth-device-pin-enroll-pin',\n devicePinEnrollConfirm: 'auth-device-pin-enroll-confirm',\n devicePinEnrollSubmit: 'auth-device-pin-enroll-submit',\n devicePinEnrollCancel: 'auth-device-pin-enroll-cancel',\n devicePinEnrollError: 'auth-device-pin-enroll-error',\n\n // Device-PIN offer (post-login)\n devicePinOffer: 'auth-device-pin-offer',\n devicePinOfferAccept: 'auth-device-pin-offer-accept',\n devicePinOfferSkip: 'auth-device-pin-offer-skip',\n\n // Device-PIN settings card\n devicePinSettings: 'auth-device-pin-settings',\n devicePinSettingsStatus: 'auth-device-pin-settings-status',\n devicePinSettingsEnable: 'auth-device-pin-settings-enable',\n devicePinSettingsDisable: 'auth-device-pin-settings-disable',\n devicePinSettingsError: 'auth-device-pin-settings-error',\n\n // Passkey login button\n passkeyLogin: 'auth-passkey-login',\n passkeyLoginButton: 'auth-passkey-login-button',\n passkeyLoginError: 'auth-passkey-login-error',\n\n // Passkey settings card\n passkeySettings: 'auth-passkey-settings',\n passkeySettingsAdd: 'auth-passkey-settings-add',\n passkeySettingsSuccess: 'auth-passkey-settings-success',\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 /** Centered, tappable secondary link row (e.g. \"use password instead\"). */\n escapeLink: ViewStyle;\n /** Outlined secondary button (e.g. disable / cancel actions). */\n secondaryButton: ViewStyle;\n /** Label drawn inside `secondaryButton`. */\n secondaryButtonText: TextStyle;\n /** Status line (e.g. the device-PIN settings enabled/disabled state). */\n statusText: 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 escapeLink: {\n alignSelf: 'center',\n marginTop: spacing.md,\n paddingVertical: spacing.xs / 2,\n },\n secondaryButton: {\n borderRadius: radii.input,\n borderWidth: 1,\n borderColor: colors.primary,\n paddingVertical: BUTTON_VERTICAL_PADDING,\n alignItems: 'center',\n justifyContent: 'center',\n marginTop: spacing.sm,\n backgroundColor: colors.surface,\n },\n secondaryButtonText: {\n fontSize: typography.body,\n fontWeight: '600',\n color: colors.primary,\n },\n statusText: {\n fontSize: typography.label,\n fontWeight: '600',\n marginTop: spacing.sm,\n color: colors.text,\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 * `useForgotPasswordSubmit` — react-query-FREE form-state + submit logic for a\n * \"request a reset link\" surface.\n *\n * Why a second forgot-password hook when `useBffForgotPassword` already exists?\n * That one wraps `useMutation`, so it can only run under a `QueryClientProvider`.\n * The product login routes (katalogos / erevna / kefi) deliberately keep\n * react-query OUT of their bundle — there is no provider there, and mounting a\n * `useMutation` crashes with \"No QueryClient set\". Every app therefore\n * hand-rolled the same direct-`client.forgotPassword` call. This hook is that\n * shared logic, promoted into the package: a plain `useState` + promise chain,\n * safe on a provider-less route.\n *\n * Behaviour mirrors the apps' modal exactly:\n * - `canSubmit` is true only when the trimmed email looks valid and no request\n * is in flight (the submit button gates on this).\n * - `submit()` no-ops when the email is invalid or a request is already running.\n * - The backend is anti-enumeration (always 200 for the \"found an account?\"\n * branch), so the only failure that surfaces is a network / 5xx one, via\n * `hasNetworkError`.\n * - `reset()` clears everything — call it when the modal closes so reopening\n * shows a fresh form.\n */\nimport { useCallback, useState } from 'react';\n\nimport type { BffAuthClient, BffForgotPasswordRequest } from '@dloizides/auth-client';\n\n// A deliberately loose, linear-time email shape check — the `[^@\\s]` / `[^.\\s]`\n// character classes share no alternation, so there is no super-linear\n// backtracking. Strict validation is the backend's job.\nconst EMAIL_REGEX = /^[^@\\s]+@[^.\\s]+\\.[^\\s]+$/;\n\n/** `true` when `value` (after trimming) looks like an email address. */\nexport function isValidForgotPasswordEmail(value: string): boolean {\n return EMAIL_REGEX.test(value.trim());\n}\n\nexport interface UseForgotPasswordSubmitArgs {\n /** The same-origin BFF client (build it with `createBffAuthClient`). */\n client: BffAuthClient;\n /**\n * Full URL with a `{token}` placeholder, forwarded to the backend so it can\n * build the reset-email link without hardcoding a frontend host.\n */\n resetUrlTemplate?: string;\n /** Invoked once the request succeeds (the generic-confirmation state). */\n onSuccess?: () => void;\n}\n\nexport interface UseForgotPasswordSubmitResult {\n email: string;\n setEmail: (value: string) => void;\n /** `true` once the request has succeeded (show the generic confirmation). */\n submitted: boolean;\n /** `true` while the request is in flight. */\n isSubmitting: boolean;\n /** `true` when the last submit hit a network / 5xx failure. */\n hasNetworkError: boolean;\n /** `true` when the email is valid and no request is in flight. */\n canSubmit: boolean;\n /** Validate, then fire the request (no-op when `canSubmit` is false). */\n submit: () => void;\n /** Clear all state — call when the modal closes. */\n reset: () => void;\n}\n\n/** Headless, react-query-free \"request a reset link\" logic. */\nexport function useForgotPasswordSubmit({\n client,\n resetUrlTemplate,\n onSuccess,\n}: UseForgotPasswordSubmitArgs): UseForgotPasswordSubmitResult {\n const [email, setEmail] = useState('');\n const [submitted, setSubmitted] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [hasNetworkError, setHasNetworkError] = useState(false);\n\n const canSubmit = isValidForgotPasswordEmail(email) && !isSubmitting;\n\n const submit = useCallback((): void => {\n const target = email.trim();\n if (!isValidForgotPasswordEmail(target) || isSubmitting) {\n return;\n }\n setHasNetworkError(false);\n setIsSubmitting(true);\n const request: BffForgotPasswordRequest = { email: target, resetUrlTemplate };\n client\n .forgotPassword(request)\n .then(() => {\n setSubmitted(true);\n onSuccess?.();\n })\n .catch(() => setHasNetworkError(true))\n .finally(() => setIsSubmitting(false));\n }, [client, email, isSubmitting, resetUrlTemplate, onSuccess]);\n\n const reset = useCallback((): void => {\n setEmail('');\n setSubmitted(false);\n setIsSubmitting(false);\n setHasNetworkError(false);\n }, []);\n\n return {\n email,\n setEmail,\n submitted,\n isSubmitting,\n hasNetworkError,\n canSubmit,\n submit,\n reset,\n };\n}\n","/**\n * `<ForgotPasswordFields>` — the embedded, themeable \"request a reset link\"\n * body, sized to live INSIDE an app-owned modal shell (not a full screen).\n *\n * The product apps each show \"Forgot password?\" as a modal launched from their\n * login route, wrapping their own modal chrome (title bar + close affordance)\n * around an identical email field + submit/cancel body. This is that body,\n * promoted into the package so the three apps stop hand-rolling it.\n *\n * Built on the react-query-free `useForgotPasswordSubmit` hook, so it renders +\n * submits on a provider-less login route (where `useMutation` would crash). The\n * backend is anti-enumeration, so a successful request swaps to a generic\n * confirmation that never reveals whether the address is registered.\n *\n * Differs from the screen-shaped `<ForgotPasswordForm>`: no outer screen/card\n * wrapper and no title (the host modal owns those), plus two modal affordances —\n * a `Cancel` button beside submit and a `Close` button on the success state —\n * each rendered only when its handler is supplied.\n */\nimport { useEffect, useMemo, type ReactElement } from 'react';\n\nimport {\n ActivityIndicator,\n StyleSheet,\n Text,\n TextInput,\n TouchableOpacity,\n View,\n type TextStyle,\n type ViewStyle,\n} from 'react-native';\n\nimport {\n DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS,\n type ForgotPasswordFieldsLabels,\n} from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { useForgotPasswordSubmit } from '../hooks/useForgotPasswordSubmit';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\nimport type { BffAuthClient } from '@dloizides/auth-client';\n\nconst SECONDARY_BORDER_WIDTH = 1;\n\nexport interface ForgotPasswordFieldsProps {\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<ForgotPasswordFieldsLabels>;\n /**\n * Full URL with a `{token}` placeholder, forwarded to the backend so it can\n * build the reset-email link without hardcoding a frontend host.\n */\n resetUrlTemplate?: string;\n /**\n * The host modal's open state. When it flips to `false` the body clears\n * itself, so reopening shows a fresh form regardless of which affordance\n * closed it. Defaults to `true` for non-modal embedding.\n */\n visible?: boolean;\n /** Called once the request succeeds (the generic-confirmation state). */\n onSuccess?: () => void;\n /** When supplied, renders a Cancel button beside submit. */\n onCancel?: () => void;\n /** When supplied, renders a Close button on the success state. */\n onClose?: () => void;\n /** Prefix applied to every `testID`. */\n testIdPrefix?: string;\n}\n\n/** The modal-specific styles `useAuthStyles` does not carry. */\ninterface ModalStyles {\n body: ViewStyle;\n actions: ViewStyle;\n secondaryButton: ViewStyle;\n secondaryButtonText: TextStyle;\n}\n\n/** Build the modal-only styles from the resolved theme. */\nfunction useModalStyles(theme: AuthTheme): ModalStyles {\n return useMemo(\n () =>\n StyleSheet.create<ModalStyles>({\n body: { padding: theme.spacing.md },\n actions: {\n flexDirection: 'row',\n justifyContent: 'flex-end',\n alignItems: 'center',\n marginTop: theme.spacing.md,\n gap: theme.spacing.sm,\n },\n secondaryButton: {\n borderRadius: theme.radii.input,\n paddingVertical: theme.spacing.sm,\n paddingHorizontal: theme.spacing.md,\n borderWidth: SECONDARY_BORDER_WIDTH,\n borderColor: theme.colors.border,\n },\n secondaryButtonText: {\n fontSize: theme.typography.body,\n fontWeight: '600',\n color: theme.colors.text,\n },\n }),\n [theme],\n );\n}\n\n/** Embedded \"request a reset link\" body for an app-owned modal. */\nexport function ForgotPasswordFields({\n client,\n theme: themeProp,\n labels: labelsProp,\n resetUrlTemplate,\n visible = true,\n onSuccess,\n onCancel,\n onClose,\n testIdPrefix,\n}: Readonly<ForgotPasswordFieldsProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const modalStyles = useModalStyles(theme);\n const labels = useMemo<ForgotPasswordFieldsLabels>(\n () => ({ ...DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n const form = useForgotPasswordSubmit({ client, resetUrlTemplate, onSuccess });\n\n // Clear the body when the host modal closes, so reopening starts fresh.\n const { reset } = form;\n useEffect(() => {\n if (!visible) {\n reset();\n }\n }, [visible, reset]);\n\n const submitButtonStyle = form.canSubmit\n ? styles.primaryButton\n : [styles.primaryButton, styles.primaryButtonDisabled];\n\n const handleCancel = (): void => {\n form.reset();\n onCancel?.();\n };\n\n const handleClose = (): void => {\n form.reset();\n onClose?.();\n };\n\n if (form.submitted) {\n return (\n <View style={modalStyles.body} testID={withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix)}>\n <Text style={styles.successText} testID={withTestIdPrefix(AuthTestIds.forgotPasswordSuccess, testIdPrefix)}>\n {labels.successMessage}\n </Text>\n {onClose !== undefined ? (\n <View style={modalStyles.actions}>\n <TouchableOpacity\n accessibilityHint={labels.close}\n accessibilityLabel={labels.close}\n accessibilityRole=\"button\"\n style={styles.primaryButton}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordCloseButton, testIdPrefix)}\n onPress={handleClose}\n >\n <Text style={styles.primaryButtonText}>{labels.close}</Text>\n </TouchableOpacity>\n </View>\n ) : null}\n </View>\n );\n }\n\n return (\n <View style={modalStyles.body} testID={withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix)}>\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={!form.isSubmitting}\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={form.email}\n onChangeText={form.setEmail}\n />\n </View>\n\n {form.hasNetworkError ? (\n <Text style={styles.errorText} testID={withTestIdPrefix(AuthTestIds.forgotPasswordError, testIdPrefix)}>\n {labels.networkError}\n </Text>\n ) : null}\n\n <View style={modalStyles.actions}>\n {onCancel !== undefined ? (\n <TouchableOpacity\n accessibilityHint={labels.cancel}\n accessibilityLabel={labels.cancel}\n accessibilityRole=\"button\"\n disabled={form.isSubmitting}\n style={modalStyles.secondaryButton}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordCancelButton, testIdPrefix)}\n onPress={handleCancel}\n >\n <Text style={modalStyles.secondaryButtonText}>{labels.cancel}</Text>\n </TouchableOpacity>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.submit}\n accessibilityLabel={form.isSubmitting ? labels.submitting : labels.submit}\n accessibilityRole=\"button\"\n disabled={!form.canSubmit}\n style={submitButtonStyle}\n testID={withTestIdPrefix(AuthTestIds.forgotPasswordSubmitButton, 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 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 * A masked numeric PIN input for the device-PIN unlock + enrol surfaces.\n *\n * A single hidden secure `TextInput` captures the digits (numeric keyboard,\n * length-capped, digits-only); a row of dot cells visualises how many have been\n * entered. Tapping anywhere on the row focuses the field. Purely presentational\n * — all submit / error logic lives in the unlock / enrol hooks. Styled from the\n * `AuthTheme` token bag (no hardcoded brand colours).\n */\nimport { useMemo, useRef, type ReactElement } from 'react';\n\nimport {\n Pressable,\n StyleSheet,\n TextInput,\n View,\n type TextInput as RNTextInput,\n type ViewStyle,\n} from 'react-native';\n\nimport { withTestIdPrefix } from './testIds';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\n\nexport interface DevicePinInputProps {\n /** The current PIN value (digits only). */\n value: string;\n /** Number of dot cells to render — the enrolled / chosen PIN length. */\n length: number;\n /** Disable input while a request is in flight. */\n disabled: boolean;\n /** Base testID for the underlying field (a11y + E2E targeting). */\n testID: string;\n /** Optional prefix applied to the testID. */\n testIdPrefix?: string;\n /** Accessibility label for the field. */\n accessibilityLabel: string;\n /** Accessibility hint for the field. */\n accessibilityHint: string;\n /** Accessibility label for a filled dot. */\n filledHint: string;\n /** Accessibility label for an empty dot. */\n emptyHint: string;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. */\n theme?: AuthTheme;\n /** Emit the next digits-only value (already length-capped). */\n onChange: (next: string) => void;\n}\n\nconst DOT_SIZE = 18;\nconst DOT_BORDER_WIDTH = 2;\nconst DOT_RADIUS = 9;\nconst ROW_GAP = 12;\nconst ROW_MIN_HEIGHT = 44;\nconst ROW_VERTICAL_MARGIN = 16;\nconst HIDDEN_SIZE = 1;\n\n/** Strip everything but digits and cap to `length`. */\nfunction sanitise(raw: string, length: number): string {\n return raw.replace(/\\D/g, '').slice(0, length);\n}\n\n/** Build the dot fill/border styles from the theme. */\nfunction useDotStyles(theme: AuthTheme): { filled: ViewStyle; empty: ViewStyle } {\n return useMemo(\n () => ({\n filled: { backgroundColor: theme.colors.primary, borderColor: theme.colors.primary },\n empty: { backgroundColor: theme.colors.background, borderColor: theme.colors.border },\n }),\n [theme],\n );\n}\n\n/** Themeable masked PIN pad — dots reflect entered digits; a hidden field captures them. */\nexport function DevicePinInput({\n value,\n length,\n disabled,\n testID,\n testIdPrefix,\n accessibilityLabel,\n accessibilityHint,\n filledHint,\n emptyHint,\n theme: themeProp,\n onChange,\n}: Readonly<DevicePinInputProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const inputRef = useRef<RNTextInput | null>(null);\n const dotStyles = useDotStyles(theme);\n const cells = Array.from({ length }, (_unused, index) => index);\n const baseId = withTestIdPrefix(testID, testIdPrefix);\n\n return (\n <Pressable\n accessibilityHint={accessibilityHint}\n accessibilityLabel={accessibilityLabel}\n accessibilityRole=\"button\"\n disabled={disabled}\n style={styles.row}\n testID={`${baseId}-row`}\n onPress={(): void => inputRef.current?.focus()}\n >\n {cells.map((index) => {\n const filled = index < value.length;\n return (\n <View\n key={index}\n accessibilityLabel={filled ? filledHint : emptyHint}\n style={[styles.dot, filled ? dotStyles.filled : dotStyles.empty]}\n testID={`${baseId}-dot-${String(index)}`}\n />\n );\n })}\n <TextInput\n ref={inputRef}\n accessibilityHint={accessibilityHint}\n accessibilityLabel={accessibilityLabel}\n autoFocus\n caretHidden\n editable={!disabled}\n keyboardType=\"number-pad\"\n maxLength={length}\n secureTextEntry\n style={styles.hiddenInput}\n testID={baseId}\n value={value}\n onChangeText={(raw: string): void => onChange(sanitise(raw, length))}\n />\n </Pressable>\n );\n}\n\nconst styles = StyleSheet.create({\n dot: {\n borderRadius: DOT_RADIUS,\n borderWidth: DOT_BORDER_WIDTH,\n height: DOT_SIZE,\n width: DOT_SIZE,\n },\n hiddenInput: {\n height: HIDDEN_SIZE,\n opacity: 0,\n position: 'absolute',\n width: HIDDEN_SIZE,\n },\n row: {\n alignItems: 'center',\n flexDirection: 'row',\n gap: ROW_GAP,\n justifyContent: 'center',\n marginVertical: ROW_VERTICAL_MARGIN,\n minHeight: ROW_MIN_HEIGHT,\n },\n});\n","/**\n * Minimal label placeholder interpolation.\n *\n * The device-PIN / passkey label bags carry `{name}` and `{count}` placeholders\n * (e.g. `'Enter your {count}-digit PIN.'`). The package ships no i18n framework,\n * so this tiny helper substitutes named placeholders without pulling one in.\n * Unknown placeholders are left untouched; absent keys substitute nothing.\n */\n\n/** Replace every `{key}` in `template` with the matching value (String-coerced). */\nexport function interpolate(\n template: string,\n values: Readonly<Record<string, string | number>>,\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key: string) => {\n const value = values[key];\n return value === undefined ? match : String(value);\n });\n}\n","/**\n * Shared device-PIN constants for the unlock + enrol surfaces.\n *\n * The allowed PIN lengths (4 / 6 / 8) mirror the BFF's accepted `digits` values\n * (`POST /bff/pin/enroll`). Centralised here so neither the enrol form nor the\n * unlock screen carries magic numbers, and so the default length is defined once.\n */\n\n/** The PIN lengths the BFF accepts on enrol (`digits` ∈ {4, 6, 8}). */\nexport const DEVICE_PIN_ALLOWED_DIGITS: readonly number[] = [4, 6, 8];\n\n/** Default PIN length offered when the BFF reports no stored `pinDigits`. */\nexport const DEVICE_PIN_DEFAULT_DIGITS = 4;\n\n/** Guard: is `value` one of the BFF-accepted PIN lengths? */\nexport function isAllowedPinDigits(value: number): boolean {\n return DEVICE_PIN_ALLOWED_DIGITS.includes(value);\n}\n","/**\n * The PIN-length (4/6/8) picker row for `<DevicePinEnrollForm>`.\n *\n * Presentational: renders one pill per allowed length and reports the chosen\n * one. Styled from the `AuthTheme` token bag. Extracted from the enrol form to\n * keep that component focused.\n */\nimport { useMemo, type ReactElement } from 'react';\n\nimport {\n Pressable,\n StyleSheet,\n Text,\n View,\n type TextStyle,\n type ViewStyle,\n} from 'react-native';\n\nimport { interpolate } from './interpolate';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { DEVICE_PIN_ALLOWED_DIGITS } from '../devicePin/devicePinConstants';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\n\nexport interface DevicePinLengthPickerProps {\n /** The currently-selected PIN length. */\n selected: number;\n /** Disable while a request is in flight. */\n disabled: boolean;\n /** Accessibility hint template for a pill; `{count}` is substituted. */\n optionHint: string;\n /** Optional prefix applied to each pill's testID. */\n testIdPrefix?: string;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. */\n theme?: AuthTheme;\n /** Report the newly-chosen length. */\n onSelect: (digits: number) => void;\n}\n\nconst PILL_VERTICAL_PADDING = 10;\nconst PILL_FONT_SIZE = 15;\n\n/** Build the theme-derived pill styles. */\nfunction usePickerStyles(theme: AuthTheme): {\n active: ViewStyle;\n text: TextStyle;\n textActive: TextStyle;\n pill: ViewStyle;\n} {\n return useMemo(\n () => ({\n pill: { borderColor: theme.colors.border },\n active: { backgroundColor: theme.colors.primary, borderColor: theme.colors.primary },\n text: { color: theme.colors.text },\n textActive: { color: theme.colors.onPrimary },\n }),\n [theme],\n );\n}\n\n/** Themeable 4/6/8 length chooser. */\nexport function DevicePinLengthPicker({\n selected,\n disabled,\n optionHint,\n testIdPrefix,\n theme: themeProp,\n onSelect,\n}: Readonly<DevicePinLengthPickerProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const dynamic = usePickerStyles(theme);\n const baseId = withTestIdPrefix(AuthTestIds.devicePinEnrollLength, testIdPrefix);\n\n return (\n <View style={styles.row}>\n {DEVICE_PIN_ALLOWED_DIGITS.map((option) => {\n const active = option === selected;\n return (\n <Pressable\n key={option}\n accessibilityHint={interpolate(optionHint, { count: option })}\n accessibilityLabel={String(option)}\n accessibilityRole=\"button\"\n accessibilityState={{ selected: active }}\n disabled={disabled}\n style={[styles.pill, dynamic.pill, active ? dynamic.active : null]}\n testID={`${baseId}-${String(option)}`}\n onPress={(): void => onSelect(option)}\n >\n <Text style={[styles.text, dynamic.text, active ? dynamic.textActive : null]}>\n {String(option)}\n </Text>\n </Pressable>\n );\n })}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n pill: {\n alignItems: 'center',\n borderRadius: 8,\n borderWidth: 1,\n flex: 1,\n paddingVertical: PILL_VERTICAL_PADDING,\n },\n row: {\n flexDirection: 'row',\n gap: 8,\n marginBottom: 8,\n },\n text: {\n fontSize: PILL_FONT_SIZE,\n fontWeight: '700',\n },\n});\n","/**\n * The localizable error states the device-PIN UNLOCK surface can show.\n *\n * Kept deliberately coarse so the UI never reveals whether a failed unlock was a\n * wrong PIN or an unknown / revoked device (both map to `Invalid`). `LockedOut`\n * and `RateLimited` carry no count — the human-readable \"try again later\" copy\n * is built from the `retryAfterSeconds` hint at the call site, not encoded here.\n */\nexport const enum DevicePinErrorKey {\n /** The PIN entered was too short for the enrolled length. */\n Incomplete = 'incomplete',\n /** Wrong PIN, or unknown / revoked device. Generic on purpose. */\n Invalid = 'invalid',\n /** Locked out after too many wrong attempts. */\n LockedOut = 'locked_out',\n /** Rate-limited by the BFF (too many requests). */\n RateLimited = 'rate_limited',\n /** Anything else (network / unexpected). */\n Generic = 'generic',\n}\n","/**\n * The react-query-FREE state machine behind {@link DevicePinUnlockScreen}.\n *\n * Lives on the login route group, which has NO QueryClient provider — so this\n * hook uses plain `useState` + `.then()/.catch()/.finally()` over the supplied\n * client's `unlockWithDevicePin`, never `useMutation`/`useQuery`. Pulling the\n * logic into a hook keeps the screen presentational and lets the submit / error\n * / lockout transitions be unit-tested without rendering.\n *\n * Submit flow:\n * - client-side preflight: a PIN shorter than the enrolled `digits` short-circuits\n * to {@link DevicePinErrorKey.Incomplete} with no network call;\n * - `success` → clear error, call `onSignedIn(user)`;\n * - `invalid` → {@link DevicePinErrorKey.Invalid} (generic — never reveal\n * wrong-pin vs unknown-device);\n * - `locked` → {@link DevicePinErrorKey.LockedOut} + the optional retry seconds;\n * - `rateLimited` → {@link DevicePinErrorKey.RateLimited} + the optional seconds;\n * - `error` / a thrown rejection → {@link DevicePinErrorKey.Generic}.\n */\nimport { useCallback, useState } from 'react';\n\nimport { DevicePinErrorKey } from './DevicePinErrorKey';\n\nimport type { DevicePinUnlockCapableClient } from './types';\n\n/** The signed-in user shape the success path hands back (claim bag). */\nexport type DevicePinUnlockedUser = { [claim: string]: unknown };\n\nexport interface UseDevicePinUnlockArgs {\n /** The client exposing `unlockWithDevicePin`. */\n client: DevicePinUnlockCapableClient;\n /** Enrolled PIN length (4/6/8) — a shorter entry is rejected before any call. */\n digits: number;\n /** Called with the fresh user after a successful unlock. */\n onSignedIn: (user: DevicePinUnlockedUser) => void;\n}\n\nexport interface UseDevicePinUnlockResult {\n /** The PIN currently entered. */\n pin: string;\n /** `true` while an unlock call is in flight. */\n submitting: boolean;\n /** The current error key, or `null` when there is none. */\n errorKey: DevicePinErrorKey | null;\n /** Seconds until retry, set with a `LockedOut`/`RateLimited` error; else `null`. */\n retryAfterSeconds: number | null;\n /** Replace the entered PIN. Clears a stale error. */\n setPin: (next: string) => void;\n /** Run the unlock attempt for the current PIN. */\n submit: () => void;\n}\n\nexport function useDevicePinUnlock({\n client,\n digits,\n onSignedIn,\n}: UseDevicePinUnlockArgs): UseDevicePinUnlockResult {\n const [pin, setPinState] = useState<string>('');\n const [submitting, setSubmitting] = useState<boolean>(false);\n const [errorKey, setErrorKey] = useState<DevicePinErrorKey | null>(null);\n const [retryAfterSeconds, setRetryAfterSeconds] = useState<number | null>(null);\n\n const setPin = useCallback((next: string): void => {\n setPinState(next);\n setErrorKey(null);\n setRetryAfterSeconds(null);\n }, []);\n\n const submit = useCallback((): void => {\n setErrorKey(null);\n setRetryAfterSeconds(null);\n if (pin.length < digits) {\n setErrorKey(DevicePinErrorKey.Incomplete);\n return;\n }\n setSubmitting(true);\n client\n .unlockWithDevicePin({ pin })\n .then((result) => {\n if (result.status === 'success') {\n onSignedIn(result.user);\n return;\n }\n if (result.status === 'invalid') {\n setErrorKey(DevicePinErrorKey.Invalid);\n return;\n }\n if (result.status === 'locked') {\n setRetryAfterSeconds(result.retryAfterSeconds);\n setErrorKey(DevicePinErrorKey.LockedOut);\n return;\n }\n if (result.status === 'rateLimited') {\n setRetryAfterSeconds(result.retryAfterSeconds);\n setErrorKey(DevicePinErrorKey.RateLimited);\n return;\n }\n setErrorKey(DevicePinErrorKey.Generic);\n })\n .catch(() => {\n setErrorKey(DevicePinErrorKey.Generic);\n })\n .finally(() => {\n setSubmitting(false);\n });\n }, [client, pin, digits, onSignedIn]);\n\n return { pin, submitting, errorKey, retryAfterSeconds, setPin, submit };\n}\n","/**\n * The device-PIN UNLOCK gate — shown on the login route for a returning,\n * logged-OUT user whose device is remembered (`hasPin && rememberedUsername`).\n *\n * Renders a masked PIN pad of the enrolled length; on submit it calls\n * `client.unlockWithDevicePin` (via {@link useDevicePinUnlock}) and, on success,\n * routes through the SAME `onSignedIn` path as the password tab. A\n * \"Sign in with password instead\" escape calls `onUsePassword` (the caller swaps\n * this screen out). All five result statuses are handled, including the lockout /\n * rate-limit retry countdown surfaced from `retryAfterSeconds`.\n *\n * react-query-FREE: all logic lives in `useDevicePinUnlock`, which uses plain\n * `useState` + `.then()` over the client — never `useMutation`. Presentational\n * only here. Distinct from the event-staff PIN (`PinForm`); this is `devicePin`.\n */\nimport { useMemo, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native';\n\nimport { DevicePinInput } from './DevicePinInput';\nimport { interpolate } from './interpolate';\nimport { DEFAULT_DEVICE_PIN_UNLOCK_LABELS, type DevicePinUnlockLabels } from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { DevicePinErrorKey } from '../devicePin/DevicePinErrorKey';\nimport {\n useDevicePinUnlock,\n type DevicePinUnlockedUser,\n} from '../devicePin/useDevicePinUnlock';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { DevicePinUnlockCapableClient } from '../devicePin/types';\nimport type { AuthTheme } from '../theme/AuthTheme';\n\nexport interface DevicePinUnlockScreenProps {\n /** The client exposing `unlockWithDevicePin`. */\n client: DevicePinUnlockCapableClient;\n /** Enrolled PIN length (4/6/8). */\n digits: number;\n /** Remembered username, shown in the greeting (may be empty). */\n rememberedUsername: string;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<DevicePinUnlockLabels>;\n /** Prefix applied to every `testID`. */\n testIdPrefix?: string;\n /** Called with the fresh user after a successful unlock. */\n onSignedIn: (user: DevicePinUnlockedUser) => void;\n /** Escape hatch → render the normal password/OTP/event-PIN tabs. */\n onUsePassword: () => void;\n}\n\n/** Resolve the localized error copy for the current unlock error state. */\nfunction resolveErrorText(\n errorKey: DevicePinErrorKey | null,\n digits: number,\n retryAfter: number | null,\n labels: DevicePinUnlockLabels,\n): string | null {\n if (errorKey === null) {\n return null;\n }\n if (errorKey === DevicePinErrorKey.Incomplete) {\n return interpolate(labels.errorIncomplete, { count: digits });\n }\n if (errorKey === DevicePinErrorKey.Invalid) {\n return labels.errorInvalid;\n }\n if (errorKey === DevicePinErrorKey.LockedOut) {\n return retryAfter !== null\n ? interpolate(labels.errorLockedOutRetry, { count: retryAfter })\n : labels.errorLockedOut;\n }\n if (errorKey === DevicePinErrorKey.RateLimited) {\n return retryAfter !== null\n ? interpolate(labels.errorRateLimitedRetry, { count: retryAfter })\n : labels.errorRateLimited;\n }\n return labels.errorGeneric;\n}\n\n/** Themeable device-PIN unlock gate built on `useDevicePinUnlock`. */\nexport function DevicePinUnlockScreen({\n client,\n digits,\n rememberedUsername,\n theme: themeProp,\n labels: labelsProp,\n testIdPrefix,\n onSignedIn,\n onUsePassword,\n}: Readonly<DevicePinUnlockScreenProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<DevicePinUnlockLabels>(\n () => ({ ...DEFAULT_DEVICE_PIN_UNLOCK_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n const { pin, submitting, errorKey, retryAfterSeconds, setPin, submit } = useDevicePinUnlock({\n client,\n digits,\n onSignedIn,\n });\n\n const hasName = rememberedUsername !== '';\n const title = hasName ? interpolate(labels.title, { name: rememberedUsername }) : labels.titleNoName;\n const error = resolveErrorText(errorKey, digits, retryAfterSeconds, labels);\n const buttonStyle = submitting\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.devicePinUnlock, testIdPrefix)}\n >\n <Text style={styles.title}>{title}</Text>\n <Text style={styles.subtitle}>{interpolate(labels.description, { count: digits })}</Text>\n\n <DevicePinInput\n accessibilityHint={labels.pinPlaceholder}\n accessibilityLabel={labels.pinLabel}\n disabled={submitting}\n emptyHint={labels.digitEmptyHint}\n filledHint={labels.digitFilledHint}\n length={digits}\n testID={AuthTestIds.devicePinUnlockInput}\n testIdPrefix={testIdPrefix}\n theme={theme}\n value={pin}\n onChange={setPin}\n />\n\n {error !== null ? (\n <Text\n style={styles.errorText}\n testID={withTestIdPrefix(AuthTestIds.devicePinUnlockError, testIdPrefix)}\n >\n {error}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.submit}\n accessibilityLabel={submitting ? labels.submitting : labels.submit}\n accessibilityRole=\"button\"\n disabled={submitting}\n style={buttonStyle}\n testID={withTestIdPrefix(AuthTestIds.devicePinUnlockSubmit, testIdPrefix)}\n onPress={submit}\n >\n {submitting ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.submit}</Text>\n )}\n </TouchableOpacity>\n\n <TouchableOpacity\n accessibilityHint={labels.usePasswordHint}\n accessibilityLabel={labels.usePasswordInstead}\n accessibilityRole=\"button\"\n disabled={submitting}\n style={styles.escapeLink}\n testID={withTestIdPrefix(AuthTestIds.devicePinUnlockUsePassword, testIdPrefix)}\n onPress={onUsePassword}\n >\n <Text style={styles.linkText}>{labels.usePasswordInstead}</Text>\n </TouchableOpacity>\n </View>\n </View>\n );\n}\n","/**\n * The localizable failure states the device-PIN ENROL form can show — shared by\n * the post-login offer and the settings toggle.\n */\nexport const enum DevicePinEnrollErrorKey {\n /** PIN length wrong or the confirmation didn't match (no network call). */\n Mismatch = 'mismatch',\n /** The current session is not authenticated (401). */\n Unauthorized = 'unauthorized',\n /** The session already has a PIN, or is otherwise forbidden (403). */\n Forbidden = 'forbidden',\n /** The PIN failed server-side validation (400). */\n InvalidPin = 'invalid_pin',\n /** Any other failure (grant / network / unexpected). */\n Failed = 'failed',\n}\n","/**\n * The react-query-FREE state machine behind {@link DevicePinEnrollForm}, shared\n * by the post-login offer and the settings toggle.\n *\n * Enrol requires an authenticated session (the session cookie travels on the\n * client's `enrollDevicePin` call) — but the post-login offer can render adjacent\n * to the login route group, so this stays react-query-free (`useState` +\n * `.then()/.catch()/.finally()`), never `useMutation`. Pulling the logic into a\n * hook lets the confirm / mismatch / status transitions be unit-tested without\n * rendering, and keeps the form component presentational.\n *\n * Submit flow (a single PIN entry confirmed against itself):\n * - preflight: PIN must be exactly `digits` long and equal its confirmation,\n * else {@link DevicePinEnrollErrorKey.Mismatch} (no network call);\n * - `success` → call `onEnrolled`;\n * - `unauthorized` / `forbidden` / `invalidPin` → the matching error key;\n * - `error` / a thrown rejection → {@link DevicePinEnrollErrorKey.Failed}.\n */\nimport { useCallback, useState } from 'react';\n\nimport { DevicePinEnrollErrorKey } from './DevicePinEnrollErrorKey';\n\nimport type { DevicePinEnrollCapableClient, DevicePinEnrollResult } from './types';\n\nexport interface UseDevicePinEnrollArgs {\n /** The client exposing `enrollDevicePin`. */\n client: DevicePinEnrollCapableClient;\n /** Chosen PIN length (4/6/8). */\n digits: number;\n /** Called after a successful enrol so the surface can dismiss / flip state. */\n onEnrolled: () => void;\n}\n\nexport interface UseDevicePinEnrollResult {\n pin: string;\n confirmPin: string;\n submitting: boolean;\n errorKey: DevicePinEnrollErrorKey | null;\n setPin: (next: string) => void;\n setConfirmPin: (next: string) => void;\n submit: () => void;\n}\n\n/** Map a non-success enrol result onto its localizable error key. */\nfunction errorKeyFor(result: DevicePinEnrollResult): DevicePinEnrollErrorKey {\n if (result.status === 'unauthorized') {\n return DevicePinEnrollErrorKey.Unauthorized;\n }\n if (result.status === 'forbidden') {\n return DevicePinEnrollErrorKey.Forbidden;\n }\n if (result.status === 'invalidPin') {\n return DevicePinEnrollErrorKey.InvalidPin;\n }\n return DevicePinEnrollErrorKey.Failed;\n}\n\nexport function useDevicePinEnroll({\n client,\n digits,\n onEnrolled,\n}: UseDevicePinEnrollArgs): UseDevicePinEnrollResult {\n const [pin, setPinState] = useState<string>('');\n const [confirmPin, setConfirmState] = useState<string>('');\n const [submitting, setSubmitting] = useState<boolean>(false);\n const [errorKey, setErrorKey] = useState<DevicePinEnrollErrorKey | null>(null);\n\n const setPin = useCallback((next: string): void => {\n setPinState(next);\n setErrorKey(null);\n }, []);\n\n const setConfirmPin = useCallback((next: string): void => {\n setConfirmState(next);\n setErrorKey(null);\n }, []);\n\n const submit = useCallback((): void => {\n setErrorKey(null);\n const wrongLength = pin.length !== digits;\n const mismatched = pin !== confirmPin;\n if (wrongLength || mismatched) {\n setErrorKey(DevicePinEnrollErrorKey.Mismatch);\n return;\n }\n setSubmitting(true);\n client\n .enrollDevicePin({ pin, digits })\n .then((result) => {\n if (result.status === 'success') {\n onEnrolled();\n return;\n }\n setErrorKey(errorKeyFor(result));\n })\n .catch(() => {\n setErrorKey(DevicePinEnrollErrorKey.Failed);\n })\n .finally(() => {\n setSubmitting(false);\n });\n }, [client, pin, confirmPin, digits, onEnrolled]);\n\n return { pin, confirmPin, submitting, errorKey, setPin, setConfirmPin, submit };\n}\n","/**\n * The shared device-PIN ENROL form — reused by the post-login offer\n * ({@link DevicePinOffer}) and the settings toggle ({@link DevicePinSettingsCard}).\n *\n * Lets the user pick a PIN length (4/6/8), enter + confirm a PIN, and submit via\n * `client.enrollDevicePin` (through {@link useDevicePinEnroll}). On success it\n * calls `onEnrolled`; `onCancel` dismisses without saving. Presentational only —\n * all submit / mismatch / status logic lives in the hook (react-query-free).\n * Styled from the `AuthTheme` token bag.\n */\nimport { useMemo, useState, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native';\n\nimport { DevicePinInput } from './DevicePinInput';\nimport { DevicePinLengthPicker } from './DevicePinLengthPicker';\nimport { interpolate } from './interpolate';\nimport { DEFAULT_DEVICE_PIN_ENROLL_LABELS, type DevicePinEnrollLabels } from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { DevicePinEnrollErrorKey } from '../devicePin/DevicePinEnrollErrorKey';\nimport { DEVICE_PIN_DEFAULT_DIGITS } from '../devicePin/devicePinConstants';\nimport { useDevicePinEnroll } from '../devicePin/useDevicePinEnroll';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { DevicePinEnrollCapableClient } from '../devicePin/types';\nimport type { AuthTheme } from '../theme/AuthTheme';\n\nexport interface DevicePinEnrollFormProps {\n /** The client exposing `enrollDevicePin`. */\n client: DevicePinEnrollCapableClient;\n /** Initial PIN length (defaults to {@link DEVICE_PIN_DEFAULT_DIGITS}). */\n initialDigits?: number;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<DevicePinEnrollLabels>;\n /** Prefix applied to every `testID`. */\n testIdPrefix?: string;\n /** Called after a successful enrol. */\n onEnrolled: () => void;\n /** Called when the user cancels without saving. */\n onCancel: () => void;\n}\n\n/** Resolve the localized error copy for the current enrol error state. */\nfunction resolveErrorText(\n errorKey: DevicePinEnrollErrorKey | null,\n digits: number,\n labels: DevicePinEnrollLabels,\n): string | null {\n if (errorKey === null) {\n return null;\n }\n if (errorKey === DevicePinEnrollErrorKey.Mismatch) {\n return interpolate(labels.errorMismatch, { count: digits });\n }\n if (errorKey === DevicePinEnrollErrorKey.Unauthorized) {\n return labels.errorUnauthorized;\n }\n if (errorKey === DevicePinEnrollErrorKey.Forbidden) {\n return labels.errorForbidden;\n }\n if (errorKey === DevicePinEnrollErrorKey.InvalidPin) {\n return labels.errorInvalidPin;\n }\n return labels.errorFailed;\n}\n\n/** Themeable device-PIN enrol form built on `useDevicePinEnroll`. */\nexport function DevicePinEnrollForm({\n client,\n initialDigits = DEVICE_PIN_DEFAULT_DIGITS,\n theme: themeProp,\n labels: labelsProp,\n testIdPrefix,\n onEnrolled,\n onCancel,\n}: Readonly<DevicePinEnrollFormProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<DevicePinEnrollLabels>(\n () => ({ ...DEFAULT_DEVICE_PIN_ENROLL_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n const [digits, setDigits] = useState<number>(initialDigits);\n const { pin, confirmPin, submitting, errorKey, setPin, setConfirmPin, submit } =\n useDevicePinEnroll({ client, digits, onEnrolled });\n const error = resolveErrorText(errorKey, digits, labels);\n const buttonStyle = submitting\n ? [styles.primaryButton, styles.primaryButtonDisabled]\n : styles.primaryButton;\n\n return (\n <View\n style={styles.card}\n testID={withTestIdPrefix(AuthTestIds.devicePinEnrollForm, testIdPrefix)}\n >\n <Text style={styles.title}>{labels.formTitle}</Text>\n <Text style={styles.subtitle}>{interpolate(labels.formDescription, { count: digits })}</Text>\n\n <Text style={styles.label}>{labels.lengthLabel}</Text>\n <DevicePinLengthPicker\n disabled={submitting}\n optionHint={labels.lengthOptionHint}\n selected={digits}\n testIdPrefix={testIdPrefix}\n theme={theme}\n onSelect={(option): void => {\n setDigits(option);\n setPin('');\n setConfirmPin('');\n }}\n />\n\n <Text style={styles.label}>{labels.pinLabel}</Text>\n <DevicePinInput\n accessibilityHint={labels.pinPlaceholder}\n accessibilityLabel={labels.pinLabel}\n disabled={submitting}\n emptyHint={labels.pinPlaceholder}\n filledHint={labels.pinLabel}\n length={digits}\n testID={AuthTestIds.devicePinEnrollPin}\n testIdPrefix={testIdPrefix}\n theme={theme}\n value={pin}\n onChange={setPin}\n />\n\n <Text style={styles.label}>{labels.confirmLabel}</Text>\n <DevicePinInput\n accessibilityHint={labels.confirmPlaceholder}\n accessibilityLabel={labels.confirmLabel}\n disabled={submitting}\n emptyHint={labels.confirmPlaceholder}\n filledHint={labels.confirmLabel}\n length={digits}\n testID={AuthTestIds.devicePinEnrollConfirm}\n testIdPrefix={testIdPrefix}\n theme={theme}\n value={confirmPin}\n onChange={setConfirmPin}\n />\n\n {error !== null ? (\n <Text\n style={styles.errorText}\n testID={withTestIdPrefix(AuthTestIds.devicePinEnrollError, testIdPrefix)}\n >\n {error}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.submit}\n accessibilityLabel={submitting ? labels.submitting : labels.submit}\n accessibilityRole=\"button\"\n disabled={submitting}\n style={buttonStyle}\n testID={withTestIdPrefix(AuthTestIds.devicePinEnrollSubmit, testIdPrefix)}\n onPress={submit}\n >\n {submitting ? (\n <ActivityIndicator color={theme.colors.onPrimary} size=\"small\" />\n ) : (\n <Text style={styles.primaryButtonText}>{labels.submit}</Text>\n )}\n </TouchableOpacity>\n\n <TouchableOpacity\n accessibilityHint={labels.cancelHint}\n accessibilityLabel={labels.cancel}\n accessibilityRole=\"button\"\n disabled={submitting}\n style={styles.escapeLink}\n testID={withTestIdPrefix(AuthTestIds.devicePinEnrollCancel, testIdPrefix)}\n onPress={onCancel}\n >\n <Text style={styles.linkText}>{labels.cancel}</Text>\n </TouchableOpacity>\n </View>\n );\n}\n","/**\n * The skippable post-login \"Set a PIN for faster sign-in?\" offer.\n *\n * Mount on the post-login landing for an authenticated user who does NOT already\n * have a device PIN. It is dismissible and non-blocking: an initial prompt with\n * \"Set up a PIN\" / \"Not now\"; tapping accept reveals the shared\n * {@link DevicePinEnrollForm}; on success or skip it calls `onDismiss` so the\n * host can hide it (and remember the dismissal). Self-contained, react-query-free.\n */\nimport { useMemo, useState, type ReactElement } from 'react';\n\nimport { Text, TouchableOpacity, View } from 'react-native';\n\nimport { DevicePinEnrollForm } from './DevicePinEnrollForm';\nimport {\n DEFAULT_DEVICE_PIN_ENROLL_LABELS,\n type DevicePinEnrollLabels,\n} from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { DevicePinEnrollCapableClient } from '../devicePin/types';\nimport type { AuthTheme } from '../theme/AuthTheme';\n\nexport interface DevicePinOfferProps {\n /** The client exposing `enrollDevicePin`. */\n client: DevicePinEnrollCapableClient;\n /** Initial PIN length offered in the enrol form. */\n initialDigits?: number;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<DevicePinEnrollLabels>;\n /** Prefix applied to every `testID`. */\n testIdPrefix?: string;\n /** Called when the offer is finished — accepted+enrolled, or skipped. */\n onDismiss: () => void;\n}\n\n/** Themeable, skippable post-login device-PIN setup offer. */\nexport function DevicePinOffer({\n client,\n initialDigits,\n theme: themeProp,\n labels: labelsProp,\n testIdPrefix,\n onDismiss,\n}: Readonly<DevicePinOfferProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<DevicePinEnrollLabels>(\n () => ({ ...DEFAULT_DEVICE_PIN_ENROLL_LABELS, ...labelsProp }),\n [labelsProp],\n );\n const [expanded, setExpanded] = useState<boolean>(false);\n const cardTestId = withTestIdPrefix(AuthTestIds.devicePinOffer, testIdPrefix);\n\n if (expanded) {\n return (\n <View style={styles.card} testID={cardTestId}>\n <DevicePinEnrollForm\n client={client}\n initialDigits={initialDigits}\n labels={labelsProp}\n testIdPrefix={testIdPrefix}\n theme={theme}\n onCancel={onDismiss}\n onEnrolled={onDismiss}\n />\n </View>\n );\n }\n\n return (\n <View style={styles.card} testID={cardTestId}>\n <Text style={styles.title}>{labels.offerTitle}</Text>\n <Text style={styles.subtitle}>{labels.offerDescription}</Text>\n\n <TouchableOpacity\n accessibilityHint={labels.offerAcceptHint}\n accessibilityLabel={labels.offerAccept}\n accessibilityRole=\"button\"\n style={styles.primaryButton}\n testID={withTestIdPrefix(AuthTestIds.devicePinOfferAccept, testIdPrefix)}\n onPress={(): void => setExpanded(true)}\n >\n <Text style={styles.primaryButtonText}>{labels.offerAccept}</Text>\n </TouchableOpacity>\n\n <TouchableOpacity\n accessibilityHint={labels.offerSkipHint}\n accessibilityLabel={labels.offerSkip}\n accessibilityRole=\"button\"\n style={styles.secondaryButton}\n testID={withTestIdPrefix(AuthTestIds.devicePinOfferSkip, testIdPrefix)}\n onPress={onDismiss}\n >\n <Text style={styles.secondaryButtonText}>{labels.offerSkip}</Text>\n </TouchableOpacity>\n </View>\n );\n}\n","/**\n * The react-query-FREE state machine behind the device-PIN settings card's\n * DISABLE action.\n *\n * Extracted from {@link DevicePinSettingsCard} so the disable transitions\n * (success flips `hasPin` off; a `false` result or a thrown rejection raises the\n * `failed` flag) can be unit-tested without rendering. Plain `useState` +\n * `.then()/.catch()/.finally()` over the client — never `useMutation`.\n *\n * Seeded with `initialHasPin` (from `GET /bff/config`); it tracks its own\n * enabled/disabled state thereafter. `markEnabled` is called by the host after a\n * successful enrol (the enrol form owns that call) to flip the card back on.\n */\nimport { useCallback, useState } from 'react';\n\nimport type { DevicePinDisableCapableClient } from './types';\n\nexport interface UseDevicePinDisableArgs {\n /** The client exposing `disableDevicePin`. */\n client: DevicePinDisableCapableClient;\n /** Whether this device already has an enrolled PIN (seeded from config). */\n initialHasPin: boolean;\n /** Called whenever the enabled state changes (enabled / disabled). */\n onChanged?: (hasPin: boolean) => void;\n}\n\nexport interface UseDevicePinDisableResult {\n /** `true` when the device currently has an enrolled PIN. */\n hasPin: boolean;\n /** `true` while a disable call is in flight. */\n disabling: boolean;\n /** `true` when the last disable attempt failed. */\n failed: boolean;\n /** Run the disable call for the current session. */\n disable: () => void;\n /** Flip the card to enabled (called by the host after a successful enrol). */\n markEnabled: () => void;\n}\n\nexport function useDevicePinDisable({\n client,\n initialHasPin,\n onChanged,\n}: UseDevicePinDisableArgs): UseDevicePinDisableResult {\n const [hasPin, setHasPin] = useState<boolean>(initialHasPin);\n const [disabling, setDisabling] = useState<boolean>(false);\n const [failed, setFailed] = useState<boolean>(false);\n\n const disable = useCallback((): void => {\n setFailed(false);\n setDisabling(true);\n client\n .disableDevicePin()\n .then((ok) => {\n if (ok) {\n setHasPin(false);\n onChanged?.(false);\n return;\n }\n setFailed(true);\n })\n .catch(() => {\n setFailed(true);\n })\n .finally(() => {\n setDisabling(false);\n });\n }, [client, onChanged]);\n\n const markEnabled = useCallback((): void => {\n setHasPin(true);\n onChanged?.(true);\n }, [onChanged]);\n\n return { hasPin, disabling, failed, disable, markEnabled };\n}\n","/**\n * The authenticated \"Quick PIN sign-in\" settings control.\n *\n * Mount on an authenticated settings/account surface. Seeded with `initialHasPin`\n * (from `GET /bff/config`); it tracks its own enabled/disabled state thereafter\n * and offers either:\n * - Enable → reveals the shared {@link DevicePinEnrollForm} → `client.enrollDevicePin`;\n * - Disable → `client.disableDevicePin` (revokes the offline token + clears the\n * device record server-side).\n *\n * `onChanged(hasPin)` fires whenever the enabled state flips, so the host can\n * persist / re-fetch. react-query-free: the disable logic lives in\n * {@link useDevicePinDisable}; the enrol logic in the shared form's hook.\n */\nimport { useMemo, useState, type ReactElement } from 'react';\n\nimport { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native';\n\nimport { DevicePinEnrollForm } from './DevicePinEnrollForm';\nimport {\n DEFAULT_DEVICE_PIN_ENROLL_LABELS,\n DEFAULT_DEVICE_PIN_SETTINGS_LABELS,\n type DevicePinEnrollLabels,\n type DevicePinSettingsLabels,\n} from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { useDevicePinDisable } from '../devicePin/useDevicePinDisable';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type {\n DevicePinDisableCapableClient,\n DevicePinEnrollCapableClient,\n} from '../devicePin/types';\nimport type { AuthTheme } from '../theme/AuthTheme';\n\nexport interface DevicePinSettingsCardProps {\n /** The client exposing both `enrollDevicePin` and `disableDevicePin`. */\n client: DevicePinEnrollCapableClient & DevicePinDisableCapableClient;\n /** Whether this device already has an enrolled PIN (seeded from config). */\n initialHasPin: boolean;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. */\n theme?: AuthTheme;\n /** Settings-card copy. Partial — unspecified keys fall back to English. */\n labels?: Partial<DevicePinSettingsLabels>;\n /** Enrol-form copy passed through to the embedded form. */\n enrollLabels?: Partial<DevicePinEnrollLabels>;\n /** Prefix applied to every `testID`. */\n testIdPrefix?: string;\n /** Called whenever the enabled state flips (enabled / disabled). */\n onChanged?: (hasPin: boolean) => void;\n}\n\n/** Themeable authenticated device-PIN enable/disable card. */\nexport function DevicePinSettingsCard({\n client,\n initialHasPin,\n theme: themeProp,\n labels: labelsProp,\n enrollLabels,\n testIdPrefix,\n onChanged,\n}: Readonly<DevicePinSettingsCardProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<DevicePinSettingsLabels>(\n () => ({ ...DEFAULT_DEVICE_PIN_SETTINGS_LABELS, ...labelsProp }),\n [labelsProp],\n );\n const resolvedEnrollLabels = useMemo<DevicePinEnrollLabels>(\n () => ({ ...DEFAULT_DEVICE_PIN_ENROLL_LABELS, ...enrollLabels }),\n [enrollLabels],\n );\n\n const [enrolling, setEnrolling] = useState<boolean>(false);\n const { hasPin, disabling, failed, disable, markEnabled } = useDevicePinDisable({\n client,\n initialHasPin,\n onChanged,\n });\n\n const handleEnrolled = (): void => {\n setEnrolling(false);\n markEnabled();\n };\n\n const disableButtonStyle = disabling\n ? [styles.secondaryButton, styles.primaryButtonDisabled]\n : styles.secondaryButton;\n\n return (\n <View\n style={styles.card}\n testID={withTestIdPrefix(AuthTestIds.devicePinSettings, testIdPrefix)}\n >\n <Text style={styles.title}>{labels.title}</Text>\n <Text style={styles.subtitle}>{labels.description}</Text>\n <Text\n style={styles.statusText}\n testID={withTestIdPrefix(AuthTestIds.devicePinSettingsStatus, testIdPrefix)}\n >\n {hasPin ? labels.statusEnabled : labels.statusDisabled}\n </Text>\n\n {failed ? (\n <Text\n style={styles.errorText}\n testID={withTestIdPrefix(AuthTestIds.devicePinSettingsError, testIdPrefix)}\n >\n {labels.disableFailed}\n </Text>\n ) : null}\n\n {renderAction()}\n </View>\n );\n\n function renderAction(): ReactElement {\n if (enrolling) {\n return (\n <DevicePinEnrollForm\n client={client}\n labels={resolvedEnrollLabels}\n testIdPrefix={testIdPrefix}\n theme={theme}\n onCancel={(): void => setEnrolling(false)}\n onEnrolled={handleEnrolled}\n />\n );\n }\n if (hasPin) {\n return (\n <TouchableOpacity\n accessibilityHint={labels.disableHint}\n accessibilityLabel={disabling ? labels.disabling : labels.disable}\n accessibilityRole=\"button\"\n disabled={disabling}\n style={disableButtonStyle}\n testID={withTestIdPrefix(AuthTestIds.devicePinSettingsDisable, testIdPrefix)}\n onPress={disable}\n >\n {disabling ? (\n <ActivityIndicator color={theme.colors.primary} size=\"small\" />\n ) : (\n <Text style={styles.secondaryButtonText}>{labels.disable}</Text>\n )}\n </TouchableOpacity>\n );\n }\n return (\n <TouchableOpacity\n accessibilityHint={labels.enableHint}\n accessibilityLabel={labels.enable}\n accessibilityRole=\"button\"\n style={styles.primaryButton}\n testID={withTestIdPrefix(AuthTestIds.devicePinSettingsEnable, testIdPrefix)}\n onPress={(): void => setEnrolling(true)}\n >\n <Text style={styles.primaryButtonText}>{labels.enable}</Text>\n </TouchableOpacity>\n );\n }\n}\n","/**\n * Navigation helpers for the passkey (WebAuthn) BFF endpoints.\n *\n * Unlike the device-PIN client (which is plain `fetch`), the passkey login and\n * registration ceremonies are NOT fetches — they are full-page BROWSER\n * NAVIGATIONS. The BFF (`Bff.AspNetCore` 1.3.x) drives the WebAuthn ceremony\n * through Keycloak's hosted pages, then redirects the browser back:\n * - login: `/bff/passkey/login?returnUrl=<rel>` → on success the browser\n * lands on `returnUrl` with the session cookie already set;\n * - registration: `/bff/passkey/register?returnUrl=<rel>` → Keycloak re-auths\n * the user (password) then runs the credential-creation ceremony, returning\n * the browser to `returnUrl?passkey=registered`;\n * - failure / cancel: the BFF redirects to `<login>?passkeyError=cancelled` or\n * `<login>?passkeyError=failed`.\n *\n * react-query-FREE by construction: there is NO fetch here at all — every\n * function is a pure `window.location` read or `window.location.assign`. The\n * login route group has no QueryClient provider, so the passkey login button\n * (which lives there) MUST avoid any react-query primitive; navigation satisfies\n * that trivially.\n *\n * All reads are SSR-safe: when `window` is undefined (server render / native)\n * they return a benign default rather than throwing.\n */\n\n/** The recognised passkey error codes the BFF sends back via `?passkeyError=`. */\nexport type PasskeyErrorCode = 'cancelled' | 'failed';\n\nconst PASSKEY_LOGIN_ENDPOINT = '/bff/passkey/login';\nconst PASSKEY_REGISTER_ENDPOINT = '/bff/passkey/register';\nconst RETURN_URL_PARAM = 'returnUrl';\nconst PASSKEY_ERROR_PARAM = 'passkeyError';\nconst PASSKEY_PARAM = 'passkey';\nconst PASSKEY_REGISTERED_VALUE = 'registered';\nconst PASSKEY_ERROR_CANCELLED: PasskeyErrorCode = 'cancelled';\nconst PASSKEY_ERROR_FAILED: PasskeyErrorCode = 'failed';\n\n/** Build the `<endpoint>?returnUrl=<encoded>` URL the browser navigates to. */\nfunction buildNavigationUrl(endpoint: string, returnUrl: string): string {\n return `${endpoint}?${RETURN_URL_PARAM}=${encodeURIComponent(returnUrl)}`;\n}\n\n/** Read the current query string SSR-safely, or `null` off-web. */\nfunction readSearchParams(): URLSearchParams | null {\n if (typeof window === 'undefined') {\n return null;\n }\n return new URLSearchParams(window.location.search);\n}\n\n/**\n * Start the passkey LOGIN ceremony by navigating the browser to the BFF's\n * `/bff/passkey/login` endpoint. The BFF redirects through Keycloak's WebAuthn\n * ceremony and, on success, returns the browser to `returnUrl` with a session\n * cookie set. No-op off-web (no `window`). `returnUrl` should be a relative\n * app path (e.g. `'/'`).\n */\nexport function startPasskeyLogin(returnUrl: string): void {\n if (typeof window === 'undefined') {\n return;\n }\n window.location.assign(buildNavigationUrl(PASSKEY_LOGIN_ENDPOINT, returnUrl));\n}\n\n/**\n * Start the passkey REGISTRATION ceremony by navigating the browser to the BFF's\n * `/bff/passkey/register` endpoint. Requires an authenticated session; Keycloak\n * re-authenticates the user (password) then runs the credential-creation\n * ceremony, returning the browser to `returnUrl?passkey=registered`. No-op\n * off-web. `returnUrl` should be a relative app path so the user lands back on\n * the same settings surface.\n */\nexport function startPasskeyRegistration(returnUrl: string): void {\n if (typeof window === 'undefined') {\n return;\n }\n window.location.assign(buildNavigationUrl(PASSKEY_REGISTER_ENDPOINT, returnUrl));\n}\n\n/**\n * Read the `?passkeyError=` query param the BFF appends on a failed / cancelled\n * ceremony. Returns `'cancelled'` or `'failed'` for the two known values, or\n * `null` for an absent / unknown value. SSR-safe (returns `null` off-web).\n */\nexport function readPasskeyError(): PasskeyErrorCode | null {\n const params = readSearchParams();\n if (params === null) {\n return null;\n }\n const value = params.get(PASSKEY_ERROR_PARAM);\n if (value === PASSKEY_ERROR_CANCELLED) {\n return PASSKEY_ERROR_CANCELLED;\n }\n if (value === PASSKEY_ERROR_FAILED) {\n return PASSKEY_ERROR_FAILED;\n }\n return null;\n}\n\n/**\n * `true` when the browser has just returned from a successful passkey\n * registration, i.e. the `?passkey=registered` query param is present. SSR-safe\n * (returns `false` off-web).\n */\nexport function readPasskeyRegistered(): boolean {\n const params = readSearchParams();\n if (params === null) {\n return false;\n }\n return params.get(PASSKEY_PARAM) === PASSKEY_REGISTERED_VALUE;\n}\n","/**\n * The \"Sign in with a passkey\" button rendered on the unified login surface when\n * the BFF advertises the `passkey` method.\n *\n * A passkey login is a full-page BROWSER NAVIGATION, not a fetch: tapping the\n * button hands off to `/bff/passkey/login`, which drives the WebAuthn ceremony\n * through Keycloak and returns the browser to `returnUrl` (default `'/'`, which\n * routes an authenticated user to their dashboard) with a session cookie set. On\n * a cancelled / failed ceremony the BFF bounces back to `?passkeyError=…`; we\n * surface that as an inline error banner above the button.\n *\n * react-query-free: it is pure `window.location` navigation (see\n * `passkeyNavigation`), so it is safe to mount inside the login route group which\n * has no QueryClient provider.\n */\nimport { useMemo, type ReactElement } from 'react';\n\nimport { Text, TouchableOpacity, View } from 'react-native';\n\nimport { DEFAULT_PASSKEY_LOGIN_LABELS, type PasskeyLoginLabels } from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport { readPasskeyError, startPasskeyLogin } from '../passkey/passkeyNavigation';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\n\nexport interface PasskeyLoginButtonProps {\n /** Relative app path the BFF returns to on success. Defaults to `'/'`. */\n returnUrl?: string;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<PasskeyLoginLabels>;\n /** Prefix applied to every `testID`. */\n testIdPrefix?: string;\n}\n\n/** The app root — an authenticated user is routed onward to their dashboard. */\nconst DEFAULT_RETURN_URL = '/';\n\n/** Themeable passkey login CTA + error banner. */\nexport function PasskeyLoginButton({\n returnUrl = DEFAULT_RETURN_URL,\n theme: themeProp,\n labels: labelsProp,\n testIdPrefix,\n}: Readonly<PasskeyLoginButtonProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<PasskeyLoginLabels>(\n () => ({ ...DEFAULT_PASSKEY_LOGIN_LABELS, ...labelsProp }),\n [labelsProp],\n );\n const error = readPasskeyError();\n\n return (\n <View testID={withTestIdPrefix(AuthTestIds.passkeyLogin, testIdPrefix)}>\n {error !== null ? (\n <Text\n style={styles.errorText}\n testID={withTestIdPrefix(AuthTestIds.passkeyLoginError, testIdPrefix)}\n >\n {error === 'cancelled' ? labels.errorCancelled : labels.errorFailed}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.signInHint}\n accessibilityLabel={labels.signInButton}\n accessibilityRole=\"button\"\n style={styles.secondaryButton}\n testID={withTestIdPrefix(AuthTestIds.passkeyLoginButton, testIdPrefix)}\n onPress={(): void => startPasskeyLogin(returnUrl)}\n >\n <Text style={styles.secondaryButtonText}>{labels.signInButton}</Text>\n </TouchableOpacity>\n </View>\n );\n}\n","/**\n * The authenticated \"Passkeys\" settings card.\n *\n * Mount on an authenticated settings / account surface (alongside the device-PIN\n * card). Adding a passkey is a full-page BROWSER NAVIGATION to\n * `/bff/passkey/register`: Keycloak re-authenticates the user (password) then\n * runs the WebAuthn credential-creation ceremony, returning the browser to the\n * SAME settings page with `?passkey=registered` appended. On mount we read that\n * param and, when present, show a success line.\n *\n * react-query-free: the add action is pure `window.location` navigation (see\n * `passkeyNavigation`); there is no fetch here. Mirrors `DevicePinSettingsCard`.\n */\nimport { useMemo, type ReactElement } from 'react';\n\nimport { Text, TouchableOpacity, View } from 'react-native';\n\nimport { DEFAULT_PASSKEY_SETTINGS_LABELS, type PasskeySettingsLabels } from './labels';\nimport { AuthTestIds, withTestIdPrefix } from './testIds';\nimport { useAuthStyles } from './useAuthStyles';\nimport {\n readPasskeyRegistered,\n startPasskeyRegistration,\n} from '../passkey/passkeyNavigation';\nimport { useAuthTheme } from '../theme/AuthThemeProvider';\n\nimport type { AuthTheme } from '../theme/AuthTheme';\n\nexport interface PasskeySettingsCardProps {\n /**\n * Relative app path the BFF returns to after registration. Defaults to the\n * current `window.location.pathname` so the user lands back on this page.\n */\n returnUrl?: string;\n /** Explicit theme; overrides any `<AuthThemeProvider>`. */\n theme?: AuthTheme;\n /** Localised copy. Partial — unspecified keys fall back to English defaults. */\n labels?: Partial<PasskeySettingsLabels>;\n /** Prefix applied to every `testID`. */\n testIdPrefix?: string;\n}\n\n/** Fallback return path when there is no `window` to read the pathname from. */\nconst DEFAULT_RETURN_PATH = '/';\n\n/** Read the current pathname SSR-safely so registration returns to this page. */\nfunction readCurrentPath(): string {\n if (typeof window === 'undefined') {\n return DEFAULT_RETURN_PATH;\n }\n return window.location.pathname;\n}\n\n/** Themeable authenticated passkey add card. */\nexport function PasskeySettingsCard({\n returnUrl,\n theme: themeProp,\n labels: labelsProp,\n testIdPrefix,\n}: Readonly<PasskeySettingsCardProps>): ReactElement {\n const theme = useAuthTheme(themeProp);\n const styles = useAuthStyles(theme);\n const labels = useMemo<PasskeySettingsLabels>(\n () => ({ ...DEFAULT_PASSKEY_SETTINGS_LABELS, ...labelsProp }),\n [labelsProp],\n );\n const justRegistered = readPasskeyRegistered();\n const target = returnUrl ?? readCurrentPath();\n\n return (\n <View\n style={styles.card}\n testID={withTestIdPrefix(AuthTestIds.passkeySettings, testIdPrefix)}\n >\n <Text style={styles.title}>{labels.title}</Text>\n <Text style={styles.subtitle}>{labels.description}</Text>\n <Text style={styles.helperText}>{labels.reauthHint}</Text>\n\n {justRegistered ? (\n <Text\n style={styles.successText}\n testID={withTestIdPrefix(AuthTestIds.passkeySettingsSuccess, testIdPrefix)}\n >\n {labels.registeredSuccess}\n </Text>\n ) : null}\n\n <TouchableOpacity\n accessibilityHint={labels.addHint}\n accessibilityLabel={labels.addButton}\n accessibilityRole=\"button\"\n style={styles.primaryButton}\n testID={withTestIdPrefix(AuthTestIds.passkeySettingsAdd, testIdPrefix)}\n onPress={(): void => startPasskeyRegistration(target)}\n >\n <Text style={styles.primaryButtonText}>{labels.addButton}</Text>\n </TouchableOpacity>\n </View>\n );\n}\n","/**\n * `useBffLoginConfig` — fetch the BFF login config once and expose it.\n *\n * The login surface only renders the methods the BFF actually has enabled, and\n * the device-PIN unlock gate only triggers when the per-device state says so.\n * Both come from `GET /bff/config`, which the supplied client reads and parses\n * (this hook is transport-agnostic — it delegates the fetch + parsing to the\n * client's `getLoginConfig`, mirroring kefi-web's `useBffConfig` shape).\n *\n * react-query-FREE by construction: plain `useState` + `useEffect`, never\n * `useQuery`. The login route group has no QueryClient provider, so this hook —\n * and every component built on it — must avoid react-query primitives.\n *\n * On a rejected `getLoginConfig` the hook falls back to a safe empty config\n * (no methods, registration off, empty device-state) so the surface stays\n * usable even when `/bff/config` is unreachable in dev. `loading` flips to\n * `false` as soon as the call settles.\n */\nimport { useEffect, useState } from 'react';\n\nimport type { BffLoginConfig, LoginConfigCapableClient } from './types';\n\n/** A safe, inert config used before the first fetch resolves / on failure. */\nconst EMPTY_CONFIG: BffLoginConfig = {\n methods: [],\n registrationEnabled: false,\n deviceState: {\n rememberedUsername: null,\n hasPin: false,\n pinDigits: null,\n preferredMethod: null,\n },\n};\n\n/** What {@link useBffLoginConfig} returns. */\nexport interface UseBffLoginConfigResult {\n /** The parsed login config; the empty fallback until the fetch resolves. */\n config: BffLoginConfig;\n /** `true` until the initial `getLoginConfig` call settles. */\n loading: boolean;\n}\n\n/**\n * Fetch `getLoginConfig()` once on mount and expose `{ config, loading }`. The\n * empty fallback config is used until the call resolves and on any failure. The\n * effect guards against a `setState` after the consumer unmounts mid-request.\n */\nexport function useBffLoginConfig(\n client: LoginConfigCapableClient,\n): UseBffLoginConfigResult {\n const [config, setConfig] = useState<BffLoginConfig>(EMPTY_CONFIG);\n const [loading, setLoading] = useState<boolean>(true);\n\n useEffect(() => {\n let active = true;\n client\n .getLoginConfig()\n .then((next) => {\n if (active) {\n setConfig(next);\n }\n })\n .catch(() => {\n if (active) {\n setConfig(EMPTY_CONFIG);\n }\n })\n .finally(() => {\n if (active) {\n setLoading(false);\n }\n });\n return (): void => {\n active = false;\n };\n }, [client]);\n\n return { config, loading };\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"]}
|