@swype-org/react-sdk 0.1.32 → 0.1.33

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
@@ -1451,8 +1451,20 @@ function hasProcessingTimedOut(processingStartedAtMs, nowMs) {
1451
1451
  if (!processingStartedAtMs) return false;
1452
1452
  return nowMs - processingStartedAtMs >= PROCESSING_TIMEOUT_MS;
1453
1453
  }
1454
+ var STATUS_DISPLAY_LABELS = {
1455
+ CREATED: "created",
1456
+ AUTHORIZED: "authorized",
1457
+ SENDING: "sending",
1458
+ SENT: "confirming delivery",
1459
+ COMPLETED: "completed",
1460
+ FAILED: "failed"
1461
+ };
1462
+ function getStatusDisplayLabel(status) {
1463
+ return STATUS_DISPLAY_LABELS[status] ?? status;
1464
+ }
1454
1465
  function buildProcessingTimeoutMessage(status) {
1455
- return `Payment is taking longer than expected (status: ${status}). Please try again.`;
1466
+ const label = getStatusDisplayLabel(status);
1467
+ return `Payment is taking longer than expected (status: ${label}). Please try again.`;
1456
1468
  }
1457
1469
 
1458
1470
  // src/walletFlow.ts
@@ -2118,34 +2130,50 @@ function LoginScreen({
2118
2130
  onSubmit,
2119
2131
  sending,
2120
2132
  error,
2121
- onBack
2133
+ onBack,
2134
+ merchantInitials,
2135
+ onSocialLogin
2122
2136
  }) {
2123
2137
  const { tokens } = useSwypeConfig();
2124
2138
  const disabled = authInput.trim().length === 0 || sending;
2125
- const walletLogos = ["MM", "R", "O", "P", "+"];
2126
2139
  return /* @__PURE__ */ jsxRuntime.jsxs(
2127
2140
  ScreenLayout,
2128
2141
  {
2129
2142
  footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2130
2143
  /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onSubmit, disabled, loading: sending, children: "Continue" }),
2131
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: dividerStyle(tokens), children: [
2132
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: dividerLineStyle(tokens.border) }),
2133
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "works with" }),
2134
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: dividerLineStyle(tokens.border) })
2144
+ onSocialLogin && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2145
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: dividerStyle(tokens), children: [
2146
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: dividerLineStyle(tokens.border) }),
2147
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "or continue with" }),
2148
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: dividerLineStyle(tokens.border) })
2149
+ ] }),
2150
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: socialRowStyle, children: ["google", "apple", "twitter"].map((provider) => /* @__PURE__ */ jsxRuntime.jsx(
2151
+ "button",
2152
+ {
2153
+ type: "button",
2154
+ onClick: () => onSocialLogin(provider),
2155
+ style: socialButtonStyle(tokens),
2156
+ children: socialLabel(provider)
2157
+ },
2158
+ provider
2159
+ )) })
2160
+ ] }),
2161
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: walletSectionStyle, children: [
2162
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: walletLabelStyle(tokens.textMuted), children: "Works with" }),
2163
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: walletLogosStyle, children: walletIcons.map(({ key, emoji }) => /* @__PURE__ */ jsxRuntime.jsx("span", { style: walletEmojiStyle, children: emoji }, key)) })
2135
2164
  ] }),
2136
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: logosRowStyle, children: walletLogos.map((label) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: logoCircleStyle(tokens), children: label }, label)) }),
2137
2165
  /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2138
2166
  ] }),
2139
2167
  children: [
2140
- /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onBack }),
2168
+ /* @__PURE__ */ jsxRuntime.jsx(
2169
+ ScreenHeader,
2170
+ {
2171
+ onBack,
2172
+ right: merchantInitials ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: avatarStyle(tokens), children: merchantInitials }) : void 0
2173
+ }
2174
+ ),
2141
2175
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle, children: [
2142
- /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "accent", size: 56, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
2143
- "path",
2144
- {
2145
- d: "M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z",
2146
- fill: tokens.accent
2147
- }
2148
- ) }) }),
2176
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: iconBoxStyle(tokens.accent), children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: iconLetterStyle, children: "S" }) }),
2149
2177
  /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle(tokens.text), children: "One-time setup.\nOne-tap deposits after." }),
