@superlogic/spree-pay 0.1.16 → 0.1.18

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.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/SpreePay.tsx
2
- import { useLayoutEffect, useMemo as useMemo2, useRef as useRef3, useState as useState7 } from "react";
3
- import NiceModal6 from "@ebay/nice-modal-react";
2
+ import { useLayoutEffect as useLayoutEffect3, useMemo as useMemo8, useRef as useRef7, useState as useState13 } from "react";
3
+ import NiceModal7 from "@ebay/nice-modal-react";
4
4
  import { SWRConfig } from "swr";
5
5
 
6
6
  // src/context/SpreePayActionsContext.tsx
@@ -18,6 +18,15 @@ var PaymentError = class extends Error {
18
18
  }
19
19
  };
20
20
 
21
+ // src/types/payments.ts
22
+ var PaymentType = /* @__PURE__ */ ((PaymentType2) => {
23
+ PaymentType2["CREDIT_CARD"] = "CREDIT_CARD";
24
+ PaymentType2["CRYPTO"] = "CRYPTO";
25
+ PaymentType2["SPLIT"] = "SPLIT";
26
+ PaymentType2["POINTS"] = "POINTS";
27
+ return PaymentType2;
28
+ })(PaymentType || {});
29
+
21
30
  // src/context/SpreePayActionsContext.tsx
22
31
  import { jsx } from "react/jsx-runtime";
23
32
  var SpreePayActionsContext = createContext(void 0);
@@ -84,6 +93,86 @@ var useSpreePayRegister = () => {
84
93
  return { register: ctx.register };
85
94
  };
86
95
 
96
+ // src/context/StaticConfigContext.tsx
97
+ import { createContext as createContext2, useContext as useContext2, useEffect, useMemo, useState as useState2 } from "react";
98
+ import { jsx as jsx2 } from "react/jsx-runtime";
99
+ var CONFIG = {
100
+ dev: {
101
+ bookit: {
102
+ slapiUrl: "https://slapi.dev.superlogic.com",
103
+ keycloakUrl: "https://auth.dev.join.bookit.com",
104
+ keycloakClientId: "oneof-next",
105
+ pointsConversionRatio: 100,
106
+ pointsTitle: "AIR SP"
107
+ },
108
+ moca: {
109
+ slapiUrl: "https://slapi.dev.air.shop",
110
+ keycloakUrl: "https://login.dev.air.shop",
111
+ keycloakClientId: "oneof-next",
112
+ pointsConversionRatio: 100,
113
+ pointsTitle: "AIR SP"
114
+ }
115
+ },
116
+ stg: {
117
+ bookit: {
118
+ slapiUrl: "https://slapi.stg.superlogic.com",
119
+ keycloakUrl: "https://auth.stg.join.bookit.com",
120
+ keycloakClientId: "oneof-next",
121
+ pointsConversionRatio: 100,
122
+ pointsTitle: "AIR SP"
123
+ },
124
+ moca: {
125
+ slapiUrl: "https://slapi.stg.air.shop",
126
+ keycloakUrl: "https://login.stg.air.shop",
127
+ keycloakClientId: "oneof-next",
128
+ pointsConversionRatio: 100,
129
+ pointsTitle: "AIR SP"
130
+ }
131
+ },
132
+ prod: {
133
+ bookit: {
134
+ slapiUrl: "https://slapi.superlogic.com",
135
+ keycloakUrl: "https://auth.join.bookit.com",
136
+ keycloakClientId: "oneof-next",
137
+ pointsConversionRatio: 100,
138
+ pointsTitle: "AIR SP"
139
+ },
140
+ moca: {
141
+ slapiUrl: "https://slapi.air.shop",
142
+ keycloakUrl: "https://login.air.shop",
143
+ keycloakClientId: "oneof-next",
144
+ pointsConversionRatio: 100,
145
+ pointsTitle: "AIR SP"
146
+ }
147
+ }
148
+ };
149
+ var StaticConfigContext = createContext2(null);
150
+ var StaticConfigProvider = ({ children, props }) => {
151
+ const { env } = useSpreePayEnv();
152
+ const [appProps, setAppProps] = useState2(props);
153
+ useEffect(() => {
154
+ setAppProps(props);
155
+ }, [props]);
156
+ const staticConfig = useMemo(() => {
157
+ const envConfig = CONFIG[env.environment];
158
+ const appKey = env.tenantId in envConfig ? env.tenantId : "moca";
159
+ return envConfig[appKey];
160
+ }, [env.environment, env.tenantId]);
161
+ return /* @__PURE__ */ jsx2(StaticConfigContext.Provider, { value: { staticConfig, appProps }, children });
162
+ };
163
+ var useStaticConfig = () => {
164
+ const ctx = useContext2(StaticConfigContext);
165
+ if (!ctx) throw new Error("useStaticConfig must be used within StaticConfigProvider");
166
+ return ctx;
167
+ };
168
+
169
+ // src/hooks/useSpreePayConfig.ts
170
+ import useSWR from "swr";
171
+ var useSpreePayConfig = () => {
172
+ const { data, isLoading } = useSWR("/v1/tenants/configs/spree-pay");
173
+ return { spreePayConfig: data, configIsLoading: isLoading };
174
+ };
175
+
87
176
  // src/lib/utils.ts
88
177
  import { clsx } from "clsx";
89
178
  import { twMerge } from "tailwind-merge";
@@ -92,7 +181,7 @@ function cn(...inputs) {
92
181
  }
93
182
 
94
183
  // src/ui/spinner.tsx
