@miden-npm/react 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1822 @@
1
+ // src/client.ts
2
+ var MidenPGClient = class {
3
+ constructor(cfg) {
4
+ this.cfg = cfg;
5
+ this.base = cfg.apiBaseUrl ?? "https://api.buzapay.com";
6
+ }
7
+ async createPaymentIntent(params) {
8
+ const res = await fetch(`${this.base}/v1/payment_intents`, {
9
+ method: "POST",
10
+ headers: {
11
+ "Content-Type": "application/json",
12
+ "X-Publishable-Key": this.cfg.publishableKey
13
+ },
14
+ body: JSON.stringify(params)
15
+ });
16
+ if (!res.ok) throw new Error(`Failed to create PI: ${res.status}`);
17
+ return res.json();
18
+ }
19
+ async confirmCardPayment(params) {
20
+ const res = await fetch(`${this.base}/v1/payment_intents/confirm`, {
21
+ method: "POST",
22
+ headers: {
23
+ "Content-Type": "application/json",
24
+ "X-Publishable-Key": this.cfg.publishableKey
25
+ },
26
+ body: JSON.stringify(params)
27
+ });
28
+ if (!res.ok) throw new Error(`Failed to confirm: ${res.status}`);
29
+ return res.json();
30
+ }
31
+ };
32
+
33
+ // src/provider.tsx
34
+ import { createContext, useContext, useMemo } from "react";
35
+ import { jsx } from "react/jsx-runtime";
36
+ var Ctx = createContext(null);
37
+ var MidenPGProvider = ({ config, children }) => {
38
+ const client = useMemo(
39
+ () => new MidenPGClient(config),
40
+ [config.publishableKey, config.apiBaseUrl]
41
+ );
42
+ return /* @__PURE__ */ jsx(Ctx.Provider, { value: client, children });
43
+ };
44
+ var useMidenPGClient = () => {
45
+ const ctx = useContext(Ctx);
46
+ if (!ctx)
47
+ throw new Error("useMidenPGClient must be used within MidenPGProvider");
48
+ return ctx;
49
+ };
50
+
51
+ // src/hooks.ts
52
+ import { useCallback } from "react";
53
+ function usePaymentIntents() {
54
+ const client = useMidenPGClient();
55
+ const create = useCallback(
56
+ (p) => client.createPaymentIntent(p),
57
+ [client]
58
+ );
59
+ const confirm = useCallback(
60
+ (p) => client.confirmCardPayment(p),
61
+ [client]
62
+ );
63
+ return { create, confirm };
64
+ }
65
+
66
+ // src/buzapay-checkout/checkout-button.tsx
67
+ import { useState as useState3 } from "react";
68
+
69
+ // src/utils/object.util.ts
70
+ var checkObjectTruthy = (obj) => {
71
+ if (obj == null || typeof obj !== "object") return false;
72
+ return Object.values(obj).every(Boolean);
73
+ };
74
+
75
+ // src/utils/api.util.ts
76
+ var getBaseUrl = (mode) => {
77
+ return mode === "sandbox" ? "https://sandbox-api.midencards.io/payment-gateway-api" : "";
78
+ };
79
+
80
+ // src/utils/string.util.ts
81
+ var currencySign = (currency) => {
82
+ if (currency === "USD") return "$";
83
+ if (currency === "NGN") return "\u20A6";
84
+ if (currency === "EUR") return "\u20AC";
85
+ if (currency === "GBP") return "\xA3";
86
+ if (currency === "JPY") return "\xA5";
87
+ if (currency === "CNY") return "\xA5";
88
+ if (currency === "USDC" || currency === "usdc") return "$\u29EB";
89
+ if (currency === "USDT" || currency === "usdt") return "\u20AE";
90
+ return "$";
91
+ };
92
+ var formatAmount = (value, currency) => {
93
+ const num = typeof value === "string" ? parseFloat(value) : value;
94
+ if (isNaN(num)) return "0";
95
+ return `${currency ? currencySign(currency) : ""} ${num?.toLocaleString(
96
+ "en-US"
97
+ )}`;
98
+ };
99
+ var truncateString = (str, num) => {
100
+ if (str.length <= num) {
101
+ return str;
102
+ }
103
+ return str.slice(0, num) + "...";
104
+ };
105
+
106
+ // src/utils/input.util.ts
107
+ var restrictToNumericKeys = (event) => {
108
+ const allowedKeys = [
109
+ "Backspace",
110
+ "Tab",
111
+ "ArrowLeft",
112
+ "ArrowRight",
113
+ "Delete",
114
+ "Home",
115
+ "End",
116
+ "."
117
+ ];
118
+ if ((event.ctrlKey || event.metaKey) && ["a", "c", "v", "x"].includes(event.key.toLowerCase())) {
119
+ return;
120
+ }
121
+ if (!allowedKeys.includes(event.key) && !/^\d$/.test(event.key)) {
122
+ event.preventDefault();
123
+ }
124
+ if (event.key === "." && event.target.value.includes(".")) {
125
+ event.preventDefault();
126
+ }
127
+ };
128
+
129
+ // src/apis/checkout.api.ts
130
+ async function createPaymentLink(paymentObject, environment, secretKey) {
131
+ try {
132
+ const baseUrl = getBaseUrl(environment);
133
+ const res = await fetch(
134
+ `${baseUrl}/api/v1/checkout/generate-payment-link2`,
135
+ {
136
+ method: "POST",
137
+ headers: {
138
+ "Content-Type": "application/json",
139
+ Accept: "application/json",
140
+ merchantId: secretKey
141
+ },
142
+ body: JSON.stringify({
143
+ ...paymentObject,
144
+ LinkName: `${Date.now()}-Link`
145
+ })
146
+ }
147
+ );
148
+ return await res.json();
149
+ } catch (error) {
150
+ }
151
+ }
152
+
153
+ // src/components/base/input-error.tsx
154
+ import { jsx as jsx2 } from "react/jsx-runtime";
155
+ function BaseInputError({ errorMessage }) {
156
+ return /* @__PURE__ */ jsx2("p", { className: "mb-0 text-body-3xs font-normal text-red-500", children: errorMessage });
157
+ }
158
+
159
+ // src/components/icons/icon-loader.tsx
160
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
161
+ function IconLoader({
162
+ size = 24,
163
+ color = "currentColor",
164
+ className = "",
165
+ ...props
166
+ }) {
167
+ return /* @__PURE__ */ jsxs(
168
+ "svg",
169
+ {
170
+ className: `animate-spin ${className}`,
171
+ xmlns: "http://www.w3.org/2000/svg",
172
+ fill: "none",
173
+ viewBox: "0 0 24 24",
174
+ width: size,
175
+ height: size,
176
+ role: "img",
177
+ "aria-label": "loading",
178
+ ...props,
179
+ children: [
180
+ /* @__PURE__ */ jsx3(
181
+ "circle",
182
+ {
183
+ className: "opacity-25",
184
+ cx: "12",
185
+ cy: "12",
186
+ r: "10",
187
+ stroke: color,
188
+ strokeWidth: 4
189
+ }
190
+ ),
191
+ /* @__PURE__ */ jsx3(
192
+ "path",
193
+ {
194
+ className: "opacity-75",
195
+ fill: color,
196
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
197
+ }
198
+ )
199
+ ]
200
+ }
201
+ );
202
+ }
203
+
204
+ // src/components/icons/icon-chevron-left.tsx
205
+ import { jsx as jsx4 } from "react/jsx-runtime";
206
+ function IconChevronLeft({
207
+ width = 17,
208
+ height = 17,
209
+ color = "currentColor",
210
+ ...props
211
+ }) {
212
+ return /* @__PURE__ */ jsx4(
213
+ "svg",
214
+ {
215
+ width,
216
+ height,
217
+ viewBox: "0 0 17 17",
218
+ fill: "none",
219
+ xmlns: "http://www.w3.org/2000/svg",
220
+ ...props,
221
+ children: /* @__PURE__ */ jsx4(
222
+ "path",
223
+ {
224
+ d: "M10.5 14.28C10.3734 14.28 10.2467 14.2333 10.1467 14.1333L5.80002 9.78668C5.09335 9.08001 5.09335 7.92001 5.80002 7.21335L10.1467 2.86668C10.34 2.67335 10.66 2.67335 10.8534 2.86668C11.0467 3.06001 11.0467 3.38001 10.8534 3.57335L6.50669 7.92001C6.18669 8.24001 6.18669 8.76001 6.50669 9.08001L10.8534 13.4267C11.0467 13.62 11.0467 13.94 10.8534 14.1333C10.7534 14.2267 10.6267 14.28 10.5 14.28Z",
225
+ fill: color
226
+ }
227
+ )
228
+ }
229
+ );
230
+ }
231
+
232
+ // src/components/icons/icon-buzapay-icon.tsx
233
+ import { jsx as jsx5 } from "react/jsx-runtime";
234
+ function IconBuzapayIcon({
235
+ width = 15,
236
+ height = 13,
237
+ color = "currentColor",
238
+ ...props
239
+ }) {
240
+ return /* @__PURE__ */ jsx5(
241
+ "svg",
242
+ {
243
+ width,
244
+ height,
245
+ viewBox: "0 0 15 13",
246
+ fill: "none",
247
+ xmlns: "http://www.w3.org/2000/svg",
248
+ ...props,
249
+ children: /* @__PURE__ */ jsx5(
250
+ "path",
251
+ {
252
+ d: "M9.97919 0.5C10.8854 0.5 11.6276 0.585938 12.2057 0.757812C12.7891 0.924479 13.2188 1.22396 13.4948 1.65625C13.7761 2.08333 13.9167 2.6901 13.9167 3.47656C13.9167 4.1849 13.7526 4.77083 13.4245 5.23438C13.0964 5.69792 12.5938 5.95312 11.9167 6C12.8021 6.08854 13.4401 6.40625 13.8307 6.95312C14.2214 7.49479 14.4167 8.17708 14.4167 9C14.4167 9.71354 14.3334 10.2995 14.1667 10.7578C14.0052 11.2161 13.7318 11.5729 13.3464 11.8281C12.961 12.0781 12.4375 12.2526 11.7761 12.3516C11.1198 12.4505 10.2995 12.5 9.31512 12.5H0.416687V0.5H9.97919ZM2.91669 7.77344H5.97235V11.167L10.2497 5.22754H7.19501V1.83398L2.91669 7.77344ZM5.97235 6.07617H8.2702L7.19501 7.57324V6.9248H4.89716L5.97235 5.42676V6.07617Z",
253
+ fill: color
254
+ }
255
+ )
256
+ }
257
+ );
258
+ }
259
+
260
+ // src/components/icons/icon-check-circle.tsx
261
+ import { jsx as jsx6 } from "react/jsx-runtime";
262
+ function IconCheckCircle({
263
+ width = 67,
264
+ height = 67,
265
+ color = "currentColor",
266
+ ...props
267
+ }) {
268
+ return /* @__PURE__ */ jsx6(
269
+ "svg",
270
+ {
271
+ width,
272
+ height,
273
+ viewBox: "0 0 67 67",
274
+ fill: "none",
275
+ xmlns: "http://www.w3.org/2000/svg",
276
+ ...props,
277
+ children: /* @__PURE__ */ jsx6(
278
+ "path",
279
+ {
280
+ d: "M33.6705 0.0820312C15.2758 0.0820312 0.36377 14.9941 0.36377 33.3888C0.36377 51.7846 15.2758 66.6956 33.6705 66.6956C52.0663 66.6956 66.9773 51.7846 66.9773 33.3888C66.9773 14.9941 52.0663 0.0820312 33.6705 0.0820312ZM33.6705 62.5978C17.6011 62.5978 4.52712 49.4583 4.52712 33.3887C4.52712 17.3192 17.6011 4.24525 33.6705 4.24525C49.74 4.24525 62.814 17.3193 62.814 33.3887C62.814 49.4581 49.74 62.5978 33.6705 62.5978ZM46.9631 21.2016L27.4213 40.8662L18.621 32.0659C17.8081 31.253 16.4904 31.253 15.6765 32.0659C14.8636 32.8788 14.8636 34.1965 15.6765 35.0094L25.9797 45.3137C26.7926 46.1255 28.1103 46.1255 28.9243 45.3137C29.0179 45.22 29.0981 45.1179 29.171 45.0118L49.9086 24.1461C50.7205 23.3332 50.7205 22.0155 49.9086 21.2016C49.0947 20.3888 47.777 20.3888 46.9631 21.2016Z",
281
+ fill: color
282
+ }
283
+ )
284
+ }
285
+ );
286
+ }
287
+
288
+ // src/components/icons/icon-copy-success.tsx
289
+ import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
290
+ function IconCopySuccess({
291
+ width = 16,
292
+ height = 17,
293
+ color = "currentColor",
294
+ ...props
295
+ }) {
296
+ return /* @__PURE__ */ jsxs2(
297
+ "svg",
298
+ {
299
+ width,
300
+ height,
301
+ viewBox: "0 0 16 17",
302
+ fill: "none",
303
+ xmlns: "http://www.w3.org/2000/svg",
304
+ ...props,
305
+ children: [
306
+ /* @__PURE__ */ jsx7(
307
+ "path",
308
+ {
309
+ d: "M11.4002 1.6875H8.60016C5.9935 1.6875 4.8335 2.8475 4.8335 5.45417V6.1875C4.8335 6.46083 5.06016 6.6875 5.3335 6.6875H7.40016C9.46683 6.6875 10.1668 7.3875 10.1668 9.45417V11.5208C10.1668 11.7942 10.3935 12.0208 10.6668 12.0208H11.4002C14.0068 12.0208 15.1668 10.8608 15.1668 8.25417V5.45417C15.1668 2.8475 14.0068 1.6875 11.4002 1.6875ZM5.8335 5.6875V5.45417C5.8335 3.3875 6.5335 2.6875 8.60016 2.6875H11.4002C13.4668 2.6875 14.1668 3.3875 14.1668 5.45417V8.25417C14.1668 10.3208 13.4668 11.0208 11.4002 11.0208H11.1668V9.45417C11.1668 6.8475 10.0068 5.6875 7.40016 5.6875H5.8335Z",
310
+ fill: color
311
+ }
312
+ ),
313
+ /* @__PURE__ */ jsx7(
314
+ "path",
315
+ {
316
+ d: "M7.40016 5.6875H4.60016C1.9935 5.6875 0.833496 6.8475 0.833496 9.45417V12.2542C0.833496 14.8608 1.9935 16.0208 4.60016 16.0208H7.40016C10.0068 16.0208 11.1668 14.8608 11.1668 12.2542V9.45417C11.1668 6.8475 10.0068 5.6875 7.40016 5.6875ZM4.60016 15.0208C2.5335 15.0208 1.8335 14.3208 1.8335 12.2542V9.45417C1.8335 7.3875 2.5335 6.6875 4.60016 6.6875H7.40016C9.46683 6.6875 10.1668 7.3875 10.1668 9.45417V12.2542C10.1668 14.3208 9.46683 15.0208 7.40016 15.0208H4.60016Z",
317
+ fill: color
318
+ }
319
+ ),
320
+ /* @__PURE__ */ jsx7(
321
+ "path",
322
+ {
323
+ d: "M5.35302 12.6542C5.22635 12.6542 5.09969 12.6075 4.99969 12.5075L3.69969 11.2075C3.50635 11.0142 3.50635 10.6942 3.69969 10.5008C3.89302 10.3075 4.21302 10.3075 4.40635 10.5008L5.35302 11.4475L7.59302 9.2075C7.78635 9.01417 8.10635 9.01417 8.29969 9.2075C8.49302 9.40083 8.49302 9.72083 8.29969 9.91417L5.69969 12.5075C5.60635 12.6008 5.47969 12.6542 5.35302 12.6542Z",
324
+ fill: color
325
+ }
326
+ )
327
+ ]
328
+ }
329
+ );
330
+ }
331
+
332
+ // src/components/icons/icon-chevron-up.tsx
333
+ import { jsx as jsx8 } from "react/jsx-runtime";
334
+ function IconChevronUp({
335
+ width = 24,
336
+ height = 24,
337
+ color = "currentColor",
338
+ ...props
339
+ }) {
340
+ return /* @__PURE__ */ jsx8(
341
+ "svg",
342
+ {
343
+ width,
344
+ height,
345
+ viewBox: "0 0 16 16",
346
+ fill: "none",
347
+ xmlns: "http://www.w3.org/2000/svg",
348
+ ...props,
349
+ children: /* @__PURE__ */ jsx8("g", { opacity: "0.7", children: /* @__PURE__ */ jsx8(
350
+ "path",
351
+ {
352
+ d: "M2.73508 9.73495L7.73508 4.73495C7.80539 4.66473 7.9007 4.62528 8.00008 4.62528C8.09945 4.62528 8.19476 4.66473 8.26508 4.73495L13.2651 9.73495C13.3313 9.80604 13.3674 9.90006 13.3657 9.99722C13.364 10.0944 13.3246 10.1871 13.2559 10.2558C13.1872 10.3245 13.0945 10.3638 12.9973 10.3655C12.9002 10.3673 12.8062 10.3312 12.7351 10.265L8.00008 5.53058L3.26508 10.265C3.19399 10.3312 3.09997 10.3673 3.00282 10.3655C2.90566 10.3638 2.81297 10.3245 2.74427 10.2558C2.67556 10.1871 2.6362 10.0944 2.63449 9.99722C2.63277 9.90006 2.66884 9.80604 2.73508 9.73495Z",
353
+ fill: color
354
+ }
355
+ ) })
356
+ }
357
+ );
358
+ }
359
+
360
+ // src/components/icons/icon-chevron-down.tsx
361
+ import { jsx as jsx9 } from "react/jsx-runtime";
362
+ function IconChevronDown({
363
+ width = 24,
364
+ height = 24,
365
+ color = "currentColor",
366
+ ...props
367
+ }) {
368
+ return /* @__PURE__ */ jsx9(
369
+ "svg",
370
+ {
371
+ width,
372
+ height,
373
+ viewBox: "0 0 20 20",
374
+ fill: "none",
375
+ xmlns: "http://www.w3.org/2000/svg",
376
+ ...props,
377
+ children: /* @__PURE__ */ jsx9("g", { opacity: "0.6", children: /* @__PURE__ */ jsx9(
378
+ "path",
379
+ {
380
+ d: "M16.5813 7.83128L10.3313 14.0813C10.2434 14.1691 10.1242 14.2184 10 14.2184C9.87581 14.2184 9.75667 14.1691 9.66878 14.0813L3.41878 7.83128C3.33598 7.74242 3.2909 7.62489 3.29304 7.50345C3.29518 7.38201 3.34438 7.26615 3.43026 7.18026C3.51615 7.09438 3.63201 7.04518 3.75345 7.04304C3.87489 7.0409 3.99242 7.08598 4.08128 7.16878L10 13.0867L15.9188 7.16878C16.0076 7.08598 16.1252 7.0409 16.2466 7.04304C16.368 7.04518 16.4839 7.09438 16.5698 7.18026C16.6557 7.26615 16.7049 7.38201 16.707 7.50345C16.7092 7.62489 16.6641 7.74242 16.5813 7.83128Z",
381
+ fill: color
382
+ }
383
+ ) })
384
+ }
385
+ );
386
+ }
387
+
388
+ // src/components/icons/icon-usdt.tsx
389
+ import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
390
+ function IconUsdt({
391
+ width = 28,
392
+ height = 28,
393
+ color = "currentColor",
394
+ ...props
395
+ }) {
396
+ return /* @__PURE__ */ jsxs3(
397
+ "svg",
398
+ {
399
+ width,
400
+ height,
401
+ viewBox: "0 0 28 28",
402
+ fill: "none",
403
+ xmlns: "http://www.w3.org/2000/svg",
404
+ ...props,
405
+ children: [
406
+ /* @__PURE__ */ jsx10("g", { "clip-path": "url(#clip0_10908_387045)", children: /* @__PURE__ */ jsx10(
407
+ "path",
408
+ {
409
+ "fill-rule": "evenodd",
410
+ "clip-rule": "evenodd",
411
+ d: "M14 28C6.26763 28 0 21.7324 0 14C0 6.26763 6.26763 0 14 0C21.7324 0 28 6.26763 28 14C28 21.7324 21.7324 28 14 28ZM15.6818 12.0689V9.99863H20.419V6.84162H7.52063V9.99863H12.2579V12.068C8.40787 12.2447 5.5125 13.0077 5.5125 13.9212C5.5125 14.8347 8.40787 15.5969 12.2579 15.7745V22.4088H15.6818V15.7727C19.5256 15.596 22.414 14.8339 22.414 13.9212C22.414 13.0086 19.5256 12.2465 15.6818 12.0689ZM15.6818 15.2101V15.2084C15.5855 15.2154 15.0894 15.2451 13.9825 15.2451C13.0987 15.2451 12.4766 15.2189 12.2579 15.2084V15.211C8.85587 15.0614 6.31662 14.469 6.31662 13.7602C6.31662 13.0524 8.85587 12.46 12.2579 12.3077V14.6212C12.4801 14.637 13.1171 14.6746 13.9974 14.6746C15.0535 14.6746 15.5829 14.6309 15.6818 14.6221V12.3095C19.0768 12.4609 21.6099 13.0532 21.6099 13.7602C21.6099 14.469 19.0768 15.0596 15.6818 15.2101Z",
412
+ fill: color
413
+ }
414
+ ) }),
415
+ /* @__PURE__ */ jsx10("defs", { children: /* @__PURE__ */ jsx10("clipPath", { id: "clip0_10908_387045", children: /* @__PURE__ */ jsx10("rect", { width: "28", height: "28", fill: color }) }) })
416
+ ]
417
+ }
418
+ );
419
+ }
420
+
421
+ // src/components/icons/icon-usdc.tsx
422
+ import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
423
+ function IconUsdc({
424
+ width = 28,
425
+ height = 28,
426
+ color = "currentColor",
427
+ ...props
428
+ }) {
429
+ return /* @__PURE__ */ jsxs4(
430
+ "svg",
431
+ {
432
+ width,
433
+ height,
434
+ viewBox: "0 0 28 28",
435
+ fill: "none",
436
+ xmlns: "http://www.w3.org/2000/svg",
437
+ ...props,
438
+ children: [
439
+ /* @__PURE__ */ jsx11("g", { "clip-path": "url(#clip0_10908_387048)", children: /* @__PURE__ */ jsx11(
440
+ "path",
441
+ {
442
+ d: "M14 0C21.7324 0 28 6.26763 28 14C28 21.7324 21.7324 28 14 28C6.26763 28 0 21.7324 0 14C0 6.26763 6.26763 0 14 0ZM16.933 4.865C16.7195 4.76 16.506 4.865 16.4535 5.07762C16.4001 5.131 16.4001 5.18438 16.4001 5.29025V6.034L16.4089 6.125C16.4546 6.30501 16.5652 6.46177 16.7195 6.56512C20.8792 8.05262 23.0125 12.6726 21.4655 16.7615C20.6657 18.9928 18.9061 20.6911 16.7195 21.4883C16.506 21.5941 16.4001 21.7534 16.4001 22.0194V22.7631L16.4045 22.8401C16.4128 22.9241 16.4479 23.0033 16.5047 23.0658C16.5614 23.1284 16.6367 23.171 16.7195 23.1875C16.7729 23.1875 16.8796 23.1875 16.933 23.135C18.1331 22.7602 19.2473 22.1517 20.2113 21.3446C21.1753 20.5375 21.9701 19.5476 22.5499 18.432C23.1298 17.3164 23.4833 16.0972 23.59 14.8444C23.6967 13.5917 23.5546 12.3302 23.1718 11.1326C22.2128 8.10512 19.866 5.8205 16.933 4.865ZM11.2805 4.8125C11.2271 4.8125 11.1204 4.8125 11.067 4.865C9.86688 5.23978 8.75274 5.84826 7.78874 6.6554C6.82475 7.46254 6.02993 8.4524 5.45006 9.56797C4.87019 10.6836 4.51673 11.9028 4.41001 13.1556C4.30329 14.4083 4.44543 15.6698 4.82825 16.8674C5.78725 19.8424 8.08062 22.1261 11.067 23.0816C11.2805 23.1875 11.494 23.0816 11.5465 22.869C11.5999 22.8165 11.5999 22.7622 11.5999 22.6564V21.9126L11.5911 21.8426C11.5544 21.6947 11.417 21.5259 11.2805 21.4349C7.12075 19.9474 4.9875 15.3274 6.5345 11.2385C7.33425 9.00725 9.09388 7.30887 11.2805 6.51175C11.494 6.40587 11.5999 6.24663 11.5999 5.98063V5.23688L11.5955 5.15987C11.5872 5.07585 11.5521 4.99673 11.4954 4.93418C11.4386 4.87163 11.3633 4.82898 11.2805 4.8125ZM14.3736 7.574H13.573L13.496 7.581C13.321 7.616 13.1933 7.7665 13.146 7.99925V9.22075L12.9649 9.24875C11.4704 9.51475 10.5341 10.5464 10.5341 11.823C10.5341 13.5748 11.5999 14.2651 13.8399 14.5311C15.3335 14.7963 15.813 15.1156 15.813 15.9653C15.813 16.814 15.0666 17.3985 14.0534 17.3985C12.6665 17.3985 12.187 16.8149 12.0269 16.0177C11.9744 15.806 11.8134 15.6992 11.6532 15.6992H10.7467L10.6776 15.7054C10.5913 15.7193 10.513 15.7641 10.4572 15.8313C10.4014 15.8985 10.3718 15.9838 10.374 16.0711V16.1236L10.4029 16.2811C10.6566 17.5271 11.5106 18.4187 13.2003 18.6734V19.9483L13.2072 20.0252C13.2422 20.1985 13.3936 20.3263 13.6273 20.3726H14.427L14.504 20.3656C14.679 20.3306 14.8067 20.1801 14.854 19.9483V18.6725L15.0351 18.6375C16.534 18.3207 17.5201 17.2366 17.5201 15.8576C17.5201 13.9991 16.4001 13.3621 14.1601 13.0961C12.5598 12.8835 12.2404 12.4591 12.2404 11.7154C12.2404 10.9716 12.7741 10.4939 13.8399 10.4939C14.7998 10.4939 15.3335 10.8124 15.5995 11.6095C15.6272 11.6866 15.6779 11.7533 15.7447 11.8007C15.8115 11.8481 15.8912 11.8739 15.9731 11.8746H16.8262L16.8954 11.8694C16.982 11.8556 17.0606 11.8108 17.1166 11.7434C17.1726 11.6759 17.2022 11.5904 17.1999 11.5027V11.4503L17.1675 11.2989C17.0361 10.755 16.7366 10.2664 16.3115 9.90255C15.8864 9.53872 15.3574 9.31821 14.7997 9.27238V7.99925L14.7928 7.92225C14.7578 7.74812 14.6073 7.62038 14.3736 7.574Z",
443
+ fill: color
444
+ }
445
+ ) }),
446
+ /* @__PURE__ */ jsx11("defs", { children: /* @__PURE__ */ jsx11("clipPath", { id: "clip0_10908_387048", children: /* @__PURE__ */ jsx11("rect", { width: "28", height: "28", fill: color }) }) })
447
+ ]
448
+ }
449
+ );
450
+ }
451
+
452
+ // src/components/icons/icon-arrow-swap.tsx
453
+ import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
454
+ function IconArrowSwap({
455
+ width = 16,
456
+ height = 17,
457
+ color = "currentColor",
458
+ ...props
459
+ }) {
460
+ return /* @__PURE__ */ jsxs5(
461
+ "svg",
462
+ {
463
+ width,
464
+ height,
465
+ viewBox: "0 0 16 17",
466
+ fill: "none",
467
+ xmlns: "http://www.w3.org/2000/svg",
468
+ ...props,
469
+ children: [
470
+ /* @__PURE__ */ jsx12(
471
+ "path",
472
+ {
473
+ d: "M10.3265 14.1948C10.1998 14.1948 10.0731 14.1481 9.97313 14.0481C9.77979 13.8548 9.77979 13.5348 9.97313 13.3414L13.3131 10.0014C13.5065 9.80811 13.8265 9.80811 14.0198 10.0014C14.2131 10.1948 14.2131 10.5148 14.0198 10.7081L10.6798 14.0481C10.5798 14.1414 10.4531 14.1948 10.3265 14.1948Z",
474
+ fill: color
475
+ }
476
+ ),
477
+ /* @__PURE__ */ jsx12(
478
+ "path",
479
+ {
480
+ d: "M13.6668 10.8477H2.3335C2.06016 10.8477 1.8335 10.621 1.8335 10.3477C1.8335 10.0743 2.06016 9.84766 2.3335 9.84766H13.6668C13.9402 9.84766 14.1668 10.0743 14.1668 10.3477C14.1668 10.621 13.9402 10.8477 13.6668 10.8477Z",
481
+ fill: color
482
+ }
483
+ ),
484
+ /* @__PURE__ */ jsx12(
485
+ "path",
486
+ {
487
+ d: "M2.33329 6.86079C2.20663 6.86079 2.07996 6.81413 1.97996 6.71413C1.78663 6.52079 1.78663 6.20079 1.97996 6.00746L5.31996 2.66746C5.51329 2.47413 5.83329 2.47413 6.02663 2.66746C6.21996 2.86079 6.21996 3.18079 6.02663 3.37413L2.68663 6.71413C2.59329 6.80746 2.45996 6.86079 2.33329 6.86079Z",
488
+ fill: color
489
+ }
490
+ ),
491
+ /* @__PURE__ */ jsx12(
492
+ "path",
493
+ {
494
+ d: "M13.6668 6.86133H2.3335C2.06016 6.86133 1.8335 6.63466 1.8335 6.36133C1.8335 6.08799 2.06016 5.86133 2.3335 5.86133H13.6668C13.9402 5.86133 14.1668 6.08799 14.1668 6.36133C14.1668 6.63466 13.9402 6.86133 13.6668 6.86133Z",
495
+ fill: color
496
+ }
497
+ )
498
+ ]
499
+ }
500
+ );
501
+ }
502
+
503
+ // src/components/base/button.tsx
504
+ import { Fragment, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
505
+ function getButtonBgClass(type, disabled) {
506
+ if (disabled)
507
+ return "bg-gray-200 text-gray-400 cursor-not-allowed border-gray-200";
508
+ switch (type) {
509
+ case "primary":
510
+ return "bg-primary text-white hover:bg-primary-black hover:border-primary-black border-primary";
511
+ case "secondary":
512
+ return "bg-gray-200 border-gray-200 hover:bg-gray-300 text-heading-text";
513
+ case "danger":
514
+ return "bg-red-500 border-red-500 text-white hover:bg-red-600";
515
+ case "neutral":
516
+ default:
517
+ return "bg-off-white border-grey-border hover:bg-gray-100";
518
+ }
519
+ }
520
+ function getButtonSizeClass(size) {
521
+ switch (size) {
522
+ case "de":
523
+ return "h-68px rounded-xl";
524
+ case "md":
525
+ return "h-42px rounded-lg";
526
+ case "sm":
527
+ return "h-32px rounded-md";
528
+ default:
529
+ return "h-68px rounded-xl";
530
+ }
531
+ }
532
+ function getLabelSizeClass(size) {
533
+ switch (size) {
534
+ case "de":
535
+ case "md":
536
+ case "sm":
537
+ return "text-body-2xs font-normal";
538
+ default:
539
+ return "text-body-xs font-normal";
540
+ }
541
+ }
542
+ function BaseButton({
543
+ label,
544
+ type = "neutral",
545
+ size = "de",
546
+ paddingClassX = "px-8",
547
+ disabled = false,
548
+ loading = false,
549
+ customClass,
550
+ onClick,
551
+ prefix,
552
+ suffix,
553
+ children
554
+ }) {
555
+ const isDisabled = disabled || loading;
556
+ const handleClick = () => {
557
+ if (!isDisabled) onClick?.();
558
+ };
559
+ return /* @__PURE__ */ jsxs6(
560
+ "button",
561
+ {
562
+ className: `flex items-center justify-center gap-2 py-3 border font-normal text-input-grey transition-colors duration-300 ease-in-out ${getButtonBgClass(
563
+ type,
564
+ isDisabled
565
+ )} ${getButtonSizeClass(size)} ${paddingClassX} ${customClass}`,
566
+ type: "button",
567
+ disabled: isDisabled,
568
+ onClick: handleClick,
569
+ children: [
570
+ prefix,
571
+ loading ? /* @__PURE__ */ jsx13(IconLoader, {}) : /* @__PURE__ */ jsx13("div", { children: label ? /* @__PURE__ */ jsx13("p", { className: `mb-0 ${getLabelSizeClass(size)}`, children: label }) : /* @__PURE__ */ jsx13(Fragment, { children }) }),
572
+ suffix
573
+ ]
574
+ }
575
+ );
576
+ }
577
+
578
+ // src/components/base/back.tsx
579
+ import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
580
+ function BaseBack({ back }) {
581
+ return /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 cursor-pointer", onClick: back, children: [
582
+ /* @__PURE__ */ jsx14(IconChevronLeft, {}),
583
+ /* @__PURE__ */ jsx14("p", { className: "mb-0 text-body-xs font-normal", children: "Back" })
584
+ ] });
585
+ }
586
+
587
+ // src/components/base/card.tsx
588
+ import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
589
+ function BaseCard({
590
+ showBackButton = false,
591
+ onBack,
592
+ children,
593
+ onClose
594
+ }) {
595
+ return /* @__PURE__ */ jsx15("div", { className: "checkout-card w-full h-screen flex flex-col items-center justify-center text-white", children: /* @__PURE__ */ jsxs8("div", { className: "flex w-1/2", children: [
596
+ showBackButton && /* @__PURE__ */ jsx15(BaseBack, { back: () => onBack?.() }),
597
+ /* @__PURE__ */ jsxs8("div", { className: "flex gap-2 w-full", children: [
598
+ /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-8 w-full", children: [
599
+ /* @__PURE__ */ jsx15("div", { className: "bg-off-white rounded-xl", children }),
600
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 justify-center", children: [
601
+ /* @__PURE__ */ jsx15("p", { className: "text-light-white-100 text-body-2xs font-regular", children: "Powered by Buzapay" }),
602
+ /* @__PURE__ */ jsx15(IconBuzapayIcon, { color: "#E8F4FF" })
603
+ ] })
604
+ ] }),
605
+ /* @__PURE__ */ jsx15(
606
+ "div",
607
+ {
608
+ onClick: onClose,
609
+ className: "close-icon flex flex-col items-center justify-center self-start cursor-pointer hover:bg-gray-500",
610
+ children: /* @__PURE__ */ jsx15("p", { className: "text-white", children: "x" })
611
+ }
612
+ )
613
+ ] })
614
+ ] }) });
615
+ }
616
+
617
+ // src/components/base/radio-group.tsx
618
+ import { useEffect, useState } from "react";
619
+ import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
620
+ var BaseRadioGroup = ({
621
+ options,
622
+ type = "vertical",
623
+ value,
624
+ defaultValue,
625
+ selectedChange,
626
+ className = ""
627
+ }) => {
628
+ const isControlled = value !== void 0;
629
+ const [internal, setInternal] = useState("");
630
+ useEffect(() => {
631
+ if (isControlled) return;
632
+ const initial = defaultValue ?? (options.length > 0 ? options[0].value : "");
633
+ setInternal(initial);
634
+ selectedChange?.(initial);
635
+ }, [isControlled, defaultValue, options]);
636
+ const selected = isControlled ? value : internal;
637
+ const setSelected = (v) => {
638
+ if (!isControlled) setInternal(v);
639
+ selectedChange?.(v);
640
+ };
641
+ const containerLayout = type === "horizontal" ? "flex-row gap-5" : "flex-col gap-6";
642
+ return /* @__PURE__ */ jsx16(
643
+ "div",
644
+ {
645
+ className: `flex ${containerLayout} ${className}`,
646
+ role: "radiogroup",
647
+ "aria-orientation": type === "horizontal" ? "horizontal" : "vertical",
648
+ tabIndex: 0,
649
+ children: options.map((option) => {
650
+ const isActive = selected === option.value;
651
+ return /* @__PURE__ */ jsxs9(
652
+ "div",
653
+ {
654
+ role: "radio",
655
+ "aria-checked": isActive,
656
+ tabIndex: -1,
657
+ onClick: () => setSelected(option.value),
658
+ className: "flex items-center gap-2 cursor-pointer transition-colors duration-200",
659
+ children: [
660
+ /* @__PURE__ */ jsx16(
661
+ "div",
662
+ {
663
+ className: [
664
+ "w-4 h-4 rounded-full border flex items-center justify-center",
665
+ isActive ? "bg-orange-500 border-orange-500" : "bg-white border-grey-200"
666
+ ].join(" "),
667
+ children: isActive && /* @__PURE__ */ jsx16("div", { className: "bg-white w-2 h-2 rounded-full" })
668
+ }
669
+ ),
670
+ /* @__PURE__ */ jsx16("p", { className: "mb-0 text-body-2xs font-medium text-heading-text", children: option.label })
671
+ ]
672
+ },
673
+ option.value
674
+ );
675
+ })
676
+ }
677
+ );
678
+ };
679
+
680
+ // src/components/base/image.tsx
681
+ import { jsx as jsx17 } from "react/jsx-runtime";
682
+ function BaseImage({
683
+ src,
684
+ height = 50,
685
+ width = 50,
686
+ alt = "Image",
687
+ customClass,
688
+ isFullWidth,
689
+ onClick
690
+ }) {
691
+ return /* @__PURE__ */ jsx17(
692
+ "img",
693
+ {
694
+ src,
695
+ height,
696
+ alt,
697
+ className: `${customClass} ${isFullWidth ? "w-full" : ""}`,
698
+ style: { width: isFullWidth ? "100%" : `${width}px` },
699
+ onClick
700
+ }
701
+ );
702
+ }
703
+
704
+ // src/components/base/copy.tsx
705
+ import { jsx as jsx18 } from "react/jsx-runtime";
706
+ function BaseCopy({ copyText, color }) {
707
+ const copyToClipboard = (text) => {
708
+ return navigator.clipboard.writeText(text);
709
+ };
710
+ const copyHandler = () => {
711
+ copyToClipboard(copyText).then(() => {
712
+ }).catch((err) => {
713
+ });
714
+ };
715
+ return /* @__PURE__ */ jsx18(
716
+ IconCopySuccess,
717
+ {
718
+ className: "cursor-pointer",
719
+ color,
720
+ onClick: () => copyHandler()
721
+ }
722
+ );
723
+ }
724
+
725
+ // src/components/base/label-info.tsx
726
+ import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
727
+ var BaseLabelInfo = ({
728
+ type = "vertical",
729
+ label = "",
730
+ labelCustomClass = "text-body-4xs font-medium text-light-copy",
731
+ valueImageSrc = "",
732
+ valueImageCustomClass = "",
733
+ valueImagePosition = "prefix",
734
+ hasValueCopy = false,
735
+ value = "",
736
+ valueCustomClass = "text-body-2xs font-medium text-sub-copy",
737
+ alignRight = false
738
+ }) => {
739
+ const showPrefixImg = valueImageSrc && valueImagePosition === "prefix";
740
+ const showSuffixImg = valueImageSrc && valueImagePosition === "suffix";
741
+ if (type === "vertical") {
742
+ return /* @__PURE__ */ jsxs10(
743
+ "div",
744
+ {
745
+ className: `flex flex-col gap-1 ${alignRight ? "text-right items-end" : ""}`,
746
+ children: [
747
+ /* @__PURE__ */ jsx19("p", { className: labelCustomClass, children: label.toUpperCase() }),
748
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1", children: [
749
+ showPrefixImg && /* @__PURE__ */ jsx19(
750
+ BaseImage,
751
+ {
752
+ src: valueImageSrc,
753
+ alt: value,
754
+ width: 22,
755
+ customClass: valueImageCustomClass
756
+ }
757
+ ),
758
+ !hasValueCopy ? /* @__PURE__ */ jsx19("p", { className: valueCustomClass, children: value }) : /* @__PURE__ */ jsx19("p", { className: `${valueCustomClass} truncate`, children: truncateString(value, 40) }),
759
+ hasValueCopy && /* @__PURE__ */ jsx19(BaseCopy, { copyText: value, color: "#9DBFDE" }),
760
+ showSuffixImg && /* @__PURE__ */ jsx19(
761
+ BaseImage,
762
+ {
763
+ src: valueImageSrc,
764
+ alt: value,
765
+ width: 22,
766
+ customClass: valueImageCustomClass
767
+ }
768
+ )
769
+ ] })
770
+ ]
771
+ }
772
+ );
773
+ }
774
+ return /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
775
+ /* @__PURE__ */ jsx19("p", { className: labelCustomClass, children: label.toUpperCase() }),
776
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1", children: [
777
+ showPrefixImg && /* @__PURE__ */ jsx19(
778
+ BaseImage,
779
+ {
780
+ src: valueImageSrc,
781
+ alt: value,
782
+ width: 22,
783
+ customClass: valueImageCustomClass
784
+ }
785
+ ),
786
+ /* @__PURE__ */ jsx19("p", { className: valueCustomClass, children: value }),
787
+ hasValueCopy && /* @__PURE__ */ jsx19(BaseCopy, { copyText: value, color: "#9DBFDE" }),
788
+ showSuffixImg && /* @__PURE__ */ jsx19(
789
+ BaseImage,
790
+ {
791
+ src: valueImageSrc,
792
+ alt: value,
793
+ width: 22,
794
+ customClass: valueImageCustomClass
795
+ }
796
+ )
797
+ ] })
798
+ ] });
799
+ };
800
+
801
+ // src/components/base/success.tsx
802
+ import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
803
+ var BaseSuccess = ({}) => {
804
+ return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-8 p-16", children: [
805
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-8", children: [
806
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-8", children: [
807
+ /* @__PURE__ */ jsx20(IconCheckCircle, { color: "#F47A1F", className: "mx-auto" }),
808
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col text-center", style: { gap: "2px" }, children: [
809
+ /* @__PURE__ */ jsx20("p", { className: "text-heading-text font-medium text-header-2xl", children: "\u20A62,500.00" }),
810
+ /* @__PURE__ */ jsx20("p", { className: "text-sub-copy font-regular text-body-3xs", children: "Has been paid successfully" })
811
+ ] })
812
+ ] }),
813
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col", children: [
814
+ /* @__PURE__ */ jsx20("div", { className: "py-4 border-b border-grey-100", children: /* @__PURE__ */ jsx20(
815
+ BaseLabelInfo,
816
+ {
817
+ type: "horizontal",
818
+ label: "Order ID",
819
+ value: "9900009000-8890-8829hd7"
820
+ }
821
+ ) }),
822
+ /* @__PURE__ */ jsx20("div", { className: "py-4", children: /* @__PURE__ */ jsx20(
823
+ BaseLabelInfo,
824
+ {
825
+ type: "horizontal",
826
+ label: "Payment date",
827
+ value: "July 24, 2025"
828
+ }
829
+ ) })
830
+ ] })
831
+ ] }),
832
+ /* @__PURE__ */ jsx20("div", { className: "mx-auto", style: { width: "80%" }, children: /* @__PURE__ */ jsx20(
833
+ BaseButton,
834
+ {
835
+ label: "Return to Merchant Website",
836
+ type: "secondary",
837
+ customClass: "w-full"
838
+ }
839
+ ) })
840
+ ] });
841
+ };
842
+
843
+ // src/components/base/hint.tsx
844
+ import { jsx as jsx21 } from "react/jsx-runtime";
845
+ function BaseHint({ hint }) {
846
+ return /* @__PURE__ */ jsx21("p", { className: "mb-0 text-body-3xs font-medium text-orange-500", children: hint });
847
+ }
848
+
849
+ // src/components/base/select.tsx
850
+ import React3 from "react";
851
+ import { jsx as jsx22, jsxs as jsxs12 } from "react/jsx-runtime";
852
+ var BaseSelect = ({
853
+ options,
854
+ value,
855
+ defaultValue,
856
+ onChange,
857
+ placeholder = "Select an option",
858
+ hasSearch = true,
859
+ disabled = false,
860
+ loading = false,
861
+ validationError = "",
862
+ label = "",
863
+ hint = "",
864
+ required = false,
865
+ itemImageType = null,
866
+ prefix,
867
+ className = ""
868
+ }) => {
869
+ const isControlled = value !== void 0;
870
+ const [open, setOpen] = React3.useState(false);
871
+ const [internalValue, setInternalValue] = React3.useState(
872
+ defaultValue ?? value ?? ""
873
+ );
874
+ const [filtered, setFiltered] = React3.useState(options);
875
+ const [activeIndex, setActiveIndex] = React3.useState(-1);
876
+ const triggerRef = React3.useRef(null);
877
+ const menuRef = React3.useRef(null);
878
+ const searchRef = React3.useRef(null);
879
+ React3.useEffect(() => {
880
+ if (isControlled) setInternalValue(value ?? "");
881
+ }, [isControlled, value]);
882
+ React3.useEffect(() => {
883
+ setFiltered(options);
884
+ }, [options]);
885
+ const selected = React3.useMemo(
886
+ () => options.find((o) => o.value === (isControlled ? value : internalValue)) || null,
887
+ [options, value, internalValue, isControlled]
888
+ );
889
+ const displayText = selected?.label || placeholder || (label ? `Select ${label}` : "Select an option");
890
+ const openMenu = React3.useCallback(() => {
891
+ if (disabled || open) return;
892
+ setFiltered(options);
893
+ const idx = selected ? Math.max(
894
+ 0,
895
+ options.findIndex((o) => o.value === selected.value)
896
+ ) : 0;
897
+ setActiveIndex(idx);
898
+ setOpen(true);
899
+ setTimeout(() => {
900
+ if (hasSearch && searchRef.current) {
901
+ searchRef.current.focus();
902
+ searchRef.current.select();
903
+ }
904
+ });
905
+ }, [disabled, open, options, selected, hasSearch]);
906
+ const closeMenu = React3.useCallback(() => {
907
+ if (!open) return;
908
+ setOpen(false);
909
+ setActiveIndex(-1);
910
+ }, [open]);
911
+ const toggleMenu = React3.useCallback(() => {
912
+ if (disabled) return;
913
+ open ? closeMenu() : openMenu();
914
+ }, [open, disabled, openMenu, closeMenu]);
915
+ React3.useEffect(() => {
916
+ if (!open) return;
917
+ const handler = (e) => {
918
+ const t = e.target;
919
+ const tri = triggerRef.current;
920
+ const menu = menuRef.current;
921
+ if (tri && !tri.contains(t) && menu && !menu.contains(t)) closeMenu();
922
+ };
923
+ document.addEventListener("mousedown", handler);
924
+ return () => document.removeEventListener("mousedown", handler);
925
+ }, [open, closeMenu]);
926
+ const commit = (val) => {
927
+ if (!isControlled) setInternalValue(val);
928
+ onChange?.(val);
929
+ closeMenu();
930
+ };
931
+ const onSearchInput = (e) => {
932
+ const q = e.target.value.toLowerCase();
933
+ const list = options.filter((o) => o.label.toLowerCase().includes(q));
934
+ setFiltered(list);
935
+ setActiveIndex(list.length ? 0 : -1);
936
+ };
937
+ const onTriggerKeyDown = (e) => {
938
+ if (disabled) return;
939
+ switch (e.key) {
940
+ case "Enter":
941
+ case " ":
942
+ case "Spacebar":
943
+ case "ArrowDown":
944
+ e.preventDefault();
945
+ if (!open) openMenu();
946
+ else moveActive(1);
947
+ break;
948
+ case "ArrowUp":
949
+ e.preventDefault();
950
+ if (!open) openMenu();
951
+ else moveActive(-1);
952
+ break;
953
+ case "Escape":
954
+ if (open) {
955
+ e.preventDefault();
956
+ closeMenu();
957
+ }
958
+ break;
959
+ }
960
+ };
961
+ const onMenuKeyDown = (e) => {
962
+ switch (e.key) {
963
+ case "ArrowDown":
964
+ e.preventDefault();
965
+ moveActive(1);
966
+ break;
967
+ case "ArrowUp":
968
+ e.preventDefault();
969
+ moveActive(-1);
970
+ break;
971
+ case "Home":
972
+ e.preventDefault();
973
+ setActiveIndex(filtered.length ? 0 : -1);
974
+ scrollActiveIntoView(0);
975
+ break;
976
+ case "End":
977
+ e.preventDefault();
978
+ setActiveIndex(filtered.length - 1);
979
+ scrollActiveIntoView(filtered.length - 1);
980
+ break;
981
+ case "Enter":
982
+ e.preventDefault();
983
+ if (activeIndex >= 0) {
984
+ const opt = filtered[activeIndex];
985
+ if (opt) commit(opt.value);
986
+ }
987
+ break;
988
+ case "Escape":
989
+ e.preventDefault();
990
+ closeMenu();
991
+ break;
992
+ case "Tab":
993
+ closeMenu();
994
+ break;
995
+ }
996
+ };
997
+ const moveActive = (delta) => {
998
+ if (!filtered.length) return;
999
+ const max = filtered.length - 1;
1000
+ const next = activeIndex < 0 ? 0 : Math.min(max, Math.max(0, activeIndex + delta));
1001
+ setActiveIndex(next);
1002
+ scrollActiveIntoView(next);
1003
+ };
1004
+ const scrollActiveIntoView = (index) => {
1005
+ const menu = menuRef.current;
1006
+ if (!menu) return;
1007
+ const items = menu.querySelectorAll("[data-option]");
1008
+ if (index >= 0 && index < items.length) {
1009
+ items[index]?.scrollIntoView({ block: "nearest" });
1010
+ }
1011
+ };
1012
+ const containerBg = disabled ? "bg-grey-100 cursor-not-allowed" : "bg-white";
1013
+ const containerBorder = validationError ? "border-red-300 bg-red-50" : "border-grey-100 bg-white";
1014
+ return /* @__PURE__ */ jsxs12("div", { className: `flex flex-col gap-2 relative ${className}`, children: [
1015
+ label ? /* @__PURE__ */ jsxs12("p", { className: "mb-0 text-body-2xs font-normal text-heading-text", children: [
1016
+ label,
1017
+ required && /* @__PURE__ */ jsx22("span", { className: "text-orange-required", children: " *" })
1018
+ ] }) : null,
1019
+ /* @__PURE__ */ jsxs12(
1020
+ "div",
1021
+ {
1022
+ ref: triggerRef,
1023
+ className: `border-c rounded-md flex items-center justify-between h-12 cursor-pointer px-3 py-2 ${containerBg} ${containerBorder}`,
1024
+ role: "combobox",
1025
+ "aria-haspopup": "listbox",
1026
+ "aria-expanded": open,
1027
+ "aria-controls": open ? "select-menu" : void 0,
1028
+ "aria-disabled": disabled || void 0,
1029
+ "aria-activedescendant": open && activeIndex >= 0 ? `option-${activeIndex}` : void 0,
1030
+ tabIndex: 0,
1031
+ onClick: toggleMenu,
1032
+ onKeyDown: onTriggerKeyDown,
1033
+ children: [
1034
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1035
+ prefix,
1036
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1037
+ selected && itemImageType === "country" && selected.countryCode && /* @__PURE__ */ jsx22(
1038
+ BaseImage,
1039
+ {
1040
+ src: `https://flagcdn.com/w40/${selected.countryCode.toLowerCase()}.png`,
1041
+ alt: selected.countryCode,
1042
+ width: 28,
1043
+ customClass: "rounded-lg"
1044
+ }
1045
+ ),
1046
+ /* @__PURE__ */ jsx22(
1047
+ "p",
1048
+ {
1049
+ className: `text-body-2xs font-normal mb-0 ${selected?.label ? "text-sub-copy" : "text-grey-500"}`,
1050
+ children: displayText
1051
+ }
1052
+ )
1053
+ ] })
1054
+ ] }),
1055
+ loading ? (
1056
+ // Loader (replace with your own IconLoader if you have one)
1057
+ /* @__PURE__ */ jsx22("span", { className: "inline-block h-4 w-4 border-2 border-current border-t-transparent rounded-full animate-spin" })
1058
+ ) : open ? /* @__PURE__ */ jsx22(IconChevronUp, { color: "#8FAECA" }) : /* @__PURE__ */ jsx22(IconChevronDown, { color: "#8FAECA" })
1059
+ ]
1060
+ }
1061
+ ),
1062
+ open && /* @__PURE__ */ jsxs12(
1063
+ "div",
1064
+ {
1065
+ ref: menuRef,
1066
+ id: "select-menu",
1067
+ className: "border-c bg-white rounded-md border-grey-border text-body-xs font-normal text-input-grey w-full mt-2 max-h-22rem overflow-y-auto",
1068
+ role: "listbox",
1069
+ "aria-label": label || "Options",
1070
+ style: { position: "absolute", top: "100%", zIndex: 10 },
1071
+ onKeyDown: onMenuKeyDown,
1072
+ children: [
1073
+ hasSearch && /* @__PURE__ */ jsx22("div", { className: "px-4 pt-2 pb-1", children: /* @__PURE__ */ jsx22(
1074
+ "input",
1075
+ {
1076
+ ref: searchRef,
1077
+ type: "text",
1078
+ onChange: onSearchInput,
1079
+ placeholder: `Search ${label || "options"}`,
1080
+ className: "bg-transparent outline-none border-b pb-2 w-full focus:outline-none focus:ring-0 text-body-2xs text-light-copy font-normal"
1081
+ }
1082
+ ) }),
1083
+ filtered.map((opt, i) => {
1084
+ const selectedOpt = selected?.value === opt.value;
1085
+ return /* @__PURE__ */ jsxs12(
1086
+ "div",
1087
+ {
1088
+ onClick: () => commit(opt.value),
1089
+ id: `option-${i}`,
1090
+ "data-option": true,
1091
+ role: "option",
1092
+ "aria-selected": selectedOpt,
1093
+ className: `px-4 py-3 first:pt-0 hover:bg-gray-100 flex items-center gap-2 cursor-pointer ${i === activeIndex ? "bg-gray-100" : ""}`,
1094
+ children: [
1095
+ itemImageType === "country" && opt.countryCode && /* @__PURE__ */ jsx22(
1096
+ BaseImage,
1097
+ {
1098
+ src: `https://flagcdn.com/w40/${opt.countryCode.toLowerCase()}.png`,
1099
+ alt: opt.countryCode,
1100
+ width: 28,
1101
+ customClass: "rounded-lg"
1102
+ }
1103
+ ),
1104
+ /* @__PURE__ */ jsx22("p", { className: "mb-0 text-body-2xs font-medium", children: opt.label })
1105
+ ]
1106
+ },
1107
+ opt.value
1108
+ );
1109
+ })
1110
+ ]
1111
+ }
1112
+ ),
1113
+ hint && /* @__PURE__ */ jsx22(BaseHint, { hint }),
1114
+ validationError && /* @__PURE__ */ jsx22(BaseInputError, { errorMessage: validationError })
1115
+ ] });
1116
+ };
1117
+
1118
+ // src/components/base/currency-amount.tsx
1119
+ import { jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
1120
+ var BaseCurrencyAmount = ({
1121
+ currency,
1122
+ amount,
1123
+ textClass = "",
1124
+ iconColorClass = "",
1125
+ iconWidth = 16,
1126
+ iconHeight = 16
1127
+ }) => {
1128
+ const cur = currency?.toUpperCase();
1129
+ if (cur !== "USDT" && cur !== "USDC") {
1130
+ return /* @__PURE__ */ jsx23("p", { className: textClass, children: formatAmount(amount, cur) });
1131
+ }
1132
+ return /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1", children: [
1133
+ cur === "USDT" && /* @__PURE__ */ jsx23(
1134
+ IconUsdt,
1135
+ {
1136
+ width: iconWidth,
1137
+ height: iconHeight,
1138
+ color: iconColorClass
1139
+ }
1140
+ ),
1141
+ cur === "USDC" && /* @__PURE__ */ jsx23(
1142
+ IconUsdc,
1143
+ {
1144
+ width: iconWidth,
1145
+ height: iconHeight,
1146
+ color: iconColorClass
1147
+ }
1148
+ ),
1149
+ /* @__PURE__ */ jsx23("p", { className: textClass, children: formatAmount(amount) })
1150
+ ] });
1151
+ };
1152
+
1153
+ // src/buzapay-checkout/checkout-iframe.tsx
1154
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef, useState as useState2 } from "react";
1155
+ import { jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
1156
+ function BzpCheckoutIframe({
1157
+ style = {
1158
+ width: "100%",
1159
+ height: "100vh",
1160
+ border: "0",
1161
+ borderRadius: "6px",
1162
+ overflow: "hidden"
1163
+ },
1164
+ url,
1165
+ secretKey,
1166
+ environment = "sandbox",
1167
+ paymentObject = {
1168
+ amount: 0,
1169
+ currency: "",
1170
+ email: "",
1171
+ phoneNumber: "",
1172
+ narration: "",
1173
+ redirectUrl: ""
1174
+ }
1175
+ }) {
1176
+ const containerRef = useRef(null);
1177
+ const iframeRef = useRef(null);
1178
+ const [message, setMessage] = useState2("");
1179
+ const [launchUrl, setLaunchUrl] = useState2("");
1180
+ const [loading, setLoading] = useState2(false);
1181
+ const launchIframe = useCallback2(
1182
+ (url2) => {
1183
+ if (iframeRef.current && iframeRef.current.parentNode) {
1184
+ iframeRef.current.parentNode.removeChild(iframeRef.current);
1185
+ }
1186
+ const iframe = document.createElement("iframe");
1187
+ iframe.src = url2;
1188
+ if (style.width) iframe.style.width = style.width;
1189
+ if (style.height) iframe.style.height = style.height;
1190
+ if (style.border) iframe.style.border = style.border;
1191
+ if (style.borderRadius) iframe.style.borderRadius = style.borderRadius;
1192
+ if (style.overflow) iframe.style.overflow = style.overflow;
1193
+ containerRef.current?.appendChild(iframe);
1194
+ iframeRef.current = iframe;
1195
+ },
1196
+ [style]
1197
+ );
1198
+ const generatePaymentLinkHandler = async () => {
1199
+ if (url) {
1200
+ launchIframe(url);
1201
+ return;
1202
+ }
1203
+ if (!secretKey) {
1204
+ return setMessage("Secret key is required.");
1205
+ }
1206
+ if (!checkObjectTruthy(paymentObject)) {
1207
+ return setMessage("Secret key is required.");
1208
+ }
1209
+ setLoading(true);
1210
+ const response = await createPaymentLink(
1211
+ paymentObject,
1212
+ environment,
1213
+ secretKey
1214
+ );
1215
+ if (response?.isSuccessful) {
1216
+ setLaunchUrl(response.launchUrl ?? "");
1217
+ setMessage("Payment link created successfully");
1218
+ if (response.launchUrl) {
1219
+ setLoading(false);
1220
+ launchIframe(response.launchUrl);
1221
+ }
1222
+ } else {
1223
+ setLoading(false);
1224
+ setMessage("Failed to create payment link");
1225
+ }
1226
+ };
1227
+ useEffect2(() => {
1228
+ if (!containerRef.current) return;
1229
+ generatePaymentLinkHandler();
1230
+ }, []);
1231
+ return /* @__PURE__ */ jsxs14("div", { className: "relative", style, children: [
1232
+ /* @__PURE__ */ jsx24("div", { ref: containerRef, className: "w-full h-full" }),
1233
+ loading && /* @__PURE__ */ jsx24("div", { className: "absolute inset-0 grid place-items-center bg-white/60", children: /* @__PURE__ */ jsx24(IconLoader, {}) })
1234
+ ] });
1235
+ }
1236
+
1237
+ // src/buzapay-checkout/checkout-button.tsx
1238
+ import { jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
1239
+ function BzpCheckoutButton({
1240
+ secretKey,
1241
+ environment = "sandbox",
1242
+ paymentObject = {
1243
+ amount: 0,
1244
+ currency: "",
1245
+ email: "",
1246
+ phoneNumber: "",
1247
+ narration: "",
1248
+ redirectUrl: ""
1249
+ },
1250
+ mode = "redirect"
1251
+ }) {
1252
+ const [message, setMessage] = useState3("");
1253
+ const [launchUrl, setLaunchUrl] = useState3("");
1254
+ const [loading, setLoading] = useState3(false);
1255
+ const generatePaymentLinkHandler = async () => {
1256
+ if (!secretKey) {
1257
+ setMessage("Secret key is required.");
1258
+ return;
1259
+ }
1260
+ if (!checkObjectTruthy(paymentObject)) {
1261
+ setMessage("Kindly ensure you are passing all the required data.");
1262
+ return;
1263
+ }
1264
+ setLoading(true);
1265
+ setMessage("");
1266
+ try {
1267
+ const response = await createPaymentLink(
1268
+ paymentObject,
1269
+ environment,
1270
+ secretKey
1271
+ );
1272
+ if (response?.isSuccessful && response.launchUrl) {
1273
+ setLaunchUrl(response.launchUrl);
1274
+ setMessage("Payment link created successfully");
1275
+ if (mode === "redirect") {
1276
+ window.open(response.launchUrl, "_blank", "noopener,noreferrer");
1277
+ }
1278
+ } else {
1279
+ setMessage("Failed to create payment link");
1280
+ }
1281
+ } catch (e) {
1282
+ setMessage(e?.message || "Failed to create payment link");
1283
+ } finally {
1284
+ setLoading(false);
1285
+ }
1286
+ };
1287
+ return launchUrl && mode === "iframe" ? /* @__PURE__ */ jsx25(
1288
+ BzpCheckoutIframe,
1289
+ {
1290
+ url: launchUrl,
1291
+ secretKey,
1292
+ environment
1293
+ }
1294
+ ) : /* @__PURE__ */ jsxs15("div", { children: [
1295
+ /* @__PURE__ */ jsx25(
1296
+ BaseButton,
1297
+ {
1298
+ label: "Pay",
1299
+ type: "primary",
1300
+ customClass: "w-full",
1301
+ loading,
1302
+ onClick: generatePaymentLinkHandler
1303
+ }
1304
+ ),
1305
+ /* @__PURE__ */ jsx25(BaseInputError, { errorMessage: message })
1306
+ ] });
1307
+ }
1308
+
1309
+ // src/buzapay-checkout/checkout-card.tsx
1310
+ import { useEffect as useEffect4, useState as useState7 } from "react";
1311
+
1312
+ // src/components/pay-by-card.tsx
1313
+ import { useState as useState4 } from "react";
1314
+
1315
+ // src/components/base/input.tsx
1316
+ import React4 from "react";
1317
+ import { Fragment as Fragment2, jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
1318
+ var BaseInput = ({
1319
+ label = "",
1320
+ type = "text",
1321
+ placeholder,
1322
+ validationError = "",
1323
+ hint = "",
1324
+ rules = [],
1325
+ isAmountInput = false,
1326
+ required = false,
1327
+ disabled = false,
1328
+ loading = false,
1329
+ showCopyIcon = false,
1330
+ value,
1331
+ defaultValue,
1332
+ onChange,
1333
+ onBlur,
1334
+ prefix,
1335
+ suffix,
1336
+ className = ""
1337
+ }) => {
1338
+ const isControlled = value !== void 0;
1339
+ const [rawValue, setRawValue] = React4.useState(
1340
+ defaultValue ?? value ?? ""
1341
+ );
1342
+ const [localHint, setLocalHint] = React4.useState("");
1343
+ const [localError, setLocalError] = React4.useState("");
1344
+ React4.useEffect(() => {
1345
+ if (isControlled) setRawValue(value ?? "");
1346
+ }, [isControlled, value]);
1347
+ const formattedValue = isAmountInput ? formatAmount(rawValue.replace(/,/g, "")) : rawValue;
1348
+ const handleChange = (e) => {
1349
+ const incoming = e.target.value.replace(/,/g, "");
1350
+ if (!isControlled) setRawValue(incoming);
1351
+ onChange?.(incoming);
1352
+ setTimeout(() => {
1353
+ const el = e.target;
1354
+ el.selectionStart = el.selectionEnd = el.value.length;
1355
+ });
1356
+ };
1357
+ const handleBlur = () => {
1358
+ onBlur?.(rawValue);
1359
+ };
1360
+ const handleKeyDown = (e) => {
1361
+ if (rules.includes("numeric")) restrictToNumericKeys(e);
1362
+ };
1363
+ const containerBg = disabled ? "bg-grey-50 cursor-not-allowed" : "bg-white";
1364
+ const containerBorder = validationError || localError ? "border-red-300 bg-red-50" : "border-grey-100";
1365
+ const copyToClipboard = (text) => {
1366
+ return navigator.clipboard.writeText(text);
1367
+ };
1368
+ const copyHandler = () => {
1369
+ copyToClipboard(rawValue).then(() => {
1370
+ setLocalHint("Text copied to clipboard");
1371
+ }).catch((err) => {
1372
+ setLocalError("Failed to copy text to clipboard");
1373
+ });
1374
+ };
1375
+ return /* @__PURE__ */ jsxs16("div", { className: `flex flex-col gap-2 ${className}`, children: [
1376
+ label ? /* @__PURE__ */ jsxs16("p", { className: "mb-0 text-body-2xs font-normal text-heading-text", children: [
1377
+ label,
1378
+ required && /* @__PURE__ */ jsx26("span", { className: "text-orange-required", children: " *" })
1379
+ ] }) : null,
1380
+ /* @__PURE__ */ jsxs16(
1381
+ "div",
1382
+ {
1383
+ className: `border-c px-3 py-2 flex items-center justify-between rounded-md h-12 ${containerBg} ${containerBorder}`,
1384
+ children: [
1385
+ prefix,
1386
+ /* @__PURE__ */ jsx26(
1387
+ "input",
1388
+ {
1389
+ type,
1390
+ value: formattedValue,
1391
+ onChange: handleChange,
1392
+ onBlur: handleBlur,
1393
+ onKeyDown: handleKeyDown,
1394
+ disabled,
1395
+ placeholder: placeholder ?? (label ? `Enter ${label.toLowerCase()}` : void 0),
1396
+ inputMode: isAmountInput ? "decimal" : void 0,
1397
+ className: "search-input bg-transparent outline-none border-none focus:outline-none focus:ring-0 text-body-2xs text-light-copy font-normal w-full"
1398
+ }
1399
+ ),
1400
+ !loading ? /* @__PURE__ */ jsxs16(Fragment2, { children: [
1401
+ suffix,
1402
+ showCopyIcon && rawValue && rawValue.trim() !== "" && /* @__PURE__ */ jsx26(
1403
+ BaseImage,
1404
+ {
1405
+ src: "assets/images/copyIcon.svg",
1406
+ alt: "copy",
1407
+ width: 16,
1408
+ height: 16,
1409
+ customClass: "cursor-pointer hover:opacity-70 transition-opacity",
1410
+ onClick: copyHandler
1411
+ }
1412
+ )
1413
+ ] }) : (
1414
+ // Simple loader placeholder; swap for your icon component if desired
1415
+ /* @__PURE__ */ jsx26("div", { className: "animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full" })
1416
+ )
1417
+ ]
1418
+ }
1419
+ ),
1420
+ (hint || localHint) && /* @__PURE__ */ jsx26("p", { className: "text-body-3xs text-light-copy", children: localHint || hint }),
1421
+ (validationError || localError) && /* @__PURE__ */ jsx26("p", { className: "text-body-3xs text-red-500", children: localError || validationError })
1422
+ ] });
1423
+ };
1424
+
1425
+ // src/components/pay-by-card.tsx
1426
+ import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
1427
+ function PayByCard({}) {
1428
+ const [formIndex, setFormIndex] = useState4(0);
1429
+ return /* @__PURE__ */ jsxs17("div", { className: "flex flex-col gap-6", children: [
1430
+ formIndex === 0 && /* @__PURE__ */ jsxs17("div", { className: "grid grid-cols-2 gap-6 overflow-y-auto", children: [
1431
+ /* @__PURE__ */ jsx27(BaseInput, { label: "First Name", required: true }),
1432
+ /* @__PURE__ */ jsx27(BaseInput, { label: "Last Name", required: true }),
1433
+ /* @__PURE__ */ jsx27(BaseInput, { label: "Email", required: true }),
1434
+ /* @__PURE__ */ jsx27(BaseInput, { label: "Phone Number", required: true }),
1435
+ /* @__PURE__ */ jsx27(
1436
+ BaseSelect,
1437
+ {
1438
+ label: "Select Country",
1439
+ required: true,
1440
+ options: [
1441
+ { label: "United States", value: "US" },
1442
+ { label: "Canada", value: "CA" },
1443
+ { label: "United Kingdom", value: "UK" }
1444
+ ]
1445
+ }
1446
+ ),
1447
+ /* @__PURE__ */ jsx27(
1448
+ BaseSelect,
1449
+ {
1450
+ label: "Select State",
1451
+ required: true,
1452
+ options: [
1453
+ { label: "California", value: "CA" },
1454
+ { label: "Texas", value: "TX" },
1455
+ { label: "New York", value: "NY" }
1456
+ ]
1457
+ }
1458
+ ),
1459
+ /* @__PURE__ */ jsx27(BaseInput, { label: "City", required: true }),
1460
+ /* @__PURE__ */ jsx27(BaseInput, { label: "Postal Code", required: true }),
1461
+ /* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(BaseInput, { label: "Street Address", required: true }) })
1462
+ ] }),
1463
+ formIndex === 1 && /* @__PURE__ */ jsxs17(
1464
+ "div",
1465
+ {
1466
+ className: "grid grid-cols-2 gap-6 overflow-y-auto",
1467
+ style: { maxHeight: "320px" },
1468
+ children: [
1469
+ /* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(BaseInput, { label: "Card Name", required: true }) }),
1470
+ /* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(BaseInput, { label: "Card Number", required: true }) }),
1471
+ /* @__PURE__ */ jsx27(BaseInput, { label: "Expiry Date", required: true }),
1472
+ /* @__PURE__ */ jsx27(BaseInput, { label: "CVV", required: true })
1473
+ ]
1474
+ }
1475
+ ),
1476
+ /* @__PURE__ */ jsx27(
1477
+ BaseButton,
1478
+ {
1479
+ label: formIndex === 0 ? "Proceed" : "Pay",
1480
+ type: "primary",
1481
+ customClass: "w-full",
1482
+ onClick: formIndex === 0 ? () => setFormIndex(1) : void 0
1483
+ }
1484
+ )
1485
+ ] });
1486
+ }
1487
+
1488
+ // src/components/pay-by-transfer.tsx
1489
+ import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState5 } from "react";
1490
+ import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
1491
+ var PayByTransfer = ({
1492
+ amountDisplay = "NGN 200,500.00",
1493
+ bankName = "Teerus MFB",
1494
+ accountNumber = "0001928940",
1495
+ initialSeconds = 30 * 60,
1496
+ onConfirmPaid,
1497
+ onCancel
1498
+ }) => {
1499
+ const [remaining, setRemaining] = useState5(initialSeconds);
1500
+ const intervalRef = useRef2(null);
1501
+ const countDownTime = useMemo2(() => {
1502
+ const clamped = Math.max(0, remaining);
1503
+ const m = Math.floor(clamped / 60);
1504
+ const s = clamped % 60;
1505
+ return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
1506
+ }, [remaining]);
1507
+ useEffect3(() => {
1508
+ intervalRef.current = window.setInterval(() => {
1509
+ setRemaining((prev) => prev - 1);
1510
+ }, 1e3);
1511
+ return () => {
1512
+ if (intervalRef.current) {
1513
+ clearInterval(intervalRef.current);
1514
+ intervalRef.current = null;
1515
+ }
1516
+ };
1517
+ }, []);
1518
+ useEffect3(() => {
1519
+ if (remaining < 0 && intervalRef.current) {
1520
+ clearInterval(intervalRef.current);
1521
+ intervalRef.current = null;
1522
+ }
1523
+ }, [remaining]);
1524
+ return /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-10", children: [
1525
+ /* @__PURE__ */ jsxs18("p", { className: "text-sub-copy text-sm font-semibold text-center", children: [
1526
+ "Amount to Pay ",
1527
+ amountDisplay
1528
+ ] }),
1529
+ /* @__PURE__ */ jsxs18("div", { className: "bg-[#EFF7FF] p-4 rounded-lg flex flex-col gap-6", children: [
1530
+ /* @__PURE__ */ jsx28(BaseLabelInfo, { label: "Bank Name", value: bankName, type: "horizontal" }),
1531
+ /* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between", children: [
1532
+ /* @__PURE__ */ jsx28(
1533
+ BaseLabelInfo,
1534
+ {
1535
+ label: "Account Number",
1536
+ value: accountNumber,
1537
+ type: "horizontal"
1538
+ }
1539
+ ),
1540
+ /* @__PURE__ */ jsx28(BaseCopy, { color: "#9DBFDE", copyText: accountNumber })
1541
+ ] }),
1542
+ /* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between", children: [
1543
+ /* @__PURE__ */ jsx28(
1544
+ BaseLabelInfo,
1545
+ {
1546
+ label: "Amount",
1547
+ value: amountDisplay,
1548
+ type: "horizontal"
1549
+ }
1550
+ ),
1551
+ /* @__PURE__ */ jsx28(BaseCopy, { color: "#9DBFDE", copyText: amountDisplay })
1552
+ ] })
1553
+ ] }),
1554
+ /* @__PURE__ */ jsxs18("p", { className: "w-2/3 mx-auto text-center text-body-2xs font-medium text-sub-copy", children: [
1555
+ "This account is for this transaction only and expires in",
1556
+ " ",
1557
+ /* @__PURE__ */ jsx28("span", { className: "text-orange-500", children: remaining >= 0 ? countDownTime : "00:00" })
1558
+ ] }),
1559
+ /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-4", children: [
1560
+ /* @__PURE__ */ jsx28(
1561
+ BaseButton,
1562
+ {
1563
+ label: "I have paid the money",
1564
+ type: "primary",
1565
+ customClass: "w-full",
1566
+ onClick: onConfirmPaid
1567
+ }
1568
+ ),
1569
+ /* @__PURE__ */ jsx28(
1570
+ "button",
1571
+ {
1572
+ type: "button",
1573
+ onClick: onCancel,
1574
+ className: "text-heading-text text-body-2xs font-medium text-center py-2 cursor-pointer",
1575
+ children: "Cancel Payment"
1576
+ }
1577
+ )
1578
+ ] })
1579
+ ] });
1580
+ };
1581
+
1582
+ // src/components/pay-by-stable-coin.tsx
1583
+ import { useState as useState6 } from "react";
1584
+ import { Fragment as Fragment3, jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
1585
+ var PayByStableCoin = ({ onProceedToPay }) => {
1586
+ const [formIndex, setFormIndex] = useState6(0);
1587
+ const payHandler = () => {
1588
+ setFormIndex(1);
1589
+ onProceedToPay?.();
1590
+ };
1591
+ return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-6", children: [
1592
+ formIndex === 0 && /* @__PURE__ */ jsxs19(Fragment3, { children: [
1593
+ /* @__PURE__ */ jsxs19("div", { className: "grid grid-cols-1 gap-6", children: [
1594
+ /* @__PURE__ */ jsx29(
1595
+ BaseSelect,
1596
+ {
1597
+ label: "Select Crypto",
1598
+ required: true,
1599
+ options: [
1600
+ { label: "USDT", value: "USDT" },
1601
+ { label: "USDC", value: "USDC" },
1602
+ { label: "BUSD", value: "BUSD" }
1603
+ ]
1604
+ }
1605
+ ),
1606
+ /* @__PURE__ */ jsx29(
1607
+ BaseSelect,
1608
+ {
1609
+ label: "Select Network",
1610
+ required: true,
1611
+ options: [
1612
+ { label: "Ethereum", value: "ETH" },
1613
+ { label: "Binance Smart Chain", value: "BSC" },
1614
+ { label: "Polygon", value: "MATIC" }
1615
+ ]
1616
+ }
1617
+ )
1618
+ ] }),
1619
+ /* @__PURE__ */ jsx29(
1620
+ BaseButton,
1621
+ {
1622
+ label: "Pay",
1623
+ type: "primary",
1624
+ customClass: "w-full",
1625
+ onClick: payHandler
1626
+ }
1627
+ )
1628
+ ] }),
1629
+ formIndex === 1 && /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-6", children: [
1630
+ /* @__PURE__ */ jsxs19("div", { className: "mx-auto", children: [
1631
+ /* @__PURE__ */ jsx29(
1632
+ BaseImage,
1633
+ {
1634
+ src: "../../../assets/images/stable-coin-qr-code.png",
1635
+ alt: "QR Code",
1636
+ width: 122,
1637
+ height: 122,
1638
+ customClass: "mb-1"
1639
+ }
1640
+ ),
1641
+ /* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-4xs text-light-copy font-normal text-center", children: "USDC" })
1642
+ ] }),
1643
+ /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-6 border-c border-grey-100 p-4 rounded-2xl bg-light-white-50", children: [
1644
+ /* @__PURE__ */ jsxs19("div", { className: "border-b border-grey-border pb-4 flex flex-col gap-2", children: [
1645
+ /* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-3xs text-light-copy font-normal", children: "Network" }),
1646
+ /* @__PURE__ */ jsxs19("div", { className: "flex justify-between", children: [
1647
+ /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-1", children: [
1648
+ /* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-2xs font-medium text-sub-copy", children: "BNB Smart Chain (BEP20)" }),
1649
+ /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
1650
+ /* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-3xs text-light-copy font-normal", children: "*Est. arrival = 3 mins" }),
1651
+ /* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-3xs text-light-copy font-normal", children: "|" }),
1652
+ /* @__PURE__ */ jsx29(
1653
+ BaseCurrencyAmount,
1654
+ {
1655
+ currency: "USDC",
1656
+ amount: 10,
1657
+ textClass: "mb-0 text-body-3xs text-light-copy font-normal",
1658
+ iconColorClass: "#557591",
1659
+ iconWidth: 12,
1660
+ iconHeight: 12
1661
+ }
1662
+ )
1663
+ ] })
1664
+ ] }),
1665
+ /* @__PURE__ */ jsx29(IconArrowSwap, {})
1666
+ ] })
1667
+ ] }),
1668
+ /* @__PURE__ */ jsxs19("div", { className: "pb-4 flex flex-col gap-2", children: [
1669
+ /* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-3xs text-light-copy font-normal", children: "Deposit Address >" }),
1670
+ /* @__PURE__ */ jsxs19("div", { className: "flex justify-between", children: [
1671
+ /* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-2xs font-medium text-sub-copy w-2/3 break-words", children: "0j8938ysheeee8333c162883a4d4f5g6t111nhk8uey37777yt6" }),
1672
+ /* @__PURE__ */ jsx29(BaseCopy, { copyText: "0j8938ysheeee8333c162883a4d4f5g6t111nhk8uey37777yt6" })
1673
+ ] })
1674
+ ] })
1675
+ ] }),
1676
+ /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-2", children: [
1677
+ /* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between border-b border-grey-border py-3", children: [
1678
+ /* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-2xs font-medium text-primary-black", children: "Network fee" }),
1679
+ /* @__PURE__ */ jsx29(
1680
+ BaseCurrencyAmount,
1681
+ {
1682
+ currency: "USDC",
1683
+ amount: 12,
1684
+ textClass: "mb-0 text-body-2xs font-extrabold text-primary-black",
1685
+ iconColorClass: "#231F20"
1686
+ }
1687
+ )
1688
+ ] }),
1689
+ /* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between py-4", children: [
1690
+ /* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-lg font-semibold text-primary-black", children: "Pay" }),
1691
+ /* @__PURE__ */ jsx29(
1692
+ BaseCurrencyAmount,
1693
+ {
1694
+ currency: "USDC",
1695
+ amount: 15,
1696
+ textClass: "mb-0 text-body-lg font-extrabold text-primary-black",
1697
+ iconColorClass: "#231F20",
1698
+ iconWidth: 20,
1699
+ iconHeight: 20
1700
+ }
1701
+ )
1702
+ ] })
1703
+ ] }),
1704
+ /* @__PURE__ */ jsx29("div", { className: "flex flex-col gap-6", children: /* @__PURE__ */ jsx29(
1705
+ BaseButton,
1706
+ {
1707
+ label: "Confirm Payment",
1708
+ type: "primary",
1709
+ customClass: "w-full"
1710
+ }
1711
+ ) })
1712
+ ] })
1713
+ ] });
1714
+ };
1715
+
1716
+ // src/buzapay-checkout/checkout-card.tsx
1717
+ import { jsx as jsx30, jsxs as jsxs20 } from "react/jsx-runtime";
1718
+ function BzpCheckoutCard({
1719
+ options,
1720
+ environment = "sandbox",
1721
+ paymentObject = {
1722
+ amount: 0,
1723
+ currency: "",
1724
+ email: "",
1725
+ phoneNumber: "",
1726
+ narration: "",
1727
+ redirectUrl: ""
1728
+ }
1729
+ }) {
1730
+ const [checkoutState, setCheckoutState] = useState7("PAYMENT");
1731
+ const paymentTypeOptions = [
1732
+ { label: "Card", value: "CARD" },
1733
+ { label: "Bank Transfer", value: "BANK_TRANSFER" },
1734
+ { label: "Stable Coin", value: "STABLE_COIN" }
1735
+ ];
1736
+ const [filteredPaymentTypeOptions, setFilteredPaymentTypeOptions] = useState7([]);
1737
+ const [paymentType, setPaymentType] = useState7("");
1738
+ const paymentTypeHandler = (event) => {
1739
+ setPaymentType(event);
1740
+ };
1741
+ useEffect4(() => {
1742
+ let options2 = [];
1743
+ if (paymentObject.currency === "USD") {
1744
+ options2 = paymentTypeOptions.filter(
1745
+ (option) => option.value !== "BANK_TRANSFER"
1746
+ );
1747
+ } else {
1748
+ options2 = paymentTypeOptions.filter(
1749
+ (option) => option.value !== "STABLE_COIN"
1750
+ );
1751
+ }
1752
+ setFilteredPaymentTypeOptions(options2);
1753
+ }, [paymentObject.currency]);
1754
+ useEffect4(() => {
1755
+ if (filteredPaymentTypeOptions.length) {
1756
+ setPaymentType(filteredPaymentTypeOptions[0].value);
1757
+ }
1758
+ }, [filteredPaymentTypeOptions]);
1759
+ return /* @__PURE__ */ jsx30(BaseCard, { showBackButton: checkoutState === "STABLE_COIN_PAYMENT", children: /* @__PURE__ */ jsxs20("div", { className: "grid grid-cols-3", children: [
1760
+ checkoutState === "PAYMENT" && /* @__PURE__ */ jsxs20("div", { className: "bg-[#EFF7FF] px-6 py-8 flex flex-col gap-5 col-span-1 rounded-l-xl", children: [
1761
+ /* @__PURE__ */ jsx30("p", { className: "text-heading-text text-body-xs font-semibold", children: "Pay with" }),
1762
+ /* @__PURE__ */ jsx30(
1763
+ BaseRadioGroup,
1764
+ {
1765
+ options: paymentTypeOptions,
1766
+ selectedChange: (e) => paymentTypeHandler(e)
1767
+ }
1768
+ )
1769
+ ] }),
1770
+ /* @__PURE__ */ jsxs20("div", { className: "col-span-2", children: [
1771
+ (checkoutState === "PAYMENT" || checkoutState === "STABLE_COIN_PAYMENT") && /* @__PURE__ */ jsxs20("div", { children: [
1772
+ checkoutState === "PAYMENT" && /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between px-12 py-8", children: [
1773
+ options?.imageUrl ? /* @__PURE__ */ jsx30(
1774
+ BaseImage,
1775
+ {
1776
+ src: options?.imageUrl ?? "",
1777
+ alt: "Merchant Logo",
1778
+ width: 52,
1779
+ height: 52,
1780
+ customClass: "rounded-lg"
1781
+ }
1782
+ ) : /* @__PURE__ */ jsx30(
1783
+ "div",
1784
+ {
1785
+ className: "bg-heading-text rounded flex flex-col justify-center",
1786
+ style: { width: "52px", height: "52px" },
1787
+ children: /* @__PURE__ */ jsx30("p", { className: "text-white text-center text-body-2xs font-medium", children: "Logo" })
1788
+ }
1789
+ ),
1790
+ /* @__PURE__ */ jsxs20("div", { className: "flex flex-col gap-1", children: [
1791
+ /* @__PURE__ */ jsx30("p", { className: "text-body-2xs font-regular text-sub-copy text-right", children: "Raymahni Merchant LLC" }),
1792
+ /* @__PURE__ */ jsxs20("p", { className: "text-body-2xs font-regular text-sub-copy text-right", children: [
1793
+ "Pay:",
1794
+ " ",
1795
+ /* @__PURE__ */ jsxs20("span", { className: "text-orange-500 font-extrabold", children: [
1796
+ currencySign(paymentObject.currency),
1797
+ " 100,051.00"
1798
+ ] })
1799
+ ] })
1800
+ ] })
1801
+ ] }),
1802
+ /* @__PURE__ */ jsx30("div", { className: "overflow-y-scroll px-10 pb-10 pt-2", children: paymentType === "CARD" ? /* @__PURE__ */ jsx30(PayByCard, {}) : paymentType === "BANK_TRANSFER" ? /* @__PURE__ */ jsx30(PayByTransfer, {}) : /* @__PURE__ */ jsx30(
1803
+ PayByStableCoin,
1804
+ {
1805
+ onProceedToPay: () => setCheckoutState("STABLE_COIN_PAYMENT")
1806
+ }
1807
+ ) })
1808
+ ] }),
1809
+ checkoutState === "SUCCESS" && /* @__PURE__ */ jsx30(BaseSuccess, {})
1810
+ ] })
1811
+ ] }) });
1812
+ }
1813
+ export {
1814
+ BzpCheckoutButton,
1815
+ BzpCheckoutCard,
1816
+ BzpCheckoutIframe,
1817
+ MidenPGClient,
1818
+ MidenPGProvider,
1819
+ useMidenPGClient,
1820
+ usePaymentIntents
1821
+ };
1822
+ //# sourceMappingURL=index.js.map