@dloizides/auth-web 1.17.0 → 1.18.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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.18.0
4
+
5
+ **Registration form, extracted from katalogos-web and erevna-web.** Additive.
6
+
7
+ - `<RegisterForm>`: themeable sign-up form with seven fields plus the off-screen `website` honeypot.
8
+ Props: `onSubmit(values)` (the app builds the request and calls its BFF), `onSuccess(result)`,
9
+ `onError(code)`, `onSubmitAttempt`, `passwordPolicy`, `labels`, `theme`, `footer`, `testIdPrefix`.
10
+ - `useRegisterForm({ onSubmit, passwordPolicy })` returns `{ state, setField, submit, isSubmitting, error }`.
11
+ A filled honeypot is refused with `Failed` and no network call; a second press mid-submit returns `InFlight`.
12
+ - `RegisterErrorCode` (const enum) and `mapRegisterErrorCode(error)` decode `USERNAME_TAKEN`, `EMAIL_TAKEN`,
13
+ `REALM_REQUIRED`, `REALM_INVALID`. No error copy in the package; apps map the code to FM() keys.
14
+ - `RegisterTestIds` keep the unprefixed `register-*` values the E2E suites select on.
15
+ - Also exported: `isRegisterPasswordStrong`, `DEFAULT_REGISTER_LABELS`, the `Register*` types.
16
+
3
17
  ## 1.17.0
4
18
 
5
19
  **Multi-account demo login — the `<DemoCredentialsHint>` now renders one labelled,
package/dist/index.d.mts CHANGED
@@ -507,6 +507,94 @@ interface AccountSettingsLabels {
507
507
  }
508
508
  declare const DEFAULT_ACCOUNT_SETTINGS_LABELS: AccountSettingsLabels;
509
509
 
510
+ /**
511
+ * The discrete failure states the registration flow can report.
512
+ *
513
+ * Each member is a stable key the consuming app maps onto a localised message
514
+ * (`FM('register.usernameTaken')`, …). The package never renders copy for these
515
+ * itself — it ships no translations.
516
+ */
517
+ declare const enum RegisterErrorCode {
518
+ /** A required field (anything but the honeypot) is empty. */
519
+ MissingFields = "missingFields",
520
+ /** The email does not look like an address. */
521
+ InvalidEmail = "invalidEmail",
522
+ /** The password fails the active password policy. */
523
+ WeakPassword = "weakPassword",
524
+ /** The confirm field does not match the password. */
525
+ PasswordMismatch = "passwordMismatch",
526
+ /** The server reported `USERNAME_TAKEN`. */
527
+ UsernameTaken = "usernameTaken",
528
+ /** The server reported `EMAIL_TAKEN`. */
529
+ EmailTaken = "emailTaken",
530
+ /** The server reported `REALM_REQUIRED` or `REALM_INVALID`. */
531
+ RealmInvalid = "realmInvalid",
532
+ /** The server rejected the request with an unrecognised message. */
533
+ ValidationFailed = "validationFailed",
534
+ /** Generic failure: network error, empty message, or a filled honeypot (never revealed). */
535
+ Failed = "failed",
536
+ /** A submit is already running; the second press was ignored. Do not surface it. */
537
+ InFlight = "inFlight"
538
+ }
539
+
540
+ /** Every value the registration form holds. */
541
+ interface RegisterFormValues {
542
+ firstName: string;
543
+ lastName: string;
544
+ username: string;
545
+ email: string;
546
+ password: string;
547
+ confirmPassword: string;
548
+ tenantName: string;
549
+ /**
550
+ * Honeypot (bot protection, no external captcha). Rendered as an off-screen,
551
+ * aria-hidden, non-focusable input a human never fills. A non-empty value
552
+ * means a bot: the hook refuses silently, and the shared BFF rejects it too
553
+ * for bots that POST directly. Never part of the required-field check.
554
+ */
555
+ website: string;
556
+ }
557
+ type RegisterField = keyof RegisterFormValues;
558
+ /** The fields a human sees (everything except the honeypot). */
559
+ type RegisterInputField = Exclude<RegisterField, 'website'>;
560
+ /**
561
+ * What `onSubmit` receives: trimmed values with `confirmPassword` dropped. The
562
+ * honeypot is kept (empty for real users) so the BFF can enforce it as well.
563
+ */
564
+ type RegisterSubmitValues = Omit<RegisterFormValues, 'confirmPassword'>;
565
+ /** `true` when the password is acceptable. */
566
+ type RegisterPasswordPolicy = (password: string) => boolean;
567
+ type RegisterSubmitOutcome<TResult> = {
568
+ ok: true;
569
+ result: TResult;
570
+ } | {
571
+ ok: false;
572
+ error: RegisterErrorCode;
573
+ };
574
+
575
+ /** Copy for one visible registration input. */
576
+ interface RegisterFieldLabels {
577
+ /** Visible label above the input. */
578
+ label: string;
579
+ placeholder: string;
580
+ /** `accessibilityHint` for the input. */
581
+ hint: string;
582
+ /** `accessibilityLabel` for the input. */
583
+ inputLabel: string;
584
+ }
585
+ /** Strings rendered by `<RegisterForm>`. Error copy is not here: the app maps `RegisterErrorCode`. */
586
+ interface RegisterFormLabels {
587
+ title: string;
588
+ subtitle: string;
589
+ submit: string;
590
+ /** `accessibilityHint` for the submit button. */
591
+ submitHint: string;
592
+ /** `accessibilityLabel` for the submit button while the request runs. */
593
+ submitting: string;
594
+ fields: Record<RegisterInputField, RegisterFieldLabels>;
595
+ }
596
+ declare const DEFAULT_REGISTER_LABELS: RegisterFormLabels;
597
+
510
598
  /**
511
599
  * Who asked for a prefill — the difference between "the user requested this" and
512
600
  * "the app offered it".
@@ -2355,6 +2443,95 @@ declare function resolveAccountList(accounts?: readonly DemoAccount[] | null): D
2355
2443
  */
