@superlogic/spree-pay 0.5.4 → 0.5.5

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Iframe3ds
3
- } from "./chunk-QJCZPYQC.js";
3
+ } from "./chunk-OTFCW74L.js";
4
4
  import {
5
5
  InfoBanner,
6
6
  Legal,
@@ -15,7 +15,7 @@ import {
15
15
  useSpreePayRegister,
16
16
  useSpreePaymentMethod,
17
17
  useStaticConfig
18
- } from "./chunk-RZ43EXC2.js";
18
+ } from "./chunk-WYLYH7AK.js";
19
19
 
20
20
  // src/components/CryptoComTab/CryptoComTab.tsx
21
21
  import { useCallback, useEffect } from "react";
@@ -2,7 +2,7 @@ import {
2
2
  CheckoutButton,
3
3
  PointsSwitch,
4
4
  cn as cn2
5
- } from "./chunk-H7S3CTS3.js";
5
+ } from "./chunk-UVD3GGPC.js";
6
6
  import {
7
7
  Dialog,
8
8
  DialogContent,
@@ -20,7 +20,7 @@ import {
20
20
  useSpreePayConfig,
21
21
  useSpreePayRegister,
22
22
  useSpreePaymentMethod
23
- } from "./chunk-RZ43EXC2.js";
23
+ } from "./chunk-WYLYH7AK.js";
24
24
 
25
25
  // src/components/CryptoTab/Crypto/CryptoWrapper.tsx
26
26
  import { useMemo as useMemo2 } from "react";
@@ -5,7 +5,7 @@ import {
5
5
  DialogTitle,
6
6
  esm_default,
7
7
  useModal
8
- } from "./chunk-RZ43EXC2.js";
8
+ } from "./chunk-WYLYH7AK.js";
9
9
 
10
10
  // src/modals/Iframe3ds.tsx
11
11
  import { useEffect } from "react";
@@ -7,7 +7,7 @@ import {
7
7
  useSpreePayEnv,
8
8
  useSpreePaymentMethod,
9
9
  useStaticConfig
10
- } from "./chunk-RZ43EXC2.js";
10
+ } from "./chunk-WYLYH7AK.js";
11
11
 
12
12
  // src/components/common/PointsSwitch.tsx
13
13
  import { useId } from "react";
@@ -86,7 +86,7 @@ var settlePaymentResult = (res, fallbackMessage, failureCode = "PAYMENT_ERROR" /
86
86
  };
87
87
 
88
88
  // package.json
89
- var version = "0.5.4";
89
+ var version = "0.5.5";
90
90
 
91
91
  // src/utils/logger.ts
92
92
  var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
@@ -986,11 +986,11 @@ var useSpreePayConfig = () => {
986
986
  const { origin, tenantId } = useSpreePayEnv();
987
987
  const { staticConfig } = useStaticConfig();
988
988
  const key = origin ? `${URL}?origin=${origin}` : URL;
989
- const { data, isLoading } = useSWR(
989
+ const { data, isLoading, error } = useSWR(
990
990
  key,
991
991
  (path) => publicGet(staticConfig.slapiUrl, tenantId, path)
992
992
  );
993
- return { spreePayConfig: data ?? null, configIsLoading: isLoading };
993
+ return { spreePayConfig: data ?? null, configIsLoading: isLoading, configError: error };
994
994
  };
995
995
 
996
996
  // src/context/LoginStatusContext.tsx
package/build/index.cjs CHANGED
@@ -575,7 +575,7 @@ var init_errors = __esm({
575
575
  var version;
576
576
  var init_package = __esm({
577
577
  "package.json"() {
578
- version = "0.5.4";
578
+ version = "0.5.5";
579
579
  }
580
580
  });
581
581
 
@@ -1412,11 +1412,11 @@ var init_useSpreePayConfig = __esm({
1412
1412
  const { origin, tenantId } = useSpreePayEnv();
1413
1413
  const { staticConfig } = useStaticConfig();
1414
1414
  const key = origin ? `${URL}?origin=${origin}` : URL;
1415
- const { data, isLoading } = (0, import_swr.default)(
1415
+ const { data, isLoading, error } = (0, import_swr.default)(
1416
1416
  key,
1417
1417
  (path) => publicGet(staticConfig.slapiUrl, tenantId, path)
1418
1418
  );
1419
- return { spreePayConfig: data ?? null, configIsLoading: isLoading };
1419
+ return { spreePayConfig: data ?? null, configIsLoading: isLoading, configError: error };
1420
1420
  };
1421
1421
  }
1422
1422
  });
@@ -3882,7 +3882,7 @@ var stripeElementClasses = {
3882
3882
  invalid: "focus-visible:ring-(--negative)",
3883
3883
  focus: "border-(--b-tertiary) ring-(--b-tertiary)/50 ring-2"
3884
3884
  };
3885
- var CreditCardForm = ({ cancel, saveCard }) => {
3885
+ var CreditCardForm = ({ cancel, saveCard, showCancel }) => {
3886
3886
  const [cardError, setCardError] = (0, import_react10.useState)(void 0);
3887
3887
  const [stripeStyles, setStripeStyles] = (0, import_react10.useState)({});
3888
3888
  const [shouldSaveCard, setShouldSaveCard] = (0, import_react10.useState)(true);
@@ -3989,7 +3989,7 @@ var CreditCardForm = ({ cancel, saveCard }) => {
3989
3989
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Label, { className: "text-sm font-medium", htmlFor: "saveCard", children: "Save card for future purchases" })
3990
3990
  ] }),
3991
3991
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex w-full justify-end gap-2", children: [
3992
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3992
+ showCancel && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3993
3993
  Button,
3994
3994
  {
3995
3995
  variant: "outline",
@@ -4014,15 +4014,32 @@ var CreditCardForm = ({ cancel, saveCard }) => {
4014
4014
 
4015
4015
  // src/components/CreditCardTab/CreditCard/CreditCard.tsx
4016
4016
  var import_jsx_runtime17 = require("react/jsx-runtime");
4017
- var StripeWrapper = ({ onCancel, saveNewCard, publicKey }) => {
4017
+ var StripeWrapper = ({ onCancel, saveNewCard, publicKey, showCancel }) => {
4018
4018
  const stripePromise = (0, import_react11.useMemo)(() => (0, import_stripe_js.loadStripe)(publicKey), [publicKey]);
4019
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_stripe_js2.Elements, { stripe: stripePromise, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CreditCardForm, { cancel: onCancel, saveCard: saveNewCard }) });
4019
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_stripe_js2.Elements, { stripe: stripePromise, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CreditCardForm, { cancel: onCancel, saveCard: saveNewCard, showCancel }) });
4020
4020
  };
