@swype-org/react-sdk 0.1.31 → 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
@@ -1801,7 +1813,7 @@ function LimitSlider({
1801
1813
  (e) => onChange(Number(e.target.value)),
1802
1814
  [onChange]
1803
1815
  );
1804
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: wrapperStyle, children: [
1816
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "swype-slider-wrap", style: wrapperStyle, children: [
1805
1817
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: trackContainerStyle, children: [
1806
1818
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: trackBgStyle(tokens.border) }),
1807
1819
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: trackFillStyle(tokens.accent, pct) }),
@@ -1815,7 +1827,7 @@ function LimitSlider({
1815
1827
  value,
1816
1828
  onChange: handleChange,
1817
1829
  disabled,
1818
- style: rangeInputStyle(tokens.accent)
1830
+ style: rangeInputStyle
1819
1831
  }
1820
1832
  )
1821
1833
  ] }),
@@ -1849,17 +1861,19 @@ var trackFillStyle = (color, pct) => ({
1849
1861
  borderRadius: 2,
1850
1862
  background: color
1851
1863
  });
1852
- var rangeInputStyle = (_accent) => ({
1864
+ var rangeInputStyle = {
1853
1865
  position: "absolute",
1854
1866
  left: 0,
1855
1867
  right: 0,
1856
1868
  width: "100%",
1857
1869
  height: 28,
1858
1870
  margin: 0,
1859
- opacity: 0,
1860
1871
  cursor: "pointer",
1861
- zIndex: 2
1862
- });
1872
+ zIndex: 2,
1873
+ WebkitAppearance: "none",
1874
+ appearance: "none",
1875
+ background: "transparent"
1876
+ };
1863
1877
  var ticksStyle = {
1864
1878
  display: "flex",
1865
1879
  justifyContent: "space-between",
@@ -1871,10 +1885,8 @@ var tickLabelStyle = (color) => ({
1871
1885
  color
1872
1886
  });
1873
1887
  var sliderThumbCss = (accent) => `
1874
- .swype-slider-wrap input[type="range"] {
1875
- -webkit-appearance: none;
1876
- appearance: none;
1877
- opacity: 1 !important;
1888
+ .swype-slider-wrap input[type="range"]::-webkit-slider-runnable-track {
1889
+ height: 4px;
1878
1890
  background: transparent;
1879
1891
  }
1880
1892
  .swype-slider-wrap input[type="range"]::-webkit-slider-thumb {
@@ -1886,6 +1898,21 @@ var sliderThumbCss = (accent) => `
1886
1898
  border: 3px solid #fff;
1887
1899
  box-shadow: 0 2px 6px rgba(0,0,0,0.15);
1888
1900
  cursor: pointer;
1901
+ margin-top: -8px;
1902
+ }
1903
+ .swype-slider-wrap input[type="range"]::-moz-range-track {
1904
+ height: 4px;
1905
+ background: transparent;
1906
+ border: none;
1907
+ }
1908
+ .swype-slider-wrap input[type="range"]::-moz-range-thumb {
1909
+ width: 14px;
1910
+ height: 14px;
1911
+ border-radius: 50%;
1912
+ background: ${accent};
1913
+ border: 3px solid #fff;
1914
+ box-shadow: 0 2px 6px rgba(0,0,0,0.15);
1915
+ cursor: pointer;
1889
1916
  }
