@reevit/react 0.3.7 → 0.4.0

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.mjs CHANGED
@@ -506,6 +506,14 @@ function detectCountryFromCurrency(currency) {
506
506
  };
507
507
  return currencyToCountry[currency.toUpperCase()] || "GH";
508
508
  }
509
+ var pspNames = {
510
+ hubtel: "Hubtel",
511
+ paystack: "Paystack",
512
+ flutterwave: "Flutterwave",
513
+ monnify: "Monnify",
514
+ mpesa: "M-Pesa",
515
+ stripe: "Stripe"
516
+ };
509
517
  var methodConfig = {
510
518
  card: {
511
519
  label: "Card",
@@ -527,13 +535,30 @@ function PaymentMethodSelector({
527
535
  methods,
528
536
  selectedMethod,
529
537
  onSelect,
530
- disabled = false
538
+ disabled = false,
539
+ provider
531
540
  }) {
541
+ const getMethodLabel = (method, psp) => {
542
+ const config = methodConfig[method];
543
+ if (psp?.toLowerCase().includes("hubtel") && method === "mobile_money") {
544
+ return `Pay with ${pspNames[psp.toLowerCase()] || "Hubtel"}`;
545
+ }
546
+ return config.label;
547
+ };
548
+ const getMethodDescription = (method, psp) => {
549
+ const config = methodConfig[method];
550
+ if (psp?.toLowerCase().includes("hubtel")) {
551
+ return "Card, Mobile Money, and Bank Transfer";
552
+ }
553
+ return config.description;
554
+ };
532
555
  return /* @__PURE__ */ jsxs("div", { className: "reevit-method-selector", children: [
533
556
  /* @__PURE__ */ jsx("div", { className: "reevit-method-selector__label", children: "Select payment method" }),
534
557
  /* @__PURE__ */ jsx("div", { className: "reevit-method-selector__options", children: methods.map((method) => {
535
558
  const config = methodConfig[method];
536
559
  const isSelected = selectedMethod === method;
560
+ const methodLabel = getMethodLabel(method, provider);
561
+ const methodDescription = getMethodDescription(method, provider);
537
562
  return /* @__PURE__ */ jsxs(
538
563
  "button",
539
564
  {
@@ -549,8 +574,8 @@ function PaymentMethodSelector({
549
574
  children: [
550
575
  /* @__PURE__ */ jsx("span", { className: "reevit-method-option__icon", children: config.icon }),
551
576
  /* @__PURE__ */ jsxs("div", { className: "reevit-method-option__content", children: [
552
- /* @__PURE__ */ jsx("span", { className: "reevit-method-option__label", children: config.label }),
553
- /* @__PURE__ */ jsx("span", { className: "reevit-method-option__description", children: config.description })
577
+ /* @__PURE__ */ jsx("span", { className: "reevit-method-option__label", children: methodLabel }),
578
+ /* @__PURE__ */ jsx("span", { className: "reevit-method-option__description", children: methodDescription })
554
579
  ] }),
555
580
  isSelected && /* @__PURE__ */ jsx("span", { className: "reevit-method-option__check", children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx(
556
581
  "path",
@@ -1357,6 +1382,87 @@ function loadStripeScript() {
1357
1382
  });
1358
1383
  return stripeScriptPromise;
1359
1384
  }
1385
+ var getReevitStripeAppearance = () => {
1386
+ const isDarkMode = typeof window !== "undefined" && window.matchMedia?.("(prefers-color-scheme: dark)").matches;
1387
+ return {
1388
+ theme: isDarkMode ? "night" : "stripe",
1389
+ variables: {
1390
+ colorPrimary: isDarkMode ? "#fafafa" : "#171717",
1391
+ colorBackground: isDarkMode ? "#171717" : "#ffffff",
1392
+ colorText: isDarkMode ? "#fafafa" : "#171717",
1393
+ colorTextSecondary: isDarkMode ? "#a3a3a3" : "#737373",
1394
+ colorTextPlaceholder: isDarkMode ? "#737373" : "#a3a3a3",
1395
+ colorDanger: "#dc2626",
1396
+ fontFamily: '"Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
1397
+ fontSizeBase: "14px",
1398
+ fontSizeSm: "12px",
1399
+ fontSizeLg: "16px",
1400
+ fontWeightNormal: "400",
1401
+ fontWeightMedium: "500",
1402
+ fontWeightBold: "600",
1403
+ borderRadius: "10px",
1404
+ spacingUnit: "4px",
1405
+ spacingGridRow: "16px",
1406
+ spacingGridColumn: "16px"
1407
+ },
1408
+ rules: {
1409
+ ".Input": {
1410
+ border: isDarkMode ? "1px solid rgba(255, 255, 255, 0.1)" : "1px solid #e5e5e5",
1411
+ boxShadow: "none",
1412
+ padding: "12px 14px",
1413
+ fontSize: "14px",
1414
+ backgroundColor: isDarkMode ? "#262626" : "#ffffff"
1415
+ },
1416
+ ".Input:focus": {
1417
+ border: isDarkMode ? "1px solid #a3a3a3" : "1px solid #737373",
1418
+ boxShadow: "none",
1419
+ backgroundColor: isDarkMode ? "#262626" : "#fafafa"
1420
+ },
1421
+ ".Input--invalid": {
1422
+ border: "1px solid #dc2626",
1423
+ boxShadow: "none"
1424
+ },
1425
+ ".Label": {
1426
+ fontSize: "12px",
1427
+ fontWeight: "500",
1428
+ marginBottom: "6px",
1429
+ color: isDarkMode ? "#a3a3a3" : "#737373",
1430
+ textTransform: "none",
1431
+ letterSpacing: "0.02em"
1432
+ },
1433
+ ".Tab": {
1434
+ border: isDarkMode ? "1px solid rgba(255, 255, 255, 0.1)" : "1px solid #e5e5e5",
1435
+ backgroundColor: "transparent",
1436
+ borderRadius: "10px",
1437
+ padding: "12px 14px"
1438
+ },
1439
+ ".Tab:hover": {
1440
+ border: isDarkMode ? "1px solid #a3a3a3" : "1px solid #737373",
1441
+ backgroundColor: isDarkMode ? "#262626" : "#fafafa"
1442
+ },
1443
+ ".Tab--selected": {
1444
+ border: isDarkMode ? "1px solid #fafafa" : "1px solid #171717",
1445
+ backgroundColor: isDarkMode ? "#262626" : "#fafafa"
1446
+ },
1447
+ ".TabIcon": {
1448
+ marginRight: "8px"
1449
+ },
1450
+ ".Block": {
1451
+ border: isDarkMode ? "1px solid rgba(255, 255, 255, 0.1)" : "1px solid #e5e5e5",
1452
+ borderRadius: "10px",
1453
+ backgroundColor: isDarkMode ? "#262626" : "#ffffff",
1454
+ padding: "12px 14px"
1455
+ },
1456
+ ".CheckboxInput": {
1457
+ border: isDarkMode ? "1px solid rgba(255, 255, 255, 0.1)" : "1px solid #e5e5e5"
1458
+ },
1459
+ ".CheckboxInput--checked": {
1460
+ backgroundColor: isDarkMode ? "#fafafa" : "#171717",
1461
+ borderColor: isDarkMode ? "#fafafa" : "#171717"
1462
+ }
1463
+ }
1464
+ };
1465
+ };
1360
1466
  function StripeBridge({
1361
1467
  publishableKey,
1362
1468
  clientSecret,
@@ -1384,9 +1490,10 @@ function StripeBridge({
1384
1490
  throw new Error("Stripe not available");
1385
1491
  }
1386
1492
  stripeRef.current = window.Stripe(publishableKey);
1493
+ const stripeAppearance = appearance || getReevitStripeAppearance();
1387
1494
  elementsRef.current = stripeRef.current.elements({
1388
1495
  clientSecret,
1389
- appearance: appearance || { theme: "stripe" }
1496
+ appearance: stripeAppearance
1390
1497
  });
1391
1498
  paymentElementRef.current = elementsRef.current.create("payment");
1392
1499
  if (containerRef.current) {
@@ -1456,6 +1563,12 @@ function StripeBridge({
1456
1563
  setIsSubmitting(false);
1457
1564
  }
1458
1565
  }, [onSuccess, onError]);
1566
+ const formattedAmount = new Intl.NumberFormat("en-US", {
1567
+ style: "currency",
1568
+ currency: currency.toUpperCase(),
1569
+ minimumFractionDigits: 2,
1570
+ maximumFractionDigits: 2
1571
+ }).format(amount / 100);
1459
1572
  return /* @__PURE__ */ jsxs("div", { className: "reevit-stripe-bridge", children: [
1460
1573
  isLoading && /* @__PURE__ */ jsxs("div", { className: "reevit-stripe-loading", children: [
1461
1574
  /* @__PURE__ */ jsx("div", { className: "reevit-spinner" }),
@@ -1469,8 +1582,8 @@ function StripeBridge({
1469
1582
  style: { display: isLoading ? "none" : "block", minHeight: "200px" }
1470
1583
  }
1471
1584
  ),
1472
- error && /* @__PURE__ */ jsx("div", { className: "reevit-stripe-error", children: /* @__PURE__ */ jsx("p", { children: error }) }),
1473
- /* @__PURE__ */ jsxs("div", { className: "reevit-stripe-actions", children: [
1585
+ error && !isLoading && /* @__PURE__ */ jsx("div", { className: "reevit-stripe-error", children: /* @__PURE__ */ jsx("p", { children: error }) }),
1586
+ !isLoading && /* @__PURE__ */ jsxs("div", { className: "reevit-stripe-actions", children: [
1474
1587
  /* @__PURE__ */ jsx(
1475
1588
  "button",
1476
1589
  {
@@ -1478,11 +1591,12 @@ function StripeBridge({
1478
1591
  className: "reevit-submit-btn",
1479
1592
  onClick: handleSubmit,
1480
1593
  disabled: isLoading || isSubmitting,
1481
- children: isSubmitting ? /* @__PURE__ */ jsx("span", { className: "reevit-spinner" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1594
+ children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
1595
+ /* @__PURE__ */ jsx("span", { className: "reevit-spinner", style: { width: "16px", height: "16px" } }),
1596
+ /* @__PURE__ */ jsx("span", { children: "Processing..." })
1597
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1482
1598
  "Pay ",
1483
- currency,
1484
- " ",
1485
- (amount / 100).toFixed(2)
1599
+ formattedAmount
1486
1600
  ] })
1487
1601
  }
1488
1602
  ),
@@ -1681,9 +1795,9 @@ function ReevitCheckout({
1681
1795
  /* @__PURE__ */ jsx("button", { className: "reevit-btn reevit-btn--primary", onClick: handleBack, children: "Try Again" })
1682
1796
  ] });
1683
1797
  }
1798
+ const psp = paymentIntent?.recommendedPsp || "paystack";
1684
1799
  if (showPSPBridge) {
1685
1800
  const pspKey = paymentIntent?.pspPublicKey || publicKey;
1686
- const psp = paymentIntent?.recommendedPsp || "paystack";
1687
1801
  const bridgeMetadata = {
1688
1802
  ...metadata,
1689
1803
  // Override with correct payment intent ID for webhook routing
@@ -1860,7 +1974,8 @@ function ReevitCheckout({
1860
1974
  methods: paymentMethods,
1861
1975
  selectedMethod,
1862
1976
  onSelect: handleMethodSelect,
1863
- disabled: isLoading
1977
+ disabled: isLoading,
1978
+ provider: psp
1864
1979
  }
1865
1980
  ),
1866
1981
  selectedMethod && selectedMethod !== "mobile_money" && /* @__PURE__ */ jsx("div", { className: "reevit-method-step__actions", children: /* @__PURE__ */ jsx(