4021
4021
  var CreditCard = ({ newCards, setNewCards }) => {
4022
4022
  const [showForm, setShowForm] = (0, import_react11.useState)(false);
4023
4023
  const isLoggedIn = useIsLoggedIn();
4024
4024
  const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
4025
4025
  const { spreePayConfig } = useSpreePayConfig();
4026
+ const { cards, cardsIsLoading } = useCards();
4027
+ const canUseForm = isLoggedIn && Boolean(spreePayConfig?.stripePublicKey);
4028
+ const hasCards = cards.length + newCards.length > 0;
4029
+ const formVisible = canUseForm && (showForm || !hasCards && !cardsIsLoading);
4030
+ const didAutoSelect = (0, import_react11.useRef)(false);
4031
+ (0, import_react11.useEffect)(() => {
4032
+ if (!isLoggedIn) {
4033
+ didAutoSelect.current = false;
4034
+ return;
4035
+ }
4036
+ if (didAutoSelect.current || cardsIsLoading) return;
4037
+ didAutoSelect.current = true;
4038
+ const alreadySelected = selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && Boolean(selectedPaymentMethod.method);
4039
+ if (!alreadySelected && cards.length > 0) {
4040
+ setSelectedPaymentMethod({ ...selectedPaymentMethod, type: "CREDIT_CARD" /* CREDIT_CARD */, method: cards[0] });
4041
+ }
4042
+ }, [isLoggedIn, cardsIsLoading, cards, selectedPaymentMethod, setSelectedPaymentMethod]);
4026
4043
  const setCard = (card) => {
4027
4044
  const isAlreadySelected = selectedPaymentMethod?.type === "CREDIT_CARD" /* CREDIT_CARD */ && selectedPaymentMethod.method?.id === card.id;
4028
4045
  setSelectedPaymentMethod({
@@ -4055,7 +4072,7 @@ var CreditCard = ({ newCards, setNewCards }) => {
4055
4072
  };
4056
4073
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex flex-col items-baseline gap-4", children: [
4057
4074
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h3", { className: "text-[22px] leading-9 font-medium text-(--brand-primary)", children: "Your Cards" }),
4058
- !showForm && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
4075
+ !formVisible && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
4059
4076
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4060
4077
  CardsList,
4061
4078
  {
@@ -4070,13 +4087,21 @@ var CreditCard = ({ newCards, setNewCards }) => {
4070
4087
  "button",
4071
4088
  {
4072
4089
  onClick: handleAddNewCard,
4073
- disabled: !isLoggedIn || !spreePayConfig?.stripePublicKey,
4090
+ disabled: !canUseForm,
4074
4091
  className: "text-md text-(--brand-primary) hover:underline disabled:cursor-not-allowed disabled:no-underline disabled:opacity-50",
4075
4092
  children: "Add new card"
4076
4093
  }
4077
4094
  )
4078
4095
  ] }),
4079
- isLoggedIn && spreePayConfig?.stripePublicKey && showForm && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(StripeWrapper, { onCancel: handleCancel, saveNewCard, publicKey: spreePayConfig.stripePublicKey })
4096
+ formVisible && spreePayConfig?.stripePublicKey && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4097
+ StripeWrapper,
4098
+ {
4099
+ onCancel: handleCancel,
4100
+ saveNewCard,
4101
+ publicKey: spreePayConfig.stripePublicKey,
4102
+ showCancel: hasCards
4103
+ }
4104
+ )
4080
4105
  ] });
4081
4106
  };
4082
4107
 
@@ -4085,6 +4110,7 @@ var import_react16 = require("react");
4085
4110
  init_LoginStatusContext();
4086
4111
  init_SpreePayActionsContext();
4087
4112
  init_StaticConfigContext();
