@movmo_app/react-common 0.14.1 → 0.16.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.ts CHANGED
@@ -28,7 +28,11 @@ export declare class AuthError extends Error {
28
28
  code: AuthErrorCode | 'network' | 'unknown';
29
29
  retryAfter?: number | undefined;
30
30
  attemptsRemaining?: number | undefined;
31
- constructor(status: number, code: AuthErrorCode | 'network' | 'unknown', retryAfter?: number | undefined, attemptsRemaining?: number | undefined);
31
+ /** RFC3339 end of the account-recovery cool-down (`recovery_cooldown` bodies). */
32
+ until?: string | undefined;
33
+ constructor(status: number, code: AuthErrorCode | 'network' | 'unknown', retryAfter?: number | undefined, attemptsRemaining?: number | undefined,
34
+ /** RFC3339 end of the account-recovery cool-down (`recovery_cooldown` bodies). */
35
+ until?: string | undefined);
32
36
  }
33
37
 
34
38
  /** Autofill options live 5 min on the server; refresh at 4½. */
@@ -341,8 +345,25 @@ export declare interface ModalProps {
341
345
 
342
346
  /** Typed client for every Movmo sign-in and passkey-management call. */
343
347
  export declare interface MovmoAuthApi {
344
- login(email: string): Promise<MovmoLoginResponse>;
348
+ /**
349
+ * `POST /v1/auth/login`. `deferCode` sends `defer_code: true`: an unenrolled
350
+ * email's flow is created without sending a code (`sendCode` releases the
351
+ * first send); used by the partner iframe.
352
+ */
353
+ login(email: string, opts?: {
354
+ deferCode?: boolean;
355
+ }): Promise<MovmoLoginResponse>;
345
356
  sendCode(flowId: string): Promise<MovmoCodeFlow>;
357
+ /**
358
+ * `POST /v1/auth/recovery {flow_id, time_zone?}`: starts account recovery for
359
+ * an enrolled email's unsent flow; the answer is a code flow (MOVMO-687).
360
+ */
361
+ startRecovery(flowId: string): Promise<MovmoCodeFlow>;
362
+ /**
363
+ * `POST /v1/auth/recovery/cancel {token}`. A token that isn't `rc1.` +
364
+ * base64url rejects with `invalid_request` before any request.
365
+ */
366
+ cancelRecovery(token: string): Promise<void>;
346
367
  passkeyOptions(): Promise<PasskeyOptionsResponse>;
347
368
  verifyCode(flowId: string, code: string): Promise<MovmoVerifyResponse>;
348
369
  verifyPasskey(flowId: string, credential: CredentialJSON): Promise<MovmoVerifyResponse>;
@@ -373,11 +394,29 @@ export declare interface MovmoSignIn {
373
394
  canUsePasskeyButton: boolean;
374
395
  /** Passkey step: the last ceremony failed; offer Try again (`retryPasskey`). */
375
396
  passkeyFailed: boolean;
397
+ /** False on re-auth (`lockedEmail`/`expectedUserId`): the passkey step offers no recovery entry. */
398
+ recoveryAvailable: boolean;
399
+ /** Recovery step: the server refused recovery (`recovery_blocked`); terminal, only Close remains. */
400
+ recoveryBlocked: boolean;
401
+ /**
402
+ * Framed passkeys: the browser won't run the passkey ceremony in this frame
403
+ * (`topOrigin_required`, or remembered). The passkey step offers `continueTopLevel`.
404
+ */
405
+ topLevelRequired: boolean;
406
+ /** Framed window with `framedPasskeys`: the passkey step always offers "Continue in a new window". */
407
+ framedPasskeys: boolean;
376
408
  liveMessage: string;
377
409
  submitEmail(): void;
378
410
  signInWithPasskey(): void;
379
411
  retryPasskey(): void;
380
- useCodeInstead(): void;
412
+ /** Passkey step, `topLevelRequired`: calls `onContinueTopLevel` synchronously (inside the click). */
413
+ continueTopLevel(): void;
414
+ /** Passkey step: "I can't use my passkey" → the recovery step (aborts the ceremony). No-op on re-auth. */
415
+ cantUsePasskey(): void;
416
+ /** Recovery step: `POST /v1/auth/recovery`, then the code step. */
417
+ sendRecoveryCode(): void;
418
+ /** Recovery step: back to the passkey step (email step when passkeys can't be used here). */
419
+ back(): void;
381
420
  /** Passkey/code step: back to email with the email kept. */
382
421
  changeEmail(): void;
383
422
  submitCode(code: string): void;
@@ -571,6 +610,13 @@ export declare interface PasskeyListProps {
571
610
  * sign-in.
572
611
  */
573
612
  onAccountMismatch: () => void;
613
+ /**
614
+ * RFC3339 end of the account-recovery cool-down (the host's
615
+ * `security-preferences.recovery_until`). While it is in the future the card
616
+ * shows the in-progress status line and disables Add and Remove up front,
617
+ * without waiting for a `403 recovery_cooldown`.
618
+ */
619
+ recoveryUntil?: string | null;
574
620
  }
575
621
 
576
622
  export declare const PhoneInput: default_2.FC<PhoneInputProps>;
@@ -645,8 +691,8 @@ export declare function readPromptState(cookie?: string, now?: number): PromptSt
645
691
  *
646
692
  * The sign-in flow runs email-first only, with the account's email locked,
647
693
  * and continues at once (`autoContinue`): the login's `allowCredentials` limit
648
- * a passkey choice to this account, and **Use a code instead** stays
649
- * available. No autofill, no discoverable "Sign in with passkey", no
694
+ * a passkey choice to this account. The passkey step offers no recovery
695
+ * entry ("I can't use my passkey"): recovery starts from the sign-in page. No autofill, no discoverable "Sign in with passkey", no
650
696
  * enrollment prompt. The flow is single-use and is mounted only while open,
651
697
  * so every open starts fresh. In a framed window it only says "Manage
652
698
  * passkeys on the Movmo Security page." and makes no sign-in or WebAuthn call.
@@ -758,8 +804,15 @@ export declare const signInCopy: {
758
804
  readonly passkeyExists: "This passkey is already on your account.";
759
805
  readonly enrollExpired: "That took too long. Try again.";
760
806
  readonly invalidEmail: "Enter a valid email address.";
761
- readonly passkeyUnavailable: "This browser couldn't use a passkey. Use a code instead.";
807
+ readonly passkeyUnavailable: "This browser couldn't use a passkey. Choose 'I can't use my passkey' to sign in with a code.";
762
808
  readonly discoverableNotRecognized: "That passkey isn't recognized. Continue with your email instead.";
809
+ readonly recoveryStarted: "Sign in without your passkey";
810
+ /** Framed passkeys (MOVMO-686): the browser won't run the passkey ceremony inside the frame. */
811
+ readonly topLevelRequired: "Your browser needs a separate window to use your passkey.";
812
+ readonly continueTopLevel: "Continue in a new window";
813
+ /** Framed passkeys: any browser-side failure; never points a framed user at account recovery first. */
814
+ readonly framedPasskeyFailed: "Your passkey didn't work here. Try again, or continue in a new window.";
815
+ readonly recoveryBlocked: "We can't recover this account right now";
763
816
  };
764
817
 
765
818
  export declare type SignInErrorCode = AuthErrorCode | 'network' | 'unknown' | WebAuthnFailure | 'account_mismatch';
@@ -786,7 +839,14 @@ export declare interface SignInFlowProps extends UseMovmoSignInOptions {
786
839
  onCancel?: () => void;
787
840
  }
788
841
 
789
- export declare type SignInMethod = 'otp' | 'passkey';
842
+ /** What `onVerified`/`onSignedIn` receive. `recoveryUntil` (RFC3339) is set only for `method: 'recovery'`. */
843
+ export declare interface SignInInfo {
844
+ method: SignInMethod;
845
+ newUser: boolean;
846
+ recoveryUntil?: string;
847
+ }
848
+
849
+ export declare type SignInMethod = 'otp' | 'passkey' | 'recovery';
790
850
 
791
851
  /**
792
852
  * "Sign in to Movmo": `SignInFlow` inside the focus-trapping `Modal`. Code or
@@ -816,14 +876,11 @@ export declare interface SignInModalProps extends Omit<UseMovmoSignInOptions, 'o
816
876
  * the prompt; `onAccountMismatch` (re-auth with `expectedUserId`) fires
817
877
  * after the package has ended the other account's session.
818
878
  */
819
- onLoginSuccess: (user: User, info: {
820
- method: SignInMethod;
821
- newUser: boolean;
822
- }) => void;
879
+ onLoginSuccess: (user: User, info: SignInInfo) => void;
823
880
  }
824
881
 
825
882
  /** `mismatch` is terminal: re-auth signed in a different account (see `onAccountMismatch`). */
826
- export declare type SignInStep = 'email' | 'passkey' | 'code' | 'enroll' | 'enrolled' | 'done' | 'mismatch';
883
+ export declare type SignInStep = 'email' | 'passkey' | 'recovery' | 'code' | 'enroll' | 'enrolled' | 'done' | 'mismatch';
827
884
 
828
885
  export declare const Textarea: React_2.ForwardRefExoticComponent<TextareaProps & React_2.RefAttributes<HTMLTextAreaElement>>;
829
886
 
@@ -874,20 +931,14 @@ export declare interface UseMovmoSignInOptions {
874
931
  surface: 'top-level' | 'embedded';
875
932
  getCurrentUser: () => Promise<User>;
876
933
  /** The traveler is signed in: fires exactly once, after the enrollment prompt when one is shown. */
877
- onSignedIn: (user: User, info: {
878
- method: SignInMethod;
879
- newUser: boolean;
880
- }) => void;
934
+ onSignedIn: (user: User, info: SignInInfo) => void;
881
935
  /**
882
936
  * Fires once, right after a successful verify and `getCurrentUser()` (the
883
937
  * server session exists), BEFORE the enrollment prompt. Use it for work that
884
938
  * mustn't wait for the traveler to answer the prompt; `onSignedIn` keeps its
885
939
  * meaning.
886
940
  */
887
- onVerified?: (user: User, info: {
888
- method: SignInMethod;
889
- newUser: boolean;
890
- }) => void;
941
+ onVerified?: (user: User, info: SignInInfo) => void;
891
942
  /**
892
943
  * Re-auth only (`expectedUserId`): a different account signed in. The server
893
944
  * session has already been ended by the package (`api.logout()`) when this
@@ -908,6 +959,36 @@ export declare interface UseMovmoSignInOptions {
908
959
  */
909
960
  expectedUserId?: string;
910
961
  promptSurface?: 'modal' | 'connect';
962
+ /**
963
+ * A framed window may run the email-first passkey `get()` (the embedding SDK
964
+ * granted `publickey-credentials-get` on the iframe). Default false. Never
965
+ * enables autofill, the passkey button, enrollment or `create()`.
966
+ */
967
+ framedPasskeys?: boolean;
968
+ /**
969
+ * The `/v1/auth/login` response the app already obtained, expected from
970
+ * `api.login(email, { deferCode: true })`: adopted on mount instead of asking
971
+ * for an email. `next:"passkey"` runs the ceremony at once (the app must call
972
+ * within the click's transient activation, ~5 s); `next:"code"` sends the first
973
+ * code (`/v1/auth/code` on the deferred flow) and shows the code step. The
974
+ * email comes from `initialEmail` / `lockedEmail`. `api.login` is not called.
975
+ */
976
+ resumeLogin?: MovmoLoginResponse;
977
+ /**
978
+ * `continueTopLevel()` calls this synchronously (the app opens its popup
979
+ * inside the click; nothing may `await` before it) with the flow's current
980
+ * email, the one the ceremony ran for (it may differ from `initialEmail`
981
+ * after an email change).
982
+ */
983
+ onContinueTopLevel?: (email: string) => void;
984
+ /**
985
+ * With `resumeLogin`: the passkey/code step's "Change" calls this instead of showing the
986
+ * hook's own email step, and the host owns the email change. That step
987
+ * calls `api.login` without `deferCode`, which would send a code at once and
988
+ * sign a code user in inside the frame, bypassing the host's popup rule.
989
+ * Without `resumeLogin` or without this, behaviour is unchanged.
990
+ */
991
+ onChangeEmail?: () => void;
911
992
  }
912
993
 
913
994
  export declare const validateEmail: (email: string) => boolean;