2356
2444
  declare function resolveDemoAccounts(credentials?: DemoCredentials | null): DemoAccount[];
2357
2445
 
2446
+ /**
2447
+ * `<RegisterForm>` — the ready-made, themeable sign-up form.
2448
+ *
2449
+ * Extracted from the identical katalogos-web and erevna-web register screens.
2450
+ * The app keeps what differs per product: the request it sends (`onSubmit`, which
2451
+ * carries the realm and verify-URL template), where to go afterwards
2452
+ * (`onSuccess`), and the localised copy (`labels`, plus mapping a
2453
+ * `RegisterErrorCode` to a message in `onError`).
2454
+ */
2455
+
2456
+ interface RegisterFormProps<TResult> {
2457
+ /** Send the registration (build the request, call the BFF). Throw on failure. */
2458
+ onSubmit: (values: RegisterSubmitValues) => Promise<TResult>;
2459
+ /** Called with whatever `onSubmit` resolved to. */
2460
+ onSuccess: (result: TResult) => void;
2461
+ /** Called with the failure code; map it to localised copy. */
2462
+ onError?: (error: RegisterErrorCode) => void;
2463
+ /** Called on every submit press, before validation (e.g. a "signup started" event). */
2464
+ onSubmitAttempt?: () => void;
2465
+ /** Password rule. Defaults to `isRegisterPasswordStrong`. */
2466
+ passwordPolicy?: RegisterPasswordPolicy;
2467
+ /** Localised copy. Partial: unspecified top-level keys fall back to English defaults. */
2468
+ labels?: Partial<RegisterFormLabels>;
2469
+ /** Explicit theme; overrides any `<AuthThemeProvider>`. */
2470
+ theme?: AuthTheme;
2471
+ /** Rendered under the submit button (e.g. "Already have an account?"). */
2472
+ footer?: ReactNode;
2473
+ /** Prefix applied to every `testID`. */
2474
+ testIdPrefix?: string;
2475
+ }
2476
+ /** Themeable registration form built on `useRegisterForm`. */
2477
+ declare function RegisterForm<TResult>({ onSubmit, onSuccess, onError, onSubmitAttempt, passwordPolicy, labels: labelsProp, theme: themeProp, footer, testIdPrefix, }: Readonly<RegisterFormProps<TResult>>): ReactElement;
2478
+
2479
+ /**
2480
+ * `testID` values for `<RegisterForm>`.
2481
+ *
2482
+ * Kept apart from `AuthTestIds` on purpose: these are the unprefixed
2483
+ * `register-*` IDs katalogos-web and erevna-web rendered before the extraction,
2484
+ * and the E2E suites (`E2ETests/shared/testIds.ts`,
2485
+ * `E2ETests/helpers/katalogos-signup-helpers.ts`) already select on them.
2486
+ * Changing a value here breaks those suites.
2487
+ *
2488
+ * `sonarjs/no-hardcoded-passwords` is disabled for this file: it flags the
2489
+ * `passwordInput` keys, but every value here is a UI test ID, not a credential.
2490
+ */
2491
+ declare const RegisterTestIds: {
2492
+ readonly form: "register-form";
2493
+ readonly firstNameInput: "register-first-name-input";
2494
+ readonly lastNameInput: "register-last-name-input";
2495
+ readonly usernameInput: "register-username-input";
2496
+ readonly emailInput: "register-email-input";
2497
+ readonly passwordInput: "register-password-input";
2498
+ readonly confirmPasswordInput: "register-confirm-password-input";
2499
+ readonly tenantNameInput: "register-tenant-name-input";
2500
+ readonly submitButton: "register-submit-button";
2501
+ readonly websiteInput: "register-website";
2502
+ };
2503
+
2504
+ interface UseRegisterFormArgs<TResult> {
2505
+ /** Send the registration. Throw on failure; the message is decoded to a code. */
2506
+ onSubmit: (values: RegisterSubmitValues) => Promise<TResult>;
2507
+ /** Password rule. Defaults to {@link isRegisterPasswordStrong}. */
2508
+ passwordPolicy?: RegisterPasswordPolicy;
2509
+ }
2510
+ interface UseRegisterFormResult<TResult> {
2511
+ state: RegisterFormValues;
2512
+ setField: (field: RegisterField, value: string) => void;
2513
+ submit: () => Promise<RegisterSubmitOutcome<TResult>>;
2514
+ isSubmitting: boolean;
2515
+ /** The last failure, cleared when a submit starts. */
2516
+ error: RegisterErrorCode | null;
2517
+ }
2518
+ /** Headless registration form logic. */
2519
+ declare function useRegisterForm<TResult>({ onSubmit, passwordPolicy, }: UseRegisterFormArgs<TResult>): UseRegisterFormResult<TResult>;
2520
+
2521
+ /**
2522
+ * Pure registration helpers: trimming, client-side validation and decoding of a
2523
+ * TenantService failure (surfaced by the BFF as a plain error whose message
2524
+ * carries an error-code substring).
2525
+ *
2526
+ * Merged from the katalogos-web and erevna-web `useRegisterForm` copies, which
2527
+ * were identical apart from katalogos' honeypot.
2528
+ */
2529
+
2530
+ /** The default password rule: 8+ characters with a letter, a digit and a special character. */
2531
+ declare function isRegisterPasswordStrong(password: string): boolean;
2532
+ /** Decode a thrown registration failure into a {@link RegisterErrorCode}. */
2533
+ declare function mapRegisterErrorCode(error: unknown): RegisterErrorCode;
2534
+
2358
2535
  /**
2359
2536
  * `createBffAuthClient` — the one-line wiring of a same-origin `BffAuthClient`.
2360
2537
  *
@@ -2644,4 +2821,4 @@ interface UseChangePasswordResult {
2644
2821
  }
2645
2822
  declare function useChangePassword({ client, onChanged, }: UseChangePasswordArgs): UseChangePasswordResult;
2646
2823
 
2647
- export { type AccountSettingsChangePasswordConfig, type AccountSettingsDevicePinConfig, type AccountSettingsLabels, type AccountSettingsPasskeysConfig, type AccountSettingsPreferredMethodConfig, AccountSettingsScreen, type AccountSettingsScreenProps, AuthScreen, type AuthScreenProps, AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type BffDeviceState, type BffLoginConfig, type BffLogoutClient, CHANGE_PASSWORD_ENDPOINT, type ChangePasswordCapableClient, ChangePasswordCard, type ChangePasswordCardProps, ChangePasswordErrorKey, type ChangePasswordRequest, type ChangePasswordResult, type CreateBffAuthClientOptions, type CreateBffChangePasswordClientOptions, DEFAULT_ACCOUNT_SETTINGS_LABELS, DEFAULT_AUTH_CARD_MAX_WIDTH, DEFAULT_DEMO_CREDENTIALS_HINT_LABELS, 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, DemoCredentialsHint, type DemoCredentialsHintLabels, type DemoCredentialsHintProps, DemoCredentialsHintVariant, type DemoCredentialsHintWiring, type DemoCredentialsLoginFormProps, 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, PasskeyCeremonyMode, PasskeyCeremonyStatus, type PasskeyErrorCode, PasskeyLoginButton, type PasskeyLoginButtonProps, type PasskeyLoginLabels, PasskeySettingsCard, type PasskeySettingsCardProps, type PasskeySettingsLabels, PasswordPolicyError, type PerformBffLogoutOptions, PinForm, type PinFormLabels, type PinFormProps, type PreferencesClientOptions, type PreferredMethodClient, PreferredMethodHint, type PreferredMethodHintLabels, type PreferredMethodHintProps, PreferredMethodSettingsCard, type PreferredMethodSettingsCardProps, type PreferredMethodSettingsLabels, PrefillIntent, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffLoginConfigResult, type UseBffResetPasswordOptions, type UseChangePasswordArgs, type UseChangePasswordResult, type UseDemoCredentialsOptions, type UseDemoCredentialsResult, type UseDevicePinDisableArgs, type UseDevicePinDisableResult, type UseDevicePinEnrollArgs, type UseDevicePinEnrollResult, type UseDevicePinUnlockArgs, type UseDevicePinUnlockResult, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePasskeyCeremonyOptions, type UsePasskeyCeremonyResult, type UsePinLoginOptions, type UsePinLoginResult, type UsePreferredMethodSettingArgs, type UsePreferredMethodSettingResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createBffChangePasswordClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, performBffLogout, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolveAccessibleRoutes, resolveAccountList, resolveDemoAccounts, resolveDemoCredentials, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useChangePassword, useDemoCredentials, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePasskeyCeremony, usePinLogin, usePreferredMethodSetting, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
2824
+ export { type AccountSettingsChangePasswordConfig, type AccountSettingsDevicePinConfig, type AccountSettingsLabels, type AccountSettingsPasskeysConfig, type AccountSettingsPreferredMethodConfig, AccountSettingsScreen, type AccountSettingsScreenProps, AuthScreen, type AuthScreenProps, AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type BffDeviceState, type BffLoginConfig, type BffLogoutClient, CHANGE_PASSWORD_ENDPOINT, type ChangePasswordCapableClient, ChangePasswordCard, type ChangePasswordCardProps, ChangePasswordErrorKey, type ChangePasswordRequest, type ChangePasswordResult, type CreateBffAuthClientOptions, type CreateBffChangePasswordClientOptions, DEFAULT_ACCOUNT_SETTINGS_LABELS, DEFAULT_AUTH_CARD_MAX_WIDTH, DEFAULT_DEMO_CREDENTIALS_HINT_LABELS, 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_REGISTER_LABELS, DEFAULT_RESET_PASSWORD_LABELS, DEVICE_PIN_ALLOWED_DIGITS, DEVICE_PIN_DEFAULT_DIGITS, DemoCredentialsHint, type DemoCredentialsHintLabels, type DemoCredentialsHintProps, DemoCredentialsHintVariant, type DemoCredentialsHintWiring, type DemoCredentialsLoginFormProps, 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, PasskeyCeremonyMode, PasskeyCeremonyStatus, type PasskeyErrorCode, PasskeyLoginButton, type PasskeyLoginButtonProps, type PasskeyLoginLabels, PasskeySettingsCard, type PasskeySettingsCardProps, type PasskeySettingsLabels, PasswordPolicyError, type PerformBffLogoutOptions, PinForm, type PinFormLabels, type PinFormProps, type PreferencesClientOptions, type PreferredMethodClient, PreferredMethodHint, type PreferredMethodHintLabels, type PreferredMethodHintProps, PreferredMethodSettingsCard, type PreferredMethodSettingsCardProps, type PreferredMethodSettingsLabels, PrefillIntent, RegisterErrorCode, type RegisterField, type RegisterFieldLabels, RegisterForm, type RegisterFormLabels, type RegisterFormProps, type RegisterFormValues, type RegisterInputField, type RegisterPasswordPolicy, type RegisterSubmitOutcome, type RegisterSubmitValues, RegisterTestIds, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffLoginConfigResult, type UseBffResetPasswordOptions, type UseChangePasswordArgs, type UseChangePasswordResult, type UseDemoCredentialsOptions, type UseDemoCredentialsResult, type UseDevicePinDisableArgs, type UseDevicePinDisableResult, type UseDevicePinEnrollArgs, type UseDevicePinEnrollResult, type UseDevicePinUnlockArgs, type UseDevicePinUnlockResult, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePasskeyCeremonyOptions, type UsePasskeyCeremonyResult, type UsePinLoginOptions, type UsePinLoginResult, type UsePreferredMethodSettingArgs, type UsePreferredMethodSettingResult, type UseRegisterFormArgs, type UseRegisterFormResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createBffChangePasswordClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isRegisterPasswordStrong, isValidForgotPasswordEmail, mapRegisterErrorCode, performBffLogout, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolveAccessibleRoutes, resolveAccountList, resolveDemoAccounts, resolveDemoCredentials, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useChangePassword, useDemoCredentials, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePasskeyCeremony, usePinLogin, usePreferredMethodSetting, useRegisterForm, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
package/dist/index.d.ts CHANGED
@@ -507,6 +507,94 @@ interface AccountSettingsLabels {
507
507
  }
508
508
  declare const DEFAULT_ACCOUNT_SETTINGS_LABELS: AccountSettingsLabels;
509
509
 
510
+ /**
511
+ * The discrete failure states the registration flow can report.
512
+ *
513
+ * Each member is a stable key the consuming app maps onto a localised message
514
+ * (`FM('register.usernameTaken')`, …). The package never renders copy for these
515
+ * itself — it ships no translations.
516
+ */
517
+ declare const enum RegisterErrorCode {
518
+ /** A required field (anything but the honeypot) is empty. */
519
+ MissingFields = "missingFields",
520
+ /** The email does not look like an address. */
521
+ InvalidEmail = "invalidEmail",
522
+ /** The password fails the active password policy. */
523
+ WeakPassword = "weakPassword",
524
+ /** The confirm field does not match the password. */
525
+ PasswordMismatch = "passwordMismatch",
526
+ /** The server reported `USERNAME_TAKEN`. */
527
+ UsernameTaken = "usernameTaken",
528
+ /** The server reported `EMAIL_TAKEN`. */
529
+ EmailTaken = "emailTaken",
530
+ /** The server reported `REALM_REQUIRED` or `REALM_INVALID`. */
531
+ RealmInvalid = "realmInvalid",
532
+ /** The server rejected the request with an unrecognised message. */
533
+ ValidationFailed = "validationFailed",
534
+ /** Generic failure: network error, empty message, or a filled honeypot (never revealed). */
535
+ Failed = "failed",
536
+ /** A submit is already running; the second press was ignored. Do not surface it. */
537
+ InFlight = "inFlight"
538
+ }
539
+
540
+ /** Every value the registration form holds. */
541
+ interface RegisterFormValues {
542
+ firstName: string;
543
+ lastName: string;
544
+ username: string;
545
+ email: string;
546
+ password: string;
547
+ confirmPassword: string;
548
+ tenantName: string;
549
+ /**
550
+ * Honeypot (bot protection, no external captcha). Rendered as an off-screen,
551
+ * aria-hidden, non-focusable input a human never fills. A non-empty value
552
+ * means a bot: the hook refuses silently, and the shared BFF rejects it too
553
+ * for bots that POST directly. Never part of the required-field check.
554
+ */
555
+ website: string;
556
+ }
557
+ type RegisterField = keyof RegisterFormValues;
558
+ /** The fields a human sees (everything except the honeypot). */
559
+ type RegisterInputField = Exclude<RegisterField, 'website'>;
560
+ /**
561
+ * What `onSubmit` receives: trimmed values with `confirmPassword` dropped. The
562
+ * honeypot is kept (empty for real users) so the BFF can enforce it as well.
563
+ */
564
+ type RegisterSubmitValues = Omit<RegisterFormValues, 'confirmPassword'>;
565
+ /** `true` when the password is acceptable. */
566
+ type RegisterPasswordPolicy = (password: string) => boolean;
567
+ type RegisterSubmitOutcome<TResult> = {
568
+ ok: true;
569
+ result: TResult;
570
+ } | {
571
+ ok: false;
572
+ error: RegisterErrorCode;
573
+ };
574
+
575
+ /** Copy for one visible registration input. */
576
+ interface RegisterFieldLabels {
577
+ /** Visible label above the input. */
578
+ label: string;
579
+ placeholder: string;
580
+ /** `accessibilityHint` for the input. */
581
+ hint: string;
582
+ /** `accessibilityLabel` for the input. */
583
+ inputLabel: string;
584
+ }
585
+ /** Strings rendered by `<RegisterForm>`. Error copy is not here: the app maps `RegisterErrorCode`. */
586
+ interface RegisterFormLabels {
587
+ title: string;
588
+ subtitle: string;
589
+ submit: string;
590
+ /** `accessibilityHint` for the submit button. */
591
+ submitHint: string;
592
+ /** `accessibilityLabel` for the submit button while the request runs. */
593
+ submitting: string;
594
+ fields: Record<RegisterInputField, RegisterFieldLabels>;
595
+ }
596
+ declare const DEFAULT_REGISTER_LABELS: RegisterFormLabels;
597
+
510
598
  /**
511
599
  * Who asked for a prefill — the difference between "the user requested this" and
512
600
  * "the app offered it".
@@ -2355,6 +2443,95 @@ declare function resolveAccountList(accounts?: readonly DemoAccount[] | null): D
2355
2443
  */