1890
1917
  `;
1891
1918
  function SourceCard({ name, address, verified, onChangeSource }) {
@@ -2016,40 +2043,137 @@ var detailStyle = (color) => ({
2016
2043
  fontSize: "0.75rem",
2017
2044
  color
2018
2045
  });
2046
+ function SettingsMenu({ onLogout }) {
2047
+ const { tokens } = useSwypeConfig();
2048
+ const [open, setOpen] = react.useState(false);
2049
+ const menuRef = react.useRef(null);
2050
+ const toggle = react.useCallback(() => setOpen((prev) => !prev), []);
2051
+ react.useEffect(() => {
2052
+ if (!open) return;
2053
+ const handleClickOutside = (e) => {
2054
+ if (menuRef.current && !menuRef.current.contains(e.target)) {
2055
+ setOpen(false);
2056
+ }
2057
+ };
2058
+ document.addEventListener("mousedown", handleClickOutside);
2059
+ return () => document.removeEventListener("mousedown", handleClickOutside);
2060
+ }, [open]);
2061
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: menuRef, style: containerStyle7, children: [
2062
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: toggle, style: triggerStyle(tokens.text), "aria-label": "Settings", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: [
2063
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "5", r: "2", fill: "currentColor" }),
2064
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "2", fill: "currentColor" }),
2065
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "19", r: "2", fill: "currentColor" })
2066
+ ] }) }),
2067
+ open && /* @__PURE__ */ jsxRuntime.jsx("div", { style: dropdownStyle(tokens), children: /* @__PURE__ */ jsxRuntime.jsxs(
2068
+ "button",
2069
+ {
2070
+ type: "button",
2071
+ onClick: () => {
2072
+ setOpen(false);
2073
+ onLogout();
2074
+ },
2075
+ style: menuItemStyle(tokens),
2076
+ children: [
2077
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { marginRight: 8, flexShrink: 0 }, children: [
2078
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4", stroke: tokens.error, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
2079
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "16 17 21 12 16 7", stroke: tokens.error, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
2080
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "12", x2: "9", y2: "12", stroke: tokens.error, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })
2081
+ ] }),
2082
+ "Log out"
2083
+ ]
2084
+ }
2085
+ ) })
2086
+ ] });
2087
+ }
2088
+ var containerStyle7 = {
2089
+ position: "relative"
2090
+ };
2091
+ var triggerStyle = (color) => ({
2092
+ background: "transparent",
2093
+ border: "none",
2094
+ cursor: "pointer",
2095
+ padding: 4,
2096
+ color,
2097
+ display: "flex",
2098
+ alignItems: "center",
2099
+ justifyContent: "center"
2100
+ });
2101
+ var dropdownStyle = (tokens) => ({
2102
+ position: "absolute",
2103
+ right: 0,
2104
+ top: "100%",
2105
+ marginTop: 4,
2106
+ minWidth: 140,
2107
+ background: tokens.bgCard,
2108
+ border: `1px solid ${tokens.border}`,
2109
+ borderRadius: 12,
2110
+ boxShadow: tokens.shadow,
2111
+ zIndex: 100,
2112
+ overflow: "hidden"
2113
+ });
2114
+ var menuItemStyle = (tokens) => ({
2115
+ width: "100%",
2116
+ display: "flex",
2117
+ alignItems: "center",
2118
+ padding: "12px 16px",
2119
+ background: "transparent",
2120
+ border: "none",
2121
+ cursor: "pointer",
2122
+ fontFamily: "inherit",
2123
+ fontSize: "0.85rem",
2124
+ fontWeight: 500,
2125
+ color: tokens.error
2126
+ });
2019
2127
  function LoginScreen({
2020
2128
  authInput,
2021
2129
  onAuthInputChange,
2022
2130
  onSubmit,
2023
2131
  sending,
2024
2132
  error,
2025
- onBack
2133
+ onBack,
2134
+ merchantInitials,
2135
+ onSocialLogin
2026
2136
  }) {
2027
2137
  const { tokens } = useSwypeConfig();
2028
2138
  const disabled = authInput.trim().length === 0 || sending;
2029
- const walletLogos = ["MM", "R", "O", "P", "+"];
2030
2139
  return /* @__PURE__ */ jsxRuntime.jsxs(
2031
2140
  ScreenLayout,
2032
2141
  {
2033
2142
  footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2034
2143
  /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onSubmit, disabled, loading: sending, children: "Continue" }),
2035
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: dividerStyle(tokens), children: [
2036
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: dividerLineStyle(tokens.border) }),
2037
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "works with" }),
2038
- /* @__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)) })
2039
2164
  ] }),
2040
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: logosRowStyle, children: walletLogos.map((label) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: logoCircleStyle(tokens), children: label }, label)) }),
2041
2165
  /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2042
2166
  ] }),
2043
2167
  children: [
2044
- /* @__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
+ ),
2045
2175
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle, children: [
2046
- /* @__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(
2047
- "path",
2048
- {
2049
- d: "M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z",
2050
- fill: tokens.accent
2051
- }
2052
- ) }) }),
2176
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: iconBoxStyle(tokens.accent), children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: iconLetterStyle, children: "S" }) }),
2053
2177
  /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle(tokens.text), children: "One-time setup.\nOne-tap deposits after." }),
2054
2178
  /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle(tokens.textSecondary), children: "Protected by Face ID." }),
2055
2179
  error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorStyle(tokens), children: error }),
@@ -2074,6 +2198,23 @@ function LoginScreen({
2074
2198
  }
2075
2199
  );
2076
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
+ }
2077
2218
  var contentStyle = {
2078
2219
  textAlign: "center",
2079
2220
  flex: 1,
@@ -2082,10 +2223,25 @@ var contentStyle = {
2082
2223
  alignItems: "center",
2083
2224
  paddingTop: 24
2084
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
+ };
2085
2241
  var headingStyle = (color) => ({
2086
- fontSize: "1.65rem",
2242
+ fontSize: "1.45rem",
2087
2243
  fontWeight: 700,
2088
- lineHeight: 1.2,
2244
+ lineHeight: 1.25,
2089
2245
  letterSpacing: "-0.02em",
2090
2246
  color,
2091
2247
  margin: "20px 0 8px",
@@ -2134,24 +2290,55 @@ var dividerLineStyle = (color) => ({
2134
2290
  height: 1,
2135
2291
  background: color
2136
2292
  });
2137
- 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 = {
2138
2322
  display: "flex",
2139
2323
  justifyContent: "center",
2140
- gap: 12,
2141
- marginBottom: 8
2324
+ gap: 16
2142
2325
  };
2143
- var logoCircleStyle = (tokens) => ({
2144
- width: 34,
2145
- height: 34,
2146
- 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%",
2147
2334
  border: `1px solid ${tokens.border}`,
2148
- background: tokens.bgInput,
2149
- color: tokens.textMuted,
2150
2335
  display: "flex",
2151
2336
  alignItems: "center",
2152
2337
  justifyContent: "center",
2153
- fontSize: "0.72rem",
2154
- fontWeight: 600
2338
+ fontSize: "0.6rem",
2339
+ fontWeight: 700,
2340
+ color: tokens.textMuted,
2341
+ background: "transparent"
2155
2342
  });
2156
2343
  var RESEND_COOLDOWN_SECONDS = 30;
2157
2344
  function OtpVerifyScreen({
@@ -2503,21 +2690,36 @@ var hintStyle2 = (color) => ({
2503
2690
  color,
2504
2691
  margin: "0 0 4px"
2505
2692
  });
2506
- var DEFAULT_TICKS = [25, 100, 250, 500];
2507
- var DEFAULT_MIN = 25;
2508
2693
  var DEFAULT_MAX = 500;
2694
+ var ABSOLUTE_MIN = 1;
2695
+ function buildTicks(min, max) {
2696
+ if (max <= min) return [min];
2697
+ const range = max - min;
2698
+ const candidates = [1, 2, 5, 10, 25, 50, 100, 250];
2699
+ const step = candidates.find((s) => range / s <= 5) ?? Math.ceil(range / 4);
2700
+ const ticks = [];
2701
+ for (let v = min; v <= max; v += step) {
2702
+ ticks.push(Math.round(v * 100) / 100);
2703
+ }
2704
+ if (ticks[ticks.length - 1] !== max) ticks.push(max);
2705
+ return ticks;
2706
+ }
2509
2707
  function SetupScreen({
2510
2708
  availableBalance,
2511
2709
  tokenCount,
2512
2710
  sourceName,
2513
2711
  onSetupOneTap,
2514
2712
  onBack,
2713
+ onLogout,
2515
2714
  loading,
2516
2715
  error
2517
2716
  }) {
2518
2717
  const { tokens } = useSwypeConfig();
2519
- const [limit, setLimit] = react.useState(100);
2520
2718
  const effectiveMax = Math.min(DEFAULT_MAX, availableBalance > 0 ? availableBalance : DEFAULT_MAX);
2719
+ const effectiveMin = Math.min(ABSOLUTE_MIN, effectiveMax);
2720
+ const sliderStep = effectiveMax <= 10 ? 0.5 : effectiveMax <= 50 ? 1 : 5;
2721
+ const ticks = buildTicks(effectiveMin, effectiveMax);
2722
+ const [limit, setLimit] = react.useState(() => Math.min(100, effectiveMax));
2521
2723
  return /* @__PURE__ */ jsxRuntime.jsxs(
2522
2724
  ScreenLayout,
2523
2725
  {
@@ -2534,7 +2736,7 @@ function SetupScreen({
2534
2736
  /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2535
2737
  ] }),
2536
2738
  children: [
2537
- /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: "Swype Setup", badge: "Simple", onBack }),
2739
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: "Swype Setup", badge: "Simple", onBack, right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
2538
2740
  /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle5(tokens.text), children: "Set up One-Tap deposits" }),
2539
2741
  /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle5(tokens.textSecondary), children: "Set your limit for instant deposits. Like a contactless card \u2014 you choose the max." }),
2540
2742
  error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle3(tokens), children: error }),
@@ -2569,10 +2771,10 @@ function SetupScreen({
2569
2771
  LimitSlider,
2570
2772
  {
2571
2773
  value: limit,
2572
- min: DEFAULT_MIN,
2774
+ min: effectiveMin,
2573
2775
  max: effectiveMax,
2574
- step: 5,
2575
- ticks: DEFAULT_TICKS.filter((t) => t <= effectiveMax),
2776
+ step: sliderStep,
2777
+ ticks,
2576
2778
  onChange: setLimit
2577
2779
  }
2578
2780
  )
@@ -2692,6 +2894,7 @@ function SetupStatusScreen({
2692
2894
  currentStepLabel,
2693
2895
  merchantName,
2694
2896
  onContinue,
2897
+ onLogout,
2695
2898
  error
2696
2899
  }) {
2697
2900
  const { tokens } = useSwypeConfig();
@@ -2709,26 +2912,29 @@ function SetupStatusScreen({
2709
2912
  },
2710
2913
  { label: "Done", status: "pending" }
2711
2914
  ];
2712
- return /* @__PURE__ */ jsxRuntime.jsx(
2915
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2713
2916
  ScreenLayout,
2714
2917
  {
2715
2918
  footer: complete ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2716
2919
  /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onContinue, children: merchantName ? `Return to ${merchantName}` : "Continue" }),
2717
2920
  /* @__PURE__ */ jsxRuntime.jsx("p", { style: swipeHintStyle(tokens.textMuted), children: "Swipe to deposit \u2014 no approvals needed." })
2718
2921
  ] }) : void 0,
2719
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle4, children: [
2720
- complete ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2721
- /* @__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 }) }) }),
2722
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle6(tokens.text), children: "You're all set!" })
2723
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2724
- /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 48 }),
2725
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle6(tokens.text), children: "Setting up One-Tap..." })
2726
- ] }),
2727
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle4(tokens), children: error }),
2728
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: stepsWrapStyle, children: /* @__PURE__ */ jsxRuntime.jsx(StepList, { steps }) }),
2729
- !complete && /* @__PURE__ */ jsxRuntime.jsx("p", { style: waitHintStyle(tokens.textMuted), children: "Usually takes a few seconds" }),
2730
- complete && /* @__PURE__ */ jsxRuntime.jsx("p", { style: readyHintStyle(tokens.textSecondary), children: "You can now deposit instantly from any partner app." })
2731
- ] })
2922
+ children: [
2923
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
2924
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle4, children: [
2925
+ complete ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2926
+ /* @__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 }) }) }),
2927
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle6(tokens.text), children: "You're all set!" })
2928
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2929
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 48 }),
2930
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle6(tokens.text), children: "Setting up One-Tap..." })
2931
+ ] }),
2932
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle4(tokens), children: error }),
2933
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: stepsWrapStyle, children: /* @__PURE__ */ jsxRuntime.jsx(StepList, { steps }) }),
2934
+ !complete && /* @__PURE__ */ jsxRuntime.jsx("p", { style: waitHintStyle(tokens.textMuted), children: "Usually takes a few seconds" }),
2935
+ complete && /* @__PURE__ */ jsxRuntime.jsx("p", { style: readyHintStyle(tokens.textSecondary), children: "You can now deposit instantly from any partner app." })
2936
+ ] })
2937
+ ]
2732
2938
  }
2733
2939
  );
2734
2940
  }
@@ -2784,7 +2990,7 @@ var swipeHintStyle = (color) => ({
2784
2990
  color,
2785
2991
  margin: "12px 0 0"
2786
2992
  });
2787
- var MIN_DEPOSIT = 1;
2993
+ var MIN_DEPOSIT = 0.25;
2788
2994
  function DepositScreen({
2789
2995
  merchantName,
2790
2996
  sourceName,
@@ -2801,7 +3007,8 @@ function DepositScreen({
2801
3007
  onDeposit,
2802
3008
  onChangeSource,
2803
3009
  onSwitchWallet,
2804
- onBack
3010
+ onBack,
3011
+ onLogout
2805
3012
  }) {
2806
3013
  const { tokens } = useSwypeConfig();
2807
3014
  const [amount, setAmount] = react.useState(initialAmount);
@@ -2809,30 +3016,6 @@ function DepositScreen({
2809
3016
  const isLowBalance = availableBalance < MIN_DEPOSIT;
2810
3017
  const canDeposit = amount >= MIN_DEPOSIT && amount <= remainingLimit && !isLowBalance && !processing;
2811
3018
  const headerTitle = merchantName ? `Deposit to ${merchantName}` : "Deposit";
2812
- const trackRef = react.useRef(null);
2813
- const [swipeX, setSwipeX] = react.useState(0);
2814
- const [swiping, setSwiping] = react.useState(false);
2815
- const startXRef = react.useRef(0);
2816
- const handleTouchStart = react.useCallback((e) => {
2817
- if (!canDeposit) return;
2818
- startXRef.current = e.touches[0].clientX - swipeX;
2819
- setSwiping(true);
2820
- }, [canDeposit, swipeX]);
2821
- const handleTouchMove = react.useCallback((e) => {
2822
- if (!swiping || !trackRef.current) return;
2823
- const trackWidth = trackRef.current.offsetWidth - 52;
2824
- const x = Math.max(0, Math.min(e.touches[0].clientX - startXRef.current, trackWidth));
2825
- setSwipeX(x);
2826
- }, [swiping]);
2827
- const handleTouchEnd = react.useCallback(() => {
2828
- if (!trackRef.current) return;
2829
- const trackWidth = trackRef.current.offsetWidth - 52;
2830
- if (swipeX > trackWidth * 0.75) {
2831
- onDeposit(amount);
2832
- }
2833
- setSwipeX(0);
2834
- setSwiping(false);
2835
- }, [swipeX, amount, onDeposit]);
2836
3019
  if (isLowBalance) {
2837
3020
  return /* @__PURE__ */ jsxRuntime.jsxs(
2838
3021
  ScreenLayout,
@@ -2844,7 +3027,7 @@ function DepositScreen({
2844
3027
  /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2845
3028
  ] }),
2846
3029
  children: [
2847
- /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: headerTitle, onBack }),
3030
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: headerTitle, onBack, right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
2848
3031
  /* @__PURE__ */ jsxRuntime.jsx(
2849
3032
  SourceCard,
2850
3033
  {
@@ -2889,30 +3072,10 @@ function DepositScreen({
2889
3072
  ScreenLayout,
2890
3073
  {
2891
3074
  footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2892
- /* @__PURE__ */ jsxRuntime.jsxs(
2893
- "div",
2894
- {
2895
- ref: trackRef,
2896
- style: swipeTrackStyle(tokens),
2897
- onTouchStart: handleTouchStart,
2898
- onTouchMove: handleTouchMove,
2899
- onTouchEnd: handleTouchEnd,
2900
- children: [
2901
- /* @__PURE__ */ jsxRuntime.jsx(
2902
- "div",
2903
- {
2904
- style: swipeThumbStyle(tokens, swipeX),
2905
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5l8 7-8 7", stroke: "#fff", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
2906
- }
2907
- ),
2908
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: swipeLabelStyle, children: processing ? "Processing..." : `Deposit $${amount.toFixed(2)}` })
2909
- ]
2910
- }
2911
- ),
2912
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: desktopFallbackStyle, children: /* @__PURE__ */ jsxRuntime.jsxs(PrimaryButton, { onClick: () => onDeposit(amount), disabled: !canDeposit, loading: processing, children: [
3075
+ /* @__PURE__ */ jsxRuntime.jsxs(PrimaryButton, { onClick: () => onDeposit(amount), disabled: !canDeposit, loading: processing, children: [
2913
3076
  "Deposit $",
2914
3077
  amount.toFixed(2)
2915
- ] }) }),
3078
+ ] }),
2916
3079
  /* @__PURE__ */ jsxRuntime.jsx("p", { style: noApprovalStyle(tokens.textMuted), children: "No approval needed \xB7 within your One-Tap limit" }),
2917
3080
  /* @__PURE__ */ jsxRuntime.jsxs("p", { style: routeStyle(tokens.textMuted), children: [
2918
3081
  "From ",
@@ -2923,7 +3086,7 @@ function DepositScreen({
2923
3086
  /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2924
3087
  ] }),
2925
3088
  children: [
2926
- /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: headerTitle, badge: "Simple", onBack }),
3089
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: headerTitle, badge: "Simple", onBack, right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
2927
3090
  /* @__PURE__ */ jsxRuntime.jsx(
2928
3091
  SourceCard,
2929
3092
  {
@@ -2968,7 +3131,7 @@ function DepositScreen({
2968
3131
  min: MIN_DEPOSIT,
2969
3132
  max: sliderMax > MIN_DEPOSIT ? sliderMax : 20,
2970
3133
  step: 0.5,
2971
- 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),
2972
3135
  onChange: setAmount
2973
3136
  }
2974
3137
  ),
@@ -2980,13 +3143,13 @@ function DepositScreen({
2980
3143
  remainingLimit.toFixed(2)
2981
3144
  ] })
2982
3145
  ] }),
2983
- 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: [
2984
3147
  "Fee: ~$",
2985
3148
  estimatedFeeUsd.toFixed(2),
2986
3149
  " (",
2987
3150
  estimatedFeePct.toFixed(1),
2988
3151
  "%)"
2989
- ] })
3152
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: detailRowStyle(tokens.textMuted), children: "Fees calculated at time of transfer" })
2990
3153
  ] }),
2991
3154
  error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle5(tokens), children: error })
2992
3155
  ]
@@ -3066,45 +3229,6 @@ var errorBannerStyle5 = (tokens) => ({
3066
3229
  marginTop: 8,
3067
3230
  lineHeight: 1.5
3068
3231
  });
3069
- var swipeTrackStyle = (tokens) => ({
3070
- position: "relative",
3071
- height: 56,
3072
- borderRadius: 999,
3073
- background: `linear-gradient(180deg, ${tokens.accent}, ${tokens.accent}dd)`,
3074
- overflow: "hidden",
3075
- display: "flex",
3076
- alignItems: "center",
3077
- touchAction: "none",
3078
- userSelect: "none"
3079
- });
3080
- var swipeThumbStyle = (tokens, x) => ({
3081
- position: "absolute",
3082
- left: 4 + x,
3083
- top: 4,
3084
- width: 48,
3085
- height: 48,
3086
- borderRadius: "50%",
3087
- background: `${tokens.accent}`,
3088
- border: "2px solid rgba(255,255,255,0.4)",
3089
- display: "flex",
3090
- alignItems: "center",
3091
- justifyContent: "center",
3092
- zIndex: 2,
3093
- transition: x === 0 ? "left 0.25s ease" : "none",
3094
- cursor: "grab"
3095
- });
3096
- var swipeLabelStyle = {
3097
- flex: 1,
3098
- textAlign: "center",
3099
- color: "#fff",
3100
- fontWeight: 700,
3101
- fontSize: "0.95rem",
3102
- zIndex: 1,
3103
- pointerEvents: "none"
3104
- };
3105
- var desktopFallbackStyle = {
3106
- marginTop: 8
3107
- };
3108
3232
  var noApprovalStyle = (color) => ({
3109
3233
  textAlign: "center",
3110
3234
  fontSize: "0.78rem",
@@ -3133,6 +3257,7 @@ function SuccessScreen({
3133
3257
  sourceName,
3134
3258
  remainingLimit,
3135
3259
  onDone,
3260
+ onLogout,
3136
3261
  onIncreaseLimits,
3137
3262
  onManageAccount
3138
3263
  }) {
@@ -3149,7 +3274,7 @@ function SuccessScreen({
3149
3274
  /* @__PURE__ */ jsxRuntime.jsx(
3150
3275
  ScreenHeader,
3151
3276
  {
3152
- right: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onDone, style: closeButtonStyle(tokens.textMuted), "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
3277
+ right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout })
3153
3278
  }
3154
3279
  ),
3155
3280
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle5, children: [
@@ -3265,15 +3390,6 @@ var upsellLinkStyle = (color) => ({
3265
3390
  fontFamily: "inherit",
3266
3391
  padding: 0
3267
3392
  });
3268
- var closeButtonStyle = (color) => ({
3269
- background: "transparent",
3270
- border: "none",
3271
- cursor: "pointer",
3272
- color,
3273
- padding: 4,
3274
- display: "flex",
3275
- alignItems: "center"
3276
- });
3277
3393
  var manageStyle = (color) => ({
3278
3394
  background: "transparent",
3279
3395
  border: "none",
@@ -3379,6 +3495,7 @@ function SwypePayment({
3379
3495
  loginWithCode: loginWithSmsCode,
3380
3496
  state: smsLoginState
3381
3497
  } = reactAuth.useLoginWithSms();
3498
+ const { initOAuth } = reactAuth.useLoginWithOAuth();
3382
3499
  const [step, setStep] = react.useState("login");
3383
3500
  const [error, setError] = react.useState(null);
3384
3501
  const [providers, setProviders] = react.useState([]);
@@ -3427,6 +3544,14 @@ function SwypePayment({
3427
3544
  setVerificationTarget(null);
3428
3545
  setOtpCode("");
3429
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]);
3430
3555
  const activeOtpStatus = verificationTarget?.kind === "email" ? emailLoginState.status : verificationTarget?.kind === "phone" ? smsLoginState.status : "initial";
3431
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;
3432
3557
  react.useEffect(() => {
@@ -3495,6 +3620,9 @@ function SwypePayment({
3495
3620
  if (!token || cancelled) return;
3496
3621
  const { config } = await fetchUserConfig(apiBaseUrl, token);
3497
3622
  if (cancelled) return;
3623
+ if (config.defaultAllowance != null) {
3624
+ setOneTapLimit(config.defaultAllowance);
3625
+ }
3498
3626
  const allPasskeys = config.passkeys ?? (config.passkey ? [config.passkey] : []);
3499
3627
  if (allPasskeys.length === 0) {
3500
3628
  setStep("create-passkey");
@@ -3852,13 +3980,15 @@ function SwypePayment({
3852
3980
  if (!sourceId) {
3853
3981
  throw new Error("No wallet selected for setup.");
3854
3982
  }
3983
+ const setupAmount = depositAmount ?? MIN_SEND_AMOUNT_USD;
3855
3984
  const t = await createTransfer(apiBaseUrl, token, {
3985
+ id: idempotencyKey,
3856
3986
  credentialId: activeCredentialId ?? "",
3857
3987
  merchantAuthorization,
3858
3988
  sourceType,
3859
3989
  sourceId,
3860
3990
  destination,
3861
- amount: 0
3991
+ amount: setupAmount
3862
3992
  });
3863
3993
  if (t.authorizationSessions && t.authorizationSessions.length > 0) {
3864
3994
  const shouldUseConnector = shouldUseWalletConnector({
@@ -3881,6 +4011,7 @@ function SwypePayment({
3881
4011
  }
3882
4012
  }, [
3883
4013
  getAccessToken,
4014
+ idempotencyKey,
3884
4015
  sourceId,
3885
4016
  sourceType,
3886
4017
  activeCredentialId,
@@ -3889,7 +4020,8 @@ function SwypePayment({
3889
4020
  merchantAuthorization,
3890
4021
  useWalletConnector,
3891
4022
  authExecutor,
3892
- onError
4023
+ onError,
4024
+ depositAmount
3893
4025
  ]);
3894
4026
  const handleSelectProvider = react.useCallback((providerId) => {
3895
4027
  setSelectedProviderId(providerId);
@@ -3950,7 +4082,9 @@ function SwypePayment({
3950
4082
  onSubmit: handleSendLoginCode,
3951
4083
  sending: activeOtpStatus === "sending-code",
3952
4084
  error,
3953
- onBack
4085
+ onBack,
4086
+ merchantInitials: merchantName ? merchantName.slice(0, 2).toUpperCase() : void 0,
4087
+ onSocialLogin: handleSocialLogin
3954
4088
  }
3955
4089
  );
3956
4090
  }
@@ -4008,6 +4142,7 @@ function SwypePayment({
4008
4142
  sourceName,
4009
4143
  onSetupOneTap: handleSetupOneTap,
4010
4144
  onBack: () => setStep("wallet-picker"),
4145
+ onLogout: handleLogout,
4011
4146
  loading: loadingData,
4012
4147
  error
4013
4148
  }
@@ -4023,6 +4158,7 @@ function SwypePayment({
4023
4158
  currentStepLabel: setupStepLabel,
4024
4159
  merchantName,
4025
4160
  onContinue: () => setStep("deposit"),
4161
+ onLogout: handleLogout,
4026
4162
  error
4027
4163
  }
4028
4164
  );
@@ -4043,20 +4179,20 @@ function SwypePayment({
4043
4179
  remainingLimit: oneTapLimit,
4044
4180
  tokenCount,
4045
4181
  initialAmount: parsedAmt,
4046
- estimatedFeePct: 0.6,
4047
- estimatedFeeUsd: parsedAmt * 6e-3,
4048
4182
  processing: creatingTransfer,
4049
4183
  error,
4050
4184
  onDeposit: handlePay,
4051
4185
  onChangeSource: () => setStep("wallet-picker"),
4052
4186
  onSwitchWallet: () => setStep("wallet-picker"),
4053
- onBack: onBack ?? (() => handleLogout())
4187
+ onBack: onBack ?? (() => handleLogout()),
4188
+ onLogout: handleLogout
4054
4189
  }
4055
4190
  );
4056
4191
  }
4057
4192
  if (step === "processing") {
4058
4193
  const currentActionType = authExecutor.currentAction?.type;
4059
- 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...";
4060
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: [
4061
4197
  /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 48 }),
4062
4198
  /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { fontSize: "1.4rem", fontWeight: 700, color: tokens.text, marginTop: 20, marginBottom: 8 }, children: statusLabel }),
@@ -4086,7 +4222,8 @@ function SwypePayment({
4086
4222
  merchantName,
4087
4223
  sourceName,
4088
4224
  remainingLimit: oneTapLimit > displayAmount ? oneTapLimit - displayAmount : 0,
4089
- onDone: handleNewPayment
4225
+ onDone: handleNewPayment,
4226
+ onLogout: handleLogout
4090
4227
  }
4091
4228
  );
4092
4229
  }
@@ -4107,7 +4244,8 @@ function SwypePayment({
4107
4244
  onDeposit: handlePay,
4108
4245
  onChangeSource: () => setStep("wallet-picker"),
4109
4246
  onSwitchWallet: () => setStep("wallet-picker"),
4110
- onBack: onBack ?? (() => handleLogout())
4247
+ onBack: onBack ?? (() => handleLogout()),
4248
+ onLogout: handleLogout
4111
4249
  }
4112
4250
  );
4113
4251
  }