95
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
184
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
96
185
  var Spinner = (props) => {
97
186
  const { size = "md", className } = props;
98
187
  const sizeClasses = {
@@ -112,7 +201,7 @@ var Spinner = (props) => {
112
201
  width: "24",
113
202
  height: "24",
114
203
  children: [
115
- /* @__PURE__ */ jsx2(
204
+ /* @__PURE__ */ jsx3(
116
205
  "path",
117
206
  {
118
207
  d: "M32 3C35.8083 3 39.5794 3.75011 43.0978 5.20749C46.6163 6.66488 49.8132 8.80101 52.5061 11.4939C55.199 14.1868 57.3351 17.3837 58.7925 20.9022C60.2499 24.4206 61 28.1917 61 32C61 35.8083 60.2499 39.5794 58.7925 43.0978C57.3351 46.6163 55.199 49.8132 52.5061 52.5061C49.8132 55.199 46.6163 57.3351 43.0978 58.7925C39.5794 60.2499 35.8083 61 32 61C28.1917 61 24.4206 60.2499 20.9022 58.7925C17.3837 57.3351 14.1868 55.199 11.4939 52.5061C8.801 49.8132 6.66487 46.6163 5.20749 43.0978C3.7501 39.5794 3 35.8083 3 32C3 28.1917 3.75011 24.4206 5.2075 20.9022C6.66489 17.3837 8.80101 14.1868 11.4939 11.4939C14.1868 8.80099 17.3838 6.66487 20.9022 5.20749C24.4206 3.7501 28.1917 3 32 3L32 3Z",
@@ -122,7 +211,7 @@ var Spinner = (props) => {
122
211
  strokeLinejoin: "round"
123
212
  }
124
213
  ),
125
- /* @__PURE__ */ jsx2(
214
+ /* @__PURE__ */ jsx3(
126
215
  "path",
127
216
  {
128
217
  d: "M32 3C36.5778 3 41.0906 4.08374 45.1692 6.16256C49.2477 8.24138 52.7762 11.2562 55.466 14.9605C58.1558 18.6647 59.9304 22.9531 60.6448 27.4748C61.3591 31.9965 60.9928 36.6232 59.5759 40.9762",
@@ -150,8 +239,9 @@ var formatUSD = (amount, currency = "USD") => {
150
239
  };
151
240
  var formatPoints = (amount, pointsTitle = "Pts") => {
152
241
  const formattedAmount = new Intl.NumberFormat("en-US", {
242
+ notation: "compact",
153
243
  style: "decimal",
154
- maximumFractionDigits: 5,
244
+ maximumFractionDigits: 1,
155
245
  minimumFractionDigits: 0
156
246
  }).format(amount);
157
247
  return `${formattedAmount} ${pointsTitle}`;
@@ -165,45 +255,85 @@ var formatCoin = (amount, currency = "USDC") => {
165
255
  return `${formattedAmount} ${currency}`;
166
256
  };
167
257
 
258
+ // src/utils/split.ts
259
+ var getSplitAmount = (amount, splitTokens, pointsConversionRatio) => {
260
+ if (!Number.isFinite(amount) || !Number.isFinite(splitTokens) || !Number.isFinite(pointsConversionRatio)) {
261
+ return amount;
262
+ }
263
+ if (pointsConversionRatio <= 0) return amount;
264
+ const usdCoveredByPoints = splitTokens / pointsConversionRatio;
265
+ const remaining = amount - usdCoveredByPoints;
266
+ return Math.max(0, parseFloat(remaining.toFixed(2)));
267
+ };
268
+
269
+ // src/utils/transactionFee.ts
270
+ var getTransactionFee = (amount = 0, transactionFeePercentage) => {
271
+ if (!Number.isFinite(amount) || amount <= 0) return 0;
272
+ if (!Number.isFinite(transactionFeePercentage) || !transactionFeePercentage || transactionFeePercentage <= 0) {
273
+ return 0;
274
+ }
275
+ const fee = amount * transactionFeePercentage;
276
+ return Math.round((fee + Number.EPSILON) * 100) / 100;
277
+ };
278
+
168
279
  // src/components/CheckoutButton.tsx
169
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
170
- var CheckoutButton = ({ isLoggedIn, isProcessing, amount, onCheckout }) => {
280
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
281
+ var CheckoutButton = ({ isLoggedIn }) => {
282
+ const { staticConfig, appProps } = useStaticConfig();
283
+ const { amount, onProcess, isProcessing, transactionFeePercentage } = appProps;
284
+ const { spreePayConfig } = useSpreePayConfig();
285
+ const { pointsTitle, pointsConversionRatio } = staticConfig;
171
286
  const { selectedPaymentMethod, isInternalProcessing } = useSpreePaymentMethod();
172
- const isDisabled = !amount || !selectedPaymentMethod.method || !!isProcessing || isInternalProcessing || !isLoggedIn;
173
- const isUSD = selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */;
287
+ const { splitAmount, type, method } = selectedPaymentMethod;
288
+ const isDisabled = !amount || !method || !!isProcessing || isInternalProcessing || !isLoggedIn;
289
+ const isCC = type === "CREDIT_CARD" /* CREDIT_CARD */;
290
+ const isCrypto = type === "CRYPTO" /* CRYPTO */;
291
+ const getCheckoutContent = () => {
292
+ if (!!isProcessing || isInternalProcessing) {
293
+ return /* @__PURE__ */ jsx4(Spinner, { className: "inline", size: "sm" });
294
+ }
295
+ if (isCC && amount) {
296
+ const usdAmount = getSplitAmount(amount, splitAmount ?? 0, pointsConversionRatio);
297
+ if (splitAmount && usdAmount) {
298
+ return `Pay ${formatUSD(usdAmount + getTransactionFee(usdAmount, transactionFeePercentage))} + ${formatPoints(splitAmount, pointsTitle)}`;
299
+ }
300
+ if (usdAmount) {
301
+ return `Pay ${formatUSD(usdAmount + getTransactionFee(usdAmount, transactionFeePercentage))}`;
302
+ }
303
+ if (splitAmount) {
304
+ return `Pay ${formatPoints(splitAmount, pointsTitle)}`;
305
+ }
306
+ return "Checkout";
307
+ }
308
+ if (isCrypto && amount) {
309
+ return `Pay ${formatCoin(amount)}`;
310
+ }
311
+ return "Checkout";
312
+ };
174
313
  return /* @__PURE__ */ jsxs2("div", { className: "flex w-full flex-col overflow-hidden rounded-3xl border border-black/25 bg-white text-xs font-medium", children: [
175
- /* @__PURE__ */ jsx3("div", { className: "px-5 py-5 md:px-7 md:py-6", children: /* @__PURE__ */ jsxs2("p", { className: "text-black/50", children: [
314
+ /* @__PURE__ */ jsx4("div", { className: "px-5 py-5 md:px-7 md:py-6", children: /* @__PURE__ */ jsxs2("p", { className: "text-black/50", children: [
176
315
  "By clicking on the button below I acknowledge that I have read and accepted the",
177
316
  " ",
178
- /* @__PURE__ */ jsx3(
179
- "a",
180
- {
181
- className: "underline",
182
- href: "https://uat.travel.air.shop/terms?locale=en-US&currency=USD",
183
- target: "_blank",
184
- rel: "noreferrer",
185
- children: "Terms and Conditions"
186
- }
187
- ),
317
+ /* @__PURE__ */ jsx4("a", { className: "underline", href: spreePayConfig?.termsConditionsUrl, target: "_blank", rel: "noreferrer", children: "Terms and Conditions" }),
188
318
  "."
189
319
  ] }) }),
190
- onCheckout && /* @__PURE__ */ jsx3(
320
+ onProcess && /* @__PURE__ */ jsx4(
191
321
  "button",
192
322
  {
193
323
  disabled: isDisabled,
194
- onClick: onCheckout,
324
+ onClick: onProcess,
195
325
  className: "bg-primary h-[60px] w-full cursor-pointer text-xl font-semibold text-white disabled:cursor-not-allowed disabled:opacity-50",
196
- children: !!isProcessing || isInternalProcessing ? /* @__PURE__ */ jsx3(Spinner, { className: "inline", size: "sm" }) : amount ? `Pay ${isUSD ? formatUSD(amount) : formatCoin(amount)}` : "Checkout"
326
+ children: getCheckoutContent()
197
327
  }
198
328
  )
199
329
  ] });
200
330
  };
201
331
 
202
332
  // src/components/SpreeLegal.tsx
203
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
333
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
204
334
  var SpreeLegal = () => {
205
335
  return /* @__PURE__ */ jsxs3("div", { className: "mt-4 flex items-center gap-4", children: [
206
- /* @__PURE__ */ jsx4("svg", { className: "flex-shrink-0", xmlns: "http://www.w3.org/2000/svg", width: "66", height: "30", fill: "none", children: /* @__PURE__ */ jsx4(
336
+ /* @__PURE__ */ jsx5("svg", { className: "flex-shrink-0", xmlns: "http://www.w3.org/2000/svg", width: "66", height: "30", fill: "none", children: /* @__PURE__ */ jsx5(
207
337
  "path",
208
338
  {
209
339
  fill: "#000",
@@ -214,7 +344,7 @@ var SpreeLegal = () => {
214
344
  /* @__PURE__ */ jsxs3("p", { className: "text-xs text-black/50", children: [
215
345
  "Spree enables seamless crypto payments for real-world goods, travel, and experiences. Enjoy secure, fast transactions and earn rewards.",
216
346
  " ",
217
- /* @__PURE__ */ jsx4("a", { className: "underline", href: "https://www.spree.finance/", target: "_blank", rel: "noreferrer", children: "Learn more" }),
347
+ /* @__PURE__ */ jsx5("a", { className: "underline", href: "https://www.spree.finance/", target: "_blank", rel: "noreferrer", children: "Learn more" }),
218
348
  " ",
219
349
  "about Spree."
220
350
  ] })
@@ -222,31 +352,13 @@ var SpreeLegal = () => {
222
352
  };
223
353
 
224
354
  // src/components/CreditCardTab/CreditCardTab.tsx
225
- import { useCallback as useCallback2, useEffect as useEffect2, useState as useState4 } from "react";
226
-
227
- // src/hooks/useCards.ts
228
- import useSWR from "swr";
229
- var useCards = () => {
230
- const { data, isLoading, mutate } = useSWR(`/v1/payments/cards`);
231
- return {
232
- cards: data?.data.filter((c) => c.active) || [],
233
- cardsIsLoading: isLoading,
234
- mutateCards: mutate
235
- };
236
- };
237
-
238
- // src/hooks/useSlapiBalance.ts
239
- import useSWR2 from "swr";
240
- var useSlapiBalance = () => {
241
- const { data, isLoading, mutate } = useSWR2(`/v1/loyalty/accounts`);
242
- return { balance: data?.detail, isBalanceLoading: isLoading, mutateBalance: mutate };
243
- };
355
+ import { useCallback as useCallback5, useEffect as useEffect7 } from "react";
244
356
 
245
- // src/services/cardPayment.ts
357
+ // src/hooks/useCardPayment.ts
246
358
  import NiceModal2 from "@ebay/nice-modal-react";
247
359
 
248
360
  // src/modals/Iframe3ds.tsx
249
- import { useEffect } from "react";
361
+ import { useEffect as useEffect2 } from "react";
250
362
  import NiceModal, { useModal } from "@ebay/nice-modal-react";
251
363
 
252
364
  // src/services/eventBus.ts
@@ -281,17 +393,17 @@ function usePortalContainer() {
281
393
  }
282
394
 
283
395
  // src/ui/dialog.tsx
284
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
396
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
285
397
  function Dialog({ ...props }) {
286
- return /* @__PURE__ */ jsx5(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
398
+ return /* @__PURE__ */ jsx6(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
287
399
  }
288
400
  function DialogPortal({ ...props }) {
289
401
  const container = usePortalContainer();
290
402
  const safeContainer = container && document.body.contains(container) ? container : void 0;
291
- return /* @__PURE__ */ jsx5(DialogPrimitive.Portal, { container: safeContainer, "data-slot": "dialog-portal", ...props });
403
+ return /* @__PURE__ */ jsx6(DialogPrimitive.Portal, { container: safeContainer, "data-slot": "dialog-portal", ...props });
292
404
  }
293
405
  function DialogOverlay({ className, ...props }) {
294
- return /* @__PURE__ */ jsx5(
406
+ return /* @__PURE__ */ jsx6(
295
407
  DialogPrimitive.Overlay,
296
408
  {
297
409
  "data-slot": "dialog-overlay",
@@ -310,7 +422,7 @@ function DialogContent({
310
422
  ...props
311
423
  }) {
312
424
  return /* @__PURE__ */ jsxs4(DialogPortal, { "data-slot": "dialog-portal", children: [
313
- /* @__PURE__ */ jsx5(DialogOverlay, {}),
425
+ /* @__PURE__ */ jsx6(DialogOverlay, {}),
314
426
  /* @__PURE__ */ jsxs4(
315
427
  DialogPrimitive.Content,
316
428
  {
@@ -328,8 +440,8 @@ function DialogContent({
328
440
  "data-slot": "dialog-close",
329
441
  className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
330
442
  children: [
331
- /* @__PURE__ */ jsx5(XIcon, {}),
332
- /* @__PURE__ */ jsx5("span", { className: "sr-only", children: "Close" })
443
+ /* @__PURE__ */ jsx6(XIcon, {}),
444
+ /* @__PURE__ */ jsx6("span", { className: "sr-only", children: "Close" })
333
445
  ]
334
446
  }
335
447
  )
@@ -339,7 +451,7 @@ function DialogContent({
339
451
  ] });
340
452
  }
341
453
  function DialogTitle({ className, ...props }) {
342
- return /* @__PURE__ */ jsx5(
454
+ return /* @__PURE__ */ jsx6(
343
455
  DialogPrimitive.Title,
344
456
  {
345
457
  "data-slot": "dialog-title",
@@ -349,7 +461,7 @@ function DialogTitle({ className, ...props }) {
349
461
  );
350
462
  }
351
463
  function DialogDescription({ className, ...props }) {
352
- return /* @__PURE__ */ jsx5(
464
+ return /* @__PURE__ */ jsx6(
353
465
  DialogPrimitive.Description,
354
466
  {
355
467
  "data-slot": "dialog-description",
@@ -360,10 +472,10 @@ function DialogDescription({ className, ...props }) {
360
472
  }
361
473
 
362
474
  // src/modals/Iframe3ds.tsx
363
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
475
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
364
476
  var Iframe3ds = NiceModal.create(({ url }) => {
365
477
  const modal = useModal();
366
- useEffect(() => {
478
+ useEffect2(() => {
367
479
  return bus.on("paymentIntent", (data) => {
368
480
  modal.resolve(data.paymentIntent);
369
481
  modal.remove();
@@ -373,9 +485,9 @@ var Iframe3ds = NiceModal.create(({ url }) => {
373
485
  modal.reject();
374
486
  modal.remove();
375
487
  };
376
- return /* @__PURE__ */ jsx6(Dialog, { open: modal.visible, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs5(DialogContent, { className: "max-h-[600px] w-full max-w-[680px] p-0", children: [
377
- /* @__PURE__ */ jsx6(DialogTitle, { className: "hidden", children: "3D Secure Verification" }),
378
- /* @__PURE__ */ jsx6("iframe", { src: url, id: "3ds-iframe", title: "3D Secure Checkout", className: "h-[500px] w-full rounded-lg border-0" })
488
+ return /* @__PURE__ */ jsx7(Dialog, { open: modal.visible, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs5(DialogContent, { className: "max-h-[600px] w-full max-w-[680px] p-0", children: [
489
+ /* @__PURE__ */ jsx7(DialogTitle, { className: "hidden", children: "3D Secure Verification" }),
490
+ /* @__PURE__ */ jsx7("iframe", { src: url, id: "3ds-iframe", title: "3D Secure Checkout", className: "h-[500px] w-full rounded-lg border-0" })
379
491
  ] }) });
380
492
  });
381
493
  Iframe3ds.displayName = "Iframe3ds";
@@ -477,32 +589,13 @@ var registerApi = (config2) => {
477
589
 
478
590
  // src/services/slapi.ts
479
591
  var SlapiPaymentService = {
480
- // checkBallance: async ({ coin, amount, slippage }: CheckBallanceParams) => {
481
- // // if no ballance known, return true and check by wallet
482
- // if (!coin.balance) return true;
483
- // const isUSDC = coin.symbol === COIN.USDC;
484
- // if (isUSDC) return coin.balance > amount;
485
- // const inputDecimals = cryptoAssets[COIN.USDC].decimals; // Decimals for USDC
486
- // const outputDecimals = coin.decimals; // Decimals for the input asset (e.g., SOL, BONK)
487
- // const params = {
488
- // inputMint: env.NEXT_PUBLIC_USDC_MAINNET_MINT_ADDRESS, // should be main net
489
- // outputMint: coin.address,
490
- // amount: Math.floor(amount * Math.pow(10, inputDecimals)), // Convert amount to smallest units
491
- // slippage,
492
- // };
493
- // // eslint-disable-next-line @typescript-eslint/no-explicit-any
494
- // const { data } = await jupiterApi.get<any>(`/quote?${qs.stringify(params)}`);
495
- // // Convert back to human-readable form
496
- // const outAmountNumber = data?.outAmount ? Number(data.outAmount) / Math.pow(10, outputDecimals) : null;
497
- // // if no ballance known, return true and check by wallet
498
- // if (!outAmountNumber) return true;
499
- // return coin.balance > outAmountNumber;
500
- // },
501
592
  createPayment: (params) => {
502
593
  const { type, hash, metadata, capture = false } = params;
503
594
  let reqParams;
504
595
  if (type === "CRYPTO" /* CRYPTO */) {
505
596
  reqParams = { type, hash, crypto: params.crypto };
597
+ } else if (type === "CREDIT_CARD" /* CREDIT_CARD */ && params.points && params.points.amount > 0) {
598
+ reqParams = { type: "SPLIT" /* SPLIT */, hash, card: params.card, points: params.points };
506
599
  } else {
507
600
  reqParams = { type, hash, card: params.card };
508
601
  }
@@ -511,148 +604,280 @@ var SlapiPaymentService = {
511
604
  baseVerify: ({ id, txHash }) => {
512
605
  return slapiApi.post(`/v1/base-transactions/transactions/${id}/verify`, { txHash });
513
606
  },
514
- // signEncodedTransaction: async (signTransaction: SignTransaction, encodedTX: string): Promise<string> => {
515
- // const swapTransactionBuf = Buffer.from(encodedTX, 'base64');
516
- // const transaction = VersionedTransaction.deserialize(swapTransactionBuf);
517
- // // Sign and send the transaction
518
- // const signedTransaction = await signTransaction(transaction);
519
- // return Buffer.from(signedTransaction.serialize()).toString('base64');
520
- // },
521
- // executeSolana: (params: { txId: string; signedTx: string }) => {
522
- // const { txId, signedTx } = params;
523
- // return slapiApi.post<string>(`/solana-transactions/transactions/${txId}/execute`, { signedTx });
524
- // },
525
- addCard: (params) => {
526
- const { source, hash } = params;
607
+ addCard: ({ source, hash }) => {
527
608
  return slapiApi.post("/v1/payments/cards", { hash, source }).then((data) => ({ data }));
528
609
  },
529
- validate3DS: (params) => {
530
- const { paymentId } = params;
531
- return slapiApi.post("/v1/payments/validate", { paymentId, type: "CREDIT_CARD" }).then((data) => ({ data }));
610
+ validate3DS: ({ paymentId }) => {
611
+ return slapiApi.post("/v1/payments/validate", { paymentId, type: "CREDIT_CARD" /* CREDIT_CARD */ }).then((data) => ({ data }));
612
+ },
613
+ validatePoints: ({ paymentId, txHash }) => {
614
+ return slapiApi.post("/v1/payments/validate", { txHash, paymentId, type: "POINTS" /* POINTS */ }).then((data) => ({ data }));
615
+ },
616
+ getStatus: (paymentId) => {
617
+ return slapiApi.get(`/v1/payments/${paymentId}/status`);
532
618
  }
533
619
  };
534
620
 
535
- // src/services/cardPayment.ts
536
- var cardPayment = async (params) => {
537
- const { card, redirect3dsURI, hash, capture, metadata, transactionFee } = params;
538
- let cardId = card.id;
539
- if ("token" in card) {
540
- const { data: cardResData } = await SlapiPaymentService.addCard({ hash, source: card.token });
541
- cardId = cardResData.id;
542
- }
543
- const { data: paymentResData } = await SlapiPaymentService.createPayment({
544
- hash,
545
- capture,
546
- metadata,
547
- type: "CREDIT_CARD" /* CREDIT_CARD */,
548
- card: {
549
- cardId,
550
- transactionFee,
551
- returnUrl: `${window.location.origin}${redirect3dsURI}`
621
+ // src/hooks/useCardPayment.ts
622
+ var useCardPayment = () => {
623
+ const { selectedPaymentMethod } = useSpreePaymentMethod();
624
+ const { env } = useSpreePayEnv();
625
+ const { appProps } = useStaticConfig();
626
+ const cardPayment = async (params) => {
627
+ if (selectedPaymentMethod.type !== "CREDIT_CARD" /* CREDIT_CARD */ || !selectedPaymentMethod.method) {
628
+ throw new Error("Unsupported payment method");
552
629
  }
553
- });
554
- if (paymentResData.redirectUrl) {
555
- const paymentIntent = await NiceModal2.show(Iframe3ds, { url: paymentResData.redirectUrl });
556
- if (paymentIntent) {
557
- const { data: validateData } = await SlapiPaymentService.validate3DS({ paymentId: paymentResData.id });
558
- return {
559
- paymentType: "CREDIT_CARD" /* CREDIT_CARD */,
560
- status: validateData.status,
561
- paymentId: paymentResData.id,
562
- txId: paymentResData.txId,
563
- txHash: null
564
- };
630
+ const { hash, capture, metadata } = params;
631
+ const card = selectedPaymentMethod.method;
632
+ let cardId;
633
+ if ("token" in card) {
634
+ const { data: cardResData } = await SlapiPaymentService.addCard({ hash, source: card.token });
635
+ cardId = cardResData.id;
636
+ } else {
637
+ cardId = card.id;
565
638
  }
566
- }
639
+ const transactionFee = getTransactionFee(appProps.amount, appProps.transactionFeePercentage);
640
+ const { data: paymentResData } = await SlapiPaymentService.createPayment({
641
+ hash,
642
+ capture,
643
+ metadata,
644
+ type: "CREDIT_CARD" /* CREDIT_CARD */,
645
+ card: {
646
+ cardId,
647
+ transactionFee,
648
+ returnUrl: `${typeof window !== "undefined" ? window.location.origin : ""}${env.redirect3dsURI}`
649
+ }
650
+ });
651
+ let { status } = paymentResData;
652
+ if (paymentResData.redirectUrl) {
653
+ const paymentIntent = await NiceModal2.show(Iframe3ds, { url: paymentResData.redirectUrl });
654
+ if (paymentIntent) {
655
+ const { data: validateData } = await SlapiPaymentService.validate3DS({ paymentId: paymentResData.id });
656
+ ({ status } = validateData);
657
+ }
658
+ }
659
+ return {
660
+ status,
661
+ paymentType: "CREDIT_CARD" /* CREDIT_CARD */,
662
+ paymentId: paymentResData.id,
663
+ txId: paymentResData.txId,
664
+ txHash: null
665
+ };
666
+ };
667
+ return { cardPayment };
668
+ };
669
+
670
+ // src/hooks/useCards.ts
671
+ import useSWR2 from "swr";
672
+ var useCards = () => {
673
+ const { data, isLoading, mutate } = useSWR2(`/v1/payments/cards`);
567
674
  return {
568
- paymentType: "CREDIT_CARD" /* CREDIT_CARD */,
569
- status: paymentResData.status,
570
- paymentId: paymentResData.id,
571
- txId: paymentResData.txId,
572
- txHash: null
675
+ cards: data?.data.filter((c) => c.active) || [],
676
+ cardsIsLoading: isLoading,
677
+ mutateCards: mutate
573
678
  };
574
679
  };
575
680
 
576
- // src/components/common/PointsSwitch.tsx
577
- import { useId } from "react";
681
+ // src/hooks/useSplitCardPayments.ts
682
+ import NiceModal3 from "@ebay/nice-modal-react";
578
683
 
579
- // src/ui/label.tsx
580
- import * as LabelPrimitive from "@radix-ui/react-label";
581
- import { jsx as jsx7 } from "react/jsx-runtime";
582
- function Label({ className, ...props }) {
583
- return /* @__PURE__ */ jsx7(
584
- LabelPrimitive.Root,
585
- {
586
- "data-slot": "label",
587
- className: cn(
588
- "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
589
- className
590
- ),
591
- ...props
684
+ // src/services/AirWalletService.ts
685
+ import { AirService, BUILD_ENV } from "@mocanetwork/airkit";
686
+ import { createWalletClient, custom, encodeFunctionData, erc20Abi, parseUnits } from "viem";
687
+ var singletonState = null;
688
+ var initPromise = null;
689
+ var cachedKey = null;
690
+ function optionsKey(opts) {
691
+ return `${opts.partnerId}|${opts.mocaChain?.id ?? "unknown"}`;
692
+ }
693
+ async function createAndInit(opts) {
694
+ const air = new AirService({ partnerId: opts.partnerId });
695
+ try {
696
+ await air.init({
697
+ buildEnv: opts.buildEnv ?? BUILD_ENV.SANDBOX,
698
+ enableLogging: opts.enableLogging ?? true,
699
+ skipRehydration: opts.skipRehydration ?? false
700
+ });
701
+ air.preloadWallet().catch(() => {
702
+ });
703
+ const loginRes = await air.login();
704
+ const address = loginRes?.abstractAccountAddress || null;
705
+ const walletClient = address ? createWalletClient({
706
+ transport: custom(air.provider),
707
+ chain: opts.mocaChain,
708
+ account: address
709
+ }) : null;
710
+ return { walletReady: true, address, walletClient, air, chain: opts.mocaChain };
711
+ } catch (e) {
712
+ const msg = e instanceof Error ? e.message : "Unknown error during AirWallet initialization";
713
+ return { walletReady: false, address: null, walletClient: null, air: null, chain: null, error: msg };
714
+ }
715
+ }
716
+ async function getAirWallet(options) {
717
+ const key = optionsKey(options);
718
+ if (singletonState && cachedKey === key) return singletonState;
719
+ if (initPromise && cachedKey === key) return initPromise;
720
+ cachedKey = key;
721
+ initPromise = createAndInit(options).then((state) => {
722
+ singletonState = state;
723
+ return state;
724
+ });
725
+ return initPromise;
726
+ }
727
+ function peekAirWallet() {
728
+ return singletonState;
729
+ }
730
+ async function handleSendErc20(params) {
731
+ const state = singletonState;
732
+ if (!state?.walletClient) {
733
+ console.error("Air wallet is not initialized");
734
+ throw new Error("Air wallet is not initialized");
735
+ }
736
+ if (!params?.recipient) {
737
+ console.error("Recipient address is not set");
738
+ throw new Error("Recipient address is not set");
739
+ }
740
+ if (!params?.token?.address || !params?.token?.decimals) {
741
+ console.error("Token address or decimals not set");
742
+ throw new Error("Token address or decimals not set");
743
+ }
744
+ try {
745
+ const { walletClient } = state;
746
+ const addresses = await walletClient.getAddresses();
747
+ const value = parseUnits(String(params.amount), params.token.decimals);
748
+ const data = encodeFunctionData({
749
+ abi: erc20Abi,
750
+ functionName: "transfer",
751
+ args: [params.recipient, value]
752
+ });
753
+ const hash = await walletClient.sendTransaction({
754
+ account: addresses[0],
755
+ to: params.token.address,
756
+ data,
757
+ value: 0n,
758
+ chain: state.chain ?? void 0
759
+ });
760
+ return { txHash: hash };
761
+ } catch (error) {
762
+ if (typeof error === "object" && error !== null && "shortMessage" in error) {
763
+ console.error(error.shortMessage);
764
+ } else {
765
+ console.error("Your wallet balances are insufficient to complete this transaction.");
592
766
  }
593
- );
767
+ }
594
768
  }
595
769
 
596
- // src/ui/switch.tsx
597
- import * as SwitchPrimitive from "@radix-ui/react-switch";
598
- import { jsx as jsx8 } from "react/jsx-runtime";
599
- function Switch({ className, ...props }) {
600
- return /* @__PURE__ */ jsx8(
601
- SwitchPrimitive.Root,
602
- {
603
- "data-slot": "switch",
604
- className: cn(
605
- "peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
606
- className
607
- ),
608
- ...props,
609
- children: /* @__PURE__ */ jsx8(
610
- SwitchPrimitive.Thumb,
611
- {
612
- "data-slot": "switch-thumb",
613
- className: "bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
614
- }
615
- )
770
+ // src/hooks/useSplitCardPayments.ts
771
+ var REFRESH_INTERVAL = 3 * 1e3;
772
+ var MAX_RETRIES = 10;
773
+ async function longPollPoints(paymentId) {
774
+ let retries = 0;
775
+ while (retries < MAX_RETRIES) {
776
+ const { detail } = await SlapiPaymentService.getStatus(paymentId);
777
+ if (detail.status === "FAILED" /* FAILED */) {
778
+ throw new Error("Something went wrong with the payment");
616
779
  }
617
- );
780
+ if (["AUTHORIZED" /* AUTHORIZED */, "CAPTURED" /* CAPTURED */].includes(detail.status)) {
781
+ return detail.status;
782
+ }
783
+ await new Promise((res) => setTimeout(res, REFRESH_INTERVAL));
784
+ retries++;
785
+ }
786
+ throw new Error("Points Payment polling timed out");
618
787
  }
619
-
620
- // src/components/common/PointsSwitch.tsx
621
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
622
- var PointsSwitch = (props) => {
623
- const { pointsConversionRatio, disabled = false, value, onChange, pointsTitle } = props;
624
- const { balance } = useSlapiBalance();
625
- const id = useId();
626
- return /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-3", children: [
627
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3", children: [
628
- /* @__PURE__ */ jsx9(Switch, { checked: value, onCheckedChange: onChange, disabled, id }),
629
- /* @__PURE__ */ jsxs6(Label, { className: "text-md items-baseline leading-[1.3] font-semibold text-black md:text-xl", htmlFor: id, children: [
630
- "Use Points ",
631
- /* @__PURE__ */ jsx9("span", { className: "text-xs font-medium", children: "Optional" })
632
- ] })
633
- ] }),
634
- balance?.availablePoints ? /* @__PURE__ */ jsxs6("p", { className: "flex-1 text-right text-sm font-medium text-black", children: [
635
- formatPoints(balance.availablePoints, pointsTitle),
636
- " ",
637
- /* @__PURE__ */ jsx9("span", { className: "text-black/50", children: formatUSD(balance.availablePoints / pointsConversionRatio) })
638
- ] }) : null
639
- ] });
788
+ async function longPollCardStatus(paymentId) {
789
+ let retries = 0;
790
+ let shown3ds = false;
791
+ while (retries < MAX_RETRIES) {
792
+ const { detail } = await SlapiPaymentService.getStatus(paymentId);
793
+ if (detail.status === "FAILED" /* FAILED */) {
794
+ throw new Error(`Something went wrong with the ${detail.validationType} payment`);
795
+ }
796
+ if (detail.validationType === "POINTS") {
797
+ return detail.status;
798
+ }
799
+ if (!shown3ds && detail.card?.redirectUrl) {
800
+ const paymentIntent = await NiceModal3.show(Iframe3ds, { url: detail.card?.redirectUrl });
801
+ shown3ds = true;
802
+ if (paymentIntent) {
803
+ await SlapiPaymentService.validate3DS({ paymentId });
804
+ }
805
+ }
806
+ await new Promise((res) => setTimeout(res, REFRESH_INTERVAL));
807
+ retries++;
808
+ }
809
+ throw new Error("Payment polling timed out");
810
+ }
811
+ var useSplitCardPayments = () => {
812
+ const { selectedPaymentMethod } = useSpreePaymentMethod();
813
+ const { env } = useSpreePayEnv();
814
+ const { appProps, staticConfig } = useStaticConfig();
815
+ const { spreePayConfig } = useSpreePayConfig();
816
+ const splitPayment = async (params) => {
817
+ if (selectedPaymentMethod.type !== "CREDIT_CARD" /* CREDIT_CARD */ || !selectedPaymentMethod.method || !params.points) {
818
+ throw new Error("Unsupported payment method");
819
+ }
820
+ const { hash, capture, metadata, points } = params;
821
+ const card = selectedPaymentMethod.method;
822
+ let cardId;
823
+ if ("token" in card) {
824
+ const { data: cardResData } = await SlapiPaymentService.addCard({ hash, source: card.token });
825
+ cardId = cardResData.id;
826
+ } else {
827
+ cardId = card.id;
828
+ }
829
+ const usdAmount = getSplitAmount(appProps.amount ?? 0, points, staticConfig.pointsConversionRatio);
830
+ const transactionFee = getTransactionFee(usdAmount, appProps.transactionFeePercentage);
831
+ const { data: paymentResData } = await SlapiPaymentService.createPayment({
832
+ hash,
833
+ capture,
834
+ metadata,
835
+ type: "CREDIT_CARD" /* CREDIT_CARD */,
836
+ card: {
837
+ cardId,
838
+ transactionFee,
839
+ returnUrl: `${typeof window !== "undefined" ? window.location.origin : ""}${env.redirect3dsURI}`
840
+ },
841
+ points: {
842
+ amount: points
843
+ }
844
+ });
845
+ await longPollCardStatus(paymentResData.id);
846
+ const wallet = peekAirWallet();
847
+ if (!wallet || !spreePayConfig?.pointsChain) {
848
+ throw new Error("AirWallet not found");
849
+ }
850
+ const transaction = await handleSendErc20({
851
+ amount: params.points,
852
+ token: spreePayConfig.pointsChain.pointsCoin,
853
+ recipient: spreePayConfig.pointsChain.recipientAddress
854
+ });
855
+ if (!transaction) {
856
+ throw new Error("Points transaction failed");
857
+ }
858
+ await SlapiPaymentService.validatePoints({
859
+ paymentId: paymentResData.id,
860
+ txHash: transaction.txHash
861
+ });
862
+ const pointsStatus = await longPollPoints(paymentResData.id);
863
+ return {
864
+ paymentType: "SPLIT" /* SPLIT */,
865
+ status: pointsStatus,
866
+ paymentId: paymentResData.id,
867
+ txId: paymentResData.txId,
868
+ txHash: transaction.txHash
869
+ };
870
+ };
871
+ return { splitPayment };
640
872
  };
641
873
 
642
874
  // src/components/CreditCardTab/CreditCard/CreditCard.tsx
643
- import { useMemo, useState as useState3 } from "react";
875
+ import { useMemo as useMemo2, useState as useState4 } from "react";
644
876
  import { Elements } from "@stripe/react-stripe-js";
645
877
  import { loadStripe } from "@stripe/stripe-js";
646
878
 
647
- // src/hooks/useConfig.ts
648
- import useSWR3 from "swr";
649
- var useConfig = () => {
650
- const { data, isLoading } = useSWR3("/v1/tenants/configs/spree-pay");
651
- return { config: data, configIsLoading: isLoading };
652
- };
653
-
654
879
  // src/components/CreditCardTab/CreditCard/CardsList.tsx
655
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
880
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
656
881
  var isRemoveDisabled = true;
657
882
  var CardListItem = ({ card, isSelected, onSelect }) => {
658
883
  const handleSelect = () => {
@@ -662,17 +887,17 @@ var CardListItem = ({ card, isSelected, onSelect }) => {
662
887
  e.stopPropagation();
663
888
  if (isSelected || isRemoveDisabled) return;
664
889
  };
665
- return /* @__PURE__ */ jsxs7("button", { type: "button", onClick: handleSelect, className: "bg-primary/8 flex h-11 w-full overflow-hidden rounded-md", children: [
666
- /* @__PURE__ */ jsx10(
890
+ return /* @__PURE__ */ jsxs6("button", { type: "button", onClick: handleSelect, className: "bg-primary/8 flex h-11 w-full overflow-hidden rounded-md", children: [
891
+ /* @__PURE__ */ jsx8(
667
892
  "div",
668
893
  {
669
894
  className: cn("flex h-full w-11 items-center justify-center bg-black/10", {
670
895
  "bg-primary": isSelected
671
896
  }),
672
- children: /* @__PURE__ */ jsx10("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-white", children: isSelected && /* @__PURE__ */ jsx10("div", { className: "bg-primary h-2.5 w-2.5 rounded-full" }) })
897
+ children: /* @__PURE__ */ jsx8("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-white", children: isSelected && /* @__PURE__ */ jsx8("div", { className: "bg-primary h-2.5 w-2.5 rounded-full" }) })
673
898
  }
674
899
  ),
675
- /* @__PURE__ */ jsxs7(
900
+ /* @__PURE__ */ jsxs6(
676
901
  "div",
677
902
  {
678
903
  className: cn(
@@ -682,13 +907,13 @@ var CardListItem = ({ card, isSelected, onSelect }) => {
682
907
  }
683
908
  ),
684
909
  children: [
685
- /* @__PURE__ */ jsx10("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx10("p", { className: "text-sm font-medium text-black", children: card.schema }) }),
686
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
687
- /* @__PURE__ */ jsxs7("p", { className: "text-sm font-medium text-black/50", children: [
910
+ /* @__PURE__ */ jsx8("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx8("p", { className: "text-sm font-medium text-black", children: card.schema }) }),
911
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
912
+ /* @__PURE__ */ jsxs6("p", { className: "text-sm font-medium text-black/50", children: [
688
913
  "Ending in ",
689
- /* @__PURE__ */ jsx10("span", { className: "text-black", children: card.lastFourNumbers })
914
+ /* @__PURE__ */ jsx8("span", { className: "text-black", children: card.lastFourNumbers })
690
915
  ] }),
691
- /* @__PURE__ */ jsx10(
916
+ /* @__PURE__ */ jsx8(
692
917
  "div",
693
918
  {
694
919
  onClick: handleRemoveCard,
@@ -696,9 +921,9 @@ var CardListItem = ({ card, isSelected, onSelect }) => {
696
921
  "cursor-not-allowed opacity-50": isSelected || isRemoveDisabled
697
922
  // 'cursor-pointer': !isSelected || !isRemoveDisabled,
698
923
  }),
699
- children: /* @__PURE__ */ jsxs7("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", fill: "none", children: [
700
- /* @__PURE__ */ jsx10("mask", { id: "mask0_188_5407", width: "20", height: "21", x: "0", y: "-1", maskUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx10("path", { fill: "#D9D9D9", d: "M0-.5h20v20H0z" }) }),
701
- /* @__PURE__ */ jsx10("g", { mask: "url(#mask0_188_5407)", children: /* @__PURE__ */ jsx10(
924
+ children: /* @__PURE__ */ jsxs6("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", fill: "none", children: [
925
+ /* @__PURE__ */ jsx8("mask", { id: "mask0_188_5407", width: "20", height: "21", x: "0", y: "-1", maskUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx8("path", { fill: "#D9D9D9", d: "M0-.5h20v20H0z" }) }),
926
+ /* @__PURE__ */ jsx8("g", { mask: "url(#mask0_188_5407)", children: /* @__PURE__ */ jsx8(
702
927
  "path",
703
928
  {
704
929
  fill: "#000",
@@ -718,23 +943,23 @@ var CardListItem = ({ card, isSelected, onSelect }) => {
718
943
  var CardsList = ({ selectedCard, setCard }) => {
719
944
  const { cards, cardsIsLoading } = useCards();
720
945
  if (cardsIsLoading) {
721
- return /* @__PURE__ */ jsxs7("div", { className: "flex w-full flex-col gap-1", children: [
722
- /* @__PURE__ */ jsx10("div", { className: "bg-primary/8 h-11 animate-pulse rounded-md" }),
723
- /* @__PURE__ */ jsx10("div", { className: "bg-primary/8 h-11 animate-pulse rounded-md" })
946
+ return /* @__PURE__ */ jsxs6("div", { className: "flex w-full flex-col gap-1", children: [
947
+ /* @__PURE__ */ jsx8("div", { className: "bg-primary/8 h-11 animate-pulse rounded-md" }),
948
+ /* @__PURE__ */ jsx8("div", { className: "bg-primary/8 h-11 animate-pulse rounded-md" })
724
949
  ] });
725
950
  }
726
951
  if (cards.length === 0) return null;
727
- return /* @__PURE__ */ jsx10("div", { className: "flex w-full flex-col gap-1", children: cards.map((card) => /* @__PURE__ */ jsx10(CardListItem, { isSelected: selectedCard?.id === card.id, onSelect: setCard, card }, card.id)) });
952
+ return /* @__PURE__ */ jsx8("div", { className: "flex w-full flex-col gap-1", children: cards.map((card) => /* @__PURE__ */ jsx8(CardListItem, { isSelected: selectedCard?.id === card.id, onSelect: setCard, card }, card.id)) });
728
953
  };
729
954
 
730
955
  // src/components/CreditCardTab/CreditCard/CreditCardForm.tsx
731
- import { useId as useId2, useState as useState2 } from "react";
956
+ import { useId, useState as useState3 } from "react";
732
957
  import { CardCvcElement, CardExpiryElement, CardNumberElement, useElements, useStripe } from "@stripe/react-stripe-js";
733
958
 
734
959
  // src/ui/button.tsx
735
960
  import { Slot } from "@radix-ui/react-slot";
736
961
  import { cva } from "class-variance-authority";
737
- import { jsx as jsx11 } from "react/jsx-runtime";
962
+ import { jsx as jsx9 } from "react/jsx-runtime";
738
963
  var buttonVariants = cva(
739
964
  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-sm transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
740
965
  {
@@ -769,15 +994,15 @@ function Button({
769
994
  ...props
770
995
  }) {
771
996
  const Comp = asChild ? Slot : "button";
772
- return /* @__PURE__ */ jsx11(Comp, { "data-slot": "button", className: cn(buttonVariants({ variant, size, className })), ...props });
997
+ return /* @__PURE__ */ jsx9(Comp, { "data-slot": "button", className: cn(buttonVariants({ variant, size, className })), ...props });
773
998
  }
774
999
 
775
1000
  // src/ui/checkbox.tsx
776
1001
  import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
777
1002
  import { CheckIcon } from "lucide-react";
778
- import { jsx as jsx12 } from "react/jsx-runtime";
1003
+ import { jsx as jsx10 } from "react/jsx-runtime";
779
1004
  function Checkbox({ className, ...props }) {
780
- return /* @__PURE__ */ jsx12(
1005
+ return /* @__PURE__ */ jsx10(
781
1006
  CheckboxPrimitive.Root,
782
1007
  {
783
1008
  "data-slot": "checkbox",
@@ -786,20 +1011,37 @@ function Checkbox({ className, ...props }) {
786
1011
  className
787
1012
  ),
788
1013
  ...props,
789
- children: /* @__PURE__ */ jsx12(
1014
+ children: /* @__PURE__ */ jsx10(
790
1015
  CheckboxPrimitive.Indicator,
791
1016
  {
792
1017
  "data-slot": "checkbox-indicator",
793
1018
  className: "flex items-center justify-center text-current transition-none",
794
- children: /* @__PURE__ */ jsx12(CheckIcon, { className: "size-3.5 text-white" })
1019
+ children: /* @__PURE__ */ jsx10(CheckIcon, { className: "size-3.5 text-white" })
795
1020
  }
796
1021
  )
797
1022
  }
798
1023
  );
799
1024
  }
800
1025
 
1026
+ // src/ui/label.tsx
1027
+ import * as LabelPrimitive from "@radix-ui/react-label";
1028
+ import { jsx as jsx11 } from "react/jsx-runtime";
1029
+ function Label({ className, ...props }) {
1030
+ return /* @__PURE__ */ jsx11(
1031
+ LabelPrimitive.Root,
1032
+ {
1033
+ "data-slot": "label",
1034
+ className: cn(
1035
+ "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
1036
+ className
1037
+ ),
1038
+ ...props
1039
+ }
1040
+ );
1041
+ }
1042
+
801
1043
  // src/components/CreditCardTab/CreditCard/CreditCardForm.tsx
802
- import { Fragment, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1044
+ import { Fragment, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
803
1045
  var style = {
804
1046
  base: {
805
1047
  fontSize: "16px",
@@ -819,10 +1061,10 @@ var stripeElementClasses = {
819
1061
  focus: "border-ring ring-ring/50 ring-2"
820
1062
  };
821
1063
  var CreditCardForm = ({ cancel, saveCard }) => {
822
- const [cardError, setCardError] = useState2(void 0);
1064
+ const [cardError, setCardError] = useState3(void 0);
823
1065
  const elements = useElements();
824
1066
  const stripe = useStripe();
825
- const id = useId2();
1067
+ const id = useId();
826
1068
  const handleSaveCard = async () => {
827
1069
  if (!elements || !stripe) return;
828
1070
  setCardError(void 0);
@@ -857,9 +1099,9 @@ var CreditCardForm = ({ cancel, saveCard }) => {
857
1099
  setCardError("An error occurred while processing your card. Please try again.");
858
1100
  }
859
1101
  };
860
- return /* @__PURE__ */ jsxs8(Fragment, { children: [
861
- /* @__PURE__ */ jsxs8("div", { className: "flex w-full flex-col gap-1", children: [
862
- /* @__PURE__ */ jsx13(
1102
+ return /* @__PURE__ */ jsxs7(Fragment, { children: [
1103
+ /* @__PURE__ */ jsxs7("div", { className: "flex w-full flex-col gap-1", children: [
1104
+ /* @__PURE__ */ jsx12(
863
1105
  CardNumberElement,
864
1106
  {
865
1107
  options: {
@@ -869,8 +1111,8 @@ var CreditCardForm = ({ cancel, saveCard }) => {
869
1111
  }
870
1112
  }
871
1113
  ),
872
- /* @__PURE__ */ jsxs8("div", { className: "flex w-full gap-1", children: [
873
- /* @__PURE__ */ jsx13(
1114
+ /* @__PURE__ */ jsxs7("div", { className: "flex w-full gap-1", children: [
1115
+ /* @__PURE__ */ jsx12(
874
1116
  CardExpiryElement,
875
1117
  {
876
1118
  options: {
@@ -880,7 +1122,7 @@ var CreditCardForm = ({ cancel, saveCard }) => {
880
1122
  }
881
1123
  }
882
1124
  ),
883
- /* @__PURE__ */ jsx13(
1125
+ /* @__PURE__ */ jsx12(
884
1126
  CardCvcElement,
885
1127
  {
886
1128
  options: {
@@ -891,32 +1133,32 @@ var CreditCardForm = ({ cancel, saveCard }) => {
891
1133
  }
892
1134
  )
893
1135
  ] }),
894
- cardError && /* @__PURE__ */ jsx13("p", { className: "text-destructive mt-1 text-sm", children: cardError })
1136
+ cardError && /* @__PURE__ */ jsx12("p", { className: "text-destructive mt-1 text-sm", children: cardError })
895
1137
  ] }),
896
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
897
- /* @__PURE__ */ jsx13(Checkbox, { disabled: true, checked: true, id: "saveCard" }),
898
- /* @__PURE__ */ jsx13(Label, { className: "text-sm font-medium", htmlFor: "saveCard", children: "Save card for future purchases" })
1138
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
1139
+ /* @__PURE__ */ jsx12(Checkbox, { disabled: true, checked: true, id: "saveCard" }),
1140
+ /* @__PURE__ */ jsx12(Label, { className: "text-sm font-medium", htmlFor: "saveCard", children: "Save card for future purchases" })
899
1141
  ] }),
900
- /* @__PURE__ */ jsxs8("div", { className: "flex w-full justify-end gap-2", children: [
901
- /* @__PURE__ */ jsx13(Button, { variant: "secondary", onClick: cancel, children: "Cancel" }),
902
- /* @__PURE__ */ jsx13(Button, { onClick: handleSaveCard, children: "Add Card" })
1142
+ /* @__PURE__ */ jsxs7("div", { className: "flex w-full justify-end gap-2", children: [
1143
+ /* @__PURE__ */ jsx12(Button, { variant: "secondary", onClick: cancel, children: "Cancel" }),
1144
+ /* @__PURE__ */ jsx12(Button, { onClick: handleSaveCard, children: "Add Card" })
903
1145
  ] })
904
1146
  ] });
905
1147
  };
906
1148
 
907
1149
  // src/components/CreditCardTab/CreditCard/CreditCard.tsx
908
- import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
909
- var SripeWrapper = (props) => {
910
- const stripePromise = useMemo(() => loadStripe(props.publicKey), [props.publicKey]);
911
- return /* @__PURE__ */ jsx14(Elements, { stripe: stripePromise, children: /* @__PURE__ */ jsx14(CreditCardForm, { cancel: props.onCancel, saveCard: props.saveNewCard }) });
1150
+ import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1151
+ var StripeWrapper = (props) => {
1152
+ const stripePromise = useMemo2(() => loadStripe(props.publicKey), [props.publicKey]);
1153
+ return /* @__PURE__ */ jsx13(Elements, { stripe: stripePromise, children: /* @__PURE__ */ jsx13(CreditCardForm, { cancel: props.onCancel, saveCard: props.saveNewCard }) });
912
1154
  };
913
1155
  var CreditCard = () => {
914
- const [showForm, setShowForm] = useState3(false);
1156
+ const [showForm, setShowForm] = useState4(false);
915
1157
  const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
916
1158
  const { mutateCards } = useCards();
917
- const { config: config2 } = useConfig();
1159
+ const { spreePayConfig } = useSpreePayConfig();
918
1160
  const setCard = (card) => {
919
- setSelectedPaymentMethod({ type: "CREDIT_CARD" /* CREDIT_CARD */, method: card });
1161
+ setSelectedPaymentMethod({ ...selectedPaymentMethod, type: "CREDIT_CARD" /* CREDIT_CARD */, method: card });
920
1162
  };
921
1163
  const saveNewCard = (newCard) => {
922
1164
  mutateCards((data) => ({ ...data, data: [...data?.data ?? [], newCard] }), { revalidate: false });
@@ -926,130 +1168,1249 @@ var CreditCard = () => {
926
1168
  const handleCancel = () => {
927
1169
  setShowForm(false);
928
1170
  };
929
- return /* @__PURE__ */ jsxs9("div", { className: "flex flex-col items-baseline gap-4", children: [
930
- /* @__PURE__ */ jsx14("h3", { className: "text-primary text-xl leading-[34px] font-semibold", children: "Your Credit Cards" }),
931
- !showForm && /* @__PURE__ */ jsxs9(Fragment2, { children: [
932
- /* @__PURE__ */ jsx14(
1171
+ return /* @__PURE__ */ jsxs8("div", { className: "flex flex-col items-baseline gap-4", children: [
1172
+ /* @__PURE__ */ jsx13("h3", { className: "text-primary text-xl leading-[34px] font-semibold", children: "Your Credit Cards" }),
1173
+ !showForm && /* @__PURE__ */ jsxs8(Fragment2, { children: [
1174
+ /* @__PURE__ */ jsx13(
933
1175
  CardsList,
934
1176
  {
935
1177
  selectedCard: selectedPaymentMethod?.type === "CREDIT_CARD" /* CREDIT_CARD */ ? selectedPaymentMethod.method : null,
936
1178
  setCard
937
1179
  }
938
1180
  ),
939
- config2?.stripePublicKey && /* @__PURE__ */ jsx14("button", { onClick: () => setShowForm(true), className: "text-sm font-medium text-black hover:underline", children: "Add new card" })
1181
+ spreePayConfig?.stripePublicKey && /* @__PURE__ */ jsx13("button", { onClick: () => setShowForm(true), className: "text-sm font-medium text-black hover:underline", children: "Add new card" })
940
1182
  ] }),
941
- config2?.stripePublicKey && showForm && /* @__PURE__ */ jsx14(SripeWrapper, { onCancel: handleCancel, saveNewCard, publicKey: config2.stripePublicKey })
1183
+ spreePayConfig?.stripePublicKey && showForm && /* @__PURE__ */ jsx13(StripeWrapper, { onCancel: handleCancel, saveNewCard, publicKey: spreePayConfig.stripePublicKey })
942
1184
  ] });
943
1185
  };
944
1186
 
945
- // src/components/CreditCardTab/CreditCardTab.tsx
946
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
947
- var PointsSelector = ({ isSelected, onSelect, children }) => {
948
- return (
949
- // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
950
- /* @__PURE__ */ jsxs10(
951
- "div",
952
- {
953
- onClick: onSelect,
954
- className: cn("bg-primary/8 cursor-pointer overflow-hidden rounded-md border-1 border-transparent", {
955
- "border-primary": isSelected
956
- }),
957
- children: [
958
- /* @__PURE__ */ jsxs10("div", { className: cn("flex h-11 w-full", { "bg-black/4": isSelected }), children: [
959
- /* @__PURE__ */ jsx15(
960
- "div",
961
- {
962
- className: cn("flex h-full w-11 items-center justify-center bg-black/10", {
963
- "bg-primary": isSelected
964
- }),
965
- children: /* @__PURE__ */ jsx15("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-white", children: isSelected && /* @__PURE__ */ jsx15("div", { className: "bg-primary h-2.5 w-2.5 rounded-full" }) })
966
- }
967
- ),
968
- /* @__PURE__ */ jsx15("div", { className: "flex h-full w-full items-center justify-between gap-4 px-3", children })
969
- ] }),
970
- isSelected && /* @__PURE__ */ jsx15("div", { className: "px-4 pt-6 pb-2", children: /* @__PURE__ */ jsx15("p", { children: "Card" }) })
971
- ]
972
- }
973
- )
974
- );
1187
+ // src/components/CreditCardTab/Points/Points.tsx
1188
+ import { useState as useState10 } from "react";
1189
+
1190
+ // src/components/common/PointsSwitch.tsx
1191
+ import { useId as useId2 } from "react";
1192
+
1193
+ // src/hooks/useSlapiBalance.ts
1194
+ import useSWR3 from "swr";
1195
+ var useSlapiBalance = () => {
1196
+ const { data, isLoading, mutate } = useSWR3(`/v1/loyalty/accounts`);
1197
+ return { balance: data?.detail, isBalanceLoading: isLoading, mutateBalance: mutate };
975
1198
  };
976
- var CreditCardTab = ({ pointsTitle, pointsConversionRatio }) => {
977
- const [usePoints, setUsePoints] = useState4(false);
978
- const [selectedPointsType, setSelectedPointsType] = useState4(null);
979
- const { balance, isBalanceLoading } = useSlapiBalance();
980
- const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
981
- const { register } = useSpreePayRegister();
982
- const { mutateCards } = useCards();
983
- const { env } = useSpreePayEnv();
984
- const handlePay = useCallback2(
985
- async (data) => {
986
- try {
987
- if (selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && selectedPaymentMethod.method) {
988
- const res = await cardPayment({
989
- ...data,
990
- card: selectedPaymentMethod.method,
991
- redirect3dsURI: env.redirect3dsURI
992
- });
993
- if (["AUTHORIZED" /* AUTHORIZED */, "CAPTURED" /* CAPTURED */].includes(res.status)) {
994
- return Promise.resolve(res);
995
- }
996
- return Promise.reject(new PaymentError("Card payment failed", res.status));
1199
+
1200
+ // src/ui/switch.tsx
1201
+ import * as SwitchPrimitive from "@radix-ui/react-switch";
1202
+ import { jsx as jsx14 } from "react/jsx-runtime";
1203
+ function Switch({ className, ...props }) {
1204
+ return /* @__PURE__ */ jsx14(
1205
+ SwitchPrimitive.Root,
1206
+ {
1207
+ "data-slot": "switch",
1208
+ className: cn(
1209
+ "peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
1210
+ className
1211
+ ),
1212
+ ...props,
1213
+ children: /* @__PURE__ */ jsx14(
1214
+ SwitchPrimitive.Thumb,
1215
+ {
1216
+ "data-slot": "switch-thumb",
1217
+ className: "bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
1218
+ }
1219
+ )
1220
+ }
1221
+ );
1222
+ }
1223
+
1224
+ // src/components/common/PointsSwitch.tsx
1225
+ import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1226
+ var PointsSwitch = (props) => {
1227
+ const { disabled = false, value, onChange } = props;
1228
+ const { staticConfig } = useStaticConfig();
1229
+ const { pointsConversionRatio, pointsTitle } = staticConfig;
1230
+ const { balance } = useSlapiBalance();
1231
+ const id = useId2();
1232
+ return /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-3", children: [
1233
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3", children: [
1234
+ /* @__PURE__ */ jsx15(Switch, { checked: value, onCheckedChange: onChange, disabled, id }),
1235
+ /* @__PURE__ */ jsxs9(Label, { className: "text-md items-baseline leading-[1.3] font-semibold text-black md:text-xl", htmlFor: id, children: [
1236
+ "Use Points ",
1237
+ /* @__PURE__ */ jsx15("span", { className: "text-xs font-medium", children: "Optional" })
1238
+ ] })
1239
+ ] }),
1240
+ balance?.availablePoints ? /* @__PURE__ */ jsxs9("p", { className: "flex-1 text-right text-sm font-medium text-black", children: [
1241
+ formatPoints(balance.availablePoints, pointsTitle),
1242
+ " ",
1243
+ /* @__PURE__ */ jsx15("span", { className: "text-black/50", children: formatUSD(balance.availablePoints / pointsConversionRatio) })
1244
+ ] }) : null
1245
+ ] });
1246
+ };
1247
+
1248
+ // src/components/CreditCardTab/Points/SplitBlock.tsx
1249
+ import { useCallback as useCallback4, useEffect as useEffect6, useState as useState9 } from "react";
1250
+
1251
+ // src/components/CreditCardTab/Points/PointsSelector.tsx
1252
+ import { useState as useState8 } from "react";
1253
+
1254
+ // src/ui/input.tsx
1255
+ import { jsx as jsx16 } from "react/jsx-runtime";
1256
+ function Input({ className, type, ...props }) {
1257
+ return /* @__PURE__ */ jsx16(
1258
+ "input",
1259
+ {
1260
+ type,
1261
+ "data-slot": "input",
1262
+ className: cn(
1263
+ "file:text-foreground placeholder:text-muted-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 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 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1264
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
1265
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
1266
+ className
1267
+ ),
1268
+ ...props
1269
+ }
1270
+ );
1271
+ }
1272
+
1273
+ // src/ui/slider.tsx
1274
+ import * as React12 from "react";
1275
+
1276
+ // ../../node_modules/@radix-ui/react-slider/dist/index.mjs
1277
+ import * as React11 from "react";
1278
+
1279
+ // ../../node_modules/@radix-ui/number/dist/index.mjs
1280
+ function clamp(value, [min, max]) {
1281
+ return Math.min(max, Math.max(min, value));
1282
+ }
1283
+
1284
+ // ../../node_modules/@radix-ui/react-slider/node_modules/@radix-ui/primitive/dist/index.mjs
1285
+ var canUseDOM = !!(typeof window !== "undefined" && window.document && window.document.createElement);
1286
+ function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {
1287
+ return function handleEvent(event) {
1288
+ originalEventHandler?.(event);
1289
+ if (checkForDefaultPrevented === false || !event.defaultPrevented) {
1290
+ return ourEventHandler?.(event);
1291
+ }
1292
+ };
1293
+ }
1294
+
1295
+ // ../../node_modules/@radix-ui/react-compose-refs/dist/index.mjs
1296
+ import * as React2 from "react";
1297
+ function setRef(ref, value) {
1298
+ if (typeof ref === "function") {
1299
+ return ref(value);
1300
+ } else if (ref !== null && ref !== void 0) {
1301
+ ref.current = value;
1302
+ }
1303
+ }
1304
+ function composeRefs(...refs) {
1305
+ return (node) => {
1306
+ let hasCleanup = false;
1307
+ const cleanups = refs.map((ref) => {
1308
+ const cleanup = setRef(ref, node);
1309
+ if (!hasCleanup && typeof cleanup == "function") {
1310
+ hasCleanup = true;
1311
+ }
1312
+ return cleanup;
1313
+ });
1314
+ if (hasCleanup) {
1315
+ return () => {
1316
+ for (let i = 0; i < cleanups.length; i++) {
1317
+ const cleanup = cleanups[i];
1318
+ if (typeof cleanup == "function") {
1319
+ cleanup();
1320
+ } else {
1321
+ setRef(refs[i], null);
1322
+ }
1323
+ }
1324
+ };
1325
+ }
1326
+ };
1327
+ }
1328
+ function useComposedRefs(...refs) {
1329
+ return React2.useCallback(composeRefs(...refs), refs);
1330
+ }
1331
+
1332
+ // ../../node_modules/@radix-ui/react-context/dist/index.mjs
1333
+ import * as React3 from "react";
1334
+ import { jsx as jsx17 } from "react/jsx-runtime";
1335
+ function createContextScope(scopeName, createContextScopeDeps = []) {
1336
+ let defaultContexts = [];
1337
+ function createContext32(rootComponentName, defaultContext) {
1338
+ const BaseContext = React3.createContext(defaultContext);
1339
+ const index = defaultContexts.length;
1340
+ defaultContexts = [...defaultContexts, defaultContext];
1341
+ const Provider = (props) => {
1342
+ const { scope, children, ...context } = props;
1343
+ const Context = scope?.[scopeName]?.[index] || BaseContext;
1344
+ const value = React3.useMemo(() => context, Object.values(context));
1345
+ return /* @__PURE__ */ jsx17(Context.Provider, { value, children });
1346
+ };
1347
+ Provider.displayName = rootComponentName + "Provider";
1348
+ function useContext22(consumerName, scope) {
1349
+ const Context = scope?.[scopeName]?.[index] || BaseContext;
1350
+ const context = React3.useContext(Context);
1351
+ if (context) return context;
1352
+ if (defaultContext !== void 0) return defaultContext;
1353
+ throw new Error(`\`${consumerName}\` must be used within \`${rootComponentName}\``);
1354
+ }
1355
+ return [Provider, useContext22];
1356
+ }
1357
+ const createScope = () => {
1358
+ const scopeContexts = defaultContexts.map((defaultContext) => {
1359
+ return React3.createContext(defaultContext);
1360
+ });
1361
+ return function useScope(scope) {
1362
+ const contexts = scope?.[scopeName] || scopeContexts;
1363
+ return React3.useMemo(
1364
+ () => ({ [`__scope${scopeName}`]: { ...scope, [scopeName]: contexts } }),
1365
+ [scope, contexts]
1366
+ );
1367
+ };
1368
+ };
1369
+ createScope.scopeName = scopeName;
1370
+ return [createContext32, composeContextScopes(createScope, ...createContextScopeDeps)];
1371
+ }
1372
+ function composeContextScopes(...scopes) {
1373
+ const baseScope = scopes[0];
1374
+ if (scopes.length === 1) return baseScope;
1375
+ const createScope = () => {
1376
+ const scopeHooks = scopes.map((createScope2) => ({
1377
+ useScope: createScope2(),
1378
+ scopeName: createScope2.scopeName
1379
+ }));
1380
+ return function useComposedScopes(overrideScopes) {
1381
+ const nextScopes = scopeHooks.reduce((nextScopes2, { useScope, scopeName }) => {
1382
+ const scopeProps = useScope(overrideScopes);
1383
+ const currentScope = scopeProps[`__scope${scopeName}`];
1384
+ return { ...nextScopes2, ...currentScope };
1385
+ }, {});
1386
+ return React3.useMemo(() => ({ [`__scope${baseScope.scopeName}`]: nextScopes }), [nextScopes]);
1387
+ };
1388
+ };
1389
+ createScope.scopeName = baseScope.scopeName;
1390
+ return createScope;
1391
+ }
1392
+
1393
+ // ../../node_modules/@radix-ui/react-use-controllable-state/dist/index.mjs
1394
+ import * as React5 from "react";
1395
+
1396
+ // ../../node_modules/@radix-ui/react-use-layout-effect/dist/index.mjs
1397
+ import * as React4 from "react";
1398
+ var useLayoutEffect2 = globalThis?.document ? React4.useLayoutEffect : () => {
1399
+ };
1400
+
1401
+ // ../../node_modules/@radix-ui/react-use-controllable-state/dist/index.mjs
1402
+ import * as React22 from "react";
1403
+ var useInsertionEffect = React5[" useInsertionEffect ".trim().toString()] || useLayoutEffect2;
1404
+ function useControllableState({
1405
+ prop,
1406
+ defaultProp,
1407
+ onChange = () => {
1408
+ },
1409
+ caller
1410
+ }) {
1411
+ const [uncontrolledProp, setUncontrolledProp, onChangeRef] = useUncontrolledState({
1412
+ defaultProp,
1413
+ onChange
1414
+ });
1415
+ const isControlled = prop !== void 0;
1416
+ const value = isControlled ? prop : uncontrolledProp;
1417
+ if (true) {
1418
+ const isControlledRef = React5.useRef(prop !== void 0);
1419
+ React5.useEffect(() => {
1420
+ const wasControlled = isControlledRef.current;
1421
+ if (wasControlled !== isControlled) {
1422
+ const from = wasControlled ? "controlled" : "uncontrolled";
1423
+ const to = isControlled ? "controlled" : "uncontrolled";
1424
+ console.warn(
1425
+ `${caller} is changing from ${from} to ${to}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`
1426
+ );
1427
+ }
1428
+ isControlledRef.current = isControlled;
1429
+ }, [isControlled, caller]);
1430
+ }
1431
+ const setValue = React5.useCallback(
1432
+ (nextValue) => {
1433
+ if (isControlled) {
1434
+ const value2 = isFunction(nextValue) ? nextValue(prop) : nextValue;
1435
+ if (value2 !== prop) {
1436
+ onChangeRef.current?.(value2);
1437
+ }
1438
+ } else {
1439
+ setUncontrolledProp(nextValue);
1440
+ }
1441
+ },
1442
+ [isControlled, prop, setUncontrolledProp, onChangeRef]
1443
+ );
1444
+ return [value, setValue];
1445
+ }
1446
+ function useUncontrolledState({
1447
+ defaultProp,
1448
+ onChange
1449
+ }) {
1450
+ const [value, setValue] = React5.useState(defaultProp);
1451
+ const prevValueRef = React5.useRef(value);
1452
+ const onChangeRef = React5.useRef(onChange);
1453
+ useInsertionEffect(() => {
1454
+ onChangeRef.current = onChange;
1455
+ }, [onChange]);
1456
+ React5.useEffect(() => {
1457
+ if (prevValueRef.current !== value) {
1458
+ onChangeRef.current?.(value);
1459
+ prevValueRef.current = value;
1460
+ }
1461
+ }, [value, prevValueRef]);
1462
+ return [value, setValue, onChangeRef];
1463
+ }
1464
+ function isFunction(value) {
1465
+ return typeof value === "function";
1466
+ }
1467
+ var SYNC_STATE = Symbol("RADIX:SYNC_STATE");
1468
+
1469
+ // ../../node_modules/@radix-ui/react-direction/dist/index.mjs
1470
+ import * as React6 from "react";
1471
+ import { jsx as jsx18 } from "react/jsx-runtime";
1472
+ var DirectionContext = React6.createContext(void 0);
1473
+ function useDirection(localDir) {
1474
+ const globalDir = React6.useContext(DirectionContext);
1475
+ return localDir || globalDir || "ltr";
1476
+ }
1477
+
1478
+ // ../../node_modules/@radix-ui/react-use-previous/dist/index.mjs
1479
+ import * as React7 from "react";
1480
+ function usePrevious(value) {
1481
+ const ref = React7.useRef({ value, previous: value });
1482
+ return React7.useMemo(() => {
1483
+ if (ref.current.value !== value) {
1484
+ ref.current.previous = ref.current.value;
1485
+ ref.current.value = value;
1486
+ }
1487
+ return ref.current.previous;
1488
+ }, [value]);
1489
+ }
1490
+
1491
+ // ../../node_modules/@radix-ui/react-use-size/dist/index.mjs
1492
+ import * as React8 from "react";
1493
+ function useSize(element) {
1494
+ const [size, setSize] = React8.useState(void 0);
1495
+ useLayoutEffect2(() => {
1496
+ if (element) {
1497
+ setSize({ width: element.offsetWidth, height: element.offsetHeight });
1498
+ const resizeObserver = new ResizeObserver((entries) => {
1499
+ if (!Array.isArray(entries)) {
1500
+ return;
1501
+ }
1502
+ if (!entries.length) {
1503
+ return;
1504
+ }
1505
+ const entry = entries[0];
1506
+ let width;
1507
+ let height;
1508
+ if ("borderBoxSize" in entry) {
1509
+ const borderSizeEntry = entry["borderBoxSize"];
1510
+ const borderSize = Array.isArray(borderSizeEntry) ? borderSizeEntry[0] : borderSizeEntry;
1511
+ width = borderSize["inlineSize"];
1512
+ height = borderSize["blockSize"];
1513
+ } else {
1514
+ width = element.offsetWidth;
1515
+ height = element.offsetHeight;
1516
+ }
1517
+ setSize({ width, height });
1518
+ });
1519
+ resizeObserver.observe(element, { box: "border-box" });
1520
+ return () => resizeObserver.unobserve(element);
1521
+ } else {
1522
+ setSize(void 0);
1523
+ }
1524
+ }, [element]);
1525
+ return size;
1526
+ }
1527
+
1528
+ // ../../node_modules/@radix-ui/react-primitive/dist/index.mjs
1529
+ import * as React9 from "react";
1530
+ import * as ReactDOM from "react-dom";
1531
+ import { createSlot } from "@radix-ui/react-slot";
1532
+ import { jsx as jsx19 } from "react/jsx-runtime";
1533
+ var NODES = [
1534
+ "a",
1535
+ "button",
1536
+ "div",
1537
+ "form",
1538
+ "h2",
1539
+ "h3",
1540
+ "img",
1541
+ "input",
1542
+ "label",
1543
+ "li",
1544
+ "nav",
1545
+ "ol",
1546
+ "p",
1547
+ "select",
1548
+ "span",
1549
+ "svg",
1550
+ "ul"
1551
+ ];
1552
+ var Primitive = NODES.reduce((primitive, node) => {
1553
+ const Slot2 = createSlot(`Primitive.${node}`);
1554
+ const Node2 = React9.forwardRef((props, forwardedRef) => {
1555
+ const { asChild, ...primitiveProps } = props;
1556
+ const Comp = asChild ? Slot2 : node;
1557
+ if (typeof window !== "undefined") {
1558
+ window[Symbol.for("radix-ui")] = true;
1559
+ }
1560
+ return /* @__PURE__ */ jsx19(Comp, { ...primitiveProps, ref: forwardedRef });
1561
+ });
1562
+ Node2.displayName = `Primitive.${node}`;
1563
+ return { ...primitive, [node]: Node2 };
1564
+ }, {});
1565
+
1566
+ // ../../node_modules/@radix-ui/react-collection/dist/index.mjs
1567
+ import React10 from "react";
1568
+ import { createSlot as createSlot2 } from "@radix-ui/react-slot";
1569
+ import { jsx as jsx20 } from "react/jsx-runtime";
1570
+ import React23 from "react";
1571
+ import { createSlot as createSlot22 } from "@radix-ui/react-slot";
1572
+ import { jsx as jsx22 } from "react/jsx-runtime";
1573
+ function createCollection(name) {
1574
+ const PROVIDER_NAME = name + "CollectionProvider";
1575
+ const [createCollectionContext, createCollectionScope2] = createContextScope(PROVIDER_NAME);
1576
+ const [CollectionProviderImpl, useCollectionContext] = createCollectionContext(
1577
+ PROVIDER_NAME,
1578
+ { collectionRef: { current: null }, itemMap: /* @__PURE__ */ new Map() }
1579
+ );
1580
+ const CollectionProvider = (props) => {
1581
+ const { scope, children } = props;
1582
+ const ref = React10.useRef(null);
1583
+ const itemMap = React10.useRef(/* @__PURE__ */ new Map()).current;
1584
+ return /* @__PURE__ */ jsx20(CollectionProviderImpl, { scope, itemMap, collectionRef: ref, children });
1585
+ };
1586
+ CollectionProvider.displayName = PROVIDER_NAME;
1587
+ const COLLECTION_SLOT_NAME = name + "CollectionSlot";
1588
+ const CollectionSlotImpl = createSlot2(COLLECTION_SLOT_NAME);
1589
+ const CollectionSlot = React10.forwardRef(
1590
+ (props, forwardedRef) => {
1591
+ const { scope, children } = props;
1592
+ const context = useCollectionContext(COLLECTION_SLOT_NAME, scope);
1593
+ const composedRefs = useComposedRefs(forwardedRef, context.collectionRef);
1594
+ return /* @__PURE__ */ jsx20(CollectionSlotImpl, { ref: composedRefs, children });
1595
+ }
1596
+ );
1597
+ CollectionSlot.displayName = COLLECTION_SLOT_NAME;
1598
+ const ITEM_SLOT_NAME = name + "CollectionItemSlot";
1599
+ const ITEM_DATA_ATTR = "data-radix-collection-item";
1600
+ const CollectionItemSlotImpl = createSlot2(ITEM_SLOT_NAME);
1601
+ const CollectionItemSlot = React10.forwardRef(
1602
+ (props, forwardedRef) => {
1603
+ const { scope, children, ...itemData } = props;
1604
+ const ref = React10.useRef(null);
1605
+ const composedRefs = useComposedRefs(forwardedRef, ref);
1606
+ const context = useCollectionContext(ITEM_SLOT_NAME, scope);
1607
+ React10.useEffect(() => {
1608
+ context.itemMap.set(ref, { ref, ...itemData });
1609
+ return () => void context.itemMap.delete(ref);
1610
+ });
1611
+ return /* @__PURE__ */ jsx20(CollectionItemSlotImpl, { ...{ [ITEM_DATA_ATTR]: "" }, ref: composedRefs, children });
1612
+ }
1613
+ );
1614
+ CollectionItemSlot.displayName = ITEM_SLOT_NAME;
1615
+ function useCollection2(scope) {
1616
+ const context = useCollectionContext(name + "CollectionConsumer", scope);
1617
+ const getItems = React10.useCallback(() => {
1618
+ const collectionNode = context.collectionRef.current;
1619
+ if (!collectionNode) return [];
1620
+ const orderedNodes = Array.from(collectionNode.querySelectorAll(`[${ITEM_DATA_ATTR}]`));
1621
+ const items = Array.from(context.itemMap.values());
1622
+ const orderedItems = items.sort(
1623
+ (a, b) => orderedNodes.indexOf(a.ref.current) - orderedNodes.indexOf(b.ref.current)
1624
+ );
1625
+ return orderedItems;
1626
+ }, [context.collectionRef, context.itemMap]);
1627
+ return getItems;
1628
+ }
1629
+ return [
1630
+ { Provider: CollectionProvider, Slot: CollectionSlot, ItemSlot: CollectionItemSlot },
1631
+ useCollection2,
1632
+ createCollectionScope2
1633
+ ];
1634
+ }
1635
+
1636
+ // ../../node_modules/@radix-ui/react-slider/dist/index.mjs
1637
+ import { jsx as jsx21, jsxs as jsxs10 } from "react/jsx-runtime";
1638
+ var PAGE_KEYS = ["PageUp", "PageDown"];
1639
+ var ARROW_KEYS = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"];
1640
+ var BACK_KEYS = {
1641
+ "from-left": ["Home", "PageDown", "ArrowDown", "ArrowLeft"],
1642
+ "from-right": ["Home", "PageDown", "ArrowDown", "ArrowRight"],
1643
+ "from-bottom": ["Home", "PageDown", "ArrowDown", "ArrowLeft"],
1644
+ "from-top": ["Home", "PageDown", "ArrowUp", "ArrowLeft"]
1645
+ };
1646
+ var SLIDER_NAME = "Slider";
1647
+ var [Collection, useCollection, createCollectionScope] = createCollection(SLIDER_NAME);
1648
+ var [createSliderContext, createSliderScope] = createContextScope(SLIDER_NAME, [
1649
+ createCollectionScope
1650
+ ]);
1651
+ var [SliderProvider, useSliderContext] = createSliderContext(SLIDER_NAME);
1652
+ var Slider = React11.forwardRef(
1653
+ (props, forwardedRef) => {
1654
+ const {
1655
+ name,
1656
+ min = 0,
1657
+ max = 100,
1658
+ step = 1,
1659
+ orientation = "horizontal",
1660
+ disabled = false,
1661
+ minStepsBetweenThumbs = 0,
1662
+ defaultValue = [min],
1663
+ value,
1664
+ onValueChange = () => {
1665
+ },
1666
+ onValueCommit = () => {
1667
+ },
1668
+ inverted = false,
1669
+ form,
1670
+ ...sliderProps
1671
+ } = props;
1672
+ const thumbRefs = React11.useRef(/* @__PURE__ */ new Set());
1673
+ const valueIndexToChangeRef = React11.useRef(0);
1674
+ const isHorizontal = orientation === "horizontal";
1675
+ const SliderOrientation = isHorizontal ? SliderHorizontal : SliderVertical;
1676
+ const [values = [], setValues] = useControllableState({
1677
+ prop: value,
1678
+ defaultProp: defaultValue,
1679
+ onChange: (value2) => {
1680
+ const thumbs = [...thumbRefs.current];
1681
+ thumbs[valueIndexToChangeRef.current]?.focus();
1682
+ onValueChange(value2);
1683
+ }
1684
+ });
1685
+ const valuesBeforeSlideStartRef = React11.useRef(values);
1686
+ function handleSlideStart(value2) {
1687
+ const closestIndex = getClosestValueIndex(values, value2);
1688
+ updateValues(value2, closestIndex);
1689
+ }
1690
+ function handleSlideMove(value2) {
1691
+ updateValues(value2, valueIndexToChangeRef.current);
1692
+ }
1693
+ function handleSlideEnd() {
1694
+ const prevValue = valuesBeforeSlideStartRef.current[valueIndexToChangeRef.current];
1695
+ const nextValue = values[valueIndexToChangeRef.current];
1696
+ const hasChanged = nextValue !== prevValue;
1697
+ if (hasChanged) onValueCommit(values);
1698
+ }
1699
+ function updateValues(value2, atIndex, { commit } = { commit: false }) {
1700
+ const decimalCount = getDecimalCount(step);
1701
+ const snapToStep = roundValue(Math.round((value2 - min) / step) * step + min, decimalCount);
1702
+ const nextValue = clamp(snapToStep, [min, max]);
1703
+ setValues((prevValues = []) => {
1704
+ const nextValues = getNextSortedValues(prevValues, nextValue, atIndex);
1705
+ if (hasMinStepsBetweenValues(nextValues, minStepsBetweenThumbs * step)) {
1706
+ valueIndexToChangeRef.current = nextValues.indexOf(nextValue);
1707
+ const hasChanged = String(nextValues) !== String(prevValues);
1708
+ if (hasChanged && commit) onValueCommit(nextValues);
1709
+ return hasChanged ? nextValues : prevValues;
1710
+ } else {
1711
+ return prevValues;
1712
+ }
1713
+ });
1714
+ }
1715
+ return /* @__PURE__ */ jsx21(
1716
+ SliderProvider,
1717
+ {
1718
+ scope: props.__scopeSlider,
1719
+ name,
1720
+ disabled,
1721
+ min,
1722
+ max,
1723
+ valueIndexToChangeRef,
1724
+ thumbs: thumbRefs.current,
1725
+ values,
1726
+ orientation,
1727
+ form,
1728
+ children: /* @__PURE__ */ jsx21(Collection.Provider, { scope: props.__scopeSlider, children: /* @__PURE__ */ jsx21(Collection.Slot, { scope: props.__scopeSlider, children: /* @__PURE__ */ jsx21(
1729
+ SliderOrientation,
1730
+ {
1731
+ "aria-disabled": disabled,
1732
+ "data-disabled": disabled ? "" : void 0,
1733
+ ...sliderProps,
1734
+ ref: forwardedRef,
1735
+ onPointerDown: composeEventHandlers(sliderProps.onPointerDown, () => {
1736
+ if (!disabled) valuesBeforeSlideStartRef.current = values;
1737
+ }),
1738
+ min,
1739
+ max,
1740
+ inverted,
1741
+ onSlideStart: disabled ? void 0 : handleSlideStart,
1742
+ onSlideMove: disabled ? void 0 : handleSlideMove,
1743
+ onSlideEnd: disabled ? void 0 : handleSlideEnd,
1744
+ onHomeKeyDown: () => !disabled && updateValues(min, 0, { commit: true }),
1745
+ onEndKeyDown: () => !disabled && updateValues(max, values.length - 1, { commit: true }),
1746
+ onStepKeyDown: ({ event, direction: stepDirection }) => {
1747
+ if (!disabled) {
1748
+ const isPageKey = PAGE_KEYS.includes(event.key);
1749
+ const isSkipKey = isPageKey || event.shiftKey && ARROW_KEYS.includes(event.key);
1750
+ const multiplier = isSkipKey ? 10 : 1;
1751
+ const atIndex = valueIndexToChangeRef.current;
1752
+ const value2 = values[atIndex];
1753
+ const stepInDirection = step * multiplier * stepDirection;
1754
+ updateValues(value2 + stepInDirection, atIndex, { commit: true });
1755
+ }
1756
+ }
1757
+ }
1758
+ ) }) })
1759
+ }
1760
+ );
1761
+ }
1762
+ );
1763
+ Slider.displayName = SLIDER_NAME;
1764
+ var [SliderOrientationProvider, useSliderOrientationContext] = createSliderContext(SLIDER_NAME, {
1765
+ startEdge: "left",
1766
+ endEdge: "right",
1767
+ size: "width",
1768
+ direction: 1
1769
+ });
1770
+ var SliderHorizontal = React11.forwardRef(
1771
+ (props, forwardedRef) => {
1772
+ const {
1773
+ min,
1774
+ max,
1775
+ dir,
1776
+ inverted,
1777
+ onSlideStart,
1778
+ onSlideMove,
1779
+ onSlideEnd,
1780
+ onStepKeyDown,
1781
+ ...sliderProps
1782
+ } = props;
1783
+ const [slider, setSlider] = React11.useState(null);
1784
+ const composedRefs = useComposedRefs(forwardedRef, (node) => setSlider(node));
1785
+ const rectRef = React11.useRef(void 0);
1786
+ const direction = useDirection(dir);
1787
+ const isDirectionLTR = direction === "ltr";
1788
+ const isSlidingFromLeft = isDirectionLTR && !inverted || !isDirectionLTR && inverted;
1789
+ function getValueFromPointer(pointerPosition) {
1790
+ const rect = rectRef.current || slider.getBoundingClientRect();
1791
+ const input = [0, rect.width];
1792
+ const output = isSlidingFromLeft ? [min, max] : [max, min];
1793
+ const value = linearScale(input, output);
1794
+ rectRef.current = rect;
1795
+ return value(pointerPosition - rect.left);
1796
+ }
1797
+ return /* @__PURE__ */ jsx21(
1798
+ SliderOrientationProvider,
1799
+ {
1800
+ scope: props.__scopeSlider,
1801
+ startEdge: isSlidingFromLeft ? "left" : "right",
1802
+ endEdge: isSlidingFromLeft ? "right" : "left",
1803
+ direction: isSlidingFromLeft ? 1 : -1,
1804
+ size: "width",
1805
+ children: /* @__PURE__ */ jsx21(
1806
+ SliderImpl,
1807
+ {
1808
+ dir: direction,
1809
+ "data-orientation": "horizontal",
1810
+ ...sliderProps,
1811
+ ref: composedRefs,
1812
+ style: {
1813
+ ...sliderProps.style,
1814
+ ["--radix-slider-thumb-transform"]: "translateX(-50%)"
1815
+ },
1816
+ onSlideStart: (event) => {
1817
+ const value = getValueFromPointer(event.clientX);
1818
+ onSlideStart?.(value);
1819
+ },
1820
+ onSlideMove: (event) => {
1821
+ const value = getValueFromPointer(event.clientX);
1822
+ onSlideMove?.(value);
1823
+ },
1824
+ onSlideEnd: () => {
1825
+ rectRef.current = void 0;
1826
+ onSlideEnd?.();
1827
+ },
1828
+ onStepKeyDown: (event) => {
1829
+ const slideDirection = isSlidingFromLeft ? "from-left" : "from-right";
1830
+ const isBackKey = BACK_KEYS[slideDirection].includes(event.key);
1831
+ onStepKeyDown?.({ event, direction: isBackKey ? -1 : 1 });
1832
+ }
1833
+ }
1834
+ )
1835
+ }
1836
+ );
1837
+ }
1838
+ );
1839
+ var SliderVertical = React11.forwardRef(
1840
+ (props, forwardedRef) => {
1841
+ const {
1842
+ min,
1843
+ max,
1844
+ inverted,
1845
+ onSlideStart,
1846
+ onSlideMove,
1847
+ onSlideEnd,
1848
+ onStepKeyDown,
1849
+ ...sliderProps
1850
+ } = props;
1851
+ const sliderRef = React11.useRef(null);
1852
+ const ref = useComposedRefs(forwardedRef, sliderRef);
1853
+ const rectRef = React11.useRef(void 0);
1854
+ const isSlidingFromBottom = !inverted;
1855
+ function getValueFromPointer(pointerPosition) {
1856
+ const rect = rectRef.current || sliderRef.current.getBoundingClientRect();
1857
+ const input = [0, rect.height];
1858
+ const output = isSlidingFromBottom ? [max, min] : [min, max];
1859
+ const value = linearScale(input, output);
1860
+ rectRef.current = rect;
1861
+ return value(pointerPosition - rect.top);
1862
+ }
1863
+ return /* @__PURE__ */ jsx21(
1864
+ SliderOrientationProvider,
1865
+ {
1866
+ scope: props.__scopeSlider,
1867
+ startEdge: isSlidingFromBottom ? "bottom" : "top",
1868
+ endEdge: isSlidingFromBottom ? "top" : "bottom",
1869
+ size: "height",
1870
+ direction: isSlidingFromBottom ? 1 : -1,
1871
+ children: /* @__PURE__ */ jsx21(
1872
+ SliderImpl,
1873
+ {
1874
+ "data-orientation": "vertical",
1875
+ ...sliderProps,
1876
+ ref,
1877
+ style: {
1878
+ ...sliderProps.style,
1879
+ ["--radix-slider-thumb-transform"]: "translateY(50%)"
1880
+ },
1881
+ onSlideStart: (event) => {
1882
+ const value = getValueFromPointer(event.clientY);
1883
+ onSlideStart?.(value);
1884
+ },
1885
+ onSlideMove: (event) => {
1886
+ const value = getValueFromPointer(event.clientY);
1887
+ onSlideMove?.(value);
1888
+ },
1889
+ onSlideEnd: () => {
1890
+ rectRef.current = void 0;
1891
+ onSlideEnd?.();
1892
+ },
1893
+ onStepKeyDown: (event) => {
1894
+ const slideDirection = isSlidingFromBottom ? "from-bottom" : "from-top";
1895
+ const isBackKey = BACK_KEYS[slideDirection].includes(event.key);
1896
+ onStepKeyDown?.({ event, direction: isBackKey ? -1 : 1 });
1897
+ }
1898
+ }
1899
+ )
1900
+ }
1901
+ );
1902
+ }
1903
+ );
1904
+ var SliderImpl = React11.forwardRef(
1905
+ (props, forwardedRef) => {
1906
+ const {
1907
+ __scopeSlider,
1908
+ onSlideStart,
1909
+ onSlideMove,
1910
+ onSlideEnd,
1911
+ onHomeKeyDown,
1912
+ onEndKeyDown,
1913
+ onStepKeyDown,
1914
+ ...sliderProps
1915
+ } = props;
1916
+ const context = useSliderContext(SLIDER_NAME, __scopeSlider);
1917
+ return /* @__PURE__ */ jsx21(
1918
+ Primitive.span,
1919
+ {
1920
+ ...sliderProps,
1921
+ ref: forwardedRef,
1922
+ onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {
1923
+ if (event.key === "Home") {
1924
+ onHomeKeyDown(event);
1925
+ event.preventDefault();
1926
+ } else if (event.key === "End") {
1927
+ onEndKeyDown(event);
1928
+ event.preventDefault();
1929
+ } else if (PAGE_KEYS.concat(ARROW_KEYS).includes(event.key)) {
1930
+ onStepKeyDown(event);
1931
+ event.preventDefault();
1932
+ }
1933
+ }),
1934
+ onPointerDown: composeEventHandlers(props.onPointerDown, (event) => {
1935
+ const target = event.target;
1936
+ target.setPointerCapture(event.pointerId);
1937
+ event.preventDefault();
1938
+ if (context.thumbs.has(target)) {
1939
+ target.focus();
1940
+ } else {
1941
+ onSlideStart(event);
1942
+ }
1943
+ }),
1944
+ onPointerMove: composeEventHandlers(props.onPointerMove, (event) => {
1945
+ const target = event.target;
1946
+ if (target.hasPointerCapture(event.pointerId)) onSlideMove(event);
1947
+ }),
1948
+ onPointerUp: composeEventHandlers(props.onPointerUp, (event) => {
1949
+ const target = event.target;
1950
+ if (target.hasPointerCapture(event.pointerId)) {
1951
+ target.releasePointerCapture(event.pointerId);
1952
+ onSlideEnd(event);
1953
+ }
1954
+ })
1955
+ }
1956
+ );
1957
+ }
1958
+ );
1959
+ var TRACK_NAME = "SliderTrack";
1960
+ var SliderTrack = React11.forwardRef(
1961
+ (props, forwardedRef) => {
1962
+ const { __scopeSlider, ...trackProps } = props;
1963
+ const context = useSliderContext(TRACK_NAME, __scopeSlider);
1964
+ return /* @__PURE__ */ jsx21(
1965
+ Primitive.span,
1966
+ {
1967
+ "data-disabled": context.disabled ? "" : void 0,
1968
+ "data-orientation": context.orientation,
1969
+ ...trackProps,
1970
+ ref: forwardedRef
1971
+ }
1972
+ );
1973
+ }
1974
+ );
1975
+ SliderTrack.displayName = TRACK_NAME;
1976
+ var RANGE_NAME = "SliderRange";
1977
+ var SliderRange = React11.forwardRef(
1978
+ (props, forwardedRef) => {
1979
+ const { __scopeSlider, ...rangeProps } = props;
1980
+ const context = useSliderContext(RANGE_NAME, __scopeSlider);
1981
+ const orientation = useSliderOrientationContext(RANGE_NAME, __scopeSlider);
1982
+ const ref = React11.useRef(null);
1983
+ const composedRefs = useComposedRefs(forwardedRef, ref);
1984
+ const valuesCount = context.values.length;
1985
+ const percentages = context.values.map(
1986
+ (value) => convertValueToPercentage(value, context.min, context.max)
1987
+ );
1988
+ const offsetStart = valuesCount > 1 ? Math.min(...percentages) : 0;
1989
+ const offsetEnd = 100 - Math.max(...percentages);
1990
+ return /* @__PURE__ */ jsx21(
1991
+ Primitive.span,
1992
+ {
1993
+ "data-orientation": context.orientation,
1994
+ "data-disabled": context.disabled ? "" : void 0,
1995
+ ...rangeProps,
1996
+ ref: composedRefs,
1997
+ style: {
1998
+ ...props.style,
1999
+ [orientation.startEdge]: offsetStart + "%",
2000
+ [orientation.endEdge]: offsetEnd + "%"
2001
+ }
2002
+ }
2003
+ );
2004
+ }
2005
+ );
2006
+ SliderRange.displayName = RANGE_NAME;
2007
+ var THUMB_NAME = "SliderThumb";
2008
+ var SliderThumb = React11.forwardRef(
2009
+ (props, forwardedRef) => {
2010
+ const getItems = useCollection(props.__scopeSlider);
2011
+ const [thumb, setThumb] = React11.useState(null);
2012
+ const composedRefs = useComposedRefs(forwardedRef, (node) => setThumb(node));
2013
+ const index = React11.useMemo(
2014
+ () => thumb ? getItems().findIndex((item) => item.ref.current === thumb) : -1,
2015
+ [getItems, thumb]
2016
+ );
2017
+ return /* @__PURE__ */ jsx21(SliderThumbImpl, { ...props, ref: composedRefs, index });
2018
+ }
2019
+ );
2020
+ var SliderThumbImpl = React11.forwardRef(
2021
+ (props, forwardedRef) => {
2022
+ const { __scopeSlider, index, name, ...thumbProps } = props;
2023
+ const context = useSliderContext(THUMB_NAME, __scopeSlider);
2024
+ const orientation = useSliderOrientationContext(THUMB_NAME, __scopeSlider);
2025
+ const [thumb, setThumb] = React11.useState(null);
2026
+ const composedRefs = useComposedRefs(forwardedRef, (node) => setThumb(node));
2027
+ const isFormControl = thumb ? context.form || !!thumb.closest("form") : true;
2028
+ const size = useSize(thumb);
2029
+ const value = context.values[index];
2030
+ const percent = value === void 0 ? 0 : convertValueToPercentage(value, context.min, context.max);
2031
+ const label = getLabel(index, context.values.length);
2032
+ const orientationSize = size?.[orientation.size];
2033
+ const thumbInBoundsOffset = orientationSize ? getThumbInBoundsOffset(orientationSize, percent, orientation.direction) : 0;
2034
+ React11.useEffect(() => {
2035
+ if (thumb) {
2036
+ context.thumbs.add(thumb);
2037
+ return () => {
2038
+ context.thumbs.delete(thumb);
2039
+ };
2040
+ }
2041
+ }, [thumb, context.thumbs]);
2042
+ return /* @__PURE__ */ jsxs10(
2043
+ "span",
2044
+ {
2045
+ style: {
2046
+ transform: "var(--radix-slider-thumb-transform)",
2047
+ position: "absolute",
2048
+ [orientation.startEdge]: `calc(${percent}% + ${thumbInBoundsOffset}px)`
2049
+ },
2050
+ children: [
2051
+ /* @__PURE__ */ jsx21(Collection.ItemSlot, { scope: props.__scopeSlider, children: /* @__PURE__ */ jsx21(
2052
+ Primitive.span,
2053
+ {
2054
+ role: "slider",
2055
+ "aria-label": props["aria-label"] || label,
2056
+ "aria-valuemin": context.min,
2057
+ "aria-valuenow": value,
2058
+ "aria-valuemax": context.max,
2059
+ "aria-orientation": context.orientation,
2060
+ "data-orientation": context.orientation,
2061
+ "data-disabled": context.disabled ? "" : void 0,
2062
+ tabIndex: context.disabled ? void 0 : 0,
2063
+ ...thumbProps,
2064
+ ref: composedRefs,
2065
+ style: value === void 0 ? { display: "none" } : props.style,
2066
+ onFocus: composeEventHandlers(props.onFocus, () => {
2067
+ context.valueIndexToChangeRef.current = index;
2068
+ })
2069
+ }
2070
+ ) }),
2071
+ isFormControl && /* @__PURE__ */ jsx21(
2072
+ SliderBubbleInput,
2073
+ {
2074
+ name: name ?? (context.name ? context.name + (context.values.length > 1 ? "[]" : "") : void 0),
2075
+ form: context.form,
2076
+ value
2077
+ },
2078
+ index
2079
+ )
2080
+ ]
2081
+ }
2082
+ );
2083
+ }
2084
+ );
2085
+ SliderThumb.displayName = THUMB_NAME;
2086
+ var BUBBLE_INPUT_NAME = "RadioBubbleInput";
2087
+ var SliderBubbleInput = React11.forwardRef(
2088
+ ({ __scopeSlider, value, ...props }, forwardedRef) => {
2089
+ const ref = React11.useRef(null);
2090
+ const composedRefs = useComposedRefs(ref, forwardedRef);
2091
+ const prevValue = usePrevious(value);
2092
+ React11.useEffect(() => {
2093
+ const input = ref.current;
2094
+ if (!input) return;
2095
+ const inputProto = window.HTMLInputElement.prototype;
2096
+ const descriptor = Object.getOwnPropertyDescriptor(inputProto, "value");
2097
+ const setValue = descriptor.set;
2098
+ if (prevValue !== value && setValue) {
2099
+ const event = new Event("input", { bubbles: true });
2100
+ setValue.call(input, value);
2101
+ input.dispatchEvent(event);
2102
+ }
2103
+ }, [prevValue, value]);
2104
+ return /* @__PURE__ */ jsx21(
2105
+ Primitive.input,
2106
+ {
2107
+ style: { display: "none" },
2108
+ ...props,
2109
+ ref: composedRefs,
2110
+ defaultValue: value
2111
+ }
2112
+ );
2113
+ }
2114
+ );
2115
+ SliderBubbleInput.displayName = BUBBLE_INPUT_NAME;
2116
+ function getNextSortedValues(prevValues = [], nextValue, atIndex) {
2117
+ const nextValues = [...prevValues];
2118
+ nextValues[atIndex] = nextValue;
2119
+ return nextValues.sort((a, b) => a - b);
2120
+ }
2121
+ function convertValueToPercentage(value, min, max) {
2122
+ const maxSteps = max - min;
2123
+ const percentPerStep = 100 / maxSteps;
2124
+ const percentage = percentPerStep * (value - min);
2125
+ return clamp(percentage, [0, 100]);
2126
+ }
2127
+ function getLabel(index, totalValues) {
2128
+ if (totalValues > 2) {
2129
+ return `Value ${index + 1} of ${totalValues}`;
2130
+ } else if (totalValues === 2) {
2131
+ return ["Minimum", "Maximum"][index];
2132
+ } else {
2133
+ return void 0;
2134
+ }
2135
+ }
2136
+ function getClosestValueIndex(values, nextValue) {
2137
+ if (values.length === 1) return 0;
2138
+ const distances = values.map((value) => Math.abs(value - nextValue));
2139
+ const closestDistance = Math.min(...distances);
2140
+ return distances.indexOf(closestDistance);
2141
+ }
2142
+ function getThumbInBoundsOffset(width, left, direction) {
2143
+ const halfWidth = width / 2;
2144
+ const halfPercent = 50;
2145
+ const offset = linearScale([0, halfPercent], [0, halfWidth]);
2146
+ return (halfWidth - offset(left) * direction) * direction;
2147
+ }
2148
+ function getStepsBetweenValues(values) {
2149
+ return values.slice(0, -1).map((value, index) => values[index + 1] - value);
2150
+ }
2151
+ function hasMinStepsBetweenValues(values, minStepsBetweenValues) {
2152
+ if (minStepsBetweenValues > 0) {
2153
+ const stepsBetweenValues = getStepsBetweenValues(values);
2154
+ const actualMinStepsBetweenValues = Math.min(...stepsBetweenValues);
2155
+ return actualMinStepsBetweenValues >= minStepsBetweenValues;
2156
+ }
2157
+ return true;
2158
+ }
2159
+ function linearScale(input, output) {
2160
+ return (value) => {
2161
+ if (input[0] === input[1] || output[0] === output[1]) return output[0];
2162
+ const ratio = (output[1] - output[0]) / (input[1] - input[0]);
2163
+ return output[0] + ratio * (value - input[0]);
2164
+ };
2165
+ }
2166
+ function getDecimalCount(value) {
2167
+ return (String(value).split(".")[1] || "").length;
2168
+ }
2169
+ function roundValue(value, decimalCount) {
2170
+ const rounder = Math.pow(10, decimalCount);
2171
+ return Math.round(value * rounder) / rounder;
2172
+ }
2173
+ var Root5 = Slider;
2174
+ var Track = SliderTrack;
2175
+ var Range = SliderRange;
2176
+ var Thumb2 = SliderThumb;
2177
+
2178
+ // ../ui/src/lib/utils.ts
2179
+ import { clsx as clsx2 } from "clsx";
2180
+ import { twMerge as twMerge2 } from "tailwind-merge";
2181
+ function cn2(...inputs) {
2182
+ return twMerge2(clsx2(inputs));
2183
+ }
2184
+
2185
+ // src/ui/slider.tsx
2186
+ import { jsx as jsx23, jsxs as jsxs11 } from "react/jsx-runtime";
2187
+ function Slider2({
2188
+ className,
2189
+ defaultValue,
2190
+ value,
2191
+ min = 0,
2192
+ max = 100,
2193
+ ...props
2194
+ }) {
2195
+ const _values = React12.useMemo(
2196
+ () => Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min, max],
2197
+ [value, defaultValue, min, max]
2198
+ );
2199
+ return /* @__PURE__ */ jsxs11(
2200
+ Root5,
2201
+ {
2202
+ "data-slot": "slider",
2203
+ defaultValue,
2204
+ value,
2205
+ min,
2206
+ max,
2207
+ className: cn2(
2208
+ "relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
2209
+ className
2210
+ ),
2211
+ ...props,
2212
+ children: [
2213
+ /* @__PURE__ */ jsx23(
2214
+ Track,
2215
+ {
2216
+ "data-slot": "slider-track",
2217
+ className: cn2(
2218
+ "bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"
2219
+ ),
2220
+ children: /* @__PURE__ */ jsx23(
2221
+ Range,
2222
+ {
2223
+ "data-slot": "slider-range",
2224
+ className: cn2("bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full")
2225
+ }
2226
+ )
2227
+ }
2228
+ ),
2229
+ Array.from({ length: _values.length }, (_, index) => /* @__PURE__ */ jsx23(
2230
+ Thumb2,
2231
+ {
2232
+ "data-slot": "slider-thumb",
2233
+ className: "border-primary bg-background ring-ring/50 block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
2234
+ },
2235
+ index
2236
+ ))
2237
+ ]
2238
+ }
2239
+ );
2240
+ }
2241
+
2242
+ // src/components/CreditCardTab/Points/PointsSelector.tsx
2243
+ import { jsx as jsx24, jsxs as jsxs12 } from "react/jsx-runtime";
2244
+ var PointsSelector = (props) => {
2245
+ const { isSelected, onSelect, children } = props;
2246
+ const { balance } = useSlapiBalance();
2247
+ const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
2248
+ const { appProps, staticConfig } = useStaticConfig();
2249
+ const min = 0;
2250
+ const max = Math.min((appProps.amount ?? 0) * staticConfig.pointsConversionRatio, balance?.availablePoints ?? 0);
2251
+ const step = 10;
2252
+ const [splitTokens, setSplitTokens] = useState8(0);
2253
+ const splitAmount = getSplitAmount(appProps.amount ?? 0, splitTokens, staticConfig.pointsConversionRatio);
2254
+ const handleCommit = (value) => {
2255
+ setSelectedPaymentMethod({ ...selectedPaymentMethod, splitAmount: value });
2256
+ };
2257
+ return /* @__PURE__ */ jsxs12(
2258
+ "button",
2259
+ {
2260
+ onClick: onSelect,
2261
+ className: cn("bg-primary/8 cursor-pointer overflow-hidden rounded-md border-1 border-transparent", {
2262
+ "border-primary": isSelected
2263
+ }),
2264
+ children: [
2265
+ /* @__PURE__ */ jsxs12("div", { className: cn("flex h-11 w-full", { "bg-black/4": isSelected }), children: [
2266
+ /* @__PURE__ */ jsx24(
2267
+ "div",
2268
+ {
2269
+ className: cn("flex h-full w-11 items-center justify-center bg-black/10", {
2270
+ "bg-primary": isSelected
2271
+ }),
2272
+ children: /* @__PURE__ */ jsx24("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-white", children: isSelected && /* @__PURE__ */ jsx24("div", { className: "bg-primary h-2.5 w-2.5 rounded-full" }) })
2273
+ }
2274
+ ),
2275
+ /* @__PURE__ */ jsx24("div", { className: "flex h-full w-full items-center justify-between gap-3 px-3", children })
2276
+ ] }),
2277
+ isSelected && /* @__PURE__ */ jsx24("div", { className: "px-3 pt-6 pb-2 md:px-4", children: /* @__PURE__ */ jsxs12("div", { className: "flex justify-between gap-3", children: [
2278
+ /* @__PURE__ */ jsxs12("div", { className: "flex max-w-[100px] flex-col gap-1", children: [
2279
+ /* @__PURE__ */ jsx24(Input, { readOnly: true, value: splitTokens, className: "bg-white text-center font-medium" }),
2280
+ /* @__PURE__ */ jsx24("p", { className: "text-left text-xs leading-[20px] text-black/45", children: "Points" })
2281
+ ] }),
2282
+ /* @__PURE__ */ jsx24("div", { className: "flex w-full items-center pb-6", children: /* @__PURE__ */ jsx24(
2283
+ Slider2,
2284
+ {
2285
+ value: [splitTokens],
2286
+ onValueCommit: ([v]) => handleCommit(v),
2287
+ onValueChange: ([v]) => setSplitTokens(v),
2288
+ min,
2289
+ max,
2290
+ step
2291
+ }
2292
+ ) }),
2293
+ /* @__PURE__ */ jsxs12("div", { className: "flex max-w-[100px] flex-col gap-1", children: [
2294
+ /* @__PURE__ */ jsx24(
2295
+ Input,
2296
+ {
2297
+ readOnly: true,
2298
+ value: formatUSD(splitAmount + getTransactionFee(splitAmount, appProps.transactionFeePercentage)),
2299
+ className: "bg-white text-center font-medium"
2300
+ }
2301
+ ),
2302
+ /* @__PURE__ */ jsx24("p", { className: "text-left text-xs leading-[20px] text-black/45", children: "Card" })
2303
+ ] })
2304
+ ] }) })
2305
+ ]
2306
+ }
2307
+ );
2308
+ };
2309
+
2310
+ // src/components/CreditCardTab/Points/SplitBlock.tsx
2311
+ import { jsx as jsx25, jsxs as jsxs13 } from "react/jsx-runtime";
2312
+ var SplitBlock = (props) => {
2313
+ const { isSelected, onSelect } = props;
2314
+ const { balance, isBalanceLoading } = useSlapiBalance();
2315
+ const { spreePayConfig } = useSpreePayConfig();
2316
+ const [address, setAddress] = useState9(null);
2317
+ const { staticConfig } = useStaticConfig();
2318
+ const { pointsConversionRatio, pointsTitle } = staticConfig;
2319
+ const initWallet = useCallback4(async (pointsChain) => {
2320
+ if (!pointsChain) {
2321
+ return;
2322
+ }
2323
+ try {
2324
+ const res = await getAirWallet({
2325
+ mocaChain: pointsChain.mocaChain,
2326
+ partnerId: pointsChain.partnerId
2327
+ });
2328
+ setAddress(res.address ?? null);
2329
+ } catch (e) {
2330
+ console.error("Air Wallet init failed:", e);
2331
+ }
2332
+ }, []);
2333
+ useEffect6(() => {
2334
+ initWallet(spreePayConfig?.pointsChain);
2335
+ }, [spreePayConfig, initWallet]);
2336
+ return /* @__PURE__ */ jsx25("div", { className: "flex flex-col gap-1", children: /* @__PURE__ */ jsxs13(PointsSelector, { onSelect: () => onSelect("air"), isSelected, children: [
2337
+ /* @__PURE__ */ jsx25("div", { className: "flex items-center gap-2", children: balance?.availablePoints ? /* @__PURE__ */ jsxs13("p", { className: "text-sm font-medium text-black", children: [
2338
+ /* @__PURE__ */ jsx25("span", { className: "text-black/50", children: "Available" }),
2339
+ " ",
2340
+ formatPoints(balance.availablePoints, pointsTitle),
2341
+ " ",
2342
+ /* @__PURE__ */ jsx25("span", { className: "text-black/50", children: formatUSD(balance.availablePoints / pointsConversionRatio) })
2343
+ ] }) : null }),
2344
+ isBalanceLoading ? /* @__PURE__ */ jsx25("div", { className: "h-4 w-6 animate-pulse bg-gray-200" }) : !balance?.availablePoints && /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-black", children: "No points available" }),
2345
+ address && /* @__PURE__ */ jsx25("div", { className: "text-sm font-medium text-black", children: address.length > 8 ? `${address.slice(0, 4)}...${address.slice(-4)}` : address })
2346
+ ] }) });
2347
+ };
2348
+
2349
+ // src/components/CreditCardTab/Points/Points.tsx
2350
+ import { Fragment as Fragment3, jsx as jsx26, jsxs as jsxs14 } from "react/jsx-runtime";
2351
+ var Points = () => {
2352
+ const [usePoints, setUsePoints] = useState10(false);
2353
+ const [selectedPointsType, setSelectedPointsType] = useState10(null);
2354
+ const { setSelectedPaymentMethod, selectedPaymentMethod } = useSpreePaymentMethod();
2355
+ const { spreePayConfig } = useSpreePayConfig();
2356
+ const handleTogglePoints = (enabled) => {
2357
+ setUsePoints(enabled);
2358
+ if (!enabled) {
2359
+ setSelectedPointsType(null);
2360
+ setSelectedPaymentMethod({ ...selectedPaymentMethod, splitAmount: void 0 });
2361
+ }
2362
+ };
2363
+ return /* @__PURE__ */ jsxs14(Fragment3, { children: [
2364
+ /* @__PURE__ */ jsx26(PointsSwitch, { disabled: !spreePayConfig?.creditCard.enabled, value: usePoints, onChange: handleTogglePoints }),
2365
+ usePoints && /* @__PURE__ */ jsx26(SplitBlock, { isSelected: selectedPointsType === "air", onSelect: setSelectedPointsType })
2366
+ ] });
2367
+ };
2368
+
2369
+ // src/components/CreditCardTab/CreditCardTab.tsx
2370
+ import { jsx as jsx27, jsxs as jsxs15 } from "react/jsx-runtime";
2371
+ var CreditCardTab = () => {
2372
+ const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
2373
+ const { register } = useSpreePayRegister();
2374
+ const { mutateCards } = useCards();
2375
+ const { cardPayment } = useCardPayment();
2376
+ const { splitPayment } = useSplitCardPayments();
2377
+ const handlePay = useCallback5(
2378
+ async (data) => {
2379
+ try {
2380
+ if (selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && selectedPaymentMethod.method) {
2381
+ let res = null;
2382
+ if (selectedPaymentMethod.splitAmount && selectedPaymentMethod.splitAmount > 0) {
2383
+ res = await splitPayment({ ...data, points: selectedPaymentMethod.splitAmount });
2384
+ } else {
2385
+ res = await cardPayment(data);
2386
+ }
2387
+ if (["AUTHORIZED" /* AUTHORIZED */, "CAPTURED" /* CAPTURED */].includes(res.status)) {
2388
+ return Promise.resolve(res);
2389
+ }
2390
+ return Promise.reject(new PaymentError("Card payment failed", res.status));
997
2391
  }
998
2392
  return Promise.reject(new PaymentError("Unsupported payment method", "FAILED" /* FAILED */));
999
2393
  } catch (_) {
1000
2394
  return Promise.reject(new PaymentError("Payment failed", "FAILED" /* FAILED */));
1001
2395
  } finally {
1002
- setSelectedPaymentMethod({ type: "CREDIT_CARD" /* CREDIT_CARD */, method: null });
2396
+ setSelectedPaymentMethod({ ...selectedPaymentMethod, type: "CREDIT_CARD" /* CREDIT_CARD */, method: null });
1003
2397
  mutateCards();
1004
2398
  }
1005
2399
  },
1006
- [setSelectedPaymentMethod, mutateCards, env.redirect3dsURI, selectedPaymentMethod]
2400
+ [mutateCards, selectedPaymentMethod, setSelectedPaymentMethod, cardPayment, splitPayment]
1007
2401
  );
1008
- useEffect2(() => {
2402
+ useEffect7(() => {
1009
2403
  register(handlePay);
1010
2404
  }, [register, handlePay]);
1011
- return /* @__PURE__ */ jsxs10("div", { children: [
1012
- /* @__PURE__ */ jsx15("div", { className: "border-b-1 border-black/7 px-5 py-5 md:px-7 md:py-6", children: /* @__PURE__ */ jsx15(CreditCard, {}) }),
1013
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-6 px-5 py-5 md:px-7 md:py-6", children: [
1014
- /* @__PURE__ */ jsx15(
1015
- PointsSwitch,
1016
- {
1017
- disabled: true,
1018
- value: usePoints,
1019
- onChange: setUsePoints,
1020
- pointsTitle,
1021
- pointsConversionRatio
1022
- }
1023
- ),
1024
- usePoints && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-1", children: [
1025
- /* @__PURE__ */ jsxs10(PointsSelector, { onSelect: () => setSelectedPointsType("slapi"), isSelected: selectedPointsType === "slapi", children: [
1026
- /* @__PURE__ */ jsx15("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx15("p", { className: "text-sm font-medium text-black", children: "from [Brand] Balance" }) }),
1027
- isBalanceLoading ? /* @__PURE__ */ jsx15("div", { className: "h-4 w-6 animate-pulse bg-gray-200" }) : !balance?.availablePoints && /* @__PURE__ */ jsx15("p", { className: "text-sm font-medium text-black", children: "No points available" }),
1028
- balance?.availablePoints ? /* @__PURE__ */ jsxs10("p", { className: "text-sm font-medium text-black", children: [
1029
- formatPoints(balance.availablePoints, pointsTitle),
1030
- " ",
1031
- /* @__PURE__ */ jsx15("span", { className: "text-black/50", children: formatUSD(balance.availablePoints / pointsConversionRatio) })
1032
- ] }) : null
1033
- ] }),
1034
- /* @__PURE__ */ jsxs10(
1035
- PointsSelector,
1036
- {
1037
- onSelect: () => setSelectedPointsType("wallet"),
1038
- isSelected: selectedPointsType === "wallet",
1039
- children: [
1040
- /* @__PURE__ */ jsx15("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx15("p", { className: "text-sm font-medium text-black", children: "from Crypto Wallet" }) }),
1041
- /* @__PURE__ */ jsx15("button", { className: "hover:bg-primary -mr-2 h-[34px] rounded-sm border-1 border-black px-3 text-sm font-medium hover:text-white", children: "Connect a Wallet" })
1042
- ]
1043
- }
1044
- )
1045
- ] })
1046
- ] })
2405
+ return /* @__PURE__ */ jsxs15("div", { children: [
2406
+ /* @__PURE__ */ jsx27("div", { className: "border-b-1 border-black/7 px-5 py-5 md:px-7 md:py-6", children: /* @__PURE__ */ jsx27(CreditCard, {}) }),
2407
+ /* @__PURE__ */ jsx27("div", { className: "flex flex-col gap-6 px-5 pt-5 pb-5 md:px-7 md:pt-6 md:pb-7", children: /* @__PURE__ */ jsx27(Points, {}) })
1047
2408
  ] });
1048
2409
  };
1049
2410
 
1050
2411
  // src/components/CryptoTab/Crypto/CryptoWrapper.tsx
1051
2412
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
1052
- import NiceModal5 from "@ebay/nice-modal-react";
2413
+ import NiceModal6 from "@ebay/nice-modal-react";
1053
2414
  import { RainbowKitProvider, connectorsForWallets } from "@rainbow-me/rainbowkit";
1054
2415
  import "@rainbow-me/rainbowkit/styles.css";
1055
2416
  import { injectedWallet, walletConnectWallet } from "@rainbow-me/rainbowkit/wallets";
@@ -1057,7 +2418,7 @@ import { WagmiProvider, createConfig, http as http2 } from "wagmi";
1057
2418
  import { base } from "wagmi/chains";
1058
2419
 
1059
2420
  // src/components/CryptoTab/Crypto/Crypto.tsx
1060
- import { useCallback as useCallback3, useEffect as useEffect4 } from "react";
2421
+ import { useCallback as useCallback6, useEffect as useEffect9 } from "react";
1061
2422
  import { useAccount as useAccount3 } from "wagmi";
1062
2423
 
1063
2424
  // ../../node_modules/@wagmi/core/dist/esm/utils/getAction.js
@@ -1109,11 +2470,11 @@ async function waitForTransactionReceipt(config2, parameters) {
1109
2470
  }
1110
2471
 
1111
2472
  // ../../node_modules/@wagmi/core/dist/esm/exports/index.js
1112
- import { custom, http, webSocket } from "viem";
2473
+ import { custom as custom2, http, webSocket } from "viem";
1113
2474
 
1114
2475
  // src/hooks/useCryptoPayment.ts
1115
- import { erc20Abi } from "viem";
1116
- import { useConfig as useConfig2, useWalletClient } from "wagmi";
2476
+ import { erc20Abi as erc20Abi2 } from "viem";
2477
+ import { useConfig, useWalletClient } from "wagmi";
1117
2478
 
1118
2479
  // src/config/baseTokens.ts
1119
2480
  var BASE_CHAIN_ID = 8453;
@@ -1157,7 +2518,7 @@ var MAX_UINT256 = BigInt(2) ** BigInt(256) - BigInt(1);
1157
2518
  var ONE_INCH_AGGREGATION_ROUTER_V6 = "0x111111125421ca6dc452d289314280a0f8842a65";
1158
2519
  var useCryptoPayment = () => {
1159
2520
  const { data: walletClient } = useWalletClient();
1160
- const config2 = useConfig2();
2521
+ const config2 = useConfig();
1161
2522
  const { selectedPaymentMethod } = useSpreePaymentMethod();
1162
2523
  const cryptoPayment = async (params) => {
1163
2524
  if (!walletClient) {
@@ -1175,14 +2536,14 @@ var useCryptoPayment = () => {
1175
2536
  }
1176
2537
  const allowance = await readContract(config2, {
1177
2538
  address: tokenAddress,
1178
- abi: erc20Abi,
2539
+ abi: erc20Abi2,
1179
2540
  functionName: "allowance",
1180
2541
  args: [walletClient.account.address, ONE_INCH_AGGREGATION_ROUTER_V6]
1181
2542
  });
1182
2543
  if (allowance <= 0n) {
1183
2544
  const result = await walletClient.writeContract({
1184
2545
  address: tokenAddress,
1185
- abi: erc20Abi,
2546
+ abi: erc20Abi2,
1186
2547
  functionName: "approve",
1187
2548
  args: [ONE_INCH_AGGREGATION_ROUTER_V6, MAX_UINT256]
1188
2549
  });
@@ -1226,13 +2587,13 @@ var useCryptoPayment = () => {
1226
2587
 
1227
2588
  // src/components/CryptoTab/Crypto/ConnectButton.tsx
1228
2589
  import { ConnectButton as RainbowButton } from "@rainbow-me/rainbowkit";
1229
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
2590
+ import { Fragment as Fragment4, jsx as jsx28, jsxs as jsxs16 } from "react/jsx-runtime";
1230
2591
  var ConnectButton = () => {
1231
- return /* @__PURE__ */ jsx16(RainbowButton.Custom, { children: ({ mounted, chain, account, openAccountModal, openChainModal, openConnectModal }) => {
2592
+ return /* @__PURE__ */ jsx28(RainbowButton.Custom, { children: ({ mounted, chain, account, openAccountModal, openChainModal, openConnectModal }) => {
1232
2593
  if (!mounted) return null;
1233
- return /* @__PURE__ */ jsx16(Fragment3, { children: (() => {
2594
+ return /* @__PURE__ */ jsx28(Fragment4, { children: (() => {
1234
2595
  if (!mounted || !account || !chain) {
1235
- return /* @__PURE__ */ jsx16(
2596
+ return /* @__PURE__ */ jsx28(
1236
2597
  "button",
1237
2598
  {
1238
2599
  className: "h-[34px] rounded-md border-1 border-black px-3 text-sm font-medium text-black",
@@ -1242,7 +2603,7 @@ var ConnectButton = () => {
1242
2603
  );
1243
2604
  }
1244
2605
  if (chain.unsupported) {
1245
- return /* @__PURE__ */ jsx16(
2606
+ return /* @__PURE__ */ jsx28(
1246
2607
  "button",
1247
2608
  {
1248
2609
  className: "h-[34px] rounded-md border-1 border-black px-3 text-sm font-medium text-red-500",
@@ -1251,13 +2612,13 @@ var ConnectButton = () => {
1251
2612
  }
1252
2613
  );
1253
2614
  }
1254
- return /* @__PURE__ */ jsxs11(
2615
+ return /* @__PURE__ */ jsxs16(
1255
2616
  "button",
1256
2617
  {
1257
2618
  className: "flex h-[34px] items-center gap-2 rounded-md border-1 border-black px-1.5 text-sm font-medium text-black",
1258
2619
  onClick: openAccountModal,
1259
2620
  children: [
1260
- chain.hasIcon && /* @__PURE__ */ jsx16("div", { className: "h-6 w-6 overflow-hidden rounded-full", style: { background: chain.iconBackground }, children: chain.iconUrl && /* @__PURE__ */ jsx16("img", { alt: chain.name ?? "Chain icon", src: chain.iconUrl }) }),
2621
+ chain.hasIcon && /* @__PURE__ */ jsx28("div", { className: "h-6 w-6 overflow-hidden rounded-full", style: { background: chain.iconBackground }, children: chain.iconUrl && /* @__PURE__ */ jsx28("img", { alt: chain.name ?? "Chain icon", src: chain.iconUrl }) }),
1261
2622
  account.displayName
1262
2623
  ]
1263
2624
  }
@@ -1267,29 +2628,29 @@ var ConnectButton = () => {
1267
2628
  };
1268
2629
 
1269
2630
  // src/config/symbolLogos.tsx
1270
- import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
1271
- var MOCA_SVG = /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", fill: "none", children: [
1272
- /* @__PURE__ */ jsx17("circle", { cx: "14", cy: "14", r: "13.5", fill: "#C15F97" }),
1273
- /* @__PURE__ */ jsx17(
2631
+ import { jsx as jsx29, jsxs as jsxs17 } from "react/jsx-runtime";
2632
+ var MOCA_SVG = /* @__PURE__ */ jsxs17("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", fill: "none", children: [
2633
+ /* @__PURE__ */ jsx29("circle", { cx: "14", cy: "14", r: "13.5", fill: "#C15F97" }),
2634
+ /* @__PURE__ */ jsx29(
1274
2635
  "path",
1275
2636
  {
1276
2637
  fill: "#fff",
1277
2638
  d: "M16.06 6.65c.3 0 .59.16.74.43l6.06 10.5a.85.85 0 1 1-1.47.84L16.06 9.2l-1.51 2.62-.02.03-3.8 6.57a.85.85 0 0 1-1.47-.84l3.57-6.18-1.27-2.2-5.32 9.22a.85.85 0 0 1-1.48-.84l6.07-10.5.06-.1a.85.85 0 0 1 1.4.1l1.52 2.62 1.52-2.62.06-.1c.16-.2.4-.33.67-.33Z"
1278
2639
  }
1279
2640
  ),
1280
- /* @__PURE__ */ jsx17("circle", { cx: "16", cy: "14", r: "1.5", fill: "#fff" })
2641
+ /* @__PURE__ */ jsx29("circle", { cx: "16", cy: "14", r: "1.5", fill: "#fff" })
1281
2642
  ] });
1282
- var USDC_SVG = /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", fill: "none", children: [
1283
- /* @__PURE__ */ jsxs12("g", { clipPath: "url(#clip0_528_9163)", children: [
1284
- /* @__PURE__ */ jsx17("path", { fill: "#2775CA", d: "M14 28c7.76 0 14-6.24 14-14S21.76 0 14 0 0 6.24 0 14s6.24 14 14 14Z" }),
1285
- /* @__PURE__ */ jsx17(
2643
+ var USDC_SVG = /* @__PURE__ */ jsxs17("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", fill: "none", children: [
2644
+ /* @__PURE__ */ jsxs17("g", { clipPath: "url(#clip0_528_9163)", children: [
2645
+ /* @__PURE__ */ jsx29("path", { fill: "#2775CA", d: "M14 28c7.76 0 14-6.24 14-14S21.76 0 14 0 0 6.24 0 14s6.24 14 14 14Z" }),
2646
+ /* @__PURE__ */ jsx29(
1286
2647
  "path",
1287
2648
  {
1288
2649
  fill: "#fff",
1289
2650
  d: "M17.85 16.22c0-2.04-1.23-2.74-3.68-3.04-1.75-.23-2.1-.7-2.1-1.51 0-.82.59-1.34 1.75-1.34 1.05 0 1.64.35 1.93 1.22.06.18.23.3.4.3h.94a.4.4 0 0 0 .41-.42v-.05a2.91 2.91 0 0 0-2.63-2.4v-1.4c0-.23-.17-.4-.46-.46h-.88c-.23 0-.4.17-.46.46v1.35c-1.75.23-2.86 1.4-2.86 2.85 0 1.93 1.16 2.69 3.61 2.98 1.64.29 2.16.64 2.16 1.57 0 .94-.81 1.58-1.92 1.58-1.52 0-2.04-.64-2.22-1.52-.06-.23-.23-.35-.4-.35h-1a.4.4 0 0 0-.4.41v.06c.23 1.46 1.16 2.5 3.08 2.8v1.4c0 .23.18.4.47.47h.88c.23 0 .4-.18.46-.47v-1.4c1.75-.3 2.92-1.52 2.92-3.1Z"
1290
2651
  }
1291
2652
  ),
1292
- /* @__PURE__ */ jsx17(
2653
+ /* @__PURE__ */ jsx29(
1293
2654
  "path",
1294
2655
  {
1295
2656
  fill: "#fff",
@@ -1297,11 +2658,11 @@ var USDC_SVG = /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/sv
1297
2658
  }
1298
2659
  )
1299
2660
  ] }),
1300
- /* @__PURE__ */ jsx17("defs", { children: /* @__PURE__ */ jsx17("clipPath", { id: "clip0_528_9163", children: /* @__PURE__ */ jsx17("path", { fill: "#fff", d: "M0 0h28v28H0z" }) }) })
2661
+ /* @__PURE__ */ jsx29("defs", { children: /* @__PURE__ */ jsx29("clipPath", { id: "clip0_528_9163", children: /* @__PURE__ */ jsx29("path", { fill: "#fff", d: "M0 0h28v28H0z" }) }) })
1301
2662
  ] });
1302
- var USDT_SVG = /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", fill: "none", children: [
1303
- /* @__PURE__ */ jsx17("path", { fill: "#26A17B", d: "M14 28a14 14 0 1 0 0-28 14 14 0 0 0 0 28Z" }),
1304
- /* @__PURE__ */ jsx17(
2663
+ var USDT_SVG = /* @__PURE__ */ jsxs17("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", fill: "none", children: [
2664
+ /* @__PURE__ */ jsx29("path", { fill: "#26A17B", d: "M14 28a14 14 0 1 0 0-28 14 14 0 0 0 0 28Z" }),
2665
+ /* @__PURE__ */ jsx29(
1305
2666
  "path",
1306
2667
  {
1307
2668
  fill: "#fff",
@@ -1309,23 +2670,23 @@ var USDT_SVG = /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/sv
1309
2670
  }
1310
2671
  )
1311
2672
  ] });
1312
- var WETH_SVG = /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", width: "28", height: "28", viewBox: "0 0 24 24", children: [
1313
- /* @__PURE__ */ jsxs12("g", { clipPath: "url(#clip0_528_9173)", children: [
1314
- /* @__PURE__ */ jsx17(
2673
+ var WETH_SVG = /* @__PURE__ */ jsxs17("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", width: "28", height: "28", viewBox: "0 0 24 24", children: [
2674
+ /* @__PURE__ */ jsxs17("g", { clipPath: "url(#clip0_528_9173)", children: [
2675
+ /* @__PURE__ */ jsx29(
1315
2676
  "path",
1316
2677
  {
1317
2678
  fill: "#000",
1318
2679
  d: "M17.14 20.57c0 .95-1.31 2.01-3.39 2.4h-2.59c-4.65 0-8.42-1.07-8.42-2.4 0-1.32 3.77-2.4 8.42-2.4s5.98 1.08 5.98 2.4Z"
1319
2680
  }
1320
2681
  ),
1321
- /* @__PURE__ */ jsx17(
2682
+ /* @__PURE__ */ jsx29(
1322
2683
  "path",
1323
2684
  {
1324
2685
  fill: "#F61F7D",
1325
2686
  d: "M23.31 11c0 5.86-5.18 11.63-11.07 11.63-5.9 0-11.9-6.17-11.9-12.03C.34 4.75 5.12 0 11.01 0s12.3 5.15 12.3 11Z"
1326
2687
  }
1327
2688
  ),
1328
- /* @__PURE__ */ jsx17(
2689
+ /* @__PURE__ */ jsx29(
1329
2690
  "path",
1330
2691
  {
1331
2692
  fill: "#000",
@@ -1334,8 +2695,8 @@ var WETH_SVG = /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/sv
1334
2695
  clipRule: "evenodd"
1335
2696
  }
1336
2697
  ),
1337
- /* @__PURE__ */ jsx17("path", { fill: "#fff", d: "M24 12.17a10.8 10.8 0 1 1-21.6 0 10.8 10.8 0 0 1 21.6 0Z" }),
1338
- /* @__PURE__ */ jsx17(
2698
+ /* @__PURE__ */ jsx29("path", { fill: "#fff", d: "M24 12.17a10.8 10.8 0 1 1-21.6 0 10.8 10.8 0 0 1 21.6 0Z" }),
2699
+ /* @__PURE__ */ jsx29(
1339
2700
  "path",
1340
2701
  {
1341
2702
  fill: "#000",
@@ -1344,8 +2705,8 @@ var WETH_SVG = /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/sv
1344
2705
  clipRule: "evenodd"
1345
2706
  }
1346
2707
  ),
1347
- /* @__PURE__ */ jsx17("path", { fill: "#000", fillRule: "evenodd", d: "M3.02 10.63.7 8.75l.74-.86 2.34 1.87-.75.87Z", clipRule: "evenodd" }),
1348
- /* @__PURE__ */ jsx17(
2708
+ /* @__PURE__ */ jsx29("path", { fill: "#000", fillRule: "evenodd", d: "M3.02 10.63.7 8.75l.74-.86 2.34 1.87-.75.87Z", clipRule: "evenodd" }),
2709
+ /* @__PURE__ */ jsx29(
1349
2710
  "path",
1350
2711
  {
1351
2712
  fill: "#000",
@@ -1353,7 +2714,7 @@ var WETH_SVG = /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/sv
1353
2714
  }
1354
2715
  )
1355
2716
  ] }),
1356
- /* @__PURE__ */ jsx17("defs", { children: /* @__PURE__ */ jsx17("clipPath", { id: "clip0_528_9173", children: /* @__PURE__ */ jsx17("path", { fill: "#fff", d: "M0 0h24v24H0z" }) }) })
2717
+ /* @__PURE__ */ jsx29("defs", { children: /* @__PURE__ */ jsx29("clipPath", { id: "clip0_528_9173", children: /* @__PURE__ */ jsx29("path", { fill: "#fff", d: "M0 0h24v24H0z" }) }) })
1357
2718
  ] });
1358
2719
  var symbolLogos = {
1359
2720
  MOCA: MOCA_SVG,
@@ -1366,34 +2727,34 @@ function getSymbolLogo(symbol) {
1366
2727
  }
1367
2728
 
1368
2729
  // src/components/CryptoTab/Crypto/Logos.tsx
1369
- import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
2730
+ import { jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
1370
2731
  var Logos = () => {
1371
- return /* @__PURE__ */ jsxs13("div", { className: "flex", children: [
1372
- /* @__PURE__ */ jsx18("div", { className: "rounded-full border border-[#F5F7FA]", children: getSymbolLogo("MOCA") }),
1373
- /* @__PURE__ */ jsx18("div", { className: "-ml-2.5 rounded-full border border-[#F5F7FA]", children: getSymbolLogo("USDC") }),
1374
- /* @__PURE__ */ jsx18("div", { className: "-ml-2.5 rounded-full border border-[#F5F7FA]", children: getSymbolLogo("USDT") }),
1375
- /* @__PURE__ */ jsx18("div", { className: "-ml-2.5 rounded-full border border-[#F5F7FA] bg-[#F5F7FA]", children: getSymbolLogo("WETH") })
2732
+ return /* @__PURE__ */ jsxs18("div", { className: "flex", children: [
2733
+ /* @__PURE__ */ jsx30("div", { className: "rounded-full border border-[#F5F7FA]", children: getSymbolLogo("MOCA") }),
2734
+ /* @__PURE__ */ jsx30("div", { className: "-ml-2.5 rounded-full border border-[#F5F7FA]", children: getSymbolLogo("USDC") }),
2735
+ /* @__PURE__ */ jsx30("div", { className: "-ml-2.5 rounded-full border border-[#F5F7FA]", children: getSymbolLogo("USDT") }),
2736
+ /* @__PURE__ */ jsx30("div", { className: "-ml-2.5 rounded-full border border-[#F5F7FA] bg-[#F5F7FA]", children: getSymbolLogo("WETH") })
1376
2737
  ] });
1377
2738
  };
1378
2739
 
1379
2740
  // src/components/CryptoTab/Crypto/SelectCoinButton.tsx
1380
- import NiceModal4 from "@ebay/nice-modal-react";
2741
+ import NiceModal5 from "@ebay/nice-modal-react";
1381
2742
 
1382
2743
  // src/modals/CryptoSelectModal.tsx
1383
- import NiceModal3, { useModal as useModal2 } from "@ebay/nice-modal-react";
2744
+ import NiceModal4, { useModal as useModal2 } from "@ebay/nice-modal-react";
1384
2745
 
1385
2746
  // src/hooks/useBaseERC20Token.ts
1386
- import * as React2 from "react";
1387
- import { erc20Abi as erc20Abi2, formatUnits, getAddress } from "viem";
2747
+ import * as React13 from "react";
2748
+ import { erc20Abi as erc20Abi3, formatUnits, getAddress } from "viem";
1388
2749
  import { useAccount, usePublicClient } from "wagmi";
1389
2750
  function useBaseERC20Token() {
1390
2751
  const { address } = useAccount();
1391
2752
  const baseClient = usePublicClient({ chainId: BASE_CHAIN_ID });
1392
2753
  const defaultClient = usePublicClient();
1393
- const [rows, setRows] = React2.useState([]);
1394
- const [isLoading, setLoading] = React2.useState(false);
1395
- const [error, setError] = React2.useState(null);
1396
- React2.useEffect(() => {
2754
+ const [rows, setRows] = React13.useState([]);
2755
+ const [isLoading, setLoading] = React13.useState(false);
2756
+ const [error, setError] = React13.useState(null);
2757
+ React13.useEffect(() => {
1397
2758
  let cancelled = false;
1398
2759
  async function run() {
1399
2760
  const client = baseClient ?? defaultClient;
@@ -1415,7 +2776,7 @@ function useBaseERC20Token() {
1415
2776
  allowFailure: true,
1416
2777
  contracts: normalizedTokens.map((t) => ({
1417
2778
  address: t.address,
1418
- abi: erc20Abi2,
2779
+ abi: erc20Abi3,
1419
2780
  functionName: "balanceOf",
1420
2781
  args: [address]
1421
2782
  }))
@@ -1467,8 +2828,8 @@ function useBaseNativeToken() {
1467
2828
  }
1468
2829
 
1469
2830
  // src/modals/CryptoSelectModal.tsx
1470
- import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
1471
- var CryptoSelectModal = NiceModal3.create(() => {
2831
+ import { Fragment as Fragment5, jsx as jsx31, jsxs as jsxs19 } from "react/jsx-runtime";
2832
+ var CryptoSelectModal = NiceModal4.create(() => {
1472
2833
  const modal = useModal2();
1473
2834
  const { isLoading, error, erc20Balances } = useBaseERC20Token();
1474
2835
  const { isLoadingNative, nativeError, nativeBalance } = useBaseNativeToken();
@@ -1477,13 +2838,13 @@ var CryptoSelectModal = NiceModal3.create(() => {
1477
2838
  modal.remove();
1478
2839
  setSelectedPaymentMethod({ type: "CRYPTO" /* CRYPTO */, method: coin });
1479
2840
  };
1480
- return /* @__PURE__ */ jsxs14(Dialog, { open: modal.visible, onOpenChange: modal.remove, children: [
1481
- /* @__PURE__ */ jsx19(DialogDescription, { className: "hidden", children: "Crypto Select Modal" }),
1482
- /* @__PURE__ */ jsxs14(DialogContent, { showCloseButton: false, className: "gap-0 p-0", children: [
1483
- /* @__PURE__ */ jsx19("div", { className: "flex flex-col gap-6 px-5 py-5 md:px-7 md:py-6", children: /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between gap-4", children: [
1484
- /* @__PURE__ */ jsx19("button", { className: "rounded-md hover:bg-gray-100", onClick: modal.remove, children: /* @__PURE__ */ jsx19("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "25", fill: "none", children: /* @__PURE__ */ jsx19("path", { stroke: "#000", d: "m15 6.5-6 6 6 6" }) }) }),
1485
- /* @__PURE__ */ jsx19(DialogTitle, { className: "text-primary text-2xl font-semibold", children: "Select a token" }),
1486
- /* @__PURE__ */ jsx19("button", { className: "rounded-md p-1 hover:bg-gray-100", onClick: modal.remove, children: /* @__PURE__ */ jsx19("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "17", fill: "none", children: /* @__PURE__ */ jsx19(
2841
+ return /* @__PURE__ */ jsxs19(Dialog, { open: modal.visible, onOpenChange: modal.remove, children: [
2842
+ /* @__PURE__ */ jsx31(DialogDescription, { className: "hidden", children: "Crypto Select Modal" }),
2843
+ /* @__PURE__ */ jsxs19(DialogContent, { showCloseButton: false, className: "gap-0 p-0", children: [
2844
+ /* @__PURE__ */ jsx31("div", { className: "flex flex-col gap-6 px-5 py-5 md:px-7 md:py-6", children: /* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between gap-4", children: [
2845
+ /* @__PURE__ */ jsx31("button", { className: "rounded-md hover:bg-gray-100", onClick: modal.remove, children: /* @__PURE__ */ jsx31("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "25", fill: "none", children: /* @__PURE__ */ jsx31("path", { stroke: "#000", d: "m15 6.5-6 6 6 6" }) }) }),
2846
+ /* @__PURE__ */ jsx31(DialogTitle, { className: "text-primary text-2xl font-semibold", children: "Select a token" }),
2847
+ /* @__PURE__ */ jsx31("button", { className: "rounded-md p-1 hover:bg-gray-100", onClick: modal.remove, children: /* @__PURE__ */ jsx31("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "17", fill: "none", children: /* @__PURE__ */ jsx31(
1487
2848
  "path",
1488
2849
  {
1489
2850
  fill: "#000",
@@ -1491,19 +2852,19 @@ var CryptoSelectModal = NiceModal3.create(() => {
1491
2852
  }
1492
2853
  ) }) })
1493
2854
  ] }) }),
1494
- /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-4 px-5 py-5 md:px-7 md:py-6", children: [
1495
- /* @__PURE__ */ jsx19("h3", { className: "text-primary text-xl font-semibold", children: "Tokens with wallet balance" }),
1496
- (error || nativeError) && /* @__PURE__ */ jsx19("p", { className: "text-center text-sm text-red-500", children: "Something wrong" }),
1497
- /* @__PURE__ */ jsxs14("div", { className: "flex w-full flex-col gap-1", children: [
1498
- isLoadingNative && /* @__PURE__ */ jsx19("div", { className: "h-11 animate-pulse rounded-md bg-gray-100" }),
1499
- nativeBalance && /* @__PURE__ */ jsxs14(
2855
+ /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-4 px-5 py-5 md:px-7 md:py-6", children: [
2856
+ /* @__PURE__ */ jsx31("h3", { className: "text-primary text-xl font-semibold", children: "Tokens with wallet balance" }),
2857
+ (error || nativeError) && /* @__PURE__ */ jsx31("p", { className: "text-center text-sm text-red-500", children: "Something wrong" }),
2858
+ /* @__PURE__ */ jsxs19("div", { className: "flex w-full flex-col gap-1", children: [
2859
+ isLoadingNative && /* @__PURE__ */ jsx31("div", { className: "h-11 animate-pulse rounded-md bg-gray-100" }),
2860
+ nativeBalance && /* @__PURE__ */ jsxs19(
1500
2861
  "button",
1501
2862
  {
1502
2863
  className: "flex h-11 w-full items-center justify-between gap-4 rounded-sm px-1.5 text-black hover:bg-gray-100",
1503
2864
  onClick: () => handleSelect(nativeBalance),
1504
2865
  children: [
1505
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
1506
- nativeBalance.logoURI && /* @__PURE__ */ jsx19(
2866
+ /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
2867
+ nativeBalance.logoURI && /* @__PURE__ */ jsx31(
1507
2868
  "img",
1508
2869
  {
1509
2870
  className: "h-8 w-8 shrink-0",
@@ -1511,31 +2872,31 @@ var CryptoSelectModal = NiceModal3.create(() => {
1511
2872
  alt: `${nativeBalance.symbol} logo`
1512
2873
  }
1513
2874
  ),
1514
- /* @__PURE__ */ jsx19("p", { className: "text-sm font-medium", children: nativeBalance.symbol })
2875
+ /* @__PURE__ */ jsx31("p", { className: "text-sm font-medium", children: nativeBalance.symbol })
1515
2876
  ] }),
1516
- /* @__PURE__ */ jsx19("p", { className: "text-sm font-medium", children: nativeBalance.formatted })
2877
+ /* @__PURE__ */ jsx31("p", { className: "text-sm font-medium", children: nativeBalance.formatted })
1517
2878
  ]
1518
2879
  },
1519
2880
  nativeBalance.symbol
1520
2881
  ),
1521
- isLoading && /* @__PURE__ */ jsxs14(Fragment4, { children: [
1522
- /* @__PURE__ */ jsx19("div", { className: "h-11 animate-pulse rounded-md bg-gray-100" }),
1523
- /* @__PURE__ */ jsx19("div", { className: "h-11 animate-pulse rounded-md bg-gray-100" }),
1524
- /* @__PURE__ */ jsx19("div", { className: "h-11 animate-pulse rounded-md bg-gray-100" })
2882
+ isLoading && /* @__PURE__ */ jsxs19(Fragment5, { children: [
2883
+ /* @__PURE__ */ jsx31("div", { className: "h-11 animate-pulse rounded-md bg-gray-100" }),
2884
+ /* @__PURE__ */ jsx31("div", { className: "h-11 animate-pulse rounded-md bg-gray-100" }),
2885
+ /* @__PURE__ */ jsx31("div", { className: "h-11 animate-pulse rounded-md bg-gray-100" })
1525
2886
  ] }),
1526
2887
  erc20Balances.map((coin) => {
1527
2888
  const Icon = getSymbolLogo(coin.symbol);
1528
- return /* @__PURE__ */ jsxs14(
2889
+ return /* @__PURE__ */ jsxs19(
1529
2890
  "button",
1530
2891
  {
1531
2892
  className: "flex h-11 w-full items-center justify-between gap-4 rounded-sm px-1.5 text-black hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50",
1532
2893
  onClick: () => handleSelect(coin),
1533
2894
  children: [
1534
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
2895
+ /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
1535
2896
  Boolean(Icon) && Icon,
1536
- /* @__PURE__ */ jsx19("p", { className: "text-sm font-medium", children: coin.symbol })
2897
+ /* @__PURE__ */ jsx31("p", { className: "text-sm font-medium", children: coin.symbol })
1537
2898
  ] }),
1538
- /* @__PURE__ */ jsx19("p", { className: "text-sm font-medium", children: coin.formatted })
2899
+ /* @__PURE__ */ jsx31("p", { className: "text-sm font-medium", children: coin.formatted })
1539
2900
  ]
1540
2901
  },
1541
2902
  coin.symbol
@@ -1549,51 +2910,51 @@ var CryptoSelectModal = NiceModal3.create(() => {
1549
2910
  CryptoSelectModal.displayName = "CryptoSelectModal";
1550
2911
 
1551
2912
  // src/components/CryptoTab/Crypto/SelectCoinButton.tsx
1552
- import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
2913
+ import { jsx as jsx32, jsxs as jsxs20 } from "react/jsx-runtime";
1553
2914
  var SelectCoinButton = () => {
1554
2915
  const openModal = () => {
1555
- NiceModal4.show(CryptoSelectModal);
2916
+ NiceModal5.show(CryptoSelectModal);
1556
2917
  };
1557
- return /* @__PURE__ */ jsxs15("button", { onClick: openModal, type: "button", className: "bg-primary/8 flex h-11 w-full overflow-hidden rounded-md", children: [
1558
- /* @__PURE__ */ jsx20("div", { className: "bg-primary flex h-full w-11 items-center justify-center", children: /* @__PURE__ */ jsx20("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-white" }) }),
1559
- /* @__PURE__ */ jsxs15("div", { className: "flex h-full w-full items-center justify-between px-3", children: [
1560
- /* @__PURE__ */ jsx20("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx20("p", { className: "font-medium text-black/50", children: "Select a token" }) }),
1561
- /* @__PURE__ */ jsx20("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "none", children: /* @__PURE__ */ jsx20("path", { stroke: "#000", strokeLinecap: "round", d: "m6 12.43 4-4-4-4" }) })
2918
+ return /* @__PURE__ */ jsxs20("button", { onClick: openModal, type: "button", className: "bg-primary/8 flex h-11 w-full overflow-hidden rounded-md", children: [
2919
+ /* @__PURE__ */ jsx32("div", { className: "bg-primary flex h-full w-11 items-center justify-center", children: /* @__PURE__ */ jsx32("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-white" }) }),
2920
+ /* @__PURE__ */ jsxs20("div", { className: "flex h-full w-full items-center justify-between px-3", children: [
2921
+ /* @__PURE__ */ jsx32("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx32("p", { className: "font-medium text-black/50", children: "Select a token" }) }),
2922
+ /* @__PURE__ */ jsx32("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "none", children: /* @__PURE__ */ jsx32("path", { stroke: "#000", strokeLinecap: "round", d: "m6 12.43 4-4-4-4" }) })
1562
2923
  ] })
1563
2924
  ] });
1564
2925
  };
1565
2926
 
1566
2927
  // src/components/CryptoTab/Crypto/SelectedCoin.tsx
1567
- import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
2928
+ import { jsx as jsx33, jsxs as jsxs21 } from "react/jsx-runtime";
1568
2929
  var SelectedCoin = (props) => {
1569
2930
  const { coin, balance, logoURI } = props;
1570
2931
  const Icon = getSymbolLogo(coin);
1571
- return /* @__PURE__ */ jsxs16("div", { className: "bg-primary/8 flex h-11 w-full overflow-hidden rounded-md", children: [
1572
- /* @__PURE__ */ jsx21("div", { className: "bg-primary flex h-full w-11 items-center justify-center", children: /* @__PURE__ */ jsx21("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-white", children: /* @__PURE__ */ jsx21("div", { className: "bg-primary h-2.5 w-2.5 rounded-full" }) }) }),
1573
- /* @__PURE__ */ jsxs16("div", { className: "border-primary flex h-full w-full items-center justify-between rounded-r-md border-1 !border-l-0 px-3", children: [
1574
- /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1", children: [
2932
+ return /* @__PURE__ */ jsxs21("div", { className: "bg-primary/8 flex h-11 w-full overflow-hidden rounded-md", children: [
2933
+ /* @__PURE__ */ jsx33("div", { className: "bg-primary flex h-full w-11 items-center justify-center", children: /* @__PURE__ */ jsx33("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-white", children: /* @__PURE__ */ jsx33("div", { className: "bg-primary h-2.5 w-2.5 rounded-full" }) }) }),
2934
+ /* @__PURE__ */ jsxs21("div", { className: "border-primary flex h-full w-full items-center justify-between rounded-r-md border-1 !border-l-0 px-3", children: [
2935
+ /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-1", children: [
1575
2936
  Icon,
1576
- !Icon && logoURI && /* @__PURE__ */ jsx21("img", { className: "mr-1 h-8 w-8 shrink-0", src: logoURI, alt: `${coin} logo` }),
1577
- /* @__PURE__ */ jsx21("p", { className: "font-semibold text-black", children: coin }),
1578
- /* @__PURE__ */ jsx21("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx21("path", { d: "M6 12.4341L10 8.43408L6 4.43408", stroke: "black", strokeLinecap: "round" }) })
2937
+ !Icon && logoURI && /* @__PURE__ */ jsx33("img", { className: "mr-1 h-8 w-8 shrink-0", src: logoURI, alt: `${coin} logo` }),
2938
+ /* @__PURE__ */ jsx33("p", { className: "font-semibold text-black", children: coin }),
2939
+ /* @__PURE__ */ jsx33("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx33("path", { d: "M6 12.4341L10 8.43408L6 4.43408", stroke: "black", strokeLinecap: "round" }) })
1579
2940
  ] }),
1580
- /* @__PURE__ */ jsxs16("p", { className: "text-xs font-medium text-black/50", children: [
2941
+ /* @__PURE__ */ jsxs21("p", { className: "text-xs font-medium text-black/50", children: [
1581
2942
  "Wallet balance ",
1582
- /* @__PURE__ */ jsx21("span", { className: "text-black", children: balance })
2943
+ /* @__PURE__ */ jsx33("span", { className: "text-black", children: balance })
1583
2944
  ] })
1584
2945
  ] })
1585
2946
  ] });
1586
2947
  };
1587
2948
 
1588
2949
  // src/components/CryptoTab/Crypto/Crypto.tsx
1589
- import { jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
2950
+ import { jsx as jsx34, jsxs as jsxs22 } from "react/jsx-runtime";
1590
2951
  var Crypto = () => {
1591
2952
  const { address } = useAccount3();
1592
2953
  const { selectedPaymentMethod } = useSpreePaymentMethod();
1593
2954
  const { cryptoPayment } = useCryptoPayment();
1594
2955
  const isWalletConnected = Boolean(address);
1595
2956
  const { register } = useSpreePayRegister();
1596
- const handlePay = useCallback3(
2957
+ const handlePay = useCallback6(
1597
2958
  async (data) => {
1598
2959
  try {
1599
2960
  const res = await cryptoPayment(data);
@@ -1607,17 +2968,17 @@ var Crypto = () => {
1607
2968
  },
1608
2969
  [cryptoPayment]
1609
2970
  );
1610
- useEffect4(() => {
2971
+ useEffect9(() => {
1611
2972
  register(handlePay);
1612
2973
  }, [register, handlePay]);
1613
- return /* @__PURE__ */ jsxs17("div", { className: "flex flex-col items-baseline gap-4", children: [
1614
- /* @__PURE__ */ jsxs17("div", { className: "flex w-full items-center justify-between gap-4", children: [
1615
- /* @__PURE__ */ jsx22("h3", { className: "text-primary text-xl leading-[1.7] font-semibold", children: "Pay with Crypto" }),
1616
- /* @__PURE__ */ jsx22(ConnectButton, {})
2974
+ return /* @__PURE__ */ jsxs22("div", { className: "flex flex-col items-baseline gap-4", children: [
2975
+ /* @__PURE__ */ jsxs22("div", { className: "flex w-full items-center justify-between gap-4", children: [
2976
+ /* @__PURE__ */ jsx34("h3", { className: "text-primary text-xl leading-[1.7] font-semibold", children: "Pay with Crypto" }),
2977
+ /* @__PURE__ */ jsx34(ConnectButton, {})
1617
2978
  ] }),
1618
- !isWalletConnected && /* @__PURE__ */ jsx22(Logos, {}),
1619
- isWalletConnected && /* @__PURE__ */ jsxs17("div", { className: "flex w-full flex-col gap-1", children: [
1620
- selectedPaymentMethod.type === "CRYPTO" /* CRYPTO */ && selectedPaymentMethod.method && /* @__PURE__ */ jsx22(
2979
+ !isWalletConnected && /* @__PURE__ */ jsx34(Logos, {}),
2980
+ isWalletConnected && /* @__PURE__ */ jsxs22("div", { className: "flex w-full flex-col gap-1", children: [
2981
+ selectedPaymentMethod.type === "CRYPTO" /* CRYPTO */ && selectedPaymentMethod.method && /* @__PURE__ */ jsx34(
1621
2982
  SelectedCoin,
1622
2983
  {
1623
2984
  coin: selectedPaymentMethod.method.symbol,
@@ -1625,13 +2986,13 @@ var Crypto = () => {
1625
2986
  logoURI: selectedPaymentMethod.method.logoURI
1626
2987
  }
1627
2988
  ),
1628
- /* @__PURE__ */ jsx22(SelectCoinButton, {})
2989
+ /* @__PURE__ */ jsx34(SelectCoinButton, {})
1629
2990
  ] })
1630
2991
  ] });
1631
2992
  };
1632
2993
 
1633
2994
  // src/components/CryptoTab/Crypto/CryptoWrapper.tsx
1634
- import { jsx as jsx23 } from "react/jsx-runtime";
2995
+ import { jsx as jsx35 } from "react/jsx-runtime";
1635
2996
  var queryClient = new QueryClient();
1636
2997
  var connectors = connectorsForWallets(
1637
2998
  [
@@ -1649,29 +3010,30 @@ var config = createConfig({
1649
3010
  ssr: true
1650
3011
  });
1651
3012
  var CryptoWrapper = () => {
1652
- return /* @__PURE__ */ jsx23(WagmiProvider, { config, children: /* @__PURE__ */ jsx23(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx23(RainbowKitProvider, { children: /* @__PURE__ */ jsx23(NiceModal5.Provider, { children: /* @__PURE__ */ jsx23(Crypto, {}) }) }) }) });
3013
+ return /* @__PURE__ */ jsx35(WagmiProvider, { config, children: /* @__PURE__ */ jsx35(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx35(RainbowKitProvider, { children: /* @__PURE__ */ jsx35(NiceModal6.Provider, { children: /* @__PURE__ */ jsx35(Crypto, {}) }) }) }) });
1653
3014
  };
1654
3015
 
1655
3016
  // src/components/CryptoTab/CryptoTab.tsx
1656
- import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
1657
- var CryptoTab = (props) => {
1658
- const { pointsTitle, pointsConversionRatio } = props;
1659
- return /* @__PURE__ */ jsxs18("div", { children: [
1660
- /* @__PURE__ */ jsx24("div", { className: "border-b-1 border-black/7 px-5 py-5 md:px-7 md:py-5", children: /* @__PURE__ */ jsx24(CryptoWrapper, {}) }),
1661
- /* @__PURE__ */ jsx24("div", { className: "px-5 py-5 md:px-7 md:py-6", children: /* @__PURE__ */ jsx24(PointsSwitch, { disabled: true, pointsTitle, pointsConversionRatio }) })
3017
+ import { jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
3018
+ var CryptoTab = () => {
3019
+ return /* @__PURE__ */ jsxs23("div", { children: [
3020
+ /* @__PURE__ */ jsx36("div", { className: "border-b-1 border-black/7 px-5 py-5 md:px-7 md:py-5", children: /* @__PURE__ */ jsx36(CryptoWrapper, {}) }),
3021
+ /* @__PURE__ */ jsx36("div", { className: "px-5 py-5 md:px-7 md:py-6", children: /* @__PURE__ */ jsx36(PointsSwitch, { disabled: true }) })
1662
3022
  ] });
1663
3023
  };
1664
3024
 
1665
3025
  // src/components/TabButtons.tsx
1666
- import { jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
1667
- var TabButton = ({ isActive, children, onClick }) => {
1668
- return /* @__PURE__ */ jsx25(
3026
+ import { jsx as jsx37, jsxs as jsxs24 } from "react/jsx-runtime";
3027
+ var TabButton = ({ isDisabled = true, isActive, children, onClick }) => {
3028
+ return /* @__PURE__ */ jsx37(
1669
3029
  "button",
1670
3030
  {
3031
+ disabled: isDisabled,
1671
3032
  onClick,
1672
3033
  className: cn(
1673
3034
  "flex w-[132px] flex-col items-baseline rounded-sm border-1 border-black/50 px-2.5 py-1.5 text-sm text-black",
1674
- { "opacity-50": !isActive },
3035
+ { "opacity-50": !isActive || isDisabled },
3036
+ { "cursor-not-allowed": isDisabled },
1675
3037
  { "bg-primary/7 border-primary text-primary": isActive }
1676
3038
  ),
1677
3039
  children
@@ -1680,84 +3042,99 @@ var TabButton = ({ isActive, children, onClick }) => {
1680
3042
  };
1681
3043
  var TabButtons = (props) => {
1682
3044
  const { value, onChange } = props;
3045
+ const { spreePayConfig } = useSpreePayConfig();
1683
3046
  const handleChange = (type) => () => {
1684
3047
  if (value !== type) {
1685
3048
  onChange({ type, method: null });
1686
3049
  }
1687
3050
  };
1688
- return /* @__PURE__ */ jsxs19("div", { className: "flex gap-2", children: [
1689
- /* @__PURE__ */ jsxs19(TabButton, { onClick: handleChange("CREDIT_CARD" /* CREDIT_CARD */), isActive: value === "CREDIT_CARD" /* CREDIT_CARD */, children: [
1690
- /* @__PURE__ */ jsx25("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", fill: "none", children: /* @__PURE__ */ jsx25(
1691
- "path",
1692
- {
1693
- fill: "currentColor",
1694
- d: "M22 6v12c0 .55-.2 1.02-.59 1.41-.39.4-.86.59-1.41.59H4c-.55 0-1.02-.2-1.41-.59-.4-.39-.59-.86-.59-1.41V6c0-.55.2-1.02.59-1.41C2.98 4.19 3.45 4 4 4h16c.55 0 1.02.2 1.41.59.4.39.59.86.59 1.41ZM4 8h16V6H4v2Zm0 4v6h16v-6H4Z"
1695
- }
1696
- ) }),
1697
- /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium", children: "Card" })
1698
- ] }),
1699
- /* @__PURE__ */ jsxs19(TabButton, { onClick: handleChange("CRYPTO" /* CRYPTO */), isActive: value === "CRYPTO" /* CRYPTO */, children: [
1700
- /* @__PURE__ */ jsxs19("svg", { className: "my-1", xmlns: "http://www.w3.org/2000/svg", width: "30", height: "16", fill: "none", children: [
1701
- /* @__PURE__ */ jsx25(
1702
- "path",
1703
- {
1704
- fill: "currentColor",
1705
- d: "M14.5 0C19.2 0 23 3.58 23 8s-3.8 8-8.5 8a8.93 8.93 0 0 1-3.35-.65 8 8 0 0 0 2.24-1.44c.36.06.73.09 1.11.09 3.7 0 6.5-2.8 6.5-6s-2.8-6-6.5-6c-.38 0-.75.03-1.11.09A8 8 0 0 0 11.15.65 8.93 8.93 0 0 1 14.5 0Z"
1706
- }
1707
- ),
1708
- /* @__PURE__ */ jsx25(
1709
- "path",
1710
- {
1711
- fill: "currentColor",
1712
- d: "M21.15 0c4.7 0 8.5 3.58 8.5 8s-3.8 8-8.5 8a8.93 8.93 0 0 1-3.35-.65 8 8 0 0 0 2.24-1.44c.36.06.73.09 1.1.09 3.71 0 6.5-2.8 6.5-6s-2.79-6-6.5-6c-.37 0-.74.03-1.1.09A8 8 0 0 0 17.8.65 8.93 8.93 0 0 1 21.15 0Z"
1713
- }
1714
- ),
1715
- /* @__PURE__ */ jsx25("circle", { cx: "8", cy: "8", r: "7", stroke: "currentColor", strokeWidth: "2" })
1716
- ] }),
1717
- /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium", children: "Crypto" })
1718
- ] })
3051
+ return /* @__PURE__ */ jsxs24("div", { className: "flex gap-2", children: [
3052
+ /* @__PURE__ */ jsxs24(
3053
+ TabButton,
3054
+ {
3055
+ isDisabled: !spreePayConfig?.creditCard.enabled,
3056
+ onClick: handleChange("CREDIT_CARD" /* CREDIT_CARD */),
3057
+ isActive: value === "CREDIT_CARD" /* CREDIT_CARD */,
3058
+ children: [
3059
+ /* @__PURE__ */ jsx37("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", fill: "none", children: /* @__PURE__ */ jsx37(
3060
+ "path",
3061
+ {
3062
+ fill: "currentColor",
3063
+ d: "M22 6v12c0 .55-.2 1.02-.59 1.41-.39.4-.86.59-1.41.59H4c-.55 0-1.02-.2-1.41-.59-.4-.39-.59-.86-.59-1.41V6c0-.55.2-1.02.59-1.41C2.98 4.19 3.45 4 4 4h16c.55 0 1.02.2 1.41.59.4.39.59.86.59 1.41ZM4 8h16V6H4v2Zm0 4v6h16v-6H4Z"
3064
+ }
3065
+ ) }),
3066
+ /* @__PURE__ */ jsx37("p", { className: "text-sm font-medium", children: "Card" })
3067
+ ]
3068
+ }
3069
+ ),
3070
+ /* @__PURE__ */ jsxs24(
3071
+ TabButton,
3072
+ {
3073
+ isDisabled: !spreePayConfig?.creditCard.enabled,
3074
+ onClick: handleChange("CRYPTO" /* CRYPTO */),
3075
+ isActive: value === "CRYPTO" /* CRYPTO */,
3076
+ children: [
3077
+ /* @__PURE__ */ jsxs24("svg", { className: "my-1", xmlns: "http://www.w3.org/2000/svg", width: "30", height: "16", fill: "none", children: [
3078
+ /* @__PURE__ */ jsx37(
3079
+ "path",
3080
+ {
3081
+ fill: "currentColor",
3082
+ d: "M14.5 0C19.2 0 23 3.58 23 8s-3.8 8-8.5 8a8.93 8.93 0 0 1-3.35-.65 8 8 0 0 0 2.24-1.44c.36.06.73.09 1.11.09 3.7 0 6.5-2.8 6.5-6s-2.8-6-6.5-6c-.38 0-.75.03-1.11.09A8 8 0 0 0 11.15.65 8.93 8.93 0 0 1 14.5 0Z"
3083
+ }
3084
+ ),
3085
+ /* @__PURE__ */ jsx37(
3086
+ "path",
3087
+ {
3088
+ fill: "currentColor",
3089
+ d: "M21.15 0c4.7 0 8.5 3.58 8.5 8s-3.8 8-8.5 8a8.93 8.93 0 0 1-3.35-.65 8 8 0 0 0 2.24-1.44c.36.06.73.09 1.1.09 3.71 0 6.5-2.8 6.5-6s-2.79-6-6.5-6c-.37 0-.74.03-1.1.09A8 8 0 0 0 17.8.65 8.93 8.93 0 0 1 21.15 0Z"
3090
+ }
3091
+ ),
3092
+ /* @__PURE__ */ jsx37("circle", { cx: "8", cy: "8", r: "7", stroke: "currentColor", strokeWidth: "2" })
3093
+ ] }),
3094
+ /* @__PURE__ */ jsx37("p", { className: "text-sm font-medium", children: "Crypto" })
3095
+ ]
3096
+ }
3097
+ )
1719
3098
  ] });
1720
3099
  };
1721
3100
 
1722
3101
  // src/components/Tabs.tsx
1723
- import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
1724
- var Tabs = ({ config: config2 }) => {
3102
+ import { jsx as jsx38, jsxs as jsxs25 } from "react/jsx-runtime";
3103
+ var Tabs = () => {
1725
3104
  const { selectedPaymentMethod, setSelectedPaymentMethod } = useSpreePaymentMethod();
1726
- const { pointsConversionRatio, pointsTitle } = config2;
1727
- return /* @__PURE__ */ jsxs20("div", { className: "mb-4 rounded-3xl border border-black/25 bg-white", children: [
1728
- /* @__PURE__ */ jsxs20("div", { className: "flex w-full flex-col gap-4 border-b-1 border-black/7 px-5 py-5 md:px-7 md:py-6", children: [
1729
- /* @__PURE__ */ jsx26("h2", { className: "text-primary text-2xl font-semibold", children: "Choose a Payment Method" }),
1730
- /* @__PURE__ */ jsx26(TabButtons, { value: selectedPaymentMethod.type, onChange: setSelectedPaymentMethod })
3105
+ return /* @__PURE__ */ jsxs25("div", { className: "mb-4 rounded-3xl border border-black/25 bg-white", children: [
3106
+ /* @__PURE__ */ jsxs25("div", { className: "flex w-full flex-col gap-4 border-b-1 border-black/7 px-5 py-5 md:px-7 md:py-6", children: [
3107
+ /* @__PURE__ */ jsx38("h2", { className: "text-primary text-2xl font-semibold", children: "Choose a Payment Method" }),
3108
+ /* @__PURE__ */ jsx38(TabButtons, { value: selectedPaymentMethod.type, onChange: setSelectedPaymentMethod })
1731
3109
  ] }),
1732
- selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && /* @__PURE__ */ jsx26(CreditCardTab, { pointsTitle, pointsConversionRatio }),
1733
- selectedPaymentMethod.type === "CRYPTO" /* CRYPTO */ && /* @__PURE__ */ jsx26(CryptoTab, { pointsTitle, pointsConversionRatio })
3110
+ selectedPaymentMethod.type === "CREDIT_CARD" /* CREDIT_CARD */ && /* @__PURE__ */ jsx38(CreditCardTab, {}),
3111
+ selectedPaymentMethod.type === "CRYPTO" /* CRYPTO */ && /* @__PURE__ */ jsx38(CryptoTab, {})
1734
3112
  ] });
1735
3113
  };
1736
3114
 
1737
3115
  // src/SpreePayContent.tsx
1738
- import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
1739
- var SpreePayContent = (props) => {
1740
- const { isLoggedIn, config: config2, amount, onProcess, isProcessing } = props;
1741
- return /* @__PURE__ */ jsxs21("div", { className: "w-full", children: [
1742
- /* @__PURE__ */ jsx27(Tabs, { config: config2 }),
1743
- /* @__PURE__ */ jsx27(CheckoutButton, { isLoggedIn, isProcessing, onCheckout: onProcess, amount }),
1744
- /* @__PURE__ */ jsx27(SpreeLegal, {})
3116
+ import { jsx as jsx39, jsxs as jsxs26 } from "react/jsx-runtime";
3117
+ var SpreePayContent = ({ isLoggedIn }) => {
3118
+ return /* @__PURE__ */ jsxs26("div", { className: "w-full", children: [
3119
+ /* @__PURE__ */ jsx39(Tabs, {}),
3120
+ /* @__PURE__ */ jsx39(CheckoutButton, { isLoggedIn }),
3121
+ /* @__PURE__ */ jsx39(SpreeLegal, {})
1745
3122
  ] });
1746
3123
  };
1747
3124
 
1748
3125
  // src/hooks/useKeycloakSSO.ts
1749
- import { useCallback as useCallback4, useEffect as useEffect5, useRef as useRef2, useState as useState6 } from "react";
3126
+ import { useCallback as useCallback7, useEffect as useEffect10, useRef as useRef6, useState as useState12 } from "react";
1750
3127
  import Keycloak from "keycloak-js";
1751
3128
  var refreshAheadSeconds = 60;
1752
3129
  function useKeycloakSSO(config2) {
1753
3130
  const { url, realm, clientId, ssoPageURI, enabled } = config2;
1754
- const initRef = useRef2(false);
1755
- const kcRef = useRef2(null);
1756
- const refreshTimerRef = useRef2(null);
1757
- const [error, setError] = useState6(null);
1758
- const [isChecking, setIsChecking] = useState6(enabled);
1759
- const [accessToken, setAccessToken] = useState6(null);
1760
- const scheduleRefresh = useCallback4(() => {
3131
+ const initRef = useRef6(false);
3132
+ const kcRef = useRef6(null);
3133
+ const refreshTimerRef = useRef6(null);
3134
+ const [error, setError] = useState12(null);
3135
+ const [isChecking, setIsChecking] = useState12(enabled);
3136
+ const [accessToken, setAccessToken] = useState12(null);
3137
+ const scheduleRefresh = useCallback7(() => {
1761
3138
  const kc = kcRef.current;
1762
3139
  if (!kc || !kc.tokenParsed || !kc.tokenParsed.exp) {
1763
3140
  return;
@@ -1778,7 +3155,7 @@ function useKeycloakSSO(config2) {
1778
3155
  });
1779
3156
  }, delayMs);
1780
3157
  }, []);
1781
- useEffect5(() => {
3158
+ useEffect10(() => {
1782
3159
  if (initRef.current || !enabled) return;
1783
3160
  initRef.current = true;
1784
3161
  setIsChecking(true);
@@ -1813,94 +3190,43 @@ function useKeycloakSSO(config2) {
1813
3190
  }
1814
3191
 
1815
3192
  // src/SpreePay.tsx
1816
- import { jsx as jsx28, jsxs as jsxs22 } from "react/jsx-runtime";
1817
- var CONFIG = {
1818
- dev: {
1819
- bookit: {
1820
- slapiUrl: "https://slapi.dev.superlogic.com",
1821
- keyklockUrl: "https://auth.dev.join.bookit.com",
1822
- keyklockClientId: "oneof-next",
1823
- pointsConversionRatio: 100,
1824
- pointsTitle: "AIR SP"
1825
- },
1826
- moca: {
1827
- slapiUrl: "https://slapi.dev.air.shop",
1828
- keyklockUrl: "https://login.dev.air.shop",
1829
- keyklockClientId: "oneof-next",
1830
- pointsConversionRatio: 100,
1831
- pointsTitle: "AIR SP"
1832
- }
1833
- },
1834
- stg: {
1835
- bookit: {
1836
- slapiUrl: "https://slapi.stg.superlogic.com",
1837
- keyklockUrl: "https://auth.stg.join.bookit.com",
1838
- keyklockClientId: "oneof-next",
1839
- pointsConversionRatio: 100,
1840
- pointsTitle: "AIR SP"
1841
- },
1842
- moca: {
1843
- slapiUrl: "https://slapi.stg.air.shop",
1844
- keyklockUrl: "https://login.stg.air.shop",
1845
- keyklockClientId: "oneof-next",
1846
- pointsConversionRatio: 100,
1847
- pointsTitle: "AIR SP"
1848
- }
1849
- },
1850
- prod: {
1851
- bookit: {
1852
- slapiUrl: "https://slapi.superlogic.com",
1853
- keyklockUrl: "https://auth.join.bookit.com",
1854
- keyklockClientId: "oneof-next",
1855
- pointsConversionRatio: 100,
1856
- pointsTitle: "AIR SP"
1857
- },
1858
- moca: {
1859
- slapiUrl: "https://slapi.air.shop",
1860
- keyklockUrl: "https://login.air.shop",
1861
- keyklockClientId: "oneof-next",
1862
- pointsConversionRatio: 100,
1863
- pointsTitle: "AIR SP"
1864
- }
1865
- }
1866
- };
1867
- var SpreePay = ({ className, ...rest }) => {
1868
- const rootRef = useRef3(null);
1869
- const [portalEl, setPortalEl] = useState7(null);
1870
- useLayoutEffect(() => {
3193
+ import { jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
3194
+ var SpreePayInner = () => {
3195
+ const rootRef = useRef7(null);
3196
+ const [portalEl, setPortalEl] = useState13(null);
3197
+ useLayoutEffect3(() => {
1871
3198
  if (!rootRef.current) return;
1872
3199
  const el = rootRef.current.querySelector(":scope > .sl-spreepay__portal");
1873
3200
  setPortalEl(el ?? null);
1874
3201
  }, []);
1875
3202
  const { env } = useSpreePayEnv();
1876
- const environment = env?.environment || "dev";
3203
+ const { staticConfig, appProps } = useStaticConfig();
1877
3204
  const tenantId = env?.tenantId || "bookit";
1878
- const config2 = CONFIG[environment]?.[tenantId];
1879
3205
  const { isChecking, accessToken } = useKeycloakSSO({
1880
3206
  realm: tenantId,
1881
- url: config2.keyklockUrl,
1882
- clientId: config2.keyklockClientId,
3207
+ url: staticConfig.keycloakUrl,
3208
+ clientId: staticConfig.keycloakClientId,
1883
3209
  ssoPageURI: env?.ssoPageURI,
1884
3210
  enabled: !env?.accessToken
1885
3211
  });
1886
- const slapiFetcher = useMemo2(() => {
3212
+ const slapiFetcher = useMemo8(() => {
1887
3213
  if (accessToken || env.accessToken) {
1888
3214
  return registerApi({
1889
3215
  accessToken: env.accessToken || accessToken,
1890
3216
  tenantId,
1891
- baseUrl: config2.slapiUrl
3217
+ baseUrl: staticConfig.slapiUrl
1892
3218
  });
1893
3219
  }
1894
- }, [env.accessToken, config2, tenantId, accessToken]);
3220
+ }, [env.accessToken, staticConfig, tenantId, accessToken]);
1895
3221
  const getContent = () => {
1896
3222
  if (isChecking) {
1897
- return /* @__PURE__ */ jsxs22("div", { className: "flex w-full flex-col", children: [
1898
- /* @__PURE__ */ jsx28("div", { className: "bg-primary/8 mb-4 h-[315px] animate-pulse rounded-3xl" }),
1899
- /* @__PURE__ */ jsx28("div", { className: "bg-primary/8 h-[135px] animate-pulse rounded-3xl" }),
1900
- /* @__PURE__ */ jsx28(SpreeLegal, {})
3223
+ return /* @__PURE__ */ jsxs27("div", { className: "flex w-full flex-col", children: [
3224
+ /* @__PURE__ */ jsx40("div", { className: "bg-primary/8 mb-4 h-[315px] animate-pulse rounded-3xl" }),
3225
+ /* @__PURE__ */ jsx40("div", { className: "bg-primary/8 h-[135px] animate-pulse rounded-3xl" }),
3226
+ /* @__PURE__ */ jsx40(SpreeLegal, {})
1901
3227
  ] });
1902
3228
  }
1903
- return /* @__PURE__ */ jsx28(
3229
+ return /* @__PURE__ */ jsx40(
1904
3230
  SWRConfig,
1905
3231
  {
1906
3232
  value: {
@@ -1909,26 +3235,30 @@ var SpreePay = ({ className, ...rest }) => {
1909
3235
  revalidateOnFocus: false,
1910
3236
  revalidateIfStale: false
1911
3237
  },
1912
- children: /* @__PURE__ */ jsx28(PortalContainerProvider, { container: portalEl, children: /* @__PURE__ */ jsx28(NiceModal6.Provider, { children: /* @__PURE__ */ jsx28(SpreePayContent, { isLoggedIn: Boolean(accessToken || env.accessToken), config: config2, ...rest }) }) })
3238
+ children: /* @__PURE__ */ jsx40(PortalContainerProvider, { container: portalEl, children: /* @__PURE__ */ jsx40(NiceModal7.Provider, { children: /* @__PURE__ */ jsx40(SpreePayContent, { isLoggedIn: Boolean(accessToken || env.accessToken) }) }) })
1913
3239
  }
1914
3240
  );
1915
3241
  };
1916
- return /* @__PURE__ */ jsxs22("div", { ref: rootRef, className: cn("sl-spreepay", className), children: [
1917
- /* @__PURE__ */ jsx28("div", { className: "sl-spreepay__portal" }),
3242
+ return /* @__PURE__ */ jsxs27("div", { ref: rootRef, className: cn("sl-spreepay", appProps.className), children: [
3243
+ /* @__PURE__ */ jsx40("div", { className: "sl-spreepay__portal" }),
1918
3244
  getContent()
1919
3245
  ] });
1920
3246
  };
3247
+ var SpreePay = (props) => {
3248
+ return /* @__PURE__ */ jsx40(StaticConfigProvider, { props, children: /* @__PURE__ */ jsx40(SpreePayInner, {}) });
3249
+ };
1921
3250
 
1922
3251
  // src/hooks/useCapture3DS.ts
1923
- import { useEffect as useEffect6 } from "react";
3252
+ import { useEffect as useEffect11 } from "react";
1924
3253
  var useCapture3DS = (searchParams) => {
1925
- useEffect6(() => {
1926
- if (window?.parent && searchParams?.paymentIntent) {
3254
+ useEffect11(() => {
3255
+ if (typeof window !== "undefined" && window.parent && searchParams?.paymentIntent) {
1927
3256
  window.parent.SP_EVENT_BUS?.emit("paymentIntent", { paymentIntent: searchParams.paymentIntent });
1928
3257
  }
1929
3258
  }, [searchParams]);
1930
3259
  };
1931
3260
  export {
3261
+ PaymentType,
1932
3262
  SpreePay,
1933
3263
  SpreePayProvider,
1934
3264
  useCapture3DS,