@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.d.mts CHANGED
@@ -163,8 +163,9 @@ interface PaymentMethodSelectorProps {
163
163
  selectedMethod: PaymentMethod | null;
164
164
  onSelect: (method: PaymentMethod) => void;
165
165
  disabled?: boolean;
166
+ provider?: string;
166
167
  }
167
- declare function PaymentMethodSelector({ methods, selectedMethod, onSelect, disabled, }: PaymentMethodSelectorProps): react_jsx_runtime.JSX.Element;
168
+ declare function PaymentMethodSelector({ methods, selectedMethod, onSelect, disabled, provider, }: PaymentMethodSelectorProps): react_jsx_runtime.JSX.Element;
168
169
 
169
170
  interface MobileMoneyFormProps {
170
171
  onSubmit: (data: MobileMoneyFormData) => void;
package/dist/index.d.ts CHANGED
@@ -163,8 +163,9 @@ interface PaymentMethodSelectorProps {
163
163
  selectedMethod: PaymentMethod | null;
164
164
  onSelect: (method: PaymentMethod) => void;
165
165
  disabled?: boolean;
166
+ provider?: string;
166
167
  }
167
- declare function PaymentMethodSelector({ methods, selectedMethod, onSelect, disabled, }: PaymentMethodSelectorProps): react_jsx_runtime.JSX.Element;
168
+ declare function PaymentMethodSelector({ methods, selectedMethod, onSelect, disabled, provider, }: PaymentMethodSelectorProps): react_jsx_runtime.JSX.Element;
168
169
 
169
170
  interface MobileMoneyFormProps {
170
171
  onSubmit: (data: MobileMoneyFormData) => void;
package/dist/index.js CHANGED
@@ -512,6 +512,14 @@ function detectCountryFromCurrency(currency) {
512
512
  };
513
513
  return currencyToCountry[currency.toUpperCase()] || "GH";
514
514
  }
515
+ var pspNames = {
516
+ hubtel: "Hubtel",
517
+ paystack: "Paystack",
518
+ flutterwave: "Flutterwave",
519
+ monnify: "Monnify",
520
+ mpesa: "M-Pesa",
521
+ stripe: "Stripe"
522
+ };
515
523
  var methodConfig = {
516
524
  card: {
517
525
  label: "Card",
@@ -533,13 +541,30 @@ function PaymentMethodSelector({
533
541
  methods,
534
542
  selectedMethod,
535
543
  onSelect,
536
- disabled = false
544
+ disabled = false,
545
+ provider
537
546
  }) {
547
+ const getMethodLabel = (method, psp) => {
548
+ const config = methodConfig[method];
549
+ if (psp?.toLowerCase().includes("hubtel") && method === "mobile_money") {
550
+ return `Pay with ${pspNames[psp.toLowerCase()] || "Hubtel"}`;
551
+ }
552
+ return config.label;
553
+ };
554
+ const getMethodDescription = (method, psp) => {
555
+ const config = methodConfig[method];
556
+ if (psp?.toLowerCase().includes("hubtel")) {
557
+ return "Card, Mobile Money, and Bank Transfer";
558
+ }
559
+ return config.description;
560
+ };
538
561
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "reevit-method-selector", children: [
539
562
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "reevit-method-selector__label", children: "Select payment method" }),
540
563
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "reevit-method-selector__options", children: methods.map((method) => {
541
564
  const config = methodConfig[method];
542
565
  const isSelected = selectedMethod === method;
566
+ const methodLabel = getMethodLabel(method, provider);
567
+ const methodDescription = getMethodDescription(method, provider);
543
568
  return /* @__PURE__ */ jsxRuntime.jsxs(
544
569
  "button",
545
570
  {
@@ -555,8 +580,8 @@ function PaymentMethodSelector({
555
580
  children: [
556
581
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "reevit-method-option__icon", children: config.icon }),
557
582
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "reevit-method-option__content", children: [
558
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "reevit-method-option__label", children: config.label }),
559
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "reevit-method-option__description", children: config.description })
583
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "reevit-method-option__label", children: methodLabel }),
584
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "reevit-method-option__description", children: methodDescription })
560
585
  ] }),