4113
+ init_useSlapiBalance();
4088
4114
  init_useSpreePayConfig();
4089
4115
  init_common();
4090
4116
 
@@ -5163,8 +5189,10 @@ var PointsSelector = (props) => {
5163
5189
  Slider2,
5164
5190
  {
5165
5191
  value: [splitTokens],
5166
- onValueCommit: ([v]) => handleCommit(v),
5167
- onValueChange: ([v]) => setSplitTokens(v),
5192
+ onValueChange: ([v]) => {
5193
+ setSplitTokens(v);
5194
+ handleCommit(v);
5195
+ },
5168
5196
  onPointerDown: (e) => e.stopPropagation(),
5169
5197
  min,
5170
5198
  max,
@@ -5264,8 +5292,21 @@ var Points = () => {
5264
5292
  const [usePoints, setUsePoints] = (0, import_react16.useState)(false);
5265
5293
  const [selectedPointsType, setSelectedPointsType] = (0, import_react16.useState)(null);
5266
5294
  const { setSelectedPaymentMethod, selectedPaymentMethod } = useSpreePaymentMethod();
5267
- const { spreePayConfig } = useSpreePayConfig();
5295
+ const { spreePayConfig, configIsLoading } = useSpreePayConfig();
5268
5296
  const { appProps } = useStaticConfig();
5297
+ const { balance } = useSlapiBalance();
5298
+ const { useWeb3Points } = useSpreePayEnv();
5299
+ const pointsDisabled = !isLoggedIn || !spreePayConfig?.creditCard.enabled || !spreePayConfig?.creditCard.points || appProps.disabledPoints;
5300
+ const [didInit, setDidInit] = (0, import_react16.useState)(false);
5301
+ if (!isLoggedIn) {
5302
+ if (didInit) setDidInit(false);
5303
+ } else if (!didInit && balance !== void 0 && !configIsLoading) {
5304
+ setDidInit(true);
5305
+ if (!useWeb3Points && !pointsDisabled && balance.availablePoints > 0) {
5306
+ setUsePoints(true);
5307
+ setSelectedPointsType("air");
5308
+ }
5309
+ }
5269
5310
  const handleTogglePoints = (enabled) => {
5270
5311
  setUsePoints(enabled);
5271
5312
  if (!enabled) {
@@ -5280,7 +5321,7 @@ var Points = () => {
5280
5321
  value: usePoints,
5281
5322
  onChange: handleTogglePoints,
5282
5323
  message: spreePayConfig?.creditCard.pointsInfoMessage,
5283
- disabled: !isLoggedIn || !spreePayConfig?.creditCard.enabled || !spreePayConfig?.creditCard.points || appProps.disabledPoints
5324
+ disabled: pointsDisabled
5284
5325
  }
5285
5326
  ),
5286
5327
  usePoints && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
@@ -5390,12 +5431,13 @@ var TabButton = ({ isDisabled = false, isActive, children, onClick }) => {
5390
5431
  };
5391
5432
  var TabButtons = (props) => {
5392
5433
  const { value, onChange } = props;
5393
- const { spreePayConfig, configIsLoading } = useSpreePayConfig();
5434
+ const { spreePayConfig, configIsLoading, configError } = useSpreePayConfig();
5394
5435
  const handleChange = (type) => () => {
5395
5436
  if (value !== type) {
5396
5437
  onChange({ type, method: null });
5397
5438
  }
5398
5439
  };
5440
+ if (configError) return null;
5399
5441
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex w-full gap-4 overflow-x-auto px-5 py-2 md:px-7", children: [
5400
5442
  configIsLoading && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-[74px] w-[180px] animate-pulse rounded-md bg-(--s-primary)" }),
5401
5443
  spreePayConfig?.creditCard.enabled && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(TabButton, { onClick: handleChange("CREDIT_CARD" /* CREDIT_CARD */), isActive: value === "CREDIT_CARD" /* CREDIT_CARD */, children: [
@@ -5443,6 +5485,8 @@ var TabButtons = (props) => {
5443
5485
  // src/SpreePayContent.tsx
5444
5486
  init_LoginStatusContext();
5445
5487
  init_SpreePayActionsContext();
5488
+ init_useSpreePayConfig();
5489
+ init_utils();
5446
5490
  var import_jsx_runtime46 = require("react/jsx-runtime");
5447
5491
  var CryptoTab2 = (0, import_react22.lazy)(() => Promise.resolve().then(() => (init_CryptoTab2(), CryptoTab_exports)).then((module2) => ({ default: module2.CryptoTab })));
5448
5492
  var CryptoComTab2 = (0, import_react22.lazy)(
@@ -5455,22 +5499,36 @@ var TabLoadingFallback = () => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("di
5455
5499
  var SpreePayContent = () => {
5456
5500
  const isLoggedIn = useIsLoggedIn();
5457
5501
  const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
5502
+ const { configError } = useSpreePayConfig();
5458
5503
  (0, import_react22.useEffect)(() => {
5459
5504
  if (!isLoggedIn) {
5460
5505
  setSelectedPaymentMethod({ type: "CREDIT_CARD" /* CREDIT_CARD */, method: null });
5461
5506
  }
5462
5507
  }, [isLoggedIn, setSelectedPaymentMethod]);
5463
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "w-full overflow-hidden rounded-3xl border border-(--border-component-specific-card) bg-(--surface-component-specific-card-default-card) shadow-[0_6.25px_25px_0_var(--shadow-component-specific-card)]", children: [
5464
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex w-full flex-col gap-2 border-b border-b-(--border-component-specific-card) pt-5 pb-3 md:pt-6 md:pb-5", children: [
5465
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h2", { className: "px-5 text-[28px] leading-8 font-medium text-(--brand-primary) md:px-7", children: "Choose a payment method" }),
5466
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(TabButtons, { value: selectedPaymentMethod.type, onChange: setSelectedPaymentMethod })
5467
- ] }),
5468
- selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(CreditCardTab, {}),
5469
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_react22.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(TabLoadingFallback, {}), children: [
5470
- selectedPaymentMethod.type === "CRYPTO" /* CRYPTO */ && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(CryptoTab2, {}),
5471
- selectedPaymentMethod.type === "CDC" /* CDC */ && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(CryptoComTab2, {})
5472
- ] })
5473
- ] });
5508
+ return (
5509
+ // Config failed: inert disables the whole widget and drops it from tab order + a11y.
5510
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
5511
+ "div",
5512
+ {
5513
+ inert: !!configError,
5514
+ className: cn(
5515
+ "w-full overflow-hidden rounded-3xl border border-(--border-component-specific-card) bg-(--surface-component-specific-card-default-card) shadow-[0_6.25px_25px_0_var(--shadow-component-specific-card)]",
5516
+ configError && "opacity-75"
5517
+ ),
5518
+ children: [
5519
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex w-full flex-col gap-2 border-b border-b-(--border-component-specific-card) pt-5 pb-3 md:pt-6 md:pb-5", children: [
5520
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h2", { className: "px-5 text-[28px] leading-8 font-medium text-(--brand-primary) md:px-7", children: "Choose a payment method" }),
5521
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(TabButtons, { value: selectedPaymentMethod.type, onChange: setSelectedPaymentMethod })
5522
+ ] }),
5523
+ selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(CreditCardTab, {}),
5524
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_react22.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(TabLoadingFallback, {}), children: [
5525
+ selectedPaymentMethod.type === "CRYPTO" /* CRYPTO */ && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(CryptoTab2, {}),
5526
+ selectedPaymentMethod.type === "CDC" /* CDC */ && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(CryptoComTab2, {})
5527
+ ] })
5528
+ ]
5529
+ }
5530
+ )
5531
+ );
5474
5532
  };
