@swype-org/react-sdk 0.1.68 → 0.1.70

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.cjs CHANGED
@@ -1618,6 +1618,9 @@ function resolvePostAuthStep(state) {
1618
1618
  }
1619
1619
  return { step: "open-wallet", clearPersistedFlow: false };
1620
1620
  }
1621
+ if (state.mobileSetupInProgress && !hasActiveWallet(state.accounts)) {
1622
+ return { step: "open-wallet", clearPersistedFlow: false };
1623
+ }
1621
1624
  if ((state.accounts.length === 0 || !hasActiveWallet(state.accounts)) && !state.connectingNewAccount) {
1622
1625
  return { step: "wallet-picker", clearPersistedFlow: false };
1623
1626
  }
@@ -1633,6 +1636,9 @@ function resolveRestoredMobileFlow(transferStatus, isSetup) {
1633
1636
  if (transferStatus === "FAILED") {
1634
1637
  return { kind: "resume-failed", step: "success", clearPersistedFlow: true };
1635
1638
  }
1639
+ if (transferStatus === "SENDING" || transferStatus === "SENT") {
1640
+ return { kind: "resume-processing", step: "processing", clearPersistedFlow: true };
1641
+ }
1636
1642
  if (isSetup) {
1637
1643
  return { kind: "resume-stale-setup", step: "wallet-picker", clearPersistedFlow: true };
1638
1644
  }
@@ -3424,6 +3430,8 @@ var outlineBtnWrapStyle = {
3424
3430
  function SuccessScreen({
3425
3431
  amount,
3426
3432
  currency,
3433
+ succeeded,
3434
+ error,
3427
3435
  merchantName,
3428
3436
  sourceName,
3429
3437
  remainingLimit,
@@ -3434,7 +3442,8 @@ function SuccessScreen({
3434
3442
  autoCloseSeconds
3435
3443
  }) {
3436
3444
  const { tokens } = useSwypeConfig();
3437
- const [countdown, setCountdown] = react.useState(autoCloseSeconds ?? 0);
3445
+ const effectiveAutoClose = succeeded ? autoCloseSeconds : void 0;
3446
+ const [countdown, setCountdown] = react.useState(effectiveAutoClose ?? 0);
3438
3447
  const doneCalledRef = react.useRef(false);
3439
3448
  const handleDone = react.useCallback(() => {
3440
3449
  if (doneCalledRef.current) return;
@@ -3442,7 +3451,7 @@ function SuccessScreen({
3442
3451
  onDone();
3443
3452
  }, [onDone]);
3444
3453
  react.useEffect(() => {
3445
- if (!autoCloseSeconds || autoCloseSeconds <= 0) return;
3454
+ if (!effectiveAutoClose || effectiveAutoClose <= 0) return;
3446
3455
  const intervalId = window.setInterval(() => {
3447
3456
  setCountdown((prev) => {
3448
3457
  if (prev <= 1) {
@@ -3453,18 +3462,18 @@ function SuccessScreen({
3453
3462
  });
3454
3463
  }, 1e3);
3455
3464
  return () => window.clearInterval(intervalId);
3456
- }, [autoCloseSeconds]);
3465
+ }, [effectiveAutoClose]);
3457
3466
  react.useEffect(() => {
3458
- if (autoCloseSeconds && countdown === 0) {
3467
+ if (effectiveAutoClose && countdown === 0) {
3459
3468
  handleDone();
3460
3469
  }
3461
- }, [autoCloseSeconds, countdown, handleDone]);
3470
+ }, [effectiveAutoClose, countdown, handleDone]);
3462
3471
  return /* @__PURE__ */ jsxRuntime.jsxs(
3463
3472
  ScreenLayout,
3464
3473
  {
3465
3474
  footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3466
- /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: handleDone, children: "Done" }),
3467
- autoCloseSeconds != null && autoCloseSeconds > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: countdownStyle(tokens.textMuted), children: [
3475
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: handleDone, children: succeeded ? "Done" : "Try again" }),
3476
+ effectiveAutoClose != null && effectiveAutoClose > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: countdownStyle(tokens.textMuted), children: [
3468
3477
  "Returning to app in ",
3469
3478
  countdown,
3470
3479
  "s\u2026"
@@ -3480,26 +3489,32 @@ function SuccessScreen({
3480
3489
  }
3481
3490
  ),
3482
3491
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle4, children: [
3483
- /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "success", size: 64, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z", fill: tokens.success }) }) }),
3484
- /* @__PURE__ */ jsxRuntime.jsxs("h2", { style: headingStyle6(tokens.text), children: [
3485
- "$",
3486
- amount.toFixed(2),
3487
- " deposited"
3488
- ] }),
3489
- merchantName && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: subtitleStyle6(tokens.textSecondary), children: [
3490
- "to ",
3491
- merchantName
3492
+ succeeded ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3493
+ /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "success", size: 64, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z", fill: tokens.success }) }) }),
3494
+ /* @__PURE__ */ jsxRuntime.jsxs("h2", { style: headingStyle6(tokens.text), children: [
3495
+ "$",
3496
+ amount.toFixed(2),
3497
+ " deposited"
3498
+ ] }),
3499
+ merchantName && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: subtitleStyle6(tokens.textSecondary), children: [
3500
+ "to ",
3501
+ merchantName
3502
+ ] })
3503
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3504
+ /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "error", size: 64, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z", fill: tokens.error }) }) }),
3505
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle6(tokens.text), children: "Transfer failed" }),
3506
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle6(tokens.error), children: error })
3492
3507
  ] }),