2150
2178
  /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle(tokens.textSecondary), children: "Protected by Face ID." }),
2151
2179
  error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorStyle(tokens), children: error }),
@@ -2170,6 +2198,23 @@ function LoginScreen({
2170
2198
  }
2171
2199
  );
2172
2200
  }
2201
+ var walletIcons = [
2202
+ { key: "metamask", emoji: "\u{1F98A}" },
2203
+ { key: "rabby", emoji: "\u{1F430}" },
2204
+ { key: "phantom", emoji: "\u25C6" },
2205
+ { key: "rainbow", emoji: "\u{1F439}" },
2206
+ { key: "coinbase", emoji: "\u{1F535}" }
2207
+ ];
2208
+ function socialLabel(provider) {
2209
+ switch (provider) {
2210
+ case "google":
2211
+ return "Google";
2212
+ case "apple":
2213
+ return "Apple";
2214
+ case "twitter":
2215
+ return "X";
2216
+ }
2217
+ }
2173
2218
  var contentStyle = {
2174
2219
  textAlign: "center",
2175
2220
  flex: 1,
@@ -2178,10 +2223,25 @@ var contentStyle = {
2178
2223
  alignItems: "center",
2179
2224
  paddingTop: 24
2180
2225
  };
2226
+ var iconBoxStyle = (accent) => ({
2227
+ width: 56,
2228
+ height: 56,
2229
+ borderRadius: 16,
2230
+ background: accent,
2231
+ display: "flex",
2232
+ alignItems: "center",
2233
+ justifyContent: "center"
2234
+ });
2235
+ var iconLetterStyle = {
2236
+ color: "#fff",
2237
+ fontSize: "1.5rem",
2238
+ fontWeight: 700,
2239
+ lineHeight: 1
2240
+ };
2181
2241
  var headingStyle = (color) => ({
2182
- fontSize: "1.65rem",
2242
+ fontSize: "1.45rem",
2183
2243
  fontWeight: 700,
2184
- lineHeight: 1.2,
2244
+ lineHeight: 1.25,
2185
2245
  letterSpacing: "-0.02em",
2186
2246
  color,
2187
2247
  margin: "20px 0 8px",
@@ -2230,24 +2290,55 @@ var dividerLineStyle = (color) => ({
2230
2290
  height: 1,
2231
2291
  background: color
2232
2292
  });
2233
- var logosRowStyle = {
2293
+ var socialRowStyle = {
2294
+ display: "flex",
2295
+ gap: 10,
2296
+ marginBottom: 20
2297
+ };
2298
+ var socialButtonStyle = (tokens) => ({
2299
+ flex: 1,
2300
+ padding: "12px 0",
2301
+ borderRadius: 12,
2302
+ border: `1px solid ${tokens.border}`,
2303
+ background: "transparent",
2304
+ color: tokens.text,
2305
+ fontSize: "0.88rem",
2306
+ fontWeight: 600,
2307
+ fontFamily: "inherit",
2308
+ cursor: "pointer"
2309
+ });
2310
+ var walletSectionStyle = {
2311
+ textAlign: "center",
2312
+ marginBottom: 8,
2313
+ marginTop: 4
2314
+ };
2315
+ var walletLabelStyle = (color) => ({
2316
+ fontSize: "0.78rem",
2317
+ color,
2318
+ display: "block",
2319
+ marginBottom: 10
2320
+ });
2321
+ var walletLogosStyle = {
2234
2322
  display: "flex",
2235
2323
  justifyContent: "center",
2236
- gap: 12,
2237
- marginBottom: 8
2324
+ gap: 16
2238
2325
  };
2239
- var logoCircleStyle = (tokens) => ({
2240
- width: 34,
2241
- height: 34,
2242
- borderRadius: 999,
2326
+ var walletEmojiStyle = {
2327
+ fontSize: "1.4rem",
2328
+ lineHeight: 1
2329
+ };
2330
+ var avatarStyle = (tokens) => ({
2331
+ width: 28,
2332
+ height: 28,
2333
+ borderRadius: "50%",
2243
2334
  border: `1px solid ${tokens.border}`,
2244
- background: tokens.bgInput,
2245
- color: tokens.textMuted,
2246
2335
  display: "flex",
2247
2336
  alignItems: "center",
2248
2337
  justifyContent: "center",
2249
- fontSize: "0.72rem",
2250
- fontWeight: 600
2338
+ fontSize: "0.6rem",
2339
+ fontWeight: 700,
2340
+ color: tokens.textMuted,
2341
+ background: "transparent"
2251
2342
  });
2252
2343
  var RESEND_COOLDOWN_SECONDS = 30;
2253
2344
  function OtpVerifyScreen({
@@ -2899,7 +2990,7 @@ var swipeHintStyle = (color) => ({
2899
2990
  color,
2900
2991
  margin: "12px 0 0"
2901
2992
  });
2902
- var MIN_DEPOSIT = 1;
2993
+ var MIN_DEPOSIT = 0.25;
2903
2994
  function DepositScreen({
2904
2995
  merchantName,
2905
2996
  sourceName,
@@ -3040,7 +3131,7 @@ function DepositScreen({
3040
3131
  min: MIN_DEPOSIT,
3041
3132
  max: sliderMax > MIN_DEPOSIT ? sliderMax : 20,
3042
3133
  step: 0.5,
3043
- ticks: [MIN_DEPOSIT, 5, 10, 20].filter((t) => t <= sliderMax || t <= 20),
3134
+ ticks: [MIN_DEPOSIT, 1, 5, 10, 20].filter((t) => t <= sliderMax || t <= 20),
3044
3135
  onChange: setAmount
3045
3136
  }
3046
3137
  ),
@@ -3052,13 +3143,13 @@ function DepositScreen({
3052
3143
  remainingLimit.toFixed(2)
3053
3144
  ] })
3054
3145
  ] }),
3055
- estimatedFeeUsd != null && estimatedFeePct != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: detailRowStyle(tokens.textMuted), children: [
3146
+ estimatedFeeUsd != null && estimatedFeePct != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: detailRowStyle(tokens.textMuted), children: [
3056
3147
  "Fee: ~$",
3057
3148
  estimatedFeeUsd.toFixed(2),
3058
3149
  " (",
3059
3150
  estimatedFeePct.toFixed(1),
3060
3151
  "%)"
3061
- ] })
3152
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: detailRowStyle(tokens.textMuted), children: "Fees calculated at time of transfer" })
3062
3153
  ] }),
