@swype-org/react-sdk 0.1.329 → 0.1.333

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.cts CHANGED
@@ -958,8 +958,16 @@ interface PasskeyScreenProps {
958
958
  popupFallback?: boolean;
959
959
  /** Opens a pop-up window on the Blink domain for passkey registration. */
960
960
  onCreatePasskeyViaPopup?: () => void;
961
- }
962
- declare function PasskeyScreen({ onCreatePasskey, onBack, onLogout, creating, error, popupFallback, onCreatePasskeyViaPopup, }: PasskeyScreenProps): react_jsx_runtime.JSX.Element;
961
+ /** Creates a brand-new passkey on this device (for users who already have one on another device). */
962
+ onCreateNewPasskey?: () => void;
963
+ /** Popup fallback variant of onCreateNewPasskey. */
964
+ onCreateNewPasskeyViaPopup?: () => void;
965
+ /** When set, overrides `popupFallback` for the create-new link only. */
966
+ createNewPopupFallback?: boolean;
967
+ /** Loading state while a new passkey is being created. */
968
+ creatingNewPasskey?: boolean;
969
+ }
970
+ declare function PasskeyScreen({ onCreatePasskey, onBack, onLogout, creating, error, popupFallback, onCreatePasskeyViaPopup, onCreateNewPasskey, onCreateNewPasskeyViaPopup, createNewPopupFallback, creatingNewPasskey, }: PasskeyScreenProps): react_jsx_runtime.JSX.Element;
963
971
 
964
972
  interface VerifyPasskeyScreenProps {
965
973
  onVerify: () => void;
package/dist/index.d.ts CHANGED
@@ -958,8 +958,16 @@ interface PasskeyScreenProps {
958
958
  popupFallback?: boolean;
959
959
  /** Opens a pop-up window on the Blink domain for passkey registration. */
960
960
  onCreatePasskeyViaPopup?: () => void;
961
- }
962
- declare function PasskeyScreen({ onCreatePasskey, onBack, onLogout, creating, error, popupFallback, onCreatePasskeyViaPopup, }: PasskeyScreenProps): react_jsx_runtime.JSX.Element;
961
+ /** Creates a brand-new passkey on this device (for users who already have one on another device). */
962
+ onCreateNewPasskey?: () => void;
963
+ /** Popup fallback variant of onCreateNewPasskey. */
964
+ onCreateNewPasskeyViaPopup?: () => void;
965
+ /** When set, overrides `popupFallback` for the create-new link only. */
966
+ createNewPopupFallback?: boolean;
967
+ /** Loading state while a new passkey is being created. */
968
+ creatingNewPasskey?: boolean;
969
+ }
970
+ declare function PasskeyScreen({ onCreatePasskey, onBack, onLogout, creating, error, popupFallback, onCreatePasskeyViaPopup, onCreateNewPasskey, onCreateNewPasskeyViaPopup, createNewPopupFallback, creatingNewPasskey, }: PasskeyScreenProps): react_jsx_runtime.JSX.Element;
963
971
 
