@superlogic/spree-pay 0.4.1 → 0.4.6

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/build/index.cjs CHANGED
@@ -49,10 +49,11 @@ var init_errors = __esm({
49
49
  });
50
50
 
51
51
  // src/types/payments.ts
52
- var PaymentType;
52
+ var isNewCard, PaymentType;
53
53
  var init_payments = __esm({
54
54
  "src/types/payments.ts"() {
55
55
  "use strict";
56
+ isNewCard = (card) => !("cardId" in card);
56
57
  PaymentType = /* @__PURE__ */ ((PaymentType2) => {
57
58
  PaymentType2["CREDIT_CARD"] = "CREDIT_CARD";
58
59
  PaymentType2["CRYPTO"] = "CRYPTO";
@@ -68,7 +69,7 @@ var init_payments = __esm({
68
69
  var version;
69
70
  var init_package = __esm({
70
71
  "package.json"() {
71
- version = "0.4.1";
72
+ version = "0.4.6";
72
73
  }
73
74
  });
74
75
 
@@ -756,10 +757,20 @@ var init_slapi = __esm({
756
757
  throw error;
757
758
  }
758
759
  },
759
- addCard: async ({ source, hash }) => {
760
+ removeCard: async ({ cardId }) => {
761
+ slapiLogger.debug("Removing card", { cardId });
762
+ try {
763
+ await slapiApi.delete(`/v1/payments/cards/${cardId}`);
764
+ slapiLogger.info("Card removed successfully", { cardId });
765
+ } catch (error) {
766
+ slapiLogger.error("Failed to remove card", error, { cardId });
767
+ throw error;
768
+ }
769
+ },
770
+ addCard: async ({ source, hash, saveCard }) => {
760
771
  slapiLogger.debug("Adding card", { hash, sourcePrefix: source.substring(0, 10) });
761
772
  try {
762
- const data = await slapiApi.post("/v1/payments/cards", { hash, source });
773
+ const data = await slapiApi.post("/v1/payments/cards", { hash, source, saveCard });
763
774
  slapiLogger.info("Card added successfully", { cardId: data.id, hash });
764
775
  return { data };
765
776
  } catch (error) {
@@ -1118,11 +1129,11 @@ var init_InfoBanner = __esm({
1118
1129
  });
1119
1130
 
1120
1131
  // src/components/common/PointsSwitch.tsx
1121
- var import_react5, import_jsx_runtime9, PointsSwitch;
1132
+ var import_react6, import_jsx_runtime9, PointsSwitch;
1122
1133
  var init_PointsSwitch = __esm({
1123
1134
  "src/components/common/PointsSwitch.tsx"() {
1124
1135
  "use strict";
1125
- import_react5 = require("react");
1136
+ import_react6 = require("react");
1126
1137
  init_StaticConfigContext();
1127
1138
  init_useSlapiBalance();
1128
1139
  init_useSpreePayConfig();
@@ -1139,7 +1150,7 @@ var init_PointsSwitch = __esm({
1139
1150
  const { balance } = useSlapiBalance();
1140
1151
  const hasForeignCurrency = !!(currencyCode && exchangeRate && foreignCurrencyAmount);
1141
1152
  const formatPointsValue = (usd) => hasForeignCurrency ? formatCurrency(usd / exchangeRate, currencyCode) : formatCurrency(usd);
1142
- const id = (0, import_react5.useId)();
1153
+ const id = (0, import_react6.useId)();
1143
1154
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col gap-6", children: [
1144
1155
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
1145
1156
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-3", children: [
@@ -1311,14 +1322,63 @@ var init_CheckoutButton = __esm({
1311
1322
 
1312
1323
  // ../ui/src/lib/utils.ts
1313
1324
  function cn2(...inputs) {
1314
- return (0, import_tailwind_merge2.twMerge)((0, import_clsx2.clsx)(inputs));
1325
+ return twMerge2((0, import_clsx2.clsx)(inputs));
1315
1326
  }
1316
- var import_clsx2, import_tailwind_merge2;
1327
+ var import_clsx2, import_tailwind_merge2, isUniversalSpacing, isLayoutToken, isUniversalRadius, isTypography, twMerge2;
1317
1328
  var init_utils2 = __esm({
1318
1329
  "../ui/src/lib/utils.ts"() {
1319
1330
  "use strict";
1320
1331
  import_clsx2 = require("clsx");
1321
1332
  import_tailwind_merge2 = require("tailwind-merge");
1333
+ isUniversalSpacing = (value) => value.startsWith("universal-");
1334
+ isLayoutToken = (value) => value.startsWith("universal-") || value.startsWith("layout-");
1335
+ isUniversalRadius = (value) => value.startsWith("radius-universal-");
1336
+ isTypography = (value) => value.startsWith("heading-") || value.startsWith("body-") || value.startsWith("label-") || value.startsWith("menu-");
1337
+ twMerge2 = (0, import_tailwind_merge2.extendTailwindMerge)({
1338
+ extend: {
1339
+ classGroups: {
1340
+ "font-size": [{ text: [isTypography] }],
1341
+ leading: [{ leading: [isTypography] }],
1342
+ "font-weight": [{ font: [isTypography] }],
1343
+ p: [{ p: [isUniversalSpacing] }],
1344
+ px: [{ px: [isUniversalSpacing] }],
1345
+ py: [{ py: [isUniversalSpacing] }],
1346
+ pt: [{ pt: [isUniversalSpacing] }],
1347
+ pb: [{ pb: [isUniversalSpacing] }],
1348
+ pl: [{ pl: [isUniversalSpacing] }],
1349
+ pr: [{ pr: [isUniversalSpacing] }],
1350
+ m: [{ m: [isUniversalSpacing] }],
1351
+ mx: [{ mx: [isUniversalSpacing] }],
1352
+ my: [{ my: [isUniversalSpacing] }],
1353
+ mt: [{ mt: [isUniversalSpacing] }],
1354
+ mb: [{ mb: [isUniversalSpacing] }],
1355
+ ml: [{ ml: [isUniversalSpacing] }],
1356
+ mr: [{ mr: [isUniversalSpacing] }],
1357
+ gap: [{ gap: [isUniversalSpacing] }],
1358
+ "gap-x": [{ "gap-x": [isUniversalSpacing] }],
1359
+ "gap-y": [{ "gap-y": [isUniversalSpacing] }],
1360
+ "space-x": [{ "space-x": [isUniversalSpacing] }],
1361
+ "space-y": [{ "space-y": [isUniversalSpacing] }],
1362
+ w: [{ w: [isLayoutToken] }],
1363
+ "min-w": [{ "min-w": [isLayoutToken] }],
1364
+ "max-w": [{ "max-w": [isLayoutToken] }],
1365
+ h: [{ h: [isLayoutToken] }],
1366
+ "min-h": [{ "min-h": [isLayoutToken] }],
1367
+ "max-h": [{ "max-h": [isLayoutToken] }],
1368
+ rounded: [{ rounded: [isUniversalRadius] }],
1369
+ "rounded-s": [{ "rounded-s": [isUniversalRadius] }],
1370
+ "rounded-e": [{ "rounded-e": [isUniversalRadius] }],
1371
+ "rounded-t": [{ "rounded-t": [isUniversalRadius] }],
1372
+ "rounded-r": [{ "rounded-r": [isUniversalRadius] }],
1373
+ "rounded-b": [{ "rounded-b": [isUniversalRadius] }],
1374
+ "rounded-l": [{ "rounded-l": [isUniversalRadius] }],
1375
+ "rounded-tl": [{ "rounded-tl": [isUniversalRadius] }],
1376
+ "rounded-tr": [{ "rounded-tr": [isUniversalRadius] }],
1377
+ "rounded-br": [{ "rounded-br": [isUniversalRadius] }],
1378
+ "rounded-bl": [{ "rounded-bl": [isUniversalRadius] }]
1379
+ }
1380
+ }
1381
+ });
1322
1382
  }
1323
1383
  });
1324
1384
 
@@ -1754,7 +1814,7 @@ function Input2({ className, type, ...props }) {
1754
1814
  type,
1755
1815
  "data-slot": "input",
1756
1816
  className: cn2(
1757
- "file:text-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base text-(--primary) shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-(--tertiary) disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1817
+ "file:text-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input px-universal-2xs py-universal-6xs rounded-radius-universal-xs text-body-m file:text-label-s file:font-label-primary flex h-9 w-full min-w-0 border bg-transparent text-(--color-text-icons-primary-default) shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent placeholder:text-(--color-text-icons-tertiary-default) disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
1758
1818
  "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
1759
1819
  "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
1760
1820
  className
@@ -1864,7 +1924,7 @@ function Separator2({
1864
1924
  decorative,
1865
1925
  orientation,
1866
1926
  className: cn2(
1867
- "shrink-0 bg-(--b-secondary) data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
1927
+ "shrink-0 bg-(--color-border-default) data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
1868
1928
  className
1869
1929
  ),
1870
1930
  ...props
@@ -1994,11 +2054,11 @@ var init_useBaseTokens = __esm({
1994
2054
  });
1995
2055
 
1996
2056
  // src/modals/CryptoSelectModal.tsx
1997
- var import_react14, import_nice_modal_react5, import_jsx_runtime37, CryptoSelectModal;
2057
+ var import_react16, import_nice_modal_react5, import_jsx_runtime37, CryptoSelectModal;
1998
2058
  var init_CryptoSelectModal = __esm({
1999
2059
  "src/modals/CryptoSelectModal.tsx"() {
2000
2060
  "use strict";
2001
- import_react14 = require("react");
2061
+ import_react16 = require("react");
2002
2062
  import_nice_modal_react5 = __toESM(require("@ebay/nice-modal-react"), 1);
2003
2063
  init_input();
2004
2064
  init_separator();
@@ -2014,8 +2074,8 @@ var init_CryptoSelectModal = __esm({
2014
2074
  const { isLoading, error, erc20Balances } = useBaseERC20Token();
2015
2075
  const { isLoadingNative, nativeError, nativeBalance } = useBaseNativeToken();
2016
2076
  const { tokens, tokensIsLoading } = useBaseTokens();
2017
- const [search, setSearch] = (0, import_react14.useState)("");
2018
- const filteredCoins = (0, import_react14.useMemo)(() => {
2077
+ const [search, setSearch] = (0, import_react16.useState)("");
2078
+ const filteredCoins = (0, import_react16.useMemo)(() => {
2019
2079
  return tokens.filter(
2020
2080
  (coin) => coin.name.toLowerCase().includes(search.toLowerCase()) || coin.symbol.toLowerCase().includes(search.toLowerCase())
2021
2081
  );
@@ -2177,11 +2237,11 @@ var init_SelectedCoin = __esm({
2177
2237
  });
2178
2238
 
2179
2239
  // src/components/CryptoTab/Crypto/Crypto.tsx
2180
- var import_react15, import_wagmi4, import_jsx_runtime40, Crypto;
2240
+ var import_react17, import_wagmi4, import_jsx_runtime40, Crypto;
2181
2241
  var init_Crypto = __esm({
2182
2242
  "src/components/CryptoTab/Crypto/Crypto.tsx"() {
2183
2243
  "use strict";
2184
- import_react15 = require("react");
2244
+ import_react17 = require("react");
2185
2245
  import_wagmi4 = require("wagmi");
2186
2246
  init_SpreePayActionsContext();
2187
2247
  init_useCryptoPayment();
@@ -2200,7 +2260,7 @@ var init_Crypto = __esm({
2200
2260
  const { spreePayConfig } = useSpreePayConfig();
2201
2261
  const isWalletConnected = Boolean(address);
2202
2262
  const { register } = useSpreePayRegister();
2203
- const handlePay = (0, import_react15.useCallback)(
2263
+ const handlePay = (0, import_react17.useCallback)(
2204
2264
  async (data) => {
2205
2265
  try {
2206
2266
  const res = await cryptoPayment(data);
@@ -2214,7 +2274,7 @@ var init_Crypto = __esm({
2214
2274
  },
2215
2275
  [cryptoPayment]
2216
2276
  );
2217
- (0, import_react15.useEffect)(() => {
2277
+ (0, import_react17.useEffect)(() => {
2218
2278
  register(handlePay);
2219
2279
  }, [register, handlePay]);
2220
2280
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-col items-baseline gap-4", children: [
@@ -2250,11 +2310,11 @@ function getCachedWagmiConfig(projectId, appName) {
2250
2310
  }
2251
2311
  return cfg2;
2252
2312
  }
2253
- var import_react16, import_react_query, import_nice_modal_react7, import_rainbowkit2, import_styles, import_wagmi5, import_chains, import_jsx_runtime41, queryClient, CHAINS, wagmiConfigCache, CryptoWrapper;
2313
+ var import_react18, import_react_query, import_nice_modal_react7, import_rainbowkit2, import_styles, import_wagmi5, import_chains, import_jsx_runtime41, queryClient, CHAINS, wagmiConfigCache, CryptoWrapper;
2254
2314
  var init_CryptoWrapper = __esm({
2255
2315
  "src/components/CryptoTab/Crypto/CryptoWrapper.tsx"() {
2256
2316
  "use strict";
2257
- import_react16 = require("react");
2317
+ import_react18 = require("react");
2258
2318
  import_react_query = require("@tanstack/react-query");
2259
2319
  import_nice_modal_react7 = __toESM(require("@ebay/nice-modal-react"), 1);
2260
2320
  import_rainbowkit2 = require("@rainbow-me/rainbowkit");
@@ -2269,7 +2329,7 @@ var init_CryptoWrapper = __esm({
2269
2329
  wagmiConfigCache = /* @__PURE__ */ new Map();
2270
2330
  CryptoWrapper = () => {
2271
2331
  const { spreePayConfig, configIsLoading } = useSpreePayConfig();
2272
- const wagmiConfig = (0, import_react16.useMemo)(() => {
2332
+ const wagmiConfig = (0, import_react18.useMemo)(() => {
2273
2333
  if (!spreePayConfig) return null;
2274
2334
  return getCachedWagmiConfig(spreePayConfig.rainbowProjectId, spreePayConfig.rainbowAppName);
2275
2335
  }, [spreePayConfig]);
@@ -2456,11 +2516,11 @@ var init_Checkout = __esm({
2456
2516
  });
2457
2517
 
2458
2518
  // src/components/CryptoComTab/CryptoComTab.tsx
2459
- var import_react17, import_jsx_runtime44, CryptoComTab;
2519
+ var import_react19, import_jsx_runtime44, CryptoComTab;
2460
2520
  var init_CryptoComTab = __esm({
2461
2521
  "src/components/CryptoComTab/CryptoComTab.tsx"() {
2462
2522
  "use strict";
2463
- import_react17 = require("react");
2523
+ import_react19 = require("react");
2464
2524
  init_SpreePayActionsContext();
2465
2525
  init_useCryptoComPayment();
2466
2526
  init_useSpreePayConfig();
@@ -2472,7 +2532,7 @@ var init_CryptoComTab = __esm({
2472
2532
  const { register } = useSpreePayRegister();
2473
2533
  const { cryptoComPayment } = useCryptoComPayment();
2474
2534
  const { spreePayConfig } = useSpreePayConfig();
2475
- const handlePay = (0, import_react17.useCallback)(
2535
+ const handlePay = (0, import_react19.useCallback)(
2476
2536
  async (data) => {
2477
2537
  try {
2478
2538
  const res = await cryptoComPayment(data);
@@ -2486,7 +2546,7 @@ var init_CryptoComTab = __esm({
2486
2546
  },
2487
2547
  [cryptoComPayment]
2488
2548
  );
2489
- (0, import_react17.useEffect)(() => {
2549
+ (0, import_react19.useEffect)(() => {
2490
2550
  register(handlePay);
2491
2551
  }, [register, handlePay]);
2492
2552
  return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex w-full flex-col gap-4 border-b border-b-(--border-component-specific-card) px-5 py-5 md:px-7 md:py-6", children: [
@@ -2525,15 +2585,15 @@ __export(index_exports, {
2525
2585
  module.exports = __toCommonJS(index_exports);
2526
2586
 
2527
2587
  // src/SpreePay.tsx
2528
- var import_react21 = require("react");
2588
+ var import_react23 = require("react");
2529
2589
  var import_nice_modal_react9 = __toESM(require("@ebay/nice-modal-react"), 1);
2530
2590
  var import_swr5 = require("swr");
2531
2591
 
2532
2592
  // src/SpreePayContent.tsx
2533
- var import_react18 = require("react");
2593
+ var import_react20 = require("react");
2534
2594
 
2535
2595
  // src/components/CreditCardTab/CreditCardTab.tsx
2536
- var import_react13 = require("react");
2596
+ var import_react15 = require("react");
2537
2597
  init_SpreePayActionsContext();
2538
2598
  init_StaticConfigContext();
2539
2599
 
@@ -2572,7 +2632,11 @@ var useCardPayment = () => {
2572
2632
  lastFour: card.lastFourNumbers,
2573
2633
  schema: card.schema
2574
2634
  });
2575
- const { data: cardResData } = await SlapiPaymentService.addCard({ hash, source: card.token });
2635
+ const { data: cardResData } = await SlapiPaymentService.addCard({
2636
+ hash,
2637
+ source: card.token,
2638
+ saveCard: card.saveCard
2639
+ });
2576
2640
  cardId = cardResData.id;
2577
2641
  cardPaymentLogger.info("New card added successfully", { cardId });
2578
2642
  } else {
@@ -3054,14 +3118,16 @@ var useSplitCardPayments = (mode = "web2") => {
3054
3118
  };
3055
3119
 
3056
3120
  // src/hooks/useCards.ts
3121
+ var import_react5 = require("react");
3057
3122
  var import_swr2 = __toESM(require("swr"), 1);
3058
3123
  init_SpreePayActionsContext();
3059
3124
  var URL2 = "/v1/payments/cards";
3060
3125
  var useCards = () => {
3061
3126
  const { origin } = useSpreePayEnv();
3062
3127
  const { data, isLoading, mutate } = (0, import_swr2.default)(origin ? `${URL2}?origin=${origin}` : URL2);
3128
+ const cards = (0, import_react5.useMemo)(() => data?.data.filter((c) => c.active) ?? [], [data]);
3063
3129
  return {
3064
- cards: data?.data.filter((c) => c.active) || [],
3130
+ cards,
3065
3131
  cardsIsLoading: isLoading,
3066
3132
  mutateCards: mutate
3067
3133
  };
@@ -3075,7 +3141,7 @@ init_split();
3075
3141
  init_CheckoutButton();
3076
3142
 
3077
3143
  // src/components/CreditCardTab/CreditCard/CreditCard.tsx
3078
- var import_react7 = require("react");
3144
+ var import_react9 = require("react");
3079
3145
  var import_react_stripe_js2 = require("@stripe/react-stripe-js");
3080
3146
  var import_stripe_js = require("@stripe/stripe-js");
3081
3147
  init_SpreePayActionsContext();
@@ -3083,27 +3149,33 @@ init_useSpreePayConfig();
3083
3149
  init_InfoBanner();
3084
3150
 
3085
3151
  // src/components/CreditCardTab/CreditCard/CardsList.tsx
3152
+ var import_react7 = require("react");
3086
3153
  init_utils();
3154
+ init_slapi();
3155
+ init_payments();
3087
3156
  var import_jsx_runtime12 = require("react/jsx-runtime");
3088
- var isRemoveDisabled = true;
3089
- var CardListItem = ({ card, isSelected, onSelect }) => {
3090
- const handleSelect = () => {
3091
- onSelect(card);
3092
- };
3093
- const handleRemoveCard = (e) => {
3157
+ var CardListItem = ({ card, isSelected, onSelect, onRemove }) => {
3158
+ const [isRemoving, setIsRemoving] = (0, import_react7.useState)(false);
3159
+ const removeDisabled = isSelected || isRemoving;
3160
+ const handleRemove = async (e) => {
3094
3161
  e.stopPropagation();
3095
- if (isSelected || isRemoveDisabled) return;
3162
+ setIsRemoving(true);
3163
+ try {
3164
+ await onRemove(card);
3165
+ } finally {
3166
+ setIsRemoving(false);
3167
+ }
3096
3168
  };
3097
3169
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3098
- "button",
3170
+ "div",
3099
3171
  {
3100
- type: "button",
3101
- onClick: handleSelect,
3172
+ role: "button",
3173
+ tabIndex: 0,
3174
+ onClick: () => onSelect(card),
3175
+ onKeyDown: (e) => (e.key === "Enter" || e.key === " ") && onSelect(card),
3102
3176
  className: cn(
3103
- "flex h-12 w-full overflow-hidden rounded-md border-2 border-(--b-inverse) bg-(--s-primary) hover:bg-(--s-primary-hover)",
3104
- {
3105
- "border-(--b-brand)": isSelected
3106
- }
3177
+ "flex h-12 w-full cursor-pointer overflow-hidden rounded-md border-2 border-(--b-inverse) bg-(--s-primary) hover:bg-(--s-primary-hover)",
3178
+ { "border-(--b-brand)": isSelected }
3107
3179
  ),
3108
3180
  children: [
3109
3181
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
@@ -3129,13 +3201,12 @@ var CardListItem = ({ card, isSelected, onSelect }) => {
3129
3201
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "text-(--brand-primary)", children: card.lastFourNumbers })
3130
3202
  ] }),
3131
3203
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3132
- "div",
3204
+ "button",
3133
3205
  {
3134
- onClick: handleRemoveCard,
3135
- className: cn("rounded-md p-1 text-(--tertiary) transition-all hover:bg-(--s-secondary)", {
3136
- "cursor-not-allowed opacity-50": isSelected || isRemoveDisabled
3137
- // 'cursor-pointer': !isSelected || !isRemoveDisabled,
3138
- }),
3206
+ type: "button",
3207
+ onClick: handleRemove,
3208
+ disabled: removeDisabled,
3209
+ className: "text-tertiary rounded-md p-1 transition-all hover:bg-(--s-secondary) disabled:cursor-not-allowed disabled:opacity-50",
3139
3210
  children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "currentColor", className: "size-5", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M6.35 16.17q-.57 0-.96-.4a1.3 1.3 0 0 1-.39-.95V4.5h-.83v-.83H7.5v-.64h5v.64h3.33v.83H15v10.32q0 .58-.39.96a1.3 1.3 0 0 1-.96.39zM14.17 4.5H5.83v10.32q0 .23.15.37.15.15.37.15h7.3q.2 0 .36-.16.15-.17.16-.36zm-6 9.17h.84v-7.5h-.84zm2.82 0h.84v-7.5h-.84z" }) })
3140
3211
  }
3141
3212
  )
@@ -3147,17 +3218,35 @@ var CardListItem = ({ card, isSelected, onSelect }) => {
3147
3218
  }
3148
3219
  );
3149
3220
  };
3150
- var CardsList = ({ selectedCard, setCard }) => {
3151
- const { cards, cardsIsLoading } = useCards();
3221
+ var CardsList = ({ selectedCard, setCard, newCards, onRemoveNewCard }) => {
3222
+ const { cards, cardsIsLoading, mutateCards } = useCards();
3223
+ const allCards = (0, import_react7.useMemo)(() => [...cards, ...newCards], [cards, newCards]);
3224
+ const handleRemove = async (card) => {
3225
+ if (isNewCard(card)) {
3226
+ onRemoveNewCard(card);
3227
+ } else {
3228
+ await SlapiPaymentService.removeCard({ cardId: card.id });
3229
+ mutateCards((data) => ({ ...data, data: (data?.data ?? []).filter((c) => c.id !== card.id) }));
3230
+ }
3231
+ };
3152
3232
  if (cardsIsLoading) {
3153
3233
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex w-full flex-col", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "h-11 animate-pulse rounded-sm bg-(--s-primary)" }) });
3154
3234
  }
3155
- if (cards.length === 0) return null;
3156
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex w-full flex-col gap-4", children: cards.map((card) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CardListItem, { isSelected: selectedCard?.id === card.id, onSelect: setCard, card }, card.id)) });
3235
+ if (allCards.length === 0) return null;
3236
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex w-full flex-col gap-4", children: allCards.map((card) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3237
+ CardListItem,
3238
+ {
3239
+ isSelected: selectedCard?.id === card.id,
3240
+ onSelect: setCard,
3241
+ onRemove: handleRemove,
3242
+ card
3243
+ },
3244
+ card.id
3245
+ )) });
3157
3246
  };
3158
3247
 
3159
3248
  // src/components/CreditCardTab/CreditCard/CreditCardForm.tsx
3160
- var import_react6 = require("react");
3249
+ var import_react8 = require("react");
3161
3250
  var import_react_stripe_js = require("@stripe/react-stripe-js");
3162
3251
 
3163
3252
  // src/ui/button.tsx
@@ -3213,7 +3302,7 @@ function Checkbox({ className, ...props }) {
3213
3302
  {
3214
3303
  "data-slot": "checkbox",
3215
3304
  className: cn(
3216
- "peer border-input dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-sm border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-(--primary) data-[state=checked]:bg-(--primary) data-[state=checked]:text-(--inverse) dark:data-[state=checked]:bg-(--primary)",
3305
+ "peer border-input dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-sm border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-(--s-brand) data-[state=checked]:bg-(--s-brand) data-[state=checked]:text-(--inverse)",
3217
3306
  className
3218
3307
  ),
3219
3308
  ...props,
@@ -3240,13 +3329,14 @@ var stripeElementClasses = {
3240
3329
  focus: "border-ring ring-ring/50 ring-2"
3241
3330
  };
3242
3331
  var CreditCardForm = ({ cancel, saveCard }) => {
3243
- const [cardError, setCardError] = (0, import_react6.useState)(void 0);
3244
- const [stripeStyles, setStripeStyles] = (0, import_react6.useState)({});
3245
- const formRef = (0, import_react6.useRef)(null);
3332
+ const [cardError, setCardError] = (0, import_react8.useState)(void 0);
3333
+ const [stripeStyles, setStripeStyles] = (0, import_react8.useState)({});
3334
+ const [shouldSaveCard, setShouldSaveCard] = (0, import_react8.useState)(true);
3335
+ const formRef = (0, import_react8.useRef)(null);
3246
3336
  const elements = (0, import_react_stripe_js.useElements)();
3247
3337
  const stripe = (0, import_react_stripe_js.useStripe)();
3248
- const id = (0, import_react6.useId)();
3249
- const computeStripeStyles = (0, import_react6.useCallback)(() => {
3338
+ const [id] = (0, import_react8.useState)(() => crypto.randomUUID());
3339
+ const computeStripeStyles = (0, import_react8.useCallback)(() => {
3250
3340
  const formRefCurrent = formRef.current;
3251
3341
  if (typeof window === "undefined" || !formRefCurrent) return {};
3252
3342
  const container = formRefCurrent.closest(".sl-spreepay");
@@ -3267,7 +3357,7 @@ var CreditCardForm = ({ cancel, saveCard }) => {
3267
3357
  }
3268
3358
  };
3269
3359
  }, []);
3270
- (0, import_react6.useEffect)(() => {
3360
+ (0, import_react8.useEffect)(() => {
3271
3361
  setStripeStyles(computeStripeStyles());
3272
3362
  }, [computeStripeStyles]);
3273
3363
  const handleSaveCard = async () => {
@@ -3295,7 +3385,8 @@ var CreditCardForm = ({ cancel, saveCard }) => {
3295
3385
  schema: token.card?.brand,
3296
3386
  lastFourNumbers: token.card?.last4 ?? "",
3297
3387
  expireMonth: `${token.card?.exp_month}`,
3298
- expireYear: `${token.card?.exp_year}`
3388
+ expireYear: `${token.card?.exp_year}`,
3389
+ saveCard: shouldSaveCard
3299
3390
  });
3300
3391
  }
3301
3392
  }
@@ -3341,7 +3432,7 @@ var CreditCardForm = ({ cancel, saveCard }) => {
3341
3432
  cardError && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-destructive mt-1 text-sm", children: cardError })
3342
3433
  ] }),
3343
3434
  /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-2", children: [
3344
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Checkbox, { disabled: true, checked: true, id: "saveCard" }),
3435
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Checkbox, { checked: shouldSaveCard, onCheckedChange: (v) => setShouldSaveCard(v === true), id: "saveCard" }),
3345
3436
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Label, { className: "text-sm font-medium", htmlFor: "saveCard", children: "Save card for future purchases" })
3346
3437
  ] }),
3347
3438
  /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex w-full justify-end gap-2", children: [
@@ -3368,23 +3459,31 @@ var CreditCardForm = ({ cancel, saveCard }) => {
3368
3459
 
3369
3460
  // src/components/CreditCardTab/CreditCard/CreditCard.tsx
3370
3461
  var import_jsx_runtime16 = require("react/jsx-runtime");
3371
- var StripeWrapper = (props) => {
3372
- const stripePromise = (0, import_react7.useMemo)(() => (0, import_stripe_js.loadStripe)(props.publicKey), [props.publicKey]);
3373
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_stripe_js2.Elements, { stripe: stripePromise, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CreditCardForm, { cancel: props.onCancel, saveCard: props.saveNewCard }) });
3462
+ var StripeWrapper = ({ onCancel, saveNewCard, publicKey }) => {
3463
+ const stripePromise = (0, import_react9.useMemo)(() => (0, import_stripe_js.loadStripe)(publicKey), [publicKey]);
3464
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_stripe_js2.Elements, { stripe: stripePromise, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CreditCardForm, { cancel: onCancel, saveCard: saveNewCard }) });
3374
3465
  };
3375
3466
  var CreditCard = () => {
3376
- const [showForm, setShowForm] = (0, import_react7.useState)(false);
3467
+ const [showForm, setShowForm] = (0, import_react9.useState)(false);
3468
+ const [newCards, setNewCards] = (0, import_react9.useState)([]);
3377
3469
  const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
3378
- const { mutateCards } = useCards();
3379
3470
  const { spreePayConfig } = useSpreePayConfig();
3380
3471
  const setCard = (card) => {
3381
- setSelectedPaymentMethod({ ...selectedPaymentMethod, type: "CREDIT_CARD" /* CREDIT_CARD */, method: card });
3472
+ const isAlreadySelected = selectedPaymentMethod?.type === "CREDIT_CARD" /* CREDIT_CARD */ && selectedPaymentMethod.method?.id === card.id;
3473
+ setSelectedPaymentMethod({
3474
+ ...selectedPaymentMethod,
3475
+ type: "CREDIT_CARD" /* CREDIT_CARD */,
3476
+ method: isAlreadySelected ? null : card
3477
+ });
3382
3478
  };
3383
3479
  const saveNewCard = (newCard) => {
3384
- mutateCards((data) => ({ ...data, data: [...data?.data ?? [], newCard] }), { revalidate: false });
3480
+ setNewCards((prev) => [...prev, newCard]);
3385
3481
  setCard(newCard);
3386
3482
  setShowForm(false);
3387
3483
  };
3484
+ const removeNewCard = (0, import_react9.useCallback)((card) => {
3485
+ setNewCards((prev) => prev.filter((c) => c.id !== card.id));
3486
+ }, []);
3388
3487
  const handleCancel = () => {
3389
3488
  setShowForm(false);
3390
3489
  };
@@ -3395,7 +3494,9 @@ var CreditCard = () => {
3395
3494
  CardsList,
3396
3495
  {
3397
3496
  selectedCard: selectedPaymentMethod?.type === "CREDIT_CARD" /* CREDIT_CARD */ ? selectedPaymentMethod.method : null,
3398
- setCard
3497
+ setCard,
3498
+ newCards,
3499
+ onRemoveNewCard: removeNewCard
3399
3500
  }
3400
3501
  ),
3401
3502
  spreePayConfig?.creditCard.infoMessage && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(InfoBanner, { message: spreePayConfig.creditCard.infoMessage }),
@@ -3414,14 +3515,14 @@ var CreditCard = () => {
3414
3515
  };
3415
3516
 
3416
3517
  // src/components/CreditCardTab/Points/Points.tsx
3417
- var import_react12 = require("react");
3518
+ var import_react14 = require("react");
3418
3519
  init_SpreePayActionsContext();
3419
3520
  init_StaticConfigContext();
3420
3521
  init_useSpreePayConfig();
3421
3522
  init_common();
3422
3523
 
3423
3524
  // src/components/CreditCardTab/Points/SplitBlock.tsx
3424
- var import_react11 = require("react");
3525
+ var import_react13 = require("react");
3425
3526
  var import_airkit2 = require("@mocanetwork/airkit");
3426
3527
  init_SpreePayActionsContext();
3427
3528
  init_StaticConfigContext();
@@ -3431,7 +3532,7 @@ init_format();
3431
3532
  init_logger();
3432
3533
 
3433
3534
  // src/components/CreditCardTab/Points/PointsSelector.tsx
3434
- var import_react10 = require("react");
3535
+ var import_react12 = require("react");
3435
3536
  init_SpreePayActionsContext();
3436
3537
  init_StaticConfigContext();
3437
3538
  init_useSlapiBalance();
@@ -3751,10 +3852,10 @@ var Primitive = NODES.reduce((primitive, node) => {
3751
3852
  }, {});
3752
3853
 
3753
3854
  // ../../node_modules/@radix-ui/react-collection/dist/index.mjs
3754
- var import_react8 = __toESM(require("react"), 1);
3855
+ var import_react10 = __toESM(require("react"), 1);
3755
3856
  var import_react_slot3 = require("@radix-ui/react-slot");
3756
3857
  var import_jsx_runtime21 = require("react/jsx-runtime");
3757
- var import_react9 = __toESM(require("react"), 1);
3858
+ var import_react11 = __toESM(require("react"), 1);
3758
3859
  var import_react_slot4 = require("@radix-ui/react-slot");
3759
3860
  var import_jsx_runtime22 = require("react/jsx-runtime");
3760
3861
  function createCollection(name) {
@@ -3766,14 +3867,14 @@ function createCollection(name) {
3766
3867
  );
3767
3868
  const CollectionProvider = (props) => {
3768
3869
  const { scope, children } = props;
3769
- const ref = import_react8.default.useRef(null);
3770
- const itemMap = import_react8.default.useRef(/* @__PURE__ */ new Map()).current;
3870
+ const ref = import_react10.default.useRef(null);
3871
+ const itemMap = import_react10.default.useRef(/* @__PURE__ */ new Map()).current;
3771
3872
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CollectionProviderImpl, { scope, itemMap, collectionRef: ref, children });
3772
3873
  };
3773
3874
  CollectionProvider.displayName = PROVIDER_NAME;
3774
3875
  const COLLECTION_SLOT_NAME = name + "CollectionSlot";
3775
3876
  const CollectionSlotImpl = (0, import_react_slot3.createSlot)(COLLECTION_SLOT_NAME);
3776
- const CollectionSlot = import_react8.default.forwardRef(
3877
+ const CollectionSlot = import_react10.default.forwardRef(
3777
3878
  (props, forwardedRef) => {
3778
3879
  const { scope, children } = props;
3779
3880
  const context = useCollectionContext(COLLECTION_SLOT_NAME, scope);
@@ -3785,13 +3886,13 @@ function createCollection(name) {
3785
3886
  const ITEM_SLOT_NAME = name + "CollectionItemSlot";
3786
3887
  const ITEM_DATA_ATTR = "data-radix-collection-item";
3787
3888
  const CollectionItemSlotImpl = (0, import_react_slot3.createSlot)(ITEM_SLOT_NAME);
3788
- const CollectionItemSlot = import_react8.default.forwardRef(
3889
+ const CollectionItemSlot = import_react10.default.forwardRef(
3789
3890
  (props, forwardedRef) => {
3790
3891
  const { scope, children, ...itemData } = props;
3791
- const ref = import_react8.default.useRef(null);
3892
+ const ref = import_react10.default.useRef(null);
3792
3893
  const composedRefs = useComposedRefs(forwardedRef, ref);
3793
3894
  const context = useCollectionContext(ITEM_SLOT_NAME, scope);
3794
- import_react8.default.useEffect(() => {
3895
+ import_react10.default.useEffect(() => {
3795
3896
  context.itemMap.set(ref, { ref, ...itemData });
3796
3897
  return () => void context.itemMap.delete(ref);
3797
3898
  });
@@ -3801,7 +3902,7 @@ function createCollection(name) {
3801
3902
  CollectionItemSlot.displayName = ITEM_SLOT_NAME;
3802
3903
  function useCollection2(scope) {
3803
3904
  const context = useCollectionContext(name + "CollectionConsumer", scope);
3804
- const getItems = import_react8.default.useCallback(() => {
3905
+ const getItems = import_react10.default.useCallback(() => {
3805
3906
  const collectionNode = context.collectionRef.current;
3806
3907
  if (!collectionNode) return [];
3807
3908
  const orderedNodes = Array.from(collectionNode.querySelectorAll(`[${ITEM_DATA_ATTR}]`));
@@ -4434,7 +4535,7 @@ var PointsSelector = (props) => {
4434
4535
  const maxByAmount = pointsConversionRatio && pointsConversionRatio > 0 ? (amount ?? 0) / pointsConversionRatio : 0;
4435
4536
  const max = Math.min(maxByAmount, balance?.availablePoints ?? 0);
4436
4537
  const step = 10;
4437
- const [splitTokens, setSplitTokens] = (0, import_react10.useState)(0);
4538
+ const [splitTokens, setSplitTokens] = (0, import_react12.useState)(0);
4438
4539
  const usdAmount = getSplitAmount(amount ?? 0, splitTokens, pointsConversionRatio);
4439
4540
  const pointsValue = String(Math.round(splitTokens));
4440
4541
  const usdWithFee = usdAmount + getTransactionFee(usdAmount, transactionFeePercentage);
@@ -4532,14 +4633,14 @@ var SplitBlock = (props) => {
4532
4633
  const { spreePayConfig } = useSpreePayConfig();
4533
4634
  const { appProps } = useStaticConfig();
4534
4635
  const { currencyCode, exchangeRate, foreignCurrencyAmount } = appProps;
4535
- const [address, setAddress] = (0, import_react11.useState)(null);
4536
- const [walletReady, setWalletReady] = (0, import_react11.useState)(false);
4636
+ const [address, setAddress] = (0, import_react13.useState)(null);
4637
+ const [walletReady, setWalletReady] = (0, import_react13.useState)(false);
4537
4638
  const { pointsConversionRatio, pointsTitle } = spreePayConfig || {};
4538
4639
  const { useWeb3Points, environment } = useSpreePayEnv();
4539
4640
  const hasForeignCurrency = !!(currencyCode && exchangeRate && foreignCurrencyAmount);
4540
4641
  const formatPointsValue = (usd) => hasForeignCurrency ? formatCurrency(usd / exchangeRate, currencyCode) : formatCurrency(usd);
4541
- const prevPointsChainRef = (0, import_react11.useRef)(spreePayConfig?.pointsChain);
4542
- const initWallet = (0, import_react11.useCallback)(
4642
+ const prevPointsChainRef = (0, import_react13.useRef)(spreePayConfig?.pointsChain);
4643
+ const initWallet = (0, import_react13.useCallback)(
4543
4644
  async (pointsChain) => {
4544
4645
  if (!pointsChain) return;
4545
4646
  try {
@@ -4562,7 +4663,7 @@ var SplitBlock = (props) => {
4562
4663
  },
4563
4664
  [onToggle, environment]
4564
4665
  );
4565
- (0, import_react11.useEffect)(() => {
4666
+ (0, import_react13.useEffect)(() => {
4566
4667
  if (!useWeb3Points) return;
4567
4668
  const pointsChainChanged = prevPointsChainRef.current !== spreePayConfig?.pointsChain;
4568
4669
  prevPointsChainRef.current = spreePayConfig?.pointsChain;
@@ -4592,8 +4693,8 @@ var SplitBlock = (props) => {
4592
4693
  // src/components/CreditCardTab/Points/Points.tsx
4593
4694
  var import_jsx_runtime27 = require("react/jsx-runtime");
4594
4695
  var Points = () => {
4595
- const [usePoints, setUsePoints] = (0, import_react12.useState)(false);
4596
- const [selectedPointsType, setSelectedPointsType] = (0, import_react12.useState)(null);
4696
+ const [usePoints, setUsePoints] = (0, import_react14.useState)(false);
4697
+ const [selectedPointsType, setSelectedPointsType] = (0, import_react14.useState)(null);
4597
4698
  const { setSelectedPaymentMethod, selectedPaymentMethod } = useSpreePaymentMethod();
4598
4699
  const { spreePayConfig } = useSpreePayConfig();
4599
4700
  const { appProps } = useStaticConfig();
@@ -4639,7 +4740,7 @@ var CreditCardTab = ({ isLoggedIn }) => {
4639
4740
  const { cardPayment } = useCardPayment();
4640
4741
  const { splitPayment } = useSplitCardPayments(isWeb3Enabled ? "web3" : "web2");
4641
4742
  const { pointsPayment } = usePointsPayment(isWeb3Enabled ? "web3" : "web2");
4642
- const handlePay = (0, import_react13.useCallback)(
4743
+ const handlePay = (0, import_react15.useCallback)(
4643
4744
  async (data) => {
4644
4745
  try {
4645
4746
  let res = null;
@@ -4678,7 +4779,7 @@ var CreditCardTab = ({ isLoggedIn }) => {
4678
4779
  mutateBalance
4679
4780
  ]
4680
4781
  );
4681
- (0, import_react13.useEffect)(() => {
4782
+ (0, import_react15.useEffect)(() => {
4682
4783
  register(handlePay);
4683
4784
  }, [register, handlePay]);
4684
4785
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { children: [
@@ -4763,8 +4864,8 @@ var TabButtons = (props) => {
4763
4864
  // src/SpreePayContent.tsx
4764
4865
  init_SpreePayActionsContext();
4765
4866
  var import_jsx_runtime45 = require("react/jsx-runtime");
4766
- var CryptoTab2 = (0, import_react18.lazy)(() => Promise.resolve().then(() => (init_CryptoTab2(), CryptoTab_exports)).then((module2) => ({ default: module2.CryptoTab })));
4767
- var CryptoComTab2 = (0, import_react18.lazy)(
4867
+ var CryptoTab2 = (0, import_react20.lazy)(() => Promise.resolve().then(() => (init_CryptoTab2(), CryptoTab_exports)).then((module2) => ({ default: module2.CryptoTab })));
4868
+ var CryptoComTab2 = (0, import_react20.lazy)(
4768
4869
  () => Promise.resolve().then(() => (init_CryptoComTab2(), CryptoComTab_exports)).then((module2) => ({ default: module2.CryptoComTab }))
4769
4870
  );
4770
4871
  var TabLoadingFallback = () => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "flex items-center justify-center px-5 py-8 md:px-7", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex flex-col items-center gap-3", children: [
@@ -4779,7 +4880,7 @@ var SpreePayContent = ({ isLoggedIn }) => {
4779
4880
  /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TabButtons, { value: selectedPaymentMethod.type, onChange: setSelectedPaymentMethod })
4780
4881
  ] }),
4781
4882
  selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(CreditCardTab, { isLoggedIn }),
4782
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_react18.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TabLoadingFallback, {}), children: [
4883
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_react20.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TabLoadingFallback, {}), children: [
4783
4884
  selectedPaymentMethod.type === "CRYPTO" /* CRYPTO */ && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(CryptoTab2, { isLoggedIn }),
4784
4885
  selectedPaymentMethod.type === "CDC" /* CDC */ && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(CryptoComTab2, {})
4785
4886
  ] })
@@ -4787,10 +4888,11 @@ var SpreePayContent = ({ isLoggedIn }) => {
4787
4888
  };
4788
4889
 
4789
4890
  // src/components/ErrorBoundary.tsx
4790
- var import_react19 = require("react");
4891
+ var import_react21 = require("react");
4892
+ init_utils();
4791
4893
  init_logger();
4792
4894
  var import_jsx_runtime46 = require("react/jsx-runtime");
4793
- var ErrorBoundary = class extends import_react19.Component {
4895
+ var ErrorBoundary = class extends import_react21.Component {
4794
4896
  constructor(props) {
4795
4897
  super(props);
4796
4898
  this.state = { hasError: false, error: null };
@@ -4808,8 +4910,8 @@ var ErrorBoundary = class extends import_react19.Component {
4808
4910
  if (this.props.fallback) {
4809
4911
  return this.props.fallback;
4810
4912
  }
4811
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex w-full flex-col items-center justify-center rounded-3xl border border-(--b-inverse) bg-(--s-primary) p-8", children: [
4812
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "mb-4 flex size-12 items-center justify-center rounded-full bg-(--s-secondary)", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
4913
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: cn("sl-spreepay", this.props.className), children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex w-full flex-col items-center justify-center rounded-3xl border border-(--border-component-specific-card) bg-(--surface-component-specific-card-default-card) p-8 shadow-[0_6.25px_25px_0_var(--shadow-component-specific-card)]", children: [
4914
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "mb-4 flex size-12 items-center justify-center rounded-full bg-(--s-warning-subtle)", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
4813
4915
  "svg",
4814
4916
  {
4815
4917
  xmlns: "http://www.w3.org/2000/svg",
@@ -4827,9 +4929,9 @@ var ErrorBoundary = class extends import_react19.Component {
4827
4929
  ]
4828
4930
  }
4829
4931
  ) }),
4830
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h3", { className: "mb-2 text-lg font-semibold text-(--primary)", children: "Payment Widget Error" }),
4831
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-center text-sm text-(--secondary)", children: "Something went wrong loading the payment widget. Please refresh the page and try again." })
4832
- ] });
4932
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h3", { className: "mb-2 text-lg font-semibold text-(--brand-primary)", children: "Payment Widget Error" }),
4933
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-center text-sm text-(--text-tertiary)", children: "Something went wrong loading the payment widget. Please refresh the page and try again." })
4934
+ ] }) });
4833
4935
  }
4834
4936
  return this.props.children;
4835
4937
  }
@@ -4841,22 +4943,22 @@ init_StaticConfigContext();
4841
4943
  init_client();
4842
4944
 
4843
4945
  // src/hooks/useKeycloakSSO.ts
4844
- var import_react20 = require("react");
4946
+ var import_react22 = require("react");
4845
4947
  var import_keycloak_js = __toESM(require("keycloak-js"), 1);
4846
4948
  init_logger();
4847
4949
  var refreshAheadSeconds = 60;
4848
4950
  var keycloakLogger = logger.child("keycloak");
4849
4951
  function useKeycloakSSO(config2) {
4850
4952
  const { url, realm, clientId, ssoPageURI, enabled } = config2;
4851
- const initRef = (0, import_react20.useRef)(false);
4852
- const kcRef = (0, import_react20.useRef)(null);
4853
- const refreshTimerRef = (0, import_react20.useRef)(null);
4854
- const scheduleRefreshRef = (0, import_react20.useRef)(() => {
4953
+ const initRef = (0, import_react22.useRef)(false);
4954
+ const kcRef = (0, import_react22.useRef)(null);
4955
+ const refreshTimerRef = (0, import_react22.useRef)(null);
4956
+ const scheduleRefreshRef = (0, import_react22.useRef)(() => {
4855
4957
  });
4856
- const [error, setError] = (0, import_react20.useState)(null);
4857
- const [isChecking, setIsChecking] = (0, import_react20.useState)(enabled);
4858
- const [accessToken, setAccessToken] = (0, import_react20.useState)(null);
4859
- const scheduleRefresh = (0, import_react20.useCallback)(() => {
4958
+ const [error, setError] = (0, import_react22.useState)(null);
4959
+ const [isChecking, setIsChecking] = (0, import_react22.useState)(enabled);
4960
+ const [accessToken, setAccessToken] = (0, import_react22.useState)(null);
4961
+ const scheduleRefresh = (0, import_react22.useCallback)(() => {
4860
4962
  const kc = kcRef.current;
4861
4963
  if (!kc || !kc.tokenParsed || !kc.tokenParsed.exp) {
4862
4964
  return;
@@ -4880,10 +4982,10 @@ function useKeycloakSSO(config2) {
4880
4982
  });
4881
4983
  }, delayMs);
4882
4984
  }, []);
4883
- (0, import_react20.useEffect)(() => {
4985
+ (0, import_react22.useEffect)(() => {
4884
4986
  scheduleRefreshRef.current = scheduleRefresh;
4885
4987
  }, [scheduleRefresh]);
4886
- (0, import_react20.useEffect)(() => {
4988
+ (0, import_react22.useEffect)(() => {
4887
4989
  if (initRef.current || !enabled) return;
4888
4990
  initRef.current = true;
4889
4991
  const kc = new import_keycloak_js.default({ url, realm, clientId });
@@ -4920,30 +5022,44 @@ function useKeycloakSSO(config2) {
4920
5022
  init_utils();
4921
5023
  init_portal();
4922
5024
  init_logger();
5025
+
5026
+ // src/utils/token.ts
5027
+ var import_jwt_decode = require("jwt-decode");
5028
+ var isTokenExpired = (token) => {
5029
+ try {
5030
+ const { exp } = (0, import_jwt_decode.jwtDecode)(token);
5031
+ return typeof exp === "number" && exp < Math.floor(Date.now() / 1e3);
5032
+ } catch {
5033
+ return true;
5034
+ }
5035
+ };
5036
+
5037
+ // src/SpreePay.tsx
4923
5038
  var import_jsx_runtime47 = require("react/jsx-runtime");
4924
5039
  var SpreePayInner = () => {
4925
- const [portalEl, setPortalEl] = (0, import_react21.useState)(null);
4926
- const rootRef = (0, import_react21.useCallback)((node) => {
5040
+ const [portalEl, setPortalEl] = (0, import_react23.useState)(null);
5041
+ const rootRef = (0, import_react23.useCallback)((node) => {
4927
5042
  if (!node) return;
4928
5043
  const el = node.querySelector(":scope > .sl-spreepay__portal");
4929
5044
  setPortalEl(el ?? null);
4930
5045
  }, []);
4931
5046
  const { environment, tenantId, keycloakClientId, accessToken: envAccessToken, ssoPageURI } = useSpreePayEnv();
4932
- (0, import_react21.useEffect)(() => {
5047
+ (0, import_react23.useEffect)(() => {
4933
5048
  configureLogger({ environment });
4934
5049
  logger.logVersion();
4935
5050
  }, [environment]);
4936
5051
  const { staticConfig, appProps } = useStaticConfig();
5052
+ const envTokenValid = Boolean(envAccessToken && !isTokenExpired(envAccessToken));
4937
5053
  const { isChecking, accessToken } = useKeycloakSSO({
4938
5054
  realm: tenantId,
4939
5055
  url: staticConfig.keycloakUrl,
4940
5056
  clientId: keycloakClientId ?? "oneof-next",
4941
5057
  ssoPageURI,
4942
- enabled: !envAccessToken
5058
+ enabled: !envTokenValid
4943
5059
  });
4944
- const _accessToken = envAccessToken ?? accessToken;
4945
- const unauthenticatedFetcher = (0, import_react21.useCallback)(() => Promise.resolve(null), []);
4946
- const slapiFetcher = (0, import_react21.useMemo)(() => {
5060
+ const _accessToken = envTokenValid ? envAccessToken : accessToken;
5061
+ const unauthenticatedFetcher = (0, import_react23.useCallback)(() => Promise.resolve(null), []);
5062
+ const slapiFetcher = (0, import_react23.useMemo)(() => {
4947
5063
  if (_accessToken) {
4948
5064
  return registerApi({
4949
5065
  accessToken: _accessToken,
@@ -4979,13 +5095,13 @@ var SpreePayInner = () => {
4979
5095
  ] });
4980
5096
  };
4981
5097
  var SpreePay = (props) => {
4982
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(StaticConfigProvider, { props, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(SpreePayInner, {}) }) });
5098
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ErrorBoundary, { className: props.className, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(StaticConfigProvider, { props, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(SpreePayInner, {}) }) });
4983
5099
  };
4984
5100
 
4985
5101
  // src/hooks/useCapture3DS.ts
4986
- var import_react22 = require("react");
5102
+ var import_react24 = require("react");
4987
5103
  var useCapture3DS = (searchParams) => {
4988
- (0, import_react22.useEffect)(() => {
5104
+ (0, import_react24.useEffect)(() => {
4989
5105
  if (typeof window !== "undefined" && window.parent && searchParams?.paymentIntent) {
4990
5106
  window.parent.SP_EVENT_BUS?.emit("paymentIntent", { paymentIntent: searchParams.paymentIntent });
4991
5107
  }