2356
2444
  declare function resolveDemoAccounts(credentials?: DemoCredentials | null): DemoAccount[];
2357
2445
 
2446
+ /**
2447
+ * `<RegisterForm>` — the ready-made, themeable sign-up form.
2448
+ *
2449
+ * Extracted from the identical katalogos-web and erevna-web register screens.
2450
+ * The app keeps what differs per product: the request it sends (`onSubmit`, which
2451
+ * carries the realm and verify-URL template), where to go afterwards
2452
+ * (`onSuccess`), and the localised copy (`labels`, plus mapping a
2453
+ * `RegisterErrorCode` to a message in `onError`).
2454
+ */
2455
+
2456
+ interface RegisterFormProps<TResult> {
2457
+ /** Send the registration (build the request, call the BFF). Throw on failure. */
2458
+ onSubmit: (values: RegisterSubmitValues) => Promise<TResult>;
2459
+ /** Called with whatever `onSubmit` resolved to. */
2460
+ onSuccess: (result: TResult) => void;
2461
+ /** Called with the failure code; map it to localised copy. */
2462
+ onError?: (error: RegisterErrorCode) => void;
2463
+ /** Called on every submit press, before validation (e.g. a "signup started" event). */
2464
+ onSubmitAttempt?: () => void;
2465
+ /** Password rule. Defaults to `isRegisterPasswordStrong`. */
2466
+ passwordPolicy?: RegisterPasswordPolicy;
2467
+ /** Localised copy. Partial: unspecified top-level keys fall back to English defaults. */
2468
+ labels?: Partial<RegisterFormLabels>;
2469
+ /** Explicit theme; overrides any `<AuthThemeProvider>`. */
2470
+ theme?: AuthTheme;
2471
+ /** Rendered under the submit button (e.g. "Already have an account?"). */
2472
+ footer?: ReactNode;
2473
+ /** Prefix applied to every `testID`. */
2474
+ testIdPrefix?: string;
2475
+ }
2476
+ /** Themeable registration form built on `useRegisterForm`. */
2477
+ declare function RegisterForm<TResult>({ onSubmit, onSuccess, onError, onSubmitAttempt, passwordPolicy, labels: labelsProp, theme: themeProp, footer, testIdPrefix, }: Readonly<RegisterFormProps<TResult>>): ReactElement;
2478
+
2479
+ /**
2480
+ * `testID` values for `<RegisterForm>`.
2481
+ *
2482
+ * Kept apart from `AuthTestIds` on purpose: these are the unprefixed
2483
+ * `register-*` IDs katalogos-web and erevna-web rendered before the extraction,
2484
+ * and the E2E suites (`E2ETests/shared/testIds.ts`,
2485
+ * `E2ETests/helpers/katalogos-signup-helpers.ts`) already select on them.
2486
+ * Changing a value here breaks those suites.
2487
+ *
2488
+ * `sonarjs/no-hardcoded-passwords` is disabled for this file: it flags the
2489
+ * `passwordInput` keys, but every value here is a UI test ID, not a credential.
2490
+ */
2491
+ declare const RegisterTestIds: {
2492
+ readonly form: "register-form";
2493
+ readonly firstNameInput: "register-first-name-input";
2494
+ readonly lastNameInput: "register-last-name-input";
2495
+ readonly usernameInput: "register-username-input";
2496
+ readonly emailInput: "register-email-input";
2497
+ readonly passwordInput: "register-password-input";
2498
+ readonly confirmPasswordInput: "register-confirm-password-input";
2499
+ readonly tenantNameInput: "register-tenant-name-input";
2500
+ readonly submitButton: "register-submit-button";
2501
+ readonly websiteInput: "register-website";
2502
+ };
2503
+
2504
+ interface UseRegisterFormArgs<TResult> {
2505
+ /** Send the registration. Throw on failure; the message is decoded to a code. */
2506
+ onSubmit: (values: RegisterSubmitValues) => Promise<TResult>;
2507
+ /** Password rule. Defaults to {@link isRegisterPasswordStrong}. */
2508
+ passwordPolicy?: RegisterPasswordPolicy;
2509
+ }
2510
+ interface UseRegisterFormResult<TResult> {
2511
+ state: RegisterFormValues;
2512
+ setField: (field: RegisterField, value: string) => void;
2513
+ submit: () => Promise<RegisterSubmitOutcome<TResult>>;
2514
+ isSubmitting: boolean;
2515
+ /** The last failure, cleared when a submit starts. */
2516
+ error: RegisterErrorCode | null;
2517
+ }
2518
+ /** Headless registration form logic. */
2519
+ declare function useRegisterForm<TResult>({ onSubmit, passwordPolicy, }: UseRegisterFormArgs<TResult>): UseRegisterFormResult<TResult>;
2520
+
2521
+ /**
2522
+ * Pure registration helpers: trimming, client-side validation and decoding of a
2523
+ * TenantService failure (surfaced by the BFF as a plain error whose message
2524
+ * carries an error-code substring).
2525
+ *
2526
+ * Merged from the katalogos-web and erevna-web `useRegisterForm` copies, which
2527
+ * were identical apart from katalogos' honeypot.
2528
+ */
2529
+
2530
+ /** The default password rule: 8+ characters with a letter, a digit and a special character. */
2531
+ declare function isRegisterPasswordStrong(password: string): boolean;
2532
+ /** Decode a thrown registration failure into a {@link RegisterErrorCode}. */
2533
+ declare function mapRegisterErrorCode(error: unknown): RegisterErrorCode;
2534
+
2358
2535
  /**
2359
2536
  * `createBffAuthClient` — the one-line wiring of a same-origin `BffAuthClient`.
2360
2537
  *
@@ -2644,4 +2821,4 @@ interface UseChangePasswordResult {
2644
2821
  }
2645
2822
  declare function useChangePassword({ client, onChanged, }: UseChangePasswordArgs): UseChangePasswordResult;
2646
2823
 
2647
- export { type AccountSettingsChangePasswordConfig, type AccountSettingsDevicePinConfig, type AccountSettingsLabels, type AccountSettingsPasskeysConfig, type AccountSettingsPreferredMethodConfig, AccountSettingsScreen, type AccountSettingsScreenProps, AuthScreen, type AuthScreenProps, AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type BffDeviceState, type BffLoginConfig, type BffLogoutClient, CHANGE_PASSWORD_ENDPOINT, type ChangePasswordCapableClient, ChangePasswordCard, type ChangePasswordCardProps, ChangePasswordErrorKey, type ChangePasswordRequest, type ChangePasswordResult, type CreateBffAuthClientOptions, type CreateBffChangePasswordClientOptions, DEFAULT_ACCOUNT_SETTINGS_LABELS, DEFAULT_AUTH_CARD_MAX_WIDTH, DEFAULT_DEMO_CREDENTIALS_HINT_LABELS, 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, DemoCredentialsHint, type DemoCredentialsHintLabels, type DemoCredentialsHintProps, DemoCredentialsHintVariant, type DemoCredentialsHintWiring, type DemoCredentialsLoginFormProps, 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, PasskeyCeremonyMode, PasskeyCeremonyStatus, type PasskeyErrorCode, PasskeyLoginButton, type PasskeyLoginButtonProps, type PasskeyLoginLabels, PasskeySettingsCard, type PasskeySettingsCardProps, type PasskeySettingsLabels, PasswordPolicyError, type PerformBffLogoutOptions, PinForm, type PinFormLabels, type PinFormProps, type PreferencesClientOptions, type PreferredMethodClient, PreferredMethodHint, type PreferredMethodHintLabels, type PreferredMethodHintProps, PreferredMethodSettingsCard, type PreferredMethodSettingsCardProps, type PreferredMethodSettingsLabels, PrefillIntent, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffLoginConfigResult, type UseBffResetPasswordOptions, type UseChangePasswordArgs, type UseChangePasswordResult, type UseDemoCredentialsOptions, type UseDemoCredentialsResult, type UseDevicePinDisableArgs, type UseDevicePinDisableResult, type UseDevicePinEnrollArgs, type UseDevicePinEnrollResult, type UseDevicePinUnlockArgs, type UseDevicePinUnlockResult, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePasskeyCeremonyOptions, type UsePasskeyCeremonyResult, type UsePinLoginOptions, type UsePinLoginResult, type UsePreferredMethodSettingArgs, type UsePreferredMethodSettingResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createBffChangePasswordClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, performBffLogout, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolveAccessibleRoutes, resolveAccountList, resolveDemoAccounts, resolveDemoCredentials, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useChangePassword, useDemoCredentials, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePasskeyCeremony, usePinLogin, usePreferredMethodSetting, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
2824
+ export { type AccountSettingsChangePasswordConfig, type AccountSettingsDevicePinConfig, type AccountSettingsLabels, type AccountSettingsPasskeysConfig, type AccountSettingsPreferredMethodConfig, AccountSettingsScreen, type AccountSettingsScreenProps, AuthScreen, type AuthScreenProps, AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type BffDeviceState, type BffLoginConfig, type BffLogoutClient, CHANGE_PASSWORD_ENDPOINT, type ChangePasswordCapableClient, ChangePasswordCard, type ChangePasswordCardProps, ChangePasswordErrorKey, type ChangePasswordRequest, type ChangePasswordResult, type CreateBffAuthClientOptions, type CreateBffChangePasswordClientOptions, DEFAULT_ACCOUNT_SETTINGS_LABELS, DEFAULT_AUTH_CARD_MAX_WIDTH, DEFAULT_DEMO_CREDENTIALS_HINT_LABELS, 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_REGISTER_LABELS, DEFAULT_RESET_PASSWORD_LABELS, DEVICE_PIN_ALLOWED_DIGITS, DEVICE_PIN_DEFAULT_DIGITS, DemoCredentialsHint, type DemoCredentialsHintLabels, type DemoCredentialsHintProps, DemoCredentialsHintVariant, type DemoCredentialsHintWiring, type DemoCredentialsLoginFormProps, 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, PasskeyCeremonyMode, PasskeyCeremonyStatus, type PasskeyErrorCode, PasskeyLoginButton, type PasskeyLoginButtonProps, type PasskeyLoginLabels, PasskeySettingsCard, type PasskeySettingsCardProps, type PasskeySettingsLabels, PasswordPolicyError, type PerformBffLogoutOptions, PinForm, type PinFormLabels, type PinFormProps, type PreferencesClientOptions, type PreferredMethodClient, PreferredMethodHint, type PreferredMethodHintLabels, type PreferredMethodHintProps, PreferredMethodSettingsCard, type PreferredMethodSettingsCardProps, type PreferredMethodSettingsLabels, PrefillIntent, RegisterErrorCode, type RegisterField, type RegisterFieldLabels, RegisterForm, type RegisterFormLabels, type RegisterFormProps, type RegisterFormValues, type RegisterInputField, type RegisterPasswordPolicy, type RegisterSubmitOutcome, type RegisterSubmitValues, RegisterTestIds, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffLoginConfigResult, type UseBffResetPasswordOptions, type UseChangePasswordArgs, type UseChangePasswordResult, type UseDemoCredentialsOptions, type UseDemoCredentialsResult, type UseDevicePinDisableArgs, type UseDevicePinDisableResult, type UseDevicePinEnrollArgs, type UseDevicePinEnrollResult, type UseDevicePinUnlockArgs, type UseDevicePinUnlockResult, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePasskeyCeremonyOptions, type UsePasskeyCeremonyResult, type UsePinLoginOptions, type UsePinLoginResult, type UsePreferredMethodSettingArgs, type UsePreferredMethodSettingResult, type UseRegisterFormArgs, type UseRegisterFormResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createBffChangePasswordClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isRegisterPasswordStrong, isValidForgotPasswordEmail, mapRegisterErrorCode, performBffLogout, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolveAccessibleRoutes, resolveAccountList, resolveDemoAccounts, resolveDemoCredentials, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useChangePassword, useDemoCredentials, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePasskeyCeremony, usePinLogin, usePreferredMethodSetting, useRegisterForm, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };