@dloizides/auth-web 1.4.0 → 1.5.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 CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactElement, ReactNode } from 'react';
2
- import { BffAuthClient, BffUser, BffLoginRequest, BffForgotPasswordRequest, BffResetPasswordRequest, BffOtpRequestResult, HttpClient } from '@dloizides/auth-client';
2
+ import { BffAuthClient, BffUser, HttpClient, BffLoginRequest, BffForgotPasswordRequest, BffResetPasswordRequest, BffOtpRequestResult } from '@dloizides/auth-client';
3
3
  export { BffAuthClient, BffAuthClientOptions, BffForgotPasswordRequest, BffLoginRequest, BffOtpRequestRequest, BffOtpRequestResult, BffOtpVerifyRequest, BffPinLoginRequest, BffRegisterRequest, BffResetPasswordRequest, BffUser, HttpClient, HttpRequest, HttpResponse, createFetchHttpClient } from '@dloizides/auth-client';
4
4
  import { UseMutationOptions, UseMutationResult } from '@tanstack/react-query';
5
5
 
@@ -232,6 +232,32 @@ interface PasskeySettingsLabels {
232
232
  /** Success line shown after returning from a registration. */
233
233
  registeredSuccess: string;
234
234
  }
235
+ /** Strings rendered by `<PreferredMethodSettingsCard>` — the cross-device default-method picker. */
236
+ interface PreferredMethodSettingsLabels {
237
+ title: string;
238
+ description: string;
239
+ /** The "no preference / ask me each time" option. */
240
+ noPreference: string;
241
+ /** Display name for the password method option. */
242
+ methodPassword: string;
243
+ /** Display name for the device-PIN method option. */
244
+ methodPin: string;
245
+ /** Display name for the passkey method option. */
246
+ methodPasskey: string;
247
+ /** Shown while a selection is being saved. */
248
+ saving: string;
249
+ /** Error shown when saving the preference fails. */
250
+ saveFailed: string;
251
+ }
252
+ /** Strings rendered by `<PreferredMethodHint>` — the login-screen "you usually sign in with…" line. */
253
+ interface PreferredMethodHintLabels {
254
+ /** Full sentence shown when the cached preference is password. */
255
+ password: string;
256
+ /** Full sentence shown when the cached preference is device-PIN. */
257
+ pin: string;
258
+ /** Full sentence shown when the cached preference is passkey. */
259
+ passkey: string;
260
+ }
235
261
  /** Strings rendered by `<ResetPasswordForm>`. */
