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