561
586
  isSelected && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "reevit-method-option__check", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
562
587
  "path",
@@ -1363,6 +1388,87 @@ function loadStripeScript() {
1363
1388
  });
1364
1389
  return stripeScriptPromise;
1365
1390
  }
1391
+ var getReevitStripeAppearance = () => {
1392
+ const isDarkMode = typeof window !== "undefined" && window.matchMedia?.("(prefers-color-scheme: dark)").matches;
1393
+ return {
1394
+ theme: isDarkMode ? "night" : "stripe",
1395
+ variables: {
1396
+ colorPrimary: isDarkMode ? "#fafafa" : "#171717",
1397
+ colorBackground: isDarkMode ? "#171717" : "#ffffff",
1398
+ colorText: isDarkMode ? "#fafafa" : "#171717",
1399
+ colorTextSecondary: isDarkMode ? "#a3a3a3" : "#737373",
1400
+ colorTextPlaceholder: isDarkMode ? "#737373" : "#a3a3a3",
1401
+ colorDanger: "#dc2626",
1402
+ fontFamily: '"Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
1403
+ fontSizeBase: "14px",
1404
+ fontSizeSm: "12px",
1405
+ fontSizeLg: "16px",
1406
+ fontWeightNormal: "400",
1407
+ fontWeightMedium: "500",
1408
+ fontWeightBold: "600",
1409
+ borderRadius: "10px",
1410
+ spacingUnit: "4px",
1411
+ spacingGridRow: "16px",
1412
+ spacingGridColumn: "16px"
1413
+ },
1414
+ rules: {
1415
+ ".Input": {
1416
+ border: isDarkMode ? "1px solid rgba(255, 255, 255, 0.1)" : "1px solid #e5e5e5",
1417
+ boxShadow: "none",
1418
+ padding: "12px 14px",
1419
+ fontSize: "14px",
1420
+ backgroundColor: isDarkMode ? "#262626" : "#ffffff"
1421
+ },
1422
+ ".Input:focus": {
1423
+ border: isDarkMode ? "1px solid #a3a3a3" : "1px solid #737373",
1424
+ boxShadow: "none",
1425
+ backgroundColor: isDarkMode ? "#262626" : "#fafafa"
1426
+ },
1427
+ ".Input--invalid": {
1428
+ border: "1px solid #dc2626",
1429
+ boxShadow: "none"
1430
+ },
1431
+ ".Label": {
1432
+ fontSize: "12px",
1433
+ fontWeight: "500",
1434
+ marginBottom: "6px",
1435
+ color: isDarkMode ? "#a3a3a3" : "#737373",
1436
+ textTransform: "none",
1437
+ letterSpacing: "0.02em"
1438
+ },
1439
+ ".Tab": {
1440
+ border: isDarkMode ? "1px solid rgba(255, 255, 255, 0.1)" : "1px solid #e5e5e5",
1441
+ backgroundColor: "transparent",
1442
+ borderRadius: "10px",
1443
+ padding: "12px 14px"
1444
+ },
1445
+ ".Tab:hover": {
1446
+ border: isDarkMode ? "1px solid #a3a3a3" : "1px solid #737373",
1447
+ backgroundColor: isDarkMode ? "#262626" : "#fafafa"
1448
+ },
1449
+ ".Tab--selected": {
1450
+ border: isDarkMode ? "1px solid #fafafa" : "1px solid #171717",
1451
+ backgroundColor: isDarkMode ? "#262626" : "#fafafa"
1452
+ },
1453
+ ".TabIcon": {
1454
+ marginRight: "8px"
1455
+ },
1456
+ ".Block": {
1457
+ border: isDarkMode ? "1px solid rgba(255, 255, 255, 0.1)" : "1px solid #e5e5e5",
1458
+ borderRadius: "10px",
1459
+ backgroundColor: isDarkMode ? "#262626" : "#ffffff",
1460
+ padding: "12px 14px"
1461
+ },
1462
+ ".CheckboxInput": {
1463
+ border: isDarkMode ? "1px solid rgba(255, 255, 255, 0.1)" : "1px solid #e5e5e5"
1464
+ },
1465
+ ".CheckboxInput--checked": {
1466
+ backgroundColor: isDarkMode ? "#fafafa" : "#171717",
1467
+ borderColor: isDarkMode ? "#fafafa" : "#171717"
1468
+ }
1469
+ }
1470
+ };
1471
+ };
1366
1472
  function StripeBridge({
1367
1473
  publishableKey,
1368
1474
  clientSecret,
@@ -1390,9 +1496,10 @@ function StripeBridge({
1390
1496
  throw new Error("Stripe not available");
1391
1497
  }
1392
1498
  stripeRef.current = window.Stripe(publishableKey);
1499
+ const stripeAppearance = appearance || getReevitStripeAppearance();
1393
1500
  elementsRef.current = stripeRef.current.elements({
1394
1501
  clientSecret,
1395
- appearance: appearance || { theme: "stripe" }
1502
+ appearance: stripeAppearance
1396
1503
  });
1397
1504
  paymentElementRef.current = elementsRef.current.create("payment");
1398
1505
  if (containerRef.current) {
@@ -1462,6 +1569,12 @@ function StripeBridge({
1462
1569
  setIsSubmitting(false);
1463
1570
  }
1464
1571
  }, [onSuccess, onError]);
1572
+ const formattedAmount = new Intl.NumberFormat("en-US", {
1573
+ style: "currency",
1574
+ currency: currency.toUpperCase(),
1575
+ minimumFractionDigits: 2,
1576
+ maximumFractionDigits: 2
1577
+ }).format(amount / 100);
1465
1578
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "reevit-stripe-bridge", children: [
1466
1579
  isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "reevit-stripe-loading", children: [
1467
1580
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "reevit-spinner" }),
@@ -1475,8 +1588,8 @@ function StripeBridge({
1475
1588
  style: { display: isLoading ? "none" : "block", minHeight: "200px" }
1476
1589
  }
1477
1590
  ),
1478
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "reevit-stripe-error", children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: error }) }),
1479
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "reevit-stripe-actions", children: [
1591
+ error && !isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "reevit-stripe-error", children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: error }) }),
1592
+ !isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "reevit-stripe-actions", children: [
1480
1593
  /* @__PURE__ */ jsxRuntime.jsx(
1481
1594
  "button",
1482
1595
  {
@@ -1484,11 +1597,12 @@ function StripeBridge({
1484
1597
  className: "reevit-submit-btn",
1485
1598
  onClick: handleSubmit,
1486
1599
  disabled: isLoading || isSubmitting,
1487
- children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "reevit-spinner" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1600
+ children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1601
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "reevit-spinner", style: { width: "16px", height: "16px" } }),
1602
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Processing..." })
1603
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1488
1604
  "Pay ",
1489
- currency,
1490
- " ",
1491
- (amount / 100).toFixed(2)
1605
+ formattedAmount
1492
1606
  ] })