3493
3508
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryCardStyle(tokens), children: [
3494
3509
  sourceName && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
3495
3510
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryLabelStyle(tokens.textMuted), children: "From" }),
3496
3511
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryValueStyle(tokens.text), children: sourceName })
3497
3512
  ] }),
3498
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
3513
+ succeeded && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
3499
3514
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryLabelStyle(tokens.textMuted), children: "Time" }),
3500
3515
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryValueStyle(tokens.text), children: "just now" })
3501
3516
  ] }),
3502
- remainingLimit != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
3517
+ succeeded && remainingLimit != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
3503
3518
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryLabelStyle(tokens.textMuted), children: "Remaining limit" }),
3504
3519
  /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { ...summaryValueStyle(tokens.text), color: tokens.accent }, children: [
3505
3520
  "$",
@@ -3507,7 +3522,7 @@ function SuccessScreen({
3507
3522
  ] })
3508
3523
  ] })
3509
3524
  ] }),
3510
- onIncreaseLimits && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: upsellCardStyle(tokens), children: [
3525
+ succeeded && onIncreaseLimits && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: upsellCardStyle(tokens), children: [
3511
3526
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: upsellHeaderStyle, children: [
3512
3527
  /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { marginRight: 6 }, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 14l5-5 5 5", stroke: tokens.accent, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
3513
3528
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Want higher limits?" })
@@ -3989,12 +4004,11 @@ var radioDotStyle2 = (color) => ({
3989
4004
  borderRadius: "50%",
3990
4005
  background: color
3991
4006
  });
3992
- var STEP_LABELS = ["Creating transfer", "Verifying", "Sent", "Done"];
4007
+ var STEP_LABELS = ["Creating transfer", "Verifying", "Sent"];
3993
4008
  var PHASE_ACTIVE_INDEX = {
3994
4009
  creating: 0,
3995
4010
  verifying: 1,
3996
- sent: 2,
3997
- done: 4
4011
+ sent: 2
3998
4012
  };
3999
4013
  function buildSteps(phase) {
4000
4014
  const activeIdx = PHASE_ACTIVE_INDEX[phase];
@@ -4513,13 +4527,13 @@ function SwypePaymentInner({
4513
4527
  polling.startPolling(persisted.transferId);
4514
4528
  }, [polling]);
4515
4529
  const handleAuthorizedMobileReturn = react.useCallback(async (authorizedTransfer, isSetup) => {
4516
- setTransfer(authorizedTransfer);
4517
4530
  polling.stopPolling();
4518
4531
  if (isSetup) {
4519
4532
  mobileSetupFlowRef.current = false;
4520
4533
  clearMobileFlowState();
4521
4534
  try {
4522
4535
  await reloadAccounts();
4536
+ setTransfer(null);
4523
4537
  setError(null);
4524
4538
  setDeeplinkUri(null);
4525
4539
  setMobileFlow(false);
@@ -4532,6 +4546,7 @@ function SwypePaymentInner({
4532
4546
  }
4533
4547
  return;
4534
4548
  }
4549
+ setTransfer(authorizedTransfer);
4535
4550
  mobileSetupFlowRef.current = false;
4536
4551
  clearMobileFlowState();
4537
4552
  setError(null);
@@ -4648,6 +4663,7 @@ function SwypePaymentInner({
4648
4663
  hasPasskey: true,
4649
4664
  accounts: accts,
4650
4665
  persistedMobileFlow: persisted,
4666
+ mobileSetupInProgress: false,
4651
4667
  connectingNewAccount: false
4652
4668
  });
4653
4669
  if (resolved.clearPersistedFlow) {
@@ -4688,6 +4704,16 @@ function SwypePaymentInner({
4688
4704
  setStep("success");
4689
4705
  return;
4690
4706
  }
4707
+ if (mobileResolution.kind === "resume-processing") {
4708
+ clearMobileFlowState();
4709
+ setMobileFlow(false);
4710
+ setDeeplinkUri(null);
4711
+ setTransfer(existingTransfer);
4712
+ setError(null);
4713
+ setStep("processing");
4714
+ polling.startPolling(existingTransfer.id);
4715
+ return;
4716
+ }
4691
4717
  if (mobileResolution.kind === "resume-stale-setup") {
4692
4718
  clearMobileFlowState();
4693
4719
  if (!cancelled) setStep("wallet-picker");
@@ -5184,6 +5210,7 @@ function SwypePaymentInner({
5184
5210
  processingStartedAtRef.current = null;
5185
5211
  pollingTransferIdRef.current = null;
5186
5212
  mobileSigningTransferIdRef.current = null;
5213
+ preSelectSourceStepRef.current = null;
5187
5214
  setConnectingNewAccount(false);
5188
5215
  setSelectedWalletId(null);
5189
5216
  if (accounts.length > 0) setSelectedAccountId(accounts[0].id);
@@ -5214,6 +5241,7 @@ function SwypePaymentInner({
5214
5241
  setAmount(depositAmount != null ? depositAmount.toString() : "");
5215
5242
  setMobileFlow(false);
5216
5243
  setDeeplinkUri(null);
5244
+ preSelectSourceStepRef.current = null;
5217
5245
  resetHeadlessLogin();
5218
5246
  }, [logout, polling, depositAmount, resetHeadlessLogin]);
5219
5247
  const handleConfirmSign = react.useCallback(async () => {
@@ -5224,12 +5252,13 @@ function SwypePaymentInner({
5224
5252
  setTransfer(signedTransfer);
5225
5253
  clearMobileFlowState();
5226
5254
  setStep("processing");
5255
+ polling.startPolling(t.id);
5227
5256
  } catch (err) {
5228
5257
  const msg = err instanceof Error ? err.message : "Failed to sign transfer";
5229
5258
  setError(msg);
5230
5259
  onError?.(msg);
5231
5260
  }
5232
- }, [transfer, polling.transfer, transferSigning, onError]);
5261
+ }, [transfer, polling.transfer, polling.startPolling, transferSigning, onError]);
5233
5262
  if (!ready) {
5234
5263
  return /* @__PURE__ */ jsxRuntime.jsx(ScreenLayout, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: "48px 0", flex: 1, display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { label: "Initializing..." }) }) });
5235
5264
  }
@@ -5354,7 +5383,7 @@ function SwypePaymentInner({
5354
5383
  }
5355
5384
  if (step === "processing") {
5356
5385
  const polledStatus = polling.transfer?.status;
5357
- const transferPhase = creatingTransfer ? "creating" : mobileFlow || authExecutor.executing || transferSigning.signing ? "verifying" : polledStatus === "SENDING" || polledStatus === "SENT" || polling.isPolling ? "sent" : "creating";
5386
+ const transferPhase = creatingTransfer ? "creating" : polledStatus === "SENDING" || polledStatus === "SENT" ? "sent" : "verifying";
5358
5387
  return /* @__PURE__ */ jsxRuntime.jsx(
5359
5388
  TransferStatusScreen,
5360
5389
  {
@@ -5385,7 +5414,7 @@ function SwypePaymentInner({
5385
5414
  );
5386
5415
  }
5387
5416
  if (step === "success") {
5388
- transfer?.status === "COMPLETED";
5417
+ const succeeded = transfer?.status === "COMPLETED";
5389
5418
  const displayAmount = transfer?.amount?.amount ?? 0;
5390
5419
  const displayCurrency = transfer?.amount?.currency ?? "USD";
5391
5420
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -5393,12 +5422,14 @@ function SwypePaymentInner({
5393
5422
  {
5394
5423
  amount: displayAmount,
5395
5424
  currency: displayCurrency,
5425
+ succeeded,
5426
+ error,
5396
5427
  merchantName,
5397
5428
  sourceName,
5398
- remainingLimit: (() => {
5429
+ remainingLimit: succeeded ? (() => {
5399
5430
  const limit = selectedAccount?.remainingAllowance ?? oneTapLimit;
5400
5431
  return limit > displayAmount ? limit - displayAmount : 0;
5401
- })(),
5432
+ })() : void 0,
5402
5433
  onDone: onDismiss ?? handleNewPayment,
5403
5434
  onLogout: handleLogout,
5404
5435
  autoCloseSeconds