5475
5533
 
5476
5534
  // src/components/ErrorBoundary.tsx
package/build/index.css CHANGED
@@ -926,6 +926,9 @@
926
926
  .sl-spreepay .opacity-70 {
927
927
  opacity: 70%;
928
928
  }
929
+ .sl-spreepay .opacity-75 {
930
+ opacity: 75%;
931
+ }
929
932
  .sl-spreepay .shadow-\(--primary\)\/20 {
930
933
  --tw-shadow-alpha: 20%;
931
934
  --tw-shadow: var(--primary);
package/build/index.js CHANGED
@@ -8,10 +8,10 @@ import {
8
8
  getSplitAmount,
9
9
  getTransactionFee,
10
10
  useSlapiBalance
11
- } from "./chunk-H7S3CTS3.js";
11
+ } from "./chunk-UVD3GGPC.js";
12
12
  import {
13
13
  Iframe3ds
14
- } from "./chunk-QJCZPYQC.js";
14
+ } from "./chunk-OTFCW74L.js";
15
15
  import {
16
16
  InfoBanner,
17
17
  LogLevel,
@@ -43,17 +43,17 @@ import {
43
43
  useSpreePayRegister,
44
44
  useSpreePaymentMethod,
45
45
  useStaticConfig
46
- } from "./chunk-RZ43EXC2.js";
46
+ } from "./chunk-WYLYH7AK.js";
47
47
 
48
48
  // src/SpreePay.tsx
49
- import { useCallback as useCallback8, useEffect as useEffect8, useMemo as useMemo9, useState as useState12 } from "react";
49
+ import { useCallback as useCallback8, useEffect as useEffect9, useMemo as useMemo9, useState as useState12 } from "react";
50
50
  import { SWRConfig } from "swr";
51
51
 
52
52
  // src/SpreePayContent.tsx
53
- import { Suspense, lazy, useEffect as useEffect6 } from "react";
53
+ import { Suspense, lazy, useEffect as useEffect7 } from "react";
54
54
 
55
55
  // src/components/CreditCardTab/CreditCardTab.tsx
56
- import { useCallback as useCallback6, useEffect as useEffect5, useState as useState10 } from "react";
56
+ import { useCallback as useCallback6, useEffect as useEffect6, useState as useState10 } from "react";
57
57
 
58
58
  // src/hooks/payments/useCardPayment.ts
59
59
  var cardPaymentLogger = logger.child("card-payment");
@@ -567,7 +567,7 @@ var useCards = () => {
567
567
  };
568
568
 
569
569
  // src/components/CreditCardTab/CreditCard/CreditCard.tsx
