@dloizides/auth-web 1.2.1 → 1.3.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 +32 -0
- package/dist/index.d.mts +109 -2
- package/dist/index.d.ts +109 -2
- package/dist/index.js +206 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +203 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.3.0 (2026-05-31)
|
|
4
|
+
|
|
5
|
+
Additive release for the auth-UX reuse roll-out (feature-reuse-roadmap #1).
|
|
6
|
+
Promotes the "Forgot password?" modal body the product apps each hand-rolled
|
|
7
|
+
into a single shared, **react-query-free** export so katalogos / erevna / kefi
|
|
8
|
+
stop duplicating it. No breaking changes; every 1.2.x export is unchanged.
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`<ForgotPasswordFields>`** — the embedded, themeable "request a reset link"
|
|
13
|
+
body, sized to live inside an app-owned modal shell (no screen/card wrapper,
|
|
14
|
+
no title — the host modal owns those). Adds the two modal affordances a
|
|
15
|
+
screen-shaped form lacks: a `Cancel` button beside submit and a `Close` button
|
|
16
|
+
on the success state, each rendered only when its handler is supplied. Clears
|
|
17
|
+
itself when `visible` flips to `false` so reopening starts fresh.
|
|
18
|
+
- **`useForgotPasswordSubmit`** — the headless, **react-query-free** forgot-
|
|
19
|
+
password logic: a plain `useState` + `client.forgotPassword(...)` promise
|
|
20
|
+
chain that runs on a provider-less login route (where the existing
|
|
21
|
+
`useBffForgotPassword` `useMutation` crashes with "No QueryClient set"). Email
|
|
22
|
+
validation gating via `canSubmit`, anti-enumeration success, `hasNetworkError`,
|
|
23
|
+
and `reset()`. Also exports the `isValidForgotPasswordEmail` helper.
|
|
24
|
+
- **`ForgotPasswordFieldsLabels`** + **`DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS`** —
|
|
25
|
+
the forgot-password label bag plus the modal `cancel` / `close` strings.
|
|
26
|
+
- New `AuthTestIds` entries `forgotPasswordCancelButton` /
|
|
27
|
+
`forgotPasswordCloseButton`.
|
|
28
|
+
|
|
29
|
+
### Notes
|
|
30
|
+
|
|
31
|
+
- The existing screen-shaped `<ForgotPasswordForm>` (react-query-based) is
|
|
32
|
+
unchanged. A future cleanup may re-base it on `useForgotPasswordSubmit` to drop
|
|
33
|
+
its react-query coupling; deferred to keep this release additive.
|
|
34
|
+
|
|
3
35
|
## 1.2.0 (2026-05-22)
|
|
4
36
|
|
|
5
37
|
Additive release for Phase 3d of the unified-auth plan — the event-scoped PIN
|
package/dist/index.d.mts
CHANGED
|
@@ -28,6 +28,9 @@ interface LoginFormLabels {
|
|
|
28
28
|
submitting: string;
|
|
29
29
|
/** The "Forgot password?" link text. */
|
|
30
30
|
forgotPassword: string;
|
|
31
|
+
/** The "Create account" link shown below the submit button when an
|
|
32
|
+
* `onSignUp` handler is supplied. Omit the handler to hide the link. */
|
|
33
|
+
signUp: string;
|
|
31
34
|
/** Generic credentials-rejected message. */
|
|
32
35
|
invalidCredentials: string;
|
|
33
36
|
/** Shown when one or both fields are empty on submit. */
|
|
@@ -49,6 +52,17 @@ interface ForgotPasswordFormLabels {
|
|
|
49
52
|
/** Shown when the entered value is not a valid email. */
|
|
50
53
|
invalidEmail: string;
|
|
51
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Strings rendered by `<ForgotPasswordFields>` — the embedded modal body. It is
|
|
57
|
+
* the forgot-password form plus the two modal affordances (`cancel` alongside
|
|
58
|
+
* submit, `close` on the success state) that a screen-shaped form has no need of.
|
|
59
|
+
*/
|
|
60
|
+
interface ForgotPasswordFieldsLabels extends ForgotPasswordFormLabels {
|
|
61
|
+
/** The "cancel" button shown alongside submit. */
|
|
62
|
+
cancel: string;
|
|
63
|
+
/** The "close" button shown on the success state. */
|
|
64
|
+
close: string;
|
|
65
|
+
}
|
|
52
66
|
/** Strings rendered by `<OtpForm>` — the two-step email-OTP login form. */
|
|
53
67
|
interface OtpFormLabels {
|
|
54
68
|
/** Title shown on the request-a-code step. */
|
|
@@ -124,6 +138,7 @@ interface ResetPasswordFormLabels {
|
|
|
124
138
|
}
|
|
125
139
|
declare const DEFAULT_LOGIN_LABELS: LoginFormLabels;
|
|
126
140
|
declare const DEFAULT_FORGOT_PASSWORD_LABELS: ForgotPasswordFormLabels;
|
|
141
|
+
declare const DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS: ForgotPasswordFieldsLabels;
|
|
127
142
|
declare const DEFAULT_OTP_LABELS: OtpFormLabels;
|
|
128
143
|
declare const DEFAULT_PIN_LABELS: PinFormLabels;
|
|
129
144
|
declare const DEFAULT_RESET_PASSWORD_LABELS: ResetPasswordFormLabels;
|
|
@@ -233,11 +248,18 @@ interface LoginFormProps {
|
|
|
233
248
|
onSuccess: (user: BffUser) => void;
|
|
234
249
|
/** Called when the user taps the "Forgot password?" link. Omit to hide the link. */
|
|
235
250
|
onForgotPassword?: () => void;
|
|
251
|
+
/**
|
|
252
|
+
* Called when the user taps the "Create account" link. Omit to hide the link
|
|
253
|
+
* (the registration UI then has to be reached some other way — direct nav,
|
|
254
|
+
* marketing CTA, etc.). The consuming app decides where the link routes;
|
|
255
|
+
* `<LoginForm>` just surfaces the entry point.
|
|
256
|
+
*/
|
|
257
|
+
onSignUp?: () => void;
|
|
236
258
|
/** Prefix applied to every `testID` so multiple forms can share a screen. */
|
|
237
259
|
testIdPrefix?: string;
|
|
238
260
|
}
|
|
239
261
|
/** Themeable password-login form built on `useBffAuth`. */
|
|
240
|
-
declare function LoginForm({ client, theme: themeProp, labels: labelsProp, onSuccess, onForgotPassword, testIdPrefix, }: Readonly<LoginFormProps>): ReactElement;
|
|
262
|
+
declare function LoginForm({ client, theme: themeProp, labels: labelsProp, onSuccess, onForgotPassword, onSignUp, testIdPrefix, }: Readonly<LoginFormProps>): ReactElement;
|
|
241
263
|
|
|
242
264
|
/**
|
|
243
265
|
* `<ForgotPasswordForm>` — the ready-made, themeable "request a reset link"
|
|
@@ -274,6 +296,56 @@ interface ForgotPasswordFormProps {
|
|
|
274
296
|
/** Themeable "request a reset link" form built on `useBffForgotPassword`. */
|
|
275
297
|
declare function ForgotPasswordForm({ client, theme: themeProp, labels: labelsProp, resetUrlTemplate, onSuccess, testIdPrefix, }: Readonly<ForgotPasswordFormProps>): ReactElement;
|
|
276
298
|
|
|
299
|
+
/**
|
|
300
|
+
* `<ForgotPasswordFields>` — the embedded, themeable "request a reset link"
|
|
301
|
+
* body, sized to live INSIDE an app-owned modal shell (not a full screen).
|
|
302
|
+
*
|
|
303
|
+
* The product apps each show "Forgot password?" as a modal launched from their
|
|
304
|
+
* login route, wrapping their own modal chrome (title bar + close affordance)
|
|
305
|
+
* around an identical email field + submit/cancel body. This is that body,
|
|
306
|
+
* promoted into the package so the three apps stop hand-rolling it.
|
|
307
|
+
*
|
|
308
|
+
* Built on the react-query-free `useForgotPasswordSubmit` hook, so it renders +
|
|
309
|
+
* submits on a provider-less login route (where `useMutation` would crash). The
|
|
310
|
+
* backend is anti-enumeration, so a successful request swaps to a generic
|
|
311
|
+
* confirmation that never reveals whether the address is registered.
|
|
312
|
+
*
|
|
313
|
+
* Differs from the screen-shaped `<ForgotPasswordForm>`: no outer screen/card
|
|
314
|
+
* wrapper and no title (the host modal owns those), plus two modal affordances —
|
|
315
|
+
* a `Cancel` button beside submit and a `Close` button on the success state —
|
|
316
|
+
* each rendered only when its handler is supplied.
|
|
317
|
+
*/
|
|
318
|
+
|
|
319
|
+
interface ForgotPasswordFieldsProps {
|
|
320
|
+
/** The same-origin BFF client (build it with `createBffAuthClient`). */
|
|
321
|
+
client: BffAuthClient;
|
|
322
|
+
/** Explicit theme; overrides any `<AuthThemeProvider>`. */
|
|
323
|
+
theme?: AuthTheme;
|
|
324
|
+
/** Localised copy. Partial — unspecified keys fall back to English defaults. */
|
|
325
|
+
labels?: Partial<ForgotPasswordFieldsLabels>;
|
|
326
|
+
/**
|
|
327
|
+
* Full URL with a `{token}` placeholder, forwarded to the backend so it can
|
|
328
|
+
* build the reset-email link without hardcoding a frontend host.
|
|
329
|
+
*/
|
|
330
|
+
resetUrlTemplate?: string;
|
|
331
|
+
/**
|
|
332
|
+
* The host modal's open state. When it flips to `false` the body clears
|
|
333
|
+
* itself, so reopening shows a fresh form regardless of which affordance
|
|
334
|
+
* closed it. Defaults to `true` for non-modal embedding.
|
|
335
|
+
*/
|
|
336
|
+
visible?: boolean;
|
|
337
|
+
/** Called once the request succeeds (the generic-confirmation state). */
|
|
338
|
+
onSuccess?: () => void;
|
|
339
|
+
/** When supplied, renders a Cancel button beside submit. */
|
|
340
|
+
onCancel?: () => void;
|
|
341
|
+
/** When supplied, renders a Close button on the success state. */
|
|
342
|
+
onClose?: () => void;
|
|
343
|
+
/** Prefix applied to every `testID`. */
|
|
344
|
+
testIdPrefix?: string;
|
|
345
|
+
}
|
|
346
|
+
/** Embedded "request a reset link" body for an app-owned modal. */
|
|
347
|
+
declare function ForgotPasswordFields({ client, theme: themeProp, labels: labelsProp, resetUrlTemplate, visible, onSuccess, onCancel, onClose, testIdPrefix, }: Readonly<ForgotPasswordFieldsProps>): ReactElement;
|
|
348
|
+
|
|
277
349
|
/**
|
|
278
350
|
* `<ResetPasswordForm>` — the ready-made, themeable "choose a new password"
|
|
279
351
|
* form.
|
|
@@ -423,10 +495,13 @@ declare const AuthTestIds: {
|
|
|
423
495
|
readonly loginPasswordInput: "auth-login-password";
|
|
424
496
|
readonly loginSubmitButton: "auth-login-submit";
|
|
425
497
|
readonly loginForgotLink: "auth-login-forgot-link";
|
|
498
|
+
readonly loginSignUpLink: "auth-login-signup-link";
|
|
426
499
|
readonly loginError: "auth-login-error";
|
|
427
500
|
readonly forgotPasswordForm: "auth-forgot-form";
|
|
428
501
|
readonly forgotPasswordEmailInput: "auth-forgot-email";
|
|
429
502
|
readonly forgotPasswordSubmitButton: "auth-forgot-submit";
|
|
503
|
+
readonly forgotPasswordCancelButton: "auth-forgot-cancel";
|
|
504
|
+
readonly forgotPasswordCloseButton: "auth-forgot-close";
|
|
430
505
|
readonly forgotPasswordError: "auth-forgot-error";
|
|
431
506
|
readonly forgotPasswordSuccess: "auth-forgot-success";
|
|
432
507
|
readonly resetPasswordForm: "auth-reset-form";
|
|
@@ -579,6 +654,38 @@ interface UseResetPasswordFormResult {
|
|
|
579
654
|
*/
|
|
580
655
|
declare function useResetPasswordForm({ client, token, onSuccess, }: UseResetPasswordFormArgs): UseResetPasswordFormResult;
|
|
581
656
|
|
|
657
|
+
/** `true` when `value` (after trimming) looks like an email address. */
|
|
658
|
+
declare function isValidForgotPasswordEmail(value: string): boolean;
|
|
659
|
+
interface UseForgotPasswordSubmitArgs {
|
|
660
|
+
/** The same-origin BFF client (build it with `createBffAuthClient`). */
|
|
661
|
+
client: BffAuthClient;
|
|
662
|
+
/**
|
|
663
|
+
* Full URL with a `{token}` placeholder, forwarded to the backend so it can
|
|
664
|
+
* build the reset-email link without hardcoding a frontend host.
|
|
665
|
+
*/
|
|
666
|
+
resetUrlTemplate?: string;
|
|
667
|
+
/** Invoked once the request succeeds (the generic-confirmation state). */
|
|
668
|
+
onSuccess?: () => void;
|
|
669
|
+
}
|
|
670
|
+
interface UseForgotPasswordSubmitResult {
|
|
671
|
+
email: string;
|
|
672
|
+
setEmail: (value: string) => void;
|
|
673
|
+
/** `true` once the request has succeeded (show the generic confirmation). */
|
|
674
|
+
submitted: boolean;
|
|
675
|
+
/** `true` while the request is in flight. */
|
|
676
|
+
isSubmitting: boolean;
|
|
677
|
+
/** `true` when the last submit hit a network / 5xx failure. */
|
|
678
|
+
hasNetworkError: boolean;
|
|
679
|
+
/** `true` when the email is valid and no request is in flight. */
|
|
680
|
+
canSubmit: boolean;
|
|
681
|
+
/** Validate, then fire the request (no-op when `canSubmit` is false). */
|
|
682
|
+
submit: () => void;
|
|
683
|
+
/** Clear all state — call when the modal closes. */
|
|
684
|
+
reset: () => void;
|
|
685
|
+
}
|
|
686
|
+
/** Headless, react-query-free "request a reset link" logic. */
|
|
687
|
+
declare function useForgotPasswordSubmit({ client, resetUrlTemplate, onSuccess, }: UseForgotPasswordSubmitArgs): UseForgotPasswordSubmitResult;
|
|
688
|
+
|
|
582
689
|
/**
|
|
583
690
|
* The two discrete steps of the email-OTP login flow.
|
|
584
691
|
*
|
|
@@ -803,4 +910,4 @@ declare function validatePasswordPolicy(password: string): PasswordPolicyError[]
|
|
|
803
910
|
/** `true` when the password satisfies every policy rule. */
|
|
804
911
|
declare function isPasswordValid(password: string): boolean;
|
|
805
912
|
|
|
806
|
-
export { AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type CreateBffAuthClientOptions, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PIN_LABELS, DEFAULT_RESET_PASSWORD_LABELS, ForgotPasswordForm, type ForgotPasswordFormLabels, type ForgotPasswordFormProps, LoginForm, type LoginFormLabels, type LoginFormProps, OtpForm, type OtpFormLabels, type OtpFormProps, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, PasswordPolicyError, PinForm, type PinFormLabels, type PinFormProps, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffResetPasswordOptions, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePinLoginOptions, type UsePinLoginResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, collectUserRoles, createBffAuthClient, defaultAuthTheme, isPasswordValid, resolvePostLoginRoute, useAuthTheme, useBffAuth, useBffForgotPassword, useBffResetPassword, useOtpLogin, usePinLogin, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
|
|
913
|
+
export { AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type CreateBffAuthClientOptions, DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PIN_LABELS, DEFAULT_RESET_PASSWORD_LABELS, ForgotPasswordFields, type ForgotPasswordFieldsLabels, type ForgotPasswordFieldsProps, ForgotPasswordForm, type ForgotPasswordFormLabels, type ForgotPasswordFormProps, LoginForm, type LoginFormLabels, type LoginFormProps, OtpForm, type OtpFormLabels, type OtpFormProps, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, PasswordPolicyError, PinForm, type PinFormLabels, type PinFormProps, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffResetPasswordOptions, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePinLoginOptions, type UsePinLoginResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, collectUserRoles, createBffAuthClient, defaultAuthTheme, isPasswordValid, isValidForgotPasswordEmail, resolvePostLoginRoute, useAuthTheme, useBffAuth, useBffForgotPassword, useBffResetPassword, useForgotPasswordSubmit, useOtpLogin, usePinLogin, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
|
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,9 @@ interface LoginFormLabels {
|
|
|
28
28
|
submitting: string;
|
|
29
29
|
/** The "Forgot password?" link text. */
|
|
30
30
|
forgotPassword: string;
|
|
31
|
+
/** The "Create account" link shown below the submit button when an
|
|
32
|
+
* `onSignUp` handler is supplied. Omit the handler to hide the link. */
|
|
33
|
+
signUp: string;
|
|
31
34
|
/** Generic credentials-rejected message. */
|
|
32
35
|
invalidCredentials: string;
|
|
33
36
|
/** Shown when one or both fields are empty on submit. */
|
|
@@ -49,6 +52,17 @@ interface ForgotPasswordFormLabels {
|
|
|
49
52
|
/** Shown when the entered value is not a valid email. */
|
|
50
53
|
invalidEmail: string;
|
|
51
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Strings rendered by `<ForgotPasswordFields>` — the embedded modal body. It is
|
|
57
|
+
* the forgot-password form plus the two modal affordances (`cancel` alongside
|
|
58
|
+
* submit, `close` on the success state) that a screen-shaped form has no need of.
|
|
59
|
+
*/
|
|
60
|
+
interface ForgotPasswordFieldsLabels extends ForgotPasswordFormLabels {
|
|
61
|
+
/** The "cancel" button shown alongside submit. */
|
|
62
|
+
cancel: string;
|
|
63
|
+
/** The "close" button shown on the success state. */
|
|
64
|
+
close: string;
|
|
65
|
+
}
|
|
52
66
|
/** Strings rendered by `<OtpForm>` — the two-step email-OTP login form. */
|
|
53
67
|
interface OtpFormLabels {
|
|
54
68
|
/** Title shown on the request-a-code step. */
|
|
@@ -124,6 +138,7 @@ interface ResetPasswordFormLabels {
|
|
|
124
138
|
}
|
|
125
139
|
declare const DEFAULT_LOGIN_LABELS: LoginFormLabels;
|
|
126
140
|
declare const DEFAULT_FORGOT_PASSWORD_LABELS: ForgotPasswordFormLabels;
|
|
141
|
+
declare const DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS: ForgotPasswordFieldsLabels;
|
|
127
142
|
declare const DEFAULT_OTP_LABELS: OtpFormLabels;
|
|
128
143
|
declare const DEFAULT_PIN_LABELS: PinFormLabels;
|
|
129
144
|
declare const DEFAULT_RESET_PASSWORD_LABELS: ResetPasswordFormLabels;
|
|
@@ -233,11 +248,18 @@ interface LoginFormProps {
|
|
|
233
248
|
onSuccess: (user: BffUser) => void;
|
|
234
249
|
/** Called when the user taps the "Forgot password?" link. Omit to hide the link. */
|
|
235
250
|
onForgotPassword?: () => void;
|
|
251
|
+
/**
|
|
252
|
+
* Called when the user taps the "Create account" link. Omit to hide the link
|
|
253
|
+
* (the registration UI then has to be reached some other way — direct nav,
|
|
254
|
+
* marketing CTA, etc.). The consuming app decides where the link routes;
|
|
255
|
+
* `<LoginForm>` just surfaces the entry point.
|
|
256
|
+
*/
|
|
257
|
+
onSignUp?: () => void;
|
|
236
258
|
/** Prefix applied to every `testID` so multiple forms can share a screen. */
|
|
237
259
|
testIdPrefix?: string;
|
|
238
260
|
}
|
|
239
261
|
/** Themeable password-login form built on `useBffAuth`. */
|
|
240
|
-
declare function LoginForm({ client, theme: themeProp, labels: labelsProp, onSuccess, onForgotPassword, testIdPrefix, }: Readonly<LoginFormProps>): ReactElement;
|
|
262
|
+
declare function LoginForm({ client, theme: themeProp, labels: labelsProp, onSuccess, onForgotPassword, onSignUp, testIdPrefix, }: Readonly<LoginFormProps>): ReactElement;
|
|
241
263
|
|
|
242
264
|
/**
|
|
243
265
|
* `<ForgotPasswordForm>` — the ready-made, themeable "request a reset link"
|
|
@@ -274,6 +296,56 @@ interface ForgotPasswordFormProps {
|
|
|
274
296
|
/** Themeable "request a reset link" form built on `useBffForgotPassword`. */
|
|
275
297
|
declare function ForgotPasswordForm({ client, theme: themeProp, labels: labelsProp, resetUrlTemplate, onSuccess, testIdPrefix, }: Readonly<ForgotPasswordFormProps>): ReactElement;
|
|
276
298
|
|
|
299
|
+
/**
|
|
300
|
+
* `<ForgotPasswordFields>` — the embedded, themeable "request a reset link"
|
|
301
|
+
* body, sized to live INSIDE an app-owned modal shell (not a full screen).
|
|
302
|
+
*
|
|
303
|
+
* The product apps each show "Forgot password?" as a modal launched from their
|
|
304
|
+
* login route, wrapping their own modal chrome (title bar + close affordance)
|
|
305
|
+
* around an identical email field + submit/cancel body. This is that body,
|
|
306
|
+
* promoted into the package so the three apps stop hand-rolling it.
|
|
307
|
+
*
|
|
308
|
+
* Built on the react-query-free `useForgotPasswordSubmit` hook, so it renders +
|
|
309
|
+
* submits on a provider-less login route (where `useMutation` would crash). The
|
|
310
|
+
* backend is anti-enumeration, so a successful request swaps to a generic
|
|
311
|
+
* confirmation that never reveals whether the address is registered.
|
|
312
|
+
*
|
|
313
|
+
* Differs from the screen-shaped `<ForgotPasswordForm>`: no outer screen/card
|
|
314
|
+
* wrapper and no title (the host modal owns those), plus two modal affordances —
|
|
315
|
+
* a `Cancel` button beside submit and a `Close` button on the success state —
|
|
316
|
+
* each rendered only when its handler is supplied.
|
|
317
|
+
*/
|
|
318
|
+
|
|
319
|
+
interface ForgotPasswordFieldsProps {
|
|
320
|
+
/** The same-origin BFF client (build it with `createBffAuthClient`). */
|
|
321
|
+
client: BffAuthClient;
|
|
322
|
+
/** Explicit theme; overrides any `<AuthThemeProvider>`. */
|
|
323
|
+
theme?: AuthTheme;
|
|
324
|
+
/** Localised copy. Partial — unspecified keys fall back to English defaults. */
|
|
325
|
+
labels?: Partial<ForgotPasswordFieldsLabels>;
|
|
326
|
+
/**
|
|
327
|
+
* Full URL with a `{token}` placeholder, forwarded to the backend so it can
|
|
328
|
+
* build the reset-email link without hardcoding a frontend host.
|
|
329
|
+
*/
|
|
330
|
+
resetUrlTemplate?: string;
|
|
331
|
+
/**
|
|
332
|
+
* The host modal's open state. When it flips to `false` the body clears
|
|
333
|
+
* itself, so reopening shows a fresh form regardless of which affordance
|
|
334
|
+
* closed it. Defaults to `true` for non-modal embedding.
|
|
335
|
+
*/
|
|
336
|
+
visible?: boolean;
|
|
337
|
+
/** Called once the request succeeds (the generic-confirmation state). */
|
|
338
|
+
onSuccess?: () => void;
|
|
339
|
+
/** When supplied, renders a Cancel button beside submit. */
|
|
340
|
+
onCancel?: () => void;
|
|
341
|
+
/** When supplied, renders a Close button on the success state. */
|
|
342
|
+
onClose?: () => void;
|
|
343
|
+
/** Prefix applied to every `testID`. */
|
|
344
|
+
testIdPrefix?: string;
|
|
345
|
+
}
|
|
346
|
+
/** Embedded "request a reset link" body for an app-owned modal. */
|
|
347
|
+
declare function ForgotPasswordFields({ client, theme: themeProp, labels: labelsProp, resetUrlTemplate, visible, onSuccess, onCancel, onClose, testIdPrefix, }: Readonly<ForgotPasswordFieldsProps>): ReactElement;
|
|
348
|
+
|
|
277
349
|
/**
|
|
278
350
|
* `<ResetPasswordForm>` — the ready-made, themeable "choose a new password"
|
|
279
351
|
* form.
|
|
@@ -423,10 +495,13 @@ declare const AuthTestIds: {
|
|
|
423
495
|
readonly loginPasswordInput: "auth-login-password";
|
|
424
496
|
readonly loginSubmitButton: "auth-login-submit";
|
|
425
497
|
readonly loginForgotLink: "auth-login-forgot-link";
|
|
498
|
+
readonly loginSignUpLink: "auth-login-signup-link";
|
|
426
499
|
readonly loginError: "auth-login-error";
|
|
427
500
|
readonly forgotPasswordForm: "auth-forgot-form";
|
|
428
501
|
readonly forgotPasswordEmailInput: "auth-forgot-email";
|
|
429
502
|
readonly forgotPasswordSubmitButton: "auth-forgot-submit";
|
|
503
|
+
readonly forgotPasswordCancelButton: "auth-forgot-cancel";
|
|
504
|
+
readonly forgotPasswordCloseButton: "auth-forgot-close";
|
|
430
505
|
readonly forgotPasswordError: "auth-forgot-error";
|
|
431
506
|
readonly forgotPasswordSuccess: "auth-forgot-success";
|
|
432
507
|
readonly resetPasswordForm: "auth-reset-form";
|
|
@@ -579,6 +654,38 @@ interface UseResetPasswordFormResult {
|
|
|
579
654
|
*/
|
|
580
655
|
declare function useResetPasswordForm({ client, token, onSuccess, }: UseResetPasswordFormArgs): UseResetPasswordFormResult;
|
|
581
656
|
|
|
657
|
+
/** `true` when `value` (after trimming) looks like an email address. */
|
|
658
|
+
declare function isValidForgotPasswordEmail(value: string): boolean;
|
|
659
|
+
interface UseForgotPasswordSubmitArgs {
|
|
660
|
+
/** The same-origin BFF client (build it with `createBffAuthClient`). */
|
|
661
|
+
client: BffAuthClient;
|
|
662
|
+
/**
|
|
663
|
+
* Full URL with a `{token}` placeholder, forwarded to the backend so it can
|
|
664
|
+
* build the reset-email link without hardcoding a frontend host.
|
|
665
|
+
*/
|
|
666
|
+
resetUrlTemplate?: string;
|
|
667
|
+
/** Invoked once the request succeeds (the generic-confirmation state). */
|
|
668
|
+
onSuccess?: () => void;
|
|
669
|
+
}
|
|
670
|
+
interface UseForgotPasswordSubmitResult {
|
|
671
|
+
email: string;
|
|
672
|
+
setEmail: (value: string) => void;
|
|
673
|
+
/** `true` once the request has succeeded (show the generic confirmation). */
|
|
674
|
+
submitted: boolean;
|
|
675
|
+
/** `true` while the request is in flight. */
|
|
676
|
+
isSubmitting: boolean;
|
|
677
|
+
/** `true` when the last submit hit a network / 5xx failure. */
|
|
678
|
+
hasNetworkError: boolean;
|
|
679
|
+
/** `true` when the email is valid and no request is in flight. */
|
|
680
|
+
canSubmit: boolean;
|
|
681
|
+
/** Validate, then fire the request (no-op when `canSubmit` is false). */
|
|
682
|
+
submit: () => void;
|
|
683
|
+
/** Clear all state — call when the modal closes. */
|
|
684
|
+
reset: () => void;
|
|
685
|
+
}
|
|
686
|
+
/** Headless, react-query-free "request a reset link" logic. */
|
|
687
|
+
declare function useForgotPasswordSubmit({ client, resetUrlTemplate, onSuccess, }: UseForgotPasswordSubmitArgs): UseForgotPasswordSubmitResult;
|
|
688
|
+
|
|
582
689
|
/**
|
|
583
690
|
* The two discrete steps of the email-OTP login flow.
|
|
584
691
|
*
|
|
@@ -803,4 +910,4 @@ declare function validatePasswordPolicy(password: string): PasswordPolicyError[]
|
|
|
803
910
|
/** `true` when the password satisfies every policy rule. */
|
|
804
911
|
declare function isPasswordValid(password: string): boolean;
|
|
805
912
|
|
|
806
|
-
export { AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type CreateBffAuthClientOptions, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PIN_LABELS, DEFAULT_RESET_PASSWORD_LABELS, ForgotPasswordForm, type ForgotPasswordFormLabels, type ForgotPasswordFormProps, LoginForm, type LoginFormLabels, type LoginFormProps, OtpForm, type OtpFormLabels, type OtpFormProps, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, PasswordPolicyError, PinForm, type PinFormLabels, type PinFormProps, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffResetPasswordOptions, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePinLoginOptions, type UsePinLoginResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, collectUserRoles, createBffAuthClient, defaultAuthTheme, isPasswordValid, resolvePostLoginRoute, useAuthTheme, useBffAuth, useBffForgotPassword, useBffResetPassword, useOtpLogin, usePinLogin, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
|
|
913
|
+
export { AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type CreateBffAuthClientOptions, DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PIN_LABELS, DEFAULT_RESET_PASSWORD_LABELS, ForgotPasswordFields, type ForgotPasswordFieldsLabels, type ForgotPasswordFieldsProps, ForgotPasswordForm, type ForgotPasswordFormLabels, type ForgotPasswordFormProps, LoginForm, type LoginFormLabels, type LoginFormProps, OtpForm, type OtpFormLabels, type OtpFormProps, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, PasswordPolicyError, PinForm, type PinFormLabels, type PinFormProps, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffResetPasswordOptions, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePinLoginOptions, type UsePinLoginResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, collectUserRoles, createBffAuthClient, defaultAuthTheme, isPasswordValid, isValidForgotPasswordEmail, resolvePostLoginRoute, useAuthTheme, useBffAuth, useBffForgotPassword, useBffResetPassword, useForgotPasswordSubmit, useOtpLogin, usePinLogin, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,7 @@ var DEFAULT_LOGIN_LABELS = {
|
|
|
19
19
|
submit: "Sign in",
|
|
20
20
|
submitting: "Signing in...",
|
|
21
21
|
forgotPassword: "Forgot password?",
|
|
22
|
+
signUp: "Create an account",
|
|
22
23
|
invalidCredentials: "Incorrect username or password.",
|
|
23
24
|
missingFields: "Enter both your username and password."
|
|
24
25
|
};
|
|
@@ -33,6 +34,11 @@ var DEFAULT_FORGOT_PASSWORD_LABELS = {
|
|
|
33
34
|
networkError: "Something went wrong. Please try again.",
|
|
34
35
|
invalidEmail: "Enter a valid email address."
|
|
35
36
|
};
|
|
37
|
+
var DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS = {
|
|
38
|
+
...DEFAULT_FORGOT_PASSWORD_LABELS,
|
|
39
|
+
cancel: "Cancel",
|
|
40
|
+
close: "Close"
|
|
41
|
+
};
|
|
36
42
|
var DEFAULT_OTP_LABELS = {
|
|
37
43
|
requestTitle: "Sign in with a code",
|
|
38
44
|
requestDescription: "Enter your email and we will send you a one-time code.",
|
|
@@ -86,10 +92,13 @@ var AuthTestIds = {
|
|
|
86
92
|
loginPasswordInput: "auth-login-password",
|
|
87
93
|
loginSubmitButton: "auth-login-submit",
|
|
88
94
|
loginForgotLink: "auth-login-forgot-link",
|
|
95
|
+
loginSignUpLink: "auth-login-signup-link",
|
|
89
96
|
loginError: "auth-login-error",
|
|
90
97
|
forgotPasswordForm: "auth-forgot-form",
|
|
91
98
|
forgotPasswordEmailInput: "auth-forgot-email",
|
|
92
99
|
forgotPasswordSubmitButton: "auth-forgot-submit",
|
|
100
|
+
forgotPasswordCancelButton: "auth-forgot-cancel",
|
|
101
|
+
forgotPasswordCloseButton: "auth-forgot-close",
|
|
93
102
|
forgotPasswordError: "auth-forgot-error",
|
|
94
103
|
forgotPasswordSuccess: "auth-forgot-success",
|
|
95
104
|
resetPasswordForm: "auth-reset-form",
|
|
@@ -359,6 +368,7 @@ function LoginForm({
|
|
|
359
368
|
labels: labelsProp,
|
|
360
369
|
onSuccess,
|
|
361
370
|
onForgotPassword,
|
|
371
|
+
onSignUp,
|
|
362
372
|
testIdPrefix
|
|
363
373
|
}) {
|
|
364
374
|
const theme = useAuthTheme(themeProp);
|
|
@@ -465,7 +475,20 @@ function LoginForm({
|
|
|
465
475
|
onPress: handleSubmit,
|
|
466
476
|
children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.primaryButtonText, children: labels.submit })
|
|
467
477
|
}
|
|
468
|
-
)
|
|
478
|
+
),
|
|
479
|
+
onSignUp !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
480
|
+
reactNative.TouchableOpacity,
|
|
481
|
+
{
|
|
482
|
+
accessibilityHint: labels.signUp,
|
|
483
|
+
accessibilityLabel: labels.signUp,
|
|
484
|
+
accessibilityRole: "link",
|
|
485
|
+
disabled: isSubmitting,
|
|
486
|
+
style: styles.fieldGroup,
|
|
487
|
+
testID: withTestIdPrefix(AuthTestIds.loginSignUpLink, testIdPrefix),
|
|
488
|
+
onPress: onSignUp,
|
|
489
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.linkText, children: labels.signUp })
|
|
490
|
+
}
|
|
491
|
+
) : null
|
|
469
492
|
] }) });
|
|
470
493
|
}
|
|
471
494
|
function useBffForgotPassword(options) {
|
|
@@ -596,6 +619,182 @@ function ForgotPasswordForm({
|
|
|
596
619
|
}
|
|
597
620
|
) });
|
|
598
621
|
}
|
|
622
|
+
var EMAIL_REGEX2 = /^[^@\s]+@[^.\s]+\.[^\s]+$/;
|
|
623
|
+
function isValidForgotPasswordEmail(value) {
|
|
624
|
+
return EMAIL_REGEX2.test(value.trim());
|
|
625
|
+
}
|
|
626
|
+
function useForgotPasswordSubmit({
|
|
627
|
+
client,
|
|
628
|
+
resetUrlTemplate,
|
|
629
|
+
onSuccess
|
|
630
|
+
}) {
|
|
631
|
+
const [email, setEmail] = react.useState("");
|
|
632
|
+
const [submitted, setSubmitted] = react.useState(false);
|
|
633
|
+
const [isSubmitting, setIsSubmitting] = react.useState(false);
|
|
634
|
+
const [hasNetworkError, setHasNetworkError] = react.useState(false);
|
|
635
|
+
const canSubmit = isValidForgotPasswordEmail(email) && !isSubmitting;
|
|
636
|
+
const submit = react.useCallback(() => {
|
|
637
|
+
const target = email.trim();
|
|
638
|
+
if (!isValidForgotPasswordEmail(target) || isSubmitting) {
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
setHasNetworkError(false);
|
|
642
|
+
setIsSubmitting(true);
|
|
643
|
+
const request = { email: target, resetUrlTemplate };
|
|
644
|
+
client.forgotPassword(request).then(() => {
|
|
645
|
+
setSubmitted(true);
|
|
646
|
+
onSuccess?.();
|
|
647
|
+
}).catch(() => setHasNetworkError(true)).finally(() => setIsSubmitting(false));
|
|
648
|
+
}, [client, email, isSubmitting, resetUrlTemplate, onSuccess]);
|
|
649
|
+
const reset = react.useCallback(() => {
|
|
650
|
+
setEmail("");
|
|
651
|
+
setSubmitted(false);
|
|
652
|
+
setIsSubmitting(false);
|
|
653
|
+
setHasNetworkError(false);
|
|
654
|
+
}, []);
|
|
655
|
+
return {
|
|
656
|
+
email,
|
|
657
|
+
setEmail,
|
|
658
|
+
submitted,
|
|
659
|
+
isSubmitting,
|
|
660
|
+
hasNetworkError,
|
|
661
|
+
canSubmit,
|
|
662
|
+
submit,
|
|
663
|
+
reset
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
var SECONDARY_BORDER_WIDTH = 1;
|
|
667
|
+
function useModalStyles(theme) {
|
|
668
|
+
return react.useMemo(
|
|
669
|
+
() => reactNative.StyleSheet.create({
|
|
670
|
+
body: { padding: theme.spacing.md },
|
|
671
|
+
actions: {
|
|
672
|
+
flexDirection: "row",
|
|
673
|
+
justifyContent: "flex-end",
|
|
674
|
+
alignItems: "center",
|
|
675
|
+
marginTop: theme.spacing.md,
|
|
676
|
+
gap: theme.spacing.sm
|
|
677
|
+
},
|
|
678
|
+
secondaryButton: {
|
|
679
|
+
borderRadius: theme.radii.input,
|
|
680
|
+
paddingVertical: theme.spacing.sm,
|
|
681
|
+
paddingHorizontal: theme.spacing.md,
|
|
682
|
+
borderWidth: SECONDARY_BORDER_WIDTH,
|
|
683
|
+
borderColor: theme.colors.border
|
|
684
|
+
},
|
|
685
|
+
secondaryButtonText: {
|
|
686
|
+
fontSize: theme.typography.body,
|
|
687
|
+
fontWeight: "600",
|
|
688
|
+
color: theme.colors.text
|
|
689
|
+
}
|
|
690
|
+
}),
|
|
691
|
+
[theme]
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
function ForgotPasswordFields({
|
|
695
|
+
client,
|
|
696
|
+
theme: themeProp,
|
|
697
|
+
labels: labelsProp,
|
|
698
|
+
resetUrlTemplate,
|
|
699
|
+
visible = true,
|
|
700
|
+
onSuccess,
|
|
701
|
+
onCancel,
|
|
702
|
+
onClose,
|
|
703
|
+
testIdPrefix
|
|
704
|
+
}) {
|
|
705
|
+
const theme = useAuthTheme(themeProp);
|
|
706
|
+
const styles = useAuthStyles(theme);
|
|
707
|
+
const modalStyles = useModalStyles(theme);
|
|
708
|
+
const labels = react.useMemo(
|
|
709
|
+
() => ({ ...DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, ...labelsProp }),
|
|
710
|
+
[labelsProp]
|
|
711
|
+
);
|
|
712
|
+
const form = useForgotPasswordSubmit({ client, resetUrlTemplate, onSuccess });
|
|
713
|
+
const { reset } = form;
|
|
714
|
+
react.useEffect(() => {
|
|
715
|
+
if (!visible) {
|
|
716
|
+
reset();
|
|
717
|
+
}
|
|
718
|
+
}, [visible, reset]);
|
|
719
|
+
const submitButtonStyle = form.canSubmit ? styles.primaryButton : [styles.primaryButton, styles.primaryButtonDisabled];
|
|
720
|
+
const handleCancel = () => {
|
|
721
|
+
form.reset();
|
|
722
|
+
onCancel?.();
|
|
723
|
+
};
|
|
724
|
+
const handleClose = () => {
|
|
725
|
+
form.reset();
|
|
726
|
+
onClose?.();
|
|
727
|
+
};
|
|
728
|
+
if (form.submitted) {
|
|
729
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: modalStyles.body, testID: withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix), children: [
|
|
730
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.successText, testID: withTestIdPrefix(AuthTestIds.forgotPasswordSuccess, testIdPrefix), children: labels.successMessage }),
|
|
731
|
+
onClose !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: modalStyles.actions, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
732
|
+
reactNative.TouchableOpacity,
|
|
733
|
+
{
|
|
734
|
+
accessibilityHint: labels.close,
|
|
735
|
+
accessibilityLabel: labels.close,
|
|
736
|
+
accessibilityRole: "button",
|
|
737
|
+
style: styles.primaryButton,
|
|
738
|
+
testID: withTestIdPrefix(AuthTestIds.forgotPasswordCloseButton, testIdPrefix),
|
|
739
|
+
onPress: handleClose,
|
|
740
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.primaryButtonText, children: labels.close })
|
|
741
|
+
}
|
|
742
|
+
) }) : null
|
|
743
|
+
] });
|
|
744
|
+
}
|
|
745
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: modalStyles.body, testID: withTestIdPrefix(AuthTestIds.forgotPasswordForm, testIdPrefix), children: [
|
|
746
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.subtitle, children: labels.description }),
|
|
747
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.fieldGroup, children: [
|
|
748
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.label, children: labels.emailLabel }),
|
|
749
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
750
|
+
reactNative.TextInput,
|
|
751
|
+
{
|
|
752
|
+
accessibilityHint: labels.emailPlaceholder,
|
|
753
|
+
accessibilityLabel: labels.emailLabel,
|
|
754
|
+
autoCapitalize: "none",
|
|
755
|
+
autoCorrect: false,
|
|
756
|
+
editable: !form.isSubmitting,
|
|
757
|
+
keyboardType: "email-address",
|
|
758
|
+
placeholder: labels.emailPlaceholder,
|
|
759
|
+
placeholderTextColor: theme.colors.textSecondary,
|
|
760
|
+
style: styles.input,
|
|
761
|
+
testID: withTestIdPrefix(AuthTestIds.forgotPasswordEmailInput, testIdPrefix),
|
|
762
|
+
value: form.email,
|
|
763
|
+
onChangeText: form.setEmail
|
|
764
|
+
}
|
|
765
|
+
)
|
|
766
|
+
] }),
|
|
767
|
+
form.hasNetworkError ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.errorText, testID: withTestIdPrefix(AuthTestIds.forgotPasswordError, testIdPrefix), children: labels.networkError }) : null,
|
|
768
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: modalStyles.actions, children: [
|
|
769
|
+
onCancel !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
770
|
+
reactNative.TouchableOpacity,
|
|
771
|
+
{
|
|
772
|
+
accessibilityHint: labels.cancel,
|
|
773
|
+
accessibilityLabel: labels.cancel,
|
|
774
|
+
accessibilityRole: "button",
|
|
775
|
+
disabled: form.isSubmitting,
|
|
776
|
+
style: modalStyles.secondaryButton,
|
|
777
|
+
testID: withTestIdPrefix(AuthTestIds.forgotPasswordCancelButton, testIdPrefix),
|
|
778
|
+
onPress: handleCancel,
|
|
779
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: modalStyles.secondaryButtonText, children: labels.cancel })
|
|
780
|
+
}
|
|
781
|
+
) : null,
|
|
782
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
783
|
+
reactNative.TouchableOpacity,
|
|
784
|
+
{
|
|
785
|
+
accessibilityHint: labels.submit,
|
|
786
|
+
accessibilityLabel: form.isSubmitting ? labels.submitting : labels.submit,
|
|
787
|
+
accessibilityRole: "button",
|
|
788
|
+
disabled: !form.canSubmit,
|
|
789
|
+
style: submitButtonStyle,
|
|
790
|
+
testID: withTestIdPrefix(AuthTestIds.forgotPasswordSubmitButton, testIdPrefix),
|
|
791
|
+
onPress: form.submit,
|
|
792
|
+
children: form.isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.primaryButtonText, children: labels.submit })
|
|
793
|
+
}
|
|
794
|
+
)
|
|
795
|
+
] })
|
|
796
|
+
] });
|
|
797
|
+
}
|
|
599
798
|
|
|
600
799
|
// src/hooks/ResetPasswordError.ts
|
|
601
800
|
var ResetPasswordError = /* @__PURE__ */ ((ResetPasswordError2) => {
|
|
@@ -1097,9 +1296,9 @@ function useOtpLogin(options) {
|
|
|
1097
1296
|
]
|
|
1098
1297
|
);
|
|
1099
1298
|
}
|
|
1100
|
-
var
|
|
1299
|
+
var EMAIL_REGEX3 = /^[^@\s]+@[^.\s]+\.[^\s]+$/;
|
|
1101
1300
|
function isValidEmail2(value) {
|
|
1102
|
-
return
|
|
1301
|
+
return EMAIL_REGEX3.test(value);
|
|
1103
1302
|
}
|
|
1104
1303
|
function transportErrorFor(step, error, labels) {
|
|
1105
1304
|
if (error === null) {
|
|
@@ -1380,11 +1579,13 @@ Object.defineProperty(exports, "createFetchHttpClient", {
|
|
|
1380
1579
|
exports.AuthTestIds = AuthTestIds;
|
|
1381
1580
|
exports.AuthThemeProvider = AuthThemeProvider;
|
|
1382
1581
|
exports.BffAuthStatus = BffAuthStatus;
|
|
1582
|
+
exports.DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS = DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS;
|
|
1383
1583
|
exports.DEFAULT_FORGOT_PASSWORD_LABELS = DEFAULT_FORGOT_PASSWORD_LABELS;
|
|
1384
1584
|
exports.DEFAULT_LOGIN_LABELS = DEFAULT_LOGIN_LABELS;
|
|
1385
1585
|
exports.DEFAULT_OTP_LABELS = DEFAULT_OTP_LABELS;
|
|
1386
1586
|
exports.DEFAULT_PIN_LABELS = DEFAULT_PIN_LABELS;
|
|
1387
1587
|
exports.DEFAULT_RESET_PASSWORD_LABELS = DEFAULT_RESET_PASSWORD_LABELS;
|
|
1588
|
+
exports.ForgotPasswordFields = ForgotPasswordFields;
|
|
1388
1589
|
exports.ForgotPasswordForm = ForgotPasswordForm;
|
|
1389
1590
|
exports.LoginForm = LoginForm;
|
|
1390
1591
|
exports.OtpForm = OtpForm;
|
|
@@ -1399,11 +1600,13 @@ exports.collectUserRoles = collectUserRoles;
|
|
|
1399
1600
|
exports.createBffAuthClient = createBffAuthClient;
|
|
1400
1601
|
exports.defaultAuthTheme = defaultAuthTheme;
|
|
1401
1602
|
exports.isPasswordValid = isPasswordValid;
|
|
1603
|
+
exports.isValidForgotPasswordEmail = isValidForgotPasswordEmail;
|
|
1402
1604
|
exports.resolvePostLoginRoute = resolvePostLoginRoute;
|
|
1403
1605
|
exports.useAuthTheme = useAuthTheme;
|
|
1404
1606
|
exports.useBffAuth = useBffAuth;
|
|
1405
1607
|
exports.useBffForgotPassword = useBffForgotPassword;
|
|
1406
1608
|
exports.useBffResetPassword = useBffResetPassword;
|
|
1609
|
+
exports.useForgotPasswordSubmit = useForgotPasswordSubmit;
|
|
1407
1610
|
exports.useOtpLogin = useOtpLogin;
|
|
1408
1611
|
exports.usePinLogin = usePinLogin;
|
|
1409
1612
|
exports.useResetPasswordForm = useResetPasswordForm;
|