964
972
  interface VerifyPasskeyScreenProps {
965
973
  onVerify: () => void;
package/dist/index.js CHANGED
@@ -1948,7 +1948,7 @@ function resolvePhase(state) {
1948
1948
  const isFundingSourceSubflow = !state.loginRequested && (currentPhase.step === "token-picker" || currentPhase.step === "one-tap-setup" || currentPhase.step === "select-source" || currentPhase.step === "confirm-sign" || currentPhase.step === "guest-token-picker" && guestTokenPickerEligible);
1949
1949
  const walletPickerSwitchEligible = currentPhase.step === "wallet-picker" && currentPhase.reason === "switch" && !state.creatingTransfer && !(state.mobileFlow && state.deeplinkUri);
1950
1950
  const missingActivePasskeyCredential = state.passkeyConfigLoaded && !state.activeCredentialId;
1951
- const shouldPromptPasskeyVerification = missingActivePasskeyCredential && state.knownCredentialIds.length > 0 && state.passkeyPopupNeeded;
1951
+ const shouldPromptPasskeyVerification = missingActivePasskeyCredential && state.knownCredentialIds.length > 0;
1952
1952
  const guestPreauthClaimPending = state.guestPreauthAccountId != null && state.guestSessionToken != null && state.privyAuthenticated && state.activeCredentialId != null && !state.guestPreauthSetupCompletePending && !state.error;
1953
1953
  const branchGuestSetupComplete = state.guestPreauthSetupCompletePending && state.privyReady && state.privyAuthenticated;
1954
1954
  const branchKeepGuestPreauthPin = !branchGuestSetupComplete && guestPreauthPinsCurrentPhase;
@@ -3757,16 +3757,33 @@ function PasskeyScreen({
3757
3757
  creating,
3758
3758
  error,
3759
3759
  popupFallback = false,
3760
- onCreatePasskeyViaPopup
3760
+ onCreatePasskeyViaPopup,
3761
+ onCreateNewPasskey,
3762
+ onCreateNewPasskeyViaPopup,
3763
+ createNewPopupFallback,
3764
+ creatingNewPasskey
3761
3765
  }) {
3762
3766
  const { tokens } = useBlinkConfig();
3763
3767
  const handleCreate = popupFallback && onCreatePasskeyViaPopup ? onCreatePasskeyViaPopup : onCreatePasskey;
3764
3768
  const buttonLabel = popupFallback ? "Open Passkey Window" : "Verify Passkey";
3769
+ const showCreateNewLink = onCreateNewPasskey != null;
3770
+ const usePopupForNew = createNewPopupFallback ?? popupFallback;
3771
+ const handleCreateNew = usePopupForNew && onCreateNewPasskeyViaPopup ? onCreateNewPasskeyViaPopup : onCreateNewPasskey;
3765
3772
  return /* @__PURE__ */ jsxs(
3766
3773
  ScreenLayout,
3767
3774
  {
3768
3775
  footer: /* @__PURE__ */ jsxs(Fragment, { children: [
3769
- /* @__PURE__ */ jsx(PrimaryButton, { onClick: handleCreate, disabled: creating, loading: creating, children: buttonLabel }),
3776
+ /* @__PURE__ */ jsx(PrimaryButton, { onClick: handleCreate, disabled: creating || creatingNewPasskey, loading: creating, children: buttonLabel }),
3777
+ showCreateNewLink && /* @__PURE__ */ jsx(
3778
+ "button",
3779
+ {
3780
+ type: "button",
3781
+ onClick: handleCreateNew,
3782
+ disabled: creatingNewPasskey || creating,
3783
+ style: createNewLinkStyle(tokens.textMuted),
3784
+ children: creatingNewPasskey ? "Creating passkey\u2026" : "Create a new passkey for this device"
3785
+ }
3786
+ ),
3770
3787
  /* @__PURE__ */ jsx(PoweredByFooter, {})
3771
3788
  ] }),
3772
3789
  children: [
@@ -3801,6 +3818,17 @@ var subtitleStyle3 = (color) => ({
3801
3818
  margin: "0 0 20px",
3802
3819
  lineHeight: 1.5
3803
3820
  });
3821
+ var createNewLinkStyle = (color) => ({
3822
+ background: "none",
3823
+ border: "none",
3824
+ color,
3825
+ fontSize: "0.85rem",
3826
+ cursor: "pointer",
3827
+ padding: "8px 16px",
3828
+ textDecoration: "underline",
3829
+ fontFamily: "inherit",
3830
+ width: "100%"
3831
+ });
3804
3832
  var errorBannerStyle2 = (tokens) => ({
3805
3833
  background: tokens.errorBg,
3806
3834
  border: `1px solid ${tokens.error}66`,
@@ -4984,13 +5012,14 @@ function DepositScreen({
4984
5012
  const selectedProviderLogo = KNOWN_LOGOS[selectedProviderName.toLowerCase()];
4985
5013
  const totalAccountBalance = selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : availableBalance;
4986
5014
  const isLowBalance = availableBalance < minDepositFloor;
5015
+ const insufficientFunds = availableBalance < amount;
4987
5016
  const exceedsLimit = remainingLimit != null && amount > remainingLimit && !isLowBalance;
4988
- const canDeposit = amount >= minDepositFloor && !exceedsLimit && !isLowBalance && !processing;
5017
+ const canDeposit = amount >= minDepositFloor && !exceedsLimit && !isLowBalance && !insufficientFunds && !processing;
4989
5018
  return /* @__PURE__ */ jsxs(
4990
5019
  ScreenLayout,
4991
5020
  {
4992
5021
  footer: /* @__PURE__ */ jsxs(Fragment, { children: [
4993
- !accountPickerOpen && !tokenPickerOpen && (exceedsLimit && onIncreaseLimit ? /* @__PURE__ */ jsx(PrimaryButton, { onClick: onIncreaseLimit, loading: increasingLimit, children: "Increase limit" }) : /* @__PURE__ */ jsx(PrimaryButton, { onClick: () => onDeposit(amount), disabled: !canDeposit, loading: processing, children: "Confirm" })),
5022
+ !accountPickerOpen && !tokenPickerOpen && (exceedsLimit && onIncreaseLimit ? /* @__PURE__ */ jsx(PrimaryButton, { onClick: onIncreaseLimit, loading: increasingLimit, children: "Increase limit" }) : /* @__PURE__ */ jsx(PrimaryButton, { onClick: () => onDeposit(amount), disabled: !canDeposit, loading: processing, children: insufficientFunds ? "Insufficient Funds" : "Confirm" })),
4994
5023
  /* @__PURE__ */ jsx(PoweredByFooter, {})
4995
5024
  ] }),
4996
5025
  children: [
@@ -7308,13 +7337,15 @@ function StepRendererContent({
7308
7337
  return /* @__PURE__ */ jsx(
7309
7338
  PasskeyScreen,
7310
7339
  {
7311
- onCreatePasskey: handlers.onRegisterPasskey,
7340
+ onCreatePasskey: handlers.onVerifyPasskey,
7312
7341
  onBack: handlers.onLogout,
7313
7342
  onLogout: handlers.onLogout,
7314
- creating: state.verifyingPasskeyPopup,
7343
+ creating: state.registeringPasskey,
7315
7344
  error: state.error,
7316
- popupFallback: true,
7317
- onCreatePasskeyViaPopup: handlers.onVerifyPasskeyViaPopup
7345
+ onCreateNewPasskey: handlers.onCreateNewPasskey,
7346
+ onCreateNewPasskeyViaPopup: handlers.onCreateNewPasskeyViaPopup,
7347
+ createNewPopupFallback: state.passkeyPopupNeeded,
7348
+ creatingNewPasskey: state.registeringPasskey
7318
7349
  }
7319
7350
  );
7320
7351
  case "wallet-picker": {
@@ -7864,6 +7895,53 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds)
7864
7895
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
7865
7896
  }
7866
7897
  }, [user, knownCredentialIds, activateExistingCredential, completePasskeyRegistration, dispatch]);
7898
+ const handleVerifyPasskey = useCallback(async () => {
7899
+ dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
7900
+ dispatch({ type: "SET_ERROR", error: null });
7901
+ try {
7902
+ const matched = await findDevicePasskey(knownCredentialIds);
7903
+ if (matched) {
7904
+ await activateExistingCredential(matched);
7905
+ } else {
7906
+ dispatch({
7907
+ type: "SET_ERROR",
7908
+ error: "No matching passkey found on this device. Please try again."
7909
+ });
7910
+ }
7911
+ } catch (err) {
7912
+ captureException(err);
7913
+ dispatch({
7914
+ type: "SET_ERROR",
7915
+ error: err instanceof Error ? err.message : "Passkey verification failed."
7916
+ });
7917
+ } finally {
7918
+ dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
7919
+ }
7920
+ }, [knownCredentialIds, activateExistingCredential, dispatch]);
7921
+ const handleCreateNewPasskey = useCallback(async () => {
7922
+ dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
7923
+ dispatch({ type: "SET_ERROR", error: null });
7924
+ try {
7925
+ const passkeyDisplayName = user?.email?.address ?? user?.google?.name ?? user?.id ?? "Blink User";
7926
+ const { credentialId, publicKey } = await createPasskeyCredential({
7927
+ userId: user?.id ?? "unknown",
7928
+ displayName: passkeyDisplayName
7929
+ });
7930
+ await completePasskeyRegistration(credentialId, publicKey);
7931
+ } catch (err) {
7932
+ if (err instanceof PasskeyIframeBlockedError) {
7933
+ dispatch({ type: "SET_PASSKEY_POPUP_NEEDED", needed: true });
7934
+ } else {
7935
+ captureException(err);
7936
+ dispatch({
7937
+ type: "SET_ERROR",
7938
+ error: err instanceof Error ? err.message : "Failed to register passkey"
7939
+ });
7940
+ }
7941
+ } finally {
7942
+ dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
7943
+ }
7944
+ }, [user, completePasskeyRegistration, dispatch]);
7867
7945
  const handleCreatePasskeyViaPopup = useCallback(async () => {
7868
7946
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
7869
7947
  dispatch({ type: "SET_ERROR", error: null });
@@ -7910,6 +7988,35 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds)
7910
7988
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
7911
7989
  }
7912
7990
  }, [user, knownCredentialIds, getAccessToken, apiBaseUrl, activateExistingCredential, dispatch]);
7991
+ const handleCreateNewPasskeyViaPopup = useCallback(async () => {
7992
+ dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
7993
+ dispatch({ type: "SET_ERROR", error: null });
7994
+ try {
7995
+ const token = await getAccessToken();
7996
+ const passkeyDisplayName = user?.email?.address ?? user?.google?.name ?? user?.id ?? "Blink User";
7997
+ const popupOptions = buildPasskeyPopupOptions({
7998
+ userId: user?.id ?? "unknown",
7999
+ displayName: passkeyDisplayName,
8000
+ authToken: token ?? void 0,
8001
+ apiBaseUrl
8002
+ });
8003
+ const { credentialId, publicKey } = await createPasskeyViaPopup(popupOptions);
8004
+ dispatch({ type: "PASSKEY_ACTIVATED", credentialId, publicKey });
8005
+ localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
8006
+ if (token) {
8007
+ reportPasskeyActivity(apiBaseUrl, token, credentialId).catch(() => {
8008
+ });
8009
+ }
8010
+ } catch (err) {
8011
+ captureException(err);
8012
+ dispatch({
8013
+ type: "SET_ERROR",
8014
+ error: err instanceof Error ? err.message : "Failed to register passkey"
8015
+ });
8016
+ } finally {
8017
+ dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
8018
+ }
8019
+ }, [user, getAccessToken, apiBaseUrl, dispatch]);
7913
8020
  const handleVerifyPasskeyViaPopup = useCallback(async () => {
7914
8021
  dispatch({ type: "SET_VERIFYING_PASSKEY", value: true });
7915
8022
  dispatch({ type: "SET_ERROR", error: null });
@@ -7952,7 +8059,10 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds)
7952
8059
  }, [knownCredentialIds, getAccessToken, apiBaseUrl, dispatch]);
7953
8060
  return {
7954
8061
  handleRegisterPasskey,
8062
+ handleVerifyPasskey,
8063
+ handleCreateNewPasskey,
7955
8064
  handleCreatePasskeyViaPopup,
8065
+ handleCreateNewPasskeyViaPopup,
7956
8066
  handleVerifyPasskeyViaPopup,
7957
8067
  checkingPasskeyRef
7958
8068
  };
@@ -9570,28 +9680,6 @@ function usePasskeyCheckEffect(deps) {
9570
9680
  await restoreState(activeCredentialId, token);
9571
9681
  return;
9572
9682
  }
9573
- if (cancelled) return;
9574
- const credentialIds = allPasskeys.map((p) => p.credentialId);
9575
- let matched = null;
9576
- if (isSafari() && isInCrossOriginIframe()) {
9577
- matched = await findDevicePasskeyViaPopup({
9578
- credentialIds,
9579
- rpId: resolvePasskeyRpId(),
9580
- authToken: token ?? void 0,
9581
- apiBaseUrl
9582
- });
9583
- } else {
9584
- matched = await findDevicePasskey(credentialIds);
9585
- }
9586
- if (cancelled) return;
9587
- if (matched) {
9588
- const publicKey = allPasskeys.find((p) => p.credentialId === matched)?.publicKey;
9589
- dispatch({ type: "PASSKEY_ACTIVATED", credentialId: matched, publicKey });
9590
- window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, matched);
9591
- reportPasskeyActivity(apiBaseUrl, token, matched).catch(() => {
9592
- });
9593
- await restoreState(matched, token);
9594
- }
9595
9683
  } catch (err) {
9596
9684
  dispatch({
9597
9685
  type: "PASSKEY_CONFIG_LOADED",
@@ -10654,7 +10742,7 @@ function BlinkPaymentInner({
10654
10742
  paymentReducer,
10655
10743
  {
10656
10744
  depositAmount,
10657
- passkeyPopupNeeded: isSafari() && isInCrossOriginIframe(),
10745
+ passkeyPopupNeeded: isSafari() && isInCrossOriginIframe() && !isDesktop,
10658
10746
  activeCredentialId: typeof window === "undefined" ? null : window.localStorage.getItem(ACTIVE_CREDENTIAL_STORAGE_KEY)
10659
10747
  },
10660
10748
  createInitialState
@@ -11010,7 +11098,10 @@ function BlinkPaymentInner({
11010
11098
  dispatch({ type: "BACK_TO_LOGIN" });
11011
11099
  },
11012
11100
  onRegisterPasskey: passkey.handleRegisterPasskey,
11101
+ onVerifyPasskey: passkey.handleVerifyPasskey,
11102
+ onCreateNewPasskey: passkey.handleCreateNewPasskey,
11013
11103
  onCreatePasskeyViaPopup: passkey.handleCreatePasskeyViaPopup,
11104
+ onCreateNewPasskeyViaPopup: passkey.handleCreateNewPasskeyViaPopup,
11014
11105
  onVerifyPasskeyViaPopup: passkey.handleVerifyPasskeyViaPopup,
11015
11106
  onPrepareProvider: provider.handlePrepareProvider,
11016
11107
  onSelectProvider: provider.handleSelectProvider,