570
- import { useCallback as useCallback2, useMemo as useMemo3, useState as useState3 } from "react";
570
+ import { useCallback as useCallback2, useEffect, useMemo as useMemo3, useRef, useState as useState3 } from "react";
571
571
  import { Elements } from "@stripe/react-stripe-js";
572
572
  import { loadStripe } from "@stripe/stripe-js";
573
573
 
@@ -744,7 +744,7 @@ var stripeElementClasses = {
744
744
  invalid: "focus-visible:ring-(--negative)",
745
745
  focus: "border-(--b-tertiary) ring-(--b-tertiary)/50 ring-2"
746
746
  };
747
- var CreditCardForm = ({ cancel, saveCard }) => {
747
+ var CreditCardForm = ({ cancel, saveCard, showCancel }) => {
748
748
  const [cardError, setCardError] = useState2(void 0);
749
749
  const [stripeStyles, setStripeStyles] = useState2({});
750
750
  const [shouldSaveCard, setShouldSaveCard] = useState2(true);
@@ -851,7 +851,7 @@ var CreditCardForm = ({ cancel, saveCard }) => {
851
851
  /* @__PURE__ */ jsx4(Label, { className: "text-sm font-medium", htmlFor: "saveCard", children: "Save card for future purchases" })
852
852
  ] }),