236
262
  interface ResetPasswordFormLabels {
237
263
  title: string;
@@ -263,6 +289,8 @@ declare const DEFAULT_DEVICE_PIN_ENROLL_LABELS: DevicePinEnrollLabels;
263
289
  declare const DEFAULT_DEVICE_PIN_SETTINGS_LABELS: DevicePinSettingsLabels;
264
290
  declare const DEFAULT_PASSKEY_LOGIN_LABELS: PasskeyLoginLabels;
265
291
  declare const DEFAULT_PASSKEY_SETTINGS_LABELS: PasskeySettingsLabels;
292
+ declare const DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS: PreferredMethodSettingsLabels;
293
+ declare const DEFAULT_PREFERRED_METHOD_HINT_LABELS: PreferredMethodHintLabels;
266
294
  declare const DEFAULT_RESET_PASSWORD_LABELS: ResetPasswordFormLabels;
267
295
 
268
296
  /**
@@ -984,6 +1012,129 @@ interface PasskeySettingsCardProps {
984
1012
  /** Themeable authenticated passkey add card. */
985
1013
  declare function PasskeySettingsCard({ returnUrl, theme: themeProp, labels: labelsProp, testIdPrefix, }: Readonly<PasskeySettingsCardProps>): ReactElement;
986
1014
 
1015
+ /**
1016
+ * Same-origin client for the user's cross-device login-method preference
1017
+ * (unified-login D5). Unlike the device-PIN client (which targets the BFF's
1018
+ * own `/bff/*` auth endpoints), the preference lives in TenantService and is
1019
+ * reached THROUGH the BFF's YARP proxy:
1020
+ *
1021
+ * - GET `${baseUrl}/bff/api/{tenantsSegment}/api/v1/me/preferences`
1022
+ * → `{ ..., preferredLoginMethod }`
1023
+ * - PUT `${baseUrl}/bff/api/{tenantsSegment}/api/v1/me/login-method-preference`
1024
+ * body `{ method }`
1025
+ *
1026
+ * The BFF attaches the session's Bearer token to the proxied request, so both
1027
+ * calls require an authenticated session (the cookie travels via
1028
+ * `credentials: 'include'`). The PUT carries the `X-BFF-Csrf` header the BFF
1029
+ * anti-forgery middleware requires.
1030
+ *
1031
+ * react-query-FREE: plain `HttpClient` calls with `.then/.catch`. Portable
1032
+ * across every consumer (Expo RN-web apps AND the kefi/poueni surfaces).
1033
+ */
1034
+
1035
+ interface PreferencesClientOptions {
1036
+ /** Runtime-agnostic HTTP transport (wrap native `fetch` with `createFetchHttpClient`). */
1037
+ http: HttpClient;
1038
+ /**
1039
+ * BFF origin. Defaults to `''` (same-origin) — the production wiring. An
1040
+ * explicit origin is only useful for tests or a non-same-origin BFF.
1041
+ */
1042
+ baseUrl?: string;
1043
+ /**
1044
+ * The BFF YARP downstream segment that routes to TenantService. Defaults to
1045
+ * `'tenants'` — the segment every product BFF (katalogos / erevna / kefi)
1046
+ * uses for `tenant-api`.
1047
+ */
1048
+ tenantsSegment?: string;
1049
+ }
1050
+ /**
1051
+ * The narrow client the preferred-method UI depends on. Both methods NEVER
1052
+ * reject — they resolve a benign value on any failure so the settings card and
1053
+ * the post-login cache sync degrade gracefully rather than throwing.
1054
+ */
1055
+ interface PreferredMethodClient {
1056
+ /**
1057
+ * `GET /me/preferences` → the stored preferred login method, or `null` when
1058
+ * the user never picked one (or on any failure).
1059
+ */
1060
+ getPreferredLoginMethod(): Promise<string | null>;
1061
+ /**
1062
+ * `PUT /me/login-method-preference` — set (or clear, with `null`) the stored
1063
+ * preference. Resolves `true` on a 2xx, `false` on anything else.
1064
+ */
1065
+ setPreferredLoginMethod(method: string | null): Promise<boolean>;
1066
+ }
1067
+ /**
1068
+ * Build a same-origin {@link PreferredMethodClient}. With no `baseUrl` this is
1069
+ * the production wiring: same-origin, the session cookie travels automatically.
1070
+ */
1071
+ declare function createPreferencesClient(options: PreferencesClientOptions): PreferredMethodClient;
1072
+
1073
+ /**
1074
+ * The authenticated "Preferred sign-in method" settings card (unified-login D5).
1075
+ *
1076
+ * Mount on an authenticated settings/account surface alongside the device-PIN
1077
+ * and passkey cards. It lets the user pick which of their enabled login methods
1078
+ * they want emphasised on the login screen — stored SERVER-SIDE so the choice
1079
+ * follows them across devices. The login screen reads the device-local mirror
1080
+ * of this value (see `readCachedPreferredMethod` / `<PreferredMethodHint>`).
1081
+ *
1082
+ * `availableMethods` should be the BFF's advertised methods (from
1083
+ * `GET /bff/config` → `useBffLoginConfig().methods`) so the card only offers
1084
+ * methods this product actually supports. A "No preference" option always
1085
+ * appears. react-query-free: the persistence lives in `usePreferredMethodSetting`.
1086
+ */
1087
+
1088
+ interface PreferredMethodSettingsCardProps {
1089
+ /** The client exposing `getPreferredLoginMethod` + `setPreferredLoginMethod`. */
1090
+ client: PreferredMethodClient;
1091
+ /**
1092
+ * The login methods this BFF advertises (lowercase, e.g.
1093
+ * `['password', 'pin', 'passkey']`). Only these are offered, plus the
1094
+ * always-present "No preference" option.
1095
+ */
1096
+ availableMethods: readonly string[];
1097
+ /** Explicit theme; overrides any `<AuthThemeProvider>`. */
1098
+ theme?: AuthTheme;
1099
+ /** Localised copy. Partial — unspecified keys fall back to English defaults. */
1100
+ labels?: Partial<PreferredMethodSettingsLabels>;
1101
+ /** Prefix applied to every `testID`. */
1102
+ testIdPrefix?: string;
1103
+ /** Called whenever a save succeeds (`null` = no preference). */
1104
+ onChanged?: (method: string | null) => void;
1105
+ }
1106
+ /** Themeable authenticated preferred-method picker. */
1107
+ declare function PreferredMethodSettingsCard({ client, availableMethods, theme: themeProp, labels: labelsProp, testIdPrefix, onChanged, }: Readonly<PreferredMethodSettingsCardProps>): ReactElement;
1108
+
1109
+ /**
1110
+ * The login-screen "you usually sign in with…" hint (unified-login D5).
1111
+ *
1112
+ * Mount at the top of the login surface. Given the device-local cached
1113
+ * preferred method (`readCachedPreferredMethod()`), it renders a single
1114
+ * reassurance line naming that method. Renders NOTHING for an unknown / absent
1115
+ * method so the login screen stays clean for first-time visitors.
1116
+ *
1117
+ * No network, no state — pure presentation driven by the cached value the host
1118
+ * passes in. (The cache is seeded post-login by `syncPreferredMethodFromServer`.)
1119
+ */
1120
+
1121
+ interface PreferredMethodHintProps {
1122
+ /**
1123
+ * The cached preferred method (`'password'` | `'pin'` | `'passkey'`), or
1124
+ * `null`. Typically `readCachedPreferredMethod()`. An unknown / `null` value
1125
+ * renders nothing.
1126
+ */
1127
+ method: string | null;
1128
+ /** Explicit theme; overrides any `<AuthThemeProvider>`. */
1129
+ theme?: AuthTheme;
1130
+ /** Localised copy. Partial — unspecified keys fall back to English defaults. */
1131
+ labels?: Partial<PreferredMethodHintLabels>;
1132
+ /** Prefix applied to the `testID`. */
1133
+ testIdPrefix?: string;
1134
+ }
1135
+ /** Themeable login-screen preferred-method hint. Renders `null` when there is nothing to say. */
1136
+ declare function PreferredMethodHint({ method, theme: themeProp, labels: labelsProp, testIdPrefix, }: Readonly<PreferredMethodHintProps>): ReactElement | null;
1137
+
987
1138
  /**
988
1139
  * React context for the `AuthTheme`.
989
1140
  *
@@ -1084,6 +1235,10 @@ declare const AuthTestIds: {
1084
1235
  readonly passkeySettings: "auth-passkey-settings";
1085
1236
  readonly passkeySettingsAdd: "auth-passkey-settings-add";
1086
1237
  readonly passkeySettingsSuccess: "auth-passkey-settings-success";
1238
+ readonly preferredMethodSettings: "auth-preferred-method-settings";
1239
+ readonly preferredMethodSettingsOption: "auth-preferred-method-settings-option";
1240
+ readonly preferredMethodSettingsError: "auth-preferred-method-settings-error";
1241
+ readonly preferredMethodHint: "auth-preferred-method-hint";
1087
1242
  };
1088
1243
  /** Apply an optional prefix to a base test ID. */
1089
1244
  declare function withTestIdPrefix(baseId: string, prefix?: string): string;
@@ -1480,6 +1635,60 @@ declare function readPasskeyError(): PasskeyErrorCode | null;
1480
1635
  */
1481
1636
  declare function readPasskeyRegistered(): boolean;
1482
1637
 
1638
+ /**
1639
+ * Device-local cache of the user's preferred login method (unified-login D5).
1640
+ *
1641
+ * The preference is owned server-side (TenantService UserPreference), but the
1642
+ * LOGIN screen needs it BEFORE the user is authenticated — when no server call
1643
+ * is possible. So we cache it in `localStorage`, seeded after every successful
1644
+ * login (see {@link syncPreferredMethodFromServer}). A user who sets "passkey"
1645
+ * on device A will, after their first login on device B, see device B's login
1646
+ * screen prefer passkey too — cross-device sync with one-login lag.
1647
+ *
1648
+ * SSR-safe: every function no-ops / returns `null` when `localStorage` is
1649
+ * unavailable (server render, native, privacy modes that throw on access).
1650
+ */
1651
+ /**
1652
+ * Read the cached preferred login method, or `null` when none is cached / the
1653
+ * store is unavailable. Cheap + synchronous so the login screen can call it on
1654
+ * render.
1655
+ */
1656
+ declare function readCachedPreferredMethod(): string | null;
1657
+ /**
1658
+ * Write (or, with `null`, clear) the cached preferred login method. No-op when
1659
+ * the store is unavailable. Never throws.
1660
+ */
1661
+ declare function cachePreferredMethod(method: string | null): void;
1662
+ /** Clear the cached preferred login method (e.g. on logout). Never throws. */
1663
+ declare function clearCachedPreferredMethod(): void;
1664
+
1665
+ /**
1666
+ * Fetch the server-stored preferred login method and mirror it into the
1667
+ * device-local cache. Resolves to the value written (or `null`). Safe to
1668
+ * `void` — it swallows all errors.
1669
+ */
1670
+ declare function syncPreferredMethodFromServer(client: PreferredMethodClient): Promise<string | null>;
1671
+
1672
+ interface UsePreferredMethodSettingArgs {
1673
+ /** The client exposing `getPreferredLoginMethod` + `setPreferredLoginMethod`. */
1674
+ client: PreferredMethodClient;
1675
+ /** Called whenever a save succeeds (the new value, `null` = no preference). */
1676
+ onChanged?: (method: string | null) => void;
1677
+ }
1678
+ interface UsePreferredMethodSettingResult {
1679
+ /** `true` until the initial server load resolves. */
1680
+ loading: boolean;
1681
+ /** `true` while a selection is being persisted. */
1682
+ saving: boolean;
1683
+ /** `true` when the last save failed (cleared on the next `select`). */
1684
+ failed: boolean;
1685
+ /** The currently-selected method, or `null` for "no preference". */
1686
+ selected: string | null;
1687
+ /** Optimistically select a method (`null` clears the preference) and persist it. */
1688
+ select: (method: string | null) => void;
1689
+ }
1690
+ declare function usePreferredMethodSetting({ client, onChanged, }: UsePreferredMethodSettingArgs): UsePreferredMethodSettingResult;
1691
+
1483
1692
  /**
1484
1693
  * `createBffAuthClient` — the one-line wiring of a same-origin `BffAuthClient`.
1485
1694
  *
@@ -1615,4 +1824,4 @@ declare function validatePasswordPolicy(password: string): PasswordPolicyError[]
1615
1824
  /** `true` when the password satisfies every policy rule. */
1616
1825
  declare function isPasswordValid(password: string): boolean;
1617
1826
 
1618
- export { AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type BffDeviceState, type BffLoginConfig, type CreateBffAuthClientOptions, DEFAULT_DEVICE_PIN_ENROLL_LABELS, DEFAULT_DEVICE_PIN_SETTINGS_LABELS, DEFAULT_DEVICE_PIN_UNLOCK_LABELS, DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PASSKEY_LOGIN_LABELS, DEFAULT_PASSKEY_SETTINGS_LABELS, DEFAULT_PIN_LABELS, DEFAULT_RESET_PASSWORD_LABELS, DEVICE_PIN_ALLOWED_DIGITS, DEVICE_PIN_DEFAULT_DIGITS, type DevicePinCapableClient, type DevicePinDisableCapableClient, type DevicePinEnrollCapableClient, DevicePinEnrollErrorKey, DevicePinEnrollForm, type DevicePinEnrollFormProps, type DevicePinEnrollLabels, type DevicePinEnrollResult, DevicePinErrorKey, DevicePinInput, type DevicePinInputProps, DevicePinLengthPicker, type DevicePinLengthPickerProps, DevicePinOffer, type DevicePinOfferProps, DevicePinSettingsCard, type DevicePinSettingsCardProps, type DevicePinSettingsLabels, type DevicePinUnlockCapableClient, type DevicePinUnlockLabels, type DevicePinUnlockResult, DevicePinUnlockScreen, type DevicePinUnlockScreenProps, type DevicePinUnlockedUser, ForgotPasswordFields, type ForgotPasswordFieldsLabels, type ForgotPasswordFieldsProps, ForgotPasswordForm, type ForgotPasswordFormLabels, type ForgotPasswordFormProps, type LoginConfigCapableClient, LoginForm, type LoginFormLabels, type LoginFormProps, OtpForm, type OtpFormLabels, type OtpFormProps, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, type PasskeyErrorCode, PasskeyLoginButton, type PasskeyLoginButtonProps, type PasskeyLoginLabels, PasskeySettingsCard, type PasskeySettingsCardProps, type PasskeySettingsLabels, PasswordPolicyError, PinForm, type PinFormLabels, type PinFormProps, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffLoginConfigResult, type UseBffResetPasswordOptions, type UseDevicePinDisableArgs, type UseDevicePinDisableResult, type UseDevicePinEnrollArgs, type UseDevicePinEnrollResult, type UseDevicePinUnlockArgs, type UseDevicePinUnlockResult, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePinLoginOptions, type UsePinLoginResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, collectUserRoles, createBffAuthClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, readPasskeyError, readPasskeyRegistered, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePinLogin, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
1827
+ export { AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type BffDeviceState, type BffLoginConfig, type CreateBffAuthClientOptions, DEFAULT_DEVICE_PIN_ENROLL_LABELS, DEFAULT_DEVICE_PIN_SETTINGS_LABELS, DEFAULT_DEVICE_PIN_UNLOCK_LABELS, DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PASSKEY_LOGIN_LABELS, DEFAULT_PASSKEY_SETTINGS_LABELS, DEFAULT_PIN_LABELS, DEFAULT_PREFERRED_METHOD_HINT_LABELS, DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS, DEFAULT_RESET_PASSWORD_LABELS, DEVICE_PIN_ALLOWED_DIGITS, DEVICE_PIN_DEFAULT_DIGITS, type DevicePinCapableClient, type DevicePinDisableCapableClient, type DevicePinEnrollCapableClient, DevicePinEnrollErrorKey, DevicePinEnrollForm, type DevicePinEnrollFormProps, type DevicePinEnrollLabels, type DevicePinEnrollResult, DevicePinErrorKey, DevicePinInput, type DevicePinInputProps, DevicePinLengthPicker, type DevicePinLengthPickerProps, DevicePinOffer, type DevicePinOfferProps, DevicePinSettingsCard, type DevicePinSettingsCardProps, type DevicePinSettingsLabels, type DevicePinUnlockCapableClient, type DevicePinUnlockLabels, type DevicePinUnlockResult, DevicePinUnlockScreen, type DevicePinUnlockScreenProps, type DevicePinUnlockedUser, ForgotPasswordFields, type ForgotPasswordFieldsLabels, type ForgotPasswordFieldsProps, ForgotPasswordForm, type ForgotPasswordFormLabels, type ForgotPasswordFormProps, type LoginConfigCapableClient, LoginForm, type LoginFormLabels, type LoginFormProps, OtpForm, type OtpFormLabels, type OtpFormProps, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, type PasskeyErrorCode, PasskeyLoginButton, type PasskeyLoginButtonProps, type PasskeyLoginLabels, PasskeySettingsCard, type PasskeySettingsCardProps, type PasskeySettingsLabels, PasswordPolicyError, PinForm, type PinFormLabels, type PinFormProps, type PreferencesClientOptions, type PreferredMethodClient, PreferredMethodHint, type PreferredMethodHintLabels, type PreferredMethodHintProps, PreferredMethodSettingsCard, type PreferredMethodSettingsCardProps, type PreferredMethodSettingsLabels, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffLoginConfigResult, type UseBffResetPasswordOptions, type UseDevicePinDisableArgs, type UseDevicePinDisableResult, type UseDevicePinEnrollArgs, type UseDevicePinEnrollResult, type UseDevicePinUnlockArgs, type UseDevicePinUnlockResult, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePinLoginOptions, type UsePinLoginResult, type UsePreferredMethodSettingArgs, type UsePreferredMethodSettingResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePinLogin, usePreferredMethodSetting, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactElement, ReactNode } from 'react';
2
- import { BffAuthClient, BffUser, BffLoginRequest, BffForgotPasswordRequest, BffResetPasswordRequest, BffOtpRequestResult, HttpClient } from '@dloizides/auth-client';
2
+ import { BffAuthClient, BffUser, HttpClient, BffLoginRequest, BffForgotPasswordRequest, BffResetPasswordRequest, BffOtpRequestResult } from '@dloizides/auth-client';
3
3
  export { BffAuthClient, BffAuthClientOptions, BffForgotPasswordRequest, BffLoginRequest, BffOtpRequestRequest, BffOtpRequestResult, BffOtpVerifyRequest, BffPinLoginRequest, BffRegisterRequest, BffResetPasswordRequest, BffUser, HttpClient, HttpRequest, HttpResponse, createFetchHttpClient } from '@dloizides/auth-client';
4
4
  import { UseMutationOptions, UseMutationResult } from '@tanstack/react-query';
5
5
 
@@ -232,6 +232,32 @@ interface PasskeySettingsLabels {
232
232
  /** Success line shown after returning from a registration. */
233
233
  registeredSuccess: string;
234
234
  }
235
+ /** Strings rendered by `<PreferredMethodSettingsCard>` — the cross-device default-method picker. */
236
+ interface PreferredMethodSettingsLabels {
237
+ title: string;
238
+ description: string;
239
+ /** The "no preference / ask me each time" option. */
240
+ noPreference: string;
241
+ /** Display name for the password method option. */
242
+ methodPassword: string;
243
+ /** Display name for the device-PIN method option. */
244
+ methodPin: string;
245
+ /** Display name for the passkey method option. */
246
+ methodPasskey: string;
247
+ /** Shown while a selection is being saved. */
248
+ saving: string;
249
+ /** Error shown when saving the preference fails. */
250
+ saveFailed: string;
251
+ }
252
+ /** Strings rendered by `<PreferredMethodHint>` — the login-screen "you usually sign in with…" line. */
253
+ interface PreferredMethodHintLabels {
254
+ /** Full sentence shown when the cached preference is password. */
255
+ password: string;
256
+ /** Full sentence shown when the cached preference is device-PIN. */
257
+ pin: string;
258
+ /** Full sentence shown when the cached preference is passkey. */
259
+ passkey: string;
260
+ }
235
261
  /** Strings rendered by `<ResetPasswordForm>`. */
236
262
  interface ResetPasswordFormLabels {
237
263
  title: string;
@@ -263,6 +289,8 @@ declare const DEFAULT_DEVICE_PIN_ENROLL_LABELS: DevicePinEnrollLabels;
263
289
  declare const DEFAULT_DEVICE_PIN_SETTINGS_LABELS: DevicePinSettingsLabels;
264
290
  declare const DEFAULT_PASSKEY_LOGIN_LABELS: PasskeyLoginLabels;
265
291
  declare const DEFAULT_PASSKEY_SETTINGS_LABELS: PasskeySettingsLabels;
292
+ declare const DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS: PreferredMethodSettingsLabels;
293
+ declare const DEFAULT_PREFERRED_METHOD_HINT_LABELS: PreferredMethodHintLabels;
266
294
  declare const DEFAULT_RESET_PASSWORD_LABELS: ResetPasswordFormLabels;
267
295
 
268
296
  /**
@@ -984,6 +1012,129 @@ interface PasskeySettingsCardProps {
984
1012
  /** Themeable authenticated passkey add card. */
985
1013
  declare function PasskeySettingsCard({ returnUrl, theme: themeProp, labels: labelsProp, testIdPrefix, }: Readonly<PasskeySettingsCardProps>): ReactElement;
986
1014
 
1015
+ /**
1016
+ * Same-origin client for the user's cross-device login-method preference
1017
+ * (unified-login D5). Unlike the device-PIN client (which targets the BFF's
1018
+ * own `/bff/*` auth endpoints), the preference lives in TenantService and is
1019
+ * reached THROUGH the BFF's YARP proxy:
1020
+ *
1021
+ * - GET `${baseUrl}/bff/api/{tenantsSegment}/api/v1/me/preferences`
1022
+ * → `{ ..., preferredLoginMethod }`
1023
+ * - PUT `${baseUrl}/bff/api/{tenantsSegment}/api/v1/me/login-method-preference`
1024
+ * body `{ method }`
1025
+ *
1026
+ * The BFF attaches the session's Bearer token to the proxied request, so both
1027
+ * calls require an authenticated session (the cookie travels via
1028
+ * `credentials: 'include'`). The PUT carries the `X-BFF-Csrf` header the BFF
1029
+ * anti-forgery middleware requires.
1030
+ *
1031
+ * react-query-FREE: plain `HttpClient` calls with `.then/.catch`. Portable
1032
+ * across every consumer (Expo RN-web apps AND the kefi/poueni surfaces).
1033
+ */
1034
+
1035
+ interface PreferencesClientOptions {
1036
+ /** Runtime-agnostic HTTP transport (wrap native `fetch` with `createFetchHttpClient`). */
1037
+ http: HttpClient;
1038
+ /**
1039
+ * BFF origin. Defaults to `''` (same-origin) — the production wiring. An
1040
+ * explicit origin is only useful for tests or a non-same-origin BFF.
1041
+ */
1042
+ baseUrl?: string;
1043
+ /**
1044
+ * The BFF YARP downstream segment that routes to TenantService. Defaults to
1045
+ * `'tenants'` — the segment every product BFF (katalogos / erevna / kefi)
1046
+ * uses for `tenant-api`.
1047
+ */
1048
+ tenantsSegment?: string;
1049
+ }
1050
+ /**
1051
+ * The narrow client the preferred-method UI depends on. Both methods NEVER
1052
+ * reject — they resolve a benign value on any failure so the settings card and
1053
+ * the post-login cache sync degrade gracefully rather than throwing.
1054
+ */
1055
+ interface PreferredMethodClient {
1056
+ /**
1057
+ * `GET /me/preferences` → the stored preferred login method, or `null` when
1058
+ * the user never picked one (or on any failure).
1059
+ */
1060
+ getPreferredLoginMethod(): Promise<string | null>;
1061
+ /**
1062
+ * `PUT /me/login-method-preference` — set (or clear, with `null`) the stored
1063
+ * preference. Resolves `true` on a 2xx, `false` on anything else.
1064
+ */
1065
+ setPreferredLoginMethod(method: string | null): Promise<boolean>;
1066
+ }
1067
+ /**
1068
+ * Build a same-origin {@link PreferredMethodClient}. With no `baseUrl` this is
1069
+ * the production wiring: same-origin, the session cookie travels automatically.
1070
+ */
1071
+ declare function createPreferencesClient(options: PreferencesClientOptions): PreferredMethodClient;
1072
+
1073
+ /**
1074
+ * The authenticated "Preferred sign-in method" settings card (unified-login D5).
1075
+ *
1076
+ * Mount on an authenticated settings/account surface alongside the device-PIN
1077
+ * and passkey cards. It lets the user pick which of their enabled login methods
1078
+ * they want emphasised on the login screen — stored SERVER-SIDE so the choice
1079
+ * follows them across devices. The login screen reads the device-local mirror
1080
+ * of this value (see `readCachedPreferredMethod` / `<PreferredMethodHint>`).
1081
+ *
1082
+ * `availableMethods` should be the BFF's advertised methods (from
1083
+ * `GET /bff/config` → `useBffLoginConfig().methods`) so the card only offers
1084
+ * methods this product actually supports. A "No preference" option always
1085
+ * appears. react-query-free: the persistence lives in `usePreferredMethodSetting`.
1086
+ */
1087
+
1088
+ interface PreferredMethodSettingsCardProps {
1089
+ /** The client exposing `getPreferredLoginMethod` + `setPreferredLoginMethod`. */
1090
+ client: PreferredMethodClient;
1091
+ /**
1092
+ * The login methods this BFF advertises (lowercase, e.g.
1093
+ * `['password', 'pin', 'passkey']`). Only these are offered, plus the
1094
+ * always-present "No preference" option.
1095
+ */
1096
+ availableMethods: readonly string[];
1097
+ /** Explicit theme; overrides any `<AuthThemeProvider>`. */
1098
+ theme?: AuthTheme;
1099
+ /** Localised copy. Partial — unspecified keys fall back to English defaults. */
1100
+ labels?: Partial<PreferredMethodSettingsLabels>;
1101
+ /** Prefix applied to every `testID`. */
1102
+ testIdPrefix?: string;
1103
+ /** Called whenever a save succeeds (`null` = no preference). */
1104
+ onChanged?: (method: string | null) => void;
1105
+ }
1106
+ /** Themeable authenticated preferred-method picker. */
1107
+ declare function PreferredMethodSettingsCard({ client, availableMethods, theme: themeProp, labels: labelsProp, testIdPrefix, onChanged, }: Readonly<PreferredMethodSettingsCardProps>): ReactElement;
1108
+
1109
+ /**
1110
+ * The login-screen "you usually sign in with…" hint (unified-login D5).
1111
+ *
1112
+ * Mount at the top of the login surface. Given the device-local cached
1113
+ * preferred method (`readCachedPreferredMethod()`), it renders a single
1114
+ * reassurance line naming that method. Renders NOTHING for an unknown / absent
1115
+ * method so the login screen stays clean for first-time visitors.
1116
+ *
1117
+ * No network, no state — pure presentation driven by the cached value the host
1118
+ * passes in. (The cache is seeded post-login by `syncPreferredMethodFromServer`.)
1119
+ */
1120
+
1121
+ interface PreferredMethodHintProps {
1122
+ /**
1123
+ * The cached preferred method (`'password'` | `'pin'` | `'passkey'`), or
1124
+ * `null`. Typically `readCachedPreferredMethod()`. An unknown / `null` value
1125
+ * renders nothing.
1126
+ */
1127
+ method: string | null;
1128
+ /** Explicit theme; overrides any `<AuthThemeProvider>`. */
1129
+ theme?: AuthTheme;
1130
+ /** Localised copy. Partial — unspecified keys fall back to English defaults. */
1131
+ labels?: Partial<PreferredMethodHintLabels>;
1132
+ /** Prefix applied to the `testID`. */
1133
+ testIdPrefix?: string;
1134
+ }
1135
+ /** Themeable login-screen preferred-method hint. Renders `null` when there is nothing to say. */
1136
+ declare function PreferredMethodHint({ method, theme: themeProp, labels: labelsProp, testIdPrefix, }: Readonly<PreferredMethodHintProps>): ReactElement | null;
1137
+
987
1138
  /**
988
1139
  * React context for the `AuthTheme`.
989
1140
  *
@@ -1084,6 +1235,10 @@ declare const AuthTestIds: {
1084
1235
  readonly passkeySettings: "auth-passkey-settings";
1085
1236
  readonly passkeySettingsAdd: "auth-passkey-settings-add";
1086
1237
  readonly passkeySettingsSuccess: "auth-passkey-settings-success";
1238
+ readonly preferredMethodSettings: "auth-preferred-method-settings";
1239
+ readonly preferredMethodSettingsOption: "auth-preferred-method-settings-option";
1240
+ readonly preferredMethodSettingsError: "auth-preferred-method-settings-error";
1241
+ readonly preferredMethodHint: "auth-preferred-method-hint";
1087
1242
  };
1088
1243
  /** Apply an optional prefix to a base test ID. */
1089
1244
  declare function withTestIdPrefix(baseId: string, prefix?: string): string;
@@ -1480,6 +1635,60 @@ declare function readPasskeyError(): PasskeyErrorCode | null;
1480
1635
  */
1481
1636
  declare function readPasskeyRegistered(): boolean;
1482
1637
 
1638
+ /**
1639
+ * Device-local cache of the user's preferred login method (unified-login D5).
1640
+ *
1641
+ * The preference is owned server-side (TenantService UserPreference), but the
1642
+ * LOGIN screen needs it BEFORE the user is authenticated — when no server call
1643
+ * is possible. So we cache it in `localStorage`, seeded after every successful
1644
+ * login (see {@link syncPreferredMethodFromServer}). A user who sets "passkey"
1645
+ * on device A will, after their first login on device B, see device B's login
1646
+ * screen prefer passkey too — cross-device sync with one-login lag.
1647
+ *
1648
+ * SSR-safe: every function no-ops / returns `null` when `localStorage` is
1649
+ * unavailable (server render, native, privacy modes that throw on access).
1650
+ */
1651
+ /**
1652
+ * Read the cached preferred login method, or `null` when none is cached / the
1653
+ * store is unavailable. Cheap + synchronous so the login screen can call it on
1654
+ * render.
1655
+ */
1656
+ declare function readCachedPreferredMethod(): string | null;
1657
+ /**
1658
+ * Write (or, with `null`, clear) the cached preferred login method. No-op when
1659
+ * the store is unavailable. Never throws.
1660
+ */
1661
+ declare function cachePreferredMethod(method: string | null): void;
1662
+ /** Clear the cached preferred login method (e.g. on logout). Never throws. */
1663
+ declare function clearCachedPreferredMethod(): void;
1664
+
1665
+ /**
1666
+ * Fetch the server-stored preferred login method and mirror it into the
1667
+ * device-local cache. Resolves to the value written (or `null`). Safe to
1668
+ * `void` — it swallows all errors.
1669
+ */
1670
+ declare function syncPreferredMethodFromServer(client: PreferredMethodClient): Promise<string | null>;
1671
+
1672
+ interface UsePreferredMethodSettingArgs {
1673
+ /** The client exposing `getPreferredLoginMethod` + `setPreferredLoginMethod`. */
1674
+ client: PreferredMethodClient;
1675
+ /** Called whenever a save succeeds (the new value, `null` = no preference). */
1676
+ onChanged?: (method: string | null) => void;
1677
+ }
1678
+ interface UsePreferredMethodSettingResult {
1679
+ /** `true` until the initial server load resolves. */
1680
+ loading: boolean;
1681
+ /** `true` while a selection is being persisted. */
1682
+ saving: boolean;
1683
+ /** `true` when the last save failed (cleared on the next `select`). */
1684
+ failed: boolean;
1685
+ /** The currently-selected method, or `null` for "no preference". */
1686
+ selected: string | null;
1687
+ /** Optimistically select a method (`null` clears the preference) and persist it. */
1688
+ select: (method: string | null) => void;
1689
+ }
1690
+ declare function usePreferredMethodSetting({ client, onChanged, }: UsePreferredMethodSettingArgs): UsePreferredMethodSettingResult;
1691
+
1483
1692
  /**
1484
1693
  * `createBffAuthClient` — the one-line wiring of a same-origin `BffAuthClient`.
1485
1694
  *
@@ -1615,4 +1824,4 @@ declare function validatePasswordPolicy(password: string): PasswordPolicyError[]
1615
1824
  /** `true` when the password satisfies every policy rule. */
1616
1825
  declare function isPasswordValid(password: string): boolean;
1617
1826
 
1618
- export { AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type BffDeviceState, type BffLoginConfig, type CreateBffAuthClientOptions, DEFAULT_DEVICE_PIN_ENROLL_LABELS, DEFAULT_DEVICE_PIN_SETTINGS_LABELS, DEFAULT_DEVICE_PIN_UNLOCK_LABELS, DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PASSKEY_LOGIN_LABELS, DEFAULT_PASSKEY_SETTINGS_LABELS, DEFAULT_PIN_LABELS, DEFAULT_RESET_PASSWORD_LABELS, DEVICE_PIN_ALLOWED_DIGITS, DEVICE_PIN_DEFAULT_DIGITS, type DevicePinCapableClient, type DevicePinDisableCapableClient, type DevicePinEnrollCapableClient, DevicePinEnrollErrorKey, DevicePinEnrollForm, type DevicePinEnrollFormProps, type DevicePinEnrollLabels, type DevicePinEnrollResult, DevicePinErrorKey, DevicePinInput, type DevicePinInputProps, DevicePinLengthPicker, type DevicePinLengthPickerProps, DevicePinOffer, type DevicePinOfferProps, DevicePinSettingsCard, type DevicePinSettingsCardProps, type DevicePinSettingsLabels, type DevicePinUnlockCapableClient, type DevicePinUnlockLabels, type DevicePinUnlockResult, DevicePinUnlockScreen, type DevicePinUnlockScreenProps, type DevicePinUnlockedUser, ForgotPasswordFields, type ForgotPasswordFieldsLabels, type ForgotPasswordFieldsProps, ForgotPasswordForm, type ForgotPasswordFormLabels, type ForgotPasswordFormProps, type LoginConfigCapableClient, LoginForm, type LoginFormLabels, type LoginFormProps, OtpForm, type OtpFormLabels, type OtpFormProps, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, type PasskeyErrorCode, PasskeyLoginButton, type PasskeyLoginButtonProps, type PasskeyLoginLabels, PasskeySettingsCard, type PasskeySettingsCardProps, type PasskeySettingsLabels, PasswordPolicyError, PinForm, type PinFormLabels, type PinFormProps, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffLoginConfigResult, type UseBffResetPasswordOptions, type UseDevicePinDisableArgs, type UseDevicePinDisableResult, type UseDevicePinEnrollArgs, type UseDevicePinEnrollResult, type UseDevicePinUnlockArgs, type UseDevicePinUnlockResult, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePinLoginOptions, type UsePinLoginResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, collectUserRoles, createBffAuthClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, readPasskeyError, readPasskeyRegistered, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePinLogin, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
1827
+ export { AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type BffDeviceState, type BffLoginConfig, type CreateBffAuthClientOptions, DEFAULT_DEVICE_PIN_ENROLL_LABELS, DEFAULT_DEVICE_PIN_SETTINGS_LABELS, DEFAULT_DEVICE_PIN_UNLOCK_LABELS, DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PASSKEY_LOGIN_LABELS, DEFAULT_PASSKEY_SETTINGS_LABELS, DEFAULT_PIN_LABELS, DEFAULT_PREFERRED_METHOD_HINT_LABELS, DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS, DEFAULT_RESET_PASSWORD_LABELS, DEVICE_PIN_ALLOWED_DIGITS, DEVICE_PIN_DEFAULT_DIGITS, type DevicePinCapableClient, type DevicePinDisableCapableClient, type DevicePinEnrollCapableClient, DevicePinEnrollErrorKey, DevicePinEnrollForm, type DevicePinEnrollFormProps, type DevicePinEnrollLabels, type DevicePinEnrollResult, DevicePinErrorKey, DevicePinInput, type DevicePinInputProps, DevicePinLengthPicker, type DevicePinLengthPickerProps, DevicePinOffer, type DevicePinOfferProps, DevicePinSettingsCard, type DevicePinSettingsCardProps, type DevicePinSettingsLabels, type DevicePinUnlockCapableClient, type DevicePinUnlockLabels, type DevicePinUnlockResult, DevicePinUnlockScreen, type DevicePinUnlockScreenProps, type DevicePinUnlockedUser, ForgotPasswordFields, type ForgotPasswordFieldsLabels, type ForgotPasswordFieldsProps, ForgotPasswordForm, type ForgotPasswordFormLabels, type ForgotPasswordFormProps, type LoginConfigCapableClient, LoginForm, type LoginFormLabels, type LoginFormProps, OtpForm, type OtpFormLabels, type OtpFormProps, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, type PasskeyErrorCode, PasskeyLoginButton, type PasskeyLoginButtonProps, type PasskeyLoginLabels, PasskeySettingsCard, type PasskeySettingsCardProps, type PasskeySettingsLabels, PasswordPolicyError, PinForm, type PinFormLabels, type PinFormProps, type PreferencesClientOptions, type PreferredMethodClient, PreferredMethodHint, type PreferredMethodHintLabels, type PreferredMethodHintProps, PreferredMethodSettingsCard, type PreferredMethodSettingsCardProps, type PreferredMethodSettingsLabels, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffLoginConfigResult, type UseBffResetPasswordOptions, type UseDevicePinDisableArgs, type UseDevicePinDisableResult, type UseDevicePinEnrollArgs, type UseDevicePinEnrollResult, type UseDevicePinUnlockArgs, type UseDevicePinUnlockResult, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePinLoginOptions, type UsePinLoginResult, type UsePreferredMethodSettingArgs, type UsePreferredMethodSettingResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePinLogin, usePreferredMethodSetting, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };