@swype-org/react-sdk 0.1.77 → 0.1.80

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
@@ -692,6 +692,11 @@ function isInCrossOriginIframe() {
692
692
  return true;
693
693
  }
694
694
  }
695
+ function isSafari() {
696
+ if (typeof navigator === "undefined") return false;
697
+ const ua = navigator.userAgent;
698
+ return /Safari/i.test(ua) && !/Chrome|CriOS|Chromium|Edg|OPR|Firefox/i.test(ua);
699
+ }
695
700
  var POPUP_RESULT_TIMEOUT_MS = 12e4;
696
701
  var POPUP_CLOSED_POLL_MS = 500;
697
702
  function createPasskeyViaPopup(options) {
@@ -3242,12 +3247,15 @@ function DepositScreen({
3242
3247
  onChangeSource,
3243
3248
  onSwitchWallet,
3244
3249
  onBack,
3245
- onLogout
3250
+ onLogout,
3251
+ onIncreaseLimit,
3252
+ increasingLimit
3246
3253
  }) {
3247
3254
  const { tokens } = useSwypeConfig();
3248
3255
  const amount = initialAmount;
3249
3256
  const isLowBalance = availableBalance < MIN_DEPOSIT;
3250
- const canDeposit = amount >= MIN_DEPOSIT && amount <= remainingLimit && !isLowBalance && !processing;
3257
+ const exceedsLimit = amount > remainingLimit && !isLowBalance;
3258
+ const canDeposit = amount >= MIN_DEPOSIT && !exceedsLimit && !isLowBalance && !processing;
3251
3259
  const headerTitle = merchantName ? `Deposit to ${merchantName}` : "Deposit";
3252
3260
  if (isLowBalance) {
3253
3261
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -3305,11 +3313,22 @@ function DepositScreen({
3305
3313
  ScreenLayout,
3306
3314
  {
3307
3315
  footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3308
- /* @__PURE__ */ jsxRuntime.jsxs(PrimaryButton, { onClick: () => onDeposit(amount), disabled: !canDeposit, loading: processing, children: [
3309
- "Deposit $",
3310
- amount.toFixed(2)
3316
+ exceedsLimit && onIncreaseLimit ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3317
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onIncreaseLimit, loading: increasingLimit, children: "Increase limit" }),
3318
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: limitExceededHintStyle(tokens.warning), children: [
3319
+ "Your deposit of $",
3320
+ amount.toFixed(2),
3321
+ " exceeds your One-Tap limit of $",
3322
+ remainingLimit.toFixed(2),
3323
+ ". Increase your limit to continue."
3324
+ ] })
3325
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3326
+ /* @__PURE__ */ jsxRuntime.jsxs(PrimaryButton, { onClick: () => onDeposit(amount), disabled: !canDeposit, loading: processing, children: [
3327
+ "Deposit $",
3328
+ amount.toFixed(2)
3329
+ ] }),
3330
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: noApprovalStyle(tokens.textMuted), children: "No approval needed \xB7 within your One-Tap limit" })
3311
3331
  ] }),
3312
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: noApprovalStyle(tokens.textMuted), children: "No approval needed \xB7 within your One-Tap limit" }),
3313
3332
  /* @__PURE__ */ jsxRuntime.jsxs("p", { style: routeStyle(tokens.textMuted), children: [
3314
3333
  "From ",
3315
3334
  sourceName,
@@ -3457,6 +3476,13 @@ var noApprovalStyle = (color) => ({
3457
3476
  color,
3458
3477
  margin: "12px 0 2px"
3459
3478
  });
3479
+ var limitExceededHintStyle = (color) => ({
3480
+ textAlign: "center",
3481
+ fontSize: "0.78rem",
3482
+ color,
3483
+ margin: "12px 0 2px",
3484
+ lineHeight: 1.5
3485
+ });
3460
3486
  var routeStyle = (color) => ({
3461
3487
  textAlign: "center",
3462
3488
  fontSize: "0.75rem",
@@ -4520,7 +4546,9 @@ function SwypePaymentInner({
4520
4546
  const [transfer, setTransfer] = react.useState(null);
4521
4547
  const [creatingTransfer, setCreatingTransfer] = react.useState(false);
4522
4548
  const [registeringPasskey, setRegisteringPasskey] = react.useState(false);
4523
- const [passkeyPopupNeeded, setPasskeyPopupNeeded] = react.useState(false);
4549
+ const [passkeyPopupNeeded, setPasskeyPopupNeeded] = react.useState(
4550
+ () => isSafari() && isInCrossOriginIframe()
4551
+ );
4524
4552
  const [activeCredentialId, setActiveCredentialId] = react.useState(() => {
4525
4553
  if (typeof window === "undefined") return null;
4526
4554
  return window.localStorage.getItem(ACTIVE_CREDENTIAL_STORAGE_KEY);
@@ -4587,7 +4615,7 @@ function SwypePaymentInner({
4587
4615
  try {
4588
4616
  await reloadAccounts();
4589
4617
  resetDataLoadingState();
4590
- setTransfer(null);
4618
+ setTransfer(authorizedTransfer);
4591
4619
  setError(null);
4592
4620
  setDeeplinkUri(null);
4593
4621
  setMobileFlow(false);
@@ -4726,6 +4754,17 @@ function SwypePaymentInner({
4726
4754
  if (resolved.clearPersistedFlow) {
4727
4755
  clearMobileFlowState();
4728
4756
  }
4757
+ if (resolved.step === "deposit" && persisted && persisted.isSetup) {
4758
+ try {
4759
+ const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
4760
+ if (cancelled) return;
4761
+ if (existingTransfer.status === "AUTHORIZED") {
4762
+ await handleAuthorizedMobileReturn(existingTransfer, true);
4763
+ return;
4764
+ }
4765
+ } catch {
4766
+ }
4767
+ }
4729
4768
  if (resolved.step === "open-wallet" && persisted) {
4730
4769
  try {
4731
4770
  const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
@@ -5192,6 +5231,81 @@ function SwypePaymentInner({
5192
5231
  merchantAuthorization,
5193
5232
  transfer
5194
5233
  ]);
5234
+ const [increasingLimit, setIncreasingLimit] = react.useState(false);
5235
+ const handleIncreaseLimit = react.useCallback(async () => {
5236
+ const parsedAmount = depositAmount ?? 5;
5237
+ if (!sourceId) {
5238
+ setError("No account or provider selected.");
5239
+ return;
5240
+ }
5241
+ if (!activeCredentialId) {
5242
+ setError("Create a passkey on this device before continuing.");
5243
+ setStep("create-passkey");
5244
+ return;
5245
+ }
5246
+ setError(null);
5247
+ setIncreasingLimit(true);
5248
+ try {
5249
+ const token = await getAccessToken();
5250
+ if (!token) throw new Error("Not authenticated");
5251
+ let effectiveSourceType = sourceType;
5252
+ let effectiveSourceId = sourceId;
5253
+ if (effectiveSourceType === "accountId") {
5254
+ const acct = accounts.find((a) => a.id === effectiveSourceId);
5255
+ const activeWallet = acct?.wallets.find((w) => w.status === "ACTIVE");
5256
+ if (activeWallet) {
5257
+ effectiveSourceType = "walletId";
5258
+ effectiveSourceId = activeWallet.id;
5259
+ }
5260
+ }
5261
+ const t = await createTransfer(apiBaseUrl, token, {
5262
+ id: idempotencyKey,
5263
+ credentialId: activeCredentialId,
5264
+ merchantAuthorization,
5265
+ sourceType: effectiveSourceType,
5266
+ sourceId: effectiveSourceId,
5267
+ destination,
5268
+ amount: parsedAmount
5269
+ });
5270
+ setTransfer(t);
5271
+ if (t.authorizationSessions && t.authorizationSessions.length > 0) {
5272
+ const uri = t.authorizationSessions[0].uri;
5273
+ setMobileFlow(true);
5274
+ pollingTransferIdRef.current = t.id;
5275
+ mobileSetupFlowRef.current = true;
5276
+ handlingMobileReturnRef.current = false;
5277
+ polling.startPolling(t.id);
5278
+ setDeeplinkUri(uri);
5279
+ persistMobileFlowState({
5280
+ transferId: t.id,
5281
+ deeplinkUri: uri,
5282
+ providerId: selectedProviderId,
5283
+ isSetup: true
5284
+ });
5285
+ triggerDeeplink(uri);
5286
+ }
5287
+ } catch (err) {
5288
+ const msg = err instanceof Error ? err.message : "Failed to increase limit";
5289
+ setError(msg);
5290
+ onError?.(msg);
5291
+ } finally {
5292
+ setIncreasingLimit(false);
5293
+ }
5294
+ }, [
5295
+ depositAmount,
5296
+ sourceId,
5297
+ sourceType,
5298
+ activeCredentialId,
5299
+ apiBaseUrl,
5300
+ getAccessToken,
5301
+ accounts,
5302
+ polling,
5303
+ onError,
5304
+ idempotencyKey,
5305
+ merchantAuthorization,
5306
+ destination,
5307
+ selectedProviderId
5308
+ ]);
5195
5309
  const completePasskeyRegistration = react.useCallback(async (credentialId, publicKey) => {
5196
5310
  const token = await getAccessToken();
5197
5311
  if (!token) throw new Error("Not authenticated");
@@ -5453,7 +5567,9 @@ function SwypePaymentInner({
5453
5567
  onChangeSource: () => setStep("wallet-picker"),
5454
5568
  onSwitchWallet: () => setStep("wallet-picker"),
5455
5569
  onBack: onBack ?? (() => handleLogout()),
5456
- onLogout: handleLogout
5570
+ onLogout: handleLogout,
5571
+ onIncreaseLimit: handleIncreaseLimit,
5572
+ increasingLimit
5457
5573
  }
5458
5574
  );
5459
5575
  }