853
853
  /* @__PURE__ */ jsxs2("div", { className: "flex w-full justify-end gap-2", children: [
854
- /* @__PURE__ */ jsx4(
854
+ showCancel && /* @__PURE__ */ jsx4(
855
855
  Button,
856
856
  {
857
857
  variant: "outline",
@@ -876,15 +876,32 @@ var CreditCardForm = ({ cancel, saveCard }) => {
876
876
 
877
877
  // src/components/CreditCardTab/CreditCard/CreditCard.tsx
878
878
  import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
879
- var StripeWrapper = ({ onCancel, saveNewCard, publicKey }) => {
879
+ var StripeWrapper = ({ onCancel, saveNewCard, publicKey, showCancel }) => {
880
880
  const stripePromise = useMemo3(() => loadStripe(publicKey), [publicKey]);
881
- return /* @__PURE__ */ jsx5(Elements, { stripe: stripePromise, children: /* @__PURE__ */ jsx5(CreditCardForm, { cancel: onCancel, saveCard: saveNewCard }) });
881
+ return /* @__PURE__ */ jsx5(Elements, { stripe: stripePromise, children: /* @__PURE__ */ jsx5(CreditCardForm, { cancel: onCancel, saveCard: saveNewCard, showCancel }) });
882
882
  };
883
883
  var CreditCard = ({ newCards, setNewCards }) => {
884
884
  const [showForm, setShowForm] = useState3(false);
885
885
  const isLoggedIn = useIsLoggedIn();
886
886
  const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
887
887
  const { spreePayConfig } = useSpreePayConfig();
888
+ const { cards, cardsIsLoading } = useCards();
889
+ const canUseForm = isLoggedIn && Boolean(spreePayConfig?.stripePublicKey);
890
+ const hasCards = cards.length + newCards.length > 0;
891
+ const formVisible = canUseForm && (showForm || !hasCards && !cardsIsLoading);
892
+ const didAutoSelect = useRef(false);
893
+ useEffect(() => {
894
+ if (!isLoggedIn) {
895
+ didAutoSelect.current = false;
896
+ return;
897
+ }
898
+ if (didAutoSelect.current || cardsIsLoading) return;
899
+ didAutoSelect.current = true;
900
+ const alreadySelected = selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && Boolean(selectedPaymentMethod.method);
901
+ if (!alreadySelected && cards.length > 0) {
902
+ setSelectedPaymentMethod({ ...selectedPaymentMethod, type: "CREDIT_CARD" /* CREDIT_CARD */, method: cards[0] });
903
+ }
904
+ }, [isLoggedIn, cardsIsLoading, cards, selectedPaymentMethod, setSelectedPaymentMethod]);
888
905
  const setCard = (card) => {
889
906
  const isAlreadySelected = selectedPaymentMethod?.type === "CREDIT_CARD" /* CREDIT_CARD */ && selectedPaymentMethod.method?.id === card.id;
890
907
  setSelectedPaymentMethod({
@@ -917,7 +934,7 @@ var CreditCard = ({ newCards, setNewCards }) => {
917
934
  };
918
935
  return /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-baseline gap-4", children: [
919
936
  /* @__PURE__ */ jsx5("h3", { className: "text-[22px] leading-9 font-medium text-(--brand-primary)", children: "Your Cards" }),
920
- !showForm && /* @__PURE__ */ jsxs3(Fragment2, { children: [
937
+ !formVisible && /* @__PURE__ */ jsxs3(Fragment2, { children: [
921
938
  /* @__PURE__ */ jsx5(
922
939
  CardsList,
923
940
  {
@@ -932,13 +949,21 @@ var CreditCard = ({ newCards, setNewCards }) => {
932
949
  "button",
933
950
  {
934
951
  onClick: handleAddNewCard,
935
- disabled: !isLoggedIn || !spreePayConfig?.stripePublicKey,
952
+ disabled: !canUseForm,
936
953
  className: "text-md text-(--brand-primary) hover:underline disabled:cursor-not-allowed disabled:no-underline disabled:opacity-50",
937
954
  children: "Add new card"
938
955
  }
939
956
  )
940
957
  ] }),
941
- isLoggedIn && spreePayConfig?.stripePublicKey && showForm && /* @__PURE__ */ jsx5(StripeWrapper, { onCancel: handleCancel, saveNewCard, publicKey: spreePayConfig.stripePublicKey })
958
+ formVisible && spreePayConfig?.stripePublicKey && /* @__PURE__ */ jsx5(
959
+ StripeWrapper,
960
+ {
961
+ onCancel: handleCancel,
962
+ saveNewCard,
963
+ publicKey: spreePayConfig.stripePublicKey,
964
+ showCancel: hasCards
965
+ }
966
+ )
942
967
  ] });
943
968
  };
944
969
 
@@ -946,7 +971,7 @@ var CreditCard = ({ newCards, setNewCards }) => {
946
971
  import { useState as useState9 } from "react";
947
972
 
948
973
  // src/components/CreditCardTab/Points/SplitBlock.tsx
949
- import { useCallback as useCallback5, useEffect as useEffect4, useRef as useRef5, useState as useState8 } from "react";
974
+ import { useCallback as useCallback5, useEffect as useEffect5, useRef as useRef6, useState as useState8 } from "react";
950
975
  import { BUILD_ENV as BUILD_ENV2 } from "@mocanetwork/airkit";
951
976
 
952
977
  // src/components/CreditCardTab/Points/PointsSelector.tsx
@@ -2004,8 +2029,10 @@ var PointsSelector = (props) => {
2004
2029
  Slider2,
2005
2030
  {
2006
2031
  value: [splitTokens],
2007
- onValueCommit: ([v]) => handleCommit(v),
2008
- onValueChange: ([v]) => setSplitTokens(v),
2032
+ onValueChange: ([v]) => {
2033
+ setSplitTokens(v);
2034
+ handleCommit(v);
2035
+ },
2009
2036
  onPointerDown: (e) => e.stopPropagation(),
2010
2037
  min,
2011
2038
  max,
@@ -2047,7 +2074,7 @@ var SplitBlock = (props) => {
2047
2074
  const { useWeb3Points, environment } = useSpreePayEnv();
2048
2075
  const hasForeignCurrency = !!(currencyCode && exchangeRate && foreignCurrencyAmount);
2049
2076
  const formatPointsValue = (usd) => hasForeignCurrency ? formatCurrency(usd / exchangeRate, currencyCode) : formatCurrency(usd);
2050
- const prevPointsChainRef = useRef5(spreePayConfig?.pointsChain);
2077
+ const prevPointsChainRef = useRef6(spreePayConfig?.pointsChain);
2051
2078
  const initWallet = useCallback5(
2052
2079
  async (pointsChain) => {
2053
2080
  if (!pointsChain) return;
@@ -2071,7 +2098,7 @@ var SplitBlock = (props) => {
2071
2098
  },
2072
2099
  [onToggle, environment]
2073
2100
  );
2074
- useEffect4(() => {
2101
+ useEffect5(() => {
2075
2102
  if (!useWeb3Points) return;
2076
2103
  const pointsChainChanged = prevPointsChainRef.current !== spreePayConfig?.pointsChain;
2077
2104
  prevPointsChainRef.current = spreePayConfig?.pointsChain;
@@ -2105,8 +2132,21 @@ var Points = () => {
2105
2132
  const [usePoints, setUsePoints] = useState9(false);
2106
2133
  const [selectedPointsType, setSelectedPointsType] = useState9(null);
2107
2134
  const { setSelectedPaymentMethod, selectedPaymentMethod } = useSpreePaymentMethod();
2108
- const { spreePayConfig } = useSpreePayConfig();
2135
+ const { spreePayConfig, configIsLoading } = useSpreePayConfig();
2109
2136
  const { appProps } = useStaticConfig();
2137
+ const { balance } = useSlapiBalance();
2138
+ const { useWeb3Points } = useSpreePayEnv();
2139
+ const pointsDisabled = !isLoggedIn || !spreePayConfig?.creditCard.enabled || !spreePayConfig?.creditCard.points || appProps.disabledPoints;
2140
+ const [didInit, setDidInit] = useState9(false);
2141
+ if (!isLoggedIn) {
2142
+ if (didInit) setDidInit(false);
2143
+ } else if (!didInit && balance !== void 0 && !configIsLoading) {
2144
+ setDidInit(true);
2145
+ if (!useWeb3Points && !pointsDisabled && balance.availablePoints > 0) {
2146
+ setUsePoints(true);
2147
+ setSelectedPointsType("air");
2148
+ }
2149
+ }
2110
2150
  const handleTogglePoints = (enabled) => {
2111
2151
  setUsePoints(enabled);
2112
2152
  if (!enabled) {
@@ -2121,7 +2161,7 @@ var Points = () => {
2121
2161
  value: usePoints,
2122
2162
  onChange: handleTogglePoints,
2123
2163
  message: spreePayConfig?.creditCard.pointsInfoMessage,
2124
- disabled: !isLoggedIn || !spreePayConfig?.creditCard.enabled || !spreePayConfig?.creditCard.points || appProps.disabledPoints
2164
+ disabled: pointsDisabled
2125
2165
  }
2126
2166
  ),
2127
2167
  usePoints && /* @__PURE__ */ jsx15(
@@ -2199,7 +2239,7 @@ var CreditCardTab = () => {
2199
2239
  mutateBalance
2200
2240
  ]
2201
2241
  );
2202
- useEffect5(() => {
2242
+ useEffect6(() => {
2203
2243
  register(handlePay);
2204
2244
  }, [register, handlePay]);
2205
2245
  return /* @__PURE__ */ jsxs9("div", { children: [
@@ -2229,12 +2269,13 @@ var TabButton = ({ isDisabled = false, isActive, children, onClick }) => {
2229
2269
  };
2230
2270
  var TabButtons = (props) => {
2231
2271
  const { value, onChange } = props;
2232
- const { spreePayConfig, configIsLoading } = useSpreePayConfig();
2272
+ const { spreePayConfig, configIsLoading, configError } = useSpreePayConfig();
2233
2273
  const handleChange = (type) => () => {
2234
2274
  if (value !== type) {
2235
2275
  onChange({ type, method: null });
2236
2276
  }
2237
2277
  };
2278
+ if (configError) return null;
2238
2279
  return /* @__PURE__ */ jsxs10("div", { className: "flex w-full gap-4 overflow-x-auto px-5 py-2 md:px-7", children: [
2239
2280
  configIsLoading && /* @__PURE__ */ jsx17("div", { className: "h-[74px] w-[180px] animate-pulse rounded-md bg-(--s-primary)" }),
2240
2281
  spreePayConfig?.creditCard.enabled && /* @__PURE__ */ jsxs10(TabButton, { onClick: handleChange("CREDIT_CARD" /* CREDIT_CARD */), isActive: value === "CREDIT_CARD" /* CREDIT_CARD */, children: [
@@ -2281,9 +2322,9 @@ var TabButtons = (props) => {
2281
2322
 
2282
2323
  // src/SpreePayContent.tsx
2283
2324
  import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
2284
- var CryptoTab = lazy(() => import("./CryptoTab-G55XLBX2.js").then((module) => ({ default: module.CryptoTab })));
2325
+ var CryptoTab = lazy(() => import("./CryptoTab-ROWYOLOL.js").then((module) => ({ default: module.CryptoTab })));
2285
2326
  var CryptoComTab = lazy(
2286
- () => import("./CryptoComTab-WXKBRJF3.js").then((module) => ({ default: module.CryptoComTab }))
2327
+ () => import("./CryptoComTab-3MCYJORT.js").then((module) => ({ default: module.CryptoComTab }))
2287
2328
  );
2288
2329
  var TabLoadingFallback = () => /* @__PURE__ */ jsx18("div", { className: "flex items-center justify-center px-5 py-8 md:px-7", children: /* @__PURE__ */ jsxs11("div", { className: "flex flex-col items-center gap-3", children: [
2289
2330
  /* @__PURE__ */ jsx18("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-(--border-component-specific-card) border-t-(--brand-primary)" }),
@@ -2292,22 +2333,36 @@ var TabLoadingFallback = () => /* @__PURE__ */ jsx18("div", { className: "flex i
2292
2333
  var SpreePayContent = () => {
2293
2334
  const isLoggedIn = useIsLoggedIn();
2294
2335
  const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
2295
- useEffect6(() => {
2336
+ const { configError } = useSpreePayConfig();
2337
+ useEffect7(() => {
2296
2338
  if (!isLoggedIn) {
2297
2339
  setSelectedPaymentMethod({ type: "CREDIT_CARD" /* CREDIT_CARD */, method: null });
2298
2340
  }
2299
2341
  }, [isLoggedIn, setSelectedPaymentMethod]);
2300
- return /* @__PURE__ */ jsxs11("div", { className: "w-full overflow-hidden rounded-3xl border border-(--border-component-specific-card) bg-(--surface-component-specific-card-default-card) shadow-[0_6.25px_25px_0_var(--shadow-component-specific-card)]", children: [
2301
- /* @__PURE__ */ jsxs11("div", { className: "flex w-full flex-col gap-2 border-b border-b-(--border-component-specific-card) pt-5 pb-3 md:pt-6 md:pb-5", children: [
2302
- /* @__PURE__ */ jsx18("h2", { className: "px-5 text-[28px] leading-8 font-medium text-(--brand-primary) md:px-7", children: "Choose a payment method" }),
2303
- /* @__PURE__ */ jsx18(TabButtons, { value: selectedPaymentMethod.type, onChange: setSelectedPaymentMethod })
2304
- ] }),
2305
- selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && /* @__PURE__ */ jsx18(CreditCardTab, {}),
2306
- /* @__PURE__ */ jsxs11(Suspense, { fallback: /* @__PURE__ */ jsx18(TabLoadingFallback, {}), children: [
2307
- selectedPaymentMethod.type === "CRYPTO" /* CRYPTO */ && /* @__PURE__ */ jsx18(CryptoTab, {}),
2308
- selectedPaymentMethod.type === "CDC" /* CDC */ && /* @__PURE__ */ jsx18(CryptoComTab, {})
2309
- ] })
2310
- ] });
2342
+ return (
2343
+ // Config failed: inert disables the whole widget and drops it from tab order + a11y.
2344
+ /* @__PURE__ */ jsxs11(
2345
+ "div",
2346
+ {
2347
+ inert: !!configError,
2348
+ className: cn(
2349
+ "w-full overflow-hidden rounded-3xl border border-(--border-component-specific-card) bg-(--surface-component-specific-card-default-card) shadow-[0_6.25px_25px_0_var(--shadow-component-specific-card)]",
2350
+ configError && "opacity-75"
2351
+ ),
2352
+ children: [
2353
+ /* @__PURE__ */ jsxs11("div", { className: "flex w-full flex-col gap-2 border-b border-b-(--border-component-specific-card) pt-5 pb-3 md:pt-6 md:pb-5", children: [
2354
+ /* @__PURE__ */ jsx18("h2", { className: "px-5 text-[28px] leading-8 font-medium text-(--brand-primary) md:px-7", children: "Choose a payment method" }),
2355
+ /* @__PURE__ */ jsx18(TabButtons, { value: selectedPaymentMethod.type, onChange: setSelectedPaymentMethod })
2356
+ ] }),
2357
+ selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && /* @__PURE__ */ jsx18(CreditCardTab, {}),
2358
+ /* @__PURE__ */ jsxs11(Suspense, { fallback: /* @__PURE__ */ jsx18(TabLoadingFallback, {}), children: [
2359
+ selectedPaymentMethod.type === "CRYPTO" /* CRYPTO */ && /* @__PURE__ */ jsx18(CryptoTab, {}),
2360
+ selectedPaymentMethod.type === "CDC" /* CDC */ && /* @__PURE__ */ jsx18(CryptoComTab, {})
2361
+ ] })
2362
+ ]
2363
+ }
2364
+ )
2365
+ );
2311
2366
  };
2312
2367
 
2313
2368
  // src/components/ErrorBoundary.tsx
@@ -2359,16 +2414,16 @@ var ErrorBoundary = class extends Component {
2359
2414
  };
2360
2415
 
2361
2416
  // src/hooks/useKeycloakSSO.ts
2362
- import { useCallback as useCallback7, useEffect as useEffect7, useRef as useRef6, useState as useState11 } from "react";
2417
+ import { useCallback as useCallback7, useEffect as useEffect8, useRef as useRef7, useState as useState11 } from "react";
2363
2418
  import Keycloak from "keycloak-js";
2364
2419
  var refreshAheadSeconds = 60;
2365
2420
  var keycloakLogger = logger.child("keycloak");
2366
2421
  function useKeycloakSSO(config) {
2367
2422
  const { url, realm, clientId, ssoPageURI, enabled } = config;
2368
- const initRef = useRef6(false);
2369
- const kcRef = useRef6(null);
2370
- const refreshTimerRef = useRef6(null);
2371
- const scheduleRefreshRef = useRef6(() => {
2423
+ const initRef = useRef7(false);
2424
+ const kcRef = useRef7(null);
2425
+ const refreshTimerRef = useRef7(null);
2426
+ const scheduleRefreshRef = useRef7(() => {
2372
2427
  });
2373
2428
  const [error, setError] = useState11(null);
2374
2429
  const [isChecking, setIsChecking] = useState11(enabled);
@@ -2397,10 +2452,10 @@ function useKeycloakSSO(config) {
2397
2452
  });
2398
2453
  }, delayMs);
2399
2454
  }, []);
2400
- useEffect7(() => {
2455
+ useEffect8(() => {
2401
2456
  scheduleRefreshRef.current = scheduleRefresh;
2402
2457
  }, [scheduleRefresh]);
2403
- useEffect7(() => {
2458
+ useEffect8(() => {
2404
2459
  if (initRef.current || !enabled) return;
2405
2460
  initRef.current = true;
2406
2461
  const kc = new Keycloak({ url, realm, clientId });
@@ -2455,7 +2510,7 @@ var SpreePayInner = () => {
2455
2510
  setPortalEl(el ?? null);
2456
2511
  }, []);
2457
2512
  const { environment, tenantId, keycloakClientId, accessToken: envAccessToken, ssoPageURI } = useSpreePayEnv();
2458
- useEffect8(() => {
2513
+ useEffect9(() => {
2459
2514
  configureLogger({ environment });
2460
2515
  logger.logVersion();
2461
2516
  }, [environment]);
@@ -2509,9 +2564,9 @@ var SpreePay = (props) => {
2509
2564
  };
2510
2565
 
2511
2566
  // src/hooks/useCapture3DS.ts
2512
- import { useEffect as useEffect9 } from "react";
2567
+ import { useEffect as useEffect10 } from "react";
2513
2568
  var useCapture3DS = ({ paymentIntent }) => {
2514
- useEffect9(() => {
2569
+ useEffect10(() => {
2515
2570
  if (typeof window !== "undefined" && window.parent && paymentIntent) {
2516
2571
  window.parent.SP_EVENT_BUS?.emit("paymentIntent", { paymentIntent });
2517
2572
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superlogic/spree-pay",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "Spree-pay React component and utilities",
5
5
  "private": false,
6
6
  "type": "module",