1493
1607
  }
1494
1608
  ),
@@ -1687,9 +1801,9 @@ function ReevitCheckout({
1687
1801
  /* @__PURE__ */ jsxRuntime.jsx("button", { className: "reevit-btn reevit-btn--primary", onClick: handleBack, children: "Try Again" })
1688
1802
  ] });
1689
1803
  }
1804
+ const psp = paymentIntent?.recommendedPsp || "paystack";
1690
1805
  if (showPSPBridge) {
1691
1806
  const pspKey = paymentIntent?.pspPublicKey || publicKey;
1692
- const psp = paymentIntent?.recommendedPsp || "paystack";
1693
1807
  const bridgeMetadata = {
1694
1808
  ...metadata,
1695
1809
  // Override with correct payment intent ID for webhook routing
@@ -1866,7 +1980,8 @@ function ReevitCheckout({
1866
1980
  methods: paymentMethods,
1867
1981
  selectedMethod,
1868
1982
  onSelect: handleMethodSelect,
1869
- disabled: isLoading
1983
+ disabled: isLoading,
1984
+ provider: psp
1870
1985
  }
1871
1986
  ),
1872
1987
  selectedMethod && selectedMethod !== "mobile_money" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "reevit-method-step__actions", children: /* @__PURE__ */ jsxRuntime.jsx(