3063
3154
  error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle5(tokens), children: error })
3064
3155
  ]
@@ -3404,6 +3495,7 @@ function SwypePayment({
3404
3495
  loginWithCode: loginWithSmsCode,
3405
3496
  state: smsLoginState
3406
3497
  } = reactAuth.useLoginWithSms();
3498
+ const { initOAuth } = reactAuth.useLoginWithOAuth();
3407
3499
  const [step, setStep] = react.useState("login");
3408
3500
  const [error, setError] = react.useState(null);
3409
3501
  const [providers, setProviders] = react.useState([]);
@@ -3452,6 +3544,14 @@ function SwypePayment({
3452
3544
  setVerificationTarget(null);
3453
3545
  setOtpCode("");
3454
3546
  }, []);
3547
+ const handleSocialLogin = react.useCallback(async (provider) => {
3548
+ setError(null);
3549
+ try {
3550
+ await initOAuth({ provider });
3551
+ } catch (err) {
3552
+ setError(err instanceof Error ? err.message : "Social login failed");
3553
+ }
3554
+ }, [initOAuth]);
3455
3555
  const activeOtpStatus = verificationTarget?.kind === "email" ? emailLoginState.status : verificationTarget?.kind === "phone" ? smsLoginState.status : "initial";
3456
3556
  const activeOtpErrorMessage = verificationTarget?.kind === "email" && emailLoginState.status === "error" ? emailLoginState.error?.message ?? "Failed to continue with email." : verificationTarget?.kind === "phone" && smsLoginState.status === "error" ? smsLoginState.error?.message ?? "Failed to continue with phone number." : null;
3457
3557
  react.useEffect(() => {
@@ -3520,6 +3620,9 @@ function SwypePayment({
3520
3620
  if (!token || cancelled) return;
3521
3621
  const { config } = await fetchUserConfig(apiBaseUrl, token);
3522
3622
  if (cancelled) return;
3623
+ if (config.defaultAllowance != null) {
3624
+ setOneTapLimit(config.defaultAllowance);
3625
+ }
3523
3626
  const allPasskeys = config.passkeys ?? (config.passkey ? [config.passkey] : []);
3524
3627
  if (allPasskeys.length === 0) {
3525
3628
  setStep("create-passkey");
@@ -3879,6 +3982,7 @@ function SwypePayment({
3879
3982
  }
3880
3983
  const setupAmount = depositAmount ?? MIN_SEND_AMOUNT_USD;
3881
3984
  const t = await createTransfer(apiBaseUrl, token, {
3985
+ id: idempotencyKey,
3882
3986
  credentialId: activeCredentialId ?? "",
3883
3987
  merchantAuthorization,
3884
3988
  sourceType,
@@ -3907,6 +4011,7 @@ function SwypePayment({
3907
4011
  }
3908
4012
  }, [
3909
4013
  getAccessToken,
4014
+ idempotencyKey,
3910
4015
  sourceId,
3911
4016
  sourceType,
3912
4017
  activeCredentialId,
@@ -3977,7 +4082,9 @@ function SwypePayment({
3977
4082
  onSubmit: handleSendLoginCode,
3978
4083
  sending: activeOtpStatus === "sending-code",
3979
4084
  error,
3980
- onBack
4085
+ onBack,
4086
+ merchantInitials: merchantName ? merchantName.slice(0, 2).toUpperCase() : void 0,
4087
+ onSocialLogin: handleSocialLogin
3981
4088
  }
3982
4089
  );
3983
4090
  }
@@ -4072,8 +4179,6 @@ function SwypePayment({
4072
4179
  remainingLimit: oneTapLimit,
4073
4180
  tokenCount,
4074
4181
  initialAmount: parsedAmt,
4075
- estimatedFeePct: 0.6,
4076
- estimatedFeeUsd: parsedAmt * 6e-3,
4077
4182
  processing: creatingTransfer,
4078
4183
  error,
4079
4184
  onDeposit: handlePay,
@@ -4086,7 +4191,8 @@ function SwypePayment({
4086
4191
  }
4087
4192
  if (step === "processing") {
4088
4193
  const currentActionType = authExecutor.currentAction?.type;
4089
- const statusLabel = creatingTransfer ? "Creating Transfer" : mobileFlow ? "Waiting for Authorization" : authExecutor.executing ? currentActionType?.replace(/_/g, " ") ?? "Authorizing" : transferSigning.signing ? "Sending transfer" : polling.isPolling ? "Transfer Sent" : "Please wait...";
4194
+ const polledStatus = polling.transfer?.status;
4195
+ const statusLabel = creatingTransfer ? "Creating Transfer" : mobileFlow ? "Waiting for Authorization" : authExecutor.executing ? currentActionType?.replace(/_/g, " ") ?? "Authorizing" : transferSigning.signing ? "Sending transfer" : polledStatus === "SENDING" ? "Sending transfer..." : polledStatus === "SENT" ? "Confirming delivery..." : polling.isPolling ? "Transfer Sent" : "Please wait...";
4090
4196
  return /* @__PURE__ */ jsxRuntime.jsx(ScreenLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", padding: "48px 0", flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }, children: [
4091
4197
  /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 48 }),
4092
4198
  /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { fontSize: "1.4rem", fontWeight: 700, color: tokens.text, marginTop: 20, marginBottom: 8 